Skip to content

Commit

Permalink
Make assists part of stats
Browse files Browse the repository at this point in the history
Signed-off-by: Pablo Herrera <[email protected]>
  • Loading branch information
Pablete1234 committed Dec 31, 2024
1 parent 4c7eb75 commit ae8b172
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ public final PlayerRelation getRelation() {
return PlayerRelation.get(getVictim().getParticipantState(), getKiller());
}

/** Get the relationship between the victim and assister */
public final PlayerRelation getAssistRelation() {
return PlayerRelation.get(getVictim().getParticipantState(), getAssister());
}

/**
* Get whether the death was caused by a teammate.
*
Expand All @@ -140,6 +145,15 @@ public final boolean isEnemyKill() {
return PlayerRelation.ENEMY == getRelation();
}

/**
* Get whether the assist was caused by an enemy.
*
* @return Whether the assist was from an enemy.
*/
public final boolean isEnemyAssist() {
return PlayerRelation.ENEMY == getAssistRelation();
}

/**
* Get whether the {@link MatchPlayer} killed themselves.
*
Expand All @@ -149,24 +163,33 @@ public final boolean isSuicide() {
return PlayerRelation.SELF == getRelation();
}

/**
* Get whether the victim and killer are the same {@link MatchPlayer}.
*
* @return
*/
/** Get whether the victim and killer are the same {@link MatchPlayer}. */
public final boolean isSelfKill() {
return getKiller() != null && getKiller().isPlayer(getVictim());
}

public final boolean isSelfAssist() {
return getAssister() != null && getAssister().isPlayer(getVictim());
}

/**
* Get whether the death was from an enemy and it was no caused by suicide.
* Get whether the death was from an enemy and it was not caused by suicide.
*
* @return Whether the death was actually "challenging."
*/
public final boolean isChallengeKill() {
return isEnemyKill() && !isSelfKill();
}

/**
* Get whether the assist was from an enemy and it was not caused by suicide.
*
* @return Whether the assist was actually "challenging."
*/
public final boolean isChallengeAssist() {
return isEnemyAssist() && !isSelfAssist();
}

private static final HandlerList handlers = new HandlerList();

@Override
Expand Down
69 changes: 55 additions & 14 deletions core/src/main/java/tc/oc/pgm/stats/PlayerStats.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import tc.oc.pgm.api.match.MatchScope;
import tc.oc.pgm.api.player.MatchPlayer;
import tc.oc.pgm.api.setting.SettingKey;
import tc.oc.pgm.api.setting.SettingValue;
import tc.oc.pgm.util.Audience;

/** A wrapper for stat info belonging to a {@link tc.oc.pgm.api.player.MatchPlayer} */
public class PlayerStats {
Expand All @@ -22,6 +28,7 @@ public class PlayerStats {
// K/D
private int kills;
private int deaths;
private int assists;
private int killstreak; // Current killstreak
private int killstreakMax; // The highest killstreak reached this match

Expand Down Expand Up @@ -53,7 +60,7 @@ public class PlayerStats {

// The task responsible for displaying the stats over the hotbar
// See StatsMatchModule#sendLongHotbarMessage
private Future<?> hotbarTaskCache;
private Future<?> hotbarTask;

public PlayerStats() {
this(null, null);
Expand All @@ -68,17 +75,25 @@ public PlayerStats(PlayerStats parent, Component component) {

// Methods to update the stats, should only be accessed by StatsMatchModule

protected void onMurder() {
protected void onMurder(MatchPlayer player) {
kills++;
killstreak++;
if (killstreak > killstreakMax) killstreakMax = killstreak;
if (parent != null) parent.onMurder();
if (parent != null) parent.onMurder(null);
sendPlayerStats(player);
}

protected void onDeath() {
protected void onDeath(MatchPlayer player) {
deaths++;
killstreak = 0;
if (parent != null) parent.onDeath();
if (parent != null) parent.onDeath(null);
sendPlayerStats(player);
}

protected void onAssist(MatchPlayer player) {
assists++;
if (parent != null) parent.onAssist(null);
sendPlayerStats(player);
}

protected void onDamage(double damage, boolean bow) {
Expand Down Expand Up @@ -148,9 +163,7 @@ protected void onWoolTouch() {
}

protected void setLongestBowKill(double distance) {
if (distance > longestBowKill) {
longestBowKill = (int) Math.round(distance);
}
if (distance > longestBowKill) longestBowKill = (int) Math.round(distance);
if (parent != null) parent.setLongestBowKill(distance);
}

Expand All @@ -173,7 +186,8 @@ public Component getBasicStatsMessage() {
number(kills, NamedTextColor.GREEN),
number(killstreak, NamedTextColor.GREEN),
number(deaths, NamedTextColor.RED),
number(getKD(), NamedTextColor.GREEN));
number(getKD(), NamedTextColor.GREEN),
number(assists, NamedTextColor.GREEN));
}

// Getters, both raw stats and some handy calculations
Expand All @@ -196,6 +210,10 @@ public int getDeaths() {
return deaths;
}

public int getAssists() {
return assists;
}

public int getKillstreak() {
return killstreak;
}
Expand Down Expand Up @@ -264,12 +282,18 @@ public Duration getLongestFlagHold() {
return longestFlagHold;
}

public Future<?> getHotbarTask() {
return hotbarTaskCache;
private void setHotbarTask(Future<?> task) {
if (hotbarTask != null && !hotbarTask.isDone()) hotbarTask.cancel(true);
hotbarTask = task;
}

public void putHotbarTaskCache(Future<?> task) {
hotbarTaskCache = task;
public void sendPlayerStats(MatchPlayer player) {
if (player == null) return;
if (player.getSettings().getValue(SettingKey.STATS) == SettingValue.STATS_OFF) return;
setHotbarTask(player
.getMatch()
.getExecutor(MatchScope.LOADED)
.scheduleWithFixedDelay(new HotbarStatsRunner(player), 0, 1, TimeUnit.SECONDS));
}

public Component getPlayerComponent() {
Expand Down Expand Up @@ -297,6 +321,23 @@ public Duration getTimePlayed() {
}

public Duration getActiveSessionDuration() {
return (inTime == null) ? Duration.ZERO : Duration.between(inTime, Instant.now());
return inTime == null ? Duration.ZERO : Duration.between(inTime, Instant.now());
}

protected class HotbarStatsRunner implements Runnable {
private final Audience audience;
private final Component message;
private int remaining = 4;

private HotbarStatsRunner(Audience audience) {
this.audience = audience;
this.message = getBasicStatsMessage();
}

@Override
public void run() {
audience.sendActionBar(message);
if (remaining-- < 0) setHotbarTask(null);
}
}
}
69 changes: 21 additions & 48 deletions core/src/main/java/tc/oc/pgm/stats/StatsMatchModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import net.kyori.adventure.text.Component;
Expand Down Expand Up @@ -50,7 +49,6 @@
import tc.oc.pgm.api.player.MatchPlayer;
import tc.oc.pgm.api.player.MatchPlayerState;
import tc.oc.pgm.api.player.ParticipantState;
import tc.oc.pgm.api.player.PlayerRelation;
import tc.oc.pgm.api.player.event.MatchPlayerDeathEvent;
import tc.oc.pgm.api.setting.SettingKey;
import tc.oc.pgm.api.setting.SettingValue;
Expand Down Expand Up @@ -238,33 +236,21 @@ public void onFlagDrop(FlagStateChangeEvent event) {
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerDeath(MatchPlayerDeathEvent event) {
MatchPlayer victim = event.getVictim();
MatchPlayer murderer = null;

if (event.getKiller() != null)
murderer = event.getKiller().getParty().getPlayer(event.getKiller().getId());

PlayerStats victimStats = getPlayerStat(victim);

victimStats.onDeath();

sendPlayerStats(victim, victimStats);

if (murderer != null
&& PlayerRelation.get(victim.getParticipantState(), murderer) != PlayerRelation.ALLY
&& PlayerRelation.get(victim.getParticipantState(), murderer) != PlayerRelation.SELF) {

PlayerStats murdererStats = getPlayerStat(murderer);

if (event.getDamageInfo() instanceof ProjectileInfo) {
murdererStats.setLongestBowKill(victim
.getState()
.getLocation()
.distance(((ProjectileInfo) event.getDamageInfo()).getOrigin()));
}

murdererStats.onMurder();
getPlayerStat(victim).onDeath(victim);

if (event.isChallengeKill()) {
MatchPlayerState killer = event.getKiller();
assert killer != null;
PlayerStats murdererStats = getPlayerStat(killer);
if (event.getDamageInfo() instanceof ProjectileInfo projectile)
murdererStats.setLongestBowKill(victim.getLocation().distance(projectile.getOrigin()));
murdererStats.onMurder(killer.getPlayer().orElse(null));
}

sendPlayerStats(murderer, murdererStats);
if (event.isChallengeAssist()) {
MatchPlayerState assister = event.getAssister();
assert assister != null;
getPlayerStat(assister).onAssist(assister.getPlayer().orElse(null));
}
}

Expand All @@ -273,24 +259,6 @@ public void onParticipationStop(PlayerParticipationStopEvent event) {
getPlayerStat(event.getPlayer()).onTeamSwitch();
}

private void sendPlayerStats(MatchPlayer player, PlayerStats stats) {
if (player.getSettings().getValue(SettingKey.STATS) == SettingValue.STATS_OFF) return;
if (stats.getHotbarTask() != null && !stats.getHotbarTask().isDone()) {
stats.getHotbarTask().cancel(true);
}
stats.putHotbarTaskCache(sendLongHotbarMessage(player, stats.getBasicStatsMessage()));
}

private Future<?> sendLongHotbarMessage(MatchPlayer player, Component message) {
Future<?> task = match
.getExecutor(MatchScope.LOADED)
.scheduleWithFixedDelay(() -> player.sendActionBar(message), 0, 1, TimeUnit.SECONDS);

match.getExecutor(MatchScope.LOADED).schedule(() -> task.cancel(true), 4, TimeUnit.SECONDS);

return task;
}

@EventHandler(priority = EventPriority.MONITOR)
public void onMatchEnd(MatchFinishEvent event) {
if (allPlayerStats.isEmpty() || showAfter.isNegative()) return;
Expand Down Expand Up @@ -319,6 +287,7 @@ public void onStatsDisplay(MatchStatsEvent event) {
Pair<UUID, Integer> bestKills = null;
Pair<UUID, Integer> bestStreaks = null;
Pair<UUID, Integer> bestDeaths = null;
Pair<UUID, Integer> bestAssists = null;
Pair<UUID, Integer> bestBowShots = null;
Pair<UUID, Double> bestDamage = null;

Expand All @@ -328,6 +297,7 @@ public void onStatsDisplay(MatchStatsEvent event) {
bestKills = getBest(bestKills, uuid, s.getKills());
bestStreaks = getBest(bestStreaks, uuid, s.getMaxKillstreak());
bestDeaths = getBest(bestDeaths, uuid, s.getDeaths());
bestAssists = getBest(bestAssists, uuid, s.getAssists());
bestBowShots = getBest(bestBowShots, uuid, s.getLongestBowKill());
bestDamage = getBest(bestDamage, uuid, s.getDamageDone());
}
Expand All @@ -337,6 +307,7 @@ public void onStatsDisplay(MatchStatsEvent event) {
best.add(getMessage("match.stats.kills", bestKills, NamedTextColor.GREEN));
best.add(getMessage("match.stats.killstreak", bestStreaks, NamedTextColor.GREEN));
best.add(getMessage("match.stats.deaths", bestDeaths, NamedTextColor.RED));
best.add(getMessage("match.stats.assists", bestAssists, NamedTextColor.GREEN));

if (bestBowShots.getRight() > 0)
best.add(getMessage("match.stats.bowshot", bestBowShots, NamedTextColor.YELLOW));
Expand All @@ -363,15 +334,17 @@ public void onStatsDisplay(MatchStatsEvent event) {

if (event.isShowOwn() && stats != null) {
Component ksHover = translatable(
"match.stats.killstreak.concise", number(stats.getKillstreak(), NamedTextColor.GREEN));
"match.stats.killstreak.concise",
number(stats.getMaxKillstreak(), NamedTextColor.GREEN));

viewer.sendMessage(translatable(
"match.stats.own",
number(stats.getKills(), NamedTextColor.GREEN),
number(stats.getMaxKillstreak(), NamedTextColor.GREEN).hoverEvent(showText(ksHover)),
number(stats.getDeaths(), NamedTextColor.RED),
number(stats.getKD(), NamedTextColor.GREEN),
damageComponent(stats.getDamageDone(), NamedTextColor.GREEN)));
damageComponent(stats.getDamageDone(), NamedTextColor.GREEN),
number(stats.getAssists(), NamedTextColor.GREEN)));
}

giveVerboseStatsItem(viewer, false);
Expand Down
6 changes: 6 additions & 0 deletions core/src/main/java/tc/oc/pgm/stats/TeamStats.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ public class TeamStats {

private int teamKills = 0;
private int teamDeaths = 0;
private int teamAssists = 0;
private double damageDone = 0;
private double damageTaken = 0;
private double bowDamage = 0;
Expand All @@ -22,6 +23,7 @@ public TeamStats(Collection<PlayerStats> playerStats) {
for (PlayerStats stats : playerStats) {
teamKills += stats.getKills();
teamDeaths += stats.getDeaths();
teamAssists += stats.getAssists();
damageDone += stats.getDamageDone();
damageTaken += stats.getDamageTaken();
bowDamage += stats.getBowDamage();
Expand All @@ -42,6 +44,10 @@ public int getTeamDeaths() {
return teamDeaths;
}

public int getTeamAssists() {
return teamAssists;
}

public double getDamageDone() {
return damageDone;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ public List<String> getLore(Player player) {
GRAY,
number(stats.getKills(), NamedTextColor.GREEN),
number(stats.getDeaths(), NamedTextColor.RED),
number(stats.getKD(), NamedTextColor.GREEN));
number(stats.getKD(), NamedTextColor.GREEN),
number(stats.getAssists(), NamedTextColor.GREEN));
Component killstreakLore = translatable(
"match.stats.killstreak.concise",
GRAY,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ public List<String> getLore(Player player) {
NamedTextColor.GRAY,
number(stats.getTeamKills(), NamedTextColor.GREEN),
number(stats.getTeamDeaths(), NamedTextColor.RED),
number(stats.getTeamKD(), NamedTextColor.GREEN));
number(stats.getTeamKD(), NamedTextColor.GREEN),
number(stats.getTeamAssists(), NamedTextColor.GREEN));

Component damageDealtLore = translatable(
"match.stats.damage.dealt",
Expand Down
Loading

0 comments on commit ae8b172

Please sign in to comment.