]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into terencehill/itemstime
authorterencehill <piuntn@gmail.com>
Mon, 18 Mar 2013 13:00:40 +0000 (14:00 +0100)
committerterencehill <piuntn@gmail.com>
Mon, 18 Mar 2013 13:00:40 +0000 (14:00 +0100)
Conflicts:
qcsrc/common/constants.qh
qcsrc/server/defs.qh

293 files changed:
Makefile
_hud_common.cfg
_hud_descriptions.cfg
balance25.cfg
balanceFruitieX.cfg
balanceXDF.cfg
balanceXPM.cfg
balanceXonotic.cfg
bf.cfg [new file with mode: 0644]
commands.cfg
defaultXonotic.cfg
gamemodes.cfg
hud_luminos.cfg
hud_luminos_minimal.cfg
hud_luminos_minimal_xhair.cfg
hud_luminos_old.cfg
hud_nexuiz.cfg
models/player/erebus.iqm_0.txt
models/player/gak.iqm_0.txt
models/player/gakarmored.iqm_0.txt
models/player/gakmasked.iqm_0.txt
models/player/ignis.iqm_0.txt
models/player/ignishalfmasked.iqm_0.txt
models/player/ignismasked.iqm_0.txt
models/player/megaerebus.iqm_0.txt
models/player/nyx.iqm_0.txt
models/player/pyria.iqm_0.txt
models/player/seraphina.iqm_0.txt
models/player/seraphinamasked.iqm_0.txt
models/player/template.md3.animinfo [deleted file]
models/player/umbra.iqm_0.txt
models/weapons/h_kleinbottle.iqm [new file with mode: 0644]
models/weapons/h_kleinbottle.iqm.framegroups [new file with mode: 0644]
models/weapons/v_kleinbottle.md3 [new file with mode: 0644]
mutator_new_toys.cfg
notifications.cfg [new file with mode: 0644]
qcsrc/Makefile
qcsrc/client/Defs.qc
qcsrc/client/Main.qc
qcsrc/client/View.qc
qcsrc/client/announcer.qc
qcsrc/client/autocvars.qh
qcsrc/client/casings.qc
qcsrc/client/command/cl_cmd.qc
qcsrc/client/command/cl_cmd.qh
qcsrc/client/csqc_builtins.qc
qcsrc/client/csqcmodel_hooks.qc
qcsrc/client/damage.qc
qcsrc/client/effects.qc
qcsrc/client/gibs.qc
qcsrc/client/hook.qc
qcsrc/client/hud.qc
qcsrc/client/hud.qh
qcsrc/client/hud_config.qc
qcsrc/client/laser.qc
qcsrc/client/main.qh
qcsrc/client/mapvoting.qc
qcsrc/client/miscfunctions.qc
qcsrc/client/modeleffects.qc
qcsrc/client/particles.qc
qcsrc/client/player_skeleton.qc [new file with mode: 0644]
qcsrc/client/player_skeleton.qh [new file with mode: 0644]
qcsrc/client/progs.src
qcsrc/client/projectile.qc
qcsrc/client/scoreboard.qc
qcsrc/client/shownames.qc
qcsrc/client/shownames.qh
qcsrc/client/teamplay.qc [deleted file]
qcsrc/client/teamplay.qh [deleted file]
qcsrc/client/teamradar.qc
qcsrc/client/tturrets.qc
qcsrc/client/tuba.qc
qcsrc/client/vehicles/vehicles.qc
qcsrc/client/wall.qc
qcsrc/client/waypointsprites.qc
qcsrc/common/animdecide.qc [new file with mode: 0644]
qcsrc/common/animdecide.qh [new file with mode: 0644]
qcsrc/common/command/generic.qc
qcsrc/common/command/generic.qh
qcsrc/common/command/rpn.qh
qcsrc/common/constants.qh
qcsrc/common/counting.qh [new file with mode: 0644]
qcsrc/common/csqcmodel_settings.qh
qcsrc/common/deathtypes.qh [new file with mode: 0644]
qcsrc/common/items.qc
qcsrc/common/items.qh
qcsrc/common/mapinfo.qc
qcsrc/common/net_notice.qc
qcsrc/common/notifications.qc [new file with mode: 0644]
qcsrc/common/notifications.qh [new file with mode: 0644]
qcsrc/common/teams.qh [new file with mode: 0644]
qcsrc/common/util-pre.qh
qcsrc/common/util.qc
qcsrc/common/util.qh
qcsrc/csqcmodellib/cl_model.qc
qcsrc/csqcmodellib/cl_model.qh
qcsrc/csqcmodellib/cl_player.qc
qcsrc/csqcmodellib/cl_player.qh
qcsrc/csqcmodellib/common.qh
qcsrc/csqcmodellib/interpolate.qc
qcsrc/csqcmodellib/interpolate.qh
qcsrc/dpdefs/csprogsdefs.qc
qcsrc/dpdefs/menudefs.qc
qcsrc/dpdefs/progsdefs.qc
qcsrc/menu/classes.c
qcsrc/menu/command/menu_cmd.qc
qcsrc/menu/item/button.c
qcsrc/menu/item/gecko.c [deleted file]
qcsrc/menu/item/listbox.c
qcsrc/menu/item/nexposee.c
qcsrc/menu/menu.qc
qcsrc/menu/menu.qh
qcsrc/menu/oo/implementation.h
qcsrc/menu/progs.src
qcsrc/menu/sys-post.qh [new file with mode: 0644]
qcsrc/menu/sys-pre.qh [new file with mode: 0644]
qcsrc/menu/xonotic/campaign.c
qcsrc/menu/xonotic/colorpicker.c
qcsrc/menu/xonotic/cvarlist.c
qcsrc/menu/xonotic/dialog_hudpanel_weapons.c
qcsrc/menu/xonotic/dialog_multiplayer_playersetup_model.c
qcsrc/menu/xonotic/dialog_news.c [deleted file]
qcsrc/menu/xonotic/dialog_settings_input.c
qcsrc/menu/xonotic/dialog_singleplayer.c
qcsrc/menu/xonotic/inputbox.c
qcsrc/menu/xonotic/keybinder.c
qcsrc/menu/xonotic/maplist.c
qcsrc/menu/xonotic/serverlist.c
qcsrc/menu/xonotic/util.qc
qcsrc/server/antilag.qc
qcsrc/server/arena.qc
qcsrc/server/assault.qc
qcsrc/server/attic/ctf.qc
qcsrc/server/attic/domination.qc [new file with mode: 0644]
qcsrc/server/attic/monsters/m_monsters.qc
qcsrc/server/attic/monsters/monster_zombie.qc
qcsrc/server/attic/nexball.qc
qcsrc/server/attic/vehicles/bumblebee.qc
qcsrc/server/autocvars.qh
qcsrc/server/bot/bot.qc
qcsrc/server/bot/havocbot/role_onslaught.qc
qcsrc/server/bot/havocbot/roles.qc
qcsrc/server/bot/scripting.qc
qcsrc/server/bot/waypoints.qc
qcsrc/server/builtins.qh [deleted file]
qcsrc/server/cl_client.qc
qcsrc/server/cl_physics.qc
qcsrc/server/cl_player.qc
qcsrc/server/cl_weapons.qc
qcsrc/server/cl_weaponsystem.qc
qcsrc/server/command/banning.qh
qcsrc/server/command/cmd.qc
qcsrc/server/command/common.qc
qcsrc/server/command/getreplies.qc
qcsrc/server/command/sv_cmd.qc
qcsrc/server/command/vote.qc
qcsrc/server/constants.qh
qcsrc/server/defs.qh
qcsrc/server/domination.qc [deleted file]
qcsrc/server/func_breakable.qc
qcsrc/server/g_damage.qc
qcsrc/server/g_hook.qc
qcsrc/server/g_lights.qc
qcsrc/server/g_subs.qc
qcsrc/server/g_tetris.qc
qcsrc/server/g_triggers.qc
qcsrc/server/g_world.qc
qcsrc/server/ipban.qc
qcsrc/server/item_key.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/mutators/base.qc
qcsrc/server/mutators/base.qh
qcsrc/server/mutators/gamemode_ctf.qc
qcsrc/server/mutators/gamemode_ctf.qh
qcsrc/server/mutators/gamemode_domination.qc [new file with mode: 0644]
qcsrc/server/mutators/gamemode_domination.qh [new file with mode: 0644]
qcsrc/server/mutators/gamemode_freezetag.qc
qcsrc/server/mutators/gamemode_keepaway.qc
qcsrc/server/mutators/gamemode_keyhunt.qc
qcsrc/server/mutators/gamemode_keyhunt.qh
qcsrc/server/mutators/gamemode_nexball.qc
qcsrc/server/mutators/gamemode_onslaught.qc
qcsrc/server/mutators/mutator_dodging.qc
qcsrc/server/mutators/mutator_new_toys.qc
qcsrc/server/mutators/mutator_nix.qc
qcsrc/server/mutators/mutator_physical_items.qc [new file with mode: 0644]
qcsrc/server/mutators/mutator_superspec.qc
qcsrc/server/mutators/mutator_vampire.qc
qcsrc/server/mutators/mutators.qh
qcsrc/server/mutators/sandbox.qc
qcsrc/server/pathlib.qc
qcsrc/server/pathlib/main.qc
qcsrc/server/pathlib/movenode.qc
qcsrc/server/pathlib/pathlib.qh
qcsrc/server/playerstats.qc
qcsrc/server/playerstats.qh
qcsrc/server/portals.qc
qcsrc/server/progs.src
qcsrc/server/race.qc
qcsrc/server/runematch.qc
qcsrc/server/scores.qc
qcsrc/server/scores.qh
qcsrc/server/scores_rules.qc
qcsrc/server/secret.qc
qcsrc/server/sv_main.qc
qcsrc/server/t_items.qc
qcsrc/server/t_jumppads.qc
qcsrc/server/t_plats.qc
qcsrc/server/t_teleporters.qc
qcsrc/server/teamplay.qc
qcsrc/server/todo.txt [deleted file]
qcsrc/server/tturrets/system/system_aimprocs.qc
qcsrc/server/tturrets/system/system_damage.qc
qcsrc/server/tturrets/system/system_main.qc
qcsrc/server/tturrets/system/system_misc.qc
qcsrc/server/tturrets/system/system_scoreprocs.qc
qcsrc/server/tturrets/units/unit_machinegun.qc
qcsrc/server/tturrets/units/unit_phaser.qc
qcsrc/server/tturrets/units/unit_tessla.qc
qcsrc/server/tturrets/units/unit_walker.qc
qcsrc/server/vehicles/bumblebee.qc
qcsrc/server/vehicles/racer.qc
qcsrc/server/vehicles/raptor.qc
qcsrc/server/vehicles/spiderbot.qc
qcsrc/server/vehicles/vehicles.qc
qcsrc/server/vehicles/vehicles_def.qh
qcsrc/server/w_common.qc
qcsrc/server/w_crylink.qc
qcsrc/server/w_electro.qc
qcsrc/server/w_fireball.qc
qcsrc/server/w_grenadelauncher.qc
qcsrc/server/w_hagar.qc
qcsrc/server/w_hlac.qc
qcsrc/server/w_hook.qc
qcsrc/server/w_laser.qc
qcsrc/server/w_minelayer.qc
qcsrc/server/w_minstanex.qc
qcsrc/server/w_nex.qc
qcsrc/server/w_porto.qc
qcsrc/server/w_rifle.qc
qcsrc/server/w_rocketlauncher.qc
qcsrc/server/w_seeker.qc
qcsrc/server/w_shotgun.qc
qcsrc/server/w_tuba.qc
qcsrc/server/w_uzi.qc
qcsrc/warpzonelib/common.qh
qcsrc/warpzonelib/server.qc
sound/weapons/tuba2_loopnote-12.ogg [new file with mode: 0644]
sound/weapons/tuba2_loopnote-18.ogg [new file with mode: 0644]
sound/weapons/tuba2_loopnote-6.ogg [new file with mode: 0644]
sound/weapons/tuba2_loopnote0.ogg [new file with mode: 0644]
sound/weapons/tuba2_loopnote12.ogg [new file with mode: 0644]
sound/weapons/tuba2_loopnote18.ogg [new file with mode: 0644]
sound/weapons/tuba2_loopnote24.ogg [new file with mode: 0644]
sound/weapons/tuba2_loopnote6.ogg [new file with mode: 0644]
sound/weapons/tuba_loopnote-1.ogg [deleted file]
sound/weapons/tuba_loopnote-10.ogg [deleted file]
sound/weapons/tuba_loopnote-11.ogg [deleted file]
sound/weapons/tuba_loopnote-13.ogg [deleted file]
sound/weapons/tuba_loopnote-14.ogg [deleted file]
sound/weapons/tuba_loopnote-15.ogg [deleted file]
sound/weapons/tuba_loopnote-16.ogg [deleted file]
sound/weapons/tuba_loopnote-17.ogg [deleted file]
sound/weapons/tuba_loopnote-2.ogg [deleted file]
sound/weapons/tuba_loopnote-3.ogg [deleted file]
sound/weapons/tuba_loopnote-4.ogg [deleted file]
sound/weapons/tuba_loopnote-5.ogg [deleted file]
sound/weapons/tuba_loopnote-7.ogg [deleted file]
sound/weapons/tuba_loopnote-8.ogg [deleted file]
sound/weapons/tuba_loopnote-9.ogg [deleted file]
sound/weapons/tuba_loopnote1.ogg [deleted file]
sound/weapons/tuba_loopnote10.ogg [deleted file]
sound/weapons/tuba_loopnote11.ogg [deleted file]
sound/weapons/tuba_loopnote13.ogg [deleted file]
sound/weapons/tuba_loopnote14.ogg [deleted file]
sound/weapons/tuba_loopnote15.ogg [deleted file]
sound/weapons/tuba_loopnote16.ogg [deleted file]
sound/weapons/tuba_loopnote17.ogg [deleted file]
sound/weapons/tuba_loopnote19.ogg [deleted file]
sound/weapons/tuba_loopnote2.ogg [deleted file]
sound/weapons/tuba_loopnote20.ogg [deleted file]
sound/weapons/tuba_loopnote21.ogg [deleted file]
sound/weapons/tuba_loopnote22.ogg [deleted file]
sound/weapons/tuba_loopnote23.ogg [deleted file]
sound/weapons/tuba_loopnote25.ogg [deleted file]
sound/weapons/tuba_loopnote26.ogg [deleted file]
sound/weapons/tuba_loopnote27.ogg [deleted file]
sound/weapons/tuba_loopnote3.ogg [deleted file]
sound/weapons/tuba_loopnote4.ogg [deleted file]
sound/weapons/tuba_loopnote5.ogg [deleted file]
sound/weapons/tuba_loopnote7.ogg [deleted file]
sound/weapons/tuba_loopnote8.ogg [deleted file]
sound/weapons/tuba_loopnote9.ogg [deleted file]

index 6d0e9a617f2c875c84036faf78a9be5c148ab734..bdac716b79444e302668067c6f62c5b8b8b86c71 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -4,10 +4,6 @@ ZIP ?= 7za a -tzip -mx=9
 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 =
 
index 7420b1a85dee1448648885bd08925a7fe2704ee4..8ab874555db8fefd96507e533d2d6af86732a107 100644 (file)
@@ -5,9 +5,20 @@ seta hud_configure_checkcollisions 0 "check for collisions against other panels
 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"
@@ -30,13 +41,14 @@ seta hud_panel_itemstime_progressbar_maxtime "30" "when left time is at least th
 
 // 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"
 
@@ -91,4 +103,4 @@ seta hud_shownames_mindistance 1000 "start fading alpha/size at this distance"
 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"
index 8fe2e3580275ce0d24f39f10191f1c76cccdaf3f..5b092524515d8282efea82af72451e43c1c2c4da 100644 (file)
@@ -52,8 +52,12 @@ seta hud_panel_weapons_complainbubble_color_unavailable "" "color of the complai
 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"
@@ -122,7 +126,6 @@ seta hud_panel_notify_bg_border "" "if set to something else than \"\" = overrid
 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"
 
@@ -152,6 +155,8 @@ seta hud_panel_radar_zoommode "" "zoom mode: 0 = zoomed by default, 1 = zoomed w
 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"
index 068f650f8f443e841deb73004c25874a35495653..666482f4a365423b4a47dbed4e0a1b5866711b19 100644 (file)
@@ -306,14 +306,12 @@ set g_balance_uzi_burst_ammo 3
 
 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
index 5ccd6827b60626eb3574fa740d4ee2a46fdd8c15..cd73187ec8daa95f35912c92d17c4bb24bc1a86a 100644 (file)
@@ -306,14 +306,12 @@ set g_balance_uzi_burst_ammo 3
 
 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
index 543a5c6176909d0ad811e91727d4a456931c86a9..514433c3269bc782851bf842e054aa95456c71b9 100644 (file)
@@ -306,14 +306,12 @@ set g_balance_uzi_burst_ammo 3
 
 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
index cd440294c054be3d391685f4107a3e604979a08c..fc02dc9cb2779daa53589b7916de455efcc60756 100644 (file)
@@ -306,14 +306,12 @@ set g_balance_uzi_burst_ammo 3
 
 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
index 871b9a390f2a39fc8daa1b59d6f0bbe34f3b50fa..a0252cb48bfdbf89b048af8063580be3fa9c8a58 100644 (file)
@@ -306,14 +306,12 @@ set g_balance_uzi_burst_ammo 3
 
 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
diff --git a/bf.cfg b/bf.cfg
new file mode 100644 (file)
index 0000000..6445def
--- /dev/null
+++ b/bf.cfg
@@ -0,0 +1,98 @@
+// 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 "+ + + + + + + + + + [ > + + + + + + + > + + + + + + + + + + > + + + > + < < < < - ] > + + . > + . + + + + + + + . . + + + . > + + . < < + + + + + + + + + + + + + + + . > . + + + . - - - - - - . - - - - - - - - . > + . > ."
index 881c0359aca39c8a9626f43d67b1b1b7bcae182f..70ee53ecb027ade180ba8dfe4855c0e9c4709d2e 100644 (file)
@@ -11,6 +11,10 @@ alias if_dedicated "${* asis}"
 _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 $${* !}"
@@ -52,11 +56,13 @@ alias who                  "qc_cmd_svcmd  who                  ${* ?}" // Displa
 
 // 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
@@ -81,6 +87,7 @@ alias addvote "qc_cmd_svmenu addtolist sv_vote_commands ${* ?}"
 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 ${* ?}"
@@ -287,7 +294,7 @@ set sv_vote_command_restriction_movetopink "1;"
 // =================================
 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"
@@ -301,6 +308,7 @@ set sv_vote_wait 120        "a player can not call a vote again for this many seconds w
 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
 
index 3c269391e8d5d656d93d0b25a0245fe5ec9bc3e3..386817f2c981466c80468a26e5a3d53b4b642df5 100644 (file)
@@ -62,6 +62,9 @@ seta cl_velocityzoom 0        "velocity based zooming of fov, negative values zoom out"
 seta cl_velocityzoom_type 3 "how to factor in speed, 1 = all velocity in all directions, 2 = velocity only in forward direction (can be negative), 3 = velocity only in forward direction (limited to forward only)"
 seta cl_velocityzoom_speed 1000 "target speed for fov factoring"
 seta cl_velocityzoom_time 0.2  "time value for averaging speed values"
+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)"
@@ -176,6 +179,9 @@ set cl_hitsound_antispam_time 0.05 "don't play the hitsound more often than this
 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)"
@@ -238,7 +244,6 @@ set sv_friction_on_land 0
 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"
@@ -247,7 +252,6 @@ set sv_doublejump 0 "allow Quake 2-style double jumps"
 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
@@ -482,7 +486,7 @@ seta g_teamdamage_resetspeed 20     "for teamplay 4: how fast player's teamdamage co
 
 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)"
 
@@ -579,6 +583,7 @@ seta cl_announcer_maptime 3 "play announcer sound telling you the remaining mapt
 
 // 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"
 
@@ -813,6 +818,7 @@ set g_chat_flood_lmax_tell 2        "private chat: maximum number of lines per chat mes
 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"
@@ -936,6 +942,7 @@ con_chat 5
 con_chatpos -9
 con_chatsize 10
 con_chatwidth 0.6
+con_notify 0
 con_notifysize 10
 con_notifyalign 0
 
@@ -946,6 +953,7 @@ seta scoreboard_columns default
 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"
@@ -964,6 +972,7 @@ seta scoreboard_offset_left 0.15 "how far (by percent) the scoreboard is offset
 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"
@@ -1016,6 +1025,7 @@ set con_completion_ply            *.dem
 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
@@ -1066,6 +1076,10 @@ alias sethostname "set menu_use_default_hostname 0; hostname $*"
 
 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\""
@@ -1226,7 +1240,6 @@ set g_jetpack 0 "Jetpack mutator (uses the hook's button, can't coexist with the
 
 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"
@@ -1287,10 +1300,6 @@ set sv_weaponstats_file "" "when set to a file name, per-weapon stats get writte
 
 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"
@@ -1312,14 +1321,13 @@ set developer_csqcentities 0 "csqc entity spam"
 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"
@@ -1433,6 +1441,8 @@ r_shadow_glossintensity 1
 // 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"
@@ -1545,6 +1555,7 @@ exec turrets.cfg
 exec vehicles.cfg
 exec crosshairs.cfg
 exec gamemodes.cfg
+exec notifications.cfg
 
 // load console command aliases and settings
 exec commands.cfg
index 6cff7e5a42666ab32954c8ec8d5abb757b1a09f6..05aaf3df40530d1379b0976ed83fbbb334d0b017 100644 (file)
@@ -197,7 +197,6 @@ set g_ctf_flag_collect_delay 1
 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"
@@ -343,7 +342,6 @@ set g_lms 0 "Last Man Standing: everyone starts with a certain amount of lives,
 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"
@@ -405,6 +403,11 @@ set g_onslaught_cp_health 1000
 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
 
 
 // ======
index ebf06360251cf34416092eea238ba38bc2a19ed6..2a147d72a9627dbcc3466895a29e4d56afdf2fa5 100644 (file)
@@ -42,9 +42,9 @@ seta hud_panel_weapons_bg_padding "4"
 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"
@@ -52,8 +52,12 @@ seta hud_panel_weapons_ammo "1"
 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
@@ -120,7 +124,6 @@ seta hud_panel_notify_bg_border ""
 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"
 
@@ -150,6 +153,8 @@ seta hud_panel_radar_zoommode "0"
 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"
index c9d8efa9c00a60e0be13c55cce2747416ea1753f..4cd38574bc775034bbaa8897828b5e53d40ee53d 100644 (file)
@@ -42,9 +42,9 @@ seta hud_panel_weapons_bg_padding ""
 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"
@@ -54,6 +54,10 @@ seta hud_panel_weapons_ammo_alpha "1"
 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
@@ -120,7 +124,6 @@ seta hud_panel_notify_bg_border ""
 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"
 
@@ -150,6 +153,8 @@ seta hud_panel_radar_zoommode "0"
 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"
index e785511160184f0dcb9d31d16fbf0ed2016844b5..966ebbb9e0bd56f8d06bc6ae45fd3cca7dc33bf0 100644 (file)
@@ -42,9 +42,9 @@ seta hud_panel_weapons_bg_padding ""
 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"
@@ -54,6 +54,10 @@ seta hud_panel_weapons_ammo_alpha "1"
 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
@@ -120,7 +124,6 @@ seta hud_panel_notify_bg_border ""
 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"
 
@@ -150,6 +153,8 @@ seta hud_panel_radar_zoommode "0"
 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"
index c766eeeca13db8a1d68254f203a003d53d10719b..c38dc9e481cc49447b2c3f7ecfa363af4d4d5de5 100644 (file)
@@ -42,9 +42,9 @@ seta hud_panel_weapons_bg_padding ""
 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"
@@ -54,6 +54,10 @@ seta hud_panel_weapons_ammo_alpha "1"
 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
@@ -120,7 +124,6 @@ seta hud_panel_notify_bg_border ""
 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"
 
@@ -150,6 +153,8 @@ seta hud_panel_radar_zoommode "0"
 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"
index 98e6f0b8631a8979cad4c02736aaad976d842b0d..0aa7a4dedffb8e0d7bf865a209ac6b4781ba8514 100644 (file)
@@ -42,9 +42,9 @@ seta hud_panel_weapons_bg_padding "-5"
 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"
@@ -54,6 +54,10 @@ seta hud_panel_weapons_ammo_alpha "1"
 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
@@ -120,7 +124,6 @@ seta hud_panel_notify_bg_border ""
 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"
 
@@ -150,6 +153,8 @@ seta hud_panel_radar_zoommode "0"
 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"
index ac81e7e090660bcc3aad378d70c0db5e6f1436ad..3b8198a6d30b4f308a84f7f4aa6df8b061b0fe70 100644 (file)
@@ -3,5 +3,12 @@ species human
 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
index 8aa74198143215bef4c609daeb34465d55b284c8..2f864a686e7887ae788d7718d742a3df7b4528e8 100644 (file)
@@ -3,5 +3,11 @@ species alien
 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
index 06ff3550b1ec43ff1eb968ea9193320e98c96ea6..d561d64800c737dbd56f117de3fcee61d8a7db69 100644 (file)
@@ -3,5 +3,11 @@ species alien
 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
index aff4f75ac6481403df54c8ec29c1f6adeb99c440..10aeee8e16808386ba2318d3e446d07cee30e92b 100644 (file)
@@ -3,5 +3,11 @@ species alien
 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
index 7597e410a90b020efb3a01d1746674f86577fc09..6744e652a56af85d517bfb2ef39a77a7b0dabb28 100644 (file)
@@ -3,5 +3,12 @@ species human
 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
index fd72a02f3f7a74c818b01a1479017bca6fdb9501..c956630f33bb961f2f237497e9700c3f4ac7fbaf 100644 (file)
@@ -3,5 +3,12 @@ species human
 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
index d1c85665f2960081f7aae4f9637a71b8b9d83f21..e89ead1dab4bdaa4d725868d4180b4c44971aab7 100644 (file)
@@ -3,5 +3,12 @@ species human
 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
index b4e2aa85af896617132d445f8b8b6d372ce9d99f..c2d811779c83544114b45874844d3698edbb0898 100644 (file)
@@ -3,5 +3,12 @@ species human
 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
index 9fb92f64752761666366b66efed9a2483c88e195..50f41f35e5dbe3344d6d2a9645903e9fd8cf6c9e 100644 (file)
@@ -3,5 +3,11 @@ species human
 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
index 2c52f6085aa3325aa9c842978c357e3634dc4e86..489571a91a51998e0519c863be828442d82283cb 100644 (file)
@@ -3,5 +3,11 @@ species human
 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
index 6b4fcf6301af663c75d957854b4599875e260980..fc5a62b248af63bbd1884718cff76a5e94d66db7 100644 (file)
@@ -3,5 +3,11 @@ species human
 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
index 47763590e1ca439fe5ed13cbad8b14e75fa117e2..2a48e8d4e552144d7a9a65ee4ddb3f21dc2f9d69 100644 (file)
@@ -3,5 +3,11 @@ species human
 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
diff --git a/models/player/template.md3.animinfo b/models/player/template.md3.animinfo
deleted file mode 100644 (file)
index 7eda007..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-  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
index 21f4c80d96a921529e1ba4da4f2e42eff2cb1089..c5933c1ab601576e6929efbac9ed42a70cbc72ee 100644 (file)
@@ -3,5 +3,11 @@ species human
 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
diff --git a/models/weapons/h_kleinbottle.iqm b/models/weapons/h_kleinbottle.iqm
new file mode 100644 (file)
index 0000000..523ef99
Binary files /dev/null and b/models/weapons/h_kleinbottle.iqm differ
diff --git a/models/weapons/h_kleinbottle.iqm.framegroups b/models/weapons/h_kleinbottle.iqm.framegroups
new file mode 100644 (file)
index 0000000..0a59625
--- /dev/null
@@ -0,0 +1,4 @@
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 40 20 0 // reload
diff --git a/models/weapons/v_kleinbottle.md3 b/models/weapons/v_kleinbottle.md3
new file mode 100644 (file)
index 0000000..b42affb
Binary files /dev/null and b/models/weapons/v_kleinbottle.md3 differ
index c4f20995affc7901dbebc125a2357e2265a6a45e..07d349324edd5230b89a5df17bf067616ce7b2ce 100644 (file)
@@ -76,8 +76,7 @@ set g_balance_minelayer_reload_time 2
 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
@@ -92,8 +91,7 @@ set g_balance_rifle_secondary 1
 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
@@ -109,7 +107,7 @@ set g_balance_rifle_reload_time 2
 // }}}
 // {{{ 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
diff --git a/notifications.cfg b/notifications.cfg
new file mode 100644 (file)
index 0000000..0006f6a
--- /dev/null
@@ -0,0 +1,500 @@
+// ********************************************** //
+// ** 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
index 27f6fc993aa0c12c1e372a7b36c25922fcce7995..3e98265a9521945ec5049ac54d552d2d2dc62e40 100644 (file)
@@ -1,15 +1,44 @@
 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 =
@@ -30,18 +59,18 @@ clean:
 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"
index 9bd8e8c8a35807e0bd5cab007646136a3159edbb..b89a177f043a465c99c5fc7812a8b0d1eb83f3c3 100644 (file)
@@ -1,6 +1,3 @@
-#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.
@@ -251,7 +248,6 @@ vector angles_held;
 .float silent;
 
 float w_deathtype, w_issilent, w_random;
-string w_deathtypestring;
 vector w_org, w_backoff;
 
 float rifle_scope;
index c7a66a8680271478e17323116cc577a02fec1272..f8b6e9cf08e1fa55b1ab3903966584e60b458fa1 100644 (file)
@@ -102,7 +102,7 @@ void CSQC_Init(void)
        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;
@@ -120,7 +120,7 @@ void CSQC_Init(void)
        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") == "")
@@ -149,12 +149,14 @@ void CSQC_Init(void)
        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
@@ -179,6 +181,7 @@ void CSQC_Init(void)
        turrets_precache();
     Announcer_Precache();
        Tuba_Precache();
+       CSQCPlayer_Precache();
        
        if(autocvar_cl_reticle)
        {
@@ -206,6 +209,7 @@ void CSQC_Init(void)
 
        WarpZone_Init();
 
+       hud_skin_path = strzone(strcat("gfx/hud/", autocvar_hud_skin));
        hud_configure_prev = -1;
        tab_panel = -1;
 
@@ -259,16 +263,16 @@ float SetTeam(entity o, float Team)
                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;
                }
@@ -284,7 +288,7 @@ float SetTeam(entity o, float Team)
                                if(GetTeam(Team, false) == world)
                                {
                                        print(sprintf(_("trying to switch to unsupported team %d\n"), Team));
-                                       Team = COLOR_SPECTATOR;
+                                       Team = NUM_SPECTATOR;
                                }
                                break;
                }
@@ -383,9 +387,10 @@ float button_zoom;
 // 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;
@@ -397,7 +402,7 @@ float CSQC_InputEvent(float bInputType, float nPrimary, float nSecondary)
        if (MapVote_InputEvent(bInputType, nPrimary, nSecondary))
                return true;
 
-       if(menu_visible)
+       if(menu_visible && menu_action)
                if(menu_action(bInputType, nPrimary, nSecondary))
                        return TRUE;
 
@@ -428,6 +433,7 @@ void Ent_ReadEntCS()
                self.origin_x = ReadShort();
                self.origin_y = ReadShort();
                self.origin_z = ReadShort();
+               setorigin(self, self.origin);
        }
        if(sf & 4)
        {
@@ -441,6 +447,7 @@ void Ent_ReadEntCS()
 
        entcs_receiver[self.sv_entnum] = self;
        self.entremove = Ent_RemoveEntCS;
+       self.iflags |= IFLAG_ORIGIN;
 
        InterpolateOrigin_Note();
 }
@@ -774,7 +781,8 @@ void CSQC_Ent_Update(float bIsNewEntity)
                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));
@@ -791,6 +799,18 @@ void Ent_Remove()
        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;
@@ -1085,7 +1105,7 @@ void Net_ReadRace()
 void Net_ReadSpawn()
 {
        zoomin_effect = 1;
-       current_viewzoom = 0.6;
+       current_viewzoom = (1 / bound(1, autocvar_cl_spawnzoom_factor, 16));
 }
 
 void Net_TeamNagger()
@@ -1107,7 +1127,8 @@ void Net_ReadPingPLReport()
        playerslots[e].ping_movementloss = ml / 255.0;
 }
 
-void Net_WeaponComplain() {
+void Net_WeaponComplain()
+{
        complain_weapon = ReadByte();
 
        if(complain_weapon_name)
@@ -1118,6 +1139,13 @@ void Net_WeaponComplain() {
 
        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.
@@ -1177,25 +1205,6 @@ float CSQC_Parse_TempEntity()
                        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;
@@ -1220,13 +1229,13 @@ float CSQC_Parse_TempEntity()
 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)
@@ -1240,14 +1249,17 @@ string getcommandkey(string text, string command)
                                        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
index 46d116cbd74dd0d8e572973621a75e35164766e6..3362ce42231193210b22b6ad0fe52f5cf8cbd1bd 100644 (file)
@@ -57,9 +57,11 @@ void Porto_Draw()
                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)
@@ -102,7 +104,7 @@ vector GetCurrentFov(float fov)
                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;
@@ -121,13 +123,20 @@ vector GetCurrentFov(float fov)
                // 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
@@ -240,7 +249,7 @@ float EnemyHitCheck()
        if(teamplay)
                if(t == myteam)
                        return SHOTTYPE_HITTEAM;
-       if(t == COLOR_SPECTATOR)
+       if(t == NUM_SPECTATOR)
                return SHOTTYPE_HITWORLD;
        return SHOTTYPE_HITENEMY;
 }
@@ -390,6 +399,13 @@ void CSQC_UpdateView(float w, float h)
 
        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
@@ -419,8 +435,8 @@ void CSQC_UpdateView(float w, float h)
        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();
 
@@ -441,12 +457,12 @@ void CSQC_UpdateView(float w, float h)
                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)
@@ -454,17 +470,20 @@ void CSQC_UpdateView(float w, float h)
                        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
@@ -473,9 +492,16 @@ void CSQC_UpdateView(float w, float h)
                        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);
@@ -539,8 +565,8 @@ void CSQC_UpdateView(float w, float h)
                        calledhooks |= HOOK_END;
                }
        }
-       
-  Announcer();
+
+       Announcer();
 
        fov = autocvar_fov;
        if(fov <= 59.5)
@@ -773,7 +799,6 @@ void CSQC_UpdateView(float w, float h)
 
 
        // improved polyblend
-       vector rgb;
        if(autocvar_hud_contents)
        {
                float contentalpha_temp, incontent, liquidalpha, contentfadetime;
@@ -890,25 +915,22 @@ void CSQC_UpdateView(float w, float h)
                // 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.
                {
@@ -936,7 +958,7 @@ void CSQC_UpdateView(float w, float h)
                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);
@@ -955,13 +977,13 @@ void CSQC_UpdateView(float w, float h)
                }
 
                // 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
                        {
@@ -1076,8 +1098,8 @@ void CSQC_UpdateView(float w, float h)
                        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) {
@@ -1265,9 +1287,9 @@ void CSQC_UpdateView(float w, float h)
                                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;
 
@@ -1483,25 +1505,8 @@ void CSQC_UpdateView(float w, float h)
 
 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();
index db1ae41336d5e1eb54d30c437975b7323b330739..240d424c6a5ee255eb4eb8135ff4e7137733a0c1 100644 (file)
@@ -27,8 +27,8 @@ void Announcer_Countdown()
        
        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
@@ -38,7 +38,7 @@ void Announcer_Countdown()
        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));
@@ -81,7 +81,7 @@ void Announcer_Time()
 {
        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)
@@ -158,7 +158,6 @@ void Announcer_Precache ()
        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"));
index 6214e82b4ac43b8f4ac399e8f8dde10272f5d54d..00d12e920dff2ea4105f55f695bc5ededfa7020f 100644 (file)
@@ -63,6 +63,9 @@ var float autocvar_cl_reticle = 1;
 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;
@@ -158,6 +161,7 @@ float autocvar_g_waypointsprite_timealphaexponent;
 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;
@@ -261,7 +265,6 @@ float autocvar_hud_panel_notify;
 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;
@@ -300,6 +303,8 @@ vector autocvar_hud_panel_radar_maximized_size;
 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;
@@ -325,14 +330,18 @@ string autocvar_hud_panel_weapons_complainbubble_color_unavailable;
 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;
@@ -359,6 +368,7 @@ float autocvar_r_fullbright;
 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;
@@ -378,6 +388,7 @@ var float autocvar_scoreboard_highlight_alpha_self = 0.25;
 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;
@@ -389,6 +400,9 @@ float autocvar_cl_hitsound_antispam_time;
 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;
@@ -413,3 +427,4 @@ string autocvar__cl_playermodel;
 float autocvar_cl_precacheplayermodels;
 float autocvar_cl_deathglow;
 float autocvar_developer_csqcentities;
+float autocvar_g_jetpack_attenuation;
index a43d1726fcdce42a09aa30356391dc25cca57ac1..70ed9f4b07d74b597a39d67968bf99bdba7cd807 100644 (file)
@@ -84,6 +84,7 @@ void Ent_Casing(float isNew)
        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;
index 23b9b8c70a5b7ee2486a7a7497f13f0751396237..acac8b3121574d22a2ec706a9f78849b5a404712 100644 (file)
@@ -214,7 +214,10 @@ void LocalCommand_hud(float request, float argc)
                                
                                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;
                                }
                        }
index f2db76a2cf293de7b05291bc1dcd4e24b9d33f22..9c29c40ee7ca11150169981275ff41fa5457b8a8 100644 (file)
@@ -7,4 +7,4 @@ void Cmd_HUD_SetFields(float);
 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);
index 15e62170bab859eca1b47c9bfa99797e959b006c..0fabb0d0c70b5eb86d9edca2d752efd2e466ee3e 100644 (file)
@@ -125,6 +125,7 @@ void (entity e)                                                                     runstandardplayerphysics = #347;
 
 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;
index 9c87d13addf9949c671a4319da1e5c91f2f69b45..a9f8410b4178a4006be7d0cc0659db8d4615425e 100644 (file)
@@ -1,4 +1,4 @@
-void CSQCModel_Hook_PreDraw();
+void CSQCModel_Hook_PreDraw(float isplayer);
 
 .float isplayermodel;
 
@@ -218,7 +218,7 @@ void CSQCPlayer_ForceModel_Apply(float islocalplayer)
                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)
@@ -270,8 +270,10 @@ void CSQCPlayer_ForceModel_Apply(float islocalplayer)
 // 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)
@@ -279,15 +281,19 @@ void CSQCPlayer_FallbackFrame_PreUpdate(void)
 {
        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"
@@ -300,8 +306,10 @@ void CSQCPlayer_FallbackFrame_PostUpdate(float isnew)
                }
                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);
 }
@@ -329,8 +337,10 @@ void CSQCPlayer_FallbackFrame_Apply(void)
 {
        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
@@ -357,7 +367,7 @@ void CSQCModel_AutoTagIndex_Apply(void)
                {
                        entity oldself = self;
                        self = self.tag_entity;
-                       CSQCModel_Hook_PreDraw();
+                       CSQCModel_Hook_PreDraw((self.entnum >= 1 && self.entnum <= maxclients));
                        self = oldself;
                }
 
@@ -388,11 +398,8 @@ void CSQCModel_AutoTagIndex_Apply(void)
                                        }
                                        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;
                                        }
                                }
 
@@ -419,6 +426,8 @@ float EF_DIMLIGHT   = 8;
 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
@@ -443,6 +452,7 @@ void CSQCModel_Effects_PostUpdate(void)
        if(self.csqcmodel_teleported)
                Projectile_ResetTrail(self.origin);
 }
+.float snd_looping;
 void CSQCModel_Effects_Apply(void)
 {
        float eff = self.csqcmodel_effects;
@@ -514,6 +524,28 @@ void CSQCModel_Effects_Apply(void)
        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
@@ -543,7 +575,16 @@ void CSQCPlayer_GlowMod_Apply(void)
 
 // 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;
@@ -562,7 +603,65 @@ void CSQCModel_Hook_PreDraw()
                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();
@@ -572,11 +671,14 @@ void CSQCModel_Hook_PreDraw()
 
 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();
        }
 }
@@ -590,7 +692,8 @@ void CSQCModel_Hook_PostUpdate(float isnew, float isplayer, float islocalplayer)
        if(self.isplayermodel)
        {
                CSQCPlayer_ForceModel_PostUpdate();
-               CSQCPlayer_FallbackFrame_PostUpdate(isnew);
+               if(!isplayer)
+                       CSQCPlayer_FallbackFrame_PostUpdate(isnew);
        }
        CSQCModel_Effects_PostUpdate();
 }
index ae83d45eea011d890b8b3fd0430866d2b17312ca..bbc8f88043453a3e0338b02fccbfef6d00955ba2 100644 (file)
@@ -39,7 +39,7 @@ void DamageEffect(vector hitorg, float dmg, float type, float specnum)
 {
        // 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;
 
@@ -61,7 +61,7 @@ void DamageEffect(vector hitorg, float dmg, float type, float specnum)
                        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
@@ -113,7 +113,7 @@ void DamageEffect(vector hitorg, float dmg, float type, float specnum)
 
 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;
 
@@ -211,43 +211,43 @@ void Ent_DamageInfo(float isNew)
                
                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)
@@ -259,15 +259,15 @@ void Ent_DamageInfo(float isNew)
                                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;
@@ -301,14 +301,14 @@ void Ent_DamageInfo(float isNew)
                                
                         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);
@@ -319,7 +319,7 @@ void Ent_DamageInfo(float isNew)
                                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;
index b695867ca361995522005d50a69a99ab482ec66a..8c237aade92621df131a49b4ef079a10760e1326 100644 (file)
@@ -85,11 +85,11 @@ void Net_ReadLightningarc()
     {
         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);
     }
index 22825bc4f38d4912b70c51922098c20213308581..9e1c6e7a1395faf93d89ca7234aad0d031bdbbf2 100644 (file)
@@ -138,7 +138,8 @@ void TossGib (string mdlname, vector safeorg, vector org, vector vconst, vector
                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;
@@ -156,7 +157,7 @@ void Ent_GibSplash(float isNew)
        vector org, vel;
        string specstr;
        float issilent;
-       string gentle_prefix;
+       string gentle_prefix = "morphed_";
 
        float c, randomvalue;
 
@@ -177,8 +178,6 @@ void Ent_GibSplash(float isNew)
                        gentle_prefix = "";
                else if(cl_gentle_gibs == 3) 
                        gentle_prefix = "happy_";
-               else
-                       gentle_prefix = "morphed_";
        }
        else if(autocvar_cl_particlegibs)
        {
@@ -195,7 +194,7 @@ void Ent_GibSplash(float isNew)
        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);
index 641d50d634fee10abbb0abacbef4d30943df4eb0..11070bae5cfe4c10500e36db2b5b3c7bb6607ffb 100644 (file)
@@ -129,22 +129,22 @@ void Draw_GrapplingHook()
                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';
@@ -226,7 +226,7 @@ void Ent_ReadHook(float bIsNew, float type)
        sf = ReadByte();
 
        self.HookSilent = (sf & 0x80);
-       self.iflags = IFLAG_VELOCITY;
+       self.iflags = IFLAG_VELOCITY | IFLAG_ORIGIN;
 
        InterpolateOrigin_Undo();
 
index 77022635cdb245c5bac229de144cc5b300c4cc29..067743a04f478103ea79bcc20217213bea8c4c4c 100644 (file)
@@ -154,18 +154,6 @@ void drawstringcenter(vector position, string text, vector scale, vector rgb, fl
        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)
 {
@@ -213,7 +201,10 @@ string MakeRaceString(float cp, float mytime, float histime, float lapdelta, str
                col = "^3";
        }
        else
+       {
                col = "^7";
+               timestr = "";
+       }
 
        if(cp == 254)
                cpname = _("Start line");
@@ -241,6 +232,30 @@ float race_CheckName(string net_name) {
        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
@@ -434,27 +449,29 @@ void HUD_Weapons(void)
        // 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; }
@@ -463,7 +480,8 @@ void HUD_Weapons(void)
        {
                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;
@@ -478,15 +496,6 @@ void HUD_Weapons(void)
 
        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])
        {
@@ -517,6 +526,9 @@ void HUD_Weapons(void)
                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)
        {
@@ -531,32 +543,50 @@ void HUD_Weapons(void)
                }
 
                // 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;
@@ -566,12 +596,21 @@ void HUD_Weapons(void)
        {
                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
@@ -592,17 +631,28 @@ void HUD_Weapons(void)
                                        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
@@ -630,6 +680,13 @@ void HUD_Weapons(void)
 
        // 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;
@@ -637,10 +694,14 @@ void HUD_Weapons(void)
        }
 
        // 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)
@@ -661,15 +722,10 @@ void HUD_Weapons(void)
                        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
@@ -677,15 +733,12 @@ void HUD_Weapons(void)
                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 
@@ -694,24 +747,15 @@ void HUD_Weapons(void)
 
                // 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);
                        }
                }
@@ -720,7 +764,7 @@ void HUD_Weapons(void)
                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)
@@ -776,14 +820,13 @@ void HUD_Weapons(void)
                }
 
                // 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");
@@ -926,7 +969,7 @@ void HUD_Ammo(void)
                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;
@@ -941,7 +984,7 @@ void HUD_Ammo(void)
                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)
        {
@@ -986,6 +1029,7 @@ void HUD_Ammo(void)
                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);
@@ -1003,7 +1047,7 @@ void HUD_Ammo(void)
 
 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)
@@ -1135,7 +1179,7 @@ void HUD_Powerups(void)
 
        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;
 
@@ -1228,7 +1272,7 @@ void HUD_Powerups(void)
                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;
@@ -1425,7 +1469,7 @@ void HUD_HealthArmor(void)
        {
                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;
@@ -1584,555 +1628,29 @@ void HUD_HealthArmor(void)
 // 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)
        {
@@ -2168,14 +1686,11 @@ void HUD_Notify (void)
        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;
@@ -2199,234 +1714,62 @@ void HUD_Notify (void)
                                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);
                        }
@@ -2527,6 +1870,8 @@ void HUD_Radar(void)
 
        HUD_Panel_UpdateCvars(radar);
        HUD_Panel_ApplyFadeAlpha();
+       
+       float f = 0;
 
        if (hud_panel_radar_maximized && !autocvar__hud_configure)
        {
@@ -2538,6 +1883,62 @@ void HUD_Radar(void)
                
                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;
@@ -2554,7 +1955,6 @@ void HUD_Radar(void)
        float color2;
        entity tm;
        float scale2d, normalsize, bigsize;
-       float f;
 
        teamradar_origin2d = pos + 0.5 * mySize;
        teamradar_size2d = mySize;
@@ -2564,40 +1964,13 @@ void HUD_Radar(void)
 
        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));
@@ -2647,13 +2020,13 @@ void HUD_Radar(void)
        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)
 //
@@ -2661,7 +2034,7 @@ void HUD_UpdatePlayerTeams();
 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);
@@ -2674,13 +2047,11 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me, float team_count)
        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
@@ -2689,7 +2060,7 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me, float team_count)
                        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;
@@ -2704,7 +2075,7 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me, float team_count)
                        {
                                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
@@ -2714,7 +2085,7 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me, float team_count)
                        }
 
                        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);
@@ -2730,11 +2101,11 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me, float team_count)
                // 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;
@@ -2746,14 +2117,14 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me, float team_count)
        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)
@@ -2771,14 +2142,14 @@ void HUD_Score_Rankings(vector pos, vector mySize, entity me, float team_count)
                        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)
@@ -2804,7 +2175,7 @@ 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;
@@ -2894,12 +2265,12 @@ void HUD_Score(void)
                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)
                        {
@@ -2936,8 +2307,9 @@ void HUD_Score(void)
                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)
@@ -2951,7 +2323,7 @@ void HUD_Score(void)
                                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)
                                {
@@ -2962,11 +2334,11 @@ void HUD_Score(void)
                        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;
                        }
                }
@@ -3004,7 +2376,7 @@ void HUD_RaceTimer (void)
        }
 
        // always force 4:1 aspect
-       vector newSize;
+       vector newSize = '0 0 0';
        if(mySize_x/mySize_y > 4)
        {
                newSize_x = 4 * mySize_y;
@@ -3096,13 +2468,13 @@ void HUD_RaceTimer (void)
                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);
                }
 
@@ -3215,7 +2587,7 @@ void HUD_VoteWindow(void)
        }
 
        // always force 3:1 aspect
-       vector newSize;
+       vector newSize = '0 0 0';
        if(mySize_x/mySize_y > 3)
        {
                newSize_x = 3 * mySize_y;
@@ -3380,7 +2752,7 @@ void HUD_Mod_CTF(vector pos, vector mySize)
                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;
@@ -3393,7 +2765,7 @@ void HUD_Mod_CTF(vector pos, vector mySize)
                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;
@@ -3408,7 +2780,7 @@ void HUD_Mod_CTF(vector pos, vector mySize)
                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;
@@ -3421,7 +2793,7 @@ void HUD_Mod_CTF(vector pos, vector mySize)
                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;
@@ -3429,7 +2801,7 @@ void HUD_Mod_CTF(vector pos, vector mySize)
        }
 
        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 {
@@ -3438,7 +2810,7 @@ void HUD_Mod_CTF(vector pos, vector mySize)
                }
                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 {
@@ -3475,7 +2847,7 @@ void HUD_Mod_KH(vector pos, vector mySize)
        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);
 
@@ -3552,16 +2924,16 @@ void HUD_Mod_KH(vector pos, vector mySize)
                {
                        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:
@@ -3792,8 +3164,10 @@ void HUD_Mod_Race(vector pos, vector mySize)
        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;
@@ -3836,6 +3210,11 @@ void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, float layout,
        float stat, pps_ratio;
        string pic;
        vector color;
+#ifdef GMQCC
+       stat = -1;
+       pic = "";
+       color = '0 0 0';
+#endif
        switch(i)
        {
                case 0:
@@ -3853,10 +3232,12 @@ void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, float layout,
                        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);
 
@@ -3897,9 +3278,9 @@ void HUD_Mod_Dom(vector myPos, vector mySize)
 {
        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;
@@ -3910,7 +3291,7 @@ void HUD_Mod_Dom(vector myPos, vector mySize)
        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;
@@ -4019,7 +3400,7 @@ void HUD_DrawPressedKeys(void)
        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;
@@ -4229,7 +3610,7 @@ void HUD_InfoMessages(void)
        }
 
        // always force 5:1 aspect
-       vector newSize;
+       vector newSize = '0 0 0';
        if(mySize_x/mySize_y > 5)
        {
                newSize_x = 5 * mySize_y;
@@ -4352,13 +3733,13 @@ void HUD_InfoMessages(void)
 
                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);
@@ -4370,7 +3751,7 @@ void HUD_InfoMessages(void)
                                        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)
@@ -4418,7 +3799,7 @@ void HUD_Physics(void)
                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;
 
@@ -4491,7 +3872,7 @@ void HUD_Physics(void)
 
        //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;
@@ -4533,7 +3914,7 @@ void HUD_Physics(void)
                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;
@@ -4592,12 +3973,12 @@ void HUD_Physics(void)
                        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)
@@ -4682,6 +4063,7 @@ float centerprint_showing;
 
 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)
@@ -4741,7 +4123,10 @@ void centerprint_generic(float new_id, string strMessage, float duration, float
        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)
@@ -4842,8 +4227,8 @@ void HUD_CenterPrint (void)
        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;
 
@@ -4853,7 +4238,7 @@ void HUD_CenterPrint (void)
        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;
@@ -4866,15 +4251,20 @@ void HUD_CenterPrint (void)
                                        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); 
@@ -4882,8 +4272,8 @@ void HUD_CenterPrint (void)
                // 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
@@ -4891,7 +4281,7 @@ void HUD_CenterPrint (void)
                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");
 
@@ -4931,6 +4321,9 @@ void HUD_CenterPrint (void)
                                        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)
                {
@@ -5268,11 +4661,14 @@ void HUD_Main (void)
                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
@@ -5342,8 +4738,8 @@ void HUD_Main (void)
        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;
@@ -5403,9 +4799,14 @@ void HUD_Main (void)
                        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;
 
index 37b38aa9bb6c6791796bbdc257b9b6bce0f2a19e..db27a488f596218e091fc3cb2c4e5d2b245f9d12 100644 (file)
@@ -16,12 +16,6 @@ const float BORDER_MULTIPLIER = 0.25;
 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;
@@ -53,6 +47,7 @@ float menu_enabled_time;
 float hud_fade_alpha;
 
 string hud_skin_path;
+string hud_skin_prev;
 
 var vector progressbar_color;
 
@@ -348,3 +343,12 @@ switch(id) { \
        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);
index dae28835583df17e8666d07c3d7d53c77045698b..e2f82d6b6b4f49172df1f2c1cb5e853c1e8524fa 100644 (file)
@@ -80,6 +80,10 @@ void HUD_Panel_ExportCfg(string cfgname)
                                        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:
@@ -113,7 +117,6 @@ void HUD_Panel_ExportCfg(string cfgname)
                                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;
@@ -127,6 +130,8 @@ void HUD_Panel_ExportCfg(string cfgname)
                                        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");
@@ -138,8 +143,8 @@ void HUD_Panel_ExportCfg(string cfgname)
                                        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");
@@ -645,8 +650,7 @@ float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary)
 {
        string s;
 
-       // we only care for keyboard events
-       if(bInputType != 0 && bInputType != 1)
+       if(bInputType == 2)
                return false;
 
        if(!autocvar__hud_configure)
@@ -656,13 +660,20 @@ float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary)
        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)))
@@ -754,8 +765,8 @@ float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary)
                }
                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
@@ -906,7 +917,7 @@ float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary)
 
 float HUD_Panel_Check_Mouse_Pos(float allow_move)
 {
-       float i, j, border;
+       float i, j = 0, border;
 
        while(j < HUD_PANEL_NUM)
        {
@@ -918,7 +929,7 @@ float HUD_Panel_Check_Mouse_Pos(float allow_move)
                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;
                }
@@ -973,7 +984,7 @@ void HUD_Panel_FirstInDrawQ(float id)
        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]), " ");
@@ -986,7 +997,7 @@ void HUD_Panel_FirstInDrawQ(float id)
 
 void HUD_Panel_Highlight(float allow_move)
 {
-       float i, j, border;
+       float i, j = 0, border;
 
        while(j < HUD_PANEL_NUM)
        {
@@ -998,7 +1009,7 @@ void HUD_Panel_Highlight(float allow_move)
                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);
@@ -1080,10 +1091,13 @@ void HUD_Panel_Mouse()
        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)
        {
@@ -1143,7 +1157,7 @@ void HUD_Panel_Mouse()
                        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);
index a91e13b01991e52517af210079478858eb0faae7..03ea99303297efc1605599b11fe622017fe60334 100644 (file)
@@ -76,15 +76,16 @@ void Ent_Laser()
        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)
        {
index 43e7b64995e3b991f05b72f0623f684fa2892acd..8369a5ff20bc9ce399d0eef7c1a35d1063b4d8a9 100644 (file)
@@ -1,5 +1,3 @@
-const string string_null;
-
 // --------------------------------------------------------------------------
 // MENU Functionality
 
@@ -40,16 +38,6 @@ float gametype;
 //.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
 
index 750bd2a75309d8774aea219b774ed1a9875c9f5d..9feb6e826d500a5e5bad8129cd9e099f393fed89 100644 (file)
@@ -28,6 +28,8 @@ string MapVote_FormatMapItem(float id, string map, float count, float maxwidth,
                        post = _(" (1 vote)");
                else if(count >= 0)
                        post = sprintf(_(" (%d votes)"), count);
+               else
+                       post = "";
        }
        else
                post = "";
@@ -50,7 +52,7 @@ vector MapVote_RGB(float id, float count)
 
 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;
@@ -169,15 +171,18 @@ void MapVote_Draw()
        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
@@ -255,7 +260,7 @@ void MapVote_Draw()
                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)
@@ -335,8 +340,8 @@ void MapVote_Init()
        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)
@@ -406,6 +411,13 @@ float MapVote_InputEvent(float bInputType, float nPrimary, float nSecondary)
        if (!mv_active)
                return false;
 
+       if(bInputType == 3)
+       {
+               mv_mousepos_x = nPrimary;
+               mv_mousepos_y = nSecondary;
+               return true;
+       }
+
        if (bInputType != 0)
                return false;
 
index 72bb9c5c40a66ec0932bc1dbed0d3b2d00e8a292..7951962e6be9086aeace7b011b83c62852fdddcb 100644 (file)
@@ -1,5 +1,3 @@
-var float(string text, float handleColors, vector fontSize) stringwidth;
-
 entity players;
 entity teams;
 
@@ -110,7 +108,7 @@ entity GetTeam(float Team, float add)
 {
        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)
@@ -149,7 +147,7 @@ float PreviewExists(string name)
 
 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);
@@ -166,20 +164,6 @@ string ColorTranslateRGB(string s)
                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)
 {
@@ -231,7 +215,7 @@ vector expandingbox_resize_centered_box_offset(float sz, vector boxsize, float b
 
 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;
@@ -250,7 +234,7 @@ void drawborderlines(float thickness, vector pos, vector dim, vector color, floa
 
 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;
@@ -576,19 +560,12 @@ void DrawCircleClippedPic(vector centre, float radius, string pic, float f, vect
 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;
@@ -637,3 +614,61 @@ void draw_endBoldFont()
 {
        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;
+}
+
index 1b546534919412bfb7f92bb48ac6d71ed00014d6..0508a8669a984ab102530a5403c1e59a7aa20667 100644 (file)
@@ -6,7 +6,7 @@
 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)
@@ -41,6 +41,7 @@ void Ent_ModelEffect(float isNew)
        e.origin_x = ReadCoord();
        e.origin_y = ReadCoord();
        e.origin_z = ReadCoord();
+       setorigin(e, e.origin);
        if(f & 1)
        {
                e.velocity_x = ReadCoord();
index 6e24893b02e005b08d9b3e142dad4d70e6c1efd7..3e2222f4aae07fc017cde94d3895caa779919bc3 100644 (file)
@@ -57,7 +57,7 @@ void Draw_PointParticles()
                        }
                        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;
@@ -68,7 +68,7 @@ void Draw_PointParticles()
                        --i;
                }
        }
-       self.origin = o;
+       setorigin(self, o);
 }
 
 void Ent_PointParticles_Remove()
diff --git a/qcsrc/client/player_skeleton.qc b/qcsrc/client/player_skeleton.qc
new file mode 100644 (file)
index 0000000..7784fc1
--- /dev/null
@@ -0,0 +1,184 @@
+.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);
+                       }
+               }
+       }
+}
diff --git a/qcsrc/client/player_skeleton.qh b/qcsrc/client/player_skeleton.qh
new file mode 100644 (file)
index 0000000..d369bac
--- /dev/null
@@ -0,0 +1,9 @@
+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;
index 0922433eebdecd2d6c3c229636162e1475c6e56b..3b8aa1bace9adc8970b782b4388416bda44dadc5 100644 (file)
@@ -14,7 +14,9 @@ Defs.qc
 ../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
@@ -23,10 +25,14 @@ Defs.qc
 ../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
@@ -38,7 +44,6 @@ movetypes.qh
 prandom.qh
 bgmscript.qh
 noise.qh
-teamplay.qh
 tturrets.qh
 ../server/tturrets/include/turrets_early.qh
 ../server/movelib.qc
@@ -49,10 +54,10 @@ vehicles/vehicles.qh
 ../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
@@ -95,6 +100,7 @@ bgmscript.qc
 noise.qc
 
 ../common/util.qc
+../common/notifications.qc
 ../common/command/markup.qc
 ../common/command/rpn.qc
 ../common/command/generic.qc
@@ -111,4 +117,7 @@ command/cl_cmd.qc
 ../warpzonelib/client.qc
 tturrets.qc
 
+player_skeleton.qc
+../common/animdecide.qc
+
 ../common/if-this-file-errors-scroll-up-and-fix-the-warnings.fteqccfail
index 4081bd8d1800c147a4867d2a6b6321bb11ed5e39..fb4fdd5ef24e1fd245486a58d3a69ecf5fae33a8 100644 (file)
@@ -4,10 +4,6 @@
 .float trail_oldtime;
 .float fade_time, fade_rate;
 
-void SUB_Null()
-{
-}
-
 void SUB_Stop()
 {
        self.move_velocity = self.move_avelocity = '0 0 0';
@@ -164,14 +160,11 @@ void loopsound(entity e, float ch, string samp, float vol, float attn)
                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);
@@ -199,7 +192,7 @@ void Ent_Projectile()
 
        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;
 
@@ -229,6 +222,7 @@ void Ent_Projectile()
                self.origin_x = ReadCoord();
                self.origin_y = ReadCoord();
                self.origin_z = ReadCoord();
+               setorigin(self, self.origin);
                if(self.count & 0x80)
                {
                        self.velocity_x = ReadCoord();
@@ -327,7 +321,7 @@ void Ent_Projectile()
                                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;
@@ -344,7 +338,7 @@ void Ent_Projectile()
                                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;
@@ -356,21 +350,21 @@ void Ent_Projectile()
                                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);
@@ -380,7 +374,7 @@ void Ent_Projectile()
                        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;
@@ -420,7 +414,7 @@ void Ent_Projectile()
                                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;
@@ -428,6 +422,7 @@ void Ent_Projectile()
                        default:
                                break;
                }
+               setsize(self, self.mins, self.maxs);
        }
 
        if(self.gravity)
index 48a7217fc703a08b3b7f7fdfab3bc58efea36c2e..2ec7db0623025d7bc813afae95a299956a0fd63c 100644 (file)
@@ -129,23 +129,39 @@ void HUD_UpdatePlayerTeams()
        */
 }
 
+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
@@ -154,33 +170,23 @@ float HUD_ComparePlayerScores(entity left, entity right)
                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;
 }
@@ -199,26 +205,30 @@ void HUD_UpdatePlayerPos(entity player)
 
 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;
 }
@@ -306,20 +316,20 @@ void Cmd_HUD_SetFields(float argc)
 {
        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;
@@ -334,17 +344,17 @@ void Cmd_HUD_SetFields(float argc)
                        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);
@@ -659,11 +669,11 @@ string HUD_FixScoreboardColumnWidth(float i, string str)
 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;
@@ -791,7 +801,7 @@ void HUD_PrintScoreboardItem(vector pos, entity pl, float is_self, float pl_numb
 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
@@ -907,7 +917,7 @@ vector HUD_Scoreboard_MakeTable(vector pos, entity tm, vector rgb, vector bg_siz
        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;
@@ -955,7 +965,7 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
 
        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;
 
@@ -988,12 +998,10 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
                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)
        {
@@ -1023,20 +1031,8 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
                        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);
                }
@@ -1048,7 +1044,7 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
        }
 
        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;
@@ -1092,7 +1088,7 @@ vector HUD_DrawMapStats(vector pos, vector rgb, vector bg_size) {
        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;
 
@@ -1124,7 +1120,7 @@ vector HUD_DrawScoreboardRankings(vector pos, entity pl,  vector rgb, vector bg_
                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;
@@ -1133,7 +1129,7 @@ vector HUD_DrawScoreboardRankings(vector pos, entity pl,  vector rgb, vector bg_
        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;
 
@@ -1152,7 +1148,7 @@ vector HUD_DrawScoreboardRankings(vector pos, entity pl,  vector rgb, vector bg_
                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)
@@ -1241,11 +1237,11 @@ void HUD_DrawScoreboard()
                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);
 
@@ -1258,16 +1254,26 @@ void HUD_DrawScoreboard()
 
                        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);
@@ -1283,18 +1289,18 @@ void HUD_DrawScoreboard()
                        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);
 
@@ -1304,7 +1310,7 @@ void HUD_DrawScoreboard()
        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);
@@ -1374,9 +1380,43 @@ void HUD_DrawScoreboard()
                }
        }
 
-
        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;
 }
index 5309c555e6085050b6a37b36509cf010964c2deb..f20f143b0315497e797817c0533a55b8a8f8966a 100644 (file)
@@ -43,7 +43,7 @@ void Draw_ShowNames(entity ent)
                }
 
                // handle tag fading
-               float overlap, onscreen, crosshairdistance;
+               float overlap = FALSE, onscreen, crosshairdistance;
                vector o, eo;
                
                o = project_3d_to_2d(ent.origin);
@@ -187,7 +187,7 @@ void Draw_ShowNames_All()
        {
                float t;
                t = GetPlayerColor(i);
-               if(t == COLOR_SPECTATOR)
+               if(t == NUM_SPECTATOR)
                        continue;
 
                entity e;
@@ -215,7 +215,7 @@ void Draw_ShowNames_All()
                        e.sameteam = 0;
                }
 
-               e.origin = getplayerorigin(i);
+               setorigin(e, getplayerorigin(i));
                if(e.origin == GETPLAYERORIGIN_ERROR)
                        continue;
                        
index 6e3f899ddc31cb0754465bacec20e7fac61c0eda..adbfa57120376e5091f3c957d05557b9873de870 100644 (file)
@@ -2,4 +2,4 @@
 .float armorvalue;
 .float sameteam;
 .float fadedelay;
-.float pointtime;
\ No newline at end of file
+.float pointtime;
diff --git a/qcsrc/client/teamplay.qc b/qcsrc/client/teamplay.qc
deleted file mode 100644 (file)
index 80d8931..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-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");
-       }
-}
diff --git a/qcsrc/client/teamplay.qh b/qcsrc/client/teamplay.qh
deleted file mode 100644 (file)
index 8335990..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-float teamplay;
-float myteam;
index f3ec99bfeebb526424a95dd5bf21cc7e84433b8f..0c0f10204a4773c2da21e2aa6669a46a88d4740a 100644 (file)
@@ -172,6 +172,8 @@ float hud_panel_radar_foreground_alpha;
 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()
 {
@@ -185,6 +187,8 @@ 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!
@@ -203,7 +207,7 @@ void Ent_RadarLink()
 
        InterpolateOrigin_Undo();
 
-       self.iflags = IFLAG_VELOCITY;
+       self.iflags = IFLAG_VELOCITY | IFLAG_ORIGIN;
        self.classname = "radarlink";
 
        if(sendflags & 1)
@@ -211,6 +215,7 @@ void Ent_RadarLink()
                self.origin_x = ReadCoord();
                self.origin_y = ReadCoord();
                self.origin_z = ReadCoord();
+               setorigin(self, self.origin);
        }
 
        if(sendflags & 2)
index 272a24610204128247559cf76ecd6fca41bef53b..24deed681f68447507443dd458d69a9dab249a2f 100644 (file)
@@ -163,22 +163,22 @@ void turret_changeteam()
 {      
        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;
@@ -542,7 +542,8 @@ entity turret_gibtoss(string _model, vector _from, vector _to, vector _cmod, flo
     
     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;
@@ -605,6 +606,7 @@ void ent_turret()
            self.origin_x = ReadCoord();
            self.origin_y = ReadCoord();
            self.origin_z = ReadCoord();
+           setorigin(self, self.origin);
            
            self.angles_x = ReadAngle();
            self.angles_y = ReadAngle();
index 2fea077c5d0c928c6629289de9273886b3e98fd9..a22347fe3ca3f53ebea4acbd59eb01aa05bc684f 100644 (file)
@@ -1,6 +1,6 @@
 #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
index 3a4597ab2e4be241d5b16d7dc8ec35a8f788dd38..a6dbcef10305d55c3c7ca9f299067d0f3a8ba4ee 100644 (file)
@@ -41,7 +41,6 @@ void CSQC_BUMBLE_GUN_HUD();
 
 #define MAX_AXH 4
 entity AuxiliaryXhair[MAX_AXH];
-const var void Draw_Not();
 
 .string axh_image;
 .float  axh_fadetime;
@@ -84,7 +83,7 @@ void AuxiliaryXhair_Draw2D()
     }
 
     if(time - self.cnt > self.axh_fadetime)
-        self.draw2d = Draw_Not;
+        self.draw2d = func_null;
 }
 
 void Net_AuXair2(float bIsNew)
@@ -95,7 +94,7 @@ 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;
@@ -148,7 +147,7 @@ void Net_VehicleSetup()
             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;
@@ -212,13 +211,13 @@ void Net_VehicleSetup()
     }
 }
 #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()
 {
@@ -231,7 +230,7 @@ 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
@@ -327,7 +326,7 @@ void CSQC_BUMBLE_HUD()
     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);
@@ -349,7 +348,7 @@ void CSQC_BUMBLE_HUD()
     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);
@@ -382,7 +381,7 @@ void CSQC_BUMBLE_GUN_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
@@ -503,7 +502,7 @@ void CSQC_SPIDER_HUD()
        if(autocvar_r_letterbox)
         return;
 
-    vector picsize, hudloc, pic2size, picloc;
+    vector picsize, hudloc = '0 0 0', pic2size, picloc;
     float i;
 
     // Fetch health & ammo stats
@@ -666,7 +665,7 @@ void CSQC_RAPTOR_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
@@ -860,7 +859,7 @@ void CSQC_WAKIZASHI_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
index 807b260ab2131eb57627aa564505898fdf9a50da..211af4cb0889593380acdfa9785149ae76a5d52d 100644 (file)
@@ -10,9 +10,10 @@ void Ent_Wall_Draw()
        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)
        {
@@ -41,10 +42,7 @@ void Ent_Wall_Draw()
 
        InterpolateOrigin_Do();
 
-       if(self.bgmscriptangular)
-               self.saved = self.angles;
-       else
-               self.saved = self.origin;
+       self.saved = self.fld;
 
        f = BGMScript(self);
        if(f >= 0)
@@ -74,13 +72,16 @@ void Ent_Wall_Remove()
 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();
 
@@ -97,6 +98,7 @@ void Ent_Wall()
                self.origin_x = ReadCoord();
                self.origin_y = ReadCoord();
                self.origin_z = ReadCoord();
+               setorigin(self, self.origin);
        }
 
        if(f & 4)
@@ -140,6 +142,7 @@ void Ent_Wall()
                }
                else
                        self.mins = self.maxs = '0 0 0';
+               setsize(self, self.mins, self.maxs);
 
                if(self.bgmscript)
                        strunzone(self.bgmscript);
@@ -170,10 +173,7 @@ void Ent_Wall()
 
        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;
index 07fe7c24e07e12589650329c5d7bb8f06941442b..366f6152d02f5c11836b852897242f9ca767e9ea 100644 (file)
@@ -436,7 +436,7 @@ void Draw_WaypointSprite()
                                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;
@@ -669,6 +669,7 @@ void Ent_WaypointSprite()
        self.draw2d = Draw_WaypointSprite;
 
        InterpolateOrigin_Undo();
+       self.iflags |= IFLAG_ORIGIN;
 
        if(sendflags & 0x80)
        {
@@ -701,6 +702,7 @@ void Ent_WaypointSprite()
                self.origin_x = ReadCoord();
                self.origin_y = ReadCoord();
                self.origin_z = ReadCoord();
+               setorigin(self, self.origin);
        }
 
        if(sendflags & 1)
diff --git a/qcsrc/common/animdecide.qc b/qcsrc/common/animdecide.qc
new file mode 100644 (file)
index 0000000..32ffef2
--- /dev/null
@@ -0,0 +1,333 @@
+// 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;
+       }
+}
diff --git a/qcsrc/common/animdecide.qh b/qcsrc/common/animdecide.qh
new file mode 100644 (file)
index 0000000..105dac7
--- /dev/null
@@ -0,0 +1,46 @@
+// 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
index b7b8da0e9f407f64da0bab06bc3dae90c7d4c528..6643387f8896069d615ecb4a15624b2c665aaa23 100644 (file)
@@ -40,8 +40,9 @@ void Curl_URI_Get_Callback(float id, float status, string data)
                cvar_set(do_cvar, data);
                strunzone(do_cvar);
        }
-       if(!do_exec && !do_cvar)
-               print(data);
+       if(!do_exec)
+               if not(do_cvar)
+                       print(data);
 }
 
 
@@ -84,7 +85,7 @@ void GenericCommand_addtolist(float request, float argc)
                        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;
@@ -92,7 +93,7 @@ void GenericCommand_addtolist(float request, float argc)
        }
 }
 
-void GenericCommand_curl(float request, float argc)
+void GenericCommand_qc_curl(float request, float argc)
 {
        switch(request)
        {
@@ -165,7 +166,7 @@ void GenericCommand_curl(float request, float argc)
                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;
                }
        }
@@ -226,6 +227,56 @@ void GenericCommand_dumpcommands(float request)
        }
 }
 
+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)
@@ -307,7 +358,7 @@ void GenericCommand_maplist(float request, float argc)
                        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");
@@ -329,7 +380,7 @@ void GenericCommand_nextframe(float request, float arguments, string command)
                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;
                }
@@ -367,7 +418,7 @@ void GenericCommand_removefromlist(float request, float argc)
                        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;
@@ -375,6 +426,45 @@ void GenericCommand_removefromlist(float request, float argc)
        }
 }
 
+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)
@@ -383,15 +473,17 @@ void GenericCommand_settemp(float request, float argc)
                {
                        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:
@@ -461,11 +553,13 @@ void GenericCommand_(float request)
 // 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") \
index be096db17f832162b4b7a235eeaa9c612882af0c..7ee3d50649b4b533b0e742c512659d167823a376 100644 (file)
@@ -19,4 +19,4 @@ void GenericCommand_macro_write_aliases(float fh);
 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];
index 6ffc5e1cb4e185206bd84abb11f19546e8c81cfb..91b1dd9b9313e8873a3efc25885fddc4c49ba203 100644 (file)
@@ -7,4 +7,4 @@
 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];
index 833216307876f0f25b5f29c71b27fe3d468ed304..898495764b60dfa322ecbf70731da392a24fac20 100644 (file)
@@ -36,17 +36,14 @@ const float TE_CSQC_NEXGUNBEAMPARTICLE = 104;
 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;
@@ -99,6 +96,7 @@ const float ENT_CLIENT_WARPZONE_TELEPORTED = 32;
 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;
@@ -180,6 +178,8 @@ const float STAT_VEHICLESTAT_RELOAD2 = 66;
 const float STAT_SECRETS_TOTAL = 70;
 const float STAT_SECRETS_FOUND = 71;
 
+const float STAT_RESPAWN_TIME = 72;
+
 const float STAT_ARMOR_LARGE_TIME = 80;
 const float STAT_HEALTH_MEGA_TIME = 81;
 const float STAT_INVISIBLE_TIME = 82;
@@ -190,7 +190,6 @@ const float STAT_SHIELD_TIME = 86;
 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;
@@ -374,85 +373,6 @@ float SPECIES_ROBOT_RUSTY  =  4;
 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
@@ -467,62 +387,6 @@ float WATERLEVEL_SUBMERGED = 3;
 
 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
@@ -530,8 +394,8 @@ float WR_CHECKAMMO1 = 3; // (SVQC) checks ammo for weapon
 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
diff --git a/qcsrc/common/counting.qh b/qcsrc/common/counting.qh
new file mode 100644 (file)
index 0000000..a74f74e
--- /dev/null
@@ -0,0 +1,199 @@
+// ===============================================
+//  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 "";
+}
index c07bbeebc37a99708ea84ecb4e3a1903b0a43fcb..a9ed986deef9e774a4a3c38b0eaaf50a30dfce82 100644 (file)
@@ -1,9 +1,12 @@
 // 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
@@ -14,6 +17,9 @@
 # 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
 
@@ -37,7 +54,7 @@
 #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
diff --git a/qcsrc/common/deathtypes.qh b/qcsrc/common/deathtypes.qh
new file mode 100644 (file)
index 0000000..ca13f15
--- /dev/null
@@ -0,0 +1,112 @@
+// ================================
+//  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
index 0aebde0af256b3a4a63d8a260030a9df429202c4..c961895d95c157aac7ad2439541f9babbd82f557 100644 (file)
@@ -172,3 +172,13 @@ void W_RandomWeapons(entity e, float n)
        }
        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;
+}
index c20715d5852c3cbf09eae967424bf50d2a6754b2..ba42d55ac62ecfffe98b046e1465055bbf607ce2 100644 (file)
@@ -242,3 +242,7 @@ string W_FixWeaponOrder_AllowIncomplete(string order);
 string W_FixWeaponOrder_ForceComplete(string order);
 
 void W_RandomWeapons(entity e, float n);
+
+string W_Name(float weaponid);
+
+float W_AmmoItemCode(float wpn);
index 05c93865dbcceed7c2606d9cb567b727e3fe8ad7..f7ced420579acb32837ea61f04511d39ddac86f5 100644 (file)
@@ -38,7 +38,7 @@ void MapInfo_Cache_Store()
                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));
@@ -65,7 +65,7 @@ float MapInfo_Cache_Retrieve(string map)
                return 0;
 
        s = db_get(_MapInfo_Cache_DB_NameToIndex, map);
-       if(!s)
+       if(s == "")
                return 0;
        i = stof(s);
 
@@ -89,6 +89,8 @@ float _MapInfo_globhandle;
 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
 }
@@ -96,11 +98,19 @@ string _MapInfo_GlobItem(float i)
 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)
index 869a44bc8bf6b2253a85f4d07227f8c4bce23bc8..625e091dcc68994ca9a3e5bdd8f4a327f3a1cff9 100644 (file)
@@ -15,7 +15,7 @@ void sv_notice_join_think()
 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();
@@ -72,7 +72,7 @@ float cl_notice_run()
     #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);
diff --git a/qcsrc/common/notifications.qc b/qcsrc/common/notifications.qc
new file mode 100644 (file)
index 0000000..cf49515
--- /dev/null
@@ -0,0 +1,1414 @@
+// ================================================
+//  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
diff --git a/qcsrc/common/notifications.qh b/qcsrc/common/notifications.qh
new file mode 100644 (file)
index 0000000..04a1cec
--- /dev/null
@@ -0,0 +1,1123 @@
+// ================================================
+//  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
diff --git a/qcsrc/common/teams.qh b/qcsrc/common/teams.qh
new file mode 100644 (file)
index 0000000..c9bed09
--- /dev/null
@@ -0,0 +1,145 @@
+#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))
index da86e98014a9e26fe625d23e2f5e95e8f65ae999..dffce2f2bb0e206c3a73b296b7136f82daecb18f 100644 (file)
@@ -1,5 +1,7 @@
+#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
index 53c14cfb0cd1798a706bb96cb36bce8afd924ba8..9db09a24345d118bb3a7620204fdd954191360bc 100644 (file)
@@ -865,44 +865,56 @@ float cvar_settemp(string tmp_cvar, string tmp_value)
        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;
 }
 
@@ -1464,8 +1476,12 @@ float isGametypeInFilter(float gt, float tp, float ts, string pattern)
                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;
 }
@@ -1985,7 +2001,7 @@ string get_model_datafilename(string m, float sk, string fil)
 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;
@@ -1995,9 +2011,21 @@ float get_model_parameters(string m, float sk)
        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")
@@ -2046,6 +2074,18 @@ float get_model_parameters(string m, float sk)
                        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)))
@@ -2463,3 +2503,86 @@ void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t
        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
index 81d5dae2148e645a4acf35de8152fb3fa7616c03..dab177b358277e0862f3b6227cd19ce72c07c5e5 100644 (file)
@@ -37,6 +37,11 @@ void ACCUMULATE_call(string func)
        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);
@@ -45,7 +50,7 @@ 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;
@@ -140,8 +145,6 @@ vector mi_pictexcoord3; // texcoords of the image corners (after transforming, t
 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);
 
@@ -226,8 +229,13 @@ void WriteInt24_t(float dest, float val);
 #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);
 
@@ -247,6 +255,12 @@ float get_model_parameters_species;
 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
 
@@ -309,7 +323,7 @@ float xdecode(string s);
 float lowestbit(float f);
 
 #ifdef CSQC
-entity ReadCSQCEntity()
+entity ReadCSQCEntity();
 #endif
 
 #ifndef MENUQC
@@ -345,8 +359,6 @@ void queue_to_execute_next_frame(string s);
 // 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
@@ -362,3 +374,60 @@ float cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor);
 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
index 163a5126d3be8f34b5e96289d61740c42c2eae0d..c4882d8d20c0c4da5a28e87a02adf6e22d7db6c7 100644 (file)
@@ -28,9 +28,8 @@ var float autocvar_cl_nolerp = 0;
 .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;
@@ -47,42 +46,62 @@ void CSQCModel_InterpolateAnimation_PreNote(float sf)
                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;
@@ -127,7 +146,9 @@ void CSQCModel_InterpolateAnimation_Do()
                        self.frame3time = 0;
                }
        }
-#else
+}
+void CSQCModel_InterpolateAnimation_1To2_Do()
+{
        if(autocvar_cl_nolerp || (autocvar_cl_lerpanim_maxdelta_framegroups == 0))
        {
                self.lerpfrac = 0;
@@ -139,22 +160,28 @@ void CSQCModel_InterpolateAnimation_Do()
                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 }
@@ -179,12 +206,14 @@ void CSQCModel_Read(float isnew)
        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 }
 
index e8ea9012cb3e16ffc6b1f761c875da7672823ef3..ded7357419221c50305a1a907df5d355d995fb54 100644 (file)
@@ -35,3 +35,16 @@ void CSQCModel_Read(float isnew);
 
 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
index 4aa8fdf92cdb89886784437e1ba471ca5b8b0d49..2711867dbc445cb68f9930c4a81600d9d3601d14 100644 (file)
 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;
@@ -217,6 +213,11 @@ void CSQCPlayer_SetCamera()
                }
                else
                {
+                       float flg = self.iflags;
+                       self.iflags &~= IFLAG_ORIGIN | IFLAG_ANGLES;
+                       InterpolateOrigin_Do();
+                       self.iflags = flg;
+
                        if(csqcplayer_status == CSQCPLAYERSTATUS_FROMSERVER)
                        {
                                vector o, v;
@@ -244,6 +245,14 @@ void CSQCPlayer_SetCamera()
                        }
                        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;
index 881ad3b329bc30100cc677b0214a72dfeb9454ec..1cb42f2a5ce8383b6345546a038766ebcee7a6e8 100644 (file)
@@ -26,6 +26,12 @@ float csqcplayer_status;
 #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();
index 587645cd4fc27b81e79e5423a6f8a765962954c3..f6044cb283f3cf3b9b87959121df6c9abfff81b2 100644 (file)
@@ -51,13 +51,13 @@ IN THE SOFTWARE.\
 .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) \
index ac0ba6e7d70ac7cb56fbc8673a4abec027b513b9..c1626f816e3b395cb70fa9da1c0e07737ccb1ae0 100644 (file)
@@ -24,6 +24,8 @@
 .vector ivelocity1, ivelocity2;
 .vector iforward1, iforward2;
 .vector iup1, iup2;
+.vector ivforward1, ivforward2;
+.vector ivup1, ivup2;
 .float itime1, itime2;
 void InterpolateOrigin_Reset()
 {
@@ -43,13 +45,20 @@ void InterpolateOrigin_Note()
        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);
@@ -67,6 +76,28 @@ void InterpolateOrigin_Note()
                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;
@@ -103,22 +134,36 @@ void InterpolateOrigin_Do()
        {
                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;
 }
index 8254fae8cfc6f44649b7dd158035d7749bec79aa..66bf491e57dd745378e9d939bf65b80e88d4d80e 100644 (file)
 #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
@@ -40,3 +44,6 @@ void InterpolateOrigin_Reset();
 
 // call this BEFORE drawing
 void InterpolateOrigin_Do();
+
+// in case we interpolate that:
+.vector v_angle;
index c9b9ce9cbc358056fa13b34169ac04c5c015559c..79d33fd3c2167931f75c3150e7d1e6ee9924a967 100644 (file)
@@ -335,7 +335,7 @@ void(entity e, vector o) setorigin = #2;
 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;
index c1198746171f79dd03925f9c2bbac36261717732..8b2933a546b94e1a51439fec66bada709ba99648 100644 (file)
@@ -253,7 +253,7 @@ vector      stov(string s)  = #55;
 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;
index 912c3ecabe18bee45be837d061a6a388f684376b..00e0d31b21d450ae116c4b6412e328904c2b2686 100644 (file)
@@ -402,7 +402,7 @@ void(entity e, vector o) setorigin  = #2;
 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;
index 8d125d40cbd83d5e4a3b95f6e82fe5a649b6f306..93ae4a838da7d0936d8e72535378cb913dd9e7c7 100644 (file)
@@ -19,7 +19,6 @@
 #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"
@@ -67,7 +66,6 @@
 #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"
index f6312931f6a11c4117c159433c2361c949ec22c0..2c0b1edf38aa33fcd42e6117bf4a5c6c108bd04a 100644 (file)
@@ -35,7 +35,10 @@ void GameCommand(string theCommand)
                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;
        }
 
@@ -48,18 +51,37 @@ void GameCommand(string theCommand)
                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;
        }
 
@@ -88,9 +110,5 @@ void GameCommand(string theCommand)
                return;
        }
 
-       if(argv(0) == "curl")
-       {
-       }
-
        print(_("Invalid command. For a list of supported commands, try menu_cmd help.\n"));
 }
index 20bc4ab9c911459c109cb7ebf57001b108a00a46..6b32bae27080d279c760923b4ddd613868469079 100644 (file)
@@ -9,7 +9,7 @@ CLASS(Button) EXTENDS(Label)
        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)
@@ -81,7 +81,8 @@ float Button_mouseRelease(entity me, vector pos)
                {
                        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;
        }
@@ -162,7 +163,8 @@ void Button_draw(entity me)
        {
                // 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;
 
diff --git a/qcsrc/menu/item/gecko.c b/qcsrc/menu/item/gecko.c
deleted file mode 100644 (file)
index 5a69c3b..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-// 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
index 60da88a09ca957307f3616e57526f2e3b19a0e19..c32057da8d2665e10655220354fd0aa85bee5dbb 100644 (file)
@@ -247,7 +247,7 @@ void ListBox_updateControlTopBottom(entity me)
 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
index 8f8f45119f8744bd74d900776d4b97015bc25406..64da6bcd6de8a93f0919d080bc425f2f358b3762 100644 (file)
@@ -279,7 +279,7 @@ float Nexposee_keyUp(entity me, float scan, float ascii, float shift)
 
 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;
index d3bf2ec6298996246eeabdf0c3424f51ca790187..ddf9ff686adc7b4413086cab0093d08fc6aa0a7a 100644 (file)
@@ -16,8 +16,6 @@ float menuInitialized;
 float menuNotTheFirstFrame;
 float menuMouseMode;
 
-void SUB_Null() { }
-
 void m_sync()
 {
        updateCompression();
@@ -55,7 +53,7 @@ void m_init()
        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)
@@ -306,6 +304,9 @@ void draw_Picture_Aligned(vector algn, float scalemode, string img, float a)
        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:
index 641ddf7d19df20db49ad73d707a74197cf427ad5..b6c0795a8544424d505b8392d8d7f4f7cec59825 100644 (file)
@@ -33,8 +33,6 @@ entity keyGrabber;
 
 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.
index 34f32e306aa16df6d831a4d3a36a9021a17ff2bb..28b7f08e4eff2ea0a5ad64e74ff532a8b3fa6b5c 100644 (file)
@@ -21,7 +21,7 @@
 #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
index 0f545e60cfa368967ca4cb6f694132fff6558fd1..36905e17ad5be250f3fd0838cb4ed118a8850928 100644 (file)
@@ -1,7 +1,9 @@
 ../../menu.dat
 
+sys-pre.qh
 ../dpdefs/menudefs.qc
 ../dpdefs/keycodes.qc
+sys-post.qh
 
 config.qh
 ../common/util-pre.qh
@@ -11,10 +13,12 @@ config.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
diff --git a/qcsrc/menu/sys-post.qh b/qcsrc/menu/sys-post.qh
new file mode 100644 (file)
index 0000000..e466fb4
--- /dev/null
@@ -0,0 +1 @@
+#pragma noref 0
diff --git a/qcsrc/menu/sys-pre.qh b/qcsrc/menu/sys-pre.qh
new file mode 100644 (file)
index 0000000..a964ae9
--- /dev/null
@@ -0,0 +1 @@
+#pragma noref 1
index 0537967bd69cf564c33986968426c98e8acb69a7..90b559b01ca4cf2a61cc513c98555ef3ba5e15dd 100644 (file)
@@ -249,7 +249,6 @@ void XonoticCampaignList_clickListBoxItem(entity me, float i, vector where)
 void XonoticCampaignList_drawListBoxItem(entity me, float i, vector absSize, float isSelected)
 {
        string s;
-       float p;
        vector theColor;
        float theAlpha;
        float j, n;
@@ -274,7 +273,6 @@ void XonoticCampaignList_drawListBoxItem(entity me, float i, vector absSize, flo
        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
index 66f292a0369588ae675b237fc0580d1d8cf34a04..eb9590827da99ce9c835a1e559f29d1758734d63 100644 (file)
@@ -53,7 +53,7 @@ vector hslimage_color(vector v, vector margin)
 
 vector color_hslimage(vector v, vector margin)
 {
-       vector pos;
+       vector pos = '0 0 0';
        v = rgb_to_hsl(v);
        if (v_y)
        {
index 03898a3f8b90ef48b11e74de917d8939a1dfe4dc..52f1a1f26e7890d18da2c2a4257749815605e9d9 100644 (file)
@@ -166,7 +166,10 @@ float XonoticCvarList_keyDown(entity me, float scan, float ascii, float shift)
                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)
index b31622f67390e02f1d1465b02c5b55652fab1907..e3cd78eb6a56ba17f982a9c24456176f724c4502 100644 (file)
@@ -33,8 +33,8 @@ void XonoticHUDWeaponsDialog_fill(entity me)
                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");
index 25b0fcb191d6ab2e41922c8ef9a63715a085077e..c55d4d488ba4ebcf37f2fd096fcf27a81e5c79ba 100644 (file)
@@ -37,12 +37,6 @@ void XonoticModelDialog_fill(entity me)
                        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);
diff --git a/qcsrc/menu/xonotic/dialog_news.c b/qcsrc/menu/xonotic/dialog_news.c
deleted file mode 100644 (file)
index f638c77..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-#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
index 96bf5e5c67d207f3b8b864535eca34c2a6628a85..daa8f3ff104fe3bcfc659fd32f7762c2ebd1fc50 100644 (file)
@@ -40,6 +40,7 @@ void XonoticInputSettingsTab_fill(entity me)
                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")));
index c37cb7e4055f105508ec1770c56eb12ffdcc5cc0..6e13f65b818ea6cb348a1d47a744e43072d33299 100644 (file)
@@ -14,7 +14,7 @@ ENDCLASS(XonoticSingleplayerDialog)
 
 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");
index 2a9c094b8eb07a74ac6752562b3eecfb87cd200a..dbbcc7b0c495af9609cae5dfac612b2ef4da9f74 100644 (file)
@@ -5,9 +5,9 @@ CLASS(XonoticInputBox) EXTENDS(InputBox)
        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)
@@ -55,7 +55,8 @@ void XonoticInputBox_setText(entity me, string new)
        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);
        }
@@ -85,7 +86,8 @@ float XonoticInputBox_keyDown(entity me, float key, float ascii, float shift)
                        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;
index 1107e60abc6b3296e77dd9582bbe6613a267ef32..739be1b056aa908da09d5ab1bfded18f3ef30708 100644 (file)
@@ -22,6 +22,7 @@ CLASS(XonoticKeyBinder) EXTENDS(XonoticListBox)
        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)
@@ -80,6 +81,8 @@ void replace_bind(string from, string to)
                if(k != -1)
                        localcmd("\nbind \"", keynumtostring(k), "\" \"", to, "\"\n");
        }
+       if(n)
+               cvar_set("_hud_showbinds_reload", "1");
 }
 void XonoticKeyBinder_configureXonoticKeyBinder(entity me)
 {
@@ -126,6 +129,7 @@ void KeyBinder_Bind_Change(entity btn, entity me)
                return;
 
        me.keyGrabButton.forcePressed = 1;
+       me.clearButton.disabled = 1;
        keyGrabber = me;
 }
 void XonoticKeyBinder_keyGrabbed(entity me, float key, float ascii)
@@ -134,6 +138,8 @@ void XonoticKeyBinder_keyGrabbed(entity me, float key, float ascii)
        string func;
 
        me.keyGrabButton.forcePressed = 0;
+       me.clearButton.disabled = 0;
+
        if(key == K_ESCAPE)
                return;
 
@@ -161,6 +167,7 @@ void XonoticKeyBinder_keyGrabbed(entity me, float key, float ascii)
        }
        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)
 {
@@ -168,11 +175,11 @@ void XonoticKeyBinder_editUserbind(entity me, string theName, string theCommandP
 
        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;
@@ -189,11 +196,11 @@ void KeyBinder_Bind_Edit(entity btn, entity me)
 
        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;
@@ -222,6 +229,7 @@ void KeyBinder_Bind_Clear(entity btn, entity me)
                        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)
 {
index 54b9554a80456d1ccc25a2f7df2c02790c1f961a..b5af66126f7fbec2e6b6d3b93c77077eaa678cbf 100644 (file)
@@ -167,7 +167,6 @@ void XonoticMapList_drawListBoxItem(entity me, float i, vector absSize, float is
 {
        // layout: Ping, Map name, Map name, NP, TP, MP
        string s;
-       float p;
        float theAlpha;
        float included;
 
@@ -185,7 +184,6 @@ void XonoticMapList_drawListBoxItem(entity me, float i, vector absSize, float is
        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
@@ -246,7 +244,7 @@ void MapList_All(entity btn, entity me)
 {
        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));
index 44ca1b227943cf7da354dbe5219f72b387f3fa48..9e49626023375b96651e5fa13bc4c2e50d0f6c54 100644 (file)
@@ -733,11 +733,11 @@ void XonoticServerList_drawListBoxItem(entity me, float i, vector absSize, float
        // 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;
 
@@ -825,7 +825,9 @@ float XonoticServerList_keyDown(entity me, float scan, float ascii, float shift)
                {
                        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)
        {
@@ -834,7 +836,9 @@ float XonoticServerList_keyDown(entity me, float scan, float ascii, float shift)
                {
                        ToggleFavorite(me.selectedServer);
                        me.ipAddressBoxFocused = -1;
+                       return 1;
                }
+               return 0;
        }
        else if(SUPER(XonoticServerList).keyDown(me, scan, ascii, shift))
                return 1;
index 4c03eaa5f9caa9edb5255ee3f4a217a904799463..e80bf30e4e410b183ca23dc487b6f15afd1ae5b1 100644 (file)
@@ -465,7 +465,7 @@ float preMenuInit()
 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
@@ -473,13 +473,12 @@ void postMenuDraw()
 {
        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();
 
index 73025f1f61004ed50996fc1dfa692aafac943895..5e0a91a3e897241196d0179e4467d7ca3f169ed0 100644 (file)
@@ -7,12 +7,6 @@
 
 .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)
index 70a89eed8d0adb636c2a8492c270f9ad23456cba..9ea8749f417eeeae11929eb7f7f9d0330792cd66 100644 (file)
@@ -126,7 +126,7 @@ void reset_map(float dorespawn)
        }
 
        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)
@@ -202,8 +202,7 @@ void Arena_Warmup()
        {
                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)
@@ -237,8 +236,7 @@ void Arena_Warmup()
                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)
@@ -250,8 +248,7 @@ void Arena_Warmup()
                                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);
                        }
                }
 
@@ -273,8 +270,7 @@ void Arena_Warmup()
                                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) {
@@ -296,22 +292,22 @@ void count_players()
        // 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;
@@ -325,12 +321,12 @@ void count_alive_players()
        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;
@@ -345,22 +341,22 @@ void count_alive_players()
        {
                // 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;
@@ -403,12 +399,12 @@ void Spawnqueue_Check()
                                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");
index 2562dca3df803fa93725204eb01f7059ef1cd189..7a5662c9799fb51f738b7293a3e5ce04f9a99f44 100644 (file)
@@ -9,7 +9,7 @@ void spawnfunc_info_player_attacker() {
                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();
 }
 
@@ -19,7 +19,7 @@ void spawnfunc_info_player_defender() {
                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();
 }
 
@@ -216,10 +216,10 @@ void spawnfunc_func_assault_destructible() {
        }
        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();
 }
@@ -289,10 +289,10 @@ void assault_roundstart_use() {
        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;
 
@@ -313,7 +313,7 @@ void spawnfunc_target_assault_roundstart() {
                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;
@@ -351,10 +351,10 @@ void assault_new_round()
        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;
        }
 
 
@@ -363,10 +363,10 @@ void assault_new_round()
        {
                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;
                }
        }
 
index d65d866ca60132011470f2a058dcd407ed2db2f4..b86e84369913f6386d103e805db1774301c09e37 100644 (file)
@@ -127,10 +127,10 @@ void ctf_flag_spawnstuff()
        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)
@@ -290,7 +290,7 @@ void DropFlag(entity e, entity penalty_receiver, entity attacker)
        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)
@@ -494,11 +494,11 @@ void FlagTouch()
                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);
                        }
@@ -513,7 +513,7 @@ void FlagTouch()
                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)
@@ -563,7 +563,7 @@ void FlagTouch()
        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);
@@ -578,22 +578,22 @@ void FlagTouch()
                                }
 
                        // 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"));
@@ -663,7 +663,7 @@ void spawnfunc_info_player_team1()
                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();}
@@ -683,7 +683,7 @@ void spawnfunc_info_player_team2()
                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();}
@@ -703,7 +703,7 @@ void spawnfunc_info_player_team3()
                remove(self);
                return;
        }
-       self.team = COLOR_TEAM3; // yellow
+       self.team = NUM_TEAM_3; // yellow
        spawnfunc_info_player_deathmatch();
 }
 
@@ -723,7 +723,7 @@ void spawnfunc_info_player_team4()
                remove(self);
                return;
        }
-       self.team = COLOR_TEAM4; // purple
+       self.team = NUM_TEAM_4; // purple
        spawnfunc_info_player_deathmatch();
 }
 
@@ -741,11 +741,11 @@ void item_flag_postspawn()
        // 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;
 
@@ -802,7 +802,7 @@ void spawnfunc_item_flag_team1()
        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###";
@@ -901,7 +901,7 @@ void spawnfunc_item_flag_team2()
        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###";
@@ -1002,8 +1002,8 @@ void ctf_spawnteams()
 
        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()
@@ -1089,7 +1089,7 @@ void ctf_setstatus()
 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) {
diff --git a/qcsrc/server/attic/domination.qc b/qcsrc/server/attic/domination.qc
new file mode 100644 (file)
index 0000000..a898b53
--- /dev/null
@@ -0,0 +1,525 @@
+
+/*
+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);
+}
+
index b450f761e31af442b2c084763e97fd44ae5faf84..0259a5756ea1620c4ab21be3a9f5df3c2dc920c3 100644 (file)
@@ -166,7 +166,7 @@ void() monsterinwall =
        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;
 }
index c95c2eaf2f819513fee854a5eaaf73ccf9ea426d..eb1105b933f7cec36e83cdd69074dc1dc12bff98 100644 (file)
@@ -170,7 +170,7 @@ void zombie_die(vector dir)
     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;
index d3f4b55f4a49acf42693df6e04df24942a1b99f3..dc9c91ce68d9102ffaaccaa5a4a13fe335b99fd9 100644 (file)
@@ -165,7 +165,7 @@ void GiveBall (entity plyr, entity ball)
 
        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.
 
@@ -235,7 +235,7 @@ void ResetBall (void)
        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)
@@ -394,7 +394,7 @@ void GoalTouch (void)
        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);
 }
 
@@ -427,10 +427,10 @@ void nb_spawnteams (void)
        {
                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;
                }
        }
 }
@@ -541,22 +541,22 @@ void SpawnGoal (void)
 
 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();
 }
 
index f7845637121c90e6cb2f58c80f314391d8990e5d..067b174369ea3cd8f1b0b22c6d83ded256f880ca 100644 (file)
@@ -261,7 +261,7 @@ void bumb_spawn()
 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;
index 16a7193c13710903da8cd9ed2db5143802504508..1ea2615eadc2e846e807fd074b13fc6954e32e61 100644 (file)
@@ -94,7 +94,6 @@ float autocvar_g_balance_rifle_primary_bullethail;
 float autocvar_g_balance_rifle_primary_burstcost;
 float autocvar_g_balance_rifle_primary_damage;
 float autocvar_g_balance_rifle_primary_force;
-float autocvar_g_balance_rifle_primary_headshotaddeddamage;
 float autocvar_g_balance_rifle_primary_lifetime;
 float autocvar_g_balance_rifle_primary_refire;
 float autocvar_g_balance_rifle_primary_shots;
@@ -109,7 +108,6 @@ float autocvar_g_balance_rifle_secondary_bullethail;
 float autocvar_g_balance_rifle_secondary_burstcost;
 float autocvar_g_balance_rifle_secondary_damage;
 float autocvar_g_balance_rifle_secondary_force;
-float autocvar_g_balance_rifle_secondary_headshotaddeddamage;
 float autocvar_g_balance_rifle_secondary_lifetime;
 float autocvar_g_balance_rifle_secondary_reload;
 float autocvar_g_balance_rifle_secondary_refire;
@@ -704,7 +702,6 @@ float autocvar_g_balance_uzi_burst_spread;
 float autocvar_g_balance_uzi_first;
 float autocvar_g_balance_uzi_first_ammo;
 float autocvar_g_balance_uzi_first_damage;
-float autocvar_g_balance_uzi_first_headshotaddeddamage;
 float autocvar_g_balance_uzi_first_force;
 float autocvar_g_balance_uzi_first_refire;
 float autocvar_g_balance_uzi_first_spread;
@@ -715,7 +712,6 @@ float autocvar_g_balance_uzi_spread_max;
 float autocvar_g_balance_uzi_spread_min;
 float autocvar_g_balance_uzi_sustained_ammo;
 float autocvar_g_balance_uzi_sustained_damage;
-float autocvar_g_balance_uzi_sustained_headshotaddeddamage;
 float autocvar_g_balance_uzi_sustained_force;
 float autocvar_g_balance_uzi_sustained_refire;
 float autocvar_g_balance_uzi_sustained_spread;
@@ -761,6 +757,7 @@ float autocvar_g_chat_flood_spl_team;
 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;
@@ -786,7 +783,6 @@ float autocvar_g_ctf_pass_request;
 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;
@@ -796,7 +792,6 @@ float autocvar_g_ctf_flag_dropped_waypoint;
 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;
@@ -868,7 +863,6 @@ string autocvar_g_hitplots_individuals;
 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;
@@ -898,7 +892,6 @@ float autocvar_g_keyhunt_teams_override;
 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")
@@ -1168,13 +1161,10 @@ float autocvar_sv_eventlog_files_counter;
 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;
@@ -1190,7 +1180,6 @@ float autocvar_sv_maxairspeed;
 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;
@@ -1229,6 +1218,7 @@ float autocvar_sv_vote_singlecount;
 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;
@@ -1257,7 +1247,6 @@ float autocvar_welcome_message_time;
 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;
@@ -1275,3 +1264,6 @@ float autocvar_g_sandbox_object_material_velocity_min;
 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;
index 3e1cae313ff6ecbc06c3629d699c911bb16abb42..d87c72695f32a6a5593def26636eeba93746267f 100644 (file)
@@ -45,7 +45,7 @@ void bot_think()
 
        if (autocvar_g_campaign && !campaign_bots_may_start)
        {
-               self.nextthink = time + 0.5;
+               self.bot_nextthink = time + 0.5;
                return;
        }
 
@@ -85,7 +85,7 @@ void bot_think()
        {
                // block the bot during the countdown to game start
                self.movement = '0 0 0';
-               self.nextthink = game_starttime;
+               self.bot_nextthink = game_starttime;
                return;
        }
 
@@ -135,16 +135,15 @@ void bot_setnameandstuff()
        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)
@@ -393,19 +392,19 @@ void bot_clientconnect()
        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);
 
@@ -426,13 +425,13 @@ void bot_removefromlargestteam()
        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;
index b17697d2f8524d6ae21bc3c9dee8205161a07cf3..8071fef74aec7fe26fbb243743fdd36d72941e57 100644 (file)
@@ -127,12 +127,12 @@ void havocbot_goalrating_ons_controlpoints_attack(float ratingscale)
                        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;
@@ -217,6 +217,7 @@ void havocbot_goalrating_ons_controlpoints_attack(float ratingscale)
        {
                // 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)
index ad3bb2367418f611d13bb67725c70cd416d7831f..a3078c4e43588bc64bbbeef1c2a09e490a4af928 100644 (file)
@@ -203,25 +203,6 @@ void havocbot_goalrating_enemyplayers(float ratingscale, vector org, float sradi
 // 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()
@@ -284,19 +265,12 @@ void havocbot_chooserole_race()
        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)
index a1c00d0409183fb32e5cea864b7ff3764a5d9c94..ace11c6d696a52a046fee386f4a44fca4563091f 100644 (file)
@@ -31,17 +31,23 @@ void bot_queuecommand(entity bot, string cmdstring)
                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);
+                       }
                }
        }
 
@@ -1091,8 +1097,24 @@ float bot_cmd_sound()
        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;
 }
index d31a88b52fbe2c954fbc30c2ba01de8ca1b5c325..8e9ae6b911e745cfb58bf6acb7132792f3d898eb 100644 (file)
@@ -360,8 +360,8 @@ void waypoint_schedulerelinkall()
 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");
@@ -375,12 +375,8 @@ float waypoint_load_links()
                return FALSE;
        }
 
-       while (1)
+       while ((s = fgets(file)))
        {
-               s = fgets(file);
-               if (!s)
-                       break;
-
                tokens = tokenizebyseparator(s, "*");
 
                if (tokens!=2)
@@ -394,7 +390,7 @@ float waypoint_load_links()
                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;
@@ -456,8 +452,8 @@ float waypoint_load_links()
 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");
@@ -473,12 +469,8 @@ void waypoint_load_links_hardwired()
                return;
        }
 
-       for (;;)
+       while ((s = fgets(file)))
        {
-               s = fgets(file);
-               if (!s)
-                       break;
-
                if(substring(s, 0, 2)=="//")
                        continue;
 
@@ -494,7 +486,7 @@ void waypoint_load_links_hardwired()
                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;
@@ -573,19 +565,20 @@ void waypoint_save_links()
                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;
@@ -686,18 +679,15 @@ float waypoint_loadall()
        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);
diff --git a/qcsrc/server/builtins.qh b/qcsrc/server/builtins.qh
deleted file mode 100644 (file)
index e69de29..0000000
index e4f6cf14526e3bc7c5d7bdad8388e8ceeb95d518..f0f87f4036de0990d35b4a63ab498588936df0e6 100644 (file)
@@ -7,9 +7,9 @@ void send_CSQC_teamnagger() {
 }
 
 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) {
@@ -408,10 +408,11 @@ void PutObserverInServer (void)
        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;
        }
 
@@ -425,12 +426,11 @@ void PutObserverInServer (void)
 
        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);
@@ -472,7 +472,7 @@ void PutObserverInServer (void)
        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;
@@ -512,11 +512,13 @@ void PutObserverInServer (void)
        {
                if(self.version_mismatch)
                {
+                       self.frags = FRAGS_SPECTATOR;
                        Spawnqueue_Unmark(self);
                        Spawnqueue_Remove(self);
                }
                else
                {
+                       self.frags = FRAGS_LMS_LOSER;
                        Spawnqueue_Insert(self);
                }
        }
@@ -535,6 +537,13 @@ void PutObserverInServer (void)
                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;
 }
@@ -555,7 +564,7 @@ void FixPlayermodel()
                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));
@@ -609,8 +618,11 @@ void FixPlayermodel()
                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))
@@ -687,7 +699,7 @@ void PutClientInServer (void)
                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
                }
 
@@ -791,7 +803,7 @@ void PutClientInServer (void)
                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;
@@ -872,9 +884,9 @@ void PutClientInServer (void)
 
                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);
@@ -917,8 +929,9 @@ void PutClientInServer (void)
                self.weaponname = "";
                self.switchingweapon = 0;
 
-               if(!self.alivetime)
-                       self.alivetime = time;
+               if(!inWarmupStage)
+                       if(!self.alivetime)
+                               self.alivetime = time;
 
                antilag_clear(self);
 
@@ -1076,7 +1089,7 @@ void ClientKill_Now_TeamChange()
                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
@@ -1227,28 +1240,28 @@ void ClientKill_TeamChange (float targetteam) // 0 = don't change, -1 = auto, -2
                        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);
                }
        }
 
@@ -1290,7 +1303,7 @@ void FixClientCvars(entity e)
                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
@@ -1339,7 +1352,6 @@ ClientConnect
 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);
@@ -1359,7 +1371,7 @@ void ClientConnect (void)
        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";
@@ -1385,9 +1397,6 @@ void ClientConnect (void)
 
        race_PreSpawnObserver();
 
-       //if(g_domination)
-       //      dom_player_join_team(self);
-
        // identify the right forced team
        if(autocvar_g_campaign)
        {
@@ -1395,30 +1404,30 @@ void ClientConnect (void)
                {
                        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")
@@ -1470,12 +1479,10 @@ void ClientConnect (void)
 
        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?
@@ -1518,7 +1525,7 @@ void ClientConnect (void)
        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;
@@ -1542,8 +1549,6 @@ void ClientConnect (void)
        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);
@@ -1575,13 +1580,10 @@ void ClientConnect (void)
        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();
 
@@ -1636,10 +1638,8 @@ void ClientDisconnect (void)
 
        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);
@@ -1786,15 +1786,9 @@ void player_powerups (void)
        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);
 
@@ -1816,7 +1810,8 @@ void player_powerups (void)
                                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
@@ -1826,7 +1821,8 @@ void player_powerups (void)
                                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);
                        }
                }
 
@@ -1836,7 +1832,8 @@ void player_powerups (void)
                        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
@@ -1844,7 +1841,8 @@ void player_powerups (void)
                        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);
                        }
                }
        }
@@ -1857,7 +1855,8 @@ void player_powerups (void)
                        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
@@ -1865,7 +1864,8 @@ void player_powerups (void)
                        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)
@@ -1875,7 +1875,8 @@ void player_powerups (void)
                        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
@@ -1883,7 +1884,8 @@ void player_powerups (void)
                        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)
@@ -1892,7 +1894,8 @@ void player_powerups (void)
                        {
                                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)
                        {
@@ -1905,7 +1908,8 @@ void player_powerups (void)
                                {
                                        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);
                                }
                        }
                }
@@ -1914,7 +1918,8 @@ void player_powerups (void)
                        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
                        {
@@ -2171,6 +2176,7 @@ void SpectateCopy(entity spectatee) {
        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);
@@ -2319,50 +2325,34 @@ void ShowRespawnCountdown()
        }
 }
 
-.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);
        }
 }
 
@@ -2413,7 +2403,7 @@ float nJoinAllowed(entity ignore) {
 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);
                }
        }
@@ -2426,12 +2416,12 @@ void PrintWelcomeMessage()
                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
@@ -2440,7 +2430,7 @@ void PrintWelcomeMessage()
                                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) {
@@ -2448,7 +2438,7 @@ void PrintWelcomeMessage()
                                        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);
                                }
                        }
                }
@@ -2562,6 +2552,11 @@ void PlayerPreThink (void)
        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
@@ -2595,7 +2590,7 @@ void PlayerPreThink (void)
                                        {
                                                // 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
                                        {
@@ -2605,13 +2600,13 @@ void PlayerPreThink (void)
                                                {
                                                        // 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);
                                                }
                                        }
                                }
@@ -2621,7 +2616,7 @@ void PlayerPreThink (void)
        // 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;
        }
 
@@ -2663,10 +2658,6 @@ void PlayerPreThink (void)
 
                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);
@@ -2734,6 +2725,11 @@ void PlayerPreThink (void)
                                }
                                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)
@@ -2776,7 +2772,7 @@ void PlayerPreThink (void)
                                //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');
@@ -2788,8 +2784,19 @@ void PlayerPreThink (void)
 
                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)
                        {
@@ -2952,18 +2959,6 @@ Called every frame for each client after the physics are run
 =============
 */
 .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
@@ -2976,11 +2971,7 @@ void PlayerPostThink (void)
        {
                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
                {
@@ -2989,12 +2980,11 @@ void PlayerPostThink (void)
                        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;
                        }
@@ -3026,10 +3016,6 @@ void PlayerPostThink (void)
                if (intermission_running)
                        return;         // intermission or finale
                GetPressedKeys();
-       } else if (self.classname == "observer") {
-               //do nothing
-       } else if (self.classname == "spectator") {
-               //do nothing
        }
        
 #ifdef TETRIS
@@ -3057,32 +3043,11 @@ void PlayerPostThink (void)
        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)
                {
index 3e2268d89748d1eb193892407968c8ee721f66a5..50401604ef905313d521380d6995b0cf202d6bec 100644 (file)
@@ -169,10 +169,7 @@ void PlayerJump (void)
        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);
@@ -897,15 +894,15 @@ void SV_PlayerPhysics()
                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);
index 3e560bd2452a71020d339d7ed22830a76b212ec8..cb44da03fe794cada0243885dd44b53f0a974860 100644 (file)
@@ -26,7 +26,7 @@ void WeaponStats_ready(entity fh, entity pass, float status)
                        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"));
@@ -161,16 +161,20 @@ void CopyBody(float keepvelocity)
        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;
@@ -208,6 +212,8 @@ void CopyBody(float keepvelocity)
        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;
 }
@@ -225,132 +231,33 @@ float player_getspecies()
 
 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)
@@ -496,6 +403,30 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
                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;
@@ -536,15 +467,15 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
                        {
                                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);
                                                }
                                        }
 
@@ -580,29 +511,8 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
        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);
@@ -644,7 +554,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
                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)
@@ -771,9 +681,9 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
                        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;
@@ -786,7 +696,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
                // 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);
                }
@@ -1023,17 +933,18 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f
                        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)
@@ -1047,7 +958,7 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f
                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);
@@ -1055,7 +966,7 @@ float Say(entity source, float teamsay, entity privatesay, string msgin, float f
                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);
@@ -1237,7 +1148,7 @@ void FakeGlobalSound(string sample, float chan, float voicetype)
                                break;
                        if(!sv_taunt)
                                break;
-                       if(sv_gentle)
+                       if(autocvar_sv_gentle)
                                break;
                        tauntrand = random();
                        msg_entity = self;
@@ -1252,10 +1163,10 @@ void FakeGlobalSound(string sample, float chan, float voicetype)
                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)
@@ -1334,7 +1245,7 @@ void GlobalSound(string sample, float chan, float voicetype)
                                break;
                        if(!sv_taunt)
                                break;
-                       if(sv_gentle)
+                       if(autocvar_sv_gentle)
                                break;
                        tauntrand = random();
                        FOR_EACH_REALCLIENT(msg_entity)
@@ -1349,10 +1260,10 @@ void GlobalSound(string sample, float chan, float voicetype)
                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)
                        {
@@ -1400,14 +1311,8 @@ void VoiceMessage(string type, string msg)
                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
@@ -1416,14 +1321,9 @@ void MoveToTeam(entity client, float team_colour, float type, float show_message
 
        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"));
 }
index 236c0923fdc330834469234bc9eb2285a1f6bb26..2a1297dc2be398d5a204852f84c880e862c54820 100644 (file)
@@ -158,16 +158,6 @@ float weapon_action(float wpn, float wrequest)
        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()
 {
@@ -298,6 +288,7 @@ string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vecto
                wep.savenextthink = wep.nextthink;
                wep.nextthink = min(wep.nextthink, time + 0.5);
                wep.pickup_anyway = TRUE; // these are ALWAYS pickable
+
                return s;
        }
 }
@@ -358,12 +349,9 @@ void W_ThrowWeapon(vector velo, vector delta, float doreduce)
 
        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
index 402b692af1230fba959a89c1fce3aef5a999ab13..c559c150db4a28adb8b41aca39b737f775277d85 100644 (file)
@@ -343,10 +343,10 @@ void CL_WeaponEntity_SetModel(string name)
 
                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
@@ -578,7 +578,6 @@ void CL_Weaponentity_Think()
 void CL_ExteriorWeaponentity_Think()
 {
        float tag_found;
-       vector ang;
        self.nextthink = time;
        if (self.owner.exteriorweaponentity != self)
        {
@@ -609,10 +608,7 @@ void CL_ExteriorWeaponentity_Think()
                        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;
@@ -621,58 +617,6 @@ void CL_ExteriorWeaponentity_Think()
        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;
 
@@ -770,7 +714,6 @@ float client_hasweapon(entity cl, float wpn, float andammo, float complain)
                                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;
@@ -784,8 +727,7 @@ float client_hasweapon(entity cl, float wpn, float andammo, float complain)
                // 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)
                        {
@@ -816,7 +758,6 @@ float client_hasweapon(entity cl, float wpn, float andammo, float complain)
                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");
@@ -879,14 +820,6 @@ void W_SwitchToOtherWeapon(entity pl)
                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)
@@ -910,7 +843,15 @@ 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;
                }
@@ -1008,13 +949,14 @@ void weapon_thinkf(float fr, float t, void() func)
        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);
@@ -1046,25 +988,17 @@ void weapon_thinkf(float fr, float t, void() func)
        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;
        }
 }
 
@@ -1196,7 +1130,7 @@ vector findperpendicular(vector v)
 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;
index 8e3ecb7ba0369ab674ac56ccc2198c9bf01c11a6..8c71af1793bcb92eab965927e6ce9d53813920ef 100644 (file)
@@ -12,4 +12,4 @@ float Ban_Insert(string ip, float bantime, string reason, float dosync);
 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);
index 530646afd2ec8fbb105dc8a080b41dadaaa25d0f..6c1e0ed56f58e79094ed4fcb1ce461bab8533162 100644 (file)
@@ -159,13 +159,15 @@ void ClientCommand_join(float request)
                                                
                                                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);
                                        }
                                }
                        }
@@ -284,10 +286,10 @@ void ClientCommand_selectteam(float request, float argc)
                                                                
                                                                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;
@@ -397,6 +399,8 @@ void ClientCommand_spectate(float request)
                                {
                                        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));
                                        }
index eae71b045c82845688d653b999d705f07854ac68..e95cf4c6585ba07ec0aa45008bdaf747bb728f8f 100644 (file)
@@ -162,14 +162,9 @@ void print_to(entity to, string input)
 // 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);
 }
@@ -184,8 +179,7 @@ void timeout_handler_think()
                {
                        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");
@@ -214,9 +208,7 @@ void timeout_handler_think()
                {
                        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
@@ -572,7 +564,7 @@ void CommonCommand_timeout(float request, entity caller) // DEAR GOD THIS COMMAN
                                {                                       
                                        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;
@@ -607,14 +599,14 @@ void CommonCommand_who(float request, entity caller, float argc)
        {
                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"));
                        
@@ -638,22 +630,13 @@ void CommonCommand_who(float request, entity caller, float argc)
                                        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));
                                
index 0bedd6d5e21f3ce44f0b2d479eed092a59029b65..39206966cfee11bf0c8326ca76a6b138c0eebe4f 100644 (file)
@@ -96,7 +96,7 @@ string getrankings()
                        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");
        }
 
@@ -240,7 +240,7 @@ string getladder()
        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----+--------");
@@ -263,7 +263,7 @@ string getladder()
                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)
index b2bf9d9b97aa6bb2a9b92433299234c351f01b28..0944f04fbbe06799f4f523d37eb243af42bddb92 100644 (file)
@@ -823,6 +823,62 @@ void GameCommand_gettaginfo(float request, float argc)
        }
 }
 
+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)
@@ -916,7 +972,6 @@ void GameCommand_moveplayer(float request, float argc)
                        string targets = strreplace(",", " ", argv(1));
                        string original_targets = strreplace(" ", ", ", targets);
                        string destination = argv(2);
-                       string notify = argv(3);
                        
                        string successful, t;
                        successful = string_null;
@@ -961,21 +1016,21 @@ void GameCommand_moveplayer(float request, float argc)
                                                        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
                                                                {
@@ -984,21 +1039,21 @@ void GameCommand_moveplayer(float request, float argc)
                                                                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
@@ -1028,13 +1083,10 @@ void GameCommand_moveplayer(float request, float argc)
                        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");
@@ -1056,7 +1108,7 @@ void GameCommand_nospectators(float request)
                                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"));
@@ -1298,7 +1350,7 @@ void GameCommand_shuffleteams(float request)
                                        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)
@@ -1312,7 +1364,7 @@ void GameCommand_shuffleteams(float request)
                                                                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;
@@ -1357,8 +1409,9 @@ void GameCommand_stuffto(float request, float argc)
        // 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:
@@ -1631,8 +1684,9 @@ void GameCommand_warp(float request, float argc)
                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;
                }
        }
@@ -1673,6 +1727,7 @@ void GameCommand_(float request)
        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") \
index d4d3d611c2d9ba31b26c62d34a4097403daca566..b1bae14c18f04c672f8761d643b94ddc525dc10d 100644 (file)
@@ -172,7 +172,7 @@ void VoteSpam(float notvoters, float mincount, string 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)
        {
@@ -347,7 +347,14 @@ void ReadyRestart_force()
        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
@@ -485,7 +492,7 @@ string ValidateMap(string validated_map, entity caller)
 {
        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;
@@ -696,6 +703,7 @@ void VoteCommand_call(float request, entity caller, float argc, string vote_comm
                        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."); }
index aec1e3256b020878305579b179dfeea42a18e67e..522bb2ffca0dc94174ef97e50321431a9c113e62 100644 (file)
@@ -106,6 +106,7 @@ float       TE_KNIGHTSPIKE                          = 8;
 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;
@@ -139,14 +140,6 @@ float      MSG_ENTITY                              = 5; // csqc
 
 //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;
index 7e4a07b5f6c5565642ecaf7c57f4a0b95bb72a20..1f6d8b23898254c8aa579c682afeaf1fd859afd7 100644 (file)
@@ -39,7 +39,6 @@ float g_pickup_respawntimejitter_powerup;
 float g_jetpack;
 
 float sv_clones;
-float sv_gentle;
 float sv_foginterval;
 
 entity activator;
@@ -58,6 +57,9 @@ float team1_score, team2_score, team3_score, team4_score;
 
 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;
@@ -116,44 +118,6 @@ float maxclients;
 .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;
@@ -245,8 +209,6 @@ float WS_READY                      = 4; // idle frame
 
 void weapon_defaultspawnfunc(float wpn);
 
-string w_deathtypestring;
-
 .vector dest1, dest2;
 
 float gameover;
@@ -292,8 +254,6 @@ float nJoinAllowed(entity ignore);
 
 .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
@@ -316,11 +276,6 @@ float default_weapon_alpha;
 .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;
 
@@ -474,7 +429,7 @@ void GlobalSound(string samplestring, float channel, float voicetype);
 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;
@@ -591,7 +546,13 @@ float client_cefc_accumulatortime;
 .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
 
@@ -625,7 +586,7 @@ string deathmessage;
 #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;
@@ -639,14 +600,7 @@ string deathmessage;
 .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
@@ -659,6 +613,8 @@ float serverflags;
 .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;
diff --git a/qcsrc/server/domination.qc b/qcsrc/server/domination.qc
deleted file mode 100644 (file)
index 0a2fe02..0000000
+++ /dev/null
@@ -1,525 +0,0 @@
-
-/*
-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);
-}
-
index 4d29b014faff68c9528bb954d3d51512e88b6d3e..58e737e58c55fd72de7990f8082d6c334c2727f2 100644 (file)
@@ -115,7 +115,7 @@ void func_breakable_behave_destroyed()
        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();
 }
@@ -240,9 +240,9 @@ void spawnfunc_func_breakable() {
        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;
index d2cc61db3346cb3405ca086e9d025657fd2a4c6f..e86b148bcb0b170851e4ac934ba1917d6a3353c3 100644 (file)
@@ -47,8 +47,6 @@ float checkrules_firstblood;
 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;
@@ -86,15 +84,6 @@ float IsFlying(entity a)
        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);
@@ -227,44 +216,6 @@ void GiveFrags (entity attacker, entity targ, float f, float deathtype)
                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;
@@ -297,7 +248,7 @@ void LogDeath(string mode, float deathtype, entity killer, entity killed)
        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)
@@ -308,225 +259,317 @@ void LogDeath(string mode, float deathtype, entity killer, entity killed)
        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
@@ -538,7 +581,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float
 {
        float mirrordamage;
        float mirrorforce;
-       float teamdamage0;
+       float complainteamdamage = 0; 
        entity attacker_save;
        mirrordamage = 0;
        mirrorforce = 0;
@@ -571,7 +614,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float
                        }
        }
 
-       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
@@ -618,10 +661,10 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float
                                        {
                                                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)
                                                        {
@@ -696,6 +739,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float
                        {
                                damage = 0;
                                mirrordamage = 0;
+                               complainteamdamage = 0;
                                if (targ != attacker)
                                {
                                        if ((targ.health >= 1) && (targ.classname == "player"))
@@ -711,6 +755,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float
                {
                        damage *= g_weapondamagefactor;
                        mirrordamage *= g_weapondamagefactor;
+                       complainteamdamage *= g_weapondamagefactor;
                        force = force * g_weaponforcefactor;
                        mirrorforce *= g_weaponforcefactor;
                }
@@ -792,31 +837,6 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float
                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;
@@ -850,12 +870,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float
                                                        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
@@ -864,7 +879,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float
                                        {
                                                attacker.typehitsound += 1;
                                        }
-                                       if(mirrordamage > 0)
+                                       if(complainteamdamage > 0)
                                                if(time > attacker.teamkill_complain)
                                                {
                                                        attacker.teamkill_complain = time + 5;
index 8867d0725b0f7c3a6cea40d022c5e133a01291dc..f7af47d924036f121a6b8340a8dc2df5a0edaee4 100644 (file)
@@ -79,7 +79,7 @@ void GrapplingHook_Stop()
        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;
index b5f4bcf8441b0f382dd10813e60c1517c80107be..854b7fef24f7466c86a373ec784ed69fea9cc420 100644 (file)
@@ -96,7 +96,7 @@ void spawnfunc_dynlight()
        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)
index b07cae2714e19770ca08d721d26fd0cec4885575..371f9da399ee9988cd7982b9f887239d95dbe1cc 100644 (file)
@@ -1,6 +1,4 @@
-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;
@@ -58,19 +56,6 @@ void updateanim(entity e)
        //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
@@ -280,7 +265,7 @@ void SUB_CalcMove_Bezier (vector tcontrol, vector tdest, float tspeed, void() fu
        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
index d194c94314279ecb9412f342c322fb359780d317..db2c9a45c14d9a5690deb7e13b6dd0cc917b48a9 100644 (file)
@@ -1244,6 +1244,14 @@ float TetrisPostFrame()
 
 #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
index 20ddc655170cfbc483ff0b41fe22ccec1e2c2284..293c78f001f0f3a2df0c050d91102db2b53a4289 100644 (file)
@@ -66,7 +66,7 @@ void SUB_UseTargets()
                if(clienttype(activator) == CLIENTTYPE_REAL)
                {
                        centerprint (activator, self.message);
-                       if (!self.noise)
+                       if (self.noise == "")
                                play2(activator, "misc/talk.wav");
                }
        }
@@ -192,7 +192,7 @@ void multi_trigger()
        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;
        }
 }
 
@@ -254,7 +254,8 @@ void multi_reset()
                self.takedamage = DAMAGE_YES;
                self.solid = SOLID_BBOX;
        }
-       self.think = SUB_Null;
+       self.think = func_null;
+       self.nextthink = 0;
        self.team = self.team_saved;
 }
 
@@ -359,7 +360,8 @@ void delay_use()
 
 void delay_reset()
 {
-       self.think = SUB_Null;
+       self.think = func_null;
+       self.nextthink = 0;
 }
 
 void spawnfunc_trigger_delay()
@@ -506,9 +508,9 @@ void spawnfunc_trigger_hurt()
        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";
 
@@ -1337,9 +1339,9 @@ void spawnfunc_misc_laser()
        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;
index fb211aaeb7a52653402f11d8f9345887d07cf2a2..a07fc32a4fc2d1841410c0c4ca4a0a70bcbe6da1 100644 (file)
@@ -58,7 +58,7 @@ float world_initialized;
 string GetMapname();
 string GetGametype();
 void GotoNextMap(float reinit);
-void ShuffleMaplist()
+void ShuffleMaplist();
 float(float reinit) DoNextMapOverride;
 
 void SetDefaultAlpha()
@@ -340,9 +340,6 @@ void cvar_changes_init()
                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:
@@ -553,6 +550,8 @@ void spawnfunc___init_dedicated_server(void)
        // 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);
@@ -597,9 +596,13 @@ void spawnfunc_worldspawn (void)
                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));
 
@@ -670,9 +673,6 @@ void spawnfunc_worldspawn (void)
 
        WaypointSprite_Init();
 
-       //if (g_domination)
-       //      dom_init();
-
        GameLogInit(); // prepare everything
        // NOTE for matchid:
        // changing the logic generating it is okay. But:
@@ -839,39 +839,42 @@ void spawnfunc_worldspawn (void)
        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"));
 
@@ -894,9 +897,11 @@ void spawnfunc_worldspawn (void)
 
        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());
@@ -952,9 +957,7 @@ void spawnfunc_worldspawn (void)
                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);
 
@@ -1355,10 +1358,10 @@ float mapvote_initialized;
 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)) )
        {
@@ -1606,6 +1609,8 @@ void NextLevel()
        PlayerStats_Shutdown();
        WeaponStats_Shutdown();
 
+       Kill_Notification(NOTIF_ALL, world, MSG_CENTER, 0); // kill all centerprints now
+
        if(autocvar_sv_eventlog)
                GameLogEcho(":gameover");
 
@@ -1621,6 +1626,8 @@ void NextLevel()
        if(autocvar_g_campaign)
                CampaignPreIntermission();
 
+       MUTATOR_CALLHOOK(MatchEnd);
+
        localcmd("\nsv_hook_gameend\n");
 }
 
@@ -1686,20 +1693,8 @@ void InitiateOvertime() // ONLY call this if InitiateSuddenDeath returned true
        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)
@@ -1767,10 +1762,10 @@ float WinningCondition_Onslaught()
        {
                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");
        }
@@ -1778,10 +1773,10 @@ float WinningCondition_Onslaught()
        {
                // 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;
        }
@@ -1819,13 +1814,13 @@ float WinningCondition_Assault()
 
        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;
@@ -1951,10 +1946,10 @@ float WinningCondition_Scores(float limit, float leadlimit)
 
        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();
@@ -2037,7 +2032,6 @@ float WinningCondition_Race(float fraglimit)
                return WINNING_STARTSUDDENDEATHOVERTIME;
        else
                return WINNING_NEVER;
-       return wc;
 }
 
 float WinningCondition_QualifyingThenRace(float limit)
@@ -2071,25 +2065,25 @@ float WinningCondition_RanOutOfSpawns()
 
        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;
        }
 
@@ -2103,20 +2097,20 @@ float WinningCondition_RanOutOfSpawns()
        {
                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);
@@ -2206,9 +2200,9 @@ void CheckRules_World()
                {
                        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
@@ -2357,7 +2351,7 @@ string MapVote_Suggest(string m)
        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))
index 38a1e249d7847a954e20a9df455dd2dfa8289b67..08fd83fe3fab99c12c6a448e5f6198328281523c 100644 (file)
@@ -431,8 +431,12 @@ float Ban_IsClientBanned(entity client, float idx)
                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;
 }
 
index 7b386ec97514ef571a9aa7ab5186e50c1773ee0a..1b423f5020f5646312a3c0b8d7a14380bb073344 100644 (file)
@@ -186,7 +186,7 @@ void spawnfunc_item_key() {
                _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;
@@ -196,18 +196,21 @@ void spawnfunc_item_key() {
        }
        
        // 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
@@ -215,14 +218,14 @@ void spawnfunc_item_key() {
                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
@@ -388,11 +391,11 @@ void spawnfunc_trigger_keylock(void) {
        }
 
        // 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)
@@ -402,11 +405,11 @@ void spawnfunc_trigger_keylock(void) {
        }
        
        // 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
index 20828800deebfdd3d7d0407269179ec0037489a8..2b73841808bed3223c1eef10bef5c06dd384138c 100644 (file)
@@ -32,7 +32,6 @@ void WarpZone_crosshair_trace(entity pl)
 void() spawnfunc_info_player_deathmatch; // needed for the other spawnpoints
 void() spawnpoint_use;
 string GetMapname();
-string ColoredTeamName(float t);
 
 string admin_name(void)
 {
@@ -80,26 +79,27 @@ float DistributeEvenly_GetRandomized(float weight)
 
 #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
@@ -107,15 +107,6 @@ 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;
@@ -428,7 +419,7 @@ string formatmessage(string msg)
                        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'));
@@ -546,7 +537,11 @@ void GetCvars(float f)
 
        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");
@@ -574,10 +569,6 @@ void GetCvars(float f)
        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");
@@ -594,102 +585,6 @@ void GetCvars(float f)
        }
 }
 
-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)
 {
@@ -1107,10 +1002,6 @@ float g_touchexplode_force;
 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)
 {
@@ -1121,6 +1012,8 @@ 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"))
@@ -1166,12 +1059,7 @@ void readlevelcvars(void)
     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)
@@ -1265,10 +1153,6 @@ void readlevelcvars(void)
        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();
 }
 
@@ -1599,9 +1483,6 @@ void precache()
     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");
@@ -1657,34 +1538,6 @@ void precache()
 #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()
@@ -1824,7 +1677,7 @@ void InitializeEntitiesRun()
             self = e_old;
         }
         //dprint("Delayed initialization: ", self.classname, "\n");
-        if(func != func_null)
+        if(func)
             func();
         else
         {
@@ -1838,7 +1691,6 @@ void InitializeEntitiesRun()
 
 .float uncustomizeentityforclient_set;
 .void(void) uncustomizeentityforclient;
-void(void) SUB_Nullpointer = #0;
 void UncustomizeEntitiesRun()
 {
     entity oldself;
@@ -1851,7 +1703,7 @@ void SetCustomizer(entity e, float(void) customizer, void(void) uncustomizer)
 {
     e.customizeentityforclient = customizer;
     e.uncustomizeentityforclient = uncustomizer;
-    e.uncustomizeentityforclient_set = (uncustomizer != SUB_Nullpointer);
+    e.uncustomizeentityforclient_set = !!uncustomizer;
 }
 
 .float nottargeted;
@@ -2164,22 +2016,6 @@ string race_readName(string map, float pos)
        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;
@@ -2410,8 +2246,8 @@ vector shotorg_adjust_values(vector vecs, float y_is_right, float visual, float
        {
                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
                {
@@ -2529,43 +2365,6 @@ vector gettaginfo_relative(entity e, float tag)
     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)
index 9be5745cb5e4ec24afbde80bee85c4e58bf94097..f4761b884dca28175d58da08589a777c589722c2 100644 (file)
@@ -101,7 +101,7 @@ float Mutator_Add(mutatorfunc_t func, string name)
        {
                if(name == loaded_mutators[i])
                        return 1; // already added
-               if(!loaded_mutators[i])
+               if not(loaded_mutators[i])
                        j = i;
        }
        if(j < 0)
@@ -116,8 +116,14 @@ float Mutator_Add(mutatorfunc_t func, string name)
                // 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)
index 29a8e4e0b5602d9fa0f645a2b5de7a1e4bb437d0..d90d564b501447acb3e3ef1def71530be1a521ee 100644 (file)
@@ -6,7 +6,7 @@
 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)
@@ -18,6 +18,7 @@ float CallbackChain_Call(entity cb);
 
 #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
@@ -27,9 +28,10 @@ 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)
@@ -205,6 +207,12 @@ MUTATOR_HOOKABLE(SV_StartFrame);
 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
index f453cc22ad727ea81b78f276ff3958aed207bde2..8f0bc931efd540c587ea0f1ea5f3371fb04bdd0d 100644 (file)
@@ -20,36 +20,45 @@ void ctf_EventLog(string mode, float flagteam, entity actor) // use an alias for
                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)
@@ -165,11 +174,7 @@ void ctf_CaptureShield_Update(entity player, float wanted_status)
        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;
        }
 }
@@ -191,7 +196,7 @@ void ctf_CaptureShield_Touch()
        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)
@@ -234,7 +239,7 @@ void ctf_Handle_Drop(entity flag, entity player, float droptype)
        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);
 
@@ -287,11 +292,11 @@ void ctf_Handle_Retrieve(entity flag, entity 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
@@ -404,7 +409,8 @@ void ctf_Handle_Capture(entity flag, entity toucher, float capturetype)
        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)
@@ -445,8 +451,8 @@ void ctf_Handle_Capture(entity flag, entity toucher, float 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);
 
@@ -471,7 +477,6 @@ void ctf_Handle_Pickup(entity flag, entity player, float pickuptype)
 {
        // 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
@@ -495,21 +500,30 @@ void ctf_Handle_Pickup(entity flag, entity player, float pickuptype)
        }
 
        // 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
@@ -568,14 +582,14 @@ void ctf_CheckFlagReturn(entity flag, float returntype)
                {
                        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);
@@ -587,10 +601,10 @@ void ctf_CheckFlagReturn(entity flag, float returntype)
 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)
@@ -604,8 +618,8 @@ void ctf_CheckStalemate(void)
                        
                        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;
                        }
                }
        }
@@ -629,10 +643,7 @@ void ctf_CheckStalemate(void)
                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;
                }
@@ -931,7 +942,7 @@ void ctf_DelayedFlagSetup(void) // called after a flag is placed on a map by ctf
        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
@@ -948,10 +959,10 @@ void ctf_FlagSetup(float teamnumber, entity flag) // called when spawning a flag
        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?
@@ -1762,6 +1773,7 @@ MUTATOR_HOOKFUNCTION(ctf_PlayerDamage) // for changing damage and force values t
                        frag_target.wps_helpme_time = time;
                        WaypointSprite_HelpMePing(frag_target.wps_flagcarrier);
                }
+               // todo: add notification for when flag carrier needs help?
        }
        return FALSE;
 }
@@ -1823,7 +1835,7 @@ MUTATOR_HOOKFUNCTION(ctf_PlayerUseKey)
                // 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
@@ -1842,13 +1854,13 @@ MUTATOR_HOOKFUNCTION(ctf_PlayerUseKey)
                                                { 
                                                        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; 
@@ -1885,7 +1897,7 @@ MUTATOR_HOOKFUNCTION(ctf_PlayerUseKey)
                                }
                                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;
                                }
                        }
@@ -1960,8 +1972,8 @@ MUTATOR_HOOKFUNCTION(ctf_AbortSpeedrun)
 {
        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;
        }
        
@@ -1985,7 +1997,7 @@ MUTATOR_HOOKFUNCTION(ctf_MatchEnd)
                                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;
                        }
                        
@@ -2008,6 +2020,14 @@ MUTATOR_HOOKFUNCTION(ctf_BotRoles)
        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
@@ -2020,7 +2040,7 @@ void spawnfunc_info_player_team1()
 {
        if(g_assault) { remove(self); return; }
        
-       self.team = COLOR_TEAM1; // red
+       self.team = NUM_TEAM_1; // red
        spawnfunc_info_player_deathmatch();
 }
 
@@ -2032,7 +2052,7 @@ void spawnfunc_info_player_team2()
 {
        if(g_assault) { remove(self); return; }
        
-       self.team = COLOR_TEAM2; // blue
+       self.team = NUM_TEAM_2; // blue
        spawnfunc_info_player_deathmatch();
 }
 
@@ -2043,7 +2063,7 @@ void spawnfunc_info_player_team3()
 {
        if(g_assault) { remove(self); return; }
        
-       self.team = COLOR_TEAM3; // yellow
+       self.team = NUM_TEAM_3; // yellow
        spawnfunc_info_player_deathmatch();
 }
 
@@ -2055,7 +2075,7 @@ void spawnfunc_info_player_team4()
 {
        if(g_assault) { remove(self); return; }
        
-       self.team = COLOR_TEAM4; // purple
+       self.team = NUM_TEAM_4; // purple
        spawnfunc_info_player_deathmatch();
 }
 
@@ -2157,8 +2177,8 @@ void ctf_DelayedInit() // Do this check with a delay so we can wait for teams to
        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();
@@ -2192,19 +2212,26 @@ MUTATOR_DEFINITION(gamemode_ctf)
        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;
index b6ca033bb3284d34b0e57847e022b21d3a1ea223..882b1064b49de78ce2d1c7dfcda641b4601839c5 100644 (file)
@@ -1,7 +1,8 @@
 // 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
@@ -130,3 +131,13 @@ vector havocbot_ctf_middlepoint;
 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;
diff --git a/qcsrc/server/mutators/gamemode_domination.qc b/qcsrc/server/mutators/gamemode_domination.qc
new file mode 100644 (file)
index 0000000..051eaa3
--- /dev/null
@@ -0,0 +1,502 @@
+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;
+}
diff --git a/qcsrc/server/mutators/gamemode_domination.qh b/qcsrc/server/mutators/gamemode_domination.qh
new file mode 100644 (file)
index 0000000..a7d1853
--- /dev/null
@@ -0,0 +1,23 @@
+// 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
index aedfd6364c942ef5f1d967b38d0dac04fa8d202f..c43a398754c34b0e513e60f189423e2a12f78406 100644 (file)
@@ -22,7 +22,6 @@ void freezetag_CheckWinner()
                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)
@@ -36,18 +35,8 @@ void freezetag_CheckWinner()
 
        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);
        }
 
@@ -242,13 +231,13 @@ MUTATOR_HOOKFUNCTION(freezetag_RemovePlayer)
 {
        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;
        }
@@ -265,13 +254,13 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerDies)
 {
        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;
 
@@ -281,16 +270,16 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerDies)
        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
@@ -312,7 +301,7 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerSpawn)
        }
        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);
        }
 
@@ -376,15 +365,9 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerPreThink)
                                }
                        }
 
-                       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
@@ -476,9 +459,17 @@ MUTATOR_DEFINITION(gamemode_freezetag)
                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;
index 07c96671c67e28b0eddc529b6e83bb58aa79d369..7a16cd62b2716f62d0115916ff4a3f09cee06350 100644 (file)
@@ -89,7 +89,7 @@ void ka_TouchEvent() // runs any time that the ball comes in contact with someth
        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;
@@ -101,9 +101,8 @@ void ka_TouchEvent() // runs any time that the ball comes in contact with someth
        
        // 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
@@ -144,9 +143,8 @@ void ka_DropEvent(entity plyr) // runs any time that a player is supposed to los
 
        // 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
@@ -254,7 +252,7 @@ MUTATOR_HOOKFUNCTION(ka_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);
@@ -426,9 +424,17 @@ MUTATOR_DEFINITION(gamemode_keepaway)
                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;
index 58d732d7f70b926c6cb13c6f93aa0f9a5807f48e..97d2dcd47936d8706973f5d495cab87ea6e88adc 100644 (file)
@@ -20,7 +20,6 @@ vector KH_KEY_MIN = '-10 -10 -46';
 vector KH_KEY_MAX = '10 10 3';
 float KH_KEY_BRIGHTNESS = 2;
 
-string kh_Controller_Waitmsg;
 float kh_no_radar_circles;
 
 // kh_state
@@ -40,10 +39,10 @@ float kh_keystatus[17];
 
 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;
 }
 
@@ -122,50 +121,20 @@ void kh_update_state()
 
 
 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;
@@ -361,13 +330,13 @@ void kh_Key_AssignTo(entity key, entity player)  // runs every time a key is pic
                        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);
@@ -436,7 +405,7 @@ void kh_Key_Collect(entity key, entity player)  //a player picks up a dropped ke
                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
 }
@@ -510,10 +479,11 @@ void kh_FinishRound()  // runs when a team captures the keys
                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;
@@ -533,15 +503,17 @@ void kh_WinnerTeam(float teem)  // runs when a team wins
        }
 
        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';
@@ -567,7 +539,7 @@ void kh_WinnerTeam(float teem)  // runs when a team wins
                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();
@@ -595,8 +567,7 @@ void kh_LoserTeam(float teem, entity lostkey)  // runs when a player pushes a fl
                        // 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
        {
@@ -655,9 +626,10 @@ void kh_LoserTeam(float teem, entity lostkey)  // runs when a player pushes a fl
 
                        --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);
 
@@ -711,11 +683,11 @@ void kh_Key_Think()  // runs all the time
                {
                        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_));
                }
        }
 
@@ -748,21 +720,21 @@ void kh_Key_Spawn(entity initial_owner, float angle, float i)  // runs every tim
        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:
@@ -774,7 +746,7 @@ void kh_Key_Spawn(entity initial_owner, float angle, float i)  // runs every tim
        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;
@@ -817,7 +789,8 @@ void kh_Key_DropOne(entity key)
 
        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);
@@ -842,7 +815,7 @@ void kh_Key_DropAll(entity player, float suicide) // runs whenever a player dies
                {
                        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);
@@ -855,83 +828,74 @@ void kh_Key_DropAll(entity player, float suicide) // runs whenever a player dies
        }
 }
 
-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)
        {
@@ -951,7 +915,8 @@ void kh_StartRound()  // runs at the start of each round
        }
 
        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
@@ -1003,7 +968,7 @@ void kh_Initialize()  // sets up th KH environment
        // 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;
@@ -1111,9 +1076,17 @@ MUTATOR_DEFINITION(gamemode_keyhunt)
                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;
index 8ee8434293669b00a15501c92612f7c1d3eedf51..bda701f96a015dafd8440f35df82b22ae032e147 100644 (file)
@@ -9,4 +9,4 @@ float kh_Key_AllOwnedByWhichTeam();
 // 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);
index 808d1a29b35229d56931b9645642a524d95e833b..8790162afa9804ed508c48bcecb4241930ad5319 100644 (file)
@@ -49,7 +49,7 @@ void nexball_setstatus(void)
        {
                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');
@@ -124,7 +124,7 @@ void GiveBall(entity plyr, entity ball)
 
        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.
 
@@ -204,8 +204,9 @@ void ResetBall(void)
        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)
@@ -341,9 +342,9 @@ void GoalTouch(void)
        {
                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)
@@ -358,7 +359,7 @@ void GoalTouch(void)
        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;
        }
 
@@ -387,7 +388,7 @@ void GoalTouch(void)
        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);
 }
 
@@ -424,28 +425,28 @@ void nb_spawnteams(void)
        {
                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)  ;
@@ -575,22 +576,22 @@ void SpawnGoal(void)
 
 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();
 }
 
@@ -668,7 +669,7 @@ void W_Nexball_Touch(void)
 {
        entity ball, attacker;
        attacker = self.owner;
-       //self.think = SUB_Null;
+       //self.think = func_null;
        //self.enemy = world;
        
        PROJECTILE_TOUCH;
@@ -773,14 +774,13 @@ void W_Nexball_Attack2(void)
        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;
        }               
        
@@ -844,14 +844,8 @@ float w_nexball_weapon(float req)
                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;
@@ -980,5 +974,18 @@ MUTATOR_DEFINITION(gamemode_nexball)
                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;
 }
index 060447c39eb7d04ec06d80564a12ec4aca752971..3801de302d9c80fa2ab8cb0e7e3215d01dbf0ff4 100644 (file)
@@ -1,8 +1,8 @@
 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);
@@ -22,8 +22,6 @@ void onslaught_link_checkupdate();
 .float lastshielded;
 .float lastcaptured;
 
-.string model1, model2, model3;
-
 entity ons_red_generator;
 entity ons_blue_generator;
 
@@ -163,16 +161,16 @@ void onslaught_updatelinks()
                        }
                        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;
                        }
                }
@@ -185,16 +183,16 @@ void onslaught_updatelinks()
                        }
                        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;
                        }
                }
@@ -254,10 +252,10 @@ void onslaught_updatelinks()
        {
                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;
@@ -271,14 +269,14 @@ void onslaught_updatelinks()
 
 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;
@@ -354,7 +352,7 @@ float onslaught_controlpoint_attackable(entity cp, float t)
                // 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;
@@ -371,7 +369,7 @@ float onslaught_controlpoint_attackable(entity cp, float t)
                // 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
@@ -419,19 +417,19 @@ void onslaught_generator_think()
                }
                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?
-                }                                  
-            }                                              
-        }    
+                }
+            }
+        }
        }
 }
 
@@ -596,7 +594,7 @@ void onslaught_generator_damage(entity inflictor, entity attacker, float damage,
                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");
                }
        }
@@ -612,25 +610,25 @@ void onslaught_generator_damage(entity inflictor, entity attacker, float damage,
                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
@@ -706,16 +704,16 @@ string onslaught_generator_waypointsprite_for_team(entity e, float t)
 {
        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 "";
 }
@@ -723,8 +721,8 @@ string onslaught_generator_waypointsprite_for_team(entity e, float t)
 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);
 
@@ -734,14 +732,14 @@ void onslaught_generator_updatesprite(entity e)
                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');
@@ -758,25 +756,25 @@ string onslaught_controlpoint_waypointsprite_for_team(entity e, float t)
                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
@@ -784,9 +782,9 @@ string onslaught_controlpoint_waypointsprite_for_team(entity e, float t)
        }
        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";
@@ -797,13 +795,13 @@ string onslaught_controlpoint_waypointsprite_for_team(entity e, float t)
 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)
        {
@@ -821,14 +819,14 @@ void onslaught_controlpoint_updatesprite(entity e)
                }
                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');
@@ -856,8 +854,11 @@ void onslaught_generator_reset()
        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);
@@ -910,10 +911,10 @@ void spawnfunc_onslaught_generator()
        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;
@@ -948,7 +949,7 @@ void spawnfunc_onslaught_generator()
        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);
 
@@ -988,7 +989,7 @@ void onslaught_controlpoint_icon_damage(entity inflictor, entity attacker, float
        if (attacker.classname == "player")
        {
                nag = FALSE;
-               if(self.team == COLOR_TEAM1)
+               if(self.team == NUM_TEAM_1)
                {
                        if(time - ons_notification_time_team1 > 10)
                        {
@@ -996,7 +997,7 @@ void onslaught_controlpoint_icon_damage(entity inflictor, entity attacker, float
                                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)
                        {
@@ -1035,8 +1036,8 @@ void onslaught_controlpoint_icon_damage(entity inflictor, entity attacker, float
                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);
@@ -1076,11 +1077,11 @@ void onslaught_controlpoint_icon_think()
 {
        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;
         
@@ -1089,7 +1090,7 @@ void onslaught_controlpoint_icon_think()
             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;
@@ -1099,9 +1100,9 @@ void onslaught_controlpoint_icon_think()
             }
         }
 
-        _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)
         {
@@ -1109,7 +1110,7 @@ void onslaught_controlpoint_icon_think()
             return;
         }
     }
-    
+
        if (time > self.pain_finished + 5)
        {
                if(self.health < self.max_health)
@@ -1234,7 +1235,7 @@ void onslaught_controlpoint_icon_buildthink()
                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);
@@ -1315,8 +1316,8 @@ void onslaught_controlpoint_reset()
        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');
 
@@ -1338,49 +1339,6 @@ keys:
 "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()
 {
@@ -1407,20 +1365,23 @@ 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";
@@ -1428,7 +1389,7 @@ void spawnfunc_onslaught_controlpoint()
        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');
 
@@ -1438,10 +1399,10 @@ void spawnfunc_onslaught_controlpoint()
        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;
 }
 
@@ -1476,28 +1437,28 @@ void onslaught_link_checkupdate()
        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;
 
@@ -1557,7 +1518,7 @@ MUTATOR_HOOKFUNCTION(ons_BuildMutatorsString)
 
 MUTATOR_HOOKFUNCTION(ons_BuildMutatorsPrettyString)
 {
-       ret_string = strcat(ret_string, ", Onslught");
+       ret_string = strcat(ret_string, ", Onslaught");
        return 0;
 }
 
@@ -1569,10 +1530,10 @@ MUTATOR_HOOKFUNCTION(ons_Spawn_Score)
     
        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"):
@@ -1606,12 +1567,12 @@ MUTATOR_HOOKFUNCTION(ons_PlayerSpawn)
         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;
@@ -1619,7 +1580,7 @@ MUTATOR_HOOKFUNCTION(ons_PlayerSpawn)
             _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;
@@ -1664,7 +1625,7 @@ MUTATOR_HOOKFUNCTION(ons_PlayerSpawn)
         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)
         {
@@ -1685,18 +1646,21 @@ MUTATOR_HOOKFUNCTION(ons_PlayerSpawn)
 
 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;
index bdd39b1283f487fe0e74ab42135b6d66f4b180c7..1d6dd911eb7f958fad79b957c120e06575433530 100644 (file)
 // 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;
@@ -117,7 +102,7 @@ MUTATOR_HOOKFUNCTION(dodging_PlayerPhysics) {
                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;
        }
@@ -283,14 +268,17 @@ MUTATOR_DEFINITION(mutator_dodging)
        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;
 }
index cc4f94324b8273fadf9fbc113c4dc286c6b8066b..6ee3e87b3c193e52354dd4e9e40301a8b6a756fc 100644 (file)
@@ -208,9 +208,19 @@ MUTATOR_DEFINITION(mutator_new_toys)
                        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;
index dad19e4a3748f468c93db674b6b2e9c7e7e43a2c..d5f95bd3039465f4df277b7ec389f6909a37c549 100644 (file)
@@ -96,7 +96,7 @@ void NIX_GiveCurrentWeapon()
                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);
 
@@ -118,7 +118,7 @@ void NIX_GiveCurrentWeapon()
        {
                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)
@@ -247,6 +247,11 @@ MUTATOR_DEFINITION(mutator_nix)
                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!
diff --git a/qcsrc/server/mutators/mutator_physical_items.qc b/qcsrc/server/mutators/mutator_physical_items.qc
new file mode 100644 (file)
index 0000000..74b7db2
--- /dev/null
@@ -0,0 +1,127 @@
+.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;
+}
index 8b6bf05a204a9f0ebe3f8ee682ffea5c9af1a782..a351f937c7c73df9d078bcf2fe0c4febb137cd79 100644 (file)
@@ -169,7 +169,7 @@ MUTATOR_HOOKFUNCTION(superspec_SV_ParseClientCommand)
                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);
@@ -190,7 +190,7 @@ MUTATOR_HOOKFUNCTION(superspec_SV_ParseClientCommand)
                        }
                        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));
@@ -217,11 +217,10 @@ MUTATOR_HOOKFUNCTION(superspec_SV_ParseClientCommand)
 
                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");
@@ -260,6 +259,7 @@ MUTATOR_HOOKFUNCTION(superspec_SV_ParseClientCommand)
                }
 
 
+               _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");
@@ -278,8 +278,7 @@ MUTATOR_HOOKFUNCTION(superspec_SV_ParseClientCommand)
                {
                        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");
@@ -293,7 +292,7 @@ MUTATOR_HOOKFUNCTION(superspec_SV_ParseClientCommand)
                                return TRUE;
                        }
 
-                       float i, _bits, _start = 1;
+                       float i, _bits = 0, _start = 1;
                        if(argv(1) == "clear")
                        {
                                self.autospec_flags = 0;
@@ -329,6 +328,7 @@ MUTATOR_HOOKFUNCTION(superspec_SV_ParseClientCommand)
                        }
                }
 
+               _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");
@@ -387,14 +387,14 @@ MUTATOR_HOOKFUNCTION(superspec_SV_ParseClientCommand)
                        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)
@@ -518,13 +518,5 @@ MUTATOR_DEFINITION(mutator_superspec)
        //MUTATOR_HOOK(MakePlayerObserver, superspec_MakePlayerObserver, CBC_ORDER_ANY);
        MUTATOR_HOOK(ClientDisconnect, superspec_ClientDisconnect, CBC_ORDER_ANY);
 
-       MUTATOR_ONADD
-       {
-       }
-
-       MUTATOR_ONREMOVE
-       {
-       }
-
        return 0;
 }
index 7e253ddf9dafbe3f50f3d247890e8573edb841bf..40a925b3ce835fbc24c9b64f424d9022690dd0bc 100644 (file)
@@ -10,7 +10,7 @@ MUTATOR_HOOKFUNCTION(vampire_PlayerDamage)
        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;
 }
index 2ac6094d339d578d174da5ec3ed06eed91fcad20..4bdcbb28234834629ecc13f8f52767fcd1e4ce90 100644 (file)
@@ -4,6 +4,7 @@ MUTATOR_DECLARATION(gamemode_keepaway);
 MUTATOR_DECLARATION(gamemode_ctf);
 MUTATOR_DECLARATION(gamemode_nexball);
 MUTATOR_DECLARATION(gamemode_onslaught);
+MUTATOR_DECLARATION(gamemode_domination);
 
 MUTATOR_DECLARATION(mutator_dodging);
 MUTATOR_DECLARATION(mutator_invincibleprojectiles);
@@ -11,6 +12,7 @@ MUTATOR_DECLARATION(mutator_new_toys);
 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);
 
index d7fec13264e5cc70bdfa10e02a21570d0b1d7c50..391e317423dffd4dd37e628effe9a988b452267f 100644 (file)
@@ -283,7 +283,7 @@ entity sandbox_ObjectPort_Load(string s, float database)
 {
        // 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, "; ");
@@ -294,7 +294,7 @@ entity sandbox_ObjectPort_Load(string s, float database)
        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);
@@ -817,6 +817,16 @@ MUTATOR_DEFINITION(sandbox)
                        sandbox_Database_Load();
        }
 
+       MUTATOR_ONROLLBACK_OR_REMOVE
+       {
+               // nothing to roll back
+       }
+
+       MUTATOR_ONREMOVE
+       {
+               // nothing to remove
+       }
+
        return FALSE;
 }
 
index ce4c2b4b8d74a40c13455b05d9020f05473e7cfc..3cb4ca750ee15f971eb5a9a59b772b0c9445d83a 100644 (file)
@@ -214,7 +214,7 @@ float edge_show(vector point,float fsize)
 #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;
 
@@ -248,7 +248,7 @@ vector pathlib_wateroutnode(vector start,vector end)
     return end;
 }
 
-vector pathlib_swimnode(vector start,vector end)
+vector pathlib_swimnode(vector start,vector end,float doedge)
 {
     pathlib_movenode_goodnode = 0;
 
index 9658747eeb7122f393d3cde584c63544b35593db..fd889d04320df9db5e8753a9982db51a92a0d76f 100644 (file)
@@ -58,7 +58,7 @@ entity pathlib_mknode(vector where,entity parent)
 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;
index 9369fb4d69f2a179ff47ac74c8677e49349a1449..c45ac0dee4bb266fc1f36552037dffc94b625198 100644 (file)
@@ -1,4 +1,4 @@
-vector pathlib_wateroutnode(vector start,vector end)
+vector pathlib_wateroutnode(vector start,vector end, float doedge)
 {
     vector surface;
 
@@ -32,7 +32,7 @@ vector pathlib_wateroutnode(vector start,vector end)
     return end;
 }
 
-vector pathlib_swimnode(vector start,vector end)
+vector pathlib_swimnode(vector start,vector end, float doedge)
 {
     pathlib_movenode_goodnode = 0;
 
@@ -43,7 +43,7 @@ vector pathlib_swimnode(vector start,vector end)
     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)
@@ -52,7 +52,7 @@ vector pathlib_swimnode(vector start,vector end)
     return end;
 }
 
-vector pathlib_flynode(vector start,vector end)
+vector pathlib_flynode(vector start,vector end, float doedge)
 {
     pathlib_movenode_goodnode = 0;
 
index 71d13caa4e084660b568389f7f96031e54bfafc1..d1b6667d715f4a6075f992f999ceb846a608e339 100644 (file)
@@ -75,9 +75,9 @@ vector movenode_boxmax;
 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);
 
index 4608b56df10f1330011e64e358e7c155035a42ef..c01a25bbdc8228807ab8602cbd83b8aeaa2dfbb8 100644 (file)
@@ -25,6 +25,7 @@ void PlayerStats_Init() // initiated before InitGameplayMode so that scores are
        PlayerStats_AddEvent(PLAYERSTATS_MATCHES);
        PlayerStats_AddEvent(PLAYERSTATS_JOINS);
        PlayerStats_AddEvent(PLAYERSTATS_SCOREBOARD_VALID);
+       PlayerStats_AddEvent(PLAYERSTATS_SCOREBOARD_POS);
        PlayerStats_AddEvent(PLAYERSTATS_RANK);
 
     // accuracy stats
@@ -70,7 +71,7 @@ void PlayerStats_AddPlayer(entity e)
        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);
@@ -144,10 +145,10 @@ void PlayerStats_AddEvent(string event_id)
        }
 }
 
-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;
@@ -155,6 +156,7 @@ void PlayerStats_Event(entity e, string event_id, float value)
        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?
@@ -210,22 +212,7 @@ void PlayerStats_TeamScore(float t, string event_id, float value) // TODO: doesn
                        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)
@@ -238,9 +225,9 @@ 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()));
@@ -353,7 +340,7 @@ void PlayerStats_AddGlobalInfo(entity p)
 {
        if(playerstats_db < 0)
                return;
-       if(!p.playerstats_id || playerstats_db < 0)
+       if((p.playerstats_id == "") || playerstats_db < 0)
                return;
        p.playerstats_addedglobalinfo = TRUE;
 
@@ -365,11 +352,11 @@ void PlayerStats_AddGlobalInfo(entity p)
        }
 
        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)
@@ -377,31 +364,47 @@ void PlayerStats_AddGlobalInfo(entity p)
 
        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);
                }
        }
 }
index 11a311028d9d13c70ffdbeb32999c852d5cc1183..445d6f31cc66028fe2e318e66363dc8f6fa23f96 100644 (file)
@@ -6,6 +6,7 @@ string PLAYERSTATS_MATCHES = "matches";
 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-";
@@ -37,7 +38,7 @@ void PlayerStats_AddTeam(float t);
 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);
index 75dae14bf5f28d666e9beb91e820e912389a1a54..3e83c972eece82f015fafae1804b1e6db6a0ddda 100644 (file)
@@ -309,8 +309,8 @@ void Portal_MakeBrokenPortal(entity portal)
 {
        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;
@@ -320,8 +320,8 @@ void Portal_MakeWaitingPortal(entity portal)
 {
        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;
@@ -342,8 +342,8 @@ void Portal_MakeOutPortal(entity portal)
 {
        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;
index 028519372f025ae24aa923d472ba0a6593de86b7..a00fd32c5e6f0e47a4865434dadee0ce79556034 100644 (file)
@@ -13,7 +13,9 @@ sys-post.qh
 ../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
@@ -22,14 +24,19 @@ sys-post.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 
@@ -141,7 +148,7 @@ t_plats.qc
 antilag.qc
 
 //ctf.qc
-domination.qc
+//domination.qc
 //mode_onslaught.qc
 //nexball.qc
 g_hook.qc
@@ -208,6 +215,7 @@ playerstats.qc
 
 mutators/base.qc
 mutators/gamemode_ctf.qc
+mutators/gamemode_domination.qc
 mutators/gamemode_freezetag.qc
 mutators/gamemode_keyhunt.qc
 mutators/gamemode_keepaway.qc
@@ -220,6 +228,7 @@ mutators/mutator_dodging.qc
 mutators/mutator_rocketflying.qc
 mutators/mutator_vampire.qc
 mutators/mutator_spawn_near_teammate.qc
+mutators/mutator_physical_items.qc
 mutators/sandbox.qc
 mutators/mutator_superspec.qc
 
@@ -229,6 +238,8 @@ 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
index c7c38165dd9845225420660ddede82ae65de8dd5..6ec8a68e4935cbd9ce7f6ee35e68b90f1f8eb401 100644 (file)
@@ -149,20 +149,17 @@ void race_setTime(string map, float t, string myuid, string mynetname, entity e)
        }
 
        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;
        }
 
@@ -171,7 +168,7 @@ void race_setTime(string map, float t, string myuid, string mynetname, entity e)
        // 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;
        }
 
@@ -190,34 +187,24 @@ void race_setTime(string map, float t, string myuid, string mynetname, entity e)
        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"
        }
 }
 
@@ -273,6 +260,10 @@ void race_SendTime(entity e, float cp, float t, float tvalid)
                }
                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);
@@ -286,7 +277,7 @@ void race_SendTime(entity e, float cp, float t, float tvalid)
                        {
                                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);
                        }
                }
@@ -817,11 +808,11 @@ void spawnfunc_trigger_race_checkpoint()
        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;
@@ -870,11 +861,11 @@ void spawnfunc_target_checkpoint() // defrag entity
        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")
@@ -903,7 +894,7 @@ void race_AbandonRaceCheck(entity p)
        {
                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);
        }
 }
@@ -1026,7 +1017,7 @@ void race_ReadyRestart()
        Score_NicePrint(world);
 
        race_ClearRecords();
-       PlayerScore_Sort(race_place);
+       PlayerScore_Sort(race_place, 0, 1, 0);
 
        entity e;
        FOR_EACH_CLIENT(e)
@@ -1102,7 +1093,7 @@ void spawnfunc_trigger_race_penalty()
        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;
index 239afb04a81c4d72702fa840078e50dc1928c29f..ba8f648c888b33e0e312cdf8774b3e1cd0169cad 100644 (file)
@@ -165,7 +165,7 @@ void rune_respawn();
 void RuneCarriedThink()
 {
        float rcount, rnum;
-       vector ang;
+       vector ang = '0 0 0';
        entity rune;
 
        if(self.owner.classname != "player" || time < game_starttime)
@@ -219,11 +219,11 @@ void rune_touch()
 
        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);
@@ -344,14 +344,14 @@ void DropAllRunes(entity pl)
        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)
index 102dd6a33ef326af860bdd8d66c0ba537f5f8a89..eb305e72203d48462e505a7a9261622660a5f2f1 100644 (file)
@@ -10,9 +10,9 @@ var .float teamscores_primary;
 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;
@@ -123,7 +123,7 @@ float TeamScore_Add(entity player, float scorefield, float score)
        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;
 
@@ -133,8 +133,12 @@ float TeamScore_Compare(entity t1, entity t2)
        {
                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;
 }
 
@@ -200,13 +204,13 @@ void ScoreInfo_Init(float teams)
                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");
 }
 
 /*
@@ -244,18 +248,18 @@ float PlayerScore_SendEntity(entity to, float sendflags)
        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)
@@ -265,6 +269,8 @@ void PlayerScore_Clear(entity player)
                                sk.SendFlags |= pow(2, i);
                sk.(scores[i]) = 0;
        }
+
+       return 1;
 }
 
 void Score_ClearAll()
@@ -352,7 +358,7 @@ float PlayerTeamScore_Add(entity player, float pscorefield, float tscorefield, f
        return r;
 }
 
-float PlayerScore_Compare(entity t1, entity t2)
+float PlayerScore_Compare(entity t1, entity t2, float strict)
 {
        if(!t1 || !t2) return (!t2) - !t1;
 
@@ -362,8 +368,12 @@ float PlayerScore_Compare(entity t1, entity t2)
        {
                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;
 }
 
@@ -409,7 +419,7 @@ void WinningConditionHelper()
                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;
@@ -419,7 +429,7 @@ void WinningConditionHelper()
                        }
                        else
                        {
-                               c = TeamScore_Compare(secondscorekeeper, sk);
+                               c = TeamScore_Compare(secondscorekeeper, sk, 1);
                                if(c < 0)
                                {
                                        WinningConditionHelper_secondteam = t + 1;
@@ -428,7 +438,7 @@ void WinningConditionHelper()
                        }
                }
 
-               WinningConditionHelper_equality = (TeamScore_Compare(winnerscorekeeper, secondscorekeeper) == 0);
+               WinningConditionHelper_equality = (TeamScore_Compare(winnerscorekeeper, secondscorekeeper, 0) == 0);
                if(WinningConditionHelper_equality)
                        WinningConditionHelper_winnerteam = WinningConditionHelper_secondteam = -1;
 
@@ -449,7 +459,7 @@ void WinningConditionHelper()
                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;
@@ -459,7 +469,7 @@ void WinningConditionHelper()
                        }
                        else
                        {
-                               c = PlayerScore_Compare(secondscorekeeper, sk);
+                               c = PlayerScore_Compare(secondscorekeeper, sk, 1);
                                if(c < 0)
                                {
                                        WinningConditionHelper_second = p;
@@ -468,7 +478,7 @@ void WinningConditionHelper()
                        }
                }
 
-               WinningConditionHelper_equality = (PlayerScore_Compare(winnerscorekeeper, secondscorekeeper) == 0);
+               WinningConditionHelper_equality = (PlayerScore_Compare(winnerscorekeeper, secondscorekeeper, 0) == 0);
                if(WinningConditionHelper_equality)
                        WinningConditionHelper_winner = WinningConditionHelper_second = world;
 
@@ -657,36 +667,42 @@ string GetTeamScoreString(float tm, float shortString)
        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;
        }
@@ -694,14 +710,14 @@ entity PlayerScore_Sort(.float field)
        
        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;
@@ -715,7 +731,11 @@ entity PlayerScore_Sort(.float field)
                        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;
@@ -775,7 +795,7 @@ void Score_NicePrint_Team(entity to, float t, float w)
        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] != "")
                        {
@@ -857,7 +877,7 @@ void Score_NicePrint(entity to)
                        ++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)
index 3ac0b03b5577dd49cf5dbb5eea7e1ad7e2fd02e6..5960b9f427fc3a459550dd0585fd8eacee686134 100644 (file)
@@ -25,8 +25,9 @@ float PlayerScore_Add(entity player, float scorefield, float score);
  * 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.
@@ -117,5 +118,8 @@ string GetTeamScoreString(float tm, float shortString);
  * 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);
index c4021fc397ea3d2cf28c67e004bb9afdde68e1aa..13fd49f29bf58e72a57ca3514b2f19103fc0d0bf 100644 (file)
@@ -44,26 +44,6 @@ void ScoreRules_generic()
        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
@@ -99,9 +79,8 @@ void ScoreRules_kh(float teams)
 // 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);
@@ -110,7 +89,7 @@ void ScoreRules_race()
                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)
        {
@@ -118,9 +97,9 @@ void ScoreRules_race()
        }
        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();
 }
index 2694cb3d6f536ac506b49b4b05f0b07ee9a75389..54d60a14b6ee5b20ad5b3ed5549896d6aae6029a 100644 (file)
@@ -71,6 +71,6 @@ void spawnfunc_trigger_secret() {
        // 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;
 }
 
index 63d91f6070ca3ecee2ecb56527f7a0c6710c9a98..c91c1ac1895ecae9d49667175258f3b91b9f9486 100644 (file)
@@ -43,7 +43,18 @@ void CreatureFrame (void)
                        {
                                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)
                                        {
@@ -64,10 +75,6 @@ void CreatureFrame (void)
                                                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
index bc8638dd2f123fa2830fc90ca1b2bdbb054d280d..11f81b1d644f8da3c61a50bb52dcb7814de555a9 100644 (file)
@@ -330,6 +330,10 @@ floatfield Item_CounterField(float it)
                // 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)
@@ -345,6 +349,10 @@ 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;
@@ -661,11 +669,6 @@ void Item_RespawnCountdown (void)
                                        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);
@@ -676,6 +679,11 @@ void Item_RespawnCountdown (void)
                                        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)
@@ -841,7 +849,7 @@ float Item_GiveTo(entity item, entity player)
                        //      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;
                }
 
@@ -911,7 +919,7 @@ float Item_GiveTo(entity item, entity player)
                                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);
                        }
                }
 
@@ -1036,7 +1044,7 @@ void Item_Reset()
 
        if(self.classname != "droppedweapon")
        {
-               self.think = SUB_Null;
+               self.think = func_null;
                self.nextthink = 0;
 
                if(self.waypointsprite_attached)
@@ -1418,6 +1426,14 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
                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
@@ -1968,7 +1984,13 @@ void spawnfunc_target_items (void)
                        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");
index 8923c19f18300e1f742acd0586e61539744c3c15..5a5042b3d48a63dc1a273feff50b33e767a7de8f 100644 (file)
@@ -200,14 +200,8 @@ void trigger_push_touch()
                        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;
@@ -246,7 +240,7 @@ void trigger_push_touch()
 
        if (self.spawnflags & PUSH_ONCE)
        {
-               self.touch = SUB_Null;
+               self.touch = func_null;
                self.think = SUB_Remove;
                self.nextthink = time;
        }
index cd3c8d10607b54642413455633077681f03e17f2..0b9da88faf2b97fc524f472364bc2ae4f6dabc7f 100644 (file)
@@ -158,7 +158,7 @@ void plat_crush()
 
 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();
@@ -191,9 +191,9 @@ void spawnfunc_func_plat()
     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)
@@ -282,7 +282,7 @@ void train_next()
        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)
@@ -302,7 +302,7 @@ void func_train_find()
        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;
@@ -319,7 +319,7 @@ void spawnfunc_func_train()
        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;
@@ -332,9 +332,9 @@ void spawnfunc_func_train()
        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;
@@ -395,9 +395,9 @@ void spawnfunc_func_rotating()
        
        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";
 
 
@@ -414,7 +414,7 @@ void spawnfunc_func_rotating()
 
        // 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
 }
@@ -469,9 +469,9 @@ void spawnfunc_func_bobbing()
 
        // 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;
@@ -495,7 +495,7 @@ void spawnfunc_func_bobbing()
        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;
@@ -542,9 +542,9 @@ void spawnfunc_func_pendulum()
                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;
@@ -572,7 +572,7 @@ void spawnfunc_func_pendulum()
        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;
 
@@ -1303,9 +1303,9 @@ void LinkDoors()
        {
                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;
@@ -1388,7 +1388,8 @@ void door_reset()
        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)
@@ -1419,9 +1420,9 @@ void spawnfunc_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)
@@ -1500,7 +1501,8 @@ void door_rotating_reset()
        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()
@@ -1544,9 +1546,9 @@ void spawnfunc_func_door_rotating()
     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)
@@ -1613,7 +1615,6 @@ float SECRET_1ST_DOWN = 4;                // 1st move is down from arrow
 float SECRET_NO_SHOOT = 8;             // only opened by trigger
 float SECRET_YES_SHOOT = 16;   // shootable even if targeted
 
-
 void fd_secret_use()
 {
        float temp;
@@ -1664,6 +1665,11 @@ void fd_secret_use()
                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()
 {
@@ -1769,7 +1775,8 @@ void secret_reset()
                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
@@ -1819,7 +1826,7 @@ void spawnfunc_func_door_secret()
        {
                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)
@@ -1886,9 +1893,9 @@ void spawnfunc_func_fourier()
        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;
@@ -1909,7 +1916,7 @@ void spawnfunc_func_fourier()
        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;
@@ -2006,7 +2013,7 @@ void func_vectormamamam_findtarget()
        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();
@@ -2049,9 +2056,9 @@ void spawnfunc_func_vectormamamam()
                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;
@@ -2065,7 +2072,7 @@ void spawnfunc_func_vectormamamam()
 
        // 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;
index 2cfdd8a7720f5bf665d22ed5d7916da177375887..9a17d90c0c53bac0a71e9d2187f057f89add046a 100644 (file)
@@ -325,7 +325,7 @@ void spawnfunc_trigger_teleport (void)
        // 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;
index b8f2f3ac8746ea4e02daae0936833d2086954699..a96726c5643f175174783c563ec77751deb70190 100644 (file)
@@ -13,46 +13,6 @@ void TeamchangeFrags(entity e)
        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();
@@ -134,7 +94,7 @@ void InitGameplayMode()
                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
        }
 
@@ -417,13 +377,13 @@ void SetPlayerTeam(entity pl, float t, float s, float noprint)
        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);
 
@@ -431,7 +391,7 @@ void SetPlayerTeam(entity pl, float t, float s, float noprint)
                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");
        }
 
 }
@@ -453,10 +413,10 @@ void CheckAllowedTeams (entity for_whom)
                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;
                }
        }
@@ -498,13 +458,13 @@ void CheckAllowedTeams (entity for_whom)
                {
                        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);
@@ -534,13 +494,13 @@ void CheckAllowedTeams (entity for_whom)
        }
 
        // 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;
 }
 
@@ -577,7 +537,7 @@ void GetTeamCounts(entity ignore)
                                bvalue = value;
                        else
                                bvalue = 0;
-                       if(t == COLOR_TEAM1)
+                       if(t == NUM_TEAM_1)
                        {
                                if(c1 >= 0)
                                {
@@ -585,7 +545,7 @@ void GetTeamCounts(entity ignore)
                                        cb1 = cb1 + bvalue;
                                }
                        }
-                       if(t == COLOR_TEAM2)
+                       if(t == NUM_TEAM_2)
                        {
                                if(c2 >= 0)
                                {
@@ -593,7 +553,7 @@ void GetTeamCounts(entity ignore)
                                        cb2 = cb2 + bvalue;
                                }
                        }
-                       if(t == COLOR_TEAM3)
+                       if(t == NUM_TEAM_3)
                        {
                                if(c3 >= 0)
                                {
@@ -601,7 +561,7 @@ void GetTeamCounts(entity ignore)
                                        cb3 = cb3 + bvalue;
                                }
                        }
-                       if(t == COLOR_TEAM4)
+                       if(t == NUM_TEAM_4)
                        {
                                if(c4 >= 0)
                                {
@@ -770,13 +730,13 @@ float JoinBestTeam(entity pl, float only_return_best, float forcebestteam)
        // 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;
@@ -803,19 +763,19 @@ float JoinBestTeam(entity pl, float only_return_best, float forcebestteam)
                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
                {
@@ -845,21 +805,21 @@ void SV_ChangeTeam(float _color)
        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);
@@ -948,13 +908,13 @@ void ShufflePlayerOutOfTeam (float source_team)
        }
 
        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;
@@ -1049,7 +1009,7 @@ void ShufflePlayerOutOfTeam (float source_team)
 
        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
@@ -1073,12 +1033,12 @@ void tdm_spawnteams()
                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()
diff --git a/qcsrc/server/todo.txt b/qcsrc/server/todo.txt
deleted file mode 100644 (file)
index bbe81a2..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-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
index a291e3ab15759496c1e8a316d29c0cc12aa136a7..675b5de0db30283236ab1532de8cbf032af153ca 100644 (file)
@@ -30,6 +30,9 @@ vector turret_stdproc_aim_generic()
                {
                        // 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);
index 48f76219bd40a6417432422749ab5800f57a1c0f..971d65cca3916eea9f99a17d28b5d41ee096211f 100644 (file)
@@ -18,7 +18,7 @@ void turret_stdproc_die()
     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;
@@ -120,8 +120,8 @@ void turret_stdproc_damage (entity inflictor, entity attacker, float damage, flo
     
     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;
index c8bbf537c336ba548310dc896b9680ac41e21f20..dd58b3cee2860e0c031dc131a47eab165c846967 100644 (file)
@@ -145,7 +145,7 @@ void turret_projectile_explode()
 {
     
     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);
@@ -718,9 +718,7 @@ entity turret_select_target()
     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;
@@ -871,7 +869,7 @@ void turret_think()
         // 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;
 
@@ -1018,7 +1016,7 @@ void turrets_manager_think()
 */
 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)
index 5a94b442343832f8ebceef28639d72cd9e277ae0..2e3a006881384a955203649f32eebd961d8f3c62 100644 (file)
@@ -45,7 +45,7 @@ vector shortangle_v(vector ang1, vector ang2)
 
 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);
index 05717bf184dab0401ec6bc21c1417772185a0827..c542dab401ba2ee88da3f88df7d7c57f48329478 100644 (file)
@@ -1,7 +1,7 @@
 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;
 
@@ -22,8 +22,8 @@ float turret_stdproc_targetscore_generic(entity _turret, entity _target)
     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)
index f96d3b93cc79911ba5e7036da81f49a92858f6ec..9358cd7baf1bff223a7e90334e52ba02e690900f 100644 (file)
@@ -5,7 +5,7 @@ void turret_machinegun_attack();
 //.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();
index 91794929b67d16a0659f62ae01bde75a5ca66066..2f28c7c3b37cbbd5634e3dc0c08319478c80bc25 100644 (file)
@@ -60,7 +60,6 @@ void beam_think()
     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,
index 85fb8bb18205bb367dd194b7e800ea9499d1c554..5969938912285b4d9b9328f9550af9dc4892be6e 100644 (file)
@@ -47,7 +47,7 @@ entity toast(entity from, float range, float damage)
 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;
@@ -86,8 +86,6 @@ void turret_tesla_fire()
     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();
index 599eb5776968117caabdc4eed6b1b1b9610a23a0..20100de047203368a5d11e5a520a8cd8cdb39e11 100644 (file)
@@ -38,7 +38,7 @@ void walker_meele_do_dmg()
     {
         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;
     }
@@ -51,7 +51,7 @@ void walker_setnoanim()
 }
 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);
 }
 
@@ -414,7 +414,7 @@ void walker_postthink()
     //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;
@@ -515,7 +515,7 @@ void walker_postthink()
 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);
 }
index 4b0f1d13a4b5b8976eda70b150523fccebd86724..429b8e5f9f8c55cdf709e2e405c5481dffb74527 100644 (file)
@@ -86,7 +86,7 @@ void bumb_fire_cannon(entity _gun, string _tagname, entity _owner)
        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()
@@ -236,7 +236,7 @@ void bumb_gunner_exit(float _exitflag)
        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;
@@ -307,7 +307,7 @@ float bumb_gunner_enter()
        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;
@@ -735,7 +735,7 @@ void bumb_blowup()
                                 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);
@@ -794,7 +794,7 @@ void bumb_die()
        if(random() > 0.5)
                _body.touch = bumb_blowup;
        else
-               _body.touch = SUB_Null;
+               _body.touch = func_null;
                
        _body.think = bumb_diethink;
        _body.nextthink = time;
@@ -805,7 +805,7 @@ void bumb_die()
        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;
@@ -814,7 +814,7 @@ void bumb_die()
        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);
index 792be585023d064650cad8f9360b771d1d16a4f0..f5788c60b4b993a4631b2b4dbebe18456a136b85 100644 (file)
@@ -74,7 +74,7 @@ float autocvar_g_vehicle_racer_bouncestop;
 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)
 {
@@ -129,7 +129,7 @@ void racer_fire_cannon(string tagname)
     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);
@@ -243,7 +243,7 @@ void racer_fire_rocket(string tagname, entity trg)
     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;
@@ -542,10 +542,10 @@ void racer_blowup()
                                        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;
 
@@ -554,8 +554,6 @@ void racer_blowup()
     self.velocity  = '0 0 0';
 
     setorigin(self, self.pos1);
-       self.think     = racer_spawn;
-       self.nextthink = time + autocvar_g_vehicle_racer_respawntime;
 }
 
 void racer_deadtouch()
@@ -569,7 +567,7 @@ 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;
@@ -626,6 +624,10 @@ void racer_spawn(float _spawnflag)
     self.damageforcescale = 0.5;
     //self.destvec = autocvar_g_vehicle_racer_bouncepain;
 }
+void racer_spawn_default()
+{
+       racer_spawn(0);
+}
 
 
 
index a623bd540727afbe8f054c6b7fb65ec277004e14..e899d4a31468b6a83d585babfee4d7f17287ffb3 100644 (file)
@@ -93,7 +93,7 @@ void raptor_bomblet_boom()
     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);
 }
 
@@ -124,7 +124,7 @@ void raptor_bomb_burst()
     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)
     {
@@ -185,7 +185,7 @@ void raptor_fire_cannon(entity gun, string tagname)
     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()
@@ -690,7 +690,7 @@ void raptor_blowup()
 {
     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;
@@ -700,7 +700,7 @@ void raptor_blowup()
     self.velocity       = '0 0 0';
 
     setorigin(self, self.pos1);
-    self.touch = SUB_Null;
+    self.touch = func_null;
     self.nextthink = 0;
 }
 
@@ -720,7 +720,7 @@ void raptor_diethink()
 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;
index 71e57a037f88213efee91d2f8a7091607c3abfe9..a66b564773635ce4b1a3d0e1b60b239d3a5cf7b5 100644 (file)
@@ -210,7 +210,7 @@ void spiderbot_rocket_do()
 {
 
     vector v;
-    entity rocket;
+    entity rocket = world;
 
     if (self.wait != -10)
     {        
@@ -257,7 +257,7 @@ void spiderbot_rocket_do()
             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) ;
@@ -271,7 +271,7 @@ void spiderbot_rocket_do()
             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;
@@ -283,10 +283,9 @@ void spiderbot_rocket_do()
             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;
@@ -496,14 +495,15 @@ float spiderbot_frame()
             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);
@@ -723,7 +723,7 @@ void spiderbot_blowup()
     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;
@@ -736,9 +736,9 @@ void spiderbot_blowup()
 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;
index 16a339e09f40380dec3e1f84cfb5512d63252d5f..e23cc702cc706cdb912cf0e6602d0c5ce351aa82 100644 (file)
@@ -377,7 +377,7 @@ void vehicles_projectile_damage(entity inflictor, entity attacker, float damage,
     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;
     }
@@ -396,7 +396,7 @@ void vehicles_projectile_explode()
 
        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);
@@ -544,7 +544,7 @@ void vehicles_touch()
         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".
         }
@@ -610,7 +610,7 @@ void vehicles_enter()
     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)
@@ -780,7 +780,7 @@ void vehicles_exit(float eject)
         _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;
@@ -1008,7 +1008,7 @@ void vehicles_showwp_goaway()
 
 void vehicles_showwp()
 {
-    entity oldself;
+    entity oldself = world;
     vector rgb;
 
     if(self.cnt)
@@ -1033,7 +1033,7 @@ void vehicles_showwp()
     }
 
     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);
@@ -1079,11 +1079,11 @@ void vehicles_setreturn()
 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;
index 834e6516787ba0411677ea34075cf769adb1bda3..7d5a787d0061d914ca9159d1ebe6a42108057690 100644 (file)
@@ -48,7 +48,7 @@ float VHF_PLAYERSLOT    = 16384;    /// This ent is a player slot on a multi-per
 //.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)
@@ -57,16 +57,15 @@ float SVC_SETVIEWPORT   = 5;   // Net.Protocol 0x05
 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
index 3780fc71384d987160f8e56c3063166fdbcc1bb3..e68a417e00de6855f4bbfce117ce244b4de3a5f1 100644 (file)
@@ -1,5 +1,5 @@
 
-void W_GiveWeapon (entity e, float wep, string name)
+void W_GiveWeapon (entity e, float wep)
 {
        entity oldself;
 
@@ -12,12 +12,8 @@ void W_GiveWeapon (entity e, float wep, string name)
        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;
 }
@@ -167,7 +163,6 @@ void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, f
        trace_dphitq3surfaceflags = endq3surfaceflags;
 }
 
-.float dmg_edge;
 .float dmg_force;
 .float dmg_radius;
 .float dmg_total;
@@ -185,24 +180,14 @@ void W_BallisticBullet_Hit (void)
        {
                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)
@@ -229,7 +214,7 @@ void W_BallisticBullet_LeaveSolid_think()
 
        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;
 
@@ -398,7 +383,7 @@ void fireBallisticBullet_trace_callback(vector start, vector hit, vector end)
        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;
@@ -434,7 +419,6 @@ void fireBallisticBullet(vector start, vector dir, float spread, float pSpeed, f
 
        proj.touch = W_BallisticBullet_Touch;
        proj.dmg = damage;
-       proj.dmg_edge = headshotbonus;
        proj.dmg_force = force;
        proj.projectiledeathtype = dtype;
 
@@ -628,7 +612,7 @@ float W_CheckProjectileDamage(entity inflictor, entity projowner, float deathtyp
 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)
        {
index bb44e827e709cd0eb84e37bdf04c361179055e45..b2472df2ae0fa5798f7cc3e80de744210cf88827 100644 (file)
@@ -228,8 +228,8 @@ void W_Crylink_LinkJoinEffect_Think()
 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)
        {
@@ -684,6 +684,14 @@ float w_crylink(float req)
        {
                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
@@ -712,19 +720,6 @@ float w_crylink(float req)
                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
index 7a91cbd89cae366bfde23606899c9fd9807281a9..20aac867e91ae0f3b856be81fecc325b96f14180 100644 (file)
@@ -35,7 +35,7 @@ void W_Plasma_Explode (void)
                                        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)
        {
@@ -54,7 +54,7 @@ void W_Plasma_Explode_Combo (void)
 {
        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);
 }
@@ -416,6 +416,7 @@ float w_electro(float req)
        {
                if(autocvar_g_balance_electro_reload_ammo) // forced reload
                {
+                       ammo_amount = 0;
                        if(autocvar_g_balance_electro_lightning)
                        {
                                if(self.clip_load > 0)
@@ -436,13 +437,8 @@ float w_electro(float req)
                {
                        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)
@@ -547,6 +543,27 @@ float w_electro(float req)
        {
                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
@@ -585,32 +602,6 @@ float w_electro(float req)
                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
index 67547e3583efef51458b138d926cfda5daf1ed2d..4d243a513575bb04ab1703521d2c981801cb8c3c 100644 (file)
@@ -14,7 +14,7 @@ void W_Fireball_Explode (void)
        vector dir;
        float d;
 
-       self.event_damage = SUB_Null;
+       self.event_damage = func_null;
        self.takedamage = DAMAGE_NO;
 
        // 1. dist damage
@@ -234,7 +234,7 @@ void W_Firemine_Touch (void)
 {
        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;
@@ -374,6 +374,24 @@ float w_fireball(float req)
        {
                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
@@ -399,37 +417,7 @@ float w_fireball(float req)
        {
                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
index 5f6c0346f5cf3c11137bf6e5271487fb764b263e..b463a4e71ab0c18823678c8bd9d992060698dbe0 100644 (file)
@@ -14,7 +14,7 @@ void W_Grenade_Explode (void)
                                        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)
@@ -34,7 +34,7 @@ void W_Grenade_Explode2 (void)
                                        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)
@@ -366,6 +366,20 @@ float w_glauncher(float req)
        {
                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
@@ -384,23 +398,6 @@ float w_glauncher(float req)
        {
                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
index 9a4b1ef4495aa95d223d7df5cd15f7e770060f0b..b4b79abb832363bfea7fcd11d775bb0c8eb84554 100644 (file)
@@ -6,7 +6,7 @@ REGISTER_WEAPON(HAGAR, w_hagar, IT_ROCKETS, 8, WEP_FLAG_NORMAL | WEP_FLAG_RELOAD
 
 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);
@@ -14,7 +14,7 @@ void W_Hagar_Explode (void)
 
 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);
@@ -351,7 +351,7 @@ float w_hagar(float req)
        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
@@ -432,6 +432,17 @@ float w_hagar(float req)
                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
@@ -459,15 +470,6 @@ float w_hagar(float req)
                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
index a2697b2f5cb527050677ace98031e52896c6b83e..142a231923214be2cfd8a91b921fa00e88d56d15 100644 (file)
@@ -7,7 +7,7 @@ void W_HLAC_Touch (void)
 {
        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);
@@ -219,6 +219,14 @@ float w_hlac(float req)
        {
                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
@@ -237,10 +245,6 @@ float w_hlac(float req)
        {
                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
index 63d02604c4271f11cc808099f148f8946393bbf1..1f9dda17b6adcad942d336bd3ea224b2e0416092 100644 (file)
@@ -35,8 +35,8 @@ void W_Hook_ExplodeThink (void)
 
 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;
@@ -265,6 +265,14 @@ float w_hook(float req)
        {
                self.hook_refire = time;
        }
+       else if (req == WR_SUICIDEMESSAGE)
+       {
+               return FALSE;
+       }
+       else if (req == WR_KILLMESSAGE)
+       {
+               return WEAPON_HOOK_MURDER;
+       }
        return TRUE;
 }
 #endif
@@ -283,10 +291,6 @@ float w_hook(float req)
        {
                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
index 5e2bb075aa5c7ff1a4fd6b258ac2cea9661954a7..69dcb17aa5c292d4328b539668c8dac674f76935 100644 (file)
@@ -9,7 +9,7 @@ void W_Laser_Touch (void)
 {
        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
@@ -291,6 +291,14 @@ float w_laser(float req)
        {
                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
@@ -309,15 +317,6 @@ float w_laser(float req)
        {
                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
index 4d98f0c91cd50927abfecdacd53c1b82c6a35dec..6d3c331739917267ff28ff3035581d5f1631aec2 100644 (file)
@@ -5,6 +5,7 @@ REGISTER_WEAPON(MINE_LAYER, w_minelayer, IT_ROCKETS, 4, WEP_FLAG_MUTATORBLOCKED
 void W_Mine_Think (void);
 .float minelayer_detonate, mine_explodeanyway;
 .float mine_time;
+.vector mine_orientation;
 
 void spawnfunc_weapon_minelayer (void)
 {
@@ -31,7 +32,7 @@ void W_Mine_Stick (entity to)
        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;
@@ -45,7 +46,7 @@ void W_Mine_Stick (entity to)
 
        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;
@@ -67,7 +68,7 @@ void W_Mine_Explode ()
                                        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);
@@ -91,11 +92,11 @@ void W_Mine_Explode ()
 
 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);
 
@@ -153,7 +154,7 @@ float W_Mine_Count(entity e)
        entity mine;
        for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.realowner == e)
                minecount += 1;
-               
+
        return minecount;
 }
 
@@ -225,7 +226,12 @@ void W_Mine_Touch (void)
        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)
        {
@@ -263,8 +269,7 @@ void W_Mine_Attack (void)
        // 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") );
@@ -355,7 +360,10 @@ float w_minelayer(float req)
        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
@@ -505,10 +513,22 @@ float w_minelayer(float req)
                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
@@ -527,20 +547,6 @@ float w_minelayer(float req)
        {
                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
index 1f1137e4b845b151321d1501c5dbdca9e325b2fd..c464af93a27c07e05ad5493efe0cfcd4b3cb60f8 100644 (file)
@@ -14,10 +14,7 @@ void W_MinstaNex_Attack (void)
 
        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)
        {
@@ -28,14 +25,10 @@ void W_MinstaNex_Attack (void)
        {
                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
                }
        }
 
@@ -50,25 +43,25 @@ void W_MinstaNex_Attack (void)
        {
            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
@@ -92,7 +85,7 @@ void minstagib_stop_countdown(entity e)
 {
        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)
@@ -157,13 +150,13 @@ 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");
@@ -278,6 +271,14 @@ float w_minstanex(float req)
 
                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
@@ -296,10 +297,6 @@ float w_minstanex(float req)
        {
                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
index 51afdd00f100bcb7a3847960c43ec561619c08dd..9d66f407ef8bbb401c2fd4c77f0c1fd2ae52cf42 100644 (file)
@@ -233,7 +233,14 @@ float w_nex(float req)
        {
                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
@@ -252,10 +259,6 @@ float w_nex(float req)
        {
                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
index f95e554b0e9799d78a52108ca39e72f2c7dde053..790bcd124c588deff469d8d258bed5b919009d3e 100644 (file)
@@ -375,10 +375,6 @@ float w_porto(float req)
        {
                // 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
index 1c5f766d7dbf2240ce03ee0bce3e149db4c48489..749906638bf0e2ab56e782516983ebeda7dcdb01 100644 (file)
@@ -5,13 +5,13 @@ REGISTER_WEAPON(RIFLE, w_rifle, IT_NAILS, 7, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_
 
 .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);
 
@@ -22,7 +22,7 @@ void W_Rifle_FireBullet(float pSpread, float pDamage, float pHeadshotAddedDamage
        }
 
        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)
@@ -31,12 +31,12 @@ void W_Rifle_FireBullet(float pSpread, float pDamage, float pHeadshotAddedDamage
 
 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)
@@ -200,6 +200,27 @@ float w_rifle(float req)
        {
                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
@@ -227,35 +248,7 @@ float w_rifle(float req)
                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
index 643bf4bd5b5b72b0984365ab6f3f368347b434a2..202dd68bdfaac166918253cf0863c88b3287c338 100644 (file)
@@ -25,7 +25,7 @@ void W_Rocket_Explode ()
                                        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);
@@ -46,7 +46,7 @@ void W_Rocket_DoRemoteExplode ()
 {
        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);
@@ -425,6 +425,7 @@ float w_rlauncher(float req)
                // 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)
@@ -445,6 +446,17 @@ float w_rlauncher(float req)
        {
                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
@@ -463,17 +475,6 @@ float w_rlauncher(float req)
        {
                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
index 7cf6cfb73634e11be73aba7215de897f8ee7b715..7dbe4aed10ba4c462fc8cbca281cbc34f128eaba 100644 (file)
@@ -12,7 +12,7 @@ REGISTER_WEAPON(SEEKER, w_seeker, IT_ROCKETS, 8, WEP_FLAG_MUTATORBLOCKED | WEP_F
 // ============================
 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);
@@ -223,7 +223,7 @@ void Seeker_Fire_Missile(vector f_diff, entity m_target)
 // ============================
 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);
 
@@ -426,8 +426,8 @@ void Seeker_Tag_Touch()
 
        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)
        {
@@ -495,8 +495,8 @@ void Seeker_Fire_Tag()
        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);
@@ -598,20 +598,49 @@ float w_seeker(float req)
        }
        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
@@ -624,21 +653,24 @@ float w_seeker(float req)
                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
                {
@@ -664,15 +696,6 @@ float w_seeker(float req)
                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
index fcf9a27c27482a25432747d58cc37ee974fae513..75f6a087d14256ef0b32ee3525809e847b47cf41 100644 (file)
@@ -27,7 +27,7 @@ void W_Shotgun_Attack (void)
 
        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);
@@ -199,7 +199,7 @@ float w_shotgun(float req)
                        }
                }
                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))
                {
@@ -238,6 +238,17 @@ float w_shotgun(float req)
        {
                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
@@ -267,15 +278,6 @@ float w_shotgun(float req)
                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
index f19a50208293073f1507fc4bf2beec258456fa13..6b3287b59ed1ee29b1e0ee8228e89e819f0b04b0 100644 (file)
@@ -130,6 +130,9 @@ void W_Tuba_NoteOff()
                                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;
                        }
                }
        }
@@ -145,6 +148,9 @@ float Tuba_GetNote(entity pl, float hittype)
        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
@@ -180,7 +186,7 @@ float Tuba_GetNote(entity pl, float hittype)
        // 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
@@ -284,8 +290,6 @@ void W_Tuba_NoteOn(float hittype)
                hittype |= HITTYPE_SECONDARY;
        if(self.tuba_instrument & 2)
                hittype |= HITTYPE_BOUNCE;
-       if(self.tuba_instrument & 4)
-               hittype |= HITTYPE_HEADSHOT;
 
        if(self.tuba_note)
        {
@@ -374,9 +378,10 @@ float w_tuba(float req)
                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)
@@ -400,6 +405,10 @@ float w_tuba(float req)
                                        self.weaponname = "akordeon";
                                        break;
                                case 1:
+                                       self.tuba_instrument = 2;
+                                       self.weaponname = "kleinbottle";
+                                       break;
+                               case 2:
                                        self.tuba_instrument = 0;
                                        self.weaponname = "tuba";
                                        break;
@@ -414,63 +423,33 @@ float w_tuba(float req)
                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
index 77d8b4aee562215cec57fa4a1021857d41be4ca0..3645b95db83f12c969e22e37fcdf1be8abb19c4d 100644 (file)
@@ -52,9 +52,9 @@ void W_UZI_Attack (float deathtype)
        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);
@@ -126,7 +126,7 @@ void uzi_mode1_fire_auto()
        }
 
        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;
@@ -152,7 +152,7 @@ void uzi_mode1_fire_burst()
                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();
 
 
@@ -289,6 +289,17 @@ float w_uzi(float req)
        {
                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
@@ -314,15 +325,6 @@ float w_uzi(float req)
                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
index e7cf23908eda0198025a0c5ebaf437b1eb890757..c79ee95d6e02d2d2062b8a35a987de07f0aca3cb 100644 (file)
@@ -27,7 +27,7 @@ void WarpZone_MakeAllOther();
 #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)
index 9b94640b5a2319c734a103db57e036b48dd26883..4b9c2bc474e76ba0d04675390648e6ea96666ddd 100644 (file)
@@ -570,6 +570,9 @@ void WarpZone_InitStep_UpdateTransform()
                norm = normalize(norm);
        }
 
+#ifdef GMQCC
+       ang = '0 0 0';
+#endif
        if(self.aiment)
        {
                org = self.aiment.origin;
diff --git a/sound/weapons/tuba2_loopnote-12.ogg b/sound/weapons/tuba2_loopnote-12.ogg
new file mode 100644 (file)
index 0000000..f01bd08
Binary files /dev/null and b/sound/weapons/tuba2_loopnote-12.ogg differ
diff --git a/sound/weapons/tuba2_loopnote-18.ogg b/sound/weapons/tuba2_loopnote-18.ogg
new file mode 100644 (file)
index 0000000..e1ca02b
Binary files /dev/null and b/sound/weapons/tuba2_loopnote-18.ogg differ
diff --git a/sound/weapons/tuba2_loopnote-6.ogg b/sound/weapons/tuba2_loopnote-6.ogg
new file mode 100644 (file)
index 0000000..411cec7
Binary files /dev/null and b/sound/weapons/tuba2_loopnote-6.ogg differ
diff --git a/sound/weapons/tuba2_loopnote0.ogg b/sound/weapons/tuba2_loopnote0.ogg
new file mode 100644 (file)
index 0000000..4924d59
Binary files /dev/null and b/sound/weapons/tuba2_loopnote0.ogg differ
diff --git a/sound/weapons/tuba2_loopnote12.ogg b/sound/weapons/tuba2_loopnote12.ogg
new file mode 100644 (file)
index 0000000..13b7c7f
Binary files /dev/null and b/sound/weapons/tuba2_loopnote12.ogg differ
diff --git a/sound/weapons/tuba2_loopnote18.ogg b/sound/weapons/tuba2_loopnote18.ogg
new file mode 100644 (file)
index 0000000..20a29c2
Binary files /dev/null and b/sound/weapons/tuba2_loopnote18.ogg differ
diff --git a/sound/weapons/tuba2_loopnote24.ogg b/sound/weapons/tuba2_loopnote24.ogg
new file mode 100644 (file)
index 0000000..0e497b5
Binary files /dev/null and b/sound/weapons/tuba2_loopnote24.ogg differ
diff --git a/sound/weapons/tuba2_loopnote6.ogg b/sound/weapons/tuba2_loopnote6.ogg
new file mode 100644 (file)
index 0000000..652d512
Binary files /dev/null and b/sound/weapons/tuba2_loopnote6.ogg differ
diff --git a/sound/weapons/tuba_loopnote-1.ogg b/sound/weapons/tuba_loopnote-1.ogg
deleted file mode 100644 (file)
index e296fe4..0000000
Binary files a/sound/weapons/tuba_loopnote-1.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote-10.ogg b/sound/weapons/tuba_loopnote-10.ogg
deleted file mode 100644 (file)
index e14fca6..0000000
Binary files a/sound/weapons/tuba_loopnote-10.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote-11.ogg b/sound/weapons/tuba_loopnote-11.ogg
deleted file mode 100644 (file)
index e220a8a..0000000
Binary files a/sound/weapons/tuba_loopnote-11.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote-13.ogg b/sound/weapons/tuba_loopnote-13.ogg
deleted file mode 100644 (file)
index 4545f50..0000000
Binary files a/sound/weapons/tuba_loopnote-13.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote-14.ogg b/sound/weapons/tuba_loopnote-14.ogg
deleted file mode 100644 (file)
index ec0e27a..0000000
Binary files a/sound/weapons/tuba_loopnote-14.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote-15.ogg b/sound/weapons/tuba_loopnote-15.ogg
deleted file mode 100644 (file)
index 2a540b0..0000000
Binary files a/sound/weapons/tuba_loopnote-15.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote-16.ogg b/sound/weapons/tuba_loopnote-16.ogg
deleted file mode 100644 (file)
index 9f0b1c8..0000000
Binary files a/sound/weapons/tuba_loopnote-16.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote-17.ogg b/sound/weapons/tuba_loopnote-17.ogg
deleted file mode 100644 (file)
index 6fbb1fc..0000000
Binary files a/sound/weapons/tuba_loopnote-17.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote-2.ogg b/sound/weapons/tuba_loopnote-2.ogg
deleted file mode 100644 (file)
index 6089e4e..0000000
Binary files a/sound/weapons/tuba_loopnote-2.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote-3.ogg b/sound/weapons/tuba_loopnote-3.ogg
deleted file mode 100644 (file)
index 8299e6a..0000000
Binary files a/sound/weapons/tuba_loopnote-3.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote-4.ogg b/sound/weapons/tuba_loopnote-4.ogg
deleted file mode 100644 (file)
index fe452d1..0000000
Binary files a/sound/weapons/tuba_loopnote-4.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote-5.ogg b/sound/weapons/tuba_loopnote-5.ogg
deleted file mode 100644 (file)
index 48f412b..0000000
Binary files a/sound/weapons/tuba_loopnote-5.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote-7.ogg b/sound/weapons/tuba_loopnote-7.ogg
deleted file mode 100644 (file)
index a71c9d9..0000000
Binary files a/sound/weapons/tuba_loopnote-7.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote-8.ogg b/sound/weapons/tuba_loopnote-8.ogg
deleted file mode 100644 (file)
index 45c7aad..0000000
Binary files a/sound/weapons/tuba_loopnote-8.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote-9.ogg b/sound/weapons/tuba_loopnote-9.ogg
deleted file mode 100644 (file)
index 6bad199..0000000
Binary files a/sound/weapons/tuba_loopnote-9.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote1.ogg b/sound/weapons/tuba_loopnote1.ogg
deleted file mode 100644 (file)
index 43c7f66..0000000
Binary files a/sound/weapons/tuba_loopnote1.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote10.ogg b/sound/weapons/tuba_loopnote10.ogg
deleted file mode 100644 (file)
index a2e99df..0000000
Binary files a/sound/weapons/tuba_loopnote10.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote11.ogg b/sound/weapons/tuba_loopnote11.ogg
deleted file mode 100644 (file)
index f9af7b0..0000000
Binary files a/sound/weapons/tuba_loopnote11.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote13.ogg b/sound/weapons/tuba_loopnote13.ogg
deleted file mode 100644 (file)
index ab865ac..0000000
Binary files a/sound/weapons/tuba_loopnote13.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote14.ogg b/sound/weapons/tuba_loopnote14.ogg
deleted file mode 100644 (file)
index 42b649a..0000000
Binary files a/sound/weapons/tuba_loopnote14.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote15.ogg b/sound/weapons/tuba_loopnote15.ogg
deleted file mode 100644 (file)
index 4d8ba65..0000000
Binary files a/sound/weapons/tuba_loopnote15.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote16.ogg b/sound/weapons/tuba_loopnote16.ogg
deleted file mode 100644 (file)
index fe5ea3a..0000000
Binary files a/sound/weapons/tuba_loopnote16.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote17.ogg b/sound/weapons/tuba_loopnote17.ogg
deleted file mode 100644 (file)
index 6351e36..0000000
Binary files a/sound/weapons/tuba_loopnote17.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote19.ogg b/sound/weapons/tuba_loopnote19.ogg
deleted file mode 100644 (file)
index 56052bb..0000000
Binary files a/sound/weapons/tuba_loopnote19.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote2.ogg b/sound/weapons/tuba_loopnote2.ogg
deleted file mode 100644 (file)
index 3945ca1..0000000
Binary files a/sound/weapons/tuba_loopnote2.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote20.ogg b/sound/weapons/tuba_loopnote20.ogg
deleted file mode 100644 (file)
index 0eabe02..0000000
Binary files a/sound/weapons/tuba_loopnote20.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote21.ogg b/sound/weapons/tuba_loopnote21.ogg
deleted file mode 100644 (file)
index aa28b41..0000000
Binary files a/sound/weapons/tuba_loopnote21.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote22.ogg b/sound/weapons/tuba_loopnote22.ogg
deleted file mode 100644 (file)
index 621e82f..0000000
Binary files a/sound/weapons/tuba_loopnote22.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote23.ogg b/sound/weapons/tuba_loopnote23.ogg
deleted file mode 100644 (file)
index 6edc262..0000000
Binary files a/sound/weapons/tuba_loopnote23.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote25.ogg b/sound/weapons/tuba_loopnote25.ogg
deleted file mode 100644 (file)
index d6b3044..0000000
Binary files a/sound/weapons/tuba_loopnote25.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote26.ogg b/sound/weapons/tuba_loopnote26.ogg
deleted file mode 100644 (file)
index 648f217..0000000
Binary files a/sound/weapons/tuba_loopnote26.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote27.ogg b/sound/weapons/tuba_loopnote27.ogg
deleted file mode 100644 (file)
index c5ddb4f..0000000
Binary files a/sound/weapons/tuba_loopnote27.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote3.ogg b/sound/weapons/tuba_loopnote3.ogg
deleted file mode 100644 (file)
index 5ef1ce8..0000000
Binary files a/sound/weapons/tuba_loopnote3.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote4.ogg b/sound/weapons/tuba_loopnote4.ogg
deleted file mode 100644 (file)
index 90ca19c..0000000
Binary files a/sound/weapons/tuba_loopnote4.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote5.ogg b/sound/weapons/tuba_loopnote5.ogg
deleted file mode 100644 (file)
index 11512d1..0000000
Binary files a/sound/weapons/tuba_loopnote5.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote7.ogg b/sound/weapons/tuba_loopnote7.ogg
deleted file mode 100644 (file)
index 3138f29..0000000
Binary files a/sound/weapons/tuba_loopnote7.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote8.ogg b/sound/weapons/tuba_loopnote8.ogg
deleted file mode 100644 (file)
index d2a4e48..0000000
Binary files a/sound/weapons/tuba_loopnote8.ogg and /dev/null differ
diff --git a/sound/weapons/tuba_loopnote9.ogg b/sound/weapons/tuba_loopnote9.ogg
deleted file mode 100644 (file)
index 9dd8c86..0000000
Binary files a/sound/weapons/tuba_loopnote9.ogg and /dev/null differ