Virtual for when a monster first acquires a target

Fri May 21, 2021 9:40 pm

I want a clean way to have a monster do things other than/along with it making its seesound and going into see state, that shouldn't be done repeatedly but only when the monster first acquires its target.

Use cases can include:
- Playing a seesound at a different pitch (this is what I was trying to do - each individual monster would have a slightly different voice pitch, which is fairly easy to do for idle, pain and death but not sight)
- Playing a different seesound depending on other circumstances (e.g., multiple pronoun options for "It's ___! Get ___!" depending on player settings, or different responses depending on whether a certain quest item is in the player's possession)
- Summoning an ally, shield, etc. that's only supposed to happen once per fight
- A different opening attack that isn't repeated again (good for characters with very limited ammo like throwing axes or whatnot)
- A flying monster launching itself into the air if it's on the ground


Something equivalent for when a monster loses/defeats its target and goes into spawn/idle would be great too.


Workarounds I'm trying to avoid include:
- constantly comparing the monster's current and immediately preceding target (can be done as a last resort)
- inserting all this stuff into the spawn/idle/see states of each monster (there are quite a few so it gets unmaintainable quickly compared to having them all inherit from another monster)

Re: Virtual for when a monster first acquires a target

Mon Jul 05, 2021 2:02 pm

So
Code:
class dummy : actor
{
   private bool first_time_target;

   override void tick()
   {
      if(first_time_target == false && target)
      {
         first_time_target = true;
         stuff that actor should do on target "aquariuming"
      }

      super.tick();
   }
}

Re: Virtual for when a monster first acquires a target

Tue Jul 06, 2021 1:34 am

^This would not let me "interrupt" entering the See state. A virtual that returns a bool would be be nice, where true would result in the usual behavior of entering the See state (or other state as defined in A_LookEx), and false cancels the state change. Parameters of the virtual could be wether the monster saw the target or not (not means that it "heard" the target or was affected by Thing_Hate or similar).

Re: Virtual for when a monster first acquires a target

Fri Jul 09, 2021 1:20 am

Cherno wrote:This would not let me "interrupt" entering the See state

JUst change the order in tick to
Code:
   override void tick()
   {
      super.tick();

      if(first_time_target == false && target)
      {
         first_time_target = true;
         stuff that actor should do on target "aquariuming"
      }
   }

Re: Virtual for when a monster first acquires a target

Fri Jul 09, 2021 2:23 am

That would trigger too late in most cases.

Re: Virtual for when a monster first acquires a target

Fri Jul 09, 2021 3:57 am

Maybe then, instead of "virtual void OnTargetAcquiring() = 0;", it have more sense to split tick into separate functions, exposed to zscript? Something like, unordered,
Code:
AActor::Tick()
{
//exposed to zscript
AdvanceState();
HandleCollision();
HandlePowerups();
BotThink();
other stuff

//still internal
UpdateRenderList();
}

Point is, this makes tick extension/custom implementation much easier. With this you can copy/paste all unchanged functions as is, and focus effort on new custom features.

Or performance degradation will be too big in this case?

Re: Virtual for when a monster first acquires a target

Fri Jul 09, 2021 4:12 am

AActor::Tick() is not the correct place for this. You would want to have the callback somewhere in A_Look.

Re: Virtual for when a monster first acquires a target

Fri Jul 09, 2021 4:55 am

@ Apeirogon:

The whole point of the "Feature Requests" subforum is not for you to suggest hacky workarounds for ideas that are posted here. If something is posted here then chances are the author (probably for good reason) wants a more direct approach to something that logically and naturally ties into an existing workflow and hopefully without creating a convoluted mess on the author's end.

The workarounds you've posted here don't really do that. So please understand that before you go suggesting more workarounds.

Re: Virtual for when a monster first acquires a target

Fri Jul 09, 2021 3:57 pm

For what it's worth, I got the effect I wanted by using a function that checks the contents of the target pointer, calls A_Look and then compares the old target value to the new value, and calling the virtual if the target has in fact been newly acquired. Then I just use that function instead of A_Look every time.

This seems to do it cleanly enough that I'm not sure if this suggestion is even needed anymore, though I'm pretty sure there's an edge case that could still mess this up.