Skip to content

Commit

Permalink
fix(skymp5-client): handle actors that ignore Disable & more (skyrim-…
Browse files Browse the repository at this point in the history
  • Loading branch information
Pospelove authored Mar 24, 2024
1 parent 3782082 commit 816987c
Showing 1 changed file with 41 additions and 6 deletions.
47 changes: 41 additions & 6 deletions skymp5-client/src/services/services/worldCleanerService.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,41 @@
import { Game, Actor } from "skyrimPlatform";
import { ClientListener, CombinedController, Sp } from "./clientListener";
import { NiPoint3 } from "../../sync/movement";
import { ObjectReferenceEx } from "../../extensions/objectReferenceEx";
import { Actor } from "skyrimPlatform";

export class WorldCleanerService extends ClientListener {
constructor(private sp: Sp, private controller: CombinedController) {
super();
this.controller.on("update", () => this.onUpdate());
this.controller.emitter.on("gameLoad", () => this.onGameLoad());
}

modWcProtection(actorId: number, mod: number): void {
const currentProtection = this.protection.get(actorId);
this.protection.set(actorId, currentProtection ? currentProtection + mod : mod);
}

getWcProtection(actorId: number): number {
return this.protection.get(actorId) || 0;
}

private onGameLoad() {
let player = this.sp.Game.getPlayer();
if (!player) return;

this.initialPos = ObjectReferenceEx.getPos(player);
this.initialCellOrWorld = ObjectReferenceEx.getWorldOrCell(player);
}

private onUpdate() {
this.processOneActor();
}

private processOneActor() {
const pc = Game.getPlayer();
const pc = this.sp.Game.getPlayer();
if (pc === null) return;

const actor = Game.findRandomActor(
const actor = this.sp.Game.findRandomActor(
pc.getPositionX(),
pc.getPositionY(),
pc.getPositionZ(),
Expand All @@ -47,13 +58,35 @@ export class WorldCleanerService extends ClientListener {
return;
}

if (actor.isDead()) {
// Keep vanila pre-placed bodies, but delete player bodies
if (actor.isDead() && actorId < 0xff000000) {
actor.blockActivation(true);
return;
}

const pos = ObjectReferenceEx.getPos(actor);
const cellOrWorld = ObjectReferenceEx.getWorldOrCell(actor);

const chickenRace = 0xa919d;

// We discovered anomaly chickens that fail to Disable if we load game near to them
// Refs: 106C22, 106C23
if (actorId < 0xff000000 && actor.getRace()?.getFormID() === chickenRace) {
if (this.initialPos && ObjectReferenceEx.getDistanceNoZ(pos, this.initialPos) < 4096) {
if (cellOrWorld === this.initialCellOrWorld) {
if (this.isActorInDialogue(actor)) return;
this.logTrace(`Deleting chicken anomaly ${actorId.toString(16)}`);
actor.killSilent(null);
actor.blockActivation(true);
actor.disableNoWait(false);
actor.setAlpha(0, false);
return;
}
}
}

actor.disable(false).then(() => {
const ac = Actor.from(Game.getFormEx(actorId));
const ac = this.sp.Actor.from(this.sp.Game.getFormEx(actorId));
if (!ac || this.isActorInDialogue(ac)) return;
ac.delete();
});
Expand All @@ -64,4 +97,6 @@ export class WorldCleanerService extends ClientListener {
}

private protection = new Map<number, number>();
private initialPos?: NiPoint3;
private initialCellOrWorld?: number;
}

0 comments on commit 816987c

Please sign in to comment.