# HG changeset patch
# User Ru5tK1ng
# Date 1705647410 21600
#      Fri Jan 19 00:56:50 2024 -0600
# Branch keyfixes2
# Node ID 9b82ce937ea52cad1520e1e1ca3c5b4d0e43f75b
# Parent  f46ab13b972a3a2ffbd7baf2e88c43a1828ce7af
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 f46ab13b972a -r 9b82ce937ea5 docs/zandronum-history.txt
--- a/docs/zandronum-history.txt	Fri Sep 29 08:23:34 2023 -0400
+++ b/docs/zandronum-history.txt	Fri Jan 19 00:56:50 2024 -0600
@@ -114,6 +114,7 @@
 -	- 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: Monsters spawned by BossBrain cubes would move before being spawned on the clients therefore triggering warning messages (addresses 2655). [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 f46ab13b972a -r 9b82ce937ea5 src/d_dehacked.cpp
--- a/src/d_dehacked.cpp	Fri Sep 29 08:23:34 2023 -0400
+++ b/src/d_dehacked.cpp	Fri Jan 19 00:56:50 2024 -0600
@@ -3197,3 +3197,8 @@
 	Super::Serialize(arc);
 	arc << droppedbymonster;
 }
+
+AInventory* ADehackedPickup::GetRealPickup()
+{
+		return RealPickup;
+}
\ No newline at end of file
diff -r f46ab13b972a -r 9b82ce937ea5 src/d_dehacked.h
--- a/src/d_dehacked.h	Fri Sep 29 08:23:34 2023 -0400
+++ b/src/d_dehacked.h	Fri Jan 19 00:56:50 2024 -0600
@@ -54,6 +54,8 @@
 	AInventory *RealPickup;
 public:
 	bool droppedbymonster;
+// [RK] Accessor
+	AInventory* GetRealPickup();
 };
 
 int D_LoadDehLumps();
diff -r f46ab13b972a -r 9b82ce937ea5 src/g_level.cpp
--- a/src/g_level.cpp	Fri Sep 29 08:23:34 2023 -0400
+++ b/src/g_level.cpp	Fri Jan 19 00:56:50 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 f46ab13b972a -r 9b82ce937ea5 src/g_shared/a_pickups.cpp
--- a/src/g_shared/a_pickups.cpp	Fri Sep 29 08:23:34 2023 -0400
+++ b/src/g_shared/a_pickups.cpp	Fri Jan 19 00:56:50 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 f46ab13b972a -r 9b82ce937ea5 src/survival.cpp
--- a/src/survival.cpp	Fri Sep 29 08:23:34 2023 -0400
+++ b/src/survival.cpp	Fri Jan 19 00:56:50 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 )
