From d432df55e9be1d56f98a1b3e8b5966aeecae4e3a Mon Sep 17 00:00:00 2001
From: Christoph Oelckers <coelckers@zdoom.fake>
Date: Tue, 5 Jan 2016 15:37:59 +0100
Subject: [PATCH] - changed Sector_SetDamage so that it can explicitly set the
 damage interval and the leakiness probability, instead of hardcoding it to
 fixed damage ranges. - fixed: FCajunMaster::IsDangerous did not check for
 Heretic's sludge type.

---
 src/b_move.cpp     |  3 ++-
 src/p_3dfloors.cpp |  2 +-
 src/p_lnspec.cpp   | 26 +++++++++++++++++++++++---
 src/p_saveg.cpp    | 32 ++++++++++++++++++++++++++++----
 src/p_spec.cpp     | 39 +++++++++++++++++++++------------------
 src/p_user.cpp     |  2 +-
 src/r_defs.h       |  8 +++++---
 src/version.h      |  2 +-
 8 files changed, 82 insertions(+), 32 deletions(-)

diff --git a/src/b_move.cpp b/src/b_move.cpp
index fd0405457..2a76f1925 100644
--- a/src/b_move.cpp
+++ b/src/b_move.cpp
@@ -357,7 +357,7 @@ bool FCajunMaster::IsDangerous (sector_t *sec)
 	int special;
 
 	return
-		   sec->damage
+		   sec->damageamount
 		|| sec->special & DAMAGE_MASK
 		|| (special = sec->special & 0xff, special == dLight_Strobe_Hurt)
 		|| special == dDamage_Hellslime
@@ -367,6 +367,7 @@ bool FCajunMaster::IsDangerous (sector_t *sec)
 		|| special == dDamage_LavaWimpy
 		|| special == dDamage_LavaHefty
 		|| special == dScroll_EastLavaDamage
+		|| special == hDamage_Sludge
 		|| special == sLight_Strobe_Hurt
 		|| special == Damage_InstantDeath
 		|| special == sDamage_SuperHellslime;
diff --git a/src/p_3dfloors.cpp b/src/p_3dfloors.cpp
index 5b29959cb..6af26652f 100644
--- a/src/p_3dfloors.cpp
+++ b/src/p_3dfloors.cpp
@@ -342,7 +342,7 @@ void P_PlayerOnSpecial3DFloor(player_t* player)
 		}
 
 		// Apply sector specials
-		if (rover->model->special || rover->model->damage)
+		if (rover->model->special || rover->model->damageamount)
 			P_PlayerInSpecialSector(player, rover->model);
 
 		// Apply flat specials (using the ceiling!)
diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp
index 9b38e149b..fb9858bc2 100644
--- a/src/p_lnspec.cpp
+++ b/src/p_lnspec.cpp
@@ -2246,7 +2246,7 @@ FUNC(LS_PointPush_SetForce)
 }
 
 FUNC(LS_Sector_SetDamage)
-// Sector_SetDamage (tag, amount, mod)
+// Sector_SetDamage (tag, amount, mod, interval, leaky)
 {
 	// The sector still stores the mod in its old format because
 	// adding an FName to the sector_t structure might cause
@@ -2257,8 +2257,28 @@ FUNC(LS_Sector_SetDamage)
 	int secnum;
 	while ((secnum = itr.Next()) >= 0)
 	{
-		sectors[secnum].damage = arg1;
-		sectors[secnum].mod = arg2;
+		if (arg3 <= 0)	// emulate old and hacky method to handle leakiness.
+		{
+			if (arg1 < 20)
+			{
+				arg4 = 0;
+				arg3 = 32;
+			}
+			else if (arg1 < 50)
+			{
+				arg4 = 5;
+				arg3 = 32;
+			}
+			else
+			{
+				arg4 = 256;
+				arg3 = 1;
+			}
+		}
+		sectors[secnum].damageamount = (short)arg1;
+		sectors[secnum].damagemod = (short)arg2;
+		sectors[secnum].damageinterval = (short)arg3;
+		sectors[secnum].leakydamage = (short)arg4;
 	}
 	return true;
 }
diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp
index 480494320..462c1e757 100644
--- a/src/p_saveg.cpp
+++ b/src/p_saveg.cpp
@@ -354,7 +354,7 @@ void P_SerializeWorld (FArchive &arc)
 			short tag;
 			arc << tag;
 		}
-		arc	<< sec->soundtraversed
+		arc << sec->soundtraversed
 			<< sec->seqType
 			<< sec->friction
 			<< sec->movefactor
@@ -369,9 +369,33 @@ void P_SerializeWorld (FArchive &arc)
 			<< sec->heightsec
 			<< sec->bottommap << sec->midmap << sec->topmap
 			<< sec->gravity
-			<< sec->damage
-			<< sec->mod
-			<< sec->SoundTarget
+			<< sec->damageamount
+			<< sec->damagemod;
+		if (SaveVersion >= 4528)
+		{
+			arc << sec->damageinterval
+				<< sec->leakydamage;
+		}
+		else
+		{
+			if (sec->damageamount < 20)
+			{
+				sec->leakydamage = 0;
+				sec->damageinterval = 32;
+			}
+			else if (sec->damageamount < 50)
+			{
+				sec->leakydamage = 5;
+				sec->damageinterval = 32;
+			}
+			else
+			{
+				sec->leakydamage = 256;
+				sec->damageinterval = 1;
+			}
+		}
+
+		arc	<< sec->SoundTarget
 			<< sec->SecActTarget
 			<< sec->sky
 			<< sec->MoreFlags
diff --git a/src/p_spec.cpp b/src/p_spec.cpp
index 95995bdab..e0b11dd7e 100644
--- a/src/p_spec.cpp
+++ b/src/p_spec.cpp
@@ -566,24 +566,11 @@ void P_PlayerInSpecialSector (player_t *player, sector_t * sector)
 	}
 
 	// [RH] Apply any customizable damage
-	if (sector->damage)
+	if (sector->damageamount != 0)
 	{
-		if (sector->damage < 20)
+		if (level.time % sector->damageinterval == 0 && (ironfeet == NULL || pr_playerinspecialsector() < sector->leakydamage))
 		{
-			if (ironfeet == NULL && !(level.time&0x1f))
-				P_DamageMobj (player->mo, NULL, NULL, sector->damage, MODtoDamageType (sector->mod));
-		}
-		else if (sector->damage < 50)
-		{
-			if ((ironfeet == NULL || (pr_playerinspecialsector()<5))
-				 && !(level.time&0x1f))
-			{
-				P_DamageMobj (player->mo, NULL, NULL, sector->damage, MODtoDamageType (sector->mod));
-			}
-		}
-		else
-		{
-			P_DamageMobj (player->mo, NULL, NULL, sector->damage, MODtoDamageType (sector->mod));
+			P_DamageMobj (player->mo, NULL, NULL, sector->damageamount, MODtoDamageType (sector->damagemod));
 		}
 	}
 
@@ -1450,8 +1437,24 @@ void P_SpawnSpecials (void)
 					FSectorTagIterator itr(lines[i].args[0]);
 					while ((s = itr.Next()) >= 0)
 					{
-						sectors[s].damage = damage;
-						sectors[s].mod = 0;//MOD_UNKNOWN;
+						sector_t *sec = &sectors[s];
+						sec->damageamount = damage;
+						sec->damagemod = 0;//MOD_UNKNOWN;
+						if (sec->damageamount < 20)
+						{
+							sec->leakydamage = 0;
+							sec->damageinterval = 32;
+						}
+						else if (sec->damageamount < 50)
+						{
+							sec->leakydamage = 5;
+							sec->damageinterval = 32;
+						}
+						else
+						{
+							sec->leakydamage = 256;
+							sec->damageinterval = 1;
+						}
 					}
 				}
 				break;
diff --git a/src/p_user.cpp b/src/p_user.cpp
index 1eb838176..8f8a93fdb 100644
--- a/src/p_user.cpp
+++ b/src/p_user.cpp
@@ -2538,7 +2538,7 @@ void P_PlayerThink (player_t *player)
 	if (!(player->cheats & CF_PREDICTING))
 	{
 		P_PlayerOnSpecial3DFloor (player);
-		if (player->mo->Sector->special || player->mo->Sector->damage)
+		if (player->mo->Sector->special || player->mo->Sector->damageamount != 0)
 		{
 			P_PlayerInSpecialSector (player);
 		}
diff --git a/src/r_defs.h b/src/r_defs.h
index b741b5f6b..2360328e6 100644
--- a/src/r_defs.h
+++ b/src/r_defs.h
@@ -709,9 +709,11 @@ struct sector_t
 	// thinglist is a subset of touching_thinglist
 	struct msecnode_t *touching_thinglist;				// phares 3/14/98
 
-	float gravity;		// [RH] Sector gravity (1.0 is normal)
-	short damage;		// [RH] Damage to do while standing on floor
-	short mod;			// [RH] Means-of-death for applied damage
+	float gravity;			// [RH] Sector gravity (1.0 is normal)
+	short damageamount;			// [RH] Damage to do while standing on floor
+	short damagemod;		// [RH] Means-of-death for applied damage
+	short damageinterval;	// Interval for damage application
+	short leakydamage;		// chance of leaking through radiation suit
 
 	WORD ZoneNumber;	// [RH] Zone this sector belongs to
 	WORD MoreFlags;		// [RH] Internal sector flags
diff --git a/src/version.h b/src/version.h
index 682c5165e..d7026786e 100644
--- a/src/version.h
+++ b/src/version.h
@@ -76,7 +76,7 @@ const char *GetVersionString();
 
 // Use 4500 as the base git save version, since it's higher than the
 // SVN revision ever got.
-#define SAVEVER 4527
+#define SAVEVER 4528
 
 #define SAVEVERSTRINGIFY2(x) #x
 #define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)