From 6dd30896f04ed5d17a0771163ec3d2d9d0ec31d6 Mon Sep 17 00:00:00 2001 From: Ceikry Date: Sat, 2 Jul 2022 07:48:46 +0000 Subject: [PATCH] Fixed a bug where an NPC could not attack an entity that was already set as their target Fixed a regression that prevents some NPCs from walking back to their spawn point Fixed a longstanding issue that didn't properly reset NPCs who wandered too far out of their natural movement radius (now disables combat + walks them back to their spawn point + fully heals them) --- .../java/core/game/node/entity/npc/NPC.java | 72 +++++++++++++------ .../entity/npc/agg/AggressiveHandler.java | 14 ++-- .../game/node/entity/combat/CombatPulse.kt | 3 +- .../node/entity/combat/CombatSwingHandler.kt | 4 ++ 4 files changed, 61 insertions(+), 32 deletions(-) diff --git a/Server/src/main/java/core/game/node/entity/npc/NPC.java b/Server/src/main/java/core/game/node/entity/npc/NPC.java index 4f6379ed0..23bdbf664 100644 --- a/Server/src/main/java/core/game/node/entity/npc/NPC.java +++ b/Server/src/main/java/core/game/node/entity/npc/NPC.java @@ -412,13 +412,42 @@ public class NPC extends Entity { */ public void handleTickActions() { if (!getLocks().isInteractionLocked()) { - if (!pathBoundMovement && walkRadius > 0 && !getLocation().withinDistance(getProperties().getSpawnLocation(), walkRadius)) { - if(!isNeverWalks()){ - if(walkRadius == 0) - walkRadius = 3; + if (!getLocks().isMovementLocked()) { + if ( + !pathBoundMovement + && walkRadius > 0 + && !getLocation().withinDistance(getProperties().getSpawnLocation(), (int)(walkRadius * 1.5)) + ) + { + if(!isNeverWalks()){ + if(walkRadius == 0) + walkRadius = 3; + } + if (aggressiveHandler != null) { + aggressiveHandler.setPauseTicks(walkRadius + 1); + } + nextWalk = GameWorld.getTicks() + walkRadius + 1; + getLocks().lockMovement(100); + getImpactHandler().setDisabledTicks(100); + setAttribute("return-to-spawn", true); + GameWorld.getPulser().submit(new MovementPulse(this, getProperties().getSpawnLocation(), Pathfinder.SMART) { + @Override + public boolean pulse() { + getProperties().getCombatPulse().stop(); + getLocks().unlockMovement(); + fullRestore(); + getImpactHandler().setDisabledTicks(0); + removeAttribute("return-to-spawn"); + return true; + } + }); + return; } - if (aggressiveHandler != null) { - aggressiveHandler.setPauseTicks(walkRadius + 1); + if (dialoguePlayer == null || !dialoguePlayer.isActive() || !dialoguePlayer.getInterfaceManager().hasChatbox()) { + dialoguePlayer = null; + if (walks && !getPulseManager().hasPulseRunning() && !getProperties().getCombatPulse().isAttacking() && !getProperties().getCombatPulse().isInCombat() && nextWalk < GameWorld.getTicks()) { + if (walkToNextDest()) return; + } } } if (aggressive && aggressiveHandler != null && aggressiveHandler.selectTarget()) { @@ -428,29 +457,26 @@ public class NPC extends Entity { return; } } - if (!getLocks().isMovementLocked()) { - if (dialoguePlayer == null || !dialoguePlayer.isActive() || !dialoguePlayer.getInterfaceManager().hasChatbox()) { - dialoguePlayer = null; - if (walks && !getPulseManager().hasPulseRunning() && !getProperties().getCombatPulse().isAttacking() && !getProperties().getCombatPulse().isInCombat() && nextWalk < GameWorld.getTicks()) { - if (RandomFunction.nextBool()) return; - setNextWalk(); - Location l = getMovementDestination(); - if (canMove(l)) { - if((Boolean) definition.getHandlers().getOrDefault("water_npc",false)){ - Pathfinder.findWater(this,l,true,Pathfinder.DUMB).walk(this); - } else { - Pathfinder.find(this, l, true, Pathfinder.DUMB).walk(this); - } - } - } - } - } if (forceTalk != null && getAttribute("lastForceTalk", 0) < GameWorld.getTicks()) { sendChat(forceTalk); setAttribute("lastForceTalk", GameWorld.getTicks() + RandomFunction.random(15, 30)); } } + private boolean walkToNextDest() { + if (RandomFunction.nextBool()) return true; + setNextWalk(); + Location l = getMovementDestination(); + if (canMove(l)) { + if((Boolean) definition.getHandlers().getOrDefault("water_npc",false)){ + Pathfinder.findWater(this,l,true,Pathfinder.DUMB).walk(this); + } else { + Pathfinder.find(this, l, true, Pathfinder.DUMB).walk(this); + } + } + return false; + } + /** * Sets the next walk. */ diff --git a/Server/src/main/java/core/game/node/entity/npc/agg/AggressiveHandler.java b/Server/src/main/java/core/game/node/entity/npc/agg/AggressiveHandler.java index c11a2e404..82d4f0a37 100644 --- a/Server/src/main/java/core/game/node/entity/npc/agg/AggressiveHandler.java +++ b/Server/src/main/java/core/game/node/entity/npc/agg/AggressiveHandler.java @@ -90,15 +90,13 @@ public final class AggressiveHandler { } if (target != null) { target.setAttribute("aggressor", entity); - if (target != entity.getProperties().getCombatPulse().getVictim()) { - if (entity.getProperties().getCombatPulse().isAttacking()) { - entity.getProperties().getCombatPulse().setVictim(target); - entity.face(target); - } else { - entity.getProperties().getCombatPulse().attack(target); - } - return true; + if (entity.getProperties().getCombatPulse().isAttacking()) { + entity.getProperties().getCombatPulse().setVictim(target); + entity.face(target); + } else { + entity.getProperties().getCombatPulse().attack(target); } + return true; } return entity.getProperties().getCombatPulse().isAttacking(); } diff --git a/Server/src/main/kotlin/rs09/game/node/entity/combat/CombatPulse.kt b/Server/src/main/kotlin/rs09/game/node/entity/combat/CombatPulse.kt index b78bb5296..3ba26e7ab 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/combat/CombatPulse.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/combat/CombatPulse.kt @@ -286,7 +286,8 @@ class CombatPulse( victim.skills.updateLevel(Skills.DEFENCE, -drain, victim.skills.getStaticLevel(Skills.DEFENCE) - drain) } } - victim.walkingQueue.reset() + if (!victim.locks.isMovementLocked) + victim.walkingQueue.reset() } setVictim(victim) entity.onAttack(victim as Entity?) diff --git a/Server/src/main/kotlin/rs09/game/node/entity/combat/CombatSwingHandler.kt b/Server/src/main/kotlin/rs09/game/node/entity/combat/CombatSwingHandler.kt index 89487c684..98cc2f513 100644 --- a/Server/src/main/kotlin/rs09/game/node/entity/combat/CombatSwingHandler.kt +++ b/Server/src/main/kotlin/rs09/game/node/entity/combat/CombatSwingHandler.kt @@ -210,6 +210,10 @@ abstract class CombatSwingHandler(var type: CombatStyle?) { * @return `True` if so. */ open fun isAttackable(entity: Entity, victim: Entity): InteractionType? { + if (victim.getAttribute("return-to-spawn", false)) { + return InteractionType.NO_INTERACT + } + if (type == CombatStyle.MELEE) { val stepType = canStepTowards(entity, victim) if (stepType != InteractionType.STILL_INTERACT) return stepType