ZIPEXCLUDE ?= -x\!*.pk3 -xr\!\.svn -x\!qcsrc
DIFF ?= diff
-# NOTE: use -DUSE_FTE instead of -TFTE here!
-# It will automagically add an engine check with -TID and then change back to -TFTE
-FTEQCCFLAGS_CSPROGS ?=
-
# xonotic build system overrides this by command line argument to turn off the check-cvars step
XON_BUILDSYSTEM =
seta hud_configure_bg_minalpha 0.25 "minimum panel background alpha when in hud configure mode"
seta hud_configure_grid_alpha 0.15 "alpha for visible grid when in configure mode"
+seta hud_cursormode 1 "handle mouse input in cursor mode when CSQC displays a cursor"
+
seta hud_fontsize 11 "text fontsize for the hud"
seta hud_width 560 "2D virtual width for the hud"
+seta hud_colorset_foreground_1 "2" "primary priority (important names, etc)"
+seta hud_colorset_foreground_2 "3" "secondary priority (items, locations, numbers, etc)"
+seta hud_colorset_foreground_3 "4" "tertiary priority or relatively inconsequential text"
+seta hud_colorset_foreground_4 "1" "notice/attention grabbing texting"
+seta hud_colorset_kill_1 "1" "'bad' or 'dangerous' text (death messages against you, kill notifications, etc)"
+seta hud_colorset_kill_2 "3" "similar to above, but less important... OR, a highlight out of above message type"
+seta hud_colorset_kill_3 "4" "'good' or 'beneficial' text (you fragging someone, etc)"
+seta hud_colorset_background "7" "neutral/unimportant text"
+
// general hud panel cvars (i.e. shouldn't be adjusted by a skin config)
seta hud_panel_weapons_ammo_full_shells 60 "show 100% of the status bar at this ammo count"
seta hud_panel_weapons_ammo_full_nails 320 "show 100% of the status bar at this ammo count"
// hud panel aliases
alias hud_panel_radar_rotate "toggle hud_panel_radar_rotation 0 1 2 3 4"
-alias +hud_panel_radar_maximized "cl_cmd hud_panel_radar_maximized 1"
-alias -hud_panel_radar_maximized "cl_cmd hud_panel_radar_maximized 0"
-alias hud_panel_radar_maximized "cl_cmd hud_panel_radar_maximized"
+alias +hud_panel_radar_maximized "cl_cmd hud radar 1"
+alias -hud_panel_radar_maximized "cl_cmd hud radar 0"
+alias hud_panel_radar_maximized "cl_cmd hud radar"
// other hud cvars
seta hud_showbinds 1 "what to show in the HUD to indicate certain keys to press: 0 display commands, 1 bound keys, 2 both"
seta hud_showbinds_limit 2 "maximum number of bound keys to show for a command. 0 for unlimited"
+set _hud_showbinds_reload 0 "set it to 1 to reload binds if you changed any. It is reset to 0 automatically"
seta hud_colorflash_alpha 0.5 "starting alpha of the color flash"
seta hud_shownames_maxdistance 5000 "alpha/size is 0 at this distance"
seta hud_shownames_antioverlap 1 "if two tags get too close to each other, fade out the one further away from you"
seta hud_shownames_antioverlap_distance 50 "2d distance to other tag after which to fade out"
-seta hud_shownames_offset 52 "offset (along z-axis) tag from player origin by this many units"
\ No newline at end of file
+seta hud_shownames_offset 52 "offset (along z-axis) tag from player origin by this many units"
seta hud_panel_weapons_ammo_color "" "color of status bar"
seta hud_panel_weapons_ammo_alpha "" "alpha of status bar"
seta hud_panel_weapons_timeout "" "panel disappears if you don't switch weapon for this amount of seconds"
-seta hud_panel_weapons_timeout_effect "" "disappearance effect: 0) no effect; 1) panel moves out of screen; 2) panel fades out"
-seta hud_panel_weapons_label "" "1 = show number of weapon, 2 = show bound key of weapon"
+seta hud_panel_weapons_timeout_effect "" "disappearance effect: 0) no effect; 1) panel fades out; 2) panel moves off the screen; 3) combination of 1 and 2"
+seta hud_panel_weapons_timeout_fadebgmin "" "minimum alpha of the panel background while in effect mode 1"
+seta hud_panel_weapons_timeout_fadefgmin "" "minimum alpha of the panel foreground while in effect mode 1"
+seta hud_panel_weapons_timeout_speed_in "" "speed that fading/moving onto the screen occurs"
+seta hud_panel_weapons_timeout_speed_out "" "speed that fading/moving off of the screen occurs"
+seta hud_panel_weapons_label "" "1 = show number of weapon, 2 = show bound key of weapon, 3 = show name of weapon"
seta hud_panel_weapons_accuracy "" "show accuracy color as the weapon icon background; colors can be configured with accuracy_color* cvars"
seta hud_panel_weapons_ammo "" "show ammo as a status bar"
seta hud_panel_weapons_onlyowned "" "show only owned weapons"
seta hud_panel_notify_bg_padding "" "if set to something else than \"\" = override default padding of contents from border"
seta hud_panel_notify_flip "" "order the list top to bottom instead of bottom to top"
seta hud_panel_notify_fontsize "" "multiplier for the font size used for player names in the panel"
-seta hud_panel_notify_print "" "also con_notify print the messages that are shown on the notify panel"
seta hud_panel_notify_fadetime "" "fade out time"
seta hud_panel_notify_time "" "time that a new entry stays until it fades out"
seta hud_panel_radar_scale "" "distance you can see on the team radar"
seta hud_panel_radar_maximized_scale "" "distance you can see on the radar when maximized"
seta hud_panel_radar_maximized_size "" "size of the radar when maximized"
+seta hud_panel_radar_maximized_rotation "" "rotation mode: you set what points up. 0 = player, 1 = west, 2 = south, 3 = east, 4 = north"
+seta hud_panel_radar_maximized_zoommode "" "zoom mode: 0 = zoomed by default, 1 = zoomed when +zoom, 2 = always zoomed, 3 = always zoomed out"
seta hud_panel_score "" "enable/disable this panel"
seta hud_panel_score_pos "" "position of this base of the panel"
set g_balance_uzi_first 1
set g_balance_uzi_first_damage 30
-set g_balance_uzi_first_headshotaddeddamage 0
set g_balance_uzi_first_force 50
set g_balance_uzi_first_spread 0.015
set g_balance_uzi_first_refire 0.2
set g_balance_uzi_first_ammo 1
set g_balance_uzi_sustained_damage 15
-set g_balance_uzi_sustained_headshotaddeddamage 0
set g_balance_uzi_sustained_force 27
set g_balance_uzi_sustained_spread 0.05
set g_balance_uzi_sustained_refire 0.1
set g_balance_uzi_first 1
set g_balance_uzi_first_damage 15 / f/ LOG: 22 -> 15
-set g_balance_uzi_first_headshotaddeddamage 0
set g_balance_uzi_first_force 50
set g_balance_uzi_first_spread 0.03
set g_balance_uzi_first_refire 0.2
set g_balance_uzi_first_ammo 2
set g_balance_uzi_sustained_damage 12 // 120 dps
-set g_balance_uzi_sustained_headshotaddeddamage 0
set g_balance_uzi_sustained_force 12
set g_balance_uzi_sustained_spread 0.06
set g_balance_uzi_sustained_refire 0.1
set g_balance_uzi_first 1
set g_balance_uzi_first_damage 14
-set g_balance_uzi_first_headshotaddeddamage 0
set g_balance_uzi_first_force 5
set g_balance_uzi_first_spread 0.03
set g_balance_uzi_first_refire 0.4
set g_balance_uzi_first_ammo 1
set g_balance_uzi_sustained_damage 12
-set g_balance_uzi_sustained_headshotaddeddamage 0
set g_balance_uzi_sustained_force 5
set g_balance_uzi_sustained_spread 0
set g_balance_uzi_sustained_refire 0.1
set g_balance_uzi_first 1
set g_balance_uzi_first_damage 14
-set g_balance_uzi_first_headshotaddeddamage 0
set g_balance_uzi_first_force 5
set g_balance_uzi_first_spread 0.03
set g_balance_uzi_first_refire 0.125
set g_balance_uzi_first_ammo 1
set g_balance_uzi_sustained_damage 10 // 100 dps
-set g_balance_uzi_sustained_headshotaddeddamage 0
set g_balance_uzi_sustained_force 5
set g_balance_uzi_sustained_spread 0.03
set g_balance_uzi_sustained_refire 0.1
set g_balance_uzi_first 1
set g_balance_uzi_first_damage 14
-set g_balance_uzi_first_headshotaddeddamage 0
set g_balance_uzi_first_force 5
set g_balance_uzi_first_spread 0.03
set g_balance_uzi_first_refire 0.125
set g_balance_uzi_first_ammo 1
set g_balance_uzi_sustained_damage 10 // 100 dps
-set g_balance_uzi_sustained_headshotaddeddamage 0
set g_balance_uzi_sustained_force 5
set g_balance_uzi_sustained_spread 0.03
set g_balance_uzi_sustained_refire 0.1
--- /dev/null
+// DP console is TURING COMPLETE!
+
+alias _bf_vcall "${$1} ${2- ?}"
+
+// number system
+// Xon RPN: set $_bf_zero 0
+// Xon RPN: alias _bf_inc "rpn /$1 $2 1 add def"
+// Xon RPN: alias _bf_dec "rpn /$1 $2 1 sub def"
+
+// unary
+// decimal | unary
+// 0 | 0
+// 1 | +
+// 2 | ++
+// -1 | -
+// -2 | --
+alias _bf_zero "set $1 0"
+alias _bf_one "set $1 +"
+alias _bf_minus_one "set $1 -"
+alias _bf_return_3 "set $1 $3"
+alias _bf_return_4 "set $1 $4"
+set _bf_zero "0"
+alias _bf_inc_loop1 "set _bf_tmp_$3 _bf_inc_loop2; set _bf_tmp_+$2 _bf_return_3; _bf_vcall _bf_tmp_$3 $*"
+alias _bf_inc_loop2 "set _bf_tmp_$2 _bf_inc_loop3; set _bf_tmp_-$4 _bf_return_4; _bf_vcall _bf_tmp_$2 $*"
+alias _bf_inc_loop3 "_bf_inc_loop1 $1 $2 +$3 -$4"
+alias _bf_inc "set _bf_tmp_$2 _bf_inc_loop1; set _bf_tmp_0 _bf_one; set _bf_tmp_- _bf_zero; _bf_vcall _bf_tmp_$2 $1 $2 + -"
+alias _bf_dec_loop1 "set _bf_tmp_$3 _bf_dec_loop2; set _bf_tmp_-$2 _bf_return_3; _bf_vcall _bf_tmp_$3 $*"
+alias _bf_dec_loop2 "set _bf_tmp_$2 _bf_dec_loop3; set _bf_tmp_+$4 _bf_return_4; _bf_vcall _bf_tmp_$2 $*"
+alias _bf_dec_loop3 "_bf_dec_loop1 $1 $2 -$3 +$4"
+alias _bf_dec "set _bf_tmp_$2 _bf_dec_loop1; set _bf_tmp_0 _bf_minus_one; set _bf_tmp_+ _bf_zero; _bf_vcall _bf_tmp_$2 $1 $2 - +"
+// end of unary
+
+// interpreter state
+set bf_input ""
+alias _bf_clearstate "set _bf_left \"\"; set _bf_right \"\"; set _bf_register $_bf_zero; set _bf_execstack \"\""
+alias _bf_dumpstate "echo rev($_bf_left) < $_bf_register > $_bf_right"
+
+// a STACK!
+alias _bf_pop_get "set $2 \"${3 ?}\"; set $1 \"${4- ?}\""
+alias _bf_pop_dispatch "_bf_pop_get $1 $2 $_bf_popstack_"
+// usage: _bf_pop stackvar outvar defaultvalue
+alias _bf_pop "set _bf_popstack_ \"${$1 ?}\"; set \"_bf_popstack_${$1 ?}\" \"${3 ?}\"; _bf_pop_dispatch $*"
+// usage: _bf_push stackvar value
+alias _bf_push "set $1 \"$2 ${$1 ?}\""
+
+// skip mode: skip until matching ] (1 on _bf_execstack), then continue executing
+alias _bf_skip_ "echo PROGRAMM FELL OFF THE EDGE"
+alias _bf_skip_+ "_bf_skip_${* ?}"
+alias _bf_skip_- "_bf_skip_${* ?}"
+alias _bf_skip_< "_bf_skip_${* ?}"
+alias _bf_skip_> "_bf_skip_${* ?}"
+alias _bf_skip_. "_bf_skip_${* ?}"
+alias _bf_skip_, "_bf_skip_${* ?}"
+alias _bf_skip_endloop_0 "_bf_skip_${* ?}" // continue skipping
+alias _bf_skip_endloop_1 "bf_${* ?}" // back to execution
+alias _bf_skip_endloop_dispatch "_bf_skip_endloop_$_bf_stackval ${* ?}"
+alias _bf_skip_] "_bf_pop _bf_execstack _bf_stackval; _bf_skip_endloop_dispatch ${* ?}"
+alias _bf_skip_[ "_bf_push _bf_execstack 0; _bf_skip_${* ?}"
+// enter
+alias _bf_skiploop "_bf_push _bf_execstack 1; _bf_skip_${* ?}"
+
+// run mode: execute until matching ] (1 on _bf_execstack), then exit
+alias bf_ "echo PROGRAMM FELL OFF THE EDGE"
+alias bf_+ "_bf_inc _bf_register $_bf_register; bf_${* ?}"
+alias bf_- "_bf_dec _bf_register $_bf_register; bf_${* ?}"
+alias bf_< "_bf_push _bf_left $_bf_register; _bf_pop _bf_right _bf_register $_bf_zero; bf_${* ?}"
+alias bf_> "_bf_push _bf_right $_bf_register; _bf_pop _bf_left _bf_register $_bf_zero; bf_${* ?}"
+alias bf_. "echo $_bf_register; bf_${* ?}"
+// note: on EOF, we don't change the register value!
+alias _bf_input_get "set _bf_register $_bf_inputval; bf_${* ?}" // read input
+alias _bf_input_eof "bf_${* ?}" // at EOF, just continue
+alias _bf_input_dispatch "set _bf_inputval_ _bf_input_get; set _bf_inputval_$_bf_inputval _bf_input_eof; _bf_vcall _bf_inputval_ ${* ?}"
+alias bf_, "_bf_pop bf_input _bf_inputval; _bf_input_dispatch ${* ?}"
+alias _bf_endloop_0 "echo IN SKIP MODE, EXCEPT NOT"
+alias _bf_endloop_1 "" // back to caller
+alias _bf_endloop_ "echo PROGRAMM FELL OFF THE EDGE"
+alias _bf_endloop_dispatch "_bf_endloop_$_bf_stackval ${* ?}"
+alias bf_] "_bf_pop _bf_execstack _bf_stackval; _bf_endloop_dispatch ${* ?}"
+// enter
+alias _bf_runloop "_bf_push _bf_execstack 1; bf_$*; bf_[ ${* ?}"
+// loop dispatcher
+alias bf_[ "set _bf_runloop_$_bf_zero _bf_runloop; set _bf_runloop_$_bf_register _bf_skiploop; _bf_vcall _bf_runloop_$_bf_zero ${* ?}"
+
+// start it
+alias bf_exec "_bf_clearstate; _bf_push _bf_execstack 1; bf_$1 ]"
+
+// "cat"
+// Xon RPN: bf_input "1 2 3 4 5"
+bf_input "+ ++ +++ ++++ +++++"
+bf_exec "[ - ] - , + [ - . + [ - ] - , + ]"
+
+// output 42
+// Xon RPN: bf_input "12 6 9"
+bf_input "++++++++++++ ++++++ +++++++++"
+bf_exec ", > , > , < [ > [ - > + > + < < ] > > [ - < < + > > ] < < < - ] < [ - > > > - < < < ] > > > ."
+
+// hello world
+bf_exec "+ + + + + + + + + + [ > + + + + + + + > + + + + + + + + + + > + + + > + < < < < - ] > + + . > + . + + + + + + + . . + + + . > + + . < < + + + + + + + + + + + + + + + . > . + + + . - - - - - - . - - - - - - - - . > + . > ."
_if_dedicated alias if_client ""
if_client alias if_dedicated ""
+// for easy access by QC
+if_dedicated set is_dedicated 1
+if_client set is_dedicated 0
+
if_dedicated "alias" qc_cmd_sv "sv_cmd $$*"
if_client "alias" qc_cmd_sv "sv_cmd $$*"
// if_client "alias" qc_cmd_sv "echo This command only works on servers: sv_cmd $${* !}"
// generic commands (across all programs)
alias addtolist "qc_cmd_svmenu addtolist ${* ?}" // Add a string to a cvar
-alias qc_curl "qc_cmd_svmenu curl ${* ?}" // curl requests
alias dumpcommands "qc_cmd_svmenu dumpcommands ${* ?}" // Dump all commands on the program to *_cmd_dump.txt
+alias dumpnotifs "qc_cmd_svcl dumpnotifs ${* ?}" // Dump all notifications into notifications_dump.txt
alias maplist "qc_cmd_svmenu maplist ${* ?}" // Automatic control of maplist
-alias nextframe "qc_cmd_svmenu nextframe ${* ?}" // do something next frame
+alias nextframe "qc_cmd_svmenu nextframe ${* ?}" // Execute the given command next frame of this VM
+alias qc_curl "qc_cmd_svmenu qc_curl ${* ?}" // Queries a URL
alias removefromlist "qc_cmd_svmenu removefromlist ${* ?}" // Remove a string from a cvar
+alias restartnotifs "qc_cmd_svcl restartnotifs ${* ?}" // Re-initialize all notifications
alias rpn "qc_cmd_svmenu rpn ${* ?}" // RPN calculator
//alias settemp "qc_cmd_svmenu settemp ${* ?}" // Temporarily set a value to a cvar which is restored later
//alias settemp_restore "qc_cmd_svmenu settemp_restore ${* ?}" // Restore all cvars set by settemp command
alias bsp "ls maps/*.bsp"
alias chmap "changelevel ${* ?}"
alias clearmap "disconnect"
+alias devmap "set _developer_save $developer; set developer 1; changelevel ${* ?}; set developer $_developer_save"
alias ply "playdemo $1"
alias rec "record demos/${1 !}"
alias search "apropos ${* ?}"
// =================================
set sv_vote_call 1 "Allow users to call a vote for the commands in sv_vote_commands"
set sv_vote_change 1 "Allow voters to change their mind after already voting"
-set sv_vote_commands "restart fraglimit chmap gotomap nextmap endmatch reducematchtime extendmatchtime allready kick cointoss movetoauto" "these commands can be voted"
+set sv_vote_commands "restart fraglimit chmap gotomap nextmap endmatch reducematchtime extendmatchtime allready kick cointoss movetoauto shuffleteams" "these commands can be voted"
set sv_vote_only_commands ""
set sv_vote_master_commands "movetored movetoblue movetoyellow movetopink" "Extra commands which vote masters can execute by themselves, along with the normal sv_vote_commands." // maybe add kickban here (but then sv_vote_master 0)
set sv_vote_master 1 "Allows the use of the vote master system"
set sv_vote_stop 15 "a player can not call a vote again for this many seconds when he stopped this vote (e.g. to correct it)"
set sv_vote_majority_factor 0.5 "What percentage of the PLAYERS constitute a majority? (Must be at least 0.5, recommended: 0.5)"
set sv_vote_majority_factor_of_voted 0.5 "What percentage of the VOTERS constitute a majority too? (Must be at least 0.5, recommended: 0.5)"
+set sv_vote_gamestart 0 "Allow voting during map change"
// when disabled, don't allow game type changes "note: set these two equal to JUST support simple majorities"
set sv_vote_override_mostrecent 0
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"
+seta cl_spawnzoom 1 "zoom effect immediately when a player spawns"
+seta cl_spawnzoom_speed 1 "speed at which zooming occurs while spawning"
+seta cl_spawnzoom_factor 2 "factor of zoom while spawning"
seta cl_zoomfactor 5 "how much +zoom will zoom (1-16)"
seta cl_zoomspeed 8 "how fast it will zoom (0.5-16), negative values mean instant zoom"
seta cl_zoomsensitivity 0 "how zoom changes sensitivity (0 = weakest, 1 = strongest)"
seta cl_eventchase_death 1 "camera goes into 3rd person mode when the player is dead"
seta cl_eventchase_distance 140 "final camera distance"
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"
//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_player_viewoffset "0 0 35" "view offset of the player model"
set sv_player_mins "-16 -16 -24" "playermodel mins"
set sv_player_maxs "16 16 45" "playermodel maxs"
-set sv_player_headsize "24 24 12" "playermodel headshot bbox size (centered at top of player bbox, preview with r_showbboxes)" // actually SHOULD be 19.2 19.2 10 according to docs
set sv_player_crouch_viewoffset "0 0 20" "view offset of the player model when crouched"
set sv_player_crouch_mins "-16 -16 -24" "mins of a crouched playermodel"
set sv_player_crouch_maxs "16 16 25" "maxs of a crouched playermodel"
set sv_jumpspeedcap_min "" "lower bound on the baseline velocity of a jump; final velocity will be >= (jumpheight * min + jumpheight)"
set sv_jumpspeedcap_max "" "upper bound on the baseline velocity of a jump; final velocity will be <= (jumpheight * max + jumpheight)"
set sv_jumpspeedcap_max_disable_on_ramps 0 "disable upper baseline velocity bound on ramps to preserve the old rampjump style"
-set sv_player_jumpanim_minfall 48 "minimum distance player has to have below their feet before the jump animation will be activated (only when falling, +jump will play anim instantly)"
seta sv_precacheplayermodels 1
seta sv_precacheweapons 0
seta g_balance_teams 1 "automatically balance out players entering instead of asking them for their preferred team"
seta g_balance_teams_prevent_imbalance 1 "prevent players from changing to larger teams"
-set g_balance_teams_scorefactor 0.34 "at the end of the game, take score into account instead of team size by this amount (beware: values over 0.5 mean that a x:0 score imbalance will cause ALL new players to prefer the losing team at the end, despite numbers)"
+set g_balance_teams_scorefactor 0.25 "at the end of the game, take score into account instead of team size by this amount (beware: values over 0.5 mean that a x:0 score imbalance will cause ALL new players to prefer the losing team at the end, despite numbers)"
set g_changeteam_banned 0 "not allowed to change team"
set g_changeteam_fragtransfer 0 "% of frags you get to keep when you change teams (rounded down)"
// startmap_dm is used when running with the -listen or -dedicated commandline options
set serverconfig server.cfg
+alias loadconfig "cvar_resettodefaults_saveonly; exec ${* !}"
set _sv_init 0
alias startmap_dm "set _sv_init 0; map _init/_init; exec $serverconfig; set _sv_init 1"
set g_chat_flood_burst_tell 2 "private chat: allow bursts of so many chat lines"
set g_chat_flood_notify_flooder 1 "when 0, the flooder still can see his own message"
set g_chat_teamcolors 0 "colorize nicknames in team color for chat"
+set g_chat_tellprivacy 1 "when disabled, tell messages are also sent to the server console log... otherwise they're kept private between players."
set g_nick_flood_timeout 120 "time after which nick flood protection resets (set to 0 to disable nick flood checking)"
set g_nick_flood_penalty 0.5 "duration of the nick flood penalty"
set g_nick_flood_penalty_yellow 3 "number of changes to allow before warning and movement blocking"
con_chatpos -9
con_chatsize 10
con_chatwidth 0.6
+con_notify 0
con_notifysize 10
con_notifyalign 0
seta scoreboard_border_thickness 1 "scoreboard border thickness"
seta scoreboard_accuracy_border_thickness 1 "accuracy stats border thickness"
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_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 scoreboard_bg_scale 0.25 "scale for the tiled scoreboard background"
+seta scoreboard_respawntime_decimals 1 "decimal places to show for the respawntime countdown display on the scoreboard"
seta accuracy_color_levels "0 20 100" "accuracy values at which a specified color (accuracy_color<X>) will be used. If your accuracy is between 2 of these values then a mix of the Xth and X+1th colors will be used. You can specify up to 10 values, in increasing order"
seta accuracy_color0 "1 0 0"
set con_completion_tdem *.dem
set con_completion_exec *.cfg
set con_completion_chmap map
+set con_completion_devmap map
set con_completion_gotomap map
set con_completion_vmap map
set con_completion_vnextmap map
set sv_foginterval 1 "force enable fog in regular intervals"
+set g_physical_items 0 "1 uses ODE physics for dropped weapons, 2 for all items, requires physics_ode to be enabled"
+set g_physical_items_damageforcescale 3 "how affected physical weapons are by damage"
+set g_physical_items_reset 1 "return map items to their original lotation after being picked up"
+
// Audio track names (for old-style "cd loop NUMBER" usage)
set _cdtrack_first "1"
alias _cdtrack_0 "g_cdtracks_remaplist \"$g_cdtracks_remaplist $1\""
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 g_loituma 0 "no, really"
set _urllib_nextslot 0 "temp variable"
set cl_warpzone_usetrace 1 "do not touch"
seta cl_noantilag 0 "turn this on if you believe antilag is bad"
-set sv_pitch_min -35 "minimum aiming angle for shooting direction display of the gun"
-set sv_pitch_max 35 "maximum aiming angle for shooting direction display of the gun"
-set sv_pitch_fixyaw 0 "workaround to fix the aiming direction on stupidly made player models, FIXME fix the models and set this to 0"
-
set rescan_pending 0 "set to 1 to schedule a fs_rescan at the end of this match"
set g_mapinfo_allow_unsupported_modes_and_let_stuff_break "0" "set to 1 to be able to force game types using g_ cvars even if the map does not support them"
set waypoint_benchmark 0 "quit after waypoint loading to benchmark bot navigation code"
set g_debug_bot_commands 0 "print scripted bot commands before executing"
set g_debug_defaultsounds 0 "always use default sounds"
-set sv_use_csqc_players 1 "set to 0 to disable CSQC players for better Xonotic 0.5 compat"
set cl_precacheplayermodels 0 "TODO please check if this needs to be 1 or if precaching a model the server already requested is fast enough to do it at runtime"
-seta cl_forceplayermodels 0 "make everyone look like your own model (requires server to have sv_use_csqc_players 1 and sv_defaultcharacter 0)"
-seta cl_forceplayercolors 0 "make everyone look like your own color (requires server to have sv_use_csqc_players 1 and sv_defaultcharacter 0, and is ignored in teamplay with more than two teams)"
-seta cl_forcemyplayermodel "" "set to the model file name you want to show yourself as (requires server to have sv_use_csqc_players 1; does not affect how enemies look with cl_forceplayermodels)"
-seta cl_forcemyplayerskin 0 "set to the skin number you want to show yourself as (requires server to have sv_use_csqc_players 1; does not affect how enemies look with cl_forceplayermodels)"
-seta cl_forcemyplayercolors 0 "set to the color value (encoding is same as _cl_color) for your own player model (requires server to have sv_use_csqc_players 1, and is ignored in teamplay; does not affect how enemies look with cl_forceplayermodels)"
-seta cl_movement_errorcompensation 1 "try to compensate for prediction errors and reduce preceived lag (requires server to have sv_use_csqc_players 1)"
+seta cl_forceplayermodels 0 "make everyone look like your own model (requires server to have sv_defaultcharacter 0)"
+seta cl_forceplayercolors 0 "make everyone look like your own color (requires server to have sv_defaultcharacter 0, and is ignored in teamplay with more than two teams)"
+seta cl_forcemyplayermodel "" "set to the model file name you want to show yourself as (does not affect how enemies look with cl_forceplayermodels)"
+seta cl_forcemyplayerskin 0 "set to the skin number you want to show yourself as (does not affect how enemies look with cl_forceplayermodels)"
+seta cl_forcemyplayercolors 0 "set to the color value (encoding is same as _cl_color) for your own player model (ignored in teamplay; does not affect how enemies look with cl_forceplayermodels)"
+seta cl_movement_errorcompensation 1 "try to compensate for prediction errors and reduce preceived lag"
// debug cvars for keyhunt attaching
set _angles "0 0 0"
// use fake light if map has no lightmaps
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
+
// strength sound settings
set sv_strengthsound_antispam_time 0.1 "minimum distance of strength sounds"
set sv_strengthsound_antispam_refire_threshold 0.04 "apply minimum distance only if refire of the gun is smaller than this"
exec vehicles.cfg
exec crosshairs.cfg
exec gamemodes.cfg
+exec notifications.cfg
// load console command aliases and settings
exec commands.cfg
set g_ctf_flag_health 0
set g_ctf_flag_dropped_waypoint 2 "show dropped flag waypointsprite when a flag is lost. 1 = team only, 2 = for all players"
set g_ctf_flag_dropped_floatinwater 200 "move upwards while in water at this velocity"
-set g_ctf_flag_pickup_verbosename 0 "show the name of the person who picked up the flag too"
set g_ctf_throw 1 "throwing allows circumventing carrierkill score, so enable this with care!"
set g_ctf_throw_angle_max 90 "maximum upwards angle you can throw the flag"
set g_ctf_throw_angle_min -90 "minimum downwards angle you can throw the flag"
set g_lms_lives_override -1
set g_lms_regenerate 0
set g_lms_campcheck_interval 10
-set g_lms_campcheck_message "^1Don't camp!"
set g_lms_campcheck_damage 100
set g_lms_campcheck_distance 1800
set g_lms_last_join 3 "if g_lms_join_anytime is false, new players can only join if the worst active player has more than (fraglimit - g_lms_last_join) lives"
set g_onslaught_cp_buildhealth 100
set g_onslaught_cp_buildtime 5
set g_onslaught_cp_regen 20
+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_spawn_at_controlpoints 0
+set g_onslaught_spawn_at_generator 0
// ======
seta hud_panel_weapons_accuracy "1"
seta hud_panel_weapons_label "1"
seta hud_panel_weapons_complainbubble "1"
-seta hud_panel_weapons_complainbubble_padding "2"
-seta hud_panel_weapons_complainbubble_time "4"
-seta hud_panel_weapons_complainbubble_fadetime "2"
+seta hud_panel_weapons_complainbubble_padding "-1"
+seta hud_panel_weapons_complainbubble_time "0"
+seta hud_panel_weapons_complainbubble_fadetime "1"
seta hud_panel_weapons_complainbubble_color_outofammo "0.8 0 0"
seta hud_panel_weapons_complainbubble_color_donthave "0.8 0.5 0"
seta hud_panel_weapons_complainbubble_color_unavailable "0 0.3 0.8"
seta hud_panel_weapons_ammo_color "0 1 0"
seta hud_panel_weapons_ammo_alpha "1"
seta hud_panel_weapons_aspect "2"
-seta hud_panel_weapons_timeout "5"
-seta hud_panel_weapons_timeout_effect "3"
+seta hud_panel_weapons_timeout "1"
+seta hud_panel_weapons_timeout_effect "1"
+seta hud_panel_weapons_timeout_fadebgmin "0.4"
+seta hud_panel_weapons_timeout_fadefgmin "0.4"
+seta hud_panel_weapons_timeout_speed_in "0.25"
+seta hud_panel_weapons_timeout_speed_out "0.75"
seta hud_panel_weapons_onlyowned "1"
seta hud_panel_ammo 1
seta hud_panel_notify_bg_padding ""
seta hud_panel_notify_flip "0"
seta hud_panel_notify_fontsize "0.8"
-seta hud_panel_notify_print "1"
seta hud_panel_notify_time "10"
seta hud_panel_notify_fadetime "3"
seta hud_panel_radar_scale "4096"
seta hud_panel_radar_maximized_scale "8192"
seta hud_panel_radar_maximized_size "0.5 0.5"
+seta hud_panel_radar_maximized_rotation "1"
+seta hud_panel_radar_maximized_zoommode "3"
seta hud_panel_score 1
seta hud_panel_score_pos "0.890000 0.030000"
seta hud_panel_weapons_accuracy "1"
seta hud_panel_weapons_label "1"
seta hud_panel_weapons_complainbubble "1"
-seta hud_panel_weapons_complainbubble_padding "-10"
-seta hud_panel_weapons_complainbubble_time "1"
-seta hud_panel_weapons_complainbubble_fadetime "0.25"
+seta hud_panel_weapons_complainbubble_padding "-1"
+seta hud_panel_weapons_complainbubble_time "0"
+seta hud_panel_weapons_complainbubble_fadetime "1"
seta hud_panel_weapons_complainbubble_color_outofammo "0.8 0 0"
seta hud_panel_weapons_complainbubble_color_donthave "0.8 0.5 0"
seta hud_panel_weapons_complainbubble_color_unavailable "0 0.3 0.8"
seta hud_panel_weapons_aspect "2"
seta hud_panel_weapons_timeout "0"
seta hud_panel_weapons_timeout_effect "0"
+seta hud_panel_weapons_timeout_fadebgmin "0"
+seta hud_panel_weapons_timeout_fadefgmin "0"
+seta hud_panel_weapons_timeout_speed_in "0.25"
+seta hud_panel_weapons_timeout_speed_out "0.75"
seta hud_panel_weapons_onlyowned "1"
seta hud_panel_ammo 1
seta hud_panel_notify_bg_padding ""
seta hud_panel_notify_flip "1"
seta hud_panel_notify_fontsize "0.8"
-seta hud_panel_notify_print "0"
seta hud_panel_notify_time "10"
seta hud_panel_notify_fadetime "3"
seta hud_panel_radar_scale "4096"
seta hud_panel_radar_maximized_scale "8192"
seta hud_panel_radar_maximized_size "0.5 0.5"
+seta hud_panel_radar_maximized_rotation "1"
+seta hud_panel_radar_maximized_zoommode "3"
seta hud_panel_score 1
seta hud_panel_score_pos "0.465000 0.045000"
seta hud_panel_weapons_accuracy "1"
seta hud_panel_weapons_label "1"
seta hud_panel_weapons_complainbubble "1"
-seta hud_panel_weapons_complainbubble_padding "-10"
-seta hud_panel_weapons_complainbubble_time "1"
-seta hud_panel_weapons_complainbubble_fadetime "0.25"
+seta hud_panel_weapons_complainbubble_padding "-1"
+seta hud_panel_weapons_complainbubble_time "0"
+seta hud_panel_weapons_complainbubble_fadetime "1"
seta hud_panel_weapons_complainbubble_color_outofammo "0.8 0 0"
seta hud_panel_weapons_complainbubble_color_donthave "0.8 0.5 0"
seta hud_panel_weapons_complainbubble_color_unavailable "0 0.3 0.8"
seta hud_panel_weapons_aspect "2"
seta hud_panel_weapons_timeout "0"
seta hud_panel_weapons_timeout_effect "0"
+seta hud_panel_weapons_timeout_fadebgmin "0"
+seta hud_panel_weapons_timeout_fadefgmin "0"
+seta hud_panel_weapons_timeout_speed_in "0.25"
+seta hud_panel_weapons_timeout_speed_out "0.75"
seta hud_panel_weapons_onlyowned "1"
seta hud_panel_ammo 1
seta hud_panel_notify_bg_padding ""
seta hud_panel_notify_flip "1"
seta hud_panel_notify_fontsize "0.8"
-seta hud_panel_notify_print "0"
seta hud_panel_notify_time "10"
seta hud_panel_notify_fadetime "3"
seta hud_panel_radar_scale "4096"
seta hud_panel_radar_maximized_scale "8192"
seta hud_panel_radar_maximized_size "0.5 0.5"
+seta hud_panel_radar_maximized_rotation "1"
+seta hud_panel_radar_maximized_zoommode "3"
seta hud_panel_score 1
seta hud_panel_score_pos "0.465000 0.045000"
seta hud_panel_weapons_accuracy "1"
seta hud_panel_weapons_label "1"
seta hud_panel_weapons_complainbubble "1"
-seta hud_panel_weapons_complainbubble_padding "-10"
-seta hud_panel_weapons_complainbubble_time "1"
-seta hud_panel_weapons_complainbubble_fadetime "0.25"
+seta hud_panel_weapons_complainbubble_padding "-1"
+seta hud_panel_weapons_complainbubble_time "0"
+seta hud_panel_weapons_complainbubble_fadetime "1"
seta hud_panel_weapons_complainbubble_color_outofammo "0.8 0 0"
seta hud_panel_weapons_complainbubble_color_donthave "0.8 0.5 0"
seta hud_panel_weapons_complainbubble_color_unavailable "0 0.3 0.8"
seta hud_panel_weapons_aspect "2"
seta hud_panel_weapons_timeout "3"
seta hud_panel_weapons_timeout_effect "1"
+seta hud_panel_weapons_timeout_fadebgmin "0"
+seta hud_panel_weapons_timeout_fadefgmin "0"
+seta hud_panel_weapons_timeout_speed_in "0.25"
+seta hud_panel_weapons_timeout_speed_out "0.75"
seta hud_panel_weapons_onlyowned "1"
seta hud_panel_ammo 1
seta hud_panel_notify_bg_padding ""
seta hud_panel_notify_flip "0"
seta hud_panel_notify_fontsize "0.8"
-seta hud_panel_notify_print "1"
seta hud_panel_notify_time "10"
seta hud_panel_notify_fadetime "3"
seta hud_panel_radar_scale "4096"
seta hud_panel_radar_maximized_scale "8192"
seta hud_panel_radar_maximized_size "0.5 0.5"
+seta hud_panel_radar_maximized_rotation "1"
+seta hud_panel_radar_maximized_zoommode "3"
seta hud_panel_score 1
seta hud_panel_score_pos "0.020000 0.920000"
seta hud_panel_weapons_accuracy "1"
seta hud_panel_weapons_label "1"
seta hud_panel_weapons_complainbubble "1"
-seta hud_panel_weapons_complainbubble_padding "-10"
-seta hud_panel_weapons_complainbubble_time "1"
-seta hud_panel_weapons_complainbubble_fadetime "0.25"
+seta hud_panel_weapons_complainbubble_padding "-1"
+seta hud_panel_weapons_complainbubble_time "0"
+seta hud_panel_weapons_complainbubble_fadetime "1"
seta hud_panel_weapons_complainbubble_color_outofammo "0.8 0 0"
seta hud_panel_weapons_complainbubble_color_donthave "0.8 0.5 0"
seta hud_panel_weapons_complainbubble_color_unavailable "0 0.3 0.8"
seta hud_panel_weapons_aspect "2"
seta hud_panel_weapons_timeout "0"
seta hud_panel_weapons_timeout_effect "0"
+seta hud_panel_weapons_timeout_fadebgmin "0"
+seta hud_panel_weapons_timeout_fadefgmin "0"
+seta hud_panel_weapons_timeout_speed_in "0.25"
+seta hud_panel_weapons_timeout_speed_out "0.75"
seta hud_panel_weapons_onlyowned "0"
seta hud_panel_ammo 1
seta hud_panel_notify_bg_padding ""
seta hud_panel_notify_flip "0"
seta hud_panel_notify_fontsize "1"
-seta hud_panel_notify_print "1"
seta hud_panel_notify_time "10"
seta hud_panel_notify_fadetime "3"
seta hud_panel_radar_scale "4096"
seta hud_panel_radar_maximized_scale "8192"
seta hud_panel_radar_maximized_size "0.5 0.5"
+seta hud_panel_radar_maximized_rotation "1"
+seta hud_panel_radar_maximized_zoommode "3"
seta hud_panel_score 1
seta hud_panel_score_pos "0.760000 0.910000"
sex Male
weight 105
age 26
+bone_upperbody spine2
+bone_aim0 0.25 spine2
+bone_aim1 0.4 spine4
+bone_aim2 0.2 upperarm_L
+bone_aim3 0.35 bip01 r hand
+bone_weapon bip01 r hand
+fixbone 1
Heavyweight Xonotic Solider
sex Male
weight 85
age 16
+bone_upperbody spine2
+bone_aim0 0.25 spine2
+bone_aim1 0.4 spine4
+bone_aim2 0.35 bip01 r hand
+bone_weapon bip01 r hand
+fixbone 1
Lightweight Xonotic Solider
sex Male
weight 90
age 20
+bone_upperbody spine2
+bone_aim0 0.25 spine2
+bone_aim1 0.4 spine4
+bone_aim2 0.35 bip01 r hand
+bone_weapon bip01 r hand
+fixbone 1
Heavyweight Xonotic Solider
sex Male
weight 87
age 18
+bone_upperbody spine2
+bone_aim0 0.25 spine2
+bone_aim1 0.4 spine4
+bone_aim2 0.35 bip01 r hand
+bone_weapon bip01 r hand
+fixbone 1
Mediumweight Xonotic Solider
sex Male
weight 88
age 31
+bone_upperbody spine2
+bone_aim0 0.25 spine2
+bone_aim1 0.4 spine4
+bone_aim2 0.2 upperarm_L
+bone_aim3 0.35 bip01 r hand
+bone_weapon bip01 r hand
+fixbone 1
Heavyweight Xonotic Solider
sex Male
weight 90
age 31
+bone_upperbody spine2
+bone_aim0 0.25 spine2
+bone_aim1 0.4 spine4
+bone_aim2 0.2 upperarm_L
+bone_aim3 0.35 bip01 r hand
+bone_weapon bip01 r hand
+fixbone 1
Heavyweight Xonotic Solider
sex Male
weight 92
age 31
+bone_upperbody spine2
+bone_aim0 0.25 spine2
+bone_aim1 0.4 spine4
+bone_aim2 0.2 upperarm_L
+bone_aim3 0.35 bip01 r hand
+bone_weapon bip01 r hand
+fixbone 1
Heavyweight Xonotic Solider
sex Male
weight 210
age 26
+bone_upperbody spine2
+bone_aim0 0.25 spine2
+bone_aim1 0.4 spine4
+bone_aim2 0.2 upperarm_L
+bone_aim3 0.35 bip01 r hand
+bone_weapon bip01 r hand
+fixbone 1
Heavyweight Xonotic Solider
sex Female
weight 100
age 24
+bone_upperbody spine2
+bone_aim0 0.25 spine2
+bone_aim1 0.4 spine4
+bone_aim2 0.35 bip01 r hand
+bone_weapon bip01 r hand
+fixbone 1
Heavyweight Xonotic Soldier
sex Female
weight 57
age 53
+bone_upperbody spine2
+bone_aim0 0.25 spine2
+bone_aim1 0.4 spine4
+bone_aim2 0.35 bip01 r hand
+bone_weapon bip01 r hand
+fixbone 1
Necro Warrior
sex Female
weight 89
age 31
+bone_upperbody spine2
+bone_aim0 0.25 spine2
+bone_aim1 0.4 spine4
+bone_aim2 0.35 bip01 r hand
+bone_weapon bip01 r hand
+fixbone 1
Heavyweight Xonotic Solider
sex Female
weight 90
age 31
+bone_upperbody spine2
+bone_aim0 0.25 spine2
+bone_aim1 0.4 spine4
+bone_aim2 0.35 bip01 r hand
+bone_weapon bip01 r hand
+fixbone 1
Heavyweight Xonotic Solider
+++ /dev/null
- 0 40 20 // die1 : die
- 40 40 20 // die2 : die differently
- 80 6 20 // draw : raise weapon
- 86 6 20 // duck : crouch quickly
- 92 12 20 // duckwalk : crouch walking
-104 10 20 // duckjump : jump from crouching position, stays on last frame until you land
-114 20 20 // duckidle : crouched
-134 30 20 // idle : standing
-164 10 20 // jump : jump, stays on last frame until you land
-174 10 20 // pain1 : flinch from pain
-184 10 20 // pain2 : flinch differently
-194 6 20 // shoot : 300ms shooting anim, may be played faster/slower by code, used for all weapons
-200 1 20 // taunt : not used
-201 10 20 // run : run forward
-211 10 20 // runbackwards : run backwards
-221 10 20 // strafeleft : fast shuffling to the left
-231 10 20 // straferight : fast shuffling to the right
-241 10 20 // forwardright : running forward and right
-251 10 20 // forwardleft : running forward and left
-261 10 20 // backright : running backward and right
-271 10 20 // backleft : running backward and left
\ No newline at end of file
sex Female
weight 61
age 25
+bone_upperbody spine2
+bone_aim0 0.25 spine2
+bone_aim1 0.4 spine4
+bone_aim2 0.35 bip01 r hand
+bone_weapon bip01 r hand
+fixbone 1
Lightweight Xonotic Solider
--- /dev/null
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 40 20 0 // reload
set g_balance_rifle_bursttime 0
set g_balance_rifle_primary_tracer 1
set g_balance_rifle_primary_shots 1
-set g_balance_rifle_primary_damage 40
-set g_balance_rifle_primary_headshotaddeddamage 40
+set g_balance_rifle_primary_damage 80
set g_balance_rifle_primary_spread 0
set g_balance_rifle_primary_force 100
set g_balance_rifle_primary_speed 40000
set g_balance_rifle_secondary_reload 0
set g_balance_rifle_secondary_tracer 0
set g_balance_rifle_secondary_shots 4
-set g_balance_rifle_secondary_damage 10
-set g_balance_rifle_secondary_headshotaddeddamage 20
+set g_balance_rifle_secondary_damage 20
set g_balance_rifle_secondary_spread 0.04
set g_balance_rifle_secondary_force 50
set g_balance_rifle_secondary_speed 20000
// }}}
// {{{ seeker
set g_balance_seeker_type 0 // 0 = old seeker, 1 = new seeker
-set g_balance_seeker_flac_ammo 0.5
+set g_balance_seeker_flac_ammo 1
set g_balance_seeker_flac_animtime 0.1
set g_balance_seeker_flac_damage 15
set g_balance_seeker_flac_edgedamage 10
--- /dev/null
+// ********************************************** //
+// ** WARNING - DO NOT MANUALLY EDIT THIS FILE ** //
+// ** ** //
+// ** This file is automatically generated ** //
+// ** by code with the command 'dumpnotifs'. ** //
+// ** ** //
+// ** If you add a new notification, please ** //
+// ** regenerate this file with that command ** //
+// ** making sure that the output matches ** //
+// ** with the lists and defaults in code. ** //
+// ** ** //
+// ********************************************** //
+
+// MSG_INFO notifications (count = 208):
+seta notification_INFO_CTF_CAPTURE_RED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_CAPTURE_BLUE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_CAPTURE_BROKEN_RED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_CAPTURE_BROKEN_BLUE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_CAPTURE_TIME_RED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_CAPTURE_TIME_BLUE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_CAPTURE_UNBROKEN_RED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_CAPTURE_UNBROKEN_BLUE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_FLAGRETURN_ABORTRUN_RED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_FLAGRETURN_ABORTRUN_BLUE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_FLAGRETURN_DAMAGED_RED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_FLAGRETURN_DAMAGED_BLUE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_FLAGRETURN_DROPPED_RED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_FLAGRETURN_DROPPED_BLUE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_FLAGRETURN_NEEDKILL_RED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_FLAGRETURN_NEEDKILL_BLUE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_FLAGRETURN_SPEEDRUN_RED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_FLAGRETURN_SPEEDRUN_BLUE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_FLAGRETURN_TIMEOUT_RED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_FLAGRETURN_TIMEOUT_BLUE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_LOST_RED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_LOST_BLUE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_PICKUP_RED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_PICKUP_BLUE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_RETURN_RED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_CTF_RETURN_BLUE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_CHEAT "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_DROWN "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_FALL "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_FIRE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_LAVA "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_SHOOTING_STAR "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_SLIME "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_SWAMP "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_TELEFRAG "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_TOUCHEXPLODE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_VH_BUMB_DEATH "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_VH_BUMB_GUN "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_VH_CRUSH "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_VH_RAPT_BOMB "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_VH_RAPT_CANNON "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_VH_RAPT_DEATH "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_VH_SPID_DEATH "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_VH_SPID_MINIGUN "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_VH_SPID_ROCKET "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_VH_WAKI_DEATH "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_VH_WAKI_GUN "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_VH_WAKI_ROCKET "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_MURDER_VOID "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_AUTOTEAMCHANGE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_BETRAYAL "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_CAMP "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_CHEAT "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_CUSTOM "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_DROWN "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_FALL "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_FIRE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_GENERIC "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_LAVA "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_NOAMMO "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_ROT "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_SHOOTING_STAR "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_SLIME "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_SUICIDE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_SWAMP "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_TEAMCHANGE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_TOUCHEXPLODE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_TURRET "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_TURRET_EWHEEL "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_TURRET_FLAC "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_TURRET_HELLION "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_TURRET_HK "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_TURRET_MACHINEGUN "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_TURRET_MLRS "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_TURRET_PHASER "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_TURRET_PLASMA "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_TURRET_TESLA "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_TURRET_WALK_GUN "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_TURRET_WALK_MEELE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_TURRET_WALK_ROCKET "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_VH_BUMB_DEATH "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_VH_CRUSH "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_VH_RAPT_BOMB "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_VH_RAPT_DEATH "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_VH_SPID_DEATH "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_VH_SPID_ROCKET "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_VH_WAKI_DEATH "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_VH_WAKI_ROCKET "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_SELF_VOID "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_TEAMKILL_RED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_TEAMKILL_BLUE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_TEAMKILL_YELLOW "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_DEATH_TEAMKILL_PINK "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_FREEZETAG_FREEZE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_FREEZETAG_REVIVE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_FREEZETAG_ROUND_WIN_RED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_FREEZETAG_ROUND_WIN_BLUE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_FREEZETAG_ROUND_WIN_YELLOW "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_FREEZETAG_ROUND_WIN_PINK "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_FREEZETAG_SELF "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_GODMODE_OFF "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_ITEM_WEAPON_DONTHAVE "0" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_ITEM_WEAPON_DROP "0" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_ITEM_WEAPON_GOT "0" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_ITEM_WEAPON_NOAMMO "0" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_ITEM_WEAPON_PRIMORSEC "0" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_ITEM_WEAPON_UNAVAILABLE "0" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_JOIN_CONNECT "2" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_JOIN_CONNECT_TEAM_RED "2" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_JOIN_CONNECT_TEAM_BLUE "2" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_JOIN_CONNECT_TEAM_YELLOW "2" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_JOIN_CONNECT_TEAM_PINK "2" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_JOIN_PLAY "2" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_KEEPAWAY_DROPPED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_KEEPAWAY_PICKUP "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_KEYHUNT_CAPTURE_RED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_KEYHUNT_CAPTURE_BLUE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_KEYHUNT_CAPTURE_YELLOW "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_KEYHUNT_CAPTURE_PINK "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_KEYHUNT_DROP_RED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_KEYHUNT_DROP_BLUE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_KEYHUNT_DROP_YELLOW "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_KEYHUNT_DROP_PINK "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_KEYHUNT_LOST_RED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_KEYHUNT_LOST_BLUE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_KEYHUNT_LOST_YELLOW "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_KEYHUNT_LOST_PINK "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_KEYHUNT_PICKUP_RED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_KEYHUNT_PICKUP_BLUE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_KEYHUNT_PICKUP_YELLOW "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_KEYHUNT_PICKUP_PINK "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_LMS_FORFEIT "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_LMS_NOLIVES "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_POWERUP_INVISIBILITY "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_POWERUP_SHIELD "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_POWERUP_SPEED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_POWERUP_STRENGTH "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_QUIT_DISCONNECT "2" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_QUIT_KICK_IDLING "2" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_QUIT_KICK_SPECTATING "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_QUIT_SPECTATE "2" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_RACE_ABANDONED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_RACE_FAIL_RANKED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_RACE_FAIL_UNRANKED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_RACE_FINISHED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_RACE_NEW_BROKEN "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_RACE_NEW_IMPROVED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_RACE_NEW_MISSING_UID "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_RACE_NEW_SET "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_SCORES_RED "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_SCORES_BLUE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_SCORES_YELLOW "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_SCORES_PINK "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_SPECTATE_WARNING "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_SUPERWEAPON_PICKUP "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_VERSION_BETA "2" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_VERSION_OLD "2" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_VERSION_OUTDATED "2" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WATERMARK "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_ACCORDEON_MURDER "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_ACCORDEON_SUICIDE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_CRYLINK_MURDER "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_CRYLINK_SUICIDE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_ELECTRO_MURDER_BOLT "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_ELECTRO_MURDER_COMBO "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_ELECTRO_MURDER_ORBS "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_ELECTRO_SUICIDE_BOLT "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_ELECTRO_SUICIDE_ORBS "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_FIREBALL_MURDER_BLAST "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_FIREBALL_MURDER_FIREMINE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_FIREBALL_SUICIDE_BLAST "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_FIREBALL_SUICIDE_FIREMINE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_HAGAR_MURDER_BURST "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_HAGAR_MURDER_SPRAY "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_HAGAR_SUICIDE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_HLAC_MURDER "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_HLAC_SUICIDE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_HOOK_MURDER "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_KLEINBOTTLE_MURDER "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_KLEINBOTTLE_SUICIDE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_LASER_MURDER "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_LASER_SUICIDE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_MINELAYER_MURDER "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_MINELAYER_SUICIDE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_MINSTANEX_MURDER "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_MORTAR_MURDER_BOUNCE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_MORTAR_MURDER_EXPLODE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_MORTAR_SUICIDE_BOUNCE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_MORTAR_SUICIDE_EXPLODE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_NEX_MURDER "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_RIFLE_MURDER "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_RIFLE_MURDER_HAIL "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_RIFLE_MURDER_HAIL_PIERCING "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_RIFLE_MURDER_HEADSHOT "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_RIFLE_MURDER_PIERCING "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_ROCKETLAUNCHER_MURDER_DIRECT "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_ROCKETLAUNCHER_MURDER_SPLASH "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_ROCKETLAUNCHER_SUICIDE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_SEEKER_MURDER_SPRAY "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_SEEKER_MURDER_TAG "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_SEEKER_SUICIDE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_SHOTGUN_MURDER "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_SHOTGUN_MURDER_SLAP "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_THINKING_WITH_PORTALS "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_TUBA_MURDER "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_TUBA_SUICIDE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_UZI_MURDER_SNIPE "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_WEAPON_UZI_MURDER_SPRAY "1" "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+
+// MSG_CENTER notifications (count = 133):
+seta notification_CENTER_ARENA_BEGIN "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_ARENA_NEEDPLAYER "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_ARENA_ROUNDSTART "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_ASSAULT_ATTACKING "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_ASSAULT_DEFENDING "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_COUNTDOWN_BEGIN "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_COUNTDOWN_GAMESTART "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_CAPTURESHIELD_FREE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_CAPTURESHIELD_SHIELDED "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_CAPTURE_RED "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_CAPTURE_BLUE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_FLAG_THROW_PUNISH "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_PASS_OTHER_RED "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_PASS_OTHER_BLUE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_PASS_RECEIVED_RED "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_PASS_RECEIVED_BLUE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_PASS_REQUESTED "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_PASS_REQUESTING "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_PASS_SENT_RED "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_PASS_SENT_BLUE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_PICKUP_RED "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_PICKUP_BLUE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_PICKUP_ENEMY "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_PICKUP_ENEMY_VERBOSE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_PICKUP_TEAM "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_PICKUP_TEAM_VERBOSE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_RETURN_RED "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_RETURN_BLUE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_STALEMATE_CARRIER "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_CTF_STALEMATE_OTHER "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_MURDER_FRAG "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_MURDER_FRAGGED "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_MURDER_FRAGGED_VERBOSE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_MURDER_FRAG_VERBOSE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_MURDER_TYPEFRAG "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_MURDER_TYPEFRAGGED "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_MURDER_TYPEFRAGGED_VERBOSE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_MURDER_TYPEFRAG_VERBOSE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_AUTOTEAMCHANGE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_BETRAYAL "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_CAMP "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_CHEAT "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_CUSTOM "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_DROWN "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_FALL "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_FIRE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_GENERIC "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_LAVA "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_NOAMMO "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_ROT "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_SHOOTING_STAR "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_SLIME "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_SUICIDE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_SWAMP "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_TEAMCHANGE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_TOUCHEXPLODE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_TURRET "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_TURRET_EWHEEL "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_TURRET_WALK "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_VH_BUMB_DEATH "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_VH_CRUSH "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_VH_RAPT_BOMB "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_VH_RAPT_DEATH "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_VH_SPID_DEATH "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_VH_SPID_ROCKET "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_VH_WAKI_DEATH "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_VH_WAKI_ROCKET "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_SELF_VOID "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_TEAMKILL_FRAG "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DEATH_TEAMKILL_FRAGGED "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_DISCONNECT_IDLING "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_FREEZETAG_FREEZE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_FREEZETAG_FROZEN "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_FREEZETAG_REVIVE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_FREEZETAG_REVIVED "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_FREEZETAG_ROUND_WIN_RED "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_FREEZETAG_ROUND_WIN_BLUE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_FREEZETAG_ROUND_WIN_YELLOW "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_FREEZETAG_ROUND_WIN_PINK "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_FREEZETAG_SELF "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_FREEZETAG_SPAWN_LATE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_ITEM_WEAPON_DONTHAVE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_ITEM_WEAPON_DROP "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_ITEM_WEAPON_GOT "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_ITEM_WEAPON_NOAMMO "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_ITEM_WEAPON_PRIMORSEC "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_ITEM_WEAPON_UNAVAILABLE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_JOIN_NOSPAWNS "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_JOIN_PREVENT "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_KEEPAWAY_DROPPED "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_KEEPAWAY_PICKUP "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_KEEPAWAY_WARN "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_KEYHUNT_HELP "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_KEYHUNT_INTERFERE_RED "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_KEYHUNT_INTERFERE_BLUE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_KEYHUNT_INTERFERE_YELLOW "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_KEYHUNT_INTERFERE_PINK "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_KEYHUNT_MEET "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_KEYHUNT_SCAN "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_KEYHUNT_START_RED "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_KEYHUNT_START_BLUE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_KEYHUNT_START_YELLOW "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_KEYHUNT_START_PINK "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_KEYHUNT_WAIT "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_LMS_CAMPCHECK "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_MINSTA_FINDAMMO "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_MINSTA_FINDAMMO_FIRST "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_MOTD "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_NIX_COUNTDOWN "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_NIX_NEWWEAPON "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_OVERTIME_FRAG "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_OVERTIME_TIME "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_POWERDOWN_INVISIBILITY "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_POWERDOWN_SHIELD "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_POWERDOWN_SPEED "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_POWERDOWN_STRENGTH "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_POWERUP_INVISIBILITY "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_POWERUP_SHIELD "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_POWERUP_SPEED "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_POWERUP_STRENGTH "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_RACE_FINISHLAP "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_SUPERWEAPON_BROKEN "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_SUPERWEAPON_LOST "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_SUPERWEAPON_PICKUP "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_TEAMCHANGE_RED "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_TEAMCHANGE_BLUE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_TEAMCHANGE_YELLOW "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_TEAMCHANGE_PINK "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_TEAMCHANGE_AUTO "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_TEAMCHANGE_SPECTATE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_TEAMCHANGE_SUICIDE "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_TIMEOUT_BEGINNING "1" "Notification control cvar: 0 = off, 1 = centerprint"
+seta notification_CENTER_TIMEOUT_ENDING "1" "Notification control cvar: 0 = off, 1 = centerprint"
+
+// MSG_MULTI notifications (count = 118):
+seta notification_DEATH_MURDER_CHEAT "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_DROWN "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_FALL "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_FIRE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_LAVA "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_SHOOTING_STAR "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_SLIME "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_SWAMP "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_TELEFRAG "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_TOUCHEXPLODE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_VH_BUMB_DEATH "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_VH_BUMB_GUN "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_VH_CRUSH "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_VH_RAPT_BOMB "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_VH_RAPT_CANNON "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_VH_RAPT_DEATH "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_VH_SPID_DEATH "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_VH_SPID_MINIGUN "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_VH_SPID_ROCKET "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_VH_WAKI_DEATH "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_VH_WAKI_GUN "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_VH_WAKI_ROCKET "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_MURDER_VOID "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_AUTOTEAMCHANGE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_BETRAYAL "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_CAMP "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_CHEAT "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_CUSTOM "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_DROWN "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_FALL "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_FIRE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_GENERIC "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_LAVA "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_NOAMMO "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_ROT "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_SHOOTING_STAR "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_SLIME "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_SUICIDE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_SWAMP "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_TEAMCHANGE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_TOUCHEXPLODE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_TURRET "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_TURRET_EWHEEL "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_TURRET_FLAC "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_TURRET_HELLION "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_TURRET_HK "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_TURRET_MACHINEGUN "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_TURRET_MLRS "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_TURRET_PHASER "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_TURRET_PLASMA "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_TURRET_TESLA "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_TURRET_WALK_GUN "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_TURRET_WALK_MEELE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_TURRET_WALK_ROCKET "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_VH_BUMB_DEATH "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_VH_CRUSH "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_VH_RAPT_BOMB "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_VH_RAPT_DEATH "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_VH_SPID_DEATH "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_VH_SPID_ROCKET "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_VH_WAKI_DEATH "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_VH_WAKI_ROCKET "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_DEATH_SELF_VOID "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_ITEM_WEAPON_DONTHAVE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_ITEM_WEAPON_DROP "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_ITEM_WEAPON_GOT "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_ITEM_WEAPON_NOAMMO "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_ITEM_WEAPON_PRIMORSEC "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_ITEM_WEAPON_UNAVAILABLE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_ACCORDEON_MURDER "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_ACCORDEON_SUICIDE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_CRYLINK_MURDER "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_CRYLINK_SUICIDE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_ELECTRO_MURDER_BOLT "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_ELECTRO_MURDER_COMBO "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_ELECTRO_MURDER_ORBS "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_ELECTRO_SUICIDE_BOLT "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_ELECTRO_SUICIDE_ORBS "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_FIREBALL_MURDER_BLAST "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_FIREBALL_MURDER_FIREMINE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_FIREBALL_SUICIDE_BLAST "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_FIREBALL_SUICIDE_FIREMINE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_HAGAR_MURDER_BURST "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_HAGAR_MURDER_SPRAY "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_HAGAR_SUICIDE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_HLAC_MURDER "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_HLAC_SUICIDE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_HOOK_MURDER "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_KLEINBOTTLE_MURDER "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_KLEINBOTTLE_SUICIDE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_LASER_MURDER "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_LASER_SUICIDE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_MINELAYER_MURDER "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_MINELAYER_SUICIDE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_MINSTANEX_MURDER "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_MORTAR_MURDER_BOUNCE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_MORTAR_MURDER_EXPLODE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_MORTAR_SUICIDE_BOUNCE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_MORTAR_SUICIDE_EXPLODE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_NEX_MURDER "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_RIFLE_MURDER "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_RIFLE_MURDER_HAIL "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_RIFLE_MURDER_HAIL_PIERCING "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_RIFLE_MURDER_HEADSHOT "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_RIFLE_MURDER_PIERCING "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_ROCKETLAUNCHER_MURDER_DIRECT "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_ROCKETLAUNCHER_MURDER_SPLASH "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_ROCKETLAUNCHER_SUICIDE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_SEEKER_MURDER_SPRAY "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_SEEKER_MURDER_TAG "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_SEEKER_SUICIDE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_SHOTGUN_MURDER "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_SHOTGUN_MURDER_SLAP "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_THINKING_WITH_PORTALS "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_TUBA_MURDER "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_TUBA_SUICIDE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_UZI_MURDER_SNIPE "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+seta notification_WEAPON_UZI_MURDER_SPRAY "1" "Notification control cvar: 0 = off, 1 = trigger subcalls"
+
+// HARD CODED notification variables:
+seta notification_allow_chatboxprint "1" "Allow notifications to be printed to chat box by setting notification cvar to 2 (You can also set this cvar to 2 to force ALL notifications to be printed to the chatbox)"
+seta notification_ctf_capture_verbose "0" "Show extra information when someone captures a flag"
+seta notification_ctf_pickup_enemy_verbose "0" "Show extra information if an enemy picks up a flag"
+seta notification_ctf_pickup_team_verbose "0" "Show extra information if a team mate picks up a flag"
+seta notification_errors_are_fatal "1" "If a notification fails upon initialization, cause a Host_Error to stop the program"
+seta notification_frag_verbose "1" "Show extra information when you frag someone (or when you are fragged"
+seta notification_item_centerprinttime "1.5" "How long to show item information centerprint messages (like 'You got the Electro' or such)"
+seta notification_lifetime_mapload "10" "Amount of time that notification entities last immediately at mapload (in seconds) to help prevent notifications from being lost on early init (like gamestart countdown)"
+seta notification_lifetime_runtime "0.5" "Amount of time that notification entities last on the server during runtime (In seconds)"
+seta notification_server_allows_frag_verbose "1" "Server side cvar for showing extra information in frag messages... 0 = no extra frag information, 1 = frag information only in warmup, 2 = frag information allowed all the time"
+seta notification_server_allows_location "1" "Server side cvar for allowing death messages to show location information too"
+seta notification_show_location "0" "Append location information to MSG_INFO death/kill messages"
+seta notification_show_location_string "" "Replacement string piped into sprintf, so you can do different messages like this: ' at the %s' or ' (near %s)'"
+seta notification_show_sprees "1" "Print information about sprees in death/kill messages"
+seta notification_show_sprees_center "1" "Show spree information in MSG_CENTER messages... 0 = off, 1 = target (but only for first victim) and attacker"
+seta notification_show_sprees_center_specialonly "1" "Don't show spree information in MSG_CENTER messages if it isn't an achievement"
+seta notification_show_sprees_info "3" "Show spree information in MSG_INFO messages... 0 = off, 1 = target only, 2 = attacker only, 3 = target and attacker"
+seta notification_show_sprees_info_newline "1" "Show attacker spree information for MSG_INFO messages on a separate line than the death notification itself"
+seta notification_show_sprees_info_specialonly "1" "Don't show attacker spree information in MSG_INFO messages if it isn't an achievement"
+
+// Notification counts (total = 459): MSG_INFO = 208, MSG_CENTER = 133, MSG_MULTI = 118
SCM := $(shell if [ -d .svn ]; then echo svn; elif [ -d ../.git ]; then echo git; fi)
-FTEQCC ?= fteqcc
PERL ?= perl
+QCCFLAGS_WATERMARK ?= -DWATERMARK='"$(shell git describe)"' -DCVAR_POPCON=1
+QCC ?= gmqcc
-FTEQCCFLAGS_WATERMARK ?= -DWATERMARK='"$(shell git describe)"' -DCVAR_POPCON
-FTEQCCFLAGS ?= -Werror -Wno-Q302 -O3 -Ono-return_only -fno-fastarrays $(FTEQCCFLAGS_EXTRA) $(FTEQCCFLAGS_WATERMARK)
-FTEQCCFLAGS_PROGS ?=
-FTEQCCFLAGS_MENU ?=
-
-# NOTE: use -DUSE_FTE instead of -TFTE here!
-# It will automagically add an engine check with -TID and then change back to -TFTE
-FTEQCCFLAGS_CSPROGS ?=
+VERSION_MESSAGE = $(shell cd server && $(QCC) --version --help)
+ifneq (,$(findstring GMQCC,$(VERSION_MESSAGE)))
+# this is gmqcc
+QCCFLAGS ?= \
+ -std=fteqcc \
+ -Werror -Wall \
+ -Wno-field-redeclared \
+ -Wno-double-declaration \
+ -Wno-uninitialized-global \
+ -O3 \
+ -fadjust-vector-fields \
+ -fftepp \
+ -fftepp-predefs \
+ -frelaxed-switch \
+ -fshort-logic \
+ -fno-perl-logic \
+ -ftranslatable-strings \
+ -fno-initialized-nonconstants \
+ -fno-assign-function-types \
+ -flno \
+ -fcorrect-ternary \
+ -fno-single-vector-defs \
+ -fcorrect-logic \
+ -ftrue-empty-strings \
+ -fno-false-empty-strings \
+ -futf8 \
+ -fno-bail-on-werror \
+ -floop-labels \
+ -funtyped-nil \
+ -fno-permissive \
+ -fvariadic-args \
+ $(QCCFLAGS_EXTRA) $(QCCFLAGS_WATERMARK)
+else
+# this. is. fteqccccccccccccccccccc!
+QCCFLAGS ?= -Werror -Wno-Q302 -O3 -Ono-return_only -fno-fastarrays $(QCCFLAGS_EXTRA) $(QCCFLAGS_WATERMARK)
+endif
# xonotic build system overrides this by command line argument to turn off the update-cvarcount step
XON_BUILDSYSTEM =
FILES_CSPROGS = $(shell find client common warpzonelib csqcmodellib -type f -not -name fteqcc.log -not -name qc.asm) $(wildcard server/w_*.qc)
../csprogs.dat: $(FILES_CSPROGS)
@echo make[1]: Entering directory \`$(PWD)/client\'
- cd client && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_CSPROGS)
+ cd client && $(QCC) $(QCCFLAGS)
FILES_PROGS = $(shell find server common warpzonelib csqcmodellib -type f -not -name fteqcc.log -not -name qc.asm) $(wildcard server/w_*.qc)
../progs.dat: $(FILES_PROGS)
@echo make[1]: Entering directory \`$(PWD)/server\'
- cd server && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_PROGS)
+ cd server && $(QCC) $(QCCFLAGS)
FILES_MENU = $(shell find menu common warpzonelib -type f -not -name fteqcc.log -not -name qc.asm) $(wildcard server/w_*.qc)
../menu.dat: $(FILES_MENU)
@echo make[1]: Entering directory \`$(PWD)/menu\'
- cd menu && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_MENU)
+ cd menu && $(QCC) $(QCCFLAGS)
.PHONY: testcase
testcase:
- cd testcase && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_CSPROGS) -DTESTCASE="$$TESTCASE"
+ cd testcase && $(QCC) $(QCCFLAGS) -DTESTCASE="$$TESTCASE"
-#pragma flag off fastarrays // make dp behave with new fteqcc versions. remove when dp bug with fteqcc fastarrays is fixed
-
-
//NOTE: THIS IS AN INTERFACE FILE. DO NOT EDIT.
//MODIFYING THIS FILE CAN RESULT IN CRC ERRORS.
//YOU HAVE BEEN WARNED.
.float silent;
float w_deathtype, w_issilent, w_random;
-string w_deathtypestring;
vector w_org, w_backoff;
float rifle_scope;
check_unacceptable_compiler_bugs();
#ifdef WATERMARK
- print(sprintf(_("^4CSQC Build information: ^1%s\n"), WATERMARK()));
+ print(sprintf(_("^4CSQC Build information: ^1%s\n"), WATERMARK));
#endif
float i;
draw_endBoldFont();
menu_visible = FALSE;
menu_show = menu_show_error;
- menu_action = menu_sub_null;
+ menu_action = func_null;
for(i = 0; i < 255; ++i)
if(getplayerkeyvalue(i, "viewentity") == "")
teams = Sort_Spawn();
players = Sort_Spawn();
- GetTeam(COLOR_SPECTATOR, true); // add specs first
+ GetTeam(NUM_SPECTATOR, true); // add specs first
// needs to be done so early because of the constants they create
CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
-
+ CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
+ CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
+
WaypointSprite_Load();
// precaches
turrets_precache();
Announcer_Precache();
Tuba_Precache();
+ CSQCPlayer_Precache();
if(autocvar_cl_reticle)
{
WarpZone_Init();
+ hud_skin_path = strzone(strcat("gfx/hud/", autocvar_hud_skin));
hud_configure_prev = -1;
tab_panel = -1;
switch(Team)
{
case -1:
- case COLOR_TEAM1:
- case COLOR_TEAM2:
- case COLOR_TEAM3:
- case COLOR_TEAM4:
+ case NUM_TEAM_1:
+ case NUM_TEAM_2:
+ case NUM_TEAM_3:
+ case NUM_TEAM_4:
break;
default:
if(GetTeam(Team, false) == world)
{
print(sprintf(_("trying to switch to unsupported team %d\n"), Team));
- Team = COLOR_SPECTATOR;
+ Team = NUM_SPECTATOR;
}
break;
}
if(GetTeam(Team, false) == world)
{
print(sprintf(_("trying to switch to unsupported team %d\n"), Team));
- Team = COLOR_SPECTATOR;
+ Team = NUM_SPECTATOR;
}
break;
}
// CSQC_InputEvent : Used to perform actions based on any key pressed, key released and mouse on the client.
// Return value should be 1 if CSQC handled the input, otherwise return 0 to have the input passed to the engine.
// All keys are in ascii.
-// bInputType = 0 is key pressed, 1 is key released, 2 is mouse input.
+// bInputType = 0 is key pressed, 1 is key released, 2 and 3 are mouse input.
// In the case of keyboard input, nPrimary is the ascii code, and nSecondary is 0.
// In the case of mouse input, nPrimary is xdelta, nSecondary is ydelta.
+// In the case of mouse input after a setcursormode(1) call, nPrimary is xpos, nSecondary is ypos.
float CSQC_InputEvent(float bInputType, float nPrimary, float nSecondary)
{
float bSkipKey;
if (MapVote_InputEvent(bInputType, nPrimary, nSecondary))
return true;
- if(menu_visible)
+ if(menu_visible && menu_action)
if(menu_action(bInputType, nPrimary, nSecondary))
return TRUE;
self.origin_x = ReadShort();
self.origin_y = ReadShort();
self.origin_z = ReadShort();
+ setorigin(self, self.origin);
}
if(sf & 4)
{
entcs_receiver[self.sv_entnum] = self;
self.entremove = Ent_RemoveEntCS;
+ self.iflags |= IFLAG_ORIGIN;
InterpolateOrigin_Note();
}
case ENT_CLIENT_TURRET: ent_turret(); 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_BUMBLE_RAYGUN: bumble_raygun_read(bIsNewEntity); break;
+ case ENT_CLIENT_NOTIFICATION: Read_Notification(bIsNewEntity); 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));
if(self.entremove)
self.entremove();
+ if(self.skeletonindex)
+ {
+ skel_delete(self.skeletonindex);
+ self.skeletonindex = 0;
+ }
+
+ if(self.snd_looping > 0)
+ {
+ sound(self, self.snd_looping, "misc/null.wav", VOL_BASE, autocvar_g_jetpack_attenuation);
+ self.snd_looping = 0;
+ }
+
self.enttype = 0;
self.classname = "";
self.draw = menu_sub_null;
void Net_ReadSpawn()
{
zoomin_effect = 1;
- current_viewzoom = 0.6;
+ current_viewzoom = (1 / bound(1, autocvar_cl_spawnzoom_factor, 16));
}
void Net_TeamNagger()
playerslots[e].ping_movementloss = ml / 255.0;
}
-void Net_WeaponComplain() {
+void Net_WeaponComplain()
+{
complain_weapon = ReadByte();
if(complain_weapon_name)
complain_weapon_time = time;
weapontime = time; // ping the weapon panel
+
+ switch(complain_weapon_type)
+ {
+ case 0: Local_Notification(MSG_MULTI, ITEM_WEAPON_NOAMMO, complain_weapon); break;
+ case 1: Local_Notification(MSG_MULTI, ITEM_WEAPON_DONTHAVE, complain_weapon); break;
+ default: Local_Notification(MSG_MULTI, ITEM_WEAPON_UNAVAILABLE, complain_weapon); break;
+ }
}
// CSQC_Parse_TempEntity : Handles all temporary entity network data in the CSQC layer.
Announcer_Play(ReadString());
bHandled = true;
break;
- case TE_CSQC_KILLNOTIFY:
- HUD_KillNotify(ReadString(), ReadString(), ReadString(), ReadShort(), ReadByte());
- bHandled = true;
- break;
- case TE_CSQC_KILLCENTERPRINT:
- HUD_KillCenterprint(ReadString(), ReadString(), ReadShort(), ReadByte());
- bHandled = true;
- break;
- case TE_CSQC_CENTERPRINT_GENERIC:
- float id;
- string s;
- id = ReadByte();
- s = ReadString();
- if (id != 0 && s != "")
- centerprint_generic(id, s, ReadByte(), ReadByte());
- else
- centerprint_generic(id, s, 0, 0);
- bHandled = true;
- break;
case TE_CSQC_WEAPONCOMPLAIN:
Net_WeaponComplain();
bHandled = true;
string getcommandkey(string text, string command)
{
string keys;
- float n, j, k, l;
+ float n, j, k, l = 0;
if (!autocvar_hud_showbinds)
return text;
keys = db_get(binddb, command);
- if (!keys)
+ if (keys == "")
{
n = tokenize(findkeysforcommand(command, 0)); // uses '...' strings
for(j = 0; j < n; ++j)
keys = strcat(keys, ", ", keynumtostring(k));
++l;
- if (autocvar_hud_showbinds_limit > 0 && autocvar_hud_showbinds_limit >= l) break;
+ if (autocvar_hud_showbinds_limit > 0 && autocvar_hud_showbinds_limit <= l)
+ break;
}
}
+ if (keys == "")
+ keys = "NO_KEY";
db_put(binddb, command, keys);
}
- if ("" == keys) {
+ if (keys == "NO_KEY") {
if (autocvar_hud_showbinds > 1)
return sprintf(_("%s (not bound)"), text);
else
if(!CheckWireframeBox(porto, p - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward))
return;
if(portal_number == 1)
+ {
portal1_idx = idx;
- if(portal_number >= 2)
- break;
+ if(portal_number >= 2)
+ break;
+ }
}
while(idx >= 2)
zoomfactor = 2.5;
zoomspeed = autocvar_cl_zoomspeed;
if(zoomspeed >= 0)
- if(zoomspeed < 0.5 || zoomspeed > 16)
+ if(zoomspeed < 0.5 || zoomspeed > 16)
zoomspeed = 3.5;
zoomdir = button_zoom;
// fteqcc failed twice here already, don't optimize this
}
- if(zoomdir)
- zoomin_effect = 0;
+ if(zoomdir) { zoomin_effect = 0; }
- if(zoomin_effect || camera_active)
+ if(camera_active)
{
current_viewzoom = min(1, current_viewzoom + drawframetime);
}
+ else if(autocvar_cl_spawnzoom && zoomin_effect)
+ {
+ float spawnzoomfactor = bound(1, autocvar_cl_spawnzoom_factor, 16);
+
+ current_viewzoom += (autocvar_cl_spawnzoom_speed * (spawnzoomfactor - current_viewzoom) * drawframetime);
+ current_viewzoom = bound(1 / spawnzoomfactor, current_viewzoom, 1);
+ if(current_viewzoom == 1) { zoomin_effect = 0; }
+ }
else
{
if(zoomspeed < 0) // instant zoom
if(teamplay)
if(t == myteam)
return SHOTTYPE_HITTEAM;
- if(t == COLOR_SPECTATOR)
+ if(t == NUM_SPECTATOR)
return SHOTTYPE_HITWORLD;
return SHOTTYPE_HITENEMY;
}
hud = getstati(STAT_HUD);
+ if(autocvar__hud_showbinds_reload) // menu can set this one
+ {
+ db_close(binddb);
+ binddb = db_create();
+ cvar_set("_hud_showbinds_reload", "0");
+ }
+
if(checkextension("DP_CSQC_MINFPS_QUALITY"))
view_quality = getproperty(VF_MINFPS_QUALITY);
else
vid_width = vf_size_x;
vid_height = vf_size_y;
- vector reticle_pos, reticle_size;
- vector splash_pos, splash_size;
+ vector reticle_pos = '0 0 0', reticle_size = '0 0 0';
+ vector splash_pos = '0 0 0', splash_size = '0 0 0';
WaypointSprite_Load();
if(spectatee_status >= 0 && (autocvar_cl_eventchase_death && getstati(STAT_HEALTH) <= 0 && !intermission) || intermission)
{
// 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 = getpropertyvec(VF_ORIGIN);
-
+ vector current_view_origin = ((csqcplayer ? csqcplayer.origin : pmove_org) + autocvar_cl_eventchase_viewoffset);
+
// We must enable chase_active to get a third person view (weapon viewmodel hidden and own player model showing).
// Ideally, there should be another way to enable third person cameras, such as through setproperty()
- if(!autocvar_chase_active)
- cvar_set("chase_active", "-1"); // -1 enables chase_active while marking it as set by this code, and not by the user (which would be 1)
+ // -1 enables chase_active while marking it as set by this code, and not by the user (which would be 1)
+ 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)
else if(eventchase_current_distance != autocvar_cl_eventchase_distance)
eventchase_current_distance = autocvar_cl_eventchase_distance;
- vector eventchase_target_origin;
makevectors(view_angles);
- // pass 1, used to check where the camera would go and obtain the trace_fraction
- eventchase_target_origin = current_view_origin - v_forward * eventchase_current_distance;
- WarpZone_TraceLine(current_view_origin, eventchase_target_origin, MOVE_WORLDONLY, self);
- // pass 2, also multiplying view_forward with trace_fraction, to prevent the camera from going through walls
- // The 0.1 subtraction is to not limit the camera precisely at the wall surface, as that allows the view to poke through
- eventchase_target_origin = current_view_origin - v_forward * eventchase_current_distance * (trace_fraction - 0.1);
- WarpZone_TraceLine(current_view_origin, eventchase_target_origin, MOVE_WORLDONLY, self);
-
- setproperty(VF_ORIGIN, trace_endpos);
+
+ vector eventchase_target_origin = (current_view_origin - (v_forward * eventchase_current_distance));
+ WarpZone_TraceBox(current_view_origin, autocvar_cl_eventchase_mins, autocvar_cl_eventchase_maxs, eventchase_target_origin, MOVE_WORLDONLY, self);
+
+ // If the boxtrace fails, revert back to line tracing.
+ if(trace_startsolid)
+ {
+ eventchase_target_origin = (current_view_origin - (v_forward * eventchase_current_distance));
+ WarpZone_TraceLine(current_view_origin, eventchase_target_origin, MOVE_WORLDONLY, self);
+ setproperty(VF_ORIGIN, (trace_endpos - (v_forward * autocvar_cl_eventchase_mins_z)));
+ }
+ else { setproperty(VF_ORIGIN, trace_endpos); }
+
setproperty(VF_ANGLES, WarpZone_TransformVAngles(WarpZone_trace_transform, view_angles));
}
else if(autocvar_chase_active < 0) // time to disable chase_active if it was set by this code
eventchase_current_distance = 0; // start from 0 next time
}
}
-
+ // workaround for camera stuck between player's legs when using chase_active 1
+ // because the engine stops updating the chase_active camera when the game ends
+ else if(intermission)
+ {
+ cvar_settemp("chase_active", "-1");
+ eventchase_current_distance = 0;
+ }
+
// do lockview after event chase camera so that it still applies whenever necessary.
- if(autocvar_cl_lockview || (autocvar__hud_configure && spectatee_status <= 0) || intermission > 1)
+ if(autocvar_cl_lockview || (!autocvar_hud_cursormode && (autocvar__hud_configure && spectatee_status <= 0 || intermission > 1)))
{
setproperty(VF_ORIGIN, freeze_org);
setproperty(VF_ANGLES, freeze_ang);
calledhooks |= HOOK_END;
}
}
-
- Announcer();
+
+ Announcer();
fov = autocvar_fov;
if(fov <= 59.5)
// improved polyblend
- vector rgb;
if(autocvar_hud_contents)
{
float contentalpha_temp, incontent, liquidalpha, contentfadetime;
// pro: matches model better
// contra: it's not red because blood is red, but because red is an alarming color, so red should stay
// maybe different reddish pics?
- if(autocvar_chase_active >= 0) // not while the event chase camera is active
+ if(autocvar_cl_gentle_damage || autocvar_cl_gentle)
{
- if(autocvar_cl_gentle_damage || autocvar_cl_gentle)
+ if(autocvar_cl_gentle_damage == 2)
{
- if(autocvar_cl_gentle_damage == 2)
+ if(myhealth_flash < pain_threshold) // only randomize when the flash is gone
{
- if(myhealth_flash < pain_threshold) // only randomize when the flash is gone
- {
- myhealth_gentlergb = eX * random() + eY * random() + eZ * random();
- }
+ myhealth_gentlergb = eX * random() + eY * random() + eZ * random();
}
- else
- myhealth_gentlergb = stov(autocvar_hud_damage_gentle_color);
-
- drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, myhealth_gentlergb, autocvar_hud_damage_gentle_alpha_multiplier * bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL);
}
else
- drawpic(splash_pos, "gfx/blood", splash_size, stov(autocvar_hud_damage_color), bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL);
+ myhealth_gentlergb = stov(autocvar_hud_damage_gentle_color);
+
+ drawfill('0 0 0', eX * vid_conwidth + eY * vid_conheight, myhealth_gentlergb, autocvar_hud_damage_gentle_alpha_multiplier * bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL);
}
+ else
+ drawpic(splash_pos, "gfx/blood", splash_size, stov(autocvar_hud_damage_color), bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL);
if(autocvar_hud_postprocessing) // we still need to set this anyway even when chase_active is set, this way it doesn't get stuck on.
{
if(cvar("r_glsl_postprocess_uservec2_enable") != e2) { cvar_set("r_glsl_postprocess_uservec2_enable", ftos(e2)); }
// blur postprocess handling done first (used by hud_damage and hud_contents)
- if((damage_blurpostprocess_x || content_blurpostprocess_x) && autocvar_chase_active >= 0) // not while the event chase camera is active
+ if((damage_blurpostprocess_x || content_blurpostprocess_x))
{
float blurradius = bound(0, damage_blurpostprocess_y + content_blurpostprocess_y, autocvar_hud_postprocessing_maxblurradius);
float bluralpha = bound(0, damage_blurpostprocess_z + content_blurpostprocess_z, autocvar_hud_postprocessing_maxbluralpha);
}
// edge detection postprocess handling done second (used by hud_powerup)
- float sharpen_intensity, strength_finished = getstatf(STAT_STRENGTH_FINISHED), invincible_finished = getstatf(STAT_INVINCIBLE_FINISHED);
+ float sharpen_intensity = 0, strength_finished = getstatf(STAT_STRENGTH_FINISHED), invincible_finished = getstatf(STAT_INVINCIBLE_FINISHED);
if (strength_finished - time > 0) { sharpen_intensity += (strength_finished - time); }
if (invincible_finished - time > 0) { sharpen_intensity += (invincible_finished - time); }
sharpen_intensity = bound(0, ((getstati(STAT_HEALTH) > 0) ? sharpen_intensity : 0), 5); // Check to see if player is alive (if not, set 0) - also bound to fade out starting at 5 seconds.
- if(autocvar_hud_powerup && sharpen_intensity > 0 && autocvar_chase_active >= 0) // not while the event chase camera is active
+ if(autocvar_hud_powerup && sharpen_intensity > 0)
{
if(sharpen_intensity != old_sharpen_intensity) // reduce cvar_set spam as much as possible
{
else
shottype = SHOTTYPE_HITWORLD;
- vector wcross_color, wcross_size;
- string wcross_wep, wcross_name;
+ 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_per_weapon) {
if (autocvar_crosshair_ring || autocvar_crosshair_ring_reload)
{
// declarations and stats
- float ring_value, ring_scale, ring_alpha, ring_inner_value, ring_inner_alpha;
- string ring_image, ring_inner_image;
- vector ring_rgb, ring_inner_rgb;
+ 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;
void CSQC_common_hud(void)
{
- // do some accuracy var caching
- float i;
- if(!(gametype == MAPINFO_TYPE_RACE || gametype == MAPINFO_TYPE_CTS))
- {
- if(autocvar_accuracy_color_levels != acc_color_levels)
- {
- if(acc_color_levels)
- strunzone(acc_color_levels);
- acc_color_levels = strzone(autocvar_accuracy_color_levels);
- acc_levels = tokenize_console(acc_color_levels);
- if (acc_levels > MAX_ACCURACY_LEVELS)
- acc_levels = MAX_ACCURACY_LEVELS;
-
- for (i = 0; i < acc_levels; ++i)
- acc_lev[i] = stof(argv(i)) / 100.0;
- }
- // let know that acc_col[] needs to be loaded
- acc_col[0] = '-1 0 0';
- }
+ if(!(gametype == MAPINFO_TYPE_RACE || gametype == MAPINFO_TYPE_CTS))
+ Accuracy_LoadLevels();
HUD_Main(); // always run these functions for alpha checks
HUD_DrawScoreboard();
if(countdown <= 0) // countdown has finished, starttime is now
{
- if (!spectatee_status)
- centerprint_generic(CPID_GAME_STARTING, _("^1Begin!"), 1, 0);
+ if (!spectatee_status)
+ Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_BEGIN);
Announcer_Play("begin");
announcer_5min = announcer_1min = FALSE; // reset maptime announcers now as well
else // countdown is still going
{
if (!spectatee_status)
- centerprint_generic(CPID_GAME_STARTING, _("^1Game starts in %d seconds"), 1, countdown_rounded);
+ Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_GAMESTART, countdown_rounded);
if(countdown_rounded <= 3 && countdown_rounded >= 1)
Announcer_Play(ftos(countdown_rounded));
{
float timelimit = getstatf(STAT_TIMELIMIT);
float timeleft = max(0, timelimit * 60 + getstatf(STAT_GAMESTARTTIME) - time);
- float warmup_timeleft;
+ float warmup_timeleft = 0;
if(warmup_stage)
if(autocvar_g_warmup_limit > 0)
precache_sound (strcat("announcer/", autocvar_cl_announcer, "/yoda.wav"));
precache_sound (strcat("announcer/", autocvar_cl_announcer, "/amazing.wav"));
precache_sound (strcat("announcer/", autocvar_cl_announcer, "/awesome.wav"));
- precache_sound (strcat("announcer/", autocvar_cl_announcer, "/headshot.wav"));
precache_sound (strcat("announcer/", autocvar_cl_announcer, "/impressive.wav"));
precache_sound (strcat("announcer/", autocvar_cl_announcer, "/prepareforbattle.wav"));
float autocvar_cl_reticle_item_nex;
float autocvar_cl_reticle_item_normal;
float autocvar_cl_reticle_stretch;
+var float autocvar_cl_spawnzoom = 1;
+var float autocvar_cl_spawnzoom_speed = 1;
+var float autocvar_cl_spawnzoom_factor = 2;
float autocvar_cl_stripcolorcodes;
var float autocvar_cl_vehicle_spiderbot_cross_alpha = 0.6;
var float autocvar_cl_vehicle_spiderbot_cross_size = 1;
var float autocvar_g_waypointsprite_turrets = TRUE;
var float autocvar_g_waypointsprite_turrets_maxdist = 5000;
+var float autocvar_hud_cursormode = TRUE;
float autocvar_hud_colorflash_alpha;
float autocvar_hud_configure_checkcollisions;
float autocvar_hud_configure_grid;
float autocvar_hud_panel_notify_fadetime;
float autocvar_hud_panel_notify_flip;
float autocvar_hud_panel_notify_fontsize;
-float autocvar_hud_panel_notify_print;
float autocvar_hud_panel_notify_time;
float autocvar_hud_panel_physics;
float autocvar_hud_panel_physics_acceleration_progressbar_mode;
float autocvar_hud_panel_radar_rotation;
float autocvar_hud_panel_radar_scale;
float autocvar_hud_panel_radar_zoommode;
+float autocvar_hud_panel_radar_maximized_rotation;
+float autocvar_hud_panel_radar_maximized_zoommode;
float autocvar_hud_panel_score;
float autocvar_hud_panel_score_rankings;
float autocvar_hud_panel_timer;
float autocvar_hud_panel_weapons_complainbubble_fadetime;
float autocvar_hud_panel_weapons_complainbubble_padding;
float autocvar_hud_panel_weapons_complainbubble_time;
-var float autocvar_hud_panel_weapons_fade = 1;
float autocvar_hud_panel_weapons_label;
float autocvar_hud_panel_weapons_onlyowned;
float autocvar_hud_panel_weapons_timeout;
float autocvar_hud_panel_weapons_timeout_effect;
+float autocvar_hud_panel_weapons_timeout_fadebgmin;
+float autocvar_hud_panel_weapons_timeout_fadefgmin;
+var float autocvar_hud_panel_weapons_timeout_speed_in = 0.25;
+var float autocvar_hud_panel_weapons_timeout_speed_out = 0.75;
float autocvar_hud_progressbar_alpha;
float autocvar_hud_showbinds;
float autocvar_hud_showbinds_limit;
+float autocvar__hud_showbinds_reload;
float autocvar_hud_shownames;
float autocvar_hud_shownames_enemies;
float autocvar_hud_shownames_crosshairdistance;
float autocvar_r_letterbox;
float autocvar_scoreboard_accuracy;
float autocvar_scoreboard_accuracy_doublerows;
+float autocvar_scoreboard_accuracy_nocolors;
float autocvar_scoreboard_alpha_bg;
var float autocvar_scoreboard_alpha_fg = 1.0;
var float autocvar_scoreboard_alpha_name = 0.9;
float autocvar_scoreboard_offset_left;
float autocvar_scoreboard_offset_right;
float autocvar_scoreboard_offset_vertical;
+float autocvar_scoreboard_respawntime_decimals;
float autocvar_v_flipped;
float autocvar_vid_conheight;
float autocvar_vid_conwidth;
var float autocvar_cl_eventchase_death = 1;
var float autocvar_cl_eventchase_distance = 140;
var float autocvar_cl_eventchase_speed = 1.3;
+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';
float autocvar_cl_lerpexcess;
string autocvar__togglezoom;
float autocvar_cl_damageeffect;
float autocvar_cl_precacheplayermodels;
float autocvar_cl_deathglow;
float autocvar_developer_csqcentities;
+float autocvar_g_jetpack_attenuation;
casing.origin_x = ReadCoord();
casing.origin_y = ReadCoord();
casing.origin_z = ReadCoord();
+ setorigin(casing, casing.origin);
casing.velocity = decompressShortVector(ReadShort());
casing.angles_x = ReadByte() * 360 / 256;
casing.angles_y = ReadByte() * 360 / 256;
case "radar":
{
- hud_panel_radar_maximized = (argv(2) ? InterpretBoolean(argv(2)) : !hud_panel_radar_maximized);
+ if(argv(2))
+ hud_panel_radar_maximized = InterpretBoolean(argv(2));
+ else
+ hud_panel_radar_maximized = !hud_panel_radar_maximized;
return;
}
}
void Cmd_HUD_Help();
// used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file
-void LocalCommand_macro_write_aliases(float fh);
\ No newline at end of file
+void LocalCommand_macro_write_aliases(float fh);
string (float playernum, string key) getplayerkeyvalue = #348;
void (string cmdname) registercmd = #352;
+void(float usecursor) setcursormode = #343;
vector () getmousepos = #344;
string (string s) uncolorstring = #170;
-void CSQCModel_Hook_PreDraw();
+void CSQCModel_Hook_PreDraw(float isplayer);
.float isplayermodel;
entity tm;
for(tm = teams.sort_next; tm; tm = tm.sort_next)
- if(tm.team != COLOR_SPECTATOR)
+ if(tm.team != NUM_SPECTATOR)
++teams_count;
if(autocvar_cl_forcemyplayercolors)
// FEATURE: fallback frames
.float csqcmodel_saveframe;
.float csqcmodel_saveframe2;
+#ifdef CSQCMODEL_HAVE_TWO_FRAMES
.float csqcmodel_saveframe3;
.float csqcmodel_saveframe4;
+#endif
.float csqcmodel_framecount;
#define IS_DEAD_FRAME(f) ((f) == 0 || (f) == 1)
{
self.frame = self.csqcmodel_saveframe;
self.frame2 = self.csqcmodel_saveframe2;
+#ifdef CSQCMODEL_HAVE_TWO_FRAMES
self.frame3 = self.csqcmodel_saveframe3;
self.frame4 = self.csqcmodel_saveframe4;
+#endif
}
void CSQCPlayer_FallbackFrame_PostUpdate(float isnew)
{
self.csqcmodel_saveframe = self.frame;
self.csqcmodel_saveframe2 = self.frame2;
+#ifdef CSQCMODEL_HAVE_TWO_FRAMES
self.csqcmodel_saveframe3 = self.frame3;
self.csqcmodel_saveframe4 = self.frame4;
+#endif
// hack for death animations: set their frametime to zero in case a
// player "pops in"
}
FIX_FRAMETIME(frame, frame1time)
FIX_FRAMETIME(frame2, frame2time)
+#ifdef CSQCMODEL_HAVE_TWO_FRAMES
FIX_FRAMETIME(frame3, frame3time)
FIX_FRAMETIME(frame4, frame4time)
+#endif
}
self.csqcmodel_isdead = IS_DEAD_FRAME(self.frame);
}
{
self.frame = CSQCPlayer_FallbackFrame(self.frame);
self.frame2 = CSQCPlayer_FallbackFrame(self.frame2);
+#ifdef CSQCMODEL_HAVE_TWO_FRAMES
self.frame3 = CSQCPlayer_FallbackFrame(self.frame3);
self.frame4 = CSQCPlayer_FallbackFrame(self.frame4);
+#endif
}
// FEATURE: auto tag_index
{
entity oldself = self;
self = self.tag_entity;
- CSQCModel_Hook_PreDraw();
+ CSQCModel_Hook_PreDraw((self.entnum >= 1 && self.entnum <= maxclients));
self = oldself;
}
}
else if(self.tag_entity.isplayermodel)
{
- self.tag_index = gettagindex(self.tag_entity, "weapon");
- if(!self.tag_index)
- self.tag_index = gettagindex(self.tag_entity, "tag_weapon");
- if(!self.tag_index)
- self.tag_index = gettagindex(self.tag_entity, "bip01 r hand");
+ skeleton_loadinfo(self.tag_entity);
+ self.tag_index = self.tag_entity.bone_weapon;
}
}
float EF_DOUBLESIDED = 32768;
float EF_NOSELFSHADOW = 65536;
float EF_DYNAMICMODELLIGHT = 131072;
+float EF_RESTARTANIM_BIT = 1048576;
+float EF_TELEPORT_BIT = 2097152;
float MF_ROCKET = 1; // leave a trail
float MF_GRENADE = 2; // leave a trail
float MF_GIB = 4; // leave a trail
if(self.csqcmodel_teleported)
Projectile_ResetTrail(self.origin);
}
+.float snd_looping;
void CSQCModel_Effects_Apply(void)
{
float eff = self.csqcmodel_effects;
if(self.csqcmodel_effects & CSQCMODEL_EF_RESPAWNGHOST)
self.renderflags |= RF_ADDITIVE;
// also special in CSQCPlayer_GlowMod_Apply
+
+ if(self.csqcmodel_modelflags & MF_ROCKET)
+ {
+ if(!self.snd_looping)
+ {
+ sound(self, CH_TRIGGER_SINGLE, "misc/jetpack_fly.wav", VOL_BASE, autocvar_g_jetpack_attenuation);
+ self.snd_looping = CH_TRIGGER_SINGLE;
+ }
+ }
+ else
+ {
+ if(self.snd_looping)
+ {
+ sound(self, self.snd_looping, "misc/null.wav", VOL_BASE, autocvar_g_jetpack_attenuation);
+ self.snd_looping = 0;
+ }
+ }
+}
+
+void CSQCPlayer_Precache()
+{
+ precache_sound("misc/jetpack_fly.wav");
}
// FEATURE: auto glowmod
// general functions
.float csqcmodel_predraw_run;
-void CSQCModel_Hook_PreDraw()
+.float anim_frame;
+.float anim_frame1time;
+.float anim_frame2;
+.float anim_frame2time;
+.float anim_saveframe;
+.float anim_saveframe1time;
+.float anim_saveframe2;
+.float anim_saveframe2time;
+.float anim_prev_pmove_flags;
+void CSQCModel_Hook_PreDraw(float isplayer)
{
if(self.csqcmodel_predraw_run == framecount)
return;
CSQCPlayer_ForceModel_Apply(self.entnum == player_localnum + 1);
CSQCPlayer_GlowMod_Apply();
CSQCPlayer_LOD_Apply();
- CSQCPlayer_FallbackFrame_Apply();
+ if(!isplayer)
+ CSQCPlayer_FallbackFrame_Apply();
+ else
+ {
+ // we know that frame3 and frame4 fields, used by InterpolateAnimation, are left alone - but that is all we know!
+ skeleton_loadinfo(self);
+ float doblend = (self.bone_upperbody >= 0);
+ float onground = 0;
+ if(self == csqcplayer)
+ {
+ if(self.pmove_flags & PMF_ONGROUND)
+ onground = 1;
+ self.anim_prev_pmove_flags = self.pmove_flags;
+ if(self.pmove_flags & PMF_DUCKED)
+ animdecide_setstate(self, self.anim_state | ANIMSTATE_DUCK, FALSE);
+ else if(self.anim_state & ANIMSTATE_DUCK)
+ animdecide_setstate(self, self.anim_state - ANIMSTATE_DUCK, FALSE);
+ }
+ else
+ {
+ tracebox(self.origin + '0 0 1', self.mins, self.maxs, self.origin - '0 0 4', MOVE_NORMAL, self);
+ if(trace_startsolid || trace_fraction < 1)
+ onground = 1;
+ }
+ animdecide_init(self);
+ animdecide_setimplicitstate(self, onground);
+ animdecide_setframes(self, doblend, anim_frame, anim_frame1time, anim_frame2, anim_frame2time);
+ float sf = 0;
+ if(self.anim_saveframe != self.anim_frame || self.anim_saveframe1time != self.anim_frame1time)
+ sf |= CSQCMODEL_PROPERTY_FRAME;
+ if(self.anim_saveframe2 != self.anim_frame2 || self.anim_saveframe2time != self.anim_frame2time)
+ sf |= CSQCMODEL_PROPERTY_FRAME2;
+ self.anim_saveframe = self.anim_frame;
+ self.anim_saveframe1time = self.anim_frame1time;
+ self.anim_saveframe2 = self.anim_frame2;
+ self.anim_saveframe2time = self.anim_frame2time;
+ if(sf)
+ {
+ CSQCModel_InterpolateAnimation_2To4_PreNote(sf | CSQCMODEL_PROPERTY_LERPFRAC);
+ self.lerpfrac = (doblend ? 0.5 : 0);
+ self.frame = self.anim_frame;
+ self.frame1time = self.anim_frame1time;
+ self.frame2 = self.anim_frame2;
+ self.frame2time = self.anim_frame2time;
+ CSQCModel_InterpolateAnimation_2To4_Note(sf | CSQCMODEL_PROPERTY_LERPFRAC, FALSE);
+ }
+ CSQCModel_InterpolateAnimation_2To4_Do();
+ if(doblend)
+ {
+ skeleton_from_frames(self, self.csqcmodel_isdead);
+ }
+ else
+ {
+ free_skeleton_from_frames(self);
+ // just in case, clear these (we're animating in frame and frame3)
+ self.lerpfrac = 0;
+ self.lerpfrac4 = 0;
+ }
+ }
}
CSQCModel_AutoTagIndex_Apply();
void CSQCModel_Hook_PreUpdate(float isnew, float isplayer, float islocalplayer)
{
+ // interpolate v_angle
+ self.iflags |= IFLAG_V_ANGLE_X;
// revert to values from server
CSQCModel_Effects_PreUpdate();
if(self.isplayermodel)
{
- CSQCPlayer_FallbackFrame_PreUpdate();
+ if(!isplayer)
+ CSQCPlayer_FallbackFrame_PreUpdate();
CSQCPlayer_ForceModel_PreUpdate();
}
}
if(self.isplayermodel)
{
CSQCPlayer_ForceModel_PostUpdate();
- CSQCPlayer_FallbackFrame_PostUpdate(isnew);
+ if(!isplayer)
+ CSQCPlayer_FallbackFrame_PostUpdate(isnew);
}
CSQCModel_Effects_PostUpdate();
}
{
// particle effects for players and objects damaged by weapons (eg: flames coming out of victims shot with rockets)
- float life, nearestbone;
+ float life, nearestbone = 0;
string specstr, effectname;
entity e;
continue; // player model bone blacklist
// now choose the bone closest to impact origin
- if(vlen(hitorg - gettaginfo(self, tagnum)) <= vlen(hitorg - gettaginfo(self, nearestbone)))
+ if(nearestbone == 0 || vlen(hitorg - gettaginfo(self, tagnum)) <= vlen(hitorg - gettaginfo(self, nearestbone)))
nearestbone = tagnum;
}
gettaginfo(self, nearestbone); // set gettaginfo_name
void Ent_DamageInfo(float isNew)
{
- float dmg, rad, edge, thisdmg, forcemul, species, hitplayer;
+ float dmg, rad, edge, thisdmg, forcemul, species, hitplayer = FALSE;
vector force, thisforce;
entity oldself;
switch(w_deathtype)
{
- case DEATH_VHCRUSH:
+ case DEATH_VH_CRUSH:
break;
// spiderbot
- case DEATH_SBMINIGUN:
+ case DEATH_VH_SPID_MINIGUN:
string _snd;
_snd = strcat("weapons/ric", ftos(1 + rint(random() * 2)), ".waw");
sound(self, CH_SHOTS, _snd, VOL_BASE, ATTN_NORM);
pointparticles(particleeffectnum("spiderbot_minigun_impact"), self.origin, w_backoff * 1000, 1);
break;
- case DEATH_SBROCKET:
+ case DEATH_VH_SPID_ROCKET:
sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
pointparticles(particleeffectnum("spiderbot_rocket_explode"), self.origin, w_backoff * 1000, 1);
break;
- case DEATH_SBBLOWUP:
+ case DEATH_VH_SPID_DEATH:
sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_MIN);
pointparticles(particleeffectnum("explosion_big"), self.origin, w_backoff * 1000, 1);
break;
- case DEATH_WAKIGUN:
+ case DEATH_VH_WAKI_GUN:
sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_NORM);
pointparticles(particleeffectnum("wakizashi_gun_impact"), self.origin, w_backoff * 1000, 1);
break;
- case DEATH_WAKIROCKET:
+ case DEATH_VH_WAKI_ROCKET:
sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
pointparticles(particleeffectnum("wakizashi_rocket_explode"), self.origin, w_backoff * 1000, 1);
break;
- case DEATH_WAKIBLOWUP:
+ case DEATH_VH_WAKI_DEATH:
sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_MIN);
pointparticles(particleeffectnum("explosion_big"), self.origin, w_backoff * 1000, 1);
break;
- case DEATH_RAPTOR_CANNON:
+ case DEATH_VH_RAPT_CANNON:
sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_NORM);
pointparticles(particleeffectnum("raptor_cannon_impact"), self.origin, w_backoff * 1000, 1);
break;
- case DEATH_RAPTOR_BOMB_SPLIT:
+ case DEATH_VH_RAPT_FRAGMENT:
float i;
vector ang, vel;
for(i = 1; i < 4; ++i)
sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
pointparticles(particleeffectnum("raptor_bomb_spread"), self.origin, w_backoff * 1000, 1);
break;
- case DEATH_RAPTOR_BOMB:
+ case DEATH_VH_RAPT_BOMB:
sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
pointparticles(particleeffectnum("raptor_bomb_impact"), self.origin, w_backoff * 1000, 1);
break;
- case DEATH_RAPTOR_DEATH:
+ case DEATH_VH_RAPT_DEATH:
sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_MIN);
pointparticles(particleeffectnum("explosion_big"), self.origin, w_backoff * 1000, 1);
break;
- case DEATH_BUMB_GUN:
+ case DEATH_VH_BUMB_GUN:
sound(self, CH_SHOTS, "weapons/fireball_impact2.wav", VOL_BASE, ATTN_NORM);
pointparticles(particleeffectnum("bigplasma_impact"), self.origin, w_backoff * 1000, 1);
break;
case DEATH_TURRET_MLRS:
case DEATH_TURRET_HK:
- case DEATH_TURRET_WALKER_ROCKET:
+ case DEATH_TURRET_WALK_ROCKET:
case DEATH_TURRET_HELLION:
sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_MIN);
pointparticles(particleeffectnum("rocket_explode"), self.origin, w_backoff * 1000, 1);
break;
case DEATH_TURRET_MACHINEGUN:
- case DEATH_TURRET_WALKER_GUN:
+ case DEATH_TURRET_WALK_GUN:
_snd = strcat("weapons/ric", ftos(1 + rint(random() * 2)), ".waw");
sound(self, CH_SHOTS, _snd, VOL_BASE, ATTN_NORM);
pointparticles(particleeffectnum("machinegun_impact"), self.origin, w_backoff * 1000, 1);
pointparticles(particleeffectnum("electro_impact"), self.origin, w_backoff * 1000, 1);
break;
- case DEATH_TURRET_WALKER_MEELE:
+ case DEATH_TURRET_WALK_MEELE:
sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTN_MIN);
pointparticles(particleeffectnum("TE_SPARK"), self.origin, w_backoff * 1000, 1);
break;
{
float seglength, drifts, drifte, branchfactor, branchfactor_add;
- seglength = autocvar_cl_effects_lightningarc_segmentlength;
- drifts = autocvar_cl_effects_lightningarc_drift_start;
- drifte = autocvar_cl_effects_lightningarc_drift_end;
- branchfactor = autocvar_cl_effects_lightningarc_branchfactor_start;
- branchfactor = autocvar_cl_effects_lightningarc_branchfactor_add;
+ seglength = autocvar_cl_effects_lightningarc_segmentlength;
+ drifts = autocvar_cl_effects_lightningarc_drift_start;
+ drifte = autocvar_cl_effects_lightningarc_drift_end;
+ branchfactor = autocvar_cl_effects_lightningarc_branchfactor_start;
+ branchfactor_add = autocvar_cl_effects_lightningarc_branchfactor_add;
cl_effetcs_lightningarc(from,to,seglength,drifts,drifte,branchfactor,branchfactor_add);
}
org = trace_endpos;
}
- gib.move_origin = gib.origin = org;
+ gib.move_origin = org;
+ setorigin(gib, org);
gib.move_velocity = vconst * autocvar_cl_gibs_velocity_scale + vrand * autocvar_cl_gibs_velocity_random + '0 0 1' * autocvar_cl_gibs_velocity_up;
gib.move_avelocity = prandomvec() * vlen(gib.move_velocity) * autocvar_cl_gibs_avelocity_scale;
gib.move_time = time;
vector org, vel;
string specstr;
float issilent;
- string gentle_prefix;
+ string gentle_prefix = "morphed_";
float c, randomvalue;
gentle_prefix = "";
else if(cl_gentle_gibs == 3)
gentle_prefix = "happy_";
- else
- gentle_prefix = "morphed_";
}
else if(autocvar_cl_particlegibs)
{
if(amount <= 0 || !isNew)
return;
- self.origin = org; // for the sounds
+ setorigin(self, org); // for the sounds
specnum = (type & 0x78) / 8; // blood/gibmodel type: using four bits (0..7, bit indexes 3,4,5)
issilent = (type & 0x40);
case ENT_CLIENT_HOOK:
intensity = 1;
offset = 0;
- if(t == COLOR_TEAM1)
+ if(t == NUM_TEAM_1)
{
tex = "particles/hook_red";
rgb = '1 .3 .3';
}
- else if(t == COLOR_TEAM2)
+ else if(t == NUM_TEAM_2)
{
tex = "particles/hook_blue";
rgb = '.3 .3 1';
}
- else if(t == COLOR_TEAM3)
+ else if(t == NUM_TEAM_3)
{
tex = "particles/hook_yellow";
rgb = '1 1 .3';
}
- else if(t == COLOR_TEAM4)
+ else if(t == NUM_TEAM_4)
{
tex = "particles/hook_pink";
rgb = '1 .3 1';
sf = ReadByte();
self.HookSilent = (sf & 0x80);
- self.iflags = IFLAG_VELOCITY;
+ self.iflags = IFLAG_VELOCITY | IFLAG_ORIGIN;
InterpolateOrigin_Undo();
drawstring(position, text, scale, rgb, theAlpha, flag);
}
-// return the string of the given race place
-string race_PlaceName(float pos) {
- if(pos == 1)
- return _("1st");
- else if(pos == 2)
- return _("2nd");
- else if(pos == 3)
- return _("3rd");
- else
- return sprintf(_("%dth"), pos);
-}
-
// return the string of the onscreen race timer
string MakeRaceString(float cp, float mytime, float histime, float lapdelta, string hisname)
{
col = "^3";
}
else
+ {
col = "^7";
+ timestr = "";
+ }
if(cp == 254)
cpname = _("Start line");
return 0;
}
+float GetPlayerColorForce(float i)
+{
+ if(!teamplay)
+ return 0;
+ else
+ return stof(getplayerkeyvalue(i, "colors")) & 15;
+}
+
+float GetPlayerColor(float i)
+{
+ if not(playerslots[i].gotscores) // unconnected
+ return NUM_SPECTATOR;
+ else if(stof(getplayerkeyvalue(i, "frags")) == FRAGS_SPECTATOR)
+ return NUM_SPECTATOR;
+ else
+ return GetPlayerColorForce(i);
+}
+
+string GetPlayerName(float i)
+{
+ return ColorTranslateRGB(getplayerkeyvalue(i, "name"));
+}
+
+
/*
==================
HUD panels
// declarations
WEPSET_DECLARE_A(weapons_stat);
WEPSET_COPY_AS(weapons_stat);
- float i, f, a, j, factor;
- float screen_ar, center_x, center_y;
- float weapon_count, weapon_id, weapon_alpha;
- float row, column, rows, columns;
+ float i, f, a;
+ float screen_ar, center_x = 0, center_y;
+ float weapon_count, weapon_id;
+ float row, column, rows = 0, columns;
float aspect = autocvar_hud_panel_weapons_aspect;
- float show_accuracy, panel_weapon_accuracy;
+ float panel_weapon_accuracy;
float timeout = autocvar_hud_panel_weapons_timeout;
- float timein_effect_length = (autocvar_hud_panel_weapons_timeout_effect ? 0.375 : 0);
- float timeout_effect_length = (autocvar_hud_panel_weapons_timeout_effect ? 0.75 : 0);
+ 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, ammo_alpha;
- float barsize_x, barsize_y, baroffset_x, baroffset_y;
+ float ammo_type, 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;
- float when = autocvar_hud_panel_weapons_complainbubble_time;
- float fadetime = autocvar_hud_panel_weapons_complainbubble_fadetime;
+ float when = max(1, autocvar_hud_panel_weapons_complainbubble_time);
+ float fadetime = max(0, autocvar_hud_panel_weapons_complainbubble_fadetime);
- vector weapon_pos, weapon_size;
+ vector weapon_pos, weapon_size = '0 0 0';
local noref vector old_panel_size; // fteqcc sucks
- vector color, ammo_color;
+ vector color;
// check to see if we want to continue
if(hud != HUD_NORMAL) { return; }
{
if((!autocvar_hud_panel_weapons) || (spectatee_status == -1))
return;
- else if(timeout && time >= weapontime + timeout + timeout_effect_length)
+ if(timeout && time >= weapontime + timeout + timeout_effect_length)
+ if(autocvar_hud_panel_weapons_timeout_effect == 3 || (autocvar_hud_panel_weapons_timeout_effect == 1 && !(autocvar_hud_panel_weapons_timeout_fadebgmin + autocvar_hud_panel_weapons_timeout_fadefgmin)))
{
weaponprevtime = time;
return;
draw_beginBoldFont();
- // calculate fading effect to weapon images for when the panel is idle
- if(autocvar_hud_panel_weapons_fade)
- {
- weapon_alpha = 3.2 - 2 * (time - weapontime);
- weapon_alpha = bound(0.7, weapon_alpha, 1) * panel_fg_alpha;
- }
- else
- weapon_alpha = panel_fg_alpha;
-
// figure out weapon order (how the weapons are sorted) // TODO make this configurable
if(weaponorder_bypriority != autocvar_cl_weaponpriority || !weaponorder[0])
{
weaponorder_cmp_str = string_null;
}
+ if(!autocvar_hud_panel_weapons_complainbubble || autocvar__hud_configure || time - complain_weapon_time >= when + fadetime)
+ complain_weapon = 0;
+
// determine which weapons are going to be shown
if (autocvar_hud_panel_weapons_onlyowned)
{
}
// do we own this weapon?
+ weapon_count = 0;
for(i = 0; i <= WEP_LAST-WEP_FIRST; ++i)
if(WEPSET_CONTAINS_AW(weapons_stat, weaponorder[i].weapon))
++weapon_count;
// add it anyway if weaponcomplain is shown
- if((!autocvar__hud_configure)
- && (autocvar_hud_panel_weapons_complainbubble
- && time - complain_weapon_time < when + fadetime))
- ++weapon_count;
+ if(complain_weapon)
+ ++weapon_count;
// might as well commit suicide now, no reason to live ;)
- if (weapon_count == 0) { return; }
-
- // reduce size of the panel
- if (panel_size_y > panel_size_x)
+ if (weapon_count == 0)
{
- old_panel_size_y = panel_size_y;
- panel_size_y *= weapon_count / WEP_COUNT;
- panel_pos_y += (old_panel_size_y - panel_size_y) / 2;
+ draw_endBoldFont();
+ return;
}
- else
+
+ old_panel_size = panel_size;
+ if(panel_bg_padding)
+ old_panel_size -= '2 2 0' * panel_bg_padding;
+
+ // first find values for the standard table (with all the weapons)
+ rows = old_panel_size_y/old_panel_size_x;
+ rows = bound(1, floor((sqrt(4 * aspect * rows * WEP_COUNT + rows * rows) + rows + 0.5) / 2), WEP_COUNT);
+ columns = ceil(WEP_COUNT/rows);
+ weapon_size_x = old_panel_size_x / columns;
+ weapon_size_y = old_panel_size_y / rows;
+
+ // change table values to include only the owned weapons
+ // weapon_size won't be changed
+ if(weapon_count <= rows)
{
- old_panel_size_x = panel_size_x;
- panel_size_x *= weapon_count / WEP_COUNT;
- panel_pos_x += (old_panel_size_x - panel_size_x) / 2;
+ rows = weapon_count;
+ columns = 1;
}
+ else
+ columns = ceil(weapon_count / rows);
+
+ // reduce size of the panel
+ panel_size_x = columns * weapon_size_x;
+ panel_size_y = rows * weapon_size_y;
+ panel_pos_x += (old_panel_size_x - panel_size_x) / 2;
+ panel_pos_y += (old_panel_size_y - panel_size_y) / 2;
+ if(panel_bg_padding)
+ panel_size += '2 2 0' * panel_bg_padding;
}
else
weapon_count = WEP_COUNT;
{
if (timeout && time >= weapontime + timeout) // apply timeout effect if needed
{
- f = (time - (weapontime + timeout)) / timeout_effect_length;
- if (autocvar_hud_panel_weapons_timeout_effect == 1 || autocvar_hud_panel_weapons_timeout_effect == 3)
+ f = bound(0, (time - (weapontime + timeout)) / timeout_effect_length, 1);
+
+ // fade the panel alpha
+ if(autocvar_hud_panel_weapons_timeout_effect == 1)
+ {
+ panel_bg_alpha *= (autocvar_hud_panel_weapons_timeout_fadebgmin * f + (1 - f));
+ panel_fg_alpha *= (autocvar_hud_panel_weapons_timeout_fadefgmin * f + (1 - f));
+ }
+ else if(autocvar_hud_panel_weapons_timeout_effect == 3)
{
panel_bg_alpha *= (1 - f);
panel_fg_alpha *= (1 - f);
}
+
+ // move the panel off the screen
if (autocvar_hud_panel_weapons_timeout_effect == 2 || autocvar_hud_panel_weapons_timeout_effect == 3)
{
f *= f; // for a cooler movement
else //top
panel_pos_y -= f * (panel_pos_y + panel_size_y);
}
+ if(f == 1)
+ center_x = -1; // mark the panel as off screen
}
weaponprevtime = time - (1 - f) * timein_effect_length;
}
else if (timeout && time < weaponprevtime + timein_effect_length) // apply timein effect if needed
{
- f = (time - weaponprevtime) / timein_effect_length;
- if (autocvar_hud_panel_weapons_timeout_effect == 1 || autocvar_hud_panel_weapons_timeout_effect == 3)
+ f = bound(0, (time - weaponprevtime) / timein_effect_length, 1);
+
+ // fade the panel alpha
+ if(autocvar_hud_panel_weapons_timeout_effect == 1)
+ {
+ panel_bg_alpha *= (autocvar_hud_panel_weapons_timeout_fadebgmin * (1 - f) + f);
+ panel_fg_alpha *= (autocvar_hud_panel_weapons_timeout_fadefgmin * (1 - f) + f);
+ }
+ else if(autocvar_hud_panel_weapons_timeout_effect == 3)
{
panel_bg_alpha *= (f);
panel_fg_alpha *= (f);
}
+
+ // move the panel back on screen
if (autocvar_hud_panel_weapons_timeout_effect == 2 || autocvar_hud_panel_weapons_timeout_effect == 3)
{
f *= f; // for a cooler movement
// draw the background, then change the virtual size of it to better fit other items inside
HUD_Panel_DrawBg(1);
+
+ if(center_x == -1)
+ {
+ draw_endBoldFont();
+ return;
+ }
+
if(panel_bg_padding)
{
panel_pos += '1 1 0' * panel_bg_padding;
}
// after the sizing and animations are done, update the other values
- rows = panel_size_y/panel_size_x;
- rows = bound(1, floor((sqrt(4 * aspect * rows * weapon_count + rows * rows) + rows + 0.5) / 2), weapon_count);
- columns = ceil(weapon_count/rows);
- weapon_size = eX * panel_size_x*(1/columns) + eY * panel_size_y*(1/rows);
+
+ if(!rows) // if rows is > 0 onlyowned code has already updated these vars
+ {
+ rows = panel_size_y/panel_size_x;
+ rows = bound(1, floor((sqrt(4 * aspect * rows * weapon_count + rows * rows) + rows + 0.5) / 2), weapon_count);
+ columns = ceil(weapon_count/rows);
+ weapon_size = eX * panel_size_x*(1/columns) + eY * panel_size_y*(1/rows);
+ }
// calculate position/size for visual bar displaying ammount of ammo status
if (autocvar_hud_panel_weapons_ammo)
baroffset_y = (weapon_size_y - barsize_y) / 2;
}
}
+ if(autocvar_hud_panel_weapons_accuracy)
+ Accuracy_LoadColors();
- if(autocvar_hud_panel_weapons_accuracy && acc_levels)
- {
- show_accuracy = true;
- if (acc_col[0] == '-1 0 0')
- for (i = 0; i < acc_levels; ++i)
- acc_col[i] = stov(cvar_string(strcat("accuracy_color", ftos(i))));
- }
-
+ row = column = 0;
for(i = 0; i <= WEP_LAST-WEP_FIRST; ++i)
{
// retrieve information about the current weapon to be drawn
weapon_id = self.impulse;
// skip if this weapon doesn't exist
- if (!self || self.impulse < 0) { continue; }
+ if(!self || weapon_id < 0) { continue; }
// skip this weapon if we don't own it (and onlyowned is enabled)-- or if weapons_complainbubble is showing for this weapon
- if (autocvar_hud_panel_weapons_onlyowned
- && !(WEPSET_CONTAINS_AW(weapons_stat, self.weapon)
- || (self.weapon == complain_weapon
- && time - complain_weapon_time < when + fadetime
- && autocvar_hud_panel_weapons_complainbubble)))
- continue;
+ if(autocvar_hud_panel_weapons_onlyowned)
+ if not(WEPSET_CONTAINS_AW(weapons_stat, self.weapon) || (self.weapon == complain_weapon))
+ continue;
// figure out the drawing position of weapon
weapon_pos = (panel_pos
// draw background behind currently selected weapon
if(self.weapon == switchweapon)
- drawpic_aspect_skin(weapon_pos, "weapon_current_bg", weapon_size, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL);
+ drawpic_aspect_skin(weapon_pos, "weapon_current_bg", weapon_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
// draw the weapon accuracy
- if(show_accuracy)
+ if(autocvar_hud_panel_weapons_accuracy)
{
panel_weapon_accuracy = weapon_accuracy[self.weapon-WEP_FIRST];
if(panel_weapon_accuracy >= 0)
{
- // find the max level lower than weapon_accuracy
- j = acc_levels-1;
- while ( j && panel_weapon_accuracy < acc_lev[j] )
- --j;
-
- // inject color j+1 in color j, how much depending on how much weapon_accuracy is higher than level j
- factor = (panel_weapon_accuracy - acc_lev[j]) / (acc_lev[j+1] - acc_lev[j]);
- color = acc_col[j];
- color = color + factor * (acc_col[j+1] - color);
-
+ color = Accuracy_GetColor(panel_weapon_accuracy);
drawpic_aspect_skin(weapon_pos, "weapon_accuracy", weapon_size, color, panel_fg_alpha, DRAWFLAG_NORMAL);
}
}
if(WEPSET_CONTAINS_AW(weapons_stat, self.weapon))
{
// draw the weapon image
- drawpic_aspect_skin(weapon_pos, strcat("weapon", self.netname), weapon_size, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL);
+ drawpic_aspect_skin(weapon_pos, strcat("weapon", self.netname), weapon_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
// draw weapon label string
switch(autocvar_hud_panel_weapons_label)
}
// draw the complain message
- if(time - complain_weapon_time < when + fadetime && self.weapon == complain_weapon && autocvar_hud_panel_weapons_complainbubble)
+ if(self.weapon == complain_weapon)
{
if(fadetime)
a = ((complain_weapon_time + when > time) ? 1 : bound(0, (complain_weapon_time + when + fadetime - time) / fadetime, 1));
else
a = ((complain_weapon_time + when > time) ? 1 : 0);
-
string s;
if(complain_weapon_type == 0) {
s = _("Out of ammo");
mySize -= '2 2 0' * panel_bg_padding;
}
- float rows, columns, row, column;
+ float rows = 0, columns, row, column;
vector ammo_size;
if (autocvar_hud_panel_ammo_onlycurrent)
ammo_size = mySize;
ammo_size = eX * mySize_x*(1/columns) + eY * mySize_y*(1/rows);
}
- local noref vector offset; // fteqcc sucks
+ local vector offset = '0 0 0'; // fteqcc sucks
float newSize;
if(ammo_size_x/ammo_size_y > 3)
{
stat_items = getstati(STAT_ITEMS, 0, 24);
if (stat_items & IT_UNLIMITED_WEAPON_AMMO)
infinite_ammo = TRUE;
+ 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);
void DrawNumIcon_expanding(vector myPos, vector mySize, float x, string icon, float vertical, float icon_right_align, vector color, float theAlpha, float fadelerp)
{
- vector newPos, newSize;
+ vector newPos = '0 0 0', newSize = '0 0 0';
vector picpos, numpos;
if (vertical)
float panel_ar = mySize_x/mySize_y;
float is_vertical = (panel_ar < 1);
- vector shield_offset, strength_offset, superweapons_offset;
+ vector shield_offset = '0 0 0', strength_offset = '0 0 0', superweapons_offset = '0 0 0';
float superweapons_is = -1;
superweapons_iconalign = strength_iconalign;
superweapons_baralign = strength_baralign;
}
- else if(superweapons_is == 2)
+ else // if(superweapons_is == 2)
{
superweapons_offset = shield_offset;
superweapons_iconalign = shield_iconalign;
{
float panel_ar = mySize_x/mySize_y;
float is_vertical = (panel_ar < 1);
- vector health_offset, armor_offset;
+ vector health_offset = '0 0 0', armor_offset = '0 0 0';
if (panel_ar >= 4 || (panel_ar >= 1/4 && panel_ar < 1))
{
mySize_x *= 0.5;
// Notification area (#4)
//
-string Weapon_SuicideMessage(float deathtype)
-{
- w_deathtype = deathtype;
- get_weaponinfo(DEATH_WEAPONOF(deathtype)).weapon_func(WR_SUICIDEMESSAGE);
- return w_deathtypestring;
-}
-
-string Weapon_KillMessage(float deathtype)
-{
- w_deathtype = deathtype;
- get_weaponinfo(DEATH_WEAPONOF(deathtype)).weapon_func(WR_KILLMESSAGE);
- return w_deathtypestring;
-}
-
-#define KN_MAX_ENTRIES 10
-float kn_index;
-float killnotify_times[KN_MAX_ENTRIES];
-float killnotify_deathtype[KN_MAX_ENTRIES];
-float killnotify_actiontype[KN_MAX_ENTRIES]; // 0 = "Y [used by] X", 1 = "X [did action to] Y"
-string killnotify_attackers[KN_MAX_ENTRIES];
-string killnotify_victims[KN_MAX_ENTRIES];
-void HUD_KillNotify_Push(string attacker, string victim, float actiontype, float wpn)
+void HUD_Notify_Push(string icon, string attacker, string victim)
{
- --kn_index;
- if (kn_index == -1)
- kn_index = KN_MAX_ENTRIES-1;
- killnotify_times[kn_index] = time;
- killnotify_deathtype[kn_index] = wpn;
- killnotify_actiontype[kn_index] = actiontype;
- if(killnotify_attackers[kn_index])
- strunzone(killnotify_attackers[kn_index]);
- killnotify_attackers[kn_index] = strzone(attacker);
- if(killnotify_victims[kn_index])
- strunzone(killnotify_victims[kn_index]);
- killnotify_victims[kn_index] = strzone(victim);
-}
+ if(icon != "")
+ {
+ --kn_index;
+ if (kn_index == -1) { kn_index = KN_MAX_ENTRIES-1; }
+ notify_times[kn_index] = time;
-void HUD_KillNotify(string s1, string s2, string s3, float type, float msg) // s1 = attacker, s2 = victim
-{
- float w;
- float alsoprint, gentle;
- alsoprint = (autocvar_hud_panel_notify_print || !panel_enabled); // print message to console if: notify panel disabled, or cvar to do so enabled
- gentle = (autocvar_cl_gentle || autocvar_cl_gentle_messages);
-
- if ((msg == MSG_SUICIDE || msg == MSG_KILL || msg == MSG_KILL_ACTION) && gametype == MAPINFO_TYPE_CTS) // selfkill isn't interesting in CTS and only spams up the notify panel
- return;
+ // icon
+ if(notify_icon[kn_index]) { strunzone(notify_icon[kn_index]); }
+ notify_icon[kn_index] = strzone(icon);
- if(msg == MSG_SUICIDE) {
- w = DEATH_WEAPONOF(type);
- if(WEP_VALID(w)) {
- HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
- if (alsoprint)
- print("^1", sprintf(Weapon_SuicideMessage(type), strcat(s1, "^1")), "\n");
- } else if (type == DEATH_KILL) {
- HUD_KillNotify_Push(s1, "", 0, DEATH_KILL);
- if (alsoprint)
- print (sprintf(_("^1%s^1 couldn't take it anymore\n"), s1));
- } else if (type == DEATH_ROT) {
- HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
- if (alsoprint)
- print (sprintf(_("^1%s^1 died\n"), s1));
- } else if (type == DEATH_NOAMMO) {
- HUD_KillNotify_Push(s1, "", 0, DEATH_NOAMMO);
- if (alsoprint)
- print (sprintf(_("^7%s^7 committed suicide. What's the point of living without ammo?\n"), s1));
- } else if (type == DEATH_CAMP) {
- HUD_KillNotify_Push(s1, "", 0, DEATH_CAMP);
- if (alsoprint)
- print (sprintf(_("^1%s^1 thought they found a nice camping ground\n"), s1));
- } else if (type == KILL_TEAM_RED || type == KILL_TEAM_BLUE) {
- HUD_KillNotify_Push(s1, "", 0, type);
- if (alsoprint)
- print (sprintf(_("^1%s^1 didn't become friends with the Lord of Teamplay\n"), s1));
- } else if (type == DEATH_CHEAT) {
- HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
- if (alsoprint)
- print (sprintf(_("^1%s^1 unfairly eliminated themself\n"), s1));
- } else if (type == DEATH_FIRE) {
- HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
- if (alsoprint)
- print (sprintf(_("^1%s^1 burned to death\n"), s1));
- } else if (type != DEATH_TEAMCHANGE && type != DEATH_QUIET) {
- HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
- if (alsoprint)
- print (sprintf(_("^1%s^1 couldn't resist the urge to self-destruct\n"), s1));
- }
-
- if (stof(s2) > 2) // killcount > 2
- print (sprintf(_("^1%s^1 ended it all after a %d kill spree\n"), s1, stof(s2)));
- } else if(msg == MSG_KILL) {
- w = DEATH_WEAPONOF(type);
- if(WEP_VALID(w)) {
- HUD_KillNotify_Push(s1, s2, 1, type);
- if (alsoprint)
- print("^1", sprintf(Weapon_KillMessage(type), strcat(s2, "^1"), strcat(s1, "^1")), "\n"); // default order: victim, killer
- }
- else if(type == KILL_TEAM_RED || type == KILL_TEAM_BLUE || type == KILL_TEAM_SPREE) {
- HUD_KillNotify_Push(s1, s2, 1, type);
- if(alsoprint)
- {
- if(gentle) {
- print (sprintf(_("^1%s^1 took action against a team mate\n"), s1));
- } else {
- print (sprintf(_("^1%s^1 mows down a team mate\n"), s1));
- }
- }
- if (stof(s2) > 2 && type == KILL_TEAM_SPREE) {
- if(gentle)
- print (sprintf(_("^1%s^1 ended a %d scoring spree by going against a team mate\n"), s1, stof(s3)));
- else
- print (sprintf(_("^1%s^1 ended a %d kill spree by killing a team mate\n"), s1, stof(s3)));
- }
- else if (stof(s2) > 2) {
- if(gentle)
- print (sprintf(_("^1%s^1's %s scoring spree was ended by a team mate!\n"), s1, stof(s3)));
- else
- print (sprintf(_("^1%s^1's %s kill spree was ended by a team mate!\n"), s1, stof(s3)));
- }
- }
- else if(type == KILL_FIRST_BLOOD)
- print(sprintf(_("^1%s^1 drew first blood\n"), s1));
- else if (type == DEATH_TELEFRAG) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_TELEFRAG);
- if(gentle)
- print (sprintf(_("^1%s^1 tried to occupy %s^1's teleport destination space\n"), s2, s1));
- else
- print (sprintf(_("^1%s^1 was telefragged by %s\n"), s2, s1));
- }
- else if (type == DEATH_DROWN) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_DROWN);
- if(alsoprint)
- print (sprintf(_("^1%s^1 was drowned by %s\n"), s2, s1));
- }
- else if (type == DEATH_SLIME) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_SLIME);
- if(alsoprint)
- print (sprintf(_("^1%s^1 was slimed by %s\n"), s2, s1));
- }
- else if (type == DEATH_LAVA) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_LAVA);
- if(alsoprint)
- print (sprintf(_("^1%s^1 was cooked by %s\n"), s2, s1));
- }
- else if (type == DEATH_FALL) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_FALL);
- if(alsoprint)
- print (sprintf(_("^1%s^1 was grounded by %s\n"), s2, s1));
- }
- else if (type == DEATH_SHOOTING_STAR) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_SHOOTING_STAR);
- if(alsoprint)
- print (sprintf(_("^1%s^1 was shot into space by %s\n"), s2, s1));
- }
- else if (type == DEATH_SWAMP) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
- if(alsoprint)
- print (sprintf(_("^1%s^1 was conserved by %s\n"), s2, s1));
- }
- else if (type == DEATH_HURTTRIGGER)
- {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_HURTTRIGGER);
- if(alsoprint)
- print(sprintf(_("^1%s^1 was thrown into a world of hurt by %s\n"), s2, s1));
- } else if(type == DEATH_VHCRUSH) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
- if(alsoprint)
- print (sprintf(_("^1%s^1 was crushed by %s\n"), s2, s1));
- } else if(type == DEATH_SBMINIGUN) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
- if(alsoprint)
- print (sprintf(_("^1%s^1 got shredded by %s\n"), s2, s1));
- } else if(type == DEATH_SBROCKET) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
- if(alsoprint)
- print (sprintf(_("^1%s^1 was blasted to bits by %s\n"), s2, s1));
- } else if(type == DEATH_SBBLOWUP) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
- if(alsoprint)
- print (sprintf(_("^1%s^1 got caught in the blast when %s^1's destroys a vehicle\n"), s2, s1));
- } else if(type == DEATH_WAKIGUN) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
- if(alsoprint)
- print (sprintf(_("^1%s^1 was bolted down by %s\n"), s2, s1));
- } else if(type == DEATH_BUMB_GUN) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
- if(alsoprint)
- print (sprintf(_("^1%s^1 saw %s's preddy lights.\n"), s2, s1));
- } else if(type == DEATH_WAKIROCKET) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
- if(alsoprint)
- print (sprintf(_("^1%s^1 could find no shelter from %s^1's rockets\n"), s2, s1));
- } else if(type == DEATH_WAKIBLOWUP) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
- if(alsoprint)
- print (sprintf(_("^1%s^1 got caught in the blast when %s^1's destroys a vehicle\n"), s2, s1));
- } else if(type == DEATH_RAPTOR_CANNON) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
- if(alsoprint)
- print (sprintf(_("^1%s^1 nailed to hell by %s\n"), s2, s1));
- } else if(type == DEATH_RAPTOR_BOMB) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
- if(alsoprint)
- print (sprintf(_("^1%s^1 cluster crushed by %s\n"), s2, s1));
- } else if(type == DEATH_RAPTOR_DEATH) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
- if(alsoprint)
- print (sprintf(_("^1%s^1 got caught in the blast when %s^1's destroys a vehicle\n"), s2, s1));
- } else if(type == DEATH_TURRET) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
- if(alsoprint)
- print (sprintf(_("^1%s^1 was pushed into the line of fire by %s\n"), s2, s1));
- } else if(type == DEATH_TOUCHEXPLODE) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
- if(alsoprint)
- print (sprintf(_("^1%s^1 was pushed into an accident by %s\n"), s2, s1));
- } else if(type == DEATH_CHEAT) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
- if(alsoprint)
- print (sprintf(_("^1%s^1 was unfairly eliminated by %s\n"), s2, s1));
- } else if (type == DEATH_FIRE) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
- if(alsoprint)
- print (sprintf(_("^1%s^1 was burnt to death by %s\n"), s2, s1));
- } else if (type == DEATH_CUSTOM) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_CUSTOM);
- if(alsoprint)
- print("^1", sprintf(s3, strcat(s2, "^1"), strcat(s1, "^1")), "\n");
- } else if (type == DEATH_HURTTRIGGER) {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_HURTTRIGGER);
- if(alsoprint)
- print("^1", sprintf(s3, strcat(s2, "^1"), strcat(s1, "^1")), "\n");
- } else {
- HUD_KillNotify_Push(s1, s2, 1, DEATH_GENERIC);
- if(alsoprint)
- print (sprintf(_("^1%s^1 was fragged by %s\n"), s2, s1));
- }
- } else if(msg == MSG_SPREE) {
- if(type == KILL_END_SPREE) {
- if(gentle)
- print (sprintf(_("^1%s^1's %s scoring spree was ended by %s\n"), s1, s2, s3));
- else
- print (sprintf(_("^1%s^1's %s kill spree was ended by %s\n"), s1, s2, s3));
- } else if(type == KILL_SPREE) {
- if(gentle)
- print (sprintf(_("^1%s^1 made %s scores in a row\n"), s1, s2));
- else
- print (sprintf(_("^1%s^1 has %s frags in a row\n"), s1, s2));
- } else if(type == KILL_SPREE_3) {
- if(gentle)
- print (sprintf(_("%s^7 made a ^1TRIPLE SCORE\n"), s1));
- else
- print (sprintf(_("%s^7 made a ^1TRIPLE FRAG\n"), s1));
- } else if(type == KILL_SPREE_5) {
- if(gentle)
- print (sprintf(_("%s^7 unleashes ^1SCORING RAGE\n"), s1));
- else
- print (sprintf(_("%s^7 unleashes ^1RAGE\n"), s1));
- } else if(type == KILL_SPREE_10) {
- if(gentle)
- print (sprintf(_("%s^7 made ^1TEN SCORES IN A ROW!\n"), s1));
- else
- print (sprintf(_("%s^7 starts the ^1MASSACRE!\n"), s1));
- } else if(type == KILL_SPREE_15) {
- if(gentle)
- print (sprintf(_("%s^7 made ^1FIFTEEN SCORES IN A ROW!\n"), s1));
- else
- print (sprintf(_("%s^7 executes ^1MAYHEM!\n"), s1));
- } else if(type == KILL_SPREE_20) {
- if(gentle)
- print (sprintf(_("%s^7 made ^1TWENTY SCORES IN A ROW!\n"), s1));
- else
- print (sprintf(_("%s^7 is a ^1BERSERKER!\n"), s1));
- } else if(type == KILL_SPREE_25) {
- if(gentle)
- print (sprintf(_("%s^7 made ^1TWENTY FIVE SCORES IN A ROW!\n"), s1));
- else
- print (sprintf(_("%s^7 inflicts ^1CARNAGE!\n"), s1));
- } else if(type == KILL_SPREE_30) {
- if(gentle)
- print (sprintf(_("%s^7 made ^1THIRTY SCORES IN A ROW!\n"), s1));
- else
- print (sprintf(_("%s^7 unleashes ^1ARMAGEDDON!\n"), s1));
- }
- } else if(msg == MSG_KILL_ACTION) { // wtf is this? isnt it basically the same as MSG_SUICIDE?
- if (type == DEATH_DROWN) {
- HUD_KillNotify_Push(s1, "", 0, DEATH_DROWN);
- if(alsoprint)
- {
- if(gentle)
- print (sprintf(_("^1%s^1 was in the water for too long\n"), s1));
- else
- print (sprintf(_("^1%s^1 drowned\n"), s1));
- }
- } else if (type == DEATH_SLIME) {
- HUD_KillNotify_Push(s1, "", 0, DEATH_SLIME);
- if(alsoprint)
- print (sprintf(_("^1%s^1 was slimed\n"), s1));
- } else if (type == DEATH_LAVA) {
- HUD_KillNotify_Push(s1, "", 0, DEATH_LAVA);
- if(alsoprint)
- {
- if(gentle)
- print (sprintf(_("^1%s^1 found a hot place\n"), s1));
- else
- print (sprintf(_("^1%s^1 turned into hot slag\n"), s1));
- }
- } else if (type == DEATH_FALL) {
- HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
- if(alsoprint)
- {
- if(gentle)
- print (sprintf(_("^1%s^1 tested gravity (and it worked)\n"), s1));
- else
- print (sprintf(_("^1%s^1 hit the ground with a crunch\n"), s1));
- }
- } else if (type == DEATH_SHOOTING_STAR) {
- HUD_KillNotify_Push(s1, "", 0, DEATH_SHOOTING_STAR);
- if(alsoprint)
- print (sprintf(_("^1%s^1 became a shooting star\n"), s1));
- } else if (type == DEATH_SWAMP) {
- HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
- if(alsoprint)
- {
- if(gentle)
- print (sprintf(_("^1%s^1 discovered a swamp\n"), s1));
- else
- print (sprintf(_("^1%s^1 is now conserved for centuries to come\n"), s1));
- }
- } else if(DEATH_ISTURRET(type)) {
- HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
- if(alsoprint)
- {
- if(gentle)
- print (sprintf(_("^1%s^1 ran into a turret\n"), s1));
- else
- {
- switch(type)
- {
- case DEATH_TURRET_EWHEEL:
- print (sprintf(_("^1%s^1 was laserd down by a eWheel turret \n"), s1));
- break;
- case DEATH_TURRET_FLAC:
- print (sprintf(_("^1%s^1 got caught in the flac \n"), s1));
- break;
- case DEATH_TURRET_MACHINEGUN:
- print (sprintf(_("^1%s^1 was riddeld full of riddled by a machinegun turret \n"), s1));
- break;
- case DEATH_TURRET_WALKER_GUN:
- print (sprintf(_("^1%s^1 got served a led enrichment by a walker turret \n"), s1));
- break;
- case DEATH_TURRET_WALKER_MEELE:
- print (sprintf(_("^1%s^1 was impaled by a walker turret \n"), s1));
- break;
- case DEATH_TURRET_WALKER_ROCKET:
- print (sprintf(_("^1%s^1 was rocketed to hell by a walker turret \n"), s1));
- break;
- case DEATH_TURRET_HELLION:
- print (sprintf(_("^1%s^1 was blasted away hellion turret \n"), s1));
- break;
- case DEATH_TURRET_HK:
- print (sprintf(_("^1%s^1 could not hide from the hunter turret \n"), s1));
- break;
- case DEATH_TURRET_MLRS:
- print (sprintf(_("^1%s^1 got turned into smoldering gibs by a mlrs turret \n"), s1));
- break;
- case DEATH_TURRET_PLASMA:
- print (sprintf(_("^1%s^1 got served some superheated plasma from a plasma turret \n"), s1));
- break;
- case DEATH_TURRET_PHASER:
- print (sprintf(_("^1%s^1 was phased out \n"), s1));
- break;
- case DEATH_TURRET_TESLA:
- print (sprintf(_("^1%s^1 was electrocuted by a tesla turret \n"), s1));
- break;
- }
- }
- }
- } else if (type == DEATH_CUSTOM) {
- HUD_KillNotify_Push(s1, "", 0, DEATH_CUSTOM);
- if(alsoprint)
- print("^1", sprintf(s2, strcat(s1, "^1")), "\n");
- } else if (type == DEATH_HURTTRIGGER) {
- HUD_KillNotify_Push(s1, "", 0, DEATH_HURTTRIGGER);
- if(alsoprint)
- print("^1", sprintf(s2, strcat(s1, "^1")), "\n");
- } else if(type == DEATH_TOUCHEXPLODE) {
- HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
- if(alsoprint)
- print (sprintf(_("^1%s^1 died in an accident\n"), s1));
- } else if(type == DEATH_CHEAT) {
- HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
- if(alsoprint)
- print (sprintf(_("^1%s^1 was unfairly eliminated\n"), s1));
- } else if(type == DEATH_FIRE) {
- HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
- if(alsoprint)
- {
- if(gentle)
- print (sprintf(_("^1%s^1 felt a little hot\n"), s1));
- else
- print (sprintf(_("^1%s^1 burnt to death\n"), s1));
- }
- } else {
- HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
- if(alsoprint)
- {
- if(gentle)
- print (sprintf(_("^1%s^1 needs a restart\n"), s1));
- else
- print (sprintf(_("^1%s^1 died\n"), s1));
- }
- }
- } else if(msg == MSG_KILL_ACTION_SPREE) {
- if(gentle)
- print (sprintf(_("^1%s^1 needs a restart after a %d scoring spree\n"), s1, stof(s2)));
- else
- print (sprintf(_("^1%s^1 died with a %d kill spree\n"), s1, stof(s2)));
- } else if(msg == MSG_INFO) {
- if(type == INFO_GOTFLAG) { // here, s2 is the flag name
- HUD_KillNotify_Push(s1, s2, 0, INFO_GOTFLAG);
- print(sprintf(_("%s^7 got the %s\n"), s1, s2));
- } else if(type == INFO_LOSTFLAG) {
- HUD_KillNotify_Push(s1, s2, 0, INFO_LOSTFLAG);
- print(sprintf(_("%s^7 lost the %s\n"), s1, s2));
- } else if(type == INFO_PICKUPFLAG) {
- HUD_KillNotify_Push(s1, s2, 0, INFO_GOTFLAG);
- print(sprintf(_("%s^7 picked up the %s\n"), s1, s2));
- } else if(type == INFO_RETURNFLAG) {
- HUD_KillNotify_Push(s1, s2, 0, INFO_RETURNFLAG);
- print(sprintf(_("%s^7 returned the %s\n"), s1, s2));
- } else if(type == INFO_CAPTUREFLAG) {
- HUD_KillNotify_Push(s1, s2, 0, INFO_CAPTUREFLAG);
- print(sprintf(_("%s^7 captured the %s%s\n"), s1, s2, s3));
- }
- } else if(msg == MSG_RACE) {
- if(type == RACE_SERVER_RECORD) {
- HUD_KillNotify_Push(s1, s2, 1, RACE_SERVER_RECORD);
- }
- else if(type == RACE_NEW_RANK) {
- HUD_KillNotify_Push(s1, s2, 1, RACE_NEW_RANK);
- }
- else if(type == RACE_NEW_TIME) {
- HUD_KillNotify_Push(s1, s2, 1, RACE_NEW_TIME);
- }
- else if(type == RACE_FAIL) {
- HUD_KillNotify_Push(s1, s2, 1, RACE_FAIL);
- }
- } else if(msg == MSG_KA) {
- if(type == KA_PICKUPBALL) {
- HUD_KillNotify_Push(s1, s2, 0, KA_PICKUPBALL);
- if(alsoprint)
- print (sprintf(_("%s^7 has picked up the ball!\n"), s1));
- }
- else if(type == KA_DROPBALL) {
- HUD_KillNotify_Push(s1, s2, 0, KA_DROPBALL);
- if(alsoprint)
- print(sprintf(_("%s^7 has dropped the ball!\n"), s1));
- }
- }
-}
+ // attacker
+ if(notify_attackers[kn_index]) { strunzone(notify_attackers[kn_index]); }
+ notify_attackers[kn_index] = strzone(attacker);
-void HUD_KillCenterprint(string s1, string s2, float type, float msg)
-{
- float gentle;
- gentle = (autocvar_cl_gentle || autocvar_cl_gentle_messages);
- if(msg == MSG_SUICIDE) {
- if (type == DEATH_TEAMCHANGE) {
- centerprint_hud(sprintf(_("You are now on: %s"), s1));
- } else if (type == DEATH_AUTOTEAMCHANGE) {
- centerprint_hud(sprintf(_("You have been moved into a different team to improve team balance\nYou are now on: %s"), s1));
- } else if (type == DEATH_CAMP) {
- if(gentle)
- centerprint_hud(_("^1Reconsider your tactics, camper!"));
- else
- centerprint_hud(_("^1Die camper!"));
- } else if (type == DEATH_NOAMMO) {
- if(gentle)
- centerprint_hud(_("^1You are reinserted into the game for running out of ammo..."));
- else
- centerprint_hud(_("^1You were killed for running out of ammo..."));
- } else if (type == DEATH_ROT) {
- if(gentle)
- centerprint_hud(_("^1You need to preserve your health"));
- else
- centerprint_hud(_("^1You grew too old without taking your medicine"));
- } else if (type == KILL_TEAM_RED || type == KILL_TEAM_BLUE) {
- if(gentle)
- centerprint_hud(_("^1Don't go against team mates!"));
- else
- centerprint_hud(_("^1Don't shoot your team mates!"));
- } else if (type == DEATH_QUIET) {
- // do nothing
- } else { // generic message
- if(gentle)
- centerprint_hud(_("^1You need to be more careful!"));
- else
- centerprint_hud(_("^1You killed your own dumb self!"));
- }
- } else if(msg == MSG_KILL) {
- if (type == KILL_TEAM_RED || type == KILL_TEAM_BLUE) {
- if(gentle) {
- centerprint_hud(sprintf(_("^1Moron! You went against ^7%s^1, a team mate!"), s1));
- } else {
- centerprint_hud(sprintf(_("^1Moron! You fragged ^7%s^1, a team mate!"), s1));
- }
- } else if (type == KILL_FIRST_BLOOD) {
- if(gentle) {
- centerprint_hud(_("^1First score"));
- } else {
- centerprint_hud(_("^1First blood"));
- }
- } else if (type == KILL_FIRST_VICTIM) {
- if(gentle) {
- centerprint_hud(_("^1First casualty"));
- } else {
- centerprint_hud(_("^1First victim"));
- }
- } else if (type == KILL_TYPEFRAG) { // s2 contains "advanced kill messages" such as ping, handicap...
- if(gentle) {
- centerprint_hud(strcat(sprintf(_("^1You scored against ^7%s^1 who was typing!"), s1), s2));
- } else {
- centerprint_hud(strcat(sprintf(_("^1You typefragged ^7%s"), s1), s2));
- }
- } else if (type == KILL_TYPEFRAGGED) {
- if(gentle) {
- centerprint_hud(strcat(sprintf(_("^1You were scored against by ^7%s^1 while you were typing!"), s1), s2));
- } else {
- centerprint_hud(strcat(sprintf(_("^1You were typefragged by ^7%s"), s1), s2));
- }
- } else if (type == KILL_FRAG) {
- if(gentle) {
- centerprint_hud(strcat(sprintf(_("^4You scored against ^7%s"), s1), s2));
- } else {
- centerprint_hud(strcat(sprintf(_("^4You fragged ^7%s"), s1), s2));
- }
- } else { // generic message
- if(gentle) {
- centerprint_hud(strcat(sprintf(_("^1You were scored against by ^7%s"), s1), s2));
- } else {
- centerprint_hud(strcat(sprintf(_("^1You were fragged by ^7%s"), s1), s2));
- }
- }
- } else if(msg == MSG_KILL_ACTION) {
- // TODO: invent more centerprints here?
- centerprint_hud(_("^1Watch your step!"));
+ // victim
+ if(notify_victims[kn_index]) { strunzone(notify_victims[kn_index]); }
+ notify_victims[kn_index] = strzone(victim);
}
}
-void HUD_Notify (void)
+void HUD_Notify(void)
{
if(!autocvar__hud_configure)
{
float fadetime;
fadetime = autocvar_hud_panel_notify_fadetime;
- string s;
-
- vector pos_attacker, pos_victim;
- vector weap_pos;
+ vector pos_attacker, pos_victim, pos_icon;
float width_attacker;
- string attacker, victim;
+ string attacker, victim, icon;
- float i, j, w, type, step, limit;
+ float i, j, step, limit;
if(autocvar_hud_panel_notify_flip) //order items from the top down
{
i = 0;
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);
- s = strcat("weapon", get_weaponinfo(WEP_FIRST + mod(floor(a*2.4), WEP_LAST)).netname);
+ 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;
}
-
- if (j == KN_MAX_ENTRIES)
- j = 0;
-
- if(killnotify_times[j] + when > time)
- a = 1;
- else if(fadetime)
- {
- a = bound(0, (killnotify_times[j] + when + fadetime - time) / fadetime, 1);
- if(!a)
- {
- break;
- }
- }
else
{
- break;
- }
-
- s = "";
+ if (j == KN_MAX_ENTRIES)
+ j = 0;
- type = killnotify_deathtype[j];
- w = DEATH_WEAPONOF(type);
-
- // TODO: maybe print in team colors?
- //
- // Y [used by] X
- if(killnotify_actiontype[j] == 0)
- {
- if(type == DEATH_GENERIC)
- {
- s = "notify_death";
- }
- else if(type == DEATH_NOAMMO)
- {
- s = "notify_outofammo";
- }
- else if(type == DEATH_KILL)
- {
- s = "notify_selfkill";
- }
- else if(type == DEATH_CAMP)
- {
- s = "notify_camping";
- }
- else if(type == KILL_TEAM_RED)
- {
- s = "notify_teamkill_red";
- }
- else if(type == KILL_TEAM_BLUE)
- {
- s = "notify_teamkill_blue";
- }
- else if(type == DEATH_DROWN)
- {
- s = "notify_water";
- }
- else if(type == DEATH_SLIME)
- {
- s = "notify_slime";
- }
- else if(type == DEATH_LAVA)
- {
- s = "notify_lava";
- }
- else if(type == DEATH_FALL)
- {
- s = "notify_fall";
- }
- else if(type == DEATH_SHOOTING_STAR)
- {
- s = "notify_shootingstar";
- }
- else if(type == DEATH_HURTTRIGGER || type == DEATH_CUSTOM)
- {
- s = "notify_death";
- }
- else if(type == INFO_GOTFLAG)
- {
- if(killnotify_victims[j] == "^1RED^7 flag")
- {
- s = "notify_red_taken";
- }
- else
- {
- s = "notify_blue_taken";
- }
- }
- else if(type == INFO_RETURNFLAG)
- {
- if(killnotify_victims[j] == "^1RED^7 flag")
- {
- s = "notify_red_returned";
- }
- else
- {
- s = "notify_blue_returned";
- }
- }
- else if(type == INFO_LOSTFLAG)
- {
- if(killnotify_victims[j] == "^1RED^7 flag")
- {
- s = "notify_red_lost";
- }
- else
- {
- s = "notify_blue_lost";
- }
- }
- else if(type == INFO_CAPTUREFLAG)
+ if(notify_times[j] + when > time)
+ a = 1;
+ else if(fadetime)
{
- if(killnotify_victims[j] == "^1RED^7 flag")
+ a = bound(0, (notify_times[j] + when + fadetime - time) / fadetime, 1);
+ if(!a)
{
- s = "notify_red_captured";
- }
- else
- {
- s = "notify_blue_captured";
+ break;
}
}
- else if(type == KA_DROPBALL)
- {
- s = "notify_balldropped";
- }
- else if(type == KA_PICKUPBALL)
+ else
{
- s = "notify_ballpickedup";
+ break;
}
- attacker = textShortenToWidth(killnotify_attackers[j], 0.48 * mySize_x - height, fontsize, stringwidth_colors);
- pos_attacker = pos + eX * (0.52 * mySize_x + height) + eY * ((0.5 * fontsize_y + i * height) + (0.5 * (height - fontheight)));
- weap_pos = pos + eX * 0.5 * mySize_x - eX * height + eY * i * height;
-
- if(s != "")
- {
- drawpic_aspect_skin(weap_pos, s, '2 1 0' * height, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
- drawcolorcodedstring(pos_attacker, attacker, fontsize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
- }
+ attacker = notify_attackers[j];
+ victim = notify_victims[j];
+ icon = notify_icon[j];
}
- // X [did action to] Y
- else
+
+ //type = notify_deathtype[j];
+ //w = DEATH_WEAPONOF(type);
+
+ if(icon != "")
{
- if(type & HITTYPE_SECONDARY && w == WEP_LASER)
- {
- s = "notify_melee_laser";
- }
- else if(type & HITTYPE_SECONDARY && w == WEP_SHOTGUN)
- {
- s = "notify_melee_shotgun";
- }
- else if(type & HITTYPE_HEADSHOT && (w == WEP_RIFLE || w == WEP_MINSTANEX)) // all headshot weapons go here
- {
- s = "notify_headshot";
- }
- else if(WEP_VALID(w))
- {
- self = get_weaponinfo(w);
- s = strcat("weapon", self.netname);
- }
- else if(type == KILL_TEAM_RED)
- {
- s = "notify_teamkill_red";
- }
- else if(type == KILL_TEAM_BLUE)
- {
- s = "notify_teamkill_red";
- }
- else if(type == DEATH_TELEFRAG)
- {
- s = "notify_telefrag";
- }
- else if(type == DEATH_DROWN)
- {
- s = "notify_water";
- }
- else if(type == DEATH_SLIME)
- {
- s = "notify_slime";
- }
- else if(type == DEATH_LAVA)
- {
- s = "notify_lava";
- }
- else if(type == DEATH_FALL)
+ if((attacker != "") && (victim == ""))
{
- s = "notify_fall";
- }
- else if(type == DEATH_SHOOTING_STAR)
- {
- s = "notify_shootingstar";
- }
- else if(type == DEATH_HURTTRIGGER || type == DEATH_CUSTOM) // DEATH_CUSTOM is also void, right?
- {
- s = "notify_void";
- }
- else if(type == RACE_SERVER_RECORD)
- {
- s = "race_newrecordserver";
- }
- else if(type == RACE_NEW_RANK)
- {
- s = "race_newrankyellow";
- }
- else if(type == RACE_NEW_TIME)
- {
- s = "race_newtime";
+ // 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;
+
+ 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(type == RACE_FAIL)
+ else if((attacker != "") && (victim != ""))
{
- s = "race_newfail";
- }
-
- attacker = textShortenToWidth(killnotify_attackers[j], 0.48 * mySize_x - height, fontsize, stringwidth_colors);
- victim = textShortenToWidth(killnotify_victims[j], 0.48 * mySize_x - height, fontsize, stringwidth_colors);
+ // 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)));
- weap_pos = pos + eX * 0.5 * mySize_x - eX * height + eY * i * height;
+ 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;
- if(s != "")
- {
- drawpic_aspect_skin(weap_pos, s, '2 1 0' * height, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
+ 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);
}
HUD_Panel_UpdateCvars(radar);
HUD_Panel_ApplyFadeAlpha();
+
+ float f = 0;
if (hud_panel_radar_maximized && !autocvar__hud_configure)
{
panel_bg = strcat(hud_skin_path, "/border_default"); // always use the default border when maximized
if(precache_pic(panel_bg) == "") { panel_bg = "gfx/hud/default/border_default"; } // fallback
+
+ switch(hud_panel_radar_maximized_zoommode)
+ {
+ default:
+ case 0:
+ f = current_zoomfraction;
+ break;
+ case 1:
+ f = 1 - current_zoomfraction;
+ break;
+ case 2:
+ f = 0;
+ break;
+ case 3:
+ f = 1;
+ break;
+ }
+
+ switch(hud_panel_radar_maximized_rotation)
+ {
+ case 0:
+ teamradar_angle = view_angles_y - 90;
+ break;
+ default:
+ teamradar_angle = 90 * hud_panel_radar_maximized_rotation;
+ break;
+ }
+ }
+ if (!hud_panel_radar_maximized && !autocvar__hud_configure)
+ {
+ switch(hud_panel_radar_zoommode)
+ {
+ default:
+ case 0:
+ f = current_zoomfraction;
+ break;
+ case 1:
+ f = 1 - current_zoomfraction;
+ break;
+ case 2:
+ f = 0;
+ break;
+ case 3:
+ f = 1;
+ break;
+ }
+
+ switch(hud_panel_radar_rotation)
+ {
+ case 0:
+ teamradar_angle = view_angles_y - 90;
+ break;
+ default:
+ teamradar_angle = 90 * hud_panel_radar_rotation;
+ break;
+ }
}
vector pos, mySize;
float color2;
entity tm;
float scale2d, normalsize, bigsize;
- float f;
teamradar_origin2d = pos + 0.5 * mySize;
teamradar_size2d = mySize;
teamradar_loadcvars();
- switch(hud_panel_radar_zoommode)
- {
- default:
- case 0:
- f = current_zoomfraction;
- break;
- case 1:
- f = 1 - current_zoomfraction;
- break;
- case 2:
- f = 0;
- break;
- case 3:
- f = 1;
- break;
- }
-
- switch(hud_panel_radar_rotation)
- {
- case 0:
- teamradar_angle = view_angles_y - 90;
- break;
- default:
- teamradar_angle = 90 * hud_panel_radar_rotation;
- break;
- }
-
scale2d = vlen_maxnorm2d(mi_picmax - mi_picmin);
teamradar_size2d = mySize;
teamradar_extraclip_mins = teamradar_extraclip_maxs = '0 0 0'; // we always center
// pixels per world qu to match the teamradar_size2d_x range in the longest dimension
- if(hud_panel_radar_rotation == 0)
+ if((hud_panel_radar_rotation == 0 && !hud_panel_radar_maximized) || (hud_panel_radar_maximized_rotation == 0 && hud_panel_radar_maximized))
{
// max-min distance must fit the radar in any rotation
bigsize = vlen_minnorm2d(teamradar_size2d) * scale2d / (1.05 * vlen2d(mi_scale));
for(tm = world; (tm = find(tm, classname, "entcs_receiver")); )
{
color2 = GetPlayerColor(tm.sv_entnum);
- //if(color == COLOR_SPECTATOR || color == color2)
- draw_teamradar_player(tm.origin, tm.angles, GetTeamRGB(color2));
+ //if(color == NUM_SPECTATOR || color == color2)
+ draw_teamradar_player(tm.origin, tm.angles, Team_ColorRGB(color2));
}
draw_teamradar_player(view_origin, view_angles, '1 1 1');
drawresetcliparea();
-};
+}
// Score (#7)
//
void HUD_Score_Rankings(vector pos, vector mySize, entity me, float team_count)
{
float score;
- entity tm, pl;
+ entity tm = world, pl;
#define SCOREPANEL_MAX_ENTRIES 6
#define SCOREPANEL_ASPECTRATIO 2
float entries = bound(1, floor(SCOREPANEL_MAX_ENTRIES * mySize_y/mySize_x * SCOREPANEL_ASPECTRATIO), SCOREPANEL_MAX_ENTRIES);
float name_size = mySize_x*0.75;
float spacing_size = mySize_x*0.04;
const float highlight_alpha = 0.2;
- float i, me_printed, first_pl;
+ float i = 0, me_printed = 0, first_pl = 0;
string s;
- i = 0;
- first_pl = 0;
if (autocvar__hud_configure)
{
- float players_per_team;
+ float players_per_team = 0;
if (team_count)
{
// show team scores in the first line
for(i=0; i<team_count; ++i) {
if (i == floor((entries - 2) / players_per_team) || (entries == 1 && i == 0))
HUD_Panel_DrawHighlight(pos + eX * score_size * i, eX * score_size + eY * fontsize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
- drawstring_aspect(pos + eX * score_size * i, ftos(175 - 23*i), eX * score_size + eY * fontsize_y, GetTeamRGB(ColorByTeam(i)) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawstring_aspect(pos + eX * score_size * i, ftos(175 - 23*i), eX * score_size + eY * fontsize_y, Team_ColorRGB(ColorByTeam(i)) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
}
first_pl = 1;
pos_y += fontsize_y;
{
rgb = '1 1 0';
drawfill(pos, eX * mySize_x + eY * fontsize_y, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
- s = GetPlayerName(pl.sv_entnum);
+ s = GetPlayerName(player_localnum);
score = 7;
}
else
}
if (team_count)
- score_color = GetTeamRGB(ColorByTeam(floor((i - first_pl) / players_per_team))) * 0.8;
+ score_color = Team_ColorRGB(ColorByTeam(floor((i - first_pl) / players_per_team))) * 0.8;
s = textShortenToWidth(s, name_size, fontsize, stringwidth_colors);
drawcolorcodedstring(pos + eX * (name_size - stringwidth(s, TRUE, fontsize)), s, fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
drawstring(pos + eX * (name_size + spacing_size), ftos(score), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL);
// show team scores in the first line
float score_size = mySize_x / team_count;
for(tm = teams.sort_next; tm; tm = tm.sort_next) {
- if(tm.team == COLOR_SPECTATOR)
+ if(tm.team == NUM_SPECTATOR)
continue;
if (tm.team == myteam)
drawfill(pos + eX * score_size * i, eX * score_size + eY * fontsize_y, '1 1 1', highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
- drawstring_aspect(pos + eX * score_size * i, ftos(tm.(teamscores[ts_primary])), eX * score_size + eY * fontsize_y, GetTeamRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawstring_aspect(pos + eX * score_size * i, ftos(tm.(teamscores[ts_primary])), eX * score_size + eY * fontsize_y, Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
++i;
}
first_pl = 1;
do
for (pl = players.sort_next; pl && i<entries; pl = pl.sort_next)
{
- if ((team_count && pl.team != tm.team) || pl.team == COLOR_SPECTATOR)
+ if ((team_count && pl.team != tm.team) || pl.team == NUM_SPECTATOR)
continue;
if (i == entries-1 && !me_printed && pl != me)
if (autocvar_hud_panel_score_rankings == 1 && spectatee_status != -1)
{
for (pl = me.sort_next; pl; pl = pl.sort_next)
- if (pl.team != COLOR_SPECTATOR)
+ if (pl.team != NUM_SPECTATOR)
break;
if (pl)
drawfill(pos, eX * mySize_x + eY * fontsize_y, rgb, highlight_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
}
if (team_count)
- score_color = GetTeamRGB(pl.team) * 0.8;
+ score_color = Team_ColorRGB(pl.team) * 0.8;
s = textShortenToWidth(GetPlayerName(pl.sv_entnum), name_size, fontsize, stringwidth_colors);
drawcolorcodedstring(pos + eX * (name_size - stringwidth(s, TRUE, fontsize)), s, fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
drawstring(pos + eX * (name_size + spacing_size), ftos(pl.(scores[ps_primary])), fontsize, score_color, panel_fg_alpha, DRAWFLAG_NORMAL);
pos_y += fontsize_y;
++i;
}
- while (i<entries && team_count && (tm = tm.sort_next) && (tm.team != COLOR_SPECTATOR || (tm = tm.sort_next)));
+ while (i<entries && team_count && (tm = tm.sort_next) && (tm.team != NUM_SPECTATOR || (tm = tm.sort_next)));
}
void HUD_Score(void)
mySize -= '2 2 0' * panel_bg_padding;
}
- float score, distribution;
+ float score, distribution = 0;
string sign;
vector distribution_color;
entity tm, pl, me;
drawstring_aspect(pos + eX * 0.75 * mySize_x, distribution_str, eX * 0.25 * mySize_x + eY * (1/3) * mySize_y, distribution_color, panel_fg_alpha, DRAWFLAG_NORMAL);
draw_endBoldFont();
} else { // teamgames
- float scores_count, row, column, rows, columns;
- local noref vector offset; // fteqcc sucks
+ float scores_count = 0, row, column, rows = 0, columns = 0;
+ local noref vector offset = '0 0 0';
vector score_pos, score_size; //for scores other than myteam
if (spectatee_status == -1 || autocvar_hud_panel_score_rankings)
{
- for(tm = teams.sort_next; tm, tm.team != COLOR_SPECTATOR; tm = tm.sort_next)
+ for(tm = teams.sort_next; tm, tm.team != NUM_SPECTATOR; tm = tm.sort_next)
++scores_count;
if (autocvar_hud_panel_score_rankings)
{
float max_fragcount;
max_fragcount = -99;
draw_beginBoldFont();
+ row = column = 0;
for(tm = teams.sort_next; tm; tm = tm.sort_next) {
- if(tm.team == COLOR_SPECTATOR)
+ if(tm.team == NUM_SPECTATOR)
continue;
score = tm.(teamscores[ts_primary]);
if(autocvar__hud_configure)
score_pos = pos + eX * column * (score_size_x + offset_x) + eY * row * (score_size_y + offset_y);
if (max_fragcount == score)
HUD_Panel_DrawHighlight(score_pos, score_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
- drawstring_aspect(score_pos, ftos(score), score_size, GetTeamRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawstring_aspect(score_pos, ftos(score), score_size, Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
++row;
if(row >= rows)
{
else if(tm.team == myteam) {
if (max_fragcount == score)
HUD_Panel_DrawHighlight(pos, eX * 0.75 * mySize_x + eY * mySize_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
- drawstring_aspect(pos, ftos(score), eX * 0.75 * mySize_x + eY * mySize_y, GetTeamRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawstring_aspect(pos, ftos(score), eX * 0.75 * mySize_x + eY * mySize_y, Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
} else {
if (max_fragcount == score)
HUD_Panel_DrawHighlight(pos + eX * 0.75 * mySize_x + eY * (1/3) * rows * mySize_y, score_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
- drawstring_aspect(pos + eX * 0.75 * mySize_x + eY * (1/3) * rows * mySize_y, ftos(score), score_size, GetTeamRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawstring_aspect(pos + eX * 0.75 * mySize_x + eY * (1/3) * rows * mySize_y, ftos(score), score_size, Team_ColorRGB(tm.team) * 0.8, panel_fg_alpha, DRAWFLAG_NORMAL);
++rows;
}
}
}
// always force 4:1 aspect
- vector newSize;
+ vector newSize = '0 0 0';
if(mySize_x/mySize_y > 4)
{
newSize_x = 4 * mySize_y;
if(race_mycheckpointtime)
{
a = bound(0, 2 - (time - race_mycheckpointtime), 1);
- s = MakeRaceString(race_mycheckpoint, TIME_DECODE(race_mycheckpointdelta), -!race_mycheckpointenemy, race_mycheckpointlapsdelta, race_mycheckpointenemy);
+ s = MakeRaceString(race_mycheckpoint, TIME_DECODE(race_mycheckpointdelta), -(race_mycheckpointenemy == ""), race_mycheckpointlapsdelta, race_mycheckpointenemy);
drawcolorcodedstring(pos + eX * 0.5 * mySize_x - '0.5 0 0' * stringwidth(s, TRUE, '1 1 0' * 0.2 * mySize_y) + eY * 0.6 * mySize_y, s, '1 1 0' * 0.2 * mySize_y, panel_fg_alpha * a, DRAWFLAG_NORMAL);
}
if(race_othercheckpointtime && race_othercheckpointenemy != "")
{
a = bound(0, 2 - (time - race_othercheckpointtime), 1);
- s = MakeRaceString(race_othercheckpoint, -TIME_DECODE(race_othercheckpointdelta), -!race_othercheckpointenemy, race_othercheckpointlapsdelta, race_othercheckpointenemy);
+ s = MakeRaceString(race_othercheckpoint, -TIME_DECODE(race_othercheckpointdelta), -(race_othercheckpointenemy == ""), race_othercheckpointlapsdelta, race_othercheckpointenemy);
drawcolorcodedstring(pos + eX * 0.5 * mySize_x - '0.5 0 0' * stringwidth(s, TRUE, '1 1 0' * 0.2 * mySize_y) + eY * 0.6 * mySize_y, s, '1 1 0' * 0.2 * mySize_y, panel_fg_alpha * a, DRAWFLAG_NORMAL);
}
}
// always force 3:1 aspect
- vector newSize;
+ vector newSize = '0 0 0';
if(mySize_x/mySize_y > 3)
{
newSize_x = 3 * mySize_y;
case 2: red_icon = "flag_red_lost"; break;
case 3: red_icon = "flag_red_carrying"; red_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break;
default:
- if((stat_items & IT_CTF_SHIELDED) && (myteam == COLOR_TEAM2))
+ if((stat_items & IT_CTF_SHIELDED) && (myteam == NUM_TEAM_2))
red_icon = "flag_red_shielded";
else
red_icon = string_null;
default:
if(redflag == 3)
red_icon_prevstatus = "flag_red_carrying"; // make it more visible
- else if((stat_items & IT_CTF_SHIELDED) && (myteam == COLOR_TEAM2))
+ else if((stat_items & IT_CTF_SHIELDED) && (myteam == NUM_TEAM_2))
red_icon_prevstatus = "flag_red_shielded";
else
red_icon_prevstatus = string_null;
case 2: blue_icon = "flag_blue_lost"; break;
case 3: blue_icon = "flag_blue_carrying"; blue_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break;
default:
- if((stat_items & IT_CTF_SHIELDED) && (myteam == COLOR_TEAM1))
+ if((stat_items & IT_CTF_SHIELDED) && (myteam == NUM_TEAM_1))
blue_icon = "flag_blue_shielded";
else
blue_icon = string_null;
default:
if(blueflag == 3)
blue_icon_prevstatus = "flag_blue_carrying"; // make it more visible
- else if((stat_items & IT_CTF_SHIELDED) && (myteam == COLOR_TEAM1))
+ else if((stat_items & IT_CTF_SHIELDED) && (myteam == NUM_TEAM_1))
blue_icon_prevstatus = "flag_blue_shielded";
else
blue_icon_prevstatus = string_null;
}
if(mySize_x > mySize_y) {
- if (myteam == COLOR_TEAM1) { // always draw own flag on left
+ if (myteam == NUM_TEAM_1) { // always draw own flag on left
redflag_pos = pos;
blueflag_pos = pos + eX * 0.5 * mySize_x;
} else {
}
flag_size = eX * 0.5 * mySize_x + eY * mySize_y;
} else {
- if (myteam == COLOR_TEAM1) { // always draw own flag on left
+ if (myteam == NUM_TEAM_1) { // always draw own flag on left
redflag_pos = pos;
blueflag_pos = pos + eY * 0.5 * mySize_y;
} else {
float kh_keys;
float keyteam;
float a, aa;
- vector p, pa, kh_size, kh_asize;
+ vector p = '0 0 0', pa, kh_size = '0 0 0', kh_asize = '0 0 0';
kh_keys = getstati(STAT_KH_KEYS);
{
switch(keyteam)
{
- case COLOR_TEAM1:
+ case NUM_TEAM_1:
drawpic_aspect_skin(pa, "kh_redarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL); // show 30% theAlpha key
break;
- case COLOR_TEAM2:
+ case NUM_TEAM_2:
drawpic_aspect_skin(pa, "kh_bluearrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL); // show 30% theAlpha key
break;
- case COLOR_TEAM3:
+ case NUM_TEAM_3:
drawpic_aspect_skin(pa, "kh_yellowarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL); // show 30% theAlpha key
break;
- case COLOR_TEAM4:
+ case NUM_TEAM_4:
drawpic_aspect_skin(pa, "kh_pinkarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL); // show 30% theAlpha key
break;
default:
float rank;
if(race_status > 0)
rank = race_CheckName(race_status_name);
+ else
+ rank = 0;
string rankname;
- rankname = race_PlaceName(rank);
+ rankname = count_ordinal(rank);
vector namepos;
namepos = medalPos + '0 0.8 0' * squareSize;
float stat, pps_ratio;
string pic;
vector color;
+#ifdef GMQCC
+ stat = -1;
+ pic = "";
+ color = '0 0 0';
+#endif
switch(i)
{
case 0:
pic = "dom_icon_yellow";
color = '1 1 0';
break;
+ default:
case 3:
stat = getstatf(STAT_DOM_PPS_PINK);
pic = "dom_icon_pink";
color = '1 0 1';
+ break;
}
pps_ratio = stat / getstatf(STAT_DOM_TOTAL_PPS);
{
mod_active = 1; // required in each mod function that always shows something
entity tm;
- float teams_count;
+ float teams_count = 0;
for(tm = teams.sort_next; tm; tm = tm.sort_next)
- if(tm.team != COLOR_SPECTATOR)
+ if(tm.team != NUM_SPECTATOR)
++teams_count;
float layout = autocvar_hud_panel_modicons_dom_layout;
columns = ceil(teams_count/rows);
int i;
- float row, column;
+ float row = 0, column = 0;
for(i=0; i<teams_count; ++i)
{
vector pos, itemSize;
float aspect = autocvar_hud_panel_pressedkeys_aspect;
if(aspect)
{
- vector newSize;
+ vector newSize = '0 0 0';
if(mySize_x/mySize_y > aspect)
{
newSize_x = aspect * mySize_y;
}
// always force 5:1 aspect
- vector newSize;
+ vector newSize = '0 0 0';
if(mySize_x/mySize_y > 5)
{
newSize_x = 5 * mySize_y;
if(teamplay && !intermission && !spectatee_status && gametype != MAPINFO_TYPE_CA && teamnagger)
{
- float ts_min, ts_max;
+ float ts_min = 0, ts_max = 0;
tm = teams.sort_next;
if (tm)
{
for(; tm.sort_next; tm = tm.sort_next)
{
- if(!tm.team_size || tm.team == COLOR_SPECTATOR)
+ if(!tm.team_size || tm.team == NUM_SPECTATOR)
continue;
if(!ts_min) ts_min = tm.team_size;
else ts_min = min(ts_min, tm.team_size);
s = strcat(blinkcolor, _("Teamnumbers are unbalanced!"));
tm = GetTeam(myteam, false);
if (tm)
- if (tm.team != COLOR_SPECTATOR)
+ if (tm.team != NUM_SPECTATOR)
if (tm.team_size == ts_max)
s = strcat(s, sprintf(_(" Press ^3%s%s to adjust"), getcommandkey("team menu", "menu_showteamselect"), blinkcolor));
drawInfoMessage(s)
panel_size -= '2 2 0' * panel_bg_padding;
}
- float acceleration_progressbar_scale;
+ float acceleration_progressbar_scale = 0;
if(autocvar_hud_panel_physics_progressbar && autocvar_hud_panel_physics_acceleration_progressbar_scale > 1)
acceleration_progressbar_scale = autocvar_hud_panel_physics_acceleration_progressbar_scale;
//compute layout
float panel_ar = panel_size_x/panel_size_y;
- vector speed_offset, acceleration_offset;
+ vector speed_offset = '0 0 0', acceleration_offset = '0 0 0';
if (panel_ar >= 5 && !acceleration_progressbar_scale)
{
panel_size_x *= 0.5;
HUD_Panel_GetProgressBarColor(speed);
HUD_Panel_DrawProgressBar(panel_pos + speed_offset, panel_size, "progressbar", speed/max_speed, 0, speed_baralign, progressbar_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
}
- vector tmp_offset, tmp_size;
+ vector tmp_offset = '0 0 0', tmp_size = '0 0 0';
if (autocvar_hud_panel_physics_text == 1 || autocvar_hud_panel_physics_text == 2)
{
tmp_size_x = panel_size_x * 0.75;
if(autocvar_hud_panel_physics_progressbar == 1 || autocvar_hud_panel_physics_progressbar == 2)
{
float peak_offset_x;
- vector peak_size;
+ vector peak_size = '0 0 0';
if (speed_baralign == 0)
peak_offset_x = min(top_speed, max_speed)/max_speed * panel_size_x;
else if (speed_baralign == 1)
peak_offset_x = (1 - min(top_speed, max_speed)/max_speed) * panel_size_x;
- else if (speed_baralign == 2)
+ else // if (speed_baralign == 2)
peak_offset_x = min(top_speed, max_speed)/max_speed * panel_size_x * 0.5;
//if speed is not 0 the speed progressbar already fetched the color
if (speed == 0)
void centerprint_generic(float new_id, string strMessage, float duration, float countdown_num)
{
+ //print(sprintf("centerprint_generic(%d, '%s^7', %d, %d);\n", new_id, strMessage, duration, countdown_num));
float i, j;
if(strMessage == "" && new_id == 0)
centerprint_messages[j] = strzone(strMessage);
centerprint_msgID[j] = new_id;
if (duration < 0)
+ {
centerprint_time[j] = -1;
+ centerprint_expire_time[j] = time;
+ }
else
{
if(duration == 0)
fontsize = '1 1 0' * height;
entries = bound(1, floor(panel_size_y/height), CENTERPRINT_MAX_ENTRIES);
- float i, j, k, n;
- float a, sz, align, current_msg_pos_y, msg_size;
+ float i, j, k, n, g;
+ float a, sz, align, current_msg_pos_y = 0, msg_size;
vector pos;
string ts;
if (autocvar_hud_panel_centerprint_flip)
pos_y += panel_size_y;
align = bound(0, autocvar_hud_panel_centerprint_align, 1);
- for (i=0, j=cpm_index; i<CENTERPRINT_MAX_MSGS; ++i, ++j)
+ for (g=0, i=0, j=cpm_index; i<CENTERPRINT_MAX_MSGS; ++i, ++j)
{
if (j == CENTERPRINT_MAX_MSGS)
j = 0;
continue;
centerprint_expire_time[j] = centerprint_expire_time[j] + centerprint_time[j];
}
- else
+ else if(centerprint_time[j] != -1)
continue;
}
-
+
+
// fade the centerprint_hud in/out
- if (centerprint_time[j] < 0 || centerprint_expire_time[j] - autocvar_hud_panel_centerprint_fade_out > time)
+ if(centerprint_time[j] < 0)
+ a = bound(0, (time - centerprint_expire_time[j]) / max(0.0001, autocvar_hud_panel_centerprint_fade_in), 1);
+ else if(centerprint_expire_time[j] - autocvar_hud_panel_centerprint_fade_out > time)
a = bound(0, (time - (centerprint_expire_time[j] - centerprint_time[j])) / max(0.0001, autocvar_hud_panel_centerprint_fade_in), 1);
- else if (centerprint_expire_time[j] > time)
+ else if(centerprint_expire_time[j] > time)
a = (centerprint_expire_time[j] - time) / max(0.0001, autocvar_hud_panel_centerprint_fade_out);
+ else
+ a = 0;
// set the size from fading in/out before subsequent fading
sz = autocvar_hud_panel_centerprint_fade_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_minfontsize);
// also fade it based on positioning
if(autocvar_hud_panel_centerprint_fade_subsequent)
{
- a = a * bound(autocvar_hud_panel_centerprint_fade_subsequent_passone_minalpha, (1 - (i / max(1, autocvar_hud_panel_centerprint_fade_subsequent_passone))), 1); // pass one: all messages after the first have half theAlpha
- a = a * bound(autocvar_hud_panel_centerprint_fade_subsequent_passtwo_minalpha, (1 - (i / max(1, autocvar_hud_panel_centerprint_fade_subsequent_passtwo))), 1); // pass two: after that, gradually lower theAlpha even more for each message
+ a = a * bound(autocvar_hud_panel_centerprint_fade_subsequent_passone_minalpha, (1 - (g / max(1, autocvar_hud_panel_centerprint_fade_subsequent_passone))), 1); // pass one: all messages after the first have half theAlpha
+ a = a * bound(autocvar_hud_panel_centerprint_fade_subsequent_passtwo_minalpha, (1 - (g / max(1, autocvar_hud_panel_centerprint_fade_subsequent_passtwo))), 1); // pass two: after that, gradually lower theAlpha even more for each message
}
// finally set the size based on the new theAlpha from subsequent fading
drawfontscale = sz * '1 1 0';
if (centerprint_countdown_num[j])
- n = tokenizebyseparator(sprintf(centerprint_messages[j], centerprint_countdown_num[j]), "\n");
+ n = tokenizebyseparator(strreplace("^COUNT", count_seconds(centerprint_countdown_num[j]), centerprint_messages[j]), "\n");
else
n = tokenizebyseparator(centerprint_messages[j], "\n");
pos_y += fontsize_y * CENTERPRINT_SPACING/2;
}
}
+
+ ++g; // move next position number up
+
msg_size = pos_y - msg_size;
if (autocvar_hud_panel_centerprint_flip)
{
return;
// Drawing stuff
- if (hud_skin_path != autocvar_hud_skin)
+ if (hud_skin_prev != autocvar_hud_skin)
{
if (hud_skin_path)
strunzone(hud_skin_path);
hud_skin_path = strzone(strcat("gfx/hud/", autocvar_hud_skin));
+ if (hud_skin_prev)
+ strunzone(hud_skin_prev);
+ hud_skin_prev = strzone(autocvar_hud_skin);
}
// HUD configure visible grid
if(autocvar__hud_panelorder != hud_panelorder_prev) {
for(i = 0; i < HUD_PANEL_NUM; ++i)
panel_order[i] = -1;
- string s;
- float p_num, warning;
+ string s = "";
+ float p_num, warning = false;
float argc = tokenize_console(autocvar__hud_panelorder);
if (argc > HUD_PANEL_NUM)
warning = true;
HUD_Panel_UpdatePosSizeForId(highlightedPanel);
HUD_Panel_HlBorder(panel_bg_border + 1.5 * hlBorderSize, '0 0.5 1', 0.25 * (1 - autocvar__menu_alpha));
}
- if (!hud_configure_prev)
+ if(!hud_configure_prev || hud_configure_prev == -1)
+ {
+ if(autocvar_hud_cursormode) { setcursormode(1); }
hudShiftState = 0;
+ }
}
+ else if (hud_configure_prev && autocvar_hud_cursormode)
+ setcursormode(0);
hud_configure_prev = autocvar__hud_configure;
float scoreboard_bottom;
float weapon_accuracy[WEP_MAXCOUNT];
-#define MAX_ACCURACY_LEVELS 10
-float acc_lev[MAX_ACCURACY_LEVELS];
-vector acc_col[MAX_ACCURACY_LEVELS];
-float acc_levels;
-string acc_color_levels;
-
float complain_weapon;
string complain_weapon_name;
float complain_weapon_type;
float hud_fade_alpha;
string hud_skin_path;
+string hud_skin_prev;
var vector progressbar_color;
case HUD_PANEL_ENGINEINFO: HUD_Panel_UpdatePosSize(engineinfo) break;\
default: HUD_Panel_UpdatePosSizeForId_Part2(id)\
}
+
+#define KN_MAX_ENTRIES 10
+
+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);
HUD_Write_PanelCvar_q("_aspect");
HUD_Write_PanelCvar_q("_timeout");
HUD_Write_PanelCvar_q("_timeout_effect");
+ HUD_Write_PanelCvar_q("_timeout_fadebgmin");
+ HUD_Write_PanelCvar_q("_timeout_fadefgmin");
+ HUD_Write_PanelCvar_q("_timeout_speed_in");
+ HUD_Write_PanelCvar_q("_timeout_speed_out");
HUD_Write_PanelCvar_q("_onlyowned");
break;
case HUD_PANEL_AMMO:
case HUD_PANEL_NOTIFY:
HUD_Write_PanelCvar_q("_flip");
HUD_Write_PanelCvar_q("_fontsize");
- HUD_Write_PanelCvar_q("_print");
HUD_Write_PanelCvar_q("_time");
HUD_Write_PanelCvar_q("_fadetime");
break;
HUD_Write_PanelCvar_q("_scale");
HUD_Write_PanelCvar_q("_maximized_scale");
HUD_Write_PanelCvar_q("_maximized_size");
+ HUD_Write_PanelCvar_q("_maximized_rotation");
+ HUD_Write_PanelCvar_q("_maximized_zoommode");
break;
case HUD_PANEL_SCORE:
HUD_Write_PanelCvar_q("_rankings");
HUD_Write_PanelCvar_q("_dom_layout");
break;
case HUD_PANEL_PRESSEDKEYS:
- HUD_Write_PanelCvar_q("_attack");
HUD_Write_PanelCvar_q("_aspect");
+ HUD_Write_PanelCvar_q("_attack");
break;
case HUD_PANEL_ENGINEINFO:
HUD_Write_PanelCvar_q("_framecounter_time");
{
string s;
- // we only care for keyboard events
- if(bInputType != 0 && bInputType != 1)
+ if(bInputType == 2)
return false;
if(!autocvar__hud_configure)
if(autocvar__menu_alpha)
return true;
+ if(bInputType == 3)
+ {
+ mousepos_x = nPrimary;
+ mousepos_y = nSecondary;
+ return true;
+ }
+
// allow console bind to work
string con_keys;
float keys;
con_keys = findkeysforcommand("toggleconsole", 0);
keys = tokenize(con_keys); // findkeysforcommand returns data for this
- float hit_con_bind, i;
+ float hit_con_bind = 0, i;
for (i = 0; i < keys; ++i)
{
if(nPrimary == stof(argv(i)))
}
tab_backward = (hudShiftState & S_SHIFT);
- float k, level, start_pos_x;
- vector candidate_pos;
+ float k, level = 0, start_pos_x;
+ vector candidate_pos = '0 0 0';
const float LEVELS_NUM = 4;
float level_height = vid_conheight / LEVELS_NUM;
:find_tab_panel
float HUD_Panel_Check_Mouse_Pos(float allow_move)
{
- float i, j, border;
+ float i, j = 0, border;
while(j < HUD_PANEL_NUM)
{
border = max(8, panel_bg_border); // FORCED border so a small border size doesn't mean you can't resize
// move
- if(allow_move && mousepos_x >= panel_pos_x && mousepos_y >= panel_pos_y && mousepos_x <= panel_pos_x + panel_size_x && mousepos_y <= panel_pos_y + panel_size_y)
+ if(allow_move && mousepos_x > panel_pos_x && mousepos_y > panel_pos_y && mousepos_x < panel_pos_x + panel_size_x && mousepos_y < panel_pos_y + panel_size_y)
{
return 1;
}
panel_order[0] = id;
// let's save them into the cvar by some strcat trickery
- string s;
+ string s = "";
for(i = 0; i < HUD_PANEL_NUM; ++i)
{
s = strcat(s, ftos(panel_order[i]), " ");
void HUD_Panel_Highlight(float allow_move)
{
- float i, j, border;
+ float i, j = 0, border;
while(j < HUD_PANEL_NUM)
{
border = max(8, panel_bg_border); // FORCED border so a small border size doesn't mean you can't resize
// move
- if(allow_move && mousepos_x >= panel_pos_x && mousepos_y >= panel_pos_y && mousepos_x <= panel_pos_x + panel_size_x && mousepos_y <= panel_pos_y + panel_size_y)
+ if(allow_move && mousepos_x > panel_pos_x && mousepos_y > panel_pos_y && mousepos_x < panel_pos_x + panel_size_x && mousepos_y < panel_pos_y + panel_size_y)
{
highlightedPanel = i;
HUD_Panel_FirstInDrawQ(i);
if(autocvar__menu_alpha == 1)
return;
- mousepos = mousepos + getmousepos() * autocvar_menu_mouse_speed;
-
- mousepos_x = bound(0, mousepos_x, vid_conwidth);
- mousepos_y = bound(0, mousepos_y, vid_conheight);
+ if not(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);
+ }
if(mouseClicked)
{
HUD_Panel_SetPos(mousepos - panel_click_distance);
else if(highlightedAction == 2)
{
- vector mySize;
+ vector mySize = '0 0 0';
if(resizeCorner == 1) {
mySize_x = panel_click_resizeorigin_x - (mousepos_x - panel_click_distance_x);
mySize_y = panel_click_resizeorigin_y - (mousepos_y - panel_click_distance_y);
self.count = (f & 0xF0);
if(self.count & 0x80)
- self.iflags = IFLAG_VELOCITY;
+ self.iflags = IFLAG_VELOCITY | IFLAG_ORIGIN;
else
- self.iflags = IFLAG_ANGLES;
+ self.iflags = IFLAG_ANGLES | IFLAG_ORIGIN;
if(f & 1)
{
self.origin_x = ReadCoord();
self.origin_y = ReadCoord();
self.origin_z = ReadCoord();
+ setorigin(self, self.origin);
}
if(f & 8)
{
-const string string_null;
-
// --------------------------------------------------------------------------
// MENU Functionality
//.float ctf_state;
//.float health;
-// Constants
-const float COLOR_TEAM_RED = 64;
-const float COLOR_TEAM_BLUE = 208;
-
-const float COLOR_TEAM1 = 4; // red
-const float COLOR_TEAM2 = 13; // blue
-const float COLOR_TEAM3 = 12; // yellow
-const float COLOR_TEAM4 = 9; // pink
-const float COLOR_SPECTATOR = 1337;
-
#define FONT_DEFAULT 0
#define FONT_USER 8
post = _(" (1 vote)");
else if(count >= 0)
post = sprintf(_(" (%d votes)"), count);
+ else
+ post = "";
}
else
post = "";
void MapVote_DrawMapItem(vector pos, float isize, float tsize, string map, string pic, float count, float id)
{
- vector img_size;
+ vector img_size = '0 0 0';
vector rgb;
string label;
float text_size;
float center;
float columns, rows;
float tsize;
- vector dist;
+ vector dist = '0 0 0';
if(!mv_active)
return;
- mv_mousepos = mv_mousepos + getmousepos();
-
- mv_mousepos_x = bound(0, mv_mousepos_x, vid_conwidth);
- mv_mousepos_y = bound(0, mv_mousepos_y, vid_conheight);
+ if not(autocvar_hud_cursormode)
+ {
+ mv_mousepos = mv_mousepos + getmousepos();
+
+ 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;
xmin = vid_conwidth*0.05; // 5% border must suffice
MapVote_DrawAbstain(pos, isize, xmax - xmin, tmp, i);
}
- drawpic(mv_mousepos, strcat("gfx/menu/", autocvar_menu_skin, "/cursor.tga"), '32 32 0', '1 1 1', autocvar_hud_panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawpic(mv_mousepos, strcat("gfx/menu/", autocvar_menu_skin, "/cursor.tga"), '32 32 0', '1 1 1', 1 - autocvar__menu_alpha, DRAWFLAG_NORMAL);
}
void Cmd_MapVote_MapDownload(float argc)
precache_sound ("misc/invshot.wav");
mv_active = 1;
-
- mv_mousepos = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
+ if(autocvar_hud_cursormode) { setcursormode(1); }
+ else { mv_mousepos = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight; }
mv_selection = -1;
for(n_ssdirs = 0; ; ++n_ssdirs)
if (!mv_active)
return false;
+ if(bInputType == 3)
+ {
+ mv_mousepos_x = nPrimary;
+ mv_mousepos_y = nSecondary;
+ return true;
+ }
+
if (bInputType != 0)
return false;
-var float(string text, float handleColors, vector fontSize) stringwidth;
-
entity players;
entity teams;
{
float num;
entity tm;
- num = (Team == COLOR_SPECTATOR) ? 16 : Team;
+ num = (Team == NUM_SPECTATOR) ? 16 : Team;
if(teamslots[num])
return teamslots[num];
if not(add)
vector rotate(vector v, float a)
{
- vector w;
+ vector w = '0 0 0';
// FTEQCC SUCKS AGAIN
w_x = v_x * cos(a) + v_y * sin(a);
w_y = -1 * v_x * sin(a) + v_y * cos(a);
return s;
}
-string Team_ColorCode(float teamid)
-{
- if (teamid == COLOR_TEAM1)
- return "^1";
- else if (teamid == COLOR_TEAM2)
- return "^4";
- else if (teamid == COLOR_TEAM3)
- return "^3";
- else if (teamid == COLOR_TEAM4)
- return "^6";
- else
- return "^7";
-}
-
// decolorizes and team colors the player name when needed
string playername(string thename, float teamid)
{
void drawborderlines(float thickness, vector pos, vector dim, vector color, float theAlpha, float drawflag)
{
- vector line_dim;
+ vector line_dim = '0 0 0';
// left and right lines
pos_x -= thickness;
void drawpic_tiled(vector pos, string pic, vector sz, vector area, vector color, float theAlpha, float drawflag)
{
- vector current_pos, end_pos, new_size, ratio;
+ vector current_pos = '0 0 0', end_pos, new_size = '0 0 0', ratio = '0 0 0';
end_pos = pos + area;
current_pos_y = pos_y;
const vector GETPLAYERORIGIN_ERROR = '1123581321 2357111317 3141592653'; // way out of bounds for anything on the map
vector getplayerorigin(float pl)
{
- string s;
entity e;
e = CSQCModel_server2csqc(pl + 1);
if(e)
return e.origin;
-#ifndef NO_LEGACY_NETWORKING
- s = getplayerkeyvalue(pl, "TEMPHACK_origin");
- if(s != "")
- return stov(s);
-#endif
-
e = entcs_receiver[pl];
if(e)
return e.origin;
{
drawfont = FONT_USER+1;
}
+
+
+#define MAX_ACCURACY_LEVELS 10
+float acc_lev[MAX_ACCURACY_LEVELS];
+vector acc_col[MAX_ACCURACY_LEVELS];
+float acc_col_loadtime;
+float acc_levels;
+string acc_color_levels;
+void Accuracy_LoadLevels()
+{
+ float i;
+ if(autocvar_accuracy_color_levels != acc_color_levels)
+ {
+ if(acc_color_levels)
+ strunzone(acc_color_levels);
+ acc_color_levels = strzone(autocvar_accuracy_color_levels);
+ acc_levels = tokenize_console(acc_color_levels);
+ if(acc_levels > MAX_ACCURACY_LEVELS)
+ acc_levels = MAX_ACCURACY_LEVELS;
+ if(acc_levels < 2)
+ print("Warning: accuracy_color_levels must contain at least 2 values\n");
+
+ for(i = 0; i < acc_levels; ++i)
+ acc_lev[i] = stof(argv(i)) / 100.0;
+ }
+}
+
+void Accuracy_LoadColors()
+{
+ float i;
+ if(time > acc_col_loadtime)
+ if(acc_levels >= 2)
+ {
+ for(i = 0; i < acc_levels; ++i)
+ acc_col[i] = stov(cvar_string(strcat("accuracy_color", ftos(i))));
+ acc_col_loadtime = time + 2;
+ }
+}
+
+vector Accuracy_GetColor(float accuracy)
+{
+ float j, factor;
+ vector color;
+ if(acc_levels < 2)
+ return '0 0 0'; // return black, can't determine the right color
+
+ // find the max level lower than acc
+ j = acc_levels-1;
+ while(j && accuracy < acc_lev[j])
+ --j;
+
+ // inject color j+1 in color j, how much depending on how much accuracy is higher than level j
+ factor = (accuracy - acc_lev[j]) / (acc_lev[j+1] - acc_lev[j]);
+ color = acc_col[j];
+ color = color + factor * (acc_col[j+1] - color);
+ return color;
+}
+
void ModelEffect_Draw()
{
self.angles = self.angles + frametime * self.avelocity;
- self.origin = self.origin + frametime * self.velocity;
+ setorigin(self, self.origin + frametime * self.velocity);
self.scale = self.scale1 + (self.scale2 - self.scale1) * (time - self.teleport_time) / (self.lifetime + self.fadetime - self.teleport_time);
self.alpha = self.cnt * bound(0, 1 - (time - self.lifetime) / self.fadetime, 1);
if(self.alpha < ALPHA_MIN_VISIBLE)
e.origin_x = ReadCoord();
e.origin_y = ReadCoord();
e.origin_z = ReadCoord();
+ setorigin(e, e.origin);
if(f & 1)
{
e.velocity_x = ReadCoord();
}
if(self.noise != "")
{
- self.origin = p;
+ setorigin(self, p);
sound(self, CH_AMBIENT, self.noise, VOL_BASE * self.volume, self.atten);
}
self.just_toggled = 0;
--i;
}
}
- self.origin = o;
+ setorigin(self, o);
}
void Ent_PointParticles_Remove()
--- /dev/null
+.float skeleton_info_modelindex;
+.float skeleton_info_skin;
+#define BONETYPE_LOWER 0
+#define BONETYPE_UPPER 1
+#define MAX_BONES 128
+.float skeleton_bonetype[MAX_BONES];
+.float skeleton_numbones;
+
+void skeleton_loadinfo(entity e)
+{
+ float i;
+ if(e.skeleton_info_modelindex == e.modelindex && e.skeleton_info_skin == e.skin)
+ return;
+ e.bone_upperbody = 0;
+ e.bone_weapon = gettagindex(e, "weapon");
+ if(!e.bone_weapon)
+ e.bone_weapon = gettagindex(e, "tag_weapon");
+ if(!e.bone_weapon)
+ e.bone_weapon = gettagindex(e, "bip01 r hand");
+ for(i = 0; i < MAX_AIM_BONES; ++i)
+ {
+ e.(bone_aim[i]) = 0;
+ e.(bone_aimweight[i]) = 0;
+ }
+ e.fixbone = 0;
+ if(get_model_parameters(e.model, e.skin))
+ {
+ if(get_model_parameters_bone_upperbody)
+ e.bone_upperbody = gettagindex(e, get_model_parameters_bone_upperbody);
+ if(e.bone_upperbody)
+ e.fixbone = get_model_parameters_fixbone;
+ if(get_model_parameters_bone_weapon)
+ e.bone_weapon = gettagindex(e, get_model_parameters_bone_weapon);
+ for(i = 0; i < MAX_AIM_BONES; ++i)
+ {
+ if(get_model_parameters_bone_aim[i])
+ e.(bone_aim[i]) = gettagindex(e, get_model_parameters_bone_aim[i]);
+ if(e.bone_aim[i])
+ e.(bone_aimweight[i]) = get_model_parameters_bone_aimweight[i];
+ }
+ }
+ else
+ dprint("No model parameters for ", e.model, "\n");
+ dprint(e.model, " uses ", ftos(e.bone_upperbody), " ", ftos(e.fixbone), "\n");
+ get_model_parameters(string_null, 0);
+ e.skeleton_info_modelindex = e.modelindex;
+ e.skeleton_info_skin = e.skin;
+ if(e.skeletonindex)
+ {
+ skel_delete(e.skeletonindex);
+ e.skeletonindex = 0;
+ }
+}
+
+void skeleton_markbones(entity e)
+{
+ float s = e.skeletonindex;
+ float n = (e.skeleton_numbones = skel_get_numbones(s));
+ float i;
+ for(i = 1; i <= n; ++i)
+ {
+ float t = BONETYPE_LOWER;
+ float p = skel_get_boneparent(s, i);
+ if(p > 0)
+ t = e.(skeleton_bonetype[p-1]);
+ if(i == e.bone_upperbody)
+ t = BONETYPE_UPPER;
+ e.(skeleton_bonetype[i-1]) = t;
+ }
+}
+
+void skel_set_boneabs(float s, float bone, vector absorg)
+{
+ vector absang = fixedvectoangles2(v_forward, v_up);
+
+ vector parentorg = skel_get_boneabs(s, skel_get_boneparent(s, bone));
+ vector parentang = fixedvectoangles2(v_forward, v_up);
+
+ vector relang = AnglesTransform_LeftDivide(parentang, absang);
+ vector relorg = AnglesTransform_Apply(AnglesTransform_Invert(parentang), absorg - parentorg);
+
+ fixedmakevectors(relang);
+ skel_set_bone(s, bone, relorg);
+
+ /*
+ vector neworg = skel_get_boneabs(s, bone);
+ print(sprintf("ANG: want: %v, got: %v\n", absang, fixedvectoangles2(v_forward, v_up)));
+ print(sprintf("ORG: want: %v, got: %v\n", absorg, neworg));
+ */
+}
+
+void free_skeleton_from_frames(entity e)
+{
+ if(e.skeletonindex)
+ {
+ skel_delete(e.skeletonindex);
+ e.skeletonindex = 0;
+ }
+}
+
+void skeleton_from_frames(entity e, float is_dead)
+{
+ float i;
+ float m = e.modelindex;
+ if(!e.skeletonindex)
+ {
+ e.skeletonindex = skel_create(m);
+ skeleton_markbones(e);
+ }
+ float s = e.skeletonindex;
+ if(!s)
+ return;
+ float bone;
+ float n = e.skeleton_numbones;
+ float savelerpfrac = e.lerpfrac;
+ float savelerpfrac3 = e.lerpfrac3;
+ float savelerpfrac4 = e.lerpfrac4;
+
+ vector fixbone_oldangles = '0 0 0';
+ if(e.fixbone)
+ {
+ // make all bones BONETYPE_UPPER
+ e.lerpfrac = 0;
+ e.lerpfrac3 = savelerpfrac3 * 2;
+ e.lerpfrac4 = 0;
+ // build skeleton
+ skel_build(s, e, m, 0, 1, n);
+ // get hip bone
+ skel_get_boneabs(s, e.bone_upperbody);
+ fixbone_oldangles = fixedvectoangles2(v_forward, v_up);
+ }
+
+ for(bone = 0; bone < n; )
+ {
+ float firstbone = bone;
+ float bonetype = e.skeleton_bonetype[bone];
+ for(++bone; (bone < n) && (e.skeleton_bonetype[bone] == bonetype); ++bone)
+ ;
+ if(bonetype == BONETYPE_UPPER)
+ {
+ // only show frames 1+3 (upper body)
+ e.lerpfrac = 0;
+ e.lerpfrac3 = savelerpfrac3 * 2;
+ e.lerpfrac4 = 0;
+ }
+ else
+ {
+ // only show frames 2+4 (lower body)
+ e.lerpfrac = savelerpfrac * 2;
+ e.lerpfrac3 = 0;
+ e.lerpfrac4 = savelerpfrac4 * 2;
+ }
+ //print(sprintf("Run: bone %d to %d, type %d\n", firstbone + 1, bone, bonetype));
+ //print(sprintf("frame %d %d %d %d lerpfrac * %d %d %d\n", e.frame, e.frame2, e.frame3, e.frame4, e.lerpfrac, e.lerpfrac3, e.lerpfrac4));
+ skel_build(s, e, m, 0, firstbone + 1, bone);
+ }
+ e.lerpfrac = savelerpfrac;
+ e.lerpfrac3 = savelerpfrac3;
+ e.lerpfrac4 = savelerpfrac4;
+
+ if(e.fixbone)
+ {
+ // FIX IT
+ vector org = skel_get_boneabs(s, e.bone_upperbody);
+ fixedmakevectors(fixbone_oldangles);
+ skel_set_boneabs(s, e.bone_upperbody, org);
+ }
+
+ if(!is_dead)
+ {
+ for(i = 0; i < MAX_AIM_BONES; ++i)
+ {
+ if(e.(bone_aim[i]))
+ {
+ vector aim = '1 0 0' * bound(-90, self.v_angle_x, 90) * e.(bone_aimweight[i]);
+ vector org = skel_get_boneabs(s, e.(bone_aim[i]));
+ vector ang_cur = fixedvectoangles2(v_forward, v_up);
+ vector ang = AnglesTransform_Multiply(aim, ang_cur);
+ fixedmakevectors(ang);
+ skel_set_boneabs(s, e.(bone_aim[i]), org);
+ }
+ }
+ }
+}
--- /dev/null
+void free_skeleton_from_frames(entity e);
+void skeleton_from_frames(entity e, float is_dead);
+void skeleton_loadinfo(entity e);
+
+.float bone_upperbody;
+.float bone_weapon;
+.float bone_aim[MAX_AIM_BONES];
+.float bone_aimweight[MAX_AIM_BONES];
+.float fixbone;
../warpzonelib/common.qh
../warpzonelib/client.qh
+../common/teams.qh
../common/util.qh
+../common/counting.qh
../common/items.qh
../common/explosion_equation.qh
../common/mapinfo.qh
../common/command/generic.qh
../common/command/shared_defs.qh
../common/urllib.qh
+../common/animdecide.qh
command/cl_cmd.qh
autocvars.qh
+../common/notifications.qh // must be after autocvars
+../common/deathtypes.qh // must be after notifications
+
damage.qh
../csqcmodellib/interpolate.qh
prandom.qh
bgmscript.qh
noise.qh
-teamplay.qh
tturrets.qh
../server/tturrets/include/turrets_early.qh
../server/movelib.qc
../csqcmodellib/cl_model.qh
../csqcmodellib/cl_player.qh
projectile.qh
+player_skeleton.qh
sortlist.qc
miscfunctions.qc
-teamplay.qc
../server/t_items.qc
teamradar.qc
noise.qc
../common/util.qc
+../common/notifications.qc
../common/command/markup.qc
../common/command/rpn.qc
../common/command/generic.qc
../warpzonelib/client.qc
tturrets.qc
+player_skeleton.qc
+../common/animdecide.qc
+
../common/if-this-file-errors-scroll-up-and-fix-the-warnings.fteqccfail
.float trail_oldtime;
.float fade_time, fade_rate;
-void SUB_Null()
-{
-}
-
void SUB_Stop()
{
self.move_velocity = self.move_avelocity = '0 0 0';
return;
sound(e, ch, samp, vol, attn);
- e.snd_looping = 1;
+ e.snd_looping = ch;
}
void Ent_RemoveProjectile()
{
- if(self.snd_looping)
- sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTN_NORM);
-
if(self.count & 0x80)
{
tracebox(self.origin, self.mins, self.maxs, self.origin + self.velocity * 0.05, MOVE_NORMAL, self);
f = ReadByte();
self.count = (f & 0x80);
- self.iflags = (self.iflags & IFLAG_INTERNALMASK) | IFLAG_AUTOANGLES | IFLAG_ANGLES;
+ self.iflags = (self.iflags & IFLAG_INTERNALMASK) | IFLAG_AUTOANGLES | IFLAG_ANGLES | IFLAG_ORIGIN;
self.solid = SOLID_TRIGGER;
//self.effects = EF_NOMODELFLAGS;
self.origin_x = ReadCoord();
self.origin_y = ReadCoord();
self.origin_z = ReadCoord();
+ setorigin(self, self.origin);
if(self.count & 0x80)
{
self.velocity_x = ReadCoord();
self.mins = '0 0 -4';
self.maxs = '0 0 -4';
self.move_movetype = MOVETYPE_BOUNCE;
- self.move_touch = SUB_Null;
+ self.move_touch = func_null;
self.move_bounce_factor = g_balance_electro_secondary_bouncefactor;
self.move_bounce_stopspeed = g_balance_electro_secondary_bouncestop;
break;
self.mins = '-3 -3 -3';
self.maxs = '3 3 3';
self.move_movetype = MOVETYPE_BOUNCE;
- self.move_touch = SUB_Null;
+ self.move_touch = func_null;
self.move_bounce_factor = g_balance_grenadelauncher_bouncefactor;
self.move_bounce_stopspeed = g_balance_grenadelauncher_bouncestop;
break;
self.colormod = '2 1 1';
self.alphamod = 0.5;
self.move_movetype = MOVETYPE_BOUNCE;
- self.move_touch = SUB_Null;
+ self.move_touch = func_null;
break;
case PROJECTILE_PORTO_BLUE:
self.colormod = '1 1 2';
self.alphamod = 0.5;
self.move_movetype = MOVETYPE_BOUNCE;
- self.move_touch = SUB_Null;
+ self.move_touch = func_null;
break;
case PROJECTILE_HAGAR_BOUNCING:
self.move_movetype = MOVETYPE_BOUNCE;
- self.move_touch = SUB_Null;
+ self.move_touch = func_null;
break;
case PROJECTILE_CRYLINK_BOUNCING:
self.move_movetype = MOVETYPE_BOUNCE;
- self.move_touch = SUB_Null;
+ self.move_touch = func_null;
break;
case PROJECTILE_FIREBALL:
loopsound(self, CH_SHOTS_SINGLE, "weapons/fireball_fly2.wav", VOL_BASE, ATTN_NORM);
case PROJECTILE_FIREMINE:
loopsound(self, CH_SHOTS_SINGLE, "weapons/fireball_fly.wav", VOL_BASE, ATTN_NORM);
self.move_movetype = MOVETYPE_BOUNCE;
- self.move_touch = SUB_Null;
+ self.move_touch = func_null;
self.mins = '-4 -4 -4';
self.maxs = '4 4 4';
break;
self.mins = '0 0 -4';
self.maxs = '0 0 -4';
self.move_movetype = MOVETYPE_BOUNCE;
- self.move_touch = SUB_Null;
+ self.move_touch = func_null;
self.move_bounce_factor = g_balance_electro_secondary_bouncefactor;
self.move_bounce_stopspeed = g_balance_electro_secondary_bouncestop;
break;
default:
break;
}
+ setsize(self, self.mins, self.maxs);
}
if(self.gravity)
*/
}
+float HUD_CompareScore(float vl, float vr, float f)
+{
+ if(f & SFL_ZERO_IS_WORST)
+ {
+ if(vl == 0 && vr != 0)
+ return 1;
+ if(vl != 0 && vr == 0)
+ return 0;
+ }
+ if(vl > vr)
+ return IS_INCREASING(f);
+ if(vl < vr)
+ return IS_DECREASING(f);
+ return -1;
+}
+
float HUD_ComparePlayerScores(entity left, entity right)
{
- float vl, vr;
+ float vl, vr, r, i;
vl = GetPlayerColor(left.sv_entnum);
vr = GetPlayerColor(right.sv_entnum);
if(!left.gotscores)
- vl = COLOR_SPECTATOR;
+ vl = NUM_SPECTATOR;
if(!right.gotscores)
- vr = COLOR_SPECTATOR;
+ vr = NUM_SPECTATOR;
if(vl > vr)
return true;
if(vl < vr)
return false;
- if(vl == COLOR_SPECTATOR)
+ if(vl == NUM_SPECTATOR)
{
// FIRST the one with scores (spectators), THEN the ones without (downloaders)
// no other sorting
return false;
}
- vl = left.scores[ps_primary];
- vr = right.scores[ps_primary];
- if(scores_flags[ps_primary] & SFL_ZERO_IS_WORST)
- {
- if(vl == 0 && vr != 0)
- return 1;
- if(vl != 0 && vr == 0)
- return 0;
- }
- if(vl > vr)
- return IS_INCREASING(scores_flags[ps_primary]);
- if(vl < vr)
- return IS_DECREASING(scores_flags[ps_primary]);
+ r = HUD_CompareScore(left.scores[ps_primary], right.scores[ps_primary], scores_flags[ps_primary]);
+ if (r >= 0)
+ return r;
+
+ r = HUD_CompareScore(left.scores[ps_secondary], right.scores[ps_secondary], scores_flags[ps_secondary]);
+ if (r >= 0)
+ return r;
- vl = left.scores[ps_secondary];
- vr = right.scores[ps_secondary];
- if(scores_flags[ps_secondary] & SFL_ZERO_IS_WORST)
+ for(i = 0; i < MAX_SCORE; ++i)
{
- if(vl == 0 && vr != 0)
- return 1;
- if(vl != 0 && vr == 0)
- return 0;
+ r = HUD_CompareScore(left.scores[i], right.scores[i], scores_flags[i]);
+ if (r >= 0)
+ return r;
}
- if(vl > vr)
- return IS_INCREASING(scores_flags[ps_secondary]);
- if(vl < vr)
- return IS_DECREASING(scores_flags[ps_secondary]);
+
+ if (left.sv_entnum < right.sv_entnum)
+ return true;
return false;
}
float HUD_CompareTeamScores(entity left, entity right)
{
- float vl, vr;
+ float i, r;
- if(left.team == COLOR_SPECTATOR)
+ if(left.team == NUM_SPECTATOR)
return 1;
- if(right.team == COLOR_SPECTATOR)
+ if(right.team == NUM_SPECTATOR)
return 0;
- vl = left.teamscores[ts_primary];
- vr = right.teamscores[ts_primary];
- if(vl > vr)
- return IS_INCREASING(teamscores_flags[ts_primary]);
- if(vl < vr)
- return IS_DECREASING(teamscores_flags[ts_primary]);
+ r = HUD_CompareScore(left.teamscores[ts_primary], right.teamscores[ts_primary], teamscores_flags[ts_primary]);
+ if (r >= 0)
+ return r;
- vl = left.teamscores[ts_secondary];
- vr = right.teamscores[ts_secondary];
- if(vl > vr)
- return IS_INCREASING(teamscores_flags[ts_secondary]);
- if(vl < vr)
- return IS_DECREASING(teamscores_flags[ts_secondary]);
+ r = HUD_CompareScore(left.teamscores[ts_secondary], right.teamscores[ts_secondary], teamscores_flags[ts_secondary]);
+ if (r >= 0)
+ return r;
+
+ for(i = 0; i < MAX_SCORE; ++i)
+ {
+ r = HUD_CompareScore(left.teamscores[i], right.teamscores[i], teamscores_flags[i]);
+ if (r >= 0)
+ return r;
+ }
+
+ if (left.team < right.team)
+ return true;
return false;
}
{
float i, j, slash;
string str, pattern;
- float have_name, have_primary, have_secondary, have_separator;
+ float have_name = 0, have_primary = 0, have_secondary = 0, have_separator = 0;
float missing;
// TODO: re enable with gametype dependant cvars?
if(argc < 3) // no arguments provided
- argc = tokenizebyseparator(strcat("x ", autocvar_scoreboard_columns), " ");
+ argc = tokenizebyseparator(strcat("0 1 ", autocvar_scoreboard_columns), " ");
if(argc < 3)
- argc = tokenizebyseparator(strcat("x ", HUD_DefaultColumnLayout()), " ");
+ argc = tokenizebyseparator(strcat("0 1 ", HUD_DefaultColumnLayout()), " ");
if(argc == 3)
{
if(argv(2) == "default")
- argc = tokenizebyseparator(strcat("x ", HUD_DefaultColumnLayout()), " ");
+ argc = tokenizebyseparator(strcat("0 1 ", HUD_DefaultColumnLayout()), " ");
else if(argv(2) == "all")
{
string s;
if(ps_secondary != ps_primary)
s = strcat(s, " ", scores_label[ps_secondary]);
s = strcat(s, " ", scores_label[ps_primary]);
- argc = tokenizebyseparator(strcat("x ", s), " ");
+ argc = tokenizebyseparator(strcat("0 1 ", s), " ");
}
}
hud_num_fields = 0;
- hud_fontsize = HUD_GetFontsize("hud_fontsize");
+ hud_fontsize = HUD_GetFontsize("hud_fontsize");
draw_beginBoldFont();
- for(i = 0; i < argc - 1; ++i)
+ for(i = 1; i < argc - 1; ++i)
{
float nocomplain;
str = argv(i+1);
void HUD_PrintScoreboardItem(vector pos, entity pl, float is_self, float pl_number)
{
vector tmp, rgb;
- rgb = GetTeamRGB(pl.team);
+ rgb = Team_ColorRGB(pl.team);
string str;
float i, field;
float is_spec;
- is_spec = (GetPlayerColor(pl.sv_entnum) == COLOR_SPECTATOR);
+ is_spec = (GetPlayerColor(pl.sv_entnum) == NUM_SPECTATOR);
if((rgb == '1 1 1') && (!is_spec)) {
rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_size)
{
float body_table_height, i;
- vector tmp, column_dim;
+ vector tmp = '0 0 0', column_dim = '0 0 0';
entity pl;
body_table_height = 1.25 * hud_fontsize_y * max(1, tm.team_size); // no player? show 1 empty line
else
for(pl = players.sort_next; pl; pl = pl.sort_next)
{
- if(pl.team == COLOR_SPECTATOR)
+ if(pl.team == NUM_SPECTATOR)
continue;
HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), i);
pos_y += 1.25 * hud_fontsize_y;
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;
- vector tmp;
+ vector tmp = '0 0 0';
tmp_x = sbwidth;
tmp_y = height * rows;
g_minstagib = 1; // TODO: real detection for minstagib?
float weapon_stats;
-
- if (!acc_levels)
+ if(autocvar_scoreboard_accuracy_nocolors)
rgb = '1 1 1';
- else if (acc_col[0] == '-1 0 0')
- for (i = 0; i < acc_levels; ++i)
- acc_col[i] = stov(cvar_string(strcat("accuracy_color", ftos(i))));
+ else
+ Accuracy_LoadColors();
for(i = WEP_FIRST; i <= WEP_LAST; ++i)
{
float padding;
padding = (weapon_width - stringwidth(s, FALSE, '1 0 0' * fontsize)) / 2; // center the accuracy value
- if (acc_levels)
- {
- // find the max level lower than weapon_stats
- float j;
- j = acc_levels-1;
- while ( j && weapon_stats < acc_lev[j] )
- --j;
-
- // inject color j+1 in color j, how much depending on how much weapon_stats is higher than level j
- float factor;
- factor = (weapon_stats - acc_lev[j]) / (acc_lev[j+1] - acc_lev[j]);
- rgb = acc_col[j];
- rgb = rgb + factor * (acc_col[j+1] - rgb);
- }
+ if(!autocvar_scoreboard_accuracy_nocolors)
+ rgb = Accuracy_GetColor(weapon_stats);
drawstring(pos + '1 0 0' * padding + '0 1 0' * weapon_height, s, '1 1 0' * fontsize, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
}
}
if(weapons_with_stats)
- average_accuracy = floor(average_accuracy / weapons_with_stats);
+ average_accuracy = floor((average_accuracy * 100 / weapons_with_stats) + 0.5);
if(rows == 2)
pos_x -= weapon_width / 2;
pos_y += 1.25 * hud_fontsize_y + autocvar_scoreboard_border_thickness;
// draw table
- vector tmp;
+ vector tmp = '0 0 0';
tmp_x = sbwidth;
tmp_y = hud_fontsize_y * rows;
return pos;
float is_spec;
- is_spec = (GetPlayerColor(pl.sv_entnum) == COLOR_SPECTATOR);
+ is_spec = (GetPlayerColor(pl.sv_entnum) == NUM_SPECTATOR);
vector hl_rgb;
hl_rgb_x = autocvar_scoreboard_color_bg_r + 0.5;
hl_rgb_y = autocvar_scoreboard_color_bg_g + 0.5;
pos_y += hud_fontsize_y;
drawstring(pos, _("Rankings"), hud_fontsize, '1 1 1', scoreboard_alpha_fg, DRAWFLAG_NORMAL);
pos_y += hud_fontsize_y + autocvar_scoreboard_border_thickness;
- vector tmp;
+ vector tmp = '0 0 0';
tmp_x = sbwidth;
tmp_y = 1.25 * hud_fontsize_y * RANKINGS_RECEIVED_CNT;
if (t == 0)
continue;
n = grecordholder[i];
- p = race_PlaceName(i+1);
+ 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)
team_score_baseoffset = eY * (2 * autocvar_scoreboard_border_thickness + hud_fontsize_y) - eX * (autocvar_scoreboard_border_thickness + hud_fontsize_x * 0.25);
for(tm = teams.sort_next; tm; tm = tm.sort_next)
{
- if(tm.team == COLOR_SPECTATOR)
+ if(tm.team == NUM_SPECTATOR)
continue;
draw_beginBoldFont();
- rgb = GetTeamRGB(tm.team);
+ rgb = Team_ColorRGB(tm.team);
str = ftos(tm.(teamscores[ts_primary]));
drawstring(pos + team_score_baseoffset - eX * stringwidth(str, FALSE, hud_fontsize * 1.5), str, hud_fontsize * 1.5, rgb, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
}
+
+#ifdef GMQCC
+ rgb = '0 0 0';
+#endif
+ rgb_x = autocvar_scoreboard_color_bg_r;
+ rgb_y = autocvar_scoreboard_color_bg_g;
+ rgb_z = autocvar_scoreboard_color_bg_b;
}
else
{
+#ifdef GMQCC
+ rgb = '0 0 0';
+#endif
rgb_x = autocvar_scoreboard_color_bg_r;
rgb_y = autocvar_scoreboard_color_bg_g;
rgb_z = autocvar_scoreboard_color_bg_b;
for(tm = teams.sort_next; tm; tm = tm.sort_next)
{
- if(tm.team == COLOR_SPECTATOR)
+ if(tm.team == NUM_SPECTATOR)
continue;
pos = HUD_Scoreboard_MakeTable(pos, tm, rgb, bg_size);
drawcolorcodedstring(pos, sprintf(_("All-time fastest: %d ^7(%s^7)"), race_speedaward_alltimebest, race_speedaward_alltimebest_holder), hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
pos_y += 1.25 * hud_fontsize_y;
}
- pos = HUD_DrawScoreboardRankings(pos, pl, rgb, bg_size);
+ pos = HUD_DrawScoreboardRankings(pos, playerslots[player_localnum], rgb, bg_size);
}
else if(autocvar_scoreboard_accuracy && spectatee_status != -1 && !warmup_stage) {
if(teamplay)
- pos = HUD_DrawScoreboardAccuracyStats(pos, GetTeamRGB(myteam), bg_size);
+ pos = HUD_DrawScoreboardAccuracyStats(pos, Team_ColorRGB(myteam), bg_size);
else
pos = HUD_DrawScoreboardAccuracyStats(pos, rgb, bg_size);
}
if(teamplay)
- pos = HUD_DrawMapStats(pos, GetTeamRGB(myteam), bg_size);
+ pos = HUD_DrawMapStats(pos, Team_ColorRGB(myteam), bg_size);
else
pos = HUD_DrawMapStats(pos, rgb, bg_size);
tmp = pos;
for(pl = players.sort_next; pl; pl = pl.sort_next)
{
- if(pl.team != COLOR_SPECTATOR)
+ if(pl.team != NUM_SPECTATOR)
continue;
pos_y += 1.25 * hud_fontsize_y;
HUD_PrintScoreboardItem(pos, pl, (pl.sv_entnum == player_localnum), specs);
}
}
-
pos_y += 1.2 * hud_fontsize_y;
drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
+ // print information about respawn status
+ float respawn_time = getstatf(STAT_RESPAWN_TIME);
+ if(respawn_time)
+ {
+ if(respawn_time < 0)
+ {
+ // a negative number means we are awaiting respawn, time value is still the same
+ respawn_time *= -1; // remove mark now that we checked it
+ respawn_time = max(time, respawn_time); // don't show a negative value while the server is respawning the player (lag)
+
+ str = sprintf(_("^1Respawning in ^3%s^1..."),
+ (autocvar_scoreboard_respawntime_decimals ?
+ count_seconds_decs(respawn_time - time, autocvar_scoreboard_respawntime_decimals)
+ :
+ count_seconds(respawn_time - time)
+ )
+ );
+ }
+ else if(time < respawn_time)
+ {
+ str = sprintf(_("You are dead, wait ^3%s^7 before respawning"),
+ (autocvar_scoreboard_respawntime_decimals ?
+ count_seconds_decs(respawn_time - time, autocvar_scoreboard_respawntime_decimals)
+ :
+ count_seconds(respawn_time - time)
+ )
+ );
+ }
+ else if(time >= respawn_time)
+ str = sprintf(_("You are dead, press ^2%s^7 to respawn"), getcommandkey("jump", "+jump"));
+
+ pos_y += 1.2 * hud_fontsize_y;
+ drawcolorcodedstring(pos + '0.5 0 0' * (sbwidth - stringwidth(str, TRUE, hud_fontsize)), str, hud_fontsize, scoreboard_alpha_fg, DRAWFLAG_NORMAL);
+ }
+
scoreboard_bottom = pos_y + 2 * hud_fontsize_y;
}
}
// handle tag fading
- float overlap, onscreen, crosshairdistance;
+ float overlap = FALSE, onscreen, crosshairdistance;
vector o, eo;
o = project_3d_to_2d(ent.origin);
{
float t;
t = GetPlayerColor(i);
- if(t == COLOR_SPECTATOR)
+ if(t == NUM_SPECTATOR)
continue;
entity e;
e.sameteam = 0;
}
- e.origin = getplayerorigin(i);
+ setorigin(e, getplayerorigin(i));
if(e.origin == GETPLAYERORIGIN_ERROR)
continue;
.float armorvalue;
.float sameteam;
.float fadedelay;
-.float pointtime;
\ No newline at end of file
+.float pointtime;
+++ /dev/null
-float TeamByColor(float color)
-{
- switch(color)
- {
- case COLOR_TEAM1: return 0;
- case COLOR_TEAM2: return 1;
- case COLOR_TEAM3: return 2;
- case COLOR_TEAM4: return 3;
- default: return 0;
- }
-}
-float ColorByTeam(float i)
-{
- switch(i)
- {
- case 0: return COLOR_TEAM1;
- case 1: return COLOR_TEAM2;
- case 2: return COLOR_TEAM3;
- case 3: return COLOR_TEAM4;
- default: return COLOR_TEAM1;
- }
-}
-
-float GetPlayerColorForce(float i)
-{
- if(!teamplay)
- return 0;
- else
- return stof(getplayerkeyvalue(i, "colors")) & 15;
-}
-
-float GetPlayerColor(float i)
-{
- if not(playerslots[i].gotscores) // unconnected
- return COLOR_SPECTATOR;
- else if(stof(getplayerkeyvalue(i, "frags")) == FRAGS_SPECTATOR)
- return COLOR_SPECTATOR;
- else
- return GetPlayerColorForce(i);
-}
-
-string GetPlayerName(float i)
-{
- return ColorTranslateRGB(getplayerkeyvalue(i, "name"));
-}
-
-vector GetTeamRGB(float color)
-{
- switch(color)
- {
- default: return '1 1 1';
- case COLOR_TEAM1: return '1 0 0'; // red
- case COLOR_TEAM2: return '0 0 1'; // blue
- case COLOR_TEAM3: return '1 1 0'; // yellow
- case COLOR_TEAM4: return '1 0 1'; // pink
- }
-}
-
-string GetTeamName(float color)
-{
- switch(color)
- {
- default: return _("Spectators");
- case COLOR_TEAM1: return _("Red Team");
- case COLOR_TEAM2: return _("Blue Team");
- case COLOR_TEAM3: return _("Yellow Team");
- case COLOR_TEAM4: return _("Pink Team");
- }
-}
+++ /dev/null
-float teamplay;
-float myteam;
float hud_panel_radar_rotation;
noref vector hud_panel_radar_size; // fteqcc sucks
float hud_panel_radar_zoommode;
+float hud_panel_radar_maximized_zoommode;
+float hud_panel_radar_maximized_rotation;
void teamradar_loadcvars()
{
hud_panel_radar_foreground_alpha = autocvar_hud_panel_radar_foreground_alpha * panel_fg_alpha;
hud_panel_radar_rotation = autocvar_hud_panel_radar_rotation;
hud_panel_radar_zoommode = autocvar_hud_panel_radar_zoommode;
+ hud_panel_radar_maximized_rotation = autocvar_hud_panel_radar_maximized_rotation;
+ hud_panel_radar_maximized_zoommode = autocvar_hud_panel_radar_maximized_zoommode;
// others default to 0
// match this to defaultXonotic.cfg!
InterpolateOrigin_Undo();
- self.iflags = IFLAG_VELOCITY;
+ self.iflags = IFLAG_VELOCITY | IFLAG_ORIGIN;
self.classname = "radarlink";
if(sendflags & 1)
self.origin_x = ReadCoord();
self.origin_y = ReadCoord();
self.origin_z = ReadCoord();
+ setorigin(self, self.origin);
}
if(sendflags & 2)
{
switch(self.team - 1)
{
- case COLOR_TEAM1: // Red
+ case NUM_TEAM_1: // Red
self.glowmod = '2 0 0';
self.teamradar_color = '1 0 0';
break;
- case COLOR_TEAM2: // Blue
+ case NUM_TEAM_2: // Blue
self.glowmod = '0 0 2';
self.teamradar_color = '0 0 1';
break;
- case COLOR_TEAM3: // Yellow
+ case NUM_TEAM_3: // Yellow
self.glowmod = '1 1 0';
self.teamradar_color = '1 1 0';
break;
- case COLOR_TEAM4: // Pink
+ case NUM_TEAM_4: // Pink
self.glowmod = '1 0 1';
self.teamradar_color = '1 0 1';
break;
gib.gravity = 1;
gib.move_movetype = MOVETYPE_BOUNCE;
- gib.move_origin = gib.origin = _from;
+ gib.move_origin = _from;
+ setorigin(gib, _from);
gib.move_velocity = _to;
gib.move_avelocity = prandomvec() * 32;
gib.move_time = time;
self.origin_x = ReadCoord();
self.origin_y = ReadCoord();
self.origin_z = ReadCoord();
+ setorigin(self, self.origin);
self.angles_x = ReadAngle();
self.angles_y = ReadAngle();
#define TUBA_MIN -18
#define TUBA_MAX 27
-#define TUBA_INSTRUMENTS 2
+#define TUBA_INSTRUMENTS 3
#define TUBA_STARTNOTE(i,n) strcat("weapons/tuba", (i ? ftos(i) : ""), "_loopnote", ftos(n), ".wav")
.float note; // note
#define MAX_AXH 4
entity AuxiliaryXhair[MAX_AXH];
-const var void Draw_Not();
.string axh_image;
.float axh_fadetime;
}
if(time - self.cnt > self.axh_fadetime)
- self.draw2d = Draw_Not;
+ self.draw2d = func_null;
}
void Net_AuXair2(float bIsNew)
if(axh == world || wasfreed(axh)) // MADNESS? THIS IS QQQQCCCCCCCCC (wasfreed, why do you exsist?)
{
axh = spawn();
- axh.draw2d = Draw_Not;
+ axh.draw2d = func_null;
axh.drawmask = MASK_NORMAL;
axh.axh_drawflag = DRAWFLAG_ADDITIVE;
axh.axh_fadetime = 0.1;
remove(axh);
axh = spawn();
- axh.draw2d = Draw_Not;
+ axh.draw2d = func_null;
axh.drawmask = MASK_NORMAL;
axh.axh_drawflag = DRAWFLAG_NORMAL;
axh.axh_fadetime = 0.1;
}
}
#define HUD_GETSTATS \
- float vh_health = getstati(STAT_VEHICLESTAT_HEALTH); \
- float shield = getstati(STAT_VEHICLESTAT_SHIELD); \
- float energy = getstati(STAT_VEHICLESTAT_ENERGY); \
- float ammo1 = getstati(STAT_VEHICLESTAT_AMMO1); \
- float reload1 = getstati(STAT_VEHICLESTAT_RELOAD1); \
- float ammo2 = getstati(STAT_VEHICLESTAT_AMMO2); \
- float reload2 = getstati(STAT_VEHICLESTAT_RELOAD2);
+ local noref float vh_health = getstati(STAT_VEHICLESTAT_HEALTH); \
+ local noref float shield = getstati(STAT_VEHICLESTAT_SHIELD); \
+ local noref float energy = getstati(STAT_VEHICLESTAT_ENERGY); \
+ local noref float ammo1 = getstati(STAT_VEHICLESTAT_AMMO1); \
+ local noref float reload1 = getstati(STAT_VEHICLESTAT_RELOAD1); \
+ local noref float ammo2 = getstati(STAT_VEHICLESTAT_AMMO2); \
+ local noref float reload2 = getstati(STAT_VEHICLESTAT_RELOAD2);
void CSQC_BUMBLE_HUD()
{
if(autocvar_r_letterbox)
return;
- vector picsize, hudloc, pic2size, picloc;
+ vector picsize, hudloc = '0 0 0', pic2size, picloc;
// Fetch health & ammo stats
HUD_GETSTATS
drawresetcliparea();
// Right gunner slot occupied?
- if(AuxiliaryXhair[1].draw2d == Draw_Not)
+ if(!AuxiliaryXhair[1].draw2d)
{
shield = (picsize_x * 0.5) - (0.5 * stringwidth(_("No right gunner!"), FALSE, '1 0 0' * picsize_y + '0 1 0' * picsize_y));
drawfill(hudloc + picloc - '0.2 0.2 0', picsize + '0.4 0.4 0', '0.25 0.25 0.25', 0.75, DRAWFLAG_NORMAL);
drawpic(hudloc + picloc, hud_ammo2_bar, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
drawresetcliparea();
// Left gunner slot occupied?
- if(AuxiliaryXhair[2].draw2d == Draw_Not)
+ if(!AuxiliaryXhair[2].draw2d)
{
shield = (picsize_x * 0.5) - (0.5 * stringwidth(_("No left gunner!"), FALSE, '1 0 0' * picsize_y + '0 1 0' * picsize_y));
drawfill(hudloc + picloc - '0.2 0.2 0', picsize + '0.4 0.4 0', '0.25 0.25 0.25', 0.75, DRAWFLAG_NORMAL);
if(autocvar_r_letterbox)
return;
- vector picsize, hudloc, pic2size, picloc;
+ vector picsize, hudloc = '0 0 0', pic2size, picloc;
// Fetch health & ammo stats
HUD_GETSTATS
if(autocvar_r_letterbox)
return;
- vector picsize, hudloc, pic2size, picloc;
+ vector picsize, hudloc = '0 0 0', pic2size, picloc;
float i;
// Fetch health & ammo stats
if(autocvar_r_letterbox)
return;
- vector picsize, hudloc, pic2size, picloc;
+ vector picsize, hudloc = '0 0 0', pic2size, picloc;
// Fetch health & ammo stats
HUD_GETSTATS
if(autocvar_r_letterbox)
return;
- vector picsize, hudloc, pic2size, picloc;
+ vector picsize, hudloc = '0 0 0', pic2size, picloc;
// Fetch health & ammo stats
HUD_GETSTATS
var .vector fld;
if(self.bgmscriptangular)
- self.angles = self.saved;
+ fld = angles;
else
- self.origin = self.saved;
+ fld = origin;
+ self.fld = self.saved;
if(self.lodmodelindex1)
{
InterpolateOrigin_Do();
- if(self.bgmscriptangular)
- self.saved = self.angles;
- else
- self.saved = self.origin;
+ self.saved = self.fld;
f = BGMScript(self);
if(f >= 0)
void Ent_Wall()
{
float f;
+ var .vector fld;
+
InterpolateOrigin_Undo();
- self.iflags = IFLAG_ANGLES;
+ self.iflags = IFLAG_ANGLES | IFLAG_ORIGIN;
if(self.bgmscriptangular)
- self.angles = self.saved;
+ fld = angles;
else
- self.origin = self.saved;
+ fld = origin;
+ self.fld = self.saved;
f = ReadByte();
self.origin_x = ReadCoord();
self.origin_y = ReadCoord();
self.origin_z = ReadCoord();
+ setorigin(self, self.origin);
}
if(f & 4)
}
else
self.mins = self.maxs = '0 0 0';
+ setsize(self, self.mins, self.maxs);
if(self.bgmscript)
strunzone(self.bgmscript);
InterpolateOrigin_Note();
- if(self.bgmscriptangular)
- self.saved = self.angles;
- else
- self.saved = self.origin;
+ self.saved = self.fld;
self.entremove = Ent_Wall_Remove;
self.draw = Ent_Wall_Draw;
spriteimage = self.netname;
break;
case SPRITERULE_TEAMPLAY:
- if(t == COLOR_SPECTATOR + 1)
+ if(t == NUM_SPECTATOR + 1)
spriteimage = self.netname3;
else if(self.team == t)
spriteimage = self.netname2;
self.draw2d = Draw_WaypointSprite;
InterpolateOrigin_Undo();
+ self.iflags |= IFLAG_ORIGIN;
if(sendflags & 0x80)
{
self.origin_x = ReadCoord();
self.origin_y = ReadCoord();
self.origin_z = ReadCoord();
+ setorigin(self, self.origin);
}
if(sendflags & 1)
--- /dev/null
+// player animation data for this model
+// each vector is as follows:
+// _x = startframe
+// _y = numframes
+// _z = framerate
+.vector anim_die1; // player dies
+.vector anim_die2; // player dies differently
+.vector anim_draw; // player pulls out a weapon
+.vector anim_duckwalk; // player walking while crouching
+.vector anim_duckjump; // player jumping from a crouch
+.vector anim_duckidle; // player idling while crouching
+.vector anim_idle; // player standing
+.vector anim_jump; // player jump
+.vector anim_pain1; // player flinches from pain
+.vector anim_pain2; // player flinches from pain, differently
+.vector anim_shoot; // player shoots
+.vector anim_taunt; // player taunts others (FIXME: no code references this)
+.vector anim_run; // player running forward
+.vector anim_runbackwards; // player running backward
+.vector anim_strafeleft; // player shuffling left quickly
+.vector anim_straferight; // player shuffling right quickly
+.vector anim_forwardright; // player running forward and right
+.vector anim_forwardleft; // player running forward and left
+.vector anim_backright; // player running backward and right
+.vector anim_backleft; // player running back and left
+.vector anim_melee; // player doing the melee action
+.vector anim_duck; // player doing the melee action
+.vector anim_duckwalkbackwards;
+.vector anim_duckwalkstrafeleft;
+.vector anim_duckwalkstraferight;
+.vector anim_duckwalkforwardright;
+.vector anim_duckwalkforwardleft;
+.vector anim_duckwalkbackright;
+.vector anim_duckwalkbackleft;
+.float animdecide_modelindex;
+
+void animdecide_init(entity e)
+{
+ if(e.modelindex == e.animdecide_modelindex)
+ return;
+ e.animdecide_modelindex = e.modelindex;
+
+ vector none = '0 0 0';
+ e.anim_die1 = animfixfps(e, '0 1 0.5', none); // 2 seconds
+ e.anim_die2 = animfixfps(e, '1 1 0.5', none); // 2 seconds
+ e.anim_draw = animfixfps(e, '2 1 3', none);
+ e.anim_duckwalk = animfixfps(e, '4 1 1', none);
+ e.anim_duckjump = animfixfps(e, '5 1 10', none);
+ e.anim_duckidle = animfixfps(e, '6 1 1', none);
+ e.anim_idle = animfixfps(e, '7 1 1', none);
+ e.anim_jump = animfixfps(e, '8 1 10', none);
+ e.anim_pain1 = animfixfps(e, '9 1 2', none); // 0.5 seconds
+ e.anim_pain2 = animfixfps(e, '10 1 2', none); // 0.5 seconds
+ e.anim_shoot = animfixfps(e, '11 1 5', none); // analyze models and set framerate
+ e.anim_taunt = animfixfps(e, '12 1 0.33', none);
+ e.anim_run = animfixfps(e, '13 1 1', none);
+ e.anim_runbackwards = animfixfps(e, '14 1 1', none);
+ e.anim_strafeleft = animfixfps(e, '15 1 1', none);
+ e.anim_straferight = animfixfps(e, '16 1 1', none);
+ e.anim_forwardright = animfixfps(e, '19 1 1', '16 1 1');
+ e.anim_forwardleft = animfixfps(e, '20 1 1', '15 1 1');
+ e.anim_backright = animfixfps(e, '21 1 1', '16 1 1');
+ e.anim_backleft = animfixfps(e, '22 1 1', '15 1 1');
+ e.anim_melee = animfixfps(e, '23 1 1', '11 1 1');
+ e.anim_duckwalkbackwards = animfixfps(e, '24 1 1', '4 1 1');
+ e.anim_duckwalkstrafeleft = animfixfps(e, '25 1 1', '4 1 1');
+ e.anim_duckwalkstraferight = animfixfps(e, '26 1 1', '4 1 1');
+ e.anim_duckwalkforwardright = animfixfps(e, '27 1 1', '4 1 1');
+ e.anim_duckwalkforwardleft = animfixfps(e, '28 1 1', '4 1 1');
+ e.anim_duckwalkbackright = animfixfps(e, '29 1 1', '4 1 1');
+ e.anim_duckwalkbackleft = animfixfps(e, '30 1 1', '4 1 1');
+
+ // these anims ought to stay until stopped explicitly by weaponsystem
+ e.anim_shoot_z = 0.001;
+ e.anim_melee_z = 0.001;
+}
+
+#define ANIMPRIO_IDLE 0
+#define ANIMPRIO_ACTIVE 1
+#define ANIMPRIO_CROUCH 2
+#define ANIMPRIO_DEAD 3
+
+vector animdecide_getupperanim(entity e)
+{
+ // death etc.
+ if(e.anim_state & ANIMSTATE_FROZEN)
+ return vec3(e.anim_idle_x, e.anim_time, ANIMPRIO_DEAD);
+ if(e.anim_state & ANIMSTATE_DEAD1)
+ return vec3(e.anim_die1_x, e.anim_time, ANIMPRIO_DEAD);
+ if(e.anim_state & ANIMSTATE_DEAD2)
+ return vec3(e.anim_die2_x, e.anim_time, ANIMPRIO_DEAD);
+
+ // is there an action?
+ vector outframe = '-1 0 0';
+ float t, a;
+ if(e.anim_upper_time >= e.anim_upper_implicit_time)
+ {
+ a = e.anim_upper_action;
+ t = e.anim_upper_time;
+ }
+ else
+ {
+ a = e.anim_upper_implicit_action;
+ t = e.anim_upper_implicit_time;
+ }
+ switch(a)
+ {
+ case ANIMACTION_DRAW: outframe = e.anim_draw; break;
+ case ANIMACTION_PAIN1: outframe = e.anim_pain1; break;
+ case ANIMACTION_PAIN2: outframe = e.anim_pain2; break;
+ case ANIMACTION_SHOOT: outframe = e.anim_shoot; break;
+ case ANIMACTION_TAUNT: outframe = e.anim_taunt; break;
+ case ANIMACTION_MELEE: outframe = e.anim_melee; break;
+ }
+ if(outframe_x >= 0)
+ {
+ if(time <= t + outframe_y / outframe_z)
+ {
+ // animation is running!
+ return vec3(outframe_x, t, ANIMPRIO_ACTIVE);
+ }
+ }
+ // or, decide the anim by state
+ t = max(e.anim_time, e.anim_implicit_time);
+ // but all states are for lower body!
+ return vec3(e.anim_idle_x, t, ANIMPRIO_IDLE);
+}
+
+vector animdecide_getloweranim(entity e)
+{
+ // death etc.
+ if(e.anim_state & ANIMSTATE_FROZEN)
+ return vec3(e.anim_idle_x, e.anim_time, ANIMPRIO_DEAD);
+ if(e.anim_state & ANIMSTATE_DEAD1)
+ return vec3(e.anim_die1_x, e.anim_time, ANIMPRIO_DEAD);
+ if(e.anim_state & ANIMSTATE_DEAD2)
+ return vec3(e.anim_die2_x, e.anim_time, ANIMPRIO_DEAD);
+
+ // is there an action?
+ vector outframe = '-1 0 0';
+ float t, a;
+ if(e.anim_lower_time >= e.anim_lower_implicit_time)
+ {
+ a = e.anim_lower_action;
+ t = e.anim_lower_time;
+ }
+ else
+ {
+ a = e.anim_lower_implicit_action;
+ t = e.anim_lower_implicit_time;
+ }
+ switch(a)
+ {
+ case ANIMACTION_JUMP: if(e.anim_implicit_state & ANIMIMPLICITSTATE_INAIR) { if(e.anim_state & ANIMSTATE_DUCK) outframe = e.anim_duckjump; else outframe = e.anim_jump; } break;
+ }
+ if(outframe_x >= 0)
+ {
+ if(time <= t + outframe_y / outframe_z)
+ {
+ // animation is running!
+ return vec3(outframe_x, t, ANIMPRIO_ACTIVE);
+ }
+ }
+ // or, decide the anim by state
+ t = max(e.anim_time, e.anim_implicit_time);
+ if(e.anim_state & ANIMSTATE_DUCK)
+ {
+ if(e.anim_implicit_state & ANIMIMPLICITSTATE_INAIR)
+ return vec3(e.anim_duckjump_x, 0, ANIMPRIO_CROUCH); // play the END of the jump anim
+ else switch(e.anim_implicit_state & (ANIMIMPLICITSTATE_FORWARD | ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_LEFT | ANIMIMPLICITSTATE_RIGHT))
+ {
+ case ANIMIMPLICITSTATE_FORWARD:
+ return vec3(e.anim_duckwalk_x, t, ANIMPRIO_CROUCH);
+ case ANIMIMPLICITSTATE_BACKWARDS:
+ return vec3(e.anim_duckwalkbackwards_x, t, ANIMPRIO_CROUCH);
+ case ANIMIMPLICITSTATE_RIGHT:
+ return vec3(e.anim_duckwalkstraferight_x, t, ANIMPRIO_CROUCH);
+ case ANIMIMPLICITSTATE_LEFT:
+ return vec3(e.anim_duckwalkstrafeleft_x, t, ANIMPRIO_CROUCH);
+ case ANIMIMPLICITSTATE_FORWARD | ANIMIMPLICITSTATE_RIGHT:
+ return vec3(e.anim_duckwalkforwardright_x, t, ANIMPRIO_CROUCH);
+ case ANIMIMPLICITSTATE_FORWARD | ANIMIMPLICITSTATE_LEFT:
+ return vec3(e.anim_duckwalkforwardleft_x, t, ANIMPRIO_CROUCH);
+ case ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_RIGHT:
+ return vec3(e.anim_duckwalkbackright_x, t, ANIMPRIO_CROUCH);
+ case ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_LEFT:
+ return vec3(e.anim_duckwalkbackleft_x, t, ANIMPRIO_CROUCH);
+ default:
+ return vec3(e.anim_duckidle_x, t, ANIMPRIO_CROUCH);
+ }
+ }
+ else
+ {
+ if(e.anim_implicit_state & ANIMIMPLICITSTATE_INAIR)
+ return vec3(e.anim_jump_x, 0, ANIMPRIO_ACTIVE); // play the END of the jump anim
+ else switch(e.anim_implicit_state & (ANIMIMPLICITSTATE_FORWARD | ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_LEFT | ANIMIMPLICITSTATE_RIGHT))
+ {
+ case ANIMIMPLICITSTATE_FORWARD:
+ return vec3(e.anim_run_x, t, ANIMPRIO_ACTIVE);
+ case ANIMIMPLICITSTATE_BACKWARDS:
+ return vec3(e.anim_runbackwards_x, t, ANIMPRIO_ACTIVE);
+ case ANIMIMPLICITSTATE_RIGHT:
+ return vec3(e.anim_straferight_x, t, ANIMPRIO_ACTIVE);
+ case ANIMIMPLICITSTATE_LEFT:
+ return vec3(e.anim_strafeleft_x, t, ANIMPRIO_ACTIVE);
+ case ANIMIMPLICITSTATE_FORWARD | ANIMIMPLICITSTATE_RIGHT:
+ return vec3(e.anim_forwardright_x, t, ANIMPRIO_ACTIVE);
+ case ANIMIMPLICITSTATE_FORWARD | ANIMIMPLICITSTATE_LEFT:
+ return vec3(e.anim_forwardleft_x, t, ANIMPRIO_ACTIVE);
+ case ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_RIGHT:
+ return vec3(e.anim_backright_x, t, ANIMPRIO_ACTIVE);
+ case ANIMIMPLICITSTATE_BACKWARDS | ANIMIMPLICITSTATE_LEFT:
+ return vec3(e.anim_backleft_x, t, ANIMPRIO_ACTIVE);
+ default:
+ return vec3(e.anim_idle_x, t, ANIMPRIO_IDLE);
+ }
+ }
+ // can't get here
+#ifdef GMQCC
+ return vec3(e.anim_idle_x, t, ANIMPRIO_IDLE);
+#endif
+}
+
+void animdecide_setimplicitstate(entity e, float onground)
+{
+ float s;
+ s = 0;
+
+ makevectors(e.angles);
+ vector v;
+ v_x = e.velocity * v_forward;
+ v_y = e.velocity * v_right;
+ v_z = 0;
+
+ // we want to match like this:
+ // the 8 directions shall be "evenly spaced"
+ // that means, the forward key includes anything from -67.5 to +67.5 degrees
+ // which then means x > |y| * cot(3pi/8)
+ //
+ // BUT, the engine's clip-movement-to-keyboard function uses 0.5 here,
+ // which would be an angle range from -63.43 to +63.43 degrees, making
+ // it slightly less likely to "hit two keys at once", so let's do this
+ // here too
+
+ if(vlen(v) > 10)
+ {
+ if(v_x > fabs(v_y) * 0.5)
+ s |= ANIMIMPLICITSTATE_FORWARD;
+ if(v_x < -fabs(v_y) * 0.5)
+ s |= ANIMIMPLICITSTATE_BACKWARDS;
+ if(v_y > fabs(v_x) * 0.5)
+ s |= ANIMIMPLICITSTATE_RIGHT;
+ if(v_y < -fabs(v_x) * 0.5)
+ s |= ANIMIMPLICITSTATE_LEFT;
+ }
+ if(!onground)
+ s |= ANIMIMPLICITSTATE_INAIR;
+
+ // detect some kinds of otherwise misdetected jumps (ground to air transition)
+ // NOTE: currently, in CSQC this is the only jump detection, as the explicit jump action is never called!
+ if(!(e.anim_implicit_state & ANIMIMPLICITSTATE_INAIR) && (s & ANIMIMPLICITSTATE_INAIR))
+ {
+ e.anim_lower_implicit_action = ANIMACTION_JUMP;
+ e.anim_lower_implicit_time = time;
+ }
+
+ if(s != e.anim_implicit_state)
+ {
+ e.anim_implicit_state = s;
+ e.anim_implicit_time = time;
+ }
+}
+void animdecide_setframes(entity e, float support_blending, .float fld_frame, .float fld_frame1time, .float fld_frame2, .float fld_frame2time)
+{
+ // _x: frame
+ // _y: start time
+ // _z: priority
+ vector upper = animdecide_getupperanim(e);
+ vector lower = animdecide_getloweranim(e);
+ //print("UPPER: ", vtos(upper), ", LOWER: ", vtos(lower), "\n");
+ if(support_blending)
+ {
+ if(upper_z && !lower_z)
+ lower = upper;
+ else if(lower_z && !upper_z)
+ upper = lower;
+ if(e.frame1time != upper_y || e.frame2time != lower_y)
+ BITXOR_ASSIGN(e.effects, EF_RESTARTANIM_BIT);
+ e.fld_frame = upper_x;
+ e.fld_frame1time = upper_y;
+ e.fld_frame2 = lower_x;
+ e.fld_frame2time = lower_y;
+ }
+ else
+ {
+ if(upper_z > lower_z)
+ lower = upper;
+ else if(lower_z > upper_z)
+ upper = lower;
+ if(e.frame1time != upper_y)
+ BITXOR_ASSIGN(e.effects, EF_RESTARTANIM_BIT);
+ e.fld_frame = upper_x;
+ e.fld_frame1time = upper_y;
+ }
+}
+
+void animdecide_setstate(entity e, float newstate, float restart)
+{
+ if(!restart)
+ if(newstate == e.anim_state)
+ return;
+ e.anim_state = newstate;
+ e.anim_time = time;
+}
+void animdecide_setaction(entity e, float action, float restart)
+{
+ if(action < 0)
+ {
+ if(!restart)
+ if(action == e.anim_lower_action)
+ return;
+ e.anim_lower_action = action;
+ e.anim_lower_time = time;
+ }
+ else
+ {
+ if(!restart)
+ if(action == e.anim_upper_action)
+ return;
+ e.anim_upper_action = action;
+ e.anim_upper_time = time;
+ }
+}
--- /dev/null
+// client side frame inferring
+void animdecide_init(entity e);
+
+void animdecide_setimplicitstate(entity e, float onground);
+void animdecide_setframes(entity e, float support_blending, .float fld_frame, .float fld_frame1time, .float fld_frame2, .float fld_frame2time);
+
+// please network this one
+.float anim_state;
+.float anim_time;
+.float anim_lower_action;
+.float anim_lower_time;
+.float anim_upper_action;
+.float anim_upper_time;
+
+// when copying entities, copy these too
+.float anim_implicit_state;
+.float anim_implicit_time;
+.float anim_lower_implicit_action;
+.float anim_lower_implicit_time;
+.float anim_upper_implicit_action;
+.float anim_upper_implicit_time;
+
+// explicit anim states (networked)
+void animdecide_setstate(entity e, float newstate, float restart);
+#define ANIMSTATE_DEAD1 1 // base frames: die1
+#define ANIMSTATE_DEAD2 2 // base frames: die2
+#define ANIMSTATE_DUCK 4 // turns walk into duckwalk, jump into duckjump, etc.
+#define ANIMSTATE_FROZEN 8 // force idle
+
+// implicit anim states (inferred from velocity, etc.)
+#define ANIMIMPLICITSTATE_INAIR 1
+#define ANIMIMPLICITSTATE_FORWARD 2
+#define ANIMIMPLICITSTATE_BACKWARDS 4
+#define ANIMIMPLICITSTATE_LEFT 8
+#define ANIMIMPLICITSTATE_RIGHT 16
+#define ANIMIMPLICITSTATE_JUMPRELEASED 32
+
+// explicit actions (networked); negative values are for lower body
+void animdecide_setaction(entity e, float action, float restart);
+#define ANIMACTION_JUMP -1 // jump
+#define ANIMACTION_DRAW 1 // draw
+#define ANIMACTION_PAIN1 2 // pain
+#define ANIMACTION_PAIN2 3 // pain
+#define ANIMACTION_SHOOT 4 // shoot
+#define ANIMACTION_TAUNT 5 // taunt
+#define ANIMACTION_MELEE 6 // melee
cvar_set(do_cvar, data);
strunzone(do_cvar);
}
- if(!do_exec && !do_cvar)
- print(data);
+ if(!do_exec)
+ if not(do_cvar)
+ print(data);
}
print("Incorrect parameters for ^2addtolist^7\n");
case CMD_REQUEST_USAGE:
{
- print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " addtolist variable value"));
+ print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " addtolist variable value\n"));
print(" Where 'variable' is what to add 'value' to.\n");
print("See also: ^2removefromlist^7\n");
return;
}
}
-void GenericCommand_curl(float request, float argc)
+void GenericCommand_qc_curl(float request, float argc)
{
switch(request)
{
default:
case CMD_REQUEST_USAGE:
{
- print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " curl [--key N] [--cvar] [--exec] URL [postargs...]"));
+ print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " qc_curl [--key N] [--cvar] [--exec] URL [postargs...]"));
return;
}
}
}
}
+void GenericCommand_dumpnotifs(float request)
+{
+ switch(request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ #ifndef MENUQC
+ float fh, alsoprint = FALSE;
+ string filename = argv(1);
+
+ if(filename == "")
+ {
+ filename = "notifications.cfg";
+ alsoprint = FALSE;
+ }
+ else if(filename == "-")
+ {
+ filename = "notifications.cfg";
+ alsoprint = TRUE;
+ }
+ fh = fopen(filename, FILE_WRITE);
+
+ if(fh >= 0)
+ {
+ Dump_Notifications(fh, alsoprint);
+ print(sprintf("Dumping notifications... File located in ^2data/data/%s^7.\n", filename));
+ fclose(fh);
+ }
+ else
+ {
+ print(sprintf("^1Error: ^7Could not open file '%s'!\n", filename));
+ }
+ #else
+ print(_("Notification dump command only works with cl_cmd and sv_cmd.\n"));
+ #endif
+ return;
+ }
+
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " dumpnotifs [filename]"));
+ print(" Where 'filename' is the file to write (default is notifications.cfg),\n");
+ print(" if supplied with '-' output to console as well as default,\n");
+ print(" if left blank, it will only write to default.\n");
+ return;
+ }
+ }
+}
+
void GenericCommand_maplist(float request, float argc)
{
switch(request)
print("Incorrect parameters for ^2maplist^7\n");
case CMD_REQUEST_USAGE:
{
- print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " maplist action [map]"));
+ print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " maplist action [map]\n"));
print(" Where 'action' is the command to complete,\n");
print(" and 'map' is what it acts upon (if required).\n");
print(" Full list of commands here: \"add, cleanup, remove, shuffle.\"\n");
default:
case CMD_REQUEST_USAGE:
{
- print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " nextframe command..."));
+ print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " nextframe command...\n"));
print(" Where command will be executed next frame of this VM\n");
return;
}
print("Incorrect parameters for ^2removefromlist^7\n");
case CMD_REQUEST_USAGE:
{
- print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " removefromlist variable value"));
+ print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " removefromlist variable value\n"));
print(" Where 'variable' is what cvar to remove 'value' from.\n");
print("See also: ^2addtolist^7\n");
return;
}
}
+void GenericCommand_restartnotifs(float request)
+{
+ switch(request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ #ifndef MENUQC
+ print(sprintf(
+ strcat(
+ "Restart_Notifications(): Restarting %d notifications... ",
+ "Counts: MSG_INFO = %d, MSG_CENTER = %d, MSG_MULTI = %d\n"
+ ),
+ (
+ NOTIF_INFO_COUNT +
+ NOTIF_CENTER_COUNT +
+ NOTIF_MULTI_COUNT
+ ),
+ NOTIF_INFO_COUNT,
+ NOTIF_CENTER_COUNT,
+ NOTIF_MULTI_COUNT
+ ));
+ Destroy_All_Notifications();
+ CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
+ #else
+ print(_("Notification restart command only works with cl_cmd and sv_cmd.\n"));
+ #endif
+ return;
+ }
+
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " restartnotifs"));
+ print(" No arguments required.\n");
+ return;
+ }
+ }
+}
+
void GenericCommand_settemp(float request, float argc)
{
switch(request)
{
if(argc >= 3)
{
- if(cvar_settemp(argv(1), argv(2)))
+ float f = cvar_settemp(argv(1), argv(2));
+ if(f == 1)
dprint("Creating new settemp tracker for ", argv(1), " and setting it to \"", argv(2), "\" temporarily.\n");
- else
+ else if(f == -1)
dprint("Already had a tracker for ", argv(1), ", updating it to \"", argv(2), "\".\n");
-
+ // else cvar_settemp itself errors out
+
return;
}
}
-
+
default:
print("Incorrect parameters for ^2settemp^7\n");
case CMD_REQUEST_USAGE:
// Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;)
#define GENERIC_COMMANDS(request,arguments,command) \
GENERIC_COMMAND("addtolist", GenericCommand_addtolist(request, arguments), "Add a string to a cvar") \
- GENERIC_COMMAND("curl", GenericCommand_curl(request, arguments), "Queries an URL") \
GENERIC_COMMAND("dumpcommands", GenericCommand_dumpcommands(request), "Dump all commands on the program to *_cmd_dump.txt") \
+ GENERIC_COMMAND("dumpnotifs", GenericCommand_dumpnotifs(request), "Dump all notifications into notifications_dump.txt") \
GENERIC_COMMAND("maplist", GenericCommand_maplist(request, arguments), "Automatic control of maplist") \
GENERIC_COMMAND("nextframe", GenericCommand_nextframe(request, arguments, command), "Execute the given command next frame of this VM") \
+ GENERIC_COMMAND("qc_curl", GenericCommand_qc_curl(request, arguments), "Queries a URL") \
GENERIC_COMMAND("removefromlist", GenericCommand_removefromlist(request, arguments), "Remove a string from a cvar") \
+ GENERIC_COMMAND("restartnotifs", GenericCommand_restartnotifs(request), "Re-initialize all notifications") \
GENERIC_COMMAND("rpn", GenericCommand_rpn(request, arguments, command), "RPN calculator") \
GENERIC_COMMAND("settemp", GenericCommand_settemp(request, arguments), "Temporarily set a value to a cvar which is restored later") \
GENERIC_COMMAND("settemp_restore", GenericCommand_settemp_restore(request, arguments), "Restore all cvars set by settemp command") \
void Curl_URI_Get_Callback(float id, float status, string data);
float curl_uri_get_pos;
float curl_uri_get_exec[URI_GET_CURL_END - URI_GET_CURL + 1];
-string curl_uri_get_cvar[URI_GET_CURL_END - URI_GET_CURL + 1];
\ No newline at end of file
+string curl_uri_get_cvar[URI_GET_CURL_END - URI_GET_CURL + 1];
float rpn_db;
float rpn_error;
float rpn_sp;
-string rpn_stack[MAX_RPN_STACK];
\ No newline at end of file
+string rpn_stack[MAX_RPN_STACK];
const float TE_CSQC_LIGHTNINGARC = 105;
const float TE_CSQC_TEAMNAGGER = 106;
const float TE_CSQC_PINGPLREPORT = 107;
-const float TE_CSQC_ANNOUNCE = 110;
-const float TE_CSQC_TARGET_MUSIC = 111;
-const float TE_CSQC_KILLNOTIFY = 112;
-const float TE_CSQC_KILLCENTERPRINT = 113;
-const float TE_CSQC_CENTERPRINT_GENERIC = 114;
-const float TE_CSQC_WEAPONCOMPLAIN = 115;
-const float TE_CSQC_NEX_SCOPE = 116;
-const float TE_CSQC_MINELAYER_MAXMINES = 117;
-const float TE_CSQC_HAGAR_MAXROCKETS = 118;
-const float TE_CSQC_VEHICLESETUP = 119;
-const float TE_CSQC_SVNOTICE = 120;
+const float TE_CSQC_ANNOUNCE = 108;
+const float TE_CSQC_TARGET_MUSIC = 109;
+const float TE_CSQC_WEAPONCOMPLAIN = 110;
+const float TE_CSQC_NEX_SCOPE = 111;
+const float TE_CSQC_MINELAYER_MAXMINES = 112;
+const float TE_CSQC_HAGAR_MAXROCKETS = 113;
+const float TE_CSQC_VEHICLESETUP = 114;
+const float TE_CSQC_SVNOTICE = 115;
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_MODEL = 33;
const float ENT_CLIENT_ITEM = 34;
const float ENT_CLIENT_BUMBLE_RAYGUN = 35;
+const float ENT_CLIENT_NOTIFICATION = 36;
const float ENT_CLIENT_TURRET = 40;
const float ENT_CLIENT_AUXILIARYXHAIR = 50;
const float STAT_SECRETS_TOTAL = 70;
const float STAT_SECRETS_FOUND = 71;
+const float STAT_RESPAWN_TIME = 72;
+
const float STAT_ARMOR_LARGE_TIME = 80;
const float STAT_HEALTH_MEGA_TIME = 81;
const float STAT_INVISIBLE_TIME = 82;
const float STAT_FUELREGEN_TIME = 87;
const float STAT_JETPACK_TIME = 88;
const float STAT_SUPERWEAPONS_TIME = 89;
-
// mod stats (1xx)
const float STAT_REDALIVE = 100;
const float STAT_BLUEALIVE = 101;
float SPECIES_ROBOT_SHINY = 5;
float SPECIES_RESERVED = 15;
-// Deathtypes (weapon deathtypes are the IT_* constants below)
-// NOTE: when adding death types, please add an explanation to Docs/spamlog.txt too.
-float DEATH_SPECIAL_START = 10000;
-float DEATH_FALL = 10000;
-float DEATH_TELEFRAG = 10001;
-float DEATH_DROWN = 10002;
-float DEATH_HURTTRIGGER = 10003;
-float DEATH_LAVA = 10004;
-float DEATH_SLIME = 10005;
-float DEATH_KILL = 10006;
-float DEATH_NOAMMO = 10007;
-float DEATH_SWAMP = 10008;
-float DEATH_TEAMCHANGE = 10009;
-float DEATH_AUTOTEAMCHANGE = 10010;
-float DEATH_CAMP = 10011;
-float DEATH_SHOOTING_STAR = 10012;
-float DEATH_ROT = 10013;
-float DEATH_MIRRORDAMAGE = 10014;
-float DEATH_TOUCHEXPLODE = 10015;
-float DEATH_CHEAT = 10016;
-float DEATH_FIRE = 10017;
-float DEATH_QUIET = 10021;
-
-float DEATH_VHFIRST = 10030;
-float DEATH_VHCRUSH = 10030;
-float DEATH_SBMINIGUN = 10031;
-float DEATH_SBROCKET = 10032;
-float DEATH_SBBLOWUP = 10033;
-float DEATH_WAKIGUN = 10034;
-float DEATH_WAKIROCKET = 10035;
-float DEATH_WAKIBLOWUP = 10036;
-float DEATH_RAPTOR_CANNON = 10037;
-float DEATH_RAPTOR_BOMB = 10038;
-float DEATH_RAPTOR_BOMB_SPLIT = 10039;
-float DEATH_RAPTOR_DEATH = 10040;
-float DEATH_BUMB_GUN = 10041;
-float DEATH_BUMB_RAY = 10042;
-float DEATH_BUMB_RAY_HEAL = 10043;
-float DEATH_BUMB_DEATH = 10044;
-float DEATH_VHLAST = 10044;
-#define DEATH_ISVEHICLE(t) ((t) >= DEATH_VHFIRST && (t) <= DEATH_VHLAST)
-
-float DEATH_GENERIC = 10050;
-
-float DEATH_WEAPON = 10100;
-
-float DEATH_CUSTOM = 10300;
-
-float DEATH_TURRET = 10500;
-float DEATH_TURRET_EWHEEL = 10501;
-float DEATH_TURRET_FLAC = 10502;
-float DEATH_TURRET_MACHINEGUN = 10503;
-float DEATH_TURRET_WALKER_GUN = 10504;
-float DEATH_TURRET_WALKER_MEELE = 10505;
-float DEATH_TURRET_WALKER_ROCKET = 10506;
-float DEATH_TURRET_HELLION = 10507;
-float DEATH_TURRET_HK = 10508;
-float DEATH_TURRET_MLRS = 10509;
-float DEATH_TURRET_PLASMA = 10510;
-float DEATH_TURRET_PHASER = 10511;
-float DEATH_TURRET_TESLA = 10512;
-float DEATH_TURRET_LAST = 10512;
-
-float DEATH_WEAPONMASK = 0xFF;
-float DEATH_HITTYPEMASK = 0x1F00; // which is WAY below 10000 used for normal deaths
-float HITTYPE_SECONDARY = 0x100;
-float HITTYPE_SPLASH = 0x200; // automatically set by RadiusDamage
-float HITTYPE_BOUNCE = 0x400;
-float HITTYPE_HEADSHOT = 0x800; // automatically set by Damage (if headshotbonus is set)
-float HITTYPE_RESERVED = 0x1000; // unused yet
-
-// macros to access these
-#define DEATH_ISTURRET(t) ((t) >= DEATH_TURRET && (t) <= DEATH_TURRET_LAST)
-#define DEATH_ISSPECIAL(t) ((t) >= DEATH_SPECIAL_START)
-#define DEATH_WEAPONOFWEAPONDEATH(t) ((t) & DEATH_WEAPONMASK)
-#define DEATH_ISWEAPON(t,w) (!DEATH_ISSPECIAL(t) && DEATH_WEAPONOFWEAPONDEATH(t) == (w))
-#define DEATH_WEAPONOF(t) (DEATH_ISSPECIAL(t) ? 0 : DEATH_WEAPONOFWEAPONDEATH(t))
-#define WEP_VALID(w) ((w) >= WEP_FIRST && (w) <= WEP_LAST)
-
#define FRAGS_PLAYER 0
#define FRAGS_SPECTATOR -666
#define FRAGS_LMS_LOSER -616
float MAX_SHOT_DISTANCE = 32768;
-//centerprint ID list
-float CPID_TEAMCHANGE = 1;
-float CPID_CTF_CAPTURESHIELD = 2;
-float CPID_MINSTA_FINDAMMO = 3;
-float CPID_NIX_WPNCHANGE = 4;
-float CPID_DISCONNECT_IDLING = 5;
-float CPID_ROUND_STARTING = 6;
-float CPID_GAME_STARTING = 7;
-float CPID_TIMEOUT_COUNTDOWN = 8;
-float CPID_MOTD = 9;
-float CPID_KH_MSG = 10;
-float CPID_PREVENT_JOIN = 11;
-
-// CSQC centerprint/notify message types
-float MSG_SUICIDE = 0;
-float MSG_KILL = 1;
-float MSG_SPREE = 2;
-float MSG_KILL_ACTION = 3;
-float MSG_KILL_ACTION_SPREE = 4;
-float MSG_INFO = 5;
-float MSG_KA = 6;
-float MSG_RACE = 10;
-
-float KILL_TEAM_RED = 12001;
-float KILL_TEAM_BLUE = 12002;
-float KILL_TEAM_SPREE = 12003;
-float KILL_FIRST_BLOOD = 12004;
-float KILL_FIRST_VICTIM = 12005;
-float KILL_TYPEFRAG = 12006;
-float KILL_TYPEFRAGGED = 12007;
-float KILL_FRAG = 12008;
-float KILL_FRAGGED = 12009;
-float KILL_SPREE = 12010;
-float KILL_END_SPREE = 12011;
-float KILL_SPREE_3 = 12012;
-float KILL_SPREE_5 = 12013;
-float KILL_SPREE_10 = 12014;
-float KILL_SPREE_15 = 12015;
-float KILL_SPREE_20 = 12016;
-float KILL_SPREE_25 = 12017;
-float KILL_SPREE_30 = 12018;
-
-float INFO_GOTFLAG = 13001;
-float INFO_PICKUPFLAG = 13002;
-float INFO_LOSTFLAG = 13003;
-float INFO_RETURNFLAG = 13004;
-float INFO_CAPTUREFLAG = 13005;
-
-float KA_PICKUPBALL = 14001;
-float KA_DROPBALL = 14002;
-
-float RACE_SERVER_RECORD = 15001;
-float RACE_NEW_TIME = 15002;
-float RACE_NEW_RANK = 15003;
-float RACE_FAIL = 15004;
-
// weapon requests
float WR_SETUP = 1; // (SVQC) setup weapon data
float WR_THINK = 2; // (SVQC) logic to run every frame
float WR_CHECKAMMO2 = 4; // (SVQC) checks ammo for weapon
float WR_AIM = 5; // (SVQC) runs bot aiming code for this weapon
float WR_PRECACHE = 6; // (CSQC and SVQC) precaches models/sounds used by this weapon
-float WR_SUICIDEMESSAGE = 7; // (CSQC) sets w_deathtypestring or leaves it alone (and may inspect w_deathtype for details)
-float WR_KILLMESSAGE = 8; // (CSQC) sets w_deathtypestring or leaves it alone
+float WR_SUICIDEMESSAGE = 7; // (SVQC) notification number for suicide message (may inspect w_deathtype for details)
+float WR_KILLMESSAGE = 8; // (SVQC) notification number for kill message (may inspect w_deathtype for details)
float WR_RELOAD = 9; // (SVQC) does not need to do anything
float WR_RESETPLAYER = 10; // (SVQC) does not need to do anything
float WR_IMPACTEFFECT = 11; // (CSQC) impact effect
--- /dev/null
+// ===============================================
+// Time processing and counting functions/macros
+// ===============================================
+
+#define count_years_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s years")), ftos_decimals(time, decs))
+#define count_years(time) count_fill(time, \
+ ZCTX(_("CI_ZER^%d years")), /* zeroth */ \
+ ZCTX(_("CI_FIR^%d year")), /* first */ \
+ ZCTX(_("CI_SEC^%d years")), /* year */ \
+ ZCTX(_("CI_THI^%d years")), /* third */ \
+ ZCTX(_("CI_MUL^%d years"))) /* multi */
+
+#define count_weeks_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s weeks")), ftos_decimals(time, decs))
+#define count_weeks(time) count_fill(time, \
+ ZCTX(_("CI_ZER^%d weeks")), /* zeroth */ \
+ ZCTX(_("CI_FIR^%d week")), /* first */ \
+ ZCTX(_("CI_SEC^%d weeks")), /* week */ \
+ ZCTX(_("CI_THI^%d weeks")), /* third */ \
+ ZCTX(_("CI_MUL^%d weeks"))) /* multi */
+
+#define count_days_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s days")), ftos_decimals(time, decs))
+#define count_days(time) count_fill(time, \
+ ZCTX(_("CI_ZER^%d days")), /* zeroth */ \
+ ZCTX(_("CI_FIR^%d day")), /* first */ \
+ ZCTX(_("CI_SEC^%d days")), /* day */ \
+ ZCTX(_("CI_THI^%d days")), /* third */ \
+ ZCTX(_("CI_MUL^%d days"))) /* multi */
+
+#define count_hours_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s hours")), ftos_decimals(time, decs))
+#define count_hours(time) count_fill(time, \
+ ZCTX(_("CI_ZER^%d hours")), /* zeroth */ \
+ ZCTX(_("CI_FIR^%d hour")), /* first */ \
+ ZCTX(_("CI_SEC^%d hours")), /* hour */ \
+ ZCTX(_("CI_THI^%d hours")), /* third */ \
+ ZCTX(_("CI_MUL^%d hours"))) /* multi */
+
+
+#define count_minutes_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s minutes")), ftos_decimals(time, decs))
+#define count_minutes(time) count_fill(time, \
+ ZCTX(_("CI_ZER^%d minutes")), /* zeroth */ \
+ ZCTX(_("CI_FIR^%d minute")), /* first */ \
+ ZCTX(_("CI_SEC^%d minutes")), /* minute */ \
+ ZCTX(_("CI_THI^%d minutes")), /* third */ \
+ ZCTX(_("CI_MUL^%d minutes"))) /* multi */
+
+#define count_seconds_decs(time,decs) sprintf(ZCTX(_("CI_DEC^%s seconds")), ftos_decimals(time, decs))
+#define count_seconds(time) count_fill(time, \
+ ZCTX(_("CI_ZER^%d seconds")), /* zeroth */ \
+ ZCTX(_("CI_FIR^%d second")), /* first */ \
+ ZCTX(_("CI_SEC^%d seconds")), /* second */ \
+ ZCTX(_("CI_THI^%d seconds")), /* third */ \
+ ZCTX(_("CI_MUL^%d seconds"))) /* multi */
+
+string count_ordinal(float interval)
+{
+ // This function is designed primarily for the English language, it's impossible
+ // to accomodate all languages unless we do a specific function for each one...
+ // and since that's not technically feasible/practical, this is all we've got folks.
+
+ // Basically, it just allows you to represent a number or count in different ways
+ // depending on the number... like, with count_ordinal you can provide integers
+ // and retrieve 1st, 2nd, 3rd, nth ordinal numbers in a clean and simple way.
+ if(floor((mod(interval, 100))/10) * 10 != 10) // examples: 12th, 111th, 213th will not execute this block
+ {
+ // otherwise, check normally for 1st,2nd,3rd insertions
+ switch(mod(interval, 10))
+ {
+ case 1: return sprintf(_("%dst"), interval);
+ case 2: return sprintf(_("%dnd"), interval);
+ case 3: return sprintf(_("%drd"), interval);
+ default: return sprintf(_("%dth"), interval);
+ }
+ }
+ else { return sprintf(_("%dth"), interval); }
+
+ return "";
+}
+
+string count_fill(float interval, string zeroth, string first, string second, string third, string multi)
+{
+ // This function is designed primarily for the English language, it's impossible
+ // to accomodate all languages unless we do a specific function for each one...
+ // and since that's not technically feasible/practical, this is all we've got folks.
+
+ // Here you can insert specific strings based on the interval number, so you could do
+ // i.e. count_seconds which outputs like this:
+ // 0 seconds
+ // 1 second
+ // 2 seconds
+ // 3 seconds
+ // etc... minutes, hours, days, etc.
+
+ switch(floor(interval))
+ {
+ case 0: return sprintf(zeroth, interval);
+ case 1:
+ {
+ if(interval == 1) // EXACTLY value of 1
+ return sprintf(first, interval);
+ else
+ return sprintf(multi, interval);
+ }
+ case 2: return sprintf(second, interval);
+ case 3: return sprintf(third, interval);
+ default: return sprintf(multi, interval);
+ }
+ return "";
+}
+
+string process_time(float outputtype, float seconds)
+{
+ float tmp_hours = 0, tmp_minutes = 0, tmp_seconds = 0;
+ float tmp_years = 0, tmp_weeks = 0, tmp_days = 0;
+
+ tmp_seconds = floor(seconds);
+
+ if(tmp_seconds)
+ {
+ tmp_minutes = floor(tmp_seconds / 60);
+
+ if(tmp_minutes)
+ {
+ tmp_seconds -= (tmp_minutes * 60);
+ tmp_hours = floor(tmp_minutes / 60);
+
+ if(tmp_hours)
+ {
+ tmp_minutes -= (tmp_hours * 60);
+ tmp_days = floor(tmp_hours / 24);
+
+ if(tmp_days)
+ {
+ tmp_hours -= (tmp_days * 24);
+ tmp_weeks = floor(tmp_days / 7);
+
+ if(tmp_weeks)
+ {
+ tmp_days -= (tmp_weeks * 7);
+ tmp_years = floor(tmp_weeks / 52);
+ }
+ }
+ }
+ }
+ }
+
+ switch(outputtype)
+ {
+ case 1: return sprintf("%02d:%02d:%02d", tmp_hours, tmp_minutes, tmp_seconds);
+ case 2:
+ {
+ string output = "";
+
+ output = count_seconds(tmp_seconds);
+
+ if(tmp_minutes)
+ {
+ output = sprintf(
+ "%s%s",
+ count_minutes(tmp_minutes),
+ ((output != "") ? sprintf(", %s", output) : ""));
+ }
+
+ if(tmp_hours)
+ {
+ output = sprintf(
+ "%s%s",
+ count_hours(tmp_hours),
+ ((output != "") ? sprintf(", %s", output) : ""));
+ }
+
+ if(tmp_days)
+ {
+ output = sprintf(
+ "%s%s",
+ count_days(tmp_days),
+ ((output != "") ? sprintf(", %s", output) : ""));
+ }
+
+ if(tmp_weeks)
+ {
+ output = sprintf(
+ "%s%s",
+ count_weeks(tmp_weeks),
+ ((output != "") ? sprintf(", %s", output) : ""));
+ }
+
+ if(tmp_years)
+ {
+ output = sprintf(
+ "%s%s",
+ count_years(tmp_years),
+ ((output != "") ? sprintf(", %s", output) : ""));
+ }
+
+ return output;
+ }
+ }
+ return "";
+}
// define this if svqc code wants to use .frame2 and .lerpfrac
-#define CSQCMODEL_HAVE_TWO_FRAMES
+//#define CSQCMODEL_HAVE_TWO_FRAMES
// don't define this ever
//#define CSQCMODEL_SUPPORT_GETTAGINFO_BEFORE_DRAW
+// server decides crouching, this lags, but so be it
+#define CSQCMODEL_SERVERSIDE_CROUCH
+
// a hack for Xonotic
#ifdef CSQC
# define TAG_ENTITY_NAME tag_networkentity
# define TAG_ENTITY_TYPE entity
#endif
+// new fields
+.vector v_angle;
+
// add properties you want networked to CSQC here
#define CSQCMODEL_EXTRAPROPERTIES \
CSQCMODEL_PROPERTY(1, float, ReadShort, WriteShort, colormap) \
CSQCMODEL_PROPERTY_SCALED(256, float, ReadByte, WriteByte, glowmod_x, 255, 0, 255) \
CSQCMODEL_PROPERTY_SCALED(256, float, ReadByte, WriteByte, glowmod_y, 255, 0, 255) \
CSQCMODEL_PROPERTY_SCALED(256, float, ReadByte, WriteByte, glowmod_z, 255, 0, 255) \
+ CSQCMODEL_ENDIF \
+ CSQCMODEL_IF(isplayer) \
+ CSQCMODEL_PROPERTY(128, float, ReadByte, WriteByte, anim_state) \
+ CSQCMODEL_PROPERTY(128, float, ReadApproxPastTime, WriteApproxPastTime, anim_time) \
+ CSQCMODEL_IF(!islocalplayer) \
+ CSQCMODEL_PROPERTY(256, float, ReadChar, WriteChar, anim_lower_action) \
+ CSQCMODEL_PROPERTY(256, float, ReadApproxPastTime, WriteApproxPastTime, anim_lower_time) \
+ CSQCMODEL_ENDIF \
+ CSQCMODEL_PROPERTY(512, float, ReadChar, WriteChar, anim_upper_action) \
+ CSQCMODEL_PROPERTY(512, float, ReadApproxPastTime, WriteApproxPastTime, anim_upper_time) \
+ CSQCMODEL_PROPERTY(1024, float, ReadAngle, WriteAngle, v_angle_x) \
CSQCMODEL_ENDIF
// TODO get rid of colormod/glowmod here, find good solution for nex charge glowmod hack; also get rid of some useless properties on non-players that only exist for CopyBody
#define CSQCMODEL_HOOK_POSTUPDATE \
CSQCModel_Hook_PostUpdate(isnew, isplayer, islocalplayer);
#define CSQCMODEL_HOOK_PREDRAW \
- CSQCModel_Hook_PreDraw();
+ CSQCModel_Hook_PreDraw(isplayer);
#define CSQCPLAYER_HOOK_POSTCAMERASETUP
// force updates of player entities that often even if unchanged
//vector PL_CROUCH_VIEW_OFS = ...;
#ifdef SVQC
-# ifdef NO_LEGACY_NETWORKING
-# define CSQCMODEL_AUTOINIT() CSQCModel_LinkEntity()
-# define CSQCMODEL_AUTOUPDATE() CSQCModel_CheckUpdate()
-# else
-.float iscsqcmodel;
-float autocvar_sv_use_csqc_players;
-# define CSQCMODEL_AUTOINIT() \
- if(autocvar_sv_use_csqc_players) \
- { \
- CSQCModel_LinkEntity(); \
- self.iscsqcmodel = 1; \
- } \
- else \
- self.iscsqcmodel = 0
-# define CSQCMODEL_AUTOUPDATE() \
- if(autocvar_sv_use_csqc_players && !self.iscsqcmodel) \
- { \
- CSQCModel_LinkEntity(); \
- self.iscsqcmodel = 1; \
- } \
- if(!autocvar_sv_use_csqc_players && self.iscsqcmodel) \
- { \
- CSQCModel_UnlinkEntity(); \
- self.iscsqcmodel = 0; \
- } \
- if(self.iscsqcmodel) \
- CSQCModel_CheckUpdate()
-# endif
+# define CSQCMODEL_AUTOINIT() CSQCModel_LinkEntity()
+# define CSQCMODEL_AUTOUPDATE() CSQCModel_CheckUpdate()
#endif
#define CSQCMODEL_EF_RESPAWNGHOST EF_SELECTABLE
--- /dev/null
+// ================================
+// Deathtypes, reworked by Samual
+// ================================
+
+#define DEATHTYPES \
+ DEATHTYPE(DEATH_AUTOTEAMCHANGE, DEATH_SELF_AUTOTEAMCHANGE, NO_MSG, DEATH_SPECIAL_START) \
+ DEATHTYPE(DEATH_CAMP, DEATH_SELF_CAMP, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_CHEAT, DEATH_SELF_CHEAT, DEATH_MURDER_CHEAT, NORMAL_POS) \
+ DEATHTYPE(DEATH_CUSTOM, DEATH_SELF_CUSTOM, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_DROWN, DEATH_SELF_DROWN, DEATH_MURDER_DROWN, NORMAL_POS) \
+ DEATHTYPE(DEATH_FALL, DEATH_SELF_FALL, DEATH_MURDER_FALL, NORMAL_POS) \
+ DEATHTYPE(DEATH_FIRE, DEATH_SELF_FIRE, DEATH_MURDER_FIRE, NORMAL_POS) \
+ DEATHTYPE(DEATH_GENERIC, DEATH_SELF_GENERIC, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_HURTTRIGGER, DEATH_SELF_VOID, DEATH_MURDER_VOID, NORMAL_POS) \
+ DEATHTYPE(DEATH_KILL, DEATH_SELF_SUICIDE, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_LAVA, DEATH_SELF_LAVA, DEATH_MURDER_LAVA, NORMAL_POS) \
+ DEATHTYPE(DEATH_MIRRORDAMAGE, DEATH_SELF_BETRAYAL, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_NOAMMO, DEATH_SELF_NOAMMO, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_ROT, DEATH_SELF_ROT, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_SHOOTING_STAR, DEATH_SELF_SHOOTING_STAR, DEATH_MURDER_SHOOTING_STAR, NORMAL_POS) \
+ DEATHTYPE(DEATH_SLIME, DEATH_SELF_SLIME, DEATH_MURDER_SLIME, NORMAL_POS) \
+ DEATHTYPE(DEATH_SWAMP, DEATH_SELF_SWAMP, DEATH_MURDER_SWAMP, NORMAL_POS) \
+ DEATHTYPE(DEATH_TEAMCHANGE, DEATH_SELF_TEAMCHANGE, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_TELEFRAG, NO_MSG, DEATH_MURDER_TELEFRAG, NORMAL_POS) \
+ DEATHTYPE(DEATH_TOUCHEXPLODE, DEATH_SELF_TOUCHEXPLODE, DEATH_MURDER_TOUCHEXPLODE, NORMAL_POS) \
+ DEATHTYPE(DEATH_TURRET, DEATH_SELF_TURRET, NO_MSG, DEATH_TURRET_FIRST) \
+ DEATHTYPE(DEATH_TURRET_EWHEEL, DEATH_SELF_TURRET_EWHEEL, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_TURRET_FLAC, DEATH_SELF_TURRET_FLAC, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_TURRET_HELLION, DEATH_SELF_TURRET_HELLION, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_TURRET_HK, DEATH_SELF_TURRET_HK, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_TURRET_MACHINEGUN, DEATH_SELF_TURRET_MACHINEGUN, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_TURRET_MLRS, DEATH_SELF_TURRET_MLRS, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_TURRET_PHASER, DEATH_SELF_TURRET_PHASER, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_TURRET_PLASMA, DEATH_SELF_TURRET_PLASMA, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_TURRET_TESLA, DEATH_SELF_TURRET_TESLA, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_TURRET_WALK_GUN, DEATH_SELF_TURRET_WALK_GUN, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_TURRET_WALK_MEELE, DEATH_SELF_TURRET_WALK_MEELE, NO_MSG, NORMAL_POS) \
+ DEATHTYPE(DEATH_TURRET_WALK_ROCKET, DEATH_SELF_TURRET_WALK_ROCKET, NO_MSG, DEATH_TURRET_LAST) \
+ DEATHTYPE(DEATH_VH_BUMB_DEATH, DEATH_SELF_VH_BUMB_DEATH, DEATH_MURDER_VH_BUMB_DEATH, DEATH_VHFIRST) \
+ DEATHTYPE(DEATH_VH_BUMB_GUN, NO_MSG, DEATH_MURDER_VH_BUMB_GUN, NORMAL_POS) \
+ DEATHTYPE(DEATH_VH_CRUSH, DEATH_SELF_VH_CRUSH, DEATH_MURDER_VH_CRUSH, NORMAL_POS) \
+ DEATHTYPE(DEATH_VH_RAPT_BOMB, DEATH_SELF_VH_RAPT_BOMB, DEATH_MURDER_VH_RAPT_BOMB, NORMAL_POS) \
+ DEATHTYPE(DEATH_VH_RAPT_CANNON, NO_MSG, DEATH_MURDER_VH_RAPT_CANNON, NORMAL_POS) \
+ DEATHTYPE(DEATH_VH_RAPT_DEATH, DEATH_SELF_VH_RAPT_DEATH, DEATH_MURDER_VH_RAPT_DEATH, NORMAL_POS) \
+ DEATHTYPE(DEATH_VH_RAPT_FRAGMENT, DEATH_SELF_VH_RAPT_BOMB, DEATH_MURDER_VH_RAPT_BOMB, NORMAL_POS) \
+ DEATHTYPE(DEATH_VH_SPID_DEATH, DEATH_SELF_VH_SPID_DEATH, DEATH_MURDER_VH_SPID_DEATH, NORMAL_POS) \
+ DEATHTYPE(DEATH_VH_SPID_MINIGUN, NO_MSG, DEATH_MURDER_VH_SPID_MINIGUN, NORMAL_POS) \
+ DEATHTYPE(DEATH_VH_SPID_ROCKET, DEATH_SELF_VH_SPID_ROCKET, DEATH_MURDER_VH_SPID_ROCKET, NORMAL_POS) \
+ DEATHTYPE(DEATH_VH_WAKI_DEATH, DEATH_SELF_VH_WAKI_DEATH, DEATH_MURDER_VH_WAKI_DEATH, NORMAL_POS) \
+ DEATHTYPE(DEATH_VH_WAKI_GUN, NO_MSG, DEATH_MURDER_VH_WAKI_GUN, NORMAL_POS) \
+ DEATHTYPE(DEATH_VH_WAKI_ROCKET, DEATH_SELF_VH_WAKI_ROCKET, DEATH_MURDER_VH_WAKI_ROCKET, DEATH_VHLAST) \
+ DEATHTYPE(DEATH_WEAPON, NO_MSG, NO_MSG, NORMAL_POS)
+
+#define DT_FIRST 10000
+#define DT_MAX 128 // limit of recursive functions with ACCUMULATE_FUNCTION
+float DT_COUNT;
+
+entity deathtypes[DT_MAX];
+.entity death_msgself;
+.entity death_msgmurder;
+
+#define DEATHTYPE(name,msg_death,msg_death_by,position) \
+ float name; \
+ float position; \
+ void RegisterDeathtype_##name() \
+ { \
+ SET_FIRST_OR_LAST(position, DT_FIRST, DT_COUNT) \
+ SET_FIELD_COUNT(name, DT_FIRST, DT_COUNT) \
+ CHECK_MAX_COUNT(name, DT_MAX, DT_COUNT, "deathtypes") \
+ \
+ entity deathent = spawn(); \
+ deathtypes[(name - DT_FIRST) - 1] = deathent; \
+ deathent.classname = "deathtype"; \
+ deathent.nent_name = #name; \
+ #if (msg_death != NO_MSG) \
+ deathent.death_msgself = msg_multi_notifs[msg_death - 1]; \
+ #endif \
+ #if (msg_death_by != NO_MSG) \
+ deathent.death_msgmurder = msg_multi_notifs[msg_death_by - 1]; \
+ #endif \
+ } \
+ ACCUMULATE_FUNCTION(RegisterDeathtypes, RegisterDeathtype_##name)
+
+DEATHTYPES
+#undef DEATHTYPE
+
+#define DEATH_ISSPECIAL(t) ((t) >= DEATH_SPECIAL_START)
+#define DEATH_ISVEHICLE(t) ((t) >= DEATH_VHFIRST && (t) <= DEATH_VHLAST)
+#define DEATH_ISTURRET(t) ((t) >= DEATH_TURRET_FIRST && (t) <= DEATH_TURRET_LAST)
+#define DEATH_WEAPONOFWEAPONDEATH(t) ((t) & DEATH_WEAPONMASK)
+#define DEATH_ISWEAPON(t,w) (!DEATH_ISSPECIAL(t) && DEATH_WEAPONOFWEAPONDEATH(t) == (w))
+#define DEATH_WEAPONOF(t) (DEATH_ISSPECIAL(t) ? 0 : DEATH_WEAPONOFWEAPONDEATH(t))
+#define WEP_VALID(w) ((w) >= WEP_FIRST && (w) <= WEP_LAST)
+
+string Deathtype_Name(float deathtype)
+{
+ if(DEATH_ISSPECIAL(deathtype))
+ {
+ entity deathent = deathtypes[(deathtype - DT_FIRST) - 1];
+ if not(deathent) { backtrace("Deathtype_Name: Could not find deathtype entity!\n"); return ""; }
+ return deathent.nent_name;
+ }
+ else { return ftos(deathtype); }
+}
+
+float DEATH_WEAPONMASK = 0xFF;
+float DEATH_HITTYPEMASK = 0x1F00; // which is WAY below 10000 used for normal deaths
+float HITTYPE_SECONDARY = 0x100;
+float HITTYPE_SPLASH = 0x200; // automatically set by RadiusDamage
+float HITTYPE_BOUNCE = 0x400;
+float HITTYPE_RESERVED2 = 0x800;
+float HITTYPE_RESERVED = 0x1000; // unused yet
}
WEPSET_COPY_EA(e, result);
}
+
+string W_Name(float weaponid)
+{
+ return (get_weaponinfo(weaponid)).message;
+}
+
+float W_AmmoItemCode(float wpn)
+{
+ return (get_weaponinfo(wpn)).items & IT_AMMO;
+}
string W_FixWeaponOrder_ForceComplete(string order);
void W_RandomWeapons(entity e, float n);
+
+string W_Name(float weaponid);
+
+float W_AmmoItemCode(float wpn);
return;
s = db_get(_MapInfo_Cache_DB_NameToIndex, MapInfo_Map_bspname);
- if(!s) // empty string is NOT valid here!
+ if(s == "")
{
i = buf_getsize(_MapInfo_Cache_Buf_IndexToMapData);
db_put(_MapInfo_Cache_DB_NameToIndex, MapInfo_Map_bspname, ftos(i));
return 0;
s = db_get(_MapInfo_Cache_DB_NameToIndex, map);
- if(!s)
+ if(s == "")
return 0;
i = stof(s);
string _MapInfo_GlobItem(float i)
{
string s;
+ if(!_MapInfo_globopen)
+ return string_null;
s = search_getfilename(_MapInfo_globhandle, i);
return substring(s, 5, strlen(s) - 9); // without maps/ and .bsp
}
void MapInfo_Enumerate()
{
if(_MapInfo_globopen)
+ {
search_end(_MapInfo_globhandle);
+ _MapInfo_globopen = 0;
+ }
MapInfo_Cache_Invalidate();
_MapInfo_globhandle = search_begin("maps/*.bsp", TRUE, TRUE);
- _MapInfo_globcount = search_getsize(_MapInfo_globhandle);
- _MapInfo_globopen = 1;
+ if(_MapInfo_globhandle >= 0)
+ {
+ _MapInfo_globcount = search_getsize(_MapInfo_globhandle);
+ _MapInfo_globopen = 1;
+ }
+ else
+ _MapInfo_globcount = 0;
}
// filter the info by game type mask (updates MapInfo_count)
void sv_notice_join()
{
// to-do: make sv_join_notices support per-entry times
- if(!autocvar_sv_join_notices || autocvar_sv_join_notices == "")
+ if(autocvar_sv_join_notices == "")
return;
entity n = spawn();
#define M1 30
#define M2 10
- vector v1, v2, v3;
+ vector v1, v2 = '0 0 0', v3;
v1 = '1 1 0' * M1;
v2_x = vid_conwidth - (2 * M1);
v2_y = vid_conheight - (2 * M1);
--- /dev/null
+// ================================================
+// Unified notification system, written by Samual
+// Last updated: March, 2013
+// ================================================
+
+string Get_Notif_TypeName(float net_type)
+{
+ switch(net_type)
+ {
+ case MSG_INFO: return "MSG_INFO";
+ case MSG_CENTER: return "MSG_CENTER";
+ case MSG_CENTER_CPID: return "MSG_CENTER_CPID";
+ case MSG_MULTI: return "MSG_MULTI";
+ }
+ backtrace(sprintf("Get_Notif_TypeName(%d): Improper net type!\n", net_type));
+ return "";
+}
+
+entity Get_Notif_Ent(float net_type, float net_name)
+{
+ switch(net_type)
+ {
+ case MSG_INFO: return msg_info_notifs[net_name - 1];
+ case MSG_CENTER: return msg_center_notifs[net_name - 1];
+ case MSG_MULTI: return msg_multi_notifs[net_name - 1];
+ }
+ backtrace(sprintf("Get_Notif_Ent(%d, %d): Improper net type!\n", net_type, net_name));
+ return world;
+}
+
+string Notification_CheckArgs_TypeName(float net_type, float net_name)
+{
+ // check supplied type and name for errors
+ string checkargs = "";
+ #define CHECKARG_TYPENAME(type) case MSG_##type##: \
+ { if(!net_name || (net_name > NOTIF_##type##_COUNT)) \
+ { checkargs = sprintf("Improper name: %d!", net_name); } break; }
+ switch(net_type)
+ {
+ CHECKARG_TYPENAME(INFO)
+ CHECKARG_TYPENAME(CENTER)
+ CHECKARG_TYPENAME(MULTI)
+ default: { checkargs = sprintf("Improper type: %d!", checkargs, net_type); break; }
+ }
+ #undef CHECKARG_TYPENAME
+ return checkargs;
+}
+
+#ifdef SVQC
+string Notification_CheckArgs(
+ float broadcast, entity client,
+ float net_type, float net_name)
+{
+ // check supplied broadcast, target, type, and name for errors
+ string checkargs = Notification_CheckArgs_TypeName(net_type, net_name);
+ if(checkargs != "") { checkargs = strcat(checkargs, " "); }
+ switch(broadcast)
+ {
+ case NOTIF_ONE:
+ case NOTIF_ONE_ONLY:
+ {
+ if(IS_NOT_A_CLIENT(client))
+ { checkargs = sprintf("%sNo client provided!", checkargs); }
+ break;
+ }
+
+ case NOTIF_ALL_EXCEPT:
+ {
+ if(IS_NOT_A_CLIENT(client))
+ { checkargs = sprintf("%sException can't be a non-client!", checkargs); }
+ break;
+ }
+
+ case NOTIF_ALL:
+ {
+ if(client)
+ { checkargs = sprintf("%sEntity provided when world was required!", checkargs); }
+ break;
+ }
+
+ case NOTIF_TEAM:
+ case NOTIF_TEAM_EXCEPT:
+ {
+ if not(teamplay) { checkargs = sprintf("%sTeamplay not active!", checkargs); }
+ else if(IS_NOT_A_CLIENT(client))
+ {
+ if(broadcast == NOTIF_TEAM) { checkargs = sprintf("%sNo client provided!", checkargs); }
+ else { checkargs = sprintf("%sException can't be a non-client!", checkargs); }
+ }
+ break;
+ }
+
+ default: { checkargs = sprintf("%sImproper broadcast: %d!", checkargs, broadcast); break; }
+ }
+ return checkargs;
+}
+#endif
+
+// ===============================
+// Initialization Core Functions
+// ===============================
+
+// used by restartnotifs command to initialize notifications
+void Destroy_Notification_Entity(entity notif)
+{
+ if(notif.nent_name != "") { strunzone(notif.nent_name); }
+ if(notif.nent_args != "") { strunzone(notif.nent_args); }
+ if(notif.nent_hudargs != "") { strunzone(notif.nent_hudargs); }
+ if(notif.nent_icon != "") { strunzone(notif.nent_icon); }
+ if(notif.nent_durcnt != "") { strunzone(notif.nent_durcnt); }
+ if(notif.nent_string != "") { strunzone(notif.nent_string); }
+ remove(notif);
+}
+
+void Destroy_All_Notifications(void)
+{
+ entity notif;
+ float i;
+
+ #define DESTROY_LOOP(type,count) \
+ for(i = 1; i <= count; ++i) \
+ { \
+ notif = Get_Notif_Ent(type, i); \
+ if not(notif) { backtrace("Destroy_All_Notifications(): Missing notification entity!\n"); return; } \
+ Destroy_Notification_Entity(notif); \
+ }
+
+ // kill all networked notifications and centerprints
+ #ifdef SVQC
+ Kill_Notification(NOTIF_ALL, world, 0, 0);
+ #else
+ reset_centerprint_messages();
+ #endif
+
+ // kill all real notification entities
+ DESTROY_LOOP(MSG_INFO, NOTIF_INFO_COUNT)
+ DESTROY_LOOP(MSG_CENTER, NOTIF_CENTER_COUNT)
+ DESTROY_LOOP(MSG_MULTI, NOTIF_MULTI_COUNT)
+ #undef DESTROY_LOOP
+}
+
+string Process_Notif_Line(
+ float msg_is_info,
+ float chat,
+ string input,
+ string notiftype,
+ string notifname,
+ string stringtype)
+{
+ if(msg_is_info)
+ {
+ #ifdef CSQC
+ if((chat && autocvar_notification_allow_chatboxprint)
+ || (autocvar_notification_allow_chatboxprint == 2))
+ {
+ // pass 1: add ETX char at beginning of line
+ input = strcat("\{3}", input);
+
+ // pass 2: add ETX char at end of each new line (so that
+ // messages with multiple lines are put through chatbox too)
+ input = strreplace("\n", "\n\{3}", input);
+
+ // pass 3: strip trailing ETX char
+ if(substring(input, (strlen(input) - 1), 1) == "\{3}")
+ { input = substring(input, 0, (strlen(input) - 1)); }
+ }
+ #endif
+ if(substring(input, (strlen(input) - 1), 1) != "\n")
+ {
+ print(sprintf(
+ strcat(
+ "^1MISSING/BROKEN NEW LINE AT END OF NOTIFICATION: ",
+ "^7net_type = %s, net_name = %s, string = %s.\n"
+ ),
+ notiftype,
+ notifname,
+ stringtype
+ ));
+ notif_error = TRUE;
+ return strcat(input, "\n");
+ }
+ }
+ return input;
+}
+
+string Process_Notif_Args(
+ float arg_type,
+ string args,
+ string notiftype,
+ string notifname)
+{
+ string selected, remaining = args;
+ float sel_num = 0;
+
+ for(;(remaining != "");)
+ {
+ selected = car(remaining); remaining = cdr(remaining);
+
+ switch(arg_type)
+ {
+ case 1: // normal args
+ {
+ if(sel_num == NOTIF_MAX_ARGS)
+ {
+ print(sprintf(
+ strcat(
+ "^1NOTIFICATION HAS TOO MANY ARGUMENTS: ",
+ "^7net_type = %s, net_name = %s, max args = %d.\n"
+ ),
+ notiftype,
+ notifname,
+ NOTIF_MAX_ARGS
+ ));
+ notif_error = TRUE;
+ break;
+ }
+
+ switch(strtolower(selected))
+ {
+ #define ARG_CASE(prog,selected,result) \
+ #if (prog != ARG_DC) \
+ case selected: { ++sel_num; break; } \
+ #endif
+ NOTIF_ARGUMENT_LIST
+ #undef ARG_CASE
+ default:
+ {
+ print(sprintf(
+ strcat(
+ "^1NOTIFICATION WITH UNKNOWN TOKEN IN ARGUMENT STRING: ",
+ "^7net_type = %s, net_name = %s, args arg = '%s'.\n"
+ ),
+ notiftype,
+ notifname,
+ selected
+ ));
+ notif_error = TRUE;
+ break;
+ }
+ }
+ break;
+ }
+ case 2: // hudargs
+ {
+ if(sel_num == NOTIF_MAX_HUDARGS)
+ {
+ print(sprintf(
+ strcat(
+ "^1NOTIFICATION HAS TOO MANY ARGUMENTS: ",
+ "^7net_type = %s, net_name = %s, max hudargs = %d.\n"
+ ),
+ notiftype,
+ notifname,
+ NOTIF_MAX_HUDARGS
+ ));
+ notif_error = TRUE;
+ break;
+ }
+
+ switch(strtolower(selected))
+ {
+ #define ARG_CASE(prog,selected,result) \
+ #if (prog == ARG_CS_SV_HA) \
+ case selected: { ++sel_num; break; } \
+ #endif
+ NOTIF_ARGUMENT_LIST
+ #undef ARG_CASE
+ default:
+ {
+ print(sprintf(
+ strcat(
+ "^1NOTIFICATION WITH UNKNOWN TOKEN IN ARGUMENT STRING: ",
+ "^7net_type = %s, net_name = %s, hudargs arg = '%s'.\n"
+ ),
+ notiftype,
+ notifname,
+ selected
+ ));
+ notif_error = TRUE;
+ break;
+ }
+ }
+ break;
+ }
+ case 3: // durcnt
+ {
+ if(sel_num == NOTIF_MAX_DURCNT)
+ {
+ print(sprintf(
+ strcat(
+ "^1NOTIFICATION HAS TOO MANY ARGUMENTS: ",
+ "^7net_type = %s, net_name = %s, max durcnt = %d.\n"
+ ),
+ notiftype,
+ notifname,
+ NOTIF_MAX_DURCNT
+ ));
+ notif_error = TRUE;
+ break;
+ }
+
+ switch(strtolower(selected))
+ {
+ #define ARG_CASE(prog,selected,result) \
+ #if (prog == ARG_CS_SV_DC) || (prog == ARG_DC) \
+ case selected: { ++sel_num; break; } \
+ #endif
+ NOTIF_ARGUMENT_LIST
+ #undef ARG_CASE
+ default:
+ {
+ if(ftos(stof(selected)) != "") { ++sel_num; }
+ else
+ {
+ print(sprintf(
+ strcat(
+ "^1NOTIFICATION WITH UNKNOWN TOKEN IN ARGUMENT STRING: ",
+ "^7net_type = %s, net_name = %s, durcnt arg = '%s'.\n"
+ ),
+ notiftype,
+ notifname,
+ selected
+ ));
+ notif_error = TRUE;
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ return args;
+}
+
+void Create_Notification_Entity(
+ float var_default,
+ float var_cvar,
+ float typeid,
+ float nameid,
+ string namestring,
+ float infoname,
+ float centername,
+ float strnum,
+ float flnum,
+ string args,
+ string hudargs,
+ string icon,
+ float cpid,
+ string durcnt,
+ string normal,
+ string gentle,
+ float msg_is_info,
+ float msg_is_multi)
+{
+ // =====================
+ // Global Entity Setup
+ // =====================
+ entity notif = spawn();
+ string typestring = "";
+ switch(typeid)
+ {
+ case MSG_INFO:
+ {
+ typestring = "MSG_INFO";
+ msg_info_notifs[nameid - 1] = notif;
+ notif.classname = "msg_info_notification";
+ break;
+ }
+ case MSG_CENTER:
+ {
+ typestring = "MSG_CENTER";
+ msg_center_notifs[nameid - 1] = notif;
+ notif.classname = "msg_center_notification";
+ break;
+ }
+ case MSG_MULTI:
+ {
+ typestring = "MSG_MULTI";
+ msg_multi_notifs[nameid - 1] = notif;
+ notif.classname = "MSG_MULTI_notification";
+ break;
+ }
+
+ default:
+ {
+ error(sprintf(
+ strcat(
+ "^1NOTIFICATION WITH IMPROPER TYPE: ",
+ "^7net_type = %d, net_name = %s.\n"
+ ),
+ typeid,
+ namestring
+ ));
+ return; // It's not possible to recover from this one
+ }
+ }
+ notif.nent_default = var_default;
+ notif.nent_name = strzone(namestring);
+ notif.nent_id = nameid;
+ notif.nent_enabled = (1 <= var_cvar);
+
+ // Other pre-notif-setup requisites
+ notif_error = FALSE;
+
+ // ====================
+ // Notification Setup
+ // ====================
+ if(msg_is_multi)
+ {
+ // Set MSG_MULTI string/float counts
+ if((infoname == NO_MSG) && (centername == NO_MSG))
+ {
+ print(sprintf(
+ strcat(
+ "^1NOTIFICATION WITH NO SUBCALLS: ",
+ "^7net_type = %s, net_name = %s.\n"
+ ),
+ typestring,
+ namestring
+ ));
+ notif_error = TRUE;
+ }
+ else
+ {
+ float infoname_stringcount = 0, infoname_floatcount = 0;
+ float centername_stringcount = 0, centername_floatcount = 0;
+
+ if(infoname != NO_MSG)
+ {
+ notif.nent_msginfo = msg_info_notifs[infoname - 1];
+ infoname_stringcount = notif.nent_msginfo.nent_stringcount;
+ infoname_floatcount = notif.nent_msginfo.nent_floatcount;
+ }
+
+ if(centername != NO_MSG)
+ {
+ notif.nent_msgcenter = msg_center_notifs[centername - 1];
+ centername_stringcount = notif.nent_msgcenter.nent_stringcount;
+ centername_floatcount = notif.nent_msgcenter.nent_floatcount;
+ }
+
+ // set the requirements of THIS notification to the totals of its subcalls
+ notif.nent_stringcount = max(infoname_stringcount, centername_stringcount);
+ notif.nent_floatcount = max(infoname_floatcount, centername_floatcount);
+ }
+ }
+ else
+ {
+ // Set MSG_INFO and MSG_CENTER string/float counts
+ notif.nent_stringcount = strnum;
+ notif.nent_floatcount = flnum;
+
+ // Only initialize arguments if we're either a client or on a dedicated server
+ #ifdef SVQC
+ float should_process_args = server_is_dedicated;
+ #else
+ float should_process_args = TRUE;
+ #endif
+
+ if(should_process_args)
+ {
+ // ========================
+ // Process Main Arguments
+ // ========================
+ if(strnum + flnum)
+ {
+ if(args != "")
+ {
+ notif.nent_args = strzone(
+ Process_Notif_Args(1, args, typestring, namestring));
+ }
+ else if((hudargs == "") && (durcnt ==""))
+ {
+ print(sprintf(
+ strcat(
+ "^1NOTIFICATION HAS ARG COUNTS BUT NO ARGS OR HUDARGS OR DURCNT: ",
+ "^7net_type = %s, net_name = %s, strnum = %d, flnum = %d\n"
+ ),
+ typestring,
+ namestring,
+ strnum,
+ flnum
+ ));
+ notif_error = TRUE;
+ }
+ }
+ else if(args != "")
+ {
+ notif.nent_args = strzone(
+ Process_Notif_Args(1, args, typestring, namestring));
+ }
+
+
+ // =======================================
+ // Process HUD and Centerprint Arguments
+ // Only processed on CSQC, as these
+ // args are only for HUD features.
+ // =======================================
+ #ifdef CSQC
+ if(hudargs != "")
+ {
+ notif.nent_hudargs = strzone(
+ Process_Notif_Args(2, hudargs, typestring, namestring));
+
+ if(icon != "") { notif.nent_icon = strzone(icon); }
+ else
+ {
+ print(sprintf(
+ strcat(
+ "^1NOTIFICATION HAS HUDARGS BUT NO ICON: ",
+ "^7net_type = %s, net_name = %s.\n"
+ ),
+ typestring,
+ namestring
+ ));
+ notif_error = TRUE;
+ }
+ }
+ else if(icon != "")
+ {
+ print(sprintf(
+ strcat(
+ "^1NOTIFICATION HAS ICON BUT NO HUDARGS: ",
+ "^7net_type = %s, net_name = %s.\n"
+ ),
+ typestring,
+ namestring
+ ));
+ notif_error = TRUE;
+ }
+
+ if(durcnt != "")
+ {
+ notif.nent_durcnt = strzone(
+ Process_Notif_Args(3, durcnt, typestring, namestring));
+
+ if(cpid != NO_MSG) { notif.nent_cpid = cpid; }
+ else
+ {
+ print(sprintf(
+ strcat(
+ "^1NOTIFICATION HAS DURCNT BUT NO CPID: ",
+ "^7net_type = %s, net_name = %s.\n"
+ ),
+ typestring,
+ namestring
+ ));
+ notif_error = TRUE;
+ }
+ }
+ else if(cpid != NO_MSG) { notif.nent_cpid = cpid; }
+ #endif
+
+
+ // ======================
+ // Process Notif String
+ // ======================
+ #define SET_NOTIF_STRING(string,stringname) \
+ notif.nent_string = strzone(CCR( \
+ Process_Notif_Line( \
+ msg_is_info, \
+ (var_cvar > 1), \
+ string, \
+ typestring, \
+ namestring, \
+ stringname \
+ )) \
+ );
+
+ if(GENTLE)
+ {
+ if(gentle != "") { SET_NOTIF_STRING(gentle, "GENTLE") }
+ else if(normal != "") { SET_NOTIF_STRING(normal, "NORMAL") }
+ }
+ else if(normal != "") { SET_NOTIF_STRING(normal, "NORMAL") }
+
+ #undef SET_NOTIF_STRING
+
+ // Check to make sure a string was chosen
+ if(notif.nent_string == "")
+ {
+ print(sprintf(
+ strcat(
+ "^1EMPTY NOTIFICATION: ",
+ "^7net_type = %s, net_name = %s.\n"
+ ),
+ typestring,
+ namestring
+ ));
+ notif_error = TRUE;
+ }
+ }
+ }
+
+ // now check to see if any errors happened
+ if(notif_error)
+ {
+ notif.nent_enabled = FALSE; // disable the notification so it can't cause trouble
+ notif_global_error = TRUE; // throw the red flag that an error happened on init
+ }
+}
+
+
+// =========================================
+// Cvar Handling With 'dumpnotifs' Command
+// =========================================
+
+void Dump_Notifications(float fh, float alsoprint)
+{
+ #define NOTIF_WRITE(a) { \
+ fputs(fh, a); \
+ if(alsoprint) { print(a); } }
+ #define NOTIF_WRITE_ENTITY(name,default,description) { \
+ notif_msg = \
+ sprintf( \
+ "seta notification_%s \"%d\" \"%s\"\n", \
+ name, default, description \
+ ); \
+ NOTIF_WRITE(notif_msg) }
+ #define NOTIF_WRITE_HARDCODED(cvar,default,description) { \
+ notif_msg = \
+ sprintf( \
+ "seta notification_%s \"%s\" \"%s\"\n", \
+ cvar, default, description \
+ ); \
+ NOTIF_WRITE(notif_msg) }
+
+ string notif_msg;
+ float i;
+ entity e;
+
+ // Note: This warning only applies to the notifications.cfg file that is output...
+
+ // You ARE supposed to manually edit this function to add i.e. hard coded
+ // notification variables for mutators or game modes or such and then
+ // regenerate the notifications.cfg file from the new code.
+
+ NOTIF_WRITE("// ********************************************** //\n");
+ NOTIF_WRITE("// ** WARNING - DO NOT MANUALLY EDIT THIS FILE ** //\n");
+ NOTIF_WRITE("// ** ** //\n");
+ NOTIF_WRITE("// ** This file is automatically generated ** //\n");
+ NOTIF_WRITE("// ** by code with the command 'dumpnotifs'. ** //\n");
+ NOTIF_WRITE("// ** ** //\n");
+ NOTIF_WRITE("// ** If you add a new notification, please ** //\n");
+ NOTIF_WRITE("// ** regenerate this file with that command ** //\n");
+ NOTIF_WRITE("// ** making sure that the output matches ** //\n");
+ NOTIF_WRITE("// ** with the lists and defaults in code. ** //\n");
+ NOTIF_WRITE("// ** ** //\n");
+ NOTIF_WRITE("// ********************************************** //\n");
+
+ // These notifications will also append their string as a comment...
+ // This is not necessary, and does not matter if they vary between config versions,
+ // it is just a semi-helpful tool for those who want to manually change their user settings.
+
+ NOTIF_WRITE(sprintf("\n// MSG_INFO notifications (count = %d):\n", NOTIF_INFO_COUNT));
+ for(i = 1; i <= NOTIF_INFO_COUNT; ++i)
+ {
+ e = Get_Notif_Ent(MSG_INFO, i);
+ if not(e) { backtrace("Dump_Notifications(): Missing notification entity!\n"); return; }
+ NOTIF_WRITE_ENTITY(e.nent_name, e.nent_default, "Notification control cvar: 0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)");
+ }
+
+ NOTIF_WRITE(sprintf("\n// MSG_CENTER notifications (count = %d):\n", NOTIF_CENTER_COUNT));
+ for(i = 1; i <= NOTIF_CENTER_COUNT; ++i)
+ {
+ e = Get_Notif_Ent(MSG_CENTER, i);
+ if not(e) { backtrace("Dump_Notifications(): Missing notification entity!\n"); return; }
+ NOTIF_WRITE_ENTITY(e.nent_name, e.nent_default, "Notification control cvar: 0 = off, 1 = centerprint");
+ }
+
+ NOTIF_WRITE(sprintf("\n// MSG_MULTI notifications (count = %d):\n", NOTIF_MULTI_COUNT));
+ for(i = 1; i <= NOTIF_MULTI_COUNT; ++i)
+ {
+ e = Get_Notif_Ent(MSG_MULTI, i);
+ if not(e) { backtrace("Dump_Notifications(): Missing notification entity!\n"); return; }
+ NOTIF_WRITE_ENTITY(e.nent_name, e.nent_default, "Notification control cvar: 0 = off, 1 = trigger subcalls");
+ }
+
+ // edit these to match whichever cvars are used for specific notification options
+ NOTIF_WRITE("\n// HARD CODED notification variables:\n");
+ NOTIF_WRITE_HARDCODED("allow_chatboxprint", "1", "Allow notifications to be printed to chat box by setting notification cvar to 2 (You can also set this cvar to 2 to force ALL notifications to be printed to the chatbox)");
+ NOTIF_WRITE_HARDCODED("ctf_capture_verbose", "0", "Show extra information when someone captures a flag");
+ NOTIF_WRITE_HARDCODED("ctf_pickup_enemy_verbose", "0", "Show extra information if an enemy picks up a flag");
+ NOTIF_WRITE_HARDCODED("ctf_pickup_team_verbose", "0", "Show extra information if a team mate picks up a flag");
+ NOTIF_WRITE_HARDCODED("errors_are_fatal", "1", "If a notification fails upon initialization, cause a Host_Error to stop the program");
+ NOTIF_WRITE_HARDCODED("frag_verbose", "1", "Show extra information when you frag someone (or when you are fragged");
+ NOTIF_WRITE_HARDCODED("item_centerprinttime", "1.5", "How long to show item information centerprint messages (like 'You got the Electro' or such)");
+ NOTIF_WRITE_HARDCODED("lifetime_mapload", "10", "Amount of time that notification entities last immediately at mapload (in seconds) to help prevent notifications from being lost on early init (like gamestart countdown)");
+ NOTIF_WRITE_HARDCODED("lifetime_runtime", "0.5", "Amount of time that notification entities last on the server during runtime (In seconds)");
+ NOTIF_WRITE_HARDCODED("server_allows_frag_verbose", "1", "Server side cvar for showing extra information in frag messages... 0 = no extra frag information, 1 = frag information only in warmup, 2 = frag information allowed all the time");
+ NOTIF_WRITE_HARDCODED("server_allows_location", "1", "Server side cvar for allowing death messages to show location information too");
+ NOTIF_WRITE_HARDCODED("show_location", "0", "Append location information to MSG_INFO death/kill messages");
+ NOTIF_WRITE_HARDCODED("show_location_string", "", "Replacement string piped into sprintf, so you can do different messages like this: ' at the %s' or ' (near %s)'");
+ NOTIF_WRITE_HARDCODED("show_sprees", "1", "Print information about sprees in death/kill messages");
+ NOTIF_WRITE_HARDCODED("show_sprees_center", "1", "Show spree information in MSG_CENTER messages... 0 = off, 1 = target (but only for first victim) and attacker");
+ NOTIF_WRITE_HARDCODED("show_sprees_center_specialonly", "1", "Don't show spree information in MSG_CENTER messages if it isn't an achievement");
+ NOTIF_WRITE_HARDCODED("show_sprees_info", "3", "Show spree information in MSG_INFO messages... 0 = off, 1 = target only, 2 = attacker only, 3 = target and attacker");
+ NOTIF_WRITE_HARDCODED("show_sprees_info_newline", "1", "Show attacker spree information for MSG_INFO messages on a separate line than the death notification itself");
+ NOTIF_WRITE_HARDCODED("show_sprees_info_specialonly", "1", "Don't show attacker spree information in MSG_INFO messages if it isn't an achievement");
+
+ NOTIF_WRITE(sprintf(
+ strcat(
+ "\n// Notification counts (total = %d): ",
+ "MSG_INFO = %d, MSG_CENTER = %d, MSG_MULTI = %d\n"
+ ),
+ (
+ NOTIF_INFO_COUNT +
+ NOTIF_CENTER_COUNT +
+ NOTIF_MULTI_COUNT
+ ),
+ NOTIF_INFO_COUNT,
+ NOTIF_CENTER_COUNT,
+ NOTIF_MULTI_COUNT
+ ));
+
+ return;
+ #undef NOTIF_WRITE_HARDCODED
+ #undef NOTIF_WRITE_ENTITY
+ #undef NOTIF_WRITE
+}
+
+#ifdef SVQC
+void Notification_GetCvars()
+{
+ GetCvars_handleFloat(get_cvars_s, get_cvars_f, FRAG_VERBOSE, "notification_frag_verbose");
+}
+#endif
+
+
+// ===============================
+// Frontend Notification Pushing
+// ===============================
+
+string Local_Notification_sprintf(
+ string input, string args,
+ string s1, string s2, string s3, string s4,
+ float f1, float f2, float f3, float f4)
+{
+ #ifdef NOTIFICATIONS_DEBUG
+ dprint(sprintf(
+ "Local_Notification_sprintf('%s^7', '%s', %s, %s);\n",
+ MakeConsoleSafe(input),
+ args,
+ MakeConsoleSafe(sprintf("'%s^7', '%s^7', '%s^7', '%s^7'", s1, s2, s3, s4)),
+ sprintf("%d, %d, %d, %d", f1, f2, f3, f4)
+ ));
+ #endif
+
+ string selected;
+ float sel_num;
+ for(sel_num = 0; sel_num < NOTIF_MAX_ARGS; ++sel_num) { arg_slot[sel_num] = ""; }
+
+ string tmp_s;
+
+ for(sel_num = 0;(args != "");)
+ {
+ selected = car(args); args = cdr(args);
+ NOTIF_HIT_MAX(NOTIF_MAX_ARGS, "Local_Notification_sprintf")
+ switch(strtolower(selected))
+ {
+ #define ARG_CASE(prog,selected,result) \
+ #ifdef CSQC \
+ #if (prog != ARG_SV) && (prog != ARG_DC) \
+ case selected: { arg_slot[sel_num] = result; ++sel_num; break; } \
+ #endif \
+ #else \
+ #if (prog != ARG_CS) && (prog != ARG_DC) \
+ case selected: { arg_slot[sel_num] = result; ++sel_num; break; } \
+ #endif \
+ #endif
+ NOTIF_ARGUMENT_LIST
+ #undef ARG_CASE
+ default: NOTIF_HIT_UNKNOWN(NOTIF_MAX_ARGS, "Local_Notification_sprintf")
+ }
+ }
+ return sprintf(input, arg_slot[0], arg_slot[1], arg_slot[2], arg_slot[3], arg_slot[4], arg_slot[5], arg_slot[6]);
+}
+
+#ifdef CSQC
+void Local_Notification_HUD_Notify_Push(
+ string icon, string hudargs,
+ string s1, string s2, string s3, string s4)
+{
+ string selected;
+ float sel_num;
+ arg_slot[0] = ""; arg_slot[1] = "";
+
+ for(sel_num = 0;(hudargs != "");)
+ {
+ selected = car(hudargs); hudargs = cdr(hudargs);
+ NOTIF_HIT_MAX(NOTIF_MAX_HUDARGS, "Local_Notification_HUD_Notify_Push")
+ switch(strtolower(selected))
+ {
+ #define ARG_CASE(prog,selected,result) \
+ #if (prog == ARG_CS_SV_HA) \
+ case selected: { arg_slot[sel_num] = result; ++sel_num; break; } \
+ #endif
+ NOTIF_ARGUMENT_LIST
+ #undef ARG_CASE
+ default: NOTIF_HIT_UNKNOWN(NOTIF_MAX_HUDARGS, "Local_Notification_HUD_Notify_Push")
+ }
+ }
+ #ifdef NOTIFICATIONS_DEBUG
+ dprint(sprintf(
+ "Local_Notification_HUD_Notify_Push('%s^7', '%s', %s, %s);\n",
+ icon,
+ hudargs,
+ MakeConsoleSafe(sprintf("'%s^7', '%s^7', '%s^7', '%s^7'", s1, s2, s3, s4)),
+ MakeConsoleSafe(sprintf("'%s^7', '%s^7'", stof(arg_slot[0]), stof(arg_slot[1])))
+ ));
+ #endif
+ HUD_Notify_Push(icon, arg_slot[0], arg_slot[1]);
+}
+
+void Local_Notification_centerprint_generic(
+ string input, string durcnt,
+ float cpid, float f1, float f2)
+{
+ string selected;
+ float sel_num;
+ arg_slot[0] = ""; arg_slot[1] = "";
+
+ for(sel_num = 0;(durcnt != "");)
+ {
+ selected = car(durcnt); durcnt = cdr(durcnt);
+ NOTIF_HIT_MAX(NOTIF_MAX_DURCNT, "Local_Notification_centerprint_generic")
+ switch(strtolower(selected))
+ {
+ #define ARG_CASE(prog,selected,result) \
+ #if (prog == ARG_CS_SV_DC) || (prog == ARG_DC) \
+ case selected: { arg_slot[sel_num] = result; ++sel_num; break; } \
+ #endif
+ NOTIF_ARGUMENT_LIST
+ #undef ARG_CASE
+ default:
+ {
+ if(ftos(stof(selected)) != "") { arg_slot[sel_num] = selected; ++sel_num; }
+ else { NOTIF_HIT_UNKNOWN(NOTIF_MAX_DURCNT, "Local_Notification_centerprint_generic") }
+ break;
+ }
+ }
+ }
+ #ifdef NOTIFICATIONS_DEBUG
+ dprint(sprintf(
+ "Local_Notification_centerprint_generic('%s^7', '%s', %d, %d, %d, %d);\n",
+ MakeConsoleSafe(input),
+ durcnt,
+ f1, f2,
+ stof(arg_slot[0]), stof(arg_slot[1])
+ ));
+ #endif
+ centerprint_generic(cpid, input, stof(arg_slot[0]), stof(arg_slot[1]));
+}
+#endif
+
+void Local_Notification(float net_type, float net_name, ...count)
+{
+ // check supplied type and name for errors
+ string checkargs = Notification_CheckArgs_TypeName(net_type, net_name);
+ if(checkargs != "") { backtrace(sprintf("Incorrect usage of Local_Notification: %s\n", checkargs)); return; }
+
+ entity notif = Get_Notif_Ent(net_type, net_name);
+ if not(notif) { backtrace("Local_Notification: Could not find notification entity!\n"); return; }
+ if not(notif.nent_enabled)
+ {
+ #ifdef NOTIFICATIONS_DEBUG
+ dprint(sprintf(
+ "Local_Notification(%s, %s): Entity was disabled...\n",
+ Get_Notif_TypeName(net_type),
+ notif.nent_name
+ ));
+ #endif
+ return;
+ }
+
+ if((notif.nent_stringcount + notif.nent_floatcount) > count)
+ {
+ backtrace(sprintf(
+ strcat(
+ "Not enough arguments for Local_Notification(%s, %s, ...)! ",
+ "stringcount(%d) + floatcount(%d) > count(%d)\n",
+ "Check the definition and function call for accuracy...?\n"
+ ),
+ Get_Notif_TypeName(net_type), notif.nent_name,
+ notif.nent_stringcount, notif.nent_floatcount, count
+ ));
+ return;
+ }
+ else if((notif.nent_stringcount + notif.nent_floatcount) < count)
+ {
+ backtrace(sprintf(
+ strcat(
+ "Too many arguments for Local_Notification(%s, %s, ...)! ",
+ "stringcount(%d) + floatcount(%d) < count(%d)\n",
+ "Check the definition and function call for accuracy...?\n"
+ ),
+ Get_Notif_TypeName(net_type), notif.nent_name,
+ notif.nent_stringcount, notif.nent_floatcount, count
+ ));
+ return;
+ }
+
+ string s1 = ((0 < notif.nent_stringcount) ? ...(0, string) : "");
+ string s2 = ((1 < notif.nent_stringcount) ? ...(1, string) : "");
+ string s3 = ((2 < notif.nent_stringcount) ? ...(2, string) : "");
+ string s4 = ((3 < notif.nent_stringcount) ? ...(3, string) : "");
+ float f1 = ((0 < notif.nent_floatcount) ? ...((notif.nent_stringcount + 0), float) : 0);
+ float f2 = ((1 < notif.nent_floatcount) ? ...((notif.nent_stringcount + 1), float) : 0);
+ float f3 = ((2 < notif.nent_floatcount) ? ...((notif.nent_stringcount + 2), float) : 0);
+ float f4 = ((3 < notif.nent_floatcount) ? ...((notif.nent_stringcount + 3), float) : 0);
+
+ #ifdef NOTIFICATIONS_DEBUG
+ dprint(sprintf(
+ "Local_Notification(%s, %s, %s, %s);\n",
+ Get_Notif_TypeName(net_type),
+ notif.nent_name,
+ MakeConsoleSafe(sprintf("'%s^7', '%s^7', '%s^7', '%s^7'", s1, s2, s3, s4)),
+ sprintf("%d, %d, %d, %d", f1, f2, f3, f4)
+ ));
+ #endif
+
+ switch(net_type)
+ {
+ case MSG_INFO:
+ {
+ print(
+ Local_Notification_sprintf(
+ notif.nent_string,
+ notif.nent_args,
+ s1, s2, s3, s4,
+ f1, f2, f3, f4)
+ );
+ #ifdef CSQC
+ if(notif.nent_icon != "")
+ {
+ Local_Notification_HUD_Notify_Push(
+ notif.nent_icon,
+ notif.nent_hudargs,
+ s1, s2, s3, s4);
+ }
+ #endif
+ break;
+ }
+
+ #ifdef CSQC
+ case MSG_CENTER:
+ {
+ Local_Notification_centerprint_generic(
+ Local_Notification_sprintf(
+ notif.nent_string,
+ notif.nent_args,
+ s1, s2, s3, s4,
+ f1, f2, f3, f4),
+ notif.nent_durcnt,
+ notif.nent_cpid,
+ f1, f2);
+ break;
+ }
+ #endif
+
+ case MSG_MULTI:
+ {
+ if(notif.nent_msginfo)
+ if(notif.nent_msginfo.nent_enabled)
+ {
+ Local_Notification_WOVA(
+ MSG_INFO,
+ notif.nent_msginfo.nent_id,
+ notif.nent_msginfo.nent_stringcount,
+ notif.nent_msginfo.nent_floatcount,
+ s1, s2, s3, s4,
+ f1, f2, f3, f4);
+ }
+ #ifdef CSQC
+ if(notif.nent_msgcenter)
+ if(notif.nent_msgcenter.nent_enabled)
+ {
+ Local_Notification_WOVA(
+ MSG_CENTER,
+ notif.nent_msgcenter.nent_id,
+ notif.nent_msgcenter.nent_stringcount,
+ notif.nent_msgcenter.nent_floatcount,
+ s1, s2, s3, s4,
+ f1, f2, f3, f4);
+ }
+ #endif
+ break;
+ }
+ }
+}
+
+// WOVA = Without Variable Arguments
+void Local_Notification_WOVA(
+ float net_type, float net_name,
+ float stringcount, float floatcount,
+ string s1, string s2, string s3, string s4,
+ float f1, float f2, float f3, float f4)
+{
+ #define VARITEM(stringc,floatc,args) \
+ if((stringcount == stringc) && (floatcount == floatc)) \
+ { Local_Notification(net_type, net_name, args); return; }
+ EIGHT_VARS_TO_VARARGS_VARLIST
+ #undef VARITEM
+ Local_Notification(net_type, net_name); // some notifications don't have any arguments at all
+}
+
+
+// =========================
+// Notification Networking
+// =========================
+
+#ifdef CSQC
+void Read_Notification(float is_new)
+{
+ float net_type = ReadByte();
+ float net_name = ReadShort();
+
+ entity notif;
+
+ if(net_type == MSG_CENTER_CPID)
+ {
+ #ifdef NOTIFICATIONS_DEBUG
+ dprint(sprintf(
+ "Read_Notification(%d) at %f: net_type = %s, net_name = %d\n",
+ is_new,
+ time,
+ Get_Notif_TypeName(net_type),
+ net_name
+ ));
+ #endif
+
+ if(is_new)
+ {
+ if(net_name == 0) { reset_centerprint_messages(); }
+ else if(net_name != NO_CPID)
+ {
+ // in this case, net_name IS the cpid we want to kill
+ centerprint_generic(net_name, "", 0, 0);
+ }
+ else
+ {
+ backtrace(sprintf(
+ "Read_Notification(%d) at %f: ^1TRIED TO KILL NO_CPID CENTERPRINT!\n",
+ is_new,
+ time
+ ));
+ }
+ }
+ }
+ else
+ {
+ notif = Get_Notif_Ent(net_type, net_name);
+ if not(notif) { backtrace("Read_Notification: Could not find notification entity!\n"); return; }
+
+ #ifdef NOTIFICATIONS_DEBUG
+ dprint(sprintf(
+ "Read_Notification(%d) at %f: net_type = %s, net_name = %s\n",
+ is_new,
+ time,
+ Get_Notif_TypeName(net_type),
+ notif.nent_name
+ ));
+ #endif
+
+ string s1 = ((0 < notif.nent_stringcount) ? ReadString() : "");
+ string s2 = ((1 < notif.nent_stringcount) ? ReadString() : "");
+ string s3 = ((2 < notif.nent_stringcount) ? ReadString() : "");
+ string s4 = ((3 < notif.nent_stringcount) ? ReadString() : "");
+ float f1 = ((0 < notif.nent_floatcount) ? ReadLong() : 0);
+ float f2 = ((1 < notif.nent_floatcount) ? ReadLong() : 0);
+ float f3 = ((2 < notif.nent_floatcount) ? ReadLong() : 0);
+ float f4 = ((3 < notif.nent_floatcount) ? ReadLong() : 0);
+
+ if(is_new)
+ {
+ Local_Notification_WOVA(
+ net_type, net_name,
+ notif.nent_stringcount,
+ notif.nent_floatcount,
+ s1, s2, s3, s4,
+ f1, f2, f3, f4);
+ }
+ }
+}
+#endif
+
+#ifdef SVQC
+void Net_Notification_Remove()
+{
+ if not(self) { backtrace(sprintf("Net_Notification_Remove() at %f: Missing self!?\n", time)); return; }
+
+ #ifdef NOTIFICATIONS_DEBUG
+ dprint(sprintf(
+ "Net_Notification_Remove() at %f: %s '%s - %s' notification\n",
+ time,
+ ((self.nent_net_name == -1) ? "Killed" : "Removed"),
+ Get_Notif_TypeName(self.nent_net_type),
+ self.owner.nent_name
+ ));
+ #endif
+
+ float i;
+ for(i = 0; i < 4; ++i) { if(self.nent_strings[i]) { strunzone(self.nent_strings[i]); } }
+ remove(self);
+}
+
+float Net_Write_Notification(entity client, float sf)
+{
+ float i, send = FALSE;
+
+ switch(self.nent_broadcast)
+ {
+ case NOTIF_ONE: // send to one client and their spectator
+ {
+ if(
+ (client == self.nent_client)
+ ||
+ (
+ IS_SPEC(client)
+ &&
+ (client.enemy == self.nent_client)
+ )
+ ) { send = TRUE; }
+ break;
+ }
+ case NOTIF_ONE_ONLY: // send ONLY to one client
+ {
+ if(client == self.nent_client) { send = TRUE; }
+ break;
+ }
+ case NOTIF_TEAM: // send only to X team and their spectators
+ {
+ if(
+ (client.team == self.nent_client.team)
+ ||
+ (
+ IS_SPEC(client)
+ &&
+ (client.enemy.team == self.nent_client.team)
+ )
+ ) { send = TRUE; }
+ break;
+ }
+ case NOTIF_TEAM_EXCEPT: // send only to X team and their spectators, except for Y person and their spectators
+ {
+ if(
+ (client != self.nent_client)
+ &&
+ (
+ (client.team == self.nent_client.team)
+ ||
+ (
+ IS_SPEC(client)
+ &&
+ (
+ (client.enemy != self.nent_client)
+ &&
+ (client.enemy.team == self.nent_client.team)
+ )
+ )
+ )
+ ) { send = TRUE; }
+ break;
+ }
+ case NOTIF_ALL: // send to everyone
+ {
+ send = TRUE;
+ break;
+ }
+ case NOTIF_ALL_EXCEPT: // send to everyone except X person and their spectators
+ {
+ if(
+ (client != self.nent_client)
+ &&
+ !(
+ IS_SPEC(client)
+ &&
+ (client.enemy == self.nent_client)
+ )
+ ) { send = TRUE; }
+ break;
+ }
+ default: { send = FALSE; break; }
+ }
+
+ if(send)
+ {
+ WriteByte(MSG_ENTITY, ENT_CLIENT_NOTIFICATION);
+ WriteByte(MSG_ENTITY, self.nent_net_type);
+ WriteShort(MSG_ENTITY, self.nent_net_name);
+ for(i = 0; i < self.nent_stringcount; ++i) { WriteString(MSG_ENTITY, self.nent_strings[i]); }
+ for(i = 0; i < self.nent_floatcount; ++i) { WriteLong(MSG_ENTITY, self.nent_floats[i]); }
+ }
+
+ return send;
+}
+
+void Kill_Notification(
+ float broadcast, entity client,
+ float net_type, float net_name)
+{
+ string checkargs = Notification_CheckArgs(broadcast, client, 1, 1);
+ if(checkargs != "") { backtrace(sprintf("Incorrect usage of Kill_Notification: %s\n", checkargs)); return; }
+
+ #ifdef NOTIFICATIONS_DEBUG
+ dprint(sprintf(
+ "Kill_Notification(%d, '%s', %s, %d);\n",
+ broadcast,
+ client.netname,
+ Get_Notif_TypeName(net_type),
+ net_name
+ ));
+ #endif
+
+ entity notif, net_notif;
+ float killed_cpid = NO_CPID;
+
+ switch(net_type)
+ {
+ case 0:
+ {
+ killed_cpid = 0; // kill ALL centerprints
+ break;
+ }
+
+ case MSG_CENTER:
+ {
+ if(net_name)
+ {
+ entity notif = Get_Notif_Ent(net_type, net_name);
+ if not(notif) { backtrace("Kill_Notification: Could not find notification entity!\n"); return; }
+
+ if(notif.nent_cpid)
+ killed_cpid = notif.nent_cpid;
+ else
+ killed_cpid = NO_CPID;
+ }
+ else
+ {
+ killed_cpid = 0; // kill ALL centerprints
+ }
+ break;
+ }
+
+ case MSG_CENTER_CPID:
+ {
+ killed_cpid = net_name;
+ break;
+ }
+ }
+
+ if(killed_cpid != NO_CPID)
+ {
+ net_notif = spawn();
+ net_notif.classname = "net_kill_notification";
+ net_notif.nent_broadcast = broadcast;
+ net_notif.nent_client = client;
+ net_notif.nent_net_type = MSG_CENTER_CPID;
+ net_notif.nent_net_name = killed_cpid;
+ Net_LinkEntity(net_notif, FALSE, autocvar_notification_lifetime_runtime, Net_Write_Notification);
+ }
+
+ for(notif = world; (notif = find(notif, classname, "net_notification"));)
+ {
+ if(net_type)
+ {
+ if(killed_cpid != NO_CPID)
+ {
+ if(notif.owner.nent_cpid == killed_cpid)
+ {
+ notif.nent_net_name = -1;
+ notif.nextthink = time;
+ }
+ else { continue; } // we ARE looking for a specific CPID, don't kill everything else too
+ }
+ else if(notif.nent_net_type == net_type)
+ {
+ if(net_name)
+ {
+ if(notif.nent_net_name == net_name) { notif.nent_net_name = -1; notif.nextthink = time; }
+ else { continue; } // we ARE looking for a certain net_name, don't kill everything else too
+ }
+ else { notif.nent_net_name = -1; notif.nextthink = time; }
+ }
+ else { continue; } // we ARE looking for a certain net_type, don't kill everything else too
+ }
+ else { notif.nent_net_name = -1; notif.nextthink = time; }
+ }
+}
+
+void Send_Notification(
+ float broadcast, entity client,
+ float net_type, float net_name,
+ ...count)
+{
+ // check supplied broadcast, target, type, and name for errors
+ string checkargs = Notification_CheckArgs(broadcast, client, net_type, net_name);
+ if(checkargs != "") { backtrace(sprintf("Incorrect usage of Send_Notification: %s\n", checkargs)); return; }
+
+ // retreive counts for the arguments of this notification
+ entity notif = Get_Notif_Ent(net_type, net_name);
+ if not(notif) { backtrace("Send_Notification: Could not find notification entity!\n"); return; }
+
+ if((notif.nent_stringcount + notif.nent_floatcount) > count)
+ {
+ backtrace(sprintf(
+ strcat(
+ "Not enough arguments for Send_Notification(%d, %s, %s, ...)! ",
+ "stringcount(%d) + floatcount(%d) > count(%d)\n",
+ "Check the definition and function call for accuracy...?\n"
+ ),
+ broadcast, Get_Notif_TypeName(net_type), notif.nent_name,
+ notif.nent_stringcount, notif.nent_floatcount, count
+ ));
+ return;
+ }
+ else if((notif.nent_stringcount + notif.nent_floatcount) < count)
+ {
+ backtrace(sprintf(
+ strcat(
+ "Too many arguments for Send_Notification(%d, %s, %s, ...)! ",
+ "stringcount(%d) + floatcount(%d) < count(%d)\n",
+ "Check the definition and function call for accuracy...?\n"
+ ),
+ broadcast, Get_Notif_TypeName(net_type), notif.nent_name,
+ notif.nent_stringcount, notif.nent_floatcount, count
+ ));
+ return;
+ }
+
+ #ifdef NOTIFICATIONS_DEBUG
+ string s1 = ((0 < notif.nent_stringcount) ? ...(0, string) : "");
+ string s2 = ((1 < notif.nent_stringcount) ? ...(1, string) : "");
+ string s3 = ((2 < notif.nent_stringcount) ? ...(2, string) : "");
+ string s4 = ((3 < notif.nent_stringcount) ? ...(3, string) : "");
+ float f1 = ((0 < notif.nent_floatcount) ? ...((notif.nent_stringcount + 0), float) : 0);
+ float f2 = ((1 < notif.nent_floatcount) ? ...((notif.nent_stringcount + 1), float) : 0);
+ float f3 = ((2 < notif.nent_floatcount) ? ...((notif.nent_stringcount + 2), float) : 0);
+ float f4 = ((3 < notif.nent_floatcount) ? ...((notif.nent_stringcount + 3), float) : 0);
+ dprint(sprintf(
+ "Send_Notification(%d, %s, %s, %s, %s);\n",
+ broadcast,
+ Get_Notif_TypeName(net_type),
+ notif.nent_name,
+ MakeConsoleSafe(sprintf("'%s^7', '%s^7', '%s^7', '%s^7'", s1, s2, s3, s4)),
+ sprintf("%d, %d, %d, %d", f1, f2, f3, f4)
+ ));
+ #endif
+
+ entity net_notif = spawn();
+ net_notif.owner = notif;
+ net_notif.classname = "net_notification";
+ net_notif.nent_broadcast = broadcast;
+ net_notif.nent_client = client;
+ net_notif.nent_net_type = net_type;
+ net_notif.nent_net_name = net_name;
+ net_notif.nent_stringcount = notif.nent_stringcount;
+ net_notif.nent_floatcount = notif.nent_floatcount;
+
+ float i;
+ for(i = 0; i < net_notif.nent_stringcount; ++i) { net_notif.nent_strings[i] = strzone(...(i, string)); }
+ for(i = 0; i < net_notif.nent_floatcount; ++i) { net_notif.nent_floats[i] = ...((net_notif.nent_stringcount + i), float); }
+
+ net_notif.think = Net_Notification_Remove;
+ net_notif.nextthink =
+ ((time > autocvar_notification_lifetime_mapload)
+ ?
+ (time + autocvar_notification_lifetime_runtime)
+ :
+ autocvar_notification_lifetime_mapload
+ );
+
+ Net_LinkEntity(net_notif, FALSE, 0, Net_Write_Notification);
+
+ if(server_is_dedicated && (broadcast == NOTIF_ALL || broadcast == NOTIF_ALL_EXCEPT) && (net_type != MSG_CENTER))
+ {
+ Local_Notification_WOVA(
+ net_type, net_name,
+ notif.nent_stringcount,
+ notif.nent_floatcount,
+ IFSTR(0), IFSTR(1), IFSTR(2), IFSTR(3),
+ IFFL(0), IFFL(1), IFFL(2), IFFL(3));
+ }
+}
+
+// WOVA = Without Variable Arguments
+void Send_Notification_WOVA(
+ float broadcast, entity client,
+ float net_type, float net_name,
+ string s1, string s2, string s3, string s4,
+ float f1, float f2, float f3, float f4)
+{
+ entity notif = Get_Notif_Ent(net_type, net_name);
+
+ #ifdef NOTIFICATIONS_DEBUG
+ dprint(sprintf(
+ "Send_Notification_WOVA(%d, %s, %s, %s, %s);\n",
+ broadcast,
+ Get_Notif_TypeName(net_type),
+ notif.nent_name,
+ MakeConsoleSafe(sprintf("'%s^7', '%s^7', '%s^7', '%s^7'", s1, s2, s3, s4)),
+ sprintf("%d, %d, %d, %d", f1, f2, f3, f4)
+ ));
+ #endif
+
+ #define VARITEM(stringc,floatc,args) \
+ if((notif.nent_stringcount == stringc) && (notif.nent_floatcount == floatc)) \
+ { Send_Notification(broadcast, client, net_type, net_name, args); return; }
+ EIGHT_VARS_TO_VARARGS_VARLIST
+ #undef VARITEM
+ Send_Notification(broadcast, client, net_type, net_name); // some notifications don't have any arguments at all
+}
+#endif // ifdef SVQC
--- /dev/null
+// ================================================
+// Unified notification system, written by Samual
+// Last updated: March, 2013
+// ================================================
+
+// main types/groups of notifications
+#define MSG_INFO 1 // "Global" information messages (sent to console, and notify panel if it has an icon)
+#define MSG_CENTER 2 // "Personal" centerprint messages
+#define MSG_CENTER_CPID 3 // Kill centerprint message
+#define MSG_MULTI 4 // Subcall MSG_INFO and/or MSG_CENTER notifications
+
+#define NO_MSG -12345
+
+#define EIGHT_VARS_TO_VARARGS_VARLIST \
+ VARITEM(1, 0, s1) \
+ VARITEM(2, 0, XPD(s1, s2)) \
+ VARITEM(3, 0, XPD(s1, s2, s3)) \
+ VARITEM(4, 0, XPD(s1, s2, s3, s4)) \
+ VARITEM(0, 1, f1) \
+ VARITEM(1, 1, XPD(s1, f1)) \
+ VARITEM(2, 1, XPD(s1, s2, f1)) \
+ VARITEM(3, 1, XPD(s1, s2, s3, f1)) \
+ VARITEM(4, 1, XPD(s1, s2, s3, s4, f1)) \
+ VARITEM(0, 2, XPD(f1, f2)) \
+ VARITEM(1, 2, XPD(s1, f1, f2)) \
+ VARITEM(2, 2, XPD(s1, s2, f1, f2)) \
+ VARITEM(3, 2, XPD(s1, s2, s3, f1, f2)) \
+ VARITEM(4, 2, XPD(s1, s2, s3, s4, f1, f2)) \
+ VARITEM(0, 3, XPD(f1, f2, f3)) \
+ VARITEM(1, 3, XPD(s1, f1, f2, f3)) \
+ VARITEM(2, 3, XPD(s1, s2, f1, f2, f3)) \
+ VARITEM(3, 3, XPD(s1, s2, s3, f1, f2, f3)) \
+ VARITEM(4, 3, XPD(s1, s2, s3, s4, f1, f2, f3)) \
+ VARITEM(0, 4, XPD(f1, f2, f3, f4)) \
+ VARITEM(1, 4, XPD(s1, f1, f2, f3, f4)) \
+ VARITEM(2, 4, XPD(s1, s2, f1, f2, f3, f4)) \
+ VARITEM(3, 4, XPD(s1, s2, s3, f1, f2, f3, f4)) \
+ VARITEM(4, 4, XPD(s1, s2, s3, s4, f1, f2, f3, f4))
+
+void Destroy_All_Notifications(void);
+void Create_Notification_Entity(
+ float var_default,
+ float var_cvar,
+ float typeid,
+ float nameid,
+ string namestring,
+ float infoname,
+ float centername,
+ float strnum,
+ float flnum,
+ string args,
+ string hudargs,
+ string icon,
+ float cpid,
+ string durcnt,
+ string normal,
+ string gentle,
+ float msg_is_info,
+ float msg_is_multi);
+
+void Dump_Notifications(float fh, float alsoprint);
+
+void Local_Notification(float net_type, float net_name, ...count);
+void Local_Notification_WOVA(
+ float net_type, float net_name,
+ float stringcount, float floatcount,
+ string s1, string s2, string s3, string s4,
+ float f1, float f2, float f3, float f4);
+
+#ifdef CSQC // CLIENT ONLY
+void Read_Notification(float is_new);
+#endif
+
+#ifdef SVQC // SERVER ONLY
+#define NOTIF_ONE 1
+#define NOTIF_ONE_ONLY 2
+#define NOTIF_TEAM 3
+#define NOTIF_TEAM_EXCEPT 4
+#define NOTIF_ALL 5
+#define NOTIF_ALL_EXCEPT 6
+
+#define IFSTR(num) ((num < notif.nent_stringcount) ? ...(num, string) : "")
+#define IFFL(num) ((((notif.nent_stringcount-1) + num) < count) ? ...(((notif.nent_stringcount-1) + num), float) : 0)
+
+void Kill_Notification(
+ float broadcast, entity client,
+ float net_type, float net_name);
+void Send_Notification(
+ float broadcast, entity client,
+ float net_type, float net_name,
+ ...count);
+void Send_Notification_WOVA(
+ float broadcast, entity client,
+ float net_type, float net_name,
+ string s1, string s2, string s3, string s4,
+ float f1, float f2, float f3, float f4);
+#endif
+
+
+// ====================================
+// Notifications List and Information
+// ====================================
+/*
+ List of all notifications (including identifiers and display information)
+ Possible Tokens: default, name, infoname, centername, strnum, flnum, args, hudargs, icon, cpid, durcnt, normal, gentle
+ Format Specifications:
+ MSG_INFO:
+ default: FLOAT: Default setting for whether the notification is enabled or not
+ ^-> 0 = disabled, 1 = enabled, 2 = also print to chat box
+ name: VAR: Name of notification
+ strnum: FLOAT: Number of STRING arguments (so that networking knows how many to send/receive)
+ flnum: FLOAT: Number of FLOAT arguments (so that networking knows how many to send/receive)
+ args: STRING: Arguments for Local_Notification_sprintf()
+ hudargs: STRING: Arguments for Local_Notification_HUD_Notify_Push()
+ icon: STRING: icon string name for the hud notify panel, "" if no icon is used
+ normal: STRING: Normal message (string for sprintf when gentle messages are NOT enabled)
+ gentle: STRING: Gentle message (string for sprintf when gentle messages ARE enabled)
+ MSG_CENTER:
+ default: FLOAT: Default setting for whether the notification is enabled or not
+ ^-> 0 = disabled, 1 = enabled
+ name: VAR: Name of notification
+ strnum: FLOAT: Number of STRING arguments (so that networking knows how many to send/receive)
+ flnum: FLOAT: Number of FLOAT arguments (so that networking knows how many to send/receive)
+ args: STRING: Arguments for Local_Notification_sprintf()
+ cpid: FLOAT: centerprint ID number (CPID_*), NO_CPID if no CPID is needed
+ durcnt: XPD(FLOAT, FLOAT): Duration/Countdown: extra arguments for centerprint messages
+ normal: STRING: Normal message (string for sprintf when gentle messages are NOT enabled)
+ gentle: STRING: Gentle message (string for sprintf when gentle messages ARE enabled)
+ MSG_MULTI:
+ default: FLOAT: Default setting for whether the notification is enabled or not
+ ^-> 0 = disabled, 1 = enabled
+ name: VAR: Name of chaining notification
+ infoname: VAR: Name of info notification for reference
+ centername: VAR: Name of centerprint notification for reference
+
+ Messages with ^F1, ^BG, ^TC, etc etc in them will replace those strings
+ with colors according to the cvars the user has chosen. This allows for
+ users to create unique color profiles for their HUD, giving more customization
+ options to HUD designers and end users who want such a feature.
+
+ Check out the definitions in util.qc/util.qh/teams.qh for string CCR(...) and
+ string TCR(...) to better understand how these code replacements work.
+
+ Additionally, you can find all the definitions and explanations for
+ the argument values and what they return down below in this file.
+
+ Guidlines for notification declaration (please try and follow these):
+ Specific rules:
+ -ALWAYS start the string with a color, preferably background.
+ -ALWAYS reset a color after a name (this way they don't set it for the whole string).
+ -NEVER re-declare an event twice.
+ -NEVER add or remove tokens from the format, it SHOULD already work.
+ -MSG_INFO messages must ALWAYS end with a new line: \n
+ -MSG_INFO hudargs must always be ATTACKER -> VICTIM
+ -MSG_CENTER should NOT end with a new line
+
+ General rules:
+ -Be clean and simple with your notification naming,
+ nothing too long for the name field... Abbreviations are your friend. :D
+ -Keep the spacing as clean as possible... if the arguments are abnormally long,
+ it's okay to go out of line a bit... but try and keep it clean still.
+ - Use ONLY spaces for spacing in the notification list, tabs are too inconsistent
+ with keeping alignment on different mediums.
+ -Sort the notifications in the most appropriate order for their tasks.
+ -ARIRE unir frk jvgu lbhe bja zbgure. (gvc sbe zvxrrhfn) -- Don't pay attention to this ^_^
+
+ Final note: DO NOT PROVIDE MORE ARGUMENTS THAN NECESSARY FOR THE NOTIFICATION YOU'RE CALLING!
+ The system is designed to save as much networking bandwidth as possible,
+ so please dynamically control your argument sending to fit *exactly* what is required.
+ If you send a notification with mismatching arguments, Send_Notification() will error.
+*/
+
+#define MULTITEAM_INFO(default,prefix,teams,strnum,flnum,args,hudargs,icon,normal,gentle) \
+ MSG_INFO_NOTIF(default, prefix##RED, strnum, flnum, args, hudargs, sprintf(icon, strtolower(NAME_TEAM_1)), TCR(normal, COL_TEAM_1, strtoupper(NAME_TEAM_1)), TCR(gentle, COL_TEAM_1, strtoupper(NAME_TEAM_1))) \
+ MSG_INFO_NOTIF(default, prefix##BLUE, strnum, flnum, args, hudargs, sprintf(icon, strtolower(NAME_TEAM_2)), TCR(normal, COL_TEAM_2, strtoupper(NAME_TEAM_2)), TCR(gentle, COL_TEAM_2, strtoupper(NAME_TEAM_2))) \
+ #if teams >= 3 \
+ MSG_INFO_NOTIF(default, prefix##YELLOW, strnum, flnum, args, hudargs, sprintf(icon, strtolower(NAME_TEAM_3)), TCR(normal, COL_TEAM_3, strtoupper(NAME_TEAM_3)), TCR(gentle, COL_TEAM_3, strtoupper(NAME_TEAM_3))) \
+ #endif \
+ #if teams >= 4 \
+ MSG_INFO_NOTIF(default, prefix##PINK, strnum, flnum, args, hudargs, sprintf(icon, strtolower(NAME_TEAM_4)), TCR(normal, COL_TEAM_4, strtoupper(NAME_TEAM_4)), TCR(gentle, COL_TEAM_4, strtoupper(NAME_TEAM_4))) \
+ #endif
+#define MSG_INFO_NOTIFICATIONS \
+ MULTITEAM_INFO(1, INFO_CTF_CAPTURE_, 2, 1, 0, "s1", "s1", "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ MULTITEAM_INFO(1, INFO_CTF_CAPTURE_UNBROKEN_, 2, 2, 2, "s1 f1p2dec s2 f2p2dec", "s1", "notify_%s_captured", _("^BG%s^BG captured the ^TC^TT^BG flag in ^F2%s^BG seconds, failing to break ^BG%s^BG's previous record of ^F1%s^BG seconds\n"), "") \
+ MULTITEAM_INFO(1, INFO_CTF_FLAGRETURN_ABORTRUN_, 2, 0, 0, "", "", "", _("^BGThe ^TC^TT^BG flag was returned to base by its owner\n"), "") \
+ MULTITEAM_INFO(1, INFO_CTF_FLAGRETURN_DAMAGED_, 2, 0, 0, "", "", "", _("^BGThe ^TC^TT^BG flag was destroyed and returned to base\n"), "") \
+ MULTITEAM_INFO(1, INFO_CTF_FLAGRETURN_DROPPED_, 2, 0, 0, "", "", "", _("^BGThe ^TC^TT^BG flag was dropped in the base and returned itself\n"), "") \
+ MULTITEAM_INFO(1, INFO_CTF_FLAGRETURN_NEEDKILL_, 2, 0, 0, "", "", "", _("^BGThe ^TC^TT^BG flag fell somewhere it couldn't be reached and returned to base\n"), "") \
+ MULTITEAM_INFO(1, INFO_CTF_FLAGRETURN_SPEEDRUN_, 2, 0, 1, "f1p2dec", "", "", _("^BGThe ^TC^TT^BG flag became impatient after ^F1%.2f^BG seconds and returned itself\n"), "") \
+ MULTITEAM_INFO(1, INFO_CTF_FLAGRETURN_TIMEOUT_, 2, 0, 0, "", "", "", _("^BGThe ^TC^TT^BG flag has returned to the base\n"), "") \
+ MULTITEAM_INFO(1, INFO_CTF_LOST_, 2, 1, 0, "s1", "s1", "notify_%s_lost", _("^BG%s^BG lost the ^TC^TT^BG flag\n"), "") \
+ MULTITEAM_INFO(1, INFO_CTF_PICKUP_, 2, 1, 0, "s1", "s1", "notify_%s_taken", _("^BG%s^BG got the ^TC^TT^BG flag\n"), "") \
+ MULTITEAM_INFO(1, INFO_CTF_RETURN_, 2, 1, 0, "s1", "s1", "notify_%s_returned", _("^BG%s^BG returned the ^TC^TT^BG flag\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_CHEAT, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was unfairly eliminated by ^BG%s^K1%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_DROWN, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_water", _("^BG%s%s^K1 was drowned by ^BG%s^K1%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_FALL, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_fall", _("^BG%s%s^K1 was grounded by ^BG%s^K1%s%s\n"), "") \
+ 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\n"), _("^BG%s^K1 felt a little hot from ^BG%s^K1's fire^K1%s%s\n")) \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_TELEFRAG, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_telefrag", _("^BG%s%s^K1 was telefragged by ^BG%s^K1%s%s\n"), _("^BG%s^K1 tried to occupy ^BG%s^K1's teleport destination space%s%s\n")) \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_TOUCHEXPLODE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 died in an accident with ^BG%s^K1%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_BUMB_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 Bumblebee exploded%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_BUMB_GUN, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 saw the pretty lights of ^BG%s^K1's Bumblebee gun%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_CRUSH, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was crushed by ^BG%s^K1%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_RAPT_BOMB, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was cluster bombed by ^BG%s^K1's Raptor%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_RAPT_CANNON, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 couldn't resist ^BG%s^K1's purple blobs%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_RAPT_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 Raptor exploded%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_SPID_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 Spiderbot exploded%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_SPID_MINIGUN, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 got shredded by ^BG%s^K1's Spiderbot%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_MURDER_VH_SPID_ROCKET, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was blasted to bits by ^BG%s^K1's Spiderbot%s%s\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_AUTOTEAMCHANGE, 2, 1, "s1 s2loc death_team", "", "", _("^BG%s^K1 was moved into the %s%s\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), _("^BG%s^K1 was in the water for too long%s%s\n")) \
+ 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\n"), _("^BG%s^K1 hit the ground with a bit too much force%s%s\n")) \
+ 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\n"), _("^BG%s^K1 felt a little hot%s%s\n")) \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_GENERIC, 2, 1, "s1 s2loc spree_lost", "s1", "notify_selfkill", _("^BG%s^K1 died%s%s\n"), "") \
+ 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\n"), _("^BG%s^K1 found a hot place%s%s\n")) \
+ 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?\n"), _("^BG%s^K1 ran out of ammo%s%s\n")) \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_ROT, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 rotted away%s%s\n"), "") \
+ 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\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_SLIME, 2, 1, "s1 s2loc spree_lost", "s1", "notify_slime", _("^BG%s^K1 was slimed%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_selfkill", _("^BG%s^K1 couldn't take it anymore%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_SWAMP, 2, 1, "s1 s2loc spree_lost", "s1", "notify_slime", _("^BG%s^K1 is now preserved for centuries to come%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TEAMCHANGE, 2, 1, "s1 s2loc death_team", "", "", _("^BG%s^K1 switched to the %s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TOUCHEXPLODE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 died in an accident%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 ran into a turret%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_EWHEEL, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was blasted away by an eWheel turret%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_FLAC, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got caught up in the FLAC turret fire%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_HELLION, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was blasted away by a Hellion turret%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_HK, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 could not hide from the Hunter turret%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_MACHINEGUN, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was riddled full of holes by a Machinegun turret%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_MLRS, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got turned into smoldering gibs by an MLRS turret%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_PHASER, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was phased out by a turret%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_PLASMA, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got served some superheated plasma from a turret%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_TESLA, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was electrocuted by a Tesla turret%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_WALK_GUN, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got served a lead enrichment by a Walker turret%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_WALK_MEELE, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was impaled by a Walker turret%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_TURRET_WALK_ROCKET, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was blasted away by a Walker turret%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_BUMB_DEATH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got caught in the blast of a Bumblebee explosion%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_CRUSH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was crushed by a vehicle%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_RAPT_BOMB, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was caught in a Raptor cluster bomb%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_RAPT_DEATH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got caught in the blast of a Raptor explosion%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_SPID_DEATH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got caught in the blast of a Spiderbot explosion%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_SPID_ROCKET, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 was blasted to bits by a Spiderbot rocket%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_DEATH_SELF_VH_WAKI_DEATH, 2, 1, "s1 s2loc spree_lost", "s1", "notify_death", _("^BG%s^K1 got caught in the blast of a Racer explosion%s%s\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_FREEZETAG_FREEZE, 2, 0, "s1 s2", "", "", _("^BG%s^K1 was frozen by ^BG%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_FREEZETAG_REVIVE, 2, 0, "s1 s2", "", "", _("^BG%s^K3 was revived by ^BG%s\n"), "") \
+ MULTITEAM_INFO(1, INFO_FREEZETAG_ROUND_WIN_, 4, 0, 0, "", "", "", _("^TC^TT^BG team wins the round, all other teams were frozen\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_FREEZETAG_SELF, 1, 0, "s1", "", "", _("^BG%s^K1 froze themself\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_GODMODE_OFF, 0, 1, "f1", "", "", _("^BGGodmode saved you %s units of damage, cheater!\n"), "") \
+ MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_DONTHAVE, 0, 1, "item_wepname", "", "", _("^BGYou do not have the ^F1%s\n"), "") \
+ MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_DROP, 1, 1, "item_wepname item_wepammo", "", "", _("^BGYou dropped the ^F1%s^BG%s\n"), "") \
+ MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_GOT, 0, 1, "item_wepname", "", "", _("^BGYou got the ^F1%s\n"), "") \
+ MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_NOAMMO, 0, 1, "item_wepname", "", "", _("^BGYou don't have enough ammo for the ^F1%s\n"), "") \
+ MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_PRIMORSEC, 0, 3, "item_wepname f2primsec f3primsec", "", "", _("^F1%s %s^BG is unable to fire, but its ^F1%s^BG can\n"), "") \
+ MSG_INFO_NOTIF(0, INFO_ITEM_WEAPON_UNAVAILABLE, 0, 1, "item_wepname", "", "", _("^F1%s^BG is ^F4not available^BG on this map\n"), "") \
+ MSG_INFO_NOTIF(2, INFO_JOIN_CONNECT, 1, 0, "s1", "", "", _("^BG%s^F3 connected%s\n"), "") \
+ MULTITEAM_INFO(2, INFO_JOIN_CONNECT_TEAM_, 4, 1, 0, "s1", "", "", _("^BG%s^F3 connected and joined the ^TC^TT\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_JOIN_PLAY, 1, 0, "s1", "", "", _("^BG%s^F3 is now playing\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_KEEPAWAY_DROPPED, 1, 0, "s1", "s1", "notify_balldropped", _("^BG%s^BG has dropped the ball!\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_KEEPAWAY_PICKUP, 1, 0, "s1", "s1", "notify_ballpickedup", _("^BG%s^BG has picked up the ball!\n"), "") \
+ MULTITEAM_INFO(1, INFO_KEYHUNT_CAPTURE_, 4, 1, 0, "s1", "", "", _("^BG%s^BG captured the keys for the ^TC^TT team\n"), "") \
+ MULTITEAM_INFO(1, INFO_KEYHUNT_DROP_, 4, 1, 0, "s1", "", "", _("^BG%s^BG dropped the ^TC^TT Key\n"), "") \
+ MULTITEAM_INFO(1, INFO_KEYHUNT_LOST_, 4, 1, 0, "s1", "", "", _("^BG%s^BG lost the ^TC^TT Key\n"), "") \
+ MULTITEAM_INFO(1, INFO_KEYHUNT_PICKUP_, 4, 1, 0, "s1", "", "", _("^BG%s^BG picked up the ^TC^TT Key\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_LMS_FORFEIT, 1, 0, "s1", "", "", _("^BG%s^F3 forfeited\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_LMS_NOLIVES, 1, 0, "s1", "", "", _("^BG%s^F3 has no more lives left\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_POWERUP_INVISIBILITY, 1, 0, "s1", "s1", "strength", _("^BG%s^K1 picked up Invisibility\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_POWERUP_SHIELD, 1, 0, "s1", "s1", "shield", _("^BG%s^K1 picked up Shield\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_POWERUP_SPEED, 1, 0, "s1", "s1", "shield", _("^BG%s^K1 picked up Speed\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_POWERUP_STRENGTH, 1, 0, "s1", "s1", "strength", _("^BG%s^K1 picked up Strength\n"), "") \
+ MSG_INFO_NOTIF(2, INFO_QUIT_DISCONNECT, 1, 0, "s1", "", "", _("^BG%s^F3 disconnected\n"), "") \
+ MSG_INFO_NOTIF(2, INFO_QUIT_KICK_IDLING, 1, 0, "s1", "", "", _("^BG%s^F3 was kicked for idling\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_QUIT_KICK_SPECTATING, 0, 0, "", "", "", _("^F2You were kicked from the server because you are a spectator and spectators aren't allowed at the moment.\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_QUIT_SPECTATE, 1, 0, "s1", "", "", _("^BG%s^F3 is now spectating\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_RACE_ABANDONED, 1, 0, "s1", "", "", _("^BG%s^BG has abandoned the race\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_RACE_FAIL_RANKED, 1, 3, "s1 race_col f1ord race_col f2race_time race_diff", "s1", "race_newfail", _("^BG%s^BG couldn't break their %s%s^BG place record of %s%s %s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_RACE_FAIL_UNRANKED, 1, 3, "s1 race_col f1ord race_col f2race_time race_diff", "s1", "race_newfail", _("^BG%s^BG couldn't break the %s%s^BG place record of %s%s %s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_RACE_FINISHED, 1, 0, "s1", "", "", _("^BG%s^BG has finished the race\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_RACE_NEW_BROKEN, 2, 3, "s1 s2 race_col f1ord race_col f2race_time race_diff", "s1 s2", "race_newrankyellow", _("^BG%s^BG broke %s^BG's %s%s^BG place record with %s%s %s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_RACE_NEW_IMPROVED, 1, 3, "s1 race_col f1ord race_col f2race_time race_diff", "s1", "race_newtime", _("^BG%s^BG improved their %s%s^BG place record with %s%s %s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_RACE_NEW_MISSING_UID, 1, 1, "s1 f1race_time", "s1", "race_newfail", _("^BG%s^BG scored a new record with ^F2%s^BG, but unfortunately lacks a UID and will be lost.\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_RACE_NEW_SET, 1, 2, "s1 race_col f1ord race_col f2race_time", "s1", "race_newrecordserver", _("^BG%s^BG set the %s%s^BG place record with %s%s\n"), "") \
+ MULTITEAM_INFO(1, INFO_SCORES_, 4, 0, 0, "", "", "", _("^TC^TT ^BGteam scores!\n"), "") \
+ 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!\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_SUPERWEAPON_PICKUP, 1, 0, "s1", "s1", "strength", _("^BG%s^K1 picked up a Superweapon\n"), "") \
+ MSG_INFO_NOTIF(2, INFO_VERSION_BETA, 2, 0, "s1 s2", "", "", _("^F4NOTE: ^BGThe server is running ^F1Xonotic %s (beta)^BG, you have ^F2Xonotic %s\n"), "") \
+ MSG_INFO_NOTIF(2, INFO_VERSION_OLD, 2, 0, "s1 s2", "", "", _("^F4NOTE: ^BGThe server is running ^F1Xonotic %s^BG, you have ^F2Xonotic %s\n"), "") \
+ 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!\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_WATERMARK, 1, 0, "s1", "", "", _("^F3SVQC Build information: ^F4%s\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_FIREBALL_SUICIDE_FIREMINE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponfireball", _("^BG%s^K1 forgot about their firemine%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_HAGAR_MURDER_BURST, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponhagar", _("^BG%s%s^K1 was pummeled by a burst of ^BG%s^K1's Hagar rockets%s%s\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_HAGAR_MURDER_SPRAY, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponhagar", _("^BG%s%s^K1 was pummeled by ^BG%s^K1's Hagar rockets%s%s\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER_HEADSHOT, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_headshot", _("^BG%s%s^K1 was shot in the head with a Rifle by ^BG%s^K1%s%s\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "") \
+ 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\n"), "")
+
+#define MULTITEAM_CENTER(default,prefix,teams,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))) \
+ MSG_CENTER_NOTIF(default, prefix##BLUE, strnum, flnum, args, cpid, durcnt, TCR(normal, COL_TEAM_2, strtoupper(NAME_TEAM_2)), TCR(gentle, COL_TEAM_2, strtoupper(NAME_TEAM_2))) \
+ #if teams >= 3 \
+ MSG_CENTER_NOTIF(default, prefix##YELLOW, strnum, flnum, args, cpid, durcnt, TCR(normal, COL_TEAM_3, strtoupper(NAME_TEAM_3)), TCR(gentle, COL_TEAM_3, strtoupper(NAME_TEAM_3))) \
+ #endif \
+ #if teams >= 4 \
+ MSG_CENTER_NOTIF(default, prefix##PINK, strnum, flnum, args, cpid, durcnt, TCR(normal, COL_TEAM_4, strtoupper(NAME_TEAM_4)), TCR(gentle, COL_TEAM_4, strtoupper(NAME_TEAM_4))) \
+ #endif
+#define MSG_CENTER_NOTIFICATIONS \
+ MSG_CENTER_NOTIF(1, CENTER_ARENA_BEGIN, 0, 0, "", CPID_ARENA, "2 0", _("^F4Begin!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_ARENA_NEEDPLAYER, 0, 0, "", CPID_ARENA, "2 0", _("^BGNeed at least 1 player in each team to play Clan Arena!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_ARENA_ROUNDSTART, 0, 1, "", CPID_ARENA, "1 f1", _("^F4Round will start in ^COUNT"), "") \
+ 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_GAMESTART, "2 0", _("^F4Begin!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_COUNTDOWN_GAMESTART, 0, 1, "", CPID_GAMESTART, "1 f1", _("^F4Game starts in ^COUNT"), "") \
+ 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_CTF_FLAG_THROW_PUNISH, 0, 1, "f1secs", CPID_CTF_LOWPRIO, "0 0", _("^BGToo many flag throws! Throwing disabled for %s."), "") \
+ MULTITEAM_CENTER(1, CENTER_CTF_PASS_OTHER_, 2, 2, 0, "s1 s2", CPID_CTF_PASS, "0 0", _("^BG%s^BG passed the ^TC^TT^BG flag to %s"), "") \
+ MULTITEAM_CENTER(1, CENTER_CTF_PASS_RECEIVED_, 2, 1, 0, "s1", CPID_CTF_PASS, "0 0", _("^BGYou received the ^TC^TT^BG flag from %s"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_CTF_PASS_REQUESTED, 1, 0, "s1 pass_key", CPID_CTF_PASS, "0 0", _("^BG%s^BG requests you to pass the flag%s"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_CTF_PASS_REQUESTING, 1, 0, "s1", CPID_CTF_PASS, "0 0", _("^BGRequesting %s^BG to pass you the flag"), "") \
+ MULTITEAM_CENTER(1, CENTER_CTF_PASS_SENT_, 2, 1, 0, "s1", CPID_CTF_PASS, "0 0", _("^BGYou passed the ^TC^TT^BG flag to %s"), "") \
+ MULTITEAM_CENTER(1, CENTER_CTF_PICKUP_, 2, 0, 0, "", CPID_CTF_LOWPRIO, "0 0", _("^BGYou got the ^TC^TT^BG flag!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_CTF_PICKUP_ENEMY, 1, 0, "s1", CPID_CTF_LOWPRIO, "0 0", _("^BGThe %senemy^BG got your flag! Retrieve it!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_CTF_PICKUP_ENEMY_VERBOSE, 2, 0, "s1 s2 s1", CPID_CTF_LOWPRIO, "0 0", _("^BGThe %senemy (^BG%s%s)^BG got your flag! Retrieve it!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_CTF_PICKUP_TEAM, 1, 0, "s1", CPID_CTF_LOWPRIO, "0 0", _("^BGYour %steam mate^BG got the flag! Protect them!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_CTF_PICKUP_TEAM_VERBOSE, 2, 0, "s1 s2 s1", CPID_CTF_LOWPRIO, "0 0", _("^BGYour %steam mate (^BG%s%s)^BG got the flag! Protect them!"), "") \
+ MULTITEAM_CENTER(1, CENTER_CTF_RETURN_, 2, 0, 0, "", CPID_CTF_LOWPRIO, "0 0", _("^BGYou returned the ^TC^TT^BG flag!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_CTF_STALEMATE_CARRIER, 0, 0, "", CPID_STALEMATE, "0 0", _("^BGStalemate! Enemies can now see you on radar!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_CTF_STALEMATE_OTHER, 0, 0, "", CPID_STALEMATE, "0 0", _("^BGStalemate! Flag carriers can now be seen by enemies on radar!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_MURDER_FRAG, 1, 1, "spree_cen s1", NO_CPID, "0 0", _("^K3%sYou fragged ^BG%s"), _("^K3%sYou scored against ^BG%s")) \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_MURDER_FRAGGED, 1, 1, "spree_cen s1", NO_CPID, "0 0", _("^K1%sYou were fragged by ^BG%s"), _("^K1%sYou were scored against by ^BG%s")) \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_MURDER_FRAGGED_VERBOSE, 1, 4, "spree_cen s1 frag_stats", NO_CPID, "0 0", _("^K1%sYou were fragged by ^BG%s^BG%s"), _("^K1%sYou were scored against by ^BG%s^BG%s")) \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_MURDER_FRAG_VERBOSE, 1, 2, "spree_cen s1 frag_ping", NO_CPID, "0 0", _("^K3%sYou fragged ^BG%s^BG%s"), _("^K3%sYou scored against ^BG%s^BG%s")) \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_MURDER_TYPEFRAG, 1, 1, "spree_cen s1", NO_CPID, "0 0", _("^K1%sYou typefragged ^BG%s"), _("^K1%sYou scored against ^BG%s^K1 while they were typing")) \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_MURDER_TYPEFRAGGED, 1, 1, "spree_cen s1", NO_CPID, "0 0", _("^K1%sYou were typefragged by ^BG%s"), _("^K1%sYou were scored against by ^BG%s^K1 while typing!")) \
+ 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_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_CHEAT, 0, 0, "", NO_CPID, "0 0", _("^K1You unfairly eliminated yourself!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_CUSTOM, 2, 0, "s2", NO_CPID, "0 0", _("^K1You were %s"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_DROWN, 0, 0, "", NO_CPID, "0 0", _("^K1You couldn't catch your breath!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_FALL, 0, 0, "", NO_CPID, "0 0", _("^K1You hit the ground with a crunch!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_FIRE, 0, 0, "", NO_CPID, "0 0", _("^K1You got a little bit too crispy!"), _("^K1You felt a little too hot!")) \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_GENERIC, 0, 0, "", NO_CPID, "0 0", _("^K1You killed your own dumb self!"), _("^K1You need to be more careful!")) \
+ 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_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_SELF_SLIME, 0, 0, "", NO_CPID, "0 0", _("^K1You melted away in slime!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_SUICIDE, 0, 0, "", NO_CPID, "0 0", _("^K1You committed suicide!"), _("^K1You ended it all!")) \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_SWAMP, 0, 0, "", NO_CPID, "0 0", _("^K1You got stuck in a swamp!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_TEAMCHANGE, 0, 1, "death_team", NO_CPID, "0 0", _("^BGYou are now on: %s"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_TOUCHEXPLODE, 0, 0, "", NO_CPID, "0 0", _("^K1You died in an accident!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_TURRET, 0, 0, "", NO_CPID, "0 0", _("^K1You were fragged by a turret!"), _("^K1You had an unfortunate run in with a turret!")) \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_TURRET_EWHEEL, 0, 0, "", NO_CPID, "0 0", _("^K1You were fragged by an eWheel turret!"), _("^K1You had an unfortunate run in with an eWheel turret!")) \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_TURRET_WALK, 0, 0, "", NO_CPID, "0 0", _("^K1You were fragged by a Walker turret!"), _("^K1You had an unfortunate run in with a Walker turret!")) \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_VH_BUMB_DEATH, 0, 0, "", NO_CPID, "0 0", _("^K1You got caught in the blast of a Bumblebee explosion!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_VH_CRUSH, 0, 0, "", NO_CPID, "0 0", _("^K1You were crushed by a vehicle!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_VH_RAPT_BOMB, 0, 0, "", NO_CPID, "0 0", _("^K1You were caught in a Raptor cluster bomb!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_VH_RAPT_DEATH, 0, 0, "", NO_CPID, "0 0", _("^K1You got caught in the blast of a Raptor explosion!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_VH_SPID_DEATH, 0, 0, "", NO_CPID, "0 0", _("^K1You got caught in the blast of a Spiderbot explosion!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_VH_SPID_ROCKET, 0, 0, "", NO_CPID, "0 0", _("^K1You were blasted to bits by a Spiderbot rocket!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_VH_WAKI_DEATH, 0, 0, "", NO_CPID, "0 0", _("^K1You got caught in the blast of a Racer explosion!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_VH_WAKI_ROCKET, 0, 0, "", NO_CPID, "0 0", _("^K1You couldn't find shelter from a Racer rocket!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_DEATH_SELF_VOID, 0, 0, "", NO_CPID, "0 0", _("^K1Watch your step!"), "") \
+ 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_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_REVIVED, 1, 0, "s1", NO_CPID, "0 0", _("^K3You were revived by ^BG%s"), "") \
+ MULTITEAM_CENTER(1, CENTER_FREEZETAG_ROUND_WIN_, 4, 0, 0, "", NO_CPID, "0 0", _("^TC^TT^BG team wins the round, all other teams were frozen"), "") \
+ 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", _("^K1You spawned after the round started, you'll spawn as frozen"), "") \
+ 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_ITEM_WEAPON_NOAMMO, 0, 1, "item_wepname", CPID_ITEM, "item_centime 0", _("^BGYou don't have enough ammo for the ^F1%s"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_ITEM_WEAPON_PRIMORSEC, 0, 3, "item_wepname f2primsec f3primsec", CPID_ITEM, "item_centime 0", _("^F1%s %s^BG is unable to fire, but its ^F1%s^BG can"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_ITEM_WEAPON_UNAVAILABLE, 0, 1, "item_wepname", CPID_ITEM, "item_centime 0", _("^F1%s^BG is ^F4not available^BG on this map"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_JOIN_NOSPAWNS, 0, 0, "", CPID_PREVENT_JOIN, "0 0", _("^K1No spawnpoints available!\nHope your team can fix it..."), "") \
+ MSG_CENTER_NOTIF(1, CENTER_JOIN_PREVENT, 0, 0, "", CPID_PREVENT_JOIN, "0 0", _("^K1You may not join the game at this time.\nThe player limit reached maximum capacity."), "") \
+ MSG_CENTER_NOTIF(1, CENTER_KEEPAWAY_DROPPED, 1, 0, "s1", CPID_KEEPAWAY, "0 0", _("^BG%s^BG has dropped the ball!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_KEEPAWAY_PICKUP, 1, 0, "s1", CPID_KEEPAWAY, "0 0", _("^BG%s^BG has picked up the ball!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_KEEPAWAY_WARN, 0, 0, "", CPID_KEEPAWAY_WARN, "0 0", _("^BGKilling people while you don't have the ball gives no points!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_KEYHUNT_HELP, 0, 0, "", CPID_KEYHUNT, "0 0", _("^BGAll keys are in your team's hands!\nHelp the key carriers to meet!"), "") \
+ MULTITEAM_CENTER(1, CENTER_KEYHUNT_INTERFERE_, 4, 0, 0, "", CPID_KEYHUNT, "0 0", _("^BGAll keys are in ^TC^TT team^BG's hands!\nInterfere ^F4NOW^BG!"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_KEYHUNT_MEET, 0, 0, "", CPID_KEYHUNT, "0 0", _("^BGAll keys are in your team's hands!\nMeet the other key carriers ^F4NOW^BG!"), "") \
+ 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, "kh_teams", CPID_KEYHUNT_OTHER, "0 0", _("^BGWaiting for players to join...\nNeed active players for: %s"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_LMS_CAMPCHECK, 0, 0, "", CPID_LMS_CAMP, "0 0", _("^F2Don't camp!"), "") \
+ 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_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_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_TIME, 0, 1, "f1time", CPID_OVERTIME, "0 0", _("^F2Now playing ^F4OVERTIME^F2!\nAdded ^F4%s^F2 to the game!"), "") \
+ 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_POWERDOWN_STRENGTH, 0, 0, "", CPID_POWERUP, "0 0", _("^F2Strength has worn off"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_POWERUP_INVISIBILITY, 0, 0, "", CPID_POWERUP, "0 0", _("^F2You are invisible"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_POWERUP_SHIELD, 0, 0, "", CPID_POWERUP, "0 0", _("^F2Shield surrounds you"), "") \
+ 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_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"), "") \
+ MULTITEAM_CENTER(1, CENTER_TEAMCHANGE_, 4, 0, 1, "", CPID_TEAMCHANGE, "1 f1", _("^K1Changing to ^TC^TT^K1 in ^COUNT"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_TEAMCHANGE_AUTO, 0, 1, "", CPID_TEAMCHANGE, "1 f1", _("^K1Changing team in ^COUNT"), "") \
+ 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"), "")
+
+#define MSG_MULTI_NOTIFICATIONS \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_CHEAT, INFO_DEATH_MURDER_CHEAT, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_DROWN, INFO_DEATH_MURDER_DROWN, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_FALL, INFO_DEATH_MURDER_FALL, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_FIRE, INFO_DEATH_MURDER_FIRE, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_LAVA, INFO_DEATH_MURDER_LAVA, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_SHOOTING_STAR, INFO_DEATH_MURDER_SHOOTING_STAR, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_SLIME, INFO_DEATH_MURDER_SLIME, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_SWAMP, INFO_DEATH_MURDER_SWAMP, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_TELEFRAG, INFO_DEATH_MURDER_TELEFRAG, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_TOUCHEXPLODE, INFO_DEATH_MURDER_TOUCHEXPLODE, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_VH_BUMB_DEATH, INFO_DEATH_MURDER_VH_BUMB_DEATH, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_VH_BUMB_GUN, INFO_DEATH_MURDER_VH_BUMB_GUN, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_VH_CRUSH, INFO_DEATH_MURDER_VH_CRUSH, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_VH_RAPT_BOMB, INFO_DEATH_MURDER_VH_RAPT_BOMB, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_VH_RAPT_CANNON, INFO_DEATH_MURDER_VH_RAPT_CANNON, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_VH_RAPT_DEATH, INFO_DEATH_MURDER_VH_RAPT_DEATH, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_VH_SPID_DEATH, INFO_DEATH_MURDER_VH_SPID_DEATH, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_VH_SPID_MINIGUN, INFO_DEATH_MURDER_VH_SPID_MINIGUN, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_VH_SPID_ROCKET, INFO_DEATH_MURDER_VH_SPID_ROCKET, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_VH_WAKI_DEATH, INFO_DEATH_MURDER_VH_WAKI_DEATH, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_VH_WAKI_GUN, INFO_DEATH_MURDER_VH_WAKI_GUN, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_VH_WAKI_ROCKET, INFO_DEATH_MURDER_VH_WAKI_ROCKET, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_MURDER_VOID, INFO_DEATH_MURDER_VOID, NO_MSG) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_AUTOTEAMCHANGE, INFO_DEATH_SELF_AUTOTEAMCHANGE, CENTER_DEATH_SELF_AUTOTEAMCHANGE) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_BETRAYAL, INFO_DEATH_SELF_BETRAYAL, CENTER_DEATH_SELF_BETRAYAL) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_CAMP, INFO_DEATH_SELF_CAMP, CENTER_DEATH_SELF_CAMP) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_CHEAT, INFO_DEATH_SELF_CHEAT, CENTER_DEATH_SELF_CHEAT) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_CUSTOM, INFO_DEATH_SELF_GENERIC, CENTER_DEATH_SELF_CUSTOM) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_DROWN, INFO_DEATH_SELF_DROWN, CENTER_DEATH_SELF_DROWN) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_FALL, INFO_DEATH_SELF_FALL, CENTER_DEATH_SELF_FALL) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_FIRE, INFO_DEATH_SELF_FIRE, CENTER_DEATH_SELF_FIRE) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_GENERIC, INFO_DEATH_SELF_GENERIC, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_LAVA, INFO_DEATH_SELF_LAVA, CENTER_DEATH_SELF_LAVA) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_NOAMMO, INFO_DEATH_SELF_NOAMMO, CENTER_DEATH_SELF_NOAMMO) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_ROT, INFO_DEATH_SELF_ROT, CENTER_DEATH_SELF_ROT) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_SHOOTING_STAR, INFO_DEATH_SELF_SHOOTING_STAR, CENTER_DEATH_SELF_SHOOTING_STAR) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_SLIME, INFO_DEATH_SELF_SLIME, CENTER_DEATH_SELF_SLIME) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_SUICIDE, INFO_DEATH_SELF_SUICIDE, CENTER_DEATH_SELF_SUICIDE) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_SWAMP, INFO_DEATH_SELF_SWAMP, CENTER_DEATH_SELF_SWAMP) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_TEAMCHANGE, INFO_DEATH_SELF_TEAMCHANGE, CENTER_DEATH_SELF_TEAMCHANGE) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_TOUCHEXPLODE, INFO_DEATH_SELF_TOUCHEXPLODE, CENTER_DEATH_SELF_TOUCHEXPLODE) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET, INFO_DEATH_SELF_TURRET, CENTER_DEATH_SELF_TURRET) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_EWHEEL, INFO_DEATH_SELF_TURRET_EWHEEL, CENTER_DEATH_SELF_TURRET_EWHEEL) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_FLAC, INFO_DEATH_SELF_TURRET_FLAC, CENTER_DEATH_SELF_TURRET) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_HELLION, INFO_DEATH_SELF_TURRET_HELLION, CENTER_DEATH_SELF_TURRET) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_HK, INFO_DEATH_SELF_TURRET_HK, CENTER_DEATH_SELF_TURRET) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_MACHINEGUN, INFO_DEATH_SELF_TURRET_MACHINEGUN, CENTER_DEATH_SELF_TURRET) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_MLRS, INFO_DEATH_SELF_TURRET_MLRS, CENTER_DEATH_SELF_TURRET) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_PHASER, INFO_DEATH_SELF_TURRET_PHASER, CENTER_DEATH_SELF_TURRET) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_PLASMA, INFO_DEATH_SELF_TURRET_PLASMA, CENTER_DEATH_SELF_TURRET) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_TESLA, INFO_DEATH_SELF_TURRET_TESLA, CENTER_DEATH_SELF_TURRET) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_WALK_GUN, INFO_DEATH_SELF_TURRET_WALK_GUN, CENTER_DEATH_SELF_TURRET_WALK) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_WALK_MEELE, INFO_DEATH_SELF_TURRET_WALK_MEELE, CENTER_DEATH_SELF_TURRET_WALK) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_TURRET_WALK_ROCKET, INFO_DEATH_SELF_TURRET_WALK_ROCKET, CENTER_DEATH_SELF_TURRET_WALK) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_VH_BUMB_DEATH, INFO_DEATH_SELF_VH_BUMB_DEATH, CENTER_DEATH_SELF_VH_BUMB_DEATH) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_VH_CRUSH, INFO_DEATH_SELF_VH_CRUSH, CENTER_DEATH_SELF_VH_CRUSH) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_VH_RAPT_BOMB, INFO_DEATH_SELF_VH_RAPT_BOMB, CENTER_DEATH_SELF_VH_RAPT_BOMB) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_VH_RAPT_DEATH, INFO_DEATH_SELF_VH_RAPT_DEATH, CENTER_DEATH_SELF_VH_RAPT_DEATH) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_VH_SPID_DEATH, INFO_DEATH_SELF_VH_SPID_DEATH, CENTER_DEATH_SELF_VH_SPID_DEATH) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_VH_SPID_ROCKET, INFO_DEATH_SELF_VH_SPID_ROCKET, CENTER_DEATH_SELF_VH_SPID_ROCKET) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_VH_WAKI_DEATH, INFO_DEATH_SELF_VH_WAKI_DEATH, CENTER_DEATH_SELF_VH_WAKI_DEATH) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_VH_WAKI_ROCKET, INFO_DEATH_SELF_VH_WAKI_ROCKET, CENTER_DEATH_SELF_VH_WAKI_ROCKET) \
+ MSG_MULTI_NOTIF(1, DEATH_SELF_VOID, INFO_DEATH_SELF_VOID, CENTER_DEATH_SELF_VOID) \
+ MSG_MULTI_NOTIF(1, ITEM_WEAPON_DONTHAVE, INFO_ITEM_WEAPON_DONTHAVE, CENTER_ITEM_WEAPON_DONTHAVE) \
+ MSG_MULTI_NOTIF(1, ITEM_WEAPON_DROP, INFO_ITEM_WEAPON_DROP, CENTER_ITEM_WEAPON_DROP) \
+ MSG_MULTI_NOTIF(1, ITEM_WEAPON_GOT, INFO_ITEM_WEAPON_GOT, CENTER_ITEM_WEAPON_GOT) \
+ MSG_MULTI_NOTIF(1, ITEM_WEAPON_NOAMMO, INFO_ITEM_WEAPON_NOAMMO, CENTER_ITEM_WEAPON_NOAMMO) \
+ MSG_MULTI_NOTIF(1, ITEM_WEAPON_PRIMORSEC, INFO_ITEM_WEAPON_PRIMORSEC, CENTER_ITEM_WEAPON_PRIMORSEC) \
+ MSG_MULTI_NOTIF(1, ITEM_WEAPON_UNAVAILABLE, INFO_ITEM_WEAPON_UNAVAILABLE, CENTER_ITEM_WEAPON_UNAVAILABLE) \
+ MSG_MULTI_NOTIF(1, WEAPON_ACCORDEON_MURDER, INFO_WEAPON_ACCORDEON_MURDER, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_ACCORDEON_SUICIDE, INFO_WEAPON_ACCORDEON_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_CRYLINK_MURDER, INFO_WEAPON_CRYLINK_MURDER, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_CRYLINK_SUICIDE, INFO_WEAPON_CRYLINK_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_ELECTRO_MURDER_BOLT, INFO_WEAPON_ELECTRO_MURDER_BOLT, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_ELECTRO_MURDER_COMBO, INFO_WEAPON_ELECTRO_MURDER_COMBO, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_ELECTRO_MURDER_ORBS, INFO_WEAPON_ELECTRO_MURDER_ORBS, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_ELECTRO_SUICIDE_BOLT, INFO_WEAPON_ELECTRO_SUICIDE_BOLT, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_ELECTRO_SUICIDE_ORBS, INFO_WEAPON_ELECTRO_SUICIDE_ORBS, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_FIREBALL_MURDER_BLAST, INFO_WEAPON_FIREBALL_MURDER_BLAST, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_FIREBALL_MURDER_FIREMINE, INFO_WEAPON_FIREBALL_MURDER_FIREMINE, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_FIREBALL_SUICIDE_BLAST, INFO_WEAPON_FIREBALL_SUICIDE_BLAST, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_FIREBALL_SUICIDE_FIREMINE, INFO_WEAPON_FIREBALL_SUICIDE_FIREMINE, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_HAGAR_MURDER_BURST, INFO_WEAPON_HAGAR_MURDER_BURST, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_HAGAR_MURDER_SPRAY, INFO_WEAPON_HAGAR_MURDER_SPRAY, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_HAGAR_SUICIDE, INFO_WEAPON_HAGAR_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_HLAC_MURDER, INFO_WEAPON_HLAC_MURDER, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_HLAC_SUICIDE, INFO_WEAPON_HLAC_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_HOOK_MURDER, INFO_WEAPON_HOOK_MURDER, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_KLEINBOTTLE_MURDER, INFO_WEAPON_KLEINBOTTLE_MURDER, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_KLEINBOTTLE_SUICIDE, INFO_WEAPON_KLEINBOTTLE_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_LASER_MURDER, INFO_WEAPON_LASER_MURDER, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_LASER_SUICIDE, INFO_WEAPON_LASER_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_MINELAYER_MURDER, INFO_WEAPON_MINELAYER_MURDER, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_MINELAYER_SUICIDE, INFO_WEAPON_MINELAYER_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_MINSTANEX_MURDER, INFO_WEAPON_MINSTANEX_MURDER, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_MORTAR_MURDER_BOUNCE, INFO_WEAPON_MORTAR_MURDER_BOUNCE, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_MORTAR_MURDER_EXPLODE, INFO_WEAPON_MORTAR_MURDER_EXPLODE, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_MORTAR_SUICIDE_BOUNCE, INFO_WEAPON_MORTAR_SUICIDE_BOUNCE, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_MORTAR_SUICIDE_EXPLODE, INFO_WEAPON_MORTAR_SUICIDE_EXPLODE, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_NEX_MURDER, INFO_WEAPON_NEX_MURDER, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_RIFLE_MURDER, INFO_WEAPON_RIFLE_MURDER, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_RIFLE_MURDER_HAIL, INFO_WEAPON_RIFLE_MURDER_HAIL, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_RIFLE_MURDER_HAIL_PIERCING, INFO_WEAPON_RIFLE_MURDER_HAIL_PIERCING, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_RIFLE_MURDER_HEADSHOT, INFO_WEAPON_RIFLE_MURDER_HEADSHOT, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_RIFLE_MURDER_PIERCING, INFO_WEAPON_RIFLE_MURDER_PIERCING, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_ROCKETLAUNCHER_MURDER_DIRECT, INFO_WEAPON_ROCKETLAUNCHER_MURDER_DIRECT, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_ROCKETLAUNCHER_MURDER_SPLASH, INFO_WEAPON_ROCKETLAUNCHER_MURDER_SPLASH, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_ROCKETLAUNCHER_SUICIDE, INFO_WEAPON_ROCKETLAUNCHER_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_SEEKER_MURDER_SPRAY, INFO_WEAPON_SEEKER_MURDER_SPRAY, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_SEEKER_MURDER_TAG, INFO_WEAPON_SEEKER_MURDER_TAG, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_SEEKER_SUICIDE, INFO_WEAPON_SEEKER_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_SHOTGUN_MURDER, INFO_WEAPON_SHOTGUN_MURDER, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_SHOTGUN_MURDER_SLAP, INFO_WEAPON_SHOTGUN_MURDER_SLAP, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_THINKING_WITH_PORTALS, INFO_WEAPON_THINKING_WITH_PORTALS, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_TUBA_MURDER, INFO_WEAPON_TUBA_MURDER, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_TUBA_SUICIDE, INFO_WEAPON_TUBA_SUICIDE, CENTER_DEATH_SELF_GENERIC) \
+ MSG_MULTI_NOTIF(1, WEAPON_UZI_MURDER_SNIPE, INFO_WEAPON_UZI_MURDER_SNIPE, NO_MSG) \
+ MSG_MULTI_NOTIF(1, WEAPON_UZI_MURDER_SPRAY, INFO_WEAPON_UZI_MURDER_SPRAY, NO_MSG)
+
+
+// ===========================
+// Special CVAR Declarations
+// ===========================
+
+// MAKE SURE THIS IS ALWAYS SYNCHRONIZED WITH THE DUMP
+// NOTIFICATIONS FUNCTION IN THE .QC FILE!
+
+#define NOTIF_ADD_AUTOCVAR(name,default) var float autocvar_notification_##name = default;
+
+var float autocvar_notification_show_location = FALSE;
+var string autocvar_notification_show_location_string = ""; //_(" at the %s");
+var float autocvar_notification_show_sprees = TRUE;
+var float autocvar_notification_show_sprees_info = 3; // 0 = off, 1 = target only, 2 = attacker only, 3 = target and attacker
+var float autocvar_notification_show_sprees_info_newline = TRUE;
+var float autocvar_notification_show_sprees_info_specialonly = TRUE;
+var float autocvar_notification_errors_are_fatal = TRUE;
+var float autocvar_notification_lifetime_runtime = 0.5;
+var float autocvar_notification_lifetime_mapload = 10;
+
+#ifdef SVQC
+.float FRAG_VERBOSE;
+void Notification_GetCvars(void);
+var float autocvar_notification_server_allows_frag_verbose = 1; // 0 = no, 1 = warmup only, 2 = all the time
+var float autocvar_notification_server_allows_location = 1; // 0 = no, 1 = yes
+#else
+var float autocvar_notification_item_centerprinttime = 1.5;
+
+// 0 = no, 1 = yes, 2 = forced on for all MSG_INFO notifs
+// DISABLED IN CODE, BUT ENABLED IN CONFIG FOR COMPATIBILITY WITH OLD CLIENTS
+var float autocvar_notification_allow_chatboxprint = 0;
+
+var float autocvar_notification_show_sprees_center = TRUE;
+var float autocvar_notification_show_sprees_center_specialonly = TRUE;
+var float autocvar_notification_frag_verbose = TRUE;
+#endif
+
+
+// ============================
+// Notification Argument List
+// ============================
+/*
+ These arguments get replaced with the Local_Notification_sprintf
+ and other such functions found in notifications.qc to supply data
+ from networked notifications to their usage in sprintf... It
+ allows for more dynamic data to be inferred by the local
+ notification parser, so that the server does not have to network
+ anything too crazy on a per-client/per-situation basis.
+
+ Pay attention to the CSQC/SVQC relations, some of these are redefined
+ in slightly different ways for different programs, this is because the
+ server does a more conservative approach to the notifs than the client.
+
+ All arguments are swapped into strings, so be sure that your
+ sprintf usage matches with proper %s placement.
+
+ Argument descriptions:
+ s1-s4: string arguments to be literally swapped into sprintf
+ s2loc: s2 string of locations of deaths or other events
+ s3loc: s3 string of locations of deaths or other events
+ f1-f4: float arguments expanded into strings to be swapped into sprintf
+ f1p2dec: f1 float to string with 2 decimal places
+ f2p2dec: f2 float to string with 2 decimal places
+ f2primsec: f2 float primary or secondary selection for weapons
+ f3primsec: f3 float primary or secondary selection for weapons
+ f1secs: count_seconds of f1
+ f1ord: count_ordinal of f1
+ f1time: process_time of f1
+ f1race_time: mmssss of f1
+ f2race_time: mmssss of f2
+ race_col: color of race time/position (i.e. good or bad)
+ race_diff: show time difference between f2 and f3
+ kh_teams: show which teams still need players in keyhunt centerprint
+ pass_key: find the keybind for "passing" or "dropping" in CTF game mode
+ frag_ping: show the ping of a player
+ frag_stats: show health/armor/ping of a player
+ frag_pos: show score status and position in the match of a player
+ spree_cen: centerprint notif for kill spree/how many kills they have
+ spree_inf: info notif for kill spree/how many kills they have
+ spree_end: placed at the end of murder messages to show ending of sprees
+ spree_lost: placed at the end of suicide messages to show losing of sprees
+ 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
+ death_team: show the full name of the team a player is switching from
+*/
+
+#define NOTIF_MAX_ARGS 7
+#define NOTIF_MAX_HUDARGS 2
+#define NOTIF_MAX_DURCNT 2
+
+string arg_slot[NOTIF_MAX_ARGS];
+
+#define ARG_CS_SV_HA 1 // enabled on CSQC, SVQC, and Hudargs
+#define ARG_CS_SV_DC 2 // enabled on CSQC, SVQC, and durcnt centerprint
+#define ARG_CS_SV 3 // enabled on CSQC and SVQC
+#define ARG_CS 4 // unique result to CSQC
+#define ARG_SV 5 // unique result to SVQC
+#define ARG_DC 6 // unique result to durcnt/centerprint
+
+// todo possible idea.... declare how many floats/strings each arg needs, and then dynamically increment the input
+// this way, we don't need to have duplicates like i.e. s2loc and s3loc?
+
+#define NOTIF_ARGUMENT_LIST \
+ ARG_CASE(ARG_CS_SV_HA, "s1", s1) \
+ ARG_CASE(ARG_CS_SV_HA, "s2", s2) \
+ ARG_CASE(ARG_CS_SV_HA, "s3", s3) \
+ ARG_CASE(ARG_CS_SV_HA, "s4", s4) \
+ ARG_CASE(ARG_CS_SV, "s2loc", ((autocvar_notification_show_location && (s2 != "")) ? sprintf(( ((tmp_s = autocvar_notification_show_location_string) != "") ? tmp_s : _(" (near %s)") ), s2) : "")) \
+ ARG_CASE(ARG_CS_SV, "s3loc", ((autocvar_notification_show_location && (s3 != "")) ? sprintf(( ((tmp_s = autocvar_notification_show_location_string) != "") ? tmp_s : _(" (near %s)") ), s3) : "")) \
+ ARG_CASE(ARG_CS_SV_DC, "f1", ftos(f1)) \
+ ARG_CASE(ARG_CS_SV_DC, "f2", ftos(f2)) \
+ ARG_CASE(ARG_CS_SV, "f3", ftos(f3)) \
+ ARG_CASE(ARG_CS_SV, "f4", ftos(f4)) \
+ ARG_CASE(ARG_CS_SV, "f1p2dec", ftos_decimals(f1/100, 2)) \
+ ARG_CASE(ARG_CS_SV, "f2p2dec", ftos_decimals(f2/100, 2)) \
+ ARG_CASE(ARG_CS, "f2primsec", (f2 ? _("secondary") : _("primary"))) \
+ ARG_CASE(ARG_CS, "f3primsec", (f3 ? _("secondary") : _("primary"))) \
+ ARG_CASE(ARG_CS, "f1secs", count_seconds(f1)) \
+ ARG_CASE(ARG_CS_SV, "f1ord", count_ordinal(f1)) \
+ ARG_CASE(ARG_CS, "f1time", process_time(2, f1)) \
+ ARG_CASE(ARG_CS_SV, "f1race_time", mmssss(f1)) \
+ ARG_CASE(ARG_CS_SV, "f2race_time", mmssss(f2)) \
+ 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, "kh_teams", notif_arg_kh_teams(f1, f2, f3, f4)) \
+ 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, "frag_pos", ((Should_Print_Score_Pos(f1)) ? sprintf("\n^BG%s", Read_Score_Pos(f1)) : ""))*/ \
+ ARG_CASE(ARG_CS, "spree_cen", (autocvar_notification_show_sprees ? notif_arg_spree_cen(f1) : "")) \
+ ARG_CASE(ARG_CS_SV, "spree_inf", (autocvar_notification_show_sprees ? notif_arg_spree_inf(1, input, s2, f2) : "")) \
+ ARG_CASE(ARG_CS_SV, "spree_end", (autocvar_notification_show_sprees ? notif_arg_spree_inf(-1, "", "", f1) : "")) \
+ 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_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)) \
+ ARG_CASE(ARG_CS, "death_team", Team_ColoredFullName(f1 - 1))
+
+#define NOTIF_HIT_MAX(count,funcname) if(sel_num == count) { backtrace(sprintf("%s: Hit maximum arguments!\n", funcname)); break; }
+#define NOTIF_HIT_UNKNOWN(token,funcname) { backtrace(sprintf("%s: Hit unknown token in selected string! '%s'\n", funcname, selected)); break; }
+
+#define KILL_SPREE_LIST \
+ SPREE_ITEM(3, 03, _("TRIPLE FRAG! "), _("%s^K1 made a TRIPLE FRAG! %s^BG"), _("%s^K1 made a TRIPLE SCORE! %s^BG")) \
+ SPREE_ITEM(5, 05, _("RAGE! "), _("%s^K1 unlocked RAGE! %s^BG"), _("%s^K1 made FIVE SCORES IN A ROW! %s^BG")) \
+ SPREE_ITEM(10, 10, _("MASSACRE! "), _("%s^K1 started a MASSACRE! %s^BG"), _("%s^K1 made TEN SCORES IN A ROW! %s^BG")) \
+ SPREE_ITEM(15, 15, _("MAYHEM! "), _("%s^K1 executed MAYHEM! %s^BG"), _("%s^K1 made FIFTEEN SCORES IN A ROW! %s^BG")) \
+ SPREE_ITEM(20, 20, _("BERSERKER! "), _("%s^K1 is a BERSERKER! %s^BG"), _("%s^K1 made TWENTY SCORES IN A ROW! %s^BG")) \
+ SPREE_ITEM(25, 25, _("CARNAGE! "), _("%s^K1 inflicts CARNAGE! %s^BG"), _("%s^K1 made TWENTY FIVE SCORES IN A ROW! %s^BG")) \
+ SPREE_ITEM(30, 30, _("ARMAGEDDON! "), _("%s^K1 unleashes ARMAGEDDON! %s^BG"), _("%s^K1 made THIRTY SCORES IN A ROW! %s^BG"))
+
+#ifdef CSQC
+string notif_arg_frag_ping(float newline, float fping)
+{
+ if(fping == NO_MSG)
+ return sprintf(CCR(_("%s(^F1Bot^BG)")), (newline ? "\n" : " "));
+ else
+ return sprintf(CCR(_("%s(Ping ^F1%d^BG)")), (newline ? "\n" : " "), fping);
+}
+
+string notif_arg_frag_stats(float fhealth, float farmor, float fping)
+{
+ if not(fhealth < 1)
+ return sprintf(CCR(_("\n(Health ^1%d^BG / Armor ^2%d^BG)%s")), fhealth, farmor, notif_arg_frag_ping(FALSE, fping));
+ else
+ return sprintf(CCR(_("\n(^F4Dead^BG)%s")), notif_arg_frag_ping(FALSE, fping));
+}
+
+string notif_arg_kh_teams(float f1, float f2, float f3, float f4)
+{
+ return sprintf("%s%s%s%s",
+ (f1 ?
+ sprintf("%s%s", Team_ColoredFullName(f1 - 1), ((f2 + f3 + f4) ? ", " : ""))
+ :
+ ""
+ ),
+ (f2 ?
+ sprintf("%s%s", Team_ColoredFullName(f2 - 1), ((f3 + f4) ? ", " : ""))
+ :
+ ""
+ ),
+ (f3 ?
+ sprintf("%s%s", Team_ColoredFullName(f3 - 1), (f4 ? ", " : ""))
+ :
+ ""
+ ),
+ (f4 ?
+ Team_ColoredFullName(f4 - 1)
+ :
+ ""
+ )
+ );
+}
+
+string notif_arg_spree_cen(float spree)
+{
+ // 0 = off, 1 = target (but only for first victim) and attacker
+ if(autocvar_notification_show_sprees_center)
+ {
+ if(spree > 1)
+ {
+ #define SPREE_ITEM(counta,countb,center,normal,gentle) \
+ case counta: { return normal_or_gentle(center, sprintf(_("%d score spree! "), spree)); }
+
+ switch(spree)
+ {
+ KILL_SPREE_LIST
+ default:
+ {
+ if not(autocvar_notification_show_sprees_center_specialonly)
+ {
+ return
+ sprintf(
+ normal_or_gentle(
+ _("%d frag spree! "),
+ _("%d score spree! ")
+ ),
+ spree);
+ }
+ else { return ""; } // don't show spree information if it isn't an achievement
+ }
+ }
+
+ #undef SPREE_ITEM
+ }
+ else if(spree == -1) // first blood
+ {
+ return normal_or_gentle(_("First blood! "), _("First score! "));
+ }
+ else if(spree == -2) // first victim
+ {
+ return normal_or_gentle(_("First victim! "), _("First casualty! "));
+ }
+ }
+ return "";
+}
+#endif
+
+string notif_arg_spree_inf(float type, string input, string player, float spree)
+{
+ switch(type)
+ {
+ case 1: // attacker kill spree
+ {
+ // 0 = off, 1 = target only, 2 = attacker only, 3 = target and attacker
+ // this conditional (& 2) is true for 2 and 3
+ if(autocvar_notification_show_sprees_info & 2)
+ {
+ #ifdef CSQC
+ string spree_newline =
+ ( autocvar_notification_show_sprees_info_newline ?
+ ((substring(input, 0, 1) == "\{3}") ? "\n\{3}" : "\n") : "" );
+ #else
+ string spree_newline =
+ (autocvar_notification_show_sprees_info_newline ? "\n" : "");
+ #endif
+
+ if(spree > 1)
+ {
+ #define SPREE_ITEM(counta,countb,center,normal,gentle) \
+ case counta: { return sprintf(CCR(normal_or_gentle(normal, gentle)), player, spree_newline); }
+
+ switch(spree)
+ {
+ KILL_SPREE_LIST
+ default:
+ {
+ if not(autocvar_notification_show_sprees_info_specialonly)
+ {
+ return
+ sprintf(
+ CCR(normal_or_gentle(
+ _("%s^K1 has %d frags in a row! %s^BG"),
+ _("%s^K1 made %d scores in a row! %s^BG")
+ )),
+ player,
+ spree,
+ spree_newline
+ );
+ }
+ else { return ""; } // don't show spree information if it isn't an achievement
+ }
+ }
+
+ #undef SPREE_ITEM
+ }
+ else if(spree == -1) // firstblood
+ {
+ return
+ sprintf(
+ CCR(normal_or_gentle(
+ _("%s^K1 drew first blood! %s^BG"),
+ _("%s^K1 got the first score! %s^BG")
+ )),
+ player,
+ spree_newline
+ );
+ }
+ }
+ break;
+ }
+
+ case -1: // kill spree ended
+ {
+ if((spree > 1) && (autocvar_notification_show_sprees_info & 1))
+ {
+ return
+ sprintf(normal_or_gentle(
+ _(", ending their %d frag spree"),
+ _(", ending their %d score spree")
+ ),
+ spree
+ );
+ }
+ break;
+ }
+
+ case -2: // kill spree lost
+ {
+ if((spree > 1) && (autocvar_notification_show_sprees_info & 1))
+ {
+ return
+ sprintf(normal_or_gentle(
+ _(", losing their %d frag spree"),
+ _(", losing their %d score spree")
+ ),
+ spree
+ );
+ }
+ break;
+ }
+ }
+ return "";
+}
+
+
+// ====================================
+// Initialization/Create Declarations
+// ====================================
+
+#define NOTIF_FIRST 1
+#define NOTIF_MAX 1024 // limit of recursive functions with ACCUMULATE_FUNCTION
+
+// error detection
+float notif_error;
+float notif_global_error;
+
+// notification entities
+entity msg_info_notifs[NOTIF_MAX];
+entity msg_center_notifs[NOTIF_MAX];
+entity msg_multi_notifs[NOTIF_MAX];
+
+// notification counts
+float NOTIF_INFO_COUNT;
+float NOTIF_CENTER_COUNT;
+float NOTIF_MULTI_COUNT;
+float NOTIF_CPID_COUNT;
+
+// notification entity values
+.float nent_default;
+.string nent_name;
+.float nent_id;
+.float nent_enabled;
+.entity nent_msginfo;
+.entity nent_msgcenter;
+.float nent_stringcount;
+.float nent_floatcount;
+.string nent_args;
+.string nent_hudargs;
+.string nent_icon;
+.float nent_cpid;
+.string nent_durcnt;
+.string nent_string;
+
+// networked notification values
+.float nent_broadcast;
+.entity nent_client;
+.float nent_net_type;
+.float nent_net_name;
+.string nent_strings[4];
+.float nent_floats[4];
+
+#define MSG_INFO_NOTIF(default,name,strnum,flnum,args,hudargs,icon,normal,gentle) \
+ NOTIF_ADD_AUTOCVAR(name, default) \
+ float name; \
+ void RegisterNotification_##name() \
+ { \
+ SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_INFO_COUNT) \
+ CHECK_MAX_COUNT(name, NOTIF_MAX, NOTIF_INFO_COUNT, "notifications") \
+ Create_Notification_Entity( \
+ default, /* var_default */ \
+ autocvar_notification_##name, /* var_cvar */ \
+ MSG_INFO, /* typeid */ \
+ name, /* nameid */ \
+ strtoupper(#name), /* namestring */ \
+ NO_MSG, /* infoname */ \
+ NO_MSG, /* centername */ \
+ strnum, /* strnum */ \
+ flnum, /* flnum */ \
+ args, /* args */ \
+ hudargs, /* hudargs */ \
+ icon, /* icon */ \
+ NO_MSG, /* cpid */ \
+ "", /* durcnt */ \
+ normal, /* normal */ \
+ gentle, /* gentle */ \
+ TRUE, /* msg_is_info */ \
+ FALSE); /* msg_is_multi */ \
+ } \
+ ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
+
+#define MSG_CENTER_NOTIF(default,name,strnum,flnum,args,cpid,durcnt,normal,gentle) \
+ NOTIF_ADD_AUTOCVAR(name, default) \
+ float name; \
+ float cpid; \
+ void RegisterNotification_##name() \
+ { \
+ SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_CENTER_COUNT) \
+ SET_FIELD_COUNT(cpid, NOTIF_FIRST, NOTIF_CPID_COUNT) \
+ CHECK_MAX_COUNT(name, NOTIF_MAX, NOTIF_CENTER_COUNT, "notifications") \
+ Create_Notification_Entity( \
+ default, /* var_default */ \
+ autocvar_notification_##name, /* var_cvar */ \
+ MSG_CENTER, /* typeid */ \
+ name, /* nameid */ \
+ strtoupper(#name), /* namestring */ \
+ NO_MSG, /* infoname */ \
+ NO_MSG, /* centername */ \
+ strnum, /* strnum */ \
+ flnum, /* flnum */ \
+ args, /* args */ \
+ "", /* hudargs */ \
+ "", /* icon */ \
+ cpid, /* cpid */ \
+ durcnt, /* durcnt */ \
+ normal, /* normal */ \
+ gentle, /* gentle */ \
+ FALSE, /* msg_is_info */ \
+ FALSE); /* msg_is_multi */ \
+ } \
+ ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
+
+#define MSG_MULTI_NOTIF(default,name,infoname,centername) \
+ NOTIF_ADD_AUTOCVAR(name, default) \
+ float name; \
+ void RegisterNotification_##name() \
+ { \
+ SET_FIELD_COUNT(name, NOTIF_FIRST, NOTIF_MULTI_COUNT) \
+ CHECK_MAX_COUNT(name, NOTIF_MAX, NOTIF_MULTI_COUNT, "notifications") \
+ Create_Notification_Entity( \
+ default, /* var_default */ \
+ autocvar_notification_##name, /* var_cvar */ \
+ MSG_MULTI, /* typeid */ \
+ name, /* nameid */ \
+ strtoupper(#name), /* namestring */ \
+ infoname, /* infoname */ \
+ centername, /* centername */ \
+ NO_MSG, /* strnum */ \
+ NO_MSG, /* flnum */ \
+ "", /* args */ \
+ "", /* hudargs */ \
+ "", /* icon */ \
+ NO_MSG, /* cpid */ \
+ "", /* durcnt */ \
+ "", /* normal */ \
+ "", /* gentle */ \
+ FALSE, /* msg_is_info */ \
+ TRUE); /* msg_is_multi */ \
+ } \
+ ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotification_##name)
+
+void RegisterNotifications_First()
+{
+ notif_global_error = FALSE;
+
+ #ifdef SVQC
+ #define dedi (server_is_dedicated ? "a dedicated " : "")
+ #else
+ #define dedi ""
+ #endif
+
+ print(sprintf("Beginning notification initialization on %s%s program...\n", dedi, PROGNAME));
+
+ // maybe do another implementation of this with checksums? for now, we don't need versioning
+ /*if(autocvar_notification_version != NOTIF_VERSION)
+ {
+ #ifdef CSQC
+ if(autocvar_notification_version_mismatch_client_error)
+ #else
+ if(autocvar_notification_version_mismatch_server_error)
+ #endif
+ notif_global_error = TRUE;
+
+ print(sprintf("^1NOTIFICATION VERSION MISMATCH: ^7program = %s, config = %d, code = %d.\n",
+ PROGNAME, autocvar_notification_version, NOTIF_VERSION));
+ }*/
+}
+
+void RegisterNotifications_Done()
+{
+ if(notif_global_error)
+ {
+ // shit happened... stop the loading of the program now if this is unacceptable
+ if(autocvar_notification_errors_are_fatal)
+ error("Notification initialization failed! Read above and fix the errors!\n");
+ else
+ print("Notification initialization failed! Read above and fix the errors!\n");
+ }
+ else { print("Notification initialization successful!\n"); }
+}
+
+// NOW we actually activate the declarations
+ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotifications_First)
+MSG_INFO_NOTIFICATIONS
+MSG_CENTER_NOTIFICATIONS
+MSG_MULTI_NOTIFICATIONS
+ACCUMULATE_FUNCTION(RegisterNotifications, RegisterNotifications_Done)
+#undef MSG_INFO_NOTIF
+#undef MSG_CENTER_NOTIF
+#undef MSG_MULTI_NOTIF
+
+#undef NOTIF_ADD_AUTOCVAR
--- /dev/null
+#ifdef TEAMNUMBERS_THAT_ARENT_STUPID
+const float NUM_TEAM_1 = 1; // red
+const float NUM_TEAM_2 = 2; // blue
+const float NUM_TEAM_3 = 3; // yellow
+const float NUM_TEAM_4 = 4; // pink
+const float NUM_SPECTATOR = 5;
+#else
+#ifdef CSQC
+const float NUM_TEAM_1 = 4; // red
+const float NUM_TEAM_2 = 13; // blue
+const float NUM_TEAM_3 = 12; // yellow
+const float NUM_TEAM_4 = 9; // pink
+#else
+const float NUM_TEAM_1 = 5; // red
+const float NUM_TEAM_2 = 14; // blue
+const float NUM_TEAM_3 = 13; // yellow
+const float NUM_TEAM_4 = 10; // pink
+#endif
+const float NUM_SPECTATOR = 1337;
+#endif
+
+const string COL_TEAM_1 = "^1";
+const string COL_TEAM_2 = "^4";
+const string COL_TEAM_3 = "^3";
+const string COL_TEAM_4 = "^6";
+const string NAME_TEAM_1 = _("Red");
+const string NAME_TEAM_2 = _("Blue");
+const string NAME_TEAM_3 = _("Yellow");
+const string NAME_TEAM_4 = _("Pink");
+const string NAME_TEAM = _("Team");
+const string NAME_NEUTRAL = _("Neutral");
+
+#define APP_TEAM_NUM_2(num,prefix) ((num == NUM_TEAM_1) ? prefix##RED : prefix##BLUE)
+#define APP_TEAM_NUM_4(num,prefix) ((num == NUM_TEAM_1) ? prefix##RED : ((num == NUM_TEAM_2) ? prefix##BLUE : ((num == NUM_TEAM_3) ? prefix##YELLOW : prefix##PINK)))
+#define APP_TEAM_ENT_2(ent,prefix) ((ent.team == NUM_TEAM_1) ? prefix##RED : prefix##BLUE)
+#define APP_TEAM_ENT_4(ent,prefix) ((ent.team == NUM_TEAM_1) ? prefix##RED : ((ent.team == NUM_TEAM_2) ? prefix##BLUE : ((ent.team == NUM_TEAM_3) ? prefix##YELLOW : prefix##PINK)))
+
+#ifdef CSQC
+float teamplay;
+float myteam;
+#endif
+
+string Team_ColorCode(float teamid)
+{
+ switch(teamid)
+ {
+ case NUM_TEAM_1: return COL_TEAM_1;
+ case NUM_TEAM_2: return COL_TEAM_2;
+ case NUM_TEAM_3: return COL_TEAM_3;
+ case NUM_TEAM_4: return COL_TEAM_4;
+ }
+
+ return "^7";
+}
+
+vector Team_ColorRGB(float teamid)
+{
+ switch(teamid)
+ {
+ #ifdef TEAMNUMBERS_THAT_ARENT_STUPID
+ case NUM_TEAM_1: return '1 0 0'; // red
+ case NUM_TEAM_2: return '0 0 1'; // blue
+ case NUM_TEAM_3: return '1 1 0'; // yellow
+ case NUM_TEAM_4: return '1 0 1'; // pink
+ #else
+ case NUM_TEAM_1: return '1 0.0625 0.0625';
+ case NUM_TEAM_2: return '0.0625 0.0625 1';
+ case NUM_TEAM_3: return '1 1 0.0625';
+ case NUM_TEAM_4: return '1 0.0625 1';
+ #endif
+ }
+
+ return '0 0 0';
+}
+
+string Team_ColorName(float teamid)
+{
+ switch(teamid)
+ {
+ case NUM_TEAM_1: return NAME_TEAM_1;
+ case NUM_TEAM_2: return NAME_TEAM_2;
+ case NUM_TEAM_3: return NAME_TEAM_3;
+ case NUM_TEAM_4: return NAME_TEAM_4;
+ }
+
+ return NAME_NEUTRAL;
+}
+
+float Team_ColorToTeam(string team_color)
+{
+ switch(strtolower(team_color))
+ {
+ case "red": return NUM_TEAM_1;
+ case "blue": return NUM_TEAM_2;
+ case "yellow": return NUM_TEAM_3;
+ case "pink": return NUM_TEAM_4;
+ case "auto": return 0;
+ }
+
+ return -1;
+}
+
+float Team_NumberToTeam(float number)
+{
+ switch(number)
+ {
+ case 1: return NUM_TEAM_1;
+ case 2: return NUM_TEAM_2;
+ case 3: return NUM_TEAM_3;
+ case 4: return NUM_TEAM_4;
+ }
+
+ return -1;
+}
+
+float Team_TeamToNumber(float teamid)
+{
+ switch(teamid)
+ {
+ case NUM_TEAM_1: return 1;
+ case NUM_TEAM_2: return 2;
+ case NUM_TEAM_3: return 3;
+ case NUM_TEAM_4: return 4;
+ }
+
+ return -1;
+}
+
+
+// legacy aliases for shitty code
+#define TeamByColor(teamid) (Team_TeamToNumber(teamid) - 1)
+#define ColorByTeam(number) Team_NumberToTeam(number + 1)
+
+// useful aliases
+#define Team_ColorName_Lower(teamid) strtolower(Team_ColorName(teamid))
+#define Team_ColorName_Upper(teamid) strtoupper(Team_ColorName(teamid))
+
+#define Team_FullName(teamid) strcat(Team_ColorName(teamid), " ", NAME_TEAM, "^7")
+#define Team_ColoredFullName(teamid) strcat(Team_ColorCode(teamid), Team_ColorName(teamid), " ", NAME_TEAM, "^7")
+
+#define Team_NumberToFullName(number) Team_FullName(Team_NumberToTeam(number))
+#define Team_NumberToColoredFullName(number) Team_ColoredFullName(Team_NumberToTeam(number))
+
+// replace these flags in a string with the strings provided
+#define TCR(input,teamcolor,teamtext) strreplace("^TC", teamcolor, strreplace("^TT", teamtext, input))
+#ifdef FTEQCC
#pragma flag enable subscope
#pragma flag enable lo
+#endif
// FTEQCC can do this
#define HAVE_YO_DAWG_CPP
# define COMPAT_XON060_DONTCRASH_CHECKPVS
#endif
+#ifdef FTEQCC
+#ifdef WATERMARK
+string FTEQCC_SUCKS_WATERMARKS_THROUGH_C60_FULLERENES = WATERMARK();
+#undef WATERMARK
+#define WATERMARK FTEQCC_SUCKS_WATERMARKS_THROUGH_C60_FULLERENES
+#endif
+#endif
float created_saved_value;
entity e;
- created_saved_value = FALSE;
-
+ created_saved_value = 0;
+
if not(tmp_cvar || tmp_value)
{
dprint("Error: Invalid usage of cvar_settemp(string, string); !\n");
- return FALSE;
+ return 0;
}
-
+
+ if(!cvar_type(tmp_cvar))
+ {
+ print(sprintf("Error: cvar %s doesn't exist!\n", tmp_cvar));
+ return 0;
+ }
+
for(e = world; (e = find(e, classname, "saved_cvar_value")); )
if(e.netname == tmp_cvar)
- goto saved; // skip creation
-
- // creating a new entity to keep track of this cvar
- e = spawn();
- e.classname = "saved_cvar_value";
- e.netname = strzone(tmp_cvar);
- e.message = strzone(cvar_string(tmp_cvar));
- created_saved_value = TRUE;
-
- // an entity for this cvar already exists
- :saved
-
+ created_saved_value = -1; // skip creation
+
+ if(created_saved_value != -1)
+ {
+ // creating a new entity to keep track of this cvar
+ e = spawn();
+ e.classname = "saved_cvar_value";
+ e.netname = strzone(tmp_cvar);
+ e.message = strzone(cvar_string(tmp_cvar));
+ created_saved_value = 1;
+ }
+
// update the cvar to the value given
cvar_set(tmp_cvar, tmp_value);
-
+
return created_saved_value;
}
float cvar_settemp_restore()
{
- float i;
- entity e;
- while((e = find(world, classname, "saved_cvar_value")))
+ float i = 0;
+ entity e = world;
+ while((e = find(e, classname, "saved_cvar_value")))
{
- cvar_set(e.netname, e.message);
- remove(e);
+ if(cvar_type(e.netname))
+ {
+ cvar_set(e.netname, e.message);
+ remove(e);
+ ++i;
+ }
+ else
+ print(sprintf("Error: cvar %s doesn't exist anymore! It can still be restored once it's manually recreated.\n", e.netname));
}
-
+
return i;
}
if(strstrofs(strcat(",", pattern, ","), subpattern, 0) < 0)
if(strstrofs(strcat(",", pattern, ","), subpattern2, 0) < 0)
if(strstrofs(strcat(",", pattern, ","), subpattern3, 0) < 0)
- if((!subpattern4) || strstrofs(strcat(",", pattern, ","), subpattern4, 0) < 0)
- return 0;
+ {
+ if not(subpattern4)
+ return 0;
+ if(strstrofs(strcat(",", pattern, ","), subpattern4, 0) < 0)
+ return 0;
+ }
}
return 1;
}
float get_model_parameters(string m, float sk)
{
string fn, s, c;
- float fh;
+ float fh, i;
get_model_parameters_modelname = string_null;
get_model_parameters_modelskin = -1;
get_model_parameters_weight = -1;
get_model_parameters_age = -1;
get_model_parameters_desc = string_null;
+ get_model_parameters_bone_upperbody = string_null;
+ get_model_parameters_bone_weapon = string_null;
+ for(i = 0; i < MAX_AIM_BONES; ++i)
+ {
+ get_model_parameters_bone_aim[i] = string_null;
+ get_model_parameters_bone_aimweight[i] = 0;
+ }
+ get_model_parameters_fixbone = 0;
if not(m)
return 1;
+
+ if(substring(m, -9, 5) == "_lod1" || substring(m, -9, 5) == "_lod2")
+ m = strcat(substring(m, 0, -10), substring(m, -4, -1));
+
if(sk < 0)
{
if(substring(m, -4, -1) != ".txt")
get_model_parameters_weight = stof(s);
if(c == "age")
get_model_parameters_age = stof(s);
+ if(c == "bone_upperbody")
+ get_model_parameters_bone_upperbody = s;
+ if(c == "bone_weapon")
+ get_model_parameters_bone_weapon = s;
+ for(i = 0; i < MAX_AIM_BONES; ++i)
+ if(c == strcat("bone_aim", ftos(i)))
+ {
+ get_model_parameters_bone_aimweight[i] = stof(car(s));
+ get_model_parameters_bone_aim[i] = cdr(s);
+ }
+ if(c == "fixbone")
+ get_model_parameters_fixbone = stof(s);
}
while((s = fgets(fh)))
for(queue_start = e; queue_start; queue_start = queue_start.fld)
queue_start.FindConnectedComponent_processing = 0;
}
+
+// todo: this sucks, lets find a better way to do backtraces?
+#ifndef MENUQC
+void backtrace(string msg)
+{
+ float dev, war;
+ #ifdef SVQC
+ dev = autocvar_developer;
+ war = autocvar_prvm_backtraceforwarnings;
+ #else
+ dev = cvar("developer");
+ war = cvar("prvm_backtraceforwarnings");
+ #endif
+ cvar_set("developer", "1");
+ cvar_set("prvm_backtraceforwarnings", "1");
+ print("\n");
+ print("--- CUT HERE ---\nWARNING: ");
+ print(msg);
+ print("\n");
+ remove(world); // isn't there any better way to cause a backtrace?
+ print("\n--- CUT UNTIL HERE ---\n");
+ cvar_set("developer", ftos(dev));
+ cvar_set("prvm_backtraceforwarnings", ftos(war));
+}
+#endif
+
+// color code replace, place inside of sprintf and parse the string
+string CCR(string input)
+{
+ // See the autocvar declarations in util.qh for default values
+
+ // foreground/normal colors
+ input = strreplace("^F1", strcat("^", autocvar_hud_colorset_foreground_1), input);
+ input = strreplace("^F2", strcat("^", autocvar_hud_colorset_foreground_2), input);
+ input = strreplace("^F3", strcat("^", autocvar_hud_colorset_foreground_3), input);
+ input = strreplace("^F4", strcat("^", autocvar_hud_colorset_foreground_4), input);
+
+ // "kill" colors
+ input = strreplace("^K1", strcat("^", autocvar_hud_colorset_kill_1), input);
+ input = strreplace("^K2", strcat("^", autocvar_hud_colorset_kill_2), input);
+ input = strreplace("^K3", strcat("^", autocvar_hud_colorset_kill_3), input);
+
+ // background colors
+ input = strreplace("^BG", strcat("^", autocvar_hud_colorset_background), input);
+ input = strreplace("^N", "^7", input); // "none"-- reset to white...
+ return input;
+}
+
+vector vec3(float x, float y, float z)
+{
+ vector v;
+ v_x = x;
+ v_y = y;
+ v_z = z;
+ return v;
+}
+
+#ifndef MENUQC
+vector animfixfps(entity e, vector a, vector b)
+{
+ // multi-frame anim: keep as-is
+ if(a_y == 1)
+ {
+ float dur;
+ dur = frameduration(e.modelindex, a_x);
+ if(dur <= 0 && b_y)
+ {
+ a = b;
+ dur = frameduration(e.modelindex, a_x);
+ }
+ if(dur > 0)
+ a_z = 1.0 / dur;
+ }
+ return a;
+}
+#endif
+
+#ifdef SVQC
+void dedicated_print(string input) // print(), but only print if the server is not local
+{
+ if(server_is_dedicated) { print(input); }
+}
+#endif
ACCUMULATE_call(#func)
#endif
+// used for simplifying ACCUMULATE_FUNCTIONs
+#define SET_FIRST_OR_LAST(input,first,count) if(!input) { input = (first + count); }
+#define SET_FIELD_COUNT(field,first,count) if(!field) { field = (first + count); ++count; }
+#define CHECK_MAX_COUNT(name,max,count,type) if(count == max) { error(strcat("Maximum ", type, " hit: ", #name, ": ", ftos(count), ".\n")); }
+
// this returns a tempstring containing a copy of s with additional \n newlines added, it also replaces \n in the text with a real newline
// NOTE: s IS allowed to be a tempstring
string wordwrap(string s, float l);
void wordwrap_sprint(string s, float l);
#endif
#endif
-void wordwrap_cb(string s, float l, void(string) callback)
+void wordwrap_cb(string s, float l, void(string) callback);
#ifndef SVQC
string draw_currentSkin;
void get_mi_min_max_texcoords(float mode);
#endif
-#define FTEQCC_YOU_SUCK_THIS_IS_NOT_UNREFERENCED(x) void reference_##x() { x = x; }
-
float almost_equals(float a, float b);
float almost_in_bounds(float a, float b, float c);
#endif
// the NULL function
-const var void func_null(void); FTEQCC_YOU_SUCK_THIS_IS_NOT_UNREFERENCED(func_null)
-const var string string_null;
+#ifdef GMQCC
+#define func_null nil
+#define string_null nil
+#else
+var void func_null(void);
+var string string_null;
+#endif
float float2range11(float f);
float float2range01(float f);
string get_model_parameters_sex;
float get_model_parameters_weight;
float get_model_parameters_age;
+string get_model_parameters_bone_upperbody;
+string get_model_parameters_bone_weapon;
+#define MAX_AIM_BONES 4
+string get_model_parameters_bone_aim[MAX_AIM_BONES];
+float get_model_parameters_bone_aimweight[MAX_AIM_BONES];
+float get_model_parameters_fixbone;
string get_model_parameters_desc;
float get_model_parameters(string mod, float skn); // call with string_null to clear; skin -1 means mod is the filename of the txt file and is to be split
float lowestbit(float f);
#ifdef CSQC
-entity ReadCSQCEntity()
+entity ReadCSQCEntity();
#endif
#ifndef MENUQC
// for marking written-to values as unused where it's a good idea to do this
noref float unused_float;
-
-
// a function f with:
// f(0) = 0
// f(1) = 1
typedef entity(entity cur, entity near, entity pass) findNextEntityNearFunction_t;
typedef float(entity a, entity b, entity pass) isConnectedFunction_t;
void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t nxt, isConnectedFunction_t iscon, entity pass);
+
+// expand multiple arguments into one argument by stripping parenthesis
+#define XPD(...) __VA_ARGS__
+
+#ifndef MENUQC
+void backtrace(string msg);
+#endif
+
+// color code replace, place inside of sprintf and parse the string... defaults described as constants
+// foreground/normal colors
+var string autocvar_hud_colorset_foreground_1 = "2"; // F1 - Green // primary priority (important names, etc)
+var string autocvar_hud_colorset_foreground_2 = "3"; // F2 - Yellow // secondary priority (items, locations, numbers, etc)
+var string autocvar_hud_colorset_foreground_3 = "4"; // F3 - Blue // tertiary priority or relatively inconsequential text
+var string autocvar_hud_colorset_foreground_4 = "1"; // F4 - Red // notice/attention grabbing texting
+// "kill" colors
+var string autocvar_hud_colorset_kill_1 = "1"; // K1 - Red // "bad" or "dangerous" text (death messages against you, kill notifications, etc)
+var string autocvar_hud_colorset_kill_2 = "3"; // K2 - Yellow // similar to above, but less important... OR, a highlight out of above message type
+var string autocvar_hud_colorset_kill_3 = "4"; // K3 - Blue // "good" or "beneficial" text (you fragging someone, etc)
+// background color
+var string autocvar_hud_colorset_background = "7"; // BG - White // neutral/unimportant text
+
+string CCR(string input);
+
+#ifndef MENUQC
+#ifdef CSQC
+#define GENTLE (autocvar_cl_gentle || autocvar_cl_gentle_messages)
+#else
+#define GENTLE autocvar_sv_gentle
+#endif
+#define normal_or_gentle(normal,gentle) (GENTLE ? ((gentle != "") ? gentle : normal) : normal)
+#endif
+
+// allow writing to also pass through to spectators (like so spectators see the same centerprints as players for example)
+#define WRITESPECTATABLE_MSG_ONE_VARNAME(varname,statement) entity varname; varname = msg_entity; FOR_EACH_REALCLIENT(msg_entity) if(msg_entity == varname || (msg_entity.classname == STR_SPECTATOR && msg_entity.enemy == varname)) statement msg_entity = varname
+#define WRITESPECTATABLE_MSG_ONE(statement) WRITESPECTATABLE_MSG_ONE_VARNAME(oldmsg_entity, statement)
+#define WRITESPECTATABLE(msg,statement) if(msg == MSG_ONE) { WRITESPECTATABLE_MSG_ONE(statement); } else statement float WRITESPECTATABLE_workaround = 0
+
+vector vec3(float x, float y, float z);
+
+#ifndef MENUQC
+vector animfixfps(entity e, vector a, vector b);
+#endif
+
+#ifdef SVQC
+void dedicated_print(string input);
+#endif
+
+// todo: better way to do this?
+#ifdef MENUQC
+#define PROGNAME "MENUQC"
+#else
+#ifdef SVQC
+#define PROGNAME "SVQC"
+#else
+#define PROGNAME "CSQC"
+#endif
+#endif
.float csqcmodel_lerpfractime;
.float csqcmodel_lerpfrac2time;
-void CSQCModel_InterpolateAnimation_PreNote(float sf)
+void CSQCModel_InterpolateAnimation_2To4_PreNote(float sf)
{
-#ifdef CSQCMODEL_HAVE_TWO_FRAMES
if(sf & CSQCMODEL_PROPERTY_FRAME)
{
self.frame3 = self.frame;
self.csqcmodel_lerpfrac2time = self.csqcmodel_lerpfractime;
self.lerpfrac = self.csqcmodel_lerpfrac;
}
-#else
+}
+void CSQCModel_InterpolateAnimation_1To2_PreNote(float sf)
+{
if(sf & CSQCMODEL_PROPERTY_FRAME)
{
self.frame2 = self.frame;
self.frame2time = self.frame1time;
}
+}
+void CSQCModel_InterpolateAnimation_PreNote(float sf)
+{
+#ifdef CSQCMODEL_HAVE_TWO_FRAMES
+ CSQCModel_InterpolateAnimation_2To4_PreNote(sf);
+#else
+ CSQCModel_InterpolateAnimation_1To2_PreNote(sf);
#endif
}
-void CSQCModel_InterpolateAnimation_Note(float sf)
+void CSQCModel_InterpolateAnimation_2To4_Note(float sf, float set_times)
{
-#ifdef CSQCMODEL_HAVE_TWO_FRAMES
if(sf & CSQCMODEL_PROPERTY_FRAME)
{
- self.frame1time = time;
+ if(set_times)
+ self.frame1time = time;
}
if(sf & CSQCMODEL_PROPERTY_FRAME2)
{
- self.frame2time = time;
+ if(set_times)
+ self.frame2time = time;
}
if(sf & CSQCMODEL_PROPERTY_LERPFRAC)
{
self.csqcmodel_lerpfrac = self.lerpfrac;
- self.csqcmodel_lerpfractime = time;
+ if(set_times)
+ self.csqcmodel_lerpfractime = time;
}
-#else
+}
+void CSQCModel_InterpolateAnimation_1To2_Note(float sf, float set_times)
+{
if(sf & CSQCMODEL_PROPERTY_FRAME)
{
- self.frame1time = time;
+ if(set_times)
+ self.frame1time = time;
}
+}
+void CSQCModel_InterpolateAnimation_Note(float sf)
+{
+#ifdef CSQCMODEL_HAVE_TWO_FRAMES
+ CSQCModel_InterpolateAnimation_2To4_Note(sf, TRUE);
+#else
+ CSQCModel_InterpolateAnimation_1To2_Note(sf, TRUE);
#endif
}
-void CSQCModel_InterpolateAnimation_Do()
+void CSQCModel_InterpolateAnimation_2To4_Do()
{
-#ifdef CSQCMODEL_HAVE_TWO_FRAMES
if(autocvar_cl_nolerp || (autocvar_cl_lerpanim_maxdelta_framegroups == 0))
{
self.lerpfrac = self.csqcmodel_lerpfrac;
self.frame3time = 0;
}
}
-#else
+}
+void CSQCModel_InterpolateAnimation_1To2_Do()
+{
if(autocvar_cl_nolerp || (autocvar_cl_lerpanim_maxdelta_framegroups == 0))
{
self.lerpfrac = 0;
else
self.lerpfrac = 1 - bound(0, (time - self.frame1time) / autocvar_cl_lerpanim_maxdelta_framegroups, 1);
}
+}
+void CSQCModel_InterpolateAnimation_Do()
+{
+#ifdef CSQCMODEL_HAVE_TWO_FRAMES
+ CSQCModel_InterpolateAnimation_2To4_Do();
+#else
+ CSQCModel_InterpolateAnimation_1To2_Do();
#endif
}
void CSQCModel_Draw()
{
// some nice flags for CSQCMODEL_IF and the hooks
- float isplayer = (self.entnum >= 1 && self.entnum <= maxclients);
- float islocalplayer = (self.entnum == player_localnum + 1);
- float isnolocalplayer = (isplayer && (self.entnum != player_localnum + 1));
+ local noref float isplayer = (self.entnum >= 1 && self.entnum <= maxclients);
+ local noref float islocalplayer = (self.entnum == player_localnum + 1);
+ local noref float isnolocalplayer = (isplayer && (self.entnum != player_localnum + 1));
// we don't do this for the local player as that one is already handled
// by CSQCPlayer_SetCamera()
if(!CSQCPlayer_IsLocalPlayer())
InterpolateOrigin_Do();
- // TODO csqcplayers: run prediction here too
CSQCModel_InterpolateAnimation_Do();
{ CSQCMODEL_HOOK_PREDRAW }
sf = ReadShort();
// some nice flags for CSQCMODEL_IF and the hooks
- float isplayer = (self.entnum >= 1 && self.entnum <= maxclients);
- float islocalplayer = (self.entnum == player_localnum + 1);
- float isnolocalplayer = (isplayer && (self.entnum != player_localnum + 1));
+ local noref float isplayer = (self.entnum >= 1 && self.entnum <= maxclients);
+ local noref float islocalplayer = (self.entnum == player_localnum + 1);
+ local noref float isnolocalplayer = (isplayer && (self.entnum != player_localnum + 1));
self.classname = "csqcmodel";
+ self.iflags |= IFLAG_ORIGIN; // interpolate origin too
self.iflags |= IFLAG_ANGLES; // interpolate angles too
+ self.iflags |= IFLAG_VELOCITY | IFLAG_AUTOVELOCITY; // let's calculate velocity automatically
{ CSQCMODEL_HOOK_PREUPDATE }
entity CSQCModel_server2csqc(float pl);
.float csqcmodel_teleported;
+
+// this is exported for custom frame animation code. Use with care.
+// to update frames, first call this:
+void CSQCModel_InterpolateAnimation_2To4_PreNote(float sf);
+void CSQCModel_InterpolateAnimation_1To2_PreNote(float sf);
+// then update frame, frame1time (and possibly frame2, frame2time, lerpfrac)
+// if set_times is not set, caller is responsible for frame1time, frame2time, csqcmodel_lerpfractime!
+void CSQCModel_InterpolateAnimation_2To4_Note(float sf, float set_times);
+void CSQCModel_InterpolateAnimation_1To2_Note(float sf, float set_times);
+// to retrieve animation state, call this
+void CSQCModel_InterpolateAnimation_2To4_Do();
+void CSQCModel_InterpolateAnimation_1To2_Do();
+// will overwrite lerpfrac, lerpfrac3, lerpfrac4, and possibly clear frame*time if they are undisplayed according to lerpfracs
var float autocvar_cl_movement_errorcompensation = 0;
// engine stuff
-.float pmove_flags;
-float pmove_onground; // weird engine flag we shouldn't really use but have to for now
-#define PMF_JUMP_HELD 1
-#define PMF_DUCKED 4
-#define PMF_ONGROUND 8
#define REFDEFFLAG_TELEPORTED 1
#define REFDEFFLAG_JUMPING 2
+float pmove_onground; // weird engine flag we shouldn't really use but have to for now
vector csqcplayer_origin, csqcplayer_velocity;
float csqcplayer_sequence, player_pmflags;
}
else
{
+ float flg = self.iflags;
+ self.iflags &~= IFLAG_ORIGIN | IFLAG_ANGLES;
+ InterpolateOrigin_Do();
+ self.iflags = flg;
+
if(csqcplayer_status == CSQCPLAYERSTATUS_FROMSERVER)
{
vector o, v;
}
CSQCPlayer_PredictTo(clientcommandframe + 1, TRUE);
+#ifdef CSQCMODEL_SERVERSIDE_CROUCH
+ // get crouch state from the server (LAG)
+ if(getstati(STAT_VIEWHEIGHT) == PL_VIEW_OFS_z)
+ self.pmove_flags &~= PMF_DUCKED;
+ else if(getstati(STAT_VIEWHEIGHT) == PL_CROUCH_VIEW_OFS_z)
+ self.pmove_flags |= PMF_DUCKED;
+#endif
+
CSQCPlayer_SetMinsMaxs();
self.angles_y = input_angles_y;
#define CSQCPLAYERSTATUS_FROMSERVER 1
#define CSQCPLAYERSTATUS_PREDICTED 2
+// only ever READ these!
+.float pmove_flags;
+#define PMF_JUMP_HELD 1
+#define PMF_DUCKED 4
+#define PMF_ONGROUND 8
+
void CSQCPlayer_SetCamera();
float CSQCPlayer_PreUpdate();
float CSQCPlayer_PostUpdate();
.float lerpfrac;
#define CSQCMODEL_PROPERTY_FRAME 32768
-#define CSQCMODEL_PROPERTY_FRAME2 16384
-#define CSQCMODEL_PROPERTY_LERPFRAC 8192
-#define CSQCMODEL_PROPERTY_TELEPORTED 4096 // the "teleport bit" cancelling interpolation
-#define CSQCMODEL_PROPERTY_MODELINDEX 2048
-#define CSQCMODEL_PROPERTY_ORIGIN 1024
-#define CSQCMODEL_PROPERTY_YAW 512
-#define CSQCMODEL_PROPERTY_PITCHROLL 256
+#define CSQCMODEL_PROPERTY_TELEPORTED 16384 // the "teleport bit" cancelling interpolation
+#define CSQCMODEL_PROPERTY_MODELINDEX 8192
+#define CSQCMODEL_PROPERTY_ORIGIN 4096
+#define CSQCMODEL_PROPERTY_YAW 2048
+#define CSQCMODEL_PROPERTY_PITCHROLL 1024
+#define CSQCMODEL_PROPERTY_FRAME2 512
+#define CSQCMODEL_PROPERTY_LERPFRAC 256
#define ALLPROPERTIES_COMMON \
CSQCMODEL_PROPERTY(CSQCMODEL_PROPERTY_FRAME, float, ReadByte, WriteByte, frame) \
.vector ivelocity1, ivelocity2;
.vector iforward1, iforward2;
.vector iup1, iup2;
+.vector ivforward1, ivforward2;
+.vector ivup1, ivup2;
.float itime1, itime2;
void InterpolateOrigin_Reset()
{
else
self.iflags |= IFLAG_PREVALID;
- self.iorigin1 = self.iorigin2;
- self.iorigin2 = self.origin;
+ if(self.iflags & IFLAG_ORIGIN)
+ {
+ self.iorigin1 = self.iorigin2;
+ self.iorigin2 = self.origin;
+ }
if(self.iflags & IFLAG_AUTOANGLES)
if(self.iorigin2 != self.iorigin1)
self.angles = vectoangles(self.iorigin2 - self.iorigin1);
+ if(self.iflags & IFLAG_AUTOVELOCITY)
+ if(self.itime2 != self.itime1)
+ self.velocity = (self.iorigin2 - self.iorigin1) * (1.0 / (self.itime2 - self.itime1));
+
if(self.iflags & IFLAG_ANGLES)
{
fixedmakevectors(self.angles);
self.iup2 = v_up;
}
+ if(self.iflags & IFLAG_V_ANGLE)
+ {
+ fixedmakevectors(self.v_angle);
+ if(f0 & IFLAG_VALID)
+ {
+ self.ivforward1 = self.ivforward2;
+ self.ivup1 = self.ivup2;
+ }
+ else
+ {
+ self.ivforward1 = v_forward;
+ self.ivup1 = v_up;
+ }
+ self.ivforward2 = v_forward;
+ self.ivup2 = v_up;
+ }
+ else if(self.iflags & IFLAG_V_ANGLE_X)
+ {
+ self.ivforward1_x = self.ivforward2_x;
+ self.ivforward2_x = self.v_angle_x;
+ }
+
if(self.iflags & IFLAG_VELOCITY)
{
self.ivelocity1 = self.ivelocity2;
{
float f;
f = bound(0, (time - self.itime1) / (self.itime2 - self.itime1), 1 + autocvar_cl_lerpexcess);
- self.origin = (1 - f) * self.iorigin1 + f * self.iorigin2;
+ if(self.iflags & IFLAG_ORIGIN)
+ setorigin(self, (1 - f) * self.iorigin1 + f * self.iorigin2);
if(self.iflags & IFLAG_ANGLES)
{
forward = (1 - f) * self.iforward1 + f * self.iforward2;
up = (1 - f) * self.iup1 + f * self.iup2;
self.angles = fixedvectoangles2(forward, up);
}
+ if(self.iflags & IFLAG_V_ANGLE)
+ {
+ forward = (1 - f) * self.ivforward1 + f * self.ivforward2;
+ up = (1 - f) * self.ivup1 + f * self.ivup2;
+ self.v_angle = fixedvectoangles2(forward, up);
+ }
+ else if(self.iflags & IFLAG_V_ANGLE_X)
+ self.v_angle_x = (1 - f) * self.ivforward1_x + f * self.ivforward2_x;
if(self.iflags & IFLAG_VELOCITY)
self.velocity = (1 - f) * self.ivelocity1 + f * self.ivelocity2;
}
}
void InterpolateOrigin_Undo()
{
- self.origin = self.iorigin2;
+ if(self.iflags & IFLAG_ORIGIN)
+ setorigin(self, self.iorigin2);
if(self.iflags & IFLAG_ANGLES)
self.angles = fixedvectoangles2(self.iforward2, self.iup2);
+ if(self.iflags & IFLAG_V_ANGLE)
+ self.v_angle = fixedvectoangles2(self.ivforward2, self.ivup2);
+ else if(self.iflags & IFLAG_V_ANGLE_X)
+ self.v_angle_x = self.ivforward2_x;
if(self.iflags & IFLAG_VELOCITY)
self.velocity = self.ivelocity2;
}
#define IFLAG_VALID 8
#define IFLAG_PREVALID 16
#define IFLAG_TELEPORTED 32
+#define IFLAG_AUTOVELOCITY 64
+#define IFLAG_V_ANGLE 128
+#define IFLAG_V_ANGLE_X 256
+#define IFLAG_ORIGIN 512
#define IFLAG_INTERNALMASK (IFLAG_VALID | IFLAG_PREVALID)
// call this BEFORE reading an entity update
// call this BEFORE drawing
void InterpolateOrigin_Do();
+
+// in case we interpolate that:
+.vector v_angle;
void(entity e, string m) setmodel = #3;
void(entity e, vector min, vector max) setsize = #4;
-void() break = #6;
+void() break_builtin = #6;
float() random = #7;
void(entity e, float chan, string samp) sound = #8;
vector(vector v) normalize = #9;
string strzone(string s) = #56;
void strunzone(string s) = #57;
-float tokenize(string s) = #58
+float tokenize(string s) = #58;
string argv(float n) = #59;
float isserver(void) = #60;
void(entity e, string m) setmodel = #3; // set movetype and solid first
void(entity e, vector min, vector max) setsize = #4;
// #5 was removed
-void() break = #6;
+void() break_builtin = #6;
float() random = #7; // returns 0 - 1
void(entity e, float chan, string samp, float vol, float atten) sound = #8;
vector(vector v) normalize = #9;
#include "item/textslider.c"
#include "item/listbox.c"
#include "item/inputbox.c"
-#include "item/gecko.c"
#include "xonotic/dialog.c"
#include "xonotic/tab.c"
#include "xonotic/mainwindow.c"
#include "xonotic/image.c"
#include "xonotic/crosshairbutton.c"
#include "xonotic/playermodel.c"
-#include "xonotic/dialog_news.c"
#include "xonotic/checkbox_slider_invalid.c"
#include "xonotic/charmap.c"
#include "xonotic/keybinder.c"
print(_("Usage: menu_cmd command..., where possible commands are:\n"));
print(_(" sync - reloads all cvars on the current menu page\n"));
print(_(" directmenu ITEM - select a menu item as main item\n"));
- GenericCommand("help");
+
+ print("\nGeneric commands shared by all programs:\n");
+ GenericCommand_macro_help();
+
return;
}
return;
}
- if(argv(0) == "directmenu") if(argc == 2)
+ if(argv(0) == "directmenu" || argv(0) == "directpanelhudmenu")
{
- // switch to a menu item
- if(!isdemo()) // don't allow this command in demos
- m_goto(argv(1));
- return;
- }
+ string filter = string_null;
+ if(argv(0) == "directpanelhudmenu")
+ filter = strzone("HUD");
- if(argv(0) == "directpanelhudmenu")
- {
- // switch to a menu item
- m_goto(strcat("HUD", argv(1)));
+ if(argc == 1)
+ {
+ print(_("Available options:\n"));
+ float i;
+ entity e;
+ string s;
+
+ for(i = 0, e = world; (e = nextent(e)); )
+ if(e.classname != "vtbl" && e.name != "")
+ {
+ s = e.name;
+ if(filter)
+ {
+ if(substring(s, 0, strlen(filter)) != filter)
+ continue;
+ s = substring(s, strlen(filter), strlen(s) - strlen(filter));
+ }
+ print(strcat(" ", s ,"\n"));
+ ++i;
+ }
+ }
+ else if(argc == 2 && !isdemo()) // don't allow this command in demos
+ m_goto(strcat(filter, argv(1))); // switch to a menu item
+ if(filter)
+ strunzone(filter);
return;
}
return;
}
- if(argv(0) == "curl")
- {
- }
-
print(_("Invalid command. For a list of supported commands, try menu_cmd help.\n"));
}
METHOD(Button, mouseDrag, float(entity, vector))
METHOD(Button, mouseRelease, float(entity, vector))
METHOD(Button, focusEnter, void(entity))
- ATTRIB(Button, onClick, void(entity, entity), SUB_Null)
+ ATTRIB(Button, onClick, void(entity, entity), func_null)
ATTRIB(Button, onClickEntity, entity, NULL)
ATTRIB(Button, src, string, string_null)
ATTRIB(Button, srcSuffix, string, string_null)
{
if(cvar("menu_sounds"))
localsound("sound/misc/menu2.wav");
- me.onClick(me, me.onClickEntity);
+ if(me.onClick)
+ me.onClick(me, me.onClickEntity);
}
me.pressed = 0;
}
{
// keyboard click timer expired? Fire the event then.
if not(me.disabled)
- me.onClick(me, me.onClickEntity);
+ if(me.onClick)
+ me.onClick(me, me.onClickEntity);
}
me.clickTime -= frametime;
+++ /dev/null
-// Andreas Kirsch Gecko item (to test it)
-#ifdef INTERFACE
-CLASS(Gecko) EXTENDS(Item)
- METHOD(Gecko, configureBrowser, void( entity, string ) )
- METHOD(Gecko, draw, void(entity))
- METHOD(Gecko, keyDown, float(entity, float, float, float))
- METHOD(Gecko, keyUp, float(entity, float, float, float))
- METHOD(Gecko, mouseMove, float(entity, vector))
- METHOD(Gecko, mouseDrag, float(entity, vector))
- METHOD(Gecko, resizeNotify, void(entity, vector, vector, vector, vector))
- ATTRIB(Gecko, texturePath, string, string_null )
- ATTRIB(Gecko, textureExtent, vector, '0 0 0')
-ENDCLASS(Gecko)
-#endif
-
-#ifdef IMPLEMENTATION
-// define static members
-float _gecko_instanceNumber;
-
-void Gecko_configureBrowser( entity me, string URI ) {
- me.focusable = 1;
-
- //create a new gecko object if needed
- if( !me.texturePath ) {
- me.texturePath = strzone( strcat( "_dynamic/gecko/menu/", ftos( _gecko_instanceNumber ) ) );
- _gecko_instanceNumber+=1;
- // TODO: add error checks
- gecko_create( me.texturePath );
- }
- gecko_navigate( me.texturePath, URI );
-}
-
-void Gecko_draw(entity me)
-{
- vector drawSize;
-
- if( me.texturePath ) {
- /* The gecko browser is actually only drawn to a part of the
- texture. Correct scaling so that part fills up the whole
- item area. */
- drawSize_x = 1.0 / me.textureExtent_x;
- drawSize_y = 1.0 / me.textureExtent_y;
- draw_Picture( '0 0 0', strcat( "/", me.texturePath ),
- drawSize, '1 1 1', 1.0 );
- } else {
- vector fontsize;
- fontsize_x = fontsize_y = 1.0 / 30.0;
- fontsize_z = 0.0;
- draw_Text( '0 0 0', _("Browser not initialized!"), fontsize, '1 1 1', 1.0, 0 );
- }
- SUPER(Gecko).draw(me);
-}
-
-float Gecko_keyDown(entity me, float scan, float ascii, float shift)
-{
- if( scan == K_ESCAPE ) {
- return 0;
- }
- if (ascii >= 32)
- return gecko_keyevent( me.texturePath, ascii, GECKO_BUTTON_DOWN );
- else
- return gecko_keyevent( me.texturePath, scan, GECKO_BUTTON_DOWN );
-}
-
-float Gecko_keyUp(entity me, float scan, float ascii, float shift)
-{
- if (ascii >= 32)
- return gecko_keyevent( me.texturePath, ascii, GECKO_BUTTON_UP );
- else
- return gecko_keyevent( me.texturePath, scan, GECKO_BUTTON_UP );
-}
-
-float Gecko_mouseMove(entity me, vector pos)
-{
- gecko_mousemove( me.texturePath, pos_x, pos_y );
- return 1;
-}
-
-float Gecko_mouseDrag(entity me, vector pos)
-{
- gecko_mousemove( me.texturePath, pos_x, pos_y );
- return 1;
-}
-
-void Gecko_resizeNotify(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
-{
- SUPER(Gecko).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
- gecko_resize( me.texturePath, absSize_x, absSize_y );
- me.textureExtent = gecko_get_texture_extent( me.texturePath );
-}
-
-string toStringGecko(entity me)
-{
- return me.texturePath;
-}
-
-#endif
void ListBox_draw(entity me)
{
float i;
- vector absSize, fillSize;
+ vector absSize, fillSize = '0 0 0';
vector oldshift, oldscale;
if(me.pressed == 2)
me.mouseDrag(me, me.dragScrollPos); // simulate mouseDrag event
float Nexposee_keyDown(entity me, float scan, float ascii, float shift)
{
- float nexposeeKey;
+ float nexposeeKey = 0;
if(me.animationState == 2)
if(SUPER(Nexposee).keyDown(me, scan, ascii, shift))
return 1;
float menuNotTheFirstFrame;
float menuMouseMode;
-void SUB_Null() { }
-
void m_sync()
{
updateCompression();
check_unacceptable_compiler_bugs();
#ifdef WATERMARK
- print(sprintf(_("^4MQC Build information: ^1%s\n"), WATERMARK()));
+ print(sprintf(_("^4MQC Build information: ^1%s\n"), WATERMARK));
#endif
// list all game dirs (TEST)
isz_w = '1 0 0' + '0 1 0' * ((sz_y / sz_x) * (draw_scale_x / draw_scale_y));
isz_h = '0 1 0' + '1 0 0' * ((sz_x / sz_y) * (draw_scale_y / draw_scale_x));
+#ifdef GMQCC
+ isz = '0 0 0';
+#endif
switch(scalemode)
{
default:
float conwidth, conheight; // "virtual" conwidth/height values for other stuff to assume for scaling
-void SUB_Null();
-
float preMenuInit(); // you have to define this for pre-menu initialization. Return 0 if initialization needs to be retried a frame later, 1 if it succeeded.
void preMenuDraw(); // this is run before the menu is drawn. You may put some stuff there that has to be done every frame.
void postMenuDraw(); // this is run just after the menu is drawn (or not). Useful to draw something over everything else.
#define EXTENDS(base) me = spawn##base (); entity basevtbl; basevtbl = base##_vtbl;
#define METHOD(cname,name,prototype) me.name = cname##_##name;
#define ATTRIB(cname,name,type,val) me.name = val;
-#define ATTRIBARRAY(cname,name,type,cnt) me.name = me.name;
+#define ATTRIBARRAY(cname,name,type,cnt)
#define ENDCLASS(cname) me.instanceOf##cname = 1; me.classname = #cname; if(!cname##_vtbl) cname##_vtbl = spawnVtbl(me, basevtbl); return me; }
// for the implementation
../../menu.dat
+sys-pre.qh
../dpdefs/menudefs.qc
../dpdefs/keycodes.qc
+sys-post.qh
config.qh
../common/util-pre.qh
oo/base.h
+../common/teams.qh
../common/constants.qh
../common/mapinfo.qh
../common/campaign_common.qh
../common/items.qh
+../common/counting.qh
../common/command/markup.qh
../common/command/rpn.qh
../common/command/generic.qh
--- /dev/null
+#pragma noref 0
--- /dev/null
+#pragma noref 1
void XonoticCampaignList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
{
string s;
- float p;
vector theColor;
float theAlpha;
float j, n;
if(isSelected)
draw_Fill('0 0 0', '1 1 0', SKINCOLOR_LISTBOX_SELECTED, SKINALPHA_LISTBOX_SELECTED);
- s = ftos(p);
if(draw_PictureSize(strcat("/maps/", campaign_mapname[i])) == '0 0 0')
draw_Picture(me.columnPreviewOrigin * eX, "nopreview_map", me.columnPreviewSize * eX + eY, '1 1 1', theAlpha);
else
vector color_hslimage(vector v, vector margin)
{
- vector pos;
+ vector pos = '0 0 0';
v = rgb_to_hsl(v);
if (v_y)
{
return 1;
}
else if(scan == K_ENTER)
+ {
me.cvarValueBox.parent.setFocus(me.cvarValueBox.parent, me.cvarValueBox);
+ return 1;
+ }
else if(SUPER(XonoticCvarList).keyDown(me, scan, ascii, shift))
return 1;
else if(!me.controlledTextbox)
setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_timeout")), "0");
me.TD(me, 1, 2.6, e = makeXonoticTextSlider(strzone(strcat("hud_panel_", panelname, "_timeout_effect"))));
e.addValue(e, ZCTX(_("EF^None")), "0");
- e.addValue(e, _("Slide"), "1");
- e.addValue(e, _("Alpha"), "2");
+ e.addValue(e, _("Alpha"), "1");
+ e.addValue(e, _("Slide"), "2");
e.addValue(e, ZCTX(_("EF^Both")), "3");
e.configureXonoticTextSliderValues(e);
setDependentStringNotEqual(e, strzone(strcat("hud_panel_", panelname, "_timeout")), "0");
e.configureXonoticTextSliderValues(e);
setDependent(e, "cl_gentle", 0, 0);
me.TR(me);
- #ifdef ALLOW_FORCEMODELS
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Force models:")));
- me.TD(me, 1, 2/3, e = makeXonoticRadioButton(6, string_null, string_null, ZCTX(_("MDL^None"))));
- me.TD(me, 1, 2/3, e = makeXonoticRadioButton(6, "cl_forceplayermodelsfromxonotic", string_null, ZCTX(_("MDL^Custom"))));
- me.TD(me, 1, 2/3, e = makeXonoticRadioButton(6, "cl_forceplayermodels", string_null, ZCTX(_("MDL^All"))));
- #endif
me.TR(me);
me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_forceplayermodels", _("Force player models to mine")));
me.TR(me);
+++ /dev/null
-#ifdef INTERFACE
-CLASS(XonoticNewsDialog) EXTENDS(XonoticDialog)
- METHOD(XonoticNewsDialog, fill, void(entity))
- ATTRIB(XonoticNewsDialog, title, string, _("News"))
- ATTRIB(XonoticNewsDialog, color, vector, SKINCOLOR_DIALOG_SETTINGS)
- ATTRIB(XonoticNewsDialog, intendedWidth, float, 0.96)
- ATTRIB(XonoticNewsDialog, rows, float, 24)
- ATTRIB(XonoticNewsDialog, columns, float, 1)
-ENDCLASS(XonoticNewsDialog)
-#endif
-
-#ifdef IMPLEMENTATION
-void XonoticNewsDialog_fill(entity me)
-{
- entity e;
- me.TR(me);
- me.TD(me, 24, 1, e = spawnGecko());
- e.configureBrowser( e, _("http://www.xonotic.org/team/blog/") );
-}
-#endif
me.TD(me, 1, 1, e = makeXonoticButton(_("Clear"), '0 0 0'));
e.onClick = KeyBinder_Bind_Clear;
e.onClickEntity = kb;
+ kb.clearButton = e;
me.gotoRC(me, 0, 3.2); me.setFirstColumn(me, me.currentColumn);
me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "con_closeontoggleconsole", _("Pressing \"enter console\" key also closes it")));
void InstantAction_LoadMap(entity btn, entity dummy)
{
- float pmin, pmax, pstep;
+ float pmin = 2, pmax = 16, pstep = 1;
cvar_set("timelimit_override", "10");
cvar_set("g_lms_lives_override", "9");
METHOD(XonoticInputBox, setText, void(entity, string))
ATTRIB(XonoticInputBox, fontSize, float, SKINFONTSIZE_NORMAL)
ATTRIB(XonoticInputBox, image, string, SKINGFX_INPUTBOX)
- ATTRIB(XonoticInputBox, onChange, void(entity, entity), SUB_Null)
+ ATTRIB(XonoticInputBox, onChange, void(entity, entity), func_null)
ATTRIB(XonoticInputBox, onChangeEntity, entity, NULL)
- ATTRIB(XonoticInputBox, onEnter, void(entity, entity), SUB_Null)
+ ATTRIB(XonoticInputBox, onEnter, void(entity, entity), func_null)
ATTRIB(XonoticInputBox, onEnterEntity, entity, NULL)
ATTRIB(XonoticInputBox, marginLeft, float, SKINMARGIN_INPUTBOX_CHARS)
ATTRIB(XonoticInputBox, marginRight, float, SKINMARGIN_INPUTBOX_CHARS)
if(me.text != new)
{
SUPER(XonoticInputBox).setText(me, new);
- me.onChange(me, me.onChangeEntity);
+ if(me.onChange)
+ me.onChange(me, me.onChangeEntity);
if(me.saveImmediately)
me.saveCvars(me);
}
me.saveCvars(me);
r = 1;
}
- me.onEnter(me, me.onEnterEntity);
+ if(me.onEnter)
+ me.onEnter(me, me.onEnterEntity);
}
if(SUPER(XonoticInputBox).keyDown(me, key, ascii, shift))
r = 1;
ATTRIB(XonoticKeyBinder, inMouseHandler, float, 0)
ATTRIB(XonoticKeyBinder, userbindEditButton, entity, NULL)
ATTRIB(XonoticKeyBinder, keyGrabButton, entity, NULL)
+ ATTRIB(XonoticKeyBinder, clearButton, entity, NULL)
ATTRIB(XonoticKeyBinder, userbindEditDialog, entity, NULL)
METHOD(XonoticKeyBinder, editUserbind, void(entity, string, string, string))
ENDCLASS(XonoticKeyBinder)
if(k != -1)
localcmd("\nbind \"", keynumtostring(k), "\" \"", to, "\"\n");
}
+ if(n)
+ cvar_set("_hud_showbinds_reload", "1");
}
void XonoticKeyBinder_configureXonoticKeyBinder(entity me)
{
return;
me.keyGrabButton.forcePressed = 1;
+ me.clearButton.disabled = 1;
keyGrabber = me;
}
void XonoticKeyBinder_keyGrabbed(entity me, float key, float ascii)
string func;
me.keyGrabButton.forcePressed = 0;
+ me.clearButton.disabled = 0;
+
if(key == K_ESCAPE)
return;
}
localcmd("\nbind \"", keynumtostring(key), "\" \"", func, "\"\n");
localcmd("-zoom\n"); // to make sure we aren't in togglezoom'd state
+ cvar_set("_hud_showbinds_reload", "1");
}
void XonoticKeyBinder_editUserbind(entity me, string theName, string theCommandPress, string theCommandRelease)
{
if(!me.userbindEditDialog)
return;
-
+
func = Xonotic_KeyBinds_Functions[me.selectedItem];
if(func == "")
return;
-
+
descr = Xonotic_KeyBinds_Descriptions[me.selectedItem];
if(substring(descr, 0, 1) != "$")
return;
if(!me.userbindEditDialog)
return;
-
+
func = Xonotic_KeyBinds_Functions[me.selectedItem];
if(func == "")
return;
-
+
descr = Xonotic_KeyBinds_Descriptions[me.selectedItem];
if(substring(descr, 0, 1) != "$")
return;
localcmd("\nbind \"", keynumtostring(k), "\" \"", KEY_NOT_BOUND_CMD, "\"\n");
}
localcmd("-zoom\n"); // to make sure we aren't in togglezoom'd state
+ cvar_set("_hud_showbinds_reload", "1");
}
void XonoticKeyBinder_clickListBoxItem(entity me, float i, vector where)
{
{
// layout: Ping, Map name, Map name, NP, TP, MP
string s;
- float p;
float theAlpha;
float included;
else if(included)
draw_Fill('0 0 0', '1 1 0', SKINCOLOR_MAPLIST_INCLUDEDBG, SKINALPHA_MAPLIST_INCLUDEDBG);
- s = ftos(p);
if(draw_PictureSize(strcat("/maps/", MapInfo_Map_bspname)) == '0 0 0')
draw_Picture(me.columnPreviewOrigin * eX, "nopreview_map", me.columnPreviewSize * eX + eY, '1 1 1', theAlpha);
else
{
float i;
string s;
- MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, MAPINFO_FLAG_FORBIDDEN | MAPINFO_FLAG_HIDDEN, 0); // all
+ MapInfo_FilterGametype(MAPINFO_TYPE_ALL, 0, 0, MapInfo_ForbiddenFlags(), 0); // all
s = "";
for(i = 0; i < MapInfo_count; ++i)
s = strcat(s, " ", MapInfo_BSPName_ByID(i));
// 5: AES required
{
- vector iconSize;
+ vector iconSize = '0 0 0';
iconSize_y = me.realFontSize_y * me.iconsSizeFactor;
iconSize_x = me.realFontSize_x * me.iconsSizeFactor;
- vector iconPos;
+ vector iconPos = '0 0 0';
iconPos_x = (me.columnIconsSize - 3 * iconSize_x) * 0.5;
iconPos_y = (1 - iconSize_y) * 0.5;
{
main.serverInfoDialog.loadServerInfo(main.serverInfoDialog, me.selectedItem);
DialogOpenButton_Click_withCoords(me, main.serverInfoDialog, org, sz);
+ return 1;
}
+ return 0;
}
else if(scan == K_INS || scan == K_MOUSE3 || scan == K_KP_INS)
{
{
ToggleFavorite(me.selectedServer);
me.ipAddressBoxFocused = -1;
+ return 1;
}
+ return 0;
}
else if(SUPER(XonoticServerList).keyDown(me, scan, ascii, shift))
return 1;
string campaign_name_previous;
float campaign_won_previous;
#ifdef WATERMARK
-var string autocvar_menu_watermark = WATERMARK();
+var string autocvar_menu_watermark = WATERMARK;
#else
var string autocvar_menu_watermark = "";
#endif
{
if(autocvar_menu_watermark != "")
{
- vector fs = '48 48 0';
draw_CenterText('0.5 0.1 0', sprintf(_("^1%s TEST BUILD"), autocvar_menu_watermark), globalToBoxSize('32 32 0', draw_scale), '1 1 1', 0.05, 1);
}
}
void preMenuDraw()
{
- vector fs, sz, line, mid;
+ vector fs, sz = '0 0 0', line, mid;
updateCheck();
.float antilag_debug;
-void antilag_dummy()
-{
- self.antilag_times = 0;
- self.antilag_origins = '0 0 0';
-}
-
void antilag_record(entity e, float t)
{
if (e.vehicle && e.vehicle.vehicle_flags == VHF_PLAYERSLOT)
}
if(g_keyhunt)
- kh_Controller_SetThink_NoMsg(autocvar_g_balance_keyhunt_delay_round+(game_starttime - time), kh_StartRound);
+ kh_Controller_SetThink(autocvar_g_balance_keyhunt_delay_round+(game_starttime - time), kh_StartRound);
if(g_arena)
if(champion && champion.classname == "player" && player_count > 1)
{
if(warmup && time < warmup)
{
- FOR_EACH_REALCLIENT(e)
- Send_CSQC_Centerprint_Generic_Expire(e, CPID_ROUND_STARTING);
+ Kill_Notification(NOTIF_ALL, world, MSG_CENTER_CPID, CPID_ARENA);
warmup = 0;
}
if(champion && g_arena)
if(f != roundStartTime_prev) {
roundStartTime_prev = f;
if(g_ca && !(red_players && blue_players)) {
- FOR_EACH_REALCLIENT(self)
- Send_CSQC_Centerprint_Generic(self, CPID_ROUND_STARTING, "^1Need at least 1 player in each team to play CA", 2, 0);
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_ARENA_NEEDPLAYER);
warmup = time + autocvar_g_ca_warmup;
} else {
if(f == 5)
else if(f == 1)
Announce("1");
- FOR_EACH_REALCLIENT(e)
- Send_CSQC_Centerprint_Generic(e, CPID_ROUND_STARTING, "Round will start in %d", 1, f);
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_ARENA_ROUNDSTART, f);
}
}
reset_map(TRUE);
} else {
Announce("begin");
- FOR_EACH_REALCLIENT(e)
- Send_CSQC_Centerprint_Generic(e, CPID_ROUND_STARTING, "^1Begin!", 1, 0);
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_ARENA_BEGIN);
}
if(g_arena) {
// count amount of players in each team
total_players = red_players = blue_players = yellow_players = pink_players = 0;
FOR_EACH_PLAYER(self) {
- if (self.team == COLOR_TEAM1)
+ if (self.team == NUM_TEAM_1)
{
red_players += 1;
total_players += 1;
}
- else if (self.team == COLOR_TEAM2)
+ else if (self.team == NUM_TEAM_2)
{
blue_players += 1;
total_players += 1;
}
- else if (self.team == COLOR_TEAM3)
+ else if (self.team == NUM_TEAM_3)
{
yellow_players += 1;
total_players += 1;
}
- else if (self.team == COLOR_TEAM4)
+ else if (self.team == NUM_TEAM_4)
{
pink_players += 1;
total_players += 1;
if(g_ca)
{
FOR_EACH_PLAYER(self) {
- if (self.team == COLOR_TEAM1 && self.health >= 1)
+ if (self.team == NUM_TEAM_1 && self.health >= 1)
{
redalive += 1;
totalalive += 1;
}
- else if (self.team == COLOR_TEAM2 && self.health >= 1)
+ else if (self.team == NUM_TEAM_2 && self.health >= 1)
{
bluealive += 1;
totalalive += 1;
{
// count amount of alive players in each team
FOR_EACH_PLAYER(self) {
- if (self.team == COLOR_TEAM1 && self.freezetag_frozen == 0 && self.health >= 1)
+ if (self.team == NUM_TEAM_1 && self.freezetag_frozen == 0 && self.health >= 1)
{
redalive += 1;
totalalive += 1;
}
- else if (self.team == COLOR_TEAM2 && self.freezetag_frozen == 0 && self.health >= 1)
+ else if (self.team == NUM_TEAM_2 && self.freezetag_frozen == 0 && self.health >= 1)
{
bluealive += 1;
totalalive += 1;
}
- else if (self.team == COLOR_TEAM3 && self.freezetag_frozen == 0 && self.health >= 1)
+ else if (self.team == NUM_TEAM_3 && self.freezetag_frozen == 0 && self.health >= 1)
{
yellowalive += 1;
totalalive += 1;
}
- else if (self.team == COLOR_TEAM4 && self.freezetag_frozen == 0 && self.health >= 1)
+ else if (self.team == NUM_TEAM_4 && self.freezetag_frozen == 0 && self.health >= 1)
{
pinkalive += 1;
totalalive += 1;
if(redalive) {
play2all("ctf/red_capture.wav");
FOR_EACH_CLIENT(self) centerprint(self, "^1RED ^7team wins the round");
- TeamScore_AddToTeam(COLOR_TEAM1, ST_SCORE, +1);
+ TeamScore_AddToTeam(NUM_TEAM_1, ST_SCORE, +1);
}
else if(bluealive) {
play2all("ctf/blue_capture.wav");
FOR_EACH_CLIENT(self) centerprint(self, "^4BLUE ^7team wins the round");
- TeamScore_AddToTeam(COLOR_TEAM2, ST_SCORE, +1);
+ TeamScore_AddToTeam(NUM_TEAM_2, ST_SCORE, +1);
}
else
FOR_EACH_CLIENT(self) centerprint(self, "^7Round tied");
remove(self);
return;
}
- self.team = COLOR_TEAM1; // red, gets swapped every round
+ self.team = NUM_TEAM_1; // red, gets swapped every round
spawnfunc_info_player_deathmatch();
}
remove(self);
return;
}
- self.team = COLOR_TEAM2; // blue, gets swapped every round
+ self.team = NUM_TEAM_2; // blue, gets swapped every round
spawnfunc_info_player_deathmatch();
}
}
self.spawnflags = 3;
self.classname = "func_assault_destructible";
- if(assault_attacker_team == COLOR_TEAM1) {
- self.team = COLOR_TEAM2;
+ if(assault_attacker_team == NUM_TEAM_1) {
+ self.team = NUM_TEAM_2;
} else {
- self.team = COLOR_TEAM1;
+ self.team = NUM_TEAM_1;
}
spawnfunc_func_breakable();
}
ent = find(world, classname, "turret_main");
while(ent) {
// Swap turret teams
- if(ent.team == COLOR_TEAM1)
- ent.team = COLOR_TEAM2;
+ if(ent.team == NUM_TEAM_1)
+ ent.team = NUM_TEAM_2;
else
- ent.team = COLOR_TEAM1;
+ ent.team = NUM_TEAM_1;
self = ent;
remove(self);
return;
}
- assault_attacker_team = COLOR_TEAM1;
+ assault_attacker_team = NUM_TEAM_1;
self.classname = "target_assault_roundstart";
self.use = assault_roundstart_use;
self.reset2 = assault_roundstart_use;
self.winning = self.winning + 1;
// swap attacker/defender roles
- if(assault_attacker_team == COLOR_TEAM1) {
- assault_attacker_team = COLOR_TEAM2;
+ if(assault_attacker_team == NUM_TEAM_1) {
+ assault_attacker_team = NUM_TEAM_2;
} else {
- assault_attacker_team = COLOR_TEAM1;
+ assault_attacker_team = NUM_TEAM_1;
}
{
if(clienttype(ent) == CLIENTTYPE_NOTACLIENT)
{
- if(ent.team_saved == COLOR_TEAM1)
- ent.team_saved = COLOR_TEAM2;
- else if(ent.team_saved == COLOR_TEAM2)
- ent.team_saved = COLOR_TEAM1;
+ if(ent.team_saved == NUM_TEAM_1)
+ ent.team_saved = NUM_TEAM_2;
+ else if(ent.team_saved == NUM_TEAM_2)
+ ent.team_saved = NUM_TEAM_1;
}
}
self.nearestwaypointtimeout = 0; // activate waypointing again
self.basewaypoint = self.nearestwaypoint;
- if(self.team == COLOR_TEAM1)
- WaypointSprite_SpawnFixed("redbase", self.origin + '0 0 61', self, sprite, RADARICON_FLAG, colormapPaletteColor(COLOR_TEAM1 - 1, FALSE));
+ if(self.team == NUM_TEAM_1)
+ WaypointSprite_SpawnFixed("redbase", self.origin + '0 0 61', self, sprite, RADARICON_FLAG, colormapPaletteColor(NUM_TEAM_1 - 1, FALSE));
else
- WaypointSprite_SpawnFixed("bluebase", self.origin + '0 0 61', self, sprite, RADARICON_FLAG, colormapPaletteColor(COLOR_TEAM2 - 1, FALSE));
+ WaypointSprite_SpawnFixed("bluebase", self.origin + '0 0 61', self, sprite, RADARICON_FLAG, colormapPaletteColor(NUM_TEAM_2 - 1, FALSE));
}
float ctf_score_value(string parameter)
ctf_captureshield_update(p, 0); // shield only
e.playerid = attacker.playerid;
e.ctf_droptime = time;
- WaypointSprite_Spawn("flagdropped", 0, 0, e, '0 0 1' * 61, world, COLOR_TEAM1 + COLOR_TEAM2 - e.team, e, waypointsprite_attachedforcarrier, FALSE, RADARICON_FLAG, '0 1 1');
+ WaypointSprite_Spawn("flagdropped", 0, 0, e, '0 0 1' * 61, world, NUM_TEAM_1 + NUM_TEAM_2 - e.team, e, waypointsprite_attachedforcarrier, FALSE, RADARICON_FLAG, '0 1 1');
WaypointSprite_Ping(e.waypointsprite_attachedforcarrier);
if(p.waypointsprite_attachedforcarrier)
UpdateFrags(other, ctf_score_value("score_capture"));
if (autocvar_g_ctf_flag_capture_effects) {
- if (other.team == COLOR_TEAM1) { // red team scores effect
+ if (other.team == NUM_TEAM_1) { // red team scores effect
pointparticles(particleeffectnum("red_ground_quake"), self.origin, '0 0 0', 1);
flag_cap_ring_spawn(self.origin);
}
- if (other.team == COLOR_TEAM2) { // blue team scores effect
+ if (other.team == NUM_TEAM_2) { // blue team scores effect
pointparticles(particleeffectnum("blue_ground_quake"), self.origin, '0 0 0', 1);
flag_cap_ring_spawn(self.origin);
}
other.next_take_time = time + 1;
}
if (self.cnt == FLAG_BASE)
- if (other.team == COLOR_TEAM1 || other.team == COLOR_TEAM2) // only red and blue team can steal flags
+ if (other.team == NUM_TEAM_1 || other.team == NUM_TEAM_2) // only red and blue team can steal flags
if (other.team != self.team)
if (!other.flagcarried)
if (!other.ctf_captureshielded)
if (self.cnt == FLAG_DROPPED)
{
self.flags = FL_ITEM | FL_NOTARGET; // clear FL_ONGROUND and any other junk
- if (other.team == self.team || (other.team != COLOR_TEAM1 && other.team != COLOR_TEAM2))
+ if (other.team == self.team || (other.team != NUM_TEAM_1 && other.team != NUM_TEAM_2))
{
// return flag
Send_KillNotification (other.netname, self.netname, "", INFO_RETURNFLAG, MSG_INFO);
}
// punish the team who was last carrying it
- if(self.team == COLOR_TEAM1)
- TeamScore_AddToTeam(COLOR_TEAM2, ST_SCORE, -ctf_score_value("penalty_returned"));
+ if(self.team == NUM_TEAM_1)
+ TeamScore_AddToTeam(NUM_TEAM_2, ST_SCORE, -ctf_score_value("penalty_returned"));
else
- TeamScore_AddToTeam(COLOR_TEAM1, ST_SCORE, -ctf_score_value("penalty_returned"));
+ TeamScore_AddToTeam(NUM_TEAM_1, ST_SCORE, -ctf_score_value("penalty_returned"));
// reward the player who returned it
if(other.playerid == self.playerid) // is this the guy who killed the FC last?
{
- if (other.team == COLOR_TEAM1 || other.team == COLOR_TEAM2)
+ if (other.team == NUM_TEAM_1 || other.team == NUM_TEAM_2)
UpdateFrags(other, ctf_score_value("score_return_by_killer"));
else
UpdateFrags(other, ctf_score_value("score_return_rogue_by_killer"));
}
else
{
- if (other.team == COLOR_TEAM1 || other.team == COLOR_TEAM2)
+ if (other.team == NUM_TEAM_1 || other.team == NUM_TEAM_2)
UpdateFrags(other, ctf_score_value("score_return"));
else
UpdateFrags(other, ctf_score_value("score_return_rogue"));
remove(self);
return;
}
- self.team = COLOR_TEAM1; // red
+ self.team = NUM_TEAM_1; // red
spawnfunc_info_player_deathmatch();
}
//self.team = 4;self.classname = "info_player_start";spawnfunc_info_player_start();}
remove(self);
return;
}
- self.team = COLOR_TEAM2; // blue
+ self.team = NUM_TEAM_2; // blue
spawnfunc_info_player_deathmatch();
}
//self.team = 13;self.classname = "info_player_start";spawnfunc_info_player_start();}
remove(self);
return;
}
- self.team = COLOR_TEAM3; // yellow
+ self.team = NUM_TEAM_3; // yellow
spawnfunc_info_player_deathmatch();
}
remove(self);
return;
}
- self.team = COLOR_TEAM4; // purple
+ self.team = NUM_TEAM_4; // purple
spawnfunc_info_player_deathmatch();
}
// Flag Glow Trail Support
if(autocvar_g_ctf_flag_glowtrails)
{ // Provide Flag Glow Trail
- if(self.team == COLOR_TEAM1)
+ if(self.team == NUM_TEAM_1)
// Red
self.glow_color = 251;
else
- if(self.team == COLOR_TEAM2)
+ if(self.team == NUM_TEAM_2)
// Blue
self.glow_color = 210;
ctf_worldflaglist = self;
self.classname = "item_flag_team";
- self.team = COLOR_TEAM1; // color 4 team (red)
+ self.team = NUM_TEAM_1; // color 4 team (red)
self.items = IT_KEY2; // gold key (redish enough)
self.netname = "^1RED^7 flag";
self.target = "###item###";
ctf_worldflaglist = self;
self.classname = "item_flag_team";
- self.team = COLOR_TEAM2; // color 13 team (blue)
+ self.team = NUM_TEAM_2; // color 13 team (blue)
self.items = IT_KEY1; // silver key (bluish enough)
self.netname = "^4BLUE^7 flag";
self.target = "###item###";
numteams = 2;//cvar("g_ctf_default_teams");
- ctf_spawnteam("Red", COLOR_TEAM1 - 1);
- ctf_spawnteam("Blue", COLOR_TEAM2 - 1);
+ ctf_spawnteam("Red", NUM_TEAM_1 - 1);
+ ctf_spawnteam("Blue", NUM_TEAM_2 - 1);
}
void ctf_delayedinit()
entity ctf_team_has_commander(float cteam)
{
entity pl;
- if(cteam != COLOR_TEAM1 || cteam != COLOR_TEAM2)
+ if(cteam != NUM_TEAM_1 || cteam != NUM_TEAM_2)
return world;
FOR_EACH_REALPLAYER(pl) {
--- /dev/null
+
+/*
+Domination as a plugin for netquake mods
+by LordHavoc (lordhavoc@ghdigital.com)
+
+How to add domination points to a mod:
+1. Add this line to progs.src above world.qc:
+domination.qc
+2. Comment out all lines in ClientObituary in client.qc that begin with targ.frags or attacker.frags.
+3. Add this above spawnfunc_worldspawn in world.qc:
+void() dom_init;
+4. Add this line to the end of spawnfunc_worldspawn in world.qc:
+dom_init();
+
+Note: The only teams who can use dom control points are identified by spawnfunc_dom_team entities (if none exist these default to red and blue and use only quake models/sounds).
+*/
+
+#define DOMPOINTFRAGS frags
+
+.float enemy_playerid;
+.entity sprite;
+.float captime;
+
+// pps: points per second
+.float dom_total_pps;
+.float dom_pps_red;
+.float dom_pps_blue;
+.float dom_pps_yellow;
+.float dom_pps_pink;
+float total_pps;
+float pps_red;
+float pps_blue;
+float pps_yellow;
+float pps_pink;
+void set_dom_state(entity e)
+{
+ e.dom_total_pps = total_pps;
+ e.dom_pps_red = pps_red;
+ e.dom_pps_blue = pps_blue;
+ if(c3 >= 0)
+ e.dom_pps_yellow = pps_yellow;
+ if(c4 >= 0)
+ e.dom_pps_pink = pps_pink;
+}
+
+void() dom_controlpoint_setup;
+
+void LogDom(string mode, float team_before, entity actor)
+{
+ string s;
+ if(!autocvar_sv_eventlog)
+ return;
+ s = strcat(":dom:", mode);
+ s = strcat(s, ":", ftos(team_before));
+ s = strcat(s, ":", ftos(actor.playerid));
+ GameLogEcho(s);
+}
+
+void() dom_spawnteams;
+
+void dompoint_captured ()
+{
+ entity head;
+ float old_delay, old_team, real_team;
+
+ // now that the delay has expired, switch to the latest team to lay claim to this point
+ head = self.owner;
+
+ real_team = self.cnt;
+ self.cnt = -1;
+
+ LogDom("taken", self.team, self.dmg_inflictor);
+ self.dmg_inflictor = world;
+
+ self.goalentity = head;
+ self.model = head.mdl;
+ self.modelindex = head.dmg;
+ self.skin = head.skin;
+
+ //bprint(head.message);
+ //bprint("\n");
+
+ //bprint(^3head.netname);
+ //bprint(head.netname);
+ //bprint(self.message);
+ //bprint("\n");
+
+ float points, wait_time;
+ if (autocvar_g_domination_point_amt)
+ points = autocvar_g_domination_point_amt;
+ else
+ points = self.frags;
+ if (autocvar_g_domination_point_rate)
+ wait_time = autocvar_g_domination_point_rate;
+ else
+ wait_time = self.wait;
+
+ bprint("^3", head.netname, "^3", self.message);
+ if (points != 1)
+ bprint(" ^7(", ftos(points), " points every ", ftos(wait_time), " seconds)\n");
+ else
+ bprint(" ^7(", ftos(points), " point every ", ftos(wait_time), " seconds)\n");
+
+ if(self.enemy.playerid == self.enemy_playerid)
+ PlayerScore_Add(self.enemy, SP_DOM_TAKES, 1);
+ else
+ self.enemy = world;
+
+ if (head.noise != "")
+ if(self.enemy)
+ sound(self.enemy, CH_TRIGGER, head.noise, VOL_BASE, ATTN_NORM);
+ else
+ sound(self, CH_TRIGGER, head.noise, VOL_BASE, ATTN_NORM);
+ if (head.noise1 != "")
+ play2all(head.noise1);
+
+ //self.nextthink = time + autocvar_g_domination_point_rate;
+ //self.think = dompointthink;
+
+ self.delay = time + wait_time;
+
+ // do trigger work
+ old_delay = self.delay;
+ old_team = self.team;
+ self.team = real_team;
+ self.delay = 0;
+ activator = self;
+ SUB_UseTargets ();
+ self.delay = old_delay;
+ self.team = old_team;
+
+ switch(self.goalentity.team)
+ {
+ case NUM_TEAM_1:
+ WaypointSprite_UpdateSprites(self.sprite, "dom-red", "", "");
+ break;
+ case NUM_TEAM_2:
+ WaypointSprite_UpdateSprites(self.sprite, "dom-blue", "", "");
+ break;
+ case NUM_TEAM_3:
+ WaypointSprite_UpdateSprites(self.sprite, "dom-yellow", "", "");
+ break;
+ case NUM_TEAM_4:
+ WaypointSprite_UpdateSprites(self.sprite, "dom-pink", "", "");
+ }
+
+ total_pps = 0, pps_red = 0, pps_blue = 0, pps_yellow = 0, pps_pink = 0;
+ for(head = world; (head = find(head, classname, "dom_controlpoint")) != world; )
+ {
+ if (autocvar_g_domination_point_amt)
+ points = autocvar_g_domination_point_amt;
+ else
+ points = head.frags;
+ if (autocvar_g_domination_point_rate)
+ wait_time = autocvar_g_domination_point_rate;
+ else
+ wait_time = head.wait;
+ switch(head.goalentity.team)
+ {
+ case NUM_TEAM_1:
+ pps_red += points/wait_time;
+ break;
+ case NUM_TEAM_2:
+ pps_blue += points/wait_time;
+ break;
+ case NUM_TEAM_3:
+ pps_yellow += points/wait_time;
+ break;
+ case NUM_TEAM_4:
+ pps_pink += points/wait_time;
+ }
+ total_pps += points/wait_time;
+ }
+
+ WaypointSprite_UpdateTeamRadar(self.sprite, RADARICON_DOMPOINT, colormapPaletteColor(self.goalentity.team - 1, 0));
+ WaypointSprite_Ping(self.sprite);
+
+ self.captime = time;
+
+ FOR_EACH_REALCLIENT(head)
+ set_dom_state(head);
+}
+
+void AnimateDomPoint()
+{
+ if(self.pain_finished > time)
+ return;
+ self.pain_finished = time + self.t_width;
+ if(self.nextthink > self.pain_finished)
+ self.nextthink = self.pain_finished;
+
+ self.frame = self.frame + 1;
+ if(self.frame > self.t_length)
+ self.frame = 0;
+}
+
+void dompointthink()
+{
+ float fragamt;
+
+ self.nextthink = time + 0.1;
+
+ //self.frame = self.frame + 1;
+ //if(self.frame > 119)
+ // self.frame = 0;
+ AnimateDomPoint();
+
+ // give points
+
+ if (gameover || self.delay > time || time < game_starttime) // game has ended, don't keep giving points
+ return;
+
+ if(autocvar_g_domination_point_rate)
+ self.delay = time + autocvar_g_domination_point_rate;
+ else
+ self.delay = time + self.wait;
+
+ // give credit to the team
+ // NOTE: this defaults to 0
+ if (self.goalentity.netname != "")
+ {
+ if(autocvar_g_domination_point_amt)
+ fragamt = autocvar_g_domination_point_amt;
+ else
+ fragamt = self.DOMPOINTFRAGS;
+ TeamScore_AddToTeam(self.goalentity.team, ST_SCORE, fragamt);
+ TeamScore_AddToTeam(self.goalentity.team, ST_DOM_TICKS, fragamt);
+
+ // give credit to the individual player, if he is still there
+ if (self.enemy.playerid == self.enemy_playerid)
+ {
+ PlayerScore_Add(self.enemy, SP_SCORE, fragamt);
+ PlayerScore_Add(self.enemy, SP_DOM_TICKS, fragamt);
+ }
+ else
+ self.enemy = world;
+ }
+}
+
+void dompointtouch()
+{
+ entity head;
+ if (other.classname != "player")
+ return;
+ if (other.health < 1)
+ return;
+
+ if(time < self.captime + 0.3)
+ return;
+
+ // only valid teams can claim it
+ head = find(world, classname, "dom_team");
+ while (head && head.team != other.team)
+ head = find(head, classname, "dom_team");
+ if (!head || head.netname == "" || head == self.goalentity)
+ return;
+
+ // delay capture
+
+ self.team = self.goalentity.team; // this stores the PREVIOUS team!
+
+ self.cnt = other.team;
+ self.owner = head; // team to switch to after the delay
+ self.dmg_inflictor = other;
+
+ // self.state = 1;
+ // self.delay = time + cvar("g_domination_point_capturetime");
+ //self.nextthink = time + cvar("g_domination_point_capturetime");
+ //self.think = dompoint_captured;
+
+ // go to neutral team in the mean time
+ head = find(world, classname, "dom_team");
+ while (head && head.netname != "")
+ head = find(head, classname, "dom_team");
+ if(head == world)
+ return;
+
+ WaypointSprite_UpdateSprites(self.sprite, "dom-neut", "", "");
+ WaypointSprite_UpdateTeamRadar(self.sprite, RADARICON_DOMPOINT, '0 1 1');
+ WaypointSprite_Ping(self.sprite);
+
+ self.goalentity = head;
+ self.model = head.mdl;
+ self.modelindex = head.dmg;
+ self.skin = head.skin;
+
+ self.enemy = other; // individual player scoring
+ self.enemy_playerid = other.playerid;
+ dompoint_captured();
+}
+
+/*QUAKED spawnfunc_dom_team (0 .5 .8) (-32 -32 -24) (32 32 32)
+Team declaration for Domination gameplay, this allows you to decide what team
+names and control point models are used in your map.
+
+Note: If you use spawnfunc_dom_team entities you must define at least 3 and only two
+can have netname set! The nameless team owns all control points at start.
+
+Keys:
+"netname"
+ Name of the team (for example Red Team, Blue Team, Green Team, Yellow Team, Life, Death, etc)
+"cnt"
+ Scoreboard color of the team (for example 4 is red and 13 is blue)
+"model"
+ Model to use for control points owned by this team (for example
+ "progs/b_g_key.mdl" is a gold keycard, and "progs/b_s_key.mdl" is a silver
+ keycard)
+"skin"
+ Skin of the model to use (for team skins on a single model)
+"noise"
+ Sound to play when this team captures a point.
+ (this is a localized sound, like a small alarm or other effect)
+"noise1"
+ Narrator speech to play when this team captures a point.
+ (this is a global sound, like "Red team has captured a control point")
+*/
+
+void spawnfunc_dom_team()
+{
+ if(!g_domination || autocvar_g_domination_teams_override >= 2)
+ {
+ remove(self);
+ return;
+ }
+ precache_model(self.model);
+ if (self.noise != "")
+ precache_sound(self.noise);
+ if (self.noise1 != "")
+ precache_sound(self.noise1);
+ self.classname = "dom_team";
+ setmodel(self, self.model); // precision not needed
+ self.mdl = self.model;
+ self.dmg = self.modelindex;
+ self.model = "";
+ self.modelindex = 0;
+ // this would have to be changed if used in quakeworld
+ if(self.cnt)
+ self.team = self.cnt + 1; // WHY are these different anyway?
+}
+
+void dom_controlpoint_setup()
+{
+ entity head;
+ // find the spawnfunc_dom_team representing unclaimed points
+ head = find(world, classname, "dom_team");
+ while(head && head.netname != "")
+ head = find(head, classname, "dom_team");
+ if (!head)
+ objerror("no spawnfunc_dom_team with netname \"\" found\n");
+
+ // copy important properties from spawnfunc_dom_team entity
+ self.goalentity = head;
+ setmodel(self, head.mdl); // precision already set
+ self.skin = head.skin;
+
+ self.cnt = -1;
+
+ if(self.message == "")
+ self.message = " has captured a control point";
+
+ if(self.DOMPOINTFRAGS <= 0)
+ self.DOMPOINTFRAGS = 1;
+ if(self.wait <= 0)
+ self.wait = 5;
+
+ float points, waittime;
+ if (autocvar_g_domination_point_amt)
+ points = autocvar_g_domination_point_amt;
+ else
+ points = self.frags;
+ if (autocvar_g_domination_point_rate)
+ waittime = autocvar_g_domination_point_rate;
+ else
+ waittime = self.wait;
+
+ total_pps += points/waittime;
+
+ if(!self.t_width)
+ self.t_width = 0.02; // frame animation rate
+ if(!self.t_length)
+ self.t_length = 239; // maximum frame
+
+ self.think = dompointthink;
+ self.nextthink = time;
+ self.touch = dompointtouch;
+ self.solid = SOLID_TRIGGER;
+ self.flags = FL_ITEM;
+ setsize(self, '-32 -32 -32', '32 32 32');
+ setorigin(self, self.origin + '0 0 20');
+ droptofloor();
+
+ waypoint_spawnforitem(self);
+ WaypointSprite_SpawnFixed("dom-neut", self.origin + '0 0 32', self, sprite, RADARICON_DOMPOINT, '0 1 1');
+}
+
+
+
+/*QUAKED spawnfunc_dom_controlpoint (0 .5 .8) (-16 -16 -24) (16 16 32)
+Control point for Domination gameplay.
+*/
+void spawnfunc_dom_controlpoint()
+{
+ if(!g_domination)
+ {
+ remove(self);
+ return;
+ }
+ self.think = dom_controlpoint_setup;
+ self.nextthink = time + 0.1;
+ self.reset = dom_controlpoint_setup;
+
+ if(!self.scale)
+ self.scale = 0.6;
+
+ //if(!self.glow_size)
+ // self.glow_size = cvar("g_domination_point_glow");
+ self.effects = self.effects | EF_LOWPRECISION;
+ if (autocvar_g_domination_point_fullbright)
+ self.effects |= EF_FULLBRIGHT;
+}
+
+// code from here on is just to support maps that don't have control point and team entities
+void dom_spawnteam (string teamname, float teamcolor, string pointmodel, float pointskin, string capsound, string capnarration, string capmessage)
+{
+ entity oldself;
+ oldself = self;
+ self = spawn();
+ self.classname = "dom_team";
+ self.netname = teamname;
+ self.cnt = teamcolor;
+ self.model = pointmodel;
+ self.skin = pointskin;
+ self.noise = capsound;
+ self.noise1 = capnarration;
+ self.message = capmessage;
+
+ // this code is identical to spawnfunc_dom_team
+ setmodel(self, self.model); // precision not needed
+ self.mdl = self.model;
+ self.dmg = self.modelindex;
+ self.model = "";
+ self.modelindex = 0;
+ // this would have to be changed if used in quakeworld
+ self.team = self.cnt + 1;
+
+ //eprint(self);
+ self = oldself;
+}
+
+void dom_spawnpoint(vector org)
+{
+ entity oldself;
+ oldself = self;
+ self = spawn();
+ self.classname = "dom_controlpoint";
+ self.think = spawnfunc_dom_controlpoint;
+ self.nextthink = time;
+ setorigin(self, org);
+ spawnfunc_dom_controlpoint();
+ self = oldself;
+}
+
+// spawn some default teams if the map is not set up for domination
+void dom_spawnteams()
+{
+ float numteams;
+ if(autocvar_g_domination_teams_override < 2)
+ numteams = autocvar_g_domination_default_teams;
+ else
+ numteams = autocvar_g_domination_teams_override;
+ // LordHavoc: edit this if you want to change defaults
+ dom_spawnteam("Red", NUM_TEAM_1-1, "models/domination/dom_red.md3", 0, "domination/claim.wav", "", "Red team has captured a control point");
+ dom_spawnteam("Blue", NUM_TEAM_2-1, "models/domination/dom_blue.md3", 0, "domination/claim.wav", "", "Blue team has captured a control point");
+ if(numteams > 2)
+ dom_spawnteam("Yellow", NUM_TEAM_3-1, "models/domination/dom_yellow.md3", 0, "domination/claim.wav", "", "Yellow team has captured a control point");
+ if(numteams > 3)
+ dom_spawnteam("Pink", NUM_TEAM_4-1, "models/domination/dom_pink.md3", 0, "domination/claim.wav", "", "Pink team has captured a control point");
+ dom_spawnteam("", 0, "models/domination/dom_unclaimed.md3", 0, "", "", "");
+}
+
+void dom_delayedinit()
+{
+ entity head;
+
+ // if no teams are found, spawn defaults, if custom teams are set, use them
+ if (find(world, classname, "dom_team") == world || autocvar_g_domination_teams_override >= 2)
+ dom_spawnteams();
+ // if no control points are found, spawn defaults
+ if (find(world, classname, "dom_controlpoint") == world)
+ {
+ // TODO in a few months (maybe 2011/08): change this into error() and remove this very poor dom point selection
+ backtrace("This map contains no dom_controlpoint entities. A very poor dom point placement will be chosen. Please fix the map.");
+
+ // if no supported map was found, make every deathmatch spawn a point
+ head = find(world, classname, "info_player_deathmatch");
+ while (head)
+ {
+ dom_spawnpoint(head.origin);
+ head = find(head, classname, "info_player_deathmatch");
+ }
+ }
+
+ ScoreRules_dom();
+}
+
+void dom_init()
+{
+ // we have to precache default models/sounds even if they might not be
+ // used because spawnfunc_worldspawn is executed before any other entities are read,
+ // so we don't even know yet if this map is set up for domination...
+ precache_model("models/domination/dom_red.md3");
+ precache_model("models/domination/dom_blue.md3");
+ precache_model("models/domination/dom_yellow.md3");
+ precache_model("models/domination/dom_pink.md3");
+ precache_model("models/domination/dom_unclaimed.md3");
+ precache_sound("domination/claim.wav");
+ InitializeEntity(world, dom_delayedinit, INITPRIO_GAMETYPE);
+
+ addstat(STAT_DOM_TOTAL_PPS, AS_FLOAT, dom_total_pps);
+ addstat(STAT_DOM_PPS_RED, AS_FLOAT, dom_pps_red);
+ addstat(STAT_DOM_PPS_BLUE, AS_FLOAT, dom_pps_blue);
+ if(c3 >= 0) addstat(STAT_DOM_PPS_YELLOW, AS_FLOAT, dom_pps_yellow);
+ if(c4 >= 0) addstat(STAT_DOM_PPS_PINK, AS_FLOAT, dom_pps_pink);
+}
+
setmodel (e, "models/ebomb.mdl");
e.movetype = MOVETYPE_NONE;
e.solid = SOLID_NOT;
- e.think = SUB_Null;
+ e.think = func_null;
e.nextthink = -1;
e.scale = 16;
}
setmodel(self,"");
self.solid = SOLID_NOT;
self.takedamage = DAMAGE_NO;
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
self.enemy = world;
self.think = zombie_spawn;
self.nextthink = time + autocvar_g_monster_zombie_respawntime;
ball.velocity = '0 0 0';
ball.movetype = MOVETYPE_NONE;
- ball.touch = SUB_Null;
+ ball.touch = func_null;
ball.effects |= EF_NOSHADOW;
ball.scale = 1; // scale down.
if (self.cnt < 2) { // step 1
if (time == self.teamtime)
bprint("The ", ColoredTeamName(self.team), " held the ball for too long.\n");
- self.touch = SUB_Null;
+ self.touch = func_null;
self.movetype = MOVETYPE_NOCLIP;
self.velocity = '0 0 0'; // just in case?
if(!self.cnt)
ball.cnt = 1;
ball.think = ResetBall;
if (ball.classname == "nexball_basketball")
- ball.touch = football_touch; // better than SUB_Null: football control until the ball gets reset
+ ball.touch = football_touch; // better than func_null: football control until the ball gets reset
ball.nextthink = time + autocvar_g_nexball_delay_goal * (self.team != GOAL_OUT);
}
{
switch(e.team)
{
- case COLOR_TEAM1: if(!t_r) { nb_spawnteam ("Red", e.team-1) ; t_r = 1; } break;
- case COLOR_TEAM2: if(!t_b) { nb_spawnteam ("Blue", e.team-1) ; t_b = 1; } break;
- case COLOR_TEAM3: if(!t_y) { nb_spawnteam ("Yellow", e.team-1); t_y = 1; } break;
- case COLOR_TEAM4: if(!t_p) { nb_spawnteam ("Pink", e.team-1) ; t_p = 1; } break;
+ case NUM_TEAM_1: if(!t_r) { nb_spawnteam ("Red", e.team-1) ; t_r = 1; } break;
+ case NUM_TEAM_2: if(!t_b) { nb_spawnteam ("Blue", e.team-1) ; t_b = 1; } break;
+ case NUM_TEAM_3: if(!t_y) { nb_spawnteam ("Yellow", e.team-1); t_y = 1; } break;
+ case NUM_TEAM_4: if(!t_p) { nb_spawnteam ("Pink", e.team-1) ; t_p = 1; } break;
}
}
}
void spawnfunc_nexball_redgoal (void)
{
- self.team = COLOR_TEAM1;
+ self.team = NUM_TEAM_1;
SpawnGoal();
}
void spawnfunc_nexball_bluegoal (void)
{
- self.team = COLOR_TEAM2;
+ self.team = NUM_TEAM_2;
SpawnGoal();
}
void spawnfunc_nexball_yellowgoal (void)
{
- self.team = COLOR_TEAM3;
+ self.team = NUM_TEAM_3;
SpawnGoal();
}
void spawnfunc_nexball_pinkgoal (void)
{
- self.team = COLOR_TEAM4;
+ self.team = NUM_TEAM_4;
SpawnGoal();
}
void bumb_die()
{
self.health = 0;
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
self.solid = SOLID_CORPSE;
self.takedamage = DAMAGE_NO;
self.deadflag = DEAD_DYING;
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_headshotaddeddamage;
float autocvar_g_balance_rifle_primary_lifetime;
float autocvar_g_balance_rifle_primary_refire;
float autocvar_g_balance_rifle_primary_shots;
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_headshotaddeddamage;
float autocvar_g_balance_rifle_secondary_lifetime;
float autocvar_g_balance_rifle_secondary_reload;
float autocvar_g_balance_rifle_secondary_refire;
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_headshotaddeddamage;
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_spread_min;
float autocvar_g_balance_uzi_sustained_ammo;
float autocvar_g_balance_uzi_sustained_damage;
-float autocvar_g_balance_uzi_sustained_headshotaddeddamage;
float autocvar_g_balance_uzi_sustained_force;
float autocvar_g_balance_uzi_sustained_refire;
float autocvar_g_balance_uzi_sustained_spread;
float autocvar_g_chat_flood_spl_tell;
float autocvar_g_chat_nospectators;
float autocvar_g_chat_teamcolors;
+float autocvar_g_chat_tellprivacy;
float autocvar_g_ctf_allow_vehicle_carry;
float autocvar_g_ctf_allow_vehicle_touch;
float autocvar_g_ctf_throw;
float autocvar_g_ctf_pass_turnrate;
float autocvar_g_ctf_pass_timelimit;
float autocvar_g_ctf_pass_velocity;
-float autocvar_g_ctf_captimerecord_always;
float autocvar_g_ctf_dynamiclights;
string autocvar_g_ctf_flag_blue_model;
float autocvar_g_ctf_flag_blue_skin;
float autocvar_g_ctf_flag_dropped_floatinwater;
float autocvar_g_ctf_flag_glowtrails;
float autocvar_g_ctf_flag_health;
-float autocvar_g_ctf_flag_pickup_verbosename;
string autocvar_g_ctf_flag_red_model;
float autocvar_g_ctf_flag_red_skin;
float autocvar_g_ctf_flag_return_time;
float autocvar_g_jetpack_acceleration_side;
float autocvar_g_jetpack_acceleration_up;
float autocvar_g_jetpack_antigravity;
-float autocvar_g_jetpack_attenuation;
float autocvar_g_jetpack_fuel;
float autocvar_g_jetpack_maxspeed_side;
float autocvar_g_jetpack_maxspeed_up;
float autocvar_g_lms_campcheck_damage;
float autocvar_g_lms_campcheck_distance;
float autocvar_g_lms_campcheck_interval;
-string autocvar_g_lms_campcheck_message;
float autocvar_g_lms_join_anytime;
float autocvar_g_lms_last_join;
#define autocvar_g_lms_lives_override cvar("g_lms_lives_override")
string autocvar_sv_eventlog_files_nameprefix;
string autocvar_sv_eventlog_files_namesuffix;
float autocvar_sv_eventlog_files_timestamps;
-float autocvar_sv_fraginfo;
-float autocvar_sv_fraginfo_handicap;
-float autocvar_sv_fraginfo_ping;
-float autocvar_sv_fraginfo_stats;
float autocvar_sv_friction;
float autocvar_sv_friction_on_land;
float autocvar_sv_gameplayfix_q2airaccelerate;
+float autocvar_sv_gentle;
#define autocvar_sv_gravity cvar("sv_gravity")
string autocvar_sv_intermission_cdtrack;
string autocvar_sv_jumpspeedcap_max;
float autocvar_sv_maxairstrafespeed;
float autocvar_sv_maxspeed;
string autocvar_sv_motd;
-float autocvar_sv_player_jumpanim_minfall;
float autocvar_sv_precacheplayermodels;
float autocvar_sv_precacheweapons;
float autocvar_sv_q3acompat_machineshotgunswap;
float autocvar_sv_vote_stop;
float autocvar_sv_vote_timeout;
float autocvar_sv_vote_wait;
+float autocvar_sv_vote_gamestart;
float autocvar_sv_warsowbunny_accel;
float autocvar_sv_warsowbunny_airforwardaccel;
float autocvar_sv_warsowbunny_backtosideratio;
float autocvar_sv_gameplayfix_gravityunaffectedbyticrate;
float autocvar_g_trueaim_minrange;
float autocvar_g_debug_defaultsounds;
-float autocvar_g_loituma;
float autocvar_g_grab_range;
float autocvar_g_sandbox_info;
float autocvar_g_sandbox_readonly;
float autocvar_g_sandbox_object_material_velocity_factor;
float autocvar_g_max_info_autoscreenshot;
float autocvar_physics_ode;
+float autocvar_g_physical_items;
+float autocvar_g_physical_items_damageforcescale;
+float autocvar_g_physical_items_reset;
if (autocvar_g_campaign && !campaign_bots_may_start)
{
- self.nextthink = time + 0.5;
+ self.bot_nextthink = time + 0.5;
return;
}
{
// block the bot during the countdown to game start
self.movement = '0 0 0';
- self.nextthink = game_starttime;
+ self.bot_nextthink = game_starttime;
return;
}
else
{
RandomSelection_Init();
- for(;;)
+ while((readfile = fgets(file)))
{
- readfile = fgets(file);
- if(!readfile)
- break;
if(substring(readfile, 0, 2) == "//")
continue;
if(substring(readfile, 0, 1) == "#")
continue;
tokens = tokenizebyseparator(readfile, "\t");
+ if(tokens == 0)
+ continue;
s = argv(0);
prio = 1;
FOR_EACH_CLIENT(p)
self.bot_nextthink = time - random();
self.lag_func = bot_lagfunc;
self.isbot = TRUE;
- self.createdtime = self.nextthink;
+ self.createdtime = self.bot_nextthink;
if(!self.bot_config_loaded) // This is needed so team overrider doesn't break between matches
bot_setnameandstuff();
if(self.bot_forced_team==1)
- self.team = COLOR_TEAM1;
+ self.team = NUM_TEAM_1;
else if(self.bot_forced_team==2)
- self.team = COLOR_TEAM2;
+ self.team = NUM_TEAM_2;
else if(self.bot_forced_team==3)
- self.team = COLOR_TEAM3;
+ self.team = NUM_TEAM_3;
else if(self.bot_forced_team==4)
- self.team = COLOR_TEAM4;
+ self.team = NUM_TEAM_4;
else
JoinBestTeam(self, FALSE, TRUE);
bestcount = 0;
while (head)
{
- if(head.team == COLOR_TEAM1)
+ if(head.team == NUM_TEAM_1)
thiscount = c1;
- else if(head.team == COLOR_TEAM2)
+ else if(head.team == NUM_TEAM_2)
thiscount = c2;
- else if(head.team == COLOR_TEAM3)
+ else if(head.team == NUM_TEAM_3)
thiscount = c3;
- else if(head.team == COLOR_TEAM4)
+ else if(head.team == NUM_TEAM_4)
thiscount = c4;
else
thiscount = 0;
continue;
// Ignore owned controlpoints
- if(self.team == COLOR_TEAM1)
+ if(self.team == NUM_TEAM_1)
{
if( (cp2.isgenneighbor_blue || cp2.iscpneighbor_blue) && !(cp2.isgenneighbor_red || cp2.iscpneighbor_red) )
continue;
}
- else if(self.team == COLOR_TEAM2)
+ else if(self.team == NUM_TEAM_2)
{
if( (cp2.isgenneighbor_red || cp2.iscpneighbor_red) && !(cp2.isgenneighbor_blue || cp2.iscpneighbor_blue) )
continue;
{
// Should be touched
// dprint(self.netname, " found a touchable controlpoint at ", vtos(cp.origin) ,"\n");
+ found = FALSE;
// Look for auto generated waypoint
if not(bot_waypoints_for_items)
// choose a role according to the situation
void havocbot_role_dm();
-//DOM:
-//go to best items, or control points you don't own
-void havocbot_role_dom()
-{
- if(self.deadflag != DEAD_NO)
- return;
-
- if (self.bot_strategytime < time)
- {
- self.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
- navigation_goalrating_start();
- havocbot_goalrating_controlpoints(10000, self.origin, 15000);
- havocbot_goalrating_items(8000, self.origin, 8000);
- //havocbot_goalrating_enemyplayers(3000, self.origin, 2000);
- //havocbot_goalrating_waypoints(1, self.origin, 1000);
- navigation_goalrating_end();
- }
-}
-
//DM:
//go to best items
void havocbot_role_dm()
self.havocbot_role = havocbot_role_race;
}
-void havocbot_chooserole_dom()
-{
- self.havocbot_role = havocbot_role_dom;
-}
-
void havocbot_chooserole()
{
dprint("choosing a role...\n");
self.bot_strategytime = 0;
if (MUTATOR_CALLHOOK(HavocBot_ChooseRule))
return;
- else if (g_domination)
- havocbot_chooserole_dom();
else if (g_keyhunt)
havocbot_chooserole_kh();
else if (g_race || g_cts)
string parm;
string cmdstr;
- sp = strstrofs(cmdstr, " ", 0);
- if(sp < 0)
+ sp = strstrofs(cmdstring, " ", 0);
+ if(sp >= 0)
{
- parm = "";
- }
- else
- {
- parm = substring(cmdstr, sp + 1, -1);
- cmdstr = substring(cmdstr, 0, sp);
+ parm = substring(cmdstring, sp + 1, -1);
+ cmdstr = substring(cmdstring, 0, sp);
if(cmdstr == "sound")
- precache_sound(cmdstr);
+ {
+ // find the LAST word
+ for(;;)
+ {
+ sp = strstrofs(parm, " ", 0);
+ if(sp < 0)
+ break;
+ parm = substring(parm, sp + 1, -1);
+ }
+ precache_sound(parm);
+ }
}
}
string f;
f = bot_cmd.bot_cmd_parm_string;
+ float n = tokenizebyseparator(f, " ");
+
+ string sample = f;
+ float chan = CH_WEAPON_B;
+ float vol = VOL_BASE;
+ float atten = ATTN_MIN;
+
+ if(n >= 1)
+ sample = argv(n - 1);
+ if(n >= 2)
+ chan = stof(argv(0));
+ if(n >= 3)
+ vol = stof(argv(1));
+ if(n >= 4)
+ atten = stof(argv(2));
+
precache_sound(f);
- sound(self, CH_WEAPON_B, f, VOL_BASE, ATTN_MIN);
+ sound(self, chan, sample, vol, atten);
return CMD_STATUS_FINISHED;
}
float waypoint_load_links()
{
string filename, s;
- float file, tokens, c, found;
- entity wp_from, wp_to;
+ float file, tokens, c = 0, found;
+ entity wp_from = world, wp_to;
vector wp_to_pos, wp_from_pos;
filename = strcat("maps/", mapname);
filename = strcat(filename, ".waypoints.cache");
return FALSE;
}
- while (1)
+ while ((s = fgets(file)))
{
- s = fgets(file);
- if (!s)
- break;
-
tokens = tokenizebyseparator(s, "*");
if (tokens!=2)
wp_to_pos = stov(argv(1));
// Search "from" waypoint
- if(wp_from.origin!=wp_from_pos)
+ if(!wp_from || wp_from.origin!=wp_from_pos)
{
wp_from = findradius(wp_from_pos, 1);
found = FALSE;
void waypoint_load_links_hardwired()
{
string filename, s;
- float file, tokens, c, found;
- entity wp_from, wp_to;
+ float file, tokens, c = 0, found;
+ entity wp_from = world, wp_to;
vector wp_to_pos, wp_from_pos;
filename = strcat("maps/", mapname);
filename = strcat(filename, ".waypoints.hardwired");
return;
}
- for (;;)
+ while ((s = fgets(file)))
{
- s = fgets(file);
- if (!s)
- break;
-
if(substring(s, 0, 2)=="//")
continue;
wp_to_pos = stov(argv(1));
// Search "from" waypoint
- if(wp_from.origin!=wp_from_pos)
+ if(!wp_from || wp_from.origin!=wp_from_pos)
{
wp_from = findradius(wp_from_pos, 5);
found = FALSE;
for(i=0;i<32;++i)
{
// :S
+ link = world;
switch(i)
{
// for i in $(seq -w 0 31); do echo "case $i:link = w.wp$i; break;"; done;
- case 00:link = w.wp00; break;
- case 01:link = w.wp01; break;
- case 02:link = w.wp02; break;
- case 03:link = w.wp03; break;
- case 04:link = w.wp04; break;
- case 05:link = w.wp05; break;
- case 06:link = w.wp06; break;
- case 07:link = w.wp07; break;
- case 08:link = w.wp08; break;
- case 09:link = w.wp09; break;
+ case 0:link = w.wp00; break;
+ case 1:link = w.wp01; break;
+ case 2:link = w.wp02; break;
+ case 3:link = w.wp03; break;
+ case 4:link = w.wp04; break;
+ case 5:link = w.wp05; break;
+ case 6:link = w.wp06; break;
+ case 7:link = w.wp07; break;
+ case 8:link = w.wp08; break;
+ case 9:link = w.wp09; break;
case 10:link = w.wp10; break;
case 11:link = w.wp11; break;
case 12:link = w.wp12; break;
file = fopen(filename, FILE_READ);
if (file >= 0)
{
- while (1)
+ while ((s = fgets(file)))
{
- s = fgets(file);
- if (!s)
- break;
m1 = stov(s);
s = fgets(file);
- if (!s)
+ if not(s)
break;
m2 = stov(s);
s = fgets(file);
- if (!s)
+ if not(s)
break;
fl = stof(s);
waypoint_spawn(m1, m2, fl);
}
void Announce(string snd) {
- WriteByte(MSG_ALL, SVC_TEMPENTITY);
- WriteByte(MSG_ALL, TE_CSQC_ANNOUNCE);
- WriteString(MSG_ALL, snd);
+ WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
+ WriteByte(MSG_BROADCAST, TE_CSQC_ANNOUNCE);
+ WriteString(MSG_BROADCAST, snd);
}
void AnnounceTo(entity e, string snd) {
minstagib_stop_countdown(self);
Portal_ClearAll(self);
-
+
if(self.alivetime)
{
- PlayerStats_Event(self, PLAYERSTATS_ALIVETIME, time - self.alivetime);
+ if(!inWarmupStage)
+ PlayerStats_Event(self, PLAYERSTATS_ALIVETIME, time - self.alivetime);
self.alivetime = 0;
}
if(self.killcount != -666) {
if(g_lms) {
- if(PlayerScore_Add(self, SP_LMS_RANK, 0) > 0)
- bprint ("^4", self.netname, "^4 has no more lives left\n");
+ if(PlayerScore_Add(self, SP_LMS_RANK, 0) > 0 && self.lms_spectate_warning != 2)
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_LMS_NOLIVES, self.netname);
else
- bprint ("^4", self.netname, "^4 is spectating now\n"); // TODO turn this into a proper forfeit?
- } else
- bprint ("^4", self.netname, "^4 is spectating now\n");
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_LMS_FORFEIT, self.netname);
+ } else { Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_QUIT_SPECTATE, self.netname); }
if(self.just_joined == FALSE) {
LogTeamchange(self.playerid, -1, 4);
self.superweapons_finished = 0;
self.pushltime = 0;
self.istypefrag = 0;
- self.think = SUB_Null;
+ self.think = func_null;
self.nextthink = 0;
self.hook_time = 0;
self.runes = 0;
{
if(self.version_mismatch)
{
+ self.frags = FRAGS_SPECTATOR;
Spawnqueue_Unmark(self);
Spawnqueue_Remove(self);
}
else
{
+ self.frags = FRAGS_LMS_LOSER;
Spawnqueue_Insert(self);
}
}
else
self.frags = FRAGS_SPECTATOR;
}
+ else if((g_race && g_race_qualifying) || g_cts)
+ {
+ if(PlayerScore_Add(self, SP_RACE_FASTEST, 0))
+ self.frags = FRAGS_LMS_LOSER;
+ else
+ self.frags = FRAGS_SPECTATOR;
+ }
else
self.frags = FRAGS_SPECTATOR;
}
if(teamplay)
{
string s;
- s = Team_ColorNameLowerCase(self.team);
+ s = Team_ColorName_Lower(self.team);
if(s != "neutral")
{
defaultmodel = cvar_string(strcat("sv_defaultplayermodel_", s));
self.skin = stof(self.playerskin);
}
- if(chmdl || oldskin != self.skin)
- self.species = player_getspecies(); // model or skin has changed
+ if(chmdl || oldskin != self.skin) // model or skin has changed
+ {
+ self.species = player_getspecies(); // update species
+ UpdatePlayerSounds(); // update skin sounds
+ }
if(!teamplay)
if(strlen(autocvar_sv_defaultplayercolors))
spot = SelectSpawnPoint (FALSE);
if(!spot)
{
- centerprint(self, "Sorry, no spawnpoints available!\nHope your team can fix it...");
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_JOIN_NOSPAWNS);
return; // spawn failed
}
self.invincible_finished = 0;
self.pushltime = 0;
// players have no think function
- self.think = SUB_Null;
+ self.think = func_null;
self.nextthink = 0;
self.hook_time = 0;
self.dmg_team = 0;
if(g_assault) {
if(self.team == assault_attacker_team)
- centerprint(self, "You are attacking!");
+ Send_Notification(NOTIF_TEAM, self, MSG_CENTER, CENTER_ASSAULT_ATTACKING);
else
- centerprint(self, "You are defending!");
+ Send_Notification(NOTIF_TEAM, self, MSG_CENTER, CENTER_ASSAULT_DEFENDING);
}
target_voicescript_clear(self);
self.weaponname = "";
self.switchingweapon = 0;
- if(!self.alivetime)
- self.alivetime = time;
+ if(!inWarmupStage)
+ if(!self.alivetime)
+ self.alivetime = time;
antilag_clear(self);
if(g_ca)
self.caplayer = 0;
if(blockSpectators)
- sprint(self, strcat("^7You have to become a player within the next ", ftos(autocvar_g_maxplayers_spectator_blocktime), " seconds, otherwise you will be kicked, because spectators aren't allowed at this time!\n"));
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
PutObserverInServer();
}
else
self.killindicator.colormod = '0 0 0';
if(clienttype(self) == CLIENTTYPE_REAL)
if(self.killindicator.cnt > 0)
- Send_CSQC_Centerprint_Generic(self, CPID_TEAMCHANGE, "^1Suicide in %d seconds", 1, self.killindicator.cnt);
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_TEAMCHANGE_SUICIDE, self.killindicator.cnt);
}
else if(targetteam == -1) // auto
{
self.killindicator.colormod = '0 1 0';
if(clienttype(self) == CLIENTTYPE_REAL)
if(self.killindicator.cnt > 0)
- Send_CSQC_Centerprint_Generic(self, CPID_TEAMCHANGE, "Changing team in %d seconds", 1, self.killindicator.cnt);
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_TEAMCHANGE_AUTO, self.killindicator.cnt);
}
else if(targetteam == -2) // spectate
{
self.killindicator.colormod = '0.5 0.5 0.5';
if(clienttype(self) == CLIENTTYPE_REAL)
if(self.killindicator.cnt > 0)
- Send_CSQC_Centerprint_Generic(self, CPID_TEAMCHANGE, "Spectating in %d seconds", 1, self.killindicator.cnt);
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_TEAMCHANGE_SPECTATE, self.killindicator.cnt);
}
else
{
- self.killindicator.colormod = TeamColor(targetteam);
+ self.killindicator.colormod = Team_ColorRGB(targetteam);
if(clienttype(self) == CLIENTTYPE_REAL)
if(self.killindicator.cnt > 0)
- Send_CSQC_Centerprint_Generic(self, CPID_TEAMCHANGE, strcat("Changing to ", ColoredTeamName(targetteam), " in %d seconds"), 1, self.killindicator.cnt);
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, APP_TEAM_NUM_4(targetteam, CENTER_TEAMCHANGE_), self.killindicator.cnt);
}
}
stuffcmd(e, "cl_cmd settemp cl_movecliptokeyboard 2\n");
if(autocvar_g_antilag == 3) // client side hitscan
stuffcmd(e, "cl_cmd settemp cl_prydoncursor_notrace 0\n");
- if(sv_gentle)
+ if(autocvar_sv_gentle)
stuffcmd(e, "cl_cmd settemp cl_gentle 1\n");
/*
* we no longer need to stuff this. Remove this comment block if you feel
Called when a client connects to the server
=============
*/
-string ColoredTeamName(float t);
void DecodeLevelParms (void);
//void dom_player_join_team(entity pl);
void set_dom_state(entity e);
DecodeLevelParms();
#ifdef WATERMARK
- sprint(self, strcat("^4SVQC Build information: ^1", WATERMARK(), "\n"));
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_WATERMARK, WATERMARK);
#endif
self.classname = "player_joining";
race_PreSpawnObserver();
- //if(g_domination)
- // dom_player_join_team(self);
-
// identify the right forced team
if(autocvar_g_campaign)
{
{
switch(autocvar_g_campaign_forceteam)
{
- case 1: self.team_forced = COLOR_TEAM1; break;
- case 2: self.team_forced = COLOR_TEAM2; break;
- case 3: self.team_forced = COLOR_TEAM3; break;
- case 4: self.team_forced = COLOR_TEAM4; break;
+ case 1: self.team_forced = NUM_TEAM_1; break;
+ case 2: self.team_forced = NUM_TEAM_2; break;
+ case 3: self.team_forced = NUM_TEAM_3; break;
+ case 4: self.team_forced = NUM_TEAM_4; break;
default: self.team_forced = 0;
}
}
}
else if(PlayerInIDList(self, autocvar_g_forced_team_red))
- self.team_forced = COLOR_TEAM1;
+ self.team_forced = NUM_TEAM_1;
else if(PlayerInIDList(self, autocvar_g_forced_team_blue))
- self.team_forced = COLOR_TEAM2;
+ self.team_forced = NUM_TEAM_2;
else if(PlayerInIDList(self, autocvar_g_forced_team_yellow))
- self.team_forced = COLOR_TEAM3;
+ self.team_forced = NUM_TEAM_3;
else if(PlayerInIDList(self, autocvar_g_forced_team_pink))
- self.team_forced = COLOR_TEAM4;
+ self.team_forced = NUM_TEAM_4;
else if(autocvar_g_forced_team_otherwise == "red")
- self.team_forced = COLOR_TEAM1;
+ self.team_forced = NUM_TEAM_1;
else if(autocvar_g_forced_team_otherwise == "blue")
- self.team_forced = COLOR_TEAM2;
+ self.team_forced = NUM_TEAM_2;
else if(autocvar_g_forced_team_otherwise == "yellow")
- self.team_forced = COLOR_TEAM3;
+ self.team_forced = NUM_TEAM_3;
else if(autocvar_g_forced_team_otherwise == "pink")
- self.team_forced = COLOR_TEAM4;
+ self.team_forced = NUM_TEAM_4;
else if(autocvar_g_forced_team_otherwise == "spectate")
self.team_forced = -1;
else if(autocvar_g_forced_team_otherwise == "spectator")
self.netname_previous = strzone(self.netname);
- bprint("^4", self.netname, "^4 connected");
-
- if(self.classname != "observer" && (g_domination || g_ctf))
- bprint(" and joined the ", ColoredTeamName(self.team));
-
- bprint("\n");
+ if((self.classname == STR_PLAYER && teamplay))
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_4(self, INFO_JOIN_CONNECT_TEAM_), self.netname);
+ else
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_JOIN_CONNECT, self.netname);
stuffcmd(self, strcat(clientstuff, "\n"));
stuffcmd(self, "cl_particles_reloadeffects\n"); // TODO do we still need this?
self.spectatortime = time;
if(blockSpectators)
{
- sprint(self, strcat("^7You have to become a player within the next ", ftos(autocvar_g_maxplayers_spectator_blocktime), " seconds, otherwise you will be kicked, because spectators aren't allowed at this time!\n"));
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
}
self.jointime = time;
if(!sv_foginterval && world.fog != "")
stuffcmd(self, strcat("\nfog ", world.fog, "\nr_fog_exp2 0\nr_drawfog 1\n"));
- SoundEntity_Attach(self);
-
if(autocvar_g_hitplots || strstrofs(strcat(" ", autocvar_g_hitplots_individuals, " "), strcat(" ", self.netaddress, " "), 0) >= 0)
{
self.hitplotfh = fopen(strcat("hits-", matchid, "-", self.netaddress, "-", ftos(self.playerid), ".plot"), FILE_WRITE);
else if(autocvar_sv_teamnagger && !(autocvar_bot_vs_human && (c3==-1 && c4==-1)) && !g_ca) // teamnagger is currently bad for ca
send_CSQC_teamnagger();
- if (g_domination)
- set_dom_state(self);
-
CheatInitClient();
if(!autocvar_g_campaign)
- Send_CSQC_Centerprint_Generic(self, CPID_MOTD, getwelcomemessage(), autocvar_welcome_message_time, 0);
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MOTD, getwelcomemessage());
CSQCMODEL_AUTOINIT();
if(autocvar_sv_eventlog)
GameLogEcho(strcat(":part:", ftos(self.playerid)));
- bprint ("^4",self.netname);
- bprint ("^4 disconnected\n");
-
- SoundEntity_Detach(self);
+
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_QUIT_DISCONNECT, self.netname);
DropAllRunes(self);
MUTATOR_CALLHOOK(ClientDisconnect);
olditems = self.items;
if((self.items & IT_USING_JETPACK) && !self.deadflag)
- {
- SoundEntity_StartSound(self, CH_TRIGGER_SINGLE, "misc/jetpack_fly.wav", VOL_BASE, autocvar_g_jetpack_attenuation);
self.modelflags |= MF_ROCKET;
- }
else
- {
- SoundEntity_StopSound(self, CH_TRIGGER_SINGLE);
self.modelflags &~= MF_ROCKET;
- }
self.effects &~= (EF_RED | EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT | EF_FLAME | EF_NODEPTHTEST);
self.alpha = default_player_alpha;
self.exteriorweaponentity.alpha = default_weapon_alpha;
self.items &~= IT_STRENGTH;
- sprint(self, "^3Invisibility has worn off\n");
+ //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERDOWN_INVISIBILITY, self.netname);
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_INVISIBILITY);
}
}
else
self.alpha = g_minstagib_invis_alpha;
self.exteriorweaponentity.alpha = g_minstagib_invis_alpha;
self.items |= IT_STRENGTH;
- sprint(self, "^3You are invisible\n");
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_INVISIBILITY, self.netname);
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_INVISIBILITY);
}
}
if (time > self.invincible_finished)
{
self.items = self.items - (self.items & IT_INVINCIBLE);
- sprint(self, "^3Speed has worn off\n");
+ //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERDOWN_SPEED, self.netname);
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_SPEED);
}
}
else
if (time < self.invincible_finished)
{
self.items = self.items | IT_INVINCIBLE;
- sprint(self, "^3You are on speed\n");
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_SPEED, self.netname);
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_SPEED);
}
}
}
if (time > self.strength_finished)
{
self.items = self.items - (self.items & IT_STRENGTH);
- sprint(self, "^3Strength has worn off\n");
+ //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERDOWN_STRENGTH, self.netname);
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_STRENGTH);
}
}
else
if (time < self.strength_finished)
{
self.items = self.items | IT_STRENGTH;
- sprint(self, "^3Strength infuses your weapons with devastating power\n");
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_STRENGTH, self.netname);
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_STRENGTH);
}
}
if (self.items & IT_INVINCIBLE)
if (time > self.invincible_finished)
{
self.items = self.items - (self.items & IT_INVINCIBLE);
- sprint(self, "^3Shield has worn off\n");
+ //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERDOWN_SHIELD, self.netname);
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_SHIELD);
}
}
else
if (time < self.invincible_finished)
{
self.items = self.items | IT_INVINCIBLE;
- sprint(self, "^3Shield surrounds you\n");
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_SHIELD, self.netname);
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_SHIELD);
}
}
if (self.items & IT_SUPERWEAPON)
{
self.superweapons_finished = 0;
self.items = self.items - (self.items & IT_SUPERWEAPON);
- sprint(self, "^3Superweapons have been lost\n");
+ //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_SUPERWEAPON_LOST, self.netname);
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_SUPERWEAPON_LOST);
}
else if (self.items & IT_UNLIMITED_SUPERWEAPONS)
{
{
self.items = self.items - (self.items & IT_SUPERWEAPON);
WEPSET_ANDNOT_EA(self, WEPBIT_SUPERWEAPONS);
- sprint(self, "^3Superweapons have broken down\n");
+ //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_SUPERWEAPON_BROKEN, self.netname);
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_SUPERWEAPON_BROKEN);
}
}
}
if (time < self.superweapons_finished || (self.items & IT_UNLIMITED_SUPERWEAPONS))
{
self.items = self.items | IT_SUPERWEAPON;
- sprint(self, "^3You now have a superweapon\n");
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_SUPERWEAPON_PICKUP, self.netname);
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_SUPERWEAPON_PICKUP);
}
else
{
self.dmg_inflictor = spectatee.dmg_inflictor;
self.v_angle = spectatee.v_angle;
self.angles = spectatee.v_angle;
+ self.stat_respawn_time = spectatee.stat_respawn_time;
if(!self.BUTTON_USE)
self.fixangle = TRUE;
setorigin(self, spectatee.origin);
}
}
-.float prevent_join_msgtime;
void LeaveSpectatorMode()
{
- if(nJoinAllowed(self)) {
- if(!teamplay || autocvar_g_campaign || autocvar_g_balance_teams || (self.wasplayer && autocvar_g_changeteam_banned) || self.team_forced > 0) {
+ if(nJoinAllowed(self))
+ {
+ if(!teamplay || autocvar_g_campaign || autocvar_g_balance_teams || (self.wasplayer && autocvar_g_changeteam_banned) || self.team_forced > 0)
+ {
self.classname = "player";
if(autocvar_g_campaign || autocvar_g_balance_teams)
- JoinBestTeam(self, FALSE, TRUE);
+ { JoinBestTeam(self, FALSE, TRUE); }
if(autocvar_g_campaign)
- campaign_bots_may_start = 1;
+ { campaign_bots_may_start = 1; }
+ else
+ { Kill_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER_CPID, CPID_MOTD); }
+ Kill_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER_CPID, CPID_PREVENT_JOIN);
+
PutClientInServer();
- if(self.classname == "player")
- bprint ("^4", self.netname, "^4 is playing now\n");
-
- if(!autocvar_g_campaign)
- if (time < self.jointime + autocvar_welcome_message_time)
- Send_CSQC_Centerprint_Generic_Expire(self, CPID_MOTD); // clear MOTD
-
- if (self.prevent_join_msgtime)
- {
- Send_CSQC_Centerprint_Generic_Expire(self, CPID_PREVENT_JOIN);
- self.prevent_join_msgtime = 0;
- }
-
- return;
- } else {
- if (g_ca && self.caplayer) {
- } // do nothing
- else
- stuffcmd(self,"menu_showteamselect\n");
- return;
+ if(IS_PLAYER(self)) { Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_JOIN_PLAY, self.netname); }
}
+ else if not(g_ca && self.caplayer) { stuffcmd(self, "menu_showteamselect\n"); }
}
- else {
- //player may not join because of g_maxplayers is set
- if (time - self.prevent_join_msgtime > 2)
- {
- Send_CSQC_Centerprint_Generic(self, CPID_PREVENT_JOIN, PREVENT_JOIN_TEXT, 0, 0);
- self.prevent_join_msgtime = time;
- }
+ else
+ {
+ // Player may not join because g_maxplayers is set
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER_CPID, CPID_PREVENT_JOIN);
}
}
void checkSpectatorBlock() {
if(self.classname == "spectator" || self.classname == "observer") {
if( time > (self.spectatortime + autocvar_g_maxplayers_spectator_blocktime) ) {
- sprint(self, "^7You were kicked from the server because you are spectator and spectators aren't allowed at the moment.\n");
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_QUIT_KICK_SPECTATING);
dropclient(self);
}
}
if (autocvar_g_campaign) {
if ((self.classname == "player" && self.BUTTON_INFO) || (self.classname != "player")) {
self.motd_actived_time = time;
- Send_CSQC_Centerprint_Generic(self, CPID_MOTD, campaign_message, -1, 0);
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MOTD, campaign_message);
}
} else {
if ((time - self.jointime > autocvar_welcome_message_time) && self.BUTTON_INFO) {
self.motd_actived_time = time;
- Send_CSQC_Centerprint_Generic(self, CPID_MOTD, getwelcomemessage(), -1, 0);
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MOTD, getwelcomemessage());
}
}
} else { // showing MOTD or campaign message
self.motd_actived_time = time;
else if ((time - self.motd_actived_time > 2) && self.classname == "player") { // hide it some seconds after BUTTON_INFO has been released
self.motd_actived_time = 0;
- Send_CSQC_Centerprint_Generic_Expire(self, CPID_MOTD);
+ Kill_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER_CPID, CPID_MOTD);
}
} else {
if ((time - self.jointime) > autocvar_welcome_message_time) {
self.motd_actived_time = time;
else if (time - self.motd_actived_time > 2) { // hide it some seconds after BUTTON_INFO has been released
self.motd_actived_time = 0;
- Send_CSQC_Centerprint_Generic_Expire(self, CPID_MOTD);
+ Kill_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER_CPID, CPID_MOTD);
}
}
}
self.stat_allow_oldnexbeam = autocvar_g_allow_oldnexbeam;
self.stat_leadlimit = autocvar_leadlimit;
+ if(g_arena || (g_ca && !allowed_to_spawn))
+ self.stat_respawn_time = 0;
+ else
+ self.stat_respawn_time = self.respawn_time;
+
if(frametime)
{
// physics frames: update anticheat stuff
{
// notify release users if connecting to git
dprint("^1NOTE^7 to ", self.netname, "^7 - the server is running ^3Xonotic ", autocvar_g_xonoticversion, " (beta)^7, you have ^3Xonotic ", self.cvar_g_xonoticversion, "^1\n");
- sprint(self, strcat("\{1}^1NOTE: ^7the server is running ^3Xonotic ", autocvar_g_xonoticversion, " (beta)^7, you have ^3Xonotic ", self.cvar_g_xonoticversion, "^1\n"));
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_VERSION_BETA, autocvar_g_xonoticversion, self.cvar_g_xonoticversion);
}
else
{
{
// give users new version
dprint("^1NOTE^7 to ", self.netname, "^7 - ^3Xonotic ", autocvar_g_xonoticversion, "^7 is out, and you still have ^3Xonotic ", self.cvar_g_xonoticversion, "^1 - get the update from ^4http://www.xonotic.org/^1!\n");
- sprint(self, strcat("\{1}^1NOTE: ^3Xonotic ", autocvar_g_xonoticversion, "^7 is out, and you still have ^3Xonotic ", self.cvar_g_xonoticversion, "^1 - get the update from ^4http://www.xonotic.org/^1!\n"));
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_VERSION_OUTDATED, autocvar_g_xonoticversion, self.cvar_g_xonoticversion);
}
else if(r > 0)
{
// notify users about old server version
print("^1NOTE^7 to ", self.netname, "^7 - the server is running ^3Xonotic ", autocvar_g_xonoticversion, "^7, you have ^3Xonotic ", self.cvar_g_xonoticversion, "^1\n");
- sprint(self, strcat("\{1}^1NOTE: ^7the server is running ^3Xonotic ", autocvar_g_xonoticversion, "^7, you have ^3Xonotic ", self.cvar_g_xonoticversion, "^1\n"));
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_VERSION_OLD, autocvar_g_xonoticversion, self.cvar_g_xonoticversion);
}
}
}
// GOD MODE info
if(!(self.flags & FL_GODMODE)) if(self.max_armorvalue)
{
- sprint(self, strcat("godmode saved you ", ftos(self.max_armorvalue), " units of damage, cheater!\n"));
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_GODMODE_OFF, self.max_armorvalue);
self.max_armorvalue = 0;
}
if(frametime)
{
-#ifndef NO_LEGACY_NETWORKING
- self.glowmod = colormapPaletteColor(self.clientcolors & 0x0F, TRUE) * 2;
-#endif
-
if(self.weapon == WEP_NEX && autocvar_g_balance_nex_charge)
{
self.weaponentity_glowmod_x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_animlimit);
}
ShowRespawnCountdown();
}
+
+ // if respawning, invert stat_respawn_time to indicate this, the client translates it
+ if(self.deadflag == DEAD_RESPAWNING && self.stat_respawn_time > 0)
+ self.stat_respawn_time *= -1;
+
return;
}
// FIXME from now on self.deadflag is always 0 (and self.health is never < 1)
//sprint(self, "distance: ", ftos(self.lms_traveled_distance), "\n");
if(self.lms_traveled_distance < autocvar_g_lms_campcheck_distance)
{
- centerprint(self, autocvar_g_lms_campcheck_message);
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_LMS_CAMPCHECK);
// FIXME KadaverJack: gibbing player here causes playermodel to bounce around, instead of eye.md3
// I wasn't able to find out WHY that happens, so I put a workaround in place that shall prevent players from being gibbed :(
Damage(self, self, self, bound(0, autocvar_g_lms_campcheck_damage, self.health + self.armorvalue * autocvar_g_balance_armor_blockpercent + 5), DEATH_CAMP, self.origin, '0 0 0');
self.prevorigin = self.origin;
- if (!self.vehicle)
- if (((self.BUTTON_CROUCH && !self.hook.state) || self.health <= g_bloodloss) && self.animstate_startframe != self.anim_melee_x && !self.freezetag_frozen) // prevent crouching if using melee attack
+ float do_crouch = self.BUTTON_CROUCH;
+ if(self.hook.state)
+ do_crouch = 0;
+ if(self.health <= g_bloodloss)
+ do_crouch = 1;
+ if(self.vehicle)
+ do_crouch = 0;
+ if(self.freezetag_frozen)
+ do_crouch = 0;
+ if(self.weapon == WEP_SHOTGUN && self.weaponentity.wframe == WFRAME_FIRE2 && time < self.weapon_nextthink)
+ do_crouch = 0;
+
+ if (do_crouch)
{
if (!self.crouch)
{
=============
*/
.float idlekick_lasttimeleft;
-.entity showheadshotbbox;
-void showheadshotbbox_think()
-{
- if(self.owner.showheadshotbbox != self)
- {
- remove(self);
- return;
- }
- self.nextthink = time;
- setorigin(self, self.owner.origin);
- setsize(self, GetHeadshotMins(self.owner), GetHeadshotMaxs(self.owner));
-}
void PlayerPostThink (void)
{
// Savage: Check for nameless players
{
if (time - self.parm_idlesince < 1) // instead of (time == self.parm_idlesince) to support sv_maxidle <= 10
{
- if(self.idlekick_lasttimeleft)
- {
- Send_CSQC_Centerprint_Generic_Expire(self, CPID_DISCONNECT_IDLING);
- self.idlekick_lasttimeleft = 0;
- }
+ if(self.idlekick_lasttimeleft) { self.idlekick_lasttimeleft = 0; }
}
else
{
if(timeleft == min(10, sv_maxidle - 1)) // - 1 to support sv_maxidle <= 10
{
if(!self.idlekick_lasttimeleft)
- Send_CSQC_Centerprint_Generic(self, CPID_DISCONNECT_IDLING, "^3Stop idling!\n^3Disconnecting in %d seconds...", 1, timeleft);
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_DISCONNECT_IDLING, timeleft);
}
if(timeleft <= 0)
{
- bprint("^3", self.netname, "^3 was kicked for idling.\n");
- AnnounceTo(self, "terminated");
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_QUIT_KICK_IDLING, self.netname);
dropclient(self);
return;
}
if (intermission_running)
return; // intermission or finale
GetPressedKeys();
- } else if (self.classname == "observer") {
- //do nothing
- } else if (self.classname == "spectator") {
- //do nothing
}
#ifdef TETRIS
if(self.waypointsprite_attachedforcarrier)
WaypointSprite_UpdateHealth(self.waypointsprite_attachedforcarrier, '1 0 0' * healtharmor_maxdamage(self.health, self.armorvalue, autocvar_g_balance_armor_blockpercent));
- if(self.classname == "player" && self.deadflag == DEAD_NO && autocvar_r_showbboxes)
- {
- if(!self.showheadshotbbox)
- {
- self.showheadshotbbox = spawn();
- self.showheadshotbbox.classname = "headshotbbox";
- self.showheadshotbbox.owner = self;
- self.showheadshotbbox.think = showheadshotbbox_think;
- self.showheadshotbbox.nextthink = time;
- self = self.showheadshotbbox;
- self.think();
- self = self.owner;
- }
- }
- else
- {
- if(self.showheadshotbbox)
- if(self.showheadshotbbox && !wasfreed(self.showheadshotbbox))
- remove(self.showheadshotbbox);
- }
-
playerdemo_write();
if((g_cts || g_race) && self.cvar_cl_allow_uidtracking == 1 && self.cvar_cl_allow_uid2name == 1)
{
- if(!self.stored_netname)
+ if not(self.stored_netname)
self.stored_netname = strzone(uid2name(self.crypto_idfp));
if(self.stored_netname != self.netname)
{
self.flags &~= FL_ONGROUND;
self.flags &~= FL_JUMPRELEASED;
- if (self.crouch)
- setanim(self, self.anim_duckjump, FALSE, TRUE, TRUE);
- else if (self.animstate_startframe != self.anim_melee_x || (self.animstate_startframe == self.anim_melee_x && time - self.animstate_starttime >= 21/20)) // jump animation shouldn't override melee until we have animation blending (or until the anim finished, 21/20 = numframes/fps)
- setanim(self, self.anim_jump, FALSE, TRUE, TRUE);
+ animdecide_setaction(self, ANIMACTION_JUMP, TRUE);
if(g_jump_grunt)
PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND);
maxspd_mod = autocvar_sv_spectator_speed_multiplier;
if(!self.spectatorspeed)
self.spectatorspeed = maxspd_mod;
- if(self.impulse && self.impulse <= 19)
+ if(self.impulse && self.impulse <= 19 || self.impulse >= 200 && self.impulse <= 209 || self.impulse >= 220 && self.impulse <= 229)
{
if(self.lastclassname != "player")
{
- if(self.impulse == 10 || self.impulse == 15 || self.impulse == 18)
+ if(self.impulse == 10 || self.impulse == 15 || self.impulse == 18 || self.impulse >= 200 && self.impulse <= 209)
self.spectatorspeed = bound(1, self.spectatorspeed + 0.5, 5);
else if(self.impulse == 11)
self.spectatorspeed = maxspd_mod;
- else if(self.impulse == 12 || self.impulse == 16 || self.impulse == 19)
+ else if(self.impulse == 12 || self.impulse == 16 || self.impulse == 19 || self.impulse >= 220 && self.impulse <= 229)
self.spectatorspeed = bound(1, self.spectatorspeed - 0.5, 5);
else if(self.impulse >= 1 && self.impulse <= 9)
self.spectatorspeed = 1 + 0.5 * (self.impulse - 1);
url_fputs(fh, "#begin statsfile\n");
url_fputs(fh, strcat("#date ", strftime(TRUE, "%a %b %e %H:%M:%S %Z %Y"), "\n"));
#ifdef WATERMARK
- url_fputs(fh, strcat("#version ", WATERMARK(), "\n"));
+ url_fputs(fh, strcat("#version ", WATERMARK, "\n"));
#endif
url_fputs(fh, strcat("#config ", ftos(crc16(FALSE, cvar_purechanges)), "\n"));
url_fputs(fh, strcat("#cvar_purechanges ", ftos(cvar_purechanges_count), "\n"));
self.effects = oldself.effects;
self.glowmod = oldself.glowmod;
self.event_damage = oldself.event_damage;
- self.animstate_startframe = oldself.animstate_startframe;
- self.animstate_numframes = oldself.animstate_numframes;
- self.animstate_framerate = oldself.animstate_framerate;
- self.animstate_starttime = oldself.animstate_starttime;
- self.animstate_endtime = oldself.animstate_endtime;
- self.animstate_override = oldself.animstate_override;
- self.animstate_looping = oldself.animstate_looping;
+ self.anim_state = oldself.anim_state;
+ self.anim_time = oldself.anim_time;
+ self.anim_lower_action = oldself.anim_lower_action;
+ self.anim_lower_time = oldself.anim_lower_time;
+ self.anim_upper_action = oldself.anim_upper_action;
+ self.anim_upper_time = oldself.anim_upper_time;
+ self.anim_implicit_state = oldself.anim_implicit_state;
+ self.anim_implicit_time = oldself.anim_implicit_time;
+ self.anim_lower_implicit_action = oldself.anim_lower_implicit_action;
+ self.anim_lower_implicit_time = oldself.anim_lower_implicit_time;
+ self.anim_upper_implicit_action = oldself.anim_upper_implicit_action;
+ self.anim_upper_implicit_time = oldself.anim_upper_implicit_time;
self.dphitcontentsmask = oldself.dphitcontentsmask;
self.death_time = oldself.death_time;
- self.frame = oldself.frame;
self.pain_finished = oldself.pain_finished;
self.health = oldself.health;
self.armorvalue = oldself.armorvalue;
self.CopyBody_think = oldself.think;
self.nextthink = time;
self.think = CopyBody_Think;
+ // "bake" the current animation frame for clones (they don't get clientside animation)
+ animdecide_setframes(self, FALSE, frame, frame1time, frame2, frame2time);
self = oldself;
}
void player_setupanimsformodel()
{
- // defaults for legacy .zym models without animinfo files
- self.anim_die1 = animfixfps(self, '0 1 0.5'); // 2 seconds
- self.anim_die2 = animfixfps(self, '1 1 0.5'); // 2 seconds
- self.anim_draw = animfixfps(self, '2 1 3');
- // self.anim_duck = '3 1 100'; // This anim is broken, use slot 3 as a new free slot in the future ;)
- self.anim_duckwalk = animfixfps(self, '4 1 1');
- self.anim_duckjump = '5 1 100'; // NOTE: zym anims keep playing until changed, so this only has to start the anim, landing will end it
- self.anim_duckidle = animfixfps(self, '6 1 1');
- self.anim_idle = animfixfps(self, '7 1 1');
- self.anim_jump = '8 1 100'; // NOTE: zym anims keep playing until changed, so this only has to start the anim, landing will end it
- self.anim_pain1 = animfixfps(self, '9 1 2'); // 0.5 seconds
- self.anim_pain2 = animfixfps(self, '10 1 2'); // 0.5 seconds
- self.anim_shoot = animfixfps(self, '11 1 5'); // analyze models and set framerate
- self.anim_taunt = animfixfps(self, '12 1 0.33');
- self.anim_run = animfixfps(self, '13 1 1');
- self.anim_runbackwards = animfixfps(self, '14 1 1');
- self.anim_strafeleft = animfixfps(self, '15 1 1');
- self.anim_straferight = animfixfps(self, '16 1 1');
- //self.anim_dead1 = animfixfps(self, '17 1 1');
- //self.anim_dead2 = animfixfps(self, '18 1 1');
- self.anim_forwardright = animfixfps(self, '19 1 1');
- self.anim_forwardleft = animfixfps(self, '20 1 1');
- self.anim_backright = animfixfps(self, '21 1 1');
- self.anim_backleft = animfixfps(self, '22 1 1');
- self.anim_melee = animfixfps(self, '23 1 1');
- self.anim_duckwalkbackwards = animfixfps(self, '24 1 1');
- self.anim_duckwalkstrafeleft = animfixfps(self, '25 1 1');
- self.anim_duckwalkstraferight = animfixfps(self, '26 1 1');
- self.anim_duckwalkforwardright = animfixfps(self, '27 1 1');
- self.anim_duckwalkforwardleft = animfixfps(self, '28 1 1');
- self.anim_duckwalkbackright = animfixfps(self, '29 1 1');
- self.anim_duckwalkbackleft = animfixfps(self, '30 1 1');
- // TODO introspect models for finding right "fps" value (1/duration)
- // reset animstate now
- setanim(self, self.anim_idle, TRUE, FALSE, TRUE);
+ // load animation info
+ animdecide_init(self);
+ animdecide_setstate(self, 0, FALSE);
}
void player_anim (void)
{
- updateanim(self);
- if (self.weaponentity)
- updateanim(self.weaponentity);
-
- if (self.deadflag != DEAD_NO)
- return;
-
- if (!self.animstate_override)
- {
- if (self.freezetag_frozen)
- setanim(self, self.anim_idle, TRUE, FALSE, FALSE);
- else if (!(self.flags & FL_ONGROUND) || self.BUTTON_JUMP)
- {
- if (self.crouch)
- {
- if (self.animstate_startframe != self.anim_duckjump_x) // don't perform another trace if already playing the crouch jump anim
- {
- traceline(self.origin + '0 0 1' * PL_CROUCH_MIN_z, self.origin + '0 0 1' * (PL_CROUCH_MIN_z - autocvar_sv_player_jumpanim_minfall), TRUE, self);
- if(!trace_startsolid && trace_fraction == 1 || !(self.animstate_startframe == self.anim_duckwalk_x || self.animstate_startframe == self.anim_duckidle_x)) // don't get stuck on non-crouch anims
- {
- setanim(self, self.anim_duckjump, FALSE, TRUE, self.restart_jump);
- self.restart_jump = FALSE;
- }
- }
- }
- else
- {
- if (self.animstate_startframe != self.anim_jump_x) // don't perform another trace if already playing the jump anim
- {
- traceline(self.origin + '0 0 1' * PL_MIN_z, self.origin + '0 0 1' * (PL_MIN_z - autocvar_sv_player_jumpanim_minfall), TRUE, self);
- if(!trace_startsolid && trace_fraction == 1 || self.animstate_startframe == self.anim_idle_x || (self.animstate_startframe == self.anim_melee_x && time - self.animstate_starttime >= 21/20)) // don't get stuck on idle animation in midair, nor melee after it finished
- {
- setanim(self, self.anim_jump, FALSE, TRUE, self.restart_jump);
- self.restart_jump = FALSE;
- }
- }
- }
- }
- else if (self.crouch)
- {
- if (self.movement_x > 0 && self.movement_y == 0)
- setanim(self, self.anim_duckwalk, TRUE, FALSE, FALSE);
- else if (self.movement_x < 0 && self.movement_y == 0)
- setanim(self, self.anim_duckwalkbackwards, TRUE, FALSE, FALSE);
- else if (self.movement_x == 0 && self.movement_y > 0)
- setanim(self, self.anim_duckwalkstraferight, TRUE, FALSE, FALSE);
- else if (self.movement_x == 0 && self.movement_y < 0)
- setanim(self, self.anim_duckwalkstrafeleft, TRUE, FALSE, FALSE);
- else if (self.movement_x > 0 && self.movement_y > 0)
- setanim(self, self.anim_duckwalkforwardright, TRUE, FALSE, FALSE);
- else if (self.movement_x > 0 && self.movement_y < 0)
- setanim(self, self.anim_duckwalkforwardleft, TRUE, FALSE, FALSE);
- else if (self.movement_x < 0 && self.movement_y > 0)
- setanim(self, self.anim_duckwalkbackright, TRUE, FALSE, FALSE);
- else if (self.movement_x < 0 && self.movement_y < 0)
- setanim(self, self.anim_duckwalkbackleft, TRUE, FALSE, FALSE);
- else
- setanim(self, self.anim_duckidle, TRUE, FALSE, FALSE);
- }
- else if ((self.movement_x * self.movement_x + self.movement_y * self.movement_y) > 20)
- {
- if (self.movement_x > 0 && self.movement_y == 0)
- setanim(self, self.anim_run, TRUE, FALSE, FALSE);
- else if (self.movement_x < 0 && self.movement_y == 0)
- setanim(self, self.anim_runbackwards, TRUE, FALSE, FALSE);
- else if (self.movement_x == 0 && self.movement_y > 0)
- setanim(self, self.anim_straferight, TRUE, FALSE, FALSE);
- else if (self.movement_x == 0 && self.movement_y < 0)
- setanim(self, self.anim_strafeleft, TRUE, FALSE, FALSE);
- else if (self.movement_x > 0 && self.movement_y > 0)
- setanim(self, self.anim_forwardright, TRUE, FALSE, FALSE);
- else if (self.movement_x > 0 && self.movement_y < 0)
- setanim(self, self.anim_forwardleft, TRUE, FALSE, FALSE);
- else if (self.movement_x < 0 && self.movement_y > 0)
- setanim(self, self.anim_backright, TRUE, FALSE, FALSE);
- else if (self.movement_x < 0 && self.movement_y < 0)
- setanim(self, self.anim_backleft, TRUE, FALSE, FALSE);
- else
- setanim(self, self.anim_run, TRUE, FALSE, FALSE);
- }
+ float deadbits = (self.anim_state & (ANIMSTATE_DEAD1 | ANIMSTATE_DEAD2));
+ if(self.deadflag && !deadbits)
+ if(random() < 0.5)
+ deadbits = ANIMSTATE_DEAD1;
else
- setanim(self, self.anim_idle, TRUE, FALSE, FALSE);
- }
+ deadbits = ANIMSTATE_DEAD2;
+ float animbits = deadbits;
+ if(self.freezetag_frozen)
+ animbits |= ANIMSTATE_FROZEN;
+ if(self.crouch)
+ animbits |= ANIMSTATE_DUCK;
+ animdecide_setstate(self, animbits, FALSE);
+ animdecide_setimplicitstate(self, (self.flags & FL_ONGROUND));
if (self.weaponentity)
- if (!self.weaponentity.animstate_override)
- setanim(self.weaponentity, self.weaponentity.anim_idle, TRUE, FALSE, FALSE);
+ {
+ updateanim(self.weaponentity);
+ if (!self.weaponentity.animstate_override)
+ setanim(self.weaponentity, self.weaponentity.anim_idle, TRUE, FALSE, FALSE);
+ }
}
void SpawnThrownWeapon (vector org, float w)
take = damage;
}
+ if(attacker == self)
+ {
+ // don't reset pushltime for self damage as it may be an attempt to
+ // escape a lava pit or similar
+ //self.pushltime = 0;
+ self.istypefrag = 0;
+ }
+ else if(attacker.classname == "player")
+ {
+ self.pusher = attacker;
+ self.pushltime = time + autocvar_g_maxpushtime;
+ self.istypefrag = self.BUTTON_CHAT;
+ }
+ else if(time < self.pushltime)
+ {
+ attacker = self.pusher;
+ self.pushltime = max(self.pushltime, time + 0.6);
+ }
+ else
+ {
+ self.pushltime = 0;
+ self.istypefrag = 0;
+ }
+
frag_inflictor = inflictor;
frag_attacker = attacker;
frag_target = self;
{
self.pain_finished = time + 0.5; //Supajoe
- if(sv_gentle < 1) {
+ if(autocvar_sv_gentle < 1) {
if(self.classname != "body") // pain anim is BORKED on our ZYMs, FIXME remove this once we have good models
{
if (!self.animstate_override)
{
if (random() > 0.5)
- setanim(self, self.anim_pain1, FALSE, TRUE, TRUE);
+ animdecide_setaction(self, ANIMACTION_PAIN1, TRUE);
else
- setanim(self, self.anim_pain2, FALSE, TRUE, TRUE);
+ animdecide_setaction(self, ANIMACTION_PAIN2, TRUE);
}
}
self.dmg_take = self.dmg_take + take;//max(take - 10, 0);
self.dmg_inflictor = inflictor;
- if(attacker == self)
- {
- // don't reset pushltime for self damage as it may be an attempt to
- // escape a lava pit or similar
- //self.pushltime = 0;
- self.istypefrag = 0;
- }
- else if(attacker.classname == "player")
- {
- self.pusher = attacker;
- self.pushltime = time + autocvar_g_maxpushtime;
- self.istypefrag = self.BUTTON_CHAT;
- }
- else if(time < self.pushltime)
- {
- attacker = self.pusher;
- self.pushltime = max(self.pushltime, time + 0.6);
- }
- else
- {
- self.pushltime = 0;
- self.istypefrag = 0;
- }
+ if(g_ca && self != attacker && attacker.classname == "player")
+ PlayerScore_Add(attacker, SP_SCORE, (damage - excess) * autocvar_g_ca_damage2score_multiplier);
float abot, vbot, awep;
abot = (clienttype(attacker) == CLIENTTYPE_BOT);
if(valid_damage_for_weaponstats)
WeaponStats_LogKill(awep, abot, self.weapon, vbot);
- if(sv_gentle < 1) // TODO make a "gentle" version?
+ if(autocvar_sv_gentle < 1) // TODO make a "gentle" version?
if(sound_allowed(MSG_BROADCAST, attacker))
{
if(deathtype == DEATH_DROWN)
self.respawn_countdown = -1; // do not count down
self.death_time = time;
if (random() < 0.5)
- setanim(self, self.anim_die1, FALSE, TRUE, TRUE);
+ animdecide_setstate(self, self.anim_state | ANIMSTATE_DEAD1, TRUE);
else
- setanim(self, self.anim_die2, FALSE, TRUE, TRUE);
+ animdecide_setstate(self, self.anim_state | ANIMSTATE_DEAD2, TRUE);
if (self.maxs_z > 5)
{
self.maxs_z = 5;
// set up to fade out later
SUB_SetFade (self, time + 6 + random (), 1);
- if(sv_gentle > 0 || autocvar_ekg) {
+ if(autocvar_sv_gentle > 0 || autocvar_ekg) {
// remove corpse
PlayerCorpseDamage (inflictor, attacker, autocvar_sv_gibhealth+1.0, deathtype, hitloc, force);
}
if(sourcecmsgstr != "" && !privatesay)
centerprint(source, sourcecmsgstr);
}
- else if(privatesay) // private message, between 2 people only, not sent to server console
+ else if(privatesay) // private message, between 2 people only
{
sprint(source, sourcemsgstr);
sprint(privatesay, msgstr);
+ if not(autocvar_g_chat_tellprivacy) { dedicated_print(msgstr); } // send to server console too if "tellprivacy" is disabled
if(cmsgstr != "")
centerprint(privatesay, cmsgstr);
}
else if(teamsay > 0) // team message, only sent to team mates
{
sprint(source, sourcemsgstr);
- //print(msgstr); // send to server console too
+ dedicated_print(msgstr); // send to server console too
if(sourcecmsgstr != "")
centerprint(source, sourcecmsgstr);
FOR_EACH_REALPLAYER(head) if(head.team == source.team)
else if(teamsay < 0) // spectator message, only sent to spectators
{
sprint(source, sourcemsgstr);
- //print(msgstr); // send to server console too
+ dedicated_print(msgstr); // send to server console too
FOR_EACH_REALCLIENT(head) if(head.classname != "player")
if(head != source)
sprint(head, msgstr);
else if(sourcemsgstr != msgstr) // trimmed/server fixed message, sent to all players
{
sprint(source, sourcemsgstr);
- //print(msgstr); // send to server console too
+ dedicated_print(msgstr); // send to server console too
FOR_EACH_REALCLIENT(head)
if(head != source)
sprint(head, msgstr);
break;
if(!sv_taunt)
break;
- if(sv_gentle)
+ if(autocvar_sv_gentle)
break;
tauntrand = random();
msg_entity = self;
case VOICETYPE_TAUNT:
if(self.classname == "player")
if(self.deadflag == DEAD_NO)
- setanim(self, self.anim_taunt, FALSE, TRUE, TRUE);
+ animdecide_setaction(self, ANIMACTION_TAUNT, TRUE);
if(!sv_taunt)
break;
- if(sv_gentle)
+ if(autocvar_sv_gentle)
break;
msg_entity = self;
if (msg_entity.cvar_cl_voice_directional >= 1)
break;
if(!sv_taunt)
break;
- if(sv_gentle)
+ if(autocvar_sv_gentle)
break;
tauntrand = random();
FOR_EACH_REALCLIENT(msg_entity)
case VOICETYPE_TAUNT:
if(self.classname == "player")
if(self.deadflag == DEAD_NO)
- setanim(self, self.anim_taunt, FALSE, TRUE, TRUE);
+ animdecide_setaction(self, ANIMACTION_TAUNT, TRUE);
if(!sv_taunt)
break;
- if(sv_gentle)
+ if(autocvar_sv_gentle)
break;
FOR_EACH_REALCLIENT(msg_entity)
{
FakeGlobalSound(self.sample, CH_VOICE, voicetype);
}
-void MoveToTeam(entity client, float team_colour, float type, float show_message)
+void MoveToTeam(entity client, float team_colour, float type)
{
-// show_message
-// 0 (00) automove centerprint, admin message
-// 1 (01) automove centerprint, no admin message
-// 2 (10) no centerprint, admin message
-// 3 (11) no centerprint, no admin message
-
float lockteams_backup;
lockteams_backup = lockteams; // backup any team lock
TeamchangeFrags(client); // move the players frags
SetPlayerColors(client, team_colour - 1); // set the players colour
- Damage(client, client, client, 100000, ((show_message & 2) ? DEATH_QUIET : DEATH_AUTOTEAMCHANGE), client.origin, '0 0 0'); // kill the player
+ Damage(client, client, client, 100000, DEATH_AUTOTEAMCHANGE, client.origin, '0 0 0'); // kill the player
lockteams = lockteams_backup; // restore the team lock
LogTeamchange(client.playerid, client.team, type);
-
- if not(show_message & 1) // admin message
- sprint(client, strcat("\{1}\{13}^3", admin_name(), "^7: You have been moved to the ", Team_ColorNameLowerCase(team_colour), " team\n")); // send a chat message
-
- bprint(strcat(client.netname, " joined the ", ColoredTeamName(client.team), "\n"));
}
return (get_weaponinfo(wpn)).weapon_func(wrequest);
}
-string W_Name(float weaponid)
-{
- return (get_weaponinfo(weaponid)).message;
-}
-
-float W_AmmoItemCode(float wpn)
-{
- return (get_weaponinfo(wpn)).items & IT_AMMO;
-}
-
.float savenextthink;
void thrown_wep_think()
{
wep.savenextthink = wep.nextthink;
wep.nextthink = min(wep.nextthink, time + 0.5);
wep.pickup_anyway = TRUE; // these are ALWAYS pickable
+
return s;
}
}
W_SwitchWeapon_Force(self, w_getbestweapon(self));
a = W_ThrowNewWeapon(self, w, doreduce, self.origin + delta, velo);
- if not(a)
- return;
- if(a == "")
- sprint(self, strcat("You dropped the ^2", W_Name(w), "\n"));
- else
- sprint(self, strcat("You dropped the ^2", W_Name(w), " with ", a, "\n"));
+
+ if not(a) return;
+ Send_Notification(NOTIF_ONE, self, MSG_MULTI, ITEM_WEAPON_DROP, a, w);
}
// Bringed back weapon frame
setmodel(self, strcat("models/weapons/h_", name, ".iqm")); // precision set below
// preset some defaults that work great for renamed zym files (which don't need an animinfo)
- self.anim_fire1 = animfixfps(self, '0 1 0.01');
- self.anim_fire2 = animfixfps(self, '1 1 0.01');
- self.anim_idle = animfixfps(self, '2 1 0.01');
- self.anim_reload = animfixfps(self, '3 1 0.01');
+ self.anim_fire1 = animfixfps(self, '0 1 0.01', '0 0 0');
+ self.anim_fire2 = animfixfps(self, '1 1 0.01', '0 0 0');
+ self.anim_idle = animfixfps(self, '2 1 0.01', '0 0 0');
+ self.anim_reload = animfixfps(self, '3 1 0.01', '0 0 0');
// if we have a "weapon" tag, let's attach the v_ model to it ("invisible hand" style model)
// if we don't, this is a "real" animated model
void CL_ExteriorWeaponentity_Think()
{
float tag_found;
- vector ang;
self.nextthink = time;
if (self.owner.exteriorweaponentity != self)
{
setattachment(self, self.owner, "bip01 r hand");
}
self.effects = self.owner.effects;
- if(sv_pitch_min == sv_pitch_max)
- self.effects |= EF_LOWPRECISION;
- else
- self.effects &~= EF_LOWPRECISION;
+ self.effects |= EF_LOWPRECISION;
self.effects = self.effects & EFMASK_CHEAP; // eat performance
if(self.owner.alpha == default_player_alpha)
self.alpha = default_weapon_alpha;
else
self.alpha = 1;
- if (!intermission_running)
- {
- ang_x = bound(sv_pitch_min, self.owner.v_angle_x, sv_pitch_max);
- ang_y = 0;
- ang_z = 0;
-
- if(sv_pitch_fixyaw) // workaround for stupid player models that don't aim forward
- {
- ang_y = self.owner.v_angle_y;
- makevectors(ang);
- var vector v = v_forward;
- var float t = self.tag_entity.frame1time;
- var float f = self.tag_entity.frame;
- self.tag_entity.frame1time = time;
- self.tag_entity.frame = self.tag_entity.anim_idle_x;
- gettaginfo(self.tag_entity, self.tag_index);
- self.tag_entity.frame1time = t;
- self.tag_entity.frame = f;
- // untransform v according to this coordinate space
- vector w;
- w_x = v_forward * v;
- w_y = -v_right * v;
- w_z = v_up * v;
- self.angles = vectoangles(w);
- }
- else
- {
- ang_x = -/* don't ask */ang_x;
- self.angles = ang;
- }
-
- if(autocvar_g_loituma)
- {
- vector modangles;
- float t;
-
- t = time * autocvar_g_loituma;
-
- modangles_x = t * 360;
- modangles_y = 90;
- modangles_z = 0;
-
- self.angles =
- AnglesTransform_ToAngles(
- AnglesTransform_Multiply(
- AnglesTransform_FromAngles(self.angles),
- AnglesTransform_FromAngles(modangles)
- )
- );
- }
- }
-
self.glowmod = self.owner.weaponentity_glowmod;
self.colormap = self.owner.colormap;
if(clienttype(cl) == CLIENTTYPE_REAL)
{
play2(cl, "weapons/unavailable.wav");
- sprint(cl, strcat("You don't have any ammo for the ^2", W_Name(wpn), "\n"));
Send_WeaponComplain (cl, wpn, W_Name(wpn), 0);
}
return FALSE;
// Report Proper Weapon Status / Modified Weapon Ownership Message
if (WEPSET_CONTAINS_AW(weaponsInMap, wpn))
{
- sprint(cl, strcat("You do not have the ^2", W_Name(wpn), "\n") );
- Send_WeaponComplain (cl, wpn, W_Name(wpn), 1);
+ Send_WeaponComplain(cl, wpn, W_Name(wpn), 1);
if(autocvar_g_showweaponspawns)
{
else
{
Send_WeaponComplain (cl, wpn, W_Name(wpn), 2);
- sprint(cl, strcat("The ^2", W_Name(wpn), "^7 is ^1NOT AVAILABLE^7 in this map\n") );
}
play2(cl, "weapons/unavailable.wav");
W_SwitchWeapon_Force(pl, ww);
}
-string PrimaryOrSecondary(float secondary)
-{
- if(secondary)
- return "secondary";
- else
- return "primary";
-}
-
.float prevdryfire;
.float prevwarntime;
float weapon_prepareattack_checkammo(float secondary)
{
if(time - self.prevwarntime > 1)
{
- sprint(self, strcat("^2", W_Name(self.weapon), " ", PrimaryOrSecondary(secondary), "^7 is unable to fire, but its ^2", PrimaryOrSecondary(1 - secondary), "^7 can.\n"));
+ Send_Notification(
+ NOTIF_ONE,
+ self,
+ MSG_MULTI,
+ ITEM_WEAPON_PRIMORSEC,
+ self.weapon,
+ secondary,
+ (1 - secondary)
+ );
}
self.prevwarntime = time;
}
if (self.weaponentity)
{
self.weaponentity.wframe = fr;
+ a = '0 0 0';
if (fr == WFRAME_IDLE)
a = self.weaponentity.anim_idle;
else if (fr == WFRAME_FIRE1)
a = self.weaponentity.anim_fire1;
else if (fr == WFRAME_FIRE2)
a = self.weaponentity.anim_fire2;
- else if (fr == WFRAME_RELOAD)
+ else // if (fr == WFRAME_RELOAD)
a = self.weaponentity.anim_reload;
a_z *= g_weaponratefactor;
setanim(self.weaponentity, a, restartanim == FALSE, restartanim, restartanim);
self.weapon_think = func;
//dprint("next ", ftos(self.weapon_nextthink), "\n");
- // The shoot animation looks TERRIBLE without animation blending! Yay for moonwalking while shooting!
- //anim = self.anim_shoot;
- if (restartanim)
- if (t)
- if (!self.crouch) // shoot anim stands up, this looks bad
+ if((fr == WFRAME_FIRE1 || fr == WFRAME_FIRE2) && t)
{
- vector anim;
- if(self.weapon == WEP_SHOTGUN && self.BUTTON_ATCK2)
- {
- anim = self.anim_melee;
- anim_z = anim_y / (t + sys_frametime);
- setanim(self, anim, FALSE, TRUE, TRUE);
- }
- else if (self.animstate_startframe == self.anim_idle_x) // only allow shoot anim to override idle animation until we have animation blending
- {
- anim = self.anim_shoot;
- anim_z = anim_y / (t + sys_frametime);
- setanim(self, anim, FALSE, TRUE, TRUE);
- }
+ if(self.weapon == WEP_SHOTGUN && fr == WFRAME_FIRE2)
+ animdecide_setaction(self, ANIMACTION_MELEE, restartanim);
+ else
+ animdecide_setaction(self, ANIMACTION_SHOOT, restartanim);
+ }
+ else
+ {
+ if(self.anim_upper_action == ANIMACTION_SHOOT || self.anim_upper_action == ANIMACTION_MELEE)
+ self.anim_upper_action = 0;
}
}
vector W_CalculateProjectileSpread(vector forward, float spread)
{
float sigma;
- vector v1, v2;
+ vector v1 = '0 0 0', v2;
float dx, dy, r;
float sstyle;
spread *= g_weaponspreadfactor;
float Ban_Delete(float i);
// used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file
-void BanCommand_macro_write_aliases(float fh)
+void BanCommand_macro_write_aliases(float fh);
self.classname = "player";
PlayerScore_Clear(self);
- bprint ("^4", self.netname, "^4 is playing now\n");
+ Kill_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER_CPID, CPID_MOTD);
+ Kill_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER_CPID, CPID_PREVENT_JOIN);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_JOIN_PLAY, self.netname);
PutClientInServer();
}
else
{
//player may not join because of g_maxplayers is set
- centerprint(self, PREVENT_JOIN_TEXT);
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER_CPID, CPID_PREVENT_JOIN);
}
}
}
switch(argv(1))
{
- case "red": selection = COLOR_TEAM1; break;
- case "blue": selection = COLOR_TEAM2; break;
- case "yellow": selection = COLOR_TEAM3; break;
- case "pink": selection = COLOR_TEAM4; break;
+ case "red": selection = NUM_TEAM_1; break;
+ case "blue": selection = NUM_TEAM_2; break;
+ case "yellow": selection = NUM_TEAM_3; break;
+ case "pink": selection = NUM_TEAM_4; break;
case "auto": selection = (-1); break;
default: selection = 0; break;
{
if(self.lms_spectate_warning)
{
+ // for the forfeit message...
+ self.lms_spectate_warning = 2;
// mark player as spectator
PlayerScore_Add(self, SP_LMS_RANK, 666 - PlayerScore_Add(self, SP_LMS_RANK, 0));
}
// used by CommonCommand_timeout() and CommonCommand_timein() to handle game pausing and messaging and such.
void timeout_handler_reset()
{
- entity tmp_player;
-
timeout_caller = world;
timeout_time = 0;
timeout_leadtime = 0;
-
- FOR_EACH_REALPLAYER(tmp_player)
- Send_CSQC_Centerprint_Generic_Expire(tmp_player, CPID_TIMEOUT_COUNTDOWN);
remove(self);
}
{
if(timeout_time > 0) // countdown is still going
{
- FOR_EACH_REALPLAYER(tmp_player)
- Send_CSQC_Centerprint_Generic(tmp_player, CPID_TIMEOUT_COUNTDOWN, "Timeout ends in %d seconds!", 1, timeout_time);
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_TIMEOUT_ENDING, timeout_time);
if(timeout_time == autocvar_sv_timeout_resumetime) // play a warning sound when only <sv_timeout_resumetime> seconds are left
Announce("prepareforbattle");
{
if(timeout_leadtime > 0) // countdown is still going
{
- // centerprint the information to every player
- FOR_EACH_REALPLAYER(tmp_player)
- Send_CSQC_Centerprint_Generic(tmp_player, CPID_TIMEOUT_COUNTDOWN, "Timeout begins in %d seconds!", 1, timeout_leadtime);
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_TIMEOUT_BEGINNING, timeout_leadtime);
self.nextthink = time + 1; // think again in one second
timeout_leadtime -= 1; // decrease the time counter
{
if(caller) { caller.allowed_timeouts -= 1; }
- bprint(GetCallerName(caller), " ^7called a timeout", (caller ? strcat(" (", ftos(caller.allowed_timeouts), " timeout(s) left)") : string_null), "!\n"); // write a bprint who started the timeout (and how many they have left)
+ bprint(GetCallerName(caller), " ^7called a timeout", (caller ? strcat(" (", ftos(caller.allowed_timeouts), " timeout(s) left)") : ""), "!\n"); // write a bprint who started the timeout (and how many they have left)
timeout_status = TIMEOUT_LEADTIME;
timeout_caller = caller;
{
case CMD_REQUEST_COMMAND:
{
- float total_listed_players, tmp_hours, tmp_minutes, tmp_seconds, is_bot;
+ float total_listed_players, is_bot;
entity tmp_player;
float privacy = (caller && autocvar_sv_status_privacy);
string separator = strreplace("%", " ", strcat((argv(1) ? argv(1) : " "), "^7"));
string tmp_netaddress, tmp_crypto_idfp;
- print_to(caller, strcat("List of client information", (privacy ? " (some data is hidden for privacy)" : string_null), ":"));
+ print_to(caller, strcat("List of client information", (privacy ? " (some data is hidden for privacy)" : ""), ":"));
print_to(caller, sprintf(strreplace(" ", separator, " %-4s %-20s %-5s %-3s %-9s %-16s %s "),
"ent", "nickname", "ping", "pl", "time", "ip", "crypto_id"));
tmp_netaddress = tmp_player.netaddress;
tmp_crypto_idfp = tmp_player.crypto_idfp;
}
-
- tmp_hours = tmp_minutes = tmp_seconds = 0;
-
- tmp_seconds = floor(time - tmp_player.jointime);
- tmp_minutes = floor(tmp_seconds / 60);
- tmp_hours = floor(tmp_minutes / 60);
-
- if(tmp_minutes) { tmp_seconds -= (tmp_minutes * 60); }
- if(tmp_hours) { tmp_minutes -= (tmp_hours * 60); }
print_to(caller, sprintf(strreplace(" ", separator, " #%-3d %-20.20s %-5d %-3d %-9s %-16s %s "),
num_for_edict(tmp_player),
tmp_player.netname,
tmp_player.ping,
tmp_player.ping_packetloss,
- sprintf("%02d:%02d:%02d", tmp_hours, tmp_minutes, tmp_seconds),
+ process_time(1, time - tmp_player.jointime),
tmp_netaddress,
tmp_crypto_idfp));
continue;
n = race_readName(map, i);
- p = race_placeName(i);
+ p = count_ordinal(i);
s = strcat(s, strpad(8, p), " ", strpad(-8, TIME_ENCODED_TOSTRING(t)), " ", n, "\n");
}
s = strcat(s, " ^7Total ^3|");
for(i = 1; i <= LADDER_CNT; ++i)
- { s = strcat(s, " ^7", race_placeName(i), " ^3|"); }
+ { s = strcat(s, " ^7", count_ordinal(i), " ^3|"); }
s = strcat(s, " ^7Speed awards ^3| ^7Name");
s = strcat(s, "\n^3----+--------");
if(argv(LADDER_CNT+1) == "") // total is 0, skip
continue;
- s = strcat(s, strpad(4, race_placeName(i+1)), "^3| ^7"); // pos
+ s = strcat(s, strpad(4, count_ordinal(i+1)), "^3| ^7"); // pos
s = strcat(s, strpad(7, argv(LADDER_CNT+1)), "^3| ^7"); // total
for(j = 1; j <= min(9, LADDER_CNT); ++j)
}
}
+void GameCommand_animbench(float request, float argc)
+{
+ switch(request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ entity tmp_entity;
+
+ if(argc >= 4)
+ {
+ tmp_entity = spawn();
+ if(argv(1) == "w")
+ setmodel(tmp_entity, (nextent(world)).weaponentity.model);
+ else
+ {
+ precache_model(argv(1));
+ setmodel(tmp_entity, argv(1));
+ }
+ float f1 = stof(argv(2));
+ float f2 = stof(argv(3));
+ float t0;
+ float t1 = 0;
+ float t2 = 0;
+ float n = 0;
+
+ while(t1 + t2 < 1)
+ {
+ tmp_entity.frame = f1;
+ t0 = gettime(GETTIME_HIRES);
+ getsurfacepoint(tmp_entity, 0, 0);
+ t1 += gettime(GETTIME_HIRES) - t0;
+ tmp_entity.frame = f2;
+ t0 = gettime(GETTIME_HIRES);
+ getsurfacepoint(tmp_entity, 0, 0);
+ t2 += gettime(GETTIME_HIRES) - t0;
+ n += 1;
+ }
+ print("model ", tmp_entity.model, " frame ", ftos(f1), " animtime ", ftos(n / t1), "/s\n");
+ print("model ", tmp_entity.model, " frame ", ftos(f2), " animtime ", ftos(n / t2), "/s\n");
+
+ remove(tmp_entity);
+ return;
+ }
+ }
+
+ default:
+ print("Incorrect parameters for ^2gettaginfo^7\n");
+ case CMD_REQUEST_USAGE:
+ {
+ print("\nUsage:^3 sv_cmd gettaginfo model frame index [command one] [command two]\n");
+ print("See also: ^2bbox, trace^7\n");
+ return;
+ }
+ }
+}
+
void GameCommand_gotomap(float request, float argc)
{
switch(request)
string targets = strreplace(",", " ", argv(1));
string original_targets = strreplace(" ", ", ", targets);
string destination = argv(2);
- string notify = argv(3);
string successful, t;
successful = string_null;
if(teamplay)
{
// set up
- float team_color;
+ float team_id;
float save = client.team_forced;
client.team_forced = 0;
// find the team to move the player to
- team_color = ColourToNumber(destination);
- if(team_color == client.team) // already on the destination team
+ team_id = Team_ColorToTeam(destination);
+ if(team_id == client.team) // already on the destination team
{
// keep the forcing undone
- print("Player ", ftos(GetFilteredNumber(t)), " (", client.netname, ") is already on the ", ColoredTeamName(client.team), (targets ? ", skipping to next player.\n" : ".\n"));
+ print("Player ", ftos(GetFilteredNumber(t)), " (", client.netname, ") is already on the ", Team_ColoredFullName(client.team), (targets ? "^7, skipping to next player.\n" : "^7.\n"));
continue;
}
- else if(team_color == 0) // auto team
+ else if(team_id == 0) // auto team
{
- team_color = NumberToTeamNumber(FindSmallestTeam(client, FALSE));
+ team_id = Team_NumberToTeam(FindSmallestTeam(client, FALSE));
}
else
{
client.team_forced = save;
// Check to see if the destination team is even available
- switch(team_color)
+ switch(team_id)
{
- case COLOR_TEAM1: if(c1 == -1) { print("Sorry, can't move player to red team if it doesn't exist.\n"); return; } break;
- case COLOR_TEAM2: if(c2 == -1) { print("Sorry, can't move player to blue team if it doesn't exist.\n"); return; } break;
- case COLOR_TEAM3: if(c3 == -1) { print("Sorry, can't move player to yellow team if it doesn't exist.\n"); return; } break;
- case COLOR_TEAM4: if(c4 == -1) { print("Sorry, can't move player to pink team if it doesn't exist.\n"); return; } break;
+ case NUM_TEAM_1: if(c1 == -1) { print("Sorry, can't move player to red team if it doesn't exist.\n"); return; } break;
+ case NUM_TEAM_2: if(c2 == -1) { print("Sorry, can't move player to blue team if it doesn't exist.\n"); return; } break;
+ case NUM_TEAM_3: if(c3 == -1) { print("Sorry, can't move player to yellow team if it doesn't exist.\n"); return; } break;
+ case NUM_TEAM_4: if(c4 == -1) { print("Sorry, can't move player to pink team if it doesn't exist.\n"); return; } break;
default: print("Sorry, can't move player here if team ", destination, " doesn't exist.\n"); return;
}
// If so, lets continue and finally move the player
client.team_forced = 0;
- MoveToTeam(client, team_color, 6, stof(notify));
+ MoveToTeam(client, team_id, 6);
successful = strcat(successful, (successful ? ", " : ""), client.netname);
- print("Player ", ftos(GetFilteredNumber(t)), " (", client.netname, ") has been moved to the ", ColoredTeamName(team_color), ".\n");
+ print("Player ", ftos(GetFilteredNumber(t)), " (", client.netname, ") has been moved to the ", Team_ColoredFullName(team_id), "^7.\n");
continue;
}
else
print("Incorrect parameters for ^2moveplayer^7\n");
case CMD_REQUEST_USAGE:
{
- print("\nUsage:^3 sv_cmd moveplayer clients destination [notify]\n");
+ print("\nUsage:^3 sv_cmd moveplayer clients destination\n");
print(" 'clients' is a list (separated by commas) of player entity ID's or nicknames\n");
print(" 'destination' is what to send the player to, be it team or spectating\n");
print(" Full list of destinations here: \"spec, spectator, red, blue, yellow, pink, auto.\"\n");
- print(" 'notify' is whether or not to send messages notifying of the move. Detail below.\n");
- print(" 0 (00) automove centerprint, admin message; 1 (01) automove centerprint, no admin message\n");
- print(" 2 (10) no centerprint, admin message; 3 (11) no centerprint, no admin message\n");
print("Examples: sv_cmd moveplayer 1,3,5 red 3\n");
print(" sv_cmd moveplayer 2 spec \n");
print("See also: ^2allspec, shuffleteams^7\n");
if(plr.classname == "spectator" || plr.classname == "observer")
{
plr.spectatortime = time;
- sprint(plr, strcat("^7You have to become a player within the next ", ftos(autocvar_g_maxplayers_spectator_blocktime), " seconds, otherwise you will be kicked, because spectators aren't allowed at this time!\n"));
+ Send_Notification(NOTIF_ONE_ONLY, plr, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
}
}
bprint(strcat("^7All spectators will be automatically kicked when not joining the game after ", ftos(autocvar_g_maxplayers_spectator_blocktime), " seconds!\n"));
x = (t_players / t_teams);
x = ((i == 1) ? ceil(x) : floor(x));
- team_color = NumberToTeamNumber(i);
+ team_color = Team_NumberToTeam(i);
// sort through the random list of players made earlier
for(z = 1; z <= maxclients; ++z)
self = edict_num(shuffleteams_players[z]);
if(self.team != team_color)
- MoveToTeam(self, team_color, 6, 0);
+ MoveToTeam(self, team_color, 6);
shuffleteams_players[z] = 0;
shuffleteams_teams[i] = shuffleteams_teams[i] + 1;
// This... is a fairly dangerous and powerful command... - It allows any arguments to be sent to a client via rcon.
// Because of this, it is disabled by default and must be enabled by the server owner when doing compilation. That way,
// we can be certain they understand the risks of it... So to enable, compile server with -DSTUFFTO_ENABLED argument.
-
+
#ifdef STUFFTO_ENABLED
+ #message "stuffto command enabled"
switch(request)
{
case CMD_REQUEST_COMMAND:
default:
case CMD_REQUEST_USAGE:
{
- print("\nUsage:^3 sv_cmd level\n");
+ print("\nUsage:^3 sv_cmd warp [level]\n");
print(" 'level' is the level to change campaign mode to.\n");
+ print(" if 'level' is not provided it will change to the next level.\n");
return;
}
}
SERVER_COMMAND("allready", GameCommand_allready(request), "Restart the server and reset the players") \
SERVER_COMMAND("allspec", GameCommand_allspec(request, arguments), "Force all players to spectate") \
SERVER_COMMAND("anticheat", GameCommand_anticheat(request, arguments), "Create an anticheat report for a client") \
+ SERVER_COMMAND("animbench", GameCommand_animbench(request, arguments), "Benchmark model animation (LAGS)") \
SERVER_COMMAND("bbox", GameCommand_bbox(request), "Print detailed information about world size") \
SERVER_COMMAND("bot_cmd", GameCommand_bot_cmd(request, arguments, command), "Control and send commands to bots") \
SERVER_COMMAND("cointoss", GameCommand_cointoss(request, arguments), "Flip a virtual coin and give random result") \
strcat("^2:^1", ftos(vote_reject_count)),
((mincount >= 0) ? strcat("^2 (^1", ftos(mincount), "^2 needed)") : "^2"),
strcat(", ^1", ftos(vote_abstain_count), "^2 didn't care"),
- strcat(", ^1", ftos(notvoters), strcat("^2 didn't ", ((mincount >= 0) ? string_null : "have to "), "vote\n"))));
+ strcat(", ^1", ftos(notvoters), strcat("^2 didn't ", ((mincount >= 0) ? "" : "have to "), "vote\n"))));
if(autocvar_sv_eventlog)
{
readyrestart_happened = 1;
game_starttime = time;
if(!g_ca && !g_arena) { game_starttime += RESTART_COUNTDOWN; }
-
+
+ // clear alivetime
+ FOR_EACH_CLIENT(tmp_player)
+ {
+ tmp_player.alivetime = 0;
+ PlayerStats_Event(tmp_player, PLAYERSTATS_ALIVETIME, -PlayerStats_Event(tmp_player, PLAYERSTATS_ALIVETIME, 0));
+ }
+
restart_mapalreadyrestarted = 0; // reset this var, needed when cvar sv_ready_restart_repeatable is in use
// disable the warmup global for the server
{
validated_map = MapInfo_FixName(validated_map);
- if(!validated_map)
+ if not(validated_map)
{
print_to(caller, "This map is not available on this server.");
return string_null;
vote_command = VoteCommand_extractcommand(vote_command, 2, argc);
if not(autocvar_sv_vote_call || !caller) { print_to(caller, "^1Vote calling is not allowed."); }
+ else if(!autocvar_sv_vote_gamestart && time < game_starttime) { print_to(caller, "^1Vote calling is not allowed before the match has started."); }
else if(vote_called) { print_to(caller, "^1There is already a vote called."); }
else if(!spectators_allowed && (caller && (caller.classname != "player"))) { print_to(caller, "^1Only players can call a vote."); }
else if(timeout_status) { print_to(caller, "^1You can not call a vote while a timeout is active."); }
float TE_LIGHTNING3 = 9;
float TE_LAVASPLASH = 10;
float TE_TELEPORT = 11;
+float TE_BEAM = 13; // grappling hook
float UPDATE_GENERAL = 0;
float UPDATE_STATIC = 1;
//float POWERUP_INVINCIBLE_TAKEDAMAGE = 0.2; // received damage multiplier for invincible powerup
-
-float TE_BEAM = 13; // grappling hook
-
-float COLOR_TEAM1 = 5; // red
-float COLOR_TEAM2 = 14; // blue
-float COLOR_TEAM3 = 13; // yellow
-float COLOR_TEAM4 = 10; // pink
-
float NUM_PLAYERSKINS_TEAMPLAY = 3;
float ASSAULT_VALUE_INACTIVE = 1000;
float g_jetpack;
float sv_clones;
-float sv_gentle;
float sv_foginterval;
entity activator;
float maxclients;
+// flag set on worldspawn so that the code knows if it is dedicated or not
+float server_is_dedicated;
+
// Fields
.void(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) event_damage;
.float animstate_override;
.float animstate_looping;
-// player animation data for this model
-// each vector is as follows:
-// _x = startframe
-// _y = numframes
-// _z = framerate
-.vector anim_die1; // player dies
-.vector anim_die2; // player dies differently
-.vector anim_draw; // player pulls out a weapon
-// .vector anim_duck; // player crouches (from idle to duckidle)
-.vector anim_duckwalk; // player walking while crouching
-.vector anim_duckjump; // player jumping from a crouch
-.vector anim_duckidle; // player idling while crouching
-.vector anim_idle; // player standing
-.vector anim_jump; // player jump
-.vector anim_pain1; // player flinches from pain
-.vector anim_pain2; // player flinches from pain, differently
-.vector anim_shoot; // player shoots
-.vector anim_taunt; // player taunts others (FIXME: no code references this)
-.vector anim_run; // player running forward
-.vector anim_runbackwards; // player running backward
-.vector anim_strafeleft; // player shuffling left quickly
-.vector anim_straferight; // player shuffling right quickly
-//.vector anim_dead1; // player dead (must be identical to last frame of die1)
-//.vector anim_dead2; // player dead (must be identical to last frame of die2)
-.vector anim_forwardright; // player running forward and right
-.vector anim_forwardleft; // player running forward and left
-.vector anim_backright; // player running backward and right
-.vector anim_backleft; // player running back and left
-.vector anim_melee; // player doing the melee action
-.vector anim_duck; // player doing the melee action
-.vector anim_duckwalkbackwards;
-.vector anim_duckwalkstrafeleft;
-.vector anim_duckwalkstraferight;
-.vector anim_duckwalkforwardright;
-.vector anim_duckwalkforwardleft;
-.vector anim_duckwalkbackright;
-.vector anim_duckwalkbackleft;
-
// weapon animation vectors:
.vector anim_fire1;
.vector anim_fire2;
void weapon_defaultspawnfunc(float wpn);
-string w_deathtypestring;
-
.vector dest1, dest2;
float gameover;
.entity flagcarried;
-.entity lastrocket;
-
.float playerid;
float playerid_last;
.float noalign; // if set to 1, the item or spawnpoint won't be dropped to the floor
.string cvar_g_xonoticversion;
.string cvar_cl_weaponpriority;
.string cvar_cl_weaponpriorities[10];
-#ifdef ALLOW_FORCEMODELS
-.float cvar_cl_forceplayermodels;
-.float cvar_cl_forceplayermodelsfromxonotic;
-float sv_clforceplayermodels;
-#endif
.float cvar_cl_gunalign;
.float cvar_cl_noantilag;
void FakeGlobalSound(string samplestring, float channel, float voicetype);
void VoiceMessage(string type, string message);
float GetPlayerSoundSampleField_notFound;
-.string GetVoiceMessageSampleField(string type)
+.string GetVoiceMessageSampleField(string type);
// autotaunt system
.float cvar_cl_autotaunt;
.float clip_load;
.float old_clip_load;
.float clip_size;
+
+.entity lastrocket;
.float minelayer_mines;
+.float nex_charge;
+.float nex_charge_rottime;
+.float nex_chargepool_ammo;
+.float hagar_load;
.float grab; // 0 = can't grab, 1 = owner can grab, 2 = owner and team mates can grab, 3 = anyone can grab
#define ACTIVE_BUSY 2
#define ACTIVE_TOGGLE 3
.float active;
-.float (float act_state) setactive;
+.void (float act_state) setactive;
.entity realowner;
.float item_armor_large_time;
.float item_jetpack_time;
.float item_superweapons_time;
-.float nex_charge;
-.float nex_charge_rottime;
-.float nex_chargepool_ammo;
-
-.float hagar_load;
-
float allowed_to_spawn; // boolean variable used by the clan arena code to determine if a player can spawn (after the round has ended)
-
float serverflags;
.float team_forced; // can be a team number to force a team, or 0 for default action, or -1 for forced spectator
.entity muzzle_flash;
.float misc_bulletcounter; // replaces uzi & hlac bullet counter.
+.float stat_respawn_time; // shows respawn time, and is negative when awaiting respawn
+
void PlayerUseKey();
typedef vector(entity player, entity spot, vector current) spawn_evalfunc_t;
+++ /dev/null
-
-/*
-Domination as a plugin for netquake mods
-by LordHavoc (lordhavoc@ghdigital.com)
-
-How to add domination points to a mod:
-1. Add this line to progs.src above world.qc:
-domination.qc
-2. Comment out all lines in ClientObituary in client.qc that begin with targ.frags or attacker.frags.
-3. Add this above spawnfunc_worldspawn in world.qc:
-void() dom_init;
-4. Add this line to the end of spawnfunc_worldspawn in world.qc:
-dom_init();
-
-Note: The only teams who can use dom control points are identified by spawnfunc_dom_team entities (if none exist these default to red and blue and use only quake models/sounds).
-*/
-
-#define DOMPOINTFRAGS frags
-
-.float enemy_playerid;
-.entity sprite;
-.float captime;
-
-// pps: points per second
-.float dom_total_pps;
-.float dom_pps_red;
-.float dom_pps_blue;
-.float dom_pps_yellow;
-.float dom_pps_pink;
-float total_pps;
-float pps_red;
-float pps_blue;
-float pps_yellow;
-float pps_pink;
-void set_dom_state(entity e)
-{
- e.dom_total_pps = total_pps;
- e.dom_pps_red = pps_red;
- e.dom_pps_blue = pps_blue;
- if(c3 >= 0)
- e.dom_pps_yellow = pps_yellow;
- if(c4 >= 0)
- e.dom_pps_pink = pps_pink;
-}
-
-void() dom_controlpoint_setup;
-
-void LogDom(string mode, float team_before, entity actor)
-{
- string s;
- if(!autocvar_sv_eventlog)
- return;
- s = strcat(":dom:", mode);
- s = strcat(s, ":", ftos(team_before));
- s = strcat(s, ":", ftos(actor.playerid));
- GameLogEcho(s);
-}
-
-void() dom_spawnteams;
-
-void dompoint_captured ()
-{
- entity head;
- float old_delay, old_team, real_team;
-
- // now that the delay has expired, switch to the latest team to lay claim to this point
- head = self.owner;
-
- real_team = self.cnt;
- self.cnt = -1;
-
- LogDom("taken", self.team, self.dmg_inflictor);
- self.dmg_inflictor = world;
-
- self.goalentity = head;
- self.model = head.mdl;
- self.modelindex = head.dmg;
- self.skin = head.skin;
-
- //bprint(head.message);
- //bprint("\n");
-
- //bprint(^3head.netname);
- //bprint(head.netname);
- //bprint(self.message);
- //bprint("\n");
-
- float points, wait_time;
- if (autocvar_g_domination_point_amt)
- points = autocvar_g_domination_point_amt;
- else
- points = self.frags;
- if (autocvar_g_domination_point_rate)
- wait_time = autocvar_g_domination_point_rate;
- else
- wait_time = self.wait;
-
- bprint("^3", head.netname, "^3", self.message);
- if (points != 1)
- bprint(" ^7(", ftos(points), " points every ", ftos(wait_time), " seconds)\n");
- else
- bprint(" ^7(", ftos(points), " point every ", ftos(wait_time), " seconds)\n");
-
- if(self.enemy.playerid == self.enemy_playerid)
- PlayerScore_Add(self.enemy, SP_DOM_TAKES, 1);
- else
- self.enemy = world;
-
- if (head.noise != "")
- if(self.enemy)
- sound(self.enemy, CH_TRIGGER, head.noise, VOL_BASE, ATTN_NORM);
- else
- sound(self, CH_TRIGGER, head.noise, VOL_BASE, ATTN_NORM);
- if (head.noise1 != "")
- play2all(head.noise1);
-
- //self.nextthink = time + autocvar_g_domination_point_rate;
- //self.think = dompointthink;
-
- self.delay = time + wait_time;
-
- // do trigger work
- old_delay = self.delay;
- old_team = self.team;
- self.team = real_team;
- self.delay = 0;
- activator = self;
- SUB_UseTargets ();
- self.delay = old_delay;
- self.team = old_team;
-
- switch(self.goalentity.team)
- {
- case COLOR_TEAM1:
- WaypointSprite_UpdateSprites(self.sprite, "dom-red", "", "");
- break;
- case COLOR_TEAM2:
- WaypointSprite_UpdateSprites(self.sprite, "dom-blue", "", "");
- break;
- case COLOR_TEAM3:
- WaypointSprite_UpdateSprites(self.sprite, "dom-yellow", "", "");
- break;
- case COLOR_TEAM4:
- WaypointSprite_UpdateSprites(self.sprite, "dom-pink", "", "");
- }
-
- total_pps = 0, pps_red = 0, pps_blue = 0, pps_yellow = 0, pps_pink = 0;
- for(head = world; (head = find(head, classname, "dom_controlpoint")) != world; )
- {
- if (autocvar_g_domination_point_amt)
- points = autocvar_g_domination_point_amt;
- else
- points = head.frags;
- if (autocvar_g_domination_point_rate)
- wait_time = autocvar_g_domination_point_rate;
- else
- wait_time = head.wait;
- switch(head.goalentity.team)
- {
- case COLOR_TEAM1:
- pps_red += points/wait_time;
- break;
- case COLOR_TEAM2:
- pps_blue += points/wait_time;
- break;
- case COLOR_TEAM3:
- pps_yellow += points/wait_time;
- break;
- case COLOR_TEAM4:
- pps_pink += points/wait_time;
- }
- total_pps += points/wait_time;
- }
-
- WaypointSprite_UpdateTeamRadar(self.sprite, RADARICON_DOMPOINT, colormapPaletteColor(self.goalentity.team - 1, 0));
- WaypointSprite_Ping(self.sprite);
-
- self.captime = time;
-
- FOR_EACH_REALCLIENT(head)
- set_dom_state(head);
-}
-
-void AnimateDomPoint()
-{
- if(self.pain_finished > time)
- return;
- self.pain_finished = time + self.t_width;
- if(self.nextthink > self.pain_finished)
- self.nextthink = self.pain_finished;
-
- self.frame = self.frame + 1;
- if(self.frame > self.t_length)
- self.frame = 0;
-}
-
-void dompointthink()
-{
- float fragamt;
-
- self.nextthink = time + 0.1;
-
- //self.frame = self.frame + 1;
- //if(self.frame > 119)
- // self.frame = 0;
- AnimateDomPoint();
-
- // give points
-
- if (gameover || self.delay > time || time < game_starttime) // game has ended, don't keep giving points
- return;
-
- if(autocvar_g_domination_point_rate)
- self.delay = time + autocvar_g_domination_point_rate;
- else
- self.delay = time + self.wait;
-
- // give credit to the team
- // NOTE: this defaults to 0
- if (self.goalentity.netname != "")
- {
- if(autocvar_g_domination_point_amt)
- fragamt = autocvar_g_domination_point_amt;
- else
- fragamt = self.DOMPOINTFRAGS;
- TeamScore_AddToTeam(self.goalentity.team, ST_SCORE, fragamt);
- TeamScore_AddToTeam(self.goalentity.team, ST_DOM_TICKS, fragamt);
-
- // give credit to the individual player, if he is still there
- if (self.enemy.playerid == self.enemy_playerid)
- {
- PlayerScore_Add(self.enemy, SP_SCORE, fragamt);
- PlayerScore_Add(self.enemy, SP_DOM_TICKS, fragamt);
- }
- else
- self.enemy = world;
- }
-}
-
-void dompointtouch()
-{
- entity head;
- if (other.classname != "player")
- return;
- if (other.health < 1)
- return;
-
- if(time < self.captime + 0.3)
- return;
-
- // only valid teams can claim it
- head = find(world, classname, "dom_team");
- while (head && head.team != other.team)
- head = find(head, classname, "dom_team");
- if (!head || head.netname == "" || head == self.goalentity)
- return;
-
- // delay capture
-
- self.team = self.goalentity.team; // this stores the PREVIOUS team!
-
- self.cnt = other.team;
- self.owner = head; // team to switch to after the delay
- self.dmg_inflictor = other;
-
- // self.state = 1;
- // self.delay = time + cvar("g_domination_point_capturetime");
- //self.nextthink = time + cvar("g_domination_point_capturetime");
- //self.think = dompoint_captured;
-
- // go to neutral team in the mean time
- head = find(world, classname, "dom_team");
- while (head && head.netname != "")
- head = find(head, classname, "dom_team");
- if(head == world)
- return;
-
- WaypointSprite_UpdateSprites(self.sprite, "dom-neut", "", "");
- WaypointSprite_UpdateTeamRadar(self.sprite, RADARICON_DOMPOINT, '0 1 1');
- WaypointSprite_Ping(self.sprite);
-
- self.goalentity = head;
- self.model = head.mdl;
- self.modelindex = head.dmg;
- self.skin = head.skin;
-
- self.enemy = other; // individual player scoring
- self.enemy_playerid = other.playerid;
- dompoint_captured();
-}
-
-/*QUAKED spawnfunc_dom_team (0 .5 .8) (-32 -32 -24) (32 32 32)
-Team declaration for Domination gameplay, this allows you to decide what team
-names and control point models are used in your map.
-
-Note: If you use spawnfunc_dom_team entities you must define at least 3 and only two
-can have netname set! The nameless team owns all control points at start.
-
-Keys:
-"netname"
- Name of the team (for example Red Team, Blue Team, Green Team, Yellow Team, Life, Death, etc)
-"cnt"
- Scoreboard color of the team (for example 4 is red and 13 is blue)
-"model"
- Model to use for control points owned by this team (for example
- "progs/b_g_key.mdl" is a gold keycard, and "progs/b_s_key.mdl" is a silver
- keycard)
-"skin"
- Skin of the model to use (for team skins on a single model)
-"noise"
- Sound to play when this team captures a point.
- (this is a localized sound, like a small alarm or other effect)
-"noise1"
- Narrator speech to play when this team captures a point.
- (this is a global sound, like "Red team has captured a control point")
-*/
-
-void spawnfunc_dom_team()
-{
- if(!g_domination || autocvar_g_domination_teams_override >= 2)
- {
- remove(self);
- return;
- }
- precache_model(self.model);
- if (self.noise != "")
- precache_sound(self.noise);
- if (self.noise1 != "")
- precache_sound(self.noise1);
- self.classname = "dom_team";
- setmodel(self, self.model); // precision not needed
- self.mdl = self.model;
- self.dmg = self.modelindex;
- self.model = "";
- self.modelindex = 0;
- // this would have to be changed if used in quakeworld
- if(self.cnt)
- self.team = self.cnt + 1; // WHY are these different anyway?
-}
-
-void dom_controlpoint_setup()
-{
- entity head;
- // find the spawnfunc_dom_team representing unclaimed points
- head = find(world, classname, "dom_team");
- while(head && head.netname != "")
- head = find(head, classname, "dom_team");
- if (!head)
- objerror("no spawnfunc_dom_team with netname \"\" found\n");
-
- // copy important properties from spawnfunc_dom_team entity
- self.goalentity = head;
- setmodel(self, head.mdl); // precision already set
- self.skin = head.skin;
-
- self.cnt = -1;
-
- if(!self.message)
- self.message = " has captured a control point";
-
- if(self.DOMPOINTFRAGS <= 0)
- self.DOMPOINTFRAGS = 1;
- if(self.wait <= 0)
- self.wait = 5;
-
- float points, waittime;
- if (autocvar_g_domination_point_amt)
- points = autocvar_g_domination_point_amt;
- else
- points = self.frags;
- if (autocvar_g_domination_point_rate)
- waittime = autocvar_g_domination_point_rate;
- else
- waittime = self.wait;
-
- total_pps += points/waittime;
-
- if(!self.t_width)
- self.t_width = 0.02; // frame animation rate
- if(!self.t_length)
- self.t_length = 239; // maximum frame
-
- self.think = dompointthink;
- self.nextthink = time;
- self.touch = dompointtouch;
- self.solid = SOLID_TRIGGER;
- self.flags = FL_ITEM;
- setsize(self, '-32 -32 -32', '32 32 32');
- setorigin(self, self.origin + '0 0 20');
- droptofloor();
-
- waypoint_spawnforitem(self);
- WaypointSprite_SpawnFixed("dom-neut", self.origin + '0 0 32', self, sprite, RADARICON_DOMPOINT, '0 1 1');
-}
-
-
-
-/*QUAKED spawnfunc_dom_controlpoint (0 .5 .8) (-16 -16 -24) (16 16 32)
-Control point for Domination gameplay.
-*/
-void spawnfunc_dom_controlpoint()
-{
- if(!g_domination)
- {
- remove(self);
- return;
- }
- self.think = dom_controlpoint_setup;
- self.nextthink = time + 0.1;
- self.reset = dom_controlpoint_setup;
-
- if(!self.scale)
- self.scale = 0.6;
-
- //if(!self.glow_size)
- // self.glow_size = cvar("g_domination_point_glow");
- self.effects = self.effects | EF_LOWPRECISION;
- if (autocvar_g_domination_point_fullbright)
- self.effects |= EF_FULLBRIGHT;
-}
-
-// code from here on is just to support maps that don't have control point and team entities
-void dom_spawnteam (string teamname, float teamcolor, string pointmodel, float pointskin, string capsound, string capnarration, string capmessage)
-{
- entity oldself;
- oldself = self;
- self = spawn();
- self.classname = "dom_team";
- self.netname = teamname;
- self.cnt = teamcolor;
- self.model = pointmodel;
- self.skin = pointskin;
- self.noise = capsound;
- self.noise1 = capnarration;
- self.message = capmessage;
-
- // this code is identical to spawnfunc_dom_team
- setmodel(self, self.model); // precision not needed
- self.mdl = self.model;
- self.dmg = self.modelindex;
- self.model = "";
- self.modelindex = 0;
- // this would have to be changed if used in quakeworld
- self.team = self.cnt + 1;
-
- //eprint(self);
- self = oldself;
-}
-
-void dom_spawnpoint(vector org)
-{
- entity oldself;
- oldself = self;
- self = spawn();
- self.classname = "dom_controlpoint";
- self.think = spawnfunc_dom_controlpoint;
- self.nextthink = time;
- setorigin(self, org);
- spawnfunc_dom_controlpoint();
- self = oldself;
-}
-
-// spawn some default teams if the map is not set up for domination
-void dom_spawnteams()
-{
- float numteams;
- if(autocvar_g_domination_teams_override < 2)
- numteams = autocvar_g_domination_default_teams;
- else
- numteams = autocvar_g_domination_teams_override;
- // LordHavoc: edit this if you want to change defaults
- dom_spawnteam("Red", COLOR_TEAM1-1, "models/domination/dom_red.md3", 0, "domination/claim.wav", "", "Red team has captured a control point");
- dom_spawnteam("Blue", COLOR_TEAM2-1, "models/domination/dom_blue.md3", 0, "domination/claim.wav", "", "Blue team has captured a control point");
- if(numteams > 2)
- dom_spawnteam("Yellow", COLOR_TEAM3-1, "models/domination/dom_yellow.md3", 0, "domination/claim.wav", "", "Yellow team has captured a control point");
- if(numteams > 3)
- dom_spawnteam("Pink", COLOR_TEAM4-1, "models/domination/dom_pink.md3", 0, "domination/claim.wav", "", "Pink team has captured a control point");
- dom_spawnteam("", 0, "models/domination/dom_unclaimed.md3", 0, "", "", "");
-}
-
-void dom_delayedinit()
-{
- entity head;
-
- // if no teams are found, spawn defaults, if custom teams are set, use them
- if (find(world, classname, "dom_team") == world || autocvar_g_domination_teams_override >= 2)
- dom_spawnteams();
- // if no control points are found, spawn defaults
- if (find(world, classname, "dom_controlpoint") == world)
- {
- // TODO in a few months (maybe 2011/08): change this into error() and remove this very poor dom point selection
- backtrace("This map contains no dom_controlpoint entities. A very poor dom point placement will be chosen. Please fix the map.");
-
- // if no supported map was found, make every deathmatch spawn a point
- head = find(world, classname, "info_player_deathmatch");
- while (head)
- {
- dom_spawnpoint(head.origin);
- head = find(head, classname, "info_player_deathmatch");
- }
- }
-
- ScoreRules_dom();
-}
-
-void dom_init()
-{
- // we have to precache default models/sounds even if they might not be
- // used because spawnfunc_worldspawn is executed before any other entities are read,
- // so we don't even know yet if this map is set up for domination...
- precache_model("models/domination/dom_red.md3");
- precache_model("models/domination/dom_blue.md3");
- precache_model("models/domination/dom_yellow.md3");
- precache_model("models/domination/dom_pink.md3");
- precache_model("models/domination/dom_unclaimed.md3");
- precache_sound("domination/claim.wav");
- InitializeEntity(world, dom_delayedinit, INITPRIO_GAMETYPE);
-
- addstat(STAT_DOM_TOTAL_PPS, AS_FLOAT, dom_total_pps);
- addstat(STAT_DOM_PPS_RED, AS_FLOAT, dom_pps_red);
- addstat(STAT_DOM_PPS_BLUE, AS_FLOAT, dom_pps_blue);
- if(c3 >= 0) addstat(STAT_DOM_PPS_YELLOW, AS_FLOAT, dom_pps_yellow);
- if(c4 >= 0) addstat(STAT_DOM_PPS_PINK, AS_FLOAT, dom_pps_pink);
-}
-
self.health = self.max_health;
self.takedamage = DAMAGE_NO;
self.bot_attack = FALSE;
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
self.state = 1;
func_breakable_colormod();
}
if(self.count == 0)
self.count = 1;
- if(!self.message)
+ if(self.message == "")
self.message = "got too close to an explosion";
- if(!self.message2)
+ if(self.message2 == "")
self.message2 = "was pushed into an explosion by";
if(!self.dmg_radius)
self.dmg_radius = 150;
float yoda;
float damage_goodhits;
float damage_gooddamage;
-float headshot;
-float damage_headshotbonus; // bonus multiplier for head shots, set to 0 after use
.float dmg_team;
.float teamkill_complain;
return 1;
}
-vector GetHeadshotMins(entity targ)
-{
- return '-0.5 0 0' * PL_HEAD_x + '0 -0.5 0' * PL_HEAD_y + '0 0 1' * (targ.maxs_z - PL_HEAD_z);
-}
-vector GetHeadshotMaxs(entity targ)
-{
- return '0.5 0 0' * PL_HEAD_x + '0 0.5 0' * PL_HEAD_y + '0 0 1' * targ.maxs_z;
-}
-
void UpdateFrags(entity player, float f)
{
PlayerTeamScore_AddScore(player, f);
UpdateFrags(attacker, f);
}
-string Obituary_ExtraFragInfo(entity player) // Extra fragmessage information
-{
- string health_output = string_null;
- string ping_output = string_null;
- string handicap_output = string_null;
- string output = string_null;
-
- if(autocvar_sv_fraginfo && ((autocvar_sv_fraginfo == 2) || inWarmupStage))
- {
- // health/armor of attacker (person who killed you)
- if(autocvar_sv_fraginfo_stats && (player.health >= 1))
- health_output = strcat("^7(Health ^1", ftos(rint(player.health)), "^7 / Armor ^2", ftos(rint(player.armorvalue)), "^7)");
-
- // ping display
- if(autocvar_sv_fraginfo_ping)
- ping_output = ((clienttype(player) == CLIENTTYPE_BOT) ? "^2Bot" : strcat("Ping ", ((player.ping >= 150) ? "^1" : "^2"), ftos(rint(player.ping)), "ms"));
-
- // handicap display
- if(autocvar_sv_fraginfo_handicap)
- {
- if(autocvar_sv_fraginfo_handicap == 2)
- handicap_output = strcat(output, strcat("Handicap ^2", ((player.cvar_cl_handicap <= 1) ? "Off" : ftos(rint(player.cvar_cl_handicap)))));
- else if(player.cvar_cl_handicap) // with _handicap 1, only show this if there actually is a handicap enabled.
- handicap_output = strcat("Handicap ^2", ftos(rint(player.cvar_cl_handicap)));
- }
-
- // format the string
- output = strcat(health_output, (health_output ? ((ping_output || handicap_output) ? " ^7(" : "") : ((ping_output || handicap_output) ? "^7(" : "")),
- ping_output, (handicap_output ? "^7 / " : ""),
- handicap_output, ((ping_output || handicap_output) ? "^7)" : ""));
-
- // add new line to the beginning if there is a message
- if(output) { output = strcat("\n", output); }
- }
-
- return output;
-}
-
string AppendItemcodes(string s, entity player)
{
float w;
s = strcat(":kill:", mode);
s = strcat(s, ":", ftos(killer.playerid));
s = strcat(s, ":", ftos(killed.playerid));
- s = strcat(s, ":type=", ftos(deathtype));
+ s = strcat(s, ":type=", Deathtype_Name(deathtype));
s = strcat(s, ":items=");
s = AppendItemcodes(s, killer);
if(killed != killer)
GameLogEcho(s);
}
-void Send_KillNotification (string s1, string s2, string s3, float msg, float type)
+void Obituary_SpecialDeath(
+ entity notif_target,
+ float murder,
+ float deathtype,
+ string s1, string s2, string s3,
+ float f1, float f2, float f3)
{
- WriteByte(MSG_ALL, SVC_TEMPENTITY);
- WriteByte(MSG_ALL, TE_CSQC_KILLNOTIFY);
- WriteString(MSG_ALL, s1);
- WriteString(MSG_ALL, s2);
- WriteString(MSG_ALL, s3);
- WriteShort(MSG_ALL, msg);
- WriteByte(MSG_ALL, type);
+ if(DEATH_ISSPECIAL(deathtype))
+ {
+ entity deathent = deathtypes[(deathtype - DT_FIRST) - 1];
+ if not(deathent) { backtrace("Obituary_SpecialDeath: Could not find deathtype entity!\n"); return; }
+
+ if(murder)
+ {
+ if(deathent.death_msgmurder)
+ {
+ Send_Notification_WOVA(
+ NOTIF_ONE,
+ notif_target,
+ MSG_MULTI,
+ deathent.death_msgmurder.nent_id,
+ s1, s2, s3, "",
+ f1, f2, f3, 0
+ );
+ Send_Notification_WOVA(
+ NOTIF_ALL_EXCEPT,
+ notif_target,
+ MSG_INFO,
+ deathent.death_msgmurder.nent_msginfo.nent_id,
+ s1, s2, s3, "",
+ f1, f2, f3, 0
+ );
+ }
+ }
+ else
+ {
+ if(deathent.death_msgself)
+ {
+ Send_Notification_WOVA(
+ NOTIF_ONE,
+ notif_target,
+ MSG_MULTI,
+ deathent.death_msgself.nent_id,
+ s1, s2, s3, "",
+ f1, f2, f3, 0
+ );
+ Send_Notification_WOVA(
+ NOTIF_ALL_EXCEPT,
+ notif_target,
+ MSG_INFO,
+ deathent.death_msgself.nent_msginfo.nent_id,
+ s1, s2, s3, "",
+ f1, f2, f3, 0
+ );
+ }
+ }
+ }
+ else { backtrace("Obituary_SpecialDeath called without a special deathtype?\n"); return; }
}
-// Function is used to send a generic centerprint whose content CSQC gets to decide (gentle version or not in the below cases)
-void Send_CSQC_KillCenterprint(entity e, string s1, string s2, float msg, float type)
+float w_deathtype;
+float Obituary_WeaponDeath(
+ entity notif_target,
+ float murder,
+ float deathtype,
+ string s1, string s2, string s3,
+ float f1, float f2)
{
- if (clienttype(e) == CLIENTTYPE_REAL)
+ float death_weapon = DEATH_WEAPONOF(deathtype);
+ if(death_weapon)
{
- msg_entity = e;
- WRITESPECTATABLE_MSG_ONE({
- WriteByte(MSG_ONE, SVC_TEMPENTITY);
- WriteByte(MSG_ONE, TE_CSQC_KILLCENTERPRINT);
- WriteString(MSG_ONE, s1);
- WriteString(MSG_ONE, s2);
- WriteShort(MSG_ONE, msg);
- WriteByte(MSG_ONE, type);
- });
+ w_deathtype = deathtype;
+ float death_message = weapon_action(death_weapon, ((murder) ? WR_KILLMESSAGE : WR_SUICIDEMESSAGE));
+ w_deathtype = FALSE;
+
+ if(death_message)
+ {
+ Send_Notification_WOVA(
+ NOTIF_ONE,
+ notif_target,
+ MSG_MULTI,
+ death_message,
+ s1, s2, s3, "",
+ f1, f2, 0, 0
+ );
+ Send_Notification_WOVA(
+ NOTIF_ALL_EXCEPT,
+ notif_target,
+ MSG_INFO,
+ msg_multi_notifs[death_message - 1].nent_msginfo.nent_id,
+ s1, s2, s3, "",
+ f1, f2, 0, 0
+ );
+ }
+ else
+ {
+ dprint(sprintf(
+ "Obituary_WeaponDeath(): ^1Deathtype ^7(%d)^1 has no notification for weapon %d!\n",
+ deathtype,
+ death_weapon
+ ));
+ }
+
+ return TRUE;
}
+ return FALSE;
}
-void Obituary (entity attacker, entity inflictor, entity targ, float deathtype)
+void Obituary(entity attacker, entity inflictor, entity targ, float deathtype)
{
- string s, a, msg;
- float w, type;
-
- if (targ.classname == "player")
+ // Sanity check
+ if not(IS_PLAYER(targ)) { backtrace("Obituary called on non-player?!\n"); return; }
+
+ // Declarations
+ float notif_firstblood = FALSE;
+ float kill_count_to_attacker, kill_count_to_target;
+
+ // Set final information for the death
+ targ.death_origin = targ.origin;
+ if(targ != attacker) { targ.killer_origin = attacker.origin; }
+ string deathlocation = (autocvar_notification_server_allows_location ? NearestLocation(targ.death_origin) : "");
+
+ #ifdef NOTIFICATIONS_DEBUG
+ dprint(
+ sprintf(
+ "Obituary(%s, %s, %s, %s = %d);\n",
+ attacker.netname,
+ inflictor.netname,
+ targ.netname,
+ Deathtype_Name(deathtype),
+ deathtype
+ )
+ );
+ #endif
+
+ // =======
+ // SUICIDE
+ // =======
+ if(targ == attacker)
{
- s = targ.netname;
- a = attacker.netname;
-
- if (targ == attacker) // suicides
+ if(DEATH_ISSPECIAL(deathtype))
{
- if (deathtype == DEATH_TEAMCHANGE || deathtype == DEATH_AUTOTEAMCHANGE)
- msg = ColoredTeamName(targ.team); // TODO: check if needed?
- else
- msg = "";
- if(!g_cts) // no "killed your own dumb self" message in CTS
- Send_CSQC_KillCenterprint(targ, msg, "", deathtype, MSG_SUICIDE);
-
- if(deathtype != DEATH_TEAMCHANGE && deathtype != DEATH_QUIET)
+ if(deathtype == DEATH_TEAMCHANGE || deathtype == DEATH_AUTOTEAMCHANGE)
{
- LogDeath("suicide", deathtype, targ, targ);
- GiveFrags(attacker, targ, -1, deathtype);
+ Obituary_SpecialDeath(targ, FALSE, deathtype, targ.netname, deathlocation, "", targ.team, 0, 0);
}
-
- if (targ.killcount > 2)
- msg = ftos(targ.killcount);
else
- msg = "";
- if(teamplay && deathtype == DEATH_MIRRORDAMAGE)
{
- if(attacker.team == COLOR_TEAM1)
- deathtype = KILL_TEAM_RED;
- else
- deathtype = KILL_TEAM_BLUE;
+ switch(deathtype)
+ {
+ case DEATH_MIRRORDAMAGE:
+ {
+ Obituary_SpecialDeath(targ, FALSE, deathtype, targ.netname, deathlocation, "", targ.killcount, 0, 0);
+ break;
+ }
+
+ default:
+ {
+ Obituary_SpecialDeath(targ, FALSE, deathtype, targ.netname, deathlocation, "", targ.killcount, 0, 0);
+ break;
+ }
+ }
}
-
- Send_KillNotification(s, msg, ftos(w), deathtype, MSG_SUICIDE);
}
- else if (attacker.classname == "player")
+ else if not(Obituary_WeaponDeath(targ, FALSE, deathtype, targ.netname, deathlocation, "", targ.killcount, 0))
{
- if(!IsDifferentTeam(attacker, targ))
- {
- if(attacker.team == COLOR_TEAM1)
- type = KILL_TEAM_RED;
- else
- type = KILL_TEAM_BLUE;
-
- GiveFrags(attacker, targ, -1, deathtype);
+ backtrace("SUICIDE: what the hell happened here?\n");
+ return;
+ }
+ LogDeath("suicide", deathtype, targ, targ);
+ GiveFrags(attacker, targ, -1, deathtype);
+ }
- Send_CSQC_KillCenterprint(attacker, s, "", type, MSG_KILL);
+ // ======
+ // MURDER
+ // ======
+ else if(IS_PLAYER(attacker))
+ {
+ if(!IsDifferentTeam(attacker, targ))
+ {
+ LogDeath("tk", deathtype, attacker, targ);
+ GiveFrags(attacker, targ, -1, deathtype);
- if (targ.killcount > 2)
- msg = ftos(targ.killcount);
- else
- msg = "";
+ attacker.killcount = 0;
+
+ Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_TEAMKILL_FRAG, targ.netname);
+ Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_TEAMKILL_FRAGGED, attacker.netname);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(targ.team, INFO_DEATH_TEAMKILL_), targ.netname, attacker.netname, targ.killcount);
- if (attacker.killcount > 2) {
- msg = ftos(attacker.killcount);
- type = KILL_TEAM_SPREE;
+ // In this case, the death message will ALWAYS be "foo was betrayed by bar"
+ // No need for specific death/weapon messages...
+ }
+ else
+ {
+ LogDeath("frag", deathtype, attacker, targ);
+ GiveFrags(attacker, targ, 1, deathtype);
+
+ attacker.taunt_soundtime = time + 1;
+ attacker.killcount = attacker.killcount + 1;
+
+ #define SPREE_ITEM(counta,countb,center,normal,gentle) \
+ case counta: \
+ { \
+ AnnounceTo(attacker, strcat(#countb, "kills")); \
+ PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_##counta, 1); \
+ break; \
}
- Send_KillNotification(a, s, msg, type, MSG_KILL);
-
- attacker.killcount = 0;
+ switch(attacker.killcount)
+ {
+ KILL_SPREE_LIST
+ default: break;
+ }
+ #undef SPREE_ITEM
- LogDeath("tk", deathtype, attacker, targ);
+ if(!checkrules_firstblood)
+ {
+ 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);
+
+ // tell spree_inf and spree_cen that this is a first-blood and first-victim event
+ kill_count_to_attacker = -1;
+ kill_count_to_target = -2;
}
else
{
- if (!checkrules_firstblood)
- {
- checkrules_firstblood = TRUE;
- Send_KillNotification(a, "", "", KILL_FIRST_BLOOD, MSG_KILL);
- // TODO: make these print a newline if they dont
- Send_CSQC_KillCenterprint(attacker, "", "", KILL_FIRST_BLOOD, MSG_KILL);
- Send_CSQC_KillCenterprint(targ, "", "", KILL_FIRST_VICTIM, MSG_KILL);
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD, 1);
- PlayerStats_Event(targ, PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM, 1);
- }
-
- if(targ.istypefrag) {
- Send_CSQC_KillCenterprint(attacker, s, Obituary_ExtraFragInfo(targ), KILL_TYPEFRAG, MSG_KILL);
- Send_CSQC_KillCenterprint(targ, a, Obituary_ExtraFragInfo(attacker), KILL_TYPEFRAGGED, MSG_KILL);
- } else {
- Send_CSQC_KillCenterprint(attacker, s, Obituary_ExtraFragInfo(targ), KILL_FRAG, MSG_KILL);
- Send_CSQC_KillCenterprint(targ, a, Obituary_ExtraFragInfo(attacker), KILL_FRAGGED, MSG_KILL);
- }
-
- attacker.taunt_soundtime = time + 1;
+ kill_count_to_attacker = attacker.killcount;
+ kill_count_to_target = 0;
+ }
- if (deathtype == DEATH_HURTTRIGGER && inflictor.message2 != "")
- msg = inflictor.message2;
- else if (deathtype == DEATH_CUSTOM)
- msg = deathmessage;
+ float verbose_allowed = (autocvar_notification_server_allows_frag_verbose && ((autocvar_notification_server_allows_frag_verbose == 2) || inWarmupStage));
+ if(targ.istypefrag)
+ {
+ if(attacker.FRAG_VERBOSE && verbose_allowed)
+ Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_MURDER_TYPEFRAG_VERBOSE, targ.netname, kill_count_to_attacker, (IS_BOT_CLIENT(targ) ? NO_MSG : targ.ping));
else
- msg = "";
-
- if(strstrofs(msg, "%", 0) < 0)
- msg = strcat("%s ", msg, " by %s");
+ Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_MURDER_TYPEFRAG, targ.netname, kill_count_to_attacker);
- Send_KillNotification(a, s, msg, deathtype, MSG_KILL);
+ if(targ.FRAG_VERBOSE && verbose_allowed)
+ Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_MURDER_TYPEFRAGGED_VERBOSE, attacker.netname, kill_count_to_target, attacker.health, attacker.armorvalue, (IS_BOT_CLIENT(attacker) ? NO_MSG : attacker.ping));
+ else
+ Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_MURDER_TYPEFRAGGED, attacker.netname, kill_count_to_target);
+ }
+ else
+ {
+ if(attacker.FRAG_VERBOSE && verbose_allowed)
+ Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_MURDER_FRAG_VERBOSE, targ.netname, kill_count_to_attacker, (IS_BOT_CLIENT(targ) ? NO_MSG : targ.ping));
+ else
+ Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_MURDER_FRAG, targ.netname, kill_count_to_attacker);
- GiveFrags(attacker, targ, 1, deathtype);
+ if(targ.FRAG_VERBOSE && verbose_allowed)
+ Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_MURDER_FRAGGED_VERBOSE, attacker.netname, kill_count_to_target, attacker.health, attacker.armorvalue, (IS_BOT_CLIENT(attacker) ? NO_MSG : attacker.ping));
+ else
+ Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_MURDER_FRAGGED, attacker.netname, kill_count_to_target);
+ }
- if (targ.killcount > 2) {
- Send_KillNotification(s, ftos(targ.killcount), a, KILL_END_SPREE, MSG_SPREE);
- }
+ if not(Obituary_WeaponDeath(targ, TRUE, deathtype, targ.netname, attacker.netname, deathlocation, targ.killcount, kill_count_to_attacker))
+ Obituary_SpecialDeath(targ, TRUE, deathtype, targ.netname, attacker.netname, deathlocation, targ.killcount, kill_count_to_attacker, 0);
+ }
+ }
- attacker.killcount = attacker.killcount + 1;
+ // =============
+ // ACCIDENT/TRAP
+ // =============
+ else
+ {
+ switch(deathtype)
+ {
+ // For now, we're just forcing HURTTRIGGER to behave as "DEATH_VOID" and giving it no special options...
+ // Later on you will only be able to make custom messages using DEATH_CUSTOM,
+ // and there will be a REAL DEATH_VOID implementation which mappers will use.
+ /*case DEATH_HURTTRIGGER:
+ {
+ s1 = targ.netname;
+ s2 = inflictor.message;
+ if(strstrofs(s2, "%", 0) < 0) { s2 = strcat("%s ", s2); }
+ break;
+ }*/
- if (attacker.killcount == 3)
- {
- Send_KillNotification(a, "", "", KILL_SPREE_3, MSG_SPREE);
- AnnounceTo(attacker, "03kills");
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_3, 1);
- }
- else if (attacker.killcount == 5)
- {
- Send_KillNotification(a, "", "", KILL_SPREE_5, MSG_SPREE);
- AnnounceTo(attacker, "05kills");
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_5, 1);
- }
- else if (attacker.killcount == 10)
- {
- Send_KillNotification(a, "", "", KILL_SPREE_10, MSG_SPREE);
- AnnounceTo(attacker, "10kills");
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_10, 1);
- }
- else if (attacker.killcount == 15)
- {
- Send_KillNotification(a, "", "", KILL_SPREE_15, MSG_SPREE);
- AnnounceTo(attacker, "15kills");
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_15, 1);
- }
- else if (attacker.killcount == 20)
- {
- Send_KillNotification(a, "", "", KILL_SPREE_20, MSG_SPREE);
- AnnounceTo(attacker, "20kills");
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_20, 1);
- }
- else if (attacker.killcount == 25)
- {
- Send_KillNotification(a, "", "", KILL_SPREE_25, MSG_SPREE);
- AnnounceTo(attacker, "25kills");
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_25, 1);
- }
- else if (attacker.killcount == 30)
- {
- Send_KillNotification(a, "", "", KILL_SPREE_30, MSG_SPREE);
- AnnounceTo(attacker, "30kills");
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_30, 1);
- }
- else if (attacker.killcount > 2) {
- Send_KillNotification(a, ftos(attacker.killcount), "", KILL_SPREE, MSG_SPREE);
- }
- LogDeath("frag", deathtype, attacker, targ);
+ case DEATH_CUSTOM:
+ {
+ Obituary_SpecialDeath(targ, FALSE, deathtype,
+ targ.netname,
+ ((strstrofs(deathmessage, "%", 0) < 0) ? strcat("%s ", deathmessage) : deathmessage),
+ deathlocation,
+ targ.killcount,
+ 0,
+ 0);
+ break;
}
- }
- else
- {
- Send_CSQC_KillCenterprint(targ, "", "", deathtype, MSG_KILL_ACTION);
- if (deathtype == DEATH_HURTTRIGGER && inflictor.message != "")
- msg = inflictor.message;
- else if (deathtype == DEATH_CUSTOM)
- msg = deathmessage;
- else
- msg = "";
- if(strstrofs(msg, "%", 0) < 0)
- msg = strcat("%s ", msg);
-
- GiveFrags(targ, targ, -1, deathtype);
- if(PlayerScore_Add(targ, SP_SCORE, 0) == -5) {
- AnnounceTo(targ, "botlike");
- PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_BOTLIKE, 1);
+
+ default:
+ {
+ Obituary_SpecialDeath(targ, FALSE, deathtype, targ.netname, deathlocation, "", targ.killcount, 0, 0);
+ break;
}
- Send_KillNotification(s, msg, "", deathtype, MSG_KILL_ACTION);
-
- if (targ.killcount > 2)
- Send_KillNotification(s, ftos(targ.killcount), "", 0, MSG_KILL_ACTION_SPREE);
-
- LogDeath("accident", deathtype, targ, targ);
}
- targ.death_origin = targ.origin;
- if(targ != attacker)
- targ.killer_origin = attacker.origin;
+ LogDeath("accident", deathtype, targ, targ);
+ GiveFrags(targ, targ, -1, deathtype);
- // FIXME: this should go in PutClientInServer
- if (targ.killcount)
- targ.killcount = 0;
+ if(PlayerScore_Add(targ, SP_SCORE, 0) == -5)
+ {
+ AnnounceTo(targ, "botlike");
+ PlayerStats_Event(attacker, PLAYERSTATS_ACHIEVEMENT_BOTLIKE, 1);
+ }
}
+
+ // reset target kill count
+ if(targ.killcount) { targ.killcount = 0; }
}
// these are updated by each Damage call for use in button triggering and such
{
float mirrordamage;
float mirrorforce;
- float teamdamage0;
+ float complainteamdamage = 0;
entity attacker_save;
mirrordamage = 0;
mirrorforce = 0;
}
}
- if(deathtype == DEATH_KILL || deathtype == DEATH_TEAMCHANGE || deathtype == DEATH_AUTOTEAMCHANGE || deathtype == DEATH_QUIET)
+ if(deathtype == DEATH_KILL || deathtype == DEATH_TEAMCHANGE || deathtype == DEATH_AUTOTEAMCHANGE)
{
// These are ALWAYS lethal
// No damage modification here
{
if(targ.classname == "player" && targ.deadflag == DEAD_NO)
{
- teamdamage0 = max(attacker.dmg_team, autocvar_g_teamdamage_threshold);
attacker.dmg_team = attacker.dmg_team + damage;
- if(attacker.dmg_team > teamdamage0 && !g_ca)
- mirrordamage = autocvar_g_mirrordamage * (attacker.dmg_team - teamdamage0);
+ complainteamdamage = attacker.dmg_team - autocvar_g_teamdamage_threshold;
+ if(complainteamdamage > 0 && !g_ca) // FIXME why is g_ca ruled out here? Why not just g_mirrordamage 0 on CA servers?
+ mirrordamage = autocvar_g_mirrordamage * complainteamdamage;
mirrorforce = autocvar_g_mirrordamage * vlen(force);
if(g_minstagib)
{
{
damage = 0;
mirrordamage = 0;
+ complainteamdamage = 0;
if (targ != attacker)
{
if ((targ.health >= 1) && (targ.classname == "player"))
{
damage *= g_weapondamagefactor;
mirrordamage *= g_weapondamagefactor;
+ complainteamdamage *= g_weapondamagefactor;
force = force * g_weaponforcefactor;
mirrorforce *= g_weaponforcefactor;
}
if(targ.takedamage == DAMAGE_AIM)
if(targ != attacker)
{
- if(damage_headshotbonus)
- {
- if(targ.classname == "player")
- {
- // HEAD SHOT:
- // find height of hit on player axis
- // if above view_ofs and below maxs, and also in the middle half of the bbox, it is head shot
- vector headmins, headmaxs, org;
- org = antilag_takebackorigin(targ, time - ANTILAG_LATENCY(attacker));
- headmins = org + GetHeadshotMins(targ);
- headmaxs = org + GetHeadshotMaxs(targ);
- if(trace_hits_box(railgun_start, railgun_end, headmins, headmaxs))
- {
- deathtype |= HITTYPE_HEADSHOT;
- }
- }
- else if(targ.classname == "turret_head")
- {
- deathtype |= HITTYPE_HEADSHOT;
- }
- if(deathtype & HITTYPE_HEADSHOT)
- if(damage_headshotbonus > 0)
- damage *= 1 + damage_headshotbonus;
- }
-
entity victim;
if((targ.vehicle_flags & VHF_ISVEHICLE) && targ.owner)
victim = targ.owner;
if(g_minstagib)
if(victim.items & IT_STRENGTH)
yoda = 1;
-
- if(deathtype & HITTYPE_HEADSHOT)
- headshot = 1;
}
- if(g_ca)
- PlayerScore_Add(attacker, SP_SCORE, damage * autocvar_g_ca_damage2score_multiplier);
}
}
else
{
attacker.typehitsound += 1;
}
- if(mirrordamage > 0)
+ if(complainteamdamage > 0)
if(time > attacker.teamkill_complain)
{
attacker.teamkill_complain = time + 5;
self.state = 1;
self.think = GrapplingHookThink;
self.nextthink = time;
- self.touch = SUB_Null;
+ self.touch = func_null;
self.velocity = '0 0 0';
self.movetype = MOVETYPE_NONE;
self.hook_length = -1;
setorigin (self, self.origin);
//self.pflags = PFLAGS_FULLDYNAMIC;
self.solid = SOLID_NOT;
- //self.blocked = SUB_Null;
+ //self.blocked = func_null;
//if (self.spawnflags & DNOSHADOW)
// self.pflags = self.pflags + PFLAGS_NOSHADOW;
//if (self.spawnflags & START_OFF)
-void SUB_Null() {}
-float SUB_True() { return 1; }
-float SUB_False() { return 0; }
+void SUB_NullThink(void) { }
void(vector destangle, float tspeed, void() func) SUB_CalcAngleMove;
void() SUB_CalcMoveDone;
//print(ftos(time), " -> ", ftos(e.frame), "\n");
}
-vector animfixfps(entity e, vector a)
-{
- // multi-frame anim: keep as-is
- if(a_y == 1)
- {
- float dur;
- dur = frameduration(e.modelindex, a_x);
- if(dur > 0)
- a_z = 1.0 / dur;
- }
- return a;
-}
-
/*
==================
SUB_Remove
controller.think1 = self.think;
// the thinking is now done by the controller
- self.think = SUB_Null;
+ self.think = SUB_NullThink; // for PushMove
self.nextthink = self.ltime + traveltime;
// invoke controller
#else
-FTEQCC_YOU_SUCK_THIS_IS_NOT_UNREFERENCED(autocvar_g_bastet);
+float TetrisPostFrame()
+{
+ if (autocvar_g_bastet)
+ {
+ cvar_set("g_bastet", "0");
+ print("The useless cvar has been toggled.\n");
+ }
+ return 0;
+}
#endif
if(clienttype(activator) == CLIENTTYPE_REAL)
{
centerprint (activator, self.message);
- if (!self.noise)
+ if (self.noise == "")
play2(activator, "misc/talk.wav");
}
}
else
{ // we can't just remove (self) here, because this is a touch function
// called wheil C code is looping through area links...
- self.touch = SUB_Null;
+ self.touch = func_null;
}
}
self.takedamage = DAMAGE_YES;
self.solid = SOLID_BBOX;
}
- self.think = SUB_Null;
+ self.think = func_null;
+ self.nextthink = 0;
self.team = self.team_saved;
}
void delay_reset()
{
- self.think = SUB_Null;
+ self.think = func_null;
+ self.nextthink = 0;
}
void spawnfunc_trigger_delay()
self.enemy = world; // I hate you all
if (!self.dmg)
self.dmg = 1000;
- if (!self.message)
+ if (self.message == "")
self.message = "was in the wrong place";
- if (!self.message2)
+ if (self.message2 == "")
self.message2 = "was thrown into a world of hurt by";
// self.message = "someone like %s always gets wrongplaced";
if(self.colormod == '0 0 0')
if(!self.alpha)
self.colormod = '1 0 0';
- if(!self.message)
+ if(self.message == "")
self.message = "saw the light";
- if (!self.message2)
+ if (self.message2 == "")
self.message2 = "was pushed into a laser by";
if(!self.scale)
self.scale = 1;
string GetMapname();
string GetGametype();
void GotoNextMap(float reinit);
-void ShuffleMaplist()
+void ShuffleMaplist();
float(float reinit) DoNextMapOverride;
void SetDefaultAlpha()
BADCVAR("gameversion");
BADPREFIX("gameversion_");
BADCVAR("sv_namechangetimer");
-#ifndef NO_LEGACY_NETWORKING
- BADCVAR("sv_use_csqc_players"); // transition
-#endif
// allowed changes to server admins (please sync this to server.cfg)
// vi commands:
// needs to be done so early because of the constants they create
CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
+ CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
+ CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
MapInfo_Enumerate();
MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
head = nextent(head);
}
+ server_is_dedicated = (stof(cvar_defstring("is_dedicated")) ? TRUE : FALSE);
+
// needs to be done so early because of the constants they create
CALL_ACCUMULATED_FUNCTION(RegisterWeapons);
CALL_ACCUMULATED_FUNCTION(RegisterGametypes);
+ CALL_ACCUMULATED_FUNCTION(RegisterNotifications);
+ CALL_ACCUMULATED_FUNCTION(RegisterDeathtypes);
ServerProgsDB = db_load(strcat("server.db", autocvar_sessionid));
WaypointSprite_Init();
- //if (g_domination)
- // dom_init();
-
GameLogInit(); // prepare everything
// NOTE for matchid:
// changing the logic generating it is okay. But:
addstat(STAT_MOVEVARS_MAXSPEED, AS_FLOAT, stat_sv_maxspeed);
addstat(STAT_MOVEVARS_AIRACCEL_QW, AS_FLOAT, stat_sv_airaccel_qw);
addstat(STAT_MOVEVARS_AIRSTRAFEACCEL_QW, AS_FLOAT, stat_sv_airstrafeaccel_qw);
-
+
// secrets
addstat(STAT_SECRETS_TOTAL, AS_FLOAT, stat_secrets_total);
addstat(STAT_SECRETS_FOUND, AS_FLOAT, stat_secrets_found);
-
+
+ // misc
+ addstat(STAT_RESPAWN_TIME, AS_FLOAT, stat_respawn_time);
+
next_pingtime = time + 5;
detect_maptype();
-
+
// set up information replies for clients and server to use
lsmaps_reply = "^7Maps available: ";
lsnewmaps_reply = "^7Maps without a record set: ";
for(i = 0, j = 0; i < MapInfo_count; ++i)
{
if(MapInfo_Get_ByID(i))
- if not(MapInfo_Map_flags & (MAPINFO_FLAG_HIDDEN | MAPINFO_FLAG_FORBIDDEN))
+ if not(MapInfo_Map_flags & MapInfo_ForbiddenFlags())
{
if(mod(i, 2))
col = "^2";
else
col = "^3";
-
+
++j;
-
+
lsmaps_reply = strcat(lsmaps_reply, col, MapInfo_Map_bspname, " ");
-
+
if(g_race && !stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, RACE_RECORD, "time"))))
lsnewmaps_reply = strcat(lsnewmaps_reply, col, MapInfo_Map_bspname, " ");
else if(g_cts && !stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, CTS_RECORD, "time"))))
lsnewmaps_reply = strcat(lsnewmaps_reply, col, MapInfo_Map_bspname, " ");
}
}
-
+
lsmaps_reply = strzone(strcat(lsmaps_reply, "\n"));
lsnewmaps_reply = strzone(strcat(((!g_race && !g_cts) ? "Need to be playing race or CTS for lsnewmaps to work." : lsnewmaps_reply), "\n"));
for(i = 0; i < 10; ++i)
{
- records_reply[i] = strzone(getrecords(i));
+ s = getrecords(i);
+ if (s)
+ records_reply[i] = strzone(s);
}
-
+
ladder_reply = strzone(getladder());
rankings_reply = strzone(getrankings());
modname = "MinstaGib";
// extra mutators that deserve to count as mod
MUTATOR_CALLHOOK(SetModname);
- // weird game types that deserve to count as mod
- if(g_cts)
- modname = "CTS";
+
// save it for later
modname = strzone(modname);
void IntermissionThink()
{
FixIntermissionClient(self);
-
+
float server_screenshot = (autocvar_sv_autoscreenshot && self.cvar_cl_autoscreenshot);
float client_screenshot = (self.cvar_cl_autoscreenshot == 2);
-
+
if( (server_screenshot || client_screenshot)
&& ((self.autoscreenshot > 0) && (time > self.autoscreenshot)) )
{
PlayerStats_Shutdown();
WeaponStats_Shutdown();
+ Kill_Notification(NOTIF_ALL, world, MSG_CENTER, 0); // kill all centerprints now
+
if(autocvar_sv_eventlog)
GameLogEcho(":gameover");
if(autocvar_g_campaign)
CampaignPreIntermission();
+ MUTATOR_CALLHOOK(MatchEnd);
+
localcmd("\nsv_hook_gameend\n");
}
tl = autocvar_timelimit;
tl += autocvar_timelimit_overtime;
cvar_set("timelimit", ftos(tl));
- string minutesPlural;
- if (autocvar_timelimit_overtime == 1)
- minutesPlural = " ^3minute";
- else
- minutesPlural = " ^3minutes";
-
- bcenterprint(
- strcat(
- "^3Now playing ^1OVERTIME^3!\n\n^3Added ^1",
- ftos(autocvar_timelimit_overtime),
- minutesPlural,
- " to the game!"
- )
- );
+
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_OVERTIME_TIME, autocvar_timelimit_overtime);
}
float GetWinningCode(float fraglimitreached, float equality)
{
if (head.health > 0)
{
- if (head.team == COLOR_TEAM1) t1 = 1;
- if (head.team == COLOR_TEAM2) t2 = 1;
- if (head.team == COLOR_TEAM3) t3 = 1;
- if (head.team == COLOR_TEAM4) t4 = 1;
+ 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");
}
{
// game over, only one team remains (or none)
ClearWinners();
- if (t1) SetWinners(team, COLOR_TEAM1);
- if (t2) SetWinners(team, COLOR_TEAM2);
- if (t3) SetWinners(team, COLOR_TEAM3);
- if (t4) SetWinners(team, COLOR_TEAM4);
+ 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;
}
status = WINNING_NO;
// as the timelimit has not yet passed just assume the defending team will win
- if(assault_attacker_team == COLOR_TEAM1)
+ if(assault_attacker_team == NUM_TEAM_1)
{
- SetWinners(team, COLOR_TEAM2);
+ SetWinners(team, NUM_TEAM_2);
}
else
{
- SetWinners(team, COLOR_TEAM1);
+ SetWinners(team, NUM_TEAM_1);
}
entity ent;
if(teamplay)
{
- team1_score = TeamScore_GetCompareValue(COLOR_TEAM1);
- team2_score = TeamScore_GetCompareValue(COLOR_TEAM2);
- team3_score = TeamScore_GetCompareValue(COLOR_TEAM3);
- team4_score = TeamScore_GetCompareValue(COLOR_TEAM4);
+ team1_score = TeamScore_GetCompareValue(NUM_TEAM_1);
+ team2_score = TeamScore_GetCompareValue(NUM_TEAM_2);
+ team3_score = TeamScore_GetCompareValue(NUM_TEAM_3);
+ team4_score = TeamScore_GetCompareValue(NUM_TEAM_4);
}
ClearWinners();
return WINNING_STARTSUDDENDEATHOVERTIME;
else
return WINNING_NEVER;
- return wc;
}
float WinningCondition_QualifyingThenRace(float limit)
FOR_EACH_PLAYER(head) if(head.deadflag == DEAD_NO)
{
- if(head.team == COLOR_TEAM1)
+ if(head.team == NUM_TEAM_1)
team1_score = 1;
- else if(head.team == COLOR_TEAM2)
+ else if(head.team == NUM_TEAM_2)
team2_score = 1;
- else if(head.team == COLOR_TEAM3)
+ else if(head.team == NUM_TEAM_3)
team3_score = 1;
- else if(head.team == COLOR_TEAM4)
+ else if(head.team == NUM_TEAM_4)
team4_score = 1;
}
for(head = world; (head = find(head, classname, "info_player_deathmatch")) != world; )
{
- if(head.team == COLOR_TEAM1)
+ if(head.team == NUM_TEAM_1)
team1_score = 1;
- else if(head.team == COLOR_TEAM2)
+ else if(head.team == NUM_TEAM_2)
team2_score = 1;
- else if(head.team == COLOR_TEAM3)
+ else if(head.team == NUM_TEAM_3)
team3_score = 1;
- else if(head.team == COLOR_TEAM4)
+ else if(head.team == NUM_TEAM_4)
team4_score = 1;
}
{
float t, i;
if(team1_score)
- t = COLOR_TEAM1;
+ t = NUM_TEAM_1;
else if(team2_score)
- t = COLOR_TEAM2;
+ t = NUM_TEAM_2;
else if(team3_score)
- t = COLOR_TEAM3;
+ t = NUM_TEAM_3;
else // if(team4_score)
- t = COLOR_TEAM4;
+ t = NUM_TEAM_4;
CheckAllowedTeams(world);
for(i = 0; i < MAX_TEAMSCORE; ++i)
{
- if(t != COLOR_TEAM1) if(c1 >= 0) TeamScore_AddToTeam(COLOR_TEAM1, i, -1000);
- if(t != COLOR_TEAM2) if(c2 >= 0) TeamScore_AddToTeam(COLOR_TEAM2, i, -1000);
- if(t != COLOR_TEAM3) if(c3 >= 0) TeamScore_AddToTeam(COLOR_TEAM3, i, -1000);
- if(t != COLOR_TEAM4) if(c4 >= 0) TeamScore_AddToTeam(COLOR_TEAM4, i, -1000);
+ if(t != NUM_TEAM_1) if(c1 >= 0) TeamScore_AddToTeam(NUM_TEAM_1, i, -1000);
+ if(t != NUM_TEAM_2) if(c2 >= 0) TeamScore_AddToTeam(NUM_TEAM_2, i, -1000);
+ if(t != NUM_TEAM_3) if(c3 >= 0) TeamScore_AddToTeam(NUM_TEAM_3, i, -1000);
+ if(t != NUM_TEAM_4) if(c4 >= 0) TeamScore_AddToTeam(NUM_TEAM_4, i, -1000);
}
AddWinners(team, t);
{
checkrules_suddendeathwarning = TRUE;
if(g_race && !g_race_qualifying)
- bcenterprint("^3Everyone, finish your lap! The race is over!");
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_RACE_FINISHLAP);
else
- bcenterprint("^3Now playing ^1OVERTIME^3!\n\n^3Keep fragging until we have a ^1winner^3!");
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_OVERTIME_FRAG);
}
}
else
if(mapvote_initialized)
return "Can't suggest - voting is already in progress!";
m = MapInfo_FixName(m);
- if(!m)
+ if not(m)
return "The map you suggested is not available on this server.";
if(!autocvar_g_maplist_votable_suggestions_override_mostrecent)
if(Map_IsRecent(m))
if(ban_idfp == s) return TRUE;
}
if(ipbanned)
- if(!autocvar_g_banned_list_idmode || !ban_idfp)
+ {
+ if(!autocvar_g_banned_list_idmode)
+ return TRUE;
+ if not(ban_idfp)
return TRUE;
+ }
return FALSE;
}
_netname = "FLUFFY PINK keycard";
_colormod = '1 1 1';
- if (!self.netname) {
+ if (self.netname == "") {
objerror("item_key doesn't have a default name for this key and a custom one was not specified!");
remove(self);
return;
}
// find default model
+#ifdef GMQCC
+ _model = string_null;
+#endif
if (self.itemkeys <= ITEM_KEY_BIT(2)) {
_model = "models/keys/key.md3";
} else if (self.itemkeys >= ITEM_KEY_BIT(3) && self.itemkeys <= ITEM_KEY_BIT(5)) {
_model = "models/keys/key.md3"; // FIXME: replace it by a keycard model!
- } else if (!self.model) {
+ } else if (self.model == "") {
objerror("item_key doesn't have a default model for this key and a custom one was not specified!");
remove(self);
return;
}
// set defailt netname
- if (!self.netname)
+ if (self.netname == "")
self.netname = _netname;
// set default colormod
self.colormod = _colormod;
// set default model
- if (!self.model)
+ if (self.model == "")
self.model = _model;
// set default pickup message
- if (!self.message)
+ if (self.message == "")
self.message = strzone(strcat("You've picked up the ", self.netname, "!"));
- if (!self.noise)
+ if (self.noise == "")
self.noise = "misc/itempickup.wav";
// save the name for later
}
// set unlocked message
- if (!self.message)
+ if (self.message == "")
self.message = "Unlocked!";
// set default unlock noise
- if (!self.noise) {
+ if (self.noise == "") {
if (self.sounds == 1)
self.noise = "misc/secret.wav";
else if (self.sounds == 2)
}
// set default use key sound
- if (!self.noise1)
+ if (self.noise1 == "")
self.noise1 = "misc/decreasevalue.wav";
// set closed sourd
- if (!self.noise2)
+ if (self.noise2 == "")
self.noise2 = "misc/talk.wav";
// delay between triggering message2 and trigger2
void() spawnfunc_info_player_deathmatch; // needed for the other spawnpoints
void() spawnpoint_use;
string GetMapname();
-string ColoredTeamName(float t);
string admin_name(void)
{
#define move_out_of_solid(e) WarpZoneLib_MoveOutOfSolid(e)
-
string STR_PLAYER = "player";
string STR_SPECTATOR = "spectator";
string STR_OBSERVER = "observer";
-#if 0
-#define FOR_EACH_CLIENT(v) for(v = world; (v = findflags(v, flags, FL_CLIENT)) != world; )
-#define FOR_EACH_REALCLIENT(v) FOR_EACH_CLIENT(v) if(clienttype(v) == CLIENTTYPE_REAL)
-#define FOR_EACH_PLAYER(v) for(v = world; (v = find(v, classname, STR_PLAYER)) != world; )
-#define FOR_EACH_REALPLAYER(v) FOR_EACH_PLAYER(v) if(clienttype(v) == CLIENTTYPE_REAL)
-#else
+#define IS_PLAYER(v) (v.classname == STR_PLAYER)
+#define IS_SPEC(v) (v.classname == STR_SPECTATOR)
+#define IS_OBSERVER(v) (v.classname == STR_OBSERVER)
+#define IS_CLIENT(v) (v.flags & FL_CLIENT)
+#define IS_BOT_CLIENT(v) (clienttype(v) == CLIENTTYPE_BOT)
+#define IS_REAL_CLIENT(v) (clienttype(v) == CLIENTTYPE_REAL)
+#define IS_NOT_A_CLIENT(v) (clienttype(v) == CLIENTTYPE_NOTACLIENT)
+
#define FOR_EACH_CLIENTSLOT(v) for(v = world; (v = nextent(v)) && (num_for_edict(v) <= maxclients); )
-#define FOR_EACH_CLIENT(v) FOR_EACH_CLIENTSLOT(v) if(v.flags & FL_CLIENT)
-#define FOR_EACH_REALCLIENT(v) FOR_EACH_CLIENT(v) if(clienttype(v) == CLIENTTYPE_REAL)
-#define FOR_EACH_PLAYER(v) FOR_EACH_CLIENT(v) if(v.classname == STR_PLAYER)
-#define FOR_EACH_SPEC(v) FOR_EACH_CLIENT(v) if(v.classname != STR_PLAYER)
-#define FOR_EACH_REALPLAYER(v) FOR_EACH_REALCLIENT(v) if(v.classname == STR_PLAYER)
-#endif
+#define FOR_EACH_CLIENT(v) FOR_EACH_CLIENTSLOT(v) if(IS_CLIENT(v))
+#define FOR_EACH_REALCLIENT(v) FOR_EACH_CLIENT(v) if(IS_REAL_CLIENT(v))
-#define CENTER_OR_VIEWOFS(ent) (ent.origin + ((ent.classname == STR_PLAYER) ? ent.view_ofs : ((ent.mins + ent.maxs) * 0.5)))
+#define FOR_EACH_PLAYER(v) FOR_EACH_CLIENT(v) if(IS_PLAYER(v))
+#define FOR_EACH_SPEC(v) FOR_EACH_CLIENT(v) if not(IS_PLAYER(v)) // Samual: shouldn't this be IS_SPEC(v)? and rather create a separate macro to include observers too
+#define FOR_EACH_REALPLAYER(v) FOR_EACH_REALCLIENT(v) if(IS_PLAYER(v))
+
+#define CENTER_OR_VIEWOFS(ent) (ent.origin + (IS_PLAYER(ent) ? ent.view_ofs : ((ent.mins + ent.maxs) * 0.5)))
// copies a string to a tempstring (so one can strunzone it)
string strcat1(string s) = #115; // FRIK_FILE
float logfile_open;
float logfile;
-void bcenterprint(string s)
-{
- // TODO replace by MSG_ALL (would show it to spectators too, though)?
- entity head;
- FOR_EACH_PLAYER(head)
- if (clienttype(head) == CLIENTTYPE_REAL)
- centerprint(head, s);
-}
-
void GameLogEcho(string s)
{
string fn;
else replacement = "batteries"; // ;)
} else if (escape == "x") {
replacement = cursor_ent.netname;
- if (!replacement || !cursor_ent)
+ if (replacement == "" || !cursor_ent)
replacement = "nothing";
} else if (escape == "s")
replacement = ftos(vlen(self.velocity - self.velocity_z * '0 0 1'));
get_cvars_f = f;
get_cvars_s = s;
+
MUTATOR_CALLHOOK(GetCvars);
+
+ Notification_GetCvars();
+
GetCvars_handleFloat(s, f, autoswitch, "cl_autoswitch");
GetCvars_handleFloat(s, f, cvar_cl_autoscreenshot, "cl_autoscreenshot");
GetCvars_handleString(s, f, cvar_g_xonoticversion, "g_xonoticversion");
self.cvar_cl_accuracy_data_share = boolean(self.cvar_cl_accuracy_data_share);
self.cvar_cl_accuracy_data_receive = boolean(self.cvar_cl_accuracy_data_receive);
-#ifdef ALLOW_FORCEMODELS
- GetCvars_handleFloat(s, f, cvar_cl_forceplayermodels, "cl_forceplayermodels");
- GetCvars_handleFloat(s, f, cvar_cl_forceplayermodelsfromxonotic, "cl_forceplayermodelsfromxonotic");
-#endif
GetCvars_handleFloatOnce(s, f, cvar_cl_gunalign, "cl_gunalign");
GetCvars_handleFloat(s, f, cvar_cl_allow_uid2name, "cl_allow_uid2name");
GetCvars_handleFloat(s, f, cvar_cl_allow_uidtracking, "cl_allow_uidtracking");
}
}
-void backtrace(string msg)
-{
- float dev, war;
- dev = autocvar_developer;
- war = autocvar_prvm_backtraceforwarnings;
- cvar_set("developer", "1");
- cvar_set("prvm_backtraceforwarnings", "1");
- print("\n");
- print("--- CUT HERE ---\nWARNING: ");
- print(msg);
- print("\n");
- remove(world); // isn't there any better way to cause a backtrace?
- print("\n--- CUT UNTIL HERE ---\n");
- cvar_set("developer", ftos(dev));
- cvar_set("prvm_backtraceforwarnings", ftos(war));
-}
-
-string Team_ColorCode(float teamid)
-{
- if (teamid == COLOR_TEAM1)
- return "^1";
- else if (teamid == COLOR_TEAM2)
- return "^4";
- else if (teamid == COLOR_TEAM3)
- return "^3";
- else if (teamid == COLOR_TEAM4)
- return "^6";
- else
- return "^7";
-}
-
-string Team_ColorName(float t)
-{
- // fixme: Search for team entities and get their .netname's!
- if (t == COLOR_TEAM1)
- return "Red";
- if (t == COLOR_TEAM2)
- return "Blue";
- if (t == COLOR_TEAM3)
- return "Yellow";
- if (t == COLOR_TEAM4)
- return "Pink";
- return "Neutral";
-}
-
-string Team_ColorNameLowerCase(float t)
-{
- // fixme: Search for team entities and get their .netname's!
- if (t == COLOR_TEAM1)
- return "red";
- if (t == COLOR_TEAM2)
- return "blue";
- if (t == COLOR_TEAM3)
- return "yellow";
- if (t == COLOR_TEAM4)
- return "pink";
- return "neutral";
-}
-
-float ColourToNumber(string team_colour)
-{
- if (team_colour == "red")
- return COLOR_TEAM1;
-
- if (team_colour == "blue")
- return COLOR_TEAM2;
-
- if (team_colour == "yellow")
- return COLOR_TEAM3;
-
- if (team_colour == "pink")
- return COLOR_TEAM4;
-
- if (team_colour == "auto")
- return 0;
-
- return -1;
-}
-
-float NumberToTeamNumber(float number)
-{
- if (number == 1)
- return COLOR_TEAM1;
-
- if (number == 2)
- return COLOR_TEAM2;
-
- if (number == 3)
- return COLOR_TEAM3;
-
- if (number == 4)
- return COLOR_TEAM4;
-
- return -1;
-}
-
// decolorizes and team colors the player name when needed
string playername(entity p)
{
float sv_autotaunt;
float sv_taunt;
-float sv_pitch_min;
-float sv_pitch_max;
-float sv_pitch_fixyaw;
-
string GetGametype(); // g_world.qc
void readlevelcvars(void)
{
MUTATOR_ADD(mutator_dodging);
if(cvar("g_spawn_near_teammate"))
MUTATOR_ADD(mutator_spawn_near_teammate);
+ if(cvar("g_physical_items"))
+ MUTATOR_ADD(mutator_physical_items);
if(!g_minstagib)
{
if(cvar("g_invincible_projectiles"))
g_touchexplode_edgedamage = cvar("g_touchexplode_edgedamage");
g_touchexplode_force = cvar("g_touchexplode_force");
-#ifdef ALLOW_FORCEMODELS
- sv_clforceplayermodels = cvar("sv_clforceplayermodels");
-#endif
-
sv_clones = cvar("sv_clones");
- sv_gentle = cvar("sv_gentle");
sv_foginterval = cvar("sv_foginterval");
g_cloaked = cvar("g_cloaked");
if(g_cts)
if not(inWarmupStage && !g_ca)
game_starttime = cvar("g_start_delay");
- sv_pitch_min = cvar("sv_pitch_min");
- sv_pitch_max = cvar("sv_pitch_max");
- sv_pitch_fixyaw = cvar("sv_pitch_fixyaw");
-
readplayerstartcvars();
}
precache_sound ("player/lava.wav");
precache_sound ("player/slime.wav");
- if (g_jetpack)
- precache_sound ("misc/jetpack_fly.wav");
-
precache_model ("models/sprites/0.spr32");
precache_model ("models/sprites/1.spr32");
precache_model ("models/sprites/2.spr32");
#endif
}
-// sorry, but using \ in macros breaks line numbers
-#define WRITESPECTATABLE_MSG_ONE_VARNAME(varname,statement) entity varname; varname = msg_entity; FOR_EACH_REALCLIENT(msg_entity) if(msg_entity == varname || (msg_entity.classname == STR_SPECTATOR && msg_entity.enemy == varname)) statement msg_entity = varname
-#define WRITESPECTATABLE_MSG_ONE(statement) WRITESPECTATABLE_MSG_ONE_VARNAME(oldmsg_entity, statement)
-#define WRITESPECTATABLE(msg,statement) if(msg == MSG_ONE) { WRITESPECTATABLE_MSG_ONE(statement); } else statement float WRITESPECTATABLE_workaround = 0
-
-
-void Send_CSQC_Centerprint_Generic(entity e, float id, string s, float duration, float countdown_num)
-{
- if ((clienttype(e) == CLIENTTYPE_REAL) && (e.flags & FL_CLIENT))
- {
- msg_entity = e;
- WRITESPECTATABLE_MSG_ONE({
- WriteByte(MSG_ONE, SVC_TEMPENTITY);
- WriteByte(MSG_ONE, TE_CSQC_CENTERPRINT_GENERIC);
- WriteByte(MSG_ONE, id);
- WriteString(MSG_ONE, s);
- if (id != 0 && s != "")
- {
- WriteByte(MSG_ONE, duration);
- WriteByte(MSG_ONE, countdown_num);
- }
- });
- }
-}
-void Send_CSQC_Centerprint_Generic_Expire(entity e, float id)
-{
- Send_CSQC_Centerprint_Generic(e, id, "", 1, 0);
-}
// WARNING: this kills the trace globals
#define EXACTTRIGGER_TOUCH if(WarpZoneLib_ExactTrigger_Touch()) return
#define EXACTTRIGGER_INIT WarpZoneLib_ExactTrigger_Init()
self = e_old;
}
//dprint("Delayed initialization: ", self.classname, "\n");
- if(func != func_null)
+ if(func)
func();
else
{
.float uncustomizeentityforclient_set;
.void(void) uncustomizeentityforclient;
-void(void) SUB_Nullpointer = #0;
void UncustomizeEntitiesRun()
{
entity oldself;
{
e.customizeentityforclient = customizer;
e.uncustomizeentityforclient = uncustomizer;
- e.uncustomizeentityforclient_set = (uncustomizer != SUB_Nullpointer);
+ e.uncustomizeentityforclient_set = !!uncustomizer;
}
.float nottargeted;
return uid2name(db_get(ServerProgsDB, strcat(map, rr, "crypto_idfp", ftos(pos))));
}
-string race_placeName(float pos) {
- if(floor((mod(pos, 100))/10) * 10 != 10) // examples: 12th, 111th, 213th will not execute this block
- {
- if(mod(pos, 10) == 1)
- return strcat(ftos(pos), "st");
- else if(mod(pos, 10) == 2)
- return strcat(ftos(pos), "nd");
- else if(mod(pos, 10) == 3)
- return strcat(ftos(pos), "rd");
- else
- return strcat(ftos(pos), "th");
- }
- else
- return strcat(ftos(pos), "th");
-}
-
float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
{
float m, i;
{
if (visual)
{
- vecs_y = 0;
- vecs_z -= 2;
+ if (autocvar_g_shootfromclient) { vecs = shotorg_adjustfromclient(vecs, y_is_right, (autocvar_g_shootfromclient >= 2), algn); }
+ else { vecs_y = 0; vecs_z -= 2; }
}
else
{
return gettaginfo(gettaginfo_relative_ent, tag);
}
-void SoundEntity_StartSound(entity pl, float chan, string samp, float vol, float attn)
-{
- float p;
- p = pow(2, chan);
- if (pl.soundentity.cnt & p)
- return;
- soundtoat(MSG_ALL, pl.soundentity, gettaginfo(pl.soundentity, 0), chan, samp, vol, attn);
- pl.soundentity.cnt |= p;
-}
-
-void SoundEntity_StopSound(entity pl, float chan)
-{
- float p;
- p = pow(2, chan);
- if (pl.soundentity.cnt & p)
- {
- stopsoundto(MSG_ALL, pl.soundentity, chan);
- pl.soundentity.cnt &~= p;
- }
-}
-
-void SoundEntity_Attach(entity pl)
-{
- pl.soundentity = spawn();
- pl.soundentity.classname = "soundentity";
- pl.soundentity.owner = pl;
- setattachment(pl.soundentity, pl, "");
- setmodel(pl.soundentity, "null");
-}
-
-void SoundEntity_Detach(entity pl)
-{
- float i;
- for (i = 0; i <= 7; ++i)
- SoundEntity_StopSound(pl, i);
-}
-
.float scale2;
float modeleffect_SendEntity(entity to, float sf)
{
if(name == loaded_mutators[i])
return 1; // already added
- if(!loaded_mutators[i])
+ if not(loaded_mutators[i])
j = i;
}
if(j < 0)
// good
return 1;
}
- backtrace("WARNING: when adding mutator: adding failed\n");
- Mutator_Remove(func, name);
+
+ backtrace("WARNING: when adding mutator: adding failed, rolling back\n");
+
+ if(func(MUTATOR_ROLLING_BACK) != 0)
+ {
+ // baaaaad
+ error("WARNING: when adding mutator: rolling back failed");
+ }
return 0;
}
void Mutator_Remove(float(float) func, string name)
float CallbackChain_ReturnValue; // read-only field of the current return value
entity CallbackChain_New(string name);
-float CallbackChain_Add(entity cb, float() func, float order)
+float CallbackChain_Add(entity cb, float() func, float order);
float CallbackChain_Remove(entity cb, float() func);
// a callback function is like this:
// float mycallback(entity me)
#define MUTATOR_REMOVING 0
#define MUTATOR_ADDING 1
+#define MUTATOR_ROLLING_BACK 2
typedef float(float) mutatorfunc_t;
float Mutator_Add(mutatorfunc_t func, string name);
void Mutator_Remove(mutatorfunc_t func, string name); // calls error() on fail
#define MUTATOR_DEFINITION(name) float MUTATOR_##name(float mode)
#define MUTATOR_DECLARATION(name) float MUTATOR_##name(float mode)
#define MUTATOR_HOOKFUNCTION(name) float HOOKFUNCTION_##name()
-#define MUTATOR_HOOK(cb,func,order) do { if(mode == MUTATOR_ADDING) { if(!HOOK_##cb) HOOK_##cb = CallbackChain_New(#cb); if(!CallbackChain_Add(HOOK_##cb,HOOKFUNCTION_##func,order)) { print("HOOK FAILED: ", #func, "\n"); return 1; } } else if(mode == MUTATOR_REMOVING) { if(HOOK_##cb) CallbackChain_Remove(HOOK_##cb,HOOKFUNCTION_##func); } } while(0)
+#define MUTATOR_HOOK(cb,func,order) do { if(mode == MUTATOR_ADDING) { if(!HOOK_##cb) HOOK_##cb = CallbackChain_New(#cb); if(!CallbackChain_Add(HOOK_##cb,HOOKFUNCTION_##func,order)) { print("HOOK FAILED: ", #func, "\n"); return 1; } } else if(mode == MUTATOR_REMOVING || mode == MUTATOR_ROLLING_BACK) { if(HOOK_##cb) CallbackChain_Remove(HOOK_##cb,HOOKFUNCTION_##func); } } while(0)
#define MUTATOR_ONADD if(mode == MUTATOR_ADDING)
#define MUTATOR_ONREMOVE if(mode == MUTATOR_REMOVING)
+#define MUTATOR_ONROLLBACK_OR_REMOVE if(mode == MUTATOR_REMOVING || mode == MUTATOR_ROLLING_BACK)
#define MUTATOR_HOOKABLE(cb) entity HOOK_##cb
#define MUTATOR_CALLHOOK(cb) CallbackChain_Call(HOOK_##cb)
MUTATOR_HOOKABLE(SetModname);
// OUT
string modname; // name of the mutator/mod if it warrants showing as such in the server browser
+
+MUTATOR_HOOKABLE(Item_Spawn);
+ // called for each item being spawned on a map, including dropped weapons
+ // return 1 to remove an item
+ // INPUT
+ entity self; // the item
MUTATOR_HOOKABLE(SetWeaponreplace);
// IN
GameLogEcho(strcat(":ctf:", mode, ":", ftos(flagteam), ((actor != world) ? (strcat(":", ftos(actor.playerid))) : "")));
}
-string ctf_CaptureRecord(entity flag, entity player)
+void ctf_CaptureRecord(entity flag, entity player)
{
- float cap_time, cap_record, success;
- string cap_message, refername;
+ entity tmp_entity;
+ float cap_record = ctf_captimerecord;
+ float cap_time = (time - flag.ctf_pickuptime);
+ string refername = db_get(ServerProgsDB, strcat(GetMapname(), "/captimerecord/netname"));
- if((autocvar_g_ctf_captimerecord_always) || (player_count - currentbots))
+ // notify about shit
+ FOR_EACH_REALCLIENT(tmp_entity)
{
- cap_record = ctf_captimerecord;
- cap_time = (time - flag.ctf_pickuptime);
-
- refername = db_get(ServerProgsDB, strcat(GetMapname(), "/captimerecord/netname"));
- refername = ((refername == player.netname) ? "their" : strcat(refername, "^7's"));
-
- if(!ctf_captimerecord)
- { cap_message = strcat(" in ", ftos_decimals(cap_time, 2), " seconds"); success = TRUE; }
- else if(cap_time < cap_record)
- { cap_message = strcat(" in ", ftos_decimals(cap_time, 2), " seconds, breaking ", refername, " previous record of ", ftos_decimals(cap_record, 2), " seconds"); success = TRUE; }
- else
- { cap_message = strcat(" in ", ftos_decimals(cap_time, 2), " seconds, failing to break ", refername, " record of ", ftos_decimals(cap_record, 2), " seconds"); success = FALSE; }
+ if(tmp_entity.CAPTURE_VERBOSE)
+ {
+ if(!ctf_captimerecord) { Send_Notification(NOTIF_ONE_ONLY, tmp_entity, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_CAPTURE_TIME_), player.netname, (cap_time * 100)); }
+ else if(cap_time < cap_record) { Send_Notification(NOTIF_ONE_ONLY, tmp_entity, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_CAPTURE_BROKEN_), player.netname, refername, (cap_time * 100), (cap_record * 100)); }
+ else { Send_Notification(NOTIF_ONE_ONLY, tmp_entity, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_CAPTURE_UNBROKEN_), player.netname, refername, (cap_time * 100), (cap_record * 100)); }
+ }
+ else { Send_Notification(NOTIF_ONE_ONLY, tmp_entity, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_CAPTURE_), player.netname); }
+ }
- if(success)
+ // the previous notification broadcast is only sent to real clients, this will notify server log too
+ if(server_is_dedicated)
+ {
+ if(autocvar_notification_ctf_capture_verbose)
{
- ctf_captimerecord = cap_time;
- db_put(ServerProgsDB, strcat(GetMapname(), "/captimerecord/time"), ftos(cap_time));
- db_put(ServerProgsDB, strcat(GetMapname(), "/captimerecord/netname"), player.netname);
- write_recordmarker(player, (time - cap_time), cap_time);
- }
+ if(!ctf_captimerecord) { Local_Notification(MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_CAPTURE_TIME_), player.netname, (cap_time * 100)); }
+ else if(cap_time < cap_record) { Local_Notification(MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_CAPTURE_BROKEN_), player.netname, refername, (cap_time * 100), (cap_record * 100)); }
+ else { Local_Notification(MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_CAPTURE_UNBROKEN_), player.netname, refername, (cap_time * 100), (cap_record * 100)); }
+ }
+ else { Local_Notification(MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_CAPTURE_), player.netname); }
}
- return cap_message;
+ // write that shit in the database
+ if((!ctf_captimerecord) || (cap_time < cap_record))
+ {
+ ctf_captimerecord = cap_time;
+ db_put(ServerProgsDB, strcat(GetMapname(), "/captimerecord/time"), ftos(cap_time));
+ db_put(ServerProgsDB, strcat(GetMapname(), "/captimerecord/netname"), player.netname);
+ write_recordmarker(player, (time - cap_time), cap_time);
+ }
}
void ctf_FlagcarrierWaypoints(entity player)
float updated_status = ctf_CaptureShield_CheckStatus(player);
if((wanted_status == player.ctf_captureshielded) && (updated_status != wanted_status)) // 0: shield only, 1: unshield only
{
- if(updated_status) // TODO csqc notifier for this // Samual: How?
- Send_CSQC_Centerprint_Generic(player, CPID_CTF_CAPTURESHIELD, "^3You are now ^4shielded^3 from the flag\n^3for ^1too many unsuccessful attempts^3 to capture.\n\n^3Make some defensive scores before trying again.", 5, 0);
- else
- Send_CSQC_Centerprint_Generic(player, CPID_CTF_CAPTURESHIELD, "^3You are now free.\n\n^3Feel free to ^1try to capture^3 the flag again\n^3if you think you will succeed.", 5, 0);
-
+ Send_Notification(NOTIF_ONE, player, MSG_CENTER, ((updated_status) ? CENTER_CTF_CAPTURESHIELD_SHIELDED : CENTER_CTF_CAPTURESHIELD_FREE));
player.ctf_captureshielded = updated_status;
}
}
vector othermid = (other.absmin + other.absmax) * 0.5;
Damage(other, self, self, 0, DEATH_HURTTRIGGER, mymid, normalize(othermid - mymid) * ctf_captureshield_force);
- Send_CSQC_Centerprint_Generic(other, CPID_CTF_CAPTURESHIELD, "^3You are ^4shielded^3 from the flag\n^3for ^1too many unsuccessful attempts^3 to capture.\n\n^3Get some defensive scores before trying again.", 5, 0);
+ Send_Notification(NOTIF_ONE, other, MSG_CENTER, CENTER_CTF_CAPTURESHIELD_SHIELDED);
}
void ctf_CaptureShield_Spawn(entity flag)
flag.ctf_status = FLAG_DROPPED;
// messages and sounds
- Send_KillNotification(player.netname, flag.netname, "", INFO_LOSTFLAG, MSG_INFO);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_LOST_), player.netname);
sound(flag, CH_TRIGGER, flag.snd_flag_dropped, VOL_BASE, ATTN_NONE);
ctf_EventLog("dropped", player.team, player);
FOR_EACH_REALPLAYER(tmp_player)
{
if(tmp_player == sender)
- centerprint(tmp_player, strcat("You passed the ", flag.netname, " to ", player.netname));
+ Send_Notification(NOTIF_ONE, tmp_player, MSG_CENTER, APP_TEAM_ENT_2(flag, CENTER_CTF_PASS_SENT_), player.netname);
else if(tmp_player == player)
- centerprint(tmp_player, strcat("You received the ", flag.netname, " from ", sender.netname));
+ Send_Notification(NOTIF_ONE, tmp_player, MSG_CENTER, APP_TEAM_ENT_2(flag, CENTER_CTF_PASS_RECEIVED_), sender.netname);
else if(!IsDifferentTeam(tmp_player, sender))
- centerprint(tmp_player, strcat(sender.netname, " passed the ", flag.netname, " to ", player.netname));
+ Send_Notification(NOTIF_ONE, tmp_player, MSG_CENTER, APP_TEAM_ENT_2(flag, CENTER_CTF_PASS_OTHER_), sender.netname, player.netname);
}
// create new waypoint
if not(player) { return; } // without someone to give the reward to, we can't possibly cap
// messages and sounds
- Send_KillNotification(player.netname, enemy_flag.netname, ctf_CaptureRecord(enemy_flag, player), INFO_CAPTUREFLAG, MSG_INFO);
+ Send_Notification(NOTIF_ONE, player, MSG_CENTER, APP_TEAM_ENT_2(enemy_flag, CENTER_CTF_CAPTURE_));
+ ctf_CaptureRecord(enemy_flag, player);
sound(player, CH_TRIGGER, flag.snd_flag_capture, VOL_BASE, ATTN_NONE);
switch(capturetype)
void ctf_Handle_Return(entity flag, entity player)
{
// messages and sounds
- //centerprint(player, strcat("You returned the ", flag.netname));
- Send_KillNotification(player.netname, flag.netname, "", INFO_RETURNFLAG, MSG_INFO);
+ Send_Notification(NOTIF_ONE, player, MSG_CENTER, APP_TEAM_ENT_2(flag, CENTER_CTF_RETURN_));
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_RETURN_), player.netname);
sound(player, CH_TRIGGER, flag.snd_flag_returned, VOL_BASE, ATTN_NONE);
ctf_EventLog("return", flag.team, player);
{
// declarations
entity tmp_player; // temporary entity which the FOR_EACH_PLAYER loop uses to scan players
- string verbosename; // holds the name of the player OR no name at all for printing in the centerprints
float pickup_dropped_score; // used to calculate dropped pickup score
// attach the flag to the player
}
// messages and sounds
- Send_KillNotification (player.netname, flag.netname, "", INFO_GOTFLAG, MSG_INFO);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_PICKUP_), player.netname);
sound(player, CH_TRIGGER, flag.snd_flag_taken, VOL_BASE, ATTN_NONE);
- verbosename = ((autocvar_g_ctf_flag_pickup_verbosename) ? strcat(Team_ColorCode(player.team), "(^7", player.netname, Team_ColorCode(player.team), ") ") : "");
-
+
FOR_EACH_REALPLAYER(tmp_player)
{
if(tmp_player == player)
{
- centerprint(tmp_player, strcat("You got the ", flag.netname, "!"));
- //if(ctf_stalemate) { centerprint(tmp_player, "Stalemate! Enemies can see you on radar!"); }
+ Send_Notification(NOTIF_ONE, tmp_player, MSG_CENTER, APP_TEAM_ENT_2(flag, CENTER_CTF_PICKUP_));
+ if(ctf_stalemate) { Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_CTF_STALEMATE_CARRIER); }
+ }
+ else if(!IsDifferentTeam(tmp_player, player) && tmp_player != player)
+ {
+ if(tmp_player.PICKUP_TEAM_VERBOSE)
+ Send_Notification(NOTIF_ONE, tmp_player, MSG_CENTER, CENTER_CTF_PICKUP_TEAM_VERBOSE, Team_ColorCode(player.team), player.netname);
+ else
+ Send_Notification(NOTIF_ONE, tmp_player, MSG_CENTER, CENTER_CTF_PICKUP_TEAM, Team_ColorCode(player.team));
+ }
+ else if(IsDifferentTeam(tmp_player, player))
+ {
+ if(tmp_player.PICKUP_ENEMY_VERBOSE)
+ Send_Notification(NOTIF_ONE, tmp_player, MSG_CENTER, CENTER_CTF_PICKUP_ENEMY_VERBOSE, Team_ColorCode(player.team), player.netname);
+ else
+ Send_Notification(NOTIF_ONE, tmp_player, MSG_CENTER, CENTER_CTF_PICKUP_ENEMY, Team_ColorCode(player.team));
}
- //else if(!IsDifferentTeam(tmp_player, player))
- // centerprint(tmp_player, strcat("Your ", Team_ColorCode(player.team), "team mate ", verbosename, "^7got the flag! Protect them!"));
- else if(!IsDifferentTeam(tmp_player, flag))
- centerprint(tmp_player, strcat("The ", Team_ColorCode(player.team), "enemy ", verbosename, "^7got your flag! Retrieve it!"));
}
// scoring
{
switch(returntype)
{
- case RETURN_DROPPED: bprint("The ", flag.netname, " was dropped in the base and returned itself\n"); break;
- case RETURN_DAMAGE: bprint("The ", flag.netname, " was destroyed and returned to base\n"); break;
- case RETURN_SPEEDRUN: bprint("The ", flag.netname, " became impatient after ", ftos_decimals(ctf_captimerecord, 2), " seconds and returned itself\n"); break;
- case RETURN_NEEDKILL: bprint("The ", flag.netname, " fell somewhere it couldn't be reached and returned to base\n"); break;
+ case RETURN_DROPPED: Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_FLAGRETURN_DROPPED_)); break;
+ case RETURN_DAMAGE: Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_FLAGRETURN_DAMAGED_)); break;
+ case RETURN_SPEEDRUN: Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_FLAGRETURN_SPEEDRUN_), ctf_captimerecord); break;
+ case RETURN_NEEDKILL: Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_FLAGRETURN_NEEDKILL_)); break;
default:
case RETURN_TIMEOUT:
- { bprint("The ", flag.netname, " has returned to base\n"); break; }
+ { Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_2(flag, INFO_CTF_FLAGRETURN_TIMEOUT_)); break; }
}
sound(flag, CH_TRIGGER, flag.snd_flag_respawn, VOL_BASE, ATTN_NONE);
ctf_EventLog("returned", flag.team, world);
void ctf_CheckStalemate(void)
{
// declarations
- float stale_red_flags, stale_blue_flags;
+ float stale_red_flags = 0, stale_blue_flags = 0;
entity tmp_entity;
- entity ctf_staleflaglist; // reset the list, we need to build the list each time this function runs
+ entity ctf_staleflaglist = world; // reset the list, we need to build the list each time this function runs
// build list of stale flags
for(tmp_entity = ctf_worldflaglist; tmp_entity; tmp_entity = tmp_entity.ctf_worldflagnext)
switch(tmp_entity.team)
{
- case COLOR_TEAM1: ++stale_red_flags; break;
- case COLOR_TEAM2: ++stale_blue_flags; break;
+ case NUM_TEAM_1: ++stale_red_flags; break;
+ case NUM_TEAM_2: ++stale_blue_flags; break;
}
}
}
if not(wpforenemy_announced)
{
FOR_EACH_REALPLAYER(tmp_entity)
- if(tmp_entity.flagcarried)
- centerprint(tmp_entity, "Stalemate! Enemies can now see you on radar!");
- else
- centerprint(tmp_entity, "Stalemate! Flag carriers can now be seen by enemies on radar!");
+ Send_Notification(NOTIF_ONE, tmp_entity, MSG_CENTER, ((tmp_entity.flagcarried) ? CENTER_CTF_STALEMATE_CARRIER : CENTER_CTF_STALEMATE_OTHER));
wpforenemy_announced = TRUE;
}
self.bot_basewaypoint = self.nearestwaypoint;
// waypointsprites
- WaypointSprite_SpawnFixed(((self.team == COLOR_TEAM1) ? "redbase" : "bluebase"), self.origin + FLAG_WAYPOINT_OFFSET, self, wps_flagbase, RADARICON_FLAG, colormapPaletteColor(self.team - 1, FALSE));
+ WaypointSprite_SpawnFixed(((self.team == NUM_TEAM_1) ? "redbase" : "bluebase"), self.origin + FLAG_WAYPOINT_OFFSET, self, wps_flagbase, RADARICON_FLAG, colormapPaletteColor(self.team - 1, FALSE));
WaypointSprite_UpdateTeamRadar(self.wps_flagbase, RADARICON_FLAG, colormapPaletteColor(self.team - 1, FALSE));
// captureshield setup
flag.ctf_worldflagnext = ctf_worldflaglist; // link flag into ctf_worldflaglist
ctf_worldflaglist = flag;
- setattachment(flag, world, "");
+ setattachment(flag, world, "");
- flag.netname = ((teamnumber) ? "^1RED^7 flag" : "^4BLUE^7 flag");
- flag.team = ((teamnumber) ? COLOR_TEAM1 : COLOR_TEAM2); // COLOR_TEAM1: color 4 team (red) - COLOR_TEAM2: color 13 team (blue)
+ flag.netname = ((teamnumber) ? "^1REPLACETHIS^7" : "^4REPLACETHIS^7"); // ((teamnumber) ? "^1RED^7 flag" : "^4BLUE^7 flag");
+ flag.team = ((teamnumber) ? NUM_TEAM_1 : NUM_TEAM_2); // NUM_TEAM_1: color 4 team (red) - NUM_TEAM_2: color 13 team (blue)
flag.items = ((teamnumber) ? IT_KEY2 : IT_KEY1); // IT_KEY2: gold key (redish enough) - IT_KEY1: silver key (bluish enough)
flag.classname = "item_flag_team";
flag.target = "###item###"; // wut?
frag_target.wps_helpme_time = time;
WaypointSprite_HelpMePing(frag_target.wps_flagcarrier);
}
+ // todo: add notification for when flag carrier needs help?
}
return FALSE;
}
// pass the flag to a team mate
if(autocvar_g_ctf_pass)
{
- entity head, closest_target;
+ entity head, closest_target = world;
head = WarpZone_FindRadius(player.origin, autocvar_g_ctf_pass_radius, TRUE);
while(head) // find the closest acceptable target to pass to
{
if(clienttype(head) == CLIENTTYPE_BOT)
{
- centerprint(player, strcat("Requesting ", head.netname, " to pass you the ", head.flagcarried.netname));
+ Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_CTF_PASS_REQUESTING, head.netname);
ctf_Handle_Throw(head, player, DROP_PASS);
}
else
{
- centerprint(head, strcat(player.netname, " requests you to pass the ", head.flagcarried.netname));
- centerprint(player, strcat("Requesting ", head.netname, " to pass you the ", head.flagcarried.netname));
+ Send_Notification(NOTIF_ONE, head, MSG_CENTER, CENTER_CTF_PASS_REQUESTED, player.netname);
+ Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_CTF_PASS_REQUESTING, head.netname);
}
player.throw_antispam = time + autocvar_g_ctf_pass_wait;
return TRUE;
}
else
{
- centerprint(player, strcat("Too many flag throws, throwing disabled for ", ftos(rint((player.throw_prevtime + autocvar_g_ctf_throw_punish_delay) - time)), " seconds."));
+ Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_CTF_FLAG_THROW_PUNISH, rint((player.throw_prevtime + autocvar_g_ctf_throw_punish_delay) - time));
return FALSE;
}
}
{
if(self.flagcarried)
{
- bprint("The ", self.flagcarried.netname, " was returned to base by its carrier\n");
- ctf_RespawnFlag(self);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_2(self.flagcarried, INFO_CTF_FLAGRETURN_ABORTRUN_));
+ ctf_RespawnFlag(self.flagcarried);
return TRUE;
}
flag.solid = SOLID_NOT;
flag.nextthink = FALSE; // stop thinking
- print("stopping the ", flag.netname, " from moving.\n");
+ //dprint("stopping the ", flag.netname, " from moving.\n");
break;
}
return TRUE;
}
+MUTATOR_HOOKFUNCTION(ctf_GetCvars)
+{
+ GetCvars_handleFloat(get_cvars_s, get_cvars_f, CAPTURE_VERBOSE, "notification_ctf_capture_verbose");
+ GetCvars_handleFloat(get_cvars_s, get_cvars_f, PICKUP_TEAM_VERBOSE, "notification_ctf_pickup_team_verbose");
+ GetCvars_handleFloat(get_cvars_s, get_cvars_f, PICKUP_ENEMY_VERBOSE, "notification_ctf_pickup_enemy_verbose");
+ return TRUE;
+}
+
// ==========
// Spawnfuncs
{
if(g_assault) { remove(self); return; }
- self.team = COLOR_TEAM1; // red
+ self.team = NUM_TEAM_1; // red
spawnfunc_info_player_deathmatch();
}
{
if(g_assault) { remove(self); return; }
- self.team = COLOR_TEAM2; // blue
+ self.team = NUM_TEAM_2; // blue
spawnfunc_info_player_deathmatch();
}
{
if(g_assault) { remove(self); return; }
- self.team = COLOR_TEAM3; // yellow
+ self.team = NUM_TEAM_3; // yellow
spawnfunc_info_player_deathmatch();
}
{
if(g_assault) { remove(self); return; }
- self.team = COLOR_TEAM4; // purple
+ self.team = NUM_TEAM_4; // purple
spawnfunc_info_player_deathmatch();
}
if(find(world, classname, "ctf_team") == world)
{
print("No ""ctf_team"" entities found on this map, creating them anyway.\n");
- ctf_SpawnTeam("Red", COLOR_TEAM1 - 1);
- ctf_SpawnTeam("Blue", COLOR_TEAM2 - 1);
+ ctf_SpawnTeam("Red", NUM_TEAM_1 - 1);
+ ctf_SpawnTeam("Blue", NUM_TEAM_2 - 1);
}
ctf_ScoreRules();
MUTATOR_HOOK(VehicleExit, ctf_VehicleExit, CBC_ORDER_ANY);
MUTATOR_HOOK(AbortSpeedrun, ctf_AbortSpeedrun, CBC_ORDER_ANY);
MUTATOR_HOOK(HavocBot_ChooseRule, ctf_BotRoles, CBC_ORDER_ANY);
+ MUTATOR_HOOK(GetCvars, ctf_GetCvars, 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.");
- g_ctf = 1;
ctf_Initialize();
}
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ // we actually cannot roll back ctf_Initialize here
+ // BUT: we don't need to! If this gets called, adding always
+ // succeeds.
+ }
+
MUTATOR_ONREMOVE
{
- g_ctf = 0;
- error("This is a game type and it cannot be removed at runtime.");
+ print("This is a game type and it cannot be removed at runtime.");
+ return -1;
}
return 0;
// these are needed since mutators are compiled last
+#ifdef SVQC
// used in cheats.qc
-void ctf_RespawnFlag(entity flag)
+void ctf_RespawnFlag(entity flag);
// score rule declarations
#define ST_CTF_CAPS 1
float havocbot_ctf_middlepoint_radius;
void havocbot_role_ctf_setrole(entity bot, float role);
+
+// client notification stuff
+.float CAPTURE_VERBOSE;
+.float PICKUP_TEAM_VERBOSE;
+.float PICKUP_ENEMY_VERBOSE;
+#else
+var float autocvar_notification_ctf_pickup_team_verbose = FALSE;
+var float autocvar_notification_ctf_pickup_enemy_verbose = FALSE;
+#endif
+var float autocvar_notification_ctf_capture_verbose = FALSE;
--- /dev/null
+void dom_EventLog(string mode, float team_before, entity actor) // use an alias for easy changing and quick editing later
+{
+ if(autocvar_sv_eventlog)
+ GameLogEcho(strcat(":dom:", mode, ":", ftos(team_before), ((actor != world) ? (strcat(":", ftos(actor.playerid))) : "")));
+}
+
+void set_dom_state(entity e)
+{
+ e.dom_total_pps = total_pps;
+ e.dom_pps_red = pps_red;
+ e.dom_pps_blue = pps_blue;
+ if(c3 >= 0)
+ e.dom_pps_yellow = pps_yellow;
+ if(c4 >= 0)
+ e.dom_pps_pink = pps_pink;
+}
+
+void dompoint_captured ()
+{
+ entity head;
+ float old_delay, old_team, real_team;
+
+ // now that the delay has expired, switch to the latest team to lay claim to this point
+ head = self.owner;
+
+ real_team = self.cnt;
+ self.cnt = -1;
+
+ dom_EventLog("taken", self.team, self.dmg_inflictor);
+ self.dmg_inflictor = world;
+
+ self.goalentity = head;
+ self.model = head.mdl;
+ self.modelindex = head.dmg;
+ self.skin = head.skin;
+
+ float points, wait_time;
+ if (autocvar_g_domination_point_amt)
+ points = autocvar_g_domination_point_amt;
+ else
+ points = self.frags;
+ if (autocvar_g_domination_point_rate)
+ wait_time = autocvar_g_domination_point_rate;
+ else
+ wait_time = self.wait;
+
+ bprint("^3", head.netname, "^3", self.message);
+ if (points != 1)
+ bprint(" ^7(", ftos(points), " points every ", ftos(wait_time), " seconds)\n");
+ else
+ bprint(" ^7(", ftos(points), " point every ", ftos(wait_time), " seconds)\n");
+
+ if(self.enemy.playerid == self.enemy_playerid)
+ PlayerScore_Add(self.enemy, SP_DOM_TAKES, 1);
+ else
+ self.enemy = world;
+
+ if (head.noise != "")
+ if(self.enemy)
+ sound(self.enemy, CH_TRIGGER, head.noise, VOL_BASE, ATTN_NORM);
+ else
+ sound(self, CH_TRIGGER, head.noise, VOL_BASE, ATTN_NORM);
+ if (head.noise1 != "")
+ play2all(head.noise1);
+
+ self.delay = time + wait_time;
+
+ // do trigger work
+ old_delay = self.delay;
+ old_team = self.team;
+ self.team = real_team;
+ self.delay = 0;
+ activator = self;
+ SUB_UseTargets ();
+ self.delay = old_delay;
+ self.team = old_team;
+
+ WaypointSprite_UpdateSprites(self.sprite, strcat("dom-", Team_ColorName_Lower(self.goalentity.team)), "", "");
+
+ total_pps = 0, pps_red = 0, pps_blue = 0, pps_yellow = 0, pps_pink = 0;
+ for(head = world; (head = find(head, classname, "dom_controlpoint")) != world; )
+ {
+ if (autocvar_g_domination_point_amt)
+ points = autocvar_g_domination_point_amt;
+ else
+ points = head.frags;
+ if (autocvar_g_domination_point_rate)
+ wait_time = autocvar_g_domination_point_rate;
+ else
+ wait_time = head.wait;
+ switch(head.goalentity.team)
+ {
+ case NUM_TEAM_1:
+ pps_red += points/wait_time;
+ break;
+ case NUM_TEAM_2:
+ pps_blue += points/wait_time;
+ break;
+ case NUM_TEAM_3:
+ pps_yellow += points/wait_time;
+ break;
+ case NUM_TEAM_4:
+ pps_pink += points/wait_time;
+ }
+ total_pps += points/wait_time;
+ }
+
+ WaypointSprite_UpdateTeamRadar(self.sprite, RADARICON_DOMPOINT, colormapPaletteColor(self.goalentity.team - 1, 0));
+ WaypointSprite_Ping(self.sprite);
+
+ self.captime = time;
+
+ FOR_EACH_REALCLIENT(head)
+ set_dom_state(head);
+}
+
+void AnimateDomPoint()
+{
+ if(self.pain_finished > time)
+ return;
+ self.pain_finished = time + self.t_width;
+ if(self.nextthink > self.pain_finished)
+ self.nextthink = self.pain_finished;
+
+ self.frame = self.frame + 1;
+ if(self.frame > self.t_length)
+ self.frame = 0;
+}
+
+void dompointthink()
+{
+ float fragamt;
+
+ self.nextthink = time + 0.1;
+
+ //self.frame = self.frame + 1;
+ //if(self.frame > 119)
+ // self.frame = 0;
+ AnimateDomPoint();
+
+ // give points
+
+ if (gameover || self.delay > time || time < game_starttime) // game has ended, don't keep giving points
+ return;
+
+ if(autocvar_g_domination_point_rate)
+ self.delay = time + autocvar_g_domination_point_rate;
+ else
+ self.delay = time + self.wait;
+
+ // give credit to the team
+ // NOTE: this defaults to 0
+ if (self.goalentity.netname != "")
+ {
+ if(autocvar_g_domination_point_amt)
+ fragamt = autocvar_g_domination_point_amt;
+ else
+ fragamt = self.frags;
+ TeamScore_AddToTeam(self.goalentity.team, ST_SCORE, fragamt);
+ TeamScore_AddToTeam(self.goalentity.team, ST_DOM_TICKS, fragamt);
+
+ // give credit to the individual player, if he is still there
+ if (self.enemy.playerid == self.enemy_playerid)
+ {
+ PlayerScore_Add(self.enemy, SP_SCORE, fragamt);
+ PlayerScore_Add(self.enemy, SP_DOM_TICKS, fragamt);
+ }
+ else
+ self.enemy = world;
+ }
+}
+
+void dompointtouch()
+{
+ entity head;
+ if (other.classname != "player")
+ return;
+ if (other.health < 1)
+ return;
+
+ if(time < self.captime + 0.3)
+ return;
+
+ // only valid teams can claim it
+ head = find(world, classname, "dom_team");
+ while (head && head.team != other.team)
+ head = find(head, classname, "dom_team");
+ if (!head || head.netname == "" || head == self.goalentity)
+ return;
+
+ // delay capture
+
+ self.team = self.goalentity.team; // this stores the PREVIOUS team!
+
+ self.cnt = other.team;
+ self.owner = head; // team to switch to after the delay
+ self.dmg_inflictor = other;
+
+ // self.state = 1;
+ // self.delay = time + cvar("g_domination_point_capturetime");
+ //self.nextthink = time + cvar("g_domination_point_capturetime");
+ //self.think = dompoint_captured;
+
+ // go to neutral team in the mean time
+ head = find(world, classname, "dom_team");
+ while (head && head.netname != "")
+ head = find(head, classname, "dom_team");
+ if(head == world)
+ return;
+
+ WaypointSprite_UpdateSprites(self.sprite, "dom-neut", "", "");
+ WaypointSprite_UpdateTeamRadar(self.sprite, RADARICON_DOMPOINT, '0 1 1');
+ WaypointSprite_Ping(self.sprite);
+
+ self.goalentity = head;
+ self.model = head.mdl;
+ self.modelindex = head.dmg;
+ self.skin = head.skin;
+
+ self.enemy = other; // individual player scoring
+ self.enemy_playerid = other.playerid;
+ dompoint_captured();
+}
+
+void dom_controlpoint_setup()
+{
+ entity head;
+ // find the spawnfunc_dom_team representing unclaimed points
+ head = find(world, classname, "dom_team");
+ while(head && head.netname != "")
+ head = find(head, classname, "dom_team");
+ if (!head)
+ objerror("no spawnfunc_dom_team with netname \"\" found\n");
+
+ // copy important properties from spawnfunc_dom_team entity
+ self.goalentity = head;
+ setmodel(self, head.mdl); // precision already set
+ self.skin = head.skin;
+
+ self.cnt = -1;
+
+ if(self.message == "")
+ self.message = " has captured a control point";
+
+ if(self.frags <= 0)
+ self.frags = 1;
+ if(self.wait <= 0)
+ self.wait = 5;
+
+ float points, waittime;
+ if (autocvar_g_domination_point_amt)
+ points = autocvar_g_domination_point_amt;
+ else
+ points = self.frags;
+ if (autocvar_g_domination_point_rate)
+ waittime = autocvar_g_domination_point_rate;
+ else
+ waittime = self.wait;
+
+ total_pps += points/waittime;
+
+ if(!self.t_width)
+ self.t_width = 0.02; // frame animation rate
+ if(!self.t_length)
+ self.t_length = 239; // maximum frame
+
+ self.think = dompointthink;
+ self.nextthink = time;
+ self.touch = dompointtouch;
+ self.solid = SOLID_TRIGGER;
+ self.flags = FL_ITEM;
+ setsize(self, '-32 -32 -32', '32 32 32');
+ setorigin(self, self.origin + '0 0 20');
+ droptofloor();
+
+ waypoint_spawnforitem(self);
+ WaypointSprite_SpawnFixed("dom-neut", self.origin + '0 0 32', self, sprite, RADARICON_DOMPOINT, '0 1 1');
+}
+
+//go to best items, or control points you don't own
+void havocbot_role_dom()
+{
+ if(self.deadflag != DEAD_NO)
+ return;
+
+ if (self.bot_strategytime < time)
+ {
+ self.bot_strategytime = time + autocvar_bot_ai_strategyinterval;
+ navigation_goalrating_start();
+ havocbot_goalrating_controlpoints(10000, self.origin, 15000);
+ havocbot_goalrating_items(8000, self.origin, 8000);
+ //havocbot_goalrating_enemyplayers(3000, self.origin, 2000);
+ //havocbot_goalrating_waypoints(1, self.origin, 1000);
+ navigation_goalrating_end();
+ }
+}
+
+MUTATOR_HOOKFUNCTION(dom_ClientConnect)
+{
+ set_dom_state(self);
+ return FALSE;
+}
+
+MUTATOR_HOOKFUNCTION(dom_BotRoles)
+{
+ self.havocbot_role = havocbot_role_dom;
+ return TRUE;
+}
+
+/*QUAKED spawnfunc_dom_controlpoint (0 .5 .8) (-16 -16 -24) (16 16 32)
+Control point for Domination gameplay.
+*/
+void spawnfunc_dom_controlpoint()
+{
+ if(!g_domination)
+ {
+ remove(self);
+ return;
+ }
+ self.think = dom_controlpoint_setup;
+ self.nextthink = time + 0.1;
+ self.reset = dom_controlpoint_setup;
+
+ if(!self.scale)
+ self.scale = 0.6;
+
+ self.effects = self.effects | EF_LOWPRECISION;
+ if (autocvar_g_domination_point_fullbright)
+ self.effects |= EF_FULLBRIGHT;
+}
+
+/*QUAKED spawnfunc_dom_team (0 .5 .8) (-32 -32 -24) (32 32 32)
+Team declaration for Domination gameplay, this allows you to decide what team
+names and control point models are used in your map.
+
+Note: If you use spawnfunc_dom_team entities you must define at least 3 and only two
+can have netname set! The nameless team owns all control points at start.
+
+Keys:
+"netname"
+ Name of the team (for example Red Team, Blue Team, Green Team, Yellow Team, Life, Death, etc)
+"cnt"
+ Scoreboard color of the team (for example 4 is red and 13 is blue)
+"model"
+ Model to use for control points owned by this team (for example
+ "progs/b_g_key.mdl" is a gold keycard, and "progs/b_s_key.mdl" is a silver
+ keycard)
+"skin"
+ Skin of the model to use (for team skins on a single model)
+"noise"
+ Sound to play when this team captures a point.
+ (this is a localized sound, like a small alarm or other effect)
+"noise1"
+ Narrator speech to play when this team captures a point.
+ (this is a global sound, like "Red team has captured a control point")
+*/
+
+void spawnfunc_dom_team()
+{
+ if(!g_domination || autocvar_g_domination_teams_override >= 2)
+ {
+ remove(self);
+ return;
+ }
+ precache_model(self.model);
+ if (self.noise != "")
+ precache_sound(self.noise);
+ if (self.noise1 != "")
+ precache_sound(self.noise1);
+ self.classname = "dom_team";
+ setmodel(self, self.model); // precision not needed
+ self.mdl = self.model;
+ self.dmg = self.modelindex;
+ self.model = "";
+ self.modelindex = 0;
+ // this would have to be changed if used in quakeworld
+ if(self.cnt)
+ self.team = self.cnt + 1; // WHY are these different anyway?
+}
+
+// scoreboard setup
+void ScoreRules_dom()
+{
+ float sp_domticks, sp_score;
+ sp_score = sp_domticks = 0;
+ if(autocvar_g_domination_disable_frags)
+ sp_domticks = SFL_SORT_PRIO_PRIMARY;
+ else
+ sp_score = SFL_SORT_PRIO_PRIMARY;
+ CheckAllowedTeams(world);
+ ScoreRules_basics(((c4>=0) ? 4 : (c3>=0) ? 3 : 2), sp_score, sp_score, TRUE);
+ ScoreInfo_SetLabel_TeamScore (ST_DOM_TICKS, "ticks", sp_domticks);
+ ScoreInfo_SetLabel_PlayerScore(SP_DOM_TICKS, "ticks", sp_domticks);
+ ScoreInfo_SetLabel_PlayerScore(SP_DOM_TAKES, "takes", 0);
+ ScoreRules_basics_end();
+}
+
+// code from here on is just to support maps that don't have control point and team entities
+void dom_spawnteam (string teamname, float teamcolor, string pointmodel, float pointskin, string capsound, string capnarration, string capmessage)
+{
+ entity oldself;
+ oldself = self;
+ self = spawn();
+ self.classname = "dom_team";
+ self.netname = teamname;
+ self.cnt = teamcolor;
+ self.model = pointmodel;
+ self.skin = pointskin;
+ self.noise = capsound;
+ self.noise1 = capnarration;
+ self.message = capmessage;
+
+ // this code is identical to spawnfunc_dom_team
+ setmodel(self, self.model); // precision not needed
+ self.mdl = self.model;
+ self.dmg = self.modelindex;
+ self.model = "";
+ self.modelindex = 0;
+ // this would have to be changed if used in quakeworld
+ self.team = self.cnt + 1;
+
+ //eprint(self);
+ self = oldself;
+}
+
+void dom_spawnpoint(vector org)
+{
+ entity oldself;
+ oldself = self;
+ self = spawn();
+ self.classname = "dom_controlpoint";
+ self.think = spawnfunc_dom_controlpoint;
+ self.nextthink = time;
+ setorigin(self, org);
+ spawnfunc_dom_controlpoint();
+ self = oldself;
+}
+
+// spawn some default teams if the map is not set up for domination
+void dom_spawnteams()
+{
+ float numteams = ((autocvar_g_domination_teams_override < 2) ? autocvar_g_domination_default_teams : autocvar_g_domination_teams_override);
+
+ dom_spawnteam("Red", NUM_TEAM_1-1, "models/domination/dom_red.md3", 0, "domination/claim.wav", "", "Red team has captured a control point");
+ dom_spawnteam("Blue", NUM_TEAM_2-1, "models/domination/dom_blue.md3", 0, "domination/claim.wav", "", "Blue team has captured a control point");
+ if(numteams > 2)
+ dom_spawnteam("Yellow", NUM_TEAM_3-1, "models/domination/dom_yellow.md3", 0, "domination/claim.wav", "", "Yellow team has captured a control point");
+ if(numteams > 3)
+ dom_spawnteam("Pink", NUM_TEAM_4-1, "models/domination/dom_pink.md3", 0, "domination/claim.wav", "", "Pink team has captured a control point");
+ dom_spawnteam("", 0, "models/domination/dom_unclaimed.md3", 0, "", "", "");
+}
+
+void dom_DelayedInit() // Do this check with a delay so we can wait for teams to be set up.
+{
+ // if no teams are found, spawn defaults
+ if(find(world, classname, "dom_team") == world || autocvar_g_domination_teams_override >= 2)
+ {
+ print("No ""dom_team"" entities found on this map, creating them anyway.\n");
+ dom_spawnteams();
+ }
+
+ ScoreRules_dom();
+}
+
+void dom_Initialize()
+{
+ precache_model("models/domination/dom_red.md3");
+ precache_model("models/domination/dom_blue.md3");
+ precache_model("models/domination/dom_yellow.md3");
+ precache_model("models/domination/dom_pink.md3");
+ precache_model("models/domination/dom_unclaimed.md3");
+ precache_sound("domination/claim.wav");
+
+ addstat(STAT_DOM_TOTAL_PPS, AS_FLOAT, dom_total_pps);
+ addstat(STAT_DOM_PPS_RED, AS_FLOAT, dom_pps_red);
+ addstat(STAT_DOM_PPS_BLUE, AS_FLOAT, dom_pps_blue);
+ if(c3 >= 0) addstat(STAT_DOM_PPS_YELLOW, AS_FLOAT, dom_pps_yellow);
+ if(c4 >= 0) addstat(STAT_DOM_PPS_PINK, AS_FLOAT, dom_pps_pink);
+
+ InitializeEntity(world, dom_DelayedInit, INITPRIO_GAMETYPE);
+}
+
+
+MUTATOR_DEFINITION(gamemode_domination)
+{
+ MUTATOR_HOOK(ClientConnect, dom_ClientConnect, CBC_ORDER_ANY);
+ MUTATOR_HOOK(HavocBot_ChooseRule, dom_BotRoles, 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.");
+ dom_Initialize();
+ }
+
+ MUTATOR_ONREMOVE
+ {
+ error("This is a game type and it cannot be removed at runtime.");
+ }
+
+ return 0;
+}
--- /dev/null
+// these are needed since mutators are compiled last
+
+// score rule declarations
+#define ST_DOM_TICKS 1
+#define SP_DOM_TICKS 4
+#define SP_DOM_TAKES 5
+
+// pps: points per second
+.float dom_total_pps;
+.float dom_pps_red;
+.float dom_pps_blue;
+.float dom_pps_yellow;
+.float dom_pps_pink;
+float total_pps;
+float pps_red;
+float pps_blue;
+float pps_yellow;
+float pps_pink;
+
+// capture declarations
+.float enemy_playerid;
+.entity sprite;
+.float captime;
\ No newline at end of file
return; // we still have active players on two or more teams, nobody won yet
entity e, winner;
- string teamname;
winner = world;
FOR_EACH_PLAYER(e)
if(winner != world) // just in case a winner wasn't found
{
- if(winner.team == COLOR_TEAM1)
- teamname = "^1Red Team";
- else if(winner.team == COLOR_TEAM2)
- teamname = "^4Blue Team";
- else if(winner.team == COLOR_TEAM3)
- teamname = "^3Yellow Team";
- else
- teamname = "^6Pink Team";
- FOR_EACH_PLAYER(e) {
- centerprint(e, strcat(teamname, "^5 wins the round, all other teams were frozen.\n"));
- }
- bprint(teamname, "^5 wins the round since all the other teams were frozen.\n");
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, APP_TEAM_NUM_4(winner.team, CENTER_FREEZETAG_ROUND_WIN_));
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(winner.team, INFO_FREEZETAG_ROUND_WIN_));
TeamScore_AddToTeam(winner.team, ST_SCORE, +1);
}
{
if(self.freezetag_frozen == 0 && self.health >= 1)
{
- if(self.team == COLOR_TEAM1)
+ if(self.team == NUM_TEAM_1)
--redalive;
- else if(self.team == COLOR_TEAM2)
+ else if(self.team == NUM_TEAM_2)
--bluealive;
- else if(self.team == COLOR_TEAM3)
+ else if(self.team == NUM_TEAM_3)
--yellowalive;
- else if(self.team == COLOR_TEAM4)
+ else if(self.team == NUM_TEAM_4)
--pinkalive;
--totalalive;
}
{
if(self.freezetag_frozen == 0)
{
- if(self.team == COLOR_TEAM1)
+ if(self.team == NUM_TEAM_1)
--redalive;
- else if(self.team == COLOR_TEAM2)
+ else if(self.team == NUM_TEAM_2)
--bluealive;
- else if(self.team == COLOR_TEAM3)
+ else if(self.team == NUM_TEAM_3)
--yellowalive;
- else if(self.team == COLOR_TEAM4)
+ else if(self.team == NUM_TEAM_4)
--pinkalive;
--totalalive;
if(frag_attacker == frag_target || frag_attacker == world)
{
if(frag_target.classname == STR_PLAYER)
- centerprint(frag_target, "^1You froze yourself.\n");
- bprint("^7", frag_target.netname, "^1 froze himself.\n");
+ Send_Notification(NOTIF_ONE, frag_target, MSG_CENTER, CENTER_FREEZETAG_SELF);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_FREEZETAG_SELF, frag_target.netname);
}
else
{
if(frag_target.classname == STR_PLAYER)
- centerprint(frag_target, strcat("^1You were frozen by ^7", frag_attacker.netname, ".\n"));
+ Send_Notification(NOTIF_ONE, frag_target, MSG_CENTER, CENTER_FREEZETAG_FROZEN, frag_attacker.netname);
if(frag_attacker.classname == STR_PLAYER)
- centerprint(frag_attacker, strcat("^2You froze ^7", frag_target.netname, ".\n"));
- bprint("^7", frag_target.netname, "^1 was frozen by ^7", frag_attacker.netname, ".\n");
+ Send_Notification(NOTIF_ONE, frag_attacker, MSG_CENTER, CENTER_FREEZETAG_FREEZE, frag_target.netname);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_FREEZETAG_FREEZE, frag_target.netname, frag_attacker.netname);
}
frag_target.health = 1; // "respawn" the player :P
}
if(warmup && time > warmup) // spawn too late, freeze player
{
- centerprint(self, "^1You spawned after the round started, you'll spawn as frozen.\n");
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_FREEZETAG_SPAWN_LATE);
freezetag_Freeze(world);
}
}
}
- if(n > 1)
- centerprint(self, strcat("^5You were revived by ^7", o.netname, "^5 et al.\n"));
- else
- centerprint(self, strcat("^5You were revived by ^7", o.netname, "^5.\n"));
- centerprint(o, strcat("^5You revived ^7", self.netname, "^5.\n"));
- if(n > 1)
- bprint("^7", o.netname, "^5 et al revived ^7", self.netname, "^5.\n");
- else
- bprint("^7", o.netname, "^5 revived ^7", self.netname, "^5.\n");
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_FREEZETAG_REVIVED, o.netname);
+ Send_Notification(NOTIF_ONE, o, MSG_CENTER, CENTER_FREEZETAG_REVIVE, self.netname);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_FREEZETAG_REVIVE, self.netname, o.netname);
}
// now find EVERY teammate within reviving radius, set their revive_progress values correct
freezetag_Initialize();
}
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ // we actually cannot roll back freezetag_Initialize here
+ // BUT: we don't need to! If this gets called, adding always
+ // succeeds.
+ }
+
MUTATOR_ONREMOVE
{
- error("This is a game type and it cannot be removed at runtime.");
+ print("This is a game type and it cannot be removed at runtime.");
+ return -1;
}
return 0;
self.velocity = '0 0 0';
self.movetype = MOVETYPE_NONE;
self.effects |= EF_NODRAW;
- self.touch = SUB_Null;
+ self.touch = func_null;
self.think = ka_TimeScoring;
self.nextthink = time + autocvar_g_keepaway_score_timeinterval;
self.takedamage = DAMAGE_NO;
// messages and sounds
ka_EventLog("pickup", other);
- Send_KillNotification(other.netname, "", "", KA_PICKUPBALL, MSG_KA);
- WriteByte(MSG_BROADCAST, SVC_CENTERPRINT);
- WriteString(MSG_BROADCAST, strcat(other.netname, "^7 has picked up the ball!"));
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_KEEPAWAY_PICKUP, other.netname);
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_KEEPAWAY_PICKUP, other.netname);
sound(self.owner, CH_TRIGGER, "keepaway/pickedup.wav", VOL_BASE, ATTN_NONE); // ATTN_NONE (it's a sound intended to be heard anywhere)
// scoring
// messages and sounds
ka_EventLog("dropped", plyr);
- Send_KillNotification(plyr.netname, "", "", KA_DROPBALL, MSG_KA);
- WriteByte(MSG_BROADCAST, SVC_CENTERPRINT);
- WriteString(MSG_BROADCAST, strcat(plyr.netname, "^7 has dropped the ball!"));
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_KEEPAWAY_DROPPED, plyr.netname);
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_KEEPAWAY_DROPPED, plyr.netname);
sound(other, CH_TRIGGER, "keepaway/dropped.wav", VOL_BASE, ATTN_NONE); // ATTN_NONE (it's a sound intended to be heard anywhere)
// scoring
}
else if(!frag_attacker.ballcarried)
if(autocvar_g_keepaway_noncarrier_warn)
- centerprint(frag_attacker, "Killing people while you don't have the ball gives no points!");
+ Send_Notification(NOTIF_ONE_ONLY, frag_attacker, MSG_CENTER, CENTER_KEEPAWAY_WARN);
if(frag_attacker.ballcarried) // add to amount of kills while ballcarrier
PlayerScore_Add(frag_attacker, SP_SCORE, autocvar_g_keepaway_score_killac);
ka_Initialize();
}
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ // we actually cannot roll back ka_Initialize here
+ // BUT: we don't need to! If this gets called, adding always
+ // succeeds.
+ }
+
MUTATOR_ONREMOVE
{
- error("This is a game type and it cannot be removed at runtime.");
+ print("This is a game type and it cannot be removed at runtime.");
+ return -1;
}
return 0;
vector KH_KEY_MAX = '10 10 3';
float KH_KEY_BRIGHTNESS = 2;
-string kh_Controller_Waitmsg;
float kh_no_radar_circles;
// kh_state
float kh_Team_ByID(float t)
{
- if(t == 0) return COLOR_TEAM1;
- if(t == 1) return COLOR_TEAM2;
- if(t == 2) return COLOR_TEAM3;
- if(t == 3) return COLOR_TEAM4;
+ if(t == 0) return NUM_TEAM_1;
+ if(t == 1) return NUM_TEAM_2;
+ if(t == 2) return NUM_TEAM_3;
+ if(t == 3) return NUM_TEAM_4;
return 0;
}
var kh_Think_t kh_Controller_Thinkfunc;
-void kh_Controller_SetThink(float t, string msg, float centerprint_duration, kh_Think_t func) // runs occasionaly
+void kh_Controller_SetThink(float t, kh_Think_t func) // runs occasionaly
{
kh_Controller_Thinkfunc = func;
kh_controller.cnt = ceil(t);
- if(kh_Controller_Waitmsg != "")
- strunzone(kh_Controller_Waitmsg);
- if(msg == "")
- kh_Controller_Waitmsg = "";
- else
- {
- kh_controller.kh_cp_duration = centerprint_duration;
- kh_Controller_Waitmsg = strzone(msg);
- }
if(t == 0)
kh_controller.nextthink = time; // force
}
-void kh_Controller_SetThink_NoMsg(float t, kh_Think_t func) // runs occasionaly
-{
- kh_Controller_SetThink(t, "", 0, func);
-}
-
+void kh_WaitForPlayers();
void kh_Controller_Think() // called a lot
{
- entity e;
if(intermission_running)
return;
if(self.cnt > 0)
- {
- if(kh_Controller_Waitmsg != "")
- {
- string s;
- if(substring(kh_Controller_Waitmsg, strlen(kh_Controller_Waitmsg)-1, 1) == " ")
- s = strcat(kh_Controller_Waitmsg, ftos(self.cnt));
- else
- s = kh_Controller_Waitmsg;
-
- //dprint(s, "\n");
-
- FOR_EACH_PLAYER(e)
- if(clienttype(e) == CLIENTTYPE_REAL)
- Send_CSQC_Centerprint_Generic(e, CPID_KH_MSG, s, self.kh_cp_duration, 0);
- }
- self.cnt -= 1;
- }
+ { if(self.think != kh_WaitForPlayers) { self.cnt -= 1; } }
else if(self.cnt == 0)
{
self.cnt -= 1;
WaypointSprite_AttachCarrier("", player, RADARICON_FLAGCARRIER, colormapPaletteColor(player.team - 1, 0));
player.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = kh_KeyCarrier_waypointsprite_visible_for_player;
WaypointSprite_UpdateRule(player.waypointsprite_attachedforcarrier, player.team, SPRITERULE_TEAMPLAY);
- if(player.team == COLOR_TEAM1)
+ if(player.team == NUM_TEAM_1)
WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-red", "keycarrier-friend", "keycarrier-red");
- else if(player.team == COLOR_TEAM2)
+ else if(player.team == NUM_TEAM_2)
WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-blue", "keycarrier-friend", "keycarrier-blue");
- else if(player.team == COLOR_TEAM3)
+ else if(player.team == NUM_TEAM_3)
WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-yellow", "keycarrier-friend", "keycarrier-yellow");
- else if(player.team == COLOR_TEAM4)
+ else if(player.team == NUM_TEAM_4)
WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-pink", "keycarrier-friend", "keycarrier-pink");
if(!kh_no_radar_circles)
WaypointSprite_Ping(player.waypointsprite_attachedforcarrier);
PlayerScore_Add(player, SP_KH_PICKUPS, 1);
}
key.kh_dropperteam = 0;
- bprint(player.netname, "^7 picked up the ", key.netname, "\n");
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_4(key, INFO_KEYHUNT_PICKUP_), player.netname);
kh_Key_AssignTo(key, player); // this also updates .kh_state
}
kh_Key_Remove(key);
kh_no_radar_circles = FALSE;
- kh_Controller_SetThink(autocvar_g_balance_keyhunt_delay_round, "Round starts in ", 1, kh_StartRound);
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_ARENA_ROUNDSTART, autocvar_g_balance_keyhunt_delay_round);
+ kh_Controller_SetThink(autocvar_g_balance_keyhunt_delay_round, kh_StartRound);
}
-void kh_WinnerTeam(float teem) // runs when a team wins
+void kh_WinnerTeam(float teem) // runs when a team wins // Samual: Teem?.... TEEM?!?! what the fuck is wrong with you people
{
// all key carriers get some points
vector firstorigin, lastorigin, midpoint;
}
first = TRUE;
+ string keyowner = "";
FOR_EACH_KH_KEY(key)
if(key.owner.kh_next == key)
{
if(!first)
- bprint("^7, ");
- bprint(key.owner.netname);
+ keyowner = strcat(keyowner, ", ");
+ keyowner = key.owner.netname;
first = FALSE;
}
- bprint("^7 captured the keys for the ", ColoredTeamName(teem), "\n");
+
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(teem, INFO_KEYHUNT_CAPTURE_), keyowner);
first = TRUE;
midpoint = '0 0 0';
te_lightning2(world, lastorigin, firstorigin);
}
midpoint = midpoint * (1 / kh_teams);
- te_customflash(midpoint, 1000, 1, TeamColor(teem) * 0.5 + '0.5 0.5 0.5'); // make the color >=0.5 in each component
+ te_customflash(midpoint, 1000, 1, Team_ColorRGB(teem) * 0.5 + '0.5 0.5 0.5'); // make the color >=0.5 in each component
play2all(kh_sound_capture);
kh_FinishRound();
// don't actually GIVE him the -nn points, just log
kh_Scores_Event(attacker, world, "push", autocvar_g_balance_keyhunt_score_push, 0);
PlayerScore_Add(attacker, SP_KH_PUSHES, 1);
- centerprint(attacker, "Your push is the best!");
- bprint("The ", ColoredTeamName(teem), "^7 could not take care of the ", lostkey.netname, "^7 when ", attacker.netname, "^7 came\n");
+ //centerprint(attacker, "Your push is the best!"); // does this really need to exist?
}
else
{
--j;
}
-
- bprint("The ", ColoredTeamName(teem), "^7 could not take care of the ", lostkey.netname, "\n");
}
+
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_4(lostkey, INFO_KEYHUNT_LOST_), lostkey.kh_previous_owner.netname);
+
play2all(kh_sound_destroy);
te_tarexplosion(lostkey.origin);
{
if(head.team == kh_interferemsg_team)
if(head.kh_next)
- Send_CSQC_Centerprint_Generic(head, CPID_KH_MSG, "All keys are in your team's hands!\n\nMeet the other key carriers ^1NOW^7!", 0, 0);
+ Send_Notification(NOTIF_ONE, head, MSG_CENTER, CENTER_KEYHUNT_MEET);
else
- Send_CSQC_Centerprint_Generic(head, CPID_KH_MSG, "All keys are in your team's hands!\n\nHelp the key carriers to meet!", 0, 0);
+ Send_Notification(NOTIF_ONE, head, MSG_CENTER, CENTER_KEYHUNT_HELP);
else
- Send_CSQC_Centerprint_Generic(head, CPID_KH_MSG, strcat("All keys are in the ", ColoredTeamName(kh_interferemsg_team), "^7's hands!\n\nInterfere ^1NOW^7!"), 0, 0);
+ Send_Notification(NOTIF_ONE, head, MSG_CENTER, APP_TEAM_NUM_4(kh_interferemsg_team, CENTER_KEYHUNT_INTERFERE_));
}
}
key.kh_dropperteam = 0;
key.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
setsize(key, KH_KEY_MIN, KH_KEY_MAX);
- key.colormod = TeamColor(initial_owner.team) * KH_KEY_BRIGHTNESS;
+ key.colormod = Team_ColorRGB(initial_owner.team) * KH_KEY_BRIGHTNESS;
key.reset = key_reset;
switch(initial_owner.team)
{
- case COLOR_TEAM1:
+ case NUM_TEAM_1:
key.netname = "^1red key";
break;
- case COLOR_TEAM2:
+ case NUM_TEAM_2:
key.netname = "^4blue key";
break;
- case COLOR_TEAM3:
+ case NUM_TEAM_3:
key.netname = "^3yellow key";
break;
- case COLOR_TEAM4:
+ case NUM_TEAM_4:
key.netname = "^6pink key";
break;
default:
key.kh_worldkeynext = kh_worldkeylist;
kh_worldkeylist = key;
- centerprint(initial_owner, strcat("You are starting with the ", key.netname, "\n")); // message to player at start of round
+ Send_Notification(NOTIF_ONE, initial_owner, MSG_CENTER, APP_TEAM_NUM_4(initial_owner.team, CENTER_KEYHUNT_START_));
WaypointSprite_Spawn("key-dropped", 0, 0, key, '0 0 1' * KH_KEY_WP_ZSHIFT, world, key.team, key, waypointsprite_attachedforcarrier, FALSE, RADARICON_FLAG, '0 1 1');
key.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = kh_Key_waypointsprite_visible_for_player;
kh_Scores_Event(player, key, "dropkey", 0, 0);
PlayerScore_Add(player, SP_KH_LOSSES, 1);
- bprint(player.netname, "^7 dropped the ", key.netname, "\n");
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_4(key, INFO_KEYHUNT_DROP_), player.netname);
+
kh_Key_AssignTo(key, world);
makevectors(player.v_angle);
key.velocity = W_CalculateProjectileVelocity(player.velocity, autocvar_g_balance_keyhunt_throwvelocity * v_forward, FALSE);
{
kh_Scores_Event(player, key, "losekey", 0, 0);
PlayerScore_Add(player, SP_KH_LOSSES, 1);
- bprint(player.netname, "^7 died and lost the ", key.netname, "\n");
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_4(key, INFO_KEYHUNT_LOST_), player.netname);
kh_Key_AssignTo(key, world);
makevectors('-1 0 0' * (45 + 45 * random()) + '0 360 0' * random());
key.velocity = W_CalculateProjectileVelocity(player.velocity, autocvar_g_balance_keyhunt_dropvelocity * v_forward, FALSE);
}
}
-string kh_CheckEnoughPlayers() // checks enough player are present, runs after every completed round
+float kh_CheckPlayers(float num)
{
- float i, players, teem;
- entity player;
- string result;
- result = "";
-
- // find a random player per team
- for(i = 0; i < kh_teams; ++i)
+ if(num < kh_teams)
{
- teem = kh_Team_ByID(i);
- players = 0;
- FOR_EACH_PLAYER(player)
- if(player.deadflag == DEAD_NO)
- if(!player.BUTTON_CHAT)
- if(player.team == teem)
+ float t_team = kh_Team_ByID(num);
+ float players = 0;
+ entity tmp_player;
+ FOR_EACH_PLAYER(tmp_player)
+ if(tmp_player.deadflag == DEAD_NO)
+ if(!tmp_player.BUTTON_CHAT)
+ if(tmp_player.team == t_team)
++players;
- if(players == 0)
- {
- if(result != "")
- result = strcat(result, ", ");
- result = strcat(result, ColoredTeamName(teem));
- }
+
+ if not(players) { return t_team; }
}
- return result;
+ return 0;
}
void kh_WaitForPlayers() // delay start of the round until enough players are present
{
- string teams_missing;
-
if(time < game_starttime)
{
- kh_Controller_SetThink_NoMsg(game_starttime - time + 0.1, kh_WaitForPlayers);
+ kh_Controller_SetThink(game_starttime - time + 0.1, kh_WaitForPlayers);
return;
}
- teams_missing = kh_CheckEnoughPlayers();
- if(teams_missing == "")
- kh_Controller_SetThink(autocvar_g_balance_keyhunt_delay_round, "Round starts in ", 1, kh_StartRound);
+ float p1 = kh_CheckPlayers(0), p2 = kh_CheckPlayers(1), p3 = kh_CheckPlayers(2), p4 = kh_CheckPlayers(3);
+ if not(p1 || p2 || p3 || p4)
+ {
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_ARENA_ROUNDSTART, autocvar_g_balance_keyhunt_delay_round);
+ kh_Controller_SetThink(autocvar_g_balance_keyhunt_delay_round, kh_StartRound);
+ }
else
- kh_Controller_SetThink(1, strcat("Waiting for players to join...\n\nNeed active players for: ", teams_missing), -1, kh_WaitForPlayers);
+ {
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_KEYHUNT_WAIT, p1, p2, p3, p4);
+ kh_Controller_SetThink(1, kh_WaitForPlayers);
+ }
}
void kh_EnableTrackingDevice() // runs after each round
{
- entity player;
-
- FOR_EACH_PLAYER(player)
- if(clienttype(player) == CLIENTTYPE_REAL)
- Send_CSQC_Centerprint_Generic_Expire(player, CPID_KH_MSG);
+ Kill_Notification(NOTIF_ALL, world, MSG_CENTER_CPID, CPID_KEYHUNT);
+ Kill_Notification(NOTIF_ALL, world, MSG_CENTER_CPID, CPID_KEYHUNT_OTHER);
kh_tracking_enabled = TRUE;
}
void kh_StartRound() // runs at the start of each round
{
- string teams_missing;
float i, players, teem;
entity player;
if(time < game_starttime)
{
- kh_Controller_SetThink_NoMsg(game_starttime - time + 0.1, kh_WaitForPlayers);
+ kh_Controller_SetThink(game_starttime - time + 0.1, kh_WaitForPlayers);
return;
}
- teams_missing = kh_CheckEnoughPlayers();
- if(teams_missing != "")
+ float p1 = kh_CheckPlayers(0), p2 = kh_CheckPlayers(1), p3 = kh_CheckPlayers(2), p4 = kh_CheckPlayers(3);
+ if(p1 || p2 || p3 || p4)
{
- kh_Controller_SetThink(1, strcat("Waiting for players to join...\n\nNeed active players for: ", teams_missing), -1, kh_WaitForPlayers);
+ kh_Controller_SetThink(1, kh_WaitForPlayers);
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_KEYHUNT_WAIT, p1, p2, p3, p4);
return;
}
-
- FOR_EACH_PLAYER(player)
- if(clienttype(player) == CLIENTTYPE_REAL)
- Send_CSQC_Centerprint_Generic_Expire(player, CPID_KH_MSG);
+
+ Kill_Notification(NOTIF_ALL, world, MSG_CENTER_CPID, CPID_KEYHUNT);
+ Kill_Notification(NOTIF_ALL, world, MSG_CENTER_CPID, CPID_KEYHUNT_OTHER);
for(i = 0; i < kh_teams; ++i)
{
}
kh_tracking_enabled = FALSE;
- kh_Controller_SetThink(autocvar_g_balance_keyhunt_delay_tracking, "Scanning frequency range...", -1, kh_EnableTrackingDevice);
+ Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_KEYHUNT_SCAN, autocvar_g_balance_keyhunt_delay_tracking);
+ kh_Controller_SetThink(autocvar_g_balance_keyhunt_delay_tracking, kh_EnableTrackingDevice);
}
float kh_HandleFrags(entity attacker, entity targ, float f) // adds to the player score
// make a KH entity for controlling the game
kh_controller = spawn();
kh_controller.think = kh_Controller_Think;
- kh_Controller_SetThink_NoMsg(0, kh_WaitForPlayers);
+ kh_Controller_SetThink(0, kh_WaitForPlayers);
setmodel(kh_controller, "models/keyhunt/key.md3");
kh_key_dropped = kh_controller.modelindex;
kh_Initialize();
}
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ // we actually cannot roll back kh_Initialize here
+ // BUT: we don't need to! If this gets called, adding always
+ // succeeds.
+ }
+
MUTATOR_ONREMOVE
{
- error("This is a game type and it cannot be removed at runtime.");
+ print("This is a game type and it cannot be removed at runtime.");
+ return -1;
}
return 0;
// used by arena.qc ready-restart:
typedef void(void) kh_Think_t;
void kh_StartRound();
-void kh_Controller_SetThink_NoMsg(float t, kh_Think_t func);
+void kh_Controller_SetThink(float t, kh_Think_t func);
{
if(self.ballcarried.teamtime && (self.ballcarried.teamtime < time))
{
- bprint("The ", ColoredTeamName(self.team), " held the ball for too long.\n");
+ bprint("The ", Team_ColoredFullName(self.team), " held the ball for too long.\n");
oldself = self;
self = self.ballcarried;
DropBall(self, self.owner.origin, '0 0 0');
ball.velocity = '0 0 0';
ball.movetype = MOVETYPE_NONE;
- ball.touch = SUB_Null;
+ ball.touch = func_null;
ball.effects |= EF_NOSHADOW;
ball.scale = 1; // scale down.
if(self.cnt < 2) // step 1
{
if(time == self.teamtime)
- bprint("The ", ColoredTeamName(self.team), " held the ball for too long.\n");
- self.touch = SUB_Null;
+ bprint("The ", Team_ColoredFullName(self.team), " held the ball for too long.\n");
+
+ self.touch = func_null;
self.movetype = MOVETYPE_NOCLIP;
self.velocity = '0 0 0'; // just in case?
if(!self.cnt)
{
LogNB("fault", ball.pusher);
if(nb_teams == 2)
- bprint(ColoredTeamName(otherteam), " gets a point due to ", pname, "^7's silliness.\n");
+ bprint(Team_ColoredFullName(otherteam), " gets a point due to ", pname, "^7's silliness.\n");
else
- bprint(ColoredTeamName(ball.team), " loses a point due to ", pname, "^7's silliness.\n");
+ bprint(Team_ColoredFullName(ball.team), " loses a point due to ", pname, "^7's silliness.\n");
pscore = -1;
}
else if(self.team == GOAL_OUT)
else //score
{
LogNB(strcat("goal:", ftos(self.team)), ball.pusher);
- bprint("Goaaaaal! ", pname, "^7 scored a point for the ", ColoredTeamName(ball.team), ".\n");
+ bprint("Goaaaaal! ", pname, "^7 scored a point for the ", Team_ColoredFullName(ball.team), ".\n");
pscore = 1;
}
ball.cnt = 1;
ball.think = ResetBall;
if(ball.classname == "nexball_basketball")
- ball.touch = football_touch; // better than SUB_Null: football control until the ball gets reset
+ ball.touch = football_touch; // better than func_null: football control until the ball gets reset
ball.nextthink = time + autocvar_g_nexball_delay_goal * (self.team != GOAL_OUT);
}
{
switch(e.team)
{
- case COLOR_TEAM1:
+ case NUM_TEAM_1:
if(!t_r)
{
nb_spawnteam("Red", e.team-1) ;
t_r = 1;
}
break;
- case COLOR_TEAM2:
+ case NUM_TEAM_2:
if(!t_b)
{
nb_spawnteam("Blue", e.team-1) ;
t_b = 1;
}
break;
- case COLOR_TEAM3:
+ case NUM_TEAM_3:
if(!t_y)
{
nb_spawnteam("Yellow", e.team-1);
t_y = 1;
}
break;
- case COLOR_TEAM4:
+ case NUM_TEAM_4:
if(!t_p)
{
nb_spawnteam("Pink", e.team-1) ;
void spawnfunc_nexball_redgoal(void)
{
- self.team = COLOR_TEAM1;
+ self.team = NUM_TEAM_1;
SpawnGoal();
}
void spawnfunc_nexball_bluegoal(void)
{
- self.team = COLOR_TEAM2;
+ self.team = NUM_TEAM_2;
SpawnGoal();
}
void spawnfunc_nexball_yellowgoal(void)
{
- self.team = COLOR_TEAM3;
+ self.team = NUM_TEAM_3;
SpawnGoal();
}
void spawnfunc_nexball_pinkgoal(void)
{
- self.team = COLOR_TEAM4;
+ self.team = NUM_TEAM_4;
SpawnGoal();
}
{
entity ball, attacker;
attacker = self.owner;
- //self.think = SUB_Null;
+ //self.think = func_null;
//self.enemy = world;
PROJECTILE_TOUCH;
missile.flags = FL_PROJECTILE;
}
-var const float() nullfunc;
float ball_customize()
{
if(!self.owner)
{
self.effects &~= EF_FLAME;
self.scale = 1;
- self.customizeentityforclient = nullfunc;
+ self.customizeentityforclient = func_null;
return TRUE;
}
precache_sound("misc/typehit.wav");
}
else if(req == WR_SETUP)
- weapon_setup(WEP_PORTO);
- else if(req == WR_SUICIDEMESSAGE)
- {
- w_deathtypestring = "is a weirdo";
- }
- else if(req == WR_KILLMESSAGE)
{
- w_deathtypestring = "got killed by #'s black magic";
+ weapon_setup(WEP_PORTO);
}
// No need to check WR_CHECKAMMO* or WR_AIM, it should always return TRUE
return TRUE;
InitializeEntity(world, nb_delayedinit, INITPRIO_GAMETYPE);
}
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ // we actually cannot roll back nb_delayedinit here
+ // BUT: we don't need to! If this gets called, adding always
+ // succeeds.
+ }
+
+ MUTATOR_ONREMOVE
+ {
+ print("This is a game type and it cannot be removed at runtime.");
+ return -1;
+ }
+
return 0;
}
float autocvar_g_onslaught_spawn_at_controlpoints;
float autocvar_g_onslaught_spawn_at_generator;
-float autocvar_g_onslaught_controlpoints_proxycap;
-float autocvar_g_onslaught_controlpoints_proxycap_distance = 512;
-float autocvar_g_onslaught_controlpoints_proxycap_dps = 100;
+float autocvar_g_onslaught_cp_proxydecap;
+var float autocvar_g_onslaught_cp_proxydecap_distance = 512;
+var float autocvar_g_onslaught_cp_proxydecap_dps = 100;
void onslaught_generator_updatesprite(entity e);
void onslaught_controlpoint_updatesprite(entity e);
.float lastshielded;
.float lastcaptured;
-.string model1, model2, model3;
-
entity ons_red_generator;
entity ons_blue_generator;
}
if(l.goalentity.classname == "onslaught_generator")
{
- if(l.goalentity.team == COLOR_TEAM1)
+ if(l.goalentity.team == NUM_TEAM_1)
l.enemy.isgenneighbor_red = TRUE;
- else if(l.goalentity.team == COLOR_TEAM2)
+ else if(l.goalentity.team == NUM_TEAM_2)
l.enemy.isgenneighbor_blue = TRUE;
}
else
{
- if(l.goalentity.team == COLOR_TEAM1)
+ if(l.goalentity.team == NUM_TEAM_1)
l.enemy.iscpneighbor_red = TRUE;
- else if(l.goalentity.team == COLOR_TEAM2)
+ else if(l.goalentity.team == NUM_TEAM_2)
l.enemy.iscpneighbor_blue = TRUE;
}
}
}
if(l.enemy.classname == "onslaught_generator")
{
- if(l.enemy.team == COLOR_TEAM1)
+ if(l.enemy.team == NUM_TEAM_1)
l.goalentity.isgenneighbor_red = TRUE;
- else if(l.enemy.team == COLOR_TEAM2)
+ else if(l.enemy.team == NUM_TEAM_2)
l.goalentity.isgenneighbor_blue = TRUE;
}
else
{
- if(l.enemy.team == COLOR_TEAM1)
+ if(l.enemy.team == NUM_TEAM_1)
l.goalentity.iscpneighbor_red = TRUE;
- else if(l.enemy.team == COLOR_TEAM2)
+ else if(l.enemy.team == NUM_TEAM_2)
l.goalentity.iscpneighbor_blue = TRUE;
}
}
{
if (l.iscaptured)
{
- if (l.team == COLOR_TEAM1) t1 = 1;
- if (l.team == COLOR_TEAM2) t2 = 1;
- if (l.team == COLOR_TEAM3) t3 = 1;
- if (l.team == COLOR_TEAM4) t4 = 1;
+ 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 = l.chain;
float onslaught_controlpoint_can_be_linked(entity cp, float t)
{
- if(t == COLOR_TEAM1)
+ if(t == NUM_TEAM_1)
{
if(cp.isgenneighbor_red)
return 2;
if(cp.iscpneighbor_red)
return 1;
}
- else if(t == COLOR_TEAM2)
+ else if(t == NUM_TEAM_2)
{
if(cp.isgenneighbor_blue)
return 2;
// if there's already an icon built, nothing happens
if(cp.team == t)
{
- a = onslaught_controlpoint_can_be_linked(cp, COLOR_TEAM1 + COLOR_TEAM2 - t);
+ a = onslaught_controlpoint_can_be_linked(cp, NUM_TEAM_1 + NUM_TEAM_2 - t);
if(a) // attackable by enemy?
return -2; // EMERGENCY!
return -1;
// free point
if(onslaught_controlpoint_can_be_linked(cp, t))
{
- a = onslaught_controlpoint_can_be_linked(cp, COLOR_TEAM1 + COLOR_TEAM2 - t);
+ a = onslaught_controlpoint_can_be_linked(cp, NUM_TEAM_1 + NUM_TEAM_2 - t);
if(a == 2)
return 4; // GET THIS ONE NOW!
else
}
else if (overtime_msg_time)
overtime_msg_time = 0;
-
+
if(!self.isshielded && self.wait < time)
{
self.wait = time + 5;
- FOR_EACH_PLAYER(e)
+ FOR_EACH_REALPLAYER(e)
{
if(e.team == self.team)
{
centerprint(e, "^1Your generator is NOT shielded!\n^7Re-capture controlpoints to shield it!");
soundto(MSG_ONE, e, CHAN_AUTO, "kh/alarm.wav", VOL_BASE, ATTN_NONE); // FIXME: Uniqe sound?
- }
- }
- }
+ }
+ }
+ }
}
}
if (time > self.pain_finished)
{
self.pain_finished = time + 10;
- bprint(ColoredTeamName(self.team), " generator under attack!\n");
+ bprint(Team_ColoredFullName(self.team), " generator under attack!\n");
play2team(self.team, "onslaught/generator_underattack.wav");
}
}
lh = ceil(self.lasthealth / 100) * 100;
h = ceil(self.health / 100) * 100;
if(lh != h)
- bprint(ColoredTeamName(self.team), " generator has less than ", ftos(h), " health remaining\n");
+ bprint(Team_ColoredFullName(self.team), " generator has less than ", ftos(h), " health remaining\n");
#endif
self.lasthealth = self.health;
}
else if not(inWarmupStage)
{
if (attacker == self)
- bprint(ColoredTeamName(self.team), " generator spontaneously exploded due to overtime!\n");
+ bprint(Team_ColoredFullName(self.team), " generator spontaneously exploded due to overtime!\n");
else
{
string t;
- t = ColoredTeamName(attacker.team);
- bprint(ColoredTeamName(self.team), " generator destroyed by ", t, "!\n");
+ 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 = SUB_Null; // won't do anything if hurt
+ 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
{
if(t == e.team)
{
- if(e.team == COLOR_TEAM1)
+ if(e.team == NUM_TEAM_1)
return "ons-gen-red";
- else if(e.team == COLOR_TEAM2)
+ else if(e.team == NUM_TEAM_2)
return "ons-gen-blue";
}
if(e.isshielded)
return "ons-gen-shielded";
- if(e.team == COLOR_TEAM1)
+ if(e.team == NUM_TEAM_1)
return "ons-gen-red";
- else if(e.team == COLOR_TEAM2)
+ else if(e.team == NUM_TEAM_2)
return "ons-gen-blue";
return "";
}
void onslaught_generator_updatesprite(entity e)
{
string s1, s2, s3;
- s1 = onslaught_generator_waypointsprite_for_team(e, COLOR_TEAM1);
- s2 = onslaught_generator_waypointsprite_for_team(e, COLOR_TEAM2);
+ 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);
e.lastshielded = e.isshielded;
if(e.lastshielded)
{
- if(e.team == COLOR_TEAM1 || e.team == COLOR_TEAM2)
+ 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 == COLOR_TEAM1 || e.team == COLOR_TEAM2)
+ 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');
a = onslaught_controlpoint_attackable(e, t);
if(a == 3 || a == 4) // ATTACK/TOUCH THIS ONE NOW
{
- if(e.team == COLOR_TEAM1)
+ if(e.team == NUM_TEAM_1)
return "ons-cp-atck-red";
- else if(e.team == COLOR_TEAM2)
+ 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 == COLOR_TEAM1)
+ if(e.team == NUM_TEAM_1)
return "ons-cp-dfnd-red";
- else if(e.team == COLOR_TEAM2)
+ 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 == COLOR_TEAM1)
+ if(e.team == NUM_TEAM_1)
return "ons-cp-red";
- else if(e.team == COLOR_TEAM2)
+ else if(e.team == NUM_TEAM_2)
return "ons-cp-blue";
}
else if(a == 2) // touch it
}
else
{
- if(e.team == COLOR_TEAM1)
+ if(e.team == NUM_TEAM_1)
return "ons-cp-red";
- else if(e.team == COLOR_TEAM2)
+ else if(e.team == NUM_TEAM_2)
return "ons-cp-blue";
else
return "ons-cp-neut";
void onslaught_controlpoint_updatesprite(entity e)
{
string s1, s2, s3;
- s1 = onslaught_controlpoint_waypointsprite_for_team(e, COLOR_TEAM1);
- s2 = onslaught_controlpoint_waypointsprite_for_team(e, COLOR_TEAM2);
+ 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);
float sh;
- sh = !(onslaught_controlpoint_can_be_linked(e, COLOR_TEAM1) || onslaught_controlpoint_can_be_linked(e, COLOR_TEAM2));
+ sh = !(onslaught_controlpoint_can_be_linked(e, NUM_TEAM_1) || onslaught_controlpoint_can_be_linked(e, NUM_TEAM_2));
if(e.lastteam != e.team + 2 || e.lastshielded != sh || e.iscaptured != e.lastcaptured)
{
}
if(e.lastshielded)
{
- if(e.team == COLOR_TEAM1 || e.team == COLOR_TEAM2)
+ if(e.team == NUM_TEAM_1 || e.team == NUM_TEAM_2)
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 == COLOR_TEAM1 || e.team == COLOR_TEAM2)
+ if(e.team == NUM_TEAM_1 || e.team == NUM_TEAM_2)
WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, colormapPaletteColor(e.team - 1, FALSE));
else
WaypointSprite_UpdateTeamRadar(e.sprite, RADARICON_CONTROLPOINT, '0.75 0.75 0.75');
setmodel(self, "models/onslaught/generator.md3");
setsize(self, '-52 -52 -14', '52 52 75');
- if (!self.noalign)
- droptofloor();
+ if(!self.noalign)
+ {
+ setorigin(self, self.origin + '0 0 20');
+ droptofloor();
+ }
WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
WaypointSprite_UpdateHealth(self.sprite, self.health);
if (!self.team)
objerror("team must be set");
- if(self.team == COLOR_TEAM1)
+ if(self.team == NUM_TEAM_1)
ons_red_generator = self;
- if(self.team == COLOR_TEAM2)
+ if(self.team == NUM_TEAM_2)
ons_blue_generator = self;
self.team_saved = self.team;
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, COLOR_TEAM2, SPRITERULE_TEAMPLAY);
+ WaypointSprite_UpdateRule(self.sprite, NUM_TEAM_2, SPRITERULE_TEAMPLAY);
WaypointSprite_UpdateMaxHealth(self.sprite, self.max_health);
WaypointSprite_UpdateHealth(self.sprite, self.health);
if (attacker.classname == "player")
{
nag = FALSE;
- if(self.team == COLOR_TEAM1)
+ if(self.team == NUM_TEAM_1)
{
if(time - ons_notification_time_team1 > 10)
{
ons_notification_time_team1 = time;
}
}
- else if(self.team == COLOR_TEAM2)
+ else if(self.team == NUM_TEAM_2)
{
if(time - ons_notification_time_team2 > 10)
{
pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
{
string t;
- t = ColoredTeamName(attacker.team);
- bprint(ColoredTeamName(self.team), " ", self.message, " control point destroyed by ", t, "\n");
+ 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);
{
entity oself;
self.nextthink = time + sys_frametime;
-
- if(autocvar_g_onslaught_controlpoints_proxycap)
- {
- float _enemy_count;
- float _friendly_count;
+
+ if(autocvar_g_onslaught_cp_proxydecap)
+ {
+ float _enemy_count = 0;
+ float _friendly_count = 0;
float _dist;
entity _player;
if(!_player.deadflag)
{
_dist = vlen(_player.origin - self.origin);
- if(_dist < autocvar_g_onslaught_controlpoints_proxycap_distance)
+ if(_dist < autocvar_g_onslaught_cp_proxydecap_distance)
{
if(_player.team == self.team)
++_friendly_count;
}
}
- _friendly_count = _friendly_count * (autocvar_g_onslaught_controlpoints_proxycap_dps * sys_frametime);
- _enemy_count = _enemy_count * (autocvar_g_onslaught_controlpoints_proxycap_dps * sys_frametime);
-
+ _friendly_count = _friendly_count * (autocvar_g_onslaught_cp_proxydecap_dps * sys_frametime);
+ _enemy_count = _enemy_count * (autocvar_g_onslaught_cp_proxydecap_dps * sys_frametime);
+
self.health = bound(0, self.health + (_friendly_count - _enemy_count), self.max_health);
if(self.health <= 0)
{
return;
}
}
-
+
if (time > self.pain_finished + 5)
{
if(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, ATTN_NORM);
- bprint(ColoredTeamName(self.team), " captured ", self.owner.message, " control point\n");
+ bprint(Team_ColoredFullName(self.team), " captured ", self.owner.message, " control point\n");
self.owner.iscaptured = TRUE;
WaypointSprite_UpdateMaxHealth(self.owner.sprite, self.max_health);
self.isshielded = TRUE;
self.enemy.solid = SOLID_NOT;
self.enemy.colormap = self.colormap;
- self.think = self.enemy.think = SUB_Null;
- self.nextthink = 0; // don't like SUB_Null :P
+ self.think = self.enemy.think = func_null;
+ self.nextthink = 0; // don't like func_null :P
setmodel(self, "models/onslaught/controlpoint_pad.md3");
//setsize(self, '-32 -32 0', '32 32 8');
"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 onslaught_controlpoint_think()
-{
- self.nextthink = time;
- //if(autocvar_g_onslaught_controlpoints_proxycap)
-
- float _enemy_count;
- float _friendly_count;
- float _dist;
- entity _player;
-
- FOR_EACH_PLAYER(_player)
- {
- if(!_player.deadflag)
- {
- _dist = vlen(_player.origin - self.origin);
- if(_dist < autocvar_g_onslaught_controlpoints_proxycap_distance)
- {
- if(_player.team == self.team)
- ++_friendly_count;
- else
- ++_enemy_count;
- }
- }
- }
-
- _friendly_count = _friendly_count * (autocvar_g_onslaught_controlpoints_proxycap_dps * sys_frametime);
- _enemy_count = _enemy_count * (autocvar_g_onslaught_controlpoints_proxycap_dps * sys_frametime);
-
- 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;
- }
-
- if(self.health == max_health)
- {
-
- }
-}
-*/
void spawnfunc_onslaught_controlpoint()
{
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)
- droptofloor();
-
- setorigin(self, self.origin);
+ 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;
+
// spawn shield model which indicates whether this can be damaged
self.enemy = spawn();
self.enemy.classname = "onslaught_controlpoint_shield";
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');
waypoint_spawnforitem(self);
WaypointSprite_SpawnFixed(string_null, self.origin + '0 0 128', self, sprite, RADARICON_NONE, '0 0 0');
- WaypointSprite_UpdateRule(self.sprite, COLOR_TEAM2, SPRITERULE_TEAMPLAY);
+ WaypointSprite_UpdateRule(self.sprite, NUM_TEAM_2, SPRITERULE_TEAMPLAY);
onslaught_updatelinks();
-
+
self.reset = onslaught_controlpoint_reset;
}
redpower = bluepower = 0;
if(self.goalentity.islinked)
{
- if(self.goalentity.team == COLOR_TEAM1)
+ if(self.goalentity.team == NUM_TEAM_1)
redpower = 1;
- else if(self.goalentity.team == COLOR_TEAM2)
+ else if(self.goalentity.team == NUM_TEAM_2)
bluepower = 1;
}
if(self.enemy.islinked)
{
- if(self.enemy.team == COLOR_TEAM1)
+ if(self.enemy.team == NUM_TEAM_1)
redpower = 2;
- else if(self.enemy.team == COLOR_TEAM2)
+ else if(self.enemy.team == NUM_TEAM_2)
bluepower = 2;
}
float cc;
if(redpower == 1 && bluepower == 2)
- cc = (COLOR_TEAM1 - 1) * 0x01 + (COLOR_TEAM2 - 1) * 0x10;
+ cc = (NUM_TEAM_1 - 1) * 0x01 + (NUM_TEAM_2 - 1) * 0x10;
else if(redpower == 2 && bluepower == 1)
- cc = (COLOR_TEAM1 - 1) * 0x10 + (COLOR_TEAM2 - 1) * 0x01;
+ cc = (NUM_TEAM_1 - 1) * 0x10 + (NUM_TEAM_2 - 1) * 0x01;
else if(redpower)
- cc = (COLOR_TEAM1 - 1) * 0x11;
+ cc = (NUM_TEAM_1 - 1) * 0x11;
else if(bluepower)
- cc = (COLOR_TEAM2 - 1) * 0x11;
+ cc = (NUM_TEAM_2 - 1) * 0x11;
else
cc = 0;
MUTATOR_HOOKFUNCTION(ons_BuildMutatorsPrettyString)
{
- ret_string = strcat(ret_string, ", Onslught");
+ ret_string = strcat(ret_string, ", Onslaught");
return 0;
}
RandomSelection_Init();
- if(self.team == COLOR_TEAM1)
+ if(self.team == NUM_TEAM_1)
RandomSelection_Add(ons_red_generator, 0, string_null, 1, 1);
- if(self.team == COLOR_TEAM2)
+ if(self.team == NUM_TEAM_2)
RandomSelection_Add(ons_blue_generator, 0, string_null, 1, 1);
entity _cp = findchain(classname, "onslaught_controlpoint"):
return 0;
float _close_to_home = ((random() > 0.5) ? TRUE : FALSE);
- entity _best, _trg_gen;
+ entity _best = world, _trg_gen = world;
float _score, _best_score = MAX_SHOT_DISTANCE;
RandomSelection_Init();
- if(self.team == COLOR_TEAM1)
+ if(self.team == NUM_TEAM_1)
{
if(!_close_to_home)
_trg_gen = ons_blue_generator;
_trg_gen = ons_red_generator;
}
- if(self.team == COLOR_TEAM2)
+ if(self.team == NUM_TEAM_2)
{
if(_close_to_home)
_trg_gen = ons_blue_generator;
if(!autocvar_g_onslaught_spawn_at_generator)
return 0;
- _trg_gen = ((self.team == COLOR_TEAM1) ? ons_red_generator : ons_blue_generator);
+ _trg_gen = ((self.team == NUM_TEAM_1) ? ons_red_generator : ons_blue_generator);
for(i = 0; i < 10; ++i)
{
MUTATOR_DEFINITION(gamemode_onslaught)
{
- //MUTATOR_HOOK(PlayerDies, nexball_BallDrop, CBC_ORDER_ANY);
- //MUTATOR_HOOK(MakePlayerObserver, nexball_BallDrop, CBC_ORDER_ANY);
- //MUTATOR_HOOK(ClientDisconnect, nexball_BallDrop, CBC_ORDER_ANY);
- //MUTATOR_HOOK(PlayerPreThink, nexball_PlayerPreThink, CBC_ORDER_ANY);
MUTATOR_HOOK(BuildMutatorsPrettyString, ons_BuildMutatorsPrettyString, CBC_ORDER_ANY);
MUTATOR_HOOK(BuildMutatorsString, ons_BuildMutatorsString, CBC_ORDER_ANY);
MUTATOR_HOOK(PlayerSpawn, ons_PlayerSpawn, CBC_ORDER_ANY);
//MUTATOR_HOOK(Spawn_Score, ons_Spawn_Score, CBC_ORDER_ANY);
-
+
MUTATOR_ONADD
{
- //InitializeEntity(world, nb_delayedinit, INITPRIO_GAMETYPE);
+ if(time > 1) // game loads at time 1
+ error("This is a game type and it cannot be added at runtime.");
+ }
+
+ MUTATOR_ONREMOVE
+ {
+ print("This is a game type and it cannot be removed at runtime.");
+ return -1;
}
return 0;
// the jump part of the dodge cannot be ramped
.float dodging_single_action;
-void dodging_Initialize() {
- // print("dodging_Initialize\n");
-
- self.last_FORWARD_KEY_time = 0;
- self.last_BACKWARD_KEY_time = 0;
- self.last_RIGHT_KEY_time = 0;
- self.last_LEFT_KEY_time = 0;
- self.last_dodging_time = 0;
- self.dodging_action = 0;
- self.dodging_velocity_gain = 0;
- self.dodging_single_action = 0;
- self.dodging_direction_x = 0;
- self.dodging_direction_y = 0;
-}
-
MUTATOR_HOOKFUNCTION(dodging_GetCvars) {
GetCvars_handleFloat(get_cvars_s, get_cvars_f, cvar_cl_dodging_timeout, "cl_dodging_timeout");
return 0;
if (autocvar_sv_dodging_sound == 1)
PlayerSound(playersound_jump, CH_PLAYER, VOICETYPE_PLAYERSOUND);
- setanim(self, self.anim_jump, TRUE, FALSE, TRUE);
+ animdecide_setaction(self, ANIMACTION_JUMP, TRUE);
self.dodging_single_action = 0;
}
MUTATOR_ONADD
{
g_dodging = 1;
- dodging_Initialize();
}
// this just turns off the cvar.
- MUTATOR_ONREMOVE
- {
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
g_dodging = 0;
}
+ MUTATOR_ONREMOVE
+ {
+ }
+
return 0;
}
if(nt_IsNewToy(i))
get_weaponinfo(i).spawnflags &~= WEP_FLAG_MUTATORBLOCKED;
}
+
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ float i;
+ for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+ if(nt_IsNewToy(i))
+ get_weaponinfo(i).spawnflags |= WEP_FLAG_MUTATORBLOCKED;
+ }
+
MUTATOR_ONREMOVE
{
- error("This cannot be removed at runtime\n");
+ print("This cannot be removed at runtime\n");
+ return -1;
}
return 0;
if(dt >= 1 && dt <= 5)
self.nix_lastinfotime = -42;
else
- Send_CSQC_Centerprint_Generic(self, CPID_NIX_WPNCHANGE, strcat("^2Active weapon: ^3", W_Name(nix_weapon)), 0, 0);
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_NEWWEAPON, nix_weapon);
weapon_action(nix_weapon, WR_RESETPLAYER);
{
self.nix_lastinfotime = dt; // initial value 0 should count as "not seen"
if(dt >= 1 && dt <= 5)
- Send_CSQC_Centerprint_Generic(self, CPID_NIX_WPNCHANGE, strcat("^3%d^2 seconds until weapon change...\n\nNext weapon: ^3", W_Name(nix_nextweapon)), 1, dt);
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_COUNTDOWN, nix_nextweapon, dt);
}
if(!(self.items & IT_UNLIMITED_WEAPON_AMMO) && time > self.nix_nextincr)
NIX_precache();
}
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ // nothing to roll back
+ }
+
MUTATOR_ONREMOVE
{
// as the PlayerSpawn hook will no longer run, NIX is turned off by this!
--- /dev/null
+.vector spawn_origin, spawn_angles;
+
+void physical_item_think()
+{
+ self.nextthink = time;
+
+ self.alpha = self.owner.alpha; // apply fading and ghosting
+
+ if(!self.cnt) // map item, not dropped
+ {
+ // copy ghost item properties
+ self.colormap = self.owner.colormap;
+ self.colormod = self.owner.colormod;
+ self.glowmod = self.owner.glowmod;
+
+ // if the item is not spawned, make sure the invisible / ghost item returns to its origin and stays there
+ if(autocvar_g_physical_items_reset)
+ {
+ if(self.owner.nextthink > time) // awaiting respawn
+ {
+ setorigin(self, self.spawn_origin);
+ self.angles = self.spawn_angles;
+ self.solid = SOLID_NOT;
+ self.movetype = MOVETYPE_NONE;
+ }
+ else
+ {
+ self.solid = SOLID_CORPSE;
+ self.movetype = MOVETYPE_PHYSICS;
+ }
+ }
+ }
+
+ if(!self.owner.modelindex)
+ remove(self); // the real item is gone, remove this
+}
+
+void physical_item_touch()
+{
+ if(!self.cnt) // not for dropped items
+ if (ITEM_TOUCH_NEEDKILL())
+ {
+ setorigin(self, self.spawn_origin);
+ self.angles = self.spawn_angles;
+ }
+}
+
+void physical_item_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+ if(!self.cnt) // not for dropped items
+ if(ITEM_DAMAGE_NEEDKILL(deathtype))
+ {
+ setorigin(self, self.spawn_origin);
+ self.angles = self.spawn_angles;
+ }
+}
+
+MUTATOR_HOOKFUNCTION(item_spawning)
+{
+ if(self.owner == world && autocvar_g_physical_items <= 1)
+ return FALSE;
+ if (self.spawnflags & 1) // floating item
+ return FALSE;
+
+ // The actual item can't be physical and trigger at the same time, so make it invisible and use a second entity for physics.
+ // Ugly hack, but unless SOLID_TRIGGER is gotten to work with MOVETYPE_PHYSICS in the engine it can't be fixed.
+ entity wep;
+ wep = spawn();
+ setmodel(wep, self.model);
+ setsize(wep, self.mins, self.maxs);
+ setorigin(wep, self.origin);
+ wep.angles = self.angles;
+ wep.velocity = self.velocity;
+
+ wep.owner = self;
+ wep.solid = SOLID_CORPSE;
+ wep.movetype = MOVETYPE_PHYSICS;
+ wep.takedamage = DAMAGE_AIM;
+ wep.effects |= EF_NOMODELFLAGS; // disable the spinning
+ wep.colormap = self.owner.colormap;
+ wep.glowmod = self.owner.glowmod;
+ wep.damageforcescale = autocvar_g_physical_items_damageforcescale;
+ wep.dphitcontentsmask = self.dphitcontentsmask;
+ wep.cnt = (self.owner != world);
+
+ wep.think = physical_item_think;
+ wep.nextthink = time;
+ wep.touch = physical_item_touch;
+ wep.event_damage = physical_item_damage;
+
+ wep.spawn_origin = self.origin;
+ wep.spawn_angles = self.angles;
+
+ self.effects |= EF_NODRAW; // hide the original weapon
+ self.movetype = MOVETYPE_FOLLOW;
+ self.aiment = wep; // attach the original weapon
+
+ return FALSE;
+}
+
+MUTATOR_DEFINITION(mutator_physical_items)
+{
+ MUTATOR_HOOK(Item_Spawn, item_spawning, CBC_ORDER_ANY);
+
+ // check if we have a physics engine
+ MUTATOR_ONADD
+ {
+ if not(autocvar_physics_ode && checkextension("DP_PHYSICS_ODE"))
+ {
+ dprint("Warning: Physical items are enabled but no physics engine can be used. Reverting to old items.\n");
+ return -1;
+ }
+ }
+
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ // nothing to roll back
+ }
+
+ MUTATOR_ONREMOVE
+ {
+ print("This cannot be removed at runtime\n");
+ return -1;
+ }
+
+ return 0;
+}
if(argv(1) == "help")
{
string _aspeco;
- _aspeco = strcat(_aspeco, "^7 superspec_itemfilter ^3\"item_classname1 item_classname2\"^7 only show thise items when ^2superspec ^3item_message^7 is on\n");
+ _aspeco = "^7 superspec_itemfilter ^3\"item_classname1 item_classname2\"^7 only show thise items when ^2superspec ^3item_message^7 is on\n";
_aspeco = strcat(_aspeco, "^3 clear^7 Remove the filter (show all pickups)\n");
_aspeco = strcat(_aspeco, "^3 show ^7 Display current filter\n");
superspec_msg("^3superspec_itemfilter help:\n\n\n", "\n^3superspec_itemfilter help:\n", self, _aspeco, 1);
}
float i;
float l = tokenize_console(self.superspec_itemfilter);
- string _msg;
+ string _msg = "";
for(i = 0; i < l; ++i)
_msg = strcat(_msg, "^3#", ftos(i), " ^7", argv(i), "\n");
//_msg = sprintf("^3#%d^7 %s\n%s", i, _msg, argv(i));
if(cmd_argc > 1)
{
- float i, _bits, _start = 1;
+ float i, _bits = 0, _start = 1;
if(argv(1) == "help")
{
- _aspeco = "";
- _aspeco = strcat(_aspeco, "use cmd superspec [option] [on|off] to set options\n\n");
+ _aspeco = "use cmd superspec [option] [on|off] to set options\n\n";
_aspeco = strcat(_aspeco, "^3 silent ^7(short^5 si^7) supress ALL mesagess from superspectate.\n");
_aspeco = strcat(_aspeco, "^3 verrbose ^7(short^5 ve^7) makes superspectate print some additional information.\n");
_aspeco = strcat(_aspeco, "^3 item_message ^7(short^5 im^7) makes superspectate print items that was picked up.\n");
}
+ _aspeco = "";
OPTIONINFO(self.superspec_flags, _aspeco, SSF_SILENT, "Silent", "silent", "si");
OPTIONINFO(self.superspec_flags, _aspeco, SSF_VERBOSE, "Verbose", "verbose", "ve");
OPTIONINFO(self.superspec_flags, _aspeco, SSF_ITEMMSG, "Item pickup messages", "item_message", "im");
{
if(argv(1) == "help")
{
- _aspeco = "";
- _aspeco = strcat(_aspeco, "use cmd autospec [option] [on|off] to set options\n\n");
+ _aspeco = "use cmd autospec [option] [on|off] to set options\n\n";
_aspeco = strcat(_aspeco, "^3 strength ^7(short^5 st^7) for automatic spectate on strength powerup\n");
_aspeco = strcat(_aspeco, "^3 shield ^7(short^5 sh^7) for automatic spectate on shield powerup\n");
_aspeco = strcat(_aspeco, "^3 mega_health ^7(short^5 mh^7) for automatic spectate on mega health\n");
return TRUE;
}
- float i, _bits, _start = 1;
+ float i, _bits = 0, _start = 1;
if(argv(1) == "clear")
{
self.autospec_flags = 0;
}
}
+ _aspeco = "";
OPTIONINFO(self.autospec_flags, _aspeco, ASF_STRENGTH, "Strength", "strength", "st");
OPTIONINFO(self.autospec_flags, _aspeco, ASF_SHIELD, "Shield", "shield", "sh");
OPTIONINFO(self.autospec_flags, _aspeco, ASF_MEGA_HP, "Mega Health", "mega_health", "mh");
return TRUE;
entity _player;
- float _team;
+ float _team = 0;
if(cmd_argc == 2)
{
if(argv(1) == "red")
- _team = COLOR_TEAM1;
+ _team = NUM_TEAM_1;
else
- _team = COLOR_TEAM2;
+ _team = NUM_TEAM_2;
}
FOR_EACH_PLAYER(_player)
//MUTATOR_HOOK(MakePlayerObserver, superspec_MakePlayerObserver, CBC_ORDER_ANY);
MUTATOR_HOOK(ClientDisconnect, superspec_ClientDisconnect, CBC_ORDER_ANY);
- MUTATOR_ONADD
- {
- }
-
- MUTATOR_ONREMOVE
- {
- }
-
return 0;
}
else
{
// otherwise: each hit gets damage back
- frag_attacker.health += damage_take;
+ frag_attacker.health = frag_attacker.health + bound(0, damage_take, self.health);
}
return 0;
}
MUTATOR_DECLARATION(gamemode_ctf);
MUTATOR_DECLARATION(gamemode_nexball);
MUTATOR_DECLARATION(gamemode_onslaught);
+MUTATOR_DECLARATION(gamemode_domination);
MUTATOR_DECLARATION(mutator_dodging);
MUTATOR_DECLARATION(mutator_invincibleprojectiles);
MUTATOR_DECLARATION(mutator_nix);
MUTATOR_DECLARATION(mutator_rocketflying);
MUTATOR_DECLARATION(mutator_spawn_near_teammate);
+MUTATOR_DECLARATION(mutator_physical_items);
MUTATOR_DECLARATION(mutator_vampire);
MUTATOR_DECLARATION(mutator_superspec);
{
// load object properties, and spawn a new object with them
float n, i;
- entity e, parent;
+ entity e = world, parent = world;
// separate objects between the ; symbols
n = tokenizebyseparator(s, "; ");
for(i = 0; i < n; ++i)
{
float argv_num;
- string tagname;
+ string tagname = string_null;
argv_num = 0;
tokenize_console(port_string[i]);
e = sandbox_ObjectSpawn(database);
sandbox_Database_Load();
}
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ // nothing to roll back
+ }
+
+ MUTATOR_ONREMOVE
+ {
+ // nothing to remove
+ }
+
return FALSE;
}
#endif
var vector pathlib_movenode(vector start,vector end,float doedge);
-vector pathlib_wateroutnode(vector start,vector end)
+vector pathlib_wateroutnode(vector start,vector end,float doedge)
{
vector surface;
return end;
}
-vector pathlib_swimnode(vector start,vector end)
+vector pathlib_swimnode(vector start,vector end,float doedge)
{
pathlib_movenode_goodnode = 0;
float pathlib_makenode_adaptive(entity parent,vector start, vector to, vector goal,float cost)
{
entity node;
- float h,g,f,doedge;
+ float h,g,f,doedge = 0;
vector where;
++pathlib_searched_cnt;
-vector pathlib_wateroutnode(vector start,vector end)
+vector pathlib_wateroutnode(vector start,vector end, float doedge)
{
vector surface;
return end;
}
-vector pathlib_swimnode(vector start,vector end)
+vector pathlib_swimnode(vector start,vector end, float doedge)
{
pathlib_movenode_goodnode = 0;
end_y = fsnap(end_y, pathlib_gridsize);
if(pointcontents(end) == CONTENT_EMPTY)
- return pathlib_wateroutnode( start, end);
+ return pathlib_wateroutnode( start, end, doedge);
tracebox(start, movenode_boxmin,movenode_boxmax, end, MOVE_WORLDONLY, self);
if(trace_fraction == 1)
return end;
}
-vector pathlib_flynode(vector start,vector end)
+vector pathlib_flynode(vector start,vector end, float doedge)
{
pathlib_movenode_goodnode = 0;
vector movenode_boxmin;
float pathlib_movenode_goodnode;
-vector pathlib_wateroutnode(vector start, vector end);
-vector pathlib_swimnode(vector start, vector end);
-vector pathlib_flynode(vector start, vector end);
+vector pathlib_wateroutnode(vector start, vector end, float doedge);
+vector pathlib_swimnode(vector start, vector end, float doedge);
+vector pathlib_flynode(vector start, vector end, float doedge);
vector pathlib_walknode(vector start, vector end, float doedge);
var vector pathlib_movenode(vector start, vector end, float doedge);
PlayerStats_AddEvent(PLAYERSTATS_MATCHES);
PlayerStats_AddEvent(PLAYERSTATS_JOINS);
PlayerStats_AddEvent(PLAYERSTATS_SCOREBOARD_VALID);
+ PlayerStats_AddEvent(PLAYERSTATS_SCOREBOARD_POS);
PlayerStats_AddEvent(PLAYERSTATS_RANK);
// accuracy stats
else if(clienttype(e) == CLIENTTYPE_BOT)
s = sprintf("bot#%g#%s", skill, e.cleanname);
- if(!s || find(world, playerstats_id, s)) // already have one of the ID - next one can't be tracked then!
+ if((s == "") || find(world, playerstats_id, s)) // already have one of the ID - next one can't be tracked then!
{
if(clienttype(e) == CLIENTTYPE_BOT)
s = sprintf("bot#%d", e.playerid);
}
}
-void PlayerStats_Event(entity e, string event_id, float value)
+float PlayerStats_Event(entity e, string event_id, float value)
{
- if(!e.playerstats_id || playerstats_db < 0)
- return;
+ if((e.playerstats_id == "") || playerstats_db < 0)
+ return 0;
string key;
float val;
val = stof(db_get(playerstats_db, key));
val += value;
db_put(playerstats_db, key, ftos(val));
+ return val;
}
void PlayerStats_TeamScore(float t, string event_id, float value) // TODO: doesn't this remain unused?
acc-<weapon netname>-cnt-fired: amount of fired shots
acc-<weapon netname>-frags: amount of frags dealt by weapon
- Response format (not used yet):
-
- V: format version (always 1) - this MUST be the first line!
- #: comment (MUST be ignored by any parser)
- R: release information on the XonStat server
- T: current time
- S: in case of a stats submit request, the human readable xonstat URL for the submitted match
- P: player ID of an existing player; this also sets the owner for all following "n", "e" and "t" lines (lower case!)
- e: followed by an event name, a space, and the event count/score, and - if this is a reply to a stats submit request - a space, and the delta of the event count/score caused by this match
- event names can be the same as above (they then are either sums, or minimum/maximum values, depending on context), as well as:
- elo: current Elo calculated by the stats server
- rank <number>: global rank of player for this game type (for stats submit requests)
- rank-<gametype> <number>: global rank of player for any game type (for non stats submit requests)
- not all events need to be included, of course
- if an event is counted additively from unprocessed submitted data, it should not be sent as part of stats submit response
- achievement-<achievementname> events may be generated by the xonstat server and reported as part of stats submit responses!
+ Response format (not used yet): see https://gist.github.com/4284222
*/
void PlayerStats_ready(entity fh, entity pass, float status)
switch(status)
{
case URL_READY_CANWRITE:
- url_fputs(fh, "V 5\n");
+ url_fputs(fh, "V 6\n");
#ifdef WATERMARK
- url_fputs(fh, sprintf("R %s\n", WATERMARK()));
+ url_fputs(fh, sprintf("R %s\n", WATERMARK));
#endif
url_fputs(fh, sprintf("T %s.%06d\n", strftime(FALSE, "%s"), floor(random() * 1000000)));
url_fputs(fh, sprintf("G %s\n", GetGametype()));
{
if(playerstats_db < 0)
return;
- if(!p.playerstats_id || playerstats_db < 0)
+ if((p.playerstats_id == "") || playerstats_db < 0)
return;
p.playerstats_addedglobalinfo = TRUE;
}
db_put(playerstats_db, sprintf("%s:_playerid", p.playerstats_id), ftos(p.playerid));
-
+
if(p.cvar_cl_allow_uid2name == 1 || clienttype(p) == CLIENTTYPE_BOT)
db_put(playerstats_db, sprintf("%s:_netname", p.playerstats_id), p.netname);
- if(teamplay)
+ if(teamplay)
db_put(playerstats_db, sprintf("%s:_team", p.playerstats_id), ftos(p.team));
if(stof(db_get(playerstats_db, sprintf("%d:%s", p.playerstats_id, PLAYERSTATS_ALIVETIME))) > 0)
PlayerStats_Accuracy(p);
+ if(clienttype(p) == CLIENTTYPE_REAL)
+ {
+ if(p.latency_cnt)
+ {
+ float latency = (p.latency_sum / p.latency_cnt);
+ if(latency) { PlayerStats_Event(p, PLAYERSTATS_AVGLATENCY, latency); }
+ }
+ }
+
strunzone(p.playerstats_id);
p.playerstats_id = string_null;
}
+.float scoreboard_pos;
void PlayerStats_EndMatch(float finished)
{
- entity p, winner;
- winner = PlayerScore_Sort(score_dummyfield);
- FOR_EACH_CLIENT(p) // spectators intentionally not included
+ entity p;
+ PlayerScore_Sort(score_dummyfield, 0, 0, 0);
+ PlayerScore_Sort(scoreboard_pos, 1, 1, 1);
+ FOR_EACH_CLIENT(p)
{
- //PlayerStats_Accuracy(p); // stats are already written with PlayerStats_AddGlobalInfo(entity), don't double them up.
-
- if((g_arena || g_lms || g_ca) && (p.alivetime <= 0)) { continue; }
- else if(p.classname != "player") { continue; }
-
- float latency = (p.latency_sum / p.latency_cnt);
- if(latency) { PlayerStats_Event(p, PLAYERSTATS_AVGLATENCY, latency); }
-
- PlayerScore_PlayerStats(p);
+ // add personal score rank
+ PlayerStats_Event(p, PLAYERSTATS_RANK, p.score_dummyfield);
+
+ if(!p.scoreboard_pos)
+ continue;
+
+ // scoreboard is valid!
PlayerStats_Event(p, PLAYERSTATS_SCOREBOARD_VALID, 1);
+
+ // add scoreboard position
+ PlayerStats_Event(p, PLAYERSTATS_SCOREBOARD_POS, p.scoreboard_pos);
+
+ // add scoreboard data
+ PlayerScore_PlayerStats(p);
+
+ // if the match ended normally, add winning info
if(finished)
{
PlayerStats_Event(p, PLAYERSTATS_WINS, p.winning);
PlayerStats_Event(p, PLAYERSTATS_MATCHES, 1);
- PlayerStats_Event(p, PLAYERSTATS_RANK, p.score_dummyfield);
}
}
}
string PLAYERSTATS_JOINS = "joins";
string PLAYERSTATS_SCOREBOARD_VALID = "scoreboardvalid";
string PLAYERSTATS_RANK = "rank";
+string PLAYERSTATS_SCOREBOARD_POS = "scoreboardpos";
string PLAYERSTATS_TOTAL = "total-";
string PLAYERSTATS_SCOREBOARD = "scoreboard-";
void PlayerStats_AddEvent(string event_id);
// call on each event to track, or at player disconnect OR match end for "global stuff"
-void PlayerStats_Event(entity e, string event_id, float value);
+float PlayerStats_Event(entity e, string event_id, float value);
// add a team score
void PlayerStats_TeamScore(float t, string event_id, float value);
{
portal.skin = 2;
portal.solid = SOLID_NOT;
- portal.touch = SUB_Null;
- portal.think = SUB_Null;
+ portal.touch = func_null;
+ portal.think = func_null;
portal.effects = 0;
portal.nextthink = 0;
portal.takedamage = DAMAGE_NO;
{
portal.skin = 2;
portal.solid = SOLID_NOT;
- portal.touch = SUB_Null;
- portal.think = SUB_Null;
+ portal.touch = func_null;
+ portal.think = func_null;
portal.effects = EF_ADDITIVE;
portal.nextthink = 0;
portal.takedamage = DAMAGE_YES;
{
portal.skin = 1;
portal.solid = SOLID_NOT;
- portal.touch = SUB_Null;
- portal.think = SUB_Null;
+ portal.touch = func_null;
+ portal.think = func_null;
portal.effects = EF_STARDUST | EF_BLUE;
portal.nextthink = 0;
portal.takedamage = DAMAGE_YES;
../warpzonelib/server.qh
../common/constants.qh
+../common/teams.qh
../common/util.qh
+../common/counting.qh
../common/items.qh
../common/explosion_equation.qh
../common/urllib.qh
../common/command/generic.qh
../common/command/shared_defs.qh
../common/net_notice.qh
+../common/animdecide.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_ctf.qh
+mutators/gamemode_domination.qh
mutators/gamemode_keyhunt.qh // TODO fix this
mutators/gamemode_keepaway.qh
mutators/gamemode_nexball.qh
antilag.qc
//ctf.qc
-domination.qc
+//domination.qc
//mode_onslaught.qc
//nexball.qc
g_hook.qc
mutators/base.qc
mutators/gamemode_ctf.qc
+mutators/gamemode_domination.qc
mutators/gamemode_freezetag.qc
mutators/gamemode_keyhunt.qc
mutators/gamemode_keepaway.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
../warpzonelib/util_server.qc
../warpzonelib/server.qc
+../common/animdecide.qc
../common/util.qc
+../common/notifications.qc
../common/if-this-file-errors-scroll-up-and-fix-the-warnings.fteqccfail
}
float oldrec;
- string recorddifference, oldrec_holder;
+ string oldrec_holder;
if (player_prevpos && (player_prevpos < newpos || !newpos))
{
oldrec = race_readTime(GetMapname(), player_prevpos);
- recorddifference = strcat(" ^1[+", TIME_ENCODED_TOSTRING(t - oldrec), "]");
- bprint(mynetname, "^7 couldn't break their ", race_placeName(player_prevpos), " place record of ", TIME_ENCODED_TOSTRING(oldrec), recorddifference, "\n");
race_SendStatus(0, e); // "fail"
- Send_KillNotification(e.netname, TIME_ENCODED_TOSTRING(t), "", RACE_FAIL, MSG_RACE);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_RACE_FAIL_RANKED, mynetname, player_prevpos, t, oldrec);
return;
} else if (!newpos) { // no ranking, time worse than the worst ranked
- recorddifference = strcat(" ^1[+", TIME_ENCODED_TOSTRING(t - race_readTime(GetMapname(), RANKINGS_CNT)), "]");
- bprint(mynetname, "^7 couldn't break the ", race_placeName(RANKINGS_CNT), " place record of ", TIME_ENCODED_TOSTRING(race_readTime(GetMapname(), RANKINGS_CNT)), recorddifference, "\n");
+ oldrec = race_readTime(GetMapname(), RANKINGS_CNT);
race_SendStatus(0, e); // "fail"
- Send_KillNotification(e.netname, TIME_ENCODED_TOSTRING(t), "", RACE_FAIL, MSG_RACE);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_RACE_FAIL_UNRANKED, mynetname, RANKINGS_CNT, t, oldrec);
return;
}
// if the player does not have a UID we can unfortunately not store the record, as the rankings system relies on UIDs
if(myuid == "")
{
- bprint(mynetname, "^1 scored a new record with ^7", TIME_ENCODED_TOSTRING(t), "^1, but lacks a UID, so the record will unfortunately be lost.\n");
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_RACE_NEW_MISSING_UID, mynetname, t);
return;
}
if(rankings_reply)
strunzone(rankings_reply);
rankings_reply = strzone(getrankings());
- if(newpos == 1) {
- if(newpos == player_prevpos) {
- recorddifference = strcat(" ^2[-", TIME_ENCODED_TOSTRING(oldrec - t), "]");
- bprint(mynetname, "^1 improved their 1st place record with ", TIME_ENCODED_TOSTRING(t), recorddifference, "\n");
- } else if (oldrec == 0) {
- bprint(mynetname, "^1 set the 1st place record with ", TIME_ENCODED_TOSTRING(t), "\n");
- } else {
- recorddifference = strcat(" ^2[-", TIME_ENCODED_TOSTRING(oldrec - t), "]");
- bprint(mynetname, "^1 broke ", oldrec_holder, "^1's 1st place record with ", strcat(TIME_ENCODED_TOSTRING(t), recorddifference, "\n"));
- }
- race_SendStatus(3, e); // "new server record"
- Send_KillNotification(e.netname, TIME_ENCODED_TOSTRING(t), "", RACE_SERVER_RECORD, MSG_RACE);
- } else {
- if(newpos == player_prevpos) {
- recorddifference = strcat(" ^2[-", TIME_ENCODED_TOSTRING(oldrec - t), "]");
- bprint(mynetname, "^5 improved their ", race_placeName(newpos), " ^5place record with ", TIME_ENCODED_TOSTRING(t), recorddifference, "\n");
- race_SendStatus(1, e); // "new time"
- Send_KillNotification(e.netname, TIME_ENCODED_TOSTRING(t), "", RACE_NEW_TIME, MSG_RACE);
- } else if (oldrec == 0) {
- bprint(mynetname, "^2 set the ", race_placeName(newpos), " ^2place record with ", TIME_ENCODED_TOSTRING(t), "\n");
- race_SendStatus(2, e); // "new rank"
- Send_KillNotification(e.netname, TIME_ENCODED_TOSTRING(t), "", RACE_NEW_RANK, MSG_RACE);
- } else {
- recorddifference = strcat(" ^2[-", TIME_ENCODED_TOSTRING(oldrec - t), "]");
- bprint(mynetname, "^2 broke ", oldrec_holder, "^2's ", race_placeName(newpos), " ^2place record with ", strcat(TIME_ENCODED_TOSTRING(t), recorddifference, "\n"));
- race_SendStatus(2, e); // "new rank"
- Send_KillNotification(e.netname, TIME_ENCODED_TOSTRING(t), "", RACE_NEW_TIME, MSG_RACE);
- }
+
+ if(newpos == player_prevpos)
+ {
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_RACE_NEW_IMPROVED, mynetname, newpos, t, oldrec);
+ if(newpos == 1) { race_SendStatus(3, e); } // "new server record"
+ else { race_SendStatus(1, e); } // "new time"
+ }
+ else if(oldrec == 0)
+ {
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_RACE_NEW_SET, mynetname, newpos, t);
+ if(newpos == 1) { race_SendStatus(3, e); } // "new server record"
+ else { race_SendStatus(2, e); } // "new rank"
+ }
+ else
+ {
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_RACE_NEW_BROKEN, mynetname, oldrec_holder, newpos, t, oldrec);
+ if(newpos == 1) { race_SendStatus(3, e); } // "new server record"
+ else { race_SendStatus(2, e); } // "new rank"
}
}
}
else
{
+ s = PlayerScore_Add(e, SP_RACE_FASTEST, 0);
+ if(!s || t < s)
+ PlayerScore_Add(e, SP_RACE_FASTEST, t - s);
+
s = PlayerScore_Add(e, SP_RACE_TIME, 0);
snew = TIME_ENCODE(time - game_starttime);
PlayerScore_Add(e, SP_RACE_TIME, snew - s);
{
e.race_completed = 1;
MAKE_INDEPENDENT_PLAYER(e);
- bprint(e.netname, "^7 has finished the race.\n");
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_RACE_FINISHED, e.netname);
ClientData_Touch(e);
}
}
waypoint_spawnforitem_force(self, trace_endpos);
self.nearestwaypointtimeout = time + 1000000000;
- if(!self.message)
+ if(self.message == "")
self.message = "went backwards";
- if (!self.message2)
+ if (self.message2 == "")
self.message2 = "was pushed backwards by";
- if (!self.race_penalty_reason)
+ if (self.race_penalty_reason == "")
self.race_penalty_reason = "missing a checkpoint";
self.race_checkpoint = self.cnt;
waypoint_spawnforitem_force(self, trace_endpos);
self.nearestwaypointtimeout = time + 1000000000;
- if(!self.message)
+ if(self.message == "")
self.message = "went backwards";
- if (!self.message2)
+ if (self.message2 == "")
self.message2 = "was pushed backwards by";
- if (!self.race_penalty_reason)
+ if (self.race_penalty_reason == "")
self.race_penalty_reason = "missing a checkpoint";
if(self.classname == "target_startTimer")
{
p.race_completed = 1;
MAKE_INDEPENDENT_PLAYER(p);
- bprint(p.netname, "^7 has abandoned the race.\n");
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_RACE_ABANDONED, p.netname);
ClientData_Touch(p);
}
}
Score_NicePrint(world);
race_ClearRecords();
- PlayerScore_Sort(race_place);
+ PlayerScore_Sort(race_place, 0, 1, 0);
entity e;
FOR_EACH_CLIENT(e)
if not(self.spawnflags & 1)
self.touch = penalty_touch;
- if (!self.race_penalty_reason)
+ if (self.race_penalty_reason == "")
self.race_penalty_reason = "missing a checkpoint";
if (!self.race_penalty)
self.race_penalty = 5;
void RuneCarriedThink()
{
float rcount, rnum;
- vector ang;
+ vector ang = '0 0 0';
entity rune;
if(self.owner.classname != "player" || time < game_starttime)
other.runes = other.runes | self.runes | self.enemy.runes;
- //self.think = SUB_Null;
+ //self.think = func_null;
//self.nextthink = 0;
self.think = RuneCarriedThink;
self.nextthink = time;
- self.touch = SUB_Null;
+ self.touch = func_null;
self.solid = SOLID_NOT;
setorigin(self, self.origin);
entity curse1, rune1, curse2, rune2;
rcount = ccount = r = c = 0;
- rune = find(rune, classname, "rune");
+ rune = find(world, classname, "rune");
while(rune)
{
if(rune.owner == pl)
rcount = rcount + 1;
rune = find(rune, classname, "rune");
}
- curse = find(curse, classname, "curse");
+ curse = find(world, classname, "curse");
while(curse)
{
if(curse.owner == pl)
float scores_flags_primary;
float teamscores_flags_primary;
-vector ScoreField_Compare(entity t1, entity t2, .float field, float fieldflags, vector previous) // returns: cmp value, best prio
+vector ScoreField_Compare(entity t1, entity t2, .float field, float fieldflags, vector previous, float strict) // returns: cmp value, best prio
{
- if(!(fieldflags & SFL_SORT_PRIO_MASK)) // column does not sort
+ if(!strict && !(fieldflags & SFL_SORT_PRIO_MASK)) // column does not sort
return previous;
if(fieldflags & SFL_SORT_PRIO_MASK < previous_y)
return previous;
return TeamScore_AddToTeam(player.team, scorefield, score);
}
-float TeamScore_Compare(entity t1, entity t2)
+float TeamScore_Compare(entity t1, entity t2, float strict)
{
if(!t1 || !t2) return (!t2) - !t1;
{
var .float f;
f = teamscores[i];
- result = ScoreField_Compare(t1, t2, f, teamscores_flags[i], result);
+ result = ScoreField_Compare(t1, t2, f, teamscores_flags[i], result, strict);
}
+
+ if (result_x == 0 && strict)
+ result_x = t1.team - t2.team;
+
return result_x;
}
Net_LinkEntity(scores_initialized, FALSE, 0, ScoreInfo_SendEntity);
}
if(teams >= 1)
- TeamScore_Spawn(COLOR_TEAM1, "Red");
+ TeamScore_Spawn(NUM_TEAM_1, "Red");
if(teams >= 2)
- TeamScore_Spawn(COLOR_TEAM2, "Blue");
+ TeamScore_Spawn(NUM_TEAM_2, "Blue");
if(teams >= 3)
- TeamScore_Spawn(COLOR_TEAM3, "Yellow");
+ TeamScore_Spawn(NUM_TEAM_3, "Yellow");
if(teams >= 4)
- TeamScore_Spawn(COLOR_TEAM4, "Pink");
+ TeamScore_Spawn(NUM_TEAM_4, "Pink");
}
/*
return TRUE;
}
-void PlayerScore_Clear(entity player)
+float PlayerScore_Clear(entity player)
{
entity sk;
float i;
if(teamscores_entities_count)
- return;
+ return 0;
- if(g_lms) return;
- if(g_arena || g_ca) return;
- if(g_cts) return; // in CTS, you don't lose score by observing
- if(g_race && g_race_qualifying) return; // in qualifying, you don't lose score by observing
+ if(g_lms) return 0;
+ if(g_arena || g_ca) return 0;
+ if(g_cts) return 0; // in CTS, you don't lose score by observing
+ if(g_race && g_race_qualifying) return 0; // in qualifying, you don't lose score by observing
sk = player.scorekeeper;
for(i = 0; i < MAX_SCORE; ++i)
sk.SendFlags |= pow(2, i);
sk.(scores[i]) = 0;
}
+
+ return 1;
}
void Score_ClearAll()
return r;
}
-float PlayerScore_Compare(entity t1, entity t2)
+float PlayerScore_Compare(entity t1, entity t2, float strict)
{
if(!t1 || !t2) return (!t2) - !t1;
{
var .float f;
f = scores[i];
- result = ScoreField_Compare(t1, t2, f, scores_flags[i], result);
+ result = ScoreField_Compare(t1, t2, f, scores_flags[i], result, strict);
}
+
+ if (result_x == 0 && strict)
+ result_x = num_for_edict(t1.owner) - num_for_edict(t2.owner);
+
return result_x;
}
for(t = 0; t < 16; ++t)
{
sk = teamscorekeepers[t];
- c = TeamScore_Compare(winnerscorekeeper, sk);
+ c = TeamScore_Compare(winnerscorekeeper, sk, 1);
if(c < 0)
{
WinningConditionHelper_secondteam = WinningConditionHelper_winnerteam;
}
else
{
- c = TeamScore_Compare(secondscorekeeper, sk);
+ c = TeamScore_Compare(secondscorekeeper, sk, 1);
if(c < 0)
{
WinningConditionHelper_secondteam = t + 1;
}
}
- WinningConditionHelper_equality = (TeamScore_Compare(winnerscorekeeper, secondscorekeeper) == 0);
+ WinningConditionHelper_equality = (TeamScore_Compare(winnerscorekeeper, secondscorekeeper, 0) == 0);
if(WinningConditionHelper_equality)
WinningConditionHelper_winnerteam = WinningConditionHelper_secondteam = -1;
FOR_EACH_PLAYER(p)
{
sk = p.scorekeeper;
- c = PlayerScore_Compare(winnerscorekeeper, sk);
+ c = PlayerScore_Compare(winnerscorekeeper, sk, 1);
if(c < 0)
{
WinningConditionHelper_second = WinningConditionHelper_winner;
}
else
{
- c = PlayerScore_Compare(secondscorekeeper, sk);
+ c = PlayerScore_Compare(secondscorekeeper, sk, 1);
if(c < 0)
{
WinningConditionHelper_second = p;
}
}
- WinningConditionHelper_equality = (PlayerScore_Compare(winnerscorekeeper, secondscorekeeper) == 0);
+ WinningConditionHelper_equality = (PlayerScore_Compare(winnerscorekeeper, secondscorekeeper, 0) == 0);
if(WinningConditionHelper_equality)
WinningConditionHelper_winner = WinningConditionHelper_second = world;
return out;
}
-float PlayerTeamScore_Compare(entity p1, entity p2)
+float PlayerTeamScore_Compare(entity p1, entity p2, float teams, float strict)
{
- if(teamscores_entities_count)
+ if(teams && teamscores_entities_count)
+ {
if(p1.team != p2.team)
{
entity t1, t2;
float r;
t1 = teamscorekeepers[p1.team - 1];
t2 = teamscorekeepers[p2.team - 1];
- r = TeamScore_Compare(t1, t2);
- if(r == 0) // ensure a deterministic order
- r = p1.team - p2.team;
+ r = TeamScore_Compare(t1, t2, ((teams >= 0) ? 1 : strict));
return r;
}
+ if(teams < 0)
+ return 0;
+ }
- return PlayerScore_Compare(p1.scorekeeper, p2.scorekeeper);
+ return PlayerScore_Compare(p1.scorekeeper, p2.scorekeeper, strict);
}
-entity PlayerScore_Sort(.float field)
+entity PlayerScore_Sort(.float field, float teams, float strict, float nospectators)
{
entity p, plist, pprev, pbest, pbestprev, pfirst, plast;
- float i;
+ float i, j;
plist = world;
FOR_EACH_CLIENT(p)
p.field = 0;
- FOR_EACH_PLAYER(p) if(p.scorekeeper)
+ FOR_EACH_CLIENT(p) if(p.scorekeeper)
{
+ if(nospectators)
+ if(p.frags == FRAGS_SPECTATOR)
+ continue;
+
p.chain = plist;
plist = p;
}
pfirst = plast = world;
- i = 0;
+ i = j = 0;
while(plist)
{
pprev = pbestprev = world;
pbest = plist;
for(p = plist; (pprev = p), (p = p.chain); )
{
- if(PlayerTeamScore_Compare(p, pbest) > 0)
+ if(PlayerTeamScore_Compare(p, pbest, teams, strict) > 0)
{
pbest = p;
pbestprev = pprev;
pbestprev.chain = pbest.chain;
pbest.chain = world;
- pbest.field = ++i;
+ ++i;
+ if(!plast || PlayerTeamScore_Compare(plast, pbest, teams, 0))
+ j = i;
+
+ pbest.field = j;
if not(pfirst)
pfirst = pbest;
sk = teamscorekeepers[t - 1];
if(sk)
{
- s = strcat(s, ColoredTeamName(t));
+ s = strcat(s, Team_ColoredFullName(t));
for(i = 0; i < MAX_TEAMSCORE; ++i)
if(teamscores_label[i] != "")
{
++t;
w = bound(6, floor(SCORESWIDTH / t - 1), 9);
- p = PlayerScore_Sort(score_dummyfield);
+ p = PlayerScore_Sort(score_dummyfield, 1, 1, 0);
t = -1;
if(!teamscores_entities_count)
* Initialize the score of this player if needed.
* Does nothing in teamplay.
* Use that when a spectator becomes a player.
+ * Returns whether clearing has been performed
*/
-void PlayerScore_Clear(entity player);
+float PlayerScore_Clear(entity player);
/**
* Adds a score to the player's team's scores.
* Sorts the players and stores their place in the given field, starting with
* 1. Non-players get 0 written into that field.
* Returns the beginning of a sorted chain of the non-spectators.
+ * teams: >0: sort by teams first (always strict ordering); <0: sort by teams only (respects strict flag)
+ * strict: return a strict ordering
+ * nospectators: exclude spectators
*/
-entity PlayerScore_Sort(.float field);
+entity PlayerScore_Sort(.float field, float teams, float strict, float nospectators);
ScoreRules_basics_end();
}
-// g_domination
-#define ST_DOM_TICKS 1
-#define SP_DOM_TICKS 4
-#define SP_DOM_TAKES 5
-void ScoreRules_dom()
-{
- float sp_domticks, sp_score;
- sp_score = sp_domticks = 0;
- if(autocvar_g_domination_disable_frags)
- sp_domticks = SFL_SORT_PRIO_PRIMARY;
- else
- sp_score = SFL_SORT_PRIO_PRIMARY;
- CheckAllowedTeams(world);
- ScoreRules_basics(((c4>=0) ? 4 : (c3>=0) ? 3 : 2), sp_score, sp_score, TRUE);
- ScoreInfo_SetLabel_TeamScore (ST_DOM_TICKS, "ticks", sp_domticks);
- ScoreInfo_SetLabel_PlayerScore(SP_DOM_TICKS, "ticks", sp_domticks);
- ScoreInfo_SetLabel_PlayerScore(SP_DOM_TAKES, "takes", 0);
- ScoreRules_basics_end();
-}
-
// LMS stuff
#define SP_LMS_LIVES 4
#define SP_LMS_RANK 5
// Race stuff
#define ST_RACE_LAPS 1
#define SP_RACE_LAPS 4
-#define SP_RACE_FASTEST 5
#define SP_RACE_TIME 5
-//#define SP_RACE_RANK 6
+#define SP_RACE_FASTEST 6
void ScoreRules_race()
{
ScoreRules_basics(race_teams, 0, 0, FALSE);
ScoreInfo_SetLabel_TeamScore( ST_RACE_LAPS, "laps", SFL_SORT_PRIO_PRIMARY);
ScoreInfo_SetLabel_PlayerScore(SP_RACE_LAPS, "laps", SFL_SORT_PRIO_PRIMARY);
ScoreInfo_SetLabel_PlayerScore(SP_RACE_TIME, "time", SFL_SORT_PRIO_SECONDARY | SFL_LOWER_IS_BETTER | SFL_TIME);
- //ScoreInfo_SetLabel_PlayerScore(SP_RACE_RANK, "rank", SFL_LOWER_IS_BETTER | SFL_RANK | SFL_ALLOW_HIDE);
+ ScoreInfo_SetLabel_PlayerScore(SP_RACE_FASTEST, "fastest", SFL_LOWER_IS_BETTER | SFL_TIME);
}
else if(g_race_qualifying)
{
}
else
{
- //ScoreInfo_SetLabel_TeamScore( ST_RACE_LAPS, "laps", 0);
ScoreInfo_SetLabel_PlayerScore(SP_RACE_LAPS, "laps", SFL_SORT_PRIO_PRIMARY);
ScoreInfo_SetLabel_PlayerScore(SP_RACE_TIME, "time", SFL_SORT_PRIO_SECONDARY | SFL_LOWER_IS_BETTER | SFL_TIME);
+ ScoreInfo_SetLabel_PlayerScore(SP_RACE_FASTEST, "fastest", SFL_LOWER_IS_BETTER | SFL_TIME);
}
ScoreRules_basics_end();
}
// take over the touch() function, so we can mark secret as found
self.touch = trigger_secret_touch;
// ignore triggering;
- self.use = SUB_Null;
+ self.use = func_null;
}
{
self.dmgtime = time + autocvar_g_balance_contents_damagerate;
- if (!projectile)
+ if (projectile)
+ {
+ if (self.watertype == CONTENT_LAVA)
+ {
+ Damage (self, world, world, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_LAVA, self.origin, '0 0 0');
+ }
+ else if (self.watertype == CONTENT_SLIME)
+ {
+ Damage (self, world, world, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_SLIME, self.origin, '0 0 0');
+ }
+ }
+ else
{
if (self.watertype == CONTENT_LAVA)
{
Damage (self, world, world, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_SLIME, self.origin, '0 0 0');
}
}
- else if ((self.watertype == CONTENT_LAVA) || (self.watertype == CONTENT_SLIME))
- {
- Damage (self, world, world, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * self.waterlevel, DEATH_SLIME, self.origin, '0 0 0');
- }
}
}
else
// add more things here (health, armor)
default: error("requested item has no counter field");
}
+#ifdef GMQCC
+ // should never happen
+ return health;
+#endif
}
string Item_CounterFieldName(float it)
// add more things here (health, armor)
default: error("requested item has no counter field name");
}
+#ifdef GMQCC
+ // should never happen
+ return string_null;
+#endif
}
.float max_armorvalue;
rgb = '1 0 0';
}
}
- if(!name)
- {
- print("Unknown powerup-marked item is wanting to respawn\n");
- localcmd(sprintf("prvm_edict server %d\n", num_for_edict(self)));
- }
if(name)
{
WaypointSprite_Spawn(name, 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, TRUE, RADARICON_POWERUP, rgb);
WaypointSprite_UpdateBuildFinished(self.waypointsprite_attached, time + ITEM_RESPAWN_TICKS);
}
}
+ else
+ {
+ print("Unknown powerup-marked item is wanting to respawn\n");
+ localcmd(sprintf("prvm_edict server %d\n", num_for_edict(self)));
+ }
}
sound (self, CH_TRIGGER, "misc/itemrespawncountdown.wav", VOL_BASE, ATTN_NORM); // play respawn sound
if(self.waypointsprite_attached)
// AnnounceTo(player, "ammo");
if (WEPSET_CONTAINS_EW(item, WEP_MINSTANEX))
- W_GiveWeapon (player, WEP_MINSTANEX, item.netname);
+ W_GiveWeapon (player, WEP_MINSTANEX);
player.health = 100;
}
pickedup = TRUE;
for(i = WEP_FIRST; i <= WEP_LAST; ++i)
if(WEPSET_CONTAINS_AW(it, i))
- W_GiveWeapon (player, i, item.netname);
+ W_GiveWeapon(player, i);
}
}
if(self.classname != "droppedweapon")
{
- self.think = SUB_Null;
+ self.think = func_null;
self.nextthink = 0;
if(self.waypointsprite_attached)
Item_Reset();
Net_LinkEntity(self, FALSE, 0, ItemSend);
+
+ // call this hook after everything else has been done
+ if(MUTATOR_CALLHOOK(Item_Spawn))
+ {
+ startitem_failed = TRUE;
+ remove(self);
+ return;
+ }
}
/* replace items in minstagib
valueprefix = "max ";
}
else
+ {
error("invalid spawnflags");
+#ifdef GMQCC
+ itemprefix = string_null;
+ valueprefix = string_null;
+#endif
+ }
self.netname = "";
self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, !!(self.items & IT_UNLIMITED_WEAPON_AMMO), "unlimited_weapon_ammo");
else
other.lastteleporttime = time;
- if (!other.animstate_override)
if (other.deadflag == DEAD_NO)
- {
- if (other.crouch)
- setanim(other, other.anim_duckjump, FALSE, TRUE, TRUE);
- else
- setanim(other, other.anim_jump, FALSE, TRUE, TRUE);
- }
+ animdecide_setaction(other, ANIMACTION_JUMP, TRUE);
}
else
other.jumppadcount = TRUE;
if (self.spawnflags & PUSH_ONCE)
{
- self.touch = SUB_Null;
+ self.touch = func_null;
self.think = SUB_Remove;
self.nextthink = time;
}
void plat_use()
{
- self.use = SUB_Null;
+ self.use = func_null;
if (self.state != 4)
objerror ("plat_use: not in up state");
plat_go_down();
if(self.spawnflags & 4)
self.dmg = 10000;
- if(self.dmg && (!self.message))
+ if(self.dmg && (self.message == ""))
self.message = "was squished";
- if(self.dmg && (!self.message2))
+ if(self.dmg && (self.message2 == ""))
self.message2 = "was squished by";
if (self.sounds == 1)
targ = find(world, targetname, self.target);
self.enemy = targ;
self.target = targ.target;
- if (!self.target)
+ if (self.target == "")
objerror("train_next: no next target");
self.wait = targ.wait;
if (!self.wait)
entity targ;
targ = find(world, targetname, self.target);
self.target = targ.target;
- if (!self.target)
+ if (self.target == "")
objerror("func_train_find: no next target");
setorigin(self, targ.origin - self.mins);
self.nextthink = self.ltime + 1;
if (self.noise != "")
precache_sound(self.noise);
- if (!self.target)
+ if (self.target == "")
objerror("func_train without a target");
if (!self.speed)
self.speed = 100;
InitializeEntity(self, func_train_find, INITPRIO_SETLOCATION);
self.blocked = generic_plat_blocked;
- if(self.dmg & (!self.message))
+ if(self.dmg && (self.message == ""))
self.message = " was squished";
- if(self.dmg && (!self.message2))
+ if(self.dmg && (self.message2 == ""))
self.message2 = "was squished by";
if(self.dmg && (!self.dmgtime))
self.dmgtime = 0.25;
self.pos1 = self.avelocity;
- if(self.dmg & (!self.message))
+ if(self.dmg && (self.message == ""))
self.message = " was squished";
- if(self.dmg && (!self.message2))
+ if(self.dmg && (self.message2 == ""))
self.message2 = "was squished by";
// wait for targets to spawn
self.nextthink = self.ltime + 999999999;
- self.think = SUB_Null;
+ self.think = SUB_NullThink; // for PushMove
// TODO make a reset function for this one
}
// damage when blocked
self.blocked = generic_plat_blocked;
- if(self.dmg & (!self.message))
+ if(self.dmg && (self.message == ""))
self.message = " was squished";
- if(self.dmg && (!self.message2))
+ if(self.dmg && (self.message2 == ""))
self.message2 = "was squished by";
if(self.dmg && (!self.dmgtime))
self.dmgtime = 0.25;
controller.nextthink = time + 1;
controller.think = func_bobbing_controller_think;
self.nextthink = self.ltime + 999999999;
- self.think = SUB_Null;
+ self.think = SUB_NullThink; // for PushMove
// Savage: Reduce bandwith, critical on e.g. nexdm02
self.effects |= EF_LOWPRECISION;
self.speed = 30;
// not initializing self.dmg to 2, to allow damageless pendulum
- if(self.dmg & (!self.message))
+ if(self.dmg && (self.message == ""))
self.message = " was squished";
- if(self.dmg && (!self.message2))
+ if(self.dmg && (self.message2 == ""))
self.message2 = "was squished by";
if(self.dmg && (!self.dmgtime))
self.dmgtime = 0.25;
controller.nextthink = time + 1;
controller.think = func_pendulum_controller_think;
self.nextthink = self.ltime + 999999999;
- self.think = SUB_Null;
+ self.think = SUB_NullThink; // for PushMove
//self.effects |= EF_LOWPRECISION;
{
if(t.health && !self.health)
self.health = t.health;
- if(t.targetname && !self.targetname)
+ if((t.targetname != "") && (self.targetname == ""))
self.targetname = t.targetname;
- if(t.message != "" && self.message == "")
+ if((t.message != "") && (self.message == ""))
self.message = t.message;
if (t.absmin_x < cmins_x)
cmins_x = t.absmin_x;
setorigin(self, self.pos1);
self.velocity = '0 0 0';
self.state = STATE_BOTTOM;
- self.think = SUB_Null;
+ self.think = func_null;
+ self.nextthink = 0;
}
// spawnflags require key (for now only func_door)
// if(self.spawnflags & 8)
// self.dmg = 10000;
- if(self.dmg && (!self.message))
+ if(self.dmg && (self.message == ""))
self.message = "was squished";
- if(self.dmg && (!self.message2))
+ if(self.dmg && (self.message2 == ""))
self.message2 = "was squished by";
if (self.sounds > 0)
self.angles = self.pos1;
self.avelocity = '0 0 0';
self.state = STATE_BOTTOM;
- self.think = SUB_Null;
+ self.think = func_null;
+ self.nextthink = 0;
}
void door_rotating_init_startopen()
if(self.spawnflags & 8)
self.dmg = 10000;
- if(self.dmg && (!self.message))
+ if(self.dmg && (self.message == ""))
self.message = "was squished";
- if(self.dmg && (!self.message2))
+ if(self.dmg && (self.message2 == ""))
self.message2 = "was squished by";
if (self.sounds > 0)
float SECRET_NO_SHOOT = 8; // only opened by trigger
float SECRET_YES_SHOOT = 16; // shootable even if targeted
-
void fd_secret_use()
{
float temp;
sound(self, CH_TRIGGER_SINGLE, self.noise2, VOL_BASE, ATTN_NORM);
}
+void fd_secret_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+ fd_secret_use();
+}
+
// Wait after first movement...
void fd_secret_move1()
{
self.takedamage = DAMAGE_YES;
}
setorigin(self, self.oldorigin);
- self.think = SUB_Null;
+ self.think = func_null;
+ self.nextthink = 0;
}
/*QUAKED spawnfunc_func_door_secret (0 .5 .8) ? open_once 1st_left 1st_down no_shoot always_shoot
{
self.health = 10000;
self.takedamage = DAMAGE_YES;
- self.event_damage = fd_secret_use;
+ self.event_damage = fd_secret_damage;
}
self.oldorigin = self.origin;
if (!self.wait)
self.cnt = 360 / self.speed;
self.blocked = generic_plat_blocked;
- if(self.dmg & (!self.message))
+ if(self.dmg && (self.message == ""))
self.message = " was squished";
- if(self.dmg && (!self.message2))
+ if(self.dmg && (self.message2 == ""))
self.message2 = "was squished by";
if(self.dmg && (!self.dmgtime))
self.dmgtime = 0.25;
controller.nextthink = time + 1;
controller.think = func_fourier_controller_think;
self.nextthink = self.ltime + 999999999;
- self.think = SUB_Null;
+ self.think = SUB_NullThink; // for PushMove
// Savage: Reduce bandwith, critical on e.g. nexdm02
self.effects |= EF_LOWPRECISION;
if(!self.wp00 && !self.wp01 && !self.wp02 && !self.wp03)
objerror("No reference entity found, so there is nothing to move. Aborting.");
- self.destvec = self.origin - func_vectormamamam_origin(self.owner, 0);
+ self.destvec = self.origin - func_vectormamamam_origin(self, 0);
entity controller;
controller = spawn();
self.target4normal = normalize(self.target4normal);
self.blocked = generic_plat_blocked;
- if(self.dmg & (!self.message))
+ if(self.dmg && (self.message == ""))
self.message = " was squished";
- if(self.dmg && (!self.message2))
+ if(self.dmg && (self.message == ""))
self.message2 = "was squished by";
if(self.dmg && (!self.dmgtime))
self.dmgtime = 0.25;
// wait for targets to spawn
self.nextthink = self.ltime + 999999999;
- self.think = SUB_Null;
+ self.think = SUB_NullThink; // for PushMove
// Savage: Reduce bandwith, critical on e.g. nexdm02
self.effects |= EF_LOWPRECISION;
// this must be called to spawn the teleport waypoints for bots
InitializeEntity(self, teleport_findtarget, INITPRIO_FINDTARGET);
- if (!self.target)
+ if (self.target == "")
{
objerror ("Teleporter with no target");
return;
PlayerScore_Clear(e);
}
-vector TeamColor(float teem)
-{
- switch(teem)
- {
- case COLOR_TEAM1:
- return '1 0.0625 0.0625';
- case COLOR_TEAM2:
- return '0.0625 0.0625 1';
- case COLOR_TEAM3:
- return '1 1 0.0625';
- case COLOR_TEAM4:
- return '1 0.0625 1';
- default:
- return '1 1 1';
- }
-}
-
-string TeamName(float t)
-{
- return strcat(Team_ColorName(t), " Team");
-}
-string ColoredTeamName(float t)
-{
- return strcat(Team_ColorCode(t), Team_ColorName(t), " Team^7");
-}
-string TeamNoName(float t)
-{
- // fixme: Search for team entities and get their .netname's!
- if(t == 1)
- return "Red Team";
- if(t == 2)
- return "Blue Team";
- if(t == 3)
- return "Yellow Team";
- if(t == 4)
- return "Pink Team";
- return "Neutral Team";
-}
-
-void dom_init();
void runematch_init();
void tdm_init();
void entcs_init();
ActivateTeamplay();
fraglimit_override = autocvar_g_domination_point_limit;
leadlimit_override = autocvar_g_domination_point_leadlimit;
- dom_init();
+ MUTATOR_ADD(gamemode_domination);
have_team_spawns = -1; // request team spawns
}
float _color;
if(t == 4)
- _color = COLOR_TEAM4 - 1;
+ _color = NUM_TEAM_4 - 1;
else if(t == 3)
- _color = COLOR_TEAM3 - 1;
+ _color = NUM_TEAM_3 - 1;
else if(t == 2)
- _color = COLOR_TEAM2 - 1;
+ _color = NUM_TEAM_2 - 1;
else
- _color = COLOR_TEAM1 - 1;
+ _color = NUM_TEAM_1 - 1;
SetPlayerColors(pl,_color);
LogTeamchange(pl.playerid, pl.team, 3); // log manual team join
if(!noprint)
- bprint(pl.netname, "^7 has changed from ", TeamNoName(s), " to ", TeamNoName(t), "\n");
+ bprint(pl.netname, "^7 has changed from ", Team_NumberToColoredFullName(s), "^7 to ", Team_NumberToColoredFullName(t), "\n");
}
}
head = findchain(classname, "onslaught_generator");
while (head)
{
- if (head.team == COLOR_TEAM1) c1 = 0;
- if (head.team == COLOR_TEAM2) c2 = 0;
- if (head.team == COLOR_TEAM3) c3 = 0;
- if (head.team == COLOR_TEAM4) c4 = 0;
+ if (head.team == NUM_TEAM_1) c1 = 0;
+ if (head.team == NUM_TEAM_2) c2 = 0;
+ if (head.team == NUM_TEAM_3) c3 = 0;
+ if (head.team == NUM_TEAM_4) c4 = 0;
head = head.chain;
}
}
{
if(!(g_domination && head.netname == ""))
{
- if(head.team == COLOR_TEAM1)
+ if(head.team == NUM_TEAM_1)
c1 = 0;
- else if(head.team == COLOR_TEAM2)
+ else if(head.team == NUM_TEAM_2)
c2 = 0;
- else if(head.team == COLOR_TEAM3)
+ else if(head.team == NUM_TEAM_3)
c3 = 0;
- else if(head.team == COLOR_TEAM4)
+ else if(head.team == NUM_TEAM_4)
c4 = 0;
}
head = find(head, classname, teament_name);
}
// if player has a forced team, ONLY allow that one
- if(self.team_forced == COLOR_TEAM1 && c1 >= 0)
+ if(self.team_forced == NUM_TEAM_1 && c1 >= 0)
c2 = c3 = c4 = -1;
- else if(self.team_forced == COLOR_TEAM2 && c2 >= 0)
+ else if(self.team_forced == NUM_TEAM_2 && c2 >= 0)
c1 = c3 = c4 = -1;
- else if(self.team_forced == COLOR_TEAM3 && c3 >= 0)
+ else if(self.team_forced == NUM_TEAM_3 && c3 >= 0)
c1 = c2 = c4 = -1;
- else if(self.team_forced == COLOR_TEAM4 && c4 >= 0)
+ else if(self.team_forced == NUM_TEAM_4 && c4 >= 0)
c1 = c2 = c3 = -1;
}
bvalue = value;
else
bvalue = 0;
- if(t == COLOR_TEAM1)
+ if(t == NUM_TEAM_1)
{
if(c1 >= 0)
{
cb1 = cb1 + bvalue;
}
}
- if(t == COLOR_TEAM2)
+ if(t == NUM_TEAM_2)
{
if(c2 >= 0)
{
cb2 = cb2 + bvalue;
}
}
- if(t == COLOR_TEAM3)
+ if(t == NUM_TEAM_3)
{
if(c3 >= 0)
{
cb3 = cb3 + bvalue;
}
}
- if(t == COLOR_TEAM4)
+ if(t == NUM_TEAM_4)
{
if(c4 >= 0)
{
// if he's not on a valid team, then let other code put him on the smallest team
if(!forcebestteam)
{
- if( c1 >= 0 && pl.team == COLOR_TEAM1)
+ if( c1 >= 0 && pl.team == NUM_TEAM_1)
selectedteam = pl.team;
- else if(c2 >= 0 && pl.team == COLOR_TEAM2)
+ else if(c2 >= 0 && pl.team == NUM_TEAM_2)
selectedteam = pl.team;
- else if(c3 >= 0 && pl.team == COLOR_TEAM3)
+ else if(c3 >= 0 && pl.team == NUM_TEAM_3)
selectedteam = pl.team;
- else if(c4 >= 0 && pl.team == COLOR_TEAM4)
+ else if(c4 >= 0 && pl.team == NUM_TEAM_4)
selectedteam = pl.team;
else
selectedteam = -1;
TeamchangeFrags(self);
if(smallest == 1)
{
- SetPlayerColors(pl, COLOR_TEAM1 - 1);
+ SetPlayerColors(pl, NUM_TEAM_1 - 1);
}
else if(smallest == 2)
{
- SetPlayerColors(pl, COLOR_TEAM2 - 1);
+ SetPlayerColors(pl, NUM_TEAM_2 - 1);
}
else if(smallest == 3)
{
- SetPlayerColors(pl, COLOR_TEAM3 - 1);
+ SetPlayerColors(pl, NUM_TEAM_3 - 1);
}
else if(smallest == 4)
{
- SetPlayerColors(pl, COLOR_TEAM4 - 1);
+ SetPlayerColors(pl, NUM_TEAM_4 - 1);
}
else
{
scolor = self.clientcolors & 0x0F;
dcolor = _color & 0x0F;
- if(scolor == COLOR_TEAM1 - 1)
+ if(scolor == NUM_TEAM_1 - 1)
steam = 1;
- else if(scolor == COLOR_TEAM2 - 1)
+ else if(scolor == NUM_TEAM_2 - 1)
steam = 2;
- else if(scolor == COLOR_TEAM3 - 1)
+ else if(scolor == NUM_TEAM_3 - 1)
steam = 3;
- else // if(scolor == COLOR_TEAM4 - 1)
+ else // if(scolor == NUM_TEAM_4 - 1)
steam = 4;
- if(dcolor == COLOR_TEAM1 - 1)
+ if(dcolor == NUM_TEAM_1 - 1)
dteam = 1;
- else if(dcolor == COLOR_TEAM2 - 1)
+ else if(dcolor == NUM_TEAM_2 - 1)
dteam = 2;
- else if(dcolor == COLOR_TEAM3 - 1)
+ else if(dcolor == NUM_TEAM_3 - 1)
dteam = 3;
- else // if(dcolor == COLOR_TEAM4 - 1)
+ else // if(dcolor == NUM_TEAM_4 - 1)
dteam = 4;
CheckAllowedTeams(self);
}
if(source_team == 1)
- steam = COLOR_TEAM1;
+ steam = NUM_TEAM_1;
else if(source_team == 2)
- steam = COLOR_TEAM2;
+ steam = NUM_TEAM_2;
else if(source_team == 3)
- steam = COLOR_TEAM3;
+ steam = NUM_TEAM_3;
else // if(source_team == 4)
- steam = COLOR_TEAM4;
+ steam = NUM_TEAM_4;
lowest_bot = world;
lowest_bot_score = 999999999;
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: ", ColoredTeamName(selected.team)));
+ 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
numteams = autocvar_g_tdm_teams;
numteams = bound(2, numteams, 4);
- tdm_spawnteam("Red", COLOR_TEAM1-1);
- tdm_spawnteam("Blue", COLOR_TEAM2-1);
+ tdm_spawnteam("Red", NUM_TEAM_1-1);
+ tdm_spawnteam("Blue", NUM_TEAM_2-1);
if(numteams >= 3)
- tdm_spawnteam("Yellow", COLOR_TEAM3-1);
+ tdm_spawnteam("Yellow", NUM_TEAM_3-1);
if(numteams >= 4)
- tdm_spawnteam("Pink", COLOR_TEAM4-1);
+ tdm_spawnteam("Pink", NUM_TEAM_4-1);
}
void tdm_delayedinit()
+++ /dev/null
-http://dev.xonotic.org/projects/xonotic/issues
-
-also: Maybe actually decide upon what to do with this todo file? No one uses it :P Just use the development tracker.
\ No newline at end of file
{
// FIXME: this cant be the best way to do this..
prep = pre_pos;
+#ifdef GMQCC
+ impact_time = 0;
+#endif
for(i = 0; i < 4; ++i)
{
distance = vlen(prep - self.tur_shotorg);
self.solid = SOLID_NOT;
self.tur_head.solid = self.solid;
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
self.takedamage = DAMAGE_NO;
self.health = 0;
if (self.health <= 0)
{
- self.event_damage = SUB_Null;
- self.tur_head.event_damage = SUB_Null;
+ self.event_damage = func_null;
+ self.tur_head.event_damage = func_null;
self.takedamage = DAMAGE_NO;
self.nextthink = time;
self.think = turret_stdproc_die;
{
self.takedamage = DAMAGE_NO;
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
#ifdef TURRET_DEBUG
float d;
d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world);
float m_score; // currently best scoreing target's score
m_score = 0;
- if(self.enemy)
- if(self.enemy.takedamage)
- if(turret_validate_target(self,self.enemy,self.target_validate_flags) > 0)
+ if(self.enemy && self.enemy.takedamage && turret_validate_target(self,self.enemy,self.target_validate_flags) > 0)
{
e_enemy = self.enemy;
m_score = self.turret_score_target(self,e_enemy) * self.target_select_samebias;
// Check if we have a vailid enemy, and try to find one if we dont.
// g_turrets_targetscan_maxdelay forces a target re-scan at least this often
- float do_target_scan;
+ float do_target_scan = 0;
if((self.target_select_time + autocvar_g_turrets_targetscan_maxdelay) < time)
do_target_scan = 1;
*/
float turret_stdproc_init (string cvar_base_name, string base, string head, float _turret_type)
{
- entity e, ee;
+ entity e, ee = world;
// Are turrets allowed?
if (autocvar_g_turrets == 0)
vector shortangle_vxy(vector ang1, vector ang2)
{
- vector vtmp;
+ vector vtmp = '0 0 0';
vtmp_x = shortangle_f(ang1_x,ang2_x);
vtmp_y = shortangle_f(ang1_y,ang2_y);
float turret_stdproc_targetscore_support(entity _turret,entity _target)
{
float score; // Total score
- float s_score, d_score;
+ float s_score = 0, d_score;
if (_turret.enemy == _target) s_score = 1;
float score; // Total score
float d_score; // Distance score
float a_score; // Angular score
- float m_score; // missile score
- float p_score; // player score
+ float m_score = 0; // missile score
+ float p_score = 0; // player score
float ikr; // ideal kill range
if (_turret.tur_defend)
//.float bulletcounter;
void turret_machinegun_attack()
{
- fireBallisticBullet (self.tur_shotorg, self.tur_shotdir_updated,self.shot_spread, self.shot_speed, 5, self.shot_dmg, 0, self.shot_force, DEATH_TURRET_MACHINEGUN, 0, 1, autocvar_g_balance_uzi_bulletconstant);
+ fireBallisticBullet (self.tur_shotorg, self.tur_shotdir_updated,self.shot_spread, self.shot_speed, 5, self.shot_dmg, self.shot_force, DEATH_TURRET_MACHINEGUN, 0, 1, autocvar_g_balance_uzi_bulletconstant);
endFireBallisticBullet();
UziFlash();
entity oldself;
oldself = self;
self = self.owner;
- //w_deathtypestring = "was phased out of existence";
FireImoBeam ( self.tur_shotorg,
self.tur_shotorg + self.tur_shotdir_updated * self.target_range,
'-1 -1 -1' * self.shot_radius,
float turret_tesla_firecheck()
{
// g_turrets_targetscan_maxdelay forces a target re-scan at least this often
- float do_target_scan;
+ float do_target_scan = 0;
if((self.target_select_time + autocvar_g_turrets_targetscan_maxdelay) < time)
do_target_scan = 1;
entity e, t;
float d, r, i;
- //w_deathtypestring = "discoverd how a tesla coil works";
-
d = self.shot_dmg;
r = self.target_range;
e = spawn();
{
if (turret_validate_target(self, e, self.target_validate_flags))
if (e != self && e.owner != self)
- Damage(e, self, self, autocvar_g_turrets_unit_walker_std_meele_dmg, DEATH_TURRET_WALKER_MEELE, '0 0 0', v_forward * autocvar_g_turrets_unit_walker_std_meele_force);
+ Damage(e, self, self, autocvar_g_turrets_unit_walker_std_meele_dmg, DEATH_TURRET_WALK_MEELE, '0 0 0', v_forward * autocvar_g_turrets_unit_walker_std_meele_force);
e = e.chain;
}
}
void walker_rocket_explode()
{
- RadiusDamage (self, self.owner, autocvar_g_turrets_unit_walker_std_rocket_dmg, 0, autocvar_g_turrets_unit_walker_std_rocket_radius, self, autocvar_g_turrets_unit_walker_std_rocket_force, DEATH_TURRET_WALKER_ROCKET, world);
+ RadiusDamage (self, self.owner, autocvar_g_turrets_unit_walker_std_rocket_dmg, 0, autocvar_g_turrets_unit_walker_std_rocket_radius, self, autocvar_g_turrets_unit_walker_std_rocket_force, DEATH_TURRET_WALK_ROCKET, world);
remove (self);
}
//if(self.animflag != ANIM_NO)
{
vector real_angle;
- float turny, turnx;
+ float turny = 0, turnx = 0;
float vz;
real_angle = vectoangles(self.steerto) - self.angles;
void walker_attack()
{
sound (self, CH_WEAPON_A, "weapons/uzi_fire.wav", VOL_BASE, ATTN_NORM);
- fireBallisticBullet (self.tur_shotorg, self.tur_shotdir_updated, self.shot_spread, self.shot_speed, 5, self.shot_dmg, 0, self.shot_force, DEATH_TURRET_WALKER_GUN, 0, 1, autocvar_g_balance_uzi_bulletconstant);
+ fireBallisticBullet (self.tur_shotorg, self.tur_shotdir_updated, self.shot_spread, self.shot_speed, 5, self.shot_dmg, self.shot_force, DEATH_TURRET_WALK_GUN, 0, 1, autocvar_g_balance_uzi_bulletconstant);
endFireBallisticBullet();
pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
}
vehicles_projectile("bigplasma_muzzleflash", "weapons/flacexp3.wav",
v, normalize(v_forward + randomvec() * autocvar_g_vehicle_bumblebee_cannon_spread) * autocvar_g_vehicle_bumblebee_cannon_speed,
autocvar_g_vehicle_bumblebee_cannon_damage, autocvar_g_vehicle_bumblebee_cannon_radius, autocvar_g_vehicle_bumblebee_cannon_force, 0,
- DEATH_BUMB_GUN, PROJECTILE_BUMBLE_GUN, 0, TRUE, TRUE, _owner);
+ DEATH_VH_BUMB_GUN, PROJECTILE_BUMBLE_GUN, 0, TRUE, TRUE, _owner);
}
float bumb_gunner_frame()
self.movetype = MOVETYPE_WALK;
self.effects &~= EF_NODRAW;
self.alpha = 1;
- self.PlayerPhysplug = SUB_Null;
+ self.PlayerPhysplug = func_null;
self.view_ofs = PL_VIEW_OFS;
self.event_damage = PlayerDamage;
self.hud = HUD_NORMAL;
other.solid = SOLID_NOT;
other.movetype = MOVETYPE_NOCLIP;
other.alpha = -1;
- other.event_damage = SUB_Null;
+ other.event_damage = func_null;
other.view_ofs = '0 0 0';
other.hud = _gun.hud;
other.PlayerPhysplug = _gun.PlayerPhysplug;
autocvar_g_vehicle_bumblebee_blowup_edgedamage,
autocvar_g_vehicle_bumblebee_blowup_radius, self,
autocvar_g_vehicle_bumblebee_blowup_forceintensity,
- DEATH_WAKIBLOWUP, world);
+ DEATH_VH_BUMB_DEATH, world);
sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
pointparticles(particleeffectnum("explosion_large"), randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1);
if(random() > 0.5)
_body.touch = bumb_blowup;
else
- _body.touch = SUB_Null;
+ _body.touch = func_null;
_body.think = bumb_diethink;
_body.nextthink = time;
pointparticles(particleeffectnum("explosion_medium"), findbetterlocation(self.origin, 16), '0 0 0', 1);
self.health = 0;
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
self.solid = SOLID_CORPSE;
self.takedamage = DAMAGE_NO;
self.deadflag = DEAD_DYING;
self.colormod = '0 0 0';
self.avelocity = '0 0 0';
self.velocity = '0 0 0';
- self.touch = SUB_Null;
+ self.touch = func_null;
self.nextthink = 0;
setorigin(self, self.pos1);
vector autocvar_g_vehicle_racer_bouncepain;
var vector racer_force_from_tag(string tag_name, float spring_length, float max_power);
-void racer_spawn(float _spawnflag);
+void racer_spawn_default();
void racer_align4point(float _delta)
{
bolt = vehicles_projectile("wakizashi_gun_muzzleflash", "weapons/lasergun_fire.wav",
v, normalize(v_forward + randomvec() * autocvar_g_vehicle_racer_cannon_spread) * autocvar_g_vehicle_racer_cannon_speed,
autocvar_g_vehicle_racer_cannon_damage, autocvar_g_vehicle_racer_cannon_radius, autocvar_g_vehicle_racer_cannon_force, 0,
- DEATH_WAKIGUN, PROJECTILE_WAKICANNON, 0, TRUE, TRUE, self.owner);
+ DEATH_VH_WAKI_GUN, PROJECTILE_WAKICANNON, 0, TRUE, TRUE, self.owner);
// Fix z-aim (for chase mode)
v = normalize(trace_endpos - bolt.origin);
entity rocket = rocket = vehicles_projectile("wakizashi_rocket_launch", "weapons/rocket_fire.wav",
v, v_forward * autocvar_g_vehicle_racer_rocket_speed,
autocvar_g_vehicle_racer_rocket_damage, autocvar_g_vehicle_racer_rocket_radius, autocvar_g_vehicle_racer_rocket_force, 3,
- DEATH_WAKIROCKET, PROJECTILE_WAKIROCKET, 20, FALSE, FALSE, self.owner);
+ DEATH_VH_WAKI_ROCKET, PROJECTILE_WAKIROCKET, 20, FALSE, FALSE, self.owner);
rocket.lip = autocvar_g_vehicle_racer_rocket_accel * sys_frametime;
rocket.wait = autocvar_g_vehicle_racer_rocket_turnrate;
autocvar_g_vehicle_racer_blowup_edgedamage,
autocvar_g_vehicle_racer_blowup_radius, world,
autocvar_g_vehicle_racer_blowup_forceintensity,
- DEATH_WAKIBLOWUP, world);
+ DEATH_VH_WAKI_DEATH, world);
self.nextthink = time + autocvar_g_vehicle_racer_respawntime;
- self.think = racer_spawn;
+ self.think = racer_spawn_default;
self.movetype = MOVETYPE_NONE;
self.effects = EF_NODRAW;
self.velocity = '0 0 0';
setorigin(self, self.pos1);
- self.think = racer_spawn;
- self.nextthink = time + autocvar_g_vehicle_racer_respawntime;
}
void racer_deadtouch()
void racer_die()
{
self.health = 0;
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
self.solid = SOLID_CORPSE;
self.takedamage = DAMAGE_NO;
self.deadflag = DEAD_DYING;
self.damageforcescale = 0.5;
//self.destvec = autocvar_g_vehicle_racer_bouncepain;
}
+void racer_spawn_default()
+{
+ racer_spawn(0);
+}
RadiusDamage (self, self.realowner, autocvar_g_vehicle_raptor_bomblet_damage,
autocvar_g_vehicle_raptor_bomblet_edgedamage,
autocvar_g_vehicle_raptor_bomblet_radius, world,
- autocvar_g_vehicle_raptor_bomblet_force, DEATH_RAPTOR_BOMB, world);
+ autocvar_g_vehicle_raptor_bomblet_force, DEATH_VH_RAPT_BOMB, world);
remove(self);
}
entity bomblet;
float i;
- Damage_DamageInfo(self.origin, 0, 0, 0, '0 0 0', DEATH_RAPTOR_BOMB_SPLIT, 0, self);
+ Damage_DamageInfo(self.origin, 0, 0, 0, '0 0 0', DEATH_VH_RAPT_FRAGMENT, 0, self);
for(i = 0; i < autocvar_g_vehicle_raptor_bomblets; ++i)
{
vehicles_projectile("raptor_cannon_muzzleflash", "weapons/lasergun_fire.wav",
gettaginfo(gun, gettagindex(gun, tagname)), normalize(v_forward + randomvec() * autocvar_g_vehicle_raptor_cannon_spread) * autocvar_g_vehicle_raptor_cannon_speed,
autocvar_g_vehicle_raptor_cannon_damage, autocvar_g_vehicle_raptor_cannon_radius, autocvar_g_vehicle_raptor_cannon_force, 0,
- DEATH_RAPTOR_CANNON, PROJECTILE_RAPTORCANNON, 0, TRUE, TRUE, self.owner);
+ DEATH_VH_RAPT_CANNON, PROJECTILE_RAPTORCANNON, 0, TRUE, TRUE, self.owner);
}
void raptor_think()
{
self.deadflag = DEAD_DEAD;
self.vehicle_exit(VHEF_NORMAL);
- RadiusDamage (self, self.enemy, 250, 15, 250, world, 250, DEATH_WAKIBLOWUP, world);
+ RadiusDamage (self, self.enemy, 250, 15, 250, world, 250, DEATH_VH_RAPT_DEATH, world);
self.alpha = -1;
self.movetype = MOVETYPE_NONE;
self.velocity = '0 0 0';
setorigin(self, self.pos1);
- self.touch = SUB_Null;
+ self.touch = func_null;
self.nextthink = 0;
}
void raptor_die()
{
self.health = 0;
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
self.solid = SOLID_CORPSE;
self.takedamage = DAMAGE_NO;
self.deadflag = DEAD_DYING;
{
vector v;
- entity rocket;
+ entity rocket = world;
if (self.wait != -10)
{
rocket = vehicles_projectile("spiderbot_rocket_launch", "weapons/rocket_fire.wav",
v, normalize(randomvec() * autocvar_g_vehicle_spiderbot_rocket_spread + v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
- DEATH_SBROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, FALSE, TRUE, self.owner);
+ DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, FALSE, TRUE, self.owner);
crosshair_trace(self.owner);
float _dist = (random() * autocvar_g_vehicle_spiderbot_rocket_radius) + vlen(v - trace_endpos);
_dist -= (random() * autocvar_g_vehicle_spiderbot_rocket_radius) ;
rocket = vehicles_projectile("spiderbot_rocket_launch", "weapons/rocket_fire.wav",
v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
- DEATH_SBROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, FALSE, FALSE, self.owner);
+ DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, FALSE, FALSE, self.owner);
crosshair_trace(self.owner);
rocket.pos1 = trace_endpos;
rocket.nextthink = time;
rocket = vehicles_projectile("spiderbot_rocket_launch", "weapons/rocket_fire.wav",
v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
- DEATH_SBROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, FALSE, TRUE, self.owner);
+ DEATH_VH_SPID_ROCKET, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, FALSE, TRUE, self.owner);
crosshair_trace(self.owner);
- vector _ct_end = trace_endpos + trace_plane_normal;
rocket.pos1 = trace_endpos + randomvec() * (0.75 * autocvar_g_vehicle_spiderbot_rocket_radius);
rocket.pos1_z = trace_endpos_z;
v_forward = normalize(v_forward);
v += v_forward * 50;
-//void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, float lifetime, float damage, float headshotbonus, float force, float dtype, float tracereffects, float gravityfactor, float bulletconstant)
+//void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, float lifetime, float damage, float force, float dtype, float tracereffects, float gravityfactor, float bulletconstant)
fireBallisticBullet(v, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_speed,
- 5, autocvar_g_vehicle_spiderbot_minigun_damage, 0, autocvar_g_vehicle_spiderbot_minigun_force, DEATH_SBMINIGUN, 0, 1, autocvar_g_vehicle_spiderbot_minigun_bulletconstant);
+ 5, autocvar_g_vehicle_spiderbot_minigun_damage, autocvar_g_vehicle_spiderbot_minigun_force, DEATH_VH_SPID_MINIGUN, 0, 1, autocvar_g_vehicle_spiderbot_minigun_bulletconstant);
+
endFireBallisticBullet();
// fireBullet (v, v_forward, autocvar_g_vehicle_spiderbot_minigun_spread, autocvar_g_vehicle_spiderbot_minigun_damage,
-// autocvar_g_vehicle_spiderbot_minigun_spread, DEATH_SBMINIGUN, 0);
+// autocvar_g_vehicle_spiderbot_minigun_spread, DEATH_VH_SPID_MINIGUN, 0);
sound (gun, CH_WEAPON_A, "weapons/uzi_fire.wav", VOL_BASE, ATTN_NORM);
//trailparticles(self, particleeffectnum("spiderbot_minigun_trail"), v, trace_endpos);
SUB_SetFade(g1, time, min(autocvar_g_vehicle_spiderbot_respawntime, 10));
SUB_SetFade(g2, time, min(autocvar_g_vehicle_spiderbot_respawntime, 10));
- RadiusDamage (self, self.enemy, 250, 15, 250, world, 250, DEATH_SBBLOWUP, world);
+ RadiusDamage (self, self.enemy, 250, 15, 250, world, 250, DEATH_VH_SPID_DEATH, world);
self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = -1;
self.movetype = MOVETYPE_NONE;
void spiderbot_die()
{
self.health = 0;
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
self.takedamage = DAMAGE_NO;
- self.touch = SUB_Null;
+ self.touch = func_null;
self.cnt = 3.4 + time + random() * 2;
self.think = spiderbot_blowup;
self.nextthink = time;
if(self.health < 1)
{
self.takedamage = DAMAGE_NO;
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
self.think = self.use;
self.nextthink = time;
}
PROJECTILE_TOUCH;
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
RadiusDamage (self, self.realowner, self.shot_dmg, 0, self.shot_radius, self, self.shot_force, self.totalfrags, other);
remove (self);
if(vehicles_crushable(other))
{
if(vlen(self.velocity) != 0)
- Damage(other, self, self.owner, autocvar_g_vehicles_crush_dmg, DEATH_VHCRUSH, '0 0 0', normalize(other.origin - self.origin) * autocvar_g_vehicles_crush_force);
+ Damage(other, self, self.owner, autocvar_g_vehicles_crush_dmg, DEATH_VH_CRUSH, '0 0 0', normalize(other.origin - self.origin) * autocvar_g_vehicles_crush_force);
return; // Dont do selfdamage when hitting "soft targets".
}
self.owner.movetype = MOVETYPE_NOCLIP;
self.owner.alpha = -1;
self.owner.vehicle = self;
- self.owner.event_damage = SUB_Null;
+ self.owner.event_damage = func_null;
self.owner.view_ofs = '0 0 0';
self.colormap = self.owner.colormap;
if(self.tur_head)
_player.movetype = MOVETYPE_WALK;
_player.effects &~= EF_NODRAW;
_player.alpha = 1;
- _player.PlayerPhysplug = SUB_Null;
+ _player.PlayerPhysplug = func_null;
_player.vehicle = world;
_player.view_ofs = PL_VIEW_OFS;
_player.event_damage = PlayerDamage;
void vehicles_showwp()
{
- entity oldself;
+ entity oldself = world;
vector rgb;
if(self.cnt)
}
if(teamplay && self.team)
- rgb = TeamColor(self.team);
+ rgb = Team_ColorRGB(self.team);
else
rgb = '1 1 1';
WaypointSprite_Spawn("vehicle", 0, 0, self, '0 0 64', world, 0, self, waypointsprite_attached, TRUE, RADARICON_POWERUP, rgb);
void vehicles_reset_colors()
{
entity e;
- float _effects, _colormap;
+ float _effects = 0, _colormap;
vector _glowmod, _colormod;
if(autocvar_g_nodepthtestplayers)
- _effects = EF_NODEPTHTEST;
+ _effects |= EF_NODEPTHTEST;
if(autocvar_g_fullbrightplayers)
_effects |= EF_FULLBRIGHT;
//.void() vehicle_spawn;
void vehicles_exit(float eject);
-var .void(float exit_flags) vehicle_exit;
+.void(float exit_flags) vehicle_exit;
float VHEF_NORMAL = 0; /// User pressed exit key
float VHEF_EJECT = 1; /// User pressed exit key 3 times fast (not implemented) or vehile is dying
float VHEF_RELESE = 2; /// Release ownership, client possibly allready dissconnected / went spec / changed team / used "kill" (not implemented)
float SVC_SETVIEWANGLES = 10; // Net.Protocol 0x0A
float SVC_UPDATEENTITY = 128; // Net.Protocol 0x80
-var .void() vehicle_enter; /// Vehicles custom funciton to be executed when owner exit it
-var .void() vehicle_die; /// Vehicles custom function to be executed when vehile die
+.void() vehicle_enter; /// Vehicles custom funciton to be executed when owner exit it
+.void() vehicle_die; /// Vehicles custom function to be executed when vehile die
#define VHSF_NORMAL 0
#define VHSF_FACTORY 2
-var .void(float _spawnflag) vehicle_spawn; /// Vehicles custom fucntion to be efecuted when vehicle (re)spawns
-const var .float(float _imp) vehicles_impusle_null;
-var .float(float _imp) vehicles_impusle;
+.void(float _spawnflag) vehicle_spawn; /// Vehicles custom fucntion to be efecuted when vehicle (re)spawns
+.float(float _imp) vehicles_impusle;
.float vehicle_weapon2mode = volly_counter;
-//§ var .void() vehicle_factory()
+//§ .void() vehicle_factory()
#ifdef VEHICLES_USE_ODE
void(entity e, float physics_enabled) physics_enable = #540; // enable or disable physics on object
-void W_GiveWeapon (entity e, float wep, string name)
+void W_GiveWeapon (entity e, float wep)
{
entity oldself;
self = e;
if not(g_minstagib)
- if (other.classname == "player")
- {
- sprint (other, "You got the ^2");
- sprint (other, name);
- sprint (other, "\n");
- }
+ if(other.classname == "player")
+ { Send_Notification(NOTIF_ONE, other, MSG_MULTI, ITEM_WEAPON_GOT, wep); }
self = oldself;
}
trace_dphitq3surfaceflags = endq3surfaceflags;
}
-.float dmg_edge;
.float dmg_force;
.float dmg_radius;
.float dmg_total;
{
endzcurveparticles();
- headshot = 0;
yoda = 0;
- damage_headshotbonus = self.dmg_edge * f;
railgun_start = self.origin - 2 * frametime * self.velocity;
railgun_end = self.origin + 2 * frametime * self.velocity;
g = accuracy_isgooddamage(self.realowner, other);
Damage(other, self, self.realowner, self.dmg * f, self.projectiledeathtype, self.origin, self.dmg_force * normalize(self.velocity) * f);
- damage_headshotbonus = 0;
- if(headshot)
- f *= q;
- if(self.dmg_edge > 0)
- {
- if(headshot)
- AnnounceTo(self.realowner, "headshot");
- if(yoda)
- AnnounceTo(self.realowner, "awesome");
- }
+ if(yoda)
+ AnnounceTo(self.realowner, "awesome");
// calculate hits for ballistic weapons
if(g)
self.think = self.W_BallisticBullet_LeaveSolid_think_save;
self.nextthink = max(time, self.W_BallisticBullet_LeaveSolid_nextthink_save);
- self.W_BallisticBullet_LeaveSolid_think_save = SUB_Null;
+ self.W_BallisticBullet_LeaveSolid_think_save = func_null;
self.flags &~= FL_ONGROUND;
self.owner = world;
}
-void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, float lifetime, float damage, float headshotbonus, float force, float dtype, float tracereffects, float gravityfactor, float bulletconstant)
+void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, float lifetime, float damage, float force, float dtype, float tracereffects, float gravityfactor, float bulletconstant)
{
float lag, dt, savetime; //, density;
entity pl, oldself;
proj.touch = W_BallisticBullet_Touch;
proj.dmg = damage;
- proj.dmg_edge = headshotbonus;
proj.dmg_force = force;
proj.projectiledeathtype = dtype;
void W_PrepareExplosionByDamage(entity attacker, void() explode)
{
self.takedamage = DAMAGE_NO;
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
if((attacker.flags & FL_CLIENT) && !autocvar_g_projectiles_keep_owner)
{
float W_Crylink_Touch_WouldHitFriendly(entity projectile, float rad)
{
entity head = WarpZone_FindRadius((projectile.origin + (projectile.mins + projectile.maxs) * 0.5), rad + MAX_DAMAGEEXTRARADIUS, FALSE);
- float hit_friendly;
- float hit_enemy;
+ float hit_friendly = 0;
+ float hit_enemy = 0;
while(head)
{
{
W_Reload(min(autocvar_g_balance_crylink_primary_ammo, autocvar_g_balance_crylink_secondary_ammo), autocvar_g_balance_crylink_reload_ammo, autocvar_g_balance_crylink_reload_time, "weapons/reload.wav");
}
+ else if (req == WR_SUICIDEMESSAGE)
+ {
+ return WEAPON_CRYLINK_SUICIDE;
+ }
+ else if (req == WR_KILLMESSAGE)
+ {
+ return WEAPON_CRYLINK_MURDER;
+ }
return TRUE;
}
#endif
precache_sound("weapons/crylink_impact2.wav");
precache_sound("weapons/crylink_impact.wav");
}
- else if (req == WR_SUICIDEMESSAGE)
- {
- w_deathtypestring = _("%s succeeded at self-destructing themself with the Crylink");
- }
- else if (req == WR_KILLMESSAGE)
- {
- if(w_deathtype & HITTYPE_BOUNCE)
- w_deathtypestring = _("%s could not hide from %s's Crylink"); // unchecked: SPLASH (SECONDARY can't be)
- else if(w_deathtype & HITTYPE_SPLASH)
- w_deathtypestring = _("%s was too close to %s's Crylink"); // unchecked: SECONDARY
- else
- w_deathtypestring = _("%s took a close look at %s's Crylink"); // unchecked: SECONDARY
- }
return TRUE;
}
#endif
if(IsFlying(other))
AnnounceTo(self.realowner, "electrobitch");
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
self.takedamage = DAMAGE_NO;
if (self.movetype == MOVETYPE_BOUNCE)
{
{
W_Plasma_TriggerCombo(self.origin, autocvar_g_balance_electro_combo_comboradius, self.realowner);
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
RadiusDamage (self, self.realowner, autocvar_g_balance_electro_combo_damage, autocvar_g_balance_electro_combo_edgedamage, autocvar_g_balance_electro_combo_radius, world, autocvar_g_balance_electro_combo_force, WEP_ELECTRO | HITTYPE_BOUNCE, world); // use THIS type for a combo because primary can't bounce
remove (self);
}
{
if(autocvar_g_balance_electro_reload_ammo) // forced reload
{
+ ammo_amount = 0;
if(autocvar_g_balance_electro_lightning)
{
if(self.clip_load > 0)
{
if(autocvar_g_balance_electro_lightning)
if(self.BUTTON_ATCK_prev)
- {
- // prolong the animtime while the gun is being fired
- if(self.animstate_startframe == self.anim_shoot_x && self.animstate_numframes == self.anim_shoot_y)
- weapon_thinkf(WFRAME_DONTCHANGE, autocvar_g_balance_electro_primary_animtime, w_ready);
- else
- weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_electro_primary_animtime, w_ready);
- }
+ weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_electro_primary_animtime, w_ready);
+
if (weapon_prepareattack(0, (autocvar_g_balance_electro_lightning ? 0 : autocvar_g_balance_electro_primary_refire)))
{
if(autocvar_g_balance_electro_lightning)
{
W_Reload(min(autocvar_g_balance_electro_primary_ammo, autocvar_g_balance_electro_secondary_ammo), autocvar_g_balance_electro_reload_ammo, autocvar_g_balance_electro_reload_time, "weapons/reload.wav");
}
+ else if (req == WR_SUICIDEMESSAGE)
+ {
+ if(w_deathtype & HITTYPE_SECONDARY)
+ return WEAPON_ELECTRO_SUICIDE_ORBS;
+ else
+ return WEAPON_ELECTRO_SUICIDE_BOLT;
+ }
+ else if (req == WR_KILLMESSAGE)
+ {
+ if(w_deathtype & HITTYPE_SECONDARY)
+ {
+ return WEAPON_ELECTRO_MURDER_ORBS;
+ }
+ else
+ {
+ if(w_deathtype & HITTYPE_BOUNCE)
+ return WEAPON_ELECTRO_MURDER_COMBO;
+ else
+ return WEAPON_ELECTRO_MURDER_BOLT;
+ }
+ }
return TRUE;
}
#endif
precache_sound("weapons/electro_impact.wav");
precache_sound("weapons/electro_impact_combo.wav");
}
- else if (req == WR_SUICIDEMESSAGE)
- {
- if(w_deathtype & HITTYPE_SECONDARY)
- w_deathtypestring = _("%s could not remember where they put their electro plasma");
- else
- w_deathtypestring = _("%s played with electro plasma");
- }
- else if (req == WR_KILLMESSAGE)
- {
- if(w_deathtype & HITTYPE_SECONDARY)
- {
- if(w_deathtype & HITTYPE_SPLASH) // unchecked: BOUNCE
- w_deathtypestring = _("%s just noticed %s's electro plasma");
- else // unchecked: BOUNCE
- w_deathtypestring = _("%s got in touch with %s's electro plasma");
- }
- else
- {
- if(w_deathtype & HITTYPE_BOUNCE) // combo
- w_deathtypestring = _("%s felt the electrifying air of %s's electro combo");
- else if(w_deathtype & HITTYPE_SPLASH)
- w_deathtypestring = _("%s got too close to %s's blue electro bolt");
- else
- w_deathtypestring = _("%s was blasted by %s's blue electro bolt");
- }
- }
return TRUE;
}
#endif
vector dir;
float d;
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
self.takedamage = DAMAGE_NO;
// 1. dist damage
{
PROJECTILE_TOUCH;
if (other.takedamage == DAMAGE_AIM)
- if(Fire_AddDamage(other, self.realowner, autocvar_g_balance_fireball_secondary_damage, autocvar_g_balance_fireball_secondary_damagetime, self.projectiledeathtype | HITTYPE_HEADSHOT) >= 0)
+ if(Fire_AddDamage(other, self.realowner, autocvar_g_balance_fireball_secondary_damage, autocvar_g_balance_fireball_secondary_damagetime, self.projectiledeathtype) >= 0)
{
remove(self);
return;
{
self.fireball_primarytime = time;
}
+ else if (req == WR_SUICIDEMESSAGE)
+ {
+ if(w_deathtype & HITTYPE_SECONDARY)
+ return WEAPON_FIREBALL_SUICIDE_FIREMINE;
+ else
+ return WEAPON_FIREBALL_SUICIDE_BLAST;
+ }
+ else if (req == WR_KILLMESSAGE)
+ {
+ if(w_deathtype & HITTYPE_SECONDARY)
+ {
+ return WEAPON_FIREBALL_MURDER_FIREMINE;
+ }
+ else
+ {
+ return WEAPON_FIREBALL_MURDER_BLAST;
+ }
+ }
return TRUE;
}
#endif
{
precache_sound("weapons/fireball_impact2.wav");
}
- else if (req == WR_SUICIDEMESSAGE)
- {
- if(w_deathtype & HITTYPE_SECONDARY)
- w_deathtypestring = _("%s forgot about some firemine");
- else
- w_deathtypestring = _("%s should have used a smaller gun");
- }
- else if (req == WR_KILLMESSAGE)
- {
- if(w_deathtype & HITTYPE_SECONDARY)
- {
- if(w_deathtype & HITTYPE_HEADSHOT)
- w_deathtypestring = _("%s tried to catch %s's firemine");
- else
- w_deathtypestring = _("%s fatefully ignored %s's firemine");
- }
- else
- {
- if(w_deathtype & HITTYPE_BOUNCE)
- {
- if(w_deathtype & HITTYPE_SPLASH) // BFG effect
- w_deathtypestring = _("%s could not hide from %s's fireball");
- else // laser
- w_deathtypestring = _("%s saw the pretty lights of %s's fireball");
- }
- else if(w_deathtype & HITTYPE_SPLASH)
- w_deathtypestring = _("%s got too close to %s's fireball");
- else
- w_deathtypestring = _("%s tasted %s's fireball");
- }
- }
+
return TRUE;
}
#endif
if(IsFlying(other))
AnnounceTo(self.realowner, "airshot");
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
self.takedamage = DAMAGE_NO;
if(self.movetype == MOVETYPE_NONE)
if(IsFlying(other))
AnnounceTo(self.realowner, "airshot");
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
self.takedamage = DAMAGE_NO;
if(self.movetype == MOVETYPE_NONE)
{
W_Reload(min(autocvar_g_balance_grenadelauncher_primary_ammo, autocvar_g_balance_grenadelauncher_secondary_ammo), autocvar_g_balance_grenadelauncher_reload_ammo, autocvar_g_balance_grenadelauncher_reload_time, "weapons/reload.wav");
}
+ else if (req == WR_SUICIDEMESSAGE)
+ {
+ if(w_deathtype & HITTYPE_SECONDARY)
+ return WEAPON_MORTAR_SUICIDE_BOUNCE;
+ else
+ return WEAPON_MORTAR_SUICIDE_EXPLODE;
+ }
+ else if (req == WR_KILLMESSAGE)
+ {
+ if(w_deathtype & HITTYPE_SECONDARY)
+ return WEAPON_MORTAR_MURDER_BOUNCE;
+ else
+ return WEAPON_MORTAR_MURDER_EXPLODE;
+ }
return TRUE;
}
#endif
{
precache_sound("weapons/grenade_impact.wav");
}
- else if (req == WR_SUICIDEMESSAGE)
- {
- if(w_deathtype & HITTYPE_SECONDARY)
- w_deathtypestring = _("%s didn't see their own grenade");
- else
- w_deathtypestring = _("%s blew themself up with their grenadelauncher");
- }
- else if (req == WR_KILLMESSAGE)
- {
- if(w_deathtype & HITTYPE_SPLASH)
- if(w_deathtype & HITTYPE_BOUNCE) // (must be secondary then)
- w_deathtypestring = _("%s didn't see %s's grenade");
- else // unchecked: SECONDARY
- w_deathtypestring = _("%s almost dodged %s's grenade");
- else // unchecked: SECONDARY, BOUNCE
- w_deathtypestring = _("%s ate %s's grenade");
- }
return TRUE;
}
#endif
void W_Hagar_Explode (void)
{
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
RadiusDamage (self, self.realowner, autocvar_g_balance_hagar_primary_damage, autocvar_g_balance_hagar_primary_edgedamage, autocvar_g_balance_hagar_primary_radius, world, autocvar_g_balance_hagar_primary_force, self.projectiledeathtype, other);
remove (self);
void W_Hagar_Explode2 (void)
{
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
RadiusDamage (self, self.realowner, autocvar_g_balance_hagar_secondary_damage, autocvar_g_balance_hagar_secondary_edgedamage, autocvar_g_balance_hagar_secondary_radius, world, autocvar_g_balance_hagar_secondary_force, self.projectiledeathtype, other);
remove (self);
else if (req == WR_THINK)
{
float loadable_secondary;
- loadable_secondary = autocvar_g_balance_hagar_secondary_load && autocvar_g_balance_hagar_secondary;
+ loadable_secondary = (autocvar_g_balance_hagar_secondary_load && autocvar_g_balance_hagar_secondary);
if (loadable_secondary)
W_Hagar_Attack2_Load(); // must always run each frame
if not(self.hagar_load) // require releasing loaded rockets first
W_Reload(min(autocvar_g_balance_hagar_primary_ammo, autocvar_g_balance_hagar_secondary_ammo), autocvar_g_balance_hagar_reload_ammo, autocvar_g_balance_hagar_reload_time, "weapons/reload.wav");
}
+ else if (req == WR_SUICIDEMESSAGE)
+ {
+ return WEAPON_HAGAR_SUICIDE;
+ }
+ else if (req == WR_KILLMESSAGE)
+ {
+ if(w_deathtype & HITTYPE_SECONDARY)
+ return WEAPON_HAGAR_MURDER_BURST;
+ else
+ return WEAPON_HAGAR_MURDER_SPRAY;
+ }
return TRUE;
}
#endif
precache_sound("weapons/hagexp2.wav");
precache_sound("weapons/hagexp3.wav");
}
- else if (req == WR_SUICIDEMESSAGE)
- w_deathtypestring = _("%s played with tiny hagar rockets");
- else if (req == WR_KILLMESSAGE)
- {
- if(w_deathtype & HITTYPE_BOUNCE) // must be secondary; unchecked: SPLASH
- w_deathtypestring = _("%s was pummeled with a burst of hagar rockets by %s");
- else // unchecked: SPLASH, SECONDARY
- w_deathtypestring = _("%s was pummeled with hagar rockets by %s");
- }
return TRUE;
}
#endif
{
PROJECTILE_TOUCH;
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
if(self.projectiledeathtype & HITTYPE_SECONDARY)
RadiusDamage (self, self.realowner, autocvar_g_balance_hlac_secondary_damage, autocvar_g_balance_hlac_secondary_edgedamage, autocvar_g_balance_hlac_secondary_radius, world, autocvar_g_balance_hlac_secondary_force, self.projectiledeathtype, other);
{
W_Reload(min(autocvar_g_balance_hlac_primary_ammo, autocvar_g_balance_hlac_secondary_ammo), autocvar_g_balance_hlac_reload_ammo, autocvar_g_balance_hlac_reload_time, "weapons/reload.wav");
}
+ else if (req == WR_SUICIDEMESSAGE)
+ {
+ return WEAPON_HLAC_SUICIDE;
+ }
+ else if (req == WR_KILLMESSAGE)
+ {
+ return WEAPON_HLAC_MURDER;
+ }
return TRUE;
}
#endif
{
precache_sound("weapons/laserimpact.wav");
}
- else if (req == WR_SUICIDEMESSAGE)
- w_deathtypestring = _("%s should have used a smaller gun");
- else if (req == WR_KILLMESSAGE)
- w_deathtypestring = _("%s was cut down with a HLAC by %s");
return TRUE;
}
#endif
void W_Hook_Explode2 (void)
{
- self.event_damage = SUB_Null;
- self.touch = SUB_Null;
+ self.event_damage = func_null;
+ self.touch = func_null;
self.effects |= EF_NODRAW;
self.think = W_Hook_ExplodeThink;
{
self.hook_refire = time;
}
+ else if (req == WR_SUICIDEMESSAGE)
+ {
+ return FALSE;
+ }
+ else if (req == WR_KILLMESSAGE)
+ {
+ return WEAPON_HOOK_MURDER;
+ }
return TRUE;
}
#endif
{
precache_sound("weapons/hookbomb_impact.wav");
}
- else if (req == WR_SUICIDEMESSAGE)
- w_deathtypestring = _("%s did the impossible");
- else if (req == WR_KILLMESSAGE)
- w_deathtypestring = _("%s was caught in %s's hook gravity bomb");
return TRUE;
}
#endif
{
PROJECTILE_TOUCH;
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
if (self.dmg)
RadiusDamage (self, self.realowner, autocvar_g_balance_laser_secondary_damage, autocvar_g_balance_laser_secondary_edgedamage, autocvar_g_balance_laser_secondary_radius, world, autocvar_g_balance_laser_secondary_force, self.projectiledeathtype, other);
else
{
W_Reload(0, autocvar_g_balance_laser_reload_ammo, autocvar_g_balance_laser_reload_time, "weapons/reload.wav");
}
+ else if (req == WR_SUICIDEMESSAGE)
+ {
+ return WEAPON_LASER_SUICIDE;
+ }
+ else if (req == WR_KILLMESSAGE)
+ {
+ return WEAPON_LASER_MURDER;
+ }
return TRUE;
}
#endif
{
precache_sound("weapons/laserimpact.wav");
}
- else if (req == WR_SUICIDEMESSAGE)
- w_deathtypestring = _("%s lasered themself to hell");
- else if (req == WR_KILLMESSAGE)
- {
- if(w_deathtype & HITTYPE_SECONDARY)
- w_deathtypestring = _("%s was cut in half by %s's gauntlet"); // unchecked: SPLASH
- else
- w_deathtypestring = _("%s was lasered to death by %s"); // unchecked: SPLASH
- }
return TRUE;
}
#endif
void W_Mine_Think (void);
.float minelayer_detonate, mine_explodeanyway;
.float mine_time;
+.vector mine_orientation;
void spawnfunc_weapon_minelayer (void)
{
setmodel(newmine, "models/mine.md3");
newmine.angles = vectoangles(-trace_plane_normal); // face against the surface
- newmine.oldvelocity = self.velocity;
+ newmine.mine_orientation = -trace_plane_normal;
newmine.takedamage = self.takedamage;
newmine.damageforcescale = self.damageforcescale;
newmine.mine_time = self.mine_time;
- newmine.touch = SUB_Null;
+ newmine.touch = func_null;
newmine.think = W_Mine_Think;
newmine.nextthink = time;
newmine.cnt = self.cnt;
if(IsFlying(other))
AnnounceTo(self.realowner, "airshot");
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
self.takedamage = DAMAGE_NO;
RadiusDamage (self, self.realowner, autocvar_g_balance_minelayer_damage, autocvar_g_balance_minelayer_edgedamage, autocvar_g_balance_minelayer_radius, world, autocvar_g_balance_minelayer_force, self.projectiledeathtype, other);
void W_Mine_DoRemoteExplode ()
{
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
self.takedamage = DAMAGE_NO;
if(self.movetype == MOVETYPE_NONE || self.movetype == MOVETYPE_FOLLOW)
- self.velocity = self.oldvelocity;
+ self.velocity = self.mine_orientation; // particle fx and decals need .velocity
RadiusDamage (self, self.realowner, autocvar_g_balance_minelayer_remote_damage, autocvar_g_balance_minelayer_remote_edgedamage, autocvar_g_balance_minelayer_remote_radius, world, autocvar_g_balance_minelayer_remote_force, self.projectiledeathtype | HITTYPE_BOUNCE, world);
entity mine;
for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.realowner == e)
minecount += 1;
-
+
return minecount;
}
if(self.movetype == MOVETYPE_NONE || self.movetype == MOVETYPE_FOLLOW)
return; // we're already a stuck mine, why do we get called? TODO does this even happen?
- PROJECTILE_TOUCH;
+ if(WarpZone_Projectile_Touch())
+ {
+ if(wasfreed(self))
+ self.realowner.minelayer_mines -= 1;
+ return;
+ }
if(other && other.classname == "player" && other.deadflag == DEAD_NO)
{
// scan how many mines we placed, and return if we reached our limit
if(autocvar_g_balance_minelayer_limit)
{
-
- if(W_Mine_Count(self) >= autocvar_g_balance_minelayer_limit)
+ if(self.minelayer_mines >= autocvar_g_balance_minelayer_limit)
{
// the refire delay keeps this message from being spammed
sprint(self, strcat("minelayer: You cannot place more than ^2", ftos(autocvar_g_balance_minelayer_limit), " ^7mines at a time\n") );
if (req == WR_AIM)
{
// aim and decide to fire if appropriate
- self.BUTTON_ATCK = bot_aim(autocvar_g_balance_minelayer_speed, 0, autocvar_g_balance_minelayer_lifetime, FALSE);
+ if(self.minelayer_mines >= autocvar_g_balance_minelayer_limit)
+ self.BUTTON_ATCK = FALSE;
+ else
+ self.BUTTON_ATCK = bot_aim(autocvar_g_balance_minelayer_speed, 0, autocvar_g_balance_minelayer_lifetime, FALSE);
if(skill >= 2) // skill 0 and 1 bots won't detonate mines!
{
// decide whether to detonate mines
else
return FALSE;
}
+ else if (req == WR_RESETPLAYER)
+ {
+ self.minelayer_mines = 0;
+ }
else if (req == WR_RELOAD)
{
W_Reload(autocvar_g_balance_minelayer_ammo, autocvar_g_balance_minelayer_reload_ammo, autocvar_g_balance_minelayer_reload_time, "weapons/reload.wav");
}
+ else if (req == WR_SUICIDEMESSAGE)
+ {
+ return WEAPON_MINELAYER_SUICIDE;
+ }
+ else if (req == WR_KILLMESSAGE)
+ {
+ return WEAPON_MINELAYER_MURDER;
+ }
return TRUE;
}
#endif
{
precache_sound("weapons/mine_exp.wav");
}
- else if (req == WR_SUICIDEMESSAGE)
- if(w_deathtype & HITTYPE_BOUNCE) // (remote detonation)
- w_deathtypestring = _("%s blew themself up with their minelayer");
- else
- w_deathtypestring = _("%s forgot about their mine");
- else if (req == WR_KILLMESSAGE)
- {
- if(w_deathtype & HITTYPE_BOUNCE) // (remote detonation)
- w_deathtypestring = _("%s got too close to %s's mine");
- else if(w_deathtype & HITTYPE_SPLASH)
- w_deathtypestring = _("%s almost dodged %s's mine");
- else
- w_deathtypestring = _("%s stepped on %s's mine");
- }
return TRUE;
}
#endif
yoda = 0;
damage_goodhits = 0;
- headshot = 0;
- damage_headshotbonus = -1; // no extra damage, just count
FireRailgunBullet (w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, 10000, 800, 0, 0, 0, 0, WEP_MINSTANEX);
- damage_headshotbonus = 0;
if(g_minstagib)
{
{
if(yoda && flying)
AnnounceTo(self, "yoda");
- if(headshot)
- {
- AnnounceTo(self, "headshot");
- }
if(damage_goodhits && self.minstanex_lasthit)
{
- if(AnnounceTo(self, "impressive"))
- damage_goodhits = 0; // only every second time
+ AnnounceTo(self, "impressive");
+ damage_goodhits = 0; // only every second time
}
}
{
switch(self.team)
{
- case COLOR_TEAM1: // Red
+ case NUM_TEAM_1: // Red
if(damage_goodhits)
WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED_HIT"), w_shotorg, v);
else
WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED"), w_shotorg, v);
break;
- case COLOR_TEAM2: // Blue
+ case NUM_TEAM_2: // Blue
if(damage_goodhits)
WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE_HIT"), w_shotorg, v);
else
WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE"), w_shotorg, v);
break;
- case COLOR_TEAM3: // Yellow
+ case NUM_TEAM_3: // Yellow
if(damage_goodhits)
WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW_HIT"), w_shotorg, v);
else
WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW"), w_shotorg, v);
break;
- case COLOR_TEAM4: // Pink
+ case NUM_TEAM_4: // Pink
if(damage_goodhits)
WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK_HIT"), w_shotorg, v);
else
{
if (!e.minstagib_needammo)
return;
- Send_CSQC_Centerprint_Generic_Expire(e, CPID_MINSTA_FINDAMMO);
+ Kill_Notification(NOTIF_ONE_ONLY, e, MSG_CENTER_CPID, CPID_MINSTA_FINDAMMO);
e.minstagib_needammo = FALSE;
}
void minstagib_ammocheck(void)
}
else if (self.health == 90)
{
- Send_CSQC_Centerprint_Generic(self, CPID_MINSTA_FINDAMMO, "^1%d^7 seconds left to find some ammo", 1, 9);
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MINSTA_FINDAMMO);
Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
AnnounceTo(self, "9");
}
else if (self.health == 100)
{
- Send_CSQC_Centerprint_Generic(self, CPID_MINSTA_FINDAMMO, "get some ammo or\nyou'll be dead in ^3%d^7 seconds...", 1, 10);
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MINSTA_FINDAMMO_FIRST);
Damage(self, self, self, 10, DEATH_NOAMMO, self.origin, '0 0 0');
if not(self.flags & FL_GODMODE)
AnnounceTo(self, "10");
W_Reload(used_ammo, autocvar_g_balance_minstanex_reload_ammo, autocvar_g_balance_minstanex_reload_time, "weapons/reload.wav");
}
+ else if (req == WR_SUICIDEMESSAGE)
+ {
+ return WEAPON_THINKING_WITH_PORTALS;
+ }
+ else if (req == WR_KILLMESSAGE)
+ {
+ return WEAPON_MINSTANEX_MURDER;
+ }
return TRUE;
}
#endif
{
precache_sound("weapons/neximpact.wav");
}
- else if (req == WR_SUICIDEMESSAGE)
- w_deathtypestring = _("%s is now thinking with portals");
- else if (req == WR_KILLMESSAGE)
- w_deathtypestring = _("%s has been vaporized by %s's minstanex");
return TRUE;
}
#endif
{
W_Reload(min(autocvar_g_balance_nex_primary_ammo, autocvar_g_balance_nex_secondary_ammo), autocvar_g_balance_nex_reload_ammo, autocvar_g_balance_nex_reload_time, "weapons/reload.wav");
}
-
+ else if (req == WR_SUICIDEMESSAGE)
+ {
+ return WEAPON_THINKING_WITH_PORTALS;
+ }
+ else if (req == WR_KILLMESSAGE)
+ {
+ return WEAPON_NEX_MURDER;
+ }
return TRUE;
}
#endif
{
precache_sound("weapons/neximpact.wav");
}
- else if (req == WR_SUICIDEMESSAGE)
- w_deathtypestring = _("%s is now thinking with portals");
- else if (req == WR_KILLMESSAGE)
- w_deathtypestring = _("%s has been vaporized by %s's nex");
return TRUE;
}
#endif
{
// nothing to do
}
- else if (req == WR_SUICIDEMESSAGE)
- w_deathtypestring = _("%s did the impossible");
- else if (req == WR_KILLMESSAGE)
- w_deathtypestring = _("%s felt %s doing the impossible to him");
return TRUE;
}
#endif
.float rifle_accumulator;
-void W_Rifle_FireBullet(float pSpread, float pDamage, float pHeadshotAddedDamage, float pForce, float pSpeed, float pLifetime, float pAmmo, float deathtype, float pBulletConstant, float pTracer, float pShots, string pSound)
+void W_Rifle_FireBullet(float pSpread, float pDamage, float pForce, float pSpeed, float pLifetime, float pAmmo, float deathtype, float pBulletConstant, float pTracer, float pShots, string pSound)
{
float i;
W_DecreaseAmmo(ammo_nails, pAmmo, autocvar_g_balance_rifle_reload_ammo);
- W_SetupShot (self, autocvar_g_antilag_bullets && pSpeed >= autocvar_g_antilag_bullets, 2, pSound, CH_WEAPON_A, (pDamage + pHeadshotAddedDamage) * pShots);
+ W_SetupShot (self, autocvar_g_antilag_bullets && pSpeed >= autocvar_g_antilag_bullets, 2, pSound, CH_WEAPON_A, pDamage * pShots);
pointparticles(particleeffectnum("rifle_muzzleflash"), w_shotorg, w_shotdir * 2000, 1);
}
for(i = 0; i < pShots; ++i)
- fireBallisticBullet(w_shotorg, w_shotdir, pSpread, pSpeed, pLifetime, pDamage, pHeadshotAddedDamage / pDamage, pForce, deathtype, (pTracer ? EF_RED : EF_BLUE), 1, pBulletConstant);
+ fireBallisticBullet(w_shotorg, w_shotdir, pSpread, pSpeed, pLifetime, pDamage, pForce, deathtype, (pTracer ? EF_RED : EF_BLUE), 1, pBulletConstant);
endFireBallisticBullet();
if (autocvar_g_casings >= 2)
void W_Rifle_Attack()
{
- W_Rifle_FireBullet(autocvar_g_balance_rifle_primary_spread, autocvar_g_balance_rifle_primary_damage, autocvar_g_balance_rifle_primary_headshotaddeddamage, autocvar_g_balance_rifle_primary_force, autocvar_g_balance_rifle_primary_speed, autocvar_g_balance_rifle_primary_lifetime, autocvar_g_balance_rifle_primary_ammo, WEP_RIFLE, autocvar_g_balance_rifle_primary_bulletconstant, autocvar_g_balance_rifle_primary_tracer, autocvar_g_balance_rifle_primary_shots, "weapons/campingrifle_fire.wav");
+ W_Rifle_FireBullet(autocvar_g_balance_rifle_primary_spread, autocvar_g_balance_rifle_primary_damage, autocvar_g_balance_rifle_primary_force, autocvar_g_balance_rifle_primary_speed, autocvar_g_balance_rifle_primary_lifetime, autocvar_g_balance_rifle_primary_ammo, WEP_RIFLE, autocvar_g_balance_rifle_primary_bulletconstant, autocvar_g_balance_rifle_primary_tracer, autocvar_g_balance_rifle_primary_shots, "weapons/campingrifle_fire.wav");
}
void W_Rifle_Attack2()
{
- W_Rifle_FireBullet(autocvar_g_balance_rifle_secondary_spread, autocvar_g_balance_rifle_secondary_damage, autocvar_g_balance_rifle_secondary_headshotaddeddamage, autocvar_g_balance_rifle_secondary_force, autocvar_g_balance_rifle_secondary_speed, autocvar_g_balance_rifle_secondary_lifetime, autocvar_g_balance_rifle_secondary_ammo, WEP_RIFLE | HITTYPE_SECONDARY, autocvar_g_balance_rifle_secondary_bulletconstant, autocvar_g_balance_rifle_secondary_tracer, autocvar_g_balance_rifle_secondary_shots, "weapons/campingrifle_fire2.wav");
+ W_Rifle_FireBullet(autocvar_g_balance_rifle_secondary_spread, autocvar_g_balance_rifle_secondary_damage, autocvar_g_balance_rifle_secondary_force, autocvar_g_balance_rifle_secondary_speed, autocvar_g_balance_rifle_secondary_lifetime, autocvar_g_balance_rifle_secondary_ammo, WEP_RIFLE | HITTYPE_SECONDARY, autocvar_g_balance_rifle_secondary_bulletconstant, autocvar_g_balance_rifle_secondary_tracer, autocvar_g_balance_rifle_secondary_shots, "weapons/campingrifle_fire2.wav");
}
void spawnfunc_weapon_rifle (void)
{
W_Reload(min(autocvar_g_balance_rifle_primary_ammo, autocvar_g_balance_rifle_secondary_ammo), autocvar_g_balance_rifle_reload_ammo, autocvar_g_balance_rifle_reload_time, "weapons/reload.wav");
}
+ else if (req == WR_SUICIDEMESSAGE)
+ {
+ return WEAPON_THINKING_WITH_PORTALS;
+ }
+ else if (req == WR_KILLMESSAGE)
+ {
+ if(w_deathtype & HITTYPE_SECONDARY)
+ {
+ if(w_deathtype & HITTYPE_BOUNCE)
+ return WEAPON_RIFLE_MURDER_HAIL_PIERCING;
+ else
+ return WEAPON_RIFLE_MURDER_HAIL;
+ }
+ else
+ {
+ if(w_deathtype & HITTYPE_BOUNCE)
+ return WEAPON_RIFLE_MURDER_PIERCING;
+ else
+ return WEAPON_RIFLE_MURDER;
+ }
+ }
return TRUE;
}
#endif
precache_sound("weapons/ric2.wav");
precache_sound("weapons/ric3.wav");
}
- else if (req == WR_SUICIDEMESSAGE)
- {
- w_deathtypestring = _("%s is now thinking with portals");
- }
- else if (req == WR_KILLMESSAGE)
- {
- if(w_deathtype & HITTYPE_SECONDARY)
- {
- if(w_deathtype & HITTYPE_BOUNCE)
- w_deathtypestring = _("%s failed to hide from %s's rifle bullet hail");
- else
- w_deathtypestring = _("%s died in %s's rifle bullet hail");
- }
- else
- {
- if(w_deathtype & HITTYPE_BOUNCE)
- {
- // TODO special headshot message here too?
- w_deathtypestring = _("%s failed to hide from %s's rifle");
- }
- else
- {
- if(w_deathtype & HITTYPE_HEADSHOT)
- w_deathtypestring = _("%s got shot in the head with a rifle by %s");
- else
- w_deathtypestring = _("%s was sniped with a rifle by %s");
- }
- }
- }
+
return TRUE;
}
#endif
if(IsFlying(other))
AnnounceTo(self.realowner, "airshot");
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
self.takedamage = DAMAGE_NO;
RadiusDamage (self, self.realowner, autocvar_g_balance_rocketlauncher_damage, autocvar_g_balance_rocketlauncher_edgedamage, autocvar_g_balance_rocketlauncher_radius, world, autocvar_g_balance_rocketlauncher_force, self.projectiledeathtype, other);
{
W_Rocket_Unregister();
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
self.takedamage = DAMAGE_NO;
RadiusDamage (self, self.realowner, autocvar_g_balance_rocketlauncher_remote_damage, autocvar_g_balance_rocketlauncher_remote_edgedamage, autocvar_g_balance_rocketlauncher_remote_radius, world, autocvar_g_balance_rocketlauncher_remote_force, self.projectiledeathtype | HITTYPE_BOUNCE, world);
// don't switch while guiding a missile
if (ATTACK_FINISHED(self) <= time || self.weapon != WEP_ROCKET_LAUNCHER)
{
+ ammo_amount = FALSE;
if(autocvar_g_balance_rocketlauncher_reload_ammo)
{
if(self.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo && self.(weapon_load[WEP_ROCKET_LAUNCHER]) < autocvar_g_balance_rocketlauncher_ammo)
{
W_Reload(autocvar_g_balance_rocketlauncher_ammo, autocvar_g_balance_rocketlauncher_reload_ammo, autocvar_g_balance_rocketlauncher_reload_time, "weapons/reload.wav");
}
+ else if (req == WR_SUICIDEMESSAGE)
+ {
+ return WEAPON_ROCKETLAUNCHER_SUICIDE;
+ }
+ else if (req == WR_KILLMESSAGE)
+ {
+ if((w_deathtype & HITTYPE_BOUNCE) || (w_deathtype & HITTYPE_SPLASH))
+ return WEAPON_ROCKETLAUNCHER_MURDER_SPLASH;
+ else
+ return WEAPON_ROCKETLAUNCHER_MURDER_DIRECT;
+ }
return TRUE;
}
#endif
{
precache_sound("weapons/rocket_impact.wav");
}
- else if (req == WR_SUICIDEMESSAGE)
- w_deathtypestring = _("%s blew themself up with their rocketlauncher");
- else if (req == WR_KILLMESSAGE)
- {
- if(w_deathtype & HITTYPE_BOUNCE) // (remote detonation)
- w_deathtypestring = _("%s got too close to %s's rocket");
- else if(w_deathtype & HITTYPE_SPLASH)
- w_deathtypestring = _("%s almost dodged %s's rocket");
- else
- w_deathtypestring = _("%s ate %s's rocket");
- }
return TRUE;
}
#endif
// ============================
void Seeker_Missile_Explode ()
{
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
RadiusDamage (self, self.realowner, autocvar_g_balance_seeker_missile_damage, autocvar_g_balance_seeker_missile_edgedamage, autocvar_g_balance_seeker_missile_radius, world, autocvar_g_balance_seeker_missile_force, self.projectiledeathtype, other);
remove (self);
// ============================
void Seeker_Flac_Explode ()
{
- self.event_damage = SUB_Null;
+ self.event_damage = func_null;
RadiusDamage (self, self.realowner, autocvar_g_balance_seeker_flac_damage, autocvar_g_balance_seeker_flac_edgedamage, autocvar_g_balance_seeker_flac_radius, world, autocvar_g_balance_seeker_flac_force, self.projectiledeathtype, other);
te_knightspike(org2);
- self.event_damage = SUB_Null;
- Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER | HITTYPE_HEADSHOT, other.species, self);
+ self.event_damage = func_null;
+ Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER | HITTYPE_BOUNCE | HITTYPE_SECONDARY, other.species, self);
if (other.takedamage == DAMAGE_AIM && other.deadflag == DEAD_NO)
{
missile.solid = SOLID_BBOX;
missile.takedamage = DAMAGE_YES;
- missile.event_damage = Seeker_Tag_Explode;
- missile.health = autocvar_g_balance_seeker_tag_health;
+ missile.event_damage = Seeker_Tag_Damage;
+ missile.health = autocvar_g_balance_seeker_tag_health;
missile.damageforcescale = autocvar_g_balance_seeker_tag_damageforcescale;
setorigin (missile, w_shotorg);
}
else if (req == WR_CHECKAMMO1)
{
- ammo_amount = self.ammo_rockets >= autocvar_g_balance_seeker_missile_ammo;
- ammo_amount += self.(weapon_load[WEP_SEEKER]) >= autocvar_g_balance_seeker_missile_ammo;
+ if (autocvar_g_balance_seeker_type == 1)
+ {
+ ammo_amount = self.ammo_rockets >= autocvar_g_balance_seeker_missile_ammo;
+ ammo_amount += self.(weapon_load[WEP_SEEKER]) >= autocvar_g_balance_seeker_missile_ammo;
+ }
+ else
+ {
+ ammo_amount = self.ammo_rockets >= autocvar_g_balance_seeker_tag_ammo;
+ ammo_amount += self.(weapon_load[WEP_SEEKER]) >= autocvar_g_balance_seeker_tag_ammo;
+ }
+
return ammo_amount;
}
else if (req == WR_CHECKAMMO2)
{
- ammo_amount = self.ammo_rockets >= autocvar_g_balance_seeker_tag_ammo;
- ammo_amount += self.(weapon_load[WEP_SEEKER]) >= autocvar_g_balance_seeker_tag_ammo;
+ if (autocvar_g_balance_seeker_type == 1)
+ {
+ ammo_amount = self.ammo_rockets >= autocvar_g_balance_seeker_tag_ammo;
+ ammo_amount += self.(weapon_load[WEP_SEEKER]) >= autocvar_g_balance_seeker_tag_ammo;
+ }
+ else
+ {
+ ammo_amount = self.ammo_rockets >= autocvar_g_balance_seeker_flac_ammo;
+ ammo_amount += self.(weapon_load[WEP_SEEKER]) >= autocvar_g_balance_seeker_flac_ammo;
+ }
+
return ammo_amount;
}
else if (req == WR_RELOAD)
{
W_Reload(min(autocvar_g_balance_seeker_missile_ammo, autocvar_g_balance_seeker_tag_ammo), autocvar_g_balance_seeker_reload_ammo, autocvar_g_balance_seeker_reload_time, "weapons/reload.wav");
}
+ else if (req == WR_SUICIDEMESSAGE)
+ {
+ return WEAPON_SEEKER_SUICIDE;
+ }
+ else if (req == WR_KILLMESSAGE)
+ {
+ if(w_deathtype & HITTYPE_SECONDARY)
+ return WEAPON_SEEKER_MURDER_TAG;
+ else
+ return WEAPON_SEEKER_MURDER_SPRAY;
+ }
return TRUE;
}
#endif
org2 = w_org + w_backoff * 6;
if(w_deathtype & HITTYPE_BOUNCE)
{
- pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1);
- if(!w_issilent)
+ if(w_deathtype & HITTYPE_SECONDARY)
{
- if (w_random<0.15)
- sound(self, CH_SHOTS, "weapons/tagexp1.wav", 1, ATTN_NORM);
- else if (w_random<0.7)
- sound(self, CH_SHOTS, "weapons/tagexp2.wav", 1, ATTN_NORM);
- else
- sound(self, CH_SHOTS, "weapons/tagexp3.wav", 1, ATTN_NORM);
+ if(!w_issilent)
+ sound(self, CH_SHOTS, "weapons/tag_impact.wav", 1, ATTN_NORM);
+ }
+ else
+ {
+ pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1);
+ if(!w_issilent)
+ {
+ if (w_random<0.15)
+ sound(self, CH_SHOTS, "weapons/tagexp1.wav", 1, ATTN_NORM);
+ else if (w_random<0.7)
+ sound(self, CH_SHOTS, "weapons/tagexp2.wav", 1, ATTN_NORM);
+ else
+ sound(self, CH_SHOTS, "weapons/tagexp3.wav", 1, ATTN_NORM);
+ }
}
- }
- else if(w_deathtype & HITTYPE_HEADSHOT)
- {
- if(!w_issilent)
- sound(self, CH_SHOTS, "weapons/tag_impact.wav", 1, ATTN_NORM);
}
else
{
precache_sound("weapons/tagexp3.wav");
precache_sound("weapons/tag_impact.wav");
}
- else if (req == WR_SUICIDEMESSAGE)
- w_deathtypestring = _("%s played with tiny seeker rockets");
- else if (req == WR_KILLMESSAGE)
- {
- if(w_deathtype & HITTYPE_SECONDARY)
- w_deathtypestring = _("%s was tagged with a seeker by %s");
- else
- w_deathtypestring = _("%s was pummeled with seeker rockets by %s");
- }
return TRUE;
}
#endif
W_SetupShot (self, autocvar_g_antilag_bullets && bulletspeed >= autocvar_g_antilag_bullets, 5, "weapons/shotgun_fire.wav", CH_WEAPON_A, d * bullets);
for (sc = 0;sc < bullets;sc = sc + 1)
- fireBallisticBullet(w_shotorg, w_shotdir, spread, bulletspeed, 5, d, 0, f, WEP_SHOTGUN, 0, 1, bulletconstant);
+ fireBallisticBullet(w_shotorg, w_shotdir, spread, bulletspeed, 5, d, f, WEP_SHOTGUN, 0, 1, bulletconstant);
endFireBallisticBullet();
pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 1000, autocvar_g_balance_shotgun_primary_ammo);
}
}
if (self.clip_load >= 0) // we are not currently reloading
- if (!self.crouch) // we are not currently crouching; this fixes an exploit where your melee anim is not visible, and besides wouldn't make much sense
+ if (!self.crouch) // no crouchmelee please
if (self.BUTTON_ATCK2 && autocvar_g_balance_shotgun_secondary)
if (weapon_prepareattack(1, autocvar_g_balance_shotgun_secondary_refire))
{
{
W_Reload(autocvar_g_balance_shotgun_primary_ammo, autocvar_g_balance_shotgun_reload_ammo, autocvar_g_balance_shotgun_reload_time, "weapons/reload.wav");
}
+ else if (req == WR_SUICIDEMESSAGE)
+ {
+ return WEAPON_THINKING_WITH_PORTALS;
+ }
+ else if (req == WR_KILLMESSAGE)
+ {
+ if(w_deathtype & HITTYPE_SECONDARY)
+ return WEAPON_SHOTGUN_MURDER_SLAP;
+ else
+ return WEAPON_SHOTGUN_MURDER;
+ }
return TRUE;
}
#endif
precache_sound("weapons/ric2.wav");
precache_sound("weapons/ric3.wav");
}
- else if (req == WR_SUICIDEMESSAGE)
- w_deathtypestring = _("%s is now thinking with portals");
- else if (req == WR_KILLMESSAGE)
- {
- if(w_deathtype & HITTYPE_SECONDARY)
- w_deathtypestring = _("%2$s slapped %1$s around a bit with a large shotgun");
- else
- w_deathtypestring = _("%s was gunned down with a shotgun by %s");
- }
return TRUE;
}
#endif
case 1:
bprint(strcat("\{1}\{13}* ^3", self.owner.netname, "^3 played on the @!#%'n Accordeon: ^7", s, "\n"));
break;
+ case 2:
+ bprint(strcat("\{1}\{13}* ^3", self.owner.netname, "^3 played on the @!#%'n Klein Bottle: ^7", s, "\n"));
+ break;
}
}
}
if(pl.movement_x > 0) movestate += 3;
if(pl.movement_y < 0) movestate -= 1;
if(pl.movement_y > 0) movestate += 1;
+#ifdef GMQCC
+ note = 0;
+#endif
switch(movestate)
{
// layout: originally I wanted
// that way, holes in the range of notes are "plugged"
if(teamplay)
{
- if(pl.team == COLOR_TEAM2 || pl.team == COLOR_TEAM4)
+ if(pl.team == NUM_TEAM_2 || pl.team == NUM_TEAM_4)
note += 3;
}
else
hittype |= HITTYPE_SECONDARY;
if(self.tuba_instrument & 2)
hittype |= HITTYPE_BOUNCE;
- if(self.tuba_instrument & 4)
- hittype |= HITTYPE_HEADSHOT;
if(self.tuba_note)
{
precache_model ("models/weapons/g_tuba.md3");
precache_model ("models/weapons/v_tuba.md3");
precache_model ("models/weapons/h_tuba.iqm");
- precache_model ("models/weapons/g_akordeon.md3");
precache_model ("models/weapons/v_akordeon.md3");
precache_model ("models/weapons/h_akordeon.iqm");
+ precache_model ("models/weapons/v_kleinbottle.md3");
+ precache_model ("models/weapons/h_kleinbottle.iqm");
//float i;
//for(i = -18; i <= +27; ++i)
self.weaponname = "akordeon";
break;
case 1:
+ self.tuba_instrument = 2;
+ self.weaponname = "kleinbottle";
+ break;
+ case 2:
self.tuba_instrument = 0;
self.weaponname = "tuba";
break;
return TRUE; // TODO use fuel?
else if (req == WR_CHECKAMMO2)
return TRUE; // TODO use fuel?
- return TRUE;
-}
-#endif
-#ifdef CSQC
-float w_tuba(float req)
-{
- if(req == WR_IMPACTEFFECT)
- {
- // nothing to do here; particles of tuba are handled differently
- }
- else if(req == WR_PRECACHE)
- {
- // nothing to do
- }
else if (req == WR_SUICIDEMESSAGE)
{
- float instr;
- instr = 0;
- if(w_deathtype & HITTYPE_SECONDARY)
- instr |= 1;
if(w_deathtype & HITTYPE_BOUNCE)
- instr |= 2;
- if(w_deathtype & HITTYPE_HEADSHOT)
- instr |= 4;
- switch(instr)
- {
- default:
- case 0: // Tuba
- w_deathtypestring = _("%s hurt his own ears with the @!#%%'n Tuba");
- break;
- case 1: // Accordeon
- w_deathtypestring = _("%s hurt his own ears with the @!#%%'n Accordeon");
- break;
- }
+ return WEAPON_KLEINBOTTLE_SUICIDE;
+ else if(w_deathtype & HITTYPE_SECONDARY)
+ return WEAPON_ACCORDEON_SUICIDE;
+ else
+ return WEAPON_TUBA_SUICIDE;
}
else if (req == WR_KILLMESSAGE)
{
- float instr;
- instr = 0;
- if(w_deathtype & HITTYPE_SECONDARY)
- instr |= 1;
if(w_deathtype & HITTYPE_BOUNCE)
- instr |= 2;
- if(w_deathtype & HITTYPE_HEADSHOT)
- instr |= 4;
- switch(instr)
- {
- default:
- case 0: // Tuba
- w_deathtypestring = _("%s died of %s's great playing on the @!#%%'n Tuba");
- break;
- case 1: // Accordeon
- w_deathtypestring = _("%s died of %s's great playing on the @!#%%'n Accordeon");
- break;
- }
+ return WEAPON_KLEINBOTTLE_MURDER;
+ else if(w_deathtype & HITTYPE_SECONDARY)
+ return WEAPON_ACCORDEON_MURDER;
+ else
+ return WEAPON_TUBA_MURDER;
}
return TRUE;
}
#endif
+#ifdef CSQC
+float w_tuba(float req)
+{
+ // nothing to do here; particles of tuba are handled differently
+
+ return TRUE;
+}
+#endif
#endif
ATTACK_FINISHED(self) = time + autocvar_g_balance_uzi_first_refire * W_WeaponRateFactor();
if (self.misc_bulletcounter == 1)
- fireBallisticBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_first_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_first_damage, autocvar_g_balance_uzi_first_headshotaddeddamage, autocvar_g_balance_uzi_first_force, deathtype, 0, 1, autocvar_g_balance_uzi_bulletconstant);
+ fireBallisticBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_first_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_first_damage, autocvar_g_balance_uzi_first_force, deathtype, 0, 1, autocvar_g_balance_uzi_bulletconstant);
else
- fireBallisticBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_sustained_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_sustained_damage, autocvar_g_balance_uzi_sustained_headshotaddeddamage, autocvar_g_balance_uzi_sustained_force, deathtype, 0, 1, autocvar_g_balance_uzi_bulletconstant);
+ fireBallisticBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_sustained_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_sustained_damage, autocvar_g_balance_uzi_sustained_force, deathtype, 0, 1, autocvar_g_balance_uzi_bulletconstant);
endFireBallisticBullet();
pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
}
uzi_spread = bound(autocvar_g_balance_uzi_spread_min, autocvar_g_balance_uzi_spread_min + (autocvar_g_balance_uzi_spread_add * self.misc_bulletcounter), autocvar_g_balance_uzi_spread_max);
- fireBallisticBullet(w_shotorg, w_shotdir, uzi_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_sustained_damage, autocvar_g_balance_uzi_sustained_headshotaddeddamage, autocvar_g_balance_uzi_sustained_force, WEP_UZI, 0, 1, autocvar_g_balance_uzi_bulletconstant);
+ fireBallisticBullet(w_shotorg, w_shotdir, uzi_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_sustained_damage, autocvar_g_balance_uzi_sustained_force, WEP_UZI, 0, 1, autocvar_g_balance_uzi_bulletconstant);
endFireBallisticBullet();
self.misc_bulletcounter = self.misc_bulletcounter + 1;
self.punchangle_y = random () - 0.5;
}
- fireBallisticBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_burst_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_sustained_damage, autocvar_g_balance_uzi_sustained_headshotaddeddamage, autocvar_g_balance_uzi_sustained_force, WEP_UZI, 0, 1, autocvar_g_balance_uzi_bulletconstant);
+ fireBallisticBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_burst_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_sustained_damage, autocvar_g_balance_uzi_sustained_force, WEP_UZI, 0, 1, autocvar_g_balance_uzi_bulletconstant);
endFireBallisticBullet();
{
W_Reload(min(max(autocvar_g_balance_uzi_sustained_ammo, autocvar_g_balance_uzi_first_ammo), autocvar_g_balance_uzi_burst_ammo), autocvar_g_balance_uzi_reload_ammo, autocvar_g_balance_uzi_reload_time, "weapons/reload.wav");
}
+ else if (req == WR_SUICIDEMESSAGE)
+ {
+ return WEAPON_THINKING_WITH_PORTALS;
+ }
+ else if (req == WR_KILLMESSAGE)
+ {
+ if(w_deathtype & HITTYPE_SECONDARY)
+ return WEAPON_UZI_MURDER_SNIPE;
+ else
+ return WEAPON_UZI_MURDER_SPRAY;
+ }
return TRUE;
}
#endif
precache_sound("weapons/ric2.wav");
precache_sound("weapons/ric3.wav");
}
- else if (req == WR_SUICIDEMESSAGE)
- w_deathtypestring = _("%s is now thinking with portals");
- else if (req == WR_KILLMESSAGE)
- {
- if(w_deathtype & HITTYPE_SECONDARY)
- w_deathtypestring = _("%s was sniped by %s's machine gun");
- else
- w_deathtypestring = _("%s was riddled full of holes by %s's machine gun");
- }
return TRUE;
}
#endif
#define MOVE_NOTHING -1
entity WarpZone_trace_forent; // temp, callback is allowed to change it
typedef void(vector start, vector hit, vector end) WarpZone_trace_callback_t; // called on every elementary trace
-const var WarpZone_trace_callback_t WarpZone_trace_callback_t_null;
+var WarpZone_trace_callback_t WarpZone_trace_callback_t_null;
entity WarpZone_trace_transform; // transform accumulator during a trace
entity WarpZone_trace_firstzone; // first warpzone hit by a trace (can differ from the requested zone in case of _ThroughZone, the trace is aborted then)
entity WarpZone_trace_lastzone; // first warpzone hit by a trace (can differ from the requested zone in case of _ThroughZone, the trace is aborted then)
norm = normalize(norm);
}
+#ifdef GMQCC
+ ang = '0 0 0';
+#endif
if(self.aiment)
{
org = self.aiment.origin;