Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 24 additions & 122 deletions src/main/java/com/xpdrops/predictedhit/XpDropDamageCalculator.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@
import com.google.gson.internal.LinkedTreeMap;
import com.google.gson.reflect.TypeToken;
import com.xpdrops.predictedhit.npcswithscalingbonus.ChambersLayoutSolver;
import com.xpdrops.predictedhit.npcswithscalingbonus.DelveNpc;
import com.xpdrops.predictedhit.npcswithscalingbonus.cox.CoXNPCs;
import com.xpdrops.predictedhit.npcswithscalingbonus.toa.ToANPCs;
import com.xpdrops.predictedhit.npcswithscalingbonus.tob.ToBNPCs;
import com.xpdrops.predictedhit.npcswithscalingbonus.IModifierBoss;
import com.xpdrops.predictedhit.npcswithscalingbonus.cox.CoX;
import com.xpdrops.predictedhit.npcswithscalingbonus.delve.Delve;
import com.xpdrops.predictedhit.npcswithscalingbonus.toa.ToA;
import com.xpdrops.predictedhit.npcswithscalingbonus.tob.ToB;
import lombok.extern.slf4j.Slf4j;
import net.runelite.api.Client;
import net.runelite.api.gameval.VarbitID;
import net.runelite.api.widgets.Widget;
import net.runelite.client.util.Text;
import org.apache.commons.lang3.tuple.Pair;

import javax.inject.Inject;
Expand All @@ -22,10 +20,7 @@
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

Expand All @@ -36,25 +31,20 @@ public class XpDropDamageCalculator
private static final HashMap<Integer, Double> XP_BONUS_MAPPING = new HashMap<>();
private static final HashMap<Integer, Double> USER_DEFINED_XP_BONUS_MAPPING = new HashMap<>();
private static final Pattern RAID_LEVEL_MATCHER = Pattern.compile("(\\d+)");
private static final int RAID_LEVEL_WIDGET_ID = (481 << 16) | 42;
private static final int ROOM_LEVEL_WIDGET_ID = (481 << 16) | 45;
private static final int COX_SCALED_PARTY_SIZE_VARBIT = 9540;
private static final int RAID_PARTY_SIZE = 5424;

private int lastToARaidLevel = 0;
private int lastToARaidPartySize = 1;
private int lastToARaidRoomLevel = 0;

private final Gson GSON;
private final Client client;
private final ChambersLayoutSolver chambersLayoutSolver;
private final List<IModifierBoss> modifierBosses;

@Inject
protected XpDropDamageCalculator(Gson gson, Client client, ChambersLayoutSolver chambersLayoutSolver)
{
this.GSON = gson;
this.client = client;
this.chambersLayoutSolver = chambersLayoutSolver;
this.modifierBosses = Arrays.asList(
new CoX(client, chambersLayoutSolver),
new Delve(client),
new ToB(client),
new ToA(client)
);
}

public void populateMap()
Expand All @@ -63,69 +53,6 @@ public void populateMap()
XP_BONUS_MAPPING.putAll(getNpcsWithXpBonus());
}

private int getCoxTotalPartySize()
{
return Math.max(1, client.getVarbitValue(COX_SCALED_PARTY_SIZE_VARBIT));
}

// Currently it checks a varbit for the amount of players in the raid.
// Ideally this method returns how many non board scaling accounts started the raid.
private int getCoxPlayersInRaid()
{
return Math.max(1, client.getVarbitValue(RAID_PARTY_SIZE));
}

private int getToBPartySize()
{
int count = 0;
for (int i = 330; i < 335; i++)
{
String jagexName = client.getVarcStrValue(i);
if (jagexName != null)
{
String name = Text.removeTags(jagexName).replace('\u00A0', ' ').trim();
if (!"".equals(name))
{
count++;
}
}
}
return count;
}

private int getToAPartySize()
{
return 1 +
(client.getVarbitValue(VarbitID.TOA_CLIENT_P1) != 0 ? 1 : 0) +
(client.getVarbitValue(VarbitID.TOA_CLIENT_P2) != 0 ? 1 : 0) +
(client.getVarbitValue(VarbitID.TOA_CLIENT_P3) != 0 ? 1 : 0) +
(client.getVarbitValue(VarbitID.TOA_CLIENT_P4) != 0 ? 1 : 0) +
(client.getVarbitValue(VarbitID.TOA_CLIENT_P5) != 0 ? 1 : 0) +
(client.getVarbitValue(VarbitID.TOA_CLIENT_P6) != 0 ? 1 : 0) +
(client.getVarbitValue(VarbitID.TOA_CLIENT_P7) != 0 ? 1 : 0);
}

private int getToARaidLevel()
{
return client.getVarbitValue(VarbitID.TOA_CLIENT_RAID_LEVEL);
}

private int getToARoomLevel()
{
Widget levelWidget = client.getWidget(ROOM_LEVEL_WIDGET_ID);
if (levelWidget != null && !levelWidget.isHidden())
{
try
{
return Integer.parseInt(Text.sanitize(levelWidget.getText()));
}
catch (Exception ignored)
{
}
}
return -1;
}

private int calculateHit(int hpXpDiff, double modifier, double configModifier)
{
if (Math.abs(configModifier) < 1e-6)
Expand All @@ -149,52 +76,27 @@ public int calculateHitOnPlayer(int cmb, int hpXpDiff, double configModifier)
public int calculateHitOnNpc(int id, int hpXpDiff, double configModifier)
{
double modifier = 1.0;
if (DelveNpc.isDelveNpc(id))
{
int maxHp = client.getVarbitValue(VarbitID.HPBAR_HUD_BASEHP);
modifier = DelveNpc.modifierFromState(maxHp);
log.debug("Delve modifier {} {} max hp {}", id, modifier, maxHp);
}
else if (CoXNPCs.isCOXNPC(id))
{
int scaledPartySize = getCoxTotalPartySize();
int playersInRaid = getCoxPlayersInRaid();
// Wrong. only follows the setting of the player's board
// int raidType = client.getVarbitValue(6385) > 0 ? 1 : 0;
int raidType = chambersLayoutSolver.getRaidType() == ChambersLayoutSolver.RaidType.CM ? 1 : 0;

modifier = CoXNPCs.getModifier(id, scaledPartySize, playersInRaid, raidType);
log.debug("COX modifier {} {} party size {} players in raid {} raid type {}", id, modifier, scaledPartySize, playersInRaid, raidType);
}
else if (ToBNPCs.isTOBNPC(id))
{
int partySize = getToBPartySize();
modifier = ToBNPCs.getModifier(id, partySize);
log.debug("TOB modifier {} {} part size {}", id, modifier, partySize);
}
else if (ToANPCs.isToANPC(id))
for(IModifierBoss boss: modifierBosses)
{
int partySize = getToAPartySize();
int roomLevel = getToARoomLevel();
int raidLevel = getToARaidLevel();
// If we cannot determine any of the above; use last known settings.
if (partySize < 0) partySize = lastToARaidPartySize;
else lastToARaidPartySize = partySize;
if (roomLevel < 0) roomLevel = lastToARaidRoomLevel;
else lastToARaidRoomLevel = roomLevel;
if (raidLevel < 0) raidLevel = lastToARaidLevel;
else lastToARaidLevel = raidLevel;
modifier = ToANPCs.getModifier(id, partySize, raidLevel, roomLevel);
log.debug("TOA modifier {} {} party size {} raid level {} room level {}", id, modifier, partySize, raidLevel, roomLevel);
if (boss.containsId(id))
{
modifier = boss.getModifier(id);

log.debug("id: {}, boss: {} , modifier: {}", id, boss.getClass().getSimpleName(), modifier);
return calculateHit(hpXpDiff, modifier, configModifier);
}
}
else if (USER_DEFINED_XP_BONUS_MAPPING.containsKey(id))

if (USER_DEFINED_XP_BONUS_MAPPING.containsKey(id))
{
modifier = USER_DEFINED_XP_BONUS_MAPPING.get(id);
}
else if (XP_BONUS_MAPPING.containsKey(id))
{
modifier = XP_BONUS_MAPPING.get(id);
}

return calculateHit(hpXpDiff, modifier, configModifier);
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.xpdrops.predictedhit.npcswithscalingbonus;

public interface IModifierBoss
{
boolean containsId(int npcId);
double getModifier(int npcId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public class NPCStats

private static final int MAX_HP_FOR_MULTIPLIER = 2000;

protected static double modifierFromStats(NPCStats npcStats)
public static double modifierFromStats(NPCStats npcStats)
{
int hp = Math.min(npcStats.hp, MAX_HP_FOR_MULTIPLIER);
double averageLevel = Math.floor((hp + npcStats.getAtt() + npcStats.getStr() + npcStats.getDef()) / 4.0);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.xpdrops.predictedhit.npcswithscalingbonus.cox;

import com.xpdrops.predictedhit.npcswithscalingbonus.IModifierBoss;
import com.xpdrops.predictedhit.npcswithscalingbonus.ChambersLayoutSolver;
import lombok.AccessLevel;
import lombok.Getter;
import net.runelite.api.Client;

import javax.inject.Inject;
import java.util.HashMap;
import java.util.Map;

public class CoX implements IModifierBoss
{
private final Client client;
private final ChambersLayoutSolver chambersLayoutSolver;

private static final Map<Integer, CoXNPC> COX_NPC_MAPPING;

private static final int COX_SCALED_PARTY_SIZE_VARBIT = 9540;
private static final int RAID_PARTY_SIZE = 5424;

@Inject
public CoX(Client client, ChambersLayoutSolver chambersLayoutSolver)
{
this.client = client;
this.chambersLayoutSolver = chambersLayoutSolver;
}

static
{
COX_NPC_MAPPING = new HashMap<>();
for (CoXNPCs value : CoXNPCs.values())
{
for (Integer id : value.getIds())
{
COX_NPC_MAPPING.put(id, value.getNpcWithScalingBonus());
}
}
}

private int getCoxTotalPartySize()
{
return Math.max(1, client.getVarbitValue(COX_SCALED_PARTY_SIZE_VARBIT));
}

// Currently it checks a varbit for the amount of players in the raid.
// Ideally this method returns how many non board scaling accounts started the raid.
private int getCoxPlayersInRaid()
{
return Math.max(1, client.getVarbitValue(RAID_PARTY_SIZE));
}

@Override
public boolean containsId(int npcId)
{
return COX_NPC_MAPPING.containsKey(npcId);
}

@Override
public double getModifier(int npcId)
{
if (!containsId(npcId))
{
return 1.0;
}

int scaledPartySize = getCoxTotalPartySize();
int playersInRaid = getCoxPlayersInRaid();
// Wrong. only follows the setting of the player's board
// int raidType = client.getVarbitValue(6385) > 0 ? 1 : 0;
int raidType = chambersLayoutSolver.getRaidType() == ChambersLayoutSolver.RaidType.CM ? 1 : 0;

return COX_NPC_MAPPING.get(npcId).calculateModifier(raidType, scaledPartySize, playersInRaid);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.xpdrops.predictedhit.npcswithscalingbonus.cox;

import lombok.AccessLevel;
import lombok.Getter;
import net.runelite.api.gameval.NpcID;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

public enum CoXNPCs
{
Expand All @@ -29,9 +31,11 @@ public enum CoXNPCs
GREAT_OLM(CoXNPCStats.GREAT_OLM.getCoxnpc(), NpcID.OLM_HEAD_SPAWNING, NpcID.OLM_HEAD),
GREAT_OLM_MAGE_HAND(CoXNPCStats.GREAT_OLM_MAGE_HAND.getCoxnpc(), NpcID.OLM_HAND_LEFT_SPAWNING, NpcID.OLM_HAND_LEFT_SPAWNING),
GREAT_OLM_MELEE_HAND(CoXNPCStats.GREAT_OLM_MELEE_HAND.getCoxnpc(), NpcID.OLM_HAND_RIGHT_SPAWNING, NpcID.OLM_HAND_RIGHT),
SCAVENGER(CoXNPCStats.SCAVENGER.getCoxnpc(), NpcID.RAIDS_SCAVENGER_BEAST_A, NpcID.RAIDS_SCAVENGER_BEAST_B),
;
SCAVENGER(CoXNPCStats.SCAVENGER.getCoxnpc(), NpcID.RAIDS_SCAVENGER_BEAST_A, NpcID.RAIDS_SCAVENGER_BEAST_B);

@Getter(AccessLevel.PACKAGE)
private final HashSet<Integer> ids;
@Getter(AccessLevel.PACKAGE)
private final CoXNPC npcWithScalingBonus;

CoXNPCs(CoXNPC coxnpc, int... ids)
Expand All @@ -41,36 +45,8 @@ public enum CoXNPCs
Arrays.stream(ids).forEach(this.ids::add);
}

private static final HashMap<Integer, CoXNPC> COXNPC_MAPPING;

static
{
COXNPC_MAPPING = new HashMap<>();
for (CoXNPCs value : CoXNPCs.values())
{
for (Integer id : value.ids)
{
COXNPC_MAPPING.put(id, value.npcWithScalingBonus);
}
}
}

public static boolean isCOXNPC(int id)
{
return COXNPC_MAPPING.containsKey(id);
}

public static double getModifier(int id, int scaledPartySize, int playersInRaid, int raidType)
{
if (isCOXNPC(id))
{
return COXNPC_MAPPING.get(id).calculateModifier(raidType, scaledPartySize, playersInRaid);
}
return 1.0;
}

@Getter
enum CoXNPCStats
enum CoXNPCStats
{
TEKTON(new Tekton(300, 390, 390, 205, 1, 205, 64, 20, 155, 165, 105, 0, 0)),
TEKTON_ENRAGED(new Tekton(300, 390, 390, 205, 1, 205, 64, 30, 280, 290, 180, 0, 0)),
Expand Down
Loading