diff --git a/src/engine/core/binders/creature/MonsterBinder.test.ts b/src/engine/core/binders/creature/MonsterBinder.test.ts index ff63e4342..d871b1211 100644 --- a/src/engine/core/binders/creature/MonsterBinder.test.ts +++ b/src/engine/core/binders/creature/MonsterBinder.test.ts @@ -498,9 +498,15 @@ describe("MonsterBinder", () => { jest.spyOn(SchemeHear, "onObjectHearSound").mockImplementation(jest.fn()); + // Do not listen for self. binder.onHearSound(object, object.id(), 128, X_VECTOR, 10); expect(SchemeHear.onObjectHearSound).not.toHaveBeenCalled(); + // Do not listen when dead. + jest.spyOn(object, "alive").mockImplementationOnce(() => false); + binder.onHearSound(object, ACTOR_ID, 128, X_VECTOR, 10); + expect(SchemeHear.onObjectHearSound).not.toHaveBeenCalled(); + binder.onHearSound(object, ACTOR_ID, 128, X_VECTOR, 10); expect(SchemeHear.onObjectHearSound).toHaveBeenCalledWith(object, ACTOR_ID, 128, X_VECTOR, 10); }); diff --git a/src/engine/core/binders/creature/MonsterBinder.ts b/src/engine/core/binders/creature/MonsterBinder.ts index fb3a06ace..6fd0ff7d6 100644 --- a/src/engine/core/binders/creature/MonsterBinder.ts +++ b/src/engine/core/binders/creature/MonsterBinder.ts @@ -301,7 +301,13 @@ export class MonsterBinder extends object_binder { /** * On monster hear sound. - * Handle surrounding sounds and process danger / aggression based on sound type and power. + * Handle surrounding sounds and process danger / aggression / condlists based on sound type and power. + * + * @param object - game object hearing sounds + * @param sourceId - ID of object producing sound + * @param soundType - mask object with types of sounds heard + * @param soundPosition - vector with 3d position of sounds source + * @param soundPower - power level of sound */ public onHearSound( object: GameObject, @@ -310,8 +316,16 @@ export class MonsterBinder extends object_binder { soundPosition: Vector, soundPower: TRate ): void { - if (sourceId !== object.id()) { - SchemeHear.onObjectHearSound(object, sourceId, soundType, soundPosition, soundPower); + // Don't handle own sounds. + if (sourceId === object.id()) { + return; + } + + // Don't handle sounds when dead. + if (!object.alive()) { + return; } + + SchemeHear.onObjectHearSound(object, sourceId, soundType, soundPosition, soundPower); } } diff --git a/src/engine/core/binders/creature/StalkerBinder.test.ts b/src/engine/core/binders/creature/StalkerBinder.test.ts index 4c26316a8..57a4365b4 100644 --- a/src/engine/core/binders/creature/StalkerBinder.test.ts +++ b/src/engine/core/binders/creature/StalkerBinder.test.ts @@ -8,6 +8,7 @@ import { SoundManager } from "@/engine/core/managers/sounds"; import { initializeObjectThemes } from "@/engine/core/managers/sounds/utils"; import { TradeManager } from "@/engine/core/managers/trade"; import { syncObjectHitSmartTerrainAlert } from "@/engine/core/objects/smart_terrain/utils"; +import { SchemeHear } from "@/engine/core/schemes/shared/hear"; import { SchemePostCombatIdle } from "@/engine/core/schemes/stalker/combat_idle"; import { SchemeReachTask } from "@/engine/core/schemes/stalker/reach_task"; import { ISchemeWoundedState } from "@/engine/core/schemes/stalker/wounded"; @@ -18,7 +19,8 @@ import { syncSpawnedObjectPosition, } from "@/engine/core/utils/object"; import { emitSchemeEvent, setupObjectLogicsOnSpawn } from "@/engine/core/utils/scheme"; -import { ZERO_VECTOR } from "@/engine/lib/constants/vectors"; +import { ACTOR_ID } from "@/engine/lib/constants/ids"; +import { X_VECTOR, ZERO_VECTOR } from "@/engine/lib/constants/vectors"; import { AnyObject, EScheme, ESchemeEvent, ESchemeType, GameObject, ServerHumanObject } from "@/engine/lib/types"; import { mockRegisteredActor, mockSchemeState, resetRegistry } from "@/fixtures/engine"; import { resetFunctionMock } from "@/fixtures/jest"; @@ -177,7 +179,24 @@ describe("StalkerBinder", () => { it.todo("should correctly handle death event"); - it.todo("should correctly handle hear event"); + it("should handle hear event", () => { + const object: GameObject = MockGameObject.mock(); + const binder: StalkerBinder = new StalkerBinder(object); + + jest.spyOn(SchemeHear, "onObjectHearSound").mockImplementation(jest.fn()); + + // Do not listen for self. + binder.onHearSound(object, object.id(), 128, X_VECTOR, 10); + expect(SchemeHear.onObjectHearSound).not.toHaveBeenCalled(); + + // Do not listen when dead. + jest.spyOn(object, "alive").mockImplementationOnce(() => false); + binder.onHearSound(object, ACTOR_ID, 128, X_VECTOR, 10); + expect(SchemeHear.onObjectHearSound).not.toHaveBeenCalled(); + + binder.onHearSound(object, ACTOR_ID, 128, X_VECTOR, 10); + expect(SchemeHear.onObjectHearSound).toHaveBeenCalledWith(object, ACTOR_ID, 128, X_VECTOR, 10); + }); it.todo("should correctly handle use event"); diff --git a/src/engine/core/binders/creature/StalkerBinder.ts b/src/engine/core/binders/creature/StalkerBinder.ts index 5a2ee2f49..4d542e285 100644 --- a/src/engine/core/binders/creature/StalkerBinder.ts +++ b/src/engine/core/binders/creature/StalkerBinder.ts @@ -390,21 +390,33 @@ export class StalkerBinder extends object_binder { } /** - * todo: Description. + * On stalker hear sound. + * Handle surrounding sounds and process danger / aggression / condlists based on sound type and power. + * + * @param object - game object hearing sounds + * @param sourceId - ID of object producing sound + * @param soundType - mask object with types of sounds heard + * @param soundPosition - vector with 3d position of sounds source + * @param soundPower - power level of sound */ public onHearSound( object: GameObject, - whoId: TNumberId, + sourceId: TNumberId, soundType: TSoundType, soundPosition: Vector, soundPower: TRate ): void { // Don't handle own sounds. - if (whoId === object.id()) { + if (sourceId === object.id()) { + return; + } + + // Don't handle sounds when dead. + if (!object.alive()) { return; } - SchemeHear.onObjectHearSound(object, whoId, soundType, soundPosition, soundPower); + SchemeHear.onObjectHearSound(object, sourceId, soundType, soundPosition, soundPower); } /**