# HG changeset patch
# User Ru5tK1ng
# Date 1705374484 21600
#      Mon Jan 15 21:08:04 2024 -0600
# Branch keyfixes
# Node ID 146a9dad37eb5b00244baf632a233f0a8de15412
# Parent  17757ad8e820f40edf930d64f27b5641c62d1fa6
Fixed: ShareKeys was not working properly with dehacked keys, with puzzle items, in hubs and would ignore losekeys when maps didn't reset in survival (addresses 4183).

diff -r 17757ad8e820 -r 146a9dad37eb docs/zandronum-history.txt
--- a/docs/zandronum-history.txt	Thu Jan 04 17:01:19 2024 -0600
+++ b/docs/zandronum-history.txt	Mon Jan 15 21:08:04 2024 -0600
@@ -111,6 +111,7 @@
 -	- Fixed: opening the text scaling menu sometimes changed the user's con_virtualwidth and/or con_virtualheight CVars when it shouldn't. [Kaminsky]
 -	- Fixed: the coop info wasn't getting drawn in clientside demos. [Kaminsky]
 -	- Fixed: Floatbob items having incorrect z-height after a map reset and glitchy GL floor clipping (addresses 2361). [Ru5tK1ng]
+-   - Fixed: ShareKeys was not working properly with dehacked keys, with puzzle items, in hubs and would ignore losekeys when maps didn't reset in survival (addresses 4183). [Ru5tK1ng]
 !	- The result value of GAMEEVENT_MEDALS event scripts can now be used to determine whether or not the player receives the medal. [Kaminsky]
 !	- GAMEMODE flags are now validated after all GAMEMODE lumps have been parsed instead of after each one. The internal game mode name (e.g. "TeamLMS") is now printed with the error message instead of the actual name. [Kaminsky]
 !	- Added an extra check to ensure that game modes have a (short) name. [Kaminsky]
diff -r 17757ad8e820 -r 146a9dad37eb src/d_dehacked.cpp
--- a/src/d_dehacked.cpp	Thu Jan 04 17:01:19 2024 -0600
+++ b/src/d_dehacked.cpp	Mon Jan 15 21:08:04 2024 -0600
@@ -3197,3 +3197,9 @@
 	Super::Serialize(arc);
 	arc << droppedbymonster;
 }
+
+AInventory* ADehackedPickup::GetRealPickup()
+{
+	if ( RealPickup != NULL )
+		return RealPickup;
+}
\ No newline at end of file
diff -r 17757ad8e820 -r 146a9dad37eb src/d_dehacked.h
--- a/src/d_dehacked.h	Thu Jan 04 17:01:19 2024 -0600
+++ b/src/d_dehacked.h	Mon Jan 15 21:08:04 2024 -0600
@@ -54,6 +54,8 @@
 	AInventory *RealPickup;
 public:
 	bool droppedbymonster;
+// [RK] Accessor
+	AInventory* GetRealPickup();
 };
 
 int D_LoadDehLumps();
diff -r 17757ad8e820 -r 146a9dad37eb src/g_level.cpp
--- a/src/g_level.cpp	Thu Jan 04 17:01:19 2024 -0600
+++ b/src/g_level.cpp	Mon Jan 15 21:08:04 2024 -0600
@@ -1306,7 +1306,9 @@
 		teamplay = false;
 
 	// [Dusk] Clear keys found
-	g_keysFound.Clear();
+	// [RK] Since PuzzleItems are tracked don't do this for hubs.
+	if( !( level.clusterflags & CLUSTER_HUB ) || autosave == false ) // Resets with map command
+		g_keysFound.Clear();
 
 	// [BC] In server mode, display the level name slightly differently.
 	if ( NETWORK_GetState( ) == NETSTATE_SERVER )
diff -r 17757ad8e820 -r 146a9dad37eb src/g_shared/a_pickups.cpp
--- a/src/g_shared/a_pickups.cpp	Thu Jan 04 17:01:19 2024 -0600
+++ b/src/g_shared/a_pickups.cpp	Mon Jan 15 21:08:04 2024 -0600
@@ -34,6 +34,7 @@
 #include "cooperative.h"
 #include "p_acs.h"
 #include "a_keys.h"
+#include "d_dehacked.h"
 
 static FRandom pr_restore ("RestorePos");
 
@@ -1088,6 +1089,7 @@
 void AInventory::Touch (AActor *toucher)
 {
 	AInventory	*pInventory;
+	ADehackedPickup *realitem = NULL;
 
 	// [BC] If this item was a bot's goal item, and it's reaching it, let the bot know that.
 	if ( toucher->player && toucher->player->pSkullBot )
@@ -1212,7 +1214,12 @@
 	}
 
 	// [RH] Execute an attached special (if any)
-	DoPickupSpecial (toucher);
+	// [RK] Do the special later for Dehacked pickups since it
+	// destorys the real pickup which we'll need for a bit more
+	if( GetClass()->IsDescendantOf( RUNTIME_CLASS( ADehackedPickup )))
+		realitem = static_cast< ADehackedPickup* >(this);
+	else
+		DoPickupSpecial (toucher);
 
 	// [BC] If this item was spawned from an invasion spot, tell the spot that the item
 	// it spawned has been picked up.
@@ -1268,16 +1275,22 @@
 	// we store the key as having been found even if shared keys is off. This
 	// way the server still remembers what keys were found and begins sharing
 	// them when sv_sharekeys is toggled on.
-	if (( NETWORK_GetState( ) == NETSTATE_SERVER ) &&
-		( IsKindOf( RUNTIME_CLASS( AKey ))) &&
-		( toucher->player != NULL ))
+	if (( NETWORK_GetState( ) == NETSTATE_SERVER ) && (toucher->player != NULL) &&
+		( IsKindOf( RUNTIME_CLASS( AKey )) ||
+		GetClass()->ActorInfo->GetReplacee()->Class->IsDescendantOf( RUNTIME_CLASS( AKey )) || // [RK] Dehacked item replaces this class
+		GetClass()->IsDescendantOf( RUNTIME_CLASS( APuzzleItem )))) // Hexen Puzzle items
 	{
 		// [Dusk] Check if the key has not been picked up yet.
 		bool pickedup = false;
 
 		for ( unsigned int i = 0; i < g_keysFound.Size(); ++i )
 		{
-			if ( g_keysFound[i] == GetClass()->getActorNetworkIndex() )
+			if( realitem != NULL && g_keysFound[i] == realitem->GetRealPickup()->GetClass()->getActorNetworkIndex() )
+			{
+					pickedup = true;
+					break;
+				}
+			else if ( g_keysFound[i] == GetClass()->getActorNetworkIndex() )
 			{
 				pickedup = true;
 				break;
@@ -1289,13 +1302,17 @@
 			// [Dusk] Store this key as having been found. For some reason
 			// storing the raw PClass pointer crashes Zandronum when sharing
 			// the keys later on so we store the actor network index instead.
-			g_keysFound.Push( GetClass()->getActorNetworkIndex() );
+			// [RK] For DEHACKED pickups we'll use the real pickup's index
+			if ( realitem != NULL)
+				g_keysFound.Push( realitem->GetRealPickup()->GetClass()->getActorNetworkIndex( ) );
+			else
+				g_keysFound.Push( GetClass()->getActorNetworkIndex() );
 
 			if ( zadmflags & ZADF_SHARE_KEYS )
 			{
 				// [Dusk] Announcement message
-				SERVER_Printf( TEXTCOLOR_GREEN "%s" TEXTCOLOR_NORMAL " has found the " TEXTCOLOR_GOLD "%s!\n",
-					toucher->player->userinfo.GetName(), GetTag() );
+				SERVER_Printf(TEXTCOLOR_GREEN "%s" TEXTCOLOR_NORMAL " has found the " TEXTCOLOR_GOLD "%s!\n",
+					toucher->player->userinfo.GetName(), (realitem ? realitem->GetRealPickup()->GetTag() : GetTag( )));
 
 				// [Dusk] Audio cue - skip the player picking the key because he
 				// hears the pickup sound from the original key. The little *bloop*
@@ -1311,6 +1328,8 @@
 			}
 		}
 	}
+	if (realitem != NULL)
+		DoPickupSpecial(toucher);
 }
 
 //===========================================================================
diff -r 17757ad8e820 -r 146a9dad37eb src/survival.cpp
--- a/src/survival.cpp	Thu Jan 04 17:01:19 2024 -0600
+++ b/src/survival.cpp	Mon Jan 15 21:08:04 2024 -0600
@@ -274,7 +274,9 @@
 	SURVIVAL_SetState( SURVS_INPROGRESS );
 
 	// Share keys so that resurrected dead spectators can get them.
-	SERVER_SyncSharedKeys( MAXPLAYERS, false );
+	// [RK] Except if we're supposed to lose keys
+	if( !(dmflags & DF_COOP_LOSE_KEYS) )
+		SERVER_SyncSharedKeys( MAXPLAYERS, false );
 }
 
 void SURVIVAL_RestartMission( void )
