// ===================================
alias ban "qc_cmd_sv ban ${* ?}" // Ban an IP address or a range of addresses (like 1.2.3)
alias banlist "qc_cmd_sv banlist ${* ?}" // List all existing bans
+alias kickkick "qc_cmd_sv kickkick ${* ?}" // Disconnect a client
alias kickban "qc_cmd_sv kickban ${* ?}" // Disconnect a client and ban it at the same time
alias mute "qc_cmd_sv mute ${* ?}" // Disallow a client from talking by muting them
alias unban "qc_cmd_sv unban ${* ?}" // Remove an existing ban
set g_ca_warmup 10 "time players get to run around before the round starts"
set g_ca_damage2score 100 "every this amount of damage done give players 1 point"
set g_ca_round_timelimit 180 "round time limit in seconds"
+set g_ca_round_stop 0 "freeze the game after round stops" // BaI mod
set g_ca_teams_override 0
set g_ca_team_spawns 0 "when 1, players spawn from the team spawnpoints of the map, if any"
set g_ca_teams 0
// freezetag
// ===========
set g_freezetag 0 "Freeze Tag: Freeze the opposing team(s) to win, unfreeze teammates by standing next to them"
-set g_freezetag_warmup 10 "time players get to run around before the round starts"
+// BaI mod changes this
+set g_freezetag_warmup 5 "time players get to run around before the round starts"
set g_freezetag_point_limit -1 "Freeze Tag point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
set g_freezetag_point_leadlimit -1 "Freeze Tag point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
set g_freezetag_revive_speed 0.4 "Speed for reviving a frozen teammate if g_freezetag_revive_time_to_score is off"
set g_freezetag_revive_nade_health 40 "Amount of health player has if they revived from their own nade explosion"
set g_freezetag_revive_time_to_score 1.5 "every this amount of seconds give players reviving a frozen teammate 1 point"
set g_freezetag_round_timelimit 360 "round time limit in seconds"
+set g_freezetag_round_stop 0 "freeze game when round ends" // BaI mod
+set g_freezetag_round_respawn 0 // BaI mod
set g_freezetag_revive_auto 1 "automatically revive frozen players after some time (g_freezetag_frozen_maxtime)"
set g_freezetag_revive_auto_progress 1 "start the automatic reviving progress as soon as the player gets frozen"
set g_freezetag_revive_auto_reducible 1 "reduce auto-revival time when frozen players are hit by enemies; set to -1 to reduce it even when they are hit by teammates"
set g_freezetag_revive_auto_reducible_forcefactor 0.01 "hit force to time reduction conversion factor"
set g_freezetag_revive_auto_reducible_maxforce 400 "max force considered at once"
+set g_freezetag_revive_respawn 1 "respawn when reviving" // BaI mod
set g_freezetag_revive_spawnshield 1 "apply spawnshield for this time in seconds after the player has been revived"
set g_freezetag_frozen_maxtime 60 "frozen players will be automatically unfrozen after this time in seconds"
set g_freezetag_teams_override 0
set g_freezetag_team_spawns 0 "when 1, players spawn from the team spawnpoints of the map, if any"
set g_freezetag_teams 0
-set g_freezetag_weaponarena "most_available" "starting weapons - takes the same options as g_weaponarena"
+// BaI mod changes this
+set g_freezetag_weaponarena "0" "starting weapons - takes the same options as g_weaponarena"
// ==========
// ==============================
// free for all and team mayhem
// ==============================
+<<<<<<< HEAD
+set g_mayhem 0 "Mayhem: Compete for the most damage dealt and frags in this chaotic mayhem!"
+set g_tmayhem 0 "Team Mayhem: Compete with your team for the most damage dealt and frags in this chaotic mayhem!"
+
+set g_mayhem_scoringmethod 1 "1: By default 25% of the score is based on kills and 75% of it is based on damage. 2: 100% frags. 3: 100% damage."
+set g_tmayhem_scoringmethod 1 "1: By default 25% of the score is based on kills and 75% of it is based on damage. 2: 100% frags. 3: 100% damage."
+set g_mayhem_scoringmethod_1_damage_weight 0.75 "for the first scoring method how much is damage equal to player's spawning health worth in score"
+set g_tmayhem_scoringmethod_1_damage_weight 0.75 "for the first scoring method how much is damage equal to player's spawning health worth in score"
+set g_mayhem_scoringmethod_1_disable_selfdamage2score 0 "disable reducing score with self damage at the cost of full penalty for suicides regardless of how much health was lost suiciding"
+set g_tmayhem_scoringmethod_1_disable_selfdamage2score 0 "disable reducing score with self damage at the cost of full penalty for suicides regardless of how much health was lost suiciding"
+set g_mayhem_scoringmethod_1_frag_weight 0.25 "for the first scoring method how much is a frag worth in score"
+set g_tmayhem_scoringmethod_1_frag_weight 0.25 "for the first scoring method how much is a frag worth in score"
+
+set g_mayhem_fraglimit 30 "Team Mayhem basis for how many frags until the match ends, edit this over point_limit preferably"
+set g_tmayhem_fraglimit 50 "Team Mayhem basis for how many frags until the match ends, edit this over point_limit preferably"
+
+set g_mayhem_visual_score_limit 1000 "Mayhem visual score limit overriding the mapinfo specified one"
+set g_tmayhem_visual_score_limit 1000 "Team Mayhem visual score limit overriding the mapinfo specified one"
+
+set g_tmayhem_score_leadlimit -1 "Team Mayhem score lead limit(based on tmayhem_visual_score_limit, not tmayhem_fraglimit) overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+=======
set g_mayhem 0 "Mayhem: Compete for the most damage dealt and kills in this chaotic mayhem!"
set g_tmayhem 0 "Team Mayhem: Compete with your team for the most damage dealt and kills in this chaotic mayhem!"
set g_mayhem_point_leadlimit -1 "Mayhem score lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
set g_tmayhem_point_limit -1 "Team Mayhem score limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
set g_tmayhem_point_leadlimit -1 "Team Mayhem score lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+>>>>>>> master
set g_mayhem_weaponarena "most_available" "starting weapons - takes the same options as g_weaponarena"
set g_tmayhem_weaponarena "most_available" "starting weapons - takes the same options as g_weaponarena"
// ********************************************** //
// MSG_ANNCE notifications:
+seta notification_ANNCE_ACCIDENT "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_ACHIEVEMENT_ACCURACY "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_ACHIEVEMENT_AIRSHOT "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_ACHIEVEMENT_AMAZING "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_ACHIEVEMENT_ASSIST "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_ACHIEVEMENT_AWESOME "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_ACHIEVEMENT_BOTLIKE "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_ACHIEVEMENT_DAMAGE "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_ACHIEVEMENT_DEFENSE "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_ACHIEVEMENT_ELECTROBITCH "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_ACHIEVEMENT_EXCELLENT "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_ACHIEVEMENT_IMPRESSIVE "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_ACHIEVEMENT_PERFECT "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_ACHIEVEMENT_TELEFRAG "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_ACHIEVEMENT_YODA "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_ALONE "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_BEGIN "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_CTF_PICKUP_ENEMY "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_CTF_PICKUP "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_CTF_PICKUP_TEAM "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_CTF_PICKUP_YOU "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_CTF_RETURN_ENEMY "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_CTF_RETURN "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_CTF_RETURN_TEAM "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_FIRSTBLOOD "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_HEADSHOT "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_HUMILIATION "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_INSTAGIB_LASTSECOND "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_INSTAGIB_NARROWLY "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_INSTAGIB_TERMINATED "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_KILLSTREAK_05 "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_KILLSTREAK_10 "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_KILLSTREAK_15 "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
-seta notification_ANNCE_KILLSTREAK_20 "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
-seta notification_ANNCE_KILLSTREAK_25 "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
-seta notification_ANNCE_KILLSTREAK_30 "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
-seta notification_ANNCE_MULTIFRAG "0" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_LEAD_GAINED "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_LEAD_LOST "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_LEAD_TIED "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_MULTIFRAG "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_NUM_1 "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_NUM_10 "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_NUM_2 "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_NUM_GAMESTART_7 "0" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_NUM_GAMESTART_8 "0" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_NUM_GAMESTART_9 "0" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_NUM_IDLE_1 "0" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_NUM_IDLE_10 "0" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_NUM_IDLE_2 "0" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_NUM_IDLE_3 "0" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_NUM_IDLE_4 "0" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_NUM_IDLE_5 "0" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_NUM_IDLE_6 "0" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_NUM_IDLE_7 "0" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_NUM_IDLE_8 "0" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_NUM_IDLE_9 "0" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_NUM_KILL_1 "0" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_NUM_KILL_10 "0" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_NUM_KILL_2 "0" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_NUM_ROUNDSTART_7 "0" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_NUM_ROUNDSTART_8 "0" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_NUM_ROUNDSTART_9 "0" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_OVERTIME "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_PREPARE "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_PREPARE_TEAM "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_REMAINING_FRAG_1 "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_REMAINING_FRAG_2 "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_REMAINING_FRAG_3 "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_REMAINING_MIN_1 "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_REMAINING_MIN_5 "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_ROUND_OVER "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_ROUND_TEAM_WIN "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_ROUND_TIED "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_SUDDENDEATH "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_SUICIDE "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_TEAM_LEADS_ENEMY "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_TEAM_LEADS "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_TEAM_LEADS_TEAM "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_TEAM_LEADS_TIED "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_TEAM_SCORES_ENEMY "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_TEAM_SCORES "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_TEAM_SCORES_TEAM "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
+seta notification_ANNCE_TEAM_WINS "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_TIMEOUT "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_VOTE_ACCEPT "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_VOTE_CALL "2" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_INFO_JOIN_CONNECT "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_JOIN_PLAY "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_JOIN_PLAY_TEAM "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_JOIN_WANTS_TEAM "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_KEEPAWAY_DROPPED "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_KEEPAWAY_PICKUP "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_KEYHUNT_CAPTURE "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_MINIGAME_INVITE "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_MONSTERS_DISABLED "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_MOVETOSPEC_IDLING "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_MOVETOSPEC_REMOVE "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_NEXBALL_RETURN_HELD "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_ONSLAUGHT_CAPTURE "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_ONSLAUGHT_CAPTURE_NONAME "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_POWERUP_SPEED "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_POWERUP_STRENGTH "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_QUIT_DISCONNECT "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_QUIT_KICK "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_QUIT_KICK_IDLING "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_QUIT_KICK_SPECTATING "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_QUIT_KICK_TEAMKILL "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_QUIT_PLAYBAN_TEAMKILL "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_QUIT_QUEUE "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_QUIT_SPECTATE "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_RACE_ABANDONED "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_RACE_FAIL_RANKED "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_RACE_NEW_SET "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_ROUND_OVER "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_ROUND_PLAYER_WIN "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_ROUND_TEAM_SCORES "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_ROUND_TEAM_WIN "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_ROUND_TIED "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_SCORES "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_CENTER_CTF_RETURN "1" "0 = off, 1 = centerprint"
seta notification_CENTER_CTF_STALEMATE_CARRIER "1" "0 = off, 1 = centerprint"
seta notification_CENTER_CTF_STALEMATE_OTHER "1" "0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_MURDER_DM "1" "0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_MURDER_DUEL "1" "0 = off, 1 = centerprint"
seta notification_CENTER_DEATH_MURDER_FRAG "1" "0 = off, 1 = centerprint"
seta notification_CENTER_DEATH_MURDER_FRAGGED "1" "0 = off, 1 = centerprint"
seta notification_CENTER_DEATH_MURDER_FRAGGED_FIRE "1" "0 = off, 1 = centerprint"
seta notification_CENTER_JOIN_PLAYBAN "1" "0 = off, 1 = centerprint"
seta notification_CENTER_JOIN_PREVENT "1" "0 = off, 1 = centerprint"
seta notification_CENTER_JOIN_PREVENT_MINIGAME "1" "0 = off, 1 = centerprint"
+seta notification_CENTER_JOIN_PREVENT_QUEUE "1" "0 = off, 1 = centerprint"
seta notification_CENTER_KEEPAWAY_DROPPED "1" "0 = off, 1 = centerprint"
seta notification_CENTER_KEEPAWAY_PICKUP "1" "0 = off, 1 = centerprint"
seta notification_CENTER_KEEPAWAY_PICKUP_SELF "1" "0 = off, 1 = centerprint"
seta notification_CENTER_LMS_VISIBLE_LEADER "1" "0 = off, 1 = centerprint"
seta notification_CENTER_LMS_VISIBLE_OTHER "1" "0 = off, 1 = centerprint"
seta notification_CENTER_MISSING_PLAYERS "1" "0 = off, 1 = centerprint"
+seta notification_CENTER_MISSING_READY "1" "0 = off, 1 = centerprint"
seta notification_CENTER_MISSING_TEAMS "1" "0 = off, 1 = centerprint"
seta notification_CENTER_MOVETOSPEC_IDLING "1" "0 = off, 1 = centerprint"
+seta notification_CENTER_MOVETOSPEC_REMOVE "1" "0 = off, 1 = centerprint"
seta notification_CENTER_NADE_BONUS "1" "0 = off, 1 = centerprint"
seta notification_CENTER_NADE_THROW "1" "0 = off, 1 = centerprint"
seta notification_CENTER_NIX_COUNTDOWN "1" "0 = off, 1 = centerprint"
seta notification_CENTER_ROUND_OVER "1" "0 = off, 1 = centerprint"
seta notification_CENTER_ROUND_PLAYER_WIN "1" "0 = off, 1 = centerprint"
seta notification_CENTER_ROUND_TEAM_LOSS "1" "0 = off, 1 = centerprint"
+seta notification_CENTER_ROUND_TEAM_SCORES "1" "0 = off, 1 = centerprint"
seta notification_CENTER_ROUND_TEAM_WIN "1" "0 = off, 1 = centerprint"
seta notification_CENTER_ROUND_TIED "1" "0 = off, 1 = centerprint"
seta notification_CENTER_SEQUENCE_COMPLETED "1" "0 = off, 1 = centerprint"
seta notification_CENTER_TEAMCHANGE_SUICIDE "1" "0 = off, 1 = centerprint"
seta notification_CENTER_TIMEOUT_BEGINNING "1" "0 = off, 1 = centerprint"
seta notification_CENTER_TIMEOUT_ENDING "1" "0 = off, 1 = centerprint"
+seta notification_CENTER_TIMEOUT_ONGOING "1" "0 = off, 1 = centerprint"
seta notification_CENTER_VEHICLE_ENTER "1" "0 = off, 1 = centerprint"
seta notification_CENTER_VEHICLE_ENTER_GUNNER "1" "0 = off, 1 = centerprint"
seta notification_CENTER_VEHICLE_ENTER_STEAL "1" "0 = off, 1 = centerprint"
seta notification_CHOICE_TYPEFRAGGED "1" "Choice for this notification 0 = off, 1 = default message, 2 = verbose message"
seta notification_CHOICE_TYPEFRAGGED_ALLOWED "1" "Allow choice for this notification 0 = off, 1 = only in warmup mode, 2 = always"
+// MSG_MEDAL notifications (count = 19):
+seta notification_MEDAL_ACCURACY "2" "Enable this multiple notification"
+seta notification_MEDAL_AIRSHOT "2" "Enable this multiple notification"
+seta notification_MEDAL_ASSIST "2" "Enable this multiple notification"
+seta notification_MEDAL_CAPTURE "2" "Enable this multiple notification"
+seta notification_MEDAL_DAMAGE "2" "Enable this multiple notification"
+seta notification_MEDAL_DEFENSE "2" "Enable this multiple notification"
+seta notification_MEDAL_ELECTROBITCH "2" "Enable this multiple notification"
+seta notification_MEDAL_EXCELLENT "2" "Enable this multiple notification"
+seta notification_MEDAL_FIRSTBLOOD "2" "Enable this multiple notification"
+seta notification_MEDAL_HEADSHOT "2" "Enable this multiple notification"
+seta notification_MEDAL_HUMILIATION "2" "Enable this multiple notification"
+seta notification_MEDAL_IMPRESSIVE "2" "Enable this multiple notification"
+seta notification_MEDAL_KILLSTREAK_03 "2" "Enable this multiple notification"
+seta notification_MEDAL_KILLSTREAK_05 "2" "Enable this multiple notification"
+seta notification_MEDAL_KILLSTREAK_10 "2" "Enable this multiple notification"
+seta notification_MEDAL_KILLSTREAK_15 "2" "Enable this multiple notification"
+seta notification_MEDAL_PERFECT "2" "Enable this multiple notification"
+seta notification_MEDAL_TELEFRAG "2" "Enable this multiple notification"
+seta notification_MEDAL_YODA "2" "Enable this multiple notification"
+
// HARD CODED notification variables:
seta notification_allow_chatboxprint "1" "Allow INFO notifications to be printed to chat box 0 = do not allow, 1 = allow only if allowed by individual notification_INFO* cvars, 2 = force all INFO notifications to be printed to the chatbox"
seta notification_debug "0" "Print extra debug information on all notification function calls (Requires -DNOTIFICATIONS_DEBUG flag to be enabled on QCSRC compilation)... 0 = disabled, 1 = dprint, 2 = print"
{
float starttime = STAT(GAMESTARTTIME);
float roundstarttime = STAT(ROUNDSTARTTIME);
- if(roundstarttime == -1)
+ bool game_timeout = (STAT(TIMEOUT_LAST) > 0);
+
+ if(roundstarttime == -1 || game_timeout)
{
Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_ROUNDSTOP);
delete(this);
float countdown = (inround ? roundstarttime - time : starttime - time);
float countdown_rounded = floor(0.5 + countdown);
+ if (time >= starttime) centerprint_ClearTitle();
if (starttime != prev_starttime || roundstarttime != prev_roundstarttime || prev_inround != inround)
this.skin = 0; // restart centerprint countdown
centerprint_SetTitle(strcat("^BG", MapInfo_Type_ToText(gametype))); // Show game type as title
if(time + 5.0 < startTime) // if connecting to server while restart was active don't always play prepareforbattle
- Local_Notification(MSG_ANNCE, ANNCE_PREPARE);
+ if(teamplay)
+ Local_Notification(MSG_ANNCE, ANNCE_PREPARE_TEAM);
+ else
+ Local_Notification(MSG_ANNCE, ANNCE_PREPARE);
}
announcer_countdown.nextthink = startTime - floor(startTime - time + 0.5); //synchronize nextthink to startTime
float hud_dynamic_shake_factor;
float hud_dynamic_shake_time;
+bool autocvar_hud_panel_spect_scores = true; //LegendGuard adds a bool to enable/disable score display HUD 06-04-2021
+bool autocvar_hud_panel_spect_playername = true; //LegendGuard adds a bool to enable/disable player name display HUD 06-04-2021
+
// shared across viewmodel effects and dynamic hud code
vector cl_followmodel_ofs;
float cl_followmodel_time;
REGISTER_HUD_PANEL(SCOREBOARD, Scoreboard_Draw, PANEL_CONFIG_NO , PANEL_SHOW_MAINGAME | PANEL_SHOW_MINIGAME | PANEL_SHOW_MAPVOTE | PANEL_SHOW_WITH_SB) // SCOREBOARD
REGISTER_HUD_PANEL(STRAFEHUD, HUD_StrafeHUD, PANEL_CONFIG_MAIN | PANEL_CONFIG_CANBEOFF, PANEL_SHOW_MAINGAME ) // STRAFEHUD
REGISTER_HUD_PANEL(PICKUP, HUD_Pickup, PANEL_CONFIG_MAIN | PANEL_CONFIG_CANBEOFF, PANEL_SHOW_MAINGAME ) // PICKUP
+REGISTER_HUD_PANEL(SPECTHUD, HUD_SpectHUD, PANEL_CONFIG_NO | PANEL_CONFIG_CANBEOFF, PANEL_SHOW_MAINGAME ) // SPECTHUD
// always add new panels to the end of list
// Because calling lots of functions in QC apparently cuts fps in half on many machines:
#include <client/hud/panel/racetimer.qc>
#include <client/hud/panel/radar.qc>
#include <client/hud/panel/score.qc>
+#include <client/hud/panel/spect.qc>
#include <client/hud/panel/scoreboard.qc>
#include <client/hud/panel/strafehud.qc>
#include <client/hud/panel/timer.qc>
#include <client/hud/panel/racetimer.qh>
#include <client/hud/panel/radar.qh>
#include <client/hud/panel/score.qh>
+#include <client/hud/panel/spect.qh>
#include <client/hud/panel/scoreboard.qh>
#include <client/hud/panel/strafehud.qh>
#include <client/hud/panel/timer.qh>
int centerprint_countdown_num[CENTERPRINT_MAX_MSGS];
bool centerprint_showing;
+float centerprint_medal_expire_time;
+string centerprint_medal_icon;
+float centerprint_medal_times;
+
string centerprint_title;
string centerprint_title_left;
string centerprint_title_right;
}
}
+void centerprint_Medal(string icon, float times)
+{
+ if(!autocvar_hud_panel_centerprint_medals) return;
+
+ //LOG_INFOF("centerprint_Medal: icon: %s times: %d", icon, times);
+ //centerprint_medal_expire_time = time + autocvar_hud_panel_centerprint_time;
+ centerprint_medal_expire_time = time + MSG_MEDAL_TIME;
+ centerprint_medal_times = times;
+ if(centerprint_medal_icon)
+ strunzone(centerprint_medal_icon);
+ centerprint_medal_icon = strzone(strcat("gfx/medal/", icon));
+
+ centerprint_showing = true;
+}
+
void centerprint_SetDuelTitle(string left, string right)
{
float namesize = autocvar_hud_panel_scoreboard_namesize * hud_fontsize.x;
bool all_messages_expired = true;
pos = panel_pos;
+
if (autocvar_hud_panel_centerprint_flip)
pos.y += panel_size.y;
align = bound(0, autocvar_hud_panel_centerprint_align, 1);
+
+ // z411 draw medals first
+ if (autocvar_hud_panel_centerprint_medals && time < centerprint_medal_expire_time) {
+ float height = vid_conheight/50 * 4;
+ pos.y -= height;
+
+ if(time < centerprint_medal_expire_time - MSG_MEDAL_FADE_TIME)
+ a = 1;
+ else
+ a = (centerprint_medal_expire_time - time) / MSG_MEDAL_FADE_TIME;
+
+ vector tmp_in = pos;
+
+ vector mysize = draw_getimagesize(centerprint_medal_icon);
+ vector newsize = vec2(height*(mysize.x/mysize.y), height);
+ vector fontsize = '1 1 0' * (newsize.y/2);
+
+ tmp_in.x += (panel_size.x - newsize.x) / 2; // center medal icon
+
+ if(centerprint_medal_times < autocvar_hud_panel_centerprint_medals_max) {
+ tmp_in.x -= ((newsize.x * 1.1) * (centerprint_medal_times - 1) / 2);
+ for(int t = 0; t < centerprint_medal_times; t++) {
+ drawpic(tmp_in, centerprint_medal_icon, newsize, '1 1 1', a, DRAWFLAG_NORMAL);
+ tmp_in.x += newsize.x * 1.1;
+ }
+ } else {
+ drawpic(tmp_in, centerprint_medal_icon, newsize, '1 1 1', a, DRAWFLAG_NORMAL);
+ tmp_in.x += newsize.x + fontsize.x * 0.25; // draw times next to it
+ tmp_in.y += (newsize.y - fontsize.y) / 2;
+ drawstring(tmp_in, ftos(centerprint_medal_times), fontsize, '1 1 1', a, DRAWFLAG_NORMAL);
+ }
+
+ pos.y += height;
+
+ all_messages_expired = false;
+ }
// Show title if available
if(centerprint_title != "" || centerprint_title_left != "") {
if (time < centerprint_start_time[j]) continue;
- float fade_in_time = autocvar_hud_panel_centerprint_fade_in;
+ float fade_in_time = 0;
float fade_out_time = autocvar_hud_panel_centerprint_fade_out;
if (centerprint_countdown_num[j] && centerprint_start_time[j]) {
a *= panel_fg_alpha;
// finally set the size based on the alpha
- sz = autocvar_hud_panel_centerprint_fade_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_minfontsize);
+ //sz = autocvar_hud_panel_centerprint_fade_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_minfontsize);
+ sz = 1; // remove zoom;
drawfontscale = hud_scale * sz;
if (centerprint_countdown_num[j])
bool autocvar_hud_panel_centerprint;
float autocvar_hud_panel_centerprint_align;
-float autocvar_hud_panel_centerprint_fade_in = 0.15;
+//float autocvar_hud_panel_centerprint_fade_in = 0;
float autocvar_hud_panel_centerprint_fade_out = 0.15;
float autocvar_hud_panel_centerprint_fade_subsequent = 1;
float autocvar_hud_panel_centerprint_fade_subsequent_passone = 3;
float autocvar_hud_panel_centerprint_fade_subsequent_passone_minalpha = 0.5;
float autocvar_hud_panel_centerprint_fade_subsequent_passtwo = 10;
float autocvar_hud_panel_centerprint_fade_subsequent_passtwo_minalpha = 0.5;
-float autocvar_hud_panel_centerprint_fade_minfontsize = 1;
+//float autocvar_hud_panel_centerprint_fade_minfontsize = 1;
bool autocvar_hud_panel_centerprint_flip;
float autocvar_hud_panel_centerprint_fontscale = 1;
float autocvar_hud_panel_centerprint_fontscale_bold = 1.4;
bool autocvar_hud_panel_centerprint_dynamichud = true;
float autocvar_hud_panel_centerprint_time;
+bool autocvar_hud_panel_centerprint_medals = true;
+int autocvar_hud_panel_centerprint_medals_max = 5;
+
void centerprint_Add(int new_id, string strMessage, float duration, int countdown_num);
void centerprint_AddStandard(string strMessage);
void centerprint_Kill(int id);
void centerprint_SetDuelTitle(string left, string right);
void centerprint_SetTitle(string title);
void centerprint_ClearTitle();
+void centerprint_Medal(string icon, int times);
#include "chat.qh"
#include <client/draw.qh>
+#include <common/items/inventory.qh>
+
// Chat (#12)
if (autocvar_con_chat != floor(mySize.y / autocvar_con_chatsize - 0.5))
cvar_set("con_chat", ftos(floor(mySize.y / autocvar_con_chatsize - 0.5)));
+ //vector chatsize = '1 1 0' * autocvar_con_chatsize;
if(autocvar__hud_configure)
{
vector chatsize = '1 1 0' * autocvar_con_chatsize;
void HUD_HealthArmor()
{
- int armor, health, fuel, air_time;
+ int armor, health, health_real, fuel, air_time;
if(!autocvar__hud_configure)
{
if((!autocvar_hud_panel_healtharmor) || (spectatee_status == -1))
if(hud != HUD_NORMAL) return;
health = STAT(HEALTH);
+ health_real = health;
if(health <= 0)
{
+ health_real = max(health, -999);
health = 0;
prev_health = -1;
if(autocvar_hud_panel_healtharmor_hide_ondeath)
else
{
health = 150;
+ health_real = 150;
armor = 75;
fuel = 20;
air_time = 6;
HUD_Panel_DrawProgressBar(pos + health_offset, mySize, autocvar_hud_panel_healtharmor_progressbar_health, p_health/maxhealth, is_vertical, health_baralign, autocvar_hud_progressbar_health_color, autocvar_hud_progressbar_alpha * panel_fg_alpha * pain_health_alpha, DRAWFLAG_NORMAL);
}
if(autocvar_hud_panel_healtharmor_text)
- DrawNumIcon(pos + health_offset, mySize, health, "health", is_vertical, false, health_iconalign, HUD_Get_Num_Color(health, maxhealth, true), 1);
+ DrawNumIcon(pos + health_offset, mySize, health_real, "health", is_vertical, false, health_iconalign, HUD_Get_Num_Color(health, maxhealth, true), 1);
}
//if(armor)
HUD_Write_Cvar("hud_panel_infomessages_flip");
}
-float autocvar_hud_panel_infomessages_group0 = 1;
+//float autocvar_hud_panel_infomessages_group0 = 1;
float autocvar_hud_panel_infomessages_group_fadetime = 0.4;
float autocvar_hud_panel_infomessages_group_time = 6;
const int IMG_COUNT = 1; // number of InfoMessage Groups
{
if(spectatee_status)
{
- if(spectatee_status == -1)
- s = _("^1Observing");
- else
- s = sprintf(_("^1Spectating: ^7%s"), entcs_GetName(current_player));
- InfoMessage(s);
+ // z411 : Show the observed played if we have the spectator HUD disabled
+ if(!autocvar_hud_panel_spect_playername) {
+ if(spectatee_status == -1)
+ s = _("^1Observing");
+ else
+ s = sprintf(_("^1Spectating: ^7%s"), entcs_GetName(current_player));
+ InfoMessage(s);
+ }
- if(autocvar_hud_panel_infomessages_group0)
+ /*if(autocvar_hud_panel_infomessages_group0)
{
img_curr_group = 0;
switch(img_select(img_curr_group) % 3)
break;
}
InfoMessage(s);
- }
+ }*/
- bool mutator_returnvalue = MUTATOR_CALLHOOK(DrawInfoMessages, pos, mySize, img_curr_group);
- pos = M_ARGV(0, vector);
- img_curr_group = M_ARGV(2, int);
+ //bool mutator_returnvalue = MUTATOR_CALLHOOK(DrawInfoMessages, pos, mySize, img_curr_group);
+ //pos = M_ARGV(0, vector);
+ //img_curr_group = M_ARGV(2, int);
- if(!mutator_returnvalue)
+ if(entcs_GetWantsJoin(current_player))
{
- s = sprintf(_("^1Press ^3%s^1 to join"), getcommandkey(_("jump"), "+jump"));
- InfoMessage(s);
+ int tm = Team_IndexToTeam(entcs_GetWantsJoin(current_player));
+ s = sprintf(_("^2You're queued to join the %s%s^2 team"), Team_ColorCode(tm), Team_ColorName(tm));
}
+ else
+ s = sprintf(_("^1Press ^3%s^1 to join"), getcommandkey(_("jump"), "+jump"));
+ InfoMessage(s);
}
if (time < STAT(GAMESTARTTIME))
InfoMessage(s);
}
}
+
+ // z411
+ if (motd_permanent != "")
+ InfoMessage(motd_permanent);
+
+ MUTATOR_CALLHOOK(DrawInfoMessages, pos, mySize, img_curr_group);
}
else
{
if(!autocvar_hud_panel_modicons) return;
if(!HUD_ModIcons_GameType) return;
}
-
+
if(mod_active || autocvar__hud_configure)
mod_alpha = min(mod_alpha + frametime * 2, 1);
else
if(mode == "")
{
- if(file == "" || file == "0")
- mode = "default";
- else
+ if(autocvar__hud_panel_quickmenu_file_from_server)
+ {
mode = "file";
+ file = autocvar__hud_panel_quickmenu_file_from_server;
+ }
+ else
+ mode = "default";
}
if(mode == "default")
#include <client/draw.qh>
#include <client/hud/panel/scoreboard.qh>
+#include <common/mapinfo.qh>
#include <common/ent_cs.qh>
#include <common/scores.qh>
}
void HUD_Score_Rankings(vector pos, vector mySize, entity me)
-{
+{
float score;
entity tm = NULL, pl;
int SCOREPANEL_MAX_ENTRIES = 6;
return;
}
- Scoreboard_UpdatePlayerTeams();
+ /*
if (team_count)
{
// show team scores in the first line
first_pl = 1;
pos.y += fontsize.y;
tm = teams.sort_next;
- }
- i = first_pl;
+ }*/
- do
- for (pl = players.sort_next; pl && i<entries; pl = pl.sort_next)
+ // z411 Basic team stats
+ if (team_count)
{
- if ((team_count && pl.team != tm.team) || pl.team == NUM_SPECTATOR)
- continue;
-
- if (i == entries-1 && !me_printed && pl != me)
- if (autocvar_hud_panel_score_rankings == 1 && spectatee_status != -1)
- {
- for (pl = me.sort_next; pl; pl = pl.sort_next)
- if (pl.team != NUM_SPECTATOR)
- break;
+ i = 0;
+ for(tm = teams.sort_next; tm; tm = tm.sort_next) {
+ if(tm.team == NUM_SPECTATOR)
+ continue;
+ if(!tm.team)
+ continue;
- if (pl)
- rgb = '1 1 0'; //not last but not among the leading players: yellow
- else
- rgb = '1 0 0'; //last: red
- pl = me;
+ /*if (tm.team == myteam)
+ drawfill(pos + eX * score_size * i, vec2(score_size, fontsize.y), '1 1 1', highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawstring_aspect(pos + eX * score_size * i, ftos(tm.(teamscores(ts_primary))), vec2(score_size, fontsize.y), Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
+ ++i;*/
+
+ if (tm.team == myteam)
+ {
+ if (i == 0)
+ rgb = '0 1 0'; //first: green
+ me_printed = true;
+ drawfill(pos, eX * mySize.x + eY * fontsize.y, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
+ }
+
+ score_color = Team_ColorRGB(tm.team) * 0.8;
+
+ // TODO secondary scores test, remove
+ if(gametype.m_modscores)
+ {
+ string icon;
+ if(tm.team == NUM_TEAM_1)
+ icon = "gfx/hud/luma/player_red";
+ else if(tm.team == NUM_TEAM_2)
+ icon = "gfx/hud/luma/player_blue";
+ else
+ icon = "gfx/hud/luma/player_neutral";
+
+ vector icon_sz = draw_getimagesize(icon);
+ vector icon_sz_new = vec2(fontsize.y*(icon_sz.x/icon_sz.y), fontsize.y);
+
+ s = ftos(gametype.m_modscores(tm.team));
+ float s_width = stringwidth(s, false, fontsize) + icon_sz_new.x;
+
+ //drawfill(pos, eX * s_width + eY * fontsize.y, score_color, panel_fg_alpha * 0.3, DRAWFLAG_NORMAL);
+ drawpic(pos, icon, icon_sz_new, '1 1 1', panel_fg_alpha * 0.7, DRAWFLAG_NORMAL);
+ drawstring(pos + eX * icon_sz_new.x, s, fontsize, '1 1 1', panel_fg_alpha * 0.7, DRAWFLAG_NORMAL);
+
+ s = textShortenToWidth(Team_CustomName(tm.team), name_size - s_width, fontsize, stringwidth_colors);
+ } else
+ s = textShortenToWidth(Team_CustomName(tm.team), name_size, fontsize, stringwidth_colors);
+ // TODO end
+
+ drawcolorcodedstring(pos + eX * (name_size - stringwidth(s, true, fontsize)), s, fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ draw_beginBoldFont();
+ drawstring(pos + eX * (name_size + spacing_size), ftos(tm.(teamscores(ts_primary))), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL);
+ draw_endBoldFont();
+
+ pos.y += fontsize.y;
+ ++i;
}
-
- if (pl == me)
+ } else {
+ i = first_pl;
+
+ do
+ for (pl = players.sort_next; pl && i<entries; pl = pl.sort_next)
{
- if (i == first_pl)
- rgb = '0 1 0'; //first: green
- me_printed = true;
- drawfill(pos, eX * mySize.x + eY * fontsize.y, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
+ if ((team_count && pl.team != tm.team) || pl.team == NUM_SPECTATOR)
+ continue;
+
+ if (i == entries-1 && !me_printed && pl != me)
+ if (autocvar_hud_panel_score_rankings == 1 && spectatee_status != -1)
+ {
+ for (pl = me.sort_next; pl; pl = pl.sort_next)
+ if (pl.team != NUM_SPECTATOR)
+ break;
+
+ if (pl)
+ rgb = '1 1 0'; //not last but not among the leading players: yellow
+ else
+ rgb = '1 0 0'; //last: red
+ pl = me;
+ }
+
+ if (team_count)
+ score_color = Team_ColorRGB(pl.team) * 0.8;
+
+ if (pl == me)
+ {
+ if (i == first_pl)
+ rgb = '0 1 0'; //first: green
+ me_printed = true;
+ drawfill(pos, eX * mySize.x + eY * fontsize.y, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
+ }
+
+ s = textShortenToWidth(entcs_GetName(pl.sv_entnum), name_size, fontsize, stringwidth_colors);
+ drawcolorcodedstring(pos + eX * (name_size - stringwidth(s, true, fontsize)), s, fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawstring(pos + eX * (name_size + spacing_size), ftos(pl.(scores(ps_primary))), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL);
+ pos.y += fontsize.y;
+ ++i;
}
- if (team_count)
- score_color = Team_ColorRGB(pl.team) * 0.8;
- s = textShortenToWidth(entcs_GetName(pl.sv_entnum), name_size, fontsize, stringwidth_colors);
- drawcolorcodedstring(pos + eX * (name_size - stringwidth(s, true, fontsize)), s, fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
- drawstring(pos + eX * (name_size + spacing_size), ftos(pl.(scores(ps_primary))), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL);
- pos.y += fontsize.y;
- ++i;
+ while (i<entries && team_count && (tm = tm.sort_next) && (tm.team != NUM_SPECTATOR || (tm = tm.sort_next)));
}
- while (i<entries && team_count && (tm = tm.sort_next) && (tm.team != NUM_SPECTATOR || (tm = tm.sort_next)));
}
void HUD_Score()
if(!autocvar_hud_panel_score) return;
if(MUTATOR_CALLHOOK(HUD_Score_show)) return;
}
+
+ Scoreboard_UpdatePlayerTeams();
+
+ // z411 : Don't display if we have the spectator HUD scores enabled
+ if(spectatee_status && autocvar_hud_panel_spect_scores) return;
HUD_Panel_LoadCvars();
vector pos, mySize;
#include <common/constants.qh>
#include <common/ent_cs.qh>
#include <common/mapinfo.qh>
+#include <common/gamemodes/gamemode/duel/duel.qh>
#include <common/minigames/cl_minigames.qh>
#include <common/net_linked.qh>
#include <common/scores.qh>
string hud_fontsize_str;
float max_namesize;
+vector duel_score_fontsize;
+vector duel_name_fontsize;
+vector duel_score_size;
+vector team_score_fontsize;
+vector team_name_fontsize;
+vector team_score_size;
+int total_medals;
+
+float autocvar_hud_panel_scoreboard_duel_weapon_scale = 1.25; // z411
+
float sbt_bg_alpha;
float sbt_fg_alpha;
float sbt_fg_alpha_self;
string autocvar_hud_panel_scoreboard_playerid_suffix = " ";
bool autocvar_hud_panel_scoreboard_scores_per_round;
+int average_ping[NUM_TEAMS];
+int total_weapons;
+
float scoreboard_time;
SHUTDOWN(scoreboard)
SCO_LABEL(_("SCO^bctime"), "bctime", " ", _("Total amount of time holding the ball in Keepaway"));
SCO_LABEL(_("SCO^caps"), "caps", " ", _("How often a flag (CTF) or a key (KeyHunt) was captured"));
SCO_LABEL(_("SCO^captime"), "captime", " ", _("Time of fastest capture (CTF)"));
+ SCO_LABEL(_("SCO^cn"), "cn", " ", _("Country of player"));
SCO_LABEL(_("SCO^deaths"), "deaths", " ", _("Number of deaths"));
SCO_LABEL(_("SCO^destroyed"), "destroyed", " ", _("Number of keys destroyed by pushing them into void"));
SCO_LABEL(_("SCO^damage"), "dmg", " ", _("The total damage done"));
// otherwise the previous exclusive rule warns anyway
// e.g. -teams,rc,cts,lms/kills ?+rc/kills
#define SCOREBOARD_DEFAULT_COLUMNS \
-"ping pl fps name |" \
+"ping pl fps cn name |" \
" -teams,rc,cts,surv,inv,lms/kills +ft,tdm,tmayhem/kills ?+rc,inv/kills" \
" -teams,surv,lms/deaths +ft,tdm,tmayhem/deaths" \
" +tdm/sum" \
}
else if(argv(2) == "all" || argv(2) == "ALL")
{
- string s = "ping pl name |"; // scores without label (not really scores)
+ string s = "ping pl cn name |"; // scores without label (not really scores)
if(argv(2) == "ALL")
{
// scores without label
sbt_num_fields = 0;
hud_fontsize = HUD_GetFontsize("hud_fontsize");
+
+ duel_score_fontsize = hud_fontsize * 3;
+ duel_name_fontsize = hud_fontsize * 1.5;
+ duel_score_size = vec2(duel_score_fontsize.x * 1.5, duel_score_fontsize.y * 1.25);
+
+ team_score_fontsize = hud_fontsize * 2;
+ team_name_fontsize = hud_fontsize * 1.5;
+ team_score_size = vec2(team_score_fontsize.x * 1.5, team_score_fontsize.y * 1.25);
for(i = 1; i < argc - 1; ++i)
{
// fields without a label (not networked via the score system)
case "ping": sbt_field[sbt_num_fields] = SP_PING; break;
case "pl": sbt_field[sbt_num_fields] = SP_PL; break;
+ case "cn": sbt_field[sbt_num_fields] = SP_COUNTRY; break; //LegendGuard adds cn label for Country column 05-04-2021
case "name": case "nick": sbt_field[sbt_num_fields] = SP_NAME; have_name = true; break;
case "|": sbt_field[sbt_num_fields] = SP_SEPARATOR; have_separator = true; break;
case "kd": case "kdr": case "kdratio": sbt_field[sbt_num_fields] = SP_KDRATIO; break;
case "sum": case "diff": case "k-d": sbt_field[sbt_num_fields] = SP_SUM; break;
+ case "cn": sbt_field[sbt_num_fields] = SP_COUNTRY; break; //LegendGuard adds cn label for Country column 05-04-2021
case "frags": sbt_field[sbt_num_fields] = SP_FRAGS; break;
default: // fields with a label
{
string sbt_field_icon0;
string sbt_field_icon1;
string sbt_field_icon2;
+string sbt_field_icon3; //LegendGuard adds for Country player flags 05-04-2021
vector sbt_field_icon0_rgb;
vector sbt_field_icon1_rgb;
vector sbt_field_icon2_rgb;
sbt_field_icon2_rgb = colormapPaletteColor(f % 16, 1);
}
}
- return entcs_GetName(pl.sv_entnum);
+ if(entcs_GetRank(pl.sv_entnum) != "")
+ return strcat(entcs_GetRank(pl.sv_entnum), "^7 ", entcs_GetName(pl.sv_entnum));
+ else
+ return entcs_GetName(pl.sv_entnum);
+}
+
+//LegendGuard adds GetCountrycode function 05-04-2021
+string Scoreboard_GetCountrycode(entity pl)
+{
+ int ccode = entcs_GetCountryCode(pl.sv_entnum);
+ if(ccode)
+ sbt_field_icon3 = strcat("gfx/flags/", ftos(ccode));
+ else
+ sbt_field_icon3 = strcat("gfx/flags/", ftos(0)); //if user hasn't assigned country flag
+
+ return "";
}
int autocvar_hud_panel_scoreboard_ping_best = 0;
#define COLOR_MED autocvar_hud_panel_scoreboard_ping_medium_color
#define COLOR_HIGH autocvar_hud_panel_scoreboard_ping_high_color
#define COLOR_WORST autocvar_hud_panel_scoreboard_ping_worst_color
+
+vector getPingColor(float f)
+{
+ if(f < PING_BEST)
+ return COLOR_BEST;
+ else if(f < PING_MED)
+ return COLOR_BEST + (COLOR_MED - COLOR_BEST) * ((f - PING_BEST) / (PING_MED - PING_BEST));
+ else if(f < PING_HIGH)
+ return COLOR_MED + (COLOR_HIGH - COLOR_MED) * ((f - PING_MED) / (PING_HIGH - PING_MED));
+ else if(f < PING_WORST)
+ return COLOR_HIGH + (COLOR_WORST - COLOR_HIGH) * ((f - PING_HIGH) / (PING_WORST - PING_HIGH));
+ else
+ return COLOR_WORST;
+}
+
string Scoreboard_GetField(entity pl, PlayerScoreField field, bool per_round)
{
float tmp, num, denom;
sbt_field_icon0 = "";
sbt_field_icon1 = "";
sbt_field_icon2 = "";
+ sbt_field_icon3 = ""; //LegendGuard adds for Country column 05-04-2021
sbt_field_icon0_rgb = '1 1 1';
sbt_field_icon1_rgb = '1 1 1';
sbt_field_icon2_rgb = '1 1 1';
f = pl.ping;
if(f == 0)
return _("N/A");
- if(f < PING_BEST)
- sbt_field_rgb = COLOR_BEST;
- else if(f < PING_MED)
- sbt_field_rgb = COLOR_BEST + (COLOR_MED - COLOR_BEST) * ((f - PING_BEST) / (PING_MED - PING_BEST));
- else if(f < PING_HIGH)
- sbt_field_rgb = COLOR_MED + (COLOR_HIGH - COLOR_MED) * ((f - PING_MED) / (PING_HIGH - PING_MED));
- else if(f < PING_WORST)
- sbt_field_rgb = COLOR_HIGH + (COLOR_WORST - COLOR_HIGH) * ((f - PING_HIGH) / (PING_WORST - PING_HIGH));
- else
- sbt_field_rgb = COLOR_WORST;
+ sbt_field_rgb = getPingColor(f);
return ftos(f);
case SP_PL:
tmp = bound(0, f / 0.2 + tmp / 0.04, 1); // 20% is REALLY BAD pl
sbt_field_rgb = '1 0.5 0.5' - '0 0.5 0.5' * tmp;
return str;
+
+ //LegendGuard adds Country REGISTER in the switch 05-04-2021
+ case SP_COUNTRY:
+ str = Scoreboard_GetCountrycode(pl);
+ return str;
+
+ //LegendGuard adds Country REGISTER in the switch 05-04-2021
+ case SP_COUNTRY:
+ str = Scoreboard_GetCountrycode(pl);
+ return str;
case SP_NAME:
str = Scoreboard_GetName(pl);
sbt_field_rgb = '1 1 1';
return ((pl.ping == 0) ? _("N/A") : "..."); // if 0 ping, either connecting or bot (either case can't show proper score)
}
+
//sbt_field_rgb = HUD_Get_Num_Color(fps, 200, true);
sbt_field_rgb = '1 0 0' + '0 1 1' * (bound(0, fps, 60) / 60);
return ftos(fps);
sbt_fixcolumnwidth_iconlen = f;
}
+ //LegendGuard adds conditional for Country column 05-04-2021
+ if(sbt_field_icon3 != "")
+ {
+ sz = draw_getimagesize(sbt_field_icon3);
+ f = sz.x / sz.y;
+ if(sbt_fixcolumnwidth_iconlen < f)
+ sbt_fixcolumnwidth_iconlen = f;
+ }
+
if(sbt_fixcolumnwidth_iconlen != 0)
{
sbt_fixcolumnwidth_iconlen *= hud_fontsize.y / hud_fontsize.x; // fix icon aspect
}
}
-vector Scoreboard_DrawHeader(vector pos, vector rgb, bool other_players)
+vector Scoreboard_DrawHeader(vector pos, vector rgb, bool other_players, int team)
{
int i;
+ string title_str;
+ vector title_rgb;
vector column_dim = eY * panel_size.y;
+
if(other_players)
column_dim.y -= 1.25 * hud_fontsize.y;
vector text_offset = eY * (1.25 - 1) / 2 * hud_fontsize.y;
{
if(sbt_field[i] == SP_SEPARATOR)
break;
+
+ vector text_offset_center = '0 0 0';
+
+ if(sbt_field[i] == SP_PING && teamplay) {
+ title_str = sprintf("(%d)", average_ping[Team_TeamToIndex(team) - 1]);
+ title_rgb = getPingColor(average_ping[Team_TeamToIndex(team) - 1]);
+ text_offset_center.x = sbt_field_size[i] - stringwidth(title_str, false, hud_fontsize);
+ } else {
+ title_str = sbt_field_title[i];
+ title_rgb = rgb * 1.5;
+ }
+
column_dim.x = sbt_field_size[i] + hud_fontsize.x;
if (sbt_highlight)
if (i % 2)
drawfill(pos - eX * hud_fontsize.x * 0.5, column_dim, '0 0 0', sbt_highlight_alpha, DRAWFLAG_NORMAL);
- drawstring(pos + text_offset, sbt_field_title[i], hud_fontsize, rgb * 1.5, sbt_fg_alpha, DRAWFLAG_NORMAL);
+ drawstring(pos + text_offset + text_offset_center, title_str, hud_fontsize, title_rgb, sbt_fg_alpha, DRAWFLAG_NORMAL);
pos.x += column_dim.x;
}
if(sbt_field[i] == SP_SEPARATOR)
drawpic(pos - tmp, sbt_field_icon1, vec2(hud_fontsize.x * sbt_fixcolumnwidth_iconlen, hud_fontsize.y), sbt_field_icon1_rgb, fg_alpha, DRAWFLAG_NORMAL);
if(sbt_field_icon2 != "")
drawpic(pos - tmp, sbt_field_icon2, vec2(hud_fontsize.x * sbt_fixcolumnwidth_iconlen, hud_fontsize.y), sbt_field_icon2_rgb, fg_alpha, DRAWFLAG_NORMAL);
+ if(sbt_field_icon3 != "") //LegendGuard adds conditional for Country column 05-04-2021
+ drawpic(pos - tmp, sbt_field_icon3, vec2(hud_fontsize.x * sbt_fixcolumnwidth_iconlen, hud_fontsize.y), sbt_field_icon1_rgb, fg_alpha, DRAWFLAG_NORMAL);
}
if(sbt_field[i] == SP_SEPARATOR)
drawpic(pos - tmp, sbt_field_icon1, vec2(hud_fontsize.x * sbt_fixcolumnwidth_iconlen, hud_fontsize.y), sbt_field_icon1_rgb, fg_alpha, DRAWFLAG_NORMAL);
if(sbt_field_icon2 != "")
drawpic(pos - tmp, sbt_field_icon2, vec2(hud_fontsize.x * sbt_fixcolumnwidth_iconlen, hud_fontsize.y), sbt_field_icon2_rgb, fg_alpha, DRAWFLAG_NORMAL);
+ if(sbt_field_icon3 != "") //LegendGuard adds conditional for Country column 05-04-2021
+ drawpic(pos - tmp, sbt_field_icon3, vec2(hud_fontsize.x * sbt_fixcolumnwidth_iconlen, hud_fontsize.y), sbt_field_icon1_rgb, fg_alpha, DRAWFLAG_NORMAL);
pos.x -= sbt_field_size[i] + hud_fontsize.x;
}
}
int i = 0;
vector h_pos = item_pos;
vector h_size = vec2(panel_size.x, hud_fontsize.y * 1.25);
+ vector sz;
bool complete = (this_team == NUM_SPECTATOR);
continue;
if(pl == ignored_pl)
continue;
+
+ string flag_name = "";
+ vector flag_size = '0 0 0';
+ Scoreboard_GetField(pl, SP_COUNTRY, autocvar_hud_panel_scoreboard_scores_per_round);
+
+ if(sbt_field_icon3 != "") {
+ sz = draw_getimagesize(sbt_field_icon3);
+ flag_name = sbt_field_icon3;
+ flag_size = vec2(hud_fontsize.x * (sz.x / sz.y), hud_fontsize.y);
+ }
+
+ if(entcs_GetWantsJoin(pl.sv_entnum))
+ {
+ vector tmcolor = Team_ColorRGB(Team_IndexToTeam(entcs_GetWantsJoin(pl.sv_entnum)));
+ tmcolor -= tmcolor * sin(2*M_PI*time);
+
+ drawstring(pos, "(Q)", hud_fontsize, tmcolor, sbt_fg_alpha, DRAWFLAG_NORMAL);
+ pos.x += stringwidth("(Q) ", true, hud_fontsize);
+ }
field = "";
if(this_team == NUM_SPECTATOR)
else if(autocvar_hud_panel_scoreboard_others_showscore)
field = Scoreboard_GetField(pl, SP_SCORE, autocvar_hud_panel_scoreboard_scores_per_round);
- string str = entcs_GetName(pl.sv_entnum);
+ string str;
+ if(entcs_GetRank(pl.sv_entnum) != "")
+ str = strcat(entcs_GetRank(pl.sv_entnum), "^7 ", entcs_GetName(pl.sv_entnum));
+ else
+ str = entcs_GetName(pl.sv_entnum);
if (autocvar_hud_panel_scoreboard_playerid)
str = Scoreboard_AddPlayerId(str, pl);
str = textShortenToWidth(str, namesize, hud_fontsize, stringwidth_colors);
}
}
+ if(flag_name != "") {
+ drawpic(pos, flag_name, flag_size, sbt_field_icon1_rgb, sbt_fg_alpha, DRAWFLAG_NORMAL);
+ pos.x += flag_size.x + hud_fontsize.x * 0.5;
+ }
+
if (scoreboard_selected_panel == SB_PANEL_SCOREBOARD && scoreboard_ui_enabled == 1)
{
if (pl == scoreboard_selected_player)
vector name_pos = pos;
if((this_team == NUM_SPECTATOR) && autocvar_hud_panel_scoreboard_spectators_aligned)
name_pos.x += max(fieldsize, min_fieldsize) + 2 * fieldpadding + hud_fontsize.x * 0.25;
+
drawcolorcodedstring(name_pos, str, hud_fontsize, sbt_fg_alpha, DRAWFLAG_NORMAL);
if(field != "")
{
return vec2(item_pos.x, item_pos.y + i * hud_fontsize.y * 1.25);
}
+vector Scoreboard_DrawMedal(vector pos, string icon, float height, float number)
+{
+ if(!number) return pos;
+ total_medals += number;
+
+ vector tmp_sz, tmp_sz2;
+ tmp_sz = draw_getimagesize(icon);
+ tmp_sz2 = vec2(height*(tmp_sz.x/tmp_sz.y), height);
+ string val = ftos(number);
+
+ drawpic(pos, icon, tmp_sz2, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ pos.x += tmp_sz2.x + hud_fontsize.x * 0.25;
+ drawstring(pos + eY * ((tmp_sz2.y - hud_fontsize.y) / 2), val, hud_fontsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ pos.x += stringwidth(val, false, hud_fontsize) + hud_fontsize.x * 0.5;
+ return pos;
+}
+
+vector Scoreboard_Duel_DrawPickup(vector pos, bool skinned, string icon, vector sz, float number, bool invert)
+{
+ vector tmp_in = pos;
+ vector tmp_sz, tmp_sz2;
+ string picpath;
+
+ // Icon
+ if(skinned) {
+ picpath = strcat(hud_skin_path, "/", icon);
+ if(precache_pic(picpath) == "")
+ picpath = strcat("gfx/hud/default/", icon);
+ } else {
+ picpath = icon;
+ }
+
+ tmp_sz = draw_getimagesize(picpath);
+ tmp_sz2 = vec2(sz.y*(tmp_sz.x/tmp_sz.y), sz.y);
+
+ tmp_in.x = pos.x + ((sz.x - tmp_sz2.x) / 2);
+ drawpic(tmp_in, picpath, tmp_sz2, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ // Number
+ if(invert)
+ tmp_in.x += tmp_sz2.x + hud_fontsize.x * 0.25;
+ else
+ tmp_in.x -= hud_fontsize.x * 0.25 + hud_fontsize.x;
+
+ tmp_in.y += (tmp_sz2.y - hud_fontsize.y) / 2;
+ drawstring(tmp_in,
+ ((number == -1) ? "?" : ftos(number)),
+ hud_fontsize, ((number > 0) ? '1 1 1' : '0.5 0.5 0.5'),
+ panel_fg_alpha,
+ DRAWFLAG_NORMAL);
+
+ pos.y += sz.y * 1.1;
+ return pos;
+}
+
+int left_pl_dmg = 50;
+int right_pl_dmg = 50;
+void Scoreboard_Duel_DrawTable(vector pos, bool invert, entity pl, entity tm)
+{
+ vector tmp, tmp_in, tmp_sz, tmp_acc;
+ string tmp_str;
+ float sz;
+ float average_acc = 0;
+
+ panel_pos = pos;
+
+ HUD_Panel_DrawBg();
+
+ // Stop here if there are no scores available
+ if(!pl) return;
+ if(entcs_GetSpecState(pl.sv_entnum) == ENTCS_SPEC_PURE) return;
+
+ tmp = pos;
+ tmp.x += panel_bg_padding;
+ tmp.y += panel_bg_padding;
+ panel_size.x -= panel_bg_padding * 2;
+
+ //if (sbt_bg_alpha)
+ // drawpic_tiled(pos, "gfx/scoreboard/scoreboard_bg", tmp, panel_size, rgb, sbt_bg_alpha, DRAWFLAG_NORMAL);
+
+ // Score: highlight
+ if(invert) { tmp.x += panel_size.x; tmp.x -= duel_score_size.x; }
+ drawfill(tmp, duel_score_size, '0 0 0', sbt_highlight_alpha, DRAWFLAG_NORMAL);
+
+ // Score: text
+ tmp_str = ftos(pl.(scores(SP_SCORE)));
+ tmp_in = tmp;
+ tmp_in.x += (duel_score_size.x / 2) - (stringwidth(tmp_str, true, duel_score_fontsize) / 2);
+ tmp_in.y += (duel_score_size.y / 2) - (duel_score_fontsize.y / 2);
+
+ draw_beginBoldFont();
+ drawstring(tmp_in, tmp_str, duel_score_fontsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ draw_endBoldFont();
+
+ tmp_in = tmp;
+ tmp_in.y += (duel_score_size.y - duel_name_fontsize.y) / 2;
+
+ // RJZ rank
+ string rank_str = entcs_GetRank(pl.sv_entnum);
+ if(rank_str != "") {
+ if(invert)
+ tmp_in.x -= stringwidth_colors(rank_str, duel_name_fontsize) + duel_name_fontsize.x * 0.5;
+ else
+ tmp_in.x += duel_score_size.x + duel_name_fontsize.x * 0.5;
+
+ draw_beginBoldFont();
+ drawcolorcodedstring(tmp_in, rank_str, duel_name_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+ draw_endBoldFont();
+ }
+
+ // Player name
+ tmp_str = entcs_GetName(pl.sv_entnum);
+ if(invert)
+ tmp_in.x -= stringwidth_colors(tmp_str, duel_name_fontsize) + duel_name_fontsize.x * 0.5;
+ else
+ tmp_in.x += (rank_str != "" ? stringwidth_colors(rank_str, duel_name_fontsize) : duel_score_size.x) + duel_name_fontsize.x * 0.5;
+ drawcolorcodedstring(tmp_in, tmp_str, duel_name_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ //LegendGuard adds a conditional sentence for country column 05-04-2021
+ // Player country icon/flag
+ Scoreboard_GetField(pl, SP_COUNTRY, autocvar_hud_panel_scoreboard_scores_per_round);
+ if(sbt_field_icon3 != "") {
+ vector rsz = draw_getimagesize(sbt_field_icon3);
+ sbt_fixcolumnwidth_iconlen = rsz.x / rsz.y;
+ if(invert)
+ tmp_in.x -= hud_fontsize.x * sbt_fixcolumnwidth_iconlen + duel_name_fontsize.x * 0.5;
+ else
+ tmp_in.x += stringwidth_colors(tmp_str, duel_name_fontsize) + duel_name_fontsize.x * 0.5;
+ tmp_in.y += (duel_name_fontsize.y - hud_fontsize.y) / 2;
+ drawpic(tmp_in, sbt_field_icon3, vec2(hud_fontsize.x * sbt_fixcolumnwidth_iconlen, hud_fontsize.y), sbt_field_icon1_rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
+ }
+
+ // Header
+ float column_width = panel_size.x / 5;
+ tmp.x = pos.x + panel_bg_padding;
+ tmp.y += hud_fontsize.y * 3 + hud_fontsize.y;
+
+ vector column_dim;
+ int i;
+
+ i = (invert ? 4 : 0);
+ column_dim = vec2(column_width * 4, hud_fontsize.y);
+
+ drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth("kills", false, hud_fontsize) / 2),
+ "kills", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth("dmg", false, hud_fontsize) / 2),
+ "dmg", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth("acc", false, hud_fontsize) / 2),
+ "acc", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth("hits", false, hud_fontsize) / 2),
+ "hits", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth("ping", false, hud_fontsize) / 2),
+ "ping", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ tmp.x = pos.x + panel_bg_padding;
+ tmp.y += hud_fontsize.y;
+
+ // Main row
+ i = (invert ? 4 : 0);
+
+ tmp_str = ftos(pl.(scores(SP_KILLS)));
+ drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth(tmp_str, false, hud_fontsize * 1.25) / 2),
+ tmp_str, hud_fontsize * 1.25, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ tmp_str = ftos(pl.(scores(SP_DMG)));
+ drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth(tmp_str, false, hud_fontsize * 1.25) / 2),
+ tmp_str, hud_fontsize * 1.25, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ tmp_acc = tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2);
+
+ if(invert)
+ i--;
+ else
+ i++;
+
+ tmp_str = Scoreboard_GetField(pl, SP_PING, autocvar_hud_panel_scoreboard_scores_per_round);
+ drawstring(tmp + eX * column_width * i + (eX * column_width / 2) - eX * (stringwidth(tmp_str, false, hud_fontsize * 1.25) / 2),
+ tmp_str, hud_fontsize * 1.25, sbt_field_rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ tmp_str = Scoreboard_GetField(pl, SP_PL, autocvar_hud_panel_scoreboard_scores_per_round);
+ drawstring(tmp + eX * column_width * (invert ? i-- : i++) + (eX * column_width / 2) - eX * (stringwidth(tmp_str, false, hud_fontsize * 0.75) / 2) + eY * (hud_fontsize.y * 1.25),
+ tmp_str, hud_fontsize * 0.75, sbt_field_rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ tmp.x = pos.x + panel_bg_padding;
+ tmp.y += hud_fontsize.y * 2;
+
+ tmp_in = tmp;
+
+ // Accuracy rows
+ int dmg_percent;
+ vector dmg_color;
+
+ total_weapons = 0;
+ int used_weapons = 0;
+
+ WepSet weapons_inmap = WepSet_GetFromStat_InMap();
+ FOREACH(Weapons, it != WEP_Null, {
+ WepSet set = it.m_wepset;
+ if (!(weapons_inmap & set) && it != WEP_BLASTER && it != WEP_SHOTGUN) // z411 TODO : We'll be hardcoding this for now.
+ continue;
+ if (it.spawnflags & WEP_TYPE_OTHER)
+ continue;
+
+ int weapon_cnt_fired = pl.accuracy_cnt_fired[i - WEP_FIRST];
+ int weapon_cnt_hit = pl.accuracy_cnt_hit[i - WEP_FIRST];
+ int weapon_acc = 0;
+ if(weapon_cnt_fired)
+ weapon_acc = floor((weapon_cnt_hit / weapon_cnt_fired) * 100);
+ average_acc += weapon_acc;
+
+ // center vertically
+ vector row_in = tmp_in;
+ row_in.y += ((hud_fontsize.y * autocvar_hud_panel_scoreboard_duel_weapon_scale) - column_dim.y) / 2;
+
+ // draw row background
+ drawfill(row_in + eX * column_width * (invert ? 1 : 0), column_dim, '0 0 0', sbt_highlight_alpha, DRAWFLAG_NORMAL);
+
+ if(weapon_cnt_fired) {
+ if(invert) {
+ if(pl.accuracy_hit[i - WEP_FIRST] > left_pl_dmg)
+ left_pl_dmg = pl.accuracy_hit[i - WEP_FIRST];
+ dmg_percent = pl.accuracy_hit[i - WEP_FIRST] / left_pl_dmg;
+ } else {
+ if(pl.accuracy_hit[i - WEP_FIRST] > right_pl_dmg)
+ right_pl_dmg = pl.accuracy_hit[i - WEP_FIRST];
+ dmg_percent = pl.accuracy_hit[i - WEP_FIRST] / right_pl_dmg;
+ }
+
+ // convert percentage range to 0.4 - 1
+ dmg_percent = dmg_percent * (1 - 0.4) + 0.4;
+
+ dmg_color.x = dmg_percent;
+ dmg_color.y = dmg_percent;
+ dmg_color.z = dmg_percent;
+
+ string draw_str;
+
+ // weapon stats
+ int c = (invert ? 4 : 0);
+
+ draw_str = ftos(pl.accuracy_frags[i - WEP_FIRST]);
+ drawstring(row_in + eX * column_width * (invert ? c-- : c++) + eX * ((column_width - stringwidth(draw_str, false, hud_fontsize)) / 2),
+ draw_str, hud_fontsize, dmg_color, panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ draw_str = ftos(pl.accuracy_hit[i - WEP_FIRST]);
+ drawstring(row_in + eX * column_width * (invert ? c-- : c++) + eX * ((column_width - stringwidth(draw_str, false, hud_fontsize)) / 2),
+ draw_str, hud_fontsize, dmg_color, panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ draw_str = sprintf("%d%%", weapon_acc);
+ drawstring(row_in + eX * column_width * (invert ? c-- : c++) + eX * ((column_width - stringwidth(draw_str, false, hud_fontsize)) / 2),
+ draw_str, hud_fontsize, dmg_color, panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ draw_str = strcat(ftos(weapon_cnt_hit), " / ", ftos(weapon_cnt_fired));
+ drawstring(row_in + eX * column_width * (invert ? c-- : c++) + eX * (column_width / 2) - eX * stringwidth(ftos(weapon_cnt_hit), false, hud_fontsize) - eX * hud_fontsize.x * 0.5,
+ draw_str, hud_fontsize, dmg_color, panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ used_weapons++;
+ }
+
+ // weapon icon
+ if(invert) {
+ tmp_in.x = pos.x + panel_size.x - panel_bg_padding - hud_fontsize.x / 2;
+ drawpic_aspect_skin(tmp_in, it.model2, vec2(50, hud_fontsize.y * autocvar_hud_panel_scoreboard_duel_weapon_scale), '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ }
+
+ tmp_in.x = pos.x + panel_bg_padding;
+ tmp_in.y += hud_fontsize.y * autocvar_hud_panel_scoreboard_duel_weapon_scale;
+
+ total_weapons++;
+ });
+
+ if(used_weapons)
+ average_acc = floor((average_acc / used_weapons) + 0.5);
+
+ // draw total accuracy now
+ tmp_str = sprintf("%d%%", average_acc);
+ drawstring(tmp_acc - eX * (stringwidth(tmp_str, false, hud_fontsize * 1.25) / 2),
+ tmp_str, hud_fontsize * 1.25, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ // Icon column
+ vector icon_sz = vec2(column_width, hud_fontsize.y*1.5);
+
+ if(!invert)
+ tmp.x += column_width * 4;
+ // Medal rows
+ drawstring(tmp + eX * ((column_width - stringwidth("medals", false, hud_fontsize)) / 2),
+ "medals", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ tmp.y += hud_fontsize.y * 1.25;
+
+ tmp = Scoreboard_Duel_DrawPickup(tmp, false, "gfx/medal/humiliation", icon_sz, pl.(scores(SP_MEDAL_HUMILIATION)), invert);
+ tmp = Scoreboard_Duel_DrawPickup(tmp, false, "gfx/medal/impressive", icon_sz, pl.(scores(SP_MEDAL_IMPRESSIVE)), invert);
+ tmp = Scoreboard_Duel_DrawPickup(tmp, false, "gfx/medal/excellent", icon_sz, pl.(scores(SP_MEDAL_EXCELLENT)), invert);
+
+ // Item rows
+ drawstring(tmp + eX * ((column_width - stringwidth("items", false, hud_fontsize)) / 2),
+ "items", hud_fontsize, '0.5 0.5 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ tmp.y += hud_fontsize.y * 1.25;
+
+ float inv_num = -1;
+ FOREACH(Items,
+ it.m_id == ITEM_ArmorMega.m_id ||
+ it.m_id == ITEM_HealthMega.m_id ||
+ it.m_id == ITEM_ArmorBig.m_id, {
+ // If the match isn't over, Only show pickups if we're spectating or they're our own
+ if(intermission || warmup_stage || spectatee_status || pl.sv_entnum == current_player)
+ inv_num = inventoryslots[pl.sv_entnum].inv_items[it.m_id];
+ tmp = Scoreboard_Duel_DrawPickup(tmp, true, it.m_icon, icon_sz, inv_num, invert);
+
+ if(it.m_id == REGISTRY_MAX(Items))
+ break;
+ });
+}
+vector Scoreboard_MakeDuelTable(vector pos, entity tm, vector rgb, vector bg_size)
+{
+ vector end_pos = pos;
+ float screen_half = panel_size.x / 2;
+ float weapon_margin = hud_fontsize.x;
+
+ panel_size.x = screen_half - weapon_margin;
+ if(total_weapons)
+ panel_size.y = max(duel_score_size.y * 5.5, duel_score_size.y * 2.25 + (hud_fontsize.y * autocvar_hud_panel_scoreboard_duel_weapon_scale * total_weapons));
+ else
+ panel_size.y = duel_score_size.y * 5.5;
+
+ entity pl_left = players.sort_next;
+ entity pl_right = pl_left.sort_next;
+
+ Scoreboard_Duel_DrawTable(pos, true, pl_left, tm);
+ Scoreboard_Duel_DrawTable(pos + eX * screen_half + eX * weapon_margin, false, pl_right, tm);
+
+ end_pos.y += panel_size.y + (panel_bg_padding * 2);
+ panel_size.x = screen_half * 2;
+ return end_pos;
+}
+
vector Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
{
int max_players = 999;
// print header row and highlight columns
- pos = Scoreboard_DrawHeader(panel_pos, rgb, (max_players < tm.team_size));
+ pos = Scoreboard_DrawHeader(panel_pos, rgb, (max_players < tm.team_size), tm.team);
// fill the table and draw the rows
bool is_self = false;
bool self_shown = false;
int i = 0;
+ int with_ping = 0;
+ if(Team_IsValidTeam(tm.team)) average_ping[Team_TeamToIndex(tm.team) - 1] = 0;
for(pl = players.sort_next; pl; pl = pl.sort_next)
{
if(pl.team != tm.team)
}
is_self = (pl.sv_entnum == current_player);
Scoreboard_DrawItem(pos, rgb, pl, is_self, i);
+
+ if(Team_IsValidTeam(tm.team) && pl.ping) {
+ average_ping[Team_TeamToIndex(tm.team) - 1] += pl.ping;
+ ++with_ping;
+ }
if(is_self)
self_shown = true;
pos.y += 1.25 * hud_fontsize.y;
++i;
}
+ if(with_ping) average_ping[Team_TeamToIndex(tm.team) - 1] /= with_ping;
if (scoreboard_selected_panel == SB_PANEL_SCOREBOARD)
{
return true;
else if (intermission == 2)
return false;
- else if (spectatee_status != -1 && STAT(HEALTH) <= 0 && autocvar_cl_deathscoreboard && !MUTATOR_CALLHOOK(DrawDeathScoreboard)
+ else if (!spectatee_status && STAT(HEALTH) <= 0 && autocvar_cl_deathscoreboard && !MUTATOR_CALLHOOK(DrawDeathScoreboard)
&& (!HUD_MinigameMenu_IsOpened() || !active_minigame))
{
return true;
return false;
}
+vector Scoreboard_MedalStats_Draw(vector pos)
+{
+ vector orig = pos;
+ float height = hud_fontsize.y * 2;
+
+ entity pl = playerslots[current_player];
+
+ vector title_pos = pos;
+ pos.x += 0.5 * hud_fontsize.x + panel_bg_padding;
+ pos.y += 1.25 * hud_fontsize.y;
+
+ total_medals = 0;
+
+ pos = Scoreboard_DrawMedal(pos, "gfx/medal/airshot", height, pl.(scores(SP_MEDAL_AIRSHOT)));
+ pos = Scoreboard_DrawMedal(pos, "gfx/medal/damage", height, pl.(scores(SP_MEDAL_DAMAGE)));
+ pos = Scoreboard_DrawMedal(pos, "gfx/medal/electrobitch", height, pl.(scores(SP_MEDAL_ELECTROBITCH)));
+ pos = Scoreboard_DrawMedal(pos, "gfx/medal/excellent", height, pl.(scores(SP_MEDAL_EXCELLENT)));
+ pos = Scoreboard_DrawMedal(pos, "gfx/medal/firstblood", height, pl.(scores(SP_MEDAL_FIRSTBLOOD)));
+ pos = Scoreboard_DrawMedal(pos, "gfx/medal/headshot", height, pl.(scores(SP_MEDAL_HEADSHOT)));
+ pos = Scoreboard_DrawMedal(pos, "gfx/medal/humiliation", height, pl.(scores(SP_MEDAL_HUMILIATION)));
+ pos = Scoreboard_DrawMedal(pos, "gfx/medal/impressive", height, pl.(scores(SP_MEDAL_IMPRESSIVE)));
+ pos = Scoreboard_DrawMedal(pos, "gfx/medal/yoda", height, pl.(scores(SP_MEDAL_YODA)));
+ pos = Scoreboard_DrawMedal(pos, "gfx/medal/telefrag", height, pl.(scores(SP_MEDAL_TELEFRAG)));
+
+ if(total_medals)
+ pos.x += hud_fontsize.x;
+
+ pos = Scoreboard_DrawMedal(pos, "gfx/medal/accuracy", height, pl.(scores(SP_MEDAL_ACCURACY)));
+ pos = Scoreboard_DrawMedal(pos, "gfx/medal/assist", height, pl.(scores(SP_MEDAL_ASSIST)));
+ pos = Scoreboard_DrawMedal(pos, "gfx/medal/capture", height, pl.(scores(SP_MEDAL_CAPTURE)));
+ pos = Scoreboard_DrawMedal(pos, "gfx/medal/defense", height, pl.(scores(SP_MEDAL_DEFENSE)));
+ pos = Scoreboard_DrawMedal(pos, "gfx/medal/perfect", height, pl.(scores(SP_MEDAL_PERFECT)));
+
+ if(!total_medals) return orig;
+
+ drawstring(title_pos, sprintf(_("Medal stats (total %d)"), total_medals),
+ hud_fontsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ pos.x = orig.x;
+ pos.y += height + hud_fontsize.y * 0.5;
+ return pos;
+}
+
float average_accuracy;
vector Scoreboard_AccuracyStats_Draw(vector pos, vector rgb, vector bg_size)
{
vector Scoreboard_ItemStats_Draw(vector pos, vector rgb, vector bg_size)
{
+ Inventory g_inventory = inventoryslots[current_player];
scoreboard_itemstats_fade_alpha = min(scoreboard_fade_alpha, scoreboard_itemstats_fade_alpha + frametime * 10);
int disowned_cnt = 0;
return pos;
}
+/*
vector Scoreboard_MapStats_Draw(vector pos, vector rgb, vector bg_size) {
float stat_secrets_found, stat_secrets_total;
float stat_monsters_killed, stat_monsters_total;
panel_size.x += panel_bg_padding * 2; // restore initial width
return end_pos;
}
+*/
vector Scoreboard_Rankings_Draw(vector pos, string ranktitle, entity pl, vector rgb, vector bg_size)
{
bool have_item_stats;
bool Scoreboard_ItemStats_WouldDraw(float ypos)
{
+ Inventory g_inventory = inventoryslots[current_player];
+
if (MUTATOR_CALLHOOK(DrawScoreboardItemStats))
return false;
if (!autocvar_hud_panel_scoreboard_itemstats || !g_inventory || warmup_stage || ypos > 0.91 * vid_conheight)
return false;
+ if (gametype == MAPINFO_TYPE_DUEL) // z411 : We already show items in our duel scoreboard.
+ return false;
if (time < scoreboard_time + autocvar_hud_panel_scoreboard_itemstats_showdelay
&& ypos > autocvar_hud_panel_scoreboard_itemstats_showdelay_minpos * vid_conheight
sb_gameinfo_type_fontsize = hud_fontsize * 2.5;
sb_gameinfo_detail_fontsize = hud_fontsize * 1.3;
+ // z411 server name
+ //drawcolorcodedstring(pos, "bienvenidoainternet.org", sb_gameinfo_type_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+ //drawpic_aspect(pos + '1 0 0' * (panel_size.x - 150), "gfx/bai_logo", vec2(150, sb_gameinfo_type_fontsize.y), '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ //pos.y += sb_gameinfo_type_fontsize.y;
+
// Game Info: Game Type
if (scoreboard_ui_enabled == 2)
str = _("Team Selection");
else
str = MapInfo_Type_ToText(gametype);
draw_beginBoldFont();
- drawcolorcodedstring(pos + '0.5 0 0' * (panel_size.x - stringwidth(str, true, sb_gameinfo_type_fontsize)), str, sb_gameinfo_type_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+ //drawcolorcodedstring(pos + '0.5 0 0' * (panel_size.x - stringwidth(str, true, sb_gameinfo_type_fontsize)), str, sb_gameinfo_type_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawcolorcodedstring(pos, str, sb_gameinfo_type_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
draw_endBoldFont();
-
+
+ vector tmp_old_sz = draw_getimagesize("gfx/bai_logo");
+ float tmp_aspect = tmp_old_sz.x/tmp_old_sz.y;
+ vector tmp_new_sz = vec2(sb_gameinfo_type_fontsize.y * tmp_aspect, sb_gameinfo_type_fontsize.y);
+
+ // z411 Server logo
+ drawpic(pos + '1 0 0' * (panel_size.x - tmp_new_sz.x), "gfx/bai_logo", tmp_new_sz, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+
pos.y += sb_gameinfo_type_fontsize.y;
+
+ // z411 servername
+ drawcolorcodedstring(pos + '0.5 0 0' * (panel_size.x - stringwidth_colors(hostname_full, sb_gameinfo_detail_fontsize)), hostname_full, sb_gameinfo_detail_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ pos.y += sb_gameinfo_detail_fontsize.y;
+
// Game Info: Game Detail
if (scoreboard_ui_enabled == 2)
{
str = strcat(str, Scoreboard_Fraglimit_Draw(ll, true));
}
}
+
drawcolorcodedstring(pos + '1 0 0' * (panel_size.x - stringwidth(str, true, sb_gameinfo_detail_fontsize)), str, sb_gameinfo_detail_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL); // align right
// map name and player count
if (campaign)
if (autocvar_hud_panel_scoreboard_team_size_position != 1) // team size not on left
{
// put team score to the left of scoreboard (and team size to the right)
- team_score_baseoffset = eY * hud_fontsize.y - eX * hud_fontsize.x * 0.5;
+ team_score_baseoffset = eY * hud_fontsize.y - eX * hud_fontsize.x * 1.5;
team_size_baseoffset = eY * hud_fontsize.y + eX * hud_fontsize.x * 0.5;
if(panel.current_panel_bg != "0")
{
else
{
// put team score to the right of scoreboard (and team size to the left)
- team_score_baseoffset = eY * hud_fontsize.y + eX * hud_fontsize.x * 0.5;
+ team_score_baseoffset = eY * hud_fontsize.y + eX * hud_fontsize.x * 1.5;
team_size_baseoffset = eY * hud_fontsize.y - eX * hud_fontsize.x * 0.5;
if(panel.current_panel_bg != "0")
{
if(!tm.team)
continue;
- draw_beginBoldFont();
vector rgb = Team_ColorRGB(tm.team);
+ /*draw_beginBoldFont();
str = ftos(tm.(teamscores(ts_primary)));
if (autocvar_hud_panel_scoreboard_team_size_position != 1) // team size not on left
{
// team score on the left (default)
- str_pos = pos + team_score_baseoffset - eX * stringwidth(str, false, hud_fontsize * 1.5);
+ str_pos = pos + team_score_baseoffset - eX * stringwidth(str, false, hud_fontsize * 3);
}
else
{
// team score on the right
- str_pos = pos + team_score_baseoffset + eX * (panel_size.x + hud_fontsize.x * 1.5);
+ str_pos = pos + team_score_baseoffset + eX * (panel_size.x + hud_fontsize.x * 3);
}
- drawstring(str_pos, str, hud_fontsize * 1.5, rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawstring(str_pos, str, hud_fontsize * 3, rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
// team size (if set to show on the side)
if (autocvar_hud_panel_scoreboard_team_size_position != 0) // team size not off
drawstring(str_pos, str, hud_fontsize, rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
}
draw_endBoldFont();
+ */
+
+ // z411 My team header
+ // Score: highlight
+ drawfill(pos, team_score_size, rgb * 0.5, sbt_highlight_alpha, DRAWFLAG_NORMAL);
+
+ // Score: text
+ str = ftos(tm.(teamscores(ts_primary)));
+ str_pos = pos;
+ str_pos.x += (team_score_size.x / 2) - (stringwidth(str, true, team_score_fontsize) / 2);
+ str_pos.y += (team_score_size.y / 2) - (team_score_fontsize.y / 2);
+
+ draw_beginBoldFont();
+ drawstring(str_pos, str, team_score_fontsize, rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
+ draw_endBoldFont();
+
+ // Team name
+ str = Team_CustomName(tm.team);
+ str_pos = pos;
+ str_pos.x += team_score_size.x + team_name_fontsize.x * 0.5;
+ str_pos.y += (team_score_size.y / 2) - (team_name_fontsize.y / 2);
+ drawcolorcodedstring(str_pos, str, team_name_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ pos.y += team_score_size.y + (hud_fontsize.y * 0.5);
+
if(autocvar_hud_panel_scoreboard_bg_teams_color_team > 0)
panel_bg_color = rgb * autocvar_hud_panel_scoreboard_bg_teams_color_team;
else if(panel_bg_color_team > 0)
}
panel_bg_color = panel_bg_color_save;
}
+ else if(gametype == MAPINFO_TYPE_DUEL)
+ {
+ for(tm = teams.sort_next; tm; tm = tm.sort_next)
+ if(tm.team != NUM_SPECTATOR)
+ break;
+
+ // z411 make DUEL TABLE
+ pos = Scoreboard_MakeDuelTable(pos, tm, panel_bg_color, bg_size);
+ }
else
{
for(tm = teams.sort_next; tm; tm = tm.sort_next)
pos = Scoreboard_MakeTable(pos, tm, panel_bg_color, bg_size);
}
+ pos = Scoreboard_MedalStats_Draw(pos);
+
// draw scoreboard spectators before accuracy and item stats
if (autocvar_hud_panel_scoreboard_spectators_position == 0) {
pos = Scoreboard_Spectators_Draw(pos);
pos = Scoreboard_Spectators_Draw(pos);
}
- pos = Scoreboard_MapStats_Draw(pos, panel_bg_color, bg_size);
+ //pos = Scoreboard_MapStats_Draw(pos, panel_bg_color, bg_size);
// draw scoreboard spectators after mapstats
if (autocvar_hud_panel_scoreboard_spectators_position == 3) {
--- /dev/null
+#include "spect.qh"
+
+#include <client/hud/hud.qh>
+#include <client/view.qh>
+#include <client/draw.qh>
+#include <client/shownames.qh>
+#include <client/hud/panel/healtharmor.qh>
+#include <common/ent_cs.qh>
+#include <common/gamemodes/gamemode/duel/duel.qh>
+#include <common/resources/cl_resources.qh>
+
+vector teamscore_size;
+vector teamscore_fontsize;
+vector teamname_fontsize;
+
+void HUD_SpectHUD_Export(int fh)
+{
+ // allow saving cvars that aesthetically change the panel into hud skin files
+}
+
+void HUD_SpectHUD_drawCurrentName(vector pos)
+{
+ vector tmp;
+ string s;
+
+ tmp = pos;
+
+ s = entcs_GetName(current_player);
+ tmp.x -= stringwidth_colors(s, hud_fontsize * 2) / 2;
+ drawcolorcodedstring(tmp, s, hud_fontsize * 2, panel_fg_alpha, DRAWFLAG_NORMAL);
+
+ tmp = pos;
+ s = (entcs_GetRank(current_player) != "" ? entcs_GetRank(current_player) : "Spectating");
+ tmp.x -= stringwidth_colors(s, hud_fontsize) / 2;
+ tmp.y -= hud_fontsize.y;
+ drawcolorcodedstring(tmp, s, hud_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+}
+
+void HUD_SpectHUD_drawTeamPlayers(vector pos, entity tm, vector rgb, bool invert)
+{
+ vector tmp_over;
+ vector line_sz = vec2((vid_conwidth - 1) / 7, hud_fontsize.y * 1.5);
+ vector line_sz_sub = vec2((vid_conwidth - 1) / 7, hud_fontsize.y);
+
+ string playername;
+ float a = panel_fg_alpha * 0.8;
+ entity pl;
+
+ if(invert)
+ pos.x -= line_sz.x + hud_fontsize.x;
+ else
+ pos.x += hud_fontsize.x;
+
+ for(pl = players.sort_next; pl; pl = pl.sort_next)
+ {
+ if(pl.team != tm.team)
+ continue;
+
+ float health = 0;
+ float armor = 0;
+ string icon = "";
+ vector icon_size = '0 0 0';
+ vector icon_rgb = '1 1 1';
+
+ // Position and size calculation vectors
+ tmp_over = pos;
+ vector total_sz = vec2(line_sz.x, line_sz.y + line_sz_sub.y);
+
+ bool dead = entcs_IsDead(pl.sv_entnum) || pl.eliminated;
+
+ if(dead) {
+ // z411 TODO : Unhardcode luma
+ icon = "gfx/hud/luma/notify_death.tga";
+ icon_rgb = rgb;
+ } else {
+ entity entcs = entcs_receiver(pl.sv_entnum);
+ if(entcs.m_entcs_private) {
+ health = (min(entcs.healthvalue, autocvar_hud_panel_healtharmor_maxhealth) / autocvar_hud_panel_healtharmor_maxhealth) * line_sz.x;
+ armor = (min(GetResource(entcs, RES_ARMOR), autocvar_hud_panel_healtharmor_maxarmor) / autocvar_hud_panel_healtharmor_maxarmor) * line_sz_sub.x;
+
+ Weapon wep = REGISTRY_GET(Weapons, entcs.activewepid);
+ icon = strcat("gfx/hud/luma/", wep.model2);
+ } else {
+ if(tm.team == NUM_TEAM_1)
+ icon = "gfx/hud/luma/player_red";
+ else if(tm.team == NUM_TEAM_2)
+ icon = "gfx/hud/luma/player_blue";
+ else if(tm.team == NUM_TEAM_3)
+ icon = "gfx/hud/luma/player_yellow";
+ else if(tm.team == NUM_TEAM_4)
+ icon = "gfx/hud/luma/player_pink";
+ else
+ icon = "gfx/hud/luma/player_neutral";
+ }
+ }
+
+ // Draw weapon
+ if(icon != "") {
+ vector tmp_sz = draw_getimagesize(icon);
+ icon_size = vec2(total_sz.y*(tmp_sz.x/tmp_sz.y), total_sz.y);
+ total_sz.x += icon_size.x;
+
+ if(invert) {
+ pos.x -= icon_size.x;
+ tmp_over.x -= icon_size.x;
+ }
+ drawpic(pos, icon, icon_size, icon_rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
+ pos.x += icon_size.x;
+ }
+
+ // Get player's name
+ string playername;
+ if(entcs_GetRank(pl.sv_entnum) != "")
+ playername = strcat(entcs_GetRank(pl.sv_entnum), "^7 ", entcs_GetName(pl.sv_entnum));
+ else
+ playername = entcs_GetName(pl.sv_entnum);
+
+ playername = textShortenToWidth(playername, line_sz.x * 0.8, hud_fontsize, stringwidth_colors);
+
+ // Draw health and name
+ drawfill(pos, line_sz, rgb * 0.7, a * 0.3, DRAWFLAG_NORMAL);
+ if(health)
+ drawfill(pos, vec2(health, line_sz.y), rgb * 0.7, a, DRAWFLAG_NORMAL);
+ drawcolorcodedstring(pos + eY * ((line_sz.y - hud_fontsize.y) / 2) + eX * (hud_fontsize.x * 0.5), playername, hud_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+ pos.y += line_sz.y;
+
+ // Draw armor
+ if(armor)
+ drawfill(pos, vec2(armor, line_sz_sub.y), rgb, a, DRAWFLAG_NORMAL);
+
+ // Highlight current player
+ if(pl.sv_entnum == current_player && spectatee_status != -1)
+ drawfill(tmp_over, total_sz, '1 1 1', 0.3, DRAWFLAG_NORMAL);
+ if(dead || pl.eliminated)
+ drawfill(tmp_over, total_sz, '0 0 0', 0.4, DRAWFLAG_NORMAL);
+
+ if(!invert)
+ pos.x -= icon_size.x;
+ pos.y += line_sz_sub.y * 2;
+ }
+}
+
+
+void HUD_SpectHUD_drawTeamScore(vector pos, entity tm, vector rgb, bool invert)
+{
+ if(!tm) return;
+
+ vector tmp;
+ string tmp_str;
+
+ // Team score
+ tmp_str = ftos(tm.(teamscores(ts_primary)));
+
+ if(invert)
+ pos.x -= teamscore_size.x;
+
+ drawfill(pos, teamscore_size, rgb * 0.8, 0.3, DRAWFLAG_NORMAL);
+
+ tmp = pos;
+ tmp.x += (teamscore_size.x - stringwidth(tmp_str, true, teamscore_fontsize)) / 2;
+ tmp.y += (teamscore_size.y - teamscore_fontsize.y) / 2;
+
+ draw_beginBoldFont();
+ drawstring(tmp, tmp_str, teamscore_fontsize, rgb, panel_fg_alpha, DRAWFLAG_NORMAL);
+ draw_endBoldFont();
+
+ // Team name
+ tmp_str = Team_CustomName(tm.team);
+
+ tmp = pos;
+ if(invert)
+ tmp.x -= stringwidth_colors(tmp_str, teamname_fontsize) + teamname_fontsize.x * 0.5;
+ else
+ tmp.x += teamscore_size.x + teamname_fontsize.x * 0.5;
+ tmp.y += (teamscore_size.y - teamname_fontsize.y) / 2;
+
+ drawcolorcodedstring(tmp, tmp_str, teamname_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+}
+
+void HUD_SpectHUD_drawDuelScore(vector pos, entity pl, bool invert)
+{
+ if(!pl) return;
+
+ vector tmp, tmp_in;
+ string tmp_str;
+ vector health_sz = vec2((vid_conwidth - 1) / 6, teamscore_size.y * 0.4);
+ vector armor_sz = vec2(health_sz.x, health_sz.y / 4);
+ vector total_sz = vec2(health_sz.x + teamscore_size.x + (teamscore_size.x * 0.1), teamscore_size.y);
+
+ float health = 0;
+ float armor = 0;
+
+ entity entcs = entcs_receiver(pl.sv_entnum);
+ if(entcs.m_entcs_private) {
+ health = (min(entcs.healthvalue, autocvar_hud_panel_healtharmor_maxhealth) / autocvar_hud_panel_healtharmor_maxhealth) * health_sz.x;
+ armor = (min(GetResource(entcs, RES_ARMOR), autocvar_hud_panel_healtharmor_maxarmor) / autocvar_hud_panel_healtharmor_maxarmor) * armor_sz.x;
+ }
+
+ if(invert)
+ pos.x -= teamscore_size.x;
+
+ // Highlight current player
+ tmp = pos;
+ if(invert) tmp.x -= health_sz.x + (teamscore_size.x * 0.1);
+
+ if(pl.sv_entnum == current_player && spectatee_status != -1)
+ drawfill(tmp, total_sz, '1 1 1', 0.3, DRAWFLAG_NORMAL);
+
+ if(entcs_IsDead(pl.sv_entnum))
+ drawfill(tmp, total_sz, '0 0 0', 0.4, DRAWFLAG_NORMAL);
+
+ // Player score
+ tmp_str = ftos(pl.(scores(ps_primary)));
+
+ drawfill(pos, teamscore_size, '0 0 0', 0.3, DRAWFLAG_NORMAL);
+
+ tmp = pos;
+ tmp.x += (teamscore_size.x - stringwidth(tmp_str, true, teamscore_fontsize)) / 2;
+ tmp.y += (teamscore_size.y - teamscore_fontsize.y) / 2;
+
+ draw_beginBoldFont();
+ drawstring(tmp, tmp_str, teamscore_fontsize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ draw_endBoldFont();
+
+ // Player health/armor
+ tmp_in = pos;
+ tmp_in.y += ((teamscore_size.y / 2) - health_sz.y) / 2;
+
+ // Background
+ tmp = tmp_in;
+ if(invert)
+ tmp.x -= health_sz.x;
+ else
+ tmp.x += teamscore_size.x;
+
+ drawfill(tmp, health_sz, '0 0 0', 0.3, DRAWFLAG_NORMAL);
+
+ // Bars
+ if(health) {
+ tmp = tmp_in;
+ if(invert)
+ tmp.x -= health;
+ else
+ tmp.x += teamscore_size.x;
+
+ drawfill(tmp, vec2(health, health_sz.y), autocvar_hud_progressbar_health_color, 0.7, DRAWFLAG_NORMAL);
+ }
+
+ if(armor) {
+ tmp = tmp_in;
+ //tmp.y += health_sz.y - armor_sz.y;
+ tmp.y += health_sz.y;
+
+ if(invert)
+ tmp.x -= armor;
+ else
+ tmp.x += teamscore_size.x;
+
+ drawfill(tmp, vec2(armor, armor_sz.y), autocvar_hud_progressbar_armor_color, 0.7, DRAWFLAG_NORMAL);
+ }
+
+ // Align vertically
+ tmp = pos;
+ tmp.y += ((teamscore_size.y / 2) - teamname_fontsize.y) / 2;
+ tmp.y += teamscore_size.y / 2;
+
+ // RJZ rank
+ string rank_str = entcs_GetRank(pl.sv_entnum);
+ if(rank_str != "") {
+ if(invert)
+ tmp.x -= stringwidth_colors(rank_str, teamname_fontsize) + teamname_fontsize.x * 0.5;
+ else
+ tmp.x += teamscore_size.x + teamname_fontsize.x * 0.5;
+
+ draw_beginBoldFont();
+ drawcolorcodedstring(tmp, rank_str, teamname_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+ draw_endBoldFont();
+ }
+
+ // Player name
+ tmp_str = entcs_GetName(pl.sv_entnum);
+
+ if(invert)
+ tmp.x -= stringwidth_colors(tmp_str, teamname_fontsize) + teamname_fontsize.x * 0.5;
+ else
+ tmp.x += (rank_str != "" ? stringwidth_colors(rank_str, teamname_fontsize) : teamscore_size.x) + teamname_fontsize.x * 0.5;
+
+ drawcolorcodedstring(tmp, tmp_str, teamname_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
+}
+
+void HUD_SpectHUD()
+{
+ if(!spectatee_status) return;
+
+ vector pos, rgb;
+ float ammo_y, timer_width;
+ entity tm;
+
+ // Set main vars
+ HUD_Panel_LoadCvars();
+ HUD_Scale_Enable();
+ hud_fontsize = HUD_GetFontsize("hud_fontsize");
+
+ // Spectator name
+ if (autocvar_hud_panel_spect_playername)
+ {
+ if(spectatee_status != -1) {
+ ammo_y = stov(cvar_string("hud_panel_ammo_pos")).y * vid_conheight;
+ pos = panel_pos + vec2((vid_conwidth - 1) / 2, (ammo_y - (hud_fontsize.y * 2)));
+ HUD_SpectHUD_drawCurrentName(pos);
+ }
+ }
+
+ // Scores
+ if (!autocvar_hud_panel_spect_scores) return;
+ if (teamplay)
+ {
+ // Set vars
+ teamscore_fontsize = hud_fontsize * 3;
+ teamname_fontsize = hud_fontsize * 2;
+ teamscore_size = vec2(teamscore_fontsize.x * 1.5, teamscore_fontsize.y * 1.25);
+ timer_width = stov(cvar_string("hud_panel_timer_size")).x * vid_conwidth;
+
+ // Team 1
+ pos = panel_pos + vec2((vid_conwidth - 1) / 2, 0);
+ tm = GetTeam(NUM_TEAM_1, false);
+ rgb = Team_ColorRGB(tm.team);
+ pos.x -= (timer_width * 1.3) / 2;
+ HUD_SpectHUD_drawTeamScore(pos, tm, rgb, true);
+
+ pos = panel_pos + vec2(0, (vid_conheight - 1) / 4 + hud_fontsize.y);
+ HUD_SpectHUD_drawTeamPlayers(pos, tm, rgb, false);
+
+ // Team 2
+ pos = panel_pos + vec2((vid_conwidth - 1) / 2, 0);
+ tm = GetTeam(NUM_TEAM_2, false);
+ rgb = Team_ColorRGB(tm.team);
+ pos.x += (timer_width * 1.3) / 2;
+ HUD_SpectHUD_drawTeamScore(pos, tm, rgb, false);
+
+ pos = panel_pos + vec2(vid_conwidth - 1, (vid_conheight - 1) / 4 + hud_fontsize.y);
+ HUD_SpectHUD_drawTeamPlayers(pos, tm, rgb, true);
+
+ // Team 3
+ pos = panel_pos + vec2((vid_conwidth - 1) / 2, 41);
+ tm = GetTeam(NUM_TEAM_3, false);
+ rgb = Team_ColorRGB(tm.team);
+ pos.x -= (timer_width * 1.3) / 2;
+ HUD_SpectHUD_drawTeamScore(pos, tm, rgb, true);
+
+ pos = panel_pos + vec2(0, (vid_conheight + 450) / 4 + hud_fontsize.y);
+ HUD_SpectHUD_drawTeamPlayers(pos, tm, rgb, false);
+
+ // Team 4
+ pos = panel_pos + vec2((vid_conwidth - 1) / 2, 41);
+ tm = GetTeam(NUM_TEAM_4, false);
+ rgb = Team_ColorRGB(tm.team);
+ pos.x += (timer_width * 1.3) / 2;
+ HUD_SpectHUD_drawTeamScore(pos, tm, rgb, false);
+
+ pos = panel_pos + vec2(vid_conwidth - 1, (vid_conheight + 450) / 4 + hud_fontsize.y);
+ HUD_SpectHUD_drawTeamPlayers(pos, tm, rgb, true);
+ } else if(gametype == MAPINFO_TYPE_DUEL) {
+ // Set vars
+ teamscore_fontsize = hud_fontsize * 3;
+ teamname_fontsize = hud_fontsize * 1.5;
+ teamscore_size = vec2(teamscore_fontsize.x * 1.5, teamscore_fontsize.y * 1.25);
+ timer_width = stov(cvar_string("hud_panel_timer_size")).x * vid_conwidth;
+
+ entity pl_left = players.sort_next;
+ entity pl_right = pl_left.sort_next;
+
+ // Left player
+ if(pl_left && (entcs_GetSpecState(pl_left.sv_entnum)) != ENTCS_SPEC_PURE) {
+ pos = panel_pos + vec2((vid_conwidth - 1) / 2, 0);
+ pos.x -= (timer_width * 1.3) / 2;
+ HUD_SpectHUD_drawDuelScore(pos, pl_left, true);
+ }
+
+ // Right player
+ if(pl_right && (entcs_GetSpecState(pl_right.sv_entnum)) != ENTCS_SPEC_PURE) {
+ pos = panel_pos + vec2((vid_conwidth - 1) / 2, 0);
+ pos.x += (timer_width * 1.3) / 2;
+ HUD_SpectHUD_drawDuelScore(pos, pl_right, false);
+ }
+ }
+}
--- /dev/null
+#pragma once
+#include "../panel.qh"
#include <client/view.qh>
// Timer (#5)
+float last_timeleft;
+int autocvar_cl_timer_countdown = 3; // 0 = disabled, 1 = always on, 2 = only spec, 3 = as dictated by server
void HUD_Timer_Export(int fh)
{
vector timer_color = '1 1 1';
vector subtimer_color = '1 1 1';
bool swap = (autocvar_hud_panel_timer_secondary == 2 && STAT(ROUNDSTARTTIME));
+ float timeout_last = STAT(TIMEOUT_LAST);
// Use real or frozen time and get the time limit
curtime = (intermission_time ? intermission_time : time);
if(!intermission_time && !warmup_stage && timelimit > 0)
timer_color = HUD_Timer_Color(timeleft);
+ // countdown sound
+ // if 3 use server dictated option, otherwise the client's
+ int countdown_type;
+ if(autocvar_cl_timer_countdown == 3)
+ countdown_type = sv_timer_countdown;
+ else
+ countdown_type = autocvar_cl_timer_countdown;
+
+ if(countdown_type && !warmup_stage && timeleft > 0 && timeleft != last_timeleft && timeleft <= 10 && !intermission_time)
+ {
+ if(countdown_type == 1 || (countdown_type == 2 && spectatee_status))
+ sound(NULL, CH_INFO, SND_ENDCOUNT, VOL_BASE, ATTN_NONE);
+
+ last_timeleft = timeleft;
+ }
+
// Timer text
- if (autocvar_hud_panel_timer_increment || timelimit <= 0)
+ if (timelimit == -1)
+ timer = (autocvar_hud_panel_timer_increment ? 0 : STAT(TIMELIMIT) * 60);
+ else if (autocvar_hud_panel_timer_increment || timelimit <= 0)
timer = HUD_Timer_TimeElapsed(curtime, STAT(GAMESTARTTIME));
else
timer = timeleft;
subtimer_str = "--:--";
subtimer_color = '1 0 0';
} else {
- float round_curtime, round_timelimit, round_timeleft;
+ float round_curtime, round_endtime, round_timelimit, round_timeleft;
// Use real or frozen time and get the time limit
- round_curtime = (game_stopped_time ? game_stopped_time : time);
+ round_endtime = STAT(ROUNDENDTIME);
round_timelimit = STAT(ROUND_TIMELIMIT);
+ if(round_endtime)
+ round_curtime = round_endtime;
+ else if(timeout_last)
+ round_curtime = timeout_last;
+ else
+ round_curtime = time;
+
// Calculate time left
round_timeleft = HUD_Timer_TimeLeft(round_curtime, STAT(ROUNDSTARTTIME), round_timelimit);
int overtimes = STAT(OVERTIMES);
if(warmup_stage || autocvar__hud_configure)
- {
- if (STAT(WARMUP_TIMELIMIT) > 0)
- subtext = _("Warmup");
- else
- {
- Scoreboard_UpdatePlayerTeams(); // ensure numplayers is current
- if (srv_minplayers - numplayers > 0)
- subtext = _("Warmup: too few players");
- else
- subtext = _("Warmup: no time limit");
- }
- }
+ subtext = _("Warmup");
else if(STAT(TIMEOUT_STATUS) == 2)
subtext = _("Timeout");
- else if (overtimes == -1)
- subtext = _("Sudden Death");
- else if(overtimes == 1)
- subtext = _("Overtime");
- else if (overtimes >= 2)
+ else if(overtimes >= 2)
subtext = sprintf(_("Overtime #%d"), overtimes);
+ else if(overtimes != 0)
+ subtext = _("Overtime");
subtext_size = vec2(mySize.x, mySize.y / 3);
timer_size = vec2(mySize.x, mySize.y - subtext_size.y);
bool weapons_orderbyimpulse_old;
void HUD_Weapons()
{
+ if(spectatee_status && teamplay) return; // z411
+
// declarations
WepSet weapons_stat = WepSet_GetFromStat();
int i;
}
// draw the weapon accuracy
- if(autocvar_hud_panel_weapons_accuracy)
+ /* z411 if(autocvar_hud_panel_weapons_accuracy)
{
float panel_weapon_accuracy = weapon_accuracy[it.m_id-WEP_FIRST];
if(panel_weapon_accuracy >= 0)
color = Accuracy_GetColor(panel_weapon_accuracy);
drawpic_aspect_skin(weapon_pos, "weapon_accuracy", weapon_size, color, panel_fg_alpha, DRAWFLAG_NORMAL);
}
- }
+ }*/
vector weapon_size_real = noncurrent_size;
float weapon_alpha_real = noncurrent_alpha;
registercvar("cl_weapon_switch_fallback_to_impulse", "1");
registercvar("cl_allow_uidranking", "1");
+
+ // z411
+ registercvar("cl_chat_sounds", "1");
if(autocvar_cl_lockview)
cvar_set("cl_lockview", "0");
NET_HANDLE(ENT_CLIENT_ACCURACY, bool isnew)
{
make_pure(this);
+ float entnum = ReadByte();
+
int sf = ReadInt24_t();
if (sf == 0) {
for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w)
int f = 1;
for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w) {
if (sf & f) {
- int b = ReadByte();
- if (b == 0)
- weapon_accuracy[w] = -1;
- else if (b == 255)
- weapon_accuracy[w] = 1.0; // no better error handling yet, sorry
- else
- weapon_accuracy[w] = (b - 1.0) / 100.0;
+ if(entnum > 0) {
+ playerslots[entnum-1].accuracy_frags[w] = ReadByte();
+ playerslots[entnum-1].accuracy_hit[w] = ReadShort();
+ playerslots[entnum-1].accuracy_cnt_hit[w] = ReadShort();
+ playerslots[entnum-1].accuracy_cnt_fired[w] = ReadShort();
+
+ //LOG_INFOF("Duel stats ?/%d", playerslots[entnum-1].accuracy_cnt_fired[w]);
+ } else {
+ int b = ReadByte();
+ if (b == 0)
+ weapon_accuracy[w] = -1;
+ else if (b == 255)
+ weapon_accuracy[w] = 1.0; // no better error handling yet, sorry
+ else
+ weapon_accuracy[w] = (b - 1.0) / 100.0;
+ }
}
f = (f == 0x800000) ? 1 : f * 2;
}
serverflags = ReadByte();
g_trueaim_minrange = ReadCoord();
+
+ strcpy(hostname_full, ReadString());
+ strcpy(motd_permanent, ReadString());
+
+ sv_timer_countdown = ReadByte();
return = true;
if (!postinit) PostInit();
}
+NET_HANDLE(TE_CSQC_TEAMNAMES, bool isNew)
+{
+ teamname_red = strzone(ReadString());
+ teamname_blue = strzone(ReadString());
+ teamname_yellow = strzone(ReadString());
+ teamname_pink = strzone(ReadString());
+
+ return = true;
+}
+
+NET_HANDLE(TE_CSQC_CHATSOUND, bool isNew)
+{
+ string snd = ReadString();
+ snd = strcat("chat/", snd, ".ogg");
+
+ precache_sound(snd);
+ _sound(NULL, CH_INFO, snd, VOL_BASE, ATTN_NONE);
+
+ return = true;
+}
+
float GetSpeedUnitFactor(int speed_unit)
{
switch(speed_unit)
#include <common/constants.qh>
#include <common/weapons/_all.qh>
+#include <common/items/inventory.qh>
+
+// z411
+string hostname_full;
+string motd_permanent;
+int sv_timer_countdown;
bool autocvar_cl_db_saveasdump;
bool autocvar_cl_spawn_event_particles;
.int enttype; // entity type sent from server
.int sv_entnum; // entity number sent from server
+// z411 accuracy info
+.float accuracy_frags[REGISTRY_MAX(Weapons)];
+.float accuracy_hit[REGISTRY_MAX(Weapons)];
+.float accuracy_cnt_hit[REGISTRY_MAX(Weapons)];
+.float accuracy_cnt_fired[REGISTRY_MAX(Weapons)];
+
.int team;
.int team_size;
+.int countrycode;
+.string rank;
int binddb;
float ticrate;
int serverflags;
+
float kill_time = STAT(KILL_TIME);
if (COMPARE_INCREASING(kill_time, kill_time_prev) > autocvar_cl_hitsound_antispam_time)
{
- sound(NULL, CH_INFO, SND_KILL, VOL_BASE, ATTN_NONE);
+ sound(NULL, CH_INFO, SND_KILL, VOL_BASE * 1.15, ATTN_NONE);
kill_time_prev = kill_time;
}
}
myhealth_flash += autocvar_hud_damage_fade_rate * frametime; // dead
}
}
+
+ if(myhealth_prev > 1 && myhealth <= 0 && !intermission)
+ {
+ // Just died
+ sound(NULL, CH_INFO, SND_DEATH, VOL_BASE, ATTN_NONE);
+ }
if(spectatee_status == -1 || intermission)
{
noref float autocvar_net_connecttimeout = 30;
+#include "announcer.qc"
+#include "colors.qc"
#include "checkextension.qc"
#ifdef GAMEQC
--- /dev/null
+//FEATURE: Custom default announcers on the server side, that clients can override if desired
+
+#ifdef GAMEQC
+REGISTER_MUTATOR(announcer, true);
+#endif
+
+#ifdef SVQC
+
+AUTOCVAR(sv_announcer, string, "", "Force client announcer to this");
+
+MUTATOR_HOOKFUNCTION(announcer, Ent_Init, CBC_ORDER_FIRST)
+{
+ WriteString(MSG_ONE, autocvar_sv_announcer);
+}
+
+#elif defined(CSQC)
+
+string sv_announcer;
+
+AUTOCVAR_SAVE(cl_announcer_force, bool, false, "Don't allow server to override default announcer");
+
+void Announcer_Precache()
+{
+ FOREACH(Notifications, it.nent_type == MSG_ANNCE, {
+ if(it.nent_enabled)
+ precache_sound(sprintf("announcer/%s/%s.wav", AnnouncerOption(), it.nent_snd));
+ });
+}
+
+MUTATOR_HOOKFUNCTION(announcer, AnnouncerOption)
+{
+ if(autocvar_cl_announcer_force || sv_announcer == "" || !sv_announcer || autocvar_cl_announcer != "default")
+ return false;
+
+ M_ARGV(0, string) = sv_announcer;
+}
+
+MUTATOR_HOOKFUNCTION(announcer, Ent_Init, CBC_ORDER_FIRST)
+{
+ sv_announcer = strzone(ReadString());
+
+ if(sv_announcer != "" && sv_announcer) { Announcer_Precache(); }
+}
+
+#endif
--- /dev/null
+#ifdef GAMEQC
+
+string mod_translate_clean(string s)
+{
+ if(ColorTranslateMode & 1)
+ return strdecolorize(s);
+
+ if(s == "" || !s)
+ return s;
+
+ s = strreplace("^x664", "^7", s);
+ s = strreplace("^x665", "^3", s);
+ s = strreplace("^x666", "^1", s);
+ s = strreplace("^x667", "^2", s);
+ s = strreplace("^x668", "^4", s);
+ s = strreplace("^x669", "^0", s);
+ return s;
+}
+
+string mod_playername(string thename, int teamid, bool team_colorize)
+{
+ TC(int, teamid);
+ bool do_colorize = (teamplay && team_colorize && Team_IsValidTeam(teamid));
+
+#ifdef SVQC
+ if(do_colorize && !intermission_running)
+#else
+ if(do_colorize)
+#endif
+ {
+ string t = Team_ColorCode(teamid);
+ return strcat(t, strdecolorize(thename));
+ }
+ else
+ return mod_translate_clean(thename);
+}
+
+#endif
+
+#ifdef CSQC
+AUTOCVAR(cl_stripfancystuff, bool, false, "Turn off the fancy blinking colorful names");
+
+vector mod_get_num_color(int num)
+{
+ vector color;
+ float thenum = 0;
+ switch(num)
+ {
+ case 1: color = vec3(sin(2 * M_PI * time), 1, sin(2 * M_PI * time)); thenum = 200; break;
+ default:
+ case 2: color = '1 0 0'; thenum = 1; break;
+ case 3: color = '0 0 1'; thenum = 1; break;
+ case 4: color = vec3(1, 1, sin(2 * M_PI * time)); thenum = 200; break;
+ case 5: color = vec3(sin(2 * M_PI * time), sin(2 * M_PI * time), sin(2 * M_PI * time)); thenum = 200; break;
+ case 6: color = '1 1 1'; thenum = 1; break;
+ case 7: color = vec3(0.69, 0.12, sin(2 * M_PI * time)); thenum = 200; break;
+ }
+
+ float blinkingamt = (1 - thenum/200/0.25);
+ if(blinkingamt > 0)
+ {
+ color.x = color.x - color.x * blinkingamt * sin(2*M_PI*time);
+ color.y = color.y - color.y * blinkingamt * sin(2*M_PI*time);
+ color.z = color.z - color.z * blinkingamt * sin(2*M_PI*time);
+ }
+ return color;
+}
+
+string mod_translate(string s)
+{
+ if(autocvar_cl_stripfancystuff)
+ return mod_translate_clean(s);
+
+ if(ColorTranslateMode & 1)
+ return strdecolorize(s);
+
+ if(s == "" || !s)
+ return s;
+
+ string theword = "";
+ int fancy = 0;
+ FOREACH_CHAR(s, true,
+ {
+ string realch = chr2str(it);
+ if(realch == "^")
+ {
+ string nc1 = chr2str(str2chr(iter_s, iter_i));
+ string nc2 = chr2str(str2chr(iter_s, iter_i + 1));
+ string nc3 = chr2str(str2chr(iter_s, iter_i + 2));
+ string nc4 = chr2str(str2chr(iter_s, iter_i + 3));
+ int fc4 = stoi(nc4);
+ if(nc1 == "x" && nc2 == "6" && nc3 == "6" && (fc4 >= 3 && fc4 <= 9)) // so far so good
+ {
+ switch(fc4)
+ {
+ case 3: fancy = 7; break;
+ case 4: fancy = 6; break;
+ case 5: fancy = 4; break;
+ default:
+ case 6: fancy = 2; break;
+ case 7: fancy = 1; break;
+ case 8: fancy = 3; break;
+ case 9: fancy = 5; break;
+ }
+ int pos = iter_i + 4; // skip the color code
+ STRING_ITERATOR_LOAD(iter, pos);
+ continue;
+ }
+ else
+ {
+ fancy = 0;
+ // not a valid hax, but also a color, add normally and continue!
+ theword = strcat(theword, realch);
+ continue;
+ }
+ }
+ else if(fancy)
+ {
+ vector thecolor = mod_get_num_color(fancy);
+ thecolor.x = bound(0, thecolor.x, 1);
+ thecolor.y = bound(0, thecolor.y, 1);
+ thecolor.z = bound(0, thecolor.z, 1);
+ theword = strcat(theword, rgb_to_hexcolor(thecolor), strdecolorize(realch));
+ }
+ else
+ theword = strcat(theword, realch);
+ });
+
+ return theword;
+}
+
+void mod_parse_print(string strMessage)
+{
+ if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_Print(\"%s\")", strMessage);
+ print(mod_translate_clean(strMessage));
+}
+
+string mod_ccr(string input)
+{
+ // See the autocvar declarations in util.qh for default values
+
+ // foreground/normal colors
+ input = strreplace("^F1", strcat("^", autocvar_hud_colorset_foreground_1), input);
+ input = strreplace("^F2", strcat("^", autocvar_hud_colorset_foreground_2), input);
+ input = strreplace("^F3", strcat("^", autocvar_hud_colorset_foreground_3), input);
+ input = strreplace("^F4", strcat("^", autocvar_hud_colorset_foreground_4), input);
+
+ // "kill" colors
+ input = strreplace("^K1", strcat("^", autocvar_hud_colorset_kill_1), input);
+ input = strreplace("^K2", strcat("^", autocvar_hud_colorset_kill_2), input);
+ input = strreplace("^K3", strcat("^", autocvar_hud_colorset_kill_3), input);
+
+ // background colors
+ input = strreplace("^BG", strcat("^", autocvar_hud_colorset_background), input);
+ input = strreplace("^N", "^7", input); // "none"-- reset to white...
+ input = mod_translate_clean(input);
+ return input;
+}
+#endif
+
+STATIC_INIT_LATE(mod_functions_override)
+{
+#ifdef CSQC
+ ColorTranslateRGB = mod_translate;
+ CSQC_Parse_Print = mod_parse_print;
+ CCR = mod_ccr;
+ //Scoreboard_GetName = mod_scoreboard_getname;
+#elif defined(SVQC)
+ playername = mod_playername;
+#endif
+}
+
+#ifdef SVQC
+REGISTER_MUTATOR(namecolors, true);
+MUTATOR_HOOKFUNCTION(namecolors, PreFormatMessage)
+{
+ string themsg = mod_translate_clean(M_ARGV(1, string));
+
+ M_ARGV(1, string) = themsg;
+}
+#endif
ENTCS_PROP(FRAGS, true, frags, frags, ENTCS_SET_NORMAL,
{ WriteShort(chan, ent.frags); },
{ ent.frags = ReadShort(); })
+
+ENTCS_PROP(COUNTRYCODE, true, countrycode, countrycode, ENTCS_SET_NORMAL,
+ { WriteByte(chan, ent.countrycode); },
+ { ent.countrycode = ReadByte(); })
+
+ENTCS_PROP(RANK, true, rank, rank, ENTCS_SET_NORMAL,
+ { WriteString(chan, ent.rank); },
+ { strcpy(ent.rank, ReadString()); })
+
+ENTCS_PROP(WANTSJOIN, true, wants_join, wants_join, ENTCS_SET_NORMAL,
+ { WriteByte(chan, ent.wants_join); },
+ { ent.wants_join = ReadByte(); })
// use sv_solid to avoid changing solidity state of entcs entities
ENTCS_PROP(SOLID, true, sv_solid, solid, ENTCS_SET_NORMAL,
{ WriteByte(chan, ent.sv_solid); },
{ ent.sv_solid = ReadByte(); })
+// z411 weapon
+ENTCS_PROP(ACTIVEWEPID, false, activewepid, activewepid, ENTCS_SET_NORMAL,
+ { WriteByte(chan, ent.activewepid); },
+ { ent.activewepid = ReadByte(); })
+
#ifdef SVQC
int ENTCS_PUBLICMASK = 0, ENTCS_PRIVATEMASK = 0;
.bool has_sv_origin;
#endif
.int sv_solid;
+.int activewepid; // z411
#ifdef SVQC
/*
* @param i zero indexed player
*/
.int frags;
+ .int wants_join;
const int ENTCS_SPEC_PURE = 1; // real spectator
const int ENTCS_SPEC_IN_SCOREBOARD = 2; // spectator but still in game (can be in a team)
#define entcs_IsSpectating(i) boolean(entcs_GetSpecState(i))
/**
* @param i zero indexed player
+ */
+ int entcs_GetWantsJoin(int i)
+ {
+ entity e = entcs_receiver(i);
+ return e.wants_join;
+ }
+
+ /**
+ * @param i zero indexed player
*/
int entcs_GetClientColors(int i)
{
entity e = entcs_receiver(i);
return e ? ColorTranslateRGB(e.netname) : "";
}
+
+ int entcs_GetCountryCode(int i)
+ {
+ entity e = entcs_receiver(i);
+ return e.countrycode;
+ }
+
+ string entcs_GetRank(int i)
+ {
+ entity e = entcs_receiver(i);
+ return e.rank;
+ }
/**
* @param i zero indexed player
#include "cl_clanarena.qh"
-#include <client/draw.qh>
+/*#include <client/draw.qh>
#include <common/mutators/base.qh>
HUD_Mod_CA_Draw(myPos, mySize, autocvar_hud_panel_modicons_ca_layout);
}
+*/
+// Clan Arena and Freeze Tag scores
+int HUD_Scores_CA(int team)
+{
+ switch(team)
+ {
+ case NUM_TEAM_1: return STAT(REDALIVE);
+ case NUM_TEAM_2: return STAT(BLUEALIVE);
+ case NUM_TEAM_3: return STAT(YELLOWALIVE);
+ default:
+ case NUM_TEAM_4: return STAT(PINKALIVE);
+ }
+
+ return 0;
+}
\ No newline at end of file
#pragma once
-int autocvar_hud_panel_modicons_ca_layout;
-
-void HUD_Mod_CA(vector myPos, vector mySize);
-void HUD_Mod_CA_Draw(vector myPos, vector mySize, int layout);
-void HUD_Mod_CA_Export(int fh);
+int HUD_Scores_CA(int team);
#include <common/mapinfo.qh>
#ifdef CSQC
-void HUD_Mod_CA(vector pos, vector mySize);
-void HUD_Mod_CA_Export(int fh);
+//void HUD_Mod_CA(vector pos, vector mySize);
+//void HUD_Mod_CA_Export(int fh);
+int HUD_Scores_CA(int team);
#endif
CLASS(ClanArena, Gametype)
INIT(ClanArena)
returns(menu, _("Round limit:"), 5, 100, 5, "fraglimit_override", "g_ca_teams_override", _("The amount of rounds won needed before the match will end"));
}
#ifdef CSQC
- ATTRIB(ClanArena, m_modicons, void(vector pos, vector mySize), HUD_Mod_CA);
- ATTRIB(ClanArena, m_modicons_export, void(int fh), HUD_Mod_CA_Export);
+ //ATTRIB(ClanArena, m_modicons, void(vector pos, vector mySize), HUD_Mod_CA);
+ //ATTRIB(ClanArena, m_modicons_export, void(int fh), HUD_Mod_CA_Export);
+ ATTRIB(ClanArena, m_modscores, int(int team), HUD_Scores_CA);
#endif
ATTRIB(ClanArena, m_legacydefaults, string, "10 20 0");
ENDCLASS(ClanArena)
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),
+ FOREACH_CLIENT(Entity_HasValidTeam(it),
{
++total_players;
- if (IS_DEAD(it))
+ entity team_ = Entity_GetTeam(it);
+
+ int num_total = Team_GetNumberOfPlayers(team_);
+ ++num_total;
+ Team_SetNumberOfPlayers(team_, num_total);
+
+ if (IS_DEAD(it) || !IS_PLAYER(it))
{
continue;
}
- entity team_ = Entity_GetTeam(it);
+
int num_alive = Team_GetNumberOfAlivePlayers(team_);
++num_alive;
Team_SetNumberOfAlivePlayers(team_, num_alive);
void nades_Clear(entity player);
+entity ca_LastPlayer(float tm)
+{
+ entity last_pl = NULL;
+ FOREACH_CLIENT(IS_PLAYER(it) && it.team == tm, {
+ if (!IS_DEAD(it))
+ {
+ if (!last_pl)
+ last_pl = it;
+ else
+ return NULL;
+ }
+ });
+ return last_pl;
+}
+
+
int CA_PreventStalemate()
{
//bprint("PreventStalemate running\n");
if (!winner_team)
return 0;
+ bool perfect = false;
if(winner_team > 0)
{
+ entity tm = Team_GetTeam(winner_team);
+ entity last_pl = ca_LastPlayer(winner_team);
+
+ if(last_pl && Team_GetNumberOfPlayers(tm) >= 3) {
+ Give_Medal(last_pl, DEFENSE);
+ }
+
Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, APP_TEAM_NUM(winner_team, CENTER_ROUND_TEAM_WIN));
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);
+
+ if (Team_GetNumberOfPlayers(tm) >= 3 &&
+ Team_GetNumberOfAlivePlayers(tm) == Team_GetNumberOfPlayers(tm))
+ perfect = true;
}
else if(winner_team == -1)
{
Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_ROUND_TIED);
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_ROUND_TIED);
+ Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_ROUND_TIED);
}
else if(winner_team == -2)
{
Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_ROUND_OVER);
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_ROUND_OVER);
+ Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_ROUND_OVER);
}
allowed_to_spawn = false;
- game_stopped = true;
+ if(autocvar_g_ca_round_stop)
+ 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);
+
+ // Give perfect medal if everyone in the winner team is alive
+ if(perfect && it.team == winner_team) {
+ 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] > 1 && (ra.accuracy_hit[w] / ra.accuracy_fired[w]) > 0.5) {
+ Give_Medal(it, ACCURACY);
+ }
+ }
+ });
return 1;
}
return true;
}
+MUTATOR_HOOKFUNCTION(ca, Scores_CountFragsRemaining)
+{
+ // announce remaining frags
+ return true;
+}
+
MUTATOR_HOOKFUNCTION(ca, reset_map_global)
{
allowed_to_spawn = true;
if (!warmup_stage && round_handler_IsActive() && round_handler_IsRoundStarted())
{
entity pl = ca_LastPlayerForTeam(this);
- if (pl)
+ if (pl) {
Send_Notification(NOTIF_ONE, pl, MSG_CENTER, CENTER_ALONE);
+ Send_Notification(NOTIF_ONE, pl, MSG_ANNCE, ANNCE_ALONE);
+ }
}
}
return true;
}
-MUTATOR_HOOKFUNCTION(ca, Scores_CountFragsRemaining)
-{
- // announce remaining frags
- return true;
-}
-
MUTATOR_HOOKFUNCTION(ca, SpectateSet)
{
entity client = M_ARGV(0, entity);
int autocvar_g_ca_point_limit;
int autocvar_g_ca_point_leadlimit;
float autocvar_g_ca_round_timelimit;
+bool autocvar_g_ca_round_stop;
bool autocvar_g_ca_team_spawns;
//int autocvar_g_ca_teams;
int autocvar_g_ca_teams_override;
ca_teams = autocvar_g_ca_teams_override;
if (ca_teams < 2)
ca_teams = cvar("g_ca_teams"); // read the cvar directly as it gets written earlier in the same frame
+ if (autocvar_g_ca_spectate_enemies == -1)
+ observe_blocked_if_eliminated = true;
ca_teams = BITS(bound(2, ca_teams, 4));
GameRules_scoring(ca_teams, SFL_SORT_PRIO_PRIMARY, 0, {
new_time = TIME_ENCODE(time - enemy_flag.ctf_pickuptime);
if(!old_time || new_time < old_time)
GameRules_scoring_add(player, CTF_CAPTIME, new_time - old_time);
+
+ Give_Medal(player, CAPTURE);
+
+ // announcer
+ AnnounceScores(player.team);
// effects
Send_Effect_(flag.capeffect, flag.origin, '0 0 0', 1);
if(flag.speedrunning) { ctf_FakeTimeLimit(player, -1); }
if((enemy_flag.ctf_dropper) && (player != enemy_flag.ctf_dropper))
- { GameRules_scoring_add_team(enemy_flag.ctf_dropper, SCORE, ((enemy_flag.score_assist) ? enemy_flag.score_assist : autocvar_g_ctf_score_capture_assist)); }
+ {
+ GameRules_scoring_add_team(enemy_flag.ctf_dropper, SCORE, ((enemy_flag.score_assist) ? enemy_flag.score_assist : autocvar_g_ctf_score_capture_assist));
+ Give_Medal(enemy_flag.ctf_dropper, ASSIST);
+ }
}
flag.enemy = toucher;
{
Send_Notification(NOTIF_ONE, player, MSG_CENTER, APP_TEAM_NUM(flag.team, CENTER_CTF_RETURN));
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(flag.team, INFO_CTF_RETURN), player.netname);
+
+ FOREACH_CLIENT(IS_PLAYER(it), {
+ if(it.team == flag.team)
+ Send_Notification(NOTIF_ONE_ONLY, it, MSG_ANNCE, ANNCE_CTF_RETURN_TEAM);
+ else
+ Send_Notification(NOTIF_ONE_ONLY, it, MSG_ANNCE, ANNCE_CTF_RETURN_ENEMY);
+ });
+ Send_Notification(NOTIF_ALL_SPEC, NULL, MSG_ANNCE, APP_TEAM_NUM(flag.team, ANNCE_CTF_RETURN));
}
_sound(player, CH_TRIGGER, flag.snd_flag_returned, VOL_BASE, ATTEN_NONE);
ctf_EventLog("return", flag.team, player);
// messages and sounds
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_NUM(flag.team, INFO_CTF_PICKUP), player.netname);
+ Send_Notification(NOTIF_ALL_SPEC, NULL, MSG_ANNCE, APP_TEAM_NUM(flag.team, ANNCE_CTF_PICKUP));
+
if(ctf_stalemate)
Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_CTF_STALEMATE_CARRIER);
if(!flag.team)
Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_CTF_PICKUP_NEUTRAL);
else if(CTF_DIFFTEAM(player, flag))
+ {
Send_Notification(NOTIF_ONE, player, MSG_CENTER, APP_TEAM_NUM(flag.team, CENTER_CTF_PICKUP));
+ Send_Notification(NOTIF_ONE_ONLY, player, MSG_ANNCE, ANNCE_CTF_PICKUP_YOU);
+ }
else
Send_Notification(NOTIF_ONE, player, MSG_CENTER, ((SAME_TEAM(player, flag)) ? CENTER_CTF_PICKUP_RETURN : CENTER_CTF_PICKUP_RETURN_ENEMY), Team_ColorCode(flag.team));
Send_Notification(NOTIF_TEAM_EXCEPT, player, MSG_CHOICE, APP_NUM(flag.team, CHOICE_CTF_PICKUP_TEAM), Team_ColorCode(player.team), player.netname);
+ Send_Notification(NOTIF_TEAM_ONLY_EXCEPT, player, MSG_ANNCE, ANNCE_CTF_PICKUP_TEAM);
if(!flag.team)
FOREACH_CLIENT(IS_PLAYER(it) && it != player && DIFF_TEAM(it, player), { Send_Notification(NOTIF_ONE, it, MSG_CHOICE, CHOICE_CTF_PICKUP_ENEMY_NEUTRAL, Team_ColorCode(player.team), player.netname); });
if(flag.team)
FOREACH_CLIENT(IS_PLAYER(it) && it != player, {
if(CTF_SAMETEAM(flag, it))
- Send_Notification(NOTIF_ONE, it, MSG_CHOICE, ((SAME_TEAM(flag, player)) ? CHOICE_CTF_PICKUP_ENEMY_TEAM : CHOICE_CTF_PICKUP_ENEMY), Team_ColorCode(player.team), player.netname);
- else if(DIFF_TEAM(player, it))
- Send_Notification(NOTIF_ONE, it, MSG_CHOICE, APP_NUM(flag.team, CHOICE_CTF_PICKUP_ENEMY_OTHER), Team_ColorCode(player.team), player.netname);
+ {
+ if(SAME_TEAM(player, it)) {
+ Send_Notification(NOTIF_ONE, it, MSG_CHOICE, APP_TEAM_NUM(flag.team, CHOICE_CTF_PICKUP_TEAM), Team_ColorCode(player.team), player.netname);
+ Send_Notification(NOTIF_ONE_ONLY, it, MSG_ANNCE, ANNCE_CTF_PICKUP_TEAM);
+ } else {
+ Send_Notification(NOTIF_ONE, it, MSG_CHOICE, ((SAME_TEAM(flag, player)) ? CHOICE_CTF_PICKUP_ENEMY_TEAM : CHOICE_CTF_PICKUP_ENEMY), Team_ColorCode(player.team), player.netname);
+ Send_Notification(NOTIF_ONE_ONLY, it, MSG_ANNCE, ANNCE_CTF_PICKUP_ENEMY);
+ }
+ }
});
_sound(player, CH_TRIGGER, flag.snd_flag_taken, VOL_BASE, ATTEN_NONE);
entity frag_attacker = M_ARGV(1, entity);
entity frag_target = M_ARGV(2, entity);
- if((frag_attacker != frag_target) && (IS_PLAYER(frag_attacker)) && (frag_target.flagcarried))
- {
- GameRules_scoring_add_team(frag_attacker, SCORE, ((SAME_TEAM(frag_attacker, frag_target)) ? -autocvar_g_ctf_score_kill : autocvar_g_ctf_score_kill));
- GameRules_scoring_add(frag_attacker, CTF_FCKILLS, 1);
+ if((frag_attacker != frag_target) && (IS_PLAYER(frag_attacker)))
+ {
+ if(frag_target.flagcarried) {
+ // Killing an enemy flag carrier
+ GameRules_scoring_add_team(frag_attacker, SCORE, ((SAME_TEAM(frag_attacker, frag_target)) ? -autocvar_g_ctf_score_kill : autocvar_g_ctf_score_kill));
+ GameRules_scoring_add(frag_attacker, CTF_FCKILLS, 1);
+ } else if(frag_attacker.flagcarried) {
+ Give_Medal(frag_attacker, DEFENSE);
+ } else {
+ entity tmp_entity;
+ for(tmp_entity = ctf_worldflaglist; tmp_entity; tmp_entity = tmp_entity.ctf_worldflagnext)
+ if(tmp_entity.ctf_status == FLAG_BASE && CTF_SAMETEAM(tmp_entity, frag_attacker))
+ {
+ if(CTF_IS_NEAR(frag_target, tmp_entity, '1 1 1' * 1500))
+ {
+ Give_Medal(frag_attacker, DEFENSE);
+ }
+ break;
+ }
+ }
}
if(frag_target.flagcarried)
ctf_Handle_Throw(frag_target, NULL, DROP_NORMAL);
tmp_entity.ctf_dropper = NULL;
}
+
}
MUTATOR_HOOKFUNCTION(ctf, GiveFragsForKill)
#pragma once
#include "ctf.qh"
+
#include <common/items/item/pickup.qh>
#include <common/mutators/base.qh>
#include <common/gamemodes/sv_rules.qh>
// team checking
#define CTF_SAMETEAM(a,b) ((autocvar_g_ctf_reverse || (ctf_oneflag && autocvar_g_ctf_oneflag_reverse)) ? DIFF_TEAM(a,b) : SAME_TEAM(a,b))
#define CTF_DIFFTEAM(a,b) ((autocvar_g_ctf_reverse || (ctf_oneflag && autocvar_g_ctf_oneflag_reverse)) ? SAME_TEAM(a,b) : DIFF_TEAM(a,b))
+#define CTF_IS_NEAR(player, it, extra_size) \
+ boxesoverlap(player.absmin - extra_size, player.absmax + extra_size, it.absmin, it.absmax)
// announce remaining frags
return true;
}
+
+MUTATOR_HOOKFUNCTION(dm, Scores_AnnounceLeads)
+{
+ // enable leads announcer
+ return true;
+}
+
+MUTATOR_HOOKFUNCTION(dm, FragCenterMessage)
+{
+ // Use normal notifications in warmup
+ if(warmup_stage) return false;
+
+ entity attacker = M_ARGV(0, entity);
+ entity targ = M_ARGV(1, entity);
+ //float frag_deathtype = M_ARGV(2, float);
+ int kill_count_to_attacker = M_ARGV(3, int);
+ int kill_count_to_target = M_ARGV(4, int);
+
+ Send_Notification(
+ NOTIF_ONE,
+ attacker,
+ MSG_CENTER,
+ CENTER_DEATH_MURDER_DM,
+ targ.netname,
+ kill_count_to_attacker,
+ GameRules_scoring_add(attacker, SCORE, 0)
+ );
+ Send_Notification(
+ NOTIF_ONE,
+ targ,
+ MSG_CHOICE,
+ CHOICE_FRAGGED,
+ attacker.netname,
+ kill_count_to_target,
+ GetResource(attacker, RES_HEALTH),
+ GetResource(attacker, RES_ARMOR),
+ (IS_BOT_CLIENT(attacker) ? -1 : CS(attacker).ping)
+ );
+
+ return true;
+}
return true;
}
+MUTATOR_HOOKFUNCTION(duel, Scores_AnnounceLeads)
+{
+ // enable leads announcer
+ return true;
+}
+
MUTATOR_HOOKFUNCTION(duel, FilterItemDefinition)
{
entity definition = M_ARGV(0, entity);
return !autocvar_g_duel_with_powerups;
}
}
+
+MUTATOR_HOOKFUNCTION(duel, FragCenterMessage)
+{
+ // Use normal notifications in warmup
+ if(warmup_stage) return false;
+
+ entity attacker = M_ARGV(0, entity);
+ entity targ = M_ARGV(1, entity);
+ string tie_str;
+ int kill_count_to_attacker = M_ARGV(3, int);
+ int kill_count_to_target = M_ARGV(4, int);
+
+ WinningConditionHelper(NULL);
+
+ if(WinningConditionHelper_equality)
+ tie_str = "^3Tied";
+ else if(attacker == WinningConditionHelper_winner)
+ tie_str = "^2Leads";
+ else
+ tie_str = "^1Trails";
+
+ Send_Notification(
+ NOTIF_ONE,
+ attacker,
+ MSG_CENTER,
+ CENTER_DEATH_MURDER_DUEL,
+ targ.netname,
+ tie_str,
+ kill_count_to_attacker,
+ GameRules_scoring_add(attacker, SCORE, 0)
+ );
+ Send_Notification(
+ NOTIF_ONE,
+ targ,
+ MSG_CHOICE,
+ CHOICE_FRAGGED,
+ attacker.netname,
+ kill_count_to_target,
+ GetResource(attacker, RES_HEALTH),
+ GetResource(attacker, RES_ARMOR),
+ (IS_BOT_CLIENT(attacker) ? -1 : CS(attacker).ping)
+ );
+
+ return true;
+}
#include "cl_freezetag.qh"
-#include <common/gamemodes/gamemode/clanarena/cl_clanarena.qh>
+//#include <common/gamemodes/gamemode/clanarena/cl_clanarena.qh>
-void HUD_Mod_FreezeTag_Export(int fh)
+/*void HUD_Mod_FreezeTag_Export(int fh)
{
HUD_Write_Cvar("hud_panel_modicons_freezetag_layout");
}
mod_active = 1; // required in each mod function that always shows something
HUD_Mod_CA_Draw(myPos, mySize, autocvar_hud_panel_modicons_freezetag_layout);
-}
+}*/
+
#pragma once
-
-int autocvar_hud_panel_modicons_freezetag_layout;
-
-void HUD_Mod_FreezeTag_Export(int fh);
#include <common/gamemodes/gamemode/clanarena/cl_clanarena.qh>
#endif
-#ifdef CSQC
-void HUD_Mod_FreezeTag(vector myPos, vector mySize);
-void HUD_Mod_FreezeTag_Export(int fh);
-#endif
+//#ifdef CSQC
+//void HUD_Mod_FreezeTag(vector myPos, vector mySize);
+//void HUD_Mod_FreezeTag_Export(int fh);
+//#endif
CLASS(FreezeTag, Gametype)
INIT(FreezeTag)
{
returns(menu, _("Round limit:"), 5, 100, 5, "fraglimit_override", "g_freezetag_teams_override", _("The amount of rounds won needed before the match will end"));
}
#ifdef CSQC
- ATTRIB(FreezeTag, m_modicons, void(vector pos, vector mySize), HUD_Mod_FreezeTag);
- ATTRIB(FreezeTag, m_modicons_export, void(int fh), HUD_Mod_FreezeTag_Export);
+ //ATTRIB(FreezeTag, m_modicons, void(vector pos, vector mySize), HUD_Mod_FreezeTag);
+ //ATTRIB(FreezeTag, m_modicons_export, void(int fh), HUD_Mod_FreezeTag_Export);
+ ATTRIB(FreezeTag, m_modscores, int(int team), HUD_Scores_CA);
#endif
ATTRIB(FreezeTag, m_legacydefaults, string, "10 20 0");
ENDCLASS(FreezeTag)
void nades_Clear(entity);
void nades_GiveBonus(entity player, float score);
+entity freezetag_LastPlayer(float tm)
+{
+ entity last_pl = NULL;
+ FOREACH_CLIENT(IS_PLAYER(it) && it.team == tm, {
+ if (STAT(FROZEN, it) != FROZEN_NORMAL && GetResource(it, RES_HEALTH) >= 1)
+ {
+ if (!last_pl)
+ last_pl = it;
+ else
+ return NULL;
+ }
+ });
+ return last_pl;
+}
+
bool freezetag_CheckWinner()
{
if(round_handler_GetEndTime() > 0 && round_handler_GetEndTime() - time <= 0)
{
Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_ROUND_OVER);
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_ROUND_OVER);
+ Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_ROUND_OVER);
+
FOREACH_CLIENT(IS_PLAYER(it), {
it.freezetag_frozen_timeout = 0;
it.freezetag_revive_time = 0;
nades_Clear(it);
});
- game_stopped = true;
+ if(autocvar_g_freezetag_round_stop)
+ game_stopped = true;
round_handler_Init(5, autocvar_g_freezetag_warmup, autocvar_g_freezetag_round_timelimit);
return true;
}
if(winner_team > 0)
{
- Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, APP_TEAM_NUM(winner_team, CENTER_ROUND_TEAM_WIN));
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(winner_team, INFO_ROUND_TEAM_WIN));
+ entity last_pl = freezetag_LastPlayer(winner_team);
+ if(last_pl) {
+ Give_Medal(last_pl, DEFENSE);
+ }
+
+ Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, APP_TEAM_NUM(winner_team, CENTER_ROUND_TEAM_SCORES));
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(winner_team, INFO_ROUND_TEAM_SCORES));
TeamScore_AddToTeam(winner_team, ST_FT_ROUNDS, +1);
+ if(fragsleft > 1) AnnounceScores(winner_team);
}
else if(winner_team == -1)
{
Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_ROUND_TIED);
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_ROUND_TIED);
+ Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_ROUND_TIED);
}
FOREACH_CLIENT(IS_PLAYER(it), {
nades_Clear(it);
});
- game_stopped = true;
+ if(autocvar_g_freezetag_round_stop)
+ game_stopped = true;
round_handler_Init(5, autocvar_g_freezetag_warmup, autocvar_g_freezetag_round_timelimit);
return true;
}
if(round_handler_IsRoundStarted())
{
entity pl = freezetag_LastPlayerForTeam(this);
- if(pl)
+ if(pl) {
Send_Notification(NOTIF_ONE, pl, MSG_CENTER, CENTER_ALONE);
+ Send_Notification(NOTIF_ONE, pl, MSG_ANNCE, ANNCE_ALONE);
+ }
}
}
{
FOREACH_CLIENT(IS_PLAYER(it), {
CS(it).killcount = 0;
- it.freezetag_revive_time = 0;
- it.freezetag_frozen_timeout = -1;
- PutClientInServer(it);
+
+ if(autocvar_g_freezetag_round_respawn) {
+ it.freezetag_frozen_timeout = -1;
+ PutClientInServer(it);
+ } else {
+ ResetPlayerResources(it);
+ }
+
it.freezetag_frozen_timeout = 0;
});
freezetag_count_alive_players();
{
entity targ = M_ARGV(0, entity);
targ.freezetag_frozen_time = 0;
+
+ if(autocvar_g_freezetag_revive_respawn) {
+ targ.freezetag_frozen_timeout = -1;
+ PutClientInServer(targ);
+ }
+
targ.freezetag_frozen_timeout = 0;
}
Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_FREEZETAG_REVIVED, revivers_first.netname);
Send_Notification(NOTIF_ONE, revivers_first, MSG_CENTER, CENTER_FREEZETAG_REVIVE, player.netname);
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_FREEZETAG_REVIVED, player.netname, revivers_first.netname);
+ Give_Medal(revivers_first, ASSIST);
if(autocvar_sv_eventlog)
{
string revivers = "";
bool autocvar_g_freezetag_team_spawns;
string autocvar_g_freezetag_weaponarena = "most_available";
+bool autocvar_g_freezetag_round_respawn;
+bool autocvar_g_freezetag_round_stop;
+
const int ST_FT_ROUNDS = 1;
void freezetag_Initialize();
float autocvar_g_freezetag_revive_time_to_score = 1.5;
bool autocvar_g_freezetag_revive_nade;
float autocvar_g_freezetag_revive_nade_health;
+bool autocvar_g_freezetag_revive_respawn;
float autocvar_g_freezetag_revive_spawnshield = 1;
player.race_movetime_frac -= f;
player.race_movetime_count += f;
player.race_movetime = player.race_movetime_frac + player.race_movetime_count;
-
+
if(IS_PLAYER(player))
{
if (player.race_penalty)
// announce remaining frags
return true;
}
+
+MUTATOR_HOOKFUNCTION(tdm, Scores_AnnounceLeads)
+{
+ // enable leads announcer
+ return true;
+}
.Inventory inventory_store;
REGISTER_NET_LINKED(ENT_CLIENT_INVENTORY)
+REGISTER_NET_TEMP(TE_CSQC_INVENTORY)
const int Inventory_groups_minor = 8; // must be a multiple of 8 (one byte) to optimize bandwidth usage
const int Inventory_groups_major = 4; // must be >= ceil(REGISTRY_COUNT(Items) / Inventory_groups_minor)
#ifdef CSQC
#include <client/hud/panel/pickup.qh>
-Inventory g_inventory;
+//Inventory g_inventory;
+Inventory inventoryslots[255];
void Inventory_remove(entity this)
{
- if(g_inventory == this)
- g_inventory = NULL;
+ // TODO z411
+ //if(g_inventory == this)
+ // g_inventory = NULL;
}
-NET_HANDLE(ENT_CLIENT_INVENTORY, bool isnew)
+void Inventory_handle(entity inv, bool mine)
{
- make_pure(this);
- g_inventory = this;
- this.entremove = Inventory_remove;
- const int majorBits = Readbits(Inventory_groups_major);
+ const int majorBits = Readbits(Inventory_groups_major);
for (int i = 0; i < Inventory_groups_major; ++i) {
if (!(majorBits & BIT(i))) {
continue;
}
const GameItem it = REGISTRY_GET(Items, Inventory_groups_minor * i + j);
.int fld = inv_items[it.m_id];
- int prev = this.(fld);
- int next = this.(fld) = ReadByte();
+ int prev = inv.(fld);
+ int next = inv.(fld) = ReadByte();
Pickup_Update(it, next - prev);
LOG_DEBUGF("%s: %.0f -> %.0f", it.m_name, prev, next);
}
}
+}
+
+NET_HANDLE(ENT_CLIENT_INVENTORY, bool isnew)
+{
+ make_pure(this);
+ inventoryslots[current_player] = this;
+ //this.entremove = Inventory_remove; // z411 TODO : Must implement this
+
+ Inventory_handle(this, true);
+ return true;
+}
+
+NET_HANDLE(TE_CSQC_INVENTORY, bool isnew)
+{
+ float entnum = ReadByte() - 1;
+
+ if(!inventoryslots[entnum])
+ inventoryslots[entnum] = NEW(Inventory);
+
+ Inventory_handle(inventoryslots[entnum], entnum == current_player);
return true;
}
#ifdef SVQC
int minorBitsArr[Inventory_groups_major];
-void Inventory_Write(Inventory data, Inventory store)
+void Inventory_Write(int channel, Inventory data, Inventory store)
{
if (!data) {
- WriteShort(MSG_ENTITY, 0);
+ WriteShort(channel, 0);
return;
}
TC(Inventory, data);
}
});
- Writebits(MSG_ENTITY, majorBits, Inventory_groups_major);
+ Writebits(channel, majorBits, Inventory_groups_major);
for (int i = 0; i < Inventory_groups_major; ++i)
{
if (!(majorBits & BIT(i)))
continue;
const int minorBits = minorBitsArr[i];
- Writebits(MSG_ENTITY, minorBits, Inventory_groups_minor);
+ Writebits(channel, minorBits, Inventory_groups_minor);
for (int j = 0; j < Inventory_groups_minor; ++j)
{
if (!(minorBits & BIT(j)))
continue;
const entity it = REGISTRY_GET(Items, Inventory_groups_minor * i + j);
- WriteByte(MSG_ENTITY, data.inv_items[it.m_id]);
+ WriteByte(channel, data.inv_items[it.m_id]);
}
}
}
#undef G_MINOR
#ifdef SVQC
+bool Inventory_Broadcast(Inventory this)
+{
+ TC(Inventory, this);
+ WriteHeader(MSG_BROADCAST, TE_CSQC_INVENTORY);
+ TC(PlayerState, this.owner);
+
+ // z411 send entity number
+ WriteByte(MSG_BROADCAST, etof(this.owner.m_client));
+
+ Inventory_Write(MSG_BROADCAST, this, this.owner.m_client.inventory_store);
+ return true;
+}
+
bool Inventory_Send(Inventory this, Client to, int sf)
{
TC(Inventory, this);
WriteHeader(MSG_ENTITY, ENT_CLIENT_INVENTORY);
TC(PlayerState, this.owner);
- Inventory_Write(this, to.inventory_store);
+
+ Inventory_Write(MSG_ENTITY, this, to.inventory_store);
return true;
}
void Inventory_new(PlayerState this)
{
Inventory inv = NEW(Inventory);
- setcefc(inv, Inventory_customize);
+ inv.owner = this;
this.inventory = inv;
- inv.owner = this;
- Net_LinkEntity(inv, false, 0, Inventory_Send);
+
+ if(!g_duel) {
+ setcefc(inv, Inventory_customize);
+ Net_LinkEntity(inv, false, 0, Inventory_Send);
+ }
}
void Inventory_delete(entity e) { delete(e.inventory); }
-void Inventory_update(entity e) { e.inventory.SendFlags = 0xFFFFFF; }
+void Inventory_update(entity e)
+{
+ if(g_duel)
+ Inventory_Broadcast(e.inventory);
+ else
+ e.inventory.SendFlags = 0xFFFFFF;
+}
void Inventory_pickupitem(Pickup this, entity player)
{
/** game type priority in random selections */
ATTRIB(Gametype, m_priority, int, 0);
#ifdef CSQC
- ATTRIB(Gametype, m_modicons, void(vector pos, vector mySize));
- ATTRIB(Gametype, m_modicons_reset, void());
- ATTRIB(Gametype, m_modicons_export, void(int fh));
+ //ATTRIB(Gametype, m_modicons, void(vector pos, vector mySize));
+ //ATTRIB(Gametype, m_modicons_reset, void());
+ //ATTRIB(Gametype, m_modicons_export, void(int fh));
+ ATTRIB(Gametype, m_modscores, int(int team));
#endif
/** DO NOT USE, this is compatibility for legacy maps! */
void monsters_setstatus(entity this)
{
- STAT(MONSTERS_TOTAL, this) = monsters_total;
- STAT(MONSTERS_KILLED, this) = monsters_killed;
+ //STAT(MONSTERS_TOTAL, this) = monsters_total;
+ //STAT(MONSTERS_KILLED, this) = monsters_killed;
}
bool autocvar_g_monsters_drop = true;
// generated file; do not modify
+#include <common/mutators/mutator/attackertext/_mod.inc>
#include <common/mutators/mutator/bloodloss/_mod.inc>
#include <common/mutators/mutator/breakablehook/_mod.inc>
#include <common/mutators/mutator/buffs/_mod.inc>
#include <common/mutators/mutator/breakablehook/_mod.qh>
#include <common/mutators/mutator/buffs/_mod.qh>
#include <common/mutators/mutator/bugrigs/_mod.qh>
+#include <common/mutators/mutator/attackertext/_mod.qh>
#include <common/mutators/mutator/campcheck/_mod.qh>
#include <common/mutators/mutator/cloaked/_mod.qh>
#include <common/mutators/mutator/damagetext/_mod.qh>
--- /dev/null
+// generated file; do not modify
+#include <common/mutators/mutator/attackertext/attackertext.qc>
+#ifdef CSQC
+ #include <common/mutators/mutator/attackertext/cl_attackertext.qc>
+#endif
+#ifdef SVQC
+ #include <common/mutators/mutator/attackertext/sv_attackertext.qc>
+#endif
--- /dev/null
+// generated file; do not modify
+#include <common/mutators/mutator/damagetext/damagetext.qh>
+#ifdef CSQC
+ #include <common/mutators/mutator/damagetext/cl_damagetext.qh>
+#endif
+#ifdef SVQC
+ #include <common/mutators/mutator/damagetext/sv_damagetext.qh>
+#endif
+#ifdef MENUQC
+ #include <common/mutators/mutator/damagetext/ui_damagetext.qh>
+#endif
--- /dev/null
+#include "attackertext.qh"
+
+#ifdef GAMEQC
+REGISTER_NET_TEMP(attackertext)
+#endif
--- /dev/null
+#pragma once
+
+const int ATFLAG_SAMETEAM = BIT(0);
+
--- /dev/null
+#include "cl_attackertext.qh"
+
+AUTOCVAR_SAVE(cl_attackertext, bool, true, "Draw damage dealt where you hit the enemy");
+AUTOCVAR_SAVE(cl_attackertext_friendlyfire, bool, false, "Show for friendlyfire");
+AUTOCVAR_SAVE(cl_attackertext_time, float, 3, "Time to show");
+AUTOCVAR_SAVE(cl_attackertext_fadetime, float, 2, "Time to fade");
+AUTOCVAR_SAVE(cl_attackertext_decolorize, int, 1, "1 = decolorize names when teamplay, 2 = decolorize always");
+
+REGISTER_MUTATOR(attackertext, true);
+
+MUTATOR_HOOKFUNCTION(attackertext, DrawInfoMessages)
+{
+ if (autocvar_cl_attackertext == 0) return false;
+
+ float fade_start = max(0, autocvar_cl_attackertext_time);
+ float fade_time = max(0, autocvar_cl_attackertext_fadetime);
+
+ if (last_attack_time && last_attack_time > time - fade_start - fade_time) {
+ vector pos = M_ARGV(0, vector);
+ vector mySize = M_ARGV(1, vector);
+ vector fontsize = '0.3 0.3 0' * mySize.y;
+ int img_curr_group = M_ARGV(2, int);
+
+ float alpha_ = 0;
+
+ if (last_attack_time + fade_start > time)
+ alpha_ = panel_fg_alpha;
+ else if (fade_time != 0)
+ alpha_ = panel_fg_alpha - bound(0, (time - last_attack_time - fade_start) * (1 / fade_time), 1);
+ else
+ return true;
+
+ pos = InfoMessages_drawstring(last_attack_name, pos, mySize, alpha_, fontsize);
+ img_curr_group = -1;
+
+ return true;
+ }
+
+ return false;
+}
+
+
+NET_HANDLE(attackertext, bool isNew)
+{
+ int server_entity_index = ReadByte();
+ int flags = ReadByte();
+ bool friendlyfire = flags & ATFLAG_SAMETEAM;
+
+ return = true;
+
+ if (autocvar_cl_attackertext == 0) return;
+ if (friendlyfire && autocvar_cl_attackertext_friendlyfire == 0) return;
+
+ string s = entcs_GetName(server_entity_index - 1);
+ if ((autocvar_cl_attackertext_decolorize == 1 && teamplay) || autocvar_cl_attackertext_decolorize == 2)
+ s = playername(s, entcs_GetTeam(server_entity_index - 1), true);
+
+ last_attack_time = time;
+ strfree(last_attack_name);
+ strcpy(last_attack_name, s);
+}
--- /dev/null
+#pragma once
+
+float last_attack_time;
+string last_attack_name;
\ No newline at end of file
--- /dev/null
+#include "sv_attackertext.qh"
+
+AUTOCVAR(sv_attackertext, int, 1, "0: disabled, 1: visible");
+
+REGISTER_MUTATOR(attackertext, true);
+
+#define SV_ATTACKERTEXT_DISABLED() (autocvar_sv_attackertext <= 0)
+#define SV_ATTACKERTEXT_ENABLED() (autocvar_sv_attackertext >= 1)
+
+void attackertext_Send(entity to, entity attacker, int sf)
+{
+ if(IS_REAL_CLIENT(to)) {
+ msg_entity = to;
+ WriteHeader(MSG_ONE, attackertext);
+ WriteByte(MSG_ONE, etof(attacker));
+ WriteByte(MSG_ONE, sf);
+ }
+}
+
+MUTATOR_HOOKFUNCTION(attackertext, PlayerDamaged) {
+ if (SV_ATTACKERTEXT_DISABLED()) return;
+
+ entity attacker = M_ARGV(0, entity);
+ entity hit = M_ARGV(1, entity);
+
+ if (hit == attacker) return;
+ if (!IS_PLAYER(attacker)) return;
+
+ int sf = 0;
+ if (SAME_TEAM(hit, attacker)) sf |= ATFLAG_SAMETEAM;
+
+ attackertext_Send(hit, attacker, sf);
+ FOREACH_CLIENT(IS_SPEC(it) && it.(enemy) == hit, { attackertext_Send(it, attacker, sf); });
+}
--- /dev/null
+#pragma once
{
entity player = M_ARGV(0, entity);
- if(game_stopped)
+ if(game_stopped || game_timeout)
return; // during intermission, the player's health changes to strange values for the engine, let's not cause damage during this phase!
if(IS_PLAYER(player))
void buff_Respawn(entity this)
{
- if(game_stopped) return;
+ if(game_stopped || game_timeout) return;
vector oldbufforigin = this.origin;
this.velocity = '0 0 200';
void buff_Touch(entity this, entity toucher)
{
- if(game_stopped) return;
+ if(game_stopped || game_timeout) return;
if(ITEM_TOUCH_NEEDKILL())
{
this.oldbuffs = this.buffdef;
}
- if(!game_stopped)
+ if(!game_stopped && !game_timeout)
if((round_handler_IsActive() && round_handler_IsRoundStarted()) || time >= game_starttime)
if(!this.buff_activetime_updated)
{
}
if(this.buff_activetime)
- if(!game_stopped)
+ if(!game_stopped && !game_timeout)
if((round_handler_IsActive() && round_handler_IsRoundStarted()) || time >= game_starttime)
{
this.buff_activetime = max(0, this.buff_activetime - frametime);
MUTATOR_HOOKFUNCTION(buffs, ForbidThrowCurrentWeapon)
{
- if(MUTATOR_RETURNVALUE || game_stopped) return;
+ if(MUTATOR_RETURNVALUE || game_stopped || game_timeout) return;
entity player = M_ARGV(0, entity);
if(StatusEffects_active(BUFF_SWAPPER, player))
{
entity player = M_ARGV(0, entity);
- if(game_stopped || IS_DEAD(player) || !IS_PLAYER(player)) return;
+ if(game_stopped || game_timeout || IS_DEAD(player) || frametime || !IS_PLAYER(player)) return;
// NOTE: this is kept here to ensure crouches are picked up each player movement frame
if(StatusEffects_active(BUFF_FLIGHT, player))
bool checked = false;
if(autocvar_g_campcheck_interval)
- if(!game_stopped && !warmup_stage && time >= game_starttime)
+ if(!game_stopped && !game_timeout && !warmup_stage && time >= game_starttime)
if(IS_PLAYER(player) && !IS_DEAD(player) && !STAT(FROZEN, player))
if(autocvar_g_campcheck_typecheck || !PHYS_INPUT_BUTTON_CHAT(player))
if(IS_REAL_CLIENT(player)) // only apply to real clients (bots may "camp" due to missing waypoints in the map, but that's no reason to constantly kill them, clones can't move)
if(!IS_PLAYER(this))
return; // not a player
- if(IS_DEAD(this) || game_stopped)
+ if(IS_DEAD(this) || game_stopped || game_timeout)
instagib_stop_countdown(this);
else if (GetResource(this, RES_CELLS) > 0 || (this.items & IT_UNLIMITED_AMMO) || (this.flags & FL_GODMODE))
instagib_stop_countdown(this);
return = true;
ItemsTime_time[i] = f;
}
+
+NET_HANDLE(TE_CSQC_TOTALSHARDS, bool isNew)
+{
+ // for RJZ
+ total_shards = ReadInt24_t();
+
+ return = true;
+}
+
#endif
#ifdef CSQC
HUD_Write_Cvar("hud_panel_itemstime_dynamicsize");
}
+// for RJZ
+void DrawItemsTimeItemFixed(vector myPos, vector mySize, float ar, string item_icon, float t, vector color)
+{
+ vector picpos, numpos;
+ if (autocvar_hud_panel_itemstime_iconalign)
+ {
+ numpos = myPos;
+ picpos = myPos + eX * (ar - 1) * mySize_y;
+ }
+ else
+ {
+ numpos = myPos + eX * mySize_y;
+ picpos = myPos;
+ }
+
+ drawstring_aspect(numpos, (t < 0 ? "-" : ftos(t)), vec2(((ar - 1)/ar) * mySize.x, mySize.y), color, panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawpic_aspect(picpos, item_icon, '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+}
+
void DrawItemsTimeItem(vector myPos, vector mySize, float ar, string item_icon, float item_time, bool item_available, float item_availableTime)
{
float t = 0;
return -1; // don't show others
}
else
- return ItemsTime_time[item];
+ {
+ float game_starttime = STAT(GAMESTARTTIME);
+ float timeout_last = STAT(TIMEOUT_LAST);
+
+ if(ItemsTime_time[item] > 0 && game_starttime < time)
+ if(timeout_last)
+ return ItemsTime_time[item] + game_starttime - timeout_last + time;
+ else
+ return ItemsTime_time[item] + game_starttime;
+ else
+ return ItemsTime_time[item];
+ }
}
void HUD_ItemsTime()
});
count += (Item_ItemsTime_GetTime(REGISTRY_MAX(Items)) != -1);
}
+ // for RJZ
+ if (total_shards != -1)
+ count++;
+
if (count == 0)
return;
itemstime_size.y = newSize;
}
}
+
+ if (total_shards != -1)
+ panel_size.y += itemstime_size.y * 0.5;
HUD_Scale_Enable();
HUD_Panel_DrawBg();
FOREACH(Items, Item_ItemsTime_Allow(it) && Item_ItemsTime_GetTime(it.m_id) != -1, {
id = it.m_id;
icon = it.m_icon;
+
LABEL(iteration)
float item_time = Item_ItemsTime_GetTime(id);
if(id == REGISTRY_MAX(Items)) // can happen only in the last fake iteration
break;
});
+
+ // for RJZ
+ if(total_shards != -1) {
+ DrawItemsTimeItemFixed(pos + vec2(column * (itemstime_size.x + offset.x), row * (itemstime_size.y + offset.y) + itemstime_size.y * 0.5), itemstime_size, ar, "gfx/shards.tga", total_shards, '0.16 0.7 0.83');
+ ++row;
+ if (row >= rows)
+ {
+ row = 0;
+ column = column + 1;
+ }
+ }
+
// add another fake iteration for superweapons time
if(id < REGISTRY_MAX(Items) && Item_ItemsTime_GetTime(REGISTRY_MAX(Items)) != -1)
{
#pragma once
+#ifdef CSQC
+int total_shards = -1;
+#endif
+
#ifdef SVQC
int autocvar_sv_itemstime;
#endif
impressive_hits = 0;
FireRailgunBullet(actor, weaponentity, w_shotorg, w_shotorg + w_shotdir * max_shot_distance, mydmg, true, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, thiswep.m_id);
- if(yoda && flying)
- Send_Notification(NOTIF_ONE, actor, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA);
+ if(yoda && flying) {
+ Give_Medal(actor, YODA);
+ }
+
if(impressive_hits && actor.oknex_lasthit)
{
- Send_Notification(NOTIF_ONE, actor, MSG_ANNCE, ANNCE_ACHIEVEMENT_IMPRESSIVE);
+ Give_Medal(actor, IMPRESSIVE);
impressive_hits = 0; // only every second time
}
METHOD(OverkillNex, wr_setup, void(entity thiswep, entity actor, .entity weaponentity))
{
- actor.oknex_lasthit = 0;
+ //actor.oknex_lasthit = 0;
}
METHOD(OverkillNex, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
REGISTER_NET_TEMP(TE_CSQC_VEHICLESETUP)
REGISTER_NET_TEMP(TE_CSQC_WEAPONPICKUP)
+REGISTER_NET_TEMP(TE_CSQC_TEAMNAMES)
+REGISTER_NET_TEMP(TE_CSQC_CHATSOUND)
+REGISTER_NET_TEMP(TE_CSQC_TOTALSHARDS) // for RJZ
+
const int RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder
const int RACE_NET_CHECKPOINT_CLEAR = 1;
const int RACE_NET_CHECKPOINT_NEXT_QUALIFYING = 2; // byte nextcheckpoint, short recordtime, string recordholder
#define N___NEVER 0
#define N_GNTLOFF 1
#define N__ALWAYS 2
+#define ANNCE_DEFTIME 2
// default time for announcer queue (time to wait before the next announcer is played)
// -1 = bypass queue and play the announcer immediately
#define ANNCE_LENGTH 0
#define ANNCE_DEFTIME 2
-#define MULTITEAM_ANNCE(prefix, defaultvalue, sound, channel, volume, position) \
+#define MULTITEAM_ANNCE(prefix, defaultvalue, sound, channel, volume, position, queuetime) \
NOTIF_ADD_AUTOCVAR(ANNCE_##prefix, defaultvalue) \
- MSG_ANNCE_NOTIF_TEAM(NUM_TEAM_1, prefix##_RED, prefix, defaultvalue, sprintf(sound, strtolower(STATIC_NAME_TEAM_1)), channel, volume, position) \
- MSG_ANNCE_NOTIF_TEAM(NUM_TEAM_2, prefix##_BLUE, prefix, defaultvalue, sprintf(sound, strtolower(STATIC_NAME_TEAM_2)), channel, volume, position) \
- MSG_ANNCE_NOTIF_TEAM(NUM_TEAM_3, prefix##_YELLOW, prefix, defaultvalue, sprintf(sound, strtolower(STATIC_NAME_TEAM_3)), channel, volume, position) \
- MSG_ANNCE_NOTIF_TEAM(NUM_TEAM_4, prefix##_PINK, prefix, defaultvalue, sprintf(sound, strtolower(STATIC_NAME_TEAM_4)), channel, volume, position)
+ MSG_ANNCE_NOTIF_TEAM(NUM_TEAM_1, prefix##_RED, prefix, defaultvalue, sprintf(sound, strtolower(STATIC_NAME_TEAM_1)), channel, volume, position, queuetime) \
+ MSG_ANNCE_NOTIF_TEAM(NUM_TEAM_2, prefix##_BLUE, prefix, defaultvalue, sprintf(sound, strtolower(STATIC_NAME_TEAM_2)), channel, volume, position, queuetime) \
+ MSG_ANNCE_NOTIF_TEAM(NUM_TEAM_3, prefix##_YELLOW, prefix, defaultvalue, sprintf(sound, strtolower(STATIC_NAME_TEAM_3)), channel, volume, position, queuetime) \
+ MSG_ANNCE_NOTIF_TEAM(NUM_TEAM_4, prefix##_PINK, prefix, defaultvalue, sprintf(sound, strtolower(STATIC_NAME_TEAM_4)), channel, volume, position, queuetime)
// MSG_ANNCE_NOTIFICATIONS
MSG_ANNCE_NOTIF(ACHIEVEMENT_AIRSHOT, N_GNTLOFF, "airshot", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
MSG_ANNCE_NOTIF(ACHIEVEMENT_AMAZING, N_GNTLOFF, "amazing", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
- MSG_ANNCE_NOTIF(ACHIEVEMENT_AWESOME, N_GNTLOFF, "awesome", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MSG_ANNCE_NOTIF(ACHIEVEMENT_ASSIST, N_GNTLOFF, "assist", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MSG_ANNCE_NOTIF(ACHIEVEMENT_AWESOME, N_GNTLOFF, "awesome", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MSG_ANNCE_NOTIF(ACHIEVEMENT_DAMAGE, N_GNTLOFF, "damage", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MSG_ANNCE_NOTIF(ACHIEVEMENT_DEFENSE, N_GNTLOFF, "defense", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MSG_ANNCE_NOTIF(ACHIEVEMENT_EXCELLENT, N_GNTLOFF, "excellent", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
MSG_ANNCE_NOTIF(ACHIEVEMENT_BOTLIKE, N_GNTLOFF, "botlike", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
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(ACHIEVEMENT_TELEFRAG, N_GNTLOFF, "telefrag", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
- MSG_ANNCE_NOTIF(BEGIN, N__ALWAYS, "begin", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
+ MSG_ANNCE_NOTIF(BEGIN, N__ALWAYS, "begin", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
MSG_ANNCE_NOTIF(HEADSHOT, N__ALWAYS, "headshot", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MSG_ANNCE_NOTIF(HUMILIATION, N__ALWAYS, "humiliation", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
MSG_ANNCE_NOTIF(KILLSTREAK_03, N_GNTLOFF, "03kills", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
MSG_ANNCE_NOTIF(KILLSTREAK_05, N_GNTLOFF, "05kills", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
MSG_ANNCE_NOTIF(KILLSTREAK_10, N_GNTLOFF, "10kills", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
MSG_ANNCE_NOTIF(KILLSTREAK_15, N_GNTLOFF, "15kills", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
- MSG_ANNCE_NOTIF(KILLSTREAK_20, N_GNTLOFF, "20kills", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
- MSG_ANNCE_NOTIF(KILLSTREAK_25, N_GNTLOFF, "25kills", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
- MSG_ANNCE_NOTIF(KILLSTREAK_30, N_GNTLOFF, "30kills", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
MSG_ANNCE_NOTIF(INSTAGIB_LASTSECOND, N_GNTLOFF, "lastsecond", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
MSG_ANNCE_NOTIF(INSTAGIB_NARROWLY, N_GNTLOFF, "narrowly", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
MSG_ANNCE_NOTIF(INSTAGIB_TERMINATED, N_GNTLOFF, "terminated", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
- MSG_ANNCE_NOTIF(MULTIFRAG, N___NEVER, "multifrag", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
-
- MSG_ANNCE_NOTIF(NUM_1, N__ALWAYS, "1", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_2, N__ALWAYS, "2", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_3, N__ALWAYS, "3", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_4, N__ALWAYS, "4", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_5, N__ALWAYS, "5", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_6, N__ALWAYS, "6", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_7, N__ALWAYS, "7", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_8, N__ALWAYS, "8", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_9, N__ALWAYS, "9", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_10, N__ALWAYS, "10", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
-
- MSG_ANNCE_NOTIF(NUM_GAMESTART_1, N__ALWAYS, "1", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_GAMESTART_2, N__ALWAYS, "2", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_GAMESTART_3, N__ALWAYS, "3", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_GAMESTART_4, N__ALWAYS, "4", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_GAMESTART_5, N__ALWAYS, "5", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_GAMESTART_6, N___NEVER, "6", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_GAMESTART_7, N___NEVER, "7", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_GAMESTART_8, N___NEVER, "8", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_GAMESTART_9, N___NEVER, "9", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_GAMESTART_10, N___NEVER, "10", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
-
- MSG_ANNCE_NOTIF(NUM_KILL_1, N___NEVER, "1", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_KILL_2, N___NEVER, "2", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_KILL_3, N___NEVER, "3", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_KILL_4, N___NEVER, "4", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_KILL_5, N___NEVER, "5", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_KILL_6, N___NEVER, "6", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_KILL_7, N___NEVER, "7", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_KILL_8, N___NEVER, "8", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_KILL_9, N___NEVER, "9", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_KILL_10, N___NEVER, "10", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
-
- MSG_ANNCE_NOTIF(NUM_RESPAWN_1, N___NEVER, "1", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_RESPAWN_2, N___NEVER, "2", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_RESPAWN_3, N___NEVER, "3", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_RESPAWN_4, N___NEVER, "4", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_RESPAWN_5, N___NEVER, "5", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_RESPAWN_6, N___NEVER, "6", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_RESPAWN_7, N___NEVER, "7", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_RESPAWN_8, N___NEVER, "8", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_RESPAWN_9, N___NEVER, "9", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_RESPAWN_10, N___NEVER, "10", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
-
- MSG_ANNCE_NOTIF(NUM_ROUNDSTART_1, N__ALWAYS, "1", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_ROUNDSTART_2, N__ALWAYS, "2", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_ROUNDSTART_3, N__ALWAYS, "3", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_ROUNDSTART_4, N___NEVER, "4", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_ROUNDSTART_5, N___NEVER, "5", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_ROUNDSTART_6, N___NEVER, "6", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_ROUNDSTART_7, N___NEVER, "7", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_ROUNDSTART_8, N___NEVER, "8", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_ROUNDSTART_9, N___NEVER, "9", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
- MSG_ANNCE_NOTIF(NUM_ROUNDSTART_10, N___NEVER, "10", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
-
- MSG_ANNCE_NOTIF(PREPARE, N__ALWAYS, "prepareforbattle", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MSG_ANNCE_NOTIF(MULTIFRAG, N_GNTLOFF, "multifrag", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MSG_ANNCE_NOTIF(FIRSTBLOOD, N_GNTLOFF, "firstblood", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+
+ MSG_ANNCE_NOTIF(NUM_1, N__ALWAYS, "1", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_2, N__ALWAYS, "2", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_3, N__ALWAYS, "3", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_4, N__ALWAYS, "4", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_5, N__ALWAYS, "5", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_6, N__ALWAYS, "6", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_7, N__ALWAYS, "7", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_8, N__ALWAYS, "8", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_9, N__ALWAYS, "9", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_10, N__ALWAYS, "10", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+
+ MSG_ANNCE_NOTIF(NUM_GAMESTART_1, N__ALWAYS, "1", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_GAMESTART_2, N__ALWAYS, "2", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_GAMESTART_3, N__ALWAYS, "3", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_GAMESTART_4, N__ALWAYS, "4", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_GAMESTART_5, N__ALWAYS, "5", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_GAMESTART_6, N___NEVER, "6", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_GAMESTART_7, N___NEVER, "7", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_GAMESTART_8, N___NEVER, "8", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_GAMESTART_9, N___NEVER, "9", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_GAMESTART_10, N___NEVER, "10", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+
+ MSG_ANNCE_NOTIF(NUM_IDLE_1, N___NEVER, "1", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_IDLE_2, N___NEVER, "2", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_IDLE_3, N___NEVER, "3", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_IDLE_4, N___NEVER, "4", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_IDLE_5, N___NEVER, "5", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_IDLE_6, N___NEVER, "6", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_IDLE_7, N___NEVER, "7", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_IDLE_8, N___NEVER, "8", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_IDLE_9, N___NEVER, "9", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_IDLE_10, N___NEVER, "10", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+
+ MSG_ANNCE_NOTIF(NUM_KILL_1, N___NEVER, "1", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_KILL_2, N___NEVER, "2", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_KILL_3, N___NEVER, "3", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_KILL_4, N___NEVER, "4", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_KILL_5, N___NEVER, "5", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_KILL_6, N___NEVER, "6", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_KILL_7, N___NEVER, "7", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_KILL_8, N___NEVER, "8", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_KILL_9, N___NEVER, "9", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_KILL_10, N___NEVER, "10", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+
+ MSG_ANNCE_NOTIF(NUM_RESPAWN_1, N___NEVER, "1", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_RESPAWN_2, N___NEVER, "2", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_RESPAWN_3, N___NEVER, "3", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_RESPAWN_4, N___NEVER, "4", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_RESPAWN_5, N___NEVER, "5", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_RESPAWN_6, N___NEVER, "6", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_RESPAWN_7, N___NEVER, "7", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_RESPAWN_8, N___NEVER, "8", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_RESPAWN_9, N___NEVER, "9", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_RESPAWN_10, N___NEVER, "10", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+
+ MSG_ANNCE_NOTIF(NUM_ROUNDSTART_1, N__ALWAYS, "1", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_ROUNDSTART_2, N__ALWAYS, "2", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_ROUNDSTART_3, N__ALWAYS, "3", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_ROUNDSTART_4, N___NEVER, "4", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_ROUNDSTART_5, N___NEVER, "5", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_ROUNDSTART_6, N___NEVER, "6", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_ROUNDSTART_7, N___NEVER, "7", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_ROUNDSTART_8, N___NEVER, "8", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_ROUNDSTART_9, N___NEVER, "9", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(NUM_ROUNDSTART_10, N___NEVER, "10", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+
+ MSG_ANNCE_NOTIF(PREPARE, N__ALWAYS, "prepareforbattle", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(PREPARE_TEAM, N__ALWAYS, "prepareyourteam", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
MSG_ANNCE_NOTIF(REMAINING_FRAG_1, N_GNTLOFF, "1fragleft", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
MSG_ANNCE_NOTIF(REMAINING_FRAG_2, N_GNTLOFF, "2fragsleft", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
MSG_ANNCE_NOTIF(REMAINING_MIN_1, N__ALWAYS, "1minuteremains", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
MSG_ANNCE_NOTIF(REMAINING_MIN_5, N__ALWAYS, "5minutesremain", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
- MSG_ANNCE_NOTIF(TIMEOUT, N__ALWAYS, "timeoutcalled", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_INSTANT)
+ MSG_ANNCE_NOTIF(TIMEOUT, N__ALWAYS, "timeoutcalled", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(OVERTIME, N__ALWAYS, "overtime", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MSG_ANNCE_NOTIF(SUDDENDEATH, N__ALWAYS, "suddendeath", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MSG_ANNCE_NOTIF(SUICIDE, N_GNTLOFF, "suicide", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
+ MSG_ANNCE_NOTIF(ACCIDENT, N_GNTLOFF, "accident", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, -1)
MSG_ANNCE_NOTIF(VOTE_ACCEPT, N__ALWAYS, "voteaccept", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
MSG_ANNCE_NOTIF(VOTE_CALL, N__ALWAYS, "votecall", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
MSG_ANNCE_NOTIF(VOTE_FAIL, N__ALWAYS, "votefail", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+
+ MSG_ANNCE_NOTIF(LEAD_GAINED, N__ALWAYS, "leadgained", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MSG_ANNCE_NOTIF(LEAD_LOST, N__ALWAYS, "leadlost", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MSG_ANNCE_NOTIF(LEAD_TIED, N__ALWAYS, "leadtied", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+
+ MULTITEAM_ANNCE(ROUND_TEAM_WIN, N__ALWAYS, "round_win_%s", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+
+ MSG_ANNCE_NOTIF(TEAM_SCORES_TEAM, N__ALWAYS, "scores_team", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MSG_ANNCE_NOTIF(TEAM_SCORES_ENEMY, N__ALWAYS, "scores_enemy", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MULTITEAM_ANNCE(TEAM_SCORES, N__ALWAYS, "scores_%s", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+
+ MSG_ANNCE_NOTIF(TEAM_LEADS_TEAM, N__ALWAYS, "leads_team", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MSG_ANNCE_NOTIF(TEAM_LEADS_ENEMY, N__ALWAYS, "leads_enemy", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MULTITEAM_ANNCE(TEAM_LEADS, N__ALWAYS, "leads_%s", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+
+ MULTITEAM_ANNCE(TEAM_WINS, N__ALWAYS, "wins_%s", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+
+ MSG_ANNCE_NOTIF(TEAM_LEADS_TIED, N__ALWAYS, "teamstied", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MSG_ANNCE_NOTIF(ROUND_OVER, N__ALWAYS, "round_over", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MSG_ANNCE_NOTIF(ROUND_TIED, N__ALWAYS, "round_tied", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MSG_ANNCE_NOTIF(ALONE, N__ALWAYS, "alone", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+
+ MSG_ANNCE_NOTIF(CTF_PICKUP_YOU, N__ALWAYS, "ctf_pickup_you", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MSG_ANNCE_NOTIF(CTF_PICKUP_TEAM, N__ALWAYS, "ctf_pickup_team", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MSG_ANNCE_NOTIF(CTF_PICKUP_ENEMY, N__ALWAYS, "ctf_pickup_enemy", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MULTITEAM_ANNCE(CTF_PICKUP, N__ALWAYS, "ctf_pickup_%s", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+
+ MSG_ANNCE_NOTIF(CTF_RETURN_TEAM, N__ALWAYS, "ctf_return_team", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MSG_ANNCE_NOTIF(CTF_RETURN_ENEMY, N__ALWAYS, "ctf_return_enemy", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+ MULTITEAM_ANNCE(CTF_RETURN, N__ALWAYS, "ctf_return_%s", CH_INFO, VOL_BASEVOICE, ATTEN_NONE, ANNCE_DEFTIME)
+
+// MSG_MEDAL_NOTIFICATIONS
+
+#define MSG_MEDAL_TIME 2
+#define MSG_MEDAL_FADE_TIME 0.5
+
+ MSG_MEDAL_NOTIF(AIRSHOT, N__ALWAYS, "airshot", ANNCE_ACHIEVEMENT_AIRSHOT)
+ MSG_MEDAL_NOTIF(ASSIST, N__ALWAYS, "assist", ANNCE_ACHIEVEMENT_ASSIST)
+ MSG_MEDAL_NOTIF(DAMAGE, N__ALWAYS, "damage", ANNCE_ACHIEVEMENT_DAMAGE)
+ MSG_MEDAL_NOTIF(DEFENSE, N__ALWAYS, "defense", ANNCE_ACHIEVEMENT_DEFENSE)
+ MSG_MEDAL_NOTIF(ELECTROBITCH, N__ALWAYS, "electrobitch", ANNCE_ACHIEVEMENT_ELECTROBITCH)
+ MSG_MEDAL_NOTIF(EXCELLENT, N__ALWAYS, "excellent", ANNCE_ACHIEVEMENT_EXCELLENT)
+ MSG_MEDAL_NOTIF(FIRSTBLOOD, N__ALWAYS, "firstblood", ANNCE_FIRSTBLOOD)
+ MSG_MEDAL_NOTIF(HEADSHOT, N__ALWAYS, "headshot", ANNCE_HEADSHOT)
+ MSG_MEDAL_NOTIF(HUMILIATION, N__ALWAYS, "humiliation", ANNCE_HUMILIATION)
+ MSG_MEDAL_NOTIF(IMPRESSIVE, N__ALWAYS, "impressive", ANNCE_ACHIEVEMENT_IMPRESSIVE)
+ MSG_MEDAL_NOTIF(YODA, N__ALWAYS, "yoda", ANNCE_ACHIEVEMENT_YODA)
+ MSG_MEDAL_NOTIF(TELEFRAG, N__ALWAYS, "telefrag", ANNCE_ACHIEVEMENT_TELEFRAG)
+
+ MSG_MEDAL_NOTIF(CAPTURE, N__ALWAYS, "capture", NULL)
+ 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)
+ MSG_MEDAL_NOTIF(KILLSTREAK_15, N__ALWAYS, "killstreak_15", ANNCE_KILLSTREAK_15)
+
#undef N___NEVER
#undef N_GNTLOFF
MSG_INFO_NOTIF(FREEZETAG_SELF, N_CONSOLE, 1, 0, "s1", "", "", _("^BG%s^K1 froze themself"), "")
MULTITEAM_INFO(ROUND_TEAM_WIN, N_CONSOLE, 0, 0, "", "", "", _("^TC^TT^BG team wins the round"), "", NAME)
+ MULTITEAM_INFO(ROUND_TEAM_SCORES, N_CONSOLE, 0, 0, "", "", "", _("^TC^TT^BG scores"), "", NAME)
MSG_INFO_NOTIF(ROUND_PLAYER_WIN, N_CONSOLE, 1, 0, "s1", "", "", _("^BG%s^BG wins the round"), "")
MSG_INFO_NOTIF(ROUND_TIED, N_CONSOLE, 0, 0, "", "", "", _("^BGRound tied"), "")
MSG_INFO_NOTIF(ROUND_OVER, N_CONSOLE, 0, 0, "", "", "", _("^BGRound over, there's no winner"), "")
MSG_INFO_NOTIF(JOIN_CONNECT, N_CHATCON, 1, 0, "s1", "", "", _("^BG%s^F3 connected"), "")
MSG_INFO_NOTIF(JOIN_PLAY, N_CHATCON, 1, 0, "s1", "", "", _("^BG%s^F3 is now playing"), "")
MULTITEAM_INFO(JOIN_PLAY_TEAM, N_CHATCON, 1, 0, "s1", "", "", _("^BG%s^F3 is now playing on the ^TC^TT team"), "", NAME)
+ MULTITEAM_INFO(JOIN_WANTS_TEAM, N_CHATCON, 1, 0, "s1", "", "", _("^BG%s^F3 wants to play on the ^TC^TT team"), "", NAME)
MSG_INFO_NOTIF(KEEPAWAY_DROPPED, N_CONSOLE, 1, 0, "s1", "s1", "notify_balldropped", _("^BG%s^BG has dropped the ball!"), "")
MSG_INFO_NOTIF(KEEPAWAY_PICKUP, N_CONSOLE, 1, 0, "s1", "s1", "notify_ballpickedup", _("^BG%s^BG has picked up the ball!"), "")
MSG_INFO_NOTIF(POWERUP_STRENGTH, N_CONSOLE, 1, 0, "s1", "s1", "strength", _("^BG%s^K1 picked up Strength"), "")
MSG_INFO_NOTIF(QUIT_DISCONNECT, N_CHATCON, 1, 0, "s1", "", "", _("^BG%s^F3 disconnected"), "")
+ MSG_INFO_NOTIF(QUIT_KICK, N_CHATCON, 1, 0, "s1", "", "", _("^BG%s^F3 was kicked"), "")
MSG_INFO_NOTIF(QUIT_KICK_IDLING, N_CHATCON, 1, 1, "s1 f1", "", "", _("^BG%s^F3 was kicked after idling for %s seconds"), "")
MSG_INFO_NOTIF(MOVETOSPEC_IDLING, N_CHATCON, 1, 1, "s1 f1", "", "", _("^BG%s^F3 was moved to^BG spectators^F3 after idling for %s seconds"), "")
+ MSG_INFO_NOTIF(MOVETOSPEC_REMOVE, N_CHATCON, 1, 0, "s1", "", "", _("^BG%s^F3 was moved to^BG spectators^F3 for balance reasons"), "")
MSG_INFO_NOTIF(QUIT_KICK_SPECTATING, N_CONSOLE, 0, 0, "", "", "", _("^F2You were kicked from the server because you are a spectator and spectators aren't allowed at the moment."), "")
MSG_INFO_NOTIF(QUIT_KICK_TEAMKILL, N_CHATCON, 1, 0, "s1", "", "", _("^BG%s^F3 was kicked for excessive teamkilling"), "")
MSG_INFO_NOTIF(QUIT_PLAYBAN_TEAMKILL, N_CHATCON, 1, 0, "s1", "", "", _("^BG%s^F3 was forced to spectate for excessive teamkilling"), "")
MSG_INFO_NOTIF(QUIT_SPECTATE, N_CHATCON, 1, 0, "s1", "", "", _("^BG%s^F3 is now^BG spectating"), "")
+ MSG_INFO_NOTIF(QUIT_QUEUE, N_CHATCON, 1, 0, "s1", "", "", _("^BG%s^F3 has left the queue"), "")
MSG_INFO_NOTIF(RACE_ABANDONED, N_CONSOLE, 1, 0, "s1", "", "", _("^BG%s^BG has abandoned the race"), "")
MSG_INFO_NOTIF(RACE_FAIL_RANKED, N_CONSOLE, 1, 3, "s1 race_col f1ord race_col f3race_time race_diff", "s1 f3race_time", "race_newfail", _("^BG%s^BG couldn't break their %s%s^BG place record of %s%s %s"), "")
#define VERBOSE_MURDER(type) strcat(MURDER_##type, "^BG%s")
- #define MURDER_FRAG BOLD(_("^K3%sYou fragged ^BG%s"))
- #define MURDER_FRAG2 BOLD(_("^K3%sYou scored against ^BG%s"))
- #define MURDER_FRAGGED BOLD(_("^K1%sYou were fragged by ^BG%s"))
- #define MURDER_FRAGGED2 BOLD(_("^K1%sYou were scored against by ^BG%s"))
+ #define MURDER_FRAG strcat(BOLD_OPERATOR, _("^K3%sYou fragged ^BG%s"))
+ #define MURDER_FRAG2 strcat(BOLD_OPERATOR, _("^K3%sYou scored against ^BG%s"))
+ #define MURDER_FRAG3 strcat(BOLD_OPERATOR, _("^K3%sYou fragged ^BG%s"), "\n", "%s^BG place with %s")
+ #define MURDER_FRAG4 strcat(BOLD_OPERATOR, _("^K3%sYou fragged ^BG%s"), "\n", "%s^BG with %s")
+ #define MURDER_FRAGGED _("^K1%sYou were fragged by ^BG%s")
+ #define MURDER_FRAGGED2 _("^K1%sYou were scored against by ^BG%s")
MSG_CENTER_NOTIF(DEATH_MURDER_FRAG, N_ENABLE, 1, 1, "spree_cen s1", CPID_Null, "0 0", MURDER_FRAG, MURDER_FRAG2 )
+ MSG_CENTER_NOTIF(DEATH_MURDER_DM, N_ENABLE, 1, 2, "spree_cen s1 frag_pos f2", CPID_Null, "0 0", MURDER_FRAG3, "")
+ MSG_CENTER_NOTIF(DEATH_MURDER_DUEL, N_ENABLE, 2, 2, "spree_cen s1 s2 f2", CPID_Null, "0 0", MURDER_FRAG4, "")
MSG_CENTER_NOTIF(DEATH_MURDER_FRAGGED, N_ENABLE, 1, 1, "spree_cen s1", CPID_Null, "0 0", MURDER_FRAGGED, MURDER_FRAGGED2 )
MSG_CENTER_NOTIF(DEATH_MURDER_FRAGGED_VERBOSE, N_ENABLE, 1, 4, "spree_cen s1 frag_stats", CPID_Null, "0 0", VERBOSE_MURDER(FRAGGED), VERBOSE_MURDER(FRAGGED2) )
MSG_CENTER_NOTIF(DEATH_MURDER_FRAG_VERBOSE, N_ENABLE, 1, 2, "spree_cen s1 frag_ping", CPID_Null, "0 0", VERBOSE_MURDER(FRAG), VERBOSE_MURDER(FRAG2) )
MSG_CENTER_NOTIF(DISCONNECT_IDLING, N_ENABLE, 0, 1, "", CPID_IDLING, "1 f1", BOLD(_("^K1Stop idling!\n^BGDisconnecting in ^COUNT...")), "")
MSG_CENTER_NOTIF(MOVETOSPEC_IDLING, N_ENABLE, 0, 1, "", CPID_IDLING, "1 f1", BOLD(_("^K1Stop idling!\n^BGMoving to spectators in ^COUNT...")), "")
+ MSG_CENTER_NOTIF(MOVETOSPEC_REMOVE, N_ENABLE, 1, 1, "s1", CPID_REMOVE, "1 f1", BOLD(_("^K1Teams unbalanced!\n^BGMoving %s^BG to spectators in ^COUNT...")), "")
MSG_CENTER_NOTIF(DOOR_LOCKED_NEED, N_ENABLE, 1, 0, "s1", CPID_Null, "0 0", _("^BGYou need %s^BG!"), "")
MSG_CENTER_NOTIF(DOOR_LOCKED_ALSONEED, N_ENABLE, 1, 0, "s1", CPID_Null, "0 0", _("^BGYou also need %s^BG!"), "")
MULTITEAM_CENTER(ROUND_TEAM_LOSS, N_ENABLE, 0, 0, "", CPID_ROUND, "0 0", _("^TC^TT^BG team loses the round"), "", NAME)
MULTITEAM_CENTER(ROUND_TEAM_WIN, N_ENABLE, 0, 0, "", CPID_ROUND, "0 0", _("^TC^TT^BG team wins the round"), "", NAME)
+ MULTITEAM_CENTER(ROUND_TEAM_SCORES, N_ENABLE, 0, 0, "", CPID_ROUND, "0 0", _("^TC^TT^BG scores"), "", NAME)
MSG_CENTER_NOTIF(ROUND_PLAYER_WIN, N_ENABLE, 1, 0, "s1", CPID_ROUND, "0 0", _("^BG%s^BG wins the round"), "")
MSG_CENTER_NOTIF(FREEZETAG_SELF, N_ENABLE, 0, 0, "", CPID_Null, "0 0", _("^K1You froze yourself"), "")
MSG_CENTER_NOTIF(JOIN_PLAYBAN, N_ENABLE, 0, 0, "", CPID_PREVENT_JOIN, "0 0", BOLD(_("^K1You aren't allowed to play because you are banned in this server")), "")
MSG_CENTER_NOTIF(JOIN_PREVENT, N_ENABLE, 0, 1, "f1", CPID_PREVENT_JOIN, "0 0", _("^K1You may not join the game at this time.\nThis match is limited to ^F2%s^BG players."), "")
MSG_CENTER_NOTIF(JOIN_PREVENT_MINIGAME, N_ENABLE, 0, 0, "", CPID_Null, "0 0", _("^K1Cannot join given minigame session!"), "" )
+ MSG_CENTER_NOTIF(JOIN_PREVENT_QUEUE, N_ENABLE, 0, 0, "", CPID_Null, "0 0", _("^BGYou are now queued to join the game."), "")
MSG_CENTER_NOTIF(KEEPAWAY_DROPPED, N_ENABLE, 1, 0, "s1", CPID_KEEPAWAY, "0 0", _("^BG%s^BG has dropped the ball!"), "")
MSG_CENTER_NOTIF(KEEPAWAY_PICKUP, N_ENABLE, 1, 0, "s1", CPID_KEEPAWAY, "0 0", _("^BG%s^BG has picked up the ball!"), "")
MSG_CENTER_NOTIF(MISSING_TEAMS, N_ENABLE, 0, 1, "missing_teams", CPID_MISSING_TEAMS, "-1 0", _("^BGWaiting for players to join...\nNeed active players for: %s"), "")
MSG_CENTER_NOTIF(MISSING_PLAYERS, N_ENABLE, 0, 1, "f1", CPID_MISSING_PLAYERS, "-1 0", _("^BGWaiting for %s player(s) to join..."), "")
+ MSG_CENTER_NOTIF(MISSING_READY, N_ENABLE, 0, 0, "", CPID_MISSING_READY, "-1 0", _("^BGThe match will begin\nwhen more players are ready.\n\nPress ^F2F4^BG to get ready"), "")
MSG_CENTER_NOTIF(INSTAGIB_DOWNGRADE, N_ENABLE, 0, 0, "", CPID_INSTAGIB_FINDAMMO, "5 0", _("^BGYour weapon has been downgraded until you find some ammo!"), "")
MSG_CENTER_NOTIF(INSTAGIB_FINDAMMO, N_ENABLE, 0, 0, "", CPID_INSTAGIB_FINDAMMO, "1 9", _("^F4^COUNT^BG left to find some ammo!"), "")
MSG_CENTER_NOTIF(TIMEOUT_BEGINNING, N_ENABLE, 0, 1, "", CPID_TIMEOUT, "1 f1", _("^F4Timeout begins in ^COUNT"), "")
MSG_CENTER_NOTIF(TIMEOUT_ENDING, N_ENABLE, 0, 1, "", CPID_TIMEIN, "1 f1", _("^F4Timeout ends in ^COUNT"), "")
+ MSG_CENTER_NOTIF(TIMEOUT_ONGOING, N_ENABLE, 0, 0, "", CPID_TIMEIN, "1 f1", _("^F4Match paused"), "")
MSG_CENTER_NOTIF(VEHICLE_ENTER, N_ENABLE, 0, 0, "pass_key", CPID_VEHICLES, "0 0", _("^BGPress ^F2%s^BG to enter/exit the vehicle"), "")
MSG_CENTER_NOTIF(VEHICLE_ENTER_GUNNER, N_ENABLE, 0, 0, "pass_key", CPID_VEHICLES, "0 0", _("^BGPress ^F2%s^BG to enter the vehicle gunner"), "")
break;
}
+ case NOTIF_ALL_SPEC:
case NOTIF_ALL:
{
if (client) {
}
case NOTIF_TEAM:
+ case NOTIF_TEAM_ONLY:
{
if (!teamplay) {
return "Teamplay not active!";
}
case NOTIF_TEAM_EXCEPT:
+ case NOTIF_TEAM_ONLY_EXCEPT:
{
if (!teamplay) {
return "Teamplay not active!";
)
)
);
+ case NOTIF_TEAM_ONLY:
+ return (
+ (to_client.team == other_client.team)
+ );
+ case NOTIF_TEAM_ONLY_EXCEPT:
+ return (
+ (to_client != other_client)
+ &&
+ (to_client.team == other_client.team)
+ );
+ case NOTIF_ALL_SPEC:
+ return (
+ (IS_SPEC(to_client) || IS_OBSERVER(to_client))
+ );
case NOTIF_ALL:
return true;
case NOTIF_ALL_EXCEPT:
case MSG_CENTER:
case MSG_MULTI:
case MSG_CHOICE:
+ case MSG_MEDAL:
break;
default:
LOG_INFOF(
}
}
+void Create_Notification_Entity_Medal(entity notif,
+ float var_cvar,
+ string namestring,
+ /* MSG_MEDAL */
+ string icon,
+ Notification anncename)
+ {
+ notif.nent_floatcount = 1;
+ if (icon != "") { notif.nent_icon = strzone(icon); }
+ if (anncename) { notif.nent_msgannce = anncename; }
+ }
// ===============
// Cvar Handling
int NOTIF_CENTER_COUNT = 0;
int NOTIF_MULTI_COUNT = 0;
int NOTIF_CHOICE_COUNT = 0;
+ int NOTIF_MEDAL_COUNT = 0;
FOREACH(Notifications, true, {
switch (it.nent_type)
{
case MSG_CENTER: ++NOTIF_CENTER_COUNT; break;
case MSG_MULTI: ++NOTIF_MULTI_COUNT; break;
case MSG_CHOICE: ++NOTIF_CHOICE_COUNT; break;
+ case MSG_MEDAL: ++NOTIF_MEDAL_COUNT; break;
}
});
"Allow choice for this notification 0 = off, 1 = only in warmup mode, 2 = always"
);
});
+
+ NOTIF_WRITE(sprintf("\n// MSG_MEDAL notifications (count = %d):\n", NOTIF_MEDAL_COUNT));
+ FOREACH(Notifications, it.nent_type == MSG_MEDAL && (!it.nent_teamnum || it.nent_teamnum == NUM_TEAM_1), {
+ NOTIF_WRITE_ENTITY(it,
+ "Enable this multiple notification"
+ );
+ });
// edit these to match whichever cvars are used for specific notification options
NOTIF_WRITE("\n// HARD CODED notification variables:\n");
NOTIF_INFO_COUNT +
NOTIF_CENTER_COUNT +
NOTIF_MULTI_COUNT +
- NOTIF_CHOICE_COUNT
+ NOTIF_CHOICE_COUNT +
+ NOTIF_MEDAL_COUNT
),
NOTIF_ANNCE_COUNT,
NOTIF_INFO_COUNT,
NOTIF_CENTER_COUNT,
NOTIF_MULTI_COUNT,
- NOTIF_CHOICE_COUNT
+ NOTIF_CHOICE_COUNT,
+ NOTIF_MEDAL_COUNT
);
#undef NOTIF_WRITE_HARDCODED
#undef NOTIF_WRITE_ENTITY
centerprint_Add(ORDINAL(cpid), input, stof(arg_slot[0]), stof(arg_slot[1]));
}
-void Local_Notification_Queue_Run(MSG net_type, entity notif)
-{
+void Local_Notification_Queue_Run(MSG net_type, entity notif, float f1)
+{
switch (net_type)
{
case MSG_ANNCE:
Local_Notification_sound(notif.nent_channel, notif.nent_snd, notif.nent_vol, notif.nent_position);
break;
}
+
+ case MSG_MEDAL:
+ {
+ centerprint_Medal(notif.nent_icon, f1);
+ if(notif.nent_msgannce)
+ Local_Notification_sound(
+ notif.nent_msgannce.nent_channel,
+ notif.nent_msgannce.nent_snd,
+ notif.nent_msgannce.nent_vol,
+ notif.nent_msgannce.nent_position);
+ break;
+ }
}
}
-void Local_Notification_Queue_Add(MSG net_type, entity notif, float queue_time)
-{
+void Local_Notification_Queue_Add(MSG net_type, entity notif, float queue_time, float f1)
+{
// Guess length if required
if(queue_time == 0)
queue_time = soundlength(AnnouncerFilename(notif.nent_snd));
if(queue_time == -1 || time > notif_queue_next_time) {
// Run immediately
- Local_Notification_Queue_Run(net_type, notif);
+ Local_Notification_Queue_Run(net_type, notif, f1);
notif_queue_next_time = time + queue_time;
} else {
// Put in queue
notif_queue_type[notif_queue_length] = net_type;
notif_queue_entity[notif_queue_length] = notif;
notif_queue_time[notif_queue_length] = notif_queue_next_time;
+ notif_queue_f1[notif_queue_length] = f1;
notif_queue_next_time += queue_time;
++notif_queue_length;
if(!notif_queue_length || notif_queue_time[0] > time)
return;
- Local_Notification_Queue_Run(notif_queue_type[0], notif_queue_entity[0]);
+ Local_Notification_Queue_Run(notif_queue_type[0], notif_queue_entity[0], notif_queue_f1[0]);
// Shift queue to the left
--notif_queue_length;
notif_queue_type[j] = notif_queue_type[j+1];
notif_queue_entity[j] = notif_queue_entity[j+1];
notif_queue_time[j] = notif_queue_time[j+1];
+ notif_queue_f1[j] = notif_queue_f1[j+1];
}
}
case MSG_ANNCE:
{
#ifdef CSQC
- Local_Notification_Queue_Add(net_type, notif, notif.nent_queuetime);
+ Local_Notification_Queue_Add(net_type, notif, notif.nent_queuetime, f1);
#else
backtrace("MSG_ANNCE on server?... Please notify Samual immediately!\n");
#endif
f1, f2, f3, f4);
break;
}
+
+ #ifdef CSQC
+ case MSG_MEDAL:
+ {
+ Local_Notification_Queue_Add(
+ net_type,
+ notif,
+ (notif.nent_msgannce ? MSG_MEDAL_TIME : 0),
+ f1);
+ break;
+ }
+ #endif
}
}
CASE(MSG, CHOICE)
/** Kill centerprint message @deprecated */
CASE(MSG, CENTER_KILL)
+ /** Medal notification */
+ CASE(MSG, MEDAL)
ENUMCLASS_END(MSG)
string Get_Notif_TypeName(MSG net_type)
case MSG_CENTER: return "MSG_CENTER";
case MSG_MULTI: return "MSG_MULTI";
case MSG_CHOICE: return "MSG_CHOICE";
+ case MSG_MEDAL: return "MSG_MEDAL";
case MSG_CENTER_KILL: return "MSG_CENTER_KILL";
}
LOG_WARNF("Get_Notif_TypeName(%d): Improper net type!", ORDINAL(net_type));
return "";
}
-
ENUMCLASS(CPID)
CASE(CPID, ASSAULT_ROLE)
CASE(CPID, ROUND)
CASE(CPID, STALEMATE)
CASE(CPID, NADES)
CASE(CPID, IDLING)
+ CASE(CPID, REMOVE)
CASE(CPID, ITEM)
CASE(CPID, PREVENT_JOIN)
CASE(CPID, KEEPAWAY)
CASE(CPID, LMS)
CASE(CPID, MISSING_TEAMS)
CASE(CPID, MISSING_PLAYERS)
+ CASE(CPID, MISSING_READY)
CASE(CPID, INSTAGIB_FINDAMMO)
CASE(CPID, NIX)
CASE(CPID, ONSLAUGHT)
Notification optiona,
Notification optionb);
+void Create_Notification_Entity_Medal(entity notif,
+ float var_cvar,
+ string namestring,
+ /* MSG_MEDAL */
+ string icon,
+ Notification anncename);
+
void Dump_Notifications(int fh, bool alsoprint);
#define DEFAULT_FILENAME "notifications_dump.cfg"
CASE(NOTIF, TEAM)
/** send only to X team and their spectators, except for Y person and their spectators */
CASE(NOTIF, TEAM_EXCEPT)
+ /** send only to X team; don't include spectators */
+ CASE(NOTIF, TEAM_ONLY)
+ /** send to team X team except for Y person; don't include spectators */
+ CASE(NOTIF, TEAM_ONLY_EXCEPT)
/** send to everyone */
CASE(NOTIF, ALL)
/** send to everyone except X person and their spectators */
CASE(NOTIF, ALL_EXCEPT)
+ /** send to all spectators **/
+ CASE(NOTIF, ALL_SPEC)
ENUMCLASS_END(NOTIF)
string Get_Notif_BroadcastName(NOTIF broadcast)
{
case NOTIF_ONE: return "NOTIF_ONE";
case NOTIF_ONE_ONLY: return "NOTIF_ONE_ONLY";
+ case NOTIF_ALL_SPEC: return "NOTIF_ALL_SPEC";
case NOTIF_ALL_EXCEPT: return "NOTIF_ALL_EXCEPT";
case NOTIF_ALL: return "NOTIF_ALL";
case NOTIF_TEAM: return "NOTIF_TEAM";
case NOTIF_TEAM_EXCEPT: return "NOTIF_TEAM_EXCEPT";
+ case NOTIF_TEAM_ONLY: return "NOTIF_TEAM_ONLY";
+ case NOTIF_TEAM_ONLY_EXCEPT: return "NOTIF_TEAM_ONLY_EXCEPT";
}
LOG_WARNF("Get_Notif_BroadcastName(%d): Improper broadcast!", broadcast);
return "";
entity notif_queue_entity[NOTIF_QUEUE_MAX];
MSG notif_queue_type[NOTIF_QUEUE_MAX];
float notif_queue_time[NOTIF_QUEUE_MAX];
+float notif_queue_f1[NOTIF_QUEUE_MAX];
float notif_queue_next_time;
int notif_queue_length;
ARG_CASE(ARG_CS, "join_key", getcommandkey(_("jump"), "+jump")) \
ARG_CASE(ARG_CS, "frag_ping", notif_arg_frag_ping(true, f2)) \
ARG_CASE(ARG_CS, "frag_stats", notif_arg_frag_stats(f2, f3, f4)) \
- /*ARG_CASE(ARG_CS, "frag_pos", ((Should_Print_Score_Pos(f1)) ? sprintf("\n^BG%s", Read_Score_Pos(f1)) : ""))*/ \
+ ARG_CASE(ARG_CS, "frag_pos", notif_arg_frag_pos(f2)) \
ARG_CASE(ARG_CS, "spree_cen", (autocvar_notification_show_sprees ? notif_arg_spree_cen(f1) : "")) \
ARG_CASE(ARG_CS_SV, "spree_inf", (autocvar_notification_show_sprees ? notif_arg_spree_inf(1, input, s2, f2) : "")) \
ARG_CASE(ARG_CS_SV, "spree_end", (autocvar_notification_show_sprees ? notif_arg_spree_inf(-1, "", "", f1) : "")) \
SPREE_ITEM(5, 05, _("RAGE! "), _("%s^K1 unlocked RAGE! %s^BG"), _("%s^K1 made FIVE SCORES IN A ROW! %s^BG")) \
SPREE_ITEM(10, 10, _("MASSACRE! "), _("%s^K1 started a MASSACRE! %s^BG"), _("%s^K1 made TEN SCORES IN A ROW! %s^BG")) \
SPREE_ITEM(15, 15, _("MAYHEM! "), _("%s^K1 executed MAYHEM! %s^BG"), _("%s^K1 made FIFTEEN SCORES IN A ROW! %s^BG")) \
- SPREE_ITEM(20, 20, _("BERSERKER! "), _("%s^K1 is a BERSERKER! %s^BG"), _("%s^K1 made TWENTY SCORES IN A ROW! %s^BG")) \
- SPREE_ITEM(25, 25, _("CARNAGE! "), _("%s^K1 inflicts CARNAGE! %s^BG"), _("%s^K1 made TWENTY FIVE SCORES IN A ROW! %s^BG")) \
- SPREE_ITEM(30, 30, _("ARMAGEDDON! "), _("%s^K1 unleashes ARMAGEDDON! %s^BG"), _("%s^K1 made THIRTY SCORES IN A ROW! %s^BG"))
#ifdef CSQC
+// z411 TODO : This actually doesn't work very well.
+// This gets run before the client gets score updates so it works
+// fine when you're playing (because frags get updated first)
+// but it breaks a lot when you're spectating because
+// we sometimes get the new frag info at different times
+// (before or after we run this). A suggested fix would
+// be to do this sorting and comparison in the server.
+string notif_arg_frag_pos(int score)
+{
+ entity pl;
+ int place = 1;
+ string str, color, tail;
+ bool tied = false;
+
+ for(pl = players.sort_next; pl; pl = pl.sort_next) {
+ if(pl.team == NUM_SPECTATOR) continue;
+ if(pl.(scores(SP_SCORE)) == score) break;
+ ++place;
+ }
+
+ entity prev = pl.sort_prev;
+ entity next = pl.sort_next;
+ if(prev && prev.(scores(SP_SCORE)) == score) {
+ tied = true;
+ --place; // We're tied always for the best place
+ }
+ if(next && next.(scores(SP_SCORE)) == score) {
+ tied = true;
+ }
+
+ switch(place) {
+ case 1:
+ color = "^4";
+ break;
+ case 2:
+ color = "^1";
+ break;
+ case 3:
+ color = "^3";
+ break;
+ default:
+ color = "";
+ }
+
+ switch(place % 10) {
+ case 1:
+ tail = "st";
+ break;
+ case 2:
+ tail = "nd";
+ break;
+ case 3:
+ tail = "rd";
+ break;
+ default:
+ tail = "th";
+ }
+
+ str = strcat(color, ftos(place), tail);
+ if(tied)
+ return strcat("Tied for ", str);
+ else
+ return str;
+}
+
string notif_arg_frag_ping(bool newline, float fping)
{
string s = newline ? "\n" : " ";
optiona, /* optiona */ \
optionb); /* optionb */ \
}
+
+#define MSG_MEDAL_NOTIF(name, defaultvalue, icon, anncename) \
+ NOTIF_ADD_AUTOCVAR(MEDAL_##name, defaultvalue) \
+ MSG_MEDAL_NOTIF_(0, MEDAL_##name, MEDAL_##name, defaultvalue, icon, anncename)
+
+#define MSG_MEDAL_NOTIF_(teamnum, name, cvarname, defaultvalue, icon, anncename) \
+ REGISTER(Notifications, name, m_id, new_pure(msg_medal_notification)) { \
+ Create_Notification_Entity (this, defaultvalue, ACVNN(cvarname), MSG_MEDAL, strtoupper(#name), teamnum); \
+ Create_Notification_Entity_Medal(this, ACVNN(cvarname), strtoupper(#name), \
+ icon, \
+ anncename); \
+ }
REGISTRY_BEGIN(Notifications)
{
REPLICATE_INIT(bool, cvar_cl_cts_noautoswitch);
REPLICATE_INIT(float, cvar_cl_handicap);
REPLICATE_INIT(bool, cvar_cl_noantilag);
+REPLICATE_INIT(bool, cvar_cl_chat_sounds);
REPLICATE_INIT(string, cvar_g_xonoticversion);
REPLICATE(cvar_cl_autoswitch, bool, "cl_autoswitch");
REPLICATE(cvar_cl_autoscreenshot, int, "cl_autoscreenshot");
REPLICATE(cvar_cl_cts_noautoswitch, bool, "cl_cts_noautoswitch");
REPLICATE(cvar_cl_handicap, float, "cl_handicap");
REPLICATE(cvar_cl_noantilag, bool, "cl_noantilag");
+REPLICATE(cvar_cl_chat_sounds, bool, "cl_chat_sounds");
REPLICATE(cvar_g_xonoticversion, string, "g_xonoticversion");
#endif
#pragma once
-#define MAX_SCORE 64
+#define MAX_SCORE 128
#define REGISTER_SP(id) REGISTER(Scores, SP, id, m_id, new_pure(PlayerScoreField))
REGISTRY(Scores, MAX_SCORE)
REGISTER_SP(PING);
REGISTER_SP(PL);
+REGISTER_SP(COUNTRY); //LegendGuard adds new column for country label 05-04-2021
REGISTER_SP(NAME);
REGISTER_SP(SEPARATOR);
REGISTER_SP(KDRATIO); // kills / deaths
REGISTER_SP(SUM); // kills - deaths
REGISTER_SP(FRAGS); // kills - suicides
+
+REGISTER_SP(MEDAL_AIRSHOT);
+REGISTER_SP(MEDAL_DAMAGE);
+REGISTER_SP(MEDAL_ELECTROBITCH);
+REGISTER_SP(MEDAL_EXCELLENT);
+REGISTER_SP(MEDAL_FIRSTBLOOD);
+REGISTER_SP(MEDAL_HEADSHOT);
+REGISTER_SP(MEDAL_HUMILIATION);
+REGISTER_SP(MEDAL_IMPRESSIVE);
+REGISTER_SP(MEDAL_YODA);
+REGISTER_SP(MEDAL_TELEFRAG);
+
+REGISTER_SP(MEDAL_ACCURACY);
+REGISTER_SP(MEDAL_ASSIST);
+REGISTER_SP(MEDAL_CAPTURE);
+REGISTER_SP(MEDAL_DEFENSE);
+REGISTER_SP(MEDAL_PERFECT);
+
+REGISTER_SP(MEDAL_KILLSTREAK_03);
+REGISTER_SP(MEDAL_KILLSTREAK_05);
+REGISTER_SP(MEDAL_KILLSTREAK_10);
+REGISTER_SP(MEDAL_KILLSTREAK_15);
+
+REGISTER_SP(SV_SURVIVALS);
+REGISTER_SP(SV_HUNTS);
#endif
SOUND(SEEKER_FIRE, W_Sound("seeker_fire"));
SOUND(SHOTGUN_FIRE, W_Sound("shotgun_fire"));
SOUND(SHOTGUN_MELEE, W_Sound("shotgun_melee"));
+SOUND(SHOTGUN_MELEE_IMPACT, W_Sound("shotgun_melee_impact"));
SOUND(STRENGTH_FIRE, W_Sound("strength_fire"));
SOUND(TAGEXP1, W_Sound("tagexp1"));
SOUND(TAGEXP2, W_Sound("tagexp2"));
SOUND(WEAPON_SWITCH, W_Sound("weapon_switch"));
SOUND(CTF_CAPTURE_NEUTRAL, "ctf/capture");
-SOUND(CTF_CAPTURE_RED, "ctf/red_capture");
-SOUND(CTF_CAPTURE_BLUE, "ctf/blue_capture");
+SOUND(CTF_CAPTURE_RED, "ctf/red_capture_clean");
+SOUND(CTF_CAPTURE_BLUE, "ctf/blue_capture_clean");
SOUND(CTF_CAPTURE_YELLOW, "ctf/yellow_capture");
SOUND(CTF_CAPTURE_PINK, "ctf/pink_capture");
Sound SND_CTF_CAPTURE(int teamid) {
}
SOUND(CTF_DROPPED_NEUTRAL, "ctf/neutral_dropped");
-SOUND(CTF_DROPPED_RED, "ctf/red_dropped");
-SOUND(CTF_DROPPED_BLUE, "ctf/blue_dropped");
+SOUND(CTF_DROPPED_RED, "ctf/red_dropped_clean");
+SOUND(CTF_DROPPED_BLUE, "ctf/blue_dropped_clean");
SOUND(CTF_DROPPED_YELLOW, "ctf/yellow_dropped");
SOUND(CTF_DROPPED_PINK, "ctf/pink_dropped");
Sound SND_CTF_DROPPED(int teamid) {
SOUND(CTF_RESPAWN, "ctf/flag_respawn");
SOUND(CTF_RETURNED_NEUTRAL, "ctf/return");
-SOUND(CTF_RETURNED_RED, "ctf/red_returned");
-SOUND(CTF_RETURNED_BLUE, "ctf/blue_returned");
+SOUND(CTF_RETURNED_RED, "ctf/red_returned_clean");
+SOUND(CTF_RETURNED_BLUE, "ctf/blue_returned_clean");
SOUND(CTF_RETURNED_YELLOW, "ctf/yellow_returned");
SOUND(CTF_RETURNED_PINK, "ctf/pink_returned");
Sound SND_CTF_RETURNED(int teamid) {
}
SOUND(CTF_TAKEN_NEUTRAL, "ctf/neutral_taken");
-SOUND(CTF_TAKEN_RED, "ctf/red_taken");
-SOUND(CTF_TAKEN_BLUE, "ctf/blue_taken");
+SOUND(CTF_TAKEN_RED, "ctf/red_taken_clean");
+SOUND(CTF_TAKEN_BLUE, "ctf/blue_taken_clean");
SOUND(CTF_TAKEN_YELLOW, "ctf/yellow_taken");
SOUND(CTF_TAKEN_PINK, "ctf/pink_taken");
Sound SND_CTF_TAKEN(int teamid) {
SOUND(HIT, "misc/hit");
SOUND(TYPEHIT, "misc/typehit");
SOUND(KILL, "misc/kill");
+SOUND(DEATH, "misc/death");
+SOUND(ENDCOUNT, "misc/endcount");
+SOUND(ENDMATCH, "misc/endmatch");
+SOUND(OVERTIME, "misc/overtime");
+SOUND(TIMEOUT, "misc/timeout");
+
+SOUND(MIDAIR, "misc/midair");
SOUND(SPAWN, "misc/spawn");
PlayerState ps = PS(this);
if (!ps) return; // initial connect
PS(this) = NULL;
- Inventory_clear(this.inventory_store); // no need to network updates, as there is no inventory attached
+ //Inventory_clear(this.inventory_store); // no need to network updates, as there is no inventory attached
if (ps.m_client != this) return; // don't own state, spectator
ps.ps_push(ps, this);
float game_stopped;
float game_starttime; //point in time when the countdown to game start is over
float round_starttime; //point in time when the countdown to round start is over
+float round_delaytime;
+float overtime_starttime; // z411 point in time where first overtime started
+
+float timeout_last;
+float timeout_total_time;
+bool game_timeout;
+
int autocvar_leadlimit;
int overtimes; // overtimes added (-1 = sudden death)
int timeout_status; // (values: 0, 1, 2) contains whether a timeout is not active (0), was called but still at leadtime (1) or is active (2)
#endif
REGISTER_STAT(WEAPONRATEFACTOR, float, W_WeaponRateFactor(this))
REGISTER_STAT(GAME_STOPPED, int, game_stopped)
+
+REGISTER_STAT(TIMEOUT_LAST, float, timeout_last)
+
REGISTER_STAT(GAMESTARTTIME, float, game_starttime)
/** arc heat in [0,1] */
REGISTER_STAT(PRESSED_KEYS, int)
REGISTER_STAT(VEHICLESTAT_RELOAD2, int)
REGISTER_STAT(VEHICLESTAT_W2MODE, int)
REGISTER_STAT(NADE_TIMER, float)
-REGISTER_STAT(SECRETS_TOTAL, int, secrets_total)
-REGISTER_STAT(SECRETS_FOUND, int, secrets_found)
REGISTER_STAT(RESPAWN_TIME, float)
REGISTER_STAT(ROUNDSTARTTIME, float, round_starttime)
+REGISTER_STAT(ROUNDENDTIME, float, round_delaytime)
REGISTER_STAT(OVERTIMES, int, overtimes)
REGISTER_STAT(TIMEOUT_STATUS, int, timeout_status)
-REGISTER_STAT(MONSTERS_TOTAL, int)
-REGISTER_STAT(MONSTERS_KILLED, int)
REGISTER_STAT(NADE_BONUS, float)
REGISTER_STAT(NADE_BONUS_TYPE, int)
REGISTER_STAT(NADE_BONUS_SCORE, float)
#ifdef SVQC
SPECTATE_COPYFIELD(_STAT(GUNALIGN))
#endif
+
+REGISTER_STAT(SURVIVAL_ROUNDTIMER, float)
#ifdef CSQC
bool teamplay;
int myteam;
+
+// z411 used for custom names
+string teamname_red;
+string teamname_blue;
+string teamname_yellow;
+string teamname_pink;
#endif
string Team_ColorCode(int teamid)
return '0 0 0';
}
+#ifdef CSQC
+string Team_CustomName(int teamid)
+{
+ switch(teamid)
+ {
+ case NUM_TEAM_1: return ((teamname_red != "") ? teamname_red : "^1RED^7 team");
+ case NUM_TEAM_2: return ((teamname_blue != "")? teamname_blue : "^4BLUE^7 team");
+ case NUM_TEAM_3: return ((teamname_yellow != "") ? teamname_yellow : "^3YELLOW^7 team");
+ case NUM_TEAM_4: return ((teamname_pink != "") ? teamname_pink : "^6PINK^7 team");
+ }
+
+ return NAME_NEUTRAL;
+}
+#endif
+
string Team_ColorName(int teamid)
{
switch(teamid)
string playername(string thename, int teamid, bool team_colorize)
{
TC(int, teamid);
- bool do_colorize = (teamplay && team_colorize);
+ bool do_colorize = (teamplay && team_colorize && Team_IsValidTeam(teamid));
#ifdef SVQC
if(do_colorize && !intermission_running)
#else
if(IS_PLAYER(directhitentity))
if(DIFF_TEAM(this.realowner, directhitentity))
if(!IS_DEAD(directhitentity))
- if(IsFlying(directhitentity))
- Send_Notification(NOTIF_ONE, this.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
+ if(IsFlying(directhitentity)) {
+ Give_Medal(this.realowner, AIRSHOT);
+ }
this.event_damage = func_null;
this.takedamage = DAMAGE_NO;
vector desireddir, olddir, newdir, desiredorigin, goal;
float velspeed, f;
this.nextthink = time;
+ if(game_timeout) { set_movetype(this, MOVETYPE_NONE); this.disableclientprediction = 2; return; } else { set_movetype(this, MOVETYPE_FLY); this.disableclientprediction = 0; }
if(time > this.cnt)
{
this.projectiledeathtype |= HITTYPE_BOUNCE;
void W_Electro_Explode(entity this, entity directhitentity)
{
- if(directhitentity.takedamage == DAMAGE_AIM)
+ /*if(directhitentity.takedamage == DAMAGE_AIM)
if(IS_PLAYER(directhitentity))
if(DIFF_TEAM(this.realowner, directhitentity))
if(!IS_DEAD(directhitentity))
- if(IsFlying(directhitentity))
- Send_Notification(NOTIF_ONE, this.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_ELECTROBITCH);
-
+ if(IsFlying(directhitentity)) {
+ Give_Medal(this.realowner, ELECTROBITCH);
+ }
+ */
+
this.event_damage = func_null;
this.takedamage = DAMAGE_NO;
this.velocity = this.movedir; // .velocity must be != '0 0 0' for particle fx and decal to work
if(IS_PLAYER(directhitentity))
if(DIFF_TEAM(this.realowner, directhitentity))
if(!IS_DEAD(directhitentity))
- if(IsFlying(directhitentity))
- Send_Notification(NOTIF_ONE, this.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
+ if(IsFlying(directhitentity)) {
+ Give_Medal(this.realowner, AIRSHOT);
+ }
this.event_damage = func_null;
this.takedamage = DAMAGE_NO;
if(IS_PLAYER(directhitentity))
if(DIFF_TEAM(this.realowner, directhitentity))
if(!IS_DEAD(directhitentity))
- if(IsFlying(directhitentity))
- Send_Notification(NOTIF_ONE, this.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
+ if(IsFlying(directhitentity)) {
+ Give_Medal(this.realowner, AIRSHOT);
+ }
this.event_damage = func_null;
this.takedamage = DAMAGE_NO;
//print(strcat(this.realowner.netname, " hitting ", target_victim.netname, " with ", strcat(ftos(swing_damage), " damage (factor: ", ftos(swing_factor), ") at "), ftos(time), " seconds.\n"));
+ sound(target_victim, CH_SHOTS, SND_SHOTGUN_MELEE_IMPACT, VOL_BASE, ATTEN_NORM);
Damage(target_victim, this.realowner, this.realowner,
swing_damage, WEP_SHOTGUN.m_id | HITTYPE_SECONDARY, this.weaponentity_fld,
this.realowner.origin + this.realowner.view_ofs,
sound (actor, CH_WEAPON_A, SND_MINSTANEXFIRE, VOL_BASE * 0.8, ATTEN_NORM);
yoda = 0;
- impressive_hits = 0;
+ //impressive_hits = 0;
FireRailgunBullet(actor, weaponentity, w_shotorg, w_shotorg + w_shotdir * max_shot_distance, vaporizer_damage, true, WEP_CVAR_PRI(vaporizer, force), 0, 0, 0, 0, thiswep.m_id);
// do this now, as goodhits is disabled below
W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, normalize(v - w_shotorg));
SendCSQCVaporizerBeamParticle(actor, impressive_hits);
- if(yoda && flying)
- Send_Notification(NOTIF_ONE, actor, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA);
- if(impressive_hits && actor.vaporizer_lasthit)
+ if(yoda && flying) {
+ Give_Medal(actor, YODA);
+ }
+
+ // We're gonna disable Impressive medals for the vaporizer.
+ /*if(impressive_hits && actor.vaporizer_lasthit)
{
- Send_Notification(NOTIF_ONE, actor, MSG_ANNCE, ANNCE_ACHIEVEMENT_IMPRESSIVE);
+ Give_Medal(actor, IMPRESSIVE);
impressive_hits = 0; // only every second time
- }
+ }*/
actor.vaporizer_lasthit = impressive_hits;
if(IS_PLAYER(directhitentity))
if(DIFF_TEAM(this.realowner, directhitentity))
if(!IS_DEAD(directhitentity))
- if(IsFlying(directhitentity))
- Send_Notification(NOTIF_ONE, this.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_ELECTROBITCH);
+ if(IsFlying(directhitentity)) {
+ Give_Medal(this.realowner, ELECTROBITCH);
+ }
this.event_damage = func_null;
this.takedamage = DAMAGE_NO;
}
METHOD(Vaporizer, wr_setup, void(entity thiswep, entity actor, .entity weaponentity))
{
- actor.vaporizer_lasthit = 0;
+ //actor.vaporizer_lasthit = 0;
}
METHOD(Vaporizer, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
{
impressive_hits = 0;
FireRailgunBullet(actor, weaponentity, w_shotorg, w_shotorg + w_shotdir * max_shot_distance, mydmg, false, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, dtype);
- if(yoda && flying)
- Send_Notification(NOTIF_ONE, actor, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA);
+ if(yoda && flying) {
+ if(charge == 1) // play additional sound if we hit in the air with maximum damage
+ sound(actor, CH_INFO, SND_MIDAIR, VOL_BASE, ATTN_NONE);
+
+ Give_Medal(actor, YODA);
+ }
+
if(impressive_hits && actor.vortex_lasthit)
{
- Send_Notification(NOTIF_ONE, actor, MSG_ANNCE, ANNCE_ACHIEVEMENT_IMPRESSIVE);
+ Give_Medal(actor, IMPRESSIVE);
impressive_hits = 0; // only every second time
}
/* reticle */ ATTRIB(Vortex, w_reticle, string, "gfx/reticle_nex");
/* wepimg */ ATTRIB(Vortex, model2, string, "weaponnex");
/* refname */ ATTRIB(Vortex, netname, string, "vortex");
-/* wepname */ ATTRIB(Vortex, m_name, string, _("Vortex"));
+/* wepname */ ATTRIB(Vortex, m_name, string, _("Nex"));
/* legacy */ ATTRIB(Vortex, m_deprecated_netname, string, "nex");
#define X(BEGIN, P, END, class, prefix) \
void sys_phys_pregame_hold(entity this)
{
if (!IS_PLAYER(this)) { return; }
- const bool allowed_to_move = (time >= game_starttime && !game_stopped);
+ // z411
+ //const bool allowed_to_move = (time >= game_starttime && !game_stopped);
+ const bool allowed_to_move = (!game_stopped && !game_timeout);
if (!allowed_to_move) {
this.velocity = '0 0 0';
set_movetype(this, MOVETYPE_NONE);
#include <common/gamemodes/_mod.qh>
#include <common/mapobjects/target/location.qh>
#include <common/mapobjects/triggers.qh>
+#include <common/net_linked.qh>
#include <common/notifications/all.qh>
#include <common/teams.qh>
#include <common/util.qh>
*/
string namestr = "";
- if (source)
- namestr = playername(source.netname, source.team, (autocvar_g_chat_teamcolors && IS_PLAYER(source)));
+ if (source) {
+ namestr = playername(source.netname, source.team, (autocvar_g_chat_teamcolors));
+
+ if (IS_DEAD(source) || source.frags == FRAGS_PLAYER_OUT_OF_GAME)
+ namestr = strcat("(DEAD) ", namestr);
+ else if (IS_OBSERVER(source) || IS_SPEC(source))
+ namestr = strcat("(s) ", namestr);
+ }
string colorprefix = (strdecolorize(namestr) == namestr) ? "^3" : "^7";
//msgin = strreplace("/me", "", msgin);
//msgin = substring(msgin, 3, strlen(msgin));
//msgin = strreplace("/me", strcat(colorstr, "(", colorprefix, namestr, colorstr, ")^7"), msgin);
- msgstr = strcat("\{1}\{13}^4* ", "^7", msgin);
+ msgstr = strcat("\{1}\{13}^4* ", "^5", msgin);
}
else
- msgstr = strcat("\{1}\{13}", colorstr, "(", colorprefix, namestr, colorstr, ") ^7", msgin);
- cmsgstr = strcat(colorstr, "(", colorprefix, namestr, colorstr, ")\n^7", msgin);
+ msgstr = strcat("\{1}\{13}", colorstr, "(Team) ", namestr, colorstr, ": ^5", msgin);
+ cmsgstr = strcat(colorstr, "(", colorprefix, namestr, colorstr, ")\n^5", msgin);
}
else
{
flood = 1;
}
- if (timeout_status == TIMEOUT_ACTIVE) // when game is paused, no flood protection
- source.(flood_field) = flood = 0;
+ // z411 : Why?
+ //if (timeout_status == TIMEOUT_ACTIVE) // when game is paused, no flood protection
+ // source.(flood_field) = flood = 0;
}
string sourcemsgstr, sourcecmsgstr;
sprint(it, msgstr);
});
- event_log_msg = sprintf(":chat_spec:%d:%s", source.playerid, strreplace("\n", " ", msgin));
+
+ if(!play_chatsound(source, msgin))
+ event_log_msg = sprintf(":chat_spec:%d:%s", source.playerid, strreplace("\n", " ", msgin));
}
else
{
sprint(it, msgstr);
});
- event_log_msg = sprintf(":chat:%d:%s", source.playerid, strreplace("\n", " ", msgin));
+
+ if(!play_chatsound(source, msgin))
+ event_log_msg = sprintf(":chat:%d:%s", source.playerid, strreplace("\n", " ", msgin));
}
}
return ret;
}
+bool play_chatsound(entity source, string msgin)
+{
+ if(autocvar_sv_chat_sounds && CS_CVAR(source).cvar_cl_chat_sounds) {
+ var .float flood_sound = floodcontrol_chatsound;
+
+ if (source.(flood_sound) < time - autocvar_sv_chat_sounds_flood) {
+ string rawmsg;
+ bool found = false;
+ rawmsg = strreplace("\n", " ", msgin);
+
+ FOREACH_WORD(autocvar_sv_chat_sounds_list, it == rawmsg, { found = true; });
+ if (found) {
+ FOREACH_CLIENT(IS_REAL_CLIENT(it) && CS_CVAR(it).cvar_cl_chat_sounds, {
+ msg_entity = it;
+ WriteHeader(MSG_ONE, TE_CSQC_CHATSOUND);
+ WriteString(MSG_ONE, rawmsg);
+ });
+ source.(flood_sound) = time;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
entity findnearest(vector point, bool checkitems, vector axismod)
{
vector dist;
bool autocvar_g_chat_teamcolors;
bool autocvar_g_chat_tellprivacy;
+bool autocvar_sv_chat_sounds;
+float autocvar_sv_chat_sounds_flood;
+string autocvar_sv_chat_sounds_list;
+
const float NUM_NEAREST_ENTITIES = 4;
entity nearest_entity[NUM_NEAREST_ENTITIES];
float nearest_length[NUM_NEAREST_ENTITIES];
.float floodcontrol_chattell;
.float floodcontrol_voice;
.float floodcontrol_voiceteam;
+.float floodcontrol_chatsound;
#define CHAT_NOSPECTATORS() ((autocvar_g_chat_nospectators == 1) || (autocvar_g_chat_nospectators == 2 && !warmup_stage))
int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodcontrol);
+bool play_chatsound(entity source, string msgin);
string NearestLocation(vector p);
WriteHeader(MSG_BROADCAST, TE_CSQC_TEAMNAGGER);
}
+void send_TeamNames(int channel, entity to) {
+ msg_entity = to;
+
+ WriteHeader(channel, TE_CSQC_TEAMNAMES);
+ WriteString(channel, autocvar_g_teamnames_red);
+ WriteString(channel, autocvar_g_teamnames_blue);
+ WriteString(channel, autocvar_g_teamnames_yellow);
+ WriteString(channel, autocvar_g_teamnames_pink);
+}
+
int CountSpectators(entity player, entity to)
{
if(!player) { return 0; } // not sure how, but best to be safe
if (CS(this).just_joined)
CS(this).just_joined = false;
+ if (this.wants_join)
+ this.wants_join = 0;
+
+ // for RJZ
+ if (autocvar_rjz_count_shards)
+ send_TotalShards(this);
}
int player_getspecies(entity this)
setcolor(player, stof(autocvar_sv_defaultplayercolors));
}
-void GiveWarmupResources(entity this)
+void ResetPlayerResources(entity this)
{
- SetResource(this, RES_SHELLS, warmup_start_ammo_shells);
- SetResource(this, RES_BULLETS, warmup_start_ammo_nails);
- SetResource(this, RES_ROCKETS, warmup_start_ammo_rockets);
- SetResource(this, RES_CELLS, warmup_start_ammo_cells);
- SetResource(this, RES_PLASMA, warmup_start_ammo_plasma);
- SetResource(this, RES_FUEL, warmup_start_ammo_fuel);
- SetResource(this, RES_HEALTH, warmup_start_health);
- SetResource(this, RES_ARMOR, warmup_start_armorvalue);
- STAT(WEAPONS, this) = WARMUP_START_WEAPONS;
+ if (warmup_stage) {
+ SetResource(this, RES_SHELLS, warmup_start_ammo_shells);
+ SetResource(this, RES_BULLETS, warmup_start_ammo_nails);
+ SetResource(this, RES_ROCKETS, warmup_start_ammo_rockets);
+ SetResource(this, RES_CELLS, warmup_start_ammo_cells);
+ SetResource(this, RES_PLASMA, warmup_start_ammo_plasma);
+ SetResource(this, RES_FUEL, warmup_start_ammo_fuel);
+ SetResource(this, RES_HEALTH, warmup_start_health);
+ SetResource(this, RES_ARMOR, warmup_start_armorvalue);
+ STAT(WEAPONS, this) = WARMUP_START_WEAPONS;
+ } else {
+ SetResource(this, RES_SHELLS, start_ammo_shells);
+ SetResource(this, RES_BULLETS, start_ammo_nails);
+ SetResource(this, RES_ROCKETS, start_ammo_rockets);
+ SetResource(this, RES_CELLS, start_ammo_cells);
+ SetResource(this, RES_PLASMA, start_ammo_plasma);
+ SetResource(this, RES_FUEL, start_ammo_fuel);
+ SetResource(this, RES_HEALTH, start_health);
+ SetResource(this, RES_ARMOR, start_armorvalue);
+ STAT(WEAPONS, this) = start_weapons;
+ if (MUTATOR_CALLHOOK(ForbidRandomStartWeapons, this) == false)
+ {
+ GiveRandomWeapons(this, random_start_weapons_count,
+ autocvar_g_random_start_weapons, random_start_ammo);
+ }
+ }
}
void PutPlayerInServer(entity this)
this.takedamage = DAMAGE_AIM;
this.effects = EF_TELEPORT_BIT | EF_RESTARTANIM_BIT;
- if (warmup_stage)
- GiveWarmupResources(this);
- else
- {
- SetResource(this, RES_SHELLS, start_ammo_shells);
- SetResource(this, RES_BULLETS, start_ammo_nails);
- SetResource(this, RES_ROCKETS, start_ammo_rockets);
- SetResource(this, RES_CELLS, start_ammo_cells);
- SetResource(this, RES_PLASMA, start_ammo_plasma);
- SetResource(this, RES_FUEL, start_ammo_fuel);
- SetResource(this, RES_HEALTH, start_health);
- SetResource(this, RES_ARMOR, start_armorvalue);
- STAT(WEAPONS, this) = start_weapons;
- if (MUTATOR_CALLHOOK(ForbidRandomStartWeapons, this) == false)
- {
- GiveRandomWeapons(this, random_start_weapons_count,
- autocvar_g_random_start_weapons, random_start_ammo);
- }
- }
+ ResetPlayerResources(this);
+
SetSpectatee_status(this, 0);
PS(this).dual_weapons = '0 0 0';
} else if (IS_PLAYER(this)) {
PutPlayerInServer(this);
}
-
+ // send team names
+ if(teamplay && IS_REAL_CLIENT(this))
+ send_TeamNames(MSG_ONE, this);
bot_relinkplayerlist();
}
WriteByte(channel, this.cnt * 255.0); // g_balance_damagepush_speedfactor
WriteByte(channel, serverflags);
WriteCoord(channel, autocvar_g_trueaim_minrange);
+
+ // z411 send full hostname
+ WriteString(channel, (autocvar_hostname_full != "" ? autocvar_hostname_full : autocvar_hostname));
+ WriteString(channel, autocvar_sv_motd_permanent);
+
+ // z411 send client countdown type
+ WriteByte(channel, autocvar_sv_timer_countdown);
}
void ClientInit_CheckUpdate(entity this)
else
CS(this).allowed_timeouts = autocvar_sv_timeout_number;
- if (autocvar_sv_eventlog)
+ if (autocvar_sv_eventlog) {
GameLogEcho(strcat(":join:", ftos(this.playerid), ":", ftos(etof(this)), ":", ((IS_REAL_CLIENT(this)) ? GameLog_ProcessIP(this.netaddress) : "bot"), ":", playername(this.netname, this.team, false)));
+
+ /* z411 for RJZ */
+ if(autocvar_rjz_ranks) GameLogEcho(strcat(":idfp:", ftos(etof(this)), ":", this.crypto_idfp));
+ }
CS(this).just_joined = true; // stop spamming the eventlog with additional lines when the client connects
+ this.wants_join = 0;
stuffcmd(this, clientstuff, "\n");
stuffcmd(this, "cl_particles_reloadeffects\n"); // TODO do we still need this?
if (player_count == 0)
localcmd("\nsv_hook_lastleave\n");
+
+ if (teamplay && autocvar_g_balance_teams_remove)
+ TeamBalance_RemoveExcessPlayers(NULL);
}
void ChatBubbleThink(entity this)
}
}
-.bool team_selected;
bool ShowTeamSelection(entity this)
{
if (!teamplay || autocvar_g_campaign || autocvar_g_balance_teams || this.team_selected || (CS(this).wasplayer && autocvar_g_changeteam_banned) || Player_HasRealForcedTeam(this))
return false;
+ if (SpectatorWantsJoin(this))
+ return false;
if (frametime) // once per frame is more than enough
stuffcmd(this, "_scoreboard_team_selection 1\n");
return true;
}
+
void Join(entity this)
{
if (autocvar_g_campaign && !campaign_bots_may_start && !game_stopped && time >= game_starttime)
TRANSMUTE(Player, this);
+ entity queued_join = SpectatorWantsJoin(this);
+ if(queued_join)
+ this.team_selected = false; // Don't let this player select team
+
if(!this.team_selected)
- if(autocvar_g_campaign || autocvar_g_balance_teams)
+ if(autocvar_g_campaign || autocvar_g_balance_teams || queued_join)
TeamBalance_JoinBestTeam(this);
if(autocvar_g_campaign)
if(IS_PLAYER(this))
if(teamplay && this.team != -1)
{
+ if(this.wants_join)
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_JOIN_PLAY_TEAM), this.netname);
}
else
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_JOIN_PLAY, this.netname);
this.team_selected = false;
+
+ // z411
+ // send constant ready notification
+ if(warmup_stage)
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_MISSING_READY);
+
+ this.wants_join = 0;
+
+ if(queued_join)
+ Join(queued_join);
}
int GetPlayerLimit()
return free_slots;
}
+bool queuePlayer(entity this)
+{
+ if(IS_QUEUE_NEEDED(this) && !SpectatorWantsJoin(this))
+ {
+ if(autocvar_g_balance_teams)
+ TeamBalance_JoinBestTeam(this);
+ return true;
+ }
+ return false;
+}
+
bool joinAllowed(entity this)
{
if (CS(this).version_mismatch) return false;
if (teamplay && lockteams) return false;
if (MUTATOR_CALLHOOK(ForbidSpawn, this)) return false;
if (ShowTeamSelection(this)) return false;
+ if (this.wants_join) return false;
+ if (queuePlayer(this)) return false;
return true;
}
return false;
}
- if (timeout_status == TIMEOUT_ACTIVE) {
- // don't allow the player to turn around while game is paused
+ if (game_timeout) {
+ // don't allow the player to turn around while game is paused
// FIXME turn this into CSQC stuff
this.v_angle = this.lastV_angle;
this.angles = this.lastV_angle;
this.fixangle = true;
+ return false;
}
if (frametime) player_powerups(this);
{
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_MOVETOSPEC_IDLING, this.netname, maxidle_time);
PutObserverInServer(this, true, true);
+ if(autocvar_g_balance_teams_remove)
+ TeamBalance_RemoveExcessPlayers(this);
}
else
{
string autocvar_hostname;
int autocvar_spawn_debug;
string autocvar_sv_motd;
+string autocvar_sv_motd_permanent;
int autocvar_sv_name_maxlength = 64;
string autocvar_sv_quickmenu_file;
bool autocvar_sv_servermodelsonly;
bool autocvar_sv_teamnagger;
float autocvar_sv_player_scale;
+// z411
+string autocvar_hostname_full;
+string autocvar_g_teamnames_red;
+string autocvar_g_teamnames_blue;
+string autocvar_g_teamnames_yellow;
+string autocvar_g_teamnames_pink;
+
+void send_TeamNames(int channel, entity to);
+
+// Medals
+float autocvar_g_medals_excellent_time = 2;
+
+// Timer
+int autocvar_sv_timer_countdown = 1; // 0 = disabled, 1 = enabled, 2 = spect only
+
// WEAPONTODO
.string weaponorder_byimpulse;
.int spectatee_status;
.bool zoomstate;
+.bool team_selected;
.bool just_joined;
+.bool wants_join;
.int pressedkeys;
ATTRIB(Client, colormap, int, this.colormap);
ATTRIB(Client, team, int, this.team);
ATTRIB(Client, clientcolors, int, this.clientcolors);
+ ATTRIB(Client, countrycode, int, this.countrycode);
+ ATTRIB(Client, rank, string, this.rank);
/** Client IP */
ATTRIB(Client, netaddress, string, this.netaddress);
ATTRIB(Client, playermodel, string, this.playermodel);
ATTRIB(Client, teamkill_soundsource, entity, this.teamkill_soundsource);
ATTRIB(Client, usekeypressed, bool, this.usekeypressed);
ATTRIB(Client, jointime, float, this.jointime);
+ ATTRIB(Client, wants_join, bool, this.wants_join);
ATTRIB(Client, spectatortime, float, this.spectatortime);
ATTRIB(Client, startplaytime, float, this.startplaytime);
ATTRIB(Client, version_nagtime, float, this.version_nagtime);
ATTRIB(Client, cvar_cl_pokenade_type, string, this.cvar_cl_pokenade_type);
ATTRIB(Client, cvar_cl_spawn_near_teammate, bool, this.cvar_cl_spawn_near_teammate);
ATTRIB(Client, cvar_cl_gunalign, int, this.cvar_cl_gunalign);
+ ATTRIB(Client, cvar_cl_chat_sounds, bool, this.cvar_cl_chat_sounds);
ATTRIB(Client, cvar_cl_handicap, float, this.cvar_cl_handicap);
ATTRIB(Client, cvar_cl_clippedspectating, bool, this.cvar_cl_clippedspectating);
ATTRIB(Client, cvar_cl_autoscreenshot, int, this.cvar_cl_autoscreenshot);
#define IS_INDEPENDENT_PLAYER(e) ((e).solid == SOLID_TRIGGER)
#define MAKE_INDEPENDENT_PLAYER(e) (((e).solid = SOLID_TRIGGER), ((e).frags = FRAGS_PLAYER_OUT_OF_GAME))
+.float lastkill;
+.int countrycode;
.int killcount;
+.string rank; // RJZ
//flood fields
.float nickspamtime; // time of last nick change
void FixPlayermodel(entity player);
-void GiveWarmupResources(entity this);
+void ResetPlayerResources(entity this);
void ClientInit_misc(entity this);
#define SPECTATE_COPYFIELD(fld) SPECTATE_COPY() { this.(fld) = spectatee.(fld); }
const int MAX_SPECTATORS = 7;
+
+float _medal_times;
+#define Give_Medal(entity,medalname) \
+ _medal_times = GameRules_scoring_add(entity, MEDAL_##medalname, 1); \
+ Send_Notification(NOTIF_ONE, entity, MSG_MEDAL, MEDAL_##medalname, _medal_times);
+
{
if (blockSpectators)
Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
- PutObserverInServer(this, false, true);
+
+ if (this.wants_join)
+ SetPlayerTeam(this, -1, TEAM_CHANGE_SPECTATOR);
+ else
+ {
+ PutObserverInServer(this, false, true);
+ if(autocvar_g_balance_teams_remove)
+ TeamBalance_RemoveExcessPlayers(this);
+ }
}
else
{
}
}
+void BanCommand_kickkick(int request, int argc, string command)
+{
+ switch (request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ if (argc >= 2)
+ {
+ entity client = GetIndexedEntity(argc, 1);
+ float accepted = VerifyKickableEntity(client);
+ float reason_arg;
+ string reason;
+
+ if (accepted > 0)
+ {
+ reason_arg = next_token;
+
+ GET_BAN_REASON(reason, "No reason provided");
+
+ Ban_KickClient(client, reason);
+
+ return;
+ }
+ else
+ {
+ LOG_INFO("kick: ", GetClientErrorString(accepted, argv(1)), ".");
+ }
+ }
+ }
+
+ default:
+ LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_HELP("Usage:^3 sv_cmd kickkick <client> [<reason>]");
+ LOG_HELP(" <client> is the entity number or name of the player to kick,");
+ LOG_HELP(" and <reason> is the string to label the ban with as reason for kicking.");
+ LOG_HELP("See also: ^2kick^7");
+ return;
+ }
+ }
+}
+
void BanCommand_kickban(int request, int argc, string command)
{
switch (request)
#define BAN_COMMANDS(request, arguments, command) \
BAN_COMMAND("ban", BanCommand_ban(request, arguments, command), "Ban an IP address or a range of addresses (like 1.2.3)") \
BAN_COMMAND("banlist", BanCommand_banlist(request), "List all existing bans") \
+ BAN_COMMAND("kickkick", BanCommand_kickkick(request, arguments, command), "Disconnect a client") \
BAN_COMMAND("kickban", BanCommand_kickban(request, arguments, command), "Disconnect a client and ban it at the same time") \
BAN_COMMAND("mute", BanCommand_mute(request, arguments, command), "Disallow a client from talking by muting them") \
BAN_COMMAND("playban", BanCommand_playban(request, arguments, command), "Force to spectate a client permanently") \
{
case CMD_REQUEST_COMMAND:
{
- if (!game_stopped && IS_CLIENT(caller) && !IS_PLAYER(caller))
+ if (!game_stopped && !game_timeout && IS_CLIENT(caller) && !IS_PLAYER(caller))
{
if (joinAllowed(caller))
Join(caller);
else
{
caller.ready = true;
- bprint(playername(caller.netname, caller.team, false), "^2 is ready\n");
+ bprint("\{1}", playername(caller.netname, caller.team, false), "^2 is ready\n");
}
ReadyCount();
}
{
case CMD_REQUEST_COMMAND:
{
- if (!intermission_running && IS_CLIENT(caller))
+ if (!intermission_running && IS_CLIENT(caller) && !game_timeout)
{
if(argv(1) != "")
{
if (mutator_returnvalue == MUT_SPECCMD_RETURN) return;
- if ((IS_PLAYER(caller) || mutator_returnvalue == MUT_SPECCMD_FORCE))
+ if ((IS_PLAYER(caller) || mutator_returnvalue == MUT_SPECCMD_FORCE || caller.wants_join))
if (autocvar_sv_spectate == 1)
ClientKill_TeamChange(caller, -2); // observe
}
}
}
+void ClientCommand_sounds(entity caller, int request)
+{
+ switch (request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ sprint(caller, strcat("Available sounds: \n\n", autocvar_sv_chat_sounds_list, "\n"));
+ return; // never fall through to usage
+ }
+
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ sprint(caller, "\nUsage:^3 cmd sounds\n");
+ return;
+ }
+ }
+}
+
void ClientCommand_suggestmap(entity caller, int request, int argc)
{
switch (request)
CLIENT_COMMAND("selfstuff", ClientCommand_selfstuff(ent, request, command), "Stuffcmd a command to your own client") \
CLIENT_COMMAND("sentcvar", ClientCommand_sentcvar(ent, request, arguments), "New system for sending a client cvar to the server") \
CLIENT_COMMAND("spectate", ClientCommand_spectate(ent, request), "Become an observer") \
+ CLIENT_COMMAND("sounds", ClientCommand_sounds(ent, request), "Get list of commsnds") \
CLIENT_COMMAND("suggestmap", ClientCommand_suggestmap(ent, request, arguments), "Suggest a map to the mapvote at match end") \
CLIENT_COMMAND("tell", ClientCommand_tell(ent, request, arguments, command), "Send a message directly to a player") \
CLIENT_COMMAND("voice", ClientCommand_voice(ent, request, arguments, command), "Send voice message via sound") \
#include <server/client.qh>
#include <server/command/common.qh>
#include <server/mutators/_mod.qh>
+#include <server/round_handler.qh>
#include <server/scores.qh>
#include <server/world.qh>
if (timeout_time == autocvar_sv_timeout_resumetime) // play a warning sound when only <sv_timeout_resumetime> seconds are left
Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_PREPARE);
- this.nextthink = time + TIMEOUT_SLOWMO_VALUE; // think again in one second
+ //this.nextthink = time + TIMEOUT_SLOWMO_VALUE; // think again in one second
+ this.nextthink = time + 1;
timeout_time -= 1; // decrease the time counter
}
+ else if (timeout_time == -1) // infinite timer
+ {
+ Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_TIMEOUT_ONGOING);
+ this.nextthink = time + TIMEOUT_SLOWMO_VALUE;
+ }
else // time to end the timeout
{
Kill_Notification(NOTIF_ALL, NULL, MSG_CENTER, CPID_TIMEIN);
timeout_status = TIMEOUT_INACTIVE;
+ float total_time = time - timeout_last;
// reset the slowmo value back to normal
- cvar_set("slowmo", ftos(orig_slowmo));
+ // z411 TODO
+ //cvar_set("slowmo", ftos(orig_slowmo));
+
+ // Disable timeout and fix times
+ game_timeout = false;
+ timeout_total_time += total_time;
+ game_starttime += total_time;
+ if(round_starttime)
+ round_starttime += total_time;
+ if(round_handler && round_handler_GetEndTime() > 0)
+ round_handler.round_endtime += total_time;
+
+ LOG_INFOF("Timeout lasted %d secs", total_time);
+ timeout_last = 0;
// unlock the view for players so they can move around again
FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it), {
timeout_status = TIMEOUT_ACTIVE;
// set the slowmo value to the timeout default slowmo value
- cvar_set("slowmo", ftos(TIMEOUT_SLOWMO_VALUE));
+ //cvar_set("slowmo", ftos(TIMEOUT_SLOWMO_VALUE));
+ game_timeout = true;
+ timeout_last = time;
+
+ // play timeout sound
+ sound(NULL, CH_INFO, SND_TIMEOUT, VOL_BASE, ATTN_NONE);
// reset all the flood variables
FOREACH_CLIENT(true, {
{
timeout_time = autocvar_sv_timeout_resumetime;
timeout_handler.nextthink = time; // timeout_handler has to take care of it immediately
- bprint(strcat("^1Attention: ^7", GetCallerName(caller), " resumed the game! Prepare for battle!\n"));
+ bprint(strcat("\{1}^1Attention: ^7", GetCallerName(caller), " resumed the game! Prepare for battle!\n"));
return;
}
{
if (caller) CS(caller).allowed_timeouts -= 1;
// write a bprint who started the timeout (and how many they have left)
- bprint(GetCallerName(caller), " ^7called a timeout", (caller ? strcat(" (", ftos(CS(caller).allowed_timeouts), " timeout(s) left)") : ""), "!\n");
+ bprint("\{1}", GetCallerName(caller), " ^7called a timeout", (caller ? strcat(" (", ftos(CS(caller).allowed_timeouts), " timeout(s) left)") : ""), "!\n");
timeout_status = TIMEOUT_LEADTIME;
timeout_caller = caller;
timeout_handler = new(timeout_handler);
setthink(timeout_handler, timeout_handler_think);
timeout_handler.nextthink = time; // always let the entity think asap
-
+
Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_TIMEOUT);
}
}
}
}
+void GameCommand_teamname(int request, int argc)
+{
+ switch (request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ if (argv(1) == "")
+ {
+ return;
+ }
+ if (!teamplay)
+ {
+ LOG_INFO("selectteam can only be used in teamgames");
+ return;
+ }
+
+ switch (argv(1))
+ {
+ case "red":
+ case "blue":
+ case "yellow":
+ case "pink":
+ {
+ int tm = Team_ColorToTeam(argv(1));
+ if(argv(2) != "") {
+ cvar_set(strcat("g_teamnames_", argv(1)), argv(2));
+ bprintf("\{1}%s%s^7 team is now known as %s^7\n", Team_ColorCode(tm), Team_ColorName(tm), argv(2));
+ } else {
+ cvar_set(strcat("g_teamnames_", argv(1)), "");
+ bprintf("\{1}%s%s^7 team now doesn't have a team name\n", Team_ColorCode(tm), Team_ColorName(tm), argv(2));
+ }
+
+ break;
+ }
+ default:
+ {
+ return;
+ }
+ }
+
+ send_TeamNames(MSG_BROADCAST, NULL);
+ return;
+ }
+
+ default:
+ LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_HELP("Usage:^3 sv_cmd sendteams");
+ LOG_HELP(" No arguments required.");
+ return;
+ }
+ }
+}
+
void GameCommand_allready(int request)
{
switch (request)
}
}
+void GameCommand_ircmsg(int request, int argc, string command)
+{
+ /* IRCSay from the SMB Modpack */
+ switch (request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ string msgstr = substring(command, strlen(argv(0))+1, strlen(command));
+
+ if(msgstr == "")
+ return;
+
+ string prefix;
+ if(substring(msgstr, 0, 3) == "^4*") // actions
+ prefix = "\{3}";
+ else
+ prefix = "\{1}";
+
+ msgstr = strcat(prefix, strreplace("\n", " ", msgstr), "\n"); // newlines only are good for centerprint
+
+ FOREACH_CLIENTSLOT(true,
+ {
+ if(!intermission_running)
+ if((autocvar_g_chat_nospectators == 1) || (autocvar_g_chat_nospectators == 2 && !(warmup_stage || game_stopped)))
+ if(IS_PLAYER(it))
+ continue;
+ if(IS_REAL_CLIENT(it))
+ sprint(it, msgstr);
+ });
+ }
+
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_HELP("Usage:^3 sv_cmd ircmsg message");
+ return;
+ }
+ }
+}
+
void GameCommand_lockteams(int request)
{
switch (request)
if (teamplay)
{
lockteams = 1;
- bprint("^1The teams are now locked.\n");
+ bprint("\{1}^1The teams are now locked.\n");
}
else
{
}
}
+void GameCommand_setflag(int request, int argc)
+{
+ switch (request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ entity client;
+ float accepted;
+
+ client = GetFilteredEntity(argv(1));
+ accepted = VerifyClientEntity(client, false, false);
+
+ if (accepted <= 0)
+ {
+ LOG_INFO("^1ERROR^7: Couldn't set country flag");
+ LOG_HELP("Usage:^3 sv_cmd setflag #client_id countrycode[0-249]");
+ return;
+ }
+
+ client.countrycode = stof(argv(2));
+ LOG_INFO("^2SUCCESS^7: Country flag set!");
+ return;
+ }
+ default:
+ LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_HELP("Usage:^3 sv_cmd setflag #client_id countrycode[0-249]");
+ return;
+ }
+ }
+}
+
+void GameCommand_setrank(int request, int argc)
+{
+ switch (request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ entity client;
+ float accepted;
+
+ client = GetFilteredEntity(argv(1));
+ accepted = VerifyClientEntity(client, false, false);
+
+ if (accepted <= 0)
+ {
+ LOG_INFO("^1ERROR^7: Couldn't set player rank");
+ LOG_HELP("Usage:^3 sv_cmd setrank #client_id rank");
+ return;
+ }
+
+ client.rank = strzone(argv(2));
+ LOG_INFO("^2SUCCESS^7: Player rank set!");
+ return;
+ }
+ default:
+ LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_HELP("Usage:^3 sv_cmd setrank #client_id #rank");
+ return;
+ }
+ }
+}
+
void GameCommand_moveplayer(int request, int argc)
{
switch (request)
}
}
+void GameCommand_printplayer(int request, int argc)
+{
+ switch (request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ entity player = GetIndexedEntity(argc, 1);
+ if (player.playerid)
+ {
+ GameLogEcho(strcat(
+ strcat(
+ ":playerinfo:", ftos(player.playerid),
+ ":", ftos(etof(player)),
+ ":", ftos(CS_CVAR(player).cvar_cl_allow_uidtracking),
+ ":", ftos(CS_CVAR(player).cvar_cl_allow_uid2name)),
+ strcat(
+ ":", ftos(CS_CVAR(player).cvar_cl_allow_uidranking),
+ ":", ((IS_REAL_CLIENT(player)) ? GameLog_ProcessIP(player.netaddress) : "bot"),
+ ":", player.crypto_idfp,
+ ":", playername(player.netname, player.team, false))));
+ }
+ return;
+ }
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_HELP("Usage:^3 sv_cmd printplayer <player_entity_id>");
+ return;
+ }
+ }
+}
+
void GameCommand_printstats(int request)
{
switch (request)
if (teamplay)
{
lockteams = 0;
- bprint("^1The teams are now unlocked.\n");
+ bprint("\{1}^1The teams are now unlocked.\n");
}
else
{
SERVER_COMMAND(gametype, "Simple command to change the active gametype") { GameCommand_gametype(request, arguments); }
SERVER_COMMAND(gettaginfo, "Get specific information about a weapon model") { GameCommand_gettaginfo(request, arguments); }
SERVER_COMMAND(gotomap, "Simple command to switch to another map") { GameCommand_gotomap(request, arguments); }
+SERVER_COMMAND(ircmsg, "Chat message to be sent by IRC bots") { GameCommand_ircmsg(request, arguments, command); }
SERVER_COMMAND(lockteams, "Disable the ability for players to switch or enter teams") { GameCommand_lockteams(request); }
SERVER_COMMAND(make_mapinfo, "Automatically rebuild mapinfo files") { GameCommand_make_mapinfo(request); }
SERVER_COMMAND(moveplayer, "Change the team/status of a player") { GameCommand_moveplayer(request, arguments); }
SERVER_COMMAND(nospectators, "Automatically remove spectators from a match") { GameCommand_nospectators(request); }
+SERVER_COMMAND(printplayer, "Print information about a player") { GameCommand_printplayer(request, arguments); }
SERVER_COMMAND(printstats, "Dump eventlog player stats and other score information") { GameCommand_printstats(request); }
SERVER_COMMAND(radarmap, "Generate a radar image of the map") { GameCommand_radarmap(request, arguments); }
SERVER_COMMAND(reducematchtime, "Decrease the timelimit value incrementally") { GameCommand_reducematchtime(request); }
SERVER_COMMAND(resetmatch, "Soft restart the game without changing teams; goes back to warmup if enabled") { GameCommand_resetmatch(request); }
SERVER_COMMAND(setbots, "Adjust how many bots are in the match") { GameCommand_setbots(request, arguments); }
+SERVER_COMMAND(setflag, "Set client flag") { GameCommand_setflag(request, arguments); }
+SERVER_COMMAND(setrank, "Set client rank") { GameCommand_setrank(request, arguments); }
SERVER_COMMAND(shuffleteams, "Randomly move players to different teams") { GameCommand_shuffleteams(request); }
SERVER_COMMAND(stuffto, "Send a command to be executed on a client") { GameCommand_stuffto(request, arguments); }
+SERVER_COMMAND(teamname, "Set team name") { GameCommand_teamname(request, arguments); }
SERVER_COMMAND(trace, "Various debugging tools with tracing") { GameCommand_trace(request, arguments); }
SERVER_COMMAND(unlockteams, "Enable the ability for players to switch or enter teams") { GameCommand_unlockteams(request); }
SERVER_COMMAND(warp, "Choose different level in campaign") { GameCommand_warp(request, arguments); }
Nagger_VoteCountChanged();
// add up all the votes from each connected client
- FOREACH_CLIENT(IS_REAL_CLIENT(it) || autocvar_sv_vote_debug, {
+ FOREACH_CLIENT(IS_REAL_CLIENT(it) && IS_CLIENT(it), {
+ // z411
+ if(vote_target_type == VOTE_TARGET_TEAM && it.team != vote_caller.team) continue;
+ if(vote_target_type == VOTE_TARGET_SINGLE && it != vote_target) continue;
+
++vote_player_count;
if (IS_PLAYER(it) || INGAME(it)) ++vote_real_player_count;
switch (it.vote_selection)
if (round_handler_IsActive())
round_handler_Reset(game_starttime);
}
+
+ // for RJZ
+ if (autocvar_rjz_count_shards) {
+ total_shards = 0;
+ send_TotalShardsAll();
+ }
if (shuffleteams_on_reset_map)
{
if(!is_fake_round_start && !warmup_stage)
localcmd("\nsv_hook_warmupend\n");
- // reset the .ready status of all clients (including spectators and bots)
- FOREACH_CLIENT(true, { it.ready = false; });
+ // reset the .ready status of all players (also spectators)
+ FOREACH_CLIENT(IS_REAL_CLIENT(it), {
+ it.ready = false;
+ Kill_Notification(NOTIF_ONE_ONLY, it, MSG_CENTER, CPID_MISSING_READY);
+ });
readycount = 0;
Nagger_ReadyCounted(); // NOTE: this causes a resend of that entity, and will also turn off warmup state on the client
FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it), { CS(it).allowed_timeouts = autocvar_sv_timeout_number; });
}
+ round_handler_Activate(!warmup_stage);
if (!sv_ready_restart_after_countdown || warmup_stage)
reset_map(is_fake_round_start);
game_starttime = time;
Send_Notification(NOTIF_ALL, NULL, MSG_MULTI, COUNTDOWN_STOP, minplayers);
if (!sv_ready_restart_after_countdown) // if we ran reset_map() at start of countdown
- FOREACH_CLIENT(IS_PLAYER(it), { GiveWarmupResources(it); });
+ FOREACH_CLIENT(IS_PLAYER(it), { ResetPlayerResources(it); });
}
if (warmup_limit > 0)
warmup_limit = -1;
case MUT_VOTEPARSE_UNACCEPTABLE: { return 0; }
}
+ vote_target_type = VOTE_TARGET_ALL;
+
switch (first_command) // now go through and parse the proper commands to adjust as needed.
{
case "movetoauto":
if (first_command == "kickban")
command_arguments = strcat(ftos(autocvar_g_ban_default_bantime), " ", ftos(autocvar_g_ban_default_masksize), " ~");
- vote_parsed_command = strcat(first_command, " # ", ftos(etof(victim)), " ", command_arguments);
+ if (first_command == "kick") // z411 : Use our kick implementation - kind of hacky...
+ vote_parsed_command = strcat("defer 2 \"sv_cmd kickkick # ", ftos(etof(victim)), " ", command_arguments, "\"");
+ else
+ vote_parsed_command = strcat("defer 2 \"", first_command, " # ", ftos(etof(victim)), " ", command_arguments, "\"");
+
vote_parsed_display = sprintf("^1%s #%d ^7%s^1 %s", first_command, etof(victim), victim.netname, reason);
}
else
{
vote_command = ValidateMap(argv(startpos + 1), caller);
if (!vote_command) return -1;
- vote_parsed_command = strcat("gotomap ", vote_command);
- vote_parsed_display = strzone(strcat("^1", vote_parsed_command));
+ vote_parsed_command = strcat("defer 2 \"gotomap ", vote_command, "\"");
+ vote_parsed_display = strzone(strcat("^1gotomap ", vote_command));
break;
}
+
+ // z411 team calls
+ case "teamname":
+ {
+ if (teamplay && Team_IsValidTeam(caller.team)) {
+ vote_target_type = VOTE_TARGET_TEAM;
+
+ string tmname = strtolower(Static_Team_ColorName(caller.team));
+ string newname = argv(startpos + 1);
+
+ vote_parsed_command = strcat(first_command, " ", tmname, " \"", newname, "\"");
+ vote_parsed_display = strzone(strcat("^3(Team) ^1", first_command, " ^2", newname));
+ } else { print_to(caller, "vcall: Not in a team\n"); return 0; }
+
+ break;
+ }
// TODO: replicate the old behaviour of being able to vote for maps from different modes on multimode servers (possibly support it in gotomap too)
// maybe fallback instead of aborting if map name is invalid?
break;
}
- case "restart":
+ case "gg":
+ case "shuffleteams":
+ case "endmatch":
{
// add a delay so that vote result can be seen and announcer can be heard
// if the vote is accepted
- vote_parsed_command = strcat("defer 1 ", vote_command);
+ vote_parsed_command = strcat("defer 2 ", vote_command);
+ vote_parsed_display = strzone(strcat("^1", vote_command));
+
+ break;
+ }
+
+ case "reset":
+ case "restart": // re-direct all match restarting to resetmatch
+ vote_command = "resetmatch"; // fall-through
+ case "resetmatch":
+ {
+ vote_parsed_command = strcat("defer 2 ", vote_command);
vote_parsed_display = strzone(strcat("^1", vote_command));
break;
return -1;
}
- vote_parsed_command = vote_command;
+ vote_parsed_command = strcat("defer 2 ", vote_command);
vote_parsed_display = strzone(strcat("^1", vote_command));
break;
}
const float VOTE_NORMAL = 1;
const float VOTE_MASTER = 2;
+// z411 vote targets
+const float VOTE_TARGET_ALL = 0;
+const float VOTE_TARGET_TEAM = 1;
+const float VOTE_TARGET_SINGLE = 2;
+
// global vote information declarations
entity vote_caller; // original caller of the current vote
string vote_caller_name; // name of the vote caller
int vote_reject_count; // same as above, but rejected
int vote_abstain_count; // same as above, but abstained
int vote_needed_overall; // total amount of players NEEDED for a vote to pass (based on sv_vote_majority_factor)
+float vote_target_type; // z411
+entity vote_target; // z411
.bool vote_master; // flag for if the player has vote master privileges
.float vote_waittime; // flag for how long the player must wait before they can vote again
.int vote_selection; // flag for which vote selection the player has made (See VOTE_SELECT_*)
void Obituary_SpecialDeath(
entity notif_target,
+ entity attacker,
float murder,
int deathtype,
string s1, string s2, string s3,
f1, f2, f3, 0
);
}
+
+ if(deathtype == DEATH_TELEFRAG.m_id) {
+ Give_Medal(attacker, TELEFRAG);
+ }
}
float Obituary_WeaponDeath(
entity notif_target,
+ entity attacker,
float murder,
int deathtype,
string s1, string s2, string s3,
s1, s2, s3, "",
f1, f2, 0, 0
);
+
+ // z411 special medals
+ if(attacker) {
+ switch(death_message) {
+ case WEAPON_SHOTGUN_MURDER_SLAP:
+ if(!cvar("g_melee_only")) { // don't spam humiliation if we're in melee_only mode
+ Give_Medal(attacker, HUMILIATION);
+ }
+ break;
+ case WEAPON_ELECTRO_MURDER_COMBO:
+ Give_Medal(attacker, ELECTROBITCH);
+ break;
+ }
+ }
}
else
{
{
if(deathtype == DEATH_TEAMCHANGE.m_id || deathtype == DEATH_AUTOTEAMCHANGE.m_id)
{
- Obituary_SpecialDeath(targ, false, deathtype, targ.netname, deathlocation, "", targ.team, 0, 0);
+ Obituary_SpecialDeath(targ, NULL, false, deathtype, targ.netname, deathlocation, "", targ.team, 0, 0);
}
else
{
{
case DEATH_MIRRORDAMAGE:
{
- Obituary_SpecialDeath(targ, false, deathtype, targ.netname, deathlocation, "", CS(targ).killcount, 0, 0);
+ Obituary_SpecialDeath(targ, NULL, false, deathtype, targ.netname, deathlocation, "", CS(targ).killcount, 0, 0);
break;
}
case DEATH_HURTTRIGGER:
- Obituary_SpecialDeath(targ, false, deathtype, targ.netname, inflictor.message, deathlocation, CS(targ).killcount, 0, 0);
+ Obituary_SpecialDeath(targ, NULL, false, deathtype, targ.netname, inflictor.message, deathlocation, CS(targ).killcount, 0, 0);
break;
default:
{
- Obituary_SpecialDeath(targ, false, deathtype, targ.netname, deathlocation, "", CS(targ).killcount, 0, 0);
+ Obituary_SpecialDeath(targ, NULL, false, deathtype, targ.netname, deathlocation, "", CS(targ).killcount, 0, 0);
break;
}
}
}
}
- else if (!Obituary_WeaponDeath(targ, false, deathtype, targ.netname, deathlocation, "", CS(targ).killcount, 0))
+ else if (!Obituary_WeaponDeath(targ, NULL, false, deathtype, targ.netname, deathlocation, "", CS(targ).killcount, 0))
{
backtrace("SUICIDE: what the hell happened here?\n");
return;
}
LogDeath("suicide", deathtype, targ, targ);
+ Send_Notification(NOTIF_ONE, targ, MSG_ANNCE, ANNCE_SUICIDE);
if(deathtype != DEATH_AUTOTEAMCHANGE.m_id) // special case: don't negate frags if auto switched
GiveFrags(attacker, targ, -1, deathtype, weaponentity);
}
Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_TEAMKILL_FRAG, targ.netname);
Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_TEAMKILL_FRAGGED, attacker_name);
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(targ.team, INFO_DEATH_TEAMKILL), targ.netname, attacker_name, deathlocation, CS(targ).killcount);
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(targ.team, INFO_DEATH_TEAMKILL),
+ playername(targ.netname, targ.team, true), playername(attacker_name, attacker.team, true),
+ deathlocation, CS(targ).killcount);
// In this case, the death message will ALWAYS be "foo was betrayed by bar"
// No need for specific death/weapon messages...
CS(attacker).killcount = CS(attacker).killcount + 1;
attacker.killsound += 1;
-
+
// TODO: improve SPREE_ITEM and KILL_SPREE_LIST
// these 2 macros are spread over multiple files
#define SPREE_ITEM(counta,countb,center,normal,gentle) \
case counta: \
- Send_Notification(NOTIF_ONE, attacker, MSG_ANNCE, ANNCE_KILLSTREAK_##countb); \
+ Give_Medal(attacker, KILLSTREAK_##countb); \
if (!warmup_stage) \
PlayerStats_GameReport_Event_Player(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_##counta, 1); \
break;
{
checkrules_firstblood = true;
notif_firstblood = true; // modify the current messages so that they too show firstblood information
+ Give_Medal(attacker, FIRSTBLOOD);
PlayerStats_GameReport_Event_Player(attacker, PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD, 1);
PlayerStats_GameReport_Event_Player(targ, PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM, 1);
kill_count_to_attacker = CS(attacker).killcount;
kill_count_to_target = 0;
}
+
+ // Excellent check
+ if(attacker.lastkill && attacker.lastkill > time - autocvar_g_medals_excellent_time) {
+ Give_Medal(attacker, EXCELLENT);
+ }
+ attacker.lastkill = time;
if(targ.istypefrag)
{
if(deathtype == DEATH_BUFF.m_id)
f3 = buff_FirstFromFlags(attacker).m_id;
- if (!Obituary_WeaponDeath(targ, true, deathtype, targ.netname, attacker_name, deathlocation, CS(targ).killcount, kill_count_to_attacker))
- Obituary_SpecialDeath(targ, true, deathtype, targ.netname, attacker_name, deathlocation, CS(targ).killcount, kill_count_to_attacker, f3);
+ if (!Obituary_WeaponDeath(targ, attacker, true, deathtype, playername(targ.netname, targ.team, true), playername(attacker_name, attacker.team, true), deathlocation, CS(targ).killcount, kill_count_to_attacker))
+ Obituary_SpecialDeath(targ, attacker, true, deathtype, playername(targ.netname, targ.team, true), playername(attacker_name, attacker.team, true), deathlocation, CS(targ).killcount, kill_count_to_attacker, f3);
}
}
// and there will be a REAL DEATH_VOID implementation which mappers will use.
case DEATH_HURTTRIGGER:
{
- Obituary_SpecialDeath(targ, false, deathtype,
- targ.netname,
+ Obituary_SpecialDeath(targ, NULL, false, deathtype,
+ playername(targ.netname, targ.team, true),
inflictor.message,
deathlocation,
CS(targ).killcount,
case DEATH_CUSTOM:
{
- Obituary_SpecialDeath(targ, false, deathtype,
- targ.netname,
+ Obituary_SpecialDeath(targ, NULL, false, deathtype,
+ playername(targ.netname, targ.team, true),
((strstrofs(deathmessage, "%", 0) < 0) ? strcat("%s ", deathmessage) : deathmessage),
deathlocation,
CS(targ).killcount,
default:
{
- Obituary_SpecialDeath(targ, false, deathtype, targ.netname, deathlocation, "", CS(targ).killcount, 0, 0);
+ Obituary_SpecialDeath(targ, NULL, false, deathtype, playername(targ.netname, targ.team, true), deathlocation, "", CS(targ).killcount, 0, 0);
break;
}
}
LogDeath("accident", deathtype, targ, targ);
+ Send_Notification(NOTIF_ONE, targ, MSG_ANNCE, ANNCE_ACCIDENT);
GiveFrags(targ, targ, -1, deathtype, weaponentity);
if(GameRules_scoring_add(targ, SCORE, 0) == -5)
.float spawnshieldtime;
.int totalfrags;
+.float lastkill;
.bool canteamdamage;
void Obituary_SpecialDeath(
entity notif_target,
+ entity attacker,
float murder,
int deathtype,
string s1, string s2, string s3,
float w_deathtype;
float Obituary_WeaponDeath(
entity notif_target,
+ entity target,
float murder,
int deathtype,
string s1, string s2, string s3,
#include <common/weapons/_all.qh>
#include <server/command/banning.qh>
#include <server/main.qh>
+#include <common/notifications/all.qh>
/*
* Protocol of online ban list:
return true;
}
+void Ban_KickClient(entity client, string reason)
+{
+ sprint(client, strcat("Kicked: ", reason, "\n"));
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_KICK, client.netname);
+ dropclient(client);
+}
+
void Ban_KickBanClient(entity client, float bantime, float masksize, string reason)
{
string ip, id;
if(!Ban_GetClientIP(client))
{
sprint(client, strcat("Kickbanned: ", reason, "\n"));
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_KICK, client.netname);
dropclient(client);
return;
}
float BanCommand(string command);
float Ban_Insert(string ip, float bantime, string reason, float dosync);
+void Ban_KickClient(entity client, string reason);
void Ban_KickBanClient(entity client, float bantime, float masksize, string reason);
void Ban_View();
float Ban_Delete(float i);
void Item_RespawnCountdown(entity this)
{
+ if(game_timeout) { this.nextthink = time + 1; return; }
+
if(this.item_respawncounter >= ITEM_RESPAWN_TICKS)
{
if(this.waypointsprite_attached)
else
{
this.nextthink = time + 1;
- this.item_respawncounter += 1;
+ this.item_respawncounter = floor((time - game_starttime) - (this.scheduledrespawntime - ITEM_RESPAWN_TICKS)) + 1;
+ //this.item_respawncounter += 1;
+ //LOG_INFOF("Respawncounter: %d", this.item_respawncounter);
+ if(this.item_respawncounter < 1) return;
+
if(this.item_respawncounter == 1)
{
do {
void Item_RespawnThink(entity this)
{
- this.nextthink = time;
+ this.nextthink = time + 1;
if(this.origin != this.oldorigin)
ItemUpdate(this);
-
- if(time >= this.wait)
+
+ if(!game_timeout && time - game_starttime >= this.wait)
Item_Respawn(this);
+
+ //LOG_INFOF("time until respawn %d", (this.wait) - (time - game_starttime));
}
void Item_ScheduleRespawnIn(entity e, float t)
if ((Item_ItemsTime_Allow(e.itemdef) || (STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS) || MUTATOR_CALLHOOK(Item_ScheduleRespawn, e, t)) && (t - ITEM_RESPAWN_TICKS) > 0)
{
setthink(e, Item_RespawnCountdown);
- e.nextthink = time + max(0, t - ITEM_RESPAWN_TICKS);
- e.scheduledrespawntime = e.nextthink + ITEM_RESPAWN_TICKS;
+ //e.nextthink = time - timeout_total_time + max(0, t - ITEM_RESPAWN_TICKS);
+ //e.scheduledrespawntime = e.nextthink + ITEM_RESPAWN_TICKS;
+ e.nextthink = time;
+ e.scheduledrespawntime = time - game_starttime + t;
e.item_respawncounter = 0;
+
if(Item_ItemsTime_Allow(e.itemdef) || (STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS))
{
t = Item_ItemsTime_UpdateTime(e, e.scheduledrespawntime);
{
setthink(e, Item_RespawnThink);
e.nextthink = time;
- e.scheduledrespawntime = time + t;
- e.wait = time + t;
+ e.scheduledrespawntime = time - game_starttime + t;
+ e.wait = time - game_starttime + t;
if(Item_ItemsTime_Allow(e.itemdef) || (STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS))
{
pickedup |= Item_GiveAmmoTo(item, player, RES_CELLS, g_pickup_cells_max);
pickedup |= Item_GiveAmmoTo(item, player, RES_PLASMA, g_pickup_plasma_max);
pickedup |= Item_GiveAmmoTo(item, player, RES_FUEL, g_pickup_fuel_max);
+
+ // for RJZ
+ if (autocvar_rjz_count_shards && !warmup_stage && item.itemdef == ITEM_ArmorSmall) {
+ total_shards++;
+ send_TotalShardsAll();
+ }
+
if (item.itemdef.instanceOfWeaponPickup)
{
WepSet w, wp;
MUTATOR_HOOKABLE(FixPlayermodel, EV_FixPlayermodel);
/** Return error to play frag remaining announcements */
+MUTATOR_HOOKABLE(Scores_AnnounceLeads, EV_NO_ARGS);
MUTATOR_HOOKABLE(Scores_CountFragsRemaining, EV_NO_ARGS);
#define EV_GrappleHookThink(i, o) \
#include <common/util.qh>
#include <server/campaign.qh>
#include <server/command/vote.qh>
+#include <server/weapons/accuracy.qh>
#include <server/scores.qh>
#include <server/world.qh>
void round_handler_Think(entity this)
{
+ if (!this.isactive) return;
+ if (game_timeout) { this.nextthink = time + 1; return; }
+
if (intermission_running)
{
round_handler_Reset(0);
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); });
rounds_played++;
if (this.roundStart) this.roundStart();
return;
if (this.canRoundEnd())
{
// schedule a new round
+ round_delaytime = time;
this.wait = true;
this.nextthink = time + this.delay;
}
return;
}
entity this = round_handler = new_pure(round_handler);
-
- setthink(this, round_handler_FirstThink);
+
this.canRoundStart = canRoundStart_func;
this.canRoundEnd = canRoundEnd_func;
this.roundStart = roundStart_func;
ScoreInfo_SetLabel_PlayerScore(SP_ROUNDS_PL, "rounds_pl", 0);
}
+void round_handler_Activate(bool active) {
+ if (round_handler) {
+ entity this = round_handler;
+
+ this.isactive = active;
+ if(active) {
+ setthink(this, round_handler_FirstThink);
+ this.nextthink = time;
+ } else {
+ round_starttime = -1;
+ }
+ }
+}
+
void round_handler_Reset(float next_think)
{
entity this = round_handler;
#pragma once
entity round_handler;
+.bool isactive;
.float delay; // stores delay from round end to countdown start
.float count; // stores initial number of the countdown
.bool wait; // it's set to true when round ends, to false when countdown starts
void round_handler_Init(float the_delay, float the_count, float the_round_timelimit);
void round_handler_Spawn(bool() canRoundStart_func, bool() canRoundEnd_func, void() roundStart_func);
void round_handler_Reset(float next_think);
+void round_handler_Activate(bool active);
void round_handler_Remove();
-#define round_handler_IsActive() (round_handler != NULL)
+#define round_handler_IsActive() (round_handler != NULL && round_handler.isactive)
#define round_handler_AwaitingNextRound() (round_handler.wait)
#define round_handler_CountdownRunning() (!round_handler.wait && round_handler.cnt)
#define round_handler_IsRoundStarted() (!round_handler.wait && !round_handler.cnt)
sk = CS(player).scorekeeper;
FOREACH(Scores, true, {
if(sk.(scores(it)) != 0)
- if(scores_label(it) != "")
- sk.SendFlags |= BIT(i % 16);
+ //if(scores_label(it) != "")
+ sk.SendFlags |= (2 ** (i % 16));
if(i != SP_ELO.m_id)
sk.(scores(it)) = 0;
});
if (!sk) continue;
FOREACH(Scores, true, {
if(sk.(scores(it)) != 0)
- if(scores_label(it) != "")
- sk.SendFlags |= BIT(i % 16);
+ //if(scores_label(it) != "")
+ sk.SendFlags |= (2 ** (i % 16));
if(i != SP_ELO.m_id)
sk.(scores(it)) = 0;
});
for(int j = 0; j < MAX_TEAMSCORE; ++j)
{
if(sk.(teamscores(j)) != 0)
- if(teamscores_label(j) != "")
- sk.SendFlags |= BIT(j);
+ //if(teamscores_label(j) != "")
+ sk.SendFlags |= (2 ** j);
sk.(teamscores(j)) = 0;
}
}
{
return s.(scores(scorefield));
}
- if(scores_label(scorefield) != "")
- s.SendFlags |= BIT(scorefield.m_id % 16);
+ //if(scores_label(scorefield) != "")
+ s.SendFlags |= (2 ** (scorefield.m_id % 16));
if(!warmup_stage)
PlayerStats_GameReport_Event_Player(s.owner, strcat(PLAYERSTATS_TOTAL, scores_label(scorefield)), score);
s.(scores(scorefield)) += score;
return result;
}
+bool Score_NewLeader()
+{
+ if(teamplay) {
+ if (WinningConditionHelper_winnerteam != WinningConditionHelper_winnerteam_last && (WinningConditionHelper_secondteam || WinningConditionHelper_equality))
+ {
+ WinningConditionHelper_winnerteam_last = WinningConditionHelper_winnerteam;
+ return true;
+ }
+ } else {
+ if (WinningConditionHelper_winner != WinningConditionHelper_winner_last && (WinningConditionHelper_second || WinningConditionHelper_equality))
+ {
+ WinningConditionHelper_winner_last = WinningConditionHelper_winner;
+ return true;
+ }
+ }
+ return false;
+}
+
void WinningConditionHelper(entity this)
{
float c;
WinningConditionHelper_equality = (PlayerScore_Compare(winnerscorekeeper, secondscorekeeper, false) == 0);
if(WinningConditionHelper_equality)
+ {
+ WinningConditionHelper_equality_one = WinningConditionHelper_winner;
+ WinningConditionHelper_equality_two = WinningConditionHelper_second;
WinningConditionHelper_winner = WinningConditionHelper_second = NULL;
+ }
+ else
+ {
+ WinningConditionHelper_equality_one = WinningConditionHelper_equality_two = NULL;
+ }
WinningConditionHelper_topscore = winnerscorekeeper.scores_primary;
WinningConditionHelper_secondscore = secondscorekeeper.scores_primary;
float WinningConditionHelper_topscore; ///< highest score
float WinningConditionHelper_secondscore; ///< second highest score
float WinningConditionHelper_winnerteam; ///< the color of the winning team, or -1 if none
+float WinningConditionHelper_winnerteam_last;
float WinningConditionHelper_secondteam; ///< the color of the second team, or -1 if none
float WinningConditionHelper_equality; ///< we have no winner
entity WinningConditionHelper_winner; ///< the winning player, or NULL if none
entity WinningConditionHelper_second; ///< the second player, or NULL if none
+entity WinningConditionHelper_winner_last;
+entity WinningConditionHelper_equality_one;
+entity WinningConditionHelper_equality_two;
float WinningConditionHelper_lowerisbetter; ///< lower is better, duh
float WinningConditionHelper_zeroisworst; ///< zero is worst, duh
#define WINNINGCONDITIONHELPER_LOWERISBETTER_WORST 999999999
* nospectators: exclude spectators
*/
entity PlayerScore_Sort(.float field, int teams, bool strict, bool nospectators);
+
+// z411
+bool Score_NewLeader();
.int m_team_balance_state; ///< Holds the state of the team balance entity.
.entity m_team_balance_team[NUM_TEAMS]; ///< ???
+.string m_team_name; // z411 team name
.float m_team_score; ///< The score of the team.
.int m_num_players; ///< Number of players (both humans and bots) in a team.
.int m_num_bots; ///< Number of bots in a team.
return g_team_entities[Team_TeamToIndex(team_num) - 1];
}
+string Team_GetTeamName(entity team_ent)
+{
+ return team_ent.m_team_name;
+}
+
+void Team_SetTeamName(entity team_ent, string name)
+{
+ team_ent.m_team_name = name;
+}
+
float Team_GetTeamScore(entity team_ent)
{
return team_ent.m_team_score;
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_GetWinnerAliveTeam()
{
int winner = 0;
return true;
}
+entity SpectatorWantsJoin(entity this)
+{
+ FOREACH_CLIENT(IS_REAL_CLIENT(it), {
+ if(it == this) continue;
+ if(it.wants_join) {
+ LOG_DEBUGF("Player is waiting to join: %s", it.netname);
+ return it;
+ }
+ });
+
+ // No players waiting to join
+ LOG_DEBUG("No players waiting to join.");
+ return NULL;
+}
+
bool SetPlayerTeam(entity player, int team_index, int type)
{
int old_team_index = Entity_GetTeamIndex(player);
TeamBalance_AutoBalanceBots();
if (team_index != -1)
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(player.team, INFO_JOIN_PLAY_TEAM), player.netname);
+ {
+ if (!IS_BOT_CLIENT(player) && IS_QUEUE_NEEDED(player) && !SpectatorWantsJoin(player))
+ {
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(player.team, INFO_JOIN_WANTS_TEAM), player.netname);
+ Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_JOIN_PREVENT_QUEUE);
+ player.wants_join = team_index; // Player queued to join
+ }
+ else
+ {
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(player.team, INFO_JOIN_PLAY_TEAM), player.netname);
+ }
+ }
}
if (team_index == -1)
Kill_Notification(NOTIF_ONE_ONLY, player, MSG_CENTER, CPID_IDLING);
CS(player).idlekick_lasttimeleft = 0;
}
+ else if (player.wants_join)
+ {
+ player.wants_join = 0;
+ player.team_selected = false;
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_QUEUE, player.netname);
+ }
else if (!CS(player).just_joined && player.frags != FRAGS_SPECTATOR)
{
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_SPECTATE, player.netname);
return result;
}
+bool TeamBalance_AreEqual(entity ignore, bool would_leave)
+{
+ entity balance = TeamBalance_CheckAllowedTeams(ignore);
+ TeamBalance_GetTeamCounts(balance, ignore);
+
+ bool equality = true;
+ int total;
+ int prev_total = 0;
+ int bots = 0;
+
+ for(int i = 1; i <= AVAILABLE_TEAMS; ++i)
+ {
+ total = TeamBalance_GetTeamFromIndex(balance, i).m_num_players;
+ bots += TeamBalance_GetTeamFromIndex(balance, i).m_num_bots;
+ if(i > 1 && total != prev_total)
+ {
+ equality = false;
+ break;
+ }
+ prev_total = total;
+ }
+ TeamBalance_Destroy(balance);
+
+ // Ignore if there are "ghost" bots that would leave if anyone joined
+ if (would_leave && bots > autocvar_bot_number)
+ return false;
+
+ return equality;
+}
+
+entity remove_countdown;
+entity remove_player;
+int remove_timeleft;
+
+void Remove_Countdown(entity this)
+{
+ if(remove_timeleft <= 0 || TeamBalance_AreEqual(NULL, false))
+ {
+ if(remove_timeleft <= 0)
+ {
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_MOVETOSPEC_REMOVE, playername(remove_player.netname, remove_player.team, true));
+ PutObserverInServer(remove_player, true, true);
+ }
+
+ Kill_Notification(NOTIF_ALL, NULL, MSG_CENTER, CPID_REMOVE);
+
+ delete(this);
+ remove_countdown = NULL;
+ remove_player = NULL;
+ remove_timeleft = 0;
+
+ TeamBalance_RemoveExcessPlayers(NULL); // Check again for excess players in case someone also left while in countdown
+ return;
+ }
+
+ --remove_timeleft;
+ this.nextthink = time + 1;
+}
+
+void TeamBalance_RemoveExcessPlayers(entity ignore)
+{
+ if(AVAILABLE_TEAMS != 2 || autocvar_g_campaign) return;
+
+ entity balance = TeamBalance_CheckAllowedTeams(ignore);
+ TeamBalance_GetTeamCounts(balance, ignore);
+
+ int min = 0;
+
+ for(int i = 1; i <= AVAILABLE_TEAMS; ++i)
+ {
+ int cur = TeamBalance_GetTeamFromIndex(balance, i).m_num_players;
+ if(i == 1 || cur < min)
+ min = cur;
+ }
+
+ for(int tmi = 1; tmi <= AVAILABLE_TEAMS; ++tmi)
+ {
+ int cur = TeamBalance_GetTeamFromIndex(balance, tmi).m_num_players;
+ if(cur > 0 && cur > min) // If this team has excess players
+ {
+ // Get newest player
+ int latest_join = 0;
+ entity latest_join_pl = NULL;
+
+ FOREACH_CLIENT(IS_REAL_CLIENT(it) || INGAME(it), {
+ if(it.team == Team_IndexToTeam(tmi) && CS(it).startplaytime > latest_join)
+ {
+ latest_join = CS(it).startplaytime;
+ latest_join_pl = it;
+ }
+ });
+
+ // Force player to spectate
+ if(latest_join_pl)
+ {
+ // Send player to spectate
+ if(autocvar_g_balance_teams_remove_wait)
+ {
+ // Give a warning before moving to spect
+ remove_player = latest_join_pl;
+ remove_timeleft = autocvar_g_balance_teams_remove_wait;
+
+ if (!remove_countdown)
+ {
+ remove_countdown = new_pure(remove_countdown);
+ setthink(remove_countdown, Remove_Countdown);
+ remove_countdown.nextthink = time;
+
+ Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_MOVETOSPEC_REMOVE, playername(remove_player.netname, remove_player.team, true), remove_timeleft);
+ }
+ }
+ else
+ {
+ // Move to spects immediately
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_MOVETOSPEC_REMOVE, latest_join_pl.netname);
+ PutObserverInServer(latest_join_pl, true, true);
+ }
+ }
+ }
+ }
+
+ TeamBalance_Destroy(balance);
+}
+
bool TeamBalance_IsTeamAllowed(entity balance, int index)
{
if (balance == NULL)
{
continue;
}
+ if (it.wants_join)
+ {
+ continue; // Queued players aren't actually in the game.
+ }
int team_num;
// TODO: Reconsider when the player is truly on the team.
if (IS_CLIENT(it) || INGAME(it))
bool autocvar_g_balance_teams;
bool autocvar_g_balance_teams_prevent_imbalance;
+bool autocvar_g_balance_teams_queue;
+bool autocvar_g_balance_teams_remove;
+int autocvar_g_balance_teams_remove_wait;
string autocvar_g_forced_team_otherwise;
.int team_forced; // can be a team number to force a team, or 0 for default action, or -1 for forced spectator
+#define IS_QUEUE_NEEDED(ignore) \
+ (teamplay && autocvar_g_balance_teams_queue && !autocvar_g_campaign && AVAILABLE_TEAMS == 2 \
+ && TeamBalance_AreEqual(ignore, true))
+
// ========================== Global teams API ================================
void Team_InitTeams();
/// \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 winner team.
/// \return Winner team or 0 if 2 or more teams have alive players or -1 if no team has any alive players.
TEAM_CHANGE_SPECTATOR = 4 ///< Player is joining spectators. //TODO: Remove?
};
+entity SpectatorWantsJoin(entity this);
+
/// \brief Sets the team of the player.
/// \param[in,out] player Player to adjust.
/// \param[in] team_index Index of the team to set.
/// \return Bitmask of allowed teams.
int TeamBalance_GetAllowedTeams(entity balance);
+bool TeamBalance_AreEqual(entity ignore, bool would_leave);
+void TeamBalance_RemoveExcessPlayers(entity ignore);
+
/// \brief Returns whether the team change to the specified team is allowed.
/// \param[in] balance Team balance entity.
/// \param[in] index Index of the team.
#include <common/constants.qh>
#include <common/net_linked.qh>
#include <common/teams.qh>
+#include <common/gamemodes/gamemode/duel/duel.qh>
#include <common/util.qh>
#include <common/weapons/_all.qh>
#include <server/client.qh>
entity a = this.owner;
if (IS_SPEC(a)) a = a.enemy;
a = CS(a).accuracy;
+
+ // z411 send entity number
+ if(g_duel)
+ WriteByte(MSG_ENTITY, etof(a.owner));
+ else
+ WriteByte(MSG_ENTITY, 0);
if (to != a.owner)
if (!autocvar_sv_accuracy_data_share && !CS_CVAR(a.owner).cvar_cl_accuracy_data_share)
// note: zero sendflags can never be sent... so we can use that to say that we send no accuracy!
WriteInt24_t(MSG_ENTITY, sf);
if (sf == 0) return true;
+
// note: we know that client and server agree about SendFlags...
int f = 1;
for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w) {
- if (sf & f) WriteByte(MSG_ENTITY, accuracy_byte(a.accuracy_hit[w], a.accuracy_fired[w]));
+ if (sf & f) {
+ if(g_duel) {
+ WriteByte(MSG_ENTITY, a.accuracy_frags[w]);
+ WriteShort(MSG_ENTITY, a.accuracy_hit[w]);
+ WriteShort(MSG_ENTITY, a.accuracy_cnt_hit[w]);
+ WriteShort(MSG_ENTITY, a.accuracy_cnt_fired[w]);
+ } else {
+ WriteByte(MSG_ENTITY, accuracy_byte(a.accuracy_hit[w], a.accuracy_fired[w]));
+ }
+ }
f = (f == 0x800000) ? 1 : f * 2;
}
return true;
void accuracy_init(entity e)
{
entity a = CS(e).accuracy = new_pure(accuracy);
+ e.roundaccuracy = new_pure(accuracy);
a.owner = e;
- a.drawonlytoclient = e;
+ if(!g_duel) // z411
+ a.drawonlytoclient = e;
Net_LinkEntity(a, false, 0, accuracy_send);
}
void accuracy_free(entity e)
{
delete(CS(e).accuracy);
+ delete(e.roundaccuracy);
}
void accuracy_reset(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, float fired, float 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;
}
- if (b == accuracy_byte(a.accuracy_hit[wepid], a.accuracy_fired[wepid])) return; // no change
+ if (!g_duel && b == accuracy_byte(a.accuracy_hit[wepid], a.accuracy_fired[wepid])) return; // no change
int sf = 1 << (wepid % 24);
a.SendFlags |= sf;
- FOREACH_CLIENT(IS_SPEC(it) && it.enemy == this, { CS(it).accuracy.SendFlags |= sf; });
+
+ if(!g_duel)
+ FOREACH_CLIENT(IS_SPEC(it) && it.enemy == this, { CS(it).accuracy.SendFlags |= sf; });
}
bool accuracy_isgooddamage(entity attacker, entity targ)
REPLICATE_INIT(bool, cvar_cl_accuracy_data_receive);
.entity accuracy;
+.entity roundaccuracy;
.float accuracy_frags[REGISTRY_MAX(Weapons)];
.float accuracy_hit[REGISTRY_MAX(Weapons)];
// 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);
#include <common/effects/all.qh>
#include <common/net_linked.qh>
#include <common/state.qh>
+#include <common/scores.qh>
#include <common/util.qh>
#include <common/weapons/_all.qh>
#include <common/wepent.qh>
IL_CLEAR(g_railgunhit);
- if(headshot)
- Send_Notification(NOTIF_ONE, this, MSG_ANNCE, ANNCE_HEADSHOT);
+ if(headshot) {
+ Give_Medal(this, HEADSHOT);
+ }
// calculate hits and fired shots for hitscan
if(this.(weaponentity))
Damage_DamageInfo(start, 0, 0, 0, max(1, force) * normalize(dir) * -damage_fraction, dtype, 0, this);
}
- if(headshot)
- Send_Notification(NOTIF_ONE, this, MSG_ANNCE, ANNCE_HEADSHOT);
+ if(headshot) {
+ Give_Medal(this, HEADSHOT);
+ }
if(lag)
antilag_restore_all(this);
#include <common/mapobjects/platforms.qh>
#include <common/monsters/_mod.qh>
#include <common/mutators/mutator/status_effects/_mod.qh>
+#include <common/ent_cs.qh>
#include <common/net_linked.qh>
#include <common/notifications/all.qh>
#include <common/resources/sv_resources.qh>
{
if (time < game_starttime && !sv_ready_restart_after_countdown) return true;
if (player.player_blocked) return true;
- if (game_stopped) return true;
+ if (game_stopped || game_timeout) return true;
if (STAT(FROZEN, player)) return true;
if (MUTATOR_CALLHOOK(LockWeapon, player)) return true;
return false;
this.m_weapon = newwep;
this.weaponname = newwep.mdl;
this.bulletcounter = 0;
+ actor.activewepid = newwep.m_id; // z411
newwep.wr_setup(newwep, actor, weaponentity);
this.state = WS_RAISE;
const float SPAWNFLAG_NO_WAYPOINTS_FOR_ITEMS = 1;
+void send_TotalShards(entity to) {
+ // for RJZ
+ // Send total number of picked up shards
+ if(!autocvar_rjz_count_shards) return;
+ if(!IS_REAL_CLIENT(to)) return;
+
+ msg_entity = to;
+ WriteHeader(MSG_ONE, TE_CSQC_TOTALSHARDS);
+ WriteInt24_t(MSG_ONE, total_shards);
+}
+
+void send_TotalShardsAll() {
+ // for RJZ
+ // Send total number of picked up shards
+ if(!autocvar_rjz_count_shards) return;
+
+ FOREACH_CLIENT(IS_REAL_CLIENT(it) && (IS_SPEC(it) || IS_OBSERVER(it)), {
+ send_TotalShards(it);
+ });
+}
+
void SetDefaultAlpha()
{
if (!MUTATOR_CALLHOOK(SetDefaultAlpha))
BADCVAR("g_mapinfo_ignore_warnings");
BADCVAR("g_maplist_ignore_sizes");
BADCVAR("g_maplist_sizes_count_bots");
-
// long
BADCVAR("hostname");
+ BADCVAR("hostname_full");
BADCVAR("g_maplist");
BADCVAR("g_maplist_mostrecent");
BADCVAR("sv_motd");
+ BADCVAR("sv_motd_permanent");
+
+ BADPREFIX("g_teamnames_");
BADCVAR("sv_termsofservice_url");
v = cvar_string(k);
BADCVAR("g_forced_respawn");
BADCVAR("g_freezetag_point_leadlimit");
BADCVAR("g_freezetag_point_limit");
+ BADCVAR("g_freezetag_revive_respawn");
+ BADCVAR("g_freezetag_round_stop");
+ BADCVAR("g_freezetag_round_respawn");
BADCVAR("g_glowtrails");
BADCVAR("g_hats");
BADCVAR("g_casings");
BADCVAR("g_tmayhem_point_leadlimit");
BADCVAR("leadlimit_and_fraglimit");
BADCVAR("leadlimit_override");
+ BADCVAR("g_mayhem_scoringmethod");
+ BADCVAR("g_mayhem_scoringmethod_damage_weight");
+ BADCVAR("g_mayhem_scoringmethod_frag_weight");
+ BADCVAR("g_tmayhem_scoringmethod");
+ BADCVAR("g_tmayhem_scoringmethod_damage_weight");
+ BADCVAR("g_tmayhem_scoringmethod_frag_weight");
BADCVAR("pausable");
BADCVAR("sv_announcer");
BADCVAR("sv_autopause");
BADPREFIX("sv_timeout_");
BADPREFIX("sv_vote_");
BADPREFIX("timelimit_");
+ BADPREFIX("sv_chat_");
+ BADPREFIX("sv_jingle_");
BADPRESUFFIX("g_", "_round_timelimit");
// allowed changes to server admins (please sync this to server.cfg)
BADCVAR("gametype");
BADCVAR("g_antilag");
BADCVAR("g_balance_teams");
+ BADCVAR("g_balance_teams_queue");
+ BADCVAR("g_balance_teams_remove");
+ BADCVAR("g_balance_teams_remove_wait");
BADCVAR("g_balance_teams_prevent_imbalance");
BADCVAR("g_balance_teams_scorefactor");
BADCVAR("g_ban_sync_trusted_servers");
BADCVAR("g_grappling_hook");
BADCVAR("g_jetpack");
+ // temporary for testing
+ // TODO remove before 0.8.3 release
+ BADCVAR("g_ca_weaponarena");
+ BADCVAR("g_freezetag_weaponarena");
+ BADCVAR("g_lms_weaponarena");
+ BADCVAR("g_mayhem_weaponarena");
+ BADCVAR("g_tmayhem_weaponarena");
+ BADCVAR("g_ctf_stalemate_time");
+
#undef BADPRESUFFIX
#undef BADPREFIX
#undef BADCVAR
WinningConditionHelper(this); // set worldstatus
+ round_handler_Activate(!warmup_stage);
+
+ // for RJZ
+ if (autocvar_rjz_count_shards && warmup_stage) {
+ total_shards = -2;
+ send_TotalShardsAll();
+ }
+
if (autocvar_sv_autopause && server_is_dedicated && !wantrestart)
// INITPRIO_LAST is too soon: bots either didn't join yet or didn't leave yet, see: bot_fixcount()
defer(this, 5, Pause_TryPause_Dedicated);
*/
//pos = FindIntermission ();
+
+ sound(NULL, CH_INFO, SND_ENDMATCH, VOL_BASE, ATTN_NONE);
VoteReset(true);
WeaponStats_Shutdown();
Kill_Notification(NOTIF_ALL, NULL, MSG_CENTER, CPID_Null); // kill all centerprints now
+
+ // send winner notification
+ if(teamplay) {
+ Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, APP_TEAM_NUM(WinningConditionHelper_winnerteam, ANNCE_TEAM_WINS));
+ }
if(autocvar_sv_eventlog)
GameLogEcho(":gameover");
});
target_music_kill();
+
+ // z411
+ if(autocvar_sv_jingle_end) {
+ int jingles_len = 0;
+ string jingles[32];
+ jingles[0] = "";
+
+ FOREACH_WORD(autocvar_sv_jingle_end_list, it,
+ {
+ jingles[jingles_len] = it;
+ jingles_len++;
+ });
+
+ if(jingles_len) {
+ int song_to_play = rint(random() * (jingles_len - 1));
+
+ FOREACH_CLIENT(IS_REAL_CLIENT(it),
+ {
+ stuffcmd(it, "cd stop\n");
+ _sound(it, CH_INFO, strcat("jingle/", jingles[song_to_play], ".ogg"), VOL_BASE * autocvar_sv_jingle_end_volume, ATTEN_NORM);
+ });
+ }
+ }
if(autocvar_g_campaign)
CampaignPreIntermission();
//add one more overtime by simply extending the timelimit
cvar_set("timelimit", ftos(autocvar_timelimit + autocvar_timelimit_overtime));
Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_OVERTIME_TIME, autocvar_timelimit_overtime * 60);
+
+ sound(NULL, CH_INFO, SND_OVERTIME, VOL_BASE, ATTN_NONE);
+ if(checkrules_overtimesadded == 1) {
+ Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_OVERTIME);
+ overtime_starttime = time;
+ }
}
float GetWinningCode(float fraglimitreached, float equality)
FOREACH_CLIENT(IS_PLAYER(it) || INGAME(it), { it.winning = 0; });
}
-int fragsleft_last;
+void AnnounceNewLeader()
+{
+ // Don't announce if in warmup or just started
+ if(warmup_stage || time - game_starttime < 1) return;
+
+ if(teamplay) {
+ if (WinningConditionHelper_equality)
+ Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_TEAM_LEADS_TIED);
+ else
+ FOREACH_CLIENT(IS_PLAYER(it), {
+ if(it.team == WinningConditionHelper_winnerteam)
+ Send_Notification(NOTIF_ONE_ONLY, it, MSG_ANNCE, ANNCE_TEAM_LEADS_TEAM);
+ else
+ Send_Notification(NOTIF_ONE_ONLY, it, MSG_ANNCE, ANNCE_TEAM_LEADS_ENEMY);
+ });
+ Send_Notification(NOTIF_ALL_SPEC, NULL, MSG_ANNCE, APP_TEAM_NUM(WinningConditionHelper_winnerteam, ANNCE_TEAM_LEADS));
+ } else {
+ if (WinningConditionHelper_equality)
+ {
+ Send_Notification(NOTIF_ONE, WinningConditionHelper_equality_one, MSG_ANNCE, ANNCE_LEAD_TIED);
+ Send_Notification(NOTIF_ONE, WinningConditionHelper_equality_two, MSG_ANNCE, ANNCE_LEAD_TIED);
+ }
+ else
+ {
+ Send_Notification(NOTIF_ONE, WinningConditionHelper_winner, MSG_ANNCE, ANNCE_LEAD_GAINED);
+ Send_Notification(NOTIF_ONE, WinningConditionHelper_second, MSG_ANNCE, ANNCE_LEAD_LOST);
+ }
+ }
+}
+
+void AnnounceScores(float tm)
+{
+ WinningConditionHelper(NULL);
+ if (Score_NewLeader()) {
+ AnnounceNewLeader();
+ } else {
+ FOREACH_CLIENT(IS_PLAYER(it), {
+ if(it.team == tm)
+ Send_Notification(NOTIF_ONE_ONLY, it, MSG_ANNCE, ANNCE_TEAM_SCORES_TEAM);
+ else
+ Send_Notification(NOTIF_ONE_ONLY, it, MSG_ANNCE, ANNCE_TEAM_SCORES_ENEMY);
+ });
+ Send_Notification(NOTIF_ALL_SPEC, NULL, MSG_ANNCE, APP_TEAM_NUM(tm, ANNCE_TEAM_SCORES));
+ }
+}
+
float WinningCondition_Scores(float limit, float leadlimit)
{
// TODO make everything use THIS winning condition (except LMS)
if(MUTATOR_CALLHOOK(Scores_CountFragsRemaining))
{
- float fragsleft;
if (checkrules_suddendeathend && time >= checkrules_suddendeathend)
{
fragsleft = 1;
fragsleft_last = fragsleft;
}
}
-
+
+ // z411 - lead announcer
+ if(MUTATOR_CALLHOOK(Scores_AnnounceLeads)) {
+ if (Score_NewLeader())
+ AnnounceNewLeader();
+ }
+
bool fraglimit_reached = (limit && WinningConditionHelper_topscore >= limit);
bool leadlimit_reached = (leadlimit && WinningConditionHelper_topscore - WinningConditionHelper_secondscore >= leadlimit);
// again, but this shouldn't hurt
return;
}
+
+ // z411 don't check rules if we're in a timeout
+ if (game_timeout) return;
float timelimit = autocvar_timelimit * 60;
float fraglimit = autocvar_fraglimit;
Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_RACE_FINISHLAP);
else
Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_OVERTIME_FRAG);
+ checkrules_overtimesadded = 1;
+ sound(NULL, CH_INFO, SND_OVERTIME, VOL_BASE, ATTN_NONE);
+ Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_OVERTIME);
}
}
else
serverflags &= ~SERVERFLAG_ALLOW_FULLBRIGHT;
if(cvar("sv_allow_fullbright"))
serverflags |= SERVERFLAG_ALLOW_FULLBRIGHT;
+ if(cvar("sv_forbid_pickuptimer"))
+ serverflags |= SERVERFLAG_FORBID_PICKUPTIMER;
serverflags &= ~SERVERFLAG_FORBID_PICKUPTIMER;
if(cvar("sv_forbid_pickuptimer"))
bool autocvar_sv_freezenonclients;
void Physics_Frame()
{
- if(autocvar_sv_freezenonclients)
+ if(autocvar_sv_freezenonclients || game_timeout)
return;
IL_EACH(g_moveables, true,
int autocvar_timelimit_overtimes;
float autocvar_timelimit_suddendeath;
+// z411
+bool autocvar_sv_jingle_end;
+string autocvar_sv_jingle_end_list;
+float autocvar_sv_jingle_end_volume;
+
+float fragsleft;
+int fragsleft_last;
bool autocvar_sv_mapformat_is_quake3;
bool autocvar_sv_mapformat_is_quake2;
.vector dropped_origin;
void droptofloor(entity this);
+/* z411 for RJZ */
+bool autocvar_rjz_count_shards = false;
+bool autocvar_rjz_ranks = false;
+int total_shards = 0;
+void send_TotalShards(entity to);
+void send_TotalShardsAll();
+
IntrusiveList g_moveables;
STATIC_INIT(g_moveables) { g_moveables = IL_NEW(); }
alias sv_hook_lastleave
// restart server if all players hit "ready"-button
-set sv_ready_restart_after_countdown 0 "reset players and map items after the countdown ended, instead of at the beginning of the countdown"
+// BaI mod changes this to 1
+set sv_ready_restart_after_countdown 1 "reset players and map items after the countdown ended, instead of at the beginning of the countdown"
alias sv_hook_readyrestart
set g_weapon_stay 0 "1: ghost weapons can be picked up but give no ammo, thrown guns have ammo 2: ghost weapons can be picked up and refill ammo to one pickup size, thrown guns have no ammo (to prevent infinite ammo abuse)"
set g_weapon_throwable 1 "if set to 1, weapons can be dropped"
set g_powerups -1 "if set to 0 no powerups will spawn, if 1 they will spawn in all game modes, -1 is game mode default"
-set g_powerups_drop 0 "allow dropping powerups (1 = timer continues, 2 = timer freezes until picked up)"
-set g_powerups_drop_ondeath 1 "players will drop their powerups on death (1 = timer continues, 2 = timer freezes until picked up)"
+// BaI mod changes this
+set g_powerups_drop 2 "allow dropping powerups (1 = timer continues, 2 = timer freezes until picked up)"
+set g_powerups_drop_ondeath 2 "players will drop their powerups on death (1 = timer continues, 2 = timer freezes until picked up)"
set g_powerups_stack 0 "enables stacking of powerup timers when picking up a powerup you already have; otherwise timer is reset to the time granted by the item, if greater than the time you currently have"
set g_powerups_strength 1 "allow strength powerups to spawn"
set g_powerups_shield 1 "allow shield powerups to spawn"
// common team values
-set teamplay_mode 4 "default teamplay setting in team games. 1 = no friendly fire, self damage. 2 = friendly fire and self damage enabled. 3 = no friendly fire, but self damage enabled. 4 = obey the cvars g_mirrordamage*, g_friendlyfire* and g_teamdamage*"
+// BaI mod changes this
+set teamplay_mode 2 "default teamplay setting in team games. 1 = no friendly fire, self damage. 2 = friendly fire and self damage enabled. 3 = no friendly fire, but self damage enabled. 4 = obey the cvars g_mirrordamage*, g_friendlyfire* and g_teamdamage*"
set g_mirrordamage 0.7 "for teamplay_mode 4: mirror damage factor"
set g_mirrordamage_virtual 1 "for teamplay_mode 4: do not actually apply mirror damage, just show graphics effect for it"
set g_mirrordamage_onlyweapons 0 "for teamplay_mode 4: only apply mirror damage if the attack was from a weapon"
set g_balance_teams 1 "automatically balance out players entering instead of asking them for their preferred team"
set g_balance_teams_prevent_imbalance 1 "prevent players from changing to larger teams"
+set g_balance_teams_queue 0 "queue players before joining"
+set g_balance_teams_remove 0 "remove excess players from teams"
+set g_balance_teams_remove_wait 10 "seconds to warn everyone before removing an excess player (0 = immediately)"
set g_changeteam_banned 0 "not allowed to change team"
set sv_teamnagger 1 "enable a nag message when the teams are unbalanced"