by Shrinker » Mon Jan 29, 2018 10:08 am
My analysis so far...
Code: Select all
"give bfg9000" in that map freezes the game. I can reproduce the error.
c_dispatch.cpp
if ( (com = FindNameInHashTable (Commands, beg, len)) )
c_cmds.cpp
CCMD (give)
DEM_GIVECHEAT
d_net.cpp
case DEM_GIVECHEAT
m_cheat.cpp
void cht_Give (player_t *player, const char *name, int amount)
VMCall(func, params, 3, nullptr, 0);
IFVIRTUALPTR leads me to script functions
the function "CheatGive" is called
so that might be in... player_cheat.txt
GiveInventory...
setting breakpoints on all giveInventory-s I can find, I land in:
p_mobj.cpp/bool AActor::GiveInventory(PClassActor *type, int amount, bool givecheat)
item = static_cast<AInventory *>(Spawn (type, Pos(), NO_REPLACE));
if (item == NULL) return false; => item is not null in our case, so the spawning worked
...
if (!item->CallTryPickup (this)) => ### this freezes ###
bool AInventory::CallTryPickup(AActor *toucher, AActor **toucher_return)
if (func == nullptr) PClass::FindFunction(&func, NAME_Inventory, NAME_CallTryPickup);
VMCall(func, params, 2, ret, 2); => back to the scripting layer
we probably land in:
inventory.txt/bool, Actor CallTryPickup(Actor toucher)
what about CanPickup? => determins if the player is allowed to pick it up
what about TryPickup?
hm... I can't figure it out further from here.
When I stop the frozen program in the debugger, I end up with a program stack that doesn't allow me to find my way back into the known source code...
I don't know how to push changed files from the zscript dir into the program -- The scripting part is so involved here it would help a lot to comment out a things a bit to pin down the fault location further.
Oh wait, I've continued and stopped the debugger a few more times and landed somewhere!
p_mobj.cpp/AActor *AActor::StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t allowreplacement, bool SpawningMapThing)
=> P_FindFloorCeilingz
while ((mit.Next(&cres)))
{
PIT_FindFloorCeiling(mit, cres, mit.Box(), tmf, flags|cres.portalflags);
}
This thing loops infinitely!
Okay so... I'm looking at your map in the editor, and my repro map from here is quite similar:
viewtopic.php?f=2&t=58193
Only there's a main difference: Your portal marker wall segments also double as real wall segments. That might be wrong!
This is how I've done it, following an example map I got from somewhere else:
https://imgur.com/a/Q6opv
Regarding the code I've found:
Maybe there should be a guard checking if the first "cres" is visited again on the way or something like that, or maybe this is really an error in the level design that should somehow be caught earlier on...
My analysis so far...
[code]
"give bfg9000" in that map freezes the game. I can reproduce the error.
c_dispatch.cpp
if ( (com = FindNameInHashTable (Commands, beg, len)) )
c_cmds.cpp
CCMD (give)
DEM_GIVECHEAT
d_net.cpp
case DEM_GIVECHEAT
m_cheat.cpp
void cht_Give (player_t *player, const char *name, int amount)
VMCall(func, params, 3, nullptr, 0);
IFVIRTUALPTR leads me to script functions
the function "CheatGive" is called
so that might be in... player_cheat.txt
GiveInventory...
setting breakpoints on all giveInventory-s I can find, I land in:
p_mobj.cpp/bool AActor::GiveInventory(PClassActor *type, int amount, bool givecheat)
item = static_cast<AInventory *>(Spawn (type, Pos(), NO_REPLACE));
if (item == NULL) return false; => item is not null in our case, so the spawning worked
...
if (!item->CallTryPickup (this)) => ### this freezes ###
bool AInventory::CallTryPickup(AActor *toucher, AActor **toucher_return)
if (func == nullptr) PClass::FindFunction(&func, NAME_Inventory, NAME_CallTryPickup);
VMCall(func, params, 2, ret, 2); => back to the scripting layer
we probably land in:
inventory.txt/bool, Actor CallTryPickup(Actor toucher)
what about CanPickup? => determins if the player is allowed to pick it up
what about TryPickup?
hm... I can't figure it out further from here.
When I stop the frozen program in the debugger, I end up with a program stack that doesn't allow me to find my way back into the known source code...
I don't know how to push changed files from the zscript dir into the program -- The scripting part is so involved here it would help a lot to comment out a things a bit to pin down the fault location further.
Oh wait, I've continued and stopped the debugger a few more times and landed somewhere!
p_mobj.cpp/AActor *AActor::StaticSpawn (PClassActor *type, const DVector3 &pos, replace_t allowreplacement, bool SpawningMapThing)
=> P_FindFloorCeilingz
while ((mit.Next(&cres)))
{
PIT_FindFloorCeiling(mit, cres, mit.Box(), tmf, flags|cres.portalflags);
}
This thing loops infinitely!
[/code]
Okay so... I'm looking at your map in the editor, and my repro map from here is quite similar: https://forum.zdoom.org/viewtopic.php?f=2&t=58193
Only there's a main difference: Your portal marker wall segments also double as real wall segments. That might be wrong!
This is how I've done it, following an example map I got from somewhere else: https://imgur.com/a/Q6opv
Regarding the code I've found:
Maybe there should be a guard checking if the first "cres" is visited again on the way or something like that, or maybe this is really an error in the level design that should somehow be caught earlier on...