slayer plugin: better support multikills
This observes deaths of tagged npcs each tick and will use those if available instead of assuming one kill per xpdrop
This commit is contained in:
@@ -30,11 +30,14 @@ import com.google.inject.Provides;
|
||||
import java.awt.Color;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import static java.lang.Integer.max;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -44,18 +47,22 @@ import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Actor;
|
||||
import net.runelite.api.ChatMessageType;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.GameState;
|
||||
import net.runelite.api.Hitsplat;
|
||||
import net.runelite.api.ItemID;
|
||||
import net.runelite.api.MessageNode;
|
||||
import net.runelite.api.NPC;
|
||||
import net.runelite.api.NPCComposition;
|
||||
import static net.runelite.api.Skill.SLAYER;
|
||||
import net.runelite.api.coords.WorldPoint;
|
||||
import net.runelite.api.events.ActorDeath;
|
||||
import net.runelite.api.events.ChatMessage;
|
||||
import net.runelite.api.events.GameStateChanged;
|
||||
import net.runelite.api.events.GameTick;
|
||||
import net.runelite.api.events.HitsplatApplied;
|
||||
import net.runelite.api.events.NpcDespawned;
|
||||
import net.runelite.api.events.NpcSpawned;
|
||||
import net.runelite.api.events.StatChanged;
|
||||
@@ -174,6 +181,10 @@ public class SlayerPlugin extends Plugin
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
private List<NPC> highlightedTargets = new ArrayList<>();
|
||||
|
||||
private final Set<NPC> taggedNpcs = new HashSet<>();
|
||||
private int taggedNpcsDiedPrevTick;
|
||||
private int taggedNpcsDiedThisTick;
|
||||
|
||||
@Getter(AccessLevel.PACKAGE)
|
||||
@Setter(AccessLevel.PACKAGE)
|
||||
private int amount;
|
||||
@@ -237,6 +248,7 @@ public class SlayerPlugin extends Plugin
|
||||
overlayManager.remove(targetMinimapOverlay);
|
||||
removeCounter();
|
||||
highlightedTargets.clear();
|
||||
taggedNpcs.clear();
|
||||
cachedXp = -1;
|
||||
|
||||
chatCommandManager.unregisterCommand(TASK_COMMAND_STRING);
|
||||
@@ -260,6 +272,7 @@ public class SlayerPlugin extends Plugin
|
||||
amount = 0;
|
||||
loginFlag = true;
|
||||
highlightedTargets.clear();
|
||||
taggedNpcs.clear();
|
||||
break;
|
||||
case LOGGED_IN:
|
||||
if (config.amount() != -1
|
||||
@@ -299,6 +312,7 @@ public class SlayerPlugin extends Plugin
|
||||
public void onNpcDespawned(NpcDespawned npcDespawned)
|
||||
{
|
||||
NPC npc = npcDespawned.getNpc();
|
||||
taggedNpcs.remove(npc);
|
||||
highlightedTargets.remove(npc);
|
||||
}
|
||||
|
||||
@@ -391,6 +405,9 @@ public class SlayerPlugin extends Plugin
|
||||
removeCounter();
|
||||
}
|
||||
}
|
||||
|
||||
taggedNpcsDiedPrevTick = taggedNpcsDiedThisTick;
|
||||
taggedNpcsDiedThisTick = 0;
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -541,20 +558,49 @@ public class SlayerPlugin extends Plugin
|
||||
return;
|
||||
}
|
||||
|
||||
final Task task = Task.getTask(taskName);
|
||||
|
||||
// null tasks are technically valid, it only means they arent explicitly defined in the Task enum
|
||||
// allow them through so that if there is a task capture failure the counter will still work
|
||||
final int taskKillExp = task != null ? task.getExpectedKillExp() : 0;
|
||||
|
||||
// Only count exp gain as a kill if the task either has no expected exp for a kill, or if the exp gain is equal
|
||||
// to the expected exp gain for the task.
|
||||
if (taskKillExp == 0 || taskKillExp == slayerExp - cachedXp)
|
||||
{
|
||||
killedOne();
|
||||
}
|
||||
|
||||
final int delta = slayerExp - cachedXp;
|
||||
cachedXp = slayerExp;
|
||||
|
||||
log.debug("Slayer xp change delta: {}, killed npcs: {}", delta, taggedNpcsDiedPrevTick);
|
||||
|
||||
final Task task = Task.getTask(taskName);
|
||||
if (task != null && task.getExpectedKillExp() > 0)
|
||||
{
|
||||
// Only decrement a kill if the xp drop matches the expected drop. This is just for Tzhaar tasks.
|
||||
if (task.getExpectedKillExp() == delta)
|
||||
{
|
||||
killed(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is at least one kill, but if we observe multiple tagged NPCs dieing on the previous tick, count them
|
||||
// instead.
|
||||
killed(max(taggedNpcsDiedPrevTick, 1));
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onHitsplatApplied(HitsplatApplied hitsplatApplied)
|
||||
{
|
||||
Actor actor = hitsplatApplied.getActor();
|
||||
Hitsplat hitsplat = hitsplatApplied.getHitsplat();
|
||||
if (hitsplat.getHitsplatType() == Hitsplat.HitsplatType.DAMAGE_ME && highlightedTargets.contains(actor))
|
||||
{
|
||||
// If the actor is in highlightedTargets it must be an NPC and also a task assignment
|
||||
taggedNpcs.add((NPC) actor);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onActorDeath(ActorDeath actorDeath)
|
||||
{
|
||||
Actor actor = actorDeath.getActor();
|
||||
if (taggedNpcs.contains(actor))
|
||||
{
|
||||
log.debug("Tagged NPC {} has died", actor.getName());
|
||||
++taggedNpcsDiedThisTick;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -576,16 +622,17 @@ public class SlayerPlugin extends Plugin
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void killedOne()
|
||||
void killed(int amt)
|
||||
{
|
||||
if (amount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
amount--;
|
||||
amount -= amt;
|
||||
if (doubleTroubleExtraKill())
|
||||
{
|
||||
assert amt == 1;
|
||||
amount--;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user