From 023fed5348aa8ba0daedb134f259ce6788f48eb7 Mon Sep 17 00:00:00 2001 From: terencehill Date: Sat, 25 Apr 2020 13:42:25 +0200 Subject: [PATCH] LMS: periodically show waypoints for leaders for a few seconds --- gamemodes-server.cfg | 4 + qcsrc/common/gamemodes/gamemode/lms/sv_lms.qc | 81 +++++++++++++++++++ .../common/mutators/mutator/waypoints/all.inc | 2 + 3 files changed, 87 insertions(+) diff --git a/gamemodes-server.cfg b/gamemodes-server.cfg index b1631b233..1dec3b681 100644 --- a/gamemodes-server.cfg +++ b/gamemodes-server.cfg @@ -441,6 +441,10 @@ set g_lms_regenerate 0 set g_lms_last_join 3 "if g_lms_join_anytime is false, new players can only join if the worst active player has more than (fraglimit - g_lms_last_join) lives" set g_lms_join_anytime 1 "if true, new players can join, but get same amount of lives as the worst player" set g_lms_weaponarena "most_available" "starting weapons - takes the same options as g_weaponarena" +set g_lms_leader_wp_lives 2 "show waypoints for players leading by this number of lives" +set g_lms_leader_wp_max_relative 0.5 "show waypoints for leaders only if they are max this fraction of total players" +set g_lms_leader_wp_time 5 "show waypoints for leaders only for this amount of time" +set g_lms_leader_wp_time_repeat 30 "periodically show again waypoints for leaders after this amount of time" // ========= diff --git a/qcsrc/common/gamemodes/gamemode/lms/sv_lms.qc b/qcsrc/common/gamemodes/gamemode/lms/sv_lms.qc index bff9722d0..af4937b9d 100644 --- a/qcsrc/common/gamemodes/gamemode/lms/sv_lms.qc +++ b/qcsrc/common/gamemodes/gamemode/lms/sv_lms.qc @@ -8,6 +8,12 @@ int autocvar_g_lms_extra_lives; bool autocvar_g_lms_join_anytime; int autocvar_g_lms_last_join; bool autocvar_g_lms_regenerate; +int autocvar_g_lms_leader_wp_lives; +float autocvar_g_lms_leader_wp_max_relative; +float autocvar_g_lms_leader_wp_time; +float autocvar_g_lms_leader_wp_time_repeat; + +.float lms_wp_time; // main functions int LMS_NewPlayerLives() @@ -125,6 +131,8 @@ MUTATOR_HOOKFUNCTION(lms, reset_map_players) it.frags = FRAGS_PLAYER; GameRules_scoring_add(it, LMS_LIVES, LMS_NewPlayerLives()); PutClientInServer(it); + if (it.waypointsprite_attachedforcarrier) + WaypointSprite_Kill(it.waypointsprite_attachedforcarrier); }); } @@ -291,6 +299,79 @@ MUTATOR_HOOKFUNCTION(lms, ForbidThrowCurrentWeapon) return true; } +bool lms_waypointsprite_visible_for_player(entity this, entity player, entity view) // runs on waypoints which are attached to ballcarriers, updates once per frame +{ + if(view.lms_wp_time) + if(IS_SPEC(player)) + return false; // we don't want spectators of leaders to see the attached waypoint on the top of their screen + + float leader_time = autocvar_g_lms_leader_wp_time; + float leader_repeat_time = leader_time + autocvar_g_lms_leader_wp_time_repeat; + float wp_time = this.owner.lms_wp_time; + if (wp_time && (time - wp_time) % leader_repeat_time > leader_time) + return false; + + return true; +} + +void lms_UpdateWaypoints() +{ + int max_lives = 0; + int pl_cnt = 0; + FOREACH_CLIENT(IS_PLAYER(it) && it.frags != FRAGS_PLAYER_OUT_OF_GAME, { + int lives = GameRules_scoring_add(it, LMS_LIVES, 0); + if (lives > max_lives) + max_lives = lives; + pl_cnt++; + }); + + int second_max_lives = 0; + int pl_cnt_with_max_lives = 0; + FOREACH_CLIENT(IS_PLAYER(it) && it.frags != FRAGS_PLAYER_OUT_OF_GAME, { + int lives = GameRules_scoring_add(it, LMS_LIVES, 0); + if (lives == max_lives) + pl_cnt_with_max_lives++; + else if (lives > second_max_lives) + second_max_lives = lives; + }); + + int lives_diff = autocvar_g_lms_leader_wp_lives; + if (max_lives - second_max_lives >= lives_diff && pl_cnt_with_max_lives <= pl_cnt * autocvar_g_lms_leader_wp_max_relative) + FOREACH_CLIENT(IS_PLAYER(it) && it.frags != FRAGS_PLAYER_OUT_OF_GAME, { + int lives = GameRules_scoring_add(it, LMS_LIVES, 0); + if (lives == max_lives) + { + if (!it.waypointsprite_attachedforcarrier) + { + WaypointSprite_AttachCarrier(WP_LmsLeader, it, RADARICON_FLAGCARRIER); + it.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = lms_waypointsprite_visible_for_player; + WaypointSprite_UpdateRule(it.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT); + WaypointSprite_Ping(it.waypointsprite_attachedforcarrier); + } + if (!it.lms_wp_time) + it.lms_wp_time = time; + } + else + { + if (it.waypointsprite_attachedforcarrier) + WaypointSprite_Kill(it.waypointsprite_attachedforcarrier); + it.lms_wp_time = 0; + } + }); + else + FOREACH_CLIENT(IS_PLAYER(it) && it.frags != FRAGS_PLAYER_OUT_OF_GAME, { + if (it.waypointsprite_attachedforcarrier) + WaypointSprite_Kill(it.waypointsprite_attachedforcarrier); + it.lms_wp_time = 0; + }); +} + +MUTATOR_HOOKFUNCTION(lms, PlayerDied) +{ + if (!warmup_stage && autocvar_g_lms_leader_wp_lives > 0) + lms_UpdateWaypoints(); +} + MUTATOR_HOOKFUNCTION(lms, GiveFragsForKill) { entity frag_target = M_ARGV(1, entity); diff --git a/qcsrc/common/mutators/mutator/waypoints/all.inc b/qcsrc/common/mutators/mutator/waypoints/all.inc index c8c4db546..5a85ca95c 100644 --- a/qcsrc/common/mutators/mutator/waypoints/all.inc +++ b/qcsrc/common/mutators/mutator/waypoints/all.inc @@ -45,6 +45,8 @@ REGISTER_WAYPOINT(KeyCarrierPink, _("Key carrier"), "kh_pink_carrying", '0 1 1', REGISTER_WAYPOINT(KaBall, _("Ball"), "notify_ballpickedup", '0 1 1', 1); REGISTER_WAYPOINT(KaBallCarrier, _("Ball carrier"), "keepawayball_carrying", '1 0 0', 1); +REGISTER_WAYPOINT(LmsLeader, _("Leader"), "", '0 1 1', 1); + REGISTER_WAYPOINT(NbBall, _("Ball"), "", '0.91 0.85 0.62', 1); REGISTER_WAYPOINT(NbGoal, _("Goal"), "", '1 0.5 0', 1); -- 2.39.5