From my testing, unwanted (to me, at minimum) behaviour occurs on level load, whether it's hub reload or a map load, with mapthing actors which were replaced with RandomSpawner. Some details differ on map load and level change, but broad strokes are the same.
BeginPlay() is apparently called during (p_mobj.cpp) ConstructActor and FLevelLocals::SpawnMapThing functions, and virtual functions processed then and there, resulting in redundant ChooseSpawn() calls; I can't tell what actually executes, but some calls such as Console.Printf definitely execute. That's bad enough already I guess, but it will produce unwanted behaviours if you attempt to override ChooseSpawn using function calls that don't just read data but write it into a static thinker or something similar.
The behaviour is easily demonstrated by using this code (replacing some common actor) and repeatedly travelling between hub levels or just quickloading:
Code: Select all
class DestroyRandomSpawner : RandomSpawner replaces Ettin
{
// Override this to decide what to spawn in some other way.
// Return the class name, or 'None' to spawn nothing, or 'Unknown' to spawn an error marker.
override Name ChooseSpawn()
{
Console.Printf("%s is still thinking!", GetClassName());
return Super.ChooseSpawn();
}
// For reference, start of a BeginPlay()
// override void BeginPlay()
// {
// // Bool check always passes even if it is the first line, suggesting the value isn't loaded in a savegame yet
// if (boolspawn) return; else boolspawn = true;
// Actor.BeginPlay(); // Super does exactly the thing it shouldn't
// let s = ChooseSpawn();
//
}
Obvious Zscript-side solution is a single bool check before starting on the rest of code... which won't work, likely because of engine-side loading sequence. Only moving entire BeginPlay() override content to PostBeginPlay() works, which is, uh,.. sort of extreme solution.
Can others share thoughts on it? I fixed what I wanted working, but another opinion never hurts.
