--- /dev/null
+//these files can be moved but while CTS Cup is WIP I'll keep them in CTS Cup's gamemode folder
+//files to update if moving: sv_ctscup.qh, ctscup folder's _mod files
+
+#include "savestate.qh"
+
+void SaveSaveState(entity player)
+{
+ if (player.savestate)
+ {
+ player.savestate.origin = player.origin;
+ player.savestate.v_angle = player.v_angle;
+ player.savestate.angles = player.angles;
+ player.savestate.velocity = player.velocity;
+ //SetResource(player.savestate, RES_ROCKETS, GetResource(player, RES_ROCKETS));
+ //SetResource(player.savestate, RES_BULLETS, GetResource(player, RES_BULLETS));
+ //SetResource(player.savestate, RES_CELLS, GetResource(player, RES_CELLS));
+ //SetResource(player.savestate, RES_PLASMA, GetResource(player, RES_PLASMA));
+ //SetResource(player.savestate, RES_SHELLS, GetResource(player, RES_SHELLS));
+ //SetResource(player.savestate, RES_FUEL, GetResource(player, RES_FUEL));
+ //SetResource(player.savestate, RES_HEALTH, max(1, GetResource(player, RES_HEALTH)));
+ //SetResource(player.savestate, RES_ARMOR, GetResource(player, RES_ARMOR));
+ //STAT(WEAPONS, player.savestate) = STAT(WEAPONS, player);
+ //StatusEffects_copy(player.statuseffects, player.savestate, 0);
+ player.savestate.items = player.items;
+ player.savestate.pauserotarmor_finished = player.pauserotarmor_finished;
+ player.savestate.pauserothealth_finished = player.pauserothealth_finished;
+ player.savestate.pauserotfuel_finished = player.pauserotfuel_finished;
+ player.savestate.pauseregen_finished = player.pauseregen_finished;
+ player.savestate.teleport_time = time;
+ }
+}
+
+bool LoadSaveState(entity player)
+{
+ if (player.savestate)
+ {
+ player.origin = player.savestate.origin;
+ player.v_angle = player.savestate.v_angle;
+ player.angles = player.savestate.angles;
+ player.fixangle = true;
+ player.velocity = player.savestate.velocity;
+ //SetResource(player, RES_ROCKETS, GetResource(player.savestate, RES_ROCKETS));
+ //SetResource(player, RES_BULLETS, GetResource(player.savestate, RES_BULLETS));
+ //SetResource(player, RES_CELLS, GetResource(player.savestate, RES_CELLS));
+ //SetResource(player, RES_PLASMA, GetResource(player.savestate, RES_PLASMA));
+ //SetResource(player, RES_SHELLS, GetResource(player.savestate, RES_SHELLS));
+ //SetResource(player, RES_FUEL, GetResource(player.savestate, RES_FUEL));
+ //SetResource(player, RES_HEALTH, GetResource(player.savestate, RES_HEALTH));
+ //SetResource(player, RES_ARMOR, GetResource(player.savestate, RES_ARMOR));
+ //STAT(WEAPONS, player) = STAT(WEAPONS, player.savestate);
+ //StatusEffects_copy(player.savestate, player.statuseffects, player.savestate.teleport_time);
+ //StatusEffects_update(player);
+ player.items = player.savestate.items;
+ player.pauserotarmor_finished = time + player.savestate.pauserotarmor_finished - player.savestate.teleport_time;
+ player.pauserothealth_finished = time + player.savestate.pauserothealth_finished - player.savestate.teleport_time;
+ player.pauserotfuel_finished = time + player.savestate.pauserotfuel_finished - player.savestate.teleport_time;
+ player.pauseregen_finished = time + player.savestate.pauseregen_finished - player.savestate.teleport_time;
+
+ return true;
+ }
+ return false;
+}
+
+void DeleteSaveState(entity player)
+{
+ if (player.savestate)
+ delete(player.savestate);
+}
+
MUTATOR_HOOKFUNCTION(ctscup, PlayerSpawn)
{
entity player = M_ARGV(0, entity);
- entity spawn_spot = M_ARGV(1, entity);
+ //entity spawn_spot = M_ARGV(1, entity);
+ //player.race_place = 0;
- if(spawn_spot.target == "")
- // Emergency: this wasn't a real spawnpoint. Can this ever happen?
- race_PreparePlayer(player);
-
- // if we need to respawn, do it right
- player.race_respawn_checkpoint = player.race_checkpoint;
- player.race_respawn_spotref = spawn_spot;
+ player.tournamentParticipant = true;
- player.race_place = 0;
+ // only spectators and connecting players do not have a savestate so here:
+ // newly connected player has spawned for the first time
+ // or during warmup a player who was spectating has joined (back)
+ // and as they're now a participant they're given a savestate
+ if (player.savestate == NULL)
+ {
+ player.savestate = new_pure(savestate);
+ SaveSaveState(player);
+ }
- player.tournamentParticipant = true;
+ // upon spawning for a new round within 1s of the round starting, save a savestate
+ if ((time - 1) < (round_handler_GetEndTime() - autocvar_g_ctscup_maxroundlength))
+ {
+ SaveSaveState(player);
+ }
+ // if somehow dying during a round and respawning, load last savestate
+ else
+ {
+ LoadSaveState(player);
+ }
}
MUTATOR_HOOKFUNCTION(ctscup, MakePlayerObserver)
race_PreparePlayer(player);
player.race_checkpoint = -1;
+
+ DeleteSaveState(player);
}
MUTATOR_HOOKFUNCTION(ctscup, Race_FinalCheckpoint)
//if(autocvar_g_cts_finish_kill_delay)
// ClientKill_Silent(player, autocvar_g_cts_finish_kill_delay);
- // clear savestate
-
if (roundFirstFinisherTime == 0 && tournamentStarted) roundFirstFinisherTime = time;
}
entity frag_target = M_ARGV(2, entity);
float frag_deathtype = M_ARGV(3, float);
float frag_damage = M_ARGV(4, float);
+ vector frag_force = M_ARGV(7, vector);
if((frag_target == frag_attacker || frag_deathtype == DEATH_FALL.m_id) && !autocvar_g_cts_selfdamage)
{
frag_damage = 0;
+ frag_force = '0 0 0';
M_ARGV(4, float) = frag_damage;
+ M_ARGV(6, vector) = frag_force;
}
// if the player were to be about to die, try to save them and restore a loadstate if possible
-// else if (IS_PLAYER(frag_target))
-// if (((GetResource(frag_target, RES_HEALTH) + GetResource(frag_target, RES_ARMOR)) - frag_damage) <= 0)
-// if (LoadSaveState(frag_target))
-// {
+ else if (IS_PLAYER(frag_target))
+ if (((GetResource(frag_target, RES_HEALTH) + GetResource(frag_target, RES_ARMOR)) - frag_damage) <= 0)
+ if (LoadSaveState(frag_target))
+ {
// if savestate loading was successful
// try to cheat death by offsetting the incoming damage
-// frag_damage = 0;
-// M_ARGV(4, float) = frag_damage;
-// }
+ frag_damage = 0;
+ frag_force = '0 0 0';
+ M_ARGV(4, float) = frag_damage;
+ M_ARGV(6, vector) = frag_force;
+ }
}