by _mental_ » Sun May 14, 2017 1:30 am
I tried to investigate the problem but would like to ask Graf to take a look.
Spoiler: Callstack for correct morph
Code: Select all
#0 P_MorphPlayer(player_t*, player_t*, PClassActor*, int, int, PClassActor*, PClassActor*) at src/g_shared/a_morph.cpp:66
#1 AF__PlayerInfo_MorphPlayer(VMValue*, TArray<VMValue, VMValue>&, int, VMReturn*, int) at src/g_shared/a_morph.cpp:190
#2 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:686
#3 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#4 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#5 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#6 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#7 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#8 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#9 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#10 VMCall(VMFunction*, VMValue*, int, VMReturn*, int) at src/scripting/vm/vmframe.cpp:463
#11 AInventory::CallTryPickup(AActor*, AActor**) at src/g_inventory/a_pickups.cpp:518
#12 DoGiveInventory(AActor*, bool, VMValue*, TArray<VMValue, VMValue>&, int, VMReturn*, int) at src/p_actionfunctions.cpp:2317
#13 AF_AActor_A_GiveInventory(VMValue*, TArray<VMValue, VMValue>&, int, VMReturn*, int) at src/p_actionfunctions.cpp:2333
#14 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:686
#15 VMCall(VMFunction*, VMValue*, int, VMReturn*, int) at src/scripting/vm/vmframe.cpp:463
#16 AStateProvider::CallStateChain(AActor*, FState*) at src/p_actionfunctions.cpp:187
#17 AF_ACustomInventory_CallStateChain(VMValue*, TArray<VMValue, VMValue>&, int, VMReturn*, int) at src/p_actionfunctions.cpp:229
#18 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:686
#19 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#20 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#21 VMCall(VMFunction*, VMValue*, int, VMReturn*, int) at src/scripting/vm/vmframe.cpp:463
#22 AActor::CallTouch(AActor*) at src/p_mobj.cpp:1740
#23 P_TouchSpecialThing(AActor*, AActor*) at src/p_interaction.cpp:114
#24 PIT_CheckThing(FMultiBlockThingsIterator&, FMultiBlockThingsIterator::CheckResult&, FBoundingBox const&, FCheckPosition&) at src/p_map.cpp:1658
#25 P_CheckPosition(AActor*, TVector2<double> const&, FCheckPosition&, bool) at src/p_map.cpp:1803
#26 P_TryMove(AActor*, TVector2<double> const&, int, secplane_t const*, FCheckPosition&, bool) at src/p_map.cpp:2242
#27 P_XYMovement(AActor*, TVector2<double>) at src/p_mobj.cpp:2515
#28 AActor::Tick() at src/p_mobj.cpp:4436
#29 APlayerPawn::Tick() at src/p_user.cpp:989
#30 AF_DThinker_Tick(VMValue*, TArray<VMValue, VMValue>&, int, VMReturn*, int) at src/dthinker.cpp:557
#31 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:686
#32 VMCall(VMFunction*, VMValue*, int, VMReturn*, int) at src/scripting/vm/vmframe.cpp:463
#33 DThinker::CallTick() at src/dthinker.cpp:567
#34 DThinker::TickThinkers(FThinkerList*, FThinkerList*) at src/dthinker.cpp:535
#35 DThinker::RunThinkers() at src/dthinker.cpp:481
#36 P_Ticker() at src/p_tick.cpp:136
#37 G_Ticker() at src/g_game.cpp:1232
#38 TryRunTics() at src/d_net.cpp:1951
#39 D_DoomLoop() at src/d_main.cpp:1038
#40 D_DoomMain() at src/d_main.cpp:2717
Spoiler: Difference in callstack for morph that aborts VM
Code: Select all
...
#27 AF_AActor_CheckBlock(VMValue*, TArray<VMValue, VMValue>&, int, VMReturn*, int) at src/p_actionfunctions.cpp:6497
#28 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:686
#29 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#30 VMCall(VMFunction*, VMValue*, int, VMReturn*, int) at src/scripting/vm/vmframe.cpp:463
#31 FState::CallAction(AActor*, AActor*, FStateParamInfo*, FState**) at src/info.cpp:152
#32 DPSprite::SetState(FState*, bool) at src/p_pspr.cpp:509
#33 AF_DPSprite_SetState(VMValue*, TArray<VMValue, VMValue>&, int, VMReturn*, int) at src/p_pspr.cpp:541
#34 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:686
#35 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#36 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#37 VMCall(VMFunction*, VMValue*, int, VMReturn*, int) at src/scripting/vm/vmframe.cpp:463
#38 P_PlayerThink(player_t*) at src/p_user.cpp:2311
...
I guess the issue with the latter is changing of PlayerPawn object, unmorphed one will have
player member set to
nullptr.
For some reason this works fine when morph happens during
APlayerPawn::Tick() but fails if called from
P_PlayerThink() function.
I'm using D4D Alpha 5 with these bindings:
Code: Select all
+bind k "summon baronrune"
+bind l "morphme"
Picking up summoned rune will end with one of callstacks above and depending on origin of morph it will work fine or abort with error.
Addition of null checks to scripting side won't solve the problem.
This will rather postpone it to a later moment when the game will crash because of
nullptr value of
player argument:
Spoiler: Callstack
Code: Select all
#0 DObject* GC::ReadBarrier<DObject>(DObject*&) at src/dobjgc.h:99
#1 TObjPtr<DBot*>::operator==(DBot*) at src/dobjgc.h:213
#2 P_CheckWeaponButtons(player_t*) at src/p_pspr.cpp:876
#3 AF_APlayerPawn_CheckWeaponButtons(VMValue*, TArray<VMValue, VMValue>&, int, VMReturn*, int) at src/p_pspr.cpp:908
#4 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:686
#5 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#6 VMCall(VMFunction*, VMValue*, int, VMReturn*, int) at src/scripting/vm/vmframe.cpp:463
#7 P_PlayerThink(player_t*) at src/p_user.cpp:2311
#8 P_Ticker() at src/p_tick.cpp:130
#9 G_Ticker() at src/g_game.cpp:1232
#10 TryRunTics() at src/d_net.cpp:1951
#11 D_DoomLoop() at src/d_main.cpp:1038
#12 D_DoomMain() at src/d_main.cpp:2717
I tried to investigate the problem but would like to ask Graf to take a look.
[spoiler=Callstack for correct morph][code]#0 P_MorphPlayer(player_t*, player_t*, PClassActor*, int, int, PClassActor*, PClassActor*) at src/g_shared/a_morph.cpp:66
#1 AF__PlayerInfo_MorphPlayer(VMValue*, TArray<VMValue, VMValue>&, int, VMReturn*, int) at src/g_shared/a_morph.cpp:190
#2 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:686
#3 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#4 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#5 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#6 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#7 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#8 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#9 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#10 VMCall(VMFunction*, VMValue*, int, VMReturn*, int) at src/scripting/vm/vmframe.cpp:463
#11 AInventory::CallTryPickup(AActor*, AActor**) at src/g_inventory/a_pickups.cpp:518
#12 DoGiveInventory(AActor*, bool, VMValue*, TArray<VMValue, VMValue>&, int, VMReturn*, int) at src/p_actionfunctions.cpp:2317
#13 AF_AActor_A_GiveInventory(VMValue*, TArray<VMValue, VMValue>&, int, VMReturn*, int) at src/p_actionfunctions.cpp:2333
#14 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:686
#15 VMCall(VMFunction*, VMValue*, int, VMReturn*, int) at src/scripting/vm/vmframe.cpp:463
#16 AStateProvider::CallStateChain(AActor*, FState*) at src/p_actionfunctions.cpp:187
#17 AF_ACustomInventory_CallStateChain(VMValue*, TArray<VMValue, VMValue>&, int, VMReturn*, int) at src/p_actionfunctions.cpp:229
#18 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:686
#19 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#20 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#21 VMCall(VMFunction*, VMValue*, int, VMReturn*, int) at src/scripting/vm/vmframe.cpp:463
#22 AActor::CallTouch(AActor*) at src/p_mobj.cpp:1740
#23 P_TouchSpecialThing(AActor*, AActor*) at src/p_interaction.cpp:114
#24 PIT_CheckThing(FMultiBlockThingsIterator&, FMultiBlockThingsIterator::CheckResult&, FBoundingBox const&, FCheckPosition&) at src/p_map.cpp:1658
#25 P_CheckPosition(AActor*, TVector2<double> const&, FCheckPosition&, bool) at src/p_map.cpp:1803
#26 P_TryMove(AActor*, TVector2<double> const&, int, secplane_t const*, FCheckPosition&, bool) at src/p_map.cpp:2242
#27 P_XYMovement(AActor*, TVector2<double>) at src/p_mobj.cpp:2515
#28 AActor::Tick() at src/p_mobj.cpp:4436
#29 APlayerPawn::Tick() at src/p_user.cpp:989
#30 AF_DThinker_Tick(VMValue*, TArray<VMValue, VMValue>&, int, VMReturn*, int) at src/dthinker.cpp:557
#31 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:686
#32 VMCall(VMFunction*, VMValue*, int, VMReturn*, int) at src/scripting/vm/vmframe.cpp:463
#33 DThinker::CallTick() at src/dthinker.cpp:567
#34 DThinker::TickThinkers(FThinkerList*, FThinkerList*) at src/dthinker.cpp:535
#35 DThinker::RunThinkers() at src/dthinker.cpp:481
#36 P_Ticker() at src/p_tick.cpp:136
#37 G_Ticker() at src/g_game.cpp:1232
#38 TryRunTics() at src/d_net.cpp:1951
#39 D_DoomLoop() at src/d_main.cpp:1038
#40 D_DoomMain() at src/d_main.cpp:2717[/code][/spoiler][spoiler=Difference in callstack for morph that aborts VM][code]...
#27 AF_AActor_CheckBlock(VMValue*, TArray<VMValue, VMValue>&, int, VMReturn*, int) at src/p_actionfunctions.cpp:6497
#28 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:686
#29 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#30 VMCall(VMFunction*, VMValue*, int, VMReturn*, int) at src/scripting/vm/vmframe.cpp:463
#31 FState::CallAction(AActor*, AActor*, FStateParamInfo*, FState**) at src/info.cpp:152
#32 DPSprite::SetState(FState*, bool) at src/p_pspr.cpp:509
#33 AF_DPSprite_SetState(VMValue*, TArray<VMValue, VMValue>&, int, VMReturn*, int) at src/p_pspr.cpp:541
#34 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:686
#35 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#36 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#37 VMCall(VMFunction*, VMValue*, int, VMReturn*, int) at src/scripting/vm/vmframe.cpp:463
#38 P_PlayerThink(player_t*) at src/p_user.cpp:2311
...[/code][/spoiler]
I guess the issue with the latter is changing of PlayerPawn object, unmorphed one will have [b]player[/b] member set to [b]nullptr[/b].
For some reason this works fine when morph happens during [b]APlayerPawn::Tick()[/b] but fails if called from [b]P_PlayerThink()[/b] function.
I'm using D4D Alpha 5 with these bindings:[code]+bind k "summon baronrune"
+bind l "morphme"[/code]
Picking up summoned rune will end with one of callstacks above and depending on origin of morph it will work fine or abort with error.
Addition of null checks to scripting side won't solve the problem.
This will rather postpone it to a later moment when the game will crash because of [b]nullptr[/b] value of [b]player[/b] argument:[spoiler=Callstack][code]#0 DObject* GC::ReadBarrier<DObject>(DObject*&) at src/dobjgc.h:99
#1 TObjPtr<DBot*>::operator==(DBot*) at src/dobjgc.h:213
#2 P_CheckWeaponButtons(player_t*) at src/p_pspr.cpp:876
#3 AF_APlayerPawn_CheckWeaponButtons(VMValue*, TArray<VMValue, VMValue>&, int, VMReturn*, int) at src/p_pspr.cpp:908
#4 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:686
#5 VMExec_Checked::Exec(VMFrameStack*, VMOP const*, VMReturn*, int) at src/scripting/vm/vmexec.h:705
#6 VMCall(VMFunction*, VMValue*, int, VMReturn*, int) at src/scripting/vm/vmframe.cpp:463
#7 P_PlayerThink(player_t*) at src/p_user.cpp:2311
#8 P_Ticker() at src/p_tick.cpp:130
#9 G_Ticker() at src/g_game.cpp:1232
#10 TryRunTics() at src/d_net.cpp:1951
#11 D_DoomLoop() at src/d_main.cpp:1038
#12 D_DoomMain() at src/d_main.cpp:2717[/code][/spoiler]