mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2025-12-09 16:45:44 -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",
|
||||
"defence_level": "100",
|
||||
"safespot": null,
|
||||
"movement_radius": "30",
|
||||
"lifepoints": "150",
|
||||
"strength_level": "100",
|
||||
"id": "2889",
|
||||
|
|
@ -27045,6 +27046,25 @@
|
|||
"range_level": "1",
|
||||
"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",
|
||||
"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
|
||||
public void onImpact(final Entity entity, BattleState state) {
|
||||
updateLifepoints = true;
|
||||
|
|
|
|||
|
|
@ -227,6 +227,7 @@ public final class PestControlActivityPlugin extends ActivityPlugin {
|
|||
PluginManager.definePlugin(new PCShifterNPC());
|
||||
PluginManager.definePlugin(new PCSplatterNPC());
|
||||
PluginManager.definePlugin(new PCSpinnerNPC());
|
||||
PluginManager.definePlugin(new PCBrawlerNPC());
|
||||
PluginManager.definePlugin(new PCObjectHandler());
|
||||
PluginManager.definePlugin(new PestControlSquire());
|
||||
PluginManager.definePlugin(new VoidSealPlugin());
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ public final class VoidSealPlugin extends OptionHandler {
|
|||
* @return {@code True} if so.
|
||||
*/
|
||||
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.InteractionType;
|
||||
import core.game.node.entity.npc.AbstractNPC;
|
||||
import core.game.node.entity.npc.NPC;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.world.map.Location;
|
||||
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
|
||||
public void onImpact(final Entity entity, BattleState 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.combat.BattleState;
|
||||
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.scenery.Scenery;
|
||||
import core.game.node.scenery.SceneryBuilder;
|
||||
|
|
@ -171,6 +172,11 @@ public class PCRavagerNPC extends AbstractNPC {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldPreventStacking(Entity mover) {
|
||||
return mover instanceof NPC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onImpact(final Entity entity, BattleState 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.InteractionType;
|
||||
import core.game.node.entity.npc.AbstractNPC;
|
||||
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;
|
||||
|
|
@ -84,6 +85,11 @@ public final class PCShifterNPC extends AbstractNPC {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldPreventStacking(Entity mover) {
|
||||
return mover instanceof NPC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onImpact(final Entity entity, BattleState 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
|
||||
public void onImpact(final Entity entity, BattleState 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
|
||||
public void onImpact(final Entity entity, BattleState 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.Projectile;
|
||||
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.link.SpellBookManager.SpellBook;
|
||||
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
|
||||
public void onImpact(final Entity entity, BattleState 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
|
||||
public void finalizeDeath(Entity killer) {
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ public final class SpinolypNPC extends AbstractNPC {
|
|||
super.init();
|
||||
super.getLocks().lockMovement(Integer.MAX_VALUE);
|
||||
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.zone.MapZone;
|
||||
import core.game.world.map.zone.ZoneBorders;
|
||||
import core.game.world.map.zone.ZoneBuilder;
|
||||
import core.game.world.map.zone.ZoneRestriction;
|
||||
import rs09.game.world.repository.Repository;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import core.plugin.Initializable;
|
||||
import core.plugin.Plugin;
|
||||
import rs09.plugin.PluginManager;
|
||||
|
||||
|
|
@ -34,6 +36,7 @@ import rs09.plugin.PluginManager;
|
|||
* Handles the waterbirth dungeon zone.
|
||||
* @author Vexia
|
||||
*/
|
||||
@Initializable
|
||||
public final class WaterBirthDungeonZone extends MapZone implements Plugin<Object> {
|
||||
|
||||
/**
|
||||
|
|
@ -54,6 +57,7 @@ public final class WaterBirthDungeonZone extends MapZone implements Plugin<Objec
|
|||
|
||||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
ZoneBuilder.configure(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ public final class WaterBirthIslandZone extends MapZone implements Plugin<Object
|
|||
@Override
|
||||
public Plugin<Object> newInstance(Object arg) throws Throwable {
|
||||
ZoneBuilder.configure(this);
|
||||
ZoneBuilder.configure(new WaterBirthDungeonZone());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -249,6 +249,13 @@ public abstract class Entity extends Node {
|
|||
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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ public abstract class CombatSpell extends MagicSpell {
|
|||
List<Entity> list = new ArrayList<>(20);
|
||||
list.add(target);
|
||||
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) {
|
||||
list.add(e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,10 +123,10 @@ public final class WalkingQueue {
|
|||
walk = walk.transform(point.getDiffX(), point.getDiffY(), 0);
|
||||
if (!entity.getZoneMonitor().move(entity.getLocation(), walk)) {
|
||||
reset();
|
||||
if (entity.getPulseManager().isMovingPulse()) {
|
||||
/*if (entity.getPulseManager().isMovingPulse()) {
|
||||
entity.getPulseManager().clear(); // TODO: Check for
|
||||
// bugs
|
||||
}
|
||||
}*/
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -137,10 +137,10 @@ public final class WalkingQueue {
|
|||
runPoint = null;
|
||||
runDirection = -1;
|
||||
reset();
|
||||
if (entity.getPulseManager().isMovingPulse()) {
|
||||
/*if (entity.getPulseManager().isMovingPulse()) {
|
||||
entity.getPulseManager().clear(); // TODO: Check for
|
||||
// bugs
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
if (runPoint != null) {
|
||||
|
|
|
|||
|
|
@ -63,11 +63,6 @@ public class AggressiveBehavior {
|
|||
*/
|
||||
public boolean canSelectTarget(Entity entity, Entity target) {
|
||||
int regionId = target.getLocation().getRegionId();
|
||||
if(target instanceof Player) {
|
||||
if (RegionManager.forId(regionId).isTolerated(target.asPlayer())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!target.isActive() || DeathTask.isDead(target)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -77,6 +72,9 @@ public class AggressiveBehavior {
|
|||
if (entity instanceof NPC && target instanceof Player) {
|
||||
NPC npc = (NPC) entity;
|
||||
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()];
|
||||
if (ticks > 3000) {
|
||||
npc.getAggressiveHandler().getPlayerTolerance()[target.getIndex()] = GameWorld.getTicks();
|
||||
|
|
@ -86,12 +84,16 @@ public class AggressiveBehavior {
|
|||
}
|
||||
}
|
||||
int level = target.getProperties().getCurrentCombatLevel();
|
||||
if (level > entity.getProperties().getCurrentCombatLevel() << 1) {
|
||||
if (level > entity.getProperties().getCurrentCombatLevel() << 1 && !ignoreCombatLevelDifference()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean ignoreCombatLevelDifference() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the priority flag.
|
||||
* @param target The target.
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ public final class AggressiveHandler {
|
|||
if (target.getAttribute("ignore_aggression", 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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,6 +93,11 @@ public class TormentedDemonNPC extends AbstractNPC {
|
|||
this.setDefaultBehavior();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldPreventStacking(Entity other) {
|
||||
return other instanceof TormentedDemonNPC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleTickActions() {
|
||||
super.handleTickActions();
|
||||
|
|
|
|||
|
|
@ -17,32 +17,34 @@ import core.tools.RandomFunction;
|
|||
*/
|
||||
@Initializable
|
||||
public final class RockCrabNPC extends AbstractNPC {
|
||||
|
||||
/**
|
||||
* The aggresive behavior.
|
||||
*/
|
||||
private static final AggressiveBehavior AGGRO_BEHAVIOR = new AggressiveBehavior() {
|
||||
@Override
|
||||
public boolean canSelectTarget(Entity entity, Entity target) {
|
||||
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());
|
||||
public boolean ignoreCombatLevelDifference() {
|
||||
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.
|
||||
|
|
@ -71,9 +73,10 @@ public final class RockCrabNPC extends AbstractNPC {
|
|||
@Override
|
||||
public void handleTickActions() {
|
||||
super.handleTickActions();
|
||||
if (aggresor && !inCombat() && target.getLocation().getDistance(this.getLocation()) > 12) {
|
||||
if ((aggressor && !inCombat() && target.getLocation().getDistance(this.getLocation()) > 12) || isInvisible()) {
|
||||
reTransform();
|
||||
aggresor = false;
|
||||
aggressor = false;
|
||||
target = null;
|
||||
getWalkingQueue().reset();
|
||||
setWalks(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -541,6 +541,9 @@ object RegionManager {
|
|||
val it = players.iterator()
|
||||
while (it.hasNext()) {
|
||||
val p = it.next()
|
||||
if(p.isInvisible()) {
|
||||
it.remove()
|
||||
}
|
||||
if(!p.location.withinMaxnormDistance(n.location, 1)) {
|
||||
it.remove()
|
||||
continue
|
||||
|
|
@ -584,6 +587,9 @@ object RegionManager {
|
|||
val it = npcs.iterator()
|
||||
while (it.hasNext()) {
|
||||
val p = it.next()
|
||||
if(p.isInvisible()) {
|
||||
it.remove()
|
||||
}
|
||||
if(!p.location.withinMaxnormDistance(n.location, 1)) {
|
||||
it.remove()
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import core.game.world.map.Direction;
|
|||
import core.game.world.map.Location;
|
||||
import core.game.world.map.MapDistance;
|
||||
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.ZoneBorders;
|
||||
import core.net.packet.PacketRepository;
|
||||
|
|
@ -122,35 +123,17 @@ public final class MultiwayCombatZone extends MapZone {
|
|||
if (e.getProperties().isNPCWalkable()) {
|
||||
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)) {
|
||||
if (n.isInvisible() || !n.getDefinition().hasAttackOption() || n == e) {
|
||||
continue;
|
||||
}
|
||||
if (player && pestControl && !(n.getId() >= 3772 && n.getId() <= 3776)) {
|
||||
continue;
|
||||
}
|
||||
Location l = n.getLocation();
|
||||
// TODO: Better support for sizes.
|
||||
int s = n.size() - 1;
|
||||
if(n.shouldPreventStacking(e)) {
|
||||
int s1 = e.size();
|
||||
int s2 = n.size();
|
||||
int x = destination.getX();
|
||||
int y = destination.getY();
|
||||
if (x > l.getX()) {
|
||||
x += e.size() - 1;
|
||||
}
|
||||
if (y > l.getY()) {
|
||||
y += e.size() - 1;
|
||||
}
|
||||
if (l.getX() <= x && l.getY() <= y && (l.getX() + s) >= x && (l.getY() + s) >= y) {
|
||||
Location l = n.getLocation();
|
||||
if(Pathfinder.isStandingIn(x, y, s1, s1, l.getX(), l.getY(), s2, s2)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -473,6 +473,18 @@ class MiscCommandSet : CommandSet(Command.Privilege.ADMIN){
|
|||
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){
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue