From 484985850fc24282ae916457a4c0fe0d3b1a9360 Mon Sep 17 00:00:00 2001 From: z411 Date: Tue, 20 Oct 2020 18:36:09 -0300 Subject: [PATCH] Added Perfect and Accuracy medals for Clan Arena --- .../gamemode/clanarena/sv_clanarena.qc | 34 +++++++++++++++++-- qcsrc/common/notifications/all.inc | 5 +++ qcsrc/common/scores.qh | 7 ++-- qcsrc/server/round_handler.qc | 1 + qcsrc/server/teamplay.qc | 10 ++++++ qcsrc/server/teamplay.qh | 2 ++ qcsrc/server/weapons/accuracy.qc | 29 ++++++++++++++-- qcsrc/server/weapons/accuracy.qh | 2 ++ 8 files changed, 84 insertions(+), 6 deletions(-) diff --git a/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc b/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc index 84e21534a..0e03cae39 100644 --- a/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc +++ b/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc @@ -9,15 +9,22 @@ void CA_count_alive_players() for (int i = 1; i <= NUM_TEAMS; ++i) { Team_SetNumberOfAlivePlayers(Team_GetTeamFromIndex(i), 0); + Team_SetNumberOfPlayers(Team_GetTeamFromIndex(i), 0); } FOREACH_CLIENT(IS_PLAYER(it) && Entity_HasValidTeam(it), { ++total_players; + entity team_ = Entity_GetTeam(it); + + int num_total = Team_GetNumberOfPlayers(team_); + ++num_total; + Team_SetNumberOfPlayers(team_, num_total); + if (IS_DEAD(it)) { continue; } - entity team_ = Entity_GetTeam(it); + int num_alive = Team_GetNumberOfAlivePlayers(team_); ++num_alive; Team_SetNumberOfAlivePlayers(team_, num_alive); @@ -101,6 +108,7 @@ float CA_CheckWinner() } int winner_team = CA_GetWinnerTeam(); + bool perfect = false; if(winner_team > 0) { entity last_pl = ca_LastPlayer(winner_team); @@ -112,6 +120,10 @@ float CA_CheckWinner() Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(winner_team, INFO_ROUND_TEAM_WIN)); if(fragsleft > 1) Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, APP_TEAM_NUM(winner_team, ANNCE_ROUND_TEAM_WIN)); TeamScore_AddToTeam(winner_team, ST_CA_ROUNDS, +1); + + entity tm = Team_GetTeam(winner_team); + + if(Team_GetNumberOfAlivePlayers(tm) == Team_GetNumberOfPlayers(tm)) perfect = true; } else if(winner_team == -1) { @@ -125,7 +137,25 @@ float CA_CheckWinner() game_stopped = true; round_handler_Init(5, autocvar_g_ca_warmup, autocvar_g_ca_round_timelimit); - FOREACH_CLIENT(IS_PLAYER(it), { nades_Clear(it); }); + FOREACH_CLIENT(IS_PLAYER(it), { + nades_Clear(it); + + if(it.team == winner_team) + { + // Give perfect medal if everyone in the winner team is alive + if(perfect) { + Give_Medal(it, PERFECT); + } + + // Give accuracy medal for each weapon above 50% + entity ra = it.roundaccuracy; + for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w) { + if(ra.accuracy_fired[w] && (ra.accuracy_hit[w] / ra.accuracy_fired[w]) > 0.5) { + Give_Medal(it, ACCURACY); + } + } + } + }); return 1; } diff --git a/qcsrc/common/notifications/all.inc b/qcsrc/common/notifications/all.inc index b3255cf77..32f9fd0b7 100644 --- a/qcsrc/common/notifications/all.inc +++ b/qcsrc/common/notifications/all.inc @@ -113,6 +113,8 @@ MSG_ANNCE_NOTIF(ACHIEVEMENT_ELECTROBITCH, N__ALWAYS, "electrobitch", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME) MSG_ANNCE_NOTIF(ACHIEVEMENT_IMPRESSIVE, N_GNTLOFF, "impressive", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME) MSG_ANNCE_NOTIF(ACHIEVEMENT_YODA, N_GNTLOFF, "yoda", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME) + MSG_ANNCE_NOTIF(ACHIEVEMENT_PERFECT, N_GNTLOFF, "perfect", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME) + MSG_ANNCE_NOTIF(ACHIEVEMENT_ACCURACY, N_GNTLOFF, "accuracy", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME) MSG_ANNCE_NOTIF(BEGIN, N__ALWAYS, "begin", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1) @@ -246,6 +248,9 @@ MSG_MEDAL_NOTIF(IMPRESSIVE, N__ALWAYS, "impressive", ANNCE_ACHIEVEMENT_IMPRESSIVE) MSG_MEDAL_NOTIF(YODA, N__ALWAYS, "yoda", ANNCE_ACHIEVEMENT_YODA) + MSG_MEDAL_NOTIF(PERFECT, N__ALWAYS, "perfect", ANNCE_ACHIEVEMENT_PERFECT) + MSG_MEDAL_NOTIF(ACCURACY, N__ALWAYS, "accuracy", ANNCE_ACHIEVEMENT_ACCURACY) + MSG_MEDAL_NOTIF(KILLSTREAK_03, N__ALWAYS, "killstreak_03", ANNCE_KILLSTREAK_03) MSG_MEDAL_NOTIF(KILLSTREAK_05, N__ALWAYS, "killstreak_05", ANNCE_KILLSTREAK_05) MSG_MEDAL_NOTIF(KILLSTREAK_10, N__ALWAYS, "killstreak_10", ANNCE_KILLSTREAK_10) diff --git a/qcsrc/common/scores.qh b/qcsrc/common/scores.qh index ee762ff24..b40378d18 100644 --- a/qcsrc/common/scores.qh +++ b/qcsrc/common/scores.qh @@ -87,9 +87,7 @@ REGISTER_SP(ONS_TAKES); REGISTER_SP(ONS_CAPS); REGISTER_SP(MEDAL_AIRSHOT); -REGISTER_SP(MEDAL_ASSIST); REGISTER_SP(MEDAL_DAMAGE); -REGISTER_SP(MEDAL_DEFENSE); REGISTER_SP(MEDAL_ELECTROBITCH); REGISTER_SP(MEDAL_EXCELLENT); REGISTER_SP(MEDAL_FIRSTBLOOD); @@ -98,6 +96,11 @@ REGISTER_SP(MEDAL_HUMILIATION); REGISTER_SP(MEDAL_IMPRESSIVE); REGISTER_SP(MEDAL_YODA); +REGISTER_SP(MEDAL_ACCURACY); +REGISTER_SP(MEDAL_ASSIST); +REGISTER_SP(MEDAL_DEFENSE); +REGISTER_SP(MEDAL_PERFECT); + REGISTER_SP(MEDAL_KILLSTREAK_03); REGISTER_SP(MEDAL_KILLSTREAK_05); REGISTER_SP(MEDAL_KILLSTREAK_10); diff --git a/qcsrc/server/round_handler.qc b/qcsrc/server/round_handler.qc index edd3942a2..ef6466747 100644 --- a/qcsrc/server/round_handler.qc +++ b/qcsrc/server/round_handler.qc @@ -44,6 +44,7 @@ void round_handler_Think(entity this) this.cnt = 0; this.round_endtime = (this.round_timelimit) ? time + this.round_timelimit : 0; this.nextthink = time; + FOREACH_CLIENT(IS_PLAYER(it), { roundaccuracy_clear(it); }); if (this.roundStart) this.roundStart(); return; } diff --git a/qcsrc/server/teamplay.qc b/qcsrc/server/teamplay.qc index fbfacf902..6499d1f46 100644 --- a/qcsrc/server/teamplay.qc +++ b/qcsrc/server/teamplay.qc @@ -101,6 +101,16 @@ void Team_SetNumberOfAlivePlayers(entity team_ent, int number) team_ent.m_num_players_alive = number; } +int Team_GetNumberOfPlayers(entity team_ent) +{ + return team_ent.m_num_players; +} + +void Team_SetNumberOfPlayers(entity team_ent, int number) +{ + team_ent.m_num_players = number; +} + int Team_GetNumberOfAliveTeams() { int result = 0; diff --git a/qcsrc/server/teamplay.qh b/qcsrc/server/teamplay.qh index 33f9d02d7..25fd2561a 100644 --- a/qcsrc/server/teamplay.qh +++ b/qcsrc/server/teamplay.qh @@ -39,11 +39,13 @@ void Team_SetTeamScore(entity team_ent, float score); /// \param[in] team_ent Team entity. /// \return Number of alive players in a team. int Team_GetNumberOfAlivePlayers(entity team_ent); +int Team_GetNumberOfPlayers(entity team_ent); /// \brief Sets the number of alive players in a team. /// \param[in,out] team_ent Team entity. /// \param[in] number Number of players to set. void Team_SetNumberOfAlivePlayers(entity team_ent, int number); +void Team_SetNumberOfPlayers(entity team_ent, int number); /// \brief Returns the number of alive teams. /// \return Number of alive teams. diff --git a/qcsrc/server/weapons/accuracy.qc b/qcsrc/server/weapons/accuracy.qc index f430a7a30..5a6ebf6b7 100644 --- a/qcsrc/server/weapons/accuracy.qc +++ b/qcsrc/server/weapons/accuracy.qc @@ -61,6 +61,7 @@ bool accuracy_send(entity this, entity to, int sf) void accuracy_init(entity e) { entity a = CS(e).accuracy = new_pure(accuracy); + e.roundaccuracy = new_pure(accuracy); a.owner = e; if(!g_duel) // z411 a.drawonlytoclient = e; @@ -70,6 +71,7 @@ void accuracy_init(entity e) void accuracy_free(entity e) { delete(CS(e).accuracy); + delete(e.roundaccuracy); } // force a resend of a player's accuracy stats @@ -82,26 +84,49 @@ void accuracy_resend(entity e) //.float hit_time; .float fired_time; +void roundaccuracy_clear(entity this) +{ + if (IS_INDEPENDENT_PLAYER(this)) return; + entity ra = this.roundaccuracy; + + for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w) { + ra.accuracy_frags[w] = 0; + ra.accuracy_hit[w] = 0; + ra.accuracy_fired[w] = 0; + ra.accuracy_cnt_hit[w] = 0; + ra.accuracy_cnt_fired[w] = 0; + } +} + void accuracy_add(entity this, Weapon w, int fired, int hit) { if (IS_INDEPENDENT_PLAYER(this)) return; entity a = CS(this).accuracy; + entity ra = this.roundaccuracy; if (!a) return; if (!hit && !fired) return; if (w == WEP_Null) return; int wepid = w.m_id; wepid -= WEP_FIRST; int b = accuracy_byte(a.accuracy_hit[wepid], a.accuracy_fired[wepid]); - if (hit) a.accuracy_hit [wepid] += hit; - if (fired) a.accuracy_fired[wepid] += fired; + if (hit) { + a.accuracy_hit[wepid] += hit; + ra.accuracy_hit[wepid] += hit; + } + if (fired) { + a.accuracy_fired[wepid] += fired; + ra.accuracy_fired[wepid] += fired; + } if (hit && STAT(HIT_TIME, a) != time) { // only run this once per frame a.accuracy_cnt_hit[wepid] += 1; + ra.accuracy_cnt_hit[wepid] += 1; STAT(HIT_TIME, a) = time; } if (fired && a.fired_time != time) { // only run this once per frame a.accuracy_cnt_fired[wepid] += 1; + ra.accuracy_cnt_fired[wepid] += 1; a.fired_time = time; } diff --git a/qcsrc/server/weapons/accuracy.qh b/qcsrc/server/weapons/accuracy.qh index 396de1bdb..2bcaadbce 100644 --- a/qcsrc/server/weapons/accuracy.qh +++ b/qcsrc/server/weapons/accuracy.qh @@ -9,6 +9,7 @@ REPLICATE(cvar_cl_accuracy_data_share, bool, "cl_accuracy_data_share"); REPLICATE(cvar_cl_accuracy_data_receive, bool, "cl_accuracy_data_receive"); .entity accuracy; +.entity roundaccuracy; .float accuracy_frags[REGISTRY_MAX(Weapons)]; .float accuracy_hit[REGISTRY_MAX(Weapons)]; @@ -26,6 +27,7 @@ void accuracy_resend(entity e); // update accuracy stats void accuracy_add(entity e, Weapon w, float fired, float hit); +void roundaccuracy_clear(entity this); // helper bool accuracy_isgooddamage(entity attacker, entity targ); -- 2.39.2