From ea697d20486f3c8b513aa4a94e4a4f4a1060c404 Mon Sep 17 00:00:00 2001
From: James R <justsomejames2@gmail.com>
Date: Wed, 22 Nov 2023 18:52:30 -0800
Subject: [PATCH] Physics changes for players in ice cube state

- Cancel offroad
- Inputs do not work
  - Cannot accelerate
  - Drift/Brake does not work (side-effect of P_PlayerInPain)
- Sprite shakes if icecube.shaketimer
- Sprite is colorized Cyan
- Max friction (slippery)
- Player is considered to be in a pain state
- Sprite slowly turns clockwise
- Sprite tilting is disabled
---
 src/k_kart.c | 29 +++++++++++++++++++++++++----
 src/p_user.c | 11 +++++++++--
 2 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/src/k_kart.c b/src/k_kart.c
index c66f58f413..61701a9188 100644
--- a/src/k_kart.c
+++ b/src/k_kart.c
@@ -1168,7 +1168,8 @@ static void K_UpdateOffroad(player_t *player)
 	fixed_t offroadstrength = 0;
 
 	// If tiregrease is active, don't
-	if (player->tiregrease == 0)
+	// If inside an ice cube, don't
+	if (player->tiregrease == 0 && player->icecube.frozen == false)
 	{
 		// TODO: Make this use actual special touch code.
 		if (terrain != NULL && terrain->offroad > 0)
@@ -3599,6 +3600,7 @@ SINT8 K_GetForwardMove(player_t *player)
 	}
 
 	if (player->spinouttimer != 0
+		|| player->icecube.frozen
 		|| K_PressingEBrake(player) == true
 		|| K_PlayerEBrake(player) == true)
 	{
@@ -8865,6 +8867,15 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
 	K_HandleDelayedHitByEm(player);
 
 	player->pflags &= ~PF_POINTME;
+
+	if (player->icecube.frozen && player->icecube.shaketimer)
+	{
+		player->mo->sprxoff += P_RandomRange(PR_DECORATION, -4, 4) * player->mo->scale;
+		player->mo->spryoff += P_RandomRange(PR_DECORATION, -4, 4) * player->mo->scale;
+		player->mo->sprzoff += P_RandomRange(PR_DECORATION, -4, 4) * player->mo->scale;
+
+		player->icecube.shaketimer--;
+	}
 }
 
 void K_KartResetPlayerColor(player_t *player)
@@ -8953,12 +8964,17 @@ void K_KartResetPlayerColor(player_t *player)
 		fullbright = true;
 		goto finalise;
 	}
-	else
+
+	if (player->icecube.frozen)
 	{
-		player->mo->colorized = (player->dye != 0);
-		player->mo->color = player->dye ? player->dye : player->skincolor;
+		player->mo->colorized = true;
+		player->mo->color = SKINCOLOR_CYAN;
+		goto finalise;
 	}
 
+	player->mo->colorized = (player->dye != 0);
+	player->mo->color = player->dye ? player->dye : player->skincolor;
+
 finalise:
 
 	if (player->curshield && player->curshield != KSHIELD_TOP)
@@ -11233,6 +11249,11 @@ void K_AdjustPlayerFriction(player_t *player)
 			player->mo->friction -= 9824;
 	}
 
+	if (player->icecube.frozen)
+	{
+		player->mo->friction = FRACUNIT;
+	}
+
 	// Cap between intended values
 	if (player->mo->friction > FRACUNIT)
 		player->mo->friction = FRACUNIT;
diff --git a/src/p_user.c b/src/p_user.c
index 2bf8b81933..3f9540ba39 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -461,7 +461,7 @@ UINT8 P_FindHighestLap(void)
 //
 boolean P_PlayerInPain(player_t *player)
 {
-	if (player->spinouttimer || (player->tumbleBounces > 0) || (player->pflags & PF_FAULT))
+	if (player->spinouttimer || (player->tumbleBounces > 0) || (player->pflags & PF_FAULT) || player->icecube.frozen)
 		return true;
 
 	return false;
@@ -2420,7 +2420,14 @@ void P_MovePlayer(player_t *player)
 	}
 
 	// Kart frames
-	if (player->tumbleBounces > 0)
+	if (player->icecube.frozen)
+	{
+		INT32 spd = FixedMul(player->mo->scale, FixedHypot(player->mo->momx, player->mo->momy)) / FRACUNIT;
+		P_SetPlayerMobjState(player->mo, S_KART_SPINOUT);
+		player->drawangle -= max(2, spd / 6) * ANG1;
+		P_ResetPitchRoll(player->mo);
+	}
+	else if (player->tumbleBounces > 0)
 	{
 		fixed_t playerSpeed = P_AproxDistance(player->mo->momx, player->mo->momy); // maybe momz too?
 
-- 
GitLab