mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2025-12-11 09:00:23 -07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
fe685d18ac
34 changed files with 237 additions and 134 deletions
|
|
@ -86655,7 +86655,7 @@
|
|||
},
|
||||
{
|
||||
"requirements": "{1,30}-{5,20}",
|
||||
"shop_price": "10",
|
||||
"shop_price": "10000",
|
||||
"ge_buy_limit": "100",
|
||||
"examine": "A Proselyte Temple Knight's leg armour.",
|
||||
"durability": null,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package core.game.content.activity.pestcontrol;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.PriorityQueue;
|
||||
|
||||
import rs09.ServerConstants;
|
||||
import core.game.component.Component;
|
||||
|
|
@ -17,6 +18,7 @@ import core.game.node.entity.state.EntityState;
|
|||
import core.game.node.item.GroundItemManager;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.system.task.Pulse;
|
||||
import rs09.game.ai.AIPlayer;
|
||||
import rs09.game.world.GameWorld;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.build.DynamicRegion;
|
||||
|
|
@ -60,7 +62,13 @@ public final class PestControlActivityPlugin extends ActivityPlugin {
|
|||
/**
|
||||
* The waiting players.
|
||||
*/
|
||||
private final List<Player> waitingPlayers = new ArrayList<>(20);
|
||||
private final PriorityQueue<Player> waitingPlayers = new PriorityQueue<Player>(20, (player1, player2) -> {
|
||||
//get priorities of players. default to 0
|
||||
int p1 = player1.getAttribute("pc_prior", 0);
|
||||
int p2 = player2.getAttribute("pc_prior", 0);
|
||||
//return in descending order
|
||||
return p2 - p1;
|
||||
});
|
||||
|
||||
/**
|
||||
* The active game sessions.
|
||||
|
|
@ -313,7 +321,7 @@ public final class PestControlActivityPlugin extends ActivityPlugin {
|
|||
* Gets the list of waiting players.
|
||||
* @return The list of waiting players.
|
||||
*/
|
||||
public List<Player> getWaitingPlayers() {
|
||||
public PriorityQueue<Player> getWaitingPlayers() {
|
||||
return waitingPlayers;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
package core.game.content.activity.pestcontrol;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.*;
|
||||
|
||||
import core.game.component.Component;
|
||||
import core.game.content.dialogue.FacialExpression;
|
||||
|
|
@ -212,7 +208,7 @@ public final class PestControlSession {
|
|||
* Starts a game.
|
||||
* @param waitingPlayers The list of waiting players.
|
||||
*/
|
||||
public void startGame(List<Player> waitingPlayers) {
|
||||
public void startGame(PriorityQueue<Player> waitingPlayers) {
|
||||
region.flagActive();
|
||||
initBarricadesList();
|
||||
List<Integer> list = new ArrayList<>(20);
|
||||
|
|
@ -225,21 +221,29 @@ public final class PestControlSession {
|
|||
ids = list.toArray(new Integer[4]);
|
||||
int count = 0;
|
||||
String portalHealth = "<col=00FF00>" + (activity.getType().ordinal() == 0 ? 200 : 250);
|
||||
for (Iterator<Player> it = waitingPlayers.iterator(); it.hasNext();) {
|
||||
Player p = it.next();
|
||||
|
||||
List<Player> remainingPlayers = new ArrayList<>();
|
||||
for (Player p = waitingPlayers.poll(); p != null; p = waitingPlayers.poll()) {
|
||||
if (p.getSession().isActive()) {
|
||||
if (++count > MAX_TEAM_SIZE) {
|
||||
int priority = p.getAttribute("pc_prior", 0) + 1;
|
||||
p.getPacketDispatch().sendMessage("You have been given priority level " + priority + " over other players in joining the next");
|
||||
p.getPacketDispatch().sendMessage("game.");
|
||||
p.setAttribute("pc_prior", priority);
|
||||
remainingPlayers.add(p);
|
||||
continue;
|
||||
}
|
||||
addPlayer(p, portalHealth);
|
||||
}
|
||||
it.remove();
|
||||
}
|
||||
|
||||
for (Player p : remainingPlayers)
|
||||
{
|
||||
int priority = p.getAttribute("pc_prior", 0) + 1;
|
||||
p.getPacketDispatch().sendMessage("You have been given priority level " + priority + " over other players in joining the next");
|
||||
p.getPacketDispatch().sendMessage("game.");
|
||||
p.setAttribute("pc_prior", priority);
|
||||
waitingPlayers.add(p);
|
||||
}
|
||||
|
||||
spawnNPCs();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -708,7 +708,7 @@ open class Shop @JvmOverloads constructor(
|
|||
open fun getBuyPrice(item: Item, player: Player): Int {
|
||||
var item = item
|
||||
item = Item(item.id, 1)
|
||||
var price = item.definition.maxValue
|
||||
var price = item.definition.value
|
||||
val sellVal = getSellingValue(item, player)
|
||||
if (price < sellVal) {
|
||||
price = getSellingValue(player, 0, item) + sellVal - (sellVal - item.definition.maxValue)
|
||||
|
|
|
|||
|
|
@ -34,18 +34,16 @@ public final class AvasDevicePlugin implements Plugin<Object> {
|
|||
state.init();
|
||||
break;
|
||||
case "unequip":
|
||||
player.clearState("avadevice");
|
||||
if (args.length == 3) {
|
||||
Item second = (Item) args[2];
|
||||
if (second.getId() == 10498 || second.getId() == 10499) {
|
||||
player.clearState("avadevice");
|
||||
AvaDeviceState newState = (AvaDeviceState) player.registerState("avadevice");
|
||||
newState.setDevice(second.getId());
|
||||
newState.init();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(player.hasActiveState("avadevice")) player.clearState("avadevice");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,16 +132,7 @@ public final class TreasureTrailPlugin extends OptionHandler {
|
|||
|
||||
@Override
|
||||
public boolean createDrop(Item item, Player player, NPC npc, Location l) {
|
||||
if ((npc.getId() == 49 || npc.getId() == 3586)) {
|
||||
return true;
|
||||
}
|
||||
if (npc.getDefinition().getDropTables().getMainTable().size() < 3) {
|
||||
return false;
|
||||
}
|
||||
if (!hasClue(player)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return !hasClue(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import java.util.HashMap;
|
|||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Class used for handling combat impacts.
|
||||
|
|
@ -262,6 +263,15 @@ public final class ImpactHandler {
|
|||
return impactLog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the impact log filtered for Player objects
|
||||
* @return The impact log of each Player and their damage
|
||||
*/
|
||||
public Map<Player, Integer> getPlayerImpactLog() {
|
||||
return impactLog.entrySet().stream().filter(entry -> entry.getKey() instanceof Player).collect(
|
||||
Collectors.toMap(m -> m.getKey().asPlayer(), m -> m.getValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the entity needs a hit update.
|
||||
* @return {@code True} if so.
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ public final class ChinchompaSwingHandler extends RangeSwingHandler {
|
|||
s.getVictim().animate(s.getVictim().getProperties().getDefenceAnimation());
|
||||
}
|
||||
}
|
||||
addExperience(entity, victim, state);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -155,4 +156,4 @@ public final class ChinchompaSwingHandler extends RangeSwingHandler {
|
|||
public static ChinchompaSwingHandler getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,9 +134,12 @@ public final class BindSpell extends CombatSpell {
|
|||
|
||||
@Override
|
||||
public Plugin<SpellType> newInstance(SpellType type) throws Throwable {
|
||||
SpellBook.MODERN.register(12, new BindSpell(SpellType.BIND, 20, 30.0, 151, BIND_START, BIND_PROJECTILE, BIND_END, Runes.NATURE_RUNE.getItem(2), Runes.EARTH_RUNE.getItem(3), Runes.WATER_RUNE.getItem(3)));
|
||||
SpellBook.MODERN.register(30, new BindSpell(SpellType.SNARE, 50, 60.0, 152, SNARE_START, SNARE_PROJECTILE, SNARE_END, Runes.NATURE_RUNE.getItem(3), Runes.EARTH_RUNE.getItem(4), Runes.WATER_RUNE.getItem(4)));
|
||||
SpellBook.MODERN.register(56, new BindSpell(SpellType.ENTANGLE, 79, 89.0, 153, ENTANGLE_START, ENTANGLE_PROJECTILE, ENTANGLE_END, Runes.NATURE_RUNE.getItem(4), Runes.EARTH_RUNE.getItem(5), Runes.WATER_RUNE.getItem(5)));
|
||||
// TODO: bind/snare/entangle have separate casting and onhit components
|
||||
// to their sound effects, in order for splashes to sound distinct, currently
|
||||
// these just sound like the spells should on success, even if they splash
|
||||
SpellBook.MODERN.register(12, new BindSpell(SpellType.BIND, 20, 30.0, 101, BIND_START, BIND_PROJECTILE, BIND_END, Runes.NATURE_RUNE.getItem(2), Runes.EARTH_RUNE.getItem(3), Runes.WATER_RUNE.getItem(3)));
|
||||
SpellBook.MODERN.register(30, new BindSpell(SpellType.SNARE, 50, 60.0, 186, SNARE_START, SNARE_PROJECTILE, SNARE_END, Runes.NATURE_RUNE.getItem(3), Runes.EARTH_RUNE.getItem(4), Runes.WATER_RUNE.getItem(4)));
|
||||
SpellBook.MODERN.register(56, new BindSpell(SpellType.ENTANGLE, 79, 89.0, 152, ENTANGLE_START, ENTANGLE_PROJECTILE, ENTANGLE_END, Runes.NATURE_RUNE.getItem(4), Runes.EARTH_RUNE.getItem(5), Runes.WATER_RUNE.getItem(5)));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ import rs09.game.system.config.ShopParser;
|
|||
import rs09.game.world.GameWorld;
|
||||
import rs09.game.world.repository.Repository;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static rs09.game.node.entity.player.info.stats.StatAttributeKeysKt.STATS_BASE;
|
||||
import static rs09.game.node.entity.player.info.stats.StatAttributeKeysKt.STATS_ENEMIES_KILLED;
|
||||
|
||||
|
|
@ -543,7 +545,7 @@ public class NPC extends Entity {
|
|||
if (getAttribute("disable:drop", false)) {
|
||||
return;
|
||||
}
|
||||
if (killer instanceof Player && p != null && p.getIronmanManager().isIronman() && getImpactHandler().getImpactLog().size() > 1) {
|
||||
if (killer instanceof Player && p != null && p.getIronmanManager().isIronman() && getImpactHandler().getPlayerImpactLog().size() > 1) {
|
||||
return;
|
||||
}
|
||||
if (definition == null || definition.getDropTables() == null) {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import core.game.node.entity.skill.Skills;
|
|||
import core.game.node.item.GroundItem;
|
||||
import core.game.node.item.GroundItemManager;
|
||||
import core.game.node.item.Item;
|
||||
import core.game.node.item.WeightedChanceItem;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.tools.RandomFunction;
|
||||
|
|
@ -41,21 +40,6 @@ public final class NPCDropTables {
|
|||
* The npcs that will display drop messages
|
||||
*/
|
||||
public static final int[] MESSAGE_NPCS = { 50, 7133, 7134, 2881, 2882, 2883, 3200, 3340, 6247, 6203, 6260, 6222, 2745, 1160, 8133, 8610, 8611, 8612, 8613, 8614, 6204, 6206, 6208, 6261, 6263, 6265, 6223, 6225, 6227 };
|
||||
|
||||
/**
|
||||
* The default drop table (holding the 100% drops).
|
||||
*/
|
||||
private final List<WeightedChanceItem> defaultTable = new ArrayList<>(20);
|
||||
|
||||
/**
|
||||
* The charms drop table (holding the charm drops).
|
||||
*/
|
||||
private final List<WeightedChanceItem> charmTable = new ArrayList<>(20);
|
||||
|
||||
/**
|
||||
* The main drop table (holding the main drops).
|
||||
*/
|
||||
private final List<WeightedChanceItem> mainTable = new ArrayList<>(20);
|
||||
|
||||
public final NPCDropTable table = new NPCDropTable();
|
||||
|
||||
|
|
@ -239,41 +223,6 @@ public final class NPCDropTables {
|
|||
return (1 / (1 + def.getCombatLevel())) * 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the defaultTable.
|
||||
*/
|
||||
public List<WeightedChanceItem> getDefaultTable() {
|
||||
return defaultTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the charmTable.
|
||||
*/
|
||||
public List<WeightedChanceItem> getCharmTable() {
|
||||
return charmTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the mainTable.
|
||||
*/
|
||||
public List<WeightedChanceItem> getMainTable() {
|
||||
return mainTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the mainTableSize.
|
||||
*/
|
||||
public int getMainTableSize() {
|
||||
return mainTableSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mainTableSize the mainTableSize to set.
|
||||
*/
|
||||
public void setMainTableSize(int mainTableSize) {
|
||||
this.mainTableSize = mainTableSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the modRate.
|
||||
* @return The modRate.
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ public class BunyipNPC extends Familiar {
|
|||
player.sendMessage("Error: Report to admin.");
|
||||
return false;
|
||||
}
|
||||
if (player.getSkills().getLevel(Skills.COOKING) < CookableItems.forId(special.getItem().getId() + 2).level) {
|
||||
if (player.getSkills().getLevel(Skills.COOKING) < CookableItems.forId(special.getItem().getId()).level) {
|
||||
player.sendMessage("You need a Cooking level of at least " + CookableItems.forId(special.getItem().getId()).level + " in order to do that.");
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -480,6 +480,7 @@ public class Player extends Entity {
|
|||
if(time == 0){
|
||||
sendMessage(colorize("%RYour antifire potion has expired."));
|
||||
removeAttribute("fire:immune");
|
||||
getAudioManager().send(2607);
|
||||
}
|
||||
}
|
||||
if(getAttribute("poison:immunity",0) > 0){
|
||||
|
|
@ -491,6 +492,7 @@ public class Player extends Entity {
|
|||
if(time == 0){
|
||||
sendMessage(colorize("%RYour antipoison potion has expired."));
|
||||
removeAttribute("poison:immunity");
|
||||
getAudioManager().send(2607);
|
||||
}
|
||||
}
|
||||
if (!artificial && (System.currentTimeMillis() - getSession().getLastPing()) > 20_000L) {
|
||||
|
|
@ -1384,7 +1386,10 @@ public class Player extends Entity {
|
|||
public void clearState(String key){
|
||||
State state = states.get(key);
|
||||
if(state == null) return;
|
||||
state.getPulse().stop();
|
||||
Pulse pulse = state.getPulse();
|
||||
if(pulse != null) {
|
||||
pulse.stop();
|
||||
}
|
||||
states.remove(key);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,11 +8,13 @@ import core.game.node.entity.combat.ImpactHandler.HitsplatType;
|
|||
import core.game.node.entity.impl.Projectile;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.system.task.Pulse;
|
||||
import core.game.world.map.Location;
|
||||
import core.game.world.map.RegionManager;
|
||||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.tools.RandomFunction;
|
||||
import rs09.game.node.entity.skill.skillcapeperks.SkillcapePerks;
|
||||
import rs09.game.world.GameWorld;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -62,8 +64,15 @@ public final class Prayer {
|
|||
player.getConfigManager().set(type.getConfig(), 0);
|
||||
}
|
||||
getActive().clear();
|
||||
player.getAppearance().setHeadIcon(-1);
|
||||
player.getAppearance().sync();
|
||||
// Clear the overhead prayer icon a tick later
|
||||
GameWorld.getPulser().submit(new Pulse(1) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
player.getAppearance().setHeadIcon(-1);
|
||||
player.getAppearance().sync();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -119,6 +128,7 @@ public final class Prayer {
|
|||
|
||||
if(prayerActiveTicks > 0 && prayerActiveTicks % 2 == 0){
|
||||
if(getPlayer().getSkills().getPrayerPoints() == 0){
|
||||
getPlayer().getAudioManager().send(2672);
|
||||
reset();
|
||||
return;
|
||||
}
|
||||
|
|
@ -190,4 +200,4 @@ public final class Prayer {
|
|||
return active;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import core.game.world.update.flag.context.Animation;
|
|||
import core.game.world.update.flag.context.Graphics;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
import core.tools.RandomFunction;
|
||||
|
||||
/**
|
||||
* The super glass make spell.
|
||||
|
|
@ -79,6 +80,11 @@ public class SuperglassMakeSpell extends MagicSpell {
|
|||
if (hasSet(player, setIndex)) {
|
||||
if (player.getInventory().remove(BUCKET_OF_SAND, SETS[setIndex])) {
|
||||
player.getInventory().add(MOLTEN_GLASS);
|
||||
// https://runescape.wiki/w/Superglass_Make?oldid=1970761
|
||||
// "On average, each set will produce 1.30 pieces of molten glass"
|
||||
if(RandomFunction.randomDouble(1.0) < 0.3) {
|
||||
player.getInventory().add(MOLTEN_GLASS);
|
||||
}
|
||||
player.getSkills().addExperience(Skills.CRAFTING, 10, true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,6 +133,7 @@ public final class RuneCraftPulse extends SkillPulse<Item> {
|
|||
public void animate() {
|
||||
player.animate(ANIMATION);
|
||||
player.graphics(GRAPHICS);
|
||||
player.getAudioManager().send(2710);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -234,14 +235,14 @@ public final class RuneCraftPulse extends SkillPulse<Item> {
|
|||
}
|
||||
if (player.getInventory().remove(new Item(PURE_ESSENCE.getId(), amount)) && player.getInventory().remove(new Item(rune.getId(), amount))) {
|
||||
for (int i = 0; i < amount; i++) {
|
||||
if (RandomFunction.random(1, 3) == 1 || hasBindingNeckalce()) {
|
||||
if (RandomFunction.random(1, 3) == 1 || hasBindingNecklace()) {
|
||||
player.getInventory().add(new Item(combo.getRune().getId(), 1));
|
||||
player.getSkills().addExperience(Skills.RUNECRAFTING, combo.getExperience(), true);
|
||||
}
|
||||
}
|
||||
if (hasBindingNeckalce()) {
|
||||
player.getEquipment().get(EquipmentContainer.SLOT_HAT).setCharge(player.getEquipment().get(EquipmentContainer.SLOT_HAT).getCharge() - 1);
|
||||
if (1000 - player.getEquipment().get(EquipmentContainer.SLOT_HAT).getCharge() > 14) {
|
||||
if (hasBindingNecklace()) {
|
||||
player.getEquipment().get(EquipmentContainer.SLOT_AMULET).setCharge(player.getEquipment().get(EquipmentContainer.SLOT_AMULET).getCharge() - 1);
|
||||
if (1000 - player.getEquipment().get(EquipmentContainer.SLOT_AMULET).getCharge() > 14) {
|
||||
player.getEquipment().remove(BINDING_NECKLACE, true);
|
||||
player.getPacketDispatch().sendMessage("Your binding necklace crumbles into dust.");
|
||||
}
|
||||
|
|
@ -325,7 +326,7 @@ public final class RuneCraftPulse extends SkillPulse<Item> {
|
|||
*
|
||||
* @return <code>True</code> if so.
|
||||
*/
|
||||
public boolean hasBindingNeckalce() {
|
||||
public boolean hasBindingNecklace() {
|
||||
return player.getEquipment().containsItem(BINDING_NECKLACE);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import core.game.node.entity.player.Player;
|
|||
import core.game.node.entity.player.link.SpellBookManager.SpellBook;
|
||||
import core.game.world.map.Location;
|
||||
import core.plugin.Initializable;
|
||||
import org.rs09.consts.Items;
|
||||
import rs09.game.node.entity.skill.slayer.SlayerUtils;
|
||||
|
||||
/**
|
||||
* Handles the kurask npc.
|
||||
|
|
@ -41,9 +43,7 @@ public final class KuraskNPC extends AbstractNPC {
|
|||
boolean effective = false;
|
||||
if (state.getAttacker() instanceof Player) {
|
||||
final Player player = (Player) state.getAttacker();
|
||||
if ((state.getWeapon() != null && state.getWeapon().getId() == 4158) || (state.getAmmunition() != null && state.getAmmunition().getItemId() == 4160) || (state.getWeapon() != null && state.getWeapon().getId() == 13290) || (state.getSpell() != null && state.getSpell().getSpellId() == 31 && player.getSpellBookManager().getSpellBook() == SpellBook.MODERN.getInterfaceId()) || (state.getAmmunition() != null && state.getAmmunition().getItemId() == 881)) {
|
||||
effective = true;
|
||||
}
|
||||
effective = new SlayerUtils(player).hasBroadWeaponEquipped(state);
|
||||
}
|
||||
if (!effective) {
|
||||
state.setEstimatedHit(0);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import core.game.node.entity.player.Player;
|
|||
import core.game.node.entity.player.link.SpellBookManager.SpellBook;
|
||||
import core.game.world.map.Location;
|
||||
import core.plugin.Initializable;
|
||||
import org.rs09.consts.Items;
|
||||
import rs09.game.node.entity.skill.slayer.SlayerUtils;
|
||||
|
||||
/**
|
||||
* Handles the turoth npc.
|
||||
|
|
@ -41,9 +43,7 @@ public final class TurothNPC extends AbstractNPC {
|
|||
boolean effective = false;
|
||||
if (state.getAttacker() instanceof Player) {
|
||||
final Player player = (Player) state.getAttacker();
|
||||
if ((state.getWeapon() != null && state.getWeapon().getId() == 4158) || (state.getAmmunition() != null && state.getAmmunition().getItemId() == 4160) || (state.getWeapon() != null && state.getWeapon().getId() == 13290) || (state.getSpell() != null && state.getSpell().getSpellId() == 31 && player.getSpellBookManager().getSpellBook() == SpellBook.MODERN.getInterfaceId())) {
|
||||
effective = true;
|
||||
}
|
||||
effective = new SlayerUtils(player).hasBroadWeaponEquipped(state);
|
||||
}
|
||||
if (!effective) {
|
||||
state.setEstimatedHit(0);
|
||||
|
|
|
|||
|
|
@ -229,6 +229,23 @@ public final class Location extends Node {
|
|||
return product <= dist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if a player is within a specified distance using max norm distance.
|
||||
* @param other The other location.
|
||||
* @param dist The amount of distance.
|
||||
* @return If you're within the other distance.
|
||||
*/
|
||||
public boolean withinMaxnormDistance(Location other, int dist) {
|
||||
if (other.z != z) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int a = Math.abs(other.x - x);
|
||||
int b = Math.abs(other.y - y);
|
||||
double max = Math.max(a, b);
|
||||
return max <= dist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the distance between you and the other.
|
||||
* @param other The other location.
|
||||
|
|
@ -455,4 +472,4 @@ public final class Location extends Node {
|
|||
public void setZ(int z) {
|
||||
this.z = z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -538,11 +538,15 @@ object RegionManager {
|
|||
*/
|
||||
@JvmStatic
|
||||
fun getSurroundingPlayers(n: Node, maximum: Int, vararg ignore: Node): List<Player> {
|
||||
val players = getLocalPlayers(n.location, 1)
|
||||
val players = getLocalPlayers(n.location, 2)
|
||||
var count = 0
|
||||
val it = players.iterator()
|
||||
while (it.hasNext()) {
|
||||
val p = it.next()
|
||||
if(!p.location.withinMaxnormDistance(n.location, 1)) {
|
||||
it.remove()
|
||||
continue
|
||||
}
|
||||
if (++count >= maximum) {
|
||||
it.remove()
|
||||
continue
|
||||
|
|
@ -577,11 +581,15 @@ object RegionManager {
|
|||
*/
|
||||
@JvmStatic
|
||||
fun getSurroundingNPCs(n: Node, maximum: Int, vararg ignore: Node): List<NPC> {
|
||||
val npcs = getLocalNpcs(n.location, 1)
|
||||
val npcs = getLocalNpcs(n.location, 2)
|
||||
var count = 0
|
||||
val it = npcs.iterator()
|
||||
while (it.hasNext()) {
|
||||
val p = it.next()
|
||||
if(!p.location.withinMaxnormDistance(n.location, 1)) {
|
||||
it.remove()
|
||||
continue
|
||||
}
|
||||
if (++count > maximum) {
|
||||
it.remove()
|
||||
continue
|
||||
|
|
@ -806,4 +814,4 @@ object RegionManager {
|
|||
|
||||
val lock: ReentrantLock
|
||||
@JvmStatic get() = LOCK
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ object EssenceTeleport {
|
|||
npc.faceTemporary(player, 1)
|
||||
npc.graphics(Graphics(108))
|
||||
player.lock()
|
||||
player.audioManager.send(195)
|
||||
player.audioManager.send(125)
|
||||
Projectile.create(npc, player, 109).send()
|
||||
npc.sendChat("Senventior Disthinte Molesko!")
|
||||
GameWorld.Pulser.submit(object : Pulse(1) {
|
||||
|
|
@ -177,4 +177,4 @@ object EssenceTeleport {
|
|||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,7 +129,7 @@ class CombatPulse(
|
|||
if (handler == null) {
|
||||
handler = entity.getSwingHandler(true)
|
||||
}
|
||||
if (!entity.isAttackable(v, handler!!.type)) {
|
||||
if (!v.isAttackable(entity, handler!!.type)) {
|
||||
return true
|
||||
}
|
||||
if (!swing(entity, victim, handler)) {
|
||||
|
|
|
|||
|
|
@ -244,6 +244,18 @@ open class MeleeSwingHandler
|
|||
if (state.secondaryHit > 0) {
|
||||
hit += state.secondaryHit
|
||||
}
|
||||
if(state.targets != null) {
|
||||
for (s in state.targets) {
|
||||
if (s != null) {
|
||||
if(s.estimatedHit > 0) {
|
||||
hit += s.estimatedHit
|
||||
}
|
||||
if(s.secondaryHit > 0) {
|
||||
hit += s.secondaryHit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var experience = hit * EXPERIENCE_MOD
|
||||
val famExp = entity.getAttribute("fam-exp", false) && entity.familiarManager.hasFamiliar()
|
||||
if (!famExp) {
|
||||
|
|
|
|||
|
|
@ -148,6 +148,18 @@ open class RangeSwingHandler
|
|||
if (state.secondaryHit > 0) {
|
||||
hit += state.secondaryHit
|
||||
}
|
||||
if(state.targets != null) {
|
||||
for (s in state.targets) {
|
||||
if (s != null) {
|
||||
if(s.estimatedHit > 0) {
|
||||
hit += s.estimatedHit
|
||||
}
|
||||
if(s.secondaryHit > 0) {
|
||||
hit += s.secondaryHit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val p = entity.asPlayer()
|
||||
val famExp = entity.getAttribute("fam-exp", false) && p.familiarManager.hasFamiliar()
|
||||
if (famExp) {
|
||||
|
|
|
|||
|
|
@ -65,9 +65,11 @@ enum class FarmingPatch(val varpIndex: Int, val varpOffset: Int, val type: Patch
|
|||
|
||||
//Other
|
||||
DRAYNOR_BELLADONNA(512, 16, PatchType.BELLADONNA),
|
||||
CANIFIS_MUSHROOM(512, 8, PatchType.MUSHROOM),
|
||||
ALKHARID_CACTUS(512, 0, PatchType.CACTUS),
|
||||
EVIL_TURNIP(1171, 7, PatchType.EVIL_TURNIP);
|
||||
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val patches = FarmingPatch.values().map { (it.varpIndex shl it.varpOffset) to it }.toMap()
|
||||
|
|
@ -93,4 +95,4 @@ enum class FarmingPatch(val varpIndex: Int, val varpOffset: Int, val type: Patch
|
|||
} else
|
||||
state.getPatch(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package rs09.game.node.entity.skill.farming
|
|||
|
||||
import core.game.node.entity.player.Player
|
||||
import core.tools.RandomFunction
|
||||
import org.rs09.consts.Items
|
||||
import rs09.game.system.SystemLogger
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.math.ceil
|
||||
|
|
@ -16,11 +17,20 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
|
|||
var cropLives = 3
|
||||
|
||||
fun setNewHarvestAmount() {
|
||||
val compostMod = when(compost) {
|
||||
CompostType.NONE -> 0
|
||||
CompostType.NORMAL -> 1
|
||||
CompostType.SUPER -> 2
|
||||
}
|
||||
harvestAmt = when (plantable) {
|
||||
Plantable.LIMPWURT_SEED, Plantable.WOAD_SEED -> 3
|
||||
Plantable.MUSHROOM_SPORE -> 6
|
||||
else -> 1
|
||||
}
|
||||
cropLives = 3
|
||||
if(plantable != null && plantable?.applicablePatch != PatchType.FLOWER) {
|
||||
harvestAmt += compostMod
|
||||
}
|
||||
cropLives = 3 + compostMod
|
||||
}
|
||||
|
||||
fun rollLivesDecrement(farmingLevel: Int, magicSecateurs: Boolean){
|
||||
|
|
@ -59,8 +69,9 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
|
|||
PatchType.ALLOTMENT -> 8 //average of 8 per life times 3 lives = average 24
|
||||
PatchType.HOPS -> 6 //average of 6 per life times 3 lives = 18
|
||||
PatchType.BELLADONNA -> 2 //average of 2 per life times 3 lives = 6
|
||||
PatchType.EVIL_TURNIP -> 2 //average 2 per, same as BELLADONNA
|
||||
PatchType.CACTUS -> 3 //average of 3 per life times 3 lives = 9
|
||||
else -> return
|
||||
else -> 0 // nothing should go here, but if it does, do not give extra crops amd decrement cropLives
|
||||
}
|
||||
|
||||
if(magicSecateurs) chance += ceil(1.10 * chance).toInt() //will increase average yield by roughly 3.
|
||||
|
|
@ -226,7 +237,7 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
|
|||
CompostType.SUPER -> 13
|
||||
}
|
||||
|
||||
if(RandomFunction.random(128) <= (17 - diseaseMod) && !isWatered && !isGrown() && !protectionPaid && !isFlowerProtected() && patch.type != PatchType.EVIL_TURNIP){
|
||||
if(patch != FarmingPatch.TROLL_STRONGHOLD_HERB && RandomFunction.random(128) <= (17 - diseaseMod) && !isWatered && !isGrown() && !protectionPaid && !isFlowerProtected() && patch.type != PatchType.EVIL_TURNIP ){
|
||||
//bush, tree, fruit tree, herb and cactus can not disease on stage 1(0) of growth.
|
||||
if(!((patch.type == PatchType.BUSH || patch.type == PatchType.TREE || patch.type == PatchType.FRUIT_TREE || patch.type == PatchType.CACTUS || patch.type == PatchType.HERB) && currentGrowthStage == 0)) {
|
||||
isDiseased = true
|
||||
|
|
@ -293,6 +304,8 @@ class Patch(val player: Player, val patch: FarmingPatch, var plantable: Plantabl
|
|||
else -> return false
|
||||
}.getPatchFor(player)
|
||||
|
||||
return (fpatch.plantable != null && fpatch.plantable == plantable?.protectionFlower && fpatch.isGrown())
|
||||
return (fpatch.plantable != null &&
|
||||
(fpatch.plantable == plantable?.protectionFlower || fpatch.plantable == Plantable.forItemID(Items.WHITE_LILY_SEED_14589))
|
||||
&& fpatch.isGrown())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ enum class PatchType(val stageGrowthTime: Int) {
|
|||
FLOWER(5),
|
||||
HERB(20),
|
||||
SPIRIT_TREE(293),
|
||||
MUSHROOM(30),
|
||||
BELLADONNA(80),
|
||||
CACTUS(60),
|
||||
EVIL_TURNIP(5)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ enum class Plantable(val itemID: Int, val value: Int, val stages: Int, val plant
|
|||
|
||||
//Other
|
||||
BELLADONNA_SEED(5281, 4, 4, 91.0, 128.0, 0.0, 63, PatchType.BELLADONNA, Items.CAVE_NIGHTSHADE_2398),
|
||||
MUSHROOM_SPORE(Items.MUSHROOM_SPORE_5282, 6, 7, 61.5, 57.7, 0.0, 53, PatchType.MUSHROOM, Items.MUSHROOM_6004),
|
||||
CACTUS_SEED(Items.CACTUS_SEED_5280, 8, 7, 66.5, 25.0, 374.0, 55, PatchType.CACTUS, Items.CACTUS_SPINE_6016),
|
||||
EVIL_TURNIP_SEED(Items.EVIL_TURNIP_SEED_12148, 4, 1, 41.0, 46.0, 0.0, 42, PatchType.EVIL_TURNIP, Items.EVIL_TURNIP_12134)
|
||||
;
|
||||
|
|
@ -98,4 +99,4 @@ enum class Plantable(val itemID: Int, val value: Int, val stages: Int, val plant
|
|||
return forItemID(item.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ object UseWithPatchHandler{
|
|||
if(player.inventory.remove(event.usedItem,false)){
|
||||
p.compost = if(usedItem.id == Items.SUPERCOMPOST_6034) CompostType.SUPER else CompostType.NORMAL
|
||||
if(p.compost == CompostType.SUPER) ContentAPI.rewardXP(player, Skills.FARMING, 26.0) else ContentAPI.rewardXP(player, Skills.FARMING, 18.5)
|
||||
if(p.plantable != null){
|
||||
if(p.plantable != null && p.plantable?.applicablePatch != PatchType.FLOWER) {
|
||||
p.harvestAmt += if(p.compost == CompostType.NORMAL) 1 else if(p.compost == CompostType.SUPER) 2 else 0
|
||||
}
|
||||
p.cropLives += if(p.compost == CompostType.SUPER) 2 else 1
|
||||
|
|
@ -212,4 +212,4 @@ object UseWithPatchHandler{
|
|||
if(this == Items.WATERING_CAN1_5333) return Items.WATERING_CAN_5331
|
||||
else return this - 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -319,6 +319,10 @@ class PitfallNPC : AbstractNPC {
|
|||
}
|
||||
|
||||
override fun isAttackable(entity: Entity, style: CombatStyle): Boolean {
|
||||
return entity is Player
|
||||
return false
|
||||
}
|
||||
|
||||
override fun isIgnoreAttackRestrictions(victim: Entity): Boolean {
|
||||
return victim is Player
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
package rs09.game.node.entity.skill.slayer
|
||||
|
||||
import core.game.node.entity.combat.BattleState
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.link.SpellBookManager.SpellBook
|
||||
import org.rs09.consts.Items
|
||||
|
||||
class SlayerUtils(val player: Player) {
|
||||
|
||||
fun hasBroadWeaponEquipped(state: BattleState): Boolean {
|
||||
return (state.weapon != null && state.weapon.id == Items.LEAF_BLADED_SPEAR_4158 ||
|
||||
state.weapon != null && state.weapon.id == Items.LEAF_BLADED_SWORD_13290 ||
|
||||
state.ammunition != null && (state.ammunition.itemId == Items.BROAD_ARROW_4160 || state.ammunition.itemId == Items.BROAD_TIPPED_BOLTS_13280) ||
|
||||
state.spell != null && state.spell.spellId == 31 && player.spellBookManager
|
||||
.spellBook == SpellBook.MODERN.interfaceId
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -22,8 +22,7 @@ class AvaDeviceState(player: Player? = null) : State(player) {
|
|||
private val ACCUMULATOR_REWARDS = arrayOf(Items.STEEL_BAR_2353,Items.STEEL_2H_SWORD_1311,Items.STEEL_KNIFE_865,Items.STEEL_DAGGER_1207,Items.STEEL_MED_HELM_1141,Items.STEEL_DART_808,Items.STEEL_BOLTS_9141,Items.STEEL_ARROW_886,Items.IRON_BAR_2351)
|
||||
|
||||
override fun save(root: JSONObject) {
|
||||
if(pulse == null || !pulse!!.isRunning)
|
||||
root.put("device-id",device)
|
||||
root.put("device-id",device)
|
||||
}
|
||||
|
||||
override fun parse(_data: JSONObject) {
|
||||
|
|
@ -44,6 +43,8 @@ class AvaDeviceState(player: Player? = null) : State(player) {
|
|||
pulse = object : Pulse(TICKS){
|
||||
override fun pulse(): Boolean {
|
||||
if(!hasDevice(player)){
|
||||
player.clearState("avadevice")
|
||||
pulse = null
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
@ -93,4 +94,4 @@ class AvaDeviceState(player: Player? = null) : State(player) {
|
|||
return false
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,37 +5,40 @@ import core.game.system.task.Pulse
|
|||
import org.json.simple.JSONObject
|
||||
import rs09.game.node.entity.state.newsys.PlayerState
|
||||
import rs09.game.node.entity.state.newsys.State
|
||||
import rs09.game.world.GameWorld;
|
||||
|
||||
@PlayerState("godcharge")
|
||||
class GodspellChargedState(player: Player? = null) : State(player) {
|
||||
var TICKS = 700
|
||||
val DURATION = 700
|
||||
var startTick: Int = 0
|
||||
|
||||
override fun save(root: JSONObject) {
|
||||
if(TICKS > 0){
|
||||
root.put("ticksleft",TICKS)
|
||||
}
|
||||
root.put("ticks_elapsed", GameWorld.ticks - startTick)
|
||||
}
|
||||
|
||||
override fun parse(_data: JSONObject) {
|
||||
if(_data.containsKey("ticksleft")){
|
||||
TICKS = _data["ticksleft"].toString().toInt()
|
||||
if(_data.containsKey("ticks_elapsed")){
|
||||
startTick = GameWorld.ticks - _data["ticks_elapsed"].toString().toInt()
|
||||
}
|
||||
}
|
||||
|
||||
override fun newInstance(player: Player?): State {
|
||||
return GodspellChargedState(player)
|
||||
var ret = GodspellChargedState(player)
|
||||
ret.startTick = GameWorld.ticks
|
||||
return ret
|
||||
}
|
||||
|
||||
override fun createPulse() {
|
||||
player ?: return
|
||||
if(TICKS <= 0) return
|
||||
pulse = object : Pulse(TICKS){
|
||||
if(GameWorld.ticks - startTick >= DURATION) return
|
||||
pulse = object : Pulse(DURATION) {
|
||||
override fun pulse(): Boolean {
|
||||
player.sendMessage("Your magical charge fades away.")
|
||||
player.clearState("godcharge")
|
||||
pulse = null
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue