@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
||||||
|
* Copyright (c) 2019, TheStonedTurtle <https://github.com/TheStonedTurtle>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package com.openosrs.client.game;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.gson.stream.JsonReader;
|
||||||
|
import io.reactivex.rxjava3.core.Completable;
|
||||||
|
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.runelite.api.NpcID;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Singleton
|
||||||
|
public class NPCManager
|
||||||
|
{
|
||||||
|
private static final Set<Integer> blacklistXpMultiplier = Set.of(
|
||||||
|
// Vorkath
|
||||||
|
NpcID.VORKATH, NpcID.VORKATH_8058, NpcID.VORKATH_8059, NpcID.VORKATH_8060, NpcID.VORKATH_8061,
|
||||||
|
|
||||||
|
// Grotesque Guardians
|
||||||
|
NpcID.DAWN, NpcID.DAWN_7852, NpcID.DAWN_7853, NpcID.DAWN_7884, NpcID.DAWN_7885,
|
||||||
|
NpcID.DUSK, NpcID.DUSK_7851, NpcID.DUSK_7854, NpcID.DUSK_7855, NpcID.DUSK_7882, NpcID.DUSK_7883, NpcID.DUSK_7886, NpcID.DUSK_7887, NpcID.DUSK_7888, NpcID.DUSK_7889,
|
||||||
|
|
||||||
|
// Kraken
|
||||||
|
NpcID.KRAKEN, NpcID.KRAKEN_6640, NpcID.KRAKEN_6656,
|
||||||
|
|
||||||
|
// Zulrah
|
||||||
|
NpcID.ZULRAH, NpcID.ZULRAH_2043, NpcID.ZULRAH_2044
|
||||||
|
);
|
||||||
|
private ImmutableMap<Integer, NPCStats> statsMap;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private NPCManager()
|
||||||
|
{
|
||||||
|
Completable.fromAction(this::loadStats)
|
||||||
|
.subscribeOn(Schedulers.computation())
|
||||||
|
.subscribe(
|
||||||
|
() -> log.debug("Loaded {} NPC stats", statsMap.size()),
|
||||||
|
ex -> log.warn("Error loading NPC stats", ex)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadStats() throws IOException
|
||||||
|
{
|
||||||
|
try (JsonReader reader = new JsonReader(new InputStreamReader(NPCManager.class.getResourceAsStream("/npc_stats.json"), StandardCharsets.UTF_8)))
|
||||||
|
{
|
||||||
|
ImmutableMap.Builder<Integer, NPCStats> builder = ImmutableMap.builderWithExpectedSize(2821);
|
||||||
|
reader.beginObject();
|
||||||
|
|
||||||
|
while (reader.hasNext())
|
||||||
|
{
|
||||||
|
builder.put(
|
||||||
|
Integer.parseInt(reader.nextName()),
|
||||||
|
NPCStats.NPC_STATS_TYPE_ADAPTER.read(reader)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.endObject();
|
||||||
|
statsMap = builder.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link NPCStats} for target NPC id
|
||||||
|
*
|
||||||
|
* @param npcId NPC id
|
||||||
|
* @return the {@link NPCStats} or null if unknown
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public NPCStats getStats(final int npcId)
|
||||||
|
{
|
||||||
|
return statsMap.get(npcId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns health for target NPC ID
|
||||||
|
*
|
||||||
|
* @param npcId NPC id
|
||||||
|
* @return health or null if unknown
|
||||||
|
*/
|
||||||
|
public int getHealth(final int npcId)
|
||||||
|
{
|
||||||
|
final NPCStats s = statsMap.get(npcId);
|
||||||
|
if (s == null || s.getHitpoints() == -1)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.getHitpoints();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the attack speed for target NPC ID.
|
||||||
|
*
|
||||||
|
* @param npcId NPC id
|
||||||
|
* @return attack speed in game ticks for NPC ID.
|
||||||
|
*/
|
||||||
|
public int getAttackSpeed(final int npcId)
|
||||||
|
{
|
||||||
|
final NPCStats s = statsMap.get(npcId);
|
||||||
|
if (s == null || s.getAttackSpeed() == -1)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.getAttackSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the exp modifier for target NPC ID based on its stats.
|
||||||
|
*
|
||||||
|
* @param npcId NPC id
|
||||||
|
* @return npcs exp modifier. Assumes default xp rate if npc stats are unknown (returns 1)
|
||||||
|
*/
|
||||||
|
public double getXpModifier(final int npcId)
|
||||||
|
{
|
||||||
|
if (blacklistXpMultiplier.contains(npcId))
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
final NPCStats s = statsMap.get(npcId);
|
||||||
|
if (s == null)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.calculateXpModifier();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,203 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, TheStonedTurtle <https://github.com/TheStonedTurtle>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package com.openosrs.client.game;
|
||||||
|
|
||||||
|
import com.google.gson.TypeAdapter;
|
||||||
|
import com.google.gson.stream.JsonReader;
|
||||||
|
import com.google.gson.stream.JsonWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
|
@Value
|
||||||
|
@Builder(builderClassName = "Builder")
|
||||||
|
public class NPCStats
|
||||||
|
{
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
private final int hitpoints;
|
||||||
|
private final int combatLevel;
|
||||||
|
private final int slayerLevel;
|
||||||
|
private final int attackSpeed;
|
||||||
|
|
||||||
|
private final int attackLevel;
|
||||||
|
private final int strengthLevel;
|
||||||
|
private final int defenceLevel;
|
||||||
|
private final int rangeLevel;
|
||||||
|
private final int magicLevel;
|
||||||
|
|
||||||
|
private final int stab;
|
||||||
|
private final int slash;
|
||||||
|
private final int crush;
|
||||||
|
private final int range;
|
||||||
|
private final int magic;
|
||||||
|
|
||||||
|
private final int stabDef;
|
||||||
|
private final int slashDef;
|
||||||
|
private final int crushDef;
|
||||||
|
private final int rangeDef;
|
||||||
|
private final int magicDef;
|
||||||
|
|
||||||
|
private final int bonusAttack;
|
||||||
|
private final int bonusStrength;
|
||||||
|
private final int bonusRangeStrength;
|
||||||
|
private final int bonusMagicDamage;
|
||||||
|
|
||||||
|
private final boolean poisonImmune;
|
||||||
|
private final boolean venomImmune;
|
||||||
|
|
||||||
|
private final boolean dragon;
|
||||||
|
private final boolean demon;
|
||||||
|
private final boolean undead;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Based off the formula found here: http://services.runescape.com/m=forum/c=PLuJ4cy6gtA/forums.ws?317,318,712,65587452,209,337584542#209
|
||||||
|
*
|
||||||
|
* @return bonus XP modifier
|
||||||
|
*/
|
||||||
|
public double calculateXpModifier()
|
||||||
|
{
|
||||||
|
final double averageLevel = Math.floor((attackLevel + strengthLevel + defenceLevel + hitpoints) / 4);
|
||||||
|
final double averageDefBonus = Math.floor((stabDef + slashDef + crushDef) / 3);
|
||||||
|
|
||||||
|
return (1 + Math.floor(averageLevel * (averageDefBonus + bonusStrength + bonusAttack) / 5120) / 40);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Because this class is here we can't add the TypeAdapter to gson (easily)
|
||||||
|
// doesn't mean we can't use one to do it a bit quicker
|
||||||
|
public static final TypeAdapter<NPCStats> NPC_STATS_TYPE_ADAPTER = new TypeAdapter<NPCStats>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void write(JsonWriter out, NPCStats value)
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException("Not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NPCStats read(JsonReader in) throws IOException
|
||||||
|
{
|
||||||
|
in.beginObject();
|
||||||
|
NPCStats.Builder builder = NPCStats.builder();
|
||||||
|
|
||||||
|
// Name is the only one that's guaranteed
|
||||||
|
in.skipValue();
|
||||||
|
builder.name(in.nextString());
|
||||||
|
|
||||||
|
while (in.hasNext())
|
||||||
|
{
|
||||||
|
switch (in.nextName())
|
||||||
|
{
|
||||||
|
case "hitpoints":
|
||||||
|
builder.hitpoints(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "combatLevel":
|
||||||
|
builder.combatLevel(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "slayerLevel":
|
||||||
|
builder.slayerLevel(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "attackSpeed":
|
||||||
|
builder.attackSpeed(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "attackLevel":
|
||||||
|
builder.attackLevel(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "strengthLevel":
|
||||||
|
builder.strengthLevel(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "defenceLevel":
|
||||||
|
builder.defenceLevel(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "rangeLevel":
|
||||||
|
builder.rangeLevel(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "magicLevel":
|
||||||
|
builder.magicLevel(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "stab":
|
||||||
|
builder.stab(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "slash":
|
||||||
|
builder.slash(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "crush":
|
||||||
|
builder.crush(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "range":
|
||||||
|
builder.range(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "magic":
|
||||||
|
builder.magic(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "stabDef":
|
||||||
|
builder.stabDef(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "slashDef":
|
||||||
|
builder.slashDef(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "crushDef":
|
||||||
|
builder.crushDef(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "rangeDef":
|
||||||
|
builder.rangeDef(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "magicDef":
|
||||||
|
builder.magicDef(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "bonusAttack":
|
||||||
|
builder.bonusAttack(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "bonusStrength":
|
||||||
|
builder.bonusStrength(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "bonusRangeStrength":
|
||||||
|
builder.bonusRangeStrength(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "bonusMagicDamage":
|
||||||
|
builder.bonusMagicDamage(in.nextInt());
|
||||||
|
break;
|
||||||
|
case "poisonImmune":
|
||||||
|
builder.poisonImmune(in.nextBoolean());
|
||||||
|
break;
|
||||||
|
case "venomImmune":
|
||||||
|
builder.venomImmune(in.nextBoolean());
|
||||||
|
break;
|
||||||
|
case "dragon":
|
||||||
|
builder.dragon(in.nextBoolean());
|
||||||
|
break;
|
||||||
|
case "demon":
|
||||||
|
builder.demon(in.nextBoolean());
|
||||||
|
break;
|
||||||
|
case "undead":
|
||||||
|
builder.undead(in.nextBoolean());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
in.endObject();
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, PKLite
|
||||||
|
* Copyright (c) 2020, ThatGamerBlue <thatgamerblue@gmail.com>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer in the documentation
|
||||||
|
* and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
package com.openosrs.client.util;
|
||||||
|
|
||||||
|
import java.awt.Polygon;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import net.runelite.api.Client;
|
||||||
|
import net.runelite.api.InventoryID;
|
||||||
|
import net.runelite.api.Item;
|
||||||
|
import net.runelite.api.ItemComposition;
|
||||||
|
import net.runelite.api.Player;
|
||||||
|
import net.runelite.api.Varbits;
|
||||||
|
import net.runelite.api.WorldType;
|
||||||
|
import net.runelite.api.coords.WorldPoint;
|
||||||
|
import net.runelite.api.geometry.Cuboid;
|
||||||
|
import net.runelite.client.game.ItemManager;
|
||||||
|
import net.runelite.client.util.QuantityFormatter;
|
||||||
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
|
|
||||||
|
public class PvPUtil
|
||||||
|
{
|
||||||
|
private static final Polygon NOT_WILDERNESS_BLACK_KNIGHTS = new Polygon( // this is black knights castle
|
||||||
|
new int[]{2994, 2995, 2996, 2996, 2994, 2994, 2997, 2998, 2998, 2999, 3000, 3001, 3002, 3003, 3004, 3005, 3005,
|
||||||
|
3005, 3019, 3020, 3022, 3023, 3024, 3025, 3026, 3026, 3027, 3027, 3028, 3028, 3029, 3029, 3030, 3030, 3031,
|
||||||
|
3031, 3032, 3033, 3034, 3035, 3036, 3037, 3037},
|
||||||
|
new int[]{3525, 3526, 3527, 3529, 3529, 3534, 3534, 3535, 3536, 3537, 3538, 3539, 3540, 3541, 3542, 3543, 3544,
|
||||||
|
3545, 3545, 3546, 3546, 3545, 3544, 3543, 3543, 3542, 3541, 3540, 3539, 3537, 3536, 3535, 3534, 3533, 3532,
|
||||||
|
3531, 3530, 3529, 3528, 3527, 3526, 3526, 3525},
|
||||||
|
43
|
||||||
|
);
|
||||||
|
private static final Cuboid MAIN_WILDERNESS_CUBOID = new Cuboid(2944, 3525, 0, 3391, 4351, 3);
|
||||||
|
private static final Cuboid GOD_WARS_WILDERNESS_CUBOID = new Cuboid(3008, 10112, 0, 3071, 10175, 3);
|
||||||
|
private static final Cuboid WILDERNESS_UNDERGROUND_CUBOID = new Cuboid(2944, 9920, 0, 3391, 10879, 3);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the wilderness level based on a world point
|
||||||
|
* Java reimplementation of clientscript 384 [proc,wilderness_level]
|
||||||
|
*
|
||||||
|
* @param point the point in the world to get the wilderness level for
|
||||||
|
* @return the int representing the wilderness level
|
||||||
|
*/
|
||||||
|
public static int getWildernessLevelFrom(WorldPoint point)
|
||||||
|
{
|
||||||
|
if (MAIN_WILDERNESS_CUBOID.contains(point))
|
||||||
|
{
|
||||||
|
if (NOT_WILDERNESS_BLACK_KNIGHTS.contains(point.getX(), point.getY()))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((point.getY() - 3520) / 8) + 1; // calc(((coordz(coord) - (55 * 64)) / 8) + 1)
|
||||||
|
}
|
||||||
|
else if (GOD_WARS_WILDERNESS_CUBOID.contains(point))
|
||||||
|
{
|
||||||
|
return ((point.getY() - 9920) / 8) - 1; // calc(((coordz(coord) - (155 * 64)) / 8) - 1)
|
||||||
|
}
|
||||||
|
else if (WILDERNESS_UNDERGROUND_CUBOID.contains(point))
|
||||||
|
{
|
||||||
|
return ((point.getY() - 9920) / 8) + 1; // calc(((coordz(coord) - (155 * 64)) / 8) + 1)
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if another player is attackable based off of wilderness level and combat levels
|
||||||
|
*
|
||||||
|
* @param client The client of the local player
|
||||||
|
* @param player the player to determine attackability
|
||||||
|
* @return returns true if the player is attackable, false otherwise
|
||||||
|
*/
|
||||||
|
public static boolean isAttackable(Client client, Player player)
|
||||||
|
{
|
||||||
|
int wildernessLevel = 0;
|
||||||
|
|
||||||
|
if (WorldType.isDeadmanWorld(client.getWorldType()))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (WorldType.isPvpWorld(client.getWorldType()))
|
||||||
|
{
|
||||||
|
wildernessLevel += 15;
|
||||||
|
}
|
||||||
|
if (client.getVar(Varbits.IN_WILDERNESS) == 1)
|
||||||
|
{
|
||||||
|
wildernessLevel += getWildernessLevelFrom(client.getLocalPlayer().getWorldLocation());
|
||||||
|
}
|
||||||
|
return wildernessLevel != 0 && Math.abs(client.getLocalPlayer().getCombatLevel() - player.getCombatLevel()) <= wildernessLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int calculateRisk(Client client, ItemManager itemManager)
|
||||||
|
{
|
||||||
|
if (client.getItemContainer(InventoryID.EQUIPMENT) == null)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (client.getItemContainer(InventoryID.INVENTORY).getItems() == null)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Item[] items = ArrayUtils.addAll(Objects.requireNonNull(client.getItemContainer(InventoryID.EQUIPMENT)).getItems(),
|
||||||
|
Objects.requireNonNull(client.getItemContainer(InventoryID.INVENTORY)).getItems());
|
||||||
|
TreeMap<Integer, Item> priceMap = new TreeMap<>(Comparator.comparingInt(Integer::intValue));
|
||||||
|
int wealth = 0;
|
||||||
|
for (Item i : items)
|
||||||
|
{
|
||||||
|
int value = (itemManager.getItemPrice(i.getId()) * i.getQuantity());
|
||||||
|
|
||||||
|
final ItemComposition itemComposition = itemManager.getItemComposition(i.getId());
|
||||||
|
if (!itemComposition.isTradeable() && value == 0)
|
||||||
|
{
|
||||||
|
value = itemComposition.getPrice() * i.getQuantity();
|
||||||
|
priceMap.put(value, i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = itemManager.getItemPrice(i.getId()) * i.getQuantity();
|
||||||
|
if (i.getId() > 0 && value > 0)
|
||||||
|
{
|
||||||
|
priceMap.put(value, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wealth += value;
|
||||||
|
}
|
||||||
|
return Integer.parseInt(QuantityFormatter.quantityToRSDecimalStack(priceMap.keySet().stream().mapToInt(Integer::intValue).sum()));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
1
runelite-client/src/main/resources/npc_stats.json
Normal file
1
runelite-client/src/main/resources/npc_stats.json
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user