diff --git a/src/events.cpp b/src/events.cpp index d07bfefe87..f71fd9e9ec 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -331,6 +331,18 @@ void EventManager::WorldThingDied(AActor* actor, AActor* inflictor) handler->WorldThingDied(actor, inflictor); } +void EventManager::WorldThingGround(AActor* actor) +{ + // don't call anything if actor was destroyed on PostBeginPlay/BeginPlay/whatever. + if (actor->ObjectFlags & OF_EuthanizeMe) + return; + + if (ShouldCallStatic(true)) staticEventManager.WorldThingGround(actor); + + for (DStaticEventHandler* handler = FirstEventHandler; handler; handler = handler->next) + handler->WorldThingGround(actor); +} + void EventManager::WorldThingRevived(AActor* actor) { // don't call anything if actor was destroyed on PostBeginPlay/BeginPlay/whatever. @@ -795,6 +807,20 @@ void DStaticEventHandler::WorldThingDied(AActor* actor, AActor* inflictor) } } +void DStaticEventHandler::WorldThingGround(AActor* actor) +{ + IFVIRTUAL(DStaticEventHandler, WorldThingGround) + { + // don't create excessive DObjects if not going to be processed anyway + if (isEmpty(func)) return; + FWorldEvent e = owner->SetupWorldEvent(); + e.Thing = actor; + VMValue params[2] = { (DStaticEventHandler*)this, &e }; + VMCall(func, params, 2, nullptr, 0); + } +} + + void DStaticEventHandler::WorldThingRevived(AActor* actor) { IFVIRTUAL(DStaticEventHandler, WorldThingRevived) diff --git a/src/events.h b/src/events.h index 816615823f..b803f76d6d 100755 --- a/src/events.h +++ b/src/events.h @@ -80,6 +80,7 @@ public: void WorldUnloaded(); void WorldThingSpawned(AActor* actor); void WorldThingDied(AActor* actor, AActor* inflictor); + void WorldThingGround(AActor* actor); void WorldThingRevived(AActor* actor); void WorldThingDamaged(AActor* actor, AActor* inflictor, AActor* source, int damage, FName mod, int flags, DAngle angle); void WorldThingDestroyed(AActor* actor); @@ -234,6 +235,8 @@ struct EventManager void WorldThingSpawned(AActor* actor); // called after AActor::Die of each actor. void WorldThingDied(AActor* actor, AActor* inflictor); + // called inside AActor::Grind just before the corpse is destroyed + void WorldThingGround(AActor* actor); // called after AActor::Revive. void WorldThingRevived(AActor* actor); // called before P_DamageMobj and before AActor::DamageMobj virtuals. diff --git a/src/playsim/p_mobj.cpp b/src/playsim/p_mobj.cpp index 56fcf47eac..b85ad78878 100644 --- a/src/playsim/p_mobj.cpp +++ b/src/playsim/p_mobj.cpp @@ -1204,6 +1204,7 @@ bool AActor::Grind(bool items) S_Sound (this, CHAN_BODY, 0, "misc/fallingsplat", 1, ATTN_IDLE); Translation = BloodTranslation; } + Level->localEventManager->WorldThingGround(this); return false; } if (!(flags & MF_NOBLOOD)) @@ -1246,6 +1247,7 @@ bool AActor::Grind(bool items) gib->Translation = BloodTranslation; } S_Sound (this, CHAN_BODY, 0, "misc/fallingsplat", 1, ATTN_IDLE); + Level->localEventManager->WorldThingGround(this); } if (flags & MF_ICECORPSE) { diff --git a/wadsrc/static/zscript/events.zs b/wadsrc/static/zscript/events.zs index aa4d620ec5..6792188004 100644 --- a/wadsrc/static/zscript/events.zs +++ b/wadsrc/static/zscript/events.zs @@ -15,7 +15,7 @@ struct WorldEvent native play version("2.4") native readonly bool IsSaveGame; // this will be true if we are re-entering the hub level. native readonly bool IsReopen; - // for thingspawned/thingdied/thingdestroyed + // for thingspawned/thingdied/thingdestroyed/thingground native readonly Actor Thing; // for thingdied. can be null native readonly Actor Inflictor; @@ -323,6 +323,7 @@ class StaticEventHandler : Object native play version("2.4") virtual void WorldUnloaded(WorldEvent e) {} virtual void WorldThingSpawned(WorldEvent e) {} virtual void WorldThingDied(WorldEvent e) {} + virtual void WorldThingGround(WorldEvent e) {} virtual void WorldThingRevived(WorldEvent e) {} virtual void WorldThingDamaged(WorldEvent e) {} virtual void WorldThingDestroyed(WorldEvent e) {}