From 39355cf45deda5cccffcf49816486cb8740c9ad0 Mon Sep 17 00:00:00 2001 From: ZZYZX Date: Thu, 2 Feb 2017 20:46:10 +0200 Subject: [PATCH] Implemented player scripts. --- src/b_game.cpp | 4 ++++ src/events.cpp | 16 +++++++++++----- src/events.h | 4 ++-- src/g_game.cpp | 3 +++ src/g_level.cpp | 26 ++++++++++++++++++++++---- src/p_interaction.cpp | 3 +++ 6 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/b_game.cpp b/src/b_game.cpp index b99b97a60..38fbfafcb 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -61,6 +61,7 @@ Everything that is changed is marked (maybe commented) with "Added by MC" #include "d_netinf.h" #include "d_player.h" #include "doomerrors.h" +#include "events.h" static FRandom pr_botspawn ("BotSpawn"); @@ -418,6 +419,9 @@ void FCajunMaster::RemoveAllBots (bool fromlist) } } } + // [ZZ] run event hook + E_PlayerDisconnected(i); + // FBehavior::StaticStartTypedScripts (SCRIPT_Disconnect, players[i].mo, true, i, true); ClearPlayer (i, !fromlist); } diff --git a/src/events.cpp b/src/events.cpp index bd78ad128..02f269db4 100755 --- a/src/events.cpp +++ b/src/events.cpp @@ -337,10 +337,15 @@ void E_WorldThingDestroyed(AActor* actor) handler->WorldThingDestroyed(actor); } -void E_PlayerEntered(int num) +void E_PlayerEntered(int num, bool fromhub) { + // this event can happen during savegamerestore. make sure that local handlers don't receive it. + // actually, global handlers don't want it too. + if (savegamerestore && !fromhub) + return; + for (DStaticEventHandler* handler = E_FirstEventHandler; handler; handler = handler->next) - handler->PlayerEntered(num); + handler->PlayerEntered(num, fromhub); } void E_PlayerRespawned(int num) @@ -540,7 +545,7 @@ static DWorldEvent* E_SetupWorldEvent() static DWorldEvent* e = nullptr; if (!e) e = (DWorldEvent*)RUNTIME_CLASS(DWorldEvent)->CreateNew(); e->IsSaveGame = savegamerestore; - e->IsReopen = level.FromSnapshot; + e->IsReopen = level.FromSnapshot && !savegamerestore; // each one by itself isnt helpful, but with hub load we have savegamerestore==0 and level.FromSnapshot==1. e->Thing = nullptr; e->Inflictor = nullptr; e->Damage = 0; @@ -710,11 +715,11 @@ static DPlayerEvent* E_SetupPlayerEvent() static DPlayerEvent* e = nullptr; if (!e) e = (DPlayerEvent*)RUNTIME_CLASS(DPlayerEvent)->CreateNew(); e->PlayerNumber = -1; - e->IsReturn = level.FromSnapshot; + e->IsReturn = false; return e; } -void DStaticEventHandler::PlayerEntered(int num) +void DStaticEventHandler::PlayerEntered(int num, bool fromhub) { IFVIRTUAL(DStaticEventHandler, PlayerEntered) { @@ -722,6 +727,7 @@ void DStaticEventHandler::PlayerEntered(int num) if (func == DStaticEventHandler_PlayerEntered_VMPtr) return; DPlayerEvent* e = E_SetupPlayerEvent(); + e->IsReturn = fromhub; e->PlayerNumber = num; VMValue params[2] = { (DStaticEventHandler*)this, e }; GlobalVMStack.Call(func, params, 2, nullptr, 0, nullptr); diff --git a/src/events.h b/src/events.h index 130f2eb17..05bda85c7 100755 --- a/src/events.h +++ b/src/events.h @@ -42,7 +42,7 @@ void E_WorldTick(); // called on each render frame once. void E_RenderFrame(); // this executes when a player enters the level (once). PlayerEnter+inhub = RETURN -void E_PlayerEntered(int num); +void E_PlayerEntered(int num, bool fromhub); // this executes when a player respawns. includes resurrect cheat. void E_PlayerRespawned(int num); // this executes when a player dies (partially duplicating worldthingdied, but whatever) @@ -112,7 +112,7 @@ public: virtual void RenderFrame(); // - virtual void PlayerEntered(int num); + virtual void PlayerEntered(int num, bool fromhub); virtual void PlayerRespawned(int num); virtual void PlayerDied(int num); virtual void PlayerDisconnected(int num); diff --git a/src/g_game.cpp b/src/g_game.cpp index e5c327472..ef864fdb0 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -91,6 +91,7 @@ #include "g_hub.h" #include "g_levellocals.h" +#include "events.h" static FRandom pr_dmspawn ("DMSpawn"); @@ -1791,6 +1792,8 @@ void G_DoPlayerPop(int playernum) // [RH] Make the player disappear FBehavior::StaticStopMyScripts(players[playernum].mo); + // [ZZ] fire player disconnect hook + E_PlayerDisconnected(playernum); // [RH] Let the scripts know the player left FBehavior::StaticStartTypedScripts(SCRIPT_Disconnect, players[playernum].mo, true, playernum, true); if (players[playernum].mo != NULL) diff --git a/src/g_level.cpp b/src/g_level.cpp index 55e6c1140..fa6e20ab5 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1256,6 +1256,10 @@ void G_FinishTravel () FPlayerStart *start; int pnum; + // + APlayerPawn* pawns[MAXPLAYERS]; + int pawnsnum = 0; + next = it.Next (); while ( (pawn = next) != NULL) { @@ -1347,16 +1351,30 @@ void G_FinishTravel () { pawn->Speed = pawn->GetDefault()->Speed; } - if (level.FromSnapshot) - { - FBehavior::StaticStartTypedScripts (SCRIPT_Return, pawn, true); - } + // [ZZ] we probably don't want to fire any scripts before all players are in, especially with runNow = true. + pawns[pawnsnum++] = pawn; } + // [ZZ] fire the reopen hook. if (level.FromSnapshot) { // [Nash] run REOPEN scripts upon map re-entry FBehavior::StaticStartTypedScripts(SCRIPT_Reopen, NULL, false); + + for (int i = 0; i < pawnsnum; i++) + { + // [ZZ] fire the enter hook. + E_PlayerEntered(pawns[i]->player - players, true); + // + FBehavior::StaticStartTypedScripts(SCRIPT_Return, pawns[i], true); + } + } + else + { + for (int i = 0; i < pawnsnum; i++) + { + E_PlayerEntered(pawns[i]->player - players, false); + } } bglobal.FinishTravel (); diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index b9c72e128..24b37a56a 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -610,6 +610,9 @@ void AActor::Die (AActor *source, AActor *inflictor, int dmgflags) // [RH] Death messages ClientObituary (this, inflictor, source, dmgflags); + // [ZZ] fire player death hook + E_PlayerDied(player - players); + // Death script execution, care of Skull Tag FBehavior::StaticStartTypedScripts (SCRIPT_Death, this, true);