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 ?=
+FTEQCCFLAGS_PROGS ?=
+FTEQCCFLAGS_MENU ?=
# NOTE: use -DUSE_FTE instead of -TFTE here!
# It will automagically add an engine check with -TID and then change back to -TFTE
clean:
rm -f progs.dat menu.dat csprogs.dat
-csprogs.dat: qcsrc/client/*.* qcsrc/common/*.* qcsrc/warpzonelib/*.*
+FILES_CSPROGS = qcsrc/client/progs.src $(shell sed '/\.dat/d; s,//.*,,; s,[^ ],qcsrc/client/&,' < qcsrc/client/progs.src)
+csprogs.dat: $(FILES_CSPROGS)
@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/*.*
+FILES_PROGS = qcsrc/server/progs.src $(shell sed '/\.dat/d; s,//.*,,; s,[^ ],qcsrc/server/&,' < qcsrc/server/progs.src)
+progs.dat: $(FILES_PROGS)
@echo make[1]: Entering directory \`$(PWD)/qcsrc/server\'
cd qcsrc/server && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_PROGS)
-menu.dat: qcsrc/menu/*.* qcsrc/menu/*/*.* qcsrc/common/*.*
+FILES_MENU = qcsrc/menu/progs.src $(shell sed '/\.dat/d; s,//.*,,; s,[^ ],qcsrc/menu/&,' < qcsrc/menu/progs.src)
+menu.dat: $(FILES_MENU)
@echo make[1]: Entering directory \`$(PWD)/qcsrc/menu\'
cd qcsrc/menu && $(FTEQCC) $(FTEQCCFLAGS) $(FTEQCCFLAGS_MENU)
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_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_minelayer -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_pickup_ammo_anyway 0
set g_pickup_weapons_anyway 0
set g_pickup_shells 15
+set g_pickup_shells_weapon 15
set g_pickup_shells_max 999
set g_pickup_nails 80
+set g_pickup_nails_weapon 80
set g_pickup_nails_max 999
set g_pickup_rockets 15
+set g_pickup_rockets_weapon 15
set g_pickup_rockets_max 999
set g_pickup_cells 25
+set g_pickup_cells_weapon 25
set g_pickup_cells_max 999
set g_pickup_fuel 25
+set g_pickup_fuel_weapon 25
set g_pickup_fuel_jetpack 50
set g_pickup_fuel_max 999
set g_pickup_armorsmall 5
set g_balance_uzi_bulletconstant 115 // 13.1qu
// }}}
// {{{ mortar
-set g_balance_grenadelauncher_primary2secondary 0
-set g_balance_grenadelauncher_primary_sticky 0
+set g_balance_grenadelauncher_primary_type 0
set g_balance_grenadelauncher_primary_damage 70
set g_balance_grenadelauncher_primary_edgedamage 38
set g_balance_grenadelauncher_primary_force 400
set g_balance_grenadelauncher_primary_animtime 0.3
set g_balance_grenadelauncher_primary_ammo 2
set g_balance_grenadelauncher_primary_health 25
-set g_balance_grenadelauncher_secondary_sticky 0
+set g_balance_grenadelauncher_primary_damageforcescale 4
+set g_balance_grenadelauncher_primary_bouncefactor 0.5
+set g_balance_grenadelauncher_primary_bouncestop 0.075
+set g_balance_grenadelauncher_primary_remote_minbouncecnt 0
+
+set g_balance_grenadelauncher_secondary_type 1
set g_balance_grenadelauncher_secondary_damage 70
set g_balance_grenadelauncher_secondary_edgedamage 38
set g_balance_grenadelauncher_secondary_force 400
set g_balance_grenadelauncher_secondary_damageforcescale 4
set g_balance_grenadelauncher_secondary_bouncefactor 0.5
set g_balance_grenadelauncher_secondary_bouncestop 0.075
+set g_balance_grenadelauncher_secondary_remote_detonateprimary 0
+// }}}
+// {{{ minelayer // TODO
+set g_balance_minelayer_damage 35
+set g_balance_minelayer_edgedamage 30
+set g_balance_minelayer_force 250
+set g_balance_minelayer_radius 175
+set g_balance_minelayer_proximityradius 150
+set g_balance_minelayer_speed 750
+set g_balance_minelayer_lifetime 60
+set g_balance_minelayer_refire 1.5
+set g_balance_minelayer_animtime 0.4
+set g_balance_minelayer_ammo 5
+set g_balance_minelayer_health 15
+set g_balance_minelayer_limit 4 // 0 disables the limit
+set g_balance_minelayer_protection 1 // don't explode if the mine would hurt the owner or a team mate
+set g_balance_minelayer_damageforcescale 0
+set g_balance_minelayer_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_minelayer_time 0.5
+set g_balance_minelayer_remote_damage 45
+set g_balance_minelayer_remote_edgedamage 40
+set g_balance_minelayer_remote_radius 200
+set g_balance_minelayer_remote_force 300
// }}}
// {{{ electro
set g_balance_electro_lightning 0
set g_balance_nex_primary_damagefalloff_forcehalflife 0
set g_balance_nex_secondary 0
+set g_balance_nex_secondary_charge 0
+set g_balance_nex_secondary_charge_rate 0.1
set g_balance_nex_secondary_damage 100
set g_balance_nex_secondary_force 600
set g_balance_nex_secondary_refire 1.5
set g_balance_nex_secondary_damagefalloff_halflife 0
set g_balance_nex_secondary_damagefalloff_forcehalflife 0
-set g_balance_nex_velocitydependent 0
-set g_balance_nex_velocitydependent_minspeed 400
-set g_balance_nex_velocitydependent_maxspeed 1000
+set g_balance_nex_charge 0
+set g_balance_nex_charge_start 0
+set g_balance_nex_charge_rate 0.1
+set g_balance_nex_charge_limit 0.5
+set g_balance_nex_charge_shot_multiplier 0.5
+set g_balance_nex_charge_velocity_rate 0.2
+set g_balance_nex_charge_minspeed 400
+set g_balance_nex_charge_maxspeed 1000
// }}}
// {{{ minstanex
set g_balance_minstanex_refire 1
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
-set g_balance_campingrifle_tracer 0
+set g_balance_campingrifle_primary_tracer 0
set g_balance_campingrifle_primary_damage 60
set g_balance_campingrifle_primary_headshotaddeddamage 100
set g_balance_campingrifle_primary_spread 0
set g_balance_campingrifle_primary_burstcost 0
set g_balance_campingrifle_primary_bullethail 0 // empty magazine on shot
set g_balance_campingrifle_secondary 1
+set g_balance_campingrifle_secondary_tracer 0
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_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_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_minelayer -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_pickup_ammo_anyway 0
set g_pickup_weapons_anyway 1
set g_pickup_shells 20
+set g_pickup_shells_weapon 20
set g_pickup_shells_max 45
set g_pickup_nails 120
+set g_pickup_nails_weapon 120
set g_pickup_nails_max 300
set g_pickup_rockets 25
+set g_pickup_rockets_weapon 25
set g_pickup_rockets_max 150
set g_pickup_cells 25
+set g_pickup_cells_weapon 25
set g_pickup_cells_max 200
set g_pickup_fuel 25
+set g_pickup_fuel_weapon 25
set g_pickup_fuel_jetpack 50
set g_pickup_fuel_max 999
set g_pickup_armorsmall 10
// {{{ shotgun
set g_balance_shotgun_primary_bullets 5
set g_balance_shotgun_primary_damage 12
-set g_balance_shotgun_primary_force 60
+set g_balance_shotgun_primary_force 40
set g_balance_shotgun_primary_spread 0.08
set g_balance_shotgun_primary_refire 0.5
set g_balance_shotgun_primary_animtime 0.2
// {{{ uzi
set g_balance_uzi_first 1
set g_balance_uzi_first_damage 26
-set g_balance_uzi_first_force 50
+set g_balance_uzi_first_force -30
set g_balance_uzi_first_spread 0.01
set g_balance_uzi_first_refire 0.2
set g_balance_uzi_first_ammo 1
-set g_balance_uzi_sustained_damage 15
+set g_balance_uzi_sustained_damage 17
set g_balance_uzi_sustained_force 27
set g_balance_uzi_sustained_spread 0.05
set g_balance_uzi_sustained_refire 0.1
set g_balance_uzi_bulletconstant 300 // 13.1qu
// }}}
// {{{ mortar
-set g_balance_grenadelauncher_primary2secondary 0
-set g_balance_grenadelauncher_primary_sticky 0
+set g_balance_grenadelauncher_primary_type 0
set g_balance_grenadelauncher_primary_damage 65
set g_balance_grenadelauncher_primary_edgedamage 35
-set g_balance_grenadelauncher_primary_force 400
+set g_balance_grenadelauncher_primary_force 310
set g_balance_grenadelauncher_primary_radius 140
set g_balance_grenadelauncher_primary_speed 2000
set g_balance_grenadelauncher_primary_speed_up 200
set g_balance_grenadelauncher_primary_animtime 0.3
set g_balance_grenadelauncher_primary_ammo 2
set g_balance_grenadelauncher_primary_health 72
-set g_balance_grenadelauncher_secondary_sticky 0
+set g_balance_grenadelauncher_primary_damageforcescale 0
+set g_balance_grenadelauncher_primary_bouncefactor 0.7
+set g_balance_grenadelauncher_primary_bouncestop 0.12
+set g_balance_grenadelauncher_primary_remote_minbouncecnt 0
+
+set g_balance_grenadelauncher_secondary_type 1
set g_balance_grenadelauncher_secondary_damage 65
set g_balance_grenadelauncher_secondary_edgedamage 35
-set g_balance_grenadelauncher_secondary_force 400
+set g_balance_grenadelauncher_secondary_force 320
set g_balance_grenadelauncher_secondary_radius 140
set g_balance_grenadelauncher_secondary_speed 1400
set g_balance_grenadelauncher_secondary_speed_up 200
set g_balance_grenadelauncher_secondary_damageforcescale 0
set g_balance_grenadelauncher_secondary_bouncefactor 0.7
set g_balance_grenadelauncher_secondary_bouncestop 0.12
+set g_balance_grenadelauncher_secondary_remote_detonateprimary 0
+// }}}
+// {{{ minelayer // TODO
+set g_balance_minelayer_damage 35
+set g_balance_minelayer_edgedamage 30
+set g_balance_minelayer_force 250
+set g_balance_minelayer_radius 175
+set g_balance_minelayer_proximityradius 150
+set g_balance_minelayer_speed 750
+set g_balance_minelayer_lifetime 60
+set g_balance_minelayer_refire 1.5
+set g_balance_minelayer_animtime 0.4
+set g_balance_minelayer_ammo 5
+set g_balance_minelayer_health 15
+set g_balance_minelayer_limit 4 // 0 disables the limit
+set g_balance_minelayer_protection 1 // don't explode if the mine would hurt the owner or a team mate
+set g_balance_minelayer_damageforcescale 0
+set g_balance_minelayer_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_minelayer_time 0.5
+set g_balance_minelayer_remote_damage 45
+set g_balance_minelayer_remote_edgedamage 40
+set g_balance_minelayer_remote_radius 200
+set g_balance_minelayer_remote_force 300
// }}}
// {{{ electro
set g_balance_electro_lightning 0
-set g_balance_electro_primary_damage 80
-set g_balance_electro_primary_edgedamage 0
-set g_balance_electro_primary_force 550
+set g_balance_electro_primary_damage 55
+set g_balance_electro_primary_edgedamage 5
+set g_balance_electro_primary_force 267
set g_balance_electro_primary_force_up 125
set g_balance_electro_primary_radius 150
set g_balance_electro_primary_comboradius 75
set g_balance_electro_primary_speed 2000
set g_balance_electro_primary_spread 0
set g_balance_electro_primary_lifetime 30
-set g_balance_electro_primary_refire 0.6
-set g_balance_electro_primary_animtime 0.74
+set g_balance_electro_primary_refire 0.78
+set g_balance_electro_primary_animtime 0.4
set g_balance_electro_primary_ammo 2
set g_balance_electro_primary_range 800
-set g_balance_electro_primary_falloff_mindist 255 // 0.3 * radius
+set g_balance_electro_primary_falloff_mindist 255
set g_balance_electro_primary_falloff_maxdist 850
-set g_balance_electro_primary_falloff_halflifedist 425
+set g_balance_electro_primary_falloff_halflifedist 0
set g_balance_electro_secondary_damage 60
set g_balance_electro_secondary_edgedamage 0
set g_balance_electro_secondary_force 200
set g_balance_electro_combo_speed 400
// }}}
// {{{ crylink
-set g_balance_crylink_primary_damage 16
+set g_balance_crylink_primary_damage 23
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_bounces 2
set g_balance_crylink_primary_refire 0.4
set g_balance_crylink_primary_animtime 0.30008
-set g_balance_crylink_primary_ammo 1
+set g_balance_crylink_primary_ammo 3
set g_balance_crylink_primary_bouncedamagefactor 0.2
set g_balance_crylink_primary_middle_lifetime 5 // range: 10000 full, fades to 20000
set g_balance_crylink_primary_other_fadetime 0.25
set g_balance_crylink_secondary 1
-set g_balance_crylink_secondary_damage 12
+set g_balance_crylink_secondary_damage 19
set g_balance_crylink_secondary_edgedamage 0
set g_balance_crylink_secondary_force -55
set g_balance_crylink_secondary_radius 3
set g_balance_crylink_secondary_bounces 0
set g_balance_crylink_secondary_refire 0.5
set g_balance_crylink_secondary_animtime 0.3
-set g_balance_crylink_secondary_ammo 2
+set g_balance_crylink_secondary_ammo 3
set g_balance_crylink_secondary_bouncedamagefactor 0.5
set g_balance_crylink_secondary_middle_lifetime 5 // range: 10000 full, fades to 10000
set g_balance_crylink_secondary_line_fadetime 2
// }}}
// {{{ nex
-set g_balance_nex_primary_ammo 7
+set g_balance_nex_primary_ammo 13
set g_balance_nex_primary_animtime 0.3
-set g_balance_nex_primary_damage 140
+set g_balance_nex_primary_damage 78
set g_balance_nex_primary_force 600
-set g_balance_nex_primary_refire 1.5
+set g_balance_nex_primary_refire 1.505
set g_balance_nex_primary_damagefalloff_mindist 9999999
set g_balance_nex_primary_damagefalloff_maxdist 9999999
set g_balance_nex_primary_damagefalloff_halflife 9999999
set g_balance_nex_primary_damagefalloff_forcehalflife 9999999
set g_balance_nex_secondary 0
+set g_balance_nex_secondary_charge 0
+set g_balance_nex_secondary_charge_rate 0.1
set g_balance_nex_secondary_damage 80
set g_balance_nex_secondary_force -500
set g_balance_nex_secondary_refire 1.25
set g_balance_nex_secondary_damagefalloff_halflife 9999999
set g_balance_nex_secondary_damagefalloff_forcehalflife 9999999
-set g_balance_nex_velocitydependent 0
-set g_balance_nex_velocitydependent_minspeed 400
-set g_balance_nex_velocitydependent_maxspeed 1000
+set g_balance_nex_charge 0
+set g_balance_nex_charge_start 0
+set g_balance_nex_charge_rate 0.1
+set g_balance_nex_charge_limit 0.5
+set g_balance_nex_charge_shot_multiplier 0.5
+set g_balance_nex_charge_velocity_rate 0.2
+set g_balance_nex_charge_minspeed 400
+set g_balance_nex_charge_maxspeed 1000
// }}}
// {{{ minstanex
set g_balance_minstanex_refire 1
// {{{ hagar
set g_balance_hagar_primary_damage 43
set g_balance_hagar_primary_edgedamage 15
-set g_balance_hagar_primary_force 100
+set g_balance_hagar_primary_force 94
set g_balance_hagar_primary_radius 70
set g_balance_hagar_primary_spread 0.010
set g_balance_hagar_primary_speed 3000
set g_balance_hagar_primary_lifetime 30
set g_balance_hagar_primary_refire 0.15
-set g_balance_hagar_primary_ammo 1
+set g_balance_hagar_primary_ammo 2
set g_balance_hagar_secondary 1
set g_balance_hagar_secondary_damage 43
set g_balance_hagar_secondary_edgedamage 15
set g_balance_hagar_secondary_lifetime_min 5
set g_balance_hagar_secondary_lifetime_rand 0
set g_balance_hagar_secondary_refire 0.15
-set g_balance_hagar_secondary_ammo 1
+set g_balance_hagar_secondary_ammo 2
// }}}
// {{{ rocketlauncher
-set g_balance_rocketlauncher_damage 130
-set g_balance_rocketlauncher_edgedamage 50
-set g_balance_rocketlauncher_force 597
+set g_balance_rocketlauncher_damage 65
+set g_balance_rocketlauncher_edgedamage 25
+set g_balance_rocketlauncher_force 360
set g_balance_rocketlauncher_radius 185
set g_balance_rocketlauncher_speed 900
set g_balance_rocketlauncher_speedaccel 0
set g_balance_rocketlauncher_lifetime 30
set g_balance_rocketlauncher_refire 1
set g_balance_rocketlauncher_animtime 0.3
-set g_balance_rocketlauncher_ammo 3
+set g_balance_rocketlauncher_ammo 7
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_guiderate 140 // max degrees per second
+set g_balance_rocketlauncher_guiderate 65 // 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_hlac_primary_spread_add 0.0045
set g_balance_hlac_primary_spread_crouchmod 0.25
-set g_balance_hlac_primary_damage 19
+set g_balance_hlac_primary_damage 17
set g_balance_hlac_primary_edgedamage 10
set g_balance_hlac_primary_force 45
set g_balance_hlac_primary_radius 70
set g_balance_hlac_primary_refire 0.1
set g_balance_hlac_primary_animtime 0.3
-set g_balance_hlac_primary_ammo 1
+set g_balance_hlac_primary_ammo 3
set g_balance_hlac_secondary 1
set g_balance_hlac_secondary_spread 0.15
set g_balance_hlac_secondary_refire 1
set g_balance_hlac_secondary_animtime 0.3
-set g_balance_hlac_secondary_ammo 10
+set g_balance_hlac_secondary_ammo 11
set g_balance_hlac_secondary_shots 6
// }}}
// {{{ campingrifle
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_tracer 0
set g_balance_campingrifle_primary_damage 75
set g_balance_campingrifle_primary_headshotaddeddamage 90
set g_balance_campingrifle_primary_spread 0
set g_balance_campingrifle_primary_burstcost 0 // require same cooldown as secondary, note it's smaller than primary refire time
set g_balance_campingrifle_primary_bullethail 0 // empty magazine on shot
set g_balance_campingrifle_secondary 1
+set g_balance_campingrifle_secondary_tracer 0
set g_balance_campingrifle_secondary_damage 40
set g_balance_campingrifle_secondary_headshotaddeddamage 20
set g_balance_campingrifle_secondary_spread 0.008
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_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_minelayer -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_pickup_ammo_anyway 0
set g_pickup_weapons_anyway 0
set g_pickup_shells 15
+set g_pickup_shells_weapon 15
set g_pickup_shells_max 999
set g_pickup_nails 80
+set g_pickup_nails_weapon 80
set g_pickup_nails_max 999
set g_pickup_rockets 15
+set g_pickup_rockets_weapon 15
set g_pickup_rockets_max 999
set g_pickup_cells 25
+set g_pickup_cells_weapon 25
set g_pickup_cells_max 999
set g_pickup_fuel 25
+set g_pickup_fuel_weapon 25
set g_pickup_fuel_jetpack 50
set g_pickup_fuel_max 999
set g_pickup_armorsmall 5
set g_balance_uzi_bulletconstant 115 // 13.1qu
// }}}
// {{{ mortar
-set g_balance_grenadelauncher_primary2secondary 0
-set g_balance_grenadelauncher_primary_sticky 0
+set g_balance_grenadelauncher_primary_type 0
set g_balance_grenadelauncher_primary_damage 70
set g_balance_grenadelauncher_primary_edgedamage 38
set g_balance_grenadelauncher_primary_force 400
set g_balance_grenadelauncher_primary_animtime 0.3
set g_balance_grenadelauncher_primary_ammo 2
set g_balance_grenadelauncher_primary_health 25
-set g_balance_grenadelauncher_secondary_sticky 0
+set g_balance_grenadelauncher_primary_damageforcescale 4
+set g_balance_grenadelauncher_primary_bouncefactor 0.5
+set g_balance_grenadelauncher_primary_bouncestop 0.075
+set g_balance_grenadelauncher_primary_remote_minbouncecnt 0
+set g_balance_grenadelauncher_secondary_type 1
set g_balance_grenadelauncher_secondary_damage 70
set g_balance_grenadelauncher_secondary_edgedamage 38
set g_balance_grenadelauncher_secondary_force 400
set g_balance_grenadelauncher_secondary_damageforcescale 4
set g_balance_grenadelauncher_secondary_bouncefactor 0.5
set g_balance_grenadelauncher_secondary_bouncestop 0.075
+set g_balance_grenadelauncher_secondary_remote_detonateprimary 0
+// }}}
+// {{{ minelayer // TODO
+set g_balance_minelayer_damage 35
+set g_balance_minelayer_edgedamage 30
+set g_balance_minelayer_force 250
+set g_balance_minelayer_radius 175
+set g_balance_minelayer_proximityradius 150
+set g_balance_minelayer_speed 750
+set g_balance_minelayer_lifetime 60
+set g_balance_minelayer_refire 1.5
+set g_balance_minelayer_animtime 0.4
+set g_balance_minelayer_ammo 5
+set g_balance_minelayer_health 15
+set g_balance_minelayer_limit 4 // 0 disables the limit
+set g_balance_minelayer_protection 1 // don't explode if the mine would hurt the owner or a team mate
+set g_balance_minelayer_damageforcescale 0
+set g_balance_minelayer_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_minelayer_time 0.5
+set g_balance_minelayer_remote_damage 45
+set g_balance_minelayer_remote_edgedamage 40
+set g_balance_minelayer_remote_radius 200
+set g_balance_minelayer_remote_force 300
// }}}
// {{{ electro
set g_balance_electro_lightning 0
set g_balance_nex_primary_damagefalloff_forcehalflife 1500
set g_balance_nex_secondary 0
+set g_balance_nex_secondary_charge 0
+set g_balance_nex_secondary_charge_rate 0.1
set g_balance_nex_secondary_damage 90
set g_balance_nex_secondary_force 200
set g_balance_nex_secondary_refire 1.5
set g_balance_nex_secondary_damagefalloff_halflife 1500
set g_balance_nex_secondary_damagefalloff_forcehalflife 1500
-set g_balance_nex_velocitydependent 0
-set g_balance_nex_velocitydependent_minspeed 400
-set g_balance_nex_velocitydependent_maxspeed 1000
+set g_balance_nex_charge 0
+set g_balance_nex_charge_start 0
+set g_balance_nex_charge_rate 0.1
+set g_balance_nex_charge_limit 0.5
+set g_balance_nex_charge_shot_multiplier 0.5
+set g_balance_nex_charge_velocity_rate 0.2
+set g_balance_nex_charge_minspeed 400
+set g_balance_nex_charge_maxspeed 1000
// }}}
// {{{ minstanex
set g_balance_minstanex_refire 1
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_tracer 0
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_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 1
+set g_balance_campingrifle_secondary_tracer 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_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_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_minelayer -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_pickup_ammo_anyway 1
set g_pickup_weapons_anyway 1
set g_pickup_shells 30
+set g_pickup_shells_weapon 30
set g_pickup_shells_max 120
set g_pickup_nails 80
+set g_pickup_nails_weapon 80
set g_pickup_nails_max 400
set g_pickup_rockets 30
+set g_pickup_rockets_weapon 30
set g_pickup_rockets_max 120
set g_pickup_cells 50
+set g_pickup_cells_weapon 50
set g_pickup_cells_max 200
set g_pickup_fuel 25
+set g_pickup_fuel_weapon 25
set g_pickup_fuel_jetpack 50
set g_pickup_fuel_max 999
set g_pickup_armorsmall 10
set g_balance_uzi_bulletconstant 115 // 13.1qu
// }}}
// {{{ mortar
-set g_balance_grenadelauncher_primary2secondary 0
-set g_balance_grenadelauncher_primary_sticky 0
+set g_balance_grenadelauncher_primary_type 0
set g_balance_grenadelauncher_primary_damage 50
set g_balance_grenadelauncher_primary_edgedamage 38
set g_balance_grenadelauncher_primary_force 400
set g_balance_grenadelauncher_primary_animtime 0.3
set g_balance_grenadelauncher_primary_ammo 2
set g_balance_grenadelauncher_primary_health 25
-set g_balance_grenadelauncher_secondary_sticky 0
+set g_balance_grenadelauncher_primary_damageforcescale 4
+set g_balance_grenadelauncher_primary_bouncefactor 0.5
+set g_balance_grenadelauncher_primary_bouncestop 0.075
+set g_balance_grenadelauncher_primary_remote_minbouncecnt 0
+
+set g_balance_grenadelauncher_secondary_type 1
set g_balance_grenadelauncher_secondary_damage 60
set g_balance_grenadelauncher_secondary_edgedamage 38
set g_balance_grenadelauncher_secondary_force 400
set g_balance_grenadelauncher_secondary_damageforcescale 4
set g_balance_grenadelauncher_secondary_bouncefactor 0.5
set g_balance_grenadelauncher_secondary_bouncestop 0.075
+set g_balance_grenadelauncher_secondary_remote_detonateprimary 1
+// }}}
+// {{{ minelayer // TODO
+set g_balance_minelayer_damage 35
+set g_balance_minelayer_edgedamage 30
+set g_balance_minelayer_force 250
+set g_balance_minelayer_radius 175
+set g_balance_minelayer_proximityradius 150
+set g_balance_minelayer_speed 750
+set g_balance_minelayer_lifetime 60
+set g_balance_minelayer_refire 1.5
+set g_balance_minelayer_animtime 0.4
+set g_balance_minelayer_ammo 5
+set g_balance_minelayer_health 15
+set g_balance_minelayer_limit 4 // 0 disables the limit
+set g_balance_minelayer_protection 1 // don't explode if the mine would hurt the owner or a team mate
+set g_balance_minelayer_damageforcescale 0
+set g_balance_minelayer_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_minelayer_time 0.5
+set g_balance_minelayer_remote_damage 45
+set g_balance_minelayer_remote_edgedamage 40
+set g_balance_minelayer_remote_radius 200
+set g_balance_minelayer_remote_force 300
// }}}
// {{{ electro
set g_balance_electro_lightning 0
set g_balance_nex_primary_damagefalloff_forcehalflife 1500
set g_balance_nex_secondary 0
+set g_balance_nex_secondary_charge 0
+set g_balance_nex_secondary_charge_rate 0.1
set g_balance_nex_secondary_damage 90
set g_balance_nex_secondary_force 300
set g_balance_nex_secondary_refire 1.5
set g_balance_nex_secondary_damagefalloff_halflife 1500
set g_balance_nex_secondary_damagefalloff_forcehalflife 1500
-set g_balance_nex_velocitydependent 0
-set g_balance_nex_velocitydependent_minspeed 400
-set g_balance_nex_velocitydependent_maxspeed 1000
+set g_balance_nex_charge 0
+set g_balance_nex_charge_start 0
+set g_balance_nex_charge_rate 0.1
+set g_balance_nex_charge_limit 0.5
+set g_balance_nex_charge_shot_multiplier 0.5
+set g_balance_nex_charge_velocity_rate 0.2
+set g_balance_nex_charge_minspeed 400
+set g_balance_nex_charge_maxspeed 1000
// }}}
// {{{ minstanex
set g_balance_minstanex_refire 1
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_tracer 0
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_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 1
+set g_balance_campingrifle_secondary_tracer 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_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_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_minelayer -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_pickup_ammo_anyway 1
set g_pickup_weapons_anyway 1
set g_pickup_shells 20
+set g_pickup_shells_weapon 10
set g_pickup_shells_max 45
set g_pickup_nails 120
+set g_pickup_nails_weapon 60
set g_pickup_nails_max 300
set g_pickup_rockets 25
+set g_pickup_rockets_weapon 15
set g_pickup_rockets_max 150
set g_pickup_cells 25
+set g_pickup_cells_weapon 15
set g_pickup_cells_max 200
set g_pickup_fuel 25
+set g_pickup_fuel_weapon 15
set g_pickup_fuel_jetpack 50
set g_pickup_fuel_max 100
set g_pickup_armorsmall 5
// }}}
// {{{ uzi
set g_balance_uzi_first 1
-set g_balance_uzi_first_damage 17
+set g_balance_uzi_first_damage 16
set g_balance_uzi_first_force 35
set g_balance_uzi_first_spread 0.03
set g_balance_uzi_first_refire 0.2
set g_balance_uzi_sustained_damage 9
set g_balance_uzi_sustained_force 7.5
set g_balance_uzi_sustained_spread 0.1
-set g_balance_uzi_sustained_refire 0.075
+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 // TODO
-set g_balance_grenadelauncher_primary2secondary 0
-set g_balance_grenadelauncher_primary_sticky 0
-set g_balance_grenadelauncher_primary_damage 60
+set g_balance_grenadelauncher_primary_type 0
+set g_balance_grenadelauncher_primary_damage 50
set g_balance_grenadelauncher_primary_edgedamage 25
set g_balance_grenadelauncher_primary_force 300
set g_balance_grenadelauncher_primary_radius 100
-set g_balance_grenadelauncher_primary_speed 1400
+set g_balance_grenadelauncher_primary_speed 1200
set g_balance_grenadelauncher_primary_speed_up 225
set g_balance_grenadelauncher_primary_speed_z 0
set g_balance_grenadelauncher_primary_spread 0
set g_balance_grenadelauncher_primary_refire 0.8
set g_balance_grenadelauncher_primary_animtime 0.4
set g_balance_grenadelauncher_primary_ammo 2
-set g_balance_grenadelauncher_primary_health 72
-set g_balance_grenadelauncher_secondary_sticky 1
-set g_balance_grenadelauncher_secondary_damage 90
+set g_balance_grenadelauncher_primary_health 80
+set g_balance_grenadelauncher_primary_damageforcescale 0
+set g_balance_grenadelauncher_primary_bouncefactor 0.5
+set g_balance_grenadelauncher_primary_bouncestop 0.12
+set g_balance_grenadelauncher_primary_remote_minbouncecnt 0
+
+set g_balance_grenadelauncher_secondary_type 1
+set g_balance_grenadelauncher_secondary_damage 70
set g_balance_grenadelauncher_secondary_edgedamage 32
set g_balance_grenadelauncher_secondary_force 300
set g_balance_grenadelauncher_secondary_radius 150
-set g_balance_grenadelauncher_secondary_speed 1400
+set g_balance_grenadelauncher_secondary_speed 1200
set g_balance_grenadelauncher_secondary_speed_up 225
set g_balance_grenadelauncher_secondary_speed_z 0
set g_balance_grenadelauncher_secondary_spread 0
-set g_balance_grenadelauncher_secondary_lifetime 5
-set g_balance_grenadelauncher_secondary_lifetime2 1
+set g_balance_grenadelauncher_secondary_lifetime 3
+set g_balance_grenadelauncher_secondary_lifetime2 0.65
set g_balance_grenadelauncher_secondary_refire 0.8
set g_balance_grenadelauncher_secondary_animtime 0.4
set g_balance_grenadelauncher_secondary_ammo 2
set g_balance_grenadelauncher_secondary_health 40
set g_balance_grenadelauncher_secondary_damageforcescale 0
-set g_balance_grenadelauncher_secondary_bouncefactor 0.7
+set g_balance_grenadelauncher_secondary_bouncefactor 0.5
set g_balance_grenadelauncher_secondary_bouncestop 0.12
+set g_balance_grenadelauncher_secondary_remote_detonateprimary 0
+// }}}
+// {{{ minelayer // TODO
+set g_balance_minelayer_damage 35
+set g_balance_minelayer_edgedamage 30
+set g_balance_minelayer_force 250
+set g_balance_minelayer_radius 175
+set g_balance_minelayer_proximityradius 150
+set g_balance_minelayer_speed 750
+set g_balance_minelayer_lifetime 60
+set g_balance_minelayer_refire 1.5
+set g_balance_minelayer_animtime 0.4
+set g_balance_minelayer_ammo 5
+set g_balance_minelayer_health 15
+set g_balance_minelayer_limit 4 // 0 disables the limit
+set g_balance_minelayer_protection 1 // don't explode if the mine would hurt the owner or a team mate
+set g_balance_minelayer_damageforcescale 0
+set g_balance_minelayer_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_minelayer_time 0.5
+set g_balance_minelayer_remote_damage 45
+set g_balance_minelayer_remote_edgedamage 40
+set g_balance_minelayer_remote_radius 200
+set g_balance_minelayer_remote_force 300
// }}}
// {{{ electro // TODO
set g_balance_electro_lightning 1
set g_balance_crylink_secondary_line_fadetime 2
// }}}
// {{{ nex
-set g_balance_nex_primary_damage 125
+set g_balance_nex_primary_damage 120
set g_balance_nex_primary_force 500
set g_balance_nex_primary_refire 1
set g_balance_nex_primary_animtime 0.75
set g_balance_nex_primary_ammo 5
-set g_balance_nex_primary_damagefalloff_mindist 500
-set g_balance_nex_primary_damagefalloff_maxdist 4500
-set g_balance_nex_primary_damagefalloff_halflife 2000
+set g_balance_nex_primary_damagefalloff_mindist 1000
+set g_balance_nex_primary_damagefalloff_maxdist 3000
+set g_balance_nex_primary_damagefalloff_halflife 1000
set g_balance_nex_primary_damagefalloff_forcehalflife 2000
set g_balance_nex_secondary 1
-set g_balance_nex_secondary_damage 125
-set g_balance_nex_secondary_force -700
-set g_balance_nex_secondary_refire 1
-set g_balance_nex_secondary_animtime 0.75
-set g_balance_nex_secondary_ammo 5
-set g_balance_nex_secondary_damagefalloff_mindist 500
-set g_balance_nex_secondary_damagefalloff_maxdist 4500
-set g_balance_nex_secondary_damagefalloff_halflife 2000
-set g_balance_nex_secondary_damagefalloff_forcehalflife 2000
+set g_balance_nex_secondary_charge 1
+set g_balance_nex_secondary_charge_rate 0.15
+set g_balance_nex_secondary_damage 0
+set g_balance_nex_secondary_force 0
+set g_balance_nex_secondary_refire 0
+set g_balance_nex_secondary_animtime 0
+set g_balance_nex_secondary_ammo 4
+set g_balance_nex_secondary_damagefalloff_mindist 0
+set g_balance_nex_secondary_damagefalloff_maxdist 0
+set g_balance_nex_secondary_damagefalloff_halflife 0
+set g_balance_nex_secondary_damagefalloff_forcehalflife 0
-set g_balance_nex_velocitydependent 1
-set g_balance_nex_velocitydependent_minspeed 400
-set g_balance_nex_velocitydependent_maxspeed 1000
+set g_balance_nex_charge 1
+set g_balance_nex_charge_start 0.2
+set g_balance_nex_charge_rate 0.05
+set g_balance_nex_charge_limit 0.5
+set g_balance_nex_charge_shot_multiplier 0.675
+set g_balance_nex_charge_velocity_rate 0.15
+set g_balance_nex_charge_minspeed 400
+set g_balance_nex_charge_maxspeed 1000
// }}}
// {{{ minstanex
set g_balance_minstanex_refire 1.25
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
-set g_balance_campingrifle_tracer 1
-set g_balance_campingrifle_primary_damage 50
-set g_balance_campingrifle_primary_headshotaddeddamage 50
+set g_balance_campingrifle_primary_tracer 1
+set g_balance_campingrifle_primary_damage 75
+set g_balance_campingrifle_primary_headshotaddeddamage 75
set g_balance_campingrifle_primary_spread 0
set g_balance_campingrifle_primary_force 2
set g_balance_campingrifle_primary_speed 35000
set g_balance_campingrifle_primary_lifetime 5
-set g_balance_campingrifle_primary_refire 0.8
-set g_balance_campingrifle_primary_animtime 0.8
+set g_balance_campingrifle_primary_refire 1.5
+set g_balance_campingrifle_primary_animtime 1.4
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 1
-set g_balance_campingrifle_secondary_damage 25
-set g_balance_campingrifle_secondary_headshotaddeddamage 25 // 50 damage only on head
-set g_balance_campingrifle_secondary_spread 0.008
-set g_balance_campingrifle_secondary_force 1
-set g_balance_campingrifle_secondary_speed 20000
+set g_balance_campingrifle_secondary_tracer 0
+set g_balance_campingrifle_secondary_damage 50
+set g_balance_campingrifle_secondary_headshotaddeddamage 50 // 50 damage only on head
+set g_balance_campingrifle_secondary_spread 0
+set g_balance_campingrifle_secondary_force 2
+set g_balance_campingrifle_secondary_speed 30000
set g_balance_campingrifle_secondary_lifetime 5
-set g_balance_campingrifle_secondary_refire 0.15
-set g_balance_campingrifle_secondary_animtime 0.1
+set g_balance_campingrifle_secondary_refire 1.5
+set g_balance_campingrifle_secondary_animtime 1.4
set g_balance_campingrifle_secondary_ammo 10
set g_balance_campingrifle_secondary_bulletconstant 130 // 18.3qu
set g_balance_campingrifle_secondary_burstcost 0
_cl_name Player
_cl_playermodel models/player/umbra.iqm
_cl_playerskin 0
-crosshair 1
+seta crosshair 3
+seta crosshair_color_red 0.6
+seta crosshair_color_green 0.8
+seta crosshair_color_blue 1
+seta crosshair_alpha 1
+seta crosshair_size 0.35
+seta crosshair_dot 1
+seta crosshair_dot_alpha 1
+seta crosshair_dot_size 1
seta crosshair_per_weapon 0 "when 1, each gun will display a different crosshair"
seta crosshair_color_override 0 "when 1, crosshair_color_* overrides the per-weapon color"
seta crosshair_effect_speed -1 "how fast (in seconds) some crosshair effects should take place, 0 = instant, -1 = 2x weapon switch time"
seta crosshair_grenadelauncher_color_blue 0 "crosshair color blue component to display when wielding the mortar"
seta crosshair_grenadelauncher_color_alpha 1.15 "crosshair alpha value to display when wielding the mortar"
seta crosshair_grenadelauncher_size 0.7 "crosshair size when wielding the mortar"
+seta crosshair_minelayer "" "crosshair to display when wielding the mortar"
+seta crosshair_minelayer_color_red 0.75 "crosshair color red component to display when wielding the mortar"
+seta crosshair_minelayer_color_green 0.75 "crosshair color green component to display when wielding the mortar"
+seta crosshair_minelayer_color_blue 0 "crosshair color blue component to display when wielding the mortar"
+seta crosshair_minelayer_color_alpha 1.15 "crosshair alpha value to display when wielding the mortar"
+seta crosshair_minelayer_size 0.9 "crosshair size when wielding the mortar"
seta crosshair_electro "" "crosshair to display when wielding the electro"
seta crosshair_electro_color_red 0.35 "crosshair color red component to display when wielding the electro"
seta crosshair_electro_color_green 0.5 "crosshair color green component to display when wielding the electro"
seta crosshair_campingrifle_color_blue 0.25 "crosshair color blue component to display when wielding the campingrifle"
seta crosshair_campingrifle_color_alpha 1 "crosshair alpha value to display when wielding the campingrifle"
seta crosshair_campingrifle_size 0.65 "crosshair size when wielding the campingrifle"
-seta crosshair_campingrifle_ring_size 1.5 "bullet counter ring size around campingrifle crosshair, multiple of crosshair_campingrifle_size"
seta crosshair_tuba "" "crosshair to display when wielding the tuba"
seta crosshair_tuba_color_red 0.85 "crosshair color red component to display when wielding the tuba"
seta crosshair_tuba_color_green 0.5 "crosshair color green component to display when wielding the tuba"
seta crosshair_fireball_color_blue 0.2 "crosshair color blue component to display when wielding the fireball"
seta crosshair_fireball_color_alpha 1 "crosshair alpha value to display when wielding the fireball"
seta crosshair_fireball_size 1 "crosshair size when wielding the fireball"
+seta crosshair_ring_size 3 "bullet counter ring size for Rifle, velocity ring for Nex"
+seta crosshair_campingrifle_bulletcounter_alpha 0.15
+seta crosshair_nexvelocity_alpha 0.15
seta cl_reticle_stretch 0 "whether to stretch reticles so they fit the screen (brakes image proportions)"
seta cl_reticle_item_nex 1 "draw aiming recticle for the nex weapon's zoom, 0 disables and values between 0 and 1 change alpha"
seta cl_reticle_item_normal 1 "draw recticle when zooming with the zoom button, 0 disables and values between 0 and 1 change alpha"
set sv_friction_on_land 0
exec physicsNoQWBunny-xpmbased.cfg
-set sv_player_viewoffset "0 0 35" "view offset of the player model"
+set sv_player_viewoffset "0 0 42" "view offset of the player model"
set sv_player_mins "-16 -16 -24" "playermodel mins"
set sv_player_maxs "16 16 45" "playermodel maxs"
-set sv_player_crouch_viewoffset "0 0 15" "view offset of the player model when crouched"
+set sv_player_crouch_viewoffset "0 0 20" "view offset of the player model when crouched"
set sv_player_crouch_mins "-16 -16 -24" "mins of a crouched playermodel"
set sv_player_crouch_maxs "16 16 25" "maxs of a crouched playermodel"
set 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 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_custom_weapon_priority_far "minstanex nex campingrifle rocketlauncher minelayer 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 minelayer 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 minelayer 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 sv_vote_call 1 "users can call a vote for the above commands"
set sv_vote_master 1 "users can call a vote to become master"
set sv_vote_master_password "" "when set, users can use \"vlogin PASSWORD\" to log in as master"
-set sv_vote_change 0 "set to 1 to allow to change you vote/mind"
+set sv_vote_change 1 "set to 1 to allow to change you vote/mind"
set sv_vote_singlecount 0 "set to 1 to count votes once after timeout or to 0 to count with every vote"
-set sv_vote_timeout 60 "a vote will timeout after this many seconds"
+set sv_vote_timeout 30 "a vote will timeout after this many seconds"
set sv_vote_wait 120 "a player can not call a vote again for this many seconds when his vote was not accepted"
set sv_vote_stop 15 "a player can not call a vote again for this many seconds when he stopped this vote (e.g. to correct it)"
set sv_vote_majority_factor 0.5 "which quotient of the PLAYERS constitute a majority? (try: 0.667, 0.75 when using the above)"
-set sv_vote_simple_majority_factor 0 "which quotient of the VOTERS constitute a majority too? (0 = off, otherwise it must be higher than or equal to sv_vote_majority_factor)"
+set sv_vote_simple_majority_factor 0.667 "which quotient of the VOTERS constitute a majority too? (0 = off, otherwise it must be higher than or equal to sv_vote_majority_factor)"
// when disabled, don't allow game type changes "note: set these two equal to JUST support simple majorities"
set sv_vote_override_mostrecent 0
alias vhelp "cmd vote help"
set cl_gravity 800 "but ignored anyway"
set g_ban_default_bantime 5400 "90 minutes"
-set g_ban_default_masksize 3 "whole 255.255.255.0 networks (set to 4 for single IPs); when UID support is compiled in, masksize 0 means banning by UID"
+set g_ban_default_masksize 3 "masksize 0 means banning by UID only, 1 means banning by /8 (IPv6: /32) network, 2 means banning by /16 (IPv6: /48) network, 3 means banning by /24 (IPv6: /56) network, 4 means banning by single IP (IPv6: /64 network)"
set g_banned_list "" "format: IP remainingtime IP remainingtime ..."
+set g_banned_list_idmode "1" "when set, the IP banning system always uses the ID over the IP address (so a user in a banned IP range can connect if they have a valid signed ID)"
alias bans "sv_cmd bans"
alias ban "sv_cmd ban $*" // usage: ban address(maybe incomplete, like 1.2.3) bantime(seconds)
alias kickban "sv_cmd kickban $*" // usage: kickban # playerno bantime(seconds) masksize(bytes)
r_textbrightness 0.2
r_textcontrast 0.8
-r_textshadow 1
+r_textshadow 0
+r_font_postprocess_blur 1
+r_font_postprocess_outline 1
// good settings for these fonts
con_chat 5
seta scoreboard_accuracy_doublerows 0 "use two rows instead of one"
seta scoreboard_accuracy 1 "0 = no weapon accuracy stats panel on scoreboard"
seta scoreboard_color_bg_r 0 "red color component of the HUD background"
-seta scoreboard_color_bg_g 0.25 "green color component of the HUD background"
-seta scoreboard_color_bg_b 0.17 "blue color component of the HUD background"
+seta scoreboard_color_bg_g 0.4 "green color component of the HUD background"
+seta scoreboard_color_bg_b 0.6 "blue color component of the HUD background"
seta scoreboard_color_bg_team 0.5 "team color multiplier of the HUD background"
seta scoreboard_alpha_bg 0.6 "scoreboard background alpha"
seta scoreboard_alpha_fg 1 "scoreboard foreground alpha"
set con_completion_vmap map
set con_completion_vnextmap map
set con_completion_vdomap map
+set con_completion_playermodel models/player/*.iqm
// these non-saved engine cvars shall be savedG
seta cl_port $cl_port
alias allready "sv_cmd allready"
-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 "minstanex rocketlauncher nex minelayer 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 (the special value 2 uses the weapon ID list for cycling)"
seta cl_weaponpriority0 "rocketlauncher grenadelauncher hagar seeker fireball" "use impulse 200 for prev gun from this list, 210 for best gun, 220 for next gun. Default value: explosives"
seta cl_weaponpriority1 "minstanex nex crylink hlac electro laser" "use impulse 201 for prev gun from this list, 211 for best gun, 221 for next gun. Default value: energy"
seta cl_weaponpriority2 "minstanex nex 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_weaponpriority4 "minelayer 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"
set g_weaponreplace_laser ""
set g_weaponreplace_shotgun ""
set g_weaponreplace_uzi ""
+set g_weaponreplace_minelayer ""
set g_weaponreplace_grenadelauncher ""
set g_weaponreplace_electro ""
set g_weaponreplace_crylink ""
scr_conscroll_x -0.1
scr_conscroll_y -0.3
+scr_loadingscreen_background 0
+scr_loadingscreen_barcolor "0 0.5 1"
+scr_loadingscreen_barheight 20
+scr_loadingscreen_count 1
+
// DP cannot properly detect this, so rather turn off the detection
r_texture_dds_load_dxt1_noalpha 1
// use fake light if map has no lightmaps
r_fakelight 1
+
+// strength sound settings
+set sv_strengthsound_antispam_time 0.1 "minimum distance of strength sounds"
+set sv_strengthsound_antispam_refire_threshold 0.04 "apply minimum distance only if refire of the gun is smaller than this"
type static
color 0x202020 0x404040
size 2 2
-sizeincrease 2
-alpha 256 256 512
+sizeincrease 0.2
+alpha 256 256 256
airfriction -4
velocityjitter 4 4 4
type smoke
tex 62 62
color 0x404040 0x808080
size 1 1
-alpha 256 256 256
+alpha 256 256 128
gravity -0.125
bounce 1.5
liquidfriction 4
effect electro_lightning
count 300
type spark
-color 0x501860 0x501860 // 0x202020 0x404040
+// color 0x501860 0x501860 // 0x202020 0x404040
+color 0x2030FF 0x80C0FF
tex 65 65
size 6 6
alpha 100 206 1724
--- /dev/null
+1 8 20 0 // fire
+9 5 20 0 // fire2
+15 200 20 1 // idle
+215 40 20 0 // reload
// These have been modified from Nexuiz 2.4.2's physicsQBR.cfg file and a bunch of other crap div0 threw on here :P
// DO NOT SCREW WITH friction on land, edge friction, step height, or sv_airaccel_qw
-
-sv_gravity 818
+sv_gravity 819
sv_maxspeed 420
sv_maxairspeed 283
+
sv_stopspeed 100
-sv_accelerate 14
-sv_airaccelerate 8
+sv_accelerate 13
+sv_airaccelerate 6
sv_friction 9.6 // higher values make you slide less
edgefriction 1 // div0 says no! lol
-sv_stepheight 34 // was told by divVerent not to mess with this, possibly to avoid breaking maps
-sv_jumpvelocity 308
+sv_stepheight 26
+sv_jumpvelocity 304
sv_wateraccelerate -1
sv_waterfriction -1
sv_airaccel_sideways_friction 0 // pain in the ass to tweak without screwing up the strafing
sv_airaccel_qw -0.93 //given a negative value to combat potential cheats, was told by divVerent not to mess with it
+
sv_airstopaccelerate 0
sv_airstrafeaccelerate 0
sv_maxairstrafespeed 0
+sv_airstrafeaccel_qw 0
sv_aircontrol 0
sv_aircontrol_penalty 0
sv_aircontrol_power 2
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
sv_warsowbunny_backtosideratio 0.8
-sv_friction_on_land 0 //Was told not to mess with this by divVerent, can cause hell for anti-lag
+sv_friction_on_land 0
sv_doublejump 0
sv_jumpspeedcap_min ""
sv_jumpspeedcap_max 0.38
-sv_jumpspeedcap_max_disable_on_ramps 1
-
+sv_jumpspeedcap_max_disable_on_ramps 0
float campingrifle_scope;
float nex_scope;
+
+float cr_maxbullets;
}
Tuba_Precache();
-#ifdef UID
- {
- // find the user ID
- string uid;
- registercvar("_cl_userid", "", CVAR_SAVE);
- uid = cvar_string("_cl_userid");
- if(strlen(uid) < 16)
- {
- uid = "";
- for(i = 0; i < 4; ++i)
- uid = strcat(uid, substring(ftos(floor(10000 + random() * 10000)), 1, -1));
- }
- cvar_set("_cl_userid", uid);
- localcmd(strcat("\ncmd uid ", uid, "\n"));
- }
-#endif
-
get_mi_min_max_texcoords(1); // try the CLEVER way first
minimapname = strcat("gfx/", mi_shortname, "_radar.tga");
shortmapname = mi_shortname;
self.angles = view_angles;
self.angles_x = -self.angles_x;
if not(self.cnt)
- R_AddEntity(self);
+ self.drawmask = MASK_NORMAL;
+ else
+ self.drawmask = 0;
}
void ShotOrg_Draw2D()
{
if(time - floor(time) > 0.5)
{
PolyDrawModel(self);
+ self.drawmask = 0;
}
else
{
self.renderflags = 0;
- R_AddEntity(self);
+ self.drawmask = MASK_NORMAL;
}
}
Net_WeaponComplain();
bHandled = true;
break;
+ case TE_CSQC_CR_MAXBULLETS:
+ cr_maxbullets = ReadByte();
+ bHandled = true;
+ break;
default:
// No special logic for this temporary entity; return 0 so the engine can handle it
bHandled = false;
input_angles = warpzone_fixview_cl_viewangles;
view_angles = warpzone_fixview_angles;
- if(cvar("cl_lockview") || autocvar__hud_configure)
+ if(cvar("cl_lockview") || (autocvar__hud_configure && spectatee_status <= 0))
{
pmove_org = freeze_pmove_org;
input_angles = view_angles = freeze_input_angles;
// the view to go back to normal, so reticle_type would become 0 as we fade out)
if(spectatee_status || getstati(STAT_HEALTH) <= 0)
reticle_type = 0; // prevent reticle from showing during the respawn zoom effect or for spectators
+ else if(activeweapon == WEP_NEX && (button_zoom || zoomscript_caught) || activeweapon == WEP_CAMPINGRIFLE && (button_zoom || zoomscript_caught) || activeweapon == WEP_MINSTANEX && (button_zoom || zoomscript_caught))
+ reticle_type = 2; // nex zoom
else if(button_zoom || zoomscript_caught)
reticle_type = 1; // normal zoom
else if(activeweapon == WEP_NEX && button_attack2 || activeweapon == WEP_CAMPINGRIFLE && button_attack2)
wcross_scale *= 1 - cvar("_menu_alpha");
wcross_alpha *= 1 - cvar("_menu_alpha");
+ ring_scale = cvar("crosshair_ring_size");
+
+ float f, a;
+ wcross_size = drawgetimagesize(wcross_name) * wcross_scale;
+
+ float nex_charge;
+ nex_charge = getstatf(STAT_NEX_CHARGE);
+
// ring around crosshair representing bullets left in camping rifle clip
- if (activeweapon == WEP_CAMPINGRIFLE)
+ if (activeweapon == WEP_CAMPINGRIFLE && cr_maxbullets)
{
- ring_scale = cvar("crosshair_campingrifle_ring_size");
- bullets = bound(0, getstati(STAT_BULLETS_LOADED), 4);
- }
- else
- bullets = 0;
+ bullets = getstati(STAT_BULLETS_LOADED);
+ f = bound(0, bullets / cr_maxbullets, 1);
-#define CROSSHAIR_DRAW_RING(i,j,sz,wcross_name,wcross_alpha) \
- drawpic(wcross_origin - ('0.5 0 0' * (sz * wcross_size_x * ring_scale + i * wcross_blur) + '0 0.5 0' * (sz * wcross_size_y * ring_scale + j * wcross_blur)), strcat("gfx/rifle_ring_", ftos(bullets)), sz * wcross_size * ring_scale, wcross_color, wcross_alpha, DRAWFLAG_NORMAL)
+ a = cvar("crosshair_campingrifle_bulletcounter_alpha");
+ DrawCircleClippedPic(wcross_origin, wcross_size_x * ring_scale, "gfx/crosshair_ring.tga", f, wcross_color, wcross_alpha * a, DRAWFLAG_ADDITIVE);
+ }
+ else if (activeweapon == WEP_NEX && nex_charge) // ring around crosshair representing velocity-dependent damage for the nex
+ {
+ a = cvar("crosshair_nexvelocity_alpha");
+ DrawCircleClippedPic(wcross_origin, wcross_size_x * ring_scale, "gfx/crosshair_ring.tga", nex_charge, wcross_color, wcross_alpha * a, DRAWFLAG_ADDITIVE);
+ }
#define CROSSHAIR_DO_BLUR(M,sz,wcross_name,wcross_alpha) \
do \
}
wcross_size = drawgetimagesize(wcross_name) * wcross_scale;
- if(bullets)
- {
- CROSSHAIR_DO_BLUR(CROSSHAIR_DRAW_RING, wcross_resolution, wcross_name, wcross_alpha);
- }
CROSSHAIR_DRAW(wcross_resolution, wcross_name, wcross_alpha * f);
+
+ if(cvar("crosshair_dot"))
+ CROSSHAIR_DRAW(wcross_resolution * cvar("crosshair_dot_size"), "gfx/crosshairdot.tga", wcross_alpha * f * cvar("crosshair_dot_alpha"));
+
wcross_name_alpha_goal_prev = f;
}
}
self.alpha = bound(0, self.cnt - time, 1);
if(self.alpha < ALPHA_MIN_VISIBLE)
+ {
Casing_Delete();
- else
- R_AddEntity(self);
+ self.drawmask = 0;
+ }
}
void Casing_Touch()
casing.angles_x = ReadByte() * 360 / 256;
casing.angles_y = ReadByte() * 360 / 256;
casing.angles_z = ReadByte() * 360 / 256;
+ casing.drawmask = MASK_NORMAL;
if(cvar("cl_casings") && isNew) {
casing.draw = Casing_Draw;
self.alpha = bound(0, self.nextthink - time, 1);
if(self.alpha < ALPHA_MIN_VISIBLE)
+ {
+ self.drawmask = 0;
Gib_Delete();
- else
- R_AddEntity(self);
+ }
}
void TossGib (string mdlname, vector org, vector vconst, vector vrand, float specnum, float destroyontouch, float issilent)
gib.damageforcescale = cvar_or("cl_gibs_damageforcescale", 3.5);
gib.nextthink = time + cvar_or("cl_gibs_lifetime", 14) * (1 + prandom() * 0.15);
+ gib.drawmask = MASK_NORMAL;
RubbleLimit("gib", cvar_or("cl_gibs_maxcount",100), Gib_Delete);
}
cursorsize = '32 32 0';
if(highlightcheck == 0)
- drawpic(mousepos, strcat("gfx/menu/", cvar_string("menu_skin"), "/cursor.tga"), '32 32 0', '1 1 1', 1, DRAWFLAG_NORMAL);
+ drawpic(mousepos, strcat("gfx/menu/", cvar_string("menu_skin"), "/cursor.tga"), '32 32 0', '1 1 1', hud_fade_alpha, DRAWFLAG_NORMAL);
else if(highlightcheck == 1)
- drawpic(mousepos - cursorsize * 0.5, strcat("gfx/menu/", cvar_string("menu_skin"), "/cursor_move.tga"), '32 32 0', '1 1 1', 1, DRAWFLAG_NORMAL);
+ drawpic(mousepos - cursorsize * 0.5, strcat("gfx/menu/", cvar_string("menu_skin"), "/cursor_move.tga"), '32 32 0', '1 1 1', hud_fade_alpha, DRAWFLAG_NORMAL);
else if(highlightcheck == 2)
- drawpic(mousepos - cursorsize * 0.5, strcat("gfx/menu/", cvar_string("menu_skin"), "/cursor_resize.tga"), '32 32 0', '1 1 1', 1, DRAWFLAG_NORMAL);
+ drawpic(mousepos - cursorsize * 0.5, strcat("gfx/menu/", cvar_string("menu_skin"), "/cursor_resize.tga"), '32 32 0', '1 1 1', hud_fade_alpha, DRAWFLAG_NORMAL);
else
- drawpic(mousepos - cursorsize * 0.5, strcat("gfx/menu/", cvar_string("menu_skin"), "/cursor_resize2.tga"), '32 32 0', '1 1 1', 1, DRAWFLAG_NORMAL);
+ drawpic(mousepos - cursorsize * 0.5, strcat("gfx/menu/", cvar_string("menu_skin"), "/cursor_resize2.tga"), '32 32 0', '1 1 1', hud_fade_alpha, DRAWFLAG_NORMAL);
prevMouseClicked = mouseClicked;
}
case WEP_UZI: return 1;
case WEP_CAMPINGRIFLE: return 1;
case WEP_GRENADE_LAUNCHER: return 2;
+ case WEP_MINE_LAYER: return 2;
case WEP_ELECTRO: return 3;
case WEP_CRYLINK: return 3;
case WEP_HLAC: return 3;
mySize -= '2 2 0' * panel_bg_padding;
}
- float armor, health;
+ float armor, health, fuel;
armor = getstati(STAT_ARMOR);
health = getstati(STAT_HEALTH);
-
- float fuel;
- fuel = getstati(GetAmmoStat(4)); // how much fuel do we have?
+ fuel = getstati(STAT_FUEL);
if(autocvar__hud_configure)
{
.float itime1, itime2;
void InterpolateOrigin_Reset()
{
- self.iflags &~= (IFLAG_PREVALID | IFLAG_VALID);
+ self.iflags &~= IFLAG_INTERNALMASK;
self.itime1 = self.itime2 = 0;
}
void InterpolateOrigin_Note()
{
float dt;
+ float f0;
dt = time - self.itime2;
+ f0 = self.iflags;
if(self.iflags & IFLAG_PREVALID)
self.iflags |= IFLAG_VALID;
else
if(self.iflags & IFLAG_ANGLES)
{
fixedmakevectors(self.angles);
- self.iforward1 = self.iforward2;
- self.iup1 = self.iup2;
+ if(f0 & IFLAG_VALID)
+ {
+ self.iforward1 = self.iforward2;
+ self.iup1 = self.iup2;
+ }
+ else
+ {
+ self.iforward1 = v_forward;
+ self.iup1 = v_up;
+ }
self.iforward2 = v_forward;
self.iup2 = v_up;
}
InterpolateOrigin_Do();
if(self.count & 0x80)
{
- traceline(self.origin, self.velocity, 0, self);
+ if(self.count & 0x10)
+ {
+ trace_endpos = self.velocity,
+ trace_dphitq3surfaceflags = 0;
+ }
+ else
+ traceline(self.origin, self.velocity, 0, self);
}
else
{
- makevectors(self.angles);
- traceline(self.origin, self.origin + v_forward * 32768, 0, self);
- if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
+ if(self.count & 0x10)
+ {
+ makevectors(self.angles);
trace_endpos = self.origin + v_forward * 1048576;
+ trace_dphitq3surfaceflags = Q3SURFACEFLAG_SKY;
+ }
+ else
+ {
+ makevectors(self.angles);
+ traceline(self.origin, self.origin + v_forward * 32768, 0, self);
+ if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
+ trace_endpos = self.origin + v_forward * 1048576;
+ }
}
if(self.scale != 0)
{
// 30 bytes, or 13 bytes for just moving
f = ReadByte();
- self.count = (f & 0xE0);
+ self.count = (f & 0xF0);
if(self.count & 0x80)
self.iflags = IFLAG_VELOCITY;
self.scale *= ReadByte() / 16.0; // beam radius
self.modelscale *= ReadByte() / 16.0; // dlight radius
}
- self.cnt = ReadShort() - 1; // effect number
+ if((f & 0x80) || !(f & 0x10))
+ self.cnt = ReadShort() - 1; // effect number
+ else
+ self.cnt = 0;
}
if(f & 2)
{
}
}
}
+
+void DrawCircleClippedPic(vector centre, float radius, string pic, float f, vector rgb, float a, float drawflag)
+{
+ float x, y, q, d;
+ vector ringsize, v, t;
+ ringsize = radius * '1 1 0';
+
+ x = cos(f * 2 * M_PI);
+ y = sin(f * 2 * M_PI);
+ q = fabs(x) + fabs(y);
+ x /= q;
+ y /= q;
+
+ if(f >= 1)
+ {
+ // draw full rectangle
+ R_BeginPolygon(pic, drawflag);
+ v = centre; t = '0.5 0.5 0';
+ v_x += 0.5 * ringsize_x; t += '0.5 0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+
+ v = centre; t = '0.5 0.5 0';
+ v_y += 0.5 * ringsize_y; t += '0.5 -0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+
+ v = centre; t = '0.5 0.5 0';
+ v_x -= 0.5 * ringsize_x; t -= '0.5 0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+
+ v = centre; t = '0.5 0.5 0';
+ v_y -= 0.5 * ringsize_y; t -= '0.5 -0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+ R_EndPolygon();
+
+ d = q - 1;
+ if(d > 0)
+ {
+ R_BeginPolygon(pic, drawflag);
+ v = centre; t = '0.5 0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+
+ v = centre; t = '0.5 0.5 0';
+ v_x += 0.5 * ringsize_x; t += '0.5 0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+ }
+ }
+ else if(f > 0.75)
+ {
+ // draw upper and first triangle
+ R_BeginPolygon(pic, drawflag);
+ v = centre; t = '0.5 0.5 0';
+ v_x += 0.5 * ringsize_x; t += '0.5 0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+
+ v = centre; t = '0.5 0.5 0';
+ v_y += 0.5 * ringsize_y; t += '0.5 -0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+
+ v = centre; t = '0.5 0.5 0';
+ v_x -= 0.5 * ringsize_x; t -= '0.5 0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+ R_EndPolygon();
+ R_BeginPolygon(pic, drawflag);
+ v = centre; t = '0.5 0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+
+ v = centre; t = '0.5 0.5 0';
+ v_x -= 0.5 * ringsize_x; t -= '0.5 0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+
+ v = centre; t = '0.5 0.5 0';
+ v_y -= 0.5 * ringsize_y; t -= '0.5 -0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+
+ d = q - 0.75;
+ if(d <= 0)
+ R_EndPolygon();
+ }
+ else if(f > 0.5)
+ {
+ // draw upper triangle
+ R_BeginPolygon(pic, drawflag);
+ v = centre; t = '0.5 0.5 0';
+ v_x += 0.5 * ringsize_x; t += '0.5 0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+
+ v = centre; t = '0.5 0.5 0';
+ v_y += 0.5 * ringsize_y; t += '0.5 -0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+
+ v = centre; t = '0.5 0.5 0';
+ v_x -= 0.5 * ringsize_x; t -= '0.5 0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+ R_EndPolygon();
+
+ d = q - 0.5;
+ if(d > 0)
+ {
+ R_BeginPolygon(pic, drawflag);
+ v = centre; t = '0.5 0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+
+ v = centre; t = '0.5 0.5 0';
+ v_x -= 0.5 * ringsize_x; t -= '0.5 0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+ }
+ }
+ else if(f > 0.25)
+ {
+ // draw first triangle
+ R_BeginPolygon(pic, drawflag);
+ v = centre; t = '0.5 0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+
+ v = centre; t = '0.5 0.5 0';
+ v_x += 0.5 * ringsize_x; t += '0.5 0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+
+ v = centre; t = '0.5 0.5 0';
+ v_y += 0.5 * ringsize_y; t += '0.5 -0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+
+ d = q - 0.25;
+ if(d <= 0)
+ R_EndPolygon();
+ }
+ else
+ {
+ d = q;
+ if(d > 0)
+ {
+ R_BeginPolygon(pic, drawflag);
+ v = centre; t = '0.5 0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+
+ v = centre; t = '0.5 0.5 0';
+ v_x += 0.5 * ringsize_x; t += '0.5 0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+ }
+ }
+
+ if(d > 0)
+ {
+ v = centre; t = '0.5 0.5 0';
+ v_x += x * 0.5 * ringsize_x; t += x * '0.5 0.5 0';
+ v_y += y * 0.5 * ringsize_y; t += y * '0.5 -0.5 0';
+ R_PolygonVertex(v, t, rgb, a);
+ R_EndPolygon();
+ }
+}
remove(self);
return;
}
+ self.drawmask = MASK_NORMAL;
if(self.scale <= 0)
+ {
+ self.drawmask = 0;
return;
- R_AddEntity(self);
+ }
}
void Ent_ModelEffect(float isNew)
else
Projectile_ResetTrail(trailorigin);
+ self.drawmask = 0;
+
if(!drawn)
return;
break;
}
- R_AddEntity(self);
+ self.drawmask = MASK_NORMAL;
}
void loopsound(entity e, float ch, string samp, float vol, float attn)
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_MINE: setmodel(self, "models/mine.md3");self.traileffect = particleeffectnum(""); break;
case PROJECTILE_LASER: setmodel(self, "models/laser.mdl");self.traileffect = particleeffectnum(""); break;
case PROJECTILE_HLAC: setmodel(self, "models/hlac_bullet.md3");self.traileffect = particleeffectnum(""); break;
case PROJECTILE_PORTO_RED: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_WIZSPIKE"); self.scale = 4; break;
self.move_bounce_factor = g_balance_grenadelauncher_secondary_bouncefactor;
self.move_bounce_stopspeed = g_balance_grenadelauncher_secondary_bouncestop;
break;
+ case PROJECTILE_MINE:
+ self.mins = '-4 -4 -4';
+ self.maxs = '4 4 4';
+ break;
case PROJECTILE_PORTO_RED:
self.colormod = '2 1 1';
self.alphamod = 0.5;
precache_model("models/ebomb.mdl");
precache_model("models/elaser.mdl");
precache_model("models/grenademodel.md3");
+ precache_model("models/mine.md3");
precache_model("models/hagarmissile.mdl");
precache_model("models/hlac_bullet.md3");
precache_model("models/laser.mdl");
.float lip;
.float bgmscriptangular;
+.float lodmodelindex0, lodmodelindex1, lodmodelindex2;
+.float loddistance1, loddistance2;
+.vector saved;
void Ent_Wall_Draw()
{
float f;
+ float d;
vector save;
var .vector fld;
+ if(self.bgmscriptangular)
+ self.angles = self.saved;
+ else
+ self.origin = self.saved;
+
+ if(self.lodmodelindex1)
+ {
+ d = cvar("loddebug");
+ if(d > 0)
+ {
+ if(d == 1)
+ self.modelindex = self.lodmodelindex0;
+ else if(d == 2 || !self.lodmodelindex2)
+ self.modelindex = self.lodmodelindex1;
+ else // if(d == 3)
+ self.modelindex = self.lodmodelindex2;
+ }
+ else
+ {
+ d = vlen(NearestPointOnBox(self, view_origin) - view_origin);
+ if(d < self.loddistance1)
+ self.modelindex = self.lodmodelindex0;
+ else if(!self.lodmodelindex2 || d < self.loddistance2)
+ self.modelindex = self.lodmodelindex1;
+ else
+ self.modelindex = self.lodmodelindex2;
+ }
+ }
+
InterpolateOrigin_Do();
if(self.bgmscriptangular)
- fld = angles;
+ self.saved = self.angles;
else
- fld = origin;
-
- save = self.fld;
+ self.saved = self.origin;
+
f = BGMScript(self);
if(f >= 0)
{
self.alpha = 1;
if(self.alpha >= ALPHA_MIN_VISIBLE)
- R_AddEntity(self);
-
- self.fld = save;
+ self.drawmask = MASK_NORMAL;
+ else
+ self.drawmask = 0;
}
void Ent_Wall_Remove()
InterpolateOrigin_Undo();
self.iflags = IFLAG_ANGLES;
+ if(self.bgmscriptangular)
+ self.angles = self.saved;
+ else
+ self.origin = self.saved;
+
f = ReadByte();
if(f & 1)
if(f & 8)
{
- self.modelindex = ReadShort();
+ if(f & 0x80)
+ {
+ self.lodmodelindex0 = ReadShort();
+ self.loddistance1 = ReadShort();
+ self.lodmodelindex1 = ReadShort();
+ self.loddistance2 = ReadShort();
+ self.lodmodelindex2 = ReadShort();
+ }
+ else
+ {
+ self.modelindex = ReadShort();
+ self.loddistance1 = 0;
+ self.loddistance2 = 0;
+ }
self.solid = ReadByte();
self.scale = ReadShort() / 256.0;
if(f & 0x20)
InterpolateOrigin_Note();
+ if(self.bgmscriptangular)
+ self.saved = self.angles;
+ else
+ self.saved = self.origin;
+
self.entremove = Ent_Wall_Remove;
self.draw = Ent_Wall_Draw;
}
{
float dh, n, i, o, f;
string s, sname, sframes;
+
dh = search_begin("models/sprites/*_frame*.tga", FALSE, FALSE);
n = search_getsize(dh);
for(i = 0; i < n; ++i)
db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname)))));
}
search_end(dh);
+
+ dh = search_begin("models/sprites/*_frame*.jpg", FALSE, FALSE);
+ n = search_getsize(dh);
+ for(i = 0; i < n; ++i)
+ {
+ s = search_getfilename(dh, i);
+ s = substring(s, 15, strlen(s) - 15 - 4); // strip models/sprites/ and .jpg
+
+ o = strstrofs(s, "_frame", 0);
+ sname = strcat("/spriteframes/", substring(s, 0, o));
+ sframes = substring(s, o + 6, strlen(s) - o - 6);
+ f = stof(sframes) + 1;
+ db_put(tempdb, sname, ftos(max(f, stof(db_get(tempdb, sname)))));
+ }
+ search_end(dh);
}
waypointsprite_initialized = 1;
}
const float TE_CSQC_WEAPONCOMPLAIN = 113;
const float TE_CSQC_CAMPINGRIFLE_SCOPE = 115;
const float TE_CSQC_NEX_SCOPE = 116;
+const float TE_CSQC_CR_MAXBULLETS = 117;
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 STAT_SHOTORG = 46; // compressShotOrigin
const float STAT_LEADLIMIT = 47;
const float STAT_BULLETS_LOADED = 48;
+const float STAT_NEX_CHARGE = 49;
// see DP source, quakedef.h
const float STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW = 222;
float PROJECTILE_ELECTRO_BEAM = 6;
float PROJECTILE_GRENADE = 7;
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;
-float PROJECTILE_HAGAR = 16;
-float PROJECTILE_HAGAR_BOUNCING = 17;
-float PROJECTILE_BULLET_GLOWING = 18;
-float PROJECTILE_CRYLINK_BOUNCING = 19;
-float PROJECTILE_FIREBALL = 20;
-float PROJECTILE_FIREMINE = 21;
-float PROJECTILE_BULLET_GLOWING_TRACER = 22;
+float PROJECTILE_MINE = 9;
+float PROJECTILE_LASER = 10;
+float PROJECTILE_HLAC = 11;
+float PROJECTILE_SEEKER = 12;
+float PROJECTILE_FLAC = 13;
+float PROJECTILE_PORTO_RED = 14;
+float PROJECTILE_PORTO_BLUE = 15;
+float PROJECTILE_HOOKBOMB = 16;
+float PROJECTILE_HAGAR = 17;
+float PROJECTILE_HAGAR_BOUNCING = 18;
+float PROJECTILE_BULLET_GLOWING = 19;
+float PROJECTILE_CRYLINK_BOUNCING = 20;
+float PROJECTILE_FIREBALL = 21;
+float PROJECTILE_FIREMINE = 22;
+float PROJECTILE_BULLET_GLOWING_TRACER = 23;
float SPECIES_HUMAN = 0;
float SPECIES_ROBOT_SOLID = 1;
else
fputs(fh, strcat("cdtrack ", _MapInfo_Map_worldspawn_music, "\n"));
}
- else if(_MapInfo_Map_worldspawn_music)
+ else
{
n = tokenize_console(cvar_string("g_cdtracks_remaplist"));
s = strcat(" ", cvar_string("g_cdtracks_dontusebydefault"), " ");
v_z = 0;
return v;
}
+
+#ifndef MENUQC
+vector NearestPointOnBox(entity box, vector org)
+{
+ vector m1, m2, nearest;
+
+ m1 = box.mins + box.origin;
+ m2 = box.maxs + box.origin;
+
+ nearest_x = bound(m1_x, org_x, m2_x);
+ nearest_y = bound(m1_y, org_y, m2_y);
+ nearest_z = bound(m1_z, org_z, m2_z);
+
+ return nearest;
+}
+#endif
HUD_Panel_GetName_Part2(id)
vector vec2(vector v);
+
+#ifndef MENUQC
+vector NearestPointOnBox(entity box, vector org);
+#endif
float log(float f) = #532;
string(string format, ...) sprintf = #627;
+
+//DP_CRYPTO
+//idea: divVerent
+//darkplaces implementation: divVerent
+//field definitions: (MENUQC)
+string crypto_getkeyfp(string serveraddress) = #633; // retrieves the cached host key's CA fingerprint of a server given by IP address
+string crypto_getidfp(string serveraddress) = #634; // retrieves the cached host key fingerprint of a server given by IP address
+string crypto_getencryptlevel(string serveraddress) = #635; // 0 if never encrypting, 1 supported, 2 requested, 3 required, appended by list of allowed methods in order of preference ("AES128"), preceded by a space each
+//description:
SKINFLOAT(ALPHA_SERVERLIST_HIGHPING, 0.4);
SKINFLOAT(ALPHA_SERVERLIST_FAVORITE, 0.8);
SKINVECTOR(COLOR_SERVERLIST_FAVORITE, '1 1 1');
+ SKINFLOAT(ALPHA_SERVERLIST_IMPOSSIBLE, 0.7);
+ SKINVECTOR(COLOR_SERVERLIST_IMPOSSIBLE, '0.3 0.3 0.3');
// item: server info
SKINVECTOR(COLOR_SERVERINFO_NAME, '1 1 1');
ATTRIB(XonoticCrosshairButton, useDownAsChecked, float, 1)
ATTRIB(XonoticCrosshairButton, src3, string, string_null)
+ ATTRIB(XonoticCrosshairButton, src4, string, string_null)
ATTRIB(XonoticCrosshairButton, cvarName, string, string_null)
ATTRIB(XonoticCrosshairButton, cvarValueFloat, float, 0)
me.configureRadioButton(me, string_null, me.fontSize, me.image, theGroup, 0);
me.srcMulti = 1;
me.src3 = strzone(strcat("/gfx/crosshair", ftos(me.cvarValueFloat)));
+ me.src4 = "/gfx/crosshairdot";
}
void XonoticCrosshairButton_setChecked(entity me, float val)
{
sz = draw_PictureSize(me.src3);
sz = globalToBoxSize(sz, draw_scale);
- sz = sz * cvar("crosshair_size");
+ sz = (10 * '1 1 0' + sz * cvar("crosshair_size")) * 0.05; // (10 * '1 1 0' + ...) * 0.05 here to make visible size changes happen also at bigger sizes
if(sz_x > 0.95)
sz = sz * (0.95 / sz_x);
if(sz_y > 0.95)
sz = sz * (0.95 / sz_y);
draw_Picture('0.5 0.5 0' - 0.5 * sz, me.src3, sz, rgb, a);
+ if(cvar("crosshair_dot"))
+ draw_Picture('0.5 0.5 0' - 0.5 * sz * cvar("crosshair_dot_size"), me.src4, sz * cvar("crosshair_dot_size"), rgb, a * cvar("crosshair_dot_alpha"));
}
#endif
me.TDempty(me, 0.2);
me.TD(me, 1, 2, e = makeXonoticRadioButton(1, "g_start_weapon_laser", "0", "No start weapons"));
e.cvarOffValue = "-1";
- makeMulti(e, "g_start_weapon_shotgun g_start_weapon_uzi g_start_weapon_grenadelauncher g_start_weapon_electro g_start_weapon_crylink g_start_weapon_nex g_start_weapon_hagar g_start_weapon_rocketlauncher g_start_weapon_campingrifle g_start_weapon_hlac g_start_weapon_seeker g_start_weapon_minstanex g_start_weapon_hook g_start_weapon_porto g_start_weapon_tuba");
+ makeMulti(e, "g_start_weapon_shotgun g_start_weapon_uzi g_start_weapon_grenadelauncher g_start_weapon_minelayer g_start_weapon_electro g_start_weapon_crylink g_start_weapon_nex g_start_weapon_hagar g_start_weapon_rocketlauncher g_start_weapon_campingrifle g_start_weapon_hlac g_start_weapon_seeker g_start_weapon_minstanex g_start_weapon_hook g_start_weapon_porto g_start_weapon_tuba");
me.gotoRC(me, me.rows - 1, 0);
me.TD(me, 1, me.columns, e = makeXonoticButton("OK", '0 0 0'));
ATTRIB(XonoticServerInfoDialog, title, string, "Server Information")
ATTRIB(XonoticServerInfoDialog, color, vector, SKINCOLOR_DIALOG_SERVERINFO)
ATTRIB(XonoticServerInfoDialog, intendedWidth, float, 0.68)
- ATTRIB(XonoticServerInfoDialog, rows, float, 11)
+ ATTRIB(XonoticServerInfoDialog, rows, float, 14)
ATTRIB(XonoticServerInfoDialog, columns, float, 12)
ATTRIB(XonoticServerInfoDialog, currentServerName, string, string_null)
ATTRIB(XonoticServerInfoDialog, currentServerMod, string, string_null)
ATTRIB(XonoticServerInfoDialog, currentServerVersion, string, string_null)
ATTRIB(XonoticServerInfoDialog, currentServerPing, string, string_null)
+ ATTRIB(XonoticServerInfoDialog, currentServerKey, string, string_null)
+ ATTRIB(XonoticServerInfoDialog, currentServerID, string, string_null)
+ ATTRIB(XonoticServerInfoDialog, currentServerEncrypt, string, string_null)
+ ATTRIB(XonoticServerInfoDialog, currentServerCanConnect, string, string_null)
ATTRIB(XonoticServerInfoDialog, nameLabel, entity, NULL)
ATTRIB(XonoticServerInfoDialog, cnameLabel, entity, NULL)
ATTRIB(XonoticServerInfoDialog, modLabel, entity, NULL)
ATTRIB(XonoticServerInfoDialog, versionLabel, entity, NULL)
ATTRIB(XonoticServerInfoDialog, pingLabel, entity, NULL)
+ ATTRIB(XonoticServerInfoDialog, keyLabel, entity, NULL)
+ ATTRIB(XonoticServerInfoDialog, idLabel, entity, NULL)
+ ATTRIB(XonoticServerInfoDialog, encryptLabel, entity, NULL)
+ ATTRIB(XonoticServerInfoDialog, canConnectLabel, entity, NULL)
ENDCLASS(XonoticServerInfoDialog)
float SLIST_FIELD_NAME;
me.currentServerType = strzone(typestr);
me.typeLabel.setText(me.typeLabel, me.currentServerType);
-
SLIST_FIELD_MAP = gethostcacheindexforkey("map");
me.currentServerMap = strzone(gethostcachestring(SLIST_FIELD_MAP, i));
me.mapLabel.setText(me.mapLabel, me.currentServerMap);
s = ftos(gethostcachenumber(SLIST_FIELD_PING, i));
me.currentServerPing = strzone(s);
me.pingLabel.setText(me.pingLabel, me.currentServerPing);
+
+ print(me.currentServerCName, "\n");
+
+ s = crypto_getidfp(me.currentServerCName);
+ if not(s)
+ s = "N/A";
+ me.currentServerID = strzone(s);
+ me.idLabel.setText(me.idLabel, me.currentServerID);
+
+ s = crypto_getkeyfp(me.currentServerCName);
+ if not(s)
+ s = "N/A";
+ me.currentServerKey = strzone(s);
+ me.keyLabel.setText(me.keyLabel, me.currentServerKey);
+
+ s = crypto_getencryptlevel(me.currentServerCName);
+ if(s == "")
+ {
+ if(cvar("crypto_aeslevel") >= 3)
+ me.currentServerEncrypt = "N/A (can't connect)";
+ else
+ me.currentServerEncrypt = "N/A";
+ }
+ else switch(stof(substring(s, 0, 1)))
+ {
+ case 0:
+ if(cvar("crypto_aeslevel") >= 3)
+ me.currentServerEncrypt = "not supported (can't connect)";
+ else
+ me.currentServerEncrypt = "not supported";
+ break;
+ case 1:
+ me.currentServerEncrypt = "supported";
+ break;
+ case 2:
+ me.currentServerEncrypt = "requested";
+ break;
+ case 3:
+ if(cvar("crypto_aeslevel") <= 0)
+ me.currentServerEncrypt = "required (can't connect)";
+ else
+ me.currentServerEncrypt = "required";
+ break;
+ }
+ me.encryptLabel.setText(me.encryptLabel, me.currentServerEncrypt);
}
void XonoticServerInfoDialog_fill(entity me)
e.allowCut = 1;
me.pingLabel = e;
+ me.TR(me);
+ me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, "CA:"));
+ me.TD(me, 1, 4.0, e = makeXonoticTextLabel(0, ""));
+ e.allowCut = 1;
+ me.keyLabel = e;
+
+ me.TR(me);
+ me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, "Key:"));
+ me.TD(me, 1, 4.0, e = makeXonoticTextLabel(0, ""));
+ e.allowCut = 1;
+ me.idLabel = e;
+
+ me.TR(me);
+ me.TD(me, 1, 1.75, e = makeXonoticTextLabel(0, "Encryption:"));
+ me.TD(me, 1, 4.0, e = makeXonoticTextLabel(0, ""));
+ e.allowCut = 1;
+ me.encryptLabel = e;
+
me.gotoRC(me, me.rows - 1, 0);
me.TD(me, 1, me.columns - 6, e = makeXonoticButton("Close", '0 0 0'));
}
me.gotoRC(me, 0, 3.5); me.setFirstColumn(me, me.currentColumn);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Field of View:"));
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Field of view:"));
me.TD(me, 1, 2, e = makeXonoticSlider(60, 130, 1, "fov"));
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Damage kick:"));
me.TR(me);
sl = makeXonoticSlider(0.45, 0.75, 0.01, "cl_bobcycle");
me.TD(me, 1, 1, e = makeXonoticSliderCheckBox(0, 1, sl, "View bobbing:"));
- me.TD(me, 1, 2, sl);
-
- me.TR(me);
+ me.TD(me, 1, 2, sl);
me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Zoom Factor:"));
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Zoom factor:"));
me.TD(me, 1, 2, e = makeXonoticSlider(2, 16, 0.5, "cl_zoomfactor"));
me.TR(me);
sl = makeXonoticSlider(1, 8, 0.5, "cl_zoomspeed");
e0.textEntity = main.weaponsDialog;
e0.allowCut = 1;
me.TR(me);
- me.TR(me);
- me.TD(me, 1, 2, e = makeXonoticCheckBox(0, "crosshair_per_weapon", "Per weapon crosshairs"));
- me.TD(me, 1, 1.3, e = makeXonoticCheckBox(1, "crosshair_color_override", "& crosshair colors"));
+ me.TD(me, 1, 0.75, e = makeXonoticTextLabel(0, "Crosshair:"));
+ me.TD(me, 1, 1.00, e = makeXonoticCheckBox(0, "crosshair_per_weapon", "Per weapon"));
+ me.TD(me, 1, 1.25, e = makeXonoticCheckBox(1, "crosshair_color_override", "& Per weapon colors"));
setDependent(e, "crosshair_per_weapon", 1, 1);
me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Crosshair:"));
+ me.TDempty(me, 0.5);
for(i = 1; i <= 10; ++i) {
me.TDNoMargin(me, 1, 2 / 10, e = makeXonoticCrosshairButton(3, i), '1 1 0');
setDependent(e, "crosshair_per_weapon", 0, 0);
}
me.TR(me);
- me.TDempty(me, 1);
+ me.TDempty(me, 0.5);
for(i = 11; i <= 20; ++i) {
me.TDNoMargin(me, 1, 2 / 10, e = makeXonoticCrosshairButton(3, i), '1 1 0');
setDependent(e, "crosshair_per_weapon", 0, 0);
}
me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Crosshair Size:"));
- me.TD(me, 1, 2, e = makeXonoticSlider(0.40, 2, 0.05, "crosshair_size"));
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Crosshair size:"));
+ me.TD(me, 1, 1.8, e = makeXonoticSlider(0.10, 1.5, 0.05, "crosshair_size"));
me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Crosshair Alpha:"));
- me.TD(me, 1, 2, e = makeXonoticSlider(0, 1, 0.01, "crosshair_color_alpha"));
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Crosshair alpha:"));
+ me.TD(me, 1, 1.8, e = makeXonoticSlider(0, 1, 0.1, "crosshair_color_alpha"));
me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Crosshair Red:"));
- me.TD(me, 1, 2, e = makeXonoticSlider(0, 1, 0.01, "crosshair_color_red"));
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Crosshair red:"));
+ me.TD(me, 1, 1.8, e = makeXonoticSlider(0, 1, 0.01, "crosshair_color_red"));
setDependentOR(e, "crosshair_per_weapon", 0, 0, "crosshair_color_override", 1, 1);
me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Crosshair Green:"));
- me.TD(me, 1, 2, e = makeXonoticSlider(0, 1, 0.01, "crosshair_color_green"));
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Crosshair green:"));
+ me.TD(me, 1, 1.8, e = makeXonoticSlider(0, 1, 0.01, "crosshair_color_green"));
setDependentOR(e, "crosshair_per_weapon", 0, 0, "crosshair_color_override", 1, 1);
me.TR(me);
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Crosshair Blue:"));
- me.TD(me, 1, 2, e = makeXonoticSlider(0, 1, 0.01, "crosshair_color_blue"));
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Crosshair blue:"));
+ me.TD(me, 1, 1.8, e = makeXonoticSlider(0, 1, 0.01, "crosshair_color_blue"));
setDependentOR(e, "crosshair_per_weapon", 0, 0, "crosshair_color_override", 1, 1);
+ me.TR(me);
+ me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "crosshair_dot", "Enable centered dot"));
+ me.TR(me);
+ me.TDempty(me, 0.2);
+ me.TD(me, 1, 0.5, e = makeXonoticTextLabel(0, "Size:"));
+ me.TD(me, 1, 0.9, e = makeXonoticSlider(0.2, 2, 0.1, "crosshair_dot_size"));
+ setDependent(e, "crosshair_dot", 1, 1);
+ me.TD(me, 1, 0.5, e = makeXonoticTextLabel(0, "Alpha:"));
+ me.TD(me, 1, 0.9, e = makeXonoticSlider(0.10, 1, 0.1, "crosshair_dot_alpha"));
+ setDependent(e, "crosshair_dot", 1, 1);
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Hit test:"));
me.TD(me, 1, 2/3, e = makeXonoticRadioButton(1, "crosshair_hittest", "0", "None"));
me.TDempty(me, 0.5);
me.TR(me);
me.TDempty(me, 0.4);
- me.TD(me, 1, 2.2, e = makeXonoticButton("HUD Setup", '0 0 0'));
+ me.TD(me, 1, 2.2, e = makeXonoticButton("Enter HUD editor", '0 0 0'));
e.onClick = HUDSetup_Join_Click;
e.onClickEntity = me;
me.TDempty(me, 0.5);
me.TR(me);
#ifdef ALLOW_FORCEMODELS
- me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Force Models:"));
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, "Force models:"));
me.TD(me, 1, 2/3, e = makeXonoticRadioButton(2, string_null, string_null, "None"));
me.TD(me, 1, 2/3, e = makeXonoticRadioButton(2, "cl_forceplayermodelsfromxonotic", string_null, "Custom"));
me.TD(me, 1, 2/3, e = makeXonoticRadioButton(2, "cl_forceplayermodels", string_null, "All"));
float IsFavorite(string srv)
{
+ string p;
float i, n;
+ if(srv == "")
+ return FALSE;
srv = netaddress_resolve(srv, 26000);
+ p = crypto_getidfp(srv);
n = tokenize_console(cvar_string("net_slist_favorites"));
for(i = 0; i < n; ++i)
- if(srv == netaddress_resolve(argv(i), 26000))
- return TRUE;
+ {
+ if(substring(argv(i), 0, 1) != "[" && strlen(argv(i)) == 44 && strstrofs(argv(i), ".", 0) < 0)
+ {
+ if(p)
+ if(argv(i) == p)
+ return TRUE;
+ }
+ else
+ {
+ if(srv == netaddress_resolve(argv(i), 26000))
+ return TRUE;
+ }
+ }
return FALSE;
}
void ToggleFavorite(string srv)
{
- string s, s0, s1, s2, srv_resolved;
- float i, n;
+ string s, s0, s1, s2, srv_resolved, p;
+ float i, n, f;
srv_resolved = netaddress_resolve(srv, 26000);
+ p = crypto_getidfp(srv_resolved);
s = cvar_string("net_slist_favorites");
n = tokenize_console(s);
+ f = 0;
for(i = 0; i < n; ++i)
- if(srv_resolved == netaddress_resolve(argv(i), 26000))
+ {
+ if(substring(argv(i), 0, 1) != "[" && strlen(argv(i)) == 44 && strstrofs(argv(i), ".", 0) < 0)
{
- s0 = s1 = s2 = "";
- if(i > 0)
- s0 = substring(s, 0, argv_end_index(i - 1));
- if(i < n-1)
- s2 = substring(s, argv_start_index(i + 1), -1);
- if(s0 != "" && s2 != "")
- s1 = " ";
- print("s0 = >>", s0, "<<\ns1 = >>", s1, "<<\ns2 = >>", s2, "<<\n");
- cvar_set("net_slist_favorites", strcat(s0, s1, s2));
- return;
+ if(p)
+ if(argv(i) != p)
+ continue;
}
+ else
+ {
+ if(srv_resolved != netaddress_resolve(argv(i), 26000))
+ continue;
+ }
+ s0 = s1 = s2 = "";
+ if(i > 0)
+ s0 = substring(s, 0, argv_end_index(i - 1));
+ if(i < n-1)
+ s2 = substring(s, argv_start_index(i + 1), -1);
+ if(s0 != "" && s2 != "")
+ s1 = " ";
+ cvar_set("net_slist_favorites", strcat(s0, s1, s2));
+ s = cvar_string("net_slist_favorites");
+ n = tokenize_console(s);
+ f = 1;
+ --i;
+ }
- s1 = "";
- if(s != "")
- s1 = " ";
- cvar_set("net_slist_favorites", strcat(s, " ", srv));
+ if(!f)
+ {
+ s1 = "";
+ if(s != "")
+ s1 = " ";
+ if(p)
+ cvar_set("net_slist_favorites", strcat(s, s1, p));
+ else
+ cvar_set("net_slist_favorites", strcat(s, s1, srv));
+ }
resorthostcache();
}
{
// layout: Ping, Server name, Map name, NP, TP, MP
string s;
- float p;
+ float p, q;
vector theColor;
float theAlpha;
theAlpha = theAlpha * (1 - SKINALPHA_SERVERLIST_FAVORITE) + SKINALPHA_SERVERLIST_FAVORITE;
}
+ s = gethostcachestring(SLIST_FIELD_CNAME, i);
+ q = stof(substring(crypto_getencryptlevel(s), 0, 1));
+ if((q <= 0 && cvar("crypto_aeslevel") >= 3) || (q >= 3 && cvar("crypto_aeslevel") <= 0))
+ {
+ theColor = SKINCOLOR_SERVERLIST_IMPOSSIBLE;
+ theAlpha = SKINALPHA_SERVERLIST_IMPOSSIBLE;
+ }
+ // TODO show an icon for encryption status
+
s = ftos(p);
draw_Text(me.realUpperMargin * eY + (me.columnPingSize - draw_TextWidth(s, 0, me.realFontSize)) * eX, s, me.realFontSize, theColor, theAlpha, 0);
s = draw_TextShortenToWidth(gethostcachestring(SLIST_FIELD_NAME, i), me.columnNameSize, 0, me.realFontSize);
<Unit filename="w_electro.qc" />
<Unit filename="w_fireball.qc" />
<Unit filename="w_grenadelauncher.qc" />
+ <Unit filename="w_minelayer.qc" />
<Unit filename="w_hagar.qc" />
<Unit filename="w_hlac.qc" />
<Unit filename="w_hook.qc" />
local float nex ; nex =-1000;
local float hagar ; hagar =-1000;
local float grenade ; grenade =-1000;
+ local float mine ; mine =-1000;
local float electro ; electro =-1000;
local float crylink ; crylink =-1000;
local float uzi ; uzi =-1000;
grenade = (cvar("g_balance_grenadelauncher_primary_damage")/cvar("g_balance_grenadelauncher_primary_refire")*1.0)
* bound(0,(cvar("g_balance_grenadelauncher_primary_speed")/distance*maxdelaytime),1)*1.1;
+ if (client_hasweapon(self, WEP_MINE_LAYER, TRUE, FALSE) &&
+ !(
+ cvar("bot_ai_weapon_combo") && self.weapon == WEP_MINE_LAYER &&
+ af > combo_time
+ )
+ )
+ mine = (cvar("g_balance_minelayer_damage")/cvar("g_balance_minelayer_refire")*1.0)
+ * bound(0,(cvar("g_balance_minelayer_speed")/distance*maxdelaytime),1)*1.1;
+
if (client_hasweapon(self, WEP_ELECTRO, TRUE, FALSE) &&
!( cvar("bot_ai_weapon_combo") && self.weapon == WEP_ELECTRO &&
af > combo_time
dprint("Nex: " , ftos(nex ), "\n");
dprint("Hagar: " , ftos(hagar ), "\n");
dprint("Grenade: ", ftos(grenade ), "\n");
+ dprint("Mine: " , ftos(mine ), "\n");
dprint("Electro: ", ftos(electro ), "\n");
dprint("Crylink: ", ftos(crylink ), "\n");
dprint("Uzi: " , ftos(uzi ), "\n");
w = WEP_NEX ;s = nex ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
w = WEP_HAGAR ;s = hagar ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
w = WEP_GRENADE_LAUNCHER ;s = grenade ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
+ w = WEP_MINE_LAYER ;s = mine ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
w = WEP_ELECTRO ;s = electro ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
w = WEP_CRYLINK ;s = crylink ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
w = WEP_UZI ;s = uzi ;if (s > bestscore){bestscore = s;bestweapon = w;} if (self.switchweapon == w) currentscore = s;
WriteByte(0, TE_CSQC_TEAMNAGGER);
}
+void send_CSQC_cr_maxbullets(entity e) {
+ msg_entity = e;
+ WriteByte(MSG_ONE, SVC_TEMPENTITY);
+ WriteByte(MSG_ONE, TE_CSQC_CR_MAXBULLETS);
+ WriteByte(MSG_ONE, cvar("g_balance_campingrifle_magazinecapacity"));
+}
+
void Announce(string snd) {
WriteByte(MSG_ALL, SVC_TEMPENTITY);
WriteByte(MSG_ALL, TE_CSQC_ANNOUNCE);
self.effects = 0;
self.air_finished = time + 12;
self.dmg = 2;
+ if(cvar("g_balance_nex_charge"))
+ self.nex_charge = cvar("g_balance_nex_charge_start");
if(inWarmupStage)
{
string ColoredTeamName(float t);
void DecodeLevelParms (void);
//void dom_player_join_team(entity pl);
-#ifdef UID
-.float uid_kicktime;
-.string uid;
-#endif
void ClientConnect (void)
{
float t;
else
self.hitplotfh = -1;
-#ifdef UID
- if(clienttype(self) == CLIENTTYPE_REAL)
- if not(self.uid)
- self.uid_kicktime = time + 60;
-#endif
-
if(g_race || g_cts) {
string rr;
if(g_cts)
else if(cvar("sv_teamnagger") && !(cvar("bot_vs_human") && (c3==-1 && c4==-1)) && !g_ca) // teamnagger is currently bad for ca
send_CSQC_teamnagger();
+ send_CSQC_cr_maxbullets(self);
+
CheatInitClient();
}
self.stat_count -= 1;
}
-#ifdef UID
- if(self.uid_kicktime)
- if(time > self.uid_kicktime)
- {
- bprint("^3", self.netname, "^3 was kicked for missing UID.\n");
- dropclient(self);
- return;
- }
-#endif
-
if(sv_maxidle && frametime)
{
// WORKAROUND: only use dropclient in server frames (frametime set). Never use it in cl_movement frames (frametime zero).
.float multijump_ready;
.float prevjumpbutton;
+.float nexspeed;
+
/*
=============
PlayerJump
}
}
}
+
+ float xyspeed;
+ xyspeed = vlen('1 0 0' * self.velocity_x + '0 1 0' * self.velocity_y);
+ if(self.weapon == WEP_NEX && cvar("g_balance_nex_charge") && cvar("g_balance_nex_charge_velocity_rate") && xyspeed > cvar("g_balance_nex_charge_minspeed"))
+ {
+ // add a maximum of charge_velocity_rate when going fast (f = 1), gradually increasing from minspeed (f = 0) to maxspeed
+ xyspeed = min(xyspeed, cvar("g_balance_nex_charge_maxspeed"));
+ float f;
+ f = (xyspeed - cvar("g_balance_nex_charge_minspeed")) / (cvar("g_balance_nex_charge_maxspeed") - cvar("g_balance_nex_charge_minspeed"));
+ // add the extra charge
+ self.nex_charge = min(1, self.nex_charge + cvar("g_balance_nex_charge_velocity_rate") * f * frametime);
+ }
:end
if(self.flags & FL_ONGROUND)
self.lastground = time;
// server framerate is very low and the weapon fire rate very high
local float c;
c = 0;
- while (c < 5)
+ while (c < W_TICSPERFRAME)
{
c = c + 1;
if(wb && ((self.weapons & wb) == 0))
// this function calculates w_shotorg and w_shotdir based on the weapon model
// offset, trueaim and antilag, and won't put w_shotorg inside a wall.
// make sure you call makevectors first (FIXME?)
+.float prevstrengthsound;
+.float prevstrengthsoundattempt;
void W_SetupShot_Dir_ProjectileSize_Range(entity ent, vector s_forward, vector mi, vector ma, float antilag, float recoil, string snd, float maxdamage, float range)
{
float nudge = 1; // added to traceline target and subtracted from result
sound (ent, CHAN_WEAPON, snd, VOL_BASE, ATTN_NORM);
}
- if (ent.items & IT_STRENGTH)
- if (!g_minstagib)
- sound (ent, CHAN_AUTO, "weapons/strength_fire.wav", VOL_BASE, ATTN_NORM);
+ if(ent.items & IT_STRENGTH)
+ if(!g_minstagib)
+ if(
+ (time > ent.prevstrengthsound + cvar("sv_strengthsound_antispam_time"))
+ ||
+ (time > ent.prevstrengthsoundattempt + cvar("sv_strengthsound_antispam_refire_threshold"))
+ ) // prevent insane sound spam
+ {
+ sound(ent, CHAN_AUTO, "weapons/strength_fire.wav", VOL_BASE, ATTN_NORM);
+ ent.prevstrengthsound = time;
+ }
+ ent.prevstrengthsoundattempt = time;
// nudge w_shotend so a trace to w_shotend hits
w_shotend = w_shotend + normalize(w_shotend - w_shotorg) * nudge;
self = cl;
f = weapon_action(wpn, WR_CHECKAMMO1);
f = f + weapon_action(wpn, WR_CHECKAMMO2);
+
+ // always allow selecting the Mine Layer if we placed mines, so that we can detonate them
+ local entity mine;
+ if(wpn == WEP_MINE_LAYER)
+ for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
+ f = 1;
+
self = oldself;
}
if (!f)
if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
if (!weapon_action(self.weapon, WR_CHECKAMMO1 + secondary))
{
+ // always keep the Mine Layer if we placed mines, so that we can detonate them
+ local entity mine;
+ if(self.weapon == WEP_MINE_LAYER)
+ for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
+ return FALSE;
+
+ if(self.weapon == self.switchweapon) // only play once BEFORE starting to switch weapons
+ sound (self, CHAN_AUTO, "weapons/dryfire.wav", VOL_BASE, ATTN_NORM);
+
W_SwitchToOtherWeapon(self);
return FALSE;
}
tokens = tokenize_console(s);
}
GetCvars(1);
-#ifdef UID
- } else if(cmd == "uid") {
- if not(self.uid)
- {
- self.uid = strzone(argv(1));
- self.uid_kicktime = 0;
- print("Client ", etos(self), " has UID ", self.uid, "\n");
- Ban_MaybeEnforceBan(self);
- }
-#endif
} else if(cmd == "sentcvar") { // new system
if(tokens == 2) // undefined cvar: use the default value on the server then
{
float WS_INUSE = 3; // fire state
float WS_READY = 4; // idle frame
+// there is 2 weapon tics that can run in one server frame
+#define W_TICSPERFRAME 2
+
void weapon_defaultspawnfunc(float wpn);
string w_deathtypestring;
.entity flagcarried;
.entity lastrocket;
+.entity lastmine;
.float playerid;
float playerid_last;
.float active;
.float (float act_state) setactive;
.entity realowner;
+
+.float nex_charge;
-//DarkPlaces supported extension list, draft version 1.04
-
-//things that don't have extensions yet:
-.float disableclientprediction;
-
-//definitions that id Software left out:
-//these are passed as the 'nomonsters' parameter to traceline/tracebox (yes really this was supported in all quake engines, nomonsters is misnamed)
-float MOVE_NORMAL = 0; // same as FALSE
-float MOVE_NOMONSTERS = 1; // same as TRUE
-float MOVE_MISSILE = 2; // save as movement with .movetype == MOVETYPE_FLYMISSILE
-
-//checkextension function
-//idea: expected by almost everyone
-//darkplaces implementation: LordHavoc
-float(string s) checkextension = #99;
-//description:
-//check if (cvar("pr_checkextension")) before calling this, this is the only
-//guaranteed extension to be present in the extension system, it allows you
-//to check if an extension is available, by name, to check for an extension
-//use code like this:
-//// (it is recommended this code be placed in worldspawn or a worldspawn called function somewhere)
-//if (cvar("pr_checkextension"))
-//if (checkextension("DP_SV_SETCOLOR"))
-// ext_setcolor = TRUE;
-//from then on you can check ext_setcolor to know if that extension is available
-
-//BX_WAL_SUPPORT
-//idea: id Software
-//darkplaces implementation: LordHavoc
-//description:
-//indicates the engine supports .wal textures for filenames in the textures/ directory
-//(note: DarkPlaces has supported this since 2001 or 2002, but did not advertise it as an extension, then I noticed Betwix was advertising it and added the extension accordingly)
-
-//DP_BUTTONCHAT
-//idea: Vermeulen
-//darkplaces implementation: LordHavoc
-//field definitions:
-.float buttonchat;
-//description:
-//true if the player is currently chatting (in messagemode, menus or console)
-
-//DP_BUTTONUSE
-//idea: id Software
-//darkplaces implementation: LordHavoc
-//field definitions:
-.float buttonuse;
-//client console commands:
-//+use
-//-use
-//description:
-//made +use and -use commands work, they now control the .buttonuse field (.button1 was used by many mods for other purposes).
-
-//DP_CL_LOADSKY
-//idea: Nehahra, LordHavoc
-//darkplaces implementation: LordHavoc
-//client console commands:
+ //DarkPlaces supported extension list, draft version 1.04
+
+ //things that don't have extensions yet:
+ .float disableclientprediction;
+
+ //definitions that id Software left out:
+ //these are passed as the 'nomonsters' parameter to traceline/tracebox (yes really this was supported in all quake engines, nomonsters is misnamed)
+ float MOVE_NORMAL = 0; // same as FALSE
+ float MOVE_NOMONSTERS = 1; // same as TRUE
+ float MOVE_MISSILE = 2; // save as movement with .movetype == MOVETYPE_FLYMISSILE
+
+ //checkextension function
+ //idea: expected by almost everyone
+ //darkplaces implementation: LordHavoc
+ float(string s) checkextension = #99;
+ //description:
+ //check if (cvar("pr_checkextension")) before calling this, this is the only
+ //guaranteed extension to be present in the extension system, it allows you
+ //to check if an extension is available, by name, to check for an extension
+ //use code like this:
+ //// (it is recommended this code be placed in worldspawn or a worldspawn called function somewhere)
+ //if (cvar("pr_checkextension"))
+ //if (checkextension("DP_SV_SETCOLOR"))
+ // ext_setcolor = TRUE;
+ //from then on you can check ext_setcolor to know if that extension is available
+
+ //BX_WAL_SUPPORT
+ //idea: id Software
+ //darkplaces implementation: LordHavoc
+ //description:
+ //indicates the engine supports .wal textures for filenames in the textures/ directory
+ //(note: DarkPlaces has supported this since 2001 or 2002, but did not advertise it as an extension, then I noticed Betwix was advertising it and added the extension accordingly)
+
+ //DP_BUTTONCHAT
+ //idea: Vermeulen
+ //darkplaces implementation: LordHavoc
+ //field definitions:
+ .float buttonchat;
+ //description:
+ //true if the player is currently chatting (in messagemode, menus or console)
+
+ //DP_BUTTONUSE
+ //idea: id Software
+ //darkplaces implementation: LordHavoc
+ //field definitions:
+ .float buttonuse;
+ //client console commands:
+ //+use
+ //-use
+ //description:
+ //made +use and -use commands work, they now control the .buttonuse field (.button1 was used by many mods for other purposes).
+
+ //DP_CL_LOADSKY
+ //idea: Nehahra, LordHavoc
+ //darkplaces implementation: LordHavoc
+ //client console commands:
//"loadsky" (parameters: "basename", example: "mtnsun_" would load "mtnsun_up.tga" and "mtnsun_rt.tga" and similar names, use "" to revert to quake sky, note: this is the same as Quake2 skybox naming)
//description:
//sets global skybox for the map for this client (can be stuffed to a client by QC), does not hurt much to repeatedly execute this command, please don't use this in mods if it can be avoided (only if changing skybox is REALLY needed, otherwise please use DP_GFX_SKYBOX).
//description:
//various physics properties can be defined in an entity and are executed via
//ODE
+
+//DP_CRYPTO
+//idea: divVerent
+//darkplaces implementation: divVerent
+//field definitions: (SVQC)
+.string crypto_keyfp; // fingerprint of CA key the player used to authenticate, or string_null if not verified
+.string crypto_mykeyfp; // fingerprint of CA key the server used to authenticate to the player, or string_null if not verified
+.string crypto_idfp; // fingerprint of ID used by the player entity, or string_null if not identified
+.string crypto_encryptmethod; // the string "AES128" if encrypting, and string_null if plaintext
+.string crypto_signmethod; // the string "HMAC-SHA256" if signing, and string_null if plaintext
+// there is no field crypto_myidfp, as that info contains no additional information the QC may have a use for
+//description:
}
}
-vector NearestPointOnBox(entity box, vector org)
-{
- vector m1, m2, nearest;
-
- m1 = box.mins + box.origin;
- m2 = box.maxs + box.origin;
-
- nearest_x = bound(m1_x, org_x, m2_x);
- nearest_y = bound(m1_y, org_y, m2_y);
- nearest_z = bound(m1_z, org_z, m2_z);
-
- return nearest;
-}
-
void Damage_RecordDamage(entity attacker, float deathtype, float damage)
{
float weaponid;
sf |= 0x20;
if(self.colormap != 0)
sf |= 0x40;
+ if(self.lodmodelindex1)
+ sf |= 0x80;
WriteByte(MSG_ENTITY, ENT_CLIENT_WALL);
WriteByte(MSG_ENTITY, sf);
if(sf & 8)
{
- WriteShort(MSG_ENTITY, self.modelindex);
+ if(sf & 0x80)
+ {
+ WriteShort(MSG_ENTITY, self.lodmodelindex0);
+ WriteShort(MSG_ENTITY, bound(0, self.loddistance1, 65535));
+ WriteShort(MSG_ENTITY, self.lodmodelindex1);
+ WriteShort(MSG_ENTITY, bound(0, self.loddistance2, 65535));
+ WriteShort(MSG_ENTITY, self.lodmodelindex2);
+ }
+ else
+ WriteShort(MSG_ENTITY, self.modelindex);
WriteByte(MSG_ENTITY, self.solid);
WriteShort(MSG_ENTITY, floor(self.scale * 256));
if(sf & 0x20)
if(!self.solid) self.solid = (sol); else if(self.solid < 0) self.solid = SOLID_NOT;
#define G_CLIENTMODEL_INIT(sol) \
- SetBrushEntityModelNoLOD(); \
+ SetBrushEntityModel(); \
if(!self.scale) self.scale = self.modelscale; \
self.use = g_clientmodel_setcolormaptoactivator; \
InitializeEntity(self, g_clientmodel_dropbyspawnflags, INITPRIO_DROPTOFLOOR); \
.float loddistance1;
.float loddistance2;
-vector NearestPointOnBox(entity box, vector org);
float LOD_customize()
{
float d;
d = cvar("loddebug");
if(d == 1)
self.modelindex = self.lodmodelindex0;
- else if(d == 2)
+ else if(d == 2 || !self.lodmodelindex2)
self.modelindex = self.lodmodelindex1;
else // if(d == 3)
self.modelindex = self.lodmodelindex2;
}
if(self.lodmodelindex1)
- SetCustomizer(self, LOD_customize, LOD_uncustomize);
+ if not(self.SendEntity)
+ SetCustomizer(self, LOD_customize, LOD_uncustomize);
}
void SetBrushEntityModel()
float laser_SendEntity(entity to, float fl)
{
WriteByte(MSG_ENTITY, ENT_CLIENT_LASER);
- fl = fl - (fl & 0xE0); // use that bit to indicate finite length laser
+ fl = fl - (fl & 0xF0); // use that bit to indicate finite length laser
if(self.spawnflags & 2)
fl |= 0x80;
if(self.alpha)
fl |= 0x40;
if(self.scale != 1 || self.modelscale != 1)
fl |= 0x20;
+ if(self.spawnflags & 4)
+ fl |= 0x10;
WriteByte(MSG_ENTITY, fl);
if(fl & 1)
{
WriteByte(MSG_ENTITY, bound(0, self.scale * 16.0, 255));
WriteByte(MSG_ENTITY, bound(0, self.modelscale * 16.0, 255));
}
- WriteShort(MSG_ENTITY, self.cnt + 1);
+ if((fl & 0x80) || !(fl & 0x10)) // effect doesn't need sending if the laser is infinite and has collision testing turned off
+ WriteShort(MSG_ENTITY, self.cnt + 1);
}
if(fl & 2)
{
self.scale = 1;
if(!self.modelscale)
self.modelscale = 1;
+ else if(self.modelscale < 0)
+ self.modelscale = 0;
self.think = misc_laser_think;
self.nextthink = time;
InitializeEntity(self, misc_laser_init, INITPRIO_FINDTARGET);
if(!pushdeltatime) return;
other.velocity = other.velocity + normalize(targ.origin - self.origin) * str * pushdeltatime;
- other.flags &~= FL_ONGROUND;
+ other.flags &~= FL_ONGROUND;
+ UpdateCSQCProjectile(other);
}
// Directionless (accelerator/decelerator) mode
// div0: ticrate independent, 1 = identity (not 20)
other.velocity = other.velocity * pow(self.strength, pushdeltatime);
+ UpdateCSQCProjectile(other);
}
// Spherical (gravity/repulsor) mode
str = self.strength;
other.velocity = other.velocity + normalize(other.origin - self.origin) * str * pushdeltatime;
+ UpdateCSQCProjectile(other);
}
/*QUAKED spawnfunc_trigger_impulse (.5 .5 .5) ?
self.cnt = ACTIVE_TOGGLE;
self.use = relay_activators_use;
}
+
+.string chmap, gametype;
+void spawnfunc_target_changelevel_use()
+{
+ if(self.gametype != "")
+ MapInfo_SwitchGameType(MapInfo_Type_FromString(self.gametype));
+
+ if (self.chmap == "")
+ localcmd("endmatch\n");
+ else
+ localcmd(strcat("changelevel ", self.chmap, "\n"));
+};
+
+void spawnfunc_target_changelevel()
+{
+ self.use = spawnfunc_target_changelevel_use;
+};
addstat(STAT_LEADLIMIT, AS_FLOAT, stat_leadlimit);
addstat(STAT_BULLETS_LOADED, AS_INT, campingrifle_bulletcounter);
+ addstat(STAT_NEX_CHARGE, AS_FLOAT, nex_charge);
+
// 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);
continue;
l = strlen(ip);
- for(j = 0; j < l; ++j)
- if(strstrofs("0123456789.", substring(ip, j, 1), 0) == -1)
- {
- print("Invalid character ", substring(ip, j, 1), " in IP address ", ip, ". Skipping this ban.\n");
- goto skip;
- }
+ if(l != 44) // length 44 is a cryptographic ID
+ {
+ for(j = 0; j < l; ++j)
+ if(strstrofs("0123456789.", substring(ip, j, 1), 0) == -1)
+ {
+ print("Invalid character ", substring(ip, j, 1), " in IP address ", ip, ". Skipping this ban.\n");
+ goto skip;
+ }
+ }
if(cvar("g_ban_sync_trusted_servers_verify"))
if((strstrofs(strcat(";", OnlineBanList_Servers, ";"), strcat(";", serverip, ";"), 0) == -1))
string ban_ip2;
string ban_ip3;
string ban_ip4;
-#ifdef UID
-string ban_uid;
-#endif
+string ban_idfp;
void Ban_SaveBans()
{
float i1, i2, i3, i4;
string s;
+ if(client.crypto_keyfp)
+ ban_idfp = client.crypto_idfp;
+ else
+ ban_idfp = string_null;
+
s = client.netaddress;
i1 = strstrofs(s, ".", 0);
if(i1 < 0)
- i1 = strstrofs(s, ":", 0);
- if(i1 < 0)
- return FALSE;
+ goto ipv6;
i2 = strstrofs(s, ".", i1 + 1);
- if(i2 < 0)
- i2 = strstrofs(s, ":", i1 + 1);
if(i2 < 0)
return FALSE;
i3 = strstrofs(s, ".", i2 + 1);
- if(i3 < 0)
- i3 = strstrofs(s, ":", i2 + 1);
if(i3 < 0)
return FALSE;
i4 = strstrofs(s, ".", i3 + 1);
- if(i4 < 0)
- i4 = strstrofs(s, ":", i3 + 1);
if(i4 >= 0)
s = substring(s, 0, i4);
- ban_ip1 = substring(s, 0, i1);
- ban_ip2 = substring(s, 0, i2);
- ban_ip3 = substring(s, 0, i3);
- ban_ip4 = strcat1(s);
-#ifdef UID
- ban_uid = client.uid;
-#endif
+ ban_ip1 = substring(s, 0, i1); // 8
+ ban_ip2 = substring(s, 0, i2); // 16
+ ban_ip3 = substring(s, 0, i3); // 24
+ ban_ip4 = strcat1(s); // 32
+ return TRUE;
+
+:ipv6
+ i1 = strstrofs(s, ":", 0);
+ if(i1 < 0)
+ return FALSE;
+ i1 = strstrofs(s, ":", i1 + 1);
+ if(i1 < 0)
+ return FALSE;
+ i2 = strstrofs(s, ":", i1 + 1);
+ if(i2 < 0)
+ return FALSE;
+ i3 = strstrofs(s, ":", i2 + 1);
+ if(i3 < 0)
+ return FALSE;
+
+ ban_ip1 = strcat(substring(s, 0, i1), "::/32"); // 32
+ ban_ip2 = strcat(substring(s, 0, i2), "::/48"); // 48
+ ban_ip4 = strcat(substring(s, 0, i3), "::/64"); // 64
+
+ if(i3 - i2 > 3) // means there is more than 2 digits and a : in the range
+ ban_ip3 = strcat(substring(s, 0, i2), ":", substring(s, i2 + 1, i3 - i2 - 3), "00::/56");
+ else
+ ban_ip3 = strcat(substring(s, 0, i2), ":0::/56");
return TRUE;
}
float Ban_IsClientBanned(entity client, float idx)
{
- float i, b, e;
+ float i, b, e, ipbanned;
if(!ban_loaded)
Ban_LoadBans();
if(!Ban_GetClientIP(client))
b = idx;
e = idx + 1;
}
+ ipbanned = FALSE;
for(i = b; i < e; ++i)
{
string s;
if(time > ban_expire[i])
continue;
s = ban_ip[i];
- if(ban_ip1 == s) return TRUE;
- if(ban_ip2 == s) return TRUE;
- if(ban_ip3 == s) return TRUE;
- if(ban_ip4 == s) return TRUE;
-#ifdef UID
- if(ban_uid == s) return TRUE;
-#endif
+ if(ban_ip1 == s) ipbanned = TRUE;
+ if(ban_ip2 == s) ipbanned = TRUE;
+ if(ban_ip3 == s) ipbanned = TRUE;
+ if(ban_ip4 == s) ipbanned = TRUE;
+ if(ban_idfp == s) return TRUE;
}
+ if(ipbanned)
+ if(!cvar("g_banned_list_idmode") || !ban_idfp)
+ return TRUE;
return FALSE;
}
default:
Ban_Insert(ban_ip4, bantime, reason, 1);
break;
-#ifdef UID
- case 0:
- Ban_Insert(ban_uid, bantime, reason, 1);
- break;
-#endif
}
+ if(ban_idfp)
+ Ban_Insert(ban_idfp, bantime, reason, 1);
/*
* not needed, as we enforce the ban in Ban_Insert anyway
// and kick him
if (g_weaponarena)
{
start_weapons = g_weaponarena;
- if (g_weaponarena & (WEPBIT_GRENADE_LAUNCHER | WEPBIT_HAGAR | WEPBIT_ROCKET_LAUNCHER))
+ if (g_weaponarena & (WEPBIT_GRENADE_LAUNCHER | WEPBIT_MINE_LAYER | WEPBIT_HAGAR | WEPBIT_ROCKET_LAUNCHER))
start_ammo_rockets = 999;
if (g_weaponarena & WEPBIT_SHOTGUN)
start_ammo_shells = 999;
precache_sound ("weapons/weapon_switch.wav");
precache_sound ("weapons/weaponpickup.wav");
precache_sound ("weapons/unavailable.wav");
+ precache_sound ("weapons/dryfire.wav");
if (g_grappling_hook)
{
precache_sound ("weapons/hook_fire.wav"); // hook
if (time >= 2)
{
spawnedexitmonsters = TRUE;
- e = find(world, classname, "trigger_changelevel");
+ e = find(world, classname, "target_changelevel");
while (e)
{
spawnmonster(e.origin + (e.mins + e.maxs) * 0.5, 8, 8, "monster_hellfish", monster_hellfish, '-16 -16 -24', '16 16 32');
- e = find(e, classname, "trigger_changelevel");
+ e = find(e, classname, "target_changelevel");
}
}
return;
+#ifdef TURRET_DEBUG
void mark_error(vector where,float lifetime);
void mark_info(vector where,float lifetime);
entity mark_misc(vector where,float lifetime);
-
+#endif
void pathlib_showpath(entity start)
{
void __showpath2_think()
{
- mark_info(self.origin,1);
+ #ifdef TURRET_DEBUG
+ mark_info(self.origin,1);
+ #endif
if(self.path_next)
{
self.path_next.think = __showpath2_think;
node = pathlib_nodeatpoint(where);
if(node)
{
+ #ifdef TURRET_DEBUG
mark_error(where, 60);
+ #endif
return node;
}
string rr;
float grecordtime[RANKINGS_CNT];
string grecordholder[RANKINGS_CNT];
-#ifdef UID
string grecorduid[RANKINGS_CNT];
-#endif
float worst_time; // last ranked time
float have_recs; // have we already read the records from the database before?
float race_GetTime(float pos) {
for(i=0;i<RANKINGS_CNT;++i) {
grecordtime[i] = stof(db_get(ServerProgsDB, strcat(GetMapname(), rr, "time", ftos(i))));
grecordholder[i] = strzone(db_get(ServerProgsDB, strcat(GetMapname(), rr, "netname", ftos(i))));
-#ifdef UID
- grecorduid[i] = strzone(db_get(ServerProgsDB, strcat(GetMapname(), rr, "uid", ftos(i))));
-#endif
+ grecorduid[i] = strzone(db_get(ServerProgsDB, strcat(GetMapname(), rr, "crypto_idfp", ftos(i))));
}
grecordtime[0] = stof(db_get(ServerProgsDB, strcat(GetMapname(), rr, "time")));
grecordholder[0] = strzone(db_get(ServerProgsDB, strcat(GetMapname(), rr, "netname")));
-#ifdef UID
- grecorduid[0] = strzone(db_get(ServerProgsDB, strcat(GetMapname(), rr, "uid")));
-#endif
+ grecorduid[0] = strzone(db_get(ServerProgsDB, strcat(GetMapname(), rr, "crypto_idfp")));
worst_time = stof(db_get(ServerProgsDB, strcat(GetMapname(), rr, strcat("time", ftos(RANKINGS_CNT-1)))));
have_recs = 1;
}
return grecordholder[pos-1];
}
-#ifdef UID
float race_CheckUID(string myuid, string net_name) { // return existing UID or player name ranking pos, else 0
float i;
+ if(myuid)
+ {
+ for (i=RANKINGS_CNT-1;i>=0;--i)
+ if(grecorduid[i] == myuid)
+ return i+1;
+ }
for (i=RANKINGS_CNT-1;i>=0;--i)
- if(grecorduid[i] == myuid)
- return i+1;
- for (i=RANKINGS_CNT-1;i>=0;--i)
- if(grecordholder[i] == net_name)
- return i+1;
- return 0;
-}
-#endif
-
-float race_CheckName(string net_name) { // Does the name already exist in rankings? In that case, where? (otherwise 0)
- float i;
- for (i=RANKINGS_CNT-1;i>=0;--i)
- if(grecordholder[i] == net_name)
- return i+1;
+ if(!grecorduid[i])
+ if(grecordholder[i] == net_name)
+ return i+1;
return 0;
}
void race_SetTime(entity e, float t, float match_rec) {
float pos, prevpos;
pos = race_GetPos(t);
-#ifdef UID
- prevpos = race_CheckUID(e.uid, e.netname);
-#else
- prevpos = race_CheckName(e.netname);
-#endif
+ prevpos = race_CheckUID(e.crypto_idfp, e.netname);
float oldrec;
string recorddifference;
for (i=prevpos-1;i>pos-1;--i) {
db_put(ServerProgsDB, strcat(GetMapname(), rr, "time", ftos(i)), ftos(grecordtime[i-1]));
db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname", ftos(i)), grecordholder[i-1]);
-#ifdef UID
- db_put(ServerProgsDB, strcat(GetMapname(), rr, "uid", ftos(i)), grecorduid[i-1]);
-#endif
+ db_put(ServerProgsDB, strcat(GetMapname(), rr, "crypto_idfp", ftos(i)), grecorduid[i-1]);
grecordtime[i] = grecordtime[i-1];
if (grecordholder[i])
strunzone(grecordholder[i]);
grecordholder[i] = strzone(grecordholder[i-1]);
-#ifdef UID
if (grecorduid[i])
strunzone(grecorduid[i]);
grecorduid[i] = strzone(grecorduid[i-1]);
-#endif
}
} else { // player has no ranked record yet
for (i=RANKINGS_CNT-1;i>pos-1;--i) {
db_put(ServerProgsDB, strcat(GetMapname(), rr, "time", ftos(i)), ftos(grecordtime[i-1]));
db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname", ftos(i)), grecordholder[i-1]);
-#ifdef UID
- db_put(ServerProgsDB, strcat(GetMapname(), rr, "uid", ftos(i)), grecorduid[i-1]);
-#endif
+ db_put(ServerProgsDB, strcat(GetMapname(), rr, "crypto_idfp", ftos(i)), grecorduid[i-1]);
grecordtime[i] = grecordtime[i-1];
if (grecordholder[i])
strunzone(grecordholder[i]);
grecordholder[i] = strzone(grecordholder[i-1]);
-#ifdef UID
if (grecorduid[i])
strunzone(grecorduid[i]);
grecorduid[i] = strzone(grecorduid[i-1]);
-#endif
}
}
if (pos == 1) {
db_put(ServerProgsDB, strcat(GetMapname(), rr, "time"), ftos(t));
db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname"), e.netname);
-#ifdef UID
- db_put(ServerProgsDB, strcat(GetMapname(), rr, "uid"), e.uid);
-#endif
+ db_put(ServerProgsDB, strcat(GetMapname(), rr, "crypto_idfp"), e.crypto_idfp);
grecordtime[0] = t;
if (grecordholder[0])
strunzone(grecordholder[0]);
grecordholder[0] = strzone(e.netname);
-#ifdef UID
if (grecorduid[0])
strunzone(grecorduid[0]);
- grecorduid[0] = strzone(e.uid);
-#endif
+ grecorduid[0] = strzone(e.crypto_idfp);
write_recordmarker(e, time - TIME_DECODE(t), TIME_DECODE(t));
race_send_recordtime(MSG_ALL);
} else {
db_put(ServerProgsDB, strcat(GetMapname(), rr, "time", ftos(pos-1)), ftos(t));
db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname", ftos(pos-1)), e.netname);
-#ifdef UID
- db_put(ServerProgsDB, strcat(GetMapname(), rr, "uid", ftos(pos-1)), e.uid);
-#endif
+ db_put(ServerProgsDB, strcat(GetMapname(), rr, "crypto_idfp", ftos(pos-1)), e.crypto_idfp);
grecordtime[pos-1] = t;
if (grecordholder[pos-1])
strunzone(grecordholder[pos-1]);
grecordholder[pos-1] = strzone(e.netname);
-#ifdef UID
if (grecorduid[pos-1])
strunzone(grecorduid[pos-1]);
- grecorduid[pos-1] = strzone(e.uid);
-#endif
+ grecorduid[pos-1] = strzone(e.crypto_idfp);
}
if (pos == RANKINGS_CNT)
if (i == 0) {
db_put(ServerProgsDB, strcat(GetMapname(), rr, "time"), ftos(grecordtime[1]));
db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname"), grecordholder[1]);
-#ifdef UID
- db_put(ServerProgsDB, strcat(GetMapname(), rr, "uid"), grecorduid[1]);
-#endif
+ db_put(ServerProgsDB, strcat(GetMapname(), rr, "crypto_idfp"), grecorduid[1]);
grecordtime[0] = grecordtime[1];
if (grecordholder[i])
strunzone(grecordholder[0]);
grecordholder[0] = strzone(grecordholder[1]);
-#ifdef UID
if (grecorduid[i])
strunzone(grecorduid[0]);
grecorduid[0] = strzone(grecorduid[1]);
-#endif
}
else if (i == RANKINGS_CNT-1) {
db_put(ServerProgsDB, strcat(GetMapname(), rr, "time", ftos(i)), string_null);
db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname", ftos(i)), string_null);
-#ifdef UID
- db_put(ServerProgsDB, strcat(GetMapname(), rr, "uid", ftos(i)), string_null);
-#endif
+ db_put(ServerProgsDB, strcat(GetMapname(), rr, "crypto_idfp", ftos(i)), string_null);
grecordtime[i] = 0;
if (grecordholder[i])
strunzone(grecordholder[i]);
grecordholder[i] = string_null;
-#ifdef UID
if (grecorduid[i])
strunzone(grecorduid[i]);
grecorduid[i] = string_null;
-#endif
}
else {
db_put(ServerProgsDB, strcat(GetMapname(), rr, "time", ftos(i)), ftos(grecordtime[i+1]));
db_put(ServerProgsDB, strcat(GetMapname(), rr, "netname", ftos(i)), grecordholder[i+1]);
-#ifdef UID
- db_put(ServerProgsDB, strcat(GetMapname(), rr, "uid", ftos(i)), grecorduid[i+1]);
-#endif
+ db_put(ServerProgsDB, strcat(GetMapname(), rr, "crypto_idfp", ftos(i)), grecorduid[i+1]);
grecordtime[i] = grecordtime[i+1];
if (grecordholder[i])
strunzone(grecordholder[i]);
grecordholder[i] = strzone(grecordholder[i+1]);
-#ifdef UID
if (grecorduid[i])
strunzone(grecorduid[i]);
grecorduid[i] = strzone(grecorduid[i+1]);
-#endif
}
}
{
ammofield = Item_CounterField(j);
if(!self.ammofield)
- self.ammofield = cvar(strcat("g_pickup_", Item_CounterFieldName(j)));
+ self.ammofield = cvar(strcat("g_pickup_", Item_CounterFieldName(j), "_weapon"));
}
}
}
// calculate sinewave using makevectors
makevectors((self.nextthink * self.owner.cnt + self.owner.phase * 360) * '0 1 0');
v = self.owner.destvec + self.owner.movedir * v_forward_y;
- // * 10 so it will arrive in 0.1 sec
- self.owner.velocity = (v - self.owner.origin) * 10;
+ if(self.owner.classname == "func_bobbing") // don't brake stuff if the func_bobbing was killtarget'ed
+ // * 10 so it will arrive in 0.1 sec
+ self.owner.velocity = (v - self.owner.origin) * 10;
};
void bobbing_blocked()
v = v + ('1 0 0' * stof(argv(i*5+2)) + '0 1 0' * stof(argv(i*5+3)) + '0 0 1' * stof(argv(i*5+4))) * self.owner.height * v_forward_y;
}
- // * 10 so it will arrive in 0.1 sec
- self.owner.velocity = (v - self.owner.origin) * 10;
+ if(self.owner.classname == "func_fourier") // don't brake stuff if the func_fourier was killtarget'ed
+ // * 10 so it will arrive in 0.1 sec
+ self.owner.velocity = (v - self.owner.origin) * 10;
};
void spawnfunc_func_fourier()
return;
}
- self.owner.velocity = (self.owner.destvec + func_vectormamamam_origin(self.owner, 0.1) - self.owner.origin) * 10;
+ if(self.owner.classname == "func_vectormamamam") // don't brake stuff if the func_vectormamamam was killtarget'ed
+ self.owner.velocity = (self.owner.destvec + func_vectormamamam_origin(self.owner, 0.1) - self.owner.origin) * 10;
}
void func_vectormamamam_findtarget()
/// Dont aim.
#define TFL_AIM_NO 1
/// Go for ground, not direct hit
-#define TFL_AIM_GROUND 2
+//#define TFL_AIM_GROUND 2
/// Go for ground, not direct hit, but only if target is on ground.
#define TFL_AIM_GROUND2 4
/// Use balistic aim. FIXME: not implemented
#define TFL_AIM_INFRONT 64
/// Aim slightly behind target
#define TFL_AIM_BEHIND 128
-/// blend real and predicted z positions. (fake bounce prediction)
-#define TFL_AIM_ZEASE 256
+/// blend real and predicted z positions. (fake bounce prediction)
+// #define TFL_AIM_ZEASE 256
/// Try to do real prediction of targets z pos at impact.
#define TFL_AIM_ZPREDICT 512
/// Simply aim at target's current location
/// on/off toggle.
.float tur_active;
-// Aim from this point,
-//.vector tur_aimorg;
-
/// and shoot from here. (can be non constant, think MLRS)
.vector tur_shotorg;
.float target_range;
/// Dont consider targets closer then
.float target_range_min;
-// Engage fire routine on targets within
-//.float target_range_fire; // no practical use aymore, work with target_range insted.
/// Targets closer to this are prefered
.float target_range_optimal;
*/
/// Maximum offset between impact and aim spot to fire
.float aim_firetolerance_dist;
-// Maximum angular offset between head and aimspot to fire
-//.float aim_firetolerance_angle;
/// How fast can i rotate/pitch (per second in stepmotor mode, base force in smooth modes)
.float aim_speed;
/// cant aim higher/lower then this
.void() turret_firefunc;
/// prefire checks go here. return 1 to go bang, 0 not to.
.float() turret_firecheckfunc;
-// Execure BEFORE main ai loop. return 0 to cancel any following proccessing.
-//.float() turret_prethink;
/// Execure AFTER main AI loop
.void() turret_postthink;
/// Add a target
.float(entity e_target,entity e_sender) turret_addtarget;
-//.float call_diehook;
-//.float call_respwnhook;
.void() turret_diehook;
.void() turret_respawnhook;
.float(float event_id) turret_eventhook;
*/
-/*
-* Some turrets need other aimsystems then other.
-* This should return the place to aim at, not acctualy turn or
-* pitch anyting.
-*
-* use turret_stdproc_aim* or Make your own.
-* Make sure you update tur_enemy_dist and tur_enemy_adist
-* with the apropriate info, if you do.
-
-removed.
-*/
-// function used to aim, usualy turret_stdproc_aim_generic
-//.vector() turret_aim;
-
-/*
-* This is where the acctual turret turning should take place
-* Use turret_stdproc_track or make your own.
-wkacked to save mem.
-*/
-// Function used to turn and pitch the .tur_head usualy turret_stdproc_track
-//.void() turret_track;
/*
* Target selection, preferably but not nessesarely
/// Function to use for target evaluation. usualy turret_stdproc_targetscore_generic
.float(entity e_turret, entity e_target) turret_score_target;
-/*
-* Damage, death and respawn.
-*/
-//void turret_gibs_precash();
-// generalized so save mem (on fields)
-// Function to handle incomming damage. usualy turret_stdproc_damage
-//.void(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector vforce) turret_damagefunc;
-// Function to handle the event of death. usualy turret_stdproc_die
-//.void() turret_diefunc;
-// Function that handles rebirth. usualy turret_stdproc_respawn
-//.void() turret_spawnfunc;
-
-/*
-* Stuff to plug into requierd but unused callbacks.
-*/
-/// Always return 1
-//float turret_stdproc_true();
-/// Always return 0
-//float turret_stdproc_false();
-/// Always return nothing at all
-//void turret_stdproc_nothing();
/*
* Target selection
*/
-// noting uses the following atm.
-// "closeer is beter" selection
-//float turret_stdproc_targetscore_close(entity e_turret, entity e_target);
-// "further is beter" selection
-//float turret_stdproc_targetscore_far(entity e_turret, entity e_target);
-// only target_range_optimal
-//float turret_stdproc_targetscore_optimal(entity e_turret, entity e_target);
-// defendpos
-//float turret_stdproc_targetscore_defend(entity e_turret, entity e_target);
-/// Generic fairly smart bias-aware target selection.
+/// Generic, fairly smart, bias-aware target selection.
float turret_stdproc_targetscore_generic(entity e_turret, entity e_target);
/// Experimental supportunits targetselector
float turret_stdproc_targetscore_support(entity e_turret,entity e_target);
* Aim functions
*/
/// Generic aimer guided by self.aim_flags
-vector turret_stdproc_aim_generic()
-// Straight line, current location
-//vector turret_stdproc_aim_simple()
+vector turret_stdproc_aim_generic();
/*
* Turret turning & pitch
/// updates aim org, shot org, shot dir and enemy org for selected turret
void turret_do_updates(entity e_turret);
-//.vector tur_aimorg_updated; // creates to much aim issues. using tur_shotorg_updated insted.
-//.vector tur_shotorg_updated; // DP8815 fixes gettaginfo, no longer needed.
.vector tur_shotdir_updated;
void turrets_precash();
supports:
TFL_AIM_NO
-TFL_AIM_GROUND
+TFL_AIM_GROUND2
TFL_AIM_LEAD
TFL_AIM_SHOTTIMECOMPENSATE
TFL_AIM_INFRONT
TFL_AIM_BEHIND
-TFL_AIM_ZEASE
not supported:
TFL_AIM_BALISTIC
+
+removed
+TFL_AIM_ZEASE
+TFL_AIM_GROUND
*/
vector turret_stdproc_aim_generic()
{
if(self.aim_flags & TFL_AIM_SIMPLE)
return real_origin(self.enemy);
- // Keep track of when we can shoot the next time and
- // try to predict where the target will be then, so we can put our aimpoint there.
- // + sys_frametime, becouse spawned REMOVE THIS IF sv_gameplayfix_delayprojectiles are 0!
- // projectiles dont move during the first tic of their life.
- //if (self.turrcaps_flags & TFL_TURRCAPS_HITSCAN)
- // mintime = max(self.attack_finished_single - time,0) + sys_frametime;
- //else
-
- mintime = max(self.attack_finished_single - time,0) + sys_frametime;
+ mintime = max(self.attack_finished_single - time,0) + sys_frametime ;
// Baseline
pre_pos = real_origin(self.enemy);
// Lead?
if (self.aim_flags & TFL_AIM_LEAD)
- if (self.aim_flags & TFL_AIM_SHOTTIMECOMPENSATE) // Need to conpensate for shot traveltime
- {
- // FIXME: this cant be the best way to do this..
- prep = pre_pos;
- for(i = 0; i < 4; ++i)
- {
- distance = vlen(prep - self.tur_shotorg);
- impact_time = distance / self.shot_speed;
- prep = pre_pos + self.enemy.velocity * impact_time;
- }
-
-
- // tnx to Rudolf "div0" Polzer for this solution.
- // hmm tobad it dont work.
- /*
- vector q;
- q = solve_quadratic(self.enemy.velocity*self.enemy.velocity - self.shot_speed*self.shot_speed, 2*(pre_pos*self.enemy.velocity), pre_pos * pre_pos);
- if(q_x > 0)
- impact_time = q_x;
- else
- impact_time = q_y;
- */
-
- prep = pre_pos + (self.enemy.velocity * (impact_time + mintime));
-
- if(self.aim_flags & TFL_AIM_ZPREDICT)
- if not(self.enemy.flags & FL_ONGROUND)
- if(self.enemy.movetype == MOVETYPE_WALK || self.enemy.movetype == MOVETYPE_TOSS || self.enemy.movetype == MOVETYPE_BOUNCE)
- {
- float vz;
- prep_z = pre_pos_z;
- vz = self.enemy.velocity_z;
- for(i = 0; i < impact_time; i += sys_frametime)
- {
- vz = vz - (sv_gravity * sys_frametime);
- prep_z = prep_z + vz * sys_frametime;
- }
- }
- pre_pos = prep;
- }
- else
- pre_pos = pre_pos + self.enemy.velocity * mintime;
-
- // Smooth out predict-Z?
- /*
- if (self.aim_flags & TFL_AIM_ZEASE)
- if (self.enemy.flags & FL_CLIENT)
- {
- vector v;
- v = real_origin(self.enemy);
- pre_pos_z = (pre_pos_z + v_z) * 0.5;
+ {
+ if (self.aim_flags & TFL_AIM_SHOTTIMECOMPENSATE) // Need to conpensate for shot traveltime
+ {
+ // FIXME: this cant be the best way to do this..
+ prep = pre_pos;
+ for(i = 0; i < 4; ++i)
+ {
+ distance = vlen(prep - self.tur_shotorg);
+ impact_time = distance / self.shot_speed;
+ prep = pre_pos + self.enemy.velocity * impact_time;
+ }
+
+ prep = pre_pos + (self.enemy.velocity * (impact_time + mintime));
+
+ if(self.aim_flags & TFL_AIM_ZPREDICT)
+ if not(self.enemy.flags & FL_ONGROUND)
+ if(self.enemy.movetype == MOVETYPE_WALK || self.enemy.movetype == MOVETYPE_TOSS || self.enemy.movetype == MOVETYPE_BOUNCE)
+ {
+ float vz;
+ prep_z = pre_pos_z;
+ vz = self.enemy.velocity_z;
+ for(i = 0; i < impact_time; i += sys_frametime)
+ {
+ vz = vz - (sv_gravity * sys_frametime);
+ prep_z = prep_z + vz * sys_frametime;
+ }
+ }
+ pre_pos = prep;
+ }
+ else
+ pre_pos = pre_pos + self.enemy.velocity * mintime;
}
- */
-
+
if(self.aim_flags & TFL_AIM_GROUND2)
{
//tracebox(pre_pos + '0 0 32',self.enemy.mins,self.enemy.maxs,pre_pos -'0 0 64',MOVE_WORLDONLY,self.enemy);
pre_pos = trace_endpos;
}
- /*
- // This turret should hit the ground neer a target rather the do a direct hit
- if (self.aim_flags & TFL_AIM_GROUND)
- {
- traceline(pre_pos + '0 0 8',pre_pos - '0 0 10000',MOVE_WORLDONLY,self.enemy);
- pre_pos = trace_endpos;
- }
- */
-
return pre_pos;
}
gib = spawn();
gib.classname = "turret_gib";
- setmodel(gib,smodel);
- setorigin(gib,v_from);
- SUB_SetFade(gib,time + f_lifetime,2);
+ setmodel(gib, smodel);
+ setorigin(gib, v_from);
+ SUB_SetFade(gib,time + f_lifetime, 2);
gib.solid = SOLID_BBOX;
-
gib.movetype = MOVETYPE_BOUNCE;
gib.takedamage = DAMAGE_YES;
gib.event_damage = turret_gib_damage;
burn.effects = EF_LOWPRECISION;//|EF_FLAME;
setattachment(burn,gib,"");
setorigin(burn,(gib.mins + gib.maxs) * 0.5);
- SUB_SetFade(burn,time + (f_lifetime * 0.5) ,2);
+ SUB_SetFade(burn,time + (f_lifetime * 0.5), 2);
}
}
s = strcat("models/turrets/head-gib",ftos(i));
s = strcat(s,".md3");
- // bprint("s:",s,"\n");
- setmodel(gib,s);
+ setmodel(gib, s);
setorigin(gib,self.origin);
SUB_SetFade(gib,time + 5,2);
gib.solid = SOLID_BBOX;
-
gib.movetype = MOVETYPE_BOUNCE;
gib.gravity = 0.5;
gib.damageforcescale = 2;
makevectors(self.angles);
if (random() > 0.5)
{
- turret_trowgib(self.origin, '0 0 0','1 1 1',"models/turrets/base-gib2.md3",min(self.respawntime,20),1,1);
+ turret_trowgib(self.origin, '0 0 0', '1 1 1', "models/turrets/base-gib2.md3", min(self.respawntime, 20), 1, 1);
+
+ t_dir = (v_up * 700) + (randomvec() * 300);
+ turret_trowgib(self.origin, t_dir, '1 1 1', "models/turrets/base-gib3.md3", min(self.respawntime, 10), 1, 1);
+
t_dir = (v_up * 700) + (randomvec() * 300);
- turret_trowgib(self.origin, t_dir,'1 1 1',"models/turrets/base-gib3.md3",min(self.respawntime,10),1,1);
- t_dir = (v_up * 700) + (randomvec() * 300);
- turret_trowgib(self.origin, t_dir,'1 1 1',"models/turrets/base-gib4.md3",min(self.respawntime,10),1,1);
+ turret_trowgib(self.origin, t_dir, '1 1 1', "models/turrets/base-gib4.md3", min(self.respawntime, 10), 1, 1);
}
else
{
- turret_trowgib(self.origin, '0 0 0','1 1 1',"models/turrets/base-gib1.md3",min(self.respawntime,20),1,1);
+ turret_trowgib(self.origin, '0 0 0', '1 1 1', "models/turrets/base-gib1.md3", min(self.respawntime, 20), 1, 1);
}
// Blow the top part up into the air
- turret_trowgib2( self.origin + (v_up * 50),
- v_up * 150 + randomvec() * 50,
- '0.2 0.2 0.2',
- self.tur_head,time + 0.5 + (random() * 0.5));
+ turret_trowgib2( self.origin + (v_up * 50), v_up * 150 + randomvec() * 50, '0.2 0.2 0.2', self.tur_head,time + 0.5 + (random() * 0.5));
}
// Go boom
}
else
{
- // Setup respawn
+ // Setup respawn
self.nextthink = time + self.respawntime;
- //self.think = self.turret_spawnfunc;
self.think = turret_stdproc_respawn;
+
if (self.turret_diehook)
self.turret_diehook();
}
-
}
+var const float SUB_NullFloat();
void turret_stdproc_respawn()
{
// Make sure all parts belong to the same team since
// this function doubles as "teamchange" function.
- self.tur_head.team = self.team;
-
- /*
- COLOR_TEAM1 = 4; // red
- COLOR_TEAM2 = 13; // blue
- COLOR_TEAM3 = 12; // yellow
- COLOR_TEAM4 = 9; // pink
- */
-
- self.colormod = '0 0 0';
+ self.tur_head.team = self.team;
+ self.colormod = '0 0 0';
switch(self.team)
{
}
self.deadflag = DEAD_NO;
- self.effects = 0;
+ self.effects = EF_LOWPRECISION;
self.tur_head.effects = self.effects;
-
self.solid = SOLID_BBOX;
-
- self.alpha = 1;
+ self.alpha = 1;
self.tur_head.alpha = self.alpha;
- self.customizeentityforclient = SUB_True;
- self.tur_head.customizeentityforclient = SUB_True;
+
+ self.customizeentityforclient = SUB_NullFloat;
+ self.tur_head.customizeentityforclient = SUB_NullFloat;
- self.takedamage = DAMAGE_AIM;
+ self.takedamage = DAMAGE_AIM;
self.event_damage = turret_stdproc_damage;
self.avelocity = '0 0 0';
}
*/
-void load_unit_settings(entity ent,string unitname,float is_reload)
+void load_unit_settings(entity ent, string unitname, float is_reload)
{
string sbase;
- // dprint("Reloading turret ",e_turret.netname,"\n");
-
if (ent == world)
return;
ent.target_range = cvar(strcat(sbase,"_target_range")) * ent.turret_scale_range;
ent.target_range_min = cvar(strcat(sbase,"_target_range_min")) * ent.turret_scale_range;
- //ent.target_range_fire = cvar(strcat(sbase,"_target_range_fire")) * ent.turret_scale_range;
ent.target_range_optimal = cvar(strcat(sbase,"_target_range_optimal")) * ent.turret_scale_range;
+ //ent.target_range_fire = cvar(strcat(sbase,"_target_range_fire")) * ent.turret_scale_range;
ent.target_select_rangebias = cvar(strcat(sbase,"_target_select_rangebias"));
ent.target_select_samebias = cvar(strcat(sbase,"_target_select_samebias"));
if(is_reload)
if(ent.turret_respawnhook)
ent.turret_respawnhook();
-
-}
-
-/*
-float turret_stdproc_true()
-{
- return 1;
}
-float turret_stdproc_false()
-{
- return 0;
-}
-
-
-void turret_stdproc_nothing()
-{
- return;
-}
-*/
/**
** updates enemy distances, predicted impact point/time
**/
void turret_do_updates(entity t_turret)
{
- vector enemy_pos,oldpos;
+ vector enemy_pos, oldpos;
entity oldself;
oldself = self;
turret_tag_fire_update();
- self.tur_shotdir_updated = normalize(v_forward);
-
+ self.tur_shotdir_updated = v_forward;
self.tur_dist_enemy = vlen(self.tur_shotorg - enemy_pos);
self.tur_dist_aimpos = vlen(self.tur_shotorg - self.tur_aimpos);
if(trace_ent == self.enemy)
self.tur_dist_impact_to_aimpos = 0;
else
- self.tur_dist_impact_to_aimpos = vlen(trace_endpos - self.tur_aimpos);// - (vlen(self.enemy.maxs - self.enemy.mins)*0.5);
+ self.tur_dist_impact_to_aimpos = vlen(trace_endpos - self.tur_aimpos);
- self.tur_impactent = trace_ent;
- self.tur_impacttime = vlen(self.tur_shotorg - trace_endpos) / self.shot_speed;
}
else
- tracebox(self.tur_shotorg, '-1 -1 -1','1 1 1',self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos),MOVE_NORMAL,self);
- //traceline(self.tur_shotorg, self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos),MOVE_NORMAL,self);
-
- self.tur_dist_impact_to_aimpos = vlen(trace_endpos - self.tur_aimpos) - (vlen(self.enemy.maxs - self.enemy.mins)*0.5);
- self.tur_impactent = trace_ent;
- self.tur_impacttime = vlen(self.tur_shotorg - trace_endpos) / self.shot_speed;
-
+ tracebox(self.tur_shotorg, '-1 -1 -1','1 1 1', self.tur_shotorg + (self.tur_shotdir_updated * self.tur_dist_aimpos),MOVE_NORMAL,self);
+
+ self.tur_dist_impact_to_aimpos = vlen(trace_endpos - self.tur_aimpos) - (vlen(self.enemy.maxs - self.enemy.mins) * 0.5);
+ self.tur_impactent = trace_ent;
+ self.tur_impacttime = vlen(self.tur_shotorg - trace_endpos) / self.shot_speed;
self = oldself;
}
** Handles head rotation according to
** the units .track_type and .track_flags
**/
-//.entity aim_mark;
void turret_stdproc_track()
{
vector target_angle; // This is where we want to aim
}
else
{
- // Find the direction
- target_angle = normalize(self.tur_aimpos - self.tur_shotorg);
- target_angle = vectoangles(target_angle); // And make a angle
+ target_angle = vectoangles(normalize(self.tur_aimpos - self.tur_shotorg));
}
-
- self.tur_head.angles_x = safeangle(self.tur_head.angles_x);
- self.tur_head.angles_y = safeangle(self.tur_head.angles_y);
+
+ self.tur_head.angles_x = anglemods(self.tur_head.angles_x);
+ self.tur_head.angles_y = anglemods(self.tur_head.angles_y);
// Find the diffrence between where we currently aim and where we want to aim
move_angle = target_angle - (self.angles + self.tur_head.angles);
move_angle = shortangle_vxy(move_angle,(self.angles + self.tur_head.angles));
-
-
-
switch(self.track_type)
{
case TFL_TRACKTYPE_STEPMOTOR:
case TFL_TRACKTYPE_FLUIDINERTIA:
f_tmp = self.aim_speed * self.ticrate; // dgr/sec -> dgr/tic
- move_angle_x = bound(-self.aim_speed, move_angle_x * self.track_accel_pitch * f_tmp,self.aim_speed);
- move_angle_y = bound(-self.aim_speed, move_angle_y * self.track_accel_rot * f_tmp,self.aim_speed);
+ move_angle_x = bound(-self.aim_speed, move_angle_x * self.track_accel_pitch * f_tmp, self.aim_speed);
+ move_angle_y = bound(-self.aim_speed, move_angle_y * self.track_accel_rot * f_tmp, self.aim_speed);
move_angle = (self.tur_head.avelocity * self.track_blendrate) + (move_angle * (1 - self.track_blendrate));
break;
self.tur_head.avelocity_x = 0;
self.tur_head.angles_x = self.aim_maxpitch;
}
+
if((self.tur_head.angles_x + self.tur_head.avelocity_x * self.ticrate) < -self.aim_maxpitch)
{
self.tur_head.avelocity_x = 0;
- self.tur_head.angles_x = self.aim_maxpitch;
+ self.tur_head.angles_x = -self.aim_maxpitch;
}
-
}
// rot
if((self.tur_head.angles_y + self.tur_head.avelocity_y * self.ticrate) < -self.aim_maxrot)
{
self.tur_head.avelocity_y = 0;
- self.tur_head.angles_y = self.aim_maxrot;
+ self.tur_head.angles_y = -self.aim_maxrot;
}
-
}
-
}
// Ready?
if (self.firecheck_flags & TFL_FIRECHECK_REFIRE)
- if (self.attack_finished_single >= time) return 0;
+ if (self.attack_finished_single > time) return 0;
// Special case: volly fire turret that has to fire a full volly if a shot was fired.
if (self.shoot_flags & TFL_SHOOT_VOLLYALWAYS)
if (self.firecheck_flags & TFL_FIRECHECK_OTHER_AMMO)
if (self.enemy.ammo >= self.enemy.ammo_max)
return 0;
+
+ // Target of opertunity?
+ if(turret_validate_target(self, self.tur_impactent, self.target_validate_flags) > 0)
+ {
+ self.enemy = self.tur_impactent;
+ return 1;
+ }
if (self.firecheck_flags & TFL_FIRECHECK_DISTANCES)
{
- // Not close enougth?
- //if (self.tur_dist_aimpos > self.target_range_fire) return 0;
-
// To close?
if (self.tur_dist_aimpos < self.target_range_min)
- return 0;
+ if(turret_validate_target(self, self.tur_impactent, self.target_validate_flags) > 0)
+ return 1; // Target of opertunity?
+ else
+ return 0;
}
// Try to avoid FF?
if (self.tur_dist_impact_to_aimpos > self.aim_firetolerance_dist)
return 0;
- //if (self.tur_impactent != self.enemy)
-
// Volly status
if (self.shot_volly > 1)
if (self.volly_counter == self.shot_volly)
** Evaluate a entity for target valitity based on validate_flags
** NOTE: the caller must check takedamage before calling this, to inline this check.
**/
-float turret_validate_target(entity e_turret,entity e_target,float validate_flags)
+float turret_validate_target(entity e_turret, entity e_target, float validate_flags)
{
vector v_tmp;
}
// Can we even aim this thing?
- tvt_thadv = angleofs3(e_turret.tur_head.origin,e_turret.angles + e_turret.tur_head.angles ,e_target);
- //tvt_thadv = angleofs(e_turret.angles,e_target);
-
-
-
- tvt_tadv = shortangle_vxy(angleofs(e_turret,e_target),e_turret.angles);
+ tvt_thadv = angleofs3(e_turret.tur_head.origin, e_turret.angles + e_turret.tur_head.angles, e_target);
+ tvt_tadv = shortangle_vxy(angleofs(e_turret, e_target), e_turret.angles);
tvt_thadf = vlen(tvt_thadv);
tvt_tadf = vlen(tvt_tadv);
float score; // target looper entity score
entity e_enemy; // currently best scoreing target
float m_score; // currently best scoreing target's score
- float f;
m_score = 0;
if(self.enemy)
else
self.enemy = world;
- e = findradius(self.origin,self.target_range);
+ e = findradius(self.origin, self.target_range);
// Nothing to aim at?
- if (!e) return world;
+ if (!e)
+ return world;
while (e)
{
if(e.takedamage)
{
- f = turret_validate_target(self,e,self.target_select_flags);
- if (f > 0)
+ if (turret_validate_target(self, e, self.target_select_flags) > 0)
{
score = self.turret_score_target(self,e);
if ((score > m_score) && (score > 0))
if not (g_onslaught)
if (self.target)
{
- e = find(world,targetname,self.target);
+ e = find(world, targetname,self.target);
if (e != world)
self.team = e.team;
}
// Handle ammo
if not (self.spawnflags & TSF_NO_AMMO_REGEN)
if (self.ammo < self.ammo_max)
- self.ammo = min(self.ammo + self.ammo_recharge,self.ammo_max);
-
+ self.ammo = min(self.ammo + self.ammo_recharge, self.ammo_max);
// Inactive turrets needs to run the think loop,
// So they can handle animation and wake up if need be.
return;
}
- //This is just wrong :| and unlikely to ever happen.
- /*
- if(self.deadflag != DEAD_NO)
- {
- dprint("WARNING: dead turret running the think function!\n");
- return;
- }
- */
-
// This is typicaly used for zaping every target in range
// turret_fusionreactor uses this to recharge friendlys.
if (self.shoot_flags & TFL_SHOOT_HITALLVALID)
// Check if we have a vailid enemy, and try to find one if we dont.
- // g_turrets_targetscan_maxdelay forces a target re-scan this often
+ // g_turrets_targetscan_maxdelay forces a target re-scan at least this often
float do_target_scan;
if((self.target_select_time + cvar("g_turrets_targetscan_maxdelay")) < time)
do_target_scan = 1;
// Old target (if any) invalid?
- if (turret_validate_target(self,self.enemy,self.target_validate_flags) <= 0)
- do_target_scan = 1;
+ if (turret_validate_target(self, self.enemy, self.target_validate_flags) <= 0)
+ {
+ self.enemy = world;
+ do_target_scan = 1;
+ }
// But never more often then g_turrets_targetscan_mindelay!
if (self.target_select_time + cvar("g_turrets_targetscan_mindelay") > time)
turret_fire();
}
- // do any per-turret stuff
+ // do any custom per-turret stuff
if(self.turret_postthink)
self.turret_postthink();
}
if (cvar("g_turrets_nofire") != 0)
return;
- /*
- // unlikely to ever happen.
- if (self.deadflag != DEAD_NO)
- return;
-
- if not (self.tur_active)
- return;
- */
-
self.turret_firefunc();
self.attack_finished_single = time + self.shot_refire;
/*
When .used a turret switch team to activator.team.
- If activator is world, the turrets goes inactive.
+ If activator is world, the turret go inactive.
*/
void turret_stdproc_use()
{
- dprint("Turret ",self.netname, " used by ",activator.classname,"\n");
+ dprint("Turret ",self.netname, " used by ", activator.classname, "\n");
self.team = activator.team;
{
entity e, ee;
- // Are turrets allowed atm?
+ // Are turrets allowed?
if (cvar("g_turrets") == 0)
return 0;
self.team = 14; // Assume turrets are on the defending side if not explicitly set otehrwize
}
else if not (teamplay)
- self.team = MAX_SHOT_DISTANCE; // Group all turrets into the same team iso they dont kill eachother.
+ self.team = MAX_SHOT_DISTANCE; // Group all turrets into the same team, so they dont kill eachother.
else if(g_onslaught && self.targetname)
{
e = find(world,target,self.targetname);
}
}
else if(!self.team)
- self.team = MAX_SHOT_DISTANCE; // Group all turrets into the same team iso they dont kill eachother.
+ self.team = MAX_SHOT_DISTANCE; // Group all turrets into the same team, so they dont kill eachother.
/*
* Try to guess some reasonaly defaults
* as possible beforehand.
*/
if (self.turrcaps_flags & TFL_TURRCAPS_SUPPORT)
- if not (self.ticrate) self.ticrate = 0.2; // Support units generaly dont need to have a high speed ai-loop
+ self.ticrate = 0.2; // Support units generaly dont need to have a high speed ai-loop
else
- if not (self.ticrate) self.ticrate = 0.1; // 10 fps for normal turrets
+ self.ticrate = 0.1; // 10 fps for normal turrets
- self.ticrate = bound(sys_frametime,self.ticrate,60); // keep it sane
+ self.ticrate = bound(sys_frametime, self.ticrate, 60); // keep it sane
// General stuff
if (self.netname == "")
if not (self.respawntime)
self.respawntime = 60;
- self.respawntime = max(-1,self.respawntime);
+ self.respawntime = max(-1, self.respawntime);
if not (self.health)
self.health = 1000;
- self.tur_health = max(1,self.health);
+ self.tur_health = max(1, self.health);
if not (self.turrcaps_flags)
self.turrcaps_flags = TFL_TURRCAPS_RADIUSDMG | TFL_TURRCAPS_MEDPROJ | TFL_TURRCAPS_PLAYERKILL;
- if (!self.damage_flags)
+ if not (self.damage_flags)
self.damage_flags = TFL_DMG_YES | TFL_DMG_RETALIATE | TFL_DMG_AIMSHAKE;
// Shot stuff.
if not (self.shot_refire)
self.shot_refire = 1;
- self.shot_refire = bound(0.01,self.shot_refire,9999);
+ self.shot_refire = bound(0.01, self.shot_refire, 9999);
if not (self.shot_dmg)
self.shot_dmg = self.shot_refire * 50;
- self.shot_dmg = max(1,self.shot_dmg);
+ self.shot_dmg = max(1, self.shot_dmg);
if not (self.shot_radius)
self.shot_radius = self.shot_dmg * 0.5;
- self.shot_radius = max(1,self.shot_radius);
+ self.shot_radius = max(1, self.shot_radius);
if not (self.shot_speed)
self.shot_speed = 2500;
- self.shot_speed = max(1,self.shot_speed);
+ self.shot_speed = max(1, self.shot_speed);
if not (self.shot_spread)
self.shot_spread = 0.0125;
- self.shot_spread = bound(0.0001,self.shot_spread,500);
+ self.shot_spread = bound(0.0001, self.shot_spread, 500);
if not (self.shot_force)
self.shot_force = self.shot_dmg * 0.5 + self.shot_radius * 0.5;
- self.shot_force = bound(0.001,self.shot_force,MAX_SHOT_DISTANCE * 0.5);
+ self.shot_force = bound(0.001, self.shot_force, 5000);
if not (self.shot_volly)
self.shot_volly = 1;
- self.shot_volly = bound(1,self.shot_volly,floor(self.ammo_max / self.shot_dmg));
+ self.shot_volly = bound(1, self.shot_volly, floor(self.ammo_max / self.shot_dmg));
if not (self.shot_volly_refire)
self.shot_volly_refire = self.shot_refire * self.shot_volly;
- self.shot_volly_refire = bound(self.shot_refire,self.shot_volly_refire,60);
+ self.shot_volly_refire = bound(self.shot_refire, self.shot_volly_refire, 60);
if not (self.firecheck_flags)
self.firecheck_flags = TFL_FIRECHECK_WORLD | TFL_FIRECHECK_DEAD | TFL_FIRECHECK_DISTANCES |
// Range stuff.
if not (self.target_range)
self.target_range = self.shot_speed * 0.5;
- self.target_range = bound(0,self.target_range,MAX_SHOT_DISTANCE);
+ self.target_range = bound(0, self.target_range, MAX_SHOT_DISTANCE);
if not (self.target_range_min)
self.target_range_min = self.shot_radius * 2;
- self.target_range_min = bound(0,self.target_range_min,MAX_SHOT_DISTANCE);
-
- //if (!self.target_range_fire)
- // self.target_range_fire = self.target_range * 0.8;
- //self.target_range_fire = bound(0,self.target_range_fire,MAX_SHOT_DISTANCE);
+ self.target_range_min = bound(0, self.target_range_min, MAX_SHOT_DISTANCE);
if not (self.target_range_optimal)
self.target_range_optimal = self.target_range * 0.5;
- self.target_range_optimal = bound(0,self.target_range_optimal,MAX_SHOT_DISTANCE);
+ self.target_range_optimal = bound(0, self.target_range_optimal, MAX_SHOT_DISTANCE);
// Aim stuff.
if not (self.aim_maxrot)
self.aim_maxrot = 90;
- self.aim_maxrot = bound(0,self.aim_maxrot,360);
+ self.aim_maxrot = bound(0, self.aim_maxrot, 360);
if not (self.aim_maxpitch)
self.aim_maxpitch = 20;
- self.aim_maxpitch = bound(0,self.aim_maxpitch,90);
+ self.aim_maxpitch = bound(0, self.aim_maxpitch, 90);
if not (self.aim_speed)
self.aim_speed = 36;
- self.aim_speed = bound(0.1,self.aim_speed, 1000);
+ self.aim_speed = bound(0.1, self.aim_speed, 1000);
if not (self.aim_firetolerance_dist)
self.aim_firetolerance_dist = 5 + (self.shot_radius * 2);
- self.aim_firetolerance_dist = bound(0.1,self.aim_firetolerance_dist,MAX_SHOT_DISTANCE);
+ self.aim_firetolerance_dist = bound(0.1, self.aim_firetolerance_dist, MAX_SHOT_DISTANCE);
if not (self.aim_flags)
{
self.aim_flags |= TFL_AIM_GROUND2;
}
- // Sill the most tested (and aim-effective)
if not (self.track_type)
self.track_type = TFL_TRACKTYPE_STEPMOTOR;
if (self.track_type != TFL_TRACKTYPE_STEPMOTOR)
{
- // Fluid / Ineria mode. Looks mutch nicer, bit experimental &
- // Can inmapt aim preformance alot.
- // needs a bit diffrent aimspeed
+ // Fluid / Ineria mode. Looks mutch nicer.
+ // Can reduce aim preformance alot, needs a bit diffrent aimspeed
if not (self.aim_speed)
self.aim_speed = 180;
- self.aim_speed = bound(0.1,self.aim_speed, 1000);
+ self.aim_speed = bound(0.1, self.aim_speed, 1000);
if not (self.track_accel_pitch)
self.track_accel_pitch = 0.5;
// Target selection stuff.
if not (self.target_select_rangebias)
self.target_select_rangebias = 1;
- self.target_select_rangebias = bound(-10,self.target_select_rangebias,10);
+ self.target_select_rangebias = bound(-10, self.target_select_rangebias, 10);
if not (self.target_select_samebias)
self.target_select_samebias = 1;
- self.target_select_samebias = bound(-10,self.target_select_samebias,10);
+ self.target_select_samebias = bound(-10, self.target_select_samebias, 10);
if not (self.target_select_anglebias)
self.target_select_anglebias = 1;
- self.target_select_anglebias = bound(-10,self.target_select_anglebias,10);
+ self.target_select_anglebias = bound(-10, self.target_select_anglebias, 10);
if not (self.target_select_missilebias)
self.target_select_missilebias = -10;
- self.target_select_missilebias = bound(-10,self.target_select_missilebias,10);
- self.target_select_playerbias = bound(-10,self.target_select_playerbias,10);
+ self.target_select_missilebias = bound(-10, self.target_select_missilebias, 10);
+ self.target_select_playerbias = bound(-10, self.target_select_playerbias, 10);
if not (self.target_select_flags)
{
// Ammo stuff
if not (self.ammo_max)
self.ammo_max = self.shot_dmg * 10;
- self.ammo_max = max(self.shot_dmg,self.ammo_max);
+ self.ammo_max = max(self.shot_dmg, self.ammo_max);
if not (self.ammo)
self.ammo = self.shot_dmg * 5;
- self.ammo = bound(0,self.ammo,self.ammo_max);
+ self.ammo = bound(0,self.ammo, self.ammo_max);
if not (self.ammo_recharge)
self.ammo_recharge = self.shot_dmg * 0.5;
- self.ammo_recharge = max(0,self.ammo_recharge);
+ self.ammo_recharge = max(0 ,self.ammo_recharge);
// Convert the recharge from X per sec to X per ticrate
self.ammo_recharge = self.ammo_recharge * self.ticrate;
self.tur_head.team = self.team;
self.tur_head.owner = self;
- setmodel(self,base);
- setmodel(self.tur_head,head);
+ setmodel(self, base);
+ setmodel(self.tur_head, head);
- setsize(self,'-32 -32 0','32 32 64');
- setsize(self.tur_head,'0 0 0','0 0 0');
+ setsize(self, '-32 -32 0', '32 32 64');
+ setsize(self.tur_head, '0 0 0', '0 0 0');
- setorigin(self.tur_head,'0 0 0');
+ setorigin(self.tur_head, '0 0 0');
setattachment(self.tur_head, self, "tag_head");
if (!self.health)
// In target defend mode, aim on the spot to defend when idle.
if (self.tur_defend)
- self.idle_aim = self.tur_head.angles + angleofs(self.tur_head,self.tur_defend);
+ self.idle_aim = self.tur_head.angles + angleofs(self.tur_head, self.tur_defend);
else
self.idle_aim = '0 0 0';
-//--// Some support routines //--//
-
-#define anglemodss(a) (a - floor(a / 360) * 360)
-
-float(float v) anglemods =
+/*
+* Return a angle within +/- 360.
+*/
+float anglemods(float v)
{
v = v - 360 * floor(v / 360);
- return v;
-}
-
-float safeangle(float a)
-{
- if((a >= -360) && (a <= 360))
- return a;
-
-
- a -= (360 * floor(a / 360));
-
- return a;
+
+ if(v >= 180)
+ return v - 360;
+ else if(v <= -180)
+ return v + 360;
+ else
+ return v;
}
-float shortangle_f(float ang1,float ang2)
+/*
+* Return the short angle
+*/
+float shortangle_f(float ang1, float ang2)
{
if(ang1 > ang2)
{
return ang1;
}
-vector shortangle_v(vector ang1,vector ang2)
+vector shortangle_v(vector ang1, vector ang2)
{
vector vtmp;
return vtmp;
}
-vector shortangle_vxy(vector ang1,vector ang2)
+vector shortangle_vxy(vector ang1, vector ang2)
{
vector vtmp;
return vtmp;
}
-// Get real origin
+
+/*
+* Get "real" origin, in worldspace, even if ent is attached to something else.
+*/
vector real_origin(entity ent)
{
entity e;
e = ent.tag_entity;
while(e)
{
- // v = v + e.origin;
v = v + ((e.absmin + e.absmax) * 0.5);
e = e.tag_entity;
}
- //v = v + ent.origin;
v = v + ((ent.absmin + ent.absmax) * 0.5);
return v;
}
-// Plug this into wherever precache is done.
-void g_turrets_common_precash()
-{
- precache_model ("models/turrets/c512.md3");
- precache_model ("models/marker.md3");
-}
-
-void SUB_Remove();
-void marker_think()
-{
- if(self.cnt)
- if(self.cnt < time)
- {
- self.think = SUB_Remove;
- self.nextthink = time;
- return;
- }
-
- self.frame += 1;
- if(self.frame > 29)
- self.frame = 0;
-
- self.nextthink = time;
-}
-
-void mark_error(vector where,float lifetime)
-{
- entity err;
-
- err = spawn();
- err.classname = "error_marker";
- setmodel(err,"models/marker.md3");
- setorigin(err,where);
- err.movetype = MOVETYPE_NONE;
- err.think = marker_think;
- err.nextthink = time;
- err.skin = 0;
- if(lifetime)
- err.cnt = lifetime + time;
-}
-
-void mark_info(vector where,float lifetime)
-{
- entity err;
-
- err = spawn();
- err.classname = "info_marker";
- setmodel(err,"models/marker.md3");
- setorigin(err,where);
- err.movetype = MOVETYPE_NONE;
- err.think = marker_think;
- err.nextthink = time;
- err.skin = 1;
- if(lifetime)
- err.cnt = lifetime + time;
-}
-
-entity mark_misc(vector where,float lifetime)
-{
- entity err;
-
- err = spawn();
- err.classname = "mark_misc";
- setmodel(err,"models/marker.md3");
- setorigin(err,where);
- err.movetype = MOVETYPE_NONE;
- err.think = marker_think;
- err.nextthink = time;
- err.skin = 3;
- if(lifetime)
- err.cnt = lifetime + time;
- return err;
-}
-
-/*
-* Paint a v_color colord circle on target onwho
-* that fades away over f_time
-*/
-void paint_target(entity onwho, float f_size, vector v_color, float f_time)
-{
- entity e;
-
- e = spawn();
- setmodel(e, "models/turrets/c512.md3"); // precision set above
- e.scale = (f_size/512);
- //setsize(e, '0 0 0', '0 0 0');
- //setattachment(e,onwho,"");
- setorigin(e,onwho.origin + '0 0 1');
- e.alpha = 0.15;
- e.movetype = MOVETYPE_FLY;
-
- e.velocity = (v_color * 32); // + '0 0 1' * 64;
-
- e.colormod = v_color;
- SUB_SetFade(e,time,f_time);
-}
-
-void paint_target2(entity onwho, float f_size, vector v_color, float f_time)
-{
- entity e;
-
- e = spawn();
- setmodel(e, "models/turrets/c512.md3"); // precision set above
- e.scale = (f_size/512);
- setsize(e, '0 0 0', '0 0 0');
-
- setorigin(e,onwho.origin + '0 0 1');
- e.alpha = 0.15;
- e.movetype = MOVETYPE_FLY;
-
- e.velocity = (v_color * 32); // + '0 0 1' * 64;
- e.avelocity_x = -128;
-
- e.colormod = v_color;
- SUB_SetFade(e,time,f_time);
-}
-
-void paint_target3(vector where, float f_size, vector v_color, float f_time)
-{
- entity e;
- e = spawn();
- setmodel(e, "models/turrets/c512.md3"); // precision set above
- e.scale = (f_size/512);
- setsize(e, '0 0 0', '0 0 0');
- setorigin(e,where+ '0 0 1');
- e.movetype = MOVETYPE_NONE;
- e.velocity = '0 0 0';
- e.colormod = v_color;
- SUB_SetFade(e,time,f_time);
-}
-
/*
* Return the angle between two enteties
*/
vector angleofs(entity from, entity to)
{
vector v_res;
-
- // makevectors(from.angles);
+
v_res = normalize(to.origin - from.origin);
v_res = vectoangles(v_res);
v_res = v_res - from.angles;
- if (v_res_x < 0) v_res_x += 360;
- if (v_res_x > 180) v_res_x -= 360;
-
- if (v_res_y < 0) v_res_y += 360;
- if (v_res_y > 180) v_res_y -= 360;
-
- return v_res;
-}
-
-vector angleofs2(entity from, vector to)
-{
- vector v_res;
-
- // makevectors(from.angles);
- v_res = normalize(to - from.origin);
- v_res = vectoangles(v_res);
- v_res = v_res - from.angles;
-
- if (v_res_x < 0) v_res_x += 360;
- if (v_res_x > 180) v_res_x -= 360;
+ if (v_res_x < 0) v_res_x += 360;
+ if (v_res_x > 180) v_res_x -= 360;
- if (v_res_y < 0) v_res_y += 360;
- if (v_res_y > 180) v_res_y -= 360;
+ if (v_res_y < 0) v_res_y += 360;
+ if (v_res_y > 180) v_res_y -= 360;
return v_res;
}
-vector angleofs3(vector from,vector from_a, entity to)
+vector angleofs3(vector from, vector from_a, entity to)
{
vector v_res;
-
- // makevectors(from.angles);
+
v_res = normalize(to.origin - from);
v_res = vectoangles(v_res);
v_res = v_res - from_a;
- if (v_res_x < 0) v_res_x += 360;
- if (v_res_x > 180) v_res_x -= 360;
+ if (v_res_x < 0) v_res_x += 360;
+ if (v_res_x > 180) v_res_x -= 360;
- if (v_res_y < 0) v_res_y += 360;
- if (v_res_y > 180) v_res_y -= 360;
+ if (v_res_y < 0) v_res_y += 360;
+ if (v_res_y > 180) v_res_y -= 360;
return v_res;
}
-float turret_tag_setup()
-{
- if(!self.tur_head)
- {
- dprint("Call to turret_tag_setup with self.tur_head missing!\n");
- self.tur_shotorg = '0 0 0';
- return 0;
- }
-
- //if not(self.turrcaps_flags & TFL_TURRCAPS_HEADATTACHED)
- // setorigin(self.tur_head,gettaginfo(self,gettagindex(self,"tag_head")));
-
- self.tur_shotorg = gettaginfo(self.tur_head,gettagindex(self.tur_head,"tag_fire"));
-
- v_forward = normalize(v_forward);
-
- return 1;
-}
-
+/*
+* Update self.tur_shotorg by getting up2date bone info
+* NOTICE this func overwrites the global v_forward, v_right and v_up vectors.
+*/
float turret_tag_fire_update()
{
if(!self.tur_head)
{
- dprint("Call to turret_tag_fire_update with self.tur_head missing!\n");
+ error("Call to turret_tag_fire_update with self.tur_head missing!\n");
self.tur_shotorg = '0 0 0';
- return 0;
+ return FALSE;
}
- self.tur_shotorg = gettaginfo(self.tur_head,gettagindex(self.tur_head,"tag_fire"));
+ self.tur_shotorg = gettaginfo(self.tur_head, gettagindex(self.tur_head, "tag_fire"));
v_forward = normalize(v_forward);
- //dprint("update: tur_shotorg: ",vtos(self.tur_shotorg)," origin:", vtos(self.tur_head.origin), " angels: ", vtos(self.tur_head.angles),"\n");
-
- return 1;
+ return TRUE;
}
-void FireImoBeam (vector start,vector end,vector smin,vector smax,
- float bforce,float f_dmg,float f_velfactor, float deathtype)
+/*
+* Railgun-like beam, but has thickness and suppots slowing of target
+*/
+void FireImoBeam (vector start, vector end, vector smin, vector smax,
+ float bforce, float f_dmg, float f_velfactor, float deathtype)
{
local vector hitloc, force, endpoint, dir;
trace_endpos = endpoint;
}
+// Plug this into wherever precache is done.
+void g_turrets_common_precash()
+{
+ precache_model ("models/turrets/c512.md3");
+ precache_model ("models/marker.md3");
+}
+
void turrets_precache_debug_models()
{
precache_model ("models/turrets/c512.md3");
//precache_model ("models/turrets/plasma.md3");
//precache_model ("models/turrets/tesla_head.md3");
//precache_model ("models/turrets/tesla_base.md3");
- //turrets_precache_debug_models();
+ #ifdef TURRET_DEBUG
+ turrets_precache_debug_models();
+ #endif
+}
+
+
+#ifdef TURRET_DEBUG
+void SUB_Remove();
+void marker_think()
+{
+ if(self.cnt)
+ if(self.cnt < time)
+ {
+ self.think = SUB_Remove;
+ self.nextthink = time;
+ return;
+ }
+
+ self.frame += 1;
+ if(self.frame > 29)
+ self.frame = 0;
+
+ self.nextthink = time;
+}
+
+void mark_error(vector where,float lifetime)
+{
+ entity err;
+
+ err = spawn();
+ err.classname = "error_marker";
+ setmodel(err,"models/marker.md3");
+ setorigin(err,where);
+ err.movetype = MOVETYPE_NONE;
+ err.think = marker_think;
+ err.nextthink = time;
+ err.skin = 0;
+ if(lifetime)
+ err.cnt = lifetime + time;
+}
+
+void mark_info(vector where,float lifetime)
+{
+ entity err;
+
+ err = spawn();
+ err.classname = "info_marker";
+ setmodel(err,"models/marker.md3");
+ setorigin(err,where);
+ err.movetype = MOVETYPE_NONE;
+ err.think = marker_think;
+ err.nextthink = time;
+ err.skin = 1;
+ if(lifetime)
+ err.cnt = lifetime + time;
+}
+
+entity mark_misc(vector where,float lifetime)
+{
+ entity err;
+
+ err = spawn();
+ err.classname = "mark_misc";
+ setmodel(err,"models/marker.md3");
+ setorigin(err,where);
+ err.movetype = MOVETYPE_NONE;
+ err.think = marker_think;
+ err.nextthink = time;
+ err.skin = 3;
+ if(lifetime)
+ err.cnt = lifetime + time;
+ return err;
+}
+
+/*
+* Paint a v_color colord circle on target onwho
+* that fades away over f_time
+*/
+void paint_target(entity onwho, float f_size, vector v_color, float f_time)
+{
+ entity e;
+
+ e = spawn();
+ setmodel(e, "models/turrets/c512.md3"); // precision set above
+ e.scale = (f_size/512);
+ //setsize(e, '0 0 0', '0 0 0');
+ //setattachment(e,onwho,"");
+ setorigin(e,onwho.origin + '0 0 1');
+ e.alpha = 0.15;
+ e.movetype = MOVETYPE_FLY;
+
+ e.velocity = (v_color * 32); // + '0 0 1' * 64;
+
+ e.colormod = v_color;
+ SUB_SetFade(e,time,f_time);
+}
+
+void paint_target2(entity onwho, float f_size, vector v_color, float f_time)
+{
+ entity e;
+
+ e = spawn();
+ setmodel(e, "models/turrets/c512.md3"); // precision set above
+ e.scale = (f_size/512);
+ setsize(e, '0 0 0', '0 0 0');
+
+ setorigin(e,onwho.origin + '0 0 1');
+ e.alpha = 0.15;
+ e.movetype = MOVETYPE_FLY;
+
+ e.velocity = (v_color * 32); // + '0 0 1' * 64;
+ e.avelocity_x = -128;
+
+ e.colormod = v_color;
+ SUB_SetFade(e,time,f_time);
+}
+
+void paint_target3(vector where, float f_size, vector v_color, float f_time)
+{
+ entity e;
+ e = spawn();
+ setmodel(e, "models/turrets/c512.md3"); // precision set above
+ e.scale = (f_size/512);
+ setsize(e, '0 0 0', '0 0 0');
+ setorigin(e,where+ '0 0 1');
+ e.movetype = MOVETYPE_NONE;
+ e.velocity = '0 0 0';
+ e.colormod = v_color;
+ SUB_SetFade(e,time,f_time);
}
+#endif
/*
* Generic bias aware score system.
*/
-float turret_stdproc_targetscore_generic(entity e_turret,entity e_target)
+float turret_stdproc_targetscore_generic(entity e_turret, entity e_target)
{
//vector v_tmp;
float d_dist; // Defendmode Distance
float ikr; // ideal kill range
- if(!e_target) return 0;
-
- //if (e_target == e_turret.enemy) s_score = 1;
+ /*
+ if(!e_target)
+ return 0;
+ */
if (e_turret.tur_defend)
{
if ((e_turret.target_select_playerbias > 0) && (e_target.flags & FL_CLIENT))
p_score = 1;
- d_score = max(d_score,0);
- a_score = max(a_score,0);
- m_score = max(m_score,0);
- p_score = max(p_score,0);
+ d_score = max(d_score, 0);
+ a_score = max(a_score, 0);
+ m_score = max(m_score, 0);
+ p_score = max(p_score, 0);
score = (d_score * e_turret.target_select_rangebias) +
(a_score * e_turret.target_select_anglebias) +
proj.bot_dodgerating = self.shot_dmg;
proj.think = turret_ewheel_projectile_explode;
proj.nextthink = time + 9;
- proj.solid = SOLID_BBOX;
+ //proj.solid = SOLID_TRIGGER;
proj.movetype = MOVETYPE_FLYMISSILE;
proj.velocity = normalize(self.tur_shotdir_updated + randomvec() * self.shot_spread) * self.shot_speed;
proj.touch = turret_ewheel_projectile_explode;
proj.enemy = self.enemy;
proj.flags = FL_PROJECTILE | FL_NOTARGET;
+ PROJECTILE_MAKETRIGGER(proj);
CSQCProjectile(proj, TRUE, PROJECTILE_LASER, TRUE);
}
self.target_select_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK | TFL_TARGETSELECT_LOS;
+ self.target_select_flags = 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;
+ self.target_validate_flags = TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;// | TFL_TARGETSELECT_LOS;
self.damage_flags |= TFL_DMG_DEATH_NOGIBS;
self.iscreature = TRUE;
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())
+ if (!turret_tag_fire_update())
dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
//setorigin(self,self.origin + '0 0 128');
self.damage_flags |= TFL_DMG_HEADSHAKE;
self.target_select_flags |= TFL_TARGETSELECT_NOTURRETS | TFL_TARGETSELECT_MISSILESONLY;
- if (!turret_tag_setup())
+ if (!turret_tag_fire_update())
dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
// Our fire routine
return;
}
- if (!turret_tag_setup())
+ if (!turret_tag_fire_update())
dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
self.turret_firefunc = turret_hellion_attack;
self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_TEAMCHECK;
- if (!turret_tag_setup())
+ if (!turret_tag_fire_update())
dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
// Our fire routine
self.ammo_flags = TFL_AMMO_BULLETS | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
self.turrcaps_flags = TFL_TURRCAPS_PLAYERKILL;
- self.aim_flags = TFL_AIM_LEAD;
-
- if(cvar("g_antilag_bullets"))
- self.turrcaps_flags |= TFL_TURRCAPS_HITSCAN;
- else
- self.aim_flags |= TFL_AIM_SHOTTIMECOMPENSATE;
+ self.aim_flags = TFL_AIM_LEAD | TFL_AIM_SHOTTIMECOMPENSATE;
+
+ if not (cvar("g_antilag_bullets"))
+ self.turrcaps_flags |= TFL_TURRCAPS_HITSCAN;
if (turret_stdproc_init("machinegun_std",0,"models/turrets/base.md3","models/turrets/machinegun.md3") == 0)
{
self.damage_flags |= TFL_DMG_HEADSHAKE;
- if (!turret_tag_setup())
+ if (!turret_tag_fire_update())
dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
// Our fire routine
self.shoot_flags |= TFL_SHOOT_VOLLYALWAYS;
self.volly_counter = self.shot_volly;
- if (!turret_tag_setup())
+ if (!turret_tag_fire_update())
dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
// Our fire routine
self.turrcaps_flags = TFL_TURRCAPS_SNIPER|TFL_TURRCAPS_HITSCAN|TFL_TURRCAPS_PLAYERKILL;
self.ammo_flags = TFL_AMMO_ENERGY | TFL_AMMO_RECHARGE | TFL_AMMO_RECIVE;
- self.aim_flags = TFL_AIM_ZEASE | TFL_AIM_LEAD;
+ self.aim_flags = TFL_AIM_LEAD;
if (turret_stdproc_init("phaser_std",0,"models/turrets/base.md3","models/turrets/phaser.md3") == 0)
{
return;
}
- if (!turret_tag_setup())
+ if (!turret_tag_fire_update())
dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
self.turret_firecheckfunc = turret_phaser_firecheck;
self.damage_flags |= TFL_DMG_HEADSHAKE;
self.firecheck_flags |= TFL_FIRECHECK_AFF;
- if (!turret_tag_setup())
+ if (!turret_tag_fire_update())
dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
// Our fireing routine
self.damage_flags |= TFL_DMG_HEADSHAKE;
self.firecheck_flags |= TFL_FIRECHECK_AFF;
- if (!turret_tag_setup())
+ if (!turret_tag_fire_update())
dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
// Our fireing routine
self.target_validate_flags = TFL_TARGETSELECT_PLAYERS | TFL_TARGETSELECT_MISSILES |
TFL_TARGETSELECT_RANGELIMTS | TFL_TARGETSELECT_TEAMCHECK;
- if (!turret_tag_setup())
+ if (!turret_tag_fire_update())
dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
self.turret_firefunc = turret_tesla_fire;
return;
}
- if (!turret_tag_setup())
+ if (!turret_tag_fire_update())
dprint("Warning: Turret ",self.classname, " faild to initialize md3 tags\n");
self.damage_flags |= TFL_DMG_DEATH_NOGIBS;
ftmp2 = ftmp * -1;
ftmp = bound(ftmp2, shortangle_f(player.v_angle_y - racer.angles_y, racer.angles_y), ftmp);
- ftmp2 = safeangle(racer.angles_y + ftmp);
+ ftmp2 = anglemods(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 = safeangle(racer.angles_z + ftmp);
+ ftmp = anglemods(racer.angles_z + ftmp);
racer.angles_z = bound(-85, ftmp, 85);
// Turn
ftmp2 = ftmp * -1;
ftmp = bound(ftmp2,shortangle_f(player.v_angle_x - racer.angles_x,racer.angles_x),ftmp);
- racer.angles_x = safeangle(racer.angles_x + ftmp);
+ racer.angles_x = anglemods(racer.angles_x + ftmp);
racer.angles_x *= -1;
df = racer.velocity * -0.5;
//vhic.angles_z = ftmp;
// Turn
- vhic.angles_y = safeangle(vhic.angles_y + ftmp);
+ vhic.angles_y = anglemods(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 = bound(-60,anglemods(vhic.angles_x + ftmp),60);
vhic.angles_x *= -1;
if(raptor_movestyle == 1)
}
else
{
- spider.angles_y = safeangle(spider.angles_y + ftmp);
+ spider.angles_y = anglemods(spider.angles_y + ftmp);
spider.tur_head.angles_y -= ftmp;
if(player.movement_x != 0)
#include "w_shotgun.qc"
#include "w_uzi.qc"
#include "w_grenadelauncher.qc"
+#include "w_minelayer.qc"
#include "w_electro.qc"
#include "w_crylink.qc"
#include "w_nex.qc"
w_shotorg = self.origin + self.view_ofs + ((w_shotorg - self.origin - self.view_ofs) * v_forward) * v_forward;
}
- fireBallisticBullet(w_shotorg, w_shotdir, pSpread, pSpeed, pLifetime, pDamage, pHeadshotAddedDamage / pDamage, pForce, deathtype, (cvar("g_balance_campingrifle_tracer") ? EF_RED : EF_BLUE), 1, pBulletConstant);
+ if(deathtype & HITTYPE_SECONDARY)
+ fireBallisticBullet(w_shotorg, w_shotdir, pSpread, pSpeed, pLifetime, pDamage, pHeadshotAddedDamage / pDamage, pForce, deathtype, (cvar("g_balance_campingrifle_secondary_tracer") ? EF_RED : EF_BLUE), 1, pBulletConstant);
+ else
+ fireBallisticBullet(w_shotorg, w_shotdir, pSpread, pSpeed, pLifetime, pDamage, pHeadshotAddedDamage / pDamage, pForce, deathtype, (cvar("g_balance_campingrifle_primary_tracer") ? EF_RED : EF_BLUE), 1, pBulletConstant);
endFireBallisticBullet();
if (cvar("g_casings") >= 2)
void lgbeam_think()
{
self.owner.prevlgfire = time;
- if (self.owner.weaponentity.state != WS_INUSE || (self.owner.ammo_cells <= 0 && !(self.owner.items & IT_UNLIMITED_WEAPON_AMMO)) || self != self.owner.lgbeam || self.owner.deadflag != DEAD_NO || !self.owner.BUTTON_ATCK)
+ if (self != self.owner.lgbeam)
{
remove(self);
return;
}
+ if (self.owner.weaponentity.state != WS_INUSE || (self.owner.ammo_cells <= 0 && !(self.owner.items & IT_UNLIMITED_WEAPON_AMMO)) || self.owner.deadflag != DEAD_NO || !self.owner.BUTTON_ATCK)
+ {
+ if(self == self.owner.lgbeam)
+ self.owner.lgbeam = world;
+ remove(self);
+ return;
+ }
self.nextthink = time;
{
if(cvar("g_balance_electro_lightning"))
{
- if (self.BUTTON_ATCK_prev == 0)
+ if ((!self.lgbeam) || wasfreed(self.lgbeam))
{
W_Electro_Attack3();
}
{
if (self.BUTTON_ATCK)
if (time >= self.fireball_primarytime)
- if (weapon_prepareattack(1, cvar("g_balance_fireball_primary_refire")))
+ if (weapon_prepareattack(0, cvar("g_balance_fireball_primary_refire")))
{
W_Fireball_Attack1_Frame0();
self.fireball_primarytime = time + cvar("g_balance_fireball_primary_refire2");
}
if (self.BUTTON_ATCK2)
- if (weapon_prepareattack(0, cvar("g_balance_fireball_secondary_refire")))
+ if (weapon_prepareattack(1, cvar("g_balance_fireball_secondary_refire")))
{
W_Fireball_Attack2();
weapon_thinkf(WFRAME_FIRE2, cvar("g_balance_fireball_secondary_animtime"), w_ready);
REGISTER_WEAPON(GRENADE_LAUNCHER, w_glauncher, IT_ROCKETS, 4, WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_MID, "gl", "grenadelauncher", "Mortar");
#else
#ifdef SVQC
+.float gl_detonate_later;
+.float gl_bouncecnt;
+
void W_Grenade_Explode (void)
{
if(other.takedamage == DAMAGE_AIM)
}
}
+void W_Grenade_Think1 (void)
+{
+ self.nextthink = time;
+ if (time > self.cnt)
+ {
+ other = world;
+ self.projectiledeathtype |= HITTYPE_BOUNCE;
+ W_Grenade_Explode ();
+ return;
+ }
+ if(self.gl_detonate_later && self.gl_bouncecnt >= cvar("g_balance_grenadelauncher_primary_remote_minbouncecnt"))
+ W_Grenade_Explode();
+}
+
void W_Grenade_Touch1 (void)
{
PROJECTILE_TOUCH;
- if(cvar("g_balance_grenadelauncher_primary_sticky") && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE)))
+ if (other.takedamage == DAMAGE_AIM || cvar("g_balance_grenadelauncher_primary_type") == 0) // always explode when hitting a player, or if normal mortar projectile
+ {
+ self.use ();
+ }
+ else if (cvar("g_balance_grenadelauncher_primary_type") == 1) // bounce
+ {
+ float r;
+ r = random() * 6;
+ if(r < 1)
+ spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce1.wav", VOL_BASE, ATTN_NORM);
+ else if(r < 2)
+ spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce2.wav", VOL_BASE, ATTN_NORM);
+ else if(r < 3)
+ spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce3.wav", VOL_BASE, ATTN_NORM);
+ else if(r < 4)
+ spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce4.wav", VOL_BASE, ATTN_NORM);
+ else if(r < 5)
+ spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce5.wav", VOL_BASE, ATTN_NORM);
+ else
+ spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce6.wav", VOL_BASE, ATTN_NORM);
+ self.projectiledeathtype |= HITTYPE_BOUNCE;
+ self.gl_bouncecnt += 1;
+ }
+ else if(cvar("g_balance_grenadelauncher_primary_type") == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick
{
spamsound (self, CHAN_PROJECTILE, "weapons/grenade_stick.wav", VOL_BASE, ATTN_NORM);
self.nextthink = min(self.nextthink, time + cvar("g_balance_grenadelauncher_primary_lifetime2"));
}
- else
- W_Grenade_Explode ();
}
void W_Grenade_Touch2 (void)
{
PROJECTILE_TOUCH;
- if(cvar("g_balance_grenadelauncher_secondary_sticky") && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE)))
+ if (other.takedamage == DAMAGE_AIM || cvar("g_balance_grenadelauncher_secondary_type") == 0) // always explode when hitting a player, or if normal mortar projectile
+ {
+ self.use ();
+ }
+ else if (cvar("g_balance_grenadelauncher_secondary_type") == 1) // bounce
+ {
+ float r;
+ r = random() * 6;
+ if(r < 1)
+ spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce1.wav", VOL_BASE, ATTN_NORM);
+ else if(r < 2)
+ spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce2.wav", VOL_BASE, ATTN_NORM);
+ else if(r < 3)
+ spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce3.wav", VOL_BASE, ATTN_NORM);
+ else if(r < 4)
+ spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce4.wav", VOL_BASE, ATTN_NORM);
+ else if(r < 5)
+ spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce5.wav", VOL_BASE, ATTN_NORM);
+ else
+ spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce6.wav", VOL_BASE, ATTN_NORM);
+ self.projectiledeathtype |= HITTYPE_BOUNCE;
+ self.gl_bouncecnt += 1;
+ }
+ else if(cvar("g_balance_grenadelauncher_secondary_type") == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick
{
spamsound (self, CHAN_PROJECTILE, "weapons/grenade_stick.wav", VOL_BASE, ATTN_NORM);
self.nextthink = min(self.nextthink, time + cvar("g_balance_grenadelauncher_secondary_lifetime2"));
}
- else
- {
- if (cvar("g_balance_grenadelauncher_secondary_sticky") || other.takedamage == DAMAGE_AIM)
- {
- self.use ();
- }
- else
- {
- float r;
- r = random() * 6;
- if(r < 1)
- spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce1.wav", VOL_BASE, ATTN_NORM);
- else if(r < 2)
- spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce2.wav", VOL_BASE, ATTN_NORM);
- else if(r < 3)
- spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce3.wav", VOL_BASE, ATTN_NORM);
- else if(r < 4)
- spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce4.wav", VOL_BASE, ATTN_NORM);
- else if(r < 5)
- spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce5.wav", VOL_BASE, ATTN_NORM);
- else
- spamsound (self, CHAN_PROJECTILE, "weapons/grenade_bounce6.wav", VOL_BASE, ATTN_NORM);
- self.projectiledeathtype |= HITTYPE_BOUNCE;
- }
- }
}
void W_Grenade_Attack (void)
gren.bot_dodge = TRUE;
gren.bot_dodgerating = cvar("g_balance_grenadelauncher_primary_damage");
gren.movetype = MOVETYPE_BOUNCE;
+ gren.bouncefactor = cvar("g_balance_grenadelauncher_primary_bouncefactor");
+ gren.bouncestop = cvar("g_balance_grenadelauncher_primary_bouncestop");
PROJECTILE_MAKETRIGGER(gren);
gren.projectiledeathtype = WEP_GRENADE_LAUNCHER;
setorigin(gren, w_shotorg);
setsize(gren, '-3 -3 -3', '3 3 3');
- gren.nextthink = time + cvar("g_balance_grenadelauncher_primary_lifetime");
- gren.think = adaptor_think2use_hittype_splash;
+ gren.cnt = time + cvar("g_balance_grenadelauncher_primary_lifetime");
+ gren.nextthink = time;
+ gren.think = W_Grenade_Think1;
gren.use = W_Grenade_Explode;
gren.touch = W_Grenade_Touch1;
gren.takedamage = DAMAGE_YES;
gren.health = cvar("g_balance_grenadelauncher_primary_health");
+ gren.damageforcescale = cvar("g_balance_grenadelauncher_primary_damageforcescale");
gren.event_damage = W_Grenade_Damage;
W_SETUPPROJECTILEVELOCITY_UP(gren, g_balance_grenadelauncher_primary);
gren.angles = vectoangles (gren.velocity);
gren.flags = FL_PROJECTILE;
- CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE, TRUE);
+ if(cvar("g_balance_grenadelauncher_primary_type") == 0 || cvar("g_balance_grenadelauncher_primary_type") == 2)
+ CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE, TRUE);
+ else
+ CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE_BOUNCING, TRUE);
}
void W_Grenade_Attack2 (void)
gren.angles = vectoangles (gren.velocity);
gren.flags = FL_PROJECTILE;
- if(cvar("g_balance_grenadelauncher_secondary_sticky"))
+ if(cvar("g_balance_grenadelauncher_secondary_type") == 0 || cvar("g_balance_grenadelauncher_secondary_type") == 2)
CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE, TRUE);
else
CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE_BOUNCING, TRUE);
.float bot_secondary_grenademooth;
float w_glauncher(float req)
{
+ entity nade;
+ float nadefound;
+
if (req == WR_AIM)
{
self.BUTTON_ATCK = FALSE;
if (self.BUTTON_ATCK)
if (weapon_prepareattack(0, cvar("g_balance_grenadelauncher_primary_refire")))
{
- if(cvar("g_balance_grenadelauncher_primary2secondary"))
- W_Grenade_Attack2();
- else
- W_Grenade_Attack();
+ W_Grenade_Attack();
weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_grenadelauncher_primary_animtime"), w_ready);
}
- if (self.BUTTON_ATCK2 && !cvar("g_balance_grenadelauncher_primary2secondary"))
- if (weapon_prepareattack(1, cvar("g_balance_grenadelauncher_secondary_refire")))
+ if (self.BUTTON_ATCK2)
{
- W_Grenade_Attack2();
- weapon_thinkf(WFRAME_FIRE2, cvar("g_balance_grenadelauncher_secondary_animtime"), w_ready);
+ if (cvar("g_balance_grenadelauncher_secondary_remote_detonateprimary"))
+ {
+ nadefound = 0;
+ for(nade = world; (nade = find(nade, classname, "grenade")); ) if(nade.owner == self)
+ {
+ if(!nade.gl_detonate_later)
+ {
+ nade.gl_detonate_later = TRUE;
+ nadefound = 1;
+ }
+ }
+ if(nadefound)
+ sound (self, CHAN_WEAPON2, "weapons/rocket_det.wav", VOL_BASE, ATTN_NORM);
+ }
+ else if (weapon_prepareattack(1, cvar("g_balance_grenadelauncher_secondary_refire")))
+ {
+ W_Grenade_Attack2();
+ weapon_thinkf(WFRAME_FIRE2, cvar("g_balance_grenadelauncher_secondary_animtime"), w_ready);
+ }
}
}
else if (req == WR_PRECACHE)
--- /dev/null
+#ifdef REGISTER_WEAPON
+REGISTER_WEAPON(MINE_LAYER, w_minelayer, IT_ROCKETS, 4, WEP_FLAG_NORMAL | WEP_TYPE_SPLASH, BOT_PICKUP_RATING_HIGH, "minelayer", "minelayer", "Mine Layer");
+#else
+#ifdef SVQC
+void W_Mine_Think (void);
+.float minelayer_detonate, minelayer_mines;
+.float mine_time;
+
+void spawnfunc_weapon_minelayer (void)
+{
+ weapon_defaultspawnfunc(WEP_MINE_LAYER);
+}
+
+void W_Mine_Stick ()
+{
+ spamsound (self, CHAN_PROJECTILE, "weapons/mine_stick.wav", VOL_BASE, ATTN_NORM);
+
+ // in order for mines to face properly when sticking to the ground, they must be a server side entity rather than a csqc projectile
+
+ local entity newmine;
+ newmine = spawn();
+ newmine.classname = self.classname;
+
+ newmine.bot_dodge = self.bot_dodge;
+ newmine.bot_dodgerating = self.bot_dodgerating;
+
+ newmine.owner = self.owner;
+ setsize(newmine, '-4 -4 -4', '4 4 4');
+ setorigin(newmine, self.origin);
+ setmodel(newmine, "models/mine.md3");
+ newmine.angles = vectoangles(-trace_plane_normal); // face against the surface
+
+ newmine.takedamage = self.takedamage;
+ newmine.damageforcescale = self.damageforcescale;
+ newmine.health = self.health;
+ newmine.event_damage = self.event_damage;
+
+ newmine.movetype = MOVETYPE_NONE; // lock the mine in place
+ newmine.projectiledeathtype = self.projectiledeathtype;
+
+ newmine.mine_time = self.mine_time;
+
+ newmine.touch = SUB_Null;
+ newmine.think = W_Mine_Think;
+ newmine.nextthink = time;
+ newmine.cnt = self.cnt;
+ newmine.flags = self.flags;
+
+ remove(self);
+ self = newmine;
+}
+
+void W_Mine_Explode ()
+{
+ if(other.takedamage == DAMAGE_AIM)
+ if(other.classname == "player")
+ if(IsDifferentTeam(self.owner, other))
+ if(IsFlying(other))
+ AnnounceTo(self.owner, "airshot");
+
+ self.event_damage = SUB_Null;
+ self.takedamage = DAMAGE_NO;
+
+ RadiusDamage (self, self.owner, cvar("g_balance_minelayer_damage"), cvar("g_balance_minelayer_edgedamage"), cvar("g_balance_minelayer_radius"), world, cvar("g_balance_minelayer_force"), self.projectiledeathtype, other);
+
+ if (self.owner.weapon == WEP_MINE_LAYER)
+ {
+ if(self.owner.ammo_rockets < cvar("g_balance_minelayer_ammo"))
+ {
+ self.owner.cnt = WEP_MINE_LAYER;
+ ATTACK_FINISHED(self.owner) = time;
+ self.owner.switchweapon = w_getbestweapon(self.owner);
+ }
+ }
+ remove (self);
+}
+
+void W_Mine_DoRemoteExplode ()
+{
+ self.event_damage = SUB_Null;
+ self.takedamage = DAMAGE_NO;
+
+ RadiusDamage (self, self.owner, cvar("g_balance_minelayer_remote_damage"), cvar("g_balance_minelayer_remote_edgedamage"), cvar("g_balance_minelayer_remote_radius"), world, cvar("g_balance_minelayer_remote_force"), self.projectiledeathtype | HITTYPE_BOUNCE, world);
+
+ if (self.owner.weapon == WEP_MINE_LAYER)
+ {
+ if(self.owner.ammo_rockets < cvar("g_balance_minelayer_ammo"))
+ {
+ self.owner.cnt = WEP_MINE_LAYER;
+ ATTACK_FINISHED(self.owner) = time;
+ self.owner.switchweapon = w_getbestweapon(self.owner);
+ }
+ }
+ remove (self);
+}
+
+void W_Mine_RemoteExplode ()
+{
+ if(self.owner.deadflag == DEAD_NO)
+ if((self.spawnshieldtime >= 0)
+ ? (time >= self.spawnshieldtime) // timer
+ : (vlen(NearestPointOnBox(self.owner, self.origin) - self.origin) > cvar("g_balance_minelayer_radius")) // safety device
+ )
+ {
+ W_Mine_DoRemoteExplode();
+ }
+}
+
+void W_Mine_ProximityExplode ()
+{
+ // make sure no friend is in the mine's radius. If there is any, explosion is delayed until he's at a safe distance
+ if(cvar("g_balance_minelayer_protection"))
+ {
+ entity head;
+ head = findradius(self.origin, cvar("g_balance_minelayer_radius"));
+ while(head)
+ {
+ if(head == self.owner || !IsDifferentTeam(head, self.owner))
+ return;
+ head = head.chain;
+ }
+ }
+
+ self.mine_time = 0;
+ W_Mine_Explode();
+}
+
+void W_Mine_Think (void)
+{
+ entity head;
+
+ self.nextthink = time;
+ if (time > self.cnt)
+ {
+ other = world;
+ self.projectiledeathtype |= HITTYPE_BOUNCE;
+ W_Mine_Explode();
+ return;
+ }
+
+ // a player's mines shall explode if he disconnects or dies
+ // TODO: Do this on team change too
+ if(self.owner.classname != "player" || self.owner.deadflag != DEAD_NO)
+ {
+ other = world;
+ self.projectiledeathtype |= HITTYPE_BOUNCE;
+ W_Mine_Explode();
+ return;
+ }
+
+ // set the mine for detonation when a foe gets close enough
+ head = findradius(self.origin, cvar("g_balance_minelayer_proximityradius"));
+ while(head)
+ {
+ if(head.classname == "player" && head.deadflag == DEAD_NO)
+ if(head != self.owner && IsDifferentTeam(head, self.owner)) // don't trigger for team mates
+ if(!self.mine_time)
+ {
+ spamsound (self, CHAN_PROJECTILE, "weapons/mine_trigger.wav", VOL_BASE, ATTN_NORM);
+ self.mine_time = time + cvar("g_balance_minelayer_time");
+ }
+ head = head.chain;
+ }
+
+ // explode if it's time to
+ if(self.mine_time && time >= self.mine_time)
+ W_Mine_ProximityExplode();
+
+ // remote detonation
+ if (self.owner.weapon == WEP_MINE_LAYER)
+ if (self.owner.deadflag == DEAD_NO)
+ if (self.minelayer_detonate)
+ W_Mine_RemoteExplode();
+
+ if(self.csqcprojectile_clientanimate == 0)
+ UpdateCSQCProjectile(self);
+}
+
+void W_Mine_Touch (void)
+{
+ PROJECTILE_TOUCH;
+ if(!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))
+ W_Mine_Stick();
+ else if(self.movetype != MOVETYPE_NONE) // don't unstick a locked mine when someone touches it
+ self.velocity = '0 0 0';
+}
+
+void W_Mine_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+ if (self.health <= 0)
+ return;
+ self.health = self.health - damage;
+ self.angles = vectoangles(self.velocity);
+ if (self.health <= 0)
+ W_PrepareExplosionByDamage(attacker, W_Mine_Explode);
+}
+
+void W_Mine_Attack (void)
+{
+ local entity mine;
+ local entity flash;
+
+ // scan how many mines we placed, and return if we reached our limit
+ if(cvar("g_balance_minelayer_limit"))
+ {
+ self.minelayer_mines = 0;
+ for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
+ self.minelayer_mines += 1;
+
+ if(self.minelayer_mines >= cvar("g_balance_minelayer_limit"))
+ {
+ // the refire delay keeps this message from being spammed
+ sprint(self, strcat("You cannot place more than ^2", cvar_string("g_balance_minelayer_limit"), " ^7mines at a time\n") );
+ play2(self, "weapons/unavailable.wav");
+ return;
+ }
+ }
+
+ if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+ self.ammo_rockets = self.ammo_rockets - cvar("g_balance_minelayer_ammo");
+
+ W_SetupShot_ProjectileSize (self, '-4 -4 -4', '4 4 4', FALSE, 5, "weapons/mine_fire.wav", cvar("g_balance_minelayer_damage"));
+ pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+ mine = WarpZone_RefSys_SpawnSameRefSys(self);
+ mine.owner = self;
+ if(cvar("g_balance_minelayer_detonatedelay") >= 0)
+ mine.spawnshieldtime = time + cvar("g_balance_minelayer_detonatedelay");
+ else
+ mine.spawnshieldtime = -1;
+ mine.classname = "mine";
+ mine.bot_dodge = TRUE;
+ mine.bot_dodgerating = cvar("g_balance_minelayer_damage") * 2; // * 2 because it can detonate inflight which makes it even more dangerous
+
+ mine.takedamage = DAMAGE_YES;
+ mine.damageforcescale = cvar("g_balance_minelayer_damageforcescale");
+ mine.health = cvar("g_balance_minelayer_health");
+ mine.event_damage = W_Mine_Damage;
+
+ mine.movetype = MOVETYPE_TOSS;
+ PROJECTILE_MAKETRIGGER(mine);
+ mine.projectiledeathtype = WEP_MINE_LAYER;
+ setsize (mine, '-4 -4 -4', '4 4 4'); // give it some size so it can be shot
+
+ setorigin (mine, w_shotorg - v_forward * 4); // move it back so it hits the wall at the right point
+ W_SetupProjectileVelocity(mine, cvar("g_balance_minelayer_speed"), 0);
+ mine.angles = vectoangles (mine.velocity);
+
+ mine.touch = W_Mine_Touch;
+ mine.think = W_Mine_Think;
+ mine.nextthink = time;
+ mine.cnt = time + cvar("g_balance_minelayer_lifetime");
+ mine.flags = FL_PROJECTILE;
+
+ CSQCProjectile(mine, FALSE, PROJECTILE_MINE, TRUE);
+
+ // muzzle flash for 1st person view
+ flash = spawn ();
+ setmodel (flash, "models/flash.md3"); // precision set below
+ SUB_SetFade (flash, time, 0.1);
+ flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
+ W_AttachToShotorg(flash, '5 0 0');
+
+ // common properties
+}
+
+void spawnfunc_weapon_minelayer (void); // defined in t_items.qc
+
+float w_minelayer(float req)
+{
+ entity mine;
+ float minfound;
+ if (req == WR_AIM)
+ {
+ // aim and decide to fire if appropriate
+ self.BUTTON_ATCK = bot_aim(cvar("g_balance_minelayer_speed"), 0, cvar("g_balance_minelayer_lifetime"), FALSE);
+ if(skill >= 2) // skill 0 and 1 bots won't detonate mines!
+ {
+ // decide whether to detonate mines
+ local entity mine, targetlist, targ;
+ local float edgedamage, coredamage, edgeradius, recipricoledgeradius, d;
+ local float selfdamage, teamdamage, enemydamage;
+ edgedamage = cvar("g_balance_minelayer_edgedamage");
+ coredamage = cvar("g_balance_minelayer_damage");
+ edgeradius = cvar("g_balance_minelayer_radius");
+ recipricoledgeradius = 1 / edgeradius;
+ selfdamage = 0;
+ teamdamage = 0;
+ enemydamage = 0;
+ targetlist = findchainfloat(bot_attack, TRUE);
+ mine = find(world, classname, "mine");
+ while (mine)
+ {
+ if (mine.owner != self)
+ {
+ mine = find(mine, classname, "mine");
+ continue;
+ }
+ targ = targetlist;
+ while (targ)
+ {
+ d = vlen(targ.origin + (targ.mins + targ.maxs) * 0.5 - mine.origin);
+ d = bound(0, edgedamage + (coredamage - edgedamage) * sqrt(1 - d * recipricoledgeradius), 10000);
+ // count potential damage according to type of target
+ if (targ == self)
+ selfdamage = selfdamage + d;
+ else if (targ.team == self.team && teams_matter)
+ teamdamage = teamdamage + d;
+ else if (bot_shouldattack(targ))
+ enemydamage = enemydamage + d;
+ targ = targ.chain;
+ }
+ mine = find(mine, classname, "mine");
+ }
+ local float desirabledamage;
+ desirabledamage = enemydamage;
+ if (teamplay != 1 && time > self.invincible_finished && time > self.spawnshieldtime)
+ desirabledamage = desirabledamage - selfdamage * cvar("g_balance_selfdamagepercent");
+ if (self.team && teamplay != 1)
+ desirabledamage = desirabledamage - teamdamage;
+
+ mine = find(world, classname, "mine");
+ while (mine)
+ {
+ if (mine.owner != self)
+ {
+ mine = find(mine, classname, "mine");
+ continue;
+ }
+ makevectors(mine.v_angle);
+ targ = targetlist;
+ if (skill > 9) // normal players only do this for the target they are tracking
+ {
+ targ = targetlist;
+ while (targ)
+ {
+ if (
+ (v_forward * normalize(mine.origin - targ.origin)< 0.1)
+ && desirabledamage > 0.1*coredamage
+ )self.BUTTON_ATCK2 = TRUE;
+ targ = targ.chain;
+ }
+ }else{
+ local float distance; distance= bound(300,vlen(self.origin-self.enemy.origin),30000);
+ //As the distance gets larger, a correct detonation gets near imposible
+ //Bots are assumed to use the mine spawnfunc_light to see if the mine gets near a player
+ if(v_forward * normalize(mine.origin - self.enemy.origin)< 0.1)
+ if(self.enemy.classname == "player")
+ if(desirabledamage >= 0.1*coredamage)
+ if(random()/distance*300 > frametime*bound(0,(10-skill)*0.2,1))
+ self.BUTTON_ATCK2 = TRUE;
+ // dprint(ftos(random()/distance*300),">");dprint(ftos(frametime*bound(0,(10-skill)*0.2,1)),"\n");
+ }
+
+ mine = find(mine, classname, "mine");
+ }
+ // if we would be doing at X percent of the core damage, detonate it
+ // but don't fire a new shot at the same time!
+ if (desirabledamage >= 0.75 * coredamage) //this should do group damage in rare fortunate events
+ self.BUTTON_ATCK2 = TRUE;
+ if ((skill > 6.5) && (selfdamage > self.health))
+ self.BUTTON_ATCK2 = FALSE;
+ //if(self.BUTTON_ATCK2 == TRUE)
+ // dprint(ftos(desirabledamage),"\n");
+ if (self.BUTTON_ATCK2 == TRUE) self.BUTTON_ATCK = FALSE;
+ }
+ }
+ else if (req == WR_THINK)
+ {
+ if (self.BUTTON_ATCK)
+ {
+ if(weapon_prepareattack(0, cvar("g_balance_minelayer_refire")))
+ {
+ W_Mine_Attack();
+ weapon_thinkf(WFRAME_FIRE1, cvar("g_balance_minelayer_animtime"), w_ready);
+ }
+ }
+
+ if (self.BUTTON_ATCK2)
+ {
+ minfound = 0;
+ for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
+ {
+ if(!mine.minelayer_detonate)
+ {
+ mine.minelayer_detonate = TRUE;
+ minfound = 1;
+ }
+ }
+ if(minfound)
+ sound (self, CHAN_WEAPON2, "weapons/mine_det.wav", VOL_BASE, ATTN_NORM);
+ }
+ }
+ else if (req == WR_PRECACHE)
+ {
+ precache_model ("models/flash.md3");
+ precache_model ("models/mine.md3");
+ precache_model ("models/weapons/g_minelayer.md3");
+ precache_model ("models/weapons/v_minelayer.md3");
+ precache_model ("models/weapons/h_minelayer.iqm");
+ precache_sound ("weapons/mine_det.wav");
+ precache_sound ("weapons/mine_fire.wav");
+ precache_sound ("weapons/mine_stick.wav");
+ precache_sound ("weapons/mine_trigger.wav");
+ }
+ else if (req == WR_SETUP)
+ {
+ weapon_setup(WEP_MINE_LAYER);
+ }
+ else if (req == WR_CHECKAMMO1)
+ {
+ // don't switch while placing a mine
+ if ((ATTACK_FINISHED(self) <= time || self.weapon != WEP_MINE_LAYER)
+ && self.ammo_rockets < cvar("g_balance_minelayer_ammo"))
+ return FALSE;
+ }
+ else if (req == WR_CHECKAMMO2)
+ return FALSE;
+ return TRUE;
+};
+#endif
+#ifdef CSQC
+float w_minelayer(float req)
+{
+ if(req == WR_IMPACTEFFECT)
+ {
+ vector org2;
+ org2 = w_org + w_backoff * 12;
+ pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1);
+ if(!w_issilent)
+ sound(self, CHAN_PROJECTILE, "weapons/mine_exp.wav", VOL_BASE, ATTN_NORM);
+ }
+ else if(req == WR_PRECACHE)
+ {
+ precache_sound("weapons/mine_exp.wav");
+ }
+ else if (req == WR_SUICIDEMESSAGE)
+ w_deathtypestring = "%s exploded";
+ else if (req == WR_KILLMESSAGE)
+ {
+ if(w_deathtype & HITTYPE_BOUNCE) // (remote detonation)
+ w_deathtypestring = "%s got too close to %s's mine";
+ else if(w_deathtype & HITTYPE_SPLASH)
+ w_deathtypestring = "%s almost dodged %s's mine";
+ else
+ w_deathtypestring = "%s stepped on %s's mine";
+ }
+ return TRUE;
+}
+#endif
+#endif
void W_Nex_Attack (float issecondary)
{
- float mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, myammo, myvel;
+ float mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, myammo;
if(issecondary)
{
mydmg = cvar("g_balance_nex_secondary_damage");
float flying;
flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
- if(cvar("g_balance_nex_velocitydependent")) // player velocity dependent damage and force
+ if(cvar("g_balance_nex_charge"))
{
- myvel = vlen(self.velocity);
- myvel = bound(cvar("g_balance_nex_velocitydependent_minspeed"), myvel, cvar("g_balance_nex_velocitydependent_maxspeed"));
-
- // TODO: make it more obvious (through effects, indicator on weapon) that damage increases when speed increases
- mydmg *= myvel / cvar("g_balance_nex_velocitydependent_maxspeed");
- myforce *= myvel / cvar("g_balance_nex_velocitydependent_maxspeed");
+ mydmg *= self.nex_charge;
+ myforce *= self.nex_charge;
+ //print("^1Damage: ^7", ftos(mydmg), "\n");
+ self.nex_charge *= cvar("g_balance_nex_charge_shot_multiplier"); // do this AFTER setting mydmg/myforce
}
W_SetupShot (self, TRUE, 5, "weapons/nexfire.wav", mydmg);
}
else if (req == WR_THINK)
{
+ if(cvar("g_balance_nex_charge") && self.nex_charge < cvar("g_balance_nex_charge_limit"))
+ self.nex_charge = min(1, self.nex_charge + cvar("g_balance_nex_charge_rate") * frametime / W_TICSPERFRAME);
if (self.BUTTON_ATCK)
{
if (weapon_prepareattack(0, cvar("g_balance_nex_primary_refire")))
}
if (self.BUTTON_ATCK2)
{
- if(cvar("g_balance_nex_secondary"))
+ if(cvar("g_balance_nex_secondary_charge"))
+ {
+ if(self.ammo_cells && self.nex_charge < 1)
+ {
+ self.nex_charge = min(1, self.nex_charge + cvar("g_balance_nex_secondary_charge_rate") * frametime / W_TICSPERFRAME);
+ self.ammo_cells = max(0, self.ammo_cells - cvar("g_balance_nex_secondary_ammo") * frametime / W_TICSPERFRAME);
+ }
+ }
+ else if(cvar("g_balance_nex_secondary"))
{
if (weapon_prepareattack(0, cvar("g_balance_nex_secondary_refire")))
{
o1 = WarpZone_TransformOrigin(self, o0);
v1 = WarpZone_TransformVelocity(self, v0);
- if(player.classname == "player")
+ if(clienttype(player) != CLIENTTYPE_NOTACLIENT)
a1 = WarpZone_TransformVAngles(self, player.v_angle);
else
a1 = WarpZone_TransformAngles(self, a0);
void WarpZoneCamera_InitStep_FindTarget()
{
+ entity e;
+ float i;
if(self.target == "")
{
error("Camera with no target");
return;
}
- self.enemy = find(world, targetname, self.target);
+ self.enemy = world;
+ for(e = world, i = 0; (e = find(e, targetname, self.target)); )
+ if(random() * ++i < 1)
+ self.enemy = e;
if(self.enemy == world)
{
error("Camera with nonexisting target");
}
++warpzone_cameras_exist;
WarpZone_Camera_SetUp(self, self.enemy.origin, self.enemy.angles);
+ self.SendFlags = 0xFFFFFF;
}
void WarpZone_InitStep_UpdateTransform()
WarpZone_InitStep_ClearTarget();
for(self = warpzone_first; self; self = self.warpzone_next)
WarpZone_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_FinalizeTransform();
self = e;
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();
self = e;
WarpZone_StoreProjectileData(e);
}
+.float warpzone_reconnecting;
+float visible_to_some_client(entity ent)
+{
+ entity e;
+ for(e = nextent(world); clienttype(e) != CLIENTTYPE_NOTACLIENT; e = nextent(e))
+ if(e.classname == "player" && clienttype(e) == CLIENTTYPE_REAL)
+ if(checkpvs(e.origin + e.view_ofs, ent))
+ return 1;
+ return 0;
+}
void trigger_warpzone_reconnect_use()
{
entity e;
// 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)
+ self.warpzone_reconnecting = ((e.target == "" || self.target == e.target) && !((e.spawnflags & 1) && (visible_to_some_client(self) || visible_to_some_client(self.enemy))));
+ for(self = warpzone_camera_first; self; self = self.warpzone_next)
+ self.warpzone_reconnecting = ((e.target == "" || self.target == e.target) && !((e.spawnflags & 1) && visible_to_some_client(self)));
+ for(self = warpzone_first; self; self = self.warpzone_next)
+ if(self.warpzone_reconnecting)
WarpZone_InitStep_ClearTarget();
for(self = warpzone_first; self; self = self.warpzone_next)
- if(e.target == "" || self.target == e.target)
+ if(self.warpzone_reconnecting)
WarpZone_InitStep_FindTarget();
+ for(self = warpzone_camera_first; self; self = self.warpzone_next)
+ if(self.warpzone_reconnecting)
+ WarpZoneCamera_InitStep_FindTarget();
for(self = warpzone_first; self; self = self.warpzone_next)
- if(e.target == "" || self.target == e.target || self.enemy.target == e.target)
+ if(self.warpzone_reconnecting || self.enemy.warpzone_reconnecting)
WarpZone_InitStep_FinalizeTransform();
self = e;
}
//startdemos demos/demo1 demos/demo2 demos/demo3
//startdemos
//play announcer/male/welcome.ogg
+crypto_keygen 0 http://rm.endoftheinternet.org/~xonotic/keygen/?ca=0&key=
set g_turrets_unit_flac_std_shot_speed 9000
set g_turrets_unit_flac_std_shot_spread 0.02
set g_turrets_unit_flac_std_shot_force 25
+set g_turrets_unit_flac_std_shot_volly 0
+set g_turrets_unit_flac_std_shot_volly_refire 0
set g_turrets_unit_flac_std_target_range 4000
set g_turrets_unit_flac_std_target_range_min 500
set g_turrets_unit_flac_std_ammo_recharge 100
set g_turrets_unit_flac_std_aim_firetolerance_dist 150
-set g_turrets_unit_flac_std_aim_speed 360
+set g_turrets_unit_flac_std_aim_speed 200
set g_turrets_unit_flac_std_aim_maxrot 360
set g_turrets_unit_flac_std_aim_maxpitch 35
set g_turrets_unit_flac_std_track_type 3
-set g_turrets_unit_flac_std_track_accel_pitch 0.25
-set g_turrets_unit_flac_std_track_accel_rot 0.8
-set g_turrets_unit_flac_std_track_blendrate 0.6
+set g_turrets_unit_flac_std_track_accel_pitch 0.5
+set g_turrets_unit_flac_std_track_accel_rot 0.7
+set g_turrets_unit_flac_std_track_blendrate 0.2
set g_turrets_unit_hellion_std_track_type 3
set g_turrets_unit_hellion_std_track_accel_pitch 0.25
-set g_turrets_unit_hellion_std_track_accel_rot 0.5
-set g_turrets_unit_hellion_std_track_blendrate 0.75
+set g_turrets_unit_hellion_std_track_accel_rot 0.6
+set g_turrets_unit_hellion_std_track_blendrate 0.25
set g_turrets_unit_hk_std_track_type 3
set g_turrets_unit_hk_std_track_accel_pitch 0.25
-set g_turrets_unit_hk_std_track_accel_rot 0.5
-set g_turrets_unit_hk_std_track_blendrate 0.25
+set g_turrets_unit_hk_std_track_accel_rot 0.6
+set g_turrets_unit_hk_std_track_blendrate 0.2
set g_turrets_unit_machinegun_std_ammo_recharge 75
set g_turrets_unit_machinegun_std_aim_firetolerance_dist 25
-set g_turrets_unit_machinegun_std_aim_speed 720
+set g_turrets_unit_machinegun_std_aim_speed 120
set g_turrets_unit_machinegun_std_aim_maxrot 360
set g_turrets_unit_machinegun_std_aim_maxpitch 25
set g_turrets_unit_machinegun_std_track_type 3
-set g_turrets_unit_machinegun_std_track_accel_pitch 0.5
-set g_turrets_unit_machinegun_std_track_accel_rot 0.75
-set g_turrets_unit_machinegun_std_track_blendrate 0.5
+set g_turrets_unit_machinegun_std_track_accel_pitch 0.4
+set g_turrets_unit_machinegun_std_track_accel_rot 0.9
+set g_turrets_unit_machinegun_std_track_blendrate 0.2
set g_turrets_unit_mlrs_std_ammo_recharge 70
set g_turrets_unit_mlrs_std_aim_firetolerance_dist 120
-set g_turrets_unit_mlrs_std_aim_speed 270
+set g_turrets_unit_mlrs_std_aim_speed 100
set g_turrets_unit_mlrs_std_aim_maxrot 360
set g_turrets_unit_mlrs_std_aim_maxpitch 20
set g_turrets_unit_mlrs_std_track_type 3
set g_turrets_unit_mlrs_std_track_accel_pitch 0.5
-set g_turrets_unit_mlrs_std_track_accel_rot 0.8
+set g_turrets_unit_mlrs_std_track_accel_rot 0.7
set g_turrets_unit_mlrs_std_track_blendrate 0.2
set g_turrets_unit_phaser_std_aim_firetolerance_dist 100
-set g_turrets_unit_phaser_std_aim_speed 540
+set g_turrets_unit_phaser_std_aim_speed 300
set g_turrets_unit_phaser_std_aim_maxrot 360
set g_turrets_unit_phaser_std_aim_maxpitch 30
set g_turrets_unit_phaser_std_track_type 3
set g_turrets_unit_phaser_std_track_accel_pitch 0.5
set g_turrets_unit_phaser_std_track_accel_rot 0.65
-set g_turrets_unit_phaser_std_track_blendrate 0.5
+set g_turrets_unit_phaser_std_track_blendrate 0.2
// If predicted emeypos is this or closer to predicted impact, fire is ok
set g_turrets_unit_plasma_std_aim_firetolerance_dist 120
// Aim how fast. for track_type 1 this is dgr/sec, for 2 & 3 its the maximum angle speed added each second
-set g_turrets_unit_plasma_std_aim_speed 270
+set g_turrets_unit_plasma_std_aim_speed 200
// Max rottation of head
set g_turrets_unit_plasma_std_aim_maxrot 360
// Max pitch of head
set g_turrets_unit_plasma_std_track_type 3
// Following controls how _track_type = 3 works.
set g_turrets_unit_plasma_std_track_accel_pitch 0.5
-set g_turrets_unit_plasma_std_track_accel_rot 0.8
+set g_turrets_unit_plasma_std_track_accel_rot 0.7
set g_turrets_unit_plasma_std_track_blendrate 0.2
set g_turrets_unit_plasma_dual_aim_firetolerance_dist 200
-set g_turrets_unit_plasma_dual_aim_speed 270
+set g_turrets_unit_plasma_dual_aim_speed 100
set g_turrets_unit_plasma_dual_aim_maxrot 360
set g_turrets_unit_plasma_dual_aim_maxpitch 30
set g_turrets_unit_plasma_dual_track_type 3
set g_turrets_unit_plasma_dual_track_accel_pitch 0.5
-set g_turrets_unit_plasma_dual_track_accel_rot 0.75
-set g_turrets_unit_plasma_dual_track_blendrate 0.75
+set g_turrets_unit_plasma_dual_track_accel_rot 0.7
+set g_turrets_unit_plasma_dual_track_blendrate 0.2
by Forest "LordHavoc" Hale
**Active Contributors
+Antonio "terencehill" Piu
Ben "MooKow" Banker
Calinou
Kristian "morfar" Johansson