--- /dev/null
+*.7z -crlf -diff
+*.aft crlf=input
+*.aliases crlf=input
+all crlf=input
+*.animinfo crlf=input
+*.aps -crlf -diff
+*.ase -crlf
+*.bat -crlf
+*.bgs crlf=input
+*.blend -crlf -diff
+*.bmp -crlf -diff
+branch-manager crlf=input
+BSDmakefile crlf=input
+bsp2ent crlf=input
+*.bsp -crlf -diff
+*.cache -crlf -diff
+*.cbp -crlf
+*.cbp -crlf -diff
+*.c crlf=input
+*.cfg crlf=input
+*.cg crlf=input
+ChangeLog crlf=input
+CHANGES crlf=input
+COMPILING crlf=input
+*.conf crlf=input
+CONTRIBUTORS crlf=input
+COPYING crlf=input
+*.cpp crlf=input
+*.css crlf=input
+Current -crlf -diff
+*.cvsignore crlf=input
+*.cvswrappers crlf=input
+*.db -crlf -diff
+*.default crlf=input
+*.def crlf=input
+*.dem -crlf -diff
+*.dev -crlf
+*.dll -crlf -diff
+DOCS -crlf -diff
+*.dot crlf=input
+DoxyConfig crlf=input
+Doxyfile crlf=input
+*.doxygen crlf=input
+*.dpm -crlf -diff
+*.dsp -crlf
+*.dsw -crlf
+*.dtd crlf=input
+*.dylib -crlf -diff
+*.EncoderPlugin crlf=input
+*.ent -crlf
+*.form crlf=input
+*.framegroups crlf=input
+*.game crlf=input
+gendox crlf=input
+gendoxfunctions crlf=input
+genDoxyfile crlf=input
+*.gif -crlf -diff
+*.gitattributes crlf=input
+git-branch-manager crlf=input
+git-filter-index crlf=input
+git-filter-repository crlf=input
+*.gitignore crlf=input
+git-pullall crlf=input
+git-split-repository crlf=input
+git-svn-checkout crlf=input
+git-svn-update crlf=input
+git-update-octopus crlf=input
+*.glp crlf=input
+*.glsl crlf=input
+GPL crlf=input
+*.hardwired crlf=input
+*.h crlf=input
+*.hs crlf=input
+*.html crlf=input
+*.html-part crlf=input
+*.icns -crlf -diff
+*.ico -crlf -diff
+*.idsoftware crlf=input
+*.inc crlf=input
+*.instantaction crlf=input
+*.java crlf=input
+*.jhm crlf=input
+*.jnlp crlf=input
+*.jpg -crlf -diff
+*.jsmooth crlf=input
+LGPL crlf=input
+LICENSE crlf=input
+*.lmp -crlf -diff
+*.loaders crlf=input
+*.lso -crlf -diff
+makefile crlf=input
+Makefile crlf=input
+*.makespr32 crlf=input
+makespr32 crlf=input
+*.map -crlf
+*.mapinfo crlf=input
+*.m crlf=input
+*.md3 -crlf -diff
+*.md5anim -crlf
+*.md5mesh -crlf
+*.mdl -crlf -diff
+*.med crlf=input
+*.mf crlf=input
+*.mid -crlf -diff
+*.mk crlf=input
+*.mmpz -crlf -diff
+*.modinfo crlf=input
+*.modules crlf=input
+nexuiz-map-compiler crlf=input
+nexuiz-osx-agl crlf=input
+nexuiz-osx-sdl crlf=input
+*.nib -crlf
+*.obj -crlf
+OFFSETS -crlf -diff
+*.ogg -crlf -diff
+*.options crlf=input
+pangorc crlf=input
+*.patch crlf=input
+*.patchsets crlf=input
+*.pcx -crlf -diff
+*.pk3 -crlf -diff
+PkgInfo crlf=input
+*.pl crlf=input
+*.plist crlf=input
+*.pm crlf=input
+*.png -crlf -diff
+POSITIONS -crlf -diff
+*.proj -crlf
+*.properties crlf=input
+*.psd -crlf -diff
+*.py crlf=input
+*.q3map1 crlf=input
+*.qc crlf=input
+*.qdt crlf=input
+*.qh crlf=input
+*.rb crlf=input
+*.rc2 crlf=input
+*.rc -crlf
+*.readme crlf=input
+README crlf=input
+*.rtlights -crlf -diff
+SCHEMA crlf=input
+*.scm crlf=input
+SDL -crlf -diff
+SDLMain.m crlf=input
+*.shader crlf=input
+*.sh crlf=input
+*.skin crlf=input
+*.sln -crlf
+*.sounds crlf=input
+*.sp2 -crlf -diff
+*.spr32 -crlf -diff
+*.spr -crlf -diff
+*.src crlf=input
+*.strings crlf=input
+*.strip crlf=input
+strip crlf=input
+*.svg -crlf -diff
+*.TAB -crlf -diff
+*.tga -crlf -diff
+TMAP -crlf -diff
+todo crlf=input
+TODO crlf=input
+*.ttf -crlf -diff
+*.TTF -crlf -diff
+*.txt crlf=input
+*.TXT crlf=input
+*.vcproj -crlf
+*.wav -crlf -diff
+*.waypoints -crlf -diff
+*.width crlf=input
+*.workspace -crlf
+*.xcf -crlf -diff
+*.xlink crlf=input
+*.xml crlf=input
+*.xpm crlf=input
+*.zip -crlf -diff
+zipdiff crlf=input
+*.zym -crlf -diff
--- /dev/null
+csprogs.dat
+menu.dat
+progs.dat
+qcsrc/client/fteqcc.log
+qcsrc/menu/fteqcc.log
+qcsrc/server/fteqcc.log
ZIPEXCLUDE ?= -x\!*.pk3 -xr\!\.svn -x\!qcsrc
DIFF ?= diff
-FTEQCCFLAGS ?= -Werror -Wall -Wno-mundane -O3 -Ono-c -Ono-cs -flo
+FTEQCCFLAGS_WATERMARK ?= -DWATERMARK='"^1$(shell git describe) TEST BUILD"'
+FTEQCCFLAGS ?= -Werror -Wall -Wno-mundane -O3 -Ono-c -Ono-cs -flo $(FTEQCCFLAGS_EXTRA) $(FTEQCCFLAGS_WATERMARK)
FTEQCCFLAGS_PROGS ?=
FTEQCCFLAGS_MENU ?=
rm -f progs.dat menu.dat csprogs.dat
csprogs.dat: qcsrc/client/*.* qcsrc/common/*.* qcsrc/warpzonelib/*.*
+ @echo make[1]: Entering directory \`$(PWD)/qcsrc/client\'
cd qcsrc/client && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_CSPROGS)
progs.dat: qcsrc/server/*.* qcsrc/common/*.* qcsrc/server/*/*.* qcsrc/server/*/*/*.* qcsrc/warpzonelib/*.*
+ @echo make[1]: Entering directory \`$(PWD)/qcsrc/server\'
cd qcsrc/server && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_PROGS)
menu.dat: qcsrc/menu/*.* qcsrc/menu/*/*.* qcsrc/common/*.*
+ @echo make[1]: Entering directory \`$(PWD)/qcsrc/menu\'
cd qcsrc/menu && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_MENU)
gfx/menu/default/skinvalues.txt: qcsrc/menu/skin-customizables.inc
-// {{{ weapon replacement
-// NOTE: this only replaces weapons on the map
-// use g_start_weapon_* to also replace the on-startup weapons!
-// example: g_weaponreplace_nex "nex minstanex", then Nexes become MinstaNexes 50% of the times
-// set the cvars to "0" to totally disable a weapon
-set sv_q3acompat_machineshotgunswap 0 "shorthand for swapping uzi and shotgun"
-set g_weaponreplace_laser ""
-set g_weaponreplace_shotgun ""
-set g_weaponreplace_uzi ""
-set g_weaponreplace_grenadelauncher ""
-set g_weaponreplace_electro ""
-set g_weaponreplace_crylink ""
-set g_weaponreplace_nex ""
-set g_weaponreplace_hagar ""
-set g_weaponreplace_rocketlauncher ""
-set g_weaponreplace_porto ""
-set g_weaponreplace_minstanex ""
-set g_weaponreplace_hook ""
-set g_weaponreplace_hlac ""
-set g_weaponreplace_campingrifle ""
-set g_weaponreplace_tuba ""
-set g_weaponreplace_fireball ""
-set sv_q3acompat_machineshotgunswap 0 "shorthand for swapping uzi and shotgun (for Q3A map compatibility)"
-// }}}
-
// {{{ starting gear
set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_hlac 0 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_hlac -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
set g_start_weapon_campingrifle -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_fireball 0 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_seeker -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
set g_balance_health_start 100
set g_balance_armor_start 0
set g_start_ammo_shells 45
set g_lms_start_ammo_rockets 50
set g_lms_start_ammo_cells 50
set g_lms_start_ammo_fuel 0
-set g_balance_nixnex_roundtime 25
-set g_balance_nixnex_incrtime 1.6
-set g_balance_nixnex_ammo_shells 15
-set g_balance_nixnex_ammo_nails 45
-set g_balance_nixnex_ammo_rockets 15
-set g_balance_nixnex_ammo_cells 15
-set g_balance_nixnex_ammo_fuel 0
-set g_balance_nixnex_ammoincr_shells 2
-set g_balance_nixnex_ammoincr_nails 6
-set g_balance_nixnex_ammoincr_rockets 2
-set g_balance_nixnex_ammoincr_cells 2
-set g_balance_nixnex_ammoincr_fuel 2
+set g_balance_nix_roundtime 25
+set g_balance_nix_incrtime 1.6
+set g_balance_nix_ammo_shells 15
+set g_balance_nix_ammo_nails 45
+set g_balance_nix_ammo_rockets 15
+set g_balance_nix_ammo_cells 15
+set g_balance_nix_ammo_fuel 0
+set g_balance_nix_ammoincr_shells 2
+set g_balance_nix_ammoincr_nails 6
+set g_balance_nix_ammoincr_rockets 2
+set g_balance_nix_ammoincr_cells 2
+set g_balance_nix_ammoincr_fuel 2
// }}}
// {{{ pickup items
+set g_pickup_ammo_anyway 0
+set g_pickup_weapons_anyway 0
set g_pickup_shells 30
set g_pickup_shells_max 120
set g_pickup_nails 80
set g_pickup_fuel_max 999
set g_pickup_armorsmall 10
set g_pickup_armorsmall_max 100
+set g_pickup_armorsmall_anyway 0
set g_pickup_armormedium 25
set g_pickup_armormedium_max 100
+set g_pickup_armormedium_anyway 0
set g_pickup_armorbig 50
set g_pickup_armorbig_max 100
+set g_pickup_armorbig_anyway 0
set g_pickup_armorlarge 100
set g_pickup_armorlarge_max 100
+set g_pickup_armorlarge_anyway 0
set g_pickup_healthsmall 10
set g_pickup_healthsmall_max 200
+set g_pickup_healthsmall_anyway 0
set g_pickup_healthmedium 25
set g_pickup_healthmedium_max 200
+set g_pickup_healthmedium_anyway 0
set g_pickup_healthlarge 50
set g_pickup_healthlarge_max 200
+set g_pickup_healthlarge_anyway 0
set g_pickup_healthmega 100
set g_pickup_healthmega_max 200
+set g_pickup_healthmega_anyway 0
set g_pickup_respawntime_short 15
set g_pickup_respawntime_medium 20
set g_pickup_respawntime_long 30
set g_balance_grenadelauncher_secondary_ammo 2
set g_balance_grenadelauncher_secondary_health 70
set g_balance_grenadelauncher_secondary_damageforcescale 4
+set g_balance_grenadelauncher_secondary_bouncefactor 0.5
+set g_balance_grenadelauncher_secondary_bouncestop 0.075
// }}}
// {{{ electro
set g_balance_electro_lightning 0
set g_balance_campingrifle_primary_ammo 10
set g_balance_campingrifle_primary_bulletconstant 130 // 56.3qu
set g_balance_campingrifle_primary_burstcost 0.35 // require same cooldown as secondary, note it's smaller than primary refire time
+set g_balance_campingrifle_primary_bullethail 0
set g_balance_campingrifle_secondary_damage 15
set g_balance_campingrifle_secondary_headshotaddeddamage 25
set g_balance_campingrifle_secondary_spread 0.02
set g_balance_campingrifle_secondary_ammo 4
set g_balance_campingrifle_secondary_bulletconstant 130 // 18.3qu
set g_balance_campingrifle_secondary_burstcost 0.35
+set g_balance_campingrifle_secondary_bullethail 0
// }}}
// {{{ tuba
set g_balance_tuba_refire 0.05
set g_balance_tuba_force 40
// }}}
// {{{ fireball
-set g_balance_fireball_primary_ammo 5
-set g_balance_fireball_primary_animtime 0.3
-set g_balance_fireball_primary_damage 40
+set g_balance_fireball_primary_ammo 40
+set g_balance_fireball_primary_animtime 0.15
+set g_balance_fireball_primary_bfgdamage 100
+set g_balance_fireball_primary_bfgforce 0
+set g_balance_fireball_primary_bfgradius 1000
+set g_balance_fireball_primary_damage 200
set g_balance_fireball_primary_damageforcescale 4
-set g_balance_fireball_primary_damagetime 5
-set g_balance_fireball_primary_force 100
+set g_balance_fireball_primary_edgedamage 0
+set g_balance_fireball_primary_force 700
+set g_balance_fireball_primary_health 50
set g_balance_fireball_primary_laserburntime 0.5
-set g_balance_fireball_primary_laserdamage 30
+set g_balance_fireball_primary_laserdamage 80
set g_balance_fireball_primary_laseredgedamage 20
-set g_balance_fireball_primary_laserradius 110
-set g_balance_fireball_primary_lifetime 7
-set g_balance_fireball_primary_refire 2
-set g_balance_fireball_primary_speed 900
-set g_balance_fireball_primary_speed_up 100
-set g_balance_fireball_primary_speed_z 0
+set g_balance_fireball_primary_laserradius 256
+set g_balance_fireball_primary_lifetime 15
+set g_balance_fireball_primary_radius 200
+set g_balance_fireball_primary_refire 5
+set g_balance_fireball_primary_refire2 0
+set g_balance_fireball_primary_speed 650
set g_balance_fireball_primary_spread 0
-set g_balance_fireball_secondary_ammo 25
-set g_balance_fireball_secondary_animtime 0.15
-set g_balance_fireball_secondary_bfgdamage 100
-set g_balance_fireball_secondary_bfgforce 500
-set g_balance_fireball_secondary_bfgradius 750
-set g_balance_fireball_secondary_damage 150
+set g_balance_fireball_secondary_ammo 5
+set g_balance_fireball_secondary_animtime 0.3
+set g_balance_fireball_secondary_damage 40
set g_balance_fireball_secondary_damageforcescale 4
-set g_balance_fireball_secondary_edgedamage 0
-set g_balance_fireball_secondary_force 700
-set g_balance_fireball_secondary_health 50
+set g_balance_fireball_secondary_damagetime 5
+set g_balance_fireball_secondary_force 100
set g_balance_fireball_secondary_laserburntime 0.5
set g_balance_fireball_secondary_laserdamage 30
set g_balance_fireball_secondary_laseredgedamage 20
-set g_balance_fireball_secondary_laserradius 256
-set g_balance_fireball_secondary_lifetime 15
-set g_balance_fireball_secondary_radius 200
-set g_balance_fireball_secondary_refire 0
-set g_balance_fireball_secondary_refire2 4
-set g_balance_fireball_secondary_speed 650
+set g_balance_fireball_secondary_laserradius 110
+set g_balance_fireball_secondary_lifetime 7
+set g_balance_fireball_secondary_refire 2
+set g_balance_fireball_secondary_speed 900
+set g_balance_fireball_secondary_speed_up 100
+set g_balance_fireball_secondary_speed_z 0
set g_balance_fireball_secondary_spread 0
// }}}
+// {{{ seeker
+set g_balance_seeker_flac_ammo 0.5
+set g_balance_seeker_flac_animtime 0.1
+set g_balance_seeker_flac_damage 15
+set g_balance_seeker_flac_edgedamage 10
+set g_balance_seeker_flac_force 50
+set g_balance_seeker_flac_lifetime 0.1
+set g_balance_seeker_flac_lifetime_rand 0.05
+set g_balance_seeker_flac_radius 100
+set g_balance_seeker_flac_refire 0.1
+set g_balance_seeker_flac_speed 3000
+set g_balance_seeker_flac_speed_up 1000
+set g_balance_seeker_flac_speed_z 0
+set g_balance_seeker_flac_spread 0.4
+set g_balance_seeker_missile_accel 1.05
+set g_balance_seeker_missile_ammo 2
+set g_balance_seeker_missile_animtime 0.3
+set g_balance_seeker_missile_count 4
+set g_balance_seeker_missile_damage 40
+set g_balance_seeker_missile_damageforcescale 4
+set g_balance_seeker_missile_decel 0.9
+set g_balance_seeker_missile_delay 0.25
+set g_balance_seeker_missile_edgedamage 10
+set g_balance_seeker_missile_force 250
+set g_balance_seeker_missile_health 5
+set g_balance_seeker_missile_lifetime 15
+set g_balance_seeker_missile_proxy 0
+set g_balance_seeker_missile_proxy_delay 0.2
+set g_balance_seeker_missile_proxy_maxrange 45
+set g_balance_seeker_missile_radius 80
+set g_balance_seeker_missile_refire 0.5
+set g_balance_seeker_missile_smart 1
+set g_balance_seeker_missile_smart_mindist 800
+set g_balance_seeker_missile_smart_trace_max 2500
+set g_balance_seeker_missile_smart_trace_min 1000
+set g_balance_seeker_missile_speed 700
+set g_balance_seeker_missile_speed_accel 0
+set g_balance_seeker_missile_speed_up 300
+set g_balance_seeker_missile_speed_z 0
+set g_balance_seeker_missile_speed_max 1250
+set g_balance_seeker_missile_spread 0
+set g_balance_seeker_missile_turnrate 0.65
+set g_balance_seeker_tag_ammo 1
+set g_balance_seeker_tag_animtime 0.3
+set g_balance_seeker_tag_damageforcescale 4
+set g_balance_seeker_tag_health 5
+set g_balance_seeker_tag_lifetime 15
+set g_balance_seeker_tag_refire 0.7
+set g_balance_seeker_tag_speed 9000
+set g_balance_seeker_tag_spread 0
+// End new seeker
-// {{{ weapon replacement
-// NOTE: this only replaces weapons on the map
-// use g_start_weapon_* to also replace the on-startup weapons!
-// example: g_weaponreplace_nex "nex minstanex", then Nexes become MinstaNexes 50% of the times
-// set the cvars to "0" to totally disable a weapon
-set g_weaponreplace_laser ""
-set g_weaponreplace_shotgun ""
-set g_weaponreplace_uzi ""
-set g_weaponreplace_grenadelauncher ""
-set g_weaponreplace_electro ""
-set g_weaponreplace_crylink ""
-set g_weaponreplace_nex ""
-set g_weaponreplace_hagar ""
-set g_weaponreplace_rocketlauncher ""
-set g_weaponreplace_porto ""
-set g_weaponreplace_minstanex ""
-set g_weaponreplace_hook ""
-set g_weaponreplace_hlac ""
-set g_weaponreplace_campingrifle ""
-set g_weaponreplace_tuba ""
-set g_weaponreplace_fireball ""
-set sv_q3acompat_machineshotgunswap 0 "shorthand for swapping uzi and shotgun (for Q3A map compatibility)"
-// }}}
-
// {{{ starting gear
set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
set g_start_weapon_campingrifle -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_seeker 0 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
set g_balance_health_start 150
set g_balance_armor_start 0
set g_start_ammo_shells 40
set g_lms_start_ammo_rockets 50
set g_lms_start_ammo_cells 50
set g_lms_start_ammo_fuel 0
-set g_balance_nixnex_roundtime 25
-set g_balance_nixnex_incrtime 1.6
-set g_balance_nixnex_ammo_shells 15
-set g_balance_nixnex_ammo_nails 45
-set g_balance_nixnex_ammo_rockets 15
-set g_balance_nixnex_ammo_cells 15
-set g_balance_nixnex_ammo_fuel 0
-set g_balance_nixnex_ammoincr_shells 2
-set g_balance_nixnex_ammoincr_nails 6
-set g_balance_nixnex_ammoincr_rockets 2
-set g_balance_nixnex_ammoincr_cells 2
-set g_balance_nixnex_ammoincr_fuel 2
+set g_balance_nix_roundtime 25
+set g_balance_nix_incrtime 1.6
+set g_balance_nix_ammo_shells 15
+set g_balance_nix_ammo_nails 45
+set g_balance_nix_ammo_rockets 15
+set g_balance_nix_ammo_cells 15
+set g_balance_nix_ammo_fuel 0
+set g_balance_nix_ammoincr_shells 2
+set g_balance_nix_ammoincr_nails 6
+set g_balance_nix_ammoincr_rockets 2
+set g_balance_nix_ammoincr_cells 2
+set g_balance_nix_ammoincr_fuel 2
// }}}
// {{{ pickup items
+set g_pickup_ammo_anyway 0
+set g_pickup_weapons_anyway 0
set g_pickup_shells 15
set g_pickup_shells_max 999
set g_pickup_nails 80
set g_pickup_fuel_max 999
set g_pickup_armorsmall 5
set g_pickup_armorsmall_max 999
+set g_pickup_armorsmall_anyway 0
set g_pickup_armormedium 25
set g_pickup_armormedium_max 999
+set g_pickup_armormedium_anyway 0
set g_pickup_armorbig 50
set g_pickup_armorbig_max 999
+set g_pickup_armorbig_anyway 0
set g_pickup_armorlarge 100
set g_pickup_armorlarge_max 999
+set g_pickup_armorlarge_anyway 0
set g_pickup_healthsmall 5
set g_pickup_healthsmall_max 999
+set g_pickup_healthsmall_anyway 0
set g_pickup_healthmedium 25
set g_pickup_healthmedium_max 999
+set g_pickup_healthmedium_anyway 0
set g_pickup_healthlarge 50
set g_pickup_healthlarge_max 999
+set g_pickup_healthlarge_anyway 0
set g_pickup_healthmega 100
set g_pickup_healthmega_max 999
+set g_pickup_healthmega_anyway 0
set g_pickup_respawntime_short 15
set g_pickup_respawntime_medium 20
set g_pickup_respawntime_long 30
set g_balance_grenadelauncher_secondary_ammo 2
set g_balance_grenadelauncher_secondary_health 10
set g_balance_grenadelauncher_secondary_damageforcescale 4
+set g_balance_grenadelauncher_secondary_bouncefactor 0.5
+set g_balance_grenadelauncher_secondary_bouncestop 0.075
// }}}
// {{{ electro
set g_balance_electro_lightning 0
set g_balance_campingrifle_primary_ammo 10
set g_balance_campingrifle_primary_bulletconstant 130 // 56.3qu
set g_balance_campingrifle_primary_burstcost 0
+set g_balance_campingrifle_primary_bullethail 0 // empty magazine on shot
set g_balance_campingrifle_secondary_damage 35
set g_balance_campingrifle_secondary_headshotaddeddamage 15 // 50 damage only on head
set g_balance_campingrifle_secondary_spread 0.008
set g_balance_campingrifle_secondary_ammo 10
set g_balance_campingrifle_secondary_bulletconstant 130 // 18.3qu
set g_balance_campingrifle_secondary_burstcost 0
+set g_balance_campingrifle_secondary_bullethail 0 // empty magazine on shot
// }}}
// {{{ tuba
set g_balance_tuba_refire 0.05
set g_balance_tuba_force 40
// }}}
// {{{ fireball
-set g_balance_fireball_primary_ammo 5
-set g_balance_fireball_primary_animtime 0.3
-set g_balance_fireball_primary_damage 100
+set g_balance_fireball_primary_ammo 40
+set g_balance_fireball_primary_animtime 0.15
+set g_balance_fireball_primary_bfgdamage 100
+set g_balance_fireball_primary_bfgforce 0
+set g_balance_fireball_primary_bfgradius 1000
+set g_balance_fireball_primary_damage 200
set g_balance_fireball_primary_damageforcescale 4
-set g_balance_fireball_primary_damagetime 5
-set g_balance_fireball_primary_force 100
+set g_balance_fireball_primary_edgedamage 0
+set g_balance_fireball_primary_force 700
+set g_balance_fireball_primary_health 50
set g_balance_fireball_primary_laserburntime 0.5
set g_balance_fireball_primary_laserdamage 80
set g_balance_fireball_primary_laseredgedamage 20
-set g_balance_fireball_primary_laserradius 128
-set g_balance_fireball_primary_lifetime 7
-set g_balance_fireball_primary_refire 1.5
-set g_balance_fireball_primary_speed 700
-set g_balance_fireball_primary_speed_up 100
-set g_balance_fireball_primary_speed_z 0
+set g_balance_fireball_primary_laserradius 256
+set g_balance_fireball_primary_lifetime 15
+set g_balance_fireball_primary_radius 200
+set g_balance_fireball_primary_refire 5
+set g_balance_fireball_primary_refire2 0
+set g_balance_fireball_primary_speed 650
set g_balance_fireball_primary_spread 0
-set g_balance_fireball_secondary_ammo 15
-set g_balance_fireball_secondary_animtime 0.15
-set g_balance_fireball_secondary_bfgdamage 200
-set g_balance_fireball_secondary_bfgforce 0
-set g_balance_fireball_secondary_bfgradius 1500
-set g_balance_fireball_secondary_damage 150
+set g_balance_fireball_secondary_ammo 5
+set g_balance_fireball_secondary_animtime 0.3
+set g_balance_fireball_secondary_damage 40
set g_balance_fireball_secondary_damageforcescale 4
-set g_balance_fireball_secondary_edgedamage 0
-set g_balance_fireball_secondary_force 700
-set g_balance_fireball_secondary_health 50
+set g_balance_fireball_secondary_damagetime 5
+set g_balance_fireball_secondary_force 100
set g_balance_fireball_secondary_laserburntime 0.5
-set g_balance_fireball_secondary_laserdamage 80
+set g_balance_fireball_secondary_laserdamage 50
set g_balance_fireball_secondary_laseredgedamage 20
-set g_balance_fireball_secondary_laserradius 256
-set g_balance_fireball_secondary_lifetime 15
-set g_balance_fireball_secondary_radius 200
+set g_balance_fireball_secondary_laserradius 110
+set g_balance_fireball_secondary_lifetime 7
set g_balance_fireball_secondary_refire 2
-set g_balance_fireball_secondary_refire2 0
-set g_balance_fireball_secondary_speed 650
+set g_balance_fireball_secondary_speed 900
+set g_balance_fireball_secondary_speed_up 100
+set g_balance_fireball_secondary_speed_z 0
set g_balance_fireball_secondary_spread 0
// }}}
+// {{{ seeker
+set g_balance_seeker_flac_ammo 0.5
+set g_balance_seeker_flac_animtime 0.1
+set g_balance_seeker_flac_damage 15
+set g_balance_seeker_flac_edgedamage 10
+set g_balance_seeker_flac_force 50
+set g_balance_seeker_flac_lifetime 0.1
+set g_balance_seeker_flac_lifetime_rand 0.05
+set g_balance_seeker_flac_radius 100
+set g_balance_seeker_flac_refire 0.1
+set g_balance_seeker_flac_speed 3000
+set g_balance_seeker_flac_speed_up 1000
+set g_balance_seeker_flac_speed_z 0
+set g_balance_seeker_flac_spread 0.4
+set g_balance_seeker_missile_accel 1.05
+set g_balance_seeker_missile_ammo 2
+set g_balance_seeker_missile_animtime 0.3
+set g_balance_seeker_missile_count 4
+set g_balance_seeker_missile_damage 40
+set g_balance_seeker_missile_damageforcescale 4
+set g_balance_seeker_missile_decel 0.9
+set g_balance_seeker_missile_delay 0.25
+set g_balance_seeker_missile_edgedamage 10
+set g_balance_seeker_missile_force 250
+set g_balance_seeker_missile_health 5
+set g_balance_seeker_missile_lifetime 15
+set g_balance_seeker_missile_proxy 0
+set g_balance_seeker_missile_proxy_delay 0.2
+set g_balance_seeker_missile_proxy_maxrange 45
+set g_balance_seeker_missile_radius 80
+set g_balance_seeker_missile_refire 0.5
+set g_balance_seeker_missile_smart 1
+set g_balance_seeker_missile_smart_mindist 800
+set g_balance_seeker_missile_smart_trace_max 2500
+set g_balance_seeker_missile_smart_trace_min 1000
+set g_balance_seeker_missile_speed 700
+set g_balance_seeker_missile_speed_accel 0
+set g_balance_seeker_missile_speed_up 300
+set g_balance_seeker_missile_speed_z 0
+set g_balance_seeker_missile_speed_max 1250
+set g_balance_seeker_missile_spread 0
+set g_balance_seeker_missile_turnrate 0.65
+set g_balance_seeker_tag_ammo 1
+set g_balance_seeker_tag_animtime 0.3
+set g_balance_seeker_tag_damageforcescale 4
+set g_balance_seeker_tag_health 5
+set g_balance_seeker_tag_lifetime 15
+set g_balance_seeker_tag_refire 0.7
+set g_balance_seeker_tag_speed 9000
+set g_balance_seeker_tag_spread 0
+// End new seeker
+++ /dev/null
-// {{{ weapon replacement
-// NOTE: this only replaces weapons on the map
-// use g_start_weapon_* to also replace the on-startup weapons!
-// example: g_weaponreplace_nex "nex minstanex", then Nexes become MinstaNexes 50% of the times
-// set the cvars to "0" to totally disable a weapon
-set g_weaponreplace_laser ""
-set g_weaponreplace_shotgun "uzi"
-set g_weaponreplace_uzi "shotgun"
-set g_weaponreplace_grenadelauncher ""
-set g_weaponreplace_electro ""
-set g_weaponreplace_crylink ""
-set g_weaponreplace_nex ""
-set g_weaponreplace_hagar ""
-set g_weaponreplace_rocketlauncher ""
-set g_weaponreplace_porto ""
-set g_weaponreplace_minstanex ""
-set g_weaponreplace_hook 0
-set g_weaponreplace_hlac 0
-set g_weaponreplace_campingrifle 0
-set g_weaponreplace_tuba ""
-set g_weaponreplace_fireball 0
-set sv_q3acompat_machineshotgunswap 0
-// }}}
-
-// {{{ starting gear
-set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_shotgun -2 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_uzi 1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_hlac 0 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_campingrifle 0 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_balance_health_start 125
-set g_balance_armor_start 0
-set g_start_ammo_shells 0
-set g_start_ammo_nails 100
-set g_start_ammo_rockets 0
-set g_start_ammo_cells 0
-set g_start_ammo_fuel 0
-set g_warmup_start_health 200 "starting values when being in warmup-stage"
-set g_warmup_start_armor 100 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_shells 50 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_nails 150 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_rockets 50 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_cells 50 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage"
-set g_lms_start_health 200
-set g_lms_start_armor 100
-set g_lms_start_ammo_shells 30
-set g_lms_start_ammo_nails 210
-set g_lms_start_ammo_rockets 150
-set g_lms_start_ammo_cells 150
-set g_lms_start_ammo_fuel 0
-set g_balance_nixnex_roundtime 25
-set g_balance_nixnex_incrtime 1.6
-set g_balance_nixnex_ammo_shells 15
-set g_balance_nixnex_ammo_nails 45
-set g_balance_nixnex_ammo_rockets 15
-set g_balance_nixnex_ammo_cells 15
-set g_balance_nixnex_ammo_fuel 0
-set g_balance_nixnex_ammoincr_shells 2
-set g_balance_nixnex_ammoincr_nails 6
-set g_balance_nixnex_ammoincr_rockets 2
-set g_balance_nixnex_ammoincr_cells 2
-set g_balance_nixnex_ammoincr_fuel 2
-// }}}
-
-// {{{ pickup items
-set g_pickup_shells 10
-set g_pickup_shells_max 30
-set g_pickup_nails 30
-set g_pickup_nails_max 210
-set g_pickup_rockets 20
-set g_pickup_rockets_max 150
-set g_pickup_cells 50
-set g_pickup_cells_max 150
-set g_pickup_fuel 25
-set g_pickup_fuel_jetpack 50
-set g_pickup_fuel_max 999
-set g_pickup_armorsmall 5
-set g_pickup_armorsmall_max 200
-set g_pickup_armormedium 25
-set g_pickup_armormedium_max 200
-set g_pickup_armorbig 50
-set g_pickup_armorbig_max 200
-set g_pickup_armorlarge 100
-set g_pickup_armorlarge_max 200
-set g_pickup_healthsmall 5
-set g_pickup_healthsmall_max 200
-set g_pickup_healthmedium 25
-set g_pickup_healthmedium_max 100
-set g_pickup_healthlarge 50
-set g_pickup_healthlarge_max 100
-set g_pickup_healthmega 100
-set g_pickup_healthmega_max 200
-set g_pickup_respawntime_short 30
-set g_pickup_respawntime_medium 30
-set g_pickup_respawntime_long 30
-set g_pickup_respawntime_powerup 90
-set g_pickup_respawntime_weapon 5
-set g_pickup_respawntime_ammo 30
-set g_pickup_respawntimejitter_short 0
-set g_pickup_respawntimejitter_medium 0
-set g_pickup_respawntimejitter_long 0
-set g_pickup_respawntimejitter_powerup 15
-set g_pickup_respawntimejitter_weapon 0
-set g_pickup_respawntimejitter_ammo 0
-// }}}
-
-// {{{ regen/rot
-set g_balance_health_regen 0
-set g_balance_health_regenlinear 0
-set g_balance_pause_health_regen 0
-set g_balance_pause_health_regen_spawn 0
-set g_balance_health_rot 0
-set g_balance_health_rotlinear 1
-set g_balance_pause_health_rot 1
-set g_balance_pause_health_rot_spawn 0
-set g_balance_health_regenstable 100
-set g_balance_health_rotstable 100
-set g_balance_health_limit 999
-set g_balance_armor_regen 0
-set g_balance_armor_regenlinear 0
-set g_balance_armor_rot 0
-set g_balance_armor_rotlinear 1
-set g_balance_pause_armor_rot 1
-set g_balance_pause_armor_rot_spawn 0
-set g_balance_armor_regenstable 100
-set g_balance_armor_rotstable 100
-set g_balance_armor_limit 999
-set g_balance_armor_blockpercent 0.66
-
-set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)"
-set g_balance_fuel_regenlinear 0
-set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter
-set g_balance_fuel_rot 0.05
-set g_balance_fuel_rotlinear 0
-set g_balance_pause_fuel_rot 5
-set g_balance_pause_fuel_rot_spawn 10
-set g_balance_fuel_regenstable 50
-set g_balance_fuel_rotstable 100
-set g_balance_fuel_limit 999
-// }}}
-
-// {{{ misc
-set g_balance_selfdamagepercent 0.75
-set g_balance_weaponswitchdelay 0.1
-set g_weaponspeedfactor 1 "weapon projectile speed multiplier"
-set g_weaponratefactor 1 "weapon fire rate multiplier"
-set g_weapondamagefactor 1 "weapon damage multiplier"
-set g_weaponforcefactor 1 "weapon force multiplier"
-set g_weaponspreadfactor 1 "weapon spread multiplier"
-set g_balance_firetransfer_time 0.9
-set g_balance_firetransfer_damage 0.8
-set g_throughfloor_damage 0.5
-set g_throughfloor_force 0.7
-set g_projectiles_newton_style 0
-// possible values:
-// 0: absolute velocity projectiles (like Quake)
-// 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
-// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
-// 3: absolute velocity + player velocity component in shot direction (note: does NOT yield the right relative velocity, but may be good enough, but it is somewhat prone to sniper rockets)
-// 4: just add the player velocity length to the absolute velocity (tZork's sniper rockets)
-set g_projectiles_newton_style_2_minfactor 0.7
-set g_projectiles_newton_style_2_maxfactor 5
-set g_projectiles_spread_style 4
-// possible values:
-// 0: forward + solid sphere (like Quake) - varies velocity
-// 1: forward + flattened solid sphere
-// 2: forward + solid circle
-// 3: forward + normal distribution 3D - varies velocity
-// 4: forward + normal distribution on a plane
-// 5: forward + circle with 1-r falloff
-// 6: forward + circle with 1-r^2 falloff
-// 7: forward + circle with (1-r)(2-r) falloff
-set g_balance_falldamage_deadminspeed 150
-set g_balance_falldamage_minspeed 675
-set g_balance_falldamage_factor 0.25
-set g_balance_falldamage_maxdamage 10
-// }}}
-
-// {{{ powerups
-set g_balance_powerup_invincible_takedamage 0.25
-set g_balance_powerup_invincible_time 30
-set g_balance_powerup_strength_damage 4
-set g_balance_powerup_strength_force 4
-set g_balance_powerup_strength_time 30
-set g_balance_powerup_strength_selfdamage 2
-set g_balance_powerup_strength_selfforce 2
-// }}}
-
-// {{{ jetpack/hook
-set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack"
-set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction"
-set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)"
-set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction"
-set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction"
-set g_jetpack_fuel 8 "fuel per second for jetpack"
-set g_jetpack_attenuation 2 "jetpack sound attenuation"
-
-set g_grappling_hook_tarzan 2 // 2: can also pull players
-set g_balance_grapplehook_speed_fly 1800
-set g_balance_grapplehook_speed_pull 2000
-set g_balance_grapplehook_force_rubber 2000
-set g_balance_grapplehook_force_rubber_overstretch 1000
-set g_balance_grapplehook_length_min 50
-set g_balance_grapplehook_stretch 50
-set g_balance_grapplehook_airfriction 0.2
-set g_balance_grapplehook_health 130
-// }}}
-
-// {{{ weapon properties
-// {{{ laser
-set g_balance_laser_primary_damage 22
-set g_balance_laser_primary_edgedamage 0
-set g_balance_laser_primary_force 200
-set g_balance_laser_primary_radius 52
-set g_balance_laser_primary_speed 0
-set g_balance_laser_primary_spread 0
-set g_balance_laser_primary_refire 0.1
-set g_balance_laser_primary_animtime 0.1
-set g_balance_laser_primary_lifetime 0
-set g_balance_laser_primary_shotangle 0
-set g_balance_laser_primary_delay 0
-set g_balance_laser_gauntlet 1
-set g_balance_laser_secondary 0 // when 1, a secondary laser mode exists
-set g_balance_laser_secondary_damage 30
-set g_balance_laser_secondary_edgedamage 0
-set g_balance_laser_secondary_force 100
-set g_balance_laser_secondary_radius 3
-set g_balance_laser_secondary_speed 1500
-set g_balance_laser_secondary_spread 0
-set g_balance_laser_secondary_refire 0
-set g_balance_laser_secondary_animtime 0.15
-set g_balance_laser_secondary_lifetime 0.066
-set g_balance_laser_secondary_shotangle 0
-set g_balance_laser_secondary_delay 0
-// }}}
-// {{{ shotgun
-set g_balance_shotgun_primary_bullets 36
-set g_balance_shotgun_primary_damage 3
-set g_balance_shotgun_primary_force 10
-set g_balance_shotgun_primary_spread 0.18
-set g_balance_shotgun_primary_refire 1
-set g_balance_shotgun_primary_animtime 0.7
-set g_balance_shotgun_primary_ammo 1
-set g_balance_shotgun_primary_speed 12000
-set g_balance_shotgun_primary_bulletconstant 75 // 3.8qu
-set g_balance_shotgun_secondary 0
-set g_balance_shotgun_secondary_bullets 22
-set g_balance_shotgun_secondary_damage 2
-set g_balance_shotgun_secondary_force 12
-set g_balance_shotgun_secondary_spread 0.25
-set g_balance_shotgun_secondary_refire 1.5
-set g_balance_shotgun_secondary_animtime 0.2
-set g_balance_shotgun_secondary_ammo 0.5
-set g_balance_shotgun_secondary_speed 12000
-set g_balance_shotgun_secondary_bulletconstant 75 // 3.8qu
-// }}}
-// {{{ uzi
-set g_balance_uzi_first 0
-set g_balance_uzi_first_damage 10
-set g_balance_uzi_first_force 50
-set g_balance_uzi_first_spread 0.007
-set g_balance_uzi_first_refire 0.15
-set g_balance_uzi_first_ammo 1
-set g_balance_uzi_sustained_damage 7
-set g_balance_uzi_sustained_force 30
-set g_balance_uzi_sustained_spread 0.02
-set g_balance_uzi_sustained_refire 0.1
-set g_balance_uzi_sustained_ammo 1
-set g_balance_uzi_speed 18000
-set g_balance_uzi_bulletconstant 115 // 13.1qu
-// }}}
-// {{{ mortar
-set g_balance_grenadelauncher_primary2secondary 1
-set g_balance_grenadelauncher_primary_damage 60
-set g_balance_grenadelauncher_primary_edgedamage 10
-set g_balance_grenadelauncher_primary_force 250
-set g_balance_grenadelauncher_primary_radius 100
-set g_balance_grenadelauncher_primary_speed 2000
-set g_balance_grenadelauncher_primary_speed_up 200
-set g_balance_grenadelauncher_primary_speed_z 0
-set g_balance_grenadelauncher_primary_spread 0
-set g_balance_grenadelauncher_primary_lifetime 5
-set g_balance_grenadelauncher_primary_refire 0.7
-set g_balance_grenadelauncher_primary_animtime 0.3
-set g_balance_grenadelauncher_primary_ammo 2
-set g_balance_grenadelauncher_secondary_damage 65
-set g_balance_grenadelauncher_secondary_edgedamage 10
-set g_balance_grenadelauncher_secondary_force 300
-set g_balance_grenadelauncher_secondary_radius 200
-set g_balance_grenadelauncher_secondary_speed 800
-set g_balance_grenadelauncher_secondary_speed_up 0
-set g_balance_grenadelauncher_secondary_speed_z 200
-set g_balance_grenadelauncher_secondary_spread 0
-set g_balance_grenadelauncher_secondary_lifetime 2
-set g_balance_grenadelauncher_secondary_refire 0.8
-set g_balance_grenadelauncher_secondary_animtime 0.5
-set g_balance_grenadelauncher_secondary_ammo 2
-set g_balance_grenadelauncher_secondary_health 0
-set g_balance_grenadelauncher_secondary_damageforcescale 0
-// }}}
-// {{{ electro
-set g_balance_electro_lightning 1
-set g_balance_electro_primary_damage 6
-set g_balance_electro_primary_edgedamage 0
-set g_balance_electro_primary_force 60 // todo: probaby needs movement nerfing code when hit?
-set g_balance_electro_primary_radius 850
-set g_balance_electro_primary_comboradius 0
-set g_balance_electro_primary_speed 0
-set g_balance_electro_primary_spread 0
-set g_balance_electro_primary_lifetime 0
-set g_balance_electro_primary_refire 0.066
-set g_balance_electro_primary_animtime 0.066
-set g_balance_electro_primary_ammo 0.66
-set g_balance_electro_secondary_damage 45
-set g_balance_electro_secondary_spread 0.10
-set g_balance_electro_secondary_edgedamage 10
-set g_balance_electro_secondary_force 100
-set g_balance_electro_secondary_radius 150
-set g_balance_electro_secondary_speed 900
-set g_balance_electro_secondary_speed_up 200
-set g_balance_electro_secondary_speed_z 0
-set g_balance_electro_secondary_spread 0.05
-set g_balance_electro_secondary_lifetime 2.5
-set g_balance_electro_secondary_refire 0.1
-set g_balance_electro_secondary_refire2 2
-set g_balance_electro_secondary_animtime 0.2
-set g_balance_electro_secondary_ammo 2
-set g_balance_electro_secondary_health 5
-set g_balance_electro_secondary_damageforcescale 4
-set g_balance_electro_secondary_count 3
-set g_balance_electro_combo_damage 50
-set g_balance_electro_combo_edgedamage 0
-set g_balance_electro_combo_force 100
-set g_balance_electro_combo_radius 250
-set g_balance_electro_combo_comboradius 0
-set g_balance_electro_combo_speed 2000
-// }}}
-// {{{ crylink
-set g_balance_crylink_primary_damage 18
-set g_balance_crylink_primary_edgedamage 18
-set g_balance_crylink_primary_force 40
-set g_balance_crylink_primary_radius 110
-set g_balance_crylink_primary_speed 1800
-set g_balance_crylink_primary_spread 0.01
-set g_balance_crylink_primary_shots 4
-set g_balance_crylink_primary_bounces 0
-set g_balance_crylink_primary_refire 0.4
-set g_balance_crylink_primary_animtime 0.4
-set g_balance_crylink_primary_ammo 2
-set g_balance_crylink_primary_bouncedamagefactor 0.5
-
-set g_balance_crylink_primary_middle_lifetime 5 // range: 35000 full, fades to 70000
-set g_balance_crylink_primary_middle_fadetime 5
-set g_balance_crylink_primary_star_lifetime 0.1 // range: 700 full, fades to 2450
-set g_balance_crylink_primary_star_fadetime 0.25
-set g_balance_crylink_primary_other_lifetime 0.1 // range: 700 full, fades to 2450
-set g_balance_crylink_primary_other_fadetime 0.25
-
-set g_balance_crylink_secondary 0
-set g_balance_crylink_secondary_damage 8
-set g_balance_crylink_secondary_edgedamage 8
-set g_balance_crylink_secondary_force -40
-set g_balance_crylink_secondary_radius 10
-set g_balance_crylink_secondary_speed 4000
-set g_balance_crylink_secondary_spread 0.01
-set g_balance_crylink_secondary_shots 3
-set g_balance_crylink_secondary_bounces 0
-set g_balance_crylink_secondary_refire 0.1
-set g_balance_crylink_secondary_animtime 0.1
-set g_balance_crylink_secondary_ammo 1
-set g_balance_crylink_secondary_bouncedamagefactor 0.5
-
-set g_balance_crylink_secondary_middle_lifetime 5 // range: 35000 full, fades to 70000
-set g_balance_crylink_secondary_middle_fadetime 5
-set g_balance_crylink_secondary_line_lifetime 2 // range: 35000 full, fades to 70000
-set g_balance_crylink_secondary_line_fadetime 2
-// }}}
-// {{{ nex
-set g_balance_nex_damage 100
-set g_balance_nex_force 200
-set g_balance_nex_refire 1.25
-set g_balance_nex_animtime 0.8
-set g_balance_nex_ammo 5
-set g_balance_nex_damagefalloff_mindist 1000
-set g_balance_nex_damagefalloff_maxdist 3000
-set g_balance_nex_damagefalloff_halflife 1500
-set g_balance_nex_damagefalloff_forcehalflife 1500
-// }}}
-// {{{ minstanex
-set g_balance_minstanex_refire 1
-set g_balance_minstanex_animtime 1
-set g_balance_minstanex_ammo 10
-// }}}
-// {{{ hagar
-set g_balance_hagar_primary_damage 12
-set g_balance_hagar_primary_edgedamage 5
-set g_balance_hagar_primary_force 70
-set g_balance_hagar_primary_radius 50
-set g_balance_hagar_primary_spread 0
-set g_balance_hagar_primary_speed 1800
-set g_balance_hagar_primary_lifetime 5
-set g_balance_hagar_primary_refire 0.1
-set g_balance_hagar_primary_ammo 1
-set g_balance_hagar_secondary 0
-set g_balance_hagar_secondary_damage 11
-set g_balance_hagar_secondary_edgedamage 4
-set g_balance_hagar_secondary_force 60
-set g_balance_hagar_secondary_radius 70
-set g_balance_hagar_secondary_spread 0.05
-set g_balance_hagar_secondary_speed 1800
-set g_balance_hagar_secondary_lifetime_min 5
-set g_balance_hagar_secondary_lifetime_rand 0
-set g_balance_hagar_secondary_refire 0.1
-set g_balance_hagar_secondary_ammo 1
-// }}}
-// {{{ rocketlauncher
-set g_balance_rocketlauncher_damage 90
-set g_balance_rocketlauncher_edgedamage 30
-set g_balance_rocketlauncher_force 350
-set g_balance_rocketlauncher_radius 110
-set g_balance_rocketlauncher_speed 1000
-set g_balance_rocketlauncher_speedaccel 0
-set g_balance_rocketlauncher_speedstart 1000
-set g_balance_rocketlauncher_lifetime 10
-set g_balance_rocketlauncher_refire 0.9
-set g_balance_rocketlauncher_animtime 0.7
-set g_balance_rocketlauncher_ammo 3
-set g_balance_rocketlauncher_health 0
-set g_balance_rocketlauncher_damageforcescale 0
-set g_balance_rocketlauncher_detonatedelay 9999 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time
-set g_balance_rocketlauncher_guiderate 0 // max degrees per second
-set g_balance_rocketlauncher_guideratedelay 0.01 // immediate
-set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic)
-set g_balance_rocketlauncher_guidedelay 0.15 // delay before guiding kicks in
-set g_balance_rocketlauncher_guidestop 1 // stop guiding when firing again
-set g_balance_rocketlauncher_laserguided_speed 1000 //650
-set g_balance_rocketlauncher_laserguided_speedaccel 0
-set g_balance_rocketlauncher_laserguided_speedstart 1000
-set g_balance_rocketlauncher_laserguided_turnrate 0.75 //0.5
-set g_balance_rocketlauncher_laserguided_allow_steal 1
-// }}}
-// {{{ porto
-set g_balance_porto_primary_refire 1.5
-set g_balance_porto_primary_animtime 0.3
-set g_balance_porto_primary_speed 5000
-set g_balance_porto_primary_lifetime 30
-set g_balance_portal_health 200 // these get recharged whenever the portal is used
-set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used
-// }}}
-// {{{ hook
-set g_balance_hook_primary_fuel 2 // hook monkeys set 0
-set g_balance_hook_primary_refire 0 // hook monkeys set 0
-set g_balance_hook_primary_animtime 0.3 // good shoot anim
-set g_balance_hook_primary_hooked_time_max 0 // infinite
-set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free
-set g_balance_hook_primary_hooked_fuel 3 // fuel per second hooked
-set g_balance_hook_secondary_damage 25 // not much
-set g_balance_hook_secondary_edgedamage 5 // not much
-set g_balance_hook_secondary_radius 500 // LOTS
-set g_balance_hook_secondary_force -2000 // LOTS
-set g_balance_hook_secondary_ammo 50 // a whole pack
-set g_balance_hook_secondary_lifetime 10 // infinite
-set g_balance_hook_secondary_speed 0 // not much throwing
-set g_balance_hook_secondary_gravity 5 // fast falling
-set g_balance_hook_secondary_refire 3 // don't drop too many bombs...
-set g_balance_hook_secondary_animtime 0.3 // good shoot anim
-set g_balance_hook_secondary_power 3 // effect behaves like a square function
-set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds
-// }}}
-// {{{ hlac
-set g_balance_hlac_primary_spread_min 0.01
-set g_balance_hlac_primary_spread_max 0.03
-set g_balance_hlac_primary_spread_add 0.002
-set g_balance_hlac_primary_spread_crouchmod 0.5
-
-set g_balance_hlac_primary_damage 6
-set g_balance_hlac_primary_edgedamage 0
-set g_balance_hlac_primary_force 60 // todo: probably needs movement nerfing code when hit
-set g_balance_hlac_primary_radius 850
-set g_balance_hlac_primary_speed 0
-set g_balance_hlac_primary_lifetime 0
-
-set g_balance_hlac_primary_refire 0.066
-set g_balance_hlac_primary_animtime 0.066
-set g_balance_hlac_primary_ammo 0.066
-
-set g_balance_hlac_secondary 0
-set g_balance_hlac_secondary_spread 0.06
-set g_balance_hlac_secondary_spread_crouchmod 0.5
-
-set g_balance_hlac_secondary_damage 11
-set g_balance_hlac_secondary_edgedamage 10
-set g_balance_hlac_secondary_force 60
-set g_balance_hlac_secondary_radius 70
-set g_balance_hlac_secondary_speed 20000
-set g_balance_hlac_secondary_lifetime 5
-
-set g_balance_hlac_secondary_refire 0.6
-set g_balance_hlac_secondary_animtime 0.6
-set g_balance_hlac_secondary_ammo 10
-set g_balance_hlac_secondary_shots 5
-// }}}
-// {{{ campingrifle
-set g_balance_campingrifle_magazinecapacity 0
-set g_balance_campingrifle_reloadtime 2 // matches reload anim
-set g_balance_campingrifle_auto_reload_after_changing_weapons 0
-set g_balance_campingrifle_bursttime 0.85 // 0.35 - 0.1 + 0.35 - 0.1 + 0.35 = three secondaries
-set g_balance_campingrifle_tracer 1
-set g_balance_campingrifle_primary_damage 50
-set g_balance_campingrifle_primary_headshotaddeddamage 80
-set g_balance_campingrifle_primary_spread 0
-set g_balance_campingrifle_primary_force 0
-set g_balance_campingrifle_primary_speed 35000
-set g_balance_campingrifle_primary_lifetime 5
-set g_balance_campingrifle_primary_refire 0.7
-set g_balance_campingrifle_primary_animtime 0.7
-set g_balance_campingrifle_primary_ammo 10
-set g_balance_campingrifle_primary_bulletconstant 130 // 56.3qu
-set g_balance_campingrifle_primary_burstcost 0.35 // require same cooldown as secondary, note it's smaller than primary refire time
-set g_balance_campingrifle_secondary_damage 15
-set g_balance_campingrifle_secondary_headshotaddeddamage 25
-set g_balance_campingrifle_secondary_spread 0.02
-set g_balance_campingrifle_secondary_force 0
-set g_balance_campingrifle_secondary_speed 20000
-set g_balance_campingrifle_secondary_lifetime 5
-set g_balance_campingrifle_secondary_refire 0.1
-set g_balance_campingrifle_secondary_animtime 0.1
-set g_balance_campingrifle_secondary_ammo 4
-set g_balance_campingrifle_secondary_bulletconstant 130 // 18.3qu
-set g_balance_campingrifle_secondary_burstcost 0.35
-// }}}
-// {{{ tuba
-set g_balance_tuba_refire 0.05
-set g_balance_tuba_animtime 0.05
-set g_balance_tuba_attenuation 0.5
-set g_balance_tuba_volume 1
-set g_balance_tuba_fadetime 0.25
-set g_balance_tuba_damage 5
-set g_balance_tuba_edgedamage 0
-set g_balance_tuba_radius 200
-set g_balance_tuba_force 40
-// }}}
-// {{{ fireball
-set g_balance_fireball_primary_ammo 5
-set g_balance_fireball_primary_animtime 0.3
-set g_balance_fireball_primary_damage 40
-set g_balance_fireball_primary_damageforcescale 4
-set g_balance_fireball_primary_damagetime 5
-set g_balance_fireball_primary_force 100
-set g_balance_fireball_primary_laserburntime 0.5
-set g_balance_fireball_primary_laserdamage 30
-set g_balance_fireball_primary_laseredgedamage 20
-set g_balance_fireball_primary_laserradius 110
-set g_balance_fireball_primary_lifetime 7
-set g_balance_fireball_primary_refire 2
-set g_balance_fireball_primary_speed 900
-set g_balance_fireball_primary_spread 0
-set g_balance_fireball_primary_speed_up 100
-set g_balance_fireball_primary_speed_z 0
-set g_balance_fireball_secondary_ammo 25
-set g_balance_fireball_secondary_animtime 0.15
-set g_balance_fireball_secondary_bfgdamage 100
-set g_balance_fireball_secondary_bfgforce 500
-set g_balance_fireball_secondary_bfgradius 750
-set g_balance_fireball_secondary_damage 150
-set g_balance_fireball_secondary_damageforcescale 4
-set g_balance_fireball_secondary_edgedamage 0
-set g_balance_fireball_secondary_force 700
-set g_balance_fireball_secondary_health 50
-set g_balance_fireball_secondary_laserburntime 0.5
-set g_balance_fireball_secondary_laserdamage 30
-set g_balance_fireball_secondary_laseredgedamage 20
-set g_balance_fireball_secondary_laserradius 256
-set g_balance_fireball_secondary_lifetime 15
-set g_balance_fireball_secondary_radius 200
-set g_balance_fireball_secondary_refire 0
-set g_balance_fireball_secondary_refire2 4
-set g_balance_fireball_secondary_speed 650
-set g_balance_fireball_secondary_spread 0
-// }}}
-// {{{ weapon replacement
-// NOTE: this only replaces weapons on the map
-// use g_start_weapon_* to also replace the on-startup weapons!
-// example: g_weaponreplace_nex "nex minstanex", then Nexes become MinstaNexes 50% of the times
-// set the cvars to "0" to totally disable a weapon
-set sv_q3acompat_machineshotgunswap 0 "shorthand for swapping uzi and shotgun"
-set g_weaponreplace_laser ""
-set g_weaponreplace_shotgun ""
-set g_weaponreplace_uzi ""
-set g_weaponreplace_grenadelauncher ""
-set g_weaponreplace_electro ""
-set g_weaponreplace_crylink ""
-set g_weaponreplace_nex ""
-set g_weaponreplace_hagar ""
-set g_weaponreplace_rocketlauncher ""
-set g_weaponreplace_porto ""
-set g_weaponreplace_minstanex ""
-set g_weaponreplace_hook ""
-set g_weaponreplace_hlac 0 // I don't particularly like this weapon.
-set g_weaponreplace_campingrifle ""
-set g_weaponreplace_tuba ""
-set g_weaponreplace_fireball 0 // Don't kill me div0, just for now until I figure out a good balance for it.
-set sv_q3acompat_machineshotgunswap 0 "shorthand for swapping uzi and shotgun (for Q3A map compatibility)"
-// }}}
-
// {{{ starting gear
set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
set g_start_weapon_campingrifle -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
set g_start_weapon_fireball 0 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_balance_health_start 100
+set g_start_weapon_seeker 0 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_balance_health_start 125
set g_balance_armor_start 0
-set g_start_ammo_shells 45
+set g_start_ammo_shells 30
set g_start_ammo_nails 0
set g_start_ammo_rockets 0
set g_start_ammo_cells 0
set g_warmup_start_ammo_cells 50 "starting values when being in warmup-stage"
set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage"
set g_lms_start_health 200
-set g_lms_start_armor 100
-set g_lms_start_ammo_shells 50
-set g_lms_start_ammo_nails 150
-set g_lms_start_ammo_rockets 50
-set g_lms_start_ammo_cells 50
+set g_lms_start_armor 200
+set g_lms_start_ammo_shells 120
+set g_lms_start_ammo_nails 400
+set g_lms_start_ammo_rockets 120
+set g_lms_start_ammo_cells 200
set g_lms_start_ammo_fuel 0
-set g_balance_nixnex_roundtime 25
-set g_balance_nixnex_incrtime 1.6
-set g_balance_nixnex_ammo_shells 15
-set g_balance_nixnex_ammo_nails 45
-set g_balance_nixnex_ammo_rockets 15
-set g_balance_nixnex_ammo_cells 15
-set g_balance_nixnex_ammo_fuel 0
-set g_balance_nixnex_ammoincr_shells 2
-set g_balance_nixnex_ammoincr_nails 6
-set g_balance_nixnex_ammoincr_rockets 2
-set g_balance_nixnex_ammoincr_cells 2
-set g_balance_nixnex_ammoincr_fuel 2
+set g_balance_nix_roundtime 25
+set g_balance_nix_incrtime 1.6
+set g_balance_nix_ammo_shells 120
+set g_balance_nix_ammo_nails 400
+set g_balance_nix_ammo_rockets 120
+set g_balance_nix_ammo_cells 200
+set g_balance_nix_ammo_fuel 0
+set g_balance_nix_ammoincr_shells 2
+set g_balance_nix_ammoincr_nails 6
+set g_balance_nix_ammoincr_rockets 2
+set g_balance_nix_ammoincr_cells 2
+set g_balance_nix_ammoincr_fuel 2
// }}}
// {{{ pickup items
+set g_pickup_ammo_anyway 1
+set g_pickup_weapons_anyway 1
set g_pickup_shells 30
set g_pickup_shells_max 120
set g_pickup_nails 80
set g_pickup_fuel_jetpack 50
set g_pickup_fuel_max 999
set g_pickup_armorsmall 10
-set g_pickup_armorsmall_max 100
+set g_pickup_armorsmall_max 200
+set g_pickup_armorsmall_anyway 1
set g_pickup_armormedium 25
-set g_pickup_armormedium_max 100
+set g_pickup_armormedium_max 200
+set g_pickup_armormedium_anyway 1
set g_pickup_armorbig 50
-set g_pickup_armorbig_max 100
+set g_pickup_armorbig_max 200
+set g_pickup_armorbig_anyway 1
set g_pickup_armorlarge 100
-set g_pickup_armorlarge_max 100
+set g_pickup_armorlarge_max 200
+set g_pickup_armorlarge_anyway 1
set g_pickup_healthsmall 10
set g_pickup_healthsmall_max 200
+set g_pickup_healthsmall_anyway 1
set g_pickup_healthmedium 25
set g_pickup_healthmedium_max 200
+set g_pickup_healthmedium_anyway 1
set g_pickup_healthlarge 50
set g_pickup_healthlarge_max 200
+set g_pickup_healthlarge_anyway 1
set g_pickup_healthmega 100
set g_pickup_healthmega_max 200
+set g_pickup_healthmega_anyway 1
set g_pickup_respawntime_short 15
set g_pickup_respawntime_medium 20
set g_pickup_respawntime_long 30
set g_balance_armor_regen 0
set g_balance_armor_regenlinear 0
set g_balance_armor_rot 0
-set g_balance_armor_rotlinear 0
+set g_balance_armor_rotlinear 3
set g_balance_pause_armor_rot 1
set g_balance_pause_armor_rot_spawn 1
set g_balance_armor_regenstable 100
// }}}
// {{{ misc
-set g_balance_selfdamagepercent 0.6
+set g_balance_selfdamagepercent 0.75
set g_balance_weaponswitchdelay 0.15
set g_weaponspeedfactor 1 "weapon projectile speed multiplier"
set g_weaponratefactor 1 "weapon fire rate multiplier"
// {{{ shotgun
set g_balance_shotgun_primary_bullets 6
set g_balance_shotgun_primary_damage 8
-set g_balance_shotgun_primary_force 0
+set g_balance_shotgun_primary_force 15
set g_balance_shotgun_primary_spread 0.11
set g_balance_shotgun_primary_refire 0.5
set g_balance_shotgun_primary_animtime 0.2
set g_balance_shotgun_secondary 1
set g_balance_shotgun_secondary_bullets 6
set g_balance_shotgun_secondary_damage 8
-set g_balance_shotgun_secondary_force 0
+set g_balance_shotgun_secondary_force 15
set g_balance_shotgun_secondary_spread 0.17
set g_balance_shotgun_secondary_refire 1.35
set g_balance_shotgun_secondary_animtime 0.2
// {{{ uzi
set g_balance_uzi_first 1
set g_balance_uzi_first_damage 12
-set g_balance_uzi_first_force 0
+set g_balance_uzi_first_force 5
set g_balance_uzi_first_spread 0.015
set g_balance_uzi_first_refire 0.15
set g_balance_uzi_first_ammo 1
set g_balance_uzi_sustained_damage 7
-set g_balance_uzi_sustained_force 0
+set g_balance_uzi_sustained_force 5
set g_balance_uzi_sustained_spread 0.05
set g_balance_uzi_sustained_refire 0.075
set g_balance_uzi_sustained_ammo 1
set g_balance_grenadelauncher_secondary_ammo 2
set g_balance_grenadelauncher_secondary_health 70
set g_balance_grenadelauncher_secondary_damageforcescale 4
+set g_balance_grenadelauncher_secondary_bouncefactor 0.5
+set g_balance_grenadelauncher_secondary_bouncestop 0.075
// }}}
// {{{ electro
set g_balance_electro_lightning 0
set g_balance_crylink_primary_damage 14
set g_balance_crylink_primary_edgedamage 0
set g_balance_crylink_primary_force -55
-set g_balance_crylink_primary_radius 80
+set g_balance_crylink_primary_radius 50
set g_balance_crylink_primary_speed 7000
-set g_balance_crylink_primary_spread 0.01
+set g_balance_crylink_primary_spread 0.02
set g_balance_crylink_primary_shots 4
set g_balance_crylink_primary_bounces 1
set g_balance_crylink_primary_refire 0.4
set g_balance_crylink_secondary_bounces 0
set g_balance_crylink_secondary_refire 0.1
set g_balance_crylink_secondary_animtime 0.1
-set g_balance_crylink_secondary_ammo 1
+set g_balance_crylink_secondary_ammo 2
set g_balance_crylink_secondary_bouncedamagefactor 0.5
set g_balance_crylink_secondary_middle_lifetime 5 // range: 35000 full, fades to 70000
// }}}
// {{{ nex
set g_balance_nex_damage 90
-set g_balance_nex_force 200
+set g_balance_nex_force 300
set g_balance_nex_refire 1.5
set g_balance_nex_animtime 0.3
set g_balance_nex_ammo 5
set g_balance_rocketlauncher_ammo 3
set g_balance_rocketlauncher_health 40
set g_balance_rocketlauncher_damageforcescale 4
-set g_balance_rocketlauncher_detonatedelay -1 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time
+set g_balance_rocketlauncher_detonatedelay 0.05 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time
set g_balance_rocketlauncher_guiderate 140 // max degrees per second
set g_balance_rocketlauncher_guideratedelay 0.01 // immediate
set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic)
set g_balance_campingrifle_primary_damage 50
set g_balance_campingrifle_primary_headshotaddeddamage 50
set g_balance_campingrifle_primary_spread 0
-set g_balance_campingrifle_primary_force 0
+set g_balance_campingrifle_primary_force 50
set g_balance_campingrifle_primary_speed 35000
set g_balance_campingrifle_primary_lifetime 5
set g_balance_campingrifle_primary_refire 0.7
set g_balance_campingrifle_primary_ammo 10
set g_balance_campingrifle_primary_bulletconstant 130 // 56.3qu
set g_balance_campingrifle_primary_burstcost 0.35 // require same cooldown as secondary, note it's smaller than primary refire time
+set g_balance_campingrifle_primary_bullethail 0
set g_balance_campingrifle_secondary_damage 15
set g_balance_campingrifle_secondary_headshotaddeddamage 25
set g_balance_campingrifle_secondary_spread 0.02
-set g_balance_campingrifle_secondary_force 0
+set g_balance_campingrifle_secondary_force 30
set g_balance_campingrifle_secondary_speed 20000
set g_balance_campingrifle_secondary_lifetime 5
set g_balance_campingrifle_secondary_refire 0.1
set g_balance_campingrifle_secondary_ammo 4
set g_balance_campingrifle_secondary_bulletconstant 130 // 18.3qu
set g_balance_campingrifle_secondary_burstcost 0.35
+set g_balance_campingrifle_secondary_bullethail 0
// }}}
// {{{ tuba
set g_balance_tuba_refire 0.05
set g_balance_tuba_force 40
// }}}
// {{{ fireball
-set g_balance_fireball_primary_ammo 5
-set g_balance_fireball_primary_animtime 0.3
-set g_balance_fireball_primary_damage 40
+set g_balance_fireball_primary_ammo 40
+set g_balance_fireball_primary_animtime 0.15
+set g_balance_fireball_primary_bfgdamage 100
+set g_balance_fireball_primary_bfgforce 0
+set g_balance_fireball_primary_bfgradius 1000
+set g_balance_fireball_primary_damage 200
set g_balance_fireball_primary_damageforcescale 4
-set g_balance_fireball_primary_damagetime 5
-set g_balance_fireball_primary_force 100
+set g_balance_fireball_primary_edgedamage 0
+set g_balance_fireball_primary_force 700
+set g_balance_fireball_primary_health 50
set g_balance_fireball_primary_laserburntime 0.5
-set g_balance_fireball_primary_laserdamage 30
+set g_balance_fireball_primary_laserdamage 80
set g_balance_fireball_primary_laseredgedamage 20
-set g_balance_fireball_primary_laserradius 110
-set g_balance_fireball_primary_lifetime 7
-set g_balance_fireball_primary_refire 2
-set g_balance_fireball_primary_speed 900
-set g_balance_fireball_primary_speed_up 100
-set g_balance_fireball_primary_speed_z 0
+set g_balance_fireball_primary_laserradius 256
+set g_balance_fireball_primary_lifetime 15
+set g_balance_fireball_primary_radius 200
+set g_balance_fireball_primary_refire 5
+set g_balance_fireball_primary_refire2 0
+set g_balance_fireball_primary_speed 650
set g_balance_fireball_primary_spread 0
-set g_balance_fireball_secondary_ammo 25
-set g_balance_fireball_secondary_animtime 0.15
-set g_balance_fireball_secondary_bfgdamage 100
-set g_balance_fireball_secondary_bfgforce 500
-set g_balance_fireball_secondary_bfgradius 750
-set g_balance_fireball_secondary_damage 150
+set g_balance_fireball_secondary_ammo 5
+set g_balance_fireball_secondary_animtime 0.3
+set g_balance_fireball_secondary_damage 40
set g_balance_fireball_secondary_damageforcescale 4
-set g_balance_fireball_secondary_edgedamage 0
-set g_balance_fireball_secondary_force 700
-set g_balance_fireball_secondary_health 50
+set g_balance_fireball_secondary_damagetime 5
+set g_balance_fireball_secondary_force 100
set g_balance_fireball_secondary_laserburntime 0.5
-set g_balance_fireball_secondary_laserdamage 30
+set g_balance_fireball_secondary_laserdamage 50
set g_balance_fireball_secondary_laseredgedamage 20
-set g_balance_fireball_secondary_laserradius 256
-set g_balance_fireball_secondary_lifetime 15
-set g_balance_fireball_secondary_radius 200
-set g_balance_fireball_secondary_refire 0
-set g_balance_fireball_secondary_refire2 4
-set g_balance_fireball_secondary_speed 650
+set g_balance_fireball_secondary_laserradius 110
+set g_balance_fireball_secondary_lifetime 7
+set g_balance_fireball_secondary_refire 2
+set g_balance_fireball_secondary_speed 900
+set g_balance_fireball_secondary_speed_up 100
+set g_balance_fireball_secondary_speed_z 0
set g_balance_fireball_secondary_spread 0
// }}}
+// {{{ seeker
+set g_balance_seeker_flac_ammo 0.5
+set g_balance_seeker_flac_animtime 0.1
+set g_balance_seeker_flac_damage 15
+set g_balance_seeker_flac_edgedamage 10
+set g_balance_seeker_flac_force 50
+set g_balance_seeker_flac_lifetime 0.1
+set g_balance_seeker_flac_lifetime_rand 0.05
+set g_balance_seeker_flac_radius 100
+set g_balance_seeker_flac_refire 0.1
+set g_balance_seeker_flac_speed 3000
+set g_balance_seeker_flac_speed_up 1000
+set g_balance_seeker_flac_speed_z 0
+set g_balance_seeker_flac_spread 0.4
+set g_balance_seeker_missile_accel 1.05
+set g_balance_seeker_missile_ammo 2
+set g_balance_seeker_missile_animtime 0.3
+set g_balance_seeker_missile_count 4
+set g_balance_seeker_missile_damage 40
+set g_balance_seeker_missile_damageforcescale 4
+set g_balance_seeker_missile_decel 0.9
+set g_balance_seeker_missile_delay 0.25
+set g_balance_seeker_missile_edgedamage 10
+set g_balance_seeker_missile_force 250
+set g_balance_seeker_missile_health 5
+set g_balance_seeker_missile_lifetime 15
+set g_balance_seeker_missile_proxy 0
+set g_balance_seeker_missile_proxy_delay 0.2
+set g_balance_seeker_missile_proxy_maxrange 45
+set g_balance_seeker_missile_radius 80
+set g_balance_seeker_missile_refire 0.5
+set g_balance_seeker_missile_smart 1
+set g_balance_seeker_missile_smart_mindist 800
+set g_balance_seeker_missile_smart_trace_max 2500
+set g_balance_seeker_missile_smart_trace_min 1000
+set g_balance_seeker_missile_speed 700
+set g_balance_seeker_missile_speed_accel 0
+set g_balance_seeker_missile_speed_up 300
+set g_balance_seeker_missile_speed_z 0
+set g_balance_seeker_missile_speed_max 1250
+set g_balance_seeker_missile_spread 0
+set g_balance_seeker_missile_turnrate 0.65
+set g_balance_seeker_tag_ammo 1
+set g_balance_seeker_tag_animtime 0.3
+set g_balance_seeker_tag_damageforcescale 4
+set g_balance_seeker_tag_health 5
+set g_balance_seeker_tag_lifetime 15
+set g_balance_seeker_tag_refire 0.7
+set g_balance_seeker_tag_speed 9000
+set g_balance_seeker_tag_spread 0
+// End new seeker
--- /dev/null
+// {{{ starting gear
+set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_shotgun -2 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_uzi 1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_hlac 0 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_campingrifle 0 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_seeker 0 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_balance_health_start 125
+set g_balance_armor_start 0
+set g_start_ammo_shells 0
+set g_start_ammo_nails 100
+set g_start_ammo_rockets 0
+set g_start_ammo_cells 0
+set g_start_ammo_fuel 0
+set g_warmup_start_health 200 "starting values when being in warmup-stage"
+set g_warmup_start_armor 100 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_shells 50 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_nails 150 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_rockets 50 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_cells 50 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage"
+set g_lms_start_health 200
+set g_lms_start_armor 100
+set g_lms_start_ammo_shells 30
+set g_lms_start_ammo_nails 210
+set g_lms_start_ammo_rockets 150
+set g_lms_start_ammo_cells 150
+set g_lms_start_ammo_fuel 0
+set g_balance_nix_roundtime 25
+set g_balance_nix_incrtime 1.6
+set g_balance_nix_ammo_shells 15
+set g_balance_nix_ammo_nails 45
+set g_balance_nix_ammo_rockets 15
+set g_balance_nix_ammo_cells 15
+set g_balance_nix_ammo_fuel 0
+set g_balance_nix_ammoincr_shells 2
+set g_balance_nix_ammoincr_nails 6
+set g_balance_nix_ammoincr_rockets 2
+set g_balance_nix_ammoincr_cells 2
+set g_balance_nix_ammoincr_fuel 2
+// }}}
+
+// {{{ pickup items
+set g_pickup_ammo_anyway 0
+set g_pickup_weapons_anyway 0
+set g_pickup_shells 10
+set g_pickup_shells_max 30
+set g_pickup_nails 30
+set g_pickup_nails_max 210
+set g_pickup_rockets 20
+set g_pickup_rockets_max 150
+set g_pickup_cells 50
+set g_pickup_cells_max 150
+set g_pickup_fuel 25
+set g_pickup_fuel_jetpack 50
+set g_pickup_fuel_max 999
+set g_pickup_armorsmall 5
+set g_pickup_armorsmall_max 200
+set g_pickup_armorsmall_anyway 0
+set g_pickup_armormedium 25
+set g_pickup_armormedium_max 200
+set g_pickup_armormedium_anyway 0
+set g_pickup_armorbig 50
+set g_pickup_armorbig_max 200
+set g_pickup_armorbig_anyway 0
+set g_pickup_armorlarge 100
+set g_pickup_armorlarge_max 200
+set g_pickup_armorlarge_anyway 0
+set g_pickup_healthsmall 5
+set g_pickup_healthsmall_max 200
+set g_pickup_healthsmall_anyway 0
+set g_pickup_healthmedium 25
+set g_pickup_healthmedium_max 100
+set g_pickup_healthmedium_anyway 0
+set g_pickup_healthlarge 50
+set g_pickup_healthlarge_max 100
+set g_pickup_healthlarge_anyway 0
+set g_pickup_healthmega 100
+set g_pickup_healthmega_max 200
+set g_pickup_healthmega_anyway 0
+set g_pickup_respawntime_short 30
+set g_pickup_respawntime_medium 30
+set g_pickup_respawntime_long 30
+set g_pickup_respawntime_powerup 90
+set g_pickup_respawntime_weapon 5
+set g_pickup_respawntime_ammo 30
+set g_pickup_respawntimejitter_short 0
+set g_pickup_respawntimejitter_medium 0
+set g_pickup_respawntimejitter_long 0
+set g_pickup_respawntimejitter_powerup 15
+set g_pickup_respawntimejitter_weapon 0
+set g_pickup_respawntimejitter_ammo 0
+// }}}
+
+// {{{ regen/rot
+set g_balance_health_regen 0
+set g_balance_health_regenlinear 0
+set g_balance_pause_health_regen 0
+set g_balance_pause_health_regen_spawn 0
+set g_balance_health_rot 0
+set g_balance_health_rotlinear 1
+set g_balance_pause_health_rot 1
+set g_balance_pause_health_rot_spawn 0
+set g_balance_health_regenstable 100
+set g_balance_health_rotstable 100
+set g_balance_health_limit 999
+set g_balance_armor_regen 0
+set g_balance_armor_regenlinear 0
+set g_balance_armor_rot 0
+set g_balance_armor_rotlinear 1
+set g_balance_pause_armor_rot 1
+set g_balance_pause_armor_rot_spawn 0
+set g_balance_armor_regenstable 100
+set g_balance_armor_rotstable 100
+set g_balance_armor_limit 999
+set g_balance_armor_blockpercent 0.66
+
+set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)"
+set g_balance_fuel_regenlinear 0
+set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter
+set g_balance_fuel_rot 0.05
+set g_balance_fuel_rotlinear 0
+set g_balance_pause_fuel_rot 5
+set g_balance_pause_fuel_rot_spawn 10
+set g_balance_fuel_regenstable 50
+set g_balance_fuel_rotstable 100
+set g_balance_fuel_limit 999
+// }}}
+
+// {{{ misc
+set g_balance_selfdamagepercent 0.75
+set g_balance_weaponswitchdelay 0.05
+set g_weaponspeedfactor 1 "weapon projectile speed multiplier"
+set g_weaponratefactor 1 "weapon fire rate multiplier"
+set g_weapondamagefactor 1 "weapon damage multiplier"
+set g_weaponforcefactor 1 "weapon force multiplier"
+set g_weaponspreadfactor 1 "weapon spread multiplier"
+set g_balance_firetransfer_time 0.9
+set g_balance_firetransfer_damage 0.8
+set g_throughfloor_damage 0.5
+set g_throughfloor_force 0.7
+set g_projectiles_newton_style 0
+// possible values:
+// 0: absolute velocity projectiles (like Quake)
+// 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
+// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
+// 3: absolute velocity + player velocity component in shot direction (note: does NOT yield the right relative velocity, but may be good enough, but it is somewhat prone to sniper rockets)
+// 4: just add the player velocity length to the absolute velocity (tZork's sniper rockets)
+set g_projectiles_newton_style_2_minfactor 0.7
+set g_projectiles_newton_style_2_maxfactor 5
+set g_projectiles_spread_style 4
+// possible values:
+// 0: forward + solid sphere (like Quake) - varies velocity
+// 1: forward + flattened solid sphere
+// 2: forward + solid circle
+// 3: forward + normal distribution 3D - varies velocity
+// 4: forward + normal distribution on a plane
+// 5: forward + circle with 1-r falloff
+// 6: forward + circle with 1-r^2 falloff
+// 7: forward + circle with (1-r)(2-r) falloff
+set g_balance_falldamage_deadminspeed 150
+set g_balance_falldamage_minspeed 675
+set g_balance_falldamage_factor 0.25
+set g_balance_falldamage_maxdamage 10
+// }}}
+
+// {{{ powerups
+set g_balance_powerup_invincible_takedamage 0.25
+set g_balance_powerup_invincible_time 30
+set g_balance_powerup_strength_damage 4
+set g_balance_powerup_strength_force 4
+set g_balance_powerup_strength_time 30
+set g_balance_powerup_strength_selfdamage 2
+set g_balance_powerup_strength_selfforce 2
+// }}}
+
+// {{{ jetpack/hook
+set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack"
+set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction"
+set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)"
+set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction"
+set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction"
+set g_jetpack_fuel 8 "fuel per second for jetpack"
+set g_jetpack_attenuation 2 "jetpack sound attenuation"
+
+set g_grappling_hook_tarzan 2 // 2: can also pull players
+set g_balance_grapplehook_speed_fly 1800
+set g_balance_grapplehook_speed_pull 2000
+set g_balance_grapplehook_force_rubber 2000
+set g_balance_grapplehook_force_rubber_overstretch 1000
+set g_balance_grapplehook_length_min 50
+set g_balance_grapplehook_stretch 50
+set g_balance_grapplehook_airfriction 0.2
+set g_balance_grapplehook_health 130
+// }}}
+
+// {{{ weapon properties
+// {{{ laser
+set g_balance_laser_primary_damage 22
+set g_balance_laser_primary_edgedamage 0
+set g_balance_laser_primary_force 200
+set g_balance_laser_primary_radius 52
+set g_balance_laser_primary_speed 0
+set g_balance_laser_primary_spread 0
+set g_balance_laser_primary_refire 0.1
+set g_balance_laser_primary_animtime 0.1
+set g_balance_laser_primary_lifetime 0
+set g_balance_laser_primary_shotangle 0
+set g_balance_laser_primary_delay 0
+set g_balance_laser_gauntlet 1
+set g_balance_laser_secondary 0 // when 1, a secondary laser mode exists
+set g_balance_laser_secondary_damage 30
+set g_balance_laser_secondary_edgedamage 0
+set g_balance_laser_secondary_force 100
+set g_balance_laser_secondary_radius 3
+set g_balance_laser_secondary_speed 1500
+set g_balance_laser_secondary_spread 0
+set g_balance_laser_secondary_refire 0
+set g_balance_laser_secondary_animtime 0.15
+set g_balance_laser_secondary_lifetime 0.066
+set g_balance_laser_secondary_shotangle 0
+set g_balance_laser_secondary_delay 0
+// }}}
+// {{{ shotgun
+set g_balance_shotgun_primary_bullets 25
+set g_balance_shotgun_primary_damage 4
+set g_balance_shotgun_primary_force 10
+set g_balance_shotgun_primary_spread 0.18
+set g_balance_shotgun_primary_refire 1
+set g_balance_shotgun_primary_animtime 0.7
+set g_balance_shotgun_primary_ammo 1
+set g_balance_shotgun_primary_speed 12000
+set g_balance_shotgun_primary_bulletconstant 75 // 3.8qu
+set g_balance_shotgun_secondary 0
+set g_balance_shotgun_secondary_bullets 22
+set g_balance_shotgun_secondary_damage 2
+set g_balance_shotgun_secondary_force 12
+set g_balance_shotgun_secondary_spread 0.25
+set g_balance_shotgun_secondary_refire 1.5
+set g_balance_shotgun_secondary_animtime 0.2
+set g_balance_shotgun_secondary_ammo 0.5
+set g_balance_shotgun_secondary_speed 12000
+set g_balance_shotgun_secondary_bulletconstant 75 // 3.8qu
+// }}}
+// {{{ uzi
+set g_balance_uzi_first 0
+set g_balance_uzi_first_damage 10
+set g_balance_uzi_first_force 50
+set g_balance_uzi_first_spread 0.007
+set g_balance_uzi_first_refire 0.15
+set g_balance_uzi_first_ammo 1
+set g_balance_uzi_sustained_damage 5
+set g_balance_uzi_sustained_force 10
+set g_balance_uzi_sustained_spread 0.02
+set g_balance_uzi_sustained_refire 0.1
+set g_balance_uzi_sustained_ammo 1
+set g_balance_uzi_speed 18000
+set g_balance_uzi_bulletconstant 115 // 13.1qu
+// }}}
+// {{{ mortar
+set g_balance_grenadelauncher_primary2secondary 1
+set g_balance_grenadelauncher_primary_damage 60
+set g_balance_grenadelauncher_primary_edgedamage 10
+set g_balance_grenadelauncher_primary_force 250
+set g_balance_grenadelauncher_primary_radius 100
+set g_balance_grenadelauncher_primary_speed 2000
+set g_balance_grenadelauncher_primary_speed_up 200
+set g_balance_grenadelauncher_primary_speed_z 0
+set g_balance_grenadelauncher_primary_spread 0
+set g_balance_grenadelauncher_primary_lifetime 5
+set g_balance_grenadelauncher_primary_refire 0.7
+set g_balance_grenadelauncher_primary_animtime 0.3
+set g_balance_grenadelauncher_primary_ammo 2
+set g_balance_grenadelauncher_secondary_damage 65
+set g_balance_grenadelauncher_secondary_edgedamage 10
+set g_balance_grenadelauncher_secondary_force 300
+set g_balance_grenadelauncher_secondary_radius 200
+set g_balance_grenadelauncher_secondary_speed 800
+set g_balance_grenadelauncher_secondary_speed_up 0
+set g_balance_grenadelauncher_secondary_speed_z 200
+set g_balance_grenadelauncher_secondary_spread 0
+set g_balance_grenadelauncher_secondary_lifetime 2
+set g_balance_grenadelauncher_secondary_refire 0.8
+set g_balance_grenadelauncher_secondary_animtime 0.5
+set g_balance_grenadelauncher_secondary_ammo 2
+set g_balance_grenadelauncher_secondary_health 0
+set g_balance_grenadelauncher_secondary_damageforcescale 0
+set g_balance_grenadelauncher_secondary_bouncefactor 0.5
+set g_balance_grenadelauncher_secondary_bouncestop 0.075
+// }}}
+// {{{ electro
+set g_balance_electro_lightning 1
+set g_balance_electro_primary_damage 6
+set g_balance_electro_primary_edgedamage 0
+set g_balance_electro_primary_force 60 // todo: probaby needs movement nerfing code when hit?
+set g_balance_electro_primary_radius 850
+set g_balance_electro_primary_comboradius 0
+set g_balance_electro_primary_speed 0
+set g_balance_electro_primary_spread 0
+set g_balance_electro_primary_lifetime 0
+set g_balance_electro_primary_refire 0.066
+set g_balance_electro_primary_animtime 0.066
+set g_balance_electro_primary_ammo 0.66
+set g_balance_electro_secondary_damage 45
+set g_balance_electro_secondary_spread 0.10
+set g_balance_electro_secondary_edgedamage 10
+set g_balance_electro_secondary_force 100
+set g_balance_electro_secondary_radius 150
+set g_balance_electro_secondary_speed 900
+set g_balance_electro_secondary_speed_up 200
+set g_balance_electro_secondary_speed_z 0
+set g_balance_electro_secondary_spread 0.05
+set g_balance_electro_secondary_lifetime 2.5
+set g_balance_electro_secondary_refire 0.1
+set g_balance_electro_secondary_refire2 2
+set g_balance_electro_secondary_animtime 0.2
+set g_balance_electro_secondary_ammo 2
+set g_balance_electro_secondary_health 5
+set g_balance_electro_secondary_damageforcescale 4
+set g_balance_electro_secondary_count 3
+set g_balance_electro_combo_damage 50
+set g_balance_electro_combo_edgedamage 0
+set g_balance_electro_combo_force 100
+set g_balance_electro_combo_radius 250
+set g_balance_electro_combo_comboradius 0
+set g_balance_electro_combo_speed 2000
+// }}}
+// {{{ crylink
+set g_balance_crylink_primary_damage 18
+set g_balance_crylink_primary_edgedamage 18
+set g_balance_crylink_primary_force 50
+set g_balance_crylink_primary_radius 100
+set g_balance_crylink_primary_speed 1100
+set g_balance_crylink_primary_spread 0.01
+set g_balance_crylink_primary_shots 4
+set g_balance_crylink_primary_bounces 0
+set g_balance_crylink_primary_refire 0.4
+set g_balance_crylink_primary_animtime 0.4
+set g_balance_crylink_primary_ammo 2
+set g_balance_crylink_primary_bouncedamagefactor 0.5
+
+set g_balance_crylink_primary_middle_lifetime 5 // range: 35000 full, fades to 70000
+set g_balance_crylink_primary_middle_fadetime 5
+set g_balance_crylink_primary_star_lifetime 3 // range: 700 full, fades to 2450
+set g_balance_crylink_primary_star_fadetime 5
+set g_balance_crylink_primary_other_lifetime 3 // range: 700 full, fades to 2450
+set g_balance_crylink_primary_other_fadetime 5
+
+set g_balance_crylink_secondary 0
+set g_balance_crylink_secondary_damage 8
+set g_balance_crylink_secondary_edgedamage 8
+set g_balance_crylink_secondary_force -40
+set g_balance_crylink_secondary_radius 10
+set g_balance_crylink_secondary_speed 4000
+set g_balance_crylink_secondary_spread 0.01
+set g_balance_crylink_secondary_shots 3
+set g_balance_crylink_secondary_bounces 0
+set g_balance_crylink_secondary_refire 0.1
+set g_balance_crylink_secondary_animtime 0.1
+set g_balance_crylink_secondary_ammo 1
+set g_balance_crylink_secondary_bouncedamagefactor 0.5
+
+set g_balance_crylink_secondary_middle_lifetime 5 // range: 35000 full, fades to 70000
+set g_balance_crylink_secondary_middle_fadetime 5
+set g_balance_crylink_secondary_line_lifetime 2 // range: 35000 full, fades to 70000
+set g_balance_crylink_secondary_line_fadetime 2
+// }}}
+// {{{ nex
+set g_balance_nex_damage 80
+set g_balance_nex_force 200
+set g_balance_nex_refire 1.25
+set g_balance_nex_animtime 1.25
+set g_balance_nex_ammo 5
+set g_balance_nex_damagefalloff_mindist 1000
+set g_balance_nex_damagefalloff_maxdist 3000
+set g_balance_nex_damagefalloff_halflife 1500
+set g_balance_nex_damagefalloff_forcehalflife 1500
+// }}}
+// {{{ minstanex
+set g_balance_minstanex_refire 1
+set g_balance_minstanex_animtime 1
+set g_balance_minstanex_ammo 10
+// }}}
+// {{{ hagar
+set g_balance_hagar_primary_damage 12
+set g_balance_hagar_primary_edgedamage 5
+set g_balance_hagar_primary_force 70
+set g_balance_hagar_primary_radius 50
+set g_balance_hagar_primary_spread 0
+set g_balance_hagar_primary_speed 1800
+set g_balance_hagar_primary_lifetime 5
+set g_balance_hagar_primary_refire 0.1
+set g_balance_hagar_primary_ammo 1
+set g_balance_hagar_secondary 0
+set g_balance_hagar_secondary_damage 11
+set g_balance_hagar_secondary_edgedamage 4
+set g_balance_hagar_secondary_force 60
+set g_balance_hagar_secondary_radius 70
+set g_balance_hagar_secondary_spread 0.05
+set g_balance_hagar_secondary_speed 1800
+set g_balance_hagar_secondary_lifetime_min 5
+set g_balance_hagar_secondary_lifetime_rand 0
+set g_balance_hagar_secondary_refire 0.1
+set g_balance_hagar_secondary_ammo 1
+// }}}
+// {{{ rocketlauncher
+set g_balance_rocketlauncher_damage 90
+set g_balance_rocketlauncher_edgedamage 30
+set g_balance_rocketlauncher_force 350
+set g_balance_rocketlauncher_radius 110
+set g_balance_rocketlauncher_speed 1000
+set g_balance_rocketlauncher_speedaccel 0
+set g_balance_rocketlauncher_speedstart 1000
+set g_balance_rocketlauncher_lifetime 10
+set g_balance_rocketlauncher_refire 0.9
+set g_balance_rocketlauncher_animtime 0.7
+set g_balance_rocketlauncher_ammo 3
+set g_balance_rocketlauncher_health 0
+set g_balance_rocketlauncher_damageforcescale 0
+set g_balance_rocketlauncher_detonatedelay 9999 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time
+set g_balance_rocketlauncher_guiderate 0 // max degrees per second
+set g_balance_rocketlauncher_guideratedelay 0.01 // immediate
+set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic)
+set g_balance_rocketlauncher_guidedelay 0.15 // delay before guiding kicks in
+set g_balance_rocketlauncher_guidestop 1 // stop guiding when firing again
+set g_balance_rocketlauncher_laserguided_speed 1000 //650
+set g_balance_rocketlauncher_laserguided_speedaccel 0
+set g_balance_rocketlauncher_laserguided_speedstart 1000
+set g_balance_rocketlauncher_laserguided_turnrate 0.75 //0.5
+set g_balance_rocketlauncher_laserguided_allow_steal 1
+// }}}
+// {{{ porto
+set g_balance_porto_primary_refire 1.5
+set g_balance_porto_primary_animtime 0.3
+set g_balance_porto_primary_speed 5000
+set g_balance_porto_primary_lifetime 30
+set g_balance_portal_health 200 // these get recharged whenever the portal is used
+set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used
+// }}}
+// {{{ hook
+set g_balance_hook_primary_fuel 2 // hook monkeys set 0
+set g_balance_hook_primary_refire 0 // hook monkeys set 0
+set g_balance_hook_primary_animtime 0.3 // good shoot anim
+set g_balance_hook_primary_hooked_time_max 0 // infinite
+set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free
+set g_balance_hook_primary_hooked_fuel 3 // fuel per second hooked
+set g_balance_hook_secondary_damage 25 // not much
+set g_balance_hook_secondary_edgedamage 5 // not much
+set g_balance_hook_secondary_radius 500 // LOTS
+set g_balance_hook_secondary_force -2000 // LOTS
+set g_balance_hook_secondary_ammo 50 // a whole pack
+set g_balance_hook_secondary_lifetime 10 // infinite
+set g_balance_hook_secondary_speed 0 // not much throwing
+set g_balance_hook_secondary_gravity 5 // fast falling
+set g_balance_hook_secondary_refire 3 // don't drop too many bombs...
+set g_balance_hook_secondary_animtime 0.3 // good shoot anim
+set g_balance_hook_secondary_power 3 // effect behaves like a square function
+set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds
+// }}}
+// {{{ hlac
+set g_balance_hlac_primary_spread_min 0.01
+set g_balance_hlac_primary_spread_max 0.03
+set g_balance_hlac_primary_spread_add 0.002
+set g_balance_hlac_primary_spread_crouchmod 0.5
+
+set g_balance_hlac_primary_damage 6
+set g_balance_hlac_primary_edgedamage 0
+set g_balance_hlac_primary_force 60 // todo: probably needs movement nerfing code when hit
+set g_balance_hlac_primary_radius 850
+set g_balance_hlac_primary_speed 0
+set g_balance_hlac_primary_lifetime 0
+
+set g_balance_hlac_primary_refire 0.066
+set g_balance_hlac_primary_animtime 0.066
+set g_balance_hlac_primary_ammo 0.066
+
+set g_balance_hlac_secondary 0
+set g_balance_hlac_secondary_spread 0.06
+set g_balance_hlac_secondary_spread_crouchmod 0.5
+
+set g_balance_hlac_secondary_damage 11
+set g_balance_hlac_secondary_edgedamage 10
+set g_balance_hlac_secondary_force 60
+set g_balance_hlac_secondary_radius 70
+set g_balance_hlac_secondary_speed 20000
+set g_balance_hlac_secondary_lifetime 5
+
+set g_balance_hlac_secondary_refire 0.6
+set g_balance_hlac_secondary_animtime 0.6
+set g_balance_hlac_secondary_ammo 10
+set g_balance_hlac_secondary_shots 5
+// }}}
+// {{{ campingrifle
+set g_balance_campingrifle_magazinecapacity 0
+set g_balance_campingrifle_reloadtime 2 // matches reload anim
+set g_balance_campingrifle_auto_reload_after_changing_weapons 0
+set g_balance_campingrifle_bursttime 0.85 // 0.35 - 0.1 + 0.35 - 0.1 + 0.35 = three secondaries
+set g_balance_campingrifle_tracer 1
+set g_balance_campingrifle_primary_damage 50
+set g_balance_campingrifle_primary_headshotaddeddamage 80
+set g_balance_campingrifle_primary_spread 0
+set g_balance_campingrifle_primary_force 0
+set g_balance_campingrifle_primary_speed 35000
+set g_balance_campingrifle_primary_lifetime 5
+set g_balance_campingrifle_primary_refire 0.7
+set g_balance_campingrifle_primary_animtime 0.7
+set g_balance_campingrifle_primary_ammo 10
+set g_balance_campingrifle_primary_bulletconstant 130 // 56.3qu
+set g_balance_campingrifle_primary_burstcost 0.35 // require same cooldown as secondary, note it's smaller than primary refire time
+set g_balance_campingrifle_primary_bullethail 0
+set g_balance_campingrifle_secondary_damage 15
+set g_balance_campingrifle_secondary_headshotaddeddamage 25
+set g_balance_campingrifle_secondary_spread 0.02
+set g_balance_campingrifle_secondary_force 0
+set g_balance_campingrifle_secondary_speed 20000
+set g_balance_campingrifle_secondary_lifetime 5
+set g_balance_campingrifle_secondary_refire 0.1
+set g_balance_campingrifle_secondary_animtime 0.1
+set g_balance_campingrifle_secondary_ammo 4
+set g_balance_campingrifle_secondary_bulletconstant 130 // 18.3qu
+set g_balance_campingrifle_secondary_burstcost 0.35
+set g_balance_campingrifle_secondary_bullethail 0
+// }}}
+// {{{ tuba
+set g_balance_tuba_refire 0.05
+set g_balance_tuba_animtime 0.05
+set g_balance_tuba_attenuation 0.5
+set g_balance_tuba_volume 1
+set g_balance_tuba_fadetime 0.25
+set g_balance_tuba_damage 5
+set g_balance_tuba_edgedamage 0
+set g_balance_tuba_radius 200
+set g_balance_tuba_force 40
+// }}}
+// {{{ fireball
+set g_balance_fireball_primary_ammo 40
+set g_balance_fireball_primary_animtime 0.15
+set g_balance_fireball_primary_bfgdamage 100
+set g_balance_fireball_primary_bfgforce 0
+set g_balance_fireball_primary_bfgradius 1000
+set g_balance_fireball_primary_damage 200
+set g_balance_fireball_primary_damageforcescale 4
+set g_balance_fireball_primary_edgedamage 0
+set g_balance_fireball_primary_force 700
+set g_balance_fireball_primary_health 50
+set g_balance_fireball_primary_laserburntime 0.5
+set g_balance_fireball_primary_laserdamage 80
+set g_balance_fireball_primary_laseredgedamage 20
+set g_balance_fireball_primary_laserradius 256
+set g_balance_fireball_primary_lifetime 15
+set g_balance_fireball_primary_radius 200
+set g_balance_fireball_primary_refire 5
+set g_balance_fireball_primary_refire2 0
+set g_balance_fireball_primary_speed 650
+set g_balance_fireball_primary_spread 0
+set g_balance_fireball_secondary_ammo 5
+set g_balance_fireball_secondary_animtime 0.3
+set g_balance_fireball_secondary_damage 40
+set g_balance_fireball_secondary_damageforcescale 4
+set g_balance_fireball_secondary_damagetime 5
+set g_balance_fireball_secondary_force 100
+set g_balance_fireball_secondary_laserburntime 0.5
+set g_balance_fireball_secondary_laserdamage 50
+set g_balance_fireball_secondary_laseredgedamage 20
+set g_balance_fireball_secondary_laserradius 110
+set g_balance_fireball_secondary_lifetime 7
+set g_balance_fireball_secondary_refire 2
+set g_balance_fireball_secondary_speed 900
+set g_balance_fireball_secondary_speed_up 100
+set g_balance_fireball_secondary_speed_z 0
+set g_balance_fireball_secondary_spread 0
+// }}}
+// {{{ seeker
+set g_balance_seeker_flac_ammo 0.5
+set g_balance_seeker_flac_animtime 0.1
+set g_balance_seeker_flac_damage 15
+set g_balance_seeker_flac_edgedamage 10
+set g_balance_seeker_flac_force 50
+set g_balance_seeker_flac_lifetime 0.1
+set g_balance_seeker_flac_lifetime_rand 0.05
+set g_balance_seeker_flac_radius 100
+set g_balance_seeker_flac_refire 0.1
+set g_balance_seeker_flac_speed 3000
+set g_balance_seeker_flac_speed_up 1000
+set g_balance_seeker_flac_speed_z 0
+set g_balance_seeker_flac_spread 0.4
+set g_balance_seeker_missile_accel 1.05
+set g_balance_seeker_missile_ammo 2
+set g_balance_seeker_missile_animtime 0.3
+set g_balance_seeker_missile_count 4
+set g_balance_seeker_missile_damage 40
+set g_balance_seeker_missile_damageforcescale 4
+set g_balance_seeker_missile_decel 0.9
+set g_balance_seeker_missile_delay 0.25
+set g_balance_seeker_missile_edgedamage 10
+set g_balance_seeker_missile_force 250
+set g_balance_seeker_missile_health 5
+set g_balance_seeker_missile_lifetime 15
+set g_balance_seeker_missile_proxy 0
+set g_balance_seeker_missile_proxy_delay 0.2
+set g_balance_seeker_missile_proxy_maxrange 45
+set g_balance_seeker_missile_radius 80
+set g_balance_seeker_missile_refire 0.5
+set g_balance_seeker_missile_smart 1
+set g_balance_seeker_missile_smart_mindist 800
+set g_balance_seeker_missile_smart_trace_max 2500
+set g_balance_seeker_missile_smart_trace_min 1000
+set g_balance_seeker_missile_speed 700
+set g_balance_seeker_missile_speed_accel 0
+set g_balance_seeker_missile_speed_up 300
+set g_balance_seeker_missile_speed_z 0
+set g_balance_seeker_missile_speed_max 1250
+set g_balance_seeker_missile_spread 0
+set g_balance_seeker_missile_turnrate 0.65
+set g_balance_seeker_tag_ammo 1
+set g_balance_seeker_tag_animtime 0.3
+set g_balance_seeker_tag_damageforcescale 4
+set g_balance_seeker_tag_health 5
+set g_balance_seeker_tag_lifetime 15
+set g_balance_seeker_tag_refire 0.7
+set g_balance_seeker_tag_speed 9000
+set g_balance_seeker_tag_spread 0
+// End new seeker
//bot configuration: name model skin shirt pants team keyboard use moving dodging ping weapon use aggressivity range aiming calmhand mouse fightthink aithink
//default team values (team-override): 1 = red, 2 = blue, 3 = yellow, 4 = pink
//use -1 for shirt-color or pants-color to get random colors
-Hellfire carni 0 4 0 0 0 0 -0.5 -1 1 1 -0.5 -1 -1 2 0.5 -1
-Toxic carni 1 14 7 0 -1 -1.5 -0.5 0 1 0 0 0 2 -0.5 -0.5 1
-Discovery crash 0 2 6 0 0 -1 -0.5 -0.5 1 -0.5 0.5 1.5 -0.5 -1 1 0.5
-Pegasus grunt 0 13 11 0 1 1 1 1 -1 0 0.5 0 -2 0 -1 0
-Eureka headhunter 0 12 7 0 0 0 -1.5 -0.5 -0.5 0 0 0 0 -0.5 1.5 1.5
-Airhead insurrectionist 0 11 1 0 -1 -1.5 -1 -0.5 1 1 -1 1 -0.5 1 0.5 0
-Gator lurk 0 3 10 0 0 1 0 0.5 -0.5 0.5 -0.5 -1 0 0 -0.5 0
-Delirium lurk 1 8 12 0 0 -1 -1 -1 0 2 0 1 0 2 -1 -1
-Death lycanthrope 0 4 11 0 -0.5 0 0 1 -0.5 0 1 0 0 0 0 0
-Scorcher marine 0 13 13 0 0 -1 0 -0.5 0.5 1 0 1 -2 1 0 0
-Necrotic nexus 0 12 14 0 0 0 0 1 0 -1 -0.5 -1 1 0 0 0
-Dominator nexus 1 3 9 0 0 0 0 2 -1 0 0 0 -1 0 0 0
-Thunderstorm nexus 2 13 6 0 0 0 0 -0.5 -1 1 0.5 0.5 -0.5 0 0.5 0
-Mystery pyria 0 9 14 0 1 1 1 1 -1 -1 0 1 1 -2 -1 -1
-Lion shock 0 0 4 0 1 1.5 2 -1 -1 -1 1 0 1 -0.5 -1 -1
-Sensible skadi 0 9 9 0 0 0 0.5 -1 0 -1 0 -1 2.5 -1.5 1 0.5
-Shadow specop 0 4 8 0 -0.5 2 1 0 0 -1 0 -1 0 1 -1 -0.5
-Resurrection visitant 0 1 1 0 0 -0.5 -0.5 0 2 -1 -1 -1 0 -1 1 1
+Hellfire umbra 0 4 0 0 0 0 -0.5 -1 1 1 -0.5 -1 -1 2 0.5 -1
+Toxic umbra 0 14 7 0 -1 -1.5 -0.5 0 1 0 0 0 2 -0.5 -0.5 1
+Discovery umbra 0 2 6 0 0 -1 -0.5 -0.5 1 -0.5 0.5 1.5 -0.5 -1 1 0.5
+Pegasus umbra 0 13 11 0 1 1 1 1 -1 0 0.5 0 -2 0 -1 0
+Eureka umbra 0 12 7 0 0 0 -1.5 -0.5 -0.5 0 0 0 0 -0.5 1.5 1.5
+Airhead umbra 0 11 1 0 -1 -1.5 -1 -0.5 1 1 -1 1 -0.5 1 0.5 0
+Gator umbra 0 3 10 0 0 1 0 0.5 -0.5 0.5 -0.5 -1 0 0 -0.5 0
+Delirium umbra 0 8 12 0 0 -1 -1 -1 0 2 0 1 0 2 -1 -1
+Death umbra 0 4 11 0 -0.5 0 0 1 -0.5 0 1 0 0 0 0 0
+Scorcher umbra 0 13 13 0 0 -1 0 -0.5 0.5 1 0 1 -2 1 0 0
+Necrotic umbra 0 12 14 0 0 0 0 1 0 -1 -0.5 -1 1 0 0 0
+Dominator umbra 0 3 9 0 0 0 0 2 -1 0 0 0 -1 0 0 0
+Thunderstorm umbra 0 13 6 0 0 0 0 -0.5 -1 1 0.5 0.5 -0.5 0 0.5 0
+Mystery umbra 0 9 14 0 1 1 1 1 -1 -1 0 1 1 -2 -1 -1
+Lion umbra 0 0 4 0 1 1.5 2 -1 -1 -1 1 0 1 -0.5 -1 -1
+Sensible umbra 0 9 9 0 0 0 0.5 -1 0 -1 0 -1 2.5 -1.5 1 0.5
+Shadow umbra 0 4 8 0 -0.5 2 1 0 0 -1 0 -1 0 1 -1 -0.5
+Resurrection umbra 0 1 1 0 0 -0.5 -0.5 0 2 -1 -1 -1 0 -1 1 1
_update_generic
set g_configversion 2
+
+// we now use mastervolume
+volume 1
exec defaultXonotic.cfg
-
-// we're not xonotic 2.6 yet
-//exec default25.cfg
+++ /dev/null
-cl_netfps 20
-sys_ticrate 0.05
-sv_gameplayfix_delayprojectiles 1
-exec physics25.cfg
-exec balance25.cfg
+++ /dev/null
-cl_netfps 60
-sys_ticrate 0.0166667
-sv_gameplayfix_delayprojectiles 0
-exec physics26.cfg
-exec balance.cfg
--- /dev/null
+// Samual's mod configuration file
+exec defaultXonotic.cfg
+
+// weapon replace options
+set g_weaponreplace_laser ""
+set g_weaponreplace_shotgun ""
+set g_weaponreplace_uzi ""
+set g_weaponreplace_grenadelauncher ""
+set g_weaponreplace_electro ""
+set g_weaponreplace_crylink ""
+set g_weaponreplace_nex ""
+set g_weaponreplace_hagar ""
+set g_weaponreplace_rocketlauncher ""
+set g_weaponreplace_porto ""
+set g_weaponreplace_minstanex ""
+set g_weaponreplace_hook ""
+set g_weaponreplace_hlac 0 // Maybe will be enabled later after I figure out what I want to do with it
+set g_weaponreplace_campingrifle ""
+set g_weaponreplace_tuba ""
+set g_weaponreplace_fireball 0 // Same with this
+set g_weaponreplace_seeker 0 // Same with this
+set sv_q3acompat_machineshotgunswap 0
+
+// other options
+set sv_fragmessage_information_ping 1
+set sv_fragmessage_information_handicap 2
+set sv_fragmessage_information_stats 1
+set sv_fragmessage_information_typefrag 1
+
+exec physicsSamual.cfg
+exec balanceSamual.cfg
--- /dev/null
+exec defaultXonotic.cfg
+
+set g_weaponreplace_laser ""
+set g_weaponreplace_shotgun "uzi"
+set g_weaponreplace_uzi "shotgun"
+set g_weaponreplace_grenadelauncher ""
+set g_weaponreplace_electro ""
+set g_weaponreplace_crylink ""
+set g_weaponreplace_nex ""
+set g_weaponreplace_hagar ""
+set g_weaponreplace_rocketlauncher ""
+set g_weaponreplace_porto ""
+set g_weaponreplace_minstanex ""
+set g_weaponreplace_hook 0
+set g_weaponreplace_hlac 0
+set g_weaponreplace_campingrifle 0
+set g_weaponreplace_tuba ""
+set g_weaponreplace_fireball 0
+set g_weaponreplace_seeker 0
+set sv_q3acompat_machineshotgunswap 0
+
+exec physicsXPM.cfg
+exec balanceXPM.cfg
set g_xonoticversion 2.5svn "Xonotic version (formatted for humans)"
-//!<showbrand
-showbrand 3
-echo
-echo A warning about this being a SVN development version was set up.
-echo This build shall be used for development and testing only!
-echo
-echo If you want to disable this warning, add the line
-echo showbrand 0
-echo to your autoexec.cfg.
-echo
-//!>showbrand
-
// changes a cvar and reports it to the server (for the menu to notify the
// server about changes)
alias setreport "set \"$1\" \"$2\" ; sendcvar \"$1\""
// player defaults
_cl_color 102
_cl_name Player
-_cl_playermodel models/player/marine.zym
+_cl_playermodel models/player/umbra.iqm
_cl_playerskin 0
crosshair 1
seta crosshair_per_weapon 0 "when 1, each gun will display a different crosshair"
seta crosshair_hlac_color_blue 0.2 "crosshair color blue component to display when wielding the H.L.A.C."
seta crosshair_hlac_color_alpha 1 "crosshair alpha value to display when wielding the H.L.A.C."
seta crosshair_hlac_size 0.6 "crosshair size when wielding the H.L.A.C."
+seta crosshair_seeker "" "crosshair to display when wielding the TAG Seeker"
+seta crosshair_seeker_color_red 1 "crosshair color red component to display when wielding the TAG seeker"
+seta crosshair_seeker_color_green 0.35 "crosshair color green component to display when wielding the TAG seeker"
+seta crosshair_seeker_color_blue 0.35 "crosshair color blue component to display when wielding the TAG seeker"
+seta crosshair_seeker_color_alpha 0.9 "crosshair alpha value to display when wielding the TAG seeker"
+seta crosshair_seeker_size 0.8 "crosshair size when wielding the TAG seeker"
seta crosshair_campingrifle "" "crosshair to display when wielding the campingrifle"
seta crosshair_campingrifle_color_red 0.85 "crosshair color red component to display when wielding the campingrifle"
seta crosshair_campingrifle_color_green 0.5 "crosshair color green component to display when wielding the campingrifle"
cl_bobcycle 0 // how long the cycle of up/down view movement takes (only works if cl_bob is not 0), default is 0.6
cl_bob 0.01 // how much view moves up/down when moving (does not move if cl_bobcycle is 0, but still enables cl_bobmodel), default is 0.02
cl_bobmodel 1 // whether to have gun model move around on screen when moving (only works if cl_bob is not 0), default is 1
+cl_leanmodel 1 // enables weapon leaning effect when looking around
+cl_leanmodel_side_speed 0.7 "gun leaning sideways speed"
+cl_leanmodel_side_limit 35 "gun leaning sideways limit"
+cl_leanmodel_side_highpass1 30 "gun leaning sideways pre-highpass in 1/s"
+cl_leanmodel_side_highpass 3 "gun leaning sideways highpass in 1/s"
+cl_leanmodel_side_lowpass 20 "gun leaning sideways lowpass in 1/s"
+cl_leanmodel_up_speed 0.65 "gun leaning upward speed"
+cl_leanmodel_up_limit 50 "gun leaning upward limit"
+cl_leanmodel_up_highpass1 5 "gun leaning upward pre-highpass in 1/s"
+cl_leanmodel_up_highpass 15 "gun leaning upward highpass in 1/s"
+cl_leanmodel_up_lowpass 20 "gun leaning upward lowpass in 1/s"
+cl_followmodel 1 // enables weapon pushing / pulling effect when walking
+cl_followmodel_side_speed 0.25 "gun following sideways speed"
+cl_followmodel_side_limit 6 "gun following sideways limit"
+cl_followmodel_side_highpass1 30 "gun following sideways pre-highpass in 1/s"
+cl_followmodel_side_highpass 5 "gun following sideways highpass in 1/s"
+cl_followmodel_side_lowpass 10 "gun following sideways lowpass in 1/s"
+cl_followmodel_up_speed 0.5 "gun following upward speed"
+cl_followmodel_up_limit 5 "gun following upward limit"
+cl_followmodel_up_highpass1 60 "gun following upward pre-highpass in 1/s"
+cl_followmodel_up_highpass 2 "gun following upward highpass in 1/s"
+cl_followmodel_up_lowpass 10 "gun following upward lowpass in 1/s"
+
cl_rollangle 0 // amount of view tilt when strafing, default is 2.0
v_kicktime 0 // how long damage kicks of the view last, default is 0 seconds
gl_polyblend 0.5 // whether to use screen tints, default is 1
set g_telefrags_avoid 0
set g_teleport_maxspeed 0 "maximum speed that a player can keep when going through a teleporter (if a misc_teleporter_dest also has a cap the smallest one of these will be used), 0 = don't limit, -1 = keep no speed"
+set g_respawn_ghosts 0 "if 1 dead bodies become ghosts and float away when the player respawns"
+set g_respawn_ghosts_speed 5 "the speed with which respawn ghosts float and rotate"
+set g_respawn_ghosts_maxtime 6 "maximum amount of time a respawn ghost can last, minimum time is half this value. 0 disables and ghosts fade when the body would"
+
// fragmessage: This allows extra information to be displayed with the frag centerprints.
set sv_fragmessage_information_ping 0 "Enable ping display information, 0 = Never display; 1 = Always display (If the player is a bot, it will say bot instead of the ping.)"
set sv_fragmessage_information_handicap 1 "Enable handicap display information, 0 = Never display; 1 = Only when the player has handicap on; 2 = Always display (Displays Off if off)"
// use default physics
set sv_friction_on_land 0
-exec physics26.cfg
+exec physicsNoQWBunny.cfg
set sv_player_viewoffset "0 0 35" "view offset of the player model"
set sv_player_mins "-16 -16 -24" "playermodel mins"
set sv_pogostick 1 "don't require releasing the space bar for jumping again"
set sv_doublejump 0 "allow Quake 2-style double jumps"
-set sv_jumpspeedcap_min "" "wont perform a doublejump if z-axis speed is higher than sv_jumpvelocity * this"
-set sv_jumpspeedcap_max "" "wont perform a doublejump if z-axis speed is higher than sv_jumpvelocity * this"
-set sv_jumpspeedcap_max_disable_on_ramps 0 "disable max jumpspeedcap on ramps to preserve the old rampjump style"
+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"
seta sv_precacheplayermodels 1
seta sv_precacheweapons 0
set bot_ai_aimskill_offset 0.3 "Amount of error induced to the bots aim"
set bot_ai_aimskill_think 1 "Aiming velocity. Use values below 1 for slower aiming"
set bot_ai_custom_weapon_priority_distances "300 850" "Define close and far distances in any order. Based on the distance to the enemy bots will choose different weapons"
-set bot_ai_custom_weapon_priority_far "minstanex nex campingrifle rocketlauncher grenadelauncher electro hagar hlac crylink laser uzi fireball shotgun tuba" "Desired weapons for far distances ordered by priority"
-set bot_ai_custom_weapon_priority_mid "minstanex rocketlauncher nex fireball grenadelauncher electro uzi campingrifle crylink hlac hagar shotgun laser tuba" "Desired weapons for middle distances ordered by priority"
-set bot_ai_custom_weapon_priority_close "minstanex nex uzi hlac tuba hagar crylink grenadelauncher shotgun electro campingrifle rocketlauncher laser fireball" "Desired weapons for close distances ordered by priority"
+set bot_ai_custom_weapon_priority_far "minstanex nex campingrifle rocketlauncher grenadelauncher electro hagar hlac crylink laser uzi fireball seeker shotgun tuba" "Desired weapons for far distances ordered by priority"
+set bot_ai_custom_weapon_priority_mid "minstanex rocketlauncher nex fireball seeker grenadelauncher electro uzi campingrifle crylink hlac hagar shotgun laser tuba" "Desired weapons for middle distances ordered by priority"
+set bot_ai_custom_weapon_priority_close "minstanex nex uzi hlac tuba seeker hagar crylink grenadelauncher shotgun electro campingrifle rocketlauncher laser fireball" "Desired weapons for close distances ordered by priority"
set bot_ai_weapon_combo 1 "Enable bots to do weapon combos"
set bot_ai_weapon_combo_threshold 0.3 "Try to make a combo N seconds after the last attack"
set bot_ai_friends_aware_pickup_radius "500" "Bots will not pickup items if a team mate is this distance near the item"
set g_grappling_hook 0 "let players spawn with the grappling hook which allows them to pull themselves up"
+set g_dodging 0 "set to 1 to enable dodging in games"
+
+seta cl_dodging_timeout 0.2 "determines how long apart (in seconds) two taps on the same direction key are considered a dodge. use 0 to disable"
+
+set sv_dodging_wall_dodging 0 "set to 1 to allow dodging off walls. 0 to disable"
+set sv_dodging_delay 0.5 "determines how long a player has to wait to be able to dodge again after dodging"
+set sv_dodging_up_speed 200 "the jump velocity of the dodge"
+set sv_dodging_horiz_speed 400 "the horizontal velocity of the dodge"
+set sv_dodging_ramp_time 0.1 "a ramp so that the horizontal part of the dodge is added smoothly (seconds)"
+set sv_dodging_height_threshold 10 "the maximum height above ground where to allow dodging"
+set sv_dodging_wall_distance_threshold 10 "the maximum distance from a wall that still allows dodging"
+set sv_dodging_sound 1 "if 1 dodging makes a sound. if 0 dodging is silent"
+
set leadlimit 0
// this means that timelimit can be overidden globally and fraglimit can be overidden for each game mode: DM/TDM, Domination, CTF, and Runematch.
alias spec "cmd spectate"
bind F3 spec
-// NixNex (No-Items x Xonotic) - at each time, everyone uses the same weapon,
+// NIX (No Items Xonotic) - at each time, everyone uses the same weapon,
// and in regular intervals, this weapon is cycled
-set g_nixnex 0 "No Items Xonotic - instead of pickup items, everyone plays with the same weapon. After some time, a countdown will start, after which everyone will switch to another weapon, and so on"
-set g_nixnex_with_laser 0 "always carry the laser as an additional weapon in NixNex"
-set g_nixnex_with_healtharmor 0 "when 1, health and armor still show up in NixNex"
-set g_nixnex_with_powerups 0 "when 1, powerups still show up in NixNex"
+set g_nix 0 "No Items Xonotic - instead of pickup items, everyone plays with the same weapon. After some time, a countdown will start, after which everyone will switch to another weapon, and so on"
+set g_nix_with_laser 0 "always carry the laser as an additional weapon in NIX"
+set g_nix_with_healtharmor 0 "when 1, health and armor still show up in NIX"
+set g_nix_with_powerups 0 "when 1, powerups still show up in NIX"
// score log
set sv_logscores_console 0 "print scores to server console"
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_voice_flood_spv 4 "normal voices: seconds between voices to not count as flooding"
-set g_voice_flood_spv_team 2 "team voices: seconds between voices to not count as flooding"
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"
set sv_foginterval 0
// Audio track names (for old-style "cd loop NUMBER" usage)
-set g_cdtracks_remaplist "digital-pursuit breakdown-easy brainsukker chaos-fog infight neuronal-diving subcities thru-the-mirror calling-bogus beast-of-insanity thunder brokenlight brokenlight stairs sixtyfour_ desert3 ninesix sixtyfour_revisited northern-lights" "list used by mapinfo system to automatically assign cdtracks - must match the cd remap command"
-set g_cdtracks_dontusebydefault "digital-pursuit thunder brokenlight" "list used by mapinfo system to automatically assign cdtracks - must be a subset of g_cdtracks_remaplist"
+set _cdtrack_first "1"
+alias _cdtrack_0 "g_cdtracks_remaplist \"$g_cdtracks_remaplist $1\""
+alias _cdtrack_1 "g_cdtracks_remaplist \"$1\"; set _cdtrack_first 0"
+alias _cdtrack "_cdtrack_$_cdtrack_first $2"
+set g_cdtracks_remaplist ""
+exec cdtracks.cfg
+unset _cdtrack_first
+unalias _cdtrack_0
+unalias _cdtrack_1
+unalias _cdtrack
+
cd remap $g_cdtracks_remaplist
set sv_intermission_cdtrack ""
-set menu_cdtrack brokenlight
+
+set g_cdtracks_dontusebydefault ""
+set menu_cdtrack "ninesix"
// maxidle (in seconds): kick players idle for more than that amount of time
set sv_maxidle 0
alias allready "sv_cmd allready"
// note: these cvars use weapon NUMBERS. Use the menu to edit this cvar, or look the numbers up in qcsrc/common/constants.qh.
-seta cl_weaponpriority "minstanex rocketlauncher nex grenadelauncher fireball hlac hagar crylink campingrifle uzi electro tuba shotgun laser hook porto" "weapon priority list"
+seta cl_weaponpriority "minstanex rocketlauncher nex grenadelauncher fireball hlac hagar seeker crylink campingrifle uzi electro tuba shotgun laser hook porto" "weapon priority list"
seta cl_weaponpriority_useforcycling 0 "when set, weapon cycling by the mouse wheel makes use of the weapon priority list"
-seta cl_weaponpriority0 "rocketlauncher grenadelauncher hagar fireball" "use impulse 200 for prev gun from this list, 210 for best gun, 220 for next gun. Default value: explosives"
-seta cl_weaponpriority1 "minstanex nex crylink hlac electro laser" "use impulse 201 for prev gun from this list, 211 for best gun, 221 for next gun. Default value: energy"
-seta cl_weaponpriority2 "minstanex nex campingrifle" "use impulse 202 for prev gun from this list, 212 for best gun, 222 for next gun. Default value: hitscan exact"
-seta cl_weaponpriority3 "minstanex nex campingrifle uzi shotgun" "use impulse 203 for prev gun from this list, 213 for best gun, 223 for next gun. Default value: hitscan all"
-seta cl_weaponpriority4 "grenadelauncher hlac hagar crylink shotgun" "use impulse 204 for prev gun from this list, 214 for best gun, 224 for next gun. Default value: spam weapons"
-seta cl_weaponpriority5 "laser hook porto" "use impulse 205 for prev gun from this list, 215 for best gun, 225 for next gun. Default value: weapons for moving"
+seta cl_weaponpriority0 "rocketlauncher grenadelauncher hagar seeker fireball" "use impulse 200 for prev gun from this list, 210 for best gun, 220 for next gun. Default value: explosives"
+seta cl_weaponpriority1 "minstanex nex crylink hlac electro laser" "use impulse 201 for prev gun from this list, 211 for best gun, 221 for next gun. Default value: energy"
+seta cl_weaponpriority2 "minstanex nex campingrifle" "use impulse 202 for prev gun from this list, 212 for best gun, 222 for next gun. Default value: hitscan exact"
+seta cl_weaponpriority3 "minstanex nex campingrifle uzi shotgun" "use impulse 203 for prev gun from this list, 213 for best gun, 223 for next gun. Default value: hitscan all"
+seta cl_weaponpriority4 "grenadelauncher hlac hagar crylink seeker shotgun" "use impulse 204 for prev gun from this list, 214 for best gun, 224 for next gun. Default value: spam weapons"
+seta cl_weaponpriority5 "laser hook porto" "use impulse 205 for prev gun from this list, 215 for best gun, 225 for next gun. Default value: weapons for moving"
seta cl_weaponpriority6 "" "use impulse 206 for prev gun from this list, 216 for best gun, 226 for next gun"
seta cl_weaponpriority7 "" "use impulse 207 for prev gun from this list, 217 for best gun, 227 for next gun"
seta cl_weaponpriority8 "" "use impulse 208 for prev gun from this list, 218 for best gun, 228 for next gun"
seta cl_weaponpriority9 "" "use impulse 209 for prev gun from this list, 219 for best gun, 229 for next gun"
+seta cl_weaponimpulsemode 0 "0: only cycle between currently usable weapons in weapon priority order; 1: cycle between all possible weapons on a key in weapon priority order"
seta sv_status_privacy 1 "hide IP addresses from \"status\" replies shown to clients"
set g_ballistics_materialconstant 1414213562
set g_ballistics_mindistance 16
+set g_ballistics_density_player 0.50 // players are 2x as easy to pass as walls
+set g_ballistics_density_corpse 0.10 // corpses are 10x as easy to pass as walls
// unit: qJ / qu^3 (energy needed per volume unit of solid to push/burn away
// parameter: bullet constant: mass / area in g/qu^2
// = mass / (pi/4 * caliber^2)
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 1 "workaround to fix the aiming direction on stupidly made player models, FIXME fix the models and set this to 0"
+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"
// FIXME workaround for engine bug
sv_gameplayfix_nudgeoutofsolid 0
// to div0: remove this once 5b7ac1706712977bbc0297d2d53294e73574c7cd (svn r9537) is in the stable branch of the engine again
+
+// otherwise, antilag breaks
+sv_gameplayfix_consistentplayerprethink 1
+
+// support Q1BSP maps
+mod_q1bsp_polygoncollisions 1
+
+// improve some minor details
+sv_gameplayfix_gravityunaffectedbyticrate 1
+sv_gameplayfix_nogravityonground 1
+
+// autodemo deleting
+seta cl_autodemo_delete_keeprecords 0 "when 1, records with a newly made race/cts demo are kept even if cl_autodemo_delete is used to delete demos"
+
+// freeze camera
+set cl_lockview 0 "when 1, the camera does not move any more"
+
+// we now use mastervolume
+volume 1
+
+// sucks less than the old one
+cl_decals_newsystem 1
+
+// NOTE: this only replaces weapons on the map
+// use g_start_weapon_* to also replace the on-startup weapons!
+// example: g_weaponreplace_nex "nex minstanex", then Nexes become MinstaNexes 50% of the times
+// set the cvars to "0" to totally disable a weapon
+set g_weaponreplace_laser ""
+set g_weaponreplace_shotgun ""
+set g_weaponreplace_uzi ""
+set g_weaponreplace_grenadelauncher ""
+set g_weaponreplace_electro ""
+set g_weaponreplace_crylink ""
+set g_weaponreplace_nex ""
+set g_weaponreplace_hagar ""
+set g_weaponreplace_rocketlauncher ""
+set g_weaponreplace_porto ""
+set g_weaponreplace_minstanex ""
+set g_weaponreplace_hook ""
+set g_weaponreplace_hlac ""
+set g_weaponreplace_campingrifle ""
+set g_weaponreplace_tuba ""
+set g_weaponreplace_fireball ""
+set g_weaponreplace_seeker ""
+set sv_q3acompat_machineshotgunswap 0 "shorthand for swapping uzi and shotgun (for Q3A map compatibility in mapinfo files)"
+
+set g_movement_highspeed 1 "movement speed modification factor (only changes movement when above maxspeed)"
lightcolor 0.4 0.9 0.9
// cloud of particles which expand rapidly and then slow to form a ball
effect TE_WIZSPIKE
-count 100
+count 50
type static
color 0x63F2EA 0x63f2EA
size 2 2
size 24 24
// sparks that rapidly expand and rapidly slow down to form an interesting spherical effect
effect TE_KNIGHTSPIKE
-count 256
+count 128
type spark
color 0x800000 0xFF8020
alpha 256 256 1024
originjitter 6 6 6
// dust/smoke drifting away from the impact
effect TE_SPIKE
-count 8
+count 4
type smoke
tex 0 8
color 0x101010 0x101010
velocityjitter 8 8 8
// dust/smoke staying at the impact
effect TE_SPIKE
-count 1
+count 0.5
type smoke
tex 0 8
color 0x505050 0x505050
velocityjitter 0 0 0
// bouncing sparks
effect TE_SPIKE
-count 20
+count 10
type spark
color 0x8f4333 0xfff31b
size 0.4 0.4
alpha 256 256 128
// large sparks
effect TE_SPIKEQUAD
-count 20
+count 10
type static
color 0x2030FF 0x80C0FF
size 32 32
originjitter 6 6 6
// dust/smoke drifting away from the impact
effect TE_SUPERSPIKE
-count 8
+count 4
type smoke
tex 0 8
color 0x101010 0x101010
velocityjitter 8 8 8
// dust/smoke staying at the impact
effect TE_SUPERSPIKE
-count 1
+count 0.5
type smoke
tex 0 8
color 0x505050 0x505050
velocityjitter 0 0 0
// sparks that disappear on impact
effect TE_SUPERSPIKE
-count 30
+count 15
type spark
color 0x8f4333 0xfff31b
size 0.4 0.4
lightcolor 0.15 0.15 1.5
// dust/smoke drifting away from the impact
effect TE_SUPERSPIKEQUAD
-count 8
+count 4
type smoke
tex 0 8
color 0x101010 0x101010
velocityjitter 8 8 8
// dust/smoke staying at the impact
effect TE_SUPERSPIKEQUAD
-count 1
+count 0.5
type smoke
tex 0 8
color 0x505050 0x505050
velocityjitter 0 0 0
// sparks that disappear on impact
effect TE_SUPERSPIKEQUAD
-count 30
+count 15
type spark
color 0x8f4333 0xfff31b
size 0.4 0.4
originjitter 6 6 6
// dust/smoke drifting away from the impact
effect TE_GUNSHOT
-count 4
+count 2
type smoke
tex 0 8
color 0x101010 0x101010
velocityjitter 8 8 8
// dust/smoke staying at the impact
effect TE_GUNSHOT
-count 1
+count 0.5
type smoke
tex 0 8
color 0x505050 0x505050
velocityjitter 0 0 0
// bouncing sparks
effect TE_GUNSHOT
-count 10
+count 5
type spark
color 0x8f4333 0xfff31b
size 0.4 0.4
alpha 256 256 512
// purple sparks
effect TE_GUNSHOTQUAD
-count 12
+count 6
type spark
color 0xA040C0 0xFFFFFF
size 1 1
// fire effect which expands then slows
effect TE_EXPLOSION
notunderwater
-count 128
+count 64
type static
tex 48 55
color 0x902010 0xFFD080
// underwater bubbles
effect TE_EXPLOSION
underwater
-count 32
+count 16
type bubble
tex 62 62
color 0x404040 0x808080
// bouncing sparks
effect TE_EXPLOSION
notunderwater
-count 32
+count 16
type spark
color 0x903010 0xFFD030
size 2 2
// smoke cloud
effect TE_EXPLOSIONQUAD
notunderwater
-count 32
+count 16
type smoke
color 0x202020 0x404040
tex 0 8
// underwater bubbles
effect TE_EXPLOSIONQUAD
underwater
-count 32
+count 16
type bubble
tex 62 62
color 0x404040 0x808080
// sparks which go through walls
effect TE_EXPLOSIONQUAD
notunderwater
-count 128
+count 64
type spark
color 0x903010 0xFFD030
size 1 1
// smoke cloud
effect TE_TAREXPLOSION
notunderwater
-count 32
+count 16
type smoke
color 0x202020 0x404040
tex 0 8
// underwater bubbles
effect TE_TAREXPLOSION
underwater
-count 32
+count 16
type bubble
tex 62 62
color 0x404040 0x808080
// sparks which go through walls
effect TE_TAREXPLOSION
notunderwater
-count 128
+count 64
type spark
color 0x903010 0xFFD030
size 1 1
// bloody impact effect indicating damage
// used nowhere in code
effect TE_BLOOD
-count 0.333
+count 0.167
type blood
tex 24 32
size 8 8
// used in qcsrc/server/antilag.qc: te_spark(antilag_takebackorigin(e, time - e.antilag_debug), '0 0 0', 32)
// used in qcsrc/server/g_triggers.qc: self.mdl = "TE_SPARK"
effect TE_SPARK
-count 1
+count 0.5
type spark
tex 40 40
color 0x8f4333 0xfff31b
alpha 256 256 512
// small sparks which form a sphere as they slow down
effect TE_PLASMABURN
-count 256
+count 128
type spark
color 0x2030FF 0x80C0FF
size 1 2
// quake effect
// used nowhere in code
effect TE_FLAMEJET
-count 1
+count 0.5
type smoke
color 0x6f0f00 0xe3974f
size 4 4
// quake effect
// used nowhere in code
effect TE_LAVASPLASH
-count 64
+count 32
type alphastatic
color 0x6f0f00 0xe3974f
size 12 12
// player teleport effect
// used nowhere in code
effect TE_TELEPORT
-count 112
+count 56
type static
color 0xA0A0A0 0xFFFFFF
size 10 10
effect TE_TEI_G3
countabsolute 1
type beam
-tex 60 60
+tex 200 200
color 0xFFFFFF 0xFFFFFF
size 4 4
alpha 128 128 256
// experimental
effect TE_TEI_G3
-trailspacing 2
+trailspacing 4
type static
color 0x202020 0x404040
size 1 1
// smoke effect
// used nowhere in code
effect TE_TEI_SMOKE
-count 0.333
+count 0.167
type smoke
color 0x202020 0x404040
tex 0 8
// fire effect
effect TE_TEI_BIGEXPLOSION
notunderwater
-count 256
+count 128
type static
tex 48 55
color 0x902010 0xFFD080
// underwater bubbles
effect TE_TEI_BIGEXPLOSION
underwater
-count 64
+count 32
type bubble
tex 62 62
color 0x404040 0x808080
// bouncing sparks
effect TE_TEI_BIGEXPLOSION
notunderwater
-count 128
+count 64
type spark
color 0x903010 0xFFD030
size 2 2
alpha 256 256 512
// cloud of bouncing sparks
effect TE_TEI_PLASMAHIT
-count 1
+count 0.5
type spark
color 0x2030FF 0x80C0FF
size 2 4
// used in qcsrc/client/gibs.qc: pointparticles(particleeffectnum("blood"), self.origin + '0 0 1', '0 0 30', 10)
// used in qcsrc/client/gibs.qc: pointparticles(particleeffectnum("blood"), org, vel, amount * 16)
effect blood
-count 0.333
+count 0.167
type blood
tex 24 32
size 3 8
// used in qcsrc/server/t_teleporters.qc: pointparticles(particleeffectnum("teleport"), player.origin, '0 0 0', 1)
// used in qcsrc/server/t_teleporters.qc: pointparticles(particleeffectnum("teleport"), to + v_forward * 32, '0 0 0', 1)
effect teleport
-count 1000
+count 500
type spark
-tex 40 40
-color 0x807aff 0x4463d5
-size 1 3
+tex 64 64
+color 0xff8400 0xff2a00
+size 1 1
alpha 0 256 100
+stretchfactor 2
//gravity 1
bounce 1.5
originjitter 1 1 1
velocitymultiplier 0.5
airfriction 2
stretchfactor 0.6
+effect teleport
+countabsolute 1
+type smoke
+tex 65 65
+size 150 150
+alpha 190 190 180
+sizeincrease -80
+color 0xff8400 0xff2a00
// normal super gory blood trail (used by gibs)
// used in qcsrc/client/gibs.qc: trailparticles(self, particleeffectnum("TR_BLOOD"), oldorg, self.origin)
effect TR_BLOOD
-trailspacing 16
+trailspacing 32
type blood
color 0xA8FFFF 0xA8FFFF
tex 24 32
// thinner blood trail (used by quake zombies)
// used in qcsrc/client/gibs.qc: trailparticles(self, particleeffectnum("TR_SLIGHTBLOOD"), oldorg, self.origin)
effect TR_SLIGHTBLOOD
-trailspacing 32
+trailspacing 64
type blood
color 0xA8FFFF 0xA8FFFF
tex 24 32
// used in qcsrc/server/g_triggers.qc: self.effects = EF_STARDUST
// used in qcsrc/server/portals.qc: portal.effects = EF_STARDUST | EF_BLUE
effect EF_STARDUST
-count 75
+count 37.5
type static
color 0xfff368 0xfff368
size 1.0 2.0
alpha 128 128 128
// cloud of particles which expand rapidly and then slow to form a ball
effect item_respawn
-count 256
+count 128
type spark
tex 41 41
color 0x63F2EA 0x63f2EA
// used in qcsrc/server/w_hlac.qc: pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
// used in qcsrc/server/w_laser.qc: pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
effect laser_muzzleflash
-count 1
+// glow and light
+countabsolute 1
type smoke
-color 0xFFFFFF 0xFFFFFF
-tex 0 8
-size 5 5
-alpha 64 64 128
-airfriction 12
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
-velocitymultiplier 0.01
+color 0xcc0000 0xff0000
+tex 65 65
+size 10 15
+alpha 256 512 6280
+airfriction 10
+sizeincrease -100
+stretchfactor 2
lightradius 200
lightradiusfade 2000
lightcolor 3 0.1 0.1
-
+// electricity
+effect laser_muzzleflash
+count 3
+type spark
+color 0xb44215 0xff0000
+tex 43 43
+size 5 7
+alpha 256 512 6280
+airfriction 10
+originjitter 2 2 2
+velocityjitter 150 150 150
+velocitymultiplier 0.2
+sizeincrease -100
+stretchfactor 2.3
+rotate -180 180 4000 -4000
+// fire
+effect laser_muzzleflash
+count 6
+type spark
+color 0xff4200 0xff0000
+tex 8 15
+size 7 9
+alpha 256 512 6280
+airfriction 12
+originjitter 2 2 2
+velocityjitter 100 100 100
+velocitymultiplier 0.2
+sizeincrease -100
+stretchfactor 2
// decal
size 24 24
// sparks that rapidly expand and rapidly slow down to form an interesting spherical effect
effect laser_impact
-count 256
+count 128
type spark
color 0x800000 0xFF8020
alpha 256 256 1024
//originjitter 32 32 32
velocityjitter 256 256 256
effect laser_impact
-count 8
+count 4
type smoke
tex 48 55
color 0x800000 0xFF8020
// used in qcsrc/server/w_shotgun.qc: pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 1000, cvar("g_balance_shotgun_primary_ammo"))
// used in qcsrc/server/w_shotgun.qc: pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 1000, cvar("g_balance_shotgun_secondary_ammo"))
effect shotgun_muzzleflash
-count 3
+count 1.5
type smoke
color 0x202020 0x404040
tex 0 8
sizeincrease 12
velocitymultiplier 0.05
effect shotgun_muzzleflash
-count 10
+count 16
type spark
-tex 40 40
-color 0xFFFDD9 0xff5a00
-size 2 2
+tex 48 55
+color 0xffdb96 0xff5400
+size 10 20
alpha 0 128 1024
originjitter 1 1 1
-velocityjitter 444 444 444
-velocitymultiplier 1.7
-gravity 0.3
+velocityjitter 100 100 100
airfriction 5
-
-
+stretchfactor 2.5
+velocitymultiplier 0.5
// shotgun pellet impact
// decal
countabsolute 1
type decal
tex 56 59
-size 3 3
+size 5 8
alpha 256 256 0
originjitter 10 10 10
//lightradius 30
//lightcolor 1 1 1
// dust/smoke drifting away from the impact
effect shotgun_impact
-count 5
-type smoke
+type alphastatic
+notunderwater
tex 0 8
-color 0xFFFFFF 0xA37443
-size 7 7
-alpha 0 64 32
-originjitter 1 1 1
-airfriction 7
-liquidfriction 16
-velocityjitter 100 100 100
-sizeincrease 12
-velocitymultiplier 0.25
+count 3
+size 10 20
+sizeincrease 25
+alpha 300 550 756
+velocityjitter 150 150 150
+velocitymultiplier 0.2
+airfriction 5
+color 0x473a37 0x0b0a07
+rotate 0 360 -50 50
// dust/smoke staying at the impact
effect shotgun_impact
-count 1
-type smoke
-tex 0 8
-color 0xFFFFFF 0xFFFFFF
-size 17 17
-alpha 64 64 32
-sizeincrease 4
+type alphastatic
+notunderwater
+tex 36 36
+count 0.5
+size 10 11
+sizeincrease 74
+alpha 200 350 500
+velocityjitter 11 11 11
+airfriction 5
+color 0x201d1a 0x000000
+bounce 6
+velocitymultiplier 0.03
+rotate 0 360 -50 50
// sparks
effect shotgun_impact
notunderwater
-count 20
+count 1.5
type spark
tex 40 40
color 0xFDFFD9 0xFDFFD9
size 0.6 0.6
-alpha 256 256 768
+alpha 0 356 268
gravity 1
-bounce 1
-airfriction 5
+bounce 1.5
+airfriction 1.1
originjitter 1 1 1
-velocityjitter 400 400 400
-velocitymultiplier 0.1
-
+velocityjitter 200 200 200
+velocitymultiplier 0.2
// used in qcsrc/server/w_uzi.qc: pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
effect uzi_muzzleflash
-count 2
+count 1
type static
color 0x202020 0x404040
tex 0 8
lightcolor 2 1.5 0.2
gravity -0.1
effect uzi_muzzleflash
-count 20
+count 10
type spark
tex 40 40
color 0xFFFDD9 0xFFFDD9
airfriction 12
-// decal
// used in qcsrc/server/cl_client.qc: //pointparticles(particleeffectnum("machinegun_impact"), self.origin + self.view_ofs + '0 0 7', '0 0 0', 1)
// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("machinegun_impact"), org2, backoff * 1000, 1)
// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("machinegun_impact"), org2, backoff * 1000, 1)
+// decal
effect machinegun_impact
countabsolute 1
type decal
lightcolor 6 3.6 0.6
// dust/smoke drifting away from the impact
effect machinegun_impact
-count 5
-type smoke
+type alphastatic
+notunderwater
tex 0 8
-color 0xFFFFFF 0xA37443
-size 7 7
-alpha 0 64 32
-originjitter 1 1 1
-airfriction 7
-liquidfriction 16
-velocityjitter 100 100 100
-sizeincrease 12
-velocitymultiplier 0.25
+count 3
+size 10 20
+sizeincrease 15
+alpha 300 550 456
+velocityjitter 150 150 150
+velocitymultiplier 0.1
+airfriction 5
+color 0x473a37 0x0b0a07
+rotate 0 360 -50 50
// dust/smoke staying at the impact
effect machinegun_impact
+type alphastatic
+notunderwater
+tex 36 36
+count 0.5
+size 10 11
+sizeincrease 74
+alpha 200 350 500
+velocityjitter 11 11 11
+airfriction 5
+color 0x201d1a 0x000000
+bounce 6
+velocitymultiplier 0.03
+rotate 0 360 -50 50
+//derbis
+effect machinegun_impact
+type alphastatic
+notunderwater
+tex 66 68
count 1
-type smoke
-tex 0 8
-color 0xFFFFFF 0xFFFFFF
-size 17 17
-alpha 64 64 32
-sizeincrease 4
+size 1 5
+airfriction 1
+gravity 1.4
+alpha 300 550 256
+velocityjitter 350 350 350
+velocitymultiplier 0.2
+bounce 1.7
+color 0x63493e 0xffffff
+rotate 0 360 -500 500
// sparks
effect machinegun_impact
notunderwater
-count 20
+count 1
type spark
tex 40 40
color 0xFDFFD9 0xFDFFD9
size 0.3 0.3
-alpha 256 256 768
+alpha 256 256 168
gravity 1
bounce 1
-airfriction 5
+airfriction 2
originjitter 1 1 1
-velocityjitter 400 400 400
-velocitymultiplier 0.1
+velocityjitter 300 300 300
+velocitymultiplier 0.2
+
// used in qcsrc/server/w_grenadelauncher.qc: pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
// used in qcsrc/server/w_porto.qc: //pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
effect grenadelauncher_muzzleflash
-count 3
+count 1.5
type smoke
color 0x202020 0x404040
tex 0 8
lightradiusfade 2000
lightcolor 2 1.5 0.2
effect grenadelauncher_muzzleflash
-count 30
+count 16
type spark
-tex 40 40
-color 0xFFFDD9 0xFFFDD9
-size 3 3
+tex 48 55
+color 0xffdb96 0xff5400
+size 10 20
alpha 0 128 1024
originjitter 1 1 1
-velocityjitter 300 300 300
+velocityjitter 100 100 100
velocitymultiplier 0.5
-airfriction 12
+airfriction 5
+stretchfactor 2.5
// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_GRENADE"), from, to)
// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_GRENADE"), from, to)
effect TR_GRENADE
-trailspacing 6
-type alphastatic
-color 0x303030 0x000000
+trailspacing 4
+type smoke
+color 0x101010 0x000000
tex 0 8
-size 1 2
+size 3 2
bounce 1
-sizeincrease 2
-alpha 100 200 280
+sizeincrease 10
+alpha 300 400 780
originjitter 1 1 1
velocityjitter 1 1 1
velocitymultiplier -0.02
// fire
effect TR_GRENADE
notunderwater
-trailspacing 2
+trailspacing 4
type static
color 0xffdf72 0x811200
tex 48 55
// bubbles
effect TR_GRENADE
underwater
-trailspacing 8
+trailspacing 16
type bubble
tex 62 62
color 0x404040 0x808080
// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_KNIGHTSPIKE"), from, to)
effect TR_KNIGHTSPIKE // used for MF_TRACER2
notunderwater
-trailspacing 5
-type alphastatic
+trailspacing 6
+type smoke
color 0x303030 0x000000
tex 0 8
size 3 3
bounce 1
sizeincrease 11
-alpha 100 200 400
+alpha 300 400 600
originjitter 2 2 2
velocityjitter 3 3 3
velocitymultiplier -0.02
tex 62 62
size 1 1
sizeincrease -0.1
-trailspacing 1
+trailspacing 2
alpha 256 256 720
// bubbles
effect TR_KNIGHTSPIKE // used for MF_TRACER2
underwater
-trailspacing 16
+trailspacing 32
type bubble
tex 62 62
color 0x404040 0x808080
countabsolute 1
type decal
tex 8 16
-size 72 72
+size 48 48
alpha 256 256 0
-originjitter 23 23 23
-lightradius 400
-lightradiusfade 750
+originjitter 26 26 26
+lightradius 250
+lightradiusfade 400
lightcolor 8 4 1
-// fire effect
+// fire effect which expands then slows
effect grenade_explode
notunderwater
-count 64
+count 40
type static
tex 48 55
-color 0x8f0d00 0xff5a00
-size 33 44
-sizeincrease 45
-alpha 200 256 512
-bounce 1.5
+color 0xe03f00 0x5e0000
+size 16 26
+sizeincrease 20
+alpha 128 228 356
+bounce 4.5
airfriction 8
liquidfriction 8
originjitter 8 8 8
-velocityjitter 512 512 512
-// fire effect 2
+velocityjitter 256 256 256
+// fire effect which make brigt dot inside
effect grenade_explode
notunderwater
-count 28
-type smoke
+count 15
+type static
tex 48 55
-color 0xea691b 0xeed05a
-size 33 44
-sizeincrease 55
-alpha 200 256 612
-bounce 2.5
-airfriction 19
-liquidfriction 19
+color 0xe03f00 0xffdf92
+size 6 16
+sizeincrease 40
+alpha 228 328 756
+bounce 1
+airfriction 8
+liquidfriction 8
originjitter 8 8 8
-velocityjitter 912 912 912
+velocityjitter 256 256 256
// smoke
effect grenade_explode
type alphastatic
notunderwater
tex 0 8
-count 64
+count 10
size 20 40
-sizeincrease 44
-alpha 200 450 456
-velocityjitter 444 444 444
+sizeincrease 34
+alpha 300 550 556
+velocityjitter 256 256 256
airfriction 5
color 0x000000 0x111111
-bounce 2
+bounce 6
// underwater bubbles
effect grenade_explode
underwater
-count 64
+count 32
type bubble
tex 62 62
color 0x404040 0x808080
-size 3 3
+size 3 6
alpha 128 256 64
gravity -0.125
bounce 1.5
liquidfriction 0.25
originjitter 16 16 16
-velocityjitter 144 144 144
+velocityjitter 196 196 196
+rotate 0 0 0 0
+// underwatershockwave
+effect grenade_explode
+underwater
+type smoke
+countabsolute 1
+tex 33 33
+size 5 5
+sizeincrease 1500
+alpha 40 40 300
+velocitymultiplier 0.3
// bouncing sparks
effect grenade_explode
notunderwater
-count 64
+count 16
type spark
tex 40 40
-color 0xffa800 0xffedaf
-size 1 1
-sizeincrease 2
-alpha 44 256 384
+color 0xffa35b 0xfff2be
+size 1 0.1
+alpha 644 956 484
gravity 1
-airfriction -1
-bounce 1.5
+airfriction 1
+bounce 1.6
liquidfriction 0.8
velocityoffset 0 0 80
originjitter 16 16 16
-velocityjitter 224 224 324
+velocityjitter 424 424 624
+// derbis
+effect grenade_explode
+notunderwater
+count 12
+type alphastatic
+tex 66 68
+color 0x6a3d25 0xcac5b4
+size 2 6
+alpha 644 956 684
+gravity 1.3
+airfriction 0.5
+bounce 1.6
+velocityjitter 324 324 524
+rotate -180 180 -1000 1000
// used in qcsrc/server/w_electro.qc: pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
// used in qcsrc/server/w_electro.qc: pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
effect electro_muzzleflash
-count 1
+countabsolute 1
type smoke
color 0x283880 0x283880 // 0x202020 0x404040
-tex 0 8
-size 5 5
+tex 65 65
+size 15 15
alpha 256 256 512
originjitter 1.5 1.5 1.5
velocityjitter 6 6 6
+sizeincrease -10
velocitymultiplier 0.01
lightradius 200
lightradiusfade 2000
lightcolor 1.5 3 6
+
effect electro_muzzleflash
-count 30
+count 7
type spark
-tex 31 31
+tex 8 15
color 0xD9FDFF 0xD9FDFF
-size 3 3
-alpha 0 128 1024
+size 5 15
+alpha 110 228 2024
originjitter 1 1 1
-velocityjitter 300 300 300
+velocityjitter 150 150 150
velocitymultiplier 0.5
-airfriction 12
+airfriction 2
+stretchfactor 1.5
+effect electro_muzzleflash
+count 5
+type spark
+tex 41 41
+color 0xD9FDFF 0xD9FDFF
+size 7 6
+alpha 110 228 1024
+originjitter 1 1 1
+velocityjitter 350 350 350
+velocitymultiplier 2.5
+airfriction 8
+gravity 1.3
+stretchfactor 0.1
// electro trail
// glowing vapor trail
-// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_XONOTICPLASMA"), from, to)
-effect TR_XONOTICPLASMA
-trailspacing 1
+// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_NEXUIZPLASMA"), from, to)
+effect TR_NEXUIZPLASMA
+trailspacing 2
type static
color 0x283880 0x283880
size 3 3
lightcolor 1.5 3 6
velocitymultiplier -0.1
// bright sparks
-effect TR_XONOTICPLASMA
-trailspacing 6
-count 3
+effect TR_NEXUIZPLASMA
+trailspacing 12
+count 1.5
type snow
tex 42 42
color 0x629dff 0x0018ff
lightradius 250
lightradiusfade 250
lightcolor 3.125 4.375 10
+// shockwave
+effect electro_impact
+type smoke
+countabsolute 1
+tex 33 33
+size 32 32
+sizeincrease 1000
+color 0x80C0FF 0x80C0FF
+alpha 40 40 350
+velocitymultiplier 44
// flare effect
effect electro_impact
countabsolute 1
alpha 256 256 512
// cloud of bouncing sparks
effect electro_impact
-count 60
+count 30
type smoke
tex 42 42
color 0x629dff 0x0018ff
airfriction 6
originjitter 1 1 1
velocityjitter 512 512 512
+rotate -180 180 -9999 9999
// inner cloud of smoke
effect electro_impact
-count 60
+count 30
type smoke
color 0x629dff 0x0018ff
tex 0 8
alpha 256 256 512
// cloud of bouncing sparks
effect electro_ballexplode
-count 128
+count 64
type spark
tex 41 41
color 0xFDFFD9 0xFDFFD9
-size 16 16
+size 1 2
alpha 256 256 1024
bounce 2
+stretchfactor 0.4
//airfriction 2
originjitter 1 1 1
velocityjitter 512 512 512
// inner cloud of smoke
effect electro_ballexplode
-count 16
+count 8
type smoke
color 0x202020 0x404040
tex 0 8
alpha 128 128 64
// large sparks
effect electro_combo
-count 20
+count 5
type static
color 0x2030FF 0x80C0FF
size 32 32
-alpha 256 256 256
+sizeincrease 50
+tex 0 7
+alpha 156 156 156
bounce 2
airfriction 6
liquidfriction 16
//velocityoffset 0 0 120
velocityjitter 512 512 512
effect electro_combo
-count 64
+count 32
type spark
tex 41 41
-color 0xFDFFD9 0xFDFFD9
-size 16 16
-alpha 444 512 866
-bounce 2
+color 0xa9cacf 0x0054ff
+size 2 4
+stretchfactor 2
+gravity 0.3
+alpha 444 512 700
+velocitymultiplier 3
+bounce 1.6
//airfriction 2
originjitter 1 1 1
-velocityjitter 512 512 512
+velocityjitter 312 312 312
// inner cloud of smoke
effect electro_combo
-count 0.25
+count 0.125
type smoke
color 0x202020 0x404040
tex 0 8
alpha 256 256 256
originjitter 20 20 20
velocityjitter 32 32 32
+// shockwave
+effect electro_combo
+type smoke
+countabsolute 1
+color 0xa9cacf 0x0054ff
+tex 33 33
+size 30 30
+sizeincrease 600
+alpha 40 40 100
+velocitymultiplier 0.3
// used in qcsrc/server/w_crylink.qc: pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots)
// used in qcsrc/server/w_crylink.qc: pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots)
effect crylink_muzzleflash
-count 1
+count 0.5
type smoke
-color 0x202020 0x404040
-tex 0 8
-size 5 5
-alpha 128 128 256
-originjitter 1.5 1.5 1.5
-velocityjitter 6 6 6
+color 0xdd9cff 0xff0090
+tex 65 65
+size 15 20
+alpha 128 128 2024
velocitymultiplier 0.01
lightradius 200
lightradiusfade 2000
lightcolor 1.6 0.2 2
effect crylink_muzzleflash
-count 10
+count 5
type spark
-tex 40 40
+tex 35 36
color 0xA080C0 0xA080C0
-size 3 3
+size 5 10
alpha 0 128 1024
originjitter 1 1 1
velocityjitter 200 200 200
velocitymultiplier 0.3
airfriction 12
-
+stretchfactor 1.5
// crylink impact effect
alpha 256 256 512
// purple sparks
effect crylink_impact
-count 20
+count 10
type spark
tex 41 41
color 0xA040C0 0xA040C0
bounce 2
-size 4 4
+size 1 2
alpha 256 256 1024
velocityjitter 256 256 256
// purple splash
effect crylink_impact
-count 3
+count 1.5
type static
color 0xE070FF 0xE070FF
size 8 8
velocityjitter 8 8 8
// purple splash
effect crylink_impact
-count 3
+count 1.5
type static
color 0xE070FF 0xE070FF
size 8 8
// used in qcsrc/server/w_minstanex.qc: pointparticles(particleeffectnum("nex_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
// used in qcsrc/client/particles.qc: pointparticles(particleeffectnum("nex_muzzleflash"), shotorg, normalize(endpos - shotorg) * 1000, 1)
effect nex_muzzleflash
-count 10
-type smoke
-color 0x202020 0x404040
-tex 0 8
+count 12
+type spark
+color 0x202020 0x0072ff
+tex 48 55
size 16 16
-alpha 128 128 192
+alpha 328 328 4000
originjitter 4 4 4
-velocityjitter 24 24 24
-velocitymultiplier 0.02
+velocityjitter 180 180 180
+velocitymultiplier 1.4
+stretchfactor 2
+sizeincrease -100
+airfriction 9
lightradius 200
lightradiusfade 200
lightcolor 2 2.5 3
effect nex_muzzleflash
-count 150
+count 50
type spark
tex 41 41
color 0xD9FDFF 0xD9FDFF
-size 3 3
+size 1 1
alpha 0 128 1024
originjitter 1 1 1
velocityjitter 600 600 600
-velocitymultiplier 0.5
+velocitymultiplier 1.5
airfriction 9
//effect nex_beam
//countabsolute 1
//type beam
-//tex 60 60
+//tex 200 200
//color 0xFFFFFF 0xFFFFFF
//size 6 6
//alpha 128 128 192
// nex beam: ring smoke
// used in qcsrc/client/particles.qc: trailparticles(world, particleeffectnum("nex_beam"), shotorg, endpos)
effect nex_beam
-trailspacing 32
+trailspacing 64
color 0x1680A0 0x1680A0
size 4 4
tex 32 32
type static
// nex beam: drifting smoke
effect nex_beam
-trailspacing 6
+trailspacing 12
color 0x5080A0 0x5080A0
size 1 1
tex 0 8
type static
// nex beam: bright core
effect nex_beam
-trailspacing 6
+trailspacing 12
color 0x80CDFF 0x80CDFF
size 4 4
//tex 48 55
type static
//sparks
effect nex_beam
-trailspacing 8
+trailspacing 16
color 0x1680A0 0x1680A0
size 1 1
tex 63 63
lightradius 200
lightradiusfade 250
lightcolor 4 6 8
+rotate -180 180 0 0
+// rotating something
+effect nex_impact
+count 5
+type smoke
+tex 46 46
+color 0x1680A0 0x1680A0
+size 25 28
+sizeincrease 20
+alpha 55 55 50
+rotate 180 -180 500 -500
// shockwave
effect nex_impact
countabsolute 1
type static
-tex 34 34
+tex 33 33
+color 0x1680A0 0x1680A0
size 16 16
-alpha 100 100 300
-sizeincrease 200
-
+alpha 50 50 400
+sizeincrease 900
+// shockwave2
+effect nex_impact
+countabsolute 1
+type static
+tex 65 65
+color 0x1680A0 0x1680A0
+size 5 5
+alpha 50 50 100
+sizeincrease 500
// flare effect
effect nex_impact
//velocityjitter 384 384 384
// small sparks which glow brightly but live briefly
effect nex_impact
-count 128
+count 64
type spark
tex 41 41
color 0xD9FDFF 0xD9FDFF
size 4 4
alpha 0 128 512
bounce 2
+stretchfactor 3
velocityjitter 600 600 600
velocitymultiplier 0.5
airfriction 9
-
-
+// small sparks that live longer
+effect nex_impact
+count 16
+type spark
+tex 41 41
+color 0xD9FDFF 0xD9FDFF
+size 2 2
+alpha 255 255 112
+bounce 1.6
+stretchfactor 0.7
+velocityjitter 300 300 600
+velocitymultiplier 2.5
+airfriction 2
+gravity 1
// used in qcsrc/server/w_hagar.qc: pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
// used in qcsrc/server/w_hagar.qc: pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
// used in qcsrc/server/w_seeker.qc: pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
effect hagar_muzzleflash
-count 4
+count 2
type smoke
color 0x202020 0x404040
tex 0 8
lightradiusfade 2000
lightcolor 2 1.5 0.2
effect hagar_muzzleflash
-count 30
+count 15
type spark
-tex 40 40
-color 0xFFFDD9 0xFFFDD9
-size 3 3
+tex 48 55
+color 0xff8400 0xff4200
+size 5 10
alpha 0 128 1024
originjitter 1 1 1
-velocityjitter 300 300 300
+velocityjitter 200 200 200
velocitymultiplier 0.5
airfriction 12
+stretchfactor 2
+rotate -180 180 -400 400
// used in qcsrc/server/w_hagar.qc: pointparticles(particleeffectnum("hagar_bounce"), self.origin, self.velocity, 1)
effect hagar_bounce
-count 4
+count 2
type smoke
color 0x202020 0x404040
tex 0 8
lightradiusfade 300
lightcolor 2 1.5 0.2
effect hagar_bounce
-count 30
+count 15
type spark
tex 40 40
color 0xFFFDD9 0xFFFDD9
// fire effect which make bright dot inside
effect hagar_explode
notunderwater
-count 10
+count 5
type smoke
tex 48 55
color 0xffe955 0xff5a00
// fire effect which expands then slows
effect hagar_explode
notunderwater
-count 24
+count 12
type static
tex 48 55
color 0x8f0d00 0xff5a00
type alphastatic
notunderwater
tex 0 8
-count 20
+count 10
size 20 40
sizeincrease 20
alpha 200 500 600
// underwater bubbles
effect hagar_explode
underwater
-count 32
+count 16
type bubble
tex 62 62
color 0x404040 0x808080
// bouncing sparks
effect hagar_explode
notunderwater
-count 16
+count 4
type spark
-color 0x903010 0xFFD030
-size 2 2
tex 40 40
-alpha 256 256 384
+color 0xffa35b 0xfff2be
+size 1 0.1
+alpha 644 956 684
gravity 1
-airfriction 0.2
-bounce 1.5
+airfriction 1
+bounce 1.6
liquidfriction 0.8
velocityoffset 0 0 80
-velocityjitter 256 256 256
+originjitter 16 16 16
+velocityjitter 224 224 224
// used in qcsrc/server/w_rocketlauncher.qc: pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1)
effect rocketlauncher_muzzleflash
-count 20
+count 10
type smoke
color 0x202020 0x404040
tex 0 8
//lightradiusfade 2000
//lightcolor 2 1.5 0.2
effect rocketlauncher_muzzleflash
-count 30
-type spark
-tex 40 40
+count 6
+type smoke
+tex 35 36
color 0xFFFDD9 0xFFFDD9
-size 3 3
-alpha 0 128 1024
-originjitter 1 1 1
-velocityjitter 300 300 300
-velocitymultiplier 0.5
-airfriction 12
+size 5 10
+sizeincrease 20
+alpha 10 25 20
+originjitter 3 3 3
+velocityjitter 100 100 100
+velocitymultiplier 0.3
+airfriction 9
+rotate -180 180 -30 30
// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_ROCKET"), from, to)
// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_ROCKET"), from, to)
effect TR_ROCKET
-trailspacing 5
-type alphastatic
+trailspacing 10
+type smoke
+notunderwater
color 0x000000 0x666666
tex 0 8
-size 1 4
+size 3 4
bounce 1
sizeincrease 11
alpha 200 300 200
originjitter 2 2 2
velocityjitter 3 3 3
velocitymultiplier -0.02
+rotate -180 180 -30 30
//gravity -0.11
// fire
effect TR_ROCKET
-notunderwater
-trailspacing 2
+trailspacing 4
type static
color 0xffdf72 0x811200
tex 48 55
velocitymultiplier -1.5
// bubbles
effect TR_ROCKET
-underwater
-trailspacing 8
type bubble
+underwater
+trailspacing 16
tex 62 62
-color 0x404040 0x808080
-size 1 1
+size 1 2
alpha 256 256 256
gravity -0.125
bounce 1.5
liquidfriction 4
velocityjitter 16 16 16
+velocitymultiplier -0.31
+rotate 0 0 0 0
// sparks
effect TR_ROCKET
-trailspacing 10
+notunderwater
+trailspacing 20
type spark
tex 40 40
color 0xFFFDD9 0xFFFDD9
-size 1 1
+size 0.5 0.5
alpha 444 512 1866
+stretchfactor 0.3
//gravity 1
bounce 1
//velocityoffset 0 0 15
countabsolute 1
type decal
tex 8 16
-size 48 48
+size 72 72
alpha 256 256 0
-originjitter 26 26 26
-lightradius 250
-lightradiusfade 400
+originjitter 23 23 23
+lightradius 400
+lightradiusfade 750
lightcolor 8 4 1
-// fire effect which expands then slows
+// fire effect
effect rocket_explode
notunderwater
-count 80
+count 32
type static
tex 48 55
-color 0xe03f00 0x5e0000
-size 16 26
-sizeincrease 20
-alpha 128 228 356
-bounce 4.5
+color 0x8f0d00 0xff5a00
+size 33 44
+sizeincrease 45
+alpha 200 256 512
+bounce 1.5
airfriction 8
liquidfriction 8
originjitter 8 8 8
-velocityjitter 256 256 256
-// fire effect which make brigt dot inside
+velocityjitter 512 512 512
+// fire effect 2
effect rocket_explode
notunderwater
-count 30
-type static
+count 14
+type smoke
tex 48 55
-color 0xe03f00 0xffdf92
-size 6 16
-sizeincrease 40
-alpha 228 328 756
-bounce 1
-airfriction 8
-liquidfriction 8
+color 0xea691b 0xeed05a
+size 33 44
+sizeincrease 55
+alpha 200 256 612
+bounce 2.5
+airfriction 19
+liquidfriction 19
originjitter 8 8 8
-velocityjitter 256 256 256
+velocityjitter 912 912 912
// smoke
effect rocket_explode
type alphastatic
notunderwater
tex 0 8
-count 20
+count 32
size 20 40
-sizeincrease 34
-alpha 300 550 556
-velocityjitter 256 256 256
+sizeincrease 44
+alpha 200 450 456
+velocityjitter 444 444 444
airfriction 5
color 0x000000 0x111111
-bounce 6
+bounce 2
// underwater bubbles
effect rocket_explode
underwater
bounce 1.5
liquidfriction 0.25
originjitter 16 16 16
-velocityjitter 96 96 96
+velocityjitter 144 144 144
+// underwatershockwave
+effect rocket_explode
+underwater
+type smoke
+countabsolute 1
+tex 33 33
+size 30 30
+sizeincrease 1900
+alpha 40 40 300
+velocitymultiplier 0.3
// bouncing sparks
effect rocket_explode
notunderwater
count 16
type spark
-color 0x903010 0xFFD030
-size 2 2
tex 40 40
-alpha 256 256 384
+color 0xffa35b 0xfff2be
+size 1 0.1
+alpha 644 956 484
gravity 1
-airfriction 0.2
-bounce 1.5
+airfriction 1
+bounce 1.6
liquidfriction 0.8
velocityoffset 0 0 80
-velocityjitter 256 256 256
-
-
+originjitter 16 16 16
+velocityjitter 424 424 624
+// derbis
+effect rocket_explode
+notunderwater
+count 12
+type alphastatic
+tex 66 68
+color 0x6a3d25 0xcac5b4
+size 2 6
+alpha 644 956 684
+gravity 1.3
+airfriction 0.5
+bounce 1.6
+velocityjitter 324 324 524
+rotate -180 180 -1000 1000
// used in qcsrc/server/g_hook.qc: pointparticles(particleeffectnum("grapple_muzzleflash"), org, '0 0 0', 1)
effect grapple_muzzleflash
effect nex242_misc_laser_beam
countabsolute 1
type beam
-tex 60 60
+tex 200 200
size 1 1
alpha 256 256 64
color 0xff0000 0xff0000
// used nowhere in code
effect nex242_misc_laser_beam_end
-count 1
+count 0.5
type spark
color 0x8f4333 0xfff31b
size 0.4 0.4
effect nex242_misc_laser_beam_fast
countabsolute 1
type beam
-tex 60 60
+tex 200 200
size 1 1
alpha 256 256 640
color 0xff0000 0xff0000
// used nowhere in code
effect nex242_misc_laser_beam_fast_end
-count 1
+count 0.5
type spark
color 0x8f4333 0xfff31b
size 0.4 0.4
effect nex242_misc_laser_green_beam
countabsolute 1
type beam
-tex 60 60
+tex 200 200
size 1 1
alpha 256 256 64
color 0x00ff00 0x00ff00
// used nowhere in code
effect nex242_misc_laser_green_beam_end
-count 1
+count 0.5
type spark
color 0x8f4333 0xfff31b
size 0.4 0.4
effect nex242_misc_laser_blue_beam
countabsolute 1
type beam
-tex 60 60
+tex 200 200
size 1 1
alpha 256 256 64
color 0x0000ff 0x0000ff
// used nowhere in code
effect nex242_misc_laser_blue_beam_end
-count 1
+count 0.5
type spark
color 0x8f4333 0xfff31b
size 0.4 0.4
effect nex242_misc_laser_yellow_beam
countabsolute 1
type beam
-tex 60 60
+tex 200 200
size 1 1
alpha 256 256 64
color 0xffff00 0xffff00
// used nowhere in code
effect nex242_misc_laser_yellow_beam_end
-count 1
+count 0.5
type spark
color 0x8f4333 0xfff31b
size 0.4 0.4
effect nex242_misc_laser_cyan_beam
countabsolute 1
type beam
-tex 60 60
+tex 200 200
size 1 1
alpha 256 256 64
color 0x00ffff 0x00ffff
// used nowhere in code
effect nex242_misc_laser_cyan_beam_end
-count 1
+count 0.5
type spark
color 0x8f4333 0xfff31b
size 0.4 0.4
effect nex242_misc_laser_magenta_beam
countabsolute 1
type beam
-tex 60 60
+tex 200 200
size 1 1
alpha 256 256 64
color 0xff00ff 0xff00ff
// used nowhere in code
effect nex242_misc_laser_magenta_beam_end
-count 1
+count 0.5
type spark
color 0x8f4333 0xfff31b
size 0.4 0.4
effect nex242_misc_laser_white_beam
countabsolute 1
type beam
-tex 60 60
+tex 200 200
size 1 1
alpha 256 256 64
color 0xffffff 0xffffff
// used nowhere in code
effect nex242_misc_laser_white_beam_end
-count 1
+count 0.5
type spark
color 0x8f4333 0xfff31b
size 0.4 0.4
effect nex242_misc_laser_black_beam
countabsolute 1
type beam
-tex 60 60
+tex 200 200
size 1 1
alpha 256 256 64
color 0x000000 0x000000
// used nowhere in code
effect nex242_misc_laser_black_beam_end
-count 1
+count 0.5
type spark
color 0x8f4333 0xfff31b
size 0.4 0.4
effect nex242_misc_laser_orange_beam
countabsolute 1
type beam
-tex 60 60
+tex 200 200
size 1 1
alpha 256 256 64
color 0xff6600 0xff6600
// used nowhere in code
effect nex242_misc_laser_orange_beam_end
-count 1
+count 0.5
type spark
color 0x8f4333 0xfff31b
size 0.4 0.4
alpha 256 256 512
// purple sparks
effect crylink_impactbig
-count 80
+count 40
type spark
tex 41 41
color 0xA040C0 0xA040C0
velocityjitter 512 512 512
// purple splash
effect crylink_impactbig
-count 3
+count 1.5
type static
color 0xE070FF 0xE070FF
size 16 16
velocityjitter 32 32 32
// purple splash
effect crylink_impactbig
-count 6
+count 3
type static
color 0xE070FF 0xE070FF
size 16 16
// used in qcsrc/client/gibs.qc: pointparticles(particleeffectnum("damage_hit"), org, vel, amount * 16)
effect damage_hit
tex 48 55
-count 1
+count 0.5
type alphastatic
color 0x00FFFF 0xFF00FF
size 16 16
velocityjitter 256 256 256
effect damage_hit
tex 48 55
-count 1
+count 0.5
type alphastatic
color 0xFF00FF 0xFFFF00
size 16 16
velocityjitter 256 256 256
effect damage_hit
tex 48 55
-count 1
+count 0.5
type alphastatic
color 0xFFFF00 0x00FFFF
size 16 16
// used in qcsrc/client/gibs.qc: pointparticles(particleeffectnum("damage_dissolve"), org, vel, amount)
effect damage_dissolve
tex 48 55
-count 30
+count 15
type alphastatic
color 0x00FFFF 0xFF00FF
size 32 32
velocityjitter 512 512 512
effect damage_dissolve
tex 48 55
-count 30
+count 15
type alphastatic
color 0xFF00FF 0xFFFF00
size 32 32
velocityjitter 512 512 512
effect damage_dissolve
tex 48 55
-count 30
+count 15
type alphastatic
color 0xFFFF00 0x00FFFF
size 32 32
liquidfriction 6
velocityjitter 512 512 512
+
// decal
// used in qcsrc/server/g_triggers.qc: self.cnt = particleeffectnum("laser_deadly")
// used in qcsrc/server/g_triggers.qc: self.cnt = particleeffectnum("laser_deadly")
originjitter 6 6 6
// dust/smoke drifting away from the impact
effect laser_deadly
-count 0.05 // 50 per second
+count 0.025
type smoke
tex 48 55
color 0xFFFFFF 0xFFFFFF
// sparks
effect laser_deadly
notunderwater
-count 0.05 // 50 per second
+count 0.025
type spark
tex 40 40
color 0xFDFFD9 0xFDFFD9
// used nowhere in code
effect torch_small
//notunderwater
-count 16
+count 8
type smoke
tex 48 55
size 1 11
// smoke
effect torch_small
type alphastatic
-count 8
+count 4
tex 0 8
size 5 10
sizeincrease 5
//fountain01
// used nowhere in code
effect fountain01
-count 32
+count 16
tex 0 8
size 10 15
alpha 0 100 100
// decal
// used in qcsrc/client/damage.qc: pointparticles(particleeffectnum("hookbomb_explode"), org2, '0 0 0', 1)
effect hookbomb_explode
-count 50
+count 25
type static
tex 38 38
color 0x807aff 0x4463d5
originjitter 6 6 6
// some sparks
effect hookbomb_explode
-count 60
+count 30
type spark
tex 38 38
color 0x807aff 0x4463d5
// smoke
effect EF_MGTURRETTRAIL
notunderwater
-trailspacing 5
+trailspacing 10
type smoke
color 0xd0d0a0 0xffffff
tex 0 8
// bubbles
effect EF_MGTURRETTRAIL
underwater
-trailspacing 16
+trailspacing 32
type bubble
tex 62 62
color 0x404040 0x808080
// used nowhere in code
effect fire_big
//notunderwater
-count 52
+count 26
type smoke
tex 48 55
size 11 31
// smoke
effect fire_big
type alphastatic
-count 22
+count 11
tex 0 8
size 22 33
sizeincrease 11
// used nowhere in code
effect red_flare
type alphastatic
-count 21
+count 10.5
tex 0 8
size 1 11
sizeincrease 11
// used nowhere in code
effect blue_flare
type alphastatic
-count 21
+count 10.5
tex 0 8
size 1 11
sizeincrease 11
// used in qcsrc/server/ctf.qc: pointparticles(particleeffectnum("smoke_ring"), 0.5 * (self.absmin + self.absmax), '0 0 0', 1);
effect smoke_ring
type smoke
-count 90
+count 45
tex 0 8
size 1 11
sizeincrease 21
// used nowhere in code
effect smoke_large
type alphastatic
-count 50
+count 25
tex 0 8
size 11 21
sizeincrease 21
//sparks
// used nowhere in code
effect sparks
-count 30
+count 15
type spark
tex 40 40
color 0xFFFDD9 0xFFFDD9
//sparks
// used nowhere in code
effect electricity_sparks
-count 70
+count 35
type spark
tex 40 40
color 0x807aff 0x4463d5
// used nowhere in code
effect steam
type smoke
-count 2
+count 1
tex 0 8
size 1 3
sizeincrease 7
// smoke emiter
// used nowhere in code
effect smoking
-count 20
+count 10
type alphastatic
tex 0 8
color 0x292929 0x000000
//golden dust (create it once per second to cover large area in small yellow particles)
// used nowhere in code
effect goldendust
-count 50
+count 25
type snow
tex 38 38
color 0xff9600 0xffefb8
// used nowhere in code
effect healing_fx
-count 50
+count 25
type spark
tex 40 40
color 0xff0000 0xff0000
// used nowhere in code
effect armorrepair_fx
-count 50
+count 25
type spark
tex 40 40
color 0x00ff00 0x00ff00
// used nowhere in code
effect ammoregen_fx
-count 50
+count 25
type spark
tex 40 40
color 0x0000ff 0x0000ff
// red-yellow flame like fx
// used nowhere in code
effect rage
-count 5
+count 2.5
type smoke
tex 35 36
color 0xff0000 0xff7800
// pieces of glass or ice falling on the floor
// used nowhere in code
effect iceorglass
-count 30
+count 15
type alphastatic
tex 44 44
color 0xffffff 0xb2d3e6
// cover small area in poison gas, spawn it once per second
// used nowhere in code
effect poisonfield
-count 30
+count 15
type smoke
tex 0 8
color 0x00ff00 0x7db843
// cover small area in icy mist, spawn it once per second
// used nowhere in code
effect icefield
-count 20
+count 10
type smoke
tex 0 8
color 0x008aff 0x75e7ff
velocityjitter 5 5 30
airfriction 1
effect icefield
-count 10
+count 5
type smoke
tex 48 55
size 1 1
// flames that go up
// used nowhere in code
effect firefield
-count 200
+count 100
type smoke
tex 48 55
color 0x8f0d00 0xff5a00
airfriction 1
//flames that stay on the ground
effect firefield
-count 100
+count 50
type smoke
tex 48 55
color 0x8f0d00 0xff5a00
originjitter 180 180 0
// smoke
effect firefield
-count 40
+count 20
type alphastatic
tex 0 8
size 1 1
//fast fire
// used nowhere in code
effect flamethrower
-count 6
+count 3
type smoke
tex 48 55
color 0x8f0d00 0xff5a00
airfriction 1.2
//slowfire
effect flamethrower
-count 5
+count 2.5
type smoke
tex 48 55
color 0x8f0d00 0xff5a00
airfriction 1.2
// very slow and small fire
effect flamethrower
-count 3
+count 1.5
type smoke
tex 48 55
color 0x8f0d00 0xff5a00
airfriction 0.3
//decreasing fire
effect flamethrower
-count 4
+count 2
type smoke
tex 48 55
color 0x8f0d00 0xff5a00
airfriction 0.3
//smoke
effect flamethrower
-count 1
+count 0.5
type alphastatic
tex 0 8
size 5 15
// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_WIZSPIKE"), from, to)
// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_WIZSPIKE"), from, to)
effect TR_WIZSPIKE
-trailspacing 2
+trailspacing 4
type static
color 0x404040 0x404040
size 3 3
velocitymultiplier -0.1
// bright sparks
effect TR_WIZSPIKE
-trailspacing 6
-count 3
+trailspacing 12
+count 1.5
type snow
tex 42 42
color 0x404040 0x404040
// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_VORESPIKE"), from, to)
// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_VORESPIKE"), from, to)
effect TR_VORESPIKE
-trailspacing 2
+trailspacing 4
type static
color 0x804000 0x804000
size 3 3
velocitymultiplier -0.1
// bright sparks
effect TR_VORESPIKE
-trailspacing 6
-count 3
+trailspacing 12
+count 1.5
type snow
tex 42 42
color 0xff8000 0xff8000
// fire effect which make bright dot inside
effect flac_explode
notunderwater
-count 6
+count 3
type smoke
tex 48 55
color 0xffe955 0xff5a00
// fire effect which expands then slows
effect flac_explode
notunderwater
-count 12
+count 6
type static
tex 48 55
color 0x8f0d00 0xff5a00
type alphastatic
notunderwater
tex 0 8
-count 10
+count 5
size 10 20
sizeincrease 20
alpha 500 600 556
// underwater bubbles
effect flac_explode
underwater
-count 16
+count 8
type bubble
tex 62 62
color 0x404040 0x808080
// bouncing sparks
effect flac_explode
notunderwater
-count 8
+count 4
type spark
color 0x903010 0xFFD030
size 2 2
// used in qcsrc/server/w_common.qc: zcurveparticles_from_tracetoss(particleeffectnum("tr_bullet"), self.origin, trace_endpos, self.velocity)
// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("tr_bullet"), from, to)
effect tr_bullet
-trailspacing 128
+trailspacing 256
type spark
color 0x800000 0xFF8020
alpha 256 256 2560
-size 3 3
-stretchfactor 0.6
+size 1.5 1.5
+stretchfactor 1
velocitymultiplier 0.7
// smoke emitter for small pipes
// used nowhere in code
effect smoking_smallemitter
-count 20
+count 10
type alphastatic
tex 0 8
color 0x292929 0x000000
// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_CRYLINKPLASMA"), from, to)
// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("TR_CRYLINKPLASMA"), from, to)
effect TR_CRYLINKPLASMA
-trailspacing 64
+trailspacing 128
type static
color 0x5522aa 0x6622ff
size 2 2
velocitymultiplier -0.01
// crylink main trail
effect TR_CRYLINKPLASMA
-trailspacing 8
+trailspacing 16
type static
color 0x5522aa 0x6622ff
size 3 3
velocitymultiplier 0.01
effect cherryblossom
-count 3
+count 1.5
type static
color 0xb123ff 0xb183ff
size 1.5 2
//lighttime 0
effect alien_blood
-count 0.333
+count 0.167
type blood
tex 24 32
size 3 8
originjitter 11 11 11
effect robot_blood
-count 0.333
+count 0.167
type blood
tex 24 32
size 3 8
effect alien_TR_BLOOD
-trailspacing 16
+trailspacing 32
type blood
color 0xC080B0 0xC080B0
tex 24 32
staintex 16 24
effect robot_TR_BLOOD
-trailspacing 16
+trailspacing 32
type blood
color 0xC0D890 0xC0D890
tex 24 32
staintex 16 24
effect alien_TR_SLIGHTBLOOD
-trailspacing 32
+trailspacing 64
type blood
color 0xC080B0 0xC080B0
tex 24 32
staintex 16 24
effect robot_TR_SLIGHTBLOOD
-trailspacing 32
+trailspacing 64
type blood
color 0xC0D890 0xC0D890
tex 24 32
alpha 128 64 64
// cloud of particles which expand rapidly and then slow to form a ball
effect item_pickup
-count 64
+count 32
type spark
tex 41 41
color 0x63F2EA 0xB0C5C4
// used in qsrc/server/ctf.qc: pointparticles(particleeffectnum("red_ground_quake"), self.origin, '0 0 0', 1);
effect red_ground_quake
type smoke
-count 180
+count 90
tex 0 8
size 20 50
sizeincrease 100
notunderwater
effect red_ground_quake
type smoke
-count 80
+count 40
tex 0 8
size 10 30
sizeincrease 60
notunderwater
effect red_ground_quake
//notunderwater
-count 32
+count 16
type smoke
tex 48 55
size 4 20
// smoke
effect red_ground_quake
type alphastatic
-count 22
+count 11
tex 0 8
size 22 33
sizeincrease 11
// used in qsrc/server/ctf.qc: pointparticles(particleeffectnum("blue_ground_quake"), self.origin, '0 0 0', 1);
effect blue_ground_quake
type smoke
-count 180
+count 90
tex 0 8
size 20 50
sizeincrease 100
notunderwater
effect blue_ground_quake
type smoke
-count 80
+count 40
tex 0 8
size 10 30
sizeincrease 60
notunderwater
effect blue_ground_quake
//notunderwater
-count 32
+count 16
type smoke
tex 48 55
size 4 20
// smoke
effect blue_ground_quake
type alphastatic
-count 22
+count 11
tex 0 8
size 22 33
sizeincrease 11
// used in qcsrc/client/gibs.qc: pointparticles(particleeffectnum("damage_hit"), org, vel, amount * 16)
effect morphed_damage_hit
tex 43 43
-count 1
+count 0.5
type spark
color 0xffffff 0x9271fb
size 14 24
effect morphed_damage_hit
tex 0 8
-count 1
+count 0.5
type smoke
color 0xffffff 0x9271fb
size 24 24
// used in qcsrc/client/gibs.qc: pointparticles(particleeffectnum("damage_dissolve"), org, vel, amount)
effect morphed_damage_dissolve
tex 43 43
-count 20
-type spark
+count 10
+type smoke
color 0xffffff 0x9271fb
-size 62 62
+size 40 40
sizeincrease -16
-alpha 256 256 328
-gravity -0.4
-airfriction 3
+alpha 456 456 1828
+gravity -1.9
+airfriction 8
liquidfriction 6
velocityjitter 256 256 512
+rotate -180 180 -399 -99
effect morphed_damage_dissolve
tex 43 43
-count 5
-type spark
+count 2.5
+type smoke
color 0x7bdbff 0xbed2ff
-size 62 62
+size 40 40
sizeincrease -16
-alpha 256 256 328
+alpha 256 256 628
gravity -0.8
-airfriction 5
+airfriction 9
liquidfriction 6
velocityjitter 256 256 512
+rotate -180 180 0 0
effect morphed_damage_dissolve
-tex 0 8
-count 10
+tex 65 65
+count 5
type smoke
color 0xffffff 0x9271fb
size 44 44
sizeincrease -16
-alpha 256 256 228
+alpha 156 156 128
airfriction 3
liquidfriction 6
-originjitter 32 32 96
-
+originjitter 22 22 76
effect morphed_damage_dissolve
tex 46 46
-count 30
+count 15
type smoke
color 0xffffff 0x9271fb
size 32 32
sizeincrease -16
-alpha 256 256 228
+alpha 56 56 128
gravity 1
bounce 1.5
airfriction 3
liquidfriction 6
velocityjitter 400 400 0
+rotate -180 180 999 -999
// Team / hit minsta effects
effect TE_TEI_G3RED
countabsolute 1
type beam
-tex 60 60
+tex 200 200
color 0xFF0000 0xFF0000
size 4 4
alpha 128 128 256
// experimental
effect TE_TEI_G3RED
-trailspacing 4
+trailspacing 8
type static
color 0x200000 0x400000
size 0.3 0.3
effect TE_TEI_G3RED_HIT
countabsolute 1
type beam
-tex 60 60
+tex 200 200
color 0xFF0000 0xFF0000
size 8 8
alpha 128 128 256
// experimental
effect TE_TEI_G3RED_HIT
-trailspacing 10
+trailspacing 20
type static
color 0xFFFFFF 0xFF0011
size 2 2
type smoke
// rings
effect TE_TEI_G3RED_HIT
-trailspacing 20
+trailspacing 40
type static
color 0xFF0000 0xFF0011
size 10 10
effect TE_TEI_G3BLUE
countabsolute 1
type beam
-tex 60 60
+tex 200 200
color 0x0000FF 0x1100FF
size 4 4
alpha 128 128 256
// experimental
effect TE_TEI_G3BLUE
-trailspacing 4
+trailspacing 8
type static
color 0x000020 0x000040
size 0.3 0.3
effect TE_TEI_G3BLUE_HIT
countabsolute 1
type beam
-tex 60 60
+tex 200 200
color 0x0000FF 0x1100FF
size 8 8
alpha 128 128 256
// experimental
effect TE_TEI_G3BLUE_HIT
-trailspacing 10
+trailspacing 20
type static
color 0xFFFFFF 0x100FF
size 2 2
type smoke
// rings
effect TE_TEI_G3BLUE_HIT
-trailspacing 20
+trailspacing 40
type static
color 0x0000FF 0x1100FF
size 10 10
effect TE_TEI_G3YELLOW
countabsolute 1
type beam
-tex 60 60
+tex 200 200
color 0xffff00 0xffff11
size 4 4
alpha 128 128 256
effect TE_TEI_G3YELLOW
-trailspacing 4
+trailspacing 8
type static
color 0x202000 0x404000
size 0.3 0.3
effect TE_TEI_G3YELLOW_HIT
countabsolute 1
type beam
-tex 60 60
+tex 200 200
color 0xffff00 0xffff11
size 8 8
alpha 128 128 256
effect TE_TEI_G3YELLOW_HIT
-trailspacing 10
+trailspacing 20
type static
color 0xFFFFFF 0xffff10
size 2 2
type smoke
// rings
effect TE_TEI_G3YELLOW_HIT
-trailspacing 20
+trailspacing 40
type static
color 0xffff00 0xffff11
size 10 10
effect TE_TEI_G3PINK
countabsolute 1
type beam
-tex 60 60
+tex 200 200
color 0xFF00FF 0xFF11FF
size 4 4
alpha 128 128 256
// experimental
effect TE_TEI_G3PINK
-trailspacing 4
+trailspacing 8
type static
color 0x200020 0x400040
size 0.3 0.3
effect TE_TEI_G3PINK_HIT
countabsolute 1
type beam
-tex 60 60
+tex 200 200
color 0xFF00FF 0xFF11FF
size 8 8
alpha 128 128 256
// experimental
effect TE_TEI_G3PINK_HIT
-trailspacing 10
+trailspacing 20
type static
color 0xFFFFFF 0xFF10FF
size 2 2
type smoke
// rings
effect TE_TEI_G3PINK_HIT
-trailspacing 20
+trailspacing 40
type static
color 0xFF00FF 0xFF11FF
size 10 10
// core decal
effect particlegibs_damage_hit
type blood
-count 1
+count 0.5
tex 0 8
size 5 10
color 0xA8FFFF 0xA8FFFFF
// front blood
effect particlegibs_damage_hit
type blood
-count 0.2
+count 0.1
tex 24 32
size 10 20
color 0xA8FFFF 0xA8FFFFF
// back blood
effect particlegibs_damage_hit
type blood
-count 0.2
+count 0.1
tex 24 32
size 5 15
color 0xA8FFFF 0xA8FFFFF
// small core blood no decals
effect particlegibs_damage_dissolve
type blood
-count 64
+count 32
tex 0 8
size 15 20
color 0x00ffff 0x82ffff
// core decal
effect particlegibs_damage_dissolve
type blood
-count 24
+count 12
tex 0 8
size 20 40
color 0xA8FFFF 0xA8FFFFF
// front blood
effect particlegibs_damage_dissolve
type blood
-count 64
+count 32
tex 24 32
size 10 20
color 0xA8FFFF 0xA8FFFFF
// back blood
effect particlegibs_damage_dissolve
type blood
-count 64
+count 32
tex 24 32
size 5 15
color 0xA8FFFF 0xA8FFFFF
// small bits
effect particlegibs_damage_dissolve
type blood
-count 150
+count 75
tex 24 32
size 1 1
color 0xA8FFFF 0xA8FFFFF
// fire effect which expands then slows
effect onslaught_generator_gib_explode
notunderwater
-count 34
+count 17
type static
tex 48 55
color 0x8f0d00 0xff5a00
type alphastatic
notunderwater
tex 0 8
-count 12
+count 6
size 1 10
sizeincrease 90
gravity -0.3
// underwater bubbles
effect onslaught_generator_gib_explode
underwater
-count 32
+count 16
type bubble
tex 62 62
color 0x404040 0x808080
// fire effect which expands then slows
effect onslaught_generator_gib_flame
notunderwater
-count 30
+count 15
type static
tex 48 55
color 0x8f0d00 0xff5a00
type alphastatic
notunderwater
tex 0 8
-count 2
+count 1
size 10 20
sizeincrease 30
gravity -0.8
// underwater bubbles
effect onslaught_generator_gib_flame
underwater
-count 32
+count 16
type bubble
tex 62 62
color 0x404040 0x808080
// used nowhere in code
effect firemine
-trailspacing 1
-count 1
+trailspacing 2
+count 0.5
type smoke
tex 48 55
color 0x8f0d00 0xff5a00
airfriction 1.2
//slowfire
effect firemine
-trailspacing 1
-count 1
+trailspacing 2
+count 0.5
type smoke
tex 48 55
color 0x8f0d00 0xff5a00
airfriction 1.2
// very slow and small fire
effect firemine
-trailspacing 2
-count 1
+trailspacing 4
+count 0.5
type smoke
tex 48 55
color 0x8f0d00 0xff5a00
airfriction 0.3
//decreasing fire
effect firemine
-trailspacing 2
-count 1
+trailspacing 4
+count 0.5
type smoke
tex 48 55
color 0x8f0d00 0xff5a00
airfriction 0.3
//smoke
effect firemine
-trailspacing 4
-count 1
+trailspacing 8
+count 0.5
type alphastatic
tex 0 8
size 1 4
airfriction 1
//fastfire
effect firemine
-trailspacing 0.5
-count 1
+trailspacing 1
+count 0.5
type smoke
tex 48 55
color 0x8f0d00 0xff5a00
airfriction 1.2
// light only
effect firemine
-trailspacing 8
+trailspacing 16
lightradius 50
lightradiusfade 50000
lightcolor 2.7 2.7 0.6
// used nowhere in code
effect fireball
-trailspacing 1
-count 1
+trailspacing 2
+count 0.5
type smoke
tex 48 55
color 0x8f0d00 0xff5a00
airfriction 1.2
//slowfire
effect fireball
-trailspacing 1
-count 1
+trailspacing 2
+count 0.5
type smoke
tex 48 55
color 0x8f0d00 0xff5a00
airfriction 1.2
// very slow and small fire
effect fireball
-trailspacing 2
-count 1
+trailspacing 4
+count 0.5
type smoke
tex 48 55
color 0x8f0d00 0xff5a00
airfriction 0.3
//decreasing fire
effect fireball
-trailspacing 2
-count 1
+trailspacing 4
+count 0.5
type smoke
tex 48 55
color 0x8f0d00 0xff5a00
airfriction 0.3
//smoke
effect fireball
-trailspacing 4
-count 1
+trailspacing 8
+count 0.5
type alphastatic
tex 0 8
size 5 15
airfriction 1
//fastfire
effect fireball
-trailspacing 0.5
-count 1
+trailspacing 1
+count 0.5
type smoke
tex 48 55
color 0x8f0d00 0xff5a00
airfriction 1.2
// light only
effect fireball
-trailspacing 8
+trailspacing 16
lightradius 300
lightradiusfade 3000
lightcolor 2.7 2.7 0.6
// fireball
effect fireball_laser
-count 20
+count 10
type spark
color 0x800000 0xFF8020
alpha 192 256 2560
// fire effect
effect fireball_explode
notunderwater
-count 256
+count 128
type static
tex 48 55
color 0x902010 0xFFD080
// underwater bubbles
effect fireball_explode
underwater
-count 64
+count 32
type bubble
tex 62 62
color 0x404040 0x808080
// bouncing sparks
effect fireball_explode
notunderwater
-count 128
+count 64
type spark
color 0x903010 0xFFD030
size 2 2
velocityjitter 384 384 384
effect fireball_muzzleflash
-count 4
+count 2
type smoke
color 0x202020 0x404040
tex 0 8
lightradiusfade 2000
lightcolor 2 1.5 0.2
effect fireball_muzzleflash
-count 30
+count 15
type spark
tex 40 40
color 0xFFFDD9 0xFFFDD9
airfriction 12
effect fireball_preattack_muzzleflash
-count 4
+count 2
type smoke
color 0x202020 0x404040
tex 0 8
lightradiusfade 2000
lightcolor 2 1.5 0.2
effect fireball_preattack_muzzleflash
-count 30
+count 15
type spark
tex 40 40
color 0xFFFDD9 0xFFFDD9
airfriction 12
effect fireball_bfgdamage
-count 4
+count 2
type smoke
color 0x202020 0x404040
tex 0 8
lightradiusfade 2000
lightcolor 2 1.5 0.2
effect fireball_bfgdamage
-count 30
+count 15
type spark
tex 40 40
color 0xFFFDD9 0xFFFDD9
// used nowhere in code
effect EF_FLAME
//notunderwater
-count 200
+count 100
type smoke
tex 48 55
size 5 21
// smoke
effect EF_FLAME
type alphastatic
-count 100
+count 50
tex 0 8
size 11 15
sizeincrease 6
velocityjitter 11 11 50
bounce 2
effect EF_FLAME
-count 1
+count 0.5
lightradius 200
lightradiusfade 10000
lightcolor 0.9 0.9 0.2
// used in qcsrc/server/w_common.qc: zcurveparticles_from_tracetoss(particleeffectnum("tr_bullet"), self.origin, trace_endpos, self.velocity)
// used in qcsrc/client/projectile.qc: trailparticles(self, particleeffectnum("tr_bullet"), from, to)
effect tr_rifle
-trailspacing 128
+trailspacing 256
type spark
color 0x800000 0xFF8020
alpha 256 256 2560
-size 3 3
-stretchfactor 0.6
+size 1.5 1.5
+stretchfactor 1
velocitymultiplier 0.7
effect tr_rifle
notunderwater
tex 0 8
-trailspacing 8
+trailspacing 16
type static
color 0x202020 0x404040
size 2 2
type smoke
effect tr_rifle
underwater
-trailspacing 32
+trailspacing 64
type bubble
tex 62 62
color 0x404040 0x808080
// rocket guiding start
-// smoke
-effect rocket_guide
-type alphastatic
-notunderwater
-tex 0 8
-count 5
-size 10 20
-sizeincrease 17
-alpha 300 550 556
-velocityjitter 128 128 128
-airfriction 5
-color 0x000000 0x111111
-bounce 6
-velocitymultiplier -0.1
// underwater bubbles
effect rocket_guide
underwater
-count 4
+count 2
type bubble
tex 62 62
color 0x404040 0x808080
// bouncing sparks
effect rocket_guide
notunderwater
-count 16
+count 8
type spark
color 0x903010 0xFFD030
-size 2 2
+size 0.3 0.7
tex 40 40
-alpha 256 256 384
+alpha 256 256 984
gravity 1
airfriction 0.2
bounce 1.5
liquidfriction 0.8
velocityoffset 0 0 80
-velocityjitter 256 256 256
-velocitymultiplier -0.1
+velocityjitter 156 156 156
+velocitymultiplier -0.3
+stretchfactor 0.4
+effect rocket_guide
+countabsolute 1
+type smoke
+tex 65 65
+color 0x903010 0xFFD030
+size 10 10
+sizeincrease 300
+alpha 100 100 500
// gauntlet laser
// used in qcsrc/server/w_laser.qc
effect laser_gauntlet
tex 43 43
-count 3
+count 1.5
type spark
color 0xff00ff 0xff0000
size 4 8
//fast fire
// used nowhere in code, meant for maps
effect torchflame
-count 6
+count 3
type smoke
tex 48 55
color 0x8f0d00 0xff5a00
airfriction 1.2
//slowfire
effect torchflame
-count 5
+count 2.5
type smoke
tex 48 55
color 0x8f0d00 0xff5a00
airfriction 1.2
// very slow and small fire
effect torchflame
-count 3
+count 1.5
type smoke
tex 48 55
color 0x8f0d00 0xff5a00
airfriction 0.3
//decreasing fire
effect torchflame
-count 4
+count 2
type smoke
tex 48 55
color 0x8f0d00 0xff5a00
airfriction 0.3
//smoke
effect torchflame
-count 1
+count 0.5
type alphastatic
tex 0 8
size 5 15
velocitymultiplier 20
velocityoffset 0 0 10
airfriction 1
+
+//happy death fx for cl_gentle
+effect happy_damage_dissolve
+tex 69 69
+count 15
+type alphastatic
+color 0x00FFFF 0xFF00FF
+size 32 32
+sizeincrease -10
+alpha 256 256 228
+gravity -0.4
+bounce 1.5
+airfriction 3
+liquidfriction 6
+velocityjitter 312 312 312
+effect happy_damage_dissolve
+tex 69 69
+count 15
+type alphastatic
+color 0xFF00FF 0xFFFF00
+size 32 32
+sizeincrease -10
+alpha 256 256 228
+gravity -0.4
+bounce 1.5
+airfriction 3
+liquidfriction 6
+velocityjitter 312 312 312
+effect happy_damage_dissolve
+tex 69 69
+count 15
+type alphastatic
+color 0xFFFF00 0x00FFFF
+size 32 32
+sizeincrease -10
+alpha 256 256 228
+gravity -0.4
+bounce 1.5
+airfriction 3
+liquidfriction 6
+velocityjitter 312 312 312
+
+
+//happy damage fx for cl_gentle
+effect happy_damage_hit
+tex 69 69
+count 0.1
+type alphastatic
+color 0x00FFFF 0xFF00FF
+size 26 26
+sizeincrease -28
+alpha 128 128 192
+gravity -0.4
+bounce 1.5
+airfriction 5
+liquidfriction 10
+velocityjitter 156 156 156
+effect happy_damage_hit
+tex 69 69
+count 0.1
+type alphastatic
+color 0xFF00FF 0xFFFF00
+size 26 26
+sizeincrease -28
+alpha 128 128 192
+gravity -0.4
+bounce 1.5
+airfriction 5
+liquidfriction 10
+velocityjitter 156 156 156
+effect happy_damage_hit
+tex 69 69
+count 0.1
+type alphastatic
+color 0xFFFF00 0x00FFFF
+size 26 26
+sizeincrease -28
+alpha 128 128 192
+gravity -0.4
+bounce 1.5
+airfriction 5
+liquidfriction 10
+velocityjitter 156 156 156
cl_decals 1
cl_decals_time 4
-cl_particles_quality 0.75
+cl_particles_quality 1
gl_flashblend 0
gl_picmip 1
gl_texture_anisotropy 16
cl_decals 1
cl_decals_time 2
-cl_particles_quality 0.2
+cl_particles_quality 0.4
gl_flashblend 1
gl_picmip 2
gl_texture_anisotropy 1
cl_decals 1
cl_decals_time 2
-cl_particles_quality 0.5
+cl_particles_quality 1
gl_flashblend 0
gl_picmip 1
gl_texture_anisotropy 1
cl_decals 1
cl_decals_time 2
-cl_particles_quality 0.5
+cl_particles_quality 1
gl_flashblend 0
gl_picmip 1
gl_texture_anisotropy 1
cl_decals 0
cl_decals_time 2
-cl_particles_quality 0.2
+cl_particles_quality 0.4
gl_flashblend 1
gl_picmip 1337
gl_texture_anisotropy 1
r_glsl_deluxemapping 1
r_glsl_offsetmapping 1
r_glsl_offsetmapping_reliefmapping 1
-r_hdr 1
+r_hdr 2
r_motionblur 0.5
r_picmipworld 0
r_shadow_gloss 1
+++ /dev/null
-// must be loaded AFTER config.cfg
-utf8_enable 1
-r_font_disable_freetype 0
-r_font_size_snapping 2
-loadfont console fonts/DejaVuSansMono,gfx/conchars $con_textsize
-loadfont notify fonts/DejaVuSans-Bold,gfx/vera-sans $con_notifysize
-loadfont chat fonts/DejaVuSans-Bold,gfx/vera-sans $con_chatsize
-loadfont centerprint fonts/DejaVuSansMono,gfx/conchars 9
-loadfont infobar fonts/DejaVuSansMono,gfx/conchars 8
-loadfont user0 fonts/DejaVuSans-Bold,gfx/vera-sans 9.6 12 12.8 16
-loadfont user1 fonts/DejaVuSans-Bold,gfx/vera-sans 8 10 14 $sbar_fontsize $scr_centersize // csqc font
-loadfont user2 fonts/DejaVuSans-Bold,gfx/vera-sans 16 24 32 // csqc bigfont
-sbar_columns_set
--- /dev/null
+title WickedX
+author sev
+
+// Colors: 'Red Green Blue'
+// Suffixes: Clicked (_c), Disabled (_d), Focused (_f), Normal (_n)
+
+// Background layer scaling:
+// Crop (c), Letterbox (l), Height (h), Width (w), Stretch (s)
+// Background layer positioning:
+// Top Left (7), Top Center (8) Top Right (9)
+// Middle Left (4), Middle Center (5) Middle Right (6)
+// Bottom Left (1), Bottom Center (2) Bottom Right (3)
+// ALIGN_BACKGROUND(_INGAME) spspsp, s=Scale p=Position
+
+//------------------------------------------------------------------------------
+// Structure (e.g. positions, sizes, margins)
+//------------------------------------------------------------------------------
+// item: color picker
+// uses "colorpicker" images
+MARGIN_COLORPICKER '0 0 0'
+
+// item: dialog
+// uses "border" images
+// uses "closebutton" images
+MARGIN_TOP 8
+MARGIN_BOTTOM 8
+MARGIN_LEFT 8
+MARGIN_RIGHT 8
+MARGIN_COLUMNS 4
+MARGIN_ROWS 4
+HEIGHT_DIALOGBORDER 1
+
+// font sizes (used for everything)
+FONTSIZE_NORMAL 12
+HEIGHT_NORMAL 1.5
+FONTSIZE_TITLE 16
+HEIGHT_TITLE 1.5
+HEIGHT_ZOOMEDTITLE -1
+
+// general
+// uses "background" images
+// uses "background_ingame" images
+ALIGN_BACKGROUND h5h5
+ALIGN_BACKGROUND_INGAME h5
+ALPHA_BACKGROUND_INGAME 1
+ALPHA_DISABLED 0.2
+ALPHA_BEHIND 0.5
+ALPHA_TEXT 0.7
+
+// mouse
+// uses "cursor" images
+SIZE_CURSOR '32 32 0'
+OFFSET_CURSOR '0 0 0'
+ALPHA_CURSOR_INTRO 0
+
+// nexposee positions of windows (they are the scale transformation
+// centers, NOT the actual positions of the windows!)
+POSITION_DIALOG_MULTIPLAYER '0.8 0.4 0'
+POSITION_DIALOG_SINGLEPLAYER '0.2 0.4 0'
+POSITION_DIALOG_SETTINGS '0.5 0.95 0'
+POSITION_DIALOG_CREDITS '-0.05 1.2 0'
+POSITION_DIALOG_QUIT '1.05 1.2 0'
+
+// tooltips
+// uses "tooltip" images
+MARGIN_TOOLTIP '8 8 0'
+BORDER_TOOLTIP '16 16 0'
+FONTSIZE_TOOLTIP 12
+ALPHA_TOOLTIP 0.7
+WIDTH_TOOLTIP 0.3
+AVOID_TOOLTIP '8 8 0'
+
+//------------------------------------------------------------------------------
+// Colors (e.g. font colors, field colors)
+//------------------------------------------------------------------------------
+// item: campaign
+ALPHA_CAMPAIGN_SELECTABLE 0.8
+COLOR_CAMPAIGN_SELECTABLE '1 1 1'
+ALPHA_CAMPAIGN_CURRENT 1
+COLOR_CAMPAIGN_CURRENT '1 1 1'
+ALPHA_CAMPAIGN_FUTURE 0.2
+COLOR_CAMPAIGN_FUTURE '1 1 1'
+ALPHA_CAMPAIGN_DESCRIPTION 0.7
+
+// item: credits list
+COLOR_CREDITS_TITLE '0.875 0.375 0'
+ALPHA_CREDITS_TITLE 1
+COLOR_CREDITS_FUNCTION '0 0.1875 0.4375'
+ALPHA_CREDITS_FUNCTION 0.5
+COLOR_CREDITS_PERSON '0 0.375 0.75'
+ALPHA_CREDITS_PERSON 0.875
+ROWS_CREDITS 20
+WIDTH_CREDITS 0.5
+
+// item: cvar list
+ALPHA_CVARLIST_SAVED 1
+ALPHA_CVARLIST_TEMPORARY 0.7
+COLOR_CVARLIST_CHANGED '0 0.375 0.75'
+COLOR_CVARLIST_REVERTBUTTON '1 0 0'
+COLOR_CVARLIST_UNCHANGED '1 1 1'
+
+// item: list box
+COLOR_LISTBOX_SELECTED '0.875 0.375 0'
+ALPHA_LISTBOX_SELECTED 1
+COLOR_LISTBOX_WAITING '1 1 1'
+ALPHA_LISTBOX_WAITING 0.5
+
+// item: map list
+COLOR_MAPLIST_TITLE '1 1 1'
+COLOR_MAPLIST_AUTHOR '0 0.375 0.75'
+COLOR_MAPLIST_INCLUDEDBG '0 0.1875 0.4375'
+ALPHA_MAPLIST_INCLUDEDFG 1
+ALPHA_MAPLIST_INCLUDEDBG 0.375
+ALPHA_MAPLIST_NOTINCLUDEDFG 0.25
+
+// item: nexposee
+ALPHAS_MAINMENU '0.8 0.9 1'
+
+// item: player model
+COLOR_MODELTITLE '1 1 1'
+ALPHA_MODELTITLE 1
+
+// item: server info
+COLOR_SERVERINFO_NAME '1 1 1'
+COLOR_SERVERINFO_IP '0.875 0.375 0'
+
+// item: server list
+ALPHA_SERVERLIST_FULL 0.4
+ALPHA_SERVERLIST_EMPTY 0.7
+COLOR_SERVERLIST_LOWPING '0 1 0'
+COLOR_SERVERLIST_MEDPING '1 0.75 0'
+COLOR_SERVERLIST_HIGHPING '1 0 0'
+ALPHA_SERVERLIST_HIGHPING 0.4
+ALPHA_SERVERLIST_FAVORITE 0.8
+COLOR_SERVERLIST_FAVORITE '1 1 1'
+
+// item: skin list
+COLOR_SKINLIST_TITLE '1 1 1'
+COLOR_SKINLIST_AUTHOR '0 0.375 0.75'
+
+//------------------------------------------------------------------------------
+// Images (colors multiplied to images)
+//------------------------------------------------------------------------------
+// item: button
+// uses "button" images
+// uses "buttongray" images
+// uses "bigbutton" images
+// uses "bigbuttongray" images
+COLOR_BUTTON_N '1 1 1'
+COLOR_BUTTON_C '1 1 1'
+COLOR_BUTTON_F '1 1 1'
+COLOR_BUTTON_D '1 1 1'
+
+// item: checkbox
+// uses "checkbox" images
+COLOR_CHECKBOX_N '1 1 1'
+COLOR_CHECKBOX_C '0.5 0.75 1'
+COLOR_CHECKBOX_F '0.5 0.75 1'
+COLOR_CHECKBOX_D '1 1 1'
+
+// item: crosshair button
+// uses "crosshairbutton" images
+
+// dialog background colors
+// uses "border" images
+COLOR_DIALOG_MULTIPLAYER '1 1 1'
+COLOR_DIALOG_SETTINGS '1 1 1'
+COLOR_DIALOG_TEAMSELECT '1 1 1'
+COLOR_DIALOG_QUIT '1 1 1'
+COLOR_DIALOG_ADVANCED '1 1 1'
+COLOR_DIALOG_MUTATORS '1 1 1'
+COLOR_DIALOG_MAPINFO '1 1 1'
+COLOR_DIALOG_USERBIND '1 1 1'
+COLOR_DIALOG_SINGLEPLAYER '1 1 1'
+COLOR_DIALOG_CREDITS '1 1 1'
+COLOR_DIALOG_WEAPONS '1 1 1'
+COLOR_DIALOG_RADAR '1 1 1'
+COLOR_DIALOG_SERVERINFO '1 1 1'
+COLOR_DIALOG_CVARS '1 0 0'
+
+// item: input box
+// uses "inputbox" images
+COLOR_INPUTBOX_N '1 1 1'
+COLOR_INPUTBOX_F '1 1 1'
+MARGIN_INPUTBOX_CHARS 1
+
+// item: key grabber
+COLOR_KEYGRABBER_TITLES '1 1 1'
+ALPHA_KEYGRABBER_TITLES 1
+COLOR_KEYGRABBER_KEYS '1 1 1'
+ALPHA_KEYGRABBER_KEYS 0.7
+
+// item: player color button
+// uses "colorbutton" images
+// uses "color" images
+
+// item: player name editor
+// uses "charmap" images
+// uses "charmapbutton" images
+
+// item: radio button
+// uses "radiobutton" images
+COLOR_RADIOBUTTON_N '1 1 1'
+COLOR_RADIOBUTTON_C '1 1 1'
+COLOR_RADIOBUTTON_F '1 1 1'
+COLOR_RADIOBUTTON_D '1 1 1'
+
+// item: scrollbar
+// uses "scrollbar" images
+COLOR_SCROLLBAR_N '1 1 1'
+COLOR_SCROLLBAR_C '0.5 0.75 1'
+COLOR_SCROLLBAR_F '0.5 0.75 1'
+COLOR_SCROLLBAR_S '0.25 0.25 0.25'
+WIDTH_SCROLLBAR 16
+
+// item: slider
+// uses "slider" images
+COLOR_SLIDER_N '1 1 1'
+COLOR_SLIDER_C '0.5 0.75 1'
+COLOR_SLIDER_F '0.5 0.75 1'
+COLOR_SLIDER_D '1 1 1'
+COLOR_SLIDER_S '0.25 0.25 0.25'
+WIDTH_SLIDERTEXT 0.333333333333
+TOLERANCE_SLIDER '0.2 2 0'
-flag,textures/flags/flag_red
-flag_cloth,textures/flags/flag_red_cloth
-flag_laser,textures/flags/flag_red_laser
+flag,flags/flag_red
+flag_cloth,flags/flag_red_cloth
+flag_laser,flags/flag_red_laser
-flag,textures/flags/flag_blue
-flag_cloth,textures/flags/flag_blue_cloth
-flag_laser,textures/flags/flag_blue_laser
+flag,flags/flag_blue
+flag_cloth,flags/flag_blue_cloth
+flag_laser,flags/flag_blue_laser
-Box03,textures/meat.tga
-Cylinder11,textures/meat.tga
\ No newline at end of file
+Box03,meat
+Cylinder11,meat
\ No newline at end of file
-Box03,textures/meat_robot.tga
-Cylinder11,textures/meat_robot.tga
\ No newline at end of file
+Box03,meat_robot
+Cylinder11,meat_robot
\ No newline at end of file
-Box03,textures/meat_alien.tga
-Cylinder11,textures/meat_alien.tga
\ No newline at end of file
+Box03,meat_alien
+Cylinder11,meat_alien
\ No newline at end of file
-Box03,textures/bloodyskull.tga
\ No newline at end of file
+Box03,bloodyskull
\ No newline at end of file
-Box03,textures/bloodyskull_robot.tga
\ No newline at end of file
+Box03,bloodyskull_robot
\ No newline at end of file
-Box03,textures/bloodyskull_alien.tga
\ No newline at end of file
+Box03,bloodyskull_alien
\ No newline at end of file
-Box02,textures/meat.tga
-Cylinder06,textures/meat.tga
\ No newline at end of file
+Box02,meat
+Cylinder06,meat
\ No newline at end of file
-Box02,textures/meat_robot.tga
-Cylinder06,textures/meat_robot.tga
\ No newline at end of file
+Box02,meat_robot
+Cylinder06,meat_robot
\ No newline at end of file
-Box02,textures/meat_alien.tga
-Cylinder06,textures/meat_alien.tga
\ No newline at end of file
+Box02,meat_alien
+Cylinder06,meat_alien
\ No newline at end of file
-legs,textures/meat.tga
\ No newline at end of file
+legs,meat
\ No newline at end of file
-legs,textures/meat_robot.tga
\ No newline at end of file
+legs,meat_robot
\ No newline at end of file
-legs,textures/meat_alien.tga
\ No newline at end of file
+legs,meat_alien
\ No newline at end of file
-legs01,textures/meat.tga
\ No newline at end of file
+legs01,meat
\ No newline at end of file
-legs01,textures/meat_robot.tga
\ No newline at end of file
+legs01,meat_robot
\ No newline at end of file
-legs01,textures/meat_alien.tga
\ No newline at end of file
+legs01,meat_alien
\ No newline at end of file
-Box01,textures/meat.tga
-Cylinder02,textures/meat.tga
-Cylinder13,textures/meat.tga
-Cylinder14,textures/meat.tga
-Cylinder15,textures/meat.tga
\ No newline at end of file
+Box01,meat
+Cylinder02,meat
+Cylinder13,meat
+Cylinder14,meat
+Cylinder15,meat
\ No newline at end of file
-Box01,textures/meat_robot.tga
-Cylinder02,textures/meat_robot.tga
-Cylinder13,textures/meat_robot.tga
-Cylinder14,textures/meat_robot.tga
-Cylinder15,textures/meat_robot.tga
\ No newline at end of file
+Box01,meat_robot
+Cylinder02,meat_robot
+Cylinder13,meat_robot
+Cylinder14,meat_robot
+Cylinder15,meat_robot
\ No newline at end of file
-Box01,textures/meat_alien.tga
-Cylinder02,textures/meat_alien.tga
-Cylinder13,textures/meat_alien.tga
-Cylinder14,textures/meat_alien.tga
-Cylinder15,textures/meat_alien.tga
\ No newline at end of file
+Box01,meat_alien
+Cylinder02,meat_alien
+Cylinder13,meat_alien
+Cylinder14,meat_alien
+Cylinder15,meat_alien
\ No newline at end of file
-1 56 30 0 // zombie attackleap 1\r
-57 41 60 1 // zombie attackrun1 2\r
-98 41 60 1 // zombie attackrun2 3\r
-139 41 60 1 // zombie attackrun3 4\r
-180 41 30 1 // zombie attackstanding1 5\r
-221 35 30 1 // zombie attackstanding2 6\r
-256 41 30 1 // zombie attackstanding3 7\r
-297 21 60 1 // zombie blockend 8\r
-318 21 60 0 // zombie blockstart 9\r
-339 96 30 0 // zombie deathback1 10\r
-435 67 30 0 // zombie deathback2 11\r
-502 71 30 0 // zombie deathback3 12\r
-573 61 30 0 // zombie deathfront1 13\r
-634 66 30 0 // zombie deathfront2 14\r
-700 96 30 0 // zombie deathfront3 15\r
-796 96 30 0 // zombie deathleft1 16\r
-892 71 30 0 // zombie deathleft2 17\r
-963 66 30 0 // zombie deathright1 18\r
-1029 86 30 0 // zombie deathright2 19\r
-1115 121 10 1 // zombie idle 20\r
-1236 11 30 0 // zombie painback1 21\r
-1247 11 30 0 // zombie painback2 22\r
-1258 11 30 0 // zombie painfront1 23\r
-1269 11 30 0 // zombie painfront2 24\r
-1280 41 60 1 // zombie runbackwards 25\r
-1321 41 60 1 // zombie runbackwardsleft 26\r
-1362 41 60 1 // zombie runbackwardsright 27\r
-1403 41 60 1 // zombie runforward 28\r
-1444 41 60 1 // zombie runforwardleft 29\r
-1485 41 60 1 // zombie runforwardright 30\r
-1526 61 30 0 // zombie spawn 31\r
+1 56 30 0 // zombie attackleap 1
+57 41 60 1 // zombie attackrun1 2
+98 41 60 1 // zombie attackrun2 3
+139 41 60 1 // zombie attackrun3 4
+180 41 30 1 // zombie attackstanding1 5
+221 35 30 1 // zombie attackstanding2 6
+256 41 30 1 // zombie attackstanding3 7
+297 21 60 1 // zombie blockend 8
+318 21 60 0 // zombie blockstart 9
+339 96 30 0 // zombie deathback1 10
+435 67 30 0 // zombie deathback2 11
+502 71 30 0 // zombie deathback3 12
+573 61 30 0 // zombie deathfront1 13
+634 66 30 0 // zombie deathfront2 14
+700 96 30 0 // zombie deathfront3 15
+796 96 30 0 // zombie deathleft1 16
+892 71 30 0 // zombie deathleft2 17
+963 66 30 0 // zombie deathright1 18
+1029 86 30 0 // zombie deathright2 19
+1115 121 10 1 // zombie idle 20
+1236 11 30 0 // zombie painback1 21
+1247 11 30 0 // zombie painback2 22
+1258 11 30 0 // zombie painfront1 23
+1269 11 30 0 // zombie painfront2 24
+1280 41 60 1 // zombie runbackwards 25
+1321 41 60 1 // zombie runbackwardsleft 26
+1362 41 60 1 // zombie runbackwardsright 27
+1403 41 60 1 // zombie runforward 28
+1444 41 60 1 // zombie runforwardleft 29
+1485 41 60 1 // zombie runforwardright 30
+1526 61 30 0 // zombie spawn 31
+++ /dev/null
-Carni
-models/player/carni
-0
-models/player/carni.zym
-species alien
-
-Mutated Warrior
-
-Sex: Male
-Weight: 107 kg
\ No newline at end of file
+++ /dev/null
-//TAG: carni-lycan
-//affirmative sound/player/carni-lycan/player/affirmative 0
-attack sound/player/carni-lycan/coms/attack 0
-//attacking sound/player/carni-lycan/player/attacking 0
-attackinfive sound/player/carni-lycan/coms/attackinfive 0
-coverme sound/player/carni-lycan/coms/coverme 0
-defend sound/player/carni-lycan/coms/defend 0
-//defending sound/player/carni-lycan/player/defending 0
-//droppedflag sound/player/carni-lycan/player/droppedflag 0
-//flagcarriertakingdamage sound/player/carni-lycan/player/flagcarriertakingdamage 0
-freelance sound/player/carni-lycan/coms/freelance 2
-//getflag sound/player/carni-lycan/player/getflag 0
-incoming sound/player/carni-lycan/coms/incoming 0
-meet sound/player/carni-lycan/coms/meet 0
-needhelp sound/player/carni-lycan/coms/needhelp 2
-//negative sound/player/carni-lycan/player/negative 0
-//onmyway sound/player/carni-lycan/player/onmyway 0
-//roaming sound/player/carni-lycan/player/roaming 0
-//seenenemy sound/player/carni-lycan/player/seenenemy 0
-seenflag sound/player/carni-lycan/coms/seenflag 0
-taunt sound/player/carni-lycan/coms/taunt 3
-teamshoot sound/player/carni-lycan/coms/teamshoot 3
-death sound/player/carni-lycan/player/death 3
-drown sound/player/carni-lycan/player/drown 0
-//fall sound/player/carni-lycan/player/fall 0
-falling sound/player/carni-lycan/player/falling 0
-gasp sound/player/carni-lycan/player/gasp 0
-jump sound/player/carni-lycan/player/jump 0
-pain25 sound/player/carni-lycan/player/pain25 0
-pain50 sound/player/carni-lycan/player/pain50 0
-pain75 sound/player/carni-lycan/player/pain75 0
-pain100 sound/player/carni-lycan/player/pain100 0
+++ /dev/null
-carni2,carni
\ No newline at end of file
+++ /dev/null
-carni2,carniarmor
+++ /dev/null
-carni2,carni
\ No newline at end of file
+++ /dev/null
-carni2,carniarmor
+++ /dev/null
-carni2,carni
\ No newline at end of file
+++ /dev/null
-carni2,carniarmor
+++ /dev/null
-Armored Carni
-models/player/carniarmor
-1
-models/player/carni.zym
-species alien
-
-Mutated Warrior
-
-Sex: Male
-Weight: 107 kg
-Age: 15
\ No newline at end of file
+++ /dev/null
-//TAG: soldier
-//affirmative sound/player/carni-lycan/player/affirmative 0
-attack sound/player/soldier/coms/attack 0
-//attacking sound/player/carni-lycan/player/attacking 0
-attackinfive sound/player/soldier/coms/attackinfive 0
-coverme sound/player/soldier/coms/coverme 0
-defend sound/player/soldier/coms/defend 0
-//defending sound/player/carni-lycan/player/defending 0
-//droppedflag sound/player/carni-lycan/player/droppedflag 0
-//flagcarriertakingdamage sound/player/carni-lycan/player/flagcarriertakingdamage 0
-freelance sound/player/soldier/coms/freelance 2
-//getflag sound/player/carni-lycan/player/getflag 0
-//incoming sound/player/soldier/coms/incoming 0
-meet sound/player/soldier/coms/meet 0
-needhelp sound/player/soldier/coms/needhelp 2
-//negative sound/player/carni-lycan/player/negative 0
-//onmyway sound/player/carni-lycan/player/onmyway 0
-//roaming sound/player/carni-lycan/player/roaming 0
-//seenenemy sound/player/carni-lycan/player/seenenemy 0
-seenflag sound/player/soldier/coms/seenflag 0
-taunt sound/player/soldier/coms/taunt 3
-teamshoot sound/player/soldier/coms/teamshoot 3
-death sound/player/soldier/player/death 3
-drown sound/player/soldier/player/drown 0
-//fall sound/player/carni-lycan/player/fall 0
-falling sound/player/soldier/player/falling 0
-gasp sound/player/soldier/player/gasp 0
-jump sound/player/soldier/player/jump 0
-pain25 sound/player/soldier/player/pain25 0
-pain50 sound/player/soldier/player/pain50 0
-pain75 sound/player/soldier/player/pain75 0
-pain100 sound/player/soldier/player/pain100 0
+++ /dev/null
-mechanical12,quark
+++ /dev/null
-mechanical12,quark
+++ /dev/null
-mechanical12,quark
+++ /dev/null
-Fricka
-models/player/fricka
-1
-models/player/visitant.zym
-species alien
-
-Mutated Warrior
-
-Sex: Female
-Weight: 57 kg
-Age: 16
\ No newline at end of file
--- /dev/null
+0 36 15.000000 0 // dieone
+36 20 15.000000 0 // dietwo
+56 15 15.000000 1 // draw
+71 20 15.000000 1 // duck
+91 21 30.000000 1 // duckwalk
+112 16 15.000000 0 // duckjump
+128 15 5.000000 1 // duckidle
+143 41 5.000000 1 // idle
+184 21 25.000000 0 // jump
+205 15 15.000000 0 // painone
+220 17 15.000000 0 // paintwo
+237 3 15.000000 1 // shoot
+240 21 15.000000 1 // taunt
+261 21 35.000000 1 // run
+282 21 35.000000 1 // runbackwards
+303 21 35.000000 1 // strafeleft
+324 21 35.000000 1 // straferight
+345 2 15.000000 0 // deadone
+347 2 15.000000 0 // deadtwo
+349 21 35.000000 1 // forwardright
+370 21 35.000000 1 // forwardleft
+391 21 35.000000 1 // backright
+412 21 30.000000 1 // backleft
--- /dev/null
+name Gak
+species alien
+sex Male
+weight 85
+age 16
+
+Lightweight Xonotic Solider
--- /dev/null
+0 36 15.000000 0 // dieone
+36 20 15.000000 0 // dietwo
+56 15 15.000000 1 // draw
+71 20 15.000000 1 // duck
+91 21 30.000000 1 // duckwalk
+112 16 15.000000 0 // duckjump
+128 15 5.000000 1 // duckidle
+143 41 5.000000 1 // idle
+184 21 25.000000 0 // jump
+205 15 15.000000 0 // painone
+220 17 15.000000 0 // paintwo
+237 3 15.000000 1 // shoot
+240 21 15.000000 1 // taunt
+261 21 35.000000 1 // run
+282 21 35.000000 1 // runbackwards
+303 21 35.000000 1 // strafeleft
+324 21 35.000000 1 // straferight
+345 2 15.000000 0 // deadone
+347 2 15.000000 0 // deadtwo
+349 21 35.000000 1 // forwardright
+370 21 35.000000 1 // forwardleft
+391 21 35.000000 1 // backright
+412 21 30.000000 1 // backleft
--- /dev/null
+name Gak Armored
+species alien
+sex Male
+weight 90
+age 20
+
+Heavyweight Xonotic Solider
--- /dev/null
+0 36 15.000000 0 // dieone
+36 20 15.000000 0 // dietwo
+56 15 15.000000 1 // draw
+71 20 15.000000 1 // duck
+91 21 30.000000 1 // duckwalk
+112 16 15.000000 0 // duckjump
+128 15 5.000000 1 // duckidle
+143 41 5.000000 1 // idle
+184 21 25.000000 0 // jump
+205 15 15.000000 0 // painone
+220 17 15.000000 0 // paintwo
+237 3 15.000000 1 // shoot
+240 21 15.000000 1 // taunt
+261 21 35.000000 1 // run
+282 21 35.000000 1 // runbackwards
+303 21 35.000000 1 // strafeleft
+324 21 35.000000 1 // straferight
+345 2 15.000000 0 // deadone
+347 2 15.000000 0 // deadtwo
+349 21 35.000000 1 // forwardright
+370 21 35.000000 1 // forwardleft
+391 21 35.000000 1 // backright
+412 21 30.000000 1 // backleft
--- /dev/null
+name Gak Masked
+species alien
+sex Male
+weight 87
+age 18
+
+Mediumweight Xonotic Solider
+++ /dev/null
-Grunt
-models/player/grunt
-0
-models/player/grunt.zym
-species robot_solid
-
-Half Mechanical
-Human Fighter
-
-Sex: Male
-Weight: 170 kg
-Age: 53
+++ /dev/null
-//TAG: carni-lycan
-//affirmative sound/player/carni-lycan/player/affirmative 0
-attack sound/player/carni-lycan/coms/attack 0
-//attacking sound/player/carni-lycan/player/attacking 0
-attackinfive sound/player/carni-lycan/coms/attackinfive 0
-coverme sound/player/carni-lycan/coms/coverme 0
-defend sound/player/carni-lycan/coms/defend 0
-//defending sound/player/carni-lycan/player/defending 0
-//droppedflag sound/player/carni-lycan/player/droppedflag 0
-//flagcarriertakingdamage sound/player/carni-lycan/player/flagcarriertakingdamage 0
-freelance sound/player/carni-lycan/coms/freelance 2
-//getflag sound/player/carni-lycan/player/getflag 0
-incoming sound/player/carni-lycan/coms/incoming 0
-meet sound/player/carni-lycan/coms/meet 0
-needhelp sound/player/carni-lycan/coms/needhelp 2
-//negative sound/player/carni-lycan/player/negative 0
-//onmyway sound/player/carni-lycan/player/onmyway 0
-//roaming sound/player/carni-lycan/player/roaming 0
-//seenenemy sound/player/carni-lycan/player/seenenemy 0
-seenflag sound/player/carni-lycan/coms/seenflag 0
-taunt sound/player/carni-lycan/coms/taunt 3
-teamshoot sound/player/carni-lycan/coms/teamshoot 3
-death sound/player/carni-lycan/player/death 3
-drown sound/player/carni-lycan/player/drown 0
-//fall sound/player/carni-lycan/player/fall 0
-falling sound/player/carni-lycan/player/falling 0
-gasp sound/player/carni-lycan/player/gasp 0
-jump sound/player/carni-lycan/player/jump 0
-pain25 sound/player/carni-lycan/player/pain25 0
-pain50 sound/player/carni-lycan/player/pain50 0
-pain75 sound/player/carni-lycan/player/pain75 0
-pain100 sound/player/carni-lycan/player/pain100 0
+++ /dev/null
-grunt,grunt
\ No newline at end of file
+++ /dev/null
-grunt,grunt
\ No newline at end of file
+++ /dev/null
-grunt,grunt
\ No newline at end of file
+++ /dev/null
-Headhunter
-models/player/headhunter
-0
-models/player/headhunter.zym
-species alien
-
-Mutated Warrior
-
-Sex: Male
-Weight: 115 kg
-Age: 34
\ No newline at end of file
+++ /dev/null
-//TAG: carni-lycan
-//affirmative sound/player/carni-lycan/player/affirmative 0
-attack sound/player/carni-lycan/coms/attack 0
-//attacking sound/player/carni-lycan/player/attacking 0
-attackinfive sound/player/carni-lycan/coms/attackinfive 0
-coverme sound/player/carni-lycan/coms/coverme 0
-defend sound/player/carni-lycan/coms/defend 0
-//defending sound/player/carni-lycan/player/defending 0
-//droppedflag sound/player/carni-lycan/player/droppedflag 0
-//flagcarriertakingdamage sound/player/carni-lycan/player/flagcarriertakingdamage 0
-freelance sound/player/carni-lycan/coms/freelance 2
-//getflag sound/player/carni-lycan/player/getflag 0
-incoming sound/player/carni-lycan/coms/incoming 0
-meet sound/player/carni-lycan/coms/meet 0
-needhelp sound/player/carni-lycan/coms/needhelp 2
-//negative sound/player/carni-lycan/player/negative 0
-//onmyway sound/player/carni-lycan/player/onmyway 0
-//roaming sound/player/carni-lycan/player/roaming 0
-//seenenemy sound/player/carni-lycan/player/seenenemy 0
-seenflag sound/player/carni-lycan/coms/seenflag 0
-taunt sound/player/carni-lycan/coms/taunt 3
-teamshoot sound/player/carni-lycan/coms/teamshoot 3
-death sound/player/carni-lycan/player/death 3
-drown sound/player/carni-lycan/player/drown 0
-//fall sound/player/carni-lycan/player/fall 0
-falling sound/player/carni-lycan/player/falling 0
-gasp sound/player/carni-lycan/player/gasp 0
-jump sound/player/carni-lycan/player/jump 0
-pain25 sound/player/carni-lycan/player/pain25 0
-pain50 sound/player/carni-lycan/player/pain50 0
-pain75 sound/player/carni-lycan/player/pain75 0
-pain100 sound/player/carni-lycan/player/pain100 0
+++ /dev/null
-headhunter,headhunter
\ No newline at end of file
+++ /dev/null
-headhunter,headhunter
\ No newline at end of file
+++ /dev/null
-headhunter,headhunter
\ No newline at end of file
+++ /dev/null
-Heroine
-models/player/heroine
-1
-models/player/jeandarc.zym
-species human
-
-Solo Fighter
-
-Sex: Female
-Weight: 50 kg
-Age: 23
\ No newline at end of file
--- /dev/null
+0 36 15.000000 0 // dieone
+36 20 15.000000 0 // dietwo
+56 15 15.000000 1 // draw
+71 20 15.000000 1 // duck
+91 21 30.000000 1 // duckwalk
+112 16 15.000000 0 // duckjump
+128 15 5.000000 1 // duckidle
+143 41 5.000000 1 // idle
+184 21 25.000000 0 // jump
+205 15 15.000000 0 // painone
+220 17 15.000000 0 // paintwo
+237 3 15.000000 1 // shoot
+240 21 15.000000 1 // taunt
+261 21 35.000000 1 // run
+282 21 35.000000 1 // runbackwards
+303 21 35.000000 1 // strafeleft
+324 21 35.000000 1 // straferight
+345 2 15.000000 0 // deadone
+347 2 15.000000 0 // deadtwo
+349 21 35.000000 1 // forwardright
+370 21 35.000000 1 // forwardleft
+391 21 35.000000 1 // backright
+412 21 30.000000 1 // backleft
--- /dev/null
+name Ignis
+species human
+sex Male
+weight 88
+age 31
+
+Heavyweight Xonotic Solider
--- /dev/null
+0 36 15.000000 0 // dieone
+36 20 15.000000 0 // dietwo
+56 15 15.000000 1 // draw
+71 20 15.000000 1 // duck
+91 21 30.000000 1 // duckwalk
+112 16 15.000000 0 // duckjump
+128 15 5.000000 1 // duckidle
+143 41 5.000000 1 // idle
+184 21 25.000000 0 // jump
+205 15 15.000000 0 // painone
+220 17 15.000000 0 // paintwo
+237 3 15.000000 1 // shoot
+240 21 15.000000 1 // taunt
+261 21 35.000000 1 // run
+282 21 35.000000 1 // runbackwards
+303 21 35.000000 1 // strafeleft
+324 21 35.000000 1 // straferight
+345 2 15.000000 0 // deadone
+347 2 15.000000 0 // deadtwo
+349 21 35.000000 1 // forwardright
+370 21 35.000000 1 // forwardleft
+391 21 35.000000 1 // backright
+412 21 30.000000 1 // backleft
--- /dev/null
+name Ignis - HalfMasked
+species human
+sex Male
+weight 90
+age 31
+
+Heavyweight Xonotic Solider
--- /dev/null
+0 36 15.000000 0 // dieone
+36 20 15.000000 0 // dietwo
+56 15 15.000000 1 // draw
+71 20 15.000000 1 // duck
+91 21 30.000000 1 // duckwalk
+112 16 15.000000 0 // duckjump
+128 15 5.000000 1 // duckidle
+143 41 5.000000 1 // idle
+184 21 25.000000 0 // jump
+205 15 15.000000 0 // painone
+220 17 15.000000 0 // paintwo
+237 3 15.000000 1 // shoot
+240 21 15.000000 1 // taunt
+261 21 35.000000 1 // run
+282 21 35.000000 1 // runbackwards
+303 21 35.000000 1 // strafeleft
+324 21 35.000000 1 // straferight
+345 2 15.000000 0 // deadone
+347 2 15.000000 0 // deadtwo
+349 21 35.000000 1 // forwardright
+370 21 35.000000 1 // forwardleft
+391 21 35.000000 1 // backright
+412 21 30.000000 1 // backleft
--- /dev/null
+name Ignis - Masked
+species human
+sex Male
+weight 92
+age 31
+
+Heavyweight Xonotic Solider
+++ /dev/null
-Insurrectionist
-models/player/insurrectionist
-0
-models/player/insurrectionist.zym
-species human
-
-Warrior
-
-Sex: Male
-Weight: 87 kg
-Age: 56
\ No newline at end of file
+++ /dev/null
-//TAG: insurrectionist
-//affirmative sound/player/carni-lycan/player/affirmative 0
-attack sound/player/insurrectionist/coms/attack 0
-//attacking sound/player/carni-lycan/player/attacking 0
-attackinfive sound/player/insurrectionist/coms/attackinfive 0
-coverme sound/player/insurrectionist/coms/coverme 0
-defend sound/player/insurrectionist/coms/defend 0
-//defending sound/player/carni-lycan/player/defending 0
-//droppedflag sound/player/carni-lycan/player/droppedflag 0
-//flagcarriertakingdamage sound/player/carni-lycan/player/flagcarriertakingdamage 0
-freelance sound/player/insurrectionist/coms/freelance 2
-//getflag sound/player/carni-lycan/player/getflag 0
-incoming sound/player/insurrectionist/coms/incoming 0
-meet sound/player/insurrectionist/coms/meet 0
-needhelp sound/player/insurrectionist/coms/needhelp 2
-//negative sound/player/carni-lycan/player/negative 0
-//onmyway sound/player/carni-lycan/player/onmyway 0
-//roaming sound/player/carni-lycan/player/roaming 0
-//seenenemy sound/player/carni-lycan/player/seenenemy 0
-seenflag sound/player/insurrectionist/coms/seenflag 0
-taunt sound/player/insurrectionist/coms/taunt 4
-teamshoot sound/player/insurrectionist/coms/teamshoot 3
-death sound/player/insurrectionist/player/death 3
-drown sound/player/insurrectionist/player/drown 0
-//fall sound/player/carni-lycan/player/fall 0
-falling sound/player/insurrectionist/player/falling 0
-gasp sound/player/insurrectionist/player/gasp 0
-jump sound/player/insurrectionist/player/jump 0
-pain25 sound/player/insurrectionist/player/pain25 0
-pain50 sound/player/insurrectionist/player/pain50 0
-pain75 sound/player/insurrectionist/player/pain75 0
-pain100 sound/player/insurrectionist/player/pain100 0
+++ /dev/null
-insurrectionist,insurrectionist
\ No newline at end of file
+++ /dev/null
-insurrectionist,insurrectionist
\ No newline at end of file
+++ /dev/null
-insurrectionist,insurrectionist
\ No newline at end of file
+++ /dev/null
-jeandarc1,heroine
+++ /dev/null
-jeandarc1,heroine
+++ /dev/null
-jeandarc1,heroine
+++ /dev/null
-Lurk
-models/player/lurk
-0
-models/player/lurk.zym
-species alien
-
-Reptilian Combatant
-
-Weight: 84 kg
-Age: 47
\ No newline at end of file
+++ /dev/null
-//TAG: reptilian
-//affirmative sound/player/carni-lycan/player/affirmative 0
-attack sound/player/reptilian/coms/attack 0
-//attacking sound/player/carni-lycan/player/attacking 0
-attackinfive sound/player/reptilian/coms/attackinfive 0
-coverme sound/player/reptilian/coms/coverme 0
-defend sound/player/reptilian/coms/defend 0
-//defending sound/player/carni-lycan/player/defending 0
-//droppedflag sound/player/carni-lycan/player/droppedflag 0
-//flagcarriertakingdamage sound/player/carni-lycan/player/flagcarriertakingdamage 0
-freelance sound/player/reptilian/coms/freelance 2
-//getflag sound/player/carni-lycan/player/getflag 0
-incoming sound/player/reptilian/coms/incoming 0
-meet sound/player/reptilian/coms/meet 0
-needhelp sound/player/reptilian/coms/needhelp 2
-//negative sound/player/carni-lycan/player/negative 0
-//onmyway sound/player/carni-lycan/player/onmyway 0
-//roaming sound/player/carni-lycan/player/roaming 0
-//seenenemy sound/player/carni-lycan/player/seenenemy 0
-seenflag sound/player/reptilian/coms/seenflag 0
-taunt sound/player/reptilian/coms/taunt 3
-teamshoot sound/player/reptilian/coms/teamshoot 3
-death sound/player/reptilian/player/death 3
-drown sound/player/reptilian/player/drown 0
-//fall sound/player/carni-lycan/player/fall 0
-falling sound/player/reptilian/player/falling 0
-gasp sound/player/reptilian/player/gasp 0
-jump sound/player/reptilian/player/jump 0
-pain25 sound/player/reptilian/player/pain25 0
-pain50 sound/player/reptilian/player/pain50 0
-pain75 sound/player/reptilian/player/pain75 0
-pain100 sound/player/reptilian/player/pain100 0
+++ /dev/null
-lurk,lurk
\ No newline at end of file
+++ /dev/null
-lurk,reptile
\ No newline at end of file
+++ /dev/null
-lurk,lurk
\ No newline at end of file
+++ /dev/null
-lurk,reptile
\ No newline at end of file
+++ /dev/null
-lurk,lurk
\ No newline at end of file
+++ /dev/null
-lurk,reptile
\ No newline at end of file
+++ /dev/null
-Lycanthrope
-models/player/lycanthrope
-0
-models/player/lycanthrope.zym
-species human
-
-Monsterous Opponent
-
-Sex: Female
-Weight: 106 kg
-Age: 24
\ No newline at end of file
+++ /dev/null
-//TAG: carni-lycan
-//affirmative sound/player/carni-lycan/player/affirmative 0
-attack sound/player/carni-lycan/coms/attack 0
-//attacking sound/player/carni-lycan/player/attacking 0
-attackinfive sound/player/carni-lycan/coms/attackinfive 0
-coverme sound/player/carni-lycan/coms/coverme 0
-defend sound/player/carni-lycan/coms/defend 0
-//defending sound/player/carni-lycan/player/defending 0
-//droppedflag sound/player/carni-lycan/player/droppedflag 0
-//flagcarriertakingdamage sound/player/carni-lycan/player/flagcarriertakingdamage 0
-freelance sound/player/carni-lycan/coms/freelance 2
-//getflag sound/player/carni-lycan/player/getflag 0
-incoming sound/player/carni-lycan/coms/incoming 0
-meet sound/player/carni-lycan/coms/meet 0
-needhelp sound/player/carni-lycan/coms/needhelp 2
-//negative sound/player/carni-lycan/player/negative 0
-//onmyway sound/player/carni-lycan/player/onmyway 0
-//roaming sound/player/carni-lycan/player/roaming 0
-//seenenemy sound/player/carni-lycan/player/seenenemy 0
-seenflag sound/player/carni-lycan/coms/seenflag 0
-taunt sound/player/carni-lycan/coms/taunt 3
-teamshoot sound/player/carni-lycan/coms/teamshoot 3
-death sound/player/carni-lycan/player/death 3
-drown sound/player/carni-lycan/player/drown 0
-//fall sound/player/carni-lycan/player/fall 0
-falling sound/player/carni-lycan/player/falling 0
-gasp sound/player/carni-lycan/player/gasp 0
-jump sound/player/carni-lycan/player/jump 0
-pain25 sound/player/carni-lycan/player/pain25 0
-pain50 sound/player/carni-lycan/player/pain50 0
-pain75 sound/player/carni-lycan/player/pain75 0
-pain100 sound/player/carni-lycan/player/pain100 0
+++ /dev/null
-lycanthrope1,lycanthrope
+++ /dev/null
-lycanthrope1,lycanthrope
+++ /dev/null
-lycanthrope1,lycanthrope
+++ /dev/null
-Marine
-models/player/marine
-0
-models/player/marine.zym
-species human
-
-Service Man
-
-Sex: Male
-Weight: 93 kg
-Age: 35
\ No newline at end of file
+++ /dev/null
-//TAG: marine
-//affirmative sound/player/carni-lycan/player/affirmative 0
-attack sound/player/marine/coms/attack 0
-//attacking sound/player/carni-lycan/player/attacking 0
-attackinfive sound/player/marine/coms/attackinfive 0
-coverme sound/player/marine/coms/coverme 0
-defend sound/player/marine/coms/defend 0
-//defending sound/player/carni-lycan/player/defending 0
-//droppedflag sound/player/carni-lycan/player/droppedflag 0
-//flagcarriertakingdamage sound/player/carni-lycan/player/flagcarriertakingdamage 0
-freelance sound/player/marine/coms/freelance 2
-//getflag sound/player/carni-lycan/player/getflag 0
-incoming sound/player/marine/coms/incoming 0
-meet sound/player/marine/coms/meet 0
-needhelp sound/player/marine/coms/needhelp 2
-//negative sound/player/carni-lycan/player/negative 0
-//onmyway sound/player/carni-lycan/player/onmyway 0
-//roaming sound/player/carni-lycan/player/roaming 0
-//seenenemy sound/player/carni-lycan/player/seenenemy 0
-seenflag sound/player/marine/coms/seenflag 0
-taunt sound/player/marine/coms/taunt 3
-teamshoot sound/player/marine/coms/teamshoot 4
-death sound/player/marine/player/death 3
-drown sound/player/marine/player/drown 0
-//fall sound/player/carni-lycan/player/fall 0
-falling sound/player/marine/player/fall 1
-gasp sound/player/marine/player/gasp 0
-jump sound/player/marine/player/jump 0
-pain25 sound/player/marine/player/pain25 0
-pain50 sound/player/marine/player/pain50 0
-pain75 sound/player/marine/player/pain75 0
-pain100 sound/player/marine/player/pain100 0
+++ /dev/null
-marine,marine
\ No newline at end of file
+++ /dev/null
-marine,marine
\ No newline at end of file
+++ /dev/null
-marine,marine
\ No newline at end of file
+++ /dev/null
-Mulder
-models/player/mulder
-1
-models/player/nexus.zym
-species robot_solid
-
-Nexuiz's Soldier
-
-Weight: 282 kg
-Age: 313
+++ /dev/null
-Nexus
-models/player/nexus
-0
-models/player/nexus.zym
-species human
-
-Nexuiz's Soldier
-
-Weight: 282 kg
-Age: 313
\ No newline at end of file
+++ /dev/null
-//TAG: soldier
-//affirmative sound/player/carni-lycan/player/affirmative 0
-attack sound/player/soldier/coms/attack 0
-//attacking sound/player/carni-lycan/player/attacking 0
-attackinfive sound/player/soldier/coms/attackinfive 0
-coverme sound/player/soldier/coms/coverme 0
-defend sound/player/soldier/coms/defend 0
-//defending sound/player/carni-lycan/player/defending 0
-//droppedflag sound/player/carni-lycan/player/droppedflag 0
-//flagcarriertakingdamage sound/player/carni-lycan/player/flagcarriertakingdamage 0
-freelance sound/player/soldier/coms/freelance 2
-//getflag sound/player/carni-lycan/player/getflag 0
-//incoming sound/player/soldier/coms/incoming 0
-meet sound/player/soldier/coms/meet 0
-needhelp sound/player/soldier/coms/needhelp 2
-//negative sound/player/carni-lycan/player/negative 0
-//onmyway sound/player/carni-lycan/player/onmyway 0
-//roaming sound/player/carni-lycan/player/roaming 0
-//seenenemy sound/player/carni-lycan/player/seenenemy 0
-seenflag sound/player/soldier/coms/seenflag 0
-taunt sound/player/soldier/coms/taunt 3
-teamshoot sound/player/soldier/coms/teamshoot 3
-death sound/player/soldier/player/death 3
-drown sound/player/soldier/player/drown 0
-//fall sound/player/carni-lycan/player/fall 0
-falling sound/player/soldier/player/falling 0
-gasp sound/player/soldier/player/gasp 0
-jump sound/player/soldier/player/jump 0
-pain25 sound/player/soldier/player/pain25 0
-pain50 sound/player/soldier/player/pain50 0
-pain75 sound/player/soldier/player/pain75 0
-pain100 sound/player/soldier/player/pain100 0
+++ /dev/null
-nexus,nexus
\ No newline at end of file
+++ /dev/null
-nexus,mulder
+++ /dev/null
-nexus,nexus
+++ /dev/null
-nexus,fbgreen
+++ /dev/null
-nexus,fbred
+++ /dev/null
-nexus,fborange
+++ /dev/null
-nexus,fbcolored
+++ /dev/null
-nexus,nexus
\ No newline at end of file
+++ /dev/null
-nexus,mulder
+++ /dev/null
-nexus,xolar
+++ /dev/null
-nexus,fbgreen
+++ /dev/null
-nexus,fbred
+++ /dev/null
-nexus,fborange
+++ /dev/null
-nexus,fbcolored
+++ /dev/null
-nexus,nexus
\ No newline at end of file
+++ /dev/null
-nexus,mulder
+++ /dev/null
-nexus,xolar
+++ /dev/null
-nexus,fbgreen
+++ /dev/null
-nexus,fbred
+++ /dev/null
-nexus,fborange
+++ /dev/null
-nexus,fbcolored
--- /dev/null
+0 36 20.000000 0 // dieone
+36 27 20.000000 0 // dietwo
+63 15 15.000000 1 // draw
+78 20 15.000000 1 // duck
+98 11 15.000000 1 // duckwalk
+109 16 15.000000 0 // duckjump
+125 15 5.000000 1 // duckidle
+140 16 5.000000 1 // idle
+156 16 15.000000 0 // jump
+172 15 15.000000 0 // painone
+187 17 15.000000 0 // paintwo
+204 5 15.000000 1 // shoot
+209 21 15.000000 1 // taunt
+230 21 40.000000 1 // run
+251 21 40.000000 1 // runbackwards
+272 21 40.000000 1 // strafeleft
+293 21 40.000000 1 // straferight
+314 2 15.000000 0 // deadone
+316 2 15.000000 0 // deadtwo
+318 21 40.000000 1 // forwardright
+339 21 40.000000 1 // forwardleft
+360 21 40.000000 1 // backright
+381 21 40.000000 1 // backleft
--- /dev/null
+//TAG: pyria-skadi
+//affirmative sound/player/carni-lycan/player/affirmative 0
+attack sound/player/pyria-skadi/coms/attack 2
+//attacking sound/player/carni-lycan/player/attacking 0
+attackinfive sound/player/pyria-skadi/coms/attackinfive 0
+//coverme sound/player/pyria-skadi/coms/coverme 0
+//defend sound/player/pyria-skadi/coms/defend 0
+//defending sound/player/carni-lycan/player/defending 0
+//droppedflag sound/player/carni-lycan/player/droppedflag 0
+//flagcarriertakingdamage sound/player/carni-lycan/player/flagcarriertakingdamage 0
+freelance sound/player/pyria-skadi/coms/freelance 2
+//getflag sound/player/carni-lycan/player/getflag 0
+//incoming sound/player/pyria-skadi/coms/incoming 0
+meet sound/player/pyria-skadi/coms/meet 0
+needhelp sound/player/pyria-skadi/coms/needhelp 2
+//negative sound/player/carni-lycan/player/negative 0
+//onmyway sound/player/carni-lycan/player/onmyway 0
+//roaming sound/player/carni-lycan/player/roaming 0
+//seenenemy sound/player/carni-lycan/player/seenenemy 0
+seenflag sound/player/pyria-skadi/coms/seenflag 0
+taunt sound/player/pyria-skadi/coms/taunt 5
+teamshoot sound/player/pyria-skadi/coms/teamshoot 4
+death sound/player/pyria-skadi/player/death 3
+drown sound/player/pyria-skadi/player/drown 0
+//fall sound/player/carni-lycan/player/fall 0
+falling sound/player/pyria-skadi/player/falling 0
+gasp sound/player/pyria-skadi/player/gasp 0
+jump sound/player/pyria-skadi/player/jump 0
+pain25 sound/player/pyria-skadi/player/pain25 0
+pain50 sound/player/pyria-skadi/player/pain50 0
+pain75 sound/player/pyria-skadi/player/pain75 0
+pain100 sound/player/pyria-skadi/player/pain100 0
--- /dev/null
+name Pyria
+species human
+sex Female
+weight 57
+age 53
+
+Necro Warrior
+++ /dev/null
-Pyria
-models/player/pyria
-0
-models/player/pyria.zym
-species human
-
-Necro Warrior
-
-Sex: Female
-Weight: 57 kg
-Age: 53
\ No newline at end of file
+++ /dev/null
-//TAG: pyria-skadi
-//affirmative sound/player/carni-lycan/player/affirmative 0
-attack sound/player/pyria-skadi/coms/attack 2
-//attacking sound/player/carni-lycan/player/attacking 0
-attackinfive sound/player/pyria-skadi/coms/attackinfive 0
-//coverme sound/player/pyria-skadi/coms/coverme 0
-//defend sound/player/pyria-skadi/coms/defend 0
-//defending sound/player/carni-lycan/player/defending 0
-//droppedflag sound/player/carni-lycan/player/droppedflag 0
-//flagcarriertakingdamage sound/player/carni-lycan/player/flagcarriertakingdamage 0
-freelance sound/player/pyria-skadi/coms/freelance 2
-//getflag sound/player/carni-lycan/player/getflag 0
-//incoming sound/player/pyria-skadi/coms/incoming 0
-meet sound/player/pyria-skadi/coms/meet 0
-needhelp sound/player/pyria-skadi/coms/needhelp 2
-//negative sound/player/carni-lycan/player/negative 0
-//onmyway sound/player/carni-lycan/player/onmyway 0
-//roaming sound/player/carni-lycan/player/roaming 0
-//seenenemy sound/player/carni-lycan/player/seenenemy 0
-seenflag sound/player/pyria-skadi/coms/seenflag 0
-taunt sound/player/pyria-skadi/coms/taunt 5
-teamshoot sound/player/pyria-skadi/coms/teamshoot 4
-death sound/player/pyria-skadi/player/death 3
-drown sound/player/pyria-skadi/player/drown 0
-//fall sound/player/carni-lycan/player/fall 0
-falling sound/player/pyria-skadi/player/falling 0
-gasp sound/player/pyria-skadi/player/gasp 0
-jump sound/player/pyria-skadi/player/jump 0
-pain25 sound/player/pyria-skadi/player/pain25 0
-pain50 sound/player/pyria-skadi/player/pain50 0
-pain75 sound/player/pyria-skadi/player/pain75 0
-pain100 sound/player/pyria-skadi/player/pain100 0
+++ /dev/null
-pyria,pyria
\ No newline at end of file
+++ /dev/null
-pyria,pyria
\ No newline at end of file
+++ /dev/null
-pyria,pyria
\ No newline at end of file
+++ /dev/null
-Quark
-models/player/quark
-0
-models/player/crash.zym
-species robot_shiny
-
-Robot Fighter
-
-Weight: 138 kg
-Age: 3 years
\ No newline at end of file
+++ /dev/null
-Reptile
-models/player/reptile
-1
-models/player/lurk.zym
-species alien
-
-Reptilian Combatant
-
-Weight: 80 kg
-Age: 32
\ No newline at end of file
+++ /dev/null
-Shock Trooper
-models/player/shock
-0
-models/player/shock.zym
-species human
-
-Necro Warrior
-
-Sex: Male
-Weight: 66 kg
-Age: 65
\ No newline at end of file
+++ /dev/null
-//TAG: marine
-//affirmative sound/player/carni-lycan/player/affirmative 0
-attack sound/player/marine/coms/attack 0
-//attacking sound/player/carni-lycan/player/attacking 0
-attackinfive sound/player/marine/coms/attackinfive 0
-coverme sound/player/marine/coms/coverme 0
-defend sound/player/marine/coms/defend 0
-//defending sound/player/carni-lycan/player/defending 0
-//droppedflag sound/player/carni-lycan/player/droppedflag 0
-//flagcarriertakingdamage sound/player/carni-lycan/player/flagcarriertakingdamage 0
-freelance sound/player/marine/coms/freelance 2
-//getflag sound/player/carni-lycan/player/getflag 0
-incoming sound/player/marine/coms/incoming 0
-meet sound/player/marine/coms/meet 0
-needhelp sound/player/marine/coms/needhelp 2
-//negative sound/player/carni-lycan/player/negative 0
-//onmyway sound/player/carni-lycan/player/onmyway 0
-//roaming sound/player/carni-lycan/player/roaming 0
-//seenenemy sound/player/carni-lycan/player/seenenemy 0
-seenflag sound/player/marine/coms/seenflag 0
-taunt sound/player/marine/coms/taunt 3
-teamshoot sound/player/marine/coms/teamshoot 4
-death sound/player/marine/player/death 3
-drown sound/player/marine/player/drown 0
-//fall sound/player/carni-lycan/player/fall 0
-falling sound/player/marine/player/fall 1
-gasp sound/player/marine/player/gasp 0
-jump sound/player/marine/player/jump 0
-pain25 sound/player/marine/player/pain25 0
-pain50 sound/player/marine/player/pain50 0
-pain75 sound/player/marine/player/pain75 0
-pain100 sound/player/marine/player/pain100 0
+++ /dev/null
-shock,shock
\ No newline at end of file
+++ /dev/null
-shock,shock
\ No newline at end of file
+++ /dev/null
-shock,shock
\ No newline at end of file
+++ /dev/null
-Skadi
-models/player/skadi
-0
-models/player/skadi.zym
-species human
-
-Necro Warrior
-
-Sex: Female
-Weight: 52 kg
-Age: 63
\ No newline at end of file
+++ /dev/null
-//TAG: pyria-skadi
-//affirmative sound/player/carni-lycan/player/affirmative 0
-attack sound/player/pyria-skadi/coms/attack 2
-//attacking sound/player/carni-lycan/player/attacking 0
-attackinfive sound/player/pyria-skadi/coms/attackinfive 0
-//coverme sound/player/pyria-skadi/coms/coverme 0
-//defend sound/player/pyria-skadi/coms/defend 0
-//defending sound/player/carni-lycan/player/defending 0
-//droppedflag sound/player/carni-lycan/player/droppedflag 0
-//flagcarriertakingdamage sound/player/carni-lycan/player/flagcarriertakingdamage 0
-freelance sound/player/pyria-skadi/coms/freelance 2
-//getflag sound/player/carni-lycan/player/getflag 0
-//incoming sound/player/pyria-skadi/coms/incoming 0
-meet sound/player/pyria-skadi/coms/meet 0
-needhelp sound/player/pyria-skadi/coms/needhelp 2
-//negative sound/player/carni-lycan/player/negative 0
-//onmyway sound/player/carni-lycan/player/onmyway 0
-//roaming sound/player/carni-lycan/player/roaming 0
-//seenenemy sound/player/carni-lycan/player/seenenemy 0
-seenflag sound/player/pyria-skadi/coms/seenflag 0
-taunt sound/player/pyria-skadi/coms/taunt 5
-teamshoot sound/player/pyria-skadi/coms/teamshoot 4
-death sound/player/pyria-skadi/player/death 3
-drown sound/player/pyria-skadi/player/drown 0
-//fall sound/player/carni-lycan/player/fall 0
-falling sound/player/pyria-skadi/player/falling 0
-gasp sound/player/pyria-skadi/player/gasp 0
-jump sound/player/pyria-skadi/player/jump 0
-pain25 sound/player/pyria-skadi/player/pain25 0
-pain50 sound/player/pyria-skadi/player/pain50 0
-pain75 sound/player/pyria-skadi/player/pain75 0
-pain100 sound/player/pyria-skadi/player/pain100 0
+++ /dev/null
-femaleshock,skadi
\ No newline at end of file
+++ /dev/null
-femaleshock,skadi
\ No newline at end of file
+++ /dev/null
-femaleshock,skadi
\ No newline at end of file
+++ /dev/null
-Specop
-models/player/specop
-0
-models/player/specop.zym
-species human
-
-Solo Warrior
-
-Sex: Female
-Weight: 61 kg
-Age: 31
\ No newline at end of file
+++ /dev/null
-//TAG: specop
-//affirmative sound/player/carni-lycan/player/affirmative 0
-attack sound/player/specop/coms/attack 0
-//attacking sound/player/carni-lycan/player/attacking 0
-attackinfive sound/player/specop/coms/attackinfive 0
-coverme sound/player/specop/coms/coverme 0
-defend sound/player/specop/coms/defend 0
-//defending sound/player/carni-lycan/player/defending 0
-//droppedflag sound/player/carni-lycan/player/droppedflag 0
-//flagcarriertakingdamage sound/player/carni-lycan/player/flagcarriertakingdamage 0
-freelance sound/player/specop/coms/freelance 2
-//getflag sound/player/carni-lycan/player/getflag 0
-incoming sound/player/specop/coms/incoming 0
-meet sound/player/specop/coms/meet 0
-needhelp sound/player/specop/coms/needhelp 1
-//negative sound/player/carni-lycan/player/negative 0
-//onmyway sound/player/carni-lycan/player/onmyway 0
-//roaming sound/player/carni-lycan/player/roaming 0
-//seenenemy sound/player/carni-lycan/player/seenenemy 0
-seenflag sound/player/specop/coms/seenflag 0
-taunt sound/player/specop/coms/taunt 4
-teamshoot sound/player/specop/coms/teamshoot 4
-death sound/player/specop/player/death 3
-drown sound/player/specop/player/drown 0
-//fall sound/player/carni-lycan/player/fall 0
-falling sound/player/specop/player/falling 0
-gasp sound/player/specop/player/gasp 0
-jump sound/player/specop/player/jump 0
-pain25 sound/player/specop/player/pain25 0
-pain50 sound/player/specop/player/pain50 0
-pain75 sound/player/specop/player/pain75 0
-pain100 sound/player/specop/player/pain100 0
+++ /dev/null
-specop,specop
\ No newline at end of file
+++ /dev/null
-specop,specop
\ No newline at end of file
+++ /dev/null
-specop,specop
\ No newline at end of file
--- /dev/null
+0 36 20.000000 0 // dieone
+36 27 20.000000 0 // dietwo
+63 15 15.000000 1 // draw
+78 20 15.000000 1 // duck
+98 11 15.000000 1 // duckwalk
+109 16 15.000000 0 // duckjump
+125 15 5.000000 1 // duckidle
+140 16 5.000000 1 // idle
+156 16 15.000000 0 // jump
+172 15 15.000000 0 // painone
+187 17 15.000000 0 // paintwo
+204 5 15.000000 1 // shoot
+209 21 15.000000 1 // taunt
+230 21 40.000000 1 // run
+251 21 40.000000 1 // runbackwards
+272 21 40.000000 1 // strafeleft
+293 21 40.000000 1 // straferight
+314 2 15.000000 0 // deadone
+316 2 15.000000 0 // deadtwo
+318 21 40.000000 1 // forwardright
+339 21 40.000000 1 // forwardleft
+360 21 40.000000 1 // backright
+381 21 40.000000 1 // backleft
--- /dev/null
+name Umbra
+species human
+sex Female
+weight 61
+age 25
+
+Lightweight Xonotic Solider
+++ /dev/null
-//TAG: fricka
-//affirmative sound/player/carni-lycan/player/affirmative 0
-attack sound/player/fricka/coms/attack 0
-//attacking sound/player/carni-lycan/player/attacking 0
-attackinfive sound/player/fricka/coms/attackinfive 0
-//coverme sound/player/fricka/coms/coverme 0
-defend sound/player/fricka/coms/defend 0
-//defending sound/player/carni-lycan/player/defending 0
-//droppedflag sound/player/carni-lycan/player/droppedflag 0
-//flagcarriertakingdamage sound/player/carni-lycan/player/flagcarriertakingdamage 0
-freelance sound/player/fricka/coms/freelance 2
-//getflag sound/player/carni-lycan/player/getflag 0
-incoming sound/player/fricka/coms/incoming 0
-meet sound/player/fricka/coms/waypoint 0
-//needhelp sound/player/fricka/coms/needhelp 0
-//negative sound/player/carni-lycan/player/negative 0
-//onmyway sound/player/carni-lycan/player/onmyway 0
-//roaming sound/player/carni-lycan/player/roaming 0
-//seenenemy sound/player/carni-lycan/player/seenenemy 0
-seenflag sound/player/fricka/coms/flagseen 0
-taunt sound/player/fricka/coms/taunt 4
-teamshoot sound/player/fricka/coms/teamshoot 3
-death sound/player/fricka/player/death 3
-drown sound/player/fricka/player/drown 0
-//fall sound/player/carni-lycan/player/fall 0
-falling sound/player/fricka/player/falling 0
-gasp sound/player/fricka/player/gasp 0
-jump sound/player/fricka/player/jump 0
-pain25 sound/player/fricka/player/pain25 0
-pain50 sound/player/fricka/player/pain50 0
-pain75 sound/player/fricka/player/pain75 0
-pain100 sound/player/fricka/player/pain100 0
+++ /dev/null
-visitant,fricka
+++ /dev/null
-visitant,fricka
+++ /dev/null
-visitant,fricka
+++ /dev/null
-/*
-Generated framegroups file for xolar
-Used by DarkPlaces to simulate frame groups in DPM models.
-*/
-
-1 41 15 0 // xolar die1
-42 47 30 0 // xolar die2
-89 11 30 1 // xolar draw
-100 11 30 1 // xolar duck
-111 81 60 1 // xolar duckwalk
-192 41 60 0 // xolar duckjump
-233 21 10 1 // xolar duckidle
-254 301 10 1 // xolar idle
-555 41 60 0 // xolar jump
-596 6 15 0 // xolar pain1
-602 6 15 0 // xolar pain2
-608 8 30 1 // xolar shoot
-616 31 30 1 // xolar taunt
-647 41 60 1 // xolar run
-688 41 60 1 // xolar runbackwards
-729 41 60 1 // xolar strafeleft
-770 41 60 1 // xolar straferight
-811 3 30 0 // xolar dead1
-814 3 30 0 // xolar dead2
-817 41 60 1 // xolar forwardright
-858 41 60 1 // xolar forwardleft
-899 41 60 1 // xolar backright
-940 41 60 1 // xolar backleft
+++ /dev/null
-//TAG: soldier
-//affirmative sound/player/carni-lycan/player/affirmative 0
-attack sound/player/soldier/coms/attack 0
-//attacking sound/player/carni-lycan/player/attacking 0
-attackinfive sound/player/soldier/coms/attackinfive 0
-coverme sound/player/soldier/coms/coverme 0
-defend sound/player/soldier/coms/defend 0
-//defending sound/player/carni-lycan/player/defending 0
-//droppedflag sound/player/carni-lycan/player/droppedflag 0
-//flagcarriertakingdamage sound/player/carni-lycan/player/flagcarriertakingdamage 0
-freelance sound/player/soldier/coms/freelance 2
-//getflag sound/player/carni-lycan/player/getflag 0
-//incoming sound/player/soldier/coms/incoming 0
-meet sound/player/soldier/coms/meet 0
-needhelp sound/player/soldier/coms/needhelp 2
-//negative sound/player/carni-lycan/player/negative 0
-//onmyway sound/player/carni-lycan/player/onmyway 0
-//roaming sound/player/carni-lycan/player/roaming 0
-//seenenemy sound/player/carni-lycan/player/seenenemy 0
-seenflag sound/player/soldier/coms/seenflag 0
-taunt sound/player/soldier/coms/taunt 3
-teamshoot sound/player/soldier/coms/teamshoot 3
-death sound/player/soldier/player/death 3
-drown sound/player/soldier/player/drown 0
-//fall sound/player/carni-lycan/player/fall 0
-falling sound/player/soldier/player/falling 0
-gasp sound/player/soldier/player/gasp 0
-jump sound/player/soldier/player/jump 0
-pain25 sound/player/soldier/player/pain25 0
-pain50 sound/player/soldier/player/pain50 0
-pain75 sound/player/soldier/player/pain75 0
-pain100 sound/player/soldier/player/pain100 0
+++ /dev/null
-Xolar
-models/player/xolar
-0
-models/player/xolar.dpm
-species robot_solid
-
-Heavy Nexuiz's Soldier
-
-Weight: 582 kg
-Age: 439
+++ /dev/null
-//TAG: soldier
-//affirmative sound/player/carni-lycan/player/affirmative 0
-attack sound/player/soldier/coms/attack 0
-//attacking sound/player/carni-lycan/player/attacking 0
-attackinfive sound/player/soldier/coms/attackinfive 0
-coverme sound/player/soldier/coms/coverme 0
-defend sound/player/soldier/coms/defend 0
-//defending sound/player/carni-lycan/player/defending 0
-//droppedflag sound/player/carni-lycan/player/droppedflag 0
-//flagcarriertakingdamage sound/player/carni-lycan/player/flagcarriertakingdamage 0
-freelance sound/player/soldier/coms/freelance 2
-//getflag sound/player/carni-lycan/player/getflag 0
-//incoming sound/player/soldier/coms/incoming 0
-meet sound/player/soldier/coms/meet 0
-needhelp sound/player/soldier/coms/needhelp 2
-//negative sound/player/carni-lycan/player/negative 0
-//onmyway sound/player/carni-lycan/player/onmyway 0
-//roaming sound/player/carni-lycan/player/roaming 0
-//seenenemy sound/player/carni-lycan/player/seenenemy 0
-seenflag sound/player/soldier/coms/seenflag 0
-taunt sound/player/soldier/coms/taunt 3
-teamshoot sound/player/soldier/coms/teamshoot 3
-death sound/player/soldier/player/death 3
-drown sound/player/soldier/player/drown 0
-//fall sound/player/carni-lycan/player/fall 0
-falling sound/player/soldier/player/falling 0
-gasp sound/player/soldier/player/gasp 0
-jump sound/player/soldier/player/jump 0
-pain25 sound/player/soldier/player/pain25 0
-pain50 sound/player/soldier/player/pain50 0
-pain75 sound/player/soldier/player/pain75 0
-pain100 sound/player/soldier/player/pain100 0
+++ /dev/null
-/*
-Generated framegroups file for xolar_lod1
-Used by DarkPlaces to simulate frame groups in DPM models.
-*/
-
-1 41 15 0 // xolar_lod1 die1
-42 47 30 0 // xolar_lod1 die2
-89 11 30 1 // xolar_lod1 draw
-100 11 30 1 // xolar_lod1 duck
-111 81 60 1 // xolar_lod1 duckwalk
-192 41 60 0 // xolar_lod1 duckjump
-233 21 10 1 // xolar_lod1 duckidle
-254 301 10 1 // xolar_lod1 idle
-555 41 60 0 // xolar_lod1 jump
-596 6 15 0 // xolar_lod1 pain1
-602 6 15 0 // xolar_lod1 pain2
-608 8 30 1 // xolar_lod1 shoot
-616 31 30 1 // xolar_lod1 taunt
-647 41 60 1 // xolar_lod1 run
-688 41 60 1 // xolar_lod1 runbackwards
-729 41 60 1 // xolar_lod1 strafeleft
-770 41 60 1 // xolar_lod1 straferight
-811 3 30 0 // xolar_lod1 dead1
-814 3 30 0 // xolar_lod1 dead2
-817 41 60 1 // xolar_lod1 forwardright
-858 41 60 1 // xolar_lod1 forwardleft
-899 41 60 1 // xolar_lod1 backright
-940 41 60 1 // xolar_lod1 backleft
+++ /dev/null
-/*
-Generated animinfo file for xolar_lod2
-Useful for game code to simulate frame groups in DPM models.
-*/
-
-
-// end of animinfo definitions for xolar_lod2
-
-
+++ /dev/null
-/*
-Generated framegroups file for xolar_lod2
-Used by DarkPlaces to simulate frame groups in DPM models.
-*/
-
-1 41 15 0 // xolar_lod2 die1
-42 47 30 0 // xolar_lod2 die2
-89 11 30 1 // xolar_lod2 draw
-100 11 30 1 // xolar_lod2 duck
-111 81 60 1 // xolar_lod2 duckwalk
-192 41 60 0 // xolar_lod2 duckjump
-233 21 10 1 // xolar_lod2 duckidle
-254 301 10 1 // xolar_lod2 idle
-555 41 60 0 // xolar_lod2 jump
-596 6 15 0 // xolar_lod2 pain1
-602 6 15 0 // xolar_lod2 pain2
-608 8 30 1 // xolar_lod2 shoot
-616 31 30 1 // xolar_lod2 taunt
-647 41 60 1 // xolar_lod2 run
-688 41 60 1 // xolar_lod2 runbackwards
-729 41 60 1 // xolar_lod2 strafeleft
-770 41 60 1 // xolar_lod2 straferight
-811 3 30 0 // xolar_lod2 dead1
-814 3 30 0 // xolar_lod2 dead2
-817 41 60 1 // xolar_lod2 forwardright
-858 41 60 1 // xolar_lod2 forwardleft
-899 41 60 1 // xolar_lod2 backright
-940 41 60 1 // xolar_lod2 backleft
-portal,textures/portals/portals_red.tga
+portal,portals/portals_red
vortex,portals_red_vortex
-portal,textures/portals/portals_blue.tga
+portal,portals/portals_blue
vortex,portals_blue_vortex
-portal,textures/portals/portals_inactive.tga
+portal,portals/portals_inactive
vortex,portals_inactive_vortex
-1 1 1 0 // ANIM_NO\r
-35 55 20 1 // ANIM_TURN\r
-5 25 20 1 // ANIM_WALK\r
-5 25 40 1 // ANIM_RUN\r
-35 55 20 1 // ANIM_STRAFE_L\r
-65 85 20 1 // ANIM_STRAFE_R\r
-95 100 20 0 // ANIM_JUMP\r
-100 107 20 0 // ANIM_LAND\r
-90 95 20 0 // ANIM_PAIN\r
-123 140 40 0 // ANIM_MEELE\r
-146 151 20 1 // ANIM_SWIM\r
-5 25 20 1 // ANIM_ROAM\r
+1 1 1 0 // ANIM_NO
+35 55 20 1 // ANIM_TURN
+5 25 20 1 // ANIM_WALK
+5 25 40 1 // ANIM_RUN
+35 55 20 1 // ANIM_STRAFE_L
+65 85 20 1 // ANIM_STRAFE_R
+95 100 20 0 // ANIM_JUMP
+100 107 20 0 // ANIM_LAND
+90 95 20 0 // ANIM_PAIN
+123 140 40 0 // ANIM_MEELE
+146 151 20 1 // ANIM_SWIM
+5 25 20 1 // ANIM_ROAM
-1 30 20 1 // forward\r
-32 30 20 1 // backward\r
-63 30 20 1 // left\r
-94 30 20 1 // right\r
-125 30 20 0 // jump\r
-0 1 20 0 // idle\r
+1 30 20 1 // forward
+32 30 20 1 // backward
+63 30 20 1 // left
+94 30 20 1 // right
+125 30 20 0 // jump
+0 1 20 0 // idle
+++ /dev/null
-1 8 20 0 // fire
-9 5 20 0 // fire2
-15 200 20 1 // idle
-215 39 20 0 // reload
--- /dev/null
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 39 20 0 // reload
+++ /dev/null
-1 8 20 0 // fire
-9 5 20 0 // fire2
-15 200 20 1 // idle
-215 40 20 0 // reload
--- /dev/null
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 40 20 0 // reload
+++ /dev/null
-1 8 20 0 // fire
-9 5 20 0 // fire2
-15 200 20 1 // idle
-215 40 20 0 // reload
--- /dev/null
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 40 20 0 // reload
+++ /dev/null
-1 8 20 0 // fire
-9 5 20 0 // fire2
-15 200 20 1 // idle
-215 40 20 0 // reload
--- /dev/null
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 40 20 0 // reload
+++ /dev/null
-1 8 20 0 // fire
-9 5 20 0 // fire2
-15 200 20 1 // idle
-215 40 20 0 // reload
--- /dev/null
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 40 20 0 // reload
+++ /dev/null
-1 8 20 0 // fire
-9 5 20 0 // fire2
-15 200 20 1 // idle
-215 40 20 0 // reload
--- /dev/null
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 40 20 0 // reload
+++ /dev/null
-1 8 20 0 // fire
-9 5 20 0 // fire2
-15 200 20 1 // idle
-215 40 20 0 // reload
--- /dev/null
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 40 20 0 // reload
+++ /dev/null
-1 8 20 0 // fire
-9 5 20 0 // fire2
-15 200 20 1 // idle
-215 40 20 0 // reload
--- /dev/null
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 40 20 0 // reload
+++ /dev/null
-1 8 20 0 // fire
-9 5 20 0 // fire2
-15 200 20 1 // idle
-215 40 20 0 // reload
--- /dev/null
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 40 20 0 // reload
+++ /dev/null
-1 8 20 0 // fire
-9 5 20 0 // fire2
-15 200 20 1 // idle
-215 40 20 0 // reload
--- /dev/null
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 40 20 0 // reload
+++ /dev/null
-1 8 20 0 // fire
-9 5 20 0 // fire2
-15 200 20 1 // idle
-215 40 20 0 // reload
--- /dev/null
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 40 20 0 // reload
+++ /dev/null
-1 8 20 0 // fire
-9 5 20 0 // fire2
-15 200 20 1 // idle
-215 40 20 0 // reload
--- /dev/null
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 40 20 0 // reload
+++ /dev/null
-1 8 20 0 // fire
-9 5 20 0 // fire2
-15 200 20 1 // idle
-215 40 20 0 // reload
--- /dev/null
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 40 20 0 // reload
--- /dev/null
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 40 20 0 // reload
+++ /dev/null
-1 8 20 0 // fire
-9 5 20 0 // fire2
-15 200 20 1 // idle
-215 40 20 0 // reload
--- /dev/null
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 40 20 0 // reload
+++ /dev/null
-1 8 20 0 // fire
-9 5 20 0 // fire2
-15 200 20 1 // idle
-215 40 20 0 // reload
--- /dev/null
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 40 20 0 // reload
+++ /dev/null
-1 8 20 0 // fire
-9 5 20 0 // fire2
-15 200 20 1 // idle
-215 40 20 0 // reload
--- /dev/null
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 40 20 0 // reload
-set g_monster_zombie_respawntime 2\r
-set g_monster_zombie_movespeed 350\r
-set g_monster_zombie_health 275\r
-set g_monster_zombie_stopspeed 90\r
-set g_monster_zombie_turnspeed 360\r
-set g_monster_zombie_idle_timer_min 5\r
-set g_monster_zombie_idle_timer_max 10\r
-set g_monster_zombie_targetrange 2048\r
-\r
-set g_monster_zombie_attack_run_range 128\r
-set g_monster_zombie_attack_run_hitrange 96\r
-set g_monster_zombie_attack_run_delay 0.35\r
-set g_monster_zombie_attack_run_damage 30\r
-set g_monster_zombie_attack_run_force 300\r
-\r
-set g_monster_zombie_attack_stand_range 64\r
-set g_monster_zombie_attack_stand_hitrange 64\r
-set g_monster_zombie_attack_stand_delay 0.25\r
-set g_monster_zombie_attack_stand_damage 60\r
-set g_monster_zombie_attack_stand_force 250\r
-\r
+set g_monster_zombie_respawntime 2
+set g_monster_zombie_movespeed 350
+set g_monster_zombie_health 275
+set g_monster_zombie_stopspeed 90
+set g_monster_zombie_turnspeed 360
+set g_monster_zombie_idle_timer_min 5
+set g_monster_zombie_idle_timer_max 10
+set g_monster_zombie_targetrange 2048
+
+set g_monster_zombie_attack_run_range 128
+set g_monster_zombie_attack_run_hitrange 96
+set g_monster_zombie_attack_run_delay 0.35
+set g_monster_zombie_attack_run_damage 30
+set g_monster_zombie_attack_run_force 300
+
+set g_monster_zombie_attack_stand_range 64
+set g_monster_zombie_attack_stand_hitrange 64
+set g_monster_zombie_attack_stand_delay 0.25
+set g_monster_zombie_attack_stand_damage 60
+set g_monster_zombie_attack_stand_force 250
+
--- /dev/null
+0 0.00048828125 0.00048828125 0.06201171875 0.06201171875
+1 0.06298828125 0.00048828125 0.12451171875 0.06201171875
+2 0.12548828125 0.00048828125 0.18701171875 0.06201171875
+3 0.18798828125 0.00048828125 0.24951171875 0.06201171875
+4 0.25048828125 0.00048828125 0.31201171875 0.06201171875
+5 0.31298828125 0.00048828125 0.37451171875 0.06201171875
+6 0.37548828125 0.00048828125 0.43701171875 0.06201171875
+7 0.43798828125 0.00048828125 0.49951171875 0.06201171875
+8 0.50048828125 0.00048828125 0.56201171875 0.06201171875
+9 0.56298828125 0.00048828125 0.62451171875 0.06201171875
+10 0.62548828125 0.00048828125 0.68701171875 0.06201171875
+11 0.68798828125 0.00048828125 0.74951171875 0.06201171875
+12 0.75048828125 0.00048828125 0.81201171875 0.06201171875
+13 0.81298828125 0.00048828125 0.87451171875 0.06201171875
+14 0.87548828125 0.00048828125 0.93701171875 0.06201171875
+15 0.93798828125 0.00048828125 0.99951171875 0.06201171875
+16 0.00048828125 0.06298828125 0.06201171875 0.12451171875
+17 0.06298828125 0.06298828125 0.12451171875 0.12451171875
+18 0.12548828125 0.06298828125 0.18701171875 0.12451171875
+19 0.18798828125 0.06298828125 0.24951171875 0.12451171875
+20 0.25048828125 0.06298828125 0.31201171875 0.12451171875
+21 0.31298828125 0.06298828125 0.37451171875 0.12451171875
+22 0.37548828125 0.06298828125 0.43701171875 0.12451171875
+23 0.43798828125 0.06298828125 0.49951171875 0.12451171875
+24 0.50048828125 0.06298828125 0.56201171875 0.12451171875
+25 0.56298828125 0.06298828125 0.62451171875 0.12451171875
+26 0.62548828125 0.06298828125 0.68701171875 0.12451171875
+27 0.68798828125 0.06298828125 0.74951171875 0.12451171875
+28 0.75048828125 0.06298828125 0.81201171875 0.12451171875
+29 0.81298828125 0.06298828125 0.87451171875 0.12451171875
+30 0.87548828125 0.06298828125 0.93701171875 0.12451171875
+31 0.93798828125 0.06298828125 0.99951171875 0.12451171875
+32 0.00048828125 0.12548828125 0.06201171875 0.18701171875
+33 0.06298828125 0.12548828125 0.12451171875 0.18701171875
+34 0.12548828125 0.12548828125 0.18701171875 0.18701171875
+35 0.18798828125 0.12548828125 0.24951171875 0.18701171875
+36 0.25048828125 0.12548828125 0.31201171875 0.18701171875
+37 0.31298828125 0.12548828125 0.37451171875 0.18701171875
+38 0.37548828125 0.12548828125 0.43701171875 0.18701171875
+39 0.43798828125 0.12548828125 0.49951171875 0.18701171875
+40 0.50048828125 0.12548828125 0.56201171875 0.18701171875
+41 0.56298828125 0.12548828125 0.62451171875 0.18701171875
+42 0.62548828125 0.12548828125 0.68701171875 0.18701171875
+43 0.68798828125 0.12548828125 0.74951171875 0.18701171875
+44 0.75048828125 0.12548828125 0.81201171875 0.18701171875
+45 0.81298828125 0.12548828125 0.87451171875 0.18701171875
+46 0.87548828125 0.12548828125 0.93701171875 0.18701171875
+47 0.93798828125 0.12548828125 0.99951171875 0.18701171875
+48 0.00048828125 0.18798828125 0.06201171875 0.24951171875
+49 0.06298828125 0.18798828125 0.12451171875 0.24951171875
+50 0.12548828125 0.18798828125 0.18701171875 0.24951171875
+51 0.18798828125 0.18798828125 0.24951171875 0.24951171875
+52 0.25048828125 0.18798828125 0.31201171875 0.24951171875
+53 0.31298828125 0.18798828125 0.37451171875 0.24951171875
+54 0.37548828125 0.18798828125 0.43701171875 0.24951171875
+55 0.43798828125 0.18798828125 0.49951171875 0.24951171875
+56 0.50048828125 0.18798828125 0.56201171875 0.24951171875
+57 0.56298828125 0.18798828125 0.62451171875 0.24951171875
+58 0.62548828125 0.18798828125 0.68701171875 0.24951171875
+59 0.68798828125 0.18798828125 0.74951171875 0.24951171875
+60 0.75048828125 0.18798828125 0.81201171875 0.24951171875
+61 0.81298828125 0.18798828125 0.87451171875 0.24951171875
+62 0.87548828125 0.18798828125 0.93701171875 0.24951171875
+63 0.93798828125 0.18798828125 0.99951171875 0.24951171875
+64 0.00048828125 0.25048828125 0.06201171875 0.31201171875
+65 0.06298828125 0.25048828125 0.12451171875 0.31201171875
+66 0.12548828125 0.25048828125 0.18701171875 0.31201171875
+67 0.18798828125 0.25048828125 0.24951171875 0.31201171875
+68 0.25048828125 0.25048828125 0.31201171875 0.31201171875
+69 0.31298828125 0.25048828125 0.37451171875 0.31201171875
+70 0.37548828125 0.25048828125 0.43701171875 0.31201171875
+71 0.43798828125 0.25048828125 0.49951171875 0.31201171875
+72 0.50048828125 0.25048828125 0.56201171875 0.31201171875
+73 0.56298828125 0.25048828125 0.62451171875 0.31201171875
+74 0.62548828125 0.25048828125 0.68701171875 0.31201171875
+75 0.68798828125 0.25048828125 0.74951171875 0.31201171875
+76 0.75048828125 0.25048828125 0.81201171875 0.31201171875
+77 0.81298828125 0.25048828125 0.87451171875 0.31201171875
+78 0.87548828125 0.25048828125 0.93701171875 0.31201171875
+79 0.93798828125 0.25048828125 0.99951171875 0.31201171875
+80 0.00048828125 0.31298828125 0.06201171875 0.37451171875
+81 0.06298828125 0.31298828125 0.12451171875 0.37451171875
+82 0.12548828125 0.31298828125 0.18701171875 0.37451171875
+83 0.18798828125 0.31298828125 0.24951171875 0.37451171875
+84 0.25048828125 0.31298828125 0.31201171875 0.37451171875
+85 0.31298828125 0.31298828125 0.37451171875 0.37451171875
+86 0.37548828125 0.31298828125 0.43701171875 0.37451171875
+87 0.43798828125 0.31298828125 0.49951171875 0.37451171875
+88 0.50048828125 0.31298828125 0.56201171875 0.37451171875
+89 0.56298828125 0.31298828125 0.62451171875 0.37451171875
+90 0.62548828125 0.31298828125 0.68701171875 0.37451171875
+91 0.68798828125 0.31298828125 0.74951171875 0.37451171875
+92 0.75048828125 0.31298828125 0.81201171875 0.37451171875
+93 0.81298828125 0.31298828125 0.87451171875 0.37451171875
+94 0.87548828125 0.31298828125 0.93701171875 0.37451171875
+95 0.93798828125 0.31298828125 0.99951171875 0.37451171875
+96 0.00048828125 0.37548828125 0.06201171875 0.43701171875
+97 0.06298828125 0.37548828125 0.12451171875 0.43701171875
+98 0.12548828125 0.37548828125 0.18701171875 0.43701171875
+99 0.18798828125 0.37548828125 0.24951171875 0.43701171875
+100 0.25048828125 0.37548828125 0.31201171875 0.43701171875
+101 0.31298828125 0.37548828125 0.37451171875 0.43701171875
+102 0.37548828125 0.37548828125 0.43701171875 0.43701171875
+103 0.43798828125 0.37548828125 0.49951171875 0.43701171875
+104 0.50048828125 0.37548828125 0.56201171875 0.43701171875
+105 0.56298828125 0.37548828125 0.62451171875 0.43701171875
+106 0.62548828125 0.37548828125 0.68701171875 0.43701171875
+107 0.68798828125 0.37548828125 0.74951171875 0.43701171875
+108 0.75048828125 0.37548828125 0.81201171875 0.43701171875
+109 0.81298828125 0.37548828125 0.87451171875 0.43701171875
+110 0.87548828125 0.37548828125 0.93701171875 0.43701171875
+111 0.93798828125 0.37548828125 0.99951171875 0.43701171875
+112 0.00048828125 0.43798828125 0.06201171875 0.49951171875
+113 0.06298828125 0.43798828125 0.12451171875 0.49951171875
+114 0.12548828125 0.43798828125 0.18701171875 0.49951171875
+115 0.18798828125 0.43798828125 0.24951171875 0.49951171875
+116 0.25048828125 0.43798828125 0.31201171875 0.49951171875
+117 0.31298828125 0.43798828125 0.37451171875 0.49951171875
+118 0.37548828125 0.43798828125 0.43701171875 0.49951171875
+119 0.43798828125 0.43798828125 0.49951171875 0.49951171875
+120 0.50048828125 0.43798828125 0.56201171875 0.49951171875
+121 0.56298828125 0.43798828125 0.62451171875 0.49951171875
+122 0.62548828125 0.43798828125 0.68701171875 0.49951171875
+123 0.68798828125 0.43798828125 0.74951171875 0.49951171875
+124 0.75048828125 0.43798828125 0.81201171875 0.49951171875
+125 0.81298828125 0.43798828125 0.87451171875 0.49951171875
+126 0.87548828125 0.43798828125 0.93701171875 0.49951171875
+127 0.93798828125 0.43798828125 0.99951171875 0.49951171875
+128 0.00048828125 0.50048828125 0.06201171875 0.56201171875
+129 0.06298828125 0.50048828125 0.12451171875 0.56201171875
+130 0.12548828125 0.50048828125 0.18701171875 0.56201171875
+131 0.18798828125 0.50048828125 0.24951171875 0.56201171875
+132 0.25048828125 0.50048828125 0.31201171875 0.56201171875
+133 0.31298828125 0.50048828125 0.37451171875 0.56201171875
+134 0.37548828125 0.50048828125 0.43701171875 0.56201171875
+135 0.43798828125 0.50048828125 0.49951171875 0.56201171875
+136 0.50048828125 0.50048828125 0.56201171875 0.56201171875
+137 0.56298828125 0.50048828125 0.62451171875 0.56201171875
+138 0.62548828125 0.50048828125 0.68701171875 0.56201171875
+139 0.68798828125 0.50048828125 0.74951171875 0.56201171875
+140 0.75048828125 0.50048828125 0.81201171875 0.56201171875
+141 0.81298828125 0.50048828125 0.87451171875 0.56201171875
+142 0.87548828125 0.50048828125 0.93701171875 0.56201171875
+143 0.93798828125 0.50048828125 0.99951171875 0.56201171875
+144 0.00048828125 0.56298828125 0.06201171875 0.62451171875
+145 0.06298828125 0.56298828125 0.12451171875 0.62451171875
+146 0.12548828125 0.56298828125 0.18701171875 0.62451171875
+147 0.18798828125 0.56298828125 0.24951171875 0.62451171875
+148 0.25048828125 0.56298828125 0.31201171875 0.62451171875
+149 0.31298828125 0.56298828125 0.37451171875 0.62451171875
+150 0.37548828125 0.56298828125 0.43701171875 0.62451171875
+151 0.43798828125 0.56298828125 0.49951171875 0.62451171875
+152 0.50048828125 0.56298828125 0.56201171875 0.62451171875
+153 0.56298828125 0.56298828125 0.62451171875 0.62451171875
+154 0.62548828125 0.56298828125 0.68701171875 0.62451171875
+155 0.68798828125 0.56298828125 0.74951171875 0.62451171875
+156 0.75048828125 0.56298828125 0.81201171875 0.62451171875
+157 0.81298828125 0.56298828125 0.87451171875 0.62451171875
+158 0.87548828125 0.56298828125 0.93701171875 0.62451171875
+159 0.93798828125 0.56298828125 0.99951171875 0.62451171875
+1000 0 0.62548828125 1 0.68701171875
+1001 0 0.68798828125 1 0.74951171875
+1002 0 0.75048828125 1 0.81201171875
+1003 0 0.81298828125 1 0.87451171875
+1004 0 0.87548828125 1 0.93701171875
+1005 0 0.93798828125 1 0.99951171875
-0 0.001953125 0.001953125 0.123046875 0.123046875
-1 0.126953125 0.001953125 0.248046875 0.123046875
-2 0.251953125 0.001953125 0.373046875 0.123046875
-3 0.376953125 0.001953125 0.498046875 0.123046875
-4 0.501953125 0.001953125 0.623046875 0.123046875
-5 0.626953125 0.001953125 0.748046875 0.123046875
-6 0.751953125 0.001953125 0.873046875 0.123046875
-7 0.876953125 0.001953125 0.998046875 0.123046875
-8 0.001953125 0.126953125 0.123046875 0.248046875
-9 0.126953125 0.126953125 0.248046875 0.248046875
-10 0.251953125 0.126953125 0.373046875 0.248046875
-11 0.376953125 0.126953125 0.498046875 0.248046875
-12 0.501953125 0.126953125 0.623046875 0.248046875
-13 0.626953125 0.126953125 0.748046875 0.248046875
-14 0.751953125 0.126953125 0.873046875 0.248046875
-15 0.876953125 0.126953125 0.998046875 0.248046875
-16 0.001953125 0.251953125 0.123046875 0.373046875
-17 0.126953125 0.251953125 0.248046875 0.373046875
-18 0.251953125 0.251953125 0.373046875 0.373046875
-19 0.376953125 0.251953125 0.498046875 0.373046875
-20 0.501953125 0.251953125 0.623046875 0.373046875
-21 0.626953125 0.251953125 0.748046875 0.373046875
-22 0.751953125 0.251953125 0.873046875 0.373046875
-23 0.876953125 0.251953125 0.998046875 0.373046875
-24 0.001953125 0.376953125 0.123046875 0.498046875
-25 0.126953125 0.376953125 0.248046875 0.498046875
-26 0.251953125 0.376953125 0.373046875 0.498046875
-27 0.376953125 0.376953125 0.498046875 0.498046875
-28 0.501953125 0.376953125 0.623046875 0.498046875
-29 0.626953125 0.376953125 0.748046875 0.498046875
-30 0.751953125 0.376953125 0.873046875 0.498046875
-31 0.876953125 0.376953125 0.998046875 0.498046875
-32 0.001953125 0.501953125 0.123046875 0.623046875
-33 0.126953125 0.501953125 0.248046875 0.623046875
-34 0.251953125 0.501953125 0.373046875 0.623046875
-35 0.376953125 0.501953125 0.498046875 0.623046875
-36 0.501953125 0.501953125 0.623046875 0.623046875
-37 0.626953125 0.501953125 0.748046875 0.623046875
-38 0.751953125 0.501953125 0.873046875 0.623046875
-39 0.876953125 0.501953125 0.998046875 0.623046875
-40 0.001953125 0.626953125 0.123046875 0.748046875
-41 0.126953125 0.626953125 0.248046875 0.748046875
-42 0.251953125 0.626953125 0.373046875 0.748046875
-43 0.376953125 0.626953125 0.498046875 0.748046875
-44 0.501953125 0.626953125 0.623046875 0.748046875
-45 0.626953125 0.626953125 0.748046875 0.748046875
-46 0.751953125 0.626953125 0.873046875 0.748046875
-47 0.876953125 0.626953125 0.998046875 0.748046875
-48 0.001953125 0.751953125 0.123046875 0.873046875
-49 0.126953125 0.751953125 0.248046875 0.873046875
-50 0.251953125 0.751953125 0.373046875 0.873046875
-51 0.376953125 0.751953125 0.498046875 0.873046875
-52 0.501953125 0.751953125 0.623046875 0.873046875
-53 0.626953125 0.751953125 0.748046875 0.873046875
-54 0.751953125 0.751953125 0.873046875 0.873046875
-55 0.876953125 0.751953125 0.998046875 0.873046875
-56 0.001953125 0.876953125 0.123046875 0.998046875
-57 0.126953125 0.876953125 0.248046875 0.998046875
-58 0.251953125 0.876953125 0.373046875 0.998046875
-59 0.376953125 0.876953125 0.498046875 0.998046875
-// 60 0.501953125 0.876953125 0.623046875 0.998046875
-61 0.626953125 0.876953125 0.748046875 0.998046875
-62 0.751953125 0.876953125 0.873046875 0.998046875
-63 0.876953125 0.876953125 0.998046875 0.998046875
+0 0.00048828125 0.00048828125 0.06201171875 0.06201171875
+1 0.06298828125 0.00048828125 0.12451171875 0.06201171875
+2 0.12548828125 0.00048828125 0.18701171875 0.06201171875
+3 0.18798828125 0.00048828125 0.24951171875 0.06201171875
+4 0.25048828125 0.00048828125 0.31201171875 0.06201171875
+5 0.31298828125 0.00048828125 0.37451171875 0.06201171875
+6 0.37548828125 0.00048828125 0.43701171875 0.06201171875
+7 0.43798828125 0.00048828125 0.49951171875 0.06201171875
+8 0.50048828125 0.00048828125 0.56201171875 0.06201171875
+9 0.56298828125 0.00048828125 0.62451171875 0.06201171875
+10 0.62548828125 0.00048828125 0.68701171875 0.06201171875
+11 0.68798828125 0.00048828125 0.74951171875 0.06201171875
+12 0.75048828125 0.00048828125 0.81201171875 0.06201171875
+13 0.81298828125 0.00048828125 0.87451171875 0.06201171875
+14 0.87548828125 0.00048828125 0.93701171875 0.06201171875
+15 0.93798828125 0.00048828125 0.99951171875 0.06201171875
+16 0.00048828125 0.06298828125 0.06201171875 0.12451171875
+17 0.06298828125 0.06298828125 0.12451171875 0.12451171875
+18 0.12548828125 0.06298828125 0.18701171875 0.12451171875
+19 0.18798828125 0.06298828125 0.24951171875 0.12451171875
+20 0.25048828125 0.06298828125 0.31201171875 0.12451171875
+21 0.31298828125 0.06298828125 0.37451171875 0.12451171875
+22 0.37548828125 0.06298828125 0.43701171875 0.12451171875
+23 0.43798828125 0.06298828125 0.49951171875 0.12451171875
+24 0.50048828125 0.06298828125 0.56201171875 0.12451171875
+25 0.56298828125 0.06298828125 0.62451171875 0.12451171875
+26 0.62548828125 0.06298828125 0.68701171875 0.12451171875
+27 0.68798828125 0.06298828125 0.74951171875 0.12451171875
+28 0.75048828125 0.06298828125 0.81201171875 0.12451171875
+29 0.81298828125 0.06298828125 0.87451171875 0.12451171875
+30 0.87548828125 0.06298828125 0.93701171875 0.12451171875
+31 0.93798828125 0.06298828125 0.99951171875 0.12451171875
+32 0.00048828125 0.12548828125 0.06201171875 0.18701171875
+33 0.06298828125 0.12548828125 0.12451171875 0.18701171875
+34 0.12548828125 0.12548828125 0.18701171875 0.18701171875
+35 0.18798828125 0.12548828125 0.24951171875 0.18701171875
+36 0.25048828125 0.12548828125 0.31201171875 0.18701171875
+37 0.31298828125 0.12548828125 0.37451171875 0.18701171875
+38 0.37548828125 0.12548828125 0.43701171875 0.18701171875
+39 0.43798828125 0.12548828125 0.49951171875 0.18701171875
+40 0.50048828125 0.12548828125 0.56201171875 0.18701171875
+41 0.56298828125 0.12548828125 0.62451171875 0.18701171875
+42 0.62548828125 0.12548828125 0.68701171875 0.18701171875
+43 0.68798828125 0.12548828125 0.74951171875 0.18701171875
+44 0.75048828125 0.12548828125 0.81201171875 0.18701171875
+45 0.81298828125 0.12548828125 0.87451171875 0.18701171875
+46 0.87548828125 0.12548828125 0.93701171875 0.18701171875
+47 0.93798828125 0.12548828125 0.99951171875 0.18701171875
+48 0.00048828125 0.18798828125 0.06201171875 0.24951171875
+49 0.06298828125 0.18798828125 0.12451171875 0.24951171875
+50 0.12548828125 0.18798828125 0.18701171875 0.24951171875
+51 0.18798828125 0.18798828125 0.24951171875 0.24951171875
+52 0.25048828125 0.18798828125 0.31201171875 0.24951171875
+53 0.31298828125 0.18798828125 0.37451171875 0.24951171875
+54 0.37548828125 0.18798828125 0.43701171875 0.24951171875
+55 0.43798828125 0.18798828125 0.49951171875 0.24951171875
+56 0.50048828125 0.18798828125 0.56201171875 0.24951171875
+57 0.56298828125 0.18798828125 0.62451171875 0.24951171875
+58 0.62548828125 0.18798828125 0.68701171875 0.24951171875
+59 0.68798828125 0.18798828125 0.74951171875 0.24951171875
+60 0.75048828125 0.18798828125 0.81201171875 0.24951171875
+61 0.81298828125 0.18798828125 0.87451171875 0.24951171875
+62 0.87548828125 0.18798828125 0.93701171875 0.24951171875
+63 0.93798828125 0.18798828125 0.99951171875 0.24951171875
+64 0.00048828125 0.25048828125 0.06201171875 0.31201171875
+65 0.06298828125 0.25048828125 0.12451171875 0.31201171875
+66 0.12548828125 0.25048828125 0.18701171875 0.31201171875
+67 0.18798828125 0.25048828125 0.24951171875 0.31201171875
+68 0.25048828125 0.25048828125 0.31201171875 0.31201171875
+69 0.31298828125 0.25048828125 0.37451171875 0.31201171875
+70 0.37548828125 0.25048828125 0.43701171875 0.31201171875
+71 0.43798828125 0.25048828125 0.49951171875 0.31201171875
+72 0.50048828125 0.25048828125 0.56201171875 0.31201171875
+73 0.56298828125 0.25048828125 0.62451171875 0.31201171875
+74 0.62548828125 0.25048828125 0.68701171875 0.31201171875
+75 0.68798828125 0.25048828125 0.74951171875 0.31201171875
+76 0.75048828125 0.25048828125 0.81201171875 0.31201171875
+77 0.81298828125 0.25048828125 0.87451171875 0.31201171875
+78 0.87548828125 0.25048828125 0.93701171875 0.31201171875
+79 0.93798828125 0.25048828125 0.99951171875 0.31201171875
+80 0.00048828125 0.31298828125 0.06201171875 0.37451171875
+81 0.06298828125 0.31298828125 0.12451171875 0.37451171875
+82 0.12548828125 0.31298828125 0.18701171875 0.37451171875
+83 0.18798828125 0.31298828125 0.24951171875 0.37451171875
+84 0.25048828125 0.31298828125 0.31201171875 0.37451171875
+85 0.31298828125 0.31298828125 0.37451171875 0.37451171875
+86 0.37548828125 0.31298828125 0.43701171875 0.37451171875
+87 0.43798828125 0.31298828125 0.49951171875 0.37451171875
+88 0.50048828125 0.31298828125 0.56201171875 0.37451171875
+89 0.56298828125 0.31298828125 0.62451171875 0.37451171875
+90 0.62548828125 0.31298828125 0.68701171875 0.37451171875
+91 0.68798828125 0.31298828125 0.74951171875 0.37451171875
+92 0.75048828125 0.31298828125 0.81201171875 0.37451171875
+93 0.81298828125 0.31298828125 0.87451171875 0.37451171875
+94 0.87548828125 0.31298828125 0.93701171875 0.37451171875
+95 0.93798828125 0.31298828125 0.99951171875 0.37451171875
+96 0.00048828125 0.37548828125 0.06201171875 0.43701171875
+97 0.06298828125 0.37548828125 0.12451171875 0.43701171875
+98 0.12548828125 0.37548828125 0.18701171875 0.43701171875
+99 0.18798828125 0.37548828125 0.24951171875 0.43701171875
+100 0.25048828125 0.37548828125 0.31201171875 0.43701171875
+101 0.31298828125 0.37548828125 0.37451171875 0.43701171875
+102 0.37548828125 0.37548828125 0.43701171875 0.43701171875
+103 0.43798828125 0.37548828125 0.49951171875 0.43701171875
+104 0.50048828125 0.37548828125 0.56201171875 0.43701171875
+105 0.56298828125 0.37548828125 0.62451171875 0.43701171875
+106 0.62548828125 0.37548828125 0.68701171875 0.43701171875
+107 0.68798828125 0.37548828125 0.74951171875 0.43701171875
+108 0.75048828125 0.37548828125 0.81201171875 0.43701171875
+109 0.81298828125 0.37548828125 0.87451171875 0.43701171875
+110 0.87548828125 0.37548828125 0.93701171875 0.43701171875
+111 0.93798828125 0.37548828125 0.99951171875 0.43701171875
+112 0.00048828125 0.43798828125 0.06201171875 0.49951171875
+113 0.06298828125 0.43798828125 0.12451171875 0.49951171875
+114 0.12548828125 0.43798828125 0.18701171875 0.49951171875
+115 0.18798828125 0.43798828125 0.24951171875 0.49951171875
+116 0.25048828125 0.43798828125 0.31201171875 0.49951171875
+117 0.31298828125 0.43798828125 0.37451171875 0.49951171875
+118 0.37548828125 0.43798828125 0.43701171875 0.49951171875
+119 0.43798828125 0.43798828125 0.49951171875 0.49951171875
+120 0.50048828125 0.43798828125 0.56201171875 0.49951171875
+121 0.56298828125 0.43798828125 0.62451171875 0.49951171875
+122 0.62548828125 0.43798828125 0.68701171875 0.49951171875
+123 0.68798828125 0.43798828125 0.74951171875 0.49951171875
+124 0.75048828125 0.43798828125 0.81201171875 0.49951171875
+125 0.81298828125 0.43798828125 0.87451171875 0.49951171875
+126 0.87548828125 0.43798828125 0.93701171875 0.49951171875
+127 0.93798828125 0.43798828125 0.99951171875 0.49951171875
+128 0.00048828125 0.50048828125 0.06201171875 0.56201171875
+129 0.06298828125 0.50048828125 0.12451171875 0.56201171875
+130 0.12548828125 0.50048828125 0.18701171875 0.56201171875
+131 0.18798828125 0.50048828125 0.24951171875 0.56201171875
+132 0.25048828125 0.50048828125 0.31201171875 0.56201171875
+133 0.31298828125 0.50048828125 0.37451171875 0.56201171875
+134 0.37548828125 0.50048828125 0.43701171875 0.56201171875
+135 0.43798828125 0.50048828125 0.49951171875 0.56201171875
+136 0.50048828125 0.50048828125 0.56201171875 0.56201171875
+137 0.56298828125 0.50048828125 0.62451171875 0.56201171875
+138 0.62548828125 0.50048828125 0.68701171875 0.56201171875
+139 0.68798828125 0.50048828125 0.74951171875 0.56201171875
+140 0.75048828125 0.50048828125 0.81201171875 0.56201171875
+141 0.81298828125 0.50048828125 0.87451171875 0.56201171875
+142 0.87548828125 0.50048828125 0.93701171875 0.56201171875
+143 0.93798828125 0.50048828125 0.99951171875 0.56201171875
+144 0.00048828125 0.56298828125 0.06201171875 0.62451171875
+145 0.06298828125 0.56298828125 0.12451171875 0.62451171875
+146 0.12548828125 0.56298828125 0.18701171875 0.62451171875
+147 0.18798828125 0.56298828125 0.24951171875 0.62451171875
+148 0.25048828125 0.56298828125 0.31201171875 0.62451171875
+149 0.31298828125 0.56298828125 0.37451171875 0.62451171875
+150 0.37548828125 0.56298828125 0.43701171875 0.62451171875
+151 0.43798828125 0.56298828125 0.49951171875 0.62451171875
+152 0.50048828125 0.56298828125 0.56201171875 0.62451171875
+153 0.56298828125 0.56298828125 0.62451171875 0.62451171875
+154 0.62548828125 0.56298828125 0.68701171875 0.62451171875
+155 0.68798828125 0.56298828125 0.74951171875 0.62451171875
+156 0.75048828125 0.56298828125 0.81201171875 0.62451171875
+157 0.81298828125 0.56298828125 0.87451171875 0.62451171875
+158 0.87548828125 0.56298828125 0.93701171875 0.62451171875
+159 0.93798828125 0.56298828125 0.99951171875 0.62451171875
+200 0 0.62548828125 1 0.68701171875
+201 0 0.68798828125 1 0.74951171875
+202 0 0.75048828125 1 0.81201171875
+203 0 0.81298828125 1 0.87451171875
+204 0 0.87548828125 1 0.93701171875
+205 0 0.93798828125 1 0.99951171875
sv_airstopaccelerate 0
sv_airstrafeaccelerate 0
sv_maxairstrafespeed 0
+sv_airstrafeaccel_qw 0
sv_aircontrol 0
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 0
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
sv_airstopaccelerate 0
sv_airstrafeaccelerate 0
sv_maxairstrafespeed 0
+sv_airstrafeaccel_qw 0
sv_aircontrol 0
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 0
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
sv_airstopaccelerate 0
sv_airstrafeaccelerate 0
sv_maxairstrafespeed 0
+sv_airstrafeaccel_qw 0
sv_aircontrol 0
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 0
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
sv_airstopaccelerate 0
sv_airstrafeaccelerate 0
sv_maxairstrafespeed 0
+sv_airstrafeaccel_qw 0
sv_aircontrol 0
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 0
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
sv_airstopaccelerate 0
sv_airstrafeaccelerate 0
sv_maxairstrafespeed 0
+sv_airstrafeaccel_qw 0
sv_aircontrol 0
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 0
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
sv_airstopaccelerate 0
sv_airstrafeaccelerate 0
sv_maxairstrafespeed 0
+sv_airstrafeaccel_qw 0
sv_aircontrol 0
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 0
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
sv_airstopaccelerate 0
sv_airstrafeaccelerate 0
sv_maxairstrafespeed 0
+sv_airstrafeaccel_qw 0
sv_aircontrol 0
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 0
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
sv_airstopaccelerate 0
sv_airstrafeaccelerate 0
sv_maxairstrafespeed 0
+sv_airstrafeaccel_qw 0
sv_aircontrol 0
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 0
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
sv_airstopaccelerate 2.5
sv_airstrafeaccelerate 70
sv_maxairstrafespeed 30
+sv_airstrafeaccel_qw 0
sv_aircontrol 150
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 0
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
sv_airstopaccelerate 0
sv_airstrafeaccelerate 0
sv_maxairstrafespeed 0
+sv_airstrafeaccel_qw 0
sv_aircontrol 0
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 0
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
--- /dev/null
+// These have been modified from Nexuiz 2.4.2's physicsQBR.cfg file
+sv_gravity 800
+sv_gravity 802
+sv_maxspeed 417
+sv_maxairspeed 202
+sv_stopspeed 100
+sv_accelerate 5.8
+sv_airaccelerate 5.5
+sv_friction 4.1
+edgefriction 1
+sv_stepheight 34
+sv_jumpvelocity 307
+sv_wateraccelerate -1
+sv_waterfriction -1
+sv_airaccel_sideways_friction 0.207
+sv_airaccel_qw -0.93
+sv_airstopaccelerate 0
+sv_airstrafeaccelerate 0
+sv_maxairstrafespeed 0
+sv_airstrafeaccel_qw 0
+sv_aircontrol 0
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
+sv_warsowbunny_turnaccel 0
+sv_warsowbunny_accel 0.1593
+sv_warsowbunny_topspeed 925
+sv_warsowbunny_backtosideratio 0.8
+sv_friction_on_land 0
+sv_doublejump 0
+sv_jumpspeedcap_min ""
+sv_jumpspeedcap_max ""
+sv_jumpspeedcap_max_disable_on_ramps 0
sv_airstopaccelerate 0
sv_airstrafeaccelerate 0
sv_maxairstrafespeed 0
+sv_airstrafeaccel_qw 0
sv_aircontrol 0
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 0
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
+++ /dev/null
-// Nexrun tweaked to suit CPM
-sv_gravity 800
-sv_maxspeed 320
-// CPMA: 320
-sv_maxairspeed 320
-// CPMA: 320
-sv_stopspeed 100
-sv_accelerate 15
-sv_airaccelerate 1
-sv_friction 8
-edgefriction 1
-sv_stepheight 34
-// CPMA: 18
-sv_jumpvelocity 270
-sv_wateraccelerate 4
-sv_waterfriction 1
-sv_airaccel_sideways_friction 0
-sv_airaccel_qw 0.95
-// CPMA: 1
-sv_airstopaccelerate 2.5
-sv_airstrafeaccelerate 70
-sv_maxairstrafespeed 30
-sv_aircontrol 150
-sv_warsowbunny_turnaccel 0
-sv_warsowbunny_accel 0.1593
-sv_warsowbunny_topspeed 925
-sv_warsowbunny_backtosideratio 0.8
-sv_friction_on_land 0
-sv_doublejump 1
-sv_jumpspeedcap_min 0
-sv_jumpspeedcap_max 1
-sv_jumpspeedcap_max_disable_on_ramps 1
+++ /dev/null
-// CPMA tweaked to match the speeds in old Nexrun
-sv_gravity 800
-sv_maxspeed 400
-// CPMA: 320
-sv_maxairspeed 400
-// CPMA: 320
-sv_stopspeed 100
-sv_accelerate 15
-sv_airaccelerate 1
-sv_friction 8
-edgefriction 1
-sv_stepheight 34
-// CPMA: 18
-sv_jumpvelocity 270
-sv_wateraccelerate 4
-sv_waterfriction 1
-sv_airaccel_sideways_friction 0
-sv_airaccel_qw 0.95
-// CPMA: 1
-sv_airstopaccelerate 2.5
-sv_airstrafeaccelerate 70
-sv_maxairstrafespeed 30
-sv_aircontrol 150
-sv_warsowbunny_turnaccel 0
-sv_warsowbunny_accel 0.1593
-sv_warsowbunny_topspeed 925
-sv_warsowbunny_backtosideratio 0.8
-sv_friction_on_land 0
-sv_doublejump 1
-sv_jumpspeedcap_min 0
-sv_jumpspeedcap_max 1
-sv_jumpspeedcap_max_disable_on_ramps 1
-// Xonotic 2.0-2.4.2 physics minus QW-bunnyhopping-bug, faster onground accel, CPMA air control
+// 2.0-2.4.2 physics minus QW-bunnyhopping-bug, faster onground accel, CPMA air control
sv_gravity 800
-sv_maxspeed 320
-sv_maxairspeed 320
+sv_maxspeed 400
+sv_maxairspeed 400
sv_stopspeed 100
sv_accelerate 15
-sv_airaccelerate 5.5
-sv_friction 5
+sv_airaccelerate 2
+sv_friction 7
edgefriction 1
sv_stepheight 34
sv_jumpvelocity 300
sv_wateraccelerate -1
sv_waterfriction -1
-sv_airaccel_sideways_friction -1
-sv_airaccel_qw -0.95
-sv_airstopaccelerate 0
-sv_airstrafeaccelerate 0
-sv_maxairstrafespeed 0
-sv_aircontrol 70
+sv_airaccel_sideways_friction -0.2
+sv_airaccel_qw -0.9475
+sv_airstopaccelerate 2.5
+sv_airstrafeaccelerate 24
+sv_maxairstrafespeed 100
+sv_airstrafeaccel_qw -0.9825
+sv_aircontrol 125
+sv_aircontrol_power 2.5
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 0
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
sv_doublejump 0
sv_jumpspeedcap_min ""
sv_jumpspeedcap_max ""
-sv_jumpspeedcap_max_disable_on_ramps 0
+sv_jumpspeedcap_max_disable_on_ramps 1
sv_airstopaccelerate 0
sv_airstrafeaccelerate 0
sv_maxairstrafespeed 0
+sv_airstrafeaccel_qw 0
sv_aircontrol 0
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 0
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
sv_airstopaccelerate 0
sv_airstrafeaccelerate 0
sv_maxairstrafespeed 0
+sv_airstrafeaccel_qw 0
sv_aircontrol 0
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 0
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
sv_airstopaccelerate 0
sv_airstrafeaccelerate 0
sv_maxairstrafespeed 0
+sv_airstrafeaccel_qw 0
sv_aircontrol 0
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 0
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
sv_airstopaccelerate 0
sv_airstrafeaccelerate 0
sv_maxairstrafespeed 0
+sv_airstrafeaccel_qw 0
sv_aircontrol 0
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 0
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
sv_airstopaccelerate 0
sv_airstrafeaccelerate 0
sv_maxairstrafespeed 0
+sv_airstrafeaccel_qw 0
sv_aircontrol 0
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 0
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
sv_airstopaccelerate 0
sv_airstrafeaccelerate 0
sv_maxairstrafespeed 0
+sv_airstrafeaccel_qw 0
sv_aircontrol 0
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 0
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
-sv_gravity 880\r
-sv_maxspeed 420\r
-sv_maxairspeed 235\r
-sv_stopspeed 200\r
-sv_accelerate 6\r
-sv_airaccelerate 6\r
-sv_friction 4\r
-edgefriction 0\r
-sv_stepheight 34\r
-sv_jumpvelocity 330\r
-sv_wateraccelerate -1\r
-sv_waterfriction -1\r
-sv_airaccel_sideways_friction 0.3\r
-sv_airaccel_qw 0.93\r
-sv_airstopaccelerate 0\r
-sv_airstrafeaccelerate 0\r
-sv_maxairstrafespeed 0\r
-sv_aircontrol 0\r
-sv_warsowbunny_turnaccel 0\r
-sv_warsowbunny_accel 0.1593\r
-sv_warsowbunny_topspeed 925\r
-sv_warsowbunny_backtosideratio 0.8\r
-sv_friction_on_land 0\r
-sv_doublejump 0\r
+// Mix of 2.3 physics and NANL physics, goal of going for faster movement
+sv_gravity 800
+sv_maxspeed 420
+sv_maxairspeed 235
+sv_stopspeed 200
+sv_accelerate 6
+sv_airaccelerate 6
+sv_friction 4
+edgefriction 1
+sv_stepheight 34
+sv_jumpvelocity 300
+sv_wateraccelerate -1
+sv_waterfriction -1
+sv_airaccel_sideways_friction 0.3
+sv_airaccel_qw 0.93
+sv_airstopaccelerate 0
+sv_airstrafeaccelerate 0
+sv_maxairstrafespeed 0
+sv_airstrafeaccel_qw 0
+sv_aircontrol 0
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
+sv_warsowbunny_turnaccel 0
+sv_warsowbunny_accel 0.1593
+sv_warsowbunny_topspeed 925
+sv_warsowbunny_backtosideratio 0.8
+sv_friction_on_land 0
+sv_doublejump 0
sv_jumpspeedcap_min ""
sv_jumpspeedcap_max ""
sv_jumpspeedcap_max_disable_on_ramps 0
sv_airstopaccelerate 2.5
sv_airstrafeaccelerate 70
sv_maxairstrafespeed 30
+sv_airstrafeaccel_qw 0
sv_aircontrol 0
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 9 // activates warsow movement mode
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
sv_airstopaccelerate 2.5
sv_airstrafeaccelerate 70
sv_maxairstrafespeed 30
+sv_airstrafeaccel_qw 0
sv_aircontrol 150
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 0
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
sv_airstopaccelerate 2
sv_airstrafeaccelerate 70
sv_maxairstrafespeed 30
+sv_airstrafeaccel_qw 0
sv_aircontrol 0
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
sv_warsowbunny_turnaccel 6 // activates warsow movement mode
sv_warsowbunny_accel 0.1585
sv_warsowbunny_topspeed 900
--- /dev/null
+// Nexrun tweaked to suit CPM
+sv_gravity 800
+sv_maxspeed 320
+// CPMA: 320
+sv_maxairspeed 320
+// CPMA: 320
+sv_stopspeed 100
+sv_accelerate 15
+sv_airaccelerate 1
+sv_friction 8
+edgefriction 1
+sv_stepheight 34
+// CPMA: 18
+sv_jumpvelocity 270
+sv_wateraccelerate 4
+sv_waterfriction 1
+sv_airaccel_sideways_friction 0
+sv_airaccel_qw 0.95
+// CPMA: 1
+sv_airstopaccelerate 2.5
+sv_airstrafeaccelerate 70
+sv_maxairstrafespeed 30
+sv_airstrafeaccel_qw 1
+sv_aircontrol 150
+sv_aircontrol_power 2
+sv_airspeedlimit_nonqw 0
+sv_warsowbunny_turnaccel 0
+sv_warsowbunny_accel 0.1593
+sv_warsowbunny_topspeed 925
+sv_warsowbunny_backtosideratio 0.8
+sv_friction_on_land 0
+sv_doublejump 1
+sv_jumpspeedcap_min 0
+sv_jumpspeedcap_max 1
+sv_jumpspeedcap_max_disable_on_ramps 1
check_unacceptable_compiler_bugs();
+#ifdef WATERMARK
+ print("^4CSQC Build information: ", WATERMARK(), "\n");
+#endif
+
float i;
CSQC_CheckEngine();
localcmd("sv_cmd debug_shotorg\n");
}
else if(cmd == "sendcvar") {
- s = cvar_string(argv(1));
- if(argv(1) == "cl_weaponpriority")
+ // W_FixWeaponOrder will trash argv, so save what we need.
+ string cvar;
+ cvar = strzone(argv(1));
+ s = cvar_string(cvar);
+ if(cvar == "cl_weaponpriority")
s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 1);
- else if(substring(argv(1), 0, 17) == "cl_weaponpriority" && strlen(argv(1)) == 18)
+ else if(substring(cvar, 0, 17) == "cl_weaponpriority" && strlen(cvar) == 18)
s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 0);
- localcmd("cmd sentcvar ", argv(1), " \"", s, "\"\n");
+ localcmd("cmd sentcvar ", cvar, " \"", s, "\"\n");
+ strunzone(cvar);
}
else if(cmd == "spawn") {
s = argv(1);
case ENT_CLIENT_TUBANOTE: Ent_TubaNote(bIsNewEntity); break;
case ENT_CLIENT_WARPZONE: WarpZone_Read(bIsNewEntity); break;
case ENT_CLIENT_WARPZONE_CAMERA: WarpZone_Camera_Read(bIsNewEntity); break;
+ case ENT_CLIENT_TRIGGER_MUSIC: Ent_ReadTriggerMusic(); break;
default:
error(strcat("unknown entity type in CSQC_Ent_Update: ", ftos(self.enttype), "\n"));
break;
g_weaponswitchdelay = ReadByte() / 255.0;
+ g_balance_grenadelauncher_secondary_bouncefactor = ReadCoord();
+ g_balance_grenadelauncher_secondary_bouncestop = ReadCoord();
+
if(!postinit)
PostInit();
}
// NOTE: Could just do return instead of break...
switch(nTEID)
{
+ case TE_CSQC_TARGET_MUSIC:
+ Net_TargetMusic();
+ bHandled = true;
+ break;
case TE_CSQC_PICTURE:
Net_MapVote_Picture();
bHandled = true;
mi = '-16 -16 -16';
ma = '16 16 16';
break;
+ case WEP_SEEKER: // projectile has a size!
+ mi = '-2 -2 -2';
+ ma = '2 2 2';
+ break;
case WEP_ELECTRO: // projectile has a size!
mi = '0 0 -3';
ma = '0 0 -3';
float camera_mode;
string NextFrameCommand;
void CSQC_SPIDER_HUD();
+void CSQC_RAPTOR_HUD();
+
+vector freeze_pmove_org, freeze_input_angles;
+
void CSQC_UpdateView(float w, float h)
{
entity e;
vo = '0 0 1' * getstati(STAT_VIEWHEIGHT);
warpzone_fixview_origin = pmove_org + vo;
- warpzone_fixview_angles = input_angles;
+ warpzone_fixview_cl_viewangles = input_angles;
+ warpzone_fixview_angles = view_angles;
WarpZone_FixView();
pmove_org = warpzone_fixview_origin - vo;
- input_angles = warpzone_fixview_angles;
+ input_angles = warpzone_fixview_cl_viewangles;
+ view_angles = warpzone_fixview_angles;
+
+ if(cvar("cl_lockview"))
+ {
+ pmove_org = freeze_pmove_org;
+ input_angles = view_angles = freeze_input_angles;
+ R_SetView(VF_ORIGIN, pmove_org + vo);
+ R_SetView(VF_ANGLES, view_angles);
+ //R_SetView(VF_CL_VIEWANGLES, input_angles);
+ }
+ freeze_pmove_org = pmove_org;
+ freeze_input_angles = input_angles;
// Render the Scene
if(!intermission || !view_set)
}
#endif
+ TargetMusic_Advance();
Fog_Force();
drawframetime = max(0.000001, time - drawtime);
}
else if(hud == HUD_WAKIZASHI)
CSQC_WAKIZASHI_HUD();
+ else if(hud == HUD_RAPTOR)
+ CSQC_RAPTOR_HUD();
else
{
if(cvar("r_letterbox") == 0)
void CSQC_SPIDER_HUD()
{
- float rockets, reload, heat, hp, shield, i;
+ float rockets, reload, heat, hp, shield;
vector picsize, hudloc;
// Fetch health & ammo stats
hp = bound(0,getstatf(STAT_VEHICLESTAT_HEALTH), 1);
shield = bound(0,getstatf(STAT_VEHICLESTAT_SHIELD), 1);
- heat = min(getstatf(STAT_VEHICLESTAT_RELOAD1), 1);
+ heat = min(getstatf(STAT_VEHICLESTAT_RELOAD1), 2);
rockets = getstati(STAT_VEHICLESTAT_AMMO2);
reload = min(getstatf(STAT_VEHICLESTAT_RELOAD2), 1);
picsize = drawgetimagesize(spider_a2) * 0.5;
drawpic(hudloc + '120 96 0', spider_a2, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
-
drawstring(hudloc + '145 19 0', strcat(ftos(rint(hp * 100)), "%"),'15 15 0','0 1 0', 1, DRAWFLAG_NORMAL);
drawstring(hudloc + '175 34 0', strcat(ftos(rint(shield * 100)), "%"),'15 15 0','0 0 1', 1, DRAWFLAG_NORMAL);
-
drawstring(hudloc + '136 102 0', strcat(ftos(100 - rint(heat * 100)), "%"),'14 14 0','1 1 0', 1, DRAWFLAG_NORMAL);
picsize = drawgetimagesize(spider_a1) * 0.85;
}
+#define raptor_h "gfx/vehicles/hud_bg.tga"
+#define raptor_b "gfx/vehicles/raptor.tga"
+#define raptor_g1 "gfx/vehicles/raptor_guns.tga"
+#define raptor_g2 "gfx/vehicles/raptor_bombs.tga"
+#define raptor_s "gfx/vehicles/shiled.tga"
+
+#define spider_a1 "gfx/hud/sb_rocket.tga"
+#define spider_a2 "gfx/sb_bullets.tga"
+
+void CSQC_RAPTOR_HUD()
+{
+ float rockets, reload, heat, hp, shield, energy;
+ vector picsize, hudloc;
+
+ // Fetch health & ammo stats
+ hp = bound(0,getstatf(STAT_VEHICLESTAT_HEALTH), 1);
+ shield = bound(0,getstatf(STAT_VEHICLESTAT_SHIELD), 1);
+ reload = min(getstatf(STAT_VEHICLESTAT_RELOAD1), 1);
+ energy = min(getstatf(STAT_VEHICLESTAT_ENERGY), 1);
+
+ // Draw the crosshairs
+ picsize = drawgetimagesize(SPIDER_CROSS);
+ picsize_x *= cvar_or("cl_vehicle_spiderbot_cross_size", 1);
+ picsize_y *= cvar_or("cl_vehicle_spiderbot_cross_size", 1);
+ drawpic('0.5 0 0' * (vid_conwidth - picsize_x) + '0 0.5 0' * (vid_conheight - picsize_y), SPIDER_CROSS, picsize, '1 1 1', cvar_or("cl_vehicle_spiderbot_cross_alpha",0.6), DRAWFLAG_NORMAL);
+
+ hudloc_y = 4;
+ hudloc_x = 4;
+
+ picsize = drawgetimagesize(raptor_h) * 0.5;
+ drawpic(hudloc, raptor_h, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+ picsize = drawgetimagesize(spider_a2) * 0.5;
+ drawpic(hudloc + '120 96 0', spider_a2, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+ drawstring(hudloc + '145 19 0', strcat(ftos(rint(hp * 100)), "%"),'15 15 0','0 1 0', 1, DRAWFLAG_NORMAL);
+ drawstring(hudloc + '175 34 0', strcat(ftos(rint(shield * 100)), "%"),'15 15 0','0 0 1', 1, DRAWFLAG_NORMAL);
+ drawstring(hudloc + '136 102 0', strcat(ftos(rint(energy * 100)), "%"),'15 15 0','0.5 0.5 1', 1, DRAWFLAG_NORMAL);
+
+
+ picsize = drawgetimagesize(spider_a1) * 0.85;
+ if(reload == 1)
+ {
+ drawpic(hudloc + '132 54 0', spider_a1, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+ drawstring(hudloc + '179 69 0', strcat(ftos(rint(reload * 100)), "%"),'14 14 0','0 1 0', 0.5, DRAWFLAG_NORMAL);
+ }
+ else
+ {
+ drawpic(hudloc + '132 54 0', spider_a1, picsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+ drawstring(hudloc + '179 69 0', strcat(ftos(rint(reload * 100)), "%"),'14 14 0','0 0 1', 1, DRAWFLAG_NORMAL);
+ }
+
+ picsize = drawgetimagesize(raptor_b) * 0.5;
+ hudloc_y = 10.5;
+ hudloc_x = 10.5;
+
+ drawpic(hudloc, raptor_s, picsize, '1 1 1', shield, DRAWFLAG_NORMAL);
+ drawpic(hudloc, raptor_b, picsize, '0 1 0' * hp + '1 0 0' * (1 - hp), 1, DRAWFLAG_NORMAL);
+ drawpic(hudloc, raptor_g1, picsize, '1 1 1' * energy + '1 0 0' * (1 - energy), 1, DRAWFLAG_NORMAL);
+ drawpic(hudloc, raptor_g2, picsize, '1 1 1' * reload + '1 0 0' * (1 - reload), 1, DRAWFLAG_NORMAL);
+
+
+ if (sb_showscores)
+ {
+ Sbar_DrawScoreboard();
+ Sbar_DrawCenterPrint();
+ }
+
+}
+
#define waki_h "gfx/vehicles/hud_bg.tga"
#define waki_b "gfx/vehicles/waki.tga"
#define waki_e "gfx/vehicles/waki_e.tga"
float log(float f) = #532;
void(entity e, entity ignore) tracetoss = #64;
+
+float(entity e, float ch) getsoundtime = #533; // (DP_SND_GETSOUNDTIME)
+
+#define PARTICLES_USEALPHA 1
+float particles_alphamin, particles_alphamax;
+#define PARTICLES_USECOLOR 2
+vector particles_colormin, particles_colormax;
+void(float effectindex, entity own, vector org_from, vector org_to, vector dir_from, vector dir_to, float countmultiplier, float flags) boxparticles = #502;
if(!issilent)
sound(self, CHAN_PROJECTILE, "weapons/hookbomb_impact.wav", VOL_BASE, ATTN_NORM);
break;
+ case WEP_SEEKER:
+ org2 = org + backoff * 6;
+ if(secondary)
+ {
+ pointparticles(particleeffectnum("flac_explode"), org2, '0 0 0', 1);
+ if(!issilent)
+ {
+ if (r<0.15)
+ sound(self, CHAN_PROJECTILE, "weapons/flacexp1.wav", 1, ATTN_NORM);
+ else if (r<0.7)
+ sound(self, CHAN_PROJECTILE, "weapons/flacexp2.wav", 1, ATTN_NORM);
+ else
+ sound(self, CHAN_PROJECTILE, "weapons/flacexp3.wav", 1, ATTN_NORM);
+ }
+ }
+ else
+ {
+ if(bounce)
+ {
+ pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1);
+ if(!issilent)
+ {
+ if (r<0.15)
+ sound(self, CHAN_PROJECTILE, "weapons/tagexp1.wav", 1, ATTN_NORM);
+ else if (r<0.7)
+ sound(self, CHAN_PROJECTILE, "weapons/tagexp2.wav", 1, ATTN_NORM);
+ else
+ sound(self, CHAN_PROJECTILE, "weapons/tagexp3.wav", 1, ATTN_NORM);
+ }
+ }
+ else if(headshot)
+ {
+ if(!issilent)
+ sound(self, CHAN_PROJECTILE, "weapons/tag_impact.wav", 1, ATTN_NORM);
+ }
+ else
+ {
+ pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1);
+ if(!issilent)
+ {
+ if (r<0.15)
+ sound(self, CHAN_PROJECTILE, "weapons/seekerexp1.wav", 1, ATTN_NORM);
+ else if (r<0.7)
+ sound(self, CHAN_PROJECTILE, "weapons/seekerexp2.wav", 1, ATTN_NORM);
+ else
+ sound(self, CHAN_PROJECTILE, "weapons/seekerexp3.wav", 1, ATTN_NORM);
+ }
+ }
+ }
+ break;
case WEP_HLAC:
org2 = org + backoff * 6;
pointparticles(particleeffectnum("laser_impact"), org2, backoff * 1000, 1);
break;
case WEP_FIREBALL:
if(secondary)
+ {
+ // firemine goes out silently
+ }
+ else
{
org2 = org + backoff * 16;
pointparticles(particleeffectnum("fireball_explode"), org2, '0 0 0', 1);
if(!issilent)
sound(self, CHAN_PROJECTILE, "weapons/fireball_impact2.wav", VOL_BASE, ATTN_NORM * 0.25); // long range boom
}
- else
- {
- // firemine goes out silently
- }
break;
default:
dprint("Unhandled damage of weapon ", ftos(hitwep), "\n");
precache_sound("weapons/crylink_impact.wav");
precache_sound("weapons/electro_impact.wav");
precache_sound("weapons/electro_impact_combo.wav");
+ precache_sound("weapons/flacexp1.wav");
+ precache_sound("weapons/flacexp2.wav");
+ precache_sound("weapons/flacexp3.wav");
precache_sound("weapons/grenade_impact.wav");
precache_sound("weapons/hagexp1.wav");
precache_sound("weapons/hagexp2.wav");
precache_sound("weapons/rocket_impact.wav");
precache_sound("weapons/fireball_impact.wav");
precache_sound("weapons/fireball_impact2.wav");
+ precache_sound("weapons/seekerexp1.wav");
+ precache_sound("weapons/seekerexp2.wav");
+ precache_sound("weapons/seekerexp3.wav");
+ precache_sound("weapons/tagexp1.wav");
+ precache_sound("weapons/tagexp2.wav");
+ precache_sound("weapons/tagexp3.wav");
+ precache_sound("weapons/tag_impact.wav");
}
if(type & 0x80)
{
- if(cvar("cl_gentle") > 1)
+ if(cvar("cl_gentle") == 2)
gentle_prefix = "";
- else
+ else if(cvar("cl_gentle") == 3)
+ gentle_prefix = "happy_";
+ else if(cvar("cl_gentle"))
gentle_prefix = "morphed_";
}
else if(cvar("cl_particlegibs"))
// direction is perpendicular to the view normal, and perpendicular to the axis
thickdir = normalize(cross(axis, view_origin - from));
+/*
+ print("from ", vtos(from), "\n");
+ print("to ", vtos(to), "\n");
+ print("org ", vtos(view_origin), "\n");
+ print("dir ", vtos(thickdir), "\n");
+*/
+
A = from - thickdir * (thickness / 2);
B = from + thickdir * (thickness / 2);
C = to + thickdir * (thickness / 2);
--- /dev/null
+/*
+==================
+Misc HUD functions
+==================
+*/
+
+// a border picture is a texture containing nine parts:
+// 1/4 width: left part
+// 1/2 width: middle part (stretched)
+// 1/4 width: right part
+// divided into
+// 1/4 height: top part
+// 1/2 height: middle part (stretched)
+// 1/4 height: bottom part
+void draw_BorderPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha, vector theBorderSize)
+{
+ vector dX, dY;
+ vector width, height;
+ vector bW, bH;
+ //pic = draw_UseSkinFor(pic);
+ width = eX * theSize_x;
+ height = eY * theSize_y;
+ if(theSize_x <= theBorderSize_x * 2)
+ {
+ // not wide enough... draw just left and right then
+ bW = eX * (0.25 * theSize_x / (theBorderSize_x * 2));
+ if(theSize_y <= theBorderSize_y * 2)
+ {
+ // not high enough... draw just corners
+ bH = eY * (0.25 * theSize_y / (theBorderSize_y * 2));
+ drawsubpic(theOrigin, width * 0.5 + height * 0.5, pic, '0 0 0', bW + bH, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + width * 0.5, width * 0.5 + height * 0.5, pic, eX - bW, bW + bH, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + height * 0.5, width * 0.5 + height * 0.5, pic, eY - bH, bW + bH, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + theSize * 0.5, width * 0.5 + height * 0.5, pic, eX + eY - bW - bH, bW + bH, theColor, theAlpha, 0);
+ }
+ else
+ {
+ dY = theBorderSize_x * eY;
+ drawsubpic(theOrigin, width * 0.5 + dY, pic, '0 0 0', '0 0.25 0' + bW, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + width * 0.5, width * 0.5 + dY, pic, '0 0 0' + eX - bW, '0 0.25 0' + bW, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + dY, width * 0.5 + height - 2 * dY, pic, '0 0.25 0', '0 0.5 0' + bW, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + width * 0.5 + dY, width * 0.5 + height - 2 * dY, pic, '0 0.25 0' + eX - bW, '0 0.5 0' + bW, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + height - dY, width * 0.5 + dY, pic, '0 0.75 0', '0 0.25 0' + bW, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + width * 0.5 + height - dY, width * 0.5 + dY, pic, '0 0.75 0' + eX - bW, '0 0.25 0' + bW, theColor, theAlpha, 0);
+ }
+ }
+ else
+ {
+ if(theSize_y <= theBorderSize_y * 2)
+ {
+ // not high enough... draw just top and bottom then
+ bH = eY * (0.25 * theSize_y / (theBorderSize_y * 2));
+ dX = theBorderSize_x * eX;
+ drawsubpic(theOrigin, dX + height * 0.5, pic, '0 0 0', '0.25 0 0' + bH, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + dX, width - 2 * dX + height * 0.5, pic, '0.25 0 0', '0.5 0 0' + bH, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + width - dX, dX + height * 0.5, pic, '0.75 0 0', '0.25 0 0' + bH, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + height * 0.5, dX + height * 0.5, pic, '0 0 0' + eY - bH, '0.25 0 0' + bH, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + dX + height * 0.5, width - 2 * dX + height * 0.5, pic, '0.25 0 0' + eY - bH, '0.5 0 0' + bH, theColor, theAlpha, 0);
+ drawsubpic(theOrigin + width - dX + height * 0.5, dX + height * 0.5, pic, '0.75 0 0' + eY - bH, '0.25 0 0' + bH, theColor, theAlpha, 0);
+ }
+ else
+ {
+ dX = theBorderSize_x * eX;
+ dY = theBorderSize_x * eY;
+ drawsubpic(theOrigin, dX + dY, pic, '0 0 0', '0.25 0.25 0', theColor, theAlpha, 0);
+ drawsubpic(theOrigin + dX, width - 2 * dX + dY, pic, '0.25 0 0', '0.5 0.25 0', theColor, theAlpha, 0);
+ drawsubpic(theOrigin + width - dX, dX + dY, pic, '0.75 0 0', '0.25 0.25 0', theColor, theAlpha, 0);
+ drawsubpic(theOrigin + dY, dX + height - 2 * dY, pic, '0 0.25 0', '0.25 0.5 0', theColor, theAlpha, 0);
+ drawsubpic(theOrigin + dY + dX, width - 2 * dX + height - 2 * dY, pic, '0.25 0.25 0', '0.5 0.5 0', theColor, theAlpha, 0);
+ drawsubpic(theOrigin + dY + width - dX, dX + height - 2 * dY, pic, '0.75 0.25 0', '0.25 0.5 0', theColor, theAlpha, 0);
+ drawsubpic(theOrigin + height - dY, dX + dY, pic, '0 0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
+ drawsubpic(theOrigin + height - dY + dX, width - 2 * dX + dY, pic, '0.25 0.75 0', '0.5 0.25 0', theColor, theAlpha, 0);
+ drawsubpic(theOrigin + height - dY + width - dX, dX + dY, pic, '0.75 0.75 0', '0.25 0.25 0', theColor, theAlpha, 0);
+ }
+ }
+}
+
+// return HUD background color
+vector HUD_GetBgColor()
+{
+ vector color;
+ if (teamplay)
+ GetTeamRGB(myteam) * hud_color_bg_team;
+ else {
+ // allow custom HUD colors in non-teamgames
+ color_x = cvar("hud_color_bg_r");
+ color_y = cvar("hud_color_bg_g");
+ color_z = cvar("hud_color_bg_b");
+ }
+ return color;
+}
+
+// return accuracy text color
+vector HUD_AccuracyColor(float accuracy)
+{
+ vector rgb;
+ float yellow_accuracy = cvar("hud_accuracy_yellow"); // value at which this function returns yellow
+ if(accuracy >= 100) {
+ rgb_x = 0;
+ rgb_y = 1;
+ }
+ else if(accuracy > yellow_accuracy) {
+ rgb_x = 1 - (accuracy-yellow_accuracy)/(100-yellow_accuracy); // red value between 1 -> 0
+ rgb_y = 1;
+ }
+ else {
+ rgb_x = 1;
+ rgb_y = accuracy/yellow_accuracy; // green value between 0 -> 1
+ }
+ rgb_z = 0;
+ return rgb;
+}
+
+// draw number in the XSCALE font
+void HUD_DrawXNum (vector pos, float num, float digits, float showsign, float lettersize, vector rgb, float highlighted, float stroke, float alpha, float dflags)
+{
+ float l, i;
+ string str, tmp, l_length;
+ float minus, plus;
+ vector vsize, num_color;
+
+ vsize_x = vsize_y = lettersize;
+ vsize_z = 0;
+
+ // showsign 1: always prefix with minus sign (useful in race distribution display)
+ // showsign 2: always prefix with plus sign (useful in race distribution display)
+ // showsign 3: prefix with minus sign if negative, plus sign if positive (useful in score distribution display)
+
+ if((showsign == 2 && num >= 0) || (num > 0 && showsign == 3))
+ {
+ plus = true;
+ pos_x -= lettersize;
+ } else
+ plus = false;
+
+ if(num < 0 || (num < 0 && showsign == 3) || (showsign == 1 && num <= 0))
+ {
+ minus = true;
+ num = -num;
+ pos_x -= lettersize;
+ } else
+ minus = false;
+
+ if(digits < 0)
+ {
+ tmp = ftos(num);
+ digits = -digits;
+ str = strcat(substring("0000000000", 0, digits - strlen(tmp)), tmp);
+ } else
+ str = ftos(num);
+
+ l = strlen(str);
+ l_length = ftos(l);
+
+ if(l > digits)
+ {
+ str = substring(str, l-digits, 999);
+ l = strlen(str);
+ } else if(l < digits)
+ pos_x += (digits-l) * lettersize;
+
+ if (highlighted == 1) {
+ vector hl_size;
+ hl_size_x = vsize_x * l + vsize_x * 0.2;
+ hl_size_y = vsize_y * 1.1;
+ hl_size_z = 0;
+ if(minus)
+ hl_size_x = hl_size_x + vsize_x;
+
+ vector hl_pos;
+ hl_pos_x = pos_x - lettersize/10;
+ hl_pos_y = pos_y - lettersize/20;
+ hl_pos_z = 0;
+
+ drawpic(hl_pos, strcat("gfx/hud/sb_highlight_", l_length), hl_size, '1 1 1', alpha, dflags);
+ }
+
+ if (stroke == 1)
+ num_color = '1 1 1';
+ else
+ num_color = rgb;
+
+ if(minus)
+ {
+ if (stroke == 1)
+ drawpic(pos, "gfx/hud/num_minus_stroke", vsize, rgb, alpha, dflags);
+ drawpic(pos, "gfx/hud/num_minus", vsize, num_color, alpha, dflags);
+ pos_x += lettersize;
+ } else if(plus)
+ {
+ if (stroke == 1)
+ drawpic(pos, "gfx/hud/num_plus_stroke", vsize, rgb, alpha, dflags);
+ drawpic(pos, "gfx/hud/num_plus", vsize, num_color, alpha, dflags);
+ pos_x += lettersize;
+ }
+
+ for(i = 0; i < l; ++i)
+ {
+ tmp = substring(str, i, 1);
+ if (stroke == 1)
+ drawpic(pos, strcat("gfx/hud/num_", tmp, "_stroke"), vsize, rgb, alpha, dflags);
+ drawpic(pos, strcat("gfx/hud/num_", tmp), vsize, num_color, alpha, dflags);
+ pos_x += lettersize;
+ }
+}
+
+// color the number differently based on how big it is (used in the health/armor panel)
+void HUD_DrawXNum_Colored (vector pos, float x, float digits, float lettersize, float alpha)
+{
+ vector color;
+ if(x > 200) {
+ color_x = 0;
+ color_y = 1;
+ color_z = 0;
+ }
+ else if(x > 150) {
+ color_x = 0.4 - (x-150)*0.02 * 0.4; //red value between 0.4 -> 0
+ color_y = 0.9 + (x-150)*0.02 * 0.1; // green value between 0.9 -> 1
+ color_z = 0;
+ }
+ else if(x > 100) {
+ color_x = 1 - (x-100)*0.02 * 0.6; //red value between 1 -> 0.4
+ color_y = 1 - (x-100)*0.02 * 0.1; // green value between 1 -> 0.9
+ color_z = 1 - (x-100)*0.02; // blue value between 1 -> 0
+ }
+ else if(x > 50) {
+ color_x = 1;
+ color_y = 1;
+ color_z = 0.2 + (x-50)*0.02 * 0.8; // blue value between 0.2 -> 1
+ }
+ else if(x > 20) {
+ color_x = 1;
+ color_y = (x-20)*90/27/100; // green value between 0 -> 1
+ color_z = (x-20)*90/27/100 * 0.2; // blue value between 0 -> 0.2
+ }
+ else {
+ color_x = 1;
+ color_y = 0;
+ color_z = 0;
+ }
+ HUD_DrawXNum(pos, x, digits, 0, lettersize, color, 0, 0, alpha, DRAWFLAG_NORMAL);
+}
+
+float stringwidth_colors(string s, vector theSize)
+{
+ return stringwidth(s, TRUE, theSize);
+}
+
+float stringwidth_nocolors(string s, vector theSize)
+{
+ return stringwidth(s, FALSE, theSize);
+}
+
+#define CENTERPRINT_MAX_LINES 30
+string centerprint_messages[CENTERPRINT_MAX_LINES];
+float centerprint_width[CENTERPRINT_MAX_LINES];
+vector centerprint_start;
+float centerprint_expire;
+float centerprint_num;
+float centerprint_offset_hint;
+vector centerprint_fontsize;
+
+void centerprint(string strMessage)
+{
+ float i, j, n, hcount;
+ string s;
+
+ centerprint_fontsize = HUD_GetFontsize("scr_centersize");
+
+ centerprint_expire = min(centerprint_expire, time); // if any of the returns happens, this message will fade out
+
+ if(cvar("scr_centertime") <= 0)
+ return;
+
+ if(strMessage == "")
+ return;
+
+ // strip trailing newlines
+ j = strlen(strMessage) - 1;
+ while(substring(strMessage, j, 1) == "\n" && j >= 0)
+ j = j - 1;
+ strMessage = substring(strMessage, 0, j + 1);
+
+ if(strMessage == "")
+ return;
+
+ // strip leading newlines and remember them, they are a hint that the message should be lower on the screen
+ j = 0;
+ while(substring(strMessage, j, 1) == "\n" && j < strlen(strMessage))
+ j = j + 1;
+ strMessage = substring(strMessage, j, strlen(strMessage) - j);
+ centerprint_offset_hint = j;
+
+ if(strMessage == "")
+ return;
+
+ // if we get here, we have a message. Initialize its height.
+ centerprint_num = 0;
+
+ n = tokenizebyseparator(strMessage, "\n");
+ i = hcount = 0;
+ for(j = 0; j < n; ++j)
+ {
+ getWrappedLine_remaining = argv(j);
+ while(getWrappedLine_remaining)
+ {
+ s = getWrappedLine(vid_conwidth * 0.75, centerprint_fontsize, stringwidth_colors);
+ if(centerprint_messages[i])
+ strunzone(centerprint_messages[i]);
+ centerprint_messages[i] = strzone(s);
+ centerprint_width[i] = stringwidth(s, TRUE, centerprint_fontsize);
+ ++i;
+
+ // half height for empty lines looks better
+ if(s == "")
+ hcount += 0.5;
+ else
+ hcount += 1;
+
+ if(i >= CENTERPRINT_MAX_LINES)
+ break;
+ }
+ }
+
+ float h, havail;
+ h = centerprint_fontsize_y*hcount;
+
+ havail = vid_conheight;
+ if(cvar("con_chatpos") < 0)
+ havail -= (-cvar("con_chatpos") + cvar("con_chat")) * cvar("con_chatsize"); // avoid overlapping chat
+ if(havail > vid_conheight - 70)
+ havail = vid_conheight - 70; // avoid overlapping HUD
+
+ centerprint_start_x = 0;
+
+#if 0
+ float forbiddenmin, forbiddenmax, allowedmin, allowedmax, preferred;
+
+ // here, the centerprint would cover the crosshair. REALLY BAD.
+ forbiddenmin = vid_conheight * 0.5 - h - 16;
+ forbiddenmax = vid_conheight * 0.5 + 16;
+
+ allowedmin = scoreboard_bottom;
+ allowedmax = havail - h;
+ preferred = (havail - h)/2;
+
+
+ // possible orderings (total: 4! / 4 = 6)
+ // allowedmin allowedmax forbiddenmin forbiddenmax
+ // forbiddenmin forbiddenmax allowedmin allowedmax
+ if(allowedmax < forbiddenmin || allowedmin > forbiddenmax)
+ {
+ // forbidden doesn't matter in this case
+ centerprint_start_y = bound(allowedmin, preferred, allowedmax);
+ }
+ // allowedmin forbiddenmin allowedmax forbiddenmax
+ else if(allowedmin < forbiddenmin && allowedmax < forbiddenmax)
+ {
+ centerprint_start_y = bound(allowedmin, preferred, forbiddenmin);
+ }
+ // allowedmin forbiddenmin forbiddenmax allowedmax
+ else if(allowedmin < forbiddenmin)
+ {
+ // make sure the forbidden zone is not covered
+ if(preferred > (forbiddenmin + forbiddenmax) * 0.5)
+ centerprint_start_y = bound(allowedmin, preferred, forbiddenmin);
+ else
+ centerprint_start_y = bound(forbiddenmax, preferred, allowedmin);
+ }
+ // forbiddenmin allowedmin allowedmax forbiddenmax
+ else if(allowedmax < forbiddenmax)
+ {
+ // it's better to leave the allowed zone (overlap with scoreboard) than
+ // to cover the forbidden zone (crosshair)
+ if(preferred > (forbiddenmin + forbiddenmax) * 0.5)
+ centerprint_start_y = forbiddenmax;
+ else
+ centerprint_start_y = forbiddenmin;
+ }
+ // forbiddenmin allowedmin forbiddenmax allowedmax
+ else
+ {
+ centerprint_start_y = bound(forbiddenmax, preferred, allowedmax);
+ }
+#else
+ centerprint_start_y =
+ min(
+ max(
+ max(scoreboard_bottom, vid_conheight * 0.5 + 16),
+ (havail - h)/2
+ ),
+ havail - h
+ );
+#endif
+
+ centerprint_num = i;
+ centerprint_expire = time + cvar("scr_centertime");
+}
+
+void HUD_DrawCenterPrint (void)
+{
+ float i;
+ vector pos;
+ string ts;
+ float a;
+
+ //if(time > centerprint_expire)
+ // return;
+
+ //a = bound(0, 1 - 2 * (time - centerprint_expire), 1);
+ a = bound(0, 1 - 4 * (time - centerprint_expire), 1);
+ //sz = 1.2 / (a + 0.2);
+
+ if(a <= 0)
+ return;
+
+ pos = centerprint_start;
+ for (i=0; i<centerprint_num; i = i + 1)
+ {
+ pos_x = (vid_conwidth - centerprint_width[i]) * 0.5;
+ ts = centerprint_messages[i];
+ if (ts != "")
+ {
+ dummyfunction(0, 0, 0, 0, 0, 0, 0, 0); // work around DP bug (set OFS_PARAM5 to 0)
+ drawcolorcodedstring(pos, ts, centerprint_fontsize, a, DRAWFLAG_NORMAL);
+ // - '0 0.5 0' * (sz - 1) * centerprint_fontsize_x - '0.5 0 0' * (sz - 1) * centerprint_width[i] * centerprint_fontsize_y, centerprint_fontsize * sz
+ pos_y = pos_y + centerprint_fontsize_y;
+ }
+ else
+ // half height for empty lines looks better
+ pos_y = pos_y + centerprint_fontsize_y * 0.5;
+ }
+}
+
+void drawstringright(vector position, string text, vector scale, vector rgb, float alpha, float flag)
+{
+ position_x -= 2 / 3 * strlen(text) * scale_x;
+ drawstring(position, text, scale, rgb, alpha, flag);
+}
+
+void drawstringcenter(vector position, string text, vector scale, vector rgb, float alpha, float flag)
+{
+ position_x = 0.5 * (vid_conwidth - 0.6025 * strlen(text) * scale_x);
+ drawstring(position, text, scale, rgb, alpha, 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 strcat(ftos(pos), "th");
+}
+
+// return the string of the onscreen race timer
+string MakeRaceString(float cp, float mytime, float histime, float lapdelta, string hisname)
+{
+ string col;
+ string timestr;
+ string cpname;
+ string lapstr;
+ lapstr = "";
+
+ if(histime == 0) // goal hit
+ {
+ if(mytime > 0)
+ {
+ timestr = strcat("+", ftos_decimals(+mytime, TIME_DECIMALS));
+ col = "^1";
+ }
+ else if(mytime == 0)
+ {
+ timestr = "+0.0";
+ col = "^3";
+ }
+ else
+ {
+ timestr = strcat("-", ftos_decimals(-mytime, TIME_DECIMALS));
+ col = "^2";
+ }
+
+ if(lapdelta > 0)
+ {
+ lapstr = strcat(" (-", ftos(lapdelta), "L)");
+ col = "^2";
+ }
+ else if(lapdelta < 0)
+ {
+ lapstr = strcat(" (+", ftos(-lapdelta), "L)");
+ col = "^1";
+ }
+ }
+ else if(histime > 0) // anticipation
+ {
+ if(mytime >= histime)
+ timestr = strcat("+", ftos_decimals(mytime - histime, TIME_DECIMALS));
+ else
+ timestr = TIME_ENCODED_TOSTRING(TIME_ENCODE(histime));
+ col = "^3";
+ }
+ else
+ col = "^7";
+
+ if(cp == 254)
+ cpname = "Start line";
+ else if(cp == 255)
+ cpname = "Finish line";
+ else if(cp)
+ cpname = strcat("Intermediate ", ftos(cp));
+ else
+ cpname = "Finish line";
+
+ if(histime < 0)
+ return strcat(col, cpname);
+ else if(hisname == "")
+ return strcat(col, cpname, " (", timestr, ")");
+ else
+ return strcat(col, cpname, " (", timestr, " ", strcat(hisname, col, lapstr), ")");
+}
+
+// Check if the given name already exist in race rankings? In that case, where? (otherwise return 0)
+float race_CheckName(string net_name) {
+ float i;
+ for (i=RANKINGS_CNT-1;i>=0;--i)
+ if(grecordholder[i] == net_name)
+ return i+1;
+ return 0;
+}
+
+/*
+==================
+HUD panels
+==================
+*/
+
+string HUD_Panel_GetName(float id)
+{
+ switch(id) {
+ case 0: return "weaponicons"; break;
+ case 1: return "inventory"; break;
+ case 2: return "powerups"; break;
+ case 3: return "healtharmor"; break;
+ case 4: return "notify"; break;
+ case 5: return "timer"; break;
+ case 6: return "radar"; break;
+ case 7: return "score"; break;
+ case 8: return "racetimer"; break;
+ case 9: return "vote"; break;
+ case 10: return "pressedkeys"; break;
+ default: return "";
+ }
+}
+
+vector HUD_Panel_CheckLimitSize(float id, vector mySize)
+{
+ switch(id) {
+ case 0:
+ mySize_x = max(mySize_y * (1/10), mySize_x); // at least 1/10 * height
+ mySize_y = max(mySize_x * (1/26), mySize_y); // at least 1/26 * width
+ break;
+ case 1:
+ mySize_x = max(mySize_y * 0.7, mySize_x); // at least 0.7 * height
+ break;
+ case 3:
+ mySize_x = max(mySize_y * 2, mySize_x); // at least 2 * height
+ break;
+ case 5:
+ mySize_x = max(mySize_y * 2, mySize_x); // at least 2 * height
+ break;
+ case 9:
+ mySize_y = (1/4) * mySize_x; // 1/4 * width
+ break;
+ case 10:
+ mySize_y = 0.5898 * mySize_x; // 0.5898 * width, reason: bg has weird dimensions...
+ break;
+ }
+ return mySize;
+}
+
+// return active status of panel
+float HUD_Panel_CheckActive(float id)
+{
+ if (cvar_or(strcat("hud_", HUD_Panel_GetName(id)), 1))
+ return 1;
+ return 0;
+}
+
+// return size of given panel
+vector HUD_Panel_GetSize(float id)
+{
+ return stov(cvar_string(strcat("hud_", HUD_Panel_GetName(id), "_size")));
+}
+
+// return pos of given panel
+vector HUD_Panel_GetPos(float id)
+{
+ vector pos;
+ pos = stov(cvar_string(strcat("hud_", HUD_Panel_GetName(id), "_pos")));
+
+ if (pos_x < 0)
+ pos_x = vid_conwidth + pos_x;
+ if (pos_y < 0)
+ pos_y = vid_conheight + pos_y;
+ return pos;
+}
+
+float HUD_Panel_GetMarigin(float id)
+{
+ return bound(1, MARIGIN_MULTIPLIER * cvar_or(strcat("hud_", HUD_Panel_GetName(id), "_marigin"), 30), 200);
+}
+
+vector HUD_Panel_GetColor(float id)
+{
+ if(cvar_string(strcat("hud_", HUD_Panel_GetName(id), "_color")) != "")
+ return stov(cvar_string(strcat("hud_", HUD_Panel_GetName(id), "_color")));
+ else
+ return stov(cvar_string("hud_color"));
+}
+
+float HUD_Panel_GetBgActive(float id)
+{
+ if(cvar("_hud_configure"))
+ return 1;
+
+ return cvar_or(strcat("hud_", HUD_Panel_GetName(id), "_bg"), 1);
+}
+
+vector HUD_Panel_GetProgressBarColor(string item)
+{
+ return stov(cvar_string(strcat("hud_progreshud_", item, "_color")));
+}
+
+float resizeCorner; // 1 = topleft, 2 = topright, 3 = bottomleft, 4 = bottomright
+// check if resize will result in panel being moved into another panel. If so, return snapped vector, otherwise return the given vector
+vector HUD_Panel_CheckResize(float id, vector myPos, vector mySize)
+{
+ float i;
+
+ vector myTarget;
+ myTarget = mySize;
+
+ vector targPos;
+ vector targSize;
+ vector myCenter;
+ vector targCenter;
+
+ for (i = 0; i < panel_cnt; ++i) {
+ if(i == id || !HUD_Panel_CheckActive(i))
+ continue;
+
+ targPos = HUD_Panel_GetPos(i);
+ targSize = HUD_Panel_GetSize(i);
+
+ targPos = HUD_Panel_GetPos(i) - '1 1 0' * HUD_Panel_GetMarigin(id);
+ targSize = HUD_Panel_GetSize(i) + '2 2 0' * HUD_Panel_GetMarigin(id);
+
+ if(myPos_y + mySize_y < targPos_y)
+ continue;
+ if(myPos_y > targPos_y + targSize_y)
+ continue;
+
+ if(myPos_x + mySize_x < targPos_x)
+ continue;
+ if(myPos_x > targPos_x + targSize_x)
+ continue;
+
+ // OK, there IS a collision.
+
+ myCenter_x = myPos_x + 0.5 * mySize_x;
+ myCenter_y = myPos_y + 0.5 * mySize_y;
+
+ targCenter_x = targPos_x + 0.5 * targSize_x;
+ targCenter_y = targPos_y + 0.5 * targSize_y;
+
+ float k, y;
+ if(myCenter_x < targCenter_x && myCenter_y < targCenter_y && resizeCorner != 1) // top left (of target panel)
+ {
+ if(myPos_x + mySize_x - targPos_x < myPos_y + mySize_y - targPos_y) // push it to the side
+ myTarget_x = targPos_x - myPos_x;
+ else // push it upwards
+ myTarget_y = targPos_y - myPos_y;
+ }
+ else if(myCenter_x > targCenter_x && myCenter_y < targCenter_y && resizeCorner != 2) // top right
+ {
+ if(targPos_x + targSize_x - myPos_x < myPos_y + mySize_y - targPos_y) // push it to the side
+ myTarget_x = targPos_x + targSize_x;
+ else // push it upwards
+ myTarget_y = targPos_y - myPos_y;
+ }
+ else if(myCenter_x < targCenter_x && myCenter_y > targCenter_y) // bottom left
+ {
+ if(myPos_x + mySize_x - targPos_x < targPos_y + targSize_y - myPos_y) // push it to the side
+ myTarget_x = targPos_x - myPos_x;
+ else // push it downwards
+ myTarget_y = targPos_y + targSize_y;
+ }
+ else if(myCenter_x > targCenter_x && myCenter_y > targCenter_y) // bottom right
+ {
+ if(targPos_x + targSize_x - myPos_x < targPos_y + targSize_y - myPos_y) // push it to the side
+ myTarget_x = targPos_x + targSize_x;
+ else // push it downwards
+ myTarget_y = targPos_y + targSize_y;
+ }
+ }
+
+ return myTarget;
+}
+
+// TODO: checkResize
+float HUD_Panel_SetSize(float id, vector mySize)
+{
+ float didntresize;
+
+ vector oldSize;
+ oldSize = stov(cvar_string(strcat("hud_", HUD_Panel_GetName(id), "_size")));
+
+ vector myPos;
+ myPos = HUD_Panel_GetPos(id);
+
+ // check for collisions
+ mySize = HUD_Panel_CheckResize(id, HUD_Panel_GetPos(id), mySize);
+
+ mySize_x = bound(0.025 * vid_conwidth, mySize_x, vid_conwidth - myPos_x);
+ mySize_y = bound(0.025 * vid_conheight, mySize_y, vid_conheight - myPos_y);
+
+ // cap against panel's own limits
+ mySize = HUD_Panel_CheckLimitSize(id, mySize);
+
+ //mySize_x = bound(0.025 * vid_conwidth, mySize_x, vid_conwidth);
+ //mySize_y = bound(0.025 * vid_conheight, mySize_y, vid_conheight);
+
+ // TODO: is this needed?
+ // this is to check if (and how) SetPos should be called
+ if(mySize_x == oldSize_x && mySize_y == oldSize_y)
+ didntresize = 3; // didnt resize either
+ else if(mySize_x == oldSize_x && mySize_y != oldSize_y)
+ didntresize = 2; // resized Y
+ else if(mySize_y == oldSize_y && mySize_x != oldSize_x)
+ didntresize = 1; // resized X
+
+ string s;
+ s = strcat(ftos(mySize_x), " ", ftos(mySize_y));
+ cvar_set(strcat("hud_", HUD_Panel_GetName(id), "_size"), s);
+ return didntresize;
+}
+
+// check if move will result in panel being moved into another panel. If so, return snapped vector, otherwise return the given vector
+vector HUD_Panel_CheckMove(float id, vector myPos, vector mySize)
+{
+ float i;
+
+ vector myTarget;
+ myTarget = myPos;
+
+ vector targPos;
+ vector targSize;
+ vector myCenter;
+ vector targCenter;
+
+ for (i = 0; i < panel_cnt; ++i) {
+ if(i == id || !HUD_Panel_CheckActive(i))
+ continue;
+
+ targPos = HUD_Panel_GetPos(i) - '1 1 0' * HUD_Panel_GetMarigin(id);
+ targSize = HUD_Panel_GetSize(i) + '2 2 0' * HUD_Panel_GetMarigin(id);
+
+ if(myPos_y + mySize_y < targPos_y)
+ continue;
+ if(myPos_y > targPos_y + targSize_y)
+ continue;
+
+ if(myPos_x + mySize_x < targPos_x)
+ continue;
+ if(myPos_x > targPos_x + targSize_x)
+ continue;
+
+ // OK, there IS a collision.
+
+ myCenter_x = myPos_x + 0.5 * mySize_x;
+ myCenter_y = myPos_y + 0.5 * mySize_y;
+
+ targCenter_x = targPos_x + 0.5 * targSize_x;
+ targCenter_y = targPos_y + 0.5 * targSize_y;
+
+ float k, y;
+ if(myCenter_x < targCenter_x && myCenter_y < targCenter_y) // top left (of the target panel)
+ {
+ if(myPos_x + mySize_x - targPos_x < myPos_y + mySize_y - targPos_y) // push it to the side
+ myTarget_x = targPos_x - mySize_x;
+ else // push it upwards
+ myTarget_y = targPos_y - mySize_y;
+ }
+ else if(myCenter_x > targCenter_x && myCenter_y < targCenter_y) // top right
+ {
+ if(targPos_x + targSize_x - myPos_x < myPos_y + mySize_y - targPos_y) // push it to the side
+ myTarget_x = targPos_x + targSize_x;
+ else // push it upwards
+ myTarget_y = targPos_y - mySize_y;
+ }
+ else if(myCenter_x < targCenter_x && myCenter_y > targCenter_y) // bottom left
+ {
+ if(myPos_x + mySize_x - targPos_x < targPos_y + targSize_y - myPos_y) // push it to the side
+ myTarget_x = targPos_x - mySize_x;
+ else // push it downwards
+ myTarget_y = targPos_y + targSize_y;
+ }
+ else if(myCenter_x > targCenter_x && myCenter_y > targCenter_y) // bottom right
+ {
+ if(targPos_x + targSize_x - myPos_x < targPos_y + targSize_y - myPos_y) // push it to the side
+ myTarget_x = targPos_x + targSize_x;
+ else // push it downwards
+ myTarget_y = targPos_y + targSize_y;
+ }
+ }
+
+ return myTarget;
+}
+
+void HUD_Panel_SetPos(float id, vector pos, float didntresize)
+{
+ vector oldPos;
+ oldPos = HUD_Panel_GetPos(id);
+ if(didntresize == 2)
+ pos_x = oldPos_x;
+ else if(didntresize == 1)
+ pos_y = oldPos_y;
+ else if(didntresize == 3)
+ return;
+
+ vector mySize;
+ mySize = HUD_Panel_GetSize(id);
+
+ pos = HUD_Panel_CheckMove(id, pos, mySize);
+
+ pos_x = bound(0, pos_x, vid_conwidth - mySize_x);
+ pos_y = bound(0, pos_y, vid_conheight - mySize_y);
+
+ if (pos_x + 0.5 * mySize_x > 0.5 * vid_conwidth)
+ pos_x = pos_x - vid_conwidth;
+ if (pos_y + 0.5 * mySize_y > 0.5 * vid_conheight)
+ pos_y = pos_y - vid_conheight;
+
+ string s;
+ s = strcat(ftos(pos_x), " ", ftos(pos_y));
+
+ cvar_set(strcat("hud_", HUD_Panel_GetName(id), "_pos"), s);
+}
+
+float mouseClicked;
+float prevMouseClicked; // previous state
+float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary)
+{
+ prevMouseClicked = mouseClicked;
+ if(nPrimary == K_MOUSE1)
+ {
+ if(bInputType == 0) { // key pressed
+ mouseClicked = 1;
+ return true;
+ }
+ if(bInputType == 1) {// key released
+ mouseClicked = 0;
+ return true;
+ }
+ }
+ return false;
+}
+
+vector mousepos, mouseprevpos;
+vector panel_click_distance; // mouse cursor distance from the top left corner of the panel (saved only upon a click)
+vector panel_click_pos; // panel pos (saved only upon a click)
+vector panel_click_size; // panel size (saved only upon a click)
+float highlightedPanel;
+float highlightedAction; // 0 = nothing, 1 = move, 2 = resize
+void HUD_Panel_Mouse()
+{
+ if(mouseClicked == 0) {
+ highlightedPanel = -1;
+ highlightedAction = 0;
+ }
+
+ mousepos = mousepos + getmousepos();
+
+ mousepos_x = bound(0, mousepos_x, vid_conwidth);
+ mousepos_y = bound(0, mousepos_y, vid_conheight);
+
+ drawpic(mousepos, "gfx/menu/default/cursor.tga", '32 32 0', '1 1 1', 1, hud_alpha_fg);
+
+ if(mouseClicked)
+ {
+ float i, marigin;
+ vector panelPos;
+ vector panelSize;
+
+ for(i = 0; i <= panel_cnt; i++)
+ {
+ panelPos = HUD_Panel_GetPos(i);
+ panelSize = HUD_Panel_GetSize(i);
+ marigin = HUD_Panel_GetMarigin(i);
+ if(prevMouseClicked == 0) {
+ // move
+ if(mousepos_x >= panelPos_x && mousepos_y >= panelPos_y && mousepos_x <= panelPos_x + panelSize_x && mousepos_y <= panelPos_y + panelSize_y)
+ {
+ highlightedPanel = i;
+ highlightedAction = 1;
+ }
+ // resize from topleft border
+ else if(mousepos_x >= panelPos_x - eX * marigin && mousepos_y >= panelPos_y - eX * marigin && mousepos_x <= panelPos_x + 0.5 * panelSize_x && mousepos_y <= panelPos_y + 0.5 * panelSize_y)
+ {
+ highlightedPanel = i;
+ highlightedAction = 2;
+ resizeCorner = 1;
+ }
+ // resize from topright border
+ else if(mousepos_x >= panelPos_x + 0.5 * panelSize_x && mousepos_y >= panelPos_y - eX * marigin && mousepos_x <= panelPos_x + panelSize_x + eX * marigin && mousepos_y <= panelPos_y + 0.5 * panelSize_y)
+ {
+ highlightedPanel = i;
+ highlightedAction = 2;
+ resizeCorner = 2;
+ }
+ // resize from bottomleft border
+ else if(mousepos_x >= panelPos_x - eX * marigin && mousepos_y >= panelPos_y + 0.5 * panelSize_y && mousepos_x <= panelPos_x + 0.5 * panelSize_x && mousepos_y <= panelPos_y + panelSize_y + eY * marigin)
+ {
+ highlightedPanel = i;
+ highlightedAction = 2;
+ resizeCorner = 3;
+ }
+ // resize from bottomright border
+ else if(mousepos_x >= panelPos_x + 0.5 * panelSize_x && mousepos_y >= panelPos_y + 0.5 * panelSize_y && mousepos_x <= panelPos_x + panelSize_x + eX * marigin && mousepos_y <= panelPos_y + panelSize_y + eY * marigin)
+ {
+ highlightedPanel = i;
+ highlightedAction = 2;
+ resizeCorner = 4;
+ }
+ }
+
+ if(highlightedPanel == i)
+ {
+ if(prevMouseClicked == 0)
+ {
+ panel_click_distance = mousepos - panelPos;
+ panel_click_pos = panelPos;
+ panel_click_size = panelSize;
+ }
+
+ if(highlightedAction == 1)
+ HUD_Panel_SetPos(i, mousepos - panel_click_distance, 0);
+ else if(highlightedAction == 2)
+ {
+ float didntresize; // panel too big/too small, dont resize (also has to affect moving)
+ if(resizeCorner == 1) {
+ didntresize = HUD_Panel_SetSize(i, panelSize + mouseprevpos - mousepos);
+ HUD_Panel_SetPos(i, mousepos - panel_click_distance, didntresize);
+ }
+ if(resizeCorner == 2) {
+ didntresize = HUD_Panel_SetSize(i, eY * panel_click_size_y + eX * (mousepos_x - panelPos_x - (panel_click_distance_x - panel_click_size_x))
+ + eY * (panel_click_distance_y + (panel_click_pos_y - mousepos_y)));
+ HUD_Panel_SetPos(i, eX * panelPos_x + eY * (mousepos_y - panel_click_distance_y), didntresize);
+ }
+ if(resizeCorner == 3) {
+ didntresize = HUD_Panel_SetSize(i, panelSize + eX * (mouseprevpos_x - mousepos_x) + eY * (mousepos_y - mouseprevpos_y));
+ HUD_Panel_SetPos(i, eX * (mousepos_x - panel_click_distance_x) + eY * panelPos_y, didntresize);
+ }
+ if(resizeCorner == 4) {
+ HUD_Panel_SetSize(i, mousepos - panelPos - (panel_click_distance - panel_click_size));
+ }
+ }
+ }
+ }
+ }
+ mouseprevpos = mousepos;
+ prevMouseClicked = mouseClicked;
+}
+
+/*void HUD_DrawDockEdge(float id, vector p1, vector p2, float target)
+{
+ vector pos;
+ vector size;
+
+ pos =
+*/ // maybe one day, since this will be quite complicated
+
+// Weapon icons (#0)
+//
+
+float weaponspace[10];
+void HUD_WeaponIcons_Clear()
+{
+ float idx;
+ for(idx = 0; idx < 10; ++idx)
+ weaponspace[idx] = 0;
+}
+
+void HUD_WeaponIcons()
+{
+ float alpha, height, marigin, accuracybar_height, stat_weapons; // "constants"
+ vector pos, mySize, mysize, mypos, color, accuracy_color;
+ float i, id, fade, weapon_stats, weapon_hit, weapon_damage, weapon_cnt; // variables
+
+ marigin = HUD_Panel_GetMarigin(0);
+ pos = HUD_Panel_GetPos(0);
+ mySize = HUD_Panel_GetSize(0);
+ color = HUD_Panel_GetColor(0);
+ accuracybar_height = cvar_or("hud_weaponicons_accuracybar_height", 3);
+
+ stat_weapons = getstati(STAT_WEAPONS);
+ for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+ {
+ self = get_weaponinfo(i);
+ if(self.weapons && self.impulse >= 0 && stat_weapons & self.weapons)
+ ++weapon_cnt;
+ }
+
+ if(HUD_Panel_GetBgActive(0) && weapon_cnt)
+ draw_BorderPicture(pos - '1 1 0' * marigin, "gfx/hud/border", mySize + '1 1 0' * 2 * marigin, color, hud_alpha_bg, '1 1 0' * (marigin/MARIGIN_MULTIPLIER));
+
+ // hits
+ weapon_stats = getstati(STAT_DAMAGE_HITS);
+ weapon_number = weapon_stats & 63;
+ weapon_hits[weapon_number-WEP_FIRST] = floor(weapon_stats / 64);
+ // fired
+ weapon_stats = getstati(STAT_DAMAGE_FIRED);
+ weapon_number = weapon_stats & 63;
+ weapon_fired[weapon_number-WEP_FIRST] = floor(weapon_stats / 64);
+
+ if(cvar_or("hud_weaponicons_fade", 1))
+ {
+ fade = 3.2 - 2 * (time - weapontime);
+ fade = bound(0.7, fade, 1);
+ }
+ else
+ fade = 1;
+
+ HUD_WeaponIcons_Clear();
+
+ float rows, columns;
+ //TODO: yuck. there must be a better way :)
+ //rows = ceil(4 * mySize_y/mySize_x);
+ if(mySize_y/mySize_x < 0.08)
+ rows = 1;
+ else if(mySize_y/mySize_x < 0.25)
+ rows = 2;
+ else if(mySize_y/mySize_x < 0.5)
+ rows = 3;
+ else if(mySize_y/mySize_x < 0.7)
+ rows = 4;
+ else if(mySize_y/mySize_x < 0.9)
+ rows = 5;
+ else if(mySize_y/mySize_x < 1.25)
+ rows = 6;
+ else if(mySize_y/mySize_x < 1.7)
+ rows = 7;
+ else if(mySize_y/mySize_x < 2.5)
+ rows = 8;
+ else if(mySize_y/mySize_x < 4)
+ rows = 12;
+ else if(mySize_y/mySize_x < 6)
+ rows = 14;
+ else
+ rows = 16;
+
+ columns = ceil(16/rows);
+ float row, column;
+ for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+ {
+ self = get_weaponinfo(i);
+ if((self.weapons && self.impulse >= 0 && stat_weapons & self.weapons) || cvar("_hud_configure"))
+ {
+ id = self.impulse;
+
+ alpha = (id == activeweapon) ? 1 : 0.6;
+
+ weapon_hit = weapon_hits[self.weapon-WEP_FIRST];
+ weapon_damage = weapon_fired[self.weapon-WEP_FIRST];
+ if(id == 0) // porto and hook should be last
+ id = 9;
+ else
+ id = --id;
+
+ if(id+1 == activeweapon)
+ drawpic(pos + eX * column * mySize_x*(1/columns) + eY * row * mySize_y*(1/rows), "gfx/hud/sb_ammobg", eX * mySize_x*(1/columns) + eY * mySize_y*(1/rows), color, fade * hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawpic(pos + eX * column * mySize_x*(1/columns) + eY * row * mySize_y*(1/rows), strcat("gfx/hud/inv_weapon", self.netname), eX * mySize_x*(1/columns) + eY * mySize_y*(1/rows), '1 1 1', fade * hud_alpha_fg, DRAWFLAG_NORMAL);
+
+ if(cvar_or("hud_weaponicons_number", 1))
+ drawstring(pos + eX * column * mySize_x*(1/columns) + eY * row * mySize_y*(1/rows), ftos(id+1), '1 1 0' * 0.5 * mySize_y*(1/rows), '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+
+ // draw the weapon accuracy on the HUD
+ if(hud_accuracy_hud && !(gametype == GAME_RACE || gametype == GAME_CTS))
+ {
+ if(weapon_damage)
+ weapon_stats = floor(100 * weapon_hit / weapon_damage);
+
+ accuracy_color = HUD_AccuracyColor(weapon_stats);
+ if(weapon_damage)
+ drawpic(pos + eX * column * mySize_x*(1/columns) + eY * row * mySize_y*(1/rows) - '2 0 0' + eY * (mySize_y/rows - accuracybar_height), "gfx/hud/sb_accuracy_bar.tga", eX * mySize_x*(1/columns) + eY * accuracybar_height, accuracy_color, hud_alpha_fg, DRAWFLAG_NORMAL);
+ }
+ }
+
+ ++row;
+ if(row >= rows)
+ {
+ row = 0;
+ ++column;
+ }
+ }
+
+}
+
+// Inventory (#1)
+//
+
+float GetAmmoStat(float i)
+{
+ switch(i)
+ {
+ case 0: return STAT_SHELLS;
+ case 1: return STAT_NAILS;
+ case 2: return STAT_ROCKETS;
+ case 3: return STAT_CELLS;
+ case 4: return STAT_FUEL;
+ default: return -1;
+ }
+}
+
+float GetAmmoItemCode(float i)
+{
+ switch(i)
+ {
+ case 0: return IT_SHELLS;
+ case 1: return IT_NAILS;
+ case 2: return IT_ROCKETS;
+ case 3: return IT_CELLS;
+ case 4: return IT_FUEL;
+ default: return -1;
+ }
+}
+
+string GetAmmoPicture(float i)
+{
+ switch(i)
+ {
+ case 0: return "gfx/hud/sb_shells";
+ case 1: return "gfx/hud/sb_bullets";
+ case 2: return "gfx/hud/sb_rocket";
+ case 3: return "gfx/hud/sb_cells";
+ case 4: return "gfx/hud/sb_fuel";
+ default: return "";
+ }
+}
+
+void HUD_Inventory()
+{
+ float i;
+ float stat_items;
+ float marigin;
+
+ vector pos, mySize, mysize, mypos, color;
+ marigin = HUD_Panel_GetMarigin(1);
+ pos = HUD_Panel_GetPos(1);
+ mySize = HUD_Panel_GetSize(1);
+ color = HUD_Panel_GetColor(1);
+
+ if(HUD_Panel_GetBgActive(1))
+ draw_BorderPicture(pos - '1 1 0' * marigin, "gfx/hud/border", mySize + '1 1 0' * 2 * marigin, color, hud_alpha_bg, '1 1 0' * (marigin/MARIGIN_MULTIPLIER));
+
+ // ammo
+ stat_items = getstati(STAT_ITEMS);
+ for (i = 0; i < 4; ++i) {
+ float a;
+ a = getstati(GetAmmoStat(i)); // how much ammo do we have of type i?
+ if(cvar("_hud_configure"))
+ a = 100;
+
+ if(cvar("hud_ammo_onlycurrent")) {
+ if (stat_items & GetAmmoItemCode(i)) {
+ drawpic(pos - '1 1 0' * marigin, "gfx/hud/sb_ammobg", mysize + '1 1 0' * marigin, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawpic(pos + eX * mysize_x * 1.7, GetAmmoPicture(i), '24 24 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ if(a < 10)
+ HUD_DrawXNum(pos + '5 5 0', a, 3, 0, 24, '0.7 0 0', 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+ else
+ HUD_DrawXNum(pos + '5 5 0', a, 3, 0, 24, '1 1 1', 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+ }
+ } else {
+ if (a > 0) {
+ if(mySize_x/mySize_y >= 10) { // arrange horizontally
+ switch (i) {
+ case 0: mypos_x = pos_x; mypos_y = pos_y; break; // shells
+ case 1: mypos_x = pos_x + 0.25 * mySize_x; mypos_y = pos_y; break; // bullets
+ case 2: mypos_x = pos_x + 0.5 * mySize_x; mypos_y = pos_y; break; // rockets
+ case 3: mypos_x = pos_x + 0.75 * mySize_x; mypos_y = pos_y; break; // cells
+ }
+ mysize_x = 0.25 * mySize_x;
+ mysize_y = mySize_y;
+ } else if(mySize_x/mySize_y >= 2.5) { // arrange in a 2x2 grid
+ switch (i) {
+ case 0: mypos_x = pos_x + 0.5 * mySize_x; mypos_y = pos_y + 0.5 * mySize_y; break; // shells
+ case 1: mypos_x = pos_x + 0.5 * mySize_x; mypos_y = pos_y; break; // bullets
+ case 2: mypos_x = pos_x; mypos_y = pos_y + 0.5 * mySize_y; break; // rockets
+ case 3: mypos_x = pos_x; mypos_y = pos_y; break; // cells
+ }
+ mysize_x = 0.5 * mySize_x;
+ mysize_y = 0.5 * mySize_y;
+ } else { // arrange vertically
+ switch (i) {
+ case 0: mypos_x = pos_x; mypos_y = pos_y; break; // shells
+ case 1: mypos_x = pos_x; mypos_y = pos_y + 0.25 * mySize_y; break; // bullets
+ case 2: mypos_x = pos_x; mypos_y = pos_y + 0.5 * mySize_y; break; // rockets
+ case 3: mypos_x = pos_x; mypos_y = pos_y + 0.75 * mySize_y; break; // cells
+ }
+ mysize_x = mySize_x;
+ mysize_y = 0.25 * mySize_y;
+ }
+
+ if (stat_items & GetAmmoItemCode(i))
+ drawpic(mypos, "gfx/hud/sb_ammobg", mysize, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawpic(mypos + eY * 0.05 * mysize_y, GetAmmoPicture(i), '1 1 0' * 0.8 * mysize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ if (a < 10) {
+ if(stat_items & GetAmmoItemCode(i))
+ HUD_DrawXNum(mypos + eX * 0.8 * mysize_y + eY * 0.25 * mysize_y, a, strlen(ftos(a)), 0, 0.5 * mysize_y, '0.7 0 0', 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+ else
+ HUD_DrawXNum(mypos + eX * 0.8 * mysize_y + eY * 0.25 * mysize_y, a, strlen(ftos(a)), 0, 0.5 * mysize_y, '0.7 0 0', 0, 0, hud_alpha_fg * 0.7, DRAWFLAG_NORMAL);
+ } else {
+ if(stat_items & GetAmmoItemCode(i))
+ HUD_DrawXNum(mypos + eX * 0.8 * mysize_y + eY * 0.25 * mysize_y, a, strlen(ftos(a)), 0, 0.5 * mysize_y, '1 1 1', 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+ else
+ HUD_DrawXNum(mypos + eX * 0.8 * mysize_y + eY * 0.25 * mysize_y, a, strlen(ftos(a)), 0, 0.5 * mysize_y, '0.7 0.7 0.7', 0, 0, hud_alpha_fg * 0.7, DRAWFLAG_NORMAL);
+ }
+ }
+ }
+ }
+
+ // fuel ammo
+ a = getstati(GetAmmoStat(4)); // how much fuel do we have?
+
+ if (a > 0) { // if we have fuel, draw the amount
+ if(pos_x + 0.5 * mySize_x > 0.5 * vid_conwidth)
+ mypos_x += pos_x + mySize_x - 0; // TODO!
+
+ drawpic(mypos - '0 2 0' + '52 0 0', GetAmmoPicture(4), '20 20 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ if (a > 10)
+ HUD_DrawXNum(mypos, a, 3, 0, 16, '1 1 1', 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+ else
+ HUD_DrawXNum(mypos, a, 3, 0, 16, '0.7 0 0', 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+ }
+}
+
+
+// Powerups (#2)
+// TODO!
+void HUD_Powerups() {
+ float stat_items, dt;
+ float marigin;
+
+ vector pos, mySize, color;
+ marigin = HUD_Panel_GetMarigin(2);
+ pos = HUD_Panel_GetPos(2);
+ mySize = HUD_Panel_GetSize(2);
+ color = HUD_Panel_GetColor(2);
+
+ if(HUD_Panel_GetBgActive(2))
+ draw_BorderPicture(pos - '1 1 0' * marigin, "gfx/hud/border", mySize + '1 1 0' * 2 * marigin, color, hud_alpha_bg, '1 1 0' * (marigin/MARIGIN_MULTIPLIER));
+
+ stat_items = getstati(STAT_ITEMS);
+ /*
+ if not(stat_items & IT_STRENGTH)
+ if not(stat_items & IT_INVINCIBLE)
+ return;
+ */
+
+ if (getstati(STAT_HEALTH) <= 0)
+ return;
+
+ float strength_time, invincibility_time, countdown_fontsize;
+
+ //strength
+ strength_time = getstatf(STAT_STRENGTH_FINISHED);
+ invincibility_time = getstatf(STAT_INVINCIBLE_FINISHED);
+
+ if (strength_time) {
+ dt = strength_time - time;
+ if(dt > 0)
+ {
+ if(dt < 5)
+ {
+ drawpic_expanding_two(pos, "gfx/hud/sb_str", '1 1 0' * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_ADDITIVE,
+ bound(0, (ceil(dt) - dt) / 0.5, 1));
+ }
+ else
+ {
+ drawpic(pos, "gfx/hud/sb_str", '1 1 0' * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_ADDITIVE);
+ }
+ HUD_DrawXNum(pos - '40 -2 0', ceil(dt), 2, 0, countdown_fontsize, '1 1 1', 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+ }
+ else if(dt > -1)
+ {
+ drawpic_expanding(pos, "gfx/hud/sb_str", '1 1 0' * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_ADDITIVE,
+ bound(0, -dt / 0.5, 1));
+ }
+ }
+
+ //invincibility
+ if (invincibility_time) {
+ dt = invincibility_time - time;
+ if(dt > 0)
+ {
+ if(dt < 5)
+ {
+ drawpic_expanding_two(pos - '0 -22 0', "gfx/hud/sb_invinc", '1 1 0' * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_ADDITIVE,
+ bound(0, (ceil(dt) - dt) / 0.5, 1));
+ }
+ else
+ {
+ drawpic(pos - '0 -22 0', "gfx/hud/sb_invinc", '1 1 0' * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_ADDITIVE);
+ }
+ HUD_DrawXNum(pos - '40 -24 0', ceil(dt), 2, 0, countdown_fontsize, '1 1 1', 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+ }
+ else if(dt > -1)
+ {
+ drawpic_expanding(pos - '0 -22 0', "gfx/hud/sb_invinc", '1 1 0' * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_ADDITIVE,
+ bound(0, -dt / 0.5, 1));
+ }
+ }
+}
+
+// Health/armor (#3)
+//
+void HUD_HealthArmor(void)
+{
+ float marigin;
+
+ vector pos, mySize, color;
+ marigin = HUD_Panel_GetMarigin(3);
+ pos = HUD_Panel_GetPos(3);
+ mySize = HUD_Panel_GetSize(3);
+ color = HUD_Panel_GetColor(3);
+
+ if(HUD_Panel_GetBgActive(3))
+ draw_BorderPicture(pos - '1 1 0' * marigin, "gfx/hud/border", mySize + '1 1 0' * 2 * marigin, color, hud_alpha_bg, '1 1 0' * (marigin/MARIGIN_MULTIPLIER));
+
+ float armor, health, x;
+ armor = getstati(STAT_ARMOR);
+ health = getstati(STAT_HEALTH);
+ if(cvar("_hud_configure"))
+ {
+ armor = 150;
+ health = 100;
+ }
+
+ if(health <= 0)
+ return;
+
+ float numbers;
+
+ // TODO!
+ if(hud_hudselector == 2) // combined health and armor display
+ {
+ vector v;
+ v = healtharmor_maxdamage(health, armor, armorblockpercent);
+
+ vector num_pos;
+ num_pos = - '96 28 0';
+
+ x = floor(v_x + 1);
+
+ if(v_z) // fully armored
+ {
+ // here, armorideal > armor
+ drawpic(num_pos + '78 -4.5 0', "gfx/hud/sb_health", '32 32 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawpic(num_pos + '108 -4.5 0', "gfx/hud/sb_armor", '20 20 0', '1 1 1', hud_alpha_fg * armor / v_y, DRAWFLAG_NORMAL);
+ }
+ else
+ {
+ drawpic(num_pos + '108 -4.5 0', "gfx/hud/sb_health", '20 20 0', '1 1 1', hud_alpha_fg * v_y / armor, DRAWFLAG_NORMAL);
+ drawpic(num_pos + '78 -4.5 0', "gfx/hud/sb_armor", '32 32 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ }
+ HUD_DrawXNum_Colored(num_pos, x, 3, 24, hud_alpha_fg); // draw the combined health and armor
+ }
+
+ else
+ {
+ vector health_pos, armor_pos;
+
+ // TODO!
+ if (hud_hudselector == 0) { // old style layout with armor left of health
+ armor_pos = pos;
+ health_pos = pos + eX * 0.5 * mySize_x;
+ } else {
+ health_pos = pos;
+ armor_pos = pos + eX * 0.5 * mySize_x;
+ }
+
+
+ if (mySize_x/mySize_y > 5)
+ {
+ // armor
+ x = armor;
+ numbers = strlen(ftos(x));
+
+ if (x > 0)
+ {
+ drawpic(pos, "gfx/hud/statuhud", eX * 0.5 * mySize_x * min(1, x/200) + eY * mySize_y, HUD_Panel_GetProgressBarColor("armor"), cvar("hud_progreshud_alpha"), DRAWFLAG_NORMAL);
+ if (x > 45)
+ drawpic(pos, "gfx/hud/sb_armor", '1 1 0' * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ else
+ drawpic(pos, "gfx/hud/sb_armor", '1 1 0' * mySize_y, '1 1 1', (x+10)/55 * hud_alpha_fg, DRAWFLAG_NORMAL);
+ HUD_DrawXNum_Colored(pos + eX * mySize_y + eY * 0.25 * mySize_y, x, numbers, 0.5 * mySize_y, hud_alpha_fg);
+ }
+
+ // health
+ x = health;
+ drawpic(pos + eX * mySize_x - eX * 0.5 * mySize_x * min(1, x/200), "gfx/hud/statuhud", eX * 0.5 * mySize_x * min(1, x/200) + eY * mySize_y, HUD_Panel_GetProgressBarColor("health"), cvar("hud_progreshud_alpha"), DRAWFLAG_NORMAL);
+ drawpic(pos + eX * mySize_x - eX * mySize_y, "gfx/hud/sb_health", '1 1 0' * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ HUD_DrawXNum_Colored(pos + eX * mySize_x - eX * 2.5 * mySize_y + eY * 0.25 * mySize_y, x, 3, 0.5 * mySize_y, hud_alpha_fg);
+ }
+ else if (mySize_x/mySize_y > 3.2)
+ {
+ // armor
+ x = armor;
+ numbers = strlen(ftos(x));
+
+ if (x > 0)
+ {
+ drawpic(pos + eY * mySize_y - eY * mySize_y * min(1, x/200), "gfx/hud/statuhud", eX * 0.5 * mySize_x + eY * mySize_y * min(1, x/200), HUD_Panel_GetProgressBarColor("armor"), cvar("hud_progreshud_alpha"), DRAWFLAG_NORMAL);
+ if (x > 45)
+ drawpic(pos + eX * 0.4 * mySize_y, "gfx/hud/sb_armor", '0.7 0.7 0' * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ else
+ drawpic(pos + eX * 0.4 * mySize_y, "gfx/hud/sb_armor", '0.7 0.7 0' * mySize_y, '1 1 1', (x+10)/55 * hud_alpha_fg, DRAWFLAG_NORMAL);
+ HUD_DrawXNum_Colored(pos + eY * 0.55 * mySize_y, x, numbers, 0.5 * mySize_y, hud_alpha_fg);
+ }
+
+ // health
+ x = health;
+ numbers = strlen(ftos(x));
+
+ drawpic(pos + eX * 0.5 * mySize_x + eY * mySize_y - eY * mySize_y * min(1, x/200), "gfx/hud/statuhud", eX * 0.5 * mySize_x + eY * mySize_y * min(1, x/200), HUD_Panel_GetProgressBarColor("health"), cvar("hud_progreshud_alpha"), DRAWFLAG_NORMAL);
+ drawpic(pos + eX * mySize_x - eX * 1.1 * mySize_y, "gfx/hud/sb_health", '0.7 0.7 0' * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ HUD_DrawXNum_Colored(pos + eX * mySize_x - eX * numbers * 0.5 * mySize_y + eY * 0.55 * mySize_y, x, numbers, 0.5 * mySize_y, hud_alpha_fg);
+ }
+ else
+ {
+ // armor
+ x = armor;
+ numbers = strlen(ftos(x));
+
+ if (x > 0)
+ {
+ drawpic(pos, "gfx/hud/statuhud", eX * mySize_x * min(1, x/200) + eY * 0.5 * mySize_y, HUD_Panel_GetProgressBarColor("armor"), cvar("hud_progreshud_alpha"), DRAWFLAG_NORMAL);
+ if (x > 45)
+ drawpic(pos, "gfx/hud/sb_armor", '0.5 0.5 0' * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ else
+ drawpic(pos, "gfx/hud/sb_armor", '0.5 0.5 0' * mySize_y, '1 1 1', (x+10)/55 * hud_alpha_fg, DRAWFLAG_NORMAL);
+ HUD_DrawXNum_Colored(pos + eX * 0.5 * mySize_y, x, numbers, 0.5 * mySize_y, hud_alpha_fg);
+ }
+
+ // health
+ x = health;
+ numbers = strlen(ftos(x));
+
+ drawpic(pos + eY * 0.5 * mySize_y, "gfx/hud/statuhud", eX * mySize_x * min(1, x/200) + eY * 0.5 * mySize_y, HUD_Panel_GetProgressBarColor("health"), cvar("hud_progreshud_alpha"), DRAWFLAG_NORMAL);
+ drawpic(pos + eY * 0.5 * mySize_y, "gfx/hud/sb_health", '0.5 0.5 0' * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ HUD_DrawXNum_Colored(pos + eX * 0.5 * mySize_y + eY * 0.5 * mySize_y, x, numbers, 0.5 * mySize_y, hud_alpha_fg);
+ }
+ }
+}
+
+// Score (#7)
+//
+void HUD_Score()
+{
+ float marigin;
+
+ vector pos, mySize, color;
+ marigin = HUD_Panel_GetMarigin(7);
+ pos = HUD_Panel_GetPos(7);
+ mySize = HUD_Panel_GetSize(7);
+ color = HUD_Panel_GetColor(7);
+
+ if(HUD_Panel_GetBgActive(7))
+ draw_BorderPicture(pos - '1 1 0' * marigin, "gfx/hud/border", mySize + '1 1 0' * 2 * marigin, color, hud_alpha_bg, '1 1 0' * (marigin/MARIGIN_MULTIPLIER));
+
+ float score, distribution, leader;
+ vector score_pos, secondary_score_pos, distribution_color;
+ entity tm, pl, me;
+ me = (spectatee_status > 0) ? playerslots[spectatee_status - 1] : playerslots[player_localentnum - 1];
+
+ if (!teamplay) { // non-teamgames
+ // me vector := [team/connected frags id]
+ pl = players.sort_next;
+ if(pl == me)
+ pl = pl.sort_next;
+
+ if(pl)
+ distribution = me.(scores[ps_primary]) - pl.(scores[ps_primary]);
+ else
+ distribution = 0;
+
+ score = me.(scores[ps_primary]);
+
+ if(distribution >= 5) {
+ distribution_color = eY;
+ leader = 1;
+ } else if(distribution >= 0) {
+ distribution_color = '1 1 1';
+ leader = 1;
+ } else if(distribution >= -5)
+ distribution_color = '1 1 0';
+ else
+ distribution_color = eX;
+
+ HUD_DrawXNum(pos + eX * mySize_x - eX * 6 * 0.3 * mySize_y, distribution, 6, 3, 0.3 * mySize_y, distribution_color, 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+ HUD_DrawXNum(pos + eX * mySize_x - eX * 6 * 0.75 * mySize_y + eY * 0.35 * mySize_y, score, 6, 0, 0.75 * mySize_y, distribution_color, leader, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+ } else { // teamgames
+ float max_fragcount;
+ max_fragcount = -999;
+
+ for(tm = teams.sort_next; tm; tm = tm.sort_next) {
+ if(tm.team == COLOR_SPECTATOR || !tm.team_size) // no players? don't display
+ continue;
+ score = tm.(teamscores[ts_primary]);
+ leader = 0;
+
+ if (score > max_fragcount)
+ max_fragcount = score;
+
+ if(tm.team == myteam) {
+ if (max_fragcount == score)
+ leader = 1;
+ HUD_DrawXNum(score_pos, score, 4, 0, 34, GetTeamRGB(tm.team) * 0.8, leader, 1, hud_alpha_fg, DRAWFLAG_NORMAL);
+ } else {
+ if (max_fragcount == score)
+ leader = 1;
+ HUD_DrawXNum(secondary_score_pos, score, 6, 0, 16, GetTeamRGB(tm.team) * 0.8, leader, 1, hud_alpha_fg, DRAWFLAG_NORMAL);
+ secondary_score_pos = secondary_score_pos + '0 16 0';
+ }
+ }
+ }
+}
+
+// Race timer (#8)
+//
+void HUD_RaceTimer (void) {
+ float marigin;
+
+ vector pos, mySize, color;
+ marigin = HUD_Panel_GetMarigin(8);
+ pos = HUD_Panel_GetPos(8);
+ mySize = HUD_Panel_GetSize(8);
+ color = HUD_Panel_GetColor(8);
+
+ if(HUD_Panel_GetBgActive(8))
+ draw_BorderPicture(pos - '1 1 0' * marigin, "gfx/hud/border", mySize + '1 1 0' * 2 * marigin, color, hud_alpha_bg, '1 1 0' * (marigin/MARIGIN_MULTIPLIER));
+
+ drawfont = hud_bigfont;
+ float a, t;
+ string s, forcetime;
+
+ if(race_checkpointtime)
+ {
+ a = bound(0, 2 - (time - race_checkpointtime), 1);
+ s = "";
+ forcetime = "";
+ if(a > 0) // just hit a checkpoint?
+ {
+ if(race_checkpoint != 254)
+ {
+ if(race_time && race_previousbesttime)
+ s = MakeRaceString(race_checkpoint, TIME_DECODE(race_time) - TIME_DECODE(race_previousbesttime), 0, 0, race_previousbestname);
+ else
+ s = MakeRaceString(race_checkpoint, 0, -1, 0, race_previousbestname);
+ if(race_time)
+ forcetime = TIME_ENCODED_TOSTRING(race_time);
+ }
+ }
+ else
+ {
+ if(race_laptime && race_nextbesttime && race_nextcheckpoint != 254)
+ {
+ a = bound(0, 2 - ((race_laptime + TIME_DECODE(race_nextbesttime)) - (time + TIME_DECODE(race_penaltyaccumulator))), 1);
+ if(a > 0) // next one?
+ {
+ s = MakeRaceString(race_nextcheckpoint, (time + TIME_DECODE(race_penaltyaccumulator)) - race_laptime, TIME_DECODE(race_nextbesttime), 0, race_nextbestname);
+ }
+ }
+ }
+
+ if(s != "" && a > 0)
+ {
+ dummyfunction(0, 0, 0, 0, 0, 0, 0, 0); // work around DP bug (set OFS_PARAM5 to 0)
+ //drawcolorcodedstring(m - '0 16 0' - '8 0 0' * stringwidth(s, TRUE), s, '16 16 0', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ drawcolorcodedstring(pos + eX * 0.5 * mySize_x - '0.5 0 0' * stringwidth(s, TRUE, '1 1 0' * 0.25 * mySize_y) + eY * 0.75 * mySize_y, s, '1 1 0' * 0.25 * mySize_y, hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ }
+
+ if(race_penaltytime)
+ {
+ a = bound(0, 2 - (time - race_penaltyeventtime), 1);
+ if(a > 0)
+ {
+ s = strcat("^1PENALTY: ", ftos_decimals(race_penaltytime * 0.1, 1), " (", race_penaltyreason, ")");
+ dummyfunction(0, 0, 0, 0, 0, 0, 0, 0); // work around DP bug (set OFS_PARAM5 to 0)
+ //drawcolorcodedstring(m - '0 32 0' - '8 0 0' * stringwidth(s, TRUE), s, '16 16 0', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ drawcolorcodedstring(pos - '0 32 0' - '0.5 0 0' * stringwidth(s, TRUE, '16 16 0'), s, '16 16 0', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ }
+ }
+
+ if(forcetime != "")
+ {
+ a = bound(0, (time - race_checkpointtime) / 0.5, 1);
+ //drawstring_expanding(m - '16 0 0' * stringwidth(forcetime, FALSE), forcetime, '32 32 0', '1 1 1', hud_alpha_fg, 0, a);
+ drawstring_expanding(pos + eX * 0.5 * mySize_x - '0.5 0 0' * stringwidth(forcetime, FALSE, '1 1 0' * 0.75 * mySize_y), forcetime, '1 1 0' * 0.75 * mySize_y, '1 1 1', hud_alpha_fg, 0, a);
+ }
+ else
+ a = 1;
+
+ if(race_laptime && race_checkpoint != 255)
+ {
+ s = TIME_ENCODED_TOSTRING(TIME_ENCODE(time + TIME_DECODE(race_penaltyaccumulator) - race_laptime));
+ //drawstring(m - '16 0 0' * stringwidth(s, FALSE), s, '32 32 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ drawstring(pos + eX * 0.5 * mySize_x - '0.5 0 0' * stringwidth(s, FALSE, '0.75 0.75 0' * mySize_y), s, '0.75 0.75 0' * mySize_y, '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ }
+ }
+ else
+ {
+ 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);
+ dummyfunction(0, 0, 0, 0, 0, 0, 0, 0); // work around DP bug (set OFS_PARAM5 to 0)
+ //drawcolorcodedstring(m - '0 16 0' - '8 0 0' * stringwidth(s, TRUE), s, '16 16 0', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ drawcolorcodedstring(pos - '0 16 0' - '0.5 0 0' * stringwidth(s, TRUE, '16 16 0'), s, '16 16 0', hud_alpha_fg * 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);
+ dummyfunction(0, 0, 0, 0, 0, 0, 0, 0); // work around DP bug (set OFS_PARAM5 to 0)
+ //drawcolorcodedstring(m - '0 0 0' - '8 0 0' * stringwidth(s, TRUE), s, '16 16 0', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ drawcolorcodedstring(pos - '0 0 0' - '0.5 0 0' * stringwidth(s, TRUE, '16 16 0'), s, '16 16 0', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ }
+
+ if(race_penaltytime && !race_penaltyaccumulator)
+ {
+ t = race_penaltytime * 0.1 + race_penaltyeventtime;
+ a = bound(0, (1 + t - time), 1);
+ if(a > 0)
+ {
+ if(time < t)
+ s = strcat("^1PENALTY: ", ftos_decimals(t - time, 1), " (", race_penaltyreason, ")");
+ else
+ s = strcat("^2PENALTY: 0.0 (", race_penaltyreason, ")");
+ dummyfunction(0, 0, 0, 0, 0, 0, 0, 0); // work around DP bug (set OFS_PARAM5 to 0)
+ //drawcolorcodedstring(m - '0 32 0' - '8 0 0' * stringwidth(s, TRUE), s, '16 16 0', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ drawcolorcodedstring(pos - '0 32 0' - '0.5 0 0' * stringwidth(s, TRUE, '16 16 0'), s, '16 16 0', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ }
+ }
+ }
+
+ drawfont = hud_font;
+}
+
+// Notification area (#4)
+void HUD_Notify (void)
+{
+ float marigin;
+
+ vector pos, mySize, color;
+ marigin = HUD_Panel_GetMarigin(4);
+ pos = HUD_Panel_GetPos(4);
+ mySize = HUD_Panel_GetSize(4);
+ color = HUD_Panel_GetColor(4);
+
+ if(HUD_Panel_GetBgActive(4))
+ draw_BorderPicture(pos - '1 1 0' * marigin, "gfx/hud/border", mySize + '1 1 0' * 2 * marigin, color, hud_alpha_bg, '1 1 0' * (marigin/MARIGIN_MULTIPLIER));
+
+ string s;
+ entity tm;
+ if(spectatee_status && !intermission)
+ {
+ drawfont = hud_bigfont;
+ if(spectatee_status == -1)
+ s = "^1Observing";
+ else
+ s = GetPlayerName(spectatee_status - 1);
+ // spectated player name between HUD and chat area, aligned to the left
+ pos_x = 0;
+ pos_y = - 50 - hud_fontsize_spec_y;
+ s = textShortenToWidth(s, vid_conwidth/2.5, hud_fontsize_spec, stringwidth_colors);
+ drawcolorcodedstring(pos, s, hud_fontsize_spec, hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawfont = hud_font;
+
+ // spectator text in the upper right corner
+ if(spectatee_status == -1)
+ s = strcat("^1Press ^3", getcommandkey("primary fire", "+attack"), "^1 to spectate");
+ else
+ s = strcat("^1Press ^3", getcommandkey("primary fire", "+attack"), "^1 for another player");
+
+ if(spectatee_status == -1)
+ s = strcat("^1Use ^3", getcommandkey("next weapon", "weapnext"), "^1 or ^3", getcommandkey("previous weapon", "weapprev"), "^1 to change the speed");
+ else
+ s = strcat("^1Press ^3", getcommandkey("secondary fire", "+attack2"), "^1 to observe");
+
+ s = strcat("^1Press ^3", getcommandkey("server info", "+show_info"), "^1 for gamemode info");
+
+ if(gametype == GAME_ARENA)
+ s = "^1Wait for your turn to join";
+ else if(gametype == GAME_LMS)
+ {
+ entity sk;
+ sk = playerslots[player_localentnum - 1];
+ if(sk.(scores[ps_primary]) >= 666)
+ s = "^1Match has already begun";
+ else if(sk.(scores[ps_primary]) > 0)
+ s = "^1You have no more lives left";
+ else
+ s = strcat("^1Press ^3", getcommandkey("jump", "+jump"), "^1 to join");
+ }
+ else
+ s = strcat("^1Press ^3", getcommandkey("jump", "+jump"), "^1 to join");
+
+ //show restart countdown:
+ if (time < getstatf(STAT_GAMESTARTTIME)) {
+ float countdown;
+ //we need to ceil, otherwise the countdown would be off by .5 when using round()
+ countdown = ceil(getstatf(STAT_GAMESTARTTIME) - time);
+ s = strcat("^1Game starts in ^3", ftos(countdown), "^1 seconds");
+ }
+ }
+ if(warmup_stage && !intermission)
+ {
+ s = "^2Currently in ^1warmup^2 stage!";
+ }
+
+ // move more important stuff more to the middle so its more visible
+
+ string blinkcolor;
+ if(mod(time, 1) >= 0.5)
+ blinkcolor = "^1";
+ else
+ blinkcolor = "^3";
+
+ if(ready_waiting && !intermission && !spectatee_status)
+ {
+ if(ready_waiting_for_me)
+ {
+ if(warmup_stage)
+ s = strcat(blinkcolor, "Press ^3", getcommandkey("ready", "ready"), blinkcolor, " to end warmup");
+ else
+ s = strcat(blinkcolor, "Press ^3", getcommandkey("ready", "ready"), blinkcolor, " once you are ready");
+ }
+ else
+ {
+ if(warmup_stage)
+ s = strcat("^2Waiting for others to ready up to end warmup...");
+ else
+ s = strcat("^2Waiting for others to ready up...");
+ }
+ }
+ else if(warmup_stage && !intermission && !spectatee_status)
+ {
+ s = strcat("^2Press ^3", getcommandkey("ready", "ready"), "^2 to end warmup");
+ }
+
+ if(teamplay && !intermission && !spectatee_status && gametype != GAME_CA && teamnagger)
+ {
+ float ts_min, ts_max;
+ tm = teams.sort_next;
+ if (tm)
+ {
+ for(; tm.sort_next; tm = tm.sort_next)
+ {
+ if(!tm.team_size || tm.team == COLOR_SPECTATOR)
+ continue;
+ if(!ts_min) ts_min = tm.team_size;
+ else ts_min = min(ts_min, tm.team_size);
+ if(!ts_max) ts_max = tm.team_size;
+ else ts_max = max(ts_max, tm.team_size);
+ }
+ if ((ts_max - ts_min) > 1)
+ {
+ s = strcat(blinkcolor, "Teamnumbers are unbalanced!");
+ tm = GetTeam(myteam, false);
+ if (tm)
+ if (tm.team != COLOR_SPECTATOR)
+ if (tm.team_size == ts_max)
+ s = strcat(s, " Press ^3", getcommandkey("team menu", "menu_showteamselect"), blinkcolor, " to adjust");
+
+ }
+ }
+ }
+}
+
+// Vote window (#9)
+float vote_yescount;
+float vote_nocount;
+float vote_needed;
+float vote_highlighted; // currently selected vote
+
+float vote_active; // is there an active vote?
+float vote_prev; // previous state of vote_active to check for a change
+float vote_alpha;
+float vote_change; // "time" when vote_active changed
+
+void HUD_VoteWindow(void)
+{
+ float marigin;
+
+ vector pos, mySize, color;
+ marigin = HUD_Panel_GetMarigin(9);
+ pos = HUD_Panel_GetPos(9);
+ mySize = HUD_Panel_GetSize(9);
+ color = HUD_Panel_GetColor(9);
+
+ string s;
+ float a;
+ if(vote_active != vote_prev) {
+ vote_change = time;
+ vote_prev = bound(0, vote_active, 1);
+ }
+
+ if(vote_active)
+ vote_alpha = bound(0, (time - vote_change) * 2, 1);
+ else
+ vote_alpha = bound(0, 1 - (time - vote_change) * 2, 1);
+
+ if(HUD_Panel_GetBgActive(9))
+ draw_BorderPicture(pos - '1 1 0' * marigin, "gfx/hud/border", mySize + '1 1 0' * 2 * marigin, color, hud_alpha_bg * vote_alpha, '1 1 0' * (marigin/MARIGIN_MULTIPLIER));
+
+ if(vote_alpha) {
+ a = vote_alpha * bound(cvar_or("hud_vote_alreadyvoted_alpha", 0.75), 1 - vote_highlighted, 1);
+
+ drawpic(pos, "gfx/hud/voteprogress_back", mySize, HUD_GetBgColor(), a * hud_alpha_bg, DRAWFLAG_NORMAL);
+
+ s = "A vote has been called for: ";
+ drawstring(pos + '0.5 0 0' * mySize_x + '0 0.1 0' * mySize_y - eX * stringwidth(s, FALSE, '1 1 0' * 0.5 * mySize_y*(1/5)), s, '1 1 0' * mySize_y*(1/5), '1 1 1', a * hud_alpha_fg, DRAWFLAG_NORMAL);
+ s = textShortenToWidth(vote_called_vote, mySize_x * 0.96, '10 0 0', stringwidth_colors);
+ drawcolorcodedstring(pos + '0.52 0 0' * mySize_x + '0 0.3 0' * mySize_y - eX * stringwidth(s, FALSE, '1 1 0' * 0.5 * mySize_y*(1/6)), s, '1 1 0' * mySize_y*(1/6), a * hud_alpha_fg, DRAWFLAG_NORMAL);
+
+ // print the yes/no counts
+ s = strcat("Yes: ", ftos(vote_yescount));
+ drawstring(pos + '0 0.6 0' * mySize_y + '0.02 0 0' * mySize_x, s, '1 1 0' * mySize_y*(1/6) , eY, a * hud_alpha_fg, DRAWFLAG_NORMAL);
+ s = strcat("No: ", ftos(vote_nocount));
+ drawstring(pos + '0 0.6 0' * mySize_y + '0.98 0 0' * mySize_x - eX * stringwidth(s, FALSE, '1 1 0' * mySize_y*(1/6)), s, '1 1 0' * mySize_y*(1/6), eX, a * hud_alpha_fg, DRAWFLAG_NORMAL);
+
+ // draw the progress bars
+ drawsetcliparea(pos_x, pos_y, mySize_x * 0.5 * (vote_yescount/vote_needed), mySize_y);
+ drawpic(pos, "gfx/hud/voteprogress_prog", mySize, eY, a * hud_alpha_fg, DRAWFLAG_NORMAL);
+
+ drawsetcliparea(pos_x + mySize_x - mySize_x * 0.5 * (vote_nocount/vote_needed), pos_y, mySize_x * 0.5, mySize_y);
+ drawpic(pos, "gfx/hud/voteprogress_prog", mySize, eX, a * hud_alpha_fg, DRAWFLAG_NORMAL);
+
+ // draw the highlights
+ if(vote_highlighted == 1) {
+ drawsetcliparea(pos_x, pos_y, mySize_x * 0.5, mySize_y);
+ drawpic(pos, "gfx/hud/voteprogress_voted", mySize, eY, a * hud_alpha_fg, DRAWFLAG_NORMAL);
+ }
+ else if(vote_highlighted == 2) {
+ drawsetcliparea(pos_x + 0.5 * mySize_x, pos_y, mySize_x * 0.5, mySize_y);
+ drawpic(pos, "gfx/hud/voteprogress_voted", mySize, eX, a * hud_alpha_fg, DRAWFLAG_NORMAL);
+ }
+
+ drawresetcliparea();
+ }
+ else if(!vote_active) {
+ vote_highlighted = 0;
+ }
+}
+
+// Awards system
+float race_status_time;
+float race_status_prev;
+string race_status_name_prev;
+void HUD_DrawRaceStatus(vector pos)
+{
+ if (race_status != race_status_prev || race_status_name != race_status_name_prev) {
+ race_status_time = time + 5;
+ race_status_prev = race_status;
+ if (race_status_name_prev)
+ strunzone(race_status_name_prev);
+ race_status_name_prev = strzone(race_status_name);
+ }
+
+ float a;
+ a = bound(0, race_status_time - time, 1);
+
+ string s;
+ s = textShortenToWidth(race_status_name, 120, '10 10 0', stringwidth_colors);
+
+ float rank;
+ if(race_status > 0)
+ rank = race_CheckName(race_status_name);
+ string rankname;
+ rankname = race_PlaceName(rank);
+
+ if(race_status == 0)
+ drawpic(pos, "gfx/hud/race/newfail", '80 80 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ else if(race_status == 1) {
+ drawpic(pos, "gfx/hud/race/newtime", '80 80 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ drawcolorcodedstring(pos + '40 80 0' - eX * stringwidth(s, TRUE, '5 0 0'), s, '10 10 0', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ drawstring(pos + '40 20 0' - eX * stringwidth(rankname, TRUE, '7 0 0'), rankname, '14 14 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ } else if(race_status == 2) {
+ if(race_status_name == GetPlayerName(player_localentnum -1) || !race_myrank || race_myrank < rank)
+ drawpic(pos, "gfx/hud/race/newrankgreen", '80 80 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ else
+ drawpic(pos, "gfx/hud/race/newrankyellow", '80 80 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ drawcolorcodedstring(pos + '40 80 0' - eX * stringwidth(s, TRUE, '5 0 0'), s, '10 10 0', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ drawstring(pos + '40 20 0' - eX * stringwidth(rankname, TRUE, '7 0 0'), rankname, '14 14 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ } else if(race_status == 3) {
+ drawpic(pos, "gfx/hud/race/newrecordserver", '80 80 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ drawcolorcodedstring(pos + '40 80 0' - eX * stringwidth(s, TRUE, '5 0 0'), s, '10 10 0', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ drawstring(pos + '40 20 0' - eX * stringwidth(rankname, TRUE, '7 0 0'), rankname, '14 14 0', '1 1 1', hud_alpha_fg * a, DRAWFLAG_NORMAL);
+ }
+
+ if (race_status_time - time <= 0) {
+ race_status_prev = -1;
+ race_status = -1;
+ if(race_status_name)
+ strunzone(race_status_name);
+ race_status_name = string_null;
+ if(race_status_name_prev)
+ strunzone(race_status_name_prev);
+ race_status_name_prev = string_null;
+ }
+}
+
+// CTF HUD modicon section
+float redflag_prevframe, blueflag_prevframe; // status during previous frame
+float redflag_prevstatus, blueflag_prevstatus; // last remembered status
+float redflag_statuschange_time, blueflag_statuschange_time; // time when the status changed
+
+void CSQC_ctf_hudreset(void)
+{
+ redflag_prevstatus = blueflag_prevstatus = redflag_prevframe = blueflag_prevframe = redflag_statuschange_time = blueflag_statuschange_time = 0;
+}
+
+void CSQC_ctf_hud(void)
+{
+ vector bottomleft, redflag_pos, blueflag_pos, sz;
+ float f; // every function should have that
+ bottomleft_y = vid_conheight;
+ bottomleft_z = 0;
+
+ float redflag, blueflag; // current status
+ float redflag_statuschange_elapsedtime, blueflag_statuschange_elapsedtime; // time since the status changed
+ float stat_items;
+
+ stat_items = getstati(STAT_ITEMS);
+ redflag = (stat_items/IT_RED_FLAG_TAKEN) & 3;
+ blueflag = (stat_items/IT_BLUE_FLAG_TAKEN) & 3;
+
+ // when status CHANGES, set old status into prevstatus and current status into status
+ if (redflag != redflag_prevframe)
+ {
+ redflag_statuschange_time = time;
+ redflag_prevstatus = redflag_prevframe;
+ redflag_prevframe = redflag;
+ }
+
+ if (blueflag != blueflag_prevframe)
+ {
+ blueflag_statuschange_time = time;
+ blueflag_prevstatus = blueflag_prevframe;
+ blueflag_prevframe = blueflag;
+ }
+
+ redflag_statuschange_elapsedtime = time - redflag_statuschange_time;
+ blueflag_statuschange_elapsedtime = time - blueflag_statuschange_time;
+
+ float BLINK_FACTOR = 0.15;
+ float BLINK_BASE = 0.85;
+ // note:
+ // RMS = sqrt(BLINK_BASE^2 + 0.5 * BLINK_FACTOR^2)
+ // thus
+ // BLINK_BASE = sqrt(RMS^2 - 0.5 * BLINK_FACTOR^2)
+ // ensure RMS == 1
+ float BLINK_FREQ = 5; // circle frequency, = 2*pi*frequency in hertz
+
+ string red_icon, red_icon_prevstatus;
+ float red_alpha, red_alpha_prevstatus;
+ red_alpha = red_alpha_prevstatus = 1;
+ switch(redflag) {
+ case 1: red_icon = "gfx/hud/sb_flag_red_taken"; break;
+ case 2: red_icon = "gfx/hud/sb_flag_red_lost"; break;
+ case 3: red_icon = "gfx/hud/sb_flag_red_carrying"; red_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break;
+ default:
+ if((stat_items & IT_CTF_SHIELDED) && (myteam == COLOR_TEAM2))
+ red_icon = "gfx/hud/sb_flag_red_shielded";
+ else
+ red_icon = string_null;
+ break;
+ }
+ switch(redflag_prevstatus) {
+ case 1: red_icon_prevstatus = "gfx/hud/sb_flag_red_taken"; break;
+ case 2: red_icon_prevstatus = "gfx/hud/sb_flag_red_lost"; break;
+ case 3: red_icon_prevstatus = "gfx/hud/sb_flag_red_carrying"; red_alpha_prevstatus = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break;
+ default:
+ if(redflag == 3)
+ red_icon_prevstatus = "gfx/hud/sb_flag_red_carrying"; // make it more visible
+ else if((stat_items & IT_CTF_SHIELDED) && (myteam == COLOR_TEAM2))
+ red_icon_prevstatus = "gfx/hud/sb_flag_red_shielded";
+ else
+ red_icon_prevstatus = string_null;
+ break;
+ }
+
+ string blue_icon, blue_icon_prevstatus;
+ float blue_alpha, blue_alpha_prevstatus;
+ blue_alpha = blue_alpha_prevstatus = 1;
+ switch(blueflag) {
+ case 1: blue_icon = "gfx/hud/sb_flag_blue_taken"; break;
+ case 2: blue_icon = "gfx/hud/sb_flag_blue_lost"; break;
+ case 3: blue_icon = "gfx/hud/sb_flag_blue_carrying"; blue_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break;
+ default:
+ if((stat_items & IT_CTF_SHIELDED) && (myteam == COLOR_TEAM1))
+ blue_icon = "gfx/hud/sb_flag_blue_shielded";
+ else
+ blue_icon = string_null;
+ break;
+ }
+ switch(blueflag_prevstatus) {
+ case 1: blue_icon_prevstatus = "gfx/hud/sb_flag_blue_taken"; break;
+ case 2: blue_icon_prevstatus = "gfx/hud/sb_flag_blue_lost"; break;
+ case 3: blue_icon_prevstatus = "gfx/hud/sb_flag_blue_carrying"; blue_alpha_prevstatus = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break;
+ default:
+ if(blueflag == 3)
+ blue_icon_prevstatus = "gfx/hud/sb_flag_blue_carrying"; // make it more visible
+ else if((stat_items & IT_CTF_SHIELDED) && (myteam == COLOR_TEAM1))
+ blue_icon_prevstatus = "gfx/hud/sb_flag_blue_shielded";
+ else
+ blue_icon_prevstatus = string_null;
+ break;
+ }
+
+ if (myteam == COLOR_TEAM1) { // always draw own flag on left
+ redflag_pos = bottomleft - '-4 50 0';
+ blueflag_pos = bottomleft - '-62 50 0';
+ } else {
+ blueflag_pos = bottomleft - '-4 50 0';
+ redflag_pos = bottomleft - '-62 50 0';
+ }
+
+ sz = '52 52 0';
+
+ f = bound(0, redflag_statuschange_elapsedtime*2, 1);
+ if(red_icon_prevstatus && f < 1)
+ drawpic_expanding(redflag_pos, red_icon_prevstatus, sz, '1 1 1', hud_alpha_fg * red_alpha_prevstatus, DRAWFLAG_NORMAL, f);
+ if(red_icon)
+ drawpic(redflag_pos, red_icon, sz, '1 1 1', hud_alpha_fg * red_alpha * f, DRAWFLAG_NORMAL);
+
+ f = bound(0, blueflag_statuschange_elapsedtime*2, 1);
+ if(blue_icon_prevstatus && f < 1)
+ drawpic_expanding(blueflag_pos, blue_icon_prevstatus, sz, '1 1 1', hud_alpha_fg * blue_alpha_prevstatus, DRAWFLAG_NORMAL, f);
+ if(blue_icon)
+ drawpic(blueflag_pos, blue_icon, sz, '1 1 1', hud_alpha_fg * blue_alpha * f, DRAWFLAG_NORMAL);
+}
+
+/*void HUD_Mod_Race (void) {
+ if((scores_flags[ps_primary] & SFL_TIME) && !teamplay) { // race/cts record display on HUD
+ pl = players.sort_next;
+ if(pl == me)
+ pl = pl.sort_next;
+ if(scores_flags[ps_primary] & SFL_ZERO_IS_WORST)
+ if(pl.scores[ps_primary] == 0)
+ pl = world;
+
+ score = me.(scores[ps_primary]);
+
+ float racemin, racesec, racemsec;
+ float distsec, distmsec, minusplus;
+
+ racemin = floor(score/(60 * TIME_FACTOR));
+ racesec = floor((score - racemin*(60 * TIME_FACTOR))/TIME_FACTOR);
+ racemsec = score - racemin*60*TIME_FACTOR - racesec*TIME_FACTOR;
+
+ if (pl && ((!(scores_flags[ps_primary] & SFL_ZERO_IS_WORST)) || score)) {
+ // distribution display
+ distribution = me.(scores[ps_primary]) - pl.(scores[ps_primary]);
+
+ if (distribution < TIME_FACTOR && distribution > -TIME_FACTOR)
+ distmsec = fabs(distribution);
+ else {
+ distsec = floor(fabs(distribution)/TIME_FACTOR);
+ distmsec = fabs(distribution) - distsec*TIME_FACTOR;
+ if (distribution < 0)
+ distsec = -distsec;
+ }
+
+ if (distribution <= 0) {
+ distribution_color = eY;
+ minusplus = 1; // minusplus 1: always prefix with minus sign
+ }
+ else {
+ distribution_color = eX;
+ minusplus = 2; // minusplus 1: always prefix with plus sign
+ }
+ HUD_DrawXNum(bottomright - '0 48 0' - '16 0 0' * TIME_DECIMALS, distmsec, -TIME_DECIMALS, 0, 16, distribution_color, 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+ HUD_DrawXNum(bottomright - '68 48 0' - '16 0 0' * TIME_DECIMALS, distsec, 4, minusplus, 16, distribution_color, 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawpic(bottomright - '10 48 0' - '16 0 0' * TIME_DECIMALS, "gfx/hud/num_dot", '16 16 0', distribution_color, hud_alpha_fg, DRAWFLAG_ADDITIVE);
+ }
+ // race record display
+ if (distribution <= 0 || distribution == score) // draw the highlight background behind the timer if we have the lead
+ drawpic(bottomright - '0 32 0' - '32 0 0' * (4 + TIME_DECIMALS), "gfx/hud/sb_highlight_4", '0 28 0' + '32 0 0' * (4 + TIME_DECIMALS), '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+
+ HUD_DrawXNum(bottomright - '0 32 0' - TIME_DECIMALS * '30 0 0', racemsec, -TIME_DECIMALS, 0, 30, '1 1 1', 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+ HUD_DrawXNum(bottomright - '0 32 0' - TIME_DECIMALS * '30 0 0' - '66 0 0', racesec, -2, 0, 30, '1 1 1', 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawpic(bottomright - '0 32 0' - TIME_DECIMALS * '30 0 0' - '18 0 0', "gfx/hud/num_dot", '30 30 0', '1 1 1', hud_alpha_fg, DRAWFLAG_ADDITIVE);
+
+ HUD_DrawXNum(bottomright - '0 32 0' - TIME_DECIMALS * '30 0 0' - '132 0 0', racemin, -2, 0, 30, '1 1 1', 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawpic(bottomright - '0 32 0' - TIME_DECIMALS * '30 0 0' - '84 0 0', "gfx/hud/num_colon", '30 30 0', '1 1 1', hud_alpha_fg, DRAWFLAG_ADDITIVE);
+ }
+}*/
+
+// Keyhunt HUD modicon section
+float kh_runheretime;
+
+void CSQC_kh_hudreset(void)
+{
+ kh_runheretime = 0;
+}
+
+void CSQC_kh_hud(void)
+{
+ float kh_keys;
+ float keyteam;
+ float a, aa;
+ vector p, pa, kh_size, kh_asize;
+
+ p_x = 6;
+ p_y = vid_conheight - 34 - 3;
+ p_z = 0;
+
+ kh_keys = getstati(STAT_KH_KEYS);
+
+ kh_size = '19 34 0';
+ kh_asize = '19 10 0';
+ pa = p + '0 -10 0';
+
+ float i, key;
+
+ float keycount;
+ keycount = 0;
+ for(i = 0; i < 4; ++i)
+ {
+ key = floor(kh_keys / pow(32, i)) & 31;
+ keyteam = key - 1;
+ if(keyteam == 30 && keycount <= 4)
+ keycount += 4;
+ if(keyteam == myteam || keyteam == -1 || keyteam == 30)
+ keycount += 1;
+ }
+ // this yields 8 exactly if "RUN HERE" shows
+
+ if(keycount == 8)
+ {
+ if(!kh_runheretime)
+ kh_runheretime = time;
+ pa_y -= fabs(sin((time - kh_runheretime) * 3.5)) * 6; // make the arrows jump in case of RUN HERE
+ }
+ else
+ kh_runheretime = 0;
+
+ for(i = 0; i < 4; ++i)
+ {
+ key = floor(kh_keys / pow(32, i)) & 31;
+ keyteam = key - 1;
+ switch(keyteam)
+ {
+ case 30: // my key
+ keyteam = myteam;
+ a = 1;
+ aa = 1;
+ break;
+ case -1: // no key
+ a = 0;
+ aa = 0;
+ break;
+ default: // owned or dropped
+ a = 0.2;
+ aa = 0.5;
+ break;
+ }
+ a = a * hud_alpha_fg;
+ aa = aa * hud_alpha_fg;
+ if(a > 0)
+ {
+ switch(keyteam)
+ {
+ case COLOR_TEAM1:
+ drawpic (pa, "gfx/hud/sb_kh_redarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL); // show 30% alpha key
+ break;
+ case COLOR_TEAM2:
+ drawpic (pa, "gfx/hud/sb_kh_bluearrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL); // show 30% alpha key
+ break;
+ case COLOR_TEAM3:
+ drawpic (pa, "gfx/hud/sb_kh_yellowarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL); // show 30% alpha key
+ break;
+ case COLOR_TEAM4:
+ drawpic (pa, "gfx/hud/sb_kh_pinkarrow", kh_asize, '1 1 1', aa, DRAWFLAG_NORMAL); // show 30% alpha key
+ break;
+ default:
+ break;
+ }
+ switch(i) // YAY! switch(i) inside a for loop for i. DailyWTF, here we come!
+ {
+ case 0:
+ drawpic (p, "gfx/hud/sb_kh_red", kh_size, '1 1 1', a, DRAWFLAG_NORMAL); // show 30% alpha key
+ break;
+ case 1:
+ drawpic (p, "gfx/hud/sb_kh_blue", kh_size, '1 1 1', a, DRAWFLAG_NORMAL); // show 30% alpha key
+ break;
+ case 2:
+ drawpic (p, "gfx/hud/sb_kh_yellow", kh_size, '1 1 1', a, DRAWFLAG_NORMAL); // show 30% alpha key
+ break;
+ case 3:
+ drawpic (p, "gfx/hud/sb_kh_pink", kh_size, '1 1 1', a, DRAWFLAG_NORMAL); // show 30% alpha key
+ break;
+ }
+ }
+ p_x += 24;
+ pa_x += 24;
+ }
+}
+
+// Nexball HUD modicon section
+#define NBPB_SIZE '96 38 0'
+#define NBPB_BT 2 //thickness
+#define NBPB_BRGB '1 1 1'
+#define NBPB_BALPH 1 //alpha
+#define NBPB_BFLAG DRAWFLAG_NORMAL
+#define NBPB_IALPH 0.4
+#define NBPB_IFLAG DRAWFLAG_NORMAL
+#define NBPB_IRGB '0.7 0.1 0'
+
+void CSQC_nb_hud(void)
+{
+ float stat_items, nb_pb_starttime, dt, p;
+ vector pos;
+
+ stat_items = getstati(STAT_ITEMS);
+ nb_pb_starttime = getstatf(STAT_NB_METERSTART);
+
+ pos_x = 4;
+ pos_y = vid_conheight - 42;
+ pos_z = 0;
+
+ //Manage the progress bar if any
+ if (nb_pb_starttime > 0)
+ {
+ vector s;
+ dt = mod(time - nb_pb_starttime, nb_pb_period);
+ // one period of positive triangle
+ p = 2 * dt / nb_pb_period;
+ if (p > 1)
+ p = 2 - p;
+
+ s = NBPB_SIZE;
+ //Draw the filling
+ drawfill(pos, p * s_x * eX + s_y * eY, NBPB_IRGB, NBPB_IALPH, NBPB_IFLAG);
+
+ //Draw the box
+ s = NBPB_SIZE;
+ drawline(NBPB_BT, pos , pos + eX * s_x, NBPB_BRGB, NBPB_BALPH, NBPB_BFLAG);
+ drawline(NBPB_BT, pos , pos + eY * s_y, NBPB_BRGB, NBPB_BALPH, NBPB_BFLAG);
+ drawline(NBPB_BT, pos + s, pos + eX * s_x, NBPB_BRGB, NBPB_BALPH, NBPB_BFLAG);
+ drawline(NBPB_BT, pos + s, pos + eY * s_y, NBPB_BRGB, NBPB_BALPH, NBPB_BFLAG);
+ }
+
+ pos_x += 12; //horizontal margin to the picture
+ pos_y += 2; //vertical margin to the picture
+
+ if (stat_items & IT_KEY1)
+ drawpic(pos, "gfx/hud/sb_nexball_carrying", '80 34 0', '1 1 1', 1, DRAWFLAG_NORMAL);
+}
+
+// Race/CTS HUD modicon section
+float crecordtime_prev; // last remembered crecordtime
+float crecordtime_change_time; // time when crecordtime last changed
+float srecordtime_prev; // last remembered srecordtime
+float srecordtime_change_time; // time when srecordtime last changed
+void CSQC_race_hud(void)
+{
+ entity me;
+ me = playerslots[player_localentnum - 1];
+ float t, score;
+ float f; // yet another function has this
+ score = me.(scores[ps_primary]);
+
+ if not((scores_flags[ps_primary] & SFL_TIME) && !teamplay) // race/cts record display on HUD
+ return; // no records in the actual race
+
+ drawfont = hud_bigfont;
+ vector pos;
+ pos_x = 2;
+ pos_y = vid_conheight - 48;
+
+ // clientside personal record
+ string rr;
+ if(gametype == GAME_CTS)
+ rr = CTS_RECORD;
+ else
+ rr = RACE_RECORD;
+ t = stof(db_get(ClientProgsDB, strcat(shortmapname, rr, "time")));
+
+ if(score && score < t || !t)
+ db_put(ClientProgsDB, strcat(shortmapname, rr, "time"), ftos(score));
+
+ if(t != crecordtime_prev) {
+ crecordtime_prev = t;
+ crecordtime_change_time = time;
+ }
+ f = time - crecordtime_change_time;
+
+ if (f > 1) {
+ drawstring(pos, "Personal best ", '10 10 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawstring(pos + '0 10 0', TIME_ENCODED_TOSTRING(t),'14 14 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ } else {
+ drawstring(pos, "Personal best ", '10 10 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawstring(pos + '0 10 0', TIME_ENCODED_TOSTRING(t),'14 14 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawstring_expanding(pos, "Personal best ", '10 10 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL, f);
+ drawstring_expanding(pos + '0 10 0', TIME_ENCODED_TOSTRING(t),'14 14 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL, f);
+ }
+
+ // server record
+ pos_y += 26;
+ t = race_server_record;
+ if(t != srecordtime_prev) {
+ srecordtime_prev = t;
+ srecordtime_change_time = time;
+ }
+ f = time - srecordtime_change_time;
+
+ if (f > 1) {
+ drawstring(pos, "Server best ", '10 10 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawstring(pos + '0 10 0', TIME_ENCODED_TOSTRING(t),'14 14 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ } else {
+ drawstring(pos, "Server best ", '10 10 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawstring(pos + '0 10 0', TIME_ENCODED_TOSTRING(t),'14 14 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawstring_expanding(pos, "Server best ", '10 10 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL, f);
+ drawstring_expanding(pos + '0 10 0', TIME_ENCODED_TOSTRING(t),'14 14 0', '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL, f);
+ }
+ drawfont = hud_font;
+}
+
+// Timer (#5)
+//
+void HUD_Timer()
+{
+ float marigin;
+
+ vector pos, mySize, color;
+ marigin = HUD_Panel_GetMarigin(5);
+ pos = HUD_Panel_GetPos(5);
+ mySize = HUD_Panel_GetSize(5);
+ color = HUD_Panel_GetColor(5);
+
+ if(HUD_Panel_GetBgActive(5))
+ draw_BorderPicture(pos - '1 1 0' * marigin, "gfx/hud/border", mySize + '1 1 0' * 2 * marigin, color, hud_alpha_bg, '1 1 0' * (marigin/MARIGIN_MULTIPLIER));
+
+ float timelimit, elapsedTime, minutes, seconds, timeleft, minutesLeft, secondsLeft;
+
+ timelimit = getstatf(STAT_TIMELIMIT);
+
+ HUD_DrawRaceStatus(pos + '0 30 0');
+
+ timeleft = max(0, timelimit * 60 + getstatf(STAT_GAMESTARTTIME) - time);
+ timeleft = ceil(timeleft);
+ minutesLeft = floor(timeleft / 60);
+ secondsLeft = timeleft - minutesLeft*60;
+
+ vector timer_color;
+ if(minutesLeft >= 5 || warmup_stage || timelimit == 0) //don't use red or yellow in warmup or when there is no timelimit
+ timer_color = '1 1 1'; //white
+ else if(minutesLeft >= 1)
+ timer_color = '1 1 0'; //yellow
+ else
+ timer_color = '1 0 0'; //red
+
+ if (cvar("hud_timer_increment") || timelimit == 0 || warmup_stage) {
+ if (time < getstatf(STAT_GAMESTARTTIME)) {
+ //while restart is still active, show 00:00
+ minutes = seconds = 0;
+ } else {
+ elapsedTime = floor(time - getstatf(STAT_GAMESTARTTIME)); //127
+ minutes = floor(elapsedTime / 60);
+ seconds = elapsedTime - minutes*60;
+ }
+ } else {
+ minutes = minutesLeft;
+ seconds = secondsLeft;
+ }
+
+ if(mySize_x/mySize_y > 5.1)
+ {
+ if(minutes > 999)
+ seconds = 99;
+ minutes = min(minutes, 999);
+ if(minutesLeft >= 1 || cvar("hud_timer_increment") || timelimit == 0 || warmup_stage) {
+ if(minutes < 100)
+ drawpic(pos + eX * mySize_x - eX * 5.1 * mySize_y, "gfx/hud/sb_timer", '1 1 0' * mySize_y, timer_color, hud_alpha_fg, DRAWFLAG_NORMAL);
+ HUD_DrawXNum(pos + eX * mySize_x - eX * 5.1 * mySize_y, minutes, 3, 0, mySize_y, timer_color, 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawpic(pos + eX * mySize_x - eX * 2.57 * mySize_y, "gfx/hud/num_colon", '1 1 0' * mySize_y, timer_color, hud_alpha_fg, DRAWFLAG_NORMAL);
+ }
+ HUD_DrawXNum(pos + eX * mySize_x - eX * 2 * mySize_y, seconds, -2, 0, mySize_y, timer_color, 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+ }
+ else
+ {
+ if(minutes > 99)
+ seconds = 99;
+ minutes = min(minutes, 99);
+ if(minutesLeft >= 1 || cvar("hud_timer_increment") || timelimit == 0 || warmup_stage) {
+ if(minutes < 100)
+ drawpic(pos + eX * 0.5 * mySize_x - eX * 0.5 * 0.5 * mySize_y, "gfx/hud/sb_timer", '0.5 0.5 0' * mySize_y, timer_color, hud_alpha_fg, DRAWFLAG_NORMAL);
+ HUD_DrawXNum(pos + eX * 0.5 * mySize_x - eX * mySize_y + eY * 0.5 * mySize_y, minutes, -2, 0, 0.5 * mySize_y, timer_color, 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawpic(pos + eX * 0.5 * mySize_x - eX * 0.5 * 0.5 * mySize_y + eY * 0.5 * mySize_y, "gfx/hud/num_colon", '0.5 0.5 0' * mySize_y, timer_color, hud_alpha_fg, DRAWFLAG_NORMAL);
+ }
+ HUD_DrawXNum(pos + eX * 0.51 * mySize_x + eY * 0.5 * mySize_y, seconds, -2, 0, 0.5 * mySize_y, timer_color, 0, 0, hud_alpha_fg, DRAWFLAG_NORMAL);
+ }
+}
+
+// Radar (#6)
+//
+
+void HUD_Radar(void)
+{
+ float marigin;
+
+ vector pos, mySize, color;
+ marigin = HUD_Panel_GetMarigin(6);
+ pos = HUD_Panel_GetPos(6);
+ mySize = HUD_Panel_GetSize(6);
+ color = HUD_Panel_GetColor(6);
+
+ if(HUD_Panel_GetBgActive(6))
+ draw_BorderPicture(pos - '1 1 0' * marigin, "gfx/hud/border", mySize + '1 1 0' * 2 * marigin, color, hud_alpha_bg, '1 1 0' * (marigin/MARIGIN_MULTIPLIER));
+
+ local float color1, color2; // color already declared as a global in hud.qc
+ local vector rgb;
+ local entity tm;
+ float scale2d, normalsize, bigsize;
+ float f;
+
+ teamradar_origin2d = pos + 0.5 * mySize; // TODO: stupid compat, should be removed
+ teamradar_size2d = mySize;
+
+ if(minimapname == "" && !ons_showmap)
+ return;
+
+ teamradar_loadcvars();
+
+ switch(cl_teamradar_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(cl_teamradar_rotation)
+ {
+ case 0:
+ teamradar_angle = view_angles_y - 90;
+ break;
+ default:
+ teamradar_angle = 90 * cl_teamradar_rotation;
+ break;
+ }
+
+ scale2d = vlen_maxnorm2d(mi_picmax - mi_picmin);
+ teamradar_size2d = mySize;
+
+ teamradar_extraclip_mins = teamradar_extraclip_maxs = '0 0 0';
+ if(pos == eX * vid_conwidth)
+ {
+ if(cl_teamradar_nohudhack < 2)
+ pos_y += 25;
+ if(cl_teamradar_nohudhack < 1)
+ teamradar_extraclip_mins_y -= 25;
+ }
+ else if(pos == eY * vid_conheight || pos == eX * vid_conwidth + eY * vid_conheight)
+ {
+ if(cl_teamradar_nohudhack < 2)
+ pos_y -= 50;
+ //if(cl_teamradar_nohudhack < 1)
+ //teamradar_extraclip_size_y += 50; // don't, the HUD looks nice
+ }
+
+ // pixels per world qu to match the teamradar_size2d_x range in the longest dimension
+ if(cl_teamradar_rotation == 0)
+ {
+ // max-min distance must fit the radar in any rotation
+ bigsize = vlen_minnorm2d(teamradar_size2d) * scale2d / (1.05 * vlen2d(mi_max - mi_min));
+ }
+ else
+ {
+ vector c0, c1, c2, c3, span;
+ c0 = rotate(mi_min, teamradar_angle * DEG2RAD);
+ c1 = rotate(mi_max, teamradar_angle * DEG2RAD);
+ c2 = rotate('1 0 0' * mi_min_x + '0 1 0' * mi_max_y, teamradar_angle * DEG2RAD);
+ c3 = rotate('1 0 0' * mi_max_x + '0 1 0' * mi_min_y, teamradar_angle * DEG2RAD);
+ span = '0 0 0';
+ span_x = max4(c0_x, c1_x, c2_x, c3_x) - min4(c0_x, c1_x, c2_x, c3_x);
+ span_y = max4(c0_y, c1_y, c2_y, c3_y) - min4(c0_y, c1_y, c2_y, c3_y);
+
+ // max-min distance must fit the radar in x=x, y=y
+ bigsize = min(
+ teamradar_size2d_x * scale2d / (1.05 * span_x),
+ teamradar_size2d_y * scale2d / (1.05 * span_y)
+ );
+ }
+
+ normalsize = vlen_maxnorm2d(teamradar_size2d) * scale2d / cl_teamradar_scale;
+ if(bigsize > normalsize)
+ normalsize = bigsize;
+
+ teamradar_size =
+ f * bigsize
+ + (1 - f) * normalsize;
+ teamradar_origin3d_in_texcoord = teamradar_3dcoord_to_texcoord(
+ f * (mi_min + mi_max) * 0.5
+ + (1 - f) * view_origin);
+
+ color1 = GetPlayerColor(player_localentnum-1);
+ rgb = GetTeamRGB(color1);
+
+ drawsetcliparea(
+ pos_x,
+ pos_y,
+ pos_x + mySize_x,
+ pos_y + mySize_y
+ );
+
+ draw_teamradar_background(cl_teamradar_background_alpha, cl_teamradar_foreground_alpha);
+
+ if(ons_showmap)
+ {
+ drawresetcliparea();
+
+ vector frame_origin, frame_size;
+ frame_origin = frame_size = '0 0 0';
+
+ frame_origin_x = pos_x - teamradar_size2d_x * 0.55859375; // matches the picture
+ frame_origin_y = pos_y - teamradar_size2d_y * 0.55859375; // matches the picture
+ frame_size_x = pos_x * 1.1171875; // matches the picture
+ frame_size_y = pos_y * 1.1171875; // matches the picture
+ drawpic(frame_origin, "gfx/ons-frame.tga", frame_size, '1 1 1', hud_alpha_fg, 0);
+ drawpic(frame_origin, "gfx/ons-frame-team.tga", frame_size, rgb, hud_alpha_fg, 0);
+
+ drawsetcliparea(
+ pos_x - teamradar_size2d_x * 0.5,
+ pos_y - teamradar_size2d_y * 0.5,
+ teamradar_size2d_x,
+ teamradar_size2d_y
+ );
+ }
+
+ for(tm = world; (tm = find(tm, classname, "radarlink")); )
+ draw_teamradar_link(tm.origin, tm.velocity, tm.team);
+ for(tm = world; (tm = findflags(tm, teamradar_icon, 0xFFFFFF)); )
+ draw_teamradar_icon(tm.origin, tm.teamradar_icon, tm, tm.teamradar_color, hud_alpha_fg);
+ 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));
+ }
+ draw_teamradar_player(view_origin, view_angles, '1 1 1');
+
+ drawresetcliparea();
+};
+
+/*
+==================
+Main HUD system
+==================
+*/
+
+void HUD_DrawPressedKeys(void)
+{
+ float marigin;
+
+ vector pos, mySize, color;
+ marigin = HUD_Panel_GetMarigin(10);
+ pos = HUD_Panel_GetPos(10);
+ mySize = HUD_Panel_GetSize(10);
+ color = HUD_Panel_GetColor(10);
+
+ if(HUD_Panel_GetBgActive(10))
+ draw_BorderPicture(pos - '1 1 0' * marigin, "gfx/hud/border", mySize + '1 1 0' * 2 * marigin, color, hud_alpha_bg, '1 1 0' * (marigin/MARIGIN_MULTIPLIER));
+
+ float pressedkeys;
+
+ pressedkeys = getstatf(STAT_PRESSED_KEYS);
+ drawpic(pos, "gfx/hud/keys/key_bg.tga", mySize, '1 1 1', 0.1 * hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawpic(pos + eX * mySize_x - eX * 0.22 * mySize_x + eY * 0.195 * mySize_y, ((pressedkeys & KEY_CROUCH) ? "gfx/hud/keys/key_crouch_inv.tga" : "gfx/hud/keys/key_crouch.tga"), '1 1 0' * (1/3) * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawpic(pos + eX * 0.5 * mySize_x - eX * 0.23 * mySize_y + eY * 0.040 * mySize_y, ((pressedkeys & KEY_FORWARD) ? "gfx/hud/keys/key_forward_inv.tga" : "gfx/hud/keys/key_forward.tga"), '1 1 0' * 0.46 * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawpic(pos + eX * 0.023 * mySize_x + eY * 0.195 * mySize_y, ((pressedkeys & KEY_JUMP) ? "gfx/hud/keys/key_jump_inv.tga" : "gfx/hud/keys/key_jump.tga"), '1 1 0' * (1/3) * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawpic(pos + eX * 0.1 * mySize_x + eY * 0.486 * mySize_y, ((pressedkeys & KEY_LEFT) ? "gfx/hud/keys/key_left_inv.tga" : "gfx/hud/keys/key_left.tga"), '1 1 0' * 0.46 * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawpic(pos + eX * 0.5 * mySize_x - eX * 0.23 * mySize_y + eY * 0.486 * mySize_y, ((pressedkeys & KEY_BACKWARD) ? "gfx/hud/keys/key_backward_inv.tga" : "gfx/hud/keys/key_backward.tga"), '1 1 0' * 0.46 * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ drawpic(pos + eX * mySize_x - eX * 0.372 * mySize_x + eY * 0.486 * mySize_y, ((pressedkeys & KEY_RIGHT) ? "gfx/hud/keys/key_right_inv.tga" : "gfx/hud/keys/key_right.tga"), '1 1 0' * 0.46 * mySize_y, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+}
+
+void HUD_ShowSpeed(void)
+{
+ vector numsize;
+ float pos, conversion_factor;
+ string speed, zspeed, unit;
+
+ switch(cvar("cl_showspeed_unit"))
+ {
+ default:
+ case 0:
+ unit = "";
+ conversion_factor = 1.0;
+ break;
+ case 1:
+ unit = " qu/s";
+ conversion_factor = 1.0;
+ break;
+ case 2:
+ unit = " m/s";
+ conversion_factor = 0.0254;
+ break;
+ case 3:
+ unit = " km/h";
+ conversion_factor = 0.0254 * 3.6;
+ break;
+ case 4:
+ unit = " mph";
+ conversion_factor = 0.0254 * 3.6 * 0.6213711922;
+ break;
+ case 5:
+ unit = " knots";
+ conversion_factor = 0.0254 * 1.943844492; // 1 m/s = 1.943844492 knots, because 1 knot = 1.852 km/h
+ break;
+ }
+
+ speed = strcat(ftos(floor( vlen(pmove_vel - pmove_vel_z * '0 0 1') * conversion_factor + 0.5 )), unit);
+
+ numsize_x = numsize_y = cvar("cl_showspeed_size");
+ pos = (vid_conheight - numsize_y) * cvar("cl_showspeed_position");
+
+ drawfont = hud_bigfont;
+ drawstringcenter(eX + pos * eY, speed, numsize, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+
+ if (cvar("cl_showspeed_z") == 1) {
+ zspeed = strcat(ftos(fabs(floor( pmove_vel_z * conversion_factor + 0.5 ))), unit);
+ drawstringcenter(eX + pos * eY + numsize_y * eY, zspeed, numsize * 0.5, '1 1 1', hud_alpha_fg, DRAWFLAG_NORMAL);
+ }
+
+ drawfont = hud_font;
+}
+
+vector acc_prevspeed;
+float acc_prevtime;
+float acc_avg;
+
+void HUD_ShowAcceleration(void)
+{
+ float acceleration, sz, scale, alpha, f;
+ vector pos, top, rgb;
+ top_x = vid_conwidth/2;
+ top_y = 0;
+
+ f = time - acc_prevtime;
+ if(cvar("cl_showacceleration_z"))
+ acceleration = (vlen(pmove_vel) - vlen(acc_prevspeed)) * (1 / f);
+ else
+ acceleration = (vlen(pmove_vel - '0 0 1' * pmove_vel_z) - vlen(acc_prevspeed - '0 0 1' * acc_prevspeed_z)) * (1 / f);
+ acc_prevspeed = pmove_vel;
+ acc_prevtime = time;
+
+ f = bound(0, f * 10, 1);
+ acc_avg = acc_avg * (1 - f) + acceleration * f;
+ acceleration = acc_avg / getstatf(STAT_MOVEVARS_MAXSPEED);
+
+ pos = top - sz/2 * eY + (cvar("cl_showacceleration_position") * vid_conheight) * eY;
+
+ sz = cvar("cl_showacceleration_size");
+ scale = cvar("cl_showacceleration_scale");
+ alpha = cvar("cl_showacceleration_alpha");
+ if (cvar("cl_showacceleration_color_custom"))
+ rgb = stov(cvar_string("cl_showacceleration_color"));
+ else {
+ rgb = '1 1 1';
+ if (acceleration < 0) {
+ rgb = '1 .5 .5' - '0 .5 .5' * bound(0, -acceleration * 0.2, 1);
+ } else if (acceleration > 0) {
+ rgb = '.5 1 .5' - '.5 0 .5' * bound(0, +acceleration * 0.2, 1);
+ }
+ }
+
+ if (acceleration > 0)
+ drawpic(pos, "gfx/hud/statuhud", acceleration * scale * '40 0 0' + sz * eY, rgb, alpha * hud_alpha_fg, DRAWFLAG_NORMAL);
+ else if (acceleration < 0)
+ drawpic(pos + acceleration * scale * '40 0 0', "gfx/hud/statuhud", -acceleration * scale * '40 0 0' + sz * eY, rgb, alpha * hud_alpha_fg, DRAWFLAG_NORMAL);
+}
+
+void HUD_Reset (void)
+{
+ // reset gametype specific icons
+ if(gametype == GAME_KEYHUNT)
+ CSQC_kh_hudreset();
+ else if(gametype == GAME_CTF)
+ CSQC_ctf_hudreset();
+}
+
+void HUD_Main (void)
+{
+ hud_alpha_bg = cvar_or("hud_alpha_bg", 0.8) * (1 - cvar("_menu_alpha"));
+ hud_border_thickness = bound(0, cvar("hud_border_thickness"), 5);
+ hud_accuracy_border_thickness = bound(0, cvar_or("hud_accuracy_border_thickness", 1), 5);
+ hud_color_bg_team = cvar("hud_color_bg_team");
+
+ hud_fontsize = HUD_GetFontsize("hud_fontsize");
+ hud_fontsize_spec = HUD_GetFontsize("hud_fontsize_spec");
+
+ if(HUD_Panel_CheckActive(0))
+ HUD_WeaponIcons();
+ if(HUD_Panel_CheckActive(1))
+ HUD_Inventory();
+ if(HUD_Panel_CheckActive(2))
+ HUD_Powerups();
+ if(HUD_Panel_CheckActive(3))
+ HUD_HealthArmor();
+ if(HUD_Panel_CheckActive(4))
+ HUD_Notify();
+ if(HUD_Panel_CheckActive(5))
+ HUD_Timer();
+ if(HUD_Panel_CheckActive(6))
+ if(ons_showmap || cvar_string("cl_teamradar") != "0" && (cvar("cl_teamradar") == 2 || teamplay))
+ HUD_Radar();
+ if(HUD_Panel_CheckActive(7))
+ HUD_Score();
+ if(HUD_Panel_CheckActive(8))
+ if(gametype == GAME_RACE || gametype == GAME_CTS || cvar("_hud_configure"))
+ HUD_RaceTimer();
+ if(HUD_Panel_CheckActive(9))
+ HUD_VoteWindow();
+ if(HUD_Panel_CheckActive(10))
+ if(spectatee_status > 0 || cvar("cl_showpressedkeys") >= 2 || cvar("_hud_configure"))
+ HUD_DrawPressedKeys();
+
+ // TODO hud_'ify these
+ if (cvar("cl_showspeed"))
+ HUD_ShowSpeed();
+ if (cvar("cl_showacceleration"))
+ HUD_ShowAcceleration();
+
+ // TODO... well make them work in a panel etc
+ if(gametype == GAME_KEYHUNT)
+ CSQC_kh_hud();
+ else if(gametype == GAME_CTF)
+ CSQC_ctf_hud();
+ else if(gametype == GAME_NEXBALL)
+ CSQC_nb_hud();
+ else if(gametype == GAME_CTS || gametype == GAME_RACE)
+ CSQC_race_hud();
+ return;
+}
#define HOOK_END 2
.float ping, ping_packetloss, ping_movementloss;
+
+float g_balance_grenadelauncher_secondary_bouncefactor;
+float g_balance_grenadelauncher_secondary_bouncestop;
wall.qc
modeleffects.qc
tuba.qc
+target_music.qc
//vehicles/spiderbot.qc
Main.qc
self.trail_oldorigin = to;
self.trail_oldtime = time;
+ // force the effect even for stationary firemine
+ if(self.cnt == PROJECTILE_FIREMINE)
+ if(from == to)
+ from_z += 1;
+
if (self.traileffect)
- trailparticles(self, self.traileffect, from, to);
+ {
+ if(checkextension("DP_CSQC_BOXPARTICLES"))
+ {
+ /* looks good, but we can do better with particle count
+ particles_alphamin = particles_alphamax = self.alpha;
+ boxparticles(self.traileffect, self, from, to, self.velocity, self.velocity, 1, PARTICLES_USEALPHA);
+ */
+ /* looks bad
+ boxparticles(self.traileffect, self, from, to, self.velocity, self.velocity, self.alpha, 0);
+ */
+ particles_alphamin = particles_alphamax = sqrt(self.alpha);
+ boxparticles(self.traileffect, self, from, to, self.velocity, self.velocity, sqrt(self.alpha), PARTICLES_USEALPHA);
+ }
+ else
+ trailparticles(self, self.traileffect, from, to);
+ }
}
void Projectile_Draw()
makevectors(ang);
a = 1 - (time - self.fade_time) * self.fade_rate;
- if(a <= 0)
+ self.alpha = bound(0, self.alphamod * a, 1);
+ if(self.alpha <= 0)
drawn = 0;
+ self.renderflags = 0;
trailorigin = self.origin;
switch(self.cnt)
break;
}
- self.alpha = self.alphamod * a;
- self.renderflags = 0;
-
R_AddEntity(self);
}
self.velocity_x = ReadCoord();
self.velocity_y = ReadCoord();
self.velocity_z = ReadCoord();
- self.gravity = ReadCoord();
-
+ if(f & 0x10)
+ self.gravity = ReadCoord();
+ else
+ self.gravity = 0; // none
self.move_origin = self.origin;
self.move_velocity = self.velocity;
}
- if(time == self.spawntime || (self.count & 0x80) || (f & 0x10))
+ if(time == self.spawntime || (self.count & 0x80) || (f & 0x08))
{
self.trail_oldorigin = self.origin;
if(!(self.count & 0x80))
self.traileffect = 0;
switch(self.cnt)
{
- case PROJECTILE_ELECTRO: setmodel(self, "models/ebomb.mdl");self.traileffect = particleeffectnum("TR_XONOTICPLASMA"); break;
+ case PROJECTILE_ELECTRO: setmodel(self, "models/ebomb.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
case PROJECTILE_ROCKET: setmodel(self, "models/rocket.md3");self.traileffect = particleeffectnum("TR_ROCKET"); self.scale = 2; break;
case PROJECTILE_BULLET: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_bullet"); break;
case PROJECTILE_BULLET_GLOWING: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_bullet"); break;
case PROJECTILE_BULLET_GLOWING_TRACER: setmodel(self, "models/tracer.mdl");self.traileffect = particleeffectnum("tr_rifle"); break;
case PROJECTILE_CRYLINK: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break;
case PROJECTILE_CRYLINK_BOUNCING: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break;
- case PROJECTILE_ELECTRO_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_XONOTICPLASMA"); break;
+ case PROJECTILE_ELECTRO_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
case PROJECTILE_GRENADE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break;
case PROJECTILE_GRENADE_BOUNCING: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break;
case PROJECTILE_LASER: setmodel(self, "models/laser.mdl");self.traileffect = particleeffectnum(""); break;
case PROJECTILE_HAGAR_BOUNCING: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("TR_GRENADE"); self.scale = 0.4; break;
case PROJECTILE_FIREBALL: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("fireball"); break; // particle effect is good enough
case PROJECTILE_FIREMINE: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("firemine"); break; // particle effect is good enough
+ case PROJECTILE_TAG: setmodel(self, "models/laser.mdl"); self.traileffect = particleeffectnum("TR_ROCKET"); break;
+ case PROJECTILE_FLAC: setmodel(self, "models/hagarmissile.mdl"); self.scale = 0.4; self.traileffect = particleeffectnum("TR_ROCKET"); break;
+ case PROJECTILE_SEEKER: setmodel(self, "models/tagrocket.md3"); self.scale = 2; self.traileffect = particleeffectnum("TR_ROCKET"); break;
default:
error("Received invalid CSQC projectile, can't work with this!");
break;
self.maxs = '0 0 -3';
self.move_movetype = MOVETYPE_BOUNCE;
self.move_touch = SUB_Null;
+ self.move_bounce_factor = g_balance_grenadelauncher_secondary_bouncefactor;
+ self.move_bounce_stopspeed = g_balance_grenadelauncher_secondary_bouncestop;
break;
case PROJECTILE_PORTO_RED:
self.colormod = '2 1 1';
self.mins = '-4 -4 -4';
self.maxs = '4 4 4';
break;
+ case PROJECTILE_TAG:
+ loopsound(self, CHAN_PROJECTILE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTN_NORM);
+ self.mins = '-2 -2 -2';
+ self.maxs = '2 2 2';
+ break;
+ case PROJECTILE_FLAC:
+ self.mins = '-2 -2 -2';
+ self.maxs = '2 2 2';
+ break;
+ case PROJECTILE_SEEKER:
+ self.mins = '-4 -4 -4';
+ self.maxs = '4 4 4';
+ break;
default:
break;
}
precache_model("models/laser.mdl");
precache_model("models/plasmatrail.mdl");
precache_model("models/rocket.md3");
+ precache_model("models/tagrocket.md3");
precache_model("models/tracer.mdl");
precache_sound("weapons/electro_fly.wav");
precache_sound("weapons/rocket_fly.wav");
precache_sound("weapons/fireball_fly.wav");
precache_sound("weapons/fireball_fly2.wav");
+ precache_sound("weapons/tag_rocket_fly.wav");
}
rr = RACE_RECORD;
t = stof(db_get(ClientProgsDB, strcat(shortmapname, rr, "time")));
- if(score && score < t || !t)
+ if(score && (score < t || !t)) {
db_put(ClientProgsDB, strcat(shortmapname, rr, "time"), ftos(score));
+ if(cvar("cl_autodemo_delete_keeprecords"))
+ {
+ f = cvar("cl_autodemo_delete");
+ f &~= 1;
+ cvar_set("cl_autodemo_delete", ftos(f)); // don't delete demo with new record!
+ }
+ }
if(t != crecordtime_prev) {
crecordtime_prev = t;
--- /dev/null
+float music_disabled;
+entity music_default;
+entity music_target;
+entity music_trigger;
+
+.float state;
+.float lastvol;
+
+void TargetMusic_Advance()
+{
+ // run AFTER all the thinks!
+ entity best, e;
+ float vol, vol0;
+ best = music_default;
+ if(music_target && time < music_target.lifetime)
+ best = music_target;
+ if(music_trigger)
+ best = music_trigger;
+ for(e = world; (e = findfloat(e, enttype, ENT_CLIENT_TRIGGER_MUSIC)); ) if(e.noise)
+ {
+ vol0 = e.lastvol;
+ if(getsoundtime(e, CHAN_VOICE) < 0)
+ {
+ vol0 = -1;
+ }
+ if(e == best)
+ {
+ // increase volume
+ if(e.fade_time > 0)
+ e.state = bound(0, e.state + frametime / e.fade_time, 1);
+ else
+ e.state = 1;
+ }
+ else
+ {
+ // decrease volume
+ if(e.fade_rate > 0)
+ e.state = bound(0, e.state - frametime / e.fade_rate, 1);
+ else
+ e.state = 0;
+ }
+ vol = e.state * e.volume * cvar("bgmvolume");
+ if(vol != vol0)
+ {
+ if(vol0 < 0)
+ sound(e, CHAN_VOICE, e.noise, vol, ATTN_NONE); // restart
+ else
+ sound(e, CHAN_VOICE, "", vol, ATTN_NONE);
+ e.lastvol = vol;
+ }
+ }
+ music_trigger = world;
+}
+
+void Net_TargetMusic()
+{
+ float vol, fai, fao, tim, id;
+ string noi;
+ entity e;
+
+ id = ReadShort();
+ vol = ReadByte() / 255.0;
+ fai = ReadByte() / 16.0;
+ fao = ReadByte() / 16.0;
+ tim = ReadByte();
+ noi = ReadString();
+
+ for(e = world; (e = findfloat(e, enttype, ENT_CLIENT_TRIGGER_MUSIC)); )
+ {
+ if(e.count == id)
+ break;
+ }
+ if(!e)
+ {
+ e = spawn();
+ e.enttype = ENT_CLIENT_TRIGGER_MUSIC;
+ e.count = id;
+ }
+ if(e.noise != noi)
+ {
+ if(e.noise)
+ strunzone(e.noise);
+ e.noise = strzone(noi);
+ precache_sound(e.noise);
+ sound(e, CHAN_VOICE, e.noise, 0, ATTN_NONE);
+ if(getsoundtime(e, CHAN_VOICE) < 0)
+ {
+ print("Cannot initialize sound ", e.noise, "\n");
+ strunzone(e.noise);
+ e.noise = string_null;
+ }
+ }
+ e.volume = vol;
+ e.fade_time = fai;
+ e.fade_rate = fao;
+ if(vol > 0)
+ {
+ if(tim == 0)
+ {
+ music_default = e;
+ if(!music_disabled)
+ {
+ e.state = 2;
+ localcmd("cd stop\n"); // just in case
+ music_disabled = 1;
+ }
+ }
+ else
+ {
+ music_target = e;
+ e.lifetime = time + tim;
+ }
+ }
+}
+
+void Ent_TriggerMusic_Think()
+{
+ if(WarpZoneLib_BoxTouchesBrush(view_origin, view_origin, self, world))
+ {
+ music_trigger = self;
+ }
+ self.nextthink = time;
+}
+
+void Ent_TriggerMusic_Remove()
+{
+ if(self.noise)
+ strunzone(self.noise);
+ self.noise = string_null;
+}
+
+void Ent_ReadTriggerMusic()
+{
+ float f;
+ string s;
+ f = ReadByte();
+ if(f & 4)
+ {
+ self.origin_x = ReadCoord();
+ self.origin_y = ReadCoord();
+ self.origin_z = ReadCoord();
+ }
+ if(f & 1)
+ {
+ self.modelindex = ReadShort();
+ if(self.modelindex)
+ {
+ self.mins_x = ReadCoord();
+ self.mins_y = ReadCoord();
+ self.mins_z = ReadCoord();
+ self.maxs_x = ReadCoord();
+ self.maxs_y = ReadCoord();
+ self.maxs_z = ReadCoord();
+ }
+ else
+ {
+ self.mins = '0 0 0';
+ self.maxs_x = ReadCoord();
+ self.maxs_y = ReadCoord();
+ self.maxs_z = ReadCoord();
+ }
+
+ self.volume = ReadByte() / 255.0;
+ self.fade_time = ReadByte() / 16.0;
+ self.fade_rate = ReadByte() / 16.0;
+ s = self.noise;
+ if(self.noise)
+ strunzone(self.noise);
+ self.noise = strzone(ReadString());
+ if(self.noise != s)
+ {
+ precache_sound(self.noise);
+ sound(self, CHAN_VOICE, self.noise, 0, ATTN_NONE);
+ if(getsoundtime(self, CHAN_VOICE) < 0)
+ {
+ print("Cannot initialize sound ", self.noise, "\n");
+ strunzone(self.noise);
+ self.noise = string_null;
+ }
+ }
+ }
+
+ setorigin(self, self.origin);
+ setsize(self, self.mins, self.maxs);
+ self.cnt = 1;
+ self.think = Ent_TriggerMusic_Think;
+ self.nextthink = time;
+}
const float TE_CSQC_VOTE = 108;
const float TE_CSQC_VOTERESET = 109;
const float TE_CSQC_ANNOUNCE = 110;
+const float TE_CSQC_TARGET_MUSIC = 111;
const float RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder
const float RACE_NET_CHECKPOINT_CLEAR = 1;
const float ENT_CLIENT_TUBANOTE = 23;
const float ENT_CLIENT_WARPZONE = 24;
const float ENT_CLIENT_WARPZONE_CAMERA = 25;
+const float ENT_CLIENT_TRIGGER_MUSIC = 26;
const float ENT_CLIENT_TURRET = 40;
const float STAT_SHOTORG = 46; // compressShotOrigin
const float STAT_LEADLIMIT = 47;
const float STAT_BULLETS_LOADED = 48;
+
+// see DP source, quakedef.h
+const float STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW = 222;
+const float STAT_MOVEVARS_AIRSTRAFEACCEL_QW = 223;
+const float STAT_MOVEVARS_AIRACCEL_QW = 254;
+
const float CTF_STATE_ATTACK = 1;
const float CTF_STATE_DEFEND = 2;
const float CTF_STATE_COMMANDER = 3;
const float HUD_NORMAL = 0;
const float HUD_SPIDERBOT = 10;
const float HUD_WAKIZASHI = 11;
+const float HUD_RAPTOR = 12;
const float STAT_VEHICLESTAT_HEALTH = 60;
const float STAT_VEHICLESTAT_SHIELD = 61;
// on world: UNUSED
// on players: voice VOICE
// on entities: ambient AMBIENT
- // on csqc: UNUSED
+ // on csqc: background music BGM
float CHAN_TRIGGER = 3; // Triggers/Items
// on world: UNUSED
// on players: item pickup ITEMS
// this sets sounds and other properties of the projectiles in csqc
float PROJECTILE_ELECTRO = 1;
float PROJECTILE_ROCKET = 2;
+float PROJECTILE_TAG = 3;
float PROJECTILE_BULLET = 4;
float PROJECTILE_CRYLINK = 5;
float PROJECTILE_ELECTRO_BEAM = 6;
float PROJECTILE_GRENADE_BOUNCING = 8;
float PROJECTILE_LASER = 9;
float PROJECTILE_HLAC = 10;
+float PROJECTILE_SEEKER = 11;
+float PROJECTILE_FLAC = 12;
float PROJECTILE_PORTO_RED = 13;
float PROJECTILE_PORTO_BLUE = 14;
float PROJECTILE_HOOKBOMB = 15;
{ }
else if(startsWith(v, "weapon_"))
MapInfo_Map_supportedFeatures |= MAPINFO_FEATURE_WEAPONS;
+ else if(v == "target_music" || v == "trigger_music")
+ _MapInfo_Map_worldspawn_music = string_null; // don't use regular BGM
}
}
}
else
fputs(fh, strcat("cdtrack ", _MapInfo_Map_worldspawn_music, "\n"));
}
- else
+ else if(_MapInfo_Map_worldspawn_music)
{
n = tokenize_console(cvar_string("g_cdtracks_remaplist"));
s = strcat(" ", cvar_string("g_cdtracks_dontusebydefault"), " ");
{
float req;
req = 0;
- if(!(cvar("g_lms") || cvar("g_minstagib") || cvar("g_nixnex") || cvar("g_weaponarena") || !cvar("g_pickup_items") || cvar("g_race") || cvar("g_cts") || cvar("g_nexball")))
+ if(!(cvar("g_lms") || cvar("g_minstagib") || cvar("g_nix") || cvar("g_weaponarena") || !cvar("g_pickup_items") || cvar("g_race") || cvar("g_cts") || cvar("g_nexball")))
req |= MAPINFO_FEATURE_WEAPONS;
return req;
}
return strcasecmp(substring(haystack, 0, strlen(needle)), needle) == 0;
}
-#ifndef MENUQC
-#endif
+string get_model_datafilename(string m, float sk, string fil)
+{
+ if(m)
+ m = strcat(m, "_");
+ else
+ m = "models/player/*_";
+ if(sk >= 0)
+ m = strcat(m, ftos(sk));
+ else
+ m = strcat(m, "*");
+ return strcat(m, ".", fil);
+}
+
+float get_model_parameters(string m, float sk)
+{
+ string fn, s, c;
+ float fh;
+
+ get_model_parameters_modelname = string_null;
+ get_model_parameters_modelskin = -1;
+ get_model_parameters_name = string_null;
+ get_model_parameters_species = -1;
+ get_model_parameters_sex = string_null;
+ get_model_parameters_weight = -1;
+ get_model_parameters_age = -1;
+ get_model_parameters_desc = string_null;
+
+ if not(m)
+ return 1;
+ if(sk < 0)
+ {
+ if(substring(m, -4, -1) != ".txt")
+ return 0;
+ if(substring(m, -6, 1) != "_")
+ return 0;
+ sk = stof(substring(m, -5, 1));
+ m = substring(m, 0, -7);
+ }
+
+ fn = get_model_datafilename(m, sk, "txt");
+ fh = fopen(fn, FILE_READ);
+ if(fh < 0)
+ return 0;
+
+ get_model_parameters_modelname = m;
+ get_model_parameters_modelskin = sk;
+ while((s = fgets(fh)))
+ {
+ if(s == "")
+ break; // next lines will be description
+ c = car(s);
+ s = cdr(s);
+ if(c == "name")
+ get_model_parameters_name = s;
+ if(c == "species")
+ switch(s)
+ {
+ case "human": get_model_parameters_species = SPECIES_HUMAN; break;
+ case "alien": get_model_parameters_species = SPECIES_ALIEN; break;
+ case "robot_shiny": get_model_parameters_species = SPECIES_ROBOT_SHINY; break;
+ case "robot_rusty": get_model_parameters_species = SPECIES_ROBOT_RUSTY; break;
+ case "robot_solid": get_model_parameters_species = SPECIES_ROBOT_SOLID; break;
+ case "animal": get_model_parameters_species = SPECIES_ANIMAL; break;
+ case "reserved": get_model_parameters_species = SPECIES_RESERVED; break;
+ }
+ if(c == "sex")
+ get_model_parameters_sex = s;
+ if(c == "weight")
+ get_model_parameters_weight = stof(s);
+ if(c == "age")
+ get_model_parameters_age = stof(s);
+ }
+
+ while((s = fgets(fh)))
+ {
+ if(get_model_parameters_desc)
+ get_model_parameters_desc = strcat(get_model_parameters_desc, "\n");
+ if(s != "")
+ get_model_parameters_desc = strcat(get_model_parameters_desc, s);
+ }
+
+ fclose(fh);
+
+ return 1;
+}
float matchacl(string acl, string str); // matches str against ACL acl (with entries +foo*, +foo, +*foo, +*foo*, and same with - for forbidding)
float startsWith(string haystack, string needle);
float startsWithNocase(string haystack, string needle);
+
+string get_model_datafilename(string mod, float skn, string fil); // skin -1 will return wildcard, mod string_null will also put wildcard there
+string get_model_parameters_modelname;
+float get_model_parameters_modelskin;
+string get_model_parameters_name;
+float get_model_parameters_species;
+string get_model_parameters_sex;
+float get_model_parameters_weight;
+float get_model_parameters_age;
+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
#endif
#ifdef IMPLEMENTATION
-void configureAnimationAnimation(entity me, entity obj, void(entity, float) setter, float startTime, float duration, float startValue, float end)
+void configureAnimationAnimation(entity me, entity obj, void(entity, float) objSetter, float animStartTime, float animDuration, float animStartValue, float animEndValue)
{
- me.setObjectSetter(me, obj, setter);
- me.setTimeStartDuration(me, startTime, duration);
- me.setValueStartEnd(me, startValue, end);
+ me.setObjectSetter(me, obj, objSetter);
+ me.setTimeStartDuration(me, animStartTime, animDuration);
+ me.setValueStartEnd(me, animStartValue, animEndValue);
}
void setTimeStartEndAnimation(entity me, float s, float e)
me.setter = s;
}
-void tickAnimation(entity me, float time)
+void tickAnimation(entity me, float tickTime)
{
- if (me.isStopped(me) || me.isFinished(me) || (time < me.startTime))
+ if (me.isStopped(me) || me.isFinished(me) || (tickTime < me.startTime))
return;
- if (time >= (me.startTime + me.duration))
+ if (tickTime >= (me.startTime + me.duration))
me.finishAnim(me);
else
- me.value = me.calcValue(me, (time - me.startTime), me.duration, me.startValue, me.delta);
+ me.value = me.calcValue(me, (tickTime - me.startTime), me.duration, me.startValue, me.delta);
me.setter(me.object, me.value);
}
-float calcValueAnimation(entity me, float time, float duration, float startValue, float delta)
+float calcValueAnimation(entity me, float tickTime, float animDuration, float animStartValue, float animDelta)
{
- return startValue;
+ return animStartValue;
}
float isStoppedAnimation(entity me)
{
me.value = me.delta + me.startValue;
me.finished = TRUE;
+ me.setter(me.object, me.value);
}
-void setterDummy(entity object, float value)
+void setterDummy(entity obj, float objValue)
{
}
CLASS(AnimHost) EXTENDS(Object)
METHOD(AnimHost, addAnim, void(entity, entity))
METHOD(AnimHost, removeAnim, void(entity, entity))
+ METHOD(AnimHost, removeAllAnim, void(entity))
+ METHOD(AnimHost, removeObjAnim, void(entity, entity))
METHOD(AnimHost, stopAllAnim, void(entity))
+ METHOD(AnimHost, stopObjAnim, void(entity, entity))
+ METHOD(AnimHost, resumeAllAnim, void(entity))
+ METHOD(AnimHost, resumeObjAnim, void(entity, entity))
METHOD(AnimHost, finishAllAnim, void(entity))
+ METHOD(AnimHost, finishObjAnim, void(entity, entity))
METHOD(AnimHost, tickAll, void(entity))
ATTRIB(AnimHost, firstChild, entity, NULL)
ATTRIB(AnimHost, lastChild, entity, NULL)
me.lastChild = p;
}
+void removeAllAnimAnimHost(entity me)
+{
+ entity e, tmp;
+ for(e = me.firstChild; e; e = e.nextSibling)
+ {
+ tmp = e;
+ e = tmp.prevSibling;
+ me.removeAnim(me, tmp);
+ }
+}
+
+void removeObjAnimAnimHost(entity me, entity obj)
+{
+ entity e, tmp;
+ for(e = me.firstChild; e; e = e.nextSibling)
+ {
+ if (e.object == obj)
+ {
+ tmp = e;
+ e = tmp.prevSibling;
+ me.removeAnim(me, tmp);
+ }
+ }
+}
+
void stopAllAnimAnimHost(entity me)
{
entity e;
}
}
+void stopObjAnimAnimHost(entity me, entity obj)
+{
+ entity e;
+ for(e = me.firstChild; e; e = e.nextSibling)
+ {
+ if (e.object == obj)
+ {
+ e.stopAnim(e);
+ }
+ }
+}
+
+void resumeAllAnimAnimHost(entity me)
+{
+ entity e;
+ for(e = me.firstChild; e; e = e.nextSibling)
+ {
+ e.resumeAnim(e);
+ }
+}
+
+void resumeObjAnimAnimHost(entity me, entity obj)
+{
+ entity e;
+ for(e = me.firstChild; e; e = e.nextSibling)
+ {
+ if (e.object == obj)
+ {
+ e.resumeAnim(e);
+ }
+ }
+}
+
void finishAllAnimAnimHost(entity me)
{
entity e, tmp;
tmp = e;
e = tmp.prevSibling;
me.removeAnim(me, tmp);
- e.finishAnim(tmp);
+ tmp.finishAnim(tmp);
+ }
+}
+
+void finishObjAnimAnimHost(entity me, entity obj)
+{
+ entity e, tmp;
+ for(e = me.firstChild; e; e = e.nextSibling)
+ {
+ if (e.object == obj)
+ {
+ tmp = e;
+ e = tmp.prevSibling;
+ me.removeAnim(me, tmp);
+ tmp.finishAnim(tmp);
+ }
}
}
#endif
#ifdef IMPLEMENTATION
-entity makeHostedEasing(entity obj, void(entity, float) setter, float(float, float, float, float) func, float duration, float startValue, float end)
+entity makeHostedEasing(entity obj, void(entity, float) objSetter, float(float, float, float, float) func, float animDuration, float animStartValue, float animEnd)
{
entity me;
- me = makeEasing(obj, setter, func, time, duration, startValue, end);
+ me = makeEasing(obj, objSetter, func, time, animDuration, animStartValue, animEnd);
anim.addAnim(anim, me);
return me;
}
-entity makeEasing(entity obj, void(entity, float) setter, float(float, float, float, float) func, float startTime, float duration, float startValue, float end)
+entity makeEasing(entity obj, void(entity, float) objSetter, float(float, float, float, float) func, float animStartTime, float animDuration, float animStartValue, float animEnd)
{
entity me;
me = spawnEasing();
- me.configureAnimation(me, obj, setter, startTime, duration, startValue, end);
+ me.configureAnimation(me, obj, objSetter, animStartTime, animDuration, animStartValue, animEnd);
me.setMath(me, func);
return me;
}
-float calcValueEasing(entity me, float time, float duration, float start, float delta)
+float calcValueEasing(entity me, float tickTime, float animDuration, float animStart, float animDelta)
{
- return me.math(time, duration, start, delta);
+ return me.math(tickTime, animDuration, animStart, animDelta);
}
void setMathEasing(entity me, float(float, float, float, float) func)
me.math = func;
}
-float easingLinear(float time, float duration, float start, float delta)
+float easingLinear(float tickTime, float animDuration, float animStart, float animDelta)
{
- return (delta * (time / duration)) + start;
+ return (animDelta * (tickTime / animDuration)) + animStart;
}
-float easingQuadIn(float time, float duration, float start, float delta)
+float easingQuadIn(float tickTime, float animDuration, float animStart, float animDelta)
{
- float frac = time / duration;
- return (delta * frac * frac) + start;
+ float frac = tickTime / animDuration;
+ return (animDelta * frac * frac) + animStart;
}
-float easingQuadOut(float time, float duration, float start, float delta)
+float easingQuadOut(float tickTime, float animDuration, float animStart, float animDelta)
{
- float frac = time / duration;
- return (-delta * frac * (frac - 2)) + start;
+ float frac = tickTime / animDuration;
+ return (-animDelta * frac * (frac - 2)) + animStart;
}
-float easingQuadInOut(float time, float duration, float start, float delta)
+float easingQuadInOut(float tickTime, float animDuration, float animStart, float animDelta)
{
- if (time < (duration / 2))
+ if (tickTime < (animDuration / 2))
{
- return easingQuadIn(time, (duration / 2), start, (delta / 2));
+ return easingQuadIn(tickTime, (animDuration / 2), animStart, (animDelta / 2));
}
else
{
- return easingQuadOut((time - (duration / 2)), (duration / 2), (start + (delta / 2)), (delta / 2));
+ return easingQuadOut((tickTime - (animDuration / 2)), (animDuration / 2), (animStart + (animDelta / 2)), (animDelta / 2));
}
}
#ifdef INTERFACE
CLASS(Keyframe) EXTENDS(Animation)
+ METHOD(Keyframe, addEasing, entity(entity, float, float, float(float, float, float, float)))
METHOD(Keyframe, addAnim, void(entity, entity))
METHOD(Keyframe, calcValue, float(entity, float, float, float, float))
ATTRIB(Keyframe, currentChild, entity, NULL)
ENDCLASS(Animation)
entity makeHostedKeyframe(entity, void(entity, float), float, float, float);
entity makeKeyframe(entity, void(entity, float), float, float, float);
+float getNewChildStart(entity);
+float getNewChildDuration(entity, float);
+float getNewChildValue(entity);
#endif
#ifdef IMPLEMENTATION
-entity makeHostedKeyframe(entity obj, void(entity, float) setter, float duration, float start, float end)
+entity makeHostedKeyframe(entity obj, void(entity, float) objSetter, float animDuration, float animStart, float animEnd)
{
entity me;
- me = makeKeyframe(obj, setter, duration, start, end);
+ me = makeKeyframe(obj, objSetter, animDuration, animStart, animEnd);
anim.addAnim(anim, me);
return me;
}
-entity makeKeyframe(entity obj, void(entity, float) setter, float duration, float start, float end)
+entity makeKeyframe(entity obj, void(entity, float) objSetter, float animDuration, float animStart, float animEnd)
{
entity me;
me = spawnKeyframe();
- me.configureAnimation(me, obj, setter, time, duration, start, end);
+ me.configureAnimation(me, obj, objSetter, time, animDuration, animStart, animEnd);
return me;
}
+entity addEasingKeyframe(entity me, float animDurationTime, float animEnd, float(float, float, float, float) func)
+{
+ entity other;
+ other = makeEasing(me.object, me.setter, func, getNewChildStart(me), getNewChildDuration(me, animDurationTime), getNewChildValue(me), animEnd);
+ me.addAnim(me, other);
+ return other;
+}
+
+float getNewChildStart(entity me)
+{
+ if (me.lastChild)
+ return (me.lastChild.startTime + me.lastChild.duration);
+ else
+ return 0;
+}
+
+float getNewChildDuration(entity me, float durationTime)
+{
+ float dura, maxDura;
+ maxDura = me.duration;
+ if (me.lastChild) maxDura = maxDura - (me.lastChild.startTime + me.lastChild.duration);
+ dura = durationTime;
+ if (0 >= dura || dura > maxDura) dura = maxDura;
+ return dura;
+}
+
+float getNewChildValue(entity me)
+{
+ if (me.lastChild)
+ return (me.lastChild.startValue + me.lastChild.delta);
+ else
+ return me.startValue;
+}
+
void addAnimKeyframe(entity me, entity other)
{
if(other.parent)
me.lastChild = other;
}
-float calcValueKeyframe(entity me, float time, float duration, float startValue, float delta)
+float calcValueKeyframe(entity me, float tickTime, float animDuration, float animStartValue, float animDelta)
{
if (me.currentChild)
if (me.currentChild.isFinished(me.currentChild))
if (me.currentChild)
{
- me.currentChild.tick(me.currentChild, time);
+ me.currentChild.tick(me.currentChild, tickTime);
return me.currentChild.value;
}
- return startValue + delta;
+ return animStartValue + animDelta;
}
#endif
METHOD(Image, draw, void(entity))
METHOD(Image, toString, string(entity))
METHOD(Image, resizeNotify, void(entity, vector, vector, vector, vector))
+ METHOD(Image, updateAspect, void(entity))
ATTRIB(Image, src, string, string_null)
ATTRIB(Image, color, vector, '1 1 1')
ATTRIB(Image, forcedAspect, float, 0)
{
draw_Picture(me.imgOrigin, me.src, me.imgSize, me.color, 1);
}
-void resizeNotifyImage(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
+void updateAspectImage(entity me)
{
- resizeNotifyItem(me, relOrigin, relSize, absOrigin, absSize);
+ float asp;
+ if(me.size_x <= 0 || me.size_y <= 0)
+ return;
if(me.forcedAspect == 0)
{
me.imgOrigin = '0 0 0';
}
else
{
- if(absSize_x > me.forcedAspect * absSize_y)
+ if(me.forcedAspect < 0)
+ {
+ vector sz;
+ sz = draw_PictureSize(me.src);
+ asp = sz_x / sz_y;
+ }
+ else
+ asp = me.forcedAspect;
+ if(me.size_x > asp * me.size_y)
{
// x too large, so center x-wise
- me.imgSize = eY + eX * (absSize_y * me.forcedAspect / absSize_x);
+ me.imgSize = eY + eX * (me.size_y * asp / me.size_x);
}
else
{
// y too large, so center y-wise
- me.imgSize = eX + eY * (absSize_x / (me.forcedAspect * absSize_y));
+ me.imgSize = eX + eY * (me.size_x / (asp * me.size_y));
}
me.imgOrigin = '0.5 0.5 0' - 0.5 * me.imgSize;
}
}
+void resizeNotifyImage(entity me, vector relOrigin, vector relSize, vector absOrigin, vector absSize)
+{
+ resizeNotifyItem(me, relOrigin, relSize, absOrigin, absSize);
+ me.updateAspect(me);
+}
#endif
if(hit)
{
// calculate new pos to v
- float delta;
- delta = (pos_y - me.pressOffset) / (1 - (me.controlBottom - me.controlTop)) * (me.nItems * me.itemHeight - 1);
- me.scrollPos = me.previousValue + delta;
+ float d;
+ d = (pos_y - me.pressOffset) / (1 - (me.controlBottom - me.controlTop)) * (me.nItems * me.itemHeight - 1);
+ me.scrollPos = me.previousValue + d;
}
else
me.scrollPos = me.previousValue;
METHOD(Slider, valueToText, string(entity, float))
METHOD(Slider, toString, string(entity))
METHOD(Slider, setValue, void(entity, float))
+ METHOD(Slider, setSliderValue, void(entity, float))
METHOD(Slider, showNotify, void(entity))
ATTRIB(Slider, src, string, string_null)
ATTRIB(Slider, focusable, float, 1)
ATTRIB(Slider, value, float, 0)
+ ATTRIB(Slider, animated, float, 1)
+ ATTRIB(Slider, sliderValue, float, 0)
ATTRIB(Slider, valueMin, float, 0)
ATTRIB(Slider, valueMax, float, 0)
ATTRIB(Slider, valueStep, float, 0)
#ifdef IMPLEMENTATION
void setValueSlider(entity me, float val)
{
+ if (me.animated) {
+ anim.stopObjAnim(anim, me);
+ anim.removeObjAnim(anim, me);
+ makeHostedEasing(me, setSliderValueSlider, easingQuadInOut, 1, me.sliderValue, val);
+ } else {
+ me.setSliderValue(me, val);
+ }
me.value = val;
}
+void setSliderValueSlider(entity me, float val)
+{
+ me.sliderValue = val;
+}
string toStringSlider(entity me)
{
return strcat(ftos(me.value), " (", me.valueToText(me, me.value), ")");
void configureSliderValuesSlider(entity me, float theValueMin, float theValue, float theValueMax, float theValueStep, float theValueKeyStep, float theValuePageStep)
{
me.value = theValue;
+ me.sliderValue = theValue;
me.valueStep = theValueStep;
me.valueMin = theValueMin;
me.valueMax = theValueMax;
float mouseDragSlider(entity me, vector pos)
{
float hit;
- float v;
+ float v, animed;
if(me.disabled)
return 0;
+
+ anim.finishObjAnim(anim, me);
+ animed = me.animated;
+ me.animated = false;
+
if(me.pressed)
{
hit = 1;
else
me.setValue(me, me.previousValue);
}
+
+ me.animated = animed;
+
return 1;
}
float mousePressSlider(entity me, vector pos)
if(me.disabled)
draw_alpha *= me.disabledAlpha;
draw_ButtonPicture('0 0 0', strcat(me.src, "_s"), eX * (1 - me.textSpace) + eY, me.color2, 1);
- if(almost_in_bounds(me.valueMin, me.value, me.valueMax))
+ if(almost_in_bounds(me.valueMin, me.sliderValue, me.valueMax))
{
- controlLeft = (me.value - me.valueMin) / (me.valueMax - me.valueMin) * (1 - me.textSpace - me.controlWidth);
+ controlLeft = (me.sliderValue - me.valueMin) / (me.valueMax - me.valueMin) * (1 - me.textSpace - me.controlWidth);
if(me.disabled)
draw_Picture(eX * controlLeft, strcat(me.src, "_d"), eX * me.controlWidth + eY, me.colorD, 1);
else if(me.pressed)
drawLabel(me);
me.text = string_null; // TEMPSTRING!
}
-#endif
\ No newline at end of file
+#endif
for(i = 0; i < me.nValues; ++i)
if(me.valueToIdentifier(me, i) == id)
{
- me.value = i;
+ setValueSlider( me, i );
return;
}
- me.value = -1;
+ setValueSlider( me, -1 );
}
string getIdentifierTextSlider(entity me)
{
#define GETGAMEDIRINFO_NAME 0
#define GETGAMEDIRINFO_DESCRIPTION 1
float log(float f) = #532;
+
+string(string format, ...) sprintf = #627;
check_unacceptable_compiler_bugs();
+#ifdef WATERMARK
+ print("^4MQC Build information: ", WATERMARK(), "\n");
+#endif
+
// list all game dirs (TEST)
if(cvar("developer"))
{
{
string s;
s = "";
+ if(cvar("g_dodging"))
+ s = strcat(s, ", Dodging");
if(cvar("g_minstagib"))
s = strcat(s, ", MinstaGib");
- if(cvar("g_nixnex"))
- s = strcat(s, ", NixNex");
+ if(cvar("g_nix"))
+ s = strcat(s, ", NIX");
if(cvar_string("g_weaponarena") != "0")
s = strcat(s, ", ", WeaponArenaString());
if(cvar("g_start_weapon_laser") == 0)
string str, hstr;
me.TR(me);
me.TD(me, 1, 2, makeXonoticTextLabel(0, "Gameplay mutators:"));
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_dodging", "Dodging"));
me.TR(me);
me.TDempty(me, 0.2);
me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "g_cloaked", "Cloaked"));
me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "g_minstagib", string_null, "MinstaGib"));
me.TR(me);
me.TDempty(me, 0.2);
- me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "g_nixnex", string_null, "NixNex"));
+ me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "g_nix", string_null, "NIX"));
me.TR(me);
me.TDempty(me, 0.4);
- me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "g_nixnex_with_laser", "with laser"));
- setDependent(e, "g_nixnex", 1, 1);
+ me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "g_nix_with_laser", "with laser"));
+ setDependent(e, "g_nix", 1, 1);
me.TR(me);
me.TDempty(me, 0.2);
me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "g_weaponarena", "most", "Most weapons"));
me.TR(me);
me.gotoRC(me, me.rows - 1, 0);
- me.TD(me, 1, me.columns, makeXonoticCommandButton("Apply immediately", '0 0 0', "color -1 -1;name \"$_cl_name\";cl_cmd sendcvar cl_weaponpriority;sendcvar cl_zoomfactor;sendcvar cl_zoomspeed;sendcvar cl_autoswitch;sendcvar cl_shownames;sendcvar cl_forceplayermodelsfromxonotic;sendcvar cl_forceplayermodels", COMMANDBUTTON_APPLY));
+ me.TD(me, 1, me.columns, makeXonoticCommandButton("Apply immediately", '0 0 0', "color -1 -1;name \"$_cl_name\";cl_cmd sendcvar cl_weaponpriority;sendcvar cl_zoomfactor;sendcvar cl_zoomspeed;sendcvar cl_autoswitch;sendcvar cl_shownames;sendcvar cl_forceplayermodelsfromxonotic;sendcvar cl_forceplayermodels;playermodel $_cl_playermodel;playerskin $_cl_playerskin", COMMANDBUTTON_APPLY));
}
#endif
entity e, s, sl;
me.TR(me);
- s = makeXonoticDecibelsSlider(-20, 0, 0.5, "bgmvolume");
- me.TD(me, 1, 1, e = makeXonoticSliderCheckBox(-1000000, 1, s, "Music:"));
+ s = makeXonoticDecibelsSlider(-20, 0, 0.5, "mastervolume");
+ me.TD(me, 1, 1, e = makeXonoticSliderCheckBox(-1000000, 1, s, "Master:"));
me.TD(me, 1, 2, s);
me.TR(me);
- me.TR(me);
- s = makeXonoticDecibelsSlider(-20, 0, 0.5, "volume");
- me.TD(me, 1, 1, e = makeXonoticSliderCheckBox(-1000000, 1, s, "Master:"));
+ me.TDempty(me, 0.2);
+ s = makeXonoticDecibelsSlider(-20, 0, 0.5, "bgmvolume");
+ makeMulti(s, "snd_csqcchannel2volume");
+ me.TD(me, 1, 0.8, e = makeXonoticSliderCheckBox(-1000000, 1, s, "Music:"));
me.TD(me, 1, 2, s);
me.TR(me);
me.TDempty(me, 0.2);
me.TR(me);
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Particle quality:"));
- me.TD(me, 1, 2, e = makeXonoticSlider(0.1, 1.0, 0.05, "cl_particles_quality"));
+ me.TD(me, 1, 2, e = makeXonoticSlider(0.2, 1.0, 0.1, "cl_particles_quality"));
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Particle dist.:"));
me.TD(me, 1, 2, e = makeXonoticSlider(500, 2000, 100, "r_drawparticles_drawdistance"));
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticCheckBox(0, "r_bloom", "Bloom"));
setDependent(e, "r_hdr", 0, 0);
- me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "r_hdr", "High Dynamic Range (HDR)"));
+ me.TD(me, 1, 2, e = makeXonoticCheckBoxEx(2, 0, "r_hdr", "High Dynamic Range (HDR)"));
me.TR(me);
s = makeXonoticSlider(0.1, 1, 0.1, "r_motionblur");
void configureXonoticImageXonoticImage(entity me, string theImage, float theAspect)
{
me.configureImage(me, theImage);
- if(theAspect < 0) // use image aspect
- {
- vector sz;
- sz = draw_PictureSize(theImage);
- me.forcedAspect = sz_x / sz_y;
- }
- else
- me.forcedAspect = theAspect;
+ me.forcedAspect = theAspect;
}
#endif
METHOD(XonoticPlayerModelSelector, resizeNotify, void(entity, vector, vector, vector, vector))
ATTRIB(XonoticPlayerModelSelector, currentModel, string, string_null)
ATTRIB(XonoticPlayerModelSelector, currentSkin, float, 0)
- ATTRIB(XonoticPlayerModelSelector, currentModelName, string, string_null)
+ ATTRIB(XonoticPlayerModelSelector, currentModelImage, string, string_null)
ATTRIB(XonoticPlayerModelSelector, currentModelTitle, string, string_null)
- ATTRIB(XonoticPlayerModelSelector, currentModelTxtName, string, string_null)
ATTRIB(XonoticPlayerModelSelector, currentModelDescription, string, string_null)
METHOD(XonoticPlayerModelSelector, go, void(entity, float))
+ METHOD(XonoticPlayerModelSelector, destroy, void(entity))
ATTRIB(XonoticPlayerModelSelector, origin, vector, '0 0 0')
ATTRIB(XonoticPlayerModelSelector, size, vector, '0 0 0')
ATTRIB(XonoticPlayerModelSelector, realFontSize, vector, '0 0 0')
ATTRIB(XonoticPlayerModelSelector, fontSize, float, SKINFONTSIZE_NORMAL)
ATTRIB(XonoticPlayerModelSelector, titleFontSize, float, SKINFONTSIZE_TITLE)
+ ATTRIB(XonoticPlayerModelSelector, bufModels, float, -1)
+ ATTRIB(XonoticPlayerModelSelector, numModels, float, -1)
+ ATTRIB(XonoticPlayerModelSelector, idxModels, float, -1)
ENDCLASS(XonoticPlayerModelSelector)
entity makeXonoticPlayerModelSelector();
void PlayerModelSelector_Next_Click(entity btn, entity me);
return me;
}
+#define BUFMODELS_TITLE 0
+#define BUFMODELS_IMAGE 1
+#define BUFMODELS_MODEL 2
+#define BUFMODELS_SKIN 3
+#define BUFMODELS_DESC 4
+#define BUFMODELS_COUNT 5
+
void configureXonoticPlayerModelSelectorXonoticPlayerModelSelector(entity me)
{
- me.configureXonoticImage(me, string_null, 263.0/360.0);
+ float sortbuf, glob, i;
+ string fn;
+
+ me.configureXonoticImage(me, string_null, -1);
+
+ sortbuf = buf_create();
+ glob = search_begin(get_model_datafilename(string_null, -1, "txt"), TRUE, TRUE);
+ for(i = 0; i < search_getsize(glob); ++i)
+ {
+ // select model #i!
+ fn = search_getfilename(glob, i);
+ if(!get_model_parameters(fn, -1))
+ continue;
+ bufstr_add(sortbuf, sprintf("%-128s%s", get_model_parameters_name, fn), 1);
+ }
+ search_end(glob);
+ buf_sort(sortbuf, 128, 0);
+ me.numModels = buf_getsize(sortbuf);
+ me.bufModels = buf_create();
+ for(i = 0; i < me.numModels; ++i)
+ {
+ fn = substring(bufstr_get(sortbuf, i), 128, -1);
+ if(!get_model_parameters(fn, -1))
+ error("But it JUST worked!");
+ bufstr_set(me.bufModels, BUFMODELS_COUNT*i+BUFMODELS_TITLE, get_model_parameters_name);
+ bufstr_set(me.bufModels, BUFMODELS_COUNT*i+BUFMODELS_IMAGE, strcat("/", substring(get_model_datafilename(get_model_parameters_modelname, get_model_parameters_modelskin, "tga"), 0, -5)));
+ bufstr_set(me.bufModels, BUFMODELS_COUNT*i+BUFMODELS_MODEL, get_model_parameters_modelname);
+ bufstr_set(me.bufModels, BUFMODELS_COUNT*i+BUFMODELS_SKIN, ftos(get_model_parameters_modelskin));
+ get_model_parameters_desc = strcat(get_model_parameters_desc, "\n");
+ if(get_model_parameters_sex)
+ get_model_parameters_desc = strcat(get_model_parameters_desc, "\nSex: ", get_model_parameters_sex);
+ if(get_model_parameters_weight)
+ get_model_parameters_desc = strcat(get_model_parameters_desc, "\nWeight: ", ftos(get_model_parameters_weight), " kg");
+ if(get_model_parameters_age)
+ get_model_parameters_desc = strcat(get_model_parameters_desc, "\nAge: ", ftos(get_model_parameters_age));
+ while(substring(get_model_parameters_desc, -1, 1) == "\n")
+ get_model_parameters_desc = substring(get_model_parameters_desc, 0, -2);
+ bufstr_set(me.bufModels, BUFMODELS_COUNT*i+BUFMODELS_DESC, get_model_parameters_desc);
+ }
+ buf_del(sortbuf);
+ get_model_parameters(string_null, 0);
me.loadCvars(me);
}
+void destroyXonoticPlayerModelSelector(entity me)
+{
+ buf_del(me.bufModels);
+ me.bufModels = -1;
+}
void loadCvarsXonoticPlayerModelSelector(entity me)
{
- float glob, i, fh;
- string fn;
- string nm, t, l;
-
+ float i;
if(me.currentModel)
strunzone(me.currentModel);
- if(me.currentModelTitle)
- strunzone(me.currentModelTitle);
- if(me.currentModelName)
- strunzone(me.currentModelName);
- if(me.currentModelTxtName)
- strunzone(me.currentModelTxtName);
- if(me.currentModelDescription)
- strunzone(me.currentModelDescription);
me.currentSkin = cvar("_cl_playerskin");
me.currentModel = strzone(cvar_string("_cl_playermodel"));
- me.currentModelName = string_null;
- me.currentModelDescription = string_null;
- me.currentModelTitle = string_null;
- me.currentModelTxtName = string_null;
-
- // lookup model name
- glob = search_begin("models/player/*.txt", TRUE, TRUE);
- if(glob < 0)
- return;
- for(i = 0; i < search_getsize(glob); ++i)
+ for(i = 0; i < me.numModels; ++i)
{
- fn = search_getfilename(glob, i);
- fh = fopen(fn, FILE_READ);
- if(fh < 0)
- continue;
- t = fgets(fh);
- nm = fgets(fh);
- if(stof(fgets(fh)) == me.currentSkin)
- if(fgets(fh) == me.currentModel)
- {
- me.currentModelName = strzone(strcat("/", nm));
- me.currentModelTxtName = strzone(fn);
- me.currentModelTitle = strzone(t);
- me.currentModelDescription = "";
- fgets(fh); // Skip species
- while((l = fgets(fh)))
- {
- if(me.currentModelDescription != "")
- me.currentModelDescription = strcat(me.currentModelDescription, "\n");
- me.currentModelDescription = strcat(me.currentModelDescription, l);
- }
- me.currentModelDescription = strzone(me.currentModelDescription);
- fclose(fh);
+ if(bufstr_get(me.bufModels, BUFMODELS_COUNT*i+BUFMODELS_MODEL) == me.currentModel)
+ if(bufstr_get(me.bufModels, BUFMODELS_COUNT*i+BUFMODELS_SKIN) == ftos(me.currentSkin))
break;
- }
- fclose(fh);
}
- search_end(glob);
+ if(i >= me.numModels) // fail
+ i = 0;
+ me.idxModels = i;
+ me.go(me, 0); // this will set the other vars for currentSkin and currentModel
}
void goXonoticPlayerModelSelector(entity me, float d)
{
- float glob, i, fh;
- string l;
-
- glob = search_begin("models/player/*.txt", TRUE, TRUE);
- if(glob < 0)
- return;
- for(i = 0; i < search_getsize(glob); ++i)
- if(search_getfilename(glob, i) == me.currentModelTxtName)
- break;
- // now i is search_getsize(glob) if not found, and the right index if found.
- if(i == search_getsize(glob))
- {
- if(d < 0)
- i = search_getsize(glob) - 1;
- else
- i = 0;
- }
- else
- {
- i = mod(i + d + search_getsize(glob), search_getsize(glob));
- }
+ me.idxModels = mod(me.idxModels + d + me.numModels, me.numModels);
if(me.currentModel)
strunzone(me.currentModel);
if(me.currentModelTitle)
strunzone(me.currentModelTitle);
- if(me.currentModelName)
- strunzone(me.currentModelName);
- if(me.currentModelTxtName)
- strunzone(me.currentModelTxtName);
+ if(me.currentModelImage)
+ strunzone(me.currentModelImage);
if(me.currentModelDescription)
strunzone(me.currentModelDescription);
// select model #i!
- me.currentModelTxtName = strzone(search_getfilename(glob, i));
- fh = fopen(me.currentModelTxtName, FILE_READ);
- search_end(glob);
- if(fh < 0)
- return;
- me.currentModelTitle = strzone(fgets(fh));
- me.currentModelName = strzone(strcat("/", fgets(fh)));
- me.currentSkin = stof(fgets(fh));
- me.currentModel = strzone(fgets(fh));
- me.currentModelDescription = "";
- fgets(fh); // Skip species
- while((l = fgets(fh)))
- {
- if(me.currentModelDescription != "")
- me.currentModelDescription = strcat(me.currentModelDescription, "\n");
- me.currentModelDescription = strcat(me.currentModelDescription, l);
- }
- me.currentModelDescription = strzone(me.currentModelDescription);
- fclose(fh);
+ me.currentModelTitle = strzone(bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_TITLE));
+ me.currentModelImage = strzone(bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_IMAGE));
+ me.currentSkin = stof(bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_SKIN));
+ me.currentModel = strzone(bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_MODEL));
+ me.currentModelDescription = strzone(bufstr_get(me.bufModels, BUFMODELS_COUNT*me.idxModels+BUFMODELS_DESC));
+
+ // fix the image
+ me.src = me.currentModelImage;
+ me.updateAspect(me);
}
void PlayerModelSelector_Next_Click(entity btn, entity me)
void saveCvarsXonoticPlayerModelSelector(entity me)
{
- // TODO rather set the _cl ones and apply later?
- localcmd(strcat("playermodel ", me.currentModel, "\nplayerskin ", ftos(me.currentSkin), "\n"));
+ // we can't immediately apply here because of flood control
+ cvar_set("_cl_playermodel", me.currentModel);
+ cvar_set("_cl_playerskin", ftos(me.currentSkin));
}
void drawXonoticPlayerModelSelector(entity me)
float i, n;
vector o;
- me.src = me.currentModelName;
drawImage(me);
- me.src = string_null;
// draw text on the image, handle \n in the description
draw_CenterText('0.5 0 0', me.currentModelTitle, me.realFontSize * (me.titleFontSize / me.fontSize), SKINCOLOR_MODELTITLE, SKINALPHA_MODELTITLE, FALSE);
{
if(val != me.value)
{
- me.value = val;
+ setValueSlider( me, val );
me.saveCvars(me);
}
}
if not(me.cvarName)
return;
- me.value = cvar(me.cvarName);
+ me.setValue( me, cvar(me.cvarName) );
}
void saveCvarsXonoticSlider(entity me)
{
v = cvar(me.cvarName);
if(v >= 0.98)
- me.value = 0;
+ setValueSlider( me, 0 );
else if(v < 0.0005)
- me.value = -1000000;
+ setValueSlider( me, -1000000 );
else
- me.value = 0.1 * floor(0.5 + 10.0 * log10(cvar(me.cvarName)) * 10);
+ setValueSlider( me, 0.1 * floor(0.5 + 10.0 * log10(cvar(me.cvarName)) * 10) );
}
void saveCvarsXonoticDecibelsSlider(entity me)
{
{
if(val != me.value)
{
- me.value = val;
+ setValueSlider( me, val );
me.saveCvars(me);
}
}
string campaign_name_previous;
float campaign_won_previous;
+#ifdef WATERMARK
+var string autocvar_menu_watermark = WATERMARK();
+#else
+var string autocvar_menu_watermark = "";
+#endif
void postMenuDraw()
{
+ if(autocvar_menu_watermark != "")
+ {
+ vector fs = '48 48 0';
+ draw_CenterText('0.5 0.1 0', autocvar_menu_watermark, globalToBoxSize('32 32 0', draw_scale), '1 1 1', 0.05, 1);
+ }
}
void preMenuDraw()
{
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="qc-client" />
+ <Option makefile="client" />
+ <Option makefile_is_custom="1" />
+ <Option pch_mode="2" />
+ <Option compiler="qaukec" />
+ <Build>
+ <Target title="Debug">
+ <Option output="bin\Debug\qc-server" prefix_auto="1" extension_auto="1" />
+ <Option object_output="obj\Debug\" />
+ <Option type="1" />
+ <Option compiler="qaukec" />
+ <Compiler>
+ <Add option="-g" />
+ </Compiler>
+ <MakeCommands>
+ <Build command="$make -src $makefile" />
+ <CompileFile command="" />
+ <Clean command="" />
+ <DistClean command="" />
+ </MakeCommands>
+ </Target>
+ <Target title="Release">
+ <Option output="bin\Release\qc-server" prefix_auto="1" extension_auto="1" />
+ <Option object_output="obj\Release\" />
+ <Option type="1" />
+ <Option compiler="qaukec" />
+ <Compiler>
+ <Add option="-O2" />
+ </Compiler>
+ <Linker>
+ <Add option="-s" />
+ </Linker>
+ <MakeCommands>
+ <Build command="$make -src $makefile" />
+ <CompileFile command="" />
+ <Clean command="" />
+ <DistClean command="" />
+ </MakeCommands>
+ </Target>
+ </Build>
+ <Compiler>
+ <Add option="-Wall" />
+ </Compiler>
+ <Unit filename="client\Defs.qc" />
+ <Unit filename="client\Main.qc" />
+ <Unit filename="client\View.qc" />
+ <Unit filename="client\autocvars.qh" />
+ <Unit filename="client\bgmscript.qc" />
+ <Unit filename="client\bgmscript.qh" />
+ <Unit filename="client\casings.qc" />
+ <Unit filename="client\csqc_builtins.qc" />
+ <Unit filename="client\csqc_constants.qc" />
+ <Unit filename="client\ctf.qc" />
+ <Unit filename="client\damage.qc" />
+ <Unit filename="client\effects.qc" />
+ <Unit filename="client\gibs.qc" />
+ <Unit filename="client\hook.qc" />
+ <Unit filename="client\interpolate.qc" />
+ <Unit filename="client\interpolate.qh" />
+ <Unit filename="client\laser.qc" />
+ <Unit filename="client\main.qh" />
+ <Unit filename="client\mapvoting.qc" />
+ <Unit filename="client\miscfunctions.qc" />
+ <Unit filename="client\modeleffects.qc" />
+ <Unit filename="client\movetypes.qc" />
+ <Unit filename="client\movetypes.qh" />
+ <Unit filename="client\particles.qc" />
+ <Unit filename="client\prandom.qc" />
+ <Unit filename="client\prandom.qh" />
+ <Unit filename="client\pre.qh" />
+ <Unit filename="client\progs.src" />
+ <Unit filename="client\projectile.qc" />
+ <Unit filename="client\rubble.qc" />
+ <Unit filename="client\sbar.qc" />
+ <Unit filename="client\sortlist.qc" />
+ <Unit filename="client\teamplay.qc" />
+ <Unit filename="client\teamradar.qc" />
+ <Unit filename="client\teamradar.qh" />
+ <Unit filename="client\tuba.qc" />
+ <Unit filename="client\wall.qc" />
+ <Unit filename="client\waypointsprites.qc" />
+ <Unit filename="client\waypointsprites.qh" />
+ <Extensions>
+ <code_completion />
+ <debugger />
+ </Extensions>
+ </Project>
+</CodeBlocks_project_file>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="qc-common" />
+ <Option makefile="none" />
+ <Option makefile_is_custom="1" />
+ <Option pch_mode="2" />
+ <Option compiler="qaukec" />
+ <Build>
+ <Target title="Debug">
+ <Option output="bin\Debug\qc-server" prefix_auto="1" extension_auto="1" />
+ <Option object_output="obj\Debug\" />
+ <Option type="1" />
+ <Option compiler="qaukec" />
+ <Compiler>
+ <Add option="-g" />
+ </Compiler>
+ <MakeCommands>
+ <Build command="$make -src $makefile" />
+ <CompileFile command="" />
+ <Clean command="" />
+ <DistClean command="" />
+ </MakeCommands>
+ </Target>
+ <Target title="Release">
+ <Option output="bin\Release\qc-server" prefix_auto="1" extension_auto="1" />
+ <Option object_output="obj\Release\" />
+ <Option type="1" />
+ <Option compiler="qaukec" />
+ <Compiler>
+ <Add option="-O2" />
+ </Compiler>
+ <Linker>
+ <Add option="-s" />
+ </Linker>
+ <MakeCommands>
+ <Build command="$make -src $makefile" />
+ <CompileFile command="" />
+ <Clean command="" />
+ <DistClean command="" />
+ </MakeCommands>
+ </Target>
+ </Build>
+ <Compiler>
+ <Add option="-Wall" />
+ </Compiler>
+ <Unit filename="common\campaign_common.qh" />
+ <Unit filename="common\campaign_file.qc" />
+ <Unit filename="common\campaign_setup.qc" />
+ <Unit filename="common\constants.qh" />
+ <Unit filename="common\gamecommand.qc" />
+ <Unit filename="common\items.qc" />
+ <Unit filename="common\items.qh" />
+ <Unit filename="common\mapinfo.qc" />
+ <Unit filename="common\mapinfo.qh" />
+ <Unit filename="common\util-pre.qh" />
+ <Unit filename="common\util.qc" />
+ <Unit filename="common\util.qh" />
+ <Extensions>
+ <code_completion />
+ <debugger />
+ </Extensions>
+ </Project>
+</CodeBlocks_project_file>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="6" />
+ <Project>
+ <Option title="qc-server" />
+ <Option makefile="server/" />
+ <Option makefile_is_custom="1" />
+ <Option pch_mode="2" />
+ <Option compiler="qaukec" />
+ <Build>
+ <Target title="Debug">
+ <Option output="bin\Debug\qc-server" prefix_auto="1" extension_auto="1" />
+ <Option object_output="obj\Debug\" />
+ <Option type="1" />
+ <Option compiler="qaukec" />
+ <Compiler>
+ <Add option="-g" />
+ </Compiler>
+ <MakeCommands>
+ <Build command="$make -DVEHICLES_ENABLED -DRELEASE -src $makefile" />
+ <CompileFile command="" />
+ <Clean command="" />
+ <DistClean command="" />
+ </MakeCommands>
+ </Target>
+ <Target title="Release">
+ <Option output="bin\Release\qc-server" prefix_auto="1" extension_auto="1" />
+ <Option object_output="obj\Release\" />
+ <Option type="1" />
+ <Option compiler="qaukec" />
+ <Compiler>
+ <Add option="-O2" />
+ </Compiler>
+ <Linker>
+ <Add option="-s" />
+ </Linker>
+ <MakeCommands>
+ <Build command="$make -DVEHICLES_ENABLED -DRELEASE -src $makefile" />
+ <CompileFile command="" />
+ <Clean command="" />
+ <DistClean command="" />
+ </MakeCommands>
+ </Target>
+ </Build>
+ <Compiler>
+ <Add option="-Wall" />
+ </Compiler>
+ <Unit filename="anticheat.qc" />
+ <Unit filename="anticheat.qh" />
+ <Unit filename="antilag.qc" />
+ <Unit filename="antilag.qh" />
+ <Unit filename="arena.qc" />
+ <Unit filename="assault.qc" />
+ <Unit filename="bot\aim.qc" />
+ <Unit filename="bot\aim.qh" />
+ <Unit filename="bot\bot.qc" />
+ <Unit filename="bot\bot.qh" />
+ <Unit filename="bot\havocbot\havocbot.qc" />
+ <Unit filename="bot\havocbot\havocbot.qh" />
+ <Unit filename="bot\havocbot\role_ctf.qc" />
+ <Unit filename="bot\havocbot\role_keyhunt.qc" />
+ <Unit filename="bot\havocbot\role_onslaught.qc" />
+ <Unit filename="bot\havocbot\roles.qc" />
+ <Unit filename="bot\navigation.qc" />
+ <Unit filename="bot\navigation.qh" />
+ <Unit filename="bot\scripting.qc" />
+ <Unit filename="bot\waypoints.qc" />
+ <Unit filename="bot\waypoints.qh" />
+ <Unit filename="builtins.qh" />
+ <Unit filename="campaign.qc" />
+ <Unit filename="campaign.qh" />
+ <Unit filename="cheats.qc" />
+ <Unit filename="cheats.qh" />
+ <Unit filename="cl_client.qc" />
+ <Unit filename="cl_impulse.qc" />
+ <Unit filename="cl_physics.qc" />
+ <Unit filename="cl_player.qc" />
+ <Unit filename="cl_weapons.qc" />
+ <Unit filename="cl_weaponsystem.qc" />
+ <Unit filename="clientcommands.qc" />
+ <Unit filename="constants.qh" />
+ <Unit filename="csqceffects.qc" />
+ <Unit filename="csqcprojectile.qc" />
+ <Unit filename="csqcprojectile.qh" />
+ <Unit filename="ctf.qc" />
+ <Unit filename="defs.qh" />
+ <Unit filename="domination.qc" />
+ <Unit filename="ent_cs.qc" />
+ <Unit filename="extensions.qh" />
+ <Unit filename="func_breakable.qc" />
+ <Unit filename="g_casings.qc" />
+ <Unit filename="g_damage.qc" />
+ <Unit filename="g_hook.qc" />
+ <Unit filename="g_hook.qh" />
+ <Unit filename="g_lights.qc" />
+ <Unit filename="g_models.qc" />
+ <Unit filename="g_subs.qc" />
+ <Unit filename="g_swamp.qc" />
+ <Unit filename="g_tetris.qc" />
+ <Unit filename="g_triggers.qc" />
+ <Unit filename="g_violence.qc" />
+ <Unit filename="g_world.qc" />
+ <Unit filename="gamecommand.qc" />
+ <Unit filename="ipban.qc" />
+ <Unit filename="ipban.qh" />
+ <Unit filename="miscfunctions.qc" />
+ <Unit filename="mode_onslaught.qc" />
+ <Unit filename="monsters\ai.qc" />
+ <Unit filename="monsters\defs.qc" />
+ <Unit filename="monsters\fight.qc" />
+ <Unit filename="monsters\m_monsters.qc" />
+ <Unit filename="monsters\mode_management.qc" />
+ <Unit filename="monsters\monster_zombie.qc" />
+ <Unit filename="movelib.qc" />
+ <Unit filename="mutators\base.qc" />
+ <Unit filename="mutators\base.qh" />
+ <Unit filename="mutators\gamemode_keyhunt.qc" />
+ <Unit filename="mutators\gamemode_keyhunt.qh" />
+ <Unit filename="mutators\mutator_dodging.qc" />
+ <Unit filename="mutators\mutator_dodging.qh" />
+ <Unit filename="mutators\mutator_nix.qc" />
+ <Unit filename="mutators\mutators.qh" />
+ <Unit filename="nexball.qc" />
+ <Unit filename="pathlib.qc" />
+ <Unit filename="pathlib\costs.qc" />
+ <Unit filename="pathlib\debug.qc" />
+ <Unit filename="pathlib\expandnode.qc" />
+ <Unit filename="pathlib\main.qc" />
+ <Unit filename="pathlib\movenode.qc" />
+ <Unit filename="pathlib\pathlib.qh" />
+ <Unit filename="pathlib\utility.qc" />
+ <Unit filename="playerdemo.qc" />
+ <Unit filename="playerdemo.qh" />
+ <Unit filename="portals.qc" />
+ <Unit filename="portals.qh" />
+ <Unit filename="post-builtins.qh" />
+ <Unit filename="pre-builtins.qh" />
+ <Unit filename="progs.src" />
+ <Unit filename="race.qc" />
+ <Unit filename="race.qh" />
+ <Unit filename="runematch.qc" />
+ <Unit filename="scores.qc" />
+ <Unit filename="scores.qh" />
+ <Unit filename="scores_rules.qc" />
+ <Unit filename="steerlib.qc" />
+ <Unit filename="sv_main.qc" />
+ <Unit filename="sv_stats.qc" />
+ <Unit filename="sys.qh" />
+ <Unit filename="t_halflife.qc" />
+ <Unit filename="t_items.qc" />
+ <Unit filename="t_jumppads.qc" />
+ <Unit filename="t_plats.qc" />
+ <Unit filename="t_quake.qc" />
+ <Unit filename="t_quake3.qc" />
+ <Unit filename="t_swamp.qc" />
+ <Unit filename="t_teleporters.qc" />
+ <Unit filename="target_spawn.qc" />
+ <Unit filename="teamplay.qc" />
+ <Unit filename="tturrets\include\turrets.qh" />
+ <Unit filename="tturrets\include\turrets_early.qh" />
+ <Unit filename="tturrets\system\system_aimprocs.qc" />
+ <Unit filename="tturrets\system\system_damage.qc" />
+ <Unit filename="tturrets\system\system_main.qc" />
+ <Unit filename="tturrets\system\system_misc.qc" />
+ <Unit filename="tturrets\system\system_scoreprocs.qc" />
+ <Unit filename="tturrets\units\unit_checkpoint.qc" />
+ <Unit filename="tturrets\units\unit_common.qc" />
+ <Unit filename="tturrets\units\unit_ewheel.qc" />
+ <Unit filename="tturrets\units\unit_flac.qc" />
+ <Unit filename="tturrets\units\unit_fusionreactor.qc" />
+ <Unit filename="tturrets\units\unit_hellion.qc" />
+ <Unit filename="tturrets\units\unit_hk.qc" />
+ <Unit filename="tturrets\units\unit_machinegun.qc" />
+ <Unit filename="tturrets\units\unit_mlrs.qc" />
+ <Unit filename="tturrets\units\unit_phaser.qc" />
+ <Unit filename="tturrets\units\unit_plasma.qc" />
+ <Unit filename="tturrets\units\unit_targettrigger.qc" />
+ <Unit filename="tturrets\units\unit_tessla.qc" />
+ <Unit filename="tturrets\units\unit_walker.qc" />
+ <Unit filename="vehicles\racer.qc" />
+ <Unit filename="vehicles\raptor.qc" />
+ <Unit filename="vehicles\spiderbot.qc" />
+ <Unit filename="vehicles\vehicles.qc" />
+ <Unit filename="vehicles\vehicles.qh" />
+ <Unit filename="verbstack.qc" />
+ <Unit filename="vote.qc" />
+ <Unit filename="vote.qh" />
+ <Unit filename="w_all.qc" />
+ <Unit filename="w_campingrifle.qc" />
+ <Unit filename="w_common.qc" />
+ <Unit filename="w_crylink.qc" />
+ <Unit filename="w_electro.qc" />
+ <Unit filename="w_fireball.qc" />
+ <Unit filename="w_grenadelauncher.qc" />
+ <Unit filename="w_hagar.qc" />
+ <Unit filename="w_hlac.qc" />
+ <Unit filename="w_hook.qc" />
+ <Unit filename="w_laser.qc" />
+ <Unit filename="w_minstanex.qc" />
+ <Unit filename="w_nex.qc" />
+ <Unit filename="w_porto.qc" />
+ <Unit filename="w_rocketlauncher.qc" />
+ <Unit filename="w_shotgun.qc" />
+ <Unit filename="w_tuba.qc" />
+ <Unit filename="w_uzi.qc" />
+ <Unit filename="waypointsprites.qc" />
+ <Extensions>
+ <code_completion />
+ <debugger />
+ </Extensions>
+ </Project>
+</CodeBlocks_project_file>
else bot_name = "Bot";
if(argv(1) != "") bot_model = argv(1);
- else bot_model = "marine";
+ else bot_model = "";
if(argv(2) != "") bot_skin = argv(2);
else bot_skin = "0";
else
name = bot_name;
+ self.cleanname = strzone(name);
+
+ // number bots with identical names
+ float i;
+ i = 0;
+ FOR_EACH_CLIENT(p)
+ {
+ if(clienttype(p) == CLIENTTYPE_BOT)
+ if(p.cleanname == name)
+ ++i;
+ }
+ if (i)
+ name = strcat(name, "(", ftos(i), ")");
+
// pick the model and skin
if(substring(bot_model, -4, 1) != ".")
- bot_model = strcat(bot_model, ".zym");
+ bot_model = strcat(bot_model, ".iqm");
self.playermodel = self.playermodel_freeme = strzone(strcat("models/player/", bot_model));
self.playerskin = self.playerskin_freeme = strzone(bot_skin);
{
if (clienttype(self) != CLIENTTYPE_BOT)
return;
+ if(self.cleanname)
+ strunzone(self.cleanname);
if(self.netname_freeme)
strunzone(self.netname_freeme);
if(self.playermodel_freeme)
strunzone(self.playermodel_freeme);
if(self.playerskin_freeme)
strunzone(self.playerskin_freeme);
+ self.cleanname = string_null;
self.netname_freeme = string_null;
self.playermodel_freeme = string_null;
self.playerskin_freeme = string_null;
entity player_list;
.entity nextbot;
.entity nextplayer;
+.string cleanname;
.string netname_freeme;
.string playermodel_freeme;
.string playerskin_freeme;
self.havocbot_keyboardtime =
max(
self.havocbot_keyboardtime
- + bound(0,0.05/(sk+self.havocbot_keyboardskill),0.05)
- +random()*bound(0,0.025/(skill+self.havocbot_keyboardskill),100)
+ + 0.05/max(1, sk+self.havocbot_keyboardskill)
+ + random()*0.025/max(0.00025, skill+self.havocbot_keyboardskill)
, time);
keyboard = self.movement * (1.0 / maxspeed);
for(i = WEP_FIRST; i < WEP_LAST ; ++i)
{
// Find weapon
- if((get_weaponinfo(i)).weapons & self.weapons)
+ if(power2of(i-1) & self.weapons)
if(++c>=4)
break;
}
IS_CHEAT(i, 0, 0);
FOR_EACH_PLAYER(e)
{
- if( e.playermodel == "models/player/jeandarc.zym"
- || e.playermodel == "models/player/pyria.zym"
- || e.playermodel == "models/player/skadi.zym"
- || (e.playermodel == "models/player/specop.zym" && random() < 0.5) // you never know
- || e.playermodel == "models/player/visitant.zym")
+ get_model_parameters(e.playermodel, e.skinindex);
+ if(get_model_parameters_sex == "Female")
{
makevectors(e.angles);
traceline(e.origin, e.origin + v_right * 256, MOVE_NORMAL, e);
}
void AnnounceTo(entity e, string snd) {
- msg_entity = e;
- WriteByte(MSG_ONE, SVC_TEMPENTITY);
- WriteByte(MSG_ONE, TE_CSQC_ANNOUNCE);
- WriteString(MSG_ONE, snd);
+ if (clienttype(e) == CLIENTTYPE_REAL)
+ {
+ msg_entity = e;
+ WriteByte(MSG_ONE, SVC_TEMPENTITY);
+ WriteByte(MSG_ONE, TE_CSQC_ANNOUNCE);
+ WriteString(MSG_ONE, snd);
+ }
}
float ClientData_Send(entity to, float sf)
Returns a valid one in doubt.
=============
*/
-string FallbackPlayerModel = "models/player/marine.zym";
+string FallbackPlayerModel;
string CheckPlayerModel(string plyermodel) {
+ if(FallbackPlayerModel != cvar_defstring("_cl_playermodel"))
+ {
+ // note: we cannot summon Don Strunzone here, some player may
+ // still have the model string set. In case anyone manages how
+ // to change a cvar default, we'll have a small leak here.
+ FallbackPlayerModel = strzone(cvar_defstring("_cl_playermodel"));
+ }
if(strlen(plyermodel) < 4)
return FallbackPlayerModel;
if( substring(plyermodel,0,14) != "models/player/")
{
if(substring(plyermodel,-4,4) != ".zym")
if(substring(plyermodel,-4,4) != ".dpm")
+ if(substring(plyermodel,-4,4) != ".iqm")
if(substring(plyermodel,-4,4) != ".md3")
if(substring(plyermodel,-4,4) != ".psk")
return FallbackPlayerModel;
return TRUE;
}
-void UpdatePlayerSounds();
void setmodel_lod(entity e, string modelname)
{
string s;
}
DropAllRunes(self);
- kh_Key_DropAll(self, TRUE);
Portal_ClearAll(self);
}
else
self.frags = FRAGS_SPECTATOR;
+
+ MUTATOR_CALLHOOK(MakePlayerObserver);
}
float RestrictSkin(float s)
self.weapons = randombits(self.weapons, g_weaponarena_random, FALSE);
self.items = start_items;
- self.switchweapon = w_getbestweapon(self);
- self.cnt = self.switchweapon;
- self.weapon = 0;
self.jump_interval = time;
self.spawnshieldtime = time + cvar("g_spawnshieldtime");
self.nextthink = 0;
self.hook_time = 0;
self.dmg_team = 0;
+ self.ballistics_density = cvar("g_ballistics_density_player");
self.metertime = 0;
}
self.cnt = WEP_LASER;
- self.nixnex_lastchange_id = -1;
CL_SpawnWeaponentity();
self.alpha = default_player_alpha;
target_voicescript_clear(self);
// reset fields the weapons may use
- for (j = WEP_FIRST; j <= WEP_LAST; ++j)
- weapon_action(j, WR_RESETPLAYER);
+ for (j = WEP_FIRST; j <= WEP_LAST; ++j)
+ weapon_action(j, WR_RESETPLAYER);
oldself = self;
self = spot;
SUB_UseTargets();
activator = world;
self = oldself;
+
+ MUTATOR_CALLHOOK(PlayerSpawn);
+
+ self.switchweapon = w_getbestweapon(self);
+ self.cnt = self.switchweapon;
+ self.weapon = 0;
} else if(self.classname == "observer" || (g_ca && !allowed_to_spawn)) {
PutObserverInServer ();
}
WriteCoord(MSG_ENTITY, hook_shotorigin_x);
WriteCoord(MSG_ENTITY, hook_shotorigin_y);
WriteCoord(MSG_ENTITY, hook_shotorigin_z);
-
if(sv_foginterval && world.fog != "")
WriteString(MSG_ENTITY, world.fog);
else
WriteString(MSG_ENTITY, "");
- WriteByte(MSG_ENTITY, cvar("g_balance_armor_blockpercent") * 255.0);
- WriteByte(MSG_ENTITY, cvar("g_balance_weaponswitchdelay") * 255.0);
+ WriteByte(MSG_ENTITY, self.count * 255.0); // g_balance_armor_blockpercent
+ WriteByte(MSG_ENTITY, self.cnt * 255.0); // g_balance_weaponswitchdelay
+ WriteCoord(MSG_ENTITY, self.bouncefactor); // g_balance_grenadelauncher_secondary_bouncefactor
+ WriteCoord(MSG_ENTITY, self.bouncestop); // g_balance_grenadelauncher_secondary_bouncestop
return TRUE;
}
+void ClientInit_CheckUpdate()
+{
+ self.nextthink = time;
+ if(self.count != cvar("g_balance_armor_blockpercent"))
+ {
+ self.count = cvar("g_balance_armor_blockpercent");
+ self.SendFlags |= 1;
+ }
+ if(self.cnt != cvar("g_balance_weaponswitchdelay"))
+ {
+ self.cnt = cvar("g_balance_weaponswitchdelay");
+ self.SendFlags |= 1;
+ }
+ if(self.bouncefactor != cvar("g_balance_grenadelauncher_secondary_bouncefactor"))
+ {
+ self.bouncefactor = cvar("g_balance_grenadelauncher_secondary_bouncefactor");
+ self.SendFlags |= 1;
+ }
+ if(self.bouncestop != cvar("g_balance_grenadelauncher_secondary_bouncestop"))
+ {
+ self.bouncestop = cvar("g_balance_grenadelauncher_secondary_bouncestop");
+ self.SendFlags |= 1;
+ }
+}
+
void ClientInit_Spawn()
{
- Net_LinkEntity(spawn(), FALSE, 0, ClientInit_SendEntity);
+ entity o;
+ entity e;
+ e = spawn();
+ e.classname = "clientinit";
+ e.think = ClientInit_CheckUpdate;
+ Net_LinkEntity(e, FALSE, 0, ClientInit_SendEntity);
+
+ o = self;
+ self = e;
+ ClientInit_CheckUpdate();
+ self = o;
}
/*
DecodeLevelParms();
+#ifdef WATERMARK
+ sprint(self, strcat("^4SVQC Build information: ", WATERMARK(), "\n"));
+#endif
+
self.classname = "player_joining";
self.flags = FL_CLIENT;
SoundEntity_Detach(self);
DropAllRunes(self);
- kh_Key_DropAll(self, TRUE);
+ MUTATOR_CALLHOOK(ClientDisconnect);
Portal_ClearAll(self);
else self.colormod = '1 1 1';
};*/
+.float oldcolormap;
void respawn(void)
{
+ if(self.modelindex != 0 && cvar("g_respawn_ghosts"))
+ {
+ self.solid = SOLID_NOT;
+ self.takedamage = DAMAGE_NO;
+ self.movetype = MOVETYPE_FLY;
+ self.velocity = '0 0 1' * cvar("g_respawn_ghosts_speed");
+ self.avelocity = randomvec() * cvar("g_respawn_ghosts_speed") * 3 - randomvec() * cvar("g_respawn_ghosts_speed") * 3;
+ self.effects |= EF_ADDITIVE;
+ self.oldcolormap = self.colormap;
+ self.colormap = 512;
+ pointparticles(particleeffectnum("respawn_ghost"), self.origin, '0 0 0', 1);
+ if(cvar("g_respawn_ghosts_maxtime"))
+ SUB_SetFade (self, time + cvar("g_respawn_ghosts_maxtime") / 2 + random () * (cvar("g_respawn_ghosts_maxtime") - cvar("g_respawn_ghosts_maxtime") / 2), 1.5);
+ }
+
CopyBody(1);
self.effects |= EF_NODRAW; // prevent another CopyBody
+ if(self.oldcolormap)
+ {
+ self.colormap = self.oldcolormap;
+ self.oldcolormap = 0;
+ }
PutClientInServer();
}
}
void GetPressedKeys(void) {
+ MUTATOR_CALLHOOK(GetPressedKeys);
if (self.movement_x > 0) // get if movement keys are pressed
{ // forward key pressed
self.pressedkeys |= KEY_FORWARD;
} else
update_stats (0, spectatee.cvar_cl_accuracy_data_share * spectatee.stat_hit, spectatee.cvar_cl_accuracy_data_share * spectatee.stat_fired);
- self.kh_state = spectatee.kh_state;
+ other = spectatee;
+ MUTATOR_CALLHOOK(SpectateCopy);
self.armortype = spectatee.armortype;
self.armorvalue = spectatee.armorvalue;
self.ammo_cells = spectatee.ammo_cells;
return;
#endif
+ MUTATOR_CALLHOOK(PlayerPreThink);
+
if(self.classname == "player") {
// if(self.netname == "Wazat")
// bprint(self.classname, "\n");
self.effects = self.effects - (self.effects & EF_NODRAW);
}
- Nixnex_GiveCurrentWeapon();
-
if(frametime > 0) // don't do this in cl_movement frames, just in server ticks
UpdateSelectedPlayer();
if(frametime)
{
- if(cvar("gameversion") >= 20600) // only do this for 2.6 and above FIXME remove this check when making 2.6
- self.glowmod = colormapPaletteColor(self.clientcolors & 0x0F, TRUE) * 2;
+ self.glowmod = colormapPaletteColor(self.clientcolors & 0x0F, TRUE) * 2;
player_powerups();
}
=============
*/
.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
ImpulseCommands();
if (intermission_running)
return; // intermission or finale
-
GetPressedKeys();
} else if (self.classname == "observer") {
//do nothing
if(self.waypointsprite_attachedforcarrier)
WaypointSprite_UpdateHealth(self.waypointsprite_attachedforcarrier, '1 0 0' * healtharmor_maxdamage(self.health, self.armorvalue, cvar("g_balance_armor_blockpercent")));
+ if(self.classname == "player" && self.deadflag == DEAD_NO && cvar("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)
+ remove(self.showheadshotbbox);
+ }
+
playerdemo_write();
/*
float sv_airstopaccelerate;
float sv_airstrafeaccelerate;
float sv_maxairstrafespeed;
+float sv_airstrafeaccel_qw;
float sv_aircontrol;
+float sv_aircontrol_power;
float sv_warsowbunny_airforwardaccel;
float sv_warsowbunny_accel;
float sv_warsowbunny_topspeed;
float sv_warsowbunny_turnaccel;
float sv_warsowbunny_backtosideratio;
+float sv_airspeedlimit_nonqw;
.float ladder_time;
.entity ladder_entity;
void PlayerJump (void)
{
float mjumpheight;
+ float doublejump;
+
+ doublejump = FALSE;
+ if (sv_doublejump)
+ {
+ tracebox(self.origin + '0 0 0.01', self.mins, self.maxs, self.origin - '0 0 0.01', MOVE_NORMAL, self);
+ if (trace_fraction < 1 && trace_plane_normal_z > 0.7)
+ doublejump = TRUE;
+ }
mjumpheight = cvar("sv_jumpvelocity");
if (self.waterlevel >= WATERLEVEL_SWIMMING)
return;
}
+ if (!doublejump)
if (!(self.flags & FL_ONGROUND))
return;
mjumpheight = mjumpheight * cvar("g_minstagib_speed_jumpheight");
}
+ // sv_jumpspeedcap_min/sv_jumpspeedcap_max act as baseline
+ // velocity bounds. Final velocity is bound between (jumpheight *
+ // min + jumpheight) and (jumpheight * max + jumpheight);
+
if(cvar_string("sv_jumpspeedcap_min") != "")
- self.velocity_z = max(cvar("sv_jumpvelocity") * cvar("sv_jumpspeedcap_min"), self.velocity_z);
- if(cvar_string("sv_jumpspeedcap_max") != "") {
- if(trace_fraction < 1 && trace_plane_normal_z < 0.98 && cvar("sv_jumpspeedcap_max_disable_on_ramps")) {
- // don't do jump speedcaps on ramps to preserve old xonotic ramjump style
- //print("Trace plane normal z: ", ftos(trace_plane_normal_z), ", disabling speed cap!\n");
+ {
+ float minjumpspeed;
+
+ minjumpspeed = mjumpheight * cvar("sv_jumpspeedcap_min");
+
+ if (self.velocity_z < minjumpspeed)
+ mjumpheight += minjumpspeed - self.velocity_z;
+ }
+
+ if(cvar_string("sv_jumpspeedcap_max") != "")
+ {
+ // don't do jump speedcaps on ramps to preserve old xonotic ramjump style
+ tracebox(self.origin + '0 0 0.01', self.mins, self.maxs, self.origin - '0 0 0.01', MOVE_NORMAL, self);
+
+ if(!(trace_fraction < 1 && trace_plane_normal_z < 0.98 && cvar("sv_jumpspeedcap_max_disable_on_ramps")))
+ {
+ float maxjumpspeed;
+
+ maxjumpspeed = mjumpheight * cvar("sv_jumpspeedcap_max");
+
+ if (self.velocity_z > maxjumpspeed)
+ mjumpheight -= self.velocity_z - maxjumpspeed;
}
- else
- self.velocity_z = min(cvar("sv_jumpvelocity") * cvar("sv_jumpspeedcap_max"), self.velocity_z) + trace_ent.velocity_z;
}
if(!(self.lastflags & FL_ONGROUND))
{
if(mv_x == 0 && mv_y == 0)
return 0; // avoid division by zero
- angle = RAD2DEG * atan2(mv_y, mv_x);
+ angle -= RAD2DEG * atan2(mv_y, mv_x);
angle = remainder(angle, 360) / 45;
if(angle > 1)
return 0;
return 1 - fabs(angle);
}
+float GeomLerp(float a, float lerp, float b)
+{
+ if(a == 0)
+ {
+ if(lerp < 1)
+ return 0;
+ else
+ return b;
+ }
+ if(b == 0)
+ {
+ if(lerp > 0)
+ return 0;
+ else
+ return a;
+ }
+ return a * pow(fabs(b / a), lerp);
+}
+
void CPM_PM_Aircontrol(vector wishdir, float wishspeed)
{
float zspeed, xyspeed, dot, k;
xyspeed = vlen(self.velocity); self.velocity = normalize(self.velocity);
dot = self.velocity * wishdir;
- k *= sv_aircontrol*dot*dot*frametime;
if(dot > 0) // we can't change direction while slowing down
{
+ k *= fabs(sv_aircontrol)*pow(dot, sv_aircontrol_power)*frametime;
self.velocity = normalize(self.velocity * xyspeed + wishdir * k);
}
self.velocity_z = zspeed;
}
+float AdjustAirAccelQW(float accelqw, float factor)
+{
+ return copysign(bound(0.000001, 1 - (1 - fabs(accelqw)) * factor, 1), accelqw);
+}
+
// example config for alternate speed clamping:
// sv_airaccel_qw 0.8
// sv_airaccel_sideways_friction 0
// prvm_globalset server speedclamp_mode 1
// (or 2)
-void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float sidefric)
+void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float sidefric, float speedlimit)
{
float vel_straight;
float vel_z;
step = accel * frametime * wishspeed0;
vel_xy_current = vlen(vel_xy);
+ if(speedlimit)
+ accelqw = AdjustAirAccelQW(accelqw, (speedlimit - bound(wishspeed, vel_xy_current, speedlimit)) / max(1, speedlimit - wishspeed));
vel_xy_forward = vel_xy_current + bound(0, wishspeed - vel_xy_current, step) * accelqw + step * (1 - accelqw);
vel_xy_backward = vel_xy_current - bound(0, wishspeed + vel_xy_current, step) * accelqw - step * (1 - accelqw);
if(vel_xy_backward < 0)
.vector v_angle_old;
.string lastclassname;
-void Nixnex_GiveCurrentWeapon();
.float() PlayerPhysplug;
string specialcommand = "xwxwxsxsxaxdxaxdx1x ";
string GetMapname(void);
float speedaward_lastupdate;
float speedaward_lastsent;
-.float jumppadusetime;
+var float autocvar_g_movement_highspeed = 1;
void SV_PlayerPhysics()
{
local vector wishvel, wishdir, v;
float not_allowed_to_move;
string c;
+ // fix physics stats for g_movement_highspeed
+ self.stat_sv_airaccel_qw = AdjustAirAccelQW(sv_airaccel_qw, autocvar_g_movement_highspeed);
+ if(sv_airstrafeaccel_qw)
+ self.stat_sv_airstrafeaccel_qw = AdjustAirAccelQW(sv_airstrafeaccel_qw, autocvar_g_movement_highspeed);
+ else
+ self.stat_sv_airstrafeaccel_qw = 0;
+ self.stat_sv_airspeedlimit_nonqw = sv_airspeedlimit_nonqw * autocvar_g_movement_highspeed;
+
if(self.PlayerPhysplug)
if(self.PlayerPhysplug())
return;
bot_think();
}
+ MUTATOR_CALLHOOK(PlayerPhysics);
+
self.items &~= IT_USING_JETPACK;
if(self.classname == "player")
if(self.classname == "player")
{
- if(sv_doublejump && time - self.jumppadusetime > 2 * sys_frametime)
- {
- tracebox(self.origin + '0 0 0.01', self.mins, self.maxs, self.origin - '0 0 0.01', MOVE_NORMAL, self);
- self.flags &~= FL_ONGROUND;
- if(trace_fraction < 1 && trace_plane_normal_z > 0.7)
- self.flags |= FL_ONGROUND;
- }
-
if (self.BUTTON_JUMP)
PlayerJump ();
else
if (wishspeed > sv_maxspeed*maxspd_mod)
wishspeed = sv_maxspeed*maxspd_mod;
if (time >= self.teleport_time)
- PM_Accelerate(wishdir, wishspeed, wishspeed, sv_accelerate*maxspd_mod, 1, 0);
+ PM_Accelerate(wishdir, wishspeed, wishspeed, sv_accelerate*maxspd_mod, 1, 0, 0);
}
else if (self.waterlevel >= WATERLEVEL_SWIMMING)
{
self.velocity = self.velocity * (1 - frametime * sv_friction);
// water acceleration
- PM_Accelerate(wishdir, wishspeed, wishspeed, sv_accelerate*maxspd_mod, 1, 0);
+ PM_Accelerate(wishdir, wishspeed, wishspeed, sv_accelerate*maxspd_mod, 1, 0, 0);
}
else if (time < self.ladder_time)
{
if (time >= self.teleport_time)
{
// water acceleration
- PM_Accelerate(wishdir, wishspeed, wishspeed, sv_accelerate*maxspd_mod, 1, 0);
+ PM_Accelerate(wishdir, wishspeed, wishspeed, sv_accelerate*maxspd_mod, 1, 0, 0);
}
}
else if ((self.items & IT_JETPACK) && self.BUTTON_HOOK && (!cvar("g_jetpack_fuel") || self.ammo_fuel >= 0.01 || self.items & IT_UNLIMITED_WEAPON_AMMO))
if (self.crouch)
wishspeed = wishspeed * 0.5;
if (time >= self.teleport_time)
- PM_Accelerate(wishdir, wishspeed, wishspeed, sv_accelerate*maxspd_mod, 1, 0);
+ PM_Accelerate(wishdir, wishspeed, wishspeed, sv_accelerate*maxspd_mod, 1, 0, 0);
}
else
{
float accelerating;
float wishspeed2;
float airaccelqw;
+ float strafity;
- airaccelqw = sv_airaccel_qw;
+ airaccelqw = self.stat_sv_airaccel_qw;
accelerating = (self.velocity * wishdir > 0);
wishspeed2 = wishspeed;
if(sv_airstopaccelerate)
if(self.velocity * wishdir < 0)
airaccel = sv_airstopaccelerate*maxspd_mod;
- // this doesn't play well with analog input, but can't r
- // fixed like the AirControl can. So, don't set the maxa
- // cvars when you want to support analog input.
- if(self.movement_x == 0 && self.movement_y != 0)
- {
- if(sv_maxairstrafespeed)
- {
- wishspeed = min(wishspeed, sv_maxairstrafespeed*maxspd_mod);
- if(sv_maxairstrafespeed < sv_maxairspeed)
- airaccelqw = 1;
- }
- if(sv_airstrafeaccelerate)
- {
- airaccel = sv_airstrafeaccelerate*maxspd_mod;
- if(sv_airstrafeaccelerate > sv_airaccelerate)
- airaccelqw = 1;
- }
- }
+ // note that for straight forward jumping:
+ // step = accel * frametime * wishspeed0;
+ // accel = bound(0, wishspeed - vel_xy_current, step) * accelqw + step * (1 - accelqw);
+ // -->
+ // dv/dt = accel * maxspeed (when slow)
+ // dv/dt = accel * maxspeed * (1 - accelqw) (when fast)
+ // log dv/dt = logaccel + logmaxspeed (when slow)
+ // log dv/dt = logaccel + logmaxspeed + log(1 - accelqw) (when fast)
+ strafity = IsMoveInDirection(self.movement, -90) + IsMoveInDirection(self.movement, +90); // if one is nonzero, other is always zero
+ if(sv_maxairstrafespeed)
+ wishspeed = min(wishspeed, GeomLerp(sv_maxairspeed*maxspd_mod, strafity, sv_maxairstrafespeed*maxspd_mod));
+ if(sv_airstrafeaccelerate)
+ airaccel = GeomLerp(airaccel, strafity, sv_airstrafeaccelerate*maxspd_mod);
+ if(self.stat_sv_airstrafeaccel_qw)
+ airaccelqw = copysign(1-GeomLerp(1-fabs(self.stat_sv_airaccel_qw), strafity, 1-fabs(self.stat_sv_airstrafeaccel_qw)), ((strafity > 0.5) ? self.stat_sv_airstrafeaccel_qw : self.stat_sv_airaccel_qw));
// !CPM
if(sv_warsowbunny_turnaccel && accelerating && self.movement_y == 0 && self.movement_x != 0)
PM_AirAccelerate(wishdir, wishspeed);
else
- PM_Accelerate(wishdir, wishspeed, wishspeed0, airaccel, airaccelqw, sv_airaccel_sideways_friction / maxairspd);
+ PM_Accelerate(wishdir, wishspeed, wishspeed0, airaccel, airaccelqw, sv_airaccel_sideways_friction / maxairspd, self.stat_sv_airspeedlimit_nonqw);
if(sv_aircontrol)
CPM_PM_Aircontrol(wishdir, wishspeed2);
self.movetype = oldself.movetype;
self.nextthink = oldself.nextthink;
self.solid = oldself.solid;
+ self.ballistics_density = oldself.ballistics_density;
self.takedamage = oldself.takedamage;
self.think = oldself.think;
self.customizeentityforclient = oldself.customizeentityforclient;
float player_getspecies()
{
- local float glob, i, j, fh, len, s, sk;
- local string fn, l;
-
- s = -1;
-
- glob = search_begin("models/player/*.txt", TRUE, TRUE);
- if(glob < 0)
- return s;
- for(j = 0; j <= 1; ++j)
- {
- for(i = 0; i < search_getsize(glob); ++i)
- {
- fn = search_getfilename(glob, i);
- fh = fopen(fn, FILE_READ);
- if(fh < 0)
- continue;
- fgets(fh); fgets(fh);
- sk = stof(fgets(fh));
- if(sk == (j ? 0 : self.skinindex)) // 2nd pass skips the skin test
- if(fgets(fh) == self.model)
- {
- l = fgets(fh);
- len = tokenize_console(l);
- if (len != 2)
- goto nospecies;
- if (argv(0) != "species")
- goto nospecies;
- switch(argv(1))
- {
- case "human": s = SPECIES_HUMAN; break;
- case "alien": s = SPECIES_ALIEN; break;
- case "robot_shiny": s = SPECIES_ROBOT_SHINY; break;
- case "robot_rusty": s = SPECIES_ROBOT_RUSTY; break;
- case "robot_solid": s = SPECIES_ROBOT_SOLID; break;
- case "animal": s = SPECIES_ANIMAL; break;
- case "reserved": s = SPECIES_RESERVED; break;
- }
- }
-:nospecies
- fclose(fh);
- }
- if (s >= 0)
- break;
- }
- search_end(glob);
-
- if (s < 0)
- s = SPECIES_HUMAN;
-
+ float s;
+ get_model_parameters(self.playermodel, self.skinindex);
+ s = get_model_parameters_species;
+ get_model_parameters(string_null, 0);
+ if(s < 0)
+ return SPECIES_HUMAN;
return s;
}
self.dmg_take = self.dmg_take + take;//max(take - 10, 0);
self.dmg_inflictor = inflictor;
- if (self.health <= -75 && self.modelindex != 0)
+ if (self.health <= -100 && self.modelindex != 0)
{
// don't use any animations as a gib
self.frame = 0;
Obituary (attacker, inflictor, self, deathtype);
race_PreDie();
DropAllRunes(self);
- if(self == attacker)
- kh_Key_DropAll(self, TRUE);
- else if(attacker.classname == "player" || attacker.classname == "gib")
- kh_Key_DropAll(self, FALSE);
- else
- kh_Key_DropAll(self, TRUE);
+
+ frag_attacker = attacker;
+ frag_inflictor = inflictor;
+ frag_target = self;
+ MUTATOR_CALLHOOK(PlayerDies);
+
if(self.flagcarried)
{
if(attacker.classname != "player" && attacker.classname != "gib")
self.movetype = MOVETYPE_TOSS;
// shootable corpse
self.solid = SOLID_CORPSE;
+ self.ballistics_density = cvar("g_ballistics_density_corpse");
// don't stick to the floor
self.flags &~= FL_ONGROUND;
// dying animation
}
.float muted; // to be used by prvm_edictset server playernumber muted 1
-void Say(entity source, float teamsay, entity privatesay, string msgin, float floodcontrol)
+float Say(entity source, float teamsay, entity privatesay, string msgin, float floodcontrol)
+// message "": do not say, just test flood control
+// return value:
+// 1 = accept
+// 0 = reject
+// -1 = fake accept
{
string msgstr, colorstr, cmsgstr, namestr, fullmsgstr, sourcemsgstr, fullcmsgstr, sourcecmsgstr, privatemsgprefix;
float flood, privatemsgprefixlen;
entity head;
+ float ret;
if(Ban_MaybeEnforceBan(source))
- return;
+ return 0;
if(!teamsay && !privatesay)
if(substring(msgin, 0, 1) == " ")
msgin = formatmessage(msgin);
- if(msgin == "")
- return;
-
if(source.classname != "player")
colorstr = "^0"; // black for spectators
else if(teams_matter)
if(intermission_running)
teamsay = FALSE;
- msgin = trigger_magicear_processmessage_forallears(source, teamsay, privatesay, msgin);
- if(msgin == "")
- return;
+ if(msgin != "")
+ msgin = trigger_magicear_processmessage_forallears(source, teamsay, privatesay, msgin);
/*
* using bprint solves this... me stupid
else
namestr = source.netname;
- if(privatesay)
+ if(msgin != "")
{
- msgstr = strcat("\{1}\{13}* ^3", namestr, "^3 tells you: ^7");
- privatemsgprefixlen = strlen(msgstr);
- msgstr = strcat(msgstr, msgin);
- cmsgstr = strcat(colorstr, "^3", namestr, "^3 tells you:\n^7", msgin);
- if(cvar("g_chat_teamcolors"))
- privatemsgprefix = strcat("\{1}\{13}* ^3You tell ", playername(privatesay), ": ^7");
+ if(privatesay)
+ {
+ msgstr = strcat("\{1}\{13}* ^3", namestr, "^3 tells you: ^7");
+ privatemsgprefixlen = strlen(msgstr);
+ msgstr = strcat(msgstr, msgin);
+ cmsgstr = strcat(colorstr, "^3", namestr, "^3 tells you:\n^7", msgin);
+ if(cvar("g_chat_teamcolors"))
+ privatemsgprefix = strcat("\{1}\{13}* ^3You tell ", playername(privatesay), ": ^7");
+ else
+ privatemsgprefix = strcat("\{1}\{13}* ^3You tell ", privatesay.netname, ": ^7");
+ }
+ else if(teamsay)
+ {
+ msgstr = strcat("\{1}\{13}", colorstr, "(^3", namestr, colorstr, ") ^7", msgin);
+ cmsgstr = strcat(colorstr, "(^3", namestr, colorstr, ")\n^7", msgin);
+ }
else
- privatemsgprefix = strcat("\{1}\{13}* ^3You tell ", privatesay.netname, ": ^7");
- }
- else if(teamsay)
- {
- msgstr = strcat("\{1}\{13}", colorstr, "(^3", namestr, colorstr, ") ^7", msgin);
- cmsgstr = strcat(colorstr, "(^3", namestr, colorstr, ")\n^7", msgin);
+ {
+ msgstr = strcat("\{1}", namestr, "^7: ", msgin);
+ cmsgstr = "";
+ }
+ msgstr = strcat(strreplace("\n", " ", msgstr), "\n"); // newlines only are good for centerprint
}
else
{
- msgstr = strcat("\{1}", namestr, "^7: ", msgin);
- cmsgstr = "";
+ msgstr = cmsgstr = "";
}
- msgstr = strcat(strreplace("\n", " ", msgstr), "\n"); // newlines only are good for centerprint
fullmsgstr = msgstr;
fullcmsgstr = cmsgstr;
// to match explanation in default.cfg, a value of 3 must allow three-line bursts and not four!
// do flood control for the default line size
- getWrappedLine_remaining = msgstr;
- msgstr = "";
- lines = 0;
- while(getWrappedLine_remaining && (!flood_lmax || lines <= flood_lmax))
+ if(msgstr != "")
{
- msgstr = strcat(msgstr, " ", getWrappedLineLen(82.4289758859709, strlennocol)); // perl averagewidth.pl < gfx/vera-sans.width
- ++lines;
- }
- msgstr = substring(msgstr, 1, strlen(msgstr) - 1);
+ getWrappedLine_remaining = msgstr;
+ msgstr = "";
+ lines = 0;
+ while(getWrappedLine_remaining && (!flood_lmax || lines <= flood_lmax))
+ {
+ msgstr = strcat(msgstr, " ", getWrappedLineLen(82.4289758859709, strlennocol)); // perl averagewidth.pl < gfx/vera-sans.width
+ ++lines;
+ }
+ msgstr = substring(msgstr, 1, strlen(msgstr) - 1);
- if(getWrappedLine_remaining != "")
- {
- msgstr = strcat(msgstr, "\n");
- flood = 2;
- }
+ if(getWrappedLine_remaining != "")
+ {
+ msgstr = strcat(msgstr, "\n");
+ flood = 2;
+ }
- if(time >= source.flood_field)
- {
- source.flood_field = max(time - flood_burst * flood_spl, source.flood_field) + lines * flood_spl;
+ if(time >= source.flood_field)
+ {
+ source.flood_field = max(time - flood_burst * flood_spl, source.flood_field) + lines * flood_spl;
+ }
+ else
+ {
+ flood = 1;
+ msgstr = fullmsgstr;
+ }
}
else
{
- flood = 1;
- msgstr = fullmsgstr;
+ if(time >= source.flood_field)
+ source.flood_field = max(time - flood_burst * flood_spl, source.flood_field) + flood_spl;
+ else
+ flood = 1;
}
}
if (timeoutStatus == 2) //when game is paused, no flood protection
source.flood_field = flood = 0;
- if(flood == 2)
+ if(flood == 2) // cannot happen for empty msgstr
{
if(cvar("g_chat_flood_notify_flooder"))
{
if(source.muted)
{
// always fake the message
- sprint(source, sourcemsgstr);
- if(cmsgstr != "" && !privatesay)
- centerprint(source, sourcecmsgstr);
+ ret = -1;
}
else if(flood == 1)
{
if(cvar("g_chat_flood_notify_flooder"))
- sprint(source, strcat("^3FLOOD CONTROL: ^7wait ^1", ftos(source.flood_field - time), "^3 seconds\n"));
- else
{
- sprint(source, sourcemsgstr);
- if(cmsgstr != "" && !privatesay)
- centerprint(source, sourcecmsgstr);
+ sprint(source, strcat("^3FLOOD CONTROL: ^7wait ^1", ftos(source.flood_field - time), "^3 seconds\n"));
+ ret = 0;
}
+ else
+ ret = -1;
}
- else if(privatesay)
- {
- sprint(source, sourcemsgstr);
- sprint(privatesay, msgstr);
- if(cmsgstr != "")
- centerprint(privatesay, cmsgstr);
- }
- else if(teamsay > 0)
- {
- sprint(source, sourcemsgstr);
- if(sourcecmsgstr != "")
- centerprint(source, sourcecmsgstr);
- FOR_EACH_REALPLAYER(head) if(head.team == source.team)
- if(head != source)
- {
- sprint(head, msgstr);
- if(cmsgstr != "")
- centerprint(head, cmsgstr);
- }
- }
- else if(teamsay < 0)
+ else
{
- sprint(source, sourcemsgstr);
- FOR_EACH_REALCLIENT(head) if(head.classname != "player")
- if(head != source)
- sprint(head, msgstr);
+ ret = 1;
}
- else if(sourcemsgstr != msgstr)
+
+ if(sourcemsgstr != "" && ret != 0)
{
- sprint(source, sourcemsgstr);
- FOR_EACH_REALCLIENT(head)
- if(head != source)
- sprint(head, msgstr);
+ if(ret < 0) // fake
+ {
+ sprint(source, sourcemsgstr);
+ if(sourcecmsgstr != "" && !privatesay)
+ centerprint(source, sourcecmsgstr);
+ }
+ else if(privatesay)
+ {
+ sprint(source, sourcemsgstr);
+ sprint(privatesay, msgstr);
+ if(cmsgstr != "")
+ centerprint(privatesay, cmsgstr);
+ }
+ else if(teamsay > 0)
+ {
+ sprint(source, sourcemsgstr);
+ if(sourcecmsgstr != "")
+ centerprint(source, sourcecmsgstr);
+ FOR_EACH_REALPLAYER(head) if(head.team == source.team)
+ if(head != source)
+ {
+ sprint(head, msgstr);
+ if(cmsgstr != "")
+ centerprint(head, cmsgstr);
+ }
+ }
+ else if(teamsay < 0)
+ {
+ sprint(source, sourcemsgstr);
+ FOR_EACH_REALCLIENT(head) if(head.classname != "player")
+ if(head != source)
+ sprint(head, msgstr);
+ }
+ else if(sourcemsgstr != msgstr)
+ {
+ sprint(source, sourcemsgstr);
+ FOR_EACH_REALCLIENT(head)
+ if(head != source)
+ sprint(head, msgstr);
+ }
+ else
+ bprint(msgstr);
}
- else
- bprint(msgstr);
+
+ return ret;
}
float GetVoiceMessageVoiceType(string type)
var .string field;
fh = fopen(f, FILE_READ);
if(fh < 0)
+ {
+ dprint("Player sound file not found: ", f, "\n");
return;
+ }
while((s = fgets(fh)))
{
if(tokenize_console(s) != 3)
}
.float modelindex_for_playersound;
+.float skinindex_for_playersound;
void UpdatePlayerSounds()
{
if(self.modelindex == self.modelindex_for_playersound)
+ if(self.skinindex == self.skinindex_for_playersound)
return;
self.modelindex_for_playersound = self.modelindex;
+ self.skinindex_for_playersound = self.skinindex;
ClearPlayerSounds();
LoadPlayerSounds("sound/player/default.sounds", 1);
- LoadPlayerSounds(strcat(self.model, ".sounds"), 0);
+ LoadPlayerSounds(get_model_datafilename(self.playermodel, self.skinindex, "sounds"), 0);
+}
+
+void FakeGlobalSound(string sample, float chan, float voicetype)
+{
+ float n;
+ float tauntrand;
+
+ if(sample == "")
+ return;
+
+ tokenize_console(sample);
+ n = stof(argv(1));
+ if(n > 0)
+ sample = strcat(argv(0), ftos(floor(random() * n + 1)), ".wav"); // randomization
+ else
+ sample = strcat(argv(0), ".wav"); // randomization
+
+ switch(voicetype)
+ {
+ case VOICETYPE_LASTATTACKER_ONLY:
+ break;
+ case VOICETYPE_LASTATTACKER:
+ if(self.pusher)
+ {
+ msg_entity = self;
+ if(clienttype(msg_entity) == CLIENTTYPE_REAL)
+ soundto(MSG_ONE, self, chan, sample, VOL_BASE, ATTN_NONE);
+ }
+ break;
+ case VOICETYPE_TEAMRADIO:
+ msg_entity = self;
+ if(msg_entity.cvar_cl_voice_directional == 1)
+ soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_MIN);
+ else
+ soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);
+ break;
+ case VOICETYPE_AUTOTAUNT:
+ if(!sv_autotaunt)
+ break;
+ if(!sv_taunt)
+ break;
+ if(sv_gentle)
+ break;
+ tauntrand = random();
+ msg_entity = self;
+ if (tauntrand < msg_entity.cvar_cl_autotaunt)
+ {
+ if (msg_entity.cvar_cl_voice_directional >= 1)
+ soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, bound(ATTN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, ATTN_MAX));
+ else
+ soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);
+ }
+ break;
+ case VOICETYPE_TAUNT:
+ if(self.classname == "player")
+ if(self.deadflag == DEAD_NO)
+ setanim(self, self.anim_taunt, FALSE, TRUE, TRUE);
+ if(!sv_taunt)
+ break;
+ if(sv_gentle)
+ break;
+ msg_entity = self;
+ if (msg_entity.cvar_cl_voice_directional >= 1)
+ soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, bound(ATTN_MIN, msg_entity.cvar_cl_voice_directional_taunt_attenuation, ATTN_MAX));
+ else
+ soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);
+ break;
+ case VOICETYPE_PLAYERSOUND:
+ msg_entity = self;
+ soundto(MSG_ONE, self, chan, sample, VOL_BASE, ATTN_NORM);
+ break;
+ default:
+ backtrace("Invalid voice type!");
+ break;
+ }
}
void GlobalSound(string sample, float chan, float voicetype)
{
case VOICETYPE_LASTATTACKER_ONLY:
if(self.pusher)
- if(self.pusher.team == self.team)
+ {
+ msg_entity = self.pusher;
+ if(clienttype(msg_entity) == CLIENTTYPE_REAL)
{
- msg_entity = self.pusher;
- if(clienttype(msg_entity) == CLIENTTYPE_REAL)
- {
- if(msg_entity.cvar_cl_voice_directional == 1)
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_MIN);
- else
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);
- }
+ if(msg_entity.cvar_cl_voice_directional == 1)
+ soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_MIN);
+ else
+ soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);
}
+ }
break;
case VOICETYPE_LASTATTACKER:
if(self.pusher)
- if(self.pusher.team == self.team)
+ {
+ msg_entity = self.pusher;
+ if(clienttype(msg_entity) == CLIENTTYPE_REAL)
{
- msg_entity = self.pusher;
- if(clienttype(msg_entity) == CLIENTTYPE_REAL)
- {
- if(msg_entity.cvar_cl_voice_directional == 1)
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_MIN);
- else
- soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);
- }
- msg_entity = self;
- if(clienttype(msg_entity) == CLIENTTYPE_REAL)
- soundto(MSG_ONE, self, chan, sample, VOL_BASE, ATTN_NONE);
+ if(msg_entity.cvar_cl_voice_directional == 1)
+ soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_MIN);
+ else
+ soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);
}
+ msg_entity = self;
+ if(clienttype(msg_entity) == CLIENTTYPE_REAL)
+ soundto(MSG_ONE, self, chan, sample, VOL_BASE, ATTN_NONE);
+ }
break;
case VOICETYPE_TEAMRADIO:
FOR_EACH_REALCLIENT(msg_entity)
else
soundto(MSG_ONE, self, chan, sample, VOL_BASEVOICE, ATTN_NONE);
}
+ break;
case VOICETYPE_PLAYERSOUND:
sound(self, chan, sample, VOL_BASE, ATTN_NORM);
break;
void PlayerSound(.string samplefield, float chan, float voicetype)
{
- string sample;
- sample = self.samplefield;
- GlobalSound(sample, chan, voicetype);
+ GlobalSound(self.samplefield, chan, voicetype);
}
void VoiceMessage(string type, string msg)
{
var .string sample;
- var float voicetype, ownteam;
+ float voicetype, ownteam;
+ float flood;
sample = GetVoiceMessageSampleField(type);
if(GetPlayerSoundSampleField_notFound)
voicetype = GetVoiceMessageVoiceType(type);
ownteam = (voicetype == VOICETYPE_TEAMRADIO);
- float flood;
- float flood_spv;
- var .float flood_field;
-
- flood = 0;
- if(ownteam)
- {
- flood_spv = cvar("g_voice_flood_spv_team");
- flood_field = floodcontrol_voiceteam;
- }
- else
- {
- flood_spv = cvar("g_voice_flood_spv");
- flood_field = floodcontrol_voice;
- }
-
- if(time >= self.flood_field)
- self.flood_field = max(time, self.flood_field) + flood_spv;
- else
- flood = 1;
-
- if (timeoutStatus == 2) //when game is paused, no flood protection
- self.flood_field = flood = 0;
-
- if (msg != "")
- Say(self, ownteam, world, msg, 0);
+ flood = Say(self, ownteam, world, msg, 1);
- if (!flood)
- PlayerSound(sample, CHAN_VOICE, voicetype);
+ if (flood > 0)
+ GlobalSound(self.sample, CHAN_VOICE, voicetype);
+ else if (flood < 0)
+ FakeGlobalSound(self.sample, CHAN_VOICE, voicetype);
}
void MoveToTeam(entity client, float team_colour, float type, float show_message)
{
if (client_hasweapon(self, imp, TRUE, TRUE))
W_SwitchWeapon_Force(self, imp);
+ else
+ self.selectweapon = imp; // update selectweapon ANYWAY
}
else
{
};
.float weaponcomplainindex;
-float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain)
+float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain, float skipmissing)
{
// We cannot tokenize in this function, as GiveItems calls this
// function. Thus we must use car/cdr.
string rest;
switchtonext = switchtolast = 0;
first_valid = prev_valid = 0;
+ float weaponcur;
+
+ if(skipmissing || pl.selectweapon == 0)
+ weaponcur = pl.switchweapon;
+ else
+ weaponcur = pl.selectweapon;
if(dir == 0)
switchtonext = 1;
++c;
- if(client_hasweapon(pl, weaponwant, TRUE, FALSE))
+ if(!skipmissing || client_hasweapon(pl, weaponwant, TRUE, FALSE))
{
if(switchtonext)
return weaponwant;
if(!first_valid)
first_valid = weaponwant;
- if(weaponwant == pl.switchweapon)
+ if(weaponwant == weaponcur)
{
if(dir >= 0)
switchtonext = 1;
void W_CycleWeapon(string weaponorder, float dir)
{
float w;
- w = W_GetCycleWeapon(self, weaponorder, dir, -1, 1);
+ w = W_GetCycleWeapon(self, weaponorder, dir, -1, 1, TRUE);
if(w > 0)
W_SwitchWeapon(w);
}
void W_NextWeaponOnImpulse(float imp)
{
float w;
- w = W_GetCycleWeapon(self, self.cvar_cl_weaponpriority, +1, imp, 1);
+ w = W_GetCycleWeapon(self, self.cvar_cl_weaponpriority, +1, imp, 1, (self.cvar_cl_weaponimpulsemode == 0));
if(w > 0)
W_SwitchWeapon(w);
}
float w_getbestweapon(entity e)
{
- return W_GetCycleWeapon(e, e.cvar_cl_weaponpriority, 0, -1, 0);
+ return W_GetCycleWeapon(e, e.cvar_cl_weaponpriority, 0, -1, FALSE, TRUE);
};
// generic weapons table
w = self.weapon;
if (w == 0)
return; // just in case
+ if(MUTATOR_CALLHOOK(ForbidThrowCurrentWeapon))
+ return;
if (g_weaponarena)
return;
if (g_lms)
return;
- if (g_nixnex)
- return;
if (g_nexball && w == WEP_GRENADE_LAUNCHER)
return;
if (!cvar("g_pickup_items"))
return;
if(!W_IsWeaponThrowable(w))
return;
+ if(self.weaponentity.state != WS_READY)
+ return;
wb = W_WeaponBit(w);
if(self.weapons & wb != wb)
self.currentammo = 1;
#endif
};
-
-float nixnex_weapon;
-float nixnex_weapon_ammo;
-float nixnex_nextchange;
-float nixnex_nextweapon;
-float nixnex_nextweapon_ammo;
-.float nixnex_lastchange_id;
-.float nixnex_lastinfotime;
-.float nixnex_nextincr;
-
-float NixNex_CanChooseWeapon(float wpn)
-{
- entity e;
- e = get_weaponinfo(wpn);
- if(!e.weapons) // skip dummies
- return FALSE;
- if(g_weaponarena)
- {
- if not(g_weaponarena & e.weapons)
- return FALSE;
- }
- else
- {
- if(wpn == WEP_LASER && g_nixnex_with_laser)
- return FALSE;
- if not(e.spawnflags & WEP_FLAG_NORMAL)
- return FALSE;
- }
- return TRUE;
-}
-void Nixnex_ChooseNextWeapon()
-{
- float j;
- RandomSelection_Init();
- for(j = WEP_FIRST; j <= WEP_LAST; ++j)
- if(NixNex_CanChooseWeapon(j))
- RandomSelection_Add(world, j, string_null, 1, (j != nixnex_weapon));
- nixnex_nextweapon = RandomSelection_chosen_float;
- nixnex_nextweapon_ammo = W_AmmoItemCode(nixnex_nextweapon);
-}
-
-void Nixnex_GiveCurrentWeapon()
-{
- float dt;
- if(g_nixnex)
- {
- if(!nixnex_nextweapon)
- Nixnex_ChooseNextWeapon();
-
- dt = ceil(nixnex_nextchange - time);
-
- if(dt <= 0)
- {
- nixnex_weapon = nixnex_nextweapon;
- nixnex_weapon_ammo = nixnex_nextweapon_ammo;
- nixnex_nextweapon = 0;
- nixnex_nextchange = time + cvar("g_balance_nixnex_roundtime");
- //weapon_action(nixnex_weapon, WR_PRECACHE); // forget it, too slow
- }
-
- if(nixnex_nextchange != self.nixnex_lastchange_id) // this shall only be called once per round!
- {
- self.nixnex_lastchange_id = nixnex_nextchange;
- if (self.items & IT_UNLIMITED_WEAPON_AMMO)
- {
- self.ammo_shells = (nixnex_weapon_ammo & IT_SHELLS) ?
- cvar("g_pickup_shells_max") : 0;
- self.ammo_nails = (nixnex_weapon_ammo & IT_NAILS) ?
- cvar("g_pickup_nails_max") : 0;
- self.ammo_rockets = (nixnex_weapon_ammo & IT_ROCKETS) ?
- cvar("g_pickup_rockets_max") : 0;
- self.ammo_cells = (nixnex_weapon_ammo & IT_CELLS) ?
- cvar("g_pickup_cells_max") : 0;
- self.ammo_fuel = (nixnex_weapon_ammo & IT_FUEL) ?
- cvar("g_pickup_fuel_max") : 0;
- }
- else
- {
- self.ammo_shells = (nixnex_weapon_ammo & IT_SHELLS) ?
- cvar("g_balance_nixnex_ammo_shells") : 0;
- self.ammo_nails = (nixnex_weapon_ammo & IT_NAILS) ?
- cvar("g_balance_nixnex_ammo_nails") : 0;
- self.ammo_rockets = (nixnex_weapon_ammo & IT_ROCKETS) ?
- cvar("g_balance_nixnex_ammo_rockets") : 0;
- self.ammo_cells = (nixnex_weapon_ammo & IT_CELLS) ?
- cvar("g_balance_nixnex_ammo_cells") : 0;
- self.ammo_fuel = (nixnex_weapon_ammo & IT_FUEL) ?
- cvar("g_balance_nixnex_ammo_fuel") : 0;
- }
- self.nixnex_nextincr = time + cvar("g_balance_nixnex_incrtime");
- if(dt >= 1 && dt <= 5)
- self.nixnex_lastinfotime = -42;
- else
- centerprint(self, strcat("\n\n^2Active weapon: ^3", W_Name(nixnex_weapon)));
- }
- if(self.nixnex_lastinfotime != dt)
- {
- self.nixnex_lastinfotime = dt; // initial value 0 should count as "not seen"
- if(dt >= 1 && dt <= 5)
- centerprint(self, strcat("^3", ftos(dt), "^2 seconds until weapon change...\n\nNext weapon: ^3", W_Name(nixnex_nextweapon), "\n"));
- }
-
- if(!(self.items & IT_UNLIMITED_WEAPON_AMMO) && time > self.nixnex_nextincr)
- {
- if (nixnex_weapon_ammo & IT_SHELLS)
- self.ammo_shells = self.ammo_shells + cvar("g_balance_nixnex_ammoincr_shells");
- else if (nixnex_weapon_ammo & IT_NAILS)
- self.ammo_nails = self.ammo_nails + cvar("g_balance_nixnex_ammoincr_nails");
- else if (nixnex_weapon_ammo & IT_ROCKETS)
- self.ammo_rockets = self.ammo_rockets + cvar("g_balance_nixnex_ammoincr_rockets");
- else if (nixnex_weapon_ammo & IT_CELLS)
- self.ammo_cells = self.ammo_cells + cvar("g_balance_nixnex_ammoincr_cells");
- if (nixnex_weapon_ammo & IT_FUEL) // hook uses cells and fuel
- self.ammo_fuel = self.ammo_fuel + cvar("g_balance_nixnex_ammoincr_fuel");
- self.nixnex_nextincr = time + cvar("g_balance_nixnex_incrtime");
- }
-
- self.weapons = 0;
- if(g_nixnex_with_laser)
- self.weapons = self.weapons | WEPBIT_LASER;
- self.weapons = self.weapons | W_WeaponBit(nixnex_weapon);
-
- if(self.switchweapon != nixnex_weapon)
- if(!client_hasweapon(self, self.switchweapon, TRUE, FALSE))
- if(client_hasweapon(self, nixnex_weapon, TRUE, FALSE))
- W_SwitchWeapon(nixnex_weapon);
- }
-}
{
e.cnt = e.switchweapon;
e.switchweapon = w;
+ e.selectweapon = w;
}
.float antilag_debug;
}
else
{
- setmodel(self, strcat("models/weapons/h_", self.owner.weaponname, ".dpm")); // precision set below
- animfilename = strcat("models/weapons/h_", self.owner.weaponname, ".dpm.animinfo");
+ setmodel(self, strcat("models/weapons/h_", self.owner.weaponname, ".iqm")); // precision set below
+ animfilename = strcat("models/weapons/h_", self.owner.weaponname, ".iqm.animinfo");
animfile = fopen(animfilename, FILE_READ);
// preset some defaults that work great for renamed zym files (which don't need an animinfo)
self.anim_fire1 = '0 1 0.01';
};
// perform weapon to attack (weaponstate and attack_finished check is here)
+void W_SwitchToOtherWeapon(entity pl)
+{
+ // hack to ensure it switches to an OTHER weapon (in case the other fire mode still has ammo, we want that anyway)
+ float w, ww;
+ w = W_WeaponBit(pl.weapon);
+ pl.weapons &~= w;
+ ww = w_getbestweapon(pl);
+ pl.weapons |= w;
+ if(ww)
+ W_SwitchWeapon_Force(pl, ww);
+}
+float weapon_prepareattack_checkammo(float secondary)
+{
+ if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+ if (!weapon_action(self.weapon, WR_CHECKAMMO1 + secondary))
+ {
+ W_SwitchToOtherWeapon(self);
+ return FALSE;
+ }
+ return TRUE;
+}
.float race_penalty;
-float weapon_prepareattack(float secondary, float attacktime)
+float weapon_prepareattack_check(float secondary, float attacktime)
{
+ if(!weapon_prepareattack_checkammo(secondary))
+ return FALSE;
+
//if sv_ready_restart_after_countdown is set, don't allow the player to shoot
//if all players readied up and the countdown is running
if(time < game_starttime || time < self.race_penalty) {
return FALSE;
}
- if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
- if (!weapon_action(self.weapon, WR_CHECKAMMO1 + secondary))
- {
- // hack to ensure it switches to an OTHER weapon (in case the other fire mode still has ammo, we want that anyway)
- float w, ww;
- w = W_WeaponBit(self.weapon);
- self.weapons &~= w;
- ww = w_getbestweapon(self);
- self.weapons |= w;
- if(ww)
- W_SwitchWeapon_Force(self, ww);
- return FALSE;
- }
-
if (timeoutStatus == 2) //don't allow the player to shoot while game is paused
return FALSE;
if (self.weaponentity.state != WS_READY)
return FALSE;
}
+
+ return TRUE;
+}
+float weapon_prepareattack_do(float secondary, float attacktime)
+{
self.weaponentity.state = WS_INUSE;
self.spawnshieldtime = min(self.spawnshieldtime, time); // kill spawn shield when you fire
self.bulletcounter += 1;
//dprint("attack finished ", ftos(ATTACK_FINISHED(self)), "\n");
return TRUE;
-};
+}
+float weapon_prepareattack(float secondary, float attacktime)
+{
+ if(weapon_prepareattack_check(secondary, attacktime))
+ {
+ weapon_prepareattack_do(secondary, attacktime);
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
void weapon_thinkf(float fr, float t, void() func)
{
DropFlag(self.flagcarried, world, world);
if(self.ballcarried)
DropBall(self.ballcarried, self.origin, self.velocity);
- kh_Key_DropAll(self, TRUE);
WaypointSprite_PlayerDead();
self.classname = "observer";
if(g_ca)
{
float ft, fr;
- // note: flag 0x10 = no trail please
- sf = sf & 0x1F;
+ // note: flag 0x08 = no trail please (teleport bit)
+ sf = sf & 0x0F;
if(self.csqcprojectile_clientanimate)
sf |= 0x80; // client animated, not interpolated
sf |= 0x20;
}
+ if(self.gravity != 0)
+ sf |= 0x10;
+
WriteByte(MSG_ENTITY, ENT_CLIENT_PROJECTILE);
WriteByte(MSG_ENTITY, sf);
WriteCoord(MSG_ENTITY, self.velocity_x);
WriteCoord(MSG_ENTITY, self.velocity_y);
WriteCoord(MSG_ENTITY, self.velocity_z);
- WriteCoord(MSG_ENTITY, self.gravity);
+ if(sf & 0x10)
+ WriteCoord(MSG_ENTITY, self.gravity);
}
if(sf & 0x20)
if(e.SendEntity == CSQCProjectile_SendEntity)
{
// send new origin data
- e.SendFlags |= 1;
+ e.SendFlags |= 0x01;
}
}
{
if(e.SendEntity == CSQCProjectile_SendEntity)
{
- // send new origin data and mark as teleported
- e.SendFlags |= 0x11;
+ // send new origin data
+ e.SendFlags |= 0x01;
+ // mark as teleported
+ e.SendFlags |= 0x08;
}
}
float ctf_score_value(string parameter);
float g_dm, g_domination, g_ctf, g_tdm, g_keyhunt, g_onslaught, g_assault, g_arena, g_ca, g_lms, g_runematch, g_race, g_nexball, g_cts;
-float g_cloaked, g_footsteps, g_jump_grunt, g_grappling_hook, g_laserguided_missile, g_midair, g_minstagib, g_nixnex, g_nixnex_with_laser, g_pinata, g_norecoil, g_vampire, g_minstagib_invis_alpha, g_bloodloss;
+float g_cloaked, g_footsteps, g_jump_grunt, g_grappling_hook, g_laserguided_missile, g_midair, g_minstagib, g_pinata, g_norecoil, g_vampire, g_minstagib_invis_alpha, g_bloodloss;
float g_warmup_limit;
float g_warmup_allguns;
float g_warmup_allow_timeout;
void ClearPlayerSounds();
void PlayerSound(.string samplefield, float channel, float voicetype);
void GlobalSound(string samplestring, float channel, float voicetype);
+void FakeGlobalSound(string samplestring, float channel, float voicetype);
void VoiceMessage(string type, string message);
// autotaunt system
float game_starttime; //point in time when the countdown is over
.float stat_game_starttime;
+.float stat_sv_airaccel_qw;
+.float stat_sv_airstrafeaccel_qw;
+.float stat_sv_airspeedlimit_nonqw;
+
void W_Porto_Remove (entity p);
.float projectiledeathtype;
.float cvar_cl_accuracy_data_share;
.float cvar_cl_accuracy_data_receive;
+
+.float cvar_cl_weaponimpulsemode;
+.float selectweapon; // last selected weapon of the player
+
+.float ballistics_density; // wall piercing factor, larger = bullet can pass through more
//DP_EF_RESTARTANIM_BIT
//idea: id software
-//darkplaces implementation: div0
+//darkplaces implementation: divVerent
//effects bit:
float EF_RESTARTANIM_BIT = 1048576;
//description:
//DP_EF_TELEPORT_BIT
//idea: id software
-//darkplaces implementation: div0
+//darkplaces implementation: divVerent
//effects bit:
float EF_TELEPORT_BIT = 2097152;
//description:
//DP_NULL_MODEL
//idea: Chris
-//darkplaces implementation: div0
+//darkplaces implementation: divVerent
//definitions:
//string dp_null_model = "null";
//description:
//note: atan2 can take unnormalized vectors (just like vectoyaw), and the function was included only for completeness (more often you want vectoyaw or vectoangles), atan2(v_x,v_y) * RAD2DEG gives the same result as vectoyaw(v)
//DP_QC_AUTOCVARS
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
//description:
//allows QC variables to be bound to cvars
//(works for float, string, vector types)
// string autocvar__cl_name;
//NOTE: copying a string-typed autocvar to another variable/field, and then
//changing the cvar or returning from progs is UNDEFINED. Writing to autocvar
-//globals is UNDEFINED. Accessing autocvar globals after cvar_set()ing that
+//globals is UNDEFINED. Accessing autocvar globals after cvar_set()ing that
//cvar is IMPLEMENTATION DEFINED (an implementation may either yield the
-//previous, or the current, value). Whether autocvar globals, after restoring
-//a savegame, have the cvar's current value, or the original value at time of
-//saving, is UNDEFINED. Restoring a savegame however must not restore the
-//cvar values themselves.
+//previous, or the current, value). Writing to an autocvar global is NOT
+//ALLOWED.
//In case the cvar does NOT exist, then it is automatically created with the
//value of the autocvar initializer, if given. This is possible with e.g.
//frikqcc and fteqcc the following way:
//returns the default value of a cvar, as a tempstring.
//DP_QC_CVAR_DESCRIPTION
-//idea: div0
-//DarkPlaces implementation: div0
+//idea: divVerent
+//DarkPlaces implementation: divVerent
//builtin definitions:
string(string name) cvar_description = #518;
//description:
//returns the value of a cvar, as a tempstring.
//DP_QC_CVAR_TYPE
-//idea: div0
-//DarkPlaces implementation: div0
+//idea: divVerent
+//DarkPlaces implementation: divVerent
//builtin definitions:
float(string name) cvar_type = #495;
float CVAR_TYPEFLAG_EXISTS = 1;
//prints "entity 1" or similar into a string. (this was a Q2 builtin)
//DP_QC_EXTRESPONSEPACKET
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
//builtin definitions:
string(void) getextresponse = #624;
//description:
//similar to find() but returns a chain of entities like findradius.
//DP_QC_FINDCHAIN_TOFIELD
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
//builtin definitions:
entity(.string fld, float match, .entity tofield) findradius_tofield = #22;
entity(.string fld, string match, .entity tofield) findchain_tofield = #402;
float SPA_LIGHTMAP0_COLOR = 6;
//builtin definitions:
vector(entity e, float s, float n, float a) getsurfacepointattribute = #486;
+
//description:
//function to query extended information about a point on a certain surface
//DP_QC_GETSURFACETRIANGLE
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
//builtin definitions:
float(entity e, float s) getsurfacenumtriangles = #628;
vector(entity e, float s, float n) getsurfacetriangle = #629;
//DP_QC_GETTAGINFO_BONEPROPERTIES
//idea: daemon
-//DarkPlaces implementation: div0
+//DarkPlaces implementation: divVerent
//global definitions:
float gettaginfo_parent;
string gettaginfo_name;
//DP_QC_GETTIME
//idea: tZork
-//darkplaces implementation: tZork, div0
+//darkplaces implementation: tZork, divVerent
//constant definitions:
float GETTIME_FRAMESTART = 0; // time of start of frame
float GETTIME_REALTIME = 1; // current time (may be OS specific)
//some timers to query...
//DP_QC_GETTIME_CDTRACK
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
//constant definitions:
float GETTIME_CDTRACK = 4;
//description:
//returns the playing time of the current cdtrack when passed to gettime()
//DP_QC_LOG
-//darkplaces implementation: div0
+//darkplaces implementation: divVerent
//builtin definitions:
float log(float f) = #532;
//description:
//useful math functions, sine of val, cosine of val, square root of val, and raise a to power b, respectively.
//DP_QC_SPRINTF
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
//builtin definitions:
string(string format, ...) sprintf = #627;
//description:
// ouxXc take a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to an unsigned int
// eEfFgG take a float if no length is specified or h is, and an int/entity if l is specified as length, and cast it to a double
// s takes a string
+// vV takes a vector, and processes the three components as if it were a gG for all three components, separated by space
// For conversions s and c, the flag # makes precision and width interpreted
// as byte count, by default it is interpreted as character count in UTF-8
// enabled engines. No other conversions can create wide characters, and #
//possibly useful for parsing IPv4 addresses (such as "1.2.3.4") and IPv6 addresses (such as "[1234:5678:9abc:def0:1234:5678:9abc:def0]:26000")
//DP_QC_TOKENIZE_CONSOLE
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
//builtin definitions:
float(string s) tokenize_console = #514;
float(float i) argv_start_index = #515;
//allows traces to hit only world (ignoring all entities, unlike MOVE_NOMONSTERS which hits all bmodels), use as the nomonsters parameter to trace functions
//DP_QC_UNLIMITEDTEMPSTRINGS
-//idea: div0
+//idea: divVerent
//darkplaces implementation: LordHavoc
//description:
//this extension alters Quake behavior such that instead of reusing a single
//creates v_forward, v_right, and v_up vectors given a forward vector, similar to makevectors except it takes a forward direction vector instead of angles.
//DP_QC_WHICHPACK
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
//builtin definitions:
string(string filename) whichpack = #503;
//description:
//returns the name of the pak/pk3/whatever containing the given file, in the same path space as FRIK_FILE functions use (that is, possibly with a path name prefix)
//DP_QC_URI_ESCAPE
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
//URI::Escape's functionality
string(string in) uri_escape = #510;
string(string in) uri_unescape = #511;
//DP_QC_URI_GET
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
//loads text from an URL into a string
//returns 1 on success of initiation, 0 if there are too many concurrent
//connections already or if the URL is invalid
//this extension indicates that FTE_CSQC_SKELETONOBJECTS functionality is available in server QC (as well as CSQC).
//DP_SV_SPAWNFUNC_PREFIX
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
//Make functions whose name start with spawnfunc_ take precedence as spawn function for loading entities.
//Useful if you have a field ammo_shells (required in any Quake mod) but want to support spawn functions called ammo_shells (like in Q3A).
//Optionally, you can declare a global "float require_spawnfunc_prefix;" which will require ANY spawn function to start with that prefix.
//implementation notes:
//entity customization is done before per-client culling (visibility for instance) because the entity may be doing setorigin to display itself in different locations on different clients, may be altering its .modelindex, .effects and other fields important to culling, so customized entities increase cpu usage (non-customized entities can use all the early culling they want however, as they are not changing on a per client basis).
+//DP_SV_DISCARDABLEDEMO
+//idea: parasti
+//darkplaces implementation: parasti
+//field definitions:
+.float discardabledemo;
+//description:
+//when this field is set to a non-zero value on a player entity, a possibly recorded server-side demo for the player is discarded
+//Note that this extension only works if:
+// auto demos are enabled (the cvar sv_autodemo_perclient is set)
+// discarding demos is enabled (the cvar sv_autodemo_perclient_discardable is set)
+
//DP_SV_DRAWONLYTOCLIENT
//idea: LordHavoc
//darkplaces implementation: LordHavoc
// To mimic the engine's default behavior, simply call remove(self).
//DP_SV_ONENTITYPREPOSTSPAWNFUNCTION
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
//engine-called QC prototypes:
//void() SV_OnEntityPreSpawnFunction;
//void() SV_OnEntityPostSpawnFunction;
//this extension allows precache_model and precache_sound (and any variants) to be used during the game (with automatic messages to clients to precache the new model/sound indices), also setmodel/sound/ambientsound can be called without precaching first (they will cause an automatic precache).
//DP_SV_QCSTATUS
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
//1. A global variable
string worldstatus;
//Its content is set as "qcstatus" field in the rules.
//range is 0 to infinite, recommended values to try are 0.1 (very slow, 10% speed), 1 (normal speed), 5 (500% speed).
//DP_SV_WRITEPICTURE
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
//builtin definitions:
void(float to, string s, float sz) WritePicture = #501;
//description:
//idea: Spike, LordHavoc
//darkplaces implementation: LordHavoc
//builtin definitions:
-float(float modlindex) skel_create = #263; // create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex.
+// all skeleton numbers are 1-based (0 being no skeleton)
+// all bone numbers are 1-based (0 being invalid)
+float(float modlindex) skel_create = #263; // create a skeleton (be sure to assign this value into .skeletonindex for use), returns skeleton index (1 or higher) on success, returns 0 on failure (for example if the modelindex is not skeletal), it is recommended that you create a new skeleton if you change modelindex, as the skeleton uses the hierarchy from the model.
float(float skel, entity ent, float modlindex, float retainfrac, float firstbone, float lastbone) skel_build = #264; // blend in a percentage of standard animation, 0 replaces entirely, 1 does nothing, 0.5 blends half, etc, and this only alters the bones in the specified range for which out of bounds values like 0,100000 are safe (uses .frame, .frame2, .frame3, .frame4, .lerpfrac, .lerpfrac3, .lerpfrac4, .frame1time, .frame2time, .frame3time, .frame4time), returns skel on success, 0 on failure
-float(float skel) skel_get_numbones = #265; // returns how many bones exist in the created skeleton
-string(float skel, float bonenum) skel_get_bonename = #266; // returns name of bone (as a tempstring)
-float(float skel, float bonenum) skel_get_boneparent = #267; // returns parent num for supplied bonenum, -1 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)
-float(float skel, string tagname) skel_find_bone = #268; // get number of bone with specified name, 0 on failure, tagindex (bonenum+1) on success, same as using gettagindex on the modelindex
+float(float skel) skel_get_numbones = #265; // returns how many bones exist in the created skeleton, 0 if skeleton does not exist
+string(float skel, float bonenum) skel_get_bonename = #266; // returns name of bone (as a tempstring), "" if invalid bonenum (< 1 for example) or skeleton does not exist
+float(float skel, float bonenum) skel_get_boneparent = #267; // returns parent num for supplied bonenum, 0 if bonenum has no parent or bone does not exist (returned value is always less than bonenum, you can loop on this)
+float(float skel, string tagname) skel_find_bone = #268; // get number of bone with specified name, 0 on failure, bonenum (1-based) on success, same as using gettagindex but takes modelindex instead of entity
vector(float skel, float bonenum) skel_get_bonerel = #269; // get matrix of bone in skeleton relative to its parent - sets v_forward, v_right, v_up, returns origin (relative to parent bone)
vector(float skel, float bonenum) skel_get_boneabs = #270; // get matrix of bone in skeleton in model space - sets v_forward, v_right, v_up, returns origin (relative to entity)
void(float skel, float bonenum, vector org) skel_set_bone = #271; // set matrix of bone relative to its parent, reads v_forward, v_right, v_up, takes origin as parameter (relative to parent bone)
//description:
//when a savegame is loaded, this function is called
-//XONOTIC_PLAYERMODEL
-//idea: Xonotic
+//NEXUIZ_PLAYERMODEL
+//idea: Nexuiz
//darkplaces implementation: Black
//console commands:
//playermodel <name> - FIXME: EXAMPLE NEEDED
.string playermodel; // name of player model sent by client
.string playerskin; // name of player skin sent by client
//description:
-//these client properties are used by Xonotic.
+//these client properties are used by Nexuiz.
//NXQ_GFX_LETTERBOX
//idea: nxQuake
//FTE_QC_CHECKPVS
//idea: Urre
-//darkplaces implementation: div0
+//darkplaces implementation: divVerent
//builtin definitions:
float checkpvs(vector viewpos, entity viewee) = #240;
//description:
//DP_CON_BESTWEAPON
//idea: many
-//darkplaces implementation: div0
+//darkplaces implementation: divVerent
//description:
//allows QC to register weapon properties for use by the bestweapon command, for mods that change required ammo count or type for the weapons
//it is done using console commands sent via stuffcmd:
void(float bufhandle, float string_index) bufstr_free = #469;
//DP_QC_STRINGBUFFERS_CVARLIST
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
//functions to list cvars and store their names into a stringbuffer
//cvars that start with pattern but not with antipattern will be stored into the buffer
void(float bufhandle, string pattern, string antipattern) buf_cvarlist = #517;
//strireplace does the same but uses case-insensitive matching of the 'search' term
//
//DP_QC_CRC16
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
//Some hash function to build hash tables with. This has to be be the CRC-16-CCITT that is also required for the QuakeWorld download protocol.
//When caseinsensitive is set, the CRC is calculated of the lower cased string.
float(float caseinsensitive, string s, ...) crc16 = #494;
//DP_SV_SHUTDOWN
-//idea: div0
-//darkplaces implementation: div0
+//idea: divVerent
+//darkplaces implementation: divVerent
//A function that gets called just before progs exit. To save persistent data from.
//It is not called on a crash or error.
//void SV_Shutdown();
-
-
+// EXPERIMENTAL (not finalized) EXTENSIONS:
//DP_PHYSICS
+//idea: LordHavoc
+//darkplaces implementation: LordHavoc, divVerent
+//constant definitions:
float SOLID_PHYSICS_BOX = 32;
float SOLID_PHYSICS_SPHERE = 33;
float SOLID_PHYSICS_CAPSULE = 34;
float MOVETYPE_PHYSICS = 32;
+float JOINTTYPE_POINT = 1; // point; uses origin (anchor)
+float JOINTTYPE_HINGE = 2; // hinge; uses origin (anchor) and angles (axis)
+float JOINTTYPE_SLIDER = 3; // slider; uses angles (axis)
+float JOINTTYPE_UNIVERSAL = 4; // universal; uses origin (anchor) and angles (forward is axis1, up is axis2)
+float JOINTTYPE_HINGE2 = 5; // hinge2; uses origin (anchor), angles (axis1), velocity (axis2)
+//field definitions:
.float mass;
-
-.float jointtype;
+.float jointtype; // see JOINTTYPE_ definitions above
// common joint properties:
// .entity aiment, enemy; // connected objects
// .vector movedir;
// movedir_y = -1 * max motor force to use
// movedir_z = stop position (+/-), set to 0 for no stop
// note that ODE does not support both in one anyway
-// motor properties only make sense for hinge and slider!
-
-float JOINTTYPE_POINT = 1;
-// .vector origin; // point anchor
-
-float JOINTTYPE_HINGE = 2;
-// .vector origin; // hinge anchor
-// .vector angles; // hinge axis
-
-float JOINTTYPE_SLIDER = 3;
-// .vector angles; // slider axis
-
-float JOINTTYPE_UNIVERSAL = 4;
-// .vector origin; // universal anchor
-// .vector angles; // universal axis1 and axis2 (axis1 is forward, axis2 is up)
-
-float JOINTTYPE_HINGE2 = 5;
-// .vector origin; // hinge2 anchor
-// .vector angles; // hinge2 first axis (as angles)
-// .vector velocity; // hinge2 second axis (as vector)
-
-
-
-
-
+//description:
+//various physics properties can be defined in an entity and are executed via
+//ODE
return 1;
}
+vector GetHeadshotMins(entity targ)
+{
+ return '0.6 0 0' * targ.mins_x + '0 0.6 0' * targ.mins_y + '0 0 1' * (1.3 * targ.view_ofs_z - 0.3 * targ.maxs_z);
+}
+vector GetHeadshotMaxs(entity targ)
+{
+ return '0.6 0 0' * targ.maxs_x + '0 0.6 0' * targ.maxs_y + '0 0 1' * targ.maxs_z;
+}
+
void UpdateFrags(entity player, float f)
{
PlayerTeamScore_AddScore(player, f);
}
// FIXME fix the mess this is (we have REAL points now!)
- if(g_runematch)
- {
- f = RunematchHandleFrags(attacker, targ, f);
- }
- else if(g_keyhunt)
+ entity oldself;
+ oldself = self;
+ self = attacker;
+ frag_attacker = attacker;
+ frag_target = targ;
+ frag_score = f;
+ if(MUTATOR_CALLHOOK(GiveFragsForKill))
{
- f = kh_HandleFrags(attacker, targ, f);
+ f = frag_score;
+ self = oldself;
}
- else if(g_lms)
+ else
{
- // remove a life
- float tl;
- tl = PlayerScore_Add(targ, SP_LMS_LIVES, -1);
- if(tl < lms_lowest_lives)
- lms_lowest_lives = tl;
- if(tl <= 0)
+ self = oldself;
+ if(g_runematch)
{
- if(!lms_next_place)
- lms_next_place = player_count;
- PlayerScore_Add(targ, SP_LMS_RANK, lms_next_place); // won't ever spawn again
- --lms_next_place;
+ f = RunematchHandleFrags(attacker, targ, f);
}
- f = 0;
- }
- else if(g_ctf)
- {
- if(g_ctf_ignore_frags)
+ else if(g_lms)
+ {
+ // remove a life
+ float tl;
+ tl = PlayerScore_Add(targ, SP_LMS_LIVES, -1);
+ if(tl < lms_lowest_lives)
+ lms_lowest_lives = tl;
+ if(tl <= 0)
+ {
+ if(!lms_next_place)
+ lms_next_place = player_count;
+ PlayerScore_Add(targ, SP_LMS_RANK, lms_next_place); // won't ever spawn again
+ --lms_next_place;
+ }
f = 0;
+ }
+ else if(g_ctf)
+ {
+ if(g_ctf_ignore_frags)
+ f = 0;
+ }
}
attacker.totalfrags += f;
// 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 + '0.6 0 0' * targ.mins_x + '0 0.6 0' * targ.mins_y + '0 0 1' * (1.3 * targ.view_ofs_z - 0.3 * targ.maxs_z);
- headmaxs = org + '0.6 0 0' * targ.maxs_x + '0 0.6 0' * targ.maxs_y + '0 0 1' * targ.maxs_z;
+ headmins = org + GetHeadshotMins(targ);
+ headmaxs = org + GetHeadshotMaxs(targ);
if(trace_hits_box(railgun_start, railgun_end, headmins, headmaxs))
{
deathtype |= HITTYPE_HEADSHOT;
Net_LinkEntity(self, TRUE, 0, g_clientmodel_genericsendentity);
// non-solid model entities:
-void spawnfunc_misc_gamemodel() { G_MODEL_INIT (SOLID_NOT) } // model entity
-void spawnfunc_misc_clientmodel() { G_CLIENTMODEL_INIT(SOLID_NOT) } // model entity
-void spawnfunc_misc_models() { G_MODEL_INIT (SOLID_NOT) } // DEPRECATED old compat entity with confusing name, do not use
+void spawnfunc_misc_gamemodel() { self.angles_x = -self.angles_x; G_MODEL_INIT (SOLID_NOT) } // model entity
+void spawnfunc_misc_clientmodel() { self.angles_x = -self.angles_x; G_CLIENTMODEL_INIT(SOLID_NOT) } // model entity
+void spawnfunc_misc_models() { self.angles_x = -self.angles_x; G_MODEL_INIT (SOLID_NOT) } // DEPRECATED old compat entity with confusing name, do not use
// non-solid brush entities:
void spawnfunc_func_illusionary() { G_MODEL_INIT (SOLID_NOT) } // Q1 name (WARNING: MISPREDICTED)
#ifdef TETRIS
+float autocvar_g_bastet;
.vector tet_org;
float tet_vs_current_id;
var float tet_high_score = 0;
-float TET_LINES = 20;
+vector TET_START_PIECE_POS = '5 1 0';
+float TET_LINES = 22;
+float TET_DISPLAY_LINES = 20;
float TET_WIDTH = 10;
+string TET_EMPTY_LINE = "0000000000"; // must match TET_WIDTH
//character values
float TET_BORDER = 139;
float TET_BLOCK = 133;
float PIECES = 7;
-.float line1, line2, line3, line4, line5, line6, line7,
-line8, line9, line10, line11, line12, line13, line14, line15,
-line16, line17, line18, line19, line20;
-
+float tet_line_buf;
float SVC_CENTERPRINTa = 26;
*********************************
*/
-void SetLine(float ln, float vl)
+void SetLine(float ln, string vl)
{
- if (ln == 1)
- self.line1 = vl;
- else if (ln == 2)
- self.line2 = vl;
- else if (ln == 3)
- self.line3 = vl;
- else if (ln == 4)
- self.line4 = vl;
- else if (ln == 5)
- self.line5 = vl;
- else if (ln == 6)
- self.line6 = vl;
- else if (ln == 7)
- self.line7 = vl;
- else if (ln == 8)
- self.line8 = vl;
- else if (ln == 9)
- self.line9 = vl;
- else if (ln == 10)
- self.line10 = vl;
- else if (ln == 11)
- self.line11 = vl;
- else if (ln == 12)
- self.line12 = vl;
- else if (ln == 13)
- self.line13 = vl;
- else if (ln == 14)
- self.line14 = vl;
- else if (ln == 15)
- self.line15 = vl;
- else if (ln == 16)
- self.line16 = vl;
- else if (ln == 17)
- self.line17 = vl;
- else if (ln == 18)
- self.line18 = vl;
- else if (ln == 19)
- self.line19 = vl;
- else if (ln == 20)
- self.line20 = vl;
+ if(ln < 1 || ln > TET_LINES)
+ error("WTF");
+ bufstr_set(tet_line_buf, ln + TET_LINES * num_for_edict(self), vl);
};
-float GetLine(float ln)
+string GetLine(float ln)
{
- if (ln == 1)
- return self.line1;
- else if (ln == 2)
- return self.line2;
- else if (ln == 3)
- return self.line3;
- else if (ln == 4)
- return self.line4;
- else if (ln == 5)
- return self.line5;
- else if (ln == 6)
- return self.line6;
- else if (ln == 7)
- return self.line7;
- else if (ln == 8)
- return self.line8;
- else if (ln == 9)
- return self.line9;
- else if (ln == 10)
- return self.line10;
- else if (ln == 11)
- return self.line11;
- else if (ln == 12)
- return self.line12;
- else if (ln == 13)
- return self.line13;
- else if (ln == 14)
- return self.line14;
- else if (ln == 15)
- return self.line15;
- else if (ln == 16)
- return self.line16;
- else if (ln == 17)
- return self.line17;
- else if (ln == 18)
- return self.line18;
- else if (ln == 19)
- return self.line19;
- else if (ln == 20)
- return self.line20;
- else
- return 0;
+ if(ln < 1 || ln > TET_LINES)
+ error("WTF");
+ if(ln < 1 || ln > TET_LINES)
+ return TET_EMPTY_LINE;
+ return bufstr_get(tet_line_buf, ln + TET_LINES * num_for_edict(self));
};
-float GetXBlock(float x, float dat)
-{
- if (x == 1)
- return dat & 3;
- else if (x == 2)
- return (dat & 12) / 4;
- else if (x == 3)
- return (dat & 48) / 16;
- else if (x == 4)
- return (dat & 192) / 64;
- else if (x == 5)
- return (dat & 768) / 256;
- else if (x == 6)
- return (dat & 3072) / 1024;
- else if (x == 7)
- return (dat & 12288) / 4096;
- else if (x == 8)
- return (dat & 49152) / 16384;
- else if (x == 9)
- return (dat & 196608) / 65536;
- else if (x == 10)
- return (dat & 786432) / 262144;
- else
- return 0;
+float GetXBlock(float x, string dat)
+{
+ if(x < 1 || x > TET_WIDTH)
+ error("WTF");
+ return stof(substring(dat, x-1, 1));
};
-float SetXBlock(float x, float dat, float new)
-{
- if (x == 1)
- return (dat - (dat & 3)) | new;
- else if (x == 2)
- return (dat - (dat & 12)) | (new*4);
- else if (x == 3)
- return (dat - (dat & 48)) | (new*16);
- else if (x == 4)
- return (dat - (dat & 192)) | (new*64);
- else if (x == 5)
- return (dat - (dat & 768)) | (new*256);
- else if (x == 6)
- return (dat - (dat & 3072)) | (new*1024);
- else if (x == 7)
- return (dat - (dat & 12288)) | (new*4096);
- else if (x == 8)
- return (dat - (dat & 49152)) | (new*16384);
- else if (x == 9)
- return (dat - (dat & 196608)) | (new*65536);
- else if (x == 10)
- return (dat - (dat & 786432)) | (new*262144);
- else
- return dat;
+string SetXBlock(float x, string dat, float new)
+{
+ return strcat(
+ substring(dat, 0, x-1),
+ ftos(new),
+ substring(dat, x, -1)
+ );
};
void SetSquare(float x, float y, float val)
{
- float dat;
-
+ string dat;
dat = GetLine(y);
- dat = SetXBlock(x, dat, val & 3);
+ dat = SetXBlock(x, dat, val);
SetLine(y, dat);
};
+float PieceColor(float pc)
+{
+ if (pc == 1)
+ return 3; // O
+ else if (pc == 2)
+ return 4; // J
+ else if (pc == 3)
+ return 7; // L // we don't have orange, let's use white instead!
+ else if (pc == 4)
+ return 5; // I
+ else if (pc == 5)
+ return 1; // Z
+ else if (pc == 6)
+ return 2; // S
+ else if (pc == 7)
+ return 6; // T
+ else
+ return 0;
+}
vector PieceShape(float pc)
{
if (pc == 1)
- return '5 5 0'; // O
+ return '20 20 0'; // O
else if (pc == 2)
return '1 21 0'; // J
else if (pc == 3)
- return '21 1 0'; // L
+ return '16 21 0'; // L
else if (pc == 4)
- return '85 0 0'; // I
+ return '0 85 0'; // I
else if (pc == 5)
return '5 20 0'; // Z
else if (pc == 6)
else
return '0 0 0';
}
-
+vector PieceSize(float pc)
+{
+ if (pc == 1)
+ return '2 2 0'; // O
+ else if (pc == 2)
+ return '3 2 0'; // J
+ else if (pc == 3)
+ return '3 2 0'; // L
+ else if (pc == 4)
+ return '4 1 0'; // I
+ else if (pc == 5)
+ return '3 2 0'; // Z
+ else if (pc == 6)
+ return '3 2 0'; // S
+ else if (pc == 7)
+ return '3 2 0'; // T
+ else
+ return '0 0 0';
+}
vector PieceCenter(float pc)
{
if(pc == 1)
- return '1.5 1.5 0'; // O
+ return '2.5 1.5 0'; // O
else if (pc == 2)
return '2 2 0'; // J
else if (pc == 3)
- return '2 1 0'; // L
+ return '2 2 0'; // L
else if (pc == 4)
- return '2.5 1.5 0'; // I
+ return '2.5 2.5 0'; // I
else if (pc == 5)
return '2 2 0'; // Z
else if (pc == 6)
float PieceMetric(float x, float y, float rot, float pc)
{
float t;
- vector piece_dat;
- float wid;
+ vector ce;
// return bits of a piece
- wid = piece_dat_z + 1;
- piece_dat = PieceCenter(pc);
+ ce = PieceCenter(pc);
if (rot == 1) // 90 degrees
{
// x+cx, y+cy -> -y+cx, x+cy
// x = X-cx
// y = Y-cy
t = y;
- y = x - piece_dat_x + piece_dat_y;
- x = -t + piece_dat_x + piece_dat_y;
+ y = x - ce_x + ce_y;
+ x = -t + ce_x + ce_y;
}
else if (rot == 2)//180
{
- x = 2 * piece_dat_x - x;
- y = 2 * piece_dat_y - y;
+ x = 2 * ce_x - x;
+ y = 2 * ce_y - y;
}
else if (rot == 3) // 270
{
// x = X-cx
// y = Y-cy
t = y;
- y = -x + piece_dat_y + piece_dat_x;
- x = t - piece_dat_y + piece_dat_x;
+ y = -x + ce_y + ce_x;
+ x = t - ce_y + ce_x;
}
if (x < 1 || y < 1 || x > 4 || y > 2)
return 0;
- piece_dat = PieceShape(pc);
+ ce = PieceShape(pc);
if (y == 1)
- return GetXBlock(x, piece_dat_x); // first row
+ return !!(ce_x & pow(4, x-1)); // first row
else if (y == 2)
- return GetXBlock(x, piece_dat_y); // second row
+ return !!(ce_y & pow(4, x-1)); // second row
else
return 0; // illegal parms
};
+vector tet_piecemins;
+vector tet_piecemaxs;
+void PieceMinsMaxs(float rot, float pc)
+{
+ vector sz, ce;
+ float t;
+ vector v;
+
+ sz = PieceSize(pc);
+ ce = PieceCenter(pc);
+ // 1 = 2..2
+ // 2 = 2..3
+ // 3 = 1..3
+ // 4 = 1..4
+ tet_piecemins_x = floor(3.0 - sz_x * 0.5);
+ tet_piecemaxs_x = floor(2.0 + sz_x * 0.5);
+ if(sz_y == 1)
+ {
+ // special case for "I"
+ tet_piecemins_y = tet_piecemaxs_y = 2;
+ }
+ else
+ {
+ tet_piecemins_y = 1;
+ tet_piecemaxs_y = sz_y;
+ }
+ //print(sprintf("ce%v sz%v mi%v ma%v\n", ce, sz, tet_piecemins, tet_piecemaxs));
+ if (rot == 1) // 90 degrees
+ {
+ t = tet_piecemins_y;
+ tet_piecemins_y = -tet_piecemins_x + ce_y + ce_x;
+ tet_piecemins_x = t - ce_y + ce_x;
+ t = tet_piecemaxs_y;
+ tet_piecemaxs_y = -tet_piecemaxs_x + ce_y + ce_x;
+ tet_piecemaxs_x = t - ce_y + ce_x;
+ // swap mins_y, maxs_y
+ t = tet_piecemins_y;
+ tet_piecemins_y = tet_piecemaxs_y;
+ tet_piecemaxs_y = t;
+ // TODO OPTIMIZE
+ }
+ else if (rot == 2)//180
+ {
+ v = tet_piecemins;
+ tet_piecemins = 2 * ce - tet_piecemaxs;
+ tet_piecemaxs = 2 * ce - v;
+ }
+ else if (rot == 3) // 270
+ {
+ t = tet_piecemins_y;
+ tet_piecemins_y = tet_piecemins_x - ce_x + ce_y;
+ tet_piecemins_x = -t + ce_x + ce_y;
+ t = tet_piecemaxs_y;
+ tet_piecemaxs_y = tet_piecemaxs_x - ce_x + ce_y;
+ tet_piecemaxs_x = -t + ce_x + ce_y;
+ // swap mins_x, maxs_x
+ t = tet_piecemins_x;
+ tet_piecemins_x = tet_piecemaxs_x;
+ tet_piecemaxs_x = t;
+ // TODO OPTIMIZE
+ }
+#ifdef VERIFY
+ print(vtos(tet_piecemins), "-");
+ print(vtos(tet_piecemaxs), "\n");
+ if(tet_piecemins_x > tet_piecemaxs_x)
+ error("inconsistent mins/maxs");
+ if(tet_piecemins_y > tet_piecemaxs_y)
+ error("inconsistent mins/maxs");
+ float i, j;
+ vector realmins, realmaxs;
+ realmins = '4 4 0';
+ realmaxs = '1 1 0';
+ for(i = 1; i <= 4; ++i)
+ for(j = 1; j <= 4; ++j)
+ if(PieceMetric(i, j, rot, pc))
+ {
+ realmins_x = min(realmins_x, i);
+ realmins_y = min(realmins_y, j);
+ realmaxs_x = max(realmaxs_x, i);
+ realmaxs_y = max(realmaxs_y, j);
+ }
+ if(realmins != tet_piecemins || realmaxs != tet_piecemaxs)
+ error(sprintf("incorrect mins/maxs: %v %v in %d rot %d mins %v maxs %v\n", realmins, realmaxs, rot, pc, tet_piecemins, tet_piecemaxs));
+#endif
+}
/*
*********************************
for (x = 1; x <= TET_WIDTH; x = x + 1)
{
- d = GetSquare(x, ln);
+ d = GetSquare(x, ln + TET_LINES - TET_DISPLAY_LINES);
if (d)
{
WriteChar(MSG_ONE, '^');
- WriteChar(MSG_ONE, d * d - 2 * d + 50); // 1, 2, 5
+ WriteChar(MSG_ONE, d + '0');
WriteChar(MSG_ONE, TET_BLOCK);
}
else
{
float x, d, piece_ln, pcolor;
vector piece_dat;
- pcolor = mod(pc, 3) + 1;
+ pcolor = PieceColor(pc);
WriteChar(MSG_ONE, TET_SPACE); // pad to 6
piece_dat = PieceShape(pc);
piece_ln = piece_dat_y;
for (x = 1; x <= 4; x = x + 1)
{
- d = GetXBlock(x, piece_ln) * pcolor;
- if (d)
+ if (piece_ln & pow(4, x-1))
{
WriteChar(MSG_ONE, '^');
- WriteChar(MSG_ONE, d * d - 2 * d + 50); // 1, 2, 5
+ WriteChar(MSG_ONE, pcolor + '0');
WriteChar(MSG_ONE, TET_BLOCK);
}
else
entity head;
msg_entity = self;
WriteChar(MSG_ONE, SVC_CENTERPRINTa);
+ if(autocvar_g_bastet)
+ {
+ WriteTetrisString("NEVER GONNA GIVE YOU");
+ WriteChar(MSG_ONE, 10);
+ }
// decoration
for (i = 1; i <= (TET_WIDTH + 2); i = i + 1)
WriteChar(MSG_ONE, TET_BORDER);
WriteTetrisString(" ");
WriteUnterminatedString(MSG_ONE, TET_PADDING_RIGHT);
WriteChar(MSG_ONE, 10);
- for (i = 1; i <= TET_LINES; i = i + 1)
+ for (i = 1; i <= TET_DISPLAY_LINES; i = i + 1)
{
if(self.tetris_on == 2)
WriteTetrisString(" GAME OVER ");
else
DrawLine(i);
if (i == 1)
- WriteTetrisString(" NEXT ");
+ WriteTetrisString(autocvar_g_bastet ? " THAT " : " NEXT ");
else if (i == 3)
DrawPiece(self.next_piece, 1);
else if (i == 4)
{
float i;
+ if(!tet_line_buf)
+ tet_line_buf = buf_create();
+
for (i=1; i<=TET_LINES; i = i + 1)
- SetLine(i, 0);
+ SetLine(i, TET_EMPTY_LINE);
self.piece_pos = '0 0 0';
self.piece_type = 0;
self.next_piece = self.tet_lines = self.tet_score = 0;
self.movetype = MOVETYPE_WALK;
};
+void PrintField()
+{
+ string l;
+ float r, c;
+ for(r = 1; r <= TET_LINES; ++r)
+ {
+ l = GetLine(r);
+ print(">");
+ for(c = 1; c <= TET_WIDTH; ++c)
+ {
+ print(ftos(GetXBlock(c, l)));
+ }
+ print("\n");
+ }
+}
+
+float BastetEvaluate()
+{
+ float height;
+ string l;
+ float lines;
+ float score, score_save;
+ string occupied, occupied_save;
+ float occupied_count, occupied_count_save;
+ float i, j, line;
+
+ score = 0;
+
+ // adds a bonus for each free dot above the occupied blocks profile
+ occupied = TET_EMPTY_LINE;
+ occupied_count = TET_WIDTH;
+ height = 0;
+ lines = 0;
+ for(i = 1; i <= TET_LINES; ++i)
+ {
+ l = GetLine(i);
+ if(l == TET_EMPTY_LINE)
+ {
+ height = i;
+ continue;
+ }
+ line = 1;
+ occupied_save = occupied;
+ occupied_count_save = occupied_count;
+ score_save = score;
+ for(j = 1; j <= TET_WIDTH; ++j)
+ {
+ if(GetXBlock(j, l))
+ {
+ if(!GetXBlock(j, occupied))
+ {
+ occupied = SetXBlock(j, occupied, 1);
+ --occupied_count;
+ }
+ }
+ else
+ line = 0;
+ score += 10000 * occupied_count;
+ }
+ if(line)
+ {
+ occupied = occupied_save;
+ occupied_count = occupied_count_save;
+ score = score_save + 100000000 + 10000 * TET_WIDTH + 1000;
+ ++lines;
+ }
+ }
+
+ score += 1000 * height;
+
+ return score;
+}
+
+float CheckMetrics(float piece, float orgx, float orgy, float rot);
+void ClearPiece(float piece, float orgx, float orgy, float rot);
+void CementPiece(float piece, float orgx, float orgy, float rot);
+float bastet_profile_evaluate_time;
+float bastet_profile_checkmetrics_time;
+float BastetSearch(float buf, float pc, float x, float y, float rot, float move_bias)
+// returns best score, or -1 if position is impossible
+{
+ string r;
+ float b;
+ float s, sm;
+ float t1, t2;
+
+ if(move_bias < 0)
+ return 0; // DO NOT WANT
+
+ if(x < 1 || x > TET_WIDTH || y < 1 || y > TET_LINES)
+ return -1; // impossible
+ if(rot < 0) rot = 3;
+ if(rot > 3) rot = 0;
+
+ // did we already try?
+ b = x + (TET_WIDTH+2) * (y + (TET_LINES+2) * rot);
+ r = bufstr_get(buf, b);
+ if(r != "") // already tried
+ return stof(r);
+
+ bufstr_set(buf, b, "0"); // in case we READ that, not that bad - we already got that value in another branch then anyway
+
+
+
+ t1 = gettime(GETTIME_HIRES);
+ if(CheckMetrics(pc, x, y, rot))
+ {
+ t2 = gettime(GETTIME_HIRES);
+ bastet_profile_checkmetrics_time += (t2 - t1);
+ // try all moves
+ sm = 1;
+ s = BastetSearch(buf, pc, x-1, y, rot, move_bias - 1); if(s > sm) sm = s;
+ s = BastetSearch(buf, pc, x+1, y, rot, move_bias - 1); if(s > sm) sm = s;
+ s = BastetSearch(buf, pc, x, y, rot+1, move_bias - 1); if(s > sm) sm = s;
+ s = BastetSearch(buf, pc, x, y, rot-1, move_bias - 1); if(s > sm) sm = s;
+
+ s = BastetSearch(buf, pc, x, y+1, rot, move_bias + 2); if(s > sm) sm = s;
+ if(s < 0)
+ {
+ //print(sprintf("MAY CEMENT AT: %d %d %d\n", x, y, rot));
+ // moving down did not work - that means we can fixate the block here
+ t1 = gettime(GETTIME_HIRES);
+
+ CementPiece(pc, x, y, rot);
+ s = BastetEvaluate();
+ ClearPiece(pc, x, y, rot);
+
+ t2 = gettime(GETTIME_HIRES);
+ bastet_profile_evaluate_time += (t2 - t1);
+
+ if(s > sm) sm = s;
+ }
+ }
+ else
+ {
+ t2 = gettime(GETTIME_HIRES);
+ bastet_profile_checkmetrics_time += (t2 - t1);
+ sm = -1; // impassible
+ }
+
+ bufstr_set(buf, b, ftos(sm));
+
+ return sm;
+}
+
+float bastet_piece[7];
+float bastet_score[7];
+float bastet_piecetime[7];
+float BastetPiece()
+{
+ float b;
+
+ bastet_profile_evaluate_time = 0;
+ bastet_profile_checkmetrics_time = 0;
+ var float t1 = gettime(GETTIME_HIRES);
+
+ b = buf_create(); bastet_piece[0] = 1; bastet_score[0] = BastetSearch(b, 1, TET_START_PIECE_POS_x, 1+TET_START_PIECE_POS_y, TET_START_PIECE_POS_y, TET_WIDTH) + 100 * random() + bastet_piecetime[0]; buf_del(b);
+ b = buf_create(); bastet_piece[1] = 2; bastet_score[1] = BastetSearch(b, 2, TET_START_PIECE_POS_x, 1+TET_START_PIECE_POS_y, TET_START_PIECE_POS_y, TET_WIDTH) + 100 * random() + bastet_piecetime[1]; buf_del(b);
+ b = buf_create(); bastet_piece[2] = 3; bastet_score[2] = BastetSearch(b, 3, TET_START_PIECE_POS_x, 1+TET_START_PIECE_POS_y, TET_START_PIECE_POS_y, TET_WIDTH) + 100 * random() + bastet_piecetime[2]; buf_del(b);
+ b = buf_create(); bastet_piece[3] = 4; bastet_score[3] = BastetSearch(b, 4, TET_START_PIECE_POS_x, 1+TET_START_PIECE_POS_y, TET_START_PIECE_POS_y, TET_WIDTH) + 100 * random() + bastet_piecetime[3]; buf_del(b);
+ b = buf_create(); bastet_piece[4] = 5; bastet_score[4] = BastetSearch(b, 5, TET_START_PIECE_POS_x, 1+TET_START_PIECE_POS_y, TET_START_PIECE_POS_y, TET_WIDTH) + 100 * random() + bastet_piecetime[4]; buf_del(b);
+ b = buf_create(); bastet_piece[5] = 6; bastet_score[5] = BastetSearch(b, 6, TET_START_PIECE_POS_x, 1+TET_START_PIECE_POS_y, TET_START_PIECE_POS_y, TET_WIDTH) + 100 * random() + bastet_piecetime[5]; buf_del(b);
+ b = buf_create(); bastet_piece[6] = 7; bastet_score[6] = BastetSearch(b, 7, TET_START_PIECE_POS_x, 1+TET_START_PIECE_POS_y, TET_START_PIECE_POS_y, TET_WIDTH) + 100 * random() + bastet_piecetime[6]; buf_del(b);
+
+ var float t2 = gettime(GETTIME_HIRES);
+ dprint(sprintf("Time taken: %.6f seconds (of this, ev = %.2f%%, cm = %.2f%%)\n", t2 - t1, 100 * bastet_profile_evaluate_time / (t2 - t1), 100 * bastet_profile_checkmetrics_time / (t2 - t1)));
+
+ // sort
+ float i, j, k, p, s;
+
+/*
+ for(i = 0; i < 7; ++i)
+ {
+ print(sprintf("piece %s value = %d\n", substring("OJLIZST", bastet_piece[i]-1, 1), bastet_score[i]));
+ }
+*/
+
+ for(i = 0; i < 7; ++i)
+ {
+ k = i;
+ p = bastet_piece[k];
+ s = bastet_score[k];
+ for(j = i + 1; j < 7; ++j)
+ {
+ if(bastet_score[j] < s)
+ {
+ k = j;
+ s = bastet_score[k];
+ p = bastet_piece[k];
+ }
+ }
+ if(k != i)
+ {
+ bastet_score[k] = bastet_score[i];
+ bastet_piece[k] = bastet_piece[i];
+ bastet_score[i] = s;
+ bastet_piece[i] = p;
+ }
+ }
+
+ b = random();
+ if(b < 0.8)
+ j = 0;
+ else if(b < 0.92)
+ j = 1;
+ else if(b < 0.98)
+ j = 2;
+ else
+ j = 3;
+ j = bastet_piece[j];
+
+ for(i = 0; i < 7; ++i)
+ {
+ if(i == j-1)
+ bastet_piecetime[i] = 0.2 * bastet_piecetime[i];
+ else
+ bastet_piecetime[i] = 1.8 * bastet_piecetime[i] + 1000;
+ }
+
+ return j;
+}
/*
float p, q;
float b;
float seen;
+
if(self.tet_piece_bucket > 1)
{
p = mod(self.tet_piece_bucket, 7);
// check to see if the piece, if moved to the locations will overlap
float x, y;
+ string l;
// why did I start counting from 1, damnit
orgx = orgx - 1;
orgy = orgy - 1;
- for (y = 0; y < 5; y = y + 1)
+ PieceMinsMaxs(rot, piece);
+ if (tet_piecemins_x+orgx<1 || tet_piecemaxs_x+orgx > TET_WIDTH || tet_piecemins_y+orgy<1 || tet_piecemaxs_y+orgy> TET_LINES)
+ return FALSE; // ouside the level
+ for (y = tet_piecemins_y; y <= tet_piecemaxs_y; y = y + 1)
{
- for (x = 0; x < 5; x = x + 1)
- {
+ l = GetLine(y + orgy);
+ if(l != TET_EMPTY_LINE)
+ for (x = tet_piecemins_x; x <= tet_piecemaxs_x; x = x + 1)
if (PieceMetric(x, y, rot, piece))
- {
- if (GetSquare(x + orgx, y + orgy))
+ if (GetXBlock(x + orgx, l))
return FALSE; // uhoh, gonna hit something.
- if (x+orgx<1 || x+orgx > TET_WIDTH || y+orgy<1 || y+orgy> TET_LINES)
- return FALSE; // ouside the level
- }
- }
}
return TRUE;
}
void ClearPiece(float piece, float orgx, float orgy, float rot) /*FIXDECL*/
{
-
float x, y;
// why did I start counting from 1, damnit
orgx = orgx - 1;
orgy = orgy - 1;
- for (y = 0; y < 5; y = y + 1)
+ PieceMinsMaxs(rot, piece);
+ for (y = tet_piecemins_y; y <= tet_piecemaxs_y; y = y + 1)
{
- for (x = 0; x < 5; x = x + 1)
+ for (x = tet_piecemins_x; x <= tet_piecemaxs_x; x = x + 1)
{
if (PieceMetric(x, y, rot, piece))
{
orgx = orgx - 1;
orgy = orgy - 1;
- pcolor = mod(piece, 3) + 1;
+ pcolor = PieceColor(piece);
- for (y = 0; y < 5; y = y + 1)
+ PieceMinsMaxs(rot, piece);
+ for (y = tet_piecemins_y; y <= tet_piecemaxs_y; y = y + 1)
{
- for (x = 0; x < 5; x = x + 1)
+ for (x = tet_piecemins_x; x <= tet_piecemaxs_x; x = x + 1)
{
if (PieceMetric(x, y, rot, piece))
{
void CompletedLines()
{
- float y, cleared, ln, added, pos, i;
+ float y, cleared, added, pos, i;
+ string ln;
cleared = 0;
y = TET_LINES;
- while(y >= 1)
+ for(;;)
{
ln = GetLine(y);
- if (((ln & LINE_LOW) | ((ln & LINE_HIGH)/2)) == LINE_LOW)
+ if(strstrofs(ln, "0", 0) < 0)
cleared = cleared + 1;
else
y = y - 1;
- ln = GetLine(y - cleared);
+ if(y < 1)
+ break;
+ if(y - cleared < 1)
+ ln = TET_EMPTY_LINE;
+ else
+ ln = GetLine(y - cleared);
SetLine(y, ln);
}
for(y = max(1, TET_LINES - added + 1); y <= TET_LINES; ++y)
{
pos = floor(random() * TET_WIDTH);
- ln = 0;
+ ln = TET_EMPTY_LINE;
for(i = 1; i <= TET_WIDTH; ++i)
if(i != pos)
- ln = SetXBlock(i, ln, floor(random() * 3 + 1));
+ ln = SetXBlock(i, ln, floor(random() * 7 + 1));
SetLine(y, ln);
}
}
self.tet_highest_line = 0;
for(y = 1; y <= TET_LINES; ++y)
- if(GetLine(y) != 0)
+ if(GetLine(y) != TET_EMPTY_LINE)
{
self.tet_highest_line = TET_LINES + 1 - y;
break;
if (self.piece_type == 0)
{
- self.piece_pos = '5 1 0'; // that's about middle top, we count from 1 ARGH
- if (self.next_piece)
- self.piece_type = self.next_piece;
+ self.piece_pos = TET_START_PIECE_POS; // that's about middle top, we count from 1 ARGH
+
+ if(autocvar_g_bastet)
+ {
+ self.piece_type = BastetPiece();
+ self.next_piece = bastet_piece[6];
+ }
else
- self.piece_type = RandomPiece();
- self.next_piece = RandomPiece();
+ {
+ if (self.next_piece)
+ self.piece_type = self.next_piece;
+ else
+ self.piece_type = RandomPiece();
+ self.next_piece = RandomPiece();
+ }
keyss = 0; // no movement first frame
self.tet_autodown = time + 0.2;
brand_new = 1;
//
//////////////////////////////////////////////////////////////
+.entity trigger_gravity_check;
+void trigger_gravity_remove(entity own)
+{
+ if(own.trigger_gravity_check.owner == own)
+ {
+ UpdateCSQCProjectile(own);
+ own.gravity = own.trigger_gravity_check.gravity;
+ remove(own.trigger_gravity_check);
+ }
+ else
+ backtrace("Removing a trigger_gravity_check with no valid owner");
+ own.trigger_gravity_check = world;
+}
+void trigger_gravity_check_think()
+{
+ // This spawns when a player enters the gravity zone and checks if he left.
+ // Each frame, self.count is set to 2 by trigger_gravity_touch() and decreased by 1 here.
+ // It the player has left the gravity trigger, this will be allowed to reach 0 and indicate that.
+ if(self.count <= 0)
+ {
+ if(self.owner.trigger_gravity_check == self)
+ trigger_gravity_remove(self.owner);
+ else
+ remove(self);
+ return;
+ }
+ else
+ {
+ self.count -= 1;
+ self.nextthink = time;
+ }
+};
+
+void trigger_gravity_use()
+{
+ self.state = !self.state;
+};
+
+void trigger_gravity_touch()
+{
+ float g;
+
+ if(self.state != TRUE)
+ return;
+
+ EXACTTRIGGER_TOUCH;
+
+ g = self.gravity;
+
+ if not(self.spawnflags & 1)
+ {
+ if(other.trigger_gravity_check)
+ {
+ if(self == other.trigger_gravity_check.enemy)
+ {
+ // same?
+ other.trigger_gravity_check.count = 2; // gravity one more frame...
+ return;
+ }
+
+ // compare prio
+ if(self.cnt > other.trigger_gravity_check.enemy.cnt)
+ trigger_gravity_remove(other);
+ else
+ return;
+ }
+ other.trigger_gravity_check = spawn();
+ other.trigger_gravity_check.enemy = self;
+ other.trigger_gravity_check.owner = other;
+ other.trigger_gravity_check.gravity = other.gravity;
+ other.trigger_gravity_check.think = trigger_gravity_check_think;
+ other.trigger_gravity_check.nextthink = time;
+ other.trigger_gravity_check.count = 2;
+ if(other.gravity)
+ g *= other.gravity;
+ }
+
+ if (other.gravity != g)
+ {
+ other.gravity = g;
+ if(self.noise != "")
+ sound (other, CHAN_AUTO, self.noise, VOL_BASE, ATTN_NORM);
+ UpdateCSQCProjectile(self.owner);
+ }
+};
+void spawnfunc_trigger_gravity()
+{
+ if(self.gravity == 1)
+ return;
+
+ EXACTTRIGGER_INIT;
+ self.touch = trigger_gravity_touch;
+ if(self.noise != "")
+ precache_sound(self.noise);
+
+ self.state = TRUE;
+ IFTARGETED
+ {
+ self.use = trigger_gravity_use;
+ if(self.spawnflags & 2)
+ self.state = FALSE;
+ }
+};
+
+//=============================================================================
// TODO add a way to do looped sounds with sound(); then complete this entity
.float volume, atten;
GameLogEcho(strcat(":gamestart:", GetGametype(), "_", GetMapname(), ":", s));
s = ":gameinfo:mutators:LIST";
+
+ ret_string = s;
+ MUTATOR_CALLHOOK(BuildMutatorsString);
+ s = ret_string;
+
if(cvar("g_grappling_hook"))
s = strcat(s, ":grappling_hook");
if(!cvar("g_use_ammunition"))
s = strcat(s, ":no_pickup_items");
if(cvar_string("g_weaponarena") != "0")
s = strcat(s, ":", cvar_string("g_weaponarena"), " arena");
- if(cvar("g_nixnex"))
- s = strcat(s, ":nixnex");
if(cvar("g_vampire"))
s = strcat(s, ":vampire");
if(cvar("g_laserguided_missile"))
addstat(STAT_LEADLIMIT, AS_FLOAT, stat_leadlimit);
addstat(STAT_BULLETS_LOADED, AS_INT, campingrifle_bulletcounter);
+ // g_movementspeed hack
+ addstat(STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW, AS_FLOAT, stat_sv_airspeedlimit_nonqw);
+ addstat(STAT_MOVEVARS_AIRACCEL_QW, AS_FLOAT, stat_sv_airaccel_qw);
+ addstat(STAT_MOVEVARS_AIRSTRAFEACCEL_QW, AS_FLOAT, stat_sv_airstrafeaccel_qw);
+
next_pingtime = time + 5;
InitializeEntity(self, cvar_changes_init, INITPRIO_CVARS);
return TRUE;
}
+void TargetMusic_RestoreGame();
void RestoreGame()
{
// Loaded from a save game
MapInfo_Enumerate();
MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 1);
WeaponStats_Init();
+
+ TargetMusic_RestoreGame();
}
void SV_Shutdown()
db_put(d, "TR_KNIGHTSPIKE", "1"); print("effect TR_KNIGHTSPIKE is ", ftos(particleeffectnum("TR_KNIGHTSPIKE")), "\n");
db_put(d, "TR_VORESPIKE", "1"); print("effect TR_VORESPIKE is ", ftos(particleeffectnum("TR_VORESPIKE")), "\n");
db_put(d, "TR_NEHAHRASMOKE", "1"); print("effect TR_NEHAHRASMOKE is ", ftos(particleeffectnum("TR_NEHAHRASMOKE")), "\n");
- db_put(d, "TR_XONOTICPLASMA", "1"); print("effect TR_XONOTICPLASMA is ", ftos(particleeffectnum("TR_XONOTICPLASMA")), "\n");
+ db_put(d, "TR_NEXUIZPLASMA", "1"); print("effect TR_NEXUIZPLASMA is ", ftos(particleeffectnum("TR_NEXUIZPLASMA")), "\n");
db_put(d, "TR_GLOWTRAIL", "1"); print("effect TR_GLOWTRAIL is ", ftos(particleeffectnum("TR_GLOWTRAIL")), "\n");
db_put(d, "SVC_PARTICLE", "1"); print("effect SVC_PARTICLE is ", ftos(particleeffectnum("SVC_PARTICLE")), "\n");
if(argv(1) == "w")
setmodel(e, (nextent(world)).weaponentity.model);
else
+ {
+ precache_model(argv(1));
setmodel(e, argv(1));
+ }
e.frame = stof(argv(2));
- i = gettagindex(e, argv(3));
+ if(substring(argv(3), 0, 1) == "#")
+ i = stof(substring(argv(3), 1, -1));
+ else
+ i = gettagindex(e, argv(3));
if(i)
{
v = gettaginfo(e, i);
- print("model ", e.model, " frame ", ftos(e.frame), " tag ", argv(3));
- print(" index = ", ftos(i));
+ print("model ", e.model, " frame ", ftos(e.frame), " tag ", gettaginfo_name);
+ print(" index ", ftos(i), " parent ", ftos(gettaginfo_parent), "\n");
print(" vector = ", ftos(v_x), " ", ftos(v_y), " ", ftos(v_z), "\n");
+ print(" offset = ", ftos(gettaginfo_offset_x), " ", ftos(gettaginfo_offset_y), " ", ftos(gettaginfo_offset_z), "\n");
+ print(" forward = ", ftos(gettaginfo_forward_x), " ", ftos(gettaginfo_forward_y), " ", ftos(gettaginfo_forward_z), "\n");
+ print(" right = ", ftos(gettaginfo_right_x), " ", ftos(gettaginfo_right_y), " ", ftos(gettaginfo_right_z), "\n");
+ print(" up = ", ftos(gettaginfo_up_x), " ", ftos(gettaginfo_up_y), " ", ftos(gettaginfo_up_z), "\n");
if(argc >= 6)
{
v_y = -v_y;
return;
}
+ if(argv(0) == "showtraceline")
+ {
+ vector src, dst;
+ src = stov(argv(1));
+ dst = stov(argv(2));
+ traceline(src, dst, MOVE_NORMAL, world);
+ trailparticles(world, particleeffectnum("TR_NEXUIZPLASMA"), src, trace_endpos);
+ trailparticles(world, particleeffectnum("TR_CRYLINKPLASMA"), trace_endpos, dst);
+ return;
+ }
+
print("Invalid command. For a list of supported commands, try sv_cmd help.\n");
}
+++ /dev/null
-#define FOR_EACH_KH_KEY(v) for(v = kh_worldkeylist; v; v = v.kh_worldkeynext )
-
-// #define KH_PLAYER_USE_ATTACHMENT
-// #define KH_PLAYER_USE_CARRIEDMODEL
-// #define KH_KEY_ATTACHMENT_DEBUG
-
-#ifdef KH_PLAYER_USE_ATTACHMENT
-vector KH_PLAYER_ATTACHMENT_DIST_ROTATED = '0 -4 0';
-vector KH_PLAYER_ATTACHMENT_DIST = '4 0 0';
-vector KH_PLAYER_ATTACHMENT = '0 0 0';
-vector KH_PLAYER_ATTACHMENT_ANGLES = '0 0 0';
-string KH_PLAYER_ATTACHMENT_BONE = "";
-#else
-float KH_KEY_ZSHIFT = 22;
-float KH_KEY_XYDIST = 24;
-float KH_KEY_XYSPEED = 45;
-#endif
-float KH_KEY_WP_ZSHIFT = 20;
-
-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
-// bits 0- 4: team of key 1, or 0 for no such key, or 30 for dropped, or 31 for self
-// bits 5- 9: team of key 2, or 0 for no such key, or 30 for dropped, or 31 for self
-// bits 10-14: team of key 3, or 0 for no such key, or 30 for dropped, or 31 for self
-// bits 15-19: team of key 4, or 0 for no such key, or 30 for dropped, or 31 for self
-.float kh_state;
-.float siren_time; // time delay the siren
-//.float stuff_time; // time delay to stuffcmd a cvar
-
-float test[17] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-//test[0] = status of dropped keys, test[1 - 16] = player #
-//replace 17 with cvar("maxplayers") or similar !!!!!!!!!
-//for(i = 0; i < maxplayers; ++i)
-// test[i] = "0";
-
-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;
- return 0;
-}
-
-entity kh_worldkeylist;
-.entity kh_worldkeynext;
-entity kh_controller;
-float kh_tracking_enabled;
-float kh_teams;
-float kh_interferemsg_time, kh_interferemsg_team;
-.entity kh_next, kh_prev; // linked list
-.float kh_droptime;
-.float kh_dropperteam;
-.entity kh_previous_owner;
-.float kh_previous_owner_playerid;
-
-string kh_sound_capture = "kh/capture.wav";
-string kh_sound_destroy = "kh/destroy.wav";
-string kh_sound_drop = "kh/drop.wav";
-string kh_sound_collect = "kh/collect.wav";
-string kh_sound_alarm = "kh/alarm.wav"; // the new siren/alarm
-
-float kh_key_dropped, kh_key_carried;
-
-void kh_Controller_SetThink(float t, string msg, 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_Waitmsg = strzone(msg);
- if(t == 0)
- kh_controller.nextthink = time; // force
-}
-
-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)
- centerprint_atprio(e, CENTERPRIO_SPAM, s);
- }
- self.cnt -= 1;
- }
- else if(self.cnt == 0)
- {
- self.cnt -= 1;
- kh_Controller_Thinkfunc();
- }
- self.nextthink = time + 1;
-}
-
-// frags f: take from cvar * f
-// frags 0: no frags
-void kh_Scores_Event(entity player, entity key, string what, float frags_player, float frags_owner) // update the score when a key is captured
-{
- string s;
- if(intermission_running)
- return;
-
- if(frags_player)
- UpdateFrags(player, frags_player);
-
- if(key && key.owner && frags_owner)
- UpdateFrags(key.owner, frags_owner);
-
- if(!cvar("sv_eventlog")) //output extra info to the console or text file
- return;
-
- s = strcat(":keyhunt:", what, ":", ftos(player.playerid), ":", ftos(frags_player));
-
- if(key && key.owner)
- s = strcat(s, ":", ftos(key.owner.playerid));
- else
- s = strcat(s, ":0");
-
- s = strcat(s, ":", ftos(frags_owner), ":");
-
- if(key)
- s = strcat(s, key.netname);
-
- GameLogEcho(s);
-}
-
-vector kh_AttachedOrigin(entity e) // runs when a team captures the flag, it can run 2 or 3 times.
-{
- if(e.tag_entity)
- {
- makevectors(e.tag_entity.angles);
- return e.tag_entity.origin + e.origin_x * v_forward - e.origin_y * v_right + e.origin_z * v_up;
- }
- else
- return e.origin;
-}
-
-void kh_Key_Attach(entity key) // runs when a player picks up a key and several times when a key is assigned to a player at the start of a round
-{
-#ifdef KH_PLAYER_USE_ATTACHMENT
- entity first;
- first = key.owner.kh_next;
- if(key == first)
- {
- setattachment(key, key.owner, KH_PLAYER_ATTACHMENT_BONE);
- if(key.kh_next)
- {
- setattachment(key.kh_next, key, "");
- setorigin(key, key.kh_next.origin - 0.5 * KH_PLAYER_ATTACHMENT_DIST);
- setorigin(key.kh_next, KH_PLAYER_ATTACHMENT_DIST_ROTATED);
- key.kh_next.angles = '0 0 0';
- }
- else
- setorigin(key, KH_PLAYER_ATTACHMENT);
- key.angles = KH_PLAYER_ATTACHMENT_ANGLES;
- }
- else
- {
- setattachment(key, key.kh_prev, "");
- if(key.kh_next)
- setattachment(key.kh_next, key, "");
- setorigin(key, KH_PLAYER_ATTACHMENT_DIST_ROTATED);
- setorigin(first, first.origin - 0.5 * KH_PLAYER_ATTACHMENT_DIST);
- key.angles = '0 0 0';
- }
-#else
- setattachment(key, key.owner, "");
- setorigin(key, '0 0 1' * KH_KEY_ZSHIFT); // fixing x, y in think
- key.angles_y -= key.owner.angles_y;
-#endif
- key.flags = 0;
- key.solid = SOLID_NOT;
- key.movetype = MOVETYPE_NONE;
- key.team = key.owner.team;
- key.nextthink = time;
- key.damageforcescale = 0;
- key.takedamage = DAMAGE_NO;
- key.modelindex = kh_key_carried;
-}
-
-void kh_Key_Detach(entity key) // runs every time a key is dropped or lost. Runs several times times when all the keys are captured
-{
-#ifdef KH_PLAYER_USE_ATTACHMENT
- entity first;
- first = key.owner.kh_next;
- if(key == first)
- {
- if(key.kh_next)
- {
- setattachment(key.kh_next, key.owner, KH_PLAYER_ATTACHMENT_BONE);
- setorigin(key.kh_next, key.origin + 0.5 * KH_PLAYER_ATTACHMENT_DIST);
- key.kh_next.angles = KH_PLAYER_ATTACHMENT_ANGLES;
- }
- }
- else
- {
- if(key.kh_next)
- setattachment(key.kh_next, key.kh_prev, "");
- setorigin(first, first.origin + 0.5 * KH_PLAYER_ATTACHMENT_DIST);
- }
- // in any case:
- setattachment(key, world, "");
- setorigin(key, key.owner.origin + '0 0 1' * (PL_MIN_z - KH_KEY_MIN_z));
- key.angles = key.owner.angles;
-#else
- setorigin(key, key.owner.origin + key.origin_z * '0 0 1');
- setattachment(key, world, "");
- key.angles_y += key.owner.angles_y;
-#endif
- key.flags = FL_ITEM;
- key.solid = SOLID_TRIGGER;
- key.movetype = MOVETYPE_TOSS;
- key.pain_finished = time + cvar("g_balance_keyhunt_delay_return");
- key.damageforcescale = cvar("g_balance_keyhunt_damageforcescale");
- key.takedamage = DAMAGE_YES;
- // let key.team stay
- key.modelindex = kh_key_dropped;
- key.kh_previous_owner = key.owner;
- key.kh_previous_owner_playerid = key.owner.playerid;
-}
-
-void kh_Key_AssignTo(entity key, entity player) // runs every time a key is picked up or assigned. Runs prior to kh_key_attach
-{
- entity k;
- float ownerteam0, ownerteam;
- if(key.owner == player)
- return;
-
- ownerteam0 = kh_Key_AllOwnedByWhichTeam();
-
- if(key.owner)
- {
- kh_Key_Detach(key);
-
- // remove from linked list
- if(key.kh_next)
- key.kh_next.kh_prev = key.kh_prev;
- key.kh_prev.kh_next = key.kh_next;
- key.kh_next = world;
- key.kh_prev = world;
-
- if(key.owner.kh_next == world)
- {
- // No longer a key carrier
- if(!kh_no_radar_circles)
- WaypointSprite_Ping(key.owner.waypointsprite_attachedforcarrier);
- WaypointSprite_DetachCarrier(key.owner);
- }
- }
-
- key.owner = player;
-
- if(player)
- {
- // insert into linked list
- key.kh_next = player.kh_next;
- key.kh_prev = player;
- player.kh_next = key;
- if(key.kh_next)
- key.kh_next.kh_prev = key;
-
- float i;
- i = test[key.owner.playerid];
- if(key.netname == "^1red key")
- i += 1;
- if(key.netname == "^4blue key")
- i += 2;
- if(key.netname == "^3yellow key")
- i += 4;
- if(key.netname == "^6pink key")
- i += 8;
- test[key.owner.playerid] = i;
-
- kh_Key_Attach(key);
-
- if(key.kh_next == world)
- {
- // player is now a key carrier
- WaypointSprite_AttachCarrier("", player);
- 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)
- WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-red", "keycarrier-friend", "keycarrier-red");
- else if(player.team == COLOR_TEAM2)
- WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-blue", "keycarrier-friend", "keycarrier-blue");
- else if(player.team == COLOR_TEAM3)
- WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-yellow", "keycarrier-friend", "keycarrier-yellow");
- else if(player.team == COLOR_TEAM4)
- WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-pink", "keycarrier-friend", "keycarrier-pink");
- WaypointSprite_UpdateTeamRadar(player.waypointsprite_attachedforcarrier, RADARICON_FLAGCARRIER, colormapPaletteColor(player.team - 1, 0));
- if(!kh_no_radar_circles)
- WaypointSprite_Ping(player.waypointsprite_attachedforcarrier);
- }
- }
-
- // moved that here, also update if there's no player
- kh_update_state();
-
- key.pusher = world;
-
- ownerteam = kh_Key_AllOwnedByWhichTeam();
- if(ownerteam != ownerteam0)
- {
- if(ownerteam != -1)
- {
- kh_interferemsg_time = time + 0.2;
- kh_interferemsg_team = player.team;
-
- // audit all key carrier sprites, update them to RUN HERE
- FOR_EACH_KH_KEY(k)
- {
- if(k.owner)
- WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, k.owner.waypointsprite_attachedforcarrier.model1, "keycarrier-finish", k.owner.waypointsprite_attachedforcarrier.model3);
- }
- }
- else
- {
- kh_interferemsg_time = 0;
-
- // audit all key carrier sprites, update them to RUN HERE
- FOR_EACH_KH_KEY(k)
- {
- if(k.owner)
- WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, k.owner.waypointsprite_attachedforcarrier.model1, "keycarrier-friend", k.owner.waypointsprite_attachedforcarrier.model3);
- }
- }
- }
-}
-
-void kh_Key_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
- if(self.owner)
- return;
- if(vlen(force) <= 0)
- return;
- if(time > self.pushltime)
- if(attacker.classname == "player")
- self.team = attacker.team;
-}
-
-void key_reset()
-{
- kh_Key_AssignTo(self, world);
- kh_Key_Remove(self);
-}
-
-void kh_Key_Spawn(entity initial_owner, float angle, float i) // runs every time a new flag is created, ie after all the keys have been collected
-{
- entity key;
- key = spawn();
- key.count = i;
- key.classname = STR_ITEM_KH_KEY;
- key.touch = kh_Key_Touch;
- key.think = kh_Key_Think;
- key.nextthink = time;
- key.items = IT_KEY1 | IT_KEY2;
- key.cnt = angle;
- key.angles = '0 360 0' * random();
- key.event_damage = kh_Key_Damage;
- key.takedamage = DAMAGE_YES;
- key.modelindex = kh_key_dropped;
- key.model = "key";
- key.kh_dropperteam = 0;
- key.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP;
- setsize(key, KH_KEY_MIN, KH_KEY_MAX);
- key.colormod = TeamColor(initial_owner.team) * KH_KEY_BRIGHTNESS;
- key.reset = key_reset;
-
- switch(initial_owner.team)
- {
- case COLOR_TEAM1:
- key.netname = "^1red key";
- break;
- case COLOR_TEAM2:
- key.netname = "^4blue key";
- break;
- case COLOR_TEAM3:
- key.netname = "^3yellow key";
- break;
- case COLOR_TEAM4:
- key.netname = "^6pink key";
- break;
- default:
- key.netname = "NETGIER key";
- break;
- }
-
- // link into key list
- 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
-
- WaypointSprite_Spawn("key-dropped", 0, 0, key, '0 0 1' * KH_KEY_WP_ZSHIFT, world, key.team, key, waypointsprite_attachedforcarrier, FALSE);
- key.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = kh_Key_waypointsprite_visible_for_player;
- WaypointSprite_UpdateTeamRadar(key.waypointsprite_attachedforcarrier, RADARICON_FLAG, '0 1 1');
-
- kh_Key_AssignTo(key, initial_owner);
-}
-
-void kh_Key_Remove(entity key) // runs after when all the keys have been collected or when a key has been dropped for more than X seconds
-{
- entity o;
- o = key.owner;
- kh_Key_AssignTo(key, world);
- if(o) // it was attached
- WaypointSprite_Kill(key.waypointsprite_attachedforcarrier);
- else // it was dropped
- WaypointSprite_DetachCarrier(key);
-
- // remove key from key list
- if (kh_worldkeylist == key)
- kh_worldkeylist = kh_worldkeylist.kh_worldkeynext;
- else
- {
- o = kh_worldkeylist;
- while (o)
- {
- if (o.kh_worldkeynext == key)
- {
- o.kh_worldkeynext = o.kh_worldkeynext.kh_worldkeynext;
- break;
- }
- o = o.kh_worldkeynext;
- }
- }
-
- remove(key);
-
- kh_update_state();
-}
-
-// -1 when no team completely owns all keys yet
-float kh_Key_AllOwnedByWhichTeam() // constantly called. check to see if all the keys are owned by the same team
-{
- entity key;
- float teem;
- float keys;
-
- teem = -1;
- keys = kh_teams;
- FOR_EACH_KH_KEY(key)
- {
- if(!key.owner)
- return -1;
- if(teem == -1)
- teem = key.team;
- else if(teem != key.team)
- return -1;
- --keys;
- }
- if(keys != 0)
- return -1;
- return teem;
-}
-
-void kh_Key_Collect(entity key, entity player) //a player picks up a dropped key
-{
- sound(player, CHAN_AUTO, kh_sound_collect, VOL_BASE, ATTN_NORM);
-
- if(key.kh_dropperteam != player.team)
- {
- kh_Scores_Event(player, key, "collect", cvar("g_balance_keyhunt_score_collect"), 0);
- PlayerScore_Add(player, SP_KH_PICKUPS, 1);
- }
- key.kh_dropperteam = 0;
- bprint(player.netname, "^7 picked up the ", key.netname, "\n");
-
- kh_Key_AssignTo(key, player); // this also updates .kh_state
-}
-
-void kh_Key_DropAll(entity player, float suicide) // runs whenever a player dies
-{
- entity key;
- entity mypusher;
- if(player.kh_next)
- {
- mypusher = world;
- if(player.pusher)
- if(time < player.pushltime)
- mypusher = player.pusher;
- while((key = player.kh_next))
- {
- 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");
- kh_Key_AssignTo(key, world);
- makevectors('-1 0 0' * (45 + 45 * random()) + '0 360 0' * random());
- key.velocity = W_CalculateProjectileVelocity(player.velocity, cvar("g_balance_keyhunt_dropvelocity") * v_forward);
- key.pusher = mypusher;
- key.pushltime = time + cvar("g_balance_keyhunt_protecttime");
- if(suicide)
- key.kh_dropperteam = player.team;
- }
- sound(player, CHAN_AUTO, kh_sound_drop, VOL_BASE, ATTN_NORM);
- }
-}
-
-void kh_Key_Touch() // runs many, many times when a key has been dropped and can be picked up
-{
- if(intermission_running)
- return;
-
- if(self.owner) // already carried
- return;
- if(other.classname != "player")
- return;
- if(other.deadflag != DEAD_NO)
- return;
- if(other == self.enemy)
- if(time < self.kh_droptime + cvar("g_balance_keyhunt_delay_collect"))
- return; // you just dropped it!
- kh_Key_Collect(self, other);
-}
-
-void kh_Key_Think() // runs all the time
-{
- entity head;
- //entity player; // needed by FOR_EACH_PLAYER
-
- if(intermission_running)
- return;
-
-#ifdef KH_KEY_ATTACHMENT_DEBUG
- if(self.kh_prev == self.owner)
- {
- if(cvar_string("_angles") != "")
- {
- self.angles = stov(cvar_string("_angles"));
- setorigin(self, stov(cvar_string("_origin")));
- }
- }
-#endif
-
- if(self.owner)
- {
-#ifndef KH_PLAYER_USE_ATTACHMENT
- makevectors('0 1 0' * (self.cnt + mod(time, 360) * KH_KEY_XYSPEED));
- setorigin(self, v_forward * KH_KEY_XYDIST + '0 0 1' * self.origin_z);
-#endif
-
- if(self.owner.BUTTON_USE)
- if(time >= self.owner.kh_droptime + cvar("g_balance_keyhunt_delay_drop"))
- {
- self.owner.kh_droptime = time;
- self.kh_droptime = time; // prevent collecting this one for some time
- self.enemy = self.owner;
- self.pusher = world;
- kh_Scores_Event(self.owner, self, "dropkey", 0, 0);
- bprint(self.owner.netname, "^7 dropped the ", self.netname, "\n");
- sound(self.owner, CHAN_AUTO, kh_sound_drop, VOL_BASE, ATTN_NORM);
- makevectors(self.owner.v_angle);
- self.velocity = W_CalculateProjectileVelocity(self.owner.velocity, cvar("g_balance_keyhunt_throwvelocity") * v_forward);
- kh_Key_AssignTo(self, world);
- self.pushltime = time + cvar("g_balance_keyhunt_protecttime");
- self.kh_dropperteam = self.team;
- }
- }
-
- // if in nodrop or time over, end the round
- if(!self.owner)
- if(time > self.pain_finished)
- kh_LoserTeam(self.team, self);
-
- if(self.owner)
- if(kh_Key_AllOwnedByWhichTeam() != -1)
- {
- if(self.siren_time < time)
- {
- sound(self.owner, CHAN_AUTO, kh_sound_alarm, VOL_BASE, ATTN_NORM); // play a simple alarm
- self.siren_time = time + 2.5; // repeat every 2.5 seconds
- }
-
- entity key;
- vector p;
- p = self.owner.origin;
- FOR_EACH_KH_KEY(key)
- if(vlen(key.owner.origin - p) > cvar("g_balance_keyhunt_maxdist"))
- goto not_winning;
- kh_WinnerTeam(self.team);
-:not_winning
- }
-
- if(kh_interferemsg_time && time > kh_interferemsg_time)
- {
- kh_interferemsg_time = 0;
- FOR_EACH_PLAYER(head)
- {
- if(head.team == kh_interferemsg_team)
- if(head.kh_next)
- centerprint(head, "All keys are in your team's hands!\n\nMeet the other key carriers ^1NOW^7!");
- else
- centerprint(head, "All keys are in your team's hands!\n\nHelp the key carriers to meet!");
- else
- centerprint(head, strcat("All keys are in the ", ColoredTeamName(kh_interferemsg_team), "^7's hands!\n\nInterfere ^1NOW^7!"));
- }
- }
-
- self.nextthink = time + 0.05;
-}
-
-void kh_WinnerTeam(float teem) // runs when a team wins
-{
- // all key carriers get some points
- vector firstorigin, lastorigin, midpoint;
- float first;
- entity key;
- float score;
- score = (kh_teams - 1) * cvar("g_balance_keyhunt_score_capture");
- DistributeEvenly_Init(score, kh_teams);
- // twice the score for 3 team games, three times the score for 4 team games!
- // note: for a win by destroying the key, this should NOT be applied
- FOR_EACH_KH_KEY(key)
- {
- float f;
- f = DistributeEvenly_Get(1);
- kh_Scores_Event(key.owner, key, "capture", f, 0);
- PlayerTeamScore_Add(key.owner, SP_KH_CAPS, ST_KH_CAPS, 1);
- }
-
- first = TRUE;
- FOR_EACH_KH_KEY(key)
- if(key.owner.kh_next == key)
- {
- if(!first)
- bprint("^7, ");
- bprint(key.owner.netname);
- first = FALSE;
- }
- bprint("^7 captured the keys for the ", ColoredTeamName(teem), "\n");
-
- first = TRUE;
- midpoint = '0 0 0';
- FOR_EACH_KH_KEY(key)
- {
- vector thisorigin;
-
- thisorigin = kh_AttachedOrigin(key);
- //dprint("Key origin: ", vtos(thisorigin), "\n");
- midpoint += thisorigin;
-
- if(!first)
- te_lightning2(world, lastorigin, thisorigin);
- lastorigin = thisorigin;
- if(first)
- firstorigin = thisorigin;
- first = FALSE;
- }
- if(kh_teams > 2)
- {
- 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
-
- play2all(kh_sound_capture);
- kh_FinishRound();
-}
-
-void kh_LoserTeam(float teem, entity lostkey) // runs when a player pushes a flag carrier off the map
-{
- entity player, key, attacker;
- float players;
- float keys;
- float f;
-
- attacker = world;
- if(lostkey.pusher)
- if(lostkey.pusher.team != teem)
- if(lostkey.pusher.classname == "player")
- attacker = lostkey.pusher;
-
- players = keys = 0;
-
- if(attacker)
- {
- if(lostkey.kh_previous_owner)
- kh_Scores_Event(lostkey.kh_previous_owner, world, "pushed", 0, -cvar("g_balance_keyhunt_score_push"));
- // don't actually GIVE him the -nn points, just log
- kh_Scores_Event(attacker, world, "push", cvar("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");
- }
- else
- {
- float of, fragsleft, i, j, thisteam;
- of = cvar("g_balance_keyhunt_score_destroyed_ownfactor");
-
- FOR_EACH_PLAYER(player)
- if(player.team != teem)
- ++players;
-
- FOR_EACH_KH_KEY(key)
- if(key.owner && key.team != teem)
- ++keys;
-
- if(lostkey.kh_previous_owner)
- kh_Scores_Event(lostkey.kh_previous_owner, world, "destroyed", 0, -cvar("g_balance_keyhunt_score_destroyed"));
- // don't actually GIVE him the -nn points, just log
-
- if(lostkey.kh_previous_owner.playerid == lostkey.kh_previous_owner_playerid)
- PlayerScore_Add(lostkey.kh_previous_owner, SP_KH_DESTROYS, 1);
-
- DistributeEvenly_Init(cvar("g_balance_keyhunt_score_destroyed"), keys * of + players);
-
- FOR_EACH_KH_KEY(key)
- if(key.owner && key.team != teem)
- {
- f = DistributeEvenly_Get(of);
- kh_Scores_Event(key.owner, world, "destroyed_holdingkey", f, 0);
- }
-
- fragsleft = DistributeEvenly_Get(players);
-
- // Now distribute these among all other teams...
- j = kh_teams - 1;
- for(i = 0; i < kh_teams; ++i)
- {
- thisteam = kh_Team_ByID(i);
- if(thisteam == teem) // bad boy, no cookie - this WILL happen
- continue;
-
- players = 0;
- FOR_EACH_PLAYER(player)
- if(player.team == thisteam)
- ++players;
-
- DistributeEvenly_Init(fragsleft, j);
- fragsleft = DistributeEvenly_Get(j - 1);
- DistributeEvenly_Init(DistributeEvenly_Get(1), players);
-
- FOR_EACH_PLAYER(player)
- if(player.team == thisteam)
- {
- f = DistributeEvenly_Get(1);
- kh_Scores_Event(player, world, "destroyed", f, 0);
- }
-
- --j;
- }
-
- bprint("The ", ColoredTeamName(teem), "^7 could not take care of the ", lostkey.netname, "\n");
- }
- play2all(kh_sound_destroy);
- te_tarexplosion(lostkey.origin);
-
- kh_FinishRound();
-}
-
-void kh_FinishRound() // runs when a team captures the keys
-{
- // prepare next round
- kh_interferemsg_time = 0;
- entity key;
-
- kh_no_radar_circles = TRUE;
- FOR_EACH_KH_KEY(key)
- kh_Key_Remove(key);
- kh_no_radar_circles = FALSE;
-
- kh_Controller_SetThink(cvar("g_balance_keyhunt_delay_round"), "Round starts in ", kh_StartRound);
-}
-
-string kh_CheckEnoughPlayers() // checks enough player are present, runs after every completed round
-{
- float i, players, teem;
- entity player;
- string result;
- result = "";
-
- // find a random player per team
- for(i = 0; i < kh_teams; ++i)
- {
- teem = kh_Team_ByID(i);
- players = 0;
- FOR_EACH_PLAYER(player)
- if(player.deadflag == DEAD_NO)
- if(!player.BUTTON_CHAT)
- if(player.team == teem)
- ++players;
- if(players == 0)
- {
- if(result != "")
- result = strcat(result, ", ");
- result = strcat(result, ColoredTeamName(teem));
- }
- }
- return result;
-}
-
-void kh_WaitForPlayers() // delay start of the round until enough players are present
-{
- string teams_missing;
-
- if(time < game_starttime)
- {
- kh_Controller_SetThink(game_starttime - time + 0.1, "", kh_WaitForPlayers);
- return;
- }
-
- teams_missing = kh_CheckEnoughPlayers();
- if(teams_missing == "")
- kh_Controller_SetThink(cvar("g_balance_keyhunt_delay_round"), "Round starts in ", kh_StartRound);
- else
- kh_Controller_SetThink(1, strcat("Waiting for players to join...\n\nNeed active players for: ", teams_missing), kh_WaitForPlayers);
-}
-
-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(game_starttime - time + 0.1, "", kh_WaitForPlayers);
- return;
- }
-
- teams_missing = kh_CheckEnoughPlayers();
- if(teams_missing != "")
- {
- kh_Controller_SetThink(1, strcat("Waiting for players to join...\n\nNeed active players for: ", teams_missing), kh_WaitForPlayers);
- return;
- }
-
- FOR_EACH_PLAYER(player)
- if(clienttype(player) == CLIENTTYPE_REAL)
- centerprint_expire(player, CENTERPRIO_SPAM);
-
- for(i = 0; i < kh_teams; ++i)
- {
- teem = kh_Team_ByID(i);
- players = 0;
- entity my_player;
- FOR_EACH_PLAYER(player)
- if(player.deadflag == DEAD_NO)
- if(!player.BUTTON_CHAT)
- if(player.team == teem)
- {
- ++players;
- if(random() * players <= 1)
- my_player = player;
- }
- kh_Key_Spawn(my_player, 360 * i / kh_teams, i);
- }
-
- kh_tracking_enabled = FALSE;
- kh_Controller_SetThink(cvar("g_balance_keyhunt_delay_tracking"), "Scanning frequency range...", kh_EnableTrackingDevice);
-}
-
-void kh_EnableTrackingDevice() // runs after each round
-{
- entity player;
-
- FOR_EACH_PLAYER(player)
- if(clienttype(player) == CLIENTTYPE_REAL)
- centerprint_expire(player, CENTERPRIO_SPAM);
-
- kh_tracking_enabled = TRUE;
-}
-
-float kh_Key_waypointsprite_visible_for_player(entity e) // ??
-{
- if(!kh_tracking_enabled)
- return FALSE;
- if(!self.owner)
- return TRUE;
- if(!self.owner.owner)
- return TRUE;
- return FALSE; // draw only when key is not owned
-}
-
-float kh_KeyCarrier_waypointsprite_visible_for_player(entity e) // runs all the time
-{
- if(e.classname != "player" || self.team != e.team)
- if(!kh_tracking_enabled)
- return FALSE;
-
- return TRUE;
-}
-
-float kh_HandleFrags(entity attacker, entity targ, float f) // adds to the player score
-{
- if(attacker == targ)
- return f;
-
- if(targ.kh_next)
- {
- if(attacker.team == targ.team)
- {
- entity k;
- float nk;
- nk = 0;
- for(k = targ.kh_next; k != world; k = k.kh_next)
- ++nk;
- kh_Scores_Event(attacker, targ.kh_next, "carrierfrag", -nk * cvar("g_balance_keyhunt_score_collect"), 0);
- }
- else
- {
- kh_Scores_Event(attacker, targ.kh_next, "carrierfrag", cvar("g_balance_keyhunt_score_carrierfrag")-1, 0);
- PlayerScore_Add(attacker, SP_KH_KCKILLS, 1);
- // the frag gets added later
- }
- }
-
- return f;
-}
-
-void kh_init() // sets up th KH environment
-{
- precache_sound(kh_sound_capture);
- precache_sound(kh_sound_destroy);
- precache_sound(kh_sound_drop);
- precache_sound(kh_sound_collect);
- precache_sound(kh_sound_alarm); // the new siren
-
-#ifdef KH_PLAYER_USE_CARRIEDMODEL
- precache_model("models/keyhunt/key-carried.md3");
-#endif
- precache_model("models/keyhunt/key.md3");
-
- // setup variables
- kh_teams = cvar("g_keyhunt_teams_override");
- if(kh_teams < 2)
- kh_teams = cvar("g_keyhunt_teams");
- kh_teams = bound(2, kh_teams, 4);
-
- // make a KH entity for controlling the game
- kh_controller = spawn();
- kh_controller.think = kh_Controller_Think;
- kh_Controller_SetThink(0, "", kh_WaitForPlayers);
-
- setmodel(kh_controller, "models/keyhunt/key.md3");
- kh_key_dropped = kh_controller.modelindex;
- /*
- dprint(vtos(kh_controller.mins));
- dprint(vtos(kh_controller.maxs));
- dprint("\n");
- */
-#ifdef KH_PLAYER_USE_CARRIEDMODEL
- setmodel(kh_controller, "models/keyhunt/key-carried.md3");
- kh_key_carried = kh_controller.modelindex;
-#else
- kh_key_carried = kh_key_dropped;
-#endif
-
- kh_controller.model = "";
- kh_controller.modelindex = 0;
-
- addstat(STAT_KH_KEYS, AS_INT, kh_state);
-
- ScoreRules_kh(kh_teams);
-}
-
-void kh_finalize()
-{
- // to be called before intermission
- kh_FinishRound();
- remove(kh_controller);
- kh_controller = world;
-}
-
-void kh_update_state()
-{
- entity player;
- entity key;
- float s;
- float f;
-
- s = 0;
- FOR_EACH_KH_KEY(key)
- {
- if(key.owner)
- f = key.team;
- else
- f = 30;
- s |= pow(32, key.count) * f;
- }
-
- FOR_EACH_CLIENT(player)
- {
- player.kh_state = s;
- }
-
- FOR_EACH_KH_KEY(key)
- {
- if(key.owner)
- key.owner.kh_state |= pow(32, key.count) * 31;
- }
- //print(ftos((nextent(world)).kh_state), "\n");
-}
+++ /dev/null
-.float kh_state;
-float kh_teams;
-float kh_tracking_enabled;
-.entity kh_next, kh_prev;
-
-void kh_Scores_Event(entity player, entity key, string what, float frags_player, float frags_owner);
-void kh_Key_Attach(entity key);
-void kh_Key_Detach(entity key);
-void kh_Key_AssignTo(entity key, entity player);
-void kh_Key_Spawn(entity initial_owner, float angle, float idx);
-void kh_Key_Remove(entity key);
-void kh_Key_Collect(entity key, entity player);
-void kh_Key_DropAll(entity player, float suicide);
-void kh_Key_Touch();
-void kh_Key_Think();
-void kh_WinnerTeam(float teem);
-void kh_LoserTeam(float teem, entity lostkey);
-void kh_FinishRound();
-void kh_StartRound();
-void kh_EnableTrackingDevice();
-void kh_init();
-void kh_finalize();
-float kh_KeyCarrier_waypointsprite_visible_for_player(entity e);
-float kh_Key_waypointsprite_visible_for_player(entity e);
-float kh_HandleFrags(entity attacker, entity targ, float f);
-float kh_Key_AllOwnedByWhichTeam();
-
-void kh_update_state();
-
-#define STR_ITEM_KH_KEY "item_kh_key"
-typedef void(void) kh_Think_t;
-var kh_Think_t kh_Controller_Thinkfunc;
-void kh_Controller_SetThink(float t, string msg, kh_Think_t func)
-void kh_Key_Remove(entity key)
}
}
else
- stuffcmd(self, strcat("sendcvar ", name, "\n"));
+ stuffcmd(self, strcat("cl_cmd sendcvar ", name, "\n"));
}
void GetCvars_handleString_Fixup(string thisname, float f, .string field, string name, string(string) func)
{
self.field = stof(argv(f + 1));
}
else
- stuffcmd(self, strcat("sendcvar ", name, "\n"));
+ stuffcmd(self, strcat("cl_cmd sendcvar ", name, "\n"));
}
void GetCvars_handleFloatOnce(string thisname, float f, .float field, string name)
{
else
{
if(!self.field)
- stuffcmd(self, strcat("sendcvar ", name, "\n"));
+ stuffcmd(self, strcat("cl_cmd sendcvar ", name, "\n"));
}
}
string W_FixWeaponOrder_ForceComplete(string s);
void GetCvars(float f)
{
string s;
+
if (f > 0)
s = strcat1(argv(f));
+
+ get_cvars_f = f;
+ get_cvars_s = s;
+ MUTATOR_CALLHOOK(GetCvars);
GetCvars_handleFloat(s, f, autoswitch, "cl_autoswitch");
GetCvars_handleFloat(s, f, cvar_cl_playerdetailreduction, "cl_playerdetailreduction");
GetCvars_handleFloat(s, f, cvar_scr_centertime, "scr_centertime");
GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriorities[7], "cl_weaponpriority7", W_FixWeaponOrder_AllowIncomplete);
GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriorities[8], "cl_weaponpriority8", W_FixWeaponOrder_AllowIncomplete);
GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriorities[9], "cl_weaponpriority9", W_FixWeaponOrder_AllowIncomplete);
+ GetCvars_handleFloat(s, f, cvar_cl_weaponimpulsemode, "cl_weaponimpulsemode");
GetCvars_handleFloat(s, f, cvar_cl_autotaunt, "cl_autotaunt");
GetCvars_handleFloat(s, f, cvar_cl_noantilag, "cl_noantilag");
GetCvars_handleFloat(s, f, cvar_cl_voice_directional, "cl_voice_directional");
float g_pickup_fuel_max;
float g_pickup_armorsmall;
float g_pickup_armorsmall_max;
+float g_pickup_armorsmall_anyway;
float g_pickup_armormedium;
float g_pickup_armormedium_max;
+float g_pickup_armormedium_anyway;
float g_pickup_armorbig;
float g_pickup_armorbig_max;
+float g_pickup_armorbig_anyway;
float g_pickup_armorlarge;
float g_pickup_armorlarge_max;
+float g_pickup_armorlarge_anyway;
float g_pickup_healthsmall;
float g_pickup_healthsmall_max;
+float g_pickup_healthsmall_anyway;
float g_pickup_healthmedium;
float g_pickup_healthmedium_max;
+float g_pickup_healthmedium_anyway;
float g_pickup_healthlarge;
float g_pickup_healthlarge_max;
+float g_pickup_healthlarge_anyway;
float g_pickup_healthmega;
float g_pickup_healthmega_max;
+float g_pickup_healthmega_anyway;
+float g_pickup_ammo_anyway;
+float g_pickup_weapons_anyway;
float g_weaponarena;
float g_weaponarena_random;
string g_weaponarena_list;
return t;
}
-float NixNex_CanChooseWeapon(float wpn);
void readplayerstartcvars()
{
entity e;
else
g_weaponarena_random = 0;
- if (g_nixnex)
- {
- start_weapons = 0;
- // will be done later
- for (i = WEP_FIRST; i <= WEP_LAST; ++i)
- if (NixNex_CanChooseWeapon(i))
- weapon_action(i, WR_PRECACHE);
- if(!cvar("g_use_ammunition"))
- start_items |= IT_UNLIMITED_AMMO;
- }
- else if (g_weaponarena)
+ if (g_weaponarena)
{
start_weapons = g_weaponarena;
if (g_weaponarena & (WEPBIT_GRENADE_LAUNCHER | WEPBIT_HAGAR | WEPBIT_ROCKET_LAUNCHER))
start_health = cvar("g_lms_start_health");
start_armorvalue = cvar("g_lms_start_armor");
}
- else if (cvar("g_use_ammunition"))
+ else
{
start_ammo_shells = cvar("g_start_ammo_shells");
start_ammo_nails = cvar("g_start_ammo_nails");
start_ammo_cells = cvar("g_start_ammo_cells");
start_ammo_fuel = cvar("g_start_ammo_fuel");
}
- else
- {
- start_ammo_shells = cvar("g_pickup_shells_max");
- start_ammo_nails = cvar("g_pickup_nails_max");
- start_ammo_rockets = cvar("g_pickup_rockets_max");
- start_ammo_cells = cvar("g_pickup_cells_max");
- start_ammo_fuel = cvar("g_pickup_fuel_max");
- start_items |= IT_UNLIMITED_AMMO;
- }
for (i = WEP_FIRST; i <= WEP_LAST; ++i)
{
e = get_weaponinfo(i);
if(want_weapon("g_start_weapon_", e, FALSE))
- {
start_weapons |= e.weapons;
- weapon_action(e.weapon, WR_PRECACHE);
- }
}
}
warmup_start_armorvalue = start_armorvalue;
warmup_start_weapons = start_weapons;
- if (!g_weaponarena && !g_nixnex && !g_minstagib && !g_ca)
+ if (!g_weaponarena && !g_minstagib && !g_ca)
{
- if (cvar("g_use_ammunition"))
- {
- warmup_start_ammo_shells = cvar("g_warmup_start_ammo_shells");
- warmup_start_ammo_cells = cvar("g_warmup_start_ammo_cells");
- warmup_start_ammo_nails = cvar("g_warmup_start_ammo_nails");
- warmup_start_ammo_rockets = cvar("g_warmup_start_ammo_rockets");
- warmup_start_ammo_fuel = cvar("g_warmup_start_ammo_fuel");
- }
+ warmup_start_ammo_shells = cvar("g_warmup_start_ammo_shells");
+ warmup_start_ammo_cells = cvar("g_warmup_start_ammo_cells");
+ warmup_start_ammo_nails = cvar("g_warmup_start_ammo_nails");
+ warmup_start_ammo_rockets = cvar("g_warmup_start_ammo_rockets");
+ warmup_start_ammo_fuel = cvar("g_warmup_start_ammo_fuel");
warmup_start_health = cvar("g_warmup_start_health");
warmup_start_armorvalue = cvar("g_warmup_start_armor");
warmup_start_weapons = 0;
{
e = get_weaponinfo(i);
if(want_weapon("g_start_weapon_", e, cvar("g_warmup_allguns")))
- {
warmup_start_weapons |= e.weapons;
- weapon_action(e.weapon, WR_PRECACHE);
- }
}
}
}
warmup_start_ammo_fuel = max(warmup_start_ammo_fuel, cvar("g_balance_fuel_rotstable"));
}
+ if(!cvar("g_use_ammunition"))
+ {
+ start_ammo_shells = cvar("g_pickup_shells_max");
+ start_ammo_nails = cvar("g_pickup_nails_max");
+ start_ammo_rockets = cvar("g_pickup_rockets_max");
+ start_ammo_cells = cvar("g_pickup_cells_max");
+ start_ammo_fuel = cvar("g_pickup_fuel_max");
+ start_items |= IT_UNLIMITED_AMMO;
+ warmup_start_ammo_shells = cvar("g_pickup_shells_max");
+ warmup_start_ammo_nails = cvar("g_pickup_nails_max");
+ warmup_start_ammo_rockets = cvar("g_pickup_rockets_max");
+ warmup_start_ammo_cells = cvar("g_pickup_cells_max");
+ warmup_start_ammo_fuel = cvar("g_pickup_fuel_max");
+ //warmup_start_items |= IT_UNLIMITED_AMMO;
+ }
+
if (g_jetpack)
start_items |= IT_JETPACK;
if (!warmup_start_ammo_fuel) warmup_start_ammo_fuel = g_pickup_fuel;
}
+ MUTATOR_CALLHOOK(SetStartItems);
+
+ for (i = WEP_FIRST; i <= WEP_LAST; ++i)
+ {
+ e = get_weaponinfo(i);
+ if(e.weapons & (start_weapons | warmup_start_weapons))
+ weapon_action(e.weapon, WR_PRECACHE);
+ }
+
start_ammo_shells = max(0, start_ammo_shells);
start_ammo_nails = max(0, start_ammo_nails);
start_ammo_cells = max(0, start_ammo_cells);
void readlevelcvars(void)
{
+ // first load all the mutators
+ if(cvar("g_nix"))
+ MUTATOR_ADD(mutator_nix);
+
g_bugrigs = cvar("g_bugrigs");
g_bugrigs_planar_movement = cvar("g_bugrigs_planar_movement");
g_bugrigs_planar_movement_car_jumping = cvar("g_bugrigs_planar_movement_car_jumping");
g_laserguided_missile = cvar("g_laserguided_missile");
g_midair = cvar("g_midair");
g_minstagib = cvar("g_minstagib");
- g_nixnex = cvar("g_nixnex");
- g_nixnex_with_laser = cvar("g_nixnex_with_laser");
g_norecoil = cvar("g_norecoil");
g_vampire = cvar("g_vampire");
g_bloodloss = cvar("g_bloodloss");
sv_maxidle = cvar("sv_maxidle");
sv_maxidle_spectatorsareidle = cvar("sv_maxidle_spectatorsareidle");
sv_pogostick = cvar("sv_pogostick");
- sv_doublejump = cvar("sv_doublejump");
g_ctf_reverse = cvar("g_ctf_reverse");
sv_autotaunt = cvar("sv_autotaunt");
sv_taunt = cvar("sv_taunt");
g_pickup_respawntimejitter_long = cvar("g_pickup_respawntimejitter_long");
g_pickup_respawntimejitter_powerup = cvar("g_pickup_respawntimejitter_powerup");
- if (g_minstagib) g_nixnex = g_weaponarena = 0;
- if (g_nixnex) g_weaponarena = 0;
- g_weaponarena = 0;
-
g_weaponspeedfactor = cvar("g_weaponspeedfactor");
g_weaponratefactor = cvar("g_weaponratefactor");
g_weapondamagefactor = cvar("g_weapondamagefactor");
g_pickup_fuel_max = cvar("g_pickup_fuel_max");
g_pickup_armorsmall = cvar("g_pickup_armorsmall");
g_pickup_armorsmall_max = cvar("g_pickup_armorsmall_max");
+ g_pickup_armorsmall_anyway = cvar("g_pickup_armorsmall_anyway");
g_pickup_armormedium = cvar("g_pickup_armormedium");
g_pickup_armormedium_max = cvar("g_pickup_armormedium_max");
+ g_pickup_armormedium_anyway = cvar("g_pickup_armormedium_anyway");
g_pickup_armorbig = cvar("g_pickup_armorbig");
g_pickup_armorbig_max = cvar("g_pickup_armorbig_max");
+ g_pickup_armorbig_anyway = cvar("g_pickup_armorbig_anyway");
g_pickup_armorlarge = cvar("g_pickup_armorlarge");
g_pickup_armorlarge_max = cvar("g_pickup_armorlarge_max");
+ g_pickup_armorlarge_anyway = cvar("g_pickup_armorlarge_anyway");
g_pickup_healthsmall = cvar("g_pickup_healthsmall");
g_pickup_healthsmall_max = cvar("g_pickup_healthsmall_max");
+ g_pickup_healthsmall_anyway = cvar("g_pickup_healthsmall_anyway");
g_pickup_healthmedium = cvar("g_pickup_healthmedium");
g_pickup_healthmedium_max = cvar("g_pickup_healthmedium_max");
+ g_pickup_healthmedium_anyway = cvar("g_pickup_healthmedium_anyway");
g_pickup_healthlarge = cvar("g_pickup_healthlarge");
g_pickup_healthlarge_max = cvar("g_pickup_healthlarge_max");
+ g_pickup_healthlarge_anyway = cvar("g_pickup_healthlarge_anyway");
g_pickup_healthmega = cvar("g_pickup_healthmega");
g_pickup_healthmega_max = cvar("g_pickup_healthmega_max");
+ g_pickup_healthmega_anyway = cvar("g_pickup_healthmega_anyway");
+
+ g_pickup_ammo_anyway = cvar("g_pickup_ammo_anyway");
+ g_pickup_weapons_anyway = cvar("g_pickup_weapons_anyway");
g_pinata = cvar("g_pinata");
}
void PrecachePlayerSounds(string f);
-void precache_all_models(string pattern)
+void precache_playermodel(string m)
{
- float globhandle, i, n;
- string f;
+ float globhandle, i, n;
+ string f;
- globhandle = search_begin(pattern, TRUE, FALSE);
- if (globhandle < 0)
- return;
- n = search_getsize(globhandle);
- for (i = 0; i < n; ++i)
- {
+ if(substring(m, -9,5) == "_lod1")
+ return;
+ if(substring(m, -9,5) == "_lod2")
+ return;
+ precache_model(m);
+ if(sv_loddistance1)
+ {
+ precache_model(strcat(substring(m, 0, -5), "_lod1", substring(m, -4, -1)));
+ precache_model(strcat(substring(m, 0, -5), "_lod2", substring(m, -4, -1)));
+ }
+
+ globhandle = search_begin(strcat(m, "_*.sounds"), TRUE, FALSE);
+ if (globhandle < 0)
+ return;
+ n = search_getsize(globhandle);
+ for (i = 0; i < n; ++i)
+ {
//print(search_getfilename(globhandle, i), "\n");
f = search_getfilename(globhandle, i);
- if(sv_loddistance1)
- precache_model(f);
- if(substring(f, -9,5) == "_lod1")
- continue;
- if(substring(f, -9,5) == "_lod2")
- continue;
- if(!sv_loddistance1)
- precache_model(f);
- PrecachePlayerSounds(strcat(f, ".sounds"));
- }
- search_end(globhandle);
+ PrecachePlayerSounds(f);
+ }
+ search_end(globhandle);
+}
+void precache_all_playermodels(string pattern)
+{
+ float globhandle, i, n;
+ string f;
+
+ globhandle = search_begin(pattern, TRUE, FALSE);
+ if (globhandle < 0)
+ return;
+ n = search_getsize(globhandle);
+ for (i = 0; i < n; ++i)
+ {
+ //print(search_getfilename(globhandle, i), "\n");
+ f = search_getfilename(globhandle, i);
+ precache_playermodel(f);
+ }
+ search_end(globhandle);
}
void precache()
if (cvar("sv_precacheplayermodels"))
{
PrecachePlayerSounds("sound/player/default.sounds");
- precache_all_models("models/player/*.zym");
- precache_all_models("models/player/*.dpm");
- precache_all_models("models/player/*.md3");
- precache_all_models("models/player/*.psk");
- //precache_model("models/player/carni.zym");
- //precache_model("models/player/crash.zym");
- //precache_model("models/player/grunt.zym");
- //precache_model("models/player/headhunter.zym");
- //precache_model("models/player/insurrectionist.zym");
- //precache_model("models/player/jeandarc.zym");
- //precache_model("models/player/lurk.zym");
- //precache_model("models/player/lycanthrope.zym");
- //precache_model("models/player/marine.zym");
- //precache_model("models/player/nexus.zym");
- //precache_model("models/player/pyria.zym");
- //precache_model("models/player/shock.zym");
- //precache_model("models/player/skadi.zym");
- //precache_model("models/player/specop.zym");
- //precache_model("models/player/visitant.zym");
+ precache_all_playermodels("models/player/*.zym");
+ precache_all_playermodels("models/player/*.dpm");
+ precache_all_playermodels("models/player/*.md3");
+ precache_all_playermodels("models/player/*.psk");
+ precache_all_playermodels("models/player/*.iqm");
}
if (cvar("sv_defaultcharacter"))
string s;
s = cvar_string("sv_defaultplayermodel_red");
if (s != "")
- {
- precache_model(s);
- PrecachePlayerSounds(strcat(s, ".sounds"));
- }
+ precache_playermodel(s);
s = cvar_string("sv_defaultplayermodel_blue");
if (s != "")
- {
- precache_model(s);
- PrecachePlayerSounds(strcat(s, ".sounds"));
- }
+ precache_playermodel(s);
s = cvar_string("sv_defaultplayermodel_yellow");
if (s != "")
- {
- precache_model(s);
- PrecachePlayerSounds(strcat(s, ".sounds"));
- }
+ precache_playermodel(s);
s = cvar_string("sv_defaultplayermodel_pink");
if (s != "")
- {
- precache_model(s);
- PrecachePlayerSounds(strcat(s, ".sounds"));
- }
+ precache_playermodel(s);
s = cvar_string("sv_defaultplayermodel");
if (s != "")
- {
- precache_model(s);
- PrecachePlayerSounds(strcat(s, ".sounds"));
- }
+ precache_playermodel(s);
}
if (g_footsteps)
precache_sound ("weapons/hook_impact.wav"); // hook
}
- if (cvar("sv_precacheweapons") || g_nixnex)
+ if(cvar("sv_precacheweapons"))
{
//precache weapon models/sounds
local float wep;
activator = a;
}
+void adaptor_think2use_hittype_splash() // for timed projectile detonation
+{
+ if not(self.flags & FL_ONGROUND) // if onground, we ARE touching something, but HITTYPE_SPLASH is to be networked if the damage causing projectile is not touching ANYTHING
+ self.projectiledeathtype |= HITTYPE_SPLASH;
+ adaptor_think2use();
+}
+
// deferred dropping
void DropToFloor_Handler()
{
{
// center
vecs_y = 0;
- vecs_z -= 4;
+ vecs_z -= 2;
}
else
{
{
// center
vecs_y = 0;
- vecs_z -= 4;
+ vecs_z -= 2;
}
else
{
else
{
vecs_y = 0;
- vecs_z -= 4;
+ vecs_z -= 2;
}
}
else if ((s = cvar_string("g_shootfromfixedorigin")) != "")
-//#define MONSTES_ENABLED\r
-#ifdef MONSTES_ENABLED\r
-\r
-#define zombie_anim_attackleap 0\r
-#define zombie_anim_attackrun1 1\r
-#define zombie_anim_attackrun2 2\r
-#define zombie_anim_attackrun3 3\r
-#define zombie_anim_attackstanding1 4\r
-#define zombie_anim_attackstanding2 5\r
-#define zombie_anim_attackstanding3 6\r
-#define zombie_anim_blockend 7\r
-#define zombie_anim_blockstart 8\r
-#define zombie_anim_deathback1 9\r
-#define zombie_anim_deathback2 10\r
-#define zombie_anim_deathback3 11\r
-#define zombie_anim_deathfront1 12\r
-#define zombie_anim_deathfront2 13\r
-#define zombie_anim_deathfront3 14\r
-#define zombie_anim_deathleft1 15\r
-#define zombie_anim_deathleft2 16\r
-#define zombie_anim_deathright1 17\r
-#define zombie_anim_deathright2 18\r
-#define zombie_anim_idle 19\r
-#define zombie_anim_painback1 20\r
-#define zombie_anim_painback2 21\r
-#define zombie_anim_painfront1 22\r
-#define zombie_anim_painfront2 23\r
-#define zombie_anim_runbackwards 24\r
-#define zombie_anim_runbackwardsleft 25\r
-#define zombie_anim_runbackwardsright 26\r
-#define zombie_anim_runforward 27\r
-#define zombie_anim_runforwardleft 28\r
-#define zombie_anim_runforwardright 29\r
-#define zombie_anim_spawn 30\r
-\r
-#define ZOMBIE_MIN '-18 -18 -25'\r
-#define ZOMBIE_MAX '18 18 47'\r
-\r
-#define ZV_IDLE 10\r
-\r
-#define ZV_PATH 100\r
-#define ZV_HUNT 200\r
-\r
-#define ZV_ATTACK_FIND 10\r
-#define ZV_ATTACK_RUN 20\r
-#define ZV_ATTACK_STAND 30\r
-\r
-#define ZV_PATH2 10000\r
-\r
-//.entity verbs_idle;\r
-//.entity verbs_attack;\r
-//.entity verbs_move;\r
-\r
-//.float state_timeout;\r
-//.void() monster_state;\r
-#define MONSTERFLAG_NORESPAWN 2\r
-\r
-void zombie_spawn();\r
-\r
-float zombie_scoretarget(entity trg)\r
-{\r
- float tmp;\r
- vector ang1;\r
-\r
- if (trg.takedamage == DAMAGE_AIM)\r
- if not (trg.flags & FL_NOTARGET)\r
- if (trg.deadflag == DEAD_NO)\r
- if (trg.team != self.team)\r
- {\r
- if((self.origin_z - trg.origin_z) < 128)\r
- {\r
- ang1 = normalize(self.origin - trg.origin);\r
- tmp = vlen(ang1 - v_forward);\r
- if(tmp > 1.5)\r
- {\r
- traceline(self.origin + '0 0 47',trg.origin + '0 0 32',MOVE_NORMAL,self);\r
- if(trace_ent != trg)\r
- return 0;\r
-\r
- return (cvar("g_monster_zombie_targetrange") - vlen(self.origin - trg.origin)) * tmp;\r
- }\r
- else if(self.enemy == trg)\r
- return (cvar("g_monster_zombie_targetrange") - vlen(self.origin - trg.origin)) * tmp;\r
- }\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-void zombie_corpse_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)\r
-{\r
- //dprint("zombie_corpse_damage\n");\r
- Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);\r
-\r
- self.health -= damage;\r
-\r
- if(self.health < 0)\r
- {\r
- Violence_GibSplash(self, 1, 1, attacker);\r
- remove(self);\r
- }\r
-}\r
-\r
-void zombie_die(vector dir)\r
-{\r
- vector v;\r
- float f;\r
-\r
- entity dummy;\r
-\r
- dummy = spawn();\r
- setmodel(dummy,"models/monsters/zombie.dpm");\r
- setorigin(dummy, self.origin);\r
- dummy.velocity = self.velocity;\r
- dummy.movetype = MOVETYPE_BOUNCE;\r
- dummy.think = SUB_Remove;\r
- dummy.nextthink = time + 3;\r
- dummy.health = 50;\r
- dummy.takedamage = DAMAGE_YES;\r
- dummy.event_damage = zombie_corpse_damage;\r
- dummy.solid = SOLID_CORPSE;\r
- setsize(dummy,self.mins,self.maxs);\r
-\r
- SUB_SetFade(dummy,time + 5,2);\r
-\r
-\r
- v = normalize(self.origin - dir);\r
- f = vlen(v_forward - v) - 1;\r
- if(f > 0.5)\r
- dummy.frame = zombie_anim_deathfront1 + rint(random() * 2);\r
- else if(f < 0.5)\r
- dummy.frame = zombie_anim_deathback1 + rint(random() * 2);\r
- else\r
- {\r
- f = vlen(v_right - v) - 1;\r
- if(f > 0.5)\r
- dummy.frame = zombie_anim_deathright1 + rint(random() * 2);\r
- else if(f < 0.5)\r
- dummy.frame = zombie_anim_deathleft1 + rint(random() * 2);\r
- }\r
-\r
-\r
- if(self.spawnflags & MONSTERFLAG_NORESPAWN)\r
- {\r
- self.think = SUB_Remove;\r
- self.nextthink = time;\r
- return;\r
- }\r
-\r
- setmodel(self,"");\r
- self.solid = SOLID_NOT;\r
- self.takedamage = DAMAGE_NO;\r
- self.event_damage = SUB_Null;\r
- self.enemy = world;\r
- self.think = zombie_spawn;\r
- self.nextthink = time + cvar("g_monster_zombie_respawntime");\r
- self.pain_finished = self.nextthink;\r
-}\r
-\r
-void zombie_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)\r
-{\r
-\r
- vector v;\r
- float f;\r
-\r
- v = normalize(self.origin - hitloc);\r
- f = vlen(v_forward - v) - 1;\r
-\r
-\r
- self.health -= damage;\r
- self.velocity = self.velocity + force;\r
- if(self.health <= 0)\r
- {\r
- zombie_die(hitloc);\r
- return;\r
- }\r
-\r
- Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);\r
-\r
- if (damage > 50)\r
- Violence_GibSplash_At(hitloc, force * -0.1, 3, 1, self, attacker);\r
- if (damage > 100)\r
- Violence_GibSplash_At(hitloc, force * -0.2, 3, 1, self, attacker);\r
-\r
- if (time > self.pain_finished)\r
- {\r
- if(f < 0.5)\r
- {\r
- if(random() < 0.5)\r
- self.frame = zombie_anim_painback1;\r
- else\r
- self.frame = zombie_anim_painback2;\r
- }\r
- else\r
- {\r
- if(random() < 0.5)\r
- self.frame = zombie_anim_painfront1;\r
- else\r
- self.frame = zombie_anim_painfront2;\r
- }\r
-\r
- self.pain_finished = time + 0.36;\r
- }\r
-}\r
-\r
-.vector bvec;\r
-.float bvec_time;\r
-\r
-void zombie_move()\r
-{\r
- vector real_angle;\r
- float vz, tdiff, tspeed;\r
-\r
- tdiff = time - self.zoomstate;\r
- tspeed = tdiff * cvar("g_monster_zombie_turnspeed");\r
- vz = self.velocity_z;\r
- self.zoomstate = time;\r
-\r
- if(self.bvec_time < time)\r
- {\r
- self.bvec_time = time + 0.2;\r
- self.bvec = steerlib_beamsteer(steerlib_attract2(self.moveto,0.5,500,0.95),512,32,34,64);\r
- }\r
-\r
- if(self.enemy)\r
- self.moveto = self.enemy.origin;\r
- else\r
- self.moveto = self.origin + v_forward;\r
-\r
- self.steerto = normalize(steerlib_attract2(self.moveto,0.5,500,0.95) + self.bvec);\r
-\r
- self.angles_y = safeangle(self.angles_y);\r
- real_angle = vectoangles(self.steerto) - self.angles;\r
- self.angles_y += bound(-10, real_angle_y, 10);\r
-\r
- if(vlen(self.origin - self.moveto) > 64)\r
- {\r
- movelib_move_simple(v_forward ,cvar("g_monster_zombie_movespeed"),0.6);\r
- if(time > self.pain_finished)\r
- if(self.attack_finished_single < time)\r
- self.frame = zombie_anim_runforward;\r
- }\r
- else\r
- {\r
- movelib_beak_simple(cvar("g_monster_zombie_stopspeed"));\r
- if(time > self.pain_finished)\r
- if(self.attack_finished_single < time)\r
- self.frame = zombie_anim_idle;\r
- }\r
-\r
- self.velocity_z = vz;\r
- self.steerto = self.origin;\r
-}\r
-\r
-float zombie_verb_idle_roam(float eval)\r
-{\r
- switch (eval)\r
- {\r
- case VCM_EVAL:\r
-\r
- if(self.enemy)\r
- return VS_CALL_NO;\r
-\r
- return verb.verb_static_value;\r
-\r
- case VCM_DO:\r
-\r
- self.moveto = v_forward * 128;\r
- self.steerto = v_forward; //steerlib_beamsteer(v_forward,512,32,34,64);\r
-\r
- return VS_CALL_YES_DOING;\r
- }\r
-\r
- return VS_CALL_YES_DONE;\r
-}\r
-\r
-float zombie_verb_idle_stand(float eval)\r
-{\r
- switch (eval)\r
- {\r
- case VCM_EVAL:\r
-\r
- if(self.enemy)\r
- return VS_CALL_NO;\r
-\r
- return verb.verb_static_value;\r
-\r
- case VCM_DO:\r
-\r
- self.moveto = self.origin;\r
- self.frame = zombie_anim_idle;\r
- self.velocity = '0 0 0';\r
-\r
- return VS_CALL_YES_DOING;\r
- }\r
-\r
- return VS_CALL_YES_DONE;\r
-}\r
-\r
-float zombie_verb_idle(float eval)\r
-{\r
- switch (eval)\r
- {\r
- case VCM_EVAL:\r
-\r
- if(self.enemy)\r
- return VS_CALL_NO;\r
-\r
- return verb.verb_static_value;\r
-\r
- case VCM_DO:\r
- float t;\r
-\r
- t = cvar("g_monster_zombie_idle_timer_max") - cvar("g_monster_zombie_idle_timer_min");\r
- t = cvar("g_monster_zombie_idle_timer_min") + (random() * t);\r
-\r
- if(random() < 0.5)\r
- verbstack_push(self.verbs_idle, zombie_verb_idle_roam, ZV_IDLE + 1, t, self);\r
- else\r
- verbstack_push(self.verbs_idle, zombie_verb_idle_stand, ZV_IDLE + 1, 0.1, self);\r
-\r
- return VS_CALL_YES_DOING;\r
- }\r
-\r
- return VS_CALL_YES_DONE;\r
-}\r
-\r
-float zombie_verb_attack_findtarget(float eval)\r
-{\r
- switch (eval)\r
- {\r
- case VCM_EVAL:\r
- if(self.enemy)\r
- return VS_CALL_NO;\r
-\r
- return verb.verb_static_value;\r
-\r
- case VCM_DO:\r
-\r
- entity trg, best_trg;\r
- float trg_score, best_trg_score;\r
-\r
- trg = findradius(self.origin,cvar("g_monster_zombie_targetrange"));\r
- while(trg)\r
- {\r
- trg_score = zombie_scoretarget(trg);\r
- if(trg_score > best_trg_score)\r
- {\r
- best_trg = trg;\r
- best_trg_score = trg_score;\r
- }\r
-\r
- trg = trg.chain;\r
- }\r
-\r
- if(best_trg)\r
- {\r
- self.enemy = best_trg;\r
- dprint("Selected: ",best_trg.netname, " as target.\n");\r
- }\r
-\r
- return VS_CALL_YES_DOING;\r
- }\r
-\r
- return VS_CALL_YES_DONE;\r
-}\r
-\r
-void zombie_runattack_damage()\r
-{\r
- entity oldself;\r
- oldself = self;\r
- self = self.owner;\r
-\r
- if(vlen(self.origin - self.enemy.origin) > cvar("g_monster_zombie_attack_run_hitrange"))\r
- return;\r
-\r
- if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6)\r
- return;\r
-\r
- Damage(self.enemy, self, self, cvar("g_monster_zombie_attack_run_damage"), DEATH_TURRET, self.enemy.origin, normalize(self.enemy.origin - self.origin) * cvar("g_monster_zombie_attack_run_force"));\r
-\r
- self = oldself;\r
- self.think = SUB_Remove;\r
- self.nextthink = time;\r
-}\r
-\r
-float zombie_verb_attack_run(float eval)\r
-{\r
- switch (eval)\r
- {\r
- case VCM_EVAL:\r
- if not (self.enemy)\r
- return VS_CALL_NO;\r
-\r
- if(self.attack_finished_single > time)\r
- return VS_CALL_NO;\r
-\r
- if(vlen(self.origin - self.enemy.origin) > cvar("g_monster_zombie_attack_run_range"))\r
- return VS_CALL_NO;\r
-\r
- if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6)\r
- return VS_CALL_NO;\r
-\r
- return verb.verb_static_value;\r
-\r
- case VCM_DO:\r
- entity pain;\r
- pain = spawn();\r
- pain.owner = self;\r
- pain.think = zombie_runattack_damage;\r
- pain.nextthink = time + cvar("g_monster_zombie_attack_run_delay");\r
-\r
- self.attack_finished_single = time + 0.7;\r
- self.frame = zombie_anim_attackrun1 + rint(random() * 2);\r
-\r
- return VS_CALL_YES_DOING;\r
- }\r
-\r
- return VS_CALL_YES_DONE;\r
-}\r
-\r
-void zombie_standattack_damage()\r
-{\r
- //entity oldself;\r
- //oldself = self;\r
- //self = self.owner;\r
-\r
- setorigin(self,self.owner.origin + v_forward * 32);\r
- RadiusDamage(self, self.owner, cvar("g_monster_zombie_attack_stand_damage"),cvar("g_monster_zombie_attack_stand_damage"),16,self, cvar("g_monster_zombie_attack_stand_force"),DEATH_TURRET,world);\r
- //float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity ignore, float forceintensity, float deathtype, entity directhitentity)\r
-\r
-\r
- //self = oldself;\r
- self.think = SUB_Remove;\r
- self.nextthink = time;\r
-}\r
-\r
-float zombie_verb_attack_stand(float eval)\r
-{\r
- switch (eval)\r
- {\r
- case VCM_EVAL:\r
- if not (self.enemy)\r
- return VS_CALL_NO;\r
-\r
- if(self.attack_finished_single > time)\r
- return VS_CALL_NO;\r
-\r
- if(vlen(self.origin - self.enemy.origin) > cvar("g_monster_zombie_attack_stand_range"))\r
- return VS_CALL_NO;\r
-\r
- if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.8)\r
- return VS_CALL_NO;\r
-\r
- return verb.verb_static_value;\r
-\r
- case VCM_DO:\r
- entity pain;\r
- pain = spawn();\r
- pain.owner = self;\r
- pain.think = zombie_runattack_damage;\r
- pain.nextthink = time + cvar("g_monster_zombie_attack_stand_delay");\r
-\r
- self.attack_finished_single = time + 0.7;\r
- self.frame = zombie_anim_attackstanding1 + rint(random() * 1);\r
- dprint("frame:",ftos(self.frame),"\n");\r
-\r
- return VS_CALL_YES_DOING;\r
- }\r
-\r
- return VS_CALL_YES_DONE;\r
-}\r
-\r
-void zombie_think()\r
-{\r
- self.angles_x *= -1;\r
- makevectors(self.angles);\r
- self.angles_x *= -1;\r
-\r
- if (zombie_scoretarget(self.enemy) == 0)\r
- self.enemy = world;\r
-\r
- verbstack_pop(self.verbs_attack);\r
- //verbstack_pop(self.verbs_move);\r
-\r
- if not (self.enemy)\r
- verbstack_pop(self.verbs_idle);\r
-\r
- zombie_move();\r
-\r
- if(self.enemy)\r
- self.nextthink = time;\r
- else\r
- self.nextthink = time + 0.2;\r
-}\r
-\r
-void zombie_spawn()\r
-{\r
- setmodel(self,"models/monsters/zombie.dpm");\r
-\r
- self.solid = SOLID_BBOX;\r
- self.takedamage = DAMAGE_AIM;\r
- self.event_damage = zombie_damage;\r
- self.enemy = world;\r
- self.frame = zombie_anim_spawn;\r
- self.think = zombie_think;\r
- self.nextthink = time + 2.1;\r
- self.pain_finished = self.nextthink;\r
- self.movetype = MOVETYPE_WALK;\r
- self.health = cvar("g_monster_zombie_health");\r
- self.velocity = '0 0 0';\r
- self.angles = self.pos2;\r
- self.moveto = self.origin;\r
- self.flags = FL_MONSTER;\r
-\r
- setorigin(self,self.pos1);\r
- setsize(self,ZOMBIE_MIN,ZOMBIE_MAX);\r
-}\r
-\r
-\r
-void spawnfunc_monster_zombie()\r
-{\r
- if not(cvar("g_monsters"))\r
- {\r
- remove(self);\r
- return;\r
- }\r
-\r
- precache_model("models/monsters/zombie.dpm");\r
-\r
-\r
- self.verbs_idle = spawn();\r
- self.verbs_attack = spawn();\r
-\r
- self.verbs_idle.owner = self;\r
- self.verbs_attack.owner = self;\r
-\r
- self.think = zombie_spawn;\r
- self.nextthink = time + 2;\r
-\r
- traceline(self.origin + '0 0 10', self.origin - '0 0 32', MOVE_WORLDONLY, self);\r
-\r
- self.pos1 = trace_endpos;\r
- self.pos2 = self.angles;\r
- self.team = MAX_SHOT_DISTANCE -1;\r
-\r
- verbstack_push(self.verbs_idle, zombie_verb_idle, ZV_IDLE,0 , self);\r
-\r
- verbstack_push(self.verbs_attack, zombie_verb_attack_findtarget, ZV_ATTACK_FIND,0 , self);\r
- verbstack_push(self.verbs_attack, zombie_verb_attack_run, ZV_ATTACK_RUN,0 , self);\r
- verbstack_push(self.verbs_attack, zombie_verb_attack_stand, ZV_ATTACK_STAND,0 , self);\r
-\r
-}\r
-\r
-#endif // MONSTES_ENABLED\r
+//#define MONSTES_ENABLED
+#ifdef MONSTES_ENABLED
+
+#define zombie_anim_attackleap 0
+#define zombie_anim_attackrun1 1
+#define zombie_anim_attackrun2 2
+#define zombie_anim_attackrun3 3
+#define zombie_anim_attackstanding1 4
+#define zombie_anim_attackstanding2 5
+#define zombie_anim_attackstanding3 6
+#define zombie_anim_blockend 7
+#define zombie_anim_blockstart 8
+#define zombie_anim_deathback1 9
+#define zombie_anim_deathback2 10
+#define zombie_anim_deathback3 11
+#define zombie_anim_deathfront1 12
+#define zombie_anim_deathfront2 13
+#define zombie_anim_deathfront3 14
+#define zombie_anim_deathleft1 15
+#define zombie_anim_deathleft2 16
+#define zombie_anim_deathright1 17
+#define zombie_anim_deathright2 18
+#define zombie_anim_idle 19
+#define zombie_anim_painback1 20
+#define zombie_anim_painback2 21
+#define zombie_anim_painfront1 22
+#define zombie_anim_painfront2 23
+#define zombie_anim_runbackwards 24
+#define zombie_anim_runbackwardsleft 25
+#define zombie_anim_runbackwardsright 26
+#define zombie_anim_runforward 27
+#define zombie_anim_runforwardleft 28
+#define zombie_anim_runforwardright 29
+#define zombie_anim_spawn 30
+
+#define ZOMBIE_MIN '-18 -18 -25'
+#define ZOMBIE_MAX '18 18 47'
+
+#define ZV_IDLE 10
+
+#define ZV_PATH 100
+#define ZV_HUNT 200
+
+#define ZV_ATTACK_FIND 10
+#define ZV_ATTACK_RUN 20
+#define ZV_ATTACK_STAND 30
+
+#define ZV_PATH2 10000
+
+//.entity verbs_idle;
+//.entity verbs_attack;
+//.entity verbs_move;
+
+//.float state_timeout;
+//.void() monster_state;
+#define MONSTERFLAG_NORESPAWN 2
+
+void zombie_spawn();
+
+float zombie_scoretarget(entity trg)
+{
+ float tmp;
+ vector ang1;
+
+ if (trg.takedamage == DAMAGE_AIM)
+ if not (trg.flags & FL_NOTARGET)
+ if (trg.deadflag == DEAD_NO)
+ if (trg.team != self.team)
+ {
+ if((self.origin_z - trg.origin_z) < 128)
+ {
+ ang1 = normalize(self.origin - trg.origin);
+ tmp = vlen(ang1 - v_forward);
+ if(tmp > 1.5)
+ {
+ traceline(self.origin + '0 0 47',trg.origin + '0 0 32',MOVE_NORMAL,self);
+ if(trace_ent != trg)
+ return 0;
+
+ return (cvar("g_monster_zombie_targetrange") - vlen(self.origin - trg.origin)) * tmp;
+ }
+ else if(self.enemy == trg)
+ return (cvar("g_monster_zombie_targetrange") - vlen(self.origin - trg.origin)) * tmp;
+ }
+ }
+
+ return 0;
+}
+
+void zombie_corpse_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+ //dprint("zombie_corpse_damage\n");
+ Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
+
+ self.health -= damage;
+
+ if(self.health < 0)
+ {
+ Violence_GibSplash(self, 1, 1, attacker);
+ remove(self);
+ }
+}
+
+void zombie_die(vector dir)
+{
+ vector v;
+ float f;
+
+ entity dummy;
+
+ dummy = spawn();
+ setmodel(dummy,"models/monsters/zombie.dpm");
+ setorigin(dummy, self.origin);
+ dummy.velocity = self.velocity;
+ dummy.movetype = MOVETYPE_BOUNCE;
+ dummy.think = SUB_Remove;
+ dummy.nextthink = time + 3;
+ dummy.health = 50;
+ dummy.takedamage = DAMAGE_YES;
+ dummy.event_damage = zombie_corpse_damage;
+ dummy.solid = SOLID_CORPSE;
+ setsize(dummy,self.mins,self.maxs);
+
+ SUB_SetFade(dummy,time + 5,2);
+
+
+ v = normalize(self.origin - dir);
+ f = vlen(v_forward - v) - 1;
+ if(f > 0.5)
+ dummy.frame = zombie_anim_deathfront1 + rint(random() * 2);
+ else if(f < 0.5)
+ dummy.frame = zombie_anim_deathback1 + rint(random() * 2);
+ else
+ {
+ f = vlen(v_right - v) - 1;
+ if(f > 0.5)
+ dummy.frame = zombie_anim_deathright1 + rint(random() * 2);
+ else if(f < 0.5)
+ dummy.frame = zombie_anim_deathleft1 + rint(random() * 2);
+ }
+
+
+ if(self.spawnflags & MONSTERFLAG_NORESPAWN)
+ {
+ self.think = SUB_Remove;
+ self.nextthink = time;
+ return;
+ }
+
+ setmodel(self,"");
+ self.solid = SOLID_NOT;
+ self.takedamage = DAMAGE_NO;
+ self.event_damage = SUB_Null;
+ self.enemy = world;
+ self.think = zombie_spawn;
+ self.nextthink = time + cvar("g_monster_zombie_respawntime");
+ self.pain_finished = self.nextthink;
+}
+
+void zombie_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+
+ vector v;
+ float f;
+
+ v = normalize(self.origin - hitloc);
+ f = vlen(v_forward - v) - 1;
+
+
+ self.health -= damage;
+ self.velocity = self.velocity + force;
+ if(self.health <= 0)
+ {
+ zombie_die(hitloc);
+ return;
+ }
+
+ Violence_GibSplash_At(hitloc, force, 2, bound(0, damage, 200) / 16, self, attacker);
+
+ if (damage > 50)
+ Violence_GibSplash_At(hitloc, force * -0.1, 3, 1, self, attacker);
+ if (damage > 100)
+ Violence_GibSplash_At(hitloc, force * -0.2, 3, 1, self, attacker);
+
+ if (time > self.pain_finished)
+ {
+ if(f < 0.5)
+ {
+ if(random() < 0.5)
+ self.frame = zombie_anim_painback1;
+ else
+ self.frame = zombie_anim_painback2;
+ }
+ else
+ {
+ if(random() < 0.5)
+ self.frame = zombie_anim_painfront1;
+ else
+ self.frame = zombie_anim_painfront2;
+ }
+
+ self.pain_finished = time + 0.36;
+ }
+}
+
+.vector bvec;
+.float bvec_time;
+
+void zombie_move()
+{
+ vector real_angle;
+ float vz, tdiff, tspeed;
+
+ tdiff = time - self.zoomstate;
+ tspeed = tdiff * cvar("g_monster_zombie_turnspeed");
+ vz = self.velocity_z;
+ self.zoomstate = time;
+
+ if(self.bvec_time < time)
+ {
+ self.bvec_time = time + 0.2;
+ self.bvec = steerlib_beamsteer(steerlib_attract2(self.moveto,0.5,500,0.95),512,32,34,64);
+ }
+
+ if(self.enemy)
+ self.moveto = self.enemy.origin;
+ else
+ self.moveto = self.origin + v_forward;
+
+ self.steerto = normalize(steerlib_attract2(self.moveto,0.5,500,0.95) + self.bvec);
+
+ self.angles_y = safeangle(self.angles_y);
+ real_angle = vectoangles(self.steerto) - self.angles;
+ self.angles_y += bound(-10, real_angle_y, 10);
+
+ if(vlen(self.origin - self.moveto) > 64)
+ {
+ movelib_move_simple(v_forward ,cvar("g_monster_zombie_movespeed"),0.6);
+ if(time > self.pain_finished)
+ if(self.attack_finished_single < time)
+ self.frame = zombie_anim_runforward;
+ }
+ else
+ {
+ movelib_beak_simple(cvar("g_monster_zombie_stopspeed"));
+ if(time > self.pain_finished)
+ if(self.attack_finished_single < time)
+ self.frame = zombie_anim_idle;
+ }
+
+ self.velocity_z = vz;
+ self.steerto = self.origin;
+}
+
+float zombie_verb_idle_roam(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+
+ if(self.enemy)
+ return VS_CALL_NO;
+
+ return verb.verb_static_value;
+
+ case VCM_DO:
+
+ self.moveto = v_forward * 128;
+ self.steerto = v_forward; //steerlib_beamsteer(v_forward,512,32,34,64);
+
+ return VS_CALL_YES_DOING;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+float zombie_verb_idle_stand(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+
+ if(self.enemy)
+ return VS_CALL_NO;
+
+ return verb.verb_static_value;
+
+ case VCM_DO:
+
+ self.moveto = self.origin;
+ self.frame = zombie_anim_idle;
+ self.velocity = '0 0 0';
+
+ return VS_CALL_YES_DOING;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+float zombie_verb_idle(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+
+ if(self.enemy)
+ return VS_CALL_NO;
+
+ return verb.verb_static_value;
+
+ case VCM_DO:
+ float t;
+
+ t = cvar("g_monster_zombie_idle_timer_max") - cvar("g_monster_zombie_idle_timer_min");
+ t = cvar("g_monster_zombie_idle_timer_min") + (random() * t);
+
+ if(random() < 0.5)
+ verbstack_push(self.verbs_idle, zombie_verb_idle_roam, ZV_IDLE + 1, t, self);
+ else
+ verbstack_push(self.verbs_idle, zombie_verb_idle_stand, ZV_IDLE + 1, 0.1, self);
+
+ return VS_CALL_YES_DOING;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+float zombie_verb_attack_findtarget(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+ if(self.enemy)
+ return VS_CALL_NO;
+
+ return verb.verb_static_value;
+
+ case VCM_DO:
+
+ entity trg, best_trg;
+ float trg_score, best_trg_score;
+
+ trg = findradius(self.origin,cvar("g_monster_zombie_targetrange"));
+ while(trg)
+ {
+ trg_score = zombie_scoretarget(trg);
+ if(trg_score > best_trg_score)
+ {
+ best_trg = trg;
+ best_trg_score = trg_score;
+ }
+
+ trg = trg.chain;
+ }
+
+ if(best_trg)
+ {
+ self.enemy = best_trg;
+ dprint("Selected: ",best_trg.netname, " as target.\n");
+ }
+
+ return VS_CALL_YES_DOING;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+void zombie_runattack_damage()
+{
+ entity oldself;
+ oldself = self;
+ self = self.owner;
+
+ if(vlen(self.origin - self.enemy.origin) > cvar("g_monster_zombie_attack_run_hitrange"))
+ return;
+
+ if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6)
+ return;
+
+ Damage(self.enemy, self, self, cvar("g_monster_zombie_attack_run_damage"), DEATH_TURRET, self.enemy.origin, normalize(self.enemy.origin - self.origin) * cvar("g_monster_zombie_attack_run_force"));
+
+ self = oldself;
+ self.think = SUB_Remove;
+ self.nextthink = time;
+}
+
+float zombie_verb_attack_run(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+ if not (self.enemy)
+ return VS_CALL_NO;
+
+ if(self.attack_finished_single > time)
+ return VS_CALL_NO;
+
+ if(vlen(self.origin - self.enemy.origin) > cvar("g_monster_zombie_attack_run_range"))
+ return VS_CALL_NO;
+
+ if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.6)
+ return VS_CALL_NO;
+
+ return verb.verb_static_value;
+
+ case VCM_DO:
+ entity pain;
+ pain = spawn();
+ pain.owner = self;
+ pain.think = zombie_runattack_damage;
+ pain.nextthink = time + cvar("g_monster_zombie_attack_run_delay");
+
+ self.attack_finished_single = time + 0.7;
+ self.frame = zombie_anim_attackrun1 + rint(random() * 2);
+
+ return VS_CALL_YES_DOING;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+void zombie_standattack_damage()
+{
+ //entity oldself;
+ //oldself = self;
+ //self = self.owner;
+
+ setorigin(self,self.owner.origin + v_forward * 32);
+ RadiusDamage(self, self.owner, cvar("g_monster_zombie_attack_stand_damage"),cvar("g_monster_zombie_attack_stand_damage"),16,self, cvar("g_monster_zombie_attack_stand_force"),DEATH_TURRET,world);
+ //float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity ignore, float forceintensity, float deathtype, entity directhitentity)
+
+
+ //self = oldself;
+ self.think = SUB_Remove;
+ self.nextthink = time;
+}
+
+float zombie_verb_attack_stand(float eval)
+{
+ switch (eval)
+ {
+ case VCM_EVAL:
+ if not (self.enemy)
+ return VS_CALL_NO;
+
+ if(self.attack_finished_single > time)
+ return VS_CALL_NO;
+
+ if(vlen(self.origin - self.enemy.origin) > cvar("g_monster_zombie_attack_stand_range"))
+ return VS_CALL_NO;
+
+ if(vlen(normalize(self.origin - self.enemy.origin) - v_forward) < 1.8)
+ return VS_CALL_NO;
+
+ return verb.verb_static_value;
+
+ case VCM_DO:
+ entity pain;
+ pain = spawn();
+ pain.owner = self;
+ pain.think = zombie_runattack_damage;
+ pain.nextthink = time + cvar("g_monster_zombie_attack_stand_delay");
+
+ self.attack_finished_single = time + 0.7;
+ self.frame = zombie_anim_attackstanding1 + rint(random() * 1);
+ dprint("frame:",ftos(self.frame),"\n");
+
+ return VS_CALL_YES_DOING;
+ }
+
+ return VS_CALL_YES_DONE;
+}
+
+void zombie_think()
+{
+ self.angles_x *= -1;
+ makevectors(self.angles);
+ self.angles_x *= -1;
+
+ if (zombie_scoretarget(self.enemy) == 0)
+ self.enemy = world;
+
+ verbstack_pop(self.verbs_attack);
+ //verbstack_pop(self.verbs_move);
+
+ if not (self.enemy)
+ verbstack_pop(self.verbs_idle);
+
+ zombie_move();
+
+ if(self.enemy)
+ self.nextthink = time;
+ else
+ self.nextthink = time + 0.2;
+}
+
+void zombie_spawn()
+{
+ setmodel(self,"models/monsters/zombie.dpm");
+
+ self.solid = SOLID_BBOX;
+ self.takedamage = DAMAGE_AIM;
+ self.event_damage = zombie_damage;
+ self.enemy = world;
+ self.frame = zombie_anim_spawn;
+ self.think = zombie_think;
+ self.nextthink = time + 2.1;
+ self.pain_finished = self.nextthink;
+ self.movetype = MOVETYPE_WALK;
+ self.health = cvar("g_monster_zombie_health");
+ self.velocity = '0 0 0';
+ self.angles = self.pos2;
+ self.moveto = self.origin;
+ self.flags = FL_MONSTER;
+
+ setorigin(self,self.pos1);
+ setsize(self,ZOMBIE_MIN,ZOMBIE_MAX);
+}
+
+
+void spawnfunc_monster_zombie()
+{
+ if not(cvar("g_monsters"))
+ {
+ remove(self);
+ return;
+ }
+
+ precache_model("models/monsters/zombie.dpm");
+
+
+ self.verbs_idle = spawn();
+ self.verbs_attack = spawn();
+
+ self.verbs_idle.owner = self;
+ self.verbs_attack.owner = self;
+
+ self.think = zombie_spawn;
+ self.nextthink = time + 2;
+
+ traceline(self.origin + '0 0 10', self.origin - '0 0 32', MOVE_WORLDONLY, self);
+
+ self.pos1 = trace_endpos;
+ self.pos2 = self.angles;
+ self.team = MAX_SHOT_DISTANCE -1;
+
+ verbstack_push(self.verbs_idle, zombie_verb_idle, ZV_IDLE,0 , self);
+
+ verbstack_push(self.verbs_attack, zombie_verb_attack_findtarget, ZV_ATTACK_FIND,0 , self);
+ verbstack_push(self.verbs_attack, zombie_verb_attack_run, ZV_ATTACK_RUN,0 , self);
+ verbstack_push(self.verbs_attack, zombie_verb_attack_stand, ZV_ATTACK_STAND,0 , self);
+
+}
+
+#endif // MONSTES_ENABLED
--- /dev/null
+.float() cbc_func;
+.entity cbc_next;
+.float cbc_order;
+
+entity CallbackChain_New(string name)
+{
+ entity e;
+ e = spawn();
+ e.classname = "callbackchain";
+ e.netname = name;
+ return e;
+}
+
+float CallbackChain_Add(entity cb, float() func, float order)
+{
+ entity e;
+ if(order & CBC_ORDER_FIRST)
+ {
+ if(order & CBC_ORDER_LAST)
+ if(cb.cbc_order & CBC_ORDER_ANY)
+ return 0;
+ if(cb.cbc_order & CBC_ORDER_FIRST)
+ return 0;
+ }
+ else if(order & CBC_ORDER_LAST)
+ {
+ if(cb.cbc_order & CBC_ORDER_LAST)
+ return 0;
+ }
+ entity thiscb;
+ thiscb = spawn();
+ thiscb.classname = "callback";
+ thiscb.cbc_func = func;
+ thiscb.cbc_order = order;
+ if(order & CBC_ORDER_FIRST)
+ {
+ thiscb.cbc_next = cb.cbc_next;
+ cb.cbc_next = thiscb;
+ }
+ else if(order & CBC_ORDER_LAST)
+ {
+ for(e = cb; e.cbc_next; e = e.cbc_next);
+ e.cbc_next = thiscb;
+ }
+ else
+ {
+ // by default we execute last, but before a possible CBC_ORDER_LAST callback
+ for(e = cb; e.cbc_next && !(e.cbc_next.cbc_order & CBC_ORDER_LAST); e = e.cbc_next); // we must make sure that we insert BEFORE an CBC_ORDER_LAST mutator!
+ thiscb.cbc_next = e.cbc_next;
+ e.cbc_next = thiscb;
+ }
+ cb.cbc_order |= (order | CBC_ORDER_ANY);
+ return 1;
+}
+
+float CallbackChain_Remove(entity cb, float() func)
+{
+ float order;
+ entity e;
+ float n;
+ n = 0;
+ for(e = cb; e.cbc_next; e = e.cbc_next)
+ {
+ while(e.cbc_next.cbc_func == func)
+ {
+ // remove e.cbc_next from the chain
+ entity e2;
+ e2 = e.cbc_next.cbc_next;
+ remove(e.cbc_next);
+ e.cbc_next = e2;
+ ++n;
+ }
+ // e.cbc_next is now something we want to keep
+ order |= (e.cbc_next.cbc_order & CBC_ORDER_ANY);
+ }
+ cb.cbc_order = order;
+ return n;
+}
+
+float CallbackChain_Call(entity cb)
+{
+ float r;
+ entity e;
+ r = 0;
+ for(e = cb; e.cbc_next; e = e.cbc_next)
+ r |= e.cbc_next.cbc_func();
+ return r; // callbacks return an error status, so 0 is default return value
+}
+
+float Mutator_Add(float(float) func)
+{
+ if(func(MUTATOR_ADDING) == 0)
+ {
+ // good
+ return 1;
+ }
+ backtrace("WARNING: when adding mutator: adding failed\n");
+ Mutator_Remove(func);
+ return 0;
+}
+void Mutator_Remove(float(float) func)
+{
+ if(func(MUTATOR_REMOVING) != 0)
+ {
+ // baaaaad
+ error("Mutator_Remove: removing mutator failed");
+ }
+}
--- /dev/null
+#define CBC_ORDER_EXCLUSIVE 3
+#define CBC_ORDER_FIRST 1
+#define CBC_ORDER_LAST 2
+#define CBC_ORDER_ANY 4
+
+entity CallbackChain_New(string name);
+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)
+// {
+// do something
+// return r;
+// }
+float CallbackChain_Call(entity cb);
+
+#define MUTATOR_REMOVING 0
+#define MUTATOR_ADDING 1
+float Mutator_Add(float(float) func);
+void Mutator_Remove(float(float) func); // calls error() on fail
+
+#define MUTATOR_ADD(name) Mutator_Add(MUTATOR_##name)
+#define MUTATOR_REMOVE(name) Mutator_Remove(MUTATOR_##name)
+#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_ONADD if(mode == MUTATOR_ADDING)
+#define MUTATOR_ONREMOVE if(mode == MUTATOR_REMOVING)
+
+#define MUTATOR_HOOKABLE(cb) entity HOOK_##cb
+#define MUTATOR_CALLHOOK(cb) CallbackChain_Call(HOOK_##cb)
+
+
+
+
+
+// register all possible hooks here
+
+MUTATOR_HOOKABLE(MakePlayerObserver);
+ // called when a player becomes observer, after shared setup
+
+MUTATOR_HOOKABLE(PlayerSpawn);
+ // called when a player spawns as player, after shared setup, before his weapon is chosen (so items may be changed in here)
+
+MUTATOR_HOOKABLE(ClientDisconnect);
+ // called when a player disconnects
+
+MUTATOR_HOOKABLE(PlayerDies);
+ // called when a player dies to e.g. remove stuff he was carrying.
+ // INPUT:
+ entity frag_inflictor;
+ entity frag_attacker;
+ entity frag_target; // same as self
+
+MUTATOR_HOOKABLE(GiveFragsForKill);
+ // called when someone was fragged by "self", and is expected to change frag_score to adjust scoring for the kill
+ // INPUT:
+ entity frag_attacker; // same as self
+ entity frag_target;
+ // INPUT, OUTPUT:
+ float frag_score;
+
+MUTATOR_HOOKABLE(MatchEnd);
+ // called when the match ends
+
+MUTATOR_HOOKABLE(GetTeamCount);
+ // should adjust ret_float to contain the team count
+ // INPUT, OUTPUT:
+ float ret_float;
+
+MUTATOR_HOOKABLE(SpectateCopy);
+ // copies variables for spectating "other" to "self"
+ // INPUT:
+ entity other;
+
+MUTATOR_HOOKABLE(ForbidThrowCurrentWeapon);
+ // returns 1 if throwing the current weapon shall not be allowed
+
+MUTATOR_HOOKABLE(SetStartItems);
+ // adjusts {warmup_}start_{items,weapons,ammo_{cells,rockets,nails,shells,fuel}}
+
+MUTATOR_HOOKABLE(BuildMutatorsString);
+ // appends ":mutatorname" to ret_string for logging
+ // INPUT, OUTPUT:
+ string ret_string;
+
+MUTATOR_HOOKABLE(BuildMutatorsPrettyString);
+ // appends ", Mutator name" to ret_string for display
+ // INPUT, OUTPUT:
+ string ret_string;
+
+MUTATOR_HOOKABLE(FilterItem);
+ // checks if the current item may be spawned (self.items and self.weapons may be read and written to, as well as the ammo_ fields)
+ // return error to request removal
+
+MUTATOR_HOOKABLE(OnEntityPreSpawn);
+ // return error to prevent entity spawn, or modify the entity
+
+MUTATOR_HOOKABLE(PlayerPreThink);
+ // runs in the event loop for players; is called for ALL player entities, also bots, also the dead, or spectators
+
+MUTATOR_HOOKABLE(GetPressedKeys);
+ // TODO change this into a general PlayerPostThink hook?
+
+MUTATOR_HOOKABLE(PlayerPhysics);
+ // called before any player physics, may adjust variables for movement,
+ // is run AFTER bot code and idle checking
+
+MUTATOR_HOOKABLE(GetCvars);
+ // is meant to call GetCvars_handle*(get_cvars_s, get_cvars_f, cvarfield, "cvarname") for cvars this mutator needs from the client
+ // INPUT:
+ float get_cvars_f;
+ string get_cvars_s;
--- /dev/null
+#define FOR_EACH_KH_KEY(v) for(v = kh_worldkeylist; v; v = v.kh_worldkeynext )
+
+// #define KH_PLAYER_USE_ATTACHMENT
+// #define KH_PLAYER_USE_CARRIEDMODEL
+// #define KH_KEY_ATTACHMENT_DEBUG
+
+#ifdef KH_PLAYER_USE_ATTACHMENT
+vector KH_PLAYER_ATTACHMENT_DIST_ROTATED = '0 -4 0';
+vector KH_PLAYER_ATTACHMENT_DIST = '4 0 0';
+vector KH_PLAYER_ATTACHMENT = '0 0 0';
+vector KH_PLAYER_ATTACHMENT_ANGLES = '0 0 0';
+string KH_PLAYER_ATTACHMENT_BONE = "";
+#else
+float KH_KEY_ZSHIFT = 22;
+float KH_KEY_XYDIST = 24;
+float KH_KEY_XYSPEED = 45;
+#endif
+float KH_KEY_WP_ZSHIFT = 20;
+
+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
+// bits 0- 4: team of key 1, or 0 for no such key, or 30 for dropped, or 31 for self
+// bits 5- 9: team of key 2, or 0 for no such key, or 30 for dropped, or 31 for self
+// bits 10-14: team of key 3, or 0 for no such key, or 30 for dropped, or 31 for self
+// bits 15-19: team of key 4, or 0 for no such key, or 30 for dropped, or 31 for self
+.float kh_state;
+.float siren_time; // time delay the siren
+//.float stuff_time; // time delay to stuffcmd a cvar
+
+float test[17] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+//test[0] = status of dropped keys, test[1 - 16] = player #
+//replace 17 with cvar("maxplayers") or similar !!!!!!!!!
+//for(i = 0; i < maxplayers; ++i)
+// test[i] = "0";
+
+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;
+ return 0;
+}
+
+entity kh_worldkeylist;
+.entity kh_worldkeynext;
+entity kh_controller;
+float kh_tracking_enabled;
+float kh_teams;
+float kh_interferemsg_time, kh_interferemsg_team;
+.entity kh_next, kh_prev; // linked list
+.float kh_droptime;
+.float kh_dropperteam;
+.entity kh_previous_owner;
+.float kh_previous_owner_playerid;
+
+string kh_sound_capture = "kh/capture.wav";
+string kh_sound_destroy = "kh/destroy.wav";
+string kh_sound_drop = "kh/drop.wav";
+string kh_sound_collect = "kh/collect.wav";
+string kh_sound_alarm = "kh/alarm.wav"; // the new siren/alarm
+
+float kh_key_dropped, kh_key_carried;
+
+float kh_KeyCarrier_waypointsprite_visible_for_player(entity e) // runs all the time
+{
+ if(e.classname != "player" || self.team != e.team)
+ if(!kh_tracking_enabled)
+ return FALSE;
+
+ return TRUE;
+}
+
+float kh_Key_waypointsprite_visible_for_player(entity e) // ??
+{
+ if(!kh_tracking_enabled)
+ return FALSE;
+ if(!self.owner)
+ return TRUE;
+ if(!self.owner.owner)
+ return TRUE;
+ return FALSE; // draw only when key is not owned
+}
+
+void kh_update_state()
+{
+ entity player;
+ entity key;
+ float s;
+ float f;
+
+ s = 0;
+ FOR_EACH_KH_KEY(key)
+ {
+ if(key.owner)
+ f = key.team;
+ else
+ f = 30;
+ s |= pow(32, key.count) * f;
+ }
+
+ FOR_EACH_CLIENT(player)
+ {
+ player.kh_state = s;
+ }
+
+ FOR_EACH_KH_KEY(key)
+ {
+ if(key.owner)
+ key.owner.kh_state |= pow(32, key.count) * 31;
+ }
+ //print(ftos((nextent(world)).kh_state), "\n");
+}
+
+
+
+
+var kh_Think_t kh_Controller_Thinkfunc;
+void kh_Controller_SetThink(float t, string msg, 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_Waitmsg = strzone(msg);
+ if(t == 0)
+ kh_controller.nextthink = time; // force
+}
+
+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)
+ centerprint_atprio(e, CENTERPRIO_SPAM, s);
+ }
+ self.cnt -= 1;
+ }
+ else if(self.cnt == 0)
+ {
+ self.cnt -= 1;
+ kh_Controller_Thinkfunc();
+ }
+ self.nextthink = time + 1;
+}
+
+// frags f: take from cvar * f
+// frags 0: no frags
+void kh_Scores_Event(entity player, entity key, string what, float frags_player, float frags_owner) // update the score when a key is captured
+{
+ string s;
+ if(intermission_running)
+ return;
+
+ if(frags_player)
+ UpdateFrags(player, frags_player);
+
+ if(key && key.owner && frags_owner)
+ UpdateFrags(key.owner, frags_owner);
+
+ if(!cvar("sv_eventlog")) //output extra info to the console or text file
+ return;
+
+ s = strcat(":keyhunt:", what, ":", ftos(player.playerid), ":", ftos(frags_player));
+
+ if(key && key.owner)
+ s = strcat(s, ":", ftos(key.owner.playerid));
+ else
+ s = strcat(s, ":0");
+
+ s = strcat(s, ":", ftos(frags_owner), ":");
+
+ if(key)
+ s = strcat(s, key.netname);
+
+ GameLogEcho(s);
+}
+
+vector kh_AttachedOrigin(entity e) // runs when a team captures the flag, it can run 2 or 3 times.
+{
+ if(e.tag_entity)
+ {
+ makevectors(e.tag_entity.angles);
+ return e.tag_entity.origin + e.origin_x * v_forward - e.origin_y * v_right + e.origin_z * v_up;
+ }
+ else
+ return e.origin;
+}
+
+void kh_Key_Attach(entity key) // runs when a player picks up a key and several times when a key is assigned to a player at the start of a round
+{
+#ifdef KH_PLAYER_USE_ATTACHMENT
+ entity first;
+ first = key.owner.kh_next;
+ if(key == first)
+ {
+ setattachment(key, key.owner, KH_PLAYER_ATTACHMENT_BONE);
+ if(key.kh_next)
+ {
+ setattachment(key.kh_next, key, "");
+ setorigin(key, key.kh_next.origin - 0.5 * KH_PLAYER_ATTACHMENT_DIST);
+ setorigin(key.kh_next, KH_PLAYER_ATTACHMENT_DIST_ROTATED);
+ key.kh_next.angles = '0 0 0';
+ }
+ else
+ setorigin(key, KH_PLAYER_ATTACHMENT);
+ key.angles = KH_PLAYER_ATTACHMENT_ANGLES;
+ }
+ else
+ {
+ setattachment(key, key.kh_prev, "");
+ if(key.kh_next)
+ setattachment(key.kh_next, key, "");
+ setorigin(key, KH_PLAYER_ATTACHMENT_DIST_ROTATED);
+ setorigin(first, first.origin - 0.5 * KH_PLAYER_ATTACHMENT_DIST);
+ key.angles = '0 0 0';
+ }
+#else
+ setattachment(key, key.owner, "");
+ setorigin(key, '0 0 1' * KH_KEY_ZSHIFT); // fixing x, y in think
+ key.angles_y -= key.owner.angles_y;
+#endif
+ key.flags = 0;
+ key.solid = SOLID_NOT;
+ key.movetype = MOVETYPE_NONE;
+ key.team = key.owner.team;
+ key.nextthink = time;
+ key.damageforcescale = 0;
+ key.takedamage = DAMAGE_NO;
+ key.modelindex = kh_key_carried;
+}
+
+void kh_Key_Detach(entity key) // runs every time a key is dropped or lost. Runs several times times when all the keys are captured
+{
+#ifdef KH_PLAYER_USE_ATTACHMENT
+ entity first;
+ first = key.owner.kh_next;
+ if(key == first)
+ {
+ if(key.kh_next)
+ {
+ setattachment(key.kh_next, key.owner, KH_PLAYER_ATTACHMENT_BONE);
+ setorigin(key.kh_next, key.origin + 0.5 * KH_PLAYER_ATTACHMENT_DIST);
+ key.kh_next.angles = KH_PLAYER_ATTACHMENT_ANGLES;
+ }
+ }
+ else
+ {
+ if(key.kh_next)
+ setattachment(key.kh_next, key.kh_prev, "");
+ setorigin(first, first.origin + 0.5 * KH_PLAYER_ATTACHMENT_DIST);
+ }
+ // in any case:
+ setattachment(key, world, "");
+ setorigin(key, key.owner.origin + '0 0 1' * (PL_MIN_z - KH_KEY_MIN_z));
+ key.angles = key.owner.angles;
+#else
+ setorigin(key, key.owner.origin + key.origin_z * '0 0 1');
+ setattachment(key, world, "");
+ key.angles_y += key.owner.angles_y;
+#endif
+ key.flags = FL_ITEM;
+ key.solid = SOLID_TRIGGER;
+ key.movetype = MOVETYPE_TOSS;
+ key.pain_finished = time + cvar("g_balance_keyhunt_delay_return");
+ key.damageforcescale = cvar("g_balance_keyhunt_damageforcescale");
+ key.takedamage = DAMAGE_YES;
+ // let key.team stay
+ key.modelindex = kh_key_dropped;
+ key.kh_previous_owner = key.owner;
+ key.kh_previous_owner_playerid = key.owner.playerid;
+}
+
+void kh_Key_AssignTo(entity key, entity player) // runs every time a key is picked up or assigned. Runs prior to kh_key_attach
+{
+ entity k;
+ float ownerteam0, ownerteam;
+ if(key.owner == player)
+ return;
+
+ ownerteam0 = kh_Key_AllOwnedByWhichTeam();
+
+ if(key.owner)
+ {
+ kh_Key_Detach(key);
+
+ // remove from linked list
+ if(key.kh_next)
+ key.kh_next.kh_prev = key.kh_prev;
+ key.kh_prev.kh_next = key.kh_next;
+ key.kh_next = world;
+ key.kh_prev = world;
+
+ if(key.owner.kh_next == world)
+ {
+ // No longer a key carrier
+ if(!kh_no_radar_circles)
+ WaypointSprite_Ping(key.owner.waypointsprite_attachedforcarrier);
+ WaypointSprite_DetachCarrier(key.owner);
+ }
+ }
+
+ key.owner = player;
+
+ if(player)
+ {
+ // insert into linked list
+ key.kh_next = player.kh_next;
+ key.kh_prev = player;
+ player.kh_next = key;
+ if(key.kh_next)
+ key.kh_next.kh_prev = key;
+
+ float i;
+ i = test[key.owner.playerid];
+ if(key.netname == "^1red key")
+ i += 1;
+ if(key.netname == "^4blue key")
+ i += 2;
+ if(key.netname == "^3yellow key")
+ i += 4;
+ if(key.netname == "^6pink key")
+ i += 8;
+ test[key.owner.playerid] = i;
+
+ kh_Key_Attach(key);
+
+ if(key.kh_next == world)
+ {
+ // player is now a key carrier
+ WaypointSprite_AttachCarrier("", player);
+ 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)
+ WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-red", "keycarrier-friend", "keycarrier-red");
+ else if(player.team == COLOR_TEAM2)
+ WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-blue", "keycarrier-friend", "keycarrier-blue");
+ else if(player.team == COLOR_TEAM3)
+ WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-yellow", "keycarrier-friend", "keycarrier-yellow");
+ else if(player.team == COLOR_TEAM4)
+ WaypointSprite_UpdateSprites(player.waypointsprite_attachedforcarrier, "keycarrier-pink", "keycarrier-friend", "keycarrier-pink");
+ WaypointSprite_UpdateTeamRadar(player.waypointsprite_attachedforcarrier, RADARICON_FLAGCARRIER, colormapPaletteColor(player.team - 1, 0));
+ if(!kh_no_radar_circles)
+ WaypointSprite_Ping(player.waypointsprite_attachedforcarrier);
+ }
+ }
+
+ // moved that here, also update if there's no player
+ kh_update_state();
+
+ key.pusher = world;
+
+ ownerteam = kh_Key_AllOwnedByWhichTeam();
+ if(ownerteam != ownerteam0)
+ {
+ if(ownerteam != -1)
+ {
+ kh_interferemsg_time = time + 0.2;
+ kh_interferemsg_team = player.team;
+
+ // audit all key carrier sprites, update them to RUN HERE
+ FOR_EACH_KH_KEY(k)
+ {
+ if(k.owner)
+ WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, k.owner.waypointsprite_attachedforcarrier.model1, "keycarrier-finish", k.owner.waypointsprite_attachedforcarrier.model3);
+ }
+ }
+ else
+ {
+ kh_interferemsg_time = 0;
+
+ // audit all key carrier sprites, update them to RUN HERE
+ FOR_EACH_KH_KEY(k)
+ {
+ if(k.owner)
+ WaypointSprite_UpdateSprites(k.owner.waypointsprite_attachedforcarrier, k.owner.waypointsprite_attachedforcarrier.model1, "keycarrier-friend", k.owner.waypointsprite_attachedforcarrier.model3);
+ }
+ }
+ }
+}
+
+void kh_Key_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+ if(self.owner)
+ return;
+ if(vlen(force) <= 0)
+ return;
+ if(time > self.pushltime)
+ if(attacker.classname == "player")
+ self.team = attacker.team;
+}
+
+void kh_Key_Collect(entity key, entity player) //a player picks up a dropped key
+{
+ sound(player, CHAN_AUTO, kh_sound_collect, VOL_BASE, ATTN_NORM);
+
+ if(key.kh_dropperteam != player.team)
+ {
+ kh_Scores_Event(player, key, "collect", cvar("g_balance_keyhunt_score_collect"), 0);
+ PlayerScore_Add(player, SP_KH_PICKUPS, 1);
+ }
+ key.kh_dropperteam = 0;
+ bprint(player.netname, "^7 picked up the ", key.netname, "\n");
+
+ kh_Key_AssignTo(key, player); // this also updates .kh_state
+}
+
+void kh_Key_Touch() // runs many, many times when a key has been dropped and can be picked up
+{
+ if(intermission_running)
+ return;
+
+ if(self.owner) // already carried
+ return;
+ if(other.classname != "player")
+ return;
+ if(other.deadflag != DEAD_NO)
+ return;
+ if(other == self.enemy)
+ if(time < self.kh_droptime + cvar("g_balance_keyhunt_delay_collect"))
+ return; // you just dropped it!
+ kh_Key_Collect(self, other);
+}
+
+void kh_Key_Remove(entity key) // runs after when all the keys have been collected or when a key has been dropped for more than X seconds
+{
+ entity o;
+ o = key.owner;
+ kh_Key_AssignTo(key, world);
+ if(o) // it was attached
+ WaypointSprite_Kill(key.waypointsprite_attachedforcarrier);
+ else // it was dropped
+ WaypointSprite_DetachCarrier(key);
+
+ // remove key from key list
+ if (kh_worldkeylist == key)
+ kh_worldkeylist = kh_worldkeylist.kh_worldkeynext;
+ else
+ {
+ o = kh_worldkeylist;
+ while (o)
+ {
+ if (o.kh_worldkeynext == key)
+ {
+ o.kh_worldkeynext = o.kh_worldkeynext.kh_worldkeynext;
+ break;
+ }
+ o = o.kh_worldkeynext;
+ }
+ }
+
+ remove(key);
+
+ kh_update_state();
+}
+
+void kh_FinishRound() // runs when a team captures the keys
+{
+ // prepare next round
+ kh_interferemsg_time = 0;
+ entity key;
+
+ kh_no_radar_circles = TRUE;
+ FOR_EACH_KH_KEY(key)
+ kh_Key_Remove(key);
+ kh_no_radar_circles = FALSE;
+
+ kh_Controller_SetThink(cvar("g_balance_keyhunt_delay_round"), "Round starts in ", kh_StartRound);
+}
+
+void kh_WinnerTeam(float teem) // runs when a team wins
+{
+ // all key carriers get some points
+ vector firstorigin, lastorigin, midpoint;
+ float first;
+ entity key;
+ float score;
+ score = (kh_teams - 1) * cvar("g_balance_keyhunt_score_capture");
+ DistributeEvenly_Init(score, kh_teams);
+ // twice the score for 3 team games, three times the score for 4 team games!
+ // note: for a win by destroying the key, this should NOT be applied
+ FOR_EACH_KH_KEY(key)
+ {
+ float f;
+ f = DistributeEvenly_Get(1);
+ kh_Scores_Event(key.owner, key, "capture", f, 0);
+ PlayerTeamScore_Add(key.owner, SP_KH_CAPS, ST_KH_CAPS, 1);
+ }
+
+ first = TRUE;
+ FOR_EACH_KH_KEY(key)
+ if(key.owner.kh_next == key)
+ {
+ if(!first)
+ bprint("^7, ");
+ bprint(key.owner.netname);
+ first = FALSE;
+ }
+ bprint("^7 captured the keys for the ", ColoredTeamName(teem), "\n");
+
+ first = TRUE;
+ midpoint = '0 0 0';
+ FOR_EACH_KH_KEY(key)
+ {
+ vector thisorigin;
+
+ thisorigin = kh_AttachedOrigin(key);
+ //dprint("Key origin: ", vtos(thisorigin), "\n");
+ midpoint += thisorigin;
+
+ if(!first)
+ te_lightning2(world, lastorigin, thisorigin);
+ lastorigin = thisorigin;
+ if(first)
+ firstorigin = thisorigin;
+ first = FALSE;
+ }
+ if(kh_teams > 2)
+ {
+ 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
+
+ play2all(kh_sound_capture);
+ kh_FinishRound();
+}
+
+void kh_LoserTeam(float teem, entity lostkey) // runs when a player pushes a flag carrier off the map
+{
+ entity player, key, attacker;
+ float players;
+ float keys;
+ float f;
+
+ attacker = world;
+ if(lostkey.pusher)
+ if(lostkey.pusher.team != teem)
+ if(lostkey.pusher.classname == "player")
+ attacker = lostkey.pusher;
+
+ players = keys = 0;
+
+ if(attacker)
+ {
+ if(lostkey.kh_previous_owner)
+ kh_Scores_Event(lostkey.kh_previous_owner, world, "pushed", 0, -cvar("g_balance_keyhunt_score_push"));
+ // don't actually GIVE him the -nn points, just log
+ kh_Scores_Event(attacker, world, "push", cvar("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");
+ }
+ else
+ {
+ float of, fragsleft, i, j, thisteam;
+ of = cvar("g_balance_keyhunt_score_destroyed_ownfactor");
+
+ FOR_EACH_PLAYER(player)
+ if(player.team != teem)
+ ++players;
+
+ FOR_EACH_KH_KEY(key)
+ if(key.owner && key.team != teem)
+ ++keys;
+
+ if(lostkey.kh_previous_owner)
+ kh_Scores_Event(lostkey.kh_previous_owner, world, "destroyed", 0, -cvar("g_balance_keyhunt_score_destroyed"));
+ // don't actually GIVE him the -nn points, just log
+
+ if(lostkey.kh_previous_owner.playerid == lostkey.kh_previous_owner_playerid)
+ PlayerScore_Add(lostkey.kh_previous_owner, SP_KH_DESTROYS, 1);
+
+ DistributeEvenly_Init(cvar("g_balance_keyhunt_score_destroyed"), keys * of + players);
+
+ FOR_EACH_KH_KEY(key)
+ if(key.owner && key.team != teem)
+ {
+ f = DistributeEvenly_Get(of);
+ kh_Scores_Event(key.owner, world, "destroyed_holdingkey", f, 0);
+ }
+
+ fragsleft = DistributeEvenly_Get(players);
+
+ // Now distribute these among all other teams...
+ j = kh_teams - 1;
+ for(i = 0; i < kh_teams; ++i)
+ {
+ thisteam = kh_Team_ByID(i);
+ if(thisteam == teem) // bad boy, no cookie - this WILL happen
+ continue;
+
+ players = 0;
+ FOR_EACH_PLAYER(player)
+ if(player.team == thisteam)
+ ++players;
+
+ DistributeEvenly_Init(fragsleft, j);
+ fragsleft = DistributeEvenly_Get(j - 1);
+ DistributeEvenly_Init(DistributeEvenly_Get(1), players);
+
+ FOR_EACH_PLAYER(player)
+ if(player.team == thisteam)
+ {
+ f = DistributeEvenly_Get(1);
+ kh_Scores_Event(player, world, "destroyed", f, 0);
+ }
+
+ --j;
+ }
+
+ bprint("The ", ColoredTeamName(teem), "^7 could not take care of the ", lostkey.netname, "\n");
+ }
+ play2all(kh_sound_destroy);
+ te_tarexplosion(lostkey.origin);
+
+ kh_FinishRound();
+}
+
+void kh_Key_Think() // runs all the time
+{
+ entity head;
+ //entity player; // needed by FOR_EACH_PLAYER
+
+ if(intermission_running)
+ return;
+
+#ifdef KH_KEY_ATTACHMENT_DEBUG
+ if(self.kh_prev == self.owner)
+ {
+ if(cvar_string("_angles") != "")
+ {
+ self.angles = stov(cvar_string("_angles"));
+ setorigin(self, stov(cvar_string("_origin")));
+ }
+ }
+#endif
+
+ if(self.owner)
+ {
+#ifndef KH_PLAYER_USE_ATTACHMENT
+ makevectors('0 1 0' * (self.cnt + mod(time, 360) * KH_KEY_XYSPEED));
+ setorigin(self, v_forward * KH_KEY_XYDIST + '0 0 1' * self.origin_z);
+#endif
+
+ if(self.owner.BUTTON_USE)
+ if(time >= self.owner.kh_droptime + cvar("g_balance_keyhunt_delay_drop"))
+ {
+ self.owner.kh_droptime = time;
+ self.kh_droptime = time; // prevent collecting this one for some time
+ self.enemy = self.owner;
+ self.pusher = world;
+ kh_Scores_Event(self.owner, self, "dropkey", 0, 0);
+ bprint(self.owner.netname, "^7 dropped the ", self.netname, "\n");
+ sound(self.owner, CHAN_AUTO, kh_sound_drop, VOL_BASE, ATTN_NORM);
+ makevectors(self.owner.v_angle);
+ self.velocity = W_CalculateProjectileVelocity(self.owner.velocity, cvar("g_balance_keyhunt_throwvelocity") * v_forward);
+ kh_Key_AssignTo(self, world);
+ self.pushltime = time + cvar("g_balance_keyhunt_protecttime");
+ self.kh_dropperteam = self.team;
+ }
+ }
+
+ // if in nodrop or time over, end the round
+ if(!self.owner)
+ if(time > self.pain_finished)
+ kh_LoserTeam(self.team, self);
+
+ if(self.owner)
+ if(kh_Key_AllOwnedByWhichTeam() != -1)
+ {
+ if(self.siren_time < time)
+ {
+ sound(self.owner, CHAN_AUTO, kh_sound_alarm, VOL_BASE, ATTN_NORM); // play a simple alarm
+ self.siren_time = time + 2.5; // repeat every 2.5 seconds
+ }
+
+ entity key;
+ vector p;
+ p = self.owner.origin;
+ FOR_EACH_KH_KEY(key)
+ if(vlen(key.owner.origin - p) > cvar("g_balance_keyhunt_maxdist"))
+ goto not_winning;
+ kh_WinnerTeam(self.team);
+:not_winning
+ }
+
+ if(kh_interferemsg_time && time > kh_interferemsg_time)
+ {
+ kh_interferemsg_time = 0;
+ FOR_EACH_PLAYER(head)
+ {
+ if(head.team == kh_interferemsg_team)
+ if(head.kh_next)
+ centerprint(head, "All keys are in your team's hands!\n\nMeet the other key carriers ^1NOW^7!");
+ else
+ centerprint(head, "All keys are in your team's hands!\n\nHelp the key carriers to meet!");
+ else
+ centerprint(head, strcat("All keys are in the ", ColoredTeamName(kh_interferemsg_team), "^7's hands!\n\nInterfere ^1NOW^7!"));
+ }
+ }
+
+ self.nextthink = time + 0.05;
+}
+
+void key_reset()
+{
+ kh_Key_AssignTo(self, world);
+ kh_Key_Remove(self);
+}
+
+string STR_ITEM_KH_KEY = "item_kh_key";
+void kh_Key_Spawn(entity initial_owner, float angle, float i) // runs every time a new flag is created, ie after all the keys have been collected
+{
+ entity key;
+ key = spawn();
+ key.count = i;
+ key.classname = STR_ITEM_KH_KEY;
+ key.touch = kh_Key_Touch;
+ key.think = kh_Key_Think;
+ key.nextthink = time;
+ key.items = IT_KEY1 | IT_KEY2;
+ key.cnt = angle;
+ key.angles = '0 360 0' * random();
+ key.event_damage = kh_Key_Damage;
+ key.takedamage = DAMAGE_YES;
+ key.modelindex = kh_key_dropped;
+ key.model = "key";
+ key.kh_dropperteam = 0;
+ key.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP;
+ setsize(key, KH_KEY_MIN, KH_KEY_MAX);
+ key.colormod = TeamColor(initial_owner.team) * KH_KEY_BRIGHTNESS;
+ key.reset = key_reset;
+
+ switch(initial_owner.team)
+ {
+ case COLOR_TEAM1:
+ key.netname = "^1red key";
+ break;
+ case COLOR_TEAM2:
+ key.netname = "^4blue key";
+ break;
+ case COLOR_TEAM3:
+ key.netname = "^3yellow key";
+ break;
+ case COLOR_TEAM4:
+ key.netname = "^6pink key";
+ break;
+ default:
+ key.netname = "NETGIER key";
+ break;
+ }
+
+ // link into key list
+ 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
+
+ WaypointSprite_Spawn("key-dropped", 0, 0, key, '0 0 1' * KH_KEY_WP_ZSHIFT, world, key.team, key, waypointsprite_attachedforcarrier, FALSE);
+ key.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = kh_Key_waypointsprite_visible_for_player;
+ WaypointSprite_UpdateTeamRadar(key.waypointsprite_attachedforcarrier, RADARICON_FLAG, '0 1 1');
+
+ kh_Key_AssignTo(key, initial_owner);
+}
+
+// -1 when no team completely owns all keys yet
+float kh_Key_AllOwnedByWhichTeam() // constantly called. check to see if all the keys are owned by the same team
+{
+ entity key;
+ float teem;
+ float keys;
+
+ teem = -1;
+ keys = kh_teams;
+ FOR_EACH_KH_KEY(key)
+ {
+ if(!key.owner)
+ return -1;
+ if(teem == -1)
+ teem = key.team;
+ else if(teem != key.team)
+ return -1;
+ --keys;
+ }
+ if(keys != 0)
+ return -1;
+ return teem;
+}
+
+void kh_Key_DropAll(entity player, float suicide) // runs whenever a player dies
+{
+ entity key;
+ entity mypusher;
+ if(player.kh_next)
+ {
+ mypusher = world;
+ if(player.pusher)
+ if(time < player.pushltime)
+ mypusher = player.pusher;
+ while((key = player.kh_next))
+ {
+ 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");
+ kh_Key_AssignTo(key, world);
+ makevectors('-1 0 0' * (45 + 45 * random()) + '0 360 0' * random());
+ key.velocity = W_CalculateProjectileVelocity(player.velocity, cvar("g_balance_keyhunt_dropvelocity") * v_forward);
+ key.pusher = mypusher;
+ key.pushltime = time + cvar("g_balance_keyhunt_protecttime");
+ if(suicide)
+ key.kh_dropperteam = player.team;
+ }
+ sound(player, CHAN_AUTO, kh_sound_drop, VOL_BASE, ATTN_NORM);
+ }
+}
+
+string kh_CheckEnoughPlayers() // checks enough player are present, runs after every completed round
+{
+ float i, players, teem;
+ entity player;
+ string result;
+ result = "";
+
+ // find a random player per team
+ for(i = 0; i < kh_teams; ++i)
+ {
+ teem = kh_Team_ByID(i);
+ players = 0;
+ FOR_EACH_PLAYER(player)
+ if(player.deadflag == DEAD_NO)
+ if(!player.BUTTON_CHAT)
+ if(player.team == teem)
+ ++players;
+ if(players == 0)
+ {
+ if(result != "")
+ result = strcat(result, ", ");
+ result = strcat(result, ColoredTeamName(teem));
+ }
+ }
+ return result;
+}
+
+void kh_WaitForPlayers() // delay start of the round until enough players are present
+{
+ string teams_missing;
+
+ if(time < game_starttime)
+ {
+ kh_Controller_SetThink(game_starttime - time + 0.1, "", kh_WaitForPlayers);
+ return;
+ }
+
+ teams_missing = kh_CheckEnoughPlayers();
+ if(teams_missing == "")
+ kh_Controller_SetThink(cvar("g_balance_keyhunt_delay_round"), "Round starts in ", kh_StartRound);
+ else
+ kh_Controller_SetThink(1, strcat("Waiting for players to join...\n\nNeed active players for: ", teams_missing), kh_WaitForPlayers);
+}
+
+void kh_EnableTrackingDevice() // runs after each round
+{
+ entity player;
+
+ FOR_EACH_PLAYER(player)
+ if(clienttype(player) == CLIENTTYPE_REAL)
+ centerprint_expire(player, CENTERPRIO_SPAM);
+
+ 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(game_starttime - time + 0.1, "", kh_WaitForPlayers);
+ return;
+ }
+
+ teams_missing = kh_CheckEnoughPlayers();
+ if(teams_missing != "")
+ {
+ kh_Controller_SetThink(1, strcat("Waiting for players to join...\n\nNeed active players for: ", teams_missing), kh_WaitForPlayers);
+ return;
+ }
+
+ FOR_EACH_PLAYER(player)
+ if(clienttype(player) == CLIENTTYPE_REAL)
+ centerprint_expire(player, CENTERPRIO_SPAM);
+
+ for(i = 0; i < kh_teams; ++i)
+ {
+ teem = kh_Team_ByID(i);
+ players = 0;
+ entity my_player;
+ FOR_EACH_PLAYER(player)
+ if(player.deadflag == DEAD_NO)
+ if(!player.BUTTON_CHAT)
+ if(player.team == teem)
+ {
+ ++players;
+ if(random() * players <= 1)
+ my_player = player;
+ }
+ kh_Key_Spawn(my_player, 360 * i / kh_teams, i);
+ }
+
+ kh_tracking_enabled = FALSE;
+ kh_Controller_SetThink(cvar("g_balance_keyhunt_delay_tracking"), "Scanning frequency range...", kh_EnableTrackingDevice);
+}
+
+float kh_HandleFrags(entity attacker, entity targ, float f) // adds to the player score
+{
+ if(attacker == targ)
+ return f;
+
+ if(targ.kh_next)
+ {
+ if(attacker.team == targ.team)
+ {
+ entity k;
+ float nk;
+ nk = 0;
+ for(k = targ.kh_next; k != world; k = k.kh_next)
+ ++nk;
+ kh_Scores_Event(attacker, targ.kh_next, "carrierfrag", -nk * cvar("g_balance_keyhunt_score_collect"), 0);
+ }
+ else
+ {
+ kh_Scores_Event(attacker, targ.kh_next, "carrierfrag", cvar("g_balance_keyhunt_score_carrierfrag")-1, 0);
+ PlayerScore_Add(attacker, SP_KH_KCKILLS, 1);
+ // the frag gets added later
+ }
+ }
+
+ return f;
+}
+
+void kh_Initialize() // sets up th KH environment
+{
+ precache_sound(kh_sound_capture);
+ precache_sound(kh_sound_destroy);
+ precache_sound(kh_sound_drop);
+ precache_sound(kh_sound_collect);
+ precache_sound(kh_sound_alarm); // the new siren
+
+#ifdef KH_PLAYER_USE_CARRIEDMODEL
+ precache_model("models/keyhunt/key-carried.md3");
+#endif
+ precache_model("models/keyhunt/key.md3");
+
+ // setup variables
+ kh_teams = cvar("g_keyhunt_teams_override");
+ if(kh_teams < 2)
+ kh_teams = cvar("g_keyhunt_teams");
+ kh_teams = bound(2, kh_teams, 4);
+
+ // make a KH entity for controlling the game
+ kh_controller = spawn();
+ kh_controller.think = kh_Controller_Think;
+ kh_Controller_SetThink(0, "", kh_WaitForPlayers);
+
+ setmodel(kh_controller, "models/keyhunt/key.md3");
+ kh_key_dropped = kh_controller.modelindex;
+ /*
+ dprint(vtos(kh_controller.mins));
+ dprint(vtos(kh_controller.maxs));
+ dprint("\n");
+ */
+#ifdef KH_PLAYER_USE_CARRIEDMODEL
+ setmodel(kh_controller, "models/keyhunt/key-carried.md3");
+ kh_key_carried = kh_controller.modelindex;
+#else
+ kh_key_carried = kh_key_dropped;
+#endif
+
+ kh_controller.model = "";
+ kh_controller.modelindex = 0;
+
+ addstat(STAT_KH_KEYS, AS_INT, kh_state);
+
+ ScoreRules_kh(kh_teams);
+}
+
+void kh_finalize()
+{
+ // to be called before intermission
+ kh_FinishRound();
+ remove(kh_controller);
+ kh_controller = world;
+}
+
+// register this as a mutator
+
+MUTATOR_HOOKFUNCTION(kh_Key_DropAll)
+{
+ kh_Key_DropAll(self, TRUE);
+ return 0;
+}
+
+MUTATOR_HOOKFUNCTION(kh_PlayerDies)
+{
+ if(self == other)
+ kh_Key_DropAll(self, TRUE);
+ else if(other.classname == "player" || other.classname == "gib")
+ kh_Key_DropAll(self, FALSE);
+ else
+ kh_Key_DropAll(self, TRUE);
+ return 0;
+}
+
+MUTATOR_HOOKFUNCTION(kh_GiveFragsForKill)
+{
+ frag_score = kh_HandleFrags(frag_attacker, frag_target, frag_score);
+ return 0;
+}
+
+MUTATOR_HOOKFUNCTION(kh_finalize)
+{
+ kh_finalize();
+ return 0;
+}
+
+MUTATOR_HOOKFUNCTION(kh_GetTeamCount)
+{
+ ret_float = kh_teams;
+ return 0;
+}
+
+MUTATOR_HOOKFUNCTION(kh_SpectateCopy)
+{
+ self.kh_state = other.kh_state;
+ return 0;
+}
+
+MUTATOR_DEFINITION(gamemode_keyhunt)
+{
+ MUTATOR_HOOK(MakePlayerObserver, kh_Key_DropAll, CBC_ORDER_ANY);
+ MUTATOR_HOOK(ClientDisconnect, kh_Key_DropAll, CBC_ORDER_ANY);
+ MUTATOR_HOOK(PlayerDies, kh_PlayerDies, CBC_ORDER_ANY);
+ MUTATOR_HOOK(GiveFragsForKill, kh_GiveFragsForKill, CBC_ORDER_FIRST);
+ MUTATOR_HOOK(MatchEnd, kh_finalize, CBC_ORDER_ANY);
+ MUTATOR_HOOK(GetTeamCount, kh_GetTeamCount, CBC_ORDER_EXCLUSIVE);
+ MUTATOR_HOOK(SpectateCopy, kh_SpectateCopy, 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_keyhunt = 1;
+ kh_Initialize();
+ }
+
+ MUTATOR_ONREMOVE
+ {
+ g_keyhunt = 0;
+ error("This is a game type and it cannot be removed at runtime.");
+ }
+
+ return 0;
+}
--- /dev/null
+// ALL OF THESE should be removed in the future, as other code should not have
+// to care
+
+// used by bots:
+float kh_tracking_enabled;
+.entity kh_next;
+float kh_Key_AllOwnedByWhichTeam();
+
+// used by arena.qc ready-restart:
+typedef void(void) kh_Think_t;
+void kh_StartRound();
+void kh_Controller_SetThink(float t, string msg, kh_Think_t func);
--- /dev/null
+
+.float cvar_cl_dodging_timeout;
+
+
+// these are used to store the last key press time for each of the keys..
+.float last_FORWARD_KEY_time;
+.float last_BACKWARD_KEY_time;
+.float last_LEFT_KEY_time;
+.float last_RIGHT_KEY_time;
+
+// these store the movement direction at the time of the dodge action happening.
+.float dodging_direction_x;
+.float dodging_direction_y;
+
+// this indicates the last time a dodge was executed. used to check if another one is allowed
+// and to ramp up the dodge acceleration in the physics hook.
+.float last_dodging_time;
+
+// set to 1 to indicate dodging has started.. reset by physics hook after dodge has been done..
+.float dodging_action;
+
+// This is the velocity gain to be added over the ramp time.
+// It will decrease from frame to frame during dodging_action = 1
+// until it's 0.
+.float dodging_velocity_gain;
+
+// 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;
+}
+
+MUTATOR_HOOKFUNCTION(dodging_PlayerPhysics) {
+ // print("dodging_PlayerPhysics\n");
+
+ float common_factor;
+ float new_velocity_gain;
+ float velocity_difference;
+ float clean_up_and_do_nothing;
+
+ new_velocity_gain = 0;
+ clean_up_and_do_nothing = 0;
+
+ if (g_dodging == 0)
+ clean_up_and_do_nothing = 1;
+
+ // when swimming, no dodging allowed..
+ if (self.waterlevel >= WATERLEVEL_SWIMMING)
+ clean_up_and_do_nothing = 1;
+
+ if (clean_up_and_do_nothing != 0) {
+ self.dodging_action = 0;
+ self.dodging_direction_x = 0;
+ self.dodging_direction_y = 0;
+ return 0;
+ }
+
+ // make sure v_up, v_right and v_forward are sane
+ makevectors(self.angles);
+
+ // if we have e.g. 0.5 sec ramptime and a frametime of 0.25, then the ramp code
+ // will be called ramp_time/frametime times = 2 times. so, we need to
+ // add 0.5 * the total speed each frame until the dodge action is done..
+ common_factor = sys_frametime / cvar("sv_dodging_ramp_time");
+
+ // if ramp time is smaller than frametime we get problems ;D
+ if (common_factor > 1)
+ common_factor = 1;
+
+ new_velocity_gain = self.dodging_velocity_gain - (common_factor * cvar("sv_dodging_horiz_speed"));
+ if (new_velocity_gain < 0)
+ new_velocity_gain = 0;
+
+ velocity_difference = self.dodging_velocity_gain - new_velocity_gain;
+
+ // ramp up dodging speed by adding some velocity each frame.. TODO: do it! :D
+ if (self.dodging_action == 1) {
+ //disable jump key during dodge accel phase
+ if (self.movement_z > 0) self.movement_z = 0;
+
+ self.velocity =
+ self.velocity
+ + ((self.dodging_direction_y * velocity_difference) * v_right)
+ + ((self.dodging_direction_x * velocity_difference) * v_forward);
+
+ self.dodging_velocity_gain = self.dodging_velocity_gain - velocity_difference;
+ }
+
+ // the up part of the dodge is a single shot action
+ if (self.dodging_single_action == 1) {
+ self.flags &~= FL_ONGROUND;
+
+ self.velocity =
+ self.velocity
+ + (cvar("sv_dodging_up_speed") * v_up);
+
+ if (cvar("sv_dodging_sound") == 1)
+ PlayerSound(playersound_jump, CHAN_PLAYER, VOICETYPE_PLAYERSOUND);
+
+ setanim(self, self.anim_jump, TRUE, FALSE, TRUE);
+
+ self.dodging_single_action = 0;
+ }
+
+ // are we done with the dodging ramp yet?
+ if((self.dodging_action == 1) && ((time - self.last_dodging_time) > cvar("sv_dodging_ramp_time")))
+ {
+ // reset state so next dodge can be done correctly
+ self.dodging_action = 0;
+ self.dodging_direction_x = 0;
+ self.dodging_direction_y = 0;
+ }
+
+ return 0;
+}
+
+
+// returns 1 if the player is close to a wall
+float check_close_to_wall(float threshold) {
+ if (cvar("sv_dodging_wall_dodging") == 0)
+ return 0;
+
+ vector trace_start;
+ vector trace_end;
+
+ trace_start = self.origin;
+
+ trace_end = self.origin + (1000*v_right);
+ tracebox(trace_start, self.mins, self.maxs, trace_end, TRUE, self);
+ if (trace_fraction < 1 && vlen (self.origin - trace_endpos) < threshold)
+ return 1;
+
+ trace_end = self.origin - (1000*v_right);
+ tracebox(trace_start, self.mins, self.maxs, trace_end, TRUE, self);
+ if (trace_fraction < 1 && vlen (self.origin - trace_endpos) < threshold)
+ return 1;
+
+ trace_end = self.origin + (1000*v_forward);
+ tracebox(trace_start, self.mins, self.maxs, trace_end, TRUE, self);
+ if (trace_fraction < 1 && vlen (self.origin - trace_endpos) < threshold)
+ return 1;
+
+ trace_end = self.origin - (1000*v_forward);
+ tracebox(trace_start, self.mins, self.maxs, trace_end, TRUE, self);
+ if (trace_fraction < 1 && vlen (self.origin - trace_endpos) < threshold)
+ return 1;
+
+ return 0;
+}
+
+float check_close_to_ground(float threshold) {
+ if (self.flags & FL_ONGROUND)
+ return 1;
+
+ return 0;
+}
+
+
+MUTATOR_HOOKFUNCTION(dodging_GetPressedKeys) {
+ // print("dodging_PlayerPhysics\n");
+
+ float length;
+ float tap_direction_x;
+ float tap_direction_y;
+
+ tap_direction_x = 0;
+ tap_direction_y = 0;
+
+ float dodge_detected;
+ if (g_dodging == 0)
+ return 0;
+
+ dodge_detected = 0;
+
+ // first check if the last dodge is far enough back in time so we can dodge again
+ if ((time - self.last_dodging_time) < cvar("sv_dodging_delay"))
+ return 0;
+
+ if (check_close_to_ground(cvar("sv_dodging_height_threshold")) != 1
+ && check_close_to_wall(cvar("sv_dodging_wall_distance_threshold")) != 1)
+ return 0;
+
+ if (self.movement_x > 0) {
+ // is this a state change?
+ if (!(self.pressedkeys & KEY_FORWARD)) {
+ if ((time - self.last_FORWARD_KEY_time) < self.cvar_cl_dodging_timeout) {
+ tap_direction_x = 1.0;
+ dodge_detected = 1;
+ }
+ self.last_FORWARD_KEY_time = time;
+ }
+ }
+
+ if (self.movement_x < 0) {
+ // is this a state change?
+ if (!(self.pressedkeys & KEY_BACKWARD)) {
+ tap_direction_x = -1.0;
+ if ((time - self.last_BACKWARD_KEY_time) < self.cvar_cl_dodging_timeout) {
+ dodge_detected = 1;
+ }
+ self.last_BACKWARD_KEY_time = time;
+ }
+ }
+
+ if (self.movement_y > 0) {
+ // is this a state change?
+ if (!(self.pressedkeys & KEY_RIGHT)) {
+ tap_direction_y = 1.0;
+ if ((time - self.last_RIGHT_KEY_time) < self.cvar_cl_dodging_timeout) {
+ dodge_detected = 1;
+ }
+ self.last_RIGHT_KEY_time = time;
+ }
+ }
+
+ if (self.movement_y < 0) {
+ // is this a state change?
+ if (!(self.pressedkeys & KEY_LEFT)) {
+ tap_direction_y = -1.0;
+ if ((time - self.last_LEFT_KEY_time) < self.cvar_cl_dodging_timeout) {
+ dodge_detected = 1;
+ }
+ self.last_LEFT_KEY_time = time;
+ }
+ }
+
+
+
+ if (dodge_detected == 1) {
+ self.last_dodging_time = time;
+
+ self.dodging_action = 1;
+ self.dodging_single_action = 1;
+
+ self.dodging_velocity_gain = cvar("sv_dodging_horiz_speed");
+
+ self.dodging_direction_x = tap_direction_x;
+ self.dodging_direction_y = tap_direction_y;
+
+ // normalize the dodging_direction vector.. (unlike UT99) XD
+ length = length + self.dodging_direction_x * self.dodging_direction_x;
+ length = length + self.dodging_direction_y * self.dodging_direction_y;
+ length = sqrt(length);
+
+ self.dodging_direction_x = self.dodging_direction_x * 1.0/length;
+ self.dodging_direction_y = self.dodging_direction_y * 1.0/length;
+ }
+
+ return 0;
+}
+
+MUTATOR_DEFINITION(dodging)
+{
+ // we need to be called before GetPressedKey does its thing so we can
+ // detect state changes and therefore dodging actions..
+ MUTATOR_HOOK(GetPressedKeys, dodging_GetPressedKeys, CBC_ORDER_ANY);
+
+ // in the physics hook we actually implement the dodge..
+ MUTATOR_HOOK(PlayerPhysics, dodging_PlayerPhysics, CBC_ORDER_ANY);
+
+ // get timeout information from the client, so the client can configure it..
+ MUTATOR_HOOK(GetCvars, dodging_GetCvars, CBC_ORDER_ANY);
+
+ // this just turns on the cvar.
+ MUTATOR_ONADD
+ {
+ g_dodging = 1;
+ dodging_Initialize();
+ }
+
+ // this just turns off the cvar.
+ MUTATOR_ONREMOVE
+ {
+ g_dodging = 0;
+ }
+
+ return 0;
+}
--- /dev/null
+float g_dodging;
+
--- /dev/null
+float g_nix_with_laser;
+
+float nix_weapon;
+float nix_weapon_ammo;
+float nix_nextchange;
+float nix_nextweapon;
+float nix_nextweapon_ammo;
+.float nix_lastchange_id;
+.float nix_lastinfotime;
+.float nix_nextincr;
+
+.float nix_save_cells;
+.float nix_save_shells;
+.float nix_save_nails;
+.float nix_save_rockets;
+.float nix_save_fuel;
+.float nix_save_weapons;
+
+float NIX_CanChooseWeapon(float wpn)
+{
+ entity e;
+ e = get_weaponinfo(wpn);
+ if(!e.weapons) // skip dummies
+ return FALSE;
+ if(g_weaponarena)
+ {
+ if not(g_weaponarena & e.weapons)
+ return FALSE;
+ }
+ else
+ {
+ if(wpn == WEP_LASER && g_nix_with_laser)
+ return FALSE;
+ if not(e.spawnflags & WEP_FLAG_NORMAL)
+ return FALSE;
+ }
+ return TRUE;
+}
+void NIX_ChooseNextWeapon()
+{
+ float j;
+ RandomSelection_Init();
+ for(j = WEP_FIRST; j <= WEP_LAST; ++j)
+ if(NIX_CanChooseWeapon(j))
+ RandomSelection_Add(world, j, string_null, 1, (j != nix_weapon));
+ nix_nextweapon = RandomSelection_chosen_float;
+ nix_nextweapon_ammo = W_AmmoItemCode(nix_nextweapon);
+}
+
+void NIX_GiveCurrentWeapon()
+{
+ float dt;
+
+ if(!nix_nextweapon)
+ NIX_ChooseNextWeapon();
+
+ dt = ceil(nix_nextchange - time);
+
+ if(dt <= 0)
+ {
+ nix_weapon = nix_nextweapon;
+ nix_weapon_ammo = nix_nextweapon_ammo;
+ nix_nextweapon = 0;
+ nix_nextchange = time + cvar("g_balance_nix_roundtime");
+ //weapon_action(nix_weapon, WR_PRECACHE); // forget it, too slow
+ }
+
+ if(nix_nextchange != self.nix_lastchange_id) // this shall only be called once per round!
+ {
+ self.nix_lastchange_id = nix_nextchange;
+ if (self.items & IT_UNLIMITED_WEAPON_AMMO)
+ {
+ self.ammo_shells = (nix_weapon_ammo & IT_SHELLS) ?
+ cvar("g_pickup_shells_max") : 0;
+ self.ammo_nails = (nix_weapon_ammo & IT_NAILS) ?
+ cvar("g_pickup_nails_max") : 0;
+ self.ammo_rockets = (nix_weapon_ammo & IT_ROCKETS) ?
+ cvar("g_pickup_rockets_max") : 0;
+ self.ammo_cells = (nix_weapon_ammo & IT_CELLS) ?
+ cvar("g_pickup_cells_max") : 0;
+ self.ammo_fuel = (nix_weapon_ammo & IT_FUEL) ?
+ cvar("g_pickup_fuel_max") : 0;
+ }
+ else
+ {
+ self.ammo_shells = (nix_weapon_ammo & IT_SHELLS) ?
+ cvar("g_balance_nix_ammo_shells") : 0;
+ self.ammo_nails = (nix_weapon_ammo & IT_NAILS) ?
+ cvar("g_balance_nix_ammo_nails") : 0;
+ self.ammo_rockets = (nix_weapon_ammo & IT_ROCKETS) ?
+ cvar("g_balance_nix_ammo_rockets") : 0;
+ self.ammo_cells = (nix_weapon_ammo & IT_CELLS) ?
+ cvar("g_balance_nix_ammo_cells") : 0;
+ self.ammo_fuel = (nix_weapon_ammo & IT_FUEL) ?
+ cvar("g_balance_nix_ammo_fuel") : 0;
+ }
+ self.nix_nextincr = time + cvar("g_balance_nix_incrtime");
+ if(dt >= 1 && dt <= 5)
+ self.nix_lastinfotime = -42;
+ else
+ centerprint(self, strcat("\n\n^2Active weapon: ^3", W_Name(nix_weapon)));
+ }
+ if(self.nix_lastinfotime != dt)
+ {
+ self.nix_lastinfotime = dt; // initial value 0 should count as "not seen"
+ if(dt >= 1 && dt <= 5)
+ centerprint(self, strcat("^3", ftos(dt), "^2 seconds until weapon change...\n\nNext weapon: ^3", W_Name(nix_nextweapon), "\n"));
+ }
+
+ if(!(self.items & IT_UNLIMITED_WEAPON_AMMO) && time > self.nix_nextincr)
+ {
+ if (nix_weapon_ammo & IT_SHELLS)
+ self.ammo_shells = self.ammo_shells + cvar("g_balance_nix_ammoincr_shells");
+ else if (nix_weapon_ammo & IT_NAILS)
+ self.ammo_nails = self.ammo_nails + cvar("g_balance_nix_ammoincr_nails");
+ else if (nix_weapon_ammo & IT_ROCKETS)
+ self.ammo_rockets = self.ammo_rockets + cvar("g_balance_nix_ammoincr_rockets");
+ else if (nix_weapon_ammo & IT_CELLS)
+ self.ammo_cells = self.ammo_cells + cvar("g_balance_nix_ammoincr_cells");
+ if (nix_weapon_ammo & IT_FUEL) // hook uses cells and fuel
+ self.ammo_fuel = self.ammo_fuel + cvar("g_balance_nix_ammoincr_fuel");
+ self.nix_nextincr = time + cvar("g_balance_nix_incrtime");
+ }
+
+ self.weapons = 0;
+ if(g_nix_with_laser)
+ self.weapons = self.weapons | WEPBIT_LASER;
+ self.weapons = self.weapons | W_WeaponBit(nix_weapon);
+
+ if(self.switchweapon != nix_weapon)
+ if(!client_hasweapon(self, self.switchweapon, TRUE, FALSE))
+ if(client_hasweapon(self, nix_weapon, TRUE, FALSE))
+ W_SwitchWeapon(nix_weapon);
+}
+
+void NIX_precache()
+{
+ float i;
+ for (i = WEP_FIRST; i <= WEP_LAST; ++i)
+ if (NIX_CanChooseWeapon(i))
+ weapon_action(i, WR_PRECACHE);
+}
+
+MUTATOR_HOOKFUNCTION(nix_ForbidThrowCurrentWeapon)
+{
+ return 1; // no throwing in NIX
+}
+
+MUTATOR_HOOKFUNCTION(nix_SetStartItems)
+{
+ NIX_precache();
+ // we do NOT change the start weapons any more, so we can later turn off the mutator!
+ // start_weapons = 0; // will be done later, when player spawns
+ // warmup_start_weapons = 0; // will be done later, when player spawns
+ return 0;
+}
+
+MUTATOR_HOOKFUNCTION(nix_BuildMutatorsString)
+{
+ ret_string = strcat(ret_string, ":NIX");
+ return 0;
+}
+
+MUTATOR_HOOKFUNCTION(nix_BuildMutatorsPrettyString)
+{
+ ret_string = strcat(ret_string, ", NIX");
+ return 0;
+}
+
+MUTATOR_HOOKFUNCTION(nix_FilterItem)
+{
+ switch (self.items)
+ {
+ case IT_HEALTH:
+ case IT_5HP:
+ case IT_25HP:
+ case IT_ARMOR:
+ case IT_ARMOR_SHARD:
+ if (cvar("g_nix_with_healtharmor"))
+ return 0;
+ break;
+ case IT_STRENGTH:
+ case IT_INVINCIBLE:
+ if (cvar("g_nix_with_powerups"))
+ return 0;
+ break;
+ }
+
+ return 1; // delete all other items
+}
+
+MUTATOR_HOOKFUNCTION(nix_OnEntityPreSpawn)
+{
+ if(self.classname == "target_items") // items triggers cannot work in nixnex (as they change weapons/ammo)
+ return 1;
+ return 0;
+}
+
+MUTATOR_HOOKFUNCTION(nix_PlayerPreThink)
+{
+ if(!intermission_running)
+ if(self.deadflag == DEAD_NO)
+ if(self.classname == "player")
+ NIX_GiveCurrentWeapon();
+ return 0;
+}
+
+MUTATOR_HOOKFUNCTION(nix_PlayerSpawn)
+{
+ self.nix_lastchange_id = -1;
+ NIX_GiveCurrentWeapon(); // overrides the weapons you got when spawning
+ return 0;
+}
+
+MUTATOR_DEFINITION(mutator_nix)
+{
+ entity e;
+
+ MUTATOR_HOOK(ForbidThrowCurrentWeapon, nix_ForbidThrowCurrentWeapon, CBC_ORDER_ANY);
+ MUTATOR_HOOK(SetStartItems, nix_SetStartItems, CBC_ORDER_EXCLUSIVE);
+ MUTATOR_HOOK(BuildMutatorsString, nix_BuildMutatorsString, CBC_ORDER_ANY);
+ MUTATOR_HOOK(BuildMutatorsPrettyString, nix_BuildMutatorsPrettyString, CBC_ORDER_ANY);
+ MUTATOR_HOOK(FilterItem, nix_FilterItem, CBC_ORDER_ANY);
+ MUTATOR_HOOK(OnEntityPreSpawn, nix_OnEntityPreSpawn, CBC_ORDER_ANY);
+ MUTATOR_HOOK(PlayerPreThink, nix_PlayerPreThink, CBC_ORDER_ANY);
+ MUTATOR_HOOK(PlayerSpawn, nix_PlayerSpawn, CBC_ORDER_ANY);
+
+ MUTATOR_ONADD
+ {
+ g_nix_with_laser = cvar("g_nix_with_laser");
+
+ nix_nextchange = time;
+ nix_nextweapon = 0;
+
+ NIX_precache();
+
+ FOR_EACH_PLAYER(e)
+ {
+ if(e.deadflag == DEAD_NO)
+ {
+ e.nix_save_cells = e.ammo_cells;
+ e.nix_save_shells = e.ammo_shells;
+ e.nix_save_nails = e.ammo_nails;
+ e.nix_save_rockets = e.ammo_rockets;
+ e.nix_save_fuel = e.ammo_fuel;
+ e.nix_save_weapons = e.weapons;
+ }
+ else
+ {
+ e.nix_save_cells = 0;
+ e.nix_save_shells = 0;
+ e.nix_save_nails = 0;
+ e.nix_save_rockets = 0;
+ e.nix_save_fuel = 0;
+ e.nix_save_weapons = 0;
+ }
+ }
+ }
+
+ MUTATOR_ONREMOVE
+ {
+ // as the PlayerSpawn hook will no longer run, NIX is turned off by this!
+
+ FOR_EACH_PLAYER(e) if(e.deadflag == DEAD_NO)
+ {
+ e.ammo_cells = max(start_ammo_cells, e.nix_save_cells);
+ e.ammo_shells = max(start_ammo_shells, e.nix_save_shells);
+ e.ammo_nails = max(start_ammo_nails, e.nix_save_nails);
+ e.ammo_rockets = max(start_ammo_rockets, e.nix_save_rockets);
+ e.ammo_fuel = max(start_ammo_fuel, e.nix_save_fuel);
+ e.weapons = (start_weapons | e.nix_save_weapons);
+ if(!client_hasweapon(e, e.weapon, TRUE, FALSE))
+ e.switchweapon = w_getbestweapon(self);
+ }
+ }
+
+ return 0;
+}
--- /dev/null
+MUTATOR_DECLARATION(gamemode_keyhunt);
+
+MUTATOR_DECLARATION(mutator_nix);
+
+MUTATOR_DECLARATION(dodging);
if(align)
{
- traceline(node.origin + '0 0 32',node.origin - '0 0 128',MOVE_WORLDONLY,node);
+ traceline(node.origin + '0 0 32', node.origin - '0 0 128', MOVE_WORLDONLY, node);
node.angles = vectoangles(trace_plane_normal);
node.angles_x -= 90;
}
for(i=0;i < 8; ++i)
{
t = plib_points[i];
- fc = pathlib_heuristic(t,goal) + pathlib_cost(node,t,pathlib_gridsize);
+ fc = pathlib_heuristic(t,goal) + pathlib_cost(node, t, pathlib_gridsize);
plib_fvals[i] = fc;
}
*/
}
- pathlib_makenode(node,start,bp,goal,pathlib_gridsize);
+ pathlib_makenode(node, start, bp, goal, pathlib_gridsize);
for(i = 0; i < 3; ++i)
{
- pathlib_makenode(node,start,plib_points2[i],goal,pathlib_gridsize);
+ pathlib_makenode(node, start, plib_points2[i], goal, pathlib_gridsize);
}
return pathlib_open_cnt;
float pathlib_expandnode_star(entity node, vector start, vector goal)
{
- vector point,where,f,r;
+ vector point, where, f, r;
where = node.origin;
f = PLIB_FORWARD * pathlib_gridsize;
r = PLIB_RIGHT * pathlib_gridsize;
+ if (node.pathlib_node_edgeflags == pathlib_node_edgeflag_unknown)
+ node.pathlib_node_edgeflags = tile_check_plus2(node.origin);
+
+ if(node.pathlib_node_edgeflags == pathlib_node_edgeflag_none)
+ {
+ dprint("Node at ", vtos(node.origin), " not expanable");
+ return pathlib_open_cnt;
+ }
+
// Forward
- point = where + f;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
+ if (node.pathlib_node_edgeflags & pathlib_node_edgeflag_forward)
+ {
+ point = where + f;
+ pathlib_makenode(node, start, point, goal, pathlib_movecost);
+ }
// Back
- point = where - f;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
+ if (node.pathlib_node_edgeflags & pathlib_node_edgeflag_back)
+ {
+ point = where - f;
+ pathlib_makenode(node, start, point, goal, pathlib_movecost);
+ }
// Right
- point = where + r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
+ if (node.pathlib_node_edgeflags & pathlib_node_edgeflag_right)
+ {
+ point = where + r;
+ pathlib_makenode(node, start, point, goal, pathlib_movecost);
+ }
// Left
- point = where - r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
+ if (node.pathlib_node_edgeflags & pathlib_node_edgeflag_left)
+ {
+ point = where - r;
+ pathlib_makenode(node, start, point, goal, pathlib_movecost);
+
+ }
// Forward-right
- point = where + f + r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+ if (node.pathlib_node_edgeflags & pathlib_node_edgeflag_forwardright)
+ {
+ point = where + f + r;
+ pathlib_makenode(node, start, point, goal, pathlib_movecost_diag);
+ }
// Forward-left
- point = where + f - r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+ if (node.pathlib_node_edgeflags & pathlib_node_edgeflag_forwardleft)
+ {
+ point = where + f - r;
+ pathlib_makenode(node, start, point, goal, pathlib_movecost_diag);
+
+ }
// Back-right
- point = where - f + r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+ if (node.pathlib_node_edgeflags & pathlib_node_edgeflag_backright)
+ {
+ point = where - f + r;
+ pathlib_makenode(node, start, point, goal, pathlib_movecost_diag);
+ }
// Back-left
- point = where - f - r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost_diag);
+ if (node.pathlib_node_edgeflags & pathlib_node_edgeflag_backleft)
+ {
+ point = where - f - r;
+ pathlib_makenode(node, start, point, goal, pathlib_movecost_diag);
+ }
return pathlib_open_cnt;
}
// Forward
point = where + f;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
+ pathlib_makenode(node, start, point, goal, pathlib_movecost);
// Back
point = where - f;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
+ pathlib_makenode(node, start, point, goal, pathlib_movecost);
// Right
point = where + r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
+ pathlib_makenode(node, start, point, goal, pathlib_movecost);
// Left
point = where - r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
+ pathlib_makenode(node, start, point, goal, pathlib_movecost);
f = PLIB_FORWARD * pathlib_gridsize * 0.5;
r = PLIB_RIGHT * pathlib_gridsize * 0.5;
// Forward-right
point = where + f + r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
+ pathlib_makenode(node, start, point, goal, pathlib_movecost);
// Forward-left
point = where + f - r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
+ pathlib_makenode(node, start, point, goal, pathlib_movecost);
// Back-right
point = where - f + r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
+ pathlib_makenode(node, start, point, goal, pathlib_movecost);
// Back-left
point = where - f - r;
- pathlib_makenode(node,start,point,goal,pathlib_movecost);
+ pathlib_makenode(node, start, point, goal, pathlib_movecost);
return pathlib_open_cnt;
}
node = pathlib_nodeatpoint(where);
if(node)
{
- mark_error(where,60);
+ mark_error(where, 60);
return node;
}
node.owner = openlist;
node.path_prev = parent;
- setmodel(node,"models/pathlib/square.md3");
- setsize(node,'0 0 0','0 0 0');
- node.colormod = randomvec() * 2;
- node.alpha = 0.25;
- node.scale = pathlib_gridsize / 512.001;
- //pathlib_showsquare2(node,'1 1 1',0);//(node.medium & CONTENT_EMPTY));
+ setsize(node, '0 0 0', '0 0 0');
+
setorigin(node, where);
node.medium = pointcontents(where);
-
- mark_info(where,60);
- //pathlib_showsquare(where,1,30);
-
+ pathlib_showsquare(where, 1 ,15);
++pathlib_made_cnt;
++pathlib_open_cnt;
if(inwater(parent.origin))
{
+ dprint("FromWater\n");
pathlib_expandnode = pathlib_expandnode_box;
pathlib_movenode = pathlib_swimnode;
}
{
if(inwater(to))
{
+ dprint("ToWater\n");
pathlib_expandnode = pathlib_expandnode_box;
pathlib_movenode = pathlib_walknode;
}
else
{
+ dprint("LandToLoand\n");
//if(edge_check(parent.origin))
// return 0;
node = pathlib_nodeatpoint(to);
if(node)
{
+ dprint("NodeAtPoint\n");
++pathlib_merge_cnt;
if(node.owner == openlist)
return 1;
}
- where = pathlib_movenode(parent.origin,to,0);
+ where = pathlib_movenode(parent.origin, to, 0);
+
if not(pathlib_movenode_goodnode)
+ {
+ //pathlib_showsquare(where, 0 ,30);
+ //pathlib_showsquare(parent.origin, 1 ,30);
+ dprint("pathlib_movenode_goodnode = 0\n");
return 0;
+ }
+
+ //pathlib_showsquare(where, 1 ,30);
if(pathlib_nodeatpoint(where))
{
return 0;
}
+
if(doedge)
if not (tile_check(where))
+ {
+ dprint("tile_check fail\n");
+ pathlib_showsquare(where, 0 ,30);
return 0;
+ }
+
h = pathlib_heuristic(where,goal);
g = pathlib_cost(parent,where,cost);
f = g + h;
-
/*
node = findradius(where,pathlib_gridsize * 0.5);
while(node)
}
*/
- node = pathlib_mknode(where,parent);
+ node = pathlib_mknode(where, parent);
node.pathlib_node_h = h;
node.pathlib_node_g = g;
node.pathlib_node_f = f;
return 0;
}
+float buildpath_nodefilter_none(vector n,vector c,vector p)
+{
+ return 0;
+}
+
entity path_build(entity next, vector where, entity prev, entity start)
{
entity path;
// Select water<->land capable node make/link
pathlib_makenode = pathlib_makenode_adaptive;
+
// Select XYZ cost estimate
//pathlib_heuristic = pathlib_h_diagonal3;
pathlib_heuristic = pathlib_h_diagonal;
+
// Select distance + waterfactor cost
pathlib_cost = pathlib_g_euclidean_water;
+
// Select star expander
pathlib_expandnode = pathlib_expandnode_star;
+
// Select walk simulation movement test
pathlib_movenode = pathlib_walknode;
+
// Filter final nodes by direction
buildpath_nodefilter = buildpath_nodefilter_directional;
+
// Filter tiles with cross pattern
tile_check = tile_check_cross;
pathlib_gridsize = 128;
pathlib_movecost = pathlib_gridsize;
pathlib_movecost_diag = vlen(('1 1 0' * pathlib_gridsize));
- pathlib_movecost_waterfactor = 1;
+ pathlib_movecost_waterfactor = 25000000;
pathlib_foundgoal = 0;
- movenode_boxmax = self.maxs * 1.25;
- movenode_boxmin = self.mins * 1.25;
+ movenode_boxmax = self.maxs * 1.1;
+ movenode_boxmin = self.mins * 1.1;
- movenode_stepsize = 32;
+ movenode_stepsize = pathlib_gridsize * 0.25;
- tile_check_size = 65;
+ tile_check_size = pathlib_gridsize * 0.5;
+ tile_check_up = '0 0 2' * pathlib_gridsize;
tile_check_up = '0 0 128';
- tile_check_down = '0 0 128';
+ tile_check_down = '0 0 3' * pathlib_gridsize;
+ tile_check_down = '0 0 256';
+ //movenode_stepup = '0 0 128';
movenode_stepup = '0 0 36';
- movenode_maxdrop = '0 0 128';
+ movenode_maxdrop = '0 0 512';
+ //movenode_maxdrop = '0 0 512';
movenode_boxup = '0 0 72';
- from_x = fsnap(from_x,pathlib_gridsize);
- from_y = fsnap(from_y,pathlib_gridsize);
+ from_x = fsnap(from_x, pathlib_gridsize);
+ from_y = fsnap(from_y, pathlib_gridsize);
+ //from_z += 32;
- to_x = fsnap(to_x,pathlib_gridsize);
- to_y = fsnap(to_y,pathlib_gridsize);
+ to_x = fsnap(to_x, pathlib_gridsize);
+ to_y = fsnap(to_y, pathlib_gridsize);
+ //to_z += 32;
dprint("AStar init\n");
- path = pathlib_mknode(from,world);
- pathlib_close_node(path,to);
+ path = pathlib_mknode(from, world);
+ pathlib_close_node(path, to);
if(pathlib_foundgoal)
{
dprint("AStar: Goal found on first node!\n");
return open;
}
- if(pathlib_expandnode(path,from,to) <= 0)
+ if(pathlib_expandnode(path, from, to) <= 0)
{
dprint("AStar path fail.\n");
pathlib_cleanup();
best_open_node = pathlib_getbestopen();
n = best_open_node;
- pathlib_close_node(best_open_node,to);
+ pathlib_close_node(best_open_node, to);
if(inwater(n.origin))
- pathlib_expandnode_box(n,from,to);
+ pathlib_expandnode_box(n, from, to);
else
- pathlib_expandnode_star(n,from,to);
+ pathlib_expandnode_star(n, from, to);
while(pathlib_open_cnt)
{
return end;
}
+void a_think()
+{
+ te_lightning1(self,self.origin, self.pos1);
+ if(self.cnt < time)
+ remove(self);
+ else
+ self.nextthink = time + 0.2;
+}
+
vector pathlib_walknode(vector start,vector end,float doedge)
{
vector direction,point,last_point,s,e;
float steps, distance, i;
+ dprint("Walking node from ", vtos(start), " to ", vtos(end), "\n");
+
pathlib_movenode_goodnode = 0;
end_x = fsnap(end_x,pathlib_gridsize);
start_y = fsnap(start_y,pathlib_gridsize);
// Find the floor
- traceline(start + movenode_stepup, start - movenode_maxdrop,MOVE_WORLDONLY,self);
+ traceline(start + movenode_stepup, start - movenode_maxdrop, MOVE_WORLDONLY, self);
if(trace_fraction == 1.0)
+ {
+ entity a;
+ a = spawn();
+ a.think = a_think;
+ a.nextthink = time;
+ setorigin(a,start + movenode_stepup);
+ a.pos1 = trace_endpos;
+ //start - movenode_maxdrop
+ a.cnt = time + 10;
+
+ dprint("I cant walk on air!\n");
return trace_endpos;
+ }
start = trace_endpos;
--- /dev/null
+var float pathlib_wpp_open(entity wp, entity child, float cost);
+
+void pathlib_wpp_close(entity wp)
+{
+ --pathlib_open_cnt;
+ ++pathlib_closed_cnt;
+
+ wp.pathlib_list = closedlist;
+
+ if(wp == best_open_node)
+ best_open_node = world;
+
+ if(wp == goal_node)
+ pathlib_foundgoal = TRUE;
+}
+
+float pathlib_wpp_opencb(entity wp, entity child, float cost)
+{
+
+ if(child.pathlib_list == closedlist)
+ return FALSE;
+
+ // FIXME! wp.wp##mincost is NOT distance. Make it distance or add a field for distance to be used here (for better speed)
+ cost = vlen(child.origin - wp.origin);
+
+ child.path_prev = wp;
+ child.pathlib_list = openlist;
+ child.pathlib_node_g = wp.pathlib_node_g + cost;
+ child.pathlib_node_h = pathlib_heuristic(child.origin, goal_node.origin);
+ child.pathlib_node_c = pathlib_wpp_waypointcallback(child, wp);
+ child.pathlib_node_f = child.pathlib_node_g + child.pathlib_node_h + child.pathlib_node_c;
+
+
+ if(child == goal_node)
+ pathlib_foundgoal = TRUE;
+
+ ++pathlib_open_cnt;
+
+ if(best_open_node.pathlib_node_f > child.pathlib_node_f)
+ best_open_node = child;
+
+ return TRUE;
+}
+
+float pathlib_wpp_openncb(entity wp, entity child, float cost)
+{
+
+ if(child.pathlib_list == closedlist)
+ return FALSE;
+
+ // FIXME! wp.wp##mincost is NOT distance. Make it distance or add a field for distance to be used here (for better speed)
+ cost = vlen(child.origin - wp.origin);
+
+ child.path_prev = wp;
+ child.pathlib_list = openlist;
+ child.pathlib_node_g = wp.pathlib_node_g + cost;
+ child.pathlib_node_h = pathlib_heuristic(child.origin, goal_node.origin);
+ child.pathlib_node_f = child.pathlib_node_g + child.pathlib_node_h;
+
+ if(child == goal_node)
+ pathlib_foundgoal = TRUE;
+
+ ++pathlib_open_cnt;
+
+ if(best_open_node.pathlib_node_f > child.pathlib_node_f)
+ best_open_node = child;
+
+ return TRUE;
+}
+
+float pathlib_wpp_expand(entity wp)
+{
+ if(wp.wp00) pathlib_wpp_open(wp,wp.wp00,wp.wp00mincost); else return 0;
+ if(wp.wp01) pathlib_wpp_open(wp,wp.wp01,wp.wp01mincost); else return 1;
+ if(wp.wp02) pathlib_wpp_open(wp,wp.wp02,wp.wp02mincost); else return 2;
+ if(wp.wp03) pathlib_wpp_open(wp,wp.wp03,wp.wp03mincost); else return 3;
+ if(wp.wp04) pathlib_wpp_open(wp,wp.wp04,wp.wp04mincost); else return 4;
+ if(wp.wp05) pathlib_wpp_open(wp,wp.wp05,wp.wp05mincost); else return 5;
+ if(wp.wp06) pathlib_wpp_open(wp,wp.wp06,wp.wp06mincost); else return 6;
+ if(wp.wp07) pathlib_wpp_open(wp,wp.wp07,wp.wp07mincost); else return 7;
+ if(wp.wp08) pathlib_wpp_open(wp,wp.wp08,wp.wp08mincost); else return 8;
+ if(wp.wp09) pathlib_wpp_open(wp,wp.wp09,wp.wp09mincost); else return 9;
+ if(wp.wp10) pathlib_wpp_open(wp,wp.wp10,wp.wp10mincost); else return 10;
+ if(wp.wp11) pathlib_wpp_open(wp,wp.wp11,wp.wp11mincost); else return 11;
+ if(wp.wp12) pathlib_wpp_open(wp,wp.wp12,wp.wp12mincost); else return 12;
+ if(wp.wp13) pathlib_wpp_open(wp,wp.wp13,wp.wp13mincost); else return 13;
+ if(wp.wp14) pathlib_wpp_open(wp,wp.wp14,wp.wp14mincost); else return 14;
+ if(wp.wp15) pathlib_wpp_open(wp,wp.wp15,wp.wp15mincost); else return 15;
+ if(wp.wp16) pathlib_wpp_open(wp,wp.wp16,wp.wp16mincost); else return 16;
+ if(wp.wp17) pathlib_wpp_open(wp,wp.wp17,wp.wp17mincost); else return 17;
+ if(wp.wp18) pathlib_wpp_open(wp,wp.wp18,wp.wp18mincost); else return 18;
+ if(wp.wp19) pathlib_wpp_open(wp,wp.wp19,wp.wp19mincost); else return 19;
+ if(wp.wp20) pathlib_wpp_open(wp,wp.wp20,wp.wp20mincost); else return 20;
+ if(wp.wp21) pathlib_wpp_open(wp,wp.wp21,wp.wp21mincost); else return 21;
+ if(wp.wp22) pathlib_wpp_open(wp,wp.wp22,wp.wp22mincost); else return 22;
+ if(wp.wp23) pathlib_wpp_open(wp,wp.wp23,wp.wp23mincost); else return 23;
+ if(wp.wp24) pathlib_wpp_open(wp,wp.wp24,wp.wp24mincost); else return 24;
+ if(wp.wp25) pathlib_wpp_open(wp,wp.wp25,wp.wp25mincost); else return 25;
+ if(wp.wp26) pathlib_wpp_open(wp,wp.wp26,wp.wp26mincost); else return 26;
+ if(wp.wp27) pathlib_wpp_open(wp,wp.wp27,wp.wp27mincost); else return 27;
+ if(wp.wp28) pathlib_wpp_open(wp,wp.wp28,wp.wp28mincost); else return 28;
+ if(wp.wp29) pathlib_wpp_open(wp,wp.wp29,wp.wp29mincost); else return 29;
+ if(wp.wp30) pathlib_wpp_open(wp,wp.wp30,wp.wp30mincost); else return 30;
+ if(wp.wp31) pathlib_wpp_open(wp,wp.wp31,wp.wp31mincost); else return 31;
+
+ return 32;
+}
+
+entity pathlib_wpp_bestopen()
+{
+ entity n, best;
+
+ if(best_open_node)
+ return best_open_node;
+
+ n = findchainentity(pathlib_list, openlist);
+ best = n;
+ while(n)
+ {
+ if(n.pathlib_node_f < best.pathlib_node_f)
+ best = n;
+
+ n = n.chain;
+ }
+
+ return best;
+
+}
+
+entity pathlib_waypointpath(entity wp_from, entity wp_to, float callback)
+{
+ entity n;
+ float ptime;
+
+ ptime = gettime(GETTIME_REALTIME);
+ pathlib_starttime = ptime;
+ pathlib_movecost = 300;
+ pathlib_movecost_diag = vlen('1 1 0' * pathlib_movecost);
+
+ if not (pathlib_wpp_waypointcallback)
+ callback = FALSE;
+
+ if (callback)
+ pathlib_wpp_open = pathlib_wpp_opencb;
+ else
+ pathlib_wpp_open = pathlib_wpp_openncb;
+
+ pathlib_heuristic = pathlib_h_none;
+
+ if not(openlist)
+ openlist = spawn();
+
+ if not(closedlist)
+ closedlist = spawn();
+
+ pathlib_closed_cnt = 0;
+ pathlib_open_cnt = 0;
+ pathlib_searched_cnt = 0;
+ pathlib_foundgoal = FALSE;
+
+ dprint("pathlib_waypointpath init\n");
+
+ // Initialize waypoint grid
+ // FIXME! presisted chain for better preformance
+ for(n = findchain(classname, "waypoint"); n; n = n.chain)
+ {
+ n.pathlib_list = world;
+ n.pathlib_node_g = 0;
+ n.pathlib_node_f = 0;
+ n.pathlib_node_h = 0;
+
+ //setmodel(n, "models/runematch/rune.mdl");
+ //n.effects = EF_LOWPRECISION;
+ //n.colormod = '0 0 0';
+ //n.scale = 1;
+
+ }
+
+ goal_node = wp_to;
+ start_node = wp_from;
+
+ start_node.pathlib_list = closedlist;
+ dprint("Expanding ",ftos(pathlib_wpp_expand(start_node))," links\n");
+ if(pathlib_open_cnt <= 0)
+ {
+ dprint("pathlib_waypointpath: Start waypoint not linked! aborting.\n");
+ return world;
+ }
+
+ return world;
+}
+
+entity pathlib_waypointpath_step()
+{
+ entity n;
+
+ n = pathlib_wpp_bestopen();
+ if(!n)
+ {
+ dprint("Cannot find best open node, abort.\n");
+ return world;
+ }
+ pathlib_wpp_close(n);
+ dprint("Expanding ",ftos(pathlib_wpp_expand(n))," links\n");
+
+ if(pathlib_foundgoal)
+ {
+ entity start, end, open, ln;
+
+ dprint("Target found. Rebuilding and filtering path...\n");
+
+ buildpath_nodefilter = buildpath_nodefilter_none;
+ start = path_build(world, start_node.origin, world, world);
+ end = path_build(world, goal_node.origin, world, start);
+ ln = end;
+
+ for(open = goal_node; open.path_prev != start_node; open = open.path_prev)
+ {
+ n = path_build(ln,open.origin,open.path_prev,start);
+ ln.path_prev = n;
+ ln = n;
+ }
+ start.path_next = n;
+ n.path_prev = start;
+
+ return start;
+ }
+
+ return world;
+}
+void plas_think()
+{
+ pathlib_waypointpath_step();
+ if(pathlib_foundgoal)
+ return;
+ self.nextthink = time + 0.1;
+}
+
+void pathlib_waypointpath_autostep()
+{
+ entity n;
+ n = spawn();
+ n.think = plas_think;
+ n.nextthink = time + 0.1;
+}
+.entity pathlib_list;
.entity path_next;
.entity path_prev;
entity openlist;
entity closedlist;
+entity edgelist;
+
entity goal_node;
+entity start_node;
.float is_path_node;
.float pathlib_node_g;
.float pathlib_node_h;
.float pathlib_node_f;
+.float pathlib_node_c;
+
+#define pathlib_node_edgeflag_unknown 0
+#define pathlib_node_edgeflag_left 2
+#define pathlib_node_edgeflag_right 4
+#define pathlib_node_edgeflag_forward 8
+#define pathlib_node_edgeflag_back 16
+#define pathlib_node_edgeflag_backleft 32
+#define pathlib_node_edgeflag_backright 64
+#define pathlib_node_edgeflag_forwardleft 128
+#define pathlib_node_edgeflag_forwardright 256
+#define pathlib_node_edgeflag_none 512
+.float pathlib_node_edgeflags;
float pathlib_open_cnt;
float pathlib_closed_cnt;
float pathlib_foundgoal;
float pathlib_starttime;
-#define pathlib_maxtime 5
+#define pathlib_maxtime 60
entity best_open_node;
vector tile_check_up;
vector tile_check_down;
float tile_check_size;
-float tile_check_cross(vector where);
-float tile_check_plus(vector where);
-float tile_check_star(vector where);
-var float tile_check(vector where);
+float tile_check_cross(vector where);
+float tile_check_plus(vector where);
+float tile_check_star(vector where);
+var float tile_check(vector where);
float movenode_stepsize;
vector movenode_stepup;
float pathlib_h_diagonal2(vector a, vector b);
float pathlib_h_diagonal3(vector a, vector b);
float pathlib_h_diagonal2sdp(vector preprev, vector prev, vector point, vector end);
+float pathlib_h_none(vector preprev, vector prev) { return 0; }
var float pathlib_heuristic(vector from, vector to);
var float pathlib_makenode(entity parent,vector start, vector to, vector goal,float cost);
var float buildpath_nodefilter(vector n,vector c,vector p);
+var float pathlib_wpp_waypointcallback(entity wp, entity wp_prev);
+var const float pathlib_wpp_wpcb_null();
#ifdef DEBUGPATHING
-#include "debug.qc"
+ #include "debug.qc"
#endif
#include "utility.qc"
#include "costs.qc"
#include "expandnode.qc"
#include "main.qc"
+#include "path_waypoint.qc"
f = PLIB_FORWARD * tile_check_size;
r = PLIB_RIGHT * tile_check_size;
+
// forward-right
p = where + f + r;
- traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
- if not (location_isok(trace_endpos,1,0))
+ traceline(p + tile_check_up, p - tile_check_down, MOVE_WORLDONLY, self);
+ if not (location_isok(trace_endpos, 1, 0))
return 0;
// Forward-left
p = where + f - r;
- traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
- if not (location_isok(trace_endpos,1,0))
+ traceline(p + tile_check_up, p - tile_check_down, MOVE_WORLDONLY, self);
+ if not (location_isok(trace_endpos, 1, 0))
return 0;
// Back-right
p = where - f + r;
- traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
- if not (location_isok(trace_endpos,1,0))
+ traceline(p + tile_check_up, p - tile_check_down, MOVE_WORLDONLY, self);
+ if not (location_isok(trace_endpos, 1 ,0))
return 0;
//Back-left
p = where - f - r;
- traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
- if not (location_isok(trace_endpos,1,0))
+ traceline(p + tile_check_up, p - tile_check_down, MOVE_WORLDONLY, self);
+ if not (location_isok(trace_endpos, 1, 0))
return 0;
return 1;
if not (location_isok(trace_endpos,1,0))
return 0;
+
//left
p = where - r;
traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
if not (location_isok(trace_endpos,1,0))
return 0;
-
// Right
p = where + r;
traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
return 1;
}
+float tile_check_plus2(vector where)
+{
+ vector p,f,r;
+ float i,e;
+
+ f = PLIB_FORWARD * pathlib_gridsize;
+ r = PLIB_RIGHT * pathlib_gridsize;
+
+//#define pathlib_node_edgeflag_left 2
+//#define pathlib_node_edgeflag_right 4
+//#define pathlib_node_edgeflag_forward 8
+//#define pathlib_node_edgeflag_back 16
+
+ // forward
+ p = where + f;
+ traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+ if (location_isok(trace_endpos,1,0))
+ {
+ ++i;
+ e |= pathlib_node_edgeflag_forward;
+ }
+
+
+ //left
+ p = where - r;
+ traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+ if (location_isok(trace_endpos,1,0))
+ {
+ ++i;
+ e |= pathlib_node_edgeflag_left;
+ }
+
+
+ // Right
+ p = where + r;
+ traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+ if (location_isok(trace_endpos,1,0))
+ {
+ ++i;
+ e |= pathlib_node_edgeflag_right;
+ }
+
+ //Back
+ p = where - f;
+ traceline(p+tile_check_up,p-tile_check_down,MOVE_WORLDONLY,self);
+ if (location_isok(trace_endpos,1,0))
+ {
+ ++i;
+ e |= pathlib_node_edgeflag_back;
+ }
+
+ // forward-right
+ p = where + f + r;
+ traceline(p + tile_check_up, p - tile_check_down, MOVE_WORLDONLY, self);
+ if (location_isok(trace_endpos, 1, 0))
+ {
+ ++i;
+ e |= pathlib_node_edgeflag_forwardright;
+ }
+
+ // Forward-left
+ p = where + f - r;
+ traceline(p + tile_check_up, p - tile_check_down, MOVE_WORLDONLY, self);
+ if (location_isok(trace_endpos, 1, 0))
+ {
+ ++i;
+ e |= pathlib_node_edgeflag_forwardleft;
+ }
+
+ // Back-right
+ p = where - f + r;
+ traceline(p + tile_check_up, p - tile_check_down, MOVE_WORLDONLY, self);
+ if (location_isok(trace_endpos, 1 ,0))
+ {
+ ++i;
+ e |= pathlib_node_edgeflag_backright;
+ }
+
+ //Back-left
+ p = where - f - r;
+ traceline(p + tile_check_up, p - tile_check_down, MOVE_WORLDONLY, self);
+ if (location_isok(trace_endpos, 1, 0))
+ {
+ ++i;
+ e |= pathlib_node_edgeflag_backleft;
+ }
+
+
+ if(i == 0)
+ e = pathlib_node_edgeflag_none;
+
+ return e;
+}
+
float tile_check_star(vector where)
{
if(tile_check_plus(where))
defs.qh // Should rename this, it has fields and globals
+mutators/base.qh
+mutators/mutators.qh
+mutators/gamemode_keyhunt.qh // TODO fix this
+mutators/mutator_dodging.qh
+
//// tZork Turrets ////
tturrets/include/turrets_early.qh
race.qh
-keyhunt.qh
-
antilag.qh
vote.qh
../common/gamecommand.qc
gamecommand.qc
-keyhunt.qc
-
assault.qc
ipban.qc
target_spawn.qc
func_breakable.qc
+target_music.qc
../common/items.qc
anticheat.qc
cheats.qc
+mutators/base.qc
+mutators/gamemode_keyhunt.qc
+mutators/mutator_nix.qc
+mutators/mutator_dodging.qc
+
../warpzonelib/anglestransform.qc
../warpzonelib/mathlib.qc
../warpzonelib/common.qc
{
if(gameover)
return 0;
- error("Adding score to unknown player!");
+ backtrace("Adding score to unknown player!");
+ return 0;
}
if(score)
if(scores_label[scorefield] != "")
sv_airstopaccelerate = cvar("sv_airstopaccelerate");
sv_airstrafeaccelerate = cvar("sv_airstrafeaccelerate");
sv_maxairstrafespeed = cvar("sv_maxairstrafespeed");
+ sv_airstrafeaccel_qw = cvar("sv_airstrafeaccel_qw");
sv_aircontrol = cvar("sv_aircontrol");
+ sv_aircontrol_power = cvar("sv_aircontrol_power");
sv_warsowbunny_airforwardaccel = cvar("sv_warsowbunny_airforwardaccel");
sv_warsowbunny_accel = cvar("sv_warsowbunny_accel");
sv_warsowbunny_topspeed = cvar("sv_warsowbunny_topspeed");
sv_warsowbunny_turnaccel = cvar("sv_warsowbunny_turnaccel");
sv_warsowbunny_backtosideratio = cvar("sv_warsowbunny_backtosideratio");
+ sv_airspeedlimit_nonqw = cvar("sv_airspeedlimit_nonqw");
teamplay = cvar ("teamplay");
sys_frametime = cvar("sys_ticrate") * cvar("slowmo");
+ sv_doublejump = cvar("sv_doublejump");
if (timeoutStatus == 1) // just before the timeout (when timeoutStatus will be 2)
orig_slowmo = cvar("slowmo"); // slowmo will be restored after the timeout
self.angles_z = self.angles_z + (random() * 2 - 1) * self.anglesjitter_z;
if(self.anglejitter != 0)
self.angles_y = self.angles_y + (random() * 2 - 1) * self.anglejitter;
+
+ if(MUTATOR_CALLHOOK(OnEntityPreSpawn))
+ {
+ remove(self);
+ return;
+ }
}
}
.float max_armorvalue;
+.float pickup_anyway;
float Item_Customize()
{
if(self.weapons != (self.weapons & other.weapons))
{
self.colormod = '0 0 0';
- if(cvar("gameversion") >= 20600) // only do this for 2.6 and above FIXME remove this check when making 2.6
- self.glowmod = self.colormod;
+ self.glowmod = self.colormod;
self.alpha = 0.5 + 0.5 * g_ghost_items; // halfway more alpha
return TRUE;
}
if(g_ghost_items)
{
self.colormod = stov(cvar_string("g_ghost_items_color"));
- if(cvar("gameversion") >= 20600) // only do this for 2.6 and above FIXME remove this check when making 2.6
- self.glowmod = self.colormod;
+ self.glowmod = self.colormod;
self.alpha = g_ghost_items;
return TRUE;
}
e.model = e.mdl;
e.solid = SOLID_TRIGGER;
e.colormod = '0 0 0';
- if(cvar("gameversion") >= 20600) // only do this for 2.6 and above FIXME remove this check when making 2.6
- self.glowmod = self.colormod;
+ self.glowmod = self.colormod;
e.alpha = 0;
e.customizeentityforclient = func_null;
e.model = string_null;
e.solid = SOLID_NOT;
e.colormod = '0 0 0';
- if(cvar("gameversion") >= 20600) // only do this for 2.6 and above FIXME remove this check when making 2.6
- self.glowmod = self.colormod;
+ self.glowmod = self.colormod;
e.alpha = 0;
e.customizeentityforclient = func_null;
e.model = e.mdl;
e.solid = SOLID_TRIGGER; // can STILL be picked up!
e.colormod = '0 0 0';
- if(cvar("gameversion") >= 20600) // only do this for 2.6 and above FIXME remove this check when making 2.6
- self.glowmod = self.colormod;
+ self.glowmod = self.colormod;
e.effects |= EF_STARDUST;
e.customizeentityforclient = Item_Customize;
e.model = e.mdl;
e.solid = SOLID_NOT;
e.colormod = stov(cvar_string("g_ghost_items_color"));
- if(cvar("gameversion") >= 20600) // only do this for 2.6 and above FIXME remove this check when making 2.6
- self.glowmod = self.colormod;
+ self.glowmod = self.colormod;
e.alpha = g_ghost_items;
e.customizeentityforclient = func_null;
e.model = string_null;
e.solid = SOLID_NOT;
e.colormod = stov(cvar_string("g_ghost_items_color"));
- if(cvar("gameversion") >= 20600) // only do this for 2.6 and above FIXME remove this check when making 2.6
- self.glowmod = self.colormod;
+ self.glowmod = self.colormod;
e.alpha = 0;
e.customizeentityforclient = func_null;
}
if (item.ammo_fuel)
- if (player.ammo_fuel < g_pickup_fuel_max)
+ if (player.ammo_fuel < g_pickup_fuel_max)
{
pickedup = TRUE;
player.ammo_fuel = min(player.ammo_fuel + item.ammo_fuel, g_pickup_fuel_max);
if(item.spawnshieldtime)
{
if (item.ammo_shells)
- if (player.ammo_shells < g_pickup_shells_max)
+ if ((player.ammo_shells < g_pickup_shells_max) || item.pickup_anyway)
{
pickedup = TRUE;
player.ammo_shells = min (player.ammo_shells + item.ammo_shells, g_pickup_shells_max);
}
if (item.ammo_nails)
- if (player.ammo_nails < g_pickup_nails_max)
+ if ((player.ammo_nails < g_pickup_nails_max) || item.pickup_anyway)
{
pickedup = TRUE;
player.ammo_nails = min (player.ammo_nails + item.ammo_nails, g_pickup_nails_max);
}
if (item.ammo_rockets)
- if (player.ammo_rockets < g_pickup_rockets_max)
+ if ((player.ammo_rockets < g_pickup_rockets_max) || item.pickup_anyway)
{
pickedup = TRUE;
player.ammo_rockets = min (player.ammo_rockets + item.ammo_rockets, g_pickup_rockets_max);
}
if (item.ammo_cells)
- if (player.ammo_cells < g_pickup_cells_max)
+ if ((player.ammo_cells < g_pickup_cells_max) || item.pickup_anyway)
{
pickedup = TRUE;
player.ammo_cells = min (player.ammo_cells + item.ammo_cells, g_pickup_cells_max);
}
if (item.ammo_fuel)
- if (player.ammo_fuel < g_pickup_fuel_max)
+ if ((player.ammo_fuel < g_pickup_fuel_max) || item.pickup_anyway)
{
pickedup = TRUE;
player.ammo_fuel = min(player.ammo_fuel + item.ammo_fuel, g_pickup_fuel_max);
}
if (item.flags & FL_WEAPON)
- if ((it = item.weapons - (item.weapons & player.weapons)))
+ if ((it = item.weapons - (item.weapons & player.weapons)) || g_pickup_weapons_anyway)
{
pickedup = TRUE;
for(i = WEP_FIRST; i <= WEP_LAST; ++i)
}
if (item.health)
- if (player.health < item.max_health)
+ if ((player.health < item.max_health) || item.pickup_anyway)
{
pickedup = TRUE;
player.health = min(player.health + item.health, item.max_health);
player.pauserothealth_finished = max(player.pauserothealth_finished, time + cvar("g_balance_pause_health_rot"));
}
if (item.armorvalue)
- if (player.armorvalue < item.max_armorvalue)
+ if ((player.armorvalue < item.max_armorvalue) || item.pickup_anyway)
{
pickedup = TRUE;
player.armorvalue = min(player.armorvalue + item.armorvalue, item.max_armorvalue);
{
startitem_failed = FALSE;
+ self.items = itemid;
+ self.weapons = weaponid;
+
// is it a dropped weapon?
if (self.classname == "droppedweapon")
{
}
else
{
+ if(MUTATOR_CALLHOOK(FilterItem)) // error means we do not want the item
+ {
+ startitem_failed = TRUE;
+ remove(self);
+ return;
+ }
+
+ itemid = self.items;
+ weaponid = self.weapons;
+
self.reset = Item_Reset;
// it's a level item
if(self.spawnflags & 1)
return;
}
}
- else if (g_nixnex)
- {
- local float rm;
-
- rm = 1;
- switch (itemid)
- {
- case IT_HEALTH:
- case IT_5HP:
- case IT_25HP:
- case IT_ARMOR:
- case IT_ARMOR_SHARD:
- if (cvar("g_nixnex_with_healtharmor"))
- rm = 0;
- break;
- case IT_STRENGTH:
- case IT_INVINCIBLE:
- if (cvar("g_nixnex_with_powerups"))
- rm = 0;
- break;
- }
-
- if(rm)
- {
- startitem_failed = TRUE;
- remove (self);
- return;
- }
- }
else if (!cvar("g_pickup_items") && itemid != IT_STRENGTH && itemid != IT_INVINCIBLE && itemid != IT_HEALTH)
{
startitem_failed = TRUE;
self.respawntimejitter = defaultrespawntimejitter;
}
self.netname = itemname;
- self.items = itemid;
- self.weapons = weaponid;
self.flags = FL_ITEM | itemflags;
self.touch = Item_Touch;
setmodel (self, self.mdl); // precision set below
void spawnfunc_item_rockets (void) {
if(!self.ammo_rockets)
self.ammo_rockets = g_pickup_rockets;
+ if(!self.pickup_anyway)
+ self.pickup_anyway = g_pickup_ammo_anyway;
StartItem ("models/items/a_rockets.md3", "misc/itempickup.wav", g_pickup_respawntime_ammo, g_pickup_respawntimejitter_ammo, "rockets", IT_ROCKETS, 0, 0, commodity_pickupevalfunc, 3000);
}
if(!self.ammo_nails)
self.ammo_nails = g_pickup_nails;
+ if(!self.pickup_anyway)
+ self.pickup_anyway = g_pickup_ammo_anyway;
StartItem ("models/items/a_bullets.mdl", "misc/itempickup.wav", g_pickup_respawntime_ammo, g_pickup_respawntimejitter_ammo, "bullets", IT_NAILS, 0, 0, commodity_pickupevalfunc, 2000);
}
void spawnfunc_item_cells (void) {
if(!self.ammo_cells)
self.ammo_cells = g_pickup_cells;
+ if(!self.pickup_anyway)
+ self.pickup_anyway = g_pickup_ammo_anyway;
StartItem ("models/items/a_cells.md3", "misc/itempickup.wav", g_pickup_respawntime_ammo, g_pickup_respawntimejitter_ammo, "cells", IT_CELLS, 0, 0, commodity_pickupevalfunc, 2000);
}
if(!self.ammo_shells)
self.ammo_shells = g_pickup_shells;
+ if(!self.pickup_anyway)
+ self.pickup_anyway = g_pickup_ammo_anyway;
StartItem ("models/items/a_shells.md3", "misc/itempickup.wav", g_pickup_respawntime_ammo, g_pickup_respawntimejitter_ammo, "shells", IT_SHELLS, 0, 0, commodity_pickupevalfunc, 500);
}
self.armorvalue = g_pickup_armorsmall;
if(!self.max_armorvalue)
self.max_armorvalue = g_pickup_armorsmall_max;
+ if(!self.pickup_anyway)
+ self.pickup_anyway = g_pickup_armorsmall_anyway;
StartItem ("models/items/g_a1.md3", "misc/armor1.wav", g_pickup_respawntime_short, g_pickup_respawntimejitter_short, "5 Armor", IT_ARMOR_SHARD, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_LOW);
}
self.armorvalue = g_pickup_armormedium;
if(!self.max_armorvalue)
self.max_armorvalue = g_pickup_armormedium_max;
+ if(!self.pickup_anyway)
+ self.pickup_anyway = g_pickup_armormedium_anyway;
StartItem ("models/items/g_armormedium.md3", "misc/armor10.wav", g_pickup_respawntime_medium, g_pickup_respawntimejitter_medium, "25 Armor", IT_ARMOR, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_MID);
}
self.armorvalue = g_pickup_armorbig;
if(!self.max_armorvalue)
self.max_armorvalue = g_pickup_armorbig_max;
+ if(!self.pickup_anyway)
+ self.pickup_anyway = g_pickup_armorbig_anyway;
StartItem ("models/items/g_a50.md3", "misc/armor17_5.wav", g_pickup_respawntime_long, g_pickup_respawntimejitter_long, "50 Armor", IT_ARMOR, 0, 0, commodity_pickupevalfunc, 20000);
}
self.armorvalue = g_pickup_armorlarge;
if(!self.max_armorvalue)
self.max_armorvalue = g_pickup_armorlarge_max;
+ if(!self.pickup_anyway)
+ self.pickup_anyway = g_pickup_armorlarge_anyway;
StartItem ("models/items/g_a25.md3", "misc/armor25.wav", g_pickup_respawntime_long, g_pickup_respawntimejitter_long, "100 Armor", IT_ARMOR, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_HIGH);
}
self.max_health = g_pickup_healthsmall_max;
if(!self.health)
self.health = g_pickup_healthsmall;
+ if(!self.pickup_anyway)
+ self.pickup_anyway = g_pickup_healthsmall_anyway;
StartItem ("models/items/g_h1.md3", "misc/minihealth.wav", g_pickup_respawntime_short, g_pickup_respawntimejitter_short, "5 Health", IT_5HP, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_LOW);
}
self.max_health = g_pickup_healthmedium_max;
if(!self.health)
self.health = g_pickup_healthmedium;
+ if(!self.pickup_anyway)
+ self.pickup_anyway = g_pickup_healthmedium_anyway;
StartItem ("models/items/g_h25.md3", "misc/mediumhealth.wav", g_pickup_respawntime_short, g_pickup_respawntimejitter_short, "25 Health", IT_25HP, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_MID);
}
self.max_health = g_pickup_healthlarge_max;
if(!self.health)
self.health = g_pickup_healthlarge;
+ if(!self.pickup_anyway)
+ self.pickup_anyway = g_pickup_healthlarge_anyway;
StartItem ("models/items/g_h50.md3", "misc/mediumhealth.wav", g_pickup_respawntime_medium, g_pickup_respawntimejitter_medium, "50 Health", IT_25HP, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_MID);
}
self.max_health = g_pickup_healthmega_max;
if(!self.health)
self.health = g_pickup_healthmega;
+ if(!self.pickup_anyway)
+ self.pickup_anyway = g_pickup_healthmega_anyway;
StartItem ("models/items/g_h100.md3", "misc/megahealth.wav", g_pickup_respawntime_long, g_pickup_respawntimejitter_long, "100 Health", IT_HEALTH, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_HIGH);
}
}
float n, i, j;
entity e;
- if(g_nixnex)
- {
- // items triggers cannot work in nixnex (as they change weapons/ammo)
- remove(self);
- return;
- }
-
self.use = target_items_use;
if(!self.strength_finished)
self.strength_finished = cvar("g_balance_powerup_strength_time");
{
if(!self.ammo_fuel)
self.ammo_fuel = g_pickup_fuel;
+ if(!self.pickup_anyway)
+ self.pickup_anyway = g_pickup_ammo_anyway;
StartItem ("models/items/g_fuel.md3", "misc/itempickup.wav", g_pickup_respawntime_ammo, g_pickup_respawntimejitter_ammo, "Fuel", IT_FUEL, 0, 0, commodity_pickupevalfunc, BOT_PICKUP_RATING_LOW);
}
StartItem ("models/items/g_jetpack.md3", "misc/itempickup.wav", g_pickup_respawntime_powerup, g_pickup_respawntimejitter_powerup, "Jet pack", IT_JETPACK, 0, FL_POWERUP, commodity_pickupevalfunc, BOT_PICKUP_RATING_LOW);
}
-// we no longer have the seeker
-void spawnfunc_weapon_seeker()
-{
- spawnfunc_weapon_fireball();
-}
-
#define OP_SET 0
#define OP_MIN 1
continue;
case "ALL":
got += GiveBit(e, items, IT_FUEL_REGEN, op, val);
- got += GiveValue(e, strength_finished, op, time + val);
- got += GiveValue(e, invincible_finished, op, time + val);
+ got += GiveValue(e, strength_finished, op, time);
+ got += GiveValue(e, invincible_finished, op, time);
got += GiveBit(e, items, IT_UNLIMITED_AMMO, op, val);
case "all":
got += GiveBit(e, items, IT_JETPACK, op, val);
other.flags &~= FL_ONGROUND;
other.velocity = self.movedir;
- other.jumppadusetime = time;
if (other.classname == "player")
{
--- /dev/null
+.float lifetime;
+// values:
+// volume
+// noise
+// targetname
+// lifetime
+// fade_time
+// fade_rate
+// when triggered, the music is overridden for activator until lifetime (or forever, if lifetime is 0)
+// when targetname is not set, THIS ONE is default
+void target_music_sendto(float to, float is)
+{
+ WriteByte(to, SVC_TEMPENTITY);
+ WriteByte(to, TE_CSQC_TARGET_MUSIC);
+ WriteShort(to, num_for_edict(self));
+ WriteByte(to, self.volume * 255.0 * is);
+ WriteByte(to, self.fade_time * 16.0);
+ WriteByte(to, self.fade_rate * 16.0);
+ WriteByte(to, self.lifetime);
+ WriteString(to, self.noise);
+}
+void target_music_reset()
+{
+ if(self.targetname == "")
+ target_music_sendto(MSG_ALL, 1);
+}
+void target_music_use()
+{
+ if(!activator)
+ return;
+ msg_entity = activator;
+ target_music_sendto(MSG_ONE, 1);
+}
+void spawnfunc_target_music()
+{
+ self.use = target_music_use;
+ self.reset = target_music_reset;
+ if(!self.volume)
+ self.volume = 1;
+ if(self.targetname == "")
+ target_music_sendto(MSG_INIT, 1);
+ else
+ target_music_sendto(MSG_INIT, 0);
+}
+void TargetMusic_RestoreGame()
+{
+ for(self = world; (self = find(self, classname, "target_music")); )
+ {
+ if(self.targetname == "")
+ target_music_sendto(MSG_INIT, 1);
+ else
+ target_music_sendto(MSG_INIT, 0);
+ }
+}
+// values:
+// volume
+// noise
+// targetname
+// fade_time
+// spawnflags:
+// 1 = START_OFF
+// when triggered, it is disabled/enabled for everyone
+float trigger_music_SendEntity(entity to, float sf)
+{
+ WriteByte(MSG_ENTITY, ENT_CLIENT_TRIGGER_MUSIC);
+ sf &~= 0x80;
+ if(self.cnt)
+ sf |= 0x80;
+ WriteByte(MSG_ENTITY, sf);
+ if(sf & 4)
+ {
+ WriteCoord(MSG_ENTITY, self.origin_x);
+ WriteCoord(MSG_ENTITY, self.origin_y);
+ WriteCoord(MSG_ENTITY, self.origin_z);
+ }
+ if(sf & 1)
+ {
+ if(self.model != "null")
+ {
+ WriteShort(MSG_ENTITY, self.modelindex);
+ WriteCoord(MSG_ENTITY, self.mins_x);
+ WriteCoord(MSG_ENTITY, self.mins_y);
+ WriteCoord(MSG_ENTITY, self.mins_z);
+ WriteCoord(MSG_ENTITY, self.maxs_x);
+ WriteCoord(MSG_ENTITY, self.maxs_y);
+ WriteCoord(MSG_ENTITY, self.maxs_z);
+ }
+ else
+ {
+ WriteShort(MSG_ENTITY, 0);
+ WriteCoord(MSG_ENTITY, self.maxs_x);
+ WriteCoord(MSG_ENTITY, self.maxs_y);
+ WriteCoord(MSG_ENTITY, self.maxs_z);
+ }
+ WriteByte(MSG_ENTITY, self.volume * 255.0);
+ WriteByte(MSG_ENTITY, self.fade_time * 16.0);
+ WriteByte(MSG_ENTITY, self.fade_rate * 16.0);
+ WriteString(MSG_ENTITY, self.noise);
+ }
+ return 1;
+}
+void trigger_music_reset()
+{
+ self.cnt = !(self.spawnflags & 1);
+ self.SendFlags |= 0x80;
+}
+void trigger_music_use()
+{
+ self.cnt = !self.cnt;
+ self.SendFlags |= 0x80;
+}
+void spawnfunc_trigger_music()
+{
+ if(self.model != "")
+ setmodel(self, self.model);
+ if(!self.volume)
+ self.volume = 1;
+ if(!self.modelindex)
+ {
+ setorigin(self, self.origin + self.mins);
+ setsize(self, '0 0 0', self.maxs - self.mins);
+ }
+ trigger_music_reset();
+
+ self.use = trigger_music_use;
+ self.reset = trigger_music_reset;
+
+ Net_LinkEntity(self, FALSE, 0, trigger_music_SendEntity);
+}
target_spawn_useon(e);
e.target_spawn_id = self.target_spawn_id;
}
+ else if(self.target == "*activator")
+ {
+ // edit entity
+ if(activator)
+ target_spawn_useon(activator);
+ }
else
{
// edit entity
fraglimit_override = cvar("fraglimit_override");
leadlimit_override = cvar("leadlimit_override");
+ if(cvar("g_dodging"))
+ MUTATOR_ADD(dodging);
+
if(g_dm)
{
game = GAME_DEATHMATCH;
ActivateTeamplay();
fraglimit_override = cvar("g_keyhunt_point_limit");
leadlimit_override = cvar("g_keyhunt_point_leadlimit");
- kh_init();
+ MUTATOR_ADD(gamemode_keyhunt);
}
if(g_assault)
}
:normal
- modifications = "";
+ ret_string = "";
+ MUTATOR_CALLHOOK(BuildMutatorsPrettyString);
+ modifications = ret_string;
+
if(g_minstagib)
modifications = strcat(modifications, ", MinstaGib");
- if(g_nixnex)
- modifications = strcat(modifications, ", NixNex");
if(g_weaponarena)
{
if(g_weaponarena_random)
c1 = c2 = c3 = c4 = -1;
cb1 = cb2 = cb3 = cb4 = 0;
- if(g_onslaught)
+ if(cvar("g_campaign") && for_whom && clienttype(for_whom) == CLIENTTYPE_REAL)
+ {
+ c1 = 0; // only allow RED team for player joining
+ }
+ else if(g_onslaught)
{
// onslaught is special
head = findchain(classname, "onslaught_generator");
else
{
// cover anything else by treating it like tdm with no teams spawned
- if(g_keyhunt)
- dm = kh_teams;
- else if(g_race)
+ if(g_race)
dm = race_teams;
else
dm = 2;
+ ret_float = dm;
+ MUTATOR_CALLHOOK(GetTeamCount);
+ dm = ret_float;
+
if(dm >= 4)
c1 = c2 = c3 = c4 = 0;
else if(dm >= 3)
if(totalteams <= 1)
{
- if(g_domination)
+ if(cvar("g_campaign") && pl && clienttype(pl) == CLIENTTYPE_REAL)
+ return 1; // special case for campaign and player joining
+ else if(g_domination)
error("Too few teams available for domination\n");
else if(g_ctf)
error("Too few teams available for ctf\n");
{
// 1: use team count, if equal prefer own team
if(c1 >= 0) RandomSelection_Add(world, 1, string_null, 1, (maxc - c1) + (self.team == COLOR_TEAM1) / 512.0);
- if(c2 >= 0) RandomSelection_Add(world, 1, string_null, 1, (maxc - c1) + (self.team == COLOR_TEAM2) / 512.0);
- if(c3 >= 0) RandomSelection_Add(world, 1, string_null, 1, (maxc - c1) + (self.team == COLOR_TEAM3) / 512.0);
- if(c4 >= 0) RandomSelection_Add(world, 1, string_null, 1, (maxc - c1) + (self.team == COLOR_TEAM4) / 512.0);
+ if(c2 >= 0) RandomSelection_Add(world, 2, string_null, 1, (maxc - c1) + (self.team == COLOR_TEAM2) / 512.0);
+ if(c3 >= 0) RandomSelection_Add(world, 3, string_null, 1, (maxc - c1) + (self.team == COLOR_TEAM3) / 512.0);
+ if(c4 >= 0) RandomSelection_Add(world, 4, string_null, 1, (maxc - c1) + (self.team == COLOR_TEAM4) / 512.0);
}
else if(balance_type == 3)
{
.string cvar_basename;
//.float spawnflags
+#define TSF_SUSPENDED 1
/// Spawn a pillar model under the turret to make it look ok on uneven ground surfaces
#define TSF_TERRAINBASE 2
/// Disable builtin ammo regeneration
if (validate_flags & TFL_TARGETSELECT_LOS)
{
v_tmp = real_origin(e_target) + ((e_target.mins + e_target.maxs) * 0.5);
- traceline(e_turret.tur_shotorg,v_tmp,0,e_turret);
+
+ traceline(e_turret.tur_shotorg, v_tmp, 0, e_turret);
if (e_turret.aim_firetolerance_dist < vlen(v_tmp - trace_endpos))
return -19;
v = gettaginfo(e,gettagindex(e,"tag_fire"));
if(v == '0 0 0')
{
- objerror("^1ERROR: Engine is borken! Turrets will NOT work. force g_turrets to 0 to run maps with turrets anyway.");
- crash();
+ //objerror("^1ERROR: Engine is borken! Turrets will NOT work. force g_turrets to 0 to run maps with turrets anyway.");
+ //crash();
}
setmodel(e,"");
csqc_shared = 0;
}
+ if not (self.spawnflags & TSF_SUSPENDED)
+ droptofloor_builtin();
+
// Terrainbase spawnflag. This puts a enlongated model
// under the turret, so it looks ok on uneaven surfaces.
if (self.spawnflags & TSF_TERRAINBASE)
float vz;
vector wish_angle,real_angle;
+ /*
+ if(self.enemy)
+ dprint("enemy!\n");
+ else
+ dprint("nothign =(!\n");
+ */
+
vz = self.velocity_z;
self.angles_x = anglemods(self.angles_x);
self.angles_y = (self.angles_y + real_angle_y);
// Simulate banking
- self.angles_z = bound(-45,real_angle_y * -2.5,45);
+ self.angles_z -= self.angles_z * frametime * 2;
+ self.angles_z = bound(-45,self.angles_z + ((real_angle_y * -25) * frametime),45);
if(self.enemy)
ewheel_move_enemy();
{
entity e;
- setorigin(self,self.pos1);
+ self.velocity = '0 0 0';
+ self.enemy = world;
+
+ setorigin(self, self.pos1);
if (self.target != "")
{
void ewheel_diehook()
{
- turret_trowgib2(self.origin,self.velocity + '0 0 400', '-0.6 -0.2 -02', self, 3 + time + random() * 2);
-
self.velocity = '0 0 0';
+ turret_trowgib2(self.origin, self.velocity + '0 0 400', '-0.6 -0.2 -02', self, 3 + time + random() * 2);
+
if (self.pathcurrent)
pathlib_deletepath(self.pathcurrent.owner);
self.pathcurrent = world;
-
- /*
- if (self.damage_flags & TFL_DMG_DEATH_NORESPAWN)
- {
- verbstack_flush(self.verbs_move);
- remove(self.verbs_move);
- }
- */
-
}
void turret_ewheel_dinit()
self.solid = SOLID_SLIDEBOX;
self.takedamage = DAMAGE_AIM;
- setsize(self,'-32 -32 0', '32 32 48');
+ setsize(self, '-32 -32 0', '32 32 48');
+ self.idle_aim = '0 0 0';
self.pos1 = self.origin;
- self.idle_aim = '0 0 0';
-
// Our fire routine
self.turret_firefunc = ewheel_attack;
self.turret_postthink = ewheel_postthink;
self.tur_head.aim_speed = cvar("g_turrets_unit_ewheel_turnrate");
self.tur_head.aim_speed = self.tur_head.aim_speed / (1 / self.ticrate);
+ if (!turret_tag_setup())
+ dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
+
+ //setorigin(self,self.origin + '0 0 128');
if (self.target != "")
{
e = find(world,targetname,self.target);
dprint("Warning: not a turrret path\n");
else
{
- self.pathcurrent = WALKER_PATH(self.origin,e.origin);
+ self.pathcurrent = WALKER_PATH(self.origin, e.origin);
self.pathgoal = e;
}
}
precache_model ("models/turrets/ewheel-base2.md3");
precache_model ("models/turrets/ewheel-gun1.md3");
+ precache_model ("models/pathlib/goodsquare.md3");
+ precache_model ("models/pathlib/badsquare.md3");
+ precache_model ("models/pathlib/square.md3");
+
turret_ewheel_loadcvars();
self.think = turret_ewheel_dinit;
return;
}
+ if (!turret_tag_setup())
+ dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
+
self.damage_flags |= TFL_DMG_DEATH_NOGIBS;
self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
float racer_speed_forward;
float racer_speed_strafe;
+float racer_afterburn_cost;
+
float jetfromtag_power;
float jetfromtag_normpower;
vector jetfromtag_origin;
racer_speed_forward = cvar("g_vehicle_racer_speed_forward");
racer_speed_strafe = cvar("g_vehicle_racer_speed_strafe");
+ racer_afterburn_cost = cvar("g_vehicle_racer_afterburn_cost");
+
racer_healthmax = cvar("g_vehicle_racer_health");
racer_shieldmax = cvar("g_vehicle_racer_shield");
racer_energymax = cvar("g_vehicle_racer_energy");
// FIXME this uses prydon cursor
v = normalize(self.owner.cursor_trace_endpos - bolt.origin);
v_forward_z = v_z * 0.5;
- //v_forward_z *= 0.5;
bolt.velocity = v_forward * cvar("g_vehicle_racer_laser_speed");
float ftmp, ftmp2;
vector df;
-
if(cvar("g_vehicle_racer_reload"))
{
racer_loadsettings();
ftmp = racer_turnspeed * sys_frametime;
ftmp2 = ftmp * -1;
- ftmp = bound(ftmp2,shortangle_f(player.v_angle_y - racer.angles_y,racer.angles_y),ftmp);
+ ftmp = bound(ftmp2, shortangle_f(player.v_angle_y - racer.angles_y, racer.angles_y), ftmp);
ftmp2 = safeangle(racer.angles_y + ftmp);
// Roll
- ftmp = bound(-45,shortangle_f(player.v_angle_z + ((racer.angles_y - ftmp2) * racer_turnroll), racer.angles_z),45);
+ ftmp = bound(-45, shortangle_f(player.v_angle_z + ((racer.angles_y - ftmp2) * racer_turnroll), racer.angles_z), 45);
ftmp = safeangle(racer.angles_z + ftmp);
- racer.angles_z = bound(-85,ftmp,85);
+ racer.angles_z = bound(-85, ftmp, 85);
// Turn
racer.angles_y = ftmp2;
racer.angles_x = safeangle(racer.angles_x + ftmp);
racer.angles_x *= -1;
- df = racer.velocity * -1;
+ df = racer.velocity * -0.5;
if(player.movement_x != 0)
{
// Afterburn
- //if (jetfromtag_groundcontact)
if (player.BUTTON_JUMP)
- if(racer.vehicle_energy >= (cvar("g_vehicle_racer_speed_afterburn_cost") * frametime))
+ if(racer.vehicle_energy >= (racer_afterburn_cost * frametime))
{
racer.wait = time + cvar("g_vehicle_racer_energy_usepause");
- racer.vehicle_energy -= cvar("g_vehicle_racer_speed_afterburn_cost") * frametime;
+ racer.vehicle_energy -= racer_afterburn_cost * frametime;
df += (v_forward * cvar("g_vehicle_racer_speed_afterburn"));
}
}
player.vehicle_reload1 = (time - racer.lip) / (racer.delay-racer.lip);
- //player.vehicle_energy = racer.vehicle_energy;
-
vehicle_stdproc_shiledregen(racer_shieldmax, frametime);
vehicle_stdproc_healthregen(racer_healthmax, frametime);
racer_enter();
}
-/*
-float racer_customizeentityforclient()
-{
- if(self.deadflag == DEAD_DEAD)
- return FALSE;
-
- return TRUE;
-}
-*/
-
void racer_spawn()
{
self.think = racer_spawnthink;
--- /dev/null
+#define RAPTOR_MIN '-40 -40 0'
+#define RAPTOR_MAX '40 40 40'
+
+float raptor_movestyle;
+float raptor_turnspeed;
+float raptor_turnroll;
+float raptor_pitchspeed;
+float raptor_speed_forward;
+float raptor_speed_strafe;
+float raptor_speed_up;
+float raptor_speed_down;
+
+float raptor_bomblet_waves;
+float raptor_bomblet_wavefirst;
+float raptor_bomblet_wavenext;
+float raptor_bomblet_wawespread;
+float raptor_bomblets;
+float raptor_bomblet_damage;
+float raptor_bomblet_edgedamage;
+float raptor_bomblet_radius;
+float raptor_bomblet_force;
+float raptor_bombs_refire;
+
+float raptor_beam_dps;
+float raptor_beam_fops;
+float raptor_beam_aps;
+float raptor_beam_size;
+float raptor_beam_leangth;
+float raptor_beam_refire;
+
+float raptor_shield_max;
+float raptor_shield_regen;
+
+float raptor_health_max;
+float raptor_health_regen;
+
+float raptor_energy_max;
+float raptor_energy_regen;
+
+void raptor_spawn();
+void raptor_return();
+float raptor_pplug();
+float raptor_takeoff();
+float raptor_land();
+
+.entity bomb1;
+.entity bomb2;
+
+float raptor_altitude(float amax)
+{
+ tracebox(self.origin, self.mins, self.maxs, '0 0 -1' * amax, TRUE, self);
+ if(trace_fraction == 1)
+ return amax+1;
+ else
+ return vlen(self.origin - trace_endpos);
+}
+
+void raptor_loadsettings()
+{
+ raptor_movestyle = CCVAR("_movestyle");
+ raptor_turnspeed = CCVAR("_turnspeed");
+ raptor_turnroll = CCVAR("_turnroll");
+ raptor_pitchspeed = CCVAR("_pitchspeed");
+ raptor_speed_forward = CCVAR("_speed_forward");
+ raptor_speed_strafe = CCVAR("_speed_strafe");
+ raptor_speed_up = CCVAR("_speed_up");
+ raptor_speed_down = CCVAR("_speed_down");
+
+ raptor_bomblet_waves = CCVAR("_bomblet_waves ");
+ raptor_bomblet_wavefirst = CCVAR("_bomblet_wavefirst");
+ raptor_bomblet_wavenext = CCVAR("_bomblet_wavenext");
+ raptor_bomblet_wawespread = CCVAR("_bomblet_wawespread");
+ raptor_bomblets = CCVAR("_bomblets");
+ raptor_bomblet_damage = CCVAR("_bomblet_damage");
+ raptor_bomblet_edgedamage = CCVAR("_bomblet_edgedamage");
+ raptor_bomblet_radius = CCVAR("_bomblet_radius");
+ raptor_bomblet_force = CCVAR("_bomblet_force ");
+ raptor_bombs_refire = CCVAR("_bombs_refire");
+
+ raptor_beam_dps = CCVAR("_beam_dps");
+ raptor_beam_fops = CCVAR("_beam_fops");
+ raptor_beam_aps = CCVAR("_beam_aps");
+ raptor_beam_size = CCVAR("_beam_size");
+ raptor_beam_leangth = CCVAR("_beam_length");
+ raptor_beam_refire = CCVAR("_beam_refire");
+
+ raptor_shield_max = CCVAR("_shield_max");
+ raptor_shield_regen = CCVAR("_shield_regen");
+
+ raptor_health_max = CCVAR("_health_max");
+ raptor_health_regen = CCVAR("_health_regen");
+
+ raptor_energy_max = CCVAR("_energy_max");
+ raptor_energy_regen = CCVAR("_energy_regen");
+}
+
+void raptor_bombs_return()
+{
+ self.owner.bomb1.alpha = 1;
+ self.owner.bomb2.alpha = 1;
+ remove(self);
+}
+
+void raptor_bomblet_boom()
+{
+ if(other.enemy == self.enemy)
+ return;
+
+ pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
+ RadiusDamage (self, self.enemy, raptor_bomblet_damage, raptor_bomblet_edgedamage, raptor_bomblet_radius, world, raptor_bomblet_force, DEATH_SBROCKET, world);
+ remove(self);
+}
+
+void raptor_bomb_burst()
+{
+ self.angles = vectoangles(self.velocity);
+
+ if(self.cnt < time)
+ {
+ entity bomblet;
+ float i,v;
+ vector d;
+
+ makevectors(self.angles);
+ v = vlen(self.velocity) + random();
+ d = normalize(self.velocity);
+ pointparticles(particleeffectnum("rocket_explode"), self.origin, '0 0 0', 1);
+
+ for(i = 0; i < raptor_bomblets; ++i)
+ {
+
+ bomblet = spawn();
+ setorigin(bomblet,self.origin);
+
+ setmodel(bomblet,"models/vehicles/raptor_bomb.dpm");
+ bomblet.scale = 0.5;
+
+ bomblet.owner = self.owner;
+ bomblet.enemy = self.enemy;
+
+ bomblet.solid = SOLID_TRIGGER;
+ bomblet.movetype = MOVETYPE_BOUNCE;
+ bomblet.touch = raptor_bomblet_boom;
+
+ bomblet.think = raptor_bomblet_boom;
+ bomblet.nextthink = time + 5;
+
+ //bomblet.modelflags = MF_ROCKET;
+ bomblet.modelflags = MF_GRENADE;
+
+ bomblet.velocity = normalize(d + randomvec() * raptor_bomblet_wawespread) * v;
+
+ bomblet.angles = vectoangles(bomblet.velocity);
+ }
+
+ self.wait -= 1;
+ if(self.wait <= 0)
+ {
+ remove(self);
+ return;
+ }
+
+ self.cnt = time + raptor_bomblet_wavenext;
+ }
+
+ self.nextthink = time;
+}
+
+void raptor_bomb_touch()
+{
+ raptor_bomb_burst();
+}
+
+void raptor_bombdrop()
+{
+ entity bomb_1, bomb_2;
+
+ self.bomb1.alpha = 0.25;
+ self.bomb2.alpha = 0.25;
+
+ bomb_1 = spawn();
+ bomb_2 = spawn();
+
+ setmodel(bomb_1,"models/vehicles/raptor_bomb.dpm");
+ setmodel(bomb_2,"models/vehicles/raptor_bomb.dpm");
+
+ setorigin(bomb_1, gettaginfo(self, gettagindex(self, "bombmount_left")));
+ setorigin(bomb_2, gettaginfo(self, gettagindex(self, "bombmount_right")));
+
+ bomb_1.movetype = bomb_2.movetype = MOVETYPE_TOSS;
+ bomb_1.velocity = bomb_2.velocity = self.velocity;
+ bomb_1.touch = bomb_2.touch = raptor_bomb_touch;
+ bomb_1.think = bomb_2.think = raptor_bomb_burst;
+ bomb_1.nextthink = bomb_2.nextthink = time;
+ bomb_1.cnt = bomb_2.cnt = time + raptor_bomblet_wavefirst;
+ bomb_1.wait = bomb_2.wait = raptor_bomblet_waves;
+
+ bomb_1.avelocity = bomb_2.avelocity = '0 0 180';
+ bomb_1.owner = bomb_2.owner = self;
+ bomb_1.enemy = bomb_2.enemy = self.owner;
+ bomb_1.angles = bomb_2.angles = self.angles;
+ bomb_1.solid = bomb_2.solid = SOLID_BBOX;
+
+ bomb_1 = spawn();
+ bomb_1.owner = self;
+ bomb_1.think = raptor_bombs_return;
+ bomb_1.nextthink = time + raptor_bombs_refire;
+}
+
+void raptor_animator_think()
+{
+ self.owner.frame += 1;
+ if(self.owner.frame == self.cnt)
+ remove(self);
+ else
+ self.nextthink = time + self.wait;
+}
+
+void raptor_setanim(float start, float end, float length)
+{
+ entity ani;
+ if(self.tur_head.enemy)
+ ani = self.tur_head.enemy;
+ else
+ ani = spawn();
+
+ self.tur_head.enemy = ani;
+ ani.owner = self;
+ self.frame = start;
+ ani.cnt = end;
+ ani.wait = sys_frametime / length;
+ ani.think = raptor_animator_think;
+ ani.nextthink = time + ani.wait;
+}
+
+void raptor_beam (vector start, vector end, vector smin, vector smax, float bforce, float f_dmg, float deathtype)
+
+{
+ vector hitloc, force, endpoint, dir;
+ entity ent;
+
+ dir = normalize(end - start);
+ force = dir * bforce;
+
+ // go a little bit into the wall because we need to hit this wall later
+ end = end + dir;
+
+ // trace multiple times until we hit a wall, each obstacle will be made unsolid.
+ // note down which entities were hit so we can damage them later
+ while (1)
+ {
+ tracebox(start, smin, smax, end, FALSE, world);
+
+ // if it is world we can't hurt it so stop now
+ if (trace_ent == world || trace_fraction == 1)
+ break;
+
+ if (trace_ent.solid == SOLID_BSP)
+ break;
+
+ // make the entity non-solid so we can hit the next one
+ trace_ent.railgunhit = TRUE;
+ trace_ent.railgunhitloc = end;
+ trace_ent.railgunhitsolidbackup = trace_ent.solid;
+
+ // make the entity non-solid
+ trace_ent.solid = SOLID_NOT;
+ }
+
+ endpoint = trace_endpos;
+
+ // find all the entities the railgun hit and hurt them
+ ent = findchainfloat(railgunhit, TRUE);
+ while (ent)
+ {
+ // get the details we need to call the damage function
+ ent.solid = ent.railgunhitsolidbackup;
+ hitloc = ent.railgunhitloc;
+ ent.railgunhitloc = '0 0 0';
+ ent.railgunhitsolidbackup = SOLID_NOT;
+ ent.railgunhit = FALSE;
+
+ // apply the damage
+ if (ent.takedamage)
+ Damage (ent, self, self, f_dmg, deathtype, hitloc, force);
+
+ ent = ent.chain;
+ }
+ trace_endpos = endpoint;
+}
+
+
+void raptor_enter()
+{
+ // Remove this when bots know how to use vehicles
+ if (clienttype(other) != CLIENTTYPE_REAL)
+ return;
+
+ if(teamplay)
+ if(self.team)
+ if(self.team != other.team)
+ return;
+
+ self.owner = other;
+ self.switchweapon = other.switchweapon;
+
+ self.event_damage = vehicle_stdproc_damage;
+ self.colormap = self.owner.colormap;
+ self.vehicle_hudmodel.viewmodelforclient = self.owner;
+ self.nextthink = 0;
+ self.owner.angles = self.angles;
+ self.owner.takedamage = DAMAGE_NO;
+ self.owner.solid = SOLID_NOT;
+ self.owner.movetype = MOVETYPE_NOCLIP;
+ self.owner.alpha = -1;
+ self.owner.PlayerPhysplug = raptor_takeoff;
+ self.owner.vehicle = self;
+ self.owner.event_damage = SUB_Null;
+ self.owner.hud = HUD_RAPTOR;
+ self.owner.vehicle_health = self.vehicle_health / raptor_health_max;
+ self.owner.vehicle_shield = self.vehicle_shield / raptor_shield_max;
+ self.owner.view_ofs = '0 0 1';
+ self.owner.vehicle_ammo1 = self.vehicle_ammo1;
+ self.owner.vehicle_ammo2 = self.vehicle_ammo2;
+ self.owner.vehicle_reload1 = self.vehicle_reload1;
+ self.owner.vehicle_reload2 = self.vehicle_reload2;
+
+ other.flags &~= FL_ONGROUND;
+ self.flags &~= FL_ONGROUND;
+
+ self.frame = 0;
+ raptor_setanim(0, 25, 1);
+
+ self.team = self.owner.team;
+ self.flags -= FL_NOTARGET;
+
+ self.velocity = '0 0 1';
+
+ setorigin(other,self.origin + '0 0 32');
+ other.velocity = self.velocity;
+
+ other.flags &~= FL_ONGROUND;
+ msg_entity = other;
+ WriteByte (MSG_ONE, SVC_SETVIEWPORT);
+ WriteEntity( MSG_ONE, self.vehicle_viewport);
+
+ WriteByte (MSG_ONE, SVC_SETVIEWANGLES); // 10 = SVC_SETVIEWANGLES
+ WriteAngle(MSG_ONE, self.angles_x * -1); // tilt
+ WriteAngle(MSG_ONE, self.angles_y); // yaw
+ WriteAngle(MSG_ONE, 0); // roll
+}
+
+void raptor_exit(float eject)
+{
+ self.colormap = 1024;
+ self.flags = FL_NOTARGET;
+
+ if not (self.owner)
+ return;
+
+ msg_entity = self.owner;
+ WriteByte (MSG_ONE, SVC_SETVIEWPORT);
+ WriteEntity( MSG_ONE, self.owner);
+
+ WriteByte (MSG_ONE, SVC_SETVIEWANGLES); // 10 = SVC_SETVIEWANGLES
+ WriteAngle(MSG_ONE, 0); // tilt
+ WriteAngle(MSG_ONE, self.angles_y); // yaw
+ WriteAngle(MSG_ONE, 0); // roll
+
+ if (self.deadflag == DEAD_NO)
+ {
+ //self.think = racer_exitthink;
+ self.nextthink = time;
+ }
+
+ self.owner.takedamage = DAMAGE_AIM;
+ self.owner.solid = SOLID_SLIDEBOX;
+ self.owner.movetype = MOVETYPE_WALK;
+
+ setsize(self.owner,PL_MIN,PL_MAX);
+
+ self.owner.effects &~= EF_NODRAW;
+ self.owner.alpha = 1;
+ self.owner.PlayerPhysplug = SUB_Null;
+ self.owner.vehicle = world;
+ self.owner.view_ofs = PL_VIEW_OFS;
+ self.owner.event_damage = PlayerDamage;
+ self.owner.hud = HUD_NORMAL;
+ //self.exteriormodeltoclient = self;
+
+ self.vehicle_hudmodel.viewmodelforclient = self;
+
+ if(eject)
+ {
+ makevectors(self.angles);
+ setorigin(self.owner,self.origin + v_forward * 100);
+ self.owner.velocity = (v_up + v_forward * 0.25) * 750;
+ }
+ else
+ {
+ self.owner.velocity = (v_forward) * -150;
+ setorigin(self.owner,self.origin - v_forward * 128);
+ }
+
+ self.owner = world;
+
+ if (self.deadflag != DEAD_NO)
+ {
+ entity ret;
+ ret = spawn();
+ ret.enemy = self;
+ ret.think = raptor_return;
+ ret.nextthink = time + cvar("g_vehicle_racer_respawntime");
+ }
+}
+
+
+float raptor_pplug()
+{
+ entity player, vhic;
+ float ftmp, ftmp2, energy_used;
+ vector df;
+
+
+ if(cvar("g_vehicle_raptor_reload"))
+ {
+ raptor_loadsettings();
+ cvar_set("g_vehicle_raptor_reload","0");
+ }
+
+ player = self;
+ vhic = self.vehicle;
+ self = vhic;
+
+ if(player.BUTTON_USE)
+ {
+ self = vhic;
+ raptor_exit(0);
+ self = player;
+ return 0;
+ }
+
+ if(vhic.deadflag != DEAD_NO)
+ {
+ self = player;
+ player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
+ return 1;
+ }
+
+ vhic.angles_x *= -1;
+ // Rotate Body
+ ftmp = raptor_turnspeed * sys_frametime;
+
+ ftmp = bound(-ftmp, shortangle_f(player.v_angle_y - vhic.angles_y, vhic.angles_y), ftmp);
+
+ // Roll
+ //ftmp = bound(-90,shortangle_f(player.v_angle_z + ((vhic.angles_y - ftmp2) * raptor_turnroll), vhic.angles_z),90);
+ //ftmp = safeangle(vhic.angles_z + ftmp);
+ //vhic.angles_z = ftmp;
+
+ // Turn
+ vhic.angles_y = safeangle(vhic.angles_y + ftmp);
+
+ // Pitch Body
+ ftmp = raptor_pitchspeed * sys_frametime;
+
+ ftmp = bound(-ftmp, shortangle_f(player.v_angle_x - vhic.angles_x,vhic.angles_x), ftmp);
+
+ vhic.angles_x = bound(-60,safeangle(vhic.angles_x + ftmp),60);
+ vhic.angles_x *= -1;
+
+ if(raptor_movestyle == 1)
+ {
+ ftmp = vhic.angles_z;
+ vhic.angles_z = 0;
+ ftmp2 = vhic.angles_x;
+ vhic.angles_x = 0;
+ fixedmakevectors(vhic.angles);
+ vhic.angles_z = ftmp;
+ vhic.angles_x = ftmp2;
+ }
+ else
+ fixedmakevectors(vhic.angles);
+
+ df = vhic.velocity * -1;
+
+ if(player.movement_x != 0)
+ {
+ if(player.movement_x > 0)
+ df += v_forward * raptor_speed_forward;
+ else if(player.movement_x < 0)
+ df -= v_forward * raptor_speed_forward;
+ }
+
+ if(player.movement_y != 0)
+ {
+ if(player.movement_y < 0)
+ df -= v_right * raptor_speed_strafe;
+ else if(player.movement_y > 0)
+ df += v_right * raptor_speed_strafe;
+
+ vhic.angles_z = bound(-30,vhic.angles_z + (player.movement_y / raptor_speed_strafe),30);
+ }
+ else
+ {
+ vhic.angles_z *= 0.95;
+ if(vhic.angles_z >= -1 && vhic.angles_z <= -1)
+ vhic.angles_z = 0;
+ }
+
+ if(player.BUTTON_CROUCH)
+ df -= v_up * raptor_speed_down;
+ else if (player.BUTTON_JUMP)
+ df += v_up * raptor_speed_up;
+ //else
+ //df_z = vhic.velocity_z * -1;
+
+ vhic.velocity += df * frametime;
+ player.velocity = player.movement = vhic.velocity;
+ setorigin(player,vhic.origin + '0 0 32');
+
+ // Aim the gunz
+ vector target_angle, move_angle, org1, org2, targ;
+
+ makevectors(player.v_angle);
+
+ //targ = (vhic.origin + player.view_ofs) + v_forward * MAX_SHOT_DISTANCE;
+ targ = player.cursor_trace_endpos;
+
+ org1 = gettaginfo(vhic.gun1,gettagindex(vhic.gun1, "fire1"));
+ org2 = gettaginfo(vhic.gun2,gettagindex(vhic.gun2, "fire1"));
+
+ traceline(vhic.origin + player.view_ofs, targ, FALSE, vhic);
+ targ = trace_endpos;
+
+ // Find the direction
+ target_angle = vectoangles(normalize(targ - org1)); // And make a angle
+
+ // Find the diffrence between where we currently aim and where we want to aim
+ move_angle = target_angle - (vhic.angles + vhic.gun1.angles);
+ move_angle = shortangle_vxy(move_angle,(vhic.angles + vhic.gun1.angles));
+ vhic.gun1.angles_x = bound(-10, move_angle_x + vhic.gun1.angles_x, 10);
+ vhic.gun1.angles_y = bound(-15, move_angle_y + vhic.gun1.angles_y, 15);
+
+ // Find the direction
+ target_angle = vectoangles(normalize(targ - org2)); // And make a angle
+
+ move_angle = target_angle - (vhic.angles + vhic.gun2.angles);
+ move_angle = shortangle_vxy(move_angle,(vhic.angles + vhic.gun2.angles));
+ vhic.gun2.angles_x = bound(-15,move_angle_x + vhic.gun2.angles_x,15);
+ vhic.gun2.angles_y = bound(-20,move_angle_y + vhic.gun2.angles_y,20);
+
+ if(player.BUTTON_ATCK)
+ if(vhic.vehicle_energy > (raptor_beam_aps * sys_frametime))
+ {
+ vector start;
+ self = player;
+
+ start = gettaginfo(vhic.gun1, gettagindex(vhic.gun1, "fire1"));
+ traceline(start, start + v_forward * MAX_SHOT_DISTANCE, TRUE, player);
+ te_lightning1(vhic.gun1, start, trace_endpos);
+ raptor_beam(start, trace_endpos, '-1 -1 -1' * raptor_beam_size, '1 1 1' * raptor_beam_size, raptor_beam_fops * sys_frametime, raptor_beam_dps * sys_frametime, DEATH_SBROCKET);
+
+
+ start = gettaginfo(vhic.gun2, gettagindex(vhic.gun2, "fire1"));
+ traceline(start, start + v_forward * MAX_SHOT_DISTANCE, TRUE, player);
+ te_lightning1(vhic.gun2, start, trace_endpos);
+ raptor_beam(start, trace_endpos, '-1 -1 -1' * raptor_beam_size, '1 1 1' * raptor_beam_size, raptor_beam_fops * sys_frametime, raptor_beam_dps * sys_frametime, DEATH_SBROCKET);
+
+ self = vhic;
+
+ vhic.vehicle_energy -= raptor_beam_aps * sys_frametime;
+ vhic.cnt = time + 1;
+ }
+
+ if(vhic.cnt < time)
+ vhic.vehicle_energy = min(vhic.vehicle_energy += raptor_energy_regen * frametime, raptor_energy_max);
+
+ player.vehicle_energy = vhic.vehicle_energy / raptor_energy_max;
+
+
+ if(player.BUTTON_ATCK2)
+ if(time > vhic.delay)
+ {
+ raptor_bombdrop();
+ vhic.delay = time + raptor_bombs_refire;
+ }
+
+ player.BUTTON_ATCK = player.BUTTON_ATCK2 = player.BUTTON_CROUCH = 0;
+ vehicle_stdproc_shiledregen(raptor_shield_max, frametime);
+ vehicle_stdproc_healthregen(raptor_health_max, frametime);
+
+ self = player;
+
+ return 1;
+}
+
+float raptor_takeoff()
+{
+ entity player, vhic;
+
+ if(self.vehicle.frame < 25)
+ return 1;
+
+ player = self;
+ vhic = self.vehicle;
+ self = vhic;
+
+ if(raptor_altitude(512) <= 256)
+ {
+ vhic.velocity_z = min(vhic.velocity_z * 1.5, 256);
+ }
+ else
+ {
+ player.PlayerPhysplug = raptor_pplug;
+ }
+
+ player.BUTTON_CROUCH = player.BUTTON_ATCK = player.BUTTON_ATCK2 = 0;
+ self = player;
+
+ return 1;
+}
+
+float raptor_land()
+{
+ return 0;
+}
+
+void raptor_return()
+{
+ pointparticles(particleeffectnum("teleport"), self.enemy.origin + '0 0 64', '0 0 0', 1);
+ self.enemy.think = raptor_spawn;
+ self.enemy.nextthink = time;
+ remove(self);
+}
+
+void raptor_think()
+{
+}
+
+void raptor_touch()
+{
+ if(self.owner)
+ {
+ if(vlen(self.velocity) == 0)
+ return;
+
+ if(other.classname != "player")
+ return;
+
+ return;
+ }
+
+ if(other.classname != "player")
+ return;
+
+ if(other.deadflag != DEAD_NO)
+ return;
+
+ if(other.vehicle != world)
+ return;
+
+ raptor_enter();
+}
+
+void raptor_die()
+{
+ self.health = 0;
+ self.event_damage = SUB_Null;
+ self.iscreature = FALSE;
+ self.solid = SOLID_NOT;
+ self.takedamage = DAMAGE_NO;
+ //self.touch = racer_dietouch;
+ self.deadflag = DEAD_DYING;
+ self.movetype = MOVETYPE_BOUNCE;
+ self.wait = time;
+
+ pointparticles(particleeffectnum("rocket_explode"), findbetterlocation (self.origin, 16), '0 0 0', 1);
+
+ self.velocity += '0 0 128';
+
+ if(random() < 0.5)
+ self.avelocity_z = 45;
+ else
+ self.avelocity_z = -45;
+
+ self.colormod = '-0.5 -0.5 -0.5';
+
+ self.think = raptor_spawn;
+ self.nextthink = time + 5;
+}
+
+void raptor_spawn()
+{
+ self.flags = FL_NOTARGET;
+ self.effects = 0;
+
+ self.vehicle_health = raptor_health_max;
+ self.vehicle_shield = raptor_shield_max;
+
+ self.event_damage = vehicle_stdproc_damage;
+ self.touch = raptor_touch;
+
+ self.iscreature = TRUE;
+ self.movetype = MOVETYPE_FLY;
+ self.solid = SOLID_SLIDEBOX;
+ self.takedamage = DAMAGE_AIM;
+
+ self.alpha = 1;
+ self.colormap = 1024;
+ self.deadflag = DEAD_NO;
+ self.bot_attack = TRUE;
+
+ self.colormod = '1 1 1';
+ self.avelocity = '0 0 0';
+ self.velocity = '0 0 0';
+
+ self.vehicle_energy = 1;
+ self.vehicle_hudmodel.viewmodelforclient = self;
+
+ setorigin(self, self.pos1);
+ self.angles = self.pos2;
+
+ setsize(self,RAPTOR_MIN ,RAPTOR_MAX );
+ pointparticles(particleeffectnum("teleport"), self.origin + '0 0 64', '0 0 0', 1);
+ self.delay = time;
+}
+
+float raptor_customizeentityforclient()
+{
+ if(self.deadflag == DEAD_DEAD)
+ return FALSE;
+
+ /*
+ if(other == self.owner)
+ self.alpha = -1;
+ else
+ self.alpha = 1;
+ */
+
+ return TRUE;
+}
+
+void raptor_dinit()
+{
+
+ if (self.netname == "")
+ self.netname = "Raptor";
+
+ setorigin(self, self.origin);
+
+ self.frame = 0;
+
+ setmodel(self,"models/vehicles/raptor.dpm");
+
+ self.bomb1 = spawn();
+ self.bomb2 = spawn();
+
+ setmodel(self.bomb1,"models/vehicles/raptor_bomb.dpm");
+ setmodel(self.bomb2,"models/vehicles/raptor_bomb.dpm");
+
+ setattachment(self.bomb1, self,"bombmount_left");
+ setattachment(self.bomb2, self,"bombmount_right");
+
+
+ if not (self.vehicle_hudmodel)
+ {
+ self.vehicle_hudmodel = spawn();
+ setmodel(self.vehicle_hudmodel, "models/vehicles/raptor_cockpit.dpm");
+ //setattachment(self.vehicle_hudmodel, self, "tag_viewport");
+ setattachment(self.vehicle_hudmodel, self, "tag_hud");
+ }
+
+ if not (self.vehicle_viewport)
+ {
+ self.vehicle_viewport = spawn();
+ setmodel (self.vehicle_viewport, "null");
+ setattachment(self.vehicle_viewport, self.vehicle_hudmodel, "tag_camera");
+ }
+
+ if not (self.gun1)
+ {
+ self.gun1 = spawn();
+ setmodel(self.gun1, "models/vehicles/raptor_gun.dpm");
+ setattachment(self.gun1, self, "gunmount_left");
+ }
+
+ if not (self.gun2)
+ {
+ self.gun2 = spawn();
+ setmodel(self.gun2, "models/vehicles/raptor_gun.dpm");
+ setattachment(self.gun2, self, "gunmount_right");
+ }
+
+ self.tur_head = spawn();
+ self.pos1 = self.origin;
+ self.pos2 = self.angles;
+
+ self.vehicle_hudmodel.viewmodelforclient = self;
+ self.customizeentityforclient = raptor_customizeentityforclient;
+
+ self.vehicle_die = raptor_die;
+ self.vehicle_exit = raptor_exit;
+
+
+ entity spinner;
+ spinner = spawn();
+ spinner.owner = self;
+ setmodel(spinner,"models/vehicles/spinner.dpm");
+ setattachment(spinner, self, "engine_left");
+ spinner.movetype = MOVETYPE_NOCLIP;
+ spinner.avelocity = '0 90 0';
+
+ spinner = spawn();
+ spinner.owner = self;
+ setmodel(spinner,"models/vehicles/spinner.dpm");
+ setattachment(spinner, self, "engine_right");
+ spinner.movetype = MOVETYPE_NOCLIP;
+ spinner.avelocity = '0 -90 0';
+
+ addstat(STAT_HUD, AS_INT, hud);
+ addstat(STAT_VEHICLESTAT_HEALTH, AS_FLOAT, vehicle_health);
+ addstat(STAT_VEHICLESTAT_SHIELD, AS_FLOAT, vehicle_shield);
+ addstat(STAT_VEHICLESTAT_ENERGY, AS_FLOAT, vehicle_energy);
+
+ addstat(STAT_VEHICLESTAT_AMMO1, AS_INT, vehicle_ammo1);
+ addstat(STAT_VEHICLESTAT_RELOAD1, AS_FLOAT, vehicle_reload1);
+
+ addstat(STAT_VEHICLESTAT_AMMO2, AS_INT, vehicle_ammo2);
+ addstat(STAT_VEHICLESTAT_RELOAD2, AS_FLOAT, vehicle_reload2);
+
+ raptor_spawn();
+}
+
+void spawnfunc_vehicle_raptor2()
+{
+ self.cvar_basename = "g_vehicle_raptor";
+ raptor_loadsettings();
+
+ self.vehicle_flags = VHF_HASSHIELD | VHF_SHIELDREGEN;
+
+ traceline(self.origin, self.origin - '0 0 2048', MOVE_WORLDONLY, self);
+ if(trace_startsolid)
+ {
+ dprint("WARNING: vehicle_raptor placed in solid\n");
+ traceline(self.origin + '0 0 512' ,self.origin - '0 0 2048',MOVE_WORLDONLY,self);
+ if(trace_startsolid || trace_fraction == 1.0)
+ {
+ dprint("ERROR: vehicle_raptor placed in more then 512 units into solid\n");
+ remove(self);
+ return;
+ }
+ }
+
+ if(trace_fraction != 1.0)
+ setorigin(self,trace_endpos + '0 0 8');
+ else
+ dprint("WARNING: vehicle_racer placed more then 2048 units above ground.\n");
+
+ precache_model ("models/vehicles/raptor.dpm");
+ precache_model ("models/vehicles/raptor_gun.dpm");
+ precache_model ("models/vehicles/spinner.dpm");
+ precache_model ("models/vehicles/raptor_cockpit.dpm");
+ precache_model ("models/vehicles/raptor_bomb.dpm");
+
+
+ self.think = raptor_dinit;
+ self.nextthink = time + 1;
+}
+
+
+void spawnfunc_vehicle_raptor()
+{
+ entity iqm,dpm,md3;
+
+ precache_model ("models/vehicles/test.iqm");
+ precache_model ("models/vehicles/test.dpm");
+ precache_model ("models/vehicles/test.md3");
+
+ iqm = spawn();
+ dpm = spawn();
+ md3 = spawn();
+ iqm.scale = md3.scale = dpm.scale = 10;
+
+ //setmodel(iqm,"models/vehicles/test.iqm");
+ //setmodel(dpm,"models/vehicles/test.dpm");
+ setmodel(md3,"models/vehicles/test.md3");
+
+ setorigin(iqm, self.origin + '0 0 16');
+ setorigin(dpm, self.origin + '0 20 32');
+ setorigin(iqm, self.origin + '0 40 48');
+}
spiderbot_rocket_explode();
}
-void spiderbot_rocket_guided()
+void spiderbot_rocket_unguided()
{
vector newdir,olddir;
self.nextthink = time;
- if (self.owner.deadflag != DEAD_NO || self.cnt < time)
- {
- spiderbot_rocket_explode();
- return;
- }
- if not (self.owner.vehicle)
- {
- UpdateCSQCProjectile(self);
- return;
- }
olddir = normalize(self.velocity);
- crosshair_trace(self.owner);
- newdir = normalize(trace_endpos - self.origin) + randomvec() * cvar("g_vehicle_spiderbot_rocket_noise");
+ newdir = normalize(self.pos1 - self.origin) + randomvec() * cvar("g_vehicle_spiderbot_rocket_noise");
self.velocity = normalize(olddir + newdir * cvar("g_vehicle_spiderbot_rocket_turnrate")) * cvar("g_vehicle_spiderbot_rocket_speed");
UpdateCSQCProjectile(self);
+
+ if (self.owner.deadflag != DEAD_NO || self.cnt < time)
+ spiderbot_rocket_explode();
+
}
-void spiderbot_rocket_unguided()
+void spiderbot_rocket_guided()
{
- vector newdir,olddir;
+ vector newdir, olddir;
self.nextthink = time;
- if (self.owner.deadflag != DEAD_NO || self.cnt < time)
- {
- spiderbot_rocket_explode();
- return;
- }
if not (self.owner.vehicle)
- {
- UpdateCSQCProjectile(self);
- return;
- }
+ self.think = spiderbot_rocket_unguided;
+ crosshair_trace(self.owner);
olddir = normalize(self.velocity);
- newdir = normalize(self.pos1 - self.origin) + randomvec() * cvar("g_vehicle_spiderbot_rocket_noise");
+ newdir = normalize(trace_endpos - self.origin) + randomvec() * cvar("g_vehicle_spiderbot_rocket_noise");
self.velocity = normalize(olddir + newdir * cvar("g_vehicle_spiderbot_rocket_turnrate")) * cvar("g_vehicle_spiderbot_rocket_speed");
UpdateCSQCProjectile(self);
-}
+ if (self.owner.deadflag != DEAD_NO || self.cnt < time)
+ spiderbot_rocket_explode();
+}
void spiderbot_rocket_damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
{
return;
}
}
-#define SBS_IDLE 0
-#define SBS_JUMP 1
-#define SBS_WALK 2
-#define SBS_BACK 3
-#define SBS_LEFT 4
-#define SBS_RIGHT 5
-.float state;
float spiderbot_pplug()
{
entity player,spider;
float ftmp;
+ if not (self.owner)
+ {
+ }
+
player = self;
spider = self.vehicle;
self = spider;
if(spider.flags & FL_ONGROUND)
{
- if(player.BUTTON_JUMP)
+ if(player.BUTTON_JUMP && self.tur_head.wait < time)
{
+ self.tur_head.wait = time + 2;
player.BUTTON_JUMP = 0;
spider.velocity = v_forward * 700 + v_up * 600;
spider.frame = 4;
else
player.vehicle_reload2 = 1 - ((spider.gun2.cnt - time) / spider.attack_finished_single);
- //setorigin(spider,spider.origin);
setorigin(player,spider.origin + '0 0 64');
player.velocity = spider.velocity;
void spiderbot_think()
{
if(self.flags & FL_ONGROUND)
- {
movelib_beak_simple(cvar("g_vehicle_spiderbot_speed_stop"));
- //movelib_groundalign4point(300,100);
- }
self.nextthink = time;
}
setsize(self,spiderbot_MIN,spiderbot_MAX);
+ self.owner = world;
self.velocity = '0 0 0';
self.vehicle_health = CCVAR("_health");
self.vehicle_shield = CCVAR("_shield");
.entity vehicle_viewport;
.entity vehicle_hudmodel;
-.float anim_start;
-.float anim_end;
+//.float anim_start;
+//.float anim_end;
.float dmg_time;
//var .float(float message) vehicle_message;
#include "vehicles.qc"
+
#include "spiderbot.qc"
#include "racer.qc"
+#include "raptor.qc"
#endif
#include "w_tuba.qc"
#include "w_campingrifle.qc"
#include "w_fireball.qc"
+#include "w_seeker.qc"
w_ready();
}
-void W_CampingRifle_Reload()
+float W_CampingRifle_Reload()
{
float t;
W_CampingRifle_CheckMaxBullets(TRUE);
- if (self.campingrifle_bulletcounter >= cvar("g_balance_campingrifle_magazinecapacity"))
- return;
- if(self.ammo_nails < min(cvar("g_balance_campingrifle_primary_ammo"), cvar("g_balance_campingrifle_secondary_ammo")))
+ if(self.ammo_nails < min(cvar("g_balance_campingrifle_primary_ammo"), cvar("g_balance_campingrifle_secondary_ammo"))) // when we get here, bulletcounter must be 0 or -1
{
+ print("cannot reload... not enough bullets\n");
self.campingrifle_bulletcounter = -1; // reload later
- return;
+ W_SwitchToOtherWeapon(self);
+ return 0;
}
+ if (self.campingrifle_bulletcounter >= cvar("g_balance_campingrifle_magazinecapacity"))
+ return 0;
+
if (self.weaponentity)
{
if (self.weaponentity.wframe == WFRAME_RELOAD)
- return;
+ return 0;
// allow to switch away while reloading, but this will cause a new reload!
self.weaponentity.state = WS_READY;
weapon_thinkf(WFRAME_RELOAD, cvar("g_balance_campingrifle_reloadtime"), W_CampingRifle_ReloadedAndReady);
self.campingrifle_bulletcounter = -1;
+
+ return 1;
}
void W_CampingRifle_CheckReloadAndReady()
{
w_ready();
- if (self.campingrifle_bulletcounter <= 0)
- W_CampingRifle_Reload();
- else
- w_ready();
+ if(self.campingrifle_bulletcounter <= 0)
+ if(W_CampingRifle_Reload())
+ return;
}
void W_CampingRifle_FireBullet(float pSpread, float pDamage, float pHeadshotAddedDamage, float pForce, float pSpeed, float pLifetime, float pAmmo, float deathtype, float pBulletConstant)
weapon_defaultspawnfunc(WEP_CAMPINGRIFLE);
}
+.void(void) campingrifle_bullethail_attackfunc;
+.float campingrifle_bullethail_frame;
+.float campingrifle_bullethail_animtime;
+.float campingrifle_bullethail_refire;
+void W_CampingRifle_BulletHail_Continue()
+{
+ float r, sw, af;
+ W_CampingRifle_CheckReloadAndReady();
+ if(self.campingrifle_bulletcounter < 0)
+ return; // reloading, so we are done
+ sw = self.switchweapon; // make it not detect weapon changes as reason to abort firing
+ af = ATTACK_FINISHED(self);
+ self.switchweapon = self.weapon;
+ ATTACK_FINISHED(self) = time;
+ print(ftos(self.ammo_nails), "\n");
+ r = weapon_prepareattack(self.campingrifle_bullethail_frame == WFRAME_FIRE2, self.campingrifle_bullethail_refire);
+ if(self.switchweapon == self.weapon)
+ self.switchweapon = sw;
+ if(r)
+ {
+ self.campingrifle_bullethail_attackfunc();
+ weapon_thinkf(self.campingrifle_bullethail_frame, self.campingrifle_bullethail_animtime, W_CampingRifle_BulletHail_Continue);
+ print("thinkf set\n");
+ }
+ else
+ {
+ ATTACK_FINISHED(self) = af; // reset attack_finished if we didn't fire, so the last shot enforces the refire time
+ print("out of ammo... ", ftos(self.weaponentity.state), "\n");
+ }
+}
+
+void W_CampingRifle_BulletHail(float mode, void(void) AttackFunc, float fr, float animtime, float refire)
+{
+ // if we get here, we have at least one bullet to fire
+ AttackFunc();
+ if(mode)
+ {
+ // continue hail
+ self.campingrifle_bullethail_attackfunc = AttackFunc;
+ self.campingrifle_bullethail_frame = fr;
+ self.campingrifle_bullethail_animtime = animtime;
+ self.campingrifle_bullethail_refire = refire;
+ weapon_thinkf(fr, animtime, W_CampingRifle_BulletHail_Continue);
+ }
+ else
+ {
+ // just one shot
+ weapon_thinkf(fr, animtime, W_CampingRifle_CheckReloadAndReady);
+ }
+}
+
.float bot_secondary_campingriflemooth;
float w_campingrifle(float req)
{
{
self.campingrifle_accumulator = bound(time - cvar("g_balance_campingrifle_bursttime"), self.campingrifle_accumulator, time);
if (self.BUTTON_ATCK)
+ if (weapon_prepareattack_check(0, cvar("g_balance_campingrifle_primary_refire")))
if (time >= self.campingrifle_accumulator + cvar("g_balance_campingrifle_primary_burstcost"))
- if (weapon_prepareattack(0, cvar("g_balance_campingrifle_primary_refire")))
{
- W_CampingRifle_Attack();
- weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_campingrifle_primary_animtime"), W_CampingRifle_CheckReloadAndReady);
+ weapon_prepareattack_do(0, cvar("g_balance_campingrifle_primary_refire"));
+ W_CampingRifle_BulletHail(cvar("g_balance_campingrifle_primary_bullethail"), W_CampingRifle_Attack, WFRAME_FIRE1, cvar("g_balance_campingrifle_primary_animtime"), cvar("g_balance_campingrifle_primary_refire"));
self.campingrifle_accumulator += cvar("g_balance_campingrifle_primary_burstcost");
}
if (self.BUTTON_ATCK2)
+ if (weapon_prepareattack_check(1, cvar("g_balance_campingrifle_secondary_refire")))
if (time >= self.campingrifle_accumulator + cvar("g_balance_campingrifle_secondary_burstcost"))
- if (weapon_prepareattack(1, cvar("g_balance_campingrifle_secondary_refire")))
{
- W_CampingRifle_Attack2();
- weapon_thinkf(WFRAME_FIRE2, cvar("g_balance_campingrifle_secondary_animtime"), W_CampingRifle_CheckReloadAndReady);
+ weapon_prepareattack_do(1, cvar("g_balance_campingrifle_secondary_refire"));
+ W_CampingRifle_BulletHail(cvar("g_balance_campingrifle_secondary_bullethail"), W_CampingRifle_Attack2, WFRAME_FIRE2, cvar("g_balance_campingrifle_secondary_animtime"), cvar("g_balance_campingrifle_primary_refire"));
self.campingrifle_accumulator += cvar("g_balance_campingrifle_secondary_burstcost");
}
}
{
precache_model ("models/weapons/g_campingrifle.md3");
precache_model ("models/weapons/v_campingrifle.md3");
- precache_model ("models/weapons/h_campingrifle.dpm");
+ precache_model ("models/weapons/h_campingrifle.iqm");
precache_sound ("weapons/campingrifle_reload.wav");
precache_sound ("weapons/campingrifle_fire.wav");
precache_sound ("weapons/campingrifle_fire2.wav");
return TRUE;
};
#endif
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0Ç[\7f\90Kg|º^fÆ,9Þ@ª w_deathtypestring = "sniped themself somehow";
- }
- else if (req == WR_KILLMESSAGE)
- {
- if(w_deathtype & HITTYPE_SECONDARY)
- {
- if(w_deathtype & HITTYPE_BOUNCE)
- w_deathtypestring = "failed to hide from #'s bullet hail";
- else
- w_deathtypestring = "died in #'s bullet hail";
- }
- else
- {
- if(w_deathtype & HITTYPE_BOUNCE)
- {
- // TODO special headshot message here too?
- w_deathtypestring = "failed to hide from #'s rifle";
- }
- else
- {
- if(w_deathtype & HITTYPE_HEADSHOT)
- w_deathtypestring = "got hit in the head by #";
- else
- w_deathtypestring = "was sniped by #";
- }
- }
- }
- else if (req == WR_RELOAD)
- {
- W_CampingRifle_Reload();
- }
- else if (req == WR_RESETPLAYER)
- {
- self.campingrifle_accumulator = time - cvar("g_balance_campingrifle_bursttime");
- self.campingrifle_bulletcounter = cvar("g_balance_campingrifle_magazinecapacity");
- W_CampingRifle_CheckMaxBullets(FALSE);
- }
- return TRUE;
-};
-#endif
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\11tì\87{³\vÃo¸?~á\85\17Ñ w_deathtypestring = "sniped themself somehow";
- }
- else if (req == WR_KILLMESSAGE)
- {
- if(w_deathtype & HITTYPE_SECONDARY)
- {
- if(w_deathtype & HITTYPE_BOUNCE)
- w_deathtypestring = "failed to hide from #'s bullet hail";
- else
- w_deathtypestring = "died in #'s bullet hail";
- }
- else
- {
- if(w_deathtype & HITTYPE_BOUNCE)
- {
- // TODO special headshot message here too?
- w_deathtypestring = "failed to hide from #'s rifle";
- }
- else
- {
- if(w_deathtype & HITTYPE_HEADSHOT)
- w_deathtypestring = "got hit in the head by #";
- else
- w_deathtypestring = "was sniped by #";
- }
- }
- }
- else if (req == WR_RELOAD)
- {
- W_CampingRifle_Reload();
- }
- else if (req == WR_RESETPLAYER)
- {
- self.campingrifle_accumulator = time - cvar("g_balance_campingrifle_bursttime");
- self.campingrifle_bulletcounter = cvar("g_balance_campingrifle_magazinecapacity");
- W_CampingRifle_CheckMaxBullets(FALSE);
- }
- return TRUE;
-};
-#endif
-\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0
\ No newline at end of file
+
void W_GiveWeapon (entity e, float wep, string name)
{
entity oldself;
void W_BallisticBullet_Touch (void)
{
+ float density;
+
if(self.think == W_BallisticBullet_LeaveSolid_think) // skip this!
return;
PROJECTILE_TOUCH;
W_BallisticBullet_Hit ();
+ density = other.ballistics_density;
+ if(density == 0)
+ density = 1;
+
// go through solid!
- if(!W_BallisticBullet_LeaveSolid(self, self.velocity, self.dmg_radius))
+ if(!W_BallisticBullet_LeaveSolid(self, self.velocity, self.dmg_radius * density))
{
remove(self);
return;
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)
{
- float lag, dt, savetime;
+ float lag, dt, savetime, density;
entity pl, oldself;
entity proj;
W_BallisticBullet_Hit();
}
+ density = other.ballistics_density;
+ if(density == 0)
+ density = 1;
+
// go through solid!
- if(!W_BallisticBullet_LeaveSolid(self, self.velocity, self.dmg_radius))
+ if(!W_BallisticBullet_LeaveSolid(self, self.velocity, self.dmg_radius * density))
break;
W_BallisticBullet_LeaveSolid_think();
{
precache_model ("models/weapons/g_crylink.md3");
precache_model ("models/weapons/v_crylink.md3");
- precache_model ("models/weapons/h_crylink.dpm");
+ precache_model ("models/weapons/h_crylink.iqm");
precache_sound ("weapons/crylink_fire.wav");
precache_sound ("weapons/crylink_fire2.wav");
}
void W_Plasma_Explode_Combo (void)
{
-
W_Plasma_TriggerCombo(self.origin, cvar("g_balance_electro_combo_comboradius"), self.owner);
self.event_damage = SUB_Null;
else
{
self.use = W_Plasma_Explode;
- self.think = adaptor_think2use;
+ self.think = adaptor_think2use; // not _hittype_splash, as this runs "immediately"
}
}
}
proj.bot_dodge = TRUE;
proj.bot_dodgerating = cvar("g_balance_electro_primary_damage");
proj.use = W_Plasma_Explode;
- proj.think = adaptor_think2use;
+ proj.think = adaptor_think2use_hittype_splash;
proj.nextthink = time + cvar("g_balance_electro_primary_lifetime");
PROJECTILE_MAKETRIGGER(proj);
proj.projectiledeathtype = WEP_ELECTRO;
proj.classname = "plasma";
proj.owner = self;
proj.use = W_Plasma_Explode;
- proj.think = adaptor_think2use;
+ proj.think = adaptor_think2use_hittype_splash;
proj.bot_dodge = TRUE;
proj.bot_dodgerating = cvar("g_balance_electro_secondary_damage");
proj.nextthink = time + cvar("g_balance_electro_secondary_lifetime");
{
precache_model ("models/weapons/g_electro.md3");
precache_model ("models/weapons/v_electro.md3");
- precache_model ("models/weapons/h_electro.dpm");
+ precache_model ("models/weapons/h_electro.iqm");
precache_sound ("weapons/electro_bounce.wav");
precache_sound ("weapons/electro_fire.wav");
precache_sound ("weapons/electro_fire2.wav");
#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(FIREBALL, w_fireball, IT_ROCKETS, 9, WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "fireball", "fireball", "Fireball");
+REGISTER_WEAPON(FIREBALL, w_fireball, IT_FUEL, 9, WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "fireball", "fireball", "Fireball");
#else
-.float bot_secondary_fireballmooth; // whatever a mooth is
+.float bot_primary_fireballmooth; // whatever a mooth is
.vector fireball_impactvec;
-.float fireball_secondarytime;
+.float fireball_primarytime;
void W_Fireball_Explode (void)
{
// 1. dist damage
d = (self.owner.health + self.owner.armorvalue);
- RadiusDamage (self, self.realowner, cvar("g_balance_fireball_secondary_damage"), cvar("g_balance_fireball_secondary_edgedamage"), cvar("g_balance_fireball_secondary_radius"), world, cvar("g_balance_fireball_secondary_force"), self.projectiledeathtype, other);
+ RadiusDamage (self, self.realowner, cvar("g_balance_fireball_primary_damage"), cvar("g_balance_fireball_primary_edgedamage"), cvar("g_balance_fireball_primary_radius"), world, cvar("g_balance_fireball_primary_force"), self.projectiledeathtype, other);
if(self.realowner.health + self.realowner.armorvalue >= d)
if(!self.cnt)
{
- modeleffect_spawn("models/sphere/sphere.md3", 0, 0, self.origin, '0 0 0', '0 0 0', '0 0 0', 0, cvar("g_balance_fireball_secondary_bfgradius"), 0.2, 0.05, 0.25);
+ modeleffect_spawn("models/sphere/sphere.md3", 0, 0, self.origin, '0 0 0', '0 0 0', '0 0 0', 0, cvar("g_balance_fireball_primary_bfgradius"), 0.2, 0.05, 0.25);
// 2. bfg effect
// NOTE: this cannot be made warpzone aware by design. So, better intentionally ignore warpzones here.
- for(e = findradius(self.origin, cvar("g_balance_fireball_secondary_bfgradius")); e; e = e.chain)
+ for(e = findradius(self.origin, cvar("g_balance_fireball_primary_bfgradius")); e; e = e.chain)
if(e != self.owner) if(e.takedamage == DAMAGE_AIM) if(e.classname != "player" || !self.owner || IsDifferentTeam(e, self))
{
// can we see fireball?
if(/* trace_startsolid || */ trace_fraction != 1)
continue;
dist = vlen(self.origin - e.origin - e.view_ofs);
- points = (1 - sqrt(dist / cvar("g_balance_fireball_secondary_bfgradius")));
+ points = (1 - sqrt(dist / cvar("g_balance_fireball_primary_bfgradius")));
if(points <= 0)
continue;
dir = normalize(e.origin + e.view_ofs - self.origin);
- Damage(e, self, self.realowner, cvar("g_balance_fireball_secondary_bfgdamage") * points, self.projectiledeathtype | HITTYPE_BOUNCE | HITTYPE_SPLASH, e.origin + e.view_ofs, cvar("g_balance_fireball_secondary_bfgforce") * dir);
+ Damage(e, self, self.realowner, cvar("g_balance_fireball_primary_bfgdamage") * points, self.projectiledeathtype | HITTYPE_BOUNCE | HITTYPE_SPLASH, e.origin + e.view_ofs, cvar("g_balance_fireball_primary_bfgforce") * dir);
pointparticles(particleeffectnum("fireball_bfgdamage"), e.origin, -1 * dir, 1);
- Damage_RecordDamage(self.owner, self.projectiledeathtype, cvar("g_balance_fireball_secondary_bfgdamage") * points);
+ Damage_RecordDamage(self.owner, self.projectiledeathtype, cvar("g_balance_fireball_primary_bfgdamage") * points);
}
}
if(time > self.pushltime)
{
self.cnt = 1;
+ self.projectiledeathtype |= HITTYPE_SPLASH;
W_Fireball_Explode();
return;
}
- W_Fireball_LaserPlay(0.1, cvar("g_balance_fireball_secondary_laserradius"), cvar("g_balance_fireball_secondary_laserdamage"), cvar("g_balance_fireball_secondary_laseredgedamage"), cvar("g_balance_fireball_secondary_laserburntime"));
+ W_Fireball_LaserPlay(0.1, cvar("g_balance_fireball_primary_laserradius"), cvar("g_balance_fireball_primary_laserdamage"), cvar("g_balance_fireball_primary_laseredgedamage"), cvar("g_balance_fireball_primary_laserburntime"));
self.nextthink = time + 0.1;
}
}
}
-void W_Fireball_Attack2()
+void W_Fireball_Attack1()
{
local entity proj;
- W_SetupShot_ProjectileSize (self, '-16 -16 -16', '16 16 16', FALSE, 2, "weapons/fireball_fire2.wav", cvar("g_balance_fireball_secondary_damage") + cvar("g_balance_fireball_secondary_bfgdamage"));
+ W_SetupShot_ProjectileSize (self, '-16 -16 -16', '16 16 16', FALSE, 2, "weapons/fireball_fire2.wav", cvar("g_balance_fireball_primary_damage") + cvar("g_balance_fireball_primary_bfgdamage"));
pointparticles(particleeffectnum("fireball_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
proj.classname = "plasma_prim";
proj.owner = proj.realowner = self;
proj.bot_dodge = TRUE;
- proj.bot_dodgerating = cvar("g_balance_fireball_secondary_damage");
- proj.pushltime = time + cvar("g_balance_fireball_secondary_lifetime");
+ proj.bot_dodgerating = cvar("g_balance_fireball_primary_damage");
+ proj.pushltime = time + cvar("g_balance_fireball_primary_lifetime");
proj.use = W_Fireball_Explode;
proj.think = W_Fireball_Think;
proj.nextthink = time;
- proj.health = cvar("g_balance_fireball_secondary_health");
+ proj.health = cvar("g_balance_fireball_primary_health");
proj.team = self.team;
proj.event_damage = W_Fireball_Damage;
proj.takedamage = DAMAGE_YES;
- proj.damageforcescale = cvar("g_balance_fireball_secondary_damageforcescale");
+ proj.damageforcescale = cvar("g_balance_fireball_primary_damageforcescale");
PROJECTILE_MAKETRIGGER(proj);
- proj.projectiledeathtype = WEP_FIREBALL | HITTYPE_SECONDARY;
+ proj.projectiledeathtype = WEP_FIREBALL;
setorigin(proj, w_shotorg);
proj.movetype = MOVETYPE_FLY;
- W_SETUPPROJECTILEVELOCITY(proj, g_balance_fireball_secondary);
+ W_SETUPPROJECTILEVELOCITY(proj, g_balance_fireball_primary);
proj.angles = vectoangles(proj.velocity);
proj.touch = W_Fireball_TouchExplode;
setsize(proj, '-16 -16 -16', '16 16 16');
pointparticles(particleeffectnum("fireball_preattack_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
}
-void W_Fireball_Attack2_Frame4()
+void W_Fireball_Attack1_Frame4()
{
- W_Fireball_Attack2();
- weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_fireball_secondary_animtime"), w_ready);
+ W_Fireball_Attack1();
+ weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_fireball_primary_animtime"), w_ready);
}
-void W_Fireball_Attack2_Frame3()
+void W_Fireball_Attack1_Frame3()
{
W_Fireball_AttackEffect(0, '+1.25 +3.75 0');
- weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_fireball_secondary_animtime"), W_Fireball_Attack2_Frame4);
+ weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_fireball_primary_animtime"), W_Fireball_Attack1_Frame4);
}
-void W_Fireball_Attack2_Frame2()
+void W_Fireball_Attack1_Frame2()
{
W_Fireball_AttackEffect(0, '-1.25 +3.75 0');
- weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_fireball_secondary_animtime"), W_Fireball_Attack2_Frame3);
+ weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_fireball_primary_animtime"), W_Fireball_Attack1_Frame3);
}
-void W_Fireball_Attack2_Frame1()
+void W_Fireball_Attack1_Frame1()
{
W_Fireball_AttackEffect(1, '+1.25 -3.75 0');
- weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_fireball_secondary_animtime"), W_Fireball_Attack2_Frame2);
+ weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_fireball_primary_animtime"), W_Fireball_Attack1_Frame2);
}
-void W_Fireball_Attack2_Frame0()
+void W_Fireball_Attack1_Frame0()
{
if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
- self.ammo_rockets = self.ammo_rockets - cvar("g_balance_fireball_secondary_ammo");
+ self.ammo_fuel = self.ammo_fuel - cvar("g_balance_fireball_primary_ammo");
W_Fireball_AttackEffect(0, '-1.25 -3.75 0');
sound (self, CHAN_WEAPON, "weapons/fireball_prefire2.wav", VOL_BASE, ATTN_NORM);
- weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_fireball_secondary_animtime"), W_Fireball_Attack2_Frame1);
+ weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_fireball_primary_animtime"), W_Fireball_Attack1_Frame1);
}
void W_Firemine_Think()
// make it "hot" once it leaves its owner
if(self.owner)
{
- if(vlen(self.origin - self.owner.origin - self.owner.view_ofs) > cvar("g_balance_fireball_primary_laserradius"))
+ if(vlen(self.origin - self.owner.origin - self.owner.view_ofs) > cvar("g_balance_fireball_secondary_laserradius"))
{
self.cnt += 1;
if(self.cnt == 3)
self.cnt = 0;
}
- W_Fireball_LaserPlay(0.1, cvar("g_balance_fireball_primary_laserradius"), cvar("g_balance_fireball_primary_laserdamage"), cvar("g_balance_fireball_primary_laseredgedamage"), cvar("g_balance_fireball_primary_laserburntime"));
+ W_Fireball_LaserPlay(0.1, cvar("g_balance_fireball_secondary_laserradius"), cvar("g_balance_fireball_secondary_laserdamage"), cvar("g_balance_fireball_secondary_laseredgedamage"), cvar("g_balance_fireball_secondary_laserburntime"));
self.nextthink = time + 0.1;
}
{
PROJECTILE_TOUCH;
if (other.takedamage == DAMAGE_AIM)
- if(Fire_AddDamage(other, self.realowner, cvar("g_balance_fireball_primary_damage"), cvar("g_balance_fireball_primary_damagetime"), self.projectiledeathtype | HITTYPE_HEADSHOT) >= 0)
+ if(Fire_AddDamage(other, self.realowner, cvar("g_balance_fireball_secondary_damage"), cvar("g_balance_fireball_secondary_damagetime"), self.projectiledeathtype | HITTYPE_HEADSHOT) >= 0)
{
remove(self);
return;
self.projectiledeathtype |= HITTYPE_BOUNCE;
}
-void W_Fireball_Attack1()
+void W_Fireball_Attack2()
{
local entity proj;
vector f_diff;
float c;
if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
- self.ammo_rockets = self.ammo_rockets - cvar("g_balance_fireball_primary_ammo");
+ self.ammo_fuel = self.ammo_fuel - cvar("g_balance_fireball_secondary_ammo");
c = mod(self.bulletcounter, 4);
switch(c)
f_diff = '+1.25 +3.75 0';
break;
}
- W_SetupShot_ProjectileSize(self, '-4 -4 -4', '4 4 4', FALSE, 2, "weapons/fireball_fire.wav", cvar("g_balance_fireball_primary_damage"));
+ W_SetupShot_ProjectileSize(self, '-4 -4 -4', '4 4 4', FALSE, 2, "weapons/fireball_fire.wav", cvar("g_balance_fireball_secondary_damage"));
traceline(w_shotorg, w_shotorg + f_diff_x * v_up + f_diff_y * v_right, MOVE_NORMAL, self);
w_shotorg = trace_endpos;
proj.owner = proj.realowner = self;
proj.classname = "grenade";
proj.bot_dodge = TRUE;
- proj.bot_dodgerating = cvar("g_balance_fireball_primary_damage");
+ proj.bot_dodgerating = cvar("g_balance_fireball_secondary_damage");
proj.movetype = MOVETYPE_BOUNCE;
- proj.projectiledeathtype = WEP_FIREBALL;
+ proj.projectiledeathtype = WEP_FIREBALL | HITTYPE_SECONDARY;
proj.touch = W_Firemine_Touch;
PROJECTILE_MAKETRIGGER(proj);
setsize(proj, '-4 -4 -4', '4 4 4');
setorigin(proj, w_shotorg);
proj.think = W_Firemine_Think;
proj.nextthink = time;
- proj.damageforcescale = cvar("g_balance_fireball_primary_damageforcescale");
- proj.pushltime = time + cvar("g_balance_fireball_primary_lifetime");
- W_SETUPPROJECTILEVELOCITY_UP(proj, g_balance_fireball_primary);
+ proj.damageforcescale = cvar("g_balance_fireball_secondary_damageforcescale");
+ proj.pushltime = time + cvar("g_balance_fireball_secondary_lifetime");
+ W_SETUPPROJECTILEVELOCITY_UP(proj, g_balance_fireball_secondary);
proj.angles = vectoangles(proj.velocity);
proj.flags = FL_PROJECTILE;
{
self.BUTTON_ATCK = FALSE;
self.BUTTON_ATCK2 = FALSE;
- if (self.bot_secondary_fireballmooth == 0)
+ if (self.bot_primary_fireballmooth == 0)
{
- if(bot_aim(cvar("g_balance_fireball_primary_speed"), cvar("g_balance_fireball_primary_speed_up"), cvar("g_balance_fireball_primary_lifetime"), TRUE))
+ if(bot_aim(cvar("g_balance_fireball_primary_speed"), 0, cvar("g_balance_fireball_primary_lifetime"), FALSE))
{
self.BUTTON_ATCK = TRUE;
- if(random() < 0.01) self.bot_secondary_fireballmooth = 1;
+ if(random() < 0.02) self.bot_primary_fireballmooth = 0;
}
}
else
{
- if(bot_aim(cvar("g_balance_fireball_secondary_speed"), 0, cvar("g_balance_fireball_secondary_lifetime"), FALSE))
+ if(bot_aim(cvar("g_balance_fireball_secondary_speed"), cvar("g_balance_fireball_secondary_speed_up"), cvar("g_balance_fireball_secondary_lifetime"), TRUE))
{
self.BUTTON_ATCK2 = TRUE;
- if(random() < 0.02) self.bot_secondary_fireballmooth = 0;
+ if(random() < 0.01) self.bot_primary_fireballmooth = 1;
}
}
}
else if (req == WR_THINK)
{
if (self.BUTTON_ATCK)
- if (weapon_prepareattack(0, cvar("g_balance_fireball_primary_refire")))
+ if (time >= self.fireball_primarytime)
+ if (weapon_prepareattack(1, cvar("g_balance_fireball_primary_refire")))
{
- W_Fireball_Attack1();
- weapon_thinkf(WFRAME_FIRE2, cvar("g_balance_fireball_primary_animtime"), w_ready);
+ W_Fireball_Attack1_Frame0();
+ self.fireball_primarytime = time + cvar("g_balance_fireball_primary_refire2");
}
if (self.BUTTON_ATCK2)
- if (time >= self.fireball_secondarytime)
- if (weapon_prepareattack(1, cvar("g_balance_fireball_secondary_refire")))
+ if (weapon_prepareattack(0, cvar("g_balance_fireball_secondary_refire")))
{
- W_Fireball_Attack2_Frame0();
- self.fireball_secondarytime = time + cvar("g_balance_fireball_secondary_refire2");
+ W_Fireball_Attack2();
+ weapon_thinkf(WFRAME_FIRE2, cvar("g_balance_fireball_secondary_animtime"), w_ready);
}
}
else if (req == WR_PRECACHE)
{
precache_model ("models/weapons/g_fireball.md3");
precache_model ("models/weapons/v_fireball.md3");
- precache_model ("models/weapons/h_fireball.dpm");
+ precache_model ("models/weapons/h_fireball.iqm");
precache_model ("models/sphere/sphere.md3");
precache_sound ("weapons/fireball_fire.wav");
precache_sound ("weapons/fireball_fire2.wav");
else if (req == WR_SETUP)
weapon_setup(WEP_FIREBALL);
else if (req == WR_CHECKAMMO1)
- return self.ammo_rockets >= cvar("g_balance_fireball_primary_ammo");
+ return self.ammo_fuel >= cvar("g_balance_fireball_primary_ammo");
else if (req == WR_CHECKAMMO2)
- return self.ammo_rockets >= cvar("g_balance_fireball_secondary_ammo");
+ return self.ammo_fuel >= cvar("g_balance_fireball_secondary_ammo");
else if (req == WR_SUICIDEMESSAGE)
{
if(w_deathtype & HITTYPE_SECONDARY)
- w_deathtypestring = "should have used a smaller gun";
- else
w_deathtypestring = "forgot about some firemine";
+ else
+ w_deathtypestring = "should have used a smaller gun";
}
else if (req == WR_KILLMESSAGE)
{
if(w_deathtype & HITTYPE_SECONDARY)
+ {
+ if(w_deathtype & HITTYPE_HEADSHOT)
+ w_deathtypestring = "tried to catch #'s firemine";
+ else
+ w_deathtypestring = "fatefully ignored #'s firemine";
+ }
+ else
{
if(w_deathtype & HITTYPE_BOUNCE)
{
else
w_deathtypestring = "tasted #'s fireball";
}
- else
- {
- if(w_deathtype & HITTYPE_HEADSHOT)
- w_deathtypestring = "tried to catch #'s firemine";
- else
- w_deathtypestring = "fatefully ignored #'s firemine";
- }
}
else if (req == WR_RESETPLAYER)
{
- self.fireball_secondarytime = time;
+ self.fireball_primarytime = time;
}
return TRUE;
};
setsize(gren, '0 0 -3', '0 0 -3');
gren.nextthink = time + cvar("g_balance_grenadelauncher_primary_lifetime");
- gren.think = adaptor_think2use;
+ gren.think = adaptor_think2use_hittype_splash;
gren.use = W_Grenade_Explode;
gren.touch = W_Grenade_Touch1;
W_SETUPPROJECTILEVELOCITY_UP(gren, g_balance_grenadelauncher_primary);
gren.bot_dodge = TRUE;
gren.bot_dodgerating = cvar("g_balance_grenadelauncher_secondary_damage");
gren.movetype = MOVETYPE_BOUNCE;
+ gren.bouncefactor = cvar("g_balance_grenadelauncher_secondary_bouncefactor");
+ gren.bouncestop = cvar("g_balance_grenadelauncher_secondary_bouncestop");
PROJECTILE_MAKETRIGGER(gren);
gren.projectiledeathtype = WEP_GRENADE_LAUNCHER | HITTYPE_SECONDARY;
setsize(gren, '0 0 -3', '0 0 -3');
setorigin(gren, w_shotorg);
gren.nextthink = time + cvar("g_balance_grenadelauncher_secondary_lifetime");
- gren.think = adaptor_think2use;
+ gren.think = adaptor_think2use_hittype_splash;
gren.use = W_Grenade_Explode2;
gren.touch = W_Grenade_Touch2;
gren.takedamage = DAMAGE_YES;
{
precache_model ("models/weapons/g_gl.md3");
precache_model ("models/weapons/v_gl.md3");
- precache_model ("models/weapons/h_gl.dpm");
+ precache_model ("models/weapons/h_gl.iqm");
precache_sound ("weapons/grenade_bounce1.wav");
precache_sound ("weapons/grenade_bounce2.wav");
precache_sound ("weapons/grenade_bounce3.wav");
missile.bot_dodgerating = cvar("g_balance_hagar_primary_damage");
missile.touch = W_Hagar_Touch;
missile.use = W_Hagar_Explode;
- missile.think = adaptor_think2use;
+ missile.think = adaptor_think2use_hittype_splash;
missile.nextthink = time + cvar("g_balance_hagar_primary_lifetime");
PROJECTILE_MAKETRIGGER(missile);
missile.projectiledeathtype = WEP_HAGAR;
missile.touch = W_Hagar_Touch2;
missile.cnt = 0;
missile.use = W_Hagar_Explode2;
- missile.think = adaptor_think2use;
+ missile.think = adaptor_think2use_hittype_splash;
missile.nextthink = time + cvar("g_balance_hagar_secondary_lifetime_min") + random() * cvar("g_balance_hagar_secondary_lifetime_rand");
PROJECTILE_MAKETRIGGER(missile);
missile.projectiledeathtype = WEP_HAGAR | HITTYPE_SECONDARY;
{
precache_model ("models/weapons/g_hagar.md3");
precache_model ("models/weapons/v_hagar.md3");
- precache_model ("models/weapons/h_hagar.dpm");
+ precache_model ("models/weapons/h_hagar.iqm");
precache_sound ("weapons/hagar_fire.wav");
}
else if (req == WR_SETUP)
{
precache_model ("models/weapons/g_hlac.md3");
precache_model ("models/weapons/v_hlac.md3");
- precache_model ("models/weapons/h_hlac.dpm");
+ precache_model ("models/weapons/h_hlac.iqm");
precache_sound ("weapons/lasergun_fire.wav");
}
setsize(gren, '0 0 0', '0 0 0');
gren.nextthink = time + cvar("g_balance_hook_secondary_lifetime");
- gren.think = adaptor_think2use;
+ gren.think = adaptor_think2use_hittype_splash;
gren.use = W_Hook_Explode2;
gren.touch = W_Hook_Touch2;
{
precache_model ("models/weapons/g_hookgun.md3");
precache_model ("models/weapons/v_hookgun.md3");
- precache_model ("models/weapons/h_hookgun.dpm");
+ precache_model ("models/weapons/h_hookgun.iqm");
precache_sound ("weapons/hook_impact.wav"); // done by g_hook.qc
precache_sound ("weapons/hook_fire.wav");
precache_sound ("weapons/hookbomb_fire.wav");
{
precache_model ("models/weapons/g_laser.md3");
precache_model ("models/weapons/v_laser.md3");
- precache_model ("models/weapons/h_laser.dpm");
+ precache_model ("models/weapons/h_laser.iqm");
precache_sound ("weapons/lasergun_fire.wav");
precache_sound ("weapons/gauntlet_fire.wav");
}
precache_model ("models/nexflash.md3");
precache_model ("models/weapons/g_minstanex.md3");
precache_model ("models/weapons/v_minstanex.md3");
- precache_model ("models/weapons/h_minstanex.dpm");
+ precache_model ("models/weapons/h_minstanex.iqm");
precache_sound ("weapons/minstanexfire.wav");
precache_sound ("weapons/nexwhoosh1.wav");
precache_sound ("weapons/nexwhoosh2.wav");
precache_model ("models/nexflash.md3");
precache_model ("models/weapons/g_nex.md3");
precache_model ("models/weapons/v_nex.md3");
- precache_model ("models/weapons/h_nex.dpm");
+ precache_model ("models/weapons/h_nex.iqm");
precache_sound ("weapons/nexfire.wav");
precache_sound ("weapons/nexwhoosh1.wav");
precache_sound ("weapons/nexwhoosh2.wav");
{
precache_model ("models/weapons/g_porto.md3");
precache_model ("models/weapons/v_porto.md3");
- precache_model ("models/weapons/h_porto.dpm");
+ precache_model ("models/weapons/h_porto.iqm");
precache_model ("models/portal.md3");
precache_sound ("porto/bounce.wav");
precache_sound ("porto/create.wav");
precache_model ("models/flash.md3");
precache_model ("models/weapons/g_rl.md3");
precache_model ("models/weapons/v_rl.md3");
- precache_model ("models/weapons/h_rl.dpm");
+ precache_model ("models/weapons/h_rl.iqm");
precache_sound ("weapons/rocket_det.wav");
precache_sound ("weapons/rocket_fire.wav");
precache_sound ("weapons/rocket_mode.wav");
--- /dev/null
+#ifdef REGISTER_WEAPON
+REGISTER_WEAPON(SEEKER, w_seeker, IT_ROCKETS, 9, WEP_FLAG_NORMAL | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "seeker", "seeker", "T.A.G. Seeker");
+#else
+//.float speed; = switchweapon
+//.float proxytime; = autoswitch
+//.float tl; = wait
+
+void Seeker_Missile_Explode ()
+{
+ self.event_damage = SUB_Null;
+ RadiusDamage (self, self.owner, cvar("g_balance_seeker_missile_damage"), cvar("g_balance_seeker_missile_edgedamage"), cvar("g_balance_seeker_missile_radius"), world, cvar("g_balance_seeker_missile_force"), self.projectiledeathtype, other);
+
+ remove (self);
+}
+
+void Seeker_Missile_Touch()
+{
+ PROJECTILE_TOUCH;
+
+ Seeker_Missile_Explode();
+}
+
+void Seeker_Missile_Think()
+{
+ entity e;
+ vector desireddir, olddir, newdir, eorg;
+ float turnrate;
+ float dist;
+
+ if (time > self.cnt)
+ {
+ self.projectiledeathtype |= HITTYPE_SPLASH;
+ Seeker_Missile_Explode();
+ }
+
+ if (!self.switchweapon)
+ self.switchweapon = cvar("g_balance_seeker_missile_speed");
+
+ if ((self.switchweapon < cvar("g_balance_seeker_missile_speed_max")) && cvar("g_balance_seeker_missile_speed_accel"))
+ self.switchweapon = self.switchweapon * cvar("g_balance_seeker_missile_accel");
+
+ if (self.switchweapon > cvar("g_balance_seeker_missile_speed_max"))
+ self.switchweapon = self.switchweapon * cvar("g_balance_seeker_missile_decel");
+
+ if (self.enemy != world)
+ if (self.enemy.takedamage != DAMAGE_AIM || self.enemy.deadflag != DEAD_NO)
+ self.enemy = world;
+
+ if (self.enemy != world)
+ {
+ e = self.enemy;
+ eorg = 0.5 * (e.absmin + e.absmax);
+ turnrate = cvar("g_balance_seeker_missile_turnrate"); // how fast to turn
+ desireddir = normalize(eorg - self.origin);
+ olddir = normalize(self.velocity); // get my current direction
+ dist = vlen(eorg - self.origin);
+
+ // Do evasive maneuvers for world objects? ( this should be a cpu hog. :P )
+ if (cvar("g_balance_seeker_missile_smart") && (dist > cvar("g_balance_seeker_missile_smart_mindist")))
+ {
+ // Is it a better idea (shorter distance) to trace to the target itself?
+ if ( vlen(self.origin + olddir * self.wait) < dist)
+ traceline(self.origin, self.origin + olddir * self.wait, FALSE, self);
+ else
+ traceline(self.origin, eorg, FALSE, self);
+
+ // Setup adaptive tracelength
+ self.wait = vlen(self.origin - trace_endpos);
+ if (self.wait < cvar("g_balance_seeker_missile_smart_trace_min")) self.wait = cvar("g_balance_seeker_missile_smart_trace_min");
+ if (self.wait > cvar("g_balance_seeker_missile_smart_trace_max")) self.wait = cvar("g_balance_seeker_missile_smart_trace_max");
+
+ // Calc how important it is that we turn and add this to the desierd (enemy) dir.
+ desireddir = normalize(((trace_plane_normal * (1 - trace_fraction)) + (desireddir * trace_fraction)) * 0.5);
+ }
+
+ //newdir = normalize((olddir + desireddir * turnrate) * 0.5);// take the average of the 2 directions; not the best method but simple & easy
+ newdir = normalize(olddir + desireddir * turnrate);// take the average of the 2 directions; not the best method but simple & easy
+
+ self.velocity = newdir * self.switchweapon; // make me fly in the new direction at my flight speed
+ }
+
+ // Proxy
+ if (cvar("g_balance_seeker_missile_proxy"))
+ {
+ if ( dist <= cvar("g_balance_seeker_missile_proxy_maxrange"))
+ {
+ if (self.autoswitch == 0)
+ {
+ self.autoswitch = time + cvar("g_balance_seeker_missile_proxy_delay");
+ }
+ else
+ {
+ if (self.autoswitch <= time)
+ {
+ Seeker_Missile_Explode();
+ self.autoswitch = 0;
+ }
+ }
+ }
+ else
+ {
+ if (self.autoswitch != 0)
+ self.autoswitch = 0;
+ }
+ }
+ ///////////////
+
+ if (self.enemy.deadflag != DEAD_NO)
+ {
+ self.enemy = world;
+ self.cnt = time + 1 + (random() * 4);
+ self.nextthink = self.cnt;
+ return;
+ }
+
+ self.angles = vectoangles(self.velocity); // turn model in the new flight direction
+ self.nextthink = time + 0.05;
+
+ UpdateCSQCProjectile(self);
+}
+
+
+
+void Seeker_Missile_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+ float d;
+ d = damage;
+
+ if (self.health <= 0)
+ return;
+
+ if (self.owner == attacker)
+ d = d * 0.25;
+
+ self.health = self.health - d;
+
+ if (self.health <= 0)
+ W_PrepareExplosionByDamage(attacker, Seeker_Missile_Explode);
+}
+
+void Seeker_Missile_Animate()
+{
+ self.frame = self.frame +1;
+ self.nextthink = time + 0.05;
+
+ if (self.enemy != world)
+ if (self.enemy.takedamage != DAMAGE_AIM || self.enemy.deadflag != DEAD_NO)
+ self.enemy = world;
+
+ if(self.frame == 5)
+ {
+ self.think = Seeker_Missile_Think;
+ self.nextthink = time;// + cvar("g_balance_seeker_missile_activate_delay"); // cant dealy with csqc projectiles
+
+ if (cvar("g_balance_seeker_missile_proxy"))
+ self.movetype = MOVETYPE_BOUNCEMISSILE;
+ else
+ self.movetype = MOVETYPE_FLYMISSILE;
+ }
+
+ UpdateCSQCProjectile(self);
+}
+
+void Seeker_Fire_Missile(vector f_diff)
+{
+ local entity missile;
+
+ if not(self.owner.items & IT_UNLIMITED_WEAPON_AMMO)
+ self.ammo_rockets = self.ammo_rockets - cvar("g_balance_seeker_missile_ammo");
+
+ makevectors(self.v_angle);
+ W_SetupShot_ProjectileSize (self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/seeker_fire.wav", cvar("g_balance_seeker_missile_damage"));
+ w_shotorg += f_diff;
+ pointparticles(particleeffectnum("seeker_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+ //self.detornator = FALSE;
+
+ missile = spawn();
+ missile.owner = self;
+ missile.classname = "seeker_missile";
+ missile.bot_dodge = TRUE;
+ missile.bot_dodgerating = cvar("g_balance_seeker_missile_damage");
+
+ missile.think = Seeker_Missile_Animate;
+
+ //if (!cvar("g_balance_seeker_missile_proxy"))
+ missile.touch = Seeker_Missile_Touch;
+
+ missile.event_damage = Seeker_Missile_Damage;
+ missile.nextthink = time;// + 0.2;// + cvar("g_balance_seeker_missile_activate_delay");
+ missile.cnt = time + cvar("g_balance_seeker_missile_lifetime");
+ missile.enemy = self.enemy;
+ missile.solid = SOLID_BBOX;
+ missile.scale = 2;
+ missile.takedamage = DAMAGE_YES;
+ missile.health = cvar("g_balance_seeker_missile_health");
+ missile.damageforcescale = cvar("g_balance_seeker_missile_damageforcescale");
+ missile.projectiledeathtype = WEP_SEEKER;
+
+ setorigin (missile, w_shotorg);
+ setsize (missile, '-4 -4 -4', '4 4 4');
+
+
+ missile.movetype = MOVETYPE_FLYMISSILE;// MOVETYPE_TOSS;
+
+ missile.flags = FL_PROJECTILE;
+
+ W_SETUPPROJECTILEVELOCITY_UP(missile, g_balance_seeker_missile);
+
+ missile.switchweapon = vlen(missile.velocity);
+ missile.angles = vectoangles (missile.velocity);
+
+ CSQCProjectile(missile, FALSE, PROJECTILE_SEEKER, TRUE);
+}
+
+void Seeker_Vollycontroler_Think()
+{
+ float c;
+ entity oldself,oldenemy;
+ self.cnt = self.cnt - 1;
+
+ if((!(self.owner.items & IT_UNLIMITED_AMMO) && self.owner.ammo_rockets < cvar("g_balance_seeker_missile_ammo")) || (self.cnt <= -1) || (self.owner.deadflag != DEAD_NO))
+ {
+ remove(self);
+ return;
+ }
+
+ self.nextthink = time + cvar("g_balance_seeker_missile_delay");
+
+ oldself = self;
+ self = self.owner;
+
+ oldenemy = self.enemy;
+ self.enemy = oldself.enemy;
+
+ c = mod(oldself.cnt, 4);
+ switch(c)
+ {
+ case 0:
+ Seeker_Fire_Missile('-1.25 -3.75 0');
+ break;
+ case 1:
+ Seeker_Fire_Missile('+1.25 -3.75 0');
+ break;
+ case 2:
+ Seeker_Fire_Missile('-1.25 +3.75 0');
+ break;
+ case 3:
+ default:
+ Seeker_Fire_Missile('+1.25 +3.75 0');
+ break;
+ }
+
+ self.enemy = oldenemy;
+ self = oldself;
+}
+
+void Seeker_Tag_Explode ()
+{
+ //if(other==self.owner)
+ // return;
+ Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER | HITTYPE_BOUNCE, self);
+
+ remove (self);
+}
+
+void Seeker_Tag_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+ if (self.health <= 0)
+ return;
+ self.health = self.health - damage;
+ if (self.health <= 0)
+ Seeker_Tag_Explode();
+}
+
+void Seeker_Tag_Think()
+{
+ remove(self);
+ return;
+}
+
+void Seeker_Tag_Touch()
+{
+ vector dir;
+ vector org2;
+
+ dir = normalize (self.owner.origin - self.origin);
+ org2 = findbetterlocation (self.origin, 8);
+
+ te_knightspike(org2);
+
+ self.event_damage = SUB_Null;
+ Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER | HITTYPE_HEADSHOT, self);
+
+ if (other.takedamage == DAMAGE_AIM && other.deadflag == DEAD_NO)
+ {
+ entity e;
+ e = spawn();
+ e.cnt = cvar("g_balance_seeker_missile_count");
+ e.owner = self.owner;
+ e.enemy = other;
+ e.think = Seeker_Vollycontroler_Think;
+ e.nextthink = time;
+
+ //sprint(self.owner, "^1Target lock ^3[^7 ",other.netname, " ^3]^1 acquired - autofire activated.\n");
+ //sprint(other,"^1You are targeted!\n");
+
+ // stuffcmd(other,"play2 weapons/zany-alarm4.ogg\n");
+ // stuffcmd(self.owner, "play2 weapons/zany-lock4.ogg\n");
+ }
+
+ remove(self);
+ return;
+}
+
+
+
+void Seeker_Fire_Tag()
+{
+ local entity missile;
+ if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+ self.ammo_rockets = self.ammo_rockets - cvar("g_balance_seeker_tag_ammo");
+
+ W_SetupShot_ProjectileSize (self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/tag_fire.wav", 0);
+
+ missile = spawn();
+ missile.owner = self;
+ missile.classname = "seeker_tag";
+ missile.bot_dodge = TRUE;
+ missile.bot_dodgerating = 50;
+ missile.touch = Seeker_Tag_Touch;
+ missile.think = Seeker_Tag_Think;
+ missile.nextthink = time + cvar("g_balance_seeker_tag_lifetime");
+ missile.movetype = MOVETYPE_FLY;
+ missile.solid = SOLID_BBOX;
+ missile.owner = self;
+
+ missile.takedamage = DAMAGE_YES;
+ missile.event_damage = Seeker_Tag_Explode;
+ missile.health = cvar("g_balance_seeker_tag_health");
+ missile.damageforcescale = cvar("g_balance_seeker_tag_damageforcescale");
+
+ setorigin (missile, w_shotorg);
+ setsize (missile, '-2 -2 -2', '2 2 2');
+
+ missile.flags = FL_PROJECTILE;
+
+ missile.movetype = MOVETYPE_FLY;
+ W_SETUPPROJECTILEVELOCITY(missile, g_balance_seeker_tag);
+ missile.angles = vectoangles (missile.velocity);
+
+ CSQCProjectile(missile, TRUE, PROJECTILE_TAG, FALSE); // has sound
+}
+
+
+void Seeker_Flac_Explode ()
+{
+ self.event_damage = SUB_Null;
+
+ RadiusDamage (self, self.owner, cvar("g_balance_seeker_flac_damage"), cvar("g_balance_seeker_flac_edgedamage"), cvar("g_balance_seeker_flac_radius"), world, cvar("g_balance_seeker_flac_force"), self.projectiledeathtype, other);
+
+ remove (self);
+}
+
+void Seeker_Flac_Touch()
+{
+ PROJECTILE_TOUCH;
+
+ Seeker_Flac_Explode();
+}
+
+void Seeker_Fire_Flac()
+{
+ local entity missile;
+ vector f_diff;
+ float c;
+
+ if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+ self.ammo_rockets = self.ammo_rockets - cvar("g_balance_seeker_flac_ammo");
+
+ c = mod(self.bulletcounter, 4);
+ switch(c)
+ {
+ case 0:
+ f_diff = '-1.25 -3.75 0';
+ break;
+ case 1:
+ f_diff = '+1.25 -3.75 0';
+ break;
+ case 2:
+ f_diff = '-1.25 +3.75 0';
+ break;
+ case 3:
+ default:
+ f_diff = '+1.25 +3.75 0';
+ break;
+ }
+ W_SetupShot_ProjectileSize (self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/flac_fire.wav", cvar("g_balance_seeker_flac_damage"));
+ w_shotorg += f_diff;
+
+ pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+ missile = spawn ();
+ missile.owner = missile.realowner = self;
+ missile.classname = "missile";
+ missile.bot_dodge = TRUE;
+ missile.bot_dodgerating = cvar("g_balance_seeker_flac_damage");
+ missile.touch = Seeker_Flac_Explode;
+ missile.use = Seeker_Flac_Explode;
+ missile.think = adaptor_think2use_hittype_splash;
+ missile.nextthink = time + cvar("g_balance_seeker_flac_lifetime") + cvar("g_balance_seeker_flac_lifetime_rand");
+ missile.solid = SOLID_BBOX;
+ missile.scale = 0.4; // BUG: the model is too big
+ missile.projectiledeathtype = WEP_SEEKER;
+ setorigin (missile, w_shotorg);
+ setsize (missile, '-2 -2 -2', '2 2 2');
+ missile.projectiledeathtype = WEP_SEEKER | HITTYPE_SECONDARY;
+
+ missile.movetype = MOVETYPE_FLY;
+ W_SETUPPROJECTILEVELOCITY_UP(missile, g_balance_seeker_flac);
+
+ missile.angles = vectoangles (missile.velocity);
+ missile.flags = FL_PROJECTILE;
+
+ CSQCProjectile(missile, TRUE, PROJECTILE_FLAC, TRUE);
+}
+
+void spawnfunc_weapon_seeker (void)
+{
+ weapon_defaultspawnfunc(WEP_SEEKER);
+}
+
+float w_seeker(float req)
+{
+ if (req == WR_AIM)
+ self.BUTTON_ATCK = bot_aim(cvar("g_balance_seeker_tag_speed"), 0, 20, FALSE);
+
+ else if (req == WR_THINK)
+ {
+ if (self.BUTTON_ATCK)
+ if (weapon_prepareattack(0, cvar("g_balance_seeker_tag_refire")))
+ {
+ Seeker_Fire_Tag();
+ weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_seeker_tag_animtime"), w_ready);
+ }
+
+ if (self.BUTTON_ATCK2)
+ if (weapon_prepareattack(1, cvar("g_balance_seeker_flac_refire")))
+ {
+ Seeker_Fire_Flac();
+ weapon_thinkf(WFRAME_FIRE2, cvar("g_balance_seeker_flac_animtime"), w_ready);
+ }
+
+ }
+ else if (req == WR_PRECACHE)
+ {
+ precache_model ("models/weapons/g_seeker.md3");
+ precache_model ("models/weapons/v_seeker.md3");
+ precache_model ("models/weapons/h_seeker.iqm");
+ precache_sound ("weapons/tag_fire.wav");
+ precache_sound ("weapons/flac_fire.wav");
+ precache_sound ("weapons/seeker_fire.wav");
+ }
+ else if (req == WR_SETUP)
+ weapon_setup(WEP_SEEKER);
+ else if (req == WR_CHECKAMMO1)
+ return self.ammo_rockets >= cvar("g_balance_seeker_tag_ammo") + cvar("g_balance_seeker_missile_ammo");
+ else if (req == WR_CHECKAMMO2)
+ return self.ammo_rockets >= cvar("g_balance_seeker_flac_ammo");
+ else if (req == WR_SUICIDEMESSAGE)
+ w_deathtypestring = "played with tiny rockets";
+ else if (req == WR_KILLMESSAGE)
+ {
+ if(w_deathtype & HITTYPE_SECONDARY)
+ w_deathtypestring = "ran into #'s flac";
+ else
+ w_deathtypestring = "was tagged by";
+ }
+ return TRUE;
+};
+#endif
precache_model ("models/uziflash.md3");
precache_model ("models/weapons/g_shotgun.md3");
precache_model ("models/weapons/v_shotgun.md3");
- precache_model ("models/weapons/h_shotgun.dpm");
+ precache_model ("models/weapons/h_shotgun.iqm");
precache_sound ("misc/itempickup.wav");
precache_sound ("weapons/shotgun_fire.wav");
}
{
precache_model ("models/weapons/g_tuba.md3");
precache_model ("models/weapons/v_tuba.md3");
- precache_model ("models/weapons/h_tuba.dpm");
+ precache_model ("models/weapons/h_tuba.iqm");
//float i;
//for(i = -18; i <= +27; ++i)
precache_model ("models/uziflash.md3");
precache_model ("models/weapons/g_uzi.md3");
precache_model ("models/weapons/v_uzi.md3");
- precache_model ("models/weapons/h_uzi.dpm");
+ precache_model ("models/weapons/h_uzi.iqm");
precache_sound ("weapons/uzi_fire.wav");
}
else if (req == WR_SETUP)
float warpzone_saved;
vector warpzone_saved_origin;
vector warpzone_saved_angles;
+vector warpzone_saved_cl_viewangles;
#ifndef KEEP_ROLL
var float autocvar_cl_rollkillspeed = 10;
#endif
void WarpZone_FixView()
{
- float pd;
+ float pd, f;
entity e;
warpzone_saved = 0;
warpzone_saved_origin = warpzone_fixview_origin;
warpzone_saved_angles = warpzone_fixview_angles;
+ warpzone_saved_cl_viewangles = warpzone_fixview_cl_viewangles;
#ifndef KEEP_ROLL
- if(autocvar_cl_rollkillspeed)
- R_SetView(VF_CL_VIEWANGLES_Z, input_angles_z * max(0, (1 - frametime * autocvar_cl_rollkillspeed)));
- else
- R_SetView(VF_CL_VIEWANGLES_Z, 0);
+ if(warpzone_fixview_angles_z != 0 || warpzone_fixview_cl_viewangles_z != 0)
+ {
+ if(autocvar_cl_rollkillspeed)
+ f = max(0, (1 - frametime * autocvar_cl_rollkillspeed));
+ else
+ f = 0;
+ warpzone_fixview_angles_z *= f;
+ warpzone_fixview_cl_viewangles_z *= f;
+ warpzone_saved_angles_z *= f; // PERMANENTLY apply that change!
+ warpzone_saved_cl_viewangles_z *= f; // PERMANENTLY apply that change!
+ warpzone_saved = 2;
+ R_SetView(VF_CL_VIEWANGLES_Z, warpzone_fixview_angles_z);
+ }
#endif
e = WarpZone_Find(warpzone_fixview_origin, warpzone_fixview_origin);
warpzone_saved = 1;
warpzone_fixview_origin = WarpZone_TransformOrigin(e, warpzone_fixview_origin);
warpzone_fixview_angles = WarpZone_TransformVAngles(e, warpzone_fixview_angles);
+ warpzone_fixview_cl_viewangles = WarpZone_TransformVAngles(e, warpzone_fixview_cl_viewangles);
WarpZone_Inside();
}
else
}
}
- if(warpzone_saved)
+ if(warpzone_saved == 1)
{
R_SetView(VF_ORIGIN, warpzone_fixview_origin);
- R_SetView(VF_ANGLES, warpzone_fixview_angles);
+ R_SetView(VF_ANGLES, warpzone_fixview_cl_viewangles);
}
}
void WarpZone_UnFixView()
{
warpzone_fixview_origin = warpzone_saved_origin;
warpzone_fixview_angles = warpzone_saved_angles;
+ warpzone_fixview_cl_viewangles = warpzone_saved_cl_viewangles;
R_SetView(VF_ORIGIN, warpzone_fixview_origin);
R_SetView(VF_ANGLES, warpzone_fixview_angles);
+ R_SetView(VF_CL_VIEWANGLES, warpzone_fixview_cl_viewangles);
}
}
vector warpzone_fixview_origin;
vector warpzone_fixview_angles;
+vector warpzone_fixview_cl_viewangles;
void WarpZone_FixView(); // this saves the previous values
void WarpZone_UnFixView(); // and restores them
void WarpZone_TraceBox_ThroughZone(vector org, vector mi, vector ma, vector end, float nomonsters, entity forent, entity zone, WarpZone_trace_callback_t cb)
{
- float frac, sol;
+ float frac, sol, i;
vector o0, e0;
entity wz;
vector vf, vr, vu;
WarpZone_MakeAllSolid();
sol = -1;
frac = 0;
+ i = 16;
for(;;)
{
+ if(--i < 1)
+ {
+ dprint("Too many warpzones in sequence, aborting trace.\n");
+ break;
+ }
tracebox(org, mi, ma, end, nomonsters, forent);
if(cb)
cb(org, trace_endpos, end);
void WarpZone_TraceToss_ThroughZone(entity e, entity forent, entity zone, WarpZone_trace_callback_t cb)
{
- float g, dt;
+ float g, dt, i;
vector vf, vr, vu, v0, o0;
entity wz;
WarpZone_MakeAllSolid();
g = cvar("sv_gravity") * e.gravity;
WarpZone_tracetoss_time = 0;
+ i = 16;
for(;;)
{
+ if(--i < 1)
+ {
+ dprint("Too many warpzones in sequence, aborting trace.\n");
+ break;
+ }
tracetoss(e, forent);
if(cb)
cb(e.origin, trace_endpos, trace_endpos);
return FALSE;
}
-void WarpZone_InitStep_FindTarget()
+void WarpZone_InitStep_FindOriginTarget()
{
- entity e;
-
if(self.killtarget != "")
{
self.aiment = find(world, targetname, self.killtarget);
return;
}
}
-
- // this way only one of the two ents needs to target
- if(self.target != "")
- {
- e = find(world, targetname, self.target);
- if(e)
- {
- self.enemy = e;
- self.enemy.enemy = self;
- }
- }
}
void WarpZonePosition_InitStep_FindTarget()
{
- entity e;
-
if(self.target == "")
{
error("Warp zone position with no target");
void WarpZoneCamera_InitStep_FindTarget()
{
- entity e;
-
if(self.target == "")
{
error("Camera with no target");
float i_s, i_t, n_t;
string tex;
- if(!self.enemy || self.enemy.enemy != self)
- {
- error("Invalid warp zone detected. Killed.");
- return;
- }
-
org = self.origin;
if(org == '0 0 0')
org = 0.5 * (self.mins + self.maxs);
self.warpzone_origin = org;
self.warpzone_angles = ang;
}
+
+void WarpZone_InitStep_ClearTarget()
+{
+ if(self.enemy)
+ self.enemy.enemy = world;
+ self.enemy = world;
+}
+
+void WarpZone_InitStep_FindTarget()
+{
+ float i;
+ entity e, e2;
+
+ // this way only one of the two ents needs to target
+ if(self.target != "")
+ {
+ e2 = world;
+ for(e = world; (e = find(e, targetname, self.target)); )
+ if(!e.enemy)
+ if(random() * ++i < 1)
+ e2 = e;
+ if(!e2)
+ {
+ error("Warpzone with non-existing target");
+ return;
+ }
+ self.enemy = e2;
+ e2.enemy = self;
+ }
+}
+
void WarpZone_InitStep_FinalizeTransform()
{
+ if(!self.enemy || self.enemy.enemy != self)
+ {
+ error("Invalid warp zone detected. Killed.");
+ return;
+ }
+
WarpZone_SetUp(self, self.warpzone_origin, self.warpzone_angles, self.enemy.warpzone_origin, self.enemy.warpzone_angles);
self.touch = WarpZone_Touch;
+ self.SendFlags = 0xFFFFFF;
}
float warpzone_initialized;
self.warpzone_next = warpzone_camera_first;
warpzone_camera_first = self;
}
+void WarpZones_Reconnect()
+{
+ entity e;
+ e = self;
+ for(self = warpzone_first; self; self = self.warpzone_next)
+ WarpZone_InitStep_ClearTarget();
+ for(self = warpzone_first; self; self = self.warpzone_next)
+ WarpZone_InitStep_FindTarget();
+ for(self = warpzone_first; self; self = self.warpzone_next)
+ WarpZone_InitStep_FinalizeTransform();
+ self = e;
+}
+
void WarpZone_StartFrame()
{
entity e;
warpzone_initialized = 1;
e = self;
for(self = warpzone_first; self; self = self.warpzone_next)
- WarpZone_InitStep_FindTarget();
+ WarpZone_InitStep_FindOriginTarget();
for(self = warpzone_position_first; self; self = self.warpzone_next)
WarpZonePosition_InitStep_FindTarget();
for(self = warpzone_camera_first; self; self = self.warpzone_next)
WarpZoneCamera_InitStep_FindTarget();
for(self = warpzone_first; self; self = self.warpzone_next)
WarpZone_InitStep_UpdateTransform();
- for(self = warpzone_first; self; self = self.warpzone_next)
- WarpZone_InitStep_FinalizeTransform();
self = e;
+ WarpZones_Reconnect();
}
for(e = world; (e = nextent(e)); )
WarpZone_StoreProjectileData(e);
}
+
+void target_warpzone_reconnect_use()
+{
+ entity e;
+ e = self;
+ // NOTE: this matches for target, not targetname, but of course
+ // targetname must be set too on the other entities
+ for(self = warpzone_first; self; self = self.warpzone_next)
+ if(e.target == "" || self.target == e.target)
+ WarpZone_InitStep_ClearTarget();
+ for(self = warpzone_first; self; self = self.warpzone_next)
+ if(e.target == "" || self.target == e.target)
+ WarpZone_InitStep_FindTarget();
+ for(self = warpzone_first; self; self = self.warpzone_next)
+ if(e.target == "" || self.target == e.target || self.enemy.target == e.target)
+ WarpZone_InitStep_FinalizeTransform();
+ self = e;
+}
+
+void trigger_warpzone_reconnect()
+{
+ self.use = target_warpzone_reconnect_use;
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<CodeBlocks_workspace_file>
+ <Workspace title="Xonotic Gamecode">
+ <Project filename="qc-server.cbp" active="1" />
+ <Project filename="qc-client.cbp" />
+ <Project filename="qc-common.cbp" />
+ </Workspace>
+</CodeBlocks_workspace_file>
--- /dev/null
+electro_plasma
+{
+ {
+ map textures/electro_plasma.tga
+ tcMod scroll 0.03 0.001
+ }
+}
+
+electro_plasma_hull
+{
+ {
+ map textures/electro_plasma_hull.tga
+ alphaFunc GT0
+ rgbGen Vertex
+ }
+}
--- /dev/null
+fireball
+{
+ {
+ map textures/fireball
+ tcgen environment
+ }
+ {
+ map $lightmap
+ }
+}
--- /dev/null
+flags/flag_red_cloth {
+ cull none
+ deformVertexes wave 100 sin 0 0.4 0 2.5
+ {
+ map textures/flags/flag_red_cloth.tga
+ }
+}
+
+flags/flag_red_laser {
+ {
+ map textures/flags/flag_red_laser.tga
+ tcMod scroll 0.2 -1
+ blendfunc add
+ }
+}
+
+
+flags/flag_blue_cloth {
+ cull none
+ deformVertexes wave 100 sin 0 0.4 0 2.5
+ {
+ map textures/flags/flag_blue_cloth.tga
+ }
+}
+
+flags/flag_blue_laser {
+ {
+ map textures/flags/flag_blue_laser.tga
+ tcMod scroll 0.2 -1
+ blendfunc add
+ }
+}
+
--- /dev/null
+hlac_plasma
+{
+ {
+ map textures/hlac_plasma.tga
+ tcMod scroll 22.5 0.2
+ tcmod scale 0.01 0.01
+ }
+}
+
+hlac_metal
+{
+ cull none
+ {
+ map textures/hlac_metal.tga
+ rgbgen vertex
+ }
+}
+hlac_glass
+{
+ qer_editorimage textures/hlac_glass.tga
+ surfaceparm trans
+ cull disable
+ qer_trans 0.5
+ {
+ map textures/hlac_glass.tga
+ blendfunc add
+ //rgbGen vertex
+ tcgen environment
+ tcmod scale 4 4
+ }
+}
+hlac_bullet
+{
+ cull disable
+ deformVertexes autosprite
+ {
+ map models/hlac_bullet.tga
+ blendfunc add
+ }
+}
--- /dev/null
+// shaders to be used on models
+
+nodraw
+{
+ surfaceparm nodraw
+ surfaceparm nolightmap
+ surfaceparm nonsolid
+ surfaceparm trans
+ surfaceparm nomarks
+}
--- /dev/null
+ons_shield
+{
+ {
+ map textures/ons_shield.tga
+ tcMod rotate 15
+ tcMod scale 0.3 0.3
+ tcMod scroll 0.03 0.001
+ tcGen environment
+ }
+}
+
+ons_pad_text
+{
+ cull none
+ {
+ map textures/ons_text.tga
+ tcMod scroll 0.1 0
+ blendfunc add
+
+ }
+}
+
+ons_icon_text
+{
+ {
+ map textures/ons_text.tga
+ tcMod scroll 0.1 0
+ }
+}
+
+ons_icon_thrust
+{
+ {
+ map textures/ons_icon_thrust.tga
+ tcMod scroll 3 0
+ tcMod rotate 10
+ }
+}
+ons_gen_spark
+{
+ cull none
+ {
+ animmap 9 textures/generator_lightning.tga textures/generator_lightning2.tga
+ tcMod scroll 0.5 0
+ blendfunc add
+
+ }
+}
+ons_fire
+{
+ {
+ map textures/ons_boom1.tga
+ tcMod scroll 0.05 0.1
+ tcMod rotate 0.01
+ blendfunc add
+
+ }
+}
+ons_smoke
+{
+ deformVertexes wave sin 1 3 2 0.2
+ {
+ map textures/ons_smoke1.tga
+ tcMod scroll 0.01 0.04
+ tcMod rotate 0.01
+ alphaFunc GE128
+
+ }
+}
+ons_shockwave
+{
+ cull none
+ {
+ map textures/ons_shockwave1.tga
+ tcMod scroll 0.2 0
+ blendfunc add
+
+ }
+}
+ons_shockwave2
+{
+ {
+ map textures/ons_shockwave2.tga
+ tcMod rotate 85
+ tcMod scroll 0.03 0.6
+ tcGen environment
+ blendfunc add
+ }
+}
+
+ons_ray
+{
+cull none
+ {
+ map textures/ons_ray.tga
+ tcMod rotate 85
+ blendfunc add
+ }
+}
\ No newline at end of file
--- /dev/null
+portals_red_vortex
+{
+ cull none
+ deformVertexes wave 100 sin 1.5 0.6 0 1.5
+ {
+ map textures/portals/portals_red_vortex.tga
+ tcMod rotate 10
+ blendfunc blend
+ }
+}
+
+portals_blue_vortex
+{
+ cull none
+ deformVertexes wave 100 sin 1.5 0.6 0 1.5
+ {
+ map textures/portals/portals_blue_vortex.tga
+ tcMod rotate 10
+ blendfunc blend
+ }
+}
+
+portals_inactive_vortex
+{
+ cull none
+ deformVertexes wave 100 sin 1.5 0.6 0 1.5
+ {
+ map textures/portals/portals_inactive_vortex.tga
+ tcMod rotate 10
+ blendfunc blend
+ }
+}
+
+portals/portals_red
+{
+ surfaceparm nonsolid
+ {
+ map textures/portals/portals_red.tga
+ }
+ {
+ map $lightmap
+ blendfunc filter
+ }
+}
+
+portals/portals_blue
+{
+ surfaceparm nonsolid
+ {
+ map textures/portals/portals_blue.tga
+ }
+ {
+ map $lightmap
+ blendfunc filter
+ }
+}
+
+portals/portals_inactive
+{
+ surfaceparm nonsolid
+ {
+ map textures/portals/portals_inactive.tga
+ }
+ {
+ map $lightmap
+ blendfunc filter
+ }
+}
--- /dev/null
+pyriahair
+{
+
+ surfaceparm trans
+ cull none
+
+ {
+ map textures/pyriahair
+ alphaFunc GE128
+ blendFunc blend
+ rgbGen identity
+ }
+}
--- /dev/null
+shotgun_sight
+{
+ surfaceparm trans
+
+ {
+ map textures/shotgun_sight.tga
+ blendfunc add
+ //rgbGen vertex
+ }
+}
--- /dev/null
+darkvisor
+{
+ qer_editorimage darkvisor.tga
+ {
+ map darkvisor.tga
+ rgbGen vertex
+ tcgen environment
+ tcmod scale 4 4
+ }
+}
\ No newline at end of file
--- /dev/null
+teamfx/blobblue
+{
+surfaceparm trans
+deformVertexes autosprite
+{
+ map models/teamfx/blobblue.tga
+ blendfunc add
+}
+}
+
+teamfx/blobred
+{
+surfaceparm trans
+deformVertexes autosprite
+{
+ map models/teamfx/blobred.tga
+ blendfunc add
+}
+
+}
+
+teamfx/blobyellow
+{
+surfaceparm trans
+deformVertexes autosprite
+{
+ map models/teamfx/blobyellow.tga
+ blendfunc add
+}
+
+}
+
+teamfx/blobpink
+{
+surfaceparm trans
+deformVertexes autosprite
+{
+ map models/teamfx/blobpink.tga
+ blendfunc add
+}
+
+}
+
+teamfx/bluering
+{
+surfaceparm trans
+{
+ map models/teamfx/blobblue.tga
+ blendfunc add
+}
+}
+teamfx/redring
+{
+surfaceparm trans
+{
+ map models/teamfx/blobyellow.tga
+ blendfunc add
+}
+}
+teamfx/yellowring
+{
+surfaceparm trans
+{
+ map models/teamfx/blobpink.tga
+ blendfunc add
+}
+}
+teamfx/pinkring
+{
+surfaceparm trans
+{
+ map models/teamfx/blobpink.tga
+ blendfunc add
+}
+}
+teamfx/flare
+{
+surfaceparm trans
+deformVertexes autosprite
+{
+ map models/teamfx/flare.tga
+ blendfunc add
+}
+}
+teamfx/rayblue
+{
+surfaceparm trans
+deformVertexes autosprite
+{
+ map models/teamfx/rayblue.tga
+ blendfunc add
+}
+}
+teamfx/rayred
+{
+surfaceparm trans
+deformVertexes autosprite
+{
+ map models/teamfx/rayred.tga
+ blendfunc add
+}
+}
+teamfx/rayyellow
+{
+surfaceparm trans
+deformVertexes autosprite
+{
+ map models/teamfx/rayyellow.tga
+ blendfunc add
+}
+}
+teamfx/raypink
+{
+surfaceparm trans
+deformVertexes autosprite
+{
+ map models/teamfx/raypink.tga
+ blendfunc add
+}
+}
--- /dev/null
+tuba
+{
+ {
+ map textures/tuba
+ tcgen environment
+ }
+ {
+ map $lightmap
+ }
+}
+tuba_misc
+{
+ {
+ map textures/tuba
+ }
+ {
+ map $lightmap
+ }
+}
--- /dev/null
+models/turrets/tesla_chrome\r
+{\r
+\r
+ qer_editorimage models/turrets/chrome.tga\r
+\r
+ //dp_reflect 0 0.75 0.75 1 0.5 \r
+ {\r
+ map models/turrets/chrome.tga \r
+ rgbGen vertex\r
+ tcGen environment \r
+ tcMod scale 2 2\r
+ \r
+ }\r
+}\r
+\r
+models/turrets/phaser_beam\r
+{\r
+ surfaceparm trans\r
+ cull none\r
+ nopicmip\r
+\r
+ qer_editorimage models/turrets/phaser_beam\r
+ { \r
+ map models/turrets/phaser_beam\r
+ blendFunc add\r
+ }\r
+\r
+}\r
+\r
+models/turrets/reactor_beams\r
+{\r
+ surfaceparm trans\r
+ cull none\r
+\r
+ qer_editorimage models/turrets/reactor\r
+ { \r
+ map models/turrets/reactor\r
+ blendFunc add\r
+ }\r
+}\r
+\r
+models/turrets/r_fx1\r
+{\r
+ surfaceparm nomarks\r
+ surfaceparm trans\r
+ surfaceparm pointlight\r
+ surfaceparm nolightmap \r
+ nopicmip\r
+ qer_editorimage models/turrets/r_fx1_1\r
+\r
+ {\r
+ animmap 10 models/turrets/r_fx1_3 models/turrets/r_fx1_4 models/turrets/r_fx1_5 models/turrets/r_fx1_4 models/turrets/r_fx1_3 models/turrets/r_fx1_2 models/turrets/r_fx1_1 models/turrets/r_fx1_2 \r
+ }\r
+\r
+}\r
+\r
+\r
--- /dev/null
+electro
+{
+ dpreflectcube cubemaps/default/sky
+ {
+ map textures/electro.tga
+ rgbgen lightingDiffuse
+ }
+}
+nexgun
+{
+ dpreflectcube cubemaps/default/sky
+ {
+ map textures/nexgun.tga
+ rgbgen lightingDiffuse
+ }
+}
+uzi
+{
+ dpreflectcube cubemaps/default/sky
+ {
+ map textures/uzi.tga
+ rgbgen lightingDiffuse
+ }
+}
+glauncher
+{
+ dpreflectcube cubemaps/default/sky
+ {
+ map textures/glauncher.tga
+ rgbgen lightingDiffuse
+ }
+}
+hagar2
+{
+ dpreflectcube cubemaps/default/sky
+ {
+ map textures/hagar2.tga
+ rgbgen lightingDiffuse
+ }
+}
+crylink
+{
+ dpreflectcube cubemaps/default/sky
+ {
+ map textures/crylink.tga
+ rgbgen lightingDiffuse
+ }
+}
+shotgun2
+{
+ dpreflectcube cubemaps/default/sky
+ {
+ map textures/shotgun2.tga
+ rgbgen lightingDiffuse
+ }
+}
+nex
+{
+ dpreflectcube cubemaps/default/sky
+ {
+ map textures/nex.tga
+ rgbgen lightingDiffuse
+ }
+}
+rl
+{
+ dpreflectcube cubemaps/default/sky
+ {
+ map textures/rl.tga
+ rgbgen lightingDiffuse
+ }
+}
+laser
+{
+ dpreflectcube cubemaps/default/sky
+ {
+ map textures/laser.tga
+ rgbgen lightingDiffuse
+ }
+}
+hlac_accessory
+{
+ dpreflectcube cubemaps/default/sky
+ {
+ map textures/hlac_accessory.tga
+ rgbgen lightingDiffuse
+ }
+}
+hlac_body
+{
+ dpreflectcube cubemaps/default/sky
+ {
+ map textures/hlac_body.tga
+ rgbgen lightingDiffuse
+ }
+}
+seeker
+{
+ dpreflectcube cubemaps/default/sky
+ {
+ map textures/seeker.tga
+ rgbgen lightingDiffuse
+ }
+}
fraglimit_override 0
timelimit_override 3
sv_eventlog 1
-g_nixnex 1
-g_nixnex_with_laser 1
-g_balance_nixnex_roundtime 3
+g_nix 1
+g_nix_with_laser 1
+g_balance_nix_roundtime 3
map downer
// time darkplaces/xonotic-dedicated +exec serverbench.cfg | grep ^: > serverbench.log
--- /dev/null
+#!/bin/sh
+
+wget -N http://svn.icculus.org/*checkout*/twilight/trunk/dpmod/qc/dpextensions.qc
+wget -N http://svn.icculus.org/*checkout*/nexuiz/trunk/data/qcsrc/server/extensions.qh
+vimdiff dpextensions.qc extensions.qh qcsrc/server/extensions.qh
#!/bin/sh
-balance_cfgs="balance25.cfg balanceSamual.cfg balanceNexrun.cfg"
+balance_cfgs="balance25.cfg balanceSamual.cfg balanceXPM.cfg"
countw=`awk '/^seta? g_/ { print $2; }' balance.cfg | sort -u | tr -d '\r' | md5sum | cut -c 1-32`
for b in $balance_cfgs; do
-**Team Leaders:
+(THIS FILE IS A HUGE TODO)
+(YES, REALLY, NOTHING HERE IS TRUE)
+(PLEASE FIX THIS FILE)
-Lee Vermeulen
-*Project Founder and Co-Designer
-Forest "LordHavoc" Hale
-*Lead Programmer and Co-Designer
+**Team Leaders:
-Rudolf "div0" Polzer
-*Programmer
**Project maintainers:
**Development Team:
+Rudolf "div0" Polzer
+*Programmer
+
Andreas "Black" Kirsch
*Programmer
Marius "GreEn`mArine" Shekow
*Programmer
+Forest "LordHavoc" Hale
+*DarkPlaces Engine Programmer
+
Braden "meoblast001" Walters
*Music
Jody Gallagher
Juergen "LowDragon" Timm
Lee David Ash
+Lee Vermeulen
Mathieu "Elric" Olivier
Mephisto
MirceaKitsune