mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2025-12-10 10:20:41 -07:00
Merge branch 'aggro-fixes' into 'master'
Fixes to NPC stacking and aggression: See merge request 2009scape/2009scape!321
This commit is contained in:
commit
370636b96b
27 changed files with 259 additions and 82 deletions
|
|
@ -27038,6 +27038,7 @@
|
||||||
"name": "Rock lobster",
|
"name": "Rock lobster",
|
||||||
"defence_level": "100",
|
"defence_level": "100",
|
||||||
"safespot": null,
|
"safespot": null,
|
||||||
|
"movement_radius": "30",
|
||||||
"lifepoints": "150",
|
"lifepoints": "150",
|
||||||
"strength_level": "100",
|
"strength_level": "100",
|
||||||
"id": "2889",
|
"id": "2889",
|
||||||
|
|
@ -27045,6 +27046,25 @@
|
||||||
"range_level": "1",
|
"range_level": "1",
|
||||||
"attack_level": "100"
|
"attack_level": "100"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"examine": "A Rock.",
|
||||||
|
"melee_animation": "2860",
|
||||||
|
"range_animation": "2860",
|
||||||
|
"attack_speed": "2",
|
||||||
|
"defence_animation": "2861",
|
||||||
|
"weakness": "7",
|
||||||
|
"magic_animation": "2860",
|
||||||
|
"death_animation": "2861",
|
||||||
|
"name": "Large rock",
|
||||||
|
"defence_level": "100",
|
||||||
|
"safespot": null,
|
||||||
|
"lifepoints": "150",
|
||||||
|
"strength_level": "100",
|
||||||
|
"id": "2890",
|
||||||
|
"aggressive": "true",
|
||||||
|
"range_level": "1",
|
||||||
|
"attack_level": "100"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"agg_radius": "12",
|
"agg_radius": "12",
|
||||||
"examine": "A sneaky, spiny, subterranean sea-dwelling scamp.",
|
"examine": "A sneaky, spiny, subterranean sea-dwelling scamp.",
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,11 @@ public final class PCPortalNPC extends AbstractNPC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldPreventStacking(Entity mover) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onImpact(final Entity entity, BattleState state) {
|
public void onImpact(final Entity entity, BattleState state) {
|
||||||
updateLifepoints = true;
|
updateLifepoints = true;
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,7 @@ public final class PestControlActivityPlugin extends ActivityPlugin {
|
||||||
PluginManager.definePlugin(new PCShifterNPC());
|
PluginManager.definePlugin(new PCShifterNPC());
|
||||||
PluginManager.definePlugin(new PCSplatterNPC());
|
PluginManager.definePlugin(new PCSplatterNPC());
|
||||||
PluginManager.definePlugin(new PCSpinnerNPC());
|
PluginManager.definePlugin(new PCSpinnerNPC());
|
||||||
|
PluginManager.definePlugin(new PCBrawlerNPC());
|
||||||
PluginManager.definePlugin(new PCObjectHandler());
|
PluginManager.definePlugin(new PCObjectHandler());
|
||||||
PluginManager.definePlugin(new PestControlSquire());
|
PluginManager.definePlugin(new PestControlSquire());
|
||||||
PluginManager.definePlugin(new VoidSealPlugin());
|
PluginManager.definePlugin(new VoidSealPlugin());
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ public final class VoidSealPlugin extends OptionHandler {
|
||||||
* @return {@code True} if so.
|
* @return {@code True} if so.
|
||||||
*/
|
*/
|
||||||
private static boolean canTarget(NPC npc) {
|
private static boolean canTarget(NPC npc) {
|
||||||
return npc instanceof PCDefilerNPC || npc instanceof PCRavagerNPC || npc instanceof PCShifterNPC || npc instanceof PCSpinnerNPC || npc instanceof PCSplatterNPC || npc instanceof PCTorcherNPC;
|
return npc instanceof PCDefilerNPC || npc instanceof PCRavagerNPC || npc instanceof PCShifterNPC || npc instanceof PCSpinnerNPC || npc instanceof PCSplatterNPC || npc instanceof PCTorcherNPC || npc instanceof PCBrawlerNPC;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
package core.game.content.activity.pestcontrol.monsters;
|
||||||
|
|
||||||
|
import core.game.content.activity.pestcontrol.PestControlSession;
|
||||||
|
import core.game.node.entity.Entity;
|
||||||
|
import core.game.node.entity.combat.BattleState;
|
||||||
|
import core.game.node.entity.combat.CombatStyle;
|
||||||
|
import core.game.node.entity.combat.InteractionType;
|
||||||
|
import core.game.node.entity.npc.AbstractNPC;
|
||||||
|
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.Animation;
|
||||||
|
import core.game.world.update.flag.context.Graphics;
|
||||||
|
import core.tools.RandomFunction;
|
||||||
|
import rs09.game.node.entity.combat.CombatPulse;
|
||||||
|
import rs09.game.node.entity.combat.CombatSwingHandler;
|
||||||
|
import rs09.game.node.entity.combat.handlers.MeleeSwingHandler;
|
||||||
|
import rs09.game.world.GameWorld;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the pest control brawler NPCs.
|
||||||
|
* @author Emperor
|
||||||
|
*/
|
||||||
|
public final class PCBrawlerNPC extends AbstractNPC {
|
||||||
|
/**
|
||||||
|
* The pest control session.
|
||||||
|
*/
|
||||||
|
private PestControlSession session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new {@code PCBrawlerNPC} {@code Object}.
|
||||||
|
*/
|
||||||
|
public PCBrawlerNPC() {
|
||||||
|
super(3772, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new {@code PCBrawlerNPC} {@code Object}.
|
||||||
|
* @param id The NPC id.
|
||||||
|
* @param location The location.
|
||||||
|
*/
|
||||||
|
public PCBrawlerNPC(int id, Location location) {
|
||||||
|
super(id, location);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
super.setAggressive(true);
|
||||||
|
super.init();
|
||||||
|
super.getDefinition().setCombatDistance(1);
|
||||||
|
super.walkRadius = 64;
|
||||||
|
getProperties().getCombatPulse().setStyle(CombatStyle.MELEE);
|
||||||
|
session = getExtension(PestControlSession.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldPreventStacking(Entity mover) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onImpact(final Entity entity, BattleState state) {
|
||||||
|
super.onImpact(entity, state);
|
||||||
|
if (session != null && state != null && entity instanceof Player) {
|
||||||
|
int total = 0;
|
||||||
|
if (state.getEstimatedHit() > 0) {
|
||||||
|
total += state.getEstimatedHit();
|
||||||
|
}
|
||||||
|
if (state.getSecondaryHit() > 0) {
|
||||||
|
total += state.getSecondaryHit();
|
||||||
|
}
|
||||||
|
session.addZealGained((Player) entity, total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractNPC construct(int id, Location location, Object... objects) {
|
||||||
|
return new PCBrawlerNPC(id, location);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] getIds() {
|
||||||
|
return new int[] { 3772, 3773, 3774, 3775, 3776 };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ import core.game.node.entity.combat.BattleState;
|
||||||
import core.game.node.entity.combat.CombatStyle;
|
import core.game.node.entity.combat.CombatStyle;
|
||||||
import core.game.node.entity.combat.InteractionType;
|
import core.game.node.entity.combat.InteractionType;
|
||||||
import core.game.node.entity.npc.AbstractNPC;
|
import core.game.node.entity.npc.AbstractNPC;
|
||||||
|
import core.game.node.entity.npc.NPC;
|
||||||
import core.game.node.entity.player.Player;
|
import core.game.node.entity.player.Player;
|
||||||
import core.game.world.map.Location;
|
import core.game.world.map.Location;
|
||||||
import core.game.world.map.MapDistance;
|
import core.game.world.map.MapDistance;
|
||||||
|
|
@ -77,6 +78,11 @@ public final class PCDefilerNPC extends AbstractNPC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldPreventStacking(Entity mover) {
|
||||||
|
return mover instanceof NPC;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onImpact(final Entity entity, BattleState state) {
|
public void onImpact(final Entity entity, BattleState state) {
|
||||||
super.onImpact(entity, state);
|
super.onImpact(entity, state);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import core.game.node.Node;
|
||||||
import core.game.node.entity.Entity;
|
import core.game.node.entity.Entity;
|
||||||
import core.game.node.entity.combat.BattleState;
|
import core.game.node.entity.combat.BattleState;
|
||||||
import core.game.node.entity.npc.AbstractNPC;
|
import core.game.node.entity.npc.AbstractNPC;
|
||||||
|
import core.game.node.entity.npc.NPC;
|
||||||
import core.game.node.entity.player.Player;
|
import core.game.node.entity.player.Player;
|
||||||
import core.game.node.scenery.Scenery;
|
import core.game.node.scenery.Scenery;
|
||||||
import core.game.node.scenery.SceneryBuilder;
|
import core.game.node.scenery.SceneryBuilder;
|
||||||
|
|
@ -171,6 +172,11 @@ public class PCRavagerNPC extends AbstractNPC {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldPreventStacking(Entity mover) {
|
||||||
|
return mover instanceof NPC;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onImpact(final Entity entity, BattleState state) {
|
public void onImpact(final Entity entity, BattleState state) {
|
||||||
super.onImpact(entity, state);
|
super.onImpact(entity, state);
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import core.game.node.entity.combat.BattleState;
|
||||||
import core.game.node.entity.combat.CombatStyle;
|
import core.game.node.entity.combat.CombatStyle;
|
||||||
import core.game.node.entity.combat.InteractionType;
|
import core.game.node.entity.combat.InteractionType;
|
||||||
import core.game.node.entity.npc.AbstractNPC;
|
import core.game.node.entity.npc.AbstractNPC;
|
||||||
|
import core.game.node.entity.npc.NPC;
|
||||||
import core.game.node.entity.player.Player;
|
import core.game.node.entity.player.Player;
|
||||||
import core.game.system.task.Pulse;
|
import core.game.system.task.Pulse;
|
||||||
import core.game.world.map.Location;
|
import core.game.world.map.Location;
|
||||||
|
|
@ -84,6 +85,11 @@ public final class PCShifterNPC extends AbstractNPC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldPreventStacking(Entity mover) {
|
||||||
|
return mover instanceof NPC;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onImpact(final Entity entity, BattleState state) {
|
public void onImpact(final Entity entity, BattleState state) {
|
||||||
super.onImpact(entity, state);
|
super.onImpact(entity, state);
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,11 @@ public final class PCSpinnerNPC extends AbstractNPC {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldPreventStacking(Entity mover) {
|
||||||
|
return mover instanceof NPC;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onImpact(final Entity entity, BattleState state) {
|
public void onImpact(final Entity entity, BattleState state) {
|
||||||
super.onImpact(entity, state);
|
super.onImpact(entity, state);
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,11 @@ public final class PCSplatterNPC extends AbstractNPC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldPreventStacking(Entity mover) {
|
||||||
|
return mover instanceof NPC;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onImpact(final Entity entity, BattleState state) {
|
public void onImpact(final Entity entity, BattleState state) {
|
||||||
super.onImpact(entity, state);
|
super.onImpact(entity, state);
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import core.game.node.entity.combat.equipment.SpellType;
|
||||||
import core.game.node.entity.impl.Animator.Priority;
|
import core.game.node.entity.impl.Animator.Priority;
|
||||||
import core.game.node.entity.impl.Projectile;
|
import core.game.node.entity.impl.Projectile;
|
||||||
import core.game.node.entity.npc.AbstractNPC;
|
import core.game.node.entity.npc.AbstractNPC;
|
||||||
|
import core.game.node.entity.npc.NPC;
|
||||||
import core.game.node.entity.player.Player;
|
import core.game.node.entity.player.Player;
|
||||||
import core.game.node.entity.player.link.SpellBookManager.SpellBook;
|
import core.game.node.entity.player.link.SpellBookManager.SpellBook;
|
||||||
import core.game.world.map.Location;
|
import core.game.world.map.Location;
|
||||||
|
|
@ -91,6 +92,11 @@ public final class PCTorcherNPC extends AbstractNPC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldPreventStacking(Entity mover) {
|
||||||
|
return mover instanceof NPC;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onImpact(final Entity entity, BattleState state) {
|
public void onImpact(final Entity entity, BattleState state) {
|
||||||
super.onImpact(entity, state);
|
super.onImpact(entity, state);
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,10 @@ public final class TzhaarFightCaveNPC extends AbstractNPC {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public boolean shouldPreventStacking(Entity mover) {
|
||||||
|
return mover instanceof TzhaarFightCaveNPC;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void finalizeDeath(Entity killer) {
|
public void finalizeDeath(Entity killer) {
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ public final class SpinolypNPC extends AbstractNPC {
|
||||||
super.init();
|
super.init();
|
||||||
super.getLocks().lockMovement(Integer.MAX_VALUE);
|
super.getLocks().lockMovement(Integer.MAX_VALUE);
|
||||||
setSpell();
|
setSpell();
|
||||||
|
getAggressiveHandler().setAllowTolerance(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,11 @@ import core.game.world.map.Location;
|
||||||
import core.game.world.map.RegionManager;
|
import core.game.world.map.RegionManager;
|
||||||
import core.game.world.map.zone.MapZone;
|
import core.game.world.map.zone.MapZone;
|
||||||
import core.game.world.map.zone.ZoneBorders;
|
import core.game.world.map.zone.ZoneBorders;
|
||||||
|
import core.game.world.map.zone.ZoneBuilder;
|
||||||
import core.game.world.map.zone.ZoneRestriction;
|
import core.game.world.map.zone.ZoneRestriction;
|
||||||
import rs09.game.world.repository.Repository;
|
import rs09.game.world.repository.Repository;
|
||||||
import core.game.world.update.flag.context.Animation;
|
import core.game.world.update.flag.context.Animation;
|
||||||
|
import core.plugin.Initializable;
|
||||||
import core.plugin.Plugin;
|
import core.plugin.Plugin;
|
||||||
import rs09.plugin.PluginManager;
|
import rs09.plugin.PluginManager;
|
||||||
|
|
||||||
|
|
@ -34,6 +36,7 @@ import rs09.plugin.PluginManager;
|
||||||
* Handles the waterbirth dungeon zone.
|
* Handles the waterbirth dungeon zone.
|
||||||
* @author Vexia
|
* @author Vexia
|
||||||
*/
|
*/
|
||||||
|
@Initializable
|
||||||
public final class WaterBirthDungeonZone extends MapZone implements Plugin<Object> {
|
public final class WaterBirthDungeonZone extends MapZone implements Plugin<Object> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -54,6 +57,7 @@ public final class WaterBirthDungeonZone extends MapZone implements Plugin<Objec
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||||
|
ZoneBuilder.configure(this);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,6 @@ public final class WaterBirthIslandZone extends MapZone implements Plugin<Object
|
||||||
@Override
|
@Override
|
||||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||||
ZoneBuilder.configure(this);
|
ZoneBuilder.configure(this);
|
||||||
ZoneBuilder.configure(new WaterBirthDungeonZone());
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -249,6 +249,13 @@ public abstract class Entity extends Node {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should this entity prevent the mover from moving through it?
|
||||||
|
*/
|
||||||
|
public boolean shouldPreventStacking(Entity mover) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks an impact before receiving it.
|
* Checks an impact before receiving it.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ public abstract class CombatSpell extends MagicSpell {
|
||||||
List<Entity> list = new ArrayList<>(20);
|
List<Entity> list = new ArrayList<>(20);
|
||||||
list.add(target);
|
list.add(target);
|
||||||
boolean npc = target instanceof NPC;
|
boolean npc = target instanceof NPC;
|
||||||
for (Entity e : npc ? RegionManager.getLocalNpcs(target, 1) : RegionManager.getLocalPlayers(target, 1)) {
|
for (Entity e : npc ? RegionManager.getSurroundingNPCs(target) : RegionManager.getSurroundingPlayers(target)) {
|
||||||
if (e != target && e != entity && CombatStyle.MAGIC.getSwingHandler().canSwing(entity, e) != InteractionType.NO_INTERACT) {
|
if (e != target && e != entity && CombatStyle.MAGIC.getSwingHandler().canSwing(entity, e) != InteractionType.NO_INTERACT) {
|
||||||
list.add(e);
|
list.add(e);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -123,10 +123,10 @@ public final class WalkingQueue {
|
||||||
walk = walk.transform(point.getDiffX(), point.getDiffY(), 0);
|
walk = walk.transform(point.getDiffX(), point.getDiffY(), 0);
|
||||||
if (!entity.getZoneMonitor().move(entity.getLocation(), walk)) {
|
if (!entity.getZoneMonitor().move(entity.getLocation(), walk)) {
|
||||||
reset();
|
reset();
|
||||||
if (entity.getPulseManager().isMovingPulse()) {
|
/*if (entity.getPulseManager().isMovingPulse()) {
|
||||||
entity.getPulseManager().clear(); // TODO: Check for
|
entity.getPulseManager().clear(); // TODO: Check for
|
||||||
// bugs
|
// bugs
|
||||||
}
|
}*/
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -137,10 +137,10 @@ public final class WalkingQueue {
|
||||||
runPoint = null;
|
runPoint = null;
|
||||||
runDirection = -1;
|
runDirection = -1;
|
||||||
reset();
|
reset();
|
||||||
if (entity.getPulseManager().isMovingPulse()) {
|
/*if (entity.getPulseManager().isMovingPulse()) {
|
||||||
entity.getPulseManager().clear(); // TODO: Check for
|
entity.getPulseManager().clear(); // TODO: Check for
|
||||||
// bugs
|
// bugs
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (runPoint != null) {
|
if (runPoint != null) {
|
||||||
|
|
|
||||||
|
|
@ -63,11 +63,6 @@ public class AggressiveBehavior {
|
||||||
*/
|
*/
|
||||||
public boolean canSelectTarget(Entity entity, Entity target) {
|
public boolean canSelectTarget(Entity entity, Entity target) {
|
||||||
int regionId = target.getLocation().getRegionId();
|
int regionId = target.getLocation().getRegionId();
|
||||||
if(target instanceof Player) {
|
|
||||||
if (RegionManager.forId(regionId).isTolerated(target.asPlayer())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!target.isActive() || DeathTask.isDead(target)) {
|
if (!target.isActive() || DeathTask.isDead(target)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -77,6 +72,9 @@ public class AggressiveBehavior {
|
||||||
if (entity instanceof NPC && target instanceof Player) {
|
if (entity instanceof NPC && target instanceof Player) {
|
||||||
NPC npc = (NPC) entity;
|
NPC npc = (NPC) entity;
|
||||||
if (npc.getAggressiveHandler() != null && npc.getAggressiveHandler().isAllowTolerance()) {
|
if (npc.getAggressiveHandler() != null && npc.getAggressiveHandler().isAllowTolerance()) {
|
||||||
|
if (RegionManager.forId(regionId).isTolerated(target.asPlayer())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
int ticks = GameWorld.getTicks() - npc.getAggressiveHandler().getPlayerTolerance()[target.getIndex()];
|
int ticks = GameWorld.getTicks() - npc.getAggressiveHandler().getPlayerTolerance()[target.getIndex()];
|
||||||
if (ticks > 3000) {
|
if (ticks > 3000) {
|
||||||
npc.getAggressiveHandler().getPlayerTolerance()[target.getIndex()] = GameWorld.getTicks();
|
npc.getAggressiveHandler().getPlayerTolerance()[target.getIndex()] = GameWorld.getTicks();
|
||||||
|
|
@ -86,12 +84,16 @@ public class AggressiveBehavior {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int level = target.getProperties().getCurrentCombatLevel();
|
int level = target.getProperties().getCurrentCombatLevel();
|
||||||
if (level > entity.getProperties().getCurrentCombatLevel() << 1) {
|
if (level > entity.getProperties().getCurrentCombatLevel() << 1 && !ignoreCombatLevelDifference()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean ignoreCombatLevelDifference() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the priority flag.
|
* Gets the priority flag.
|
||||||
* @param target The target.
|
* @param target The target.
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ public final class AggressiveHandler {
|
||||||
if (target.getAttribute("ignore_aggression", false)) {
|
if (target.getAttribute("ignore_aggression", false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (((Player) target).getRights().equals(Rights.ADMINISTRATOR)) {
|
if (((Player) target).getRights().equals(Rights.ADMINISTRATOR) && !target.getAttribute("allow_admin_aggression", false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,11 @@ public class TormentedDemonNPC extends AbstractNPC {
|
||||||
this.setDefaultBehavior();
|
this.setDefaultBehavior();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean shouldPreventStacking(Entity other) {
|
||||||
|
return other instanceof TormentedDemonNPC;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleTickActions() {
|
public void handleTickActions() {
|
||||||
super.handleTickActions();
|
super.handleTickActions();
|
||||||
|
|
|
||||||
|
|
@ -17,32 +17,34 @@ import core.tools.RandomFunction;
|
||||||
*/
|
*/
|
||||||
@Initializable
|
@Initializable
|
||||||
public final class RockCrabNPC extends AbstractNPC {
|
public final class RockCrabNPC extends AbstractNPC {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The aggresive behavior.
|
* The aggresive behavior.
|
||||||
*/
|
*/
|
||||||
private static final AggressiveBehavior AGGRO_BEHAVIOR = new AggressiveBehavior() {
|
private static final AggressiveBehavior AGGRO_BEHAVIOR = new AggressiveBehavior() {
|
||||||
@Override
|
@Override
|
||||||
public boolean canSelectTarget(Entity entity, Entity target) {
|
public boolean ignoreCombatLevelDifference() {
|
||||||
int regionId = target.getLocation().getRegionId();
|
|
||||||
if(target instanceof Player){
|
|
||||||
if(RegionManager.forId(regionId).isTolerated(target.asPlayer())) return false;
|
|
||||||
}
|
|
||||||
RockCrabNPC npc = (RockCrabNPC) entity;
|
|
||||||
if (entity.getLocation().withinDistance(target.getLocation(), 3)) {
|
|
||||||
npc.aggresor = true;
|
|
||||||
npc.target = target;
|
|
||||||
npc.transform(npc.getTransformId());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return super.canSelectTarget(entity, target);
|
@Override
|
||||||
|
public boolean canSelectTarget(Entity entity, Entity target) {
|
||||||
|
return super.canSelectTarget(entity, target) &&
|
||||||
|
entity.getLocation().withinDistance(target.getLocation(), 3);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttack(Entity target) {
|
||||||
|
this.aggressor = true;
|
||||||
|
this.target = target;
|
||||||
|
if(getId() == getOriginalId()) {
|
||||||
|
this.transform(getOriginalId() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If currently an aggresor.
|
* If currently an aggressor.
|
||||||
*/
|
*/
|
||||||
private boolean aggresor;
|
private boolean aggressor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The target.
|
* The target.
|
||||||
|
|
@ -71,9 +73,10 @@ public final class RockCrabNPC extends AbstractNPC {
|
||||||
@Override
|
@Override
|
||||||
public void handleTickActions() {
|
public void handleTickActions() {
|
||||||
super.handleTickActions();
|
super.handleTickActions();
|
||||||
if (aggresor && !inCombat() && target.getLocation().getDistance(this.getLocation()) > 12) {
|
if ((aggressor && !inCombat() && target.getLocation().getDistance(this.getLocation()) > 12) || isInvisible()) {
|
||||||
reTransform();
|
reTransform();
|
||||||
aggresor = false;
|
aggressor = false;
|
||||||
|
target = null;
|
||||||
getWalkingQueue().reset();
|
getWalkingQueue().reset();
|
||||||
setWalks(false);
|
setWalks(false);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -541,6 +541,9 @@ object RegionManager {
|
||||||
val it = players.iterator()
|
val it = players.iterator()
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
val p = it.next()
|
val p = it.next()
|
||||||
|
if(p.isInvisible()) {
|
||||||
|
it.remove()
|
||||||
|
}
|
||||||
if(!p.location.withinMaxnormDistance(n.location, 1)) {
|
if(!p.location.withinMaxnormDistance(n.location, 1)) {
|
||||||
it.remove()
|
it.remove()
|
||||||
continue
|
continue
|
||||||
|
|
@ -584,6 +587,9 @@ object RegionManager {
|
||||||
val it = npcs.iterator()
|
val it = npcs.iterator()
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
val p = it.next()
|
val p = it.next()
|
||||||
|
if(p.isInvisible()) {
|
||||||
|
it.remove()
|
||||||
|
}
|
||||||
if(!p.location.withinMaxnormDistance(n.location, 1)) {
|
if(!p.location.withinMaxnormDistance(n.location, 1)) {
|
||||||
it.remove()
|
it.remove()
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import core.game.world.map.Direction;
|
||||||
import core.game.world.map.Location;
|
import core.game.world.map.Location;
|
||||||
import core.game.world.map.MapDistance;
|
import core.game.world.map.MapDistance;
|
||||||
import core.game.world.map.RegionManager;
|
import core.game.world.map.RegionManager;
|
||||||
|
import core.game.world.map.path.Pathfinder;
|
||||||
import core.game.world.map.zone.MapZone;
|
import core.game.world.map.zone.MapZone;
|
||||||
import core.game.world.map.zone.ZoneBorders;
|
import core.game.world.map.zone.ZoneBorders;
|
||||||
import core.net.packet.PacketRepository;
|
import core.net.packet.PacketRepository;
|
||||||
|
|
@ -122,35 +123,17 @@ public final class MultiwayCombatZone extends MapZone {
|
||||||
if (e.getProperties().isNPCWalkable()) {
|
if (e.getProperties().isNPCWalkable()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
boolean pestControl = e.getViewport().getRegion().getRegionId() == 10536;
|
|
||||||
boolean player = e instanceof Player;
|
|
||||||
if (!player) {
|
|
||||||
Direction dir = Direction.getDirection(loc, destination);
|
|
||||||
if (dir.getStepX() != 0 && dir.getStepY() != 0) {
|
|
||||||
return true; // Allow diagonal steps so people can still "stack"
|
|
||||||
// npcs (see barraging mummies)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (e instanceof NPC || pestControl) {
|
|
||||||
for (NPC n : RegionManager.getLocalNpcs(e, MapDistance.RENDERING.getDistance() / 2)) {
|
for (NPC n : RegionManager.getLocalNpcs(e, MapDistance.RENDERING.getDistance() / 2)) {
|
||||||
if (n.isInvisible() || !n.getDefinition().hasAttackOption() || n == e) {
|
if (n.isInvisible() || !n.getDefinition().hasAttackOption() || n == e) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (player && pestControl && !(n.getId() >= 3772 && n.getId() <= 3776)) {
|
if(n.shouldPreventStacking(e)) {
|
||||||
continue;
|
int s1 = e.size();
|
||||||
}
|
int s2 = n.size();
|
||||||
Location l = n.getLocation();
|
|
||||||
// TODO: Better support for sizes.
|
|
||||||
int s = n.size() - 1;
|
|
||||||
int x = destination.getX();
|
int x = destination.getX();
|
||||||
int y = destination.getY();
|
int y = destination.getY();
|
||||||
if (x > l.getX()) {
|
Location l = n.getLocation();
|
||||||
x += e.size() - 1;
|
if(Pathfinder.isStandingIn(x, y, s1, s1, l.getX(), l.getY(), s2, s2)) {
|
||||||
}
|
|
||||||
if (y > l.getY()) {
|
|
||||||
y += e.size() - 1;
|
|
||||||
}
|
|
||||||
if (l.getX() <= x && l.getY() <= y && (l.getX() + s) >= x && (l.getY() + s) >= y) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -473,6 +473,18 @@ class MiscCommandSet : CommandSet(Command.Privilege.ADMIN){
|
||||||
else -> reject(player, usageStr)
|
else -> reject(player, usageStr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
define("allow_aggro", Command.Privilege.ADMIN) { player, args ->
|
||||||
|
val usageStr = "Usage: ::allow_aggro true | false"
|
||||||
|
if(args.size < 2) {
|
||||||
|
reject(player, usageStr)
|
||||||
|
}
|
||||||
|
when(args[1]) {
|
||||||
|
"true" -> player.setAttribute("allow_admin_aggression", true)
|
||||||
|
"false" -> player.removeAttribute("allow_admin_aggression")
|
||||||
|
else -> reject(player, usageStr)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showGeSell(player: Player){
|
fun showGeSell(player: Player){
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue