mirror of
https://gitlab.com/2009scape/2009scape.git
synced 2026-08-24 11:55:13 -06:00
Cats on bridges, no more infinite familiar call loops
This commit is contained in:
parent
5a37f2f8da
commit
8f855105b9
3 changed files with 54 additions and 5 deletions
|
|
@ -115,6 +115,14 @@ public final class HouseZone extends MapZone {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Take the player's familiar along before the teardown pulse below wipes every NPC
|
||||
// still left inside the house - a wiped familiar is gone until relog (GL #2313). The
|
||||
// call either materializes it at the destination or parks it invisibly at the owner's
|
||||
// side until there is room for it.
|
||||
if (!logout && p.getFamiliarManager().hasFamiliar()) {
|
||||
p.getFamiliarManager().getFamiliar().call();
|
||||
}
|
||||
|
||||
remove_items(p);
|
||||
// The below tears down the house if the owner was the one who left
|
||||
|
|
|
|||
|
|
@ -391,10 +391,17 @@ public abstract class Familiar extends NPC implements Plugin<Object> {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onRegionInactivity() {
|
||||
call();
|
||||
// NPC.tick() short-circuits into this method while the region is inactive, so Entity.tick()
|
||||
// never runs to consume a teleport that call() just set; apply it manually here or the
|
||||
// familiar re-calls forever without ever moving (GL #2313).
|
||||
if (getProperties().getTeleportLocation() != null && owner.isActive()) {
|
||||
getWalkingQueue().update();
|
||||
getUpdateMasks().prepare(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -699,10 +706,20 @@ public abstract class Familiar extends NPC implements Plugin<Object> {
|
|||
//owner.getPacketDispatch().sendMessage("Your familiar is too big to fit here. Try calling it again when you are standing");
|
||||
//owner.getPacketDispatch().sendMessage("somewhere with more space.");
|
||||
//spamTimer = 50;
|
||||
// No room to materialize, so wait invisibly at the owner's side (like init() does when
|
||||
// there is no room at summon time). Waiting in place instead means being left behind:
|
||||
// once the abandoned region unloads, the familiar either gets wiped with it
|
||||
// (DynamicRegion teardown) or gets stuck endlessly re-calling from an inactive region
|
||||
// that no longer ticks it normally (GL #2313).
|
||||
setInvisible(true);
|
||||
stayWithOwner();
|
||||
return false;
|
||||
}
|
||||
setInvisible(owner.getZoneMonitor().isRestricted(ZoneRestriction.FOLLOWERS) && !owner.getLocks().isLocked("enable_summoning"));
|
||||
if (isInvisible()) return true;
|
||||
if (isInvisible()) {
|
||||
stayWithOwner();
|
||||
return true;
|
||||
}
|
||||
getProperties().setTeleportLocation(destination);
|
||||
if (!(this instanceof Pet)) {
|
||||
if (firstCall) {
|
||||
|
|
@ -723,13 +740,33 @@ public abstract class Familiar extends NPC implements Plugin<Object> {
|
|||
} else {
|
||||
face(owner);
|
||||
}
|
||||
if (!isRenderable() && owner.isActive()) {
|
||||
// A familiar pulled in from another region must move immediately rather than on its next
|
||||
// tick: NPCs tick before players, so when this call runs from the owner's movement (e.g.
|
||||
// leaving a POH), the familiar's tick for this cycle has already passed - and a region
|
||||
// teardown pulse (POH exit portal, building-mode rebuild) runs at the start of the next
|
||||
// cycle, wiping any NPC still inside before it can consume a pending teleport (GL #2313).
|
||||
boolean leftInAnotherRegion = getLocation().getRegionId() != owner.getLocation().getRegionId();
|
||||
if ((!isRenderable() || leftInAnotherRegion) && owner.isActive()) {
|
||||
// log(this.getClass(), Log.ERR, "Familiar in inactive region!");
|
||||
getWalkingQueue().update();
|
||||
getUpdateMasks().prepare(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves a familiar that cannot materialize to its owner's location, so it is never left
|
||||
* behind in a region that may unload. The teleport is applied immediately because this can
|
||||
* run from an inactive region, where Entity.tick() (the normal consumer) no longer runs.
|
||||
*/
|
||||
private void stayWithOwner() {
|
||||
if (!owner.isActive() || getLocation().equals(owner.getLocation())) {
|
||||
return;
|
||||
}
|
||||
getProperties().setTeleportLocation(owner.getLocation());
|
||||
getWalkingQueue().update();
|
||||
getUpdateMasks().prepare(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the spawning location of the familiar.
|
||||
|
|
|
|||
|
|
@ -332,10 +332,14 @@ object RegionManager {
|
|||
}
|
||||
}
|
||||
val l = owner.location.transform(stepX, stepY, 0)
|
||||
// Check if ALL target tiles are unclipped
|
||||
// Check if the NPC can stand on ALL target tiles. This must not use isClipped(),
|
||||
// which rejects any tile that has a wall along ANY of its sides: every tile of a
|
||||
// railed bridge deck has one (e.g. the whole Lumbridge bridge), which made familiars
|
||||
// and pets unable to materialize anywhere on it (GL #1471). Materializing is the
|
||||
// same question as teleporting, so ask the teleport predicate.
|
||||
for (x in 0 until node.size()) {
|
||||
for (y in 0 until node.size()) {
|
||||
if (isClipped(l.transform(x, y, 0))) {
|
||||
if (!isTeleportPermitted(l.transform(x, y, 0))) {
|
||||
continue@outer
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue