From f2e01b9dd381d818df43eba67ee48db7c273643a Mon Sep 17 00:00:00 2001 From: Rudolf Polzer Date: Tue, 13 Jun 2023 09:10:59 -0400 Subject: [PATCH] New mutator: Killers Spawn Faster. Should work in most game types, and increases one's respawn delay on every death, while decreasing it when fragging someone. --- qcsrc/common/mutators/mutator/_mod.inc | 1 + qcsrc/common/mutators/mutator/_mod.qh | 1 + .../mutator/killers_spawn_faster/_mod.inc | 4 ++ .../mutator/killers_spawn_faster/_mod.qh | 4 ++ .../killers_spawn_faster/sv_respawntime.qc | 68 +++++++++++++++++++ .../killers_spawn_faster/sv_respawntime.qh | 3 + qcsrc/server/client.qc | 7 +- qcsrc/server/mutators/events.qh | 10 ++- qcsrc/server/scores.qc | 2 + 9 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 qcsrc/common/mutators/mutator/killers_spawn_faster/_mod.inc create mode 100644 qcsrc/common/mutators/mutator/killers_spawn_faster/_mod.qh create mode 100644 qcsrc/common/mutators/mutator/killers_spawn_faster/sv_respawntime.qc create mode 100644 qcsrc/common/mutators/mutator/killers_spawn_faster/sv_respawntime.qh diff --git a/qcsrc/common/mutators/mutator/_mod.inc b/qcsrc/common/mutators/mutator/_mod.inc index c463c429f..34f7fe79a 100644 --- a/qcsrc/common/mutators/mutator/_mod.inc +++ b/qcsrc/common/mutators/mutator/_mod.inc @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/qcsrc/common/mutators/mutator/_mod.qh b/qcsrc/common/mutators/mutator/_mod.qh index 3b4eba7cb..23ee03dd7 100644 --- a/qcsrc/common/mutators/mutator/_mod.qh +++ b/qcsrc/common/mutators/mutator/_mod.qh @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include diff --git a/qcsrc/common/mutators/mutator/killers_spawn_faster/_mod.inc b/qcsrc/common/mutators/mutator/killers_spawn_faster/_mod.inc new file mode 100644 index 000000000..3eb660807 --- /dev/null +++ b/qcsrc/common/mutators/mutator/killers_spawn_faster/_mod.inc @@ -0,0 +1,4 @@ +// generated file; do not modify +#ifdef SVQC + #include +#endif diff --git a/qcsrc/common/mutators/mutator/killers_spawn_faster/_mod.qh b/qcsrc/common/mutators/mutator/killers_spawn_faster/_mod.qh new file mode 100644 index 000000000..6105ab2df --- /dev/null +++ b/qcsrc/common/mutators/mutator/killers_spawn_faster/_mod.qh @@ -0,0 +1,4 @@ +// generated file; do not modify +#ifdef SVQC + #include +#endif diff --git a/qcsrc/common/mutators/mutator/killers_spawn_faster/sv_respawntime.qc b/qcsrc/common/mutators/mutator/killers_spawn_faster/sv_respawntime.qc new file mode 100644 index 000000000..6ca25cdf5 --- /dev/null +++ b/qcsrc/common/mutators/mutator/killers_spawn_faster/sv_respawntime.qc @@ -0,0 +1,68 @@ +#include "sv_respawntime.qh" + +AUTOCVAR(g_killers_spawn_faster, bool, false, "Killers spawn faster: a mutator that penalizes dying, and rewards killing, by adjusting time to respawn"); +AUTOCVAR(g_killers_spawn_faster_frag_modifier, float, -0.2, "Killers spawn faster: respawntime factor change when fragging someone"); +AUTOCVAR(g_killers_spawn_faster_death_modifier, float, 0.5, "Killers spawn faster: respawntime factor change when dying"); +REGISTER_MUTATOR(mutator_killers_spawn_faster, autocvar_g_killers_spawn_faster); + +float killers_spawn_faster_adjust(float base, float adj) { + if (adj < 0) { + adj *= base; + } + return base + adj; +} + +MUTATOR_HOOKFUNCTION(mutator_killers_spawn_faster, BuildMutatorsString) { + M_ARGV(0, string) = strcat(M_ARGV(0, string), ":KillersSpawnFaster"); +} + +MUTATOR_HOOKFUNCTION(mutator_killers_spawn_faster, BuildMutatorsPrettyString) { + M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Killers spawn faster"); +} + +MUTATOR_HOOKFUNCTION(mutator_killers_spawn_faster, ClientConnect) { + entity player = M_ARGV(0, entity); + player.killers_spawn_faster_factor = 1; + LOG_DEBUGF("Newly spawned player %i with respawntime factor %f", player, player.killers_spawn_faster_factor); +} + +MUTATOR_HOOKFUNCTION(mutator_killers_spawn_faster, PlayerDies) { + // Note: this runs BEFORE CalculateRespawnTime. + entity attacker = M_ARGV(1, entity); + entity target = M_ARGV(2, entity); + if (target.classname == "body") { + error("WAT"); + return false; + } + attacker.killers_spawn_faster_factor = killers_spawn_faster_adjust( + attacker.killers_spawn_faster_factor, + autocvar_g_killers_spawn_faster_frag_modifier); + LOG_DEBUGF("Killer player %i now has respawntime factor %f", attacker, attacker.killers_spawn_faster_factor); +} + +MUTATOR_HOOKFUNCTION(mutator_killers_spawn_faster, CalculateRespawnTime) { + entity player = M_ARGV(0, entity); + float sdelay = M_ARGV(1, float); + sdelay *= player.killers_spawn_faster_factor; + LOG_DEBUGF("Adjusted player %i respawntime to %f", player, sdelay); + M_ARGV(1, float) = sdelay; +} + +MUTATOR_HOOKFUNCTION(mutator_killers_spawn_faster, PlayerDied) { + // Note: this runs AFTER CalculateRespawnTime. + entity player = M_ARGV(0, entity); + if (player.classname == "body") { + error("WAT"); + return false; + } + player.killers_spawn_faster_factor = killers_spawn_faster_adjust( + player.killers_spawn_faster_factor, + autocvar_g_killers_spawn_faster_death_modifier); + LOG_DEBUGF("Dying player %i now has respawntime factor %f", player, player.killers_spawn_faster_factor); +} + +MUTATOR_HOOKFUNCTION(mutator_killers_spawn_faster, PlayerScore_Clear) { + entity player = M_ARGV(0, entity); + player.killers_spawn_faster_factor = 1; + LOG_DEBUGF("Restarted player %i now has respawntime factor %f", player, player.killers_spawn_faster_factor); +} diff --git a/qcsrc/common/mutators/mutator/killers_spawn_faster/sv_respawntime.qh b/qcsrc/common/mutators/mutator/killers_spawn_faster/sv_respawntime.qh new file mode 100644 index 000000000..04dd4d855 --- /dev/null +++ b/qcsrc/common/mutators/mutator/killers_spawn_faster/sv_respawntime.qh @@ -0,0 +1,3 @@ +#pragma once + +.float killers_spawn_faster_factor; diff --git a/qcsrc/server/client.qc b/qcsrc/server/client.qc index 0a8846d5d..5c34e26b3 100644 --- a/qcsrc/server/client.qc +++ b/qcsrc/server/client.qc @@ -1340,9 +1340,6 @@ void UpdateChatBubble(entity this) void calculate_player_respawn_time(entity this) { - if(MUTATOR_CALLHOOK(CalculateRespawnTime, this)) - return; - float gametype_setting_tmp; float sdelay_max = GAMETYPE_DEFAULTED_SETTING(respawn_delay_max); float sdelay_small = GAMETYPE_DEFAULTED_SETTING(respawn_delay_small); @@ -1405,6 +1402,10 @@ void calculate_player_respawn_time(entity this) else // NOTE: this case implies sdelay_large_count > sdelay_small_count. sdelay = sdelay_small + (sdelay_large - sdelay_small) * (pcount - sdelay_small_count) / (sdelay_large_count - sdelay_small_count); + if(MUTATOR_CALLHOOK(CalculateRespawnTime, this, sdelay)) + return; + sdelay = M_ARGV(1, float); + if(waves) this.respawn_time = ceil((time + sdelay) / waves) * waves; else diff --git a/qcsrc/server/mutators/events.qh b/qcsrc/server/mutators/events.qh index ce9f95826..f468dce54 100644 --- a/qcsrc/server/mutators/events.qh +++ b/qcsrc/server/mutators/events.qh @@ -63,6 +63,12 @@ MUTATOR_HOOKABLE(reset_map_global, EV_reset_map_global); /**/ MUTATOR_HOOKABLE(reset_map_players, EV_reset_map_players); +/** called when entering play after observing, or switching teams */ +#define EV_PlayerScore_Clear(i, o) \ + /** player */ i(entity, MUTATOR_ARGV_0_entity) \ + /**/ +MUTATOR_HOOKABLE(PlayerScore_Clear, EV_PlayerScore_Clear); + /** returns 1 if clearing player score shall not be allowed */ #define EV_ForbidPlayerScore_Clear(i, o) \ /**/ @@ -1206,7 +1212,9 @@ MUTATOR_HOOKABLE(HavocBot_Aim, EV_HavocBot_Aim); /** return true to skip respawn time calculations */ #define EV_CalculateRespawnTime(i, o) \ - /** player */ i(entity, MUTATOR_ARGV_0_entity) \ + /** player */ i(entity, MUTATOR_ARGV_0_entity) \ + /** spawn delay */ i(float, MUTATOR_ARGV_1_float) \ + /** spawn delay */ o(float, MUTATOR_ARGV_1_float) \ /**/ MUTATOR_HOOKABLE(CalculateRespawnTime, EV_CalculateRespawnTime); diff --git a/qcsrc/server/scores.qc b/qcsrc/server/scores.qc index 5e1c8d9db..bdbeebffc 100644 --- a/qcsrc/server/scores.qc +++ b/qcsrc/server/scores.qc @@ -284,6 +284,8 @@ float PlayerScore_Clear(entity player) { entity sk; + MUTATOR_CALLHOOK(PlayerScore_Clear, player); + if(teamscores_entities_count) return 0; -- 2.39.2