So after some discussion in Discord, it seems that PlayerEntered() acts more like a RETURN script. As I understand it (?) this means it can't reliably be used for first-time initialization on players because it A) only runs once for a level load, and B) might catch a nullpointer for a player that has entered the map/game but doesn't yet have a PlayerPawn. Also, it seems PlayerRespawned() only runs after the player has died at least once, so it can't be used for first-time initialization.
I'd like to request a new event, PlayerSpawned(), that acts more like an ENTER script and can be safely used for first-time initialization on players / playerpawns.
Spoiler: for context
For context, here are my initialization functions that were causing address zero pointer errors for certain players when running in a multiplayer game:
I'm trying to do a custom "start with shotgun" thingy and it's a bit of a hassle to either create a function and set up 2 separate overrides just to avoid creating a whole new playerpawn (and editing mapinfo, etc. to get that working), while this mod has no use for PlayerEntered/Respawned otherwise.
A generic PlayerSpawned would definitely be much more helpful and intuitive to use.
Caligari87 wrote:Sorry for the bump but is there any reason this can't be added?
Yes, in short: Voodoo dolls. There is simply no good way to find a place where to do this reliably. We can either keep PlayerEntered as it is, with all its shortcomings, or call the event on every player spawn, including voodoo dolls - there is simply no middle ground here that naively works "as it should".
How does an ACS ENTER script (apparently, according to people more knowledgeable than me) do this properly? I'm not familiar with all the inner workings and quirks, but to my understanding it properly catches an actual player.mo spawning in the level and can be used for initialization. Or am I wrong, and an ACS ENTER script A) triggers for voodoo dolls too, B) triggers the same way as a PlayerEntered event, or C) something else?
If a spawn event is added that triggers on all player spawns, including voodoo dolls, what about adding a flag to the event indicating the player is a voodoo doll? Again I'm not familiar with the inner workings, but I would hope GZDoom internally tracks and/or "emulates" voodoo doll behavior in such a way that it can be flagged for events like this.
If the engine can't tell the event handler that the spawned player is a voodoo doll, would it really be so bad to run a spawn event on every player and voodoo doll anyway? If they're not supposed to be differentiated from actual players, I would want to run initialization on them too, right?
If PlayerEntered is kept as-is, what is the recommended workaround for ensuring I actually have a valid / existing player? Obviously the event only runs once so I can't simply not do initialization if the player.mo doesn't exist. For example, I received this pull request on my mod Ugly as Sin (a sub-mod for Hideous Destructor). As I understand the workaround, it defers my initialization code to a separate function. If the PlayerEntered event fails to initialize, it creates a thinker attached to the player, that calls the initialization in the thinker's PostBeginPlay instead. To me, this seems hacky and I declined to implement it in favor of waiting for an answer here.
My other theorized solutions included:
Doing initialization in a WorldThingSpawned event and checking if the thing is a player.
Flagging a potential player in PlayerEntered but running the actual initialization in a WorldTick override that continuously checks if the player.mo exists first
ENTER scripts trigger for all voodoo dolls as well, that's precisely the problem I was talking about. Of course I can add an event with exactly the same behavior, that wouldn't be a problem.
Ah, okay. To be honest I'd be fine with that, since the behavior already exists and seems not super-problematic, I guess? It would definitely be nice to have the ability to check "e.IsVoodooDoll" or something, if possible.
I made what is probably a very crude/rudimentary attempt at this by simply calling a new event handler at the same place (I think) that ENTER scripts are called.