// e.g. Xonotic 1.5.1 RC1 will be 15101
set g_xonoticversion git "Xonotic version (formatted for humans)"
- gameversion 700 // 0.7.0
+ gameversion 800 // 0.8.0
gameversion_min 0 // git builds see all versions
gameversion_max 65535 // git builds see all versions
// other aliases
alias +hook +button6
alias -hook -button6
+ alias +jetpack +button10
+ alias -jetpack -button10
alias use "impulse 21"
// for backwards compatibility
alias +show_info +button7
alias -show_info -button7
- bind f6 team_auto
-
// merge lightmaps up to 2048x2048 textures
mod_q3bsp_lightmapmergepower 4
// player defaults
_cl_color "112.211" // same effect as 112, but menuqc can detect this as the default and not intentionally set
- _cl_name Player
+ _cl_name ""
_cl_playermodel models/player/erebus.iqm
_cl_playerskin 0
seta cl_reticle 1 "control for toggling whether ANY zoom reticles are shown"
seta cl_reticle_stretch 0 "whether to stretch reticles so they fit the screen (breaks image proportions)"
- seta cl_reticle_item_nex 1 "draw aiming reticle for the nex weapon's zoom, 0 disables and values between 0 and 1 change alpha"
+ seta cl_reticle_item_vortex 1 "draw aiming reticle for the vortex weapon's zoom, 0 disables and values between 0 and 1 change alpha"
seta cl_reticle_item_normal 1 "draw reticle when zooming with the zoom button, 0 disables and values between 0 and 1 change alpha"
fov 100
- seta cl_velocityzoom 0 "velocity based zooming of fov, negative values zoom out"
+ seta cl_velocityzoom_enabled 0 "velocity based zooming of fov"
+ seta cl_velocityzoom_factor 0 "factor of fov zooming (negative values zoom out)"
seta cl_velocityzoom_type 3 "how to factor in speed, 1 = all velocity in all directions, 2 = velocity only in forward direction (can be negative), 3 = velocity only in forward direction (limited to forward only)"
seta cl_velocityzoom_speed 1000 "target speed for fov factoring"
seta cl_velocityzoom_time 0.2 "time value for averaging speed values"
set sv_ready_restart_after_countdown 0 "if set to 1 the players and map items are reset after the countdown ended, otherwise they're reset already at the beginning of the countdown"
set sv_ready_restart_repeatable 0 "allows the players to restart the game as often as needed"
- seta cl_hitsound 1 "play a hit notifier sound when you have hit an enemy"
+ seta cl_hitsound 1 "play a hit notifier sound when you have hit an enemy, 1: same pitch 2: increase pitch with more damage 3: decrease pitch with more damage"
set cl_hitsound_antispam_time 0.05 "don't play the hitsound more often than this"
+ seta cl_hitsound_min_pitch 0.75 "minimum pitch of hit sound"
+ seta cl_hitsound_max_pitch 1.5 "maximum pitch of hit sound"
+ seta cl_hitsound_nom_damage 25 "damage amount at which hitsound bases pitch off"
- seta cl_eventchase_death 1 "camera goes into 3rd person mode when the player is dead"
+ seta cl_eventchase_death 1 "camera goes into 3rd person mode when the player is dead; set to 2 to active the effect only when the corpse doesn't move anymore"
seta cl_eventchase_nexball 1 "camera goes into 3rd person mode when in nexball game-mode"
seta cl_eventchase_distance 140 "final camera distance"
+seta cl_eventchase_distance 400 "final camera distance while viewing generator explosion"
seta cl_eventchase_speed 1.3 "how fast the camera slides back, 0 is instant"
seta cl_eventchase_maxs "12 12 8" "max size of eventchase camera bbox"
seta cl_eventchase_mins "-12 -12 -8" "min size of eventchase camera bbox"
seta cl_eventchase_viewoffset "0 0 20" "viewoffset of eventchase camera"
+seta cl_eventchase_generator_viewoffset "0 0 80" "viewoffset of eventchase camera while viewing generator explosion"
//nifreks lockonrestart feature, used in team-based game modes, if set to 1 and all players readied up no other player can then join the game anymore, useful to block spectators from joining
set teamplay_lockonrestart 0 "it set to 1 in a team-based game, the teams are locked once all players readied up and the game restarted (no new players can join after restart unless using the server-command unlockteams)"
set sv_timeout_leadtime 4 "how long the players will be informed that a timeout was called before it starts, in seconds"
set sv_timeout_resumetime 3 "how long the remaining timeout-time will be after a player called the timein command"
- set g_allow_oldnexbeam 0 "If enabled, clients are allowed to use old v2.3 Nexgun beam"
- seta cl_particles_oldnexbeam 0 "Uses the old v2.3 Nexgun beam instead of the new beam, only works if server allows it (g_allow_oldnexbeam 1)"
+ set g_allow_oldvortexbeam 0 "If enabled, clients are allowed to use old v2.3 Vortex beam"
+ seta cl_particles_oldvortexbeam 0 "Uses the old v2.3 Vortex beam instead of the new beam, only works if server allows it (g_allow_oldvortexbeam 1)"
set g_telefrags 1 "telefragging, i.e. killing someone who stands in the way of someone who is teleporting"
set g_telefrags_teamplay 1 "never telefrag team mates"
set bot_ai_aimskill_offset 0.3 "Amount of error induced to the bots aim"
set bot_ai_aimskill_think 1 "Aiming velocity. Use values below 1 for slower aiming"
set bot_ai_custom_weapon_priority_distances "300 850" "Define close and far distances in any order. Based on the distance to the enemy bots will choose different weapons"
- set bot_ai_custom_weapon_priority_far "minstanex nex rifle electro rocketlauncher grenadelauncher hagar hlac crylink laser uzi fireball seeker shotgun tuba minelayer" "Desired weapons for far distances ordered by priority"
- set bot_ai_custom_weapon_priority_mid "minstanex rocketlauncher nex fireball seeker grenadelauncher electro uzi crylink hlac hagar shotgun laser rifle tuba minelayer" "Desired weapons for middle distances ordered by priority"
- set bot_ai_custom_weapon_priority_close "minstanex shotgun nex uzi hlac tuba seeker hagar crylink grenadelauncher electro rocketlauncher laser fireball rifle minelayer" "Desired weapons for close distances ordered by priority"
+ set bot_ai_custom_weapon_priority_far "vaporizer vortex rifle electro devastator mortar hagar hlac crylink blaster machinegun fireball seeker shotgun tuba minelayer" "Desired weapons for far distances ordered by priority"
+ set bot_ai_custom_weapon_priority_mid "vaporizer devastator vortex fireball seeker mortar electro machinegun crylink hlac hagar shotgun blaster rifle tuba minelayer arc shockwave" "Desired weapons for middle distances ordered by priority"
+ set bot_ai_custom_weapon_priority_close "vaporizer shotgun vortex machinegun hlac tuba seeker hagar crylink mortar electro devastator blaster fireball rifle minelayer arc shockwave" "Desired weapons for close distances ordered by priority"
set bot_ai_weapon_combo 1 "Enable bots to do weapon combos"
set bot_ai_weapon_combo_threshold 0.4 "Try to make a combo N seconds after the last attack"
set bot_ai_friends_aware_pickup_radius "500" "Bots will not pickup items if a team mate is this distance near the item"
set g_pickup_items -1 "if set to 0 all items (health, armor, ammo, weapons...) are removed from the map, if 1 they are forced to spawn"
set g_weaponarena "0" "put in a list of weapons to enable a weapon arena mode, or try \"all\" or \"most\""
set g_weaponarena_random "0" "if set to a number, only that weapon count is given on every spawn (randomly)"
- set g_weaponarena_random_with_laser "1" "additionally, always provide the laser in random weapon arena games"
- set g_midair 0 "if set to 1 you can only apply damage to your opponent while he is airborne"
- set g_midair_shieldtime 0.3 "number of seconds you are still invincible since you lost contact to the ground"
+ set g_weaponarena_random_with_blaster "1" "additionally, always provide the blaster in random weapon arena games"
set g_spawnpoints_auto_move_out_of_solid 0 "if set to 1 you will see a warning if a spawn point was placed inside a solid"
set g_forced_respawn 0 "if set to 1 and a player died, that player gets automatically respawned once <g_respawn_delay> seconds are over"
set g_fullbrightplayers 0 "brightens up player models (note that the color, skin or model of the players does not change!)"
seta menu_sandbox_edit_force 1
seta menu_sandbox_edit_material ""
- bind f7 menu_showsandboxtools
-
seta menu_monsters_edit_spawn ""
seta menu_monsters_edit_skin 0
seta menu_monsters_edit_movetarget 1
set g_grappling_hook 0 "let players spawn with the grappling hook which allows them to pull themselves up"
set g_spawn_alloweffects 1 "allow clients to enable spawn point and event effects such as particles and sounds, see cl_spawn_ cvars for more info"
- set g_spawn_furthest 1 "this amount of the spawns shall be far away from any players"
+ set g_spawn_furthest 0.5 "this amount of the spawns shall be far away from any players"
set g_spawn_useallspawns 0 "use all spawns, e.g. also team spawns in non-teamplay, and all spawns, even enemy spawns, in teamplay"
// respawn delay
set g_respawn_delay_small 2 "small game number of seconds you have to wait before you can respawn again"
set g_tdm 0 "Team Deathmatch: the team who kills their opponents most often wins"
set g_tdm_on_dm_maps 0 "when this is set, all DM maps automatically support TDM"
- seta 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 following four cvars"
+ seta 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_threshold*"
seta g_mirrordamage 0.700000 "for teamplay 4: mirror damage factor"
seta g_mirrordamage_virtual 1 "for teamplay 4: do not actually apply mirror damage, just show graphics effect for it"
seta g_friendlyfire 0.500000 "for teamplay 4: fiendly fire factor"
set g_footsteps 1 "serverside footstep sounds"
- set g_deathglow 1.25 "when enabled, players stop glowing after they die (the value specifies glow fading speed)"
-
set g_multijump 0 "Number of multiple jumps to allow (jumping again in the air), -1 allows for infinite jumps"
set g_multijump_add 0 "0 = make the current z velocity equal to jumpvelocity, 1 = add jumpvelocity to the current z velocity"
set g_multijump_speed -999999 "Minimum vertical speed a player must have in order to jump again"
r_mipskins 1
r_shadow_realtime_world_lightmaps 1
cl_decals_fadetime 5
- cl_decals_time 2
+ cl_decals_time 1
seta cl_gunalign 3 "Gun alignment; 1 = center (if allowed by g_shootfromclient) or right, 2 = center (if allowed by g_shootfromclient) or left, 3 = right only, 4 = left only"
seta cl_nogibs 0 "reduce number of violence effects, or remove them totally"
seta cl_particlegibs 0 "simpler gibs"
seta cl_gibs_damageforcescale 3.5 "force to push around gibs"
- seta cl_gibs_lifetime 5 "average lifetime of gibs"
+ seta cl_gibs_lifetime 2.5 "average lifetime of gibs"
seta cl_gibs_velocity_scale 1 "gib throw velocity force scale"
seta cl_gibs_velocity_random 1 "gib throw velocity randomness scale"
seta cl_gibs_velocity_up 1 "extra z velocity for gibs"
seta cl_casings_bronze_time 10 "bullet casings lifetime"
seta cl_casings_ticrate 0.1 "ticrate for casings"
seta cl_casings_sloppy 1 "sloppy casings, may temporarily penetrate walls"
- seta cl_projectiles_sloppy 0 "sloppy projectiles, may temporarily penetrate walls"
+ seta cl_projectiles_sloppy 1 "sloppy projectiles, may temporarily penetrate walls"
cl_stainmaps 0
cl_particles_smoke 1
vid_gl20 1
alias reload "impulse 20"
- // movement
- bind w +forward
- bind a +moveleft
- bind s +back
- bind d +moveright
- bind UPARROW +forward
- bind LEFTARROW +moveleft
- bind DOWNARROW +back
- bind RIGHTARROW +moveright
- bind SHIFT +crouch
- bind ENTER +jump
- bind SPACE +jump
-
// weapons
alias weapon_group_1 "impulse 1"
alias weapon_group_2 "impulse 2"
alias weapon_group_9 "impulse 9"
alias weapon_group_0 "impulse 14" // cycles the superweapons
exec weapons.cfg
- bind 0 weapon_group_0
- bind 1 weapon_group_1
- bind 2 weapon_group_2
- bind 3 weapon_group_3
- bind 4 weapon_group_4
- bind 5 weapon_group_5
- bind 6 weapon_group_6
- bind 7 weapon_group_7
- bind 8 weapon_group_8
- bind 9 weapon_group_9
- bind q weaplast
- bind MOUSE1 +fire
- bind MOUSE2 +fire2
- bind MOUSE3 togglezoom
- bind MOUSE4 weaplast
- bind MOUSE5 +hook
- bind MWHEELUP weapnext
- bind MWHEELDOWN weapprev
- bind r reload
- bind BACKSPACE dropweapon
- bind g dropweapon
- bind f +use
- bind v +button8 // drag object
-
- // misc
- bind e +hook
- bind ` toggleconsole
- bind ~ toggleconsole
- bind TAB +showscores
- bind ESCAPE togglemenu
- bind t messagemode
- bind y messagemode2
- bind z messagemode2
- bind u "+con_chat_maximize"
- bind m +hud_panel_radar_maximized
- bind i +show_info
- bind PAUSE pause
- bind F10 menu_showquitdialog
- bind F11 disconnect
- bind F12 screenshot
- bind F4 ready
- bind ALT +showaccuracy
-
- // Gamepad defaults. Tested with Logitech Rumblepad 2, I hope similar ones works as well.
- bind JOY1 "+crouch"
- bind JOY2 "+jump"
- bind JOY3 "weapprev"
- bind JOY4 "weapnext"
- bind JOY5 "+fire2"
- bind JOY6 "+fire"
- bind JOY7 "+zoom"
- bind JOY8 "dropweapon"
- bind JOY9 "menu_showteamselect"
- bind JOY10 "+show_info"
- bind JOY11 "+showscores"
- bind JOY12 "+con_chat_maximize"
- seta joyadvanced "1"
- seta joyadvaxisr "2"
- seta joyadvaxisx "3"
- seta joyadvaxisy "1"
- seta joyadvaxisz "4"
- seta joysidesensitivity "1.0"
- seta joypitchsensitivity "0.9"
- seta joyyawsensitivity "-1.8"
- // SDL only
- seta joy_deadzoneforward "0.05"
- seta joy_deadzonepitch "0.05"
- seta joy_deadzoneside "0.05"
- seta joy_deadzoneup "0.05"
- seta joy_deadzoneyaw "0.05"
- seta joy_sensitivitypitch "0.9"
- seta joy_sensitivityyaw "-1.8"
-
- // team say
- bind kp_ins messagemode
- bind kp_del messagemode2
- bind kp_end "+userbind 1"
- bind kp_downarrow "+userbind 2"
- bind kp_pgdn "+userbind 3"
- bind kp_leftarrow "+userbind 4"
- bind kp_5 "+userbind 6"
- bind kp_rightarrow "+userbind 7"
- bind kp_home "+userbind 9"
- bind kp_uparrow "+userbind 10"
- bind kp_pgup "+userbind 11"
- bind kp_multiply "+userbind 12"
- bind kp_slash "+userbind 13"
- bind kp_enter "+userbind 16"
- bind kp_plus "+userbind 17"
- bind kp_minus "+userbind 18"
-
- bind F1 vyes
- bind F2 vno
-
- //used for spectate/observer mode
- bind F3 spec
// score log
set sv_logscores_console 0 "print scores to server console"
seta g_maplist_votable_abstain 0 "when 1, you can abstain from your vote"
seta g_maplist_votable_screenshot_dir "maps levelshots" "where to look for map screenshots"
+ set sv_vote_gametype 0 "show a vote screen for gametypes before map vote screen"
+ set sv_vote_gametype_keeptwotime 10 "show only 2 options for this amount of time during gametype vote screen"
+ set sv_vote_gametype_options "dm ctf ca lms tdm ft"
+ set sv_vote_gametype_timeout 20
+ set sv_vote_gametype_default_current 1 "Keep the current gametype if no one votes"
+
set g_chat_flood_spl 3 "normal chat: seconds between lines to not count as flooding"
set g_chat_flood_lmax 2 "normal chat: maximum number of lines per chat message at once"
set g_chat_flood_burst 2 "normal chat: allow bursts of so many chat lines"
r_labelsprites_scale 0.40625 // labels sprites get displayed at 0.5x from 640x480 to 1280x1024, and at 1x from 1600x1200 onwards
- // usercommands. These can be edited and bound by the menu.
- seta "userbind1_press" "say_team quad soon"; seta "userbind1_release" ""; seta "userbind1_description" "team: quad soon"
- seta "userbind2_press" "say_team free item %x^7 (l:%y^7); g_waypointsprite_team_here_p"; seta "userbind2_release" ""; seta "userbind2_description" "team: free item, icon"
- seta "userbind3_press" "say_team took item (l:%l^7); g_waypointsprite_team_here"; seta "userbind3_release" ""; seta "userbind3_description" "team: took item, icon"
- seta "userbind4_press" "say_team negative"; seta "userbind4_release" ""; seta "userbind4_description" "team: negative"
- seta "userbind5_press" "say_team positive"; seta "userbind5_release" ""; seta "userbind5_description" "team: positive"
- seta "userbind6_press" "say_team need help (l:%l^7) (h:%h^7 a:%a^7 w:%w^7); g_waypointsprite_team_helpme; cmd voice needhelp"; seta "userbind6_release" ""; seta "userbind6_description" "team: need help, icon"
- seta "userbind7_press" "say_team enemy seen (l:%y^7); g_waypointsprite_team_danger_p; cmd voice incoming"; seta "userbind7_release" ""; seta "userbind7_description" "team: enemy seen, icon"
- seta "userbind8_press" "say_team flag seen (l:%y^7); g_waypointsprite_team_here_p; cmd voice seenflag"; seta "userbind8_release" ""; seta "userbind8_description" "team: flag seen, icon"
- seta "userbind9_press" "say_team defending (l:%l^7) (h:%h^7 a:%a^7 w:%w^7); g_waypointsprite_team_here"; seta "userbind9_release" ""; seta "userbind9_description" "team: defending, icon"
- seta "userbind10_press" "say_team roaming (l:%l^7) (h:%h^7 a:%a^7 w:%w^7); g_waypointsprite_team_here"; seta "userbind10_release" ""; seta "userbind10_description" "team: roaming, icon"
- seta "userbind11_press" "say_team attacking (l:%l^7) (h:%h^7 a:%a^7 w:%w^7); g_waypointsprite_team_here"; seta "userbind11_release" ""; seta "userbind11_description" "team: attacking, icon"
- seta "userbind12_press" "say_team killed flagcarrier (l:%y^7); g_waypointsprite_team_here_p"; seta "userbind12_release" ""; seta "userbind12_description" "team: killed flag, icon"
- seta "userbind13_press" "say_team dropped flag (l:%d^7); g_waypointsprite_team_here_d"; seta "userbind13_release" ""; seta "userbind13_description" "team: dropped flag, icon"
- seta "userbind14_press" "say_team dropped gun %w^7 (l:%l^7); g_waypointsprite_team_here; wait; dropweapon"; seta "userbind14_release" ""; seta "userbind14_description" "team: drop gun, icon"
- // TODO change this to "use" once we can
- seta "userbind15_press" "say_team dropped flag/key %w^7 (l:%l^7); g_waypointsprite_team_here; wait; +use"; seta "userbind15_release" "-use"; seta "userbind15_description" "team: drop flag/key, icon"
- seta "userbind16_press" "say :-) / nice one"; seta "userbind16_release" ""; seta "userbind16_description" "chat: nice one"
- seta "userbind17_press" "say good game"; seta "userbind17_release" ""; seta "userbind17_description" "chat: good game"
- seta "userbind18_press" "say hi / good luck and have fun"; seta "userbind18_release" ""; seta "userbind18_description" "chat: hi / good luck"
- seta "userbind19_press" "+showscores; +con_chat_maximize"; seta "userbind19_release" "-showscores; -con_chat_maximize"; seta "userbind19_description" "scoreboard / chat history"
- seta "userbind20_press" "toggle cl_capturevideo"; seta "userbind20_release" ""; seta "userbind20_description" "toggle recording .avi"
- seta "userbind21_press" "toggle vid_fullscreen; vid_restart"; seta "userbind21_release" ""; seta "userbind21_description" "toggle fullscreen"
- seta "userbind22_press" ""; seta "userbind22_release" ""; seta "userbind22_description" ""
- seta "userbind23_press" ""; seta "userbind23_release" ""; seta "userbind23_description" ""
- seta "userbind24_press" ""; seta "userbind24_release" ""; seta "userbind24_description" ""
- seta "userbind25_press" ""; seta "userbind25_release" ""; seta "userbind25_description" ""
- seta "userbind26_press" ""; seta "userbind26_release" ""; seta "userbind26_description" ""
- seta "userbind27_press" ""; seta "userbind27_release" ""; seta "userbind27_description" ""
- seta "userbind28_press" ""; seta "userbind28_release" ""; seta "userbind28_description" ""
- seta "userbind29_press" ""; seta "userbind29_release" ""; seta "userbind29_description" ""
- seta "userbind30_press" ""; seta "userbind30_release" ""; seta "userbind30_description" ""
- seta "userbind31_press" ""; seta "userbind31_release" ""; seta "userbind31_description" ""
- seta "userbind32_press" ""; seta "userbind32_release" ""; seta "userbind32_description" ""
- alias _userbind_call "${$1}"
- alias +userbind "_userbind_call userbind${1}_press"
- alias -userbind "_userbind_call userbind${1}_release"
+ exec binds-default.cfg
// we must change its default from 1.0 to 1 to be consistent with menuqc
set slowmo 1
seta scoreboard_accuracy_doublerows 0 "use two rows instead of one"
seta scoreboard_accuracy_nocolors 0 "don't use colors displaying accuracy stats"
seta scoreboard_accuracy 1 "show weapon accuracy stats panel on scoreboard; colors can be configured with accuracy_color* cvars"
- seta scoreboard_color_bg_r 0 "red color component of the scoreboard background"
- seta scoreboard_color_bg_g 0.4 "green color component of the scoreboard background"
- seta scoreboard_color_bg_b 0.6 "blue color component of the scoreboard background"
- seta scoreboard_color_bg_team 0.5 "team color multiplier of the scoreboard background"
- seta scoreboard_alpha_bg 0.6 "scoreboard background alpha"
+ seta scoreboard_color_bg_r 0.125 "red color component of the scoreboard background"
+ seta scoreboard_color_bg_g 0.55 "green color component of the scoreboard background"
+ seta scoreboard_color_bg_b 0.875 "blue color component of the scoreboard background"
+ seta scoreboard_color_bg_team 0.6 "team color multiplier of the scoreboard background"
+ seta scoreboard_alpha_bg 0.7 "scoreboard background alpha"
seta scoreboard_alpha_fg 1 "scoreboard foreground alpha"
seta scoreboard_alpha_name 0.9 "alpha of player text in scoreboard list other than self"
seta scoreboard_alpha_name_self 1 "alpha of player text in scoreboard list of self"
seta scoreboard_fadeinspeed 10 "speed at which scoreboard fades in, higher is faster (0 = instant)"
seta scoreboard_fadeoutspeed 5 "speed at which scoreboard fades out, higher is faster (0 = instant)"
seta scoreboard_highlight 1 "enable highlighting for rows and columns in the scoreboard"
- seta scoreboard_highlight_alpha 0.10 "highlight alpha value (depends on hud_scoreboard_highlight 1)"
- seta scoreboard_highlight_alpha_self 0.25 "self highlight alpha value"
+ seta scoreboard_highlight_alpha 0.08 "highlight alpha value (depends on hud_scoreboard_highlight 1)"
+ seta scoreboard_highlight_alpha_self 0.3 "self highlight alpha value"
seta scoreboard_offset_left 0.15 "how far (by percent) the scoreboard is offset from the left screen edge"
seta scoreboard_offset_right 0.15 "how far (by percent) the scoreboard is offset from the right screen edge"
seta scoreboard_offset_vertical 0.05 "how far (by percent) the scoreboard is offset from the top and bottom of the screen"
seta menu_slist_categories_CAT_XPM_override "CAT_NORMAL"
seta menu_slist_categories_CAT_MODIFIED_override ""
seta menu_slist_categories_CAT_OVERKILL_override ""
- seta menu_slist_categories_CAT_MINSTAGIB_override ""
+ seta menu_slist_categories_CAT_INSTAGIB_override ""
seta menu_slist_categories_CAT_DEFRAG_override ""
seta menu_weaponarena ""
set con_completion_vmap map
set con_completion_vnextmap map
set con_completion_vdomap map
- set con_completion_playermodel models/player/*.iqm
+ set con_completion_playermodel "models/player/*.iqm"
// helper
// these non-saved engine cvars shall be saved
makesaved vid_gl20
makesaved v_idlescale
makesaved v_kicktime
+ makesaved music_playlist_list0
+ makesaved music_playlist_random0
// ticrate
//sys_ticrate 0.0166667 // 60fps. This would be ideal, but kills home routers.
set sv_intermission_cdtrack ""
set g_cdtracks_dontusebydefault "rising-of-the-phoenix"
- set menu_cdtrack "rising-of-the-phoenix"
+ seta menu_cdtrack "rising-of-the-phoenix"
set sv_maxidle 0 "kick players idle for more than this amount of time in seconds"
set sv_maxidle_spectatorsareidle 0 "when sv_maxidle is not 0, assume spectators are idle too"
set g_jump_grunt 0 "Do you make a grunting noise every time you jump? Is it the same grunting noise every time?"
- seta cl_weaponpriority "minstanex nex fireball grenadelauncher uzi hagar rifle electro rocketlauncher crylink minelayer shotgun hlac tuba laser porto seeker hook" "weapon priority list"
+ seta cl_weaponpriority "vaporizer vortex fireball mortar machinegun hagar rifle arc electro devastator crylink minelayer shotgun hlac tuba blaster porto seeker hook" "weapon priority list"
seta cl_weaponpriority_useforcycling 0 "when set, weapon cycling by the mouse wheel makes use of the weapon priority list (the special value 2 uses the weapon ID list for cycling)"
- seta cl_weaponpriority0 "rocketlauncher grenadelauncher hagar seeker fireball" "use impulse 200 for prev gun from this list, 210 for best gun, 220 for next gun. Default value: explosives"
- seta cl_weaponpriority1 "minstanex nex crylink hlac electro laser" "use impulse 201 for prev gun from this list, 211 for best gun, 221 for next gun. Default value: energy"
- seta cl_weaponpriority2 "minstanex nex rifle" "use impulse 202 for prev gun from this list, 212 for best gun, 222 for next gun. Default value: hitscan exact"
- seta cl_weaponpriority3 "minstanex nex rifle uzi shotgun" "use impulse 203 for prev gun from this list, 213 for best gun, 223 for next gun. Default value: hitscan all"
- seta cl_weaponpriority4 "grenadelauncher minelayer hlac hagar crylink seeker shotgun" "use impulse 204 for prev gun from this list, 214 for best gun, 224 for next gun. Default value: spam weapons"
- seta cl_weaponpriority5 "laser hook porto" "use impulse 205 for prev gun from this list, 215 for best gun, 225 for next gun. Default value: weapons for moving"
+ seta cl_weaponpriority0 "devastator mortar hagar seeker fireball" "use impulse 200 for prev gun from this list, 210 for best gun, 220 for next gun. Default value: explosives"
+ seta cl_weaponpriority1 "vaporizer vortex crylink hlac arc electro blaster shockwave" "use impulse 201 for prev gun from this list, 211 for best gun, 221 for next gun. Default value: energy"
+ seta cl_weaponpriority2 "vaporizer vortex rifle" "use impulse 202 for prev gun from this list, 212 for best gun, 222 for next gun. Default value: hitscan exact"
+ seta cl_weaponpriority3 "vaporizer vortex rifle machinegun shotgun" "use impulse 203 for prev gun from this list, 213 for best gun, 223 for next gun. Default value: hitscan all"
+ seta cl_weaponpriority4 "mortar minelayer hlac hagar crylink seeker shotgun" "use impulse 204 for prev gun from this list, 214 for best gun, 224 for next gun. Default value: spam weapons"
+ seta cl_weaponpriority5 "blaster shockwave hook porto" "use impulse 205 for prev gun from this list, 215 for best gun, 225 for next gun. Default value: weapons for moving"
seta cl_weaponpriority6 "" "use impulse 206 for prev gun from this list, 216 for best gun, 226 for next gun"
seta cl_weaponpriority7 "" "use impulse 207 for prev gun from this list, 217 for best gun, 227 for next gun"
seta cl_weaponpriority8 "" "use impulse 208 for prev gun from this list, 218 for best gun, 228 for next gun"
seta cl_autoscreenshot 1 "Take a screenshot upon the end of a match... 0 = Disable completely, 1 = Allow sv_autoscreenshot to take a screenshot when requested, 2 = Always take an autoscreenshot anyway."
+ seta cl_jetpack_jump 1 "Activate jetpack by pressing jump in the air. 0 = Disable, 1 = Stop when touching ground, 2 = Enable"
+
// must be at the bottom of this file:
- // alias for switching the teamselect menu
- bind f5 menu_showteamselect
set g_bugrigs 0
set g_bugrigs_planar_movement 1 "BROTRR bug emulation"
seta cl_gentle_messages 0 "client side gentle mode (only replaces frag messages/centerprints)"
seta cl_gentle_damage 0 "client side gentle mode (only replaces damage flash); when set to 1, a white flash replaces the blood image, when set to 2, a randomily colored flash is used instead"
- set g_jetpack 0 "Jetpack mutator (uses the hook's button, can't coexist with the offhand hook, but only with the onhand one)"
+ set g_jetpack 0 "Jetpack mutator"
set g_running_guns 0 "... or wonder, till it drives you mad, what would have followed if you had."
set g_bastet 0 "don't try"
set cl_loddistance1 1024
set cl_loddistance2 3072
- seta cl_playerdetailreduction 1 "the higher, the less detailed player models are displayed (LOD)"
+ seta cl_playerdetailreduction 4 "the higher, the less detailed player models are displayed (LOD)"
seta cl_modeldetailreduction 1 "the higher, the less detailed certain map models are displayed (LOD)"
set g_mapinfo_settemp_acl "+*" "ACL for mapinfo setting cvars"
set cl_accuracy_data_share 0 "1 share my weapon accuracy data statistics with other players, 0 keep my weapon accuracy data statistics hidden"
set cl_accuracy_data_receive 0 "1 receive weapon accuracy data statistics at the end of the match"
- set developer_fteqccbugs 0 "check fteqcc bugs on startup"
- set _allow_unacceptable_compiler_bugs 0 "don't bail out if certain bugs are detected (HANDLE WITH CARE)"
set spawn_debug 0 "use all spawns one by one, then abort, to verify all spawnpoints"
set loddebug 0 "force this LOD level"
set spawn_debugview 0 "display spawnpoints and their rating on spawn to debug spawnpoint rating calculation"
// sucks less than the old one
cl_decals_newsystem 1
- // NOTE: this only replaces weapons on the map
- // use g_start_weapon_* to also replace the on-startup weapons!
- // example: g_weaponreplace_nex "nex minstanex", then Nexes become MinstaNexes 50% of the times
- // set the cvars to "0" to totally disable a weapon
- set g_weaponreplace_laser ""
- set g_weaponreplace_shotgun ""
- set g_weaponreplace_uzi ""
- set g_weaponreplace_grenadelauncher ""
- set g_weaponreplace_electro ""
- set g_weaponreplace_crylink ""
- set g_weaponreplace_nex ""
- set g_weaponreplace_hagar ""
- set g_weaponreplace_rocketlauncher ""
- set g_weaponreplace_porto ""
- set g_weaponreplace_minstanex ""
- set g_weaponreplace_hook ""
- set g_weaponreplace_tuba ""
- set g_weaponreplace_fireball ""
- set sv_q3acompat_machineshotgunswap 0 "shorthand for swapping uzi and shotgun (for Q3A map compatibility in mapinfo files)"
+ set sv_q3acompat_machineshotgunswap 0 "shorthand for swapping machinegun and shotgun (for Q3A map compatibility in mapinfo files)"
set g_movement_highspeed 1 "movement speed modification factor (only changes movement when above maxspeed)"
r_fakelight 1
r_water_hideplayer 1 // hide your own feet/player model in refraction views, this way you don't see half of your body under water
+ r_water_refractdistort 0.019
// strength sound settings
set sv_strengthsound_antispam_time 0.1 "minimum distance of strength sounds"
scr_loadingscreen_scale_limit 2
// other config files
- exec mutator_new_toys.cfg // run BEFORE balance to make sure balance wins
- exec balanceXonotic.cfg
+ exec balance-xonotic.cfg
exec effects-normal.cfg
exec physicsX.cfg
exec turrets.cfg
// =================
// gamestart hooks
// =================
+ seta cl_matchcount 0 // incremented by cl_hook_gameend and used by playerstats to know when to
alias _cl_hook_gamestart "set _cl_hook_gametype $1; _cl_hook_gamestart_stage2"
alias _cl_hook_gamestart_stage2 "cl_hook_gamestart_all; cl_hook_gamestart_${_cl_hook_gametype}"
alias cl_hook_gamestart_all
alias cl_hook_gamestart_ka
alias cl_hook_gamestart_ft
alias cl_hook_gamestart_inv
- alias cl_hook_gameend
+ alias cl_hook_gameend "rpn /cl_matchcount dup load 1 + =" // increase match count every time a game ends
alias cl_hook_activeweapon
alias _sv_hook_gamestart "set _sv_hook_gametype $1; _sv_hook_gamestart_stage2"
alias sv_hook_gameend
+ // =====================
+ // gametype vote hooks
+ // =====================
+ // these are called when the mode is switched via gametype vote screen, earlier than gamestart hooks (useful for enabling per-gamemode mutators)
+ alias sv_vote_gametype_hook_all
+ alias sv_vote_gametype_hook_as
+ alias sv_vote_gametype_hook_ca
+ alias sv_vote_gametype_hook_ctf
+ alias sv_vote_gametype_hook_cts
+ alias sv_vote_gametype_hook_dm
+ alias sv_vote_gametype_hook_dom
+ alias sv_vote_gametype_hook_ft
+ alias sv_vote_gametype_hook_inv
+ alias sv_vote_gametype_hook_ka
+ alias sv_vote_gametype_hook_kh
+ alias sv_vote_gametype_hook_lms
+ alias sv_vote_gametype_hook_nb
+ alias sv_vote_gametype_hook_ons
+ alias sv_vote_gametype_hook_rc
+ alias sv_vote_gametype_hook_tdm
+
+
// ===========
// leadlimit
// ===========
// ============
// clan arena
// ============
- set g_ca 0 "Clan Arena: Played in rounds, once you're dead you're out! The team with survivors wins the round."
- set g_ca_point_limit 10 "point limit 10 is standard for clan arena"
- set g_ca_point_leadlimit 0
- set g_ca_spectate_enemies 0 "Allow spectating enemy player by dead player during clan arena games."
+ set g_ca 0 "Clan Arena: Played in rounds, once you're dead you're out! The team with survivors wins the round"
+ seta g_ca_point_limit -1 "Clan Arena point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+ seta g_ca_point_leadlimit -1 "Clan Arena point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+ set g_ca_spectate_enemies 0 "Allow spectating enemy player by dead player during clan arena games"
set g_ca_warmup 10 "how long the players will have time to run around the map before the round starts"
set g_ca_damage2score_multiplier 0.01
set g_ca_round_timelimit 180 "round time limit in seconds"
set g_tdm_teams 2 "how many teams are in team deathmatch (set by mapinfo)"
set g_tdm_team_spawns 0 "when 1, players spawn from the team spawnpoints of the map, if any"
seta g_tdm_teams_override 0 "how many teams are in team deathmatch"
+ set g_tdm_point_limit -1 "TDM point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+ set g_tdm_point_leadlimit -1 "TDM point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
// ============
set g_domination_point_rate 0 "override: how often to give those points"
set g_domination_point_capturetime 0.1 "how long it takes to capture a point (given no interference)"
set g_domination_point_glow 0 "domination point glow (warning, slow)"
+ set g_domination_roundbased 0 "enable round-based domination (capture all control points to win the round)"
+ set g_domination_roundbased_point_limit 5 "capture limit in round-based domination mode"
+ set g_domination_round_timelimit 120
+ set g_domination_warmup 5
//set g_domination_balance_team_points 1 "# of points received is based on team sizes"
set g_freezetag_revive_speed 0.4 "Speed for reviving a frozen teammate"
set g_freezetag_revive_clearspeed 1.6 "Speed at which reviving progress gets lost when out of range"
set g_freezetag_revive_extra_size 100 "Distance in qu that you can stand from a frozen teammate to keep reviving him"
+ set g_freezetag_revive_nade 1 "Enable reviving from own nade explosion"
+ set g_freezetag_revive_nade_health 40 "Amount of health player has if they revived from their own nade explosion"
set g_freezetag_revive_falldamage 0 "Enable reviving from this amount of fall damage"
set g_freezetag_revive_falldamage_health 40 "Amount of health player has if they revived from falling"
set g_freezetag_round_timelimit 180 "round time limit in seconds"
+ set g_freezetag_frozen_damage_trigger 1 "if 1, frozen players falling into the void will die instead of teleporting to spawn"
set g_freezetag_frozen_force 0.6 "How much to multiply the force on a frozen player with"
set g_freezetag_frozen_maxtime 60 "frozen players will be automatically unfrozen after this time in seconds"
seta g_freezetag_teams_override 0
// onslaught
// ===========
set g_onslaught 0 "Onslaught: take control points towards the enemy generator and then destroy it"
+set g_onslaught_point_limit 1 "Onslaught point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
+set g_onslaught_warmup 5
+set g_onslaught_round_timelimit 280
+set g_onslaught_debug 0 "show debug prints in onslaught"
+set g_onslaught_teleport_radius 200 "Allows teleporting from a control point to another"
+set g_onslaught_teleport_wait 5 "Time before player can teleport again"
+set g_onslaught_spawn_choose 1 "Allow players to choose the control point to be spawned at"
+set g_onslaught_click_radius 500 "When choosing from the map, this level of precision is required"
+
set g_onslaught_gen_health 2500
+set g_onslaught_allow_vehicle_touch 0
set g_onslaught_cp_health 1000
set g_onslaught_cp_buildhealth 100
set g_onslaught_cp_buildtime 5
set g_onslaught_cp_proxydecap 0 "de-capture controlpoints by standing close to them"
set g_onslaught_cp_proxydecap_distance 512
set g_onslaught_cp_proxydecap_dps 100
+set g_onslaught_shield_force 100
set g_onslaught_spawn_at_controlpoints 0
+set g_onslaught_spawn_at_controlpoints_chance 0.5
+set g_onslaught_spawn_at_controlpoints_random 0
set g_onslaught_spawn_at_generator 0
+set g_onslaught_spawn_at_generator_chance 0
+set g_onslaught_spawn_at_generator_random 0
// ======
{
}
- #ifdef USE_FTE
- float __engine_check;
- #endif
-
string forcefog;
void WaypointSprite_Load();
void ConsoleCommand_macro_init();
void CSQC_Init(void)
{
prvm_language = cvar_string("prvm_language");
- #ifdef USE_FTE
- #pragma target ID
- __engine_check = checkextension("DP_SV_WRITEPICTURE");
- if(!__engine_check)
- {
- print(_("^3Your engine build is outdated\n^3This Server uses a newer QC VM. Please update!\n"));
- localcmd("\ndisconnect\n");
- return;
- }
- #pragma target FTE
- #endif
-
- check_unacceptable_compiler_bugs();
#ifdef WATERMARK
- printf(_("^4CSQC Build information: ^1%s\n"), WATERMARK);
+ dprintf("^4CSQC Build information: ^1%s\n", WATERMARK);
#endif
float i;
- #ifdef COMPAT_XON050_ENGINE
- // old engine lacks implementation of player_localnum
- player_localnum = player_localentnum - 1;
- #endif
-
binddb = db_create();
tempdb = db_create();
ClientProgsDB = db_load("client.db");
registercvar("hud_usecsqc", "1");
registercvar("scoreboard_columns", "default");
+ registercvar("cl_nade_type", "3");
+ registercvar("cl_pokenade_type", "zombie");
+
gametype = 0;
// hud_fields uses strunzone on the titles!
for(i = 0; i < MAX_HUD_FIELDS; ++i)
hud_title[i] = strzone("(null)");
+ Cmd_HUD_SetFields(0);
+
postinit = false;
calledhooks = 0;
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
CALL_ACCUMULATED_FUNCTION(RegisterHUD_Panels);
+ CALL_ACCUMULATED_FUNCTION(RegisterBuffs);
WaypointSprite_Load();
precache_sound("misc/hit.wav");
precache_sound("misc/typehit.wav");
+ generator_precache();
Projectile_Precache();
Hook_Precache();
GibSplash_Precache();
Casings_Precache();
- DamageInfo_Precache();
Vehicles_Precache();
turrets_precache();
Tuba_Precache();
if(autocvar_cl_reticle)
{
- if(autocvar_cl_reticle_item_normal) { precache_pic("gfx/reticle_normal"); }
- if(autocvar_cl_reticle_item_nex) { precache_pic("gfx/reticle_nex"); }
+ precache_pic("gfx/reticle_normal");
+ // weapon reticles are precached in weapon files
}
get_mi_min_max_texcoords(1); // try the CLEVER way first
// CSQC_Shutdown : Called every time the CSQC code is shutdown (changing maps, quitting, etc)
void Shutdown(void)
{
- #ifdef USE_FTE
- #pragma TARGET id
- if(!__engine_check)
- return 0;
- #pragma TARGET fte
- #endif
-
WarpZone_Shutdown();
remove(teams);
void TrueAim_Init();
void PostInit(void)
{
- localcmd(strcat("\nscoreboard_columns_set ", autocvar_scoreboard_columns, ";\n"));
-
entity playerchecker;
playerchecker = spawn();
playerchecker.think = Playerchecker_Think;
if (HUD_Panel_InputEvent(bInputType, nPrimary, nSecondary))
return true;
+ if ( HUD_Radar_InputEvent(bInputType, nPrimary, nSecondary) )
+ return true;
+
if (MapVote_InputEvent(bInputType, nPrimary, nSecondary))
return true;
}
spectatee_status = newspectatee_status;
- // non-COMPAT_XON050_ENGINE: we could get rid of spectatee_status, and derive it from player_localentnum and player_localnum
+ // we could get rid of spectatee_status, and derive it from player_localentnum and player_localnum
}
void Ent_Nagger()
warmup_stage = (nags & 16);
}
+ void Ent_EliminatedPlayers()
+ {
+ float sf, i, j, b, f;
+
+ sf = ReadByte();
+ if(sf & 1)
+ {
+ for(j = 0; j < maxclients; ++j)
+ if(playerslots[j])
+ playerslots[j].eliminated = 1;
+ for(i = 1; i <= maxclients; i += 8)
+ {
+ f = ReadByte();
+ for(j = i-1, b = 1; b < 256; b *= 2, ++j)
+ if (!(f & b))
+ if(playerslots[j])
+ playerslots[j].eliminated = 0;
+ }
+ }
+ }
+
void Ent_RandomSeed()
{
float s;
button_zoom = FALSE;
}
}
-
+ HUD_Radar_Hide_Maximized();
//printf("Ent_ReadSpawnEvent(is_new = %d); origin = %s, entnum = %d, localentnum = %d\n", is_new, vtos(self.origin), entnum, player_localentnum);
}
case ENT_CLIENT_RAINSNOW: Ent_RainOrSnow(); break;
case ENT_CLIENT_LASER: Ent_Laser(); break;
case ENT_CLIENT_NAGGER: Ent_Nagger(); break;
+ case ENT_CLIENT_ELIMINATEDPLAYERS: Ent_EliminatedPlayers(); break;
case ENT_CLIENT_WAYPOINT: Ent_WaypointSprite(); break;
case ENT_CLIENT_RADARLINK: Ent_RadarLink(); break;
case ENT_CLIENT_PROJECTILE: Ent_Projectile(); break;
case ENT_CLIENT_WARPZONE_TELEPORTED: WarpZone_Teleported_Read(bIsNewEntity); break;
case ENT_CLIENT_TRIGGER_MUSIC: Ent_ReadTriggerMusic(); break;
case ENT_CLIENT_HOOK: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_HOOK); break;
- case ENT_CLIENT_LGBEAM: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_LGBEAM); break;
- case ENT_CLIENT_GAUNTLET: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_GAUNTLET); break;
+ case ENT_CLIENT_ARC_BEAM: Ent_ReadArcBeam(bIsNewEntity); break;
case ENT_CLIENT_ACCURACY: Ent_ReadAccuracy(); break;
case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break;
case ENT_CLIENT_TURRET: ent_turret(); break;
+ case ENT_CLIENT_GENERATOR: ent_generator(); break;
+ case ENT_CLIENT_CONTROLPOINT_ICON: ent_cpicon(); break;
case ENT_CLIENT_MODEL: CSQCModel_Read(bIsNewEntity); break;
case ENT_CLIENT_ITEM: ItemRead(bIsNewEntity); break;
case ENT_CLIENT_BUMBLE_RAYGUN: bumble_raygun_read(bIsNewEntity); break;
case ENT_CLIENT_SPAWNPOINT: Ent_ReadSpawnPoint(bIsNewEntity); break;
case ENT_CLIENT_SPAWNEVENT: Ent_ReadSpawnEvent(bIsNewEntity); break;
case ENT_CLIENT_NOTIFICATION: Read_Notification(bIsNewEntity); break;
+ case ENT_CLIENT_HEALING_ORB: ent_healer(); break;
default:
//error(strcat(_("unknown entity type in CSQC_Ent_Update: %d\n"), self.enttype));
- error(sprintf(_("Unknown entity type in CSQC_Ent_Update (enttype: %d, edict: %d, classname: %s)\n"), self.enttype, num_for_edict(self), self.classname));
+ error(sprintf("Unknown entity type in CSQC_Ent_Update (enttype: %d, edict: %d, classname: %s)\n", self.enttype, num_for_edict(self), self.classname));
break;
}
HUD_ModIcons_SetFunc();
for(i = 0; i < MAX_SCORE; ++i)
{
+ if(scores_label[i])
+ strunzone(scores_label[i]);
scores_label[i] = strzone(ReadString());
scores_flags[i] = ReadByte();
}
for(i = 0; i < MAX_TEAMSCORE; ++i)
{
+ if(teamscores_label[i])
+ strunzone(teamscores_label[i]);
teamscores_label[i] = strzone(ReadString());
teamscores_flags[i] = ReadByte();
}
hook_shotorigin[1] = decompressShotOrigin(ReadInt24_t());
hook_shotorigin[2] = decompressShotOrigin(ReadInt24_t());
hook_shotorigin[3] = decompressShotOrigin(ReadInt24_t());
- electro_shotorigin[0] = decompressShotOrigin(ReadInt24_t());
- electro_shotorigin[1] = decompressShotOrigin(ReadInt24_t());
- electro_shotorigin[2] = decompressShotOrigin(ReadInt24_t());
- electro_shotorigin[3] = decompressShotOrigin(ReadInt24_t());
- gauntlet_shotorigin[0] = decompressShotOrigin(ReadInt24_t());
- gauntlet_shotorigin[1] = decompressShotOrigin(ReadInt24_t());
- gauntlet_shotorigin[2] = decompressShotOrigin(ReadInt24_t());
- gauntlet_shotorigin[3] = decompressShotOrigin(ReadInt24_t());
+ arc_shotorigin[0] = decompressShotOrigin(ReadInt24_t());
+ arc_shotorigin[1] = decompressShotOrigin(ReadInt24_t());
+ arc_shotorigin[2] = decompressShotOrigin(ReadInt24_t());
+ arc_shotorigin[3] = decompressShotOrigin(ReadInt24_t());
if(forcefog)
strunzone(forcefog);
armorblockpercent = ReadByte() / 255.0;
- g_balance_grenadelauncher_bouncefactor = ReadCoord();
- g_balance_grenadelauncher_bouncestop = ReadCoord();
+ g_balance_mortar_bouncefactor = ReadCoord();
+ g_balance_mortar_bouncestop = ReadCoord();
g_balance_electro_secondary_bouncefactor = ReadCoord();
g_balance_electro_secondary_bouncestop = ReadCoord();
- nex_scope = !ReadByte();
+ vortex_scope = !ReadByte();
rifle_scope = !ReadByte();
serverflags = ReadByte();
if(complain_weapon_name)
strunzone(complain_weapon_name);
- complain_weapon_name = strzone(ReadString());
+ complain_weapon_name = strzone(WEP_NAME(complain_weapon));
complain_weapon_type = ReadByte();
Net_ReadRace();
bHandled = true;
break;
- case TE_CSQC_NEXGUNBEAMPARTICLE:
- Net_ReadNexgunBeamParticle();
+ case TE_CSQC_VORTEXBEAMPARTICLE:
+ Net_ReadVortexBeamParticle();
bHandled = true;
break;
case TE_CSQC_TEAMNAGGER:
Net_TeamNagger();
bHandled = true;
break;
- case TE_CSQC_LIGHTNINGARC:
- Net_ReadLightningarc();
+ case TE_CSQC_ARC:
+ Net_ReadArc();
bHandled = true;
break;
case TE_CSQC_PINGPLREPORT:
cl_notice_read();
bHandled = true;
break;
+ case TE_CSQC_SHOCKWAVEPARTICLE:
+ Net_ReadShockwaveParticle();
+ bHandled = true;
+ break;
default:
// No special logic for this temporary entity; return 0 so the engine can handle it
bHandled = false;
return text;
}
else if (autocvar_hud_showbinds > 1)
- return sprintf(_("%s (%s)"), text, keys);
+ return sprintf("%s (%s)", text, keys);
else
return keys;
}
zoomdir = button_zoom;
if(hud == HUD_NORMAL)
- if((activeweapon == WEP_NEX && nex_scope) || (activeweapon == WEP_RIFLE && rifle_scope)) // do NOT use switchweapon here
+ if((activeweapon == WEP_VORTEX && vortex_scope) || (activeweapon == WEP_RIFLE && rifle_scope)) // do NOT use switchweapon here
zoomdir += button_attack2;
if(spectatee_status > 0 || isdemo())
{
else
setsensitivityscale(1);
- makevectors(view_angles);
-
- if(autocvar_cl_velocityzoom && autocvar_cl_velocityzoom_type) // _type = 0 disables velocity zoom too
+ if(autocvar_cl_velocityzoom_enabled && autocvar_cl_velocityzoom_type) // _type = 0 disables velocity zoom too
{
if(intermission) { curspeed = 0; }
else
{
+
+ makevectors(view_angles);
v = pmove_vel;
if(csqcplayer)
v = csqcplayer.velocity;
velocityzoom = bound(0, drawframetime / max(0.000000001, autocvar_cl_velocityzoom_time), 1); // speed at which the zoom adapts to player velocity
avgspeed = avgspeed * (1 - velocityzoom) + (curspeed / autocvar_cl_velocityzoom_speed) * velocityzoom;
- velocityzoom = exp(float2range11(avgspeed * -autocvar_cl_velocityzoom / 1) * 1);
+ velocityzoom = exp(float2range11(avgspeed * -autocvar_cl_velocityzoom_factor / 1) * 1);
//print(ftos(avgspeed), " avgspeed, ", ftos(curspeed), " curspeed, ", ftos(velocityzoom), " return\n"); // for debugging
}
float TrueAimCheck()
{
- float nudge = 1; // added to traceline target and subtracted from result
+ float nudge = 1; // added to traceline target and subtracted from result TOOD(divVerent): do we still need this? Doesn't the engine do this now for us?
vector vecs, trueaimpoint, w_shotorg;
vector mi, ma, dv;
float shottype;
ta = trueaim;
mv = MOVE_NOMONSTERS;
- switch(activeweapon)
+ switch(activeweapon) // WEAPONTODO
{
case WEP_TUBA: // no aim
case WEP_PORTO: // shoots from eye
case WEP_HOOK: // no trueaim
- case WEP_GRENADE_LAUNCHER: // toss curve
+ case WEP_MORTAR: // toss curve
return SHOTTYPE_HITWORLD;
- case WEP_NEX:
- case WEP_MINSTANEX:
+ case WEP_VORTEX:
+ case WEP_VAPORIZER:
mv = MOVE_NORMAL;
break;
case WEP_RIFLE:
return EnemyHitCheck();
}
break;
- case WEP_ROCKET_LAUNCHER: // projectile has a size!
+ case WEP_DEVASTATOR: // projectile has a size!
mi = '-3 -3 -3';
ma = '3 3 3';
break;
const float CAMERA_FREE = 1;
const float CAMERA_CHASE = 2;
float reticle_type;
+ string reticle_image;
string NextFrameCommand;
void CSQC_SPIDER_HUD();
void CSQC_RAPTOR_HUD();
#define MAX_TIME_DIFF 5
float pickup_crosshair_time, pickup_crosshair_size;
- float hit_time, typehit_time;
- float nextsound_hit_time, nextsound_typehit_time;
- float hitindication_crosshair_time, hitindication_crosshair_size;
- float use_nex_chargepool;
+ float hitindication_crosshair_size;
+ float use_vortex_chargepool;
float myhealth, myhealth_prev;
float myhealth_flash;
vector liquidcolor_prev;
float eventchase_current_distance;
+ float eventchase_running;
+ float WantEventchase()
+ {
+ if(autocvar_cl_orthoview)
+ return FALSE;
+ if(intermission)
+ return TRUE;
+ if(spectatee_status >= 0)
+ {
+ if(autocvar_cl_eventchase_nexball && gametype == MAPINFO_TYPE_NEXBALL && !(WepSet_GetFromStat() & WepSet_FromWeapon(WEP_PORTO)))
+ return TRUE;
+ if(autocvar_cl_eventchase_death && (getstati(STAT_HEALTH) <= 0))
+ {
+ if(autocvar_cl_eventchase_death == 2)
+ {
+ // don't stop eventchase once it's started (even if velocity changes afterwards)
+ if(self.velocity == '0 0 0' || eventchase_running)
+ return TRUE;
+ }
+ else return TRUE;
+ }
+ }
+ return FALSE;
+ }
vector damage_blurpostprocess, content_blurpostprocess;
float checkfail[16];
- float rainbow_last_flicker;
- vector rainbow_prev_color;
+ float unaccounted_damage = 0;
+ void UpdateDamage()
+ {
+ // accumulate damage with each stat update
+ static float damage_total_prev = 0;
+ float damage_total = getstati(STAT_DAMAGE_DEALT_TOTAL);
+ float unaccounted_damage_new = COMPARE_INCREASING(damage_total, damage_total_prev);
+ damage_total_prev = damage_total;
+
+ static float damage_dealt_time_prev = 0;
+ float damage_dealt_time = getstatf(STAT_HIT_TIME);
+ if (damage_dealt_time != damage_dealt_time_prev)
+ {
+ unaccounted_damage += unaccounted_damage_new;
+ dprint("dmg total: ", ftos(unaccounted_damage), " (+", ftos(unaccounted_damage_new), ")", "\n");
+ }
+ damage_dealt_time_prev = damage_dealt_time;
+
+ // prevent hitsound when switching spectatee
+ static float spectatee_status_prev = 0;
+ if (spectatee_status != spectatee_status_prev)
+ unaccounted_damage = 0;
+ spectatee_status_prev = spectatee_status;
+ }
+
+ void UpdateHitsound()
+ {
+ // varying sound pitch
+
+ static float hitsound_time_prev = 0;
+ // HACK: the only way to get the arc to sound consistent with pitch shift is to ignore cl_hitsound_antispam_time
+ float arc_hack = activeweapon == WEP_ARC && autocvar_cl_hitsound >= 2;
+ if (arc_hack || COMPARE_INCREASING(time, hitsound_time_prev) > autocvar_cl_hitsound_antispam_time)
+ {
+ if (autocvar_cl_hitsound && unaccounted_damage)
+ {
+ // customizable gradient function that crosses (0,a), (c,1) and asymptotically approaches b
+ float a = autocvar_cl_hitsound_max_pitch;
+ float b = autocvar_cl_hitsound_min_pitch;
+ float c = autocvar_cl_hitsound_nom_damage;
+ float x = unaccounted_damage;
+ float pitch_shift = (b*x*(a-1) + a*c*(1-b)) / (x*(a-1) + c*(1-b));
+
+ // if sound variation is disabled, set pitch_shift to 1
+ if (autocvar_cl_hitsound == 1)
+ pitch_shift = 1;
+
+ // if pitch shift is reversed, mirror in (max-min)/2 + min
+ if (autocvar_cl_hitsound == 3)
+ {
+ float mirror_value = (a-b)/2 + b;
+ pitch_shift = mirror_value + (mirror_value - pitch_shift);
+ }
+
+ dprint("dmg total (dmg): ", ftos(unaccounted_damage), " , pitch shift: ", ftos(pitch_shift), "\n");
+
+ // todo: avoid very long and very short sounds from wave stretching using different sound files? seems unnecessary
+ // todo: normalize sound pressure levels? seems unnecessary
+
+ sound7(world, CH_INFO, "misc/hit.wav", VOL_BASE, ATTN_NONE, pitch_shift * 100, 0);
+ }
+ unaccounted_damage = 0;
+ hitsound_time_prev = time;
+ }
+
+ static float typehit_time_prev = 0;
+ float typehit_time = getstatf(STAT_TYPEHIT_TIME);
+ if (COMPARE_INCREASING(typehit_time, typehit_time_prev) > autocvar_cl_hitsound_antispam_time)
+ {
+ sound(world, CH_INFO, "misc/typehit.wav", VOL_BASE, ATTN_NONE);
+ typehit_time_prev = typehit_time;
+ }
+ }
+
+ void UpdateCrosshair()
+ {
+ static float rainbow_last_flicker;
+ static vector rainbow_prev_color;
+ entity e = self;
+ float f, i, j;
+ vector v;
+ if(getstati(STAT_FROZEN))
+ drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, ((getstatf(STAT_REVIVE_PROGRESS)) ? ('0.25 0.90 1' + ('1 0 0' * getstatf(STAT_REVIVE_PROGRESS)) + ('0 1 1' * getstatf(STAT_REVIVE_PROGRESS) * -1)) : '0.25 0.90 1'), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
+ else if (getstatf(STAT_HEALING_ORB)>time)
+ drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, Nade_Color(NADE_TYPE_HEAL), autocvar_hud_colorflash_alpha*getstatf(STAT_HEALING_ORB_ALPHA), DRAWFLAG_ADDITIVE);
+ if(!intermission)
+ if(getstatf(STAT_NADE_TIMER) && autocvar_cl_nade_timer) // give nade top priority, as it's a matter of life and death
+ {
+ DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", getstatf(STAT_NADE_TIMER), '0.25 0.90 1' + ('1 0 0' * getstatf(STAT_NADE_TIMER)) - ('0 1 1' * getstatf(STAT_NADE_TIMER)), autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
+ drawstring_aspect(eY * 0.64 * vid_conheight, ((autocvar_cl_nade_timer == 2) ? _("Nade timer") : ""), eX * vid_conwidth + eY * 0.025 * vid_conheight, '1 1 1', 1, DRAWFLAG_NORMAL);
+ }
+ else if(getstatf(STAT_REVIVE_PROGRESS))
+ {
+ DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", getstatf(STAT_REVIVE_PROGRESS), '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
+ drawstring_aspect(eY * 0.64 * vid_conheight, _("Revival progress"), eX * vid_conwidth + eY * 0.025 * vid_conheight, '1 1 1', 1, DRAWFLAG_NORMAL);
+ }
+
+ if(autocvar_r_letterbox == 0)
+ if(autocvar_viewsize < 120)
+ CSQC_common_hud();
+
+ // crosshair goes VERY LAST
+ if(!scoreboard_active && !camera_active && intermission != 2 && spectatee_status != -1 && hud == HUD_NORMAL)
+ {
+ if (!autocvar_crosshair_enabled) // main toggle for crosshair rendering
+ return;
+
+ string wcross_style;
+ float wcross_alpha, wcross_resolution;
+ wcross_style = autocvar_crosshair;
+ if (wcross_style == "0")
+ return;
+ wcross_resolution = autocvar_crosshair_size;
+ if (wcross_resolution == 0)
+ return;
+ wcross_alpha = autocvar_crosshair_alpha;
+ if (wcross_alpha == 0)
+ return;
+
+ // TrueAim check
+ float shottype;
+
+ // wcross_origin = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
+ wcross_origin = project_3d_to_2d(view_origin + MAX_SHOT_DISTANCE * view_forward);
+ wcross_origin_z = 0;
+ if(autocvar_crosshair_hittest)
+ {
+ vector wcross_oldorigin;
+ wcross_oldorigin = wcross_origin;
+ shottype = TrueAimCheck();
+ if(shottype == SHOTTYPE_HITWORLD)
+ {
+ v = wcross_origin - wcross_oldorigin;
+ v_x /= vid_conwidth;
+ v_y /= vid_conheight;
+ if(vlen(v) > 0.01)
+ shottype = SHOTTYPE_HITOBSTRUCTION;
+ }
+ if(!autocvar_crosshair_hittest_showimpact)
+ wcross_origin = wcross_oldorigin;
+ }
+ else
+ shottype = SHOTTYPE_HITWORLD;
+
+ vector wcross_color = '0 0 0', wcross_size = '0 0 0';
+ string wcross_name = "";
+ float wcross_scale, wcross_blur;
+
+ if(autocvar_crosshair_per_weapon || (autocvar_crosshair_color_special == 1))
+ {
+ e = get_weaponinfo(switchingweapon);
+ if(e)
+ {
+ if(autocvar_crosshair_per_weapon)
+ {
+ // WEAPONTODO: access these through some general settings (with non-balance config settings)
+ //wcross_resolution *= cvar(strcat("crosshair_", wcross_wep, "_size"));
+ //if (wcross_resolution == 0)
+ //return;
+
+ //wcross_style = cvar_string(strcat("crosshair_", wcross_wep));
+ wcross_resolution *= e.w_crosshair_size;
+ wcross_name = e.w_crosshair;
+ }
+ }
+ }
+
+ if(wcross_name == "")
+ wcross_name = strcat("gfx/crosshair", wcross_style);
+
+ // MAIN CROSSHAIR COLOR DECISION
+ switch(autocvar_crosshair_color_special)
+ {
+ case 1: // crosshair_color_per_weapon
+ {
+ if(e)
+ {
+ wcross_color = e.wpcolor;
+ break;
+ }
+ else { goto normalcolor; }
+ }
+
+ case 2: // crosshair_color_by_health
+ {
+ float x = getstati(STAT_HEALTH);
+
+ //x = red
+ //y = green
+ //z = blue
+
+ wcross_color_z = 0;
+
+ if(x > 200)
+ {
+ wcross_color_x = 0;
+ wcross_color_y = 1;
+ }
+ else if(x > 150)
+ {
+ wcross_color_x = 0.4 - (x-150)*0.02 * 0.4;
+ wcross_color_y = 0.9 + (x-150)*0.02 * 0.1;
+ }
+ else if(x > 100)
+ {
+ wcross_color_x = 1 - (x-100)*0.02 * 0.6;
+ wcross_color_y = 1 - (x-100)*0.02 * 0.1;
+ wcross_color_z = 1 - (x-100)*0.02;
+ }
+ else if(x > 50)
+ {
+ wcross_color_x = 1;
+ wcross_color_y = 1;
+ wcross_color_z = 0.2 + (x-50)*0.02 * 0.8;
+ }
+ else if(x > 20)
+ {
+ wcross_color_x = 1;
+ wcross_color_y = (x-20)*90/27/100;
+ wcross_color_z = (x-20)*90/27/100 * 0.2;
+ }
+ else
+ {
+ wcross_color_x = 1;
+ wcross_color_y = 0;
+ }
+ break;
+ }
+
+ case 3: // crosshair_color_rainbow
+ {
+ if(time >= rainbow_last_flicker)
+ {
+ rainbow_prev_color = randomvec() * autocvar_crosshair_color_special_rainbow_brightness;
+ rainbow_last_flicker = time + autocvar_crosshair_color_special_rainbow_delay;
+ }
+ wcross_color = rainbow_prev_color;
+ break;
+ }
+ :normalcolor
+ default: { wcross_color = stov(autocvar_crosshair_color); break; }
+ }
+
+ if(autocvar_crosshair_effect_scalefade)
+ {
+ wcross_scale = wcross_resolution;
+ wcross_resolution = 1;
+ }
+ else
+ {
+ wcross_scale = 1;
+ }
+
+ if(autocvar_crosshair_pickup)
+ {
+ float stat_pickup_time = getstatf(STAT_LAST_PICKUP);
+
+ if(pickup_crosshair_time < stat_pickup_time)
+ {
+ if(time - stat_pickup_time < MAX_TIME_DIFF) // don't trigger the animation if it's too old
+ pickup_crosshair_size = 1;
+
+ pickup_crosshair_time = stat_pickup_time;
+ }
+
+ if(pickup_crosshair_size > 0)
+ pickup_crosshair_size -= autocvar_crosshair_pickup_speed * frametime;
+ else
+ pickup_crosshair_size = 0;
+
+ wcross_scale += sin(pickup_crosshair_size) * autocvar_crosshair_pickup;
+ }
+
+ // todo: make crosshair hit indication dependent on damage dealt
+ if(autocvar_crosshair_hitindication)
+ {
+ vector hitindication_color = ((autocvar_crosshair_color_special == 1) ? stov(autocvar_crosshair_hitindication_per_weapon_color) : stov(autocvar_crosshair_hitindication_color));
+
+ if(unaccounted_damage)
+ {
+ hitindication_crosshair_size = 1;
+ }
+
+ if(hitindication_crosshair_size > 0)
+ hitindication_crosshair_size -= autocvar_crosshair_hitindication_speed * frametime;
+ else
+ hitindication_crosshair_size = 0;
+
+ wcross_scale += sin(hitindication_crosshair_size) * autocvar_crosshair_hitindication;
+ wcross_color_x += sin(hitindication_crosshair_size) * hitindication_color_x;
+ wcross_color_y += sin(hitindication_crosshair_size) * hitindication_color_y;
+ wcross_color_z += sin(hitindication_crosshair_size) * hitindication_color_z;
+ }
+
+ if(shottype == SHOTTYPE_HITENEMY)
+ wcross_scale *= autocvar_crosshair_hittest; // is not queried if hittest is 0
+ if(shottype == SHOTTYPE_HITTEAM)
+ wcross_scale /= autocvar_crosshair_hittest; // is not queried if hittest is 0
+
+ f = fabs(autocvar_crosshair_effect_time);
+ if(wcross_scale != wcross_scale_goal_prev || wcross_alpha != wcross_alpha_goal_prev || wcross_color != wcross_color_goal_prev)
+ {
+ wcross_changedonetime = time + f;
+ }
+ if(wcross_name != wcross_name_goal_prev || wcross_resolution != wcross_resolution_goal_prev)
+ {
+ wcross_name_changestarttime = time;
+ wcross_name_changedonetime = time + f;
+ if(wcross_name_goal_prev_prev)
+ strunzone(wcross_name_goal_prev_prev);
+ wcross_name_goal_prev_prev = wcross_name_goal_prev;
+ wcross_name_goal_prev = strzone(wcross_name);
+ wcross_name_alpha_goal_prev_prev = wcross_name_alpha_goal_prev;
+ wcross_resolution_goal_prev_prev = wcross_resolution_goal_prev;
+ wcross_resolution_goal_prev = wcross_resolution;
+ }
+
+ wcross_scale_goal_prev = wcross_scale;
+ wcross_alpha_goal_prev = wcross_alpha;
+ wcross_color_goal_prev = wcross_color;
+
+ if(shottype == SHOTTYPE_HITTEAM || (shottype == SHOTTYPE_HITOBSTRUCTION && autocvar_crosshair_hittest_blur && !autocvar_chase_active))
+ {
+ wcross_blur = 1;
+ wcross_alpha *= 0.75;
+ }
+ else
+ wcross_blur = 0;
+ // *_prev is at time-frametime
+ // * is at wcross_changedonetime+f
+ // what do we have at time?
+ if(time < wcross_changedonetime)
+ {
+ f = frametime / (wcross_changedonetime - time + frametime);
+ wcross_scale = f * wcross_scale + (1 - f) * wcross_scale_prev;
+ wcross_alpha = f * wcross_alpha + (1 - f) * wcross_alpha_prev;
+ wcross_color = f * wcross_color + (1 - f) * wcross_color_prev;
+ }
+
+ wcross_scale_prev = wcross_scale;
+ wcross_alpha_prev = wcross_alpha;
+ wcross_color_prev = wcross_color;
+
+ wcross_scale *= 1 - autocvar__menu_alpha;
+ wcross_alpha *= 1 - autocvar__menu_alpha;
+ wcross_size = draw_getimagesize(wcross_name) * wcross_scale;
+
+ if(wcross_scale >= 0.001 && wcross_alpha >= 0.001)
+ {
+ // crosshair rings for weapon stats
+ if (autocvar_crosshair_ring || autocvar_crosshair_ring_reload)
+ {
+ // declarations and stats
+ float ring_value = 0, ring_scale = 0, ring_alpha = 0, ring_inner_value = 0, ring_inner_alpha = 0;
+ string ring_image = string_null, ring_inner_image = string_null;
+ vector ring_rgb = '0 0 0', ring_inner_rgb = '0 0 0';
+
+ ring_scale = autocvar_crosshair_ring_size;
+
+ float weapon_clipload, weapon_clipsize;
+ weapon_clipload = getstati(STAT_WEAPON_CLIPLOAD);
+ weapon_clipsize = getstati(STAT_WEAPON_CLIPSIZE);
+
+ float ok_ammo_charge, ok_ammo_chargepool;
+ ok_ammo_charge = getstatf(STAT_OK_AMMO_CHARGE);
+ ok_ammo_chargepool = getstatf(STAT_OK_AMMO_CHARGEPOOl);
+
+ float vortex_charge, vortex_chargepool;
+ vortex_charge = getstatf(STAT_VORTEX_CHARGE);
+ vortex_chargepool = getstatf(STAT_VORTEX_CHARGEPOOL);
+
+ float arc_heat = getstatf(STAT_ARC_HEAT);
+
+ if(vortex_charge_movingavg == 0) // this should only happen if we have just loaded up the game
+ vortex_charge_movingavg = vortex_charge;
+
+
+ // handle the values
+ if (autocvar_crosshair_ring && activeweapon == WEP_VORTEX && vortex_charge && autocvar_crosshair_ring_vortex) // ring around crosshair representing velocity-dependent damage for the vortex
+ {
+ if (vortex_chargepool || use_vortex_chargepool) {
+ use_vortex_chargepool = 1;
+ ring_inner_value = vortex_chargepool;
+ } else {
+ vortex_charge_movingavg = (1 - autocvar_crosshair_ring_vortex_currentcharge_movingavg_rate) * vortex_charge_movingavg + autocvar_crosshair_ring_vortex_currentcharge_movingavg_rate * vortex_charge;
+ ring_inner_value = bound(0, autocvar_crosshair_ring_vortex_currentcharge_scale * (vortex_charge - vortex_charge_movingavg), 1);
+ }
+
+ ring_inner_alpha = autocvar_crosshair_ring_vortex_inner_alpha;
+ ring_inner_rgb = eX * autocvar_crosshair_ring_vortex_inner_color_red + eY * autocvar_crosshair_ring_vortex_inner_color_green + eZ * autocvar_crosshair_ring_vortex_inner_color_blue;
+ ring_inner_image = "gfx/crosshair_ring_inner.tga";
+
+ // draw the outer ring to show the current charge of the weapon
+ ring_value = vortex_charge;
+ ring_alpha = autocvar_crosshair_ring_vortex_alpha;
+ ring_rgb = wcross_color;
+ ring_image = "gfx/crosshair_ring_nexgun.tga";
+ }
+ else if (autocvar_crosshair_ring && activeweapon == WEP_MINE_LAYER && minelayer_maxmines && autocvar_crosshair_ring_minelayer)
+ {
+ ring_value = bound(0, getstati(STAT_LAYED_MINES) / minelayer_maxmines, 1); // if you later need to use the count of bullets in another place, then add a float for it. For now, no need to.
+ ring_alpha = autocvar_crosshair_ring_minelayer_alpha;
+ ring_rgb = wcross_color;
+ ring_image = "gfx/crosshair_ring.tga";
+ }
+ else if (activeweapon == WEP_HAGAR && getstati(STAT_HAGAR_LOAD) && autocvar_crosshair_ring_hagar)
+ {
+ ring_value = bound(0, getstati(STAT_HAGAR_LOAD) / hagar_maxrockets, 1);
+ ring_alpha = autocvar_crosshair_ring_hagar_alpha;
+ ring_rgb = wcross_color;
+ ring_image = "gfx/crosshair_ring.tga";
+ }
+ else if (ok_ammo_charge)
+ {
+ ring_value = ok_ammo_chargepool;
+ ring_alpha = autocvar_crosshair_ring_reload_alpha;
+ ring_rgb = wcross_color;
+ ring_image = "gfx/crosshair_ring.tga";
+ }
+ else if(autocvar_crosshair_ring_reload && weapon_clipsize) // forces there to be only an ammo ring
+ {
+ ring_value = bound(0, weapon_clipload / weapon_clipsize, 1);
+ ring_scale = autocvar_crosshair_ring_reload_size;
+ ring_alpha = autocvar_crosshair_ring_reload_alpha;
+ ring_rgb = wcross_color;
+
+ // Note: This is to stop Taoki from complaining that the image doesn't match all potential balances.
+ // if a new image for another weapon is added, add the code (and its respective file/value) here
+ if ((activeweapon == WEP_RIFLE) && (weapon_clipsize == 80))
+ ring_image = "gfx/crosshair_ring_rifle.tga";
+ else
+ ring_image = "gfx/crosshair_ring.tga";
+ }
+ else if ( autocvar_crosshair_ring && autocvar_crosshair_ring_arc && arc_heat && activeweapon == WEP_ARC )
+ {
+ ring_value = arc_heat;
+ ring_alpha = (1-arc_heat)*autocvar_crosshair_ring_arc_cold_alpha +
+ arc_heat*autocvar_crosshair_ring_arc_hot_alpha;
+ ring_rgb = (1-arc_heat)*wcross_color + arc_heat*autocvar_crosshair_ring_arc_hot_color;
+ ring_image = "gfx/crosshair_ring.tga";
+ }
+
+ // if in weapon switch animation, fade ring out/in
+ if(autocvar_crosshair_effect_time > 0)
+ {
+ f = (time - wcross_name_changestarttime) / autocvar_crosshair_effect_time;
+ if (!(f < 1))
+ {
+ wcross_ring_prev = ((ring_image) ? TRUE : FALSE);
+ }
+
+ if(wcross_ring_prev)
+ {
+ if(f < 1)
+ ring_alpha *= fabs(1 - bound(0, f, 1));
+ }
+ else
+ {
+ if(f < 1)
+ ring_alpha *= bound(0, f, 1);
+ }
+ }
+
+ if (autocvar_crosshair_ring_inner && ring_inner_value) // lets draw a ring inside a ring so you can ring while you ring
+ DrawCircleClippedPic(wcross_origin, wcross_size_x * ring_scale, ring_inner_image, ring_inner_value, ring_inner_rgb, wcross_alpha * ring_inner_alpha, DRAWFLAG_ADDITIVE);
+
+ if (ring_value)
+ DrawCircleClippedPic(wcross_origin, wcross_size_x * ring_scale, ring_image, ring_value, ring_rgb, wcross_alpha * ring_alpha, DRAWFLAG_ADDITIVE);
+ }
+
+ #define CROSSHAIR_DO_BLUR(M,sz,wcross_name,wcross_alpha) \
+ do \
+ { \
+ if(wcross_blur > 0) \
+ { \
+ for(i = -2; i <= 2; ++i) \
+ for(j = -2; j <= 2; ++j) \
+ M(i,j,sz,wcross_name,wcross_alpha*0.04); \
+ } \
+ else \
+ { \
+ M(0,0,sz,wcross_name,wcross_alpha); \
+ } \
+ } \
+ while(0)
+
+ #define CROSSHAIR_DRAW_SINGLE(i,j,sz,wcross_name,wcross_alpha) \
+ drawpic(wcross_origin - ('0.5 0 0' * (sz * wcross_size_x + i * wcross_blur) + '0 0.5 0' * (sz * wcross_size_y + j * wcross_blur)), wcross_name, sz * wcross_size, wcross_color, wcross_alpha, DRAWFLAG_NORMAL)
+
+ #define CROSSHAIR_DRAW(sz,wcross_name,wcross_alpha) \
+ CROSSHAIR_DO_BLUR(CROSSHAIR_DRAW_SINGLE,sz,wcross_name,wcross_alpha)
+
+ if(time < wcross_name_changedonetime && wcross_name != wcross_name_goal_prev_prev && wcross_name_goal_prev_prev)
+ {
+ f = (wcross_name_changedonetime - time) / (wcross_name_changedonetime - wcross_name_changestarttime);
+ wcross_size = draw_getimagesize(wcross_name_goal_prev_prev) * wcross_scale;
+ CROSSHAIR_DRAW(wcross_resolution_goal_prev_prev, wcross_name_goal_prev_prev, wcross_alpha * f * wcross_name_alpha_goal_prev_prev);
+ f = 1 - f;
+ }
+ else
+ {
+ f = 1;
+ }
+ wcross_name_alpha_goal_prev = f;
+
+ wcross_size = draw_getimagesize(wcross_name) * wcross_scale;
+ CROSSHAIR_DRAW(wcross_resolution, wcross_name, wcross_alpha * f);
+
+ if(autocvar_crosshair_dot)
+ {
+ vector wcross_color_old;
+ wcross_color_old = wcross_color;
+
+ if((autocvar_crosshair_dot_color_custom) && (autocvar_crosshair_dot_color != "0"))
+ wcross_color = stov(autocvar_crosshair_dot_color);
+
+ CROSSHAIR_DRAW(wcross_resolution * autocvar_crosshair_dot_size, "gfx/crosshairdot.tga", f * autocvar_crosshair_dot_alpha);
+ // FIXME why don't we use wcross_alpha here?cl_notice_run();
+ wcross_color = wcross_color_old;
+ }
+ }
+ }
+ else
+ {
+ wcross_scale_prev = 0;
+ wcross_alpha_prev = 0;
+ wcross_scale_goal_prev = 0;
+ wcross_alpha_goal_prev = 0;
+ wcross_changedonetime = 0;
+ if(wcross_name_goal_prev)
+ strunzone(wcross_name_goal_prev);
+ wcross_name_goal_prev = string_null;
+ if(wcross_name_goal_prev_prev)
+ strunzone(wcross_name_goal_prev_prev);
+ wcross_name_goal_prev_prev = string_null;
+ wcross_name_changestarttime = 0;
+ wcross_name_changedonetime = 0;
+ wcross_name_alpha_goal_prev = 0;
+ wcross_name_alpha_goal_prev_prev = 0;
+ wcross_resolution_goal_prev = 0;
+ wcross_resolution_goal_prev_prev = 0;
+ }
+ }
#define BUTTON_3 4
#define BUTTON_4 8
float cl_notice_run();
float prev_myteam;
+.float health;
void CSQC_UpdateView(float w, float h)
{
entity e;
float fov;
- float f, i, j;
- vector v;
+ float f, i;
vector vf_size, vf_min;
float a;
CSQCPlayer_SetCamera();
- #ifdef COMPAT_XON050_ENGINE
- if(spectatee_status)
- myteam = GetPlayerColor(spectatee_status - 1);
- else
- #endif
- myteam = GetPlayerColor(player_localentnum - 1);
+ myteam = GetPlayerColor(player_localentnum - 1);
if(myteam != prev_myteam)
{
// event chase camera
if(autocvar_chase_active <= 0) // greater than 0 means it's enabled manually, and this code is skipped
{
- WepSet weapons_stat = WepSet_GetFromStat();
- if(WantEventchase())
+ float ons_roundlost = (gametype == MAPINFO_TYPE_ONSLAUGHT && getstati(STAT_ROUNDLOST));
+ entity gen = world;
+
+ if(ons_roundlost)
+ {
+ entity e;
+ for(e = world; (e = find(e, classname, "onslaught_generator")); )
+ {
+ if(e.health <= 0)
+ {
+ gen = e;
+ break;
+ }
+ }
+ if(!gen)
+ ons_roundlost = FALSE; // don't enforce the 3rd person camera if there is no dead generator to show
+ }
- if(((spectatee_status >= 0 && (autocvar_cl_eventchase_death && is_dead)) || intermission || ons_roundlost) && !autocvar_cl_orthoview || (autocvar_cl_eventchase_nexball && gametype == MAPINFO_TYPE_NEXBALL && !(weapons_stat & WepSet_FromWeapon(WEP_PORTO))))
++ if(WantEventchase() || (!autocvar_cl_orthoview && ons_roundlost))
{
+ eventchase_running = TRUE;
+
// make special vector since we can't use view_origin (It is one frame old as of this code, it gets set later with the results this code makes.)
vector current_view_origin = (csqcplayer ? csqcplayer.origin : pmove_org);
+ if(ons_roundlost) { current_view_origin = gen.origin; }
// detect maximum viewoffset and use it
- if(autocvar_cl_eventchase_viewoffset)
+ vector view_offset = autocvar_cl_eventchase_viewoffset;
+ if(ons_roundlost) { view_offset = autocvar_cl_eventchase_generator_viewoffset; }
+
+ if(view_offset)
{
- WarpZone_TraceLine(current_view_origin, current_view_origin + autocvar_cl_eventchase_viewoffset + ('0 0 1' * autocvar_cl_eventchase_maxs_z), MOVE_WORLDONLY, self);
- if(trace_fraction == 1) { current_view_origin += autocvar_cl_eventchase_viewoffset; }
+ WarpZone_TraceLine(current_view_origin, current_view_origin + view_offset + ('0 0 1' * autocvar_cl_eventchase_maxs_z), MOVE_WORLDONLY, self);
+ if(trace_fraction == 1) { current_view_origin += view_offset; }
else { current_view_origin_z += max(0, (trace_endpos_z - current_view_origin_z) - autocvar_cl_eventchase_maxs_z); }
}
if(!autocvar_chase_active) { cvar_set("chase_active", "-1"); }
// make the camera smooth back
- if(autocvar_cl_eventchase_speed && eventchase_current_distance < autocvar_cl_eventchase_distance)
- eventchase_current_distance += autocvar_cl_eventchase_speed * (autocvar_cl_eventchase_distance - eventchase_current_distance) * frametime; // slow down the further we get
- else if(eventchase_current_distance != autocvar_cl_eventchase_distance)
- eventchase_current_distance = autocvar_cl_eventchase_distance;
+ float chase_distance = autocvar_cl_eventchase_distance;
+ if(ons_roundlost) { chase_distance = autocvar_cl_eventchase_generator_distance; }
+
+ if(autocvar_cl_eventchase_speed && eventchase_current_distance < chase_distance)
+ eventchase_current_distance += autocvar_cl_eventchase_speed * (chase_distance - eventchase_current_distance) * frametime; // slow down the further we get
+ else if(eventchase_current_distance != chase_distance)
+ eventchase_current_distance = chase_distance;
makevectors(view_angles);
}
else if(autocvar_chase_active < 0) // time to disable chase_active if it was set by this code
{
+ eventchase_running = FALSE;
cvar_set("chase_active", "0");
eventchase_current_distance = 0; // start from 0 next time
}
// ALWAYS Clear Current Scene First
clearscene();
- #ifdef WORKAROUND_XON010
- if(checkextension("DP_CSQC_ROTATEMOVES"))
- {
- #endif
+
setproperty(VF_ORIGIN, view_origin);
setproperty(VF_ANGLES, view_angles);
- #ifdef WORKAROUND_XON010
- }
- #endif
// FIXME engine bug? VF_SIZE and VF_MIN are not restored to sensible values by this
setproperty(VF_SIZE, vf_size);
{
// apply night vision effect
vector tc_00, tc_01, tc_10, tc_11;
- vector rgb;
- rgb_x = 0; // fteqcc sucks
- rgb_y = 0; // fteqcc sucks
- rgb_z = 0; // fteqcc sucks
+ vector rgb = '0 0 0';
if(!nightvision_noise)
{
R_EndPolygon();
}
- // Draw the aiming reticle for weapons that use it
- // reticle_type is changed to the item we are zooming / aiming with, to decide which reticle to use
- // It must be a persisted float for fading out to work properly (you let go of the zoom button for
- // the view to go back to normal, so reticle_type would become 0 as we fade out)
- if(spectatee_status || is_dead || hud != HUD_NORMAL)
- reticle_type = 0; // prevent reticle from showing during the respawn zoom effect or for spectators
- else if((activeweapon == WEP_NEX || activeweapon == WEP_RIFLE || activeweapon == WEP_MINSTANEX) && (button_zoom || zoomscript_caught))
- reticle_type = 2; // nex zoom
- else if(button_zoom || zoomscript_caught)
- reticle_type = 1; // normal zoom
- else if((activeweapon == WEP_NEX) && button_attack2)
- reticle_type = 2; // nex zoom
-
- if(reticle_type && autocvar_cl_reticle)
+ if(autocvar_cl_reticle)
{
- if(autocvar_cl_reticle_stretch)
+ // Draw the aiming reticle for weapons that use it
+ // reticle_type is changed to the item we are zooming / aiming with, to decide which reticle to use
+ // It must be a persisted float for fading out to work properly (you let go of the zoom button for
+ // the view to go back to normal, so reticle_type would become 0 as we fade out)
+ if(spectatee_status || is_dead || hud != HUD_NORMAL)
{
- reticle_size_x = vid_conwidth;
- reticle_size_y = vid_conheight;
- reticle_pos_x = 0;
- reticle_pos_y = 0;
+ // no zoom reticle while dead
+ reticle_type = 0;
}
- else
+ else if(WEP_ACTION(activeweapon, WR_ZOOMRETICLE) && autocvar_cl_reticle_weapon)
{
- reticle_size_x = max(vid_conwidth, vid_conheight);
- reticle_size_y = max(vid_conwidth, vid_conheight);
- reticle_pos_x = (vid_conwidth - reticle_size_x) / 2;
- reticle_pos_y = (vid_conheight - reticle_size_y) / 2;
+ if(reticle_image != "") { reticle_type = 2; }
+ else { reticle_type = 0; }
}
-
- f = current_zoomfraction;
- if(zoomscript_caught)
- f = 1;
- if(autocvar_cl_reticle_item_normal)
+ else if(button_zoom || zoomscript_caught)
{
- if(reticle_type == 1 && f)
- drawpic(reticle_pos, "gfx/reticle_normal", reticle_size, '1 1 1', f * autocvar_cl_reticle_item_normal, DRAWFLAG_NORMAL);
+ // normal zoom
+ reticle_type = 1;
}
- if(autocvar_cl_reticle_item_nex)
+
+ if(reticle_type)
{
- if(reticle_type == 2 && f)
- drawpic(reticle_pos, "gfx/reticle_nex", reticle_size, '1 1 1', f * autocvar_cl_reticle_item_nex, DRAWFLAG_NORMAL);
+ if(autocvar_cl_reticle_stretch)
+ {
+ reticle_size_x = vid_conwidth;
+ reticle_size_y = vid_conheight;
+ reticle_pos_x = 0;
+ reticle_pos_y = 0;
+ }
+ else
+ {
+ reticle_size_x = max(vid_conwidth, vid_conheight);
+ reticle_size_y = max(vid_conwidth, vid_conheight);
+ reticle_pos_x = (vid_conwidth - reticle_size_x) / 2;
+ reticle_pos_y = (vid_conheight - reticle_size_y) / 2;
+ }
+
+ if(zoomscript_caught)
+ f = 1;
+ else
+ f = current_zoomfraction;
+
+ if(f)
+ {
+ switch(reticle_type)
+ {
+ case 1: drawpic(reticle_pos, "gfx/reticle_normal", reticle_size, '1 1 1', f * autocvar_cl_reticle_normal_alpha, DRAWFLAG_NORMAL); break;
+ case 2: drawpic(reticle_pos, reticle_image, reticle_size, '1 1 1', f * autocvar_cl_reticle_weapon_alpha, DRAWFLAG_NORMAL); break;
+ }
+ }
}
}
+ else
+ {
+ if(reticle_type != 0) { reticle_type = 0; }
+ }
// improved polyblend
scoreboard_active = HUD_WouldDrawScoreboard();
- hit_time = getstatf(STAT_HIT_TIME);
- if(hit_time > nextsound_hit_time && autocvar_cl_hitsound)
- {
- if(time - hit_time < MAX_TIME_DIFF) // don't play the sound if it's too old.
- sound(world, CH_INFO, "misc/hit.wav", VOL_BASE, ATTEN_NONE);
-
- nextsound_hit_time = time + autocvar_cl_hitsound_antispam_time;
- }
- typehit_time = getstatf(STAT_TYPEHIT_TIME);
- if(typehit_time > nextsound_typehit_time)
- {
- if(time - typehit_time < MAX_TIME_DIFF) // don't play the sound if it's too old.
- sound(world, CH_INFO, "misc/typehit.wav", VOL_BASE, ATTEN_NONE);
-
- nextsound_typehit_time = time + autocvar_cl_hitsound_antispam_time;
- }
-
- //else
- {
- if(gametype == MAPINFO_TYPE_FREEZETAG)
- {
- if(getstati(STAT_FROZEN))
- drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
- if(getstatf(STAT_REVIVE_PROGRESS))
- {
- DrawCircleClippedPic(eX * 0.5 * vid_conwidth + eY * 0.6 * vid_conheight, 0.1 * vid_conheight, "gfx/crosshair_ring.tga", getstatf(STAT_REVIVE_PROGRESS), '0.25 0.90 1', autocvar_hud_colorflash_alpha, DRAWFLAG_ADDITIVE);
- drawstring_aspect(eY * 0.64 * vid_conheight, _("Revival progress"), eX * vid_conwidth + eY * 0.025 * vid_conheight, '1 1 1', 1, DRAWFLAG_NORMAL);
- }
- }
-
- if(autocvar_r_letterbox == 0)
- if(autocvar_viewsize < 120)
- CSQC_common_hud();
-
- // crosshair goes VERY LAST
- if(!scoreboard_active && !camera_active && intermission != 2 && spectatee_status != -1 && hud == HUD_NORMAL)
- {
- if (!autocvar_crosshair_enabled) // main toggle for crosshair rendering
- return;
-
- string wcross_style;
- float wcross_alpha, wcross_resolution;
- wcross_style = autocvar_crosshair;
- if (wcross_style == "0")
- return;
- wcross_resolution = autocvar_crosshair_size;
- if (wcross_resolution == 0)
- return;
- wcross_alpha = autocvar_crosshair_alpha;
- if (wcross_alpha == 0)
- return;
-
- // TrueAim check
- float shottype;
-
- // wcross_origin = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
- wcross_origin = project_3d_to_2d(view_origin + MAX_SHOT_DISTANCE * view_forward);
- wcross_origin_z = 0;
- if(autocvar_crosshair_hittest)
- {
- vector wcross_oldorigin;
- wcross_oldorigin = wcross_origin;
- shottype = TrueAimCheck();
- if(shottype == SHOTTYPE_HITWORLD)
- {
- v = wcross_origin - wcross_oldorigin;
- v_x /= vid_conwidth;
- v_y /= vid_conheight;
- if(vlen(v) > 0.01)
- shottype = SHOTTYPE_HITOBSTRUCTION;
- }
- if(!autocvar_crosshair_hittest_showimpact)
- wcross_origin = wcross_oldorigin;
- }
- else
- shottype = SHOTTYPE_HITWORLD;
-
- vector wcross_color = '0 0 0', wcross_size = '0 0 0';
- string wcross_wep = "", wcross_name;
- float wcross_scale, wcross_blur;
-
- if (autocvar_crosshair_per_weapon || (autocvar_crosshair_color_special == 1))
- {
- e = get_weaponinfo(switchingweapon);
- if (e && e.netname != "")
- {
- wcross_wep = e.netname;
- if(autocvar_crosshair_per_weapon)
- {
- wcross_resolution *= cvar(strcat("crosshair_", wcross_wep, "_size"));
- if (wcross_resolution == 0)
- return;
- wcross_alpha *= cvar(strcat("crosshair_", wcross_wep, "_alpha"));
- if (wcross_alpha == 0)
- return;
-
- wcross_style = cvar_string(strcat("crosshair_", wcross_wep));
- if(wcross_style == "" || wcross_style == "0")
- wcross_style = wcross_wep;
- }
- }
- }
-
- //printf("crosshair style: %s\n", wcross_style);
- wcross_name = strcat("gfx/crosshair", wcross_style);
-
- // MAIN CROSSHAIR COLOR DECISION
- switch(autocvar_crosshair_color_special)
- {
- case 1: // crosshair_color_per_weapon
- {
- if(wcross_wep != "")
- {
- wcross_color = stov(cvar_string(sprintf("crosshair_%s_color", wcross_wep)));
- break;
- }
- else { goto normalcolor; }
- }
-
- case 2: // crosshair_color_by_health
- {
- float x = getstati(STAT_HEALTH);
-
- //x = red
- //y = green
- //z = blue
-
- wcross_color_z = 0;
-
- if(x > 200)
- {
- wcross_color_x = 0;
- wcross_color_y = 1;
- }
- else if(x > 150)
- {
- wcross_color_x = 0.4 - (x-150)*0.02 * 0.4;
- wcross_color_y = 0.9 + (x-150)*0.02 * 0.1;
- }
- else if(x > 100)
- {
- wcross_color_x = 1 - (x-100)*0.02 * 0.6;
- wcross_color_y = 1 - (x-100)*0.02 * 0.1;
- wcross_color_z = 1 - (x-100)*0.02;
- }
- else if(x > 50)
- {
- wcross_color_x = 1;
- wcross_color_y = 1;
- wcross_color_z = 0.2 + (x-50)*0.02 * 0.8;
- }
- else if(x > 20)
- {
- wcross_color_x = 1;
- wcross_color_y = (x-20)*90/27/100;
- wcross_color_z = (x-20)*90/27/100 * 0.2;
- }
- else
- {
- wcross_color_x = 1;
- wcross_color_y = 0;
- }
- break;
- }
-
- case 3: // crosshair_color_rainbow
- {
- if(time >= rainbow_last_flicker)
- {
- rainbow_prev_color = randomvec() * autocvar_crosshair_color_special_rainbow_brightness;
- rainbow_last_flicker = time + autocvar_crosshair_color_special_rainbow_delay;
- }
- wcross_color = rainbow_prev_color;
- break;
- }
- :normalcolor
- default: { wcross_color = stov(autocvar_crosshair_color); break; }
- }
-
- if(autocvar_crosshair_effect_scalefade)
- {
- wcross_scale = wcross_resolution;
- wcross_resolution = 1;
- }
- else
- {
- wcross_scale = 1;
- }
-
- if(autocvar_crosshair_pickup)
- {
- float stat_pickup_time = getstatf(STAT_LAST_PICKUP);
-
- if(pickup_crosshair_time < stat_pickup_time)
- {
- if(time - stat_pickup_time < MAX_TIME_DIFF) // don't trigger the animation if it's too old
- pickup_crosshair_size = 1;
-
- pickup_crosshair_time = stat_pickup_time;
- }
-
- if(pickup_crosshair_size > 0)
- pickup_crosshair_size -= autocvar_crosshair_pickup_speed * frametime;
- else
- pickup_crosshair_size = 0;
-
- wcross_scale += sin(pickup_crosshair_size) * autocvar_crosshair_pickup;
- }
-
- if(autocvar_crosshair_hitindication)
- {
- vector hitindication_color = ((autocvar_crosshair_color_special == 1) ? stov(autocvar_crosshair_hitindication_per_weapon_color) : stov(autocvar_crosshair_hitindication_color));
-
- if(hitindication_crosshair_time < hit_time)
- {
- if(time - hit_time < MAX_TIME_DIFF) // don't trigger the animation if it's too old
- hitindication_crosshair_size = 1;
-
- hitindication_crosshair_time = hit_time;
- }
-
- if(hitindication_crosshair_size > 0)
- hitindication_crosshair_size -= autocvar_crosshair_hitindication_speed * frametime;
- else
- hitindication_crosshair_size = 0;
-
- wcross_scale += sin(hitindication_crosshair_size) * autocvar_crosshair_hitindication;
- wcross_color_x += sin(hitindication_crosshair_size) * hitindication_color_x;
- wcross_color_y += sin(hitindication_crosshair_size) * hitindication_color_y;
- wcross_color_z += sin(hitindication_crosshair_size) * hitindication_color_z;
- }
-
- if(shottype == SHOTTYPE_HITENEMY)
- wcross_scale *= autocvar_crosshair_hittest; // is not queried if hittest is 0
- if(shottype == SHOTTYPE_HITTEAM)
- wcross_scale /= autocvar_crosshair_hittest; // is not queried if hittest is 0
-
- f = fabs(autocvar_crosshair_effect_time);
- if(wcross_scale != wcross_scale_goal_prev || wcross_alpha != wcross_alpha_goal_prev || wcross_color != wcross_color_goal_prev)
- {
- wcross_changedonetime = time + f;
- }
- if(wcross_name != wcross_name_goal_prev || wcross_resolution != wcross_resolution_goal_prev)
- {
- wcross_name_changestarttime = time;
- wcross_name_changedonetime = time + f;
- if(wcross_name_goal_prev_prev)
- strunzone(wcross_name_goal_prev_prev);
- wcross_name_goal_prev_prev = wcross_name_goal_prev;
- wcross_name_goal_prev = strzone(wcross_name);
- wcross_name_alpha_goal_prev_prev = wcross_name_alpha_goal_prev;
- wcross_resolution_goal_prev_prev = wcross_resolution_goal_prev;
- wcross_resolution_goal_prev = wcross_resolution;
- }
-
- wcross_scale_goal_prev = wcross_scale;
- wcross_alpha_goal_prev = wcross_alpha;
- wcross_color_goal_prev = wcross_color;
-
- if(shottype == SHOTTYPE_HITTEAM || (shottype == SHOTTYPE_HITOBSTRUCTION && autocvar_crosshair_hittest_blur && !autocvar_chase_active))
- {
- wcross_blur = 1;
- wcross_alpha *= 0.75;
- }
- else
- wcross_blur = 0;
- // *_prev is at time-frametime
- // * is at wcross_changedonetime+f
- // what do we have at time?
- if(time < wcross_changedonetime)
- {
- f = frametime / (wcross_changedonetime - time + frametime);
- wcross_scale = f * wcross_scale + (1 - f) * wcross_scale_prev;
- wcross_alpha = f * wcross_alpha + (1 - f) * wcross_alpha_prev;
- wcross_color = f * wcross_color + (1 - f) * wcross_color_prev;
- }
-
- wcross_scale_prev = wcross_scale;
- wcross_alpha_prev = wcross_alpha;
- wcross_color_prev = wcross_color;
-
- wcross_scale *= 1 - autocvar__menu_alpha;
- wcross_alpha *= 1 - autocvar__menu_alpha;
- wcross_size = draw_getimagesize(wcross_name) * wcross_scale;
-
- if(wcross_scale >= 0.001 && wcross_alpha >= 0.001)
- {
- // crosshair rings for weapon stats
- if (autocvar_crosshair_ring || autocvar_crosshair_ring_reload)
- {
- // declarations and stats
- float ring_value = 0, ring_scale = 0, ring_alpha = 0, ring_inner_value = 0, ring_inner_alpha = 0;
- string ring_image = string_null, ring_inner_image = string_null;
- vector ring_rgb = '0 0 0', ring_inner_rgb = '0 0 0';
-
- ring_scale = autocvar_crosshair_ring_size;
-
- float weapon_clipload, weapon_clipsize;
- weapon_clipload = getstati(STAT_WEAPON_CLIPLOAD);
- weapon_clipsize = getstati(STAT_WEAPON_CLIPSIZE);
-
- float nex_charge, nex_chargepool;
- nex_charge = getstatf(STAT_NEX_CHARGE);
- nex_chargepool = getstatf(STAT_NEX_CHARGEPOOL);
-
- if(nex_charge_movingavg == 0) // this should only happen if we have just loaded up the game
- nex_charge_movingavg = nex_charge;
-
-
- // handle the values
- if (autocvar_crosshair_ring && activeweapon == WEP_NEX && nex_charge && autocvar_crosshair_ring_nex) // ring around crosshair representing velocity-dependent damage for the nex
- {
- if (nex_chargepool || use_nex_chargepool) {
- use_nex_chargepool = 1;
- ring_inner_value = nex_chargepool;
- } else {
- nex_charge_movingavg = (1 - autocvar_crosshair_ring_nex_currentcharge_movingavg_rate) * nex_charge_movingavg + autocvar_crosshair_ring_nex_currentcharge_movingavg_rate * nex_charge;
- ring_inner_value = bound(0, autocvar_crosshair_ring_nex_currentcharge_scale * (nex_charge - nex_charge_movingavg), 1);
- }
-
- ring_inner_alpha = autocvar_crosshair_ring_nex_inner_alpha;
- ring_inner_rgb = eX * autocvar_crosshair_ring_nex_inner_color_red + eY * autocvar_crosshair_ring_nex_inner_color_green + eZ * autocvar_crosshair_ring_nex_inner_color_blue;
- ring_inner_image = "gfx/crosshair_ring_inner.tga";
-
- // draw the outer ring to show the current charge of the weapon
- ring_value = nex_charge;
- ring_alpha = autocvar_crosshair_ring_nex_alpha;
- ring_rgb = wcross_color;
- ring_image = "gfx/crosshair_ring_nexgun.tga";
- }
- else if (autocvar_crosshair_ring && activeweapon == WEP_MINE_LAYER && minelayer_maxmines && autocvar_crosshair_ring_minelayer)
- {
- ring_value = bound(0, getstati(STAT_LAYED_MINES) / minelayer_maxmines, 1); // if you later need to use the count of bullets in another place, then add a float for it. For now, no need to.
- ring_alpha = autocvar_crosshair_ring_minelayer_alpha;
- ring_rgb = wcross_color;
- ring_image = "gfx/crosshair_ring.tga";
- }
- else if (activeweapon == WEP_HAGAR && getstati(STAT_HAGAR_LOAD) && autocvar_crosshair_ring_hagar)
- {
- ring_value = bound(0, getstati(STAT_HAGAR_LOAD) / hagar_maxrockets, 1);
- ring_alpha = autocvar_crosshair_ring_hagar_alpha;
- ring_rgb = wcross_color;
- ring_image = "gfx/crosshair_ring.tga";
- }
-
- if(autocvar_crosshair_ring_reload && weapon_clipsize) // forces there to be only an ammo ring
- {
- ring_value = bound(0, weapon_clipload / weapon_clipsize, 1);
- ring_scale = autocvar_crosshair_ring_reload_size;
- ring_alpha = autocvar_crosshair_ring_reload_alpha;
- ring_rgb = wcross_color;
-
- // Note: This is to stop Taoki from complaining that the image doesn't match all potential balances.
- // if a new image for another weapon is added, add the code (and its respective file/value) here
- if ((activeweapon == WEP_RIFLE) && (weapon_clipsize == 80))
- ring_image = "gfx/crosshair_ring_rifle.tga";
- else
- ring_image = "gfx/crosshair_ring.tga";
- }
-
- // if in weapon switch animation, fade ring out/in
- if(autocvar_crosshair_effect_time > 0)
- {
- f = (time - wcross_name_changestarttime) / autocvar_crosshair_effect_time;
- if (!(f < 1))
- {
- wcross_ring_prev = ((ring_image) ? TRUE : FALSE);
- }
-
- if(wcross_ring_prev)
- {
- if(f < 1)
- ring_alpha *= fabs(1 - bound(0, f, 1));
- }
- else
- {
- if(f < 1)
- ring_alpha *= bound(0, f, 1);
- }
- }
-
- if (autocvar_crosshair_ring_inner && ring_inner_value) // lets draw a ring inside a ring so you can ring while you ring
- DrawCircleClippedPic(wcross_origin, wcross_size_x * ring_scale, ring_inner_image, ring_inner_value, ring_inner_rgb, wcross_alpha * ring_inner_alpha, DRAWFLAG_ADDITIVE);
-
- if (ring_value)
- DrawCircleClippedPic(wcross_origin, wcross_size_x * ring_scale, ring_image, ring_value, ring_rgb, wcross_alpha * ring_alpha, DRAWFLAG_ADDITIVE);
- }
-
- #define CROSSHAIR_DO_BLUR(M,sz,wcross_name,wcross_alpha) \
- do \
- { \
- if(wcross_blur > 0) \
- { \
- for(i = -2; i <= 2; ++i) \
- for(j = -2; j <= 2; ++j) \
- M(i,j,sz,wcross_name,wcross_alpha*0.04); \
- } \
- else \
- { \
- M(0,0,sz,wcross_name,wcross_alpha); \
- } \
- } \
- while(0)
-
- #define CROSSHAIR_DRAW_SINGLE(i,j,sz,wcross_name,wcross_alpha) \
- drawpic(wcross_origin - ('0.5 0 0' * (sz * wcross_size_x + i * wcross_blur) + '0 0.5 0' * (sz * wcross_size_y + j * wcross_blur)), wcross_name, sz * wcross_size, wcross_color, wcross_alpha, DRAWFLAG_NORMAL)
-
- #define CROSSHAIR_DRAW(sz,wcross_name,wcross_alpha) \
- CROSSHAIR_DO_BLUR(CROSSHAIR_DRAW_SINGLE,sz,wcross_name,wcross_alpha)
-
- if(time < wcross_name_changedonetime && wcross_name != wcross_name_goal_prev_prev && wcross_name_goal_prev_prev)
- {
- f = (wcross_name_changedonetime - time) / (wcross_name_changedonetime - wcross_name_changestarttime);
- wcross_size = draw_getimagesize(wcross_name_goal_prev_prev) * wcross_scale;
- CROSSHAIR_DRAW(wcross_resolution_goal_prev_prev, wcross_name_goal_prev_prev, wcross_alpha * f * wcross_name_alpha_goal_prev_prev);
- f = 1 - f;
- }
- else
- {
- f = 1;
- }
- wcross_name_alpha_goal_prev = f;
-
- wcross_size = draw_getimagesize(wcross_name) * wcross_scale;
- CROSSHAIR_DRAW(wcross_resolution, wcross_name, wcross_alpha * f);
-
- if(autocvar_crosshair_dot)
- {
- vector wcross_color_old;
- wcross_color_old = wcross_color;
-
- if((autocvar_crosshair_dot_color_custom) && (autocvar_crosshair_dot_color != "0"))
- wcross_color = stov(autocvar_crosshair_dot_color);
-
- CROSSHAIR_DRAW(wcross_resolution * autocvar_crosshair_dot_size, "gfx/crosshairdot.tga", f * autocvar_crosshair_dot_alpha);
- // FIXME why don't we use wcross_alpha here?cl_notice_run();
- wcross_color = wcross_color_old;
- }
- }
- }
- else
- {
- wcross_scale_prev = 0;
- wcross_alpha_prev = 0;
- wcross_scale_goal_prev = 0;
- wcross_alpha_goal_prev = 0;
- wcross_changedonetime = 0;
- if(wcross_name_goal_prev)
- strunzone(wcross_name_goal_prev);
- wcross_name_goal_prev = string_null;
- if(wcross_name_goal_prev_prev)
- strunzone(wcross_name_goal_prev_prev);
- wcross_name_goal_prev_prev = string_null;
- wcross_name_changestarttime = 0;
- wcross_name_changedonetime = 0;
- wcross_name_alpha_goal_prev = 0;
- wcross_name_alpha_goal_prev_prev = 0;
- wcross_resolution_goal_prev = 0;
- wcross_resolution_goal_prev_prev = 0;
- }
- }
+ UpdateDamage();
+ UpdateCrosshair();
+ UpdateHitsound();
if(NextFrameCommand)
{
if(autocvar__hud_configure)
HUD_Panel_Mouse();
+ else
+ HUD_Radar_Mouse();
if(hud && !intermission)
{
float autocvar_cl_orthoview;
float autocvar_cl_orthoview_nofog;
float autocvar_cl_particlegibs;
- float autocvar_cl_particles_oldnexbeam;
+ float autocvar_cl_particles_oldvortexbeam;
float autocvar_cl_particles_quality;
float autocvar_cl_projectiles_sloppy;
float autocvar_cl_readpicture_force;
var float autocvar_cl_reticle = 1;
- float autocvar_cl_reticle_item_nex;
- float autocvar_cl_reticle_item_normal;
+ var float autocvar_cl_reticle_normal_alpha = 1;
+ var float autocvar_cl_reticle_weapon = 1;
+ var float autocvar_cl_reticle_weapon_alpha = 1;
float autocvar_cl_reticle_stretch;
float autocvar_cl_spawn_event_particles;
var float autocvar_cl_spawn_event_sound = 1;
var float autocvar_cl_vehicle_spiderbot_cross_alpha = 0.6;
var float autocvar_cl_vehicle_spiderbot_cross_size = 1;
var float autocvar_cl_vehicles_hud_tactical = 1;
- float autocvar_cl_velocityzoom;
+ float autocvar_cl_velocityzoom_enabled;
+ float autocvar_cl_velocityzoom_factor;
var float autocvar_cl_velocityzoom_type = 3;
float autocvar_cl_velocityzoom_speed;
float autocvar_cl_velocityzoom_time;
float autocvar_crosshair_hitindication_speed;
float autocvar_crosshair_hittest;
float autocvar_crosshair_hittest_blur;
+ var float autocvar_crosshair_hittest_scale = 1.25;
float autocvar_crosshair_hittest_showimpact;
float autocvar_crosshair_per_weapon;
float autocvar_crosshair_pickup;
float autocvar_crosshair_ring_minelayer_alpha;
float autocvar_crosshair_ring_hagar;
float autocvar_crosshair_ring_hagar_alpha;
- float autocvar_crosshair_ring_nex;
- float autocvar_crosshair_ring_nex_alpha;
- float autocvar_crosshair_ring_nex_currentcharge_movingavg_rate;
- float autocvar_crosshair_ring_nex_currentcharge_scale;
- float autocvar_crosshair_ring_nex_inner_alpha;
- float autocvar_crosshair_ring_nex_inner_color_blue;
- float autocvar_crosshair_ring_nex_inner_color_green;
- float autocvar_crosshair_ring_nex_inner_color_red;
+ var float autocvar_crosshair_ring_vortex = 1;
+ var float autocvar_crosshair_ring_vortex_alpha = 0.15;
+ var float autocvar_crosshair_ring_vortex_currentcharge_movingavg_rate = 0.05;
+ var float autocvar_crosshair_ring_vortex_currentcharge_scale = 30;
+ var float autocvar_crosshair_ring_vortex_inner_alpha = 0.15;
+ var float autocvar_crosshair_ring_vortex_inner_color_blue = 0;
+ var float autocvar_crosshair_ring_vortex_inner_color_green = 0;
+ var float autocvar_crosshair_ring_vortex_inner_color_red = 0.8;
+ var float autocvar_crosshair_ring_arc = 1;
+ var vector autocvar_crosshair_ring_arc_hot_color = '1 0 0';
+ var float autocvar_crosshair_ring_arc_cold_alpha = 0.2;
+ var float autocvar_crosshair_ring_arc_hot_alpha = 0.5;
float autocvar_crosshair_ring_size;
float autocvar_crosshair_ring_reload;
float autocvar_crosshair_ring_reload_alpha;
float autocvar_hud_panel_ammo_iconalign;
float autocvar_hud_panel_ammo_maxammo;
float autocvar_hud_panel_ammo_onlycurrent;
+ float autocvar_hud_panel_ammo_noncurrent_alpha = 0.7;
+ float autocvar_hud_panel_ammo_noncurrent_scale = 1;
float autocvar_hud_panel_ammo_progressbar;
string autocvar_hud_panel_ammo_progressbar_name;
float autocvar_hud_panel_ammo_progressbar_xoffset;
float autocvar_hud_panel_notify_flip;
float autocvar_hud_panel_notify_fontsize;
float autocvar_hud_panel_notify_time;
+ float autocvar_hud_panel_notify_icon_aspect;
float autocvar_hud_panel_physics;
float autocvar_hud_panel_physics_acceleration_progressbar_mode;
float autocvar_hud_panel_physics_acceleration_progressbar_scale;
float autocvar_hud_panel_powerups_flip;
float autocvar_hud_panel_powerups_iconalign;
float autocvar_hud_panel_powerups_progressbar;
+ float autocvar_hud_panel_buffs;
+ //float autocvar_hud_panel_buffs_iconalign;
string autocvar_hud_panel_powerups_progressbar_shield;
string autocvar_hud_panel_powerups_progressbar_strength;
string autocvar_hud_panel_powerups_progressbar_superweapons;
float autocvar_hud_panel_weapons_ammo_alpha;
string autocvar_hud_panel_weapons_ammo_color;
float autocvar_hud_panel_weapons_ammo_full_cells;
+ float autocvar_hud_panel_weapons_ammo_full_plasma;
float autocvar_hud_panel_weapons_ammo_full_fuel;
float autocvar_hud_panel_weapons_ammo_full_nails;
float autocvar_hud_panel_weapons_ammo_full_rockets;
float autocvar_vid_pixelheight;
float autocvar_viewsize;
float autocvar_cl_hitsound;
+ var float autocvar_cl_hitsound_min_pitch = 0.75; // minimal difference in minsta
+ var float autocvar_cl_hitsound_max_pitch = 1.5;
+ var float autocvar_cl_hitsound_nom_damage = 25;
float autocvar_cl_hitsound_antispam_time;
var float autocvar_cl_eventchase_death = 1;
var float autocvar_cl_eventchase_nexball = 1;
var vector autocvar_cl_eventchase_maxs = '12 12 8';
var vector autocvar_cl_eventchase_mins = '-12 -12 -8';
var vector autocvar_cl_eventchase_viewoffset = '0 0 20';
+var vector autocvar_cl_eventchase_generator_viewoffset = '0 0 80';
+var float autocvar_cl_eventchase_generator_distance = 400;
float autocvar_cl_lerpexcess;
string autocvar__togglezoom;
float autocvar_cl_damageeffect;
float autocvar_cl_deathglow;
float autocvar_developer_csqcentities;
float autocvar_g_jetpack_attenuation;
+ var string autocvar_crosshair_hmg = "";
+ var vector autocvar_crosshair_hmg_color = '0.2 1.0 0.2';
+ var float autocvar_crosshair_hmg_alpha = 1;
+ var float autocvar_crosshair_hmg_size = 1;
+ var string autocvar_crosshair_rpc = "";
+ var vector autocvar_crosshair_rpc_color = '0.2 1.0 0.2';
+ var float autocvar_crosshair_rpc_alpha = 1;
+ var float autocvar_crosshair_rpc_size = 1;
+ float autocvar_cl_nade_timer;
if(histime < 0)
return strcat(col, cpname);
else if(hisname == "")
- return strcat(col, sprintf(_("%s (%s)"), cpname, timestr));
+ return strcat(col, sprintf("%s (%s)", cpname, timestr));
else
- return strcat(col, sprintf(_("%s (%s %s)"), cpname, timestr, strcat(hisname, col, lapstr)));
+ return strcat(col, sprintf("%s (%s %s)", cpname, timestr, strcat(hisname, col, lapstr)));
}
// Check if the given name already exist in race rankings? In that case, where? (otherwise return 0)
return aj - ai; // the string is in REVERSE order (higher prio at the right is what we want, but higher prio first is the string)
}
- float GetAmmoStat(float i)
- {
- switch(i)
- {
- case 0: return STAT_SHELLS;
- case 1: return STAT_NAILS;
- case 2: return STAT_ROCKETS;
- case 3: return STAT_CELLS;
- case 4: return STAT_FUEL;
- default: return -1;
- }
- }
-
- float GetAmmoTypeForWep(float i)
- {
- switch(i)
- {
- case WEP_SHOTGUN: return 0;
- case WEP_UZI: return 1;
- case WEP_GRENADE_LAUNCHER: return 2;
- case WEP_MINE_LAYER: return 2;
- case WEP_ELECTRO: return 3;
- case WEP_CRYLINK: return 3;
- case WEP_HLAC: return 3;
- case WEP_MINSTANEX: return 3;
- case WEP_NEX: return 3;
- case WEP_RIFLE: return 1;
- case WEP_HAGAR: return 2;
- case WEP_ROCKET_LAUNCHER: return 2;
- case WEP_SEEKER: return 2;
- case WEP_FIREBALL: return 4;
- case WEP_HOOK: return 3;
- default: return -1;
- }
- }
-
void HUD_Weapons(void)
{
// declarations
float timein_effect_length = autocvar_hud_panel_weapons_timeout_speed_in; //? 0.375 : 0);
float timeout_effect_length = autocvar_hud_panel_weapons_timeout_speed_out; //? 0.75 : 0);
- float ammo_type, ammo_full;
+ float ammo_full;
float barsize_x = 0, barsize_y = 0, baroffset_x = 0, baroffset_y = 0;
vector ammo_color = '1 0 1';
float ammo_alpha = 1;
if(weapons_stat & WepSet_FromWeapon(self.weapon))
{
// draw the weapon image
- drawpic_aspect_skin(weapon_pos, strcat("weapon", self.netname), weapon_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawpic_aspect_skin(weapon_pos, self.model2, weapon_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
// draw weapon label string
switch(autocvar_hud_panel_weapons_label)
break;
case 3: // weapon name
- drawstring(weapon_pos, self.netname, '1 1 0' * 0.5 * weapon_size_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawstring(weapon_pos, strtolower(self.message), '1 1 0' * 0.5 * weapon_size_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
break;
default: // nothing
}
// draw ammo status bar
- if(autocvar_hud_panel_weapons_ammo && self.weapon != WEP_TUBA && self.weapon != WEP_LASER && self.weapon != WEP_PORTO)
+ if(autocvar_hud_panel_weapons_ammo && (self.ammo_field != ammo_none))
{
- a = 0;
- ammo_type = GetAmmoTypeForWep(self.weapon);
- if(ammo_type != -1)
- a = getstati(GetAmmoStat(ammo_type)); // how much ammo do we have?
+ a = getstati(GetAmmoStat(self.ammo_field)); // how much ammo do we have?
if(a > 0)
{
- switch(ammo_type) {
- case 0: ammo_full = autocvar_hud_panel_weapons_ammo_full_shells; break;
- case 1: ammo_full = autocvar_hud_panel_weapons_ammo_full_nails; break;
- case 2: ammo_full = autocvar_hud_panel_weapons_ammo_full_rockets; break;
- case 3: ammo_full = autocvar_hud_panel_weapons_ammo_full_cells; break;
- case 4: ammo_full = autocvar_hud_panel_weapons_ammo_full_fuel; break;
+ switch(self.ammo_field)
+ {
+ case ammo_shells: ammo_full = autocvar_hud_panel_weapons_ammo_full_shells; break;
+ case ammo_nails: ammo_full = autocvar_hud_panel_weapons_ammo_full_nails; break;
+ case ammo_rockets: ammo_full = autocvar_hud_panel_weapons_ammo_full_rockets; break;
+ case ammo_cells: ammo_full = autocvar_hud_panel_weapons_ammo_full_cells; break;
+ case ammo_plasma: ammo_full = autocvar_hud_panel_weapons_ammo_full_plasma; break;
+ case ammo_fuel: ammo_full = autocvar_hud_panel_weapons_ammo_full_fuel; break;
default: ammo_full = 60;
}
weapon_pos_x + baroffset_x,
weapon_pos_y + baroffset_y,
barsize_x * bound(0, a/ammo_full, 1),
- barsize_y);
- drawpic_aspect_skin(weapon_pos, "weapon_ammo", weapon_size, ammo_color, ammo_alpha, DRAWFLAG_NORMAL);
+ barsize_y
+ );
+
+ drawpic_aspect_skin(
+ weapon_pos,
+ "weapon_ammo",
+ weapon_size,
+ ammo_color,
+ ammo_alpha,
+ DRAWFLAG_NORMAL
+ );
+
drawresetcliparea();
}
}
}
else // draw a "ghost weapon icon" if you don't have the weapon
{
- drawpic_aspect_skin(weapon_pos, strcat("weapon", self.netname), weapon_size, '0 0 0', panel_fg_alpha * 0.5, DRAWFLAG_NORMAL);
+ drawpic_aspect_skin(weapon_pos, self.model2, weapon_size, '0 0 0', panel_fg_alpha * 0.5, DRAWFLAG_NORMAL);
}
// draw the complain message
}
// Ammo (#1)
- //
- // TODO: macro
- float GetAmmoItemCode(float i)
+ void DrawNadeScoreBar(vector myPos, vector mySize, vector color)
{
- switch(i)
- {
- case 0: return IT_SHELLS;
- case 1: return IT_NAILS;
- case 2: return IT_ROCKETS;
- case 3: return IT_CELLS;
- case 4: return IT_FUEL;
- default: return -1;
- }
+
+ HUD_Panel_DrawProgressBar(
+ myPos + eX * autocvar_hud_panel_ammo_progressbar_xoffset * mySize_x,
+ mySize - eX * autocvar_hud_panel_ammo_progressbar_xoffset * mySize_x,
+ autocvar_hud_panel_ammo_progressbar_name,
+ getstatf(STAT_NADE_BONUS_SCORE), 0, 0, color,
+ autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
+
}
- string GetAmmoPicture(float i)
+ void DrawAmmoNades(vector myPos, vector mySize, float draw_expanding, float expand_time)
{
- switch(i)
+ float theAlpha = 1, a, b;
+ vector nade_color, picpos, numpos;
+
+ nade_color = Nade_Color(getstati(STAT_NADE_BONUS_TYPE));
+
+ a = getstatf(STAT_NADE_BONUS);
+ b = getstatf(STAT_NADE_BONUS_SCORE);
+
+ if(autocvar_hud_panel_ammo_iconalign)
+ {
+ numpos = myPos;
+ picpos = myPos + eX * 2 * mySize_y;
+ }
+ else
+ {
+ numpos = myPos + eX * mySize_y;
+ picpos = myPos;
+ }
+
+ DrawNadeScoreBar(myPos, mySize, nade_color);
+
+ if(b > 0 || a > 0)
{
- case 0: return "ammo_shells";
- case 1: return "ammo_bullets";
- case 2: return "ammo_rockets";
- case 3: return "ammo_cells";
- case 4: return "ammo_fuel";
- default: return "";
+ if(autocvar_hud_panel_ammo_text)
+ drawstring_aspect(numpos, ftos(a), eX * (2/3) * mySize_x + eY * mySize_y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL);
+
+ if(draw_expanding)
+ drawpic_aspect_skin_expanding(picpos, "nade_nbg", '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL, expand_time);
+
+ drawpic_aspect_skin(picpos, "nade_bg" , '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL);
+ drawpic_aspect_skin(picpos, "nade_nbg" , '1 1 0' * mySize_y, nade_color, panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL);
}
}
- void DrawAmmoItem(vector myPos, vector mySize, float itemcode, float currently_selected, float infinite_ammo)
+ void DrawAmmoItem(vector myPos, vector mySize, .float ammoType, float isCurrent, float isInfinite)
{
- float a;
+ if(ammoType == ammo_none)
+ return;
+
+ // Initialize variables
+
+ float ammo;
if(autocvar__hud_configure)
{
- currently_selected = (itemcode == 2); //rockets always selected
- a = 31 + mod(itemcode*93, 128);
+ isCurrent = (ammoType == ammo_rockets); // Rockets always current
+ ammo = 60;
}
else
- a = getstati(GetAmmoStat(itemcode)); // how much ammo do we have of type itemcode?
-
- vector color;
- if(infinite_ammo)
- color = '0 0.5 0.75';
- else if(a < 10)
- color = '0.7 0 0';
- else
- color = '1 1 1';
+ ammo = getstati(GetAmmoStat(ammoType));
- float theAlpha;
- if(currently_selected)
- theAlpha = 1;
- else
- theAlpha = 0.7;
+ if(!isCurrent)
+ {
+ float scale = bound(0, autocvar_hud_panel_ammo_noncurrent_scale, 1);
+ myPos = myPos + (mySize - mySize * scale) * 0.5;
+ mySize = mySize * scale;
+ }
- vector picpos, numpos;
+ vector iconPos, textPos;
if(autocvar_hud_panel_ammo_iconalign)
{
- numpos = myPos;
- picpos = myPos + eX * 2 * mySize_y;
+ iconPos = myPos + eX * 2 * mySize_y;
+ textPos = myPos;
}
else
{
- numpos = myPos + eX * mySize_y;
- picpos = myPos;
+ iconPos = myPos;
+ textPos = myPos + eX * mySize_y;
}
- if (currently_selected)
+ float isShadowed = (ammo <= 0 && !isCurrent && !isInfinite);
+
+ vector iconColor = isShadowed ? '0 0 0' : '1 1 1';
+ vector textColor;
+ if(isInfinite)
+ textColor = '0.2 0.95 0';
+ else if(isShadowed)
+ textColor = '0 0 0';
+ else if(ammo < 10)
+ textColor = '0.8 0.04 0';
+ else
+ textColor = '1 1 1';
+
+ float alpha;
+ if(isCurrent)
+ alpha = panel_fg_alpha;
+ else if(isShadowed)
+ alpha = panel_fg_alpha * bound(0, autocvar_hud_panel_ammo_noncurrent_alpha, 1) * 0.5;
+ else
+ alpha = panel_fg_alpha * bound(0, autocvar_hud_panel_ammo_noncurrent_alpha, 1);
+
+ string text = isInfinite ? "\xE2\x88\x9E" : ftos(ammo); // Use infinity symbol (U+221E)
+
+ // Draw item
+
+ if(isCurrent)
drawpic_aspect_skin(myPos, "ammo_current_bg", mySize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
- if(a > 0 && autocvar_hud_panel_ammo_progressbar)
- HUD_Panel_DrawProgressBar(myPos + eX * autocvar_hud_panel_ammo_progressbar_xoffset * mySize_x, mySize - eX * autocvar_hud_panel_ammo_progressbar_xoffset * mySize_x, autocvar_hud_panel_ammo_progressbar_name, a/autocvar_hud_panel_ammo_maxammo, 0, 0, color, autocvar_hud_progressbar_alpha * panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL);
+ if(ammo > 0 && autocvar_hud_panel_ammo_progressbar)
+ HUD_Panel_DrawProgressBar(myPos + eX * autocvar_hud_panel_ammo_progressbar_xoffset * mySize_x, mySize - eX * autocvar_hud_panel_ammo_progressbar_xoffset * mySize_x, autocvar_hud_panel_ammo_progressbar_name, ammo/autocvar_hud_panel_ammo_maxammo, 0, 0, textColor, autocvar_hud_progressbar_alpha * alpha, DRAWFLAG_NORMAL);
- if(autocvar_hud_panel_ammo_text)
- {
- if(a > 0 || infinite_ammo)
- drawstring_aspect(numpos, ftos(a), eX * (2/3) * mySize_x + eY * mySize_y, color, panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL);
- else // "ghost" ammo count
- drawstring_aspect(numpos, ftos(a), eX * (2/3) * mySize_x + eY * mySize_y, '0 0 0', panel_fg_alpha * theAlpha * 0.5, DRAWFLAG_NORMAL);
- }
- if(a > 0 || infinite_ammo)
- drawpic_aspect_skin(picpos, GetAmmoPicture(itemcode), '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL);
- else // "ghost" ammo icon
- drawpic_aspect_skin(picpos, GetAmmoPicture(itemcode), '1 1 0' * mySize_y, '0 0 0', panel_fg_alpha * theAlpha * 0.5, DRAWFLAG_NORMAL);
+ if(autocvar_hud_panel_ammo_text)
+ drawstring_aspect(textPos, text, eX * (2/3) * mySize_x + eY * mySize_y, textColor, alpha, DRAWFLAG_NORMAL);
+
+ drawpic_aspect_skin(iconPos, GetAmmoPicture(ammoType), '1 1 0' * mySize_y, iconColor, alpha, DRAWFLAG_NORMAL);
}
+ float nade_prevstatus;
+ float nade_prevframe;
+ float nade_statuschange_time;
void HUD_Ammo(void)
{
if(hud != HUD_NORMAL) return;
mySize -= '2 2 0' * panel_bg_padding;
}
- const float AMMO_COUNT = 4;
float rows = 0, columns, row, column;
+ float nade_cnt = getstatf(STAT_NADE_BONUS), nade_score = getstatf(STAT_NADE_BONUS_SCORE);
+ float draw_nades = (nade_cnt > 0 || nade_score > 0), nade_statuschange_elapsedtime;
+ float total_ammo_count;
+
vector ammo_size;
if (autocvar_hud_panel_ammo_onlycurrent)
- ammo_size = mySize;
+ total_ammo_count = 1;
else
+ total_ammo_count = AMMO_COUNT;
+
+ if(draw_nades)
{
- rows = mySize_y/mySize_x;
- rows = bound(1, floor((sqrt(4 * (3/1) * rows * AMMO_COUNT + rows * rows) + rows + 0.5) / 2), AMMO_COUNT);
- // ^^^ ammo item aspect goes here
+ ++total_ammo_count;
+ if (nade_cnt != nade_prevframe)
+ {
+ nade_statuschange_time = time;
+ nade_prevstatus = nade_prevframe;
+ nade_prevframe = nade_cnt;
+ }
+ }
+ else
+ nade_prevstatus = nade_prevframe = nade_statuschange_time = 0;
- columns = ceil(AMMO_COUNT/rows);
+ rows = mySize_y/mySize_x;
+ rows = bound(1, floor((sqrt(4 * (3/1) * rows * (total_ammo_count) + rows * rows) + rows + 0.5) / 2), (total_ammo_count));
+ // ^^^ ammo item aspect goes here
- ammo_size = eX * mySize_x*(1/columns) + eY * mySize_y*(1/rows);
- }
+ columns = ceil((total_ammo_count)/rows);
+
+ ammo_size = eX * mySize_x*(1/columns) + eY * mySize_y*(1/rows);
+
local vector offset = '0 0 0'; // fteqcc sucks
float newSize;
ammo_size_y = newSize;
}
- float i, stat_items, currently_selected, infinite_ammo;
- infinite_ammo = FALSE;
- if (autocvar_hud_panel_ammo_onlycurrent)
+ float i;
+ float infinite_ammo = (getstati(STAT_ITEMS, 0, 24) & IT_UNLIMITED_WEAPON_AMMO);
+ row = column = 0;
+ if(autocvar_hud_panel_ammo_onlycurrent)
{
if(autocvar__hud_configure)
{
- DrawAmmoItem(pos, ammo_size, 2, true, FALSE); //show rockets
+ DrawAmmoItem(pos, ammo_size, ammo_rockets, TRUE, FALSE);
}
else
{
- stat_items = getstati(STAT_ITEMS, 0, 24);
- if (stat_items & IT_UNLIMITED_WEAPON_AMMO)
- infinite_ammo = TRUE;
- for (i = 0; i < AMMO_COUNT; ++i) {
- currently_selected = stat_items & GetAmmoItemCode(i);
- if (currently_selected)
- {
- DrawAmmoItem(pos, ammo_size, i, true, infinite_ammo);
- break;
- }
- }
+ DrawAmmoItem(
+ pos,
+ ammo_size,
+ (get_weaponinfo(switchweapon)).ammo_field,
+ TRUE,
+ infinite_ammo
+ );
+ }
+
+ ++row;
+ if(row >= rows)
+ {
+ row = 0;
+ column = column + 1;
}
}
else
{
- stat_items = getstati(STAT_ITEMS, 0, 24);
- if (stat_items & IT_UNLIMITED_WEAPON_AMMO)
- infinite_ammo = TRUE;
+ .float ammotype;
row = column = 0;
- for (i = 0; i < AMMO_COUNT; ++i) {
- currently_selected = stat_items & GetAmmoItemCode(i);
- DrawAmmoItem(pos + eX * column * (ammo_size_x + offset_x) + eY * row * (ammo_size_y + offset_y), ammo_size, i, currently_selected, infinite_ammo);
+ for(i = 0; i < AMMO_COUNT; ++i)
+ {
+ ammotype = GetAmmoFieldFromNum(i);
+ DrawAmmoItem(
+ pos + eX * column * (ammo_size_x + offset_x) + eY * row * (ammo_size_y + offset_y),
+ ammo_size,
+ ammotype,
+ ((get_weaponinfo(switchweapon)).ammo_field == ammotype),
+ infinite_ammo
+ );
+
++row;
if(row >= rows)
{
}
}
+ if (draw_nades)
+ {
+ nade_statuschange_elapsedtime = time - nade_statuschange_time;
+
+ float f = bound(0, nade_statuschange_elapsedtime*2, 1);
+
+ DrawAmmoNades(pos + eX * column * (ammo_size_x + offset_x) + eY * row * (ammo_size_y + offset_y), ammo_size, nade_prevstatus < nade_cnt && nade_cnt != 0 && f < 1, f);
+ }
+
draw_endBoldFont();
}
void HUD_Notify_Push(string icon, string attacker, string victim)
{
- if(icon != "")
- {
- --kn_index;
- if (kn_index == -1) { kn_index = KN_MAX_ENTRIES-1; }
- notify_times[kn_index] = time;
+ if (icon == "")
+ return;
+
+ ++notify_count;
+ --notify_index;
+
+ if (notify_index == -1)
+ notify_index = NOTIFY_MAX_ENTRIES-1;
+
+ // Free old strings
+ if (notify_attackers[notify_index])
+ strunzone(notify_attackers[notify_index]);
- // icon
- if(notify_icon[kn_index]) { strunzone(notify_icon[kn_index]); }
- notify_icon[kn_index] = strzone(icon);
+ if (notify_victims[notify_index])
+ strunzone(notify_victims[notify_index]);
- // attacker
- if(notify_attackers[kn_index]) { strunzone(notify_attackers[kn_index]); }
- notify_attackers[kn_index] = strzone(attacker);
+ if (notify_icons[notify_index])
+ strunzone(notify_icons[notify_index]);
- // victim
- if(notify_victims[kn_index]) { strunzone(notify_victims[kn_index]); }
- notify_victims[kn_index] = strzone(victim);
+ // Allocate new strings
+ if (victim != "")
+ {
+ notify_attackers[notify_index] = strzone(attacker);
+ notify_victims[notify_index] = strzone(victim);
+ }
+ else
+ {
+ // In case of a notification without a victim, the attacker
+ // is displayed on the victim's side. Instead of special
+ // treatment later on, we can simply switch them here.
+ notify_attackers[notify_index] = string_null;
+ notify_victims[notify_index] = strzone(attacker);
}
+
+ notify_icons[notify_index] = strzone(icon);
+ notify_times[notify_index] = time;
}
void HUD_Notify(void)
{
- if(!autocvar__hud_configure)
- {
- if(!autocvar_hud_panel_notify) return;
- }
+ if (!autocvar__hud_configure)
+ if (!autocvar_hud_panel_notify)
+ return;
HUD_Panel_UpdateCvars();
- vector pos, mySize;
- pos = panel_pos;
- mySize = panel_size;
-
HUD_Panel_DrawBg(1);
- if(panel_bg_padding)
+
+ if (!autocvar__hud_configure)
+ if (notify_count == 0)
+ return;
+
+ vector pos, size;
+ pos = panel_pos;
+ size = panel_size;
+
+ if (panel_bg_padding)
{
- pos += '1 1 0' * panel_bg_padding;
- mySize -= '2 2 0' * panel_bg_padding;
+ pos += '1 1 0' * panel_bg_padding;
+ size -= '2 2 0' * panel_bg_padding;
}
- float entries, height;
- entries = bound(1, floor(KN_MAX_ENTRIES * mySize_y/mySize_x), KN_MAX_ENTRIES);
- height = mySize_y/entries;
+ float fade_start = max(0, autocvar_hud_panel_notify_time);
+ float fade_time = max(0, autocvar_hud_panel_notify_fadetime);
+ float icon_aspect = max(1, autocvar_hud_panel_notify_icon_aspect);
- vector fontsize;
- float fontheight = height * autocvar_hud_panel_notify_fontsize;
- fontsize = '0.5 0.5 0' * fontheight;
+ float entry_count = bound(1, floor(NOTIFY_MAX_ENTRIES * size_y / size_x), NOTIFY_MAX_ENTRIES);
+ float entry_height = size_y / entry_count;
- float a;
- float when;
- when = autocvar_hud_panel_notify_time;
- float fadetime;
- fadetime = autocvar_hud_panel_notify_fadetime;
+ float panel_width_half = size_x * 0.5;
+ float icon_width_half = entry_height * icon_aspect / 2;
+ float name_maxwidth = panel_width_half - icon_width_half - size_x * NOTIFY_ICON_MARGIN;
- vector pos_attacker, pos_victim, pos_icon;
- float width_attacker;
+ vector font_size = '0.5 0.5 0' * entry_height * autocvar_hud_panel_notify_fontsize;
+ vector icon_size = (eX * icon_aspect + eY) * entry_height;
+ vector icon_left = eX * (panel_width_half - icon_width_half);
+ vector attacker_right = eX * name_maxwidth;
+ vector victim_left = eX * (size_x - name_maxwidth);
+
+ vector attacker_pos, victim_pos, icon_pos;
string attacker, victim, icon;
+ float i, j, count, step, limit, alpha;
- float i, j, step, limit;
- if(autocvar_hud_panel_notify_flip) //order items from the top down
+ if (autocvar_hud_panel_notify_flip)
{
+ // Order items from the top down
i = 0;
step = +1;
- limit = entries;
+ limit = entry_count;
}
- else //order items from the bottom up
+ else
{
- i = entries - 1;
+ // Order items from the bottom up
+ i = entry_count - 1;
step = -1;
limit = -1;
}
- for(j = kn_index; i != limit; i += step, ++j)
+ for (j = notify_index, count = 0; i != limit; i += step, ++j, ++count)
{
if(autocvar__hud_configure)
{
- if (step == +1)
- a = i;
- else // inverse order
- a = entries - 1 - i;
- attacker = textShortenToWidth(sprintf(_("Player %d"), a+1), 0.48 * mySize_x - height, fontsize, stringwidth_colors);
- victim = textShortenToWidth(sprintf(_("Player %d"), a+2), 0.48 * mySize_x - height, fontsize, stringwidth_colors);
- icon = strcat("weapon", get_weaponinfo(WEP_FIRST + mod(floor(a*2.4), WEP_LAST)).netname);
- a = bound(0, (when - a) / 4, 1);
- goto hud_config_notifyprint;
+ attacker = sprintf(_("Player %d"), count + 1);
+ victim = sprintf(_("Player %d"), count + 2);
+ icon = get_weaponinfo(min(WEP_FIRST + count * 2, WEP_LAST)).model2;
+ alpha = bound(0, 1.2 - count / entry_count, 1);
}
else
{
- if (j == KN_MAX_ENTRIES)
+ if (j == NOTIFY_MAX_ENTRIES)
j = 0;
- if(notify_times[j] + when > time)
- a = 1;
- else if(fadetime)
+ if (notify_times[j] + fade_start > time)
+ alpha = 1;
+ else if (fade_time != 0)
{
- a = bound(0, (notify_times[j] + when + fadetime - time) / fadetime, 1);
- if(!a)
- {
+ alpha = bound(0, (notify_times[j] + fade_start + fade_time - time) / fade_time, 1);
+ if (alpha == 0)
break;
- }
}
else
- {
break;
- }
attacker = notify_attackers[j];
victim = notify_victims[j];
- icon = notify_icon[j];
+ icon = notify_icons[j];
}
- //type = notify_deathtype[j];
- //w = DEATH_WEAPONOF(type);
-
- if(icon != "")
+ if (icon != "" && victim != "")
{
- if((attacker != "") && (victim == ""))
- {
- // Y [used by] X
- attacker = textShortenToWidth(attacker, 0.73 * mySize_x - height, fontsize, stringwidth_colors);
- pos_attacker = pos + eX * (0.27 * mySize_x + height) + eY * ((0.5 * fontsize_y + i * height) + (0.5 * (height - fontheight)));
- pos_icon = pos + eX * 0.25 * mySize_x - eX * height + eY * i * height;
+ vector name_top = eY * (i * entry_height + 0.5 * (entry_height - font_size_y));
- drawpic_aspect_skin(pos_icon, icon, '2 1 0' * height, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
- drawcolorcodedstring(pos_attacker, attacker, fontsize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
- }
- else if((attacker != "") && (victim != ""))
+ icon_pos = pos + icon_left + eY * i * entry_height;
+ drawpic_aspect_skin(icon_pos, icon, icon_size, '1 1 1', panel_fg_alpha * alpha, DRAWFLAG_NORMAL);
+
+ victim = textShortenToWidth(victim, name_maxwidth, font_size, stringwidth_colors);
+ victim_pos = pos + victim_left + name_top;
+ drawcolorcodedstring(victim_pos, victim, font_size, panel_fg_alpha * alpha, DRAWFLAG_NORMAL);
+
+ if (attacker != "")
{
- // X [did action to] Y
- attacker = textShortenToWidth(attacker, 0.48 * mySize_x - height, fontsize, stringwidth_colors);
- victim = textShortenToWidth(victim, 0.48 * mySize_x - height, fontsize, stringwidth_colors);
- :hud_config_notifyprint
- width_attacker = stringwidth(attacker, TRUE, fontsize);
- pos_attacker = pos + eX * (0.48 * mySize_x - height - width_attacker) + eY * ((0.5 * fontsize_y + i * height) + (0.5 * (height - fontheight)));
- pos_victim = pos + eX * (0.52 * mySize_x + height) + eY * ((0.5 * fontsize_y + i * height) + (0.5 * (height - fontheight)));
- pos_icon = pos + eX * 0.5 * mySize_x - eX * height + eY * i * height;
-
- drawpic_aspect_skin(pos_icon, icon, '2 1 0' * height, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
- drawcolorcodedstring(pos_attacker, attacker, fontsize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
- drawcolorcodedstring(pos_victim, victim, fontsize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
+ attacker = textShortenToWidth(attacker, name_maxwidth, font_size, stringwidth_colors);
+ attacker_pos = pos + attacker_right - eX * stringwidth(attacker, TRUE, font_size) + name_top;
+ drawcolorcodedstring(attacker_pos, attacker, font_size, panel_fg_alpha * alpha, DRAWFLAG_NORMAL);
}
}
}
+
+ notify_count = count;
}
// Timer (#5)
// Radar (#6)
//
+
+float HUD_Radar_Clickable()
+{
+ return hud_panel_radar_mouse && !hud_panel_radar_temp_hidden;
+}
+
+void HUD_Radar_Show_Maximized(float show,float clickable)
+{
+ hud_panel_radar_maximized = show;
+ hud_panel_radar_temp_hidden = 0;
+
+ if ( show )
+ {
+ if (clickable)
+ {
+ if(autocvar_hud_cursormode)
+ setcursormode(1);
+ hud_panel_radar_mouse = 1;
+ }
+ }
+ else if ( hud_panel_radar_mouse )
+ {
+ hud_panel_radar_mouse = 0;
+ mouseClicked = 0;
+ if(autocvar_hud_cursormode)
+ if(!mv_active)
+ setcursormode(0);
+ }
+}
+void HUD_Radar_Hide_Maximized()
+{
+ HUD_Radar_Show_Maximized(false,false);
+}
+
+
+float HUD_Radar_InputEvent(float bInputType, float nPrimary, float nSecondary)
+{
+ if(!hud_panel_radar_maximized || !hud_panel_radar_mouse ||
+ autocvar__hud_configure || mv_active)
+ return false;
+
+ if(bInputType == 3)
+ {
+ mousepos_x = nPrimary;
+ mousepos_y = nSecondary;
+ return true;
+ }
+
+ if(nPrimary == K_MOUSE1)
+ {
+ if(bInputType == 0) // key pressed
+ mouseClicked |= S_MOUSE1;
+ else if(bInputType == 1) // key released
+ mouseClicked -= (mouseClicked & S_MOUSE1);
+ }
+ else if(nPrimary == K_MOUSE2)
+ {
+ if(bInputType == 0) // key pressed
+ mouseClicked |= S_MOUSE2;
+ else if(bInputType == 1) // key released
+ mouseClicked -= (mouseClicked & S_MOUSE2);
+ }
+ else if ( nPrimary == K_ESCAPE && bInputType == 0 )
+ {
+ HUD_Radar_Hide_Maximized();
+ }
+ else
+ {
+ // allow console/use binds to work without hiding the map
+ string con_keys;
+ float keys;
+ float i;
+ con_keys = strcat(findkeysforcommand("toggleconsole", 0)," ",findkeysforcommand("+use", 0)) ;
+ keys = tokenize(con_keys); // findkeysforcommand returns data for this
+ for (i = 0; i < keys; ++i)
+ {
+ if(nPrimary == stof(argv(i)))
+ return false;
+ }
+
+ if ( getstati(STAT_HEALTH) <= 0 )
+ {
+ // Show scoreboard
+ if ( bInputType < 2 )
+ {
+ con_keys = findkeysforcommand("+showscores", 0);
+ keys = tokenize(con_keys);
+ for (i = 0; i < keys; ++i)
+ {
+ if ( nPrimary == stof(argv(i)) )
+ {
+ hud_panel_radar_temp_hidden = bInputType == 0;
+ return false;
+ }
+ }
+ }
+ }
+ else if ( bInputType == 0 )
+ HUD_Radar_Hide_Maximized();
+
+ return false;
+ }
+
+ return true;
+}
+
+void HUD_Radar_Mouse()
+{
+ if ( !hud_panel_radar_mouse ) return;
+ if(mv_active) return;
+
+ if ( intermission )
+ {
+ HUD_Radar_Hide_Maximized();
+ return;
+ }
+
+ if(mouseClicked & S_MOUSE2)
+ {
+ HUD_Radar_Hide_Maximized();
+ return;
+ }
+
+ if(!autocvar_hud_cursormode)
+ {
+ mousepos = mousepos + getmousepos() * autocvar_menu_mouse_speed;
+
+ mousepos_x = bound(0, mousepos_x, vid_conwidth);
+ mousepos_y = bound(0, mousepos_y, vid_conheight);
+ }
+
+ HUD_Panel_UpdateCvars();
+
+
+ panel_size = autocvar_hud_panel_radar_maximized_size;
+ panel_size_x = bound(0.2, panel_size_x, 1) * vid_conwidth;
+ panel_size_y = bound(0.2, panel_size_y, 1) * vid_conheight;
+ panel_pos_x = (vid_conwidth - panel_size_x) / 2;
+ panel_pos_y = (vid_conheight - panel_size_y) / 2;
+
+ if(mouseClicked & S_MOUSE1)
+ {
+ // click outside
+ if ( mousepos_x < panel_pos_x || mousepos_x > panel_pos_x + panel_size_x ||
+ mousepos_y < panel_pos_y || mousepos_y > panel_pos_y + panel_size_y )
+ {
+ HUD_Radar_Hide_Maximized();
+ return;
+ }
+ vector pos = teamradar_texcoord_to_3dcoord(teamradar_2dcoord_to_texcoord(mousepos),view_origin_z);
+ localcmd(sprintf("cmd ons_spawn %f %f %f",pos_x,pos_y,pos_z));
+
+ HUD_Radar_Hide_Maximized();
+ return;
+ }
+
+
+ const vector cursorsize = '32 32 0';
+ drawpic(mousepos-'8 4 0', strcat("gfx/menu/", autocvar_menu_skin, "/cursor.tga"), cursorsize, '1 1 1', 0.8, DRAWFLAG_NORMAL);
+}
+
void HUD_Radar(void)
{
if (!autocvar__hud_configure)
}
}
}
+
+ if ( hud_panel_radar_temp_hidden )
+ return;
HUD_Panel_UpdateCvars();
for(tm = world; (tm = find(tm, classname, "radarlink")); )
draw_teamradar_link(tm.origin, tm.velocity, tm.team);
+
+ vector coord;
+ vector brightcolor;
for(tm = world; (tm = findflags(tm, teamradar_icon, 0xFFFFFF)); )
+ {
+ if ( hud_panel_radar_mouse )
+ if ( tm.health > 0 )
+ if ( tm.team == myteam+1 )
+ {
+ coord = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(tm.origin));
+ if ( vlen(mousepos-coord) < 8 )
+ {
+ brightcolor_x = min(1,tm.teamradar_color_x*1.5);
+ brightcolor_y = min(1,tm.teamradar_color_y*1.5);
+ brightcolor_z = min(1,tm.teamradar_color_z*1.5);
+ drawpic(coord - '8 8 0', "gfx/teamradar_icon_glow", '16 16 0', brightcolor, panel_fg_alpha, 0);
+ }
+ }
+
draw_teamradar_icon(tm.origin, tm.teamradar_icon, tm, tm.teamradar_color, panel_fg_alpha);
+ }
for(tm = world; (tm = find(tm, classname, "entcs_receiver")); )
{
color2 = GetPlayerColor(tm.sv_entnum);
draw_teamradar_player(view_origin, view_angles, '1 1 1');
drawresetcliparea();
+
+ if ( hud_panel_radar_mouse )
+ {
+ string message = "Click to select teleport destination";
+
+ if ( getstati(STAT_HEALTH) <= 0 )
+ {
+ message = "Click to select spawn location";
+ }
+
+ drawcolorcodedstring(pos + '0.5 0 0' * (mySize_x - stringwidth(message, TRUE, hud_fontsize)) - '0 1 0' * hud_fontsize_y * 2,
+ message, hud_fontsize, hud_panel_radar_foreground_alpha, DRAWFLAG_NORMAL);
+
+ hud_panel_radar_bottom = pos_y + mySize_y + hud_fontsize_y;
+ }
}
// Score (#7)
vector distribution_color;
entity tm, pl, me;
- #ifdef COMPAT_XON050_ENGINE
- me = (spectatee_status > 0) ? playerslots[spectatee_status - 1] : playerslots[player_localentnum - 1];
- #else
me = playerslots[player_localentnum - 1];
- #endif
if((scores_flags[ps_primary] & SFL_TIME) && !teamplay) { // race/cts record display on HUD
string timer, distrtimer;
//Manage the progress bar if any
if (nb_pb_starttime > 0)
{
- dt = mod(time - nb_pb_starttime, nb_pb_period);
+ dt = (time - nb_pb_starttime) % nb_pb_period;
// one period of positive triangle
p = 2 * dt / nb_pb_period;
if (p > 1)
if(spectatee_status == -1)
s = _("^1Observing");
else
- #ifdef COMPAT_XON050_ENGINE
- s = sprintf(_("^1Spectating: ^7%s"), GetPlayerName(spectatee_status - 1));
- #else
s = sprintf(_("^1Spectating: ^7%s"), GetPlayerName(player_localentnum - 1));
- #endif
drawInfoMessage(s)
if(spectatee_status == -1)
}
string blinkcolor;
- if(mod(time, 1) >= 0.5)
+ if(time % 1 >= 0.5)
blinkcolor = "^1";
else
blinkcolor = "^3";
{
float r;
r = random();
- if (r > 0.9)
+ if (r > 0.75)
centerprint_generic(floor(r*1000), strcat(sprintf("^3Countdown message at time %s", seconds_tostring(time)), ", seconds left: ^COUNT"), 1, 10);
- else if (r > 0.8)
+ else if (r > 0.5)
centerprint_generic(0, sprintf("^1Multiline message at time %s that\n^1lasts longer than normal", seconds_tostring(time)), 20, 0);
else
centerprint_hud(sprintf("Message at time %s", seconds_tostring(time)));
hud_fade_alpha = 1 - autocvar__menu_alpha;
}
HUD_Panel_UpdateCvars();
-
- if(scoreboard_fade_alpha)
+
+ if ( HUD_Radar_Clickable() )
+ {
+ if (hud_panel_radar_bottom >= 0.96 * vid_conheight)
+ return;
+
+ panel_pos = eY * hud_panel_radar_bottom + eX * 0.5 * (vid_conwidth - panel_size_x);
+ panel_size_y = min(panel_size_y, vid_conheight - hud_panel_radar_bottom);
+ }
+ else if(scoreboard_fade_alpha)
{
hud_fade_alpha = hud_fade_alpha_save;
else // Expiring soon, so fade it out.
a = (centerprint_expire_time[j] - time) / max(0.0001, autocvar_hud_panel_centerprint_fade_out);
- if (a <= 0.5/255.0) // Guaranteed invisible - don't show.
+ // while counting down show it anyway in order to hold the current message position
+ if (a <= 0.5/255.0 && centerprint_countdown_num[j] == 0) // Guaranteed invisible - don't show.
continue;
if (a > 1)
a = 1;
}
}
+ // Buffs (#18)
+ //
+ void HUD_Buffs(void)
+ {
+ float buffs = getstati(STAT_BUFFS, 0, 24);
+ if(!autocvar__hud_configure)
+ {
+ if(!autocvar_hud_panel_buffs) return;
+ if(spectatee_status == -1) return;
+ if(getstati(STAT_HEALTH) <= 0) return;
+ if(!buffs) return;
+ }
+ else
+ {
+ buffs = Buff_Type_first.items; // force first buff
+ }
+
+ float b = 0; // counter to tell other functions that we have buffs
+ entity e;
+ string s = "";
+ for(e = Buff_Type_first; e; e = e.enemy) if(buffs & e.items)
+ {
+ ++b;
+ string o = strcat(rgb_to_hexcolor(Buff_Color(e.items)), Buff_PrettyName(e.items));
+ if(s == "")
+ s = o;
+ else
+ s = strcat(s, " ", o);
+ }
+
+ HUD_Panel_UpdateCvars();
+
+ draw_beginBoldFont();
+
+ vector pos, mySize;
+ pos = panel_pos;
+ mySize = panel_size;
+
+ HUD_Panel_DrawBg(bound(0, b, 1));
+ if(panel_bg_padding)
+ {
+ pos += '1 1 0' * panel_bg_padding;
+ mySize -= '2 2 0' * panel_bg_padding;
+ }
+
+ //float panel_ar = mySize_x/mySize_y;
+ //float is_vertical = (panel_ar < 1);
+ //float buff_iconalign = autocvar_hud_panel_buffs_iconalign;
+ vector buff_offset = '0 0 0';
+
+ for(e = Buff_Type_first; e; e = e.enemy) if(buffs & e.items)
+ {
+ //DrawNumIcon(pos + buff_offset, mySize, shield, "shield", is_vertical, buff_iconalign, '1 1 1', 1);
+ drawcolorcodedstring_aspect(pos + buff_offset, s, mySize, panel_fg_alpha * 0.5, DRAWFLAG_NORMAL);
+ }
+
+ draw_endBoldFont();
+ }
+
+
/*
==================
Main HUD system
hud_skin_prev = strzone(autocvar_hud_skin);
}
- #ifdef COMPAT_XON050_ENGINE
- current_player = (spectatee_status > 0) ? spectatee_status : player_localentnum;
- #else
current_player = player_localentnum;
- #endif
// draw the dock
if(autocvar_hud_dock != "" && autocvar_hud_dock != "0")
}
else if(hud_dock_color == "pants") {
f = stof(getplayerkeyvalue(current_player - 1, "colors"));
- color = colormapPaletteColor(mod(f, 16), 1);
+ color = colormapPaletteColor(f % 16, 1);
}
else
color = stov(hud_dock_color);
}
}
if (warning)
- print(_("Automatically fixed wrong/missing panel numbers in _hud_panelorder\n"));
+ dprint("Automatically fixed wrong/missing panel numbers in _hud_panelorder\n");
cvar_set("_hud_panelorder", s);
if(hud_panelorder_prev)
float hud_draw_maximized;
float hud_panel_radar_maximized;
+float hud_panel_radar_mouse;
+float hud_panel_radar_bottom;
+float hud_panel_radar_temp_hidden;
float chat_panel_modified;
float radar_panel_modified;
+void HUD_Radar_Hide_Maximized();
+
vector mousepos;
vector panel_click_distance; // mouse cursor distance from the top left corner of the panel (saved only upon a click)
vector panel_click_resizeorigin; // coordinates for opposite point when resizing
float current_player;
+float mv_active;
+
#define HUD_PANELS \
HUD_PANEL(WEAPONS , HUD_Weapons , weapons) \
HUD_PANEL(ENGINEINFO , HUD_EngineInfo , engineinfo) \
HUD_PANEL(INFOMESSAGES , HUD_InfoMessages , infomessages) \
HUD_PANEL(PHYSICS , HUD_Physics , physics) \
- HUD_PANEL(CENTERPRINT , HUD_CenterPrint , centerprint)
+ HUD_PANEL(CENTERPRINT , HUD_CenterPrint , centerprint) \
+ HUD_PANEL(BUFFS , HUD_Buffs , buffs)
#define HUD_PANEL(NAME,draw_func,name) \
float HUD_PANEL_##NAME; \
if(panel_bg_color_str == "shirt") {\
panel_bg_color = colormapPaletteColor(floor(stof(getplayerkeyvalue(current_player - 1, "colors")) / 16), 0);\
} else if(panel_bg_color_str == "pants") {\
- panel_bg_color = colormapPaletteColor(mod(stof(getplayerkeyvalue(current_player - 1, "colors")), 16), 1);\
+ panel_bg_color = colormapPaletteColor(stof(getplayerkeyvalue(current_player - 1, "colors")) % 16, 1);\
} else {\
panel_bg_color = stov(panel_bg_color_str);\
}\
HUD_Panel_GetBorder() \
} ENDS_WITH_CURLY_BRACE
+ #define NOTIFY_MAX_ENTRIES 10
+ #define NOTIFY_ICON_MARGIN 0.02
- #define KN_MAX_ENTRIES 10
+ float notify_index;
+ float notify_count;
+ float notify_times[NOTIFY_MAX_ENTRIES];
+ string notify_attackers[NOTIFY_MAX_ENTRIES];
+ string notify_victims[NOTIFY_MAX_ENTRIES];
+ string notify_icons[NOTIFY_MAX_ENTRIES];
- float kn_index;
- float notify_times[KN_MAX_ENTRIES];
- string notify_icon[KN_MAX_ENTRIES];
- string notify_attackers[KN_MAX_ENTRIES];
- string notify_victims[KN_MAX_ENTRIES];
void HUD_Notify_Push(string icon, string attacker, string victim);
var void HUD_ModIcons_GameType(vector pos, vector size);
float mv_num_maps;
-float mv_active;
string mv_maps[MAPVOTE_COUNT];
string mv_pics[MAPVOTE_COUNT];
string mv_pk3[MAPVOTE_COUNT];
float mv_preview[MAPVOTE_COUNT];
float mv_votes[MAPVOTE_COUNT];
+ float mv_avail[MAPVOTE_COUNT];
+ float mv_avail_start[MAPVOTE_COUNT];
entity mv_pk3list;
float mv_abstain;
float mv_ownvote;
float mv_detail;
float mv_timeout;
- float mv_maps_mask;
float mv_top2_time;
float mv_top2_alpha;
vector mv_mousepos;
float mv_selection;
+ float mv_columns;
+ float mv_mouse_selection;
+ float mv_selection_keyboard;
+
+ float gametypevote;
+ string mapvote_chosenmap;
+ vector gtv_text_size;
+ vector gtv_text_size_small;
string MapVote_FormatMapItem(float id, string map, float count, float maxwidth, vector fontsize)
{
{
if(count == 1)
post = _(" (1 vote)");
- else if(count >= 0)
+ else if(count >= 0 && mv_avail[id] == GTV_AVAILABLE)
post = sprintf(_(" (%d votes)"), count);
else
post = "";
return strcat(pre, map, post);
}
- vector MapVote_RGB(float id, float count)
+ string GameTypeVote_DescriptionByID(float id)
+ {
+ return MapInfo_Type_Description(MapInfo_Type_FromString(mv_maps[id]));
+ }
+
+ vector MapVote_RGB(float id)
{
- if(count < 0)
+ if(mv_avail[id] != GTV_AVAILABLE)
return '1 1 1';
if(id == mv_ownvote)
return '0 1 0';
return '1 1 1';
}
+ void GameTypeVote_DrawGameTypeItem(vector pos, float maxh, float tsize, string gtype, string pic, float count, float id)
+ {
+ float alpha;
+ float desc_padding = gtv_text_size_x * 3;
+ float rect_margin = hud_fontsize_y / 2;
+ vector rect_pos = pos - '0.5 0.5 0' * rect_margin;
+ vector rect_size = '1 1 0';
+ rect_size_x = tsize + rect_margin;
+ rect_size_y = maxh + rect_margin;
+ vector rgb = MapVote_RGB(id);
+ vector offset = pos;
+ float nlines = 0;
+
+ if(mv_avail_start[id] != GTV_AVAILABLE)
+ alpha = 0.2;
+ else if ( mv_avail[id] != GTV_AVAILABLE && mv_top2_alpha)
+ alpha = mv_top2_alpha;
+ else
+ alpha = 1;
+
+ if(id == mv_selection && mv_avail[id] == GTV_AVAILABLE)
+ {
+ drawfill(rect_pos, rect_size, '1 1 1', 0.1, DRAWFLAG_NORMAL);
+ }
+ if(id == mv_ownvote)
+ {
+ drawfill(rect_pos, rect_size, rgb, 0.1*alpha, DRAWFLAG_NORMAL);
+ drawborderlines(autocvar_scoreboard_border_thickness, rect_pos, rect_size, rgb, alpha, DRAWFLAG_NORMAL);
+ }
+
+ entity title;
+ title = spawn();
+ title.message = MapVote_FormatMapItem(id, MapInfo_Type_ToText(MapInfo_Type_FromString(gtype)),
+ count, tsize, gtv_text_size);
+ title.origin = pos-offset;
+
+ pos_y += gtv_text_size_small_y;
+ pos_y += gtv_text_size_y/2;
+
+ maxh -= gtv_text_size_y;
+
+ entity picent = spawn();
+ picent.origin = pos-offset;
+ picent.maxs = '1 1 0 ' * min(maxh, desc_padding) * 0.8;
+
+ pos_x += desc_padding;
+ tsize -= desc_padding;
+
+ string thelabel = GameTypeVote_DescriptionByID(id), ts;
+ entity last = title;
+ entity next = world;
+ if( thelabel != "")
+ {
+ float i,n = tokenizebyseparator(thelabel, "\n");
+ for(i = 0; i < n && maxh > (nlines+1)*gtv_text_size_small_y; ++i)
+ {
+ getWrappedLine_remaining = argv(i);
+ while(getWrappedLine_remaining && maxh > (nlines+1)*gtv_text_size_small_y)
+ {
+ ts = getWrappedLine(tsize, gtv_text_size_small, stringwidth_colors);
+ if (ts != "")
+ {
+ next = spawn();
+ next.message = ts;
+ next.origin = pos-offset;
+ last.chain = next;
+ last = next;
+ pos_y += gtv_text_size_small_y;
+ nlines++;
+ }
+ }
+ }
+ }
+
+ maxh -= max(nlines*gtv_text_size_small_y,picent.maxs_y);
+ if ( maxh > 0 )
+ offset_y += maxh/2;
+ drawstring(title.origin+offset, title.message, gtv_text_size, rgb, alpha, DRAWFLAG_NORMAL);
+
+ if(pic != "")
+ drawpic(picent.origin+offset, pic, picent.maxs, '1 1 1', alpha, DRAWFLAG_NORMAL);
+
+ for ( last = title.chain; last ; )
+ {
+ drawstring(last.origin+offset, last.message, gtv_text_size_small, '1 1 1', alpha, DRAWFLAG_NORMAL);
+ next = last;
+ last = last.chain;
+ remove(next);
+ }
+
+ remove(picent);
+ remove(title);
+ }
+
void MapVote_DrawMapItem(vector pos, float isize, float tsize, string map, string pic, float count, float id)
{
vector img_size = '0 0 0';
isize -= hud_fontsize_y; // respect the text when calculating the image size
- rgb = MapVote_RGB(id, count);
+ rgb = MapVote_RGB(id);
img_size_y = isize;
img_size_x = isize / 0.75; // 4:3 x can be stretched easily, height is defined in isize
text_size = stringwidth(label, false, hud_fontsize);
float theAlpha;
- if (count < 0 && mv_top2_alpha)
+ if (mv_avail[id] != GTV_AVAILABLE && mv_top2_alpha)
theAlpha = mv_top2_alpha;
else
theAlpha = 1;
else
drawborderlines(autocvar_scoreboard_border_thickness, pos, img_size, '0 0 0', theAlpha, DRAWFLAG_NORMAL);
- if(id == mv_selection && count >= 0)
+ if(id == mv_selection && mv_avail[id] == GTV_AVAILABLE)
drawfill(pos, img_size, '1 1 1', 0.1, DRAWFLAG_NORMAL);
}
float text_size;
string label;
- rgb = MapVote_RGB(id, count);
+ rgb = MapVote_RGB(id);
pos_y = pos_y + hud_fontsize_y;
vector MapVote_GridVec(vector gridspec, float i, float m)
{
float r;
- r = mod(i, m);
+ r = i % m;
return
'1 0 0' * (gridspec_x * r)
+
float MapVote_Selection(vector topleft, vector cellsize, float rows, float columns)
{
- float cell;
+
float c, r;
- cell = -1;
+ mv_mouse_selection = -1;
for (r = 0; r < rows; ++r)
for (c = 0; c < columns; ++c)
mv_mousepos_y >= topleft_y + cellsize_y * r &&
mv_mousepos_y <= topleft_y + cellsize_y * (r + 1))
{
- cell = r * columns + c;
+ mv_mouse_selection = r * columns + c;
break;
}
}
- if (cell >= mv_num_maps)
- cell = -1;
+ if (mv_mouse_selection >= mv_num_maps)
+ mv_mouse_selection = -1;
- if (mv_abstain && cell < 0)
- return mv_num_maps;
+ if (mv_abstain && mv_mouse_selection < 0)
+ mv_mouse_selection = mv_num_maps;
- return cell;
+ if ( mv_selection_keyboard )
+ return mv_selection;
+
+ return mv_mouse_selection;
}
void MapVote_Draw()
vector pos;
float isize;
float center;
- float columns, rows;
+ float rows;
float tsize;
vector dist = '0 0 0';
if (!autocvar_hud_cursormode)
{
- mv_mousepos = mv_mousepos + getmousepos();
+ vector mpos = mv_mousepos + getmousepos();
+ mpos_x = bound(0, mpos_x, vid_conwidth);
+ mpos_y = bound(0, mpos_y, vid_conheight);
+
+ if ( mpos_x != mv_mousepos_x || mpos_y != mv_mousepos_y )
+ mv_selection_keyboard = 0;
+ mv_mousepos = mpos;
- mv_mousepos_x = bound(0, mv_mousepos_x, vid_conwidth);
- mv_mousepos_y = bound(0, mv_mousepos_y, vid_conheight);
}
center = (vid_conwidth - 1)/2;
pos_z = 0;
draw_beginBoldFont();
- map = _("Vote for a map");
+ map = ((gametypevote) ? _("Decide the gametype") : _("Vote for a map"));
pos_x = center - stringwidth(map, false, '12 0 0');
drawstring(pos, map, '24 24 0', '1 1 1', 1, DRAWFLAG_NORMAL);
pos_y += 26;
+ if( mapvote_chosenmap != "" )
+ {
+ pos_x = center - stringwidth(mapvote_chosenmap, false, hud_fontsize*1.5/2);
+ drawstring(pos, mapvote_chosenmap, hud_fontsize*1.5, '1 1 1', 1, DRAWFLAG_NORMAL);
+ pos_y += hud_fontsize_y*2;
+ }
+
i = ceil(max(0, mv_timeout - time));
map = sprintf(_("%d seconds left"), i);
pos_x = center - stringwidth(map, false, '8 0 0');
if(mv_abstain)
mv_num_maps -= 1;
- if(mv_num_maps > 3)
- {
- columns = 3;
- } else {
- columns = mv_num_maps;
- }
- rows = ceil(mv_num_maps / columns);
+ rows = ceil(mv_num_maps / mv_columns);
- dist_x = (xmax - xmin) / columns;
+ dist_x = (xmax - xmin) / mv_columns;
dist_y = (ymax - pos_y) / rows;
- tsize = dist_x - 10;
- isize = min(dist_y - 10, 0.75 * tsize);
- mv_selection = MapVote_Selection(pos, dist, rows, columns);
+ if ( gametypevote )
+ {
+ tsize = dist_x - hud_fontsize_y;
+ isize = dist_y;
+ float maxheight = (ymax - pos_y) / 3;
+ if ( isize > maxheight )
+ {
+ pos_x += (isize - maxheight)/2;
+ isize = maxheight;
+ }
+ else
+ dist_y += hud_fontsize_y;
+ pos_x = ( vid_conwidth - dist_x * mv_columns ) / 2;
+ }
+ else
+ {
+ tsize = dist_x - 10;
+ isize = min(dist_y - 10, 0.75 * tsize);
+ }
+
+ mv_selection = MapVote_Selection(pos, dist, rows, mv_columns);
- pos_x += (xmax - xmin) / (2 * columns);
+ if ( !gametypevote )
+ pos_x += dist_x / 2;
pos_y += (dist_y - isize) / 2;
ymax -= isize;
if (mv_top2_time)
mv_top2_alpha = max(0.2, 1 - (time - mv_top2_time)*(time - mv_top2_time));
+ void (vector, float, float, string, string, float, float) DrawItem;
+
+ if(gametypevote)
+ DrawItem = GameTypeVote_DrawGameTypeItem;
+ else
+ DrawItem = MapVote_DrawMapItem;
+
for(i = 0; i < mv_num_maps; ++i)
{
tmp = mv_votes[i]; // FTEQCC bug: too many array accesses in the function call screw it up
map = mv_maps[i];
if(mv_preview[i])
- MapVote_DrawMapItem(pos + MapVote_GridVec(dist, i, columns), isize, tsize, map, mv_pics[i], tmp, i);
+ DrawItem(pos + MapVote_GridVec(dist, i, mv_columns), isize, tsize, map, mv_pics[i], tmp, i);
else
- MapVote_DrawMapItem(pos + MapVote_GridVec(dist, i, columns), isize, tsize, map, "", tmp, i);
+ DrawItem(pos + MapVote_GridVec(dist, i, mv_columns), isize, tsize, map, "", tmp, i);
}
if(mv_abstain)
MapVote_CheckPK3(pic, pk3, id);
}
+ void MapVote_ReadMask()
+ {
+ float i;
+ if ( mv_num_maps < 24 )
+ {
+ float mask, power;
+ if(mv_num_maps < 8)
+ mask = ReadByte();
+ else if(mv_num_maps < 16)
+ mask = ReadShort();
+ else
+ mask = ReadLong();
+
+ for(i = 0, power = 1; i < mv_num_maps; ++i, power *= 2)
+ mv_avail[i] = (mask & power) ? GTV_AVAILABLE : GTV_FORBIDDEN;
+ }
+ else
+ {
+ for(i = 0; i < mv_num_maps; ++i )
+ mv_avail[i] = ReadByte();
+ }
+ }
+
#define NUM_SSDIRS 4
string ssdirs[NUM_SSDIRS];
float n_ssdirs;
void MapVote_Init()
{
- float i, j, power;
+ float i, j;
string map, pk3, s;
precache_sound ("misc/invshot.wav");
if(autocvar_hud_cursormode) { setcursormode(1); }
else { mv_mousepos = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight; }
mv_selection = -1;
+ mv_selection_keyboard = 0;
for(n_ssdirs = 0; ; ++n_ssdirs)
{
mv_ownvote = -1;
mv_timeout = ReadCoord();
- if(mv_num_maps <= 8)
- mv_maps_mask = ReadByte();
- else
- mv_maps_mask = ReadShort();
+ gametypevote = ReadByte();
+
+ float mv_real_num_maps = mv_num_maps - mv_abstain;
+
+ if(gametypevote)
+ {
+ mapvote_chosenmap = strzone(ReadString());
+ if ( gametypevote == 2 )
+ gametypevote = 0;
+
+ gtv_text_size = hud_fontsize*1.4;
+ gtv_text_size_small = hud_fontsize*1.1;
+
+ if (mv_real_num_maps > 8 )
+ mv_columns = 3;
+ else
+ mv_columns = min(2, mv_real_num_maps);
+ }
+ else
+ {
+ if (mv_real_num_maps > 16)
+ mv_columns = 5;
+ else if (mv_real_num_maps > 9)
+ mv_columns = 4;
+ else if(mv_real_num_maps > 3)
+ mv_columns = 3;
+ else
+ mv_columns = mv_real_num_maps;
+ }
+
+ MapVote_ReadMask();
+ for(i = 0; i < mv_num_maps; ++i )
+ mv_avail_start[i] = mv_avail[i];
// Assume mv_pk3list is world, there should only be 1 mapvote per round
mv_pk3list = world; // I'm still paranoid!
- for(i = 0, power = 1; i < mv_num_maps; ++i, power *= 2)
+ for(i = 0; i < mv_num_maps; ++i)
{
mv_votes[i] = 0;
- if(mv_maps_mask & power)
- {
- map = strzone(ReadString());
- pk3 = strzone(ReadString());
- j = bound(0, ReadByte(), n_ssdirs - 1);
-
- mv_maps[i] = map;
- mv_pk3[i] = pk3;
- map = strzone(strcat(ssdirs[j], "/", map));
- mv_pics[i] = map;
+ map = strzone(ReadString());
+ pk3 = strzone(ReadString());
+ j = bound(0, ReadByte(), n_ssdirs - 1);
- mv_preview[i] = false;
+ mv_maps[i] = map;
+ mv_pk3[i] = pk3;
+ mv_avail[i] = ReadByte();
- MapVote_CheckPic(map, pk3, i);
+ if(gametypevote)
+ {
+ //map = strzone(strcat("gfx/menu/default/gametype_", map));
+ //map = strzone(sprintf("gfx/menu/%s/gametype_%s", autocvar_menu_skin, map));
+ string mv_picpath = sprintf("gfx/menu/%s/gametype_%s", autocvar_menu_skin, map);
+ if(precache_pic(mv_picpath) == "")
+ mv_picpath = strcat("gfx/menu/default/gametype_", map);
+ map = strzone(mv_picpath);
+ mv_pics[i] = map;
+ mv_preview[i] = PreviewExists(map);
}
else
{
- mv_maps[i] = strzone("if-you-see-this-the-code-is-broken");
- mv_pk3[i] = strzone("if-you-see-this-the-code-is-broken");
- mv_pics[i] = strzone("if-you-see-this-the-code-is-broken");
+ map = strzone(strcat(ssdirs[j], "/", map));
+ mv_pics[i] = map;
mv_preview[i] = false;
+ MapVote_CheckPic(map, pk3, i);
}
}
n_ssdirs = 0;
}
+ void MapVote_SendChoice(float index)
+ {
+ localcmd(strcat("\nimpulse ", ftos(index+1), "\n"));
+ }
+
+ float MapVote_MoveLeft(float pos)
+ {
+ float imp;
+ if ( pos < 0 )
+ imp = mv_num_maps - 1;
+ else
+ imp = pos < 1 ? mv_num_maps - 1 : pos - 1;
+ if ( mv_avail[imp] != GTV_AVAILABLE && imp != mv_ownvote )
+ imp = MapVote_MoveLeft(imp);
+ return imp;
+ }
+ float MapVote_MoveRight(float pos)
+ {
+ float imp;
+ if ( pos < 0 )
+ imp = 0;
+ else
+ imp = pos >= mv_num_maps - 1 ? 0 : pos + 1;
+ if ( mv_avail[imp] != GTV_AVAILABLE && imp != mv_ownvote )
+ imp = MapVote_MoveRight(imp);
+ return imp;
+ }
+ float MapVote_MoveUp(float pos)
+ {
+ float imp;
+ if ( pos < 0 )
+ imp = mv_num_maps - 1;
+ else
+ {
+ imp = pos - mv_columns;
+ if ( imp < 0 )
+ {
+ imp = floor(mv_num_maps/mv_columns)*mv_columns + pos % mv_columns;
+ if ( imp >= mv_num_maps )
+ imp -= mv_columns;
+ }
+ }
+ if ( mv_avail[imp] != GTV_AVAILABLE && imp != mv_ownvote )
+ imp = MapVote_MoveUp(imp);
+ return imp;
+ }
+ float MapVote_MoveDown(float pos)
+ {
+ float imp;
+ if ( pos < 0 )
+ imp = 0;
+ else
+ {
+ imp = pos + mv_columns;
+ if ( imp >= mv_num_maps )
+ imp = imp % mv_columns;
+ }
+ if ( mv_avail[imp] != GTV_AVAILABLE && imp != mv_ownvote )
+ imp = MapVote_MoveDown(imp);
+ return imp;
+ }
+
float MapVote_InputEvent(float bInputType, float nPrimary, float nSecondary)
{
float imp;
{
mv_mousepos_x = nPrimary;
mv_mousepos_y = nSecondary;
+ mv_selection_keyboard = 0;
return true;
}
case K_KP_8: localcmd("\nimpulse 8\n"); return true;
case K_KP_9: localcmd("\nimpulse 9\n"); return true;
case K_KP_0: localcmd("\nimpulse 10\n"); return true;
+
+ case K_RIGHTARROW:
+ mv_selection_keyboard = 1;
+ mv_selection = MapVote_MoveRight(mv_selection);
+ return true;
+ case K_LEFTARROW:
+ mv_selection_keyboard = 1;
+ mv_selection = MapVote_MoveLeft(mv_selection);
+ return true;
+ case K_DOWNARROW:
+ mv_selection_keyboard = 1;
+ mv_selection = MapVote_MoveDown(mv_selection);
+ return true;
+ case K_UPARROW:
+ mv_selection_keyboard = 1;
+ mv_selection = MapVote_MoveUp(mv_selection);
+ return true;
+ case K_KP_ENTER:
+ case K_ENTER:
+ case K_SPACE:
+ if ( mv_selection_keyboard )
+ MapVote_SendChoice(mv_selection);
+ return true;
}
if (nPrimary == K_MOUSE1)
+ {
+ mv_selection_keyboard = 0;
+ mv_selection = mv_mouse_selection;
if (mv_selection >= 0)
{
imp = min(mv_selection + 1, mv_num_maps);
localcmd(strcat("\nimpulse ", ftos(imp), "\n"));
return true;
}
+ }
return false;
}
void MapVote_UpdateMask()
{
- float i, power;
- float oldmask;
-
- oldmask = mv_maps_mask;
- if(mv_num_maps <= 8)
- mv_maps_mask = ReadByte();
- else
- mv_maps_mask = ReadShort();
-
- if((oldmask & mv_maps_mask) != oldmask)
- if((oldmask & mv_maps_mask) == mv_maps_mask)
- sound(world, CH_INFO, "misc_invshot.wav", VOL_BASE, ATTEN_NONE);
-
- // remove votes that no longer apply
- for(i = 0, power = 1; i < mv_num_maps; ++i, power *= 2)
- if (!(mv_maps_mask & power))
- mv_votes[i] = -1;
-
+ MapVote_ReadMask();
mv_top2_time = time;
}
void MapVote_UpdateVotes()
{
- float i, power;
- for(i = 0, power = 1; i < mv_num_maps; ++i, power *= 2)
+ float i;
+ for(i = 0; i < mv_num_maps; ++i)
{
- if(mv_maps_mask & power)
+ if(mv_avail[i] == GTV_AVAILABLE)
{
if(mv_detail)
mv_votes[i] = ReadByte();
Defs.qc
../dpdefs/keycodes.qc
../common/constants.qh
+ ../common/stats.qh
../warpzonelib/anglestransform.qh
../warpzonelib/mathlib.qh
../warpzonelib/common.qh
../warpzonelib/client.qh
+ ../common/playerstats.qh
../common/teams.qh
../common/util.qh
+ ../common/nades.qh
+ ../common/buffs.qh
../common/test.qh
../common/counting.qh
- ../common/items.qh
- ../common/explosion_equation.qh
+ ../common/weapons/weapons.qh // TODO
../common/mapinfo.qh
../common/command/markup.qh
../common/command/rpn.qh
tturrets.qh
../server/tturrets/include/turrets_early.qh
../server/movelib.qc
+generator.qh
+controlpoint.qh
main.qh
vehicles/vehicles.qh
../common/csqcmodel_settings.qh
../csqcmodellib/common.qh
../csqcmodellib/cl_model.qh
../csqcmodellib/cl_player.qh
- projectile.qh
+ weapons/projectile.qh // TODO
player_skeleton.qh
sortlist.qc
miscfunctions.qc
+ ../server/t_items.qh
../server/t_items.qc
teamradar.qc
hook.qc
particles.qc
laser.qc
- projectile.qc
+ weapons/projectile.qc // TODO
gibs.qc
damage.qc
casings.qc
../common/test.qc
../common/util.qc
+ ../common/playerstats.qc
../common/notifications.qc
../common/command/markup.qc
../common/command/rpn.qc
../common/command/generic.qc
../common/mapinfo.qc
- ../common/items.qc
- ../server/w_all.qc
- ../common/explosion_equation.qc
+ ../common/weapons/weapons.qc // TODO
../common/urllib.qc
command/cl_cmd.qc
../common/monsters/monsters.qc
+ ../common/nades.qc
+ ../common/buffs.qc
+
../warpzonelib/anglestransform.qc
../warpzonelib/mathlib.qc
../warpzonelib/common.qc
../warpzonelib/client.qc
+
+generator.qc
+controlpoint.qc
+
tturrets.qc
player_skeleton.qc
"other gamemodes except DM.\n"));
}
- string HUD_DefaultColumnLayout()
- {
- return strcat( // fteqcc sucks
- "ping pl name | ",
- "-teams,race,lms/kills +freezetag/kills -teams,lms/deaths +freezetag/deaths -teams,lms,race,ka/suicides +freezetag/suicides -race,dm,tdm,ka,freezetag/frags ", // tdm already has this in "score"
- "+tdm/kills +tdm/deaths +tdm/suicides ",
- "+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns +ons/caps +ons/takes ",
- "+lms/lives +lms/rank ",
- "+kh/caps +kh/pushes +kh/destroyed ",
- "?+race/laps ?+race/time ?+race/fastest ",
- "+as/objectives +nexball/faults +nexball/goals +ka/pickups +ka/bckills +ka/bctime +freezetag/revivals ",
- "-lms,race,nexball/score");
- }
+ #define HUD_DefaultColumnLayout() \
+ "ping pl name | " \
+ "-teams,race,lms/kills +ft,tdm/kills -teams,lms/deaths +ft,tdm/deaths -teams,lms,race,ka/suicides +ft,tdm/suicides -race,dm,tdm,ka,ft/frags " /* tdm already has this in "score" */ \
-"+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns " \
++"+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns +ons/caps +ons/takes " \
+ "+lms/lives +lms/rank " \
+ "+kh/caps +kh/pushes +kh/destroyed " \
+ "?+race/laps ?+race/time ?+race/fastest " \
+ "+as/objectives +nb/faults +nb/goals +ka/pickups +ka/bckills +ka/bctime +ft/revivals " \
+ "-lms,race,nb/score"
void Cmd_HUD_SetFields(float argc)
{
float have_name = 0, have_primary = 0, have_secondary = 0, have_separator = 0;
float missing;
+ if(!gametype)
+ {
+ // set up a temporary scoreboard layout
+ // no layout can be properly set up until score_info data haven't been received
+ argc = tokenizebyseparator("0 1 ping pl name | score", " ");
+ ps_primary = 0;
+ scores_label[ps_primary] = strzone("score");
+ scores_flags[ps_primary] = SFL_ALLOW_HIDE;
+ }
+
// TODO: re enable with gametype dependant cvars?
if(argc < 3) // no arguments provided
argc = tokenizebyseparator(strcat("0 1 ", autocvar_scoreboard_columns), " ");
hud_field[hud_num_fields] = SP_PL;
} else if(str == "kd" || str == "kdr" || str == "kdratio" || str == "k/d") {
hud_field[hud_num_fields] = SP_KDRATIO;
- } else if(str == "sum" || str == "diff" || str == "f-d") {
+ } else if(str == "sum" || str == "diff" || str == "k-d") {
hud_field[hud_num_fields] = SP_SUM;
} else if(str == "name" || str == "nick") {
hud_field[hud_num_fields] = SP_NAME;
{
case SP_PING:
if (!pl.gotscores)
- return "\xEE\x82\x8D\xEE\x82\x8D\xEE\x82\x8D"; // >>> sign
+ return "\xE2\x96\xB6\xE2\x96\xB6\xE2\x96\xB6"; // >>> sign using U+25B6
//str = getplayerkeyvalue(pl.sv_entnum, "ping");
f = pl.ping;
if(f == 0)
hud_field_icon1 = "gfx/scoreboard/playercolor_shirt";
hud_field_icon1_rgb = colormapPaletteColor(floor(f / 16), 0);
hud_field_icon2 = "gfx/scoreboard/playercolor_pants";
- hud_field_icon2_rgb = colormapPaletteColor(mod(f, 16), 1);
+ hud_field_icon2_rgb = colormapPaletteColor(f % 16, 1);
}
}
return GetPlayerName(pl.sv_entnum);
return str;
}
- void HUD_PrintScoreboardItem(vector pos, entity pl, float is_self, float pl_number)
+ void HUD_PrintScoreboardItem(vector pos, vector item_size, entity pl, float is_self, float pl_number)
{
vector tmp, rgb;
rgb = Team_ColorRGB(pl.team);
rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
rgb_z = autocvar_scoreboard_color_bg_b + 0.5; }
- // Layout:
- tmp_x = sbwidth;
- tmp_y = hud_fontsize_y * 1.25;
- tmp_z = 0;
-
+ vector h_pos = pos - '1 1 0';
+ vector h_size = item_size + '2 0 0';
// alternated rows highlighting
if(is_self)
- drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
- else if((scoreboard_highlight) && (!mod(pl_number,2)))
- drawfill(pos - '1 1 0', tmp + '2 0 0', rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
+ drawfill(h_pos, h_size, rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
+ else if((scoreboard_highlight) && (!(pl_number % 2)))
+ drawfill(h_pos, h_size, rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
+ tmp_x = item_size_x;
tmp_y = 0;
+ tmp_z = 0;
for(i = 0; i < hud_num_fields; ++i)
{
pos_x -= hud_size[i] + hud_fontsize_x;
}
}
+
+ if(pl.eliminated)
+ drawfill(h_pos, h_size, '0 0 0', 0.5, DRAWFLAG_NORMAL);
}
/*
column_dim_x = hud_size[i] + hud_fontsize_x;
if (scoreboard_highlight)
{
- if (mod(i,2))
+ if (i % 2)
drawfill(pos - '0 1 0' - hud_fontsize_x / 2 * '1 0 0', column_dim, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
}
drawstring(pos, hud_title[i], hud_fontsize, rgb * 1.5, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
if (scoreboard_highlight)
{
- if (!mod(i,2))
+ if (!(i % 2))
{
if (i == hud_num_fields-1)
column_dim_x = hud_size[i] + hud_fontsize_x / 2 + 1;
pos_y += 1.25 * hud_fontsize_y; // skip the header
pos_y += autocvar_scoreboard_border_thickness;
+ // item size
+ tmp_x = sbwidth;
+ tmp_y = hud_fontsize_y * 1.25;
+
// fill the table and draw the rows
i = 0;
if (teamplay)
{
if(pl.team != tm.team)
continue;
- HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
+ HUD_PrintScoreboardItem(pos, tmp, pl, (pl.sv_entnum == player_localnum), i);
pos_y += 1.25 * hud_fontsize_y;
++i;
}
{
if(pl.team == NUM_SPECTATOR)
continue;
- HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
+ HUD_PrintScoreboardItem(pos, tmp, pl, (pl.sv_entnum == player_localnum), i);
pos_y += 1.25 * hud_fontsize_y;
++i;
}
float HUD_WouldDrawScoreboard() {
if (autocvar__hud_configure)
return 0;
+ else if (HUD_Radar_Clickable())
+ return 0;
else if (scoreboard_showscores)
return 1;
else if (intermission == 1)
vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
{
float i;
- float weapon_cnt = WEP_COUNT - 3; // either minstanex/nex are hidden, no port-o-launch, no tuba
+ float weapon_cnt = WEP_COUNT - 3; // either vaporizer/vortex are hidden, no port-o-launch, no tuba
float rows;
if(autocvar_scoreboard_accuracy_doublerows)
rows = 2;
float fontsize = height * 1/3;
float weapon_height = height * 2/3;
float weapon_width = sbwidth / weapon_cnt;
- float g_minstagib = 0;
+ float g_instagib = 0;
drawstring(pos, sprintf(_("Accuracy stats (average %d%%)"), average_accuracy), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
// column highlighting
for(i = 0; i < weapon_cnt/rows; ++i)
{
- if(!mod(i, 2))
+ if(!(i % 2))
drawfill(pos + '1 0 0' * weapon_width * rows * i, '0 1 0' * height * rows + '1 0 0' * weapon_width * rows, '0 0 0', scoreboard_alpha_bg * 0.2, DRAWFLAG_NORMAL);
}
if(rows == 2)
pos_x += weapon_width / 2;
- if(switchweapon == WEP_MINSTANEX)
- g_minstagib = 1; // TODO: real detection for minstagib?
+ if(switchweapon == WEP_VAPORIZER)
+ g_instagib = 1; // TODO: real detection for instagib?
float weapon_stats;
if(autocvar_scoreboard_accuracy_nocolors)
self = get_weaponinfo(i);
if (!self.weapon)
continue;
- if ((i == WEP_NEX && g_minstagib) || i == WEP_PORTO || (i == WEP_MINSTANEX && !g_minstagib) || i == WEP_TUBA) // skip port-o-launch, nex || minstanex and tuba
+ if ((i == WEP_VORTEX && g_instagib) || i == WEP_PORTO || (i == WEP_VAPORIZER && !g_instagib) || i == WEP_TUBA) // skip port-o-launch, vortex || vaporizer and tuba
continue;
weapon_stats = weapon_accuracy[i-WEP_FIRST];
weapon_alpha = 0.2 * scoreboard_alpha_fg;
// weapon icon
- drawpic_aspect_skin(pos, strcat("weapon", self.netname), '1 0 0' * weapon_width + '0 1 0' * weapon_height, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL);
+ drawpic_aspect_skin(pos, self.model2, '1 0 0' * weapon_width + '0 1 0' * weapon_height, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL);
// the accuracy
if(weapon_stats >= 0) {
weapons_with_stats += 1;
average_accuracy += weapon_stats; // store sum of all accuracies in average_accuracy
string s;
- s = sprintf(_("%d%%"), weapon_stats*100);
+ s = sprintf("%d%%", weapon_stats*100);
float padding;
padding = (weapon_width - stringwidth(s, FALSE, '1 0 0' * fontsize)) / 2; // center the accuracy value
float stat_monsters_killed, stat_monsters_total;
float rows = 0;
string val;
-
+
// get monster stats
stat_monsters_killed = getstatf(STAT_MONSTERS_KILLED);
stat_monsters_total = getstatf(STAT_MONSTERS_TOTAL);
p = count_ordinal(i+1);
if(grecordholder[i] == GetPlayerName(player_localnum))
drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha_self, DRAWFLAG_NORMAL);
- else if(!mod(i, 2) && scoreboard_highlight)
+ else if(!(i % 2) && scoreboard_highlight)
drawfill(pos, '1 0 0' * sbwidth + '0 1.25 0' * hud_fontsize_y, hl_rgb, scoreboard_highlight_alpha, DRAWFLAG_NORMAL);
drawstring(pos, p, '1 1 0' * hud_fontsize_y, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
drawstring(pos + '3 0 0' * hud_fontsize_y, TIME_ENCODED_TOSTRING(t), '1 1 0' * hud_fontsize_y, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
float specs;
specs = 0;
tmp = pos;
+ vector item_size;
+ item_size_x = sbwidth;
+ item_size_y = hud_fontsize_y * 1.25;
+ item_size_z = 0;
for(pl = players.sort_next; pl; pl = pl.sort_next)
{
if(pl.team != NUM_SPECTATOR)
continue;
pos_y += 1.25 * hud_fontsize_y;
- HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), specs);
+ HUD_PrintScoreboardItem(pos, item_size, pl, (pl.sv_entnum == player_localnum), specs);
++specs;
}
.float maxdistance;
.float hideflags;
.float spawntime;
-.float health;
.float build_started;
.float build_starthealth;
.float build_finished;
{
switch(s)
{
- case "ons-cp-atck-neut": return 2;
- case "ons-cp-atck-red": return 2;
- case "ons-cp-atck-blue": return 2;
- case "ons-cp-dfnd-red": return 0.5;
- case "ons-cp-dfnd-blue": return 0.5;
+ case "ons-cp-atck": return 2;
+ case "ons-cp-dfnd": return 0.5;
case "item-invis": return 2;
case "item-extralife": return 2;
case "item-speed": return 2;
}
vector spritelookupcolor(string s, vector def)
{
+ if(substring(s, 0, 4) == "wpn-")
+ return (get_weaponinfo(stof(substring(s, 4, strlen(s)))).wpcolor);
+
switch(s)
{
case "keycarrier-friend": return '0 1 0';
- case "wpn-laser": return '1 0.5 0.5';
- case "wpn-shotgun": return '0.5 0.25 0';
- case "wpn-uzi": return '1 1 0';
- case "wpn-gl": return '1 0 0';
- case "wpn-electro": return '0 0.5 1';
- case "wpn-crylink": return '1 0.5 1';
- case "wpn-nex": return '0.5 1 1';
- case "wpn-hagar": return '1 1 0.5';
- case "wpn-rl": return '1 1 0';
- case "wpn-porto": return '0.5 0.5 0.5';
- case "wpn-minstanex": return '0.5 1 1';
- case "wpn-hookgun": return '0 0.5 0';
- case "wpn-fireball": return '1 0.5 0';
- case "wpn-hlac": return '0 1 0';
- case "wpn-campingrifle": return '0.5 1 0';
- case "wpn-minelayer": return '0.75 1 0';
default: return def;
}
}
string spritelookuptext(string s)
{
+ if(substring(s, 0, 4) == "wpn-") { return (get_weaponinfo(stof(substring(s, 4, strlen(s)))).message); }
+ if(substring(s, 0, 5) == "buff-") { return Buff_PrettyName(Buff_Type_FromSprite(s)); }
+
switch(s)
{
case "as-push": return _("Push");
case "keycarrier-yellow": return _("Key carrier");
case "redbase": return _("Red base");
case "waypoint": return _("Waypoint");
- case "ons-gen-red": return _("Generator");
- case "ons-gen-blue": return _("Generator");
+ case "ons-gen": return _("Generator");
case "ons-gen-shielded": return _("Generator");
- case "ons-cp-neut": return _("Control point");
- case "ons-cp-red": return _("Control point");
- case "ons-cp-blue": return _("Control point");
- case "ons-cp-atck-neut": return _("Control point");
- case "ons-cp-atck-red": return _("Control point");
- case "ons-cp-atck-blue": return _("Control point");
- case "ons-cp-dfnd-red": return _("Control point");
- case "ons-cp-dfnd-blue": return _("Control point");
+ case "ons-cp": return _("Control point");
+ case "ons-cp-atck": return _("Control point");
+ case "ons-cp-dfnd": return _("Control point");
case "race-checkpoint": return _("Checkpoint");
case "race-finish": return _("Finish");
case "race-start": return _("Start");
case "nb-ball": return _("Ball");
case "ka-ball": return _("Ball");
case "ka-ballcarrier": return _("Ball carrier");
- case "wpn-laser": return _("Laser");
- case "wpn-shotgun": return _("Shotgun");
- case "wpn-uzi": return _("Machine Gun");
- case "wpn-gl": return _("Mortar");
- case "wpn-electro": return _("Electro");
- case "wpn-crylink": return _("Crylink");
- case "wpn-nex": return _("Nex");
- case "wpn-hagar": return _("Hagar");
- case "wpn-rl": return _("Rocket Launcher");
- case "wpn-porto": return _("Port-O-Launch");
- case "wpn-minstanex": return _("Minstanex");
- case "wpn-hookgun": return _("Hook");
- case "wpn-fireball": return _("Fireball");
- case "wpn-hlac": return _("HLAC");
- case "wpn-campingrifle": return _("Rifle");
- case "wpn-minelayer": return _("Mine Layer");
case "dom-neut": return _("Control point");
case "dom-red": return _("Control point");
case "dom-blue": return _("Control point");
case "item-shield": return _("Shield");
case "item-fuelregen": return _("Fuel regen");
case "item-jetpack": return _("Jet Pack");
- case "freezetag_frozen": return _("Frozen!");
+ case "frozen": return _("Frozen!");
case "tagged-target": return _("Tagged");
case "vehicle": return _("Vehicle");
default: return s;
if(f & 0x80)
{
self.(teamradar_times[self.teamradar_time_index]) = time;
- self.teamradar_time_index = mod(self.teamradar_time_index + 1, MAX_TEAMRADAR_TIMES);
+ self.teamradar_time_index = (self.teamradar_time_index + 1) % MAX_TEAMRADAR_TIMES;
}
self.teamradar_color_x = ReadByte() / 255.0;
self.teamradar_color_y = ReadByte() / 255.0;
const float TE_CSQC_PICTURE = 100;
const float TE_CSQC_RACE = 101;
- const float TE_CSQC_NEXGUNBEAMPARTICLE = 103;
- const float TE_CSQC_LIGHTNINGARC = 104;
+ const float TE_CSQC_VORTEXBEAMPARTICLE = 103;
+ const float TE_CSQC_ARC = 104;
const float TE_CSQC_TEAMNAGGER = 105;
const float TE_CSQC_PINGPLREPORT = 106;
const float TE_CSQC_TARGET_MUSIC = 107;
const float TE_CSQC_WEAPONCOMPLAIN = 108;
- const float TE_CSQC_NEX_SCOPE = 109;
+ const float TE_CSQC_VORTEX_SCOPE = 109;
const float TE_CSQC_MINELAYER_MAXMINES = 110;
const float TE_CSQC_HAGAR_MAXROCKETS = 111;
const float TE_CSQC_VEHICLESETUP = 112;
const float TE_CSQC_SVNOTICE = 113;
+ const float TE_CSQC_SHOCKWAVEPARTICLE = 114;
const float RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder
const float RACE_NET_CHECKPOINT_CLEAR = 1;
const float ENT_CLIENT_WARPZONE_CAMERA = 25;
const float ENT_CLIENT_TRIGGER_MUSIC = 26;
const float ENT_CLIENT_HOOK = 27;
- const float ENT_CLIENT_LGBEAM = 28;
- const float ENT_CLIENT_GAUNTLET = 29;
+ const float ENT_CLIENT_ARC_BEAM = 29; // WEAPONTODO: fix numbers
const float ENT_CLIENT_ACCURACY = 30;
const float ENT_CLIENT_SHOWNAMES = 31;
const float ENT_CLIENT_WARPZONE_TELEPORTED = 32;
const float ENT_CLIENT_SPAWNPOINT = 36;
const float ENT_CLIENT_SPAWNEVENT = 37;
const float ENT_CLIENT_NOTIFICATION = 38;
-
+ const float ENT_CLIENT_ELIMINATEDPLAYERS = 39;
const float ENT_CLIENT_TURRET = 40;
const float ENT_CLIENT_AUXILIARYXHAIR = 50;
const float ENT_CLIENT_VEHICLE = 60;
+const float ENT_CLIENT_GENERATOR = 70;
+const float ENT_CLIENT_CONTROLPOINT_ICON = 71;
+ const float ENT_CLIENT_HEALING_ORB = 80;
+
const float SPRITERULE_DEFAULT = 0;
const float SPRITERULE_TEAMPLAY = 1;
///////////////////////////
// csqc communication stuff
- const float STAT_KH_KEYS = 32;
- const float STAT_CTF_STATE = 33;
- const float STAT_WEAPONS = 35;
- const float STAT_SWITCHWEAPON = 36;
- const float STAT_GAMESTARTTIME = 37;
- const float STAT_STRENGTH_FINISHED = 38;
- const float STAT_INVINCIBLE_FINISHED = 39;
- const float STAT_PRESSED_KEYS = 42;
- const float STAT_ALLOW_OLDNEXBEAM = 43; // this stat could later contain some other bits of info, like, more server-side particle config
- const float STAT_FUEL = 44;
- const float STAT_NB_METERSTART = 45;
- const float STAT_SHOTORG = 46; // compressShotOrigin
- const float STAT_LEADLIMIT = 47;
- const float STAT_WEAPON_CLIPLOAD = 48;
- const float STAT_WEAPON_CLIPSIZE = 49;
- const float STAT_NEX_CHARGE = 50;
- const float STAT_LAST_PICKUP = 51;
- const float STAT_HUD = 52;
- const float STAT_NEX_CHARGEPOOL = 53;
- const float STAT_HIT_TIME = 54;
- const float STAT_TYPEHIT_TIME = 55;
- const float STAT_LAYED_MINES = 56;
- const float STAT_HAGAR_LOAD = 57;
- const float STAT_SWITCHINGWEAPON = 58;
- const float STAT_SUPERWEAPONS_FINISHED = 59;
-
- const float STAT_VEHICLESTAT_HEALTH = 60;
- const float STAT_VEHICLESTAT_SHIELD = 61;
- const float STAT_VEHICLESTAT_ENERGY = 62;
- const float STAT_VEHICLESTAT_AMMO1 = 63;
- const float STAT_VEHICLESTAT_RELOAD1 = 64;
- const float STAT_VEHICLESTAT_AMMO2 = 65;
- const float STAT_VEHICLESTAT_RELOAD2 = 66;
-
- const float STAT_SECRETS_TOTAL = 70;
- const float STAT_SECRETS_FOUND = 71;
-
- const float STAT_RESPAWN_TIME = 72;
- const float STAT_ROUNDSTARTTIME = 73;
-
- const float STAT_WEAPONS2 = 74;
- const float STAT_WEAPONS3 = 75;
-
- const float STAT_MONSTERS_TOTAL = 76;
- const float STAT_MONSTERS_KILLED = 77;
-
- const float STAT_ROUNDLOST = 96;
-
- // mod stats (1xx)
- const float STAT_REDALIVE = 100;
- const float STAT_BLUEALIVE = 101;
- const float STAT_YELLOWALIVE = 102;
- const float STAT_PINKALIVE = 103;
-
- // freeze tag
- const float STAT_FROZEN = 104;
- const float STAT_REVIVE_PROGRESS = 105;
-
- // domination
- const float STAT_DOM_TOTAL_PPS = 100;
- const float STAT_DOM_PPS_RED = 101;
- const float STAT_DOM_PPS_BLUE = 102;
- const float STAT_DOM_PPS_PINK = 103;
- const float STAT_DOM_PPS_YELLOW = 104;
-
- //const float STAT_SPIDERBOT_AIM 53 // compressShotOrigin
- //const float STAT_SPIDERBOT_TARGET 54 // compressShotOrigin
-
- // see DP source, quakedef.h
- const float STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW = 222;
- const float STAT_MOVEVARS_AIRSTRAFEACCEL_QW = 223;
- const float STAT_MOVEVARS_MAXSPEED = 244;
- const float STAT_MOVEVARS_AIRACCEL_QW = 254;
-
const float CTF_STATE_ATTACK = 1;
const float CTF_STATE_DEFEND = 2;
const float CTF_STATE_COMMANDER = 3;
// moved that here so the client knows the max.
// # of maps, I'll use arrays for them :P
- #define MAPVOTE_COUNT 10
+ #define MAPVOTE_COUNT 30
/**
* Lower scores are better (e.g. suicides)
#define SP_SCORE 3
// game mode specific indices are not in common/, but in server/scores_rules.qc!
- #ifdef COMPAT_XON010_CHANNELS
- const float CH_INFO = 0; // only on world and csqc
- const float CH_TRIGGER = 0; // only on players; compat: FALSELY CONTROLLED BY "Info"
- const float CH_WEAPON_A = 1; // only on players and entities
- const float CH_WEAPON_SINGLE = 5; // only on players and entities
- const float CH_VOICE = 2; // only on players
- const float CH_BGM_SINGLE = 2; // only on csqc; compat: FALSELY CONTROLLED BY "Voice"
- const float CH_AMBIENT = 2; // only on csqc; compat: FALSELY CONTROLLED BY "Voice"
- const float CH_TRIGGER_SINGLE = 3; // only on players, entities, csqc
- const float CH_SHOTS = 4; // only on players, entities, csqc
- const float CH_SHOTS_SINGLE = 4; // only on players, entities, csqc
- const float CH_WEAPON_B = 5; // only on players and entities
- const float CH_PAIN = 6; // only on players and csqc
- const float CH_PAIN_SINGLE = 6; // only on players and csqc
- const float CH_PLAYER = 7; // only on players and entities
- const float CH_TUBA = 5; // only on csqc
- #else
const float CH_INFO = 0;
const float CH_TRIGGER = -3;
const float CH_WEAPON_A = -1;
const float CH_PAIN = -6;
const float CH_PAIN_SINGLE = 6;
const float CH_PLAYER = -7;
- const float CH_TUBA = 5;
- #endif
+ const float CH_PLAYER_SINGLE = 7;
+ const float CH_TUBA_SINGLE = 5;
const float ATTEN_NONE = 0;
const float ATTEN_MIN = 0.015625;
#define VOL_BASE 0.7
#define VOL_BASEVOICE 1.0
- // this sets sounds and other properties of the projectiles in csqc
+ // WEAPONTODO: move this into separate/new projectile handling code // this sets sounds and other properties of the projectiles in csqc
const float PROJECTILE_ELECTRO = 1;
const float PROJECTILE_ROCKET = 2;
const float PROJECTILE_TAG = 3;
const float PROJECTILE_GRENADE = 7;
const float PROJECTILE_GRENADE_BOUNCING = 8;
const float PROJECTILE_MINE = 9;
- const float PROJECTILE_LASER = 10;
+ const float PROJECTILE_BLASTER = 10;
const float PROJECTILE_HLAC = 11;
const float PROJECTILE_SEEKER = 12;
const float PROJECTILE_FLAC = 13;
const float PROJECTILE_MAGE_SPIKE = 32;
const float PROJECTILE_SHAMBLER_LIGHTNING = 33;
- const float PROJECTILE_NADE_RED = 50;
- const float PROJECTILE_NADE_RED_BURN = 51;
- const float PROJECTILE_NADE_BLUE = 52;
- const float PROJECTILE_NADE_BLUE_BURN = 53;
- const float PROJECTILE_NADE_YELLOW = 54;
- const float PROJECTILE_NADE_YELLOW_BURN = 55;
- const float PROJECTILE_NADE_PINK = 56;
- const float PROJECTILE_NADE_PINK_BURN = 57;
- const float PROJECTILE_NADE = 58;
- const float PROJECTILE_NADE_BURN = 59;
+ const float PROJECTILE_RPC = 60;
const float SPECIES_HUMAN = 0;
const float SPECIES_ROBOT_SOLID = 1;
const float WATERLEVEL_WETFEET = 1;
const float WATERLEVEL_SWIMMING = 2;
const float WATERLEVEL_SUBMERGED = 3;
-
- const float MAX_SHOT_DISTANCE = 32768;
-
- // weapon requests
- const float WR_SETUP = 1; // (SVQC) setup weapon data
- const float WR_THINK = 2; // (SVQC) logic to run every frame
- const float WR_CHECKAMMO1 = 3; // (SVQC) checks ammo for weapon
- const float WR_CHECKAMMO2 = 4; // (SVQC) checks ammo for weapon
- const float WR_AIM = 5; // (SVQC) runs bot aiming code for this weapon
- const float WR_PRECACHE = 6; // (CSQC and SVQC) precaches models/sounds used by this weapon
- const float WR_SUICIDEMESSAGE = 7; // (SVQC) notification number for suicide message (may inspect w_deathtype for details)
- const float WR_KILLMESSAGE = 8; // (SVQC) notification number for kill message (may inspect w_deathtype for details)
- const float WR_RELOAD = 9; // (SVQC) does not need to do anything
- const float WR_RESETPLAYER = 10; // (SVQC) does not need to do anything
- const float WR_IMPACTEFFECT = 11; // (CSQC) impact effect
- const float WR_SWITCHABLE = 12; // (CSQC) impact effect
- const float WR_PLAYERDEATH = 13; // (SVQC) does not need to do anything
- const float WR_GONETHINK = 14; // (SVQC) logic to run every frame, also if no longer having the weapon as long as the switch away has not been performed
-
#define SERVERFLAG_ALLOW_FULLBRIGHT 1
#define SERVERFLAG_TEAMPLAY 2
#define SERVERFLAG_PLAYERSTATS 4
#define URI_GET_UPDATENOTIFICATION 33
#define URI_GET_URLLIB 128
#define URI_GET_URLLIB_END 191
+
+ // gametype votes
+ #define GTV_AVAILABLE 0
+ // for later use in per-map gametype filtering
+ #define GTV_FORBIDDEN 2
.string netname; // game type name as in cvar (with g_ prefix)
.string mdl; // game type short name
.string message; // human readable name
+ .float team; // does this gametype support teamplay?
.string model2; // game type defaults
+ .string gametype_description; // game type description
- #define REGISTER_GAMETYPE(hname,sname,g_name,NAME,defaults) \
+ #define REGISTER_GAMETYPE(hname,sname,g_name,NAME,gteamplay,defaults,gdescription) \
var float MAPINFO_TYPE_##NAME; \
var entity MapInfo_Type##g_name; \
void RegisterGametypes_##g_name() \
MapInfo_Type##g_name.netname = #g_name; \
MapInfo_Type##g_name.mdl = #sname; \
MapInfo_Type##g_name.message = hname; \
+ MapInfo_Type##g_name.team = gteamplay; \
MapInfo_Type##g_name.model2 = defaults; \
+ MapInfo_Type##g_name.gametype_description = gdescription; \
if(!MapInfo_Type_first) \
MapInfo_Type_first = MapInfo_Type##g_name; \
if(MapInfo_Type_last) \
#define IS_GAMETYPE(NAME) \
(MapInfo_LoadedGametype == MAPINFO_TYPE_##NAME)
- REGISTER_GAMETYPE(_("Deathmatch"),dm,g_dm,DEATHMATCH,"timelimit=20 pointlimit=30 leadlimit=0");
+ REGISTER_GAMETYPE(_("Deathmatch"),dm,g_dm,DEATHMATCH,FALSE,"timelimit=20 pointlimit=30 leadlimit=0",_("Kill all enemies"));
#define g_dm IS_GAMETYPE(DEATHMATCH)
- REGISTER_GAMETYPE(_("Last Man Standing"),lms,g_lms,LMS,"timelimit=20 lives=9 leadlimit=0");
+ REGISTER_GAMETYPE(_("Last Man Standing"),lms,g_lms,LMS,FALSE,"timelimit=20 lives=9 leadlimit=0",_("Survive and kill until the enemies have no lives left"));
#define g_lms IS_GAMETYPE(LMS)
- REGISTER_GAMETYPE(_("Race"),rc,g_race,RACE,"timelimit=20 qualifying_timelimit=5 laplimit=7 teamlaplimit=15 leadlimit=0");
+ REGISTER_GAMETYPE(_("Race"),rc,g_race,RACE,FALSE,"timelimit=20 qualifying_timelimit=5 laplimit=7 teamlaplimit=15 leadlimit=0",_("Race against other players to the finish line"));
#define g_race IS_GAMETYPE(RACE)
- REGISTER_GAMETYPE(_("Race CTS"),cts,g_cts,CTS,"timelimit=20 skill=-1");
+ REGISTER_GAMETYPE(_("Race CTS"),cts,g_cts,CTS,FALSE,"timelimit=20 skill=-1",_("Race for fastest time"));
#define g_cts IS_GAMETYPE(CTS)
- REGISTER_GAMETYPE(_("Team Deathmatch"),tdm,g_tdm,TEAM_DEATHMATCH,"timelimit=20 pointlimit=50 teams=2 leadlimit=0");
+ REGISTER_GAMETYPE(_("Team Deathmatch"),tdm,g_tdm,TEAM_DEATHMATCH,TRUE,"timelimit=20 pointlimit=50 teams=2 leadlimit=0",_("Kill all enemy teammates"));
#define g_tdm IS_GAMETYPE(TEAM_DEATHMATCH)
- REGISTER_GAMETYPE(_("Capture the Flag"),ctf,g_ctf,CTF,"timelimit=20 caplimit=10 leadlimit=0");
+ REGISTER_GAMETYPE(_("Capture the Flag"),ctf,g_ctf,CTF,TRUE,"timelimit=20 caplimit=10 leadlimit=6",_("Find and bring the enemy flag to your base to capture it"));
#define g_ctf IS_GAMETYPE(CTF)
- REGISTER_GAMETYPE(_("Clan Arena"),ca,g_ca,CA,"timelimit=20 pointlimit=10 leadlimit=0");
+ REGISTER_GAMETYPE(_("Clan Arena"),ca,g_ca,CA,TRUE,"timelimit=20 pointlimit=10 teams=2 leadlimit=0",_("Kill all enemy teammates to win the round"));
#define g_ca IS_GAMETYPE(CA)
- REGISTER_GAMETYPE(_("Domination"),dom,g_domination,DOMINATION,"timelimit=20 pointlimit=200 teams=2 leadlimit=0");
+ REGISTER_GAMETYPE(_("Domination"),dom,g_domination,DOMINATION,TRUE,"timelimit=20 pointlimit=200 teams=2 leadlimit=0",_("Capture all the control points to win"));
#define g_domination IS_GAMETYPE(DOMINATION)
- REGISTER_GAMETYPE(_("Key Hunt"),kh,g_keyhunt,KEYHUNT,"timelimit=20 pointlimit=1000 teams=3 leadlimit=0");
+ REGISTER_GAMETYPE(_("Key Hunt"),kh,g_keyhunt,KEYHUNT,TRUE,"timelimit=20 pointlimit=1000 teams=3 leadlimit=0",_("Gather all the keys to win the round"));
#define g_keyhunt IS_GAMETYPE(KEYHUNT)
- REGISTER_GAMETYPE(_("Assault"),as,g_assault,ASSAULT,"timelimit=20");
+ REGISTER_GAMETYPE(_("Assault"),as,g_assault,ASSAULT,TRUE,"timelimit=20",_("Destroy obstacles to find and destroy the enemy power core before time runs out"));
#define g_assault IS_GAMETYPE(ASSAULT)
- REGISTER_GAMETYPE(_("Onslaught"),ons,g_onslaught,ONSLAUGHT,"pointlimit=1 timelimit=30");
-REGISTER_GAMETYPE(_("Onslaught"),ons,g_onslaught,ONSLAUGHT,TRUE,"timelimit=20",_("Capture control points to reach and destroy the enemy generator"));
++REGISTER_GAMETYPE(_("Onslaught"),ons,g_onslaught,ONSLAUGHT,TRUE,"pointlimit = 1 timelimit=30",_("Capture control points to reach and destroy the enemy generator"));
#define g_onslaught IS_GAMETYPE(ONSLAUGHT)
- REGISTER_GAMETYPE(_("Nexball"),nb,g_nexball,NEXBALL,"timelimit=20 pointlimit=5 leadlimit=0");
+ REGISTER_GAMETYPE(_("Nexball"),nb,g_nexball,NEXBALL,TRUE,"timelimit=20 pointlimit=5 leadlimit=0",_("XonSports"));
#define g_nexball IS_GAMETYPE(NEXBALL)
- REGISTER_GAMETYPE(_("Freeze Tag"),ft,g_freezetag,FREEZETAG,"timelimit=20 pointlimit=10 teams=2 leadlimit=0");
+ REGISTER_GAMETYPE(_("Freeze Tag"),ft,g_freezetag,FREEZETAG,TRUE,"timelimit=20 pointlimit=10 teams=2 leadlimit=0",_("Kill enemies to freeze them, stand next to teammates to revive them"));
#define g_freezetag IS_GAMETYPE(FREEZETAG)
- REGISTER_GAMETYPE(_("Keepaway"),ka,g_keepaway,KEEPAWAY,"timelimit=20 pointlimit=30");
+ REGISTER_GAMETYPE(_("Keepaway"),ka,g_keepaway,KEEPAWAY,TRUE,"timelimit=20 pointlimit=30",_("Hold the ball to get points for kills"));
#define g_keepaway IS_GAMETYPE(KEEPAWAY)
- REGISTER_GAMETYPE(_("Invasion"),inv,g_invasion,INVASION,"pointlimit=50 teams=0");
+ REGISTER_GAMETYPE(_("Invasion"),inv,g_invasion,INVASION,FALSE,"pointlimit=50 teams=0",_("Survive against waves of monsters"));
#define g_invasion IS_GAMETYPE(INVASION)
- const float MAPINFO_FEATURE_WEAPONS = 1; // not defined for minstagib-only maps
+ const float MAPINFO_FEATURE_WEAPONS = 1; // not defined for instagib-only maps
const float MAPINFO_FEATURE_VEHICLES = 2;
const float MAPINFO_FEATURE_TURRETS = 4;
const float MAPINFO_FEATURE_MONSTERS = 8;
void MapInfo_LoadMap(string s, float reinit);
// list all maps for the current game type
- string MapInfo_ListAllowedMaps(float pFlagsRequired, float pFlagsForbidden);
+ string MapInfo_ListAllowedMaps(float type, float pFlagsRequired, float pFlagsForbidden);
// list all allowed maps (for any game type)
string MapInfo_ListAllAllowedMaps(float pFlagsRequired, float pFlagsForbidden);
// gets a gametype from a string
string _MapInfo_GetDefaultEx(float t);
+ float _MapInfo_GetTeamPlayBool(float t);
float MapInfo_Type_FromString(string t);
+ string MapInfo_Type_Description(float t);
string MapInfo_Type_ToString(float t);
string MapInfo_Type_ToText(float t);
void MapInfo_SwitchGameType(float t);
MSG_ANNCE_NOTIF(1, ANNCE_KILLSTREAK_20, CH_INFO, "20kills", VOL_BASEVOICE, ATTEN_NONE) \
MSG_ANNCE_NOTIF(1, ANNCE_KILLSTREAK_25, CH_INFO, "25kills", VOL_BASEVOICE, ATTEN_NONE) \
MSG_ANNCE_NOTIF(1, ANNCE_KILLSTREAK_30, CH_INFO, "30kills", VOL_BASEVOICE, ATTEN_NONE) \
- MSG_ANNCE_NOTIF(1, ANNCE_MINSTAGIB_LASTSECOND, CH_INFO, "lastsecond", VOL_BASEVOICE, ATTEN_NONE) \
- MSG_ANNCE_NOTIF(1, ANNCE_MINSTAGIB_NARROWLY, CH_INFO, "narrowly", VOL_BASEVOICE, ATTEN_NONE) \
- MSG_ANNCE_NOTIF(1, ANNCE_MINSTAGIB_TERMINATED, CH_INFO, "terminated", VOL_BASEVOICE, ATTEN_NONE) \
+ MSG_ANNCE_NOTIF(1, ANNCE_INSTAGIB_LASTSECOND, CH_INFO, "lastsecond", VOL_BASEVOICE, ATTEN_NONE) \
+ MSG_ANNCE_NOTIF(1, ANNCE_INSTAGIB_NARROWLY, CH_INFO, "narrowly", VOL_BASEVOICE, ATTEN_NONE) \
+ MSG_ANNCE_NOTIF(1, ANNCE_INSTAGIB_TERMINATED, CH_INFO, "terminated", VOL_BASEVOICE, ATTEN_NONE) \
MSG_ANNCE_NOTIF(0, ANNCE_MULTIFRAG, CH_INFO, "multifrag", VOL_BASEVOICE, ATTEN_NONE) \
MSG_ANNCE_NOTIF(2, ANNCE_NUM_1, CH_INFO, "1", VOL_BASEVOICE, ATTEN_NONE) \
MSG_ANNCE_NOTIF(2, ANNCE_NUM_2, CH_INFO, "2", VOL_BASEVOICE, ATTEN_NONE) \
#define MSG_INFO_NOTIFICATIONS \
MSG_INFO_NOTIF(2, INFO_CHAT_NOSPECTATORS, 0, 0, "", "", "", _("^F4NOTE: ^BGSpectator chat is not sent to players during the match"), "") \
+ MSG_INFO_NOTIF(2, INFO_COINTOSS, 1, 0, "s1", "", "", _("^F2Throwing coin... Result: %s^F2!"), "") \
+ MSG_INFO_NOTIF(1, INFO_JETPACK_NOFUEL, 0, 0, "", "", "", _("^BGYou don't have any fuel for the ^F1Jetpack"), "") \
+ MSG_INFO_NOTIF(2, INFO_SUPERSPEC_MISSING_UID, 0, 0, "", "", "", _("^F2You lack a UID, superspec options will not be saved/restored"), "") \
+ MSG_INFO_NOTIF(1, INFO_CA_JOIN_LATE, 0, 0, "", "", "", _("^F1Round already started, you will join the game in the next round"), "") \
+ MSG_INFO_NOTIF(1, INFO_CA_LEAVE, 0, 0, "", "", "", _("^F2You will spectate in the next round"), "") \
MULTITEAM_INFO(1, INFO_CTF_CAPTURE_, 2, 1, 0, "s1", "s1", "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag"), "") \
MULTITEAM_INFO(1, INFO_CTF_CAPTURE_BROKEN_, 2, 2, 2, "s1 f1p2dec s2 f2p2dec", "s1", "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag in ^F1%s^BG seconds, breaking ^BG%s^BG's previous record of ^F2%s^BG seconds"), "") \
MULTITEAM_INFO(1, INFO_CTF_CAPTURE_TIME_, 2, 1, 1, "s1 f1p2dec", "s1", "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag in ^F1%s^BG seconds"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_FIRE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was burnt up into a crisp by ^BG%s^K1%s%s"), _("^BG%s%s^K1 felt a little hot from ^BG%s^K1's fire^K1%s%s")) \
MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_LAVA, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_lava", _("^BG%s%s^K1 was cooked by ^BG%s^K1%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_MONSTER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was pushed infront of a monster by ^BG%s^K1%s%s"), "") \
- MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_NADE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was blown up by ^BG%s^K1's Nade%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_NADE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_nade", _("^BG%s%s^K1 was blown up by ^BG%s^K1's Nade%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_NADE_NAPALM, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_nade_napalm", _("^BG%s%s^K1 was burned to death by ^BG%s^K1's Napalm Nade%s%s"), _("^BG%s%s^K1 got too close to a napalm explosion%s%s")) \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_NADE_ICE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_nade_ice", _("^BG%s%s^K1 was blown up by ^BG%s^K1's Ice Nade%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_NADE_ICE_FREEZE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_nade_ice", _("^BG%s%s^K1 was frozen to death by ^BG%s^K1's Ice Nade%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_NADE_HEAL, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_nade_heal", _("^BG%s%s^K1 has not been healed by ^BG%s^K1's Healing Nade%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_SHOOTING_STAR, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_shootingstar", _("^BG%s%s^K1 was shot into space by ^BG%s^K1%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_SLIME, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_slime", _("^BG%s%s^K1 was slimed by ^BG%s^K1%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_SWAMP, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_slime", _("^BG%s%s^K1 was preserved by ^BG%s^K1%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_WAKI_DEATH, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Racer exploded%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_WAKI_GUN, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was bolted down by ^BG%s^K1's Racer%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_WAKI_ROCKET, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 couldn't find shelter from ^BG%s^K1's Racer%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VENGEANCE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was destroyed by the vengeful ^BG%s^K1%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VOID, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_void", _("^BG%s%s^K1 was thrown into a world of hurt by ^BG%s^K1%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_AUTOTEAMCHANGE, 2, 1, "s1 s2loc death_team", "", "", _("^BG%s^K1 was moved into the %s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_BETRAYAL, 2, 1, "s1 s2loc spree_lost", "s1", "notify_teamkill_red", _("^BG%s^K1 became enemies with the Lord of Teamplay%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_CAMP, 2, 1, "s1 s2loc spree_lost", "s1", "notify_camping", _("^BG%s^K1 thought they found a nice camping ground%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_CHEAT, 2, 1, "s1 s2loc spree_lost", "s1", "notify_selfkill", _("^BG%s^K1 unfairly eliminated themself%s%s"), "") \
- MSG_INFO_NOTIF(1, INFO_DEATH_SELF_CUSTOM, 3, 1, "s1 s2 s3loc spree_lost", "s1", "notify_void", _("^BG%s^K1 %s^K1%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_CUSTOM, 3, 1, "s1 s2 s3loc spree_lost", "s1", "notify_void", "^BG%s^K1 %s^K1%s%s", "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_DROWN, 2, 1, "s1 s2loc spree_lost", "s1", "notify_water", _("^BG%s^K1 couldn't catch their breath%s%s"), _("^BG%s^K1 was in the water for too long%s%s")) \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_FALL, 2, 1, "s1 s2loc spree_lost", "s1", "notify_fall", _("^BG%s^K1 hit the ground with a crunch%s%s"), _("^BG%s^K1 hit the ground with a bit too much force%s%s")) \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_FIRE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 became a bit too crispy%s%s"), _("^BG%s^K1 felt a little hot%s%s")) \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_GENERIC, 2, 1, "s1 s2loc spree_lost", "s1", "notify_selfkill", _("^BG%s^K1 died%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_LAVA, 2, 1, "s1 s2loc spree_lost", "s1", "notify_lava", _("^BG%s^K1 turned into hot slag%s%s"), _("^BG%s^K1 found a hot place%s%s")) \
- MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NADE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 mastered the art of self-nading%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_MAGE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was exploded by a Mage%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SHAMBLER_CLAW, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1's innards became outwards by a Shambler%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_SHAMBLER_SMASH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was smashed by a Shambler%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_WYVERN, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was fireballed by a Wyvern%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_ZOMBIE_JUMP, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 joins the Zombies%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_MON_ZOMBIE_MELEE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was given kung fu lessons by a Zombie%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NADE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_nade", _("^BG%s^K1 mastered the art of self-nading%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NADE_NAPALM, 2, 1, "s1 s2loc spree_lost", "s1", "notify_nade_napalm", _("^BG%s^K1 was burned to death by their own Napalm Nade%s%s"), _("^BG%s^K1 decided to take a look at the results of their napalm explosion%s%s")) \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NADE_ICE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_nade_ice", _("^BG%s^K1 mastered the art of self-nading%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NADE_ICE_FREEZE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_nade_ice", _("^BG%s^K1 was frozen to death by their own Ice Nade%s%s"), _("^BG%s^K1 felt a little chilly%s%s")) \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NADE_HEAL, 2, 1, "s1 s2loc spree_lost", "s1", "notify_nade_heal", _("^BG%s^K1's Healing Nade didn't quite heal them%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_NOAMMO, 2, 1, "s1 s2loc spree_lost", "s1", "notify_outofammo", _("^BG%s^K1 died%s%s. What's the point of living without ammo?"), _("^BG%s^K1 ran out of ammo%s%s")) \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_ROT, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 rotted away%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_SHOOTING_STAR, 2, 1, "s1 s2loc spree_lost", "s1", "notify_shootingstar", _("^BG%s^K1 became a shooting star%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_WAKI_ROCKET, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 couldn't find shelter from a Racer rocket%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VOID, 2, 1, "s1 s2loc spree_lost", "s1", "notify_void", _("^BG%s^K1 was in the wrong place%s%s"), "") \
MULTITEAM_INFO(1, INFO_DEATH_TEAMKILL_, 4, 3, 1, "s1 s2 s3loc spree_end", "s2 s1", "notify_teamkill_%s", _("^BG%s^K1 was betrayed by ^BG%s^K1%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_DOMINATION_CAPTURE_TIME, 2, 2, "s1 s2 f1 f2", "", "", _("^BG%s^BG%s^BG (%s points every %s seconds)"), "") \
MSG_INFO_NOTIF(1, INFO_FREEZETAG_FREEZE, 2, 0, "s1 s2", "", "", _("^BG%s^K1 was frozen by ^BG%s"), "") \
MSG_INFO_NOTIF(1, INFO_FREEZETAG_REVIVED, 2, 0, "s1 s2", "", "", _("^BG%s^K3 was revived by ^BG%s"), "") \
MSG_INFO_NOTIF(1, INFO_FREEZETAG_REVIVED_FALL, 1, 0, "s1", "", "", _("^BG%s^K3 was revived by falling"), "") \
+ MSG_INFO_NOTIF(1, INFO_FREEZETAG_REVIVED_NADE, 1, 0, "s1", "", "", _("^BG%s^K3 was revived by their Nade explosion"), "") \
MSG_INFO_NOTIF(1, INFO_FREEZETAG_AUTO_REVIVED, 1, 1, "s1 f1", "", "", _("^BG%s^K3 was automatically revived after %s second(s)"), "") \
MULTITEAM_INFO(1, INFO_ROUND_TEAM_WIN_, 4, 0, 0, "", "", "", _("^TC^TT^BG team wins the round"), "") \
MSG_INFO_NOTIF(1, INFO_ROUND_PLAYER_WIN, 1, 0, "s1", "", "", _("^BG%s^BG wins the round"), "") \
MSG_INFO_NOTIF(1, INFO_ROUND_OVER, 0, 0, "", "", "", _("^BGRound over, there's no winner"), "") \
MSG_INFO_NOTIF(1, INFO_FREEZETAG_SELF, 1, 0, "s1", "", "", _("^BG%s^K1 froze themself"), "") \
MSG_INFO_NOTIF(1, INFO_GODMODE_OFF, 0, 1, "f1", "", "", _("^BGGodmode saved you %s units of damage, cheater!"), "") \
+ MSG_INFO_NOTIF(1, INFO_ITEM_BUFF, 1, 1, "s1 item_buffname", "", "", _("^BG%s^BG got the %s^BG buff!"), "") \
+ MSG_INFO_NOTIF(1, INFO_ITEM_BUFF_LOST, 1, 1, "s1 item_buffname", "", "", _("^BG%s^BG lost the %s^BG buff!"), "") \
+ MSG_INFO_NOTIF(1, INFO_ITEM_BUFF_DROP, 0, 1, "item_buffname", "", "", _("^BGYou dropped the %s^BG buff!"), "") \
+ MSG_INFO_NOTIF(1, INFO_ITEM_BUFF_GOT, 0, 1, "item_buffname", "", "", _("^BGYou got the %s^BG buff!"), "") \
MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_DONTHAVE, 0, 1, "item_wepname", "", "", _("^BGYou do not have the ^F1%s"), "") \
MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_DROP, 1, 1, "item_wepname item_wepammo", "", "", _("^BGYou dropped the ^F1%s^BG%s"), "") \
MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_GOT, 0, 1, "item_wepname", "", "", _("^BGYou got the ^F1%s"), "") \
MSG_INFO_NOTIF(1, INFO_LMS_FORFEIT, 1, 0, "s1", "", "", _("^BG%s^F3 forfeited"), "") \
MSG_INFO_NOTIF(1, INFO_LMS_NOLIVES, 1, 0, "s1", "", "", _("^BG%s^F3 has no more lives left"), "") \
MSG_INFO_NOTIF(1, INFO_MONSTERS_DISABLED, 0, 0, "", "", "", _("^BGMonsters are currently disabled"), "") \
+ MSG_INFO_NOTIF(1, INFO_ONSLAUGHT_CAPTURE, 2, 0, "s1 s2", "", "", _("^BG%s^BG captured %s^BG control point"), "") \
+ MULTITEAM_INFO(1, INFO_ONSLAUGHT_CPDESTROYED_, 4, 2, 0, "s1 s2", "", "", _("^TC^TT^BG team %s^BG control point has been destroyed by %s"), "") \
+ MULTITEAM_INFO(1, INFO_ONSLAUGHT_GENDESTROYED_, 4, 0, 0, "", "", "", _("^TC^TT^BG generator has been destroyed"), "") \
+ MULTITEAM_INFO(1, INFO_ONSLAUGHT_GENDESTROYED_OVERTIME_, 4, 0, 0, "", "", "", _("^TC^TT^BG generator spontaneously combusted due to overtime!"), "") \
MSG_INFO_NOTIF(1, INFO_POWERUP_INVISIBILITY, 1, 0, "s1", "s1", "strength", _("^BG%s^K1 picked up Invisibility"), "") \
MSG_INFO_NOTIF(1, INFO_POWERUP_SHIELD, 1, 0, "s1", "s1", "shield", _("^BG%s^K1 picked up Shield"), "") \
MSG_INFO_NOTIF(1, INFO_POWERUP_SPEED, 1, 0, "s1", "s1", "shield", _("^BG%s^K1 picked up Speed"), "") \
MSG_INFO_NOTIF(1, INFO_RACE_NEW_SET, 1, 2, "s1 race_col f1ord race_col f2race_time", "s1 f2race_time", "race_newrecordserver", _("^BG%s^BG set the %s%s^BG place record with %s%s"), "") \
MULTITEAM_INFO(1, INFO_SCORES_, 4, 0, 0, "", "", "", _("^TC^TT ^BGteam scores!"), "") \
MSG_INFO_NOTIF(1, INFO_SPECTATE_WARNING, 0, 1, "f1secs", "", "", _("^F2You have to become a player within the next %s, otherwise you will be kicked, because spectating isn't allowed at this time!"), "") \
- MSG_INFO_NOTIF(1, INFO_SUPERWEAPON_PICKUP, 1, 0, "s1", "s1", "strength", _("^BG%s^K1 picked up a Superweapon"), "") \
+ MSG_INFO_NOTIF(1, INFO_SUPERWEAPON_PICKUP, 1, 0, "s1", "s1", "superweapons", _("^BG%s^K1 picked up a Superweapon"), "") \
+ MSG_INFO_NOTIF(1, INFO_TEAMCHANGE_LARGERTEAM, 0, 0, "", "", "", _("^BGYou cannot change to a larger team"), "") \
+ MSG_INFO_NOTIF(1, INFO_TEAMCHANGE_NOTALLOWED, 0, 0, "", "", "", _("^BGYou are not allowed to change teams"), "") \
MSG_INFO_NOTIF(2, INFO_VERSION_BETA, 2, 0, "s1 s2", "", "", _("^F4NOTE: ^BGThe server is running ^F1Xonotic %s (beta)^BG, you have ^F2Xonotic %s"), "") \
MSG_INFO_NOTIF(2, INFO_VERSION_OLD, 2, 0, "s1 s2", "", "", _("^F4NOTE: ^BGThe server is running ^F1Xonotic %s^BG, you have ^F2Xonotic %s"), "") \
MSG_INFO_NOTIF(2, INFO_VERSION_OUTDATED, 2, 0, "s1 s2", "", "", _("^F4NOTE: ^F1Xonotic %s^BG is out, and you still have ^F2Xonotic %s^BG - get the update from ^F3http://www.xonotic.org/^BG!"), "") \
MSG_INFO_NOTIF(1, INFO_WATERMARK, 1, 0, "s1", "", "", _("^F3SVQC Build information: ^F4%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_ACCORDEON_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapontuba", _("^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Accordeon%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_ACCORDEON_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weapontuba", _("^BG%s^K1 hurt their own ears with the @!#%%'n Accordeon%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_ARC_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponarc", _("^BG%s%s^K1 was electrocuted by ^BG%s^K1's Arc%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_BLASTER_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponlaser", _("^BG%s%s^K1 was shot to death by ^BG%s^K1's Blaster%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_BLASTER_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponlaser", _("^BG%s^K1 shot themself to hell with their Blaster%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_CRYLINK_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponcrylink", _("^BG%s%s^K1 felt the strong pull of ^BG%s^K1's Crylink%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_CRYLINK_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponcrylink", _("^BG%s^K1 felt the strong pull of their Crylink%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_DEVASTATOR_MURDER_DIRECT, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrocketlauncher", _("^BG%s%s^K1 ate ^BG%s^K1's rocket%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_DEVASTATOR_MURDER_SPLASH, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrocketlauncher", _("^BG%s%s^K1 got too close ^BG%s^K1's rocket%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_DEVASTATOR_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponrocketlauncher", _("^BG%s^K1 blew themself up with their Devastator%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_MURDER_BOLT, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponelectro", _("^BG%s%s^K1 was blasted by ^BG%s^K1's Electro bolt%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_MURDER_COMBO, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponelectro", _("^BG%s%s^K1 felt the electrifying air of ^BG%s^K1's Electro combo%s%s"), "") \
- MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_MURDER_ORBS, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponelectro", _("^BG%s%s^K1 got too close to ^BG%s^K1's Electro plasma%s%s"), "") \
- MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_SUICIDE_BOLT, 2, 1, "s1 s2loc spree_lost", "s1", "weaponelectro", _("^BG%s^K1 played with Electro plasma%s%s"), "") \
- MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_SUICIDE_ORBS, 2, 1, "s1 s2loc spree_lost", "s1", "weaponelectro", _("^BG%s^K1 could not remember where they put their Electro plasma%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_MURDER_ORBS, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponelectro", _("^BG%s%s^K1 got too close to ^BG%s^K1's Electro orb%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_SUICIDE_BOLT, 2, 1, "s1 s2loc spree_lost", "s1", "weaponelectro", _("^BG%s^K1 played with Electro bolts%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_SUICIDE_ORBS, 2, 1, "s1 s2loc spree_lost", "s1", "weaponelectro", _("^BG%s^K1 could not remember where they put their Electro orb%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_FIREBALL_MURDER_BLAST, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponfireball", _("^BG%s%s^K1 got too close to ^BG%s^K1's fireball%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_FIREBALL_MURDER_FIREMINE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponfireball", _("^BG%s%s^K1 got burnt by ^BG%s^K1's firemine%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_FIREBALL_SUICIDE_BLAST, 2, 1, "s1 s2loc spree_lost", "s1", "weaponfireball", _("^BG%s^K1 should have used a smaller gun%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_HAGAR_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponhagar", _("^BG%s^K1 played with tiny Hagar rockets%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_HLAC_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponhlac", _("^BG%s%s^K1 was cut down with ^BG%s^K1's HLAC%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_HLAC_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponhlac", _("^BG%s^K1 got a little jumpy with their HLAC%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_HMG_MURDER_SNIPE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponhmg", _("^BG%s%s^K1 was sniped by ^BG%s^K1's Heavy Machine Gun%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_HMG_MURDER_SPRAY, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponhmg", _("^BG%s%s^K1 was torn to bits by ^BG%s^K1's Heavy Machine Gun%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_HOOK_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponhook", _("^BG%s%s^K1 was caught in ^BG%s^K1's Hook gravity bomb%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_KLEINBOTTLE_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapontuba", _("^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Klein Bottle%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_KLEINBOTTLE_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weapontuba", _("^BG%s^K1 hurt their own ears with the @!#%%'n Klein Bottle%s%s"), "") \
- MSG_INFO_NOTIF(1, INFO_WEAPON_LASER_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponlaser", _("^BG%s%s^K1 was shot to death by ^BG%s^K1's Laser%s%s"), "") \
- MSG_INFO_NOTIF(1, INFO_WEAPON_LASER_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponlaser", _("^BG%s^K1 shot themself to hell with their Laser%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_MACHINEGUN_MURDER_SNIPE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponuzi", _("^BG%s%s^K1 was sniped by ^BG%s^K1's Machine Gun%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_MACHINEGUN_MURDER_SPRAY, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponuzi", _("^BG%s%s^K1 was riddled full of holes by ^BG%s^K1's Machine Gun%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_MINELAYER_LIMIT, 0, 1, "f1", "", "", _("^BGYou cannot place more than ^F2%s^BG mines at a time"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_MINELAYER_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponminelayer", _("^BG%s%s^K1 got too close to ^BG%s^K1's mine%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_MINELAYER_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponminelayer", _("^BG%s^K1 forgot about their mine%s%s"), "") \
- MSG_INFO_NOTIF(1, INFO_WEAPON_MINSTANEX_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponminstanex", _("^BG%s%s^K1 has been vaporized by ^BG%s^K1's Minstanex%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_MORTAR_MURDER_BOUNCE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapongrenadelauncher", _("^BG%s%s^K1 got too close to ^BG%s^K1's Mortar grenade%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_MORTAR_MURDER_EXPLODE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapongrenadelauncher", _("^BG%s%s^K1 ate ^BG%s^K1's Mortar grenade%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_MORTAR_SUICIDE_BOUNCE, 2, 1, "s1 s2loc spree_lost", "s1", "weapongrenadelauncher", _("^BG%s^K1 didn't see their own Mortar grenade%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_MORTAR_SUICIDE_EXPLODE, 2, 1, "s1 s2loc spree_lost", "s1", "weapongrenadelauncher", _("^BG%s^K1 blew themself up with their own Mortar%s%s"), "") \
- MSG_INFO_NOTIF(1, INFO_WEAPON_NEX_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponnex", _("^BG%s%s^K1 has been vaporized by ^BG%s^K1's Nex%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrifle", _("^BG%s%s^K1 was sniped with a Rifle by ^BG%s^K1%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER_HAIL, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrifle", _("^BG%s%s^K1 died in ^BG%s^K1's Rifle bullet hail%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER_HAIL_PIERCING, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrifle", _("^BG%s%s^K1 failed to hide from ^BG%s^K1's Rifle bullet hail%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER_PIERCING, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrifle", _("^BG%s%s^K1 failed to hide from ^BG%s^K1's Rifle%s%s"), "") \
- MSG_INFO_NOTIF(1, INFO_WEAPON_ROCKETLAUNCHER_MURDER_DIRECT, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrocketlauncher", _("^BG%s%s^K1 ate ^BG%s^K1's rocket%s%s"), "") \
- MSG_INFO_NOTIF(1, INFO_WEAPON_ROCKETLAUNCHER_MURDER_SPLASH, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrocketlauncher", _("^BG%s%s^K1 got too close ^BG%s^K1's rocket%s%s"), "") \
- MSG_INFO_NOTIF(1, INFO_WEAPON_ROCKETLAUNCHER_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponrocketlauncher", _("^BG%s^K1 blew themself up with their Rocketlauncher%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_RPC_MURDER_DIRECT, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrpc", _("^BG%s%s^K1 was sawn in half by ^BG%s^K1's Rocket Propelled Chainsaw%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_RPC_MURDER_SPLASH, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrpc", _("^BG%s%s^K1 almost dodged ^BG%s^K1's Rocket Propelled Chainsaw%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_RPC_SUICIDE_DIRECT, 2, 1, "s1 s2loc spree_lost", "s1", "weaponrpc", _("^BG%s^K1 was sawn in half by their own Rocket Propelled Chainsaw%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_RPC_SUICIDE_SPLASH, 2, 1, "s1 s2loc spree_lost", "s1", "weaponrpc", _("^BG%s^K1 blew themself up with their Rocket Propelled Chainsaw%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_SEEKER_MURDER_SPRAY, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponseeker", _("^BG%s%s^K1 was pummeled by ^BG%s^K1's Seeker rockets%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_SEEKER_MURDER_TAG, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponseeker", _("^BG%s%s^K1 was tagged by ^BG%s^K1's Seeker%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_SEEKER_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponseeker", _("^BG%s^K1 played with tiny Seeker rockets%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_SHOCKWAVE_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponshotgun", _("^BG%s%s^K1 was gunned down by ^BG%s^K1's Shockwave%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_SHOCKWAVE_MURDER_SLAP, 3, 2, "spree_inf s2 s1 s3loc spree_end", "s2 s1", "notify_melee_shotgun", _("^BG%s%s^K1 slapped ^BG%s^K1 around a bit with a large Shockwave%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_SHOTGUN_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponshotgun", _("^BG%s%s^K1 was gunned down by ^BG%s^K1's Shotgun%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_SHOTGUN_MURDER_SLAP, 3, 2, "spree_inf s2 s1 s3loc spree_end", "s2 s1", "notify_melee_shotgun", _("^BG%s%s^K1 slapped ^BG%s^K1 around a bit with a large Shotgun%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_THINKING_WITH_PORTALS, 2, 1, "s1 s2loc spree_lost", "s1", "notify_selfkill", _("^BG%s^K1 is now thinking with portals%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_TUBA_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapontuba", _("^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Tuba%s%s"), "") \
MSG_INFO_NOTIF(1, INFO_WEAPON_TUBA_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weapontuba", _("^BG%s^K1 hurt their own ears with the @!#%%'n Tuba%s%s"), "") \
- MSG_INFO_NOTIF(1, INFO_WEAPON_UZI_MURDER_SNIPE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponuzi", _("^BG%s%s^K1 was sniped by ^BG%s^K1's Machine Gun%s%s"), "") \
- MSG_INFO_NOTIF(1, INFO_WEAPON_UZI_MURDER_SPRAY, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponuzi", _("^BG%s%s^K1 was riddled full of holes by ^BG%s^K1's Machine Gun%s%s"), "")
+ MSG_INFO_NOTIF(1, INFO_WEAPON_VAPORIZER_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponminstanex", _("^BG%s%s^K1 has been sublimated by ^BG%s^K1's Vaporizer%s%s"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_VORTEX_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponnex", _("^BG%s%s^K1 has been vaporized by ^BG%s^K1's Vortex%s%s"), "")
#define MULTITEAM_CENTER2(default,prefix,strnum,flnum,args,cpid,durcnt,normal,gentle) \
MSG_CENTER_NOTIF(default, prefix##RED, strnum, flnum, args, cpid, durcnt, TCR(normal, COL_TEAM_1, strtoupper(NAME_TEAM_1)), TCR(gentle, COL_TEAM_1, strtoupper(NAME_TEAM_1))) \
MULTITEAM_CENTER##teams(default,prefix,strnum,flnum,args,cpid,durcnt,normal,gentle)
#define MSG_CENTER_NOTIFICATIONS \
+ MSG_CENTER_NOTIF(1, CENTER_ALONE, 0, 0, "", NO_CPID, "0 0", _("^F4You are now alone!"), "") \
MSG_CENTER_NOTIF(1, CENTER_ASSAULT_ATTACKING, 0, 0, "", CPID_ASSAULT_ROLE, "0 0", _("^BGYou are attacking!"), "") \
MSG_CENTER_NOTIF(1, CENTER_ASSAULT_DEFENDING, 0, 0, "", CPID_ASSAULT_ROLE, "0 0", _("^BGYou are defending!"), "") \
MSG_CENTER_NOTIF(1, CENTER_COUNTDOWN_BEGIN, 0, 0, "", CPID_ROUND, "2 0", _("^F4Begin!"), "") \
MSG_CENTER_NOTIF(1, CENTER_ROUND_TIED, 0, 0, "", CPID_ROUND, "0 0", _("^BGRound tied"), "") \
MSG_CENTER_NOTIF(1, CENTER_ROUND_OVER, 0, 0, "", CPID_ROUND, "0 0", _("^BGRound over, there's no winner"), "") \
MSG_CENTER_NOTIF(1, CENTER_CAMPCHECK, 0, 0, "", CPID_CAMPCHECK, "0 0", _("^F2Don't camp!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_COINTOSS, 1, 0, "s1", NO_CPID, "0 0", _("^F2Throwing coin... Result: %s^F2!"), "") \
MSG_CENTER_NOTIF(1, CENTER_CTF_CAPTURESHIELD_FREE, 0, 0, "", CPID_CTF_CAPSHIELD, "0 0", _("^BGYou are now free.\n^BGFeel free to ^F2try to capture^BG the flag again\n^BGif you think you will succeed."), "") \
MSG_CENTER_NOTIF(1, CENTER_CTF_CAPTURESHIELD_SHIELDED, 0, 0, "", CPID_CTF_CAPSHIELD, "0 0", _("^BGYou are now ^F1shielded^BG from the flag\n^BGfor ^F2too many unsuccessful attempts^BG to capture.\n^BGMake some defensive scores before trying again."), "") \
MULTITEAM_CENTER(1, CENTER_CTF_CAPTURE_, 2, 0, 0, "", CPID_CTF_LOWPRIO, "0 0", _("^BGYou captured the ^TC^TT^BG flag!"), "") \
MSG_CENTER_NOTIF(1, CENTER_DEATH_MURDER_TYPEFRAGGED_VERBOSE, 1, 4, "spree_cen s1 frag_stats", NO_CPID, "0 0", _("^K1%sYou were typefragged by ^BG%s^BG%s"), _("^K1%sYou were scored against by ^BG%s^K1 while typing^BG%s")) \
MSG_CENTER_NOTIF(1, CENTER_DEATH_MURDER_TYPEFRAG_VERBOSE, 1, 2, "spree_cen s1 frag_ping", NO_CPID, "0 0", _("^K1%sYou typefragged ^BG%s^BG%s"), _("^K1%sYou scored against ^BG%s^K1 while they were typing^BG%s")) \
MSG_CENTER_NOTIF(1, CENTER_NADE_THROW, 0, 0, "", CPID_NADES, "0 0", _("^BGPress ^F2DROPWEAPON^BG again to toss the nade!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_NADE_BONUS, 0, 0, "", CPID_NADES, "0 0", _("^F2You got a ^K1BONUS GRENADE^F2!"), "") \
MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_AUTOTEAMCHANGE, 0, 1, "death_team", NO_CPID, "0 0", _("^BGYou have been moved into a different team\nYou are now on: %s"), "") \
MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_BETRAYAL, 0, 0, "", NO_CPID, "0 0", _("^K1Don't shoot your team mates!"), _("^K1Don't go against your team mates!")) \
MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_CAMP, 0, 0, "", NO_CPID, "0 0", _("^K1Die camper!"), _("^K1Reconsider your tactics, camper!")) \
MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_LAVA, 0, 0, "", NO_CPID, "0 0", _("^K1You couldn't stand the heat!"), "") \
MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_MONSTER, 0, 0, "", NO_CPID, "0 0", _("^K1You were killed by a monster!"), _("^K1You need to watch out for monsters!")) \
MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_NADE, 0, 0, "", NO_CPID, "0 0", _("^K1You forgot to put the pin back in!"), _("^K1Tastes like chicken!")) \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_NADE_NAPALM, 0, 0, "", NO_CPID, "0 0", _("^K1Hanging around a napalm explosion is bad!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_NADE_ICE_FREEZE, 0, 0, "", NO_CPID, "0 0", _("^K1You got a little bit too cold!"), _("^K1You felt a little chilly!")) \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_NADE_HEAL, 0, 0, "", NO_CPID, "0 0", _("^K1Your Healing Nade is a bit defective"), "") \
MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_NOAMMO, 0, 0, "", NO_CPID, "0 0", _("^K1You were killed for running out of ammo..."), _("^K1You are respawning for running out of ammo...")) \
MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_ROT, 0, 0, "", NO_CPID, "0 0", _("^K1You grew too old without taking your medicine"), _("^K1You need to preserve your health")) \
MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_SHOOTING_STAR, 0, 0, "", NO_CPID, "0 0", _("^K1You became a shooting star!"), "") \
MSG_CENTER_NOTIF(1, CENTER_DEATH_TEAMKILL_FRAG, 1, 0, "s1", NO_CPID, "0 0", _("^K1Moron! You fragged ^BG%s^K1, a team mate!"), _("^K1Moron! You went against ^BG%s^K1, a team mate!")) \
MSG_CENTER_NOTIF(1, CENTER_DEATH_TEAMKILL_FRAGGED, 1, 0, "s1", NO_CPID, "0 0", _("^K1You were fragged by ^BG%s^K1, a team mate"), _("^K1You were scored against by ^BG%s^K1, a team mate")) \
MSG_CENTER_NOTIF(1, CENTER_DISCONNECT_IDLING, 0, 1, "", CPID_IDLING, "1 f1", _("^K1Stop idling!\n^BGDisconnecting in ^COUNT..."), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DOOR_LOCKED_NEED, 0, 0, "", NO_CPID, "0 0", _("^BGYou need %s^BG!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DOOR_LOCKED_ALSONEED, 0, 0, "", NO_CPID, "0 0", _("^BGYou also need %s^BG!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DOOR_UNLOCKED, 0, 0, "", NO_CPID, "0 0", _("^BGDoor unlocked!"), "") \
MSG_CENTER_NOTIF(1, CENTER_EXTRALIVES, 0, 0, "", NO_CPID, "0 0", _("^F2You picked up some extra lives"), "") \
MSG_CENTER_NOTIF(1, CENTER_FREEZETAG_FREEZE, 1, 0, "s1", NO_CPID, "0 0", _("^K3You froze ^BG%s"), "") \
MSG_CENTER_NOTIF(1, CENTER_FREEZETAG_FROZEN, 1, 0, "s1", NO_CPID, "0 0", _("^K1You were frozen by ^BG%s"), "") \
MSG_CENTER_NOTIF(1, CENTER_FREEZETAG_REVIVE, 1, 0, "s1", NO_CPID, "0 0", _("^K3You revived ^BG%s"), "") \
- MSG_CENTER_NOTIF(1, CENTER_FREEZETAG_REVIVE_FALL, 0, 0, "", NO_CPID, "0 0", _("^K3You revived yourself"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_FREEZETAG_REVIVE_SELF, 0, 0, "", NO_CPID, "0 0", _("^K3You revived yourself"), "") \
MSG_CENTER_NOTIF(1, CENTER_FREEZETAG_REVIVED, 1, 0, "s1", NO_CPID, "0 0", _("^K3You were revived by ^BG%s"), "") \
MSG_CENTER_NOTIF(1, CENTER_FREEZETAG_AUTO_REVIVED, 0, 1, "f1", NO_CPID, "0 0", _("^K3You were automatically revived after %s second(s)"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_GENERATOR_UNDERATTACK, 0, 0, "", NO_CPID, "0 0", _("^BGThe generator is under attack!"), "") \
MULTITEAM_CENTER(1, CENTER_ROUND_TEAM_WIN_, 4, 0, 0, "", CPID_ROUND, "0 0", _("^TC^TT^BG team wins the round"), "") \
MSG_CENTER_NOTIF(1, CENTER_ROUND_PLAYER_WIN, 1, 0, "s1", CPID_ROUND, "0 0", _("^BG%s^BG wins the round"), "") \
MSG_CENTER_NOTIF(1, CENTER_FREEZETAG_SELF, 0, 0, "", NO_CPID, "0 0", _("^K1You froze yourself"), "") \
MSG_CENTER_NOTIF(1, CENTER_FREEZETAG_SPAWN_LATE, 0, 0, "", NO_CPID, "0 0", _("^K1Round already started, you spawn as frozen"), "") \
MSG_CENTER_NOTIF(1, CENTER_INVASION_SUPERMONSTER, 1, 0, "s1", NO_CPID, "0 0", _("^K1A %s has arrived!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_ITEM_BUFF_DROP, 0, 1, "item_buffname", CPID_ITEM, "item_centime 0", _("^BGYou dropped the %s^BG buff!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_ITEM_BUFF_GOT, 0, 1, "item_buffname", CPID_ITEM, "item_centime 0", _("^BGYou got the %s^BG buff!"), "") \
MSG_CENTER_NOTIF(1, CENTER_ITEM_WEAPON_DONTHAVE, 0, 1, "item_wepname", CPID_ITEM, "item_centime 0", _("^BGYou do not have the ^F1%s"), "") \
MSG_CENTER_NOTIF(1, CENTER_ITEM_WEAPON_DROP, 1, 1, "item_wepname item_wepammo", CPID_ITEM, "item_centime 0", _("^BGYou dropped the ^F1%s^BG%s"), "") \
MSG_CENTER_NOTIF(1, CENTER_ITEM_WEAPON_GOT, 0, 1, "item_wepname", CPID_ITEM, "item_centime 0", _("^BGYou got the ^F1%s"), "") \
MSG_CENTER_NOTIF(1, CENTER_KEYHUNT_ROUNDSTART, 0, 1, "", CPID_KEYHUNT_OTHER, "1 f1", _("^F4Round will start in ^COUNT"), "") \
MSG_CENTER_NOTIF(1, CENTER_KEYHUNT_SCAN, 0, 1, "", CPID_KEYHUNT_OTHER, "f1 0", _("^BGScanning frequency range..."), "") \
MULTITEAM_CENTER(1, CENTER_KEYHUNT_START_, 4, 0, 0, "", CPID_KEYHUNT, "0 0", _("^BGYou are starting with the ^TC^TT Key"), "") \
- MSG_CENTER_NOTIF(1, CENTER_KEYHUNT_WAIT, 0, 4, "missing_teams", CPID_KEYHUNT_OTHER, "0 0", _("^BGWaiting for players to join...\nNeed active players for: %s"), "") \
- MSG_CENTER_NOTIF(1, CENTER_MISSING_TEAMS, 0, 4, "missing_teams", CPID_MISSING_TEAMS, "-1 0", _("^BGWaiting for players to join...\nNeed active players for: %s"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_KEYHUNT_WAIT, 0, 1, "missing_teams", CPID_KEYHUNT_OTHER, "0 0", _("^BGWaiting for players to join...\nNeed active players for: %s"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_LMS_NOLIVES, 0, 0, "", CPID_LMS, "0 0", _("^BGYou have no lives left, you must wait until the next match"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_MISSING_TEAMS, 0, 1, "missing_teams", CPID_MISSING_TEAMS, "-1 0", _("^BGWaiting for players to join...\nNeed active players for: %s"), "") \
MSG_CENTER_NOTIF(1, CENTER_MISSING_PLAYERS, 0, 1, "f1", CPID_MISSING_PLAYERS, "-1 0", _("^BGWaiting for %s player(s) to join..."), "") \
- MSG_CENTER_NOTIF(1, CENTER_MINSTA_FINDAMMO, 0, 0, "", CPID_MINSTA_FINDAMMO, "1 9", _("^F4^COUNT^BG left to find some ammo!"), "") \
- MSG_CENTER_NOTIF(1, CENTER_MINSTA_FINDAMMO_FIRST, 0, 0, "", CPID_MINSTA_FINDAMMO, "1 10", _("^BGGet some ammo or you'll be dead in ^F4^COUNT^BG!"), _("^BGGet some ammo! ^F4^COUNT^BG left!")) \
- MSG_CENTER_NOTIF(1, CENTER_MINSTA_LIVES_REMAINING, 0, 1, "f1", NO_CPID, "0 0", _("^F2Extra lives remaining: ^K1%s"), "") \
- MSG_CENTER_NOTIF(1, CENTER_MINSTA_SECONDARY, 0, 0, "", NO_CPID, "0 0", _("^BGSecondary fire inflicts no damage!"), "") \
- MSG_CENTER_NOTIF(1, CENTER_MOTD, 1, 0, "s1", CPID_MOTD, "-1 0", _("^BG%s"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_INSTAGIB_FINDAMMO, 0, 0, "", CPID_INSTAGIB_FINDAMMO,"1 9", _("^F4^COUNT^BG left to find some ammo!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_INSTAGIB_FINDAMMO_FIRST, 0, 0, "", CPID_INSTAGIB_FINDAMMO,"1 10", _("^BGGet some ammo or you'll be dead in ^F4^COUNT^BG!"), _("^BGGet some ammo! ^F4^COUNT^BG left!")) \
+ MSG_CENTER_NOTIF(1, CENTER_INSTAGIB_LIVES_REMAINING, 0, 1, "f1", NO_CPID, "0 0", _("^F2Extra lives remaining: ^K1%s"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_MOTD, 1, 0, "s1", CPID_MOTD, "-1 0", "^BG%s", "") \
MSG_CENTER_NOTIF(1, CENTER_NIX_COUNTDOWN, 0, 2, "item_wepname", CPID_NIX, "1 f2", _("^F2^COUNT^BG until weapon change...\nNext weapon: ^F1%s"), "") \
MSG_CENTER_NOTIF(1, CENTER_NIX_NEWWEAPON, 0, 1, "item_wepname", CPID_NIX, "0 0", _("^F2Active weapon: ^F1%s"), "") \
MSG_CENTER_NOTIF(1, CENTER_NADE, 0, 0, "", NO_CPID, "0 0", _("^BGPress ^F2DROPWEAPON^BG again to toss the grenade!"), "") \
- MSG_CENTER_NOTIF(1, CENTER_ONS_NOTSHIELDED, 0, 0, "", CPID_ONSLAUGHT, "0 0", _("^K1Your generator is NOT shielded!\n^BGRe-capture controlpoints to shield it!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_ONS_CAPTURE, 1, 0, "s1", CPID_ONSLAUGHT, "0 0", _("^BGYou captured %s^BG control point"), "") \
+ MULTITEAM_CENTER(1, CENTER_ONS_CAPTURE_, 4, 1, 0, "s1", CPID_ONSLAUGHT, "0 0", _("^TC^TT^BG team captured %s^BG control point"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_ONS_CONTROLPOINT_SHIELDED, 0, 0, "", CPID_ONS_CAPSHIELD, "0 0", _("^BGThis control point currently cannot be captured"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_ONS_GENERATOR_SHIELDED, 0, 0, "", CPID_ONS_CAPSHIELD, "0 0", _("^BGThe enemy generator cannot be destroyed yet\n^F2Capture some control points to unshield it"), "") \
+ MULTITEAM_CENTER(1, CENTER_ONS_NOTSHIELDED_, 4, 0, 0, "", CPID_ONSLAUGHT, "0 0", _("^BGThe ^TCenemy^BG generator is no longer shielded!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_ONS_NOTSHIELDED_TEAM, 0, 0, "", CPID_ONSLAUGHT, "0 0", _("^K1Your generator is NOT shielded!\n^BGRe-capture control points to shield it!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_ONS_TELEPORT, 0, 0, "pass_key", CPID_ONSLAUGHT, "0 0", _("^BGPress ^F2DROPFLAG%s^BG to teleport"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_ONS_TELEPORT_ANTISPAM, 0, 1, "f1secs", CPID_ONSLAUGHT, "0 0", _("^BGTeleporting disabled for %s"), "") \
MSG_CENTER_NOTIF(1, CENTER_OVERTIME_FRAG, 0, 0, "", CPID_OVERTIME, "0 0", _("^F2Now playing ^F4OVERTIME^F2!\nKeep fragging until we have a winner!"), _("^F2Now playing ^F4OVERTIME^F2!\nKeep scoring until we have a winner!")) \
MSG_CENTER_NOTIF(1, CENTER_OVERTIME_CONTROLPOINT, 0, 0, "", CPID_OVERTIME, "5 0", _("^F2Now playing ^F4OVERTIME^F2!\n\nGenerators are now decaying.\nThe more control points your team holds,\nthe faster the enemy generator decays"), "") \
MSG_CENTER_NOTIF(1, CENTER_OVERTIME_TIME, 0, 1, "f1time", CPID_OVERTIME, "0 0", _("^F2Now playing ^F4OVERTIME^F2!\n^BGAdded ^F4%s^BG to the game!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_PORTO_CREATED_IN, 0, 0, "", NO_CPID, "0 0", _("^K1In^BG-portal created"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_PORTO_CREATED_OUT, 0, 0, "", NO_CPID, "0 0", _("^F3Out^BG-portal created"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_PORTO_FAILED, 0, 0, "", NO_CPID, "0 0", _("^K1Portal deployment failed.\n\n^F2Catch it to try again!"), "") \
MSG_CENTER_NOTIF(1, CENTER_POWERDOWN_INVISIBILITY, 0, 0, "", CPID_POWERUP, "0 0", _("^F2Invisibility has worn off"), "") \
MSG_CENTER_NOTIF(1, CENTER_POWERDOWN_SHIELD, 0, 0, "", CPID_POWERUP, "0 0", _("^F2Shield has worn off"), "") \
MSG_CENTER_NOTIF(1, CENTER_POWERDOWN_SPEED, 0, 0, "", CPID_POWERUP, "0 0", _("^F2Speed has worn off"), "") \
MSG_CENTER_NOTIF(1, CENTER_POWERUP_SPEED, 0, 0, "", CPID_POWERUP, "0 0", _("^F2You are on speed"), "") \
MSG_CENTER_NOTIF(1, CENTER_POWERUP_STRENGTH, 0, 0, "", CPID_POWERUP, "0 0", _("^F2Strength infuses your weapons with devastating power"), "") \
MSG_CENTER_NOTIF(1, CENTER_RACE_FINISHLAP, 0, 0, "", CPID_RACE_FINISHLAP, "0 0", _("^F2The race is over, finish your lap!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_SECONDARY_NODAMAGE, 0, 0, "", NO_CPID, "0 0", _("^BGSecondary fire inflicts no damage!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_SEQUENCE_COMPLETED, 0, 0, "", NO_CPID, "0 0", _("^BGSequence completed!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_SEQUENCE_COUNTER, 0, 0, "", NO_CPID, "0 0", _("^BGThere are more to go..."), "") \
+ MSG_CENTER_NOTIF(1, CENTER_SEQUENCE_COUNTER_FEWMORE, 0, 1, "f1", NO_CPID, "0 0", _("^BGOnly %s^BG more to go..."), "") \
MSG_CENTER_NOTIF(1, CENTER_SUPERWEAPON_BROKEN, 0, 0, "", CPID_POWERUP, "0 0", _("^F2Superweapons have broken down"), "") \
MSG_CENTER_NOTIF(1, CENTER_SUPERWEAPON_LOST, 0, 0, "", CPID_POWERUP, "0 0", _("^F2Superweapons have been lost"), "") \
MSG_CENTER_NOTIF(1, CENTER_SUPERWEAPON_PICKUP, 0, 0, "", CPID_POWERUP, "0 0", _("^F2You now have a superweapon"), "") \
MSG_CENTER_NOTIF(1, CENTER_TEAMCHANGE_SPECTATE, 0, 1, "", CPID_TEAMCHANGE, "1 f1", _("^K1Spectating in ^COUNT"), "") \
MSG_CENTER_NOTIF(1, CENTER_TEAMCHANGE_SUICIDE, 0, 1, "", CPID_TEAMCHANGE, "1 f1", _("^K1Suicide in ^COUNT"), "") \
MSG_CENTER_NOTIF(1, CENTER_TIMEOUT_BEGINNING, 0, 1, "", CPID_TIMEOUT, "1 f1", _("^F4Timeout begins in ^COUNT"), "") \
- MSG_CENTER_NOTIF(1, CENTER_TIMEOUT_ENDING, 0, 1, "", CPID_TIMEOUT, "1 f1", _("^F4Timeout ends in ^COUNT"), "")
+ MSG_CENTER_NOTIF(1, CENTER_TIMEOUT_ENDING, 0, 1, "", CPID_TIMEOUT, "1 f1", _("^F4Timeout ends in ^COUNT"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_WEAPON_MINELAYER_LIMIT, 0, 1, "f1", NO_CPID, "0 0", _("^BGYou cannot place more than ^F2%s^BG mines at a time"), "")
#define MULTITEAM_MULTI2(default,prefix,anncepre,infopre,centerpre) \
MSG_MULTI_NOTIF(default, prefix##RED, anncepre##RED, infopre##RED, centerpre##RED) \
MSG_MULTI_NOTIF(1, DEATH_MURDER_LAVA, NO_MSG, INFO_DEATH_MURDER_LAVA, NO_MSG) \
MSG_MULTI_NOTIF(1, DEATH_MURDER_MONSTER, NO_MSG, INFO_DEATH_MURDER_MONSTER, CENTER_DEATH_SELF_MONSTER) \
MSG_MULTI_NOTIF(1, DEATH_MURDER_NADE, NO_MSG, INFO_DEATH_MURDER_NADE, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_NADE_NAPALM, NO_MSG, INFO_DEATH_MURDER_NADE_NAPALM, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_NADE_ICE, NO_MSG, INFO_DEATH_MURDER_NADE_ICE, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_NADE_ICE_FREEZE, NO_MSG, INFO_DEATH_MURDER_NADE_ICE_FREEZE, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_NADE_HEAL, NO_MSG, INFO_DEATH_MURDER_NADE_HEAL, NO_MSG) \
MSG_MULTI_NOTIF(1, DEATH_MURDER_SHOOTING_STAR, NO_MSG, INFO_DEATH_MURDER_SHOOTING_STAR, NO_MSG) \
MSG_MULTI_NOTIF(1, DEATH_MURDER_SLIME, NO_MSG, INFO_DEATH_MURDER_SLIME, NO_MSG) \
MSG_MULTI_NOTIF(1, DEATH_MURDER_SWAMP, NO_MSG, INFO_DEATH_MURDER_SWAMP, NO_MSG) \
MSG_MULTI_NOTIF(1, DEATH_MURDER_VH_WAKI_DEATH, NO_MSG, INFO_DEATH_MURDER_VH_WAKI_DEATH, NO_MSG) \
MSG_MULTI_NOTIF(1, DEATH_MURDER_VH_WAKI_GUN, NO_MSG, INFO_DEATH_MURDER_VH_WAKI_GUN, NO_MSG) \
MSG_MULTI_NOTIF(1, DEATH_MURDER_VH_WAKI_ROCKET, NO_MSG, INFO_DEATH_MURDER_VH_WAKI_ROCKET, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_VENGEANCE, NO_MSG, INFO_DEATH_MURDER_VENGEANCE, NO_MSG) \
MSG_MULTI_NOTIF(1, DEATH_MURDER_VOID, NO_MSG, INFO_DEATH_MURDER_VOID, NO_MSG) \
MSG_MULTI_NOTIF(1, DEATH_SELF_AUTOTEAMCHANGE, NO_MSG, INFO_DEATH_SELF_AUTOTEAMCHANGE, CENTER_DEATH_SELF_AUTOTEAMCHANGE) \
MSG_MULTI_NOTIF(1, DEATH_SELF_BETRAYAL, NO_MSG, INFO_DEATH_SELF_BETRAYAL, CENTER_DEATH_SELF_BETRAYAL) \
MSG_MULTI_NOTIF(1, DEATH_SELF_MON_ZOMBIE_JUMP, NO_MSG, INFO_DEATH_SELF_MON_ZOMBIE_JUMP, CENTER_DEATH_SELF_MONSTER) \
MSG_MULTI_NOTIF(1, DEATH_SELF_MON_ZOMBIE_MELEE, NO_MSG, INFO_DEATH_SELF_MON_ZOMBIE_MELEE, CENTER_DEATH_SELF_MONSTER) \
MSG_MULTI_NOTIF(1, DEATH_SELF_NADE, NO_MSG, INFO_DEATH_SELF_NADE, CENTER_DEATH_SELF_NADE) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_NADE_NAPALM, NO_MSG, INFO_DEATH_SELF_NADE_NAPALM, CENTER_DEATH_SELF_NADE_NAPALM) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_NADE_ICE, NO_MSG, INFO_DEATH_SELF_NADE_ICE, CENTER_DEATH_SELF_NADE_ICE_FREEZE) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_NADE_ICE_FREEZE, NO_MSG, INFO_DEATH_SELF_NADE_ICE_FREEZE, CENTER_DEATH_SELF_NADE_ICE_FREEZE) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_NADE_HEAL, NO_MSG, INFO_DEATH_SELF_NADE_HEAL, CENTER_DEATH_SELF_NADE_HEAL) \
MSG_MULTI_NOTIF(1, DEATH_SELF_NOAMMO, NO_MSG, INFO_DEATH_SELF_NOAMMO, CENTER_DEATH_SELF_NOAMMO) \
MSG_MULTI_NOTIF(1, DEATH_SELF_ROT, NO_MSG, INFO_DEATH_SELF_ROT, CENTER_DEATH_SELF_ROT) \
MSG_MULTI_NOTIF(1, DEATH_SELF_SHOOTING_STAR, NO_MSG, INFO_DEATH_SELF_SHOOTING_STAR, CENTER_DEATH_SELF_SHOOTING_STAR) \
MSG_MULTI_NOTIF(1, DEATH_SELF_VH_WAKI_DEATH, NO_MSG, INFO_DEATH_SELF_VH_WAKI_DEATH, CENTER_DEATH_SELF_VH_WAKI_DEATH) \
MSG_MULTI_NOTIF(1, DEATH_SELF_VH_WAKI_ROCKET, NO_MSG, INFO_DEATH_SELF_VH_WAKI_ROCKET, CENTER_DEATH_SELF_VH_WAKI_ROCKET) \
MSG_MULTI_NOTIF(1, DEATH_SELF_VOID, NO_MSG, INFO_DEATH_SELF_VOID, CENTER_DEATH_SELF_VOID) \
+ MSG_MULTI_NOTIF(1, ITEM_BUFF_DROP, NO_MSG, INFO_ITEM_BUFF_DROP, CENTER_ITEM_BUFF_DROP) \
+ MSG_MULTI_NOTIF(1, ITEM_BUFF_GOT, NO_MSG, INFO_ITEM_BUFF_GOT, CENTER_ITEM_BUFF_GOT) \
MSG_MULTI_NOTIF(1, ITEM_WEAPON_DONTHAVE, NO_MSG, INFO_ITEM_WEAPON_DONTHAVE, CENTER_ITEM_WEAPON_DONTHAVE) \
MSG_MULTI_NOTIF(1, ITEM_WEAPON_DROP, NO_MSG, INFO_ITEM_WEAPON_DROP, CENTER_ITEM_WEAPON_DROP) \
MSG_MULTI_NOTIF(1, ITEM_WEAPON_GOT, NO_MSG, INFO_ITEM_WEAPON_GOT, CENTER_ITEM_WEAPON_GOT) \
MSG_MULTI_NOTIF(1, ITEM_WEAPON_NOAMMO, NO_MSG, INFO_ITEM_WEAPON_NOAMMO, CENTER_ITEM_WEAPON_NOAMMO) \
MSG_MULTI_NOTIF(1, ITEM_WEAPON_PRIMORSEC, NO_MSG, INFO_ITEM_WEAPON_PRIMORSEC, CENTER_ITEM_WEAPON_PRIMORSEC) \
MSG_MULTI_NOTIF(1, ITEM_WEAPON_UNAVAILABLE, NO_MSG, INFO_ITEM_WEAPON_UNAVAILABLE, CENTER_ITEM_WEAPON_UNAVAILABLE) \
+ MSG_MULTI_NOTIF(1, MULTI_COINTOSS, NO_MSG, INFO_COINTOSS, CENTER_COINTOSS) \
MSG_MULTI_NOTIF(1, MULTI_COUNTDOWN_BEGIN, ANNCE_BEGIN, NO_MSG, CENTER_COUNTDOWN_BEGIN) \
- MSG_MULTI_NOTIF(1, MULTI_MINSTA_FINDAMMO, ANNCE_NUM_10, NO_MSG, CENTER_MINSTA_FINDAMMO_FIRST) \
+ MSG_MULTI_NOTIF(1, MULTI_INSTAGIB_FINDAMMO, ANNCE_NUM_10, NO_MSG, CENTER_INSTAGIB_FINDAMMO_FIRST) \
MSG_MULTI_NOTIF(1, WEAPON_ACCORDEON_MURDER, NO_MSG, INFO_WEAPON_ACCORDEON_MURDER, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_ACCORDEON_SUICIDE, NO_MSG, INFO_WEAPON_ACCORDEON_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_ARC_MURDER, NO_MSG, INFO_WEAPON_ARC_MURDER, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_BLASTER_MURDER, NO_MSG, INFO_WEAPON_BLASTER_MURDER, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_BLASTER_SUICIDE, NO_MSG, INFO_WEAPON_BLASTER_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
MSG_MULTI_NOTIF(1, WEAPON_CRYLINK_MURDER, NO_MSG, INFO_WEAPON_CRYLINK_MURDER, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_CRYLINK_SUICIDE, NO_MSG, INFO_WEAPON_CRYLINK_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_DEVASTATOR_MURDER_DIRECT, NO_MSG, INFO_WEAPON_DEVASTATOR_MURDER_DIRECT, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_DEVASTATOR_MURDER_SPLASH, NO_MSG, INFO_WEAPON_DEVASTATOR_MURDER_SPLASH, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_DEVASTATOR_SUICIDE, NO_MSG, INFO_WEAPON_DEVASTATOR_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
MSG_MULTI_NOTIF(1, WEAPON_ELECTRO_MURDER_BOLT, NO_MSG, INFO_WEAPON_ELECTRO_MURDER_BOLT, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_ELECTRO_MURDER_COMBO, NO_MSG, INFO_WEAPON_ELECTRO_MURDER_COMBO, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_ELECTRO_MURDER_ORBS, NO_MSG, INFO_WEAPON_ELECTRO_MURDER_ORBS, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_HAGAR_SUICIDE, NO_MSG, INFO_WEAPON_HAGAR_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
MSG_MULTI_NOTIF(1, WEAPON_HLAC_MURDER, NO_MSG, INFO_WEAPON_HLAC_MURDER, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_HLAC_SUICIDE, NO_MSG, INFO_WEAPON_HLAC_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_HMG_MURDER_SNIPE, NO_MSG, INFO_WEAPON_HMG_MURDER_SNIPE, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_HMG_MURDER_SPRAY, NO_MSG, INFO_WEAPON_HMG_MURDER_SPRAY, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_HOOK_MURDER, NO_MSG, INFO_WEAPON_HOOK_MURDER, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_KLEINBOTTLE_MURDER, NO_MSG, INFO_WEAPON_KLEINBOTTLE_MURDER, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_KLEINBOTTLE_SUICIDE, NO_MSG, INFO_WEAPON_KLEINBOTTLE_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
- MSG_MULTI_NOTIF(1, WEAPON_LASER_MURDER, NO_MSG, INFO_WEAPON_LASER_MURDER, NO_MSG) \
- MSG_MULTI_NOTIF(1, WEAPON_LASER_SUICIDE, NO_MSG, INFO_WEAPON_LASER_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_MACHINEGUN_MURDER_SNIPE, NO_MSG, INFO_WEAPON_MACHINEGUN_MURDER_SNIPE, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_MACHINEGUN_MURDER_SPRAY, NO_MSG, INFO_WEAPON_MACHINEGUN_MURDER_SPRAY, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_MINELAYER_LIMIT, NO_MSG, INFO_WEAPON_MINELAYER_LIMIT, CENTER_WEAPON_MINELAYER_LIMIT) \
MSG_MULTI_NOTIF(1, WEAPON_MINELAYER_MURDER, NO_MSG, INFO_WEAPON_MINELAYER_MURDER, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_MINELAYER_SUICIDE, NO_MSG, INFO_WEAPON_MINELAYER_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
- MSG_MULTI_NOTIF(1, WEAPON_MINSTANEX_MURDER, NO_MSG, INFO_WEAPON_MINSTANEX_MURDER, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_MORTAR_MURDER_BOUNCE, NO_MSG, INFO_WEAPON_MORTAR_MURDER_BOUNCE, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_MORTAR_MURDER_EXPLODE, NO_MSG, INFO_WEAPON_MORTAR_MURDER_EXPLODE, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_MORTAR_SUICIDE_BOUNCE, NO_MSG, INFO_WEAPON_MORTAR_SUICIDE_BOUNCE, CENTER_DEATH_SELF_GENERIC) \
MSG_MULTI_NOTIF(1, WEAPON_MORTAR_SUICIDE_EXPLODE, NO_MSG, INFO_WEAPON_MORTAR_SUICIDE_EXPLODE, CENTER_DEATH_SELF_GENERIC) \
- MSG_MULTI_NOTIF(1, WEAPON_NEX_MURDER, NO_MSG, INFO_WEAPON_NEX_MURDER, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_RIFLE_MURDER, NO_MSG, INFO_WEAPON_RIFLE_MURDER, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_RIFLE_MURDER_HAIL, NO_MSG, INFO_WEAPON_RIFLE_MURDER_HAIL, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_RIFLE_MURDER_HAIL_PIERCING, NO_MSG, INFO_WEAPON_RIFLE_MURDER_HAIL_PIERCING, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_RIFLE_MURDER_PIERCING, NO_MSG, INFO_WEAPON_RIFLE_MURDER_PIERCING, NO_MSG) \
- MSG_MULTI_NOTIF(1, WEAPON_ROCKETLAUNCHER_MURDER_DIRECT, NO_MSG, INFO_WEAPON_ROCKETLAUNCHER_MURDER_DIRECT, NO_MSG) \
- MSG_MULTI_NOTIF(1, WEAPON_ROCKETLAUNCHER_MURDER_SPLASH, NO_MSG, INFO_WEAPON_ROCKETLAUNCHER_MURDER_SPLASH, NO_MSG) \
- MSG_MULTI_NOTIF(1, WEAPON_ROCKETLAUNCHER_SUICIDE, NO_MSG, INFO_WEAPON_ROCKETLAUNCHER_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_RPC_MURDER_DIRECT, NO_MSG, INFO_WEAPON_RPC_MURDER_DIRECT, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_RPC_MURDER_SPLASH, NO_MSG, INFO_WEAPON_RPC_MURDER_SPLASH, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_RPC_SUICIDE_DIRECT, NO_MSG, INFO_WEAPON_RPC_SUICIDE_DIRECT, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_RPC_SUICIDE_SPLASH, NO_MSG, INFO_WEAPON_RPC_SUICIDE_SPLASH, CENTER_DEATH_SELF_GENERIC) \
MSG_MULTI_NOTIF(1, WEAPON_SEEKER_MURDER_SPRAY, NO_MSG, INFO_WEAPON_SEEKER_MURDER_SPRAY, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_SEEKER_MURDER_TAG, NO_MSG, INFO_WEAPON_SEEKER_MURDER_TAG, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_SEEKER_SUICIDE, NO_MSG, INFO_WEAPON_SEEKER_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_SHOCKWAVE_MURDER, NO_MSG, INFO_WEAPON_SHOCKWAVE_MURDER, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_SHOCKWAVE_MURDER_SLAP, NO_MSG, INFO_WEAPON_SHOCKWAVE_MURDER_SLAP, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_SHOTGUN_MURDER, NO_MSG, INFO_WEAPON_SHOTGUN_MURDER, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_SHOTGUN_MURDER_SLAP, NO_MSG, INFO_WEAPON_SHOTGUN_MURDER_SLAP, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_THINKING_WITH_PORTALS, NO_MSG, INFO_WEAPON_THINKING_WITH_PORTALS, CENTER_DEATH_SELF_GENERIC) \
MSG_MULTI_NOTIF(1, WEAPON_TUBA_MURDER, NO_MSG, INFO_WEAPON_TUBA_MURDER, NO_MSG) \
MSG_MULTI_NOTIF(1, WEAPON_TUBA_SUICIDE, NO_MSG, INFO_WEAPON_TUBA_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
- MSG_MULTI_NOTIF(1, WEAPON_UZI_MURDER_SNIPE, NO_MSG, INFO_WEAPON_UZI_MURDER_SNIPE, NO_MSG) \
- MSG_MULTI_NOTIF(1, WEAPON_UZI_MURDER_SPRAY, NO_MSG, INFO_WEAPON_UZI_MURDER_SPRAY, NO_MSG)
+ MSG_MULTI_NOTIF(1, WEAPON_VAPORIZER_MURDER, NO_MSG, INFO_WEAPON_VAPORIZER_MURDER, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_VORTEX_MURDER, NO_MSG, INFO_WEAPON_VORTEX_MURDER, NO_MSG)
#define MULTITEAM_CHOICE2(default,challow,prefix,chtype,optiona,optionb) \
MSG_CHOICE_NOTIF(default, challow, prefix##RED, chtype, optiona##RED, optionb##RED) \
item_wepname: return full name of a weapon from weaponid
item_wepammo: ammo display for weapon from string
item_centime: amount of time to display weapon message in centerprint
+ item_buffname: return full name of a buff from buffid
death_team: show the full name of the team a player is switching from
*/
ARG_CASE(ARG_CS_SV_HA, "f3race_time", mmssss(f3)) \
ARG_CASE(ARG_CS_SV, "race_col", CCR(((f1 == 1) ? "^F1" : "^F2"))) \
ARG_CASE(ARG_CS_SV, "race_diff", ((f2 > f3) ? sprintf(CCR("^1[+%s]"), mmssss(f2 - f3)) : sprintf(CCR("^2[-%s]"), mmssss(f3 - f2)))) \
- ARG_CASE(ARG_CS, "missing_teams", notif_arg_missing_teams(f1, f2, f3, f4)) \
+ ARG_CASE(ARG_CS, "missing_teams", notif_arg_missing_teams(f1)) \
ARG_CASE(ARG_CS, "pass_key", ((((tmp_s = getcommandkey("pass", "+use")) != "pass") && !(strstrofs(tmp_s, "not bound", 0) >= 0)) ? sprintf(CCR(_(" ^F1(Press %s)")), tmp_s) : "")) \
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_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) : "")) \
ARG_CASE(ARG_CS_SV, "spree_lost", (autocvar_notification_show_sprees ? notif_arg_spree_inf(-2, "", "", f1) : "")) \
- ARG_CASE(ARG_CS_SV, "item_wepname", W_Name(f1)) \
+ ARG_CASE(ARG_CS_SV, "item_wepname", WEP_NAME(f1)) \
+ ARG_CASE(ARG_CS_SV, "item_buffname", sprintf("%s%s", rgb_to_hexcolor(Buff_Color(f1)), Buff_PrettyName(f1))) \
ARG_CASE(ARG_CS_SV, "item_wepammo", (s1 != "" ? sprintf(_(" with %s"), s1) : "")) \
ARG_CASE(ARG_DC, "item_centime", ftos(autocvar_notification_item_centerprinttime)) \
ARG_CASE(ARG_SV, "death_team", Team_ColoredFullName(f1)) \
return sprintf(CCR(_("\n(^F4Dead^BG)%s")), notif_arg_frag_ping(FALSE, fping));
}
- string notif_arg_missing_teams(float f1, float f2, float f3, float f4)
+ string notif_arg_missing_teams(float f1)
{
return sprintf("%s%s%s%s",
- (f1 ?
- sprintf("%s%s", Team_ColoredFullName(f1 - 1), ((f2 + f3 + f4) ? ", " : ""))
+ ((f1 & 1) ?
+ sprintf("%s%s", Team_ColoredFullName(NUM_TEAM_1), ((f1 & (2 + 4 + 8)) ? ", " : ""))
:
""
),
- (f2 ?
- sprintf("%s%s", Team_ColoredFullName(f2 - 1), ((f3 + f4) ? ", " : ""))
+ ((f1 & 2) ?
+ sprintf("%s%s", Team_ColoredFullName(NUM_TEAM_2), ((f1 & (4 + 8)) ? ", " : ""))
:
""
),
- (f3 ?
- sprintf("%s%s", Team_ColoredFullName(f3 - 1), (f4 ? ", " : ""))
+ ((f1 & 4) ?
+ sprintf("%s%s", Team_ColoredFullName(NUM_TEAM_3), ((f1 & 8) ? ", " : ""))
:
""
),
- (f4 ?
- Team_ColoredFullName(f4 - 1)
+ ((f1 & 8) ?
+ Team_ColoredFullName(NUM_TEAM_4)
:
""
)
#endif
printf("Beginning notification initialization on %s%s program...\n", dedi, PROGNAME);
+ #undef dedi
// maybe do another implementation of this with checksums? for now, we don't need versioning
/*if(autocvar_notification_version != NOTIF_VERSION)
--- /dev/null
-// 87 empty?
+ // Full list of all stat constants, icnluded in a single location for easy reference
+ // 255 is the current limit (MAX_CL_STATS - 1), engine will need to be modified if you wish to add more stats
+
+ const float MAX_CL_STATS = 256;
+ const float STAT_HEALTH = 0;
+ // 1 empty?
+ const float STAT_WEAPON = 2;
+ const float STAT_AMMO = 3;
+ const float STAT_ARMOR = 4;
+ const float STAT_WEAPONFRAME = 5;
+ const float STAT_SHELLS = 6;
+ const float STAT_NAILS = 7;
+ const float STAT_ROCKETS = 8;
+ const float STAT_CELLS = 9;
+ const float STAT_ACTIVEWEAPON = 10;
+ const float STAT_TOTALSECRETS = 11;
+ const float STAT_TOTALMONSTERS = 12;
+ const float STAT_SECRETS = 13;
+ const float STAT_MONSTERS = 14;
+ const float STAT_ITEMS = 15;
+ const float STAT_VIEWHEIGHT = 16;
+ // 17 empty?
+ // 18 empty?
+ // 19 empty?
+ // 20 empty?
+ const float STAT_VIEWZOOM = 21;
+ // 22 empty?
+ // 23 empty?
+ // 24 empty?
+ // 25 empty?
+ // 26 empty?
+ // 27 empty?
+ // 28 empty?
+ // 29 empty?
+ // 30 empty?
+ // 31 empty?
+ const float STAT_KH_KEYS = 32;
+ const float STAT_CTF_STATE = 33;
+ // 34 empty?
+ const float STAT_WEAPONS = 35;
+ const float STAT_SWITCHWEAPON = 36;
+ const float STAT_GAMESTARTTIME = 37;
+ const float STAT_STRENGTH_FINISHED = 38;
+ const float STAT_INVINCIBLE_FINISHED = 39;
+ // 40 empty?
+ const float STAT_ARC_HEAT = 41;
+ const float STAT_PRESSED_KEYS = 42;
+ const float STAT_ALLOW_OLDVORTEXBEAM = 43; // this stat could later contain some other bits of info, like, more server-side particle config
+ const float STAT_FUEL = 44;
+ const float STAT_NB_METERSTART = 45;
+ const float STAT_SHOTORG = 46; // compressShotOrigin
+ const float STAT_LEADLIMIT = 47;
+ const float STAT_WEAPON_CLIPLOAD = 48;
+ const float STAT_WEAPON_CLIPSIZE = 49;
+ const float STAT_VORTEX_CHARGE = 50;
+ const float STAT_LAST_PICKUP = 51;
+ const float STAT_HUD = 52;
+ const float STAT_VORTEX_CHARGEPOOL = 53;
+ const float STAT_HIT_TIME = 54;
+ const float STAT_DAMAGE_DEALT_TOTAL = 55;
+ const float STAT_TYPEHIT_TIME = 56;
+ const float STAT_LAYED_MINES = 57;
+ const float STAT_HAGAR_LOAD = 58;
+ const float STAT_SWITCHINGWEAPON = 59;
+ const float STAT_SUPERWEAPONS_FINISHED = 60;
+ const float STAT_VEHICLESTAT_HEALTH = 61;
+ const float STAT_VEHICLESTAT_SHIELD = 62;
+ const float STAT_VEHICLESTAT_ENERGY = 63;
+ const float STAT_VEHICLESTAT_AMMO1 = 64;
+ const float STAT_VEHICLESTAT_RELOAD1 = 65;
+ const float STAT_VEHICLESTAT_AMMO2 = 66;
+ const float STAT_VEHICLESTAT_RELOAD2 = 67;
+ const float STAT_VEHICLESTAT_W2MODE = 68;
+ const float STAT_NADE_TIMER = 69;
+ const float STAT_SECRETS_TOTAL = 70;
+ const float STAT_SECRETS_FOUND = 71;
+ const float STAT_RESPAWN_TIME = 72;
+ const float STAT_ROUNDSTARTTIME = 73;
+ const float STAT_WEAPONS2 = 74;
+ const float STAT_WEAPONS3 = 75;
+ const float STAT_MONSTERS_TOTAL = 76;
+ const float STAT_MONSTERS_KILLED = 77;
+ const float STAT_BUFFS = 78;
+ const float STAT_NADE_BONUS = 79;
+ const float STAT_NADE_BONUS_TYPE = 80;
+ const float STAT_NADE_BONUS_SCORE = 81;
+ const float STAT_HEALING_ORB = 82;
+ const float STAT_HEALING_ORB_ALPHA = 83;
+ const float STAT_PLASMA = 84;
+ const float STAT_OK_AMMO_CHARGE = 85;
+ const float STAT_OK_AMMO_CHARGEPOOl = 86;
++const float STAT_ROUNDLOST = 87;
+ // 88 empty?
+ // 89 empty?
+ // 90 empty?
+ // 91 empty?
+ // 92 empty?
+ // 93 empty?
+ // 94 empty?
+ // 95 empty?
+ // 96 empty?
+ // 97 empty?
+ // 98 empty?
+ // 99 empty?
+
+
+ /* The following stats change depending on the gamemode, so can share the same ID */
+ // IDs 100 to 104 reserved for gamemodes
+
+ // freeze tag, clan arena, jailbreak
+ const float STAT_REDALIVE = 100;
+ const float STAT_BLUEALIVE = 101;
+ const float STAT_YELLOWALIVE = 102;
+ const float STAT_PINKALIVE = 103;
+
+ // domination
+ const float STAT_DOM_TOTAL_PPS = 100;
+ const float STAT_DOM_PPS_RED = 101;
+ const float STAT_DOM_PPS_BLUE = 102;
+ const float STAT_DOM_PPS_YELLOW = 103;
+ const float STAT_DOM_PPS_PINK = 104;
+
+ // vip
+ const float STAT_VIP = 100;
+ const float STAT_VIP_RED = 101;
+ const float STAT_VIP_BLUE = 102;
+ const float STAT_VIP_YELLOW = 103;
+ const float STAT_VIP_PINK = 104;
+
+ // key hunt
+ const float STAT_KH_REDKEY_TEAM = 100;
+ const float STAT_KH_BLUEKEY_TEAM = 101;
+ const float STAT_KH_YELLOWKEY_TEAM = 102;
+ const float STAT_KH_PINKKEY_TEAM = 103;
+
+ /* Gamemode-specific stats end here */
+
+
+ const float STAT_FROZEN = 105;
+ const float STAT_REVIVE_PROGRESS = 106;
+ // 107 empty?
+ // 108 empty?
+ // 109 empty?
+ // 110 empty?
+ // 111 empty?
+ // 112 empty?
+ // 113 empty?
+ // 114 empty?
+ // 115 empty?
+ // 116 empty?
+ // 117 empty?
+ // 118 empty?
+ // 119 empty?
+ // 120 empty?
+ // 121 empty?
+ // 122 empty?
+ // 123 empty?
+ // 124 empty?
+ // 125 empty?
+ // 126 empty?
+ // 127 empty?
+ // 128 empty?
+ // 129 empty?
+ // 130 empty?
+ // 131 empty?
+ // 132 empty?
+ // 133 empty?
+ // 134 empty?
+ // 135 empty?
+ // 136 empty?
+ // 137 empty?
+ // 138 empty?
+ // 139 empty?
+ // 140 empty?
+ // 141 empty?
+ // 142 empty?
+ // 143 empty?
+ // 144 empty?
+ // 145 empty?
+ // 146 empty?
+ // 147 empty?
+ // 148 empty?
+ // 149 empty?
+ // 150 empty?
+ // 151 empty?
+ // 152 empty?
+ // 153 empty?
+ // 154 empty?
+ // 155 empty?
+ // 156 empty?
+ // 157 empty?
+ // 158 empty?
+ // 159 empty?
+ // 160 empty?
+ // 161 empty?
+ // 162 empty?
+ // 162 empty?
+ // 163 empty?
+ // 164 empty?
+ // 165 empty?
+ // 166 empty?
+ // 167 empty?
+ // 168 empty?
+ // 169 empty?
+ // 170 empty?
+ // 171 empty?
+ // 172 empty?
+ // 173 empty?
+ // 174 empty?
+ // 175 empty?
+ // 176 empty?
+ // 177 empty?
+ // 178 empty?
+ // 179 empty?
+ // 180 empty?
+ // 181 empty?
+ // 182 empty?
+ // 183 empty?
+ // 184 empty?
+ // 185 empty?
+ // 186 empty?
+ // 187 empty?
+ // 188 empty?
+ // 189 empty?
+ // 190 empty?
+ // 191 empty?
+ // 192 empty?
+ // 193 empty?
+ // 194 empty?
+ // 195 empty?
+ // 196 empty?
+ // 197 empty?
+ // 198 empty?
+ // 199 empty?
+ // 200 empty?
+ // 201 empty?
+ // 202 empty?
+ // 203 empty?
+ // 204 empty?
+ // 205 empty?
+ // 206 empty?
+ // 207 empty?
+ // 208 empty?
+ // 209 empty?
+ // 210 empty?
+ // 211 empty?
+ // 212 empty?
+ // 213 empty?
+ // 214 empty?
+ // 215 empty?
+ // 216 empty?
+ // 217 empty?
+ // 218 empty?
+ // 219 empty?
+ const float STAT_MOVEVARS_AIRACCEL_QW_STRETCHFACTOR = 220;
+ const float STAT_MOVEVARS_AIRCONTROL_PENALTY = 221;
+ const float STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW = 222;
+ const float STAT_MOVEVARS_AIRSTRAFEACCEL_QW = 223;
+ const float STAT_MOVEVARS_AIRCONTROL_POWER = 224;
+ const float STAT_MOVEFLAGS = 225;
+ const float STAT_MOVEVARS_WARSOWBUNNY_AIRFORWARDACCEL = 226;
+ const float STAT_MOVEVARS_WARSOWBUNNY_ACCEL = 227;
+ const float STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED = 228;
+ const float STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL = 229;
+ const float STAT_MOVEVARS_WARSOWBUNNY_BACKTOSIDERATIO = 230;
+ const float STAT_MOVEVARS_AIRSTOPACCELERATE = 231;
+ const float STAT_MOVEVARS_AIRSTRAFEACCELERATE = 232;
+ const float STAT_MOVEVARS_MAXAIRSTRAFESPEED = 233;
+ const float STAT_MOVEVARS_AIRCONTROL = 234;
+ const float STAT_FRAGLIMIT = 235;
+ const float STAT_TIMELIMIT = 236;
+ const float STAT_MOVEVARS_WALLFRICTION = 237;
+ const float STAT_MOVEVARS_FRICTION = 238;
+ const float STAT_MOVEVARS_WATERFRICTION = 239;
+ const float STAT_MOVEVARS_TICRATE = 240;
+ const float STAT_MOVEVARS_TIMESCALE = 241;
+ const float STAT_MOVEVARS_GRAVITY = 242;
+ const float STAT_MOVEVARS_STOPSPEED = 243;
+ const float STAT_MOVEVARS_MAXSPEED = 244;
+ const float STAT_MOVEVARS_SPECTATORMAXSPEED = 245;
+ const float STAT_MOVEVARS_ACCELERATE = 246;
+ const float STAT_MOVEVARS_AIRACCELERATE = 247;
+ const float STAT_MOVEVARS_WATERACCELERATE = 248;
+ const float STAT_MOVEVARS_ENTGRAVITY = 249;
+ const float STAT_MOVEVARS_JUMPVELOCITY = 250;
+ const float STAT_MOVEVARS_EDGEFRICTION = 251;
+ const float STAT_MOVEVARS_MAXAIRSPEED = 252;
+ const float STAT_MOVEVARS_STEPHEIGHT = 253;
+ const float STAT_MOVEVARS_AIRACCEL_QW = 254;
+ const float STAT_MOVEVARS_AIRACCEL_SIDEWAYS_FRICTION = 255;
float autocvar_captureleadlimit_override;
#define autocvar_capturelimit_override cvar("capturelimit_override")
#define autocvar_developer cvar("developer")
- float autocvar_developer_fteqccbugs;
float autocvar_ekg;
#define autocvar_fraglimit cvar("fraglimit")
#define autocvar_fraglimit_override cvar("fraglimit_override")
- float autocvar_g_allow_oldnexbeam;
+ float autocvar_g_allow_oldvortexbeam;
float autocvar_g_antilag;
float autocvar_g_antilag_nudge;
float autocvar_g_balance_armor_blockpercent;
float autocvar_g_balance_armor_rotlinear;
float autocvar_g_balance_armor_rotstable;
float autocvar_g_balance_armor_start;
- float autocvar_g_balance_rifle_bursttime;
- float autocvar_g_balance_rifle_primary_ammo;
- float autocvar_g_balance_rifle_primary_animtime;
- float autocvar_g_balance_rifle_primary_bullethail;
- float autocvar_g_balance_rifle_primary_burstcost;
- float autocvar_g_balance_rifle_primary_damage;
- float autocvar_g_balance_rifle_primary_force;
- float autocvar_g_balance_rifle_primary_refire;
- float autocvar_g_balance_rifle_primary_shots;
- float autocvar_g_balance_rifle_primary_solidpenetration;
- float autocvar_g_balance_rifle_primary_spread;
- float autocvar_g_balance_rifle_primary_tracer;
- float autocvar_g_balance_rifle_secondary;
- float autocvar_g_balance_rifle_secondary_ammo;
- float autocvar_g_balance_rifle_secondary_animtime;
- float autocvar_g_balance_rifle_secondary_bullethail;
- float autocvar_g_balance_rifle_secondary_burstcost;
- float autocvar_g_balance_rifle_secondary_damage;
- float autocvar_g_balance_rifle_secondary_force;
- float autocvar_g_balance_rifle_secondary_reload;
- float autocvar_g_balance_rifle_secondary_refire;
- float autocvar_g_balance_rifle_secondary_shots;
- float autocvar_g_balance_rifle_secondary_solidpenetration;
- float autocvar_g_balance_rifle_secondary_spread;
- float autocvar_g_balance_rifle_secondary_tracer;
- float autocvar_g_balance_rifle_reload_ammo;
- float autocvar_g_balance_rifle_reload_time;
float autocvar_g_balance_cloaked_alpha;
float autocvar_g_balance_contents_damagerate;
float autocvar_g_balance_contents_drowndelay;
float autocvar_g_balance_contents_playerdamage_lava;
float autocvar_g_balance_contents_playerdamage_slime;
float autocvar_g_balance_contents_projectiledamage;
- float autocvar_g_balance_crylink_primary_ammo;
- float autocvar_g_balance_crylink_primary_animtime;
- float autocvar_g_balance_crylink_primary_bouncedamagefactor;
- float autocvar_g_balance_crylink_primary_bounces;
- float autocvar_g_balance_crylink_primary_damage;
- float autocvar_g_balance_crylink_primary_edgedamage;
- float autocvar_g_balance_crylink_primary_force;
- float autocvar_g_balance_crylink_primary_joindelay;
- float autocvar_g_balance_crylink_primary_joinexplode;
- float autocvar_g_balance_crylink_primary_joinexplode_damage;
- float autocvar_g_balance_crylink_primary_joinexplode_edgedamage;
- float autocvar_g_balance_crylink_primary_joinexplode_force;
- float autocvar_g_balance_crylink_primary_joinexplode_radius;
- float autocvar_g_balance_crylink_primary_joinspread;
- float autocvar_g_balance_crylink_primary_linkexplode;
- float autocvar_g_balance_crylink_primary_middle_fadetime;
- float autocvar_g_balance_crylink_primary_middle_lifetime;
- float autocvar_g_balance_crylink_primary_other_fadetime;
- float autocvar_g_balance_crylink_primary_other_lifetime;
- float autocvar_g_balance_crylink_primary_radius;
- float autocvar_g_balance_crylink_primary_refire;
- float autocvar_g_balance_crylink_primary_shots;
- float autocvar_g_balance_crylink_primary_speed;
- float autocvar_g_balance_crylink_primary_spread;
- float autocvar_g_balance_crylink_secondary;
- float autocvar_g_balance_crylink_secondary_ammo;
- float autocvar_g_balance_crylink_secondary_animtime;
- float autocvar_g_balance_crylink_secondary_bouncedamagefactor;
- float autocvar_g_balance_crylink_secondary_bounces;
- float autocvar_g_balance_crylink_secondary_damage;
- float autocvar_g_balance_crylink_secondary_edgedamage;
- float autocvar_g_balance_crylink_secondary_force;
- float autocvar_g_balance_crylink_secondary_joindelay;
- float autocvar_g_balance_crylink_secondary_joinexplode;
- float autocvar_g_balance_crylink_secondary_joinexplode_damage;
- float autocvar_g_balance_crylink_secondary_joinexplode_edgedamage;
- float autocvar_g_balance_crylink_secondary_joinexplode_force;
- float autocvar_g_balance_crylink_secondary_joinexplode_radius;
- float autocvar_g_balance_crylink_secondary_joinspread;
- float autocvar_g_balance_crylink_secondary_line_fadetime;
- float autocvar_g_balance_crylink_secondary_line_lifetime;
- float autocvar_g_balance_crylink_secondary_linkexplode;
- float autocvar_g_balance_crylink_secondary_middle_fadetime;
- float autocvar_g_balance_crylink_secondary_middle_lifetime;
- float autocvar_g_balance_crylink_secondary_radius;
- float autocvar_g_balance_crylink_secondary_refire;
- float autocvar_g_balance_crylink_secondary_shots;
- float autocvar_g_balance_crylink_secondary_speed;
- float autocvar_g_balance_crylink_secondary_spread;
- float autocvar_g_balance_crylink_secondary_spreadtype;
- float autocvar_g_balance_crylink_reload_ammo;
- float autocvar_g_balance_crylink_reload_time;
float autocvar_g_balance_damagepush_speedfactor;
- float autocvar_g_balance_electro_combo_comboradius;
- float autocvar_g_balance_electro_combo_damage;
- float autocvar_g_balance_electro_combo_edgedamage;
- float autocvar_g_balance_electro_combo_force;
- float autocvar_g_balance_electro_combo_radius;
- float autocvar_g_balance_electro_combo_speed;
- float autocvar_g_balance_electro_combo_safeammocheck;
- float autocvar_g_balance_electro_lightning;
- float autocvar_g_balance_electro_primary_ammo;
- float autocvar_g_balance_electro_primary_animtime;
- float autocvar_g_balance_electro_primary_comboradius;
- float autocvar_g_balance_electro_primary_damage;
- float autocvar_g_balance_electro_primary_edgedamage;
- float autocvar_g_balance_electro_primary_falloff_halflifedist;
- float autocvar_g_balance_electro_primary_falloff_maxdist;
- float autocvar_g_balance_electro_primary_falloff_mindist;
- float autocvar_g_balance_electro_primary_force;
- float autocvar_g_balance_electro_primary_force_up;
- float autocvar_g_balance_electro_primary_lifetime;
- float autocvar_g_balance_electro_primary_radius;
- float autocvar_g_balance_electro_primary_range;
- float autocvar_g_balance_electro_primary_refire;
- float autocvar_g_balance_electro_primary_speed;
- float autocvar_g_balance_electro_secondary_ammo;
- float autocvar_g_balance_electro_secondary_animtime;
- float autocvar_g_balance_electro_secondary_bouncefactor;
- float autocvar_g_balance_electro_secondary_bouncestop;
- float autocvar_g_balance_electro_secondary_count;
- float autocvar_g_balance_electro_secondary_damage;
- float autocvar_g_balance_electro_secondary_damageforcescale;
- float autocvar_g_balance_electro_secondary_damagedbycontents;
- float autocvar_g_balance_electro_secondary_edgedamage;
- float autocvar_g_balance_electro_secondary_force;
- float autocvar_g_balance_electro_secondary_health;
- float autocvar_g_balance_electro_secondary_lifetime;
- float autocvar_g_balance_electro_secondary_radius;
- float autocvar_g_balance_electro_secondary_refire;
- float autocvar_g_balance_electro_secondary_refire2;
- float autocvar_g_balance_electro_secondary_speed;
- float autocvar_g_balance_electro_reload_ammo;
- float autocvar_g_balance_electro_reload_time;
float autocvar_g_balance_falldamage_deadminspeed;
float autocvar_g_balance_falldamage_factor;
float autocvar_g_balance_falldamage_maxdamage;
float autocvar_g_balance_falldamage_minspeed;
- float autocvar_g_balance_fireball_primary_animtime;
- float autocvar_g_balance_fireball_primary_bfgdamage;
- float autocvar_g_balance_fireball_primary_bfgforce;
- float autocvar_g_balance_fireball_primary_bfgradius;
- float autocvar_g_balance_fireball_primary_damage;
- float autocvar_g_balance_fireball_primary_damageforcescale;
- float autocvar_g_balance_fireball_primary_edgedamage;
- float autocvar_g_balance_fireball_primary_force;
- float autocvar_g_balance_fireball_primary_health;
- float autocvar_g_balance_fireball_primary_laserburntime;
- float autocvar_g_balance_fireball_primary_laserdamage;
- float autocvar_g_balance_fireball_primary_laseredgedamage;
- float autocvar_g_balance_fireball_primary_laserradius;
- float autocvar_g_balance_fireball_primary_lifetime;
- float autocvar_g_balance_fireball_primary_radius;
- float autocvar_g_balance_fireball_primary_refire;
- float autocvar_g_balance_fireball_primary_refire2;
- float autocvar_g_balance_fireball_primary_speed;
- float autocvar_g_balance_fireball_secondary_animtime;
- float autocvar_g_balance_fireball_secondary_damage;
- float autocvar_g_balance_fireball_secondary_damageforcescale;
- float autocvar_g_balance_fireball_secondary_damagetime;
- float autocvar_g_balance_fireball_secondary_laserburntime;
- float autocvar_g_balance_fireball_secondary_laserdamage;
- float autocvar_g_balance_fireball_secondary_laseredgedamage;
- float autocvar_g_balance_fireball_secondary_laserradius;
- float autocvar_g_balance_fireball_secondary_lifetime;
- float autocvar_g_balance_fireball_secondary_refire;
- float autocvar_g_balance_fireball_secondary_speed;
- float autocvar_g_balance_fireball_secondary_speed_up;
float autocvar_g_balance_firetransfer_damage;
float autocvar_g_balance_firetransfer_time;
float autocvar_g_balance_fuel_limit;
float autocvar_g_balance_grapplehook_stretch;
float autocvar_g_balance_grapplehook_damagedbycontents;
float autocvar_g_balance_grapplehook_refire;
- float autocvar_g_balance_grenadelauncher_bouncefactor;
- float autocvar_g_balance_grenadelauncher_bouncestop;
- float autocvar_g_balance_grenadelauncher_primary_ammo;
- float autocvar_g_balance_grenadelauncher_primary_animtime;
- float autocvar_g_balance_grenadelauncher_primary_damage;
- float autocvar_g_balance_grenadelauncher_primary_damageforcescale;
- float autocvar_g_balance_grenadelauncher_primary_edgedamage;
- float autocvar_g_balance_grenadelauncher_primary_force;
- float autocvar_g_balance_grenadelauncher_primary_health;
- float autocvar_g_balance_grenadelauncher_primary_lifetime;
- float autocvar_g_balance_grenadelauncher_primary_lifetime_stick;
- float autocvar_g_balance_grenadelauncher_primary_radius;
- float autocvar_g_balance_grenadelauncher_primary_refire;
- float autocvar_g_balance_grenadelauncher_primary_remote_minbouncecnt;
- float autocvar_g_balance_grenadelauncher_primary_speed;
- float autocvar_g_balance_grenadelauncher_primary_speed_up;
- float autocvar_g_balance_grenadelauncher_primary_type;
- float autocvar_g_balance_grenadelauncher_secondary_ammo;
- float autocvar_g_balance_grenadelauncher_secondary_animtime;
- float autocvar_g_balance_grenadelauncher_secondary_damage;
- float autocvar_g_balance_grenadelauncher_secondary_damageforcescale;
- float autocvar_g_balance_grenadelauncher_secondary_edgedamage;
- float autocvar_g_balance_grenadelauncher_secondary_force;
- float autocvar_g_balance_grenadelauncher_secondary_health;
- float autocvar_g_balance_grenadelauncher_secondary_lifetime;
- float autocvar_g_balance_grenadelauncher_secondary_lifetime_bounce;
- float autocvar_g_balance_grenadelauncher_secondary_lifetime_stick;
- float autocvar_g_balance_grenadelauncher_secondary_radius;
- float autocvar_g_balance_grenadelauncher_secondary_refire;
- float autocvar_g_balance_grenadelauncher_secondary_speed;
- float autocvar_g_balance_grenadelauncher_secondary_speed_up;
- float autocvar_g_balance_grenadelauncher_secondary_type;
- float autocvar_g_balance_grenadelauncher_reload_ammo;
- float autocvar_g_balance_grenadelauncher_reload_time;
- float autocvar_g_balance_hagar_primary_ammo;
- float autocvar_g_balance_hagar_primary_damage;
- float autocvar_g_balance_hagar_primary_edgedamage;
- float autocvar_g_balance_hagar_primary_force;
- float autocvar_g_balance_hagar_primary_health;
- float autocvar_g_balance_hagar_primary_damageforcescale;
- float autocvar_g_balance_hagar_primary_lifetime;
- float autocvar_g_balance_hagar_primary_radius;
- float autocvar_g_balance_hagar_primary_refire;
- float autocvar_g_balance_hagar_primary_speed;
- float autocvar_g_balance_hagar_secondary;
- float autocvar_g_balance_hagar_secondary_load;
- float autocvar_g_balance_hagar_secondary_load_speed;
- float autocvar_g_balance_hagar_secondary_load_spread;
- float autocvar_g_balance_hagar_secondary_load_spread_bias;
- float autocvar_g_balance_hagar_secondary_load_max;
- float autocvar_g_balance_hagar_secondary_load_hold;
- float autocvar_g_balance_hagar_secondary_load_releasedeath;
- float autocvar_g_balance_hagar_secondary_load_abort;
- float autocvar_g_balance_hagar_secondary_load_linkexplode;
- float autocvar_g_balance_hagar_secondary_load_animtime;
- float autocvar_g_balance_hagar_secondary_ammo;
- float autocvar_g_balance_hagar_secondary_damage;
- float autocvar_g_balance_hagar_secondary_edgedamage;
- float autocvar_g_balance_hagar_secondary_force;
- float autocvar_g_balance_hagar_secondary_health;
- float autocvar_g_balance_hagar_secondary_damageforcescale;
- float autocvar_g_balance_hagar_secondary_lifetime_min;
- float autocvar_g_balance_hagar_secondary_lifetime_rand;
- float autocvar_g_balance_hagar_secondary_radius;
- float autocvar_g_balance_hagar_secondary_refire;
- float autocvar_g_balance_hagar_secondary_speed;
- float autocvar_g_balance_hagar_secondary_spread;
- float autocvar_g_balance_hagar_reload_ammo;
- float autocvar_g_balance_hagar_reload_time;
float autocvar_g_balance_health_limit;
float autocvar_g_balance_health_regen;
float autocvar_g_balance_health_regenlinear;
float autocvar_g_balance_health_rot;
float autocvar_g_balance_health_rotlinear;
float autocvar_g_balance_health_rotstable;
- float autocvar_g_balance_hlac_primary_ammo;
- float autocvar_g_balance_hlac_primary_animtime;
- float autocvar_g_balance_hlac_primary_damage;
- float autocvar_g_balance_hlac_primary_edgedamage;
- float autocvar_g_balance_hlac_primary_force;
- float autocvar_g_balance_hlac_primary_lifetime;
- float autocvar_g_balance_hlac_primary_radius;
- float autocvar_g_balance_hlac_primary_refire;
- float autocvar_g_balance_hlac_primary_speed;
- float autocvar_g_balance_hlac_primary_spread_add;
- float autocvar_g_balance_hlac_primary_spread_crouchmod;
- float autocvar_g_balance_hlac_primary_spread_max;
- float autocvar_g_balance_hlac_primary_spread_min;
- float autocvar_g_balance_hlac_secondary;
- float autocvar_g_balance_hlac_secondary_ammo;
- float autocvar_g_balance_hlac_secondary_animtime;
- float autocvar_g_balance_hlac_secondary_damage;
- float autocvar_g_balance_hlac_secondary_edgedamage;
- float autocvar_g_balance_hlac_secondary_force;
- float autocvar_g_balance_hlac_secondary_lifetime;
- float autocvar_g_balance_hlac_secondary_radius;
- float autocvar_g_balance_hlac_secondary_refire;
- float autocvar_g_balance_hlac_secondary_shots;
- float autocvar_g_balance_hlac_secondary_speed;
- float autocvar_g_balance_hlac_secondary_spread;
- float autocvar_g_balance_hlac_secondary_spread_crouchmod;
- float autocvar_g_balance_hlac_reload_ammo;
- float autocvar_g_balance_hlac_reload_time;
- float autocvar_g_balance_hook_primary_animtime;
- float autocvar_g_balance_hook_primary_fuel;
- float autocvar_g_balance_hook_primary_hooked_fuel;
- float autocvar_g_balance_hook_primary_hooked_time_free;
- float autocvar_g_balance_hook_primary_hooked_time_max;
- float autocvar_g_balance_hook_primary_refire;
- float autocvar_g_balance_hook_secondary_ammo;
- float autocvar_g_balance_hook_secondary_animtime;
- float autocvar_g_balance_hook_secondary_damage;
- float autocvar_g_balance_hook_secondary_duration;
- float autocvar_g_balance_hook_secondary_edgedamage;
- float autocvar_g_balance_hook_secondary_force;
- float autocvar_g_balance_hook_secondary_gravity;
- float autocvar_g_balance_hook_secondary_lifetime;
- float autocvar_g_balance_hook_secondary_power;
- float autocvar_g_balance_hook_secondary_radius;
- float autocvar_g_balance_hook_secondary_refire;
- float autocvar_g_balance_hook_secondary_speed;
- float autocvar_g_balance_hook_secondary_health;
- float autocvar_g_balance_hook_secondary_damageforcescale;
float autocvar_g_balance_keyhunt_damageforcescale;
float autocvar_g_balance_keyhunt_delay_collect;
float autocvar_g_balance_keyhunt_delay_return;
float autocvar_g_balance_keyhunt_throwvelocity;
float autocvar_g_balance_kill_delay;
float autocvar_g_balance_kill_antispam;
- float autocvar_g_balance_laser_primary_animtime;
- float autocvar_g_balance_laser_primary_damage;
- float autocvar_g_balance_laser_primary_delay;
- float autocvar_g_balance_laser_primary_edgedamage;
- float autocvar_g_balance_laser_primary_force;
- float autocvar_g_balance_laser_primary_force_other_scale;
- float autocvar_g_balance_laser_primary_force_velocitybias;
- float autocvar_g_balance_laser_primary_force_zscale;
- float autocvar_g_balance_laser_primary_lifetime;
- float autocvar_g_balance_laser_primary_radius;
- float autocvar_g_balance_laser_primary_refire;
- float autocvar_g_balance_laser_primary_shotangle;
- float autocvar_g_balance_laser_primary_speed;
- float autocvar_g_balance_laser_secondary;
- float autocvar_g_balance_laser_secondary_animtime;
- float autocvar_g_balance_laser_secondary_damage;
- float autocvar_g_balance_laser_secondary_edgedamage;
- float autocvar_g_balance_laser_secondary_force;
- float autocvar_g_balance_laser_secondary_force_other_scale;
- float autocvar_g_balance_laser_secondary_force_velocitybias;
- float autocvar_g_balance_laser_secondary_force_zscale;
- float autocvar_g_balance_laser_secondary_lifetime;
- float autocvar_g_balance_laser_secondary_radius;
- float autocvar_g_balance_laser_secondary_speed;
- float autocvar_g_balance_laser_reload_ammo;
- float autocvar_g_balance_laser_reload_time;
- float autocvar_g_balance_minelayer_ammo;
- float autocvar_g_balance_minelayer_animtime;
- float autocvar_g_balance_minelayer_damage;
- float autocvar_g_balance_minelayer_damageforcescale;
- float autocvar_g_balance_minelayer_detonatedelay;
- float autocvar_g_balance_minelayer_edgedamage;
- float autocvar_g_balance_minelayer_force;
- float autocvar_g_balance_minelayer_health;
- float autocvar_g_balance_minelayer_lifetime;
- float autocvar_g_balance_minelayer_lifetime_countdown;
- float autocvar_g_balance_minelayer_limit;
- float autocvar_g_balance_minelayer_protection;
- float autocvar_g_balance_minelayer_proximityradius;
- float autocvar_g_balance_minelayer_radius;
- float autocvar_g_balance_minelayer_refire;
- float autocvar_g_balance_minelayer_remote_damage;
- float autocvar_g_balance_minelayer_remote_edgedamage;
- float autocvar_g_balance_minelayer_remote_force;
- float autocvar_g_balance_minelayer_remote_radius;
- float autocvar_g_balance_minelayer_speed;
- float autocvar_g_balance_minelayer_time;
- float autocvar_g_balance_minelayer_reload_ammo;
- float autocvar_g_balance_minelayer_reload_time;
- float autocvar_g_balance_minstanex_ammo;
- float autocvar_g_balance_minstanex_laser_ammo;
- float autocvar_g_balance_minstanex_laser_animtime;
- float autocvar_g_balance_minstanex_laser_refire;
- float autocvar_g_balance_minstanex_animtime;
- float autocvar_g_balance_minstanex_refire;
- float autocvar_g_balance_minstanex_reload_ammo;
- float autocvar_g_balance_minstanex_reload_time;
- float autocvar_g_balance_nex_charge;
- float autocvar_g_balance_nex_charge_animlimit;
- float autocvar_g_balance_nex_charge_limit;
- float autocvar_g_balance_nex_charge_maxspeed;
- float autocvar_g_balance_nex_charge_mindmg;
- float autocvar_g_balance_nex_charge_minspeed;
- float autocvar_g_balance_nex_charge_rate;
- float autocvar_g_balance_nex_charge_rot_pause;
- float autocvar_g_balance_nex_charge_rot_rate;
- float autocvar_g_balance_nex_charge_shot_multiplier;
- float autocvar_g_balance_nex_charge_start;
- float autocvar_g_balance_nex_charge_velocity_rate;
- float autocvar_g_balance_nex_primary_ammo;
- float autocvar_g_balance_nex_primary_animtime;
- float autocvar_g_balance_nex_primary_damage;
- float autocvar_g_balance_nex_primary_damagefalloff_forcehalflife;
- float autocvar_g_balance_nex_primary_damagefalloff_halflife;
- float autocvar_g_balance_nex_primary_damagefalloff_maxdist;
- float autocvar_g_balance_nex_primary_damagefalloff_mindist;
- float autocvar_g_balance_nex_primary_force;
- float autocvar_g_balance_nex_primary_refire;
- float autocvar_g_balance_nex_secondary;
- float autocvar_g_balance_nex_secondary_ammo;
- float autocvar_g_balance_nex_secondary_animtime;
- float autocvar_g_balance_nex_secondary_charge;
- float autocvar_g_balance_nex_secondary_charge_rate;
- float autocvar_g_balance_nex_secondary_chargepool;
- float autocvar_g_balance_nex_secondary_chargepool_pause_health_regen;
- float autocvar_g_balance_nex_secondary_chargepool_pause_regen;
- float autocvar_g_balance_nex_secondary_chargepool_regen;
- float autocvar_g_balance_nex_secondary_damage;
- float autocvar_g_balance_nex_secondary_damagefalloff_forcehalflife;
- float autocvar_g_balance_nex_secondary_damagefalloff_halflife;
- float autocvar_g_balance_nex_secondary_damagefalloff_maxdist;
- float autocvar_g_balance_nex_secondary_damagefalloff_mindist;
- float autocvar_g_balance_nex_secondary_force;
- float autocvar_g_balance_nex_secondary_refire;
- float autocvar_g_balance_nex_reload_ammo;
- float autocvar_g_balance_nex_reload_time;
float autocvar_g_balance_nexball_primary_animtime;
float autocvar_g_balance_nexball_primary_refire;
float autocvar_g_balance_nexball_primary_speed;
float autocvar_g_balance_nexball_secondary_refire;
float autocvar_g_balance_nexball_secondary_speed;
float autocvar_g_balance_nix_ammo_cells;
+ float autocvar_g_balance_nix_ammo_plasma;
float autocvar_g_balance_nix_ammo_fuel;
float autocvar_g_balance_nix_ammo_nails;
float autocvar_g_balance_nix_ammo_rockets;
float autocvar_g_balance_nix_ammo_shells;
float autocvar_g_balance_nix_ammoincr_cells;
+ float autocvar_g_balance_nix_ammoincr_plasma;
float autocvar_g_balance_nix_ammoincr_fuel;
float autocvar_g_balance_nix_ammoincr_nails;
float autocvar_g_balance_nix_ammoincr_rockets;
float autocvar_g_balance_pause_health_rot_spawn;
float autocvar_g_balance_portal_health;
float autocvar_g_balance_portal_lifetime;
- float autocvar_g_balance_porto_primary_animtime;
- float autocvar_g_balance_porto_primary_lifetime;
- float autocvar_g_balance_porto_primary_refire;
- float autocvar_g_balance_porto_primary_speed;
- float autocvar_g_balance_porto_secondary;
- float autocvar_g_balance_porto_secondary_animtime;
- float autocvar_g_balance_porto_secondary_lifetime;
- float autocvar_g_balance_porto_secondary_refire;
- float autocvar_g_balance_porto_secondary_speed;
float autocvar_g_balance_powerup_invincible_takedamage;
float autocvar_g_balance_powerup_invincible_time;
float autocvar_g_balance_powerup_strength_damage;
float autocvar_g_balance_powerup_strength_selfforce;
float autocvar_g_balance_powerup_strength_time;
float autocvar_g_balance_superweapons_time;
- float autocvar_g_balance_rocketlauncher_ammo;
- float autocvar_g_balance_rocketlauncher_animtime;
- float autocvar_g_balance_rocketlauncher_damage;
- float autocvar_g_balance_rocketlauncher_damageforcescale;
- float autocvar_g_balance_rocketlauncher_detonatedelay;
- float autocvar_g_balance_rocketlauncher_edgedamage;
- float autocvar_g_balance_rocketlauncher_force;
- float autocvar_g_balance_rocketlauncher_guidedelay;
- float autocvar_g_balance_rocketlauncher_guidegoal;
- float autocvar_g_balance_rocketlauncher_guiderate;
- float autocvar_g_balance_rocketlauncher_guideratedelay;
- float autocvar_g_balance_rocketlauncher_guidestop;
- float autocvar_g_balance_rocketlauncher_health;
- float autocvar_g_balance_rocketlauncher_lifetime;
- float autocvar_g_balance_rocketlauncher_radius;
- float autocvar_g_balance_rocketlauncher_refire;
- float autocvar_g_balance_rocketlauncher_remote_damage;
- float autocvar_g_balance_rocketlauncher_remote_edgedamage;
- float autocvar_g_balance_rocketlauncher_remote_force;
- float autocvar_g_balance_rocketlauncher_remote_radius;
- float autocvar_g_balance_rocketlauncher_speed;
- float autocvar_g_balance_rocketlauncher_speedaccel;
- float autocvar_g_balance_rocketlauncher_speedstart;
- float autocvar_g_balance_rocketlauncher_reload_ammo;
- float autocvar_g_balance_rocketlauncher_reload_time;
- float autocvar_g_balance_seeker_type;
- float autocvar_g_balance_seeker_flac_ammo;
- float autocvar_g_balance_seeker_flac_animtime;
- float autocvar_g_balance_seeker_flac_damage;
- float autocvar_g_balance_seeker_flac_edgedamage;
- float autocvar_g_balance_seeker_flac_force;
- float autocvar_g_balance_seeker_flac_lifetime;
- float autocvar_g_balance_seeker_flac_lifetime_rand;
- float autocvar_g_balance_seeker_flac_radius;
- float autocvar_g_balance_seeker_flac_refire;
- float autocvar_g_balance_seeker_missile_accel;
- float autocvar_g_balance_seeker_missile_ammo;
- float autocvar_g_balance_seeker_missile_animtime;
- float autocvar_g_balance_seeker_missile_count;
- float autocvar_g_balance_seeker_missile_damage;
- float autocvar_g_balance_seeker_missile_damageforcescale;
- float autocvar_g_balance_seeker_missile_decel;
- float autocvar_g_balance_seeker_missile_delay;
- float autocvar_g_balance_seeker_missile_edgedamage;
- float autocvar_g_balance_seeker_missile_force;
- float autocvar_g_balance_seeker_missile_health;
- float autocvar_g_balance_seeker_missile_lifetime;
- float autocvar_g_balance_seeker_missile_proxy;
- float autocvar_g_balance_seeker_missile_proxy_delay;
- float autocvar_g_balance_seeker_missile_proxy_maxrange;
- float autocvar_g_balance_seeker_missile_radius;
- float autocvar_g_balance_seeker_missile_refire;
- float autocvar_g_balance_seeker_missile_smart;
- float autocvar_g_balance_seeker_missile_smart_mindist;
- float autocvar_g_balance_seeker_missile_smart_trace_max;
- float autocvar_g_balance_seeker_missile_smart_trace_min;
- float autocvar_g_balance_seeker_missile_speed_max;
- float autocvar_g_balance_seeker_missile_turnrate;
- float autocvar_g_balance_seeker_tag_ammo;
- float autocvar_g_balance_seeker_tag_animtime;
- float autocvar_g_balance_seeker_tag_damageforcescale;
- float autocvar_g_balance_seeker_tag_health;
- float autocvar_g_balance_seeker_tag_lifetime;
- float autocvar_g_balance_seeker_tag_refire;
- float autocvar_g_balance_seeker_tag_speed;
- float autocvar_g_balance_seeker_tag_tracker_lifetime;
- float autocvar_g_balance_seeker_reload_ammo;
- float autocvar_g_balance_seeker_reload_time;
float autocvar_g_balance_selfdamagepercent;
- float autocvar_g_balance_shotgun_primary_ammo;
- float autocvar_g_balance_shotgun_primary_animtime;
- float autocvar_g_balance_shotgun_primary_bullets;
- float autocvar_g_balance_shotgun_primary_damage;
- float autocvar_g_balance_shotgun_primary_force;
- float autocvar_g_balance_shotgun_primary_refire;
- float autocvar_g_balance_shotgun_primary_solidpenetration;
- float autocvar_g_balance_shotgun_primary_spread;
- float autocvar_g_balance_shotgun_secondary;
- float autocvar_g_balance_shotgun_secondary_animtime;
- float autocvar_g_balance_shotgun_secondary_damage;
- float autocvar_g_balance_shotgun_secondary_force;
- float autocvar_g_balance_shotgun_secondary_melee_delay;
- float autocvar_g_balance_shotgun_secondary_melee_range;
- float autocvar_g_balance_shotgun_secondary_melee_swing_side;
- float autocvar_g_balance_shotgun_secondary_melee_swing_up;
- float autocvar_g_balance_shotgun_secondary_melee_time;
- float autocvar_g_balance_shotgun_secondary_melee_traces;
- float autocvar_g_balance_shotgun_secondary_melee_no_doubleslap;
- float autocvar_g_balance_shotgun_secondary_melee_nonplayerdamage;
- float autocvar_g_balance_shotgun_secondary_melee_multihit;
- float autocvar_g_balance_shotgun_secondary_refire;
- float autocvar_g_balance_shotgun_reload_ammo;
- float autocvar_g_balance_shotgun_reload_time;
float autocvar_g_balance_teams;
float autocvar_g_balance_teams_prevent_imbalance;
float autocvar_g_balance_teams_scorefactor;
- float autocvar_g_balance_tuba_animtime;
- float autocvar_g_balance_tuba_attenuation;
- float autocvar_g_balance_tuba_damage;
- float autocvar_g_balance_tuba_edgedamage;
- float autocvar_g_balance_tuba_force;
- float autocvar_g_balance_tuba_radius;
- float autocvar_g_balance_tuba_refire;
- float autocvar_g_balance_uzi_burst;
- float autocvar_g_balance_uzi_burst_ammo;
- float autocvar_g_balance_uzi_burst_animtime;
- float autocvar_g_balance_uzi_burst_refire;
- float autocvar_g_balance_uzi_burst_refire2;
- float autocvar_g_balance_uzi_burst_spread;
- float autocvar_g_balance_uzi_first;
- float autocvar_g_balance_uzi_first_ammo;
- float autocvar_g_balance_uzi_first_damage;
- float autocvar_g_balance_uzi_first_force;
- float autocvar_g_balance_uzi_first_refire;
- float autocvar_g_balance_uzi_first_spread;
- float autocvar_g_balance_uzi_mode;
- float autocvar_g_balance_uzi_solidpenetration;
- float autocvar_g_balance_uzi_spread_add;
- float autocvar_g_balance_uzi_spread_max;
- float autocvar_g_balance_uzi_spread_min;
- float autocvar_g_balance_uzi_sustained_ammo;
- float autocvar_g_balance_uzi_sustained_damage;
- float autocvar_g_balance_uzi_sustained_force;
- float autocvar_g_balance_uzi_sustained_refire;
- float autocvar_g_balance_uzi_sustained_spread;
- float autocvar_g_balance_uzi_reload_ammo;
- float autocvar_g_balance_uzi_reload_time;
float autocvar_g_ballistics_density_corpse;
float autocvar_g_ballistics_density_player;
float autocvar_g_ballistics_mindistance;
float autocvar_g_domination_point_amt;
float autocvar_g_domination_point_fullbright;
float autocvar_g_domination_point_leadlimit;
+ float autocvar_g_domination_roundbased;
+ float autocvar_g_domination_roundbased_point_limit;
+ float autocvar_g_domination_round_timelimit;
+ float autocvar_g_domination_warmup;
#define autocvar_g_domination_point_limit cvar("g_domination_point_limit")
float autocvar_g_domination_point_rate;
float autocvar_g_domination_teams_override;
string autocvar_g_forced_team_pink;
string autocvar_g_forced_team_red;
string autocvar_g_forced_team_yellow;
+ float autocvar_g_freezetag_frozen_damage_trigger;
float autocvar_g_freezetag_frozen_force;
float autocvar_g_freezetag_frozen_maxtime;
float autocvar_g_freezetag_revive_falldamage;
float autocvar_g_freezetag_revive_falldamage_health;
+ float autocvar_g_freezetag_revive_nade;
+ float autocvar_g_freezetag_revive_nade_health;
float autocvar_g_freezetag_point_leadlimit;
float autocvar_g_freezetag_point_limit;
float autocvar_g_freezetag_revive_extra_size;
float autocvar_g_maxpushtime;
float autocvar_g_maxspeed;
float autocvar_g_midair_shieldtime;
- #define autocvar_g_minstagib cvar("g_minstagib")
- float autocvar_g_minstagib_ammo_drop;
- float autocvar_g_minstagib_extralives;
- float autocvar_g_minstagib_speed_highspeed;
- float autocvar_g_minstagib_invis_alpha;
+ #define autocvar_g_instagib cvar("g_instagib")
+ float autocvar_g_instagib_ammo_drop;
+ float autocvar_g_instagib_extralives;
+ float autocvar_g_instagib_speed_highspeed;
+ float autocvar_g_instagib_invis_alpha;
#define autocvar_g_mirrordamage cvar("g_mirrordamage")
#define autocvar_g_mirrordamage_virtual cvar("g_mirrordamage_virtual")
float autocvar_g_nick_flood_penalty_yellow;
//float autocvar_g_nick_flood_timeout;
float autocvar_g_nix_with_healtharmor;
- float autocvar_g_nix_with_laser;
+ float autocvar_g_nix_with_blaster;
float autocvar_g_nix_with_powerups;
float autocvar_g_nodepthtestitems;
float autocvar_g_nodepthtestplayers;
float autocvar_g_norecoil;
-float autocvar_g_onslaught_cp_buildhealth;
-float autocvar_g_onslaught_cp_buildtime;
-float autocvar_g_onslaught_cp_health;
-float autocvar_g_onslaught_cp_regen;
-float autocvar_g_onslaught_gen_health;
float autocvar_g_pickup_cells_max;
+ float autocvar_g_pickup_plasma_max;
float autocvar_g_pickup_fuel_max;
float autocvar_g_pickup_items;
float autocvar_g_pickup_nails_max;
float autocvar_g_player_alpha;
float autocvar_g_player_brightness;
float autocvar_g_playerclip_collisions;
- string autocvar_g_playerstats_uri;
float autocvar_g_powerups;
float autocvar_g_projectiles_damage;
float autocvar_g_projectiles_keep_owner;
float autocvar_g_spawn_useallspawns;
float autocvar_g_spawnpoints_auto_move_out_of_solid;
#define autocvar_g_spawnshieldtime cvar("g_spawnshieldtime")
- #define autocvar_g_start_weapon_laser cvar("g_start_weapon_laser")
float autocvar_g_tdm_team_spawns;
+ float autocvar_g_tdm_point_limit;
+ float autocvar_g_tdm_point_leadlimit;
float autocvar_g_tdm_teams;
float autocvar_g_tdm_teams_override;
float autocvar_g_teamdamage_resetspeed;
float autocvar_sv_dodging_wall_distance_threshold;
float autocvar_sv_dodging_wall_dodging;
float autocvar_sv_dodging_frozen;
+ float autocvar_sv_dodging_frozen_doubletap;
float autocvar_sv_doublejump;
float autocvar_sv_eventlog;
float autocvar_sv_eventlog_console;
float autocvar_sv_maxspeed;
string autocvar_sv_motd;
float autocvar_sv_precacheplayermodels;
- float autocvar_sv_precacheweapons;
+ //float autocvar_sv_precacheweapons; // WEAPONTODO?
float autocvar_sv_q3acompat_machineshotgunswap;
float autocvar_sv_ready_restart;
float autocvar_sv_ready_restart_after_countdown;
float autocvar_sv_vote_call;
float autocvar_sv_vote_change;
string autocvar_sv_vote_commands;
+ float autocvar_sv_vote_gametype;
+ float autocvar_sv_vote_gametype_timeout;
+ string autocvar_sv_vote_gametype_options;
+ float autocvar_sv_vote_gametype_keeptwotime;
+ float autocvar_sv_vote_gametype_default_current;
float autocvar_sv_vote_limit;
float autocvar_sv_vote_majority_factor;
float autocvar_sv_vote_majority_factor_of_voted;
float autocvar_g_random_gravity_delay;
float autocvar_g_nades;
float autocvar_g_nades_spawn;
+ float autocvar_g_nades_spawn_count;
+ float autocvar_g_nades_client_select;
float autocvar_g_nades_nade_lifetime;
float autocvar_g_nades_nade_minforce;
float autocvar_g_nades_nade_maxforce;
float autocvar_g_nades_nade_radius;
float autocvar_g_nades_nade_force;
float autocvar_g_nades_nade_newton_style;
+ float autocvar_g_nades_napalm_ball_count;
+ float autocvar_g_nades_napalm_ball_spread;
+ float autocvar_g_nades_napalm_ball_damage;
+ float autocvar_g_nades_napalm_ball_damageforcescale;
+ float autocvar_g_nades_napalm_ball_lifetime;
+ float autocvar_g_nades_napalm_ball_radius;
+ float autocvar_g_nades_napalm_blast;
+ float autocvar_g_nades_napalm_fountain_lifetime;
+ float autocvar_g_nades_napalm_fountain_delay;
+ float autocvar_g_nades_napalm_fountain_radius;
+ float autocvar_g_nades_napalm_fountain_damage;
+ float autocvar_g_nades_napalm_fountain_edgedamage;
+ float autocvar_g_nades_napalm_burntime;
+ float autocvar_g_nades_napalm_selfdamage;
+ float autocvar_g_nades_nade_type;
+ float autocvar_g_nades_bonus_type;
+ float autocvar_g_nades_bonus;
+ float autocvar_g_nades_bonus_onstrength;
+ float autocvar_g_nades_bonus_client_select;
+ float autocvar_g_nades_bonus_max;
+ float autocvar_g_nades_bonus_score_max;
+ float autocvar_g_nades_bonus_score_time;
+ float autocvar_g_nades_bonus_score_time_flagcarrier;
+ float autocvar_g_nades_bonus_score_minor;
+ float autocvar_g_nades_bonus_score_low;
+ float autocvar_g_nades_bonus_score_high;
+ float autocvar_g_nades_bonus_score_medium;
+ float autocvar_g_nades_bonus_score_spree;
+ float autocvar_g_nades_ice_freeze_time;
+ float autocvar_g_nades_ice_health;
+ float autocvar_g_nades_ice_explode;
+ float autocvar_g_nades_ice_teamcheck;
+ float autocvar_g_nades_heal_time;
+ float autocvar_g_nades_heal_rate;
+ float autocvar_g_nades_heal_friend;
+ float autocvar_g_nades_heal_foe;
+ string autocvar_g_nades_pokenade_monster_type;
+ float autocvar_g_nades_pokenade_monster_lifetime;
float autocvar_g_campcheck_damage;
float autocvar_g_campcheck_distance;
float autocvar_g_campcheck_interval;
float autocvar_g_jump_grunt;
+ float autocvar_g_overkill_powerups_replace;
+ float autocvar_g_overkill_superguns_respawn_time;
+ float autocvar_g_overkill_100h_anyway;
+ float autocvar_g_overkill_100a_anyway;
+ float autocvar_g_overkill_ammo_charge;
+ float autocvar_g_overkill_ammo_charge_notice;
+ float autocvar_g_overkill_ammo_charge_limit;
float autocvar_g_spawn_near_teammate_distance;
float autocvar_g_spawn_near_teammate_ignore_spawnpoint;
float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death;
float autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health;
float autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath;
-
+float autocvar_g_onslaught_debug;
+float autocvar_g_onslaught_teleport_wait;
+float autocvar_g_onslaught_spawn_at_controlpoints;
+var float autocvar_g_onslaught_spawn_at_controlpoints_chance = 0.5;
+float autocvar_g_onslaught_spawn_at_controlpoints_random;
+float autocvar_g_onslaught_spawn_at_generator;
+float autocvar_g_onslaught_spawn_at_generator_chance;
+float autocvar_g_onslaught_spawn_at_generator_random;
+float autocvar_g_onslaught_cp_proxydecap;
+var float autocvar_g_onslaught_cp_proxydecap_distance = 512;
+var float autocvar_g_onslaught_cp_proxydecap_dps = 100;
+float autocvar_g_onslaught_cp_buildhealth;
+float autocvar_g_onslaught_cp_buildtime;
+float autocvar_g_onslaught_cp_health;
+float autocvar_g_onslaught_cp_regen;
+float autocvar_g_onslaught_gen_health;
+var float autocvar_g_onslaught_shield_force = 100;
+float autocvar_g_onslaught_allow_vehicle_touch;
+float autocvar_g_onslaught_round_timelimit;
+float autocvar_g_onslaught_point_limit;
+float autocvar_g_onslaught_warmup;
+float autocvar_g_onslaught_teleport_radius;
+float autocvar_g_onslaught_spawn_choose;
+float autocvar_g_onslaught_click_radius;
+ float autocvar_g_buffs_waypoint_distance;
+ float autocvar_g_buffs_randomize;
+ float autocvar_g_buffs_random_lifetime;
+ float autocvar_g_buffs_random_location;
+ float autocvar_g_buffs_random_location_attempts;
+ float autocvar_g_buffs_spawn_count;
+ float autocvar_g_buffs_replace_powerups;
+ float autocvar_g_buffs_cooldown_activate;
+ float autocvar_g_buffs_cooldown_respawn;
+ float autocvar_g_buffs_resistance_blockpercent;
+ float autocvar_g_buffs_medic_survive_chance;
+ float autocvar_g_buffs_medic_survive_health;
+ float autocvar_g_buffs_medic_rot;
+ float autocvar_g_buffs_medic_max;
+ float autocvar_g_buffs_medic_regen;
+ float autocvar_g_buffs_vengeance_damage_multiplier;
+ float autocvar_g_buffs_bash_force;
+ float autocvar_g_buffs_bash_force_self;
+ float autocvar_g_buffs_disability_time;
+ float autocvar_g_buffs_disability_speed;
+ float autocvar_g_buffs_disability_rate;
+ float autocvar_g_buffs_speed_speed;
+ float autocvar_g_buffs_speed_rate;
+ float autocvar_g_buffs_speed_damage_take;
+ float autocvar_g_buffs_speed_regen;
+ float autocvar_g_buffs_vampire_damage_steal;
+ float autocvar_g_buffs_invisible_alpha;
+ float autocvar_g_buffs_flight_gravity;
+ float autocvar_g_buffs_jump_height;
#include "havocbot.qh"
-#include "role_onslaught.qc"
#include "role_keyhunt.qc"
#include "roles.qc"
if(self.weapons)
{
- weapon_action(self.weapon, WR_AIM);
+ WEP_ACTION(self.weapon, WR_AIM);
if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(self))
{
self.BUTTON_ATCK = FALSE;
for(i = WEP_FIRST; i <= WEP_LAST; ++i)
{
e = get_weaponinfo(i);
- if ((self.weapons & WepSet_FromWeapon(i)) && (e.spawnflags & WEP_FLAG_RELOADABLE) && (self.weapon_load[i] < cvar(strcat("g_balance_", e.netname, "_reload_ammo"))))
+ if ((self.weapons & WepSet_FromWeapon(i)) && (e.spawnflags & WEP_FLAG_RELOADABLE) && (self.weapon_load[i] < e.reloading_ammo))
self.switchweapon = i;
}
}
return;
}
- else if(self.health>autocvar_g_balance_rocketlauncher_damage*0.5)
+ else if(self.health>WEP_CVAR(devastator, damage)*0.5)
{
if(self.velocity_z < 0)
- if(client_hasweapon(self, WEP_ROCKET_LAUNCHER, TRUE, FALSE))
+ if(client_hasweapon(self, WEP_DEVASTATOR, TRUE, FALSE))
{
self.movement_x = maxspeed;
return;
}
- self.switchweapon = WEP_ROCKET_LAUNCHER;
+ self.switchweapon = WEP_DEVASTATOR;
self.v_angle_x = 90;
self.BUTTON_ATCK = TRUE;
- self.rocketjumptime = time + autocvar_g_balance_rocketlauncher_detonatedelay;
+ self.rocketjumptime = time + WEP_CVAR(devastator, detonatedelay);
return;
}
}
for(i = WEP_FIRST; i <= WEP_LAST; ++i)
{
// if we are out of ammo for all other weapons, it's an emergency to switch to anything else
- if (weapon_action(i, WR_CHECKAMMO1) + weapon_action(i, WR_CHECKAMMO2))
+ if (WEP_ACTION(i, WR_CHECKAMMO1) + WEP_ACTION(i, WR_CHECKAMMO2))
other_weapon_available = TRUE;
}
if(other_weapon_available)
{
// If no weapon was chosen get the first available weapon
if(self.weapon==0)
- for(i=WEP_LASER + 1; i < WEP_COUNT ; ++i)
+ for(i = WEP_FIRST; i <= WEP_LAST; ++i) if(i != WEP_BLASTER)
{
if(client_hasweapon(self, i, TRUE, FALSE))
{
if (head.ammo_rockets && player.ammo_rockets > self.ammo_rockets)
continue;
- if (head.ammo_cells && player.ammo_cells > self.ammo_cells )
+ if (head.ammo_cells && player.ammo_cells > self.ammo_cells)
+ continue;
+
+ if (head.ammo_plasma && player.ammo_plasma > self.ammo_plasma)
continue;
discard = FALSE;
}
}
- //Race:
- //go to next checkpoint, and annoy enemies
- .float race_checkpoint;
- void havocbot_role_race()
- {
- if(self.deadflag != DEAD_NO)
- return;
-
- entity e;
- if (self.bot_strategytime < time)
- {
- self.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
- navigation_goalrating_start();
- /*
- havocbot_goalrating_items(100, self.origin, 10000);
- havocbot_goalrating_enemyplayers(500, self.origin, 20000);
- */
-
- for(e = world; (e = find(e, classname, "trigger_race_checkpoint")) != world; )
- {
- if(e.cnt == self.race_checkpoint)
- {
- navigation_routerating(e, 1000000, 5000);
- }
- else if(self.race_checkpoint == -1)
- {
- navigation_routerating(e, 1000000, 5000);
- }
- }
-
- navigation_goalrating_end();
- }
- }
-
void havocbot_chooserole_dm()
{
self.havocbot_role = havocbot_role_dm;
}
- void havocbot_chooserole_race()
- {
- self.havocbot_role = havocbot_role_race;
- }
-
void havocbot_chooserole()
{
dprint("choosing a role...\n");
return;
else if (g_keyhunt)
havocbot_chooserole_kh();
- else if (g_race || g_cts)
- havocbot_chooserole_race();
- else if (g_onslaught)
- havocbot_chooserole_ons();
else // assume anything else is deathmatch
havocbot_chooserole_dm();
}
// regular frag
PlayerScore_Add(attacker, SP_KILLS, 1);
if(targ.playerid)
- PlayerStats_Event(attacker, sprintf("kills-%d", targ.playerid), 1);
+ PS_GR_P_ADDVAL(attacker, sprintf("kills-%d", targ.playerid), 1);
}
PlayerScore_Add(targ, SP_DEATHS, 1);
else if(!(attacker.weapons & WepSet_FromWeapon(culprit)))
culprit = attacker.weapon;
- if(g_weaponarena_random_with_laser && culprit == WEP_LASER)
+ if(g_weaponarena_random_with_blaster && culprit == WEP_BLASTER) // WEAPONTODO: Shouldn't this be in a mutator?
{
// no exchange
}
if(death_weapon)
{
w_deathtype = deathtype;
- float death_message = weapon_action(death_weapon, ((murder) ? WR_KILLMESSAGE : WR_SUICIDEMESSAGE));
+ float death_message = WEP_ACTION(death_weapon, ((murder) ? WR_KILLMESSAGE : WR_SUICIDEMESSAGE));
w_deathtype = FALSE;
if(death_message)
case counta: \
{ \
Send_Notification(NOTIF_ONE, attacker, MSG_ANNCE, ANNCE_KILLSTREAK_##countb); \
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_##counta, 1); \
+ PS_GR_P_ADDVAL(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_##counta, 1); \
break; \
}
switch(attacker.killcount)
{
checkrules_firstblood = TRUE;
notif_firstblood = TRUE; // modify the current messages so that they too show firstblood information
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD, 1);
- PlayerStats_Event(targ, PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM, 1);
+ PS_GR_P_ADDVAL(attacker, PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD, 1);
+ PS_GR_P_ADDVAL(targ, PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM, 1);
// tell spree_inf and spree_cen that this is a first-blood and first-victim event
kill_count_to_attacker = -1;
if(PlayerScore_Add(targ, SP_SCORE, 0) == -5)
{
Send_Notification(NOTIF_ONE, targ, MSG_ANNCE, ANNCE_ACHIEVEMENT_BOTLIKE);
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_BOTLIKE, 1);
+ PS_GR_P_ADDVAL(attacker, PLAYERSTATS_ACHIEVEMENT_BOTLIKE, 1);
}
}
if(targ.killcount) { targ.killcount = 0; }
}
+ void Ice_Think()
+ {
+ if(!self.owner.frozen || self.owner.iceblock != self)
+ {
+ remove(self);
+ return;
+ }
+ setorigin(self, self.owner.origin - '0 0 16');
+ self.nextthink = time;
+ }
+
+ void Freeze (entity targ, float freeze_time, float frozen_type, float show_waypoint)
+ {
+ if(!IS_PLAYER(targ) && !(targ.flags & FL_MONSTER)) // only specified entities can be freezed
+ return;
+
+ if(targ.frozen)
+ return;
+
+ float targ_maxhealth = ((targ.flags & FL_MONSTER) ? targ.max_health : start_health);
+
+ targ.frozen = frozen_type;
+ targ.revive_progress = ((frozen_type == 3) ? 1 : 0);
+ targ.health = ((frozen_type == 3) ? targ_maxhealth : 1);
+ targ.revive_speed = freeze_time;
+
+ entity ice, head;
+ ice = spawn();
+ ice.owner = targ;
+ ice.classname = "ice";
+ ice.scale = targ.scale;
+ ice.think = Ice_Think;
+ ice.nextthink = time;
+ ice.frame = floor(random() * 21); // ice model has 20 different looking frames
+ setmodel(ice, "models/ice/ice.md3");
+ ice.alpha = 1;
+ ice.colormod = Team_ColorRGB(targ.team);
+ ice.glowmod = ice.colormod;
+ targ.iceblock = ice;
+ targ.revival_time = 0;
+
+ entity oldself;
+ oldself = self;
+ self = ice;
+ Ice_Think();
+ self = oldself;
+
+ RemoveGrapplingHook(targ);
+
+ FOR_EACH_PLAYER(head)
+ if(head.hook.aiment == targ)
+ RemoveGrapplingHook(head);
+
+ // add waypoint
+ if(show_waypoint)
+ WaypointSprite_Spawn("frozen", 0, 0, targ, '0 0 64', world, targ.team, targ, waypointsprite_attached, TRUE, RADARICON_WAYPOINT, '0.25 0.90 1');
+ }
+
+ void Unfreeze (entity targ)
+ {
+ if(targ.frozen && targ.frozen != 3) // only reset health if target was frozen
+ targ.health = ((IS_PLAYER(targ)) ? start_health : targ.max_health);
+
+ entity head;
+ targ.frozen = 0;
+ targ.revive_progress = 0;
+ targ.revival_time = time;
+
+ WaypointSprite_Kill(targ.waypointsprite_attached);
+
+ FOR_EACH_PLAYER(head)
+ if(head.hook.aiment == targ)
+ RemoveGrapplingHook(head);
+
+ // remove the ice block
+ if(targ.iceblock)
+ remove(targ.iceblock);
+ targ.iceblock = world;
+ }
+
// these are updated by each Damage call for use in button triggering and such
entity damage_targ;
entity damage_inflictor;
attacker.dmg_take += v_x;
attacker.dmg_save += v_y;
attacker.dmg_inflictor = inflictor;
- mirrordamage = v_z; // = 0, to make fteqcc stfu
+ mirrordamage = v_z;
mirrorforce = 0;
}
mirrordamage = frag_mirrordamage;
force = frag_force;
- if (!g_minstagib)
+ if(targ.frozen)
+ if(deathtype != DEATH_HURTTRIGGER && deathtype != DEATH_TEAMCHANGE && deathtype != DEATH_AUTOTEAMCHANGE)
+ {
+ if(autocvar_g_freezetag_revive_falldamage > 0)
+ if(deathtype == DEATH_FALL)
+ if(damage >= autocvar_g_freezetag_revive_falldamage)
+ {
+ Unfreeze(targ);
+ targ.health = autocvar_g_freezetag_revive_falldamage_health;
+ pointparticles(particleeffectnum("iceorglass"), targ.origin, '0 0 0', 3);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_FREEZETAG_REVIVED_FALL, targ.netname);
+ Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_FREEZETAG_REVIVE_SELF);
+ }
+
+ damage = 0;
+ force *= autocvar_g_freezetag_frozen_force;
+ }
+
+ if(targ.frozen && deathtype == DEATH_HURTTRIGGER && !autocvar_g_freezetag_frozen_damage_trigger)
+ {
+ pointparticles(particleeffectnum("teleport"), targ.origin, '0 0 0', 1);
+
+ entity oldself = self;
+ self = targ;
+ entity spot = SelectSpawnPoint (FALSE);
+
+ if(spot)
+ {
+ damage = 0;
+ self.deadflag = DEAD_NO;
+
+ self.angles = spot.angles;
+
+ self.effects = 0;
+ self.effects |= EF_TELEPORT_BIT;
+
+ self.angles_z = 0; // never spawn tilted even if the spot says to
+ self.fixangle = TRUE; // turn this way immediately
+ self.velocity = '0 0 0';
+ self.avelocity = '0 0 0';
+ self.punchangle = '0 0 0';
+ self.punchvector = '0 0 0';
+ self.oldvelocity = self.velocity;
+
+ self.spawnorigin = spot.origin;
+ setorigin (self, spot.origin + '0 0 1' * (1 - self.mins_z - 24));
+ // don't reset back to last position, even if new position is stuck in solid
+ self.oldorigin = self.origin;
+ self.prevorigin = self.origin;
+
+ pointparticles(particleeffectnum("teleport"), self.origin, '0 0 0', 1);
+ }
+
+ self = oldself;
+ }
+
+ if(!g_instagib)
{
// apply strength multiplier
if (attacker.items & IT_STRENGTH)
}
if (targ == attacker)
- {
- if(g_cts && !autocvar_g_cts_selfdamage)
- damage = 0;
- else
- damage = damage * autocvar_g_balance_selfdamagepercent; // Partial damage if the attacker hits himself
- }
+ damage = damage * autocvar_g_balance_selfdamagepercent; // Partial damage if the attacker hits himself
// count the damage
if(attacker)
if(!targ.deadflag)
+ if(deathtype != DEATH_BUFF_VENGEANCE)
if(targ.takedamage == DAMAGE_AIM)
if(targ != attacker)
{
else
victim = targ;
- if(IS_PLAYER(victim) || victim.turrcaps_flags & TFL_TURRCAPS_ISTURRET || victim.flags & FL_MONSTER || victim.classname == "func_assault_destructible" || (victim.classname == "onslaught_generator" && !victim.isshielded) || (victim.classname == "onslaught_controlpoint_icon" && !victim.owner.isshielded))
- if(IS_PLAYER(victim) || (victim.turrcaps_flags & TFL_TURRCAPS_ISTURRET) || (victim.flags & FL_MONSTER))
++ if(IS_PLAYER(victim) || (victim.turrcaps_flags & TFL_TURRCAPS_ISTURRET) || (victim.flags & FL_MONSTER) || victim.classname == "func_assault_destructible" || (victim.classname == "onslaught_generator" && !victim.isshielded) || (victim.classname == "onslaught_controlpoint_icon" && !victim.owner.isshielded))
{
- if(DIFF_TEAM(victim, attacker))
+ if(DIFF_TEAM(victim, attacker) && !victim.frozen)
{
if(damage > 0)
{
if(victim.BUTTON_CHAT)
attacker.typehitsound += 1;
else
- attacker.hitsound += 1;
+ attacker.damage_dealt += damage;
}
damage_goodhits += 1;
// apply push
if (self.damageforcescale)
if (vlen(force))
- if (!IS_PLAYER(self) || time >= self.spawnshieldtime)
+ if (!IS_PLAYER(self) || time >= self.spawnshieldtime || self == attacker)
{
vector farce = damage_explosion_calcpush(self.damageforcescale * force, self.velocity, autocvar_g_balance_damagepush_speedfactor);
if(self.movetype == MOVETYPE_PHYSICS)
}
float RadiusDamage_running;
- float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity ignore, float forceintensity, float deathtype, entity directhitentity)
+ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float inflictorselfdamage, float forceintensity, float deathtype, entity directhitentity)
// Returns total damage applies to creatures
{
entity targ;
- vector blastorigin;
vector force;
float total_damage_to_creatures;
entity next;
tfloordmg = autocvar_g_throughfloor_damage;
tfloorforce = autocvar_g_throughfloor_force;
- blastorigin = (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5);
total_damage_to_creatures = 0;
if(deathtype != (WEP_HOOK | HITTYPE_SECONDARY | HITTYPE_BOUNCE)) // only send gravity bomb damage once
if(DEATH_WEAPONOF(deathtype) != WEP_TUBA) // do not send tuba damage (bandwidth hog)
{
- force = inflictor.velocity;
+ force = inflictorvelocity;
if(vlen(force) == 0)
force = '0 0 -1';
else
force = normalize(force);
if(forceintensity >= 0)
- Damage_DamageInfo(blastorigin, coredamage, edgedamage, rad, forceintensity * force, deathtype, 0, attacker);
+ Damage_DamageInfo(inflictororigin, coredamage, edgedamage, rad, forceintensity * force, deathtype, 0, attacker);
else
- Damage_DamageInfo(blastorigin, coredamage, edgedamage, -rad, (-forceintensity) * force, deathtype, 0, attacker);
+ Damage_DamageInfo(inflictororigin, coredamage, edgedamage, -rad, (-forceintensity) * force, deathtype, 0, attacker);
}
stat_damagedone = 0;
- targ = WarpZone_FindRadius (blastorigin, rad + MAX_DAMAGEEXTRARADIUS, FALSE);
+ targ = WarpZone_FindRadius (inflictororigin, rad + MAX_DAMAGEEXTRARADIUS, FALSE);
while (targ)
{
next = targ.chain;
- if (targ != inflictor)
- if (ignore != targ) if(targ.takedamage)
+ if ((targ != inflictor) || inflictorselfdamage)
+ if (((cantbe != targ) && !mustbe) || (mustbe == targ))
+ if (targ.takedamage)
+ {
+ vector nearest;
+ vector diff;
+ float power;
+
+ // LordHavoc: measure distance to nearest point on target (not origin)
+ // (this guarentees 100% damage on a touch impact)
+ nearest = targ.WarpZone_findradius_nearest;
+ diff = targ.WarpZone_findradius_dist;
+ // round up a little on the damage to ensure full damage on impacts
+ // and turn the distance into a fraction of the radius
+ power = 1 - ((vlen (diff) - bound(MIN_DAMAGEEXTRARADIUS, targ.damageextraradius, MAX_DAMAGEEXTRARADIUS)) / rad);
+ //bprint(" ");
+ //bprint(ftos(power));
+ //if (targ == attacker)
+ // print(ftos(power), "\n");
+ if (power > 0)
{
- vector nearest;
- vector diff;
- float power;
-
- // LordHavoc: measure distance to nearest point on target (not origin)
- // (this guarentees 100% damage on a touch impact)
- nearest = targ.WarpZone_findradius_nearest;
- diff = targ.WarpZone_findradius_dist;
- // round up a little on the damage to ensure full damage on impacts
- // and turn the distance into a fraction of the radius
- power = 1 - ((vlen (diff) - bound(MIN_DAMAGEEXTRARADIUS, targ.damageextraradius, MAX_DAMAGEEXTRARADIUS)) / rad);
- //bprint(" ");
- //bprint(ftos(power));
- //if (targ == attacker)
- // print(ftos(power), "\n");
- if (power > 0)
+ float finaldmg;
+ if (power > 1)
+ power = 1;
+ finaldmg = coredamage * power + edgedamage * (1 - power);
+ if (finaldmg > 0)
{
- float finaldmg;
- if (power > 1)
- power = 1;
- finaldmg = coredamage * power + edgedamage * (1 - power);
- if (finaldmg > 0)
- {
- float a;
- float c;
- vector hitloc;
- vector myblastorigin;
- vector center;
+ float a;
+ float c;
+ vector hitloc;
+ vector myblastorigin;
+ vector center;
- myblastorigin = WarpZone_TransformOrigin(targ, blastorigin);
+ myblastorigin = WarpZone_TransformOrigin(targ, inflictororigin);
- // if it's a player, use the view origin as reference
- center = CENTER_OR_VIEWOFS(targ);
+ // if it's a player, use the view origin as reference
+ center = CENTER_OR_VIEWOFS(targ);
- force = normalize(center - myblastorigin);
- force = force * (finaldmg / coredamage) * forceintensity;
- hitloc = nearest;
+ force = normalize(center - myblastorigin);
+ force = force * (finaldmg / coredamage) * forceintensity;
+ hitloc = nearest;
- if(targ != directhitentity)
- {
- float hits;
- float total;
- float hitratio;
- float mininv_f, mininv_d;
+ if(deathtype & WEP_BLASTER)
+ force *= WEP_CVAR_BOTH(blaster, !(deathtype & HITTYPE_SECONDARY), force_zscale);
- // test line of sight to multiple positions on box,
- // and do damage if any of them hit
- hits = 0;
+ if(targ != directhitentity)
+ {
+ float hits;
+ float total;
+ float hitratio;
+ float mininv_f, mininv_d;
- // we know: max stddev of hitratio = 1 / (2 * sqrt(n))
- // so for a given max stddev:
- // n = (1 / (2 * max stddev of hitratio))^2
+ // test line of sight to multiple positions on box,
+ // and do damage if any of them hit
+ hits = 0;
- mininv_d = (finaldmg * (1-tfloordmg)) / autocvar_g_throughfloor_damage_max_stddev;
- mininv_f = (vlen(force) * (1-tfloorforce)) / autocvar_g_throughfloor_force_max_stddev;
+ // we know: max stddev of hitratio = 1 / (2 * sqrt(n))
+ // so for a given max stddev:
+ // n = (1 / (2 * max stddev of hitratio))^2
- if(autocvar_g_throughfloor_debug)
- printf("THROUGHFLOOR: D=%f F=%f max(dD)=1/%f max(dF)=1/%f", finaldmg, vlen(force), mininv_d, mininv_f);
+ mininv_d = (finaldmg * (1-tfloordmg)) / autocvar_g_throughfloor_damage_max_stddev;
+ mininv_f = (vlen(force) * (1-tfloorforce)) / autocvar_g_throughfloor_force_max_stddev;
- total = 0.25 * pow(max(mininv_f, mininv_d), 2);
+ if(autocvar_g_throughfloor_debug)
+ printf("THROUGHFLOOR: D=%f F=%f max(dD)=1/%f max(dF)=1/%f", finaldmg, vlen(force), mininv_d, mininv_f);
- if(autocvar_g_throughfloor_debug)
- printf(" steps=%f", total);
- if (IS_PLAYER(targ))
- total = ceil(bound(autocvar_g_throughfloor_min_steps_player, total, autocvar_g_throughfloor_max_steps_player));
- else
- total = ceil(bound(autocvar_g_throughfloor_min_steps_other, total, autocvar_g_throughfloor_max_steps_other));
+ total = 0.25 * pow(max(mininv_f, mininv_d), 2);
- if(autocvar_g_throughfloor_debug)
- printf(" steps=%f dD=%f dF=%f", total, finaldmg * (1-tfloordmg) / (2 * sqrt(total)), vlen(force) * (1-tfloorforce) / (2 * sqrt(total)));
+ if(autocvar_g_throughfloor_debug)
+ printf(" steps=%f", total);
- for(c = 0; c < total; ++c)
- {
- //traceline(targ.WarpZone_findradius_findorigin, nearest, MOVE_NOMONSTERS, inflictor);
- WarpZone_TraceLine(blastorigin, WarpZone_UnTransformOrigin(targ, nearest), MOVE_NOMONSTERS, inflictor);
- if (trace_fraction == 1 || trace_ent == targ)
- {
- ++hits;
- if (hits > 1)
- hitloc = hitloc + nearest;
- else
- hitloc = nearest;
- }
- nearest_x = targ.origin_x + targ.mins_x + random() * targ.size_x;
- nearest_y = targ.origin_y + targ.mins_y + random() * targ.size_y;
- nearest_z = targ.origin_z + targ.mins_z + random() * targ.size_z;
- }
- nearest = hitloc * (1 / max(1, hits));
- hitratio = (hits / total);
- a = bound(0, tfloordmg + (1-tfloordmg) * hitratio, 1);
- finaldmg = finaldmg * a;
- a = bound(0, tfloorforce + (1-tfloorforce) * hitratio, 1);
- force = force * a;
+ if (IS_PLAYER(targ))
+ total = ceil(bound(autocvar_g_throughfloor_min_steps_player, total, autocvar_g_throughfloor_max_steps_player));
+ else
+ total = ceil(bound(autocvar_g_throughfloor_min_steps_other, total, autocvar_g_throughfloor_max_steps_other));
- if(autocvar_g_throughfloor_debug)
- printf(" D=%f F=%f\n", finaldmg, vlen(force));
- }
+ if(autocvar_g_throughfloor_debug)
+ printf(" steps=%f dD=%f dF=%f", total, finaldmg * (1-tfloordmg) / (2 * sqrt(total)), vlen(force) * (1-tfloorforce) / (2 * sqrt(total)));
- // laser force adjustments :P
- if(DEATH_WEAPONOF(deathtype) == WEP_LASER)
+ for(c = 0; c < total; ++c)
{
- if (targ == attacker)
+ //traceline(targ.WarpZone_findradius_findorigin, nearest, MOVE_NOMONSTERS, inflictor);
+ WarpZone_TraceLine(inflictororigin, WarpZone_UnTransformOrigin(targ, nearest), MOVE_NOMONSTERS, inflictor);
+ if (trace_fraction == 1 || trace_ent == targ)
{
- vector vel;
-
- float force_zscale;
- float force_velocitybiasramp;
- float force_velocitybias;
-
- force_velocitybiasramp = autocvar_sv_maxspeed;
- if(deathtype & HITTYPE_SECONDARY)
- {
- force_zscale = autocvar_g_balance_laser_secondary_force_zscale;
- force_velocitybias = autocvar_g_balance_laser_secondary_force_velocitybias;
- }
+ ++hits;
+ if (hits > 1)
+ hitloc = hitloc + nearest;
else
- {
- force_zscale = autocvar_g_balance_laser_primary_force_zscale;
- force_velocitybias = autocvar_g_balance_laser_primary_force_velocitybias;
- }
-
- vel = targ.velocity;
- vel_z = 0;
- vel = normalize(vel) * bound(0, vlen(vel) / force_velocitybiasramp, 1) * force_velocitybias;
- force =
- vlen(force)
- *
- normalize(normalize(force) + vel);
-
- force_z *= force_zscale;
- }
- else
- {
- if(deathtype & HITTYPE_SECONDARY)
- {
- force *= autocvar_g_balance_laser_secondary_force_other_scale;
- }
- else
- {
- force *= autocvar_g_balance_laser_primary_force_other_scale;
- }
+ hitloc = nearest;
}
+ nearest_x = targ.origin_x + targ.mins_x + random() * targ.size_x;
+ nearest_y = targ.origin_y + targ.mins_y + random() * targ.size_y;
+ nearest_z = targ.origin_z + targ.mins_z + random() * targ.size_z;
}
- //if (targ == attacker)
- //{
- // print("hits ", ftos(hits), " / ", ftos(total));
- // print(" finaldmg ", ftos(finaldmg), " force ", vtos(force));
- // print(" (", ftos(a), ")\n");
- //}
- if(finaldmg || vlen(force))
- {
- if(targ.iscreature)
- {
- total_damage_to_creatures += finaldmg;
+ nearest = hitloc * (1 / max(1, hits));
+ hitratio = (hits / total);
+ a = bound(0, tfloordmg + (1-tfloordmg) * hitratio, 1);
+ finaldmg = finaldmg * a;
+ a = bound(0, tfloorforce + (1-tfloorforce) * hitratio, 1);
+ force = force * a;
- if(accuracy_isgooddamage(attacker, targ))
- stat_damagedone += finaldmg;
- }
+ if(autocvar_g_throughfloor_debug)
+ printf(" D=%f F=%f\n", finaldmg, vlen(force));
+ }
- if(targ == directhitentity || DEATH_ISSPECIAL(deathtype))
- Damage (targ, inflictor, attacker, finaldmg, deathtype, nearest, force);
- else
- Damage (targ, inflictor, attacker, finaldmg, deathtype | HITTYPE_SPLASH, nearest, force);
+ //if (targ == attacker)
+ //{
+ // print("hits ", ftos(hits), " / ", ftos(total));
+ // print(" finaldmg ", ftos(finaldmg), " force ", vtos(force));
+ // print(" (", ftos(a), ")\n");
+ //}
+ if(finaldmg || vlen(force))
+ {
+ if(targ.iscreature)
+ {
+ total_damage_to_creatures += finaldmg;
+
+ if(accuracy_isgooddamage(attacker, targ))
+ stat_damagedone += finaldmg;
}
+
+ if(targ == directhitentity || DEATH_ISSPECIAL(deathtype))
+ Damage (targ, inflictor, attacker, finaldmg, deathtype, nearest, force);
+ else
+ Damage (targ, inflictor, attacker, finaldmg, deathtype | HITTYPE_SPLASH, nearest, force);
}
}
}
+ }
targ = next;
}
return total_damage_to_creatures;
}
+ float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, float deathtype, entity directhitentity)
+ {
+ return RadiusDamageForSource (inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker, coredamage, edgedamage, rad, cantbe, mustbe, FALSE, forceintensity, deathtype, directhitentity);
+ }
+
.float fire_damagepersec;
.float fire_endtime;
.float fire_deathtype;
e.fire_endtime = 0;
// ice stops fire
- if(e.freezetag_frozen)
+ if(e.frozen)
e.fire_endtime = 0;
t = min(frametime, e.fire_endtime - time);
d = e.fire_damagepersec * t;
- hi = e.fire_owner.hitsound;
+ hi = e.fire_owner.damage_dealt;
ty = e.fire_owner.typehitsound;
Damage(e, e, e.fire_owner, d, e.fire_deathtype, e.origin, '0 0 0');
if(e.fire_hitsound && e.fire_owner)
{
- e.fire_owner.hitsound = hi;
+ e.fire_owner.damage_dealt = hi;
e.fire_owner.typehitsound = ty;
}
e.fire_hitsound = TRUE;
if (!IS_INDEPENDENT_PLAYER(e))
- if(!e.freezetag_frozen)
+ if(!e.frozen)
FOR_EACH_PLAYER(other) if(e != other)
{
if(IS_PLAYER(other))
WriteByte(MSG_BROADCAST, 0);
WriteByte(MSG_BROADCAST, 0);
}
- self.cnt = mod(self.cnt + 1, maxclients);
+ self.cnt = (self.cnt + 1) % maxclients;
}
void PingPLReport_Spawn()
{
string redirection_target;
float world_initialized;
- string GetMapname();
string GetGametype();
void GotoNextMap(float reinit);
void ShuffleMaplist();
}
}
- void fteqcc_testbugs()
- {
- float a, b;
-
- if(!autocvar_developer_fteqccbugs)
- return;
-
- dprint("*** fteqcc test: checking for bugs...\n");
-
- a = 1;
- b = 5;
- if(sqrt(a) - sqrt(b - a) == 0)
- dprint("*** fteqcc test: found same-function-twice bug\n");
- else
- dprint("*** fteqcc test: same-function-twice bug got FINALLY FIXED! HOORAY!\n");
-
- world.cnt = -10;
- world.enemy = world;
- world.enemy.cnt += 10;
- if(world.cnt > 0.2 || world.cnt < -0.2) // don't error out if it's just roundoff errors
- dprint("*** fteqcc test: found += bug\n");
- else
- dprint("*** fteqcc test: += bug got FINALLY FIXED! HOORAY!\n");
- world.cnt = 0;
- }
-
void GotoFirstMap()
{
float n;
// private
BADCVAR("developer");
BADCVAR("log_dest_udp");
- BADCVAR("log_file");
BADCVAR("net_address");
BADCVAR("net_address_ipv6");
BADCVAR("port");
BADPREFIX("g_playerstats_");
BADPREFIX("g_respawn_ghosts");
BADPREFIX("g_voice_flood_");
+ BADPREFIX("log_file");
BADPREFIX("rcon_");
BADPREFIX("sv_allowdownloads");
BADPREFIX("sv_autodemo");
BADPREFIX("sv_ready_restart_");
// mutators that announce themselves properly to the server browser
- BADCVAR("g_minstagib");
+ BADCVAR("g_instagib");
BADCVAR("g_new_toys");
BADCVAR("g_nix");
BADCVAR("g_grappling_hook");
CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
+ CALL_ACCUMULATED_FUNCTION(RegisterBuffs);
MapInfo_Enumerate();
MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
remove = remove_safely; // during spawning, watch what you remove!
- check_unacceptable_compiler_bugs();
-
cvar_changes_init(); // do this very early now so it REALLY matches the server config
compressShortVector_init();
CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
+ CALL_ACCUMULATED_FUNCTION(RegisterBuffs);
ServerProgsDB = db_load(strcat("server.db", autocvar_sessionid));
Map_MarkAsRecent(mapname);
- PlayerStats_Init(); // we need this to be initiated before InitGameplayMode
+ PlayerStats_GameReport_Init(); // we need this to be initiated before InitGameplayMode
precache_model ("null"); // we need this one before InitGameplayMode
InitGameplayMode();
readlevelcvars();
GrappleHookInit();
- ElectroInit();
- LaserInit();
player_count = 0;
bot_waypoints_for_items = autocvar_g_waypoints_for_items;
if(autocvar_g_campaign)
CampaignPostInit();
- fteqcc_testbugs();
-
Ban_LoadBans();
MapInfo_Enumerate();
addstat(STAT_SWITCHINGWEAPON, AS_INT, switchingweapon);
addstat(STAT_GAMESTARTTIME, AS_FLOAT, stat_game_starttime);
addstat(STAT_ROUNDSTARTTIME, AS_FLOAT, stat_round_starttime);
- addstat(STAT_ALLOW_OLDNEXBEAM, AS_INT, stat_allow_oldnexbeam);
+ addstat(STAT_ALLOW_OLDVORTEXBEAM, AS_INT, stat_allow_oldvortexbeam);
Nagger_Init();
addstat(STAT_STRENGTH_FINISHED, AS_FLOAT, strength_finished);
addstat(STAT_SUPERWEAPONS_FINISHED, AS_FLOAT, superweapons_finished);
addstat(STAT_PRESSED_KEYS, AS_FLOAT, pressedkeys);
addstat(STAT_FUEL, AS_INT, ammo_fuel);
+ addstat(STAT_PLASMA, AS_INT, ammo_plasma);
addstat(STAT_SHOTORG, AS_INT, stat_shotorg);
addstat(STAT_LEADLIMIT, AS_FLOAT, stat_leadlimit);
addstat(STAT_WEAPON_CLIPLOAD, AS_INT, clip_load);
addstat(STAT_WEAPON_CLIPSIZE, AS_INT, clip_size);
addstat(STAT_LAST_PICKUP, AS_FLOAT, last_pickup);
addstat(STAT_HIT_TIME, AS_FLOAT, hit_time);
+ addstat(STAT_DAMAGE_DEALT_TOTAL, AS_INT, damage_dealt_total);
addstat(STAT_TYPEHIT_TIME, AS_FLOAT, typehit_time);
addstat(STAT_LAYED_MINES, AS_INT, minelayer_mines);
- addstat(STAT_NEX_CHARGE, AS_FLOAT, nex_charge);
- addstat(STAT_NEX_CHARGEPOOL, AS_FLOAT, nex_chargepool_ammo);
+ addstat(STAT_VORTEX_CHARGE, AS_FLOAT, vortex_charge);
+ addstat(STAT_VORTEX_CHARGEPOOL, AS_FLOAT, vortex_chargepool_ammo);
addstat(STAT_HAGAR_LOAD, AS_INT, hagar_load);
+
+ addstat(STAT_ARC_HEAT, AS_FLOAT, arc_heat_percent);
+
+ // freeze attacks
+ addstat(STAT_FROZEN, AS_INT, frozen);
+ addstat(STAT_REVIVE_PROGRESS, AS_FLOAT, revive_progress);
// g_movementspeed hack
addstat(STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW, AS_FLOAT, stat_sv_airspeedlimit_nonqw);
return MapInfo_Type_ToString(MapInfo_LoadedGametype);
}
- string getmapname_stored;
string GetMapname()
{
return mapname;
for(i = 1; i < Map_Count; ++i)
{
float mapindex;
- mapindex = mod(i + Map_Current, Map_Count);
+ mapindex = (i + Map_Current) % Map_Count;
if(Map_Check(mapindex, pass))
return mapindex;
}
for(i = 0; i <= imax; ++i)
{
float mapindex;
- mapindex = mod(Map_Current + floor(random() * (Map_Count - 1) + 1), Map_Count); // any OTHER map
+ mapindex = (Map_Current + floor(random() * (Map_Count - 1) + 1)) % Map_Count; // any OTHER map
if(Map_Check(mapindex, 1))
return mapindex;
}
return TRUE;
}
if(autocvar_nextmap != "")
- if(MapInfo_CheckMap(autocvar_nextmap))
+ {
+ string m;
+ m = GameTypeVote_MapInfo_FixName(autocvar_nextmap);
+ cvar_set("nextmap",m);
+
+ if(!m || gametypevote)
+ return FALSE;
+ if(autocvar_sv_vote_gametype)
{
- Map_Goto_SetStr(autocvar_nextmap);
+ Map_Goto_SetStr(m);
+ return FALSE;
+ }
+
+ if(MapInfo_CheckMap(m))
+ {
+ Map_Goto_SetStr(m);
Map_Goto(reinit);
alreadychangedlevel = TRUE;
return TRUE;
}
+ }
if(!reinit && autocvar_lastlevel)
{
cvar_settemp_restore();
============
*/
.float autoscreenshot;
- void() MapVote_Start;
- void() MapVote_Think;
- float mapvote_initialized;
void IntermissionThink()
{
FixIntermissionClient(self);
DumpStats(TRUE);
// send statistics
- entity e;
- PlayerStats_EndMatch(1);
- FOR_EACH_CLIENT(e)
- PlayerStats_AddGlobalInfo(e);
- PlayerStats_Shutdown();
+ PlayerStats_GameReport(TRUE);
WeaponStats_Shutdown();
Kill_Notification(NOTIF_ALL, world, MSG_CENTER, 0); // kill all centerprints now
head.winning = 0;
}
-// Onslaught winning condition:
-// game terminates if only one team has a working generator (or none)
-float WinningCondition_Onslaught()
-{
- entity head;
- float t1, t2, t3, t4;
-
- WinningConditionHelper(); // set worldstatus
-
- if(warmup_stage)
- return WINNING_NO;
-
- // first check if the game has ended
- t1 = t2 = t3 = t4 = 0;
- head = find(world, classname, "onslaught_generator");
- while (head)
- {
- if (head.health > 0)
- {
- if (head.team == NUM_TEAM_1) t1 = 1;
- if (head.team == NUM_TEAM_2) t2 = 1;
- if (head.team == NUM_TEAM_3) t3 = 1;
- if (head.team == NUM_TEAM_4) t4 = 1;
- }
- head = find(head, classname, "onslaught_generator");
- }
- if (t1 + t2 + t3 + t4 < 2)
- {
- // game over, only one team remains (or none)
- ClearWinners();
- if (t1) SetWinners(team, NUM_TEAM_1);
- if (t2) SetWinners(team, NUM_TEAM_2);
- if (t3) SetWinners(team, NUM_TEAM_3);
- if (t4) SetWinners(team, NUM_TEAM_4);
- dprint("Have a winner, ending game.\n");
- return WINNING_YES;
- }
-
- // Two or more teams remain
- return WINNING_NO;
-}
-
// Assault winning condition: If the attackers triggered a round end (by fulfilling all objectives)
// they win. Otherwise the defending team wins once the timelimit passes.
void assault_new_round();
SetDefaultAlpha();
- /*
- MapVote_Think should now do that part
- if (intermission_running)
- if (time >= intermission_exittime + 60)
- {
- if(!DoNextMapOverride())
- GotoNextMap();
- return;
- }
- */
-
if (gameover) // someone else quit the game already
{
if(player_count == 0) // Nobody there? Then let's go to the next map
return;
}
- if(g_onslaught)
- timelimit = 0; // ONS has its own overtime rule
-
float wantovertime;
wantovertime = 0;
{
checkrules_status = WinningCondition_LMS();
}
- else if (g_onslaught)
- {
- checkrules_status = WinningCondition_Onslaught(); // TODO remove this?
- }
else
{
checkrules_status = WinningCondition_Scores(fraglimit, leadlimit);
}
}
- float mapvote_nextthink;
- float mapvote_initialized;
- float mapvote_keeptwotime;
- float mapvote_timeout;
- string mapvote_message;
- #define MAPVOTE_SCREENSHOT_DIRS_COUNT 4
- string mapvote_screenshot_dirs[MAPVOTE_SCREENSHOT_DIRS_COUNT];
- float mapvote_screenshot_dirs_count;
-
- float mapvote_count;
- float mapvote_count_real;
- string mapvote_maps[MAPVOTE_COUNT];
- float mapvote_maps_screenshot_dir[MAPVOTE_COUNT];
- string mapvote_maps_pakfile[MAPVOTE_COUNT];
- float mapvote_maps_suggested[MAPVOTE_COUNT];
- string mapvote_suggestions[MAPVOTE_COUNT];
- float mapvote_suggestion_ptr;
- float mapvote_voters;
- float mapvote_selections[MAPVOTE_COUNT];
- float mapvote_run;
- float mapvote_detail;
- float mapvote_abstain;
- .float mapvote;
-
- void MapVote_ClearAllVotes()
- {
- FOR_EACH_CLIENT(other)
- other.mapvote = 0;
- }
-
- string MapVote_Suggest(string m)
+ string GotoMap(string m)
{
- float i;
- if(m == "")
- return "That's not how to use this command.";
- if(!autocvar_g_maplist_votable_suggestions)
- return "Suggestions are not accepted on this server.";
- if(mapvote_initialized)
- return "Can't suggest - voting is already in progress!";
- m = MapInfo_FixName(m);
+ m = GameTypeVote_MapInfo_FixName(m);
if (!m)
return "The map you suggested is not available on this server.";
- if(!autocvar_g_maplist_votable_suggestions_override_mostrecent)
- if(Map_IsRecent(m))
- return "This server does not allow for recent maps to be played again. Please be patient for some rounds.";
-
+ if (!autocvar_sv_vote_gametype)
if(!MapInfo_CheckMap(m))
return "The map you suggested does not support the current game mode.";
- for(i = 0; i < mapvote_suggestion_ptr; ++i)
- if(mapvote_suggestions[i] == m)
- return "This map was already suggested.";
- if(mapvote_suggestion_ptr >= MAPVOTE_COUNT)
- {
- i = floor(random() * mapvote_suggestion_ptr);
- }
- else
- {
- i = mapvote_suggestion_ptr;
- mapvote_suggestion_ptr += 1;
- }
- if(mapvote_suggestions[i] != "")
- strunzone(mapvote_suggestions[i]);
- mapvote_suggestions[i] = strzone(m);
- if(autocvar_sv_eventlog)
- GameLogEcho(strcat(":vote:suggested:", m, ":", ftos(self.playerid)));
- return strcat("Suggestion of ", m, " accepted.");
- }
-
- void MapVote_AddVotable(string nextMap, float isSuggestion)
- {
- float j, i, o;
- string pakfile, mapfile;
-
- if(nextMap == "")
- return;
- for(j = 0; j < mapvote_count; ++j)
- if(mapvote_maps[j] == nextMap)
- return;
- // suggestions might be no longer valid/allowed after gametype switch!
- if(isSuggestion)
- if(!MapInfo_CheckMap(nextMap))
- return;
- mapvote_maps[mapvote_count] = strzone(nextMap);
- mapvote_maps_suggested[mapvote_count] = isSuggestion;
-
- pakfile = string_null;
- for(i = 0; i < mapvote_screenshot_dirs_count; ++i)
- {
- mapfile = strcat(mapvote_screenshot_dirs[i], "/", mapvote_maps[i]);
- pakfile = whichpack(strcat(mapfile, ".tga"));
- if(pakfile == "")
- pakfile = whichpack(strcat(mapfile, ".jpg"));
- if(pakfile == "")
- pakfile = whichpack(strcat(mapfile, ".png"));
- if(pakfile != "")
- break;
- }
- if(i >= mapvote_screenshot_dirs_count)
- i = 0; // FIXME maybe network this error case, as that means there is no mapshot on the server?
- for(o = strstr(pakfile, "/", 0)+1; o > 0; o = strstr(pakfile, "/", 0)+1)
- pakfile = substring(pakfile, o, -1);
-
- mapvote_maps_screenshot_dir[mapvote_count] = i;
- mapvote_maps_pakfile[mapvote_count] = strzone(pakfile);
-
- mapvote_count += 1;
- }
-
- void MapVote_Spawn();
- void MapVote_Init()
- {
- float i;
- float nmax, smax;
-
- MapVote_ClearAllVotes();
-
- mapvote_count = 0;
- mapvote_detail = !autocvar_g_maplist_votable_nodetail;
- mapvote_abstain = autocvar_g_maplist_votable_abstain;
-
- if(mapvote_abstain)
- nmax = min(MAPVOTE_COUNT - 1, autocvar_g_maplist_votable);
- else
- nmax = min(MAPVOTE_COUNT, autocvar_g_maplist_votable);
- smax = min3(nmax, autocvar_g_maplist_votable_suggestions, mapvote_suggestion_ptr);
-
- // we need this for AddVotable, as that cycles through the screenshot dirs
- mapvote_screenshot_dirs_count = tokenize_console(autocvar_g_maplist_votable_screenshot_dir);
- if(mapvote_screenshot_dirs_count == 0)
- mapvote_screenshot_dirs_count = tokenize_console("maps levelshots");
- mapvote_screenshot_dirs_count = min(mapvote_screenshot_dirs_count, MAPVOTE_SCREENSHOT_DIRS_COUNT);
- for(i = 0; i < mapvote_screenshot_dirs_count; ++i)
- mapvote_screenshot_dirs[i] = strzone(argv(i));
-
- if(mapvote_suggestion_ptr)
- for(i = 0; i < 100 && mapvote_count < smax; ++i)
- MapVote_AddVotable(mapvote_suggestions[floor(random() * mapvote_suggestion_ptr)], TRUE);
-
- for(i = 0; i < 100 && mapvote_count < nmax; ++i)
- MapVote_AddVotable(GetNextMap(), FALSE);
-
- if(mapvote_count == 0)
- {
- bprint( "Maplist contains no single playable map! Resetting it to default map list.\n" );
- cvar_set("g_maplist", MapInfo_ListAllAllowedMaps(MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags()));
- if(autocvar_g_maplist_shuffle)
- ShuffleMaplist();
- localcmd("\nmenu_cmd sync\n");
- for(i = 0; i < 100 && mapvote_count < nmax; ++i)
- MapVote_AddVotable(GetNextMap(), FALSE);
- }
-
- mapvote_count_real = mapvote_count;
- if(mapvote_abstain)
- MapVote_AddVotable("don't care", 0);
-
- //dprint("mapvote count is ", ftos(mapvote_count), "\n");
-
- mapvote_keeptwotime = time + autocvar_g_maplist_votable_keeptwotime;
- mapvote_timeout = time + autocvar_g_maplist_votable_timeout;
- if(mapvote_count_real < 3 || mapvote_keeptwotime <= time)
- mapvote_keeptwotime = 0;
- mapvote_message = "Choose a map and press its key!";
-
- MapVote_Spawn();
- }
-
- void MapVote_SendPicture(float id)
- {
- msg_entity = self;
- WriteByte(MSG_ONE, SVC_TEMPENTITY);
- WriteByte(MSG_ONE, TE_CSQC_PICTURE);
- WriteByte(MSG_ONE, id);
- WritePicture(MSG_ONE, strcat(mapvote_screenshot_dirs[mapvote_maps_screenshot_dir[id]], "/", mapvote_maps[id]), 3072);
- }
-
- float MapVote_GetMapMask()
- {
- float mask, i, power;
- mask = 0;
- for(i = 0, power = 1; i < mapvote_count; ++i, power *= 2)
- if(mapvote_maps[i] != "")
- mask |= power;
- return mask;
- }
-
- entity mapvote_ent;
- float MapVote_SendEntity(entity to, float sf)
- {
- float i;
-
- if(sf & 1)
- sf &= ~2; // if we send 1, we don't need to also send 2
-
- WriteByte(MSG_ENTITY, ENT_CLIENT_MAPVOTE);
- WriteByte(MSG_ENTITY, sf);
-
- if(sf & 1)
- {
- // flag 1 == initialization
- for(i = 0; i < mapvote_screenshot_dirs_count; ++i)
- WriteString(MSG_ENTITY, mapvote_screenshot_dirs[i]);
- WriteString(MSG_ENTITY, "");
- WriteByte(MSG_ENTITY, mapvote_count);
- WriteByte(MSG_ENTITY, mapvote_abstain);
- WriteByte(MSG_ENTITY, mapvote_detail);
- WriteCoord(MSG_ENTITY, mapvote_timeout);
- if(mapvote_count <= 8)
- WriteByte(MSG_ENTITY, MapVote_GetMapMask());
- else
- WriteShort(MSG_ENTITY, MapVote_GetMapMask());
- for(i = 0; i < mapvote_count; ++i)
- if(mapvote_maps[i] != "")
- {
- if(mapvote_abstain && i == mapvote_count - 1)
- {
- WriteString(MSG_ENTITY, ""); // abstain needs no text
- WriteString(MSG_ENTITY, ""); // abstain needs no pack
- WriteByte(MSG_ENTITY, 0); // abstain needs no screenshot dir
- }
- else
- {
- WriteString(MSG_ENTITY, mapvote_maps[i]);
- WriteString(MSG_ENTITY, mapvote_maps_pakfile[i]);
- WriteByte(MSG_ENTITY, mapvote_maps_screenshot_dir[i]);
- }
- }
- }
-
- if(sf & 2)
- {
- // flag 2 == update of mask
- if(mapvote_count <= 8)
- WriteByte(MSG_ENTITY, MapVote_GetMapMask());
- else
- WriteShort(MSG_ENTITY, MapVote_GetMapMask());
- }
-
- if(sf & 4)
- {
- if(mapvote_detail)
- for(i = 0; i < mapvote_count; ++i)
- if(mapvote_maps[i] != "")
- WriteByte(MSG_ENTITY, mapvote_selections[i]);
-
- WriteByte(MSG_ENTITY, to.mapvote);
- }
-
- return TRUE;
- }
-
- void MapVote_Spawn()
- {
- Net_LinkEntity(mapvote_ent = spawn(), FALSE, 0, MapVote_SendEntity);
- }
-
- void MapVote_TouchMask()
- {
- mapvote_ent.SendFlags |= 2;
- }
-
- void MapVote_TouchVotes(entity voter)
- {
- mapvote_ent.SendFlags |= 4;
- }
-
- float MapVote_Finished(float mappos)
- {
- string result;
- float i;
- float didntvote;
-
- if(autocvar_sv_eventlog)
- {
- result = strcat(":vote:finished:", mapvote_maps[mappos]);
- result = strcat(result, ":", ftos(mapvote_selections[mappos]), "::");
- didntvote = mapvote_voters;
- for(i = 0; i < mapvote_count; ++i)
- if(mapvote_maps[i] != "")
- {
- didntvote -= mapvote_selections[i];
- if(i != mappos)
- {
- result = strcat(result, ":", mapvote_maps[i]);
- result = strcat(result, ":", ftos(mapvote_selections[i]));
- }
- }
- result = strcat(result, ":didn't vote:", ftos(didntvote));
-
- GameLogEcho(result);
- if(mapvote_maps_suggested[mappos])
- GameLogEcho(strcat(":vote:suggestion_accepted:", mapvote_maps[mappos]));
- }
-
- FOR_EACH_REALCLIENT(other)
- FixClientCvars(other);
-
- Map_Goto_SetStr(mapvote_maps[mappos]);
- Map_Goto(0);
- alreadychangedlevel = TRUE;
- return TRUE;
- }
- void MapVote_CheckRules_1()
- {
- float i;
-
- for(i = 0; i < mapvote_count; ++i) if(mapvote_maps[i] != "")
- {
- //dprint("Map ", ftos(i), ": "); dprint(mapvote_maps[i], "\n");
- mapvote_selections[i] = 0;
- }
-
- mapvote_voters = 0;
- FOR_EACH_REALCLIENT(other)
- {
- ++mapvote_voters;
- if(other.mapvote)
- {
- i = other.mapvote - 1;
- //dprint("Player ", other.netname, " vote = ", ftos(other.mapvote - 1), "\n");
- mapvote_selections[i] = mapvote_selections[i] + 1;
- }
- }
- }
-
- float MapVote_CheckRules_2()
- {
- float i;
- float firstPlace, secondPlace;
- float firstPlaceVotes, secondPlaceVotes;
- float mapvote_voters_real;
- string result;
-
- if(mapvote_count_real == 1)
- return MapVote_Finished(0);
-
- mapvote_voters_real = mapvote_voters;
- if(mapvote_abstain)
- mapvote_voters_real -= mapvote_selections[mapvote_count - 1];
-
- RandomSelection_Init();
- for(i = 0; i < mapvote_count_real; ++i) if(mapvote_maps[i] != "")
- RandomSelection_Add(world, i, string_null, 1, mapvote_selections[i]);
- firstPlace = RandomSelection_chosen_float;
- firstPlaceVotes = RandomSelection_best_priority;
- //dprint("First place: ", ftos(firstPlace), "\n");
- //dprint("First place votes: ", ftos(firstPlaceVotes), "\n");
-
- RandomSelection_Init();
- for(i = 0; i < mapvote_count_real; ++i) if(mapvote_maps[i] != "")
- if(i != firstPlace)
- RandomSelection_Add(world, i, string_null, 1, mapvote_selections[i]);
- secondPlace = RandomSelection_chosen_float;
- secondPlaceVotes = RandomSelection_best_priority;
- //dprint("Second place: ", ftos(secondPlace), "\n");
- //dprint("Second place votes: ", ftos(secondPlaceVotes), "\n");
-
- if(firstPlace == -1)
- error("No first place in map vote... WTF?");
-
- if(secondPlace == -1 || time > mapvote_timeout || (mapvote_voters_real - firstPlaceVotes) < firstPlaceVotes)
- return MapVote_Finished(firstPlace);
-
- if(mapvote_keeptwotime)
- if(time > mapvote_keeptwotime || (mapvote_voters_real - firstPlaceVotes - secondPlaceVotes) < secondPlaceVotes)
- {
- float didntvote;
- MapVote_TouchMask();
- mapvote_message = "Now decide between the TOP TWO!";
- mapvote_keeptwotime = 0;
- result = strcat(":vote:keeptwo:", mapvote_maps[firstPlace]);
- result = strcat(result, ":", ftos(firstPlaceVotes));
- result = strcat(result, ":", mapvote_maps[secondPlace]);
- result = strcat(result, ":", ftos(secondPlaceVotes), "::");
- didntvote = mapvote_voters;
- for(i = 0; i < mapvote_count; ++i)
- if(mapvote_maps[i] != "")
- {
- didntvote -= mapvote_selections[i];
- if(i != firstPlace)
- if(i != secondPlace)
- {
- result = strcat(result, ":", mapvote_maps[i]);
- result = strcat(result, ":", ftos(mapvote_selections[i]));
- if(i < mapvote_count_real)
- {
- strunzone(mapvote_maps[i]);
- mapvote_maps[i] = "";
- strunzone(mapvote_maps_pakfile[i]);
- mapvote_maps_pakfile[i] = "";
- }
- }
- }
- result = strcat(result, ":didn't vote:", ftos(didntvote));
- if(autocvar_sv_eventlog)
- GameLogEcho(result);
- }
-
- return FALSE;
- }
- void MapVote_Tick()
- {
- float keeptwo;
- float totalvotes;
-
- keeptwo = mapvote_keeptwotime;
- MapVote_CheckRules_1(); // count
- if(MapVote_CheckRules_2()) // decide
- return;
-
- totalvotes = 0;
- FOR_EACH_REALCLIENT(other)
- {
- // hide scoreboard again
- if(other.health != 2342)
- {
- other.health = 2342;
- other.impulse = 0;
- if(IS_REAL_CLIENT(other))
- {
- msg_entity = other;
- WriteByte(MSG_ONE, SVC_FINALE);
- WriteString(MSG_ONE, "");
- }
- }
-
- // clear possibly invalid votes
- if(mapvote_maps[other.mapvote - 1] == "")
- other.mapvote = 0;
- // use impulses as new vote
- if(other.impulse >= 1 && other.impulse <= mapvote_count)
- if(mapvote_maps[other.impulse - 1] != "")
- {
- other.mapvote = other.impulse;
- MapVote_TouchVotes(other);
- }
- other.impulse = 0;
-
- if(other.mapvote)
- ++totalvotes;
- }
-
- MapVote_CheckRules_1(); // just count
- }
- void MapVote_Start()
- {
- if(mapvote_run)
- return;
-
- // wait for stats to be sent first
- if(!playerstats_waitforme)
- return;
-
- MapInfo_Enumerate();
- if(MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 1))
- mapvote_run = TRUE;
- }
- void MapVote_Think()
- {
- if(!mapvote_run)
- return;
-
- if(alreadychangedlevel)
- return;
-
- if(time < mapvote_nextthink)
- return;
- //dprint("tick\n");
-
- mapvote_nextthink = time + 0.5;
-
- if(!mapvote_initialized)
- {
- if(autocvar_rescan_pending == 1)
- {
- cvar_set("rescan_pending", "2");
- localcmd("fs_rescan\nrescan_pending 3\n");
- return;
- }
- else if(autocvar_rescan_pending == 2)
- {
- return;
- }
- else if(autocvar_rescan_pending == 3)
- {
- // now build missing mapinfo files
- if(!MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 1))
- return;
-
- // we're done, start the timer
- cvar_set("rescan_pending", "0");
- }
-
- mapvote_initialized = TRUE;
- if(DoNextMapOverride(0))
- return;
- if(!autocvar_g_maplist_votable || player_count <= 0)
- {
- GotoNextMap(0);
- return;
- }
- MapVote_Init();
- }
-
- MapVote_Tick();
- }
-
- string GotoMap(string m)
- {
- if(!MapInfo_CheckMap(m))
- return "The map you chose is not available on this server.";
cvar_set("nextmap", m);
cvar_set("timelimit", "-1");
if(mapvote_initialized || alreadychangedlevel)
float altime;
FOR_EACH_REALCLIENT(self)
{
- if(IS_SPEC(self))
+ entity e = IS_SPEC(self) ? self.enemy : self;
+ if(e.typehitsound)
+ self.typehit_time = time;
+ else if(e.damage_dealt)
{
- if(self.enemy.typehitsound)
- self.typehit_time = time;
- else if(self.enemy.hitsound)
- self.hit_time = time;
- }
- else
- {
- if(self.typehitsound)
- self.typehit_time = time;
- else if(self.hitsound)
- self.hit_time = time;
+ self.hit_time = time;
+ self.damage_dealt_total += ceil(e.damage_dealt);
}
}
altime = time + frametime * (1 + autocvar_g_antilag_nudge);
// needed!
FOR_EACH_CLIENT(self)
{
- self.hitsound = FALSE;
self.typehitsound = FALSE;
+ self.damage_dealt = 0;
antilag_record(self, altime);
}
+ FOR_EACH_MONSTER(self)
+ antilag_record(self, altime);
}
void Shutdown()
{
- entity e;
-
gameover = 2;
if(world_initialized > 0)
print("Saving persistent data...\n");
Ban_SaveBans();
- PlayerStats_EndMatch(0);
- FOR_EACH_CLIENT(e)
- PlayerStats_AddGlobalInfo(e);
- PlayerStats_Shutdown();
+ // playerstats with unfinished match
+ PlayerStats_GameReport(FALSE);
if(!cheatcount_total)
{
wep = self.switchweapon;
if (!wep)
wep = self.cnt;
- replacement = W_Name(wep);
+ replacement = WEP_NAME(wep);
} else if (escape == "W") {
if (self.items & IT_SHELLS) replacement = "shells";
else if (self.items & IT_NAILS) replacement = "bullets";
else if (self.items & IT_ROCKETS) replacement = "rockets";
else if (self.items & IT_CELLS) replacement = "cells";
+ else if (self.items & IT_PLASMA) replacement = "plasma";
else replacement = "batteries"; // ;)
} else if (escape == "x") {
replacement = cursor_ent.netname;
stuffcmd(self, strcat("cl_cmd sendcvar ", name, "\n"));
}
}
- float w_getbestweapon(entity e);
string W_FixWeaponOrder_ForceComplete_AndBuildImpulseList(string wo)
{
string o;
GetCvars_handleFloat(s, f, autoswitch, "cl_autoswitch");
GetCvars_handleFloat(s, f, cvar_cl_autoscreenshot, "cl_autoscreenshot");
+ GetCvars_handleFloat(s, f, cvar_cl_jetpack_jump, "cl_jetpack_jump");
GetCvars_handleString(s, f, cvar_g_xonoticversion, "g_xonoticversion");
GetCvars_handleFloat(s, f, cvar_cl_handicap, "cl_handicap");
GetCvars_handleFloat(s, f, cvar_cl_clippedspectating, "cl_clippedspectating");
if (s == "cl_weaponpriority")
self.switchweapon = w_getbestweapon(self);
if (s == "cl_allow_uidtracking")
- PlayerStats_AddPlayer(self);
+ PlayerStats_GameReport_AddPlayer(self);
}
}
return p.netname;
}
-vector randompos(vector m1, vector m2)
-{
- vector v;
- m2 = m2 - m1;
- v_x = m2_x * random() + m1_x;
- v_y = m2_y * random() + m1_y;
- v_z = m2_z * random() + m1_z;
- return v;
-}
-
//#NO AUTOCVARS START
float g_pickup_shells;
float g_pickup_rockets_max;
float g_pickup_cells;
float g_pickup_cells_max;
+ float g_pickup_plasma;
+ float g_pickup_plasma_max;
float g_pickup_fuel;
float g_pickup_fuel_jetpack;
float g_pickup_fuel_max;
float g_weaponarena;
WepSet g_weaponarena_weapons;
float g_weaponarena_random;
- float g_weaponarena_random_with_laser;
+ float g_weaponarena_random_with_blaster;
string g_weaponarena_list;
float g_weaponspeedfactor;
float g_weaponratefactor;
float start_ammo_nails;
float start_ammo_rockets;
float start_ammo_cells;
+ float start_ammo_plasma;
float start_ammo_fuel;
float start_health;
float start_armorvalue;
float warmup_start_ammo_nails;
float warmup_start_ammo_rockets;
float warmup_start_ammo_cells;
+ float warmup_start_ammo_plasma;
float warmup_start_ammo_fuel;
float warmup_start_health;
float warmup_start_armorvalue;
float g_weapon_stay;
- entity get_weaponinfo(float w);
-
- float want_weapon(string cvarprefix, entity weaponinfo, float allguns)
+ float want_weapon(entity weaponinfo, float allguns) // WEAPONTODO: what still needs done?
{
var float i = weaponinfo.weapon;
var float d = 0;
else if (g_nexball)
d = 0; // weapon is set a few lines later
else
- d = (i == WEP_LASER || i == WEP_SHOTGUN);
+ d = !(!weaponinfo.weaponstart);
if(g_grappling_hook) // if possible, redirect off-hand hook to on-hand hook
d |= (i == WEP_HOOK);
- if(weaponinfo.spawnflags & WEP_FLAG_MUTATORBLOCKED) // never default mutator blocked guns
+ if(!g_cts && (weaponinfo.spawnflags & WEP_FLAG_MUTATORBLOCKED)) // never default mutator blocked guns
d = 0;
- var float t = cvar(strcat(cvarprefix, weaponinfo.netname));
+ var float t = weaponinfo.weaponstartoverride;
//print(strcat("want_weapon: ", weaponinfo.netname, " - d: ", ftos(d), ", t: ", ftos(t), ". \n"));
start_ammo_nails = 0;
start_ammo_rockets = 0;
start_ammo_cells = 0;
+ start_ammo_plasma = 0;
start_health = cvar("g_balance_health_start");
start_armorvalue = cvar("g_balance_armor_start");
{
// forcibly turn off weaponarena
}
- else if (s == "all")
+ else if (s == "all" || s == "1")
{
g_weaponarena = 1;
g_weaponarena_list = "All Weapons";
g_weaponarena_random = cvar("g_weaponarena_random");
else
g_weaponarena_random = 0;
- g_weaponarena_random_with_laser = cvar("g_weaponarena_random_with_laser");
+ g_weaponarena_random_with_blaster = cvar("g_weaponarena_random_with_blaster");
if (g_weaponarena)
{
for (i = WEP_FIRST; i <= WEP_LAST; ++i)
{
e = get_weaponinfo(i);
- float w = want_weapon("g_start_weapon_", e, FALSE);
+ float w = want_weapon(e, FALSE);
if(w & 1)
start_weapons |= WepSet_FromWeapon(i);
if(w & 2)
if(start_items & IT_UNLIMITED_WEAPON_AMMO)
{
- start_ammo_rockets = 999;
start_ammo_shells = 999;
- start_ammo_cells = 999;
start_ammo_nails = 999;
+ start_ammo_rockets = 999;
+ start_ammo_cells = 999;
+ start_ammo_plasma = 999;
start_ammo_fuel = 999;
}
else
start_ammo_nails = cvar("g_start_ammo_nails");
start_ammo_rockets = cvar("g_start_ammo_rockets");
start_ammo_cells = cvar("g_start_ammo_cells");
+ start_ammo_plasma = cvar("g_start_ammo_plasma");
start_ammo_fuel = cvar("g_start_ammo_fuel");
}
warmup_start_ammo_nails = start_ammo_nails;
warmup_start_ammo_rockets = start_ammo_rockets;
warmup_start_ammo_cells = start_ammo_cells;
+ warmup_start_ammo_plasma = start_ammo_plasma;
warmup_start_ammo_fuel = start_ammo_fuel;
warmup_start_health = start_health;
warmup_start_armorvalue = start_armorvalue;
if (!g_weaponarena && !g_ca)
{
warmup_start_ammo_shells = cvar("g_warmup_start_ammo_shells");
- warmup_start_ammo_cells = cvar("g_warmup_start_ammo_cells");
warmup_start_ammo_nails = cvar("g_warmup_start_ammo_nails");
warmup_start_ammo_rockets = cvar("g_warmup_start_ammo_rockets");
+ warmup_start_ammo_cells = cvar("g_warmup_start_ammo_cells");
+ warmup_start_ammo_plasma = cvar("g_warmup_start_ammo_plasma");
warmup_start_ammo_fuel = cvar("g_warmup_start_ammo_fuel");
warmup_start_health = cvar("g_warmup_start_health");
warmup_start_armorvalue = cvar("g_warmup_start_armor");
for (i = WEP_FIRST; i <= WEP_LAST; ++i)
{
e = get_weaponinfo(i);
- float w = want_weapon("g_start_weapon_", e, g_warmup_allguns);
+ float w = want_weapon(e, g_warmup_allguns);
if(w & 1)
warmup_start_weapons |= WepSet_FromWeapon(i);
if(w & 2)
if ((start_items & IT_JETPACK) || (g_grappling_hook && (start_weapons & WEPSET_HOOK)))
{
- g_grappling_hook = 0; // these two can't coexist, as they use the same button
start_items |= IT_FUEL_REGEN;
start_ammo_fuel = max(start_ammo_fuel, cvar("g_balance_fuel_rotstable"));
warmup_start_ammo_fuel = max(warmup_start_ammo_fuel, cvar("g_balance_fuel_rotstable"));
{
e = get_weaponinfo(i);
if(precache_weapons & WepSet_FromWeapon(i))
- weapon_action(i, WR_PRECACHE);
+ WEP_ACTION(i, WR_INIT);
}
start_ammo_shells = max(0, start_ammo_shells);
start_ammo_nails = max(0, start_ammo_nails);
- start_ammo_cells = max(0, start_ammo_cells);
start_ammo_rockets = max(0, start_ammo_rockets);
+ start_ammo_cells = max(0, start_ammo_cells);
+ start_ammo_plasma = max(0, start_ammo_plasma);
start_ammo_fuel = max(0, start_ammo_fuel);
warmup_start_ammo_shells = max(0, warmup_start_ammo_shells);
warmup_start_ammo_nails = max(0, warmup_start_ammo_nails);
- warmup_start_ammo_cells = max(0, warmup_start_ammo_cells);
warmup_start_ammo_rockets = max(0, warmup_start_ammo_rockets);
+ warmup_start_ammo_cells = max(0, warmup_start_ammo_cells);
+ warmup_start_ammo_plasma = max(0, warmup_start_ammo_plasma);
warmup_start_ammo_fuel = max(0, warmup_start_ammo_fuel);
}
float sv_taunt;
string GetGametype(); // g_world.qc
+ void mutators_add(); // mutators.qc
void readlevelcvars(void)
{
// load mutators
- #define CHECK_MUTATOR_ADD(mut_cvar,mut_name,dependence) \
- { if(cvar(mut_cvar) && dependence) { MUTATOR_ADD(mut_name); } }
-
- CHECK_MUTATOR_ADD("g_dodging", mutator_dodging, 1);
- CHECK_MUTATOR_ADD("g_spawn_near_teammate", mutator_spawn_near_teammate, teamplay);
- CHECK_MUTATOR_ADD("g_physical_items", mutator_physical_items, 1);
- CHECK_MUTATOR_ADD("g_touchexplode", mutator_touchexplode, 1);
- CHECK_MUTATOR_ADD("g_minstagib", mutator_minstagib, 1);
- CHECK_MUTATOR_ADD("g_invincible_projectiles", mutator_invincibleprojectiles, !cvar("g_minstagib"));
- CHECK_MUTATOR_ADD("g_new_toys", mutator_new_toys, !cvar("g_minstagib"));
- CHECK_MUTATOR_ADD("g_nix", mutator_nix, !cvar("g_minstagib"));
- CHECK_MUTATOR_ADD("g_rocket_flying", mutator_rocketflying, !cvar("g_minstagib"));
- CHECK_MUTATOR_ADD("g_vampire", mutator_vampire, !cvar("g_minstagib"));
- CHECK_MUTATOR_ADD("g_superspectate", mutator_superspec, 1);
- CHECK_MUTATOR_ADD("g_pinata", mutator_pinata, !cvar("g_minstagib"));
- CHECK_MUTATOR_ADD("g_midair", mutator_midair, 1);
- CHECK_MUTATOR_ADD("g_bloodloss", mutator_bloodloss, !cvar("g_minstagib"));
- CHECK_MUTATOR_ADD("g_random_gravity", mutator_random_gravity, 1);
- CHECK_MUTATOR_ADD("g_multijump", mutator_multijump, 1);
- CHECK_MUTATOR_ADD("g_melee_only", mutator_melee_only, !cvar("g_minstagib"));
- CHECK_MUTATOR_ADD("g_nades", mutator_nades, 1);
- CHECK_MUTATOR_ADD("g_sandbox", sandbox, 1);
- CHECK_MUTATOR_ADD("g_campcheck", mutator_campcheck, 1);
-
- #undef CHECK_MUTATOR_ADD
+ mutators_add();
if(cvar("sv_allow_fullbright"))
serverflags |= SERVERFLAG_ALLOW_FULLBRIGHT;
g_bugrigs_speed_pow = cvar("g_bugrigs_speed_pow");
g_bugrigs_steer = cvar("g_bugrigs_steer");
- g_minstagib = cvar("g_minstagib");
+ g_instagib = cvar("g_instagib");
sv_clones = cvar("sv_clones");
sv_foginterval = cvar("sv_foginterval");
g_cloaked = cvar("g_cloaked");
- if(g_cts)
- g_cloaked = 1; // always enable cloak in CTS
g_footsteps = cvar("g_footsteps");
g_grappling_hook = cvar("g_grappling_hook");
g_jetpack = cvar("g_jetpack");
g_pickup_rockets_max = cvar("g_pickup_rockets_max");
g_pickup_cells = cvar("g_pickup_cells");
g_pickup_cells_max = cvar("g_pickup_cells_max");
+ g_pickup_plasma = cvar("g_pickup_plasma");
+ g_pickup_plasma_max = cvar("g_pickup_plasma_max");
g_pickup_fuel = cvar("g_pickup_fuel");
g_pickup_fuel_jetpack = cvar("g_pickup_fuel_jetpack");
g_pickup_fuel_max = cvar("g_pickup_fuel_max");
return TRUE;
}
- #ifdef COMPAT_XON010_CHANNELS
- void(entity e, float chan, string samp, float vol, float atten) builtin_sound = #8;
- void sound(entity e, float chan, string samp, float vol, float atten)
- {
- if (!sound_allowed(MSG_BROADCAST, e))
- return;
- builtin_sound(e, chan, samp, vol, atten);
- }
- #else
#undef sound
void sound(entity e, float chan, string samp, float vol, float atten)
{
return;
sound7(e, chan, samp, vol, atten, 0, 0);
}
- #endif
void soundtoat(float dest, entity e, vector o, float chan, string samp, float vol, float atten)
{
{
// gamemode related things
precache_model ("models/misc/chatbubble.spr");
+ precache_model("models/ice/ice.md3");
#ifdef TTURRETS_ENABLED
if (autocvar_g_turrets)
precache_sound ("weapons/hook_impact.wav"); // hook
}
- if(autocvar_sv_precacheweapons)
- {
- //precache weapon models/sounds
- float wep;
- wep = WEP_FIRST;
- while (wep <= WEP_LAST)
- {
- weapon_action(wep, WR_PRECACHE);
- wep = wep + 1;
- }
- }
-
precache_model("models/elaser.mdl");
precache_model("models/laser.mdl");
precache_model("models/ebomb.mdl");
}
}
+
+ entity eliminatedPlayers;
+ .float(entity) isEliminated;
+ float EliminatedPlayers_SendEntity(entity to, float sendflags)
+ {
+ float i, f, b;
+ entity e;
+ WriteByte(MSG_ENTITY, ENT_CLIENT_ELIMINATEDPLAYERS);
+ WriteByte(MSG_ENTITY, sendflags);
+
+ if(sendflags & 1)
+ {
+ for(i = 1; i <= maxclients; i += 8)
+ {
+ for(f = 0, e = edict_num(i), b = 1; b < 256; b *= 2, e = nextent(e))
+ {
+ if(eliminatedPlayers.isEliminated(e))
+ f |= b;
+ }
+ WriteByte(MSG_ENTITY, f);
+ }
+ }
+
+ return TRUE;
+ }
+
+ void EliminatedPlayers_Init(float(entity) isEliminated_func)
+ {
+ if(eliminatedPlayers)
+ {
+ backtrace("Can't spawn eliminatedPlayers again!");
+ return;
+ }
+ Net_LinkEntity(eliminatedPlayers = spawn(), FALSE, 0, EliminatedPlayers_SendEntity);
+ eliminatedPlayers.isEliminated = isEliminated_func;
+ }
+
+
void adaptor_think2touch()
{
entity o;
return TRUE;
if(SUB_NoImpactCheck())
{
- if(self.classname == "grapplinghook")
+ if(self.classname == "nade")
+ return FALSE; // no checks here
+ else if(self.classname == "grapplinghook")
RemoveGrapplingHook(self.realowner);
else if(self.classname == "spike")
{
return s;
}
- float race_readTime(string map, float pos)
- {
- string rr;
- if(g_cts)
- rr = CTS_RECORD;
- else
- rr = RACE_RECORD;
-
- return stof(db_get(ServerProgsDB, strcat(map, rr, "time", ftos(pos))));
- }
-
- string race_readUID(string map, float pos)
- {
- string rr;
- if(g_cts)
- rr = CTS_RECORD;
- else
- rr = RACE_RECORD;
-
- return db_get(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(pos)));
- }
-
- float race_readPos(string map, float t) {
- float i;
- for (i = 1; i <= RANKINGS_CNT; ++i)
- if (race_readTime(map, i) == 0 || race_readTime(map, i) > t)
- return i;
-
- return 0; // pos is zero if unranked
- }
-
- void race_writeTime(string map, float t, string myuid)
- {
- string rr;
- if(g_cts)
- rr = CTS_RECORD;
- else
- rr = RACE_RECORD;
-
- float newpos;
- newpos = race_readPos(map, t);
-
- float i, prevpos = 0;
- for(i = 1; i <= RANKINGS_CNT; ++i)
- {
- if(race_readUID(map, i) == myuid)
- prevpos = i;
- }
- if (prevpos) { // player improved his existing record, only have to iterate on ranks between new and old recs
- for (i = prevpos; i > newpos; --i) {
- db_put(ServerProgsDB, strcat(map, rr, "time", ftos(i)), ftos(race_readTime(map, i - 1)));
- db_put(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(i)), race_readUID(map, i - 1));
- }
- } else { // player has no ranked record yet
- for (i = RANKINGS_CNT; i > newpos; --i) {
- db_put(ServerProgsDB, strcat(map, rr, "time", ftos(i)), ftos(race_readTime(map, i - 1)));
- db_put(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(i)), race_readUID(map, i - 1));
- }
- }
-
- // store new time itself
- db_put(ServerProgsDB, strcat(map, rr, "time", ftos(newpos)), ftos(t));
- db_put(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(newpos)), myuid);
- }
-
- string race_readName(string map, float pos)
- {
- string rr;
- if(g_cts)
- rr = CTS_RECORD;
- else
- rr = RACE_RECORD;
-
- return uid2name(db_get(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(pos))));
- }
-
float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
{
float m, i;
-float autocvar_g_onslaught_spawn_at_controlpoints;
-float autocvar_g_onslaught_spawn_at_generator;
-float autocvar_g_onslaught_cp_proxydecap;
-var float autocvar_g_onslaught_cp_proxydecap_distance = 512;
-var float autocvar_g_onslaught_cp_proxydecap_dps = 100;
+// =======================
+// CaptureShield Functions
+// =======================
-void onslaught_generator_updatesprite(entity e);
-void onslaught_controlpoint_updatesprite(entity e);
-void onslaught_link_checkupdate();
-
-.entity sprite;
-.string target2;
-.float iscaptured;
-.float islinked;
-.float isgenneighbor_red;
-.float isgenneighbor_blue;
-.float iscpneighbor_red;
-.float iscpneighbor_blue;
-.float isshielded;
-.float lasthealth;
-.float lastteam;
-.float lastshielded;
-.float lastcaptured;
+float ons_CaptureShield_Customize()
+{
+ entity e = WaypointSprite_getviewentity(other);
-entity ons_red_generator;
-entity ons_blue_generator;
+ if(!self.enemy.isshielded && (ons_ControlPoint_Attackable(self.enemy, e.team) > 0 || self.enemy.classname != "onslaught_controlpoint")) { return FALSE; }
+ if(SAME_TEAM(self, e)) { return FALSE; }
-void ons_gib_damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce)
-{
- self.velocity = self.velocity + vforce;
+ return TRUE;
}
-.float giblifetime;
-void ons_throwgib_think()
+void ons_CaptureShield_Touch()
{
- float d;
+ if(!self.enemy.isshielded && (ons_ControlPoint_Attackable(self.enemy, other.team) > 0 || self.enemy.classname != "onslaught_controlpoint")) { return; }
+ if(!IS_PLAYER(other)) { return; }
+ if(SAME_TEAM(other, self)) { return; }
- self.nextthink = time + 0.05;
+ vector mymid = (self.absmin + self.absmax) * 0.5;
+ vector othermid = (other.absmin + other.absmax) * 0.5;
- d = self.giblifetime - time;
+ Damage(other, self, self, 0, DEATH_HURTTRIGGER, mymid, normalize(othermid - mymid) * ons_captureshield_force);
- if(d<0)
+ if(IS_REAL_CLIENT(other))
{
- self.think = SUB_Remove;
- return;
+ play2(other, "onslaught/damageblockedbyshield.wav");
+
+ if(self.enemy.classname == "onslaught_generator")
+ Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_ONS_GENERATOR_SHIELDED);
+ else
+ Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_ONS_CONTROLPOINT_SHIELDED);
}
- if(d<1)
- self.alpha = d;
+}
- if(d>2)
- if(random()<0.6)
- pointparticles(particleeffectnum("onslaught_generator_gib_flame"), self.origin, '0 0 0', 1);
+void ons_CaptureShield_Reset()
+{
+ self.colormap = self.enemy.colormap;
+ self.team = self.enemy.team;
}
-void ons_throwgib(vector v_from, vector v_to, string smodel, float f_lifetime, float b_burn)
+void ons_CaptureShield_Spawn(entity generator, float is_generator)
{
- entity gib;
+ entity shield = spawn();
+
+ shield.enemy = generator;
+ shield.team = generator.team;
+ shield.colormap = generator.colormap;
+ shield.reset = ons_CaptureShield_Reset;
+ shield.touch = ons_CaptureShield_Touch;
+ shield.customizeentityforclient = ons_CaptureShield_Customize;
+ shield.classname = "ons_captureshield";
+ shield.effects = EF_ADDITIVE;
+ shield.movetype = MOVETYPE_NOCLIP;
+ shield.solid = SOLID_TRIGGER;
+ shield.avelocity = '7 0 11';
+ shield.scale = 1;
+ shield.model = ((is_generator) ? "models/onslaught/generator_shield.md3" : "models/onslaught/controlpoint_shield.md3");
+
+ precache_model(shield.model);
+ setorigin(shield, generator.origin);
+ setmodel(shield, shield.model);
+ setsize(shield, shield.scale * shield.mins, shield.scale * shield.maxs);
+}
- gib = spawn();
- setmodel(gib, smodel);
- setorigin(gib, v_from);
- gib.solid = SOLID_BBOX;
- gib.movetype = MOVETYPE_BOUNCE;
- gib.takedamage = DAMAGE_YES;
- gib.event_damage = ons_gib_damage;
- gib.health = -1;
- gib.effects = EF_LOWPRECISION;
- gib.flags = FL_NOTARGET;
- gib.velocity = v_to;
- gib.giblifetime = time + f_lifetime;
+// ==========
+// Junk Pile
+// ==========
- if (b_burn)
+void ons_debug(string input)
+{
+ switch(autocvar_g_onslaught_debug)
{
- gib.think = ons_throwgib_think;
- gib.nextthink = time + 0.05;
+ case 1: dprint(input); break;
+ case 2: print(input); break;
}
- else
- SUB_SetFade(gib, gib.giblifetime, 2);
+}
+
+void FixSize(entity e)
+{
+ e.mins_x = rint(e.mins_x);
+ e.mins_y = rint(e.mins_y);
+ e.mins_z = rint(e.mins_z);
+
+ e.maxs_x = rint(e.maxs_x);
+ e.maxs_y = rint(e.maxs_y);
+ e.maxs_z = rint(e.maxs_z);
+}
+
+vector randompos(vector m1, vector m2)
+{
+ vector v;
+ m2 = m2 - m1;
+ v_x = m2_x * random() + m1_x;
+ v_y = m2_y * random() + m1_y;
+ v_z = m2_z * random() + m1_z;
+ return v;
+}
+
+void setmodel_fixsize(entity e, string m)
+{
+ setmodel(e, m);
+ FixSize(e);
}
void onslaught_updatelinks()
{
- entity l, links;
- float stop, t1, t2, t3, t4;
+ entity l;
// first check if the game has ended
- dprint("--- updatelinks ---\n");
- links = findchain(classname, "onslaught_link");
+ ons_debug("--- updatelinks ---\n");
// mark generators as being shielded and networked
- l = findchain(classname, "onslaught_generator");
- while (l)
+ for(l = ons_worldgeneratorlist; l; l = l.ons_worldgeneratornext)
{
if (l.iscaptured)
- dprint(etos(l), " (generator) belongs to team ", ftos(l.team), "\n");
+ ons_debug(strcat(etos(l), " (generator) belongs to team ", ftos(l.team), "\n"));
else
- dprint(etos(l), " (generator) is destroyed\n");
+ ons_debug(strcat(etos(l), " (generator) is destroyed\n"));
l.islinked = l.iscaptured;
l.isshielded = l.iscaptured;
- l = l.chain;
+ l.sprite.SendFlags |= 16;
}
// mark points as shielded and not networked
- l = findchain(classname, "onslaught_controlpoint");
- while (l)
+ for(l = ons_worldcplist; l; l = l.ons_worldcpnext)
{
l.islinked = FALSE;
l.isshielded = TRUE;
- l.isgenneighbor_red = FALSE;
- l.isgenneighbor_blue = FALSE;
- l.iscpneighbor_red = FALSE;
- l.iscpneighbor_blue = FALSE;
- dprint(etos(l), " (point) belongs to team ", ftos(l.team), "\n");
- l = l.chain;
+ float i;
+ for(i = 0; i < 17; ++i) { l.isgenneighbor[i] = FALSE; l.iscpneighbor[i] = FALSE; }
+ ons_debug(strcat(etos(l), " (point) belongs to team ", ftos(l.team), "\n"));
+ l.sprite.SendFlags |= 16;
}
// flow power outward from the generators through the network
- l = links;
- while (l)
- {
- dprint(etos(l), " (link) connects ", etos(l.goalentity), " with ", etos(l.enemy), "\n");
- l = l.chain;
- }
- stop = FALSE;
+ float stop = FALSE;
while (!stop)
{
stop = TRUE;
- l = links;
- while (l)
+ for(l = ons_worldlinklist; l; l = l.ons_worldlinknext)
{
// if both points are captured by the same team, and only one of
// them is powered, mark the other one as powered as well
if (l.enemy.iscaptured && l.goalentity.iscaptured)
if (l.enemy.islinked != l.goalentity.islinked)
- if (l.enemy.team == l.goalentity.team)
+ if(SAME_TEAM(l.enemy, l.goalentity))
{
if (!l.goalentity.islinked)
{
stop = FALSE;
l.goalentity.islinked = TRUE;
- dprint(etos(l), " (link) is marking ", etos(l.goalentity), " (point) because its team matches ", etos(l.enemy), " (point)\n");
+ ons_debug(strcat(etos(l), " (link) is marking ", etos(l.goalentity), " (point) because its team matches ", etos(l.enemy), " (point)\n"));
}
else if (!l.enemy.islinked)
{
stop = FALSE;
l.enemy.islinked = TRUE;
- dprint(etos(l), " (link) is marking ", etos(l.enemy), " (point) because its team matches ", etos(l.goalentity), " (point)\n");
+ ons_debug(strcat(etos(l), " (link) is marking ", etos(l.enemy), " (point) because its team matches ", etos(l.goalentity), " (point)\n"));
}
}
- l = l.chain;
}
}
// now that we know which points are powered we can mark their neighbors
// as unshielded if team differs
- l = links;
- while (l)
+ for(l = ons_worldlinklist; l; l = l.ons_worldlinknext)
{
if (l.goalentity.islinked)
{
- if (l.goalentity.team != l.enemy.team)
+ if(DIFF_TEAM(l.goalentity, l.enemy))
{
- dprint(etos(l), " (link) is unshielding ", etos(l.enemy), " (point) because its team does not match ", etos(l.goalentity), " (point)\n");
+ ons_debug(strcat(etos(l), " (link) is unshielding ", etos(l.enemy), " (point) because its team does not match ", etos(l.goalentity), " (point)\n"));
l.enemy.isshielded = FALSE;
}
if(l.goalentity.classname == "onslaught_generator")
- {
- if(l.goalentity.team == NUM_TEAM_1)
- l.enemy.isgenneighbor_red = TRUE;
- else if(l.goalentity.team == NUM_TEAM_2)
- l.enemy.isgenneighbor_blue = TRUE;
- }
+ l.enemy.isgenneighbor[l.goalentity.team] = TRUE;
else
- {
- if(l.goalentity.team == NUM_TEAM_1)
- l.enemy.iscpneighbor_red = TRUE;
- else if(l.goalentity.team == NUM_TEAM_2)
- l.enemy.iscpneighbor_blue = TRUE;
- }
+ l.enemy.iscpneighbor[l.goalentity.team] = TRUE;
}
if (l.enemy.islinked)
{
- if (l.goalentity.team != l.enemy.team)
+ if(DIFF_TEAM(l.goalentity, l.enemy))
{
- dprint(etos(l), " (link) is unshielding ", etos(l.goalentity), " (point) because its team does not match ", etos(l.enemy), " (point)\n");
+ ons_debug(strcat(etos(l), " (link) is unshielding ", etos(l.goalentity), " (point) because its team does not match ", etos(l.enemy), " (point)\n"));
l.goalentity.isshielded = FALSE;
}
if(l.enemy.classname == "onslaught_generator")
- {
- if(l.enemy.team == NUM_TEAM_1)
- l.goalentity.isgenneighbor_red = TRUE;
- else if(l.enemy.team == NUM_TEAM_2)
- l.goalentity.isgenneighbor_blue = TRUE;
- }
+ l.goalentity.isgenneighbor[l.enemy.team] = TRUE;
else
- {
- if(l.enemy.team == NUM_TEAM_1)
- l.goalentity.iscpneighbor_red = TRUE;
- else if(l.enemy.team == NUM_TEAM_2)
- l.goalentity.iscpneighbor_blue = TRUE;
- }
+ l.goalentity.iscpneighbor[l.enemy.team] = TRUE;
}
- l = l.chain;
}
- // now update the takedamage and alpha variables on generator shields
- l = findchain(classname, "onslaught_generator");
- while (l)
+ // now update the generators
+ for(l = ons_worldgeneratorlist; l; l = l.ons_worldgeneratornext)
{
if (l.isshielded)
{
- dprint(etos(l), " (generator) is shielded\n");
- l.enemy.alpha = 1;
+ ons_debug(strcat(etos(l), " (generator) is shielded\n"));
l.takedamage = DAMAGE_NO;
l.bot_attack = FALSE;
}
else
{
- dprint(etos(l), " (generator) is not shielded\n");
- l.enemy.alpha = -1;
+ ons_debug(strcat(etos(l), " (generator) is not shielded\n"));
l.takedamage = DAMAGE_AIM;
l.bot_attack = TRUE;
}
- l = l.chain;
+
+ ons_Generator_UpdateSprite(l);
}
// now update the takedamage and alpha variables on control point icons
- l = findchain(classname, "onslaught_controlpoint");
- while (l)
+ for(l = ons_worldcplist; l; l = l.ons_worldcpnext)
{
if (l.isshielded)
{
- dprint(etos(l), " (point) is shielded\n");
- l.enemy.alpha = 1;
+ ons_debug(strcat(etos(l), " (point) is shielded\n"));
if (l.goalentity)
{
l.goalentity.takedamage = DAMAGE_NO;
}
else
{
- dprint(etos(l), " (point) is not shielded\n");
- l.enemy.alpha = -1;
+ ons_debug(strcat(etos(l), " (point) is not shielded\n"));
if (l.goalentity)
{
l.goalentity.takedamage = DAMAGE_AIM;
l.goalentity.bot_attack = TRUE;
}
}
- onslaught_controlpoint_updatesprite(l);
- l = l.chain;
+ ons_ControlPoint_UpdateSprite(l);
}
- // count generators owned by each team
- t1 = t2 = t3 = t4 = 0;
- l = findchain(classname, "onslaught_generator");
- while (l)
+ l = findchain(classname, "ons_captureshield");
+ while(l)
{
- if (l.iscaptured)
- {
- if (l.team == NUM_TEAM_1) t1 = 1;
- if (l.team == NUM_TEAM_2) t2 = 1;
- if (l.team == NUM_TEAM_3) t3 = 1;
- if (l.team == NUM_TEAM_4) t4 = 1;
- }
- onslaught_generator_updatesprite(l);
+ l.team = l.enemy.team;
+ l.colormap = l.enemy.colormap;
l = l.chain;
}
- // see if multiple teams remain (if not, it's game over)
- if (t1 + t2 + t3 + t4 < 2)
- dprint("--- game over ---\n");
- else
- dprint("--- done updating links ---\n");
}
-float onslaught_controlpoint_can_be_linked(entity cp, float t)
+
+// ===================
+// Main Link Functions
+// ===================
+
+float ons_Link_Send(entity to, float sendflags)
{
- if(t == NUM_TEAM_1)
+ WriteByte(MSG_ENTITY, ENT_CLIENT_RADARLINK);
+ WriteByte(MSG_ENTITY, sendflags);
+ if(sendflags & 1)
{
- if(cp.isgenneighbor_red)
- return 2;
- if(cp.iscpneighbor_red)
- return 1;
+ WriteCoord(MSG_ENTITY, self.goalentity.origin_x);
+ WriteCoord(MSG_ENTITY, self.goalentity.origin_y);
+ WriteCoord(MSG_ENTITY, self.goalentity.origin_z);
}
- else if(t == NUM_TEAM_2)
+ if(sendflags & 2)
{
- if(cp.isgenneighbor_blue)
- return 2;
- if(cp.iscpneighbor_blue)
- return 1;
+ WriteCoord(MSG_ENTITY, self.enemy.origin_x);
+ WriteCoord(MSG_ENTITY, self.enemy.origin_y);
+ WriteCoord(MSG_ENTITY, self.enemy.origin_z);
}
- return 0;
- /*
- entity e;
- // check to see if this player has a legitimate claim to capture this
- // control point - more specifically that there is a captured path of
- // points leading back to the team generator
- e = findchain(classname, "onslaught_link");
- while (e)
- {
- if (e.goalentity == cp)
- {
- dprint(etos(e), " (link) connects to ", etos(e.enemy), " (point)");
- if (e.enemy.islinked)
- {
- dprint(" which is linked");
- if (e.enemy.team == t)
+ if(sendflags & 4)
{
- dprint(" and has the correct team!\n");
- return 1;
- }
- else
- dprint(" but has the wrong team\n");
- }
- else
- dprint("\n");
+ WriteByte(MSG_ENTITY, self.clientcolors); // which is goalentity's color + enemy's color * 16
}
- else if (e.enemy == cp)
- {
- dprint(etos(e), " (link) connects to ", etos(e.goalentity), " (point)");
- if (e.goalentity.islinked)
- {
- dprint(" which is linked");
- if (e.goalentity.team == t)
+ return TRUE;
+}
+
+void ons_Link_CheckUpdate()
+{
+ // TODO check if the two sides have moved (currently they won't move anyway)
+ float cc = 0, cc1 = 0, cc2 = 0;
+
+ if(self.goalentity.islinked || self.goalentity.iscaptured) { cc1 = (self.goalentity.team - 1) * 0x01; }
+ if(self.enemy.islinked || self.enemy.iscaptured) { cc2 = (self.enemy.team - 1) * 0x10; }
+
+ cc = cc1 + cc2;
+
+ if(cc != self.clientcolors)
{
- dprint(" and has a team!\n");
- return 1;
- }
- else
- dprint(" but has the wrong team\n");
- }
- else
- dprint("\n");
- }
- e = e.chain;
+ self.clientcolors = cc;
+ self.SendFlags |= 4;
}
+
+ self.nextthink = time;
+}
+
+void ons_DelayedLinkSetup()
+{
+ self.goalentity = find(world, targetname, self.target);
+ self.enemy = find(world, targetname, self.target2);
+ if(!self.goalentity) { objerror("can not find target\n"); }
+ if(!self.enemy) { objerror("can not find target2\n"); }
+
+ ons_debug(strcat(etos(self.goalentity), " linked with ", etos(self.enemy), "\n"));
+ self.SendFlags |= 3;
+ self.think = ons_Link_CheckUpdate;
+ self.nextthink = time;
+}
+
+
+// =============================
+// Main Control Point Functions
+// =============================
+
+float ons_ControlPoint_CanBeLinked(entity cp, float teamnumber)
+{
+ if(cp.isgenneighbor[teamnumber]) { return 2; }
+ if(cp.iscpneighbor[teamnumber]) { return 1; }
+
return 0;
- */
}
-float onslaught_controlpoint_attackable(entity cp, float t)
+float ons_ControlPoint_Attackable(entity cp, float teamnumber)
// -2: SAME TEAM, attackable by enemy!
// -1: SAME TEAM!
// 0: off limits
else if(cp.goalentity)
{
// if there's already an icon built, nothing happens
- if(cp.team == t)
+ if(cp.team == teamnumber)
{
- a = onslaught_controlpoint_can_be_linked(cp, NUM_TEAM_1 + NUM_TEAM_2 - t);
+ a = ons_ControlPoint_CanBeLinked(cp, teamnumber);
if(a) // attackable by enemy?
return -2; // EMERGENCY!
return -1;
}
// we know it can be linked, so no need to check
// but...
- a = onslaught_controlpoint_can_be_linked(cp, t);
+ a = ons_ControlPoint_CanBeLinked(cp, teamnumber);
if(a == 2) // near our generator?
return 3; // EMERGENCY!
return 1;
else
{
// free point
- if(onslaught_controlpoint_can_be_linked(cp, t))
+ if(ons_ControlPoint_CanBeLinked(cp, teamnumber))
{
- a = onslaught_controlpoint_can_be_linked(cp, NUM_TEAM_1 + NUM_TEAM_2 - t);
+ a = ons_ControlPoint_CanBeLinked(cp, teamnumber); // why was this here NUM_TEAM_1 + NUM_TEAM_2 - t
if(a == 2)
return 4; // GET THIS ONE NOW!
else
return 0;
}
-float overtime_msg_time;
-void onslaught_generator_think()
+void ons_ControlPoint_Icon_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
{
- float d;
- entity e;
- self.nextthink = ceil(time + 1);
- if (!gameover)
+ entity oself;
+
+ if(damage <= 0) { return; }
+
+ if (self.owner.isshielded)
{
- if (autocvar_timelimit && time > game_starttime + autocvar_timelimit * 60)
- {
- if (!overtime_msg_time)
- {
- Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_OVERTIME_CONTROLPOINT);
- overtime_msg_time = time;
- }
- // self.max_health / 300 gives 5 minutes of overtime.
- // control points reduce the overtime duration.
- sound(self, CH_TRIGGER, "onslaught/generator_decay.wav", VOL_BASE, ATTEN_NORM);
- d = 1;
- e = findchain(classname, "onslaught_controlpoint");
- while (e)
+ // this is protected by a shield, so ignore the damage
+ if (time > self.pain_finished)
+ if (IS_PLAYER(attacker))
{
- if (e.team != self.team)
- if (e.islinked)
- d = d + 1;
- e = e.chain;
+ play2(attacker, "onslaught/damageblockedbyshield.wav");
+ self.pain_finished = time + 1;
+ attacker.typehitsound += 1; // play both sounds (shield is way too quiet)
}
- if(autocvar_g_campaign && autocvar__campaign_testrun)
- d = d * self.max_health;
- else
- d = d * self.max_health / max(30, 60 * autocvar_timelimit_suddendeath);
-
- Damage(self, self, self, d, DEATH_HURTTRIGGER, self.origin, '0 0 0');
- }
- else if (overtime_msg_time)
- overtime_msg_time = 0;
-
- if(!self.isshielded && self.wait < time)
- {
- self.wait = time + 5;
- FOR_EACH_REALPLAYER(e)
- {
- if(SAME_TEAM(e, self))
- {
- Send_Notification(NOTIF_ONE, e, MSG_CENTER, CENTER_ONS_NOTSHIELDED);
- soundto(MSG_ONE, e, CHAN_AUTO, "kh/alarm.wav", VOL_BASE, ATTEN_NONE); // FIXME: Uniqe sound?
- }
- }
- }
+ return;
}
-}
-
-void onslaught_generator_ring_spawn(vector org)
-{
- modeleffect_spawn("models/onslaught/shockwavetransring.md3", 0, 0, org, '0 0 0', '0 0 0', '0 0 0', 0, -16, 0.1, 1.25, 0.25);
-}
-void onslaught_generator_ray_think()
-{
- self.nextthink = time + 0.05;
- if(self.count > 10)
+ if(IS_PLAYER(attacker))
+ if(time - ons_notification_time[self.team] > 10)
{
- self.think = SUB_Remove;
- return;
+ play2team(self.team, "onslaught/controlpoint_underattack.wav");
+ ons_notification_time[self.team] = time;
}
- if(self.count > 5)
- self.alpha -= 0.1;
+ self.health = self.health - damage;
+ if(self.owner.iscaptured)
+ WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
+ else
- WaypointSprite_UpdateBuildFinished(self.owner.sprite, time + (self.max_health - self.health) / (self.count / CP_THINKRATE));
++ WaypointSprite_UpdateBuildFinished(self.owner.sprite, time + (self.max_health - self.health) / (self.count / ONS_CP_THINKRATE));
+ self.pain_finished = time + 1;
+ // particles on every hit
+ pointparticles(particleeffectnum("sparks"), hitloc, force*-1, 1);
+ //sound on every hit
+ if (random() < 0.5)
+ sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE+0.3, ATTEN_NORM);
else
- self.alpha += 0.1;
+ sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE+0.3, ATTEN_NORM);
- self.scale += 0.2;
- self.count +=1;
-}
+ if (self.health < 0)
+ {
+ sound(self, CH_TRIGGER, "weapons/grenade_impact.wav", VOL_BASE, ATTEN_NORM);
+ pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(self.team, INFO_ONSLAUGHT_CPDESTROYED_), self.owner.message, attacker.netname);
+
+ PlayerScore_Add(attacker, SP_ONS_TAKES, 1);
+ PlayerScore_Add(attacker, SP_SCORE, 10);
+
+ self.owner.goalentity = world;
+ self.owner.islinked = FALSE;
+ self.owner.iscaptured = FALSE;
+ self.owner.team = 0;
+ self.owner.colormap = 1024;
-void onslaught_generator_ray_spawn(vector org)
-{
- entity e;
- e = spawn();
- setmodel(e, "models/onslaught/ons_ray.md3");
- setorigin(e, org);
- e.angles = randomvec() * 360;
- e.alpha = 0;
- e.scale = random() * 5 + 8;
- e.think = onslaught_generator_ray_think;
- e.nextthink = time + 0.05;
-}
+ WaypointSprite_UpdateMaxHealth(self.owner.sprite, 0);
-void onslaught_generator_shockwave_spawn(vector org)
-{
- shockwave_spawn("models/onslaught/shockwave.md3", org, -64, 0.75, 0.5);
-}
+ onslaught_updatelinks();
-void onslaught_generator_damage_think()
-{
- if(self.owner.health < 0)
- {
- self.think = SUB_Remove;
- return;
- }
- self.nextthink = time+0.1;
+ // Use targets now (somebody make sure this is in the right place..)
+ oself = self;
+ self = self.owner;
+ activator = self;
+ SUB_UseTargets ();
+ self = oself;
- // damaged fx (less probable the more damaged is the generator)
- if(random() < 0.9 - self.owner.health / self.owner.max_health)
- if(random() < 0.01)
- {
- pointparticles(particleeffectnum("electro_ballexplode"), self.origin + randompos('-50 -50 -20', '50 50 50'), '0 0 0', 1);
- sound(self, CH_TRIGGER, "onslaught/electricity_explode.wav", VOL_BASE, ATTEN_NORM);
- }
- else
- pointparticles(particleeffectnum("torch_small"), self.origin + randompos('-60 -60 -20', '60 60 60'), '0 0 0', 1);
-}
+ self.owner.waslinked = self.owner.islinked;
+ if(self.owner.model != "models/onslaught/controlpoint_pad.md3")
+ setmodel_fixsize(self.owner, "models/onslaught/controlpoint_pad.md3");
+ //setsize(self, '-32 -32 0', '32 32 8');
-void onslaught_generator_damage_spawn(entity gd_owner)
-{
- entity e;
- e = spawn();
- e.owner = gd_owner;
- e.health = self.owner.health;
- setorigin(e, gd_owner.origin);
- e.think = onslaught_generator_damage_think;
- e.nextthink = time+1;
+ remove(self);
+ }
+
+ self.SendFlags |= CPSF_STATUS;
}
-void onslaught_generator_deaththink()
+void ons_ControlPoint_Icon_Think()
{
- vector org;
- float i;
-
- if (!self.count)
- self.count = 40;
+ entity oself;
- self.nextthink = time + CP_THINKRATE;
++ self.nextthink = time + ONS_CP_THINKRATE;
- // White shockwave
- if(self.count==40||self.count==20)
+ if(autocvar_g_onslaught_cp_proxydecap)
{
- onslaught_generator_ring_spawn(self.origin);
- sound(self, CH_TRIGGER, "onslaught/shockwave.wav", VOL_BASE, ATTEN_NORM);
- }
+ float _enemy_count = 0;
+ float _friendly_count = 0;
+ float _dist;
+ entity _player;
- // Throw some gibs
- if(random() < 0.3)
- {
- i = random();
- if(i < 0.3)
- ons_throwgib(self.origin + '0 0 40', (100 * randomvec() - '1 1 1') * 11 + '0 0 20', "models/onslaught/gen_gib1.md3", 6, TRUE);
- else if(i > 0.7)
- ons_throwgib(self.origin + '0 0 40', (100 * randomvec() - '1 1 1') * 12 + '0 0 20', "models/onslaught/gen_gib2.md3", 6, TRUE);
- else
- ons_throwgib(self.origin + '0 0 40', (100 * randomvec() - '1 1 1') * 13 + '0 0 20', "models/onslaught/gen_gib3.md3", 6, TRUE);
- }
+ FOR_EACH_PLAYER(_player)
+ {
+ if(!_player.deadflag)
+ {
+ _dist = vlen(_player.origin - self.origin);
+ if(_dist < autocvar_g_onslaught_cp_proxydecap_distance)
+ {
+ if(SAME_TEAM(_player, self))
+ ++_friendly_count;
+ else
+ ++_enemy_count;
+ }
+ }
+ }
+
- _friendly_count = _friendly_count * (autocvar_g_onslaught_cp_proxydecap_dps * CP_THINKRATE);
- _enemy_count = _enemy_count * (autocvar_g_onslaught_cp_proxydecap_dps * CP_THINKRATE);
++ _friendly_count = _friendly_count * (autocvar_g_onslaught_cp_proxydecap_dps * ONS_CP_THINKRATE);
++ _enemy_count = _enemy_count * (autocvar_g_onslaught_cp_proxydecap_dps * ONS_CP_THINKRATE);
- // Spawn fire balls
- for(i=0;i < 10;++i)
+ self.health = bound(0, self.health + (_friendly_count - _enemy_count), self.max_health);
+ self.SendFlags |= CPSF_STATUS;
+ if(self.health <= 0)
+ {
+ ons_ControlPoint_Icon_Damage(self, self, 1, 0, self.origin, '0 0 0');
+ return;
+ }
+ }
+
+ if (time > self.pain_finished + 5)
{
- org = self.origin + randompos('-30 -30 -30' * i + '0 0 -20', '30 30 30' * i + '0 0 20');
- pointparticles(particleeffectnum("onslaught_generator_gib_explode"), org, '0 0 0', 1);
+ if(self.health < self.max_health)
+ {
+ self.health = self.health + self.count;
+ if (self.health >= self.max_health)
+ self.health = self.max_health;
+ WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
+ }
}
- // Short explosion sound + small explosion
- if(random() < 0.25)
+ if(self.owner.islinked != self.owner.waslinked)
{
- te_explosion(self.origin);
- sound(self, CH_TRIGGER, "weapons/grenade_impact.wav", VOL_BASE, ATTEN_NORM);
- }
+ // unteam the spawnpoint if needed
+ float t;
+ t = self.owner.team;
+ if(!self.owner.islinked)
+ self.owner.team = 0;
+
+ oself = self;
+ self = self.owner;
+ activator = self;
+ SUB_UseTargets ();
+ self = oself;
- // Particles
- org = self.origin + randompos(self.mins + '8 8 8', self.maxs + '-8 -8 -8');
- pointparticles(particleeffectnum("onslaught_generator_smallexplosion"), org, '0 0 0', 1);
+ self.owner.team = t;
- // rays
- if(random() > 0.25 )
- {
- onslaught_generator_ray_spawn(self.origin);
+ self.owner.waslinked = self.owner.islinked;
}
- // Final explosion
- if(self.count==1)
+ // damaged fx
+ if(random() < 0.6 - self.health / self.max_health)
{
- org = self.origin;
- te_explosion(org);
- onslaught_generator_shockwave_spawn(org);
- pointparticles(particleeffectnum("onslaught_generator_finalexplosion"), org, '0 0 0', 1);
- sound(self, CH_TRIGGER, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
- }
- else
- self.nextthink = time + 0.05;
-
- self.count = self.count - 1;
-}
+ pointparticles(particleeffectnum("electricity_sparks"), self.origin + randompos('-10 -10 -20', '10 10 20'), '0 0 0', 1);
-void onslaught_generator_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
- float i;
- if (damage <= 0)
- return;
- if(warmup_stage)
- return;
- if (attacker != self)
- {
- if (self.isshielded)
- {
- // this is protected by a shield, so ignore the damage
- if (time > self.pain_finished)
- if (IS_PLAYER(attacker))
- {
- play2(attacker, "onslaught/damageblockedbyshield.wav");
- self.pain_finished = time + 1;
- }
- return;
- }
- if (time > self.pain_finished)
- {
- self.pain_finished = time + 10;
- bprint(Team_ColoredFullName(self.team), " generator under attack!\n");
- play2team(self.team, "onslaught/generator_underattack.wav");
- }
- }
- self.health = self.health - damage;
- WaypointSprite_UpdateHealth(self.sprite, self.health);
- // choose an animation frame based on health
- self.frame = 10 * bound(0, (1 - self.health / self.max_health), 1);
- // see if the generator is still functional, or dying
- if (self.health > 0)
- {
-#ifdef ONSLAUGHT_SPAM
- float h, lh;
- lh = ceil(self.lasthealth / 100) * 100;
- h = ceil(self.health / 100) * 100;
- if(lh != h)
- bprint(Team_ColoredFullName(self.team), " generator has less than ", ftos(h), " health remaining\n");
-#endif
- self.lasthealth = self.health;
+ if(random() > 0.8)
+ sound(self, CH_PAIN, "onslaught/ons_spark1.wav", VOL_BASE, ATTEN_NORM);
+ else if (random() > 0.5)
+ sound(self, CH_PAIN, "onslaught/ons_spark2.wav", VOL_BASE, ATTEN_NORM);
}
- else if (!warmup_stage)
- {
- if (attacker == self)
- bprint(Team_ColoredFullName(self.team), " generator spontaneously exploded due to overtime!\n");
- else
- {
- string t;
- t = Team_ColoredFullName(attacker.team);
- bprint(Team_ColoredFullName(self.team), " generator destroyed by ", t, "!\n");
- }
- self.iscaptured = FALSE;
- self.islinked = FALSE;
- self.isshielded = FALSE;
- self.takedamage = DAMAGE_NO; // can't be hurt anymore
- self.event_damage = func_null; // won't do anything if hurt
- self.count = 0; // reset counter
- self.think = onslaught_generator_deaththink; // explosion sequence
- self.nextthink = time; // start exploding immediately
- self.think(); // do the first explosion now
+}
- WaypointSprite_UpdateMaxHealth(self.sprite, 0);
+void ons_ControlPoint_Icon_BuildThink()
+{
+ entity oself;
+ float a;
- self.nextthink = time + CP_THINKRATE;
- onslaught_updatelinks();
- }
++ self.nextthink = time + ONS_CP_THINKRATE;
- if(self.health <= 0)
- setmodel(self, "models/onslaught/generator_dead.md3");
- else if(self.health < self.max_health * 0.10)
- setmodel(self, "models/onslaught/generator_dmg9.md3");
- else if(self.health < self.max_health * 0.20)
- setmodel(self, "models/onslaught/generator_dmg8.md3");
- else if(self.health < self.max_health * 0.30)
- setmodel(self, "models/onslaught/generator_dmg7.md3");
- else if(self.health < self.max_health * 0.40)
- setmodel(self, "models/onslaught/generator_dmg6.md3");
- else if(self.health < self.max_health * 0.50)
- setmodel(self, "models/onslaught/generator_dmg5.md3");
- else if(self.health < self.max_health * 0.60)
- setmodel(self, "models/onslaught/generator_dmg4.md3");
- else if(self.health < self.max_health * 0.70)
- setmodel(self, "models/onslaught/generator_dmg3.md3");
- else if(self.health < self.max_health * 0.80)
- setmodel(self, "models/onslaught/generator_dmg2.md3");
- else if(self.health < self.max_health * 0.90)
- setmodel(self, "models/onslaught/generator_dmg1.md3");
- setsize(self, '-52 -52 -14', '52 52 75');
+ // only do this if there is power
+ a = ons_ControlPoint_CanBeLinked(self.owner, self.owner.team);
+ if(!a)
+ return;
- // Throw some flaming gibs on damage, more damage = more chance for gib
- if(random() < damage/220)
- {
- sound(self, CH_TRIGGER, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
- i = random();
- if(i < 0.3)
- ons_throwgib(hitloc + '0 0 20', force * -1, "models/onslaught/gen_gib1.md3", 5, TRUE);
- else if(i > 0.7)
- ons_throwgib(hitloc + '0 0 20', force * -1, "models/onslaught/gen_gib2.md3", 5, TRUE);
- else
- ons_throwgib(hitloc + '0 0 20', force * -1, "models/onslaught/gen_gib3.md3", 5, TRUE);
- }
- else
+ self.health = self.health + self.count;
+
+ self.SendFlags |= CPSF_STATUS;
+
+ if (self.health >= self.max_health)
{
- // particles on every hit
- pointparticles(particleeffectnum("sparks"), hitloc, force * -1, 1);
+ self.health = self.max_health;
- self.count = autocvar_g_onslaught_cp_regen * CP_THINKRATE; // slow repair rate from now on
++ self.count = autocvar_g_onslaught_cp_regen * ONS_CP_THINKRATE; // slow repair rate from now on
+ self.think = ons_ControlPoint_Icon_Think;
+ sound(self, CH_TRIGGER, "onslaught/controlpoint_built.wav", VOL_BASE, ATTEN_NORM);
+ self.owner.iscaptured = TRUE;
+ self.solid = SOLID_BBOX;
- //sound on every hit
- if (random() < 0.5)
- sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE, ATTEN_NORM);
- else
- sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE, ATTEN_NORM);
- }
+ pointparticles(particleeffectnum(sprintf("%s_cap", Static_Team_ColorName_Lower(self.owner.team))), self.owner.origin, '0 0 0', 1);
- //throw some gibs on damage
- if(random() < damage/200+0.2)
- if(random() < 0.5)
- ons_throwgib(hitloc + '0 0 20', randomvec()*360, "models/onslaught/gen_gib1.md3", 5, FALSE);
-}
+ WaypointSprite_UpdateMaxHealth(self.owner.sprite, self.max_health);
+ WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
-// update links after a delay
-void onslaught_generator_delayed()
-{
- onslaught_updatelinks();
- // now begin normal thinking
- self.think = onslaught_generator_think;
- self.nextthink = time;
-}
+ if(IS_PLAYER(self.owner.ons_toucher))
+ {
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ONSLAUGHT_CAPTURE, self.owner.ons_toucher.netname, self.owner.message);
+ Send_Notification(NOTIF_ALL_EXCEPT, self.owner.ons_toucher, MSG_CENTER, APP_TEAM_ENT_4(self.owner.ons_toucher, CENTER_ONS_CAPTURE_), self.owner.message);
+ Send_Notification(NOTIF_ONE, self.owner.ons_toucher, MSG_CENTER, CENTER_ONS_CAPTURE, self.owner.message);
+ PlayerScore_Add(self.owner.ons_toucher, SP_ONS_CAPS, 1);
+ PlayerTeamScore_AddScore(self.owner.ons_toucher, 10);
+ }
+
+ self.owner.ons_toucher = world;
-string onslaught_generator_waypointsprite_for_team(entity e, float t)
-{
- if(t == e.team)
- {
- if(e.team == NUM_TEAM_1)
- return "ons-gen-red";
- else if(e.team == NUM_TEAM_2)
- return "ons-gen-blue";
+ onslaught_updatelinks();
+
+ // Use targets now (somebody make sure this is in the right place..)
+ oself = self;
+ self = self.owner;
+ activator = self;
+ SUB_UseTargets ();
+ self = oself;
+
+ self.SendFlags |= CPSF_SETUP;
}
- if(e.isshielded)
- return "ons-gen-shielded";
- if(e.team == NUM_TEAM_1)
- return "ons-gen-red";
- else if(e.team == NUM_TEAM_2)
- return "ons-gen-blue";
- return "";
+ if(self.owner.model != "models/onslaught/controlpoint_pad2.md3")
+ setmodel_fixsize(self.owner, "models/onslaught/controlpoint_pad2.md3");
+
+ if(random() < 0.9 - self.health / self.max_health)
+ pointparticles(particleeffectnum("rage"), self.origin + 10 * randomvec(), '0 0 -1', 1);
}
-void onslaught_generator_updatesprite(entity e)
+void ons_ControlPoint_Icon_Spawn(entity cp, entity player)
{
- string s1, s2, s3;
- s1 = onslaught_generator_waypointsprite_for_team(e, NUM_TEAM_1);
- s2 = onslaught_generator_waypointsprite_for_team(e, NUM_TEAM_2);
- s3 = onslaught_generator_waypointsprite_for_team(e, -1);
- WaypointSprite_UpdateSprites(e.sprite, s1, s2, s3);
+ entity e = spawn();
+
+ setsize(e, CPICON_MIN, CPICON_MAX);
+ setorigin(e, cp.origin + CPICON_OFFSET);
+
+ e.classname = "onslaught_controlpoint_icon";
+ e.owner = cp;
+ e.max_health = autocvar_g_onslaught_cp_health;
+ e.health = autocvar_g_onslaught_cp_buildhealth;
+ e.solid = SOLID_NOT;
+ e.takedamage = DAMAGE_AIM;
+ e.bot_attack = TRUE;
+ e.event_damage = ons_ControlPoint_Icon_Damage;
+ e.team = player.team;
+ e.colormap = 1024 + (e.team - 1) * 17;
- e.count = (e.max_health - e.health) * CP_THINKRATE / autocvar_g_onslaught_cp_buildtime; // how long it takes to build
++ e.count = (e.max_health - e.health) * ONS_CP_THINKRATE / autocvar_g_onslaught_cp_buildtime; // how long it takes to build
+
+ sound(e, CH_TRIGGER, "onslaught/controlpoint_build.wav", VOL_BASE, ATTEN_NORM);
+
+ cp.goalentity = e;
+ cp.team = e.team;
+ cp.colormap = e.colormap;
- if(e.lastteam != e.team + 2 || e.lastshielded != e.isshielded)
- {
- e.lastteam = e.team + 2;
- e.lastshielded = e.isshielded;
- if(e.lastshielded)
- {
- if(e.team == NUM_TEAM_1 || e.team == NUM_TEAM_2)
- WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, 0.5 * colormapPaletteColor(e.team - 1, FALSE));
- else
- WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0.5 0.5 0.5');
- }
- else
- {
- if(e.team == NUM_TEAM_1 || e.team == NUM_TEAM_2)
- WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, colormapPaletteColor(e.team - 1, FALSE));
- else
- WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0.75 0.75 0.75');
- }
- WaypointSprite_Ping(e.sprite);
- }
+ pointparticles(particleeffectnum(sprintf("%sflag_touch", Static_Team_ColorName_Lower(player.team))), e.origin, '0 0 0', 1);
+
- WaypointSprite_UpdateBuildFinished(cp.sprite, time + (e.max_health - e.health) / (e.count / CP_THINKRATE));
++ WaypointSprite_UpdateBuildFinished(cp.sprite, time + (e.max_health - e.health) / (e.count / ONS_CP_THINKRATE));
+ WaypointSprite_UpdateRule(cp.sprite,cp.team,SPRITERULE_TEAMPLAY);
+ cp.sprite.SendFlags |= 16;
+
+ onslaught_controlpoint_icon_link(e, ons_ControlPoint_Icon_BuildThink);
}
-string onslaught_controlpoint_waypointsprite_for_team(entity e, float t)
+string ons_ControlPoint_Waypoint(entity e)
{
float a;
- if(t != -1)
+ if(e.team)
{
- a = onslaught_controlpoint_attackable(e, t);
- if(a == 3 || a == 4) // ATTACK/TOUCH THIS ONE NOW
- {
- if(e.team == NUM_TEAM_1)
- return "ons-cp-atck-red";
- else if(e.team == NUM_TEAM_2)
- return "ons-cp-atck-blue";
- else
- return "ons-cp-atck-neut";
- }
- else if(a == -2) // DEFEND THIS ONE NOW
- {
- if(e.team == NUM_TEAM_1)
- return "ons-cp-dfnd-red";
- else if(e.team == NUM_TEAM_2)
- return "ons-cp-dfnd-blue";
- }
- else if(e.team == t || a == -1 || a == 1) // own point, or fire at it
- {
- if(e.team == NUM_TEAM_1)
- return "ons-cp-red";
- else if(e.team == NUM_TEAM_2)
- return "ons-cp-blue";
- }
- else if(a == 2) // touch it
- return "ons-cp-neut";
+ a = ons_ControlPoint_Attackable(e, e.team);
+
+ if(a == -2) { return "ons-cp-dfnd"; } // defend now
+ if(a == -1 || a == 1 || a == 2) { return "ons-cp"; } // touch
+ if(a == 3 || a == 4) { return "ons-cp-atck"; } // attack
}
else
- {
- if(e.team == NUM_TEAM_1)
- return "ons-cp-red";
- else if(e.team == NUM_TEAM_2)
- return "ons-cp-blue";
- else
- return "ons-cp-neut";
- }
+ return "ons-cp";
+
return "";
}
-void onslaught_controlpoint_updatesprite(entity e)
+void ons_ControlPoint_UpdateSprite(entity e)
{
- string s1, s2, s3;
- s1 = onslaught_controlpoint_waypointsprite_for_team(e, NUM_TEAM_1);
- s2 = onslaught_controlpoint_waypointsprite_for_team(e, NUM_TEAM_2);
- s3 = onslaught_controlpoint_waypointsprite_for_team(e, -1);
- WaypointSprite_UpdateSprites(e.sprite, s1, s2, s3);
+ string s1;
+ s1 = ons_ControlPoint_Waypoint(e);
+ WaypointSprite_UpdateSprites(e.sprite, s1, s1, s1);
float sh;
- sh = !(onslaught_controlpoint_can_be_linked(e, NUM_TEAM_1) || onslaught_controlpoint_can_be_linked(e, NUM_TEAM_2));
+ sh = !(ons_ControlPoint_CanBeLinked(e, NUM_TEAM_1) || ons_ControlPoint_CanBeLinked(e, NUM_TEAM_2) || ons_ControlPoint_CanBeLinked(e, NUM_TEAM_3) || ons_ControlPoint_CanBeLinked(e, NUM_TEAM_4));
if(e.lastteam != e.team + 2 || e.lastshielded != sh || e.iscaptured != e.lastcaptured)
{
}
if(e.lastshielded)
{
- if(e.team == NUM_TEAM_1 || e.team == NUM_TEAM_2)
+ if(e.team)
WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, 0.5 * colormapPaletteColor(e.team - 1, FALSE));
else
WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, '0.5 0.5 0.5');
}
else
{
- if(e.team == NUM_TEAM_1 || e.team == NUM_TEAM_2)
+ if(e.team)
WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, colormapPaletteColor(e.team - 1, FALSE));
else
WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, '0.75 0.75 0.75');
}
}
-void onslaught_generator_reset()
+void ons_ControlPoint_Touch()
{
- self.team = self.team_saved;
- self.lasthealth = self.max_health = self.health = autocvar_g_onslaught_gen_health;
- self.takedamage = DAMAGE_AIM;
- self.bot_attack = TRUE;
- self.iscaptured = TRUE;
- self.islinked = TRUE;
- self.isshielded = TRUE;
- self.enemy.solid = SOLID_NOT;
- self.think = onslaught_generator_delayed;
- self.nextthink = time + 0.2;
- setmodel(self, "models/onslaught/generator.md3");
- setsize(self, '-52 -52 -14', '52 52 75');
-
- if(!self.noalign)
+ entity toucher = other;
+ float attackable;
+
+ if((toucher.vehicle_flags & VHF_ISVEHICLE) && toucher.owner)
+ if(autocvar_g_onslaught_allow_vehicle_touch)
+ toucher = toucher.owner;
+ else
+ return;
+
+ if(!IS_PLAYER(toucher)) { return; }
++ if(toucher.frozen) { return; }
+ if(toucher.deadflag != DEAD_NO) { return; }
+
+ if ( SAME_TEAM(self,toucher) )
+ if ( self.iscaptured )
{
- setorigin(self, self.origin + '0 0 20');
- droptofloor();
+ if(time <= toucher.teleport_antispam)
+ Send_Notification(NOTIF_ONE, toucher, MSG_CENTER, CENTER_ONS_TELEPORT_ANTISPAM, rint(toucher.teleport_antispam - time));
+ else
+ Send_Notification(NOTIF_ONE, toucher, MSG_CENTER, CENTER_ONS_TELEPORT);
}
+
+ attackable = ons_ControlPoint_Attackable(self, toucher.team);
+ if(attackable != 2 && attackable != 4)
+ return;
+ // we've verified that this player has a legitimate claim to this point,
+ // so start building the captured point icon (which only captures this
+ // point if it successfully builds without being destroyed first)
+ ons_ControlPoint_Icon_Spawn(self, toucher);
+
+ self.ons_toucher = toucher;
- WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
- WaypointSprite_UpdateHealth(self.sprite, self.health);
+ onslaught_updatelinks();
}
-/*QUAKED spawnfunc_onslaught_generator (0 .5 .8) (-32 -32 -24) (32 32 64)
- Base generator.
-
- spawnfunc_onslaught_link entities can target this.
-
-keys:
-"team" - team that owns this generator (5 = red, 14 = blue, etc), MUST BE SET.
-"targetname" - name that spawnfunc_onslaught_link entities will use to target this.
- */
-void spawnfunc_onslaught_generator()
+void ons_ControlPoint_Think()
{
- self.nextthink = time + CP_THINKRATE;
- if (!g_onslaught)
- {
- remove(self);
- return;
- }
-
- //entity e;
- precache_model("models/onslaught/generator.md3");
- precache_model("models/onslaught/generator_shield.md3");
- precache_model("models/onslaught/generator_dmg1.md3");
- precache_model("models/onslaught/generator_dmg2.md3");
- precache_model("models/onslaught/generator_dmg3.md3");
- precache_model("models/onslaught/generator_dmg4.md3");
- precache_model("models/onslaught/generator_dmg5.md3");
- precache_model("models/onslaught/generator_dmg6.md3");
- precache_model("models/onslaught/generator_dmg7.md3");
- precache_model("models/onslaught/generator_dmg8.md3");
- precache_model("models/onslaught/generator_dmg9.md3");
- precache_model("models/onslaught/generator_dead.md3");
- precache_model("models/onslaught/shockwave.md3");
- precache_model("models/onslaught/shockwavetransring.md3");
- precache_model("models/onslaught/gen_gib1.md3");
- precache_model("models/onslaught/gen_gib2.md3");
- precache_model("models/onslaught/gen_gib3.md3");
- precache_model("models/onslaught/ons_ray.md3");
- precache_sound("onslaught/generator_decay.wav");
- precache_sound("weapons/grenade_impact.wav");
- precache_sound("weapons/rocket_impact.wav");
- precache_sound("onslaught/generator_underattack.wav");
- precache_sound("onslaught/shockwave.wav");
- precache_sound("onslaught/ons_hit1.wav");
- precache_sound("onslaught/ons_hit2.wav");
- precache_sound("onslaught/electricity_explode.wav");
- if (!self.team)
- objerror("team must be set");
-
- if(self.team == NUM_TEAM_1)
- ons_red_generator = self;
++ self.nextthink = time + ONS_CP_THINKRATE;
+ CSQCMODEL_AUTOUPDATE();
+}
- if(self.team == NUM_TEAM_2)
- ons_blue_generator = self;
+void ons_ControlPoint_Reset()
+{
+ if(self.goalentity)
+ remove(self.goalentity);
- self.team_saved = self.team;
- self.colormap = 1024 + (self.team - 1) * 17;
- self.solid = SOLID_BBOX;
- self.movetype = MOVETYPE_NONE;
- self.lasthealth = self.max_health = self.health = autocvar_g_onslaught_gen_health;
- setmodel(self, "models/onslaught/generator.md3");
- setsize(self, '-52 -52 -14', '52 52 75');
- setorigin(self, self.origin);
- self.takedamage = DAMAGE_AIM;
- self.bot_attack = TRUE;
- self.event_damage = onslaught_generator_damage;
- self.iscaptured = TRUE;
- self.islinked = TRUE;
+ self.goalentity = world;
+ self.team = 0;
+ self.colormap = 1024;
+ self.iscaptured = FALSE;
+ self.islinked = FALSE;
self.isshielded = TRUE;
- // helper entity that create fx when generator is damaged
- onslaught_generator_damage_spawn(self);
- // spawn shield model which indicates whether this can be damaged
- self.enemy = spawn();
- setattachment(self.enemy , self, "");
- self.enemy.classname = "onslaught_generator_shield";
- self.enemy.solid = SOLID_NOT;
- self.enemy.movetype = MOVETYPE_NONE;
- self.enemy.effects = EF_ADDITIVE;
- setmodel(self.enemy, "models/onslaught/generator_shield.md3");
- //setorigin(e, self.origin);
- self.enemy.colormap = self.colormap;
- self.enemy.team = self.team;
- //self.think = onslaught_generator_delayed;
- //self.nextthink = time + 0.2;
- InitializeEntity(self, onslaught_generator_delayed, INITPRIO_LAST);
-
- WaypointSprite_SpawnFixed(string_null, self.origin + '0 0 128', self, sprite, RADARICON_NONE, '0 0 0');
- WaypointSprite_UpdateRule(self.sprite, NUM_TEAM_2, SPRITERULE_TEAMPLAY);
- WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
- WaypointSprite_UpdateHealth(self.sprite, self.health);
+ self.think = ons_ControlPoint_Think;
+ self.ons_toucher = world;
- self.nextthink = time + CP_THINKRATE;
++ self.nextthink = time + ONS_CP_THINKRATE;
+ setmodel_fixsize(self, "models/onslaught/controlpoint_pad.md3");
- waypoint_spawnforitem(self);
+ WaypointSprite_UpdateMaxHealth(self.sprite, 0);
+ WaypointSprite_UpdateRule(self.sprite,self.team,SPRITERULE_TEAMPLAY);
onslaught_updatelinks();
- self.reset = onslaught_generator_reset;
+ activator = self;
+ SUB_UseTargets(); // to reset the structures, playerspawns etc.
+
+ CSQCMODEL_AUTOUPDATE();
}
-.float waslinked;
-.float cp_bob_spd;
-.vector cp_origin, cp_bob_origin, cp_bob_dmg;
+void ons_DelayedControlPoint_Setup(void)
+{
+ onslaught_updatelinks();
+
+ // captureshield setup
+ ons_CaptureShield_Spawn(self, FALSE);
-float ons_notification_time_team1;
-float ons_notification_time_team2;
+ CSQCMODEL_AUTOINIT();
+}
-void onslaught_controlpoint_icon_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+void ons_ControlPoint_Setup(entity cp)
{
- entity oself;
- float nag;
+ // declarations
+ self = cp; // for later usage with droptofloor()
+
+ // main setup
+ cp.ons_worldcpnext = ons_worldcplist; // link control point into ons_worldcplist
+ ons_worldcplist = cp;
+
+ cp.netname = "Control point";
+ cp.team = 0;
+ cp.solid = SOLID_BBOX;
+ cp.movetype = MOVETYPE_NONE;
+ cp.touch = ons_ControlPoint_Touch;
+ cp.think = ons_ControlPoint_Think;
- cp.nextthink = time + CP_THINKRATE;
++ cp.nextthink = time + ONS_CP_THINKRATE;
+ cp.reset = ons_ControlPoint_Reset;
+ cp.colormap = 1024;
+ cp.iscaptured = FALSE;
+ cp.islinked = FALSE;
+ cp.isshielded = TRUE;
+
+ if(cp.message == "") { cp.message = "a"; }
- if (damage <= 0)
- return;
- if (self.owner.isshielded)
+ // precache - TODO: clean up!
+ precache_model("models/onslaught/controlpoint_pad.md3");
+ precache_model("models/onslaught/controlpoint_pad2.md3");
+ precache_model("models/onslaught/controlpoint_shield.md3");
+ precache_model("models/onslaught/controlpoint_icon.md3");
+ precache_model("models/onslaught/controlpoint_icon_dmg1.md3");
+ precache_model("models/onslaught/controlpoint_icon_dmg2.md3");
+ precache_model("models/onslaught/controlpoint_icon_dmg3.md3");
+ precache_model("models/onslaught/controlpoint_icon_gib1.md3");
+ precache_model("models/onslaught/controlpoint_icon_gib2.md3");
+ precache_model("models/onslaught/controlpoint_icon_gib4.md3");
+ precache_sound("onslaught/controlpoint_build.wav");
+ precache_sound("onslaught/controlpoint_built.wav");
+ precache_sound("weapons/grenade_impact.wav");
+ precache_sound("onslaught/damageblockedbyshield.wav");
+ precache_sound("onslaught/controlpoint_underattack.wav");
+ precache_sound("onslaught/ons_spark1.wav");
+ precache_sound("onslaught/ons_spark2.wav");
+
+ // appearence
+ setmodel_fixsize(cp, "models/onslaught/controlpoint_pad.md3");
+
+ // control point placement
+ if((cp.spawnflags & 1) || cp.noalign) // don't drop to floor, just stay at fixed location
{
- // this is protected by a shield, so ignore the damage
- if (time > self.pain_finished)
- if (IS_PLAYER(attacker))
- {
- play2(attacker, "onslaught/damageblockedbyshield.wav");
- self.pain_finished = time + 1;
- }
- return;
+ cp.noalign = TRUE;
+ cp.movetype = MOVETYPE_NONE;
}
-
- if (IS_PLAYER(attacker))
+ else // drop to floor, automatically find a platform and set that as spawn origin
{
- nag = FALSE;
- if(self.team == NUM_TEAM_1)
- {
- if(time - ons_notification_time_team1 > 10)
- {
- nag = TRUE;
- ons_notification_time_team1 = time;
- }
- }
- else if(self.team == NUM_TEAM_2)
+ setorigin(cp, cp.origin + '0 0 20');
+ cp.noalign = FALSE;
+ self = cp;
+ droptofloor();
+ cp.movetype = MOVETYPE_TOSS;
+ }
+
+ // waypointsprites
+ WaypointSprite_SpawnFixed(string_null, self.origin + CPGEN_WAYPOINT_OFFSET, self, sprite, RADARICON_NONE, '0 0 0');
+ WaypointSprite_UpdateRule(self.sprite, self.team, SPRITERULE_TEAMPLAY);
+
+ InitializeEntity(cp, ons_DelayedControlPoint_Setup, INITPRIO_SETLOCATION);
+}
+
+
+// =========================
+// Main Generator Functions
+// =========================
+
+string ons_Generator_Waypoint(entity e)
+{
+ if(e.isshielded)
+ return "ons-gen-shielded";
+ return "ons-gen";
+}
+
+void ons_Generator_UpdateSprite(entity e)
+{
+ string s1;
+ s1 = ons_Generator_Waypoint(e);
+ WaypointSprite_UpdateSprites(e.sprite, s1, s1, s1);
+
+ if(e.lastteam != e.team + 2 || e.lastshielded != e.isshielded)
+ {
+ e.lastteam = e.team + 2;
+ e.lastshielded = e.isshielded;
+ if(e.lastshielded)
{
- if(time - ons_notification_time_team2 > 10)
- {
- nag = TRUE;
- ons_notification_time_team2 = time;
- }
+ if(e.team)
+ WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, 0.5 * colormapPaletteColor(e.team - 1, FALSE));
+ else
+ WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0.5 0.5 0.5');
}
else
- nag = TRUE;
-
- if(nag)
- play2team(self.team, "onslaught/controlpoint_underattack.wav");
+ {
+ if(e.team)
+ WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, colormapPaletteColor(e.team - 1, FALSE));
+ else
+ WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_GENERATOR, '0.75 0.75 0.75');
+ }
+ WaypointSprite_Ping(e.sprite);
}
+}
+
+void ons_GeneratorDamage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+ if(damage <= 0) { return; }
+ if(warmup_stage || gameover) { return; }
+ if(!round_handler_IsRoundStarted()) { return; }
+ if (attacker != self)
+ {
+ if (self.isshielded)
+ {
+ // this is protected by a shield, so ignore the damage
+ if (time > self.pain_finished)
+ if (IS_PLAYER(attacker))
+ {
+ play2(attacker, "onslaught/damageblockedbyshield.wav");
+ attacker.typehitsound += 1;
+ self.pain_finished = time + 1;
+ }
+ return;
+ }
+ if (time > self.pain_finished)
+ {
+ self.pain_finished = time + 10;
+ entity head;
+ FOR_EACH_REALPLAYER(head) if(SAME_TEAM(head, self)) { Send_Notification(NOTIF_ONE, head, MSG_CENTER, CENTER_GENERATOR_UNDERATTACK); }
+ play2team(self.team, "onslaught/generator_underattack.wav");
+ }
+ }
self.health = self.health - damage;
- if(self.owner.iscaptured)
- WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
- else
- WaypointSprite_UpdateBuildFinished(self.owner.sprite, time + (self.max_health - self.health) / (self.count / sys_frametime));
- self.pain_finished = time + 1;
- self.punchangle = (2 * randomvec() - '1 1 1') * 45;
- self.cp_bob_dmg_z = (2 * random() - 1) * 15;
- // colormod flash when shot
- self.colormod = '2 2 2';
- // particles on every hit
- pointparticles(particleeffectnum("sparks"), hitloc, force*-1, 1);
- //sound on every hit
- if (random() < 0.5)
- sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE+0.3, ATTEN_NORM);
+ WaypointSprite_UpdateHealth(self.sprite, self.health);
+ // choose an animation frame based on health
+ self.frame = 10 * bound(0, (1 - self.health / self.max_health), 1);
+ // see if the generator is still functional, or dying
+ if (self.health > 0)
+ {
+ self.lasthealth = self.health;
+ }
else
- sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE+0.3, ATTEN_NORM);
-
- if (self.health < 0)
{
- sound(self, CH_TRIGGER, "weapons/grenade_impact.wav", VOL_BASE, ATTEN_NORM);
- pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
+ if (attacker == self)
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(self.team, INFO_ONSLAUGHT_GENDESTROYED_OVERTIME_));
+ else
{
- string t;
- t = Team_ColoredFullName(attacker.team);
- bprint(Team_ColoredFullName(self.team), " ", self.message, " control point destroyed by ", t, "\n");
- ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 25, "models/onslaught/controlpoint_icon_gib1.md3", 3, FALSE);
- ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 45, "models/onslaught/controlpoint_icon_gib2.md3", 3, FALSE);
- ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 45, "models/onslaught/controlpoint_icon_gib2.md3", 3, FALSE);
- ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 75, "models/onslaught/controlpoint_icon_gib4.md3", 3, FALSE);
- ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 75, "models/onslaught/controlpoint_icon_gib4.md3", 3, FALSE);
- ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 75, "models/onslaught/controlpoint_icon_gib4.md3", 3, FALSE);
- ons_throwgib(self.origin, (2 * randomvec() - '1 1 1') * 75, "models/onslaught/controlpoint_icon_gib4.md3", 3, FALSE);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(self.team, INFO_ONSLAUGHT_GENDESTROYED_));
+ PlayerScore_Add(attacker, SP_SCORE, 100);
}
- self.owner.goalentity = world;
- self.owner.islinked = FALSE;
- self.owner.iscaptured = FALSE;
- self.owner.team = 0;
- self.owner.colormap = 1024;
+ self.iscaptured = FALSE;
+ self.islinked = FALSE;
+ self.isshielded = FALSE;
+ self.takedamage = DAMAGE_NO; // can't be hurt anymore
+ self.event_damage = func_null; // won't do anything if hurt
+ self.count = 0; // reset counter
+ self.think = func_null;
+ self.nextthink = 0;
+ //self.think(); // do the first explosion now
- WaypointSprite_UpdateMaxHealth(self.owner.sprite, 0);
+ WaypointSprite_UpdateMaxHealth(self.sprite, 0);
+ WaypointSprite_Ping(self.sprite);
+ //WaypointSprite_Kill(self.sprite); // can't do this yet, code too poor
onslaught_updatelinks();
+ }
- // Use targets now (somebody make sure this is in the right place..)
- oself = self;
- self = self.owner;
- activator = self;
- SUB_UseTargets ();
- self = oself;
-
-
- self.owner.waslinked = self.owner.islinked;
- if(self.owner.model != "models/onslaught/controlpoint_pad.md3")
- setmodel(self.owner, "models/onslaught/controlpoint_pad.md3");
- //setsize(self, '-32 -32 0', '32 32 8');
+ // Throw some flaming gibs on damage, more damage = more chance for gib
+ if(random() < damage/220)
+ {
+ sound(self, CH_TRIGGER, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
+ }
+ else
+ {
+ // particles on every hit
+ pointparticles(particleeffectnum("sparks"), hitloc, force * -1, 1);
- remove(self);
+ //sound on every hit
+ if (random() < 0.5)
+ sound(self, CH_TRIGGER, "onslaught/ons_hit1.wav", VOL_BASE, ATTEN_NORM);
+ else
+ sound(self, CH_TRIGGER, "onslaught/ons_hit2.wav", VOL_BASE, ATTEN_NORM);
}
+
+ self.SendFlags |= GSF_STATUS;
}
-void onslaught_controlpoint_icon_think()
+void ons_GeneratorThink()
{
- entity oself;
- self.nextthink = time + sys_frametime;
-
- if(autocvar_g_onslaught_cp_proxydecap)
+ entity e;
+ self.nextthink = time + GEN_THINKRATE;
+ if (!gameover)
{
- float _enemy_count = 0;
- float _friendly_count = 0;
- float _dist;
- entity _player;
-
- FOR_EACH_PLAYER(_player)
+ if(!self.isshielded && self.wait < time)
{
- if(!_player.deadflag)
+ self.wait = time + 5;
+ FOR_EACH_REALPLAYER(e)
{
- _dist = vlen(_player.origin - self.origin);
- if(_dist < autocvar_g_onslaught_cp_proxydecap_distance)
- {
- if(_player.team == self.team)
- ++_friendly_count;
- else
- ++_enemy_count;
+ if(SAME_TEAM(e, self))
+ {
+ Send_Notification(NOTIF_ONE, e, MSG_CENTER, CENTER_ONS_NOTSHIELDED_TEAM);
+ soundto(MSG_ONE, e, CHAN_AUTO, "kh/alarm.wav", VOL_BASE, ATTEN_NONE); // FIXME: unique sound?
}
+ else
+ Send_Notification(NOTIF_ONE, e, MSG_CENTER, APP_TEAM_NUM_4(self.team, CENTER_ONS_NOTSHIELDED_));
}
}
+ }
+}
+
+void ons_GeneratorReset()
+{
+ self.team = self.team_saved;
+ self.lasthealth = self.max_health = self.health = autocvar_g_onslaught_gen_health;
+ self.takedamage = DAMAGE_AIM;
+ self.bot_attack = TRUE;
+ self.iscaptured = TRUE;
+ self.islinked = TRUE;
+ self.isshielded = TRUE;
+ self.event_damage = ons_GeneratorDamage;
+ self.think = ons_GeneratorThink;
+ self.nextthink = time + GEN_THINKRATE;
+
+ Net_LinkEntity(self, FALSE, 0, generator_send);
+
+ self.SendFlags = GSF_SETUP; // just incase
+ self.SendFlags |= GSF_STATUS;
- _friendly_count = _friendly_count * (autocvar_g_onslaught_cp_proxydecap_dps * sys_frametime);
- _enemy_count = _enemy_count * (autocvar_g_onslaught_cp_proxydecap_dps * sys_frametime);
+ WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
+ WaypointSprite_UpdateHealth(self.sprite, self.health);
+ WaypointSprite_UpdateRule(self.sprite,self.team,SPRITERULE_TEAMPLAY);
+
+ onslaught_updatelinks();
+}
- self.health = bound(0, self.health + (_friendly_count - _enemy_count), self.max_health);
- if(self.health <= 0)
- {
- onslaught_controlpoint_icon_damage(self, self, 1, 0, self.origin, '0 0 0');
- return;
- }
- }
+void ons_DelayedGeneratorSetup()
+{
+ // bot waypoints
+ waypoint_spawnforitem_force(self, self.origin);
+ self.nearestwaypointtimeout = 0; // activate waypointing again
+ self.bot_basewaypoint = self.nearestwaypoint;
- if (time > self.pain_finished + 5)
+ // captureshield setup
+ ons_CaptureShield_Spawn(self, TRUE);
+
+ onslaught_updatelinks();
+
+ Net_LinkEntity(self, FALSE, 0, generator_send);
+}
+
+
+void onslaught_generator_touch()
+{
+ if ( IS_PLAYER(other) )
+ if ( SAME_TEAM(self,other) )
+ if ( self.iscaptured )
{
- if(self.health < self.max_health)
- {
- self.health = self.health + self.count;
- if (self.health >= self.max_health)
- self.health = self.max_health;
- WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
- }
+ Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_ONS_TELEPORT);
}
- if (self.health < self.max_health * 0.25)
- setmodel(self, "models/onslaught/controlpoint_icon_dmg3.md3");
- else if (self.health < self.max_health * 0.50)
- setmodel(self, "models/onslaught/controlpoint_icon_dmg2.md3");
- else if (self.health < self.max_health * 0.75)
- setmodel(self, "models/onslaught/controlpoint_icon_dmg1.md3");
- else if (self.health < self.max_health * 0.90)
- setmodel(self, "models/onslaught/controlpoint_icon.md3");
- // colormod flash when shot
- self.colormod = '1 1 1' * (2 - bound(0, (self.pain_finished - time) / 10, 1));
+}
- if(self.owner.islinked != self.owner.waslinked)
- {
- // unteam the spawnpoint if needed
- float t;
- t = self.owner.team;
- if(!self.owner.islinked)
- self.owner.team = 0;
+void ons_GeneratorSetup(entity gen) // called when spawning a generator entity on the map as a spawnfunc
+{
+ // declarations
+ float teamnumber = gen.team;
+ self = gen; // for later usage with droptofloor()
+
+ // main setup
+ gen.ons_worldgeneratornext = ons_worldgeneratorlist; // link generator into ons_worldgeneratorlist
+ ons_worldgeneratorlist = gen;
+
+ gen.netname = sprintf("%s generator", Team_ColoredFullName(teamnumber));
+ gen.classname = "onslaught_generator";
+ gen.solid = SOLID_BBOX;
+ gen.team_saved = teamnumber;
+ gen.movetype = MOVETYPE_NONE;
+ gen.lasthealth = gen.max_health = gen.health = autocvar_g_onslaught_gen_health;
+ gen.takedamage = DAMAGE_AIM;
+ gen.bot_attack = TRUE;
+ gen.event_damage = ons_GeneratorDamage;
+ gen.reset = ons_GeneratorReset;
+ gen.think = ons_GeneratorThink;
+ gen.nextthink = time + GEN_THINKRATE;
+ gen.iscaptured = TRUE;
+ gen.islinked = TRUE;
+ gen.isshielded = TRUE;
+ gen.touch = onslaught_generator_touch;
+
+ // precache - TODO: clean up!
+ precache_model("models/onslaught/generator_shield.md3");
+ precache_model("models/onslaught/gen_gib1.md3");
+ precache_model("models/onslaught/gen_gib2.md3");
+ precache_model("models/onslaught/gen_gib3.md3");
+ precache_sound("onslaught/generator_decay.wav");
+ precache_sound("weapons/grenade_impact.wav");
+ precache_sound("weapons/rocket_impact.wav");
+ precache_sound("onslaught/generator_underattack.wav");
+ precache_sound("onslaught/shockwave.wav");
+ precache_sound("onslaught/ons_hit1.wav");
+ precache_sound("onslaught/ons_hit2.wav");
+ precache_sound("onslaught/generator_underattack.wav");
+
+ // appearence
+ // model handled by CSQC
+ setsize(gen, GENERATOR_MIN, GENERATOR_MAX);
+ setorigin(gen, (gen.origin + CPGEN_SPAWN_OFFSET));
+ gen.colormap = 1024 + (teamnumber - 1) * 17;
+
+ // generator placement
+ self = gen;
+ droptofloor();
+
+ // waypointsprites
+ WaypointSprite_SpawnFixed(string_null, self.origin + CPGEN_WAYPOINT_OFFSET, self, sprite, RADARICON_NONE, '0 0 0');
+ WaypointSprite_UpdateRule(self.sprite, self.team, SPRITERULE_TEAMPLAY);
+ WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
+ WaypointSprite_UpdateHealth(self.sprite, self.health);
+
+ InitializeEntity(gen, ons_DelayedGeneratorSetup, INITPRIO_SETLOCATION);
+}
- oself = self;
- self = self.owner;
- activator = self;
- SUB_UseTargets ();
- self = oself;
- self.owner.team = t;
+// ===============
+// Round Handler
+// ===============
- self.owner.waslinked = self.owner.islinked;
+float total_generators, redowned, blueowned, yellowowned, pinkowned;
+void Onslaught_count_generators()
+{
+ entity e;
+ total_generators = redowned = blueowned = yellowowned = pinkowned = 0;
+ for(e = ons_worldgeneratorlist; e; e = e.ons_worldgeneratornext)
+ {
+ ++total_generators;
+ redowned += (e.team == NUM_TEAM_1 && e.health > 0);
+ blueowned += (e.team == NUM_TEAM_2 && e.health > 0);
+ yellowowned += (e.team == NUM_TEAM_3 && e.health > 0);
+ pinkowned += (e.team == NUM_TEAM_4 && e.health > 0);
}
+}
- if (self.punchangle_x > 0)
+float Onslaught_GetWinnerTeam()
+{
+ float winner_team = 0;
+ if(redowned > 0)
+ winner_team = NUM_TEAM_1;
+ if(blueowned > 0)
{
- self.punchangle_x = self.punchangle_x - 60 * sys_frametime;
- if (self.punchangle_x < 0)
- self.punchangle_x = 0;
+ if(winner_team) return 0;
+ winner_team = NUM_TEAM_2;
}
- else if (self.punchangle_x < 0)
+ if(yellowowned > 0)
{
- self.punchangle_x = self.punchangle_x + 60 * sys_frametime;
- if (self.punchangle_x > 0)
- self.punchangle_x = 0;
+ if(winner_team) return 0;
+ winner_team = NUM_TEAM_3;
}
-
- if (self.punchangle_y > 0)
+ if(pinkowned > 0)
{
- self.punchangle_y = self.punchangle_y - 60 * sys_frametime;
- if (self.punchangle_y < 0)
- self.punchangle_y = 0;
+ if(winner_team) return 0;
+ winner_team = NUM_TEAM_4;
}
- else if (self.punchangle_y < 0)
+ if(winner_team)
+ return winner_team;
+ return -1; // no generators left?
+}
+
+#define ONS_OWNED_GENERATORS() ((redowned > 0) + (blueowned > 0) + (yellowowned > 0) + (pinkowned > 0))
+#define ONS_OWNED_GENERATORS_OK() (ONS_OWNED_GENERATORS() > 1)
+float Onslaught_CheckWinner()
+{
+ entity e;
+
+ if ((autocvar_timelimit && time > game_starttime + autocvar_timelimit * 60) || (round_handler_GetEndTime() > 0 && round_handler_GetEndTime() - time <= 0))
{
- self.punchangle_y = self.punchangle_y + 60 * sys_frametime;
- if (self.punchangle_y > 0)
- self.punchangle_y = 0;
+ ons_stalemate = TRUE;
+
+ if (!wpforenemy_announced)
+ {
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_OVERTIME_CONTROLPOINT);
+ sound(world, CH_INFO, "onslaught/generator_decay.wav", VOL_BASE, ATTEN_NONE);
+
+ wpforenemy_announced = TRUE;
+ }
+
+ entity tmp_entity; // temporary entity
+ float d;
+ for(tmp_entity = ons_worldgeneratorlist; tmp_entity; tmp_entity = tmp_entity.ons_worldgeneratornext) if(time >= tmp_entity.ons_overtime_damagedelay)
+ {
+ // tmp_entity.max_health / 300 gives 5 minutes of overtime.
+ // control points reduce the overtime duration.
+ d = 1;
+ for(e = ons_worldcplist; e; e = e.ons_worldcpnext)
+ {
+ if(DIFF_TEAM(e, tmp_entity))
+ if(e.islinked)
+ d = d + 1;
+ }
+
+ if(autocvar_g_campaign && autocvar__campaign_testrun)
+ d = d * tmp_entity.max_health;
+ else
+ d = d * tmp_entity.max_health / max(30, 60 * autocvar_timelimit_suddendeath);
+
+ Damage(tmp_entity, tmp_entity, tmp_entity, d, DEATH_HURTTRIGGER, tmp_entity.origin, '0 0 0');
+
+ tmp_entity.sprite.SendFlags |= 16;
+
+ tmp_entity.ons_overtime_damagedelay = time + 1;
+ }
}
+ else { wpforenemy_announced = FALSE; ons_stalemate = FALSE; }
+
+ Onslaught_count_generators();
+
+ if(ONS_OWNED_GENERATORS_OK())
+ return 0;
+
+ float winner_team = Onslaught_GetWinnerTeam();
- if (self.punchangle_z > 0)
+ if(winner_team > 0)
{
- self.punchangle_z = self.punchangle_z - 60 * sys_frametime;
- if (self.punchangle_z < 0)
- self.punchangle_z = 0;
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, APP_TEAM_NUM_4(winner_team, CENTER_ROUND_TEAM_WIN_));
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(winner_team, INFO_ROUND_TEAM_WIN_));
+ TeamScore_AddToTeam(winner_team, ST_ONS_CAPS, +1);
}
- else if (self.punchangle_z < 0)
+ else if(winner_team == -1)
{
- self.punchangle_z = self.punchangle_z + 60 * sys_frametime;
- if (self.punchangle_z > 0)
- self.punchangle_z = 0;
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_ROUND_TIED);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ROUND_TIED);
}
+
+ ons_stalemate = FALSE;
- self.angles_x = self.punchangle_x;
- self.angles_y = self.punchangle_y + self.mangle_y;
- self.angles_z = self.punchangle_z;
- self.mangle_y = self.mangle_y + 45 * sys_frametime;
+ play2all(sprintf("ctf/%s_capture.wav", Static_Team_ColorName_Lower(winner_team)));
+
+ round_handler_Init(7, autocvar_g_onslaught_warmup, autocvar_g_onslaught_round_timelimit);
+
+ FOR_EACH_PLAYER(e)
+ {
+ e.ons_roundlost = TRUE;
+ e.player_blocked = TRUE;
+
- self.cp_bob_origin_z = 4 * PI * (1 - cos(self.cp_bob_spd));
- self.cp_bob_spd = self.cp_bob_spd + 1.875 * sys_frametime;
- if(self.cp_bob_dmg_z > 0)
- self.cp_bob_dmg_z = self.cp_bob_dmg_z - 3 * sys_frametime;
- else
- self.cp_bob_dmg_z = 0;
- setorigin(self,self.cp_origin + self.cp_bob_origin + self.cp_bob_dmg);
++ nades_Clear(e);
+ }
-
+
- // damaged fx
- if(random() < 0.6 - self.health / self.max_health)
+ return 1;
+}
+
+float Onslaught_CheckPlayers()
+{
+ return 1;
+}
+
+void Onslaught_RoundStart()
+{
+ entity tmp_entity;
+ FOR_EACH_PLAYER(tmp_entity) { tmp_entity.player_blocked = FALSE; }
+
+ for(tmp_entity = ons_worldcplist; tmp_entity; tmp_entity = tmp_entity.ons_worldcpnext)
+ tmp_entity.sprite.SendFlags |= 16;
+
+ for(tmp_entity = ons_worldgeneratorlist; tmp_entity; tmp_entity = tmp_entity.ons_worldgeneratornext)
+ tmp_entity.sprite.SendFlags |= 16;
+}
+
+
+// ================
+// Bot player logic
+// ================
+
+// NOTE: LEGACY CODE, needs to be re-written!
+
+void havocbot_goalrating_ons_offenseitems(float ratingscale, vector org, float sradius)
+{
+ entity head;
+ float t, i, c, needarmor = FALSE, needweapons = FALSE;
+
+ // Needs armor/health?
+ if(self.health<100)
+ needarmor = TRUE;
+
+ // Needs weapons?
+ c = 0;
+ for(i = WEP_FIRST; i <= WEP_LAST ; ++i)
{
- pointparticles(particleeffectnum("electricity_sparks"), self.origin + randompos('-10 -10 -20', '10 10 20'), '0 0 0', 1);
+ // Find weapon
+ if(self.weapons & WepSet_FromWeapon(i))
+ if(++c>=4)
+ break;
+ }
- if(random() > 0.8)
- sound(self, CH_PAIN, "onslaught/ons_spark1.wav", VOL_BASE, ATTEN_NORM);
- else if (random() > 0.5)
- sound(self, CH_PAIN, "onslaught/ons_spark2.wav", VOL_BASE, ATTEN_NORM);
+ if(c<4)
+ needweapons = TRUE;
+
+ if(!needweapons && !needarmor)
+ return;
+
+ ons_debug(strcat(self.netname, " needs weapons ", ftos(needweapons) , "\n"));
+ ons_debug(strcat(self.netname, " needs armor ", ftos(needarmor) , "\n"));
+
+ // See what is around
+ head = findchainfloat(bot_pickup, TRUE);
+ while (head)
+ {
+ // gather health and armor only
+ if (head.solid)
+ if ( ((head.health || head.armorvalue) && needarmor) || (head.weapons && needweapons ) )
+ if (vlen(head.origin - org) < sradius)
+ {
+ t = head.bot_pickupevalfunc(self, head);
+ if (t > 0)
+ navigation_routerating(head, t * ratingscale, 500);
+ }
+ head = head.chain;
}
}
-void onslaught_controlpoint_icon_buildthink()
+void havocbot_role_ons_setrole(entity bot, float role)
{
- entity oself;
- float a;
+ ons_debug(strcat(bot.netname," switched to "));
+ switch(role)
+ {
+ case HAVOCBOT_ONS_ROLE_DEFENSE:
+ ons_debug("defense");
+ bot.havocbot_role = havocbot_role_ons_defense;
+ bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_DEFENSE;
+ bot.havocbot_role_timeout = 0;
+ break;
+ case HAVOCBOT_ONS_ROLE_ASSISTANT:
+ ons_debug("assistant");
+ bot.havocbot_role = havocbot_role_ons_assistant;
+ bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_ASSISTANT;
+ bot.havocbot_role_timeout = 0;
+ break;
+ case HAVOCBOT_ONS_ROLE_OFFENSE:
+ ons_debug("offense");
+ bot.havocbot_role = havocbot_role_ons_offense;
+ bot.havocbot_role_flags = HAVOCBOT_ONS_ROLE_OFFENSE;
+ bot.havocbot_role_timeout = 0;
+ break;
+ }
+ ons_debug("\n");
+}
- self.nextthink = time + sys_frametime;
+float havocbot_ons_teamcount(entity bot, float role)
+{
+ float c = 0;
+ entity head;
- // only do this if there is power
- a = onslaught_controlpoint_can_be_linked(self.owner, self.owner.team);
- if(!a)
- return;
+ FOR_EACH_PLAYER(head)
+ if(SAME_TEAM(head, self))
+ if(head.havocbot_role_flags & role)
+ ++c;
- self.health = self.health + self.count;
+ return c;
+}
- if (self.health >= self.max_health)
+void havocbot_goalrating_ons_controlpoints_attack(float ratingscale)
+{
+ entity cp, cp1, cp2, best, pl, wp;
+ float radius, found, bestvalue, c;
+
+ // Filter control points
+ for(cp2 = ons_worldcplist; cp2; cp2 = cp2.ons_worldcpnext)
{
- self.health = self.max_health;
- self.count = autocvar_g_onslaught_cp_regen * sys_frametime; // slow repair rate from now on
- self.think = onslaught_controlpoint_icon_think;
- sound(self, CH_TRIGGER, "onslaught/controlpoint_built.wav", VOL_BASE, ATTEN_NORM);
- bprint(Team_ColoredFullName(self.team), " captured ", self.owner.message, " control point\n");
- self.owner.iscaptured = TRUE;
+ cp2.wpcost = c = 0;
+ cp2.wpconsidered = FALSE;
- WaypointSprite_UpdateMaxHealth(self.owner.sprite, self.max_health);
- WaypointSprite_UpdateHealth(self.owner.sprite, self.health);
+ if(cp2.isshielded)
+ continue;
- onslaught_updatelinks();
+ // Ignore owned controlpoints
+ if(!(cp2.isgenneighbor[self.team] || cp2.iscpneighbor[self.team]))
+ continue;
- // Use targets now (somebody make sure this is in the right place..)
- oself = self;
- self = self.owner;
- activator = self;
- SUB_UseTargets ();
- self = oself;
- self.cp_origin = self.origin;
- self.cp_bob_origin = '0 0 0.1';
- self.cp_bob_spd = 0;
+ // Count team mates interested in this control point
+ // (easier and cleaner than keeping counters per cp and teams)
+ FOR_EACH_PLAYER(pl)
+ if(SAME_TEAM(pl, self))
+ if(pl.havocbot_role_flags & HAVOCBOT_ONS_ROLE_OFFENSE)
+ if(pl.havocbot_ons_target==cp2)
+ ++c;
+
+ // NOTE: probably decrease the cost of attackable control points
+ cp2.wpcost = c;
+ cp2.wpconsidered = TRUE;
}
- self.alpha = self.health / self.max_health;
- // colormod flash when shot
- self.colormod = '1 1 1' * (2 - bound(0, (self.pain_finished - time) / 10, 1));
- if(self.owner.model != "models/onslaught/controlpoint_pad2.md3")
- setmodel(self.owner, "models/onslaught/controlpoint_pad2.md3");
- //setsize(self, '-32 -32 0', '32 32 8');
- if(random() < 0.9 - self.health / self.max_health)
- pointparticles(particleeffectnum("rage"), self.origin + 10 * randomvec(), '0 0 -1', 1);
+ // We'll consider only the best case
+ bestvalue = 99999999999;
+ cp = world;
+ for(cp1 = ons_worldcplist; cp1; cp1 = cp1.ons_worldcpnext)
+ {
+ if (!cp1.wpconsidered)
+ continue;
+
+ if(cp1.wpcost<bestvalue)
+ {
+ bestvalue = cp1.wpcost;
+ cp = cp1;
+ self.havocbot_ons_target = cp1;
+ }
+ }
+
+ if (!cp)
+ return;
+
+ ons_debug(strcat(self.netname, " chose cp ranked ", ftos(bestvalue), "\n"));
+
+ if(cp.goalentity)
+ {
+ // Should be attacked
+ // Rate waypoints near it
+ found = FALSE;
+ best = world;
+ bestvalue = 99999999999;
+ for(radius=0; radius<1000 && !found; radius+=500)
+ {
+ for(wp=findradius(cp.origin,radius); wp; wp=wp.chain)
+ {
+ if(!(wp.wpflags & WAYPOINTFLAG_GENERATED))
+ if(wp.classname=="waypoint")
+ if(checkpvs(wp.origin,cp))
+ {
+ found = TRUE;
+ if(wp.cnt<bestvalue)
+ {
+ best = wp;
+ bestvalue = wp.cnt;
+ }
+ }
+ }
+ }
+
+ if(best)
+ {
+ navigation_routerating(best, ratingscale, 10000);
+ best.cnt += 1;
+
+ self.havocbot_attack_time = 0;
+ if(checkpvs(self.view_ofs,cp))
+ if(checkpvs(self.view_ofs,best))
+ self.havocbot_attack_time = time + 2;
+ }
+ else
+ {
+ navigation_routerating(cp, ratingscale, 10000);
+ }
+ ons_debug(strcat(self.netname, " found an attackable controlpoint at ", vtos(cp.origin) ,"\n"));
+ }
+ else
+ {
+ // Should be touched
+ ons_debug(strcat(self.netname, " found a touchable controlpoint at ", vtos(cp.origin) ,"\n"));
+ found = FALSE;
+
+ // Look for auto generated waypoint
+ if (!bot_waypoints_for_items)
+ for (wp = findradius(cp.origin,100); wp; wp = wp.chain)
+ {
+ if(wp.classname=="waypoint")
+ {
+ navigation_routerating(wp, ratingscale, 10000);
+ found = TRUE;
+ }
+ }
+
+ // Nothing found, rate the controlpoint itself
+ if (!found)
+ navigation_routerating(cp, ratingscale, 10000);
+ }
}
+float havocbot_goalrating_ons_generator_attack(float ratingscale)
+{
+ entity g, wp, bestwp;
+ float found, best;
+
+ for(g = ons_worldgeneratorlist; g; g = g.ons_worldgeneratornext)
+ {
+ if(SAME_TEAM(g, self) || g.isshielded)
+ continue;
+
+ // Should be attacked
+ // Rate waypoints near it
+ found = FALSE;
+ bestwp = world;
+ best = 99999999999;
+ for(wp=findradius(g.origin,400); wp; wp=wp.chain)
+ {
+ if(wp.classname=="waypoint")
+ if(checkpvs(wp.origin,g))
+ {
+ found = TRUE;
+ if(wp.cnt<best)
+ {
+ bestwp = wp;
+ best = wp.cnt;
+ }
+ }
+ }
+ if(bestwp)
+ {
+ ons_debug("waypoints found around generator\n");
+ navigation_routerating(bestwp, ratingscale, 10000);
+ bestwp.cnt += 1;
+
+ self.havocbot_attack_time = 0;
+ if(checkpvs(self.view_ofs,g))
+ if(checkpvs(self.view_ofs,bestwp))
+ self.havocbot_attack_time = time + 5;
+
+ return TRUE;
+ }
+ else
+ {
+ ons_debug("generator found without waypoints around\n");
+ // if there aren't waypoints near the generator go straight to it
+ navigation_routerating(g, ratingscale, 10000);
+ self.havocbot_attack_time = 0;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
-void onslaught_controlpoint_touch()
+void havocbot_role_ons_offense()
{
- entity e;
- float a;
- if (!IS_PLAYER(other))
+ if(self.deadflag != DEAD_NO)
+ {
+ self.havocbot_attack_time = 0;
+ havocbot_ons_reset_role(self);
return;
- a = onslaught_controlpoint_attackable(self, other.team);
- if(a != 2 && a != 4)
+ }
+
+ // Set the role timeout if necessary
+ if (!self.havocbot_role_timeout)
+ self.havocbot_role_timeout = time + 120;
+
+ if (time > self.havocbot_role_timeout)
+ {
+ havocbot_ons_reset_role(self);
return;
- // we've verified that this player has a legitimate claim to this point,
- // so start building the captured point icon (which only captures this
- // point if it successfully builds without being destroyed first)
- self.goalentity = e = spawn();
- e.classname = "onslaught_controlpoint_icon";
- e.owner = self;
- e.max_health = autocvar_g_onslaught_cp_health;
- e.health = autocvar_g_onslaught_cp_buildhealth;
- e.solid = SOLID_BBOX;
- e.movetype = MOVETYPE_NONE;
- setmodel(e, "models/onslaught/controlpoint_icon.md3");
- setsize(e, '-32 -32 -32', '32 32 32');
- setorigin(e, self.origin + '0 0 96');
- e.takedamage = DAMAGE_AIM;
- e.bot_attack = TRUE;
- e.event_damage = onslaught_controlpoint_icon_damage;
- e.team = other.team;
- e.colormap = 1024 + (e.team - 1) * 17;
- e.think = onslaught_controlpoint_icon_buildthink;
- e.nextthink = time + sys_frametime;
- e.count = (e.max_health - e.health) * sys_frametime / autocvar_g_onslaught_cp_buildtime; // how long it takes to build
- sound(e, CH_TRIGGER, "onslaught/controlpoint_build.wav", VOL_BASE, ATTEN_NORM);
- self.team = e.team;
- self.colormap = e.colormap;
- WaypointSprite_UpdateBuildFinished(self.sprite, time + (e.max_health - e.health) / (e.count / sys_frametime));
- onslaught_updatelinks();
+ }
+
+ if(self.havocbot_attack_time>time)
+ return;
+
+ if (self.bot_strategytime < time)
+ {
+ navigation_goalrating_start();
+ havocbot_goalrating_enemyplayers(20000, self.origin, 650);
+ if(!havocbot_goalrating_ons_generator_attack(20000))
+ havocbot_goalrating_ons_controlpoints_attack(20000);
+ havocbot_goalrating_ons_offenseitems(10000, self.origin, 10000);
+ navigation_goalrating_end();
+
+ self.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
+ }
}
-void onslaught_controlpoint_think()
+void havocbot_role_ons_assistant()
{
- self.nextthink = time;
- CSQCMODEL_AUTOUPDATE();
+ havocbot_ons_reset_role(self);
}
-void onslaught_controlpoint_reset()
+void havocbot_role_ons_defense()
{
- if(self.goalentity && self.goalentity != world)
- remove(self.goalentity);
- self.goalentity = world;
- self.team = 0;
- self.colormap = 1024;
- self.iscaptured = FALSE;
- self.islinked = FALSE;
- self.isshielded = TRUE;
- self.enemy.solid = SOLID_NOT;
- self.enemy.colormap = self.colormap;
- self.think = onslaught_controlpoint_think;
- self.enemy.think = func_null;
- self.nextthink = time; // don't like func_null :P
- setmodel(self, "models/onslaught/controlpoint_pad.md3");
- //setsize(self, '-32 -32 0', '32 32 8');
-
- WaypointSprite_UpdateMaxHealth(self.sprite, 0);
+ havocbot_ons_reset_role(self);
+}
- onslaught_updatelinks();
+void havocbot_ons_reset_role(entity bot)
+{
+ entity head;
+ float c;
- activator = self;
- SUB_UseTargets(); // to reset the structures, playerspawns etc.
-
- CSQCMODEL_AUTOUPDATE();
-}
+ if(self.deadflag != DEAD_NO)
+ return;
-/*QUAKED spawnfunc_onslaught_controlpoint (0 .5 .8) (-32 -32 0) (32 32 128)
- Control point. Be sure to give this enough clearance so that the shootable part has room to exist
+ bot.havocbot_ons_target = world;
- This should link to an spawnfunc_onslaught_controlpoint entity or spawnfunc_onslaught_generator entity.
+ // TODO: Defend control points or generator if necessary
-keys:
-"targetname" - name that spawnfunc_onslaught_link entities will use to target this.
-"target" - target any entities that are tied to this control point, such as vehicles and buildable structure entities.
-"message" - name of this control point (should reflect the location in the map, such as "center bridge", "north tower", etc)
- */
+ // if there is only me on the team switch to offense
+ c = 0;
+ FOR_EACH_PLAYER(head)
+ if(SAME_TEAM(head, self))
+ ++c;
-void spawnfunc_onslaught_controlpoint()
-{
- //entity e;
- if (!g_onslaught)
+ if(c==1)
{
- remove(self);
+ havocbot_role_ons_setrole(bot, HAVOCBOT_ONS_ROLE_OFFENSE);
return;
}
- precache_model("models/onslaught/controlpoint_pad.md3");
- precache_model("models/onslaught/controlpoint_pad2.md3");
- precache_model("models/onslaught/controlpoint_shield.md3");
- precache_model("models/onslaught/controlpoint_icon.md3");
- precache_model("models/onslaught/controlpoint_icon_dmg1.md3");
- precache_model("models/onslaught/controlpoint_icon_dmg2.md3");
- precache_model("models/onslaught/controlpoint_icon_dmg3.md3");
- precache_model("models/onslaught/controlpoint_icon_gib1.md3");
- precache_model("models/onslaught/controlpoint_icon_gib2.md3");
- precache_model("models/onslaught/controlpoint_icon_gib4.md3");
- precache_sound("onslaught/controlpoint_build.wav");
- precache_sound("onslaught/controlpoint_built.wav");
- precache_sound("weapons/grenade_impact.wav");
- precache_sound("onslaught/damageblockedbyshield.wav");
- precache_sound("onslaught/controlpoint_underattack.wav");
- precache_sound("onslaught/ons_spark1.wav");
- precache_sound("onslaught/ons_spark2.wav");
- self.solid = SOLID_BBOX;
- self.movetype = MOVETYPE_NONE;
- setmodel(self, "models/onslaught/controlpoint_pad.md3");
- //setsize(self, '-32 -32 0', '32 32 8');
- if(!self.noalign)
- {
- setorigin(self, self.origin + '0 0 20');
- droptofloor();
- }
- self.touch = onslaught_controlpoint_touch;
- self.team = 0;
- self.colormap = 1024;
- self.iscaptured = FALSE;
- self.islinked = FALSE;
- self.isshielded = TRUE;
+ havocbot_role_ons_setrole(bot, HAVOCBOT_ONS_ROLE_OFFENSE);
+}
- // spawn shield model which indicates whether this can be damaged
- self.enemy = spawn();
- self.enemy.classname = "onslaught_controlpoint_shield";
- self.enemy.solid = SOLID_NOT;
- self.enemy.movetype = MOVETYPE_NONE;
- self.enemy.effects = EF_ADDITIVE;
- setmodel(self.enemy , "models/onslaught/controlpoint_shield.md3");
- setattachment(self.enemy , self, "");
- //setsize(e, '-32 -32 0', '32 32 128');
+/*
+ * Find control point or generator owned by the same team self which is nearest to pos
+ * if max_dist is positive, only control points within this range will be considered
+ */
+entity ons_Nearest_ControlPoint(vector pos, float max_dist)
+{
+ entity tmp_entity, closest_target = world;
+ tmp_entity = findchain(classname, "onslaught_controlpoint");
+ while(tmp_entity)
+ {
+ if(SAME_TEAM(tmp_entity, self))
+ if(tmp_entity.iscaptured)
+ if(max_dist <= 0 || vlen(tmp_entity.origin - pos) <= max_dist)
+ if(vlen(tmp_entity.origin - pos) <= vlen(closest_target.origin - pos) || closest_target == world)
+ closest_target = tmp_entity;
+ tmp_entity = tmp_entity.chain;
+ }
+ tmp_entity = findchain(classname, "onslaught_generator");
+ while(tmp_entity)
+ {
+ if(SAME_TEAM(tmp_entity, self))
+ if(max_dist <= 0 || vlen(tmp_entity.origin - pos) < max_dist)
+ if(vlen(tmp_entity.origin - pos) <= vlen(closest_target.origin - pos) || closest_target == world)
+ closest_target = tmp_entity;
+ tmp_entity = tmp_entity.chain;
+ }
+
+ return closest_target;
+}
- //setorigin(e, self.origin);
- self.enemy.colormap = self.colormap;
+/*
+ * Find control point or generator owned by the same team self which is nearest to pos
+ * if max_dist is positive, only control points within this range will be considered
+ * This function only check distances on the XY plane, disregarding Z
+ */
+entity ons_Nearest_ControlPoint_2D(vector pos, float max_dist)
+{
+ entity tmp_entity, closest_target = world;
+ vector delta;
+ float smallest_distance = 0, distance;
+
+ tmp_entity = findchain(classname, "onslaught_controlpoint");
+ while(tmp_entity)
+ {
+ delta = tmp_entity.origin - pos;
+ delta_z = 0;
+ distance = vlen(delta);
+
+ if(SAME_TEAM(tmp_entity, self))
+ if(tmp_entity.iscaptured)
+ if(max_dist <= 0 || distance <= max_dist)
+ if(closest_target == world || distance <= smallest_distance )
+ {
+ closest_target = tmp_entity;
+ smallest_distance = distance;
+ }
+
+ tmp_entity = tmp_entity.chain;
+ }
+ tmp_entity = findchain(classname, "onslaught_generator");
+ while(tmp_entity)
+ {
+ delta = tmp_entity.origin - pos;
+ delta_z = 0;
+ distance = vlen(delta);
+
+ if(SAME_TEAM(tmp_entity, self))
+ if(max_dist <= 0 || distance <= max_dist)
+ if(closest_target == world || distance <= smallest_distance )
+ {
+ closest_target = tmp_entity;
+ smallest_distance = distance;
+ }
+
+ tmp_entity = tmp_entity.chain;
+ }
+
+ return closest_target;
+}
+/**
+ * find the number of control points and generators in the same team as self
+ */
+float ons_Count_SelfControlPoints()
+{
+ entity tmp_entity;
+ tmp_entity = findchain(classname, "onslaught_controlpoint");
+ float n = 0;
+ while(tmp_entity)
+ {
+ if(SAME_TEAM(tmp_entity, self))
+ if(tmp_entity.iscaptured)
+ n++;
+ tmp_entity = tmp_entity.chain;
+ }
+ tmp_entity = findchain(classname, "onslaught_generator");
+ while(tmp_entity)
+ {
+ if(SAME_TEAM(tmp_entity, self))
+ n++;
+ tmp_entity = tmp_entity.chain;
+ }
+ return n;
+}
- waypoint_spawnforitem(self);
+/**
+ * Teleport player to a random position near tele_target
+ * if tele_effects is true, teleport sound+particles are created
+ * return FALSE on failure
+ */
+float ons_Teleport(entity player, entity tele_target, float range, float tele_effects)
+{
+ if ( !tele_target )
+ return FALSE;
- self.think = onslaught_controlpoint_think;
- self.nextthink = time;
+ float i;
+ vector loc;
+ float theta;
+ for(i = 0; i < 16; ++i)
+ {
+ theta = random() * 2 * M_PI;
+ loc_y = sin(theta);
+ loc_x = cos(theta);
+ loc_z = 0;
+ loc *= random() * range;
+
+ loc += tele_target.origin + '0 0 128';
+
+ tracebox(loc, PL_MIN, PL_MAX, loc, MOVE_NORMAL, player);
+ if(trace_fraction == 1.0 && !trace_startsolid)
+ {
+ traceline(tele_target.origin, loc, MOVE_NOMONSTERS, tele_target); // double check to make sure we're not spawning outside the world
+ if(trace_fraction == 1.0 && !trace_startsolid)
+ {
+ if ( tele_effects )
+ {
+ pointparticles(particleeffectnum("teleport"), player.origin, '0 0 0', 1);
+ sound (player, CH_TRIGGER, "misc/teleport.wav", VOL_BASE, ATTEN_NORM);
+ }
+ setorigin(player, loc);
+ player.angles = '0 1 0' * ( theta * RAD2DEG + 180 );
+ makevectors(player.angles);
+ player.fixangle = TRUE;
+ player.teleport_antispam = time + autocvar_g_onslaught_teleport_wait;
+
+ if ( tele_effects )
+ pointparticles(particleeffectnum("teleport"), player.origin + v_forward * 32, '0 0 0', 1);
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
- WaypointSprite_SpawnFixed(string_null, self.origin + '0 0 128', self, sprite, RADARICON_NONE, '0 0 0');
- WaypointSprite_UpdateRule(self.sprite, NUM_TEAM_2, SPRITERULE_TEAMPLAY);
+// ==============
+// Hook Functions
+// ==============
- onslaught_updatelinks();
+MUTATOR_HOOKFUNCTION(ons_ResetMap)
+{
+ FOR_EACH_PLAYER(self)
+ {
+ self.ons_roundlost = FALSE;
+ self.ons_deathloc = '0 0 0';
+ PutClientInServer();
+ }
+ return FALSE;
+}
- self.reset = onslaught_controlpoint_reset;
-
- CSQCMODEL_AUTOINIT();
+MUTATOR_HOOKFUNCTION(ons_RemovePlayer)
+{
+ self.ons_deathloc = '0 0 0';
+ return FALSE;
}
-float onslaught_link_send(entity to, float sendflags)
+MUTATOR_HOOKFUNCTION(ons_PlayerSpawn)
{
- WriteByte(MSG_ENTITY, ENT_CLIENT_RADARLINK);
- WriteByte(MSG_ENTITY, sendflags);
- if(sendflags & 1)
+ if(!round_handler_IsRoundStarted())
{
- WriteCoord(MSG_ENTITY, self.goalentity.origin_x);
- WriteCoord(MSG_ENTITY, self.goalentity.origin_y);
- WriteCoord(MSG_ENTITY, self.goalentity.origin_z);
+ self.player_blocked = TRUE;
+ return FALSE;
}
- if(sendflags & 2)
+
+ entity l;
+ for(l = ons_worldgeneratorlist; l; l = l.ons_worldgeneratornext)
{
- WriteCoord(MSG_ENTITY, self.enemy.origin_x);
- WriteCoord(MSG_ENTITY, self.enemy.origin_y);
- WriteCoord(MSG_ENTITY, self.enemy.origin_z);
+ l.sprite.SendFlags |= 16;
}
- if(sendflags & 4)
+ for(l = ons_worldcplist; l; l = l.ons_worldcpnext)
{
- WriteByte(MSG_ENTITY, self.clientcolors); // which is goalentity's color + enemy's color * 16
+ l.sprite.SendFlags |= 16;
}
- return TRUE;
-}
-void onslaught_link_checkupdate()
-{
- // TODO check if the two sides have moved (currently they won't move anyway)
- float redpower, bluepower;
+ if(ons_stalemate) { Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_OVERTIME_CONTROLPOINT); }
- redpower = bluepower = 0;
- if(self.goalentity.islinked)
+ if ( autocvar_g_onslaught_spawn_choose )
+ if ( self.ons_spawn_by )
+ if ( ons_Teleport(self,self.ons_spawn_by,autocvar_g_onslaught_teleport_radius,FALSE) )
{
- if(self.goalentity.team == NUM_TEAM_1)
- redpower = 1;
- else if(self.goalentity.team == NUM_TEAM_2)
- bluepower = 1;
+ self.ons_spawn_by = world;
+ return FALSE;
}
- if(self.enemy.islinked)
+
+ if(autocvar_g_onslaught_spawn_at_controlpoints)
+ if(random() <= autocvar_g_onslaught_spawn_at_controlpoints_chance)
{
- if(self.enemy.team == NUM_TEAM_1)
- redpower = 2;
- else if(self.enemy.team == NUM_TEAM_2)
- bluepower = 2;
- }
+ float random_target = autocvar_g_onslaught_spawn_at_controlpoints_random;
+ entity tmp_entity, closest_target = world;
+ vector spawn_loc = self.ons_deathloc;
+
+ // new joining player or round reset, don't bother checking
+ if(spawn_loc == '0 0 0') { return FALSE; }
- float cc;
- if(redpower == 1 && bluepower == 2)
- cc = (NUM_TEAM_1 - 1) * 0x01 + (NUM_TEAM_2 - 1) * 0x10;
- else if(redpower == 2 && bluepower == 1)
- cc = (NUM_TEAM_1 - 1) * 0x10 + (NUM_TEAM_2 - 1) * 0x01;
- else if(redpower)
- cc = (NUM_TEAM_1 - 1) * 0x11;
- else if(bluepower)
- cc = (NUM_TEAM_2 - 1) * 0x11;
- else
- cc = 0;
-
- //print(etos(self), " rp=", ftos(redpower), " bp=", ftos(bluepower), " ");
- //print("cc=", ftos(cc), "\n");
+ if(random_target) { RandomSelection_Init(); }
- if(cc != self.clientcolors)
- {
- self.clientcolors = cc;
- self.SendFlags |= 4;
+ for(tmp_entity = ons_worldcplist; tmp_entity; tmp_entity = tmp_entity.ons_worldcpnext)
+ {
+ if(SAME_TEAM(tmp_entity, self))
+ if(random_target)
+ RandomSelection_Add(tmp_entity, 0, string_null, 1, 1);
+ else if(vlen(tmp_entity.origin - spawn_loc) <= vlen(closest_target.origin - spawn_loc) || closest_target == world)
+ closest_target = tmp_entity;
+ }
+
+ if(random_target) { closest_target = RandomSelection_chosen_ent; }
+
+ if(closest_target)
+ {
+ float i;
+ vector loc;
+ for(i = 0; i < 10; ++i)
+ {
+ loc = closest_target.origin + '0 0 96';
+ loc += ('0 1 0' * random()) * 128;
+ tracebox(loc, PL_MIN, PL_MAX, loc, MOVE_NORMAL, self);
+ if(trace_fraction == 1.0 && !trace_startsolid)
+ {
+ traceline(closest_target.origin, loc, MOVE_NOMONSTERS, closest_target); // double check to make sure we're not spawning outside the world
+ if(trace_fraction == 1.0 && !trace_startsolid)
+ {
+ setorigin(self, loc);
+ self.angles = normalize(loc - closest_target.origin) * RAD2DEG;
+ return FALSE;
+ }
+ }
+ }
+ }
+ }
+
+ if(autocvar_g_onslaught_spawn_at_generator)
+ if(random() <= autocvar_g_onslaught_spawn_at_generator_chance)
+ {
+ float random_target = autocvar_g_onslaught_spawn_at_generator_random;
+ entity tmp_entity, closest_target = world;
+ vector spawn_loc = self.ons_deathloc;
+
+ // new joining player or round reset, don't bother checking
+ if(spawn_loc == '0 0 0') { return FALSE; }
+
+ if(random_target) { RandomSelection_Init(); }
+
+ for(tmp_entity = ons_worldgeneratorlist; tmp_entity; tmp_entity = tmp_entity.ons_worldgeneratornext)
+ {
+ if(random_target)
+ RandomSelection_Add(tmp_entity, 0, string_null, 1, 1);
+ else
+ {
+ if(SAME_TEAM(tmp_entity, self))
+ if(vlen(tmp_entity.origin - spawn_loc) <= vlen(closest_target.origin - spawn_loc) || closest_target == world)
+ closest_target = tmp_entity;
+ }
+ }
+
+ if(random_target) { closest_target = RandomSelection_chosen_ent; }
+
+ if(closest_target)
+ {
+ float i;
+ vector loc;
+ for(i = 0; i < 10; ++i)
+ {
+ loc = closest_target.origin + '0 0 128';
+ loc += ('0 1 0' * random()) * 256;
+ tracebox(loc, PL_MIN, PL_MAX, loc, MOVE_NORMAL, self);
+ if(trace_fraction == 1.0 && !trace_startsolid)
+ {
+ traceline(closest_target.origin, loc, MOVE_NOMONSTERS, closest_target); // double check to make sure we're not spawning outside the world
+ if(trace_fraction == 1.0 && !trace_startsolid)
+ {
+ setorigin(self, loc);
+ self.angles = normalize(loc - closest_target.origin) * RAD2DEG;
+ return FALSE;
+ }
+ }
+ }
+ }
}
- self.nextthink = time;
+ return FALSE;
}
-void onslaught_link_delayed()
+MUTATOR_HOOKFUNCTION(ons_PlayerDies)
{
- self.goalentity = find(world, targetname, self.target);
- self.enemy = find(world, targetname, self.target2);
- if (!self.goalentity)
- objerror("can not find target\n");
- if (!self.enemy)
- objerror("can not find target2\n");
- dprint(etos(self.goalentity), " linked with ", etos(self.enemy), "\n");
- self.SendFlags |= 3;
- self.think = onslaught_link_checkupdate;
- self.nextthink = time;
+ frag_target.ons_deathloc = frag_target.origin;
+ entity l;
+ for(l = ons_worldgeneratorlist; l; l = l.ons_worldgeneratornext)
+ {
+ l.sprite.SendFlags |= 16;
+ }
+ for(l = ons_worldcplist; l; l = l.ons_worldcpnext)
+ {
+ l.sprite.SendFlags |= 16;
+ }
+
+ if ( autocvar_g_onslaught_spawn_choose )
+ if ( ons_Count_SelfControlPoints() > 1 )
+ stuffcmd(self, "qc_cmd_cl hud clickradar\n");
+
+ return FALSE;
}
-/*QUAKED spawnfunc_onslaught_link (0 .5 .8) (-16 -16 -16) (16 16 16)
- Link between control points.
+MUTATOR_HOOKFUNCTION(ons_MonsterThink)
+{
+ entity e = find(world, targetname, self.target);
+ if (e != world)
+ self.team = e.team;
- This entity targets two different spawnfunc_onslaught_controlpoint or spawnfunc_onslaught_generator entities, and suppresses shielding on both if they are owned by different teams.
+ return FALSE;
+}
-keys:
-"target" - first control point.
-"target2" - second control point.
- */
-void spawnfunc_onslaught_link()
+void ons_MonsterSpawn_Delayed()
{
- if (!g_onslaught)
+ entity e, own = self.owner;
+
+ if(!own) { remove(self); return; }
+
+ if(own.targetname)
{
- remove(self);
- return;
+ e = find(world, target, own.targetname);
+ if(e != world)
+ {
+ own.team = e.team;
+
+ activator = e;
+ own.use();
+ }
}
- if (self.target == "" || self.target2 == "")
- objerror("target and target2 must be set\n");
- InitializeEntity(self, onslaught_link_delayed, INITPRIO_FINDTARGET);
- Net_LinkEntity(self, FALSE, 0, onslaught_link_send);
+
+ remove(self);
}
-MUTATOR_HOOKFUNCTION(ons_BuildMutatorsString)
+MUTATOR_HOOKFUNCTION(ons_MonsterSpawn)
{
- ret_string = strcat(ret_string, ":ONS");
- return 0;
-}
+ entity e = spawn();
+ e.owner = self;
+ InitializeEntity(e, ons_MonsterSpawn_Delayed, INITPRIO_FINDTARGET);
-MUTATOR_HOOKFUNCTION(ons_BuildMutatorsPrettyString)
-{
- ret_string = strcat(ret_string, ", Onslaught");
- return 0;
+ return FALSE;
}
-MUTATOR_HOOKFUNCTION(ons_Spawn_Score)
+void ons_TurretSpawn_Delayed()
{
+ entity e, own = self.owner;
- /*
- float _neer_home = (random() > 0.5 ? TRUE : FALSE);
+ if(!own) { remove(self); return; }
- RandomSelection_Init();
+ if(own.targetname)
+ {
+ e = find(world, target, own.targetname);
+ if(e != world)
+ {
+ own.team = e.team;
+ own.active = ACTIVE_NOT;
+
+ activator = e;
+ own.use();
+ }
+ }
- if(self.team == NUM_TEAM_1)
- RandomSelection_Add(ons_red_generator, 0, string_null, 1, 1);
+ remove(self);
+}
- if(self.team == NUM_TEAM_2)
- RandomSelection_Add(ons_blue_generator, 0, string_null, 1, 1);
+MUTATOR_HOOKFUNCTION(ons_TurretSpawn)
+{
+ entity e = spawn();
+ e.owner = self;
+ InitializeEntity(e, ons_TurretSpawn_Delayed, INITPRIO_FINDTARGET);
- entity _cp = findchain(classname, "onslaught_controlpoint"):
- while _cp;
- {
- if(_cp.team == self.team)
- RandomSelection_Add(_cp, 0, string_null, 1, 1);
+ return FALSE;
+}
- _cp = _cp.chain;
- }
+MUTATOR_HOOKFUNCTION(ons_BotRoles)
+{
+ havocbot_ons_reset_role(self);
+ return TRUE;
+}
- if(RandomSelection_chosen_ent)
+MUTATOR_HOOKFUNCTION(ons_GetTeamCount)
+{
+ // onslaught is special
+ entity tmp_entity;
+ for(tmp_entity = ons_worldgeneratorlist; tmp_entity; tmp_entity = tmp_entity.ons_worldgeneratornext)
{
- self.tur_head = RandomSelection_chosen_ent;
- spawn_score_x += SPAWN_PRIO_NEAR_TEAMMATE_FOUND;
+ switch(tmp_entity.team)
+ {
+ case NUM_TEAM_1: c1 = 0; break;
+ case NUM_TEAM_2: c2 = 0; break;
+ case NUM_TEAM_3: c3 = 0; break;
+ case NUM_TEAM_4: c4 = 0; break;
+ }
}
- else if(self.team == spawn_spot.team)
- spawn_score_x += SPAWN_PRIO_NEAR_TEAMMATE_SAMETEAM; // prefer same team, if we can't find a spawn near teammate
- */
+ return TRUE;
+}
+
+MUTATOR_HOOKFUNCTION(ons_SpectateCopy)
+{
+ self.ons_roundlost = other.ons_roundlost; // make spectators see it too
+ return FALSE;
+}
- entity source_point = ons_Nearest_ControlPoint(self.origin, autocvar_g_onslaught_teleport_radius);
-
- if ( !source_point && self.health > 0 )
- {
- sprint(self, "\nYou need to be next to a control point\n");
- return 1;
- }
-
- entity closest_target = ons_Nearest_ControlPoint_2D(pos, autocvar_g_onslaught_click_radius);
-
- if ( closest_target == world )
- {
- sprint(self, "\nNo control point found\n");
- return 1;
- }
-
- if ( self.health <= 0 )
- {
- self.ons_spawn_by = closest_target;
- self.respawn_flags = self.respawn_flags | RESPAWN_FORCE;
- }
- else
+MUTATOR_HOOKFUNCTION(ons_SV_ParseClientCommand)
+{
+ if(MUTATOR_RETURNVALUE) // command was already handled?
+ return FALSE;
+
+ if ( cmd_name == "ons_spawn" )
+ {
+ vector pos = self.origin;
+ if(cmd_argc > 1)
+ pos_x = stof(argv(1));
+ if(cmd_argc > 2)
+ pos_y = stof(argv(2));
+ if(cmd_argc > 3)
+ pos_z = stof(argv(3));
+
+ if ( IS_PLAYER(self) )
+ {
- if ( source_point == closest_target )
++ if ( !self.frozen )
+ {
- sprint(self, "\nTeleporting to the same point\n");
++ entity source_point = ons_Nearest_ControlPoint(self.origin, autocvar_g_onslaught_teleport_radius);
++
++ if ( !source_point && self.health > 0 )
+ {
-
- if ( !ons_Teleport(self,closest_target,autocvar_g_onslaught_teleport_radius,TRUE) )
- sprint(self, "\nUnable to teleport there\n");
++ sprint(self, "\nYou need to be next to a control point\n");
+ return 1;
+ }
- //sprint(self, "\nNo teleportation for you\n");
-
- return 1;
++
++
++ entity closest_target = ons_Nearest_ControlPoint_2D(pos, autocvar_g_onslaught_click_radius);
++
++ if ( closest_target == world )
++ {
++ sprint(self, "\nNo control point found\n");
++ return 1;
++ }
++
++ if ( self.health <= 0 )
++ {
++ self.ons_spawn_by = closest_target;
++ self.respawn_flags = self.respawn_flags | RESPAWN_FORCE;
++ }
++ else
++ {
++ if ( source_point == closest_target )
++ {
++ sprint(self, "\nTeleporting to the same point\n");
++ return 1;
++ }
++
++ if ( !ons_Teleport(self,closest_target,autocvar_g_onslaught_teleport_radius,TRUE) )
++ sprint(self, "\nUnable to teleport there\n");
++ }
++
++ return 1;
+ }
+
++ sprint(self, "\nNo teleportation for you\n");
+ }
+
+ return 1;
+ }
return 0;
}
-MUTATOR_HOOKFUNCTION(ons_PlayerSpawn)
+MUTATOR_HOOKFUNCTION(ons_PlayerUseKey)
{
- if(!autocvar_g_onslaught_spawn_at_controlpoints)
- return 0;
+ if(MUTATOR_RETURNVALUE || gameover) { return FALSE; }
+
+ if((time > self.teleport_antispam) && (self.deadflag == DEAD_NO) && !self.vehicle)
+ {
+ entity source_point = ons_Nearest_ControlPoint(self.origin, autocvar_g_onslaught_teleport_radius);
+ if ( source_point )
+ {
+ stuffcmd(self, "qc_cmd_cl hud clickradar\n");
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
- if(random() < 0.5) // 50/50 chane to use default spawnsystem.
- return 0;
+// ==========
+// Spawnfuncs
+// ==========
- float _close_to_home = ((random() > 0.5) ? TRUE : FALSE);
- entity _best = world, _trg_gen = world;
- float _score, _best_score = MAX_SHOT_DISTANCE;
+/*QUAKED spawnfunc_onslaught_link (0 .5 .8) (-16 -16 -16) (16 16 16)
+ Link between control points.
- RandomSelection_Init();
+ This entity targets two different spawnfunc_onslaught_controlpoint or spawnfunc_onslaught_generator entities, and suppresses shielding on both if they are owned by different teams.
- if(self.team == NUM_TEAM_1)
- {
- if(!_close_to_home)
- _trg_gen = ons_blue_generator;
- else
- _trg_gen = ons_red_generator;
- }
+keys:
+"target" - first control point.
+"target2" - second control point.
+ */
+void spawnfunc_onslaught_link()
+{
+ if(!g_onslaught) { remove(self); return; }
- if(self.team == NUM_TEAM_2)
- {
- if(_close_to_home)
- _trg_gen = ons_blue_generator;
- else
- _trg_gen = ons_red_generator;
- }
+ if (self.target == "" || self.target2 == "")
+ objerror("target and target2 must be set\n");
- entity _cp = findchain(classname, "onslaught_controlpoint");
- while(_cp)
- {
- if(_cp.team == self.team)
- {
- _score = vlen(_trg_gen.origin - _cp.origin);
- if(_score < _best_score)
- {
- _best = _cp;
- _best_score = _score;
- }
- }
- _cp = _cp.chain;
- }
+ self.ons_worldlinknext = ons_worldlinklist; // link into ons_worldlinklist
+ ons_worldlinklist = self;
- vector _loc;
- float i;
- if(_best)
- {
- for(i = 0; i < 10; ++i)
- {
- _loc = _best.origin + '0 0 96';
- _loc += ('0 1 0' * random()) * 128;
- tracebox(_loc, PL_MIN, PL_MAX, _loc, MOVE_NORMAL, self);
- if(trace_fraction == 1.0 && !trace_startsolid)
- {
- setorigin(self, _loc);
- self.angles = normalize(_loc - _best.origin) * RAD2DEG;
- return 0;
- }
- }
- }
- else
- {
- if(!autocvar_g_onslaught_spawn_at_generator)
- return 0;
+ InitializeEntity(self, ons_DelayedLinkSetup, INITPRIO_FINDTARGET);
+ Net_LinkEntity(self, FALSE, 0, ons_Link_Send);
+}
- _trg_gen = ((self.team == NUM_TEAM_1) ? ons_red_generator : ons_blue_generator);
+/*QUAKED spawnfunc_onslaught_controlpoint (0 .5 .8) (-32 -32 0) (32 32 128)
+ Control point. Be sure to give this enough clearance so that the shootable part has room to exist
- for(i = 0; i < 10; ++i)
- {
- _loc = _trg_gen.origin + '0 0 96';
- _loc += ('0 1 0' * random()) * 128;
- tracebox(_loc, PL_MIN, PL_MAX, _loc, MOVE_NORMAL, self);
- if(trace_fraction == 1.0 && !trace_startsolid)
- {
- setorigin(self, _loc);
- self.angles = normalize(_loc - _trg_gen.origin) * RAD2DEG;
- return 0;
- }
- }
- }
+ This should link to an spawnfunc_onslaught_controlpoint entity or spawnfunc_onslaught_generator entity.
- return 0;
+keys:
+"targetname" - name that spawnfunc_onslaught_link entities will use to target this.
+"target" - target any entities that are tied to this control point, such as vehicles and buildable structure entities.
+"message" - name of this control point (should reflect the location in the map, such as "center bridge", "north tower", etc)
+ */
+
+void spawnfunc_onslaught_controlpoint()
+{
+ if(!g_onslaught) { remove(self); return; }
+
+ ons_ControlPoint_Setup(self);
}
-MUTATOR_HOOKFUNCTION(ons_MonsterThink)
+/*QUAKED spawnfunc_onslaught_generator (0 .5 .8) (-32 -32 -24) (32 32 64)
+ Base generator.
+
+ spawnfunc_onslaught_link entities can target this.
+
+keys:
+"team" - team that owns this generator (5 = red, 14 = blue, etc), MUST BE SET.
+"targetname" - name that spawnfunc_onslaught_link entities will use to target this.
+ */
+void spawnfunc_onslaught_generator()
{
- entity e = find(world, targetname, self.target);
- if (e != world)
- self.team = e.team;
+ if(!g_onslaught) { remove(self); return; }
+ if(!self.team) { objerror("team must be set"); }
- return FALSE;
+ ons_GeneratorSetup(self);
}
-MUTATOR_HOOKFUNCTION(ons_MonsterSpawn)
+
+// scoreboard setup
+void ons_ScoreRules()
{
- entity e, ee = world;
-
- if(self.targetname)
- {
- e = find(world,target,self.targetname);
- if(e != world)
- {
- self.team = e.team;
- ee = e;
- }
- }
+ CheckAllowedTeams(world);
+ ScoreRules_basics(((c4>=0) ? 4 : (c3>=0) ? 3 : 2), SFL_SORT_PRIO_PRIMARY, 0, TRUE);
+ ScoreInfo_SetLabel_TeamScore (ST_ONS_CAPS, "destroyed", SFL_SORT_PRIO_PRIMARY);
+ ScoreInfo_SetLabel_PlayerScore(SP_ONS_CAPS, "caps", SFL_SORT_PRIO_SECONDARY);
+ ScoreInfo_SetLabel_PlayerScore(SP_ONS_TAKES, "takes", 0);
+ ScoreRules_basics_end();
+}
+
+void ons_DelayedInit() // Do this check with a delay so we can wait for teams to be set up
+{
+ ons_ScoreRules();
- if(ee)
- {
- activator = ee;
- self.use();
- }
+ round_handler_Spawn(Onslaught_CheckPlayers, Onslaught_CheckWinner, Onslaught_RoundStart);
+ round_handler_Init(5, autocvar_g_onslaught_warmup, autocvar_g_onslaught_round_timelimit);
+}
- return FALSE;
+void ons_Initialize()
+{
+ precache_sound("ctf/red_capture.wav");
+ precache_sound("ctf/blue_capture.wav");
+ precache_sound("ctf/yellow_capture.wav");
+ precache_sound("ctf/pink_capture.wav");
+
+ ons_captureshield_force = autocvar_g_onslaught_shield_force;
+
+ addstat(STAT_ROUNDLOST, AS_INT, ons_roundlost);
+
+ InitializeEntity(world, ons_DelayedInit, INITPRIO_GAMETYPE);
}
MUTATOR_DEFINITION(gamemode_onslaught)
{
- MUTATOR_HOOK(BuildMutatorsPrettyString, ons_BuildMutatorsPrettyString, CBC_ORDER_ANY);
- MUTATOR_HOOK(BuildMutatorsString, ons_BuildMutatorsString, CBC_ORDER_ANY);
+ MUTATOR_HOOK(reset_map_global, ons_ResetMap, CBC_ORDER_ANY);
+ MUTATOR_HOOK(MakePlayerObserver, ons_RemovePlayer, CBC_ORDER_ANY);
+ MUTATOR_HOOK(ClientDisconnect, ons_RemovePlayer, CBC_ORDER_ANY);
MUTATOR_HOOK(PlayerSpawn, ons_PlayerSpawn, CBC_ORDER_ANY);
+ MUTATOR_HOOK(PlayerDies, ons_PlayerDies, CBC_ORDER_ANY);
MUTATOR_HOOK(MonsterMove, ons_MonsterThink, CBC_ORDER_ANY);
MUTATOR_HOOK(MonsterSpawn, ons_MonsterSpawn, CBC_ORDER_ANY);
- //MUTATOR_HOOK(Spawn_Score, ons_Spawn_Score, CBC_ORDER_ANY);
+ MUTATOR_HOOK(TurretSpawn, ons_TurretSpawn, CBC_ORDER_ANY);
+ MUTATOR_HOOK(HavocBot_ChooseRole, ons_BotRoles, CBC_ORDER_ANY);
+ MUTATOR_HOOK(GetTeamCount, ons_GetTeamCount, CBC_ORDER_ANY);
+ MUTATOR_HOOK(SpectateCopy, ons_SpectateCopy, CBC_ORDER_ANY);
+ MUTATOR_HOOK(SV_ParseClientCommand, ons_SV_ParseClientCommand, CBC_ORDER_ANY);
+ MUTATOR_HOOK(PlayerUseKey, ons_PlayerUseKey, CBC_ORDER_ANY);
MUTATOR_ONADD
{
if(time > 1) // game loads at time 1
error("This is a game type and it cannot be added at runtime.");
+ ons_Initialize();
+ }
+
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ // we actually cannot roll back ons_Initialize here
+ // BUT: we don't need to! If this gets called, adding always
+ // succeeds.
}
MUTATOR_ONREMOVE
return -1;
}
- return 0;
+ return FALSE;
}
--- /dev/null
- #define CP_THINKRATE 0.2
+// these are needed since mutators are compiled last
+
+#ifdef SVQC
+
+.entity ons_toucher; // player who touched the control point
+
+// control point / generator constants
++#define ONS_CP_THINKRATE 0.2
+#define GEN_THINKRATE 1
+#define CPGEN_SPAWN_OFFSET ('0 0 1' * (PL_MAX_z - 13))
+#define CPGEN_WAYPOINT_OFFSET ('0 0 128')
+#define CPICON_OFFSET ('0 0 96')
+
+// list of generators on the map
+entity ons_worldgeneratorlist;
+.entity ons_worldgeneratornext;
+.entity ons_stalegeneratornext;
+
+// list of control points on the map
+entity ons_worldcplist;
+.entity ons_worldcpnext;
+.entity ons_stalecpnext;
+
+// list of links on the map
+entity ons_worldlinklist;
+.entity ons_worldlinknext;
+.entity ons_stalelinknext;
+
+// definitions
+.entity sprite;
+.string target2;
+.float iscaptured;
+.float islinked;
+.float isshielded;
+.float lasthealth;
+.float lastteam;
+.float lastshielded;
+.float lastcaptured;
+
+.float waslinked;
+
+float ons_stalemate;
+
+.float teleport_antispam;
+
+.float ons_roundlost;
+
+// waypoint sprites
+.entity bot_basewaypoint; // generator waypointsprite
+float wpforenemy_announced;
+
+.float isgenneighbor[17];
+.float iscpneighbor[17];
+float ons_notification_time[17];
+
+.float ons_overtime_damagedelay;
+
+.vector ons_deathloc;
+
+.entity ons_spawn_by;
+
+// declarations for functions used outside gamemode_onslaught.qc
+void ons_Generator_UpdateSprite(entity e);
+void ons_ControlPoint_UpdateSprite(entity e);
+float ons_ControlPoint_Attackable(entity cp, float teamnumber);
+
+// CaptureShield: Prevent capturing or destroying control point/generator if it is not available yet
+float ons_captureshield_force; // push force of the shield
+
+// bot player logic
+#define HAVOCBOT_ONS_ROLE_NONE 0
+#define HAVOCBOT_ONS_ROLE_DEFENSE 2
+#define HAVOCBOT_ONS_ROLE_ASSISTANT 4
+#define HAVOCBOT_ONS_ROLE_OFFENSE 8
+
+.entity havocbot_ons_target;
+
+.float havocbot_role_flags;
+.float havocbot_attack_time;
+
+void havocbot_role_ons_defense();
+void havocbot_role_ons_offense();
+void havocbot_role_ons_assistant();
+
+void havocbot_ons_reset_role(entity bot);
+void havocbot_goalrating_items(float ratingscale, vector org, float sradius);
+void havocbot_goalrating_enemyplayers(float ratingscale, vector org, float sradius);
+
+// score rule declarations
+#define ST_ONS_CAPS 1
+#define SP_ONS_CAPS 4
+#define SP_ONS_TAKES 6
+
+#endif
--- /dev/null
+ #include "base.qh"
+ #include "mutators.qh"
+ #include "gamemode_assault.qh"
+ #include "gamemode_ca.qh"
+ #include "gamemode_ctf.qh"
+ #include "gamemode_domination.qh"
+ #include "gamemode_keyhunt.qh"
+ #include "gamemode_keepaway.qh"
+ #include "gamemode_nexball.qh"
+ #include "gamemode_lms.qh"
+ #include "gamemode_invasion.qh"
+ #include "gamemode_race.qh"
+ #include "gamemode_cts.qh"
++#include "gamemode_onslaught.qh"
+
+ #include "mutator_dodging.qh"
+ #include "mutator_overkill.qh"
+ #include "mutator_nades.qh"
+ #include "mutator_buffs.qh"
../warpzonelib/common.qh
../warpzonelib/util_server.qh
../warpzonelib/server.qh
-
../common/constants.qh
+ ../common/stats.qh
../common/teams.qh
../common/util.qh
+ ../common/nades.qh
+ ../common/buffs.qh
../common/test.qh
../common/counting.qh
- ../common/items.qh
- ../common/explosion_equation.qh
../common/urllib.qh
../common/command/markup.qh
../common/command/rpn.qh
../common/monsters/sv_monsters.qh
../common/monsters/spawn.qh
+ ../common/weapons/config.qh
+ ../common/weapons/weapons.qh // TODO
+ weapons/accuracy.qh
+ weapons/common.qh
+ weapons/csqcprojectile.qh // TODO
+ weapons/hitplot.qh
+ weapons/selection.qh
+ weapons/spawning.qh
+ weapons/throwing.qh
+ weapons/tracing.qh
+ weapons/weaponstats.qh
+ weapons/weaponsystem.qh
+
+ t_items.qh
+
autocvars.qh
constants.qh
defs.qh // Should rename this, it has fields and globals
../common/notifications.qh // must be after autocvars
../common/deathtypes.qh // must be after notifications
- mutators/base.qh
- mutators/mutators.qh
- mutators/gamemode_assault.qh
- mutators/gamemode_ca.qh
- mutators/gamemode_ctf.qh
- mutators/gamemode_domination.qh
- mutators/gamemode_keyhunt.qh // TODO fix this
- mutators/gamemode_keepaway.qh
- mutators/gamemode_nexball.qh
- mutators/gamemode_lms.qh
- mutators/gamemode_invasion.qh
- mutators/gamemode_onslaught.qh
- mutators/mutator_dodging.qh
- mutators/mutator_nades.qh
+ mutators/mutators_include.qh
//// tZork Turrets ////
tturrets/include/turrets_early.qh
vehicles/vehicles_def.qh
+generator.qh
+controlpoint.qh
+
campaign.qh
../common/campaign_common.qh
../common/mapinfo.qh
command/cmd.qh
command/sv_cmd.qh
- accuracy.qh
- csqcprojectile.qh
+
../common/csqcmodel_settings.qh
../csqcmodellib/common.qh
../csqcmodellib/sv_model.qh
anticheat.qh
cheats.qh
- playerstats.qh
+ ../common/playerstats.qh
portals.qh
- g_hook.qh
- w_electro.qh
- w_laser.qh
+ g_hook.qh // TODO
scores.qh
spawnpoints.qh
+ mapvoting.qh
+
ipban.qh
race.qh
miscfunctions.qc
+ mutators/mutators.qc
+
waypointsprites.qc
bot/bot.qc
g_world.qc
g_casings.qc
+ mapvoting.qc
+
t_jumppads.qc
t_teleporters.qc
item_key.qc
secret.qc
- cl_weaponsystem.qc
- w_common.qc
-
- w_all.qc
+ weapons/accuracy.qc
+ weapons/common.qc
+ weapons/csqcprojectile.qc // TODO
+ weapons/hitplot.qc
+ weapons/selection.qc
+ weapons/spawning.qc
+ weapons/throwing.qc
+ weapons/tracing.qc
+ weapons/weaponstats.qc
+ weapons/weaponsystem.qc
+ ../common/weapons/config.qc
+ ../common/weapons/weapons.qc // TODO
t_items.qc
- cl_weapons.qc
cl_impulse.qc
ent_cs.qc
portals.qc
+generator.qc
+controlpoint.qc
+
target_spawn.qc
func_breakable.qc
target_music.qc
- ../common/items.qc
+ ../common/nades.qc
+ ../common/buffs.qc
-
- accuracy.qc
../csqcmodellib/sv_model.qc
- csqcprojectile.qc
playerdemo.qc
anticheat.qc
cheats.qc
- playerstats.qc
+ ../common/playerstats.qc
round_handler.qc
- ../common/explosion_equation.qc
-
../common/monsters/sv_monsters.qc
../common/monsters/monsters.qc
../common/monsters/spawn.qc
- mutators/base.qc
- mutators/gamemode_assault.qc
- mutators/gamemode_ca.qc
- mutators/gamemode_ctf.qc
- mutators/gamemode_domination.qc
- mutators/gamemode_freezetag.qc
- mutators/gamemode_keyhunt.qc
- mutators/gamemode_keepaway.qc
- mutators/gamemode_nexball.qc
- mutators/gamemode_onslaught.qc
- mutators/gamemode_lms.qc
- mutators/gamemode_invasion.qc
- mutators/mutator_invincibleproj.qc
- mutators/mutator_new_toys.qc
- mutators/mutator_nix.qc
- mutators/mutator_dodging.qc
- mutators/mutator_rocketflying.qc
- mutators/mutator_vampire.qc
- mutators/mutator_spawn_near_teammate.qc
- mutators/mutator_physical_items.qc
- mutators/sandbox.qc
- mutators/mutator_superspec.qc
- mutators/mutator_minstagib.qc
- mutators/mutator_touchexplode.qc
- mutators/mutator_pinata.qc
- mutators/mutator_midair.qc
- mutators/mutator_bloodloss.qc
- mutators/mutator_random_gravity.qc
- mutators/mutator_multijump.qc
- mutators/mutator_melee_only.qc
- mutators/mutator_nades.qc
- mutators/mutator_campcheck.qc
+ mutators/mutators_include.qc
../warpzonelib/anglestransform.qc
../warpzonelib/mathlib.qc
PlayerScore_Clear(e);
}
- void tdm_init();
void entcs_init();
void LogTeamchange(float player_id, float team_number, float type)
if(g_tdm)
{
ActivateTeamplay();
- tdm_init();
+ fraglimit_override = autocvar_g_tdm_point_limit;
+ leadlimit_override = autocvar_g_tdm_point_leadlimit;
if(autocvar_g_tdm_team_spawns)
have_team_spawns = -1; // request team spawns
+ MUTATOR_ADD(gamemode_tdm);
}
if(g_domination)
ActivateTeamplay();
fraglimit_override = autocvar_g_domination_point_limit;
leadlimit_override = autocvar_g_domination_point_leadlimit;
- MUTATOR_ADD(gamemode_domination);
+ if(autocvar_g_domination_roundbased && autocvar_g_domination_roundbased_point_limit)
+ fraglimit_override = autocvar_g_domination_roundbased_point_limit;
have_team_spawns = -1; // request team spawns
+ MUTATOR_ADD(gamemode_domination);
}
if(g_ctf)
ActivateTeamplay();
fraglimit_override = autocvar_capturelimit_override;
leadlimit_override = autocvar_captureleadlimit_override;
- MUTATOR_ADD(gamemode_ctf);
have_team_spawns = -1; // request team spawns
+ MUTATOR_ADD(gamemode_ctf);
}
if(g_lms)
ActivateTeamplay();
fraglimit_override = autocvar_g_ca_point_limit;
leadlimit_override = autocvar_g_ca_point_leadlimit;
- MUTATOR_ADD(gamemode_ca);
if(autocvar_g_ca_team_spawns)
have_team_spawns = -1; // request team spawns
+ MUTATOR_ADD(gamemode_ca);
}
if(g_keyhunt)
ActivateTeamplay();
fraglimit_override = autocvar_g_freezetag_point_limit;
leadlimit_override = autocvar_g_freezetag_point_leadlimit;
- MUTATOR_ADD(gamemode_freezetag);
if(autocvar_g_freezetag_team_spawns)
have_team_spawns = -1; // request team spawns
+ MUTATOR_ADD(gamemode_freezetag);
}
if(g_assault)
{
ActivateTeamplay();
- MUTATOR_ADD(gamemode_assault);
have_team_spawns = -1; // request team spawns
+ MUTATOR_ADD(gamemode_assault);
}
if(g_onslaught)
{
ActivateTeamplay();
+ fraglimit_override = autocvar_g_onslaught_point_limit;
have_team_spawns = -1; // request team spawns
MUTATOR_ADD(gamemode_onslaught);
}
if(g_race)
{
-
if(autocvar_g_race_teams)
{
ActivateTeamplay();
}
else
race_teams = 0;
-
qualifying_override = autocvar_g_race_qualifying_timelimit_override;
fraglimit_override = autocvar_g_race_laps_limit;
leadlimit_override = 0; // currently not supported by race
+
+ // we need to find out the correct value for g_race_qualifying
+ float want_qualifying = ((qualifying_override >= 0) ? qualifying_override : autocvar_g_race_qualifying_timelimit) > 0;
+
+ if(autocvar_g_campaign)
+ {
+ g_race_qualifying = 1;
+ independent_players = 1;
+ }
+ else if(!autocvar_g_campaign && want_qualifying)
+ {
+ g_race_qualifying = 2;
+ independent_players = 1;
+ race_fraglimit = (race_fraglimit >= 0) ? fraglimit_override : autocvar_fraglimit;
+ race_leadlimit = (race_leadlimit >= 0) ? leadlimit_override : autocvar_leadlimit;
+ race_timelimit = (race_timelimit >= 0) ? timelimit_override : autocvar_timelimit;
+ fraglimit_override = 0;
+ leadlimit_override = 0;
+ timelimit_override = autocvar_g_race_qualifying_timelimit;
+ }
+ else
+ {
+ g_race_qualifying = 0;
+ }
+
+ MUTATOR_ADD(gamemode_race);
}
if(g_cts)
g_race_qualifying = 1;
fraglimit_override = 0;
leadlimit_override = 0;
+ independent_players = 1;
+ MUTATOR_ADD(gamemode_cts);
}
if(g_nexball)
{
- fraglimit_override = autocvar_g_nexball_goallimit;
- leadlimit_override = autocvar_g_nexball_goalleadlimit;
- ActivateTeamplay();
- have_team_spawns = -1; // request team spawns
- MUTATOR_ADD(gamemode_nexball);
+ fraglimit_override = autocvar_g_nexball_goallimit;
+ leadlimit_override = autocvar_g_nexball_goalleadlimit;
+ ActivateTeamplay();
+ have_team_spawns = -1; // request team spawns
+ MUTATOR_ADD(gamemode_nexball);
}
if(g_keepaway)
cvar_set("g_race_qualifying_timelimit", ftos(qualifying_override));
}
- if(g_race)
- {
- // we need to find out the correct value for g_race_qualifying
- if(autocvar_g_campaign)
- {
- g_race_qualifying = 1;
- }
- else if(!autocvar_g_campaign && autocvar_g_race_qualifying_timelimit > 0)
- {
- g_race_qualifying = 2;
- race_fraglimit = autocvar_fraglimit;
- race_leadlimit = autocvar_leadlimit;
- race_timelimit = autocvar_timelimit;
- cvar_set("fraglimit", "0");
- cvar_set("leadlimit", "0");
- cvar_set("timelimit", ftos(autocvar_g_race_qualifying_timelimit));
- }
- else
- g_race_qualifying = 0;
- }
-
- if(g_race || g_cts)
- {
- if(g_race_qualifying)
- independent_players = 1;
-
- ScoreRules_race();
- }
-
InitializeEntity(world, default_delayedinit, INITPRIO_GAMETYPE_FALLBACK);
}
else
modifications = strcat(modifications, ", ", g_weaponarena_list, " Arena");
}
- if(autocvar_g_start_weapon_laser == 0)
+ if(cvar("g_balance_blaster_weaponstart") == 0)
modifications = strcat(modifications, ", No start weapons");
if(cvar("sv_gravity") < stof(cvar_defstring("sv_gravity")))
modifications = strcat(modifications, ", Low gravity");
if (g_grappling_hook)
s = strcat(s, "\n\n^3grappling hook^8 is enabled, press 'e' to use it\n");
+ if (cvar("g_nades"))
+ s = strcat(s, "\n\n^3nades^8 are enabled, press 'g' to use them\n");
+
if(cache_lastmutatormsg != autocvar_g_mutatormsg)
{
if(cache_lastmutatormsg)
else
{
// cover anything else by treating it like tdm with no teams spawned
- if(g_race)
- dm = race_teams;
- else
- dm = 2;
+ dm = 2;
ret_float = dm;
MUTATOR_CALLHOOK(GetTeamCount);
FOR_EACH_CLIENT(head)
{
float t;
- if(IS_PLAYER(head))
+ if(IS_PLAYER(head) || head.caplayer)
t = head.team;
else if(head.team_forced > 0)
t = head.team_forced; // reserve the spot
{
if(autocvar_g_campaign && pl && IS_REAL_CLIENT(pl))
return 1; // special case for campaign and player joining
- else if(g_domination)
- error("Too few teams available for domination\n");
- else if(g_ctf)
- error("Too few teams available for ctf\n");
- else if(g_keyhunt)
- error("Too few teams available for key hunt\n");
- else if(g_freezetag)
- error("Too few teams available for freeze tag\n");
else
- error("Too few teams available for team deathmatch\n");
+ error(sprintf("Too few teams available for %s\n", MapInfo_Type_ToString(MapInfo_CurrentGametype())));
}
// count how many players are in each team
}
if((autocvar_g_campaign) || (autocvar_g_changeteam_banned && self.wasplayer)) {
- sprint(self, "Team changes not allowed\n");
+ Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_TEAMCHANGE_NOTALLOWED);
return; // changing teams is not allowed
}
GetTeamCounts(self);
if(!TeamSmallerEqThanTeam(dteam, steam, self))
{
- sprint(self, "Cannot change to a larger/better/shinier team\n");
+ Send_Notification(NOTIF_ONE, self, MSG_INFO, INFO_TEAMCHANGE_LARGERTEAM);
return;
}
}
if(selected.deadflag == DEAD_NO)
Damage(selected, selected, selected, 100000, DEATH_AUTOTEAMCHANGE, selected.origin, '0 0 0');
- centerprint(selected, strcat("You have been moved into a different team to improve team balance\nYou are now on: ", Team_ColoredFullName(selected.team)));
- }
-
- // code from here on is just to support maps that don't have team entities
- void tdm_spawnteam (string teamname, float teamcolor)
- {
- entity e;
- e = spawn();
- e.classname = "tdm_team";
- e.netname = teamname;
- e.cnt = teamcolor;
- e.team = e.cnt + 1;
- }
-
- // spawn some default teams if the map is not set up for tdm
- void tdm_spawnteams()
- {
- float numteams;
-
- numteams = autocvar_g_tdm_teams_override;
- if(numteams < 2)
- numteams = autocvar_g_tdm_teams;
- numteams = bound(2, numteams, 4);
-
- tdm_spawnteam("Red", NUM_TEAM_1-1);
- tdm_spawnteam("Blue", NUM_TEAM_2-1);
- if(numteams >= 3)
- tdm_spawnteam("Yellow", NUM_TEAM_3-1);
- if(numteams >= 4)
- tdm_spawnteam("Pink", NUM_TEAM_4-1);
- }
-
- void tdm_delayedinit()
- {
- // if no teams are found, spawn defaults
- if (find(world, classname, "tdm_team") == world)
- tdm_spawnteams();
- }
-
- void tdm_init()
- {
- InitializeEntity(world, tdm_delayedinit, INITPRIO_GAMETYPE);
+ Send_Notification(NOTIF_ONE, selected, MSG_CENTER, CENTER_DEATH_SELF_AUTOTEAMCHANGE, selected.team);
}