]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
implement savestates
authordrjaska <drjaska83@gmail.com>
Sat, 7 May 2022 10:08:47 +0000 (13:08 +0300)
committerdrjaska <drjaska83@gmail.com>
Sat, 7 May 2022 10:08:47 +0000 (13:08 +0300)
currently there's an import dependency issue which disables saving and loading a bunch of things

qcsrc/common/gamemodes/gamemode/ctscup/_mod.inc
qcsrc/common/gamemodes/gamemode/ctscup/_mod.qh
qcsrc/common/gamemodes/gamemode/ctscup/savestate.qc [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/ctscup/savestate.qh [new file with mode: 0644]
qcsrc/common/gamemodes/gamemode/ctscup/sv_ctscup.qc
qcsrc/common/gamemodes/gamemode/ctscup/sv_ctscup.qh

index 89d6a2c7a48ba0a69b2c2e0df4cc25bb5b1fd72f..d57a6255ec95c682479ab6e2892f6fb743392695 100644 (file)
@@ -6,3 +6,4 @@
 #ifdef SVQC
     #include <common/gamemodes/gamemode/ctscup/sv_ctscup.qc>
 #endif
+#include <common/gamemodes/gamemode/ctscup/savestate.qc>
index e9459a01769fddc2fdaeb0472810819d9ccd4815..6c08b79f42c6bdb1d428f56d61669a32e694bcf9 100644 (file)
@@ -6,3 +6,4 @@
 #ifdef SVQC
     #include <common/gamemodes/gamemode/ctscup/sv_ctscup.qh>
 #endif
+#include <common/gamemodes/gamemode/ctscup/savestate.qh>
diff --git a/qcsrc/common/gamemodes/gamemode/ctscup/savestate.qc b/qcsrc/common/gamemodes/gamemode/ctscup/savestate.qc
new file mode 100644 (file)
index 0000000..e07c55e
--- /dev/null
@@ -0,0 +1,69 @@
+//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);
+}
+
diff --git a/qcsrc/common/gamemodes/gamemode/ctscup/savestate.qh b/qcsrc/common/gamemodes/gamemode/ctscup/savestate.qh
new file mode 100644 (file)
index 0000000..eac6517
--- /dev/null
@@ -0,0 +1,21 @@
+//#include <common/resources/cl_resources.qh>
+//#include <common/mutators/mutator/status_effects/status_effects.qh>
+//#include <lib/stats.qh>
+
+.entity savestate;
+
+void SaveSaveState(entity player);
+bool LoadSaveState(entity player);
+void DeleteSaveState(entity player);
+
+.vector origin;
+.vector v_angle;
+.vector angles;
+.bool fixangle;
+.vector velocity;
+.float items;
+.float pauserotarmor_finished;
+.float pauserothealth_finished;
+.float pauserotfuel_finished;
+.float pauseregen_finished;
+.float teleport_time;
index 9c080d2d64f8869b66b7c9225876b472cfc64a45..f801ebb4c623303f39da8a8863ec11ac3d46b885 100644 (file)
@@ -272,19 +272,31 @@ float autocvar_g_ctscup_maxroundlength; //round length unless it ends prematurel
 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)
@@ -295,6 +307,8 @@ MUTATOR_HOOKFUNCTION(ctscup, MakePlayerObserver)
 
        race_PreparePlayer(player);
        player.race_checkpoint = -1;
+
+       DeleteSaveState(player);
 }
 
 MUTATOR_HOOKFUNCTION(ctscup, Race_FinalCheckpoint)
@@ -305,8 +319,6 @@ 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;
 }
 
@@ -316,22 +328,27 @@ MUTATOR_HOOKFUNCTION(ctscup, Damage_Calculate)
        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;
+                       }
 }
 
 
index c92362162d1398cbb2648f8e480a5c24f96a3eff..943db58d9d84ce19b96fa93ce61e6250ef4f2bdc 100644 (file)
@@ -1,6 +1,6 @@
 #pragma once
 
-//#include "savestate.qh"
+#include "savestate.qh"
 
 #include <common/mutators/base.qh>
 #include <server/race.qh>