Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WorldThingGoalReached Virtual #2823

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,18 @@ void EventManager::WorldThingDamaged(AActor* actor, AActor* inflictor, AActor* s
handler->WorldThingDamaged(actor, inflictor, source, damage, mod, flags, angle);
}

void EventManager::WorldThingGoalReached(AActor* actor, AActor* oldgoal)
{
// don't call anything if actor was destroyed on PostBeginPlay/BeginPlay/whatever.
if (actor->ObjectFlags & OF_EuthanizeMe)
return;

if (ShouldCallStatic(true)) staticEventManager.WorldThingGoalReached(actor, oldgoal);

for (DStaticEventHandler* handler = FirstEventHandler; handler; handler = handler->next)
handler->WorldThingGoalReached(actor, oldgoal);
}

void EventManager::WorldThingDestroyed(AActor* actor)
{
// don't call anything if actor was destroyed on PostBeginPlay/BeginPlay/whatever.
Expand Down Expand Up @@ -1776,6 +1788,20 @@ void DStaticEventHandler::WorldThingDamaged(AActor* actor, AActor* inflictor, AA
}
}

void DStaticEventHandler::WorldThingGoalReached(AActor* actor, AActor* oldgoal)
{
IFVIRTUAL(DStaticEventHandler, WorldThingGoalReached)
{
// don't create excessive DObjects if not going to be processed anyway
if (isEmpty(func)) return;
FWorldEvent e = owner->SetupWorldEvent();
e.Thing = actor;
e.Inflictor = oldgoal;
VMValue params[2] = { (DStaticEventHandler*)this, &e };
VMCall(func, params, 2, nullptr, 0);
}
}

void DStaticEventHandler::WorldThingDestroyed(AActor* actor)
{
IFVIRTUAL(DStaticEventHandler, WorldThingDestroyed)
Expand Down
5 changes: 4 additions & 1 deletion src/events.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ class DStaticEventHandler : public DObject // make it a part of normal GC proces
void WorldThingGround(AActor* actor, FState* st);
void WorldThingRevived(AActor* actor);
void WorldThingDamaged(AActor* actor, AActor* inflictor, AActor* source, int damage, FName mod, int flags, DAngle angle);
void WorldThingGoalReached(AActor* actor, AActor* oldgoal);
void WorldThingDestroyed(AActor* actor);
void WorldLinePreActivated(line_t* line, AActor* actor, int activationType, bool* shouldactivate);
void WorldLineActivated(line_t* line, AActor* actor, int activationType);
Expand Down Expand Up @@ -471,8 +472,10 @@ struct EventManager
void WorldThingGround(AActor* actor, FState* st);
// called after AActor::Revive.
void WorldThingRevived(AActor* actor);
// called before P_DamageMobj and before AActor::DamageMobj virtuals.
// called after damage has been dealt
void WorldThingDamaged(AActor* actor, AActor* inflictor, AActor* source, int damage, FName mod, int flags, DAngle angle);
// called when the actor changes goals. Goal is the OLD goal.
void WorldThingGoalReached(AActor* actor, AActor* oldgoal);
// called before AActor::Destroy of each actor.
void WorldThingDestroyed(AActor* actor);
// called in P_ActivateLine before executing special, set shouldactivate to false to prevent activation.
Expand Down
21 changes: 19 additions & 2 deletions src/playsim/p_enemy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include "actorinlines.h"
#include "a_ceiling.h"
#include "shadowinlines.h"
#include "events.h"

#include "gi.h"

Expand Down Expand Up @@ -2370,6 +2371,20 @@ DEFINE_ACTION_FUNCTION(AActor, A_Look2)
return 0;
}

void GoalReached(AActor* self, AActor* oldgoal)
{
if (self && self->Level)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self doesn't need to be nulled checked since the VM ensures that this won't happen

self->Level->localEventManager->WorldThingGoalReached(self, oldgoal);
}

DEFINE_ACTION_FUNCTION(AActor, GoalReached)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be native
DEFINE_ACTION_FUNCTION_NATIVE(AActor, GoalReached, GoalReached)

{
PARAM_SELF_PROLOGUE(AActor);
PARAM_OBJECT(oldgoal, AActor);
GoalReached(self, oldgoal);
return 0;
}

//=============================================================================
//
// A_Chase
Expand Down Expand Up @@ -2549,7 +2564,8 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi
// [RH] Don't attack if just moving toward goal
if (actor->target == actor->goal || (actor->flags5&MF5_CHASEGOAL && actor->goal != NULL))
{
AActor * savedtarget = actor->target;
AActor *savedtarget = actor->target;
AActor *savedgoal = actor->goal;
actor->target = actor->goal;
bool result = P_CheckMeleeRange(actor);
actor->target = savedtarget;
Expand All @@ -2572,7 +2588,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi
DAngle lastgoalang = actor->goal->Angles.Yaw;
int delay;
AActor * newgoal = iterator.Next ();
if (newgoal != NULL && actor->goal == actor->target)
if (newgoal != nullptr && actor->goal == actor->target)
{
delay = newgoal->args[1];
actor->reactiontime = delay * TICRATE + actor->Level->maptime;
Expand All @@ -2592,6 +2608,7 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi
}
actor->flags7 &= ~MF7_INCHASE;
actor->goal = newgoal;
GoalReached(actor, savedgoal);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing destruction check before calling this since a goal special could delete it.
if (!(actor->ObjectFlags & OF_EuthanizeMe))

return;
}
if (actor->goal == actor->target) goto nomissile;
Expand Down
3 changes: 3 additions & 0 deletions wadsrc/static/zscript/actors/actor.zs
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,9 @@ class Actor : Thinker native
movecount = random[TryWalk](0, 15);
return true;
}

// Calls WorldThingGoalReached.
native void GoalReached(Actor oldgoal);

native bool TryMove(vector2 newpos, int dropoff, bool missilecheck = false, FCheckPosition tm = null);
native bool CheckMove(vector2 newpos, int flags = 0, FCheckPosition tm = null);
Expand Down
5 changes: 3 additions & 2 deletions wadsrc/static/zscript/events.zs
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,9 @@ struct WorldEvent native play version("2.4")
native readonly bool IsReopen;
// for unloaded, name of next map (if any)
native readonly String NextMap;
// for thingspawned/thingdied/thingdestroyed/thingground
// for thingspawned/thingdied/thingdestroyed/thingground/thinggoalreached
native readonly Actor Thing;
// for thingdied. can be null
// for thingdied. can be null. [MC] Also used for ThingGoalReached, inflictor is the old goal.
native readonly Actor Inflictor;
// for thingdamaged, line/sector damaged
native readonly int Damage;
Expand Down Expand Up @@ -154,6 +154,7 @@ class StaticEventHandler : Object native play version("2.4")
virtual void WorldThingGround(WorldEvent e) {}
virtual void WorldThingRevived(WorldEvent e) {}
virtual void WorldThingDamaged(WorldEvent e) {}
virtual void WorldThingGoalReached(WorldEvent e) {}
virtual void WorldThingDestroyed(WorldEvent e) {}
virtual void WorldLinePreActivated(WorldEvent e) {}
virtual void WorldLineActivated(WorldEvent e) {}
Expand Down