From: Mario Date: Fri, 14 Nov 2014 09:09:39 +0000 (+1100) Subject: Revert "Merge branch 'Mario/despawn_effects'" X-Git-Tag: xonotic-v0.8.0~151 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=5fcaa5e1251bcbbdedf31d885bdca0b2b75811c7;p=xonotic%2Fxonotic-data.pk3dir.git Revert "Merge branch 'Mario/despawn_effects'" This reverts commit 28931c8069eb1d283f01a26f31ad91d921294d9c, reversing changes made to d55940c3b65bffebfd3c571067398c65b29e9488. --- diff --git a/_hud_common.cfg b/_hud_common.cfg index 5aa1bbfee..4a4999706 100644 --- a/_hud_common.cfg +++ b/_hud_common.cfg @@ -23,7 +23,6 @@ seta hud_colorset_background "7" "neutral/unimportant text" seta hud_panel_weapons_ammo_full_shells 60 "show 100% of the status bar at this ammo count" seta hud_panel_weapons_ammo_full_nails 320 "show 100% of the status bar at this ammo count" seta hud_panel_weapons_ammo_full_cells 180 "show 100% of the status bar at this ammo count" -seta hud_panel_weapons_ammo_full_plasma 180 "show 100% of the status bar at this ammo count" seta hud_panel_weapons_ammo_full_rockets 160 "show 100% of the status bar at this ammo count" seta hud_panel_weapons_ammo_full_fuel 100 "show 100% of the status bar at this ammo count" diff --git a/bal-wep-rev.cfg b/bal-wep-rev.cfg deleted file mode 100644 index 99599dd15..000000000 --- a/bal-wep-rev.cfg +++ /dev/null @@ -1,753 +0,0 @@ -// {{{ #1: Blaster -set g_balance_blaster_primary_animtime 0.2 -set g_balance_blaster_primary_damage 25 -set g_balance_blaster_primary_delay 0 -set g_balance_blaster_primary_edgedamage 12.5 -set g_balance_blaster_primary_force 300 -set g_balance_blaster_primary_force_zscale 1.25 -set g_balance_blaster_primary_lifetime 5 -set g_balance_blaster_primary_radius 60 -set g_balance_blaster_primary_refire 0.7 -set g_balance_blaster_primary_shotangle 0 -set g_balance_blaster_primary_speed 6000 -set g_balance_blaster_primary_spread 0 -set g_balance_blaster_secondary 0 -set g_balance_blaster_secondary_animtime 0.2 -set g_balance_blaster_secondary_damage 25 -set g_balance_blaster_secondary_delay 0 -set g_balance_blaster_secondary_edgedamage 12.5 -set g_balance_blaster_secondary_force 300 -set g_balance_blaster_secondary_force_zscale 1.2 -set g_balance_blaster_secondary_lifetime 5 -set g_balance_blaster_secondary_radius 70 -set g_balance_blaster_secondary_refire 0.7 -set g_balance_blaster_secondary_shotangle 0 -set g_balance_blaster_secondary_speed 6000 -set g_balance_blaster_secondary_spread 0 -set g_balance_blaster_switchdelay_drop 0.2 -set g_balance_blaster_switchdelay_raise 0.2 -set g_balance_blaster_weaponreplace "" -set g_balance_blaster_weaponstart 1 -set g_balance_blaster_weaponstartoverride -1 -set g_balance_blaster_weaponthrowable 0 -// }}} -// {{{ #2: Shotgun -set g_balance_shotgun_primary_ammo 1 -set g_balance_shotgun_primary_animtime 0.2 -set g_balance_shotgun_primary_bullets 14 -set g_balance_shotgun_primary_damage 4 -set g_balance_shotgun_primary_force 15 -set g_balance_shotgun_primary_refire 0.75 -set g_balance_shotgun_primary_solidpenetration 3.8 -set g_balance_shotgun_primary_spread 0.12 -set g_balance_shotgun_reload_ammo 0 -set g_balance_shotgun_reload_time 2 -set g_balance_shotgun_secondary 1 -set g_balance_shotgun_secondary_animtime 1 -set g_balance_shotgun_secondary_damage 80 -set g_balance_shotgun_secondary_force 200 -set g_balance_shotgun_secondary_melee_delay 0.25 -set g_balance_shotgun_secondary_melee_multihit 1 -set g_balance_shotgun_secondary_melee_no_doubleslap 1 -set g_balance_shotgun_secondary_melee_nonplayerdamage 40 -set g_balance_shotgun_secondary_melee_range 120 -set g_balance_shotgun_secondary_melee_swing_side 120 -set g_balance_shotgun_secondary_melee_swing_up 30 -set g_balance_shotgun_secondary_melee_time 0.15 -set g_balance_shotgun_secondary_melee_traces 10 -set g_balance_shotgun_secondary_refire 1.25 -set g_balance_shotgun_switchdelay_drop 0.2 -set g_balance_shotgun_switchdelay_raise 0.2 -set g_balance_shotgun_weaponreplace "" -set g_balance_shotgun_weaponstart 1 -set g_balance_shotgun_weaponstartoverride -1 -set g_balance_shotgun_weaponthrowable 1 -// }}} -// {{{ #3: Machine Gun -set g_balance_machinegun_burst 3 -set g_balance_machinegun_burst_ammo 3 -set g_balance_machinegun_burst_animtime 0.3 -set g_balance_machinegun_burst_refire 0.06 -set g_balance_machinegun_burst_refire2 0.45 -set g_balance_machinegun_burst_speed 0 -set g_balance_machinegun_first 1 -set g_balance_machinegun_first_ammo 1 -set g_balance_machinegun_first_damage 14 -set g_balance_machinegun_first_force 5 -set g_balance_machinegun_first_refire 0.125 -set g_balance_machinegun_first_spread 0.03 -set g_balance_machinegun_mode 1 -set g_balance_machinegun_reload_ammo 60 -set g_balance_machinegun_reload_time 2 -set g_balance_machinegun_solidpenetration 13.1 -set g_balance_machinegun_spread_add 0.012 -set g_balance_machinegun_spread_max 0.05 -set g_balance_machinegun_spread_min 0.02 -set g_balance_machinegun_sustained_ammo 1 -set g_balance_machinegun_sustained_damage 10 -set g_balance_machinegun_sustained_force 5 -set g_balance_machinegun_sustained_refire 0.1 -set g_balance_machinegun_sustained_spread 0.03 -set g_balance_machinegun_switchdelay_drop 0.2 -set g_balance_machinegun_switchdelay_raise 0.2 -set g_balance_machinegun_weaponreplace "arc machinegun" -set g_balance_machinegun_weaponstart 0 -set g_balance_machinegun_weaponstartoverride -1 -set g_balance_machinegun_weaponthrowable 1 -// }}} -// {{{ #4: Mortar -set g_balance_mortar_bouncefactor 0.5 -set g_balance_mortar_bouncestop 0.075 -set g_balance_mortar_primary_ammo 2 -set g_balance_mortar_primary_animtime 0.3 -set g_balance_mortar_primary_damage 50 -set g_balance_mortar_primary_damageforcescale 0 -set g_balance_mortar_primary_edgedamage 25 -set g_balance_mortar_primary_force 250 -set g_balance_mortar_primary_health 15 -set g_balance_mortar_primary_lifetime 5 -set g_balance_mortar_primary_lifetime_stick 0 -set g_balance_mortar_primary_radius 120 -set g_balance_mortar_primary_refire 0.8 -set g_balance_mortar_primary_remote_minbouncecnt 0 -set g_balance_mortar_primary_speed 1900 -set g_balance_mortar_primary_speed_up 225 -set g_balance_mortar_primary_speed_z 0 -set g_balance_mortar_primary_spread 0 -set g_balance_mortar_primary_type 0 -set g_balance_mortar_reload_ammo 0 -set g_balance_mortar_reload_time 2 -set g_balance_mortar_secondary_ammo 2 -set g_balance_mortar_secondary_animtime 0.3 -set g_balance_mortar_secondary_damage 55 -set g_balance_mortar_secondary_damageforcescale 4 -set g_balance_mortar_secondary_edgedamage 30 -set g_balance_mortar_secondary_force 250 -set g_balance_mortar_secondary_health 30 -set g_balance_mortar_secondary_lifetime 5 -set g_balance_mortar_secondary_lifetime_bounce 0.5 -set g_balance_mortar_secondary_lifetime_stick 0 -set g_balance_mortar_secondary_radius 120 -set g_balance_mortar_secondary_refire 0.7 -set g_balance_mortar_secondary_remote_detonateprimary 0 -set g_balance_mortar_secondary_speed 1400 -set g_balance_mortar_secondary_speed_up 150 -set g_balance_mortar_secondary_speed_z 0 -set g_balance_mortar_secondary_spread 0 -set g_balance_mortar_secondary_type 1 -set g_balance_mortar_switchdelay_drop 0.2 -set g_balance_mortar_switchdelay_raise 0.2 -set g_balance_mortar_weaponreplace "" -set g_balance_mortar_weaponstart 0 -set g_balance_mortar_weaponstartoverride -1 -set g_balance_mortar_weaponthrowable 1 -// }}} -// {{{ #5: Mine Layer (MUTATOR WEAPON) -set g_balance_minelayer_ammo 4 -set g_balance_minelayer_animtime 0.4 -set g_balance_minelayer_damage 40 -set g_balance_minelayer_damageforcescale 0 -set g_balance_minelayer_detonatedelay -1 -set g_balance_minelayer_edgedamage 20 -set g_balance_minelayer_force 250 -set g_balance_minelayer_health 15 -set g_balance_minelayer_lifetime 10 -set g_balance_minelayer_lifetime_countdown 0.5 -set g_balance_minelayer_limit 3 -set g_balance_minelayer_protection 0 -set g_balance_minelayer_proximityradius 150 -set g_balance_minelayer_radius 175 -set g_balance_minelayer_refire 1.5 -set g_balance_minelayer_reload_ammo 0 -set g_balance_minelayer_reload_time 2 -set g_balance_minelayer_remote_damage 45 -set g_balance_minelayer_remote_edgedamage 40 -set g_balance_minelayer_remote_force 300 -set g_balance_minelayer_remote_radius 200 -set g_balance_minelayer_speed 1000 -set g_balance_minelayer_switchdelay_drop 0.2 -set g_balance_minelayer_switchdelay_raise 0.2 -set g_balance_minelayer_time 0.5 -set g_balance_minelayer_weaponreplace "" -set g_balance_minelayer_weaponstart 0 -set g_balance_minelayer_weaponstartoverride -1 -set g_balance_minelayer_weaponthrowable 1 -// }}} -// {{{ #6: Electro -set g_balance_electro_combo_comboradius 250 -set g_balance_electro_combo_comboradius_thruwall 200 -set g_balance_electro_combo_damage 50 -set g_balance_electro_combo_edgedamage 25 -set g_balance_electro_combo_force 120 -set g_balance_electro_combo_radius 100 -set g_balance_electro_combo_safeammocheck 1 -set g_balance_electro_combo_speed 2000 -set g_balance_electro_primary_ammo 4 -set g_balance_electro_primary_animtime 0.3 -set g_balance_electro_primary_comboradius 300 -set g_balance_electro_primary_damage 40 -set g_balance_electro_primary_edgedamage 20 -set g_balance_electro_primary_force 200 -set g_balance_electro_primary_lifetime 5 -set g_balance_electro_primary_midaircombo_explode 1 -set g_balance_electro_primary_midaircombo_interval 0.1 -set g_balance_electro_primary_midaircombo_radius 100 -set g_balance_electro_primary_radius 100 -set g_balance_electro_primary_refire 0.6 -set g_balance_electro_primary_speed 2500 -set g_balance_electro_primary_spread 0 -set g_balance_electro_reload_ammo 0 -set g_balance_electro_reload_time 2 -set g_balance_electro_secondary_ammo 2 -set g_balance_electro_secondary_animtime 0.2 -set g_balance_electro_secondary_bouncefactor 0.3 -set g_balance_electro_secondary_bouncestop 0.05 -set g_balance_electro_secondary_count 3 -set g_balance_electro_secondary_damage 40 -set g_balance_electro_secondary_damagedbycontents 1 -set g_balance_electro_secondary_damageforcescale 4 -set g_balance_electro_secondary_edgedamage 20 -set g_balance_electro_secondary_force 50 -set g_balance_electro_secondary_health 5 -set g_balance_electro_secondary_lifetime 4 -set g_balance_electro_secondary_radius 150 -set g_balance_electro_secondary_refire 0.2 -set g_balance_electro_secondary_refire2 1.6 -set g_balance_electro_secondary_speed 1000 -set g_balance_electro_secondary_speed_up 200 -set g_balance_electro_secondary_speed_z 0 -set g_balance_electro_secondary_spread 0.04 -set g_balance_electro_secondary_touchexplode 0 -set g_balance_electro_switchdelay_drop 0.2 -set g_balance_electro_switchdelay_raise 0.2 -set g_balance_electro_weaponreplace "" -set g_balance_electro_weaponstart 0 -set g_balance_electro_weaponstartoverride -1 -set g_balance_electro_weaponthrowable 1 -// }}} -// {{{ #7: Crylink -set g_balance_crylink_primary_ammo 3 -set g_balance_crylink_primary_animtime 0.3 -set g_balance_crylink_primary_bouncedamagefactor 0.5 -set g_balance_crylink_primary_bounces 1 -set g_balance_crylink_primary_damage 12 -set g_balance_crylink_primary_edgedamage 6 -set g_balance_crylink_primary_force -60 -set g_balance_crylink_primary_joindelay 0.1 -set g_balance_crylink_primary_joinexplode 1 -set g_balance_crylink_primary_joinexplode_damage 0 -set g_balance_crylink_primary_joinexplode_edgedamage 0 -set g_balance_crylink_primary_joinexplode_force 0 -set g_balance_crylink_primary_joinexplode_radius 0 -set g_balance_crylink_primary_joinspread 0.2 -set g_balance_crylink_primary_linkexplode 1 -set g_balance_crylink_primary_middle_fadetime 5 -set g_balance_crylink_primary_middle_lifetime 5 -set g_balance_crylink_primary_other_fadetime 5 -set g_balance_crylink_primary_other_lifetime 5 -set g_balance_crylink_primary_radius 80 -set g_balance_crylink_primary_refire 0.7 -set g_balance_crylink_primary_shots 6 -set g_balance_crylink_primary_speed 2000 -set g_balance_crylink_primary_spread 0.08 -set g_balance_crylink_reload_ammo 0 -set g_balance_crylink_reload_time 2 -set g_balance_crylink_secondary 1 -set g_balance_crylink_secondary_ammo 2 -set g_balance_crylink_secondary_animtime 0.2 -set g_balance_crylink_secondary_bouncedamagefactor 0.5 -set g_balance_crylink_secondary_bounces 1 -set g_balance_crylink_secondary_damage 5 -set g_balance_crylink_secondary_edgedamage 0 -set g_balance_crylink_secondary_force -40 -set g_balance_crylink_secondary_joindelay 0 -set g_balance_crylink_secondary_joinexplode 0 -set g_balance_crylink_secondary_joinexplode_damage 0 -set g_balance_crylink_secondary_joinexplode_edgedamage 0 -set g_balance_crylink_secondary_joinexplode_force 0 -set g_balance_crylink_secondary_joinexplode_radius 0 -set g_balance_crylink_secondary_joinspread 0 -set g_balance_crylink_secondary_linkexplode 1 -set g_balance_crylink_secondary_middle_fadetime 5 -set g_balance_crylink_secondary_middle_lifetime 5 -set g_balance_crylink_secondary_other_fadetime 5 -set g_balance_crylink_secondary_other_lifetime 5 -set g_balance_crylink_secondary_radius 70 -set g_balance_crylink_secondary_refire 0.2 -set g_balance_crylink_secondary_shots 3 -set g_balance_crylink_secondary_speed 2000 -set g_balance_crylink_secondary_spread 0.02 -set g_balance_crylink_secondary_spreadtype 1 -set g_balance_crylink_switchdelay_drop 0.2 -set g_balance_crylink_switchdelay_raise 0.2 -set g_balance_crylink_weaponreplace "" -set g_balance_crylink_weaponstart 0 -set g_balance_crylink_weaponstartoverride -1 -set g_balance_crylink_weaponthrowable 1 -// }}} -// {{{ #8: Vortex -set g_balance_vortex_charge 1 -set g_balance_vortex_charge_animlimit 0.5 -set g_balance_vortex_charge_limit 1 -set g_balance_vortex_charge_maxspeed 800 -set g_balance_vortex_charge_mindmg 40 -set g_balance_vortex_charge_minspeed 400 -set g_balance_vortex_charge_rate 0.4 -set g_balance_vortex_charge_rot_pause 0 -set g_balance_vortex_charge_rot_rate 0 -set g_balance_vortex_charge_shot_multiplier 0 -set g_balance_vortex_charge_start 0.5 -set g_balance_vortex_charge_velocity_rate 0 -set g_balance_vortex_primary_ammo 6 -set g_balance_vortex_primary_animtime 0.4 -set g_balance_vortex_primary_damage 90 -set g_balance_vortex_primary_damagefalloff_forcehalflife 0 -set g_balance_vortex_primary_damagefalloff_halflife 0 -set g_balance_vortex_primary_damagefalloff_maxdist 0 -set g_balance_vortex_primary_damagefalloff_mindist 0 -set g_balance_vortex_primary_force 400 -set g_balance_vortex_primary_refire 1.5 -set g_balance_vortex_reload_ammo 0 -set g_balance_vortex_reload_time 2 -set g_balance_vortex_secondary 0 -set g_balance_vortex_secondary_ammo 2 -set g_balance_vortex_secondary_animtime 0 -set g_balance_vortex_secondary_chargepool 0 -set g_balance_vortex_secondary_chargepool_pause_regen 1 -set g_balance_vortex_secondary_chargepool_regen 0.15 -set g_balance_vortex_secondary_damage 0 -set g_balance_vortex_secondary_damagefalloff_forcehalflife 0 -set g_balance_vortex_secondary_damagefalloff_halflife 0 -set g_balance_vortex_secondary_damagefalloff_maxdist 0 -set g_balance_vortex_secondary_damagefalloff_mindist 0 -set g_balance_vortex_secondary_force 0 -set g_balance_vortex_secondary_refire 0 -set g_balance_vortex_switchdelay_drop 0.25 -set g_balance_vortex_switchdelay_raise 0.25 -set g_balance_vortex_weaponreplace "" -set g_balance_vortex_weaponstart 0 -set g_balance_vortex_weaponstartoverride -1 -set g_balance_vortex_weaponthrowable 1 -// }}} -// {{{ #9: Hagar -set g_balance_hagar_primary_ammo 1 -set g_balance_hagar_primary_damage 25 -set g_balance_hagar_primary_damageforcescale 0 -set g_balance_hagar_primary_edgedamage 12.5 -set g_balance_hagar_primary_force 100 -set g_balance_hagar_primary_health 15 -set g_balance_hagar_primary_lifetime 5 -set g_balance_hagar_primary_radius 65 -set g_balance_hagar_primary_refire 0.16667 -set g_balance_hagar_primary_speed 2200 -set g_balance_hagar_primary_spread 0.03 -set g_balance_hagar_reload_ammo 0 -set g_balance_hagar_reload_time 2 -set g_balance_hagar_secondary 1 -set g_balance_hagar_secondary_ammo 1 -set g_balance_hagar_secondary_damage 40 -set g_balance_hagar_secondary_damageforcescale 0 -set g_balance_hagar_secondary_edgedamage 20 -set g_balance_hagar_secondary_force 75 -set g_balance_hagar_secondary_health 15 -set g_balance_hagar_secondary_lifetime_min 10 -set g_balance_hagar_secondary_lifetime_rand 0 -set g_balance_hagar_secondary_load 1 -set g_balance_hagar_secondary_load_abort 1 -set g_balance_hagar_secondary_load_animtime 0.2 -set g_balance_hagar_secondary_load_hold 4 -set g_balance_hagar_secondary_load_linkexplode 0 -set g_balance_hagar_secondary_load_max 4 -set g_balance_hagar_secondary_load_releasedeath 0 -set g_balance_hagar_secondary_load_speed 0.5 -set g_balance_hagar_secondary_load_spread 0.075 -set g_balance_hagar_secondary_load_spread_bias 0.5 -set g_balance_hagar_secondary_radius 80 -set g_balance_hagar_secondary_refire 0.5 -set g_balance_hagar_secondary_speed 2000 -set g_balance_hagar_secondary_spread 0.05 -set g_balance_hagar_switchdelay_drop 0.2 -set g_balance_hagar_switchdelay_raise 0.2 -set g_balance_hagar_weaponreplace "" -set g_balance_hagar_weaponstart 0 -set g_balance_hagar_weaponstartoverride -1 -set g_balance_hagar_weaponthrowable 1 -// }}} -// {{{ #10: Devastator -set g_balance_devastator_ammo 4 -set g_balance_devastator_animtime 0.4 -set g_balance_devastator_damage 80 -set g_balance_devastator_damageforcescale 1 -set g_balance_devastator_detonatedelay 0.02 -set g_balance_devastator_edgedamage 40 -set g_balance_devastator_force 400 -set g_balance_devastator_guidedelay 0.2 -set g_balance_devastator_guidegoal 512 -set g_balance_devastator_guiderate 90 -set g_balance_devastator_guideratedelay 0.01 -set g_balance_devastator_guidestop 0 -set g_balance_devastator_health 30 -set g_balance_devastator_lifetime 10 -set g_balance_devastator_radius 110 -set g_balance_devastator_refire 1.1 -set g_balance_devastator_reload_ammo 0 -set g_balance_devastator_reload_time 2 -set g_balance_devastator_remote_damage 70 -set g_balance_devastator_remote_edgedamage 35 -set g_balance_devastator_remote_force 400 -set g_balance_devastator_remote_jump_damage 70 -set g_balance_devastator_remote_jump_radius 0 -set g_balance_devastator_remote_jump_velocity_z_add 400 -set g_balance_devastator_remote_jump_velocity_z_max 1500 -set g_balance_devastator_remote_jump_velocity_z_min 400 -set g_balance_devastator_remote_radius 110 -set g_balance_devastator_speed 1300 -set g_balance_devastator_speedaccel 1300 -set g_balance_devastator_speedstart 1000 -set g_balance_devastator_switchdelay_drop 0.2 -set g_balance_devastator_switchdelay_raise 0.2 -set g_balance_devastator_weaponreplace "" -set g_balance_devastator_weaponstart 0 -set g_balance_devastator_weaponstartoverride -1 -set g_balance_devastator_weaponthrowable 1 -// }}} -// {{{ #11: Port-O-Launch -set g_balance_porto_primary_animtime 0.3 -set g_balance_porto_primary_lifetime 5 -set g_balance_porto_primary_refire 1.5 -set g_balance_porto_primary_speed 1000 -set g_balance_porto_secondary 1 -set g_balance_porto_secondary_animtime 0.3 -set g_balance_porto_secondary_lifetime 5 -set g_balance_porto_secondary_refire 1.5 -set g_balance_porto_secondary_speed 1000 -set g_balance_porto_switchdelay_drop 0.2 -set g_balance_porto_switchdelay_raise 0.2 -set g_balance_porto_weaponreplace "" -set g_balance_porto_weaponstart 0 -set g_balance_porto_weaponstartoverride -1 -set g_balance_porto_weaponthrowable 1 -// }}} -// {{{ #12: Vaporizer -set g_balance_vaporizer_primary_ammo 10 -set g_balance_vaporizer_primary_animtime 0.3 -set g_balance_vaporizer_primary_refire 1 -set g_balance_vaporizer_reload_ammo 0 -set g_balance_vaporizer_reload_time 0 -set g_balance_vaporizer_secondary_ammo 0 -set g_balance_vaporizer_secondary_animtime 0.2 -set g_balance_vaporizer_secondary_damage 25 -set g_balance_vaporizer_secondary_delay 0 -set g_balance_vaporizer_secondary_edgedamage 12.5 -set g_balance_vaporizer_secondary_force 400 -set g_balance_vaporizer_secondary_lifetime 5 -set g_balance_vaporizer_secondary_radius 70 -set g_balance_vaporizer_secondary_refire 0.7 -set g_balance_vaporizer_secondary_shotangle 0 -set g_balance_vaporizer_secondary_speed 6000 -set g_balance_vaporizer_secondary_spread 0 -set g_balance_vaporizer_switchdelay_drop 0.2 -set g_balance_vaporizer_switchdelay_raise 0.2 -set g_balance_vaporizer_weaponreplace "" -set g_balance_vaporizer_weaponstart 0 -set g_balance_vaporizer_weaponstartoverride -1 -set g_balance_vaporizer_weaponthrowable 0 -// }}} -// {{{ #13: Grappling Hook -set g_balance_hook_primary_ammo 5 -set g_balance_hook_primary_animtime 0.3 -set g_balance_hook_primary_hooked_ammo 5 -set g_balance_hook_primary_hooked_time_free 2 -set g_balance_hook_primary_hooked_time_max 0 -set g_balance_hook_primary_refire 0.2 -set g_balance_hook_secondary_animtime 0.3 -set g_balance_hook_secondary_damage 25 -set g_balance_hook_secondary_damageforcescale 0 -set g_balance_hook_secondary_duration 1.5 -set g_balance_hook_secondary_edgedamage 5 -set g_balance_hook_secondary_force -2000 -set g_balance_hook_secondary_gravity 5 -set g_balance_hook_secondary_health 15 -set g_balance_hook_secondary_lifetime 5 -set g_balance_hook_secondary_power 3 -set g_balance_hook_secondary_radius 500 -set g_balance_hook_secondary_refire 3 -set g_balance_hook_secondary_speed 0 -set g_balance_hook_switchdelay_drop 0.2 -set g_balance_hook_switchdelay_raise 0.2 -set g_balance_hook_weaponreplace "" -set g_balance_hook_weaponstart 0 -set g_balance_hook_weaponstartoverride -1 -set g_balance_hook_weaponthrowable 1 -// }}} -// {{{ #14: Heavy Laser Assault Cannon (MUTATOR WEAPON) -set g_balance_hlac_primary_ammo 1 -set g_balance_hlac_primary_animtime 0.4 -set g_balance_hlac_primary_damage 18 -set g_balance_hlac_primary_edgedamage 9 -set g_balance_hlac_primary_force 90 -set g_balance_hlac_primary_lifetime 5 -set g_balance_hlac_primary_radius 70 -set g_balance_hlac_primary_refire 0.15 -set g_balance_hlac_primary_speed 9000 -set g_balance_hlac_primary_spread_add 0.0045 -set g_balance_hlac_primary_spread_crouchmod 0.25 -set g_balance_hlac_primary_spread_max 0.25 -set g_balance_hlac_primary_spread_min 0.01 -set g_balance_hlac_reload_ammo 0 -set g_balance_hlac_reload_time 2 -set g_balance_hlac_secondary 1 -set g_balance_hlac_secondary_ammo 10 -set g_balance_hlac_secondary_animtime 0.3 -set g_balance_hlac_secondary_damage 15 -set g_balance_hlac_secondary_edgedamage 7.5 -set g_balance_hlac_secondary_force 90 -set g_balance_hlac_secondary_lifetime 5 -set g_balance_hlac_secondary_radius 70 -set g_balance_hlac_secondary_refire 1 -set g_balance_hlac_secondary_shots 6 -set g_balance_hlac_secondary_speed 9000 -set g_balance_hlac_secondary_spread 0.15 -set g_balance_hlac_secondary_spread_crouchmod 0.5 -set g_balance_hlac_switchdelay_drop 0.2 -set g_balance_hlac_switchdelay_raise 0.2 -set g_balance_hlac_weaponreplace "" -set g_balance_hlac_weaponstart 0 -set g_balance_hlac_weaponstartoverride -1 -set g_balance_hlac_weaponthrowable 1 -// }}} -// {{{ #15: @!#%'n Tuba -set g_balance_tuba_animtime 0.05 -set g_balance_tuba_attenuation 0.5 -set g_balance_tuba_damage 5 -set g_balance_tuba_edgedamage 0 -set g_balance_tuba_force 40 -set g_balance_tuba_radius 200 -set g_balance_tuba_refire 0.05 -set g_balance_tuba_switchdelay_drop 0.2 -set g_balance_tuba_switchdelay_raise 0.2 -set g_balance_tuba_weaponreplace "" -set g_balance_tuba_weaponstart 0 -set g_balance_tuba_weaponstartoverride -1 -set g_balance_tuba_weaponthrowable 1 -// }}} -// {{{ #16: Rifle (MUTATOR WEAPON) -set g_balance_rifle_bursttime 0 -set g_balance_rifle_primary_ammo 10 -set g_balance_rifle_primary_animtime 0.4 -set g_balance_rifle_primary_bullethail 0 -set g_balance_rifle_primary_burstcost 0 -set g_balance_rifle_primary_damage 80 -set g_balance_rifle_primary_force 100 -set g_balance_rifle_primary_refire 1.2 -set g_balance_rifle_primary_shots 1 -set g_balance_rifle_primary_solidpenetration 62.2 -set g_balance_rifle_primary_spread 0 -set g_balance_rifle_primary_tracer 1 -set g_balance_rifle_reload_ammo 80 -set g_balance_rifle_reload_time 2 -set g_balance_rifle_secondary 1 -set g_balance_rifle_secondary_ammo 10 -set g_balance_rifle_secondary_animtime 0.3 -set g_balance_rifle_secondary_bullethail 0 -set g_balance_rifle_secondary_burstcost 0 -set g_balance_rifle_secondary_damage 20 -set g_balance_rifle_secondary_force 50 -set g_balance_rifle_secondary_refire 0.9 -set g_balance_rifle_secondary_reload 0 -set g_balance_rifle_secondary_shots 4 -set g_balance_rifle_secondary_solidpenetration 15.5 -set g_balance_rifle_secondary_spread 0.04 -set g_balance_rifle_secondary_tracer 0 -set g_balance_rifle_switchdelay_drop 0.2 -set g_balance_rifle_switchdelay_raise 0.2 -set g_balance_rifle_weaponreplace "" -set g_balance_rifle_weaponstart 0 -set g_balance_rifle_weaponstartoverride -1 -set g_balance_rifle_weaponthrowable 1 -// }}} -// {{{ #17: Fireball -set g_balance_fireball_primary_animtime 0.4 -set g_balance_fireball_primary_bfgdamage 100 -set g_balance_fireball_primary_bfgforce 0 -set g_balance_fireball_primary_bfgradius 1000 -set g_balance_fireball_primary_damage 200 -set g_balance_fireball_primary_damageforcescale 0 -set g_balance_fireball_primary_edgedamage 50 -set g_balance_fireball_primary_force 600 -set g_balance_fireball_primary_health 0 -set g_balance_fireball_primary_laserburntime 0.5 -set g_balance_fireball_primary_laserdamage 80 -set g_balance_fireball_primary_laseredgedamage 20 -set g_balance_fireball_primary_laserradius 256 -set g_balance_fireball_primary_lifetime 15 -set g_balance_fireball_primary_radius 200 -set g_balance_fireball_primary_refire 2 -set g_balance_fireball_primary_refire2 0 -set g_balance_fireball_primary_speed 1200 -set g_balance_fireball_primary_spread 0 -set g_balance_fireball_secondary_animtime 0.3 -set g_balance_fireball_secondary_damage 40 -set g_balance_fireball_secondary_damageforcescale 4 -set g_balance_fireball_secondary_damagetime 5 -set g_balance_fireball_secondary_laserburntime 0.5 -set g_balance_fireball_secondary_laserdamage 50 -set g_balance_fireball_secondary_laseredgedamage 20 -set g_balance_fireball_secondary_laserradius 110 -set g_balance_fireball_secondary_lifetime 7 -set g_balance_fireball_secondary_refire 1.5 -set g_balance_fireball_secondary_speed 900 -set g_balance_fireball_secondary_speed_up 100 -set g_balance_fireball_secondary_speed_z 0 -set g_balance_fireball_secondary_spread 0 -set g_balance_fireball_switchdelay_drop 0.2 -set g_balance_fireball_switchdelay_raise 0.2 -set g_balance_fireball_weaponreplace "" -set g_balance_fireball_weaponstart 0 -set g_balance_fireball_weaponstartoverride -1 -set g_balance_fireball_weaponthrowable 0 -// }}} -// {{{ #18: T.A.G. Seeker (MUTATOR WEAPON) -set g_balance_seeker_flac_ammo 1 -set g_balance_seeker_flac_animtime 0.1 -set g_balance_seeker_flac_damage 15 -set g_balance_seeker_flac_edgedamage 10 -set g_balance_seeker_flac_force 50 -set g_balance_seeker_flac_lifetime 0.1 -set g_balance_seeker_flac_lifetime_rand 0.05 -set g_balance_seeker_flac_radius 100 -set g_balance_seeker_flac_refire 0.1 -set g_balance_seeker_flac_speed 3000 -set g_balance_seeker_flac_speed_up 1000 -set g_balance_seeker_flac_speed_z 0 -set g_balance_seeker_flac_spread 0.4 -set g_balance_seeker_missile_accel 1400 -set g_balance_seeker_missile_ammo 2 -set g_balance_seeker_missile_animtime 0.2 -set g_balance_seeker_missile_count 3 -set g_balance_seeker_missile_damage 30 -set g_balance_seeker_missile_damageforcescale 4 -set g_balance_seeker_missile_decel 1400 -set g_balance_seeker_missile_delay 0.25 -set g_balance_seeker_missile_edgedamage 10 -set g_balance_seeker_missile_force 150 -set g_balance_seeker_missile_health 5 -set g_balance_seeker_missile_lifetime 15 -set g_balance_seeker_missile_proxy 0 -set g_balance_seeker_missile_proxy_delay 0.2 -set g_balance_seeker_missile_proxy_maxrange 45 -set g_balance_seeker_missile_radius 80 -set g_balance_seeker_missile_refire 0.5 -set g_balance_seeker_missile_smart 1 -set g_balance_seeker_missile_smart_mindist 800 -set g_balance_seeker_missile_smart_trace_max 2500 -set g_balance_seeker_missile_smart_trace_min 1000 -set g_balance_seeker_missile_speed 700 -set g_balance_seeker_missile_speed_max 1300 -set g_balance_seeker_missile_speed_up 300 -set g_balance_seeker_missile_speed_z 0 -set g_balance_seeker_missile_spread 0 -set g_balance_seeker_missile_turnrate 0.65 -set g_balance_seeker_reload_ammo 0 -set g_balance_seeker_reload_time 2 -set g_balance_seeker_switchdelay_drop 0.2 -set g_balance_seeker_switchdelay_raise 0.2 -set g_balance_seeker_tag_ammo 1 -set g_balance_seeker_tag_animtime 0.2 -set g_balance_seeker_tag_damageforcescale 4 -set g_balance_seeker_tag_health 5 -set g_balance_seeker_tag_lifetime 15 -set g_balance_seeker_tag_refire 0.75 -set g_balance_seeker_tag_speed 5000 -set g_balance_seeker_tag_spread 0 -set g_balance_seeker_tag_tracker_lifetime 10 -set g_balance_seeker_type 0 -set g_balance_seeker_weaponreplace "" -set g_balance_seeker_weaponstart 0 -set g_balance_seeker_weaponstartoverride -1 -set g_balance_seeker_weaponthrowable 1 -// }}} -// {{{ #19: Shockwave (MUTATOR WEAPON) -set g_balance_shockwave_blast_animtime 0.3 -set g_balance_shockwave_blast_damage 20 -set g_balance_shockwave_blast_distance 1000 -set g_balance_shockwave_blast_edgedamage 0 -set g_balance_shockwave_blast_force 200 -set g_balance_shockwave_blast_force_forwardbias 50 -set g_balance_shockwave_blast_force_zscale 2 -set g_balance_shockwave_blast_jump_damage 20 -set g_balance_shockwave_blast_jump_edgedamage 0 -set g_balance_shockwave_blast_jump_force 300 -set g_balance_shockwave_blast_jump_force_velocitybias 0 -set g_balance_shockwave_blast_jump_force_zscale 1.25 -set g_balance_shockwave_blast_jump_multiplier_accuracy 0.5 -set g_balance_shockwave_blast_jump_multiplier_distance 0.5 -set g_balance_shockwave_blast_jump_multiplier_min 0 -set g_balance_shockwave_blast_jump_radius 150 -set g_balance_shockwave_blast_multiplier_accuracy 0.5 -set g_balance_shockwave_blast_multiplier_distance 0.5 -set g_balance_shockwave_blast_multiplier_min 0 -set g_balance_shockwave_blast_refire 0.75 -set g_balance_shockwave_blast_splash_damage 15 -set g_balance_shockwave_blast_splash_edgedamage 0 -set g_balance_shockwave_blast_splash_force 100 -set g_balance_shockwave_blast_splash_force_forwardbias 50 -set g_balance_shockwave_blast_splash_multiplier_accuracy 0.5 -set g_balance_shockwave_blast_splash_multiplier_distance 0.5 -set g_balance_shockwave_blast_splash_multiplier_min 0 -set g_balance_shockwave_blast_splash_radius 70 -set g_balance_shockwave_blast_spread_max 120 -set g_balance_shockwave_blast_spread_min 25 -set g_balance_shockwave_melee_animtime 1.3 -set g_balance_shockwave_melee_damage 80 -set g_balance_shockwave_melee_delay 0.25 -set g_balance_shockwave_melee_force 200 -set g_balance_shockwave_melee_multihit 1 -set g_balance_shockwave_melee_no_doubleslap 1 -set g_balance_shockwave_melee_nonplayerdamage 40 -set g_balance_shockwave_melee_range 120 -set g_balance_shockwave_melee_refire 1.25 -set g_balance_shockwave_melee_swing_side 120 -set g_balance_shockwave_melee_swing_up 30 -set g_balance_shockwave_melee_time 0.15 -set g_balance_shockwave_melee_traces 10 -set g_balance_shockwave_switchdelay_drop 0.2 -set g_balance_shockwave_switchdelay_raise 0.2 -set g_balance_shockwave_weaponreplace "" -set g_balance_shockwave_weaponstart 1 -set g_balance_shockwave_weaponstartoverride -1 -set g_balance_shockwave_weaponthrowable 0 -// }}} -// {{{ #20: Arc -set g_balance_arc_beam_ammo 4 -set g_balance_arc_beam_animtime 0.2 -set g_balance_arc_beam_botaimlifetime 0 -set g_balance_arc_beam_botaimspeed 0 -set g_balance_arc_beam_damage 115 -set g_balance_arc_beam_degreespersegment 1 -set g_balance_arc_beam_distancepersegment 0 -set g_balance_arc_beam_falloff_halflifedist 0 -set g_balance_arc_beam_falloff_maxdist 0 -set g_balance_arc_beam_falloff_mindist 0 -set g_balance_arc_beam_force 900 -set g_balance_arc_beam_healing_amax 200 -set g_balance_arc_beam_healing_aps 50 -set g_balance_arc_beam_healing_hmax 200 -set g_balance_arc_beam_healing_hps 50 -set g_balance_arc_beam_maxangle 10 -set g_balance_arc_beam_nonplayerdamage 80 -set g_balance_arc_beam_range 1000 -set g_balance_arc_beam_refire 0.5 -set g_balance_arc_beam_returnspeed 8 -set g_balance_arc_beam_tightness 0.5 -set g_balance_arc_burst_ammo 15 -set g_balance_arc_burst_damage 500 -set g_balance_arc_burst_healing_aps 100 -set g_balance_arc_burst_healing_hps 100 -set g_balance_arc_switchdelay_drop 0.3 -set g_balance_arc_switchdelay_raise 0.3 -set g_balance_arc_weaponreplace "" -set g_balance_arc_weaponstart 0 -set g_balance_arc_weaponstartoverride -1 -set g_balance_arc_weaponthrowable 1 -// }}} diff --git a/bal-wep-xonotic.cfg b/bal-wep-xonotic.cfg deleted file mode 100644 index 867e9932d..000000000 --- a/bal-wep-xonotic.cfg +++ /dev/null @@ -1,753 +0,0 @@ -// {{{ #1: Blaster -set g_balance_blaster_primary_animtime 0.2 -set g_balance_blaster_primary_damage 25 -set g_balance_blaster_primary_delay 0 -set g_balance_blaster_primary_edgedamage 12.5 -set g_balance_blaster_primary_force 300 -set g_balance_blaster_primary_force_zscale 1.2 -set g_balance_blaster_primary_lifetime 5 -set g_balance_blaster_primary_radius 70 -set g_balance_blaster_primary_refire 0.7 -set g_balance_blaster_primary_shotangle 0 -set g_balance_blaster_primary_speed 6000 -set g_balance_blaster_primary_spread 0 -set g_balance_blaster_secondary 0 -set g_balance_blaster_secondary_animtime 0.2 -set g_balance_blaster_secondary_damage 25 -set g_balance_blaster_secondary_delay 0 -set g_balance_blaster_secondary_edgedamage 12.5 -set g_balance_blaster_secondary_force 300 -set g_balance_blaster_secondary_force_zscale 1.2 -set g_balance_blaster_secondary_lifetime 5 -set g_balance_blaster_secondary_radius 70 -set g_balance_blaster_secondary_refire 0.7 -set g_balance_blaster_secondary_shotangle 0 -set g_balance_blaster_secondary_speed 6000 -set g_balance_blaster_secondary_spread 0 -set g_balance_blaster_switchdelay_drop 0.15 -set g_balance_blaster_switchdelay_raise 0.15 -set g_balance_blaster_weaponreplace "" -set g_balance_blaster_weaponstart 1 -set g_balance_blaster_weaponstartoverride -1 -set g_balance_blaster_weaponthrowable 0 -// }}} -// {{{ #2: Shotgun -set g_balance_shotgun_primary_ammo 1 -set g_balance_shotgun_primary_animtime 0.2 -set g_balance_shotgun_primary_bullets 14 -set g_balance_shotgun_primary_damage 4 -set g_balance_shotgun_primary_force 15 -set g_balance_shotgun_primary_refire 0.75 -set g_balance_shotgun_primary_solidpenetration 3.8 -set g_balance_shotgun_primary_spread 0.12 -set g_balance_shotgun_reload_ammo 0 -set g_balance_shotgun_reload_time 2 -set g_balance_shotgun_secondary 1 -set g_balance_shotgun_secondary_animtime 1 -set g_balance_shotgun_secondary_damage 80 -set g_balance_shotgun_secondary_force 200 -set g_balance_shotgun_secondary_melee_delay 0.25 -set g_balance_shotgun_secondary_melee_multihit 1 -set g_balance_shotgun_secondary_melee_no_doubleslap 1 -set g_balance_shotgun_secondary_melee_nonplayerdamage 40 -set g_balance_shotgun_secondary_melee_range 120 -set g_balance_shotgun_secondary_melee_swing_side 120 -set g_balance_shotgun_secondary_melee_swing_up 30 -set g_balance_shotgun_secondary_melee_time 0.15 -set g_balance_shotgun_secondary_melee_traces 10 -set g_balance_shotgun_secondary_refire 1.25 -set g_balance_shotgun_switchdelay_drop 0.2 -set g_balance_shotgun_switchdelay_raise 0.2 -set g_balance_shotgun_weaponreplace "" -set g_balance_shotgun_weaponstart 1 -set g_balance_shotgun_weaponstartoverride -1 -set g_balance_shotgun_weaponthrowable 1 -// }}} -// {{{ #3: Machine Gun -set g_balance_machinegun_burst 3 -set g_balance_machinegun_burst_ammo 3 -set g_balance_machinegun_burst_animtime 0.3 -set g_balance_machinegun_burst_refire 0.06 -set g_balance_machinegun_burst_refire2 0.45 -set g_balance_machinegun_burst_speed 0 -set g_balance_machinegun_first 1 -set g_balance_machinegun_first_ammo 1 -set g_balance_machinegun_first_damage 14 -set g_balance_machinegun_first_force 5 -set g_balance_machinegun_first_refire 0.125 -set g_balance_machinegun_first_spread 0.03 -set g_balance_machinegun_mode 1 -set g_balance_machinegun_reload_ammo 60 -set g_balance_machinegun_reload_time 2 -set g_balance_machinegun_solidpenetration 13.1 -set g_balance_machinegun_spread_add 0.012 -set g_balance_machinegun_spread_max 0.05 -set g_balance_machinegun_spread_min 0.02 -set g_balance_machinegun_sustained_ammo 1 -set g_balance_machinegun_sustained_damage 10 -set g_balance_machinegun_sustained_force 5 -set g_balance_machinegun_sustained_refire 0.1 -set g_balance_machinegun_sustained_spread 0.03 -set g_balance_machinegun_switchdelay_drop 0.2 -set g_balance_machinegun_switchdelay_raise 0.2 -set g_balance_machinegun_weaponreplace "arc machinegun" -set g_balance_machinegun_weaponstart 0 -set g_balance_machinegun_weaponstartoverride -1 -set g_balance_machinegun_weaponthrowable 1 -// }}} -// {{{ #4: Mortar -set g_balance_mortar_bouncefactor 0.5 -set g_balance_mortar_bouncestop 0.075 -set g_balance_mortar_primary_ammo 2 -set g_balance_mortar_primary_animtime 0.3 -set g_balance_mortar_primary_damage 50 -set g_balance_mortar_primary_damageforcescale 0 -set g_balance_mortar_primary_edgedamage 25 -set g_balance_mortar_primary_force 250 -set g_balance_mortar_primary_health 15 -set g_balance_mortar_primary_lifetime 5 -set g_balance_mortar_primary_lifetime_stick 0 -set g_balance_mortar_primary_radius 120 -set g_balance_mortar_primary_refire 0.8 -set g_balance_mortar_primary_remote_minbouncecnt 0 -set g_balance_mortar_primary_speed 1900 -set g_balance_mortar_primary_speed_up 225 -set g_balance_mortar_primary_speed_z 0 -set g_balance_mortar_primary_spread 0 -set g_balance_mortar_primary_type 0 -set g_balance_mortar_reload_ammo 0 -set g_balance_mortar_reload_time 2 -set g_balance_mortar_secondary_ammo 2 -set g_balance_mortar_secondary_animtime 0.3 -set g_balance_mortar_secondary_damage 60 -set g_balance_mortar_secondary_damageforcescale 4 -set g_balance_mortar_secondary_edgedamage 30 -set g_balance_mortar_secondary_force 250 -set g_balance_mortar_secondary_health 30 -set g_balance_mortar_secondary_lifetime 5 -set g_balance_mortar_secondary_lifetime_bounce 0.5 -set g_balance_mortar_secondary_lifetime_stick 0 -set g_balance_mortar_secondary_radius 120 -set g_balance_mortar_secondary_refire 0.7 -set g_balance_mortar_secondary_remote_detonateprimary 0 -set g_balance_mortar_secondary_speed 1400 -set g_balance_mortar_secondary_speed_up 150 -set g_balance_mortar_secondary_speed_z 0 -set g_balance_mortar_secondary_spread 0 -set g_balance_mortar_secondary_type 1 -set g_balance_mortar_switchdelay_drop 0.2 -set g_balance_mortar_switchdelay_raise 0.2 -set g_balance_mortar_weaponreplace "" -set g_balance_mortar_weaponstart 0 -set g_balance_mortar_weaponstartoverride -1 -set g_balance_mortar_weaponthrowable 1 -// }}} -// {{{ #5: Mine Layer (MUTATOR WEAPON) -set g_balance_minelayer_ammo 4 -set g_balance_minelayer_animtime 0.4 -set g_balance_minelayer_damage 40 -set g_balance_minelayer_damageforcescale 0 -set g_balance_minelayer_detonatedelay -1 -set g_balance_minelayer_edgedamage 20 -set g_balance_minelayer_force 250 -set g_balance_minelayer_health 15 -set g_balance_minelayer_lifetime 10 -set g_balance_minelayer_lifetime_countdown 0.5 -set g_balance_minelayer_limit 3 -set g_balance_minelayer_protection 0 -set g_balance_minelayer_proximityradius 150 -set g_balance_minelayer_radius 175 -set g_balance_minelayer_refire 1.5 -set g_balance_minelayer_reload_ammo 0 -set g_balance_minelayer_reload_time 2 -set g_balance_minelayer_remote_damage 45 -set g_balance_minelayer_remote_edgedamage 40 -set g_balance_minelayer_remote_force 300 -set g_balance_minelayer_remote_radius 200 -set g_balance_minelayer_speed 1000 -set g_balance_minelayer_switchdelay_drop 0.2 -set g_balance_minelayer_switchdelay_raise 0.2 -set g_balance_minelayer_time 0.5 -set g_balance_minelayer_weaponreplace "" -set g_balance_minelayer_weaponstart 0 -set g_balance_minelayer_weaponstartoverride -1 -set g_balance_minelayer_weaponthrowable 1 -// }}} -// {{{ #6: Electro -set g_balance_electro_combo_comboradius 300 -set g_balance_electro_combo_comboradius_thruwall 200 -set g_balance_electro_combo_damage 50 -set g_balance_electro_combo_edgedamage 25 -set g_balance_electro_combo_force 120 -set g_balance_electro_combo_radius 150 -set g_balance_electro_combo_safeammocheck 1 -set g_balance_electro_combo_speed 2000 -set g_balance_electro_primary_ammo 4 -set g_balance_electro_primary_animtime 0.3 -set g_balance_electro_primary_comboradius 300 -set g_balance_electro_primary_damage 40 -set g_balance_electro_primary_edgedamage 20 -set g_balance_electro_primary_force 200 -set g_balance_electro_primary_lifetime 5 -set g_balance_electro_primary_midaircombo_explode 1 -set g_balance_electro_primary_midaircombo_interval 0.1 -set g_balance_electro_primary_midaircombo_radius 100 -set g_balance_electro_primary_radius 100 -set g_balance_electro_primary_refire 0.6 -set g_balance_electro_primary_speed 2500 -set g_balance_electro_primary_spread 0 -set g_balance_electro_reload_ammo 0 -set g_balance_electro_reload_time 2 -set g_balance_electro_secondary_ammo 2 -set g_balance_electro_secondary_animtime 0.2 -set g_balance_electro_secondary_bouncefactor 0.3 -set g_balance_electro_secondary_bouncestop 0.05 -set g_balance_electro_secondary_count 3 -set g_balance_electro_secondary_damage 40 -set g_balance_electro_secondary_damagedbycontents 1 -set g_balance_electro_secondary_damageforcescale 4 -set g_balance_electro_secondary_edgedamage 20 -set g_balance_electro_secondary_force 50 -set g_balance_electro_secondary_health 5 -set g_balance_electro_secondary_lifetime 4 -set g_balance_electro_secondary_radius 150 -set g_balance_electro_secondary_refire 0.2 -set g_balance_electro_secondary_refire2 1.6 -set g_balance_electro_secondary_speed 1000 -set g_balance_electro_secondary_speed_up 200 -set g_balance_electro_secondary_speed_z 0 -set g_balance_electro_secondary_spread 0.04 -set g_balance_electro_secondary_touchexplode 0 -set g_balance_electro_switchdelay_drop 0.2 -set g_balance_electro_switchdelay_raise 0.2 -set g_balance_electro_weaponreplace "" -set g_balance_electro_weaponstart 0 -set g_balance_electro_weaponstartoverride -1 -set g_balance_electro_weaponthrowable 1 -// }}} -// {{{ #7: Crylink -set g_balance_crylink_primary_ammo 3 -set g_balance_crylink_primary_animtime 0.3 -set g_balance_crylink_primary_bouncedamagefactor 0.5 -set g_balance_crylink_primary_bounces 1 -set g_balance_crylink_primary_damage 12 -set g_balance_crylink_primary_edgedamage 6 -set g_balance_crylink_primary_force -50 -set g_balance_crylink_primary_joindelay 0.1 -set g_balance_crylink_primary_joinexplode 1 -set g_balance_crylink_primary_joinexplode_damage 0 -set g_balance_crylink_primary_joinexplode_edgedamage 0 -set g_balance_crylink_primary_joinexplode_force 0 -set g_balance_crylink_primary_joinexplode_radius 0 -set g_balance_crylink_primary_joinspread 0.2 -set g_balance_crylink_primary_linkexplode 1 -set g_balance_crylink_primary_middle_fadetime 5 -set g_balance_crylink_primary_middle_lifetime 5 -set g_balance_crylink_primary_other_fadetime 5 -set g_balance_crylink_primary_other_lifetime 5 -set g_balance_crylink_primary_radius 80 -set g_balance_crylink_primary_refire 0.7 -set g_balance_crylink_primary_shots 6 -set g_balance_crylink_primary_speed 2000 -set g_balance_crylink_primary_spread 0.08 -set g_balance_crylink_reload_ammo 0 -set g_balance_crylink_reload_time 2 -set g_balance_crylink_secondary 1 -set g_balance_crylink_secondary_ammo 2 -set g_balance_crylink_secondary_animtime 0.2 -set g_balance_crylink_secondary_bouncedamagefactor 0.5 -set g_balance_crylink_secondary_bounces 0 -set g_balance_crylink_secondary_damage 10 -set g_balance_crylink_secondary_edgedamage 5 -set g_balance_crylink_secondary_force -250 -set g_balance_crylink_secondary_joindelay 0 -set g_balance_crylink_secondary_joinexplode 0 -set g_balance_crylink_secondary_joinexplode_damage 0 -set g_balance_crylink_secondary_joinexplode_edgedamage 0 -set g_balance_crylink_secondary_joinexplode_force 0 -set g_balance_crylink_secondary_joinexplode_radius 0 -set g_balance_crylink_secondary_joinspread 0 -set g_balance_crylink_secondary_linkexplode 1 -set g_balance_crylink_secondary_middle_fadetime 5 -set g_balance_crylink_secondary_middle_lifetime 5 -set g_balance_crylink_secondary_other_fadetime 5 -set g_balance_crylink_secondary_other_lifetime 5 -set g_balance_crylink_secondary_radius 100 -set g_balance_crylink_secondary_refire 0.7 -set g_balance_crylink_secondary_shots 5 -set g_balance_crylink_secondary_speed 3000 -set g_balance_crylink_secondary_spread 0.01 -set g_balance_crylink_secondary_spreadtype 1 -set g_balance_crylink_switchdelay_drop 0.2 -set g_balance_crylink_switchdelay_raise 0.2 -set g_balance_crylink_weaponreplace "" -set g_balance_crylink_weaponstart 0 -set g_balance_crylink_weaponstartoverride -1 -set g_balance_crylink_weaponthrowable 1 -// }}} -// {{{ #8: Vortex -set g_balance_vortex_charge 1 -set g_balance_vortex_charge_animlimit 0.5 -set g_balance_vortex_charge_limit 1 -set g_balance_vortex_charge_maxspeed 800 -set g_balance_vortex_charge_mindmg 40 -set g_balance_vortex_charge_minspeed 400 -set g_balance_vortex_charge_rate 0.4 -set g_balance_vortex_charge_rot_pause 0 -set g_balance_vortex_charge_rot_rate 0 -set g_balance_vortex_charge_shot_multiplier 0 -set g_balance_vortex_charge_start 0.5 -set g_balance_vortex_charge_velocity_rate 0 -set g_balance_vortex_primary_ammo 6 -set g_balance_vortex_primary_animtime 0.6 -set g_balance_vortex_primary_damage 80 -set g_balance_vortex_primary_damagefalloff_forcehalflife 0 -set g_balance_vortex_primary_damagefalloff_halflife 0 -set g_balance_vortex_primary_damagefalloff_maxdist 0 -set g_balance_vortex_primary_damagefalloff_mindist 0 -set g_balance_vortex_primary_force 400 -set g_balance_vortex_primary_refire 1.5 -set g_balance_vortex_reload_ammo 0 -set g_balance_vortex_reload_time 2 -set g_balance_vortex_secondary 0 -set g_balance_vortex_secondary_ammo 2 -set g_balance_vortex_secondary_animtime 0 -set g_balance_vortex_secondary_chargepool 0 -set g_balance_vortex_secondary_chargepool_pause_regen 1 -set g_balance_vortex_secondary_chargepool_regen 0.15 -set g_balance_vortex_secondary_damage 0 -set g_balance_vortex_secondary_damagefalloff_forcehalflife 0 -set g_balance_vortex_secondary_damagefalloff_halflife 0 -set g_balance_vortex_secondary_damagefalloff_maxdist 0 -set g_balance_vortex_secondary_damagefalloff_mindist 0 -set g_balance_vortex_secondary_force 0 -set g_balance_vortex_secondary_refire 0 -set g_balance_vortex_switchdelay_drop 0.2 -set g_balance_vortex_switchdelay_raise 0.2 -set g_balance_vortex_weaponreplace "" -set g_balance_vortex_weaponstart 0 -set g_balance_vortex_weaponstartoverride -1 -set g_balance_vortex_weaponthrowable 1 -// }}} -// {{{ #9: Hagar -set g_balance_hagar_primary_ammo 1 -set g_balance_hagar_primary_damage 25 -set g_balance_hagar_primary_damageforcescale 0 -set g_balance_hagar_primary_edgedamage 12.5 -set g_balance_hagar_primary_force 100 -set g_balance_hagar_primary_health 15 -set g_balance_hagar_primary_lifetime 5 -set g_balance_hagar_primary_radius 65 -set g_balance_hagar_primary_refire 0.16667 -set g_balance_hagar_primary_speed 2500 -set g_balance_hagar_primary_spread 0.03 -set g_balance_hagar_reload_ammo 0 -set g_balance_hagar_reload_time 2 -set g_balance_hagar_secondary 1 -set g_balance_hagar_secondary_ammo 1 -set g_balance_hagar_secondary_damage 40 -set g_balance_hagar_secondary_damageforcescale 0 -set g_balance_hagar_secondary_edgedamage 20 -set g_balance_hagar_secondary_force 75 -set g_balance_hagar_secondary_health 15 -set g_balance_hagar_secondary_lifetime_min 10 -set g_balance_hagar_secondary_lifetime_rand 0 -set g_balance_hagar_secondary_load 1 -set g_balance_hagar_secondary_load_abort 0 -set g_balance_hagar_secondary_load_animtime 0.2 -set g_balance_hagar_secondary_load_hold 4 -set g_balance_hagar_secondary_load_linkexplode 0 -set g_balance_hagar_secondary_load_max 4 -set g_balance_hagar_secondary_load_releasedeath 0 -set g_balance_hagar_secondary_load_speed 0.5 -set g_balance_hagar_secondary_load_spread 0.075 -set g_balance_hagar_secondary_load_spread_bias 0.5 -set g_balance_hagar_secondary_radius 80 -set g_balance_hagar_secondary_refire 0.5 -set g_balance_hagar_secondary_speed 2500 -set g_balance_hagar_secondary_spread 0.05 -set g_balance_hagar_switchdelay_drop 0.2 -set g_balance_hagar_switchdelay_raise 0.2 -set g_balance_hagar_weaponreplace "" -set g_balance_hagar_weaponstart 0 -set g_balance_hagar_weaponstartoverride -1 -set g_balance_hagar_weaponthrowable 1 -// }}} -// {{{ #10: Devastator -set g_balance_devastator_ammo 4 -set g_balance_devastator_animtime 0.4 -set g_balance_devastator_damage 70 -set g_balance_devastator_damageforcescale 1 -set g_balance_devastator_detonatedelay 0.02 -set g_balance_devastator_edgedamage 35 -set g_balance_devastator_force 450 -set g_balance_devastator_guidedelay 0.2 -set g_balance_devastator_guidegoal 512 -set g_balance_devastator_guiderate 70 -set g_balance_devastator_guideratedelay 0.01 -set g_balance_devastator_guidestop 0 -set g_balance_devastator_health 30 -set g_balance_devastator_lifetime 10 -set g_balance_devastator_radius 110 -set g_balance_devastator_refire 1.2 -set g_balance_devastator_reload_ammo 0 -set g_balance_devastator_reload_time 2 -set g_balance_devastator_remote_damage 70 -set g_balance_devastator_remote_edgedamage 35 -set g_balance_devastator_remote_force 400 -set g_balance_devastator_remote_jump_damage 70 -set g_balance_devastator_remote_jump_radius 0 -set g_balance_devastator_remote_jump_velocity_z_add 400 -set g_balance_devastator_remote_jump_velocity_z_max 1500 -set g_balance_devastator_remote_jump_velocity_z_min 400 -set g_balance_devastator_remote_radius 110 -set g_balance_devastator_speed 1300 -set g_balance_devastator_speedaccel 1300 -set g_balance_devastator_speedstart 1000 -set g_balance_devastator_switchdelay_drop 0.2 -set g_balance_devastator_switchdelay_raise 0.2 -set g_balance_devastator_weaponreplace "" -set g_balance_devastator_weaponstart 0 -set g_balance_devastator_weaponstartoverride -1 -set g_balance_devastator_weaponthrowable 1 -// }}} -// {{{ #11: Port-O-Launch -set g_balance_porto_primary_animtime 0.3 -set g_balance_porto_primary_lifetime 5 -set g_balance_porto_primary_refire 1.5 -set g_balance_porto_primary_speed 1000 -set g_balance_porto_secondary 1 -set g_balance_porto_secondary_animtime 0.3 -set g_balance_porto_secondary_lifetime 5 -set g_balance_porto_secondary_refire 1.5 -set g_balance_porto_secondary_speed 1000 -set g_balance_porto_switchdelay_drop 0.2 -set g_balance_porto_switchdelay_raise 0.2 -set g_balance_porto_weaponreplace "" -set g_balance_porto_weaponstart 0 -set g_balance_porto_weaponstartoverride -1 -set g_balance_porto_weaponthrowable 1 -// }}} -// {{{ #12: Vaporizer -set g_balance_vaporizer_primary_ammo 10 -set g_balance_vaporizer_primary_animtime 0.3 -set g_balance_vaporizer_primary_refire 1 -set g_balance_vaporizer_reload_ammo 0 -set g_balance_vaporizer_reload_time 0 -set g_balance_vaporizer_secondary_ammo 0 -set g_balance_vaporizer_secondary_animtime 0.2 -set g_balance_vaporizer_secondary_damage 25 -set g_balance_vaporizer_secondary_delay 0 -set g_balance_vaporizer_secondary_edgedamage 12.5 -set g_balance_vaporizer_secondary_force 400 -set g_balance_vaporizer_secondary_lifetime 5 -set g_balance_vaporizer_secondary_radius 70 -set g_balance_vaporizer_secondary_refire 0.7 -set g_balance_vaporizer_secondary_shotangle 0 -set g_balance_vaporizer_secondary_speed 6000 -set g_balance_vaporizer_secondary_spread 0 -set g_balance_vaporizer_switchdelay_drop 0.2 -set g_balance_vaporizer_switchdelay_raise 0.2 -set g_balance_vaporizer_weaponreplace "" -set g_balance_vaporizer_weaponstart 0 -set g_balance_vaporizer_weaponstartoverride -1 -set g_balance_vaporizer_weaponthrowable 0 -// }}} -// {{{ #13: Grappling Hook -set g_balance_hook_primary_ammo 5 -set g_balance_hook_primary_animtime 0.3 -set g_balance_hook_primary_hooked_ammo 5 -set g_balance_hook_primary_hooked_time_free 2 -set g_balance_hook_primary_hooked_time_max 0 -set g_balance_hook_primary_refire 0.2 -set g_balance_hook_secondary_animtime 0.3 -set g_balance_hook_secondary_damage 25 -set g_balance_hook_secondary_damageforcescale 0 -set g_balance_hook_secondary_duration 1.5 -set g_balance_hook_secondary_edgedamage 5 -set g_balance_hook_secondary_force -2000 -set g_balance_hook_secondary_gravity 5 -set g_balance_hook_secondary_health 15 -set g_balance_hook_secondary_lifetime 5 -set g_balance_hook_secondary_power 3 -set g_balance_hook_secondary_radius 500 -set g_balance_hook_secondary_refire 3 -set g_balance_hook_secondary_speed 0 -set g_balance_hook_switchdelay_drop 0.2 -set g_balance_hook_switchdelay_raise 0.2 -set g_balance_hook_weaponreplace "" -set g_balance_hook_weaponstart 0 -set g_balance_hook_weaponstartoverride -1 -set g_balance_hook_weaponthrowable 1 -// }}} -// {{{ #14: Heavy Laser Assault Cannon (MUTATOR WEAPON) -set g_balance_hlac_primary_ammo 1 -set g_balance_hlac_primary_animtime 0.4 -set g_balance_hlac_primary_damage 18 -set g_balance_hlac_primary_edgedamage 9 -set g_balance_hlac_primary_force 90 -set g_balance_hlac_primary_lifetime 5 -set g_balance_hlac_primary_radius 70 -set g_balance_hlac_primary_refire 0.15 -set g_balance_hlac_primary_speed 9000 -set g_balance_hlac_primary_spread_add 0.0045 -set g_balance_hlac_primary_spread_crouchmod 0.25 -set g_balance_hlac_primary_spread_max 0.25 -set g_balance_hlac_primary_spread_min 0.01 -set g_balance_hlac_reload_ammo 0 -set g_balance_hlac_reload_time 2 -set g_balance_hlac_secondary 1 -set g_balance_hlac_secondary_ammo 10 -set g_balance_hlac_secondary_animtime 0.3 -set g_balance_hlac_secondary_damage 15 -set g_balance_hlac_secondary_edgedamage 7.5 -set g_balance_hlac_secondary_force 90 -set g_balance_hlac_secondary_lifetime 5 -set g_balance_hlac_secondary_radius 70 -set g_balance_hlac_secondary_refire 1 -set g_balance_hlac_secondary_shots 6 -set g_balance_hlac_secondary_speed 9000 -set g_balance_hlac_secondary_spread 0.15 -set g_balance_hlac_secondary_spread_crouchmod 0.5 -set g_balance_hlac_switchdelay_drop 0.2 -set g_balance_hlac_switchdelay_raise 0.2 -set g_balance_hlac_weaponreplace "" -set g_balance_hlac_weaponstart 0 -set g_balance_hlac_weaponstartoverride -1 -set g_balance_hlac_weaponthrowable 1 -// }}} -// {{{ #15: @!#%'n Tuba -set g_balance_tuba_animtime 0.05 -set g_balance_tuba_attenuation 0.5 -set g_balance_tuba_damage 5 -set g_balance_tuba_edgedamage 0 -set g_balance_tuba_force 40 -set g_balance_tuba_radius 200 -set g_balance_tuba_refire 0.05 -set g_balance_tuba_switchdelay_drop 0.2 -set g_balance_tuba_switchdelay_raise 0.2 -set g_balance_tuba_weaponreplace "" -set g_balance_tuba_weaponstart 0 -set g_balance_tuba_weaponstartoverride -1 -set g_balance_tuba_weaponthrowable 1 -// }}} -// {{{ #16: Rifle (MUTATOR WEAPON) -set g_balance_rifle_bursttime 0 -set g_balance_rifle_primary_ammo 10 -set g_balance_rifle_primary_animtime 0.4 -set g_balance_rifle_primary_bullethail 0 -set g_balance_rifle_primary_burstcost 0 -set g_balance_rifle_primary_damage 80 -set g_balance_rifle_primary_force 100 -set g_balance_rifle_primary_refire 1.2 -set g_balance_rifle_primary_shots 1 -set g_balance_rifle_primary_solidpenetration 62.2 -set g_balance_rifle_primary_spread 0 -set g_balance_rifle_primary_tracer 1 -set g_balance_rifle_reload_ammo 80 -set g_balance_rifle_reload_time 2 -set g_balance_rifle_secondary 1 -set g_balance_rifle_secondary_ammo 10 -set g_balance_rifle_secondary_animtime 0.3 -set g_balance_rifle_secondary_bullethail 0 -set g_balance_rifle_secondary_burstcost 0 -set g_balance_rifle_secondary_damage 20 -set g_balance_rifle_secondary_force 50 -set g_balance_rifle_secondary_refire 0.9 -set g_balance_rifle_secondary_reload 0 -set g_balance_rifle_secondary_shots 4 -set g_balance_rifle_secondary_solidpenetration 15.5 -set g_balance_rifle_secondary_spread 0.04 -set g_balance_rifle_secondary_tracer 0 -set g_balance_rifle_switchdelay_drop 0.2 -set g_balance_rifle_switchdelay_raise 0.2 -set g_balance_rifle_weaponreplace "" -set g_balance_rifle_weaponstart 0 -set g_balance_rifle_weaponstartoverride -1 -set g_balance_rifle_weaponthrowable 1 -// }}} -// {{{ #17: Fireball -set g_balance_fireball_primary_animtime 0.2 -set g_balance_fireball_primary_bfgdamage 100 -set g_balance_fireball_primary_bfgforce 0 -set g_balance_fireball_primary_bfgradius 1000 -set g_balance_fireball_primary_damage 200 -set g_balance_fireball_primary_damageforcescale 0 -set g_balance_fireball_primary_edgedamage 50 -set g_balance_fireball_primary_force 600 -set g_balance_fireball_primary_health 0 -set g_balance_fireball_primary_laserburntime 0.5 -set g_balance_fireball_primary_laserdamage 80 -set g_balance_fireball_primary_laseredgedamage 20 -set g_balance_fireball_primary_laserradius 256 -set g_balance_fireball_primary_lifetime 15 -set g_balance_fireball_primary_radius 200 -set g_balance_fireball_primary_refire 2 -set g_balance_fireball_primary_refire2 0 -set g_balance_fireball_primary_speed 1200 -set g_balance_fireball_primary_spread 0 -set g_balance_fireball_secondary_animtime 0.3 -set g_balance_fireball_secondary_damage 40 -set g_balance_fireball_secondary_damageforcescale 4 -set g_balance_fireball_secondary_damagetime 5 -set g_balance_fireball_secondary_laserburntime 0.5 -set g_balance_fireball_secondary_laserdamage 50 -set g_balance_fireball_secondary_laseredgedamage 20 -set g_balance_fireball_secondary_laserradius 110 -set g_balance_fireball_secondary_lifetime 7 -set g_balance_fireball_secondary_refire 1.5 -set g_balance_fireball_secondary_speed 900 -set g_balance_fireball_secondary_speed_up 100 -set g_balance_fireball_secondary_speed_z 0 -set g_balance_fireball_secondary_spread 0 -set g_balance_fireball_switchdelay_drop 0.2 -set g_balance_fireball_switchdelay_raise 0.2 -set g_balance_fireball_weaponreplace "" -set g_balance_fireball_weaponstart 0 -set g_balance_fireball_weaponstartoverride -1 -set g_balance_fireball_weaponthrowable 0 -// }}} -// {{{ #18: T.A.G. Seeker (MUTATOR WEAPON) -set g_balance_seeker_flac_ammo 1 -set g_balance_seeker_flac_animtime 0.1 -set g_balance_seeker_flac_damage 15 -set g_balance_seeker_flac_edgedamage 10 -set g_balance_seeker_flac_force 50 -set g_balance_seeker_flac_lifetime 0.1 -set g_balance_seeker_flac_lifetime_rand 0.05 -set g_balance_seeker_flac_radius 100 -set g_balance_seeker_flac_refire 0.1 -set g_balance_seeker_flac_speed 3000 -set g_balance_seeker_flac_speed_up 1000 -set g_balance_seeker_flac_speed_z 0 -set g_balance_seeker_flac_spread 0.4 -set g_balance_seeker_missile_accel 1400 -set g_balance_seeker_missile_ammo 2 -set g_balance_seeker_missile_animtime 0.2 -set g_balance_seeker_missile_count 3 -set g_balance_seeker_missile_damage 30 -set g_balance_seeker_missile_damageforcescale 4 -set g_balance_seeker_missile_decel 1400 -set g_balance_seeker_missile_delay 0.25 -set g_balance_seeker_missile_edgedamage 10 -set g_balance_seeker_missile_force 150 -set g_balance_seeker_missile_health 5 -set g_balance_seeker_missile_lifetime 15 -set g_balance_seeker_missile_proxy 0 -set g_balance_seeker_missile_proxy_delay 0.2 -set g_balance_seeker_missile_proxy_maxrange 45 -set g_balance_seeker_missile_radius 80 -set g_balance_seeker_missile_refire 0.5 -set g_balance_seeker_missile_smart 1 -set g_balance_seeker_missile_smart_mindist 800 -set g_balance_seeker_missile_smart_trace_max 2500 -set g_balance_seeker_missile_smart_trace_min 1000 -set g_balance_seeker_missile_speed 700 -set g_balance_seeker_missile_speed_max 1300 -set g_balance_seeker_missile_speed_up 300 -set g_balance_seeker_missile_speed_z 0 -set g_balance_seeker_missile_spread 0 -set g_balance_seeker_missile_turnrate 0.65 -set g_balance_seeker_reload_ammo 0 -set g_balance_seeker_reload_time 2 -set g_balance_seeker_switchdelay_drop 0.2 -set g_balance_seeker_switchdelay_raise 0.2 -set g_balance_seeker_tag_ammo 1 -set g_balance_seeker_tag_animtime 0.2 -set g_balance_seeker_tag_damageforcescale 4 -set g_balance_seeker_tag_health 5 -set g_balance_seeker_tag_lifetime 15 -set g_balance_seeker_tag_refire 0.75 -set g_balance_seeker_tag_speed 5000 -set g_balance_seeker_tag_spread 0 -set g_balance_seeker_tag_tracker_lifetime 10 -set g_balance_seeker_type 0 -set g_balance_seeker_weaponreplace "" -set g_balance_seeker_weaponstart 0 -set g_balance_seeker_weaponstartoverride -1 -set g_balance_seeker_weaponthrowable 1 -// }}} -// {{{ #19: Shockwave (MUTATOR WEAPON) -set g_balance_shockwave_blast_animtime 0.3 -set g_balance_shockwave_blast_damage 20 -set g_balance_shockwave_blast_distance 1000 -set g_balance_shockwave_blast_edgedamage 0 -set g_balance_shockwave_blast_force 200 -set g_balance_shockwave_blast_force_forwardbias 50 -set g_balance_shockwave_blast_force_zscale 2 -set g_balance_shockwave_blast_jump_damage 20 -set g_balance_shockwave_blast_jump_edgedamage 0 -set g_balance_shockwave_blast_jump_force 300 -set g_balance_shockwave_blast_jump_force_velocitybias 0 -set g_balance_shockwave_blast_jump_force_zscale 1.25 -set g_balance_shockwave_blast_jump_multiplier_accuracy 0.5 -set g_balance_shockwave_blast_jump_multiplier_distance 0.5 -set g_balance_shockwave_blast_jump_multiplier_min 0 -set g_balance_shockwave_blast_jump_radius 150 -set g_balance_shockwave_blast_multiplier_accuracy 0.5 -set g_balance_shockwave_blast_multiplier_distance 0.5 -set g_balance_shockwave_blast_multiplier_min 0 -set g_balance_shockwave_blast_refire 0.75 -set g_balance_shockwave_blast_splash_damage 15 -set g_balance_shockwave_blast_splash_edgedamage 0 -set g_balance_shockwave_blast_splash_force 100 -set g_balance_shockwave_blast_splash_force_forwardbias 50 -set g_balance_shockwave_blast_splash_multiplier_accuracy 0.5 -set g_balance_shockwave_blast_splash_multiplier_distance 0.5 -set g_balance_shockwave_blast_splash_multiplier_min 0 -set g_balance_shockwave_blast_splash_radius 70 -set g_balance_shockwave_blast_spread_max 120 -set g_balance_shockwave_blast_spread_min 25 -set g_balance_shockwave_melee_animtime 1.3 -set g_balance_shockwave_melee_damage 80 -set g_balance_shockwave_melee_delay 0.25 -set g_balance_shockwave_melee_force 200 -set g_balance_shockwave_melee_multihit 1 -set g_balance_shockwave_melee_no_doubleslap 1 -set g_balance_shockwave_melee_nonplayerdamage 40 -set g_balance_shockwave_melee_range 120 -set g_balance_shockwave_melee_refire 1.25 -set g_balance_shockwave_melee_swing_side 120 -set g_balance_shockwave_melee_swing_up 30 -set g_balance_shockwave_melee_time 0.15 -set g_balance_shockwave_melee_traces 10 -set g_balance_shockwave_switchdelay_drop 0.2 -set g_balance_shockwave_switchdelay_raise 0.2 -set g_balance_shockwave_weaponreplace "" -set g_balance_shockwave_weaponstart 1 -set g_balance_shockwave_weaponstartoverride -1 -set g_balance_shockwave_weaponthrowable 0 -// }}} -// {{{ #20: Arc -set g_balance_arc_beam_ammo 4 -set g_balance_arc_beam_animtime 0.2 -set g_balance_arc_beam_botaimlifetime 0 -set g_balance_arc_beam_botaimspeed 0 -set g_balance_arc_beam_damage 115 -set g_balance_arc_beam_degreespersegment 1 -set g_balance_arc_beam_distancepersegment 0 -set g_balance_arc_beam_falloff_halflifedist 0 -set g_balance_arc_beam_falloff_maxdist 0 -set g_balance_arc_beam_falloff_mindist 0 -set g_balance_arc_beam_force 900 -set g_balance_arc_beam_healing_amax 200 -set g_balance_arc_beam_healing_aps 50 -set g_balance_arc_beam_healing_hmax 200 -set g_balance_arc_beam_healing_hps 50 -set g_balance_arc_beam_maxangle 10 -set g_balance_arc_beam_nonplayerdamage 80 -set g_balance_arc_beam_range 1000 -set g_balance_arc_beam_refire 0.5 -set g_balance_arc_beam_returnspeed 8 -set g_balance_arc_beam_tightness 0.5 -set g_balance_arc_burst_ammo 15 -set g_balance_arc_burst_damage 500 -set g_balance_arc_burst_healing_aps 100 -set g_balance_arc_burst_healing_hps 100 -set g_balance_arc_switchdelay_drop 0.3 -set g_balance_arc_switchdelay_raise 0.3 -set g_balance_arc_weaponreplace "" -set g_balance_arc_weaponstart 0 -set g_balance_arc_weaponstartoverride -1 -set g_balance_arc_weaponthrowable 1 -// }}} diff --git a/bal-wep-xpm.cfg b/bal-wep-xpm.cfg deleted file mode 100644 index f0b222a6a..000000000 --- a/bal-wep-xpm.cfg +++ /dev/null @@ -1,753 +0,0 @@ -// {{{ #1: Blaster -set g_balance_blaster_primary_animtime 0.2 -set g_balance_blaster_primary_damage 25 -set g_balance_blaster_primary_delay 0 -set g_balance_blaster_primary_edgedamage 12.5 -set g_balance_blaster_primary_force 300 -set g_balance_blaster_primary_force_zscale 1.2 -set g_balance_blaster_primary_lifetime 5 -set g_balance_blaster_primary_radius 70 -set g_balance_blaster_primary_refire 0.7 -set g_balance_blaster_primary_shotangle 0 -set g_balance_blaster_primary_speed 6000 -set g_balance_blaster_primary_spread 0 -set g_balance_blaster_secondary 0 -set g_balance_blaster_secondary_animtime 0.2 -set g_balance_blaster_secondary_damage 25 -set g_balance_blaster_secondary_delay 0 -set g_balance_blaster_secondary_edgedamage 12.5 -set g_balance_blaster_secondary_force 300 -set g_balance_blaster_secondary_force_zscale 1.2 -set g_balance_blaster_secondary_lifetime 5 -set g_balance_blaster_secondary_radius 70 -set g_balance_blaster_secondary_refire 0.7 -set g_balance_blaster_secondary_shotangle 0 -set g_balance_blaster_secondary_speed 6000 -set g_balance_blaster_secondary_spread 0 -set g_balance_blaster_switchdelay_drop 0.15 -set g_balance_blaster_switchdelay_raise 0.15 -set g_balance_blaster_weaponreplace "" -set g_balance_blaster_weaponstart 1 -set g_balance_blaster_weaponstartoverride -1 -set g_balance_blaster_weaponthrowable 0 -// }}} -// {{{ #2: Shotgun -set g_balance_shotgun_primary_ammo 1 -set g_balance_shotgun_primary_animtime 0.2 -set g_balance_shotgun_primary_bullets 14 -set g_balance_shotgun_primary_damage 4 -set g_balance_shotgun_primary_force 15 -set g_balance_shotgun_primary_refire 0.75 -set g_balance_shotgun_primary_solidpenetration 3.8 -set g_balance_shotgun_primary_spread 0.12 -set g_balance_shotgun_reload_ammo 0 -set g_balance_shotgun_reload_time 2 -set g_balance_shotgun_secondary 1 -set g_balance_shotgun_secondary_animtime 1 -set g_balance_shotgun_secondary_damage 80 -set g_balance_shotgun_secondary_force 200 -set g_balance_shotgun_secondary_melee_delay 0.25 -set g_balance_shotgun_secondary_melee_multihit 1 -set g_balance_shotgun_secondary_melee_no_doubleslap 1 -set g_balance_shotgun_secondary_melee_nonplayerdamage 40 -set g_balance_shotgun_secondary_melee_range 120 -set g_balance_shotgun_secondary_melee_swing_side 120 -set g_balance_shotgun_secondary_melee_swing_up 30 -set g_balance_shotgun_secondary_melee_time 0.15 -set g_balance_shotgun_secondary_melee_traces 10 -set g_balance_shotgun_secondary_refire 1.25 -set g_balance_shotgun_switchdelay_drop 0.2 -set g_balance_shotgun_switchdelay_raise 0.2 -set g_balance_shotgun_weaponreplace "" -set g_balance_shotgun_weaponstart 1 -set g_balance_shotgun_weaponstartoverride -1 -set g_balance_shotgun_weaponthrowable 1 -// }}} -// {{{ #3: Machine Gun -set g_balance_machinegun_burst 3 -set g_balance_machinegun_burst_ammo 3 -set g_balance_machinegun_burst_animtime 0.3 -set g_balance_machinegun_burst_refire 0.06 -set g_balance_machinegun_burst_refire2 0.45 -set g_balance_machinegun_burst_speed 0 -set g_balance_machinegun_first 1 -set g_balance_machinegun_first_ammo 1 -set g_balance_machinegun_first_damage 14 -set g_balance_machinegun_first_force 5 -set g_balance_machinegun_first_refire 0.125 -set g_balance_machinegun_first_spread 0.03 -set g_balance_machinegun_mode 1 -set g_balance_machinegun_reload_ammo 60 -set g_balance_machinegun_reload_time 2 -set g_balance_machinegun_solidpenetration 13.1 -set g_balance_machinegun_spread_add 0.012 -set g_balance_machinegun_spread_max 0.05 -set g_balance_machinegun_spread_min 0.02 -set g_balance_machinegun_sustained_ammo 1 -set g_balance_machinegun_sustained_damage 10 -set g_balance_machinegun_sustained_force 5 -set g_balance_machinegun_sustained_refire 0.1 -set g_balance_machinegun_sustained_spread 0.03 -set g_balance_machinegun_switchdelay_drop 0.2 -set g_balance_machinegun_switchdelay_raise 0.2 -set g_balance_machinegun_weaponreplace "arc machinegun" -set g_balance_machinegun_weaponstart 0 -set g_balance_machinegun_weaponstartoverride -1 -set g_balance_machinegun_weaponthrowable 1 -// }}} -// {{{ #4: Mortar -set g_balance_mortar_bouncefactor 0.5 -set g_balance_mortar_bouncestop 0.075 -set g_balance_mortar_primary_ammo 2 -set g_balance_mortar_primary_animtime 0.3 -set g_balance_mortar_primary_damage 50 -set g_balance_mortar_primary_damageforcescale 0 -set g_balance_mortar_primary_edgedamage 25 -set g_balance_mortar_primary_force 250 -set g_balance_mortar_primary_health 15 -set g_balance_mortar_primary_lifetime 5 -set g_balance_mortar_primary_lifetime_stick 0 -set g_balance_mortar_primary_radius 120 -set g_balance_mortar_primary_refire 0.8 -set g_balance_mortar_primary_remote_minbouncecnt 0 -set g_balance_mortar_primary_speed 1900 -set g_balance_mortar_primary_speed_up 225 -set g_balance_mortar_primary_speed_z 0 -set g_balance_mortar_primary_spread 0 -set g_balance_mortar_primary_type 0 -set g_balance_mortar_reload_ammo 0 -set g_balance_mortar_reload_time 2 -set g_balance_mortar_secondary_ammo 2 -set g_balance_mortar_secondary_animtime 0.3 -set g_balance_mortar_secondary_damage 60 -set g_balance_mortar_secondary_damageforcescale 4 -set g_balance_mortar_secondary_edgedamage 30 -set g_balance_mortar_secondary_force 250 -set g_balance_mortar_secondary_health 30 -set g_balance_mortar_secondary_lifetime 5 -set g_balance_mortar_secondary_lifetime_bounce 0.5 -set g_balance_mortar_secondary_lifetime_stick 0 -set g_balance_mortar_secondary_radius 120 -set g_balance_mortar_secondary_refire 0.7 -set g_balance_mortar_secondary_remote_detonateprimary 0 -set g_balance_mortar_secondary_speed 1400 -set g_balance_mortar_secondary_speed_up 150 -set g_balance_mortar_secondary_speed_z 0 -set g_balance_mortar_secondary_spread 0 -set g_balance_mortar_secondary_type 1 -set g_balance_mortar_switchdelay_drop 0.2 -set g_balance_mortar_switchdelay_raise 0.2 -set g_balance_mortar_weaponreplace "" -set g_balance_mortar_weaponstart 0 -set g_balance_mortar_weaponstartoverride -1 -set g_balance_mortar_weaponthrowable 1 -// }}} -// {{{ #5: Mine Layer (MUTATOR WEAPON) -set g_balance_minelayer_ammo 4 -set g_balance_minelayer_animtime 0.4 -set g_balance_minelayer_damage 40 -set g_balance_minelayer_damageforcescale 0 -set g_balance_minelayer_detonatedelay -1 -set g_balance_minelayer_edgedamage 20 -set g_balance_minelayer_force 250 -set g_balance_minelayer_health 15 -set g_balance_minelayer_lifetime 10 -set g_balance_minelayer_lifetime_countdown 0.5 -set g_balance_minelayer_limit 3 -set g_balance_minelayer_protection 0 -set g_balance_minelayer_proximityradius 150 -set g_balance_minelayer_radius 175 -set g_balance_minelayer_refire 1.5 -set g_balance_minelayer_reload_ammo 0 -set g_balance_minelayer_reload_time 2 -set g_balance_minelayer_remote_damage 45 -set g_balance_minelayer_remote_edgedamage 40 -set g_balance_minelayer_remote_force 300 -set g_balance_minelayer_remote_radius 200 -set g_balance_minelayer_speed 1000 -set g_balance_minelayer_switchdelay_drop 0.2 -set g_balance_minelayer_switchdelay_raise 0.2 -set g_balance_minelayer_time 0.5 -set g_balance_minelayer_weaponreplace "" -set g_balance_minelayer_weaponstart 0 -set g_balance_minelayer_weaponstartoverride -1 -set g_balance_minelayer_weaponthrowable 1 -// }}} -// {{{ #6: Electro -set g_balance_electro_combo_comboradius 300 -set g_balance_electro_combo_comboradius_thruwall 200 -set g_balance_electro_combo_damage 50 -set g_balance_electro_combo_edgedamage 25 -set g_balance_electro_combo_force 120 -set g_balance_electro_combo_radius 150 -set g_balance_electro_combo_safeammocheck 1 -set g_balance_electro_combo_speed 2000 -set g_balance_electro_primary_ammo 4 -set g_balance_electro_primary_animtime 0.3 -set g_balance_electro_primary_comboradius 300 -set g_balance_electro_primary_damage 40 -set g_balance_electro_primary_edgedamage 20 -set g_balance_electro_primary_force 200 -set g_balance_electro_primary_lifetime 5 -set g_balance_electro_primary_midaircombo_explode 1 -set g_balance_electro_primary_midaircombo_interval 0.1 -set g_balance_electro_primary_midaircombo_radius 100 -set g_balance_electro_primary_radius 100 -set g_balance_electro_primary_refire 0.6 -set g_balance_electro_primary_speed 2500 -set g_balance_electro_primary_spread 0 -set g_balance_electro_reload_ammo 0 -set g_balance_electro_reload_time 2 -set g_balance_electro_secondary_ammo 2 -set g_balance_electro_secondary_animtime 0.2 -set g_balance_electro_secondary_bouncefactor 0.3 -set g_balance_electro_secondary_bouncestop 0.05 -set g_balance_electro_secondary_count 3 -set g_balance_electro_secondary_damage 40 -set g_balance_electro_secondary_damagedbycontents 1 -set g_balance_electro_secondary_damageforcescale 4 -set g_balance_electro_secondary_edgedamage 20 -set g_balance_electro_secondary_force 50 -set g_balance_electro_secondary_health 5 -set g_balance_electro_secondary_lifetime 4 -set g_balance_electro_secondary_radius 150 -set g_balance_electro_secondary_refire 0.2 -set g_balance_electro_secondary_refire2 1.6 -set g_balance_electro_secondary_speed 1000 -set g_balance_electro_secondary_speed_up 200 -set g_balance_electro_secondary_speed_z 0 -set g_balance_electro_secondary_spread 0.04 -set g_balance_electro_secondary_touchexplode 0 -set g_balance_electro_switchdelay_drop 0.2 -set g_balance_electro_switchdelay_raise 0.2 -set g_balance_electro_weaponreplace "" -set g_balance_electro_weaponstart 0 -set g_balance_electro_weaponstartoverride -1 -set g_balance_electro_weaponthrowable 1 -// }}} -// {{{ #7: Crylink -set g_balance_crylink_primary_ammo 3 -set g_balance_crylink_primary_animtime 0.3 -set g_balance_crylink_primary_bouncedamagefactor 0.5 -set g_balance_crylink_primary_bounces 1 -set g_balance_crylink_primary_damage 12 -set g_balance_crylink_primary_edgedamage 6 -set g_balance_crylink_primary_force -50 -set g_balance_crylink_primary_joindelay 0.1 -set g_balance_crylink_primary_joinexplode 1 -set g_balance_crylink_primary_joinexplode_damage 0 -set g_balance_crylink_primary_joinexplode_edgedamage 0 -set g_balance_crylink_primary_joinexplode_force 0 -set g_balance_crylink_primary_joinexplode_radius 0 -set g_balance_crylink_primary_joinspread 0.2 -set g_balance_crylink_primary_linkexplode 1 -set g_balance_crylink_primary_middle_fadetime 5 -set g_balance_crylink_primary_middle_lifetime 5 -set g_balance_crylink_primary_other_fadetime 5 -set g_balance_crylink_primary_other_lifetime 5 -set g_balance_crylink_primary_radius 80 -set g_balance_crylink_primary_refire 0.7 -set g_balance_crylink_primary_shots 6 -set g_balance_crylink_primary_speed 2000 -set g_balance_crylink_primary_spread 0.08 -set g_balance_crylink_reload_ammo 0 -set g_balance_crylink_reload_time 2 -set g_balance_crylink_secondary 1 -set g_balance_crylink_secondary_ammo 2 -set g_balance_crylink_secondary_animtime 0.2 -set g_balance_crylink_secondary_bouncedamagefactor 0.5 -set g_balance_crylink_secondary_bounces 0 -set g_balance_crylink_secondary_damage 10 -set g_balance_crylink_secondary_edgedamage 5 -set g_balance_crylink_secondary_force -250 -set g_balance_crylink_secondary_joindelay 0 -set g_balance_crylink_secondary_joinexplode 0 -set g_balance_crylink_secondary_joinexplode_damage 0 -set g_balance_crylink_secondary_joinexplode_edgedamage 0 -set g_balance_crylink_secondary_joinexplode_force 0 -set g_balance_crylink_secondary_joinexplode_radius 0 -set g_balance_crylink_secondary_joinspread 0 -set g_balance_crylink_secondary_linkexplode 1 -set g_balance_crylink_secondary_middle_fadetime 5 -set g_balance_crylink_secondary_middle_lifetime 5 -set g_balance_crylink_secondary_other_fadetime 5 -set g_balance_crylink_secondary_other_lifetime 5 -set g_balance_crylink_secondary_radius 100 -set g_balance_crylink_secondary_refire 0.7 -set g_balance_crylink_secondary_shots 5 -set g_balance_crylink_secondary_speed 3000 -set g_balance_crylink_secondary_spread 0.01 -set g_balance_crylink_secondary_spreadtype 1 -set g_balance_crylink_switchdelay_drop 0.2 -set g_balance_crylink_switchdelay_raise 0.2 -set g_balance_crylink_weaponreplace "" -set g_balance_crylink_weaponstart 0 -set g_balance_crylink_weaponstartoverride -1 -set g_balance_crylink_weaponthrowable 1 -// }}} -// {{{ #8: Vortex -set g_balance_vortex_charge 1 -set g_balance_vortex_charge_animlimit 0.5 -set g_balance_vortex_charge_limit 1 -set g_balance_vortex_charge_maxspeed 800 -set g_balance_vortex_charge_mindmg 40 -set g_balance_vortex_charge_minspeed 400 -set g_balance_vortex_charge_rate 0.4 -set g_balance_vortex_charge_rot_pause 0 -set g_balance_vortex_charge_rot_rate 0 -set g_balance_vortex_charge_shot_multiplier 0 -set g_balance_vortex_charge_start 0.5 -set g_balance_vortex_charge_velocity_rate 0 -set g_balance_vortex_primary_ammo 6 -set g_balance_vortex_primary_animtime 0.6 -set g_balance_vortex_primary_damage 80 -set g_balance_vortex_primary_damagefalloff_forcehalflife 0 -set g_balance_vortex_primary_damagefalloff_halflife 0 -set g_balance_vortex_primary_damagefalloff_maxdist 0 -set g_balance_vortex_primary_damagefalloff_mindist 0 -set g_balance_vortex_primary_force 400 -set g_balance_vortex_primary_refire 1.5 -set g_balance_vortex_reload_ammo 0 -set g_balance_vortex_reload_time 2 -set g_balance_vortex_secondary 0 -set g_balance_vortex_secondary_ammo 2 -set g_balance_vortex_secondary_animtime 0 -set g_balance_vortex_secondary_chargepool 0 -set g_balance_vortex_secondary_chargepool_pause_regen 1 -set g_balance_vortex_secondary_chargepool_regen 0.15 -set g_balance_vortex_secondary_damage 0 -set g_balance_vortex_secondary_damagefalloff_forcehalflife 0 -set g_balance_vortex_secondary_damagefalloff_halflife 0 -set g_balance_vortex_secondary_damagefalloff_maxdist 0 -set g_balance_vortex_secondary_damagefalloff_mindist 0 -set g_balance_vortex_secondary_force 0 -set g_balance_vortex_secondary_refire 0 -set g_balance_vortex_switchdelay_drop 0.2 -set g_balance_vortex_switchdelay_raise 0.2 -set g_balance_vortex_weaponreplace "" -set g_balance_vortex_weaponstart 0 -set g_balance_vortex_weaponstartoverride -1 -set g_balance_vortex_weaponthrowable 1 -// }}} -// {{{ #9: Hagar -set g_balance_hagar_primary_ammo 1 -set g_balance_hagar_primary_damage 25 -set g_balance_hagar_primary_damageforcescale 0 -set g_balance_hagar_primary_edgedamage 12.5 -set g_balance_hagar_primary_force 100 -set g_balance_hagar_primary_health 15 -set g_balance_hagar_primary_lifetime 5 -set g_balance_hagar_primary_radius 65 -set g_balance_hagar_primary_refire 0.16667 -set g_balance_hagar_primary_speed 2500 -set g_balance_hagar_primary_spread 0.03 -set g_balance_hagar_reload_ammo 0 -set g_balance_hagar_reload_time 2 -set g_balance_hagar_secondary 1 -set g_balance_hagar_secondary_ammo 1 -set g_balance_hagar_secondary_damage 40 -set g_balance_hagar_secondary_damageforcescale 0 -set g_balance_hagar_secondary_edgedamage 20 -set g_balance_hagar_secondary_force 75 -set g_balance_hagar_secondary_health 15 -set g_balance_hagar_secondary_lifetime_min 10 -set g_balance_hagar_secondary_lifetime_rand 0 -set g_balance_hagar_secondary_load 1 -set g_balance_hagar_secondary_load_abort 0 -set g_balance_hagar_secondary_load_animtime 0.2 -set g_balance_hagar_secondary_load_hold 4 -set g_balance_hagar_secondary_load_linkexplode 0 -set g_balance_hagar_secondary_load_max 4 -set g_balance_hagar_secondary_load_releasedeath 0 -set g_balance_hagar_secondary_load_speed 0.5 -set g_balance_hagar_secondary_load_spread 0.075 -set g_balance_hagar_secondary_load_spread_bias 0.5 -set g_balance_hagar_secondary_radius 80 -set g_balance_hagar_secondary_refire 0.5 -set g_balance_hagar_secondary_speed 2000 -set g_balance_hagar_secondary_spread 0.05 -set g_balance_hagar_switchdelay_drop 0.2 -set g_balance_hagar_switchdelay_raise 0.2 -set g_balance_hagar_weaponreplace "" -set g_balance_hagar_weaponstart 0 -set g_balance_hagar_weaponstartoverride -1 -set g_balance_hagar_weaponthrowable 1 -// }}} -// {{{ #10: Devastator -set g_balance_devastator_ammo 4 -set g_balance_devastator_animtime 0.4 -set g_balance_devastator_damage 70 -set g_balance_devastator_damageforcescale 1 -set g_balance_devastator_detonatedelay 0.02 -set g_balance_devastator_edgedamage 35 -set g_balance_devastator_force 450 -set g_balance_devastator_guidedelay 0.2 -set g_balance_devastator_guidegoal 512 -set g_balance_devastator_guiderate 70 -set g_balance_devastator_guideratedelay 0.01 -set g_balance_devastator_guidestop 0 -set g_balance_devastator_health 30 -set g_balance_devastator_lifetime 10 -set g_balance_devastator_radius 110 -set g_balance_devastator_refire 1.2 -set g_balance_devastator_reload_ammo 0 -set g_balance_devastator_reload_time 2 -set g_balance_devastator_remote_damage 70 -set g_balance_devastator_remote_edgedamage 35 -set g_balance_devastator_remote_force 400 -set g_balance_devastator_remote_jump_damage 70 -set g_balance_devastator_remote_jump_radius 0 -set g_balance_devastator_remote_jump_velocity_z_add 400 -set g_balance_devastator_remote_jump_velocity_z_max 1500 -set g_balance_devastator_remote_jump_velocity_z_min 400 -set g_balance_devastator_remote_radius 110 -set g_balance_devastator_speed 1300 -set g_balance_devastator_speedaccel 1300 -set g_balance_devastator_speedstart 1000 -set g_balance_devastator_switchdelay_drop 0.2 -set g_balance_devastator_switchdelay_raise 0.2 -set g_balance_devastator_weaponreplace "" -set g_balance_devastator_weaponstart 0 -set g_balance_devastator_weaponstartoverride -1 -set g_balance_devastator_weaponthrowable 1 -// }}} -// {{{ #11: Port-O-Launch -set g_balance_porto_primary_animtime 0.3 -set g_balance_porto_primary_lifetime 5 -set g_balance_porto_primary_refire 1.5 -set g_balance_porto_primary_speed 1000 -set g_balance_porto_secondary 1 -set g_balance_porto_secondary_animtime 0.3 -set g_balance_porto_secondary_lifetime 5 -set g_balance_porto_secondary_refire 1.5 -set g_balance_porto_secondary_speed 1000 -set g_balance_porto_switchdelay_drop 0.2 -set g_balance_porto_switchdelay_raise 0.2 -set g_balance_porto_weaponreplace "" -set g_balance_porto_weaponstart 0 -set g_balance_porto_weaponstartoverride -1 -set g_balance_porto_weaponthrowable 1 -// }}} -// {{{ #12: Vaporizer -set g_balance_vaporizer_primary_ammo 10 -set g_balance_vaporizer_primary_animtime 0.3 -set g_balance_vaporizer_primary_refire 1 -set g_balance_vaporizer_reload_ammo 0 -set g_balance_vaporizer_reload_time 0 -set g_balance_vaporizer_secondary_ammo 0 -set g_balance_vaporizer_secondary_animtime 0.2 -set g_balance_vaporizer_secondary_damage 25 -set g_balance_vaporizer_secondary_delay 0 -set g_balance_vaporizer_secondary_edgedamage 12.5 -set g_balance_vaporizer_secondary_force 400 -set g_balance_vaporizer_secondary_lifetime 5 -set g_balance_vaporizer_secondary_radius 70 -set g_balance_vaporizer_secondary_refire 0.7 -set g_balance_vaporizer_secondary_shotangle 0 -set g_balance_vaporizer_secondary_speed 6000 -set g_balance_vaporizer_secondary_spread 0 -set g_balance_vaporizer_switchdelay_drop 0.2 -set g_balance_vaporizer_switchdelay_raise 0.2 -set g_balance_vaporizer_weaponreplace "" -set g_balance_vaporizer_weaponstart 0 -set g_balance_vaporizer_weaponstartoverride -1 -set g_balance_vaporizer_weaponthrowable 0 -// }}} -// {{{ #13: Grappling Hook -set g_balance_hook_primary_ammo 5 -set g_balance_hook_primary_animtime 0.3 -set g_balance_hook_primary_hooked_ammo 5 -set g_balance_hook_primary_hooked_time_free 2 -set g_balance_hook_primary_hooked_time_max 0 -set g_balance_hook_primary_refire 0.2 -set g_balance_hook_secondary_animtime 0.3 -set g_balance_hook_secondary_damage 25 -set g_balance_hook_secondary_damageforcescale 0 -set g_balance_hook_secondary_duration 1.5 -set g_balance_hook_secondary_edgedamage 5 -set g_balance_hook_secondary_force -2000 -set g_balance_hook_secondary_gravity 5 -set g_balance_hook_secondary_health 15 -set g_balance_hook_secondary_lifetime 5 -set g_balance_hook_secondary_power 3 -set g_balance_hook_secondary_radius 500 -set g_balance_hook_secondary_refire 3 -set g_balance_hook_secondary_speed 0 -set g_balance_hook_switchdelay_drop 0.2 -set g_balance_hook_switchdelay_raise 0.2 -set g_balance_hook_weaponreplace "" -set g_balance_hook_weaponstart 0 -set g_balance_hook_weaponstartoverride -1 -set g_balance_hook_weaponthrowable 1 -// }}} -// {{{ #14: Heavy Laser Assault Cannon (MUTATOR WEAPON) -set g_balance_hlac_primary_ammo 1 -set g_balance_hlac_primary_animtime 0.4 -set g_balance_hlac_primary_damage 18 -set g_balance_hlac_primary_edgedamage 9 -set g_balance_hlac_primary_force 90 -set g_balance_hlac_primary_lifetime 5 -set g_balance_hlac_primary_radius 70 -set g_balance_hlac_primary_refire 0.15 -set g_balance_hlac_primary_speed 9000 -set g_balance_hlac_primary_spread_add 0.0045 -set g_balance_hlac_primary_spread_crouchmod 0.25 -set g_balance_hlac_primary_spread_max 0.25 -set g_balance_hlac_primary_spread_min 0.01 -set g_balance_hlac_reload_ammo 0 -set g_balance_hlac_reload_time 2 -set g_balance_hlac_secondary 1 -set g_balance_hlac_secondary_ammo 10 -set g_balance_hlac_secondary_animtime 0.3 -set g_balance_hlac_secondary_damage 15 -set g_balance_hlac_secondary_edgedamage 7.5 -set g_balance_hlac_secondary_force 90 -set g_balance_hlac_secondary_lifetime 5 -set g_balance_hlac_secondary_radius 70 -set g_balance_hlac_secondary_refire 1 -set g_balance_hlac_secondary_shots 6 -set g_balance_hlac_secondary_speed 9000 -set g_balance_hlac_secondary_spread 0.15 -set g_balance_hlac_secondary_spread_crouchmod 0.5 -set g_balance_hlac_switchdelay_drop 0.2 -set g_balance_hlac_switchdelay_raise 0.2 -set g_balance_hlac_weaponreplace "" -set g_balance_hlac_weaponstart 0 -set g_balance_hlac_weaponstartoverride -1 -set g_balance_hlac_weaponthrowable 1 -// }}} -// {{{ #15: @!#%'n Tuba -set g_balance_tuba_animtime 0.05 -set g_balance_tuba_attenuation 0.5 -set g_balance_tuba_damage 5 -set g_balance_tuba_edgedamage 0 -set g_balance_tuba_force 40 -set g_balance_tuba_radius 200 -set g_balance_tuba_refire 0.05 -set g_balance_tuba_switchdelay_drop 0.2 -set g_balance_tuba_switchdelay_raise 0.2 -set g_balance_tuba_weaponreplace "" -set g_balance_tuba_weaponstart 0 -set g_balance_tuba_weaponstartoverride -1 -set g_balance_tuba_weaponthrowable 1 -// }}} -// {{{ #16: Rifle (MUTATOR WEAPON) -set g_balance_rifle_bursttime 0 -set g_balance_rifle_primary_ammo 10 -set g_balance_rifle_primary_animtime 0.4 -set g_balance_rifle_primary_bullethail 0 -set g_balance_rifle_primary_burstcost 0 -set g_balance_rifle_primary_damage 80 -set g_balance_rifle_primary_force 100 -set g_balance_rifle_primary_refire 1.2 -set g_balance_rifle_primary_shots 1 -set g_balance_rifle_primary_solidpenetration 62.2 -set g_balance_rifle_primary_spread 0 -set g_balance_rifle_primary_tracer 1 -set g_balance_rifle_reload_ammo 80 -set g_balance_rifle_reload_time 2 -set g_balance_rifle_secondary 1 -set g_balance_rifle_secondary_ammo 10 -set g_balance_rifle_secondary_animtime 0.3 -set g_balance_rifle_secondary_bullethail 0 -set g_balance_rifle_secondary_burstcost 0 -set g_balance_rifle_secondary_damage 20 -set g_balance_rifle_secondary_force 50 -set g_balance_rifle_secondary_refire 0.9 -set g_balance_rifle_secondary_reload 0 -set g_balance_rifle_secondary_shots 4 -set g_balance_rifle_secondary_solidpenetration 15.5 -set g_balance_rifle_secondary_spread 0.04 -set g_balance_rifle_secondary_tracer 0 -set g_balance_rifle_switchdelay_drop 0.2 -set g_balance_rifle_switchdelay_raise 0.2 -set g_balance_rifle_weaponreplace "" -set g_balance_rifle_weaponstart 0 -set g_balance_rifle_weaponstartoverride -1 -set g_balance_rifle_weaponthrowable 1 -// }}} -// {{{ #17: Fireball -set g_balance_fireball_primary_animtime 0.2 -set g_balance_fireball_primary_bfgdamage 100 -set g_balance_fireball_primary_bfgforce 0 -set g_balance_fireball_primary_bfgradius 1000 -set g_balance_fireball_primary_damage 200 -set g_balance_fireball_primary_damageforcescale 0 -set g_balance_fireball_primary_edgedamage 50 -set g_balance_fireball_primary_force 600 -set g_balance_fireball_primary_health 0 -set g_balance_fireball_primary_laserburntime 0.5 -set g_balance_fireball_primary_laserdamage 80 -set g_balance_fireball_primary_laseredgedamage 20 -set g_balance_fireball_primary_laserradius 256 -set g_balance_fireball_primary_lifetime 15 -set g_balance_fireball_primary_radius 200 -set g_balance_fireball_primary_refire 2 -set g_balance_fireball_primary_refire2 0 -set g_balance_fireball_primary_speed 1200 -set g_balance_fireball_primary_spread 0 -set g_balance_fireball_secondary_animtime 0.3 -set g_balance_fireball_secondary_damage 40 -set g_balance_fireball_secondary_damageforcescale 4 -set g_balance_fireball_secondary_damagetime 5 -set g_balance_fireball_secondary_laserburntime 0.5 -set g_balance_fireball_secondary_laserdamage 50 -set g_balance_fireball_secondary_laseredgedamage 20 -set g_balance_fireball_secondary_laserradius 110 -set g_balance_fireball_secondary_lifetime 7 -set g_balance_fireball_secondary_refire 1.5 -set g_balance_fireball_secondary_speed 900 -set g_balance_fireball_secondary_speed_up 100 -set g_balance_fireball_secondary_speed_z 0 -set g_balance_fireball_secondary_spread 0 -set g_balance_fireball_switchdelay_drop 0.2 -set g_balance_fireball_switchdelay_raise 0.2 -set g_balance_fireball_weaponreplace "" -set g_balance_fireball_weaponstart 0 -set g_balance_fireball_weaponstartoverride -1 -set g_balance_fireball_weaponthrowable 0 -// }}} -// {{{ #18: T.A.G. Seeker (MUTATOR WEAPON) -set g_balance_seeker_flac_ammo 1 -set g_balance_seeker_flac_animtime 0.1 -set g_balance_seeker_flac_damage 15 -set g_balance_seeker_flac_edgedamage 10 -set g_balance_seeker_flac_force 50 -set g_balance_seeker_flac_lifetime 0.1 -set g_balance_seeker_flac_lifetime_rand 0.05 -set g_balance_seeker_flac_radius 100 -set g_balance_seeker_flac_refire 0.1 -set g_balance_seeker_flac_speed 3000 -set g_balance_seeker_flac_speed_up 1000 -set g_balance_seeker_flac_speed_z 0 -set g_balance_seeker_flac_spread 0.4 -set g_balance_seeker_missile_accel 1400 -set g_balance_seeker_missile_ammo 2 -set g_balance_seeker_missile_animtime 0.2 -set g_balance_seeker_missile_count 3 -set g_balance_seeker_missile_damage 30 -set g_balance_seeker_missile_damageforcescale 4 -set g_balance_seeker_missile_decel 1400 -set g_balance_seeker_missile_delay 0.25 -set g_balance_seeker_missile_edgedamage 10 -set g_balance_seeker_missile_force 150 -set g_balance_seeker_missile_health 5 -set g_balance_seeker_missile_lifetime 15 -set g_balance_seeker_missile_proxy 0 -set g_balance_seeker_missile_proxy_delay 0.2 -set g_balance_seeker_missile_proxy_maxrange 45 -set g_balance_seeker_missile_radius 80 -set g_balance_seeker_missile_refire 0.5 -set g_balance_seeker_missile_smart 1 -set g_balance_seeker_missile_smart_mindist 800 -set g_balance_seeker_missile_smart_trace_max 2500 -set g_balance_seeker_missile_smart_trace_min 1000 -set g_balance_seeker_missile_speed 700 -set g_balance_seeker_missile_speed_max 1300 -set g_balance_seeker_missile_speed_up 300 -set g_balance_seeker_missile_speed_z 0 -set g_balance_seeker_missile_spread 0 -set g_balance_seeker_missile_turnrate 0.65 -set g_balance_seeker_reload_ammo 0 -set g_balance_seeker_reload_time 2 -set g_balance_seeker_switchdelay_drop 0.2 -set g_balance_seeker_switchdelay_raise 0.2 -set g_balance_seeker_tag_ammo 1 -set g_balance_seeker_tag_animtime 0.2 -set g_balance_seeker_tag_damageforcescale 4 -set g_balance_seeker_tag_health 5 -set g_balance_seeker_tag_lifetime 15 -set g_balance_seeker_tag_refire 0.75 -set g_balance_seeker_tag_speed 5000 -set g_balance_seeker_tag_spread 0 -set g_balance_seeker_tag_tracker_lifetime 10 -set g_balance_seeker_type 0 -set g_balance_seeker_weaponreplace "" -set g_balance_seeker_weaponstart 0 -set g_balance_seeker_weaponstartoverride -1 -set g_balance_seeker_weaponthrowable 1 -// }}} -// {{{ #19: Shockwave (MUTATOR WEAPON) -set g_balance_shockwave_blast_animtime 0.3 -set g_balance_shockwave_blast_damage 20 -set g_balance_shockwave_blast_distance 1000 -set g_balance_shockwave_blast_edgedamage 0 -set g_balance_shockwave_blast_force 200 -set g_balance_shockwave_blast_force_forwardbias 50 -set g_balance_shockwave_blast_force_zscale 2 -set g_balance_shockwave_blast_jump_damage 20 -set g_balance_shockwave_blast_jump_edgedamage 0 -set g_balance_shockwave_blast_jump_force 300 -set g_balance_shockwave_blast_jump_force_velocitybias 0 -set g_balance_shockwave_blast_jump_force_zscale 1.25 -set g_balance_shockwave_blast_jump_multiplier_accuracy 0.5 -set g_balance_shockwave_blast_jump_multiplier_distance 0.5 -set g_balance_shockwave_blast_jump_multiplier_min 0 -set g_balance_shockwave_blast_jump_radius 150 -set g_balance_shockwave_blast_multiplier_accuracy 0.5 -set g_balance_shockwave_blast_multiplier_distance 0.5 -set g_balance_shockwave_blast_multiplier_min 0 -set g_balance_shockwave_blast_refire 0.75 -set g_balance_shockwave_blast_splash_damage 15 -set g_balance_shockwave_blast_splash_edgedamage 0 -set g_balance_shockwave_blast_splash_force 100 -set g_balance_shockwave_blast_splash_force_forwardbias 50 -set g_balance_shockwave_blast_splash_multiplier_accuracy 0.5 -set g_balance_shockwave_blast_splash_multiplier_distance 0.5 -set g_balance_shockwave_blast_splash_multiplier_min 0 -set g_balance_shockwave_blast_splash_radius 70 -set g_balance_shockwave_blast_spread_max 120 -set g_balance_shockwave_blast_spread_min 25 -set g_balance_shockwave_melee_animtime 1.3 -set g_balance_shockwave_melee_damage 80 -set g_balance_shockwave_melee_delay 0.25 -set g_balance_shockwave_melee_force 200 -set g_balance_shockwave_melee_multihit 1 -set g_balance_shockwave_melee_no_doubleslap 1 -set g_balance_shockwave_melee_nonplayerdamage 40 -set g_balance_shockwave_melee_range 120 -set g_balance_shockwave_melee_refire 1.25 -set g_balance_shockwave_melee_swing_side 120 -set g_balance_shockwave_melee_swing_up 30 -set g_balance_shockwave_melee_time 0.15 -set g_balance_shockwave_melee_traces 10 -set g_balance_shockwave_switchdelay_drop 0.2 -set g_balance_shockwave_switchdelay_raise 0.2 -set g_balance_shockwave_weaponreplace "" -set g_balance_shockwave_weaponstart 1 -set g_balance_shockwave_weaponstartoverride -1 -set g_balance_shockwave_weaponthrowable 0 -// }}} -// {{{ #20: Arc -set g_balance_arc_beam_ammo 4 -set g_balance_arc_beam_animtime 0.2 -set g_balance_arc_beam_botaimlifetime 0 -set g_balance_arc_beam_botaimspeed 0 -set g_balance_arc_beam_damage 115 -set g_balance_arc_beam_degreespersegment 1 -set g_balance_arc_beam_distancepersegment 0 -set g_balance_arc_beam_falloff_halflifedist 0 -set g_balance_arc_beam_falloff_maxdist 0 -set g_balance_arc_beam_falloff_mindist 0 -set g_balance_arc_beam_force 900 -set g_balance_arc_beam_healing_amax 200 -set g_balance_arc_beam_healing_aps 50 -set g_balance_arc_beam_healing_hmax 200 -set g_balance_arc_beam_healing_hps 50 -set g_balance_arc_beam_maxangle 10 -set g_balance_arc_beam_nonplayerdamage 80 -set g_balance_arc_beam_range 1000 -set g_balance_arc_beam_refire 0.5 -set g_balance_arc_beam_returnspeed 8 -set g_balance_arc_beam_tightness 0.5 -set g_balance_arc_burst_ammo 15 -set g_balance_arc_burst_damage 500 -set g_balance_arc_burst_healing_aps 100 -set g_balance_arc_burst_healing_hps 100 -set g_balance_arc_switchdelay_drop 0.3 -set g_balance_arc_switchdelay_raise 0.3 -set g_balance_arc_weaponreplace "" -set g_balance_arc_weaponstart 0 -set g_balance_arc_weaponstartoverride -1 -set g_balance_arc_weaponthrowable 1 -// }}} diff --git a/balance-rev.cfg b/balance-rev.cfg deleted file mode 100644 index c7e78963e..000000000 --- a/balance-rev.cfg +++ /dev/null @@ -1,223 +0,0 @@ -g_mod_balance Xonotic - -// {{{ starting gear -set g_balance_health_start 100 -set g_balance_armor_start 0 -set g_start_ammo_shells 15 -set g_start_ammo_nails 0 -set g_start_ammo_rockets 0 -set g_start_ammo_cells 0 -set g_start_ammo_plasma 0 -set g_start_ammo_fuel 0 -set g_warmup_start_health 100 "starting values when being in warmup-stage" -set g_warmup_start_armor 100 "starting values when being in warmup-stage" -set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage" -set g_warmup_start_ammo_nails 160 "starting values when being in warmup-stage" -set g_warmup_start_ammo_rockets 80 "starting values when being in warmup-stage" -set g_warmup_start_ammo_cells 90 "starting values when being in warmup-stage" -set g_warmup_start_ammo_plasma 90 "starting values when being in warmup-stage" -set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage" -set g_lms_start_health 200 -set g_lms_start_armor 200 -set g_lms_start_ammo_shells 60 -set g_lms_start_ammo_nails 320 -set g_lms_start_ammo_rockets 160 -set g_lms_start_ammo_cells 180 -set g_lms_start_ammo_plasma 180 -set g_lms_start_ammo_fuel 0 -set g_balance_nix_roundtime 25 -set g_balance_nix_incrtime 1.6 -set g_balance_nix_ammo_shells 60 -set g_balance_nix_ammo_nails 320 -set g_balance_nix_ammo_rockets 160 -set g_balance_nix_ammo_cells 180 -set g_balance_nix_ammo_plasma 180 -set g_balance_nix_ammo_fuel 0 -set g_balance_nix_ammoincr_shells 2 // eh this will need figured out later I assume -set g_balance_nix_ammoincr_nails 6 -set g_balance_nix_ammoincr_rockets 2 -set g_balance_nix_ammoincr_cells 2 -set g_balance_nix_ammoincr_plasma 2 -set g_balance_nix_ammoincr_fuel 2 -// }}} - -// {{{ pickup items -set g_pickup_ammo_anyway 1 -set g_pickup_weapons_anyway 1 -set g_pickup_shells 15 -set g_pickup_shells_weapon 15 -set g_pickup_shells_max 60 -set g_pickup_nails 80 -set g_pickup_nails_weapon 80 -set g_pickup_nails_max 320 -set g_pickup_rockets 40 -set g_pickup_rockets_weapon 40 -set g_pickup_rockets_max 160 -set g_pickup_cells 30 -set g_pickup_cells_weapon 30 -set g_pickup_cells_max 180 -set g_pickup_plasma 30 -set g_pickup_plasma_weapon 30 -set g_pickup_plasma_max 180 -set g_pickup_fuel 50 -set g_pickup_fuel_weapon 50 -set g_pickup_fuel_jetpack 100 -set g_pickup_fuel_max 100 -set g_pickup_armorsmall 5 -set g_pickup_armorsmall_max 200 -set g_pickup_armorsmall_anyway 0 -set g_pickup_armormedium 25 -set g_pickup_armormedium_max 100 -set g_pickup_armormedium_anyway 0 -set g_pickup_armorbig 50 -set g_pickup_armorbig_max 100 -set g_pickup_armorbig_anyway 0 -set g_pickup_armorlarge 100 -set g_pickup_armorlarge_max 200 -set g_pickup_armorlarge_anyway 0 -set g_pickup_healthsmall 5 -set g_pickup_healthsmall_max 200 -set g_pickup_healthsmall_anyway 0 -set g_pickup_healthmedium 25 -set g_pickup_healthmedium_max 100 -set g_pickup_healthmedium_anyway 0 -set g_pickup_healthlarge 50 -set g_pickup_healthlarge_max 100 -set g_pickup_healthlarge_anyway 0 -set g_pickup_healthmega 100 -set g_pickup_healthmega_max 200 -set g_pickup_healthmega_anyway 0 -set g_pickup_respawntime_short 15 -set g_pickup_respawntime_medium 20 -set g_pickup_respawntime_long 30 -set g_pickup_respawntime_powerup 120 -set g_pickup_respawntime_weapon 10 -set g_pickup_respawntime_superweapon 120 -set g_pickup_respawntime_ammo 15 -set g_pickup_respawntimejitter_short 0 -set g_pickup_respawntimejitter_medium 0 -set g_pickup_respawntimejitter_long 0 -set g_pickup_respawntimejitter_powerup 30 -set g_pickup_respawntimejitter_weapon 0 -set g_pickup_respawntimejitter_superweapon 10 -set g_pickup_respawntimejitter_ammo 0 -// }}} - -// {{{ regen/rot -set g_balance_health_regen 0.08 -set g_balance_health_regenlinear 0.5 -set g_balance_pause_health_regen 5 -set g_balance_pause_health_regen_spawn 0 -set g_balance_health_rot 0.03 -set g_balance_health_rotlinear 0.75 -set g_balance_pause_health_rot 1 -set g_balance_pause_health_rot_spawn 5 -set g_balance_health_regenstable 100 -set g_balance_health_rotstable 100 -set g_balance_health_limit 999 -set g_balance_armor_regen 0 -set g_balance_armor_regenlinear 0 -set g_balance_armor_rot 0.03 -set g_balance_armor_rotlinear 0.75 -set g_balance_pause_armor_rot 1 -set g_balance_pause_armor_rot_spawn 5 -set g_balance_armor_regenstable 100 -set g_balance_armor_rotstable 100 -set g_balance_armor_limit 999 -set g_balance_armor_blockpercent 0.6 -set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)" -set g_balance_fuel_regenlinear 0 -set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter -set g_balance_fuel_rot 0.05 -set g_balance_fuel_rotlinear 0 -set g_balance_pause_fuel_rot 5 -set g_balance_pause_fuel_rot_spawn 10 -set g_balance_fuel_regenstable 50 -set g_balance_fuel_rotstable 100 -set g_balance_fuel_limit 999 -// }}} - -// {{{ misc -set g_balance_selfdamagepercent 0.65 -set g_weaponspeedfactor 1 "weapon projectile speed multiplier" -set g_weaponratefactor 1 "weapon fire rate multiplier" -set g_weapondamagefactor 1 "weapon damage multiplier" -set g_weaponforcefactor 1 "weapon force multiplier" -set g_weaponspreadfactor 1 "weapon spread multiplier" -set g_balance_firetransfer_time 0.9 -set g_balance_firetransfer_damage 0.8 -set g_throughfloor_damage 0.75 -set g_throughfloor_force 0.75 -set g_projectiles_damage -2 -// possible values: -// -2: absolutely no damage to projectiles (no exceptions) -// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines) -// 0: only damage from contents (lava/slime) or exceptions -// 1: only self damage or damage from contents or exceptions -// 2: allow all damage to projectiles normally -set g_projectiles_keep_owner 0 -set g_projectiles_newton_style 0 -// possible values: -// 0: absolute velocity projectiles (like Quake) -// 1: relative velocity projectiles, "Newtonian" (like Tribes 2) -// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard) -set g_projectiles_newton_style_2_minfactor 0.8 -set g_projectiles_newton_style_2_maxfactor 1.5 -set g_projectiles_spread_style 7 -// possible values: -// 0: forward + solid sphere (like Quake) - varies velocity -// 1: forward + flattened solid sphere -// 2: forward + solid circle -// 3: forward + normal distribution 3D - varies velocity -// 4: forward + normal distribution on a plane -// 5: forward + circle with 1-r falloff -// 6: forward + circle with 1-r^2 falloff -// 7: forward + circle with (1-r)(2-r) falloff -set g_balance_falldamage_deadminspeed 250 -set g_balance_falldamage_minspeed 900 -set g_balance_falldamage_factor 0.20 -set g_balance_falldamage_maxdamage 40 -set g_balance_damagepush_speedfactor 2.5 -set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage -set g_balance_contents_drowndelay 10 // time under water before a player begins drowning -set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning -set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava -set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime -set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime -set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap" -// }}} - -// {{{ powerups -set g_balance_powerup_invincible_takedamage 0.25 // only 1/4th damage is taken -set g_balance_powerup_invincible_time 30 -set g_balance_powerup_strength_damage 3 -set g_balance_powerup_strength_force 3 -set g_balance_powerup_strength_time 30 -set g_balance_powerup_strength_selfdamage 1.5 -set g_balance_powerup_strength_selfforce 1.5 -set g_balance_superweapons_time 30 -// }}} - -// {{{ jetpack/hook -set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack" -set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction" -set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)" -set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction" -set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction" -set g_jetpack_fuel 8 "fuel per second for jetpack" -set g_jetpack_attenuation 2 "jetpack sound attenuation" - -set g_grappling_hook_tarzan 2 // 2: can also pull players -set g_balance_grapplehook_speed_fly 1800 -set g_balance_grapplehook_speed_pull 2000 -set g_balance_grapplehook_force_rubber 2000 -set g_balance_grapplehook_force_rubber_overstretch 1000 -set g_balance_grapplehook_length_min 50 -set g_balance_grapplehook_stretch 50 -set g_balance_grapplehook_airfriction 0.2 -set g_balance_grapplehook_health 50 -set g_balance_grapplehook_damagedbycontents 1 -set g_balance_grapplehook_refire 0.2 -// }}} - -exec bal-wep-xonotic.cfg diff --git a/balance-xonotic.cfg b/balance-xonotic.cfg deleted file mode 100644 index 4c3dcdb7a..000000000 --- a/balance-xonotic.cfg +++ /dev/null @@ -1,223 +0,0 @@ -g_mod_balance Xonotic - -// {{{ starting gear -set g_balance_health_start 100 -set g_balance_armor_start 0 -set g_start_ammo_shells 15 -set g_start_ammo_nails 0 -set g_start_ammo_rockets 0 -set g_start_ammo_cells 0 -set g_start_ammo_plasma 0 -set g_start_ammo_fuel 0 -set g_warmup_start_health 100 "starting values when being in warmup-stage" -set g_warmup_start_armor 100 "starting values when being in warmup-stage" -set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage" -set g_warmup_start_ammo_nails 160 "starting values when being in warmup-stage" -set g_warmup_start_ammo_rockets 80 "starting values when being in warmup-stage" -set g_warmup_start_ammo_cells 90 "starting values when being in warmup-stage" -set g_warmup_start_ammo_plasma 90 "starting values when being in warmup-stage" -set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage" -set g_lms_start_health 200 -set g_lms_start_armor 200 -set g_lms_start_ammo_shells 60 -set g_lms_start_ammo_nails 320 -set g_lms_start_ammo_rockets 160 -set g_lms_start_ammo_cells 180 -set g_lms_start_ammo_plasma 180 -set g_lms_start_ammo_fuel 0 -set g_balance_nix_roundtime 25 -set g_balance_nix_incrtime 1.6 -set g_balance_nix_ammo_shells 60 -set g_balance_nix_ammo_nails 320 -set g_balance_nix_ammo_rockets 160 -set g_balance_nix_ammo_cells 180 -set g_balance_nix_ammo_plasma 180 -set g_balance_nix_ammo_fuel 0 -set g_balance_nix_ammoincr_shells 2 // eh this will need figured out later I assume -set g_balance_nix_ammoincr_nails 6 -set g_balance_nix_ammoincr_rockets 2 -set g_balance_nix_ammoincr_cells 2 -set g_balance_nix_ammoincr_plasma 2 -set g_balance_nix_ammoincr_fuel 2 -// }}} - -// {{{ pickup items -set g_pickup_ammo_anyway 1 -set g_pickup_weapons_anyway 1 -set g_pickup_shells 15 -set g_pickup_shells_weapon 15 -set g_pickup_shells_max 60 -set g_pickup_nails 80 -set g_pickup_nails_weapon 80 -set g_pickup_nails_max 320 -set g_pickup_rockets 40 -set g_pickup_rockets_weapon 40 -set g_pickup_rockets_max 160 -set g_pickup_cells 30 -set g_pickup_cells_weapon 30 -set g_pickup_cells_max 180 -set g_pickup_plasma 30 -set g_pickup_plasma_weapon 30 -set g_pickup_plasma_max 180 -set g_pickup_fuel 50 -set g_pickup_fuel_weapon 50 -set g_pickup_fuel_jetpack 100 -set g_pickup_fuel_max 100 -set g_pickup_armorsmall 5 -set g_pickup_armorsmall_max 200 -set g_pickup_armorsmall_anyway 1 -set g_pickup_armormedium 25 -set g_pickup_armormedium_max 200 -set g_pickup_armormedium_anyway 1 -set g_pickup_armorbig 50 -set g_pickup_armorbig_max 200 -set g_pickup_armorbig_anyway 1 -set g_pickup_armorlarge 100 -set g_pickup_armorlarge_max 200 -set g_pickup_armorlarge_anyway 1 -set g_pickup_healthsmall 5 -set g_pickup_healthsmall_max 200 -set g_pickup_healthsmall_anyway 1 -set g_pickup_healthmedium 25 -set g_pickup_healthmedium_max 200 -set g_pickup_healthmedium_anyway 1 -set g_pickup_healthlarge 50 -set g_pickup_healthlarge_max 200 -set g_pickup_healthlarge_anyway 1 -set g_pickup_healthmega 100 -set g_pickup_healthmega_max 200 -set g_pickup_healthmega_anyway 1 -set g_pickup_respawntime_short 15 -set g_pickup_respawntime_medium 20 -set g_pickup_respawntime_long 30 -set g_pickup_respawntime_powerup 120 -set g_pickup_respawntime_weapon 10 -set g_pickup_respawntime_superweapon 120 -set g_pickup_respawntime_ammo 10 -set g_pickup_respawntimejitter_short 0 -set g_pickup_respawntimejitter_medium 0 -set g_pickup_respawntimejitter_long 0 -set g_pickup_respawntimejitter_powerup 30 -set g_pickup_respawntimejitter_weapon 0 -set g_pickup_respawntimejitter_superweapon 10 -set g_pickup_respawntimejitter_ammo 0 -// }}} - -// {{{ regen/rot -set g_balance_health_regen 0.08 -set g_balance_health_regenlinear 0.5 -set g_balance_pause_health_regen 5 -set g_balance_pause_health_regen_spawn 0 -set g_balance_health_rot 0.04 -set g_balance_health_rotlinear 0.75 -set g_balance_pause_health_rot 1 -set g_balance_pause_health_rot_spawn 5 -set g_balance_health_regenstable 100 -set g_balance_health_rotstable 100 -set g_balance_health_limit 999 -set g_balance_armor_regen 0 -set g_balance_armor_regenlinear 0 -set g_balance_armor_rot 0.04 -set g_balance_armor_rotlinear 0.75 -set g_balance_pause_armor_rot 1 -set g_balance_pause_armor_rot_spawn 5 -set g_balance_armor_regenstable 100 -set g_balance_armor_rotstable 100 -set g_balance_armor_limit 999 -set g_balance_armor_blockpercent 0.6 -set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)" -set g_balance_fuel_regenlinear 0 -set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter -set g_balance_fuel_rot 0.05 -set g_balance_fuel_rotlinear 0 -set g_balance_pause_fuel_rot 5 -set g_balance_pause_fuel_rot_spawn 10 -set g_balance_fuel_regenstable 50 -set g_balance_fuel_rotstable 100 -set g_balance_fuel_limit 999 -// }}} - -// {{{ misc -set g_balance_selfdamagepercent 0.65 -set g_weaponspeedfactor 1 "weapon projectile speed multiplier" -set g_weaponratefactor 1 "weapon fire rate multiplier" -set g_weapondamagefactor 1 "weapon damage multiplier" -set g_weaponforcefactor 1 "weapon force multiplier" -set g_weaponspreadfactor 1 "weapon spread multiplier" -set g_balance_firetransfer_time 0.9 -set g_balance_firetransfer_damage 0.8 -set g_throughfloor_damage 0.75 -set g_throughfloor_force 0.75 -set g_projectiles_damage 2 -// possible values: -// -2: absolutely no damage to projectiles (no exceptions) -// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines) -// 0: only damage from contents (lava/slime) or exceptions -// 1: only self damage or damage from contents or exceptions -// 2: allow all damage to projectiles normally -set g_projectiles_keep_owner 0 -set g_projectiles_newton_style 2 -// possible values: -// 0: absolute velocity projectiles (like Quake) -// 1: relative velocity projectiles, "Newtonian" (like Tribes 2) -// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard) -set g_projectiles_newton_style_2_minfactor 0.8 -set g_projectiles_newton_style_2_maxfactor 1.5 -set g_projectiles_spread_style 7 -// possible values: -// 0: forward + solid sphere (like Quake) - varies velocity -// 1: forward + flattened solid sphere -// 2: forward + solid circle -// 3: forward + normal distribution 3D - varies velocity -// 4: forward + normal distribution on a plane -// 5: forward + circle with 1-r falloff -// 6: forward + circle with 1-r^2 falloff -// 7: forward + circle with (1-r)(2-r) falloff -set g_balance_falldamage_deadminspeed 250 -set g_balance_falldamage_minspeed 900 -set g_balance_falldamage_factor 0.20 -set g_balance_falldamage_maxdamage 40 -set g_balance_damagepush_speedfactor 2.5 -set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage -set g_balance_contents_drowndelay 10 // time under water before a player begins drowning -set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning -set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava -set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime -set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime -set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap" -// }}} - -// {{{ powerups -set g_balance_powerup_invincible_takedamage 0.25 // only 1/4th damage is taken -set g_balance_powerup_invincible_time 30 -set g_balance_powerup_strength_damage 3 -set g_balance_powerup_strength_force 3 -set g_balance_powerup_strength_time 30 -set g_balance_powerup_strength_selfdamage 1.5 -set g_balance_powerup_strength_selfforce 1.5 -set g_balance_superweapons_time 30 -// }}} - -// {{{ jetpack/hook -set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack" -set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction" -set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)" -set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction" -set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction" -set g_jetpack_fuel 8 "fuel per second for jetpack" -set g_jetpack_attenuation 2 "jetpack sound attenuation" - -set g_grappling_hook_tarzan 2 // 2: can also pull players -set g_balance_grapplehook_speed_fly 1800 -set g_balance_grapplehook_speed_pull 2000 -set g_balance_grapplehook_force_rubber 2000 -set g_balance_grapplehook_force_rubber_overstretch 1000 -set g_balance_grapplehook_length_min 50 -set g_balance_grapplehook_stretch 50 -set g_balance_grapplehook_airfriction 0.2 -set g_balance_grapplehook_health 50 -set g_balance_grapplehook_damagedbycontents 1 -set g_balance_grapplehook_refire 0.2 -// }}} - -exec bal-wep-xonotic.cfg diff --git a/balance-xpm.cfg b/balance-xpm.cfg deleted file mode 100644 index 7a310da1a..000000000 --- a/balance-xpm.cfg +++ /dev/null @@ -1,223 +0,0 @@ -g_mod_balance Xonotic - -// {{{ starting gear -set g_balance_health_start 100 -set g_balance_armor_start 0 -set g_start_ammo_shells 15 -set g_start_ammo_nails 0 -set g_start_ammo_rockets 0 -set g_start_ammo_cells 0 -set g_start_ammo_plasma 0 -set g_start_ammo_fuel 0 -set g_warmup_start_health 100 "starting values when being in warmup-stage" -set g_warmup_start_armor 100 "starting values when being in warmup-stage" -set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage" -set g_warmup_start_ammo_nails 160 "starting values when being in warmup-stage" -set g_warmup_start_ammo_rockets 80 "starting values when being in warmup-stage" -set g_warmup_start_ammo_cells 90 "starting values when being in warmup-stage" -set g_warmup_start_ammo_plasma 90 "starting values when being in warmup-stage" -set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage" -set g_lms_start_health 200 -set g_lms_start_armor 200 -set g_lms_start_ammo_shells 60 -set g_lms_start_ammo_nails 320 -set g_lms_start_ammo_rockets 160 -set g_lms_start_ammo_cells 180 -set g_lms_start_ammo_plasma 180 -set g_lms_start_ammo_fuel 0 -set g_balance_nix_roundtime 25 -set g_balance_nix_incrtime 1.6 -set g_balance_nix_ammo_shells 60 -set g_balance_nix_ammo_nails 320 -set g_balance_nix_ammo_rockets 160 -set g_balance_nix_ammo_cells 180 -set g_balance_nix_ammo_plasma 180 -set g_balance_nix_ammo_fuel 0 -set g_balance_nix_ammoincr_shells 2 // eh this will need figured out later I assume -set g_balance_nix_ammoincr_nails 6 -set g_balance_nix_ammoincr_rockets 2 -set g_balance_nix_ammoincr_cells 2 -set g_balance_nix_ammoincr_plasma 2 -set g_balance_nix_ammoincr_fuel 2 -// }}} - -// {{{ pickup items -set g_pickup_ammo_anyway 1 -set g_pickup_weapons_anyway 1 -set g_pickup_shells 15 -set g_pickup_shells_weapon 15 -set g_pickup_shells_max 60 -set g_pickup_nails 80 -set g_pickup_nails_weapon 80 -set g_pickup_nails_max 320 -set g_pickup_rockets 40 -set g_pickup_rockets_weapon 40 -set g_pickup_rockets_max 160 -set g_pickup_cells 30 -set g_pickup_cells_weapon 30 -set g_pickup_cells_max 180 -set g_pickup_plasma 30 -set g_pickup_plasma_weapon 30 -set g_pickup_plasma_max 180 -set g_pickup_fuel 50 -set g_pickup_fuel_weapon 50 -set g_pickup_fuel_jetpack 100 -set g_pickup_fuel_max 100 -set g_pickup_armorsmall 5 -set g_pickup_armorsmall_max 200 -set g_pickup_armorsmall_anyway 0 -set g_pickup_armormedium 25 -set g_pickup_armormedium_max 100 -set g_pickup_armormedium_anyway 0 -set g_pickup_armorbig 50 -set g_pickup_armorbig_max 100 -set g_pickup_armorbig_anyway 0 -set g_pickup_armorlarge 100 -set g_pickup_armorlarge_max 200 -set g_pickup_armorlarge_anyway 0 -set g_pickup_healthsmall 5 -set g_pickup_healthsmall_max 200 -set g_pickup_healthsmall_anyway 0 -set g_pickup_healthmedium 25 -set g_pickup_healthmedium_max 100 -set g_pickup_healthmedium_anyway 0 -set g_pickup_healthlarge 50 -set g_pickup_healthlarge_max 100 -set g_pickup_healthlarge_anyway 0 -set g_pickup_healthmega 100 -set g_pickup_healthmega_max 200 -set g_pickup_healthmega_anyway 0 -set g_pickup_respawntime_short 15 -set g_pickup_respawntime_medium 20 -set g_pickup_respawntime_long 30 -set g_pickup_respawntime_powerup 120 -set g_pickup_respawntime_weapon 10 -set g_pickup_respawntime_superweapon 120 -set g_pickup_respawntime_ammo 15 -set g_pickup_respawntimejitter_short 0 -set g_pickup_respawntimejitter_medium 0 -set g_pickup_respawntimejitter_long 0 -set g_pickup_respawntimejitter_powerup 30 -set g_pickup_respawntimejitter_weapon 0 -set g_pickup_respawntimejitter_superweapon 10 -set g_pickup_respawntimejitter_ammo 0 -// }}} - -// {{{ regen/rot -set g_balance_health_regen 0.08 -set g_balance_health_regenlinear 0.5 -set g_balance_pause_health_regen 5 -set g_balance_pause_health_regen_spawn 0 -set g_balance_health_rot 0.03 -set g_balance_health_rotlinear 0.75 -set g_balance_pause_health_rot 1 -set g_balance_pause_health_rot_spawn 5 -set g_balance_health_regenstable 100 -set g_balance_health_rotstable 100 -set g_balance_health_limit 999 -set g_balance_armor_regen 0 -set g_balance_armor_regenlinear 0 -set g_balance_armor_rot 0.03 -set g_balance_armor_rotlinear 0.75 -set g_balance_pause_armor_rot 1 -set g_balance_pause_armor_rot_spawn 5 -set g_balance_armor_regenstable 100 -set g_balance_armor_rotstable 100 -set g_balance_armor_limit 999 -set g_balance_armor_blockpercent 0.6 -set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)" -set g_balance_fuel_regenlinear 0 -set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter -set g_balance_fuel_rot 0.05 -set g_balance_fuel_rotlinear 0 -set g_balance_pause_fuel_rot 5 -set g_balance_pause_fuel_rot_spawn 10 -set g_balance_fuel_regenstable 50 -set g_balance_fuel_rotstable 100 -set g_balance_fuel_limit 999 -// }}} - -// {{{ misc -set g_balance_selfdamagepercent 0.65 -set g_weaponspeedfactor 1 "weapon projectile speed multiplier" -set g_weaponratefactor 1 "weapon fire rate multiplier" -set g_weapondamagefactor 1 "weapon damage multiplier" -set g_weaponforcefactor 1 "weapon force multiplier" -set g_weaponspreadfactor 1 "weapon spread multiplier" -set g_balance_firetransfer_time 0.9 -set g_balance_firetransfer_damage 0.8 -set g_throughfloor_damage 0.75 -set g_throughfloor_force 0.75 -set g_projectiles_damage 1 -// possible values: -// -2: absolutely no damage to projectiles (no exceptions) -// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines) -// 0: only damage from contents (lava/slime) or exceptions -// 1: only self damage or damage from contents or exceptions -// 2: allow all damage to projectiles normally -set g_projectiles_keep_owner 0 -set g_projectiles_newton_style 0 -// possible values: -// 0: absolute velocity projectiles (like Quake) -// 1: relative velocity projectiles, "Newtonian" (like Tribes 2) -// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard) -set g_projectiles_newton_style_2_minfactor 0.8 -set g_projectiles_newton_style_2_maxfactor 1.5 -set g_projectiles_spread_style 7 -// possible values: -// 0: forward + solid sphere (like Quake) - varies velocity -// 1: forward + flattened solid sphere -// 2: forward + solid circle -// 3: forward + normal distribution 3D - varies velocity -// 4: forward + normal distribution on a plane -// 5: forward + circle with 1-r falloff -// 6: forward + circle with 1-r^2 falloff -// 7: forward + circle with (1-r)(2-r) falloff -set g_balance_falldamage_deadminspeed 250 -set g_balance_falldamage_minspeed 900 -set g_balance_falldamage_factor 0.20 -set g_balance_falldamage_maxdamage 40 -set g_balance_damagepush_speedfactor 2.5 -set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage -set g_balance_contents_drowndelay 10 // time under water before a player begins drowning -set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning -set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava -set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime -set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime -set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap" -// }}} - -// {{{ powerups -set g_balance_powerup_invincible_takedamage 0.25 // only 1/4th damage is taken -set g_balance_powerup_invincible_time 30 -set g_balance_powerup_strength_damage 3 -set g_balance_powerup_strength_force 3 -set g_balance_powerup_strength_time 30 -set g_balance_powerup_strength_selfdamage 1.5 -set g_balance_powerup_strength_selfforce 1.5 -set g_balance_superweapons_time 30 -// }}} - -// {{{ jetpack/hook -set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack" -set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction" -set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)" -set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction" -set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction" -set g_jetpack_fuel 8 "fuel per second for jetpack" -set g_jetpack_attenuation 2 "jetpack sound attenuation" - -set g_grappling_hook_tarzan 2 // 2: can also pull players -set g_balance_grapplehook_speed_fly 1800 -set g_balance_grapplehook_speed_pull 2000 -set g_balance_grapplehook_force_rubber 2000 -set g_balance_grapplehook_force_rubber_overstretch 1000 -set g_balance_grapplehook_length_min 50 -set g_balance_grapplehook_stretch 50 -set g_balance_grapplehook_airfriction 0.2 -set g_balance_grapplehook_health 50 -set g_balance_grapplehook_damagedbycontents 1 -set g_balance_grapplehook_refire 0.2 -// }}} - -exec bal-wep-xonotic.cfg diff --git a/balance25.cfg b/balance25.cfg new file mode 100644 index 000000000..be0e84f3f --- /dev/null +++ b/balance25.cfg @@ -0,0 +1,706 @@ +g_mod_balance Nexuiz25 + +// {{{ starting gear +set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_balance_health_start 150 +set g_balance_armor_start 0 +set g_start_ammo_shells 40 +set g_start_ammo_nails 0 +set g_start_ammo_rockets 0 +set g_start_ammo_cells 0 +set g_start_ammo_fuel 0 +set g_warmup_start_health 250 "starting values when being in warmup-stage" +set g_warmup_start_armor 100 "starting values when being in warmup-stage" +set g_warmup_start_ammo_shells 50 "starting values when being in warmup-stage" +set g_warmup_start_ammo_nails 150 "starting values when being in warmup-stage" +set g_warmup_start_ammo_rockets 50 "starting values when being in warmup-stage" +set g_warmup_start_ammo_cells 50 "starting values when being in warmup-stage" +set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage" +set g_lms_start_health 250 +set g_lms_start_armor 100 +set g_lms_start_ammo_shells 50 +set g_lms_start_ammo_nails 150 +set g_lms_start_ammo_rockets 50 +set g_lms_start_ammo_cells 50 +set g_lms_start_ammo_fuel 0 +set g_balance_nix_roundtime 25 +set g_balance_nix_incrtime 1.6 +set g_balance_nix_ammo_shells 15 +set g_balance_nix_ammo_nails 45 +set g_balance_nix_ammo_rockets 15 +set g_balance_nix_ammo_cells 15 +set g_balance_nix_ammo_fuel 0 +set g_balance_nix_ammoincr_shells 2 +set g_balance_nix_ammoincr_nails 6 +set g_balance_nix_ammoincr_rockets 2 +set g_balance_nix_ammoincr_cells 2 +set g_balance_nix_ammoincr_fuel 2 +// }}} + +// {{{ pickup items +set g_pickup_ammo_anyway 0 +set g_pickup_weapons_anyway 0 +set g_pickup_shells 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_pickup_armorsmall_max 999 +set g_pickup_armorsmall_anyway 0 +set g_pickup_armormedium 25 +set g_pickup_armormedium_max 999 +set g_pickup_armormedium_anyway 0 +set g_pickup_armorbig 50 +set g_pickup_armorbig_max 999 +set g_pickup_armorbig_anyway 0 +set g_pickup_armorlarge 100 +set g_pickup_armorlarge_max 999 +set g_pickup_armorlarge_anyway 0 +set g_pickup_healthsmall 5 +set g_pickup_healthsmall_max 999 +set g_pickup_healthsmall_anyway 0 +set g_pickup_healthmedium 25 +set g_pickup_healthmedium_max 999 +set g_pickup_healthmedium_anyway 0 +set g_pickup_healthlarge 50 +set g_pickup_healthlarge_max 999 +set g_pickup_healthlarge_anyway 0 +set g_pickup_healthmega 100 +set g_pickup_healthmega_max 999 +set g_pickup_healthmega_anyway 0 +set g_pickup_respawntime_short 15 +set g_pickup_respawntime_medium 20 +set g_pickup_respawntime_long 30 +set g_pickup_respawntime_powerup 120 +set g_pickup_respawntime_weapon 15 +set g_pickup_respawntime_superweapon 120 +set g_pickup_respawntime_ammo 15 +set g_pickup_respawntimejitter_short 0 +set g_pickup_respawntimejitter_medium 0 +set g_pickup_respawntimejitter_long 0 +set g_pickup_respawntimejitter_powerup 10 +set g_pickup_respawntimejitter_weapon 0 +set g_pickup_respawntimejitter_superweapon 10 +set g_pickup_respawntimejitter_ammo 0 +// }}} + +// {{{ regen/rot +set g_balance_health_regen 0.1 +set g_balance_health_regenlinear 0 +set g_balance_pause_health_regen 5 +set g_balance_pause_health_regen_spawn 0 +set g_balance_health_rot 0.1 +set g_balance_health_rotlinear 0 +set g_balance_pause_health_rot 5 +set g_balance_pause_health_rot_spawn 10 +set g_balance_health_regenstable 100 +set g_balance_health_rotstable 100 +set g_balance_health_limit 999 +set g_balance_armor_regen 0 +set g_balance_armor_regenlinear 0 +set g_balance_armor_rot 0.1 +set g_balance_armor_rotlinear 0 +set g_balance_pause_armor_rot 5 +set g_balance_pause_armor_rot_spawn 10 +set g_balance_armor_regenstable 100 +set g_balance_armor_rotstable 100 +set g_balance_armor_limit 999 +set g_balance_armor_blockpercent 0.6 +set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)" +set g_balance_fuel_regenlinear 0 +set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter +set g_balance_fuel_rot 0.05 +set g_balance_fuel_rotlinear 0 +set g_balance_pause_fuel_rot 5 +set g_balance_pause_fuel_rot_spawn 10 +set g_balance_fuel_regenstable 50 +set g_balance_fuel_rotstable 100 +set g_balance_fuel_limit 999 +// }}} + +// {{{ misc +set g_balance_selfdamagepercent 0.6 +set g_weaponspeedfactor 1 "weapon projectile speed multiplier" +set g_weaponratefactor 1 "weapon fire rate multiplier" +set g_weapondamagefactor 1 "weapon damage multiplier" +set g_weaponforcefactor 1 "weapon force multiplier" +set g_weaponspreadfactor 1 "weapon spread multiplier" +set g_balance_firetransfer_time 0.9 +set g_balance_firetransfer_damage 0.8 +set g_throughfloor_damage 1 +set g_throughfloor_force 1 +set g_projectiles_damage 2 +// possible values: +// -2: absolutely no damage to projectiles (no exceptions) +// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines) +// 0: only damage from contents (lava/slime) or exceptions +// 1: only self damage or damage from contents or exceptions +// 2: allow all damage to projectiles normally +set g_projectiles_keep_owner 0 +set g_projectiles_newton_style 2 +// possible values: +// 0: absolute velocity projectiles (like Quake) +// 1: relative velocity projectiles, "Newtonian" (like Tribes 2) +// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard) +set g_projectiles_newton_style_2_minfactor 0.7 +set g_projectiles_newton_style_2_maxfactor 5 +set g_projectiles_spread_style 0 +// possible values: +// 0: forward + solid sphere (like Quake) - varies velocity +// 1: forward + flattened solid sphere +// 2: forward + solid circle +// 3: forward + normal distribution 3D - varies velocity +// 4: forward + normal distribution on a plane +// 5: forward + circle with 1-r falloff +// 6: forward + circle with 1-r^2 falloff +// 7: forward + circle with (1-r)(2-r) falloff +set g_balance_falldamage_deadminspeed 150 +set g_balance_falldamage_minspeed 1400 +set g_balance_falldamage_factor 0.15 +set g_balance_falldamage_maxdamage 25 +set g_balance_damagepush_speedfactor 0 +set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage +set g_balance_contents_drowndelay 10 // time under water before a player begins drowning +set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning +set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava +set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime +set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime +set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap" +// }}} + +// {{{ powerups +set g_balance_powerup_invincible_takedamage 0.2 +set g_balance_powerup_invincible_time 30 +set g_balance_powerup_strength_damage 3 +set g_balance_powerup_strength_force 4 +set g_balance_powerup_strength_time 30 +set g_balance_powerup_strength_selfdamage 1.5 +set g_balance_powerup_strength_selfforce 1.5 +set g_balance_superweapons_time 30 +// }}} + +// {{{ jetpack/hook +set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack" +set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction" +set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)" +set g_jetpack_maxspeed_side 1500 "max speed of the jetpack in xy direction" +set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction" +set g_jetpack_fuel 8 "fuel per second for jetpack" +set g_jetpack_attenuation 2 "jetpack sound attenuation" + +set g_grappling_hook_tarzan 2 // 2: can also pull players +set g_balance_grapplehook_speed_fly 1800 +set g_balance_grapplehook_speed_pull 2000 +set g_balance_grapplehook_force_rubber 2000 +set g_balance_grapplehook_force_rubber_overstretch 1000 +set g_balance_grapplehook_length_min 50 +set g_balance_grapplehook_stretch 50 +set g_balance_grapplehook_airfriction 0.2 +set g_balance_grapplehook_health 130 +set g_balance_grapplehook_damagedbycontents 0 +set g_balance_grapplehook_refire 0.2 +// }}} + +// {{{ weapon properties +// {{{ laser +set g_balance_laser_primary_damage 35 +set g_balance_laser_primary_edgedamage 10 +set g_balance_laser_primary_force 400 +set g_balance_laser_primary_radius 70 +set g_balance_laser_primary_speed 9000 +set g_balance_laser_primary_spread 0 +set g_balance_laser_primary_refire 0.7 +set g_balance_laser_primary_animtime 0.3 +set g_balance_laser_primary_lifetime 30 +set g_balance_laser_primary_shotangle 0 +set g_balance_laser_primary_delay 0.05 +set g_balance_laser_primary_gauntlet 0 +set g_balance_laser_primary_force_zscale 1 +set g_balance_laser_primary_force_velocitybias 0 +set g_balance_laser_primary_force_other_scale 1 +set g_balance_laser_secondary 0 // when 1, a secondary laser mode exists +set g_balance_laser_secondary_damage 35 +set g_balance_laser_secondary_edgedamage 10 +set g_balance_laser_secondary_force 400 +set g_balance_laser_secondary_radius 70 +set g_balance_laser_secondary_speed 9000 +set g_balance_laser_secondary_spread 0 +set g_balance_laser_secondary_refire 0.7 +set g_balance_laser_secondary_animtime 0.3 +set g_balance_laser_secondary_lifetime 30 +set g_balance_laser_secondary_shotangle 0 +set g_balance_laser_secondary_delay 0 +set g_balance_laser_secondary_gauntlet 0 +set g_balance_laser_secondary_force_zscale 1 +set g_balance_laser_secondary_force_velocitybias 0 +set g_balance_laser_secondary_force_other_scale 1 +set g_balance_laser_switchdelay_drop 0.15 +set g_balance_laser_switchdelay_raise 0.15 +set g_balance_laser_reload_ammo 0 //default: 6 +set g_balance_laser_reload_time 2 +// }}} +// {{{ shotgun +set g_balance_shotgun_primary_bullets 6 +set g_balance_shotgun_primary_damage 9 +set g_balance_shotgun_primary_force 60 +set g_balance_shotgun_primary_spread 0.07 +set g_balance_shotgun_primary_refire 0.5 +set g_balance_shotgun_primary_animtime 0.2 +set g_balance_shotgun_primary_ammo 1 +set g_balance_shotgun_primary_solidpenetration 3.8 +set g_balance_shotgun_secondary 1 +set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow +set g_balance_shotgun_secondary_melee_range 120 +set g_balance_shotgun_secondary_melee_swing_side 120 +set g_balance_shotgun_secondary_melee_swing_up 30 +set g_balance_shotgun_secondary_melee_time 0.15 +set g_balance_shotgun_secondary_melee_traces 10 +set g_balance_shotgun_secondary_melee_no_doubleslap 1 +set g_balance_shotgun_secondary_melee_nonplayerdamage 0 +set g_balance_shotgun_secondary_melee_multihit 1 +set g_balance_shotgun_secondary_damage 115 +set g_balance_shotgun_secondary_force 150 +set g_balance_shotgun_secondary_refire 1.1 +set g_balance_shotgun_secondary_animtime 1 +set g_balance_shotgun_switchdelay_drop 0.15 +set g_balance_shotgun_switchdelay_raise 0.15 +set g_balance_shotgun_reload_ammo 0 //default: 5 +set g_balance_shotgun_reload_time 2 +// }}} +// {{{ uzi +set g_balance_uzi_mode 0 // Activates varible spread for sustained & burst mode secondary +set g_balance_uzi_spread_min 0.02 +set g_balance_uzi_spread_max 0.6 +set g_balance_uzi_spread_add 0.012 + +set g_balance_uzi_burst 0 // # of bullets in a burst (if set to 2 or more) +set g_balance_uzi_burst_animtime 0.75 +set g_balance_uzi_burst_refire 0.05 // refire between burst bullets +set g_balance_uzi_burst_refire2 0.75 // refire after burst +set g_balance_uzi_burst_spread 0.04 +set g_balance_uzi_burst_damage 18 +set g_balance_uzi_burst_force 50 +set g_balance_uzi_burst_ammo 3 + +set g_balance_uzi_first 1 +set g_balance_uzi_first_damage 30 +set g_balance_uzi_first_force 50 +set g_balance_uzi_first_spread 0.015 +set g_balance_uzi_first_refire 0.2 +set g_balance_uzi_first_ammo 1 + +set g_balance_uzi_sustained_damage 15 +set g_balance_uzi_sustained_force 27 +set g_balance_uzi_sustained_spread 0.05 +set g_balance_uzi_sustained_refire 0.1 +set g_balance_uzi_sustained_ammo 1 + +set g_balance_uzi_solidpenetration 13.1 + +set g_balance_uzi_switchdelay_drop 0.15 +set g_balance_uzi_switchdelay_raise 0.15 + +set g_balance_uzi_reload_ammo 0 //default: 30 +set g_balance_uzi_reload_time 2 +// }}} +// {{{ mortar +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_radius 140 +set g_balance_grenadelauncher_primary_speed 2000 +set g_balance_grenadelauncher_primary_speed_up 200 +set g_balance_grenadelauncher_primary_speed_z 0 +set g_balance_grenadelauncher_primary_spread 0 +set g_balance_grenadelauncher_primary_lifetime 30 +set g_balance_grenadelauncher_primary_lifetime2 1 +set g_balance_grenadelauncher_primary_refire 0.8 +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_primary_damageforcescale 4 +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_radius 140 +set g_balance_grenadelauncher_secondary_speed 1400 +set g_balance_grenadelauncher_secondary_speed_up 200 +set g_balance_grenadelauncher_secondary_speed_z 0 +set g_balance_grenadelauncher_secondary_spread 0 +set g_balance_grenadelauncher_secondary_lifetime 2.5 +set g_balance_grenadelauncher_secondary_lifetime_bounce 0 +set g_balance_grenadelauncher_secondary_lifetime_stick 0 +set g_balance_grenadelauncher_secondary_refire 0.7 +set g_balance_grenadelauncher_secondary_animtime 0.3 +set g_balance_grenadelauncher_secondary_ammo 2 +set g_balance_grenadelauncher_secondary_health 10 +set g_balance_grenadelauncher_secondary_damageforcescale 4 +set g_balance_grenadelauncher_secondary_remote_detonateprimary 0 + +set g_balance_grenadelauncher_bouncefactor 0.5 +set g_balance_grenadelauncher_bouncestop 0.075 + +set g_balance_grenadelauncher_switchdelay_drop 0.15 +set g_balance_grenadelauncher_switchdelay_raise 0.15 + +set g_balance_grenadelauncher_reload_ammo 0 //default: 12 +set g_balance_grenadelauncher_reload_time 2 +// }}} +// {{{ electro +set g_balance_electro_lightning 0 +set g_balance_electro_primary_damage 65 +set g_balance_electro_primary_edgedamage 0 +set g_balance_electro_primary_force 200 +set g_balance_electro_primary_force_up 0 +set g_balance_electro_primary_radius 150 +set g_balance_electro_primary_comboradius 0 +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.3 +set g_balance_electro_primary_ammo 2 +set g_balance_electro_primary_range 0 +set g_balance_electro_primary_falloff_mindist 255 // 0.3 * radius +set g_balance_electro_primary_falloff_maxdist 850 +set g_balance_electro_primary_falloff_halflifedist 425 +set g_balance_electro_secondary_damage 50 +set g_balance_electro_secondary_edgedamage 0 +set g_balance_electro_secondary_force 200 +set g_balance_electro_secondary_radius 150 +set g_balance_electro_secondary_speed 900 +set g_balance_electro_secondary_speed_up 200 +set g_balance_electro_secondary_speed_z 0 +set g_balance_electro_secondary_spread 0 +set g_balance_electro_secondary_lifetime 5 +set g_balance_electro_secondary_refire 0.3 +set g_balance_electro_secondary_refire2 0 +set g_balance_electro_secondary_animtime 0.3 +set g_balance_electro_secondary_ammo 2 +set g_balance_electro_secondary_health 5 +set g_balance_electro_secondary_damageforcescale 4 +set g_balance_electro_secondary_damagedbycontents 0 +set g_balance_electro_secondary_count 1 +set g_balance_electro_secondary_bouncefactor 0.5 +set g_balance_electro_secondary_bouncestop 0.075 +set g_balance_electro_combo_damage 80 +set g_balance_electro_combo_edgedamage 0 +set g_balance_electro_combo_force 200 +set g_balance_electro_combo_radius 250 +set g_balance_electro_combo_comboradius 0 +set g_balance_electro_combo_speed 2000 +set g_balance_electro_combo_safeammocheck 0 +set g_balance_electro_switchdelay_drop 0.15 +set g_balance_electro_switchdelay_raise 0.15 +set g_balance_electro_reload_ammo 0 //default: 20 +set g_balance_electro_reload_time 2 +// }}} +// {{{ crylink +set g_balance_crylink_primary_damage 18 +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_speed 7000 +set g_balance_crylink_primary_spread 0.03 +set g_balance_crylink_primary_shots 4 +set g_balance_crylink_primary_bounces 1 +set g_balance_crylink_primary_refire 0.4 +set g_balance_crylink_primary_animtime 0.3 +set g_balance_crylink_primary_ammo 2 +set g_balance_crylink_primary_bouncedamagefactor 0.5 +set g_balance_crylink_primary_joindelay 0 +set g_balance_crylink_primary_joinspread 0 +set g_balance_crylink_primary_joinexplode 0 +set g_balance_crylink_primary_joinexplode_damage 0 +set g_balance_crylink_primary_joinexplode_edgedamage 0 +set g_balance_crylink_primary_joinexplode_radius 0 +set g_balance_crylink_primary_joinexplode_force 0 +set g_balance_crylink_primary_linkexplode 1 + +set g_balance_crylink_primary_middle_lifetime 5 // range: 35000 full, fades to 70000 +set g_balance_crylink_primary_middle_fadetime 5 +set g_balance_crylink_primary_other_lifetime 0.1 // range: 700 full, fades to 2450 +set g_balance_crylink_primary_other_fadetime 0.25 + +set g_balance_crylink_secondary 1 +set g_balance_crylink_secondary_damage 18 +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_speed 7000 +set g_balance_crylink_secondary_spread 0.08 +set g_balance_crylink_secondary_spreadtype 0 +set g_balance_crylink_secondary_shots 7 +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_bouncedamagefactor 0.5 +set g_balance_crylink_secondary_joindelay 0 +set g_balance_crylink_secondary_joinspread 0 +set g_balance_crylink_secondary_joinexplode 0 +set g_balance_crylink_secondary_joinexplode_damage 0 +set g_balance_crylink_secondary_joinexplode_edgedamage 0 +set g_balance_crylink_secondary_joinexplode_radius 0 +set g_balance_crylink_secondary_joinexplode_force 0 +set g_balance_crylink_secondary_linkexplode 1 + +set g_balance_crylink_secondary_middle_lifetime 5 // range: 35000 full, fades to 70000 +set g_balance_crylink_secondary_middle_fadetime 5 +set g_balance_crylink_secondary_line_lifetime 2 // range: 35000 full, fades to 70000 +set g_balance_crylink_secondary_line_fadetime 2 + +set g_balance_crylink_switchdelay_drop 0.15 +set g_balance_crylink_switchdelay_raise 0.15 + +set g_balance_crylink_reload_ammo 0 //default: 10 +set g_balance_crylink_reload_time 2 +// }}} +// {{{ nex +set g_balance_nex_primary_damage 100 +set g_balance_nex_primary_force 600 +set g_balance_nex_primary_refire 1.5 +set g_balance_nex_primary_animtime 0.3 +set g_balance_nex_primary_ammo 5 +set g_balance_nex_primary_damagefalloff_mindist 0 +set g_balance_nex_primary_damagefalloff_maxdist 0 +set g_balance_nex_primary_damagefalloff_halflife 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_chargepool 0 +set g_balance_nex_secondary_chargepool_regen 0.15 +set g_balance_nex_secondary_chargepool_pause_regen 1 +set g_balance_nex_secondary_chargepool_pause_health_regen 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_animtime 0.3 +set g_balance_nex_secondary_ammo 5 +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_charge 0 +set g_balance_nex_charge_mindmg 40 +set g_balance_nex_charge_start 0 +set g_balance_nex_charge_rate 0.1 +set g_balance_nex_charge_animlimit 0.5 +set g_balance_nex_charge_limit 0.5 +set g_balance_nex_charge_rot_rate 0 +set g_balance_nex_charge_rot_pause 0 // Dont rot down until this long after release of charge button +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 + +set g_balance_nex_switchdelay_drop 0.15 +set g_balance_nex_switchdelay_raise 0.15 + +set g_balance_nex_reload_ammo 0 //default: 25 +set g_balance_nex_reload_time 2 +// }}} +// {{{ minstanex +set g_balance_minstanex_refire 1 +set g_balance_minstanex_animtime 0.3 +set g_balance_minstanex_ammo 10 +set g_balance_minstanex_laser_ammo 0 +set g_balance_minstanex_laser_animtime 0.3 +set g_balance_minstanex_laser_refire 0.7 +set g_balance_minstanex_switchdelay_drop 0.15 +set g_balance_minstanex_switchdelay_raise 0.15 +set g_balance_minstanex_reload_ammo 0 //default: 50 +set g_balance_minstanex_reload_time 2 +// }}} +// {{{ hagar +set g_balance_hagar_primary_damage 37 +set g_balance_hagar_primary_edgedamage 15 +set g_balance_hagar_primary_force 100 +set g_balance_hagar_primary_health 0 +set g_balance_hagar_primary_damageforcescale 0 +set g_balance_hagar_primary_radius 65 +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_secondary 1 +set g_balance_hagar_secondary_load 0 +set g_balance_hagar_secondary_load_speed 0.6 +set g_balance_hagar_secondary_load_spread 0.075 +set g_balance_hagar_secondary_load_spread_bias 0.5 +set g_balance_hagar_secondary_load_max 4 +set g_balance_hagar_secondary_load_hold 0 +set g_balance_hagar_secondary_load_releasedeath 1 +set g_balance_hagar_secondary_load_abort 1 +set g_balance_hagar_secondary_load_linkexplode 0 +set g_balance_hagar_secondary_load_animtime 0.2 +set g_balance_hagar_secondary_damage 37 +set g_balance_hagar_secondary_edgedamage 15 +set g_balance_hagar_secondary_force 100 +set g_balance_hagar_secondary_health 0 +set g_balance_hagar_secondary_damageforcescale 0 +set g_balance_hagar_secondary_radius 65 +set g_balance_hagar_secondary_spread 0.015 +set g_balance_hagar_secondary_speed 1400 +set g_balance_hagar_secondary_lifetime_min 30 +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_switchdelay_drop 0.15 +set g_balance_hagar_switchdelay_raise 0.15 +set g_balance_hagar_reload_ammo 0 //default: 25 +set g_balance_hagar_reload_time 2 +// }}} +// {{{ rocketlauncher +set g_balance_rocketlauncher_damage 105 +set g_balance_rocketlauncher_edgedamage 40 +set g_balance_rocketlauncher_force 600 +set g_balance_rocketlauncher_radius 150 +set g_balance_rocketlauncher_speed 850 +set g_balance_rocketlauncher_speedaccel 0 +set g_balance_rocketlauncher_speedstart 850 +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_health 40 +set g_balance_rocketlauncher_damageforcescale 4 +set g_balance_rocketlauncher_detonatedelay 0.2 // 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 90 // max degrees per second +set g_balance_rocketlauncher_guideratedelay 0.01 // immediate +set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic) +set g_balance_rocketlauncher_guidedelay 0.15 // delay before guiding kicks in +set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again +set g_balance_rocketlauncher_remote_damage 105 +set g_balance_rocketlauncher_remote_edgedamage 40 +set g_balance_rocketlauncher_remote_radius 150 +set g_balance_rocketlauncher_remote_force 600 +set g_balance_rocketlauncher_switchdelay_drop 0.15 +set g_balance_rocketlauncher_switchdelay_raise 0.15 +set g_balance_rocketlauncher_reload_ammo 0 //default: 25 +set g_balance_rocketlauncher_reload_time 2 +// }}} +// {{{ porto +set g_balance_porto_primary_refire 1.5 +set g_balance_porto_primary_animtime 0.3 +set g_balance_porto_primary_speed 2000 +set g_balance_porto_primary_lifetime 30 +set g_balance_porto_secondary 0 +set g_balance_porto_secondary_refire 1.5 +set g_balance_porto_secondary_animtime 0.3 +set g_balance_porto_secondary_speed 2000 +set g_balance_porto_secondary_lifetime 30 +set g_balance_porto_switchdelay_drop 0.15 +set g_balance_porto_switchdelay_raise 0.15 +set g_balance_portal_health 200 // these get recharged whenever the portal is used +set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used +// }}} +// {{{ hook +set g_balance_hook_primary_fuel 5 // hook monkeys set 0 +set g_balance_hook_primary_refire 0.2 // hook monkeys set 0 +set g_balance_hook_primary_animtime 0.3 // good shoot anim +set g_balance_hook_primary_hooked_time_max 0 // infinite +set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free +set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked +set g_balance_hook_secondary_damage 25 // not much +set g_balance_hook_secondary_edgedamage 5 // not much +set g_balance_hook_secondary_radius 500 // LOTS +set g_balance_hook_secondary_force -2000 // LOTS +set g_balance_hook_secondary_ammo 50 // a whole pack +set g_balance_hook_secondary_lifetime 30 // infinite +set g_balance_hook_secondary_speed 0 // not much throwing +set g_balance_hook_secondary_gravity 5 // fast falling +set g_balance_hook_secondary_refire 3 // don't drop too many bombs... +set g_balance_hook_secondary_animtime 0.3 // good shoot anim +set g_balance_hook_secondary_power 3 // effect behaves like a square function +set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds +set g_balance_hook_secondary_health 0 +set g_balance_hook_secondary_damageforcescale 0 +set g_balance_hook_switchdelay_drop 0.15 +set g_balance_hook_switchdelay_raise 0.15 +// }}} +// {{{ tuba +set g_balance_tuba_refire 0.05 +set g_balance_tuba_animtime 0.05 +set g_balance_tuba_attenuation 0.5 +set g_balance_tuba_volume 1 +set g_balance_tuba_fadetime 0.25 +set g_balance_tuba_damage 5 +set g_balance_tuba_edgedamage 0 +set g_balance_tuba_radius 200 +set g_balance_tuba_force 40 +set g_balance_tuba_pitchstep 6 +set g_balance_tuba_switchdelay_drop 0.15 +set g_balance_tuba_switchdelay_raise 0.15 +// }}} +// {{{ fireball +set g_balance_fireball_primary_animtime 0.15 +set g_balance_fireball_primary_bfgdamage 100 +set g_balance_fireball_primary_bfgforce 0 +set g_balance_fireball_primary_bfgradius 1000 +set g_balance_fireball_primary_damage 200 +set g_balance_fireball_primary_damageforcescale 4 +set g_balance_fireball_primary_edgedamage 0 +set g_balance_fireball_primary_force 700 +set g_balance_fireball_primary_health 50 +set g_balance_fireball_primary_laserburntime 0.5 +set g_balance_fireball_primary_laserdamage 80 +set g_balance_fireball_primary_laseredgedamage 20 +set g_balance_fireball_primary_laserradius 256 +set g_balance_fireball_primary_lifetime 15 +set g_balance_fireball_primary_radius 200 +set g_balance_fireball_primary_refire 5 +set g_balance_fireball_primary_refire2 0 +set g_balance_fireball_primary_speed 650 +set g_balance_fireball_primary_spread 0 +set g_balance_fireball_secondary_animtime 0.3 +set g_balance_fireball_secondary_damage 40 +set g_balance_fireball_secondary_damageforcescale 4 +set g_balance_fireball_secondary_damagetime 5 +set g_balance_fireball_secondary_force 100 +set g_balance_fireball_secondary_laserburntime 0.5 +set g_balance_fireball_secondary_laserdamage 50 +set g_balance_fireball_secondary_laseredgedamage 20 +set g_balance_fireball_secondary_laserradius 110 +set g_balance_fireball_secondary_lifetime 7 +set g_balance_fireball_secondary_refire 2 +set g_balance_fireball_secondary_speed 900 +set g_balance_fireball_secondary_speed_up 100 +set g_balance_fireball_secondary_speed_z 0 +set g_balance_fireball_secondary_spread 0 +set g_balance_fireball_switchdelay_drop 0.15 +set g_balance_fireball_switchdelay_raise 0.15 +// }}} diff --git a/balanceFruitieX.cfg b/balanceFruitieX.cfg new file mode 100644 index 000000000..99d458d1d --- /dev/null +++ b/balanceFruitieX.cfg @@ -0,0 +1,706 @@ +g_mod_balance FruitieX + +// {{{ starting gear +set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_balance_health_start 125 +set g_balance_armor_start 0 +set g_start_ammo_shells 20 +set g_start_ammo_nails 0 +set g_start_ammo_rockets 0 +set g_start_ammo_cells 0 +set g_start_ammo_fuel 0 +set g_warmup_start_health 200 "starting values when being in warmup-stage" +set g_warmup_start_armor 100 "starting values when being in warmup-stage" +set g_warmup_start_ammo_shells 50 "starting values when being in warmup-stage" +set g_warmup_start_ammo_nails 150 "starting values when being in warmup-stage" +set g_warmup_start_ammo_rockets 50 "starting values when being in warmup-stage" +set g_warmup_start_ammo_cells 50 "starting values when being in warmup-stage" +set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage" +set g_lms_start_health 200 +set g_lms_start_armor 100 +set g_lms_start_ammo_shells 30 +set g_lms_start_ammo_nails 200 +set g_lms_start_ammo_rockets 150 +set g_lms_start_ammo_cells 150 +set g_lms_start_ammo_fuel 0 +set g_balance_nix_roundtime 25 +set g_balance_nix_incrtime 1.6 +set g_balance_nix_ammo_shells 15 +set g_balance_nix_ammo_nails 45 +set g_balance_nix_ammo_rockets 15 +set g_balance_nix_ammo_cells 15 +set g_balance_nix_ammo_fuel 0 +set g_balance_nix_ammoincr_shells 2 +set g_balance_nix_ammoincr_nails 6 +set g_balance_nix_ammoincr_rockets 2 +set g_balance_nix_ammoincr_cells 2 +set g_balance_nix_ammoincr_fuel 2 +// }}} + +// {{{ pickup items +set g_pickup_ammo_anyway 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 30 +set g_pickup_cells_weapon 20 +set g_pickup_cells_max 150 +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 +set g_pickup_armorsmall_max 150 +set g_pickup_armorsmall_anyway 1 +set g_pickup_armormedium 25 +set g_pickup_armormedium_max 50 +set g_pickup_armormedium_anyway 0 +set g_pickup_armorbig 50 +set g_pickup_armorbig_max 75; // LOG: to allow a little more armor from medium armor +set g_pickup_armorbig_anyway 0 +set g_pickup_armorlarge 100 +set g_pickup_armorlarge_max 150 +set g_pickup_armorlarge_anyway 1 +set g_pickup_healthsmall 5 +set g_pickup_healthsmall_max 250 +set g_pickup_healthsmall_anyway 1 +set g_pickup_healthmedium 25 +set g_pickup_healthmedium_max 100 +set g_pickup_healthmedium_anyway 0 +set g_pickup_healthlarge 50 +set g_pickup_healthlarge_max 150 +set g_pickup_healthlarge_anyway 0 +set g_pickup_healthmega 100 +set g_pickup_healthmega_max 250 +set g_pickup_healthmega_anyway 1 +set g_pickup_respawntime_short 15 +set g_pickup_respawntime_medium 20 +set g_pickup_respawntime_long 30 +set g_pickup_respawntime_powerup 120 +set g_pickup_respawntime_weapon 10 +set g_pickup_respawntime_superweapon 120 +set g_pickup_respawntime_ammo 25 +set g_pickup_respawntimejitter_short 0 +set g_pickup_respawntimejitter_medium 0 +set g_pickup_respawntimejitter_long 0 +set g_pickup_respawntimejitter_powerup 10 +set g_pickup_respawntimejitter_weapon 0 +set g_pickup_respawntimejitter_superweapon 10 +set g_pickup_respawntimejitter_ammo 0 +// }}} + +// {{{ regen/rot +set g_balance_health_regen 0.05 +set g_balance_health_regenlinear 0 +set g_balance_pause_health_regen 5 +set g_balance_pause_health_regen_spawn 0 +set g_balance_health_rot 0 +set g_balance_health_rotlinear 1 +set g_balance_pause_health_rot 1 +set g_balance_pause_health_rot_spawn 0 +set g_balance_health_regenstable 100 +set g_balance_health_rotstable 100 +set g_balance_health_limit 999 +set g_balance_armor_regen 0 +set g_balance_armor_regenlinear 0 +set g_balance_armor_rot 0 +set g_balance_armor_rotlinear 1 +set g_balance_pause_armor_rot 1 +set g_balance_pause_armor_rot_spawn 0 +set g_balance_armor_regenstable 100 +set g_balance_armor_rotstable 100 +set g_balance_armor_limit 999 +set g_balance_armor_blockpercent 0.7 +set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)" +set g_balance_fuel_regenlinear 0 +set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter +set g_balance_fuel_rot 0.05 +set g_balance_fuel_rotlinear 0 +set g_balance_pause_fuel_rot 5 +set g_balance_pause_fuel_rot_spawn 10 +set g_balance_fuel_regenstable 50 +set g_balance_fuel_rotstable 100 +set g_balance_fuel_limit 999 +// }}} + +// {{{ misc +set g_balance_selfdamagepercent 0.65 +set g_weaponspeedfactor 1 "weapon projectile speed multiplier" +set g_weaponratefactor 1 "weapon fire rate multiplier" +set g_weapondamagefactor 1 "weapon damage multiplier" +set g_weaponforcefactor 1 "weapon force multiplier" +set g_weaponspreadfactor 1 "weapon spread multiplier" +set g_balance_firetransfer_time 0.9 +set g_balance_firetransfer_damage 0.8 +set g_throughfloor_damage 0.7 +set g_throughfloor_force 0.8 +set g_projectiles_damage 2 +// possible values: +// -2: absolutely no damage to projectiles (no exceptions) +// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines) +// 0: only damage from contents (lava/slime) or exceptions +// 1: only self damage or damage from contents or exceptions +// 2: allow all damage to projectiles normally +set g_projectiles_keep_owner 0 +set g_projectiles_newton_style 2 +// possible values: +// 0: absolute velocity projectiles (like Quake) +// 1: relative velocity projectiles, "Newtonian" (like Tribes 2) +// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard) +set g_projectiles_newton_style_2_minfactor 0.7 +set g_projectiles_newton_style_2_maxfactor 5 +set g_projectiles_spread_style 7 +// possible values: +// 0: forward + solid sphere (like Quake) - varies velocity +// 1: forward + flattened solid sphere +// 2: forward + solid circle +// 3: forward + normal distribution 3D - varies velocity +// 4: forward + normal distribution on a plane +// 5: forward + circle with 1-r falloff +// 6: forward + circle with 1-r^2 falloff +// 7: forward + circle with (1-r)(2-r) falloff +set g_balance_falldamage_deadminspeed 150 +set g_balance_falldamage_minspeed 800 +set g_balance_falldamage_factor 0.20 +set g_balance_falldamage_maxdamage 15 +set g_balance_damagepush_speedfactor 2.5 +set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage +set g_balance_contents_drowndelay 10 // time under water before a player begins drowning +set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning +set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava +set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime +set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime +set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap" +// }}} + +// {{{ powerups +set g_balance_powerup_invincible_takedamage 0.6 +set g_balance_powerup_invincible_time 30 +set g_balance_powerup_strength_damage 3 +set g_balance_powerup_strength_force 4 +set g_balance_powerup_strength_time 30 +set g_balance_powerup_strength_selfdamage 1.5 +set g_balance_powerup_strength_selfforce 1.5 +set g_balance_superweapons_time 30 +// }}} + +// {{{ jetpack/hook +set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack" +set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction" +set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)" +set g_jetpack_maxspeed_side 1500 "max speed of the jetpack in xy direction" +set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction" +set g_jetpack_fuel 8 "fuel per second for jetpack" +set g_jetpack_attenuation 2 "jetpack sound attenuation" + +set g_grappling_hook_tarzan 2 // 2: can also pull players +set g_balance_grapplehook_speed_fly 1800 +set g_balance_grapplehook_speed_pull 2000 +set g_balance_grapplehook_force_rubber 2000 +set g_balance_grapplehook_force_rubber_overstretch 1000 +set g_balance_grapplehook_length_min 50 +set g_balance_grapplehook_stretch 50 +set g_balance_grapplehook_airfriction 0.2 +set g_balance_grapplehook_health 130 +set g_balance_grapplehook_damagedbycontents 0 +set g_balance_grapplehook_refire 0.2 +// }}} + +// {{{ weapon properties +// {{{ laser +set g_balance_laser_primary_damage 20 // dps 33, hope that's not too high +set g_balance_laser_primary_edgedamage 20 +set g_balance_laser_primary_force 150 // this looks insanely low, but actually isn't with zscale and velocitybias +set g_balance_laser_primary_radius 60 +set g_balance_laser_primary_speed 5000 +set g_balance_laser_primary_spread 0 +set g_balance_laser_primary_refire 0.6 +set g_balance_laser_primary_animtime 0.4 +set g_balance_laser_primary_lifetime 5 +set g_balance_laser_primary_shotangle 0 +set g_balance_laser_primary_delay 0 +set g_balance_laser_primary_gauntlet 0 +set g_balance_laser_primary_force_zscale 2 // 300 upforce +set g_balance_laser_primary_force_velocitybias 0.3 +set g_balance_laser_primary_force_other_scale 2.5 // force 375 when pushing others around +set g_balance_laser_secondary 0 // when 1, a secondary laser mode exists +set g_balance_laser_secondary_damage 200 // dps +set g_balance_laser_secondary_edgedamage 0 +set g_balance_laser_secondary_force 1300 +set g_balance_laser_secondary_radius 60 +set g_balance_laser_secondary_speed 0 +set g_balance_laser_secondary_spread 0 +set g_balance_laser_secondary_refire 0.066 +set g_balance_laser_secondary_animtime 0.066 +set g_balance_laser_secondary_lifetime 0 +set g_balance_laser_secondary_shotangle 0 +set g_balance_laser_secondary_delay 0 +set g_balance_laser_secondary_gauntlet 1 +set g_balance_laser_secondary_force_zscale 1.25 +set g_balance_laser_secondary_force_velocitybias 0 +set g_balance_laser_secondary_force_other_scale 0 +set g_balance_laser_switchdelay_drop 0.15 +set g_balance_laser_switchdelay_raise 0.15 +set g_balance_laser_reload_ammo 0 //default: 6 +set g_balance_laser_reload_time 2 +// }}} +// {{{ shotgun +set g_balance_shotgun_primary_bullets 18 +set g_balance_shotgun_primary_damage 3.5 // LOG: changed from 4 to 3.5, total damage 63 +set g_balance_shotgun_primary_force 20 +set g_balance_shotgun_primary_spread 0.16 // LOG: changed from 0.18 -> 0.16 to compensate a little for lower damage +set g_balance_shotgun_primary_refire 1 +set g_balance_shotgun_primary_animtime 0.3 +set g_balance_shotgun_primary_ammo 1 +set g_balance_shotgun_primary_solidpenetration 3.8 +set g_balance_shotgun_secondary 1 +set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow +set g_balance_shotgun_secondary_melee_range 120 +set g_balance_shotgun_secondary_melee_swing_side 120 +set g_balance_shotgun_secondary_melee_swing_up 30 +set g_balance_shotgun_secondary_melee_time 0.15 +set g_balance_shotgun_secondary_melee_traces 10 +set g_balance_shotgun_secondary_melee_no_doubleslap 1 +set g_balance_shotgun_secondary_melee_nonplayerdamage 0 +set g_balance_shotgun_secondary_melee_multihit 1 +set g_balance_shotgun_secondary_damage 110 +set g_balance_shotgun_secondary_force 150 +set g_balance_shotgun_secondary_refire 1.1 +set g_balance_shotgun_secondary_animtime 1 +set g_balance_shotgun_switchdelay_drop 0.15 +set g_balance_shotgun_switchdelay_raise 0.15 +set g_balance_shotgun_reload_ammo 0 //default: 5 +set g_balance_shotgun_reload_time 2 +// }}} +// {{{ uzi +set g_balance_uzi_mode 1 // Activates varible spread for sustained & burst mode secondary +set g_balance_uzi_spread_min 0.02 +set g_balance_uzi_spread_max 0.3 // LOG: 0.6 -> 0.3 +set g_balance_uzi_spread_add 0.008 + +set g_balance_uzi_burst 3 // # of bullets in a burst (if set to 2 or more) +set g_balance_uzi_burst_animtime 0.45 +set g_balance_uzi_burst_refire 0.05 // refire between burst bullets +set g_balance_uzi_burst_refire2 0.45 // refire after burst +set g_balance_uzi_burst_spread 0.07 +set g_balance_uzi_burst_damage 25 +set g_balance_uzi_burst_force 50 +set g_balance_uzi_burst_ammo 3 + +set g_balance_uzi_first 1 +set g_balance_uzi_first_damage 15 / f/ LOG: 22 -> 15 +set g_balance_uzi_first_force 50 +set g_balance_uzi_first_spread 0.03 +set g_balance_uzi_first_refire 0.2 +set g_balance_uzi_first_ammo 2 + +set g_balance_uzi_sustained_damage 12 // 120 dps +set g_balance_uzi_sustained_force 12 +set g_balance_uzi_sustained_spread 0.06 +set g_balance_uzi_sustained_refire 0.1 +set g_balance_uzi_sustained_ammo 1 + +set g_balance_uzi_solidpenetration 13.1 + +set g_balance_uzi_switchdelay_drop 0.15 +set g_balance_uzi_switchdelay_raise 0.15 + +set g_balance_uzi_reload_ammo 0 //default: 30 +set g_balance_uzi_reload_time 2 +// }}} +// {{{ mortar +set g_balance_grenadelauncher_primary_type 0 +set g_balance_grenadelauncher_primary_damage 44 +set g_balance_grenadelauncher_primary_edgedamage 32 +set g_balance_grenadelauncher_primary_force 300 +set g_balance_grenadelauncher_primary_radius 115 +set g_balance_grenadelauncher_primary_speed 1500 +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_lifetime 5 +set g_balance_grenadelauncher_primary_lifetime2 0.65 +set g_balance_grenadelauncher_primary_refire 0.8 +set g_balance_grenadelauncher_primary_animtime 0.3 +set g_balance_grenadelauncher_primary_ammo 2 +set g_balance_grenadelauncher_primary_health 80 +set g_balance_grenadelauncher_primary_damageforcescale 0 +set g_balance_grenadelauncher_primary_remote_minbouncecnt 0 + +set g_balance_grenadelauncher_secondary_type 1 +set g_balance_grenadelauncher_secondary_damage 62 +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 1000 +set g_balance_grenadelauncher_secondary_speed_up 250 +set g_balance_grenadelauncher_secondary_speed_z 0 +set g_balance_grenadelauncher_secondary_spread 0 +set g_balance_grenadelauncher_secondary_lifetime 3 +set g_balance_grenadelauncher_secondary_lifetime_bounce 0 +set g_balance_grenadelauncher_secondary_lifetime_stick 0.65 +set g_balance_grenadelauncher_secondary_refire 0.8 +set g_balance_grenadelauncher_secondary_animtime 0.3 +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_remote_detonateprimary 0 + +set g_balance_grenadelauncher_bouncefactor 0.5 +set g_balance_grenadelauncher_bouncestop 0.12 + +set g_balance_grenadelauncher_switchdelay_drop 0.15 +set g_balance_grenadelauncher_switchdelay_raise 0.15 + +set g_balance_grenadelauncher_reload_ammo 0 //default: 12 +set g_balance_grenadelauncher_reload_time 2 +// }}} +// {{{ electro +set g_balance_electro_lightning 1 +set g_balance_electro_primary_damage 100 +set g_balance_electro_primary_edgedamage 0 +set g_balance_electro_primary_force 425 +set g_balance_electro_primary_force_up 125 +set g_balance_electro_primary_radius 850 +set g_balance_electro_primary_comboradius 150 +set g_balance_electro_primary_speed 0 +set g_balance_electro_primary_spread 0 +set g_balance_electro_primary_lifetime 0 +set g_balance_electro_primary_refire 0.4 +set g_balance_electro_primary_animtime 0.2 +set g_balance_electro_primary_ammo 5 +set g_balance_electro_primary_range 800 +set g_balance_electro_primary_falloff_mindist 0 +set g_balance_electro_primary_falloff_maxdist 0 +set g_balance_electro_primary_falloff_halflifedist 0 +set g_balance_electro_secondary_damage 25 +set g_balance_electro_secondary_edgedamage 0 +set g_balance_electro_secondary_force 100 +set g_balance_electro_secondary_radius 100 +set g_balance_electro_secondary_speed 700 +set g_balance_electro_secondary_speed_up 200 +set g_balance_electro_secondary_speed_z 0 +set g_balance_electro_secondary_spread 0.08 +set g_balance_electro_secondary_lifetime 3.5 +set g_balance_electro_secondary_refire 0.2 +set g_balance_electro_secondary_refire2 2 +set g_balance_electro_secondary_animtime 0.2 +set g_balance_electro_secondary_ammo 2 +set g_balance_electro_secondary_health 10 +set g_balance_electro_secondary_damageforcescale 4 +set g_balance_electro_secondary_damagedbycontents 0 +set g_balance_electro_secondary_count 3 +set g_balance_electro_secondary_bouncefactor 0.5 +set g_balance_electro_secondary_bouncestop 0.075 +set g_balance_electro_combo_damage 50 +set g_balance_electro_combo_edgedamage 0 +set g_balance_electro_combo_force 80 +set g_balance_electro_combo_radius 250 +set g_balance_electro_combo_comboradius 0 +set g_balance_electro_combo_speed 400 +set g_balance_electro_combo_safeammocheck 1 +set g_balance_electro_switchdelay_drop 0.15 +set g_balance_electro_switchdelay_raise 0.15 +set g_balance_electro_reload_ammo 0 //default: 20 +set g_balance_electro_reload_time 2 +// }}} +// {{{ crylink +set g_balance_crylink_primary_damage 7 // LOG: 10 -> 7 +set g_balance_crylink_primary_edgedamage 4 // LOG: 6 -> 4 +set g_balance_crylink_primary_force 35 +set g_balance_crylink_primary_radius 80 +set g_balance_crylink_primary_speed 1500 +set g_balance_crylink_primary_spread 0.05 +set g_balance_crylink_primary_shots 7 +set g_balance_crylink_primary_bounces 2 +set g_balance_crylink_primary_refire 0.8 +set g_balance_crylink_primary_animtime 0.3 +set g_balance_crylink_primary_ammo 2 +set g_balance_crylink_primary_bouncedamagefactor 0.2 +set g_balance_crylink_primary_joindelay 0 +set g_balance_crylink_primary_joinspread 0.2 +set g_balance_crylink_primary_joinexplode 0 +set g_balance_crylink_primary_joinexplode_damage 0 +set g_balance_crylink_primary_joinexplode_edgedamage 0 +set g_balance_crylink_primary_joinexplode_radius 0 +set g_balance_crylink_primary_joinexplode_force 0 +set g_balance_crylink_primary_linkexplode 1 + +set g_balance_crylink_primary_middle_lifetime 5 // range: 10000 full, fades to 20000 +set g_balance_crylink_primary_middle_fadetime 5 +set g_balance_crylink_primary_other_lifetime 2 // range: 800 full, fades to 1300 +set g_balance_crylink_primary_other_fadetime 0.25 + +set g_balance_crylink_secondary 1 +set g_balance_crylink_secondary_damage 5 // LOG: 8 -> 5 +set g_balance_crylink_secondary_edgedamage 3 +set g_balance_crylink_secondary_force 16 // LOG: 20 -> 16 +set g_balance_crylink_secondary_radius 15 // LOG: 20 -> 15 +set g_balance_crylink_secondary_speed 1250 // LOG: 1500 -> 1250 +set g_balance_crylink_secondary_spread 0.1 +set g_balance_crylink_secondary_spreadtype 0 +set g_balance_crylink_secondary_shots 6 +set g_balance_crylink_secondary_bounces 2 +set g_balance_crylink_secondary_refire 0.9 // LOG: 0.8 -> 0.9 +set g_balance_crylink_secondary_animtime 0.3 +set g_balance_crylink_secondary_ammo 3 // LOG: 2 -> 3 +set g_balance_crylink_secondary_bouncedamagefactor 0.4 // LOG: 0.2 -> 0.4 +set g_balance_crylink_secondary_joindelay 0 +set g_balance_crylink_secondary_joinspread 0.2 +set g_balance_crylink_secondary_joinexplode 0 +set g_balance_crylink_secondary_joinexplode_damage 0 +set g_balance_crylink_secondary_joinexplode_edgedamage 0 +set g_balance_crylink_secondary_joinexplode_radius 0 +set g_balance_crylink_secondary_joinexplode_force 0 +set g_balance_crylink_secondary_linkexplode 0 + +set g_balance_crylink_secondary_middle_lifetime 5 // range: 10000 full, fades to 10000 +set g_balance_crylink_secondary_middle_fadetime 5 +set g_balance_crylink_secondary_line_lifetime 2 // range: 4000 full, fades to 8000 +set g_balance_crylink_secondary_line_fadetime 0.25 + +set g_balance_crylink_switchdelay_drop 0.15 +set g_balance_crylink_switchdelay_raise 0.15 + +set g_balance_crylink_reload_ammo 0 //default: 10 +set g_balance_crylink_reload_time 2 +// }}} +// {{{ nex +set g_balance_nex_primary_damage 90 +set g_balance_nex_primary_force 500 +set g_balance_nex_primary_refire 1 +set g_balance_nex_primary_animtime 0.3 +set g_balance_nex_primary_ammo 5 +set g_balance_nex_primary_damagefalloff_mindist 0 +set g_balance_nex_primary_damagefalloff_maxdist 0 +set g_balance_nex_primary_damagefalloff_halflife 0 +set g_balance_nex_primary_damagefalloff_forcehalflife 0 + +set g_balance_nex_secondary 0 // LOG: disable secondary +set g_balance_nex_secondary_charge 0 // LOG: disable secondary charge +set g_balance_nex_secondary_charge_rate 0.4 +set g_balance_nex_secondary_chargepool 1 +set g_balance_nex_secondary_chargepool_regen 0.25 +set g_balance_nex_secondary_chargepool_pause_regen 2 +set g_balance_nex_secondary_chargepool_pause_health_regen 0.5 +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 0.4 // full charge pool is 1, so it depletes in 2.5 secs +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_charge 1 +set g_balance_nex_charge_mindmg 20 +set g_balance_nex_charge_start 0.5 +set g_balance_nex_charge_rate 0.5 +set g_balance_nex_charge_animlimit 0.5 +set g_balance_nex_charge_limit 1 // LOG: 0.5 -> 1 - allow to fully charge automaticaly +set g_balance_nex_charge_rot_rate 0 // LOG: 0.1 -> 0 - disable rot +set g_balance_nex_charge_rot_pause 0.5 // Dont rot down until this long after release of charge button +set g_balance_nex_charge_shot_multiplier 0 +set g_balance_nex_charge_velocity_rate 0 +set g_balance_nex_charge_minspeed 600 +set g_balance_nex_charge_maxspeed 1000 + +set g_balance_nex_switchdelay_drop 0.15 +set g_balance_nex_switchdelay_raise 0.15 + +set g_balance_nex_reload_ammo 0 //default: 25 +set g_balance_nex_reload_time 2 +// }}} +// {{{ minstanex +set g_balance_minstanex_refire 1 +set g_balance_minstanex_animtime 0.50 +set g_balance_minstanex_ammo 10 +set g_balance_minstanex_laser_ammo 0 +set g_balance_minstanex_laser_animtime 0.3 +set g_balance_minstanex_laser_refire 0.6 +set g_balance_minstanex_switchdelay_drop 0.15 +set g_balance_minstanex_switchdelay_raise 0.15 +set g_balance_minstanex_reload_ammo 0 //default: 50 +set g_balance_minstanex_reload_time 2 +// }}} +// {{{ hagar +set g_balance_hagar_primary_damage 14 +set g_balance_hagar_primary_edgedamage 6 +set g_balance_hagar_primary_force 70 +set g_balance_hagar_primary_health 0 +set g_balance_hagar_primary_damageforcescale 0 +set g_balance_hagar_primary_radius 110 +set g_balance_hagar_primary_spread 0.1 +set g_balance_hagar_primary_speed 1800 +set g_balance_hagar_primary_lifetime 5 +set g_balance_hagar_primary_refire 0.12 +set g_balance_hagar_primary_ammo 1 +set g_balance_hagar_secondary 1 +set g_balance_hagar_secondary_load 0 +set g_balance_hagar_secondary_load_speed 0.6 +set g_balance_hagar_secondary_load_spread 0.075 +set g_balance_hagar_secondary_load_spread_bias 0.5 +set g_balance_hagar_secondary_load_max 4 +set g_balance_hagar_secondary_load_hold 0 +set g_balance_hagar_secondary_load_releasedeath 1 +set g_balance_hagar_secondary_load_abort 1 +set g_balance_hagar_secondary_load_linkexplode 0 +set g_balance_hagar_secondary_load_animtime 0.2 +set g_balance_hagar_secondary_damage 14 // default for _load: 32 +set g_balance_hagar_secondary_edgedamage 6 // default for _load: 10 +set g_balance_hagar_secondary_force 70 // default for _load: 160 +set g_balance_hagar_secondary_health 0 +set g_balance_hagar_secondary_damageforcescale 0 +set g_balance_hagar_secondary_radius 125 +set g_balance_hagar_secondary_spread 0.15 // default for _load: 0.08 +set g_balance_hagar_secondary_speed 1800 +set g_balance_hagar_secondary_lifetime_min 5 +set g_balance_hagar_secondary_lifetime_rand 0 +set g_balance_hagar_secondary_refire 0.12 // default for _load: 0.8 +set g_balance_hagar_secondary_ammo 1 +set g_balance_hagar_switchdelay_drop 0.15 +set g_balance_hagar_switchdelay_raise 0.15 +set g_balance_hagar_reload_ammo 0 //default: 25 +set g_balance_hagar_reload_time 2 +// }}} +// {{{ rocketlauncher +set g_balance_rocketlauncher_damage 82 +set g_balance_rocketlauncher_edgedamage 32 +set g_balance_rocketlauncher_force 350 +set g_balance_rocketlauncher_radius 130 +set g_balance_rocketlauncher_speed 1400 +set g_balance_rocketlauncher_speedaccel 1400 +set g_balance_rocketlauncher_speedstart 800 +set g_balance_rocketlauncher_lifetime 5 +set g_balance_rocketlauncher_refire 1 +set g_balance_rocketlauncher_animtime 0.3 +set g_balance_rocketlauncher_ammo 3 +set g_balance_rocketlauncher_health 0 +set g_balance_rocketlauncher_damageforcescale 0 +set g_balance_rocketlauncher_detonatedelay 0.05 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time +set g_balance_rocketlauncher_guiderate 42 // max degrees per second +set g_balance_rocketlauncher_guideratedelay 0.01 // immediate +set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic) +set g_balance_rocketlauncher_guidedelay 0.15 // delay before guiding kicks in +set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again +set g_balance_rocketlauncher_remote_damage 60 +set g_balance_rocketlauncher_remote_edgedamage 20 +set g_balance_rocketlauncher_remote_radius 120 +set g_balance_rocketlauncher_remote_force 350 +set g_balance_rocketlauncher_switchdelay_drop 0.15 +set g_balance_rocketlauncher_switchdelay_raise 0.15 +set g_balance_rocketlauncher_reload_ammo 0 //default: 25 +set g_balance_rocketlauncher_reload_time 2 +// }}} +// {{{ porto +set g_balance_porto_primary_refire 1.5 +set g_balance_porto_primary_animtime 0.2 +set g_balance_porto_primary_speed 2000 +set g_balance_porto_primary_lifetime 5 +set g_balance_porto_secondary 0 +set g_balance_porto_secondary_refire 1.5 +set g_balance_porto_secondary_animtime 0.2 +set g_balance_porto_secondary_speed 2000 +set g_balance_porto_secondary_lifetime 5 +set g_balance_porto_switchdelay_drop 0.15 +set g_balance_porto_switchdelay_raise 0.15 +set g_balance_portal_health 200 // these get recharged whenever the portal is used +set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used +// }}} +// {{{ hook +set g_balance_hook_primary_fuel 5 // hook monkeys set 0 +set g_balance_hook_primary_refire 0.2 // hook monkeys set 0 +set g_balance_hook_primary_animtime 0.2 // good shoot anim +set g_balance_hook_primary_hooked_time_max 0 // infinite +set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free +set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked +set g_balance_hook_secondary_damage 25 // not much +set g_balance_hook_secondary_edgedamage 5 // not much +set g_balance_hook_secondary_radius 500 // LOTS +set g_balance_hook_secondary_force -2000 // LOTS +set g_balance_hook_secondary_ammo 50 // a whole pack +set g_balance_hook_secondary_lifetime 5 // infinite +set g_balance_hook_secondary_speed 0 // not much throwing +set g_balance_hook_secondary_gravity 5 // fast falling +set g_balance_hook_secondary_refire 3 // don't drop too many bombs... +set g_balance_hook_secondary_animtime 0.2 // good shoot anim +set g_balance_hook_secondary_power 3 // effect behaves like a square function +set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds +set g_balance_hook_secondary_health 0 +set g_balance_hook_secondary_damageforcescale 0 +set g_balance_hook_switchdelay_drop 0.15 +set g_balance_hook_switchdelay_raise 0.15 +// }}} +// {{{ tuba +set g_balance_tuba_refire 0.05 +set g_balance_tuba_animtime 0.05 +set g_balance_tuba_attenuation 0.5 +set g_balance_tuba_volume 1 +set g_balance_tuba_fadetime 0.25 +set g_balance_tuba_damage 5 +set g_balance_tuba_edgedamage 0 +set g_balance_tuba_radius 200 +set g_balance_tuba_force 40 +set g_balance_tuba_pitchstep 6 +set g_balance_tuba_switchdelay_drop 0.15 +set g_balance_tuba_switchdelay_raise 0.15 +// }}} +// {{{ fireball +set g_balance_fireball_primary_animtime 0.2 +set g_balance_fireball_primary_bfgdamage 100 +set g_balance_fireball_primary_bfgforce 0 +set g_balance_fireball_primary_bfgradius 1000 +set g_balance_fireball_primary_damage 200 +set g_balance_fireball_primary_damageforcescale 4 +set g_balance_fireball_primary_edgedamage 0 +set g_balance_fireball_primary_force 700 +set g_balance_fireball_primary_health 50 +set g_balance_fireball_primary_laserburntime 0.5 +set g_balance_fireball_primary_laserdamage 80 +set g_balance_fireball_primary_laseredgedamage 20 +set g_balance_fireball_primary_laserradius 256 +set g_balance_fireball_primary_lifetime 15 +set g_balance_fireball_primary_radius 200 +set g_balance_fireball_primary_refire 5 +set g_balance_fireball_primary_refire2 0 +set g_balance_fireball_primary_speed 650 +set g_balance_fireball_primary_spread 0 +set g_balance_fireball_secondary_animtime 0.2 +set g_balance_fireball_secondary_damage 40 +set g_balance_fireball_secondary_damageforcescale 4 +set g_balance_fireball_secondary_damagetime 5 +set g_balance_fireball_secondary_force 100 +set g_balance_fireball_secondary_laserburntime 0.5 +set g_balance_fireball_secondary_laserdamage 50 +set g_balance_fireball_secondary_laseredgedamage 20 +set g_balance_fireball_secondary_laserradius 110 +set g_balance_fireball_secondary_lifetime 7 +set g_balance_fireball_secondary_refire 2 +set g_balance_fireball_secondary_speed 900 +set g_balance_fireball_secondary_speed_up 100 +set g_balance_fireball_secondary_speed_z 0 +set g_balance_fireball_secondary_spread 0 +set g_balance_fireball_switchdelay_drop 0.15 +set g_balance_fireball_switchdelay_raise 0.15 +// }}} diff --git a/balanceXDF.cfg b/balanceXDF.cfg new file mode 100644 index 000000000..41d193619 --- /dev/null +++ b/balanceXDF.cfg @@ -0,0 +1,706 @@ +g_mod_balance XDF + +// {{{ starting gear +set g_start_weapon_laser 0 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_shotgun 0 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_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" +set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" // UNTIL IT CAN BE REMOVED FROM CODE +set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_balance_health_start 100 +set g_balance_armor_start 0 +set g_start_ammo_shells 15 +set g_start_ammo_nails 0 +set g_start_ammo_rockets 0 +set g_start_ammo_cells 0 +set g_start_ammo_fuel 0 +set g_warmup_start_health 100 "starting values when being in warmup-stage" +set g_warmup_start_armor 100 "starting values when being in warmup-stage" +set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage" +set g_warmup_start_ammo_nails 160 "starting values when being in warmup-stage" +set g_warmup_start_ammo_rockets 80 "starting values when being in warmup-stage" +set g_warmup_start_ammo_cells 90 "starting values when being in warmup-stage" +set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage" +set g_lms_start_health 200 +set g_lms_start_armor 200 +set g_lms_start_ammo_shells 60 +set g_lms_start_ammo_nails 320 +set g_lms_start_ammo_rockets 160 +set g_lms_start_ammo_cells 180 +set g_lms_start_ammo_fuel 0 +set g_balance_nix_roundtime 25 +set g_balance_nix_incrtime 1.6 +set g_balance_nix_ammo_shells 60 +set g_balance_nix_ammo_nails 320 +set g_balance_nix_ammo_rockets 160 +set g_balance_nix_ammo_cells 180 +set g_balance_nix_ammo_fuel 0 +set g_balance_nix_ammoincr_shells 2 // eh this will need figured out later I assume +set g_balance_nix_ammoincr_nails 6 +set g_balance_nix_ammoincr_rockets 2 +set g_balance_nix_ammoincr_cells 2 +set g_balance_nix_ammoincr_fuel 2 +// }}} + +// {{{ pickup items +set g_pickup_ammo_anyway 1 +set g_pickup_weapons_anyway 1 +set g_pickup_shells 15 +set g_pickup_shells_weapon 15 +set g_pickup_shells_max 60 +set g_pickup_nails 80 +set g_pickup_nails_weapon 80 +set g_pickup_nails_max 320 +set g_pickup_rockets 40 +set g_pickup_rockets_weapon 40 +set g_pickup_rockets_max 160 +set g_pickup_cells 30 +set g_pickup_cells_weapon 30 +set g_pickup_cells_max 180 +set g_pickup_fuel 50 +set g_pickup_fuel_weapon 50 +set g_pickup_fuel_jetpack 100 +set g_pickup_fuel_max 100 +set g_pickup_armorsmall 5 +set g_pickup_armorsmall_max 200 +set g_pickup_armorsmall_anyway 1 +set g_pickup_armormedium 25 +set g_pickup_armormedium_max 200 +set g_pickup_armormedium_anyway 1 +set g_pickup_armorbig 50 +set g_pickup_armorbig_max 200 +set g_pickup_armorbig_anyway 1 +set g_pickup_armorlarge 100 +set g_pickup_armorlarge_max 200 +set g_pickup_armorlarge_anyway 1 +set g_pickup_healthsmall 5 +set g_pickup_healthsmall_max 200 +set g_pickup_healthsmall_anyway 1 +set g_pickup_healthmedium 25 +set g_pickup_healthmedium_max 200 +set g_pickup_healthmedium_anyway 1 +set g_pickup_healthlarge 50 +set g_pickup_healthlarge_max 200 +set g_pickup_healthlarge_anyway 1 +set g_pickup_healthmega 100 +set g_pickup_healthmega_max 200 +set g_pickup_healthmega_anyway 1 +set g_pickup_respawntime_short 0.1 +set g_pickup_respawntime_medium 0.1 +set g_pickup_respawntime_long 0.1 +set g_pickup_respawntime_powerup 0.1 +set g_pickup_respawntime_weapon 0.1 +set g_pickup_respawntime_superweapon 0.1 +set g_pickup_respawntime_ammo 0.1 +set g_pickup_respawntimejitter_short 0 +set g_pickup_respawntimejitter_medium 0 +set g_pickup_respawntimejitter_long 0 +set g_pickup_respawntimejitter_powerup 30 +set g_pickup_respawntimejitter_weapon 0 +set g_pickup_respawntimejitter_superweapon 10 +set g_pickup_respawntimejitter_ammo 0 +// }}} + +// {{{ regen/rot +set g_balance_health_regen 0.08 +set g_balance_health_regenlinear 0.5 +set g_balance_pause_health_regen 5 +set g_balance_pause_health_regen_spawn 0 +set g_balance_health_rot 0.04 +set g_balance_health_rotlinear 0.75 +set g_balance_pause_health_rot 1 +set g_balance_pause_health_rot_spawn 5 +set g_balance_health_regenstable 100 +set g_balance_health_rotstable 100 +set g_balance_health_limit 999 +set g_balance_armor_regen 0 +set g_balance_armor_regenlinear 0 +set g_balance_armor_rot 0.04 +set g_balance_armor_rotlinear 0.75 +set g_balance_pause_armor_rot 1 +set g_balance_pause_armor_rot_spawn 5 +set g_balance_armor_regenstable 100 +set g_balance_armor_rotstable 100 +set g_balance_armor_limit 999 +set g_balance_armor_blockpercent 0.6 +set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)" +set g_balance_fuel_regenlinear 0 +set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter +set g_balance_fuel_rot 0.05 +set g_balance_fuel_rotlinear 0 +set g_balance_pause_fuel_rot 5 +set g_balance_pause_fuel_rot_spawn 10 +set g_balance_fuel_regenstable 50 +set g_balance_fuel_rotstable 100 +set g_balance_fuel_limit 999 +// }}} + +// {{{ misc +set g_balance_selfdamagepercent 0 +set g_weaponspeedfactor 1 "weapon projectile speed multiplier" +set g_weaponratefactor 1 "weapon fire rate multiplier" +set g_weapondamagefactor 1 "weapon damage multiplier" +set g_weaponforcefactor 1 "weapon force multiplier" +set g_weaponspreadfactor 1 "weapon spread multiplier" +set g_balance_firetransfer_time 0.9 +set g_balance_firetransfer_damage 0.8 +set g_throughfloor_damage 0.4 +set g_throughfloor_force 0.7 +set g_projectiles_damage 2 +// possible values: +// -2: absolutely no damage to projectiles (no exceptions) +// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines) +// 0: only damage from contents (lava/slime) or exceptions +// 1: only self damage or damage from contents or exceptions +// 2: allow all damage to projectiles normally +set g_projectiles_keep_owner 0 +set g_projectiles_newton_style 2 +// possible values: +// 0: absolute velocity projectiles (like Quake) +// 1: relative velocity projectiles, "Newtonian" (like Tribes 2) +// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard) +set g_projectiles_newton_style_2_minfactor 0.8 +set g_projectiles_newton_style_2_maxfactor 1.5 +set g_projectiles_spread_style 7 +// possible values: +// 0: forward + solid sphere (like Quake) - varies velocity +// 1: forward + flattened solid sphere +// 2: forward + solid circle +// 3: forward + normal distribution 3D - varies velocity +// 4: forward + normal distribution on a plane +// 5: forward + circle with 1-r falloff +// 6: forward + circle with 1-r^2 falloff +// 7: forward + circle with (1-r)(2-r) falloff +set g_balance_falldamage_deadminspeed 250 +set g_balance_falldamage_minspeed 900 +set g_balance_falldamage_factor 0.20 +set g_balance_falldamage_maxdamage 40 +set g_balance_damagepush_speedfactor 2.5 +set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage +set g_balance_contents_drowndelay 10 // time under water before a player begins drowning +set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning +set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava +set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime +set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime +set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap" +// }}} + +// {{{ powerups +set g_balance_powerup_invincible_takedamage 0.25 // only 1/4th damage is taken +set g_balance_powerup_invincible_time 999 +set g_balance_powerup_strength_damage 3 +set g_balance_powerup_strength_force 3 +set g_balance_powerup_strength_time 999 +set g_balance_powerup_strength_selfdamage 1.5 +set g_balance_powerup_strength_selfforce 1.5 +set g_balance_superweapons_time 30 +// }}} + +// {{{ jetpack/hook +set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack" +set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction" +set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)" +set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction" +set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction" +set g_jetpack_fuel 8 "fuel per second for jetpack" +set g_jetpack_attenuation 2 "jetpack sound attenuation" + +set g_grappling_hook_tarzan 2 // 2: can also pull players +set g_balance_grapplehook_speed_fly 1800 +set g_balance_grapplehook_speed_pull 2000 +set g_balance_grapplehook_force_rubber 2000 +set g_balance_grapplehook_force_rubber_overstretch 1000 +set g_balance_grapplehook_length_min 50 +set g_balance_grapplehook_stretch 50 +set g_balance_grapplehook_airfriction 0.2 +set g_balance_grapplehook_health 130 +set g_balance_grapplehook_damagedbycontents 0 +set g_balance_grapplehook_refire 0.2 +// }}} + +// {{{ weapon properties +// {{{ laser +set g_balance_laser_primary_damage 25 +set g_balance_laser_primary_edgedamage 12.5 +set g_balance_laser_primary_force 250 +set g_balance_laser_primary_radius 70 +set g_balance_laser_primary_speed 6000 +set g_balance_laser_primary_spread 0 +set g_balance_laser_primary_refire 0.7 +set g_balance_laser_primary_animtime 0.3 +set g_balance_laser_primary_lifetime 5 +set g_balance_laser_primary_shotangle 0 +set g_balance_laser_primary_delay 0 +set g_balance_laser_primary_gauntlet 0 +set g_balance_laser_primary_force_zscale 1.5 +set g_balance_laser_primary_force_velocitybias 0 +set g_balance_laser_primary_force_other_scale 1 +set g_balance_laser_secondary 0 // when 1, a secondary laser mode exists +set g_balance_laser_secondary_damage 25 +set g_balance_laser_secondary_edgedamage 12.5 +set g_balance_laser_secondary_force 400 +set g_balance_laser_secondary_radius 70 +set g_balance_laser_secondary_speed 12000 +set g_balance_laser_secondary_spread 0 +set g_balance_laser_secondary_refire 0.7 +set g_balance_laser_secondary_animtime 0.3 +set g_balance_laser_secondary_lifetime 5 +set g_balance_laser_secondary_shotangle -90 +set g_balance_laser_secondary_delay 0 +set g_balance_laser_secondary_gauntlet 0 +set g_balance_laser_secondary_force_zscale 1.25 +set g_balance_laser_secondary_force_velocitybias 0 +set g_balance_laser_secondary_force_other_scale 1 +set g_balance_laser_switchdelay_drop 0 +set g_balance_laser_switchdelay_raise 0 +set g_balance_laser_reload_ammo 0 //default: 6 +set g_balance_laser_reload_time 2 +// }}} +// {{{ shotgun +set g_balance_shotgun_primary_bullets 14 +set g_balance_shotgun_primary_damage 4 +set g_balance_shotgun_primary_force 15 +set g_balance_shotgun_primary_spread 0.12 +set g_balance_shotgun_primary_refire 0.75 +set g_balance_shotgun_primary_animtime 0.2 +set g_balance_shotgun_primary_ammo 1 +set g_balance_shotgun_primary_solidpenetration 3.8 +set g_balance_shotgun_secondary 1 +set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow +set g_balance_shotgun_secondary_melee_range 120 +set g_balance_shotgun_secondary_melee_swing_side 120 +set g_balance_shotgun_secondary_melee_swing_up 30 +set g_balance_shotgun_secondary_melee_time 0.15 +set g_balance_shotgun_secondary_melee_traces 10 +set g_balance_shotgun_secondary_melee_no_doubleslap 1 +set g_balance_shotgun_secondary_melee_nonplayerdamage 40 +set g_balance_shotgun_secondary_melee_multihit 1 +set g_balance_shotgun_secondary_damage 80 +set g_balance_shotgun_secondary_force 200 +set g_balance_shotgun_secondary_refire 1.25 +set g_balance_shotgun_secondary_animtime 1 +set g_balance_shotgun_switchdelay_drop 0 +set g_balance_shotgun_switchdelay_raise 0 +set g_balance_shotgun_reload_ammo 0 //default: 5 +set g_balance_shotgun_reload_time 2 +// }}} +// {{{ uzi +set g_balance_uzi_mode 1 // Activates varible spread for sustained & burst mode secondary +set g_balance_uzi_spread_min 0 +set g_balance_uzi_spread_max 0 +set g_balance_uzi_spread_add 0 + +set g_balance_uzi_burst 3 // # of bullets in a burst (if set to 2 or more) +set g_balance_uzi_burst_animtime 0.3 +set g_balance_uzi_burst_refire 0.06 // refire between burst bullets +set g_balance_uzi_burst_refire2 0.45 // refire after burst +set g_balance_uzi_burst_spread 0.03 +set g_balance_uzi_burst_damage 25 +set g_balance_uzi_burst_force 20 +set g_balance_uzi_burst_ammo 3 + +set g_balance_uzi_first 1 +set g_balance_uzi_first_damage 14 +set g_balance_uzi_first_force 5 +set g_balance_uzi_first_spread 0.03 +set g_balance_uzi_first_refire 0.4 +set g_balance_uzi_first_ammo 1 + +set g_balance_uzi_sustained_damage 12 +set g_balance_uzi_sustained_force 5 +set g_balance_uzi_sustained_spread 0 +set g_balance_uzi_sustained_refire 0.1 +set g_balance_uzi_sustained_ammo 1 + +set g_balance_uzi_solidpenetration 13.1 + +set g_balance_uzi_switchdelay_drop 0 +set g_balance_uzi_switchdelay_raise 0 + +set g_balance_uzi_reload_ammo 0 //default: 30 +set g_balance_uzi_reload_time 2 +// }}} +// {{{ mortar +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 250 +set g_balance_grenadelauncher_primary_radius 100 +set g_balance_grenadelauncher_primary_speed 2000 +set g_balance_grenadelauncher_primary_speed_up 200 +set g_balance_grenadelauncher_primary_speed_z 0 +set g_balance_grenadelauncher_primary_spread 0 +set g_balance_grenadelauncher_primary_lifetime 5 +set g_balance_grenadelauncher_primary_lifetime2 1 +set g_balance_grenadelauncher_primary_refire 0.7 +set g_balance_grenadelauncher_primary_animtime 0.3 +set g_balance_grenadelauncher_primary_ammo 2 +set g_balance_grenadelauncher_primary_health 0 +set g_balance_grenadelauncher_primary_damageforcescale 0 +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 30 +set g_balance_grenadelauncher_secondary_force 300 +set g_balance_grenadelauncher_secondary_radius 200 +set g_balance_grenadelauncher_secondary_speed 800 +set g_balance_grenadelauncher_secondary_speed_up 0 +set g_balance_grenadelauncher_secondary_speed_z 200 +set g_balance_grenadelauncher_secondary_spread 0 +set g_balance_grenadelauncher_secondary_lifetime 8 +set g_balance_grenadelauncher_secondary_lifetime_bounce 0.5 +set g_balance_grenadelauncher_secondary_lifetime_stick 0 +set g_balance_grenadelauncher_secondary_refire 0.7 +set g_balance_grenadelauncher_secondary_animtime 0.5 +set g_balance_grenadelauncher_secondary_ammo 2 +set g_balance_grenadelauncher_secondary_health 0 +set g_balance_grenadelauncher_secondary_damageforcescale 0 +set g_balance_grenadelauncher_secondary_remote_detonateprimary 0 + +set g_balance_grenadelauncher_bouncefactor 0.5 +set g_balance_grenadelauncher_bouncestop 0.075 + +set g_balance_grenadelauncher_switchdelay_drop 0 +set g_balance_grenadelauncher_switchdelay_raise 0 + +set g_balance_grenadelauncher_reload_ammo 0 //default: 12 +set g_balance_grenadelauncher_reload_time 2 +// }}} +// {{{ electro +set g_balance_electro_lightning 0 +set g_balance_electro_primary_damage 55 +set g_balance_electro_primary_edgedamage 27.5 +set g_balance_electro_primary_force 200 +set g_balance_electro_primary_force_up 0 +set g_balance_electro_primary_radius 100 +set g_balance_electro_primary_comboradius 150 +set g_balance_electro_primary_speed 2500 +set g_balance_electro_primary_spread 0 +set g_balance_electro_primary_lifetime 5 +set g_balance_electro_primary_refire 0.6 +set g_balance_electro_primary_animtime 0.1 +set g_balance_electro_primary_ammo 4 +set g_balance_electro_primary_range 0 +set g_balance_electro_primary_falloff_mindist 255 // 0.3 * radius +set g_balance_electro_primary_falloff_maxdist 850 +set g_balance_electro_primary_falloff_halflifedist 425 +set g_balance_electro_secondary_damage 40 +set g_balance_electro_secondary_edgedamage 20 +set g_balance_electro_secondary_force 200 +set g_balance_electro_secondary_radius 150 +set g_balance_electro_secondary_speed 900 +set g_balance_electro_secondary_speed_up 200 +set g_balance_electro_secondary_speed_z 0 +set g_balance_electro_secondary_spread 0.05 +set g_balance_electro_secondary_lifetime 3 +set g_balance_electro_secondary_refire 0.2 +set g_balance_electro_secondary_refire2 1.5 +set g_balance_electro_secondary_animtime 0.2 +set g_balance_electro_secondary_ammo 2 +set g_balance_electro_secondary_health 5 +set g_balance_electro_secondary_damageforcescale 4 +set g_balance_electro_secondary_damagedbycontents 1 +set g_balance_electro_secondary_count 3 +set g_balance_electro_secondary_bouncefactor 0.4 +set g_balance_electro_secondary_bouncestop 0.05 +set g_balance_electro_combo_damage 40 +set g_balance_electro_combo_edgedamage 20 +set g_balance_electro_combo_force 120 +set g_balance_electro_combo_radius 175 +set g_balance_electro_combo_comboradius 275 +set g_balance_electro_combo_speed 2000 +set g_balance_electro_combo_safeammocheck 1 +set g_balance_electro_switchdelay_drop 0 +set g_balance_electro_switchdelay_raise 0 +set g_balance_electro_reload_ammo 0 //default: 20 +set g_balance_electro_reload_time 2 +// }}} +// {{{ crylink +set g_balance_crylink_primary_damage 12 +set g_balance_crylink_primary_edgedamage 6 +set g_balance_crylink_primary_force -50 +set g_balance_crylink_primary_radius 80 +set g_balance_crylink_primary_speed 2000 +set g_balance_crylink_primary_spread 0.08 +set g_balance_crylink_primary_shots 6 +set g_balance_crylink_primary_bounces 1 +set g_balance_crylink_primary_refire 0.7 +set g_balance_crylink_primary_animtime 0.3 +set g_balance_crylink_primary_ammo 3 +set g_balance_crylink_primary_bouncedamagefactor 0.5 +set g_balance_crylink_primary_joindelay 0.1 +set g_balance_crylink_primary_joinspread 0.2 +set g_balance_crylink_primary_joinexplode 1 +set g_balance_crylink_primary_joinexplode_damage 0 +set g_balance_crylink_primary_joinexplode_edgedamage 0 +set g_balance_crylink_primary_joinexplode_radius 0 +set g_balance_crylink_primary_joinexplode_force 0 +set g_balance_crylink_primary_linkexplode 1 + +set g_balance_crylink_primary_middle_lifetime 5 // range: 35000 full, fades to 70000 +set g_balance_crylink_primary_middle_fadetime 5 +set g_balance_crylink_primary_other_lifetime 5 +set g_balance_crylink_primary_other_fadetime 5 + +set g_balance_crylink_secondary 1 +set g_balance_crylink_secondary_damage 10 +set g_balance_crylink_secondary_edgedamage 5 +set g_balance_crylink_secondary_force -150 +set g_balance_crylink_secondary_radius 100 +set g_balance_crylink_secondary_speed 3000 +set g_balance_crylink_secondary_spread 0.01 +set g_balance_crylink_secondary_spreadtype 1 +set g_balance_crylink_secondary_shots 5 +set g_balance_crylink_secondary_bounces 0 +set g_balance_crylink_secondary_refire 0.7 +set g_balance_crylink_secondary_animtime 0.2 +set g_balance_crylink_secondary_ammo 2 +set g_balance_crylink_secondary_bouncedamagefactor 0.5 +set g_balance_crylink_secondary_joindelay 0 +set g_balance_crylink_secondary_joinspread 0 +set g_balance_crylink_secondary_joinexplode 0 +set g_balance_crylink_secondary_joinexplode_damage 0 +set g_balance_crylink_secondary_joinexplode_edgedamage 0 +set g_balance_crylink_secondary_joinexplode_radius 0 +set g_balance_crylink_secondary_joinexplode_force 0 +set g_balance_crylink_secondary_linkexplode 1 + +set g_balance_crylink_secondary_middle_lifetime 5 // range: 35000 full, fades to 70000 +set g_balance_crylink_secondary_middle_fadetime 5 +set g_balance_crylink_secondary_line_lifetime 5 +set g_balance_crylink_secondary_line_fadetime 5 + +set g_balance_crylink_switchdelay_drop 0 +set g_balance_crylink_switchdelay_raise 0 + +set g_balance_crylink_reload_ammo 0 //default: 10 +set g_balance_crylink_reload_time 2 +// }}} +// {{{ nex +set g_balance_nex_primary_damage 90 +set g_balance_nex_primary_force 400 +set g_balance_nex_primary_refire 1.5 +set g_balance_nex_primary_animtime 0.4 +set g_balance_nex_primary_ammo 6 +set g_balance_nex_primary_damagefalloff_mindist 0 // 1000 For tZork ;3 +set g_balance_nex_primary_damagefalloff_maxdist 0 // 3000 +set g_balance_nex_primary_damagefalloff_halflife 0 // 1500 +set g_balance_nex_primary_damagefalloff_forcehalflife 0 // 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_chargepool 0 +set g_balance_nex_secondary_chargepool_regen 0.15 +set g_balance_nex_secondary_chargepool_pause_regen 1 +set g_balance_nex_secondary_chargepool_pause_health_regen 1 +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 2 +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_charge 1 +set g_balance_nex_charge_mindmg 40 +set g_balance_nex_charge_start 0.5 +set g_balance_nex_charge_rate 0.4 +set g_balance_nex_charge_animlimit 0.5 +set g_balance_nex_charge_limit 1 +set g_balance_nex_charge_rot_rate 0 +set g_balance_nex_charge_rot_pause 0 // Dont rot down untill this long after release of charge button +set g_balance_nex_charge_shot_multiplier 0 +set g_balance_nex_charge_velocity_rate 0 +set g_balance_nex_charge_minspeed 400 +set g_balance_nex_charge_maxspeed 800 + +set g_balance_nex_switchdelay_drop 0 +set g_balance_nex_switchdelay_raise 0 + +set g_balance_nex_reload_ammo 0 //default: 25 +set g_balance_nex_reload_time 2 +// }}} +// {{{ minstanex +set g_balance_minstanex_refire 1 +set g_balance_minstanex_animtime 0.3 +set g_balance_minstanex_ammo 10 +set g_balance_minstanex_laser_ammo 0 +set g_balance_minstanex_laser_animtime 0.3 +set g_balance_minstanex_laser_refire 0.7 +set g_balance_minstanex_switchdelay_drop 0 +set g_balance_minstanex_switchdelay_raise 0 +set g_balance_minstanex_reload_ammo 0 //default: 50 +set g_balance_minstanex_reload_time 2 +// }}} +// {{{ hagar +set g_balance_hagar_primary_damage 25 +set g_balance_hagar_primary_edgedamage 12.5 +set g_balance_hagar_primary_force 92 +set g_balance_hagar_primary_health 15 +set g_balance_hagar_primary_damageforcescale 0 +set g_balance_hagar_primary_radius 25 +set g_balance_hagar_primary_spread 0.03 +set g_balance_hagar_primary_speed 2000 +set g_balance_hagar_primary_lifetime 5 +set g_balance_hagar_primary_refire 0.11 +set g_balance_hagar_primary_ammo 1 +set g_balance_hagar_secondary 0 +set g_balance_hagar_secondary_load 1 +set g_balance_hagar_secondary_load_speed 0.5 +set g_balance_hagar_secondary_load_spread 0.075 +set g_balance_hagar_secondary_load_spread_bias 0.5 +set g_balance_hagar_secondary_load_max 4 +set g_balance_hagar_secondary_load_hold 4 +set g_balance_hagar_secondary_load_releasedeath 0 +set g_balance_hagar_secondary_load_abort 0 +set g_balance_hagar_secondary_load_linkexplode 0 +set g_balance_hagar_secondary_load_animtime 0.2 +set g_balance_hagar_secondary_damage 40 +set g_balance_hagar_secondary_edgedamage 20 +set g_balance_hagar_secondary_force 75 +set g_balance_hagar_secondary_health 15 +set g_balance_hagar_secondary_damageforcescale 0 +set g_balance_hagar_secondary_radius 80 +set g_balance_hagar_secondary_spread 0.05 +set g_balance_hagar_secondary_speed 2000 +set g_balance_hagar_secondary_lifetime_min 10 +set g_balance_hagar_secondary_lifetime_rand 0 +set g_balance_hagar_secondary_refire 0.5 +set g_balance_hagar_secondary_ammo 1 +set g_balance_hagar_switchdelay_drop 0 +set g_balance_hagar_switchdelay_raise 0 +set g_balance_hagar_reload_ammo 0 //default: 25 +set g_balance_hagar_reload_time 2 +// }}} +// {{{ rocketlauncher +set g_balance_rocketlauncher_damage 80 +set g_balance_rocketlauncher_edgedamage 40 +set g_balance_rocketlauncher_force 350 +set g_balance_rocketlauncher_radius 110 +set g_balance_rocketlauncher_speed 1000 +set g_balance_rocketlauncher_speedaccel 0 +set g_balance_rocketlauncher_speedstart 1000 +set g_balance_rocketlauncher_lifetime 100 +set g_balance_rocketlauncher_refire 0.9 +set g_balance_rocketlauncher_animtime 0.7 +set g_balance_rocketlauncher_ammo 4 +set g_balance_rocketlauncher_health 0 // 30 // 5 hitpoints above maximum laser value -- this way lasers can't blow it up, but grenadelauncher still can most the time. +set g_balance_rocketlauncher_damageforcescale 0 // low damage force scale so that it can still be affected by other hits, but not so much that it does a 90 degree turn +set g_balance_rocketlauncher_detonatedelay 999 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time +set g_balance_rocketlauncher_guiderate 0 // max degrees per second +set g_balance_rocketlauncher_guideratedelay 0.01 // immediate +set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic) +set g_balance_rocketlauncher_guidedelay 0.2 // delay before guiding kicks in +set g_balance_rocketlauncher_guidestop 1 // stop guiding when firing again +set g_balance_rocketlauncher_remote_damage 70 +set g_balance_rocketlauncher_remote_edgedamage 35 +set g_balance_rocketlauncher_remote_radius 110 +set g_balance_rocketlauncher_remote_force 350 +set g_balance_rocketlauncher_switchdelay_drop 0 +set g_balance_rocketlauncher_switchdelay_raise 0 +set g_balance_rocketlauncher_reload_ammo 0 //default: 25 +set g_balance_rocketlauncher_reload_time 2 +// }}} +// {{{ porto +set g_balance_porto_primary_refire 1.5 +set g_balance_porto_primary_animtime 0.3 +set g_balance_porto_primary_speed 5000 +set g_balance_porto_primary_lifetime 5 +set g_balance_porto_secondary 1 +set g_balance_porto_secondary_refire 1.5 +set g_balance_porto_secondary_animtime 0.3 +set g_balance_porto_secondary_speed 1000 +set g_balance_porto_secondary_lifetime 5 +set g_balance_porto_switchdelay_drop 0 +set g_balance_porto_switchdelay_raise 0 +set g_balance_portal_health 200 // these get recharged whenever the portal is used +set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used +// }}} +// {{{ hook +set g_balance_hook_primary_fuel 5 // hook monkeys set 0 +set g_balance_hook_primary_refire 0.2 // hook monkeys set 0 +set g_balance_hook_primary_animtime 0.3 // good shoot anim +set g_balance_hook_primary_hooked_time_max 0 // infinite +set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free +set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked +set g_balance_hook_secondary_damage 25 // not much +set g_balance_hook_secondary_edgedamage 5 // not much +set g_balance_hook_secondary_radius 500 // LOTS +set g_balance_hook_secondary_force -2000 // LOTS +set g_balance_hook_secondary_ammo 50 // a whole pack +set g_balance_hook_secondary_lifetime 5 // infinite +set g_balance_hook_secondary_speed 0 // not much throwing +set g_balance_hook_secondary_gravity 5 // fast falling +set g_balance_hook_secondary_refire 3 // don't drop too many bombs... +set g_balance_hook_secondary_animtime 0.3 // good shoot anim +set g_balance_hook_secondary_power 3 // effect behaves like a square function +set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds +set g_balance_hook_secondary_health 15 +set g_balance_hook_secondary_damageforcescale 0 +set g_balance_hook_switchdelay_drop 0 +set g_balance_hook_switchdelay_raise 0 +// }}} +// {{{ tuba +set g_balance_tuba_refire 0.05 +set g_balance_tuba_animtime 0.05 +set g_balance_tuba_attenuation 0.5 +set g_balance_tuba_volume 1 +set g_balance_tuba_fadetime 0.25 +set g_balance_tuba_damage 5 +set g_balance_tuba_edgedamage 0 +set g_balance_tuba_radius 200 +set g_balance_tuba_force 40 +set g_balance_tuba_pitchstep 6 +set g_balance_tuba_switchdelay_drop 0 +set g_balance_tuba_switchdelay_raise 0 +// }}} +// {{{ fireball // this is a superweapon -- lets make it behave as one. +set g_balance_fireball_primary_animtime 0.2 +set g_balance_fireball_primary_bfgdamage 100 +set g_balance_fireball_primary_bfgforce 0 +set g_balance_fireball_primary_bfgradius 1000 +set g_balance_fireball_primary_damage 200 +set g_balance_fireball_primary_damageforcescale 0 +set g_balance_fireball_primary_edgedamage 50 +set g_balance_fireball_primary_force 600 +set g_balance_fireball_primary_health 0 +set g_balance_fireball_primary_laserburntime 0.5 +set g_balance_fireball_primary_laserdamage 80 +set g_balance_fireball_primary_laseredgedamage 20 +set g_balance_fireball_primary_laserradius 256 +set g_balance_fireball_primary_lifetime 15 +set g_balance_fireball_primary_radius 200 +set g_balance_fireball_primary_refire 2 +set g_balance_fireball_primary_refire2 0 +set g_balance_fireball_primary_speed 1200 +set g_balance_fireball_primary_spread 0 +set g_balance_fireball_secondary_animtime 0.3 +set g_balance_fireball_secondary_damage 40 +set g_balance_fireball_secondary_damageforcescale 4 +set g_balance_fireball_secondary_damagetime 5 +set g_balance_fireball_secondary_force 100 +set g_balance_fireball_secondary_laserburntime 0.5 +set g_balance_fireball_secondary_laserdamage 50 +set g_balance_fireball_secondary_laseredgedamage 20 +set g_balance_fireball_secondary_laserradius 110 +set g_balance_fireball_secondary_lifetime 7 +set g_balance_fireball_secondary_refire 1.5 +set g_balance_fireball_secondary_speed 900 +set g_balance_fireball_secondary_speed_up 100 +set g_balance_fireball_secondary_speed_z 0 +set g_balance_fireball_secondary_spread 0 +set g_balance_fireball_switchdelay_drop 0 +set g_balance_fireball_switchdelay_raise 0 +// }}} diff --git a/balanceXPM.cfg b/balanceXPM.cfg new file mode 100644 index 000000000..f560aee10 --- /dev/null +++ b/balanceXPM.cfg @@ -0,0 +1,706 @@ +g_mod_balance XPM + +// {{{ starting gear +set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" // UNTIL IT CAN BE REMOVED FROM CODE +set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" +set g_balance_health_start 100 +set g_balance_armor_start 0 +set g_start_ammo_shells 15 +set g_start_ammo_nails 0 +set g_start_ammo_rockets 0 +set g_start_ammo_cells 0 +set g_start_ammo_fuel 0 +set g_warmup_start_health 100 "starting values when being in warmup-stage" +set g_warmup_start_armor 100 "starting values when being in warmup-stage" +set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage" +set g_warmup_start_ammo_nails 160 "starting values when being in warmup-stage" +set g_warmup_start_ammo_rockets 80 "starting values when being in warmup-stage" +set g_warmup_start_ammo_cells 90 "starting values when being in warmup-stage" +set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage" +set g_lms_start_health 200 +set g_lms_start_armor 200 +set g_lms_start_ammo_shells 60 +set g_lms_start_ammo_nails 320 +set g_lms_start_ammo_rockets 160 +set g_lms_start_ammo_cells 180 +set g_lms_start_ammo_fuel 0 +set g_balance_nix_roundtime 25 +set g_balance_nix_incrtime 1.6 +set g_balance_nix_ammo_shells 60 +set g_balance_nix_ammo_nails 320 +set g_balance_nix_ammo_rockets 160 +set g_balance_nix_ammo_cells 180 +set g_balance_nix_ammo_fuel 0 +set g_balance_nix_ammoincr_shells 2 // eh this will need figured out later I assume +set g_balance_nix_ammoincr_nails 6 +set g_balance_nix_ammoincr_rockets 2 +set g_balance_nix_ammoincr_cells 2 +set g_balance_nix_ammoincr_fuel 2 +// }}} + +// {{{ pickup items +set g_pickup_ammo_anyway 1 +set g_pickup_weapons_anyway 1 +set g_pickup_shells 15 +set g_pickup_shells_weapon 15 +set g_pickup_shells_max 60 +set g_pickup_nails 80 +set g_pickup_nails_weapon 80 +set g_pickup_nails_max 320 +set g_pickup_rockets 40 +set g_pickup_rockets_weapon 40 +set g_pickup_rockets_max 160 +set g_pickup_cells 30 +set g_pickup_cells_weapon 30 +set g_pickup_cells_max 180 +set g_pickup_fuel 50 +set g_pickup_fuel_weapon 50 +set g_pickup_fuel_jetpack 100 +set g_pickup_fuel_max 100 +set g_pickup_armorsmall 5 +set g_pickup_armorsmall_max 200 +set g_pickup_armorsmall_anyway 0 +set g_pickup_armormedium 25 +set g_pickup_armormedium_max 100 +set g_pickup_armormedium_anyway 0 +set g_pickup_armorbig 50 +set g_pickup_armorbig_max 100 +set g_pickup_armorbig_anyway 0 +set g_pickup_armorlarge 100 +set g_pickup_armorlarge_max 200 +set g_pickup_armorlarge_anyway 0 +set g_pickup_healthsmall 5 +set g_pickup_healthsmall_max 200 +set g_pickup_healthsmall_anyway 0 +set g_pickup_healthmedium 25 +set g_pickup_healthmedium_max 100 +set g_pickup_healthmedium_anyway 0 +set g_pickup_healthlarge 50 +set g_pickup_healthlarge_max 100 +set g_pickup_healthlarge_anyway 0 +set g_pickup_healthmega 100 +set g_pickup_healthmega_max 200 +set g_pickup_healthmega_anyway 0 +set g_pickup_respawntime_short 15 +set g_pickup_respawntime_medium 20 +set g_pickup_respawntime_long 30 +set g_pickup_respawntime_powerup 120 +set g_pickup_respawntime_weapon 10 +set g_pickup_respawntime_superweapon 120 +set g_pickup_respawntime_ammo 15 +set g_pickup_respawntimejitter_short 0 +set g_pickup_respawntimejitter_medium 0 +set g_pickup_respawntimejitter_long 0 +set g_pickup_respawntimejitter_powerup 30 +set g_pickup_respawntimejitter_weapon 0 +set g_pickup_respawntimejitter_superweapon 10 +set g_pickup_respawntimejitter_ammo 0 +// }}} + +// {{{ regen/rot +set g_balance_health_regen 0.08 +set g_balance_health_regenlinear 0.5 +set g_balance_pause_health_regen 5 +set g_balance_pause_health_regen_spawn 0 +set g_balance_health_rot 0.03 +set g_balance_health_rotlinear 0.75 +set g_balance_pause_health_rot 1 +set g_balance_pause_health_rot_spawn 5 +set g_balance_health_regenstable 100 +set g_balance_health_rotstable 100 +set g_balance_health_limit 999 +set g_balance_armor_regen 0 +set g_balance_armor_regenlinear 0 +set g_balance_armor_rot 0.03 +set g_balance_armor_rotlinear 0.75 +set g_balance_pause_armor_rot 1 +set g_balance_pause_armor_rot_spawn 5 +set g_balance_armor_regenstable 100 +set g_balance_armor_rotstable 100 +set g_balance_armor_limit 999 +set g_balance_armor_blockpercent 0.6 +set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)" +set g_balance_fuel_regenlinear 0 +set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter +set g_balance_fuel_rot 0.05 +set g_balance_fuel_rotlinear 0 +set g_balance_pause_fuel_rot 5 +set g_balance_pause_fuel_rot_spawn 10 +set g_balance_fuel_regenstable 50 +set g_balance_fuel_rotstable 100 +set g_balance_fuel_limit 999 +// }}} + +// {{{ misc +set g_balance_selfdamagepercent 0.65 +set g_weaponspeedfactor 1 "weapon projectile speed multiplier" +set g_weaponratefactor 1 "weapon fire rate multiplier" +set g_weapondamagefactor 1 "weapon damage multiplier" +set g_weaponforcefactor 1 "weapon force multiplier" +set g_weaponspreadfactor 1 "weapon spread multiplier" +set g_balance_firetransfer_time 0.9 +set g_balance_firetransfer_damage 0.8 +set g_throughfloor_damage 0.75 +set g_throughfloor_force 0.75 +set g_projectiles_damage 1 +// possible values: +// -2: absolutely no damage to projectiles (no exceptions) +// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines) +// 0: only damage from contents (lava/slime) or exceptions +// 1: only self damage or damage from contents or exceptions +// 2: allow all damage to projectiles normally +set g_projectiles_keep_owner 0 +set g_projectiles_newton_style 0 +// possible values: +// 0: absolute velocity projectiles (like Quake) +// 1: relative velocity projectiles, "Newtonian" (like Tribes 2) +// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard) +set g_projectiles_newton_style_2_minfactor 0.8 +set g_projectiles_newton_style_2_maxfactor 1.5 +set g_projectiles_spread_style 7 +// possible values: +// 0: forward + solid sphere (like Quake) - varies velocity +// 1: forward + flattened solid sphere +// 2: forward + solid circle +// 3: forward + normal distribution 3D - varies velocity +// 4: forward + normal distribution on a plane +// 5: forward + circle with 1-r falloff +// 6: forward + circle with 1-r^2 falloff +// 7: forward + circle with (1-r)(2-r) falloff +set g_balance_falldamage_deadminspeed 250 +set g_balance_falldamage_minspeed 900 +set g_balance_falldamage_factor 0.20 +set g_balance_falldamage_maxdamage 40 +set g_balance_damagepush_speedfactor 2.5 +set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage +set g_balance_contents_drowndelay 10 // time under water before a player begins drowning +set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning +set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava +set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime +set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime +set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap" +// }}} + +// {{{ powerups +set g_balance_powerup_invincible_takedamage 0.25 // only 1/4th damage is taken +set g_balance_powerup_invincible_time 30 +set g_balance_powerup_strength_damage 3 +set g_balance_powerup_strength_force 3 +set g_balance_powerup_strength_time 30 +set g_balance_powerup_strength_selfdamage 1.5 +set g_balance_powerup_strength_selfforce 1.5 +set g_balance_superweapons_time 30 +// }}} + +// {{{ jetpack/hook +set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack" +set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction" +set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)" +set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction" +set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction" +set g_jetpack_fuel 8 "fuel per second for jetpack" +set g_jetpack_attenuation 2 "jetpack sound attenuation" + +set g_grappling_hook_tarzan 2 // 2: can also pull players +set g_balance_grapplehook_speed_fly 1800 +set g_balance_grapplehook_speed_pull 2000 +set g_balance_grapplehook_force_rubber 2000 +set g_balance_grapplehook_force_rubber_overstretch 1000 +set g_balance_grapplehook_length_min 50 +set g_balance_grapplehook_stretch 50 +set g_balance_grapplehook_airfriction 0.2 +set g_balance_grapplehook_health 50 +set g_balance_grapplehook_damagedbycontents 1 +set g_balance_grapplehook_refire 0.2 +// }}} + +// {{{ weapon properties +// {{{ laser +set g_balance_laser_primary_damage 25 +set g_balance_laser_primary_edgedamage 12.5 +set g_balance_laser_primary_force 300 +set g_balance_laser_primary_radius 70 +set g_balance_laser_primary_speed 6000 +set g_balance_laser_primary_spread 0 +set g_balance_laser_primary_refire 0.7 +set g_balance_laser_primary_animtime 0.2 +set g_balance_laser_primary_lifetime 5 +set g_balance_laser_primary_shotangle 0 +set g_balance_laser_primary_delay 0 +set g_balance_laser_primary_gauntlet 0 +set g_balance_laser_primary_force_zscale 1.2 +set g_balance_laser_primary_force_velocitybias 0 +set g_balance_laser_primary_force_other_scale 1 +set g_balance_laser_secondary 0 // when 1, a secondary laser mode exists +set g_balance_laser_secondary_damage 25 +set g_balance_laser_secondary_edgedamage 12.5 +set g_balance_laser_secondary_force 400 +set g_balance_laser_secondary_radius 70 +set g_balance_laser_secondary_speed 12000 +set g_balance_laser_secondary_spread 0 +set g_balance_laser_secondary_refire 0.7 +set g_balance_laser_secondary_animtime 0.2 +set g_balance_laser_secondary_lifetime 5 +set g_balance_laser_secondary_shotangle -90 +set g_balance_laser_secondary_delay 0 +set g_balance_laser_secondary_gauntlet 0 +set g_balance_laser_secondary_force_zscale 1.25 +set g_balance_laser_secondary_force_velocitybias 0 +set g_balance_laser_secondary_force_other_scale 1 +set g_balance_laser_switchdelay_drop 0.15 +set g_balance_laser_switchdelay_raise 0.15 +set g_balance_laser_reload_ammo 0 //default: 6 +set g_balance_laser_reload_time 2 +// }}} +// {{{ shotgun +set g_balance_shotgun_primary_bullets 14 +set g_balance_shotgun_primary_damage 4 +set g_balance_shotgun_primary_force 15 +set g_balance_shotgun_primary_spread 0.12 +set g_balance_shotgun_primary_refire 0.75 +set g_balance_shotgun_primary_animtime 0.2 +set g_balance_shotgun_primary_ammo 1 +set g_balance_shotgun_primary_solidpenetration 3.8 +set g_balance_shotgun_secondary 1 +set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow +set g_balance_shotgun_secondary_melee_range 120 +set g_balance_shotgun_secondary_melee_swing_side 120 +set g_balance_shotgun_secondary_melee_swing_up 30 +set g_balance_shotgun_secondary_melee_time 0.15 +set g_balance_shotgun_secondary_melee_traces 10 +set g_balance_shotgun_secondary_melee_no_doubleslap 1 +set g_balance_shotgun_secondary_melee_nonplayerdamage 40 +set g_balance_shotgun_secondary_melee_multihit 1 +set g_balance_shotgun_secondary_damage 80 +set g_balance_shotgun_secondary_force 200 +set g_balance_shotgun_secondary_refire 1.25 +set g_balance_shotgun_secondary_animtime 1 +set g_balance_shotgun_switchdelay_drop 0.2 +set g_balance_shotgun_switchdelay_raise 0.2 +set g_balance_shotgun_reload_ammo 0 //default: 5 +set g_balance_shotgun_reload_time 2 +// }}} +// {{{ uzi +set g_balance_uzi_mode 1 // Activates varible spread for sustained & burst mode secondary +set g_balance_uzi_spread_min 0.02 +set g_balance_uzi_spread_max 0.05 +set g_balance_uzi_spread_add 0.012 + +set g_balance_uzi_burst 3 // # of bullets in a burst (if set to 2 or more) +set g_balance_uzi_burst_animtime 0.3 +set g_balance_uzi_burst_refire 0.06 // refire between burst bullets +set g_balance_uzi_burst_refire2 0.45 // refire after burst +set g_balance_uzi_burst_spread 0.02 +set g_balance_uzi_burst_damage 25 +set g_balance_uzi_burst_force 20 +set g_balance_uzi_burst_ammo 3 + +set g_balance_uzi_first 1 +set g_balance_uzi_first_damage 14 +set g_balance_uzi_first_force 5 +set g_balance_uzi_first_spread 0.03 +set g_balance_uzi_first_refire 0.125 +set g_balance_uzi_first_ammo 1 + +set g_balance_uzi_sustained_damage 10 // 100 dps +set g_balance_uzi_sustained_force 5 +set g_balance_uzi_sustained_spread 0.03 +set g_balance_uzi_sustained_refire 0.1 +set g_balance_uzi_sustained_ammo 1 + +set g_balance_uzi_solidpenetration 13.1 + +set g_balance_uzi_switchdelay_drop 0.2 +set g_balance_uzi_switchdelay_raise 0.2 + +set g_balance_uzi_reload_ammo 60 //default: 30 +set g_balance_uzi_reload_time 2 +// }}} +// {{{ mortar +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 250 +set g_balance_grenadelauncher_primary_radius 120 +set g_balance_grenadelauncher_primary_speed 1900 +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_lifetime 5 +set g_balance_grenadelauncher_primary_lifetime2 1 +set g_balance_grenadelauncher_primary_refire 0.8 +set g_balance_grenadelauncher_primary_animtime 0.3 +set g_balance_grenadelauncher_primary_ammo 2 +set g_balance_grenadelauncher_primary_health 15 +set g_balance_grenadelauncher_primary_damageforcescale 0 +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 30 +set g_balance_grenadelauncher_secondary_force 250 +set g_balance_grenadelauncher_secondary_radius 120 +set g_balance_grenadelauncher_secondary_speed 1400 +set g_balance_grenadelauncher_secondary_speed_up 150 +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_lifetime_bounce 0.5 +set g_balance_grenadelauncher_secondary_lifetime_stick 0 +set g_balance_grenadelauncher_secondary_refire 0.7 +set g_balance_grenadelauncher_secondary_animtime 0.3 +set g_balance_grenadelauncher_secondary_ammo 2 +set g_balance_grenadelauncher_secondary_health 30 +set g_balance_grenadelauncher_secondary_damageforcescale 4 +set g_balance_grenadelauncher_secondary_remote_detonateprimary 0 + +set g_balance_grenadelauncher_bouncefactor 0.5 +set g_balance_grenadelauncher_bouncestop 0.075 + +set g_balance_grenadelauncher_switchdelay_drop 0.2 +set g_balance_grenadelauncher_switchdelay_raise 0.2 + +set g_balance_grenadelauncher_reload_ammo 0 //default: 12 +set g_balance_grenadelauncher_reload_time 2 +// }}} +// {{{ electro +set g_balance_electro_lightning 0 +set g_balance_electro_primary_damage 40 +set g_balance_electro_primary_edgedamage 20 +set g_balance_electro_primary_force 200 +set g_balance_electro_primary_force_up 0 +set g_balance_electro_primary_radius 100 +set g_balance_electro_primary_comboradius 300 +set g_balance_electro_primary_speed 2500 +set g_balance_electro_primary_spread 0 +set g_balance_electro_primary_lifetime 5 +set g_balance_electro_primary_refire 0.6 +set g_balance_electro_primary_animtime 0.3 +set g_balance_electro_primary_ammo 4 +set g_balance_electro_primary_range 0 +set g_balance_electro_primary_falloff_mindist 255 // 0.3 * radius +set g_balance_electro_primary_falloff_maxdist 850 +set g_balance_electro_primary_falloff_halflifedist 425 +set g_balance_electro_secondary_damage 40 +set g_balance_electro_secondary_edgedamage 20 +set g_balance_electro_secondary_force 50 +set g_balance_electro_secondary_radius 150 +set g_balance_electro_secondary_speed 1000 +set g_balance_electro_secondary_speed_up 200 +set g_balance_electro_secondary_speed_z 0 +set g_balance_electro_secondary_spread 0.04 +set g_balance_electro_secondary_lifetime 4 +set g_balance_electro_secondary_refire 0.2 +set g_balance_electro_secondary_refire2 1.6 +set g_balance_electro_secondary_animtime 0.2 +set g_balance_electro_secondary_ammo 2 +set g_balance_electro_secondary_health 5 +set g_balance_electro_secondary_damageforcescale 4 +set g_balance_electro_secondary_damagedbycontents 1 +set g_balance_electro_secondary_count 3 +set g_balance_electro_secondary_bouncefactor 0.3 +set g_balance_electro_secondary_bouncestop 0.05 +set g_balance_electro_combo_damage 50 +set g_balance_electro_combo_edgedamage 25 +set g_balance_electro_combo_force 120 +set g_balance_electro_combo_radius 150 +set g_balance_electro_combo_comboradius 300 +set g_balance_electro_combo_speed 2000 +set g_balance_electro_combo_safeammocheck 1 +set g_balance_electro_switchdelay_drop 0.2 +set g_balance_electro_switchdelay_raise 0.2 +set g_balance_electro_reload_ammo 0 //default: 20 +set g_balance_electro_reload_time 2 +// }}} +// {{{ crylink +set g_balance_crylink_primary_damage 12 +set g_balance_crylink_primary_edgedamage 6 +set g_balance_crylink_primary_force -50 +set g_balance_crylink_primary_radius 80 +set g_balance_crylink_primary_speed 2000 +set g_balance_crylink_primary_spread 0.08 +set g_balance_crylink_primary_shots 6 +set g_balance_crylink_primary_bounces 1 +set g_balance_crylink_primary_refire 0.7 +set g_balance_crylink_primary_animtime 0.3 +set g_balance_crylink_primary_ammo 3 +set g_balance_crylink_primary_bouncedamagefactor 0.5 +set g_balance_crylink_primary_joindelay 0.1 +set g_balance_crylink_primary_joinspread 0.2 +set g_balance_crylink_primary_joinexplode 1 +set g_balance_crylink_primary_joinexplode_damage 0 +set g_balance_crylink_primary_joinexplode_edgedamage 0 +set g_balance_crylink_primary_joinexplode_radius 0 +set g_balance_crylink_primary_joinexplode_force 0 +set g_balance_crylink_primary_linkexplode 1 + +set g_balance_crylink_primary_middle_lifetime 5 // range: 35000 full, fades to 70000 +set g_balance_crylink_primary_middle_fadetime 5 +set g_balance_crylink_primary_other_lifetime 5 +set g_balance_crylink_primary_other_fadetime 5 + +set g_balance_crylink_secondary 1 +set g_balance_crylink_secondary_damage 10 +set g_balance_crylink_secondary_edgedamage 5 +set g_balance_crylink_secondary_force -250 +set g_balance_crylink_secondary_radius 100 +set g_balance_crylink_secondary_speed 3000 +set g_balance_crylink_secondary_spread 0.01 +set g_balance_crylink_secondary_spreadtype 1 +set g_balance_crylink_secondary_shots 5 +set g_balance_crylink_secondary_bounces 0 +set g_balance_crylink_secondary_refire 0.7 +set g_balance_crylink_secondary_animtime 0.2 +set g_balance_crylink_secondary_ammo 2 +set g_balance_crylink_secondary_bouncedamagefactor 0.5 +set g_balance_crylink_secondary_joindelay 0 +set g_balance_crylink_secondary_joinspread 0 +set g_balance_crylink_secondary_joinexplode 0 +set g_balance_crylink_secondary_joinexplode_damage 0 +set g_balance_crylink_secondary_joinexplode_edgedamage 0 +set g_balance_crylink_secondary_joinexplode_radius 0 +set g_balance_crylink_secondary_joinexplode_force 0 +set g_balance_crylink_secondary_linkexplode 1 + +set g_balance_crylink_secondary_middle_lifetime 5 // range: 35000 full, fades to 70000 +set g_balance_crylink_secondary_middle_fadetime 5 +set g_balance_crylink_secondary_line_lifetime 5 +set g_balance_crylink_secondary_line_fadetime 5 + +set g_balance_crylink_switchdelay_drop 0.2 +set g_balance_crylink_switchdelay_raise 0.2 + +set g_balance_crylink_reload_ammo 0 //default: 10 +set g_balance_crylink_reload_time 2 +// }}} +// {{{ nex +set g_balance_nex_primary_damage 80 +set g_balance_nex_primary_force 400 +set g_balance_nex_primary_refire 1.5 +set g_balance_nex_primary_animtime 0.6 +set g_balance_nex_primary_ammo 6 +set g_balance_nex_primary_damagefalloff_mindist 0 // 1000 For tZork ;3 +set g_balance_nex_primary_damagefalloff_maxdist 0 // 3000 +set g_balance_nex_primary_damagefalloff_halflife 0 // 1500 +set g_balance_nex_primary_damagefalloff_forcehalflife 0 // 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_chargepool 0 +set g_balance_nex_secondary_chargepool_regen 0.15 +set g_balance_nex_secondary_chargepool_pause_regen 1 +set g_balance_nex_secondary_chargepool_pause_health_regen 1 +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 2 +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_charge 1 +set g_balance_nex_charge_mindmg 40 +set g_balance_nex_charge_start 0.5 +set g_balance_nex_charge_rate 0.4 +set g_balance_nex_charge_animlimit 0.5 +set g_balance_nex_charge_limit 1 +set g_balance_nex_charge_rot_rate 0 +set g_balance_nex_charge_rot_pause 0 // Dont rot down until this long after release of charge button +set g_balance_nex_charge_shot_multiplier 0 +set g_balance_nex_charge_velocity_rate 0 +set g_balance_nex_charge_minspeed 400 +set g_balance_nex_charge_maxspeed 800 + +set g_balance_nex_switchdelay_drop 0.3 +set g_balance_nex_switchdelay_raise 0.25 + +set g_balance_nex_reload_ammo 0 //default: 25 +set g_balance_nex_reload_time 2 +// }}} +// {{{ minstanex +set g_balance_minstanex_refire 1 +set g_balance_minstanex_animtime 0.3 +set g_balance_minstanex_ammo 10 +set g_balance_minstanex_laser_ammo 0 +set g_balance_minstanex_laser_animtime 0.3 +set g_balance_minstanex_laser_refire 0.7 +set g_balance_minstanex_switchdelay_drop 0.2 +set g_balance_minstanex_switchdelay_raise 0.2 +set g_balance_minstanex_reload_ammo 0 //default: 50 +set g_balance_minstanex_reload_time 2 +// }}} +// {{{ hagar +set g_balance_hagar_primary_damage 25 +set g_balance_hagar_primary_edgedamage 12.5 +set g_balance_hagar_primary_force 100 +set g_balance_hagar_primary_health 15 +set g_balance_hagar_primary_damageforcescale 0 +set g_balance_hagar_primary_radius 65 +set g_balance_hagar_primary_spread 0.03 +set g_balance_hagar_primary_speed 2500 +set g_balance_hagar_primary_lifetime 5 +set g_balance_hagar_primary_refire 0.16667 // 6 rockets per second +set g_balance_hagar_primary_ammo 1 +set g_balance_hagar_secondary 1 +set g_balance_hagar_secondary_load 1 +set g_balance_hagar_secondary_load_speed 0.5 +set g_balance_hagar_secondary_load_spread 0.075 +set g_balance_hagar_secondary_load_spread_bias 0.5 +set g_balance_hagar_secondary_load_max 4 +set g_balance_hagar_secondary_load_hold 4 +set g_balance_hagar_secondary_load_releasedeath 0 +set g_balance_hagar_secondary_load_abort 0 +set g_balance_hagar_secondary_load_linkexplode 0 +set g_balance_hagar_secondary_load_animtime 0.2 +set g_balance_hagar_secondary_damage 40 +set g_balance_hagar_secondary_edgedamage 20 +set g_balance_hagar_secondary_force 75 +set g_balance_hagar_secondary_health 15 +set g_balance_hagar_secondary_damageforcescale 0 +set g_balance_hagar_secondary_radius 80 +set g_balance_hagar_secondary_spread 0.05 +set g_balance_hagar_secondary_speed 2000 +set g_balance_hagar_secondary_lifetime_min 10 +set g_balance_hagar_secondary_lifetime_rand 0 +set g_balance_hagar_secondary_refire 0.5 +set g_balance_hagar_secondary_ammo 1 +set g_balance_hagar_switchdelay_drop 0.2 +set g_balance_hagar_switchdelay_raise 0.2 +set g_balance_hagar_reload_ammo 0 //default: 25 +set g_balance_hagar_reload_time 2 +// }}} +// {{{ rocketlauncher +set g_balance_rocketlauncher_damage 70 +set g_balance_rocketlauncher_edgedamage 35 +set g_balance_rocketlauncher_force 450 +set g_balance_rocketlauncher_radius 110 +set g_balance_rocketlauncher_speed 1300 +set g_balance_rocketlauncher_speedaccel 1300 +set g_balance_rocketlauncher_speedstart 1000 +set g_balance_rocketlauncher_lifetime 10 +set g_balance_rocketlauncher_refire 1.2 +set g_balance_rocketlauncher_animtime 0.4 +set g_balance_rocketlauncher_ammo 4 +set g_balance_rocketlauncher_health 30 // 30 // 5 hitpoints above maximum laser value -- this way lasers can't blow it up, but grenadelauncher still can most the time. +set g_balance_rocketlauncher_damageforcescale 1 // low damage force scale so that it can still be affected by other hits, but not so much that it does a 90 degree turn +set g_balance_rocketlauncher_detonatedelay 0.02 // 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 70 // 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.2 // delay before guiding kicks in +set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again +set g_balance_rocketlauncher_remote_damage 70 +set g_balance_rocketlauncher_remote_edgedamage 35 +set g_balance_rocketlauncher_remote_radius 110 +set g_balance_rocketlauncher_remote_force 400 +set g_balance_rocketlauncher_switchdelay_drop 0.3 +set g_balance_rocketlauncher_switchdelay_raise 0.2 +set g_balance_rocketlauncher_reload_ammo 0 //default: 25 +set g_balance_rocketlauncher_reload_time 2 +// }}} +// {{{ porto +set g_balance_porto_primary_refire 1.5 +set g_balance_porto_primary_animtime 0.3 +set g_balance_porto_primary_speed 1000 +set g_balance_porto_primary_lifetime 5 +set g_balance_porto_secondary 1 +set g_balance_porto_secondary_refire 1.5 +set g_balance_porto_secondary_animtime 0.3 +set g_balance_porto_secondary_speed 1000 +set g_balance_porto_secondary_lifetime 5 +set g_balance_porto_switchdelay_drop 0.2 +set g_balance_porto_switchdelay_raise 0.2 +set g_balance_portal_health 200 // these get recharged whenever the portal is used +set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used +// }}} +// {{{ hook +set g_balance_hook_primary_fuel 5 // hook monkeys set 0 +set g_balance_hook_primary_refire 0.2 // hook monkeys set 0 +set g_balance_hook_primary_animtime 0.3 // good shoot anim +set g_balance_hook_primary_hooked_time_max 0 // infinite +set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free +set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked +set g_balance_hook_secondary_damage 25 // not much +set g_balance_hook_secondary_edgedamage 5 // not much +set g_balance_hook_secondary_radius 500 // LOTS +set g_balance_hook_secondary_force -2000 // LOTS +set g_balance_hook_secondary_ammo 30 // a whole pack +set g_balance_hook_secondary_lifetime 5 // infinite +set g_balance_hook_secondary_speed 0 // not much throwing +set g_balance_hook_secondary_gravity 5 // fast falling +set g_balance_hook_secondary_refire 3 // don't drop too many bombs... +set g_balance_hook_secondary_animtime 0.3 // good shoot anim +set g_balance_hook_secondary_power 3 // effect behaves like a square function +set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds +set g_balance_hook_secondary_health 15 +set g_balance_hook_secondary_damageforcescale 0 +set g_balance_hook_switchdelay_drop 0.2 +set g_balance_hook_switchdelay_raise 0.2 +// }}} +// {{{ tuba +set g_balance_tuba_refire 0.05 +set g_balance_tuba_animtime 0.05 +set g_balance_tuba_attenuation 0.5 +set g_balance_tuba_volume 1 +set g_balance_tuba_fadetime 0.25 +set g_balance_tuba_damage 5 +set g_balance_tuba_edgedamage 0 +set g_balance_tuba_radius 200 +set g_balance_tuba_force 40 +set g_balance_tuba_pitchstep 6 +set g_balance_tuba_switchdelay_drop 0.2 +set g_balance_tuba_switchdelay_raise 0.2 +// }}} +// {{{ fireball // this is a superweapon -- lets make it behave as one. +set g_balance_fireball_primary_animtime 0.2 +set g_balance_fireball_primary_bfgdamage 100 +set g_balance_fireball_primary_bfgforce 0 +set g_balance_fireball_primary_bfgradius 1000 +set g_balance_fireball_primary_damage 200 +set g_balance_fireball_primary_damageforcescale 0 +set g_balance_fireball_primary_edgedamage 50 +set g_balance_fireball_primary_force 600 +set g_balance_fireball_primary_health 0 +set g_balance_fireball_primary_laserburntime 0.5 +set g_balance_fireball_primary_laserdamage 80 +set g_balance_fireball_primary_laseredgedamage 20 +set g_balance_fireball_primary_laserradius 256 +set g_balance_fireball_primary_lifetime 15 +set g_balance_fireball_primary_radius 200 +set g_balance_fireball_primary_refire 2 +set g_balance_fireball_primary_refire2 0 +set g_balance_fireball_primary_speed 1200 +set g_balance_fireball_primary_spread 0 +set g_balance_fireball_secondary_animtime 0.3 +set g_balance_fireball_secondary_damage 40 +set g_balance_fireball_secondary_damageforcescale 4 +set g_balance_fireball_secondary_damagetime 5 +set g_balance_fireball_secondary_force 100 +set g_balance_fireball_secondary_laserburntime 0.5 +set g_balance_fireball_secondary_laserdamage 50 +set g_balance_fireball_secondary_laseredgedamage 20 +set g_balance_fireball_secondary_laserradius 110 +set g_balance_fireball_secondary_lifetime 7 +set g_balance_fireball_secondary_refire 1.5 +set g_balance_fireball_secondary_speed 900 +set g_balance_fireball_secondary_speed_up 100 +set g_balance_fireball_secondary_speed_z 0 +set g_balance_fireball_secondary_spread 0 +set g_balance_fireball_switchdelay_drop 0.2 +set g_balance_fireball_switchdelay_raise 0.2 +// }}} diff --git a/balanceXonotic.cfg b/balanceXonotic.cfg new file mode 100644 index 000000000..198801547 --- /dev/null +++ b/balanceXonotic.cfg @@ -0,0 +1,706 @@ +g_mod_balance Xonotic + +// {{{ starting gear +set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" // UNTIL IT CAN BE REMOVED FROM CODE +set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" +set g_balance_health_start 100 +set g_balance_armor_start 0 +set g_start_ammo_shells 15 +set g_start_ammo_nails 0 +set g_start_ammo_rockets 0 +set g_start_ammo_cells 0 +set g_start_ammo_fuel 0 +set g_warmup_start_health 100 "starting values when being in warmup-stage" +set g_warmup_start_armor 100 "starting values when being in warmup-stage" +set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage" +set g_warmup_start_ammo_nails 160 "starting values when being in warmup-stage" +set g_warmup_start_ammo_rockets 80 "starting values when being in warmup-stage" +set g_warmup_start_ammo_cells 90 "starting values when being in warmup-stage" +set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage" +set g_lms_start_health 200 +set g_lms_start_armor 200 +set g_lms_start_ammo_shells 60 +set g_lms_start_ammo_nails 320 +set g_lms_start_ammo_rockets 160 +set g_lms_start_ammo_cells 180 +set g_lms_start_ammo_fuel 0 +set g_balance_nix_roundtime 25 +set g_balance_nix_incrtime 1.6 +set g_balance_nix_ammo_shells 60 +set g_balance_nix_ammo_nails 320 +set g_balance_nix_ammo_rockets 160 +set g_balance_nix_ammo_cells 180 +set g_balance_nix_ammo_fuel 0 +set g_balance_nix_ammoincr_shells 2 // eh this will need figured out later I assume +set g_balance_nix_ammoincr_nails 6 +set g_balance_nix_ammoincr_rockets 2 +set g_balance_nix_ammoincr_cells 2 +set g_balance_nix_ammoincr_fuel 2 +// }}} + +// {{{ pickup items +set g_pickup_ammo_anyway 1 +set g_pickup_weapons_anyway 1 +set g_pickup_shells 15 +set g_pickup_shells_weapon 15 +set g_pickup_shells_max 60 +set g_pickup_nails 80 +set g_pickup_nails_weapon 80 +set g_pickup_nails_max 320 +set g_pickup_rockets 40 +set g_pickup_rockets_weapon 40 +set g_pickup_rockets_max 160 +set g_pickup_cells 30 +set g_pickup_cells_weapon 30 +set g_pickup_cells_max 180 +set g_pickup_fuel 50 +set g_pickup_fuel_weapon 50 +set g_pickup_fuel_jetpack 100 +set g_pickup_fuel_max 100 +set g_pickup_armorsmall 5 +set g_pickup_armorsmall_max 200 +set g_pickup_armorsmall_anyway 1 +set g_pickup_armormedium 25 +set g_pickup_armormedium_max 200 +set g_pickup_armormedium_anyway 1 +set g_pickup_armorbig 50 +set g_pickup_armorbig_max 200 +set g_pickup_armorbig_anyway 1 +set g_pickup_armorlarge 100 +set g_pickup_armorlarge_max 200 +set g_pickup_armorlarge_anyway 1 +set g_pickup_healthsmall 5 +set g_pickup_healthsmall_max 200 +set g_pickup_healthsmall_anyway 1 +set g_pickup_healthmedium 25 +set g_pickup_healthmedium_max 200 +set g_pickup_healthmedium_anyway 1 +set g_pickup_healthlarge 50 +set g_pickup_healthlarge_max 200 +set g_pickup_healthlarge_anyway 1 +set g_pickup_healthmega 100 +set g_pickup_healthmega_max 200 +set g_pickup_healthmega_anyway 1 +set g_pickup_respawntime_short 15 +set g_pickup_respawntime_medium 20 +set g_pickup_respawntime_long 30 +set g_pickup_respawntime_powerup 120 +set g_pickup_respawntime_weapon 10 +set g_pickup_respawntime_superweapon 120 +set g_pickup_respawntime_ammo 10 +set g_pickup_respawntimejitter_short 0 +set g_pickup_respawntimejitter_medium 0 +set g_pickup_respawntimejitter_long 0 +set g_pickup_respawntimejitter_powerup 30 +set g_pickup_respawntimejitter_weapon 0 +set g_pickup_respawntimejitter_superweapon 10 +set g_pickup_respawntimejitter_ammo 0 +// }}} + +// {{{ regen/rot +set g_balance_health_regen 0.08 +set g_balance_health_regenlinear 0.5 +set g_balance_pause_health_regen 5 +set g_balance_pause_health_regen_spawn 0 +set g_balance_health_rot 0.04 +set g_balance_health_rotlinear 0.75 +set g_balance_pause_health_rot 1 +set g_balance_pause_health_rot_spawn 5 +set g_balance_health_regenstable 100 +set g_balance_health_rotstable 100 +set g_balance_health_limit 999 +set g_balance_armor_regen 0 +set g_balance_armor_regenlinear 0 +set g_balance_armor_rot 0.04 +set g_balance_armor_rotlinear 0.75 +set g_balance_pause_armor_rot 1 +set g_balance_pause_armor_rot_spawn 5 +set g_balance_armor_regenstable 100 +set g_balance_armor_rotstable 100 +set g_balance_armor_limit 999 +set g_balance_armor_blockpercent 0.6 +set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)" +set g_balance_fuel_regenlinear 0 +set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter +set g_balance_fuel_rot 0.05 +set g_balance_fuel_rotlinear 0 +set g_balance_pause_fuel_rot 5 +set g_balance_pause_fuel_rot_spawn 10 +set g_balance_fuel_regenstable 50 +set g_balance_fuel_rotstable 100 +set g_balance_fuel_limit 999 +// }}} + +// {{{ misc +set g_balance_selfdamagepercent 0.65 +set g_weaponspeedfactor 1 "weapon projectile speed multiplier" +set g_weaponratefactor 1 "weapon fire rate multiplier" +set g_weapondamagefactor 1 "weapon damage multiplier" +set g_weaponforcefactor 1 "weapon force multiplier" +set g_weaponspreadfactor 1 "weapon spread multiplier" +set g_balance_firetransfer_time 0.9 +set g_balance_firetransfer_damage 0.8 +set g_throughfloor_damage 0.75 +set g_throughfloor_force 0.75 +set g_projectiles_damage 2 +// possible values: +// -2: absolutely no damage to projectiles (no exceptions) +// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines) +// 0: only damage from contents (lava/slime) or exceptions +// 1: only self damage or damage from contents or exceptions +// 2: allow all damage to projectiles normally +set g_projectiles_keep_owner 0 +set g_projectiles_newton_style 2 +// possible values: +// 0: absolute velocity projectiles (like Quake) +// 1: relative velocity projectiles, "Newtonian" (like Tribes 2) +// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard) +set g_projectiles_newton_style_2_minfactor 0.8 +set g_projectiles_newton_style_2_maxfactor 1.5 +set g_projectiles_spread_style 7 +// possible values: +// 0: forward + solid sphere (like Quake) - varies velocity +// 1: forward + flattened solid sphere +// 2: forward + solid circle +// 3: forward + normal distribution 3D - varies velocity +// 4: forward + normal distribution on a plane +// 5: forward + circle with 1-r falloff +// 6: forward + circle with 1-r^2 falloff +// 7: forward + circle with (1-r)(2-r) falloff +set g_balance_falldamage_deadminspeed 250 +set g_balance_falldamage_minspeed 900 +set g_balance_falldamage_factor 0.20 +set g_balance_falldamage_maxdamage 40 +set g_balance_damagepush_speedfactor 2.5 +set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage +set g_balance_contents_drowndelay 10 // time under water before a player begins drowning +set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning +set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava +set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime +set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime +set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap" +// }}} + +// {{{ powerups +set g_balance_powerup_invincible_takedamage 0.25 // only 1/4th damage is taken +set g_balance_powerup_invincible_time 30 +set g_balance_powerup_strength_damage 3 +set g_balance_powerup_strength_force 3 +set g_balance_powerup_strength_time 30 +set g_balance_powerup_strength_selfdamage 1.5 +set g_balance_powerup_strength_selfforce 1.5 +set g_balance_superweapons_time 30 +// }}} + +// {{{ jetpack/hook +set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack" +set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction" +set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)" +set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction" +set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction" +set g_jetpack_fuel 8 "fuel per second for jetpack" +set g_jetpack_attenuation 2 "jetpack sound attenuation" + +set g_grappling_hook_tarzan 2 // 2: can also pull players +set g_balance_grapplehook_speed_fly 1800 +set g_balance_grapplehook_speed_pull 2000 +set g_balance_grapplehook_force_rubber 2000 +set g_balance_grapplehook_force_rubber_overstretch 1000 +set g_balance_grapplehook_length_min 50 +set g_balance_grapplehook_stretch 50 +set g_balance_grapplehook_airfriction 0.2 +set g_balance_grapplehook_health 50 +set g_balance_grapplehook_damagedbycontents 1 +set g_balance_grapplehook_refire 0.2 +// }}} + +// {{{ weapon properties +// {{{ laser +set g_balance_laser_primary_damage 25 +set g_balance_laser_primary_edgedamage 12.5 +set g_balance_laser_primary_force 300 +set g_balance_laser_primary_radius 70 +set g_balance_laser_primary_speed 6000 +set g_balance_laser_primary_spread 0 +set g_balance_laser_primary_refire 0.7 +set g_balance_laser_primary_animtime 0.2 +set g_balance_laser_primary_lifetime 5 +set g_balance_laser_primary_shotangle 0 +set g_balance_laser_primary_delay 0 +set g_balance_laser_primary_gauntlet 0 +set g_balance_laser_primary_force_zscale 1.2 +set g_balance_laser_primary_force_velocitybias 0 +set g_balance_laser_primary_force_other_scale 1 +set g_balance_laser_secondary 0 // when 1, a secondary laser mode exists +set g_balance_laser_secondary_damage 25 +set g_balance_laser_secondary_edgedamage 12.5 +set g_balance_laser_secondary_force 400 +set g_balance_laser_secondary_radius 70 +set g_balance_laser_secondary_speed 12000 +set g_balance_laser_secondary_spread 0 +set g_balance_laser_secondary_refire 0.7 +set g_balance_laser_secondary_animtime 0.2 +set g_balance_laser_secondary_lifetime 5 +set g_balance_laser_secondary_shotangle -90 +set g_balance_laser_secondary_delay 0 +set g_balance_laser_secondary_gauntlet 0 +set g_balance_laser_secondary_force_zscale 1.25 +set g_balance_laser_secondary_force_velocitybias 0 +set g_balance_laser_secondary_force_other_scale 1 +set g_balance_laser_switchdelay_drop 0.15 +set g_balance_laser_switchdelay_raise 0.15 +set g_balance_laser_reload_ammo 0 //default: 6 +set g_balance_laser_reload_time 2 +// }}} +// {{{ shotgun +set g_balance_shotgun_primary_bullets 14 +set g_balance_shotgun_primary_damage 4 +set g_balance_shotgun_primary_force 15 +set g_balance_shotgun_primary_spread 0.12 +set g_balance_shotgun_primary_refire 0.75 +set g_balance_shotgun_primary_animtime 0.2 +set g_balance_shotgun_primary_ammo 1 +set g_balance_shotgun_primary_solidpenetration 3.8 +set g_balance_shotgun_secondary 1 +set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow +set g_balance_shotgun_secondary_melee_range 120 +set g_balance_shotgun_secondary_melee_swing_side 120 +set g_balance_shotgun_secondary_melee_swing_up 30 +set g_balance_shotgun_secondary_melee_time 0.15 +set g_balance_shotgun_secondary_melee_traces 10 +set g_balance_shotgun_secondary_melee_no_doubleslap 1 +set g_balance_shotgun_secondary_melee_nonplayerdamage 40 +set g_balance_shotgun_secondary_melee_multihit 1 +set g_balance_shotgun_secondary_damage 80 +set g_balance_shotgun_secondary_force 200 +set g_balance_shotgun_secondary_refire 1.25 +set g_balance_shotgun_secondary_animtime 1 +set g_balance_shotgun_switchdelay_drop 0.2 +set g_balance_shotgun_switchdelay_raise 0.2 +set g_balance_shotgun_reload_ammo 0 //default: 5 +set g_balance_shotgun_reload_time 2 +// }}} +// {{{ uzi +set g_balance_uzi_mode 1 // Activates varible spread for sustained & burst mode secondary +set g_balance_uzi_spread_min 0.02 +set g_balance_uzi_spread_max 0.05 +set g_balance_uzi_spread_add 0.012 + +set g_balance_uzi_burst 3 // # of bullets in a burst (if set to 2 or more) +set g_balance_uzi_burst_animtime 0.3 +set g_balance_uzi_burst_refire 0.06 // refire between burst bullets +set g_balance_uzi_burst_refire2 0.45 // refire after burst +set g_balance_uzi_burst_spread 0.02 +set g_balance_uzi_burst_damage 25 +set g_balance_uzi_burst_force 20 +set g_balance_uzi_burst_ammo 3 + +set g_balance_uzi_first 1 +set g_balance_uzi_first_damage 14 +set g_balance_uzi_first_force 5 +set g_balance_uzi_first_spread 0.03 +set g_balance_uzi_first_refire 0.125 +set g_balance_uzi_first_ammo 1 + +set g_balance_uzi_sustained_damage 10 // 100 dps +set g_balance_uzi_sustained_force 5 +set g_balance_uzi_sustained_spread 0.03 +set g_balance_uzi_sustained_refire 0.1 +set g_balance_uzi_sustained_ammo 1 + +set g_balance_uzi_solidpenetration 13.1 + +set g_balance_uzi_switchdelay_drop 0.2 +set g_balance_uzi_switchdelay_raise 0.2 + +set g_balance_uzi_reload_ammo 60 //default: 30 +set g_balance_uzi_reload_time 2 +// }}} +// {{{ mortar +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 250 +set g_balance_grenadelauncher_primary_radius 120 +set g_balance_grenadelauncher_primary_speed 1900 +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_lifetime 5 +set g_balance_grenadelauncher_primary_lifetime2 1 +set g_balance_grenadelauncher_primary_refire 0.8 +set g_balance_grenadelauncher_primary_animtime 0.3 +set g_balance_grenadelauncher_primary_ammo 2 +set g_balance_grenadelauncher_primary_health 15 +set g_balance_grenadelauncher_primary_damageforcescale 0 +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 30 +set g_balance_grenadelauncher_secondary_force 250 +set g_balance_grenadelauncher_secondary_radius 120 +set g_balance_grenadelauncher_secondary_speed 1400 +set g_balance_grenadelauncher_secondary_speed_up 150 +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_lifetime_bounce 0.5 +set g_balance_grenadelauncher_secondary_lifetime_stick 0 +set g_balance_grenadelauncher_secondary_refire 0.7 +set g_balance_grenadelauncher_secondary_animtime 0.3 +set g_balance_grenadelauncher_secondary_ammo 2 +set g_balance_grenadelauncher_secondary_health 30 +set g_balance_grenadelauncher_secondary_damageforcescale 4 +set g_balance_grenadelauncher_secondary_remote_detonateprimary 0 + +set g_balance_grenadelauncher_bouncefactor 0.5 +set g_balance_grenadelauncher_bouncestop 0.075 + +set g_balance_grenadelauncher_switchdelay_drop 0.2 +set g_balance_grenadelauncher_switchdelay_raise 0.2 + +set g_balance_grenadelauncher_reload_ammo 0 //default: 12 +set g_balance_grenadelauncher_reload_time 2 +// }}} +// {{{ electro +set g_balance_electro_lightning 0 +set g_balance_electro_primary_damage 40 +set g_balance_electro_primary_edgedamage 20 +set g_balance_electro_primary_force 200 +set g_balance_electro_primary_force_up 0 +set g_balance_electro_primary_radius 100 +set g_balance_electro_primary_comboradius 300 +set g_balance_electro_primary_speed 2500 +set g_balance_electro_primary_spread 0 +set g_balance_electro_primary_lifetime 5 +set g_balance_electro_primary_refire 0.6 +set g_balance_electro_primary_animtime 0.3 +set g_balance_electro_primary_ammo 4 +set g_balance_electro_primary_range 0 +set g_balance_electro_primary_falloff_mindist 255 // 0.3 * radius +set g_balance_electro_primary_falloff_maxdist 850 +set g_balance_electro_primary_falloff_halflifedist 425 +set g_balance_electro_secondary_damage 40 +set g_balance_electro_secondary_edgedamage 20 +set g_balance_electro_secondary_force 50 +set g_balance_electro_secondary_radius 150 +set g_balance_electro_secondary_speed 1000 +set g_balance_electro_secondary_speed_up 200 +set g_balance_electro_secondary_speed_z 0 +set g_balance_electro_secondary_spread 0.04 +set g_balance_electro_secondary_lifetime 4 +set g_balance_electro_secondary_refire 0.2 +set g_balance_electro_secondary_refire2 1.6 +set g_balance_electro_secondary_animtime 0.2 +set g_balance_electro_secondary_ammo 2 +set g_balance_electro_secondary_health 5 +set g_balance_electro_secondary_damageforcescale 4 +set g_balance_electro_secondary_damagedbycontents 1 +set g_balance_electro_secondary_count 3 +set g_balance_electro_secondary_bouncefactor 0.3 +set g_balance_electro_secondary_bouncestop 0.05 +set g_balance_electro_combo_damage 50 +set g_balance_electro_combo_edgedamage 25 +set g_balance_electro_combo_force 120 +set g_balance_electro_combo_radius 150 +set g_balance_electro_combo_comboradius 300 +set g_balance_electro_combo_speed 2000 +set g_balance_electro_combo_safeammocheck 1 +set g_balance_electro_switchdelay_drop 0.2 +set g_balance_electro_switchdelay_raise 0.2 +set g_balance_electro_reload_ammo 0 //default: 20 +set g_balance_electro_reload_time 2 +// }}} +// {{{ crylink +set g_balance_crylink_primary_damage 12 +set g_balance_crylink_primary_edgedamage 6 +set g_balance_crylink_primary_force -50 +set g_balance_crylink_primary_radius 80 +set g_balance_crylink_primary_speed 2000 +set g_balance_crylink_primary_spread 0.08 +set g_balance_crylink_primary_shots 6 +set g_balance_crylink_primary_bounces 1 +set g_balance_crylink_primary_refire 0.7 +set g_balance_crylink_primary_animtime 0.3 +set g_balance_crylink_primary_ammo 3 +set g_balance_crylink_primary_bouncedamagefactor 0.5 +set g_balance_crylink_primary_joindelay 0.1 +set g_balance_crylink_primary_joinspread 0.2 +set g_balance_crylink_primary_joinexplode 1 +set g_balance_crylink_primary_joinexplode_damage 0 +set g_balance_crylink_primary_joinexplode_edgedamage 0 +set g_balance_crylink_primary_joinexplode_radius 0 +set g_balance_crylink_primary_joinexplode_force 0 +set g_balance_crylink_primary_linkexplode 1 + +set g_balance_crylink_primary_middle_lifetime 5 // range: 35000 full, fades to 70000 +set g_balance_crylink_primary_middle_fadetime 5 +set g_balance_crylink_primary_other_lifetime 5 +set g_balance_crylink_primary_other_fadetime 5 + +set g_balance_crylink_secondary 1 +set g_balance_crylink_secondary_damage 10 +set g_balance_crylink_secondary_edgedamage 5 +set g_balance_crylink_secondary_force -250 +set g_balance_crylink_secondary_radius 100 +set g_balance_crylink_secondary_speed 3000 +set g_balance_crylink_secondary_spread 0.01 +set g_balance_crylink_secondary_spreadtype 1 +set g_balance_crylink_secondary_shots 5 +set g_balance_crylink_secondary_bounces 0 +set g_balance_crylink_secondary_refire 0.7 +set g_balance_crylink_secondary_animtime 0.2 +set g_balance_crylink_secondary_ammo 2 +set g_balance_crylink_secondary_bouncedamagefactor 0.5 +set g_balance_crylink_secondary_joindelay 0 +set g_balance_crylink_secondary_joinspread 0 +set g_balance_crylink_secondary_joinexplode 0 +set g_balance_crylink_secondary_joinexplode_damage 0 +set g_balance_crylink_secondary_joinexplode_edgedamage 0 +set g_balance_crylink_secondary_joinexplode_radius 0 +set g_balance_crylink_secondary_joinexplode_force 0 +set g_balance_crylink_secondary_linkexplode 1 + +set g_balance_crylink_secondary_middle_lifetime 5 // range: 35000 full, fades to 70000 +set g_balance_crylink_secondary_middle_fadetime 5 +set g_balance_crylink_secondary_line_lifetime 5 +set g_balance_crylink_secondary_line_fadetime 5 + +set g_balance_crylink_switchdelay_drop 0.2 +set g_balance_crylink_switchdelay_raise 0.2 + +set g_balance_crylink_reload_ammo 0 //default: 10 +set g_balance_crylink_reload_time 2 +// }}} +// {{{ nex +set g_balance_nex_primary_damage 80 +set g_balance_nex_primary_force 400 +set g_balance_nex_primary_refire 1.5 +set g_balance_nex_primary_animtime 0.6 +set g_balance_nex_primary_ammo 6 +set g_balance_nex_primary_damagefalloff_mindist 0 // 1000 For tZork ;3 +set g_balance_nex_primary_damagefalloff_maxdist 0 // 3000 +set g_balance_nex_primary_damagefalloff_halflife 0 // 1500 +set g_balance_nex_primary_damagefalloff_forcehalflife 0 // 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_chargepool 0 +set g_balance_nex_secondary_chargepool_regen 0.15 +set g_balance_nex_secondary_chargepool_pause_regen 1 +set g_balance_nex_secondary_chargepool_pause_health_regen 1 +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 2 +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_charge 1 +set g_balance_nex_charge_mindmg 40 +set g_balance_nex_charge_start 0.5 +set g_balance_nex_charge_rate 0.4 +set g_balance_nex_charge_animlimit 0.5 +set g_balance_nex_charge_limit 1 +set g_balance_nex_charge_rot_rate 0 +set g_balance_nex_charge_rot_pause 0 // Dont rot down until this long after release of charge button +set g_balance_nex_charge_shot_multiplier 0 +set g_balance_nex_charge_velocity_rate 0 +set g_balance_nex_charge_minspeed 400 +set g_balance_nex_charge_maxspeed 800 + +set g_balance_nex_switchdelay_drop 0.3 +set g_balance_nex_switchdelay_raise 0.25 + +set g_balance_nex_reload_ammo 0 //default: 25 +set g_balance_nex_reload_time 2 +// }}} +// {{{ minstanex +set g_balance_minstanex_refire 1 +set g_balance_minstanex_animtime 0.3 +set g_balance_minstanex_ammo 10 +set g_balance_minstanex_laser_ammo 0 +set g_balance_minstanex_laser_animtime 0.3 +set g_balance_minstanex_laser_refire 0.7 +set g_balance_minstanex_switchdelay_drop 0.2 +set g_balance_minstanex_switchdelay_raise 0.2 +set g_balance_minstanex_reload_ammo 0 //default: 50 +set g_balance_minstanex_reload_time 2 +// }}} +// {{{ hagar +set g_balance_hagar_primary_damage 25 +set g_balance_hagar_primary_edgedamage 12.5 +set g_balance_hagar_primary_force 100 +set g_balance_hagar_primary_health 15 +set g_balance_hagar_primary_damageforcescale 0 +set g_balance_hagar_primary_radius 65 +set g_balance_hagar_primary_spread 0.03 +set g_balance_hagar_primary_speed 2500 +set g_balance_hagar_primary_lifetime 5 +set g_balance_hagar_primary_refire 0.16667 // 6 rockets per second +set g_balance_hagar_primary_ammo 1 +set g_balance_hagar_secondary 1 +set g_balance_hagar_secondary_load 1 +set g_balance_hagar_secondary_load_speed 0.5 +set g_balance_hagar_secondary_load_spread 0.075 +set g_balance_hagar_secondary_load_spread_bias 0.5 +set g_balance_hagar_secondary_load_max 4 +set g_balance_hagar_secondary_load_hold 4 +set g_balance_hagar_secondary_load_releasedeath 0 +set g_balance_hagar_secondary_load_abort 0 +set g_balance_hagar_secondary_load_linkexplode 0 +set g_balance_hagar_secondary_load_animtime 0.2 +set g_balance_hagar_secondary_damage 40 +set g_balance_hagar_secondary_edgedamage 20 +set g_balance_hagar_secondary_force 75 +set g_balance_hagar_secondary_health 15 +set g_balance_hagar_secondary_damageforcescale 0 +set g_balance_hagar_secondary_radius 80 +set g_balance_hagar_secondary_spread 0.05 +set g_balance_hagar_secondary_speed 2500 +set g_balance_hagar_secondary_lifetime_min 10 +set g_balance_hagar_secondary_lifetime_rand 0 +set g_balance_hagar_secondary_refire 0.5 +set g_balance_hagar_secondary_ammo 1 +set g_balance_hagar_switchdelay_drop 0.2 +set g_balance_hagar_switchdelay_raise 0.2 +set g_balance_hagar_reload_ammo 0 //default: 25 +set g_balance_hagar_reload_time 2 +// }}} +// {{{ rocketlauncher +set g_balance_rocketlauncher_damage 70 +set g_balance_rocketlauncher_edgedamage 35 +set g_balance_rocketlauncher_force 450 +set g_balance_rocketlauncher_radius 110 +set g_balance_rocketlauncher_speed 1300 +set g_balance_rocketlauncher_speedaccel 1300 +set g_balance_rocketlauncher_speedstart 1000 +set g_balance_rocketlauncher_lifetime 10 +set g_balance_rocketlauncher_refire 1.2 +set g_balance_rocketlauncher_animtime 0.4 +set g_balance_rocketlauncher_ammo 4 +set g_balance_rocketlauncher_health 30 // 30 // 5 hitpoints above maximum laser value -- this way lasers can't blow it up, but grenadelauncher still can most the time. +set g_balance_rocketlauncher_damageforcescale 1 // low damage force scale so that it can still be affected by other hits, but not so much that it does a 90 degree turn +set g_balance_rocketlauncher_detonatedelay 0.02 // 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 70 // 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.2 // delay before guiding kicks in +set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again +set g_balance_rocketlauncher_remote_damage 70 +set g_balance_rocketlauncher_remote_edgedamage 35 +set g_balance_rocketlauncher_remote_radius 110 +set g_balance_rocketlauncher_remote_force 400 +set g_balance_rocketlauncher_switchdelay_drop 0.3 +set g_balance_rocketlauncher_switchdelay_raise 0.2 +set g_balance_rocketlauncher_reload_ammo 0 //default: 25 +set g_balance_rocketlauncher_reload_time 2 +// }}} +// {{{ porto +set g_balance_porto_primary_refire 1.5 +set g_balance_porto_primary_animtime 0.3 +set g_balance_porto_primary_speed 1000 +set g_balance_porto_primary_lifetime 5 +set g_balance_porto_secondary 1 +set g_balance_porto_secondary_refire 1.5 +set g_balance_porto_secondary_animtime 0.3 +set g_balance_porto_secondary_speed 1000 +set g_balance_porto_secondary_lifetime 5 +set g_balance_porto_switchdelay_drop 0.2 +set g_balance_porto_switchdelay_raise 0.2 +set g_balance_portal_health 200 // these get recharged whenever the portal is used +set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used +// }}} +// {{{ hook +set g_balance_hook_primary_fuel 5 // hook monkeys set 0 +set g_balance_hook_primary_refire 0.2 // hook monkeys set 0 +set g_balance_hook_primary_animtime 0.3 // good shoot anim +set g_balance_hook_primary_hooked_time_max 0 // infinite +set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free +set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked +set g_balance_hook_secondary_damage 25 // not much +set g_balance_hook_secondary_edgedamage 5 // not much +set g_balance_hook_secondary_radius 500 // LOTS +set g_balance_hook_secondary_force -2000 // LOTS +set g_balance_hook_secondary_ammo 30 // a whole pack +set g_balance_hook_secondary_lifetime 5 // infinite +set g_balance_hook_secondary_speed 0 // not much throwing +set g_balance_hook_secondary_gravity 5 // fast falling +set g_balance_hook_secondary_refire 3 // don't drop too many bombs... +set g_balance_hook_secondary_animtime 0.3 // good shoot anim +set g_balance_hook_secondary_power 3 // effect behaves like a square function +set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds +set g_balance_hook_secondary_health 15 +set g_balance_hook_secondary_damageforcescale 0 +set g_balance_hook_switchdelay_drop 0.2 +set g_balance_hook_switchdelay_raise 0.2 +// }}} +// {{{ tuba +set g_balance_tuba_refire 0.05 +set g_balance_tuba_animtime 0.05 +set g_balance_tuba_attenuation 0.5 +set g_balance_tuba_volume 1 +set g_balance_tuba_fadetime 0.25 +set g_balance_tuba_damage 5 +set g_balance_tuba_edgedamage 0 +set g_balance_tuba_radius 200 +set g_balance_tuba_force 40 +set g_balance_tuba_pitchstep 6 +set g_balance_tuba_switchdelay_drop 0.2 +set g_balance_tuba_switchdelay_raise 0.2 +// }}} +// {{{ fireball // this is a superweapon -- lets make it behave as one. +set g_balance_fireball_primary_animtime 0.2 +set g_balance_fireball_primary_bfgdamage 100 +set g_balance_fireball_primary_bfgforce 0 +set g_balance_fireball_primary_bfgradius 1000 +set g_balance_fireball_primary_damage 200 +set g_balance_fireball_primary_damageforcescale 0 +set g_balance_fireball_primary_edgedamage 50 +set g_balance_fireball_primary_force 600 +set g_balance_fireball_primary_health 0 +set g_balance_fireball_primary_laserburntime 0.5 +set g_balance_fireball_primary_laserdamage 80 +set g_balance_fireball_primary_laseredgedamage 20 +set g_balance_fireball_primary_laserradius 256 +set g_balance_fireball_primary_lifetime 15 +set g_balance_fireball_primary_radius 200 +set g_balance_fireball_primary_refire 2 +set g_balance_fireball_primary_refire2 0 +set g_balance_fireball_primary_speed 1200 +set g_balance_fireball_primary_spread 0 +set g_balance_fireball_secondary_animtime 0.3 +set g_balance_fireball_secondary_damage 40 +set g_balance_fireball_secondary_damageforcescale 4 +set g_balance_fireball_secondary_damagetime 5 +set g_balance_fireball_secondary_force 100 +set g_balance_fireball_secondary_laserburntime 0.5 +set g_balance_fireball_secondary_laserdamage 50 +set g_balance_fireball_secondary_laseredgedamage 20 +set g_balance_fireball_secondary_laserradius 110 +set g_balance_fireball_secondary_lifetime 7 +set g_balance_fireball_secondary_refire 1.5 +set g_balance_fireball_secondary_speed 900 +set g_balance_fireball_secondary_speed_up 100 +set g_balance_fireball_secondary_speed_z 0 +set g_balance_fireball_secondary_spread 0 +set g_balance_fireball_switchdelay_drop 0.2 +set g_balance_fireball_switchdelay_raise 0.2 +// }}} diff --git a/check-cvars.sh b/check-cvars.sh index 031613a7b..78985b819 100755 --- a/check-cvars.sh +++ b/check-cvars.sh @@ -23,7 +23,7 @@ check_files() done } -check_files "balance-xonotic.cfg" "balance-*.cfg" "/^seta? g_/" +check_files "balanceXonotic.cfg" "balance*.cfg" "/^seta? g_/" check_files "_hud_descriptions.cfg" "hud_*.cfg" "/^seta? hud_/" if $errord; then diff --git a/crosshairs.cfg b/crosshairs.cfg index 6a9d8822c..c6a9e837b 100644 --- a/crosshairs.cfg +++ b/crosshairs.cfg @@ -41,9 +41,87 @@ seta crosshair_color_special 1 "special color handling for crosshair... 1 = per- seta crosshair_color_special_rainbow_delay 0.1 seta crosshair_color_special_rainbow_brightness 20 "color brightness of the random crosshair colors" -// per-weapon crosshairs + +// =============================== +// Per weapon crosshair settings +// =============================== +// main settings seta crosshair_per_weapon 1 "when 1, each gun will display a different crosshair" +// per weapon settings +seta crosshair_laser "" "crosshair to display when wielding the laser" +seta crosshair_laser_color "1 0.35 0.2" "crosshair color to display when wielding the laser" +seta crosshair_laser_alpha 0.75 "crosshair alpha value to display when wielding the laser" +seta crosshair_laser_size 0.4 "crosshair size when wielding the laser" +seta crosshair_shotgun "" "crosshair to display when wielding the shotgun" +seta crosshair_shotgun_color "0.7 0.7 0.7" "crosshair color to display when wielding the shotgun" +seta crosshair_shotgun_alpha 1.1 "crosshair alpha value to display when wielding the shotgun" +seta crosshair_shotgun_size 0.65 "crosshair size when wielding the shotgun" +seta crosshair_uzi "" "crosshair to display when wielding the machinegun" +seta crosshair_uzi_color "0.4 0.9 0.35" "crosshair color to display when wielding the machinegun" +seta crosshair_uzi_alpha 0.9 "crosshair alpha value to display when wielding the machinegun" +seta crosshair_uzi_size 0.6 "crosshair size when wielding the machinegun" +seta crosshair_grenadelauncher "" "crosshair to display when wielding the mortar" +seta crosshair_grenadelauncher_color "1 0.15 0" "crosshair color to display when wielding the mortar" +seta crosshair_grenadelauncher_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 "0.75 0.75 0" "crosshair color to display when wielding the mortar" +seta crosshair_minelayer_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 "0.35 0.5 1" "crosshair color to display when wielding the electro" +seta crosshair_electro_alpha 1 "crosshair alpha value to display when wielding the electro" +seta crosshair_electro_size 0.5 "crosshair size when wielding the electro" +seta crosshair_crylink "" "crosshair to display when wielding the crylink" +seta crosshair_crylink_color "0.85 0.25 1" "crosshair color to display when wielding the crylink" +seta crosshair_crylink_alpha 0.85 "crosshair alpha value to display when wielding the crylink" +seta crosshair_crylink_size 0.4 "crosshair size when wielding the crylink" +seta crosshair_nex "" "crosshair to display when wielding the nex gun" +seta crosshair_nex_color "0 0.9 1" "crosshair color to display when wielding the nex gun" +seta crosshair_nex_alpha 0.85 "crosshair alpha value to display when wielding the nex gun" +seta crosshair_nex_size 0.65 "crosshair size when wielding the nex gun" +seta crosshair_hagar "" "crosshair to display when wielding the hagar" +seta crosshair_hagar_color "0.85 0.5 0.35" "crosshair color to display when wielding the hagar" +seta crosshair_hagar_alpha 1 "crosshair alpha value to display when wielding the hagar" +seta crosshair_hagar_size 0.8 "crosshair size when wielding the hagar" +seta crosshair_rocketlauncher "" "crosshair to display when wielding the rocketlauncher" +seta crosshair_rocketlauncher_color "1 0.75 0.2" "crosshair color to display when wielding the rocketlauncher" +seta crosshair_rocketlauncher_alpha 1 "crosshair alpha value to display when wielding the rocketlauncher" +seta crosshair_rocketlauncher_size 0.5875 "crosshair size when wielding the rocketlauncher" +seta crosshair_porto "" "crosshair to display when wielding the porto" +seta crosshair_porto_color "0.5 1 0.5" "crosshair color to display when wielding the porto" +seta crosshair_porto_alpha 0.85 "crosshair alpha value to display when wielding the porto" +seta crosshair_porto_size 0.6 "crosshair size when wielding the porto" +seta crosshair_minstanex "" "crosshair to display when wielding the minstanex gun" +seta crosshair_minstanex_color "0.65 0.65 1" "crosshair color to display when wielding the minstanex gun" +seta crosshair_minstanex_alpha 1 "crosshair alpha value to display when wielding the minstanex gun" +seta crosshair_minstanex_size 0.4 "crosshair size when wielding the minstanex gun" +seta crosshair_hook "" "crosshair to display when wielding the hook" +seta crosshair_hook_color "0.65 1 0.85" "crosshair color to display when wielding the hook" +seta crosshair_hook_alpha 0.85 "crosshair alpha value to display when wielding the hook" +seta crosshair_hook_size 0.5 "crosshair size when wielding the hook" +seta crosshair_hlac "" "crosshair to display when wielding the H.L.A.C" +seta crosshair_hlac_color "1 0.65 0.2" "crosshair color to display when wielding the H.L.A.C." +seta crosshair_hlac_alpha 1 "crosshair alpha value to display when wielding the H.L.A.C." +seta crosshair_hlac_size 0.6 "crosshair size when wielding the H.L.A.C." +seta crosshair_seeker "" "crosshair to display when wielding the TAG Seeker" +seta crosshair_seeker_color "1 0.35 0.35" "crosshair color to display when wielding the TAG seeker" +seta crosshair_seeker_alpha 0.9 "crosshair alpha value to display when wielding the TAG seeker" +seta crosshair_seeker_size 0.8 "crosshair size when wielding the TAG seeker" +seta crosshair_rifle "" "crosshair to display when wielding the rifle" +seta crosshair_rifle_color "0.85 0.5 0.25" "crosshair color to display when wielding the rifle" +seta crosshair_rifle_alpha 1 "crosshair alpha value to display when wielding the rifle" +seta crosshair_rifle_size 0.5 "crosshair size when wielding the rifle" +seta crosshair_tuba "" "crosshair to display when wielding the tuba" +seta crosshair_tuba_color "0.85 0.5 0.25" "crosshair color to display when wielding the tuba" +seta crosshair_tuba_alpha 1 "crosshair alpha value to display when wielding the tuba" +seta crosshair_tuba_size 1 "crosshair size when wielding the tuba" +seta crosshair_fireball "" "crosshair to display when wielding the fireball" +seta crosshair_fireball_color "0.2 1.0 0.2" "crosshair color to display when wielding the fireball" +seta crosshair_fireball_alpha 1 "crosshair alpha value to display when wielding the fireball" +seta crosshair_fireball_size 1 "crosshair size when wielding the fireball" + // ========================= // Crosshair ring settings @@ -55,15 +133,15 @@ seta crosshair_ring_inner 0 "allow inner rings to be drawn too" seta crosshair_ring_size 2 "ring size" seta crosshair_ring_alpha 0.2 "ring alpha" -// vortex ring // WEAPONTODO: Make this part of the crosshair line in REGISTER_WEAPON -seta crosshair_ring_vortex 1 "draw a ring showing the current charge of the vortex" -seta crosshair_ring_vortex_alpha 0.15 -seta crosshair_ring_vortex_inner_alpha 0.15 -seta crosshair_ring_vortex_inner_color_red 0.8 -seta crosshair_ring_vortex_inner_color_green 0 -seta crosshair_ring_vortex_inner_color_blue 0 -seta crosshair_ring_vortex_currentcharge_scale 30 -seta crosshair_ring_vortex_currentcharge_movingavg_rate 0.05 +// nexgun ring +seta crosshair_ring_nex 1 "draw a ring showing the current charge of the nexgun" +seta crosshair_ring_nex_alpha 0.15 +seta crosshair_ring_nex_inner_alpha 0.15 +seta crosshair_ring_nex_inner_color_red 0.8 +seta crosshair_ring_nex_inner_color_green 0 +seta crosshair_ring_nex_inner_color_blue 0 +seta crosshair_ring_nex_currentcharge_scale 30 +seta crosshair_ring_nex_currentcharge_movingavg_rate 0.05 // minelayer ring seta crosshair_ring_minelayer 1 diff --git a/defaultXPM.cfg b/defaultXPM.cfg index f6f25d338..4a55a5ee7 100644 --- a/defaultXPM.cfg +++ b/defaultXPM.cfg @@ -3,7 +3,7 @@ // ================== exec defaultXonotic.cfg -exec balance-xpm.cfg +exec balanceXPM.cfg // general gameplay set g_norecoil 1 diff --git a/defaultXonotic.cfg b/defaultXonotic.cfg index 9480860c6..18af3e895 100644 --- a/defaultXonotic.cfg +++ b/defaultXonotic.cfg @@ -57,7 +57,7 @@ _cl_playerskin 0 seta cl_reticle 1 "control for toggling whether ANY zoom reticles are shown" seta cl_reticle_stretch 0 "whether to stretch reticles so they fit the screen (breaks image proportions)" -seta cl_reticle_item_vortex 1 "draw aiming reticle for the vortex weapon's zoom, 0 disables and values between 0 and 1 change alpha" +seta cl_reticle_item_nex 1 "draw aiming reticle for the nex weapon's zoom, 0 disables and values between 0 and 1 change alpha" seta cl_reticle_item_normal 1 "draw reticle when zooming with the zoom button, 0 disables and values between 0 and 1 change alpha" fov 100 seta cl_velocityzoom 0 "velocity based zooming of fov, negative values zoom out" @@ -360,9 +360,9 @@ set bot_ai_keyboard_threshold 0.57 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 "vaporizer vortex rifle electro devastator grenadelauncher hagar hlac crylink laser machinegun fireball seeker shotgun tuba minelayer" "Desired weapons for far distances ordered by priority" -set bot_ai_custom_weapon_priority_mid "vaporizer devastator vortex fireball seeker mortar electro machinegun crylink hlac hagar shotgun blaster rifle tuba minelayer arc shockwave" "Desired weapons for middle distances ordered by priority" -set bot_ai_custom_weapon_priority_close "vaporizer shotgun vortex machinegun hlac tuba seeker hagar crylink mortar electro rocketlauncher blaster fireball rifle minelayer arc shockwave" "Desired weapons for close distances ordered by priority" +set bot_ai_custom_weapon_priority_far "minstanex nex rifle electro rocketlauncher grenadelauncher hagar hlac crylink laser uzi fireball seeker shotgun tuba minelayer" "Desired weapons for far distances ordered by priority" +set bot_ai_custom_weapon_priority_mid "minstanex rocketlauncher nex fireball seeker grenadelauncher electro uzi crylink hlac hagar shotgun laser rifle tuba minelayer" "Desired weapons for middle distances ordered by priority" +set bot_ai_custom_weapon_priority_close "minstanex shotgun nex uzi hlac tuba seeker hagar crylink grenadelauncher electro rocketlauncher laser fireball rifle minelayer" "Desired weapons for close distances ordered by priority" set bot_ai_weapon_combo 1 "Enable bots to do weapon combos" set bot_ai_weapon_combo_threshold 0.4 "Try to make a combo N seconds after the last attack" set bot_ai_friends_aware_pickup_radius "500" "Bots will not pickup items if a team mate is this distance near the item" @@ -1144,12 +1144,12 @@ sv_allowdownloads 0 // download protocol is evil set g_jump_grunt 0 "Do you make a grunting noise every time you jump? Is it the same grunting noise every time?" -seta cl_weaponpriority "minstanex vortex fireball grenadelauncher machinegun hagar rifle electro rocketlauncher crylink minelayer shotgun hlac tuba laser porto seeker hook" "weapon priority list" +seta cl_weaponpriority "minstanex nex fireball grenadelauncher uzi hagar rifle electro rocketlauncher crylink minelayer shotgun hlac tuba laser porto seeker hook" "weapon priority list" seta cl_weaponpriority_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 vortex 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 vortex rifle" "use impulse 202 for prev gun from this list, 212 for best gun, 222 for next gun. Default value: hitscan exact" -seta cl_weaponpriority3 "minstanex vortex rifle machinegun shotgun" "use impulse 203 for prev gun from this list, 213 for best gun, 223 for next gun. Default value: hitscan all" +seta cl_weaponpriority1 "minstanex nex crylink hlac electro laser" "use impulse 201 for prev gun from this list, 211 for best gun, 221 for next gun. Default value: energy" +seta cl_weaponpriority2 "minstanex nex rifle" "use impulse 202 for prev gun from this list, 212 for best gun, 222 for next gun. Default value: hitscan exact" +seta cl_weaponpriority3 "minstanex nex rifle uzi shotgun" "use impulse 203 for prev gun from this list, 213 for best gun, 223 for next gun. Default value: hitscan all" seta cl_weaponpriority4 "grenadelauncher minelayer hlac hagar crylink seeker shotgun" "use impulse 204 for prev gun from this list, 214 for best gun, 224 for next gun. Default value: spam weapons" seta cl_weaponpriority5 "laser hook porto" "use impulse 205 for prev gun from this list, 215 for best gun, 225 for next gun. Default value: weapons for moving" seta cl_weaponpriority6 "" "use impulse 206 for prev gun from this list, 216 for best gun, 226 for next gun" @@ -1383,19 +1383,19 @@ cl_decals_newsystem 1 // set the cvars to "0" to totally disable a weapon set g_weaponreplace_laser "" set g_weaponreplace_shotgun "" -set g_weaponreplace_machinegun "" +set g_weaponreplace_uzi "" set g_weaponreplace_grenadelauncher "" set g_weaponreplace_electro "" set g_weaponreplace_crylink "" -set g_weaponreplace_vortex "" +set g_weaponreplace_nex "" set g_weaponreplace_hagar "" set g_weaponreplace_rocketlauncher "" set g_weaponreplace_porto "" -set g_weaponreplace_vaporizer "" +set g_weaponreplace_minstanex "" set g_weaponreplace_hook "" set g_weaponreplace_tuba "" set g_weaponreplace_fireball "" -set sv_q3acompat_machineshotgunswap 0 "shorthand for swapping machinegun and shotgun (for Q3A map compatibility in mapinfo files)" +set sv_q3acompat_machineshotgunswap 0 "shorthand for swapping uzi and shotgun (for Q3A map compatibility in mapinfo files)" set g_movement_highspeed 1 "movement speed modification factor (only changes movement when above maxspeed)" @@ -1549,7 +1549,8 @@ scr_loadingscreen_scale_base 1 scr_loadingscreen_scale_limit 2 // other config files -exec balance-xonotic.cfg +exec mutator_new_toys.cfg // run BEFORE balance to make sure balance wins +exec balanceXonotic.cfg exec effects-normal.cfg exec physicsX.cfg exec turrets.cfg diff --git a/effectinfo.txt b/effectinfo.txt index 0ca352eea..782521447 100644 --- a/effectinfo.txt +++ b/effectinfo.txt @@ -7411,8 +7411,8 @@ velocityjitter 64 64 64 //lightcolor 1 0.9 0.7 //lightshadow 1 - // heal ray muzzleflash + effect healray_muzzleflash countabsolute 1 type smoke @@ -8949,48 +8949,3 @@ alpha 644 956 2500 originjitter 64 64 64 velocityjitter 324 324 324 rotate -180 180 -100 100 - -// shockwave_attack -// used nowhere in code -effect shockwave_attack // glow and light - //countabsolute 1 - //type smoke - //color 0xcc0000 0xff0000 - //tex 65 65 - //size 10 15 - //alpha 256 512 6280 - //airfriction 10 - //sizeincrease 1.5 - //stretchfactor 2 - //lightradius 200 - //lightradiusfade 2000 - //lightcolor 3 0.1 0.1 -effect shockwave_attack // electricity - count 1 - type spark - color 0xb44215 0xff0000 - tex 43 43 - size 5 7 - bounce 0 - alpha 4096 4096 20000 - airfriction 1 - originjitter 2 2 2 - velocityjitter 10 10 10 - velocitymultiplier 10 - sizeincrease 1.5 - stretchfactor 2.3 - rotate -180 180 4000 -4000 -effect shockwave_attack // fire - count 1 - type spark - color 0xff4200 0xff0000 - tex 8 15 - size 7 9 - bounce 0 - alpha 4096 4096 20000 - airfriction 1 - originjitter 2 2 2 - velocityjitter 10 10 10 - velocitymultiplier 10 - sizeincrease 1.5 - stretchfactor 2 diff --git a/models/weapons/g_arc.md3 b/models/weapons/g_arc.md3 deleted file mode 100755 index 878373964..000000000 Binary files a/models/weapons/g_arc.md3 and /dev/null differ diff --git a/models/weapons/h_arc.iqm b/models/weapons/h_arc.iqm deleted file mode 100755 index 9c4a29dbb..000000000 Binary files a/models/weapons/h_arc.iqm and /dev/null differ diff --git a/models/weapons/h_arc.iqm.framegroups b/models/weapons/h_arc.iqm.framegroups deleted file mode 100755 index 1c95207bd..000000000 --- a/models/weapons/h_arc.iqm.framegroups +++ /dev/null @@ -1,6 +0,0 @@ -1 8 20 0 // fire -9 23 20 0 // fire2 -32 200 20 1 // idle -232 40 20 0 // reload -// compile opts used in the iqm exporter (apparently needed to prevent insane ram usage): -// fire:1:8, fire2:1:23, idle:1:200, reload:1:40 diff --git a/models/weapons/v_arc.md3 b/models/weapons/v_arc.md3 deleted file mode 100755 index 7415aba60..000000000 Binary files a/models/weapons/v_arc.md3 and /dev/null differ diff --git a/models/weapons/w_crylink.zym b/models/weapons/w_crylink.zym new file mode 100644 index 000000000..4aea5b861 Binary files /dev/null and b/models/weapons/w_crylink.zym differ diff --git a/models/weapons/w_electro.zym b/models/weapons/w_electro.zym new file mode 100644 index 000000000..70cbd174e Binary files /dev/null and b/models/weapons/w_electro.zym differ diff --git a/models/weapons/w_gl.zym b/models/weapons/w_gl.zym new file mode 100644 index 000000000..5f28a0a1d Binary files /dev/null and b/models/weapons/w_gl.zym differ diff --git a/models/weapons/w_hagar.zym b/models/weapons/w_hagar.zym new file mode 100644 index 000000000..d8d78710f Binary files /dev/null and b/models/weapons/w_hagar.zym differ diff --git a/models/weapons/w_laser.zym b/models/weapons/w_laser.zym new file mode 100644 index 000000000..459b932ac Binary files /dev/null and b/models/weapons/w_laser.zym differ diff --git a/models/weapons/w_nex.zym b/models/weapons/w_nex.zym new file mode 100644 index 000000000..26ae92476 Binary files /dev/null and b/models/weapons/w_nex.zym differ diff --git a/models/weapons/w_rl.zym b/models/weapons/w_rl.zym new file mode 100644 index 000000000..6d3f70193 Binary files /dev/null and b/models/weapons/w_rl.zym differ diff --git a/models/weapons/w_shotgun.zym b/models/weapons/w_shotgun.zym new file mode 100644 index 000000000..031fa8609 Binary files /dev/null and b/models/weapons/w_shotgun.zym differ diff --git a/models/weapons/w_uzi.zym b/models/weapons/w_uzi.zym new file mode 100644 index 000000000..f86923748 Binary files /dev/null and b/models/weapons/w_uzi.zym differ diff --git a/mutator_new_toys.cfg b/mutator_new_toys.cfg new file mode 100644 index 000000000..9835f41dd --- /dev/null +++ b/mutator_new_toys.cfg @@ -0,0 +1,166 @@ +set g_new_toys 0 "Mutator 'New Toys': enable extra fun guns" +set g_new_toys_autoreplace 2 "0: never replace, 1: always auto replace guns by available new toys, 2: randomly auto replace guns by available new toys" + +set g_weaponreplace_hlac "" +set g_weaponreplace_minelayer "" +set g_weaponreplace_rifle "" +set g_weaponreplace_seeker "" + +set g_start_weapon_hlac -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" // UNTIL IT CAN BE REMOVED FROM CODE +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_rifle -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" // UNTIL IT CAN BE REMOVED FROM CODE +set g_start_weapon_seeker -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" + +// {{{ hlac +set g_balance_hlac_primary_spread_min 0.01 +set g_balance_hlac_primary_spread_max 0.25 +set g_balance_hlac_primary_spread_add 0.0045 +set g_balance_hlac_primary_spread_crouchmod 0.25 + +set g_balance_hlac_primary_damage 18 +set g_balance_hlac_primary_edgedamage 9 +set g_balance_hlac_primary_force 90 +set g_balance_hlac_primary_radius 70 +set g_balance_hlac_primary_speed 9000 +set g_balance_hlac_primary_lifetime 5 + +set g_balance_hlac_primary_refire 0.15 +set g_balance_hlac_primary_animtime 0.4 +set g_balance_hlac_primary_ammo 1 + +set g_balance_hlac_secondary 1 +set g_balance_hlac_secondary_spread 0.15 +set g_balance_hlac_secondary_spread_crouchmod 0.5 + +set g_balance_hlac_secondary_damage 15 +set g_balance_hlac_secondary_edgedamage 7.5 +set g_balance_hlac_secondary_force 90 +set g_balance_hlac_secondary_radius 70 +set g_balance_hlac_secondary_speed 9000 +set g_balance_hlac_secondary_lifetime 5 + +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_shots 6 + +set g_balance_hlac_switchdelay_drop 0.2 +set g_balance_hlac_switchdelay_raise 0.2 + +set g_balance_hlac_reload_ammo 0 //default: 20 +set g_balance_hlac_reload_time 2 +// }}} +// {{{ minelayer +set g_balance_minelayer_damage 40 +set g_balance_minelayer_edgedamage 20 +set g_balance_minelayer_force 250 +set g_balance_minelayer_radius 175 +set g_balance_minelayer_proximityradius 150 +set g_balance_minelayer_speed 1000 +set g_balance_minelayer_lifetime 10 +set g_balance_minelayer_lifetime_countdown 0.5 +set g_balance_minelayer_refire 1.5 +set g_balance_minelayer_animtime 0.4 +set g_balance_minelayer_ammo 4 +set g_balance_minelayer_health 15 +set g_balance_minelayer_limit 3 // 0 disables the limit +set g_balance_minelayer_protection 0 // 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 +set g_balance_minelayer_switchdelay_drop 0.2 +set g_balance_minelayer_switchdelay_raise 0.2 +set g_balance_minelayer_reload_ammo 0 //default: 15 +set g_balance_minelayer_reload_time 2 +// }}} +// {{{ rifle +set g_balance_rifle_bursttime 0 +set g_balance_rifle_primary_tracer 1 +set g_balance_rifle_primary_shots 1 +set g_balance_rifle_primary_damage 80 +set g_balance_rifle_primary_spread 0 +set g_balance_rifle_primary_force 100 +set g_balance_rifle_primary_refire 1.2 +set g_balance_rifle_primary_animtime 0.4 +set g_balance_rifle_primary_ammo 10 +set g_balance_rifle_primary_solidpenetration 62.2 +set g_balance_rifle_primary_burstcost 0 +set g_balance_rifle_primary_bullethail 0 // empty magazine on shot +set g_balance_rifle_secondary 1 +set g_balance_rifle_secondary_reload 0 +set g_balance_rifle_secondary_tracer 0 +set g_balance_rifle_secondary_shots 4 +set g_balance_rifle_secondary_damage 20 +set g_balance_rifle_secondary_spread 0.04 +set g_balance_rifle_secondary_force 50 +set g_balance_rifle_secondary_refire 0.9 +set g_balance_rifle_secondary_animtime 0.3 +set g_balance_rifle_secondary_ammo 10 +set g_balance_rifle_secondary_solidpenetration 15.5 +set g_balance_rifle_secondary_burstcost 0 +set g_balance_rifle_secondary_bullethail 0 // empty magazine on shot +set g_balance_rifle_switchdelay_drop 0.2 +set g_balance_rifle_switchdelay_raise 0.2 +set g_balance_rifle_reload_ammo 80 //default: 80 +set g_balance_rifle_reload_time 2 +// }}} +// {{{ seeker +set g_balance_seeker_type 0 // 0 = old seeker, 1 = new seeker +set g_balance_seeker_flac_ammo 1 +set g_balance_seeker_flac_animtime 0.1 +set g_balance_seeker_flac_damage 15 +set g_balance_seeker_flac_edgedamage 10 +set g_balance_seeker_flac_force 50 +set g_balance_seeker_flac_lifetime 0.1 +set g_balance_seeker_flac_lifetime_rand 0.05 +set g_balance_seeker_flac_radius 100 +set g_balance_seeker_flac_refire 0.1 +set g_balance_seeker_flac_speed 3000 +set g_balance_seeker_flac_speed_up 1000 +set g_balance_seeker_flac_speed_z 0 +set g_balance_seeker_flac_spread 0.4 +set g_balance_seeker_tag_ammo 1 +set g_balance_seeker_tag_animtime 0.2 +set g_balance_seeker_tag_damageforcescale 4 +set g_balance_seeker_tag_health 5 +set g_balance_seeker_tag_lifetime 15 +set g_balance_seeker_tag_refire 0.75 // LOG: 0.7 -> 0.75 +set g_balance_seeker_tag_speed 5000 +set g_balance_seeker_tag_spread 0 +set g_balance_seeker_tag_tracker_lifetime 10 +set g_balance_seeker_missile_accel 1400 +set g_balance_seeker_missile_ammo 2 +set g_balance_seeker_missile_animtime 0.2 +set g_balance_seeker_missile_count 3 // LOG: 8 -> 3 +set g_balance_seeker_missile_damage 30 // LOG: 15 -> 30 +set g_balance_seeker_missile_damageforcescale 4 +set g_balance_seeker_missile_decel 1400 +set g_balance_seeker_missile_delay 0.25 +set g_balance_seeker_missile_edgedamage 10 +set g_balance_seeker_missile_force 150 // LOG: 100 -> 150 +set g_balance_seeker_missile_health 5 +set g_balance_seeker_missile_lifetime 15 +set g_balance_seeker_missile_proxy 0 +set g_balance_seeker_missile_proxy_delay 0.2 +set g_balance_seeker_missile_proxy_maxrange 45 +set g_balance_seeker_missile_radius 80 +set g_balance_seeker_missile_refire 0.5 +set g_balance_seeker_missile_smart 1 +set g_balance_seeker_missile_smart_mindist 800 +set g_balance_seeker_missile_smart_trace_max 2500 +set g_balance_seeker_missile_smart_trace_min 1000 +set g_balance_seeker_missile_speed 700 +set g_balance_seeker_missile_speed_up 300 +set g_balance_seeker_missile_speed_z 0 +set g_balance_seeker_missile_speed_max 1300 // LOG: 1400 -> 1300 +set g_balance_seeker_missile_spread 0 +set g_balance_seeker_missile_turnrate 0.65 +set g_balance_seeker_switchdelay_drop 0.2 +set g_balance_seeker_switchdelay_raise 0.2 +set g_balance_seeker_reload_ammo 0 //default: 15 +set g_balance_seeker_reload_time 2 +// End new seeker diff --git a/mutators.cfg b/mutators.cfg index 6873aa89e..4b7904867 100644 --- a/mutators.cfg +++ b/mutators.cfg @@ -231,13 +231,6 @@ set g_campcheck_damage 100 set g_campcheck_distance 1800 -<<<<<<< HEAD -// ========== -// New Toys -// ========== -set g_new_toys 0 "Mutator 'New Toys': enable extra fun guns" -set g_new_toys_autoreplace 2 "0: never replace, 1: always auto replace guns by available new toys, 2: randomly auto replace guns by available new toys" -======= // ======= // buffs // ======= @@ -284,4 +277,3 @@ set g_buffs_flight_gravity 0.3 "player gravity multiplier while holding flight b set g_buffs_invisible 1 "invisible buff: carrier becomes invisible" set g_buffs_invisible_alpha 0.4 "player invisibility multiplier while holding invisible buff" ->>>>>>> master diff --git a/oldbalance25.cfg b/oldbalance25.cfg deleted file mode 100644 index df43b549e..000000000 --- a/oldbalance25.cfg +++ /dev/null @@ -1,780 +0,0 @@ -g_mod_balance Nexuiz25 - -// {{{ starting gear -set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_balance_health_start 150 -set g_balance_armor_start 0 -set g_start_ammo_shells 40 -set g_start_ammo_nails 0 -set g_start_ammo_rockets 0 -set g_start_ammo_cells 0 -set g_start_ammo_fuel 0 -set g_warmup_start_health 250 "starting values when being in warmup-stage" -set g_warmup_start_armor 100 "starting values when being in warmup-stage" -set g_warmup_start_ammo_shells 50 "starting values when being in warmup-stage" -set g_warmup_start_ammo_nails 150 "starting values when being in warmup-stage" -set g_warmup_start_ammo_rockets 50 "starting values when being in warmup-stage" -set g_warmup_start_ammo_cells 50 "starting values when being in warmup-stage" -set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage" -set g_lms_start_health 250 -set g_lms_start_armor 100 -set g_lms_start_ammo_shells 50 -set g_lms_start_ammo_nails 150 -set g_lms_start_ammo_rockets 50 -set g_lms_start_ammo_cells 50 -set g_lms_start_ammo_fuel 0 -set g_balance_nix_roundtime 25 -set g_balance_nix_incrtime 1.6 -set g_balance_nix_ammo_shells 15 -set g_balance_nix_ammo_nails 45 -set g_balance_nix_ammo_rockets 15 -set g_balance_nix_ammo_cells 15 -set g_balance_nix_ammo_fuel 0 -set g_balance_nix_ammoincr_shells 2 -set g_balance_nix_ammoincr_nails 6 -set g_balance_nix_ammoincr_rockets 2 -set g_balance_nix_ammoincr_cells 2 -set g_balance_nix_ammoincr_fuel 2 -// }}} - -// {{{ pickup items -set g_pickup_ammo_anyway 0 -set g_pickup_weapons_anyway 0 -set g_pickup_shells 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_pickup_armorsmall_max 999 -set g_pickup_armorsmall_anyway 0 -set g_pickup_armormedium 25 -set g_pickup_armormedium_max 999 -set g_pickup_armormedium_anyway 0 -set g_pickup_armorbig 50 -set g_pickup_armorbig_max 999 -set g_pickup_armorbig_anyway 0 -set g_pickup_armorlarge 100 -set g_pickup_armorlarge_max 999 -set g_pickup_armorlarge_anyway 0 -set g_pickup_healthsmall 5 -set g_pickup_healthsmall_max 999 -set g_pickup_healthsmall_anyway 0 -set g_pickup_healthmedium 25 -set g_pickup_healthmedium_max 999 -set g_pickup_healthmedium_anyway 0 -set g_pickup_healthlarge 50 -set g_pickup_healthlarge_max 999 -set g_pickup_healthlarge_anyway 0 -set g_pickup_healthmega 100 -set g_pickup_healthmega_max 999 -set g_pickup_healthmega_anyway 0 -set g_pickup_respawntime_short 15 -set g_pickup_respawntime_medium 20 -set g_pickup_respawntime_long 30 -set g_pickup_respawntime_powerup 120 -set g_pickup_respawntime_weapon 15 -set g_pickup_respawntime_superweapon 120 -set g_pickup_respawntime_ammo 15 -set g_pickup_respawntimejitter_short 0 -set g_pickup_respawntimejitter_medium 0 -set g_pickup_respawntimejitter_long 0 -set g_pickup_respawntimejitter_powerup 10 -set g_pickup_respawntimejitter_weapon 0 -set g_pickup_respawntimejitter_superweapon 10 -set g_pickup_respawntimejitter_ammo 0 -// }}} - -// {{{ regen/rot -set g_balance_health_regen 0.1 -set g_balance_health_regenlinear 0 -set g_balance_pause_health_regen 5 -set g_balance_pause_health_regen_spawn 0 -set g_balance_health_rot 0.1 -set g_balance_health_rotlinear 0 -set g_balance_pause_health_rot 5 -set g_balance_pause_health_rot_spawn 10 -set g_balance_health_regenstable 100 -set g_balance_health_rotstable 100 -set g_balance_health_limit 999 -set g_balance_armor_regen 0 -set g_balance_armor_regenlinear 0 -set g_balance_armor_rot 0.1 -set g_balance_armor_rotlinear 0 -set g_balance_pause_armor_rot 5 -set g_balance_pause_armor_rot_spawn 10 -set g_balance_armor_regenstable 100 -set g_balance_armor_rotstable 100 -set g_balance_armor_limit 999 -set g_balance_armor_blockpercent 0.6 -set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)" -set g_balance_fuel_regenlinear 0 -set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter -set g_balance_fuel_rot 0.05 -set g_balance_fuel_rotlinear 0 -set g_balance_pause_fuel_rot 5 -set g_balance_pause_fuel_rot_spawn 10 -set g_balance_fuel_regenstable 50 -set g_balance_fuel_rotstable 100 -set g_balance_fuel_limit 999 -// }}} - -// {{{ misc -set g_balance_selfdamagepercent 0.6 -set g_weaponspeedfactor 1 "weapon projectile speed multiplier" -set g_weaponratefactor 1 "weapon fire rate multiplier" -set g_weapondamagefactor 1 "weapon damage multiplier" -set g_weaponforcefactor 1 "weapon force multiplier" -set g_weaponspreadfactor 1 "weapon spread multiplier" -set g_balance_firetransfer_time 0.9 -set g_balance_firetransfer_damage 0.8 -set g_throughfloor_damage 1 -set g_throughfloor_force 1 -set g_projectiles_damage 2 -// possible values: -// -2: absolutely no damage to projectiles (no exceptions) -// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines) -// 0: only damage from contents (lava/slime) or exceptions -// 1: only self damage or damage from contents or exceptions -// 2: allow all damage to projectiles normally -set g_projectiles_keep_owner 0 -set g_projectiles_newton_style 2 -// possible values: -// 0: absolute velocity projectiles (like Quake) -// 1: relative velocity projectiles, "Newtonian" (like Tribes 2) -// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard) -set g_projectiles_newton_style_2_minfactor 0.7 -set g_projectiles_newton_style_2_maxfactor 5 -set g_projectiles_spread_style 0 -// possible values: -// 0: forward + solid sphere (like Quake) - varies velocity -// 1: forward + flattened solid sphere -// 2: forward + solid circle -// 3: forward + normal distribution 3D - varies velocity -// 4: forward + normal distribution on a plane -// 5: forward + circle with 1-r falloff -// 6: forward + circle with 1-r^2 falloff -// 7: forward + circle with (1-r)(2-r) falloff -set g_balance_falldamage_deadminspeed 150 -set g_balance_falldamage_minspeed 1400 -set g_balance_falldamage_factor 0.15 -set g_balance_falldamage_maxdamage 25 -set g_balance_damagepush_speedfactor 0 -set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage -set g_balance_contents_drowndelay 10 // time under water before a player begins drowning -set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning -set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava -set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime -set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime -set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap" -// }}} - -// {{{ powerups -set g_balance_powerup_invincible_takedamage 0.2 -set g_balance_powerup_invincible_time 30 -set g_balance_powerup_strength_damage 3 -set g_balance_powerup_strength_force 4 -set g_balance_powerup_strength_time 30 -set g_balance_powerup_strength_selfdamage 1.5 -set g_balance_powerup_strength_selfforce 1.5 -set g_balance_superweapons_time 30 -// }}} - -// {{{ jetpack/hook -set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack" -set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction" -set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)" -set g_jetpack_maxspeed_side 1500 "max speed of the jetpack in xy direction" -set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction" -set g_jetpack_fuel 8 "fuel per second for jetpack" -set g_jetpack_attenuation 2 "jetpack sound attenuation" - -set g_grappling_hook_tarzan 2 // 2: can also pull players -set g_balance_grapplehook_speed_fly 1800 -set g_balance_grapplehook_speed_pull 2000 -set g_balance_grapplehook_force_rubber 2000 -set g_balance_grapplehook_force_rubber_overstretch 1000 -set g_balance_grapplehook_length_min 50 -set g_balance_grapplehook_stretch 50 -set g_balance_grapplehook_airfriction 0.2 -set g_balance_grapplehook_health 130 -set g_balance_grapplehook_damagedbycontents 0 -set g_balance_grapplehook_refire 0.2 -// }}} - -// {{{ weapon properties -// {{{ laser -set g_balance_laser_melee_animtime 0.3 -set g_balance_laser_melee_damage 80 -set g_balance_laser_melee_delay 0.25 -set g_balance_laser_melee_force 200 -set g_balance_laser_melee_multihit 1 -set g_balance_laser_melee_no_doubleslap 1 -set g_balance_laser_melee_nonplayerdamage 40 -set g_balance_laser_melee_range 120 -set g_balance_laser_melee_refire 1.25 -set g_balance_laser_melee_swing_side 120 -set g_balance_laser_melee_swing_up 30 -set g_balance_laser_melee_time 0.15 -set g_balance_laser_melee_traces 10 - -set g_balance_laser_primary 1 // 0 = shockwave attack, 1 = projectile primary -set g_balance_laser_primary_damage 35 -set g_balance_laser_primary_edgedamage 10 -set g_balance_laser_primary_force 400 -set g_balance_laser_primary_radius 70 -set g_balance_laser_primary_speed 9000 -set g_balance_laser_primary_spread 0 -set g_balance_laser_primary_refire 0.7 -set g_balance_laser_primary_animtime 0.3 -set g_balance_laser_primary_lifetime 30 -set g_balance_laser_primary_shotangle 0 -set g_balance_laser_primary_delay 0.05 -set g_balance_laser_primary_force_zscale 1 -set g_balance_laser_primary_force_velocitybias 0 -set g_balance_laser_primary_force_other_scale 1 - -set g_balance_laser_secondary 0 // 0 = switch away to last used weapon, 1 = projectile secondary, 2 = melee secondary -set g_balance_laser_secondary_damage 35 -set g_balance_laser_secondary_edgedamage 10 -set g_balance_laser_secondary_force 400 -set g_balance_laser_secondary_radius 70 -set g_balance_laser_secondary_speed 9000 -set g_balance_laser_secondary_spread 0 -set g_balance_laser_secondary_refire 0.7 -set g_balance_laser_secondary_animtime 0.3 -set g_balance_laser_secondary_lifetime 30 -set g_balance_laser_secondary_shotangle 0 -set g_balance_laser_secondary_delay 0 -set g_balance_laser_secondary_force_zscale 1 -set g_balance_laser_secondary_force_velocitybias 0 -set g_balance_laser_secondary_force_other_scale 1 - -set g_balance_laser_shockwave_damage 20 -set g_balance_laser_shockwave_distance 2000 -set g_balance_laser_shockwave_edgedamage 0 -set g_balance_laser_shockwave_force 200 -set g_balance_laser_shockwave_force_forwardbias 50 -set g_balance_laser_shockwave_force_zscale 1.5 -set g_balance_laser_shockwave_jump_damage 20 -set g_balance_laser_shockwave_jump_edgedamage 0 -set g_balance_laser_shockwave_jump_force 300 -set g_balance_laser_shockwave_jump_force_velocitybias 0 -set g_balance_laser_shockwave_jump_force_zscale 1.25 -set g_balance_laser_shockwave_jump_multiplier_accuracy 0.5 -set g_balance_laser_shockwave_jump_multiplier_distance 0.5 -set g_balance_laser_shockwave_jump_multiplier_min 0 -set g_balance_laser_shockwave_jump_radius 150 -set g_balance_laser_shockwave_multiplier_accuracy 0.5 -set g_balance_laser_shockwave_multiplier_distance 0.5 -set g_balance_laser_shockwave_multiplier_min 0 -set g_balance_laser_shockwave_splash_damage 15 -set g_balance_laser_shockwave_splash_edgedamage 0 -set g_balance_laser_shockwave_splash_force 100 -set g_balance_laser_shockwave_splash_force_forwardbias 50 -set g_balance_laser_shockwave_splash_multiplier_accuracy 0.5 -set g_balance_laser_shockwave_splash_multiplier_distance 0.5 -set g_balance_laser_shockwave_splash_multiplier_min 0 -set g_balance_laser_shockwave_splash_radius 70 -set g_balance_laser_shockwave_spread_max 100 -set g_balance_laser_shockwave_spread_min 20 - -set g_balance_laser_switchdelay_drop 0.15 -set g_balance_laser_switchdelay_raise 0.15 -set g_balance_laser_reload_ammo 0 //default: 6 -set g_balance_laser_reload_time 2 -// }}} -// {{{ shotgun -set g_balance_shotgun_primary_bullets 6 -set g_balance_shotgun_primary_damage 9 -set g_balance_shotgun_primary_force 60 -set g_balance_shotgun_primary_spread 0.07 -set g_balance_shotgun_primary_refire 0.5 -set g_balance_shotgun_primary_animtime 0.2 -set g_balance_shotgun_primary_ammo 1 -set g_balance_shotgun_primary_solidpenetration 3.8 -set g_balance_shotgun_secondary 1 -set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow -set g_balance_shotgun_secondary_melee_range 120 -set g_balance_shotgun_secondary_melee_swing_side 120 -set g_balance_shotgun_secondary_melee_swing_up 30 -set g_balance_shotgun_secondary_melee_time 0.15 -set g_balance_shotgun_secondary_melee_traces 10 -set g_balance_shotgun_secondary_melee_no_doubleslap 1 -set g_balance_shotgun_secondary_melee_nonplayerdamage 0 -set g_balance_shotgun_secondary_melee_multihit 1 -set g_balance_shotgun_secondary_damage 115 -set g_balance_shotgun_secondary_force 150 -set g_balance_shotgun_secondary_refire 1.1 -set g_balance_shotgun_secondary_animtime 1 -set g_balance_shotgun_switchdelay_drop 0.15 -set g_balance_shotgun_switchdelay_raise 0.15 -set g_balance_shotgun_reload_ammo 0 //default: 5 -set g_balance_shotgun_reload_time 2 -// }}} -// {{{ uzi -set g_balance_uzi_mode 0 // Activates varible spread for sustained & burst mode secondary -set g_balance_uzi_spread_min 0.02 -set g_balance_uzi_spread_max 0.6 -set g_balance_uzi_spread_add 0.012 - -set g_balance_uzi_burst 0 // # of bullets in a burst (if set to 2 or more) -set g_balance_uzi_burst_animtime 0.75 -set g_balance_uzi_burst_refire 0.05 // refire between burst bullets -set g_balance_uzi_burst_refire2 0.75 // refire after burst -set g_balance_uzi_burst_spread 0.04 -set g_balance_uzi_burst_damage 18 -set g_balance_uzi_burst_force 50 -set g_balance_uzi_burst_ammo 3 - -set g_balance_uzi_first 1 -set g_balance_uzi_first_damage 30 -set g_balance_uzi_first_force 50 -set g_balance_uzi_first_spread 0.015 -set g_balance_uzi_first_refire 0.2 -set g_balance_uzi_first_ammo 1 - -set g_balance_uzi_sustained_damage 15 -set g_balance_uzi_sustained_force 27 -set g_balance_uzi_sustained_spread 0.05 -set g_balance_uzi_sustained_refire 0.1 -set g_balance_uzi_sustained_ammo 1 - -set g_balance_uzi_solidpenetration 13.1 - -set g_balance_uzi_switchdelay_drop 0.15 -set g_balance_uzi_switchdelay_raise 0.15 - -set g_balance_uzi_reload_ammo 0 //default: 30 -set g_balance_uzi_reload_time 2 -// }}} -// {{{ mortar -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_radius 140 -set g_balance_grenadelauncher_primary_speed 2000 -set g_balance_grenadelauncher_primary_speed_up 200 -set g_balance_grenadelauncher_primary_speed_z 0 -set g_balance_grenadelauncher_primary_spread 0 -set g_balance_grenadelauncher_primary_lifetime 30 -set g_balance_grenadelauncher_primary_lifetime2 1 -set g_balance_grenadelauncher_primary_refire 0.8 -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_primary_damageforcescale 4 -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_radius 140 -set g_balance_grenadelauncher_secondary_speed 1400 -set g_balance_grenadelauncher_secondary_speed_up 200 -set g_balance_grenadelauncher_secondary_speed_z 0 -set g_balance_grenadelauncher_secondary_spread 0 -set g_balance_grenadelauncher_secondary_lifetime 2.5 -set g_balance_grenadelauncher_secondary_lifetime_bounce 0 -set g_balance_grenadelauncher_secondary_lifetime_stick 0 -set g_balance_grenadelauncher_secondary_refire 0.7 -set g_balance_grenadelauncher_secondary_animtime 0.3 -set g_balance_grenadelauncher_secondary_ammo 2 -set g_balance_grenadelauncher_secondary_health 10 -set g_balance_grenadelauncher_secondary_damageforcescale 4 -set g_balance_grenadelauncher_secondary_remote_detonateprimary 0 - -set g_balance_grenadelauncher_bouncefactor 0.5 -set g_balance_grenadelauncher_bouncestop 0.075 - -set g_balance_grenadelauncher_switchdelay_drop 0.15 -set g_balance_grenadelauncher_switchdelay_raise 0.15 - -set g_balance_grenadelauncher_reload_ammo 0 //default: 12 -set g_balance_grenadelauncher_reload_time 2 -// }}} -// {{{ electro -set g_balance_electro_lightning 0 -set g_balance_electro_primary_damage 65 -set g_balance_electro_primary_edgedamage 0 -set g_balance_electro_primary_force 200 -set g_balance_electro_primary_force_up 0 -set g_balance_electro_primary_radius 150 -set g_balance_electro_primary_comboradius 0 -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.3 -set g_balance_electro_primary_ammo 2 -set g_balance_electro_primary_range 0 -set g_balance_electro_primary_falloff_mindist 255 // 0.3 * radius -set g_balance_electro_primary_falloff_maxdist 850 -set g_balance_electro_primary_falloff_halflifedist 425 -set g_balance_electro_secondary_damage 50 -set g_balance_electro_secondary_edgedamage 0 -set g_balance_electro_secondary_force 200 -set g_balance_electro_secondary_radius 150 -set g_balance_electro_secondary_speed 900 -set g_balance_electro_secondary_speed_up 200 -set g_balance_electro_secondary_speed_z 0 -set g_balance_electro_secondary_spread 0 -set g_balance_electro_secondary_lifetime 5 -set g_balance_electro_secondary_refire 0.3 -set g_balance_electro_secondary_refire2 0 -set g_balance_electro_secondary_animtime 0.3 -set g_balance_electro_secondary_ammo 2 -set g_balance_electro_secondary_health 5 -set g_balance_electro_secondary_damageforcescale 4 -set g_balance_electro_secondary_damagedbycontents 0 -set g_balance_electro_secondary_count 1 -set g_balance_electro_secondary_bouncefactor 0.5 -set g_balance_electro_secondary_bouncestop 0.075 -set g_balance_electro_combo_damage 80 -set g_balance_electro_combo_edgedamage 0 -set g_balance_electro_combo_force 200 -set g_balance_electro_combo_radius 250 -set g_balance_electro_combo_comboradius 0 -set g_balance_electro_combo_speed 2000 -set g_balance_electro_combo_safeammocheck 0 -set g_balance_electro_switchdelay_drop 0.15 -set g_balance_electro_switchdelay_raise 0.15 -set g_balance_electro_reload_ammo 0 //default: 20 -set g_balance_electro_reload_time 2 -// }}} -// {{{ lightning -set g_balance_lightning_primary_ammo 5 -set g_balance_lightning_primary_animtime 0.2 -set g_balance_lightning_primary_damage 100 -set g_balance_lightning_primary_edgedamage 0 -set g_balance_lightning_primary_falloff_mindist 0 -set g_balance_lightning_primary_falloff_maxdist 0 -set g_balance_lightning_primary_falloff_halflifedist 0 -set g_balance_lightning_primary_force 425 -set g_balance_lightning_primary_lifetime 0 -set g_balance_lightning_primary_radius 850 -set g_balance_lightning_primary_range 800 -set g_balance_lightning_primary_refire 0.4 -set g_balance_lightning_primary_speed 0 -set g_balance_lightning_primary_spread 0 -set g_balance_lightning_secondary_ammo 5 -set g_balance_lightning_secondary_animtime 0.5 -set g_balance_lightning_secondary_damage 100 -set g_balance_lightning_secondary_damageforcescale 4 -set g_balance_lightning_secondary_edgedamage 80 -set g_balance_lightning_secondary_flyingdamage 1 -set g_balance_lightning_secondary_flyingforce -80 -set g_balance_lightning_secondary_flyingradius 200 -set g_balance_lightning_secondary_force -200 -set g_balance_lightning_secondary_health 1 -set g_balance_lightning_secondary_lifetime 30 -set g_balance_lightning_secondary_radius 300 -set g_balance_lightning_secondary_refire 5 -set g_balance_lightning_secondary_speed 600 -// }}} -// {{{ crylink -set g_balance_crylink_primary_damage 18 -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_speed 7000 -set g_balance_crylink_primary_spread 0.03 -set g_balance_crylink_primary_shots 4 -set g_balance_crylink_primary_bounces 1 -set g_balance_crylink_primary_refire 0.4 -set g_balance_crylink_primary_animtime 0.3 -set g_balance_crylink_primary_ammo 2 -set g_balance_crylink_primary_bouncedamagefactor 0.5 -set g_balance_crylink_primary_joindelay 0 -set g_balance_crylink_primary_joinspread 0 -set g_balance_crylink_primary_joinexplode 0 -set g_balance_crylink_primary_joinexplode_damage 0 -set g_balance_crylink_primary_joinexplode_edgedamage 0 -set g_balance_crylink_primary_joinexplode_radius 0 -set g_balance_crylink_primary_joinexplode_force 0 -set g_balance_crylink_primary_linkexplode 1 - -set g_balance_crylink_primary_middle_lifetime 5 // range: 35000 full, fades to 70000 -set g_balance_crylink_primary_middle_fadetime 5 -set g_balance_crylink_primary_other_lifetime 0.1 // range: 700 full, fades to 2450 -set g_balance_crylink_primary_other_fadetime 0.25 - -set g_balance_crylink_secondary 1 -set g_balance_crylink_secondary_damage 18 -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_speed 7000 -set g_balance_crylink_secondary_spread 0.08 -set g_balance_crylink_secondary_spreadtype 0 -set g_balance_crylink_secondary_shots 7 -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_bouncedamagefactor 0.5 -set g_balance_crylink_secondary_joindelay 0 -set g_balance_crylink_secondary_joinspread 0 -set g_balance_crylink_secondary_joinexplode 0 -set g_balance_crylink_secondary_joinexplode_damage 0 -set g_balance_crylink_secondary_joinexplode_edgedamage 0 -set g_balance_crylink_secondary_joinexplode_radius 0 -set g_balance_crylink_secondary_joinexplode_force 0 -set g_balance_crylink_secondary_linkexplode 1 - -set g_balance_crylink_secondary_middle_lifetime 5 // range: 35000 full, fades to 70000 -set g_balance_crylink_secondary_middle_fadetime 5 -set g_balance_crylink_secondary_line_lifetime 2 // range: 35000 full, fades to 70000 -set g_balance_crylink_secondary_line_fadetime 2 - -set g_balance_crylink_switchdelay_drop 0.15 -set g_balance_crylink_switchdelay_raise 0.15 - -set g_balance_crylink_reload_ammo 0 //default: 10 -set g_balance_crylink_reload_time 2 -// }}} -// {{{ nex -set g_balance_nex_primary_damage 100 -set g_balance_nex_primary_force 600 -set g_balance_nex_primary_refire 1.5 -set g_balance_nex_primary_animtime 0.3 -set g_balance_nex_primary_ammo 5 -set g_balance_nex_primary_damagefalloff_mindist 0 -set g_balance_nex_primary_damagefalloff_maxdist 0 -set g_balance_nex_primary_damagefalloff_halflife 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_chargepool 0 -set g_balance_nex_secondary_chargepool_regen 0.15 -set g_balance_nex_secondary_chargepool_pause_regen 1 -set g_balance_nex_secondary_chargepool_pause_health_regen 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_animtime 0.3 -set g_balance_nex_secondary_ammo 5 -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_charge 0 -set g_balance_nex_charge_mindmg 40 -set g_balance_nex_charge_start 0 -set g_balance_nex_charge_rate 0.1 -set g_balance_nex_charge_animlimit 0.5 -set g_balance_nex_charge_limit 0.5 -set g_balance_nex_charge_rot_rate 0 -set g_balance_nex_charge_rot_pause 0 // Dont rot down until this long after release of charge button -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 - -set g_balance_nex_switchdelay_drop 0.15 -set g_balance_nex_switchdelay_raise 0.15 - -set g_balance_nex_reload_ammo 0 //default: 25 -set g_balance_nex_reload_time 2 -// }}} -// {{{ minstanex -set g_balance_minstanex_refire 1 -set g_balance_minstanex_animtime 0.3 -set g_balance_minstanex_ammo 10 -set g_balance_minstanex_laser_ammo 0 -set g_balance_minstanex_laser_animtime 0.3 -set g_balance_minstanex_laser_refire 0.7 -set g_balance_minstanex_switchdelay_drop 0.15 -set g_balance_minstanex_switchdelay_raise 0.15 -set g_balance_minstanex_reload_ammo 0 //default: 50 -set g_balance_minstanex_reload_time 2 -// }}} -// {{{ hagar -set g_balance_hagar_primary_damage 37 -set g_balance_hagar_primary_edgedamage 15 -set g_balance_hagar_primary_force 100 -set g_balance_hagar_primary_health 0 -set g_balance_hagar_primary_damageforcescale 0 -set g_balance_hagar_primary_radius 65 -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_secondary 1 -set g_balance_hagar_secondary_load 0 -set g_balance_hagar_secondary_load_speed 0.6 -set g_balance_hagar_secondary_load_spread 0.075 -set g_balance_hagar_secondary_load_spread_bias 0.5 -set g_balance_hagar_secondary_load_max 4 -set g_balance_hagar_secondary_load_hold 0 -set g_balance_hagar_secondary_load_releasedeath 1 -set g_balance_hagar_secondary_load_abort 1 -set g_balance_hagar_secondary_load_linkexplode 0 -set g_balance_hagar_secondary_load_animtime 0.2 -set g_balance_hagar_secondary_damage 37 -set g_balance_hagar_secondary_edgedamage 15 -set g_balance_hagar_secondary_force 100 -set g_balance_hagar_secondary_health 0 -set g_balance_hagar_secondary_damageforcescale 0 -set g_balance_hagar_secondary_radius 65 -set g_balance_hagar_secondary_spread 0.015 -set g_balance_hagar_secondary_speed 1400 -set g_balance_hagar_secondary_lifetime_min 30 -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_switchdelay_drop 0.15 -set g_balance_hagar_switchdelay_raise 0.15 -set g_balance_hagar_reload_ammo 0 //default: 25 -set g_balance_hagar_reload_time 2 -// }}} -// {{{ rocketlauncher -set g_balance_rocketlauncher_damage 105 -set g_balance_rocketlauncher_edgedamage 40 -set g_balance_rocketlauncher_force 600 -set g_balance_rocketlauncher_radius 150 -set g_balance_rocketlauncher_speed 850 -set g_balance_rocketlauncher_speedaccel 0 -set g_balance_rocketlauncher_speedstart 850 -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_health 40 -set g_balance_rocketlauncher_damageforcescale 4 -set g_balance_rocketlauncher_detonatedelay 0.2 // 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 90 // max degrees per second -set g_balance_rocketlauncher_guideratedelay 0.01 // immediate -set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic) -set g_balance_rocketlauncher_guidedelay 0.15 // delay before guiding kicks in -set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again -set g_balance_rocketlauncher_remote_damage 105 -set g_balance_rocketlauncher_remote_edgedamage 40 -set g_balance_rocketlauncher_remote_radius 150 -set g_balance_rocketlauncher_remote_force 600 -set g_balance_rocketlauncher_switchdelay_drop 0.15 -set g_balance_rocketlauncher_switchdelay_raise 0.15 -set g_balance_rocketlauncher_reload_ammo 0 //default: 25 -set g_balance_rocketlauncher_reload_time 2 -// }}} -// {{{ porto -set g_balance_porto_primary_refire 1.5 -set g_balance_porto_primary_animtime 0.3 -set g_balance_porto_primary_speed 2000 -set g_balance_porto_primary_lifetime 30 -set g_balance_porto_secondary 0 -set g_balance_porto_secondary_refire 1.5 -set g_balance_porto_secondary_animtime 0.3 -set g_balance_porto_secondary_speed 2000 -set g_balance_porto_secondary_lifetime 30 -set g_balance_porto_switchdelay_drop 0.15 -set g_balance_porto_switchdelay_raise 0.15 -set g_balance_portal_health 200 // these get recharged whenever the portal is used -set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used -// }}} -// {{{ hook -set g_balance_hook_primary_fuel 5 // hook monkeys set 0 -set g_balance_hook_primary_refire 0.2 // hook monkeys set 0 -set g_balance_hook_primary_animtime 0.3 // good shoot anim -set g_balance_hook_primary_hooked_time_max 0 // infinite -set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free -set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked -set g_balance_hook_secondary_damage 25 // not much -set g_balance_hook_secondary_edgedamage 5 // not much -set g_balance_hook_secondary_radius 500 // LOTS -set g_balance_hook_secondary_force -2000 // LOTS -set g_balance_hook_secondary_ammo 50 // a whole pack -set g_balance_hook_secondary_lifetime 30 // infinite -set g_balance_hook_secondary_speed 0 // not much throwing -set g_balance_hook_secondary_gravity 5 // fast falling -set g_balance_hook_secondary_refire 3 // don't drop too many bombs... -set g_balance_hook_secondary_animtime 0.3 // good shoot anim -set g_balance_hook_secondary_power 3 // effect behaves like a square function -set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds -set g_balance_hook_secondary_health 0 -set g_balance_hook_secondary_damageforcescale 0 -set g_balance_hook_switchdelay_drop 0.15 -set g_balance_hook_switchdelay_raise 0.15 -// }}} -// {{{ tuba -set g_balance_tuba_refire 0.05 -set g_balance_tuba_animtime 0.05 -set g_balance_tuba_attenuation 0.5 -set g_balance_tuba_volume 1 -set g_balance_tuba_fadetime 0.25 -set g_balance_tuba_damage 5 -set g_balance_tuba_edgedamage 0 -set g_balance_tuba_radius 200 -set g_balance_tuba_force 40 -set g_balance_tuba_pitchstep 6 -set g_balance_tuba_switchdelay_drop 0.15 -set g_balance_tuba_switchdelay_raise 0.15 -// }}} -// {{{ fireball -set g_balance_fireball_primary_animtime 0.15 -set g_balance_fireball_primary_bfgdamage 100 -set g_balance_fireball_primary_bfgforce 0 -set g_balance_fireball_primary_bfgradius 1000 -set g_balance_fireball_primary_damage 200 -set g_balance_fireball_primary_damageforcescale 4 -set g_balance_fireball_primary_edgedamage 0 -set g_balance_fireball_primary_force 700 -set g_balance_fireball_primary_health 50 -set g_balance_fireball_primary_laserburntime 0.5 -set g_balance_fireball_primary_laserdamage 80 -set g_balance_fireball_primary_laseredgedamage 20 -set g_balance_fireball_primary_laserradius 256 -set g_balance_fireball_primary_lifetime 15 -set g_balance_fireball_primary_radius 200 -set g_balance_fireball_primary_refire 5 -set g_balance_fireball_primary_refire2 0 -set g_balance_fireball_primary_speed 650 -set g_balance_fireball_primary_spread 0 -set g_balance_fireball_secondary_animtime 0.3 -set g_balance_fireball_secondary_damage 40 -set g_balance_fireball_secondary_damageforcescale 4 -set g_balance_fireball_secondary_damagetime 5 -set g_balance_fireball_secondary_force 100 -set g_balance_fireball_secondary_laserburntime 0.5 -set g_balance_fireball_secondary_laserdamage 50 -set g_balance_fireball_secondary_laseredgedamage 20 -set g_balance_fireball_secondary_laserradius 110 -set g_balance_fireball_secondary_lifetime 7 -set g_balance_fireball_secondary_refire 2 -set g_balance_fireball_secondary_speed 900 -set g_balance_fireball_secondary_speed_up 100 -set g_balance_fireball_secondary_speed_z 0 -set g_balance_fireball_secondary_spread 0 -set g_balance_fireball_switchdelay_drop 0.15 -set g_balance_fireball_switchdelay_raise 0.15 -// }}} diff --git a/oldbalanceFruitieX.cfg b/oldbalanceFruitieX.cfg deleted file mode 100644 index d5b6a9a2d..000000000 --- a/oldbalanceFruitieX.cfg +++ /dev/null @@ -1,780 +0,0 @@ -g_mod_balance FruitieX - -// {{{ starting gear -set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_balance_health_start 125 -set g_balance_armor_start 0 -set g_start_ammo_shells 20 -set g_start_ammo_nails 0 -set g_start_ammo_rockets 0 -set g_start_ammo_cells 0 -set g_start_ammo_fuel 0 -set g_warmup_start_health 200 "starting values when being in warmup-stage" -set g_warmup_start_armor 100 "starting values when being in warmup-stage" -set g_warmup_start_ammo_shells 50 "starting values when being in warmup-stage" -set g_warmup_start_ammo_nails 150 "starting values when being in warmup-stage" -set g_warmup_start_ammo_rockets 50 "starting values when being in warmup-stage" -set g_warmup_start_ammo_cells 50 "starting values when being in warmup-stage" -set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage" -set g_lms_start_health 200 -set g_lms_start_armor 100 -set g_lms_start_ammo_shells 30 -set g_lms_start_ammo_nails 200 -set g_lms_start_ammo_rockets 150 -set g_lms_start_ammo_cells 150 -set g_lms_start_ammo_fuel 0 -set g_balance_nix_roundtime 25 -set g_balance_nix_incrtime 1.6 -set g_balance_nix_ammo_shells 15 -set g_balance_nix_ammo_nails 45 -set g_balance_nix_ammo_rockets 15 -set g_balance_nix_ammo_cells 15 -set g_balance_nix_ammo_fuel 0 -set g_balance_nix_ammoincr_shells 2 -set g_balance_nix_ammoincr_nails 6 -set g_balance_nix_ammoincr_rockets 2 -set g_balance_nix_ammoincr_cells 2 -set g_balance_nix_ammoincr_fuel 2 -// }}} - -// {{{ pickup items -set g_pickup_ammo_anyway 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 30 -set g_pickup_cells_weapon 20 -set g_pickup_cells_max 150 -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 -set g_pickup_armorsmall_max 150 -set g_pickup_armorsmall_anyway 1 -set g_pickup_armormedium 25 -set g_pickup_armormedium_max 50 -set g_pickup_armormedium_anyway 0 -set g_pickup_armorbig 50 -set g_pickup_armorbig_max 75; // LOG: to allow a little more armor from medium armor -set g_pickup_armorbig_anyway 0 -set g_pickup_armorlarge 100 -set g_pickup_armorlarge_max 150 -set g_pickup_armorlarge_anyway 1 -set g_pickup_healthsmall 5 -set g_pickup_healthsmall_max 250 -set g_pickup_healthsmall_anyway 1 -set g_pickup_healthmedium 25 -set g_pickup_healthmedium_max 100 -set g_pickup_healthmedium_anyway 0 -set g_pickup_healthlarge 50 -set g_pickup_healthlarge_max 150 -set g_pickup_healthlarge_anyway 0 -set g_pickup_healthmega 100 -set g_pickup_healthmega_max 250 -set g_pickup_healthmega_anyway 1 -set g_pickup_respawntime_short 15 -set g_pickup_respawntime_medium 20 -set g_pickup_respawntime_long 30 -set g_pickup_respawntime_powerup 120 -set g_pickup_respawntime_weapon 10 -set g_pickup_respawntime_superweapon 120 -set g_pickup_respawntime_ammo 25 -set g_pickup_respawntimejitter_short 0 -set g_pickup_respawntimejitter_medium 0 -set g_pickup_respawntimejitter_long 0 -set g_pickup_respawntimejitter_powerup 10 -set g_pickup_respawntimejitter_weapon 0 -set g_pickup_respawntimejitter_superweapon 10 -set g_pickup_respawntimejitter_ammo 0 -// }}} - -// {{{ regen/rot -set g_balance_health_regen 0.05 -set g_balance_health_regenlinear 0 -set g_balance_pause_health_regen 5 -set g_balance_pause_health_regen_spawn 0 -set g_balance_health_rot 0 -set g_balance_health_rotlinear 1 -set g_balance_pause_health_rot 1 -set g_balance_pause_health_rot_spawn 0 -set g_balance_health_regenstable 100 -set g_balance_health_rotstable 100 -set g_balance_health_limit 999 -set g_balance_armor_regen 0 -set g_balance_armor_regenlinear 0 -set g_balance_armor_rot 0 -set g_balance_armor_rotlinear 1 -set g_balance_pause_armor_rot 1 -set g_balance_pause_armor_rot_spawn 0 -set g_balance_armor_regenstable 100 -set g_balance_armor_rotstable 100 -set g_balance_armor_limit 999 -set g_balance_armor_blockpercent 0.7 -set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)" -set g_balance_fuel_regenlinear 0 -set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter -set g_balance_fuel_rot 0.05 -set g_balance_fuel_rotlinear 0 -set g_balance_pause_fuel_rot 5 -set g_balance_pause_fuel_rot_spawn 10 -set g_balance_fuel_regenstable 50 -set g_balance_fuel_rotstable 100 -set g_balance_fuel_limit 999 -// }}} - -// {{{ misc -set g_balance_selfdamagepercent 0.65 -set g_weaponspeedfactor 1 "weapon projectile speed multiplier" -set g_weaponratefactor 1 "weapon fire rate multiplier" -set g_weapondamagefactor 1 "weapon damage multiplier" -set g_weaponforcefactor 1 "weapon force multiplier" -set g_weaponspreadfactor 1 "weapon spread multiplier" -set g_balance_firetransfer_time 0.9 -set g_balance_firetransfer_damage 0.8 -set g_throughfloor_damage 0.7 -set g_throughfloor_force 0.8 -set g_projectiles_damage 2 -// possible values: -// -2: absolutely no damage to projectiles (no exceptions) -// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines) -// 0: only damage from contents (lava/slime) or exceptions -// 1: only self damage or damage from contents or exceptions -// 2: allow all damage to projectiles normally -set g_projectiles_keep_owner 0 -set g_projectiles_newton_style 2 -// possible values: -// 0: absolute velocity projectiles (like Quake) -// 1: relative velocity projectiles, "Newtonian" (like Tribes 2) -// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard) -set g_projectiles_newton_style_2_minfactor 0.7 -set g_projectiles_newton_style_2_maxfactor 5 -set g_projectiles_spread_style 7 -// possible values: -// 0: forward + solid sphere (like Quake) - varies velocity -// 1: forward + flattened solid sphere -// 2: forward + solid circle -// 3: forward + normal distribution 3D - varies velocity -// 4: forward + normal distribution on a plane -// 5: forward + circle with 1-r falloff -// 6: forward + circle with 1-r^2 falloff -// 7: forward + circle with (1-r)(2-r) falloff -set g_balance_falldamage_deadminspeed 150 -set g_balance_falldamage_minspeed 800 -set g_balance_falldamage_factor 0.20 -set g_balance_falldamage_maxdamage 15 -set g_balance_damagepush_speedfactor 2.5 -set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage -set g_balance_contents_drowndelay 10 // time under water before a player begins drowning -set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning -set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava -set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime -set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime -set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap" -// }}} - -// {{{ powerups -set g_balance_powerup_invincible_takedamage 0.6 -set g_balance_powerup_invincible_time 30 -set g_balance_powerup_strength_damage 3 -set g_balance_powerup_strength_force 4 -set g_balance_powerup_strength_time 30 -set g_balance_powerup_strength_selfdamage 1.5 -set g_balance_powerup_strength_selfforce 1.5 -set g_balance_superweapons_time 30 -// }}} - -// {{{ jetpack/hook -set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack" -set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction" -set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)" -set g_jetpack_maxspeed_side 1500 "max speed of the jetpack in xy direction" -set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction" -set g_jetpack_fuel 8 "fuel per second for jetpack" -set g_jetpack_attenuation 2 "jetpack sound attenuation" - -set g_grappling_hook_tarzan 2 // 2: can also pull players -set g_balance_grapplehook_speed_fly 1800 -set g_balance_grapplehook_speed_pull 2000 -set g_balance_grapplehook_force_rubber 2000 -set g_balance_grapplehook_force_rubber_overstretch 1000 -set g_balance_grapplehook_length_min 50 -set g_balance_grapplehook_stretch 50 -set g_balance_grapplehook_airfriction 0.2 -set g_balance_grapplehook_health 130 -set g_balance_grapplehook_damagedbycontents 0 -set g_balance_grapplehook_refire 0.2 -// }}} - -// {{{ weapon properties -// {{{ laser -set g_balance_laser_melee_animtime 0.3 -set g_balance_laser_melee_damage 80 -set g_balance_laser_melee_delay 0.25 -set g_balance_laser_melee_force 200 -set g_balance_laser_melee_multihit 1 -set g_balance_laser_melee_no_doubleslap 1 -set g_balance_laser_melee_nonplayerdamage 40 -set g_balance_laser_melee_range 120 -set g_balance_laser_melee_refire 1.25 -set g_balance_laser_melee_swing_side 120 -set g_balance_laser_melee_swing_up 30 -set g_balance_laser_melee_time 0.15 -set g_balance_laser_melee_traces 10 - -set g_balance_laser_primary 1 // 0 = shockwave attack, 1 = projectile primary -set g_balance_laser_primary_damage 20 // dps 33, hope that's not too high -set g_balance_laser_primary_edgedamage 20 -set g_balance_laser_primary_force 150 // this looks insanely low, but actually isn't with zscale and velocitybias -set g_balance_laser_primary_radius 60 -set g_balance_laser_primary_speed 5000 -set g_balance_laser_primary_spread 0 -set g_balance_laser_primary_refire 0.6 -set g_balance_laser_primary_animtime 0.4 -set g_balance_laser_primary_lifetime 5 -set g_balance_laser_primary_shotangle 0 -set g_balance_laser_primary_delay 0 -set g_balance_laser_primary_force_zscale 2 // 300 upforce -set g_balance_laser_primary_force_velocitybias 0.3 -set g_balance_laser_primary_force_other_scale 2.5 // force 375 when pushing others around - -set g_balance_laser_secondary 0 // 0 = switch away to last used weapon, 1 = projectile secondary, 2 = melee secondary -set g_balance_laser_secondary_damage 200 // dps -set g_balance_laser_secondary_edgedamage 0 -set g_balance_laser_secondary_force 1300 -set g_balance_laser_secondary_radius 60 -set g_balance_laser_secondary_speed 0 -set g_balance_laser_secondary_spread 0 -set g_balance_laser_secondary_refire 0.066 -set g_balance_laser_secondary_animtime 0.066 -set g_balance_laser_secondary_lifetime 0 -set g_balance_laser_secondary_shotangle 0 -set g_balance_laser_secondary_delay 0 -set g_balance_laser_secondary_force_zscale 1.25 -set g_balance_laser_secondary_force_velocitybias 0 -set g_balance_laser_secondary_force_other_scale 0 - -set g_balance_laser_shockwave_damage 20 -set g_balance_laser_shockwave_distance 2000 -set g_balance_laser_shockwave_edgedamage 0 -set g_balance_laser_shockwave_force 200 -set g_balance_laser_shockwave_force_forwardbias 50 -set g_balance_laser_shockwave_force_zscale 1.5 -set g_balance_laser_shockwave_jump_damage 20 -set g_balance_laser_shockwave_jump_edgedamage 0 -set g_balance_laser_shockwave_jump_force 300 -set g_balance_laser_shockwave_jump_force_velocitybias 0 -set g_balance_laser_shockwave_jump_force_zscale 1.25 -set g_balance_laser_shockwave_jump_multiplier_accuracy 0.5 -set g_balance_laser_shockwave_jump_multiplier_distance 0.5 -set g_balance_laser_shockwave_jump_multiplier_min 0 -set g_balance_laser_shockwave_jump_radius 150 -set g_balance_laser_shockwave_multiplier_accuracy 0.5 -set g_balance_laser_shockwave_multiplier_distance 0.5 -set g_balance_laser_shockwave_multiplier_min 0 -set g_balance_laser_shockwave_splash_damage 15 -set g_balance_laser_shockwave_splash_edgedamage 0 -set g_balance_laser_shockwave_splash_force 100 -set g_balance_laser_shockwave_splash_force_forwardbias 50 -set g_balance_laser_shockwave_splash_multiplier_accuracy 0.5 -set g_balance_laser_shockwave_splash_multiplier_distance 0.5 -set g_balance_laser_shockwave_splash_multiplier_min 0 -set g_balance_laser_shockwave_splash_radius 70 -set g_balance_laser_shockwave_spread_max 100 -set g_balance_laser_shockwave_spread_min 20 - -set g_balance_laser_switchdelay_drop 0.15 -set g_balance_laser_switchdelay_raise 0.15 -set g_balance_laser_reload_ammo 0 //default: 6 -set g_balance_laser_reload_time 2 -// }}} -// {{{ shotgun -set g_balance_shotgun_primary_bullets 18 -set g_balance_shotgun_primary_damage 3.5 // LOG: changed from 4 to 3.5, total damage 63 -set g_balance_shotgun_primary_force 20 -set g_balance_shotgun_primary_spread 0.16 // LOG: changed from 0.18 -> 0.16 to compensate a little for lower damage -set g_balance_shotgun_primary_refire 1 -set g_balance_shotgun_primary_animtime 0.3 -set g_balance_shotgun_primary_ammo 1 -set g_balance_shotgun_primary_solidpenetration 3.8 -set g_balance_shotgun_secondary 1 -set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow -set g_balance_shotgun_secondary_melee_range 120 -set g_balance_shotgun_secondary_melee_swing_side 120 -set g_balance_shotgun_secondary_melee_swing_up 30 -set g_balance_shotgun_secondary_melee_time 0.15 -set g_balance_shotgun_secondary_melee_traces 10 -set g_balance_shotgun_secondary_melee_no_doubleslap 1 -set g_balance_shotgun_secondary_melee_nonplayerdamage 0 -set g_balance_shotgun_secondary_melee_multihit 1 -set g_balance_shotgun_secondary_damage 110 -set g_balance_shotgun_secondary_force 150 -set g_balance_shotgun_secondary_refire 1.1 -set g_balance_shotgun_secondary_animtime 1 -set g_balance_shotgun_switchdelay_drop 0.15 -set g_balance_shotgun_switchdelay_raise 0.15 -set g_balance_shotgun_reload_ammo 0 //default: 5 -set g_balance_shotgun_reload_time 2 -// }}} -// {{{ uzi -set g_balance_uzi_mode 1 // Activates varible spread for sustained & burst mode secondary -set g_balance_uzi_spread_min 0.02 -set g_balance_uzi_spread_max 0.3 // LOG: 0.6 -> 0.3 -set g_balance_uzi_spread_add 0.008 - -set g_balance_uzi_burst 3 // # of bullets in a burst (if set to 2 or more) -set g_balance_uzi_burst_animtime 0.45 -set g_balance_uzi_burst_refire 0.05 // refire between burst bullets -set g_balance_uzi_burst_refire2 0.45 // refire after burst -set g_balance_uzi_burst_spread 0.07 -set g_balance_uzi_burst_damage 25 -set g_balance_uzi_burst_force 50 -set g_balance_uzi_burst_ammo 3 - -set g_balance_uzi_first 1 -set g_balance_uzi_first_damage 15 / f/ LOG: 22 -> 15 -set g_balance_uzi_first_force 50 -set g_balance_uzi_first_spread 0.03 -set g_balance_uzi_first_refire 0.2 -set g_balance_uzi_first_ammo 2 - -set g_balance_uzi_sustained_damage 12 // 120 dps -set g_balance_uzi_sustained_force 12 -set g_balance_uzi_sustained_spread 0.06 -set g_balance_uzi_sustained_refire 0.1 -set g_balance_uzi_sustained_ammo 1 - -set g_balance_uzi_solidpenetration 13.1 - -set g_balance_uzi_switchdelay_drop 0.15 -set g_balance_uzi_switchdelay_raise 0.15 - -set g_balance_uzi_reload_ammo 0 //default: 30 -set g_balance_uzi_reload_time 2 -// }}} -// {{{ mortar -set g_balance_grenadelauncher_primary_type 0 -set g_balance_grenadelauncher_primary_damage 44 -set g_balance_grenadelauncher_primary_edgedamage 32 -set g_balance_grenadelauncher_primary_force 300 -set g_balance_grenadelauncher_primary_radius 115 -set g_balance_grenadelauncher_primary_speed 1500 -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_lifetime 5 -set g_balance_grenadelauncher_primary_lifetime2 0.65 -set g_balance_grenadelauncher_primary_refire 0.8 -set g_balance_grenadelauncher_primary_animtime 0.3 -set g_balance_grenadelauncher_primary_ammo 2 -set g_balance_grenadelauncher_primary_health 80 -set g_balance_grenadelauncher_primary_damageforcescale 0 -set g_balance_grenadelauncher_primary_remote_minbouncecnt 0 - -set g_balance_grenadelauncher_secondary_type 1 -set g_balance_grenadelauncher_secondary_damage 62 -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 1000 -set g_balance_grenadelauncher_secondary_speed_up 250 -set g_balance_grenadelauncher_secondary_speed_z 0 -set g_balance_grenadelauncher_secondary_spread 0 -set g_balance_grenadelauncher_secondary_lifetime 3 -set g_balance_grenadelauncher_secondary_lifetime_bounce 0 -set g_balance_grenadelauncher_secondary_lifetime_stick 0.65 -set g_balance_grenadelauncher_secondary_refire 0.8 -set g_balance_grenadelauncher_secondary_animtime 0.3 -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_remote_detonateprimary 0 - -set g_balance_grenadelauncher_bouncefactor 0.5 -set g_balance_grenadelauncher_bouncestop 0.12 - -set g_balance_grenadelauncher_switchdelay_drop 0.15 -set g_balance_grenadelauncher_switchdelay_raise 0.15 - -set g_balance_grenadelauncher_reload_ammo 0 //default: 12 -set g_balance_grenadelauncher_reload_time 2 -// }}} -// {{{ electro -set g_balance_electro_lightning 1 -set g_balance_electro_primary_damage 100 -set g_balance_electro_primary_edgedamage 0 -set g_balance_electro_primary_force 425 -set g_balance_electro_primary_force_up 125 -set g_balance_electro_primary_radius 850 -set g_balance_electro_primary_comboradius 150 -set g_balance_electro_primary_speed 0 -set g_balance_electro_primary_spread 0 -set g_balance_electro_primary_lifetime 0 -set g_balance_electro_primary_refire 0.4 -set g_balance_electro_primary_animtime 0.2 -set g_balance_electro_primary_ammo 5 -set g_balance_electro_primary_range 800 -set g_balance_electro_primary_falloff_mindist 0 -set g_balance_electro_primary_falloff_maxdist 0 -set g_balance_electro_primary_falloff_halflifedist 0 -set g_balance_electro_secondary_damage 25 -set g_balance_electro_secondary_edgedamage 0 -set g_balance_electro_secondary_force 100 -set g_balance_electro_secondary_radius 100 -set g_balance_electro_secondary_speed 700 -set g_balance_electro_secondary_speed_up 200 -set g_balance_electro_secondary_speed_z 0 -set g_balance_electro_secondary_spread 0.08 -set g_balance_electro_secondary_lifetime 3.5 -set g_balance_electro_secondary_refire 0.2 -set g_balance_electro_secondary_refire2 2 -set g_balance_electro_secondary_animtime 0.2 -set g_balance_electro_secondary_ammo 2 -set g_balance_electro_secondary_health 10 -set g_balance_electro_secondary_damageforcescale 4 -set g_balance_electro_secondary_damagedbycontents 0 -set g_balance_electro_secondary_count 3 -set g_balance_electro_secondary_bouncefactor 0.5 -set g_balance_electro_secondary_bouncestop 0.075 -set g_balance_electro_combo_damage 50 -set g_balance_electro_combo_edgedamage 0 -set g_balance_electro_combo_force 80 -set g_balance_electro_combo_radius 250 -set g_balance_electro_combo_comboradius 0 -set g_balance_electro_combo_speed 400 -set g_balance_electro_combo_safeammocheck 1 -set g_balance_electro_switchdelay_drop 0.15 -set g_balance_electro_switchdelay_raise 0.15 -set g_balance_electro_reload_ammo 0 //default: 20 -set g_balance_electro_reload_time 2 -// }}} -// {{{ lightning -set g_balance_lightning_primary_ammo 5 -set g_balance_lightning_primary_animtime 0.2 -set g_balance_lightning_primary_damage 100 -set g_balance_lightning_primary_edgedamage 0 -set g_balance_lightning_primary_falloff_mindist 0 -set g_balance_lightning_primary_falloff_maxdist 0 -set g_balance_lightning_primary_falloff_halflifedist 0 -set g_balance_lightning_primary_force 425 -set g_balance_lightning_primary_lifetime 0 -set g_balance_lightning_primary_radius 850 -set g_balance_lightning_primary_range 800 -set g_balance_lightning_primary_refire 0.4 -set g_balance_lightning_primary_speed 0 -set g_balance_lightning_primary_spread 0 -set g_balance_lightning_secondary_ammo 5 -set g_balance_lightning_secondary_animtime 0.5 -set g_balance_lightning_secondary_damage 100 -set g_balance_lightning_secondary_damageforcescale 4 -set g_balance_lightning_secondary_edgedamage 80 -set g_balance_lightning_secondary_flyingdamage 1 -set g_balance_lightning_secondary_flyingforce -80 -set g_balance_lightning_secondary_flyingradius 200 -set g_balance_lightning_secondary_force -200 -set g_balance_lightning_secondary_health 1 -set g_balance_lightning_secondary_lifetime 30 -set g_balance_lightning_secondary_radius 300 -set g_balance_lightning_secondary_refire 5 -set g_balance_lightning_secondary_speed 600 -// }}} -// {{{ crylink -set g_balance_crylink_primary_damage 7 // LOG: 10 -> 7 -set g_balance_crylink_primary_edgedamage 4 // LOG: 6 -> 4 -set g_balance_crylink_primary_force 35 -set g_balance_crylink_primary_radius 80 -set g_balance_crylink_primary_speed 1500 -set g_balance_crylink_primary_spread 0.05 -set g_balance_crylink_primary_shots 7 -set g_balance_crylink_primary_bounces 2 -set g_balance_crylink_primary_refire 0.8 -set g_balance_crylink_primary_animtime 0.3 -set g_balance_crylink_primary_ammo 2 -set g_balance_crylink_primary_bouncedamagefactor 0.2 -set g_balance_crylink_primary_joindelay 0 -set g_balance_crylink_primary_joinspread 0.2 -set g_balance_crylink_primary_joinexplode 0 -set g_balance_crylink_primary_joinexplode_damage 0 -set g_balance_crylink_primary_joinexplode_edgedamage 0 -set g_balance_crylink_primary_joinexplode_radius 0 -set g_balance_crylink_primary_joinexplode_force 0 -set g_balance_crylink_primary_linkexplode 1 - -set g_balance_crylink_primary_middle_lifetime 5 // range: 10000 full, fades to 20000 -set g_balance_crylink_primary_middle_fadetime 5 -set g_balance_crylink_primary_other_lifetime 2 // range: 800 full, fades to 1300 -set g_balance_crylink_primary_other_fadetime 0.25 - -set g_balance_crylink_secondary 1 -set g_balance_crylink_secondary_damage 5 // LOG: 8 -> 5 -set g_balance_crylink_secondary_edgedamage 3 -set g_balance_crylink_secondary_force 16 // LOG: 20 -> 16 -set g_balance_crylink_secondary_radius 15 // LOG: 20 -> 15 -set g_balance_crylink_secondary_speed 1250 // LOG: 1500 -> 1250 -set g_balance_crylink_secondary_spread 0.1 -set g_balance_crylink_secondary_spreadtype 0 -set g_balance_crylink_secondary_shots 6 -set g_balance_crylink_secondary_bounces 2 -set g_balance_crylink_secondary_refire 0.9 // LOG: 0.8 -> 0.9 -set g_balance_crylink_secondary_animtime 0.3 -set g_balance_crylink_secondary_ammo 3 // LOG: 2 -> 3 -set g_balance_crylink_secondary_bouncedamagefactor 0.4 // LOG: 0.2 -> 0.4 -set g_balance_crylink_secondary_joindelay 0 -set g_balance_crylink_secondary_joinspread 0.2 -set g_balance_crylink_secondary_joinexplode 0 -set g_balance_crylink_secondary_joinexplode_damage 0 -set g_balance_crylink_secondary_joinexplode_edgedamage 0 -set g_balance_crylink_secondary_joinexplode_radius 0 -set g_balance_crylink_secondary_joinexplode_force 0 -set g_balance_crylink_secondary_linkexplode 0 - -set g_balance_crylink_secondary_middle_lifetime 5 // range: 10000 full, fades to 10000 -set g_balance_crylink_secondary_middle_fadetime 5 -set g_balance_crylink_secondary_line_lifetime 2 // range: 4000 full, fades to 8000 -set g_balance_crylink_secondary_line_fadetime 0.25 - -set g_balance_crylink_switchdelay_drop 0.15 -set g_balance_crylink_switchdelay_raise 0.15 - -set g_balance_crylink_reload_ammo 0 //default: 10 -set g_balance_crylink_reload_time 2 -// }}} -// {{{ nex -set g_balance_nex_primary_damage 90 -set g_balance_nex_primary_force 500 -set g_balance_nex_primary_refire 1 -set g_balance_nex_primary_animtime 0.3 -set g_balance_nex_primary_ammo 5 -set g_balance_nex_primary_damagefalloff_mindist 0 -set g_balance_nex_primary_damagefalloff_maxdist 0 -set g_balance_nex_primary_damagefalloff_halflife 0 -set g_balance_nex_primary_damagefalloff_forcehalflife 0 - -set g_balance_nex_secondary 0 // LOG: disable secondary -set g_balance_nex_secondary_charge 0 // LOG: disable secondary charge -set g_balance_nex_secondary_charge_rate 0.4 -set g_balance_nex_secondary_chargepool 1 -set g_balance_nex_secondary_chargepool_regen 0.25 -set g_balance_nex_secondary_chargepool_pause_regen 2 -set g_balance_nex_secondary_chargepool_pause_health_regen 0.5 -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 0.4 // full charge pool is 1, so it depletes in 2.5 secs -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_charge 1 -set g_balance_nex_charge_mindmg 20 -set g_balance_nex_charge_start 0.5 -set g_balance_nex_charge_rate 0.5 -set g_balance_nex_charge_animlimit 0.5 -set g_balance_nex_charge_limit 1 // LOG: 0.5 -> 1 - allow to fully charge automaticaly -set g_balance_nex_charge_rot_rate 0 // LOG: 0.1 -> 0 - disable rot -set g_balance_nex_charge_rot_pause 0.5 // Dont rot down until this long after release of charge button -set g_balance_nex_charge_shot_multiplier 0 -set g_balance_nex_charge_velocity_rate 0 -set g_balance_nex_charge_minspeed 600 -set g_balance_nex_charge_maxspeed 1000 - -set g_balance_nex_switchdelay_drop 0.15 -set g_balance_nex_switchdelay_raise 0.15 - -set g_balance_nex_reload_ammo 0 //default: 25 -set g_balance_nex_reload_time 2 -// }}} -// {{{ minstanex -set g_balance_minstanex_refire 1 -set g_balance_minstanex_animtime 0.50 -set g_balance_minstanex_ammo 10 -set g_balance_minstanex_laser_ammo 0 -set g_balance_minstanex_laser_animtime 0.3 -set g_balance_minstanex_laser_refire 0.6 -set g_balance_minstanex_switchdelay_drop 0.15 -set g_balance_minstanex_switchdelay_raise 0.15 -set g_balance_minstanex_reload_ammo 0 //default: 50 -set g_balance_minstanex_reload_time 2 -// }}} -// {{{ hagar -set g_balance_hagar_primary_damage 14 -set g_balance_hagar_primary_edgedamage 6 -set g_balance_hagar_primary_force 70 -set g_balance_hagar_primary_health 0 -set g_balance_hagar_primary_damageforcescale 0 -set g_balance_hagar_primary_radius 110 -set g_balance_hagar_primary_spread 0.1 -set g_balance_hagar_primary_speed 1800 -set g_balance_hagar_primary_lifetime 5 -set g_balance_hagar_primary_refire 0.12 -set g_balance_hagar_primary_ammo 1 -set g_balance_hagar_secondary 1 -set g_balance_hagar_secondary_load 0 -set g_balance_hagar_secondary_load_speed 0.6 -set g_balance_hagar_secondary_load_spread 0.075 -set g_balance_hagar_secondary_load_spread_bias 0.5 -set g_balance_hagar_secondary_load_max 4 -set g_balance_hagar_secondary_load_hold 0 -set g_balance_hagar_secondary_load_releasedeath 1 -set g_balance_hagar_secondary_load_abort 1 -set g_balance_hagar_secondary_load_linkexplode 0 -set g_balance_hagar_secondary_load_animtime 0.2 -set g_balance_hagar_secondary_damage 14 // default for _load: 32 -set g_balance_hagar_secondary_edgedamage 6 // default for _load: 10 -set g_balance_hagar_secondary_force 70 // default for _load: 160 -set g_balance_hagar_secondary_health 0 -set g_balance_hagar_secondary_damageforcescale 0 -set g_balance_hagar_secondary_radius 125 -set g_balance_hagar_secondary_spread 0.15 // default for _load: 0.08 -set g_balance_hagar_secondary_speed 1800 -set g_balance_hagar_secondary_lifetime_min 5 -set g_balance_hagar_secondary_lifetime_rand 0 -set g_balance_hagar_secondary_refire 0.12 // default for _load: 0.8 -set g_balance_hagar_secondary_ammo 1 -set g_balance_hagar_switchdelay_drop 0.15 -set g_balance_hagar_switchdelay_raise 0.15 -set g_balance_hagar_reload_ammo 0 //default: 25 -set g_balance_hagar_reload_time 2 -// }}} -// {{{ rocketlauncher -set g_balance_rocketlauncher_damage 82 -set g_balance_rocketlauncher_edgedamage 32 -set g_balance_rocketlauncher_force 350 -set g_balance_rocketlauncher_radius 130 -set g_balance_rocketlauncher_speed 1400 -set g_balance_rocketlauncher_speedaccel 1400 -set g_balance_rocketlauncher_speedstart 800 -set g_balance_rocketlauncher_lifetime 5 -set g_balance_rocketlauncher_refire 1 -set g_balance_rocketlauncher_animtime 0.3 -set g_balance_rocketlauncher_ammo 3 -set g_balance_rocketlauncher_health 0 -set g_balance_rocketlauncher_damageforcescale 0 -set g_balance_rocketlauncher_detonatedelay 0.05 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time -set g_balance_rocketlauncher_guiderate 42 // max degrees per second -set g_balance_rocketlauncher_guideratedelay 0.01 // immediate -set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic) -set g_balance_rocketlauncher_guidedelay 0.15 // delay before guiding kicks in -set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again -set g_balance_rocketlauncher_remote_damage 60 -set g_balance_rocketlauncher_remote_edgedamage 20 -set g_balance_rocketlauncher_remote_radius 120 -set g_balance_rocketlauncher_remote_force 350 -set g_balance_rocketlauncher_switchdelay_drop 0.15 -set g_balance_rocketlauncher_switchdelay_raise 0.15 -set g_balance_rocketlauncher_reload_ammo 0 //default: 25 -set g_balance_rocketlauncher_reload_time 2 -// }}} -// {{{ porto -set g_balance_porto_primary_refire 1.5 -set g_balance_porto_primary_animtime 0.2 -set g_balance_porto_primary_speed 2000 -set g_balance_porto_primary_lifetime 5 -set g_balance_porto_secondary 0 -set g_balance_porto_secondary_refire 1.5 -set g_balance_porto_secondary_animtime 0.2 -set g_balance_porto_secondary_speed 2000 -set g_balance_porto_secondary_lifetime 5 -set g_balance_porto_switchdelay_drop 0.15 -set g_balance_porto_switchdelay_raise 0.15 -set g_balance_portal_health 200 // these get recharged whenever the portal is used -set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used -// }}} -// {{{ hook -set g_balance_hook_primary_fuel 5 // hook monkeys set 0 -set g_balance_hook_primary_refire 0.2 // hook monkeys set 0 -set g_balance_hook_primary_animtime 0.2 // good shoot anim -set g_balance_hook_primary_hooked_time_max 0 // infinite -set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free -set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked -set g_balance_hook_secondary_damage 25 // not much -set g_balance_hook_secondary_edgedamage 5 // not much -set g_balance_hook_secondary_radius 500 // LOTS -set g_balance_hook_secondary_force -2000 // LOTS -set g_balance_hook_secondary_ammo 50 // a whole pack -set g_balance_hook_secondary_lifetime 5 // infinite -set g_balance_hook_secondary_speed 0 // not much throwing -set g_balance_hook_secondary_gravity 5 // fast falling -set g_balance_hook_secondary_refire 3 // don't drop too many bombs... -set g_balance_hook_secondary_animtime 0.2 // good shoot anim -set g_balance_hook_secondary_power 3 // effect behaves like a square function -set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds -set g_balance_hook_secondary_health 0 -set g_balance_hook_secondary_damageforcescale 0 -set g_balance_hook_switchdelay_drop 0.15 -set g_balance_hook_switchdelay_raise 0.15 -// }}} -// {{{ tuba -set g_balance_tuba_refire 0.05 -set g_balance_tuba_animtime 0.05 -set g_balance_tuba_attenuation 0.5 -set g_balance_tuba_volume 1 -set g_balance_tuba_fadetime 0.25 -set g_balance_tuba_damage 5 -set g_balance_tuba_edgedamage 0 -set g_balance_tuba_radius 200 -set g_balance_tuba_force 40 -set g_balance_tuba_pitchstep 6 -set g_balance_tuba_switchdelay_drop 0.15 -set g_balance_tuba_switchdelay_raise 0.15 -// }}} -// {{{ fireball -set g_balance_fireball_primary_animtime 0.2 -set g_balance_fireball_primary_bfgdamage 100 -set g_balance_fireball_primary_bfgforce 0 -set g_balance_fireball_primary_bfgradius 1000 -set g_balance_fireball_primary_damage 200 -set g_balance_fireball_primary_damageforcescale 4 -set g_balance_fireball_primary_edgedamage 0 -set g_balance_fireball_primary_force 700 -set g_balance_fireball_primary_health 50 -set g_balance_fireball_primary_laserburntime 0.5 -set g_balance_fireball_primary_laserdamage 80 -set g_balance_fireball_primary_laseredgedamage 20 -set g_balance_fireball_primary_laserradius 256 -set g_balance_fireball_primary_lifetime 15 -set g_balance_fireball_primary_radius 200 -set g_balance_fireball_primary_refire 5 -set g_balance_fireball_primary_refire2 0 -set g_balance_fireball_primary_speed 650 -set g_balance_fireball_primary_spread 0 -set g_balance_fireball_secondary_animtime 0.2 -set g_balance_fireball_secondary_damage 40 -set g_balance_fireball_secondary_damageforcescale 4 -set g_balance_fireball_secondary_damagetime 5 -set g_balance_fireball_secondary_force 100 -set g_balance_fireball_secondary_laserburntime 0.5 -set g_balance_fireball_secondary_laserdamage 50 -set g_balance_fireball_secondary_laseredgedamage 20 -set g_balance_fireball_secondary_laserradius 110 -set g_balance_fireball_secondary_lifetime 7 -set g_balance_fireball_secondary_refire 2 -set g_balance_fireball_secondary_speed 900 -set g_balance_fireball_secondary_speed_up 100 -set g_balance_fireball_secondary_speed_z 0 -set g_balance_fireball_secondary_spread 0 -set g_balance_fireball_switchdelay_drop 0.15 -set g_balance_fireball_switchdelay_raise 0.15 -// }}} diff --git a/oldbalanceXDF.cfg b/oldbalanceXDF.cfg deleted file mode 100644 index cbc380bfa..000000000 --- a/oldbalanceXDF.cfg +++ /dev/null @@ -1,750 +0,0 @@ -g_mod_balance XDF - -// {{{ starting gear -set g_start_weapon_laser 0 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_shotgun 0 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_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" -set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" -set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" -set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" -set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" // UNTIL IT CAN BE REMOVED FROM CODE -set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" -set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" -set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" -set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" -set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" -set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" -set g_balance_health_start 100 -set g_balance_armor_start 0 -set g_start_ammo_shells 15 -set g_start_ammo_nails 0 -set g_start_ammo_rockets 0 -set g_start_ammo_cells 0 -set g_start_ammo_fuel 0 -set g_warmup_start_health 100 "starting values when being in warmup-stage" -set g_warmup_start_armor 100 "starting values when being in warmup-stage" -set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage" -set g_warmup_start_ammo_nails 160 "starting values when being in warmup-stage" -set g_warmup_start_ammo_rockets 80 "starting values when being in warmup-stage" -set g_warmup_start_ammo_cells 90 "starting values when being in warmup-stage" -set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage" -set g_lms_start_health 200 -set g_lms_start_armor 200 -set g_lms_start_ammo_shells 60 -set g_lms_start_ammo_nails 320 -set g_lms_start_ammo_rockets 160 -set g_lms_start_ammo_cells 180 -set g_lms_start_ammo_fuel 0 -set g_balance_nix_roundtime 25 -set g_balance_nix_incrtime 1.6 -set g_balance_nix_ammo_shells 60 -set g_balance_nix_ammo_nails 320 -set g_balance_nix_ammo_rockets 160 -set g_balance_nix_ammo_cells 180 -set g_balance_nix_ammo_fuel 0 -set g_balance_nix_ammoincr_shells 2 // eh this will need figured out later I assume -set g_balance_nix_ammoincr_nails 6 -set g_balance_nix_ammoincr_rockets 2 -set g_balance_nix_ammoincr_cells 2 -set g_balance_nix_ammoincr_fuel 2 -// }}} - -// {{{ pickup items -set g_pickup_ammo_anyway 1 -set g_pickup_weapons_anyway 1 -set g_pickup_shells 15 -set g_pickup_shells_weapon 15 -set g_pickup_shells_max 60 -set g_pickup_nails 80 -set g_pickup_nails_weapon 80 -set g_pickup_nails_max 320 -set g_pickup_rockets 40 -set g_pickup_rockets_weapon 40 -set g_pickup_rockets_max 160 -set g_pickup_cells 30 -set g_pickup_cells_weapon 30 -set g_pickup_cells_max 180 -set g_pickup_fuel 50 -set g_pickup_fuel_weapon 50 -set g_pickup_fuel_jetpack 100 -set g_pickup_fuel_max 100 -set g_pickup_armorsmall 5 -set g_pickup_armorsmall_max 200 -set g_pickup_armorsmall_anyway 1 -set g_pickup_armormedium 25 -set g_pickup_armormedium_max 200 -set g_pickup_armormedium_anyway 1 -set g_pickup_armorbig 50 -set g_pickup_armorbig_max 200 -set g_pickup_armorbig_anyway 1 -set g_pickup_armorlarge 100 -set g_pickup_armorlarge_max 200 -set g_pickup_armorlarge_anyway 1 -set g_pickup_healthsmall 5 -set g_pickup_healthsmall_max 200 -set g_pickup_healthsmall_anyway 1 -set g_pickup_healthmedium 25 -set g_pickup_healthmedium_max 200 -set g_pickup_healthmedium_anyway 1 -set g_pickup_healthlarge 50 -set g_pickup_healthlarge_max 200 -set g_pickup_healthlarge_anyway 1 -set g_pickup_healthmega 100 -set g_pickup_healthmega_max 200 -set g_pickup_healthmega_anyway 1 -set g_pickup_respawntime_short 0.1 -set g_pickup_respawntime_medium 0.1 -set g_pickup_respawntime_long 0.1 -set g_pickup_respawntime_powerup 0.1 -set g_pickup_respawntime_weapon 0.1 -set g_pickup_respawntime_superweapon 0.1 -set g_pickup_respawntime_ammo 0.1 -set g_pickup_respawntimejitter_short 0 -set g_pickup_respawntimejitter_medium 0 -set g_pickup_respawntimejitter_long 0 -set g_pickup_respawntimejitter_powerup 30 -set g_pickup_respawntimejitter_weapon 0 -set g_pickup_respawntimejitter_superweapon 10 -set g_pickup_respawntimejitter_ammo 0 -// }}} - -// {{{ regen/rot -set g_balance_health_regen 0.08 -set g_balance_health_regenlinear 0.5 -set g_balance_pause_health_regen 5 -set g_balance_pause_health_regen_spawn 0 -set g_balance_health_rot 0.04 -set g_balance_health_rotlinear 0.75 -set g_balance_pause_health_rot 1 -set g_balance_pause_health_rot_spawn 5 -set g_balance_health_regenstable 100 -set g_balance_health_rotstable 100 -set g_balance_health_limit 999 -set g_balance_armor_regen 0 -set g_balance_armor_regenlinear 0 -set g_balance_armor_rot 0.04 -set g_balance_armor_rotlinear 0.75 -set g_balance_pause_armor_rot 1 -set g_balance_pause_armor_rot_spawn 5 -set g_balance_armor_regenstable 100 -set g_balance_armor_rotstable 100 -set g_balance_armor_limit 999 -set g_balance_armor_blockpercent 0.6 -set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)" -set g_balance_fuel_regenlinear 0 -set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter -set g_balance_fuel_rot 0.05 -set g_balance_fuel_rotlinear 0 -set g_balance_pause_fuel_rot 5 -set g_balance_pause_fuel_rot_spawn 10 -set g_balance_fuel_regenstable 50 -set g_balance_fuel_rotstable 100 -set g_balance_fuel_limit 999 -// }}} - -// {{{ misc -set g_balance_selfdamagepercent 0 -set g_weaponspeedfactor 1 "weapon projectile speed multiplier" -set g_weaponratefactor 1 "weapon fire rate multiplier" -set g_weapondamagefactor 1 "weapon damage multiplier" -set g_weaponforcefactor 1 "weapon force multiplier" -set g_weaponspreadfactor 1 "weapon spread multiplier" -set g_balance_firetransfer_time 0.9 -set g_balance_firetransfer_damage 0.8 -set g_throughfloor_damage 0.4 -set g_throughfloor_force 0.7 -set g_projectiles_damage 2 -// possible values: -// -2: absolutely no damage to projectiles (no exceptions) -// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines) -// 0: only damage from contents (lava/slime) or exceptions -// 1: only self damage or damage from contents or exceptions -// 2: allow all damage to projectiles normally -set g_projectiles_keep_owner 0 -set g_projectiles_newton_style 2 -// possible values: -// 0: absolute velocity projectiles (like Quake) -// 1: relative velocity projectiles, "Newtonian" (like Tribes 2) -// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard) -set g_projectiles_newton_style_2_minfactor 0.8 -set g_projectiles_newton_style_2_maxfactor 1.5 -set g_projectiles_spread_style 7 -// possible values: -// 0: forward + solid sphere (like Quake) - varies velocity -// 1: forward + flattened solid sphere -// 2: forward + solid circle -// 3: forward + normal distribution 3D - varies velocity -// 4: forward + normal distribution on a plane -// 5: forward + circle with 1-r falloff -// 6: forward + circle with 1-r^2 falloff -// 7: forward + circle with (1-r)(2-r) falloff -set g_balance_falldamage_deadminspeed 250 -set g_balance_falldamage_minspeed 900 -set g_balance_falldamage_factor 0.20 -set g_balance_falldamage_maxdamage 40 -set g_balance_damagepush_speedfactor 2.5 -set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage -set g_balance_contents_drowndelay 10 // time under water before a player begins drowning -set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning -set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava -set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime -set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime -set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap" -// }}} - -// {{{ powerups -set g_balance_powerup_invincible_takedamage 0.25 // only 1/4th damage is taken -set g_balance_powerup_invincible_time 999 -set g_balance_powerup_strength_damage 3 -set g_balance_powerup_strength_force 3 -set g_balance_powerup_strength_time 999 -set g_balance_powerup_strength_selfdamage 1.5 -set g_balance_powerup_strength_selfforce 1.5 -set g_balance_superweapons_time 30 -// }}} - -// {{{ jetpack/hook -set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack" -set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction" -set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)" -set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction" -set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction" -set g_jetpack_fuel 8 "fuel per second for jetpack" -set g_jetpack_attenuation 2 "jetpack sound attenuation" - -set g_grappling_hook_tarzan 2 // 2: can also pull players -set g_balance_grapplehook_speed_fly 1800 -set g_balance_grapplehook_speed_pull 2000 -set g_balance_grapplehook_force_rubber 2000 -set g_balance_grapplehook_force_rubber_overstretch 1000 -set g_balance_grapplehook_length_min 50 -set g_balance_grapplehook_stretch 50 -set g_balance_grapplehook_airfriction 0.2 -set g_balance_grapplehook_health 130 -set g_balance_grapplehook_damagedbycontents 0 -set g_balance_grapplehook_refire 0.2 -// }}} - -// {{{ weapon properties -// {{{ laser -set g_balance_laser_melee_animtime 0.3 -set g_balance_laser_melee_damage 80 -set g_balance_laser_melee_delay 0.25 -set g_balance_laser_melee_force 200 -set g_balance_laser_melee_multihit 1 -set g_balance_laser_melee_no_doubleslap 1 -set g_balance_laser_melee_nonplayerdamage 40 -set g_balance_laser_melee_range 120 -set g_balance_laser_melee_refire 1.25 -set g_balance_laser_melee_swing_side 120 -set g_balance_laser_melee_swing_up 30 -set g_balance_laser_melee_time 0.15 -set g_balance_laser_melee_traces 10 - -set g_balance_laser_primary 1 // 0 = shockwave attack, 1 = projectile primary -set g_balance_laser_primary_damage 25 -set g_balance_laser_primary_edgedamage 12.5 -set g_balance_laser_primary_force 250 -set g_balance_laser_primary_radius 70 -set g_balance_laser_primary_speed 6000 -set g_balance_laser_primary_spread 0 -set g_balance_laser_primary_refire 0.7 -set g_balance_laser_primary_animtime 0.3 -set g_balance_laser_primary_lifetime 5 -set g_balance_laser_primary_shotangle 0 -set g_balance_laser_primary_delay 0 -set g_balance_laser_primary_force_zscale 1.5 -set g_balance_laser_primary_force_velocitybias 0 -set g_balance_laser_primary_force_other_scale 1 - -set g_balance_laser_secondary 0 // 0 = switch away to last used weapon, 1 = projectile secondary, 2 = melee secondary -set g_balance_laser_secondary_damage 25 -set g_balance_laser_secondary_edgedamage 12.5 -set g_balance_laser_secondary_force 400 -set g_balance_laser_secondary_radius 70 -set g_balance_laser_secondary_speed 12000 -set g_balance_laser_secondary_spread 0 -set g_balance_laser_secondary_refire 0.7 -set g_balance_laser_secondary_animtime 0.2 -set g_balance_laser_secondary_lifetime 5 -set g_balance_laser_secondary_shotangle -90 -set g_balance_laser_secondary_delay 0 -set g_balance_laser_secondary_force_zscale 1.25 -set g_balance_laser_secondary_force_velocitybias 0 -set g_balance_laser_secondary_force_other_scale 1 - -set g_balance_laser_shockwave_damage 20 -set g_balance_laser_shockwave_distance 2000 -set g_balance_laser_shockwave_edgedamage 0 -set g_balance_laser_shockwave_force 200 -set g_balance_laser_shockwave_force_forwardbias 50 -set g_balance_laser_shockwave_force_zscale 2 -set g_balance_laser_shockwave_jump_damage 20 -set g_balance_laser_shockwave_jump_edgedamage 0 -set g_balance_laser_shockwave_jump_force 300 -set g_balance_laser_shockwave_jump_force_velocitybias 0 -set g_balance_laser_shockwave_jump_force_zscale 1.25 -set g_balance_laser_shockwave_jump_multiplier_accuracy 0.5 -set g_balance_laser_shockwave_jump_multiplier_distance 0.5 -set g_balance_laser_shockwave_jump_multiplier_min 0 -set g_balance_laser_shockwave_jump_radius 150 -set g_balance_laser_shockwave_multiplier_accuracy 0.5 -set g_balance_laser_shockwave_multiplier_distance 0.5 -set g_balance_laser_shockwave_multiplier_min 0 -set g_balance_laser_shockwave_splash_damage 15 -set g_balance_laser_shockwave_splash_edgedamage 0 -set g_balance_laser_shockwave_splash_force 100 -set g_balance_laser_shockwave_splash_force_forwardbias 50 -set g_balance_laser_shockwave_splash_multiplier_accuracy 0.5 -set g_balance_laser_shockwave_splash_multiplier_distance 0.5 -set g_balance_laser_shockwave_splash_multiplier_min 0 -set g_balance_laser_shockwave_splash_radius 70 -set g_balance_laser_shockwave_spread_max 120 -set g_balance_laser_shockwave_spread_min 25 - -set g_balance_laser_switchdelay_drop 0 -set g_balance_laser_switchdelay_raise 0 -set g_balance_laser_reload_ammo 0 //default: 6 -set g_balance_laser_reload_time 2 -// }}} -// {{{ shotgun -set g_balance_shotgun_primary_bullets 14 -set g_balance_shotgun_primary_damage 4 -set g_balance_shotgun_primary_force 15 -set g_balance_shotgun_primary_spread 0.12 -set g_balance_shotgun_primary_refire 0.75 -set g_balance_shotgun_primary_animtime 0.2 -set g_balance_shotgun_primary_ammo 1 -set g_balance_shotgun_primary_solidpenetration 3.8 -set g_balance_shotgun_secondary 1 -set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow -set g_balance_shotgun_secondary_melee_range 120 -set g_balance_shotgun_secondary_melee_swing_side 120 -set g_balance_shotgun_secondary_melee_swing_up 30 -set g_balance_shotgun_secondary_melee_time 0.15 -set g_balance_shotgun_secondary_melee_traces 10 -set g_balance_shotgun_secondary_melee_no_doubleslap 1 -set g_balance_shotgun_secondary_melee_nonplayerdamage 40 -set g_balance_shotgun_secondary_melee_multihit 1 -set g_balance_shotgun_secondary_damage 80 -set g_balance_shotgun_secondary_force 200 -set g_balance_shotgun_secondary_refire 1.25 -set g_balance_shotgun_secondary_animtime 1 -set g_balance_shotgun_switchdelay_drop 0 -set g_balance_shotgun_switchdelay_raise 0 -set g_balance_shotgun_reload_ammo 0 //default: 5 -set g_balance_shotgun_reload_time 2 -// }}} -// {{{ uzi -set g_balance_uzi_mode 1 // Activates varible spread for sustained & burst mode secondary -set g_balance_uzi_spread_min 0 -set g_balance_uzi_spread_max 0 -set g_balance_uzi_spread_add 0 - -set g_balance_uzi_burst 3 // # of bullets in a burst (if set to 2 or more) -set g_balance_uzi_burst_animtime 0.3 -set g_balance_uzi_burst_refire 0.06 // refire between burst bullets -set g_balance_uzi_burst_refire2 0.45 // refire after burst -set g_balance_uzi_burst_spread 0.03 -set g_balance_uzi_burst_damage 25 -set g_balance_uzi_burst_force 20 -set g_balance_uzi_burst_ammo 3 - -set g_balance_uzi_first 1 -set g_balance_uzi_first_damage 14 -set g_balance_uzi_first_force 5 -set g_balance_uzi_first_spread 0.03 -set g_balance_uzi_first_refire 0.4 -set g_balance_uzi_first_ammo 1 - -set g_balance_uzi_sustained_damage 12 -set g_balance_uzi_sustained_force 5 -set g_balance_uzi_sustained_spread 0 -set g_balance_uzi_sustained_refire 0.1 -set g_balance_uzi_sustained_ammo 1 - -set g_balance_uzi_solidpenetration 13.1 - -set g_balance_uzi_switchdelay_drop 0 -set g_balance_uzi_switchdelay_raise 0 - -set g_balance_uzi_reload_ammo 0 //default: 30 -set g_balance_uzi_reload_time 2 -// }}} -// {{{ mortar -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 250 -set g_balance_grenadelauncher_primary_radius 100 -set g_balance_grenadelauncher_primary_speed 2000 -set g_balance_grenadelauncher_primary_speed_up 200 -set g_balance_grenadelauncher_primary_speed_z 0 -set g_balance_grenadelauncher_primary_spread 0 -set g_balance_grenadelauncher_primary_lifetime 5 -set g_balance_grenadelauncher_primary_lifetime2 1 -set g_balance_grenadelauncher_primary_refire 0.7 -set g_balance_grenadelauncher_primary_animtime 0.3 -set g_balance_grenadelauncher_primary_ammo 2 -set g_balance_grenadelauncher_primary_health 0 -set g_balance_grenadelauncher_primary_damageforcescale 0 -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 30 -set g_balance_grenadelauncher_secondary_force 300 -set g_balance_grenadelauncher_secondary_radius 200 -set g_balance_grenadelauncher_secondary_speed 800 -set g_balance_grenadelauncher_secondary_speed_up 0 -set g_balance_grenadelauncher_secondary_speed_z 200 -set g_balance_grenadelauncher_secondary_spread 0 -set g_balance_grenadelauncher_secondary_lifetime 8 -set g_balance_grenadelauncher_secondary_lifetime_bounce 0.5 -set g_balance_grenadelauncher_secondary_lifetime_stick 0 -set g_balance_grenadelauncher_secondary_refire 0.7 -set g_balance_grenadelauncher_secondary_animtime 0.5 -set g_balance_grenadelauncher_secondary_ammo 2 -set g_balance_grenadelauncher_secondary_health 0 -set g_balance_grenadelauncher_secondary_damageforcescale 0 -set g_balance_grenadelauncher_secondary_remote_detonateprimary 0 - -set g_balance_grenadelauncher_bouncefactor 0.5 -set g_balance_grenadelauncher_bouncestop 0.075 - -set g_balance_grenadelauncher_switchdelay_drop 0 -set g_balance_grenadelauncher_switchdelay_raise 0 - -set g_balance_grenadelauncher_reload_ammo 0 //default: 12 -set g_balance_grenadelauncher_reload_time 2 -// }}} -// {{{ electro -set g_balance_electro_lightning 0 -set g_balance_electro_primary_damage 55 -set g_balance_electro_primary_edgedamage 27.5 -set g_balance_electro_primary_force 200 -set g_balance_electro_primary_force_up 0 -set g_balance_electro_primary_radius 100 -set g_balance_electro_primary_comboradius 150 -set g_balance_electro_primary_speed 2500 -set g_balance_electro_primary_spread 0 -set g_balance_electro_primary_lifetime 5 -set g_balance_electro_primary_refire 0.6 -set g_balance_electro_primary_animtime 0.1 -set g_balance_electro_primary_ammo 4 -set g_balance_electro_primary_range 0 -set g_balance_electro_primary_falloff_mindist 255 // 0.3 * radius -set g_balance_electro_primary_falloff_maxdist 850 -set g_balance_electro_primary_falloff_halflifedist 425 -set g_balance_electro_secondary_damage 40 -set g_balance_electro_secondary_edgedamage 20 -set g_balance_electro_secondary_force 200 -set g_balance_electro_secondary_radius 150 -set g_balance_electro_secondary_speed 900 -set g_balance_electro_secondary_speed_up 200 -set g_balance_electro_secondary_speed_z 0 -set g_balance_electro_secondary_spread 0.05 -set g_balance_electro_secondary_lifetime 3 -set g_balance_electro_secondary_refire 0.2 -set g_balance_electro_secondary_refire2 1.5 -set g_balance_electro_secondary_animtime 0.2 -set g_balance_electro_secondary_ammo 2 -set g_balance_electro_secondary_health 5 -set g_balance_electro_secondary_damageforcescale 4 -set g_balance_electro_secondary_damagedbycontents 1 -set g_balance_electro_secondary_count 3 -set g_balance_electro_secondary_bouncefactor 0.4 -set g_balance_electro_secondary_bouncestop 0.05 -set g_balance_electro_combo_damage 40 -set g_balance_electro_combo_edgedamage 20 -set g_balance_electro_combo_force 120 -set g_balance_electro_combo_radius 175 -set g_balance_electro_combo_comboradius 275 -set g_balance_electro_combo_speed 2000 -set g_balance_electro_combo_safeammocheck 1 -set g_balance_electro_switchdelay_drop 0 -set g_balance_electro_switchdelay_raise 0 -set g_balance_electro_reload_ammo 0 //default: 20 -set g_balance_electro_reload_time 2 -// }}} -// {{{ crylink -set g_balance_crylink_primary_damage 12 -set g_balance_crylink_primary_edgedamage 6 -set g_balance_crylink_primary_force -50 -set g_balance_crylink_primary_radius 80 -set g_balance_crylink_primary_speed 2000 -set g_balance_crylink_primary_spread 0.08 -set g_balance_crylink_primary_shots 6 -set g_balance_crylink_primary_bounces 1 -set g_balance_crylink_primary_refire 0.7 -set g_balance_crylink_primary_animtime 0.3 -set g_balance_crylink_primary_ammo 3 -set g_balance_crylink_primary_bouncedamagefactor 0.5 -set g_balance_crylink_primary_joindelay 0.1 -set g_balance_crylink_primary_joinspread 0.2 -set g_balance_crylink_primary_joinexplode 1 -set g_balance_crylink_primary_joinexplode_damage 0 -set g_balance_crylink_primary_joinexplode_edgedamage 0 -set g_balance_crylink_primary_joinexplode_radius 0 -set g_balance_crylink_primary_joinexplode_force 0 -set g_balance_crylink_primary_linkexplode 1 - -set g_balance_crylink_primary_middle_lifetime 5 // range: 35000 full, fades to 70000 -set g_balance_crylink_primary_middle_fadetime 5 -set g_balance_crylink_primary_other_lifetime 5 -set g_balance_crylink_primary_other_fadetime 5 - -set g_balance_crylink_secondary 1 -set g_balance_crylink_secondary_damage 10 -set g_balance_crylink_secondary_edgedamage 5 -set g_balance_crylink_secondary_force -150 -set g_balance_crylink_secondary_radius 100 -set g_balance_crylink_secondary_speed 3000 -set g_balance_crylink_secondary_spread 0.01 -set g_balance_crylink_secondary_spreadtype 1 -set g_balance_crylink_secondary_shots 5 -set g_balance_crylink_secondary_bounces 0 -set g_balance_crylink_secondary_refire 0.7 -set g_balance_crylink_secondary_animtime 0.2 -set g_balance_crylink_secondary_ammo 2 -set g_balance_crylink_secondary_bouncedamagefactor 0.5 -set g_balance_crylink_secondary_joindelay 0 -set g_balance_crylink_secondary_joinspread 0 -set g_balance_crylink_secondary_joinexplode 0 -set g_balance_crylink_secondary_joinexplode_damage 0 -set g_balance_crylink_secondary_joinexplode_edgedamage 0 -set g_balance_crylink_secondary_joinexplode_radius 0 -set g_balance_crylink_secondary_joinexplode_force 0 -set g_balance_crylink_secondary_linkexplode 1 - -set g_balance_crylink_secondary_middle_lifetime 5 // range: 35000 full, fades to 70000 -set g_balance_crylink_secondary_middle_fadetime 5 -set g_balance_crylink_secondary_line_lifetime 5 -set g_balance_crylink_secondary_line_fadetime 5 - -set g_balance_crylink_switchdelay_drop 0 -set g_balance_crylink_switchdelay_raise 0 - -set g_balance_crylink_reload_ammo 0 //default: 10 -set g_balance_crylink_reload_time 2 -// }}} -// {{{ nex -set g_balance_nex_primary_damage 90 -set g_balance_nex_primary_force 400 -set g_balance_nex_primary_refire 1.5 -set g_balance_nex_primary_animtime 0.4 -set g_balance_nex_primary_ammo 6 -set g_balance_nex_primary_damagefalloff_mindist 0 // 1000 For tZork ;3 -set g_balance_nex_primary_damagefalloff_maxdist 0 // 3000 -set g_balance_nex_primary_damagefalloff_halflife 0 // 1500 -set g_balance_nex_primary_damagefalloff_forcehalflife 0 // 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_chargepool 0 -set g_balance_nex_secondary_chargepool_regen 0.15 -set g_balance_nex_secondary_chargepool_pause_regen 1 -set g_balance_nex_secondary_chargepool_pause_health_regen 1 -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 2 -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_charge 1 -set g_balance_nex_charge_mindmg 40 -set g_balance_nex_charge_start 0.5 -set g_balance_nex_charge_rate 0.4 -set g_balance_nex_charge_animlimit 0.5 -set g_balance_nex_charge_limit 1 -set g_balance_nex_charge_rot_rate 0 -set g_balance_nex_charge_rot_pause 0 // Dont rot down untill this long after release of charge button -set g_balance_nex_charge_shot_multiplier 0 -set g_balance_nex_charge_velocity_rate 0 -set g_balance_nex_charge_minspeed 400 -set g_balance_nex_charge_maxspeed 800 - -set g_balance_nex_switchdelay_drop 0 -set g_balance_nex_switchdelay_raise 0 - -set g_balance_nex_reload_ammo 0 //default: 25 -set g_balance_nex_reload_time 2 -// }}} -// {{{ minstanex -set g_balance_minstanex_refire 1 -set g_balance_minstanex_animtime 0.3 -set g_balance_minstanex_ammo 10 -set g_balance_minstanex_laser_ammo 0 -set g_balance_minstanex_laser_animtime 0.3 -set g_balance_minstanex_laser_refire 0.7 -set g_balance_minstanex_switchdelay_drop 0 -set g_balance_minstanex_switchdelay_raise 0 -set g_balance_minstanex_reload_ammo 0 //default: 50 -set g_balance_minstanex_reload_time 2 -// }}} -// {{{ hagar -set g_balance_hagar_primary_damage 25 -set g_balance_hagar_primary_edgedamage 12.5 -set g_balance_hagar_primary_force 92 -set g_balance_hagar_primary_health 15 -set g_balance_hagar_primary_damageforcescale 0 -set g_balance_hagar_primary_radius 25 -set g_balance_hagar_primary_spread 0.03 -set g_balance_hagar_primary_speed 2000 -set g_balance_hagar_primary_lifetime 5 -set g_balance_hagar_primary_refire 0.11 -set g_balance_hagar_primary_ammo 1 -set g_balance_hagar_secondary 0 -set g_balance_hagar_secondary_load 1 -set g_balance_hagar_secondary_load_speed 0.5 -set g_balance_hagar_secondary_load_spread 0.075 -set g_balance_hagar_secondary_load_spread_bias 0.5 -set g_balance_hagar_secondary_load_max 4 -set g_balance_hagar_secondary_load_hold 4 -set g_balance_hagar_secondary_load_releasedeath 0 -set g_balance_hagar_secondary_load_abort 0 -set g_balance_hagar_secondary_load_linkexplode 0 -set g_balance_hagar_secondary_load_animtime 0.2 -set g_balance_hagar_secondary_damage 40 -set g_balance_hagar_secondary_edgedamage 20 -set g_balance_hagar_secondary_force 75 -set g_balance_hagar_secondary_health 15 -set g_balance_hagar_secondary_damageforcescale 0 -set g_balance_hagar_secondary_radius 80 -set g_balance_hagar_secondary_spread 0.05 -set g_balance_hagar_secondary_speed 2000 -set g_balance_hagar_secondary_lifetime_min 10 -set g_balance_hagar_secondary_lifetime_rand 0 -set g_balance_hagar_secondary_refire 0.5 -set g_balance_hagar_secondary_ammo 1 -set g_balance_hagar_switchdelay_drop 0 -set g_balance_hagar_switchdelay_raise 0 -set g_balance_hagar_reload_ammo 0 //default: 25 -set g_balance_hagar_reload_time 2 -// }}} -// {{{ rocketlauncher -set g_balance_rocketlauncher_damage 80 -set g_balance_rocketlauncher_edgedamage 40 -set g_balance_rocketlauncher_force 350 -set g_balance_rocketlauncher_radius 110 -set g_balance_rocketlauncher_speed 1000 -set g_balance_rocketlauncher_speedaccel 0 -set g_balance_rocketlauncher_speedstart 1000 -set g_balance_rocketlauncher_lifetime 100 -set g_balance_rocketlauncher_refire 0.9 -set g_balance_rocketlauncher_animtime 0.7 -set g_balance_rocketlauncher_ammo 4 -set g_balance_rocketlauncher_health 0 // 30 // 5 hitpoints above maximum laser value -- this way lasers can't blow it up, but grenadelauncher still can most the time. -set g_balance_rocketlauncher_damageforcescale 0 // low damage force scale so that it can still be affected by other hits, but not so much that it does a 90 degree turn -set g_balance_rocketlauncher_detonatedelay 999 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time -set g_balance_rocketlauncher_guiderate 0 // max degrees per second -set g_balance_rocketlauncher_guideratedelay 0.01 // immediate -set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic) -set g_balance_rocketlauncher_guidedelay 0.2 // delay before guiding kicks in -set g_balance_rocketlauncher_guidestop 1 // stop guiding when firing again -set g_balance_rocketlauncher_remote_damage 70 -set g_balance_rocketlauncher_remote_edgedamage 35 -set g_balance_rocketlauncher_remote_radius 110 -set g_balance_rocketlauncher_remote_force 350 -set g_balance_rocketlauncher_switchdelay_drop 0 -set g_balance_rocketlauncher_switchdelay_raise 0 -set g_balance_rocketlauncher_reload_ammo 0 //default: 25 -set g_balance_rocketlauncher_reload_time 2 -// }}} -// {{{ porto -set g_balance_porto_primary_refire 1.5 -set g_balance_porto_primary_animtime 0.3 -set g_balance_porto_primary_speed 5000 -set g_balance_porto_primary_lifetime 5 -set g_balance_porto_secondary 1 -set g_balance_porto_secondary_refire 1.5 -set g_balance_porto_secondary_animtime 0.3 -set g_balance_porto_secondary_speed 1000 -set g_balance_porto_secondary_lifetime 5 -set g_balance_porto_switchdelay_drop 0 -set g_balance_porto_switchdelay_raise 0 -set g_balance_portal_health 200 // these get recharged whenever the portal is used -set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used -// }}} -// {{{ hook -set g_balance_hook_primary_fuel 5 // hook monkeys set 0 -set g_balance_hook_primary_refire 0.2 // hook monkeys set 0 -set g_balance_hook_primary_animtime 0.3 // good shoot anim -set g_balance_hook_primary_hooked_time_max 0 // infinite -set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free -set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked -set g_balance_hook_secondary_damage 25 // not much -set g_balance_hook_secondary_edgedamage 5 // not much -set g_balance_hook_secondary_radius 500 // LOTS -set g_balance_hook_secondary_force -2000 // LOTS -set g_balance_hook_secondary_ammo 50 // a whole pack -set g_balance_hook_secondary_lifetime 5 // infinite -set g_balance_hook_secondary_speed 0 // not much throwing -set g_balance_hook_secondary_gravity 5 // fast falling -set g_balance_hook_secondary_refire 3 // don't drop too many bombs... -set g_balance_hook_secondary_animtime 0.3 // good shoot anim -set g_balance_hook_secondary_power 3 // effect behaves like a square function -set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds -set g_balance_hook_secondary_health 15 -set g_balance_hook_secondary_damageforcescale 0 -set g_balance_hook_switchdelay_drop 0 -set g_balance_hook_switchdelay_raise 0 -// }}} -// {{{ tuba -set g_balance_tuba_refire 0.05 -set g_balance_tuba_animtime 0.05 -set g_balance_tuba_attenuation 0.5 -set g_balance_tuba_volume 1 -set g_balance_tuba_fadetime 0.25 -set g_balance_tuba_damage 5 -set g_balance_tuba_edgedamage 0 -set g_balance_tuba_radius 200 -set g_balance_tuba_force 40 -set g_balance_tuba_pitchstep 6 -set g_balance_tuba_switchdelay_drop 0 -set g_balance_tuba_switchdelay_raise 0 -// }}} -// {{{ fireball // this is a superweapon -- lets make it behave as one. -set g_balance_fireball_primary_animtime 0.2 -set g_balance_fireball_primary_bfgdamage 100 -set g_balance_fireball_primary_bfgforce 0 -set g_balance_fireball_primary_bfgradius 1000 -set g_balance_fireball_primary_damage 200 -set g_balance_fireball_primary_damageforcescale 0 -set g_balance_fireball_primary_edgedamage 50 -set g_balance_fireball_primary_force 600 -set g_balance_fireball_primary_health 0 -set g_balance_fireball_primary_laserburntime 0.5 -set g_balance_fireball_primary_laserdamage 80 -set g_balance_fireball_primary_laseredgedamage 20 -set g_balance_fireball_primary_laserradius 256 -set g_balance_fireball_primary_lifetime 15 -set g_balance_fireball_primary_radius 200 -set g_balance_fireball_primary_refire 2 -set g_balance_fireball_primary_refire2 0 -set g_balance_fireball_primary_speed 1200 -set g_balance_fireball_primary_spread 0 -set g_balance_fireball_secondary_animtime 0.3 -set g_balance_fireball_secondary_damage 40 -set g_balance_fireball_secondary_damageforcescale 4 -set g_balance_fireball_secondary_damagetime 5 -set g_balance_fireball_secondary_force 100 -set g_balance_fireball_secondary_laserburntime 0.5 -set g_balance_fireball_secondary_laserdamage 50 -set g_balance_fireball_secondary_laseredgedamage 20 -set g_balance_fireball_secondary_laserradius 110 -set g_balance_fireball_secondary_lifetime 7 -set g_balance_fireball_secondary_refire 1.5 -set g_balance_fireball_secondary_speed 900 -set g_balance_fireball_secondary_speed_up 100 -set g_balance_fireball_secondary_speed_z 0 -set g_balance_fireball_secondary_spread 0 -set g_balance_fireball_switchdelay_drop 0 -set g_balance_fireball_switchdelay_raise 0 -// }}} diff --git a/oldbalanceXPM.cfg b/oldbalanceXPM.cfg deleted file mode 100644 index f7b088aae..000000000 --- a/oldbalanceXPM.cfg +++ /dev/null @@ -1,780 +0,0 @@ -g_mod_balance XPM - -// {{{ starting gear -set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" // UNTIL IT CAN BE REMOVED FROM CODE -set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" -set g_balance_health_start 100 -set g_balance_armor_start 0 -set g_start_ammo_shells 15 -set g_start_ammo_nails 0 -set g_start_ammo_rockets 0 -set g_start_ammo_cells 0 -set g_start_ammo_fuel 0 -set g_warmup_start_health 100 "starting values when being in warmup-stage" -set g_warmup_start_armor 100 "starting values when being in warmup-stage" -set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage" -set g_warmup_start_ammo_nails 160 "starting values when being in warmup-stage" -set g_warmup_start_ammo_rockets 80 "starting values when being in warmup-stage" -set g_warmup_start_ammo_cells 90 "starting values when being in warmup-stage" -set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage" -set g_lms_start_health 200 -set g_lms_start_armor 200 -set g_lms_start_ammo_shells 60 -set g_lms_start_ammo_nails 320 -set g_lms_start_ammo_rockets 160 -set g_lms_start_ammo_cells 180 -set g_lms_start_ammo_fuel 0 -set g_balance_nix_roundtime 25 -set g_balance_nix_incrtime 1.6 -set g_balance_nix_ammo_shells 60 -set g_balance_nix_ammo_nails 320 -set g_balance_nix_ammo_rockets 160 -set g_balance_nix_ammo_cells 180 -set g_balance_nix_ammo_fuel 0 -set g_balance_nix_ammoincr_shells 2 // eh this will need figured out later I assume -set g_balance_nix_ammoincr_nails 6 -set g_balance_nix_ammoincr_rockets 2 -set g_balance_nix_ammoincr_cells 2 -set g_balance_nix_ammoincr_fuel 2 -// }}} - -// {{{ pickup items -set g_pickup_ammo_anyway 1 -set g_pickup_weapons_anyway 1 -set g_pickup_shells 15 -set g_pickup_shells_weapon 15 -set g_pickup_shells_max 60 -set g_pickup_nails 80 -set g_pickup_nails_weapon 80 -set g_pickup_nails_max 320 -set g_pickup_rockets 40 -set g_pickup_rockets_weapon 40 -set g_pickup_rockets_max 160 -set g_pickup_cells 30 -set g_pickup_cells_weapon 30 -set g_pickup_cells_max 180 -set g_pickup_fuel 50 -set g_pickup_fuel_weapon 50 -set g_pickup_fuel_jetpack 100 -set g_pickup_fuel_max 100 -set g_pickup_armorsmall 5 -set g_pickup_armorsmall_max 200 -set g_pickup_armorsmall_anyway 0 -set g_pickup_armormedium 25 -set g_pickup_armormedium_max 100 -set g_pickup_armormedium_anyway 0 -set g_pickup_armorbig 50 -set g_pickup_armorbig_max 100 -set g_pickup_armorbig_anyway 0 -set g_pickup_armorlarge 100 -set g_pickup_armorlarge_max 200 -set g_pickup_armorlarge_anyway 0 -set g_pickup_healthsmall 5 -set g_pickup_healthsmall_max 200 -set g_pickup_healthsmall_anyway 0 -set g_pickup_healthmedium 25 -set g_pickup_healthmedium_max 100 -set g_pickup_healthmedium_anyway 0 -set g_pickup_healthlarge 50 -set g_pickup_healthlarge_max 100 -set g_pickup_healthlarge_anyway 0 -set g_pickup_healthmega 100 -set g_pickup_healthmega_max 200 -set g_pickup_healthmega_anyway 0 -set g_pickup_respawntime_short 15 -set g_pickup_respawntime_medium 20 -set g_pickup_respawntime_long 30 -set g_pickup_respawntime_powerup 120 -set g_pickup_respawntime_weapon 10 -set g_pickup_respawntime_superweapon 120 -set g_pickup_respawntime_ammo 15 -set g_pickup_respawntimejitter_short 0 -set g_pickup_respawntimejitter_medium 0 -set g_pickup_respawntimejitter_long 0 -set g_pickup_respawntimejitter_powerup 30 -set g_pickup_respawntimejitter_weapon 0 -set g_pickup_respawntimejitter_superweapon 10 -set g_pickup_respawntimejitter_ammo 0 -// }}} - -// {{{ regen/rot -set g_balance_health_regen 0.08 -set g_balance_health_regenlinear 0.5 -set g_balance_pause_health_regen 5 -set g_balance_pause_health_regen_spawn 0 -set g_balance_health_rot 0.03 -set g_balance_health_rotlinear 0.75 -set g_balance_pause_health_rot 1 -set g_balance_pause_health_rot_spawn 5 -set g_balance_health_regenstable 100 -set g_balance_health_rotstable 100 -set g_balance_health_limit 999 -set g_balance_armor_regen 0 -set g_balance_armor_regenlinear 0 -set g_balance_armor_rot 0.03 -set g_balance_armor_rotlinear 0.75 -set g_balance_pause_armor_rot 1 -set g_balance_pause_armor_rot_spawn 5 -set g_balance_armor_regenstable 100 -set g_balance_armor_rotstable 100 -set g_balance_armor_limit 999 -set g_balance_armor_blockpercent 0.6 -set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)" -set g_balance_fuel_regenlinear 0 -set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter -set g_balance_fuel_rot 0.05 -set g_balance_fuel_rotlinear 0 -set g_balance_pause_fuel_rot 5 -set g_balance_pause_fuel_rot_spawn 10 -set g_balance_fuel_regenstable 50 -set g_balance_fuel_rotstable 100 -set g_balance_fuel_limit 999 -// }}} - -// {{{ misc -set g_balance_selfdamagepercent 0.65 -set g_weaponspeedfactor 1 "weapon projectile speed multiplier" -set g_weaponratefactor 1 "weapon fire rate multiplier" -set g_weapondamagefactor 1 "weapon damage multiplier" -set g_weaponforcefactor 1 "weapon force multiplier" -set g_weaponspreadfactor 1 "weapon spread multiplier" -set g_balance_firetransfer_time 0.9 -set g_balance_firetransfer_damage 0.8 -set g_throughfloor_damage 0.75 -set g_throughfloor_force 0.75 -set g_projectiles_damage 1 -// possible values: -// -2: absolutely no damage to projectiles (no exceptions) -// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines) -// 0: only damage from contents (lava/slime) or exceptions -// 1: only self damage or damage from contents or exceptions -// 2: allow all damage to projectiles normally -set g_projectiles_keep_owner 0 -set g_projectiles_newton_style 0 -// possible values: -// 0: absolute velocity projectiles (like Quake) -// 1: relative velocity projectiles, "Newtonian" (like Tribes 2) -// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard) -set g_projectiles_newton_style_2_minfactor 0.8 -set g_projectiles_newton_style_2_maxfactor 1.5 -set g_projectiles_spread_style 7 -// possible values: -// 0: forward + solid sphere (like Quake) - varies velocity -// 1: forward + flattened solid sphere -// 2: forward + solid circle -// 3: forward + normal distribution 3D - varies velocity -// 4: forward + normal distribution on a plane -// 5: forward + circle with 1-r falloff -// 6: forward + circle with 1-r^2 falloff -// 7: forward + circle with (1-r)(2-r) falloff -set g_balance_falldamage_deadminspeed 250 -set g_balance_falldamage_minspeed 900 -set g_balance_falldamage_factor 0.20 -set g_balance_falldamage_maxdamage 40 -set g_balance_damagepush_speedfactor 2.5 -set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage -set g_balance_contents_drowndelay 10 // time under water before a player begins drowning -set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning -set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava -set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime -set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime -set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap" -// }}} - -// {{{ powerups -set g_balance_powerup_invincible_takedamage 0.25 // only 1/4th damage is taken -set g_balance_powerup_invincible_time 30 -set g_balance_powerup_strength_damage 3 -set g_balance_powerup_strength_force 3 -set g_balance_powerup_strength_time 30 -set g_balance_powerup_strength_selfdamage 1.5 -set g_balance_powerup_strength_selfforce 1.5 -set g_balance_superweapons_time 30 -// }}} - -// {{{ jetpack/hook -set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack" -set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction" -set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)" -set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction" -set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction" -set g_jetpack_fuel 8 "fuel per second for jetpack" -set g_jetpack_attenuation 2 "jetpack sound attenuation" - -set g_grappling_hook_tarzan 2 // 2: can also pull players -set g_balance_grapplehook_speed_fly 1800 -set g_balance_grapplehook_speed_pull 2000 -set g_balance_grapplehook_force_rubber 2000 -set g_balance_grapplehook_force_rubber_overstretch 1000 -set g_balance_grapplehook_length_min 50 -set g_balance_grapplehook_stretch 50 -set g_balance_grapplehook_airfriction 0.2 -set g_balance_grapplehook_health 50 -set g_balance_grapplehook_damagedbycontents 1 -set g_balance_grapplehook_refire 0.2 -// }}} - -// {{{ weapon properties -// {{{ laser -set g_balance_laser_melee_animtime 0.3 -set g_balance_laser_melee_damage 80 -set g_balance_laser_melee_delay 0.25 -set g_balance_laser_melee_force 200 -set g_balance_laser_melee_multihit 1 -set g_balance_laser_melee_no_doubleslap 1 -set g_balance_laser_melee_nonplayerdamage 40 -set g_balance_laser_melee_range 120 -set g_balance_laser_melee_refire 1.25 -set g_balance_laser_melee_swing_side 120 -set g_balance_laser_melee_swing_up 30 -set g_balance_laser_melee_time 0.15 -set g_balance_laser_melee_traces 10 - -set g_balance_laser_primary 0 // 0 = shockwave attack, 1 = projectile primary -set g_balance_laser_primary_damage 25 -set g_balance_laser_primary_edgedamage 12.5 -set g_balance_laser_primary_force 300 -set g_balance_laser_primary_radius 70 -set g_balance_laser_primary_speed 6000 -set g_balance_laser_primary_spread 0 -set g_balance_laser_primary_refire 0.7 -set g_balance_laser_primary_animtime 0.2 -set g_balance_laser_primary_lifetime 5 -set g_balance_laser_primary_shotangle 0 -set g_balance_laser_primary_delay 0 -set g_balance_laser_primary_force_zscale 1.2 -set g_balance_laser_primary_force_velocitybias 0 -set g_balance_laser_primary_force_other_scale 1 - -set g_balance_laser_secondary 2 // 0 = switch away to last used weapon, 1 = projectile secondary, 2 = melee secondary -set g_balance_laser_secondary_damage 25 -set g_balance_laser_secondary_edgedamage 12.5 -set g_balance_laser_secondary_force 400 -set g_balance_laser_secondary_radius 70 -set g_balance_laser_secondary_speed 12000 -set g_balance_laser_secondary_spread 0 -set g_balance_laser_secondary_refire 0.7 -set g_balance_laser_secondary_animtime 0.2 -set g_balance_laser_secondary_lifetime 5 -set g_balance_laser_secondary_shotangle -90 -set g_balance_laser_secondary_delay 0 -set g_balance_laser_secondary_force_zscale 1.25 -set g_balance_laser_secondary_force_velocitybias 0 -set g_balance_laser_secondary_force_other_scale 1 - -set g_balance_laser_shockwave_damage 20 -set g_balance_laser_shockwave_distance 2000 -set g_balance_laser_shockwave_edgedamage 0 -set g_balance_laser_shockwave_force 200 -set g_balance_laser_shockwave_force_forwardbias 50 -set g_balance_laser_shockwave_force_zscale 2 -set g_balance_laser_shockwave_jump_damage 20 -set g_balance_laser_shockwave_jump_edgedamage 0 -set g_balance_laser_shockwave_jump_force 300 -set g_balance_laser_shockwave_jump_force_velocitybias 0 -set g_balance_laser_shockwave_jump_force_zscale 1.25 -set g_balance_laser_shockwave_jump_multiplier_accuracy 0.5 -set g_balance_laser_shockwave_jump_multiplier_distance 0.5 -set g_balance_laser_shockwave_jump_multiplier_min 0 -set g_balance_laser_shockwave_jump_radius 150 -set g_balance_laser_shockwave_multiplier_accuracy 0.5 -set g_balance_laser_shockwave_multiplier_distance 0.5 -set g_balance_laser_shockwave_multiplier_min 0 -set g_balance_laser_shockwave_splash_damage 15 -set g_balance_laser_shockwave_splash_edgedamage 0 -set g_balance_laser_shockwave_splash_force 100 -set g_balance_laser_shockwave_splash_force_forwardbias 50 -set g_balance_laser_shockwave_splash_multiplier_accuracy 0.5 -set g_balance_laser_shockwave_splash_multiplier_distance 0.5 -set g_balance_laser_shockwave_splash_multiplier_min 0 -set g_balance_laser_shockwave_splash_radius 70 -set g_balance_laser_shockwave_spread_max 120 -set g_balance_laser_shockwave_spread_min 25 - -set g_balance_laser_switchdelay_drop 0.15 -set g_balance_laser_switchdelay_raise 0.15 -set g_balance_laser_reload_ammo 0 //default: 6 -set g_balance_laser_reload_time 2 -// }}} -// {{{ shotgun -set g_balance_shotgun_primary_bullets 14 -set g_balance_shotgun_primary_damage 4 -set g_balance_shotgun_primary_force 15 -set g_balance_shotgun_primary_spread 0.12 -set g_balance_shotgun_primary_refire 0.75 -set g_balance_shotgun_primary_animtime 0.2 -set g_balance_shotgun_primary_ammo 1 -set g_balance_shotgun_primary_solidpenetration 3.8 -set g_balance_shotgun_secondary 1 -set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow -set g_balance_shotgun_secondary_melee_range 120 -set g_balance_shotgun_secondary_melee_swing_side 120 -set g_balance_shotgun_secondary_melee_swing_up 30 -set g_balance_shotgun_secondary_melee_time 0.15 -set g_balance_shotgun_secondary_melee_traces 10 -set g_balance_shotgun_secondary_melee_no_doubleslap 1 -set g_balance_shotgun_secondary_melee_nonplayerdamage 40 -set g_balance_shotgun_secondary_melee_multihit 1 -set g_balance_shotgun_secondary_damage 80 -set g_balance_shotgun_secondary_force 200 -set g_balance_shotgun_secondary_refire 1.25 -set g_balance_shotgun_secondary_animtime 1 -set g_balance_shotgun_switchdelay_drop 0.2 -set g_balance_shotgun_switchdelay_raise 0.2 -set g_balance_shotgun_reload_ammo 0 //default: 5 -set g_balance_shotgun_reload_time 2 -// }}} -// {{{ uzi -set g_balance_uzi_mode 1 // Activates varible spread for sustained & burst mode secondary -set g_balance_uzi_spread_min 0.02 -set g_balance_uzi_spread_max 0.05 -set g_balance_uzi_spread_add 0.012 - -set g_balance_uzi_burst 3 // # of bullets in a burst (if set to 2 or more) -set g_balance_uzi_burst_animtime 0.3 -set g_balance_uzi_burst_refire 0.06 // refire between burst bullets -set g_balance_uzi_burst_refire2 0.45 // refire after burst -set g_balance_uzi_burst_spread 0.02 -set g_balance_uzi_burst_damage 25 -set g_balance_uzi_burst_force 20 -set g_balance_uzi_burst_ammo 3 - -set g_balance_uzi_first 1 -set g_balance_uzi_first_damage 14 -set g_balance_uzi_first_force 5 -set g_balance_uzi_first_spread 0.03 -set g_balance_uzi_first_refire 0.125 -set g_balance_uzi_first_ammo 1 - -set g_balance_uzi_sustained_damage 10 // 100 dps -set g_balance_uzi_sustained_force 5 -set g_balance_uzi_sustained_spread 0.03 -set g_balance_uzi_sustained_refire 0.1 -set g_balance_uzi_sustained_ammo 1 - -set g_balance_uzi_solidpenetration 13.1 - -set g_balance_uzi_switchdelay_drop 0.2 -set g_balance_uzi_switchdelay_raise 0.2 - -set g_balance_uzi_reload_ammo 60 //default: 30 -set g_balance_uzi_reload_time 2 -// }}} -// {{{ mortar -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 250 -set g_balance_grenadelauncher_primary_radius 120 -set g_balance_grenadelauncher_primary_speed 1900 -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_lifetime 5 -set g_balance_grenadelauncher_primary_lifetime2 1 -set g_balance_grenadelauncher_primary_refire 0.8 -set g_balance_grenadelauncher_primary_animtime 0.3 -set g_balance_grenadelauncher_primary_ammo 2 -set g_balance_grenadelauncher_primary_health 15 -set g_balance_grenadelauncher_primary_damageforcescale 0 -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 30 -set g_balance_grenadelauncher_secondary_force 250 -set g_balance_grenadelauncher_secondary_radius 120 -set g_balance_grenadelauncher_secondary_speed 1400 -set g_balance_grenadelauncher_secondary_speed_up 150 -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_lifetime_bounce 0.5 -set g_balance_grenadelauncher_secondary_lifetime_stick 0 -set g_balance_grenadelauncher_secondary_refire 0.7 -set g_balance_grenadelauncher_secondary_animtime 0.3 -set g_balance_grenadelauncher_secondary_ammo 2 -set g_balance_grenadelauncher_secondary_health 30 -set g_balance_grenadelauncher_secondary_damageforcescale 4 -set g_balance_grenadelauncher_secondary_remote_detonateprimary 0 - -set g_balance_grenadelauncher_bouncefactor 0.5 -set g_balance_grenadelauncher_bouncestop 0.075 - -set g_balance_grenadelauncher_switchdelay_drop 0.2 -set g_balance_grenadelauncher_switchdelay_raise 0.2 - -set g_balance_grenadelauncher_reload_ammo 0 //default: 12 -set g_balance_grenadelauncher_reload_time 2 -// }}} -// {{{ electro -set g_balance_electro_lightning 0 -set g_balance_electro_primary_damage 40 -set g_balance_electro_primary_edgedamage 20 -set g_balance_electro_primary_force 200 -set g_balance_electro_primary_force_up 0 -set g_balance_electro_primary_radius 100 -set g_balance_electro_primary_comboradius 300 -set g_balance_electro_primary_speed 2500 -set g_balance_electro_primary_spread 0 -set g_balance_electro_primary_lifetime 5 -set g_balance_electro_primary_refire 0.6 -set g_balance_electro_primary_animtime 0.3 -set g_balance_electro_primary_ammo 4 -set g_balance_electro_primary_range 0 -set g_balance_electro_primary_falloff_mindist 255 // 0.3 * radius -set g_balance_electro_primary_falloff_maxdist 850 -set g_balance_electro_primary_falloff_halflifedist 425 -set g_balance_electro_secondary_damage 40 -set g_balance_electro_secondary_edgedamage 20 -set g_balance_electro_secondary_force 50 -set g_balance_electro_secondary_radius 150 -set g_balance_electro_secondary_speed 1000 -set g_balance_electro_secondary_speed_up 200 -set g_balance_electro_secondary_speed_z 0 -set g_balance_electro_secondary_spread 0.04 -set g_balance_electro_secondary_lifetime 4 -set g_balance_electro_secondary_refire 0.2 -set g_balance_electro_secondary_refire2 1.6 -set g_balance_electro_secondary_animtime 0.2 -set g_balance_electro_secondary_ammo 2 -set g_balance_electro_secondary_health 5 -set g_balance_electro_secondary_damageforcescale 4 -set g_balance_electro_secondary_damagedbycontents 1 -set g_balance_electro_secondary_count 3 -set g_balance_electro_secondary_bouncefactor 0.3 -set g_balance_electro_secondary_bouncestop 0.05 -set g_balance_electro_combo_damage 50 -set g_balance_electro_combo_edgedamage 25 -set g_balance_electro_combo_force 120 -set g_balance_electro_combo_radius 150 -set g_balance_electro_combo_comboradius 300 -set g_balance_electro_combo_speed 2000 -set g_balance_electro_combo_safeammocheck 1 -set g_balance_electro_switchdelay_drop 0.2 -set g_balance_electro_switchdelay_raise 0.2 -set g_balance_electro_reload_ammo 0 //default: 20 -set g_balance_electro_reload_time 2 -// }}} -// {{{ lightning -set g_balance_lightning_primary_ammo 5 -set g_balance_lightning_primary_animtime 0.2 -set g_balance_lightning_primary_damage 100 -set g_balance_lightning_primary_edgedamage 0 -set g_balance_lightning_primary_falloff_mindist 0 -set g_balance_lightning_primary_falloff_maxdist 0 -set g_balance_lightning_primary_falloff_halflifedist 0 -set g_balance_lightning_primary_force 425 -set g_balance_lightning_primary_lifetime 0 -set g_balance_lightning_primary_radius 850 -set g_balance_lightning_primary_range 800 -set g_balance_lightning_primary_refire 0.4 -set g_balance_lightning_primary_speed 0 -set g_balance_lightning_primary_spread 0 -set g_balance_lightning_secondary_ammo 5 -set g_balance_lightning_secondary_animtime 0.5 -set g_balance_lightning_secondary_damage 100 -set g_balance_lightning_secondary_damageforcescale 4 -set g_balance_lightning_secondary_edgedamage 80 -set g_balance_lightning_secondary_flyingdamage 1 -set g_balance_lightning_secondary_flyingforce -80 -set g_balance_lightning_secondary_flyingradius 200 -set g_balance_lightning_secondary_force -200 -set g_balance_lightning_secondary_health 1 -set g_balance_lightning_secondary_lifetime 30 -set g_balance_lightning_secondary_radius 300 -set g_balance_lightning_secondary_refire 5 -set g_balance_lightning_secondary_speed 600 -// }}} -// {{{ crylink -set g_balance_crylink_primary_damage 12 -set g_balance_crylink_primary_edgedamage 6 -set g_balance_crylink_primary_force -50 -set g_balance_crylink_primary_radius 80 -set g_balance_crylink_primary_speed 2000 -set g_balance_crylink_primary_spread 0.08 -set g_balance_crylink_primary_shots 6 -set g_balance_crylink_primary_bounces 1 -set g_balance_crylink_primary_refire 0.7 -set g_balance_crylink_primary_animtime 0.3 -set g_balance_crylink_primary_ammo 3 -set g_balance_crylink_primary_bouncedamagefactor 0.5 -set g_balance_crylink_primary_joindelay 0.1 -set g_balance_crylink_primary_joinspread 0.2 -set g_balance_crylink_primary_joinexplode 1 -set g_balance_crylink_primary_joinexplode_damage 0 -set g_balance_crylink_primary_joinexplode_edgedamage 0 -set g_balance_crylink_primary_joinexplode_radius 0 -set g_balance_crylink_primary_joinexplode_force 0 -set g_balance_crylink_primary_linkexplode 1 - -set g_balance_crylink_primary_middle_lifetime 5 // range: 35000 full, fades to 70000 -set g_balance_crylink_primary_middle_fadetime 5 -set g_balance_crylink_primary_other_lifetime 5 -set g_balance_crylink_primary_other_fadetime 5 - -set g_balance_crylink_secondary 1 -set g_balance_crylink_secondary_damage 10 -set g_balance_crylink_secondary_edgedamage 5 -set g_balance_crylink_secondary_force -250 -set g_balance_crylink_secondary_radius 100 -set g_balance_crylink_secondary_speed 3000 -set g_balance_crylink_secondary_spread 0.01 -set g_balance_crylink_secondary_spreadtype 1 -set g_balance_crylink_secondary_shots 5 -set g_balance_crylink_secondary_bounces 0 -set g_balance_crylink_secondary_refire 0.7 -set g_balance_crylink_secondary_animtime 0.2 -set g_balance_crylink_secondary_ammo 2 -set g_balance_crylink_secondary_bouncedamagefactor 0.5 -set g_balance_crylink_secondary_joindelay 0 -set g_balance_crylink_secondary_joinspread 0 -set g_balance_crylink_secondary_joinexplode 0 -set g_balance_crylink_secondary_joinexplode_damage 0 -set g_balance_crylink_secondary_joinexplode_edgedamage 0 -set g_balance_crylink_secondary_joinexplode_radius 0 -set g_balance_crylink_secondary_joinexplode_force 0 -set g_balance_crylink_secondary_linkexplode 1 - -set g_balance_crylink_secondary_middle_lifetime 5 // range: 35000 full, fades to 70000 -set g_balance_crylink_secondary_middle_fadetime 5 -set g_balance_crylink_secondary_line_lifetime 5 -set g_balance_crylink_secondary_line_fadetime 5 - -set g_balance_crylink_switchdelay_drop 0.2 -set g_balance_crylink_switchdelay_raise 0.2 - -set g_balance_crylink_reload_ammo 0 //default: 10 -set g_balance_crylink_reload_time 2 -// }}} -// {{{ nex -set g_balance_nex_primary_damage 80 -set g_balance_nex_primary_force 400 -set g_balance_nex_primary_refire 1.5 -set g_balance_nex_primary_animtime 0.6 -set g_balance_nex_primary_ammo 6 -set g_balance_nex_primary_damagefalloff_mindist 0 // 1000 For tZork ;3 -set g_balance_nex_primary_damagefalloff_maxdist 0 // 3000 -set g_balance_nex_primary_damagefalloff_halflife 0 // 1500 -set g_balance_nex_primary_damagefalloff_forcehalflife 0 // 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_chargepool 0 -set g_balance_nex_secondary_chargepool_regen 0.15 -set g_balance_nex_secondary_chargepool_pause_regen 1 -set g_balance_nex_secondary_chargepool_pause_health_regen 1 -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 2 -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_charge 1 -set g_balance_nex_charge_mindmg 40 -set g_balance_nex_charge_start 0.5 -set g_balance_nex_charge_rate 0.4 -set g_balance_nex_charge_animlimit 0.5 -set g_balance_nex_charge_limit 1 -set g_balance_nex_charge_rot_rate 0 -set g_balance_nex_charge_rot_pause 0 // Dont rot down until this long after release of charge button -set g_balance_nex_charge_shot_multiplier 0 -set g_balance_nex_charge_velocity_rate 0 -set g_balance_nex_charge_minspeed 400 -set g_balance_nex_charge_maxspeed 800 - -set g_balance_nex_switchdelay_drop 0.3 -set g_balance_nex_switchdelay_raise 0.25 - -set g_balance_nex_reload_ammo 0 //default: 25 -set g_balance_nex_reload_time 2 -// }}} -// {{{ minstanex -set g_balance_minstanex_refire 1 -set g_balance_minstanex_animtime 0.3 -set g_balance_minstanex_ammo 10 -set g_balance_minstanex_laser_ammo 0 -set g_balance_minstanex_laser_animtime 0.3 -set g_balance_minstanex_laser_refire 0.7 -set g_balance_minstanex_switchdelay_drop 0.2 -set g_balance_minstanex_switchdelay_raise 0.2 -set g_balance_minstanex_reload_ammo 0 //default: 50 -set g_balance_minstanex_reload_time 2 -// }}} -// {{{ hagar -set g_balance_hagar_primary_damage 25 -set g_balance_hagar_primary_edgedamage 12.5 -set g_balance_hagar_primary_force 100 -set g_balance_hagar_primary_health 15 -set g_balance_hagar_primary_damageforcescale 0 -set g_balance_hagar_primary_radius 65 -set g_balance_hagar_primary_spread 0.03 -set g_balance_hagar_primary_speed 2500 -set g_balance_hagar_primary_lifetime 5 -set g_balance_hagar_primary_refire 0.16667 // 6 rockets per second -set g_balance_hagar_primary_ammo 1 -set g_balance_hagar_secondary 1 -set g_balance_hagar_secondary_load 1 -set g_balance_hagar_secondary_load_speed 0.5 -set g_balance_hagar_secondary_load_spread 0.075 -set g_balance_hagar_secondary_load_spread_bias 0.5 -set g_balance_hagar_secondary_load_max 4 -set g_balance_hagar_secondary_load_hold 4 -set g_balance_hagar_secondary_load_releasedeath 0 -set g_balance_hagar_secondary_load_abort 0 -set g_balance_hagar_secondary_load_linkexplode 0 -set g_balance_hagar_secondary_load_animtime 0.2 -set g_balance_hagar_secondary_damage 40 -set g_balance_hagar_secondary_edgedamage 20 -set g_balance_hagar_secondary_force 75 -set g_balance_hagar_secondary_health 15 -set g_balance_hagar_secondary_damageforcescale 0 -set g_balance_hagar_secondary_radius 80 -set g_balance_hagar_secondary_spread 0.05 -set g_balance_hagar_secondary_speed 2000 -set g_balance_hagar_secondary_lifetime_min 10 -set g_balance_hagar_secondary_lifetime_rand 0 -set g_balance_hagar_secondary_refire 0.5 -set g_balance_hagar_secondary_ammo 1 -set g_balance_hagar_switchdelay_drop 0.2 -set g_balance_hagar_switchdelay_raise 0.2 -set g_balance_hagar_reload_ammo 0 //default: 25 -set g_balance_hagar_reload_time 2 -// }}} -// {{{ rocketlauncher -set g_balance_rocketlauncher_damage 70 -set g_balance_rocketlauncher_edgedamage 35 -set g_balance_rocketlauncher_force 450 -set g_balance_rocketlauncher_radius 110 -set g_balance_rocketlauncher_speed 1300 -set g_balance_rocketlauncher_speedaccel 1300 -set g_balance_rocketlauncher_speedstart 1000 -set g_balance_rocketlauncher_lifetime 10 -set g_balance_rocketlauncher_refire 1.2 -set g_balance_rocketlauncher_animtime 0.4 -set g_balance_rocketlauncher_ammo 4 -set g_balance_rocketlauncher_health 30 // 30 // 5 hitpoints above maximum laser value -- this way lasers can't blow it up, but grenadelauncher still can most the time. -set g_balance_rocketlauncher_damageforcescale 1 // low damage force scale so that it can still be affected by other hits, but not so much that it does a 90 degree turn -set g_balance_rocketlauncher_detonatedelay 0.02 // 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 70 // 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.2 // delay before guiding kicks in -set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again -set g_balance_rocketlauncher_remote_damage 70 -set g_balance_rocketlauncher_remote_edgedamage 35 -set g_balance_rocketlauncher_remote_radius 110 -set g_balance_rocketlauncher_remote_force 400 -set g_balance_rocketlauncher_switchdelay_drop 0.3 -set g_balance_rocketlauncher_switchdelay_raise 0.2 -set g_balance_rocketlauncher_reload_ammo 0 //default: 25 -set g_balance_rocketlauncher_reload_time 2 -// }}} -// {{{ porto -set g_balance_porto_primary_refire 1.5 -set g_balance_porto_primary_animtime 0.3 -set g_balance_porto_primary_speed 1000 -set g_balance_porto_primary_lifetime 5 -set g_balance_porto_secondary 1 -set g_balance_porto_secondary_refire 1.5 -set g_balance_porto_secondary_animtime 0.3 -set g_balance_porto_secondary_speed 1000 -set g_balance_porto_secondary_lifetime 5 -set g_balance_porto_switchdelay_drop 0.2 -set g_balance_porto_switchdelay_raise 0.2 -set g_balance_portal_health 200 // these get recharged whenever the portal is used -set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used -// }}} -// {{{ hook -set g_balance_hook_primary_fuel 5 // hook monkeys set 0 -set g_balance_hook_primary_refire 0.2 // hook monkeys set 0 -set g_balance_hook_primary_animtime 0.3 // good shoot anim -set g_balance_hook_primary_hooked_time_max 0 // infinite -set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free -set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked -set g_balance_hook_secondary_damage 25 // not much -set g_balance_hook_secondary_edgedamage 5 // not much -set g_balance_hook_secondary_radius 500 // LOTS -set g_balance_hook_secondary_force -2000 // LOTS -set g_balance_hook_secondary_ammo 30 // a whole pack -set g_balance_hook_secondary_lifetime 5 // infinite -set g_balance_hook_secondary_speed 0 // not much throwing -set g_balance_hook_secondary_gravity 5 // fast falling -set g_balance_hook_secondary_refire 3 // don't drop too many bombs... -set g_balance_hook_secondary_animtime 0.3 // good shoot anim -set g_balance_hook_secondary_power 3 // effect behaves like a square function -set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds -set g_balance_hook_secondary_health 15 -set g_balance_hook_secondary_damageforcescale 0 -set g_balance_hook_switchdelay_drop 0.2 -set g_balance_hook_switchdelay_raise 0.2 -// }}} -// {{{ tuba -set g_balance_tuba_refire 0.05 -set g_balance_tuba_animtime 0.05 -set g_balance_tuba_attenuation 0.5 -set g_balance_tuba_volume 1 -set g_balance_tuba_fadetime 0.25 -set g_balance_tuba_damage 5 -set g_balance_tuba_edgedamage 0 -set g_balance_tuba_radius 200 -set g_balance_tuba_force 40 -set g_balance_tuba_pitchstep 6 -set g_balance_tuba_switchdelay_drop 0.2 -set g_balance_tuba_switchdelay_raise 0.2 -// }}} -// {{{ fireball // this is a superweapon -- lets make it behave as one. -set g_balance_fireball_primary_animtime 0.2 -set g_balance_fireball_primary_bfgdamage 100 -set g_balance_fireball_primary_bfgforce 0 -set g_balance_fireball_primary_bfgradius 1000 -set g_balance_fireball_primary_damage 200 -set g_balance_fireball_primary_damageforcescale 0 -set g_balance_fireball_primary_edgedamage 50 -set g_balance_fireball_primary_force 600 -set g_balance_fireball_primary_health 0 -set g_balance_fireball_primary_laserburntime 0.5 -set g_balance_fireball_primary_laserdamage 80 -set g_balance_fireball_primary_laseredgedamage 20 -set g_balance_fireball_primary_laserradius 256 -set g_balance_fireball_primary_lifetime 15 -set g_balance_fireball_primary_radius 200 -set g_balance_fireball_primary_refire 2 -set g_balance_fireball_primary_refire2 0 -set g_balance_fireball_primary_speed 1200 -set g_balance_fireball_primary_spread 0 -set g_balance_fireball_secondary_animtime 0.3 -set g_balance_fireball_secondary_damage 40 -set g_balance_fireball_secondary_damageforcescale 4 -set g_balance_fireball_secondary_damagetime 5 -set g_balance_fireball_secondary_force 100 -set g_balance_fireball_secondary_laserburntime 0.5 -set g_balance_fireball_secondary_laserdamage 50 -set g_balance_fireball_secondary_laseredgedamage 20 -set g_balance_fireball_secondary_laserradius 110 -set g_balance_fireball_secondary_lifetime 7 -set g_balance_fireball_secondary_refire 1.5 -set g_balance_fireball_secondary_speed 900 -set g_balance_fireball_secondary_speed_up 100 -set g_balance_fireball_secondary_speed_z 0 -set g_balance_fireball_secondary_spread 0 -set g_balance_fireball_switchdelay_drop 0.2 -set g_balance_fireball_switchdelay_raise 0.2 -// }}} diff --git a/qcsrc/client/Defs.qc b/qcsrc/client/Defs.qc index 24a5fbfc0..b89a177f0 100644 --- a/qcsrc/client/Defs.qc +++ b/qcsrc/client/Defs.qc @@ -223,8 +223,8 @@ string shortmapname; float tempdb; float ClientProgsDB; vector hook_shotorigin[4]; -vector lightning_shotorigin[4]; - +vector electro_shotorigin[4]; +vector gauntlet_shotorigin[4]; #ifdef BLURTEST float blurtest_time0, blurtest_time1, blurtest_radius, blurtest_power; @@ -251,7 +251,7 @@ float w_deathtype, w_issilent, w_random; vector w_org, w_backoff; float rifle_scope; -float vortex_scope; +float nex_scope; float minelayer_maxmines; @@ -262,7 +262,7 @@ float bgmtime; string weaponorder_byimpulse; string weaponorder_bypriority; -float vortex_charge_movingavg; +float nex_charge_movingavg; float serverflags; diff --git a/qcsrc/client/Main.qc b/qcsrc/client/Main.qc index 7d85532ba..c0e37ae62 100644 --- a/qcsrc/client/Main.qc +++ b/qcsrc/client/Main.qc @@ -125,6 +125,7 @@ void CSQC_Init(void) Hook_Precache(); GibSplash_Precache(); Casings_Precache(); + DamageInfo_Precache(); Vehicles_Precache(); turrets_precache(); Tuba_Precache(); @@ -132,8 +133,8 @@ void CSQC_Init(void) if(autocvar_cl_reticle) { - precache_pic("gfx/reticle_normal"); - // weapon reticles are precached in weapon files + if(autocvar_cl_reticle_item_normal) { precache_pic("gfx/reticle_normal"); } + if(autocvar_cl_reticle_item_nex) { precache_pic("gfx/reticle_nex"); } } get_mi_min_max_texcoords(1); // try the CLEVER way first @@ -822,7 +823,8 @@ void CSQC_Ent_Update(float bIsNewEntity) case ENT_CLIENT_WARPZONE_TELEPORTED: WarpZone_Teleported_Read(bIsNewEntity); break; case ENT_CLIENT_TRIGGER_MUSIC: Ent_ReadTriggerMusic(); break; case ENT_CLIENT_HOOK: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_HOOK); break; - case ENT_CLIENT_ARC_BEAM: Ent_ReadArcBeam(bIsNewEntity); break; + case ENT_CLIENT_LGBEAM: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_LGBEAM); break; + case ENT_CLIENT_GAUNTLET: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_GAUNTLET); break; case ENT_CLIENT_ACCURACY: Ent_ReadAccuracy(); break; case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break; case ENT_CLIENT_TURRET: ent_turret(); break; @@ -962,10 +964,14 @@ void Ent_Init() hook_shotorigin[1] = decompressShotOrigin(ReadInt24_t()); hook_shotorigin[2] = decompressShotOrigin(ReadInt24_t()); hook_shotorigin[3] = decompressShotOrigin(ReadInt24_t()); - arc_shotorigin[0] = decompressShotOrigin(ReadInt24_t()); - arc_shotorigin[1] = decompressShotOrigin(ReadInt24_t()); - arc_shotorigin[2] = decompressShotOrigin(ReadInt24_t()); - arc_shotorigin[3] = decompressShotOrigin(ReadInt24_t()); + electro_shotorigin[0] = decompressShotOrigin(ReadInt24_t()); + electro_shotorigin[1] = decompressShotOrigin(ReadInt24_t()); + electro_shotorigin[2] = decompressShotOrigin(ReadInt24_t()); + electro_shotorigin[3] = decompressShotOrigin(ReadInt24_t()); + gauntlet_shotorigin[0] = decompressShotOrigin(ReadInt24_t()); + gauntlet_shotorigin[1] = decompressShotOrigin(ReadInt24_t()); + gauntlet_shotorigin[2] = decompressShotOrigin(ReadInt24_t()); + gauntlet_shotorigin[3] = decompressShotOrigin(ReadInt24_t()); if(forcefog) strunzone(forcefog); @@ -978,7 +984,7 @@ void Ent_Init() g_balance_electro_secondary_bouncefactor = ReadCoord(); g_balance_electro_secondary_bouncestop = ReadCoord(); - vortex_scope = !ReadByte(); + nex_scope = !ReadByte(); rifle_scope = !ReadByte(); serverflags = ReadByte(); @@ -1175,7 +1181,7 @@ void Net_WeaponComplain() if(complain_weapon_name) strunzone(complain_weapon_name); - complain_weapon_name = strzone(WEP_NAME(complain_weapon)); + complain_weapon_name = strzone(ReadString()); complain_weapon_type = ReadByte(); @@ -1219,16 +1225,16 @@ float CSQC_Parse_TempEntity() Net_ReadRace(); bHandled = true; break; - case TE_CSQC_VORTEXBEAMPARTICLE: - Net_ReadVortexBeamParticle(); + case TE_CSQC_NEXGUNBEAMPARTICLE: + Net_ReadNexgunBeamParticle(); bHandled = true; break; case TE_CSQC_TEAMNAGGER: Net_TeamNagger(); bHandled = true; break; - case TE_CSQC_ARC: - Net_ReadArc(); + case TE_CSQC_LIGHTNINGARC: + Net_ReadLightningarc(); bHandled = true; break; case TE_CSQC_PINGPLREPORT: @@ -1247,10 +1253,6 @@ float CSQC_Parse_TempEntity() cl_notice_read(); bHandled = true; break; - case TE_CSQC_SHOCKWAVEPARTICLE: - Net_ReadShockwaveParticle(); - bHandled = true; - break; default: // No special logic for this temporary entity; return 0 so the engine can handle it bHandled = false; diff --git a/qcsrc/client/View.qc b/qcsrc/client/View.qc index f68ea32e5..a069faa46 100644 --- a/qcsrc/client/View.qc +++ b/qcsrc/client/View.qc @@ -104,7 +104,7 @@ vector GetCurrentFov(float fov) zoomdir = button_zoom; if(hud == HUD_NORMAL) - if((activeweapon == WEP_VORTEX && vortex_scope) || (activeweapon == WEP_RIFLE && rifle_scope)) // do NOT use switchweapon here + if((activeweapon == WEP_NEX && nex_scope) || (activeweapon == WEP_RIFLE && rifle_scope)) // do NOT use switchweapon here zoomdir += button_attack2; if(spectatee_status > 0 || isdemo()) { @@ -269,7 +269,7 @@ float EnemyHitCheck() float TrueAimCheck() { - float nudge = 1; // added to traceline target and subtracted from result TOOD(divVerent): do we still need this? Doesn't the engine do this now for us? + float nudge = 1; // added to traceline target and subtracted from result vector vecs, trueaimpoint, w_shotorg; vector mi, ma, dv; float shottype; @@ -280,15 +280,15 @@ float TrueAimCheck() ta = trueaim; mv = MOVE_NOMONSTERS; - switch(activeweapon) // WEAPONTODO + switch(activeweapon) { case WEP_TUBA: // no aim case WEP_PORTO: // shoots from eye case WEP_HOOK: // no trueaim - case WEP_MORTAR: // toss curve + case WEP_GRENADE_LAUNCHER: // toss curve return SHOTTYPE_HITWORLD; - case WEP_VORTEX: - case WEP_VAPORIZER: + case WEP_NEX: + case WEP_MINSTANEX: mv = MOVE_NORMAL; break; case WEP_RIFLE: @@ -300,7 +300,7 @@ float TrueAimCheck() return EnemyHitCheck(); } break; - case WEP_DEVASTATOR: // projectile has a size! + case WEP_ROCKET_LAUNCHER: // projectile has a size! mi = '-3 -3 -3'; ma = '3 3 3'; break; @@ -365,7 +365,6 @@ float camera_mode; const float CAMERA_FREE = 1; const float CAMERA_CHASE = 2; float reticle_type; -string reticle_image; string NextFrameCommand; void CSQC_SPIDER_HUD(); void CSQC_RAPTOR_HUD(); @@ -378,7 +377,7 @@ float pickup_crosshair_time, pickup_crosshair_size; float hit_time, typehit_time; float nextsound_hit_time, nextsound_typehit_time; float hitindication_crosshair_time, hitindication_crosshair_size; -float use_vortex_chargepool; +float use_nex_chargepool; float myhealth, myhealth_prev; float myhealth_flash; @@ -868,64 +867,50 @@ void CSQC_UpdateView(float w, float h) R_EndPolygon(); } - if(autocvar_cl_reticle) + // Draw the aiming reticle for weapons that use it + // reticle_type is changed to the item we are zooming / aiming with, to decide which reticle to use + // It must be a persisted float for fading out to work properly (you let go of the zoom button for + // the view to go back to normal, so reticle_type would become 0 as we fade out) + if(spectatee_status || is_dead || hud != HUD_NORMAL) + reticle_type = 0; // prevent reticle from showing during the respawn zoom effect or for spectators + else if((activeweapon == WEP_NEX || activeweapon == WEP_RIFLE || activeweapon == WEP_MINSTANEX) && (button_zoom || zoomscript_caught)) + reticle_type = 2; // nex zoom + else if(button_zoom || zoomscript_caught) + reticle_type = 1; // normal zoom + else if((activeweapon == WEP_NEX) && button_attack2) + reticle_type = 2; // nex zoom + + if(reticle_type && autocvar_cl_reticle) { - // Draw the aiming reticle for weapons that use it - // reticle_type is changed to the item we are zooming / aiming with, to decide which reticle to use - // It must be a persisted float for fading out to work properly (you let go of the zoom button for - // the view to go back to normal, so reticle_type would become 0 as we fade out) - if(spectatee_status || is_dead || hud != HUD_NORMAL) + if(autocvar_cl_reticle_stretch) { - // no zoom reticle while dead - reticle_type = 0; + reticle_size_x = vid_conwidth; + reticle_size_y = vid_conheight; + reticle_pos_x = 0; + reticle_pos_y = 0; } - else if(WEP_ACTION(activeweapon, WR_ZOOMRETICLE) && autocvar_cl_reticle_weapon) + else { - if(reticle_image != "") { reticle_type = 2; } - else { reticle_type = 0; } + reticle_size_x = max(vid_conwidth, vid_conheight); + reticle_size_y = max(vid_conwidth, vid_conheight); + reticle_pos_x = (vid_conwidth - reticle_size_x) / 2; + reticle_pos_y = (vid_conheight - reticle_size_y) / 2; } - else if(button_zoom || zoomscript_caught) + + f = current_zoomfraction; + if(zoomscript_caught) + f = 1; + if(autocvar_cl_reticle_item_normal) { - // normal zoom - reticle_type = 1; + if(reticle_type == 1 && f) + drawpic(reticle_pos, "gfx/reticle_normal", reticle_size, '1 1 1', f * autocvar_cl_reticle_item_normal, DRAWFLAG_NORMAL); } - - if(reticle_type) + if(autocvar_cl_reticle_item_nex) { - if(autocvar_cl_reticle_stretch) - { - reticle_size_x = vid_conwidth; - reticle_size_y = vid_conheight; - reticle_pos_x = 0; - reticle_pos_y = 0; - } - else - { - reticle_size_x = max(vid_conwidth, vid_conheight); - reticle_size_y = max(vid_conwidth, vid_conheight); - reticle_pos_x = (vid_conwidth - reticle_size_x) / 2; - reticle_pos_y = (vid_conheight - reticle_size_y) / 2; - } - - if(zoomscript_caught) - f = 1; - else - f = current_zoomfraction; - - if(f) - { - switch(reticle_type) - { - case 1: drawpic(reticle_pos, "gfx/reticle_normal", reticle_size, '1 1 1', f * autocvar_cl_reticle_normal_alpha, DRAWFLAG_NORMAL); break; - case 2: drawpic(reticle_pos, reticle_image, reticle_size, '1 1 1', f * autocvar_cl_reticle_weapon_alpha, DRAWFLAG_NORMAL); break; - } - } + if(reticle_type == 2 && f) + drawpic(reticle_pos, "gfx/reticle_nex", reticle_size, '1 1 1', f * autocvar_cl_reticle_item_nex, DRAWFLAG_NORMAL); } } - else - { - if(reticle_type != 0) { reticle_type = 0; } - } // improved polyblend @@ -1234,39 +1219,42 @@ void CSQC_UpdateView(float w, float h) shottype = SHOTTYPE_HITWORLD; vector wcross_color = '0 0 0', wcross_size = '0 0 0'; - string wcross_name = ""; + string wcross_wep = "", wcross_name; float wcross_scale, wcross_blur; - if(autocvar_crosshair_per_weapon || (autocvar_crosshair_color_special == 1)) + if (autocvar_crosshair_per_weapon || (autocvar_crosshair_color_special == 1)) { e = get_weaponinfo(switchingweapon); - if(e) + if (e && e.netname != "") { + wcross_wep = e.netname; if(autocvar_crosshair_per_weapon) { - // WEAPONTODO: access these through some general settings (with non-balance config settings) - //wcross_resolution *= cvar(strcat("crosshair_", wcross_wep, "_size")); - //if (wcross_resolution == 0) - //return; - - //wcross_style = cvar_string(strcat("crosshair_", wcross_wep)); - wcross_resolution *= e.w_crosshair_size; - wcross_name = e.w_crosshair; + wcross_resolution *= cvar(strcat("crosshair_", wcross_wep, "_size")); + if (wcross_resolution == 0) + return; + wcross_alpha *= cvar(strcat("crosshair_", wcross_wep, "_alpha")); + if (wcross_alpha == 0) + return; + + wcross_style = cvar_string(strcat("crosshair_", wcross_wep)); + if(wcross_style == "" || wcross_style == "0") + wcross_style = wcross_wep; } } } - if(wcross_name == "") - wcross_name = strcat("gfx/crosshair", wcross_style); + //printf("crosshair style: %s\n", wcross_style); + wcross_name = strcat("gfx/crosshair", wcross_style); // MAIN CROSSHAIR COLOR DECISION switch(autocvar_crosshair_color_special) { case 1: // crosshair_color_per_weapon { - if(e) + if(wcross_wep != "") { - wcross_color = e.wpcolor; + wcross_color = stov(cvar_string(sprintf("crosshair_%s_color", wcross_wep))); break; } else { goto normalcolor; } @@ -1454,32 +1442,32 @@ void CSQC_UpdateView(float w, float h) weapon_clipload = getstati(STAT_WEAPON_CLIPLOAD); weapon_clipsize = getstati(STAT_WEAPON_CLIPSIZE); - float vortex_charge, vortex_chargepool; - vortex_charge = getstatf(STAT_VORTEX_CHARGE); - vortex_chargepool = getstatf(STAT_VORTEX_CHARGEPOOL); + float nex_charge, nex_chargepool; + nex_charge = getstatf(STAT_NEX_CHARGE); + nex_chargepool = getstatf(STAT_NEX_CHARGEPOOL); - if(vortex_charge_movingavg == 0) // this should only happen if we have just loaded up the game - vortex_charge_movingavg = vortex_charge; + if(nex_charge_movingavg == 0) // this should only happen if we have just loaded up the game + nex_charge_movingavg = nex_charge; // handle the values - if (autocvar_crosshair_ring && activeweapon == WEP_VORTEX && vortex_charge && autocvar_crosshair_ring_vortex) // ring around crosshair representing velocity-dependent damage for the vortex + if (autocvar_crosshair_ring && activeweapon == WEP_NEX && nex_charge && autocvar_crosshair_ring_nex) // ring around crosshair representing velocity-dependent damage for the nex { - if (vortex_chargepool || use_vortex_chargepool) { - use_vortex_chargepool = 1; - ring_inner_value = vortex_chargepool; + if (nex_chargepool || use_nex_chargepool) { + use_nex_chargepool = 1; + ring_inner_value = nex_chargepool; } else { - vortex_charge_movingavg = (1 - autocvar_crosshair_ring_vortex_currentcharge_movingavg_rate) * vortex_charge_movingavg + autocvar_crosshair_ring_vortex_currentcharge_movingavg_rate * vortex_charge; - ring_inner_value = bound(0, autocvar_crosshair_ring_vortex_currentcharge_scale * (vortex_charge - vortex_charge_movingavg), 1); + nex_charge_movingavg = (1 - autocvar_crosshair_ring_nex_currentcharge_movingavg_rate) * nex_charge_movingavg + autocvar_crosshair_ring_nex_currentcharge_movingavg_rate * nex_charge; + ring_inner_value = bound(0, autocvar_crosshair_ring_nex_currentcharge_scale * (nex_charge - nex_charge_movingavg), 1); } - ring_inner_alpha = autocvar_crosshair_ring_vortex_inner_alpha; - ring_inner_rgb = eX * autocvar_crosshair_ring_vortex_inner_color_red + eY * autocvar_crosshair_ring_vortex_inner_color_green + eZ * autocvar_crosshair_ring_vortex_inner_color_blue; + ring_inner_alpha = autocvar_crosshair_ring_nex_inner_alpha; + ring_inner_rgb = eX * autocvar_crosshair_ring_nex_inner_color_red + eY * autocvar_crosshair_ring_nex_inner_color_green + eZ * autocvar_crosshair_ring_nex_inner_color_blue; ring_inner_image = "gfx/crosshair_ring_inner.tga"; // draw the outer ring to show the current charge of the weapon - ring_value = vortex_charge; - ring_alpha = autocvar_crosshair_ring_vortex_alpha; + ring_value = nex_charge; + ring_alpha = autocvar_crosshair_ring_nex_alpha; ring_rgb = wcross_color; ring_image = "gfx/crosshair_ring_nexgun.tga"; } diff --git a/qcsrc/client/autocvars.qh b/qcsrc/client/autocvars.qh index e33ea8081..28ef157e5 100644 --- a/qcsrc/client/autocvars.qh +++ b/qcsrc/client/autocvars.qh @@ -62,9 +62,8 @@ float autocvar_cl_particles_quality; float autocvar_cl_projectiles_sloppy; float autocvar_cl_readpicture_force; var float autocvar_cl_reticle = 1; -var float autocvar_cl_reticle_normal_alpha = 1; -var float autocvar_cl_reticle_weapon = 1; -var float autocvar_cl_reticle_weapon_alpha = 1; +float autocvar_cl_reticle_item_nex; +float autocvar_cl_reticle_item_normal; float autocvar_cl_reticle_stretch; float autocvar_cl_spawn_event_particles; var float autocvar_cl_spawn_event_sound = 1; @@ -126,14 +125,14 @@ float autocvar_crosshair_ring_minelayer; float autocvar_crosshair_ring_minelayer_alpha; float autocvar_crosshair_ring_hagar; float autocvar_crosshair_ring_hagar_alpha; -float autocvar_crosshair_ring_vortex; -float autocvar_crosshair_ring_vortex_alpha; -float autocvar_crosshair_ring_vortex_currentcharge_movingavg_rate; -float autocvar_crosshair_ring_vortex_currentcharge_scale; -float autocvar_crosshair_ring_vortex_inner_alpha; -float autocvar_crosshair_ring_vortex_inner_color_blue; -float autocvar_crosshair_ring_vortex_inner_color_green; -float autocvar_crosshair_ring_vortex_inner_color_red; +float autocvar_crosshair_ring_nex; +float autocvar_crosshair_ring_nex_alpha; +float autocvar_crosshair_ring_nex_currentcharge_movingavg_rate; +float autocvar_crosshair_ring_nex_currentcharge_scale; +float autocvar_crosshair_ring_nex_inner_alpha; +float autocvar_crosshair_ring_nex_inner_color_blue; +float autocvar_crosshair_ring_nex_inner_color_green; +float autocvar_crosshair_ring_nex_inner_color_red; float autocvar_crosshair_ring_size; float autocvar_crosshair_ring_reload; float autocvar_crosshair_ring_reload_alpha; @@ -325,7 +324,6 @@ float autocvar_hud_panel_weapons_ammo; float autocvar_hud_panel_weapons_ammo_alpha; string autocvar_hud_panel_weapons_ammo_color; float autocvar_hud_panel_weapons_ammo_full_cells; -float autocvar_hud_panel_weapons_ammo_full_plasma; float autocvar_hud_panel_weapons_ammo_full_fuel; float autocvar_hud_panel_weapons_ammo_full_nails; float autocvar_hud_panel_weapons_ammo_full_rockets; diff --git a/qcsrc/client/csqcmodel_hooks.qc b/qcsrc/client/csqcmodel_hooks.qc index 077b7d972..120b6658d 100644 --- a/qcsrc/client/csqcmodel_hooks.qc +++ b/qcsrc/client/csqcmodel_hooks.qc @@ -470,14 +470,8 @@ void CSQCModel_Effects_PreUpdate(void) self.effects = self.csqcmodel_effects; self.modelflags = self.csqcmodel_modelflags; } -void Reset_ArcBeam(void); void CSQCModel_Effects_PostUpdate(void) { - if (self == csqcplayer) { - if (self.csqcmodel_teleported) { - Reset_ArcBeam(); - } - } self.csqcmodel_effects = self.effects; self.csqcmodel_modelflags = self.modelflags; self.effects = 0; diff --git a/qcsrc/client/damage.qc b/qcsrc/client/damage.qc index 32849c2ac..cc3653db4 100644 --- a/qcsrc/client/damage.qc +++ b/qcsrc/client/damage.qc @@ -80,22 +80,27 @@ void DamageEffect(vector hitorg, float dmg, float type, float specnum) } life = bound(autocvar_cl_damageeffect_lifetime_min, dmg * autocvar_cl_damageeffect_lifetime, autocvar_cl_damageeffect_lifetime_max); + specstr = species_prefix(specnum); + type = DEATH_WEAPONOF(type); + e = get_weaponinfo(type); - effectname = get_weaponinfo(DEATH_WEAPONOF(type)).netname; + effectname = strcat("damage_", e.netname); - if(substring(effectname, strlen(effectname) - 5, 5) == "BLOOD") + // if damage was dealt with a bullet weapon, our effect is blood + // since blood is species dependent, include the species tag + if(type == WEP_SHOTGUN || type == WEP_UZI || type == WEP_RIFLE) { if(self.isplayermodel) { - specstr = species_prefix(specnum); - specstr = substring(specstr, 0, strlen(specstr) - 1); - effectname = strreplace("BLOOD", specstr, effectname); + effectname = strcat(effectname, "_", specstr); + effectname = substring(effectname, 0, strlen(effectname) - 1); // remove the _ symbol at the end of the species tag } - else { return; } // objects don't bleed + else + return; // objects don't bleed } e = spawn(); - setmodel(e, "null"); // necessary to attach and read origin + setmodel(e, "null"); // necessary to attach and read origin // samual: FIXME: this is weird, is there some better way to do this? setattachment(e, self, gettaginfo_name); // attach to the given bone e.classname = "damage"; e.owner = self; @@ -339,12 +344,19 @@ void Ent_DamageInfo(float isNew) w_random = prandom(); traceline(w_org - normalize(force) * 16, w_org + normalize(force) * 16, MOVE_NOMONSTERS, world); - if(trace_fraction < 1 && hitwep != WEP_VORTEX && hitwep != WEP_VAPORIZER) + if(trace_fraction < 1 && hitwep != WEP_NEX && hitwep != WEP_MINSTANEX) w_backoff = trace_plane_normal; else w_backoff = -1 * normalize(force); setorigin(self, w_org + w_backoff * 2); // for sound() calls - WEP_ACTION(hitwep, WR_IMPACTEFFECT); + (get_weaponinfo(hitwep)).weapon_func(WR_IMPACTEFFECT); } } + +void DamageInfo_Precache() +{ + float i; + for(i = WEP_FIRST; i <= WEP_LAST; ++i) + (get_weaponinfo(i)).weapon_func(WR_PRECACHE); +} diff --git a/qcsrc/client/effects.qc b/qcsrc/client/effects.qc index c35a3a94a..8c237aade 100644 --- a/qcsrc/client/effects.qc +++ b/qcsrc/client/effects.qc @@ -95,4 +95,3 @@ void Net_ReadLightningarc() } } -void Net_ReadArc() { Net_ReadLightningarc(); } diff --git a/qcsrc/client/hook.qc b/qcsrc/client/hook.qc index 8b2ffca19..889e75d26 100644 --- a/qcsrc/client/hook.qc +++ b/qcsrc/client/hook.qc @@ -75,8 +75,11 @@ void Draw_GrapplingHook() case ENT_CLIENT_HOOK: vs = hook_shotorigin[s]; break; - case ENT_CLIENT_ARC_BEAM: - vs = lightning_shotorigin[s]; + case ENT_CLIENT_LGBEAM: + vs = electro_shotorigin[s]; + break; + case ENT_CLIENT_GAUNTLET: + vs = gauntlet_shotorigin[s]; break; } @@ -89,7 +92,8 @@ void Draw_GrapplingHook() a = view_origin + view_forward * vs_x + view_right * -vs_y + view_up * vs_z; b = self.origin; break; - case ENT_CLIENT_ARC_BEAM: + case ENT_CLIENT_LGBEAM: + case ENT_CLIENT_GAUNTLET: if(self.HookRange) b = view_origin + view_forward * self.HookRange; else @@ -109,7 +113,8 @@ void Draw_GrapplingHook() a = self.velocity; b = self.origin; break; - case ENT_CLIENT_ARC_BEAM: + case ENT_CLIENT_LGBEAM: + case ENT_CLIENT_GAUNTLET: a = self.origin; b = self.velocity; break; @@ -133,12 +138,18 @@ void Draw_GrapplingHook() default: tex = "particles/hook_white"; rgb = getcsqcplayercolor(self.sv_entnum); break; } break; - case ENT_CLIENT_ARC_BEAM: // todo + case ENT_CLIENT_LGBEAM: intensity = bound(0.2, 1 + Noise_Pink(self, frametime) * 1 + Noise_Burst(self, frametime, 0.03) * 0.3, 2); offset = Noise_Brown(self, frametime) * 10; tex = "particles/lgbeam"; rgb = '1 1 1'; break; + case ENT_CLIENT_GAUNTLET: + intensity = 1; + offset = Noise_White(self, frametime); + tex = "particles/gauntletbeam"; + rgb = '1 1 1'; + break; } Draw_GrapplingHook_trace_callback_tex = tex; @@ -165,7 +176,8 @@ void Draw_GrapplingHook() self.drawmask = 0; } break; - case ENT_CLIENT_ARC_BEAM: + case ENT_CLIENT_LGBEAM: + case ENT_CLIENT_GAUNTLET: setorigin(self, a); // beam origin! break; } @@ -175,8 +187,11 @@ void Draw_GrapplingHook() default: case ENT_CLIENT_HOOK: break; - case ENT_CLIENT_ARC_BEAM: - pointparticles(particleeffectnum("electro_lightning"), trace_endpos, normalize(atrans - trace_endpos), frametime * intensity); // todo: new effect + case ENT_CLIENT_LGBEAM: + pointparticles(particleeffectnum("electro_lightning"), trace_endpos, normalize(atrans - trace_endpos), frametime * intensity); + break; + case ENT_CLIENT_GAUNTLET: + pointparticles(particleeffectnum("gauntlet_lightning"), b, normalize(a - b), frametime * intensity); break; } } @@ -207,9 +222,10 @@ void Ent_ReadHook(float bIsNew, float type) { default: case ENT_CLIENT_HOOK: + case ENT_CLIENT_GAUNTLET: self.HookRange = 0; break; - case ENT_CLIENT_ARC_BEAM: + case ENT_CLIENT_LGBEAM: self.HookRange = ReadCoord(); break; } @@ -243,9 +259,12 @@ void Ent_ReadHook(float bIsNew, float type) setmodel(self, "models/hook.md3"); self.drawmask = MASK_NORMAL; break; - case ENT_CLIENT_ARC_BEAM: + case ENT_CLIENT_LGBEAM: sound (self, CH_SHOTS_SINGLE, "weapons/lgbeam_fly.wav", VOL_BASE, ATTEN_NORM); break; + case ENT_CLIENT_GAUNTLET: + sound (self, CH_SHOTS_SINGLE, "weapons/gauntletbeam_fly.wav", VOL_BASE, ATTEN_NORM); + break; } } @@ -255,6 +274,7 @@ void Ent_ReadHook(float bIsNew, float type) void Hook_Precache() { precache_sound("weapons/lgbeam_fly.wav"); + precache_sound("weapons/gauntletbeam_fly.wav"); precache_model("models/hook.md3"); } diff --git a/qcsrc/client/hud.qc b/qcsrc/client/hud.qc index 701990d6b..ab61eb3c3 100644 --- a/qcsrc/client/hud.qc +++ b/qcsrc/client/hud.qc @@ -408,6 +408,42 @@ float weaponorder_cmp(float i, float j, entity pass) return aj - ai; // the string is in REVERSE order (higher prio at the right is what we want, but higher prio first is the string) } +float GetAmmoStat(float i) +{ + switch(i) + { + case 0: return STAT_SHELLS; + case 1: return STAT_NAILS; + case 2: return STAT_ROCKETS; + case 3: return STAT_CELLS; + case 4: return STAT_FUEL; + default: return -1; + } +} + +float GetAmmoTypeForWep(float i) +{ + switch(i) + { + case WEP_SHOTGUN: return 0; + case WEP_UZI: return 1; + case WEP_GRENADE_LAUNCHER: return 2; + case WEP_MINE_LAYER: return 2; + case WEP_ELECTRO: return 3; + case WEP_CRYLINK: return 3; + case WEP_HLAC: return 3; + case WEP_MINSTANEX: return 3; + case WEP_NEX: return 3; + case WEP_RIFLE: return 1; + case WEP_HAGAR: return 2; + case WEP_ROCKET_LAUNCHER: return 2; + case WEP_SEEKER: return 2; + case WEP_FIREBALL: return 4; + case WEP_HOOK: return 3; + default: return -1; + } +} + void HUD_Weapons(void) { // declarations @@ -424,7 +460,7 @@ void HUD_Weapons(void) float timein_effect_length = autocvar_hud_panel_weapons_timeout_speed_in; //? 0.375 : 0); float timeout_effect_length = autocvar_hud_panel_weapons_timeout_speed_out; //? 0.75 : 0); - float ammo_full; + float ammo_type, ammo_full; float barsize_x = 0, barsize_y = 0, baroffset_x = 0, baroffset_y = 0; vector ammo_color = '1 0 1'; float ammo_alpha = 1; @@ -728,7 +764,7 @@ void HUD_Weapons(void) if(weapons_stat & WepSet_FromWeapon(self.weapon)) { // draw the weapon image - drawpic_aspect_skin(weapon_pos, self.model2, weapon_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + drawpic_aspect_skin(weapon_pos, strcat("weapon", self.netname), weapon_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); // draw weapon label string switch(autocvar_hud_panel_weapons_label) @@ -742,7 +778,7 @@ void HUD_Weapons(void) break; case 3: // weapon name - drawstring(weapon_pos, strtolower(self.message), '1 1 0' * 0.5 * weapon_size_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); + drawstring(weapon_pos, self.netname, '1 1 0' * 0.5 * weapon_size_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); break; default: // nothing @@ -750,20 +786,21 @@ void HUD_Weapons(void) } // draw ammo status bar - if(autocvar_hud_panel_weapons_ammo && (self.ammo_field != ammo_none)) + if(autocvar_hud_panel_weapons_ammo && self.weapon != WEP_TUBA && self.weapon != WEP_LASER && self.weapon != WEP_PORTO) { - a = getstati(GetAmmoStat(self.ammo_field)); // how much ammo do we have? + a = 0; + ammo_type = GetAmmoTypeForWep(self.weapon); + if(ammo_type != -1) + a = getstati(GetAmmoStat(ammo_type)); // how much ammo do we have? if(a > 0) { - switch(self.ammo_field) - { - case ammo_shells: ammo_full = autocvar_hud_panel_weapons_ammo_full_shells; break; - case ammo_nails: ammo_full = autocvar_hud_panel_weapons_ammo_full_nails; break; - case ammo_rockets: ammo_full = autocvar_hud_panel_weapons_ammo_full_rockets; break; - case ammo_cells: ammo_full = autocvar_hud_panel_weapons_ammo_full_cells; break; - case ammo_plasma: ammo_full = autocvar_hud_panel_weapons_ammo_full_plasma; break; - case ammo_fuel: ammo_full = autocvar_hud_panel_weapons_ammo_full_fuel; break; + switch(ammo_type) { + case 0: ammo_full = autocvar_hud_panel_weapons_ammo_full_shells; break; + case 1: ammo_full = autocvar_hud_panel_weapons_ammo_full_nails; break; + case 2: ammo_full = autocvar_hud_panel_weapons_ammo_full_rockets; break; + case 3: ammo_full = autocvar_hud_panel_weapons_ammo_full_cells; break; + case 4: ammo_full = autocvar_hud_panel_weapons_ammo_full_fuel; break; default: ammo_full = 60; } @@ -771,25 +808,15 @@ void HUD_Weapons(void) weapon_pos_x + baroffset_x, weapon_pos_y + baroffset_y, barsize_x * bound(0, a/ammo_full, 1), - barsize_y - ); - - drawpic_aspect_skin( - weapon_pos, - "weapon_ammo", - weapon_size, - ammo_color, - ammo_alpha, - DRAWFLAG_NORMAL - ); - + barsize_y); + drawpic_aspect_skin(weapon_pos, "weapon_ammo", weapon_size, ammo_color, ammo_alpha, DRAWFLAG_NORMAL); drawresetcliparea(); } } } else // draw a "ghost weapon icon" if you don't have the weapon { - drawpic_aspect_skin(weapon_pos, self.model2, weapon_size, '0 0 0', panel_fg_alpha * 0.5, DRAWFLAG_NORMAL); + drawpic_aspect_skin(weapon_pos, strcat("weapon", self.netname), weapon_size, '0 0 0', panel_fg_alpha * 0.5, DRAWFLAG_NORMAL); } // draw the complain message @@ -831,6 +858,34 @@ void HUD_Weapons(void) } // Ammo (#1) +// +// TODO: macro +float GetAmmoItemCode(float i) +{ + switch(i) + { + case 0: return IT_SHELLS; + case 1: return IT_NAILS; + case 2: return IT_ROCKETS; + case 3: return IT_CELLS; + case 4: return IT_FUEL; + default: return -1; + } +} + +string GetAmmoPicture(float i) +{ + switch(i) + { + case 0: return "ammo_shells"; + case 1: return "ammo_bullets"; + case 2: return "ammo_rockets"; + case 3: return "ammo_cells"; + case 4: return "ammo_fuel"; + default: return ""; + } +} + void DrawNadeScoreBar(vector myPos, vector mySize, vector color) { @@ -879,30 +934,16 @@ void DrawAmmoNades(vector myPos, vector mySize, float draw_expanding, float expa } } -void DrawAmmoItem(vector myPos, vector mySize, .float ammotype, float currently_selected, float infinite_ammo) +void DrawAmmoItem(vector myPos, vector mySize, float itemcode, float currently_selected, float infinite_ammo) { - float a = 0; - if(ammotype != ammo_none) + float a; + if(autocvar__hud_configure) { - if(autocvar__hud_configure) - { - currently_selected = (ammotype == ammo_rockets); //rockets always selected - a = 60; - } - else - { - // how much ammo do we have of this ammotype? - a = getstati(GetAmmoStat(ammotype)); - } + currently_selected = (itemcode == 2); //rockets always selected + a = 31 + mod(itemcode*93, 128); } else - { - #if 0 - infinite_ammo = TRUE; - #else - return; // just don't draw infinite ammo at all. - #endif - } + a = getstati(GetAmmoStat(itemcode)); // how much ammo do we have of type itemcode? vector color; if(infinite_ammo) @@ -930,7 +971,7 @@ void DrawAmmoItem(vector myPos, vector mySize, .float ammotype, float currently_ picpos = myPos; } - if(currently_selected) + if (currently_selected) drawpic_aspect_skin(myPos, "ammo_current_bg", mySize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); if(a > 0 && autocvar_hud_panel_ammo_progressbar) @@ -944,9 +985,9 @@ void DrawAmmoItem(vector myPos, vector mySize, .float ammotype, float currently_ drawstring_aspect(numpos, ftos(a), eX * (2/3) * mySize_x + eY * mySize_y, '0 0 0', panel_fg_alpha * theAlpha * 0.5, DRAWFLAG_NORMAL); } if(a > 0 || infinite_ammo) - drawpic_aspect_skin(picpos, GetAmmoPicture(ammotype), '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL); + drawpic_aspect_skin(picpos, GetAmmoPicture(itemcode), '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL); else // "ghost" ammo icon - drawpic_aspect_skin(picpos, GetAmmoPicture(ammotype), '1 1 0' * mySize_y, '0 0 0', panel_fg_alpha * theAlpha * 0.5, DRAWFLAG_NORMAL); + drawpic_aspect_skin(picpos, GetAmmoPicture(itemcode), '1 1 0' * mySize_y, '0 0 0', panel_fg_alpha * theAlpha * 0.5, DRAWFLAG_NORMAL); } float nade_prevstatus; @@ -982,6 +1023,7 @@ void HUD_Ammo(void) float total_ammo_count; vector ammo_size; + float AMMO_COUNT = 4; if (autocvar_hud_panel_ammo_onlycurrent) total_ammo_count = 1; else @@ -1026,24 +1068,31 @@ void HUD_Ammo(void) ammo_size_y = newSize; } - float i; - float infinite_ammo = (getstati(STAT_ITEMS, 0, 24) & IT_UNLIMITED_WEAPON_AMMO); + float i, stat_items, currently_selected, infinite_ammo; + infinite_ammo = FALSE; + row = column = 0; - if(autocvar_hud_panel_ammo_onlycurrent) + + if (autocvar_hud_panel_ammo_onlycurrent) { if(autocvar__hud_configure) { - DrawAmmoItem(pos, ammo_size, ammo_rockets, TRUE, FALSE); + DrawAmmoItem(pos, ammo_size, 2, true, FALSE); //show rockets } else { - DrawAmmoItem( - pos, - ammo_size, - (get_weaponinfo(switchweapon)).ammo_field, - TRUE, - infinite_ammo - ); + stat_items = getstati(STAT_ITEMS, 0, 24); + if (stat_items & IT_UNLIMITED_WEAPON_AMMO) + infinite_ammo = TRUE; + for (i = 0; i < AMMO_COUNT; ++i) { + currently_selected = stat_items & GetAmmoItemCode(i); + if (currently_selected) + { + DrawAmmoItem(pos, ammo_size, i, true, infinite_ammo); + break; + } + } + } ++row; if(row >= rows) @@ -1051,23 +1100,15 @@ void HUD_Ammo(void) row = 0; column = column + 1; } - } } else { - .float ammotype; - row = column = 0; - for(i = 0; i < AMMO_COUNT; ++i) - { - ammotype = GetAmmoFieldFromNum(i); - DrawAmmoItem( - pos + eX * column * (ammo_size_x + offset_x) + eY * row * (ammo_size_y + offset_y), - ammo_size, - ammotype, - ((get_weaponinfo(switchweapon)).ammo_field == ammotype), - infinite_ammo - ); - + stat_items = getstati(STAT_ITEMS, 0, 24); + if (stat_items & IT_UNLIMITED_WEAPON_AMMO) + infinite_ammo = TRUE; + for (i = 0; i < AMMO_COUNT; ++i) { + currently_selected = stat_items & GetAmmoItemCode(i); + DrawAmmoItem(pos + eX * column * (ammo_size_x + offset_x) + eY * row * (ammo_size_y + offset_y), ammo_size, i, currently_selected, infinite_ammo); ++row; if(row >= rows) { @@ -1750,7 +1791,7 @@ void HUD_Notify(void) { attacker = sprintf(_("Player %d"), count + 1); victim = sprintf(_("Player %d"), count + 2); - icon = get_weaponinfo(min(WEP_FIRST + count * 2, WEP_LAST)).model2; + icon = strcat("weapon", get_weaponinfo(min(WEP_FIRST + count * 2, WEP_LAST)).netname); alpha = bound(0, 1.2 - count / entry_count, 1); } else diff --git a/qcsrc/client/particles.qc b/qcsrc/client/particles.qc index 6c5ceac7f..8751cc0c5 100644 --- a/qcsrc/client/particles.qc +++ b/qcsrc/client/particles.qc @@ -225,7 +225,7 @@ void Ent_RainOrSnow() self.draw = Draw_Snow; } -void Net_ReadVortexBeamParticle() +void Net_ReadNexgunBeamParticle() { vector shotorg, endpos; float charge; diff --git a/qcsrc/client/progs.src b/qcsrc/client/progs.src index 90f445c51..86a8b4339 100644 --- a/qcsrc/client/progs.src +++ b/qcsrc/client/progs.src @@ -21,7 +21,8 @@ Defs.qc ../common/buffs.qh ../common/test.qh ../common/counting.qh -../common/weapons/weapons.qh // TODO +../common/items.qh +../common/explosion_equation.qh ../common/mapinfo.qh ../common/command/markup.qh ../common/command/rpn.qh @@ -58,12 +59,11 @@ vehicles/vehicles.qh ../csqcmodellib/common.qh ../csqcmodellib/cl_model.qh ../csqcmodellib/cl_player.qh -weapons/projectile.qh // TODO +projectile.qh player_skeleton.qh sortlist.qc miscfunctions.qc -../server/t_items.qh ../server/t_items.qc teamradar.qc @@ -78,7 +78,7 @@ rubble.qc hook.qc particles.qc laser.qc -weapons/projectile.qc // TODO +projectile.qc gibs.qc damage.qc casings.qc @@ -112,7 +112,9 @@ noise.qc ../common/command/rpn.qc ../common/command/generic.qc ../common/mapinfo.qc -../common/weapons/weapons.qc // TODO +../common/items.qc +../server/w_all.qc +../common/explosion_equation.qc ../common/urllib.qc command/cl_cmd.qc diff --git a/qcsrc/client/projectile.qc b/qcsrc/client/projectile.qc new file mode 100644 index 000000000..8ff5e0f91 --- /dev/null +++ b/qcsrc/client/projectile.qc @@ -0,0 +1,505 @@ +.vector iorigin1, iorigin2; +.float spawntime; +.vector trail_oldorigin; +.float trail_oldtime; +.float fade_time, fade_rate; + +void SUB_Stop() +{ + self.move_velocity = self.move_avelocity = '0 0 0'; + self.move_movetype = MOVETYPE_NONE; +} + +.float alphamod; +.float count; // set if clientside projectile +.float cnt; // sound index +.float gravity; +.float snd_looping; +.float silent; + +void Projectile_ResetTrail(vector to) +{ + self.trail_oldorigin = to; + self.trail_oldtime = time; +} + +void Projectile_DrawTrail(vector to) +{ + vector from; + float t0; + + from = self.trail_oldorigin; + t0 = self.trail_oldtime; + self.trail_oldorigin = to; + self.trail_oldtime = time; + + // force the effect even for stationary firemine + if(self.cnt == PROJECTILE_FIREMINE) + if(from == to) + from_z += 1; + + if (self.traileffect) + { + particles_alphamin = particles_alphamax = particles_fade = sqrt(self.alpha); + boxparticles(self.traileffect, self, from, to, self.velocity, self.velocity, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE | PARTICLES_DRAWASTRAIL); + } +} + +void Projectile_Draw() +{ + vector rot; + vector trailorigin; + float f; + float drawn; + float t; + float a; + + f = self.move_flags; + + if(self.count & 0x80) + { + //self.move_flags &= ~FL_ONGROUND; + if(self.move_movetype == MOVETYPE_NONE || self.move_movetype == MOVETYPE_FLY) + Movetype_Physics_NoMatchServer(); + // the trivial movetypes do not have to match the + // server's ticrate as they are ticrate independent + // NOTE: this assumption is only true if MOVETYPE_FLY + // projectiles detonate on impact. If they continue + // moving, we might still be ticrate dependent. + else + Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy); + if(!(self.move_flags & FL_ONGROUND)) + if(self.velocity != '0 0 0') + self.move_angles = self.angles = vectoangles(self.velocity); + } + else + { + InterpolateOrigin_Do(); + } + + if(self.count & 0x80) + { + drawn = (time >= self.spawntime - 0.02); + t = max(time, self.spawntime); + } + else + { + drawn = (self.iflags & IFLAG_VALID); + t = time; + } + + if(!(f & FL_ONGROUND)) + { + rot = '0 0 0'; + switch(self.cnt) + { + /* + case PROJECTILE_GRENADE: + rot = '-2000 0 0'; // forward + break; + */ + case PROJECTILE_GRENADE_BOUNCING: + rot = '0 -1000 0'; // sideways + break; + case PROJECTILE_HOOKBOMB: + rot = '1000 0 0'; // forward + break; + default: + break; + } + + if(Nade_IDFromProjectile(self.cnt) != 0) + rot = self.avelocity; + + self.angles = AnglesTransform_ToAngles(AnglesTransform_Multiply(AnglesTransform_FromAngles(self.angles), rot * (t - self.spawntime))); + } + + vector ang; + ang = self.angles; + ang_x = -ang_x; + makevectors(ang); + + a = 1 - (time - self.fade_time) * self.fade_rate; + self.alpha = bound(0, self.alphamod * a, 1); + if(self.alpha <= 0) + drawn = 0; + self.renderflags = 0; + + trailorigin = self.origin; + switch(self.cnt) + { + case PROJECTILE_GRENADE: + case PROJECTILE_GRENADE_BOUNCING: + trailorigin += v_right * 1 + v_forward * -10; + break; + default: + break; + } + + if(Nade_IDFromProjectile(self.cnt) != 0) + trailorigin += v_up * 4; + + if(drawn) + Projectile_DrawTrail(trailorigin); + else + Projectile_ResetTrail(trailorigin); + + self.drawmask = 0; + + if(!drawn) + return; + + switch(self.cnt) + { + // Possibly add dlights here. + default: + break; + } + + self.drawmask = MASK_NORMAL; +} + +void loopsound(entity e, float ch, string samp, float vol, float attn) +{ + if(self.silent) + return; + + sound(e, ch, samp, vol, attn); + e.snd_looping = ch; +} + +void Ent_RemoveProjectile() +{ + if(self.count & 0x80) + { + tracebox(self.origin, self.mins, self.maxs, self.origin + self.velocity * 0.05, MOVE_NORMAL, self); + Projectile_DrawTrail(trace_endpos); + } +} + +void Ent_Projectile() +{ + float f; + + // projectile properties: + // kind (interpolated, or clientside) + // + // modelindex + // origin + // scale + // if clientside: + // velocity + // gravity + // soundindex (hardcoded list) + // effects + // + // projectiles don't send angles, because they always follow the velocity + + f = ReadByte(); + self.count = (f & 0x80); + self.iflags = (self.iflags & IFLAG_INTERNALMASK) | IFLAG_AUTOANGLES | IFLAG_ANGLES | IFLAG_ORIGIN; + self.solid = SOLID_TRIGGER; + //self.effects = EF_NOMODELFLAGS; + + // this should make collisions with bmodels more exact, but it leads to + // projectiles no longer being able to lie on a bmodel + self.move_nomonsters = MOVE_WORLDONLY; + if(f & 0x40) + self.move_flags |= FL_ONGROUND; + else + self.move_flags &= ~FL_ONGROUND; + + if(!self.move_time) + { + // for some unknown reason, we don't need to care for + // sv_gameplayfix_delayprojectiles here. + self.move_time = time; + self.spawntime = time; + } + else + self.move_time = max(self.move_time, time); + + if(!(self.count & 0x80)) + InterpolateOrigin_Undo(); + + if(f & 1) + { + self.origin_x = ReadCoord(); + self.origin_y = ReadCoord(); + self.origin_z = ReadCoord(); + setorigin(self, self.origin); + if(self.count & 0x80) + { + self.velocity_x = ReadCoord(); + self.velocity_y = ReadCoord(); + self.velocity_z = ReadCoord(); + if(f & 0x10) + self.gravity = ReadCoord(); + else + self.gravity = 0; // none + self.move_origin = self.origin; + self.move_velocity = self.velocity; + } + + if(time == self.spawntime || (self.count & 0x80) || (f & 0x08)) + { + self.trail_oldorigin = self.origin; + if(!(self.count & 0x80)) + InterpolateOrigin_Reset(); + } + + if(f & 0x20) + { + self.fade_time = time + ReadByte() * ticrate; + self.fade_rate = 1 / (ReadByte() * ticrate); + } + else + { + self.fade_time = 0; + self.fade_rate = 0; + } + + self.team = ReadByte() - 1; + } + + if(f & 2) + { + self.cnt = ReadByte(); + + self.silent = (self.cnt & 0x80); + self.cnt = (self.cnt & 0x7F); + + self.scale = 1; + self.traileffect = 0; + switch(self.cnt) + { + case PROJECTILE_ELECTRO: setmodel(self, "models/ebomb.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break; + case PROJECTILE_ROCKET: setmodel(self, "models/rocket.md3");self.traileffect = particleeffectnum("TR_ROCKET"); self.scale = 2; break; + case PROJECTILE_CRYLINK: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break; + case PROJECTILE_CRYLINK_BOUNCING: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break; + case PROJECTILE_ELECTRO_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_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("TR_GRENADE"); 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; + case PROJECTILE_PORTO_BLUE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_WIZSPIKE"); self.scale = 4; break; + case PROJECTILE_HOOKBOMB: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_KNIGHTSPIKE"); break; + case PROJECTILE_HAGAR: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("tr_hagar"); self.scale = 0.75; break; + case PROJECTILE_HAGAR_BOUNCING: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("tr_hagar"); self.scale = 0.75; break; + case PROJECTILE_NAPALM_FOUNTAIN: //self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("torch_small"); break; + case PROJECTILE_FIREBALL: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("fireball"); break; // particle effect is good enough + case PROJECTILE_FIREMINE: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("firemine"); break; // particle effect is good enough + case PROJECTILE_TAG: setmodel(self, "models/laser.mdl"); self.traileffect = particleeffectnum("TR_ROCKET"); break; + case PROJECTILE_FLAC: setmodel(self, "models/hagarmissile.mdl"); self.scale = 0.4; self.traileffect = particleeffectnum("TR_SEEKER"); break; + case PROJECTILE_SEEKER: setmodel(self, "models/tagrocket.md3"); self.traileffect = particleeffectnum("TR_SEEKER"); break; + + case PROJECTILE_MAGE_SPIKE: setmodel(self, "models/ebomb.mdl"); self.traileffect = particleeffectnum("TR_VORESPIKE"); break; + case PROJECTILE_SHAMBLER_LIGHTNING: setmodel(self, "models/ebomb.mdl"); self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break; + + case PROJECTILE_RAPTORBOMB: setmodel(self, "models/vehicles/clusterbomb.md3"); self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = particleeffectnum(""); break; + case PROJECTILE_RAPTORBOMBLET: setmodel(self, "models/vehicles/bomblet.md3"); self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = particleeffectnum(""); break; + case PROJECTILE_RAPTORCANNON: setmodel(self, "models/plasmatrail.mdl"); self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break; + + case PROJECTILE_SPIDERROCKET: setmodel(self, "models/vehicles/rocket02.md3"); self.traileffect = particleeffectnum("spiderbot_rocket_thrust"); break; + case PROJECTILE_WAKIROCKET: setmodel(self, "models/vehicles/rocket01.md3"); self.traileffect = particleeffectnum("wakizashi_rocket_thrust"); break; + case PROJECTILE_WAKICANNON: setmodel(self, "models/laser.mdl"); self.traileffect = particleeffectnum(""); break; + + case PROJECTILE_BUMBLE_GUN: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break; + case PROJECTILE_BUMBLE_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break; + + default: + if(Nade_IDFromProjectile(self.cnt) != 0) { setmodel(self, "models/weapons/v_ok_grenade.md3");self.traileffect = particleeffectnum(Nade_TrailEffect(self.cnt, self.team)); break; } + error("Received invalid CSQC projectile, can't work with this!"); + break; + } + + self.mins = '0 0 0'; + self.maxs = '0 0 0'; + self.colormod = '0 0 0'; + self.move_touch = SUB_Stop; + self.move_movetype = MOVETYPE_TOSS; + self.alphamod = 1; + + switch(self.cnt) + { + case PROJECTILE_ELECTRO: + // only new engines support sound moving with object + loopsound(self, CH_SHOTS_SINGLE, "weapons/electro_fly.wav", VOL_BASE, ATTEN_NORM); + self.mins = '0 0 -4'; + self.maxs = '0 0 -4'; + self.move_movetype = MOVETYPE_BOUNCE; + self.move_touch = func_null; + self.move_bounce_factor = g_balance_electro_secondary_bouncefactor; + self.move_bounce_stopspeed = g_balance_electro_secondary_bouncestop; + break; + case PROJECTILE_ROCKET: + loopsound(self, CH_SHOTS_SINGLE, "weapons/rocket_fly.wav", VOL_BASE, ATTEN_NORM); + self.mins = '-3 -3 -3'; + self.maxs = '3 3 3'; + break; + case PROJECTILE_GRENADE: + self.mins = '-3 -3 -3'; + self.maxs = '3 3 3'; + break; + case PROJECTILE_GRENADE_BOUNCING: + self.mins = '-3 -3 -3'; + self.maxs = '3 3 3'; + self.move_movetype = MOVETYPE_BOUNCE; + self.move_touch = func_null; + self.move_bounce_factor = g_balance_grenadelauncher_bouncefactor; + self.move_bounce_stopspeed = g_balance_grenadelauncher_bouncestop; + break; + case PROJECTILE_SHAMBLER_LIGHTNING: + self.mins = '-8 -8 -8'; + self.maxs = '8 8 8'; + self.scale = 2.5; + self.avelocity = randomvec() * 720; + 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; + self.move_movetype = MOVETYPE_BOUNCE; + self.move_touch = func_null; + break; + case PROJECTILE_PORTO_BLUE: + self.colormod = '1 1 2'; + self.alphamod = 0.5; + self.move_movetype = MOVETYPE_BOUNCE; + self.move_touch = func_null; + break; + case PROJECTILE_HAGAR_BOUNCING: + self.move_movetype = MOVETYPE_BOUNCE; + self.move_touch = func_null; + break; + case PROJECTILE_CRYLINK_BOUNCING: + self.move_movetype = MOVETYPE_BOUNCE; + self.move_touch = func_null; + break; + case PROJECTILE_NAPALM_FOUNTAIN: + case PROJECTILE_FIREBALL: + loopsound(self, CH_SHOTS_SINGLE, "weapons/fireball_fly2.wav", VOL_BASE, ATTEN_NORM); + self.mins = '-16 -16 -16'; + self.maxs = '16 16 16'; + break; + case PROJECTILE_FIREMINE: + loopsound(self, CH_SHOTS_SINGLE, "weapons/fireball_fly.wav", VOL_BASE, ATTEN_NORM); + self.move_movetype = MOVETYPE_BOUNCE; + self.move_touch = func_null; + self.mins = '-4 -4 -4'; + self.maxs = '4 4 4'; + break; + case PROJECTILE_TAG: + self.mins = '-2 -2 -2'; + self.maxs = '2 2 2'; + break; + case PROJECTILE_FLAC: + self.mins = '-2 -2 -2'; + self.maxs = '2 2 2'; + break; + case PROJECTILE_SEEKER: + loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTEN_NORM); + self.mins = '-4 -4 -4'; + self.maxs = '4 4 4'; + break; + case PROJECTILE_RAPTORBOMB: + self.mins = '-3 -3 -3'; + self.maxs = '3 3 3'; + break; + case PROJECTILE_RAPTORBOMBLET: + break; + case PROJECTILE_RAPTORCANNON: + break; + case PROJECTILE_SPIDERROCKET: + loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTEN_NORM); + break; + case PROJECTILE_WAKIROCKET: + loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTEN_NORM); + break; + /* + case PROJECTILE_WAKICANNON: + break; + case PROJECTILE_BUMBLE_GUN: + // only new engines support sound moving with object + loopsound(self, CH_SHOTS_SINGLE, "weapons/electro_fly.wav", VOL_BASE, ATTEN_NORM); + self.mins = '0 0 -4'; + self.maxs = '0 0 -4'; + self.move_movetype = MOVETYPE_BOUNCE; + self.move_touch = func_null; + self.move_bounce_factor = g_balance_electro_secondary_bouncefactor; + self.move_bounce_stopspeed = g_balance_electro_secondary_bouncestop; + break; + */ + default: + break; + } + + if(Nade_IDFromProjectile(self.cnt) != 0) + { + self.mins = '-16 -16 -16'; + self.maxs = '16 16 16'; + self.colormod = Nade_Color(Nade_IDFromProjectile(self.cnt)); + self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP; + self.move_movetype = MOVETYPE_BOUNCE; + self.move_touch = func_null; + self.scale = 1.5; + self.avelocity = randomvec() * 720; + + if(Nade_IDFromProjectile(self.cnt) == NADE_TYPE_TRANSLOCATE) + self.solid = SOLID_TRIGGER; + } + + setsize(self, self.mins, self.maxs); + } + + if(self.gravity) + { + if(self.move_movetype == MOVETYPE_FLY) + self.move_movetype = MOVETYPE_TOSS; + if(self.move_movetype == MOVETYPE_BOUNCEMISSILE) + self.move_movetype = MOVETYPE_BOUNCE; + } + else + { + if(self.move_movetype == MOVETYPE_TOSS) + self.move_movetype = MOVETYPE_FLY; + if(self.move_movetype == MOVETYPE_BOUNCE) + self.move_movetype = MOVETYPE_BOUNCEMISSILE; + } + + if(!(self.count & 0x80)) + InterpolateOrigin_Note(); + + self.draw = Projectile_Draw; + self.entremove = Ent_RemoveProjectile; +} + +void Projectile_Precache() +{ + 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"); + precache_model("models/plasmatrail.mdl"); + precache_model("models/rocket.md3"); + precache_model("models/tagrocket.md3"); + precache_model("models/tracer.mdl"); + precache_model("models/sphere/sphere.md3"); + + precache_model("models/weapons/v_ok_grenade.md3"); + + precache_sound("weapons/electro_fly.wav"); + precache_sound("weapons/rocket_fly.wav"); + precache_sound("weapons/fireball_fly.wav"); + precache_sound("weapons/fireball_fly2.wav"); + precache_sound("weapons/tag_rocket_fly.wav"); + +} diff --git a/qcsrc/client/projectile.qh b/qcsrc/client/projectile.qh new file mode 100644 index 000000000..70c8ba0df --- /dev/null +++ b/qcsrc/client/projectile.qh @@ -0,0 +1,3 @@ +.float traileffect; +void Projectile_ResetTrail(vector to); +void Projectile_DrawTrail(vector to); diff --git a/qcsrc/client/scoreboard.qc b/qcsrc/client/scoreboard.qc index 06e29680f..52bf9190b 100644 --- a/qcsrc/client/scoreboard.qc +++ b/qcsrc/client/scoreboard.qc @@ -955,7 +955,7 @@ float average_accuracy; vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size) { float i; - float weapon_cnt = WEP_COUNT - 3; // either vaporizer/nex are hidden, no port-o-launch, no tuba + float weapon_cnt = WEP_COUNT - 3; // either minstanex/nex are hidden, no port-o-launch, no tuba float rows; if(autocvar_scoreboard_accuracy_doublerows) rows = 2; @@ -998,7 +998,7 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size) if(rows == 2) pos_x += weapon_width / 2; - if(switchweapon == WEP_VAPORIZER) + if(switchweapon == WEP_MINSTANEX) g_minstagib = 1; // TODO: real detection for minstagib? float weapon_stats; @@ -1012,7 +1012,7 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size) self = get_weaponinfo(i); if (!self.weapon) continue; - if ((i == WEP_VORTEX && g_minstagib) || i == WEP_PORTO || (i == WEP_VAPORIZER && !g_minstagib) || i == WEP_TUBA) // skip port-o-launch, vortex || vaporizer and tuba + if ((i == WEP_NEX && g_minstagib) || i == WEP_PORTO || (i == WEP_MINSTANEX && !g_minstagib) || i == WEP_TUBA) // skip port-o-launch, nex || minstanex and tuba continue; weapon_stats = weapon_accuracy[i-WEP_FIRST]; @@ -1023,7 +1023,7 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size) weapon_alpha = 0.2 * scoreboard_alpha_fg; // weapon icon - drawpic_aspect_skin(pos, self.model2, '1 0 0' * weapon_width + '0 1 0' * weapon_height, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL); + drawpic_aspect_skin(pos, strcat("weapon", self.netname), '1 0 0' * weapon_width + '0 1 0' * weapon_height, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL); // the accuracy if(weapon_stats >= 0) { weapons_with_stats += 1; diff --git a/qcsrc/client/waypointsprites.qc b/qcsrc/client/waypointsprites.qc index c99fc5d51..7ee34672c 100644 --- a/qcsrc/client/waypointsprites.qc +++ b/qcsrc/client/waypointsprites.qc @@ -217,20 +217,31 @@ float spritelookupblinkvalue(string s) } vector spritelookupcolor(string s, vector def) { - if(substring(s, 0, 4) == "wpn-") - return (get_weaponinfo(stof(substring(s, 4, strlen(s)))).wpcolor); - switch(s) { case "keycarrier-friend": return '0 1 0'; + case "wpn-laser": return '1 0.5 0.5'; + case "wpn-shotgun": return '0.5 0.25 0'; + case "wpn-uzi": return '1 1 0'; + case "wpn-gl": return '1 0 0'; + case "wpn-electro": return '0 0.5 1'; + case "wpn-crylink": return '1 0.5 1'; + case "wpn-nex": return '0.5 1 1'; + case "wpn-hagar": return '1 1 0.5'; + case "wpn-rl": return '1 1 0'; + case "wpn-porto": return '0.5 0.5 0.5'; + case "wpn-minstanex": return '0.5 1 1'; + case "wpn-hookgun": return '0 0.5 0'; + case "wpn-fireball": return '1 0.5 0'; + case "wpn-hlac": return '0 1 0'; + case "wpn-campingrifle": return '0.5 1 0'; + case "wpn-minelayer": return '0.75 1 0'; default: return def; } } string spritelookuptext(string s) { - if(substring(s, 0, 4) == "wpn-") { return (get_weaponinfo(stof(substring(s, 4, strlen(s)))).message); } if(substring(s, 0, 5) == "buff-") { return Buff_PrettyName(Buff_Type_FromSprite(s)); } - switch(s) { case "as-push": return _("Push"); @@ -271,6 +282,22 @@ string spritelookuptext(string s) case "nb-ball": return _("Ball"); case "ka-ball": return _("Ball"); case "ka-ballcarrier": return _("Ball carrier"); + case "wpn-laser": return _("Laser"); + case "wpn-shotgun": return _("Shotgun"); + case "wpn-uzi": return _("Machine Gun"); + case "wpn-gl": return _("Mortar"); + case "wpn-electro": return _("Electro"); + case "wpn-crylink": return _("Crylink"); + case "wpn-nex": return _("Nex"); + case "wpn-hagar": return _("Hagar"); + case "wpn-rl": return _("Rocket Launcher"); + case "wpn-porto": return _("Port-O-Launch"); + case "wpn-minstanex": return _("Minstanex"); + case "wpn-hookgun": return _("Hook"); + case "wpn-fireball": return _("Fireball"); + case "wpn-hlac": return _("HLAC"); + case "wpn-campingrifle": return _("Rifle"); + case "wpn-minelayer": return _("Mine Layer"); case "dom-neut": return _("Control point"); case "dom-red": return _("Control point"); case "dom-blue": return _("Control point"); diff --git a/qcsrc/client/weapons/projectile.qc b/qcsrc/client/weapons/projectile.qc deleted file mode 100644 index 58bd11ee4..000000000 --- a/qcsrc/client/weapons/projectile.qc +++ /dev/null @@ -1,505 +0,0 @@ -.vector iorigin1, iorigin2; -.float spawntime; -.vector trail_oldorigin; -.float trail_oldtime; -.float fade_time, fade_rate; - -void SUB_Stop() -{ - self.move_velocity = self.move_avelocity = '0 0 0'; - self.move_movetype = MOVETYPE_NONE; -} - -.float alphamod; -.float count; // set if clientside projectile -.float cnt; // sound index -.float gravity; -.float snd_looping; -.float silent; - -void Projectile_ResetTrail(vector to) -{ - self.trail_oldorigin = to; - self.trail_oldtime = time; -} - -void Projectile_DrawTrail(vector to) -{ - vector from; - float t0; - - from = self.trail_oldorigin; - t0 = self.trail_oldtime; - self.trail_oldorigin = to; - self.trail_oldtime = time; - - // force the effect even for stationary firemine - if(self.cnt == PROJECTILE_FIREMINE) - if(from == to) - from_z += 1; - - if (self.traileffect) - { - particles_alphamin = particles_alphamax = particles_fade = sqrt(self.alpha); - boxparticles(self.traileffect, self, from, to, self.velocity, self.velocity, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE | PARTICLES_DRAWASTRAIL); - } -} - -void Projectile_Draw() -{ - vector rot; - vector trailorigin; - float f; - float drawn; - float t; - float a; - - f = self.move_flags; - - if(self.count & 0x80) - { - //self.move_flags &= ~FL_ONGROUND; - if(self.move_movetype == MOVETYPE_NONE || self.move_movetype == MOVETYPE_FLY) - Movetype_Physics_NoMatchServer(); - // the trivial movetypes do not have to match the - // server's ticrate as they are ticrate independent - // NOTE: this assumption is only true if MOVETYPE_FLY - // projectiles detonate on impact. If they continue - // moving, we might still be ticrate dependent. - else - Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy); - if(!(self.move_flags & FL_ONGROUND)) - if(self.velocity != '0 0 0') - self.move_angles = self.angles = vectoangles(self.velocity); - } - else - { - InterpolateOrigin_Do(); - } - - if(self.count & 0x80) - { - drawn = (time >= self.spawntime - 0.02); - t = max(time, self.spawntime); - } - else - { - drawn = (self.iflags & IFLAG_VALID); - t = time; - } - - if(!(f & FL_ONGROUND)) - { - rot = '0 0 0'; - switch(self.cnt) - { - /* - case PROJECTILE_GRENADE: - rot = '-2000 0 0'; // forward - break; - */ - case PROJECTILE_GRENADE_BOUNCING: - rot = '0 -1000 0'; // sideways - break; - case PROJECTILE_HOOKBOMB: - rot = '1000 0 0'; // forward - break; - default: - break; - } - - if(Nade_IDFromProjectile(self.cnt) != 0) - rot = self.avelocity; - - self.angles = AnglesTransform_ToAngles(AnglesTransform_Multiply(AnglesTransform_FromAngles(self.angles), rot * (t - self.spawntime))); - } - - vector ang; - ang = self.angles; - ang_x = -ang_x; - makevectors(ang); - - a = 1 - (time - self.fade_time) * self.fade_rate; - self.alpha = bound(0, self.alphamod * a, 1); - if(self.alpha <= 0) - drawn = 0; - self.renderflags = 0; - - trailorigin = self.origin; - switch(self.cnt) - { - case PROJECTILE_GRENADE: - case PROJECTILE_GRENADE_BOUNCING: - trailorigin += v_right * 1 + v_forward * -10; - break; - default: - break; - } - - if(Nade_IDFromProjectile(self.cnt) != 0) - trailorigin += v_up * 4; - - if(drawn) - Projectile_DrawTrail(trailorigin); - else - Projectile_ResetTrail(trailorigin); - - self.drawmask = 0; - - if(!drawn) - return; - - switch(self.cnt) - { - // Possibly add dlights here. - default: - break; - } - - self.drawmask = MASK_NORMAL; -} - -void loopsound(entity e, float ch, string samp, float vol, float attn) -{ - if(self.silent) - return; - - sound(e, ch, samp, vol, attn); - e.snd_looping = ch; -} - -void Ent_RemoveProjectile() -{ - if(self.count & 0x80) - { - tracebox(self.origin, self.mins, self.maxs, self.origin + self.velocity * 0.05, MOVE_NORMAL, self); - Projectile_DrawTrail(trace_endpos); - } -} - -void Ent_Projectile() -{ - float f; - - // projectile properties: - // kind (interpolated, or clientside) - // - // modelindex - // origin - // scale - // if clientside: - // velocity - // gravity - // soundindex (hardcoded list) - // effects - // - // projectiles don't send angles, because they always follow the velocity - - f = ReadByte(); - self.count = (f & 0x80); - self.iflags = (self.iflags & IFLAG_INTERNALMASK) | IFLAG_AUTOANGLES | IFLAG_ANGLES | IFLAG_ORIGIN; - self.solid = SOLID_TRIGGER; - //self.effects = EF_NOMODELFLAGS; - - // this should make collisions with bmodels more exact, but it leads to - // projectiles no longer being able to lie on a bmodel - self.move_nomonsters = MOVE_WORLDONLY; - if(f & 0x40) - self.move_flags |= FL_ONGROUND; - else - self.move_flags &= ~FL_ONGROUND; - - if(!self.move_time) - { - // for some unknown reason, we don't need to care for - // sv_gameplayfix_delayprojectiles here. - self.move_time = time; - self.spawntime = time; - } - else - self.move_time = max(self.move_time, time); - - if(!(self.count & 0x80)) - InterpolateOrigin_Undo(); - - if(f & 1) - { - self.origin_x = ReadCoord(); - self.origin_y = ReadCoord(); - self.origin_z = ReadCoord(); - setorigin(self, self.origin); - if(self.count & 0x80) - { - self.velocity_x = ReadCoord(); - self.velocity_y = ReadCoord(); - self.velocity_z = ReadCoord(); - if(f & 0x10) - self.gravity = ReadCoord(); - else - self.gravity = 0; // none - self.move_origin = self.origin; - self.move_velocity = self.velocity; - } - - if(time == self.spawntime || (self.count & 0x80) || (f & 0x08)) - { - self.trail_oldorigin = self.origin; - if(!(self.count & 0x80)) - InterpolateOrigin_Reset(); - } - - if(f & 0x20) - { - self.fade_time = time + ReadByte() * ticrate; - self.fade_rate = 1 / (ReadByte() * ticrate); - } - else - { - self.fade_time = 0; - self.fade_rate = 0; - } - - self.team = ReadByte() - 1; - } - - if(f & 2) - { - self.cnt = ReadByte(); - - self.silent = (self.cnt & 0x80); - self.cnt = (self.cnt & 0x7F); - - self.scale = 1; - self.traileffect = 0; - switch(self.cnt) - { - case PROJECTILE_ELECTRO: setmodel(self, "models/ebomb.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break; - case PROJECTILE_ROCKET: setmodel(self, "models/rocket.md3");self.traileffect = particleeffectnum("TR_ROCKET"); self.scale = 2; break; - case PROJECTILE_CRYLINK: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break; - case PROJECTILE_CRYLINK_BOUNCING: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break; - case PROJECTILE_ELECTRO_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_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("TR_GRENADE"); break; - case PROJECTILE_BLASTER: 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; - case PROJECTILE_PORTO_BLUE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_WIZSPIKE"); self.scale = 4; break; - case PROJECTILE_HOOKBOMB: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_KNIGHTSPIKE"); break; - case PROJECTILE_HAGAR: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("tr_hagar"); self.scale = 0.75; break; - case PROJECTILE_HAGAR_BOUNCING: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("tr_hagar"); self.scale = 0.75; break; - case PROJECTILE_NAPALM_FOUNTAIN: //self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("torch_small"); break; - case PROJECTILE_FIREBALL: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("fireball"); break; // particle effect is good enough - case PROJECTILE_FIREMINE: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("firemine"); break; // particle effect is good enough - case PROJECTILE_TAG: setmodel(self, "models/laser.mdl"); self.traileffect = particleeffectnum("TR_ROCKET"); break; - case PROJECTILE_FLAC: setmodel(self, "models/hagarmissile.mdl"); self.scale = 0.4; self.traileffect = particleeffectnum("TR_SEEKER"); break; - case PROJECTILE_SEEKER: setmodel(self, "models/tagrocket.md3"); self.traileffect = particleeffectnum("TR_SEEKER"); break; - - case PROJECTILE_MAGE_SPIKE: setmodel(self, "models/ebomb.mdl"); self.traileffect = particleeffectnum("TR_VORESPIKE"); break; - case PROJECTILE_SHAMBLER_LIGHTNING: setmodel(self, "models/ebomb.mdl"); self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break; - - case PROJECTILE_RAPTORBOMB: setmodel(self, "models/vehicles/clusterbomb.md3"); self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = particleeffectnum(""); break; - case PROJECTILE_RAPTORBOMBLET: setmodel(self, "models/vehicles/bomblet.md3"); self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = particleeffectnum(""); break; - case PROJECTILE_RAPTORCANNON: setmodel(self, "models/plasmatrail.mdl"); self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break; - - case PROJECTILE_SPIDERROCKET: setmodel(self, "models/vehicles/rocket02.md3"); self.traileffect = particleeffectnum("spiderbot_rocket_thrust"); break; - case PROJECTILE_WAKIROCKET: setmodel(self, "models/vehicles/rocket01.md3"); self.traileffect = particleeffectnum("wakizashi_rocket_thrust"); break; - case PROJECTILE_WAKICANNON: setmodel(self, "models/laser.mdl"); self.traileffect = particleeffectnum(""); break; - - case PROJECTILE_BUMBLE_GUN: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break; - case PROJECTILE_BUMBLE_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break; - - default: - if(Nade_IDFromProjectile(self.cnt) != 0) { setmodel(self, "models/weapons/v_ok_grenade.md3");self.traileffect = particleeffectnum(Nade_TrailEffect(self.cnt, self.team)); break; } - error("Received invalid CSQC projectile, can't work with this!"); - break; - } - - self.mins = '0 0 0'; - self.maxs = '0 0 0'; - self.colormod = '0 0 0'; - self.move_touch = SUB_Stop; - self.move_movetype = MOVETYPE_TOSS; - self.alphamod = 1; - - switch(self.cnt) - { - case PROJECTILE_ELECTRO: - // only new engines support sound moving with object - loopsound(self, CH_SHOTS_SINGLE, "weapons/electro_fly.wav", VOL_BASE, ATTEN_NORM); - self.mins = '0 0 -4'; - self.maxs = '0 0 -4'; - self.move_movetype = MOVETYPE_BOUNCE; - self.move_touch = func_null; - self.move_bounce_factor = g_balance_electro_secondary_bouncefactor; - self.move_bounce_stopspeed = g_balance_electro_secondary_bouncestop; - break; - case PROJECTILE_ROCKET: - loopsound(self, CH_SHOTS_SINGLE, "weapons/rocket_fly.wav", VOL_BASE, ATTEN_NORM); - self.mins = '-3 -3 -3'; - self.maxs = '3 3 3'; - break; - case PROJECTILE_GRENADE: - self.mins = '-3 -3 -3'; - self.maxs = '3 3 3'; - break; - case PROJECTILE_GRENADE_BOUNCING: - self.mins = '-3 -3 -3'; - self.maxs = '3 3 3'; - self.move_movetype = MOVETYPE_BOUNCE; - self.move_touch = func_null; - self.move_bounce_factor = g_balance_grenadelauncher_bouncefactor; - self.move_bounce_stopspeed = g_balance_grenadelauncher_bouncestop; - break; - case PROJECTILE_SHAMBLER_LIGHTNING: - self.mins = '-8 -8 -8'; - self.maxs = '8 8 8'; - self.scale = 2.5; - self.avelocity = randomvec() * 720; - 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; - self.move_movetype = MOVETYPE_BOUNCE; - self.move_touch = func_null; - break; - case PROJECTILE_PORTO_BLUE: - self.colormod = '1 1 2'; - self.alphamod = 0.5; - self.move_movetype = MOVETYPE_BOUNCE; - self.move_touch = func_null; - break; - case PROJECTILE_HAGAR_BOUNCING: - self.move_movetype = MOVETYPE_BOUNCE; - self.move_touch = func_null; - break; - case PROJECTILE_CRYLINK_BOUNCING: - self.move_movetype = MOVETYPE_BOUNCE; - self.move_touch = func_null; - break; - case PROJECTILE_NAPALM_FOUNTAIN: - case PROJECTILE_FIREBALL: - loopsound(self, CH_SHOTS_SINGLE, "weapons/fireball_fly2.wav", VOL_BASE, ATTEN_NORM); - self.mins = '-16 -16 -16'; - self.maxs = '16 16 16'; - break; - case PROJECTILE_FIREMINE: - loopsound(self, CH_SHOTS_SINGLE, "weapons/fireball_fly.wav", VOL_BASE, ATTEN_NORM); - self.move_movetype = MOVETYPE_BOUNCE; - self.move_touch = func_null; - self.mins = '-4 -4 -4'; - self.maxs = '4 4 4'; - break; - case PROJECTILE_TAG: - self.mins = '-2 -2 -2'; - self.maxs = '2 2 2'; - break; - case PROJECTILE_FLAC: - self.mins = '-2 -2 -2'; - self.maxs = '2 2 2'; - break; - case PROJECTILE_SEEKER: - loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTEN_NORM); - self.mins = '-4 -4 -4'; - self.maxs = '4 4 4'; - break; - case PROJECTILE_RAPTORBOMB: - self.mins = '-3 -3 -3'; - self.maxs = '3 3 3'; - break; - case PROJECTILE_RAPTORBOMBLET: - break; - case PROJECTILE_RAPTORCANNON: - break; - case PROJECTILE_SPIDERROCKET: - loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTEN_NORM); - break; - case PROJECTILE_WAKIROCKET: - loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTEN_NORM); - break; - /* - case PROJECTILE_WAKICANNON: - break; - case PROJECTILE_BUMBLE_GUN: - // only new engines support sound moving with object - loopsound(self, CH_SHOTS_SINGLE, "weapons/electro_fly.wav", VOL_BASE, ATTEN_NORM); - self.mins = '0 0 -4'; - self.maxs = '0 0 -4'; - self.move_movetype = MOVETYPE_BOUNCE; - self.move_touch = func_null; - self.move_bounce_factor = g_balance_electro_secondary_bouncefactor; - self.move_bounce_stopspeed = g_balance_electro_secondary_bouncestop; - break; - */ - default: - break; - } - - if(Nade_IDFromProjectile(self.cnt) != 0) - { - self.mins = '-16 -16 -16'; - self.maxs = '16 16 16'; - self.colormod = Nade_Color(Nade_IDFromProjectile(self.cnt)); - self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP; - self.move_movetype = MOVETYPE_BOUNCE; - self.move_touch = func_null; - self.scale = 1.5; - self.avelocity = randomvec() * 720; - - if(Nade_IDFromProjectile(self.cnt) == NADE_TYPE_TRANSLOCATE) - self.solid = SOLID_TRIGGER; - } - - setsize(self, self.mins, self.maxs); - } - - if(self.gravity) - { - if(self.move_movetype == MOVETYPE_FLY) - self.move_movetype = MOVETYPE_TOSS; - if(self.move_movetype == MOVETYPE_BOUNCEMISSILE) - self.move_movetype = MOVETYPE_BOUNCE; - } - else - { - if(self.move_movetype == MOVETYPE_TOSS) - self.move_movetype = MOVETYPE_FLY; - if(self.move_movetype == MOVETYPE_BOUNCE) - self.move_movetype = MOVETYPE_BOUNCEMISSILE; - } - - if(!(self.count & 0x80)) - InterpolateOrigin_Note(); - - self.draw = Projectile_Draw; - self.entremove = Ent_RemoveProjectile; -} - -void Projectile_Precache() -{ - 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"); - precache_model("models/plasmatrail.mdl"); - precache_model("models/rocket.md3"); - precache_model("models/tagrocket.md3"); - precache_model("models/tracer.mdl"); - precache_model("models/sphere/sphere.md3"); - - precache_model("models/weapons/v_ok_grenade.md3"); - - precache_sound("weapons/electro_fly.wav"); - precache_sound("weapons/rocket_fly.wav"); - precache_sound("weapons/fireball_fly.wav"); - precache_sound("weapons/fireball_fly2.wav"); - precache_sound("weapons/tag_rocket_fly.wav"); - -} diff --git a/qcsrc/client/weapons/projectile.qh b/qcsrc/client/weapons/projectile.qh deleted file mode 100644 index 70c8ba0df..000000000 --- a/qcsrc/client/weapons/projectile.qh +++ /dev/null @@ -1,3 +0,0 @@ -.float traileffect; -void Projectile_ResetTrail(vector to); -void Projectile_DrawTrail(vector to); diff --git a/qcsrc/common/command/generic.qc b/qcsrc/common/command/generic.qc index 3f87609ee..08b0b69dd 100644 --- a/qcsrc/common/command/generic.qc +++ b/qcsrc/common/command/generic.qc @@ -239,12 +239,12 @@ void GenericCommand_dumpnotifs(float request) if(filename == "") { - filename = "notifications_dump.cfg"; + filename = "notifications.cfg"; alsoprint = FALSE; } else if(filename == "-") { - filename = "notifications_dump.cfg"; + filename = "notifications.cfg"; alsoprint = TRUE; } fh = fopen(filename, FILE_WRITE); @@ -269,60 +269,7 @@ void GenericCommand_dumpnotifs(float request) case CMD_REQUEST_USAGE: { print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " dumpnotifs [filename]")); - print(" Where 'filename' is the file to write (default is notifications_dump.cfg),\n"); - print(" if supplied with '-' output to console as well as default,\n"); - print(" if left blank, it will only write to default.\n"); - return; - } - } -} - -void GenericCommand_dumpweapons(float request) // WEAPONTODO: make this work with other progs than just server -{ - switch(request) - { - case CMD_REQUEST_COMMAND: - { - #ifdef SVQC - wep_config_file = -1; - wep_config_alsoprint = -1; - string filename = argv(1); - - if(filename == "") - { - filename = "weapons_dump.cfg"; - wep_config_alsoprint = FALSE; - } - else if(filename == "-") - { - filename = "weapons_dump.cfg"; - wep_config_alsoprint = TRUE; - } - wep_config_file = fopen(filename, FILE_WRITE); - - if(wep_config_file >= 0) - { - Dump_Weapon_Settings(); - print(sprintf("Dumping weapons... File located in ^2data/data/%s^7.\n", filename)); - fclose(wep_config_file); - wep_config_file = -1; - wep_config_alsoprint = -1; - } - else - { - print(sprintf("^1Error: ^7Could not open file '%s'!\n", filename)); - } - #else - print(_("Weapons dump command only works with sv_cmd.\n")); - #endif - return; - } - - default: - case CMD_REQUEST_USAGE: - { - print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " dumpweapons [filename]")); - print(" Where 'filename' is the file to write (default is weapons_dump.cfg),\n"); + print(" Where 'filename' is the file to write (default is notifications.cfg),\n"); print(" if supplied with '-' output to console as well as default,\n"); print(" if left blank, it will only write to default.\n"); return; @@ -638,7 +585,6 @@ void GenericCommand_(float request) GENERIC_COMMAND("addtolist", GenericCommand_addtolist(request, arguments), "Add a string to a cvar") \ GENERIC_COMMAND("dumpcommands", GenericCommand_dumpcommands(request), "Dump all commands on the program to *_cmd_dump.txt") \ GENERIC_COMMAND("dumpnotifs", GenericCommand_dumpnotifs(request), "Dump all notifications into notifications_dump.txt") \ - GENERIC_COMMAND("dumpweapons", GenericCommand_dumpweapons(request), "Dump all weapons into weapons_dump.txt") \ GENERIC_COMMAND("maplist", GenericCommand_maplist(request, arguments), "Automatic control of maplist") \ GENERIC_COMMAND("nextframe", GenericCommand_nextframe(request, arguments, command), "Execute the given command next frame of this VM") \ GENERIC_COMMAND("qc_curl", GenericCommand_qc_curl(request, arguments), "Queries a URL") \ diff --git a/qcsrc/common/constants.qh b/qcsrc/common/constants.qh index 2d0c83a49..fb6d781c0 100644 --- a/qcsrc/common/constants.qh +++ b/qcsrc/common/constants.qh @@ -30,18 +30,17 @@ const float AS_FLOAT = 8; const float TE_CSQC_PICTURE = 100; const float TE_CSQC_RACE = 101; -const float TE_CSQC_VORTEXBEAMPARTICLE = 103; -const float TE_CSQC_ARC = 104; +const float TE_CSQC_NEXGUNBEAMPARTICLE = 103; +const float TE_CSQC_LIGHTNINGARC = 104; const float TE_CSQC_TEAMNAGGER = 105; const float TE_CSQC_PINGPLREPORT = 106; const float TE_CSQC_TARGET_MUSIC = 107; const float TE_CSQC_WEAPONCOMPLAIN = 108; -const float TE_CSQC_VORTEX_SCOPE = 109; +const float TE_CSQC_NEX_SCOPE = 109; const float TE_CSQC_MINELAYER_MAXMINES = 110; const float TE_CSQC_HAGAR_MAXROCKETS = 111; const float TE_CSQC_VEHICLESETUP = 112; const float TE_CSQC_SVNOTICE = 113; -const float TE_CSQC_SHOCKWAVEPARTICLE = 114; const float RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder const float RACE_NET_CHECKPOINT_CLEAR = 1; @@ -86,7 +85,8 @@ const float ENT_CLIENT_WARPZONE = 24; const float ENT_CLIENT_WARPZONE_CAMERA = 25; const float ENT_CLIENT_TRIGGER_MUSIC = 26; const float ENT_CLIENT_HOOK = 27; -const float ENT_CLIENT_ARC_BEAM = 29; // WEAPONTODO: fix numbers +const float ENT_CLIENT_LGBEAM = 28; +const float ENT_CLIENT_GAUNTLET = 29; const float ENT_CLIENT_ACCURACY = 30; const float ENT_CLIENT_SHOWNAMES = 31; const float ENT_CLIENT_WARPZONE_TELEPORTED = 32; @@ -238,7 +238,7 @@ const float ATTEN_MAX = 3.984375; #define VOL_BASE 0.7 #define VOL_BASEVOICE 1.0 -// WEAPONTODO: move this into separate/new projectile handling code // this sets sounds and other properties of the projectiles in csqc +// this sets sounds and other properties of the projectiles in csqc const float PROJECTILE_ELECTRO = 1; const float PROJECTILE_ROCKET = 2; const float PROJECTILE_TAG = 3; @@ -247,7 +247,7 @@ const float PROJECTILE_ELECTRO_BEAM = 6; const float PROJECTILE_GRENADE = 7; const float PROJECTILE_GRENADE_BOUNCING = 8; const float PROJECTILE_MINE = 9; -const float PROJECTILE_BLASTER = 10; +const float PROJECTILE_LASER = 10; const float PROJECTILE_HLAC = 11; const float PROJECTILE_SEEKER = 12; const float PROJECTILE_FLAC = 13; @@ -292,6 +292,25 @@ const float WATERLEVEL_NONE = 0; const float WATERLEVEL_WETFEET = 1; const float WATERLEVEL_SWIMMING = 2; const float WATERLEVEL_SUBMERGED = 3; + +const float MAX_SHOT_DISTANCE = 32768; + +// weapon requests +const float WR_SETUP = 1; // (SVQC) setup weapon data +const float WR_THINK = 2; // (SVQC) logic to run every frame +const float WR_CHECKAMMO1 = 3; // (SVQC) checks ammo for weapon +const float WR_CHECKAMMO2 = 4; // (SVQC) checks ammo for weapon +const float WR_AIM = 5; // (SVQC) runs bot aiming code for this weapon +const float WR_PRECACHE = 6; // (CSQC and SVQC) precaches models/sounds used by this weapon +const float WR_SUICIDEMESSAGE = 7; // (SVQC) notification number for suicide message (may inspect w_deathtype for details) +const float WR_KILLMESSAGE = 8; // (SVQC) notification number for kill message (may inspect w_deathtype for details) +const float WR_RELOAD = 9; // (SVQC) does not need to do anything +const float WR_RESETPLAYER = 10; // (SVQC) does not need to do anything +const float WR_IMPACTEFFECT = 11; // (CSQC) impact effect +const float WR_SWITCHABLE = 12; // (CSQC) impact effect +const float WR_PLAYERDEATH = 13; // (SVQC) does not need to do anything +const float WR_GONETHINK = 14; // (SVQC) logic to run every frame, also if no longer having the weapon as long as the switch away has not been performed + #define SERVERFLAG_ALLOW_FULLBRIGHT 1 #define SERVERFLAG_TEAMPLAY 2 #define SERVERFLAG_PLAYERSTATS 4 diff --git a/qcsrc/common/explosion_equation.qc b/qcsrc/common/explosion_equation.qc new file mode 100644 index 000000000..3fddd70d2 --- /dev/null +++ b/qcsrc/common/explosion_equation.qc @@ -0,0 +1,62 @@ +float explosion_calcpush_getmultiplier(vector explosion_v, vector target_v) +{ + float a; + a = explosion_v * (explosion_v - target_v); + + if(a <= 0) + // target is too fast to be hittable by this + return 0; + + a /= (explosion_v * explosion_v); + // we know we can divide by this, or above a would be == 0 + + return a; +} + +#if 0 +vector explosion_calcpush(vector explosion_v, float explosion_m, vector target_v, float target_m, float elasticity) +{ + // solution of the equations: + // v' = v + a vp // central hit + // m*v' + mp*vp' = m*v + mp*vp // conservation of momentum + // m*v'^2 + mp*vp'^2 = m*v^2 + mp*vp^2 // conservation of energy (ELASTIC hit) + // -> a = 0 // case 1: did not hit + // -> a = 2*mp*(vp^2 - vp.v) / ((m+mp) * vp^2) // case 2: did hit + // // non-elastic hits are somewhere between these two + + // this would be physically correct, but we don't do that + return explosion_v * explosion_calcpush_getmultiplier(explosion_v, target_v) * ( + (1 + elasticity) * ( + explosion_m + ) / ( + target_m + explosion_m + ) + ); // note: this factor is at least 0, at most 2 +} +#endif + +// simplified formula, tuned so that if the target has velocity 0, we get exactly the original force +vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor) +{ + // if below 1, the formulas make no sense (and would cause superjumps) + if(speedfactor < 1) + return explosion_f; + +#if 0 + float m; + // find m so that + // speedfactor * (1 + e) * m / (1 + m) == 1 + m = 1 / ((1 + 0) * speedfactor - 1); + vector v; + v = explosion_calcpush(explosion_f * speedfactor, m, target_v, 1, 0); + // the factor we then get is: + // 1 + printf("MASS: %f\nv: %v -> %v\nENERGY BEFORE == %f + %f = %f\nENERGY AFTER >= %f\n", + m, + target_v, target_v + v, + target_v * target_v, m * explosion_f * speedfactor * explosion_f * speedfactor, target_v * target_v + m * explosion_f * speedfactor * explosion_f * speedfactor, + (target_v + v) * (target_v + v)); + return v; +#endif + return explosion_f * explosion_calcpush_getmultiplier(explosion_f * speedfactor, target_v); +} diff --git a/qcsrc/common/explosion_equation.qh b/qcsrc/common/explosion_equation.qh new file mode 100644 index 000000000..c8630cdb1 --- /dev/null +++ b/qcsrc/common/explosion_equation.qh @@ -0,0 +1 @@ +vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor); diff --git a/qcsrc/common/items.qc b/qcsrc/common/items.qc new file mode 100644 index 000000000..19173079f --- /dev/null +++ b/qcsrc/common/items.qc @@ -0,0 +1,251 @@ +// WEAPON PLUGIN SYSTEM +entity weapon_info[WEP_MAXCOUNT]; +entity dummy_weapon_info; + +#if WEP_MAXCOUNT > 72 +# error Kein Weltraum links auf dem Gerät +#endif + +WepSet WepSet_FromWeapon(float a) { + a -= WEP_FIRST; +#if WEP_MAXCOUNT > 24 + if(a >= 24) { + a -= 24; +#if WEP_MAXCOUNT > 48 + if(a >= 24) { + a -= 24; + return '0 0 1' * power2of(a); + } +#endif + return '0 1 0' * power2of(a); + } +#endif + return '1 0 0' * power2of(a); +} +#ifdef SVQC +void WepSet_AddStat() +{ + addstat(STAT_WEAPONS, AS_INT, weapons_x); +#if WEP_MAXCOUNT > 24 + addstat(STAT_WEAPONS2, AS_INT, weapons_y); +#if WEP_MAXCOUNT > 48 + addstat(STAT_WEAPONS3, AS_INT, weapons_z); +#endif +#endif +} +void WriteWepSet(float dst, WepSet w) +{ +#if WEP_MAXCOUNT > 48 + WriteInt72_t(dst, w); +#elif WEP_MAXCOUNT > 24 + WriteInt48_t(dst, w); +#else + WriteInt24_t(dst, w_x); +#endif +} +#endif +#ifdef CSQC +WepSet WepSet_GetFromStat() +{ + WepSet w = '0 0 0'; + w_x = getstati(STAT_WEAPONS); +#if WEP_MAXCOUNT > 24 + w_y = getstati(STAT_WEAPONS2); +#if WEP_MAXCOUNT > 48 + w_z = getstati(STAT_WEAPONS3); +#endif +#endif + return w; +} +WepSet ReadWepSet() +{ +#if WEP_MAXCOUNT > 48 + return ReadInt72_t(); +#elif WEP_MAXCOUNT > 24 + return ReadInt48_t(); +#else + return ReadInt24_t() * '1 0 0'; +#endif +} +#endif + +void register_weapon(float id, WepSet bit, float(float) func, float ammotype, float i, float weapontype, float pickupbasevalue, string modelname, string shortname, string wname) +{ + entity e; + weapon_info[id - 1] = e = spawn(); + e.classname = "weapon_info"; + e.weapon = id; + e.weapons = bit; + e.netname = shortname; + e.message = wname; + e.items = ammotype; + e.weapon_func = func; + e.mdl = modelname; + e.model = strzone(strcat("models/weapons/g_", modelname, ".md3")); + e.spawnflags = weapontype; + e.model2 = strzone(strcat("wpn-", e.mdl)); + e.impulse = i; + e.bot_pickupbasevalue = pickupbasevalue; + if(ammotype & IT_SHELLS) + e.ammo_field = ammo_shells; + else if(ammotype & IT_NAILS) + e.ammo_field = ammo_nails; + else if(ammotype & IT_ROCKETS) + e.ammo_field = ammo_rockets; + else if(ammotype & IT_CELLS) + e.ammo_field = ammo_cells; + else if(ammotype & IT_FUEL) + e.ammo_field = ammo_fuel; + else + e.ammo_field = ammo_batteries; +} +float w_null(float dummy) +{ + return 0; +} +void register_weapons_done() +{ + dummy_weapon_info = spawn(); + dummy_weapon_info.classname = "weapon_info"; + dummy_weapon_info.weapon = 0; // you can recognize dummies by this + dummy_weapon_info.weapons = '0 0 0'; + dummy_weapon_info.netname = ""; + dummy_weapon_info.message = "AOL CD Thrower"; + dummy_weapon_info.items = 0; + dummy_weapon_info.weapon_func = w_null; + dummy_weapon_info.mdl = ""; + dummy_weapon_info.model = ""; + dummy_weapon_info.spawnflags = 0; + dummy_weapon_info.model2 = ""; + dummy_weapon_info.impulse = -1; + dummy_weapon_info.bot_pickupbasevalue = 0; + + float i; + weaponorder_byid = ""; + for(i = WEP_MAXCOUNT; i >= 1; --i) + if(weapon_info[i-1]) + weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i)); + weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1)); +} +entity get_weaponinfo(float id) +{ + entity w; + if(id < WEP_FIRST || id > WEP_LAST) + return dummy_weapon_info; + w = weapon_info[id - 1]; + if(w) + return w; + return dummy_weapon_info; +} +string W_FixWeaponOrder(string order, float complete) +{ + return fixPriorityList(order, WEP_FIRST, WEP_LAST, 230 - WEP_FIRST, complete); +} +string W_NameWeaponOrder_MapFunc(string s) +{ + entity wi; + if(s == "0" || stof(s)) + { + wi = get_weaponinfo(stof(s)); + if(wi != dummy_weapon_info) + return wi.netname; + } + return s; +} +string W_NameWeaponOrder(string order) +{ + return mapPriorityList(order, W_NameWeaponOrder_MapFunc); +} +string W_NumberWeaponOrder_MapFunc(string s) +{ + float i; + if(s == "0" || stof(s)) + return s; + for(i = WEP_FIRST; i <= WEP_LAST; ++i) + if(s == get_weaponinfo(i).netname) + return ftos(i); + return s; +} +string W_NumberWeaponOrder(string order) +{ + return mapPriorityList(order, W_NumberWeaponOrder_MapFunc); +} + +float W_FixWeaponOrder_BuildImpulseList_buf[WEP_MAXCOUNT]; +string W_FixWeaponOrder_BuildImpulseList_order; +void W_FixWeaponOrder_BuildImpulseList_swap(float i, float j, entity pass) +{ + float h; + h = W_FixWeaponOrder_BuildImpulseList_buf[i]; + W_FixWeaponOrder_BuildImpulseList_buf[i] = W_FixWeaponOrder_BuildImpulseList_buf[j]; + W_FixWeaponOrder_BuildImpulseList_buf[j] = h; +} +float W_FixWeaponOrder_BuildImpulseList_cmp(float i, float j, entity pass) +{ + entity e1, e2; + float d; + e1 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[i]); + e2 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[j]); + d = mod(e1.impulse + 9, 10) - mod(e2.impulse + 9, 10); + if(d != 0) + return -d; // high impulse first! + return + strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[i]), 0) + - + strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[j]), 0) + ; // low char index first! +} +string W_FixWeaponOrder_BuildImpulseList(string o) +{ + float i; + W_FixWeaponOrder_BuildImpulseList_order = o; + for(i = WEP_FIRST; i <= WEP_LAST; ++i) + W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST] = i; + heapsort(WEP_LAST - WEP_FIRST + 1, W_FixWeaponOrder_BuildImpulseList_swap, W_FixWeaponOrder_BuildImpulseList_cmp, world); + o = ""; + for(i = WEP_FIRST; i <= WEP_LAST; ++i) + o = strcat(o, " ", ftos(W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST])); + W_FixWeaponOrder_BuildImpulseList_order = string_null; + return substring(o, 1, -1); +} + +string W_FixWeaponOrder_AllowIncomplete(string order) +{ + return W_FixWeaponOrder(order, 0); +} + +string W_FixWeaponOrder_ForceComplete(string order) +{ + if(order == "") + order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority")); + return W_FixWeaponOrder(order, 1); +} + +void W_RandomWeapons(entity e, float n) +{ + float i, j; + WepSet remaining; + WepSet result; + remaining = e.weapons; + result = '0 0 0'; + for(i = 0; i < n; ++i) + { + RandomSelection_Init(); + for(j = WEP_FIRST; j <= WEP_LAST; ++j) + if(remaining & WepSet_FromWeapon(j)) + RandomSelection_Add(world, j, string_null, 1, 1); + result |= WepSet_FromWeapon(RandomSelection_chosen_float); + remaining &= ~WepSet_FromWeapon(RandomSelection_chosen_float); + } + e.weapons = result; +} + +string W_Name(float weaponid) +{ + return (get_weaponinfo(weaponid)).message; +} + +float W_AmmoItemCode(float wpn) +{ + return (get_weaponinfo(wpn)).items & IT_AMMO; +} diff --git a/qcsrc/common/items.qh b/qcsrc/common/items.qh new file mode 100644 index 000000000..264c9ca73 --- /dev/null +++ b/qcsrc/common/items.qh @@ -0,0 +1,151 @@ +const float BOT_PICKUP_RATING_LOW = 2500; +const float BOT_PICKUP_RATING_MID = 5000; +const float BOT_PICKUP_RATING_HIGH = 10000; + +const float WEP_TYPE_OTHER = 0x00; // not for damaging people +const float WEP_TYPE_SPLASH = 0x01; // splash damage +const float WEP_TYPE_HITSCAN = 0x02; // hitscan +const float WEP_TYPEMASK = 0x0F; +const float WEP_FLAG_CANCLIMB = 0x10; // can be used for movement +const float WEP_FLAG_NORMAL = 0x20; // in "most weapons" set +const float WEP_FLAG_HIDDEN = 0x40; // hides from menu +const float WEP_FLAG_RELOADABLE = 0x80; // can has reload +const float WEP_FLAG_SUPERWEAPON = 0x100; // powerup timer +const float WEP_FLAG_MUTATORBLOCKED = 0x200; // hides from impulse 99 etc. (mutators are allowed to clear this flag) + +const float IT_UNLIMITED_WEAPON_AMMO = 1; +// when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup. +const float IT_UNLIMITED_SUPERWEAPONS = 2; +// when this bit is set, superweapons don't expire. Checkpoints can give this powerup. +const float IT_CTF_SHIELDED = 4; // set for the flag shield +const float IT_USING_JETPACK = 8; // confirmation that button is pressed +const float IT_JETPACK = 16; // actual item +const float IT_FUEL_REGEN = 32; // fuel regeneration trigger +WANT_CONST float IT_SHELLS = 256; +WANT_CONST float IT_NAILS = 512; +WANT_CONST float IT_ROCKETS = 1024; +WANT_CONST float IT_CELLS = 2048; +const float IT_SUPERWEAPON = 4096; +const float IT_FUEL = 128; +const float IT_STRENGTH = 8192; +const float IT_INVINCIBLE = 16384; +const float IT_HEALTH = 32768; +// union: + // for items: + WANT_CONST float IT_KEY1 = 131072; + WANT_CONST float IT_KEY2 = 262144; + // for players: + const float IT_RED_FLAG_TAKEN = 32768; + const float IT_RED_FLAG_LOST = 65536; + const float IT_RED_FLAG_CARRYING = 98304; + const float IT_BLUE_FLAG_TAKEN = 131072; + const float IT_BLUE_FLAG_LOST = 262144; + const float IT_BLUE_FLAG_CARRYING = 393216; +// end +const float IT_5HP = 524288; +const float IT_25HP = 1048576; +const float IT_ARMOR_SHARD = 2097152; +const float IT_ARMOR = 4194304; + +const float IT_AMMO = 3968; // IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS | IT_FUEL; +const float IT_PICKUPMASK = 51; // IT_FUEL_REGEN | IT_JETPACK | IT_UNLIMITED_AMMO; // strength and invincible are handled separately +const float IT_UNLIMITED_AMMO = 3; // IT_UNLIMITED_SUPERWEAPONS | IT_UNLIMITED_WEAPON_AMMO; + +// variables: +string weaponorder_byid; + +// functions: +entity get_weaponinfo(float id); +string W_FixWeaponOrder(string order, float complete); +string W_NameWeaponOrder(string order); +string W_NumberWeaponOrder(string order); + +// ammo types +.float ammo_shells; +.float ammo_nails; +.float ammo_rockets; +.float ammo_cells; +.float ammo_fuel; +.float ammo_batteries; // dummy + +// Weapon sets +typedef vector WepSet; +WepSet WepSet_FromWeapon(float a); +#ifdef SVQC +void WepSet_AddStat(); +void WriteWepSet(float dest, WepSet w); +#endif +#ifdef CSQC +WepSet WepSet_GetFromStat(); +WepSet ReadWepSet(); +#endif + +// Weapon name macros +#define WEP_FIRST 1 +#define WEP_MAXCOUNT 24 // Increase as needed. Can be up to three times as much. +float WEP_COUNT; +float WEP_LAST; +WepSet WEPSET_ALL; +WepSet WEPSET_SUPERWEAPONS; + +// entity properties of weaponinfo: +.float weapon; // WEP_... +.WepSet weapons; // WEPSET_... +.string netname; // short name +.string message; // human readable name +.float items; // IT_... +.float(float) weapon_func; // w_... +.string mdl; // modelname without g_, v_, w_ +.string model; // full name of g_ model +.float spawnflags; // WEPSPAWNFLAG_... combined +.float impulse; // weapon impulse +.float bot_pickupbasevalue; // bot weapon priority +.string model2; // wpn- sprite name +..float ammo_field; // main ammo field + +// dynamic weapon adding +float w_null(float dummy); +void register_weapon(float id, WepSet bit, float(float) func, float ammotype, float i, float weapontype, float pickupbasevalue, string modelname, string shortname, string wname); +void register_weapons_done(); + +#define REGISTER_WEAPON_2(id,bit,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname) \ + float id; \ + WepSet bit; \ + float func(float); \ + void RegisterWeapons_##id() \ + { \ + WEP_LAST = (id = WEP_FIRST + WEP_COUNT); \ + bit = WepSet_FromWeapon(id); \ + WEPSET_ALL |= bit; \ + if((weapontype) & WEP_FLAG_SUPERWEAPON) \ + WEPSET_SUPERWEAPONS |= bit; \ + ++WEP_COUNT; \ + register_weapon(id,bit,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname); \ + } \ + ACCUMULATE_FUNCTION(RegisterWeapons, RegisterWeapons_##id) +#ifdef MENUQC +#define REGISTER_WEAPON(id,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname) \ + REGISTER_WEAPON_2(WEP_##id,WEPSET_##id,w_null,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname) +#else +#define REGISTER_WEAPON(id,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname) \ + REGISTER_WEAPON_2(WEP_##id,WEPSET_##id,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname) +#endif + +#include "../server/w_all.qc" + +#undef REGISTER_WEAPON +ACCUMULATE_FUNCTION(RegisterWeapons, register_weapons_done); + + +string W_FixWeaponOrder(string order, float complete); +string W_NumberWeaponOrder(string order); +string W_NameWeaponOrder(string order); +string W_FixWeaponOrder_BuildImpulseList(string o); +string W_FixWeaponOrder_AllowIncomplete(string order); +string W_FixWeaponOrder_ForceComplete(string order); + +void W_RandomWeapons(entity e, float n); + +string W_Name(float weaponid); + +float W_AmmoItemCode(float wpn); diff --git a/qcsrc/common/monsters/monster/mage.qc b/qcsrc/common/monsters/monster/mage.qc index 3adc59a30..26bb0a9af 100644 --- a/qcsrc/common/monsters/monster/mage.qc +++ b/qcsrc/common/monsters/monster/mage.qc @@ -70,7 +70,7 @@ float friend_needshelp(entity e) switch(self.skin) { case 0: return (e.health < autocvar_g_balance_health_regenstable); - case 1: return ((e.ammo_cells && e.ammo_cells < g_pickup_cells_max) || (e.ammo_plasma && e.ammo_plasma < g_pickup_plasma_max) || (e.ammo_rockets && e.ammo_rockets < g_pickup_rockets_max) || (e.ammo_nails && e.ammo_nails < g_pickup_nails_max) || (e.ammo_shells && e.ammo_shells < g_pickup_shells_max)); + case 1: return ((e.ammo_cells && e.ammo_cells < g_pickup_cells_max) || (e.ammo_rockets && e.ammo_rockets < g_pickup_rockets_max) || (e.ammo_nails && e.ammo_nails < g_pickup_nails_max) || (e.ammo_shells && e.ammo_shells < g_pickup_shells_max)); case 2: return (e.armorvalue < autocvar_g_balance_armor_regenstable); case 3: return (e.health > 0); } @@ -87,7 +87,7 @@ void mage_spike_explode() self.realowner.mage_spike = world; pointparticles(particleeffectnum("explosion_small"), self.origin, '0 0 0', 1); - RadiusDamage (self, self.realowner, (autocvar_g_monster_mage_attack_spike_damage), (autocvar_g_monster_mage_attack_spike_damage) * 0.5, (autocvar_g_monster_mage_attack_spike_radius), world, world, 0, DEATH_MONSTER_MAGE, other); + RadiusDamage (self, self.realowner, (autocvar_g_monster_mage_attack_spike_damage), (autocvar_g_monster_mage_attack_spike_damage) * 0.5, (autocvar_g_monster_mage_attack_spike_radius), world, 0, DEATH_MONSTER_MAGE, other); remove (self); } @@ -209,7 +209,6 @@ void mage_heal() break; case 1: if(head.ammo_cells) head.ammo_cells = bound(head.ammo_cells, head.ammo_cells + 1, g_pickup_cells_max); - if(head.ammo_plasma) head.ammo_plasma = bound(head.ammo_plasma, head.ammo_plasma + 1, g_pickup_plasma_max); if(head.ammo_rockets) head.ammo_rockets = bound(head.ammo_rockets, head.ammo_rockets + 1, g_pickup_rockets_max); if(head.ammo_shells) head.ammo_shells = bound(head.ammo_shells, head.ammo_shells + 2, g_pickup_shells_max); if(head.ammo_nails) head.ammo_nails = bound(head.ammo_nails, head.ammo_nails + 5, g_pickup_nails_max); @@ -249,7 +248,7 @@ void mage_heal() void mage_push() { sound(self, CH_SHOTS, "weapons/tagexp1.wav", 1, ATTEN_NORM); - RadiusDamage (self, self, (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_radius), world, world, (autocvar_g_monster_mage_attack_push_force), DEATH_MONSTER_MAGE, self.enemy); + RadiusDamage (self, self, (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_radius), world, (autocvar_g_monster_mage_attack_push_force), DEATH_MONSTER_MAGE, self.enemy); pointparticles(particleeffectnum("TE_EXPLOSION"), self.origin, '0 0 0', 1); self.frame = mage_anim_attack; diff --git a/qcsrc/common/monsters/monster/shambler.qc b/qcsrc/common/monsters/monster/shambler.qc index 7c46a1da1..0e82fe8d2 100644 --- a/qcsrc/common/monsters/monster/shambler.qc +++ b/qcsrc/common/monsters/monster/shambler.qc @@ -74,7 +74,7 @@ void shambler_lightning_explode() if(self.movetype == MOVETYPE_NONE) self.velocity = self.oldvelocity; - RadiusDamage (self, self.realowner, (autocvar_g_monster_shambler_attack_lightning_damage), (autocvar_g_monster_shambler_attack_lightning_damage), (autocvar_g_monster_shambler_attack_lightning_radius), world, world, (autocvar_g_monster_shambler_attack_lightning_force), self.projectiledeathtype, other); + RadiusDamage (self, self.realowner, (autocvar_g_monster_shambler_attack_lightning_damage), (autocvar_g_monster_shambler_attack_lightning_damage), (autocvar_g_monster_shambler_attack_lightning_radius), world, (autocvar_g_monster_shambler_attack_lightning_force), self.projectiledeathtype, other); for(head = findradius(self.origin, (autocvar_g_monster_shambler_attack_lightning_radius_zap)); head; head = head.chain) if(head != self.realowner) if(head.takedamage) { @@ -148,7 +148,7 @@ void shambler_lightning() gren.event_damage = shambler_lightning_damage; gren.damagedbycontents = TRUE; gren.missile_flags = MIF_SPLASH | MIF_ARC; - W_SetupProjVelocity_Explicit(gren, v_forward, v_up, (autocvar_g_monster_shambler_attack_lightning_speed), (autocvar_g_monster_shambler_attack_lightning_speed_up), 0, 0, FALSE); + W_SetupProjectileVelocityEx(gren, v_forward, v_up, (autocvar_g_monster_shambler_attack_lightning_speed), (autocvar_g_monster_shambler_attack_lightning_speed_up), 0, 0, FALSE); gren.angles = vectoangles (gren.velocity); gren.flags = FL_PROJECTILE; @@ -222,7 +222,7 @@ float m_shambler(float req) self.monster_loot = spawnfunc_item_health_mega; self.monster_attackfunc = shambler_attack; self.frame = shambler_anim_stand; - self.weapon = WEP_VORTEX; + self.weapon = WEP_NEX; return TRUE; } diff --git a/qcsrc/common/monsters/monster/spider.qc b/qcsrc/common/monsters/monster/spider.qc index c6c454547..7e35b8b16 100644 --- a/qcsrc/common/monsters/monster/spider.qc +++ b/qcsrc/common/monsters/monster/spider.qc @@ -35,7 +35,7 @@ void spider_web_explode() if(self) { pointparticles(particleeffectnum("electro_impact"), self.origin, '0 0 0', 1); - RadiusDamage(self, self.realowner, 0, 0, 25, world, world, 25, self.projectiledeathtype, world); + RadiusDamage(self, self.realowner, 0, 0, 25, world, 25, self.projectiledeathtype, world); for(e = findradius(self.origin, 25); e; e = e.chain) if(e != self) if(e.takedamage && e.deadflag == DEAD_NO) if(e.health > 0) if(e.monsterid != MON_SPIDER) e.spider_slowness = time + (autocvar_g_monster_spider_attack_web_damagetime); @@ -72,7 +72,7 @@ void spider_shootweb() //proj.glow_size = 50; //proj.glow_color = 45; proj.movetype = MOVETYPE_BOUNCE; - W_SetupProjVelocity_Explicit(proj, v_forward, v_up, (autocvar_g_monster_spider_attack_web_speed), (autocvar_g_monster_spider_attack_web_speed_up), 0, 0, FALSE); + W_SetupProjectileVelocityEx(proj, v_forward, v_up, (autocvar_g_monster_spider_attack_web_speed), (autocvar_g_monster_spider_attack_web_speed_up), 0, 0, FALSE); proj.touch = spider_web_touch; setsize(proj, '-4 -4 -4', '4 4 4'); proj.takedamage = DAMAGE_NO; diff --git a/qcsrc/common/monsters/monster/wyvern.qc b/qcsrc/common/monsters/monster/wyvern.qc index a44f6d9c7..ed4962d06 100644 --- a/qcsrc/common/monsters/monster/wyvern.qc +++ b/qcsrc/common/monsters/monster/wyvern.qc @@ -35,7 +35,7 @@ void wyvern_fireball_explode() { pointparticles(particleeffectnum("fireball_explode"), self.origin, '0 0 0', 1); - RadiusDamage(self, self.realowner, (autocvar_g_monster_wyvern_attack_fireball_damage), (autocvar_g_monster_wyvern_attack_fireball_edgedamage), (autocvar_g_monster_wyvern_attack_fireball_force), world, world, (autocvar_g_monster_wyvern_attack_fireball_radius), self.projectiledeathtype, world); + RadiusDamage(self, self.realowner, (autocvar_g_monster_wyvern_attack_fireball_damage), (autocvar_g_monster_wyvern_attack_fireball_edgedamage), (autocvar_g_monster_wyvern_attack_fireball_force), world, (autocvar_g_monster_wyvern_attack_fireball_radius), self.projectiledeathtype, world); for(e = world; (e = findfloat(e, takedamage, DAMAGE_AIM)); ) if(vlen(e.origin - self.origin) <= (autocvar_g_monster_wyvern_attack_fireball_radius)) Fire_AddDamage(e, self, 5 * Monster_SkillModifier(), (autocvar_g_monster_wyvern_attack_fireball_damagetime), self.projectiledeathtype); diff --git a/qcsrc/common/monsters/sv_monsters.qc b/qcsrc/common/monsters/sv_monsters.qc index fd966f5d2..6d06de50e 100644 --- a/qcsrc/common/monsters/sv_monsters.qc +++ b/qcsrc/common/monsters/sv_monsters.qc @@ -335,7 +335,7 @@ void Monster_CheckMinibossFlag () self.health += autocvar_g_monsters_miniboss_healthboost; self.effects |= EF_RED; if(!self.weapon) - self.weapon = WEP_VORTEX; + self.weapon = WEP_NEX; } } diff --git a/qcsrc/common/notifications.qh b/qcsrc/common/notifications.qh index 27e2f7ede..60cc622fa 100644 --- a/qcsrc/common/notifications.qh +++ b/qcsrc/common/notifications.qh @@ -497,19 +497,13 @@ void Send_Notification_WOCOVA( MSG_INFO_NOTIF(1, INFO_WATERMARK, 1, 0, "s1", "", "", _("^F3SVQC Build information: ^F4%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_ACCORDEON_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapontuba", _("^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Accordeon%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_ACCORDEON_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weapontuba", _("^BG%s^K1 hurt their own ears with the @!#%%'n Accordeon%s%s"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_ARC_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponhlac", _("^BG%s%s^K1 was electrocuted by ^BG%s^K1's Arc%s%s"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_BLASTER_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponlaser", _("^BG%s%s^K1 was shot to death by ^BG%s^K1's Blaster%s%s"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_BLASTER_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponlaser", _("^BG%s^K1 shot themself to hell with their Blaster%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_CRYLINK_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponcrylink", _("^BG%s%s^K1 felt the strong pull of ^BG%s^K1's Crylink%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_CRYLINK_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponcrylink", _("^BG%s^K1 felt the strong pull of their Crylink%s%s"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_DEVASTATOR_MURDER_DIRECT, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrocketlauncher", _("^BG%s%s^K1 ate ^BG%s^K1's rocket%s%s"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_DEVASTATOR_MURDER_SPLASH, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrocketlauncher", _("^BG%s%s^K1 got too close ^BG%s^K1's rocket%s%s"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_DEVASTATOR_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponrocketlauncher", _("^BG%s^K1 blew themself up with their Devastator%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_MURDER_BOLT, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponelectro", _("^BG%s%s^K1 was blasted by ^BG%s^K1's Electro bolt%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_MURDER_COMBO, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponelectro", _("^BG%s%s^K1 felt the electrifying air of ^BG%s^K1's Electro combo%s%s"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_MURDER_ORBS, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponelectro", _("^BG%s%s^K1 got too close to ^BG%s^K1's Electro orb%s%s"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_SUICIDE_BOLT, 2, 1, "s1 s2loc spree_lost", "s1", "weaponelectro", _("^BG%s^K1 played with Electro bolts%s%s"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_SUICIDE_ORBS, 2, 1, "s1 s2loc spree_lost", "s1", "weaponelectro", _("^BG%s^K1 could not remember where they put their Electro orb%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_MURDER_ORBS, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponelectro", _("^BG%s%s^K1 got too close to ^BG%s^K1's Electro plasma%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_SUICIDE_BOLT, 2, 1, "s1 s2loc spree_lost", "s1", "weaponelectro", _("^BG%s^K1 played with Electro plasma%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_SUICIDE_ORBS, 2, 1, "s1 s2loc spree_lost", "s1", "weaponelectro", _("^BG%s^K1 could not remember where they put their Electro plasma%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_FIREBALL_MURDER_BLAST, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponfireball", _("^BG%s%s^K1 got too close to ^BG%s^K1's fireball%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_FIREBALL_MURDER_FIREMINE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponfireball", _("^BG%s%s^K1 got burnt by ^BG%s^K1's firemine%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_FIREBALL_SUICIDE_BLAST, 2, 1, "s1 s2loc spree_lost", "s1", "weaponfireball", _("^BG%s^K1 should have used a smaller gun%s%s"), "") \ @@ -522,30 +516,33 @@ void Send_Notification_WOCOVA( MSG_INFO_NOTIF(1, INFO_WEAPON_HOOK_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponhook", _("^BG%s%s^K1 was caught in ^BG%s^K1's Hook gravity bomb%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_KLEINBOTTLE_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapontuba", _("^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Klein Bottle%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_KLEINBOTTLE_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weapontuba", _("^BG%s^K1 hurt their own ears with the @!#%%'n Klein Bottle%s%s"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_MACHINEGUN_MURDER_SNIPE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponuzi", _("^BG%s%s^K1 was sniped by ^BG%s^K1's Machine Gun%s%s"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_MACHINEGUN_MURDER_SPRAY, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponuzi", _("^BG%s%s^K1 was riddled full of holes by ^BG%s^K1's Machine Gun%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_LASER_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponlaser", _("^BG%s%s^K1 was shot to death by ^BG%s^K1's Laser%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_LASER_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponlaser", _("^BG%s^K1 shot themself to hell with their Laser%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_MINELAYER_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponminelayer", _("^BG%s%s^K1 got too close to ^BG%s^K1's mine%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_MINELAYER_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponminelayer", _("^BG%s^K1 forgot about their mine%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_MINSTANEX_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponminstanex", _("^BG%s%s^K1 has been vaporized by ^BG%s^K1's Minstanex%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_MORTAR_MURDER_BOUNCE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapongrenadelauncher", _("^BG%s%s^K1 got too close to ^BG%s^K1's Mortar grenade%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_MORTAR_MURDER_EXPLODE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapongrenadelauncher", _("^BG%s%s^K1 ate ^BG%s^K1's Mortar grenade%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_MORTAR_SUICIDE_BOUNCE, 2, 1, "s1 s2loc spree_lost", "s1", "weapongrenadelauncher", _("^BG%s^K1 didn't see their own Mortar grenade%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_MORTAR_SUICIDE_EXPLODE, 2, 1, "s1 s2loc spree_lost", "s1", "weapongrenadelauncher", _("^BG%s^K1 blew themself up with their own Mortar%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_NEX_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponnex", _("^BG%s%s^K1 has been vaporized by ^BG%s^K1's Nex%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrifle", _("^BG%s%s^K1 was sniped with a Rifle by ^BG%s^K1%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER_HAIL, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrifle", _("^BG%s%s^K1 died in ^BG%s^K1's Rifle bullet hail%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER_HAIL_PIERCING, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrifle", _("^BG%s%s^K1 failed to hide from ^BG%s^K1's Rifle bullet hail%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER_PIERCING, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrifle", _("^BG%s%s^K1 failed to hide from ^BG%s^K1's Rifle%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_ROCKETLAUNCHER_MURDER_DIRECT, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrocketlauncher", _("^BG%s%s^K1 ate ^BG%s^K1's rocket%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_ROCKETLAUNCHER_MURDER_SPLASH, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponrocketlauncher", _("^BG%s%s^K1 got too close ^BG%s^K1's rocket%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_ROCKETLAUNCHER_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponrocketlauncher", _("^BG%s^K1 blew themself up with their Rocketlauncher%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_SEEKER_MURDER_SPRAY, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponseeker", _("^BG%s%s^K1 was pummeled by ^BG%s^K1's Seeker rockets%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_SEEKER_MURDER_TAG, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponseeker", _("^BG%s%s^K1 was tagged by ^BG%s^K1's Seeker%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_SEEKER_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weaponseeker", _("^BG%s^K1 played with tiny Seeker rockets%s%s"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_SHOCKWAVE_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponshotgun", _("^BG%s%s^K1 was gunned down by ^BG%s^K1's Shockwave%s%s"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_SHOCKWAVE_MURDER_SLAP, 3, 2, "spree_inf s2 s1 s3loc spree_end", "s2 s1", "notify_melee_shotgun", _("^BG%s%s^K1 slapped ^BG%s^K1 around a bit with a large Shockwave%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_SHOTGUN_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponshotgun", _("^BG%s%s^K1 was gunned down by ^BG%s^K1's Shotgun%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_SHOTGUN_MURDER_SLAP, 3, 2, "spree_inf s2 s1 s3loc spree_end", "s2 s1", "notify_melee_shotgun", _("^BG%s%s^K1 slapped ^BG%s^K1 around a bit with a large Shotgun%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_THINKING_WITH_PORTALS, 2, 1, "s1 s2loc spree_lost", "s1", "notify_selfkill", _("^BG%s^K1 is now thinking with portals%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_TUBA_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weapontuba", _("^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Tuba%s%s"), "") \ MSG_INFO_NOTIF(1, INFO_WEAPON_TUBA_SUICIDE, 2, 1, "s1 s2loc spree_lost", "s1", "weapontuba", _("^BG%s^K1 hurt their own ears with the @!#%%'n Tuba%s%s"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_VAPORIZER_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponminstanex", _("^BG%s%s^K1 has been sublimated by ^BG%s^K1's Vaporizer%s%s"), "") \ - MSG_INFO_NOTIF(1, INFO_WEAPON_VORTEX_MURDER, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponnex", _("^BG%s%s^K1 has been vaporized by ^BG%s^K1's Vortex%s%s"), "") + MSG_INFO_NOTIF(1, INFO_WEAPON_UZI_MURDER_SNIPE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponuzi", _("^BG%s%s^K1 was sniped by ^BG%s^K1's Machine Gun%s%s"), "") \ + MSG_INFO_NOTIF(1, INFO_WEAPON_UZI_MURDER_SPRAY, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "weaponuzi", _("^BG%s%s^K1 was riddled full of holes by ^BG%s^K1's Machine Gun%s%s"), "") #define MULTITEAM_CENTER2(default,prefix,strnum,flnum,args,cpid,durcnt,normal,gentle) \ MSG_CENTER_NOTIF(default, prefix##RED, strnum, flnum, args, cpid, durcnt, TCR(normal, COL_TEAM_1, strtoupper(NAME_TEAM_1)), TCR(gentle, COL_TEAM_1, strtoupper(NAME_TEAM_1))) \ @@ -812,14 +809,8 @@ void Send_Notification_WOCOVA( MSG_MULTI_NOTIF(1, MULTI_MINSTA_FINDAMMO, ANNCE_NUM_10, NO_MSG, CENTER_MINSTA_FINDAMMO_FIRST) \ MSG_MULTI_NOTIF(1, WEAPON_ACCORDEON_MURDER, NO_MSG, INFO_WEAPON_ACCORDEON_MURDER, NO_MSG) \ MSG_MULTI_NOTIF(1, WEAPON_ACCORDEON_SUICIDE, NO_MSG, INFO_WEAPON_ACCORDEON_SUICIDE, CENTER_DEATH_SELF_GENERIC) \ - MSG_MULTI_NOTIF(1, WEAPON_ARC_MURDER, NO_MSG, INFO_WEAPON_ARC_MURDER, NO_MSG) \ - MSG_MULTI_NOTIF(1, WEAPON_BLASTER_MURDER, NO_MSG, INFO_WEAPON_BLASTER_MURDER, NO_MSG) \ - MSG_MULTI_NOTIF(1, WEAPON_BLASTER_SUICIDE, NO_MSG, INFO_WEAPON_BLASTER_SUICIDE, CENTER_DEATH_SELF_GENERIC) \ MSG_MULTI_NOTIF(1, WEAPON_CRYLINK_MURDER, NO_MSG, INFO_WEAPON_CRYLINK_MURDER, NO_MSG) \ MSG_MULTI_NOTIF(1, WEAPON_CRYLINK_SUICIDE, NO_MSG, INFO_WEAPON_CRYLINK_SUICIDE, CENTER_DEATH_SELF_GENERIC) \ - MSG_MULTI_NOTIF(1, WEAPON_DEVASTATOR_MURDER_DIRECT, NO_MSG, INFO_WEAPON_DEVASTATOR_MURDER_DIRECT, NO_MSG) \ - MSG_MULTI_NOTIF(1, WEAPON_DEVASTATOR_MURDER_SPLASH, NO_MSG, INFO_WEAPON_DEVASTATOR_MURDER_SPLASH, NO_MSG) \ - MSG_MULTI_NOTIF(1, WEAPON_DEVASTATOR_SUICIDE, NO_MSG, INFO_WEAPON_DEVASTATOR_SUICIDE, CENTER_DEATH_SELF_GENERIC) \ MSG_MULTI_NOTIF(1, WEAPON_ELECTRO_MURDER_BOLT, NO_MSG, INFO_WEAPON_ELECTRO_MURDER_BOLT, NO_MSG) \ MSG_MULTI_NOTIF(1, WEAPON_ELECTRO_MURDER_COMBO, NO_MSG, INFO_WEAPON_ELECTRO_MURDER_COMBO, NO_MSG) \ MSG_MULTI_NOTIF(1, WEAPON_ELECTRO_MURDER_ORBS, NO_MSG, INFO_WEAPON_ELECTRO_MURDER_ORBS, NO_MSG) \ @@ -837,30 +828,33 @@ void Send_Notification_WOCOVA( MSG_MULTI_NOTIF(1, WEAPON_HOOK_MURDER, NO_MSG, INFO_WEAPON_HOOK_MURDER, NO_MSG) \ MSG_MULTI_NOTIF(1, WEAPON_KLEINBOTTLE_MURDER, NO_MSG, INFO_WEAPON_KLEINBOTTLE_MURDER, NO_MSG) \ MSG_MULTI_NOTIF(1, WEAPON_KLEINBOTTLE_SUICIDE, NO_MSG, INFO_WEAPON_KLEINBOTTLE_SUICIDE, CENTER_DEATH_SELF_GENERIC) \ - MSG_MULTI_NOTIF(1, WEAPON_MACHINEGUN_MURDER_SNIPE, NO_MSG, INFO_WEAPON_MACHINEGUN_MURDER_SNIPE, NO_MSG) \ - MSG_MULTI_NOTIF(1, WEAPON_MACHINEGUN_MURDER_SPRAY, NO_MSG, INFO_WEAPON_MACHINEGUN_MURDER_SPRAY, NO_MSG) \ + MSG_MULTI_NOTIF(1, WEAPON_LASER_MURDER, NO_MSG, INFO_WEAPON_LASER_MURDER, NO_MSG) \ + MSG_MULTI_NOTIF(1, WEAPON_LASER_SUICIDE, NO_MSG, INFO_WEAPON_LASER_SUICIDE, CENTER_DEATH_SELF_GENERIC) \ MSG_MULTI_NOTIF(1, WEAPON_MINELAYER_MURDER, NO_MSG, INFO_WEAPON_MINELAYER_MURDER, NO_MSG) \ MSG_MULTI_NOTIF(1, WEAPON_MINELAYER_SUICIDE, NO_MSG, INFO_WEAPON_MINELAYER_SUICIDE, CENTER_DEATH_SELF_GENERIC) \ + MSG_MULTI_NOTIF(1, WEAPON_MINSTANEX_MURDER, NO_MSG, INFO_WEAPON_MINSTANEX_MURDER, NO_MSG) \ MSG_MULTI_NOTIF(1, WEAPON_MORTAR_MURDER_BOUNCE, NO_MSG, INFO_WEAPON_MORTAR_MURDER_BOUNCE, NO_MSG) \ MSG_MULTI_NOTIF(1, WEAPON_MORTAR_MURDER_EXPLODE, NO_MSG, INFO_WEAPON_MORTAR_MURDER_EXPLODE, NO_MSG) \ MSG_MULTI_NOTIF(1, WEAPON_MORTAR_SUICIDE_BOUNCE, NO_MSG, INFO_WEAPON_MORTAR_SUICIDE_BOUNCE, CENTER_DEATH_SELF_GENERIC) \ MSG_MULTI_NOTIF(1, WEAPON_MORTAR_SUICIDE_EXPLODE, NO_MSG, INFO_WEAPON_MORTAR_SUICIDE_EXPLODE, CENTER_DEATH_SELF_GENERIC) \ + MSG_MULTI_NOTIF(1, WEAPON_NEX_MURDER, NO_MSG, INFO_WEAPON_NEX_MURDER, NO_MSG) \ MSG_MULTI_NOTIF(1, WEAPON_RIFLE_MURDER, NO_MSG, INFO_WEAPON_RIFLE_MURDER, NO_MSG) \ MSG_MULTI_NOTIF(1, WEAPON_RIFLE_MURDER_HAIL, NO_MSG, INFO_WEAPON_RIFLE_MURDER_HAIL, NO_MSG) \ MSG_MULTI_NOTIF(1, WEAPON_RIFLE_MURDER_HAIL_PIERCING, NO_MSG, INFO_WEAPON_RIFLE_MURDER_HAIL_PIERCING, NO_MSG) \ MSG_MULTI_NOTIF(1, WEAPON_RIFLE_MURDER_PIERCING, NO_MSG, INFO_WEAPON_RIFLE_MURDER_PIERCING, NO_MSG) \ + MSG_MULTI_NOTIF(1, WEAPON_ROCKETLAUNCHER_MURDER_DIRECT, NO_MSG, INFO_WEAPON_ROCKETLAUNCHER_MURDER_DIRECT, NO_MSG) \ + MSG_MULTI_NOTIF(1, WEAPON_ROCKETLAUNCHER_MURDER_SPLASH, NO_MSG, INFO_WEAPON_ROCKETLAUNCHER_MURDER_SPLASH, NO_MSG) \ + MSG_MULTI_NOTIF(1, WEAPON_ROCKETLAUNCHER_SUICIDE, NO_MSG, INFO_WEAPON_ROCKETLAUNCHER_SUICIDE, CENTER_DEATH_SELF_GENERIC) \ MSG_MULTI_NOTIF(1, WEAPON_SEEKER_MURDER_SPRAY, NO_MSG, INFO_WEAPON_SEEKER_MURDER_SPRAY, NO_MSG) \ MSG_MULTI_NOTIF(1, WEAPON_SEEKER_MURDER_TAG, NO_MSG, INFO_WEAPON_SEEKER_MURDER_TAG, NO_MSG) \ MSG_MULTI_NOTIF(1, WEAPON_SEEKER_SUICIDE, NO_MSG, INFO_WEAPON_SEEKER_SUICIDE, CENTER_DEATH_SELF_GENERIC) \ - MSG_MULTI_NOTIF(1, WEAPON_SHOCKWAVE_MURDER, NO_MSG, INFO_WEAPON_SHOCKWAVE_MURDER, NO_MSG) \ - MSG_MULTI_NOTIF(1, WEAPON_SHOCKWAVE_MURDER_SLAP, NO_MSG, INFO_WEAPON_SHOCKWAVE_MURDER_SLAP, NO_MSG) \ MSG_MULTI_NOTIF(1, WEAPON_SHOTGUN_MURDER, NO_MSG, INFO_WEAPON_SHOTGUN_MURDER, NO_MSG) \ MSG_MULTI_NOTIF(1, WEAPON_SHOTGUN_MURDER_SLAP, NO_MSG, INFO_WEAPON_SHOTGUN_MURDER_SLAP, NO_MSG) \ MSG_MULTI_NOTIF(1, WEAPON_THINKING_WITH_PORTALS, NO_MSG, INFO_WEAPON_THINKING_WITH_PORTALS, CENTER_DEATH_SELF_GENERIC) \ MSG_MULTI_NOTIF(1, WEAPON_TUBA_MURDER, NO_MSG, INFO_WEAPON_TUBA_MURDER, NO_MSG) \ MSG_MULTI_NOTIF(1, WEAPON_TUBA_SUICIDE, NO_MSG, INFO_WEAPON_TUBA_SUICIDE, CENTER_DEATH_SELF_GENERIC) \ - MSG_MULTI_NOTIF(1, WEAPON_VAPORIZER_MURDER, NO_MSG, INFO_WEAPON_VAPORIZER_MURDER, NO_MSG) \ - MSG_MULTI_NOTIF(1, WEAPON_VORTEX_MURDER, NO_MSG, INFO_WEAPON_VORTEX_MURDER, NO_MSG) + MSG_MULTI_NOTIF(1, WEAPON_UZI_MURDER_SNIPE, NO_MSG, INFO_WEAPON_UZI_MURDER_SNIPE, NO_MSG) \ + MSG_MULTI_NOTIF(1, WEAPON_UZI_MURDER_SPRAY, NO_MSG, INFO_WEAPON_UZI_MURDER_SPRAY, NO_MSG) #define MULTITEAM_CHOICE2(default,challow,prefix,chtype,optiona,optionb) \ MSG_CHOICE_NOTIF(default, challow, prefix##RED, chtype, optiona##RED, optionb##RED) \ @@ -1024,7 +1018,7 @@ string arg_slot[NOTIF_MAX_ARGS]; ARG_CASE(ARG_CS_SV, "spree_inf", (autocvar_notification_show_sprees ? notif_arg_spree_inf(1, input, s2, f2) : "")) \ ARG_CASE(ARG_CS_SV, "spree_end", (autocvar_notification_show_sprees ? notif_arg_spree_inf(-1, "", "", f1) : "")) \ ARG_CASE(ARG_CS_SV, "spree_lost", (autocvar_notification_show_sprees ? notif_arg_spree_inf(-2, "", "", f1) : "")) \ - ARG_CASE(ARG_CS_SV, "item_wepname", WEP_NAME(f1)) \ + ARG_CASE(ARG_CS_SV, "item_wepname", W_Name(f1)) \ ARG_CASE(ARG_CS_SV, "item_buffname", sprintf("%s%s", rgb_to_hexcolor(Buff_Color(f1)), Buff_PrettyName(f1))) \ ARG_CASE(ARG_CS_SV, "item_wepammo", (s1 != "" ? sprintf(_(" with %s"), s1) : "")) \ ARG_CASE(ARG_DC, "item_centime", ftos(autocvar_notification_item_centerprinttime)) \ diff --git a/qcsrc/common/stats.qh b/qcsrc/common/stats.qh index 44a540b65..793582e12 100644 --- a/qcsrc/common/stats.qh +++ b/qcsrc/common/stats.qh @@ -52,10 +52,10 @@ const float STAT_SHOTORG = 46; // compressShotOrigin const float STAT_LEADLIMIT = 47; const float STAT_WEAPON_CLIPLOAD = 48; const float STAT_WEAPON_CLIPSIZE = 49; -const float STAT_VORTEX_CHARGE = 50; +const float STAT_NEX_CHARGE = 50; const float STAT_LAST_PICKUP = 51; const float STAT_HUD = 52; -const float STAT_VORTEX_CHARGEPOOL = 53; +const float STAT_NEX_CHARGEPOOL = 53; const float STAT_HIT_TIME = 54; const float STAT_TYPEHIT_TIME = 55; const float STAT_LAYED_MINES = 56; @@ -86,7 +86,7 @@ const float STAT_NADE_BONUS_TYPE = 80; const float STAT_NADE_BONUS_SCORE = 81; const float STAT_HEALING_ORB = 82; const float STAT_HEALING_ORB_ALPHA = 83; -const float STAT_PLASMA = 84; +// 84 empty? // 85 empty? // 86 empty? // 87 empty? diff --git a/qcsrc/common/util.qc b/qcsrc/common/util.qc index b5c98190e..c50a3ba53 100644 --- a/qcsrc/common/util.qc +++ b/qcsrc/common/util.qc @@ -2558,30 +2558,6 @@ void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t queue_start.FindConnectedComponent_processing = 0; } -#ifdef SVQC -vector combine_to_vector(float x, float y, float z) -{ - vector result; result_x = x; result_y = y; result_z = z; - return result; -} - -vector get_corner_position(entity box, float corner) -{ - switch(corner) - { - case 1: return combine_to_vector(box.absmin_x, box.absmin_y, box.absmin_z); - case 2: return combine_to_vector(box.absmax_x, box.absmin_y, box.absmin_z); - case 3: return combine_to_vector(box.absmin_x, box.absmax_y, box.absmin_z); - case 4: return combine_to_vector(box.absmin_x, box.absmin_y, box.absmax_z); - case 5: return combine_to_vector(box.absmax_x, box.absmax_y, box.absmin_z); - case 6: return combine_to_vector(box.absmin_x, box.absmax_y, box.absmax_z); - case 7: return combine_to_vector(box.absmax_x, box.absmin_y, box.absmax_z); - case 8: return combine_to_vector(box.absmax_x, box.absmax_y, box.absmax_z); - default: return '0 0 0'; - } -} -#endif - // todo: this sucks, lets find a better way to do backtraces? #ifndef MENUQC void backtrace(string msg) diff --git a/qcsrc/common/util.qh b/qcsrc/common/util.qh index a959931c3..9b969134a 100644 --- a/qcsrc/common/util.qh +++ b/qcsrc/common/util.qh @@ -1,3 +1,4 @@ +#define WANT_CONST // commonly used, but better make them macros #define TRUE 1 #define FALSE 0 @@ -363,11 +364,6 @@ typedef entity(entity cur, entity near, entity pass) findNextEntityNearFunction_ typedef float(entity a, entity b, entity pass) isConnectedFunction_t; void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t nxt, isConnectedFunction_t iscon, entity pass); -#ifdef SVQC -vector combine_to_vector(float x, float y, float z); -vector get_corner_position(entity box, float corner); -#endif - // expand multiple arguments into one argument by stripping parenthesis #define XPD(...) __VA_ARGS__ @@ -449,5 +445,3 @@ float Mod_Q1BSP_NativeContentsFromSuperContents(float supercontents); // Quadratic splines (bezier) vector bezier_quadratic_getpoint(vector a, vector p, vector b, float t); vector bezier_quadratic_getderivative(vector a, vector p, vector b, float t); - -#define APPEND_TO_STRING(list,sep,add) ((list) = (((list) != "") ? strcat(list, sep, add) : (add))) diff --git a/qcsrc/common/weapons/all.qh b/qcsrc/common/weapons/all.qh deleted file mode 100644 index a40488f83..000000000 --- a/qcsrc/common/weapons/all.qh +++ /dev/null @@ -1,27 +0,0 @@ -// ONLY EVER ADD NEW WEAPONS AT THE END. IF YOU REMOVE ONE, PUT THE LAST ONE ON -// ITS PLACE. THIS IS TO AVOID UNNECESSARY RENUMBERING OF WEAPON IMPULSES. -// IF YOU DISREGARD THIS NOTICE, I'LL KILL YOU WITH THE @!#%'N TUBA - -// core weapons -#include "w_blaster.qc" -#include "w_shotgun.qc" -#include "w_machinegun.qc" -#include "w_mortar.qc" -#include "w_minelayer.qc" -#include "w_electro.qc" -#include "w_crylink.qc" -#include "w_vortex.qc" -#include "w_hagar.qc" -#include "w_devastator.qc" - -// other weapons -#include "w_porto.qc" -#include "w_vaporizer.qc" -#include "w_hook.qc" -#include "w_hlac.qc" -#include "w_tuba.qc" -#include "w_rifle.qc" -#include "w_fireball.qc" -#include "w_seeker.qc" -#include "w_shockwave.qc" -#include "w_arc.qc" diff --git a/qcsrc/common/weapons/calculations.qc b/qcsrc/common/weapons/calculations.qc deleted file mode 100644 index 7bc64e0b5..000000000 --- a/qcsrc/common/weapons/calculations.qc +++ /dev/null @@ -1,261 +0,0 @@ -// ============================= -// Explosion Force Calculation -// ============================= - -float explosion_calcpush_getmultiplier(vector explosion_v, vector target_v) -{ - float a; - a = explosion_v * (explosion_v - target_v); - - if(a <= 0) - // target is too fast to be hittable by this - return 0; - - a /= (explosion_v * explosion_v); - // we know we can divide by this, or above a would be == 0 - - return a; -} - -#if 0 -vector explosion_calcpush(vector explosion_v, float explosion_m, vector target_v, float target_m, float elasticity) -{ - // solution of the equations: - // v' = v + a vp // central hit - // m*v' + mp*vp' = m*v + mp*vp // conservation of momentum - // m*v'^2 + mp*vp'^2 = m*v^2 + mp*vp^2 // conservation of energy (ELASTIC hit) - // -> a = 0 // case 1: did not hit - // -> a = 2*mp*(vp^2 - vp.v) / ((m+mp) * vp^2) // case 2: did hit - // // non-elastic hits are somewhere between these two - - // this would be physically correct, but we don't do that - return explosion_v * explosion_calcpush_getmultiplier(explosion_v, target_v) * ( - (1 + elasticity) * ( - explosion_m - ) / ( - target_m + explosion_m - ) - ); // note: this factor is at least 0, at most 2 -} -#endif - -// simplified formula, tuned so that if the target has velocity 0, we get exactly the original force -vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor) -{ - // if below 1, the formulas make no sense (and would cause superjumps) - if(speedfactor < 1) - return explosion_f; - -#if 0 - float m; - // find m so that - // speedfactor * (1 + e) * m / (1 + m) == 1 - m = 1 / ((1 + 0) * speedfactor - 1); - vector v; - v = explosion_calcpush(explosion_f * speedfactor, m, target_v, 1, 0); - // the factor we then get is: - // 1 - printf("MASS: %f\nv: %v -> %v\nENERGY BEFORE == %f + %f = %f\nENERGY AFTER >= %f\n", - m, - target_v, target_v + v, - target_v * target_v, m * explosion_f * speedfactor * explosion_f * speedfactor, target_v * target_v + m * explosion_f * speedfactor * explosion_f * speedfactor, - (target_v + v) * (target_v + v)); - return v; -#endif - return explosion_f * explosion_calcpush_getmultiplier(explosion_f * speedfactor, target_v); -} - - -// ========================= -// Shot Spread Calculation -// ========================= - -vector cliptoplane(vector v, vector p) -{ - return v - (v * p) * p; -} - -vector solve_cubic_pq(float p, float q) -{ - float D, u, v, a; - D = q*q/4.0 + p*p*p/27.0; - if(D < 0) - { - // irreducibilis - a = 1.0/3.0 * acos(-q/2.0 * sqrt(-27.0/(p*p*p))); - u = sqrt(-4.0/3.0 * p); - // a in range 0..pi/3 - // cos(a) - // cos(a + 2pi/3) - // cos(a + 4pi/3) - return - u * - ( - '1 0 0' * cos(a + 2.0/3.0*M_PI) - + - '0 1 0' * cos(a + 4.0/3.0*M_PI) - + - '0 0 1' * cos(a) - ); - } - else if(D == 0) - { - // simple - if(p == 0) - return '0 0 0'; - u = 3*q/p; - v = -u/2; - if(u >= v) - return '1 1 0' * v + '0 0 1' * u; - else - return '0 1 1' * v + '1 0 0' * u; - } - else - { - // cardano - u = cbrt(-q/2.0 + sqrt(D)); - v = cbrt(-q/2.0 - sqrt(D)); - return '1 1 1' * (u + v); - } -} -vector solve_cubic_abcd(float a, float b, float c, float d) -{ - // y = 3*a*x + b - // x = (y - b) / 3a - float p, q; - vector v; - p = (9*a*c - 3*b*b); - q = (27*a*a*d - 9*a*b*c + 2*b*b*b); - v = solve_cubic_pq(p, q); - v = (v - b * '1 1 1') * (1.0 / (3.0 * a)); - if(a < 0) - v += '1 0 -1' * (v_z - v_x); // swap x, z - return v; -} - -vector findperpendicular(vector v) -{ - vector p; - p_x = v_z; - p_y = -v_x; - p_z = v_y; - return normalize(cliptoplane(p, v)); -} - -vector W_CalculateSpread(vector forward, float spread, float spreadfactor, float spreadstyle) -{ - float sigma; - vector v1 = '0 0 0', v2; - float dx, dy, r; - float sstyle; - spread *= spreadfactor; //g_weaponspreadfactor; - if(spread <= 0) - return forward; - sstyle = spreadstyle; //autocvar_g_projectiles_spread_style; - - if(sstyle == 0) - { - // this is the baseline for the spread value! - // standard deviation: sqrt(2/5) - // density function: sqrt(1-r^2) - return forward + randomvec() * spread; - } - else if(sstyle == 1) - { - // same thing, basically - return normalize(forward + cliptoplane(randomvec() * spread, forward)); - } - else if(sstyle == 2) - { - // circle spread... has at sigma=1 a standard deviation of sqrt(1/2) - sigma = spread * 0.89442719099991587855; // match baseline stddev - v1 = findperpendicular(forward); - v2 = cross(forward, v1); - // random point on unit circle - dx = random() * 2 * M_PI; - dy = sin(dx); - dx = cos(dx); - // radius in our dist function - r = random(); - r = sqrt(r); - return normalize(forward + (v1 * dx + v2 * dy) * r * sigma); - } - else if(sstyle == 3) // gauss 3d - { - sigma = spread * 0.44721359549996; // match baseline stddev - // note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right - v1 = forward; - v1_x += gsl_ran_gaussian(sigma); - v1_y += gsl_ran_gaussian(sigma); - v1_z += gsl_ran_gaussian(sigma); - return v1; - } - else if(sstyle == 4) // gauss 2d - { - sigma = spread * 0.44721359549996; // match baseline stddev - // note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right - v1_x = gsl_ran_gaussian(sigma); - v1_y = gsl_ran_gaussian(sigma); - v1_z = gsl_ran_gaussian(sigma); - return normalize(forward + cliptoplane(v1, forward)); - } - else if(sstyle == 5) // 1-r - { - sigma = spread * 1.154700538379252; // match baseline stddev - v1 = findperpendicular(forward); - v2 = cross(forward, v1); - // random point on unit circle - dx = random() * 2 * M_PI; - dy = sin(dx); - dx = cos(dx); - // radius in our dist function - r = random(); - r = solve_cubic_abcd(-2, 3, 0, -r) * '0 1 0'; - return normalize(forward + (v1 * dx + v2 * dy) * r * sigma); - } - else if(sstyle == 6) // 1-r^2 - { - sigma = spread * 1.095445115010332; // match baseline stddev - v1 = findperpendicular(forward); - v2 = cross(forward, v1); - // random point on unit circle - dx = random() * 2 * M_PI; - dy = sin(dx); - dx = cos(dx); - // radius in our dist function - r = random(); - r = sqrt(1 - r); - r = sqrt(1 - r); - return normalize(forward + (v1 * dx + v2 * dy) * r * sigma); - } - else if(sstyle == 7) // (1-r) (2-r) - { - sigma = spread * 1.224744871391589; // match baseline stddev - v1 = findperpendicular(forward); - v2 = cross(forward, v1); - // random point on unit circle - dx = random() * 2 * M_PI; - dy = sin(dx); - dx = cos(dx); - // radius in our dist function - r = random(); - r = 1 - sqrt(r); - r = 1 - sqrt(r); - return normalize(forward + (v1 * dx + v2 * dy) * r * sigma); - } - else - error("g_projectiles_spread_style must be 0 (sphere), 1 (flattened sphere), 2 (circle), 3 (gauss 3D), 4 (gauss plane), 5 (linear falloff), 6 (quadratic falloff), 7 (stronger falloff)!"); - return '0 0 0'; - /* - * how to derive falloff functions: - * rho(r) := (2-r) * (1-r); - * a : 0; - * b : 1; - * rhor(r) := r * rho(r); - * cr(t) := integrate(rhor(r), r, a, t); - * scr(t) := integrate(rhor(r) * r^2, r, a, t); - * variance : scr(b) / cr(b); - * solve(cr(r) = rand * cr(b), r), programmmode:false; - * sqrt(0.4 / variance), numer; - */ -} diff --git a/qcsrc/common/weapons/calculations.qh b/qcsrc/common/weapons/calculations.qh deleted file mode 100644 index 9a6dd1c54..000000000 --- a/qcsrc/common/weapons/calculations.qh +++ /dev/null @@ -1,2 +0,0 @@ -vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor); -vector W_CalculateSpread(vector forward, float spread, float spreadfactor, float spreadstyle); diff --git a/qcsrc/common/weapons/config.qc b/qcsrc/common/weapons/config.qc deleted file mode 100644 index 2537022f6..000000000 --- a/qcsrc/common/weapons/config.qc +++ /dev/null @@ -1,55 +0,0 @@ -// ========================== -// Balance Config Generator -// ========================== - -void W_Config_Queue_Swap(float root, float child, entity pass) -{ - string oldroot = wep_config_queue[root]; - wep_config_queue[root] = wep_config_queue[child]; - wep_config_queue[child] = oldroot; -} - -float W_Config_Queue_Compare(float root, float child, entity pass) -{ - return strcmp(wep_config_queue[root], wep_config_queue[child]); -} - -void Dump_Weapon_Settings(void) -{ - float i, x, totalsettings = 0; - for(i = WEP_FIRST; i <= WEP_LAST; ++i) - { - // step 1: clear the queue - WEP_CONFIG_COUNT = 0; - for(x = 0; x <= MAX_WEP_CONFIG; ++x) - { wep_config_queue[x] = string_null; } - - // step 2: build new queue - WEP_ACTION(i, WR_CONFIG); - - // step 3: sort queue - heapsort(WEP_CONFIG_COUNT, W_Config_Queue_Swap, W_Config_Queue_Compare, world); - - // step 4: write queue - WEP_CONFIG_WRITETOFILE(sprintf( - "// {{{ #%d: %s%s\n", - i, - WEP_NAME(i), - (((get_weaponinfo(i)).spawnflags & WEP_FLAG_MUTATORBLOCKED) ? " (MUTATOR WEAPON)" : "") - )) - for(x = 0; x <= WEP_CONFIG_COUNT; ++x) { WEP_CONFIG_WRITETOFILE(wep_config_queue[x]) } - WEP_CONFIG_WRITETOFILE("// }}}\n") - - // step 5: debug info - print(sprintf("#%d: %s: %d settings...\n", i, WEP_NAME(i), WEP_CONFIG_COUNT)); - totalsettings += WEP_CONFIG_COUNT; - } - - // clear queue now that we're finished - WEP_CONFIG_COUNT = 0; - for(x = 0; x <= MAX_WEP_CONFIG; ++x) - { wep_config_queue[x] = string_null; } - - // extra information - print(sprintf("Totals: %d weapons, %d settings\n", (i - 1), totalsettings)); -} diff --git a/qcsrc/common/weapons/config.qh b/qcsrc/common/weapons/config.qh deleted file mode 100644 index 6a0489314..000000000 --- a/qcsrc/common/weapons/config.qh +++ /dev/null @@ -1,44 +0,0 @@ -// ========================== -// Balance Config Generator -// ========================== - -void Dump_Weapon_Settings(void); -float wep_config_file; -float wep_config_alsoprint; - -#define MAX_WEP_CONFIG 256 -float WEP_CONFIG_COUNT; -string wep_config_queue[MAX_WEP_CONFIG]; - -#define WEP_CONFIG_QUEUE(a) { \ - wep_config_queue[WEP_CONFIG_COUNT] = a; \ - ++WEP_CONFIG_COUNT; } - -#define WEP_CONFIG_WRITETOFILE(a) { \ - fputs(wep_config_file, a); \ - if(wep_config_alsoprint) { print(a); } } - -#define WEP_CONFIG_WRITE_CVARS_NONE(wepname,name) \ - { WEP_CONFIG_QUEUE( \ - sprintf("set g_balance_%s_%s %g\n", #wepname, #name, \ - cvar(sprintf("g_balance_%s_%s", #wepname, #name)))) } - -#define WEP_CONFIG_WRITE_CVARS_PRI(wepname,name) WEP_CONFIG_WRITE_CVARS_NONE(wepname, primary_##name) -#define WEP_CONFIG_WRITE_CVARS_SEC(wepname,name) WEP_CONFIG_WRITE_CVARS_NONE(wepname, secondary_##name) -#define WEP_CONFIG_WRITE_CVARS_BOTH(wepname,name) \ - WEP_CONFIG_WRITE_CVARS_PRI(wepname, name) \ - WEP_CONFIG_WRITE_CVARS_SEC(wepname, name) - -#define WEP_CONFIG_WRITE_CVARS(wepid,wepname,mode,name) WEP_CONFIG_WRITE_CVARS_##mode(wepname, name) - -#define WEP_CONFIG_WRITE_PROPS_string(wepname,name) \ - { WEP_CONFIG_QUEUE( \ - sprintf("set g_balance_%s_%s \"%s\"\n", #wepname, #name, \ - cvar_string(sprintf("g_balance_%s_%s", #wepname, #name)))) } - -#define WEP_CONFIG_WRITE_PROPS_float(wepname,name) \ - { WEP_CONFIG_QUEUE( \ - sprintf("set g_balance_%s_%s %g\n", #wepname, #name, \ - cvar(sprintf("g_balance_%s_%s", #wepname, #name)))) } - -#define WEP_CONFIG_WRITE_PROPS(wepid,wepname,type,prop,name) WEP_CONFIG_WRITE_PROPS_##type(wepname,name) diff --git a/qcsrc/common/weapons/w_arc.qc b/qcsrc/common/weapons/w_arc.qc deleted file mode 100644 index c666619e5..000000000 --- a/qcsrc/common/weapons/w_arc.qc +++ /dev/null @@ -1,1427 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ ARC, -/* function */ W_Arc, -/* ammotype */ ammo_cells, -/* impulse */ 3, -/* flags */ WEP_FLAG_NORMAL, -/* rating */ BOT_PICKUP_RATING_HIGH, -/* color */ '1 1 1', -/* modelname */ "arc", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairhlac 0.7", -/* wepimg */ "weaponhlac", -/* refname */ "arc", -/* wepname */ _("Arc") -); - -#define ARC_SETTINGS(w_cvar,w_prop) ARC_SETTINGS_LIST(w_cvar, w_prop, ARC, arc) -#define ARC_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, NONE, beam_ammo) \ - w_cvar(id, sn, NONE, beam_animtime) \ - w_cvar(id, sn, NONE, beam_botaimspeed) \ - w_cvar(id, sn, NONE, beam_botaimlifetime) \ - w_cvar(id, sn, NONE, beam_damage) \ - w_cvar(id, sn, NONE, beam_degreespersegment) \ - w_cvar(id, sn, NONE, beam_distancepersegment) \ - w_cvar(id, sn, NONE, beam_falloff_halflifedist) \ - w_cvar(id, sn, NONE, beam_falloff_maxdist) \ - w_cvar(id, sn, NONE, beam_falloff_mindist) \ - w_cvar(id, sn, NONE, beam_force) \ - w_cvar(id, sn, NONE, beam_healing_amax) \ - w_cvar(id, sn, NONE, beam_healing_aps) \ - w_cvar(id, sn, NONE, beam_healing_hmax) \ - w_cvar(id, sn, NONE, beam_healing_hps) \ - w_cvar(id, sn, NONE, beam_maxangle) \ - w_cvar(id, sn, NONE, beam_nonplayerdamage) \ - w_cvar(id, sn, NONE, beam_range) \ - w_cvar(id, sn, NONE, beam_refire) \ - w_cvar(id, sn, NONE, beam_returnspeed) \ - w_cvar(id, sn, NONE, beam_tightness) \ - w_cvar(id, sn, NONE, burst_ammo) \ - w_cvar(id, sn, NONE, burst_damage) \ - w_cvar(id, sn, NONE, burst_healing_aps) \ - w_cvar(id, sn, NONE, burst_healing_hps) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifndef MENUQC -#define ARC_MAX_SEGMENTS 20 -vector arc_shotorigin[4]; -.vector beam_start; -.vector beam_dir; -.vector beam_wantdir; -.float beam_type; - -#define ARC_BT_MISS 0 -#define ARC_BT_WALL 1 -#define ARC_BT_HEAL 2 -#define ARC_BT_HIT 3 -#define ARC_BT_BURST_MISS 10 -#define ARC_BT_BURST_WALL 11 -#define ARC_BT_BURST_HEAL 12 -#define ARC_BT_BURST_HIT 13 -#define ARC_BT_BURSTMASK 10 - -#define ARC_SF_SETTINGS 1 -#define ARC_SF_START 2 -#define ARC_SF_WANTDIR 4 -#define ARC_SF_BEAMDIR 8 -#define ARC_SF_BEAMTYPE 16 -#define ARC_SF_LOCALMASK 14 -#endif -#ifdef SVQC -ARC_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) -.entity arc_beam; -.float BUTTON_ATCK_prev; // for better animation control -.float beam_prev; -.float beam_initialized; -.float beam_bursting; -.float beam_teleporttime; -#endif -#ifdef CSQC -void Ent_ReadArcBeam(float isnew); - -.vector beam_color; -.float beam_alpha; -.float beam_thickness; -.float beam_traileffect; -.float beam_hiteffect; -.float beam_hitlight[4]; // 0: radius, 123: rgb -.float beam_muzzleeffect; -.float beam_muzzlelight[4]; // 0: radius, 123: rgb -.string beam_image; - -.entity beam_muzzleentity; - -.float beam_degreespersegment; -.float beam_distancepersegment; -.float beam_usevieworigin; -.float beam_initialized; -.float beam_maxangle; -.float beam_range; -.float beam_returnspeed; -.float beam_tightness; -.vector beam_shotorigin; - -entity Draw_ArcBeam_callback_entity; -float Draw_ArcBeam_callback_last_thickness; -vector Draw_ArcBeam_callback_last_top; // NOTE: in same coordinate system as player. -vector Draw_ArcBeam_callback_last_bottom; // NOTE: in same coordinate system as player. -#endif -#else -#ifdef SVQC -void spawnfunc_weapon_arc(void) { weapon_defaultspawnfunc(WEP_ARC); } - -float W_Arc_Beam_Send(entity to, float sf) -{ - WriteByte(MSG_ENTITY, ENT_CLIENT_ARC_BEAM); - - // Truncate information when this beam is displayed to the owner client - // - The owner client has no use for beam start position or directions, - // it always figures this information out for itself with csqc code. - // - Spectating the owner also truncates this information. - float drawlocal = ((to == self.owner) || ((to.enemy == self.owner) && IS_SPEC(to))); - if(drawlocal) { sf &= ~ARC_SF_LOCALMASK; } - - WriteByte(MSG_ENTITY, sf); - - if(sf & ARC_SF_SETTINGS) // settings information - { - WriteShort(MSG_ENTITY, WEP_CVAR(arc, beam_degreespersegment)); - WriteShort(MSG_ENTITY, WEP_CVAR(arc, beam_distancepersegment)); - WriteShort(MSG_ENTITY, WEP_CVAR(arc, beam_maxangle)); - WriteCoord(MSG_ENTITY, WEP_CVAR(arc, beam_range)); - WriteShort(MSG_ENTITY, WEP_CVAR(arc, beam_returnspeed)); - WriteByte(MSG_ENTITY, WEP_CVAR(arc, beam_tightness) * 10); - - WriteByte(MSG_ENTITY, drawlocal); - } - if(sf & ARC_SF_START) // starting location - { - WriteCoord(MSG_ENTITY, self.beam_start_x); - WriteCoord(MSG_ENTITY, self.beam_start_y); - WriteCoord(MSG_ENTITY, self.beam_start_z); - } - if(sf & ARC_SF_WANTDIR) // want/aim direction - { - WriteCoord(MSG_ENTITY, self.beam_wantdir_x); - WriteCoord(MSG_ENTITY, self.beam_wantdir_y); - WriteCoord(MSG_ENTITY, self.beam_wantdir_z); - } - if(sf & ARC_SF_BEAMDIR) // beam direction - { - WriteCoord(MSG_ENTITY, self.beam_dir_x); - WriteCoord(MSG_ENTITY, self.beam_dir_y); - WriteCoord(MSG_ENTITY, self.beam_dir_z); - } - if(sf & ARC_SF_BEAMTYPE) // beam type - { - WriteByte(MSG_ENTITY, self.beam_type); - } - - return TRUE; -} - -void Reset_ArcBeam(entity player, vector forward) -{ - if (!player.arc_beam) { - return; - } - player.arc_beam.beam_dir = forward; - player.arc_beam.beam_teleporttime = time; -} - -void W_Arc_Beam_Think(void) -{ - if(self != self.owner.arc_beam) - { - remove(self); - return; - } - - if( - !IS_PLAYER(self.owner) - || - (self.owner.WEP_AMMO(ARC) <= 0 && !(self.owner.items & IT_UNLIMITED_WEAPON_AMMO)) - || - self.owner.deadflag != DEAD_NO - || - (!self.owner.BUTTON_ATCK /* FIXME(Samual): && !self.beam_bursting */) - || - self.owner.frozen - ) - { - if(self == self.owner.arc_beam) { self.owner.arc_beam = world; } - entity oldself = self; - self = self.owner; - if(!WEP_ACTION(WEP_ARC, WR_CHECKAMMO1) && !WEP_ACTION(WEP_ARC, WR_CHECKAMMO2)) - { - // note: this doesn't force the switch - W_SwitchToOtherWeapon(self); - } - self = oldself; - remove(self); - return; - } - - float burst = 0; - if(/*self.owner.BUTTON_ATCK2 || */self.beam_bursting) - { - if(!self.beam_bursting) - self.beam_bursting = TRUE; - burst = ARC_BT_BURSTMASK; - } - - // decrease ammo - float coefficient = frametime; - if(!(self.owner.items & IT_UNLIMITED_WEAPON_AMMO)) - { - float rootammo; - if(burst) - { rootammo = WEP_CVAR(arc, burst_ammo); } - else - { rootammo = WEP_CVAR(arc, beam_ammo); } - - if(rootammo) - { - coefficient = min(coefficient, self.owner.WEP_AMMO(ARC) / rootammo); - self.owner.WEP_AMMO(ARC) = max(0, self.owner.WEP_AMMO(ARC) - (rootammo * frametime)); - } - } - - makevectors(self.owner.v_angle); - - W_SetupShot_Range( - self.owner, - TRUE, - 0, - "", - 0, - WEP_CVAR(arc, beam_damage) * coefficient, - WEP_CVAR(arc, beam_range) - ); - - // After teleport, "lock" the beam until the teleport is confirmed. - if (time < self.beam_teleporttime + ANTILAG_LATENCY(self.owner)) { - w_shotdir = self.beam_dir; - } - - // network information: shot origin and want/aim direction - if(self.beam_start != w_shotorg) - { - self.SendFlags |= ARC_SF_START; - self.beam_start = w_shotorg; - } - if(self.beam_wantdir != w_shotdir) - { - self.SendFlags |= ARC_SF_WANTDIR; - self.beam_wantdir = w_shotdir; - } - - if(!self.beam_initialized) - { - self.beam_dir = w_shotdir; - self.beam_initialized = TRUE; - } - - // WEAPONTODO: Detect player velocity so that the beam curves when moving too - // idea: blend together self.beam_dir with the inverted direction the player is moving in - // might have to make some special accomodation so that it only uses view_right and view_up - - // note that if we do this, it'll always be corrected to a maximum angle by beam_maxangle handling - - float segments; - if(self.beam_dir != w_shotdir) - { - // calculate how much we're going to move the end of the beam to the want position - // WEAPONTODO (server and client): - // blendfactor never actually becomes 0 in this situation, which is a problem - // regarding precision... this means that self.beam_dir and w_shotdir approach - // eachother, however they never actually become the same value with this method. - // Perhaps we should do some form of rounding/snapping? - float angle = vlen(w_shotdir - self.beam_dir) * RAD2DEG; - if(angle && (angle > WEP_CVAR(arc, beam_maxangle))) - { - // if the angle is greater than maxangle, force the blendfactor to make this the maximum factor - float blendfactor = bound( - 0, - (1 - (WEP_CVAR(arc, beam_returnspeed) * frametime)), - min(WEP_CVAR(arc, beam_maxangle) / angle, 1) - ); - self.beam_dir = normalize((w_shotdir * (1 - blendfactor)) + (self.beam_dir * blendfactor)); - } - else - { - // the radius is not too far yet, no worries :D - float blendfactor = bound( - 0, - (1 - (WEP_CVAR(arc, beam_returnspeed) * frametime)), - 1 - ); - self.beam_dir = normalize((w_shotdir * (1 - blendfactor)) + (self.beam_dir * blendfactor)); - } - - // network information: beam direction - self.SendFlags |= ARC_SF_BEAMDIR; - - // calculate how many segments are needed - float max_allowed_segments; - - if(WEP_CVAR(arc, beam_distancepersegment)) - { - max_allowed_segments = min( - ARC_MAX_SEGMENTS, - 1 + (vlen(w_shotdir / WEP_CVAR(arc, beam_distancepersegment))) - ); - } - else { max_allowed_segments = ARC_MAX_SEGMENTS; } - - if(WEP_CVAR(arc, beam_degreespersegment)) - { - segments = bound( - 1, - ( - min( - angle, - WEP_CVAR(arc, beam_maxangle) - ) - / - WEP_CVAR(arc, beam_degreespersegment) - ), - max_allowed_segments - ); - } - else { segments = 1; } - } - else { segments = 1; } - - vector beam_endpos = (w_shotorg + (self.beam_dir * WEP_CVAR(arc, beam_range))); - vector beam_controlpoint = w_shotorg + w_shotdir * (WEP_CVAR(arc, beam_range) * (1 - WEP_CVAR(arc, beam_tightness))); - - float i; - float new_beam_type = 0; - vector last_origin = w_shotorg; - for(i = 1; i <= segments; ++i) - { - // WEAPONTODO (client): - // In order to do nice fading and pointing on the starting segment, we must always - // have that drawn as a separate triangle... However, that is difficult to do when - // keeping in mind the above problems and also optimizing the amount of segments - // drawn on screen at any given time. (Automatic beam quality scaling, essentially) - - vector new_origin = bezier_quadratic_getpoint( - w_shotorg, - beam_controlpoint, - beam_endpos, - i / segments); - vector new_dir = normalize(new_origin - last_origin); - - WarpZone_traceline_antilag( - self.owner, - last_origin, - new_origin, - MOVE_NORMAL, - self.owner, - ANTILAG_LATENCY(self.owner) - ); - - // Do all the transforms for warpzones right now, as we already - // "are" in the post-trace system (if we hit a player, that's - // always BEHIND the last passed wz). - last_origin = trace_endpos; - w_shotorg = WarpZone_TransformOrigin(WarpZone_trace_transform, w_shotorg); - beam_controlpoint = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_controlpoint); - beam_endpos = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_endpos); - new_dir = WarpZone_TransformVelocity(WarpZone_trace_transform, new_dir); - - float is_player = ( - trace_ent.classname == "player" - || - trace_ent.classname == "body" - || - (trace_ent.flags & FL_MONSTER) - ); - - if(trace_ent && trace_ent.takedamage && (is_player || WEP_CVAR(arc, beam_nonplayerdamage))) - { - // calculate our own hit origin as trace_endpos tends to jump around annoyingly (to player origin?) - // NO. trace_endpos should be just fine. If not, - // that's an engine bug that needs proper debugging. - vector hitorigin = trace_endpos; - - float falloff = ExponentialFalloff( - WEP_CVAR(arc, beam_falloff_mindist), - WEP_CVAR(arc, beam_falloff_maxdist), - WEP_CVAR(arc, beam_falloff_halflifedist), - vlen(WarpZone_UnTransformOrigin(WarpZone_trace_transform, hitorigin) - w_shotorg) - ); - - if(is_player && SAME_TEAM(self.owner, trace_ent)) - { - float roothealth, rootarmor; - if(burst) - { - roothealth = WEP_CVAR(arc, burst_healing_hps); - rootarmor = WEP_CVAR(arc, burst_healing_aps); - } - else - { - roothealth = WEP_CVAR(arc, beam_healing_hps); - rootarmor = WEP_CVAR(arc, beam_healing_aps); - } - - if(trace_ent.health <= WEP_CVAR(arc, beam_healing_hmax) && roothealth) - { - trace_ent.health = min( - trace_ent.health + (roothealth * coefficient), - WEP_CVAR(arc, beam_healing_hmax) - ); - } - if(trace_ent.armorvalue <= WEP_CVAR(arc, beam_healing_amax) && rootarmor) - { - trace_ent.armorvalue = min( - trace_ent.armorvalue + (rootarmor * coefficient), - WEP_CVAR(arc, beam_healing_amax) - ); - } - - // stop rot, set visual effect - if(roothealth || rootarmor) - { - trace_ent.pauserothealth_finished = max( - trace_ent.pauserothealth_finished, - time + autocvar_g_balance_pause_health_rot - ); - trace_ent.pauserotarmor_finished = max( - trace_ent.pauserotarmor_finished, - time + autocvar_g_balance_pause_armor_rot - ); - new_beam_type = ARC_BT_HEAL; - } - } - else - { - float rootdamage; - if(is_player) - { - if(burst) - { rootdamage = WEP_CVAR(arc, burst_damage); } - else - { rootdamage = WEP_CVAR(arc, beam_damage); } - } - else - { rootdamage = WEP_CVAR(arc, beam_nonplayerdamage); } - - if(accuracy_isgooddamage(self.owner, trace_ent)) - { - accuracy_add( - self.owner, - WEP_ARC, - 0, - rootdamage * coefficient * falloff - ); - } - - Damage( - trace_ent, - self.owner, - self.owner, - rootdamage * coefficient * falloff, - WEP_ARC, - hitorigin, - WEP_CVAR(arc, beam_force) * new_dir * coefficient * falloff - ); - - new_beam_type = ARC_BT_HIT; - } - break; - } - else if(trace_fraction != 1) - { - // we collided with geometry - new_beam_type = ARC_BT_WALL; - break; - } - } - - // te_explosion(trace_endpos); - - // if we're bursting, use burst visual effects - new_beam_type += burst; - - // network information: beam type - if(new_beam_type != self.beam_type) - { - self.SendFlags |= ARC_SF_BEAMTYPE; - self.beam_type = new_beam_type; - } - - self.owner.beam_prev = time; - self.nextthink = time; -} - -void W_Arc_Beam(float burst) -{ - // FIXME(Samual): remove this when overheat and burst work. - if (burst) - { - centerprint(self, "^4NOTE:^7 Arc burst (secondary) is not implemented yet."); - } - - // only play fire sound if 1 sec has passed since player let go the fire button - if(time - self.beam_prev > 1) - { - sound(self, CH_WEAPON_A, "weapons/lgbeam_fire.wav", VOL_BASE, ATTN_NORM); - } - - entity beam = self.arc_beam = spawn(); - beam.classname = "W_Arc_Beam"; - beam.solid = SOLID_NOT; - beam.think = W_Arc_Beam_Think; - beam.owner = self; - beam.movetype = MOVETYPE_NONE; - beam.bot_dodge = TRUE; - beam.bot_dodgerating = WEP_CVAR(arc, beam_damage); - beam.beam_bursting = burst; - Net_LinkEntity(beam, FALSE, 0, W_Arc_Beam_Send); - - entity oldself = self; - self = beam; - self.think(); - self = oldself; -} - -float W_Arc(float req) -{ - switch(req) - { - case WR_AIM: - { - if(WEP_CVAR(arc, beam_botaimspeed)) - { - self.BUTTON_ATCK = bot_aim( - WEP_CVAR(arc, beam_botaimspeed), - 0, - WEP_CVAR(arc, beam_botaimlifetime), - FALSE - ); - } - else - { - self.BUTTON_ATCK = bot_aim( - 1000000, - 0, - 0.001, - FALSE - ); - } - return TRUE; - } - case WR_THINK: - { - #if 0 - if(self.arc_beam.beam_heat > threshold) - { - stop the beam somehow - play overheat animation - } - #endif - - if(self.BUTTON_ATCK || self.BUTTON_ATCK2 /* FIXME(Samual): || self.arc_beam.beam_bursting */) - { - if(self.BUTTON_ATCK_prev) - { - #if 0 - if(self.animstate_startframe == self.anim_shoot_x && self.animstate_numframes == self.anim_shoot_y) - weapon_thinkf(WFRAME_DONTCHANGE, autocvar_g_balance_arc_primary_animtime, w_ready); - else - #endif - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready); - } - - if((!self.arc_beam) || wasfreed(self.arc_beam)) - { - if(weapon_prepareattack(!!self.BUTTON_ATCK2, 0)) - { - W_Arc_Beam(!!self.BUTTON_ATCK2); - - if(!self.BUTTON_ATCK_prev) - { - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready); - self.BUTTON_ATCK_prev = 1; - } - } - } - } - else // todo - { - if(self.BUTTON_ATCK_prev != 0) - { - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready); - ATTACK_FINISHED(self) = time + WEP_CVAR(arc, beam_refire) * W_WeaponRateFactor(); - } - self.BUTTON_ATCK_prev = 0; - } - - #if 0 - if(self.BUTTON_ATCK2) - if(weapon_prepareattack(1, autocvar_g_balance_arc_secondary_refire)) - { - W_Arc_Attack2(); - self.arc_count = autocvar_g_balance_arc_secondary_count; - weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_arc_secondary_animtime, w_arc_checkattack); - self.arc_secondarytime = time + autocvar_g_balance_arc_secondary_refire2 * W_WeaponRateFactor(); - } - #endif - - return TRUE; - } - case WR_INIT: - { - precache_model("models/weapons/g_arc.md3"); - precache_model("models/weapons/v_arc.md3"); - precache_model("models/weapons/h_arc.iqm"); - precache_sound("weapons/lgbeam_fire.wav"); - if(!arc_shotorigin[0]) - { - arc_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC), FALSE, FALSE, 1); - arc_shotorigin[1] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC), FALSE, FALSE, 2); - arc_shotorigin[2] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC), FALSE, FALSE, 3); - arc_shotorigin[3] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC), FALSE, FALSE, 4); - } - ARC_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP) - return TRUE; - } - case WR_CHECKAMMO1: - { - return ((!WEP_CVAR(arc, beam_ammo)) || (self.WEP_AMMO(ARC) > 0)); - } - case WR_CHECKAMMO2: - { - // arc currently has no secondary attack - return FALSE; - //return ((!WEP_CVAR(arc, burst_ammo)) || (self.WEP_AMMO(ARC) > 0)); - } - case WR_CONFIG: - { - ARC_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS) - return TRUE; - } - case WR_KILLMESSAGE: - { - return WEAPON_ARC_MURDER; - } - } - return FALSE; -} -#endif -#ifdef CSQC -void Draw_ArcBeam_callback(vector start, vector hit, vector end) -{ - entity beam = Draw_ArcBeam_callback_entity; - vector transformed_view_org; - transformed_view_org = WarpZone_TransformOrigin(WarpZone_trace_transform, view_origin); - - // Thickdir shall be perpendicular to the beam and to the view-to-beam direction (WEAPONTODO: WHY) - // WEAPONTODO: Wouldn't it be better to be perpendicular to the beam and to the view FORWARD direction? - vector thickdir = normalize(cross(normalize(start - hit), transformed_view_org - start)); - - vector hitorigin; - - // draw segment - #if 0 - if(trace_fraction != 1) - { - // calculate our own hit origin as trace_endpos tends to jump around annoyingly (to player origin?) - hitorigin = start + (Draw_ArcBeam_callback_new_dir * Draw_ArcBeam_callback_segmentdist * trace_fraction); - hitorigin = WarpZone_TransformOrigin(WarpZone_trace_transform, hitorigin); - } - else - { - hitorigin = hit; - } - #else - hitorigin = hit; - #endif - - // decide upon thickness - float thickness = beam.beam_thickness; - - // draw primary beam render - vector top = hitorigin + (thickdir * thickness); - vector bottom = hitorigin - (thickdir * thickness); - - vector last_top = WarpZone_TransformOrigin(WarpZone_trace_transform, Draw_ArcBeam_callback_last_top); - vector last_bottom = WarpZone_TransformOrigin(WarpZone_trace_transform, Draw_ArcBeam_callback_last_bottom); - - R_BeginPolygon(beam.beam_image, DRAWFLAG_NORMAL); // DRAWFLAG_ADDITIVE - R_PolygonVertex( - top, - '0 0.5 0' + ('0 0.5 0' * (thickness / beam.beam_thickness)), - beam.beam_color, - beam.beam_alpha - ); - R_PolygonVertex( - last_top, - '0 0.5 0' + ('0 0.5 0' * (Draw_ArcBeam_callback_last_thickness / beam.beam_thickness)), - beam.beam_color, - beam.beam_alpha - ); - R_PolygonVertex( - last_bottom, - '0 0.5 0' * (1 - (Draw_ArcBeam_callback_last_thickness / beam.beam_thickness)), - beam.beam_color, - beam.beam_alpha - ); - R_PolygonVertex( - bottom, - '0 0.5 0' * (1 - (thickness / beam.beam_thickness)), - beam.beam_color, - beam.beam_alpha - ); - R_EndPolygon(); - - // draw trailing particles - // NOTES: - // - Don't use spammy particle counts here, use a FEW small particles around the beam - // - We're not using WarpZone_TrailParticles here because we will handle warpzones ourselves. - if(beam.beam_traileffect) - { - trailparticles(beam, beam.beam_traileffect, start, hitorigin); - } - - // set up for the next - Draw_ArcBeam_callback_last_thickness = thickness; - Draw_ArcBeam_callback_last_top = WarpZone_UnTransformOrigin(WarpZone_trace_transform, top); - Draw_ArcBeam_callback_last_bottom = WarpZone_UnTransformOrigin(WarpZone_trace_transform, bottom); -} - -void Reset_ArcBeam(void) -{ - entity e; - for (e = world; (e = findfloat(e, beam_usevieworigin, 1)); ) { - e.beam_initialized = FALSE; - } - for (e = world; (e = findfloat(e, beam_usevieworigin, 2)); ) { - e.beam_initialized = FALSE; - } -} - -void Draw_ArcBeam(void) -{ - if(!self.beam_usevieworigin) - { - InterpolateOrigin_Do(); - } - - // origin = beam starting origin - // v_angle = wanted/aim direction - // angles = current direction of beam - - vector start_pos; - vector wantdir; //= view_forward; - vector beamdir; //= self.beam_dir; - - float segments; - if(self.beam_usevieworigin) - { - // WEAPONTODO: - // Currently we have to replicate nearly the same method of figuring - // out the shotdir that the server does... Ideally in the future we - // should be able to acquire this from a generalized function built - // into a weapon system for client code. - - // find where we are aiming - makevectors(warpzone_save_view_angles); - vector forward = v_forward; - vector right = v_right; - vector up = v_up; - - // decide upon start position - if(self.beam_usevieworigin == 2) - { start_pos = warpzone_save_view_origin; } - else - { start_pos = self.origin; } - - // trace forward with an estimation - WarpZone_TraceLine( - start_pos, - start_pos + forward * self.beam_range, - MOVE_NOMONSTERS, - self - ); - - // untransform in case our trace went through a warpzone - vector end_pos = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos); - - // un-adjust trueaim if shotend is too close - if(vlen(end_pos - start_pos) < g_trueaim_minrange) - end_pos = start_pos + (forward * g_trueaim_minrange); - - // move shot origin to the actual gun muzzle origin - vector origin_offset = - right * -self.beam_shotorigin_y - + up * self.beam_shotorigin_z; - - start_pos = start_pos + origin_offset; - - // Move it also forward, but only as far as possible without hitting anything. Don't poke into walls! - traceline(start_pos, start_pos + forward * self.beam_shotorigin_x, MOVE_NORMAL, self); - start_pos = trace_endpos; - - // calculate the aim direction now - wantdir = normalize(end_pos - start_pos); - - if(!self.beam_initialized) - { - self.beam_dir = wantdir; - self.beam_initialized = TRUE; - } - - if(self.beam_dir != wantdir) - { - // calculate how much we're going to move the end of the beam to the want position - // WEAPONTODO (server and client): - // blendfactor never actually becomes 0 in this situation, which is a problem - // regarding precision... this means that self.beam_dir and w_shotdir approach - // eachother, however they never actually become the same value with this method. - // Perhaps we should do some form of rounding/snapping? - float angle = vlen(wantdir - self.beam_dir) * RAD2DEG; - if(angle && (angle > self.beam_maxangle)) - { - // if the angle is greater than maxangle, force the blendfactor to make this the maximum factor - float blendfactor = bound( - 0, - (1 - (self.beam_returnspeed * frametime)), - min(self.beam_maxangle / angle, 1) - ); - self.beam_dir = normalize((wantdir * (1 - blendfactor)) + (self.beam_dir * blendfactor)); - } - else - { - // the radius is not too far yet, no worries :D - float blendfactor = bound( - 0, - (1 - (self.beam_returnspeed * frametime)), - 1 - ); - self.beam_dir = normalize((wantdir * (1 - blendfactor)) + (self.beam_dir * blendfactor)); - } - - // calculate how many segments are needed - float max_allowed_segments; - - if(self.beam_distancepersegment) - { - max_allowed_segments = min( - ARC_MAX_SEGMENTS, - 1 + (vlen(wantdir / self.beam_distancepersegment)) - ); - } - else { max_allowed_segments = ARC_MAX_SEGMENTS; } - - if(self.beam_degreespersegment) - { - segments = bound( - 1, - ( - min( - angle, - self.beam_maxangle - ) - / - self.beam_degreespersegment - ), - max_allowed_segments - ); - } - else { segments = 1; } - } - else { segments = 1; } - - // set the beam direction which the rest of the code will refer to - beamdir = self.beam_dir; - - // finally, set self.angles to the proper direction so that muzzle attachment points in proper direction - self.angles = fixedvectoangles2(forward, up); // TODO(Samual): is this == warpzone_save_view_angles? - } - else - { - // set the values from the provided info from the networked entity - start_pos = self.origin; - wantdir = self.v_angle; - beamdir = self.angles; - - if(beamdir != wantdir) - { - float angle = vlen(wantdir - beamdir) * RAD2DEG; - - // calculate how many segments are needed - float max_allowed_segments; - - if(self.beam_distancepersegment) - { - max_allowed_segments = min( - ARC_MAX_SEGMENTS, - 1 + (vlen(wantdir / self.beam_distancepersegment)) - ); - } - else { max_allowed_segments = ARC_MAX_SEGMENTS; } - - if(self.beam_degreespersegment) - { - segments = bound( - 1, - ( - min( - angle, - self.beam_maxangle - ) - / - self.beam_degreespersegment - ), - max_allowed_segments - ); - } - else { segments = 1; } - } - else { segments = 1; } - } - - setorigin(self, start_pos); - self.beam_muzzleentity.angles_z = random() * 360; // WEAPONTODO: use avelocity instead? - - vector beam_endpos = (start_pos + (beamdir * self.beam_range)); - vector beam_controlpoint = start_pos + wantdir * (self.beam_range * (1 - self.beam_tightness)); - - Draw_ArcBeam_callback_entity = self; - Draw_ArcBeam_callback_last_thickness = 0; - Draw_ArcBeam_callback_last_top = start_pos; - Draw_ArcBeam_callback_last_bottom = start_pos; - - vector last_origin = start_pos; - vector original_start_pos = start_pos; - - float i; - for(i = 1; i <= segments; ++i) - { - // WEAPONTODO (client): - // In order to do nice fading and pointing on the starting segment, we must always - // have that drawn as a separate triangle... However, that is difficult to do when - // keeping in mind the above problems and also optimizing the amount of segments - // drawn on screen at any given time. (Automatic beam quality scaling, essentially) - - vector new_origin = bezier_quadratic_getpoint( - start_pos, - beam_controlpoint, - beam_endpos, - i / segments); - - WarpZone_TraceBox_ThroughZone( - last_origin, - '0 0 0', - '0 0 0', - new_origin, - MOVE_NORMAL, - world, - world, - Draw_ArcBeam_callback - ); - - // Do all the transforms for warpzones right now, as we already "are" in the post-trace - // system (if we hit a player, that's always BEHIND the last passed wz). - last_origin = trace_endpos; - start_pos = WarpZone_TransformOrigin(WarpZone_trace_transform, start_pos); - beam_controlpoint = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_controlpoint); - beam_endpos = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_endpos); - beamdir = WarpZone_TransformVelocity(WarpZone_trace_transform, beamdir); - Draw_ArcBeam_callback_last_top = WarpZone_TransformOrigin(WarpZone_trace_transform, Draw_ArcBeam_callback_last_top); - Draw_ArcBeam_callback_last_bottom = WarpZone_TransformOrigin(WarpZone_trace_transform, Draw_ArcBeam_callback_last_bottom); - - if(trace_fraction < 1) { break; } - } - - // visual effects for startpoint and endpoint - if(self.beam_hiteffect) - { - // FIXME we really should do this on the server so it actually - // matches gameplay. What this client side stuff is doing is no - // more than guesswork. - pointparticles( - self.beam_hiteffect, - last_origin, - beamdir * -1, - frametime * 2 - ); - } - if(self.beam_hitlight[0]) - { - adddynamiclight( - last_origin, - self.beam_hitlight[0], - vec3( - self.beam_hitlight[1], - self.beam_hitlight[2], - self.beam_hitlight[3] - ) - ); - } - if(self.beam_muzzleeffect) - { - pointparticles( - self.beam_muzzleeffect, - original_start_pos + wantdir * 20, - wantdir * 1000, - frametime * 0.1 - ); - } - if(self.beam_muzzlelight[0]) - { - adddynamiclight( - original_start_pos + wantdir * 20, - self.beam_muzzlelight[0], - vec3( - self.beam_muzzlelight[1], - self.beam_muzzlelight[2], - self.beam_muzzlelight[3] - ) - ); - } - - // cleanup - Draw_ArcBeam_callback_entity = world; - Draw_ArcBeam_callback_last_thickness = 0; - Draw_ArcBeam_callback_last_top = '0 0 0'; - Draw_ArcBeam_callback_last_bottom = '0 0 0'; -} - -void Remove_ArcBeam(void) -{ - remove(self.beam_muzzleentity); - sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM); -} - -void Ent_ReadArcBeam(float isnew) -{ - float sf = ReadByte(); - entity flash; - - if(isnew) - { - // calculate shot origin offset from gun alignment - float gunalign = autocvar_cl_gunalign; - if(gunalign != 1 && gunalign != 2 && gunalign != 4) - gunalign = 3; // default value - --gunalign; - - self.beam_shotorigin = arc_shotorigin[gunalign]; - - // set other main attributes of the beam - self.draw = Draw_ArcBeam; - self.entremove = Remove_ArcBeam; - sound(self, CH_SHOTS_SINGLE, "weapons/lgbeam_fly.wav", VOL_BASE, ATTEN_NORM); - - flash = spawn(); - flash.owner = self; - flash.effects = EF_ADDITIVE | EF_FULLBRIGHT; - flash.drawmask = MASK_NORMAL; - flash.solid = SOLID_NOT; - flash.avelocity_z = 5000; - setattachment(flash, self, ""); - setorigin(flash, '0 0 0'); - - self.beam_muzzleentity = flash; - } - else - { - flash = self.beam_muzzleentity; - } - - if(sf & ARC_SF_SETTINGS) // settings information - { - self.beam_degreespersegment = ReadShort(); - self.beam_distancepersegment = ReadShort(); - self.beam_maxangle = ReadShort(); - self.beam_range = ReadCoord(); - self.beam_returnspeed = ReadShort(); - self.beam_tightness = (ReadByte() / 10); - - if(ReadByte()) - { - if(autocvar_chase_active) - { self.beam_usevieworigin = 1; } - else // use view origin - { self.beam_usevieworigin = 2; } - } - else - { - self.beam_usevieworigin = 0; - } - } - - if(!self.beam_usevieworigin) - { - // self.iflags = IFLAG_ORIGIN | IFLAG_ANGLES | IFLAG_V_ANGLE; // why doesn't this work? - self.iflags = IFLAG_ORIGIN; - - InterpolateOrigin_Undo(); - } - - if(sf & ARC_SF_START) // starting location - { - self.origin_x = ReadCoord(); - self.origin_y = ReadCoord(); - self.origin_z = ReadCoord(); - } - else if(self.beam_usevieworigin) // infer the location from player location - { - if(self.beam_usevieworigin == 2) - { - // use view origin - self.origin = view_origin; - } - else - { - // use player origin so that third person display still works - self.origin = getplayerorigin(player_localnum) + ('0 0 1' * getstati(STAT_VIEWHEIGHT)); - } - } - - setorigin(self, self.origin); - - if(sf & ARC_SF_WANTDIR) // want/aim direction - { - self.v_angle_x = ReadCoord(); - self.v_angle_y = ReadCoord(); - self.v_angle_z = ReadCoord(); - } - - if(sf & ARC_SF_BEAMDIR) // beam direction - { - self.angles_x = ReadCoord(); - self.angles_y = ReadCoord(); - self.angles_z = ReadCoord(); - } - - if(sf & ARC_SF_BEAMTYPE) // beam type - { - self.beam_type = ReadByte(); - switch(self.beam_type) - { - case ARC_BT_MISS: - { - self.beam_color = '-1 -1 1'; - self.beam_alpha = 0.5; - self.beam_thickness = 8; - self.beam_traileffect = FALSE; - self.beam_hiteffect = particleeffectnum("electro_lightning"); - self.beam_hitlight[0] = 0; - self.beam_hitlight[1] = 1; - self.beam_hitlight[2] = 1; - self.beam_hitlight[3] = 1; - self.beam_muzzleeffect = -1; //particleeffectnum("nex_muzzleflash"); - self.beam_muzzlelight[0] = 0; - self.beam_muzzlelight[1] = 1; - self.beam_muzzlelight[2] = 1; - self.beam_muzzlelight[3] = 1; - if(self.beam_muzzleeffect >= 0) - { - self.beam_image = "particles/lgbeam"; - setmodel(flash, "models/flash.md3"); - flash.alpha = self.beam_alpha; - flash.colormod = self.beam_color; - flash.scale = 0.5; - } - break; - } - case ARC_BT_WALL: // grenadelauncher_muzzleflash healray_muzzleflash - { - self.beam_color = '0.5 0.5 1'; - self.beam_alpha = 0.5; - self.beam_thickness = 8; - self.beam_traileffect = FALSE; - self.beam_hiteffect = particleeffectnum("electro_lightning"); - self.beam_hitlight[0] = 0; - self.beam_hitlight[1] = 1; - self.beam_hitlight[2] = 1; - self.beam_hitlight[3] = 1; - self.beam_muzzleeffect = -1; // particleeffectnum("grenadelauncher_muzzleflash"); - self.beam_muzzlelight[0] = 0; - self.beam_muzzlelight[1] = 1; - self.beam_muzzlelight[2] = 1; - self.beam_muzzlelight[3] = 1; - self.beam_image = "particles/lgbeam"; - if(self.beam_muzzleeffect >= 0) - { - setmodel(flash, "models/flash.md3"); - flash.alpha = self.beam_alpha; - flash.colormod = self.beam_color; - flash.scale = 0.5; - } - break; - } - case ARC_BT_HEAL: - { - self.beam_color = '0 1 0'; - self.beam_alpha = 0.5; - self.beam_thickness = 8; - self.beam_traileffect = FALSE; - self.beam_hiteffect = particleeffectnum("healray_impact"); - self.beam_hitlight[0] = 0; - self.beam_hitlight[1] = 1; - self.beam_hitlight[2] = 1; - self.beam_hitlight[3] = 1; - self.beam_muzzleeffect = -1; //particleeffectnum("nex_muzzleflash"); - self.beam_muzzlelight[0] = 0; - self.beam_muzzlelight[1] = 1; - self.beam_muzzlelight[2] = 1; - self.beam_muzzlelight[3] = 1; - self.beam_image = "particles/lgbeam"; - if(self.beam_muzzleeffect >= 0) - { - self.beam_image = "particles/lgbeam"; - setmodel(flash, "models/flash.md3"); - flash.alpha = self.beam_alpha; - flash.colormod = self.beam_color; - flash.scale = 0.5; - } - break; - } - case ARC_BT_HIT: - { - self.beam_color = '1 0 1'; - self.beam_alpha = 0.5; - self.beam_thickness = 8; - self.beam_traileffect = FALSE; - self.beam_hiteffect = particleeffectnum("electro_lightning"); - self.beam_hitlight[0] = 20; - self.beam_hitlight[1] = 1; - self.beam_hitlight[2] = 0; - self.beam_hitlight[3] = 0; - self.beam_muzzleeffect = -1; //particleeffectnum("nex_muzzleflash"); - self.beam_muzzlelight[0] = 50; - self.beam_muzzlelight[1] = 1; - self.beam_muzzlelight[2] = 0; - self.beam_muzzlelight[3] = 0; - self.beam_image = "particles/lgbeam"; - if(self.beam_muzzleeffect >= 0) - { - self.beam_image = "particles/lgbeam"; - setmodel(flash, "models/flash.md3"); - flash.alpha = self.beam_alpha; - flash.colormod = self.beam_color; - flash.scale = 0.5; - } - break; - } - case ARC_BT_BURST_MISS: - { - self.beam_color = '-1 -1 1'; - self.beam_alpha = 0.5; - self.beam_thickness = 14; - self.beam_traileffect = FALSE; - self.beam_hiteffect = particleeffectnum("electro_lightning"); - self.beam_hitlight[0] = 0; - self.beam_hitlight[1] = 1; - self.beam_hitlight[2] = 1; - self.beam_hitlight[3] = 1; - self.beam_muzzleeffect = -1; //particleeffectnum("nex_muzzleflash"); - self.beam_muzzlelight[0] = 0; - self.beam_muzzlelight[1] = 1; - self.beam_muzzlelight[2] = 1; - self.beam_muzzlelight[3] = 1; - self.beam_image = "particles/lgbeam"; - setmodel(flash, "models/flash.md3"); - flash.alpha = self.beam_alpha; - flash.colormod = self.beam_color; - flash.scale = 0.5; - break; - } - case ARC_BT_BURST_WALL: - { - self.beam_color = '0.5 0.5 1'; - self.beam_alpha = 0.5; - self.beam_thickness = 14; - self.beam_traileffect = FALSE; - self.beam_hiteffect = particleeffectnum("electro_lightning"); - self.beam_hitlight[0] = 0; - self.beam_hitlight[1] = 1; - self.beam_hitlight[2] = 1; - self.beam_hitlight[3] = 1; - self.beam_muzzleeffect = -1; //particleeffectnum("nex_muzzleflash"); - self.beam_muzzlelight[0] = 0; - self.beam_muzzlelight[1] = 1; - self.beam_muzzlelight[2] = 1; - self.beam_muzzlelight[3] = 1; - self.beam_image = "particles/lgbeam"; - if(self.beam_muzzleeffect >= 0) - { - self.beam_image = "particles/lgbeam"; - setmodel(flash, "models/flash.md3"); - flash.alpha = self.beam_alpha; - flash.colormod = self.beam_color; - flash.scale = 0.5; - } - break; - } - case ARC_BT_BURST_HEAL: - { - self.beam_color = '0 1 0'; - self.beam_alpha = 0.5; - self.beam_thickness = 14; - self.beam_traileffect = FALSE; - self.beam_hiteffect = particleeffectnum("electro_lightning"); - self.beam_hitlight[0] = 0; - self.beam_hitlight[1] = 1; - self.beam_hitlight[2] = 1; - self.beam_hitlight[3] = 1; - self.beam_muzzleeffect = -1; //particleeffectnum("nex_muzzleflash"); - self.beam_muzzlelight[0] = 0; - self.beam_muzzlelight[1] = 1; - self.beam_muzzlelight[2] = 1; - self.beam_muzzlelight[3] = 1; - self.beam_image = "particles/lgbeam"; - if(self.beam_muzzleeffect >= 0) - { - self.beam_image = "particles/lgbeam"; - setmodel(flash, "models/flash.md3"); - flash.alpha = self.beam_alpha; - flash.colormod = self.beam_color; - flash.scale = 0.5; - } - break; - } - case ARC_BT_BURST_HIT: - { - self.beam_color = '1 0 1'; - self.beam_alpha = 0.5; - self.beam_thickness = 14; - self.beam_traileffect = FALSE; - self.beam_hiteffect = particleeffectnum("electro_lightning"); - self.beam_hitlight[0] = 0; - self.beam_hitlight[1] = 1; - self.beam_hitlight[2] = 1; - self.beam_hitlight[3] = 1; - self.beam_muzzleeffect = -1; //particleeffectnum("nex_muzzleflash"); - self.beam_muzzlelight[0] = 0; - self.beam_muzzlelight[1] = 1; - self.beam_muzzlelight[2] = 1; - self.beam_muzzlelight[3] = 1; - self.beam_image = "particles/lgbeam"; - if(self.beam_muzzleeffect >= 0) - { - self.beam_image = "particles/lgbeam"; - setmodel(flash, "models/flash.md3"); - flash.alpha = self.beam_alpha; - flash.colormod = self.beam_color; - flash.scale = 0.5; - } - break; - } - - // shouldn't be possible, but lets make it colorful if it does :D - default: - { - self.beam_color = randomvec(); - self.beam_alpha = 1; - self.beam_thickness = 8; - self.beam_traileffect = FALSE; - self.beam_hiteffect = FALSE; - self.beam_hitlight[0] = 0; - self.beam_hitlight[1] = 1; - self.beam_hitlight[2] = 1; - self.beam_hitlight[3] = 1; - self.beam_muzzleeffect = -1; //particleeffectnum("nex_muzzleflash"); - self.beam_muzzlelight[0] = 0; - self.beam_muzzlelight[1] = 1; - self.beam_muzzlelight[2] = 1; - self.beam_muzzlelight[3] = 1; - self.beam_image = "particles/lgbeam"; - if(self.beam_muzzleeffect >= 0) - { - self.beam_image = "particles/lgbeam"; - setmodel(flash, "models/flash.md3"); - flash.alpha = self.beam_alpha; - flash.colormod = self.beam_color; - flash.scale = 0.5; - } - break; - } - } - } - - if(!self.beam_usevieworigin) - { - InterpolateOrigin_Note(); - } -} - -float W_Arc(float req) -{ - switch(req) - { - case WR_IMPACTEFFECT: - { - // todo - return TRUE; - } - case WR_INIT: - { - precache_sound("weapons/lgbeam_fly.wav"); - return TRUE; - } - case WR_ZOOMRETICLE: - { - // no weapon specific image for this weapon - return FALSE; - } - } - return FALSE; -} -#endif -#endif diff --git a/qcsrc/common/weapons/w_blaster.qc b/qcsrc/common/weapons/w_blaster.qc deleted file mode 100644 index aa8d0a89b..000000000 --- a/qcsrc/common/weapons/w_blaster.qc +++ /dev/null @@ -1,296 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ BLASTER, -/* function */ W_Blaster, -/* ammotype */ ammo_none, -/* impulse */ 1, -/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, -/* rating */ 0, -/* color */ '1 0.5 0.5', -/* modelname */ "laser", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairlaser 0.4", -/* wepimg */ "weaponlaser", -/* refname */ "blaster", -/* wepname */ _("Blaster") -); - -#define BLASTER_SETTINGS(w_cvar,w_prop) BLASTER_SETTINGS_LIST(w_cvar, w_prop, BLASTER, blaster) -#define BLASTER_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, BOTH, animtime) \ - w_cvar(id, sn, BOTH, damage) \ - w_cvar(id, sn, BOTH, delay) \ - w_cvar(id, sn, BOTH, edgedamage) \ - w_cvar(id, sn, BOTH, force) \ - w_cvar(id, sn, BOTH, force_zscale) \ - w_cvar(id, sn, BOTH, lifetime) \ - w_cvar(id, sn, BOTH, radius) \ - w_cvar(id, sn, BOTH, refire) \ - w_cvar(id, sn, BOTH, shotangle) \ - w_cvar(id, sn, BOTH, speed) \ - w_cvar(id, sn, BOTH, spread) \ - w_cvar(id, sn, NONE, secondary) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifdef SVQC -BLASTER_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) -.float blaster_damage; -.float blaster_edgedamage; -.float blaster_radius; -.float blaster_force; -.float blaster_lifetime; -#endif -#else -#ifdef SVQC -void spawnfunc_weapon_blaster(void) { weapon_defaultspawnfunc(WEP_BLASTER); } -void spawnfunc_weapon_laser(void) { spawnfunc_weapon_blaster(); } - -void W_Blaster_Touch(void) -{ - PROJECTILE_TOUCH; - - self.event_damage = func_null; - - RadiusDamage( - self, - self.realowner, - self.blaster_damage, - self.blaster_edgedamage, - self.blaster_radius, - world, - world, - self.blaster_force, - self.projectiledeathtype, - other - ); - - remove(self); -} - -void W_Blaster_Think(void) -{ - self.movetype = MOVETYPE_FLY; - self.think = SUB_Remove; - self.nextthink = time + self.blaster_lifetime; - CSQCProjectile(self, TRUE, PROJECTILE_BLASTER, TRUE); -} - -void W_Blaster_Attack( - float atk_deathtype, - float atk_shotangle, - float atk_damage, - float atk_edgedamage, - float atk_radius, - float atk_force, - float atk_speed, - float atk_spread, - float atk_delay, - float atk_lifetime) -{ - vector s_forward = v_forward * cos(atk_shotangle * DEG2RAD) + v_up * sin(atk_shotangle * DEG2RAD); - - W_SetupShot_Dir(self, s_forward, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_B, atk_damage); - pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - entity missile = spawn(); - missile.owner = missile.realowner = self; - missile.classname = "blasterbolt"; - missile.bot_dodge = TRUE; - missile.bot_dodgerating = atk_damage; - PROJECTILE_MAKETRIGGER(missile); - - missile.blaster_damage = atk_damage; - missile.blaster_edgedamage = atk_edgedamage; - missile.blaster_radius = atk_radius; - missile.blaster_force = atk_force; - missile.blaster_lifetime = atk_lifetime; - - setorigin(missile, w_shotorg); - setsize(missile, '0 0 0', '0 0 0'); - - W_SetupProjVelocity_Explicit( - missile, - w_shotdir, - v_up, - atk_speed, - 0, - 0, - atk_spread, - FALSE - ); - - missile.angles = vectoangles(missile.velocity); - - //missile.glow_color = 250; // 244, 250 - //missile.glow_size = 120; - - missile.touch = W_Blaster_Touch; - missile.flags = FL_PROJECTILE; - missile.missile_flags = MIF_SPLASH; - missile.projectiledeathtype = atk_deathtype; - missile.think = W_Blaster_Think; - missile.nextthink = time + atk_delay; - - other = missile; MUTATOR_CALLHOOK(EditProjectile); - - if(time >= missile.nextthink) - { - entity oldself; - oldself = self; - self = missile; - self.think(); - self = oldself; - } -} -float W_Blaster(float request) -{ - switch(request) - { - case WR_AIM: - { - if(WEP_CVAR(blaster, secondary)) - { - if((random() * (WEP_CVAR_PRI(blaster, damage) + WEP_CVAR_SEC(blaster, damage))) > WEP_CVAR_PRI(blaster, damage)) - { self.BUTTON_ATCK2 = bot_aim(WEP_CVAR_SEC(blaster, speed), 0, WEP_CVAR_SEC(blaster, lifetime), FALSE); } - else - { self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(blaster, speed), 0, WEP_CVAR_PRI(blaster, lifetime), FALSE); } - } - else - { self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(blaster, speed), 0, WEP_CVAR_PRI(blaster, lifetime), FALSE); } - - return TRUE; - } - - case WR_THINK: - { - if(self.BUTTON_ATCK) - { - if(weapon_prepareattack(0, WEP_CVAR_PRI(blaster, refire))) - { - W_Blaster_Attack( - WEP_BLASTER, - WEP_CVAR_PRI(blaster, shotangle), - WEP_CVAR_PRI(blaster, damage), - WEP_CVAR_PRI(blaster, edgedamage), - WEP_CVAR_PRI(blaster, radius), - WEP_CVAR_PRI(blaster, force), - WEP_CVAR_PRI(blaster, speed), - WEP_CVAR_PRI(blaster, spread), - WEP_CVAR_PRI(blaster, delay), - WEP_CVAR_PRI(blaster, lifetime) - ); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(blaster, animtime), w_ready); - } - } - else if(self.BUTTON_ATCK2) - { - switch(WEP_CVAR(blaster, secondary)) - { - case 0: // switch to last used weapon - { - if(self.switchweapon == WEP_BLASTER) // don't do this if already switching - W_LastWeapon(); - break; - } - - case 1: // normal projectile secondary - { - if(weapon_prepareattack(1, WEP_CVAR_SEC(blaster, refire))) - { - W_Blaster_Attack( - WEP_BLASTER | HITTYPE_SECONDARY, - WEP_CVAR_SEC(blaster, shotangle), - WEP_CVAR_SEC(blaster, damage), - WEP_CVAR_SEC(blaster, edgedamage), - WEP_CVAR_SEC(blaster, radius), - WEP_CVAR_SEC(blaster, force), - WEP_CVAR_SEC(blaster, speed), - WEP_CVAR_SEC(blaster, spread), - WEP_CVAR_SEC(blaster, delay), - WEP_CVAR_SEC(blaster, lifetime) - ); - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(blaster, animtime), w_ready); - } - - break; - } - } - } - return TRUE; - } - - case WR_INIT: - { - precache_model("models/weapons/g_laser.md3"); - precache_model("models/weapons/v_laser.md3"); - precache_model("models/weapons/h_laser.iqm"); - precache_sound("weapons/lasergun_fire.wav"); - BLASTER_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP) - return TRUE; - } - - case WR_SETUP: - { - self.ammo_field = ammo_none; - return TRUE; - } - - case WR_CHECKAMMO1: - case WR_CHECKAMMO2: - { - return TRUE; // laser has infinite ammo - } - - case WR_CONFIG: - { - BLASTER_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS) - return TRUE; - } - - case WR_SUICIDEMESSAGE: - { - return WEAPON_BLASTER_SUICIDE; - } - - case WR_KILLMESSAGE: - { - return WEAPON_BLASTER_MURDER; - } - } - return FALSE; -} -#endif -#ifdef CSQC -float W_Blaster(float request) -{ - switch(request) - { - case WR_IMPACTEFFECT: - { - vector org2; - org2 = w_org + w_backoff * 6; - pointparticles(particleeffectnum("laser_impact"), org2, w_backoff * 1000, 1); - if(!w_issilent) { sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_NORM); } - return TRUE; - } - - case WR_INIT: - { - precache_sound("weapons/laserimpact.wav"); - return TRUE; - } - case WR_ZOOMRETICLE: - { - // no weapon specific image for this weapon - return FALSE; - } - } - return FALSE; -} -#endif -#endif diff --git a/qcsrc/common/weapons/w_crylink.qc b/qcsrc/common/weapons/w_crylink.qc deleted file mode 100644 index d17826a92..000000000 --- a/qcsrc/common/weapons/w_crylink.qc +++ /dev/null @@ -1,730 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ CRYLINK, -/* function */ W_Crylink, -/* ammotype */ ammo_cells, -/* impulse */ 6, -/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH, -/* rating */ BOT_PICKUP_RATING_MID, -/* color */ '1 0.5 1', -/* modelname */ "crylink", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshaircrylink 0.4", -/* wepimg */ "weaponcrylink", -/* refname */ "crylink", -/* wepname */ _("Crylink") -); - -#define CRYLINK_SETTINGS(w_cvar,w_prop) CRYLINK_SETTINGS_LIST(w_cvar, w_prop, CRYLINK, crylink) -#define CRYLINK_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, BOTH, ammo) \ - w_cvar(id, sn, BOTH, animtime) \ - w_cvar(id, sn, BOTH, damage) \ - w_cvar(id, sn, BOTH, edgedamage) \ - w_cvar(id, sn, BOTH, radius) \ - w_cvar(id, sn, BOTH, force) \ - w_cvar(id, sn, BOTH, spread) \ - w_cvar(id, sn, BOTH, refire) \ - w_cvar(id, sn, BOTH, speed) \ - w_cvar(id, sn, BOTH, shots) \ - w_cvar(id, sn, BOTH, bounces) \ - w_cvar(id, sn, BOTH, bouncedamagefactor) \ - w_cvar(id, sn, BOTH, middle_lifetime) \ - w_cvar(id, sn, BOTH, middle_fadetime) \ - w_cvar(id, sn, BOTH, other_lifetime) \ - w_cvar(id, sn, BOTH, other_fadetime) \ - w_cvar(id, sn, BOTH, linkexplode) \ - w_cvar(id, sn, BOTH, joindelay) \ - w_cvar(id, sn, BOTH, joinspread) \ - w_cvar(id, sn, BOTH, joinexplode) \ - w_cvar(id, sn, BOTH, joinexplode_damage) \ - w_cvar(id, sn, BOTH, joinexplode_edgedamage) \ - w_cvar(id, sn, BOTH, joinexplode_radius) \ - w_cvar(id, sn, BOTH, joinexplode_force) \ - w_cvar(id, sn, SEC, spreadtype) \ - w_cvar(id, sn, NONE, secondary) \ - w_prop(id, sn, float, reloading_ammo, reload_ammo) \ - w_prop(id, sn, float, reloading_time, reload_time) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifdef SVQC -CRYLINK_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) -.float gravity; -.float crylink_waitrelease; -.entity crylink_lastgroup; - -.entity queuenext; -.entity queueprev; -#endif -#else -#ifdef SVQC -void spawnfunc_weapon_crylink(void) { weapon_defaultspawnfunc(WEP_CRYLINK); } - -void W_Crylink_CheckLinks(entity e) -{ - float i; - entity p; - - if(e == world) - error("W_Crylink_CheckLinks: entity is world"); - if(e.classname != "spike" || wasfreed(e)) - error(sprintf("W_Crylink_CheckLinks: entity is not a spike but a %s (freed: %d)", e.classname, wasfreed(e))); - - p = e; - for(i = 0; i < 1000; ++i) - { - if(p.queuenext.queueprev != p || p.queueprev.queuenext != p) - error("W_Crylink_CheckLinks: queue is inconsistent"); - p = p.queuenext; - if(p == e) - break; - } - if(i >= 1000) - error("W_Crylink_CheckLinks: infinite chain"); -} - -void W_Crylink_Dequeue_Raw(entity own, entity prev, entity me, entity next) -{ - W_Crylink_CheckLinks(next); - if(me == own.crylink_lastgroup) - own.crylink_lastgroup = ((me == next) ? world : next); - prev.queuenext = next; - next.queueprev = prev; - me.classname = "spike_oktoremove"; - if(me != next) - W_Crylink_CheckLinks(next); -} - -void W_Crylink_Dequeue(entity e) -{ - W_Crylink_Dequeue_Raw(e.realowner, e.queueprev, e, e.queuenext); -} - -void W_Crylink_Reset(void) -{ - W_Crylink_Dequeue(self); - remove(self); -} - -// force projectile to explode -void W_Crylink_LinkExplode(entity e, entity e2) -{ - float a; - - if(e == e2) - return; - - a = bound(0, 1 - (time - e.fade_time) * e.fade_rate, 1); - - if(e == e.realowner.crylink_lastgroup) - e.realowner.crylink_lastgroup = world; - - float isprimary = !(e.projectiledeathtype & HITTYPE_SECONDARY); - - RadiusDamage(e, e.realowner, WEP_CVAR_BOTH(crylink, isprimary, damage) * a, WEP_CVAR_BOTH(crylink, isprimary, edgedamage) * a, WEP_CVAR_BOTH(crylink, isprimary, radius), world, world, WEP_CVAR_BOTH(crylink, isprimary, force) * a, e.projectiledeathtype, other); - - W_Crylink_LinkExplode(e.queuenext, e2); - - e.classname = "spike_oktoremove"; - remove(e); -} - -// adjust towards center -// returns the origin where they will meet... and the time till the meeting is -// stored in w_crylink_linkjoin_time. -// could possibly network this origin and time, and display a special particle -// effect when projectiles meet there :P -// jspeed: joining speed (calculate this as join spread * initial speed) -float w_crylink_linkjoin_time; -vector W_Crylink_LinkJoin(entity e, float jspeed) -{ - vector avg_origin, avg_velocity; - vector targ_origin; - float avg_dist, n; - entity p; - - // FIXME remove this debug code - W_Crylink_CheckLinks(e); - - w_crylink_linkjoin_time = 0; - - avg_origin = e.origin; - avg_velocity = e.velocity; - n = 1; - for(p = e; (p = p.queuenext) != e; ) - { - avg_origin += WarpZone_RefSys_TransformOrigin(p, e, p.origin); - avg_velocity += WarpZone_RefSys_TransformVelocity(p, e, p.velocity); - ++n; - } - avg_origin *= (1.0 / n); - avg_velocity *= (1.0 / n); - - if(n < 2) - return avg_origin; // nothing to do - - // yes, mathematically we can do this in ONE step, but beware of 32bit floats... - avg_dist = pow(vlen(e.origin - avg_origin), 2); - for(p = e; (p = p.queuenext) != e; ) - avg_dist += pow(vlen(WarpZone_RefSys_TransformOrigin(p, e, p.origin) - avg_origin), 2); - avg_dist *= (1.0 / n); - avg_dist = sqrt(avg_dist); - - if(avg_dist == 0) - return avg_origin; // no change needed - - if(jspeed == 0) - { - e.velocity = avg_velocity; - UpdateCSQCProjectile(e); - for(p = e; (p = p.queuenext) != e; ) - { - p.velocity = WarpZone_RefSys_TransformVelocity(e, p, avg_velocity); - UpdateCSQCProjectile(p); - } - targ_origin = avg_origin + 1000000000 * normalize(avg_velocity); // HUUUUUUGE - } - else - { - w_crylink_linkjoin_time = avg_dist / jspeed; - targ_origin = avg_origin + w_crylink_linkjoin_time * avg_velocity; - - e.velocity = (targ_origin - e.origin) * (1.0 / w_crylink_linkjoin_time); - UpdateCSQCProjectile(e); - for(p = e; (p = p.queuenext) != e; ) - { - p.velocity = WarpZone_RefSys_TransformVelocity(e, p, (targ_origin - WarpZone_RefSys_TransformOrigin(p, e, p.origin)) * (1.0 / w_crylink_linkjoin_time)); - UpdateCSQCProjectile(p); - } - - // analysis: - // jspeed -> +infinity: - // w_crylink_linkjoin_time -> +0 - // targ_origin -> avg_origin - // p->velocity -> HUEG towards center - // jspeed -> 0: - // w_crylink_linkjoin_time -> +/- infinity - // targ_origin -> avg_velocity * +/- infinity - // p->velocity -> avg_velocity - // jspeed -> -infinity: - // w_crylink_linkjoin_time -> -0 - // targ_origin -> avg_origin - // p->velocity -> HUEG away from center - } - - W_Crylink_CheckLinks(e); - - return targ_origin; -} - -void W_Crylink_LinkJoinEffect_Think(void) -{ - // is there at least 2 projectiles very close? - entity e, p; - float n; - e = self.owner.crylink_lastgroup; - n = 0; - if(e) - { - if(vlen(e.origin - self.origin) < vlen(e.velocity) * frametime) - ++n; - for(p = e; (p = p.queuenext) != e; ) - { - if(vlen(p.origin - self.origin) < vlen(p.velocity) * frametime) - ++n; - } - if(n >= 2) - { - float isprimary = !(e.projectiledeathtype & HITTYPE_SECONDARY); - - if(WEP_CVAR_BOTH(crylink, isprimary, joinexplode)) - { - n /= WEP_CVAR_BOTH(crylink, isprimary, shots); - RadiusDamage( - e, - e.realowner, - WEP_CVAR_BOTH(crylink, isprimary, joinexplode_damage) * n, - WEP_CVAR_BOTH(crylink, isprimary, joinexplode_edgedamage) * n, - WEP_CVAR_BOTH(crylink, isprimary, joinexplode_radius) * n, - e.realowner, - world, - WEP_CVAR_BOTH(crylink, isprimary, joinexplode_force) * n, - e.projectiledeathtype, - other - ); - pointparticles(particleeffectnum("crylink_joinexplode"), self.origin, '0 0 0', n); - } - } - } - remove(self); -} - -float W_Crylink_Touch_WouldHitFriendly(entity projectile, float rad) -{ - entity head = WarpZone_FindRadius((projectile.origin + (projectile.mins + projectile.maxs) * 0.5), rad + MAX_DAMAGEEXTRARADIUS, FALSE); - float hit_friendly = 0; - float hit_enemy = 0; - - while(head) - { - if((head.takedamage != DAMAGE_NO) && (head.deadflag == DEAD_NO)) - { - if(SAME_TEAM(head, projectile.realowner)) - ++hit_friendly; - else - ++hit_enemy; - } - - head = head.chain; - } - - return (hit_enemy ? FALSE : hit_friendly); -} - -// NO bounce protection, as bounces are limited! -void W_Crylink_Touch(void) -{ - float finalhit; - float f; - float isprimary = !(self.projectiledeathtype & HITTYPE_SECONDARY); - PROJECTILE_TOUCH; - - float a; - a = bound(0, 1 - (time - self.fade_time) * self.fade_rate, 1); - - finalhit = ((self.cnt <= 0) || (other.takedamage != DAMAGE_NO)); - if(finalhit) - f = 1; - else - f = WEP_CVAR_BOTH(crylink, isprimary, bouncedamagefactor); - if(a) - f *= a; - - float totaldamage = RadiusDamage(self, self.realowner, WEP_CVAR_BOTH(crylink, isprimary, damage) * f, WEP_CVAR_BOTH(crylink, isprimary, edgedamage) * f, WEP_CVAR_BOTH(crylink, isprimary, radius), world, world, WEP_CVAR_BOTH(crylink, isprimary, force) * f, self.projectiledeathtype, other); - - if(totaldamage && ((WEP_CVAR_BOTH(crylink, isprimary, linkexplode) == 2) || ((WEP_CVAR_BOTH(crylink, isprimary, linkexplode) == 1) && !W_Crylink_Touch_WouldHitFriendly(self, WEP_CVAR_BOTH(crylink, isprimary, radius))))) - { - if(self == self.realowner.crylink_lastgroup) - self.realowner.crylink_lastgroup = world; - W_Crylink_LinkExplode(self.queuenext, self); - self.classname = "spike_oktoremove"; - remove(self); - return; - } - else if(finalhit) - { - // just unlink - W_Crylink_Dequeue(self); - remove(self); - return; - } - self.cnt = self.cnt - 1; - self.angles = vectoangles(self.velocity); - self.owner = world; - self.projectiledeathtype |= HITTYPE_BOUNCE; - // commented out as it causes a little hitch... - //if(proj.cnt == 0) - // CSQCProjectile(proj, TRUE, PROJECTILE_CRYLINK, TRUE); -} - -void W_Crylink_Fadethink(void) -{ - W_Crylink_Dequeue(self); - remove(self); -} - -void W_Crylink_Attack(void) -{ - float counter, shots; - entity proj, prevproj, firstproj; - vector s; - vector forward, right, up; - float maxdmg; - - W_DecreaseAmmo(WEP_CVAR_PRI(crylink, ammo)); - - maxdmg = WEP_CVAR_PRI(crylink, damage) * WEP_CVAR_PRI(crylink, shots); - maxdmg *= 1 + WEP_CVAR_PRI(crylink, bouncedamagefactor) * WEP_CVAR_PRI(crylink, bounces); - if(WEP_CVAR_PRI(crylink, joinexplode)) - maxdmg += WEP_CVAR_PRI(crylink, joinexplode_damage); - - W_SetupShot(self, FALSE, 2, "weapons/crylink_fire.wav", CH_WEAPON_A, maxdmg); - forward = v_forward; - right = v_right; - up = v_up; - - shots = WEP_CVAR_PRI(crylink, shots); - pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots); - proj = prevproj = firstproj = world; - for(counter = 0; counter < shots; ++counter) - { - proj = spawn(); - proj.reset = W_Crylink_Reset; - proj.realowner = proj.owner = self; - proj.classname = "spike"; - proj.bot_dodge = TRUE; - proj.bot_dodgerating = WEP_CVAR_PRI(crylink, damage); - if(shots == 1) { - proj.queuenext = proj; - proj.queueprev = proj; - } - else if(counter == 0) { // first projectile, store in firstproj for now - firstproj = proj; - } - else if(counter == shots - 1) { // last projectile, link up with first projectile - prevproj.queuenext = proj; - firstproj.queueprev = proj; - proj.queuenext = firstproj; - proj.queueprev = prevproj; - } - else { // else link up with previous projectile - prevproj.queuenext = proj; - proj.queueprev = prevproj; - } - - prevproj = proj; - - proj.movetype = MOVETYPE_BOUNCEMISSILE; - PROJECTILE_MAKETRIGGER(proj); - proj.projectiledeathtype = WEP_CRYLINK; - //proj.gravity = 0.001; - - setorigin(proj, w_shotorg); - setsize(proj, '0 0 0', '0 0 0'); - - - s = '0 0 0'; - if(counter == 0) - s = '0 0 0'; - else - { - makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1))); - s_y = v_forward_x; - s_z = v_forward_y; - } - s = s * WEP_CVAR_PRI(crylink, spread) * g_weaponspreadfactor; - W_SetupProjVelocity_Explicit(proj, w_shotdir + right * s_y + up * s_z, v_up, WEP_CVAR_PRI(crylink, speed), 0, 0, 0, FALSE); - proj.touch = W_Crylink_Touch; - - proj.think = W_Crylink_Fadethink; - if(counter == 0) - { - proj.fade_time = time + WEP_CVAR_PRI(crylink, middle_lifetime); - proj.fade_rate = 1 / WEP_CVAR_PRI(crylink, middle_fadetime); - proj.nextthink = time + WEP_CVAR_PRI(crylink, middle_lifetime) + WEP_CVAR_PRI(crylink, middle_fadetime); - } - else - { - proj.fade_time = time + WEP_CVAR_PRI(crylink, other_lifetime); - proj.fade_rate = 1 / WEP_CVAR_PRI(crylink, other_fadetime); - proj.nextthink = time + WEP_CVAR_PRI(crylink, other_lifetime) + WEP_CVAR_PRI(crylink, other_fadetime); - } - proj.teleport_time = time + WEP_CVAR_PRI(crylink, joindelay); - proj.cnt = WEP_CVAR_PRI(crylink, bounces); - //proj.scale = 1 + 1 * proj.cnt; - - proj.angles = vectoangles(proj.velocity); - - //proj.glow_size = 20; - - proj.flags = FL_PROJECTILE; - proj.missile_flags = MIF_SPLASH; - - CSQCProjectile(proj, TRUE, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), TRUE); - - other = proj; MUTATOR_CALLHOOK(EditProjectile); - } - if(WEP_CVAR_PRI(crylink, joinspread) != 0) - { - self.crylink_lastgroup = proj; - W_Crylink_CheckLinks(proj); - self.crylink_waitrelease = 1; - } -} - -void W_Crylink_Attack2(void) -{ - float counter, shots; - entity proj, prevproj, firstproj; - vector s; - vector forward, right, up; - float maxdmg; - - W_DecreaseAmmo(WEP_CVAR_SEC(crylink, ammo)); - - maxdmg = WEP_CVAR_SEC(crylink, damage) * WEP_CVAR_SEC(crylink, shots); - maxdmg *= 1 + WEP_CVAR_SEC(crylink, bouncedamagefactor) * WEP_CVAR_SEC(crylink, bounces); - if(WEP_CVAR_SEC(crylink, joinexplode)) - maxdmg += WEP_CVAR_SEC(crylink, joinexplode_damage); - - W_SetupShot(self, FALSE, 2, "weapons/crylink_fire2.wav", CH_WEAPON_A, maxdmg); - forward = v_forward; - right = v_right; - up = v_up; - - shots = WEP_CVAR_SEC(crylink, shots); - pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots); - proj = prevproj = firstproj = world; - for(counter = 0; counter < shots; ++counter) - { - proj = spawn(); - proj.reset = W_Crylink_Reset; - proj.realowner = proj.owner = self; - proj.classname = "spike"; - proj.bot_dodge = TRUE; - proj.bot_dodgerating = WEP_CVAR_SEC(crylink, damage); - if(shots == 1) { - proj.queuenext = proj; - proj.queueprev = proj; - } - else if(counter == 0) { // first projectile, store in firstproj for now - firstproj = proj; - } - else if(counter == shots - 1) { // last projectile, link up with first projectile - prevproj.queuenext = proj; - firstproj.queueprev = proj; - proj.queuenext = firstproj; - proj.queueprev = prevproj; - } - else { // else link up with previous projectile - prevproj.queuenext = proj; - proj.queueprev = prevproj; - } - - prevproj = proj; - - proj.movetype = MOVETYPE_BOUNCEMISSILE; - PROJECTILE_MAKETRIGGER(proj); - proj.projectiledeathtype = WEP_CRYLINK | HITTYPE_SECONDARY; - //proj.gravity = 0.001; - - setorigin(proj, w_shotorg); - setsize(proj, '0 0 0', '0 0 0'); - - if(WEP_CVAR_SEC(crylink, spreadtype) == 1) - { - s = '0 0 0'; - if(counter == 0) - s = '0 0 0'; - else - { - makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1))); - s_y = v_forward_x; - s_z = v_forward_y; - } - s = s * WEP_CVAR_SEC(crylink, spread) * g_weaponspreadfactor; - s = w_shotdir + right * s_y + up * s_z; - } - else - { - s = (w_shotdir + (((counter + 0.5) / shots) * 2 - 1) * v_right * WEP_CVAR_SEC(crylink, spread) * g_weaponspreadfactor); - } - - W_SetupProjVelocity_Explicit(proj, s, v_up, WEP_CVAR_SEC(crylink, speed), 0, 0, 0, FALSE); - proj.touch = W_Crylink_Touch; - proj.think = W_Crylink_Fadethink; - if(counter == (shots - 1) / 2) - { - proj.fade_time = time + WEP_CVAR_SEC(crylink, middle_lifetime); - proj.fade_rate = 1 / WEP_CVAR_SEC(crylink, middle_fadetime); - proj.nextthink = time + WEP_CVAR_SEC(crylink, middle_lifetime) + WEP_CVAR_SEC(crylink, middle_fadetime); - } - else - { - proj.fade_time = time + WEP_CVAR_SEC(crylink, other_lifetime); - proj.fade_rate = 1 / WEP_CVAR_SEC(crylink, other_fadetime); - proj.nextthink = time + WEP_CVAR_SEC(crylink, other_lifetime) + WEP_CVAR_SEC(crylink, other_fadetime); - } - proj.teleport_time = time + WEP_CVAR_SEC(crylink, joindelay); - proj.cnt = WEP_CVAR_SEC(crylink, bounces); - //proj.scale = 1 + 1 * proj.cnt; - - proj.angles = vectoangles(proj.velocity); - - //proj.glow_size = 20; - - proj.flags = FL_PROJECTILE; - proj.missile_flags = MIF_SPLASH; - - CSQCProjectile(proj, TRUE, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), TRUE); - - other = proj; MUTATOR_CALLHOOK(EditProjectile); - } - if(WEP_CVAR_SEC(crylink, joinspread) != 0) - { - self.crylink_lastgroup = proj; - W_Crylink_CheckLinks(proj); - self.crylink_waitrelease = 2; - } -} - -float W_Crylink(float req) -{ - float ammo_amount; - switch(req) - { - case WR_AIM: - { - if(random() < 0.10) - self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(crylink, speed), 0, WEP_CVAR_PRI(crylink, middle_lifetime), FALSE); - else - self.BUTTON_ATCK2 = bot_aim(WEP_CVAR_SEC(crylink, speed), 0, WEP_CVAR_SEC(crylink, middle_lifetime), FALSE); - - return TRUE; - } - case WR_THINK: - { - if(autocvar_g_balance_crylink_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo))) // forced reload - WEP_ACTION(self.weapon, WR_RELOAD); - - if(self.BUTTON_ATCK) - { - if(self.crylink_waitrelease != 1) - if(weapon_prepareattack(0, WEP_CVAR_PRI(crylink, refire))) - { - W_Crylink_Attack(); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(crylink, animtime), w_ready); - } - } - - if(self.BUTTON_ATCK2 && autocvar_g_balance_crylink_secondary) - { - if(self.crylink_waitrelease != 2) - if(weapon_prepareattack(1, WEP_CVAR_SEC(crylink, refire))) - { - W_Crylink_Attack2(); - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(crylink, animtime), w_ready); - } - } - - if((self.crylink_waitrelease == 1 && !self.BUTTON_ATCK) || (self.crylink_waitrelease == 2 && !self.BUTTON_ATCK2)) - { - if(!self.crylink_lastgroup || time > self.crylink_lastgroup.teleport_time) - { - // fired and released now! - if(self.crylink_lastgroup) - { - vector pos; - entity linkjoineffect; - float isprimary = (self.crylink_waitrelease == 1); - - pos = W_Crylink_LinkJoin(self.crylink_lastgroup, WEP_CVAR_BOTH(crylink, isprimary, joinspread) * WEP_CVAR_BOTH(crylink, isprimary, speed)); - - linkjoineffect = spawn(); - linkjoineffect.think = W_Crylink_LinkJoinEffect_Think; - linkjoineffect.classname = "linkjoineffect"; - linkjoineffect.nextthink = time + w_crylink_linkjoin_time; - linkjoineffect.owner = self; - setorigin(linkjoineffect, pos); - } - self.crylink_waitrelease = 0; - if(!W_Crylink(WR_CHECKAMMO1) && !W_Crylink(WR_CHECKAMMO2)) - if(!(self.items & IT_UNLIMITED_WEAPON_AMMO)) - { - // ran out of ammo! - self.cnt = WEP_CRYLINK; - self.switchweapon = w_getbestweapon(self); - } - } - } - - return TRUE; - } - case WR_INIT: - { - precache_model("models/weapons/g_crylink.md3"); - precache_model("models/weapons/v_crylink.md3"); - precache_model("models/weapons/h_crylink.iqm"); - precache_sound("weapons/crylink_fire.wav"); - precache_sound("weapons/crylink_fire2.wav"); - precache_sound("weapons/crylink_linkjoin.wav"); - CRYLINK_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP) - return TRUE; - } - case WR_CHECKAMMO1: - { - // don't "run out of ammo" and switch weapons while waiting for release - if(self.crylink_lastgroup && self.crylink_waitrelease) - return TRUE; - - ammo_amount = self.WEP_AMMO(CRYLINK) >= WEP_CVAR_PRI(crylink, ammo); - ammo_amount += self.(weapon_load[WEP_CRYLINK]) >= WEP_CVAR_PRI(crylink, ammo); - return ammo_amount; - } - case WR_CHECKAMMO2: - { - // don't "run out of ammo" and switch weapons while waiting for release - if(self.crylink_lastgroup && self.crylink_waitrelease) - return TRUE; - - ammo_amount = self.WEP_AMMO(CRYLINK) >= WEP_CVAR_SEC(crylink, ammo); - ammo_amount += self.(weapon_load[WEP_CRYLINK]) >= WEP_CVAR_SEC(crylink, ammo); - return ammo_amount; - } - case WR_CONFIG: - { - CRYLINK_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS) - return TRUE; - } - case WR_RELOAD: - { - W_Reload(min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo)), "weapons/reload.wav"); - return TRUE; - } - case WR_SUICIDEMESSAGE: - { - return WEAPON_CRYLINK_SUICIDE; - } - case WR_KILLMESSAGE: - { - return WEAPON_CRYLINK_MURDER; - } - } - return FALSE; -} -#endif -#ifdef CSQC -float W_Crylink(float req) -{ - switch(req) - { - case WR_IMPACTEFFECT: - { - vector org2; - org2 = w_org + w_backoff * 2; - if(w_deathtype & HITTYPE_SECONDARY) - { - pointparticles(particleeffectnum("crylink_impact"), org2, '0 0 0', 1); - if(!w_issilent) - sound(self, CH_SHOTS, "weapons/crylink_impact2.wav", VOL_BASE, ATTN_NORM); - } - else - { - pointparticles(particleeffectnum("crylink_impactbig"), org2, '0 0 0', 1); - if(!w_issilent) - sound(self, CH_SHOTS, "weapons/crylink_impact.wav", VOL_BASE, ATTN_NORM); - } - - return TRUE; - } - case WR_INIT: - { - precache_sound("weapons/crylink_impact2.wav"); - precache_sound("weapons/crylink_impact.wav"); - return TRUE; - } - case WR_ZOOMRETICLE: - { - // no weapon specific image for this weapon - return FALSE; - } - } - return FALSE; -} -#endif -#endif diff --git a/qcsrc/common/weapons/w_devastator.qc b/qcsrc/common/weapons/w_devastator.qc deleted file mode 100644 index 2e69c5f53..000000000 --- a/qcsrc/common/weapons/w_devastator.qc +++ /dev/null @@ -1,683 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ DEVASTATOR, -/* function */ W_Devastator, -/* ammotype */ ammo_rockets, -/* impulse */ 9, -/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, -/* rating */ BOT_PICKUP_RATING_HIGH, -/* color */ '1 1 0', -/* modelname */ "rl", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairrocketlauncher 0.5875", -/* wepimg */ "weaponrocketlauncher", -/* refname */ "devastator", -/* wepname */ _("Devastator") -); - -#define DEVASTATOR_SETTINGS(w_cvar,w_prop) DEVASTATOR_SETTINGS_LIST(w_cvar, w_prop, DEVASTATOR, devastator) -#define DEVASTATOR_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, NONE, ammo) \ - w_cvar(id, sn, NONE, animtime) \ - w_cvar(id, sn, NONE, damage) \ - w_cvar(id, sn, NONE, damageforcescale) \ - w_cvar(id, sn, NONE, detonatedelay) \ - w_cvar(id, sn, NONE, edgedamage) \ - w_cvar(id, sn, NONE, force) \ - w_cvar(id, sn, NONE, guidedelay) \ - w_cvar(id, sn, NONE, guidegoal) \ - w_cvar(id, sn, NONE, guiderate) \ - w_cvar(id, sn, NONE, guideratedelay) \ - w_cvar(id, sn, NONE, guidestop) \ - w_cvar(id, sn, NONE, health) \ - w_cvar(id, sn, NONE, lifetime) \ - w_cvar(id, sn, NONE, radius) \ - w_cvar(id, sn, NONE, refire) \ - w_cvar(id, sn, NONE, remote_damage) \ - w_cvar(id, sn, NONE, remote_edgedamage) \ - w_cvar(id, sn, NONE, remote_force) \ - w_cvar(id, sn, NONE, remote_jump_damage) \ - w_cvar(id, sn, NONE, remote_jump_radius) \ - w_cvar(id, sn, NONE, remote_jump_velocity_z_add) \ - w_cvar(id, sn, NONE, remote_jump_velocity_z_max) \ - w_cvar(id, sn, NONE, remote_jump_velocity_z_min) \ - w_cvar(id, sn, NONE, remote_radius) \ - w_cvar(id, sn, NONE, speed) \ - w_cvar(id, sn, NONE, speedaccel) \ - w_cvar(id, sn, NONE, speedstart) \ - w_prop(id, sn, float, reloading_ammo, reload_ammo) \ - w_prop(id, sn, float, reloading_time, reload_time) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifdef SVQC -DEVASTATOR_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) -.float rl_release; -.float rl_detonate_later; -#endif -#else -#ifdef SVQC -void spawnfunc_weapon_devastator(void) { weapon_defaultspawnfunc(WEP_DEVASTATOR); } -void spawnfunc_weapon_rocketlauncher(void) { spawnfunc_weapon_devastator(); } - -void W_Devastator_Unregister(void) -{ - if(self.realowner && self.realowner.lastrocket == self) - { - self.realowner.lastrocket = world; - // self.realowner.rl_release = 1; - } -} - -void W_Devastator_Explode(void) -{ - W_Devastator_Unregister(); - - if(other.takedamage == DAMAGE_AIM) - if(IS_PLAYER(other)) - if(DIFF_TEAM(self.realowner, other)) - if(other.deadflag == DEAD_NO) - if(IsFlying(other)) - Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT); - - self.event_damage = func_null; - self.takedamage = DAMAGE_NO; - - RadiusDamage( - self, - self.realowner, - WEP_CVAR(devastator, damage), - WEP_CVAR(devastator, edgedamage), - WEP_CVAR(devastator, radius), - world, - world, - WEP_CVAR(devastator, force), - self.projectiledeathtype, - other - ); - - if(self.realowner.weapon == WEP_DEVASTATOR) - { - if(self.realowner.WEP_AMMO(DEVASTATOR) < WEP_CVAR(devastator, ammo)) - { - self.realowner.cnt = WEP_DEVASTATOR; - ATTACK_FINISHED(self.realowner) = time; - self.realowner.switchweapon = w_getbestweapon(self.realowner); - } - } - remove(self); -} - -void W_Devastator_DoRemoteExplode(void) -{ - W_Devastator_Unregister(); - - self.event_damage = func_null; - self.takedamage = DAMAGE_NO; - - float handled_as_rocketjump = FALSE; - - entity head = WarpZone_FindRadius( - self.origin, - WEP_CVAR(devastator, remote_jump_radius), - FALSE - ); - - while(head) - { - if(head.takedamage && (head == self.realowner)) - { - float distance_to_head = vlen(self.origin - head.WarpZone_findradius_nearest); - if(distance_to_head <= WEP_CVAR(devastator, remote_jump_radius)) - { - // we handled this as a rocketjump :) - handled_as_rocketjump = TRUE; - - // modify velocity - head.velocity_x *= 0.9; - head.velocity_y *= 0.9; - head.velocity_z = bound( - WEP_CVAR(devastator, remote_jump_velocity_z_min), - head.velocity_z + WEP_CVAR(devastator, remote_jump_velocity_z_add), - WEP_CVAR(devastator, remote_jump_velocity_z_max) - ); - - // now do the damage - RadiusDamage( - self, - head, - WEP_CVAR(devastator, remote_jump_damage), - WEP_CVAR(devastator, remote_jump_damage), - WEP_CVAR(devastator, remote_jump_radius), - world, - head, - 0, - self.projectiledeathtype | HITTYPE_BOUNCE, - world - ); - break; - } - } - head = head.chain; - } - - RadiusDamage( - self, - self.realowner, - WEP_CVAR(devastator, remote_damage), - WEP_CVAR(devastator, remote_edgedamage), - WEP_CVAR(devastator, remote_radius), - (handled_as_rocketjump ? head : world), - world, - WEP_CVAR(devastator, remote_force), - self.projectiledeathtype | HITTYPE_BOUNCE, - world - ); - - if(self.realowner.weapon == WEP_DEVASTATOR) - { - if(self.realowner.WEP_AMMO(DEVASTATOR) < WEP_CVAR(devastator, ammo)) - { - self.realowner.cnt = WEP_DEVASTATOR; - ATTACK_FINISHED(self.realowner) = time; - self.realowner.switchweapon = w_getbestweapon(self.realowner); - } - } - remove(self); -} - -void W_Devastator_RemoteExplode(void) -{ - if(self.realowner.deadflag == DEAD_NO) - if(self.realowner.lastrocket) - { - if((self.spawnshieldtime >= 0) - ? (time >= self.spawnshieldtime) // timer - : (vlen(NearestPointOnBox(self.realowner, self.origin) - self.origin) > WEP_CVAR(devastator, remote_radius)) // safety device - ) - { - W_Devastator_DoRemoteExplode(); - } - } -} - -vector W_Devastator_SteerTo(vector thisdir, vector goaldir, float maxturn_cos) -{ - if(thisdir * goaldir > maxturn_cos) - return goaldir; - if(thisdir * goaldir < -0.9998) // less than 1 degree and opposite - return thisdir; // refuse to guide (better than letting a numerical error happen) - float f, m2; - vector v; - // solve: - // g = normalize(thisdir + goaldir * X) - // thisdir * g = maxturn - // - // gg = thisdir + goaldir * X - // (thisdir * gg)^2 = maxturn^2 * (gg * gg) - // - // (1 + (thisdir * goaldir) * X)^2 = maxturn^2 * (1 + X*X + 2 * X * thisdir * goaldir) - f = thisdir * goaldir; - // (1 + f * X)^2 = maxturn^2 * (1 + X*X + 2 * X * f) - // 0 = (m^2 - f^2) * x^2 + (2 * f * (m^2 - 1)) * x + (m^2 - 1) - m2 = maxturn_cos * maxturn_cos; - v = solve_quadratic(m2 - f * f, 2 * f * (m2 - 1), m2 - 1); - return normalize(thisdir + goaldir * v_y); // the larger solution! -} -// assume thisdir == -goaldir: -// f == -1 -// v = solve_qadratic(m2 - 1, -2 * (m2 - 1), m2 - 1) -// (m2 - 1) x^2 - 2 * (m2 - 1) * x + (m2 - 1) = 0 -// x^2 - 2 * x + 1 = 0 -// (x - 1)^2 = 0 -// x = 1 -// normalize(thisdir + goaldir) -// normalize(0) - -void W_Devastator_Think(void) -{ - vector desireddir, olddir, newdir, desiredorigin, goal; - float velspeed, f; - self.nextthink = time; - if(time > self.cnt) - { - other = world; - self.projectiledeathtype |= HITTYPE_BOUNCE; - W_Devastator_Explode(); - return; - } - - // accelerate - makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0'); - velspeed = WEP_CVAR(devastator, speed) * g_weaponspeedfactor - (self.velocity * v_forward); - if(velspeed > 0) - self.velocity = self.velocity + v_forward * min(WEP_CVAR(devastator, speedaccel) * g_weaponspeedfactor * frametime, velspeed); - - // laser guided, or remote detonation - if(self.realowner.weapon == WEP_DEVASTATOR) - { - if(self == self.realowner.lastrocket) - if(!self.realowner.rl_release) - if(!self.BUTTON_ATCK2) - if(WEP_CVAR(devastator, guiderate)) - if(time > self.pushltime) - if(self.realowner.deadflag == DEAD_NO) - { - f = WEP_CVAR(devastator, guideratedelay); - if(f) - f = bound(0, (time - self.pushltime) / f, 1); - else - f = 1; - - velspeed = vlen(self.velocity); - - makevectors(self.realowner.v_angle); - desireddir = WarpZone_RefSys_TransformVelocity(self.realowner, self, v_forward); - desiredorigin = WarpZone_RefSys_TransformOrigin(self.realowner, self, self.realowner.origin + self.realowner.view_ofs); - olddir = normalize(self.velocity); - - // now it gets tricky... we want to move like some curve to approximate the target direction - // but we are limiting the rate at which we can turn! - goal = desiredorigin + ((self.origin - desiredorigin) * desireddir + WEP_CVAR(devastator, guidegoal)) * desireddir; - newdir = W_Devastator_SteerTo(olddir, normalize(goal - self.origin), cos(WEP_CVAR(devastator, guiderate) * f * frametime * DEG2RAD)); - - self.velocity = newdir * velspeed; - self.angles = vectoangles(self.velocity); - - if(!self.count) - { - pointparticles(particleeffectnum("rocket_guide"), self.origin, self.velocity, 1); - // TODO add a better sound here - sound(self.realowner, CH_WEAPON_B, "weapons/rocket_mode.wav", VOL_BASE, ATTN_NORM); - self.count = 1; - } - } - - if(self.rl_detonate_later) - W_Devastator_RemoteExplode(); - } - - if(self.csqcprojectile_clientanimate == 0) - UpdateCSQCProjectile(self); -} - -void W_Devastator_Touch(void) -{ - if(WarpZone_Projectile_Touch()) - { - if(wasfreed(self)) - W_Devastator_Unregister(); - return; - } - W_Devastator_Unregister(); - W_Devastator_Explode(); -} - -void W_Devastator_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) -{ - if(self.health <= 0) - return; - - if(!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions - return; // g_projectiles_damage says to halt - - self.health = self.health - damage; - self.angles = vectoangles(self.velocity); - - if(self.health <= 0) - W_PrepareExplosionByDamage(attacker, W_Devastator_Explode); -} - -void W_Devastator_Attack(void) -{ - entity missile; - entity flash; - - W_DecreaseAmmo(WEP_CVAR(devastator, ammo)); - - W_SetupShot_ProjectileSize(self, '-3 -3 -3', '3 3 3', FALSE, 5, "weapons/rocket_fire.wav", CH_WEAPON_A, WEP_CVAR(devastator, damage)); - pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - missile = WarpZone_RefSys_SpawnSameRefSys(self); - missile.owner = missile.realowner = self; - self.lastrocket = missile; - if(WEP_CVAR(devastator, detonatedelay) >= 0) - missile.spawnshieldtime = time + WEP_CVAR(devastator, detonatedelay); - else - missile.spawnshieldtime = -1; - missile.pushltime = time + WEP_CVAR(devastator, guidedelay); - missile.classname = "rocket"; - missile.bot_dodge = TRUE; - missile.bot_dodgerating = WEP_CVAR(devastator, damage) * 2; // * 2 because it can be detonated inflight which makes it even more dangerous - - missile.takedamage = DAMAGE_YES; - missile.damageforcescale = WEP_CVAR(devastator, damageforcescale); - missile.health = WEP_CVAR(devastator, health); - missile.event_damage = W_Devastator_Damage; - missile.damagedbycontents = TRUE; - - missile.movetype = MOVETYPE_FLY; - PROJECTILE_MAKETRIGGER(missile); - missile.projectiledeathtype = WEP_DEVASTATOR; - setsize(missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot - - setorigin(missile, w_shotorg - v_forward * 3); // move it back so it hits the wall at the right point - W_SetupProjVelocity_Basic(missile, WEP_CVAR(devastator, speedstart), 0); - missile.angles = vectoangles(missile.velocity); - - missile.touch = W_Devastator_Touch; - missile.think = W_Devastator_Think; - missile.nextthink = time; - missile.cnt = time + WEP_CVAR(devastator, lifetime); - missile.flags = FL_PROJECTILE; - missile.missile_flags = MIF_SPLASH; - - CSQCProjectile(missile, WEP_CVAR(devastator, guiderate) == 0 && WEP_CVAR(devastator, speedaccel) == 0, PROJECTILE_ROCKET, FALSE); // because of fly sound - - // 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 - other = missile; MUTATOR_CALLHOOK(EditProjectile); -} - -float W_Devastator(float req) -{ - entity rock; - float rockfound; - float ammo_amount; - switch(req) - { - #if 0 - case WR_AIM: - { - // aim and decide to fire if appropriate - self.BUTTON_ATCK = bot_aim(WEP_CVAR(devastator, speed), 0, WEP_CVAR(devastator, lifetime), FALSE); - if(skill >= 2) // skill 0 and 1 bots won't detonate rockets! - { - // decide whether to detonate rockets - entity missile, targetlist, targ; - targetlist = findchainfloat(bot_attack, TRUE); - for(missile = world; (missile = find(missile, classname, "rocket")); ) if(missile.realowner == self) - { - targ = targetlist; - while(targ) - { - if(targ != missile.realowner && vlen(targ.origin - missile.origin) < WEP_CVAR(devastator, radius)) - { - self.BUTTON_ATCK2 = TRUE; - break; - } - targ = targ.chain; - } - } - - if(self.BUTTON_ATCK2) self.BUTTON_ATCK = FALSE; - } - - return TRUE; - } - #else - case WR_AIM: - { - // aim and decide to fire if appropriate - self.BUTTON_ATCK = bot_aim(WEP_CVAR(devastator, speed), 0, WEP_CVAR(devastator, lifetime), FALSE); - if(skill >= 2) // skill 0 and 1 bots won't detonate rockets! - { - // decide whether to detonate rockets - entity missile, targetlist, targ; - float edgedamage, coredamage, edgeradius, recipricoledgeradius, d; - float selfdamage, teamdamage, enemydamage; - edgedamage = WEP_CVAR(devastator, edgedamage); - coredamage = WEP_CVAR(devastator, damage); - edgeradius = WEP_CVAR(devastator, radius); - recipricoledgeradius = 1 / edgeradius; - selfdamage = 0; - teamdamage = 0; - enemydamage = 0; - targetlist = findchainfloat(bot_attack, TRUE); - missile = find(world, classname, "rocket"); - while(missile) - { - if(missile.realowner != self) - { - missile = find(missile, classname, "rocket"); - continue; - } - targ = targetlist; - while(targ) - { - d = vlen(targ.origin + (targ.mins + targ.maxs) * 0.5 - missile.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 && teamplay) - teamdamage = teamdamage + d; - else if(bot_shouldattack(targ)) - enemydamage = enemydamage + d; - targ = targ.chain; - } - missile = find(missile, classname, "rocket"); - } - float desirabledamage; - desirabledamage = enemydamage; - if(time > self.invincible_finished && time > self.spawnshieldtime) - desirabledamage = desirabledamage - selfdamage * autocvar_g_balance_selfdamagepercent; - if(teamplay && self.team) - desirabledamage = desirabledamage - teamdamage; - - missile = find(world, classname, "rocket"); - while(missile) - { - if(missile.realowner != self) - { - missile = find(missile, classname, "rocket"); - continue; - } - makevectors(missile.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(missile.origin - targ.origin)< 0.1) - && desirabledamage > 0.1*coredamage - )self.BUTTON_ATCK2 = TRUE; - targ = targ.chain; - } - }else{ - 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 rocket spawnfunc_light to see if the rocket gets near a player - if(v_forward * normalize(missile.origin - self.enemy.origin)< 0.1) - if(IS_PLAYER(self.enemy)) - 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"); - } - - missile = find(missile, classname, "rocket"); - } - // 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; - } - - return TRUE; - } - #endif - case WR_THINK: - { - if(WEP_CVAR(devastator, reload_ammo) && self.clip_load < WEP_CVAR(devastator, ammo)) // forced reload - WEP_ACTION(self.weapon, WR_RELOAD); - else - { - if(self.BUTTON_ATCK) - { - if(self.rl_release || WEP_CVAR(devastator, guidestop)) - if(weapon_prepareattack(0, WEP_CVAR(devastator, refire))) - { - W_Devastator_Attack(); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(devastator, animtime), w_ready); - self.rl_release = 0; - } - } - else - self.rl_release = 1; - - if(self.BUTTON_ATCK2) - { - rockfound = 0; - for(rock = world; (rock = find(rock, classname, "rocket")); ) if(rock.realowner == self) - { - if(!rock.rl_detonate_later) - { - rock.rl_detonate_later = TRUE; - rockfound = 1; - } - } - if(rockfound) - sound(self, CH_WEAPON_B, "weapons/rocket_det.wav", VOL_BASE, ATTN_NORM); - } - } - - return TRUE; - } - case WR_INIT: - { - //if(autocvar_sv_precacheweapons) - //{ - precache_model("models/flash.md3"); - precache_model("models/weapons/g_rl.md3"); - precache_model("models/weapons/v_rl.md3"); - precache_model("models/weapons/h_rl.iqm"); - precache_sound("weapons/rocket_det.wav"); - precache_sound("weapons/rocket_fire.wav"); - precache_sound("weapons/rocket_mode.wav"); - //} - DEVASTATOR_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP) - return TRUE; - } - case WR_SETUP: - { - self.rl_release = 1; - return TRUE; - } - case WR_CHECKAMMO1: - { - #if 0 - // don't switch while guiding a missile - if(ATTACK_FINISHED(self) <= time || self.weapon != WEP_DEVASTATOR) - { - ammo_amount = FALSE; - if(WEP_CVAR(devastator, reload_ammo)) - { - if(self.WEP_AMMO(DEVASTATOR) < WEP_CVAR(devastator, ammo) && self.(weapon_load[WEP_DEVASTATOR]) < WEP_CVAR(devastator, ammo)) - ammo_amount = TRUE; - } - else if(self.WEP_AMMO(DEVASTATOR) < WEP_CVAR(devastator, ammo)) - ammo_amount = TRUE; - return !ammo_amount; - } - #endif - #if 0 - if(self.rl_release == 0) - { - printf("W_Devastator(WR_CHECKAMMO1): %d, %.2f, %d: TRUE\n", self.rl_release, self.WEP_AMMO(DEVASTATOR), WEP_CVAR(devastator, ammo)); - return TRUE; - } - else - { - ammo_amount = self.WEP_AMMO(DEVASTATOR) >= WEP_CVAR(devastator, ammo); - ammo_amount += self.(weapon_load[WEP_DEVASTATOR]) >= WEP_CVAR(devastator, ammo); - printf("W_Devastator(WR_CHECKAMMO1): %d, %.2f, %d: %s\n", self.rl_release, self.WEP_AMMO(DEVASTATOR), WEP_CVAR(devastator, ammo), (ammo_amount ? "TRUE" : "FALSE")); - return ammo_amount; - } - #else - ammo_amount = self.WEP_AMMO(DEVASTATOR) >= WEP_CVAR(devastator, ammo); - ammo_amount += self.(weapon_load[WEP_DEVASTATOR]) >= WEP_CVAR(devastator, ammo); - return ammo_amount; - #endif - } - case WR_CHECKAMMO2: - { - return FALSE; - } - case WR_CONFIG: - { - DEVASTATOR_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS) - return TRUE; - } - case WR_RESETPLAYER: - { - self.rl_release = 0; - return TRUE; - } - case WR_RELOAD: - { - W_Reload(WEP_CVAR(devastator, ammo), "weapons/reload.wav"); - return TRUE; - } - case WR_SUICIDEMESSAGE: - { - return WEAPON_DEVASTATOR_SUICIDE; - } - case WR_KILLMESSAGE: - { - if((w_deathtype & HITTYPE_BOUNCE) || (w_deathtype & HITTYPE_SPLASH)) - return WEAPON_DEVASTATOR_MURDER_SPLASH; - else - return WEAPON_DEVASTATOR_MURDER_DIRECT; - } - } - return FALSE; -} -#endif -#ifdef CSQC -float W_Devastator(float req) -{ - switch(req) - { - case WR_IMPACTEFFECT: - { - vector org2; - org2 = w_org + w_backoff * 12; - pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1); - if(!w_issilent) - sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); - - return TRUE; - } - case WR_INIT: - { - precache_sound("weapons/rocket_impact.wav"); - return TRUE; - } - case WR_ZOOMRETICLE: - { - // no weapon specific image for this weapon - return FALSE; - } - } - return FALSE; -} -#endif -#endif diff --git a/qcsrc/common/weapons/w_electro.qc b/qcsrc/common/weapons/w_electro.qc deleted file mode 100644 index 3847e2d56..000000000 --- a/qcsrc/common/weapons/w_electro.qc +++ /dev/null @@ -1,620 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ ELECTRO, -/* function */ W_Electro, -/* ammotype */ ammo_cells, -/* impulse */ 5, -/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH, -/* rating */ BOT_PICKUP_RATING_MID, -/* color */ '0 0.5 1', -/* modelname */ "electro", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairelectro 0.5", -/* wepimg */ "weaponelectro", -/* refname */ "electro", -/* wepname */ _("Electro") -); - -#define ELECTRO_SETTINGS(w_cvar,w_prop) ELECTRO_SETTINGS_LIST(w_cvar, w_prop, ELECTRO, electro) -#define ELECTRO_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, BOTH, ammo) \ - w_cvar(id, sn, BOTH, animtime) \ - w_cvar(id, sn, BOTH, damage) \ - w_cvar(id, sn, BOTH, edgedamage) \ - w_cvar(id, sn, BOTH, force) \ - w_cvar(id, sn, BOTH, radius) \ - w_cvar(id, sn, BOTH, refire) \ - w_cvar(id, sn, BOTH, speed) \ - w_cvar(id, sn, BOTH, spread) \ - w_cvar(id, sn, BOTH, lifetime) \ - w_cvar(id, sn, PRI, comboradius) \ - w_cvar(id, sn, PRI, midaircombo_explode) \ - w_cvar(id, sn, PRI, midaircombo_interval) \ - w_cvar(id, sn, PRI, midaircombo_radius) \ - w_cvar(id, sn, SEC, bouncefactor) \ - w_cvar(id, sn, SEC, bouncestop) \ - w_cvar(id, sn, SEC, count) \ - w_cvar(id, sn, SEC, damageforcescale) \ - w_cvar(id, sn, SEC, damagedbycontents) \ - w_cvar(id, sn, SEC, health) \ - w_cvar(id, sn, SEC, refire2) \ - w_cvar(id, sn, SEC, speed_up) \ - w_cvar(id, sn, SEC, speed_z) \ - w_cvar(id, sn, SEC, touchexplode) \ - w_cvar(id, sn, NONE, combo_comboradius) \ - w_cvar(id, sn, NONE, combo_comboradius_thruwall) \ - w_cvar(id, sn, NONE, combo_damage) \ - w_cvar(id, sn, NONE, combo_edgedamage) \ - w_cvar(id, sn, NONE, combo_force) \ - w_cvar(id, sn, NONE, combo_radius) \ - w_cvar(id, sn, NONE, combo_speed) \ - w_cvar(id, sn, NONE, combo_safeammocheck) \ - w_prop(id, sn, float, reloading_ammo, reload_ammo) \ - w_prop(id, sn, float, reloading_time, reload_time) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifdef SVQC -ELECTRO_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) -.float electro_count; -.float electro_secondarytime; -void W_Electro_ExplodeCombo(void); -#endif -#else -#ifdef SVQC -void spawnfunc_weapon_electro(void) { weapon_defaultspawnfunc(WEP_ELECTRO); } - -void W_Electro_TriggerCombo(vector org, float rad, entity own) -{ - entity e = WarpZone_FindRadius(org, rad, !WEP_CVAR(electro, combo_comboradius_thruwall)); - while(e) - { - if(e.classname == "electro_orb") - { - // do we allow thruwall triggering? - if(WEP_CVAR(electro, combo_comboradius_thruwall)) - { - // if distance is greater than thruwall distance, check to make sure it's not through a wall - if(vlen(e.WarpZone_findradius_dist) > WEP_CVAR(electro, combo_comboradius_thruwall)) - { - WarpZone_TraceLine(org, e.origin, MOVE_NOMONSTERS, e); - if(trace_fraction != 1) - { - // trigger is through a wall and outside of thruwall range, abort - e = e.chain; - continue; - } - } - } - - // change owner to whoever caused the combo explosion - e.realowner = own; - e.takedamage = DAMAGE_NO; - e.classname = "electro_orb_chain"; - - // now set the next one to trigger as well - e.think = W_Electro_ExplodeCombo; - - // delay combo chains, looks cooler - e.nextthink = - ( - time - + - (WEP_CVAR(electro, combo_speed) ? - (vlen(e.WarpZone_findradius_dist) / WEP_CVAR(electro, combo_speed)) - : - 0 - ) - ); - } - e = e.chain; - } -} - -void W_Electro_ExplodeCombo(void) -{ - W_Electro_TriggerCombo(self.origin, WEP_CVAR(electro, combo_comboradius), self.realowner); - - self.event_damage = func_null; - - RadiusDamage( - self, - self.realowner, - WEP_CVAR(electro, combo_damage), - WEP_CVAR(electro, combo_edgedamage), - WEP_CVAR(electro, combo_radius), - world, - world, - WEP_CVAR(electro, combo_force), - WEP_ELECTRO | HITTYPE_BOUNCE, // use THIS type for a combo because primary can't bounce - world - ); - - remove(self); -} - -void W_Electro_Explode(void) -{ - if(other.takedamage == DAMAGE_AIM) - if(IS_PLAYER(other)) - if(DIFF_TEAM(self.realowner, other)) - if(other.deadflag == DEAD_NO) - if(IsFlying(other)) - Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_ELECTROBITCH); - - self.event_damage = func_null; - self.takedamage = DAMAGE_NO; - - if(self.movetype == MOVETYPE_BOUNCE) - { - RadiusDamage( - self, - self.realowner, - WEP_CVAR_SEC(electro, damage), - WEP_CVAR_SEC(electro, edgedamage), - WEP_CVAR_SEC(electro, radius), - world, - world, - WEP_CVAR_SEC(electro, force), - self.projectiledeathtype, - other - ); - } - else - { - W_Electro_TriggerCombo(self.origin, WEP_CVAR_PRI(electro, comboradius), self.realowner); - RadiusDamage( - self, - self.realowner, - WEP_CVAR_PRI(electro, damage), - WEP_CVAR_PRI(electro, edgedamage), - WEP_CVAR_PRI(electro, radius), - world, - world, - WEP_CVAR_PRI(electro, force), - self.projectiledeathtype, - other - ); - } - - remove(self); -} - -void W_Electro_TouchExplode(void) -{ - PROJECTILE_TOUCH; - W_Electro_Explode(); -} - -void W_Electro_Bolt_Think(void) -{ - if(time >= self.ltime) - { - self.use(); - return; - } - - if(WEP_CVAR_PRI(electro, midaircombo_radius)) - { - float found = 0; - entity e = WarpZone_FindRadius(self.origin, WEP_CVAR_PRI(electro, midaircombo_radius), TRUE); - - // loop through nearby orbs and trigger them - while(e) - { - if(e.classname == "electro_orb") - { - // change owner to whoever caused the combo explosion - e.realowner = self.realowner; - e.takedamage = DAMAGE_NO; - e.classname = "electro_orb_chain"; - - // now set the next one to trigger as well - e.think = W_Electro_ExplodeCombo; - - // delay combo chains, looks cooler - e.nextthink = - ( - time - + - (WEP_CVAR(electro, combo_speed) ? - (vlen(e.WarpZone_findradius_dist) / WEP_CVAR(electro, combo_speed)) - : - 0 - ) - ); - - ++found; - } - e = e.chain; - } - - // if we triggered an orb, should we explode? if not, lets try again next time - if(found && WEP_CVAR_PRI(electro, midaircombo_explode)) - { self.use(); } - else - { self.nextthink = min(time + WEP_CVAR_PRI(electro, midaircombo_interval), self.ltime); } - } - else { self.nextthink = self.ltime; } -} - -void W_Electro_Attack_Bolt(void) -{ - entity proj; - - W_DecreaseAmmo(WEP_CVAR_PRI(electro, ammo)); - - W_SetupShot_ProjectileSize( - self, - '0 0 -3', - '0 0 -3', - FALSE, - 2, - "weapons/electro_fire.wav", - CH_WEAPON_A, - WEP_CVAR_PRI(electro, damage) - ); - - pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - proj = spawn(); - proj.classname = "electro_bolt"; - proj.owner = proj.realowner = self; - proj.bot_dodge = TRUE; - proj.bot_dodgerating = WEP_CVAR_PRI(electro, damage); - proj.use = W_Electro_Explode; - proj.think = W_Electro_Bolt_Think; - proj.nextthink = time; - proj.ltime = time + WEP_CVAR_PRI(electro, lifetime); - PROJECTILE_MAKETRIGGER(proj); - proj.projectiledeathtype = WEP_ELECTRO; - setorigin(proj, w_shotorg); - - proj.movetype = MOVETYPE_FLY; - W_SetupProjVelocity_PRI(proj, electro); - proj.angles = vectoangles(proj.velocity); - proj.touch = W_Electro_TouchExplode; - setsize(proj, '0 0 -3', '0 0 -3'); - proj.flags = FL_PROJECTILE; - proj.missile_flags = MIF_SPLASH; - - CSQCProjectile(proj, TRUE, PROJECTILE_ELECTRO_BEAM, TRUE); - - other = proj; MUTATOR_CALLHOOK(EditProjectile); -} - -void W_Electro_Orb_Touch(void) -{ - PROJECTILE_TOUCH; - if(other.takedamage == DAMAGE_AIM) - { if(WEP_CVAR_SEC(electro, touchexplode)) { W_Electro_Explode(); } } - else - { - //UpdateCSQCProjectile(self); - spamsound(self, CH_SHOTS, "weapons/electro_bounce.wav", VOL_BASE, ATTEN_NORM); - self.projectiledeathtype |= HITTYPE_BOUNCE; - } -} - -void W_Electro_Orb_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) -{ - if(self.health <= 0) - return; - - // note: combos are usually triggered by W_Electro_TriggerCombo, not damage - float is_combo = (inflictor.classname == "electro_orb_chain" || inflictor.classname == "electro_bolt"); - - if(!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, (is_combo ? 1 : -1))) - return; // g_projectiles_damage says to halt - - self.health = self.health - damage; - if(self.health <= 0) - { - self.takedamage = DAMAGE_NO; - self.nextthink = time; - if(is_combo) - { - // change owner to whoever caused the combo explosion - self.realowner = inflictor.realowner; - self.classname = "electro_orb_chain"; - self.think = W_Electro_ExplodeCombo; - self.nextthink = time + - ( - // bound the length, inflictor may be in a galaxy far far away (warpzones) - min( - WEP_CVAR(electro, combo_radius), - vlen(self.origin - inflictor.origin) - ) - / - // delay combo chains, looks cooler - WEP_CVAR(electro, combo_speed) - ); - } - else - { - self.use = W_Electro_Explode; - self.think = adaptor_think2use; // not _hittype_splash, as this runs "immediately" - } - } -} - -void W_Electro_Attack_Orb(void) -{ - W_DecreaseAmmo(WEP_CVAR_SEC(electro, ammo)); - - W_SetupShot_ProjectileSize( - self, - '0 0 -4', - '0 0 -4', - FALSE, - 2, - "weapons/electro_fire2.wav", - CH_WEAPON_A, - WEP_CVAR_SEC(electro, damage) - ); - - w_shotdir = v_forward; // no TrueAim for grenades please - - pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - entity proj = spawn(); - proj.classname = "electro_orb"; - proj.owner = proj.realowner = self; - proj.use = W_Electro_Explode; - proj.think = adaptor_think2use_hittype_splash; - proj.bot_dodge = TRUE; - proj.bot_dodgerating = WEP_CVAR_SEC(electro, damage); - proj.nextthink = time + WEP_CVAR_SEC(electro, lifetime); - PROJECTILE_MAKETRIGGER(proj); - proj.projectiledeathtype = WEP_ELECTRO | HITTYPE_SECONDARY; - setorigin(proj, w_shotorg); - - //proj.glow_size = 50; - //proj.glow_color = 45; - proj.movetype = MOVETYPE_BOUNCE; - W_SetupProjVelocity_UP_SEC(proj, electro); - proj.touch = W_Electro_Orb_Touch; - setsize(proj, '0 0 -4', '0 0 -4'); - proj.takedamage = DAMAGE_YES; - proj.damageforcescale = WEP_CVAR_SEC(electro, damageforcescale); - proj.health = WEP_CVAR_SEC(electro, health); - proj.event_damage = W_Electro_Orb_Damage; - proj.flags = FL_PROJECTILE; - proj.damagedbycontents = (WEP_CVAR_SEC(electro, damagedbycontents)); - - proj.bouncefactor = WEP_CVAR_SEC(electro, bouncefactor); - proj.bouncestop = WEP_CVAR_SEC(electro, bouncestop); - proj.missile_flags = MIF_SPLASH | MIF_ARC; - -#if 0 - entity p2; - p2 = spawn(); - copyentity(proj, p2); - setmodel(p2, "models/ebomb.mdl"); - setsize(p2, proj.mins, proj.maxs); -#endif - - CSQCProjectile(proj, TRUE, PROJECTILE_ELECTRO, FALSE); // no culling, it has sound - - other = proj; MUTATOR_CALLHOOK(EditProjectile); -} - -void W_Electro_CheckAttack(void) -{ - if(self.electro_count > 1) - if(self.BUTTON_ATCK2) - if(weapon_prepareattack(1, -1)) - { - W_Electro_Attack_Orb(); - self.electro_count -= 1; - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(electro, animtime), W_Electro_CheckAttack); - return; - } - // WEAPONTODO: when the player releases the button, cut down the length of refire2? - w_ready(); -} - -.float bot_secondary_electromooth; -float W_Electro(float req) -{ - float ammo_amount; - switch(req) - { - case WR_AIM: - { - self.BUTTON_ATCK = self.BUTTON_ATCK2 = FALSE; - if(vlen(self.origin-self.enemy.origin) > 1000) { self.bot_secondary_electromooth = 0; } - if(self.bot_secondary_electromooth == 0) - { - float shoot; - - if(WEP_CVAR_PRI(electro, speed)) - shoot = bot_aim(WEP_CVAR_PRI(electro, speed), 0, WEP_CVAR_PRI(electro, lifetime), FALSE); - else - shoot = bot_aim(1000000, 0, 0.001, FALSE); - - if(shoot) - { - self.BUTTON_ATCK = TRUE; - if(random() < 0.01) self.bot_secondary_electromooth = 1; - } - } - else - { - if(bot_aim(WEP_CVAR_SEC(electro, speed), WEP_CVAR_SEC(electro, speed_up), WEP_CVAR_SEC(electro, lifetime), TRUE)) - { - self.BUTTON_ATCK2 = TRUE; - if(random() < 0.03) self.bot_secondary_electromooth = 0; - } - } - - return TRUE; - } - case WR_THINK: - { - if(autocvar_g_balance_electro_reload_ammo) // forced reload // WEAPONTODO - { - ammo_amount = 0; - if(self.clip_load >= WEP_CVAR_PRI(electro, ammo)) - ammo_amount = 1; - if(self.clip_load >= WEP_CVAR_SEC(electro, ammo)) - ammo_amount += 1; - - if(!ammo_amount) - { - WEP_ACTION(self.weapon, WR_RELOAD); - return FALSE; - } - - return TRUE; - } - - if(self.BUTTON_ATCK) - { - if(weapon_prepareattack(0, WEP_CVAR_PRI(electro, refire))) - { - W_Electro_Attack_Bolt(); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready); - } - } - else if(self.BUTTON_ATCK2) - { - if(time >= self.electro_secondarytime) - if(weapon_prepareattack(1, WEP_CVAR_SEC(electro, refire))) - { - W_Electro_Attack_Orb(); - self.electro_count = WEP_CVAR_SEC(electro, count); - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(electro, animtime), W_Electro_CheckAttack); - self.electro_secondarytime = time + WEP_CVAR_SEC(electro, refire2) * W_WeaponRateFactor(); - } - } - - return TRUE; - } - case WR_INIT: - { - precache_model("models/weapons/g_electro.md3"); - precache_model("models/weapons/v_electro.md3"); - precache_model("models/weapons/h_electro.iqm"); - precache_sound("weapons/electro_bounce.wav"); - precache_sound("weapons/electro_fire.wav"); - precache_sound("weapons/electro_fire2.wav"); - precache_sound("weapons/electro_impact.wav"); - precache_sound("weapons/electro_impact_combo.wav"); - ELECTRO_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP) - return TRUE; - } - case WR_CHECKAMMO1: - { - ammo_amount = self.WEP_AMMO(ELECTRO) >= WEP_CVAR_PRI(electro, ammo); - ammo_amount += self.(weapon_load[WEP_ELECTRO]) >= WEP_CVAR_PRI(electro, ammo); - return ammo_amount; - } - case WR_CHECKAMMO2: - { - if(WEP_CVAR(electro, combo_safeammocheck)) // true if you can fire at least one secondary blob AND one primary shot after it, otherwise false. - { - ammo_amount = self.WEP_AMMO(ELECTRO) >= WEP_CVAR_SEC(electro, ammo) + WEP_CVAR_PRI(electro, ammo); - ammo_amount += self.(weapon_load[WEP_ELECTRO]) >= WEP_CVAR_SEC(electro, ammo) + WEP_CVAR_PRI(electro, ammo); - } - else - { - ammo_amount = self.WEP_AMMO(ELECTRO) >= WEP_CVAR_SEC(electro, ammo); - ammo_amount += self.(weapon_load[WEP_ELECTRO]) >= WEP_CVAR_SEC(electro, ammo); - } - return ammo_amount; - } - case WR_CONFIG: - { - ELECTRO_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS) - return TRUE; - } - case WR_RESETPLAYER: - { - self.electro_secondarytime = time; - return TRUE; - } - case WR_RELOAD: - { - W_Reload(min(WEP_CVAR_PRI(electro, ammo), WEP_CVAR_SEC(electro, ammo)), "weapons/reload.wav"); - return TRUE; - } - case WR_SUICIDEMESSAGE: - { - if(w_deathtype & HITTYPE_SECONDARY) - return WEAPON_ELECTRO_SUICIDE_ORBS; - else - return WEAPON_ELECTRO_SUICIDE_BOLT; - } - case WR_KILLMESSAGE: - { - if(w_deathtype & HITTYPE_SECONDARY) - { - return WEAPON_ELECTRO_MURDER_ORBS; - } - else - { - if(w_deathtype & HITTYPE_BOUNCE) - return WEAPON_ELECTRO_MURDER_COMBO; - else - return WEAPON_ELECTRO_MURDER_BOLT; - } - } - } - return FALSE; -} -#endif -#ifdef CSQC -float W_Electro(float req) -{ - switch(req) - { - case WR_IMPACTEFFECT: - { - vector org2; - org2 = w_org + w_backoff * 6; - if(w_deathtype & HITTYPE_SECONDARY) - { - pointparticles(particleeffectnum("electro_ballexplode"), org2, '0 0 0', 1); - if(!w_issilent) - sound(self, CH_SHOTS, "weapons/electro_impact.wav", VOL_BASE, ATTEN_NORM); - } - else - { - if(w_deathtype & HITTYPE_BOUNCE) - { - // this is sent as "primary (w_deathtype & HITTYPE_BOUNCE)" to distinguish it from (w_deathtype & HITTYPE_SECONDARY) bounced balls - pointparticles(particleeffectnum("electro_combo"), org2, '0 0 0', 1); - if(!w_issilent) - sound(self, CH_SHOTS, "weapons/electro_impact_combo.wav", VOL_BASE, ATTEN_NORM); - } - else - { - pointparticles(particleeffectnum("electro_impact"), org2, '0 0 0', 1); - if(!w_issilent) - sound(self, CH_SHOTS, "weapons/electro_impact.wav", VOL_BASE, ATTEN_NORM); - } - } - - return TRUE; - } - case WR_INIT: - { - precache_sound("weapons/electro_impact.wav"); - precache_sound("weapons/electro_impact_combo.wav"); - return TRUE; - } - case WR_ZOOMRETICLE: - { - // no weapon specific image for this weapon - return FALSE; - } - } - return FALSE; -} -#endif -#endif diff --git a/qcsrc/common/weapons/w_fireball.qc b/qcsrc/common/weapons/w_fireball.qc deleted file mode 100644 index a5bca22cd..000000000 --- a/qcsrc/common/weapons/w_fireball.qc +++ /dev/null @@ -1,485 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ FIREBALL, -/* function */ W_Fireball, -/* ammotype */ ammo_none, -/* impulse */ 9, -/* flags */ WEP_FLAG_SUPERWEAPON | WEP_TYPE_SPLASH, -/* rating */ BOT_PICKUP_RATING_MID, -/* color */ '1 0.5 0', -/* modelname */ "fireball", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairfireball", -/* wepimg */ "weaponfireball", -/* refname */ "fireball", -/* wepname */ _("Fireball") -); - -#define FIREBALL_SETTINGS(w_cvar,w_prop) FIREBALL_SETTINGS_LIST(w_cvar, w_prop, FIREBALL, fireball) -#define FIREBALL_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, BOTH, animtime) \ - w_cvar(id, sn, BOTH, refire) \ - w_cvar(id, sn, BOTH, damage) \ - w_cvar(id, sn, BOTH, damageforcescale) \ - w_cvar(id, sn, BOTH, speed) \ - w_cvar(id, sn, BOTH, spread) \ - w_cvar(id, sn, BOTH, lifetime) \ - w_cvar(id, sn, BOTH, laserburntime) \ - w_cvar(id, sn, BOTH, laserdamage) \ - w_cvar(id, sn, BOTH, laseredgedamage) \ - w_cvar(id, sn, BOTH, laserradius) \ - w_cvar(id, sn, PRI, edgedamage) \ - w_cvar(id, sn, PRI, force) \ - w_cvar(id, sn, PRI, radius) \ - w_cvar(id, sn, PRI, health) \ - w_cvar(id, sn, PRI, refire2) \ - w_cvar(id, sn, PRI, bfgdamage) \ - w_cvar(id, sn, PRI, bfgforce) \ - w_cvar(id, sn, PRI, bfgradius) \ - w_cvar(id, sn, SEC, damagetime) \ - w_cvar(id, sn, SEC, speed_up) \ - w_cvar(id, sn, SEC, speed_z) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifdef SVQC -FIREBALL_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) -.float bot_primary_fireballmooth; // whatever a mooth is -.vector fireball_impactvec; -.float fireball_primarytime; -#endif -#else -#ifdef SVQC -void spawnfunc_weapon_fireball(void) { weapon_defaultspawnfunc(WEP_FIREBALL); } - -void W_Fireball_Explode(void) -{ - entity e; - float dist; - float points; - vector dir; - float d; - - self.event_damage = func_null; - self.takedamage = DAMAGE_NO; - - // 1. dist damage - d = (self.realowner.health + self.realowner.armorvalue); - RadiusDamage(self, self.realowner, WEP_CVAR_PRI(fireball, damage), WEP_CVAR_PRI(fireball, edgedamage), WEP_CVAR_PRI(fireball, radius), world, world, WEP_CVAR_PRI(fireball, force), self.projectiledeathtype, other); - if(self.realowner.health + self.realowner.armorvalue >= d) - if(!self.cnt) - { - modeleffect_spawn("models/sphere/sphere.md3", 0, 0, self.origin, '0 0 0', '0 0 0', '0 0 0', 0, WEP_CVAR_PRI(fireball, bfgradius), 0.2, 0.05, 0.25); - - // 2. bfg effect - // NOTE: this cannot be made warpzone aware by design. So, better intentionally ignore warpzones here. - for(e = findradius(self.origin, WEP_CVAR_PRI(fireball, bfgradius)); e; e = e.chain) - if(e != self.realowner) if(e.takedamage == DAMAGE_AIM) if(!IS_PLAYER(e) || !self.realowner || DIFF_TEAM(e, self)) - { - // can we see fireball? - traceline(e.origin + e.view_ofs, self.origin, MOVE_NORMAL, e); - if(/* trace_startsolid || */ trace_fraction != 1) // startsolid should be never happening anyway - continue; - // can we see player who shot fireball? - traceline(e.origin + e.view_ofs, self.realowner.origin + self.realowner.view_ofs, MOVE_NORMAL, e); - if(trace_ent != self.realowner) - if(/* trace_startsolid || */ trace_fraction != 1) - continue; - dist = vlen(self.origin - e.origin - e.view_ofs); - points = (1 - sqrt(dist / WEP_CVAR_PRI(fireball, bfgradius))); - if(points <= 0) - continue; - dir = normalize(e.origin + e.view_ofs - self.origin); - - if(accuracy_isgooddamage(self.realowner, e)) - accuracy_add(self.realowner, WEP_FIREBALL, 0, WEP_CVAR_PRI(fireball, bfgdamage) * points); - - Damage(e, self, self.realowner, WEP_CVAR_PRI(fireball, bfgdamage) * points, self.projectiledeathtype | HITTYPE_BOUNCE | HITTYPE_SPLASH, e.origin + e.view_ofs, WEP_CVAR_PRI(fireball, bfgforce) * dir); - pointparticles(particleeffectnum("fireball_bfgdamage"), e.origin, -1 * dir, 1); - } - } - - remove(self); -} - -void W_Fireball_TouchExplode(void) -{ - PROJECTILE_TOUCH; - W_Fireball_Explode(); -} - -void W_Fireball_LaserPlay(float dt, float dist, float damage, float edgedamage, float burntime) -{ - entity e; - float d; - vector p; - - if(damage <= 0) - return; - - RandomSelection_Init(); - for(e = WarpZone_FindRadius(self.origin, dist, TRUE); e; e = e.chain) - if(e != self.realowner) if(e.takedamage == DAMAGE_AIM) if(!IS_PLAYER(e) || !self.realowner || DIFF_TEAM(e, self)) - { - p = e.origin; - p_x += e.mins_x + random() * (e.maxs_x - e.mins_x); - p_y += e.mins_y + random() * (e.maxs_y - e.mins_y); - p_z += e.mins_z + random() * (e.maxs_z - e.mins_z); - d = vlen(WarpZone_UnTransformOrigin(e, self.origin) - p); - if(d < dist) - { - e.fireball_impactvec = p; - RandomSelection_Add(e, 0, string_null, 1 / (1 + d), !Fire_IsBurning(e)); - } - } - if(RandomSelection_chosen_ent) - { - d = vlen(WarpZone_UnTransformOrigin(RandomSelection_chosen_ent, self.origin) - RandomSelection_chosen_ent.fireball_impactvec); - d = damage + (edgedamage - damage) * (d / dist); - Fire_AddDamage(RandomSelection_chosen_ent, self.realowner, d * burntime, burntime, self.projectiledeathtype | HITTYPE_BOUNCE); - //trailparticles(self, particleeffectnum("fireball_laser"), self.origin, RandomSelection_chosen_ent.fireball_impactvec); - pointparticles(particleeffectnum("fireball_laser"), self.origin, RandomSelection_chosen_ent.fireball_impactvec - self.origin, 1); - } -} - -void W_Fireball_Think(void) -{ - if(time > self.pushltime) - { - self.cnt = 1; - self.projectiledeathtype |= HITTYPE_SPLASH; - W_Fireball_Explode(); - return; - } - - W_Fireball_LaserPlay(0.1, WEP_CVAR_PRI(fireball, laserradius), WEP_CVAR_PRI(fireball, laserdamage), WEP_CVAR_PRI(fireball, laseredgedamage), WEP_CVAR_PRI(fireball, laserburntime)); - - self.nextthink = time + 0.1; -} - -void W_Fireball_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) -{ - if(self.health <= 0) - return; - - if(!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions - return; // g_projectiles_damage says to halt - - self.health = self.health - damage; - if(self.health <= 0) - { - self.cnt = 1; - W_PrepareExplosionByDamage(attacker, W_Fireball_Explode); - } -} - -void W_Fireball_Attack1(void) -{ - entity proj; - - W_SetupShot_ProjectileSize(self, '-16 -16 -16', '16 16 16', FALSE, 2, "weapons/fireball_fire2.wav", CH_WEAPON_A, WEP_CVAR_PRI(fireball, damage) + WEP_CVAR_PRI(fireball, bfgdamage)); - - pointparticles(particleeffectnum("fireball_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - proj = spawn(); - proj.classname = "plasma_prim"; - proj.owner = proj.realowner = self; - proj.bot_dodge = TRUE; - proj.bot_dodgerating = WEP_CVAR_PRI(fireball, damage); - proj.pushltime = time + WEP_CVAR_PRI(fireball, lifetime); - proj.use = W_Fireball_Explode; - proj.think = W_Fireball_Think; - proj.nextthink = time; - proj.health = WEP_CVAR_PRI(fireball, health); - proj.team = self.team; - proj.event_damage = W_Fireball_Damage; - proj.takedamage = DAMAGE_YES; - proj.damageforcescale = WEP_CVAR_PRI(fireball, damageforcescale); - PROJECTILE_MAKETRIGGER(proj); - proj.projectiledeathtype = WEP_FIREBALL; - setorigin(proj, w_shotorg); - - proj.movetype = MOVETYPE_FLY; - W_SetupProjVelocity_PRI(proj, fireball); - proj.angles = vectoangles(proj.velocity); - proj.touch = W_Fireball_TouchExplode; - setsize(proj, '-16 -16 -16', '16 16 16'); - proj.flags = FL_PROJECTILE; - proj.missile_flags = MIF_SPLASH | MIF_PROXY; - - CSQCProjectile(proj, TRUE, PROJECTILE_FIREBALL, TRUE); - - other = proj; MUTATOR_CALLHOOK(EditProjectile); -} - -void W_Fireball_AttackEffect(float i, vector f_diff) -{ - W_SetupShot_ProjectileSize(self, '-16 -16 -16', '16 16 16', FALSE, 0, "", 0, 0); - w_shotorg += f_diff_x * v_up + f_diff_y * v_right; - pointparticles(particleeffectnum("fireball_preattack_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); -} - -void W_Fireball_Attack1_Frame4(void) -{ - W_Fireball_Attack1(); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), w_ready); -} - -void W_Fireball_Attack1_Frame3(void) -{ - W_Fireball_AttackEffect(0, '+1.25 +3.75 0'); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame4); -} - -void W_Fireball_Attack1_Frame2(void) -{ - W_Fireball_AttackEffect(0, '-1.25 +3.75 0'); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame3); -} - -void W_Fireball_Attack1_Frame1(void) -{ - W_Fireball_AttackEffect(1, '+1.25 -3.75 0'); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame2); -} - -void W_Fireball_Attack1_Frame0(void) -{ - W_Fireball_AttackEffect(0, '-1.25 -3.75 0'); - sound(self, CH_WEAPON_SINGLE, "weapons/fireball_prefire2.wav", VOL_BASE, ATTEN_NORM); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame1); -} - -void W_Fireball_Firemine_Think(void) -{ - if(time > self.pushltime) - { - remove(self); - return; - } - - // make it "hot" once it leaves its owner - if(self.owner) - { - if(vlen(self.origin - self.owner.origin - self.owner.view_ofs) > WEP_CVAR_SEC(fireball, laserradius)) - { - self.cnt += 1; - if(self.cnt == 3) - self.owner = world; - } - else - self.cnt = 0; - } - - W_Fireball_LaserPlay(0.1, WEP_CVAR_SEC(fireball, laserradius), WEP_CVAR_SEC(fireball, laserdamage), WEP_CVAR_SEC(fireball, laseredgedamage), WEP_CVAR_SEC(fireball, laserburntime)); - - self.nextthink = time + 0.1; -} - -void W_Fireball_Firemine_Touch(void) -{ - PROJECTILE_TOUCH; - if(other.takedamage == DAMAGE_AIM) - if(Fire_AddDamage(other, self.realowner, WEP_CVAR_SEC(fireball, damage), WEP_CVAR_SEC(fireball, damagetime), self.projectiledeathtype) >= 0) - { - remove(self); - return; - } - self.projectiledeathtype |= HITTYPE_BOUNCE; -} - -void W_Fireball_Attack2(void) -{ - entity proj; - vector f_diff; - float c; - - c = mod(self.bulletcounter, 4); - switch(c) - { - case 0: - f_diff = '-1.25 -3.75 0'; - break; - case 1: - f_diff = '+1.25 -3.75 0'; - break; - case 2: - f_diff = '-1.25 +3.75 0'; - break; - case 3: - default: - f_diff = '+1.25 +3.75 0'; - break; - } - W_SetupShot_ProjectileSize(self, '-4 -4 -4', '4 4 4', FALSE, 2, "weapons/fireball_fire.wav", CH_WEAPON_A, WEP_CVAR_SEC(fireball, damage)); - traceline(w_shotorg, w_shotorg + f_diff_x * v_up + f_diff_y * v_right, MOVE_NORMAL, self); - w_shotorg = trace_endpos; - - pointparticles(particleeffectnum("fireball_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - proj = spawn(); - proj.owner = proj.realowner = self; - proj.classname = "grenade"; - proj.bot_dodge = TRUE; - proj.bot_dodgerating = WEP_CVAR_SEC(fireball, damage); - proj.movetype = MOVETYPE_BOUNCE; - proj.projectiledeathtype = WEP_FIREBALL | HITTYPE_SECONDARY; - proj.touch = W_Fireball_Firemine_Touch; - PROJECTILE_MAKETRIGGER(proj); - setsize(proj, '-4 -4 -4', '4 4 4'); - setorigin(proj, w_shotorg); - proj.think = W_Fireball_Firemine_Think; - proj.nextthink = time; - proj.damageforcescale = WEP_CVAR_SEC(fireball, damageforcescale); - proj.pushltime = time + WEP_CVAR_SEC(fireball, lifetime); - W_SetupProjVelocity_UP_SEC(proj, fireball); - - proj.angles = vectoangles(proj.velocity); - proj.flags = FL_PROJECTILE; - proj.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_ARC; - - CSQCProjectile(proj, TRUE, PROJECTILE_FIREMINE, TRUE); - - other = proj; MUTATOR_CALLHOOK(EditProjectile); -} - -float W_Fireball(float req) -{ - switch(req) - { - case WR_AIM: - { - self.BUTTON_ATCK = FALSE; - self.BUTTON_ATCK2 = FALSE; - if(self.bot_primary_fireballmooth == 0) - { - if(bot_aim(WEP_CVAR_PRI(fireball, speed), 0, WEP_CVAR_PRI(fireball, lifetime), FALSE)) - { - self.BUTTON_ATCK = TRUE; - if(random() < 0.02) self.bot_primary_fireballmooth = 0; - } - } - else - { - if(bot_aim(WEP_CVAR_SEC(fireball, speed), WEP_CVAR_SEC(fireball, speed_up), WEP_CVAR_SEC(fireball, lifetime), TRUE)) - { - self.BUTTON_ATCK2 = TRUE; - if(random() < 0.01) self.bot_primary_fireballmooth = 1; - } - } - - return TRUE; - } - case WR_THINK: - { - if(self.BUTTON_ATCK) - { - if(time >= self.fireball_primarytime) - if(weapon_prepareattack(0, WEP_CVAR_PRI(fireball, refire))) - { - W_Fireball_Attack1_Frame0(); - self.fireball_primarytime = time + WEP_CVAR_PRI(fireball, refire2) * W_WeaponRateFactor(); - } - } - else if(self.BUTTON_ATCK2) - { - if(weapon_prepareattack(1, WEP_CVAR_SEC(fireball, refire))) - { - W_Fireball_Attack2(); - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(fireball, animtime), w_ready); - } - } - - return TRUE; - } - case WR_INIT: - { - precache_model("models/weapons/g_fireball.md3"); - precache_model("models/weapons/v_fireball.md3"); - precache_model("models/weapons/h_fireball.iqm"); - precache_model("models/sphere/sphere.md3"); - precache_sound("weapons/fireball_fire.wav"); - precache_sound("weapons/fireball_fire2.wav"); - precache_sound("weapons/fireball_prefire2.wav"); - FIREBALL_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP) - return TRUE; - } - case WR_SETUP: - { - self.ammo_field = ammo_none; - return TRUE; - } - case WR_CHECKAMMO1: - case WR_CHECKAMMO2: - { - return TRUE; // fireball has infinite ammo - } - case WR_CONFIG: - { - FIREBALL_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS) - return TRUE; - } - case WR_RESETPLAYER: - { - self.fireball_primarytime = time; - return TRUE; - } - case WR_SUICIDEMESSAGE: - { - if(w_deathtype & HITTYPE_SECONDARY) - return WEAPON_FIREBALL_SUICIDE_FIREMINE; - else - return WEAPON_FIREBALL_SUICIDE_BLAST; - } - case WR_KILLMESSAGE: - { - if(w_deathtype & HITTYPE_SECONDARY) - return WEAPON_FIREBALL_MURDER_FIREMINE; - else - return WEAPON_FIREBALL_MURDER_BLAST; - } - } - return FALSE; -} -#endif -#ifdef CSQC -float W_Fireball(float req) -{ - switch(req) - { - case WR_IMPACTEFFECT: - { - vector org2; - if(w_deathtype & HITTYPE_SECONDARY) - { - // firemine goes out silently - } - else - { - org2 = w_org + w_backoff * 16; - pointparticles(particleeffectnum("fireball_explode"), org2, '0 0 0', 1); - if(!w_issilent) - sound(self, CH_SHOTS, "weapons/fireball_impact2.wav", VOL_BASE, ATTEN_NORM * 0.25); // long range boom - } - - return TRUE; - } - case WR_INIT: - { - precache_sound("weapons/fireball_impact2.wav"); - return TRUE; - } - case WR_ZOOMRETICLE: - { - // no weapon specific image for this weapon - return FALSE; - } - } - return FALSE; -} -#endif -#endif diff --git a/qcsrc/common/weapons/w_hagar.qc b/qcsrc/common/weapons/w_hagar.qc deleted file mode 100644 index fe3abf0a9..000000000 --- a/qcsrc/common/weapons/w_hagar.qc +++ /dev/null @@ -1,559 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ HAGAR, -/* function */ W_Hagar, -/* ammotype */ ammo_rockets, -/* impulse */ 8, -/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, -/* rating */ BOT_PICKUP_RATING_MID, -/* color */ '1 1 0.5', -/* modelname */ "hagar", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairhagar 0.8", -/* wepimg */ "weaponhagar", -/* refname */ "hagar", -/* wepname */ _("Hagar") -); - -#define HAGAR_SETTINGS(w_cvar,w_prop) HAGAR_SETTINGS_LIST(w_cvar, w_prop, HAGAR, hagar) -#define HAGAR_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, BOTH, ammo) \ - w_cvar(id, sn, BOTH, damage) \ - w_cvar(id, sn, BOTH, edgedamage) \ - w_cvar(id, sn, BOTH, force) \ - w_cvar(id, sn, BOTH, radius) \ - w_cvar(id, sn, BOTH, refire) \ - w_cvar(id, sn, BOTH, speed) \ - w_cvar(id, sn, BOTH, spread) \ - w_cvar(id, sn, BOTH, damageforcescale) \ - w_cvar(id, sn, BOTH, health) \ - w_cvar(id, sn, PRI, lifetime) \ - w_cvar(id, sn, SEC, load) \ - w_cvar(id, sn, SEC, load_max) \ - w_cvar(id, sn, SEC, load_abort) \ - w_cvar(id, sn, SEC, load_animtime) \ - w_cvar(id, sn, SEC, load_hold) \ - w_cvar(id, sn, SEC, load_speed) \ - w_cvar(id, sn, SEC, load_releasedeath) \ - w_cvar(id, sn, SEC, load_spread) \ - w_cvar(id, sn, SEC, load_spread_bias) \ - w_cvar(id, sn, SEC, load_linkexplode) \ - w_cvar(id, sn, SEC, lifetime_min) \ - w_cvar(id, sn, SEC, lifetime_rand) \ - w_cvar(id, sn, NONE, secondary) \ - w_prop(id, sn, float, reloading_ammo, reload_ammo) \ - w_prop(id, sn, float, reloading_time, reload_time) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifdef SVQC -HAGAR_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) -#endif -#else -#ifdef SVQC -void spawnfunc_weapon_hagar(void) { weapon_defaultspawnfunc(WEP_HAGAR); } - -// NO bounce protection, as bounces are limited! - -void W_Hagar_Explode(void) -{ - self.event_damage = func_null; - RadiusDamage(self, self.realowner, WEP_CVAR_PRI(hagar, damage), WEP_CVAR_PRI(hagar, edgedamage), WEP_CVAR_PRI(hagar, radius), world, world, WEP_CVAR_PRI(hagar, force), self.projectiledeathtype, other); - - remove(self); -} - -void W_Hagar_Explode2(void) -{ - self.event_damage = func_null; - RadiusDamage(self, self.realowner, WEP_CVAR_SEC(hagar, damage), WEP_CVAR_SEC(hagar, edgedamage), WEP_CVAR_SEC(hagar, radius), world, world, WEP_CVAR_SEC(hagar, force), self.projectiledeathtype, other); - - remove(self); -} - -void W_Hagar_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) -{ - if(self.health <= 0) - return; - - float is_linkexplode = ( ((inflictor.owner != world) ? (inflictor.owner == self.owner) : TRUE) - && (inflictor.projectiledeathtype & HITTYPE_SECONDARY) - && (self.projectiledeathtype & HITTYPE_SECONDARY)); - - if(is_linkexplode) - is_linkexplode = (is_linkexplode && WEP_CVAR_SEC(hagar, load_linkexplode)); - else - is_linkexplode = -1; // not secondary load, so continue as normal without exception. - - if(!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, is_linkexplode)) - return; // g_projectiles_damage says to halt - - self.health = self.health - damage; - self.angles = vectoangles(self.velocity); - - if(self.health <= 0) - W_PrepareExplosionByDamage(attacker, self.think); -} - -void W_Hagar_Touch(void) -{ - PROJECTILE_TOUCH; - self.use(); -} - -void W_Hagar_Touch2(void) -{ - PROJECTILE_TOUCH; - - if(self.cnt > 0 || other.takedamage == DAMAGE_AIM) { - self.use(); - } else { - self.cnt++; - pointparticles(particleeffectnum("hagar_bounce"), self.origin, self.velocity, 1); - self.angles = vectoangles(self.velocity); - self.owner = world; - self.projectiledeathtype |= HITTYPE_BOUNCE; - } -} - -void W_Hagar_Attack(void) -{ - entity missile; - - W_DecreaseAmmo(WEP_CVAR_PRI(hagar, ammo)); - - W_SetupShot(self, FALSE, 2, "weapons/hagar_fire.wav", CH_WEAPON_A, WEP_CVAR_PRI(hagar, damage)); - - pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - missile = spawn(); - missile.owner = missile.realowner = self; - missile.classname = "missile"; - missile.bot_dodge = TRUE; - missile.bot_dodgerating = WEP_CVAR_PRI(hagar, damage); - - missile.takedamage = DAMAGE_YES; - missile.health = WEP_CVAR_PRI(hagar, health); - missile.damageforcescale = WEP_CVAR_PRI(hagar, damageforcescale); - missile.event_damage = W_Hagar_Damage; - missile.damagedbycontents = TRUE; - - missile.touch = W_Hagar_Touch; - missile.use = W_Hagar_Explode; - missile.think = adaptor_think2use_hittype_splash; - missile.nextthink = time + WEP_CVAR_PRI(hagar, lifetime); - PROJECTILE_MAKETRIGGER(missile); - missile.projectiledeathtype = WEP_HAGAR; - setorigin(missile, w_shotorg); - setsize(missile, '0 0 0', '0 0 0'); - - missile.movetype = MOVETYPE_FLY; - W_SetupProjVelocity_PRI(missile, hagar); - - missile.angles = vectoangles(missile.velocity); - missile.flags = FL_PROJECTILE; - missile.missile_flags = MIF_SPLASH; - - CSQCProjectile(missile, TRUE, PROJECTILE_HAGAR, TRUE); - - other = missile; MUTATOR_CALLHOOK(EditProjectile); -} - -void W_Hagar_Attack2(void) -{ - entity missile; - - W_DecreaseAmmo(WEP_CVAR_SEC(hagar, ammo)); - - W_SetupShot(self, FALSE, 2, "weapons/hagar_fire.wav", CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage)); - - pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - missile = spawn(); - missile.owner = missile.realowner = self; - missile.classname = "missile"; - missile.bot_dodge = TRUE; - missile.bot_dodgerating = WEP_CVAR_SEC(hagar, damage); - - missile.takedamage = DAMAGE_YES; - missile.health = WEP_CVAR_SEC(hagar, health); - missile.damageforcescale = WEP_CVAR_SEC(hagar, damageforcescale); - missile.event_damage = W_Hagar_Damage; - missile.damagedbycontents = TRUE; - - missile.touch = W_Hagar_Touch2; - missile.cnt = 0; - missile.use = W_Hagar_Explode2; - missile.think = adaptor_think2use_hittype_splash; - missile.nextthink = time + WEP_CVAR_SEC(hagar, lifetime_min) + random() * WEP_CVAR_SEC(hagar, lifetime_rand); - PROJECTILE_MAKETRIGGER(missile); - missile.projectiledeathtype = WEP_HAGAR | HITTYPE_SECONDARY; - setorigin(missile, w_shotorg); - setsize(missile, '0 0 0', '0 0 0'); - - missile.movetype = MOVETYPE_BOUNCEMISSILE; - W_SetupProjVelocity_SEC(missile, hagar); - - missile.angles = vectoangles(missile.velocity); - missile.flags = FL_PROJECTILE; - missile.missile_flags = MIF_SPLASH; - - CSQCProjectile(missile, TRUE, PROJECTILE_HAGAR_BOUNCING, TRUE); - - other = missile; MUTATOR_CALLHOOK(EditProjectile); -} - -.float hagar_loadstep, hagar_loadblock, hagar_loadbeep, hagar_warning; -void W_Hagar_Attack2_Load_Release(void) -{ - // time to release the rockets we've loaded - - entity missile; - float counter, shots, spread_pershot; - vector s; - vector forward, right, up; - - if(!self.hagar_load) - return; - - weapon_prepareattack_do(1, WEP_CVAR_SEC(hagar, refire)); - - W_SetupShot(self, FALSE, 2, "weapons/hagar_fire.wav", CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage)); - pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - forward = v_forward; - right = v_right; - up = v_up; - - shots = self.hagar_load; - missile = world; - for(counter = 0; counter < shots; ++counter) - { - missile = spawn(); - missile.owner = missile.realowner = self; - missile.classname = "missile"; - missile.bot_dodge = TRUE; - missile.bot_dodgerating = WEP_CVAR_SEC(hagar, damage); - - missile.takedamage = DAMAGE_YES; - missile.health = WEP_CVAR_SEC(hagar, health); - missile.damageforcescale = WEP_CVAR_SEC(hagar, damageforcescale); - missile.event_damage = W_Hagar_Damage; - missile.damagedbycontents = TRUE; - - missile.touch = W_Hagar_Touch; // not bouncy - missile.use = W_Hagar_Explode2; - missile.think = adaptor_think2use_hittype_splash; - missile.nextthink = time + WEP_CVAR_SEC(hagar, lifetime_min) + random() * WEP_CVAR_SEC(hagar, lifetime_rand); - PROJECTILE_MAKETRIGGER(missile); - missile.projectiledeathtype = WEP_HAGAR | HITTYPE_SECONDARY; - setorigin(missile, w_shotorg); - setsize(missile, '0 0 0', '0 0 0'); - missile.movetype = MOVETYPE_FLY; - missile.missile_flags = MIF_SPLASH; - - // per-shot spread calculation: the more shots there are, the less spread is applied (based on the bias cvar) - spread_pershot = ((shots - 1) / (WEP_CVAR_SEC(hagar, load_max) - 1)); - spread_pershot = (1 - (spread_pershot * WEP_CVAR_SEC(hagar, load_spread_bias))); - spread_pershot = (WEP_CVAR_SEC(hagar, spread) * spread_pershot * g_weaponspreadfactor); - - // pattern spread calculation - s = '0 0 0'; - if(counter == 0) - s = '0 0 0'; - else - { - makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1))); - s_y = v_forward_x; - s_z = v_forward_y; - } - s = s * WEP_CVAR_SEC(hagar, load_spread) * g_weaponspreadfactor; - - W_SetupProjVelocity_Explicit(missile, w_shotdir + right * s_y + up * s_z, v_up, WEP_CVAR_SEC(hagar, speed), 0, 0, spread_pershot, FALSE); - - missile.angles = vectoangles(missile.velocity); - missile.flags = FL_PROJECTILE; - - CSQCProjectile(missile, TRUE, PROJECTILE_HAGAR, TRUE); - - other = missile; MUTATOR_CALLHOOK(EditProjectile); - } - - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(hagar, load_animtime), w_ready); - self.hagar_loadstep = time + WEP_CVAR_SEC(hagar, refire) * W_WeaponRateFactor(); - self.hagar_load = 0; -} - -void W_Hagar_Attack2_Load(void) -{ - // loadable hagar secondary attack, must always run each frame - - if(time < game_starttime) - return; - - float loaded, enough_ammo; - loaded = self.hagar_load >= WEP_CVAR_SEC(hagar, load_max); - - // this is different than WR_CHECKAMMO when it comes to reloading - if(autocvar_g_balance_hagar_reload_ammo) - enough_ammo = self.(weapon_load[WEP_HAGAR]) >= WEP_CVAR_SEC(hagar, ammo); - else - enough_ammo = self.WEP_AMMO(HAGAR) >= WEP_CVAR_SEC(hagar, ammo); - - if(self.BUTTON_ATCK2) - { - if(self.BUTTON_ATCK && WEP_CVAR_SEC(hagar, load_abort)) - { - if(self.hagar_load) - { - // if we pressed primary fire while loading, unload all rockets and abort - self.weaponentity.state = WS_READY; - W_DecreaseAmmo(WEP_CVAR_SEC(hagar, ammo) * self.hagar_load * -1); // give back ammo - self.hagar_load = 0; - sound(self, CH_WEAPON_A, "weapons/hagar_beep.wav", VOL_BASE, ATTN_NORM); - - // pause until we can load rockets again, once we re-press the alt fire button - self.hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_speed) * W_WeaponRateFactor(); - - // require letting go of the alt fire button before we can load again - self.hagar_loadblock = TRUE; - } - } - else - { - // check if we can attempt to load another rocket - if(!loaded && enough_ammo) - { - if(!self.hagar_loadblock && self.hagar_loadstep < time) - { - W_DecreaseAmmo(WEP_CVAR_SEC(hagar, ammo)); - self.weaponentity.state = WS_INUSE; - self.hagar_load += 1; - sound(self, CH_WEAPON_B, "weapons/hagar_load.wav", VOL_BASE * 0.8, ATTN_NORM); // sound is too loud according to most - - if(self.hagar_load >= WEP_CVAR_SEC(hagar, load_max)) - self.hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_hold) * W_WeaponRateFactor(); - else - self.hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_speed) * W_WeaponRateFactor(); - } - } - else if(!self.hagar_loadbeep && self.hagar_load) // prevents the beep from playing each frame - { - // if this is the last rocket we can load, play a beep sound to notify the player - sound(self, CH_WEAPON_A, "weapons/hagar_beep.wav", VOL_BASE, ATTN_NORM); - self.hagar_loadbeep = TRUE; - } - } - } - else if(self.hagar_loadblock) - { - // the alt fire button has been released, so re-enable loading if blocked - self.hagar_loadblock = FALSE; - } - - if(self.hagar_load) - { - // play warning sound if we're about to release - if((loaded || !enough_ammo) && self.hagar_loadstep - 0.5 < time && WEP_CVAR_SEC(hagar, load_hold) >= 0) - { - if(!self.hagar_warning && self.hagar_load) // prevents the beep from playing each frame - { - // we're about to automatically release after holding time, play a beep sound to notify the player - sound(self, CH_WEAPON_A, "weapons/hagar_beep.wav", VOL_BASE, ATTN_NORM); - self.hagar_warning = TRUE; - } - } - - // release if player let go of button or if they've held it in too long - if(!self.BUTTON_ATCK2 || ((loaded || !enough_ammo) && self.hagar_loadstep < time && WEP_CVAR_SEC(hagar, load_hold) >= 0)) - { - self.weaponentity.state = WS_READY; - W_Hagar_Attack2_Load_Release(); - } - } - else - { - self.hagar_loadbeep = FALSE; - self.hagar_warning = FALSE; - } - - // we aren't checking ammo during an attack, so we must do it here - if(!(WEP_ACTION(self.weapon, WR_CHECKAMMO1) + WEP_ACTION(self.weapon, WR_CHECKAMMO2))) - { - // note: this doesn't force the switch - W_SwitchToOtherWeapon(self); - return; - } -} - -float W_Hagar(float req) -{ - float ammo_amount; - switch(req) - { - case WR_AIM: - { - if(random()>0.15) - self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), FALSE); - else // not using secondary_speed since these are only 15% and should cause some ricochets without re-aiming - self.BUTTON_ATCK2 = bot_aim(WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), FALSE); - - return TRUE; - } - case WR_THINK: - { - float loadable_secondary; - loadable_secondary = (WEP_CVAR_SEC(hagar, load) && WEP_CVAR(hagar, secondary)); - - if(loadable_secondary) - W_Hagar_Attack2_Load(); // must always run each frame - if(autocvar_g_balance_hagar_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo))) // forced reload - WEP_ACTION(self.weapon, WR_RELOAD); - else if(self.BUTTON_ATCK && !self.hagar_load && !self.hagar_loadblock) // not while secondary is loaded or awaiting reset - { - if(weapon_prepareattack(0, WEP_CVAR_PRI(hagar, refire))) - { - W_Hagar_Attack(); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(hagar, refire), w_ready); - } - } - else if(self.BUTTON_ATCK2 && !loadable_secondary && WEP_CVAR(hagar, secondary)) - { - if(weapon_prepareattack(1, WEP_CVAR_SEC(hagar, refire))) - { - W_Hagar_Attack2(); - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(hagar, refire), w_ready); - } - } - - return TRUE; - } - case WR_GONETHINK: - { - // we lost the weapon and want to prepare switching away - if(self.hagar_load) - { - self.weaponentity.state = WS_READY; - W_Hagar_Attack2_Load_Release(); - } - - return TRUE; - } - case WR_INIT: - { - precache_model("models/weapons/g_hagar.md3"); - precache_model("models/weapons/v_hagar.md3"); - precache_model("models/weapons/h_hagar.iqm"); - precache_sound("weapons/hagar_fire.wav"); - precache_sound("weapons/hagar_load.wav"); - precache_sound("weapons/hagar_beep.wav"); - HAGAR_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP) - return TRUE; - } - case WR_SETUP: - { - self.hagar_loadblock = FALSE; - - if(self.hagar_load) - { - W_DecreaseAmmo(WEP_CVAR_SEC(hagar, ammo) * self.hagar_load * -1); // give back ammo if necessary - self.hagar_load = 0; - } - - return TRUE; - } - case WR_CHECKAMMO1: - { - ammo_amount = self.WEP_AMMO(HAGAR) >= WEP_CVAR_PRI(hagar, ammo); - ammo_amount += self.(weapon_load[WEP_HAGAR]) >= WEP_CVAR_PRI(hagar, ammo); - return ammo_amount; - } - case WR_CHECKAMMO2: - { - ammo_amount = self.WEP_AMMO(HAGAR) >= WEP_CVAR_SEC(hagar, ammo); - ammo_amount += self.(weapon_load[WEP_HAGAR]) >= WEP_CVAR_SEC(hagar, ammo); - return ammo_amount; - } - case WR_CONFIG: - { - HAGAR_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS) - return TRUE; - } - case WR_RESETPLAYER: - { - self.hagar_load = 0; - return TRUE; - } - case WR_PLAYERDEATH: - { - // if we have any rockets loaded when we die, release them - if(self.hagar_load && WEP_CVAR_SEC(hagar, load_releasedeath)) - W_Hagar_Attack2_Load_Release(); - - return TRUE; - } - case WR_RELOAD: - { - if(!self.hagar_load) // require releasing loaded rockets first - W_Reload(min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo)), "weapons/reload.wav"); - - return TRUE; - } - case WR_SUICIDEMESSAGE: - { - return WEAPON_HAGAR_SUICIDE; - } - case WR_KILLMESSAGE: - { - if(w_deathtype & HITTYPE_SECONDARY) - return WEAPON_HAGAR_MURDER_BURST; - else - return WEAPON_HAGAR_MURDER_SPRAY; - } - } - return FALSE; -} -#endif -#ifdef CSQC -float W_Hagar(float req) -{ - switch(req) - { - case WR_IMPACTEFFECT: - { - vector org2; - org2 = w_org + w_backoff * 6; - pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1); - if(!w_issilent) - { - if(w_random<0.15) - sound(self, CH_SHOTS, "weapons/hagexp1.wav", VOL_BASE, ATTN_NORM); - else if(w_random<0.7) - sound(self, CH_SHOTS, "weapons/hagexp2.wav", VOL_BASE, ATTN_NORM); - else - sound(self, CH_SHOTS, "weapons/hagexp3.wav", VOL_BASE, ATTN_NORM); - } - - return TRUE; - } - case WR_INIT: - { - precache_sound("weapons/hagexp1.wav"); - precache_sound("weapons/hagexp2.wav"); - precache_sound("weapons/hagexp3.wav"); - return TRUE; - } - case WR_ZOOMRETICLE: - { - // no weapon specific image for this weapon - return FALSE; - } - } - return FALSE; -} -#endif -#endif diff --git a/qcsrc/common/weapons/w_hlac.qc b/qcsrc/common/weapons/w_hlac.qc deleted file mode 100644 index d3dbed2f9..000000000 --- a/qcsrc/common/weapons/w_hlac.qc +++ /dev/null @@ -1,313 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ HLAC, -/* function */ W_HLAC, -/* ammotype */ ammo_cells, -/* impulse */ 6, -/* flags */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH, -/* rating */ BOT_PICKUP_RATING_MID, -/* color */ '0 1 0', -/* modelname */ "hlac", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairhlac 0.6", -/* wepimg */ "weaponhlac", -/* refname */ "hlac", -/* wepname */ _("Heavy Laser Assault Cannon") -); - -#define HLAC_SETTINGS(w_cvar,w_prop) HLAC_SETTINGS_LIST(w_cvar, w_prop, HLAC, hlac) -#define HLAC_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, BOTH, ammo) \ - w_cvar(id, sn, BOTH, animtime) \ - w_cvar(id, sn, BOTH, damage) \ - w_cvar(id, sn, BOTH, edgedamage) \ - w_cvar(id, sn, BOTH, force) \ - w_cvar(id, sn, BOTH, lifetime) \ - w_cvar(id, sn, BOTH, radius) \ - w_cvar(id, sn, BOTH, refire) \ - w_cvar(id, sn, BOTH, speed) \ - w_cvar(id, sn, BOTH, spread_crouchmod) \ - w_cvar(id, sn, PRI, spread_add) \ - w_cvar(id, sn, PRI, spread_max) \ - w_cvar(id, sn, PRI, spread_min) \ - w_cvar(id, sn, NONE, secondary) \ - w_cvar(id, sn, SEC, shots) \ - w_cvar(id, sn, SEC, spread) \ - w_prop(id, sn, float, reloading_ammo, reload_ammo) \ - w_prop(id, sn, float, reloading_time, reload_time) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifdef SVQC -HLAC_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) -#endif -#else -#ifdef SVQC -void spawnfunc_weapon_hlac(void) { weapon_defaultspawnfunc(WEP_HLAC); } - -void W_HLAC_Touch(void) -{ - float isprimary; - - PROJECTILE_TOUCH; - - self.event_damage = func_null; - - isprimary = !(self.projectiledeathtype & HITTYPE_SECONDARY); - - RadiusDamage(self, self.realowner, WEP_CVAR_BOTH(hlac, isprimary, damage), WEP_CVAR_BOTH(hlac, isprimary, edgedamage), WEP_CVAR_BOTH(hlac, isprimary, radius), world, world, WEP_CVAR_BOTH(hlac, isprimary, force), self.projectiledeathtype, other); - - remove(self); -} - -void W_HLAC_Attack(void) -{ - entity missile; - float spread; - - W_DecreaseAmmo(WEP_CVAR_PRI(hlac, ammo)); - - spread = WEP_CVAR_PRI(hlac, spread_min) + (WEP_CVAR_PRI(hlac, spread_add) * self.misc_bulletcounter); - spread = min(spread,WEP_CVAR_PRI(hlac, spread_max)); - if(self.crouch) - spread = spread * WEP_CVAR_PRI(hlac, spread_crouchmod); - - W_SetupShot(self, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_A, WEP_CVAR_PRI(hlac, damage)); - pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - if(!autocvar_g_norecoil) - { - self.punchangle_x = random() - 0.5; - self.punchangle_y = random() - 0.5; - } - - missile = spawn(); - missile.owner = missile.realowner = self; - missile.classname = "hlacbolt"; - missile.bot_dodge = TRUE; - - missile.bot_dodgerating = WEP_CVAR_PRI(hlac, damage); - - missile.movetype = MOVETYPE_FLY; - PROJECTILE_MAKETRIGGER(missile); - - setorigin(missile, w_shotorg); - setsize(missile, '0 0 0', '0 0 0'); - - W_SetupProjVelocity_Basic(missile, WEP_CVAR_PRI(hlac, speed), spread); - //missile.angles = vectoangles(missile.velocity); // csqc - - missile.touch = W_HLAC_Touch; - missile.think = SUB_Remove; - - missile.nextthink = time + WEP_CVAR_PRI(hlac, lifetime); - - missile.flags = FL_PROJECTILE; - missile.projectiledeathtype = WEP_HLAC; - - CSQCProjectile(missile, TRUE, PROJECTILE_HLAC, TRUE); - - other = missile; MUTATOR_CALLHOOK(EditProjectile); -} - -void W_HLAC_Attack2(void) -{ - entity missile; - float spread; - - spread = WEP_CVAR_SEC(hlac, spread); - - - if(self.crouch) - spread = spread * WEP_CVAR_SEC(hlac, spread_crouchmod); - - W_SetupShot(self, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_A, WEP_CVAR_SEC(hlac, damage)); - pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - missile = spawn(); - missile.owner = missile.realowner = self; - missile.classname = "hlacbolt"; - missile.bot_dodge = TRUE; - - missile.bot_dodgerating = WEP_CVAR_SEC(hlac, damage); - - missile.movetype = MOVETYPE_FLY; - PROJECTILE_MAKETRIGGER(missile); - - setorigin(missile, w_shotorg); - setsize(missile, '0 0 0', '0 0 0'); - - W_SetupProjVelocity_Basic(missile, WEP_CVAR_SEC(hlac, speed), spread); - //missile.angles = vectoangles(missile.velocity); // csqc - - missile.touch = W_HLAC_Touch; - missile.think = SUB_Remove; - - missile.nextthink = time + WEP_CVAR_SEC(hlac, lifetime); - - missile.flags = FL_PROJECTILE; - missile.missile_flags = MIF_SPLASH; - missile.projectiledeathtype = WEP_HLAC | HITTYPE_SECONDARY; - - CSQCProjectile(missile, TRUE, PROJECTILE_HLAC, TRUE); - - other = missile; MUTATOR_CALLHOOK(EditProjectile); -} - -// weapon frames -void W_HLAC_Attack_Frame(void) -{ - if(self.weapon != self.switchweapon) // abort immediately if switching - { - w_ready(); - return; - } - - if(self.BUTTON_ATCK) - { - if(!WEP_ACTION(self.weapon, WR_CHECKAMMO1)) - if(!(self.items & IT_UNLIMITED_WEAPON_AMMO)) - { - W_SwitchWeapon_Force(self, w_getbestweapon(self)); - w_ready(); - return; - } - - ATTACK_FINISHED(self) = time + WEP_CVAR_PRI(hlac, refire) * W_WeaponRateFactor(); - W_HLAC_Attack(); - self.misc_bulletcounter = self.misc_bulletcounter + 1; - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame); - } - else - { - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(hlac, animtime), w_ready); - } -} - -void W_HLAC_Attack2_Frame(void) -{ - float i; - - W_DecreaseAmmo(WEP_CVAR_SEC(hlac, ammo)); - - for(i=WEP_CVAR_SEC(hlac, shots);i>0;--i) - W_HLAC_Attack2(); - - if(!autocvar_g_norecoil) - { - self.punchangle_x = random() - 0.5; - self.punchangle_y = random() - 0.5; - } -} - -float W_HLAC(float req) -{ - float ammo_amount; - switch(req) - { - case WR_AIM: - { - self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(hlac, speed), 0, WEP_CVAR_PRI(hlac, lifetime), FALSE); - return TRUE; - } - case WR_THINK: - { - if(autocvar_g_balance_hlac_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo))) // forced reload - WEP_ACTION(self.weapon, WR_RELOAD); - else if(self.BUTTON_ATCK) - { - if(weapon_prepareattack(0, WEP_CVAR_PRI(hlac, refire))) - { - self.misc_bulletcounter = 0; - W_HLAC_Attack(); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame); - } - } - - else if(self.BUTTON_ATCK2 && WEP_CVAR(hlac, secondary)) - { - if(weapon_prepareattack(1, WEP_CVAR_SEC(hlac, refire))) - { - W_HLAC_Attack2_Frame(); - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(hlac, animtime), w_ready); - } - } - - return TRUE; - } - case WR_INIT: - { - precache_model("models/weapons/g_hlac.md3"); - precache_model("models/weapons/v_hlac.md3"); - precache_model("models/weapons/h_hlac.iqm"); - precache_sound("weapons/lasergun_fire.wav"); - HLAC_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP) - return TRUE; - } - case WR_CHECKAMMO1: - { - ammo_amount = self.WEP_AMMO(HLAC) >= WEP_CVAR_PRI(hlac, ammo); - ammo_amount += self.(weapon_load[WEP_HLAC]) >= WEP_CVAR_PRI(hlac, ammo); - return ammo_amount; - } - case WR_CHECKAMMO2: - { - ammo_amount = self.WEP_AMMO(HLAC) >= WEP_CVAR_SEC(hlac, ammo); - ammo_amount += self.(weapon_load[WEP_HLAC]) >= WEP_CVAR_SEC(hlac, ammo); - return ammo_amount; - } - case WR_CONFIG: - { - HLAC_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS) - return TRUE; - } - case WR_RELOAD: - { - W_Reload(min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo)), "weapons/reload.wav"); - return TRUE; - } - case WR_SUICIDEMESSAGE: - { - return WEAPON_HLAC_SUICIDE; - } - case WR_KILLMESSAGE: - { - return WEAPON_HLAC_MURDER; - } - } - return FALSE; -} -#endif -#ifdef CSQC -float W_HLAC(float req) -{ - switch(req) - { - case WR_IMPACTEFFECT: - { - vector org2; - org2 = w_org + w_backoff * 6; - pointparticles(particleeffectnum("laser_impact"), org2, w_backoff * 1000, 1); - if(!w_issilent) - sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_NORM); - - return TRUE; - } - case WR_INIT: - { - precache_sound("weapons/laserimpact.wav"); - return TRUE; - } - case WR_ZOOMRETICLE: - { - // no weapon specific image for this weapon - return FALSE; - } - } - return FALSE; -} -#endif -#endif diff --git a/qcsrc/common/weapons/w_hook.qc b/qcsrc/common/weapons/w_hook.qc deleted file mode 100644 index 931d3e0ad..000000000 --- a/qcsrc/common/weapons/w_hook.qc +++ /dev/null @@ -1,367 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ HOOK, -/* function */ W_Hook, -/* ammotype */ ammo_fuel, -/* impulse */ 0, -/* flags */ WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, -/* rating */ 0, -/* color */ '0 0.5 0', -/* modelname */ "hookgun", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairhook 0.5", -/* wepimg */ "weaponhook", -/* refname */ "hook", -/* wepname */ _("Grappling Hook") -); - -#define HOOK_SETTINGS(w_cvar,w_prop) HOOK_SETTINGS_LIST(w_cvar, w_prop, HOOK, hook) -#define HOOK_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, BOTH, animtime) \ - w_cvar(id, sn, BOTH, refire) \ - w_cvar(id, sn, PRI, ammo) \ - w_cvar(id, sn, PRI, hooked_ammo) \ - w_cvar(id, sn, PRI, hooked_time_free) \ - w_cvar(id, sn, PRI, hooked_time_max) \ - w_cvar(id, sn, SEC, damage) \ - w_cvar(id, sn, SEC, duration) \ - w_cvar(id, sn, SEC, edgedamage) \ - w_cvar(id, sn, SEC, force) \ - w_cvar(id, sn, SEC, gravity) \ - w_cvar(id, sn, SEC, lifetime) \ - w_cvar(id, sn, SEC, power) \ - w_cvar(id, sn, SEC, radius) \ - w_cvar(id, sn, SEC, speed) \ - w_cvar(id, sn, SEC, health) \ - w_cvar(id, sn, SEC, damageforcescale) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifdef SVQC -HOOK_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) - -.float dmg; -.float dmg_edge; -.float dmg_radius; -.float dmg_force; -.float dmg_power; -.float dmg_duration; -.float dmg_last; -.float hook_refire; -.float hook_time_hooked; -.float hook_time_fueldecrease; -#endif -#else -#ifdef SVQC - -void spawnfunc_weapon_hook(void) -{ - if(g_grappling_hook) // offhand hook - { - startitem_failed = TRUE; - remove(self); - return; - } - weapon_defaultspawnfunc(WEP_HOOK); -} - -void W_Hook_ExplodeThink(void) -{ - float dt, dmg_remaining_next, f; - - dt = time - self.teleport_time; - dmg_remaining_next = pow(bound(0, 1 - dt / self.dmg_duration, 1), self.dmg_power); - - f = self.dmg_last - dmg_remaining_next; - self.dmg_last = dmg_remaining_next; - - RadiusDamage(self, self.realowner, self.dmg * f, self.dmg_edge * f, self.dmg_radius, self.realowner, world, self.dmg_force * f, self.projectiledeathtype, world); - self.projectiledeathtype |= HITTYPE_BOUNCE; - //RadiusDamage(self, world, self.dmg * f, self.dmg_edge * f, self.dmg_radius, world, world, self.dmg_force * f, self.projectiledeathtype, world); - - if(dt < self.dmg_duration) - self.nextthink = time + 0.05; // soon - else - remove(self); -} - -void W_Hook_Explode2(void) -{ - self.event_damage = func_null; - self.touch = func_null; - self.effects |= EF_NODRAW; - - self.think = W_Hook_ExplodeThink; - self.nextthink = time; - self.dmg = WEP_CVAR_SEC(hook, damage); - self.dmg_edge = WEP_CVAR_SEC(hook, edgedamage); - self.dmg_radius = WEP_CVAR_SEC(hook, radius); - self.dmg_force = WEP_CVAR_SEC(hook, force); - self.dmg_power = WEP_CVAR_SEC(hook, power); - self.dmg_duration = WEP_CVAR_SEC(hook, duration); - self.teleport_time = time; - self.dmg_last = 1; - self.movetype = MOVETYPE_NONE; -} - -void W_Hook_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) -{ - if(self.health <= 0) - return; - - if(!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions - return; // g_projectiles_damage says to halt - - self.health = self.health - damage; - - if(self.health <= 0) - W_PrepareExplosionByDamage(self.realowner, W_Hook_Explode2); -} - -void W_Hook_Touch2(void) -{ - PROJECTILE_TOUCH; - self.use(); -} - -void W_Hook_Attack2(void) -{ - entity gren; - - //W_DecreaseAmmo(WEP_CVAR_SEC(hook, ammo)); // WEAPONTODO: Figure out how to handle ammo with hook secondary (gravitybomb) - W_SetupShot(self, FALSE, 4, "weapons/hookbomb_fire.wav", CH_WEAPON_A, WEP_CVAR_SEC(hook, damage)); - - gren = spawn(); - gren.owner = gren.realowner = self; - gren.classname = "hookbomb"; - gren.bot_dodge = TRUE; - gren.bot_dodgerating = WEP_CVAR_SEC(hook, damage); - gren.movetype = MOVETYPE_TOSS; - PROJECTILE_MAKETRIGGER(gren); - gren.projectiledeathtype = WEP_HOOK | HITTYPE_SECONDARY; - setorigin(gren, w_shotorg); - setsize(gren, '0 0 0', '0 0 0'); - - gren.nextthink = time + WEP_CVAR_SEC(hook, lifetime); - gren.think = adaptor_think2use_hittype_splash; - gren.use = W_Hook_Explode2; - gren.touch = W_Hook_Touch2; - - gren.takedamage = DAMAGE_YES; - gren.health = WEP_CVAR_SEC(hook, health); - gren.damageforcescale = WEP_CVAR_SEC(hook, damageforcescale); - gren.event_damage = W_Hook_Damage; - gren.damagedbycontents = TRUE; - gren.missile_flags = MIF_SPLASH | MIF_ARC; - - gren.velocity = '0 0 1' * WEP_CVAR_SEC(hook, speed); - if(autocvar_g_projectiles_newton_style) - gren.velocity = gren.velocity + self.velocity; - - gren.gravity = WEP_CVAR_SEC(hook, gravity); - //W_SetupProjVelocity_Basic(gren); // just falling down! - - gren.angles = '0 0 0'; - gren.flags = FL_PROJECTILE; - - CSQCProjectile(gren, TRUE, PROJECTILE_HOOKBOMB, TRUE); - - other = gren; MUTATOR_CALLHOOK(EditProjectile); -} - -float W_Hook(float req) -{ - float hooked_time_max, hooked_fuel; - - switch(req) - { - case WR_AIM: - { - // no bot AI for hook (yet?) - return TRUE; - } - case WR_THINK: - { - if(self.BUTTON_ATCK || (!(self.items & IT_JETPACK) && self.BUTTON_HOOK)) - { - if(!self.hook) - if(!(self.hook_state & HOOK_WAITING_FOR_RELEASE)) - if(!(self.hook_state & HOOK_FIRING)) - if(time > self.hook_refire) - if(weapon_prepareattack(0, -1)) - { - W_DecreaseAmmo(WEP_CVAR_PRI(hook, ammo)); - self.hook_state |= HOOK_FIRING; - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(hook, animtime), w_ready); - } - } - - if(self.BUTTON_ATCK2) - { - if(weapon_prepareattack(1, WEP_CVAR_SEC(hook, refire))) - { - W_Hook_Attack2(); - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(hook, animtime), w_ready); - } - } - - if(self.hook) - { - // if hooked, no bombs, and increase the timer - self.hook_refire = max(self.hook_refire, time + WEP_CVAR_PRI(hook, refire) * W_WeaponRateFactor()); - - // hook also inhibits health regeneration, but only for 1 second - if(!(self.items & IT_UNLIMITED_WEAPON_AMMO)) - self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen); - } - - if(self.hook && self.hook.state == 1) - { - hooked_time_max = WEP_CVAR_PRI(hook, hooked_time_max); - if(hooked_time_max > 0) - { - if( time > self.hook_time_hooked + hooked_time_max ) - self.hook_state |= HOOK_REMOVING; - } - - hooked_fuel = WEP_CVAR_PRI(hook, hooked_ammo); - if(hooked_fuel > 0) - { - if( time > self.hook_time_fueldecrease ) - { - if(!(self.items & IT_UNLIMITED_WEAPON_AMMO)) - { - if( self.ammo_fuel >= (time - self.hook_time_fueldecrease) * hooked_fuel ) - { - W_DecreaseAmmo((time - self.hook_time_fueldecrease) * hooked_fuel); - self.hook_time_fueldecrease = time; - // decrease next frame again - } - else - { - self.ammo_fuel = 0; - self.hook_state |= HOOK_REMOVING; - W_SwitchWeapon_Force(self, w_getbestweapon(self)); - } - } - } - } - } - else - { - self.hook_time_hooked = time; - self.hook_time_fueldecrease = time + WEP_CVAR_PRI(hook, hooked_time_free); - } - - if(self.BUTTON_CROUCH) - { - self.hook_state &= ~HOOK_PULLING; - if(self.BUTTON_ATCK || (!(self.items & IT_JETPACK) && self.BUTTON_HOOK)) - self.hook_state &= ~HOOK_RELEASING; - else - self.hook_state |= HOOK_RELEASING; - } - else - { - self.hook_state |= HOOK_PULLING; - self.hook_state &= ~HOOK_RELEASING; - - if(self.BUTTON_ATCK || (!(self.items & IT_JETPACK) && self.BUTTON_HOOK)) - { - // already fired - if(self.hook) - self.hook_state |= HOOK_WAITING_FOR_RELEASE; - } - else - { - self.hook_state |= HOOK_REMOVING; - self.hook_state &= ~HOOK_WAITING_FOR_RELEASE; - } - } - - return TRUE; - } - case WR_INIT: - { - precache_model("models/weapons/g_hookgun.md3"); - precache_model("models/weapons/v_hookgun.md3"); - precache_model("models/weapons/h_hookgun.iqm"); - precache_sound("weapons/hook_impact.wav"); // done by g_hook.qc - precache_sound("weapons/hook_fire.wav"); - precache_sound("weapons/hookbomb_fire.wav"); - HOOK_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP) - return TRUE; - } - case WR_SETUP: - { - self.hook_state &= ~HOOK_WAITING_FOR_RELEASE; - return TRUE; - } - case WR_CHECKAMMO1: - { - if(self.hook) - return self.ammo_fuel > 0; - else - return self.ammo_fuel >= WEP_CVAR_PRI(hook, ammo); - } - case WR_CHECKAMMO2: - { - // infinite ammo for now - return TRUE; // self.ammo_cells >= WEP_CVAR_SEC(hook, ammo); // WEAPONTODO: see above - } - case WR_CONFIG: - { - HOOK_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS) - return TRUE; - } - case WR_RESETPLAYER: - { - self.hook_refire = time; - return TRUE; - } - case WR_SUICIDEMESSAGE: - { - return FALSE; - } - case WR_KILLMESSAGE: - { - return WEAPON_HOOK_MURDER; - } - } - return FALSE; -} -#endif -#ifdef CSQC -float W_Hook(float req) -{ - switch(req) - { - case WR_IMPACTEFFECT: - { - vector org2; - org2 = w_org + w_backoff * 2; - pointparticles(particleeffectnum("hookbomb_explode"), org2, '0 0 0', 1); - if(!w_issilent) - sound(self, CH_SHOTS, "weapons/hookbomb_impact.wav", VOL_BASE, ATTN_NORM); - - return TRUE; - } - case WR_INIT: - { - precache_sound("weapons/hookbomb_impact.wav"); - return TRUE; - } - case WR_ZOOMRETICLE: - { - // no weapon specific image for this weapon - return FALSE; - } - } - return FALSE; -} -#endif -#endif diff --git a/qcsrc/common/weapons/w_machinegun.qc b/qcsrc/common/weapons/w_machinegun.qc deleted file mode 100644 index 9c69c8d82..000000000 --- a/qcsrc/common/weapons/w_machinegun.qc +++ /dev/null @@ -1,407 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ MACHINEGUN, -/* function */ W_MachineGun, -/* ammotype */ ammo_nails, -/* impulse */ 3, -/* flags */ WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN, -/* rating */ BOT_PICKUP_RATING_MID, -/* color */ '1 1 0', -/* modelname */ "uzi", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairuzi 0.6", -/* wepimg */ "weaponuzi", -/* refname */ "machinegun", -/* wepname */ _("Machine Gun") -); - -#define MACHINEGUN_SETTINGS(w_cvar,w_prop) MACHINEGUN_SETTINGS_LIST(w_cvar, w_prop, MACHINEGUN, machinegun) -#define MACHINEGUN_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, NONE, spread_min) \ - w_cvar(id, sn, NONE, spread_max) \ - w_cvar(id, sn, NONE, spread_add) \ - w_cvar(id, sn, NONE, mode) \ - w_cvar(id, sn, NONE, first) \ - w_cvar(id, sn, NONE, first_damage) \ - w_cvar(id, sn, NONE, first_force) \ - w_cvar(id, sn, NONE, first_refire) \ - w_cvar(id, sn, NONE, first_spread) \ - w_cvar(id, sn, NONE, first_ammo) \ - w_cvar(id, sn, NONE, solidpenetration) \ - w_cvar(id, sn, NONE, sustained_damage) \ - w_cvar(id, sn, NONE, sustained_force) \ - w_cvar(id, sn, NONE, sustained_refire) \ - w_cvar(id, sn, NONE, sustained_spread) \ - w_cvar(id, sn, NONE, sustained_ammo) \ - w_cvar(id, sn, NONE, burst) \ - w_cvar(id, sn, NONE, burst_refire) \ - w_cvar(id, sn, NONE, burst_refire2) \ - w_cvar(id, sn, NONE, burst_animtime) \ - w_cvar(id, sn, NONE, burst_speed) \ - w_cvar(id, sn, NONE, burst_ammo) \ - w_prop(id, sn, float, reloading_ammo, reload_ammo) \ - w_prop(id, sn, float, reloading_time, reload_time) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifdef SVQC -MACHINEGUN_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) -#endif -#else -#ifdef SVQC - -void spawnfunc_weapon_machinegun(void) -{ - if(autocvar_sv_q3acompat_machineshotgunswap) - if(self.classname != "droppedweapon") - { - weapon_defaultspawnfunc(WEP_SHOCKWAVE); - return; - } - weapon_defaultspawnfunc(WEP_MACHINEGUN); -} -void spawnfunc_weapon_uzi(void) { spawnfunc_weapon_machinegun(); } - -void W_MachineGun_MuzzleFlash_Think(void) -{ - self.frame = self.frame + 2; - self.scale = self.scale * 0.5; - self.alpha = self.alpha - 0.25; - self.nextthink = time + 0.05; - - if(self.alpha <= 0) - { - self.think = SUB_Remove; - self.nextthink = time; - self.realowner.muzzle_flash = world; - return; - } - -} - -void W_MachineGun_MuzzleFlash(void) -{ - if(self.muzzle_flash == world) - self.muzzle_flash = spawn(); - - // muzzle flash for 1st person view - setmodel(self.muzzle_flash, "models/uziflash.md3"); // precision set below - - self.muzzle_flash.scale = 0.75; - self.muzzle_flash.think = W_MachineGun_MuzzleFlash_Think; - self.muzzle_flash.nextthink = time + 0.02; - self.muzzle_flash.frame = 2; - self.muzzle_flash.alpha = 0.75; - self.muzzle_flash.angles_z = random() * 180; - self.muzzle_flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION; - self.muzzle_flash.owner = self.muzzle_flash.realowner = self; -} - -void W_MachineGun_Attack(float deathtype) -{ - W_SetupShot(self, TRUE, 0, "weapons/uzi_fire.wav", CH_WEAPON_A, ((self.misc_bulletcounter == 1) ? WEP_CVAR(machinegun, first_damage) : WEP_CVAR(machinegun, sustained_damage))); - if(!autocvar_g_norecoil) - { - self.punchangle_x = random() - 0.5; - self.punchangle_y = random() - 0.5; - } - - // this attack_finished just enforces a cooldown at the end of a burst - ATTACK_FINISHED(self) = time + WEP_CVAR(machinegun, first_refire) * W_WeaponRateFactor(); - - if(self.misc_bulletcounter == 1) - fireBullet(w_shotorg, w_shotdir, WEP_CVAR(machinegun, first_spread), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, first_damage), WEP_CVAR(machinegun, first_force), deathtype, 0); - else - fireBullet(w_shotorg, w_shotdir, WEP_CVAR(machinegun, sustained_spread), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), deathtype, 0); - - pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - W_MachineGun_MuzzleFlash(); - W_AttachToShotorg(self.muzzle_flash, '5 0 0'); - - // casing code - if(autocvar_g_casings >= 2) - SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self); - - if(self.misc_bulletcounter == 1) - W_DecreaseAmmo(WEP_CVAR(machinegun, first_ammo)); - else - W_DecreaseAmmo(WEP_CVAR(machinegun, sustained_ammo)); -} - -// weapon frames -void W_MachineGun_Attack_Frame(void) -{ - if(self.weapon != self.switchweapon) // abort immediately if switching - { - w_ready(); - return; - } - if(self.BUTTON_ATCK) - { - if(!WEP_ACTION(self.weapon, WR_CHECKAMMO2)) - if(!(self.items & IT_UNLIMITED_WEAPON_AMMO)) - { - W_SwitchWeapon_Force(self, w_getbestweapon(self)); - w_ready(); - return; - } - self.misc_bulletcounter = self.misc_bulletcounter + 1; - W_MachineGun_Attack(WEP_MACHINEGUN); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Frame); - } - else - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), w_ready); -} - - -void W_MachineGun_Attack_Auto(void) -{ - float machinegun_spread; - - if(!self.BUTTON_ATCK) - { - w_ready(); - return; - } - - if(!WEP_ACTION(self.weapon, WR_CHECKAMMO1)) - if(!(self.items & IT_UNLIMITED_WEAPON_AMMO)) - { - W_SwitchWeapon_Force(self, w_getbestweapon(self)); - w_ready(); - return; - } - - W_DecreaseAmmo(WEP_CVAR(machinegun, sustained_ammo)); - - W_SetupShot(self, TRUE, 0, "weapons/uzi_fire.wav", CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage)); - if(!autocvar_g_norecoil) - { - self.punchangle_x = random() - 0.5; - self.punchangle_y = random() - 0.5; - } - - machinegun_spread = bound(WEP_CVAR(machinegun, spread_min), WEP_CVAR(machinegun, spread_min) + (WEP_CVAR(machinegun, spread_add) * self.misc_bulletcounter), WEP_CVAR(machinegun, spread_max)); - fireBullet(w_shotorg, w_shotdir, machinegun_spread, WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), WEP_MACHINEGUN, 0); - - self.misc_bulletcounter = self.misc_bulletcounter + 1; - - pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - W_MachineGun_MuzzleFlash(); - W_AttachToShotorg(self.muzzle_flash, '5 0 0'); - - if(autocvar_g_casings >= 2) // casing code - SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self); - - ATTACK_FINISHED(self) = time + WEP_CVAR(machinegun, first_refire) * W_WeaponRateFactor(); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Auto); -} - -void W_MachineGun_Attack_Burst(void) -{ - W_SetupShot(self, TRUE, 0, "weapons/uzi_fire.wav", CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage)); - if(!autocvar_g_norecoil) - { - self.punchangle_x = random() - 0.5; - self.punchangle_y = random() - 0.5; - } - - fireBullet(w_shotorg, w_shotdir, WEP_CVAR(machinegun, burst_speed), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), WEP_MACHINEGUN, 0); - - pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - W_MachineGun_MuzzleFlash(); - W_AttachToShotorg(self.muzzle_flash, '5 0 0'); - - if(autocvar_g_casings >= 2) // casing code - SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self); - - self.misc_bulletcounter = self.misc_bulletcounter + 1; - if(self.misc_bulletcounter == 0) - { - ATTACK_FINISHED(self) = time + WEP_CVAR(machinegun, burst_refire2) * W_WeaponRateFactor(); - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(machinegun, burst_animtime), w_ready); - } - else - { - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(machinegun, burst_refire), W_MachineGun_Attack_Burst); - } - -} - -float W_MachineGun(float req) -{ - float ammo_amount; - switch(req) - { - case WR_AIM: - { - if(vlen(self.origin-self.enemy.origin) < 3000 - bound(0, skill, 10) * 200) - self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, FALSE); - else - self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, FALSE); - - return TRUE; - } - case WR_THINK: - { - if(WEP_CVAR(machinegun, reload_ammo) && self.clip_load < min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo))) // forced reload - WEP_ACTION(self.weapon, WR_RELOAD); - else if(WEP_CVAR(machinegun, mode) == 1) - { - if(self.BUTTON_ATCK) - if(weapon_prepareattack(0, 0)) - { - self.misc_bulletcounter = 0; - W_MachineGun_Attack_Auto(); - } - - if(self.BUTTON_ATCK2) - if(weapon_prepareattack(1, 0)) - { - if(!WEP_ACTION(self.weapon, WR_CHECKAMMO2)) - if(!(self.items & IT_UNLIMITED_WEAPON_AMMO)) - { - W_SwitchWeapon_Force(self, w_getbestweapon(self)); - w_ready(); - return FALSE; - } - - W_DecreaseAmmo(WEP_CVAR(machinegun, burst_ammo)); - - self.misc_bulletcounter = WEP_CVAR(machinegun, burst) * -1; - W_MachineGun_Attack_Burst(); - } - } - else - { - - if(self.BUTTON_ATCK) - if(weapon_prepareattack(0, 0)) - { - self.misc_bulletcounter = 1; - W_MachineGun_Attack(WEP_MACHINEGUN); // sets attack_finished - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Frame); - } - - if(self.BUTTON_ATCK2 && WEP_CVAR(machinegun, first)) - if(weapon_prepareattack(1, 0)) - { - self.misc_bulletcounter = 1; - W_MachineGun_Attack(WEP_MACHINEGUN | HITTYPE_SECONDARY); // sets attack_finished - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(machinegun, first_refire), w_ready); - } - } - - return TRUE; - } - case WR_INIT: - { - precache_model("models/uziflash.md3"); - precache_model("models/weapons/g_uzi.md3"); - precache_model("models/weapons/v_uzi.md3"); - precache_model("models/weapons/h_uzi.iqm"); - precache_sound("weapons/uzi_fire.wav"); - MACHINEGUN_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP) - return TRUE; - } - case WR_CHECKAMMO1: - { - if(WEP_CVAR(machinegun, mode) == 1) - ammo_amount = self.WEP_AMMO(MACHINEGUN) >= WEP_CVAR(machinegun, sustained_ammo); - else - ammo_amount = self.WEP_AMMO(MACHINEGUN) >= WEP_CVAR(machinegun, first_ammo); - - if(WEP_CVAR(machinegun, reload_ammo)) - { - if(WEP_CVAR(machinegun, mode) == 1) - ammo_amount += self.(weapon_load[WEP_MACHINEGUN]) >= WEP_CVAR(machinegun, sustained_ammo); - else - ammo_amount += self.(weapon_load[WEP_MACHINEGUN]) >= WEP_CVAR(machinegun, first_ammo); - } - return ammo_amount; - } - case WR_CHECKAMMO2: - { - if(WEP_CVAR(machinegun, mode) == 1) - ammo_amount = self.WEP_AMMO(MACHINEGUN) >= WEP_CVAR(machinegun, burst_ammo); - else - ammo_amount = self.WEP_AMMO(MACHINEGUN) >= WEP_CVAR(machinegun, first_ammo); - - if(WEP_CVAR(machinegun, reload_ammo)) - { - if(WEP_CVAR(machinegun, mode) == 1) - ammo_amount += self.(weapon_load[WEP_MACHINEGUN]) >= WEP_CVAR(machinegun, burst_ammo); - else - ammo_amount += self.(weapon_load[WEP_MACHINEGUN]) >= WEP_CVAR(machinegun, first_ammo); - } - return ammo_amount; - } - case WR_CONFIG: - { - MACHINEGUN_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS) - return TRUE; - } - case WR_RELOAD: - { - W_Reload(min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo)), "weapons/reload.wav"); - return TRUE; - } - case WR_SUICIDEMESSAGE: - { - return WEAPON_THINKING_WITH_PORTALS; - } - case WR_KILLMESSAGE: - { - if(w_deathtype & HITTYPE_SECONDARY) - return WEAPON_MACHINEGUN_MURDER_SNIPE; - else - return WEAPON_MACHINEGUN_MURDER_SPRAY; - } - } - return FALSE; -} -#endif -#ifdef CSQC -float W_MachineGun(float req) -{ - switch(req) - { - case WR_IMPACTEFFECT: - { - vector org2; - org2 = w_org + w_backoff * 2; - pointparticles(particleeffectnum("machinegun_impact"), org2, w_backoff * 1000, 1); - if(!w_issilent) - if(w_random < 0.05) - sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTN_NORM); - else if(w_random < 0.1) - sound(self, CH_SHOTS, "weapons/ric2.wav", VOL_BASE, ATTN_NORM); - else if(w_random < 0.2) - sound(self, CH_SHOTS, "weapons/ric3.wav", VOL_BASE, ATTN_NORM); - - return TRUE; - } - case WR_INIT: - { - precache_sound("weapons/ric1.wav"); - precache_sound("weapons/ric2.wav"); - precache_sound("weapons/ric3.wav"); - return TRUE; - } - case WR_ZOOMRETICLE: - { - // no weapon specific image for this weapon - return FALSE; - } - } - return FALSE; -} -#endif -#endif diff --git a/qcsrc/common/weapons/w_minelayer.qc b/qcsrc/common/weapons/w_minelayer.qc deleted file mode 100644 index e0e9c6256..000000000 --- a/qcsrc/common/weapons/w_minelayer.qc +++ /dev/null @@ -1,620 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ MINE_LAYER, -/* function */ W_MineLayer, -/* ammotype */ ammo_rockets, -/* impulse */ 4, -/* flags */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH, -/* rating */ BOT_PICKUP_RATING_HIGH, -/* color */ '0.75 1 0', -/* modelname */ "minelayer", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairminelayer 0.9", -/* wepimg */ "weaponminelayer", -/* refname */ "minelayer", -/* wepname */ _("Mine Layer") -); - -#define MINELAYER_SETTINGS(w_cvar,w_prop) MINELAYER_SETTINGS_LIST(w_cvar, w_prop, MINE_LAYER, minelayer) -#define MINELAYER_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, NONE, ammo) \ - w_cvar(id, sn, NONE, animtime) \ - w_cvar(id, sn, NONE, damage) \ - w_cvar(id, sn, NONE, damageforcescale) \ - w_cvar(id, sn, NONE, detonatedelay) \ - w_cvar(id, sn, NONE, edgedamage) \ - w_cvar(id, sn, NONE, force) \ - w_cvar(id, sn, NONE, health) \ - w_cvar(id, sn, NONE, lifetime) \ - w_cvar(id, sn, NONE, lifetime_countdown) \ - w_cvar(id, sn, NONE, limit) \ - w_cvar(id, sn, NONE, protection) \ - w_cvar(id, sn, NONE, proximityradius) \ - w_cvar(id, sn, NONE, radius) \ - w_cvar(id, sn, NONE, refire) \ - w_cvar(id, sn, NONE, remote_damage) \ - w_cvar(id, sn, NONE, remote_edgedamage) \ - w_cvar(id, sn, NONE, remote_force) \ - w_cvar(id, sn, NONE, remote_radius) \ - w_cvar(id, sn, NONE, speed) \ - w_cvar(id, sn, NONE, time) \ - w_prop(id, sn, float, reloading_ammo, reload_ammo) \ - w_prop(id, sn, float, reloading_time, reload_time) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifdef SVQC -MINELAYER_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) -void W_MineLayer_Think(void); -.float minelayer_detonate, mine_explodeanyway; -.float mine_time; -.vector mine_orientation; -#endif -#else -#ifdef SVQC -void spawnfunc_weapon_minelayer(void) { weapon_defaultspawnfunc(WEP_MINE_LAYER); } - -void W_MineLayer_Stick(entity to) -{ - spamsound(self, CH_SHOTS, "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 - - entity newmine; - newmine = spawn(); - newmine.classname = self.classname; - - newmine.bot_dodge = self.bot_dodge; - newmine.bot_dodgerating = self.bot_dodgerating; - - newmine.owner = self.owner; - newmine.realowner = self.realowner; - 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.mine_orientation = -trace_plane_normal; - - newmine.takedamage = self.takedamage; - newmine.damageforcescale = self.damageforcescale; - newmine.health = self.health; - newmine.event_damage = self.event_damage; - newmine.spawnshieldtime = self.spawnshieldtime; - newmine.damagedbycontents = TRUE; - - newmine.movetype = MOVETYPE_NONE; // lock the mine in place - newmine.projectiledeathtype = self.projectiledeathtype; - - newmine.mine_time = self.mine_time; - - newmine.touch = func_null; - newmine.think = W_MineLayer_Think; - newmine.nextthink = time; - newmine.cnt = self.cnt; - newmine.flags = self.flags; - - remove(self); - self = newmine; - - if(to) - SetMovetypeFollow(self, to); -} - -void W_MineLayer_Explode(void) -{ - if(other.takedamage == DAMAGE_AIM) - if(IS_PLAYER(other)) - if(DIFF_TEAM(self.realowner, other)) - if(other.deadflag == DEAD_NO) - if(IsFlying(other)) - Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT); - - self.event_damage = func_null; - self.takedamage = DAMAGE_NO; - - RadiusDamage(self, self.realowner, WEP_CVAR(minelayer, damage), WEP_CVAR(minelayer, edgedamage), WEP_CVAR(minelayer, radius), world, world, WEP_CVAR(minelayer, force), self.projectiledeathtype, other); - - if(self.realowner.weapon == WEP_MINE_LAYER) - { - entity oldself; - oldself = self; - self = self.realowner; - if(!WEP_ACTION(WEP_MINE_LAYER, WR_CHECKAMMO1)) - { - self.cnt = WEP_MINE_LAYER; - ATTACK_FINISHED(self) = time; - self.switchweapon = w_getbestweapon(self); - } - self = oldself; - } - self.realowner.minelayer_mines -= 1; - remove(self); -} - -void W_MineLayer_DoRemoteExplode(void) -{ - self.event_damage = func_null; - self.takedamage = DAMAGE_NO; - - if(self.movetype == MOVETYPE_NONE || self.movetype == MOVETYPE_FOLLOW) - self.velocity = self.mine_orientation; // particle fx and decals need .velocity - - RadiusDamage(self, self.realowner, WEP_CVAR(minelayer, remote_damage), WEP_CVAR(minelayer, remote_edgedamage), WEP_CVAR(minelayer, remote_radius), world, world, WEP_CVAR(minelayer, remote_force), self.projectiledeathtype | HITTYPE_BOUNCE, world); - - if(self.realowner.weapon == WEP_MINE_LAYER) - { - entity oldself; - oldself = self; - self = self.realowner; - if(!WEP_ACTION(WEP_MINE_LAYER, WR_CHECKAMMO1)) - { - self.cnt = WEP_MINE_LAYER; - ATTACK_FINISHED(self) = time; - self.switchweapon = w_getbestweapon(self); - } - self = oldself; - } - self.realowner.minelayer_mines -= 1; - remove(self); -} - -void W_MineLayer_RemoteExplode(void) -{ - if(self.realowner.deadflag == DEAD_NO) - if((self.spawnshieldtime >= 0) - ? (time >= self.spawnshieldtime) // timer - : (vlen(NearestPointOnBox(self.realowner, self.origin) - self.origin) > WEP_CVAR(minelayer, remote_radius)) // safety device - ) - { - W_MineLayer_DoRemoteExplode(); - } -} - -void W_MineLayer_ProximityExplode(void) -{ - // 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(WEP_CVAR(minelayer, protection) && self.mine_explodeanyway == 0) - { - entity head; - head = findradius(self.origin, WEP_CVAR(minelayer, radius)); - while(head) - { - if(head == self.realowner || SAME_TEAM(head, self.realowner)) - return; - head = head.chain; - } - } - - self.mine_time = 0; - W_MineLayer_Explode(); -} - -float W_MineLayer_Count(entity e) -{ - float minecount = 0; - entity mine; - for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.realowner == e) - minecount += 1; - - return minecount; -} - -void W_MineLayer_Think(void) -{ - entity head; - - self.nextthink = time; - - if(self.movetype == MOVETYPE_FOLLOW) - { - if(LostMovetypeFollow(self)) - { - UnsetMovetypeFollow(self); - self.movetype = MOVETYPE_NONE; - } - } - - // our lifetime has expired, it's time to die - mine_time just allows us to play a sound for this - // TODO: replace this mine_trigger.wav sound with a real countdown - if((time > self.cnt) && (!self.mine_time)) - { - if(WEP_CVAR(minelayer, lifetime_countdown) > 0) - spamsound(self, CH_SHOTS, "weapons/mine_trigger.wav", VOL_BASE, ATTN_NORM); - self.mine_time = time + WEP_CVAR(minelayer, lifetime_countdown); - self.mine_explodeanyway = 1; // make the mine super aggressive -- Samual: Rather, make it not care if a team mate is near. - } - - // a player's mines shall explode if he disconnects or dies - // TODO: Do this on team change too -- Samual: But isn't a player killed when they switch teams? - if(!IS_PLAYER(self.realowner) || self.realowner.deadflag != DEAD_NO || self.realowner.frozen) - { - other = world; - self.projectiledeathtype |= HITTYPE_BOUNCE; - W_MineLayer_Explode(); - return; - } - - // set the mine for detonation when a foe gets close enough - head = findradius(self.origin, WEP_CVAR(minelayer, proximityradius)); - while(head) - { - if(IS_PLAYER(head) && head.deadflag == DEAD_NO && !head.frozen) - if(head != self.realowner && DIFF_TEAM(head, self.realowner)) // don't trigger for team mates - if(!self.mine_time) - { - spamsound(self, CH_SHOTS, "weapons/mine_trigger.wav", VOL_BASE, ATTN_NORM); - self.mine_time = time + WEP_CVAR(minelayer, time); - } - head = head.chain; - } - - // explode if it's time to - if(self.mine_time && time >= self.mine_time) - { - W_MineLayer_ProximityExplode(); - return; - } - - // remote detonation - if(self.realowner.weapon == WEP_MINE_LAYER) - if(self.realowner.deadflag == DEAD_NO) - if(self.minelayer_detonate) - W_MineLayer_RemoteExplode(); -} - -void W_MineLayer_Touch(void) -{ - if(self.movetype == MOVETYPE_NONE || self.movetype == MOVETYPE_FOLLOW) - return; // we're already a stuck mine, why do we get called? TODO does this even happen? - - if(WarpZone_Projectile_Touch()) - { - if(wasfreed(self)) - self.realowner.minelayer_mines -= 1; - return; - } - - if(other && IS_PLAYER(other) && other.deadflag == DEAD_NO) - { - // hit a player - // don't stick - } - else - { - W_MineLayer_Stick(other); - } -} - -void W_MineLayer_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) -{ - if(self.health <= 0) - return; - - float is_from_enemy = (inflictor.realowner != self.realowner); - - if(!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, (is_from_enemy ? 1 : -1))) - return; // g_projectiles_damage says to halt - - self.health = self.health - damage; - self.angles = vectoangles(self.velocity); - - if(self.health <= 0) - W_PrepareExplosionByDamage(attacker, W_MineLayer_Explode); -} - -void W_MineLayer_Attack(void) -{ - entity mine; - entity flash; - - // scan how many mines we placed, and return if we reached our limit - if(WEP_CVAR(minelayer, limit)) - { - if(self.minelayer_mines >= WEP_CVAR(minelayer, limit)) - { - // the refire delay keeps this message from being spammed - sprint(self, strcat("minelayer: You cannot place more than ^2", ftos(WEP_CVAR(minelayer, limit)), " ^7mines at a time\n") ); - play2(self, "weapons/unavailable.wav"); - return; - } - } - - W_DecreaseAmmo(WEP_CVAR(minelayer, ammo)); - - W_SetupShot_ProjectileSize(self, '-4 -4 -4', '4 4 4', FALSE, 5, "weapons/mine_fire.wav", CH_WEAPON_A, WEP_CVAR(minelayer, damage)); - pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - mine = WarpZone_RefSys_SpawnSameRefSys(self); - mine.owner = mine.realowner = self; - if(WEP_CVAR(minelayer, detonatedelay) >= 0) - mine.spawnshieldtime = time + WEP_CVAR(minelayer, detonatedelay); - else - mine.spawnshieldtime = -1; - mine.classname = "mine"; - mine.bot_dodge = TRUE; - mine.bot_dodgerating = WEP_CVAR(minelayer, damage) * 2; // * 2 because it can detonate inflight which makes it even more dangerous - - mine.takedamage = DAMAGE_YES; - mine.damageforcescale = WEP_CVAR(minelayer, damageforcescale); - mine.health = WEP_CVAR(minelayer, health); - mine.event_damage = W_MineLayer_Damage; - mine.damagedbycontents = TRUE; - - 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_SetupProjVelocity_Basic(mine, WEP_CVAR(minelayer, speed), 0); - mine.angles = vectoangles(mine.velocity); - - mine.touch = W_MineLayer_Touch; - mine.think = W_MineLayer_Think; - mine.nextthink = time; - mine.cnt = time + (WEP_CVAR(minelayer, lifetime) - WEP_CVAR(minelayer, lifetime_countdown)); - mine.flags = FL_PROJECTILE; - mine.missile_flags = MIF_SPLASH | MIF_ARC | MIF_PROXY; - - CSQCProjectile(mine, TRUE, 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 - - other = mine; MUTATOR_CALLHOOK(EditProjectile); - - self.minelayer_mines = W_MineLayer_Count(self); -} - -float W_MineLayer_PlacedMines(float detonate) -{ - entity mine; - float minfound = 0; - - for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.realowner == self) - { - if(detonate) - { - if(!mine.minelayer_detonate) - { - mine.minelayer_detonate = TRUE; - minfound = 1; - } - } - else - minfound = 1; - } - return minfound; -} - -float W_MineLayer(float req) -{ - entity mine; - float ammo_amount; - switch(req) - { - case WR_AIM: - { - // aim and decide to fire if appropriate - if(self.minelayer_mines >= WEP_CVAR(minelayer, limit)) - self.BUTTON_ATCK = FALSE; - else - self.BUTTON_ATCK = bot_aim(WEP_CVAR(minelayer, speed), 0, WEP_CVAR(minelayer, lifetime), FALSE); - if(skill >= 2) // skill 0 and 1 bots won't detonate mines! - { - // decide whether to detonate mines - entity targetlist, targ; - float edgedamage, coredamage, edgeradius, recipricoledgeradius, d; - float selfdamage, teamdamage, enemydamage; - edgedamage = WEP_CVAR(minelayer, edgedamage); - coredamage = WEP_CVAR(minelayer, damage); - edgeradius = WEP_CVAR(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.realowner != 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 && teamplay) - teamdamage = teamdamage + d; - else if(bot_shouldattack(targ)) - enemydamage = enemydamage + d; - targ = targ.chain; - } - mine = find(mine, classname, "mine"); - } - float desirabledamage; - desirabledamage = enemydamage; - if(time > self.invincible_finished && time > self.spawnshieldtime) - desirabledamage = desirabledamage - selfdamage * autocvar_g_balance_selfdamagepercent; - if(teamplay && self.team) - desirabledamage = desirabledamage - teamdamage; - - mine = find(world, classname, "mine"); - while(mine) - { - if(mine.realowner != 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{ - 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(IS_PLAYER(self.enemy)) - 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; - } - - return TRUE; - } - case WR_THINK: - { - if(autocvar_g_balance_minelayer_reload_ammo && self.clip_load < WEP_CVAR(minelayer, ammo)) // forced reload - { - // not if we're holding the minelayer without enough ammo, but can detonate existing mines - if(!(W_MineLayer_PlacedMines(FALSE) && self.WEP_AMMO(MINE_LAYER) < WEP_CVAR(minelayer, ammo))) - WEP_ACTION(self.weapon, WR_RELOAD); - } - else if(self.BUTTON_ATCK) - { - if(weapon_prepareattack(0, WEP_CVAR(minelayer, refire))) - { - W_MineLayer_Attack(); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(minelayer, animtime), w_ready); - } - } - - if(self.BUTTON_ATCK2) - { - if(W_MineLayer_PlacedMines(TRUE)) - sound(self, CH_WEAPON_B, "weapons/mine_det.wav", VOL_BASE, ATTN_NORM); - } - - return TRUE; - } - case WR_INIT: - { - 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"); - MINELAYER_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP) - return TRUE; - } - case WR_CHECKAMMO1: - { - // don't switch while placing a mine - if(ATTACK_FINISHED(self) <= time || self.weapon != WEP_MINE_LAYER) - { - ammo_amount = self.WEP_AMMO(MINE_LAYER) >= WEP_CVAR(minelayer, ammo); - ammo_amount += self.(weapon_load[WEP_MINE_LAYER]) >= WEP_CVAR(minelayer, ammo); - return ammo_amount; - } - return TRUE; - } - case WR_CHECKAMMO2: - { - if(W_MineLayer_PlacedMines(FALSE)) - return TRUE; - else - return FALSE; - } - case WR_CONFIG: - { - MINELAYER_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS) - return TRUE; - } - case WR_RESETPLAYER: - { - self.minelayer_mines = 0; - return TRUE; - } - case WR_RELOAD: - { - W_Reload(WEP_CVAR(minelayer, ammo), "weapons/reload.wav"); - return TRUE; - } - case WR_SUICIDEMESSAGE: - { - return WEAPON_MINELAYER_SUICIDE; - } - case WR_KILLMESSAGE: - { - return WEAPON_MINELAYER_MURDER; - } - } - return FALSE; -} -#endif -#ifdef CSQC -float W_MineLayer(float req) -{ - switch(req) - { - case WR_IMPACTEFFECT: - { - vector org2; - org2 = w_org + w_backoff * 12; - pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1); - if(!w_issilent) - sound(self, CH_SHOTS, "weapons/mine_exp.wav", VOL_BASE, ATTN_NORM); - - return TRUE; - } - case WR_INIT: - { - precache_sound("weapons/mine_exp.wav"); - return TRUE; - } - case WR_ZOOMRETICLE: - { - // no weapon specific image for this weapon - return FALSE; - } - } - return FALSE; -} -#endif -#endif diff --git a/qcsrc/common/weapons/w_mortar.qc b/qcsrc/common/weapons/w_mortar.qc deleted file mode 100644 index de40fcb39..000000000 --- a/qcsrc/common/weapons/w_mortar.qc +++ /dev/null @@ -1,490 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ MORTAR, -/* function */ W_Mortar, -/* ammotype */ ammo_rockets, -/* impulse */ 4, -/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, -/* rating */ BOT_PICKUP_RATING_MID, -/* color */ '1 0 0', -/* modelname */ "gl", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairgrenadelauncher 0.7", -/* wepimg */ "weapongrenadelauncher", -/* refname */ "mortar", -/* wepname */ _("Mortar") -); - -#define MORTAR_SETTINGS(w_cvar,w_prop) MORTAR_SETTINGS_LIST(w_cvar, w_prop, MORTAR, mortar) -#define MORTAR_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, BOTH, ammo) \ - w_cvar(id, sn, BOTH, animtime) \ - w_cvar(id, sn, NONE, bouncefactor) \ - w_cvar(id, sn, NONE, bouncestop) \ - w_cvar(id, sn, BOTH, damage) \ - w_cvar(id, sn, BOTH, damageforcescale) \ - w_cvar(id, sn, BOTH, edgedamage) \ - w_cvar(id, sn, BOTH, force) \ - w_cvar(id, sn, BOTH, health) \ - w_cvar(id, sn, BOTH, lifetime) \ - w_cvar(id, sn, SEC, lifetime_bounce) \ - w_cvar(id, sn, BOTH, lifetime_stick) \ - w_cvar(id, sn, BOTH, radius) \ - w_cvar(id, sn, BOTH, refire) \ - w_cvar(id, sn, SEC, remote_detonateprimary) \ - w_cvar(id, sn, PRI, remote_minbouncecnt) \ - w_cvar(id, sn, BOTH, speed) \ - w_cvar(id, sn, BOTH, speed_up) \ - w_cvar(id, sn, BOTH, speed_z) \ - w_cvar(id, sn, BOTH, spread) \ - w_cvar(id, sn, BOTH, type) \ - w_prop(id, sn, float, reloading_ammo, reload_ammo) \ - w_prop(id, sn, float, reloading_time, reload_time) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifdef SVQC -MORTAR_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) -.float gl_detonate_later; -.float gl_bouncecnt; -#endif -#else -#ifdef SVQC - -void spawnfunc_weapon_mortar(void) { weapon_defaultspawnfunc(WEP_MORTAR); } -void spawnfunc_weapon_grenadelauncher(void) { spawnfunc_weapon_mortar(); } - -void W_Mortar_Grenade_Explode(void) -{ - if(other.takedamage == DAMAGE_AIM) - if(IS_PLAYER(other)) - if(DIFF_TEAM(self.realowner, other)) - if(other.deadflag == DEAD_NO) - if(IsFlying(other)) - Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT); - - self.event_damage = func_null; - self.takedamage = DAMAGE_NO; - - if(self.movetype == MOVETYPE_NONE) - self.velocity = self.oldvelocity; - - RadiusDamage(self, self.realowner, WEP_CVAR_PRI(mortar, damage), WEP_CVAR_PRI(mortar, edgedamage), WEP_CVAR_PRI(mortar, radius), world, world, WEP_CVAR_PRI(mortar, force), self.projectiledeathtype, other); - - remove(self); -} - -void W_Mortar_Grenade_Explode2(void) -{ - if(other.takedamage == DAMAGE_AIM) - if(IS_PLAYER(other)) - if(DIFF_TEAM(self.realowner, other)) - if(other.deadflag == DEAD_NO) - if(IsFlying(other)) - Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT); - - self.event_damage = func_null; - self.takedamage = DAMAGE_NO; - - if(self.movetype == MOVETYPE_NONE) - self.velocity = self.oldvelocity; - - RadiusDamage(self, self.realowner, WEP_CVAR_SEC(mortar, damage), WEP_CVAR_SEC(mortar, edgedamage), WEP_CVAR_SEC(mortar, radius), world, world, WEP_CVAR_SEC(mortar, force), self.projectiledeathtype, other); - - remove(self); -} - - -void W_Mortar_Grenade_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) -{ - if(self.health <= 0) - return; - - if(!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions - return; // g_projectiles_damage says to halt - - self.health = self.health - damage; - - if(self.health <= 0) - W_PrepareExplosionByDamage(attacker, self.use); -} - -void W_Mortar_Grenade_Think1(void) -{ - self.nextthink = time; - if(time > self.cnt) - { - other = world; - self.projectiledeathtype |= HITTYPE_BOUNCE; - W_Mortar_Grenade_Explode(); - return; - } - if(self.gl_detonate_later && self.gl_bouncecnt >= WEP_CVAR_PRI(mortar, remote_minbouncecnt)) - W_Mortar_Grenade_Explode(); -} - -void W_Mortar_Grenade_Touch1(void) -{ - PROJECTILE_TOUCH; - if(other.takedamage == DAMAGE_AIM || WEP_CVAR_PRI(mortar, type) == 0) // always explode when hitting a player, or if normal mortar projectile - { - self.use(); - } - else if(WEP_CVAR_PRI(mortar, type) == 1) // bounce - { - float r; - r = random() * 6; - if(r < 1) - spamsound(self, CH_SHOTS, "weapons/grenade_bounce1.wav", VOL_BASE, ATTN_NORM); - else if(r < 2) - spamsound(self, CH_SHOTS, "weapons/grenade_bounce2.wav", VOL_BASE, ATTN_NORM); - else if(r < 3) - spamsound(self, CH_SHOTS, "weapons/grenade_bounce3.wav", VOL_BASE, ATTN_NORM); - else if(r < 4) - spamsound(self, CH_SHOTS, "weapons/grenade_bounce4.wav", VOL_BASE, ATTN_NORM); - else if(r < 5) - spamsound(self, CH_SHOTS, "weapons/grenade_bounce5.wav", VOL_BASE, ATTN_NORM); - else - spamsound(self, CH_SHOTS, "weapons/grenade_bounce6.wav", VOL_BASE, ATTN_NORM); - pointparticles(particleeffectnum("hagar_bounce"), self.origin, self.velocity, 1); - self.projectiledeathtype |= HITTYPE_BOUNCE; - self.gl_bouncecnt += 1; - } - else if(WEP_CVAR_PRI(mortar, type) == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick - { - spamsound(self, CH_SHOTS, "weapons/grenade_stick.wav", VOL_BASE, ATTN_NORM); - - // let it stick whereever it is - self.oldvelocity = self.velocity; - self.velocity = '0 0 0'; - self.movetype = MOVETYPE_NONE; // also disables gravity - self.gravity = 0; // nope, it does NOT! maybe a bug in CSQC code? TODO - UpdateCSQCProjectile(self); - - // do not respond to any more touches - self.solid = SOLID_NOT; - - self.nextthink = min(self.nextthink, time + WEP_CVAR_PRI(mortar, lifetime_stick)); - } -} - -void W_Mortar_Grenade_Touch2(void) -{ - PROJECTILE_TOUCH; - if(other.takedamage == DAMAGE_AIM || WEP_CVAR_SEC(mortar, type) == 0) // always explode when hitting a player, or if normal mortar projectile - { - self.use(); - } - else if(WEP_CVAR_SEC(mortar, type) == 1) // bounce - { - float r; - r = random() * 6; - if(r < 1) - spamsound(self, CH_SHOTS, "weapons/grenade_bounce1.wav", VOL_BASE, ATTN_NORM); - else if(r < 2) - spamsound(self, CH_SHOTS, "weapons/grenade_bounce2.wav", VOL_BASE, ATTN_NORM); - else if(r < 3) - spamsound(self, CH_SHOTS, "weapons/grenade_bounce3.wav", VOL_BASE, ATTN_NORM); - else if(r < 4) - spamsound(self, CH_SHOTS, "weapons/grenade_bounce4.wav", VOL_BASE, ATTN_NORM); - else if(r < 5) - spamsound(self, CH_SHOTS, "weapons/grenade_bounce5.wav", VOL_BASE, ATTN_NORM); - else - spamsound(self, CH_SHOTS, "weapons/grenade_bounce6.wav", VOL_BASE, ATTN_NORM); - pointparticles(particleeffectnum("hagar_bounce"), self.origin, self.velocity, 1); - self.projectiledeathtype |= HITTYPE_BOUNCE; - self.gl_bouncecnt += 1; - - if(WEP_CVAR_SEC(mortar, lifetime_bounce) && self.gl_bouncecnt == 1) - self.nextthink = time + WEP_CVAR_SEC(mortar, lifetime_bounce); - - } - else if(WEP_CVAR_SEC(mortar, type) == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick - { - spamsound(self, CH_SHOTS, "weapons/grenade_stick.wav", VOL_BASE, ATTN_NORM); - - // let it stick whereever it is - self.oldvelocity = self.velocity; - self.velocity = '0 0 0'; - self.movetype = MOVETYPE_NONE; // also disables gravity - self.gravity = 0; // nope, it does NOT! maybe a bug in CSQC code? TODO - UpdateCSQCProjectile(self); - - // do not respond to any more touches - self.solid = SOLID_NOT; - - self.nextthink = min(self.nextthink, time + WEP_CVAR_SEC(mortar, lifetime_stick)); - } -} - -void W_Mortar_Attack(void) -{ - entity gren; - - W_DecreaseAmmo(WEP_CVAR_PRI(mortar, ammo)); - - W_SetupShot_ProjectileSize(self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CH_WEAPON_A, WEP_CVAR_PRI(mortar, damage)); - w_shotdir = v_forward; // no TrueAim for grenades please - - pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - gren = spawn(); - gren.owner = gren.realowner = self; - gren.classname = "grenade"; - gren.bot_dodge = TRUE; - gren.bot_dodgerating = WEP_CVAR_PRI(mortar, damage); - gren.movetype = MOVETYPE_BOUNCE; - gren.bouncefactor = WEP_CVAR(mortar, bouncefactor); - gren.bouncestop = WEP_CVAR(mortar, bouncestop); - PROJECTILE_MAKETRIGGER(gren); - gren.projectiledeathtype = WEP_MORTAR; - setorigin(gren, w_shotorg); - setsize(gren, '-3 -3 -3', '3 3 3'); - - gren.cnt = time + WEP_CVAR_PRI(mortar, lifetime); - gren.nextthink = time; - gren.think = W_Mortar_Grenade_Think1; - gren.use = W_Mortar_Grenade_Explode; - gren.touch = W_Mortar_Grenade_Touch1; - - gren.takedamage = DAMAGE_YES; - gren.health = WEP_CVAR_PRI(mortar, health); - gren.damageforcescale = WEP_CVAR_PRI(mortar, damageforcescale); - gren.event_damage = W_Mortar_Grenade_Damage; - gren.damagedbycontents = TRUE; - gren.missile_flags = MIF_SPLASH | MIF_ARC; - W_SetupProjVelocity_UP_PRI(gren, mortar); - - gren.angles = vectoangles(gren.velocity); - gren.flags = FL_PROJECTILE; - - if(WEP_CVAR_PRI(mortar, type) == 0 || WEP_CVAR_PRI(mortar, type) == 2) - CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE, TRUE); - else - CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE_BOUNCING, TRUE); - - other = gren; MUTATOR_CALLHOOK(EditProjectile); -} - -void W_Mortar_Attack2(void) -{ - entity gren; - - W_DecreaseAmmo(WEP_CVAR_SEC(mortar, ammo)); - - W_SetupShot_ProjectileSize(self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CH_WEAPON_A, WEP_CVAR_SEC(mortar, damage)); - w_shotdir = v_forward; // no TrueAim for grenades please - - pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - gren = spawn(); - gren.owner = gren.realowner = self; - gren.classname = "grenade"; - gren.bot_dodge = TRUE; - gren.bot_dodgerating = WEP_CVAR_SEC(mortar, damage); - gren.movetype = MOVETYPE_BOUNCE; - gren.bouncefactor = WEP_CVAR(mortar, bouncefactor); - gren.bouncestop = WEP_CVAR(mortar, bouncestop); - PROJECTILE_MAKETRIGGER(gren); - gren.projectiledeathtype = WEP_MORTAR | HITTYPE_SECONDARY; - setorigin(gren, w_shotorg); - setsize(gren, '-3 -3 -3', '3 3 3'); - - gren.nextthink = time + WEP_CVAR_SEC(mortar, lifetime); - gren.think = adaptor_think2use_hittype_splash; - gren.use = W_Mortar_Grenade_Explode2; - gren.touch = W_Mortar_Grenade_Touch2; - - gren.takedamage = DAMAGE_YES; - gren.health = WEP_CVAR_SEC(mortar, health); - gren.damageforcescale = WEP_CVAR_SEC(mortar, damageforcescale); - gren.event_damage = W_Mortar_Grenade_Damage; - gren.damagedbycontents = TRUE; - gren.missile_flags = MIF_SPLASH | MIF_ARC; - W_SetupProjVelocity_UP_SEC(gren, mortar); - - gren.angles = vectoangles(gren.velocity); - gren.flags = FL_PROJECTILE; - - if(WEP_CVAR_SEC(mortar, type) == 0 || WEP_CVAR_SEC(mortar, type) == 2) - CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE, TRUE); - else - CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE_BOUNCING, TRUE); - - other = gren; MUTATOR_CALLHOOK(EditProjectile); -} - -.float bot_secondary_grenademooth; -float W_Mortar(float req) -{ - entity nade; - float nadefound; - float ammo_amount; - switch(req) - { - case WR_AIM: - { - self.BUTTON_ATCK = FALSE; - self.BUTTON_ATCK2 = FALSE; - if(self.bot_secondary_grenademooth == 0) // WEAPONTODO: merge this into using WEP_CVAR_BOTH - { - if(bot_aim(WEP_CVAR_PRI(mortar, speed), WEP_CVAR_PRI(mortar, speed_up), WEP_CVAR_PRI(mortar, lifetime), TRUE)) - { - self.BUTTON_ATCK = TRUE; - if(random() < 0.01) self.bot_secondary_grenademooth = 1; - } - } - else - { - if(bot_aim(WEP_CVAR_SEC(mortar, speed), WEP_CVAR_SEC(mortar, speed_up), WEP_CVAR_SEC(mortar, lifetime), TRUE)) - { - self.BUTTON_ATCK2 = TRUE; - if(random() < 0.02) self.bot_secondary_grenademooth = 0; - } - } - - return TRUE; - } - /*case WR_CALCINFO: - { - wepinfo_pri_refire = max3(sys_frametime, WEP_CVAR_PRI(mortar, refire), WEP_CVAR_PRI(mortar, animtime)); - wepinfo_pri_dps = (WEP_CVAR_PRI(mortar, damage) * (1 / wepinfo_pri_refire)); - wepinfo_pri_speed = (1 / max(1, (10000 / max(1, WEP_CVAR_PRI(mortar, speed))))); - - // for the range calculation, closer to 1 is better - wepinfo_pri_range_max = 2000 * wepinfo_pri_speed; - wepinfo_pri_range = wepinfo_pri_speed * WEP_CVAR_PRI(mortar, - - wepinfo_sec_refire = max3(sys_frametime, WEP_CVAR_SEC(mortar, refire), WEP_CVAR_SEC(mortar, animtime)); - wepinfo_sec_dps = (WEP_CVAR_SEC(mortar, damage) * (1 / wepinfo_sec_refire)); - - wepinfo_sec_dps = (WEP_CVAR_SEC(mortar, damage) * (1 / max3(sys_frametime, WEP_CVAR_SEC(mortar, refire), WEP_CVAR_SEC(mortar, animtime)))); - wepinfo_ter_dps = 0; - */ - case WR_THINK: - { - if(autocvar_g_balance_mortar_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo))) // forced reload - WEP_ACTION(self.weapon, WR_RELOAD); - else if(self.BUTTON_ATCK) - { - if(weapon_prepareattack(0, WEP_CVAR_PRI(mortar, refire))) - { - W_Mortar_Attack(); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(mortar, animtime), w_ready); - } - } - else if(self.BUTTON_ATCK2) - { - if(WEP_CVAR_SEC(mortar, remote_detonateprimary)) - { - nadefound = 0; - for(nade = world; (nade = find(nade, classname, "grenade")); ) if(nade.realowner == self) - { - if(!nade.gl_detonate_later) - { - nade.gl_detonate_later = TRUE; - nadefound = 1; - } - } - if(nadefound) - sound(self, CH_WEAPON_B, "weapons/rocket_det.wav", VOL_BASE, ATTN_NORM); - } - else if(weapon_prepareattack(1, WEP_CVAR_SEC(mortar, refire))) - { - W_Mortar_Attack2(); - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(mortar, animtime), w_ready); - } - } - - return TRUE; - } - case WR_INIT: - { - precache_model("models/weapons/g_gl.md3"); - precache_model("models/weapons/v_gl.md3"); - precache_model("models/weapons/h_gl.iqm"); - precache_sound("weapons/grenade_bounce1.wav"); - precache_sound("weapons/grenade_bounce2.wav"); - precache_sound("weapons/grenade_bounce3.wav"); - precache_sound("weapons/grenade_bounce4.wav"); - precache_sound("weapons/grenade_bounce5.wav"); - precache_sound("weapons/grenade_bounce6.wav"); - precache_sound("weapons/grenade_stick.wav"); - precache_sound("weapons/grenade_fire.wav"); - MORTAR_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP) - return TRUE; - } - case WR_CHECKAMMO1: - { - ammo_amount = self.WEP_AMMO(MORTAR) >= WEP_CVAR_PRI(mortar, ammo); - ammo_amount += self.(weapon_load[WEP_MORTAR]) >= WEP_CVAR_PRI(mortar, ammo); - return ammo_amount; - } - case WR_CHECKAMMO2: - { - ammo_amount = self.WEP_AMMO(MORTAR) >= WEP_CVAR_SEC(mortar, ammo); - ammo_amount += self.(weapon_load[WEP_MORTAR]) >= WEP_CVAR_SEC(mortar, ammo); - return ammo_amount; - } - case WR_CONFIG: - { - MORTAR_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS) - return TRUE; - } - case WR_RELOAD: - { - W_Reload(min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo)), "weapons/reload.wav"); // WEAPONTODO - return TRUE; - } - case WR_SUICIDEMESSAGE: - { - if(w_deathtype & HITTYPE_SECONDARY) - return WEAPON_MORTAR_SUICIDE_BOUNCE; - else - return WEAPON_MORTAR_SUICIDE_EXPLODE; - } - case WR_KILLMESSAGE: - { - if(w_deathtype & HITTYPE_SECONDARY) - return WEAPON_MORTAR_MURDER_BOUNCE; - else - return WEAPON_MORTAR_MURDER_EXPLODE; - } - } - return FALSE; -} -#endif -#ifdef CSQC -float W_Mortar(float req) -{ - switch(req) - { - case WR_IMPACTEFFECT: - { - vector org2; - org2 = w_org + w_backoff * 12; - pointparticles(particleeffectnum("grenade_explode"), org2, '0 0 0', 1); - if(!w_issilent) - sound(self, CH_SHOTS, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM); - - return TRUE; - } - case WR_INIT: - { - precache_sound("weapons/grenade_impact.wav"); - return TRUE; - } - case WR_ZOOMRETICLE: - { - // no weapon specific image for this weapon - return FALSE; - } - } - return FALSE; -} -#endif -#endif diff --git a/qcsrc/common/weapons/w_porto.qc b/qcsrc/common/weapons/w_porto.qc deleted file mode 100644 index 49fb47e43..000000000 --- a/qcsrc/common/weapons/w_porto.qc +++ /dev/null @@ -1,422 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ PORTO, -/* function */ W_Porto, -/* ammotype */ ammo_none, -/* impulse */ 0, -/* flags */ WEP_TYPE_OTHER | WEP_FLAG_SUPERWEAPON, -/* rating */ 0, -/* color */ '0.5 0.5 0.5', -/* modelname */ "porto", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairporto 0.6", -/* wepimg */ "weaponporto", -/* refname */ "porto", -/* wepname */ _("Port-O-Launch") -); - -#define PORTO_SETTINGS(w_cvar,w_prop) PORTO_SETTINGS_LIST(w_cvar, w_prop, PORTO, porto) -#define PORTO_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, BOTH, animtime) \ - w_cvar(id, sn, BOTH, lifetime) \ - w_cvar(id, sn, BOTH, refire) \ - w_cvar(id, sn, BOTH, speed) \ - w_cvar(id, sn, NONE, secondary) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifdef SVQC -PORTO_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) -.entity porto_current; -.vector porto_v_angle; // holds "held" view angles -.float porto_v_angle_held; -.vector right_vector; -#endif -#else -#ifdef SVQC -void spawnfunc_weapon_porto(void) { weapon_defaultspawnfunc(WEP_PORTO); } - -void W_Porto_Success(void) -{ - if(self.realowner == world) - { - objerror("Cannot succeed successfully: no owner\n"); - return; - } - - self.realowner.porto_current = world; - remove(self); -} - -string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo); -void W_Porto_Fail(float failhard) -{ - if(self.realowner == world) - { - objerror("Cannot fail successfully: no owner\n"); - return; - } - - // no portals here! - if(self.cnt < 0) - { - Portal_ClearWithID(self.realowner, self.portal_id); - } - - self.realowner.porto_current = world; - - if(self.cnt < 0 && !failhard && self.realowner.playerid == self.playerid && self.realowner.deadflag == DEAD_NO && !(self.realowner.weapons & WEPSET_PORTO)) - { - setsize(self, '-16 -16 0', '16 16 32'); - setorigin(self, self.origin + trace_plane_normal); - if(move_out_of_solid(self)) - { - self.flags = FL_ITEM; - self.velocity = trigger_push_calculatevelocity(self.origin, self.realowner, 128); - tracetoss(self, self); - if(vlen(trace_endpos - self.realowner.origin) < 128) - { - W_ThrowNewWeapon(self.realowner, WEP_PORTO, 0, self.origin, self.velocity); - centerprint(self.realowner, "^1Portal deployment failed.\n\n^2Catch it to try again!"); - } - } - } - remove(self); -} - -void W_Porto_Remove(entity p) -{ - if(p.porto_current.realowner == p && p.porto_current.classname == "porto") - { - entity oldself; - oldself = self; - self = p.porto_current; - W_Porto_Fail(1); - self = oldself; - } -} - -void W_Porto_Think(void) -{ - trace_plane_normal = '0 0 0'; - if(self.realowner.playerid != self.playerid) - remove(self); - else - W_Porto_Fail(0); -} - -void W_Porto_Touch(void) -{ - vector norm; - - // do not use PROJECTILE_TOUCH here - // FIXME but DO handle warpzones! - - if(other.classname == "portal") - return; // handled by the portal - - norm = trace_plane_normal; - if(trace_ent.iscreature) - { - traceline(trace_ent.origin, trace_ent.origin + '0 0 2' * PL_MIN_z, MOVE_WORLDONLY, self); - if(trace_fraction >= 1) - return; - if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP) - return; - if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) - return; - } - - if(self.realowner.playerid != self.playerid) - { - sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM); - remove(self); - } - else if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP) - { - spamsound(self, CH_SHOTS, "porto/bounce.wav", VOL_BASE, ATTEN_NORM); - // just reflect - self.right_vector = self.right_vector - 2 * trace_plane_normal * (self.right_vector * trace_plane_normal); - self.angles = vectoangles(self.velocity - 2 * trace_plane_normal * (self.velocity * trace_plane_normal)); - } - else if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) - { - sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM); - W_Porto_Fail(0); - if(self.cnt < 0) - Portal_ClearAll_PortalsOnly(self.realowner); - } - else if(self.cnt == 0) - { - // in-portal only - if(Portal_SpawnInPortalAtTrace(self.realowner, self.right_vector, self.portal_id)) - { - sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM); - trace_plane_normal = norm; - centerprint(self.realowner, "^1In^7-portal created."); - W_Porto_Success(); - } - else - { - sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM); - trace_plane_normal = norm; - W_Porto_Fail(0); - } - } - else if(self.cnt == 1) - { - // out-portal only - if(Portal_SpawnOutPortalAtTrace(self.realowner, self.right_vector, self.portal_id)) - { - sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM); - trace_plane_normal = norm; - centerprint(self.realowner, "^4Out^7-portal created."); - W_Porto_Success(); - } - else - { - sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM); - trace_plane_normal = norm; - W_Porto_Fail(0); - } - } - else if(self.effects & EF_RED) - { - self.effects += EF_BLUE - EF_RED; - if(Portal_SpawnInPortalAtTrace(self.realowner, self.right_vector, self.portal_id)) - { - sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM); - trace_plane_normal = norm; - centerprint(self.realowner, "^1In^7-portal created."); - self.right_vector = self.right_vector - 2 * trace_plane_normal * (self.right_vector * norm); - self.angles = vectoangles(self.velocity - 2 * trace_plane_normal * (self.velocity * norm)); - CSQCProjectile(self, TRUE, PROJECTILE_PORTO_BLUE, TRUE); // change type - } - else - { - sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM); - trace_plane_normal = norm; - Portal_ClearAll_PortalsOnly(self.realowner); - W_Porto_Fail(0); - } - } - else - { - if(self.realowner.portal_in.portal_id == self.portal_id) - { - if(Portal_SpawnOutPortalAtTrace(self.realowner, self.right_vector, self.portal_id)) - { - sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM); - trace_plane_normal = norm; - centerprint(self.realowner, "^4Out^7-portal created."); - W_Porto_Success(); - } - else - { - sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM); - Portal_ClearAll_PortalsOnly(self.realowner); - W_Porto_Fail(0); - } - } - else - { - sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM); - Portal_ClearAll_PortalsOnly(self.realowner); - W_Porto_Fail(0); - } - } -} - -void W_Porto_Attack(float type) -{ - entity gren; - - W_SetupShot(self, FALSE, 4, "porto/fire.wav", CH_WEAPON_A, 0); - // always shoot from the eye - w_shotdir = v_forward; - w_shotorg = self.origin + self.view_ofs + ((w_shotorg - self.origin - self.view_ofs) * v_forward) * v_forward; - - //pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - gren = spawn(); - gren.cnt = type; - gren.owner = gren.realowner = self; - gren.playerid = self.playerid; - gren.classname = "porto"; - gren.bot_dodge = TRUE; - gren.bot_dodgerating = 200; - gren.movetype = MOVETYPE_BOUNCEMISSILE; - PROJECTILE_MAKETRIGGER(gren); - gren.effects = EF_RED; - gren.scale = 4; - setorigin(gren, w_shotorg); - setsize(gren, '0 0 0', '0 0 0'); - - gren.nextthink = time + WEP_CVAR_BOTH(porto, (type <= 0), lifetime); - gren.think = W_Porto_Think; - gren.touch = W_Porto_Touch; - - if(self.items & IT_STRENGTH) - W_SetupProjVelocity_Basic(gren, WEP_CVAR_BOTH(porto, (type <= 0), speed) * autocvar_g_balance_powerup_strength_force, 0); - else - W_SetupProjVelocity_Basic(gren, WEP_CVAR_BOTH(porto, (type <= 0), speed), 0); - - gren.angles = vectoangles(gren.velocity); - gren.flags = FL_PROJECTILE; - - gren.portal_id = time; - self.porto_current = gren; - gren.playerid = self.playerid; - fixedmakevectors(fixedvectoangles(gren.velocity)); - gren.right_vector = v_right; - - gren.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP; - - if(type > 0) - CSQCProjectile(gren, TRUE, PROJECTILE_PORTO_BLUE, TRUE); - else - CSQCProjectile(gren, TRUE, PROJECTILE_PORTO_RED, TRUE); - - other = gren; MUTATOR_CALLHOOK(EditProjectile); -} - -float w_nexball_weapon(float req); // WEAPONTODO -float W_Porto(float req) -{ - //vector v_angle_save; - - if(g_nexball) { return w_nexball_weapon(req); } - - switch(req) - { - case WR_AIM: - { - self.BUTTON_ATCK = FALSE; - self.BUTTON_ATCK2 = FALSE; - if(!WEP_CVAR(porto, secondary)) - if(bot_aim(WEP_CVAR_PRI(porto, speed), 0, WEP_CVAR_PRI(porto, lifetime), FALSE)) - self.BUTTON_ATCK = TRUE; - - return TRUE; - } - case WR_CONFIG: - { - PORTO_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS) - return TRUE; - } - case WR_THINK: - { - if(WEP_CVAR(porto, secondary)) - { - if(self.BUTTON_ATCK) - if(!self.porto_current) - if(!self.porto_forbidden) - if(weapon_prepareattack(0, WEP_CVAR_PRI(porto, refire))) - { - W_Porto_Attack(0); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(porto, animtime), w_ready); - } - - if(self.BUTTON_ATCK2) - if(!self.porto_current) - if(!self.porto_forbidden) - if(weapon_prepareattack(1, WEP_CVAR_SEC(porto, refire))) - { - W_Porto_Attack(1); - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(porto, animtime), w_ready); - } - } - else - { - if(self.porto_v_angle_held) - { - if(!self.BUTTON_ATCK2) - { - self.porto_v_angle_held = 0; - - ClientData_Touch(self); - } - } - else - { - if(self.BUTTON_ATCK2) - { - self.porto_v_angle = self.v_angle; - self.porto_v_angle_held = 1; - - ClientData_Touch(self); - } - } - if(self.porto_v_angle_held) - makevectors(self.porto_v_angle); // override the previously set angles - - if(self.BUTTON_ATCK) - if(!self.porto_current) - if(!self.porto_forbidden) - if(weapon_prepareattack(0, WEP_CVAR_PRI(porto, refire))) - { - W_Porto_Attack(-1); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(porto, animtime), w_ready); - } - } - - return TRUE; - } - case WR_INIT: - { - precache_model("models/weapons/g_porto.md3"); - precache_model("models/weapons/v_porto.md3"); - precache_model("models/weapons/h_porto.iqm"); - precache_model("models/portal.md3"); - precache_sound("porto/bounce.wav"); - precache_sound("porto/create.wav"); - precache_sound("porto/expire.wav"); - precache_sound("porto/explode.wav"); - precache_sound("porto/fire.wav"); - precache_sound("porto/unsupported.wav"); - PORTO_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP) - return TRUE; - } - case WR_SETUP: - { - self.ammo_field = ammo_none; - return TRUE; - } - case WR_RESETPLAYER: - { - self.porto_current = world; - return TRUE; - } - } - return FALSE; -} -#endif -#ifdef CSQC -float W_Porto(float req) -{ - switch(req) - { - case WR_IMPACTEFFECT: - { - print("Since when does Porto send DamageInfo?\n"); - return TRUE; - } - case WR_INIT: - { - // nothing to do - return TRUE; - } - case WR_ZOOMRETICLE: - { - // no weapon specific image for this weapon - return FALSE; - } - } - return FALSE; -} -#endif -#endif diff --git a/qcsrc/common/weapons/w_rifle.qc b/qcsrc/common/weapons/w_rifle.qc deleted file mode 100644 index 03c396ceb..000000000 --- a/qcsrc/common/weapons/w_rifle.qc +++ /dev/null @@ -1,316 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ RIFLE, -/* function */ W_Rifle, -/* ammotype */ ammo_nails, -/* impulse */ 7, -/* flags */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN, -/* rating */ BOT_PICKUP_RATING_MID, -/* color */ '0.5 1 0', -/* modelname */ "campingrifle", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairrifle 0.5", -/* wepimg */ "weaponrifle", -/* refname */ "rifle", -/* wepname */ _("Rifle") -); - -#define RIFLE_SETTINGS(w_cvar,w_prop) RIFLE_SETTINGS_LIST(w_cvar, w_prop, RIFLE, rifle) -#define RIFLE_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, BOTH, ammo) \ - w_cvar(id, sn, BOTH, animtime) \ - w_cvar(id, sn, BOTH, bullethail) \ - w_cvar(id, sn, BOTH, burstcost) \ - w_cvar(id, sn, BOTH, damage) \ - w_cvar(id, sn, BOTH, force) \ - w_cvar(id, sn, BOTH, refire) \ - w_cvar(id, sn, BOTH, shots) \ - w_cvar(id, sn, BOTH, solidpenetration) \ - w_cvar(id, sn, BOTH, spread) \ - w_cvar(id, sn, BOTH, tracer) \ - w_cvar(id, sn, NONE, bursttime) \ - w_cvar(id, sn, NONE, secondary) \ - w_cvar(id, sn, SEC, reload) \ - w_prop(id, sn, float, reloading_ammo, reload_ammo) \ - w_prop(id, sn, float, reloading_time, reload_time) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifdef SVQC -RIFLE_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) -.float rifle_accumulator; -#endif -#else -#ifdef SVQC -void spawnfunc_weapon_rifle(void) { weapon_defaultspawnfunc(WEP_RIFLE); } -void spawnfunc_weapon_campingrifle(void) { spawnfunc_weapon_rifle(); } -void spawnfunc_weapon_sniperrifle(void) { spawnfunc_weapon_rifle(); } - -void W_Rifle_FireBullet(float pSpread, float pDamage, float pForce, float pSolidPenetration, float pAmmo, float deathtype, float pTracer, float pShots, string pSound) -{ - float i; - - W_DecreaseAmmo(pAmmo); - - W_SetupShot(self, TRUE, 2, pSound, CH_WEAPON_A, pDamage * pShots); - - pointparticles(particleeffectnum("rifle_muzzleflash"), w_shotorg, w_shotdir * 2000, 1); - - if(self.BUTTON_ZOOM | self.BUTTON_ZOOMSCRIPT) // if zoomed, shoot from the eye - { - w_shotdir = v_forward; - w_shotorg = self.origin + self.view_ofs + ((w_shotorg - self.origin - self.view_ofs) * v_forward) * v_forward; - } - - for(i = 0; i < pShots; ++i) - fireBullet(w_shotorg, w_shotdir, pSpread, pSolidPenetration, pDamage, pForce, deathtype, (pTracer ? EF_RED : EF_BLUE)); - - if(autocvar_g_casings >= 2) - SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self); -} - -void W_Rifle_Attack(void) -{ - W_Rifle_FireBullet(WEP_CVAR_PRI(rifle, spread), WEP_CVAR_PRI(rifle, damage), WEP_CVAR_PRI(rifle, force), WEP_CVAR_PRI(rifle, solidpenetration), WEP_CVAR_PRI(rifle, ammo), WEP_RIFLE, WEP_CVAR_PRI(rifle, tracer), WEP_CVAR_PRI(rifle, shots), "weapons/campingrifle_fire.wav"); -} - -void W_Rifle_Attack2(void) -{ - W_Rifle_FireBullet(WEP_CVAR_SEC(rifle, spread), WEP_CVAR_SEC(rifle, damage), WEP_CVAR_SEC(rifle, force), WEP_CVAR_SEC(rifle, solidpenetration), WEP_CVAR_SEC(rifle, ammo), WEP_RIFLE | HITTYPE_SECONDARY, WEP_CVAR_SEC(rifle, tracer), WEP_CVAR_SEC(rifle, shots), "weapons/campingrifle_fire2.wav"); -} - -.void(void) rifle_bullethail_attackfunc; -.float rifle_bullethail_frame; -.float rifle_bullethail_animtime; -.float rifle_bullethail_refire; -void W_Rifle_BulletHail_Continue(void) -{ - float r, sw, af; - - sw = self.switchweapon; // make it not detect weapon changes as reason to abort firing - af = ATTACK_FINISHED(self); - self.switchweapon = self.weapon; - ATTACK_FINISHED(self) = time; - print(ftos(self.WEP_AMMO(RIFLE)), "\n"); - r = weapon_prepareattack(self.rifle_bullethail_frame == WFRAME_FIRE2, self.rifle_bullethail_refire); - if(self.switchweapon == self.weapon) - self.switchweapon = sw; - if(r) - { - self.rifle_bullethail_attackfunc(); - weapon_thinkf(self.rifle_bullethail_frame, self.rifle_bullethail_animtime, W_Rifle_BulletHail_Continue); - print("thinkf set\n"); - } - else - { - ATTACK_FINISHED(self) = af; // reset attack_finished if we didn't fire, so the last shot enforces the refire time - print("out of ammo... ", ftos(self.weaponentity.state), "\n"); - } -} - -void W_Rifle_BulletHail(float mode, void(void) AttackFunc, float fr, float animtime, float refire) -{ - // if we get here, we have at least one bullet to fire - AttackFunc(); - if(mode) - { - // continue hail - self.rifle_bullethail_attackfunc = AttackFunc; - self.rifle_bullethail_frame = fr; - self.rifle_bullethail_animtime = animtime; - self.rifle_bullethail_refire = refire; - weapon_thinkf(fr, animtime, W_Rifle_BulletHail_Continue); - } - else - { - // just one shot - weapon_thinkf(fr, animtime, w_ready); - } -} - -.float bot_secondary_riflemooth; -float W_Rifle(float req) -{ - float ammo_amount; - - switch(req) - { - case WR_AIM: - { - self.BUTTON_ATCK=FALSE; - self.BUTTON_ATCK2=FALSE; - if(vlen(self.origin-self.enemy.origin) > 1000) - self.bot_secondary_riflemooth = 0; - if(self.bot_secondary_riflemooth == 0) - { - if(bot_aim(1000000, 0, 0.001, FALSE)) - { - self.BUTTON_ATCK = TRUE; - if(random() < 0.01) self.bot_secondary_riflemooth = 1; - } - } - else - { - if(bot_aim(1000000, 0, 0.001, FALSE)) - { - self.BUTTON_ATCK2 = TRUE; - if(random() < 0.03) self.bot_secondary_riflemooth = 0; - } - } - - return TRUE; - } - case WR_THINK: - { - if(autocvar_g_balance_rifle_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(rifle, ammo), WEP_CVAR_SEC(rifle, ammo))) // forced reload - WEP_ACTION(self.weapon, WR_RELOAD); - else - { - self.rifle_accumulator = bound(time - WEP_CVAR(rifle, bursttime), self.rifle_accumulator, time); - if(self.BUTTON_ATCK) - if(weapon_prepareattack_check(0, WEP_CVAR_PRI(rifle, refire))) - if(time >= self.rifle_accumulator + WEP_CVAR_PRI(rifle, burstcost)) - { - weapon_prepareattack_do(0, WEP_CVAR_PRI(rifle, refire)); - W_Rifle_BulletHail(WEP_CVAR_PRI(rifle, bullethail), W_Rifle_Attack, WFRAME_FIRE1, WEP_CVAR_PRI(rifle, animtime), WEP_CVAR_PRI(rifle, refire)); - self.rifle_accumulator += WEP_CVAR_PRI(rifle, burstcost); - } - if(self.BUTTON_ATCK2) - { - if(WEP_CVAR(rifle, secondary)) - { - if(WEP_CVAR_SEC(rifle, reload)) - WEP_ACTION(self.weapon, WR_RELOAD); - else - { - if(weapon_prepareattack_check(1, WEP_CVAR_SEC(rifle, refire))) - if(time >= self.rifle_accumulator + WEP_CVAR_SEC(rifle, burstcost)) - { - weapon_prepareattack_do(1, WEP_CVAR_SEC(rifle, refire)); - W_Rifle_BulletHail(WEP_CVAR_SEC(rifle, bullethail), W_Rifle_Attack2, WFRAME_FIRE2, WEP_CVAR_SEC(rifle, animtime), WEP_CVAR_PRI(rifle, refire)); - self.rifle_accumulator += WEP_CVAR_SEC(rifle, burstcost); - } - } - } - } - } - - return TRUE; - } - case WR_INIT: - { - precache_model("models/weapons/g_campingrifle.md3"); - precache_model("models/weapons/v_campingrifle.md3"); - precache_model("models/weapons/h_campingrifle.iqm"); - precache_sound("weapons/campingrifle_fire.wav"); - precache_sound("weapons/campingrifle_fire2.wav"); - RIFLE_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP) - return TRUE; - } - case WR_CHECKAMMO1: - { - ammo_amount = self.WEP_AMMO(RIFLE) >= WEP_CVAR_PRI(rifle, ammo); - ammo_amount += self.(weapon_load[WEP_RIFLE]) >= WEP_CVAR_PRI(rifle, ammo); - return ammo_amount; - } - case WR_CHECKAMMO2: - { - ammo_amount = self.WEP_AMMO(RIFLE) >= WEP_CVAR_SEC(rifle, ammo); - ammo_amount += self.(weapon_load[WEP_RIFLE]) >= WEP_CVAR_SEC(rifle, ammo); - return ammo_amount; - } - case WR_CONFIG: - { - RIFLE_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS) - return TRUE; - } - case WR_RESETPLAYER: - { - self.rifle_accumulator = time - WEP_CVAR(rifle, bursttime); - return TRUE; - } - case WR_RELOAD: - { - W_Reload(min(WEP_CVAR_PRI(rifle, ammo), WEP_CVAR_SEC(rifle, ammo)), "weapons/reload.wav"); - return TRUE; - } - case WR_SUICIDEMESSAGE: - { - return WEAPON_THINKING_WITH_PORTALS; - } - case WR_KILLMESSAGE: - { - if(w_deathtype & HITTYPE_SECONDARY) - { - if(w_deathtype & HITTYPE_BOUNCE) - return WEAPON_RIFLE_MURDER_HAIL_PIERCING; - else - return WEAPON_RIFLE_MURDER_HAIL; - } - else - { - if(w_deathtype & HITTYPE_BOUNCE) - return WEAPON_RIFLE_MURDER_PIERCING; - else - return WEAPON_RIFLE_MURDER; - } - } - } - return FALSE; -} -#endif -#ifdef CSQC -float W_Rifle(float req) -{ - switch(req) - { - case WR_IMPACTEFFECT: - { - vector org2; - org2 = w_org + w_backoff * 2; - pointparticles(particleeffectnum("machinegun_impact"), org2, w_backoff * 1000, 1); - if(!w_issilent) - { - if(w_random < 0.2) - sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTN_NORM); - else if(w_random < 0.4) - sound(self, CH_SHOTS, "weapons/ric2.wav", VOL_BASE, ATTN_NORM); - else if(w_random < 0.5) - sound(self, CH_SHOTS, "weapons/ric3.wav", VOL_BASE, ATTN_NORM); - } - - return TRUE; - } - case WR_INIT: - { - precache_sound("weapons/ric1.wav"); - precache_sound("weapons/ric2.wav"); - precache_sound("weapons/ric3.wav"); - if(autocvar_cl_reticle && autocvar_cl_reticle_weapon) - { - precache_pic("gfx/reticle_nex"); - } - return TRUE; - } - case WR_ZOOMRETICLE: - { - if(button_zoom || zoomscript_caught) - { - reticle_image = "gfx/reticle_nex"; - return TRUE; - } - else - { - // no weapon specific image for this weapon - return FALSE; - } - } - } - return FALSE; -} -#endif -#endif diff --git a/qcsrc/common/weapons/w_seeker.qc b/qcsrc/common/weapons/w_seeker.qc deleted file mode 100644 index 7d933d5ca..000000000 --- a/qcsrc/common/weapons/w_seeker.qc +++ /dev/null @@ -1,792 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ SEEKER, -/* function */ W_Seeker, -/* ammotype */ ammo_rockets, -/* impulse */ 8, -/* flags */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH, -/* rating */ BOT_PICKUP_RATING_MID, -/* color */ '0.5 1 0', -/* modelname */ "seeker", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairseeker 0.8", -/* wepimg */ "weaponseeker", -/* refname */ "seeker", -/* wepname */ _("T.A.G. Seeker") -); - -#define SEEKER_SETTINGS(w_cvar,w_prop) SEEKER_SETTINGS_LIST(w_cvar, w_prop, SEEKER, seeker) -#define SEEKER_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, NONE, type) \ - w_cvar(id, sn, NONE, flac_ammo) \ - w_cvar(id, sn, NONE, flac_animtime) \ - w_cvar(id, sn, NONE, flac_damage) \ - w_cvar(id, sn, NONE, flac_edgedamage) \ - w_cvar(id, sn, NONE, flac_force) \ - w_cvar(id, sn, NONE, flac_lifetime) \ - w_cvar(id, sn, NONE, flac_lifetime_rand) \ - w_cvar(id, sn, NONE, flac_radius) \ - w_cvar(id, sn, NONE, flac_refire) \ - w_cvar(id, sn, NONE, flac_speed) \ - w_cvar(id, sn, NONE, flac_speed_up) \ - w_cvar(id, sn, NONE, flac_speed_z) \ - w_cvar(id, sn, NONE, flac_spread) \ - w_cvar(id, sn, NONE, missile_accel) \ - w_cvar(id, sn, NONE, missile_ammo) \ - w_cvar(id, sn, NONE, missile_animtime) \ - w_cvar(id, sn, NONE, missile_count) \ - w_cvar(id, sn, NONE, missile_damage) \ - w_cvar(id, sn, NONE, missile_damageforcescale) \ - w_cvar(id, sn, NONE, missile_decel) \ - w_cvar(id, sn, NONE, missile_delay) \ - w_cvar(id, sn, NONE, missile_edgedamage) \ - w_cvar(id, sn, NONE, missile_force) \ - w_cvar(id, sn, NONE, missile_health) \ - w_cvar(id, sn, NONE, missile_lifetime) \ - w_cvar(id, sn, NONE, missile_proxy) \ - w_cvar(id, sn, NONE, missile_proxy_delay) \ - w_cvar(id, sn, NONE, missile_proxy_maxrange) \ - w_cvar(id, sn, NONE, missile_radius) \ - w_cvar(id, sn, NONE, missile_refire) \ - w_cvar(id, sn, NONE, missile_smart) \ - w_cvar(id, sn, NONE, missile_smart_mindist) \ - w_cvar(id, sn, NONE, missile_smart_trace_max) \ - w_cvar(id, sn, NONE, missile_smart_trace_min) \ - w_cvar(id, sn, NONE, missile_speed) \ - w_cvar(id, sn, NONE, missile_speed_max) \ - w_cvar(id, sn, NONE, missile_speed_up) \ - w_cvar(id, sn, NONE, missile_speed_z) \ - w_cvar(id, sn, NONE, missile_spread) \ - w_cvar(id, sn, NONE, missile_turnrate) \ - w_cvar(id, sn, NONE, tag_ammo) \ - w_cvar(id, sn, NONE, tag_animtime) \ - w_cvar(id, sn, NONE, tag_damageforcescale) \ - w_cvar(id, sn, NONE, tag_health) \ - w_cvar(id, sn, NONE, tag_lifetime) \ - w_cvar(id, sn, NONE, tag_refire) \ - w_cvar(id, sn, NONE, tag_speed) \ - w_cvar(id, sn, NONE, tag_spread) \ - w_cvar(id, sn, NONE, tag_tracker_lifetime) \ - w_prop(id, sn, float, reloading_ammo, reload_ammo) \ - w_prop(id, sn, float, reloading_time, reload_time) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifdef SVQC -SEEKER_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) -.entity tag_target, wps_tag_tracker; -.float tag_time; -#endif -#else -#ifdef SVQC -void spawnfunc_weapon_seeker(void) { weapon_defaultspawnfunc(WEP_SEEKER); } - -// ============================ -// Begin: Missile functions, these are general functions to be manipulated by other code -// ============================ -void W_Seeker_Missile_Explode(void) -{ - self.event_damage = func_null; - RadiusDamage(self, self.realowner, WEP_CVAR(seeker, missile_damage), WEP_CVAR(seeker, missile_edgedamage), WEP_CVAR(seeker, missile_radius), world, world, WEP_CVAR(seeker, missile_force), self.projectiledeathtype, other); - - remove(self); -} - -void W_Seeker_Missile_Touch(void) -{ - PROJECTILE_TOUCH; - - W_Seeker_Missile_Explode(); -} - -void W_Seeker_Missile_Think(void) -{ - entity e; - vector desireddir, olddir, newdir, eorg; - float turnrate; - float dist; - float spd; - - if(time > self.cnt) - { - self.projectiledeathtype |= HITTYPE_SPLASH; - W_Seeker_Missile_Explode(); - } - - spd = vlen(self.velocity); - spd = bound( - spd - WEP_CVAR(seeker, missile_decel) * frametime, - WEP_CVAR(seeker, missile_speed_max), - spd + WEP_CVAR(seeker, missile_accel) * frametime - ); - - if(self.enemy != world) - if(self.enemy.takedamage != DAMAGE_AIM || self.enemy.deadflag != DEAD_NO) - self.enemy = world; - - if(self.enemy != world) - { - e = self.enemy; - eorg = 0.5 * (e.absmin + e.absmax); - turnrate = WEP_CVAR(seeker, missile_turnrate); // how fast to turn - desireddir = normalize(eorg - self.origin); - olddir = normalize(self.velocity); // get my current direction - dist = vlen(eorg - self.origin); - - // Do evasive maneuvers for world objects? ( this should be a cpu hog. :P ) - if(WEP_CVAR(seeker, missile_smart) && (dist > WEP_CVAR(seeker, missile_smart_mindist))) - { - // Is it a better idea (shorter distance) to trace to the target itself? - if( vlen(self.origin + olddir * self.wait) < dist) - traceline(self.origin, self.origin + olddir * self.wait, FALSE, self); - else - traceline(self.origin, eorg, FALSE, self); - - // Setup adaptive tracelength - self.wait = bound(WEP_CVAR(seeker, missile_smart_trace_min), vlen(self.origin - trace_endpos), self.wait = WEP_CVAR(seeker, missile_smart_trace_max)); - - // Calc how important it is that we turn and add this to the desierd (enemy) dir. - desireddir = normalize(((trace_plane_normal * (1 - trace_fraction)) + (desireddir * trace_fraction)) * 0.5); - } - - newdir = normalize(olddir + desireddir * turnrate); // take the average of the 2 directions; not the best method but simple & easy - self.velocity = newdir * spd; // make me fly in the new direction at my flight speed - } - else - dist = 0; - - // Proxy - if(WEP_CVAR(seeker, missile_proxy)) - { - if(dist <= WEP_CVAR(seeker, missile_proxy_maxrange)) - { - if(self.autoswitch == 0) - { - self.autoswitch = time + WEP_CVAR(seeker, missile_proxy_delay); - } - else - { - if(self.autoswitch <= time) - { - W_Seeker_Missile_Explode(); - self.autoswitch = 0; - } - } - } - else - { - if(self.autoswitch != 0) - self.autoswitch = 0; - } - } - /////////////// - - if(self.enemy.deadflag != DEAD_NO) - { - self.enemy = world; - self.cnt = time + 1 + (random() * 4); - self.nextthink = self.cnt; - return; - } - - //self.angles = vectoangles(self.velocity); // turn model in the new flight direction - self.nextthink = time;// + 0.05; // csqc projectiles - UpdateCSQCProjectile(self); -} - - - -void W_Seeker_Missile_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) -{ - if(self.health <= 0) - return; - - if(!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions - return; // g_projectiles_damage says to halt - - if(self.realowner == attacker) - self.health = self.health - (damage * 0.25); - else - self.health = self.health - damage; - - if(self.health <= 0) - W_PrepareExplosionByDamage(attacker, W_Seeker_Missile_Explode); -} - -/* -void W_Seeker_Missile_Animate(void) -{ - self.frame = self.frame +1; - self.nextthink = time + 0.05; - - if(self.enemy != world) - if(self.enemy.takedamage != DAMAGE_AIM || self.enemy.deadflag != DEAD_NO) - self.enemy = world; - - if(self.frame == 5) - { - self.think = W_Seeker_Missile_Think; - self.nextthink = time;// + cvar("g_balance_seeker_missile_activate_delay"); // cant dealy with csqc projectiles - - if(autocvar_g_balance_seeker_missile_proxy) - self.movetype = MOVETYPE_BOUNCEMISSILE; - else - self.movetype = MOVETYPE_FLYMISSILE; - } - - UpdateCSQCProjectile(self); -} -*/ - -void W_Seeker_Fire_Missile(vector f_diff, entity m_target) -{ - entity missile; - - W_DecreaseAmmo(WEP_CVAR(seeker, missile_ammo)); - - makevectors(self.v_angle); - W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/seeker_fire.wav", CH_WEAPON_A, 0); - w_shotorg += f_diff; - pointparticles(particleeffectnum("seeker_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - //self.detornator = FALSE; - - missile = spawn(); - missile.owner = missile.realowner = self; - missile.classname = "seeker_missile"; - missile.bot_dodge = TRUE; - missile.bot_dodgerating = WEP_CVAR(seeker, missile_damage); - - missile.think = W_Seeker_Missile_Think; - missile.touch = W_Seeker_Missile_Touch; - missile.event_damage = W_Seeker_Missile_Damage; - missile.nextthink = time;// + 0.2;// + cvar("g_balance_seeker_missile_activate_delay"); - missile.cnt = time + WEP_CVAR(seeker, missile_lifetime); - missile.enemy = m_target; - missile.solid = SOLID_BBOX; - missile.scale = 2; - missile.takedamage = DAMAGE_YES; - missile.health = WEP_CVAR(seeker, missile_health); - missile.damageforcescale = WEP_CVAR(seeker, missile_damageforcescale); - missile.damagedbycontents = TRUE; - //missile.think = W_Seeker_Missile_Animate; // csqc projectiles. - - if(missile.enemy != world) - missile.projectiledeathtype = WEP_SEEKER | HITTYPE_SECONDARY; - else - missile.projectiledeathtype = WEP_SEEKER; - - - setorigin(missile, w_shotorg); - setsize(missile, '-4 -4 -4', '4 4 4'); - missile.movetype = MOVETYPE_FLYMISSILE; - missile.flags = FL_PROJECTILE; - missile.missile_flags = MIF_SPLASH | MIF_GUIDED_TAG; - - W_SetupProjVelocity_UP_PRE(missile, seeker, missile_); - - missile.angles = vectoangles(missile.velocity); - - CSQCProjectile(missile, FALSE, PROJECTILE_SEEKER, TRUE); - - other = missile; MUTATOR_CALLHOOK(EditProjectile); -} - -// ============================ -// Begin: FLAC, close range attack meant for defeating rockets which are coming at you. -// ============================ -void W_Seeker_Flac_Explode(void) -{ - self.event_damage = func_null; - - RadiusDamage(self, self.realowner, WEP_CVAR(seeker, flac_damage), WEP_CVAR(seeker, flac_edgedamage), WEP_CVAR(seeker, flac_radius), world, world, WEP_CVAR(seeker, flac_force), self.projectiledeathtype, other); - - remove(self); -} - -void W_Seeker_Flac_Touch(void) -{ - PROJECTILE_TOUCH; - - W_Seeker_Flac_Explode(); -} - -void W_Seeker_Fire_Flac(void) -{ - entity missile; - vector f_diff; - float c; - - W_DecreaseAmmo(WEP_CVAR(seeker, flac_ammo)); - - c = mod(self.bulletcounter, 4); - switch(c) - { - case 0: - f_diff = '-1.25 -3.75 0'; - break; - case 1: - f_diff = '+1.25 -3.75 0'; - break; - case 2: - f_diff = '-1.25 +3.75 0'; - break; - case 3: - default: - f_diff = '+1.25 +3.75 0'; - break; - } - W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/flac_fire.wav", CH_WEAPON_A, WEP_CVAR(seeker, flac_damage)); - w_shotorg += f_diff; - - pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - missile = spawn(); - missile.owner = missile.realowner = self; - missile.classname = "missile"; - missile.bot_dodge = TRUE; - missile.bot_dodgerating = WEP_CVAR(seeker, flac_damage); - missile.touch = W_Seeker_Flac_Explode; - missile.use = W_Seeker_Flac_Explode; - missile.think = adaptor_think2use_hittype_splash; - missile.nextthink = time + WEP_CVAR(seeker, flac_lifetime) + WEP_CVAR(seeker, flac_lifetime_rand); - missile.solid = SOLID_BBOX; - missile.movetype = MOVETYPE_FLY; - missile.projectiledeathtype = WEP_SEEKER; - missile.projectiledeathtype = WEP_SEEKER | HITTYPE_SECONDARY; - missile.flags = FL_PROJECTILE; - missile.missile_flags = MIF_SPLASH; - - // csqc projectiles - //missile.angles = vectoangles(missile.velocity); - //missile.scale = 0.4; // BUG: the model is too big - - setorigin(missile, w_shotorg); - setsize(missile, '-2 -2 -2', '2 2 2'); - - W_SetupProjVelocity_UP_PRE(missile, seeker, flac_); - CSQCProjectile(missile, TRUE, PROJECTILE_FLAC, TRUE); - - other = missile; MUTATOR_CALLHOOK(EditProjectile); -} - -// ============================ -// Begin: Tag and rocket controllers -// ============================ -entity W_Seeker_Tagged_Info(entity isowner, entity istarget) -{ - entity tag; - for(tag = world; (tag = find(tag, classname, "tag_tracker")); ) - if((tag.realowner == isowner) && (tag.tag_target == istarget)) - return tag; - - return world; -} - -void W_Seeker_Attack(void) -{ - entity tracker, closest_target; - - closest_target = world; - for(tracker = world; (tracker = find(tracker, classname, "tag_tracker")); ) if (tracker.realowner == self) - { - if(closest_target) - { - if(vlen(self.origin - tracker.tag_target.origin) < vlen(self.origin - closest_target.origin)) - closest_target = tracker.tag_target; - } - else - closest_target = tracker.tag_target; - } - - traceline(self.origin + self.view_ofs, closest_target.origin, MOVE_NOMONSTERS, self); - if((!closest_target) || ((trace_fraction < 1) && (trace_ent != closest_target))) - closest_target = world; - - W_Seeker_Fire_Missile('0 0 0', closest_target); -} - -void W_Seeker_Vollycontroller_Think(void) // TODO: Merge this with W_Seeker_Attack -{ - float c; - entity oldself,oldenemy; - self.cnt = self.cnt - 1; - - if((!(self.realowner.items & IT_UNLIMITED_AMMO) && self.realowner.WEP_AMMO(SEEKER) < WEP_CVAR(seeker, missile_ammo)) || (self.cnt <= -1) || (self.realowner.deadflag != DEAD_NO) || (self.realowner.switchweapon != WEP_SEEKER)) - { - remove(self); - return; - } - - self.nextthink = time + WEP_CVAR(seeker, missile_delay) * W_WeaponRateFactor(); - - oldself = self; - self = self.realowner; - - oldenemy = self.enemy; - self.enemy = oldself.enemy; - - c = mod(self.cnt, 4); - switch(c) - { - case 0: - W_Seeker_Fire_Missile('-1.25 -3.75 0', self.enemy); - break; - case 1: - W_Seeker_Fire_Missile('+1.25 -3.75 0', self.enemy); - break; - case 2: - W_Seeker_Fire_Missile('-1.25 +3.75 0', self.enemy); - break; - case 3: - default: - W_Seeker_Fire_Missile('+1.25 +3.75 0', self.enemy); - break; - } - - self.enemy = oldenemy; - self = oldself; -} - -void W_Seeker_Tracker_Think(void) -{ - // commit suicide if: You die OR target dies OR you switch away from the seeker OR commit suicide if lifetime is up - if((self.realowner.deadflag != DEAD_NO) || (self.tag_target.deadflag != DEAD_NO) || (self.realowner.switchweapon != WEP_SEEKER) - || (time > self.tag_time + WEP_CVAR(seeker, tag_tracker_lifetime))) - { - if(self) - { - WaypointSprite_Kill(self.tag_target.wps_tag_tracker); - remove(self); - } - return; - } - - // Update the think method information - self.nextthink = time; -} - -// ============================ -// Begin: Tag projectile -// ============================ -void W_Seeker_Tag_Explode(void) -{ - //if(other==self.realowner) - // return; - Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER | HITTYPE_BOUNCE, other.species, self); - - remove(self); -} - -void W_Seeker_Tag_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) -{ - if(self.health <= 0) - return; - self.health = self.health - damage; - if(self.health <= 0) - W_Seeker_Tag_Explode(); -} - -void W_Seeker_Tag_Touch(void) -{ - vector dir; - vector org2; - entity e; - - PROJECTILE_TOUCH; - - dir = normalize(self.realowner.origin - self.origin); - org2 = findbetterlocation(self.origin, 8); - - te_knightspike(org2); - - self.event_damage = func_null; - Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER | HITTYPE_BOUNCE | HITTYPE_SECONDARY, other.species, self); - - if(other.takedamage == DAMAGE_AIM && other.deadflag == DEAD_NO) - { - // check to see if this person is already tagged by me - entity tag = W_Seeker_Tagged_Info(self.realowner, other); - - if(tag != world) - { - if(other.wps_tag_tracker && (WEP_CVAR(seeker, type) == 1)) // don't attach another waypointsprite without killing the old one first - WaypointSprite_Kill(other.wps_tag_tracker); - - tag.tag_time = time; - } - else - { - //sprint(self.realowner, strcat("You just tagged ^2", other.netname, "^7 with a tracking device!\n")); - e = spawn(); - e.cnt = WEP_CVAR(seeker, missile_count); - e.classname = "tag_tracker"; - e.owner = self.owner; - e.realowner = self.realowner; - - if(WEP_CVAR(seeker, type) == 1) - { - e.tag_target = other; - e.tag_time = time; - e.think = W_Seeker_Tracker_Think; - } - else - { - e.enemy = other; - e.think = W_Seeker_Vollycontroller_Think; - } - - e.nextthink = time; - } - - if(WEP_CVAR(seeker, type) == 1) - { - WaypointSprite_Spawn("tagged-target", WEP_CVAR(seeker, tag_tracker_lifetime), 0, other, '0 0 64', self.realowner, 0, other, wps_tag_tracker, TRUE, RADARICON_TAGGED, '0.5 1 0'); - WaypointSprite_UpdateRule(other.wps_tag_tracker, 0, SPRITERULE_DEFAULT); - } - } - - remove(self); - return; -} - -void W_Seeker_Fire_Tag(void) -{ - entity missile; - W_DecreaseAmmo(WEP_CVAR(seeker, tag_ammo)); - - W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/tag_fire.wav", CH_WEAPON_A, WEP_CVAR(seeker, missile_damage) * WEP_CVAR(seeker, missile_count)); - - missile = spawn(); - missile.owner = missile.realowner = self; - missile.classname = "seeker_tag"; - missile.bot_dodge = TRUE; - missile.bot_dodgerating = 50; - missile.touch = W_Seeker_Tag_Touch; - missile.think = SUB_Remove; - missile.nextthink = time + WEP_CVAR(seeker, tag_lifetime); - missile.movetype = MOVETYPE_FLY; - missile.solid = SOLID_BBOX; - - missile.takedamage = DAMAGE_YES; - missile.event_damage = W_Seeker_Tag_Damage; - missile.health = WEP_CVAR(seeker, tag_health); - missile.damageforcescale = WEP_CVAR(seeker, tag_damageforcescale); - - setorigin(missile, w_shotorg); - setsize(missile, '-2 -2 -2', '2 2 2'); - - missile.flags = FL_PROJECTILE; - //missile.missile_flags = MIF_..?; - - missile.movetype = MOVETYPE_FLY; - W_SetupProjVelocity_PRE(missile, seeker, tag_); - missile.angles = vectoangles(missile.velocity); - - CSQCProjectile(missile, TRUE, PROJECTILE_TAG, FALSE); // has sound - - other = missile; MUTATOR_CALLHOOK(EditProjectile); -} - -// ============================ -// Begin: Genereal weapon functions -// ============================ - -float W_Seeker(float req) -{ - float ammo_amount; - - switch(req) - { - case WR_AIM: - { - if(WEP_CVAR(seeker, type) == 1) - if(W_Seeker_Tagged_Info(self, self.enemy) != world) - self.BUTTON_ATCK = bot_aim(WEP_CVAR(seeker, missile_speed_max), 0, WEP_CVAR(seeker, missile_lifetime), FALSE); - else - self.BUTTON_ATCK2 = bot_aim(WEP_CVAR(seeker, tag_speed), 0, WEP_CVAR(seeker, tag_lifetime), FALSE); - else - self.BUTTON_ATCK = bot_aim(WEP_CVAR(seeker, tag_speed), 0, WEP_CVAR(seeker, tag_lifetime), FALSE); - return TRUE; - } - case WR_THINK: - { - if(autocvar_g_balance_seeker_reload_ammo && self.clip_load < min(WEP_CVAR(seeker, missile_ammo), WEP_CVAR(seeker, tag_ammo))) // forced reload - WEP_ACTION(self.weapon, WR_RELOAD); - - else if(self.BUTTON_ATCK) - { - if(WEP_CVAR(seeker, type) == 1) - { - if(weapon_prepareattack(0, WEP_CVAR(seeker, missile_refire))) - { - W_Seeker_Attack(); - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(seeker, missile_animtime), w_ready); - } - } - else - { - if(weapon_prepareattack(0, WEP_CVAR(seeker, tag_refire))) - { - W_Seeker_Fire_Tag(); - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(seeker, tag_animtime), w_ready); - } - } - } - - else if(self.BUTTON_ATCK2) - { - if(WEP_CVAR(seeker, type) == 1) - { - if(weapon_prepareattack(0, WEP_CVAR(seeker, tag_refire))) - { - W_Seeker_Fire_Tag(); - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(seeker, tag_animtime), w_ready); - } - } - else - { - if(weapon_prepareattack(0, WEP_CVAR(seeker, flac_refire))) - { - W_Seeker_Fire_Flac(); - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(seeker, flac_animtime), w_ready); - } - } - } - - return TRUE; - } - case WR_INIT: - { - precache_model("models/weapons/g_seeker.md3"); - precache_model("models/weapons/v_seeker.md3"); - precache_model("models/weapons/h_seeker.iqm"); - precache_sound("weapons/tag_fire.wav"); - precache_sound("weapons/flac_fire.wav"); - precache_sound("weapons/seeker_fire.wav"); - SEEKER_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP) - return TRUE; - } - case WR_CHECKAMMO1: - { - if(WEP_CVAR(seeker, type) == 1) - { - ammo_amount = self.WEP_AMMO(SEEKER) >= WEP_CVAR(seeker, missile_ammo); - ammo_amount += self.(weapon_load[WEP_SEEKER]) >= WEP_CVAR(seeker, missile_ammo); - } - else - { - ammo_amount = self.WEP_AMMO(SEEKER) >= WEP_CVAR(seeker, tag_ammo); - ammo_amount += self.(weapon_load[WEP_SEEKER]) >= WEP_CVAR(seeker, tag_ammo); - } - return ammo_amount; - } - case WR_CHECKAMMO2: - { - if(WEP_CVAR(seeker, type) == 1) - { - ammo_amount = self.WEP_AMMO(SEEKER) >= WEP_CVAR(seeker, tag_ammo); - ammo_amount += self.(weapon_load[WEP_SEEKER]) >= WEP_CVAR(seeker, tag_ammo); - } - else - { - ammo_amount = self.WEP_AMMO(SEEKER) >= WEP_CVAR(seeker, flac_ammo); - ammo_amount += self.(weapon_load[WEP_SEEKER]) >= WEP_CVAR(seeker, flac_ammo); - } - return ammo_amount; - } - case WR_CONFIG: - { - SEEKER_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS) - return TRUE; - } - case WR_RELOAD: - { - W_Reload(min(WEP_CVAR(seeker, missile_ammo), WEP_CVAR(seeker, tag_ammo)), "weapons/reload.wav"); - return TRUE; - } - case WR_SUICIDEMESSAGE: - { - return WEAPON_SEEKER_SUICIDE; - } - case WR_KILLMESSAGE: - { - if(w_deathtype & HITTYPE_SECONDARY) - return WEAPON_SEEKER_MURDER_TAG; - else - return WEAPON_SEEKER_MURDER_SPRAY; - } - } - return FALSE; -} -#endif -#ifdef CSQC -float W_Seeker(float req) -{ - switch(req) - { - case WR_IMPACTEFFECT: - { - vector org2; - org2 = w_org + w_backoff * 6; - if(w_deathtype & HITTYPE_BOUNCE) - { - if(w_deathtype & HITTYPE_SECONDARY) - { - if(!w_issilent) - sound(self, CH_SHOTS, "weapons/tag_impact.wav", 1, ATTEN_NORM); - } - else - { - pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1); - if(!w_issilent) - { - if(w_random<0.15) - sound(self, CH_SHOTS, "weapons/tagexp1.wav", 1, ATTEN_NORM); - else if(w_random<0.7) - sound(self, CH_SHOTS, "weapons/tagexp2.wav", 1, ATTEN_NORM); - else - sound(self, CH_SHOTS, "weapons/tagexp3.wav", 1, ATTEN_NORM); - } - } - } - else - { - pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1); - if(!w_issilent) - { - if(w_random<0.15) - sound(self, CH_SHOTS, "weapons/seekerexp1.wav", 1, ATTEN_NORM); - else if(w_random<0.7) - sound(self, CH_SHOTS, "weapons/seekerexp2.wav", 1, ATTEN_NORM); - else - sound(self, CH_SHOTS, "weapons/seekerexp3.wav", 1, ATTEN_NORM); - } - } - return TRUE; - } - case WR_INIT: - { - precache_sound("weapons/seekerexp1.wav"); - precache_sound("weapons/seekerexp2.wav"); - precache_sound("weapons/seekerexp3.wav"); - precache_sound("weapons/tagexp1.wav"); - precache_sound("weapons/tagexp2.wav"); - precache_sound("weapons/tagexp3.wav"); - precache_sound("weapons/tag_impact.wav"); - return TRUE; - } - case WR_ZOOMRETICLE: - { - // no weapon specific image for this weapon - return FALSE; - } - } - return FALSE; -} -#endif -#endif diff --git a/qcsrc/common/weapons/w_shockwave.qc b/qcsrc/common/weapons/w_shockwave.qc deleted file mode 100644 index 759dc35ea..000000000 --- a/qcsrc/common/weapons/w_shockwave.qc +++ /dev/null @@ -1,897 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ SHOCKWAVE, -/* function */ W_Shockwave, -/* ammotype */ ammo_none, -/* impulse */ 2, -/* flags */ WEP_FLAG_NORMAL | WEP_TYPE_HITSCAN | WEP_FLAG_CANCLIMB | WEP_FLAG_MUTATORBLOCKED, -/* rating */ BOT_PICKUP_RATING_LOW, -/* color */ '0.5 0.25 0', -/* modelname */ "shotgun", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairshotgun 0.7", -/* wepimg */ "weaponshotgun", -/* refname */ "shockwave", -/* wepname */ _("Shockwave") -); - -#define SHOCKWAVE_SETTINGS(w_cvar,w_prop) SHOCKWAVE_SETTINGS_LIST(w_cvar, w_prop, SHOCKWAVE, shockwave) -#define SHOCKWAVE_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, NONE, blast_animtime) \ - w_cvar(id, sn, NONE, blast_damage) \ - w_cvar(id, sn, NONE, blast_distance) \ - w_cvar(id, sn, NONE, blast_edgedamage) \ - w_cvar(id, sn, NONE, blast_force) \ - w_cvar(id, sn, NONE, blast_force_forwardbias) \ - w_cvar(id, sn, NONE, blast_force_zscale) \ - w_cvar(id, sn, NONE, blast_jump_damage) \ - w_cvar(id, sn, NONE, blast_jump_edgedamage) \ - w_cvar(id, sn, NONE, blast_jump_force) \ - w_cvar(id, sn, NONE, blast_jump_force_velocitybias) \ - w_cvar(id, sn, NONE, blast_jump_force_zscale) \ - w_cvar(id, sn, NONE, blast_jump_multiplier_accuracy) \ - w_cvar(id, sn, NONE, blast_jump_multiplier_distance) \ - w_cvar(id, sn, NONE, blast_jump_multiplier_min) \ - w_cvar(id, sn, NONE, blast_jump_radius) \ - w_cvar(id, sn, NONE, blast_multiplier_accuracy) \ - w_cvar(id, sn, NONE, blast_multiplier_distance) \ - w_cvar(id, sn, NONE, blast_multiplier_min) \ - w_cvar(id, sn, NONE, blast_refire) \ - w_cvar(id, sn, NONE, blast_splash_damage) \ - w_cvar(id, sn, NONE, blast_splash_edgedamage) \ - w_cvar(id, sn, NONE, blast_splash_force) \ - w_cvar(id, sn, NONE, blast_splash_force_forwardbias) \ - w_cvar(id, sn, NONE, blast_splash_multiplier_accuracy) \ - w_cvar(id, sn, NONE, blast_splash_multiplier_distance) \ - w_cvar(id, sn, NONE, blast_splash_multiplier_min) \ - w_cvar(id, sn, NONE, blast_splash_radius) \ - w_cvar(id, sn, NONE, blast_spread_max) \ - w_cvar(id, sn, NONE, blast_spread_min) \ - w_cvar(id, sn, NONE, melee_animtime) \ - w_cvar(id, sn, NONE, melee_damage) \ - w_cvar(id, sn, NONE, melee_delay) \ - w_cvar(id, sn, NONE, melee_force) \ - w_cvar(id, sn, NONE, melee_multihit) \ - w_cvar(id, sn, NONE, melee_no_doubleslap) \ - w_cvar(id, sn, NONE, melee_nonplayerdamage) \ - w_cvar(id, sn, NONE, melee_range) \ - w_cvar(id, sn, NONE, melee_refire) \ - w_cvar(id, sn, NONE, melee_swing_side) \ - w_cvar(id, sn, NONE, melee_swing_up) \ - w_cvar(id, sn, NONE, melee_time) \ - w_cvar(id, sn, NONE, melee_traces) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifdef SVQC -SHOCKWAVE_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) -#endif -#ifdef CSQC -void Net_ReadShockwaveParticle(void); -.vector sw_shotorg; -.vector sw_shotdir; -.float sw_distance; -.float sw_spread_max; -.float sw_spread_min; -.float sw_time; -#endif -#else -#ifdef SVQC -void spawnfunc_weapon_shockwave(void) -{ - //if(autocvar_sv_q3acompat_machineshockwaveswap) // WEAPONTODO - if(autocvar_sv_q3acompat_machineshotgunswap) - if(self.classname != "droppedweapon") - { - weapon_defaultspawnfunc(WEP_MACHINEGUN); - return; - } - weapon_defaultspawnfunc(WEP_SHOCKWAVE); -} - -#define MAX_SHOCKWAVE_HITS 10 -//#define DEBUG_SHOCKWAVE - -.float swing_prev; -.entity swing_alreadyhit; -.float shockwave_blasttime; -entity shockwave_hit[MAX_SHOCKWAVE_HITS]; -float shockwave_hit_damage[MAX_SHOCKWAVE_HITS]; -vector shockwave_hit_force[MAX_SHOCKWAVE_HITS]; - -// MELEE ATTACK MODE -void W_Shockwave_Melee_Think(void) -{ - // declarations - float i, f, swing, swing_factor, swing_damage, meleetime, is_player; - entity target_victim; - vector targpos; - - // check to see if we can still continue, otherwise give up now - if((self.realowner.deadflag != DEAD_NO) && WEP_CVAR(shockwave, melee_no_doubleslap)) - { - remove(self); - return; - } - - // set start time of melee - if(!self.cnt) - { - self.cnt = time; - W_PlayStrengthSound(self.realowner); - } - - // update values for v_* vectors - makevectors(self.realowner.v_angle); - - // calculate swing percentage based on time - meleetime = WEP_CVAR(shockwave, melee_time) * W_WeaponRateFactor(); - swing = bound(0, (self.cnt + meleetime - time) / meleetime, 10); - f = ((1 - swing) * WEP_CVAR(shockwave, melee_traces)); - - // perform the traces needed for this frame - for(i=self.swing_prev; i < f; ++i) - { - swing_factor = ((1 - (i / WEP_CVAR(shockwave, melee_traces))) * 2 - 1); - - targpos = (self.realowner.origin + self.realowner.view_ofs - + (v_forward * WEP_CVAR(shockwave, melee_range)) - + (v_up * swing_factor * WEP_CVAR(shockwave, melee_swing_up)) - + (v_right * swing_factor * WEP_CVAR(shockwave, melee_swing_side))); - - WarpZone_traceline_antilag( - self.realowner, - (self.realowner.origin + self.realowner.view_ofs), - targpos, - FALSE, - self.realowner, - ANTILAG_LATENCY(self.realowner) - ); - - // draw lightning beams for debugging -#ifdef DEBUG_SHOCKWAVE - te_lightning2(world, targpos, self.realowner.origin + self.realowner.view_ofs + v_forward * 5 - v_up * 5); - te_customflash(targpos, 40, 2, '1 1 1'); -#endif - - is_player = (IS_PLAYER(trace_ent) || trace_ent.classname == "body" || (trace_ent.flags & FL_MONSTER)); - - if((trace_fraction < 1) // if trace is good, apply the damage and remove self if necessary - && (trace_ent.takedamage == DAMAGE_AIM) - && (trace_ent != self.swing_alreadyhit) - && (is_player || WEP_CVAR(shockwave, melee_nonplayerdamage))) - { - target_victim = trace_ent; // so it persists through other calls - - if(is_player) // this allows us to be able to nerf the non-player damage done in e.g. assault or onslaught - swing_damage = (WEP_CVAR(shockwave, melee_damage) * min(1, swing_factor + 1)); - else - swing_damage = (WEP_CVAR(shockwave, melee_nonplayerdamage) * min(1, swing_factor + 1)); - - // trigger damage with this calculated info - Damage( - target_victim, - self.realowner, - self.realowner, - swing_damage, - (WEP_SHOCKWAVE | HITTYPE_SECONDARY), - (self.realowner.origin + self.realowner.view_ofs), - (v_forward * WEP_CVAR(shockwave, melee_force)) - ); - - // handle accuracy - if(accuracy_isgooddamage(self.realowner, target_victim)) - { accuracy_add(self.realowner, WEP_SHOCKWAVE, 0, swing_damage); } - - #ifdef DEBUG_SHOCKWAVE - print(sprintf( - "MELEE: %s hitting %s with %f damage (factor: %f) at %f time.\n", - self.realowner.netname, - target_victim.netname, - swing_damage, - swing_factor, - time - )); - #endif - - // allow multiple hits with one swing, but not against the same player twice - if(WEP_CVAR(shockwave, melee_multihit)) - { - self.swing_alreadyhit = target_victim; - continue; // move along to next trace - } - else - { - remove(self); - return; - } - } - } - - if(time >= self.cnt + meleetime) - { - // melee is finished - remove(self); - return; - } - else - { - // set up next frame - self.swing_prev = i; - self.nextthink = time; - } -} - -void W_Shockwave_Melee(void) -{ - sound(self, CH_WEAPON_A, "weapons/shotgun_melee.wav", VOL_BASE, ATTN_NORM); - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(shockwave, melee_animtime), w_ready); - - entity meleetemp; - meleetemp = spawn(); - meleetemp.owner = meleetemp.realowner = self; - meleetemp.think = W_Shockwave_Melee_Think; - meleetemp.nextthink = time + WEP_CVAR(shockwave, melee_delay) * W_WeaponRateFactor(); - W_SetupShot_Range(self, TRUE, 0, "", 0, WEP_CVAR(shockwave, melee_damage), WEP_CVAR(shockwave, melee_range)); -} - -// SHOCKWAVE ATTACK MODE -float W_Shockwave_Attack_CheckSpread( - vector targetorg, - vector nearest_on_line, - vector sw_shotorg, - vector attack_endpos) -{ - float spreadlimit; - float distance_of_attack = vlen(sw_shotorg - attack_endpos); - float distance_from_line = vlen(targetorg - nearest_on_line); - - spreadlimit = (distance_of_attack ? min(1, (vlen(sw_shotorg - nearest_on_line) / distance_of_attack)) : 1); - spreadlimit = - ( - (WEP_CVAR(shockwave, blast_spread_min) * (1 - spreadlimit)) - + - (WEP_CVAR(shockwave, blast_spread_max) * spreadlimit) - ); - - if( - (spreadlimit && (distance_from_line <= spreadlimit)) - && - ((vlen(normalize(targetorg - sw_shotorg) - normalize(attack_endpos - sw_shotorg)) * RAD2DEG) <= 90) - ) - { return bound(0, (distance_from_line / spreadlimit), 1); } - else - { return FALSE; } -} - -float W_Shockwave_Attack_IsVisible( - entity head, - vector nearest_on_line, - vector sw_shotorg, - vector attack_endpos) -{ - vector nearest_to_attacker = head.WarpZone_findradius_nearest; - vector center = (head.origin + (head.mins + head.maxs) * 0.5); - vector corner; - float i; - - // STEP ONE: Check if the nearest point is clear - if(W_Shockwave_Attack_CheckSpread(nearest_to_attacker, nearest_on_line, sw_shotorg, attack_endpos)) - { - WarpZone_TraceLine(sw_shotorg, nearest_to_attacker, MOVE_NOMONSTERS, self); - if(trace_fraction == 1) { return TRUE; } // yes, the nearest point is clear and we can allow the damage - } - - // STEP TWO: Check if shotorg to center point is clear - if(W_Shockwave_Attack_CheckSpread(center, nearest_on_line, sw_shotorg, attack_endpos)) - { - WarpZone_TraceLine(sw_shotorg, center, MOVE_NOMONSTERS, self); - if(trace_fraction == 1) { return TRUE; } // yes, the center point is clear and we can allow the damage - } - - // STEP THREE: Check each corner to see if they are clear - for(i=1; i<=8; ++i) - { - corner = get_corner_position(head, i); - if(W_Shockwave_Attack_CheckSpread(corner, nearest_on_line, sw_shotorg, attack_endpos)) - { - WarpZone_TraceLine(sw_shotorg, corner, MOVE_NOMONSTERS, self); - if(trace_fraction == 1) { return TRUE; } // yes, this corner is clear and we can allow the damage - } - } - - return FALSE; -} - -float W_Shockwave_Attack_CheckHit( - float queue, - entity head, - vector final_force, - float final_damage) -{ - if(!head) { return FALSE; } - float i; - - for(i = 0; i <= queue; ++i) - { - if(shockwave_hit[i] == head) - { - if(vlen(final_force) > vlen(shockwave_hit_force[i])) { shockwave_hit_force[i] = final_force; } - if(final_damage > shockwave_hit_damage[i]) { shockwave_hit_damage[i] = final_damage; } - return FALSE; - } - } - - shockwave_hit[queue] = head; - shockwave_hit_force[queue] = final_force; - shockwave_hit_damage[queue] = final_damage; - return TRUE; -} - -void W_Shockwave_Send(void) -{ - WriteByte(MSG_BROADCAST, SVC_TEMPENTITY); - WriteByte(MSG_BROADCAST, TE_CSQC_SHOCKWAVEPARTICLE); - WriteCoord(MSG_BROADCAST, w_shotorg_x); - WriteCoord(MSG_BROADCAST, w_shotorg_y); - WriteCoord(MSG_BROADCAST, w_shotorg_z); - WriteCoord(MSG_BROADCAST, w_shotdir_x); - WriteCoord(MSG_BROADCAST, w_shotdir_y); - WriteCoord(MSG_BROADCAST, w_shotdir_z); - WriteShort(MSG_BROADCAST, WEP_CVAR(shockwave, blast_distance)); - WriteByte(MSG_BROADCAST, bound(0, WEP_CVAR(shockwave, blast_spread_max), 255)); - WriteByte(MSG_BROADCAST, bound(0, WEP_CVAR(shockwave, blast_spread_min), 255)); - WriteByte(MSG_BROADCAST, num_for_edict(self)); -} - -void W_Shockwave_Attack(void) -{ - // declarations - float multiplier, multiplier_from_accuracy, multiplier_from_distance; - float final_damage; - vector final_force, center, vel; - entity head; - - float i, queue = 0; - - // set up the shot direction - W_SetupShot(self, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_B, WEP_CVAR(shockwave, blast_damage)); - vector attack_endpos = (w_shotorg + (w_shotdir * WEP_CVAR(shockwave, blast_distance))); - WarpZone_TraceLine(w_shotorg, attack_endpos, MOVE_NOMONSTERS, self); - vector attack_hitpos = trace_endpos; - float distance_to_end = vlen(w_shotorg - attack_endpos); - float distance_to_hit = vlen(w_shotorg - attack_hitpos); - //entity transform = WarpZone_trace_transform; - - // do the firing effect now - W_Shockwave_Send(); - Damage_DamageInfo( - attack_hitpos, - WEP_CVAR(shockwave, blast_splash_damage), - WEP_CVAR(shockwave, blast_splash_edgedamage), - WEP_CVAR(shockwave, blast_splash_radius), - w_shotdir * WEP_CVAR(shockwave, blast_splash_force), - WEP_SHOCKWAVE, - 0, - self - ); - - // splash damage/jumping trace - head = WarpZone_FindRadius( - attack_hitpos, - max( - WEP_CVAR(shockwave, blast_splash_radius), - WEP_CVAR(shockwave, blast_jump_radius) - ), - FALSE - ); - - while(head) - { - if(head.takedamage) - { - float distance_to_head = vlen(attack_hitpos - head.WarpZone_findradius_nearest); - - if((head == self) && (distance_to_head <= WEP_CVAR(shockwave, blast_jump_radius))) - { - // ======================== - // BLAST JUMP CALCULATION - // ======================== - - // calculate importance of distance and accuracy for this attack - multiplier_from_accuracy = (1 - - (distance_to_head ? - min(1, (distance_to_head / WEP_CVAR(shockwave, blast_jump_radius))) - : - 0 - ) - ); - multiplier_from_distance = (1 - - (distance_to_hit ? - min(1, (distance_to_hit / distance_to_end)) - : - 0 - ) - ); - multiplier = - max( - WEP_CVAR(shockwave, blast_jump_multiplier_min), - ( - (multiplier_from_accuracy * WEP_CVAR(shockwave, blast_jump_multiplier_accuracy)) - + - (multiplier_from_distance * WEP_CVAR(shockwave, blast_jump_multiplier_distance)) - ) - ); - - // calculate damage from multiplier: 1 = "highest" damage, 0 = "lowest" edgedamage - final_damage = - ( - (WEP_CVAR(shockwave, blast_jump_damage) * multiplier) - + - (WEP_CVAR(shockwave, blast_jump_edgedamage) * (1 - multiplier)) - ); - - // figure out the direction of force - vel = normalize(combine_to_vector(head.velocity_x, head.velocity_y, 0)); - vel *= - ( - bound(0, (vlen(vel) / autocvar_sv_maxspeed), 1) - * - WEP_CVAR(shockwave, blast_jump_force_velocitybias) - ); - final_force = normalize((CENTER_OR_VIEWOFS(head) - attack_hitpos) + vel); - - // now multiply the direction by force units - final_force *= (WEP_CVAR(shockwave, blast_jump_force) * multiplier); - final_force_z *= WEP_CVAR(shockwave, blast_jump_force_zscale); - - // trigger damage with this calculated info - Damage( - head, - self, - self, - final_damage, - WEP_SHOCKWAVE, - head.origin, - final_force - ); - - #ifdef DEBUG_SHOCKWAVE - print(sprintf( - "SELF HIT: multiplier = %f, damage = %f, force = %f... " - "multiplier_from_accuracy = %f, multiplier_from_distance = %f.\n", - multiplier, - final_damage, - vlen(final_force), - multiplier_from_accuracy, - multiplier_from_distance - )); - #endif - } - else if(distance_to_head <= WEP_CVAR(shockwave, blast_splash_radius)) - { - // ========================== - // BLAST SPLASH CALCULATION - // ========================== - - // calculate importance of distance and accuracy for this attack - multiplier_from_accuracy = (1 - - (distance_to_head ? - min(1, (distance_to_head / WEP_CVAR(shockwave, blast_splash_radius))) - : - 0 - ) - ); - multiplier_from_distance = (1 - - (distance_to_hit ? - min(1, (distance_to_hit / distance_to_end)) - : - 0 - ) - ); - multiplier = - max( - WEP_CVAR(shockwave, blast_splash_multiplier_min), - ( - (multiplier_from_accuracy * WEP_CVAR(shockwave, blast_splash_multiplier_accuracy)) - + - (multiplier_from_distance * WEP_CVAR(shockwave, blast_splash_multiplier_distance)) - ) - ); - - // calculate damage from multiplier: 1 = "highest" damage, 0 = "lowest" edgedamage - final_damage = - ( - (WEP_CVAR(shockwave, blast_splash_damage) * multiplier) - + - (WEP_CVAR(shockwave, blast_splash_edgedamage) * (1 - multiplier)) - ); - - // figure out the direction of force - final_force = (w_shotdir * WEP_CVAR(shockwave, blast_splash_force_forwardbias)); - final_force = normalize(CENTER_OR_VIEWOFS(head) - (attack_hitpos - final_force)); - //te_lightning2(world, attack_hitpos, (attack_hitpos + (final_force * 200))); - - // now multiply the direction by force units - final_force *= (WEP_CVAR(shockwave, blast_splash_force) * multiplier); - final_force_z *= WEP_CVAR(shockwave, blast_force_zscale); - - // queue damage with this calculated info - if(W_Shockwave_Attack_CheckHit(queue, head, final_force, final_damage)) { queue = min(queue + 1, MAX_SHOCKWAVE_HITS); } - - #ifdef DEBUG_SHOCKWAVE - print(sprintf( - "SPLASH HIT: multiplier = %f, damage = %f, force = %f... " - "multiplier_from_accuracy = %f, multiplier_from_distance = %f.\n", - multiplier, - final_damage, - vlen(final_force), - multiplier_from_accuracy, - multiplier_from_distance - )); - #endif - } - } - head = head.chain; - } - - // cone damage trace - head = WarpZone_FindRadius(w_shotorg, WEP_CVAR(shockwave, blast_distance), FALSE); - while(head) - { - if((head != self) && head.takedamage) - { - // ======================== - // BLAST CONE CALCULATION - // ======================== - - // if it's a player, use the view origin as reference (stolen from RadiusDamage functions in g_damage.qc) - center = CENTER_OR_VIEWOFS(head); - - // find the closest point on the enemy to the center of the attack - float ang; // angle between shotdir and h - float h; // hypotenuse, which is the distance between attacker to head - float a; // adjacent side, which is the distance between attacker and the point on w_shotdir that is closest to head.origin - - h = vlen(center - self.origin); - ang = acos(dotproduct(normalize(center - self.origin), w_shotdir)); - a = h * cos(ang); - // WEAPONTODO: replace with simpler method - - vector nearest_on_line = (w_shotorg + a * w_shotdir); - vector nearest_to_attacker = WarpZoneLib_NearestPointOnBox(center + head.mins, center + head.maxs, nearest_on_line); - - if((vlen(head.WarpZone_findradius_dist) <= WEP_CVAR(shockwave, blast_distance)) - && (W_Shockwave_Attack_IsVisible(head, nearest_on_line, w_shotorg, attack_endpos))) - { - // calculate importance of distance and accuracy for this attack - multiplier_from_accuracy = (1 - - W_Shockwave_Attack_CheckSpread( - nearest_to_attacker, - nearest_on_line, - w_shotorg, - attack_endpos - ) - ); - multiplier_from_distance = (1 - - (distance_to_hit ? - min(1, (vlen(head.WarpZone_findradius_dist) / distance_to_end)) - : - 0 - ) - ); - multiplier = - max( - WEP_CVAR(shockwave, blast_multiplier_min), - ( - (multiplier_from_accuracy * WEP_CVAR(shockwave, blast_multiplier_accuracy)) - + - (multiplier_from_distance * WEP_CVAR(shockwave, blast_multiplier_distance)) - ) - ); - - // calculate damage from multiplier: 1 = "highest" damage, 0 = "lowest" edgedamage - final_damage = - ( - (WEP_CVAR(shockwave, blast_damage) * multiplier) - + - (WEP_CVAR(shockwave, blast_edgedamage) * (1 - multiplier)) - ); - - // figure out the direction of force - final_force = (w_shotdir * WEP_CVAR(shockwave, blast_force_forwardbias)); - final_force = normalize(center - (nearest_on_line - final_force)); - //te_lightning2(world, nearest_on_line, (attack_hitpos + (final_force * 200))); - - // now multiply the direction by force units - final_force *= (WEP_CVAR(shockwave, blast_force) * multiplier); - final_force_z *= WEP_CVAR(shockwave, blast_force_zscale); - - // queue damage with this calculated info - if(W_Shockwave_Attack_CheckHit(queue, head, final_force, final_damage)) { queue = min(queue + 1, MAX_SHOCKWAVE_HITS); } - - #ifdef DEBUG_SHOCKWAVE - print(sprintf( - "BLAST HIT: multiplier = %f, damage = %f, force = %f... " - "multiplier_from_accuracy = %f, multiplier_from_distance = %f.\n", - multiplier, - final_damage, - vlen(final_force), - multiplier_from_accuracy, - multiplier_from_distance - )); - #endif - } - } - head = head.chain; - } - - for(i = 1; i <= queue; ++i) - { - head = shockwave_hit[i-1]; - final_force = shockwave_hit_force[i-1]; - final_damage = shockwave_hit_damage[i-1]; - - Damage( - head, - self, - self, - final_damage, - WEP_SHOCKWAVE, - head.origin, - final_force - ); - - if(accuracy_isgooddamage(self.realowner, head)) - { - print("wtf\n"); - accuracy_add(self.realowner, WEP_SHOCKWAVE, 0, final_damage); - } - - #ifdef DEBUG_SHOCKWAVE - print(sprintf( - "SHOCKWAVE by %s: damage = %f, force = %f.\n", - self.netname, - final_damage, - vlen(final_force) - )); - #endif - - shockwave_hit[i-1] = world; - shockwave_hit_force[i-1] = '0 0 0'; - shockwave_hit_damage[i-1] = 0; - } -} - -float W_Shockwave(float req) -{ - switch(req) - { - case WR_AIM: - { - if(vlen(self.origin - self.enemy.origin) <= WEP_CVAR(shockwave, melee_range)) - { self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, FALSE); } - else - { self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, FALSE); } - - return TRUE; - } - case WR_THINK: - { - if(self.BUTTON_ATCK) - { - if(time >= self.shockwave_blasttime) // handle refire separately so the secondary can be fired straight after a primary - { - if(weapon_prepareattack(0, WEP_CVAR(shockwave, blast_animtime))) - { - W_Shockwave_Attack(); - self.shockwave_blasttime = time + WEP_CVAR(shockwave, blast_refire) * W_WeaponRateFactor(); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(shockwave, blast_animtime), w_ready); - } - } - } - else if(self.BUTTON_ATCK2) - { - //if(self.clip_load >= 0) // we are not currently reloading - if(!self.crouch) // no crouchmelee please - if(weapon_prepareattack(1, WEP_CVAR(shockwave, melee_refire))) - { - // attempt forcing playback of the anim by switching to another anim (that we never play) here... - weapon_thinkf(WFRAME_FIRE1, 0, W_Shockwave_Melee); - } - } - - return TRUE; - } - case WR_INIT: - { - precache_model("models/uziflash.md3"); - precache_model("models/weapons/g_shotgun.md3"); - precache_model("models/weapons/v_shotgun.md3"); - precache_model("models/weapons/h_shotgun.iqm"); - precache_sound("misc/itempickup.wav"); - precache_sound("weapons/lasergun_fire.wav"); - precache_sound("weapons/shotgun_melee.wav"); - SHOCKWAVE_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP) - return TRUE; - } - case WR_CHECKAMMO1: - case WR_CHECKAMMO2: - { - // shockwave has infinite ammo - return TRUE; - } - case WR_CONFIG: - { - SHOCKWAVE_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS) - return TRUE; - } - case WR_SUICIDEMESSAGE: - { - return WEAPON_THINKING_WITH_PORTALS; - } - case WR_KILLMESSAGE: - { - if(w_deathtype & HITTYPE_SECONDARY) - return WEAPON_SHOCKWAVE_MURDER_SLAP; - else - return WEAPON_SHOCKWAVE_MURDER; - } - } - return FALSE; -} -#endif -#ifdef CSQC -// WEAPONTODO: add client side settings for these -#define SW_MAXALPHA 0.5 -#define SW_FADETIME 0.4 -#define SW_DISTTOMIN 200 -void Draw_Shockwave() -{ - // fading/removal control - float a = bound(0, (SW_MAXALPHA - ((time - self.sw_time) / SW_FADETIME)), SW_MAXALPHA); - if(a < ALPHA_MIN_VISIBLE) { remove(self); } - - // WEAPONTODO: save this only once when creating the entity - vector sw_color = getcsqcplayercolor(self.sv_entnum); // GetTeamRGB(GetPlayerColor(self.sv_entnum)); - - // WEAPONTODO: trace to find what we actually hit - vector endpos = (self.sw_shotorg + (self.sw_shotdir * self.sw_distance)); - - vectorvectors(self.sw_shotdir); - vector right = v_right; // save this for when we do makevectors later - vector up = v_up; // save this for when we do makevectors later - - // WEAPONTODO: combine and simplify these calculations - vector min_end = ((self.sw_shotorg + (self.sw_shotdir * SW_DISTTOMIN)) + (up * self.sw_spread_min)); - vector max_end = (endpos + (up * self.sw_spread_max)); - float spread_to_min = vlen(normalize(min_end - self.sw_shotorg) - self.sw_shotdir); - float spread_to_max = vlen(normalize(max_end - min_end) - self.sw_shotdir); - - vector first_min_end = '0 0 0', prev_min_end = '0 0 0', new_min_end = '0 0 0'; - vector first_max_end = '0 0 0', prev_max_end = '0 0 0', new_max_end = '0 0 0'; - float new_max_dist, new_min_dist; - - vector deviation, angle = '0 0 0'; - float counter, divisions = 20; - for(counter = 0; counter < divisions; ++counter) - { - // perfect circle effect lines - makevectors('0 360 0' * (0.75 + (counter - 0.5) / divisions)); - angle_y = v_forward_x; - angle_z = v_forward_y; - - // first do the spread_to_min effect - deviation = angle * spread_to_min; - deviation = ((self.sw_shotdir + (right * deviation_y) + (up * deviation_z))); - new_min_dist = SW_DISTTOMIN; - new_min_end = (self.sw_shotorg + (deviation * new_min_dist)); - //te_lightning2(world, new_min_end, self.sw_shotorg); - - // then calculate spread_to_max effect - deviation = angle * spread_to_max; - deviation = ((self.sw_shotdir + (right * deviation_y) + (up * deviation_z))); - new_max_dist = vlen(new_min_end - endpos); - new_max_end = (new_min_end + (deviation * new_max_dist)); - //te_lightning2(world, new_end, prev_min_end); - - - if(counter == 0) - { - first_min_end = new_min_end; - first_max_end = new_max_end; - } - - if(counter >= 1) - { - // draw from shot origin to min spread radius - R_BeginPolygon("", DRAWFLAG_NORMAL); - R_PolygonVertex(prev_min_end, '0 0 0', sw_color, a); - R_PolygonVertex(new_min_end, '0 0 0', sw_color, a); - R_PolygonVertex(self.sw_shotorg, '0 0 0', sw_color, a); - R_EndPolygon(); - - // draw from min spread radius to max spread radius - R_BeginPolygon("", DRAWFLAG_NORMAL); - R_PolygonVertex(new_min_end, '0 0 0', sw_color, a); - R_PolygonVertex(prev_min_end, '0 0 0', sw_color, a); - R_PolygonVertex(prev_max_end, '0 0 0', sw_color, a); - R_PolygonVertex(new_max_end, '0 0 0', sw_color, a); - R_EndPolygon(); - } - - prev_min_end = new_min_end; - prev_max_end = new_max_end; - - // last division only - if((counter + 1) == divisions) - { - // draw from shot origin to min spread radius - R_BeginPolygon("", DRAWFLAG_NORMAL); - R_PolygonVertex(prev_min_end, '0 0 0', sw_color, a); - R_PolygonVertex(first_min_end, '0 0 0', sw_color, a); - R_PolygonVertex(self.sw_shotorg, '0 0 0', sw_color, a); - R_EndPolygon(); - - // draw from min spread radius to max spread radius - R_BeginPolygon("", DRAWFLAG_NORMAL); - R_PolygonVertex(first_min_end, '0 0 0', sw_color, a); - R_PolygonVertex(prev_min_end, '0 0 0', sw_color, a); - R_PolygonVertex(prev_max_end, '0 0 0', sw_color, a); - R_PolygonVertex(first_max_end, '0 0 0', sw_color, a); - R_EndPolygon(); - } - } -} - -void Net_ReadShockwaveParticle(void) -{ - entity shockwave; - shockwave = spawn(); - shockwave.draw = Draw_Shockwave; - - shockwave.sw_shotorg_x = ReadCoord(); shockwave.sw_shotorg_y = ReadCoord(); shockwave.sw_shotorg_z = ReadCoord(); - shockwave.sw_shotdir_x = ReadCoord(); shockwave.sw_shotdir_y = ReadCoord(); shockwave.sw_shotdir_z = ReadCoord(); - - shockwave.sw_distance = ReadShort(); - shockwave.sw_spread_max = ReadByte(); - shockwave.sw_spread_min = ReadByte(); - - shockwave.sv_entnum = ReadByte(); - - shockwave.sw_time = time; -} - -float W_Shockwave(float req) -{ - switch(req) - { - case WR_IMPACTEFFECT: - { - // handled by Net_ReadShockwaveParticle - //vector org2; - //org2 = w_org + w_backoff * 2; - //pointparticles(particleeffectnum("laser_impact"), org2, w_backoff * 1000, 1); - return FALSE; - } - case WR_INIT: - { - //precache_sound("weapons/ric1.wav"); - //precache_sound("weapons/ric2.wav"); - //precache_sound("weapons/ric3.wav"); - return FALSE; - } - case WR_ZOOMRETICLE: - { - // no weapon specific image for this weapon - return FALSE; - } - } - return FALSE; -} -#endif -#endif diff --git a/qcsrc/common/weapons/w_shotgun.qc b/qcsrc/common/weapons/w_shotgun.qc deleted file mode 100644 index 6e500dff2..000000000 --- a/qcsrc/common/weapons/w_shotgun.qc +++ /dev/null @@ -1,329 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ SHOTGUN, -/* function */ W_Shotgun, -/* ammotype */ ammo_none, -/* impulse */ 2, -/* flags */ WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN, -/* rating */ BOT_PICKUP_RATING_LOW, -/* color */ '0.5 0.25 0', -/* modelname */ "shotgun", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairshotgun 0.65", -/* wepimg */ "weaponshotgun", -/* refname */ "shotgun", -/* wepname */ _("Shotgun") -); - -#define SHOTGUN_SETTINGS(w_cvar,w_prop) SHOTGUN_SETTINGS_LIST(w_cvar, w_prop, SHOTGUN, shotgun) -#define SHOTGUN_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, PRI, ammo) \ - w_cvar(id, sn, BOTH, animtime) \ - w_cvar(id, sn, BOTH, refire) \ - w_cvar(id, sn, PRI, bullets) \ - w_cvar(id, sn, BOTH, damage) \ - w_cvar(id, sn, BOTH, force) \ - w_cvar(id, sn, PRI, solidpenetration) \ - w_cvar(id, sn, PRI, spread) \ - w_cvar(id, sn, NONE, secondary) \ - w_cvar(id, sn, SEC, melee_time) \ - w_cvar(id, sn, SEC, melee_no_doubleslap) \ - w_cvar(id, sn, SEC, melee_traces) \ - w_cvar(id, sn, SEC, melee_swing_up) \ - w_cvar(id, sn, SEC, melee_swing_side) \ - w_cvar(id, sn, SEC, melee_nonplayerdamage) \ - w_cvar(id, sn, SEC, melee_multihit) \ - w_cvar(id, sn, SEC, melee_delay) \ - w_cvar(id, sn, SEC, melee_range) \ - w_prop(id, sn, float, reloading_ammo, reload_ammo) \ - w_prop(id, sn, float, reloading_time, reload_time) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifdef SVQC -SHOTGUN_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) -#endif -#else -#ifdef SVQC -void spawnfunc_weapon_shotgun(void) { weapon_defaultspawnfunc(WEP_SHOTGUN); } - -void W_Shotgun_Attack(void) -{ - float sc; - entity flash; - - W_DecreaseAmmo(WEP_CVAR_PRI(shotgun, ammo)); - - W_SetupShot(self, TRUE, 5, "weapons/shotgun_fire.wav", CH_WEAPON_A, WEP_CVAR_PRI(shotgun, damage) * WEP_CVAR_PRI(shotgun, bullets)); - for(sc = 0;sc < WEP_CVAR_PRI(shotgun, bullets);sc = sc + 1) - fireBullet(w_shotorg, w_shotdir, WEP_CVAR_PRI(shotgun, spread), WEP_CVAR_PRI(shotgun, solidpenetration), WEP_CVAR_PRI(shotgun, damage), WEP_CVAR_PRI(shotgun, force), WEP_SHOTGUN, 0); - - pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 1000, WEP_CVAR_PRI(shotgun, ammo)); - - // casing code - if(autocvar_g_casings >= 1) - for(sc = 0;sc < WEP_CVAR_PRI(shotgun, ammo);sc = sc + 1) - SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 30) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 1, self); - - // muzzle flash for 1st person view - flash = spawn(); - setmodel(flash, "models/uziflash.md3"); // precision set below - flash.think = SUB_Remove; - flash.nextthink = time + 0.06; - flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION; - W_AttachToShotorg(flash, '5 0 0'); -} - -.float swing_prev; -.entity swing_alreadyhit; -void W_Shotgun_Melee_Think(void) -{ - // declarations - float i, f, swing, swing_factor, swing_damage, meleetime, is_player; - entity target_victim; - vector targpos; - - if(!self.cnt) // set start time of melee - { - self.cnt = time; - W_PlayStrengthSound(self.realowner); - } - - makevectors(self.realowner.v_angle); // update values for v_* vectors - - // calculate swing percentage based on time - meleetime = WEP_CVAR_SEC(shotgun, melee_time) * W_WeaponRateFactor(); - swing = bound(0, (self.cnt + meleetime - time) / meleetime, 10); - f = ((1 - swing) * WEP_CVAR_SEC(shotgun, melee_traces)); - - // check to see if we can still continue, otherwise give up now - if((self.realowner.deadflag != DEAD_NO) && WEP_CVAR_SEC(shotgun, melee_no_doubleslap)) - { - remove(self); - return; - } - - // if okay, perform the traces needed for this frame - for(i=self.swing_prev; i < f; ++i) - { - swing_factor = ((1 - (i / WEP_CVAR_SEC(shotgun, melee_traces))) * 2 - 1); - - targpos = (self.realowner.origin + self.realowner.view_ofs - + (v_forward * WEP_CVAR_SEC(shotgun, melee_range)) - + (v_up * swing_factor * WEP_CVAR_SEC(shotgun, melee_swing_up)) - + (v_right * swing_factor * WEP_CVAR_SEC(shotgun, melee_swing_side))); - - WarpZone_traceline_antilag(self, self.realowner.origin + self.realowner.view_ofs, targpos, FALSE, self, ANTILAG_LATENCY(self.realowner)); - - // draw lightning beams for debugging - //te_lightning2(world, targpos, self.realowner.origin + self.realowner.view_ofs + v_forward * 5 - v_up * 5); - //te_customflash(targpos, 40, 2, '1 1 1'); - - is_player = (IS_PLAYER(trace_ent) || trace_ent.classname == "body" || (trace_ent.flags & FL_MONSTER)); - - if((trace_fraction < 1) // if trace is good, apply the damage and remove self - && (trace_ent.takedamage == DAMAGE_AIM) - && (trace_ent != self.swing_alreadyhit) - && (is_player || WEP_CVAR_SEC(shotgun, melee_nonplayerdamage))) - { - target_victim = trace_ent; // so it persists through other calls - - if(is_player) // this allows us to be able to nerf the non-player damage done in e.g. assault or onslaught. - swing_damage = (WEP_CVAR_SEC(shotgun, damage) * min(1, swing_factor + 1)); - else - swing_damage = (WEP_CVAR_SEC(shotgun, melee_nonplayerdamage) * min(1, swing_factor + 1)); - - //print(strcat(self.realowner.netname, " hitting ", target_victim.netname, " with ", strcat(ftos(swing_damage), " damage (factor: ", ftos(swing_factor), ") at "), ftos(time), " seconds.\n")); - - Damage(target_victim, self.realowner, self.realowner, - swing_damage, WEP_SHOTGUN | HITTYPE_SECONDARY, - self.realowner.origin + self.realowner.view_ofs, - v_forward * WEP_CVAR_SEC(shotgun, force)); - - if(accuracy_isgooddamage(self.realowner, target_victim)) { accuracy_add(self.realowner, WEP_SHOTGUN, 0, swing_damage); } - - // draw large red flash for debugging - //te_customflash(targpos, 200, 2, '15 0 0'); - - if(WEP_CVAR_SEC(shotgun, melee_multihit)) // allow multiple hits with one swing, but not against the same player twice. - { - self.swing_alreadyhit = target_victim; - continue; // move along to next trace - } - else - { - remove(self); - return; - } - } - } - - if(time >= self.cnt + meleetime) - { - // melee is finished - remove(self); - return; - } - else - { - // set up next frame - self.swing_prev = i; - self.nextthink = time; - } -} - -void W_Shotgun_Attack2(void) -{ - sound(self, CH_WEAPON_A, "weapons/shotgun_melee.wav", VOL_BASE, ATTEN_NORM); - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(shotgun, animtime), w_ready); - - entity meleetemp; - meleetemp = spawn(); - meleetemp.realowner = self; - meleetemp.think = W_Shotgun_Melee_Think; - meleetemp.nextthink = time + WEP_CVAR_SEC(shotgun, melee_delay) * W_WeaponRateFactor(); - W_SetupShot_Range(self, TRUE, 0, "", 0, WEP_CVAR_SEC(shotgun, damage), WEP_CVAR_SEC(shotgun, melee_range)); -} - -.float shotgun_primarytime; - -float W_Shotgun(float req) -{ - switch(req) - { - case WR_AIM: - { - if(vlen(self.origin-self.enemy.origin) <= WEP_CVAR_SEC(shotgun, melee_range)) - self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, FALSE); - else - self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, FALSE); - - return TRUE; - } - case WR_THINK: - { - if(WEP_CVAR(shotgun, reload_ammo) && self.clip_load < WEP_CVAR_PRI(shotgun, ammo)) // forced reload - { - // don't force reload an empty shotgun if its melee attack is active - if(!WEP_CVAR(shotgun, secondary)) - WEP_ACTION(self.weapon, WR_RELOAD); - } - else - { - if(self.BUTTON_ATCK) - { - if(time >= self.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary - { - if(weapon_prepareattack(0, WEP_CVAR_PRI(shotgun, animtime))) - { - W_Shotgun_Attack(); - self.shotgun_primarytime = time + WEP_CVAR_PRI(shotgun, refire) * W_WeaponRateFactor(); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(shotgun, animtime), w_ready); - } - } - } - } - if(self.clip_load >= 0) // we are not currently reloading - if(!self.crouch) // no crouchmelee please - if(self.BUTTON_ATCK2 && WEP_CVAR(shotgun, secondary)) - if(weapon_prepareattack(1, WEP_CVAR_SEC(shotgun, refire))) - { - // attempt forcing playback of the anim by switching to another anim (that we never play) here... - weapon_thinkf(WFRAME_FIRE1, 0, W_Shotgun_Attack2); - } - - return TRUE; - } - case WR_INIT: - { - precache_model("models/uziflash.md3"); - precache_model("models/weapons/g_shotgun.md3"); - precache_model("models/weapons/v_shotgun.md3"); - precache_model("models/weapons/h_shotgun.iqm"); - precache_sound("misc/itempickup.wav"); - precache_sound("weapons/shotgun_fire.wav"); - precache_sound("weapons/shotgun_melee.wav"); - SHOTGUN_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP) - return TRUE; - } - case WR_SETUP: - { - self.ammo_field = ammo_none; - return TRUE; - } - case WR_CHECKAMMO1: - case WR_CHECKAMMO2: - { - // shotgun has infinite ammo - return TRUE; - } - case WR_CONFIG: - { - SHOTGUN_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS) - return TRUE; - } - case WR_RELOAD: - { - W_Reload(WEP_CVAR_PRI(shotgun, ammo), "weapons/reload.wav"); // WEAPONTODO - return TRUE; - } - case WR_SUICIDEMESSAGE: - { - return WEAPON_THINKING_WITH_PORTALS; - } - case WR_KILLMESSAGE: - { - if(w_deathtype & HITTYPE_SECONDARY) - return WEAPON_SHOTGUN_MURDER_SLAP; - else - return WEAPON_SHOTGUN_MURDER; - } - } - return FALSE; -} -#endif -#ifdef CSQC -.float prevric; -float W_Shotgun(float req) -{ - switch(req) - { - case WR_IMPACTEFFECT: - { - vector org2; - org2 = w_org + w_backoff * 2; - pointparticles(particleeffectnum("shotgun_impact"), org2, w_backoff * 1000, 1); - if(!w_issilent && time - self.prevric > 0.25) - { - if(w_random < 0.0165) - sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTEN_NORM); - else if(w_random < 0.033) - sound(self, CH_SHOTS, "weapons/ric2.wav", VOL_BASE, ATTEN_NORM); - else if(w_random < 0.05) - sound(self, CH_SHOTS, "weapons/ric3.wav", VOL_BASE, ATTEN_NORM); - self.prevric = time; - } - - return TRUE; - } - case WR_INIT: - { - precache_sound("weapons/ric1.wav"); - precache_sound("weapons/ric2.wav"); - precache_sound("weapons/ric3.wav"); - return TRUE; - } - case WR_ZOOMRETICLE: - { - // no weapon specific image for this weapon - return FALSE; - } - } - return FALSE; -} -#endif -#endif diff --git a/qcsrc/common/weapons/w_tuba.qc b/qcsrc/common/weapons/w_tuba.qc deleted file mode 100644 index e450c5bd0..000000000 --- a/qcsrc/common/weapons/w_tuba.qc +++ /dev/null @@ -1,508 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ TUBA, -/* function */ W_Tuba, -/* ammotype */ ammo_none, -/* impulse */ 1, -/* flags */ WEP_FLAG_HIDDEN | WEP_TYPE_SPLASH, -/* rating */ BOT_PICKUP_RATING_MID, -/* color */ '0 1 0', -/* modelname */ "tuba", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairtuba", -/* wepimg */ "weapontuba", -/* refname */ "tuba", -/* xgettext:no-c-format */ -/* wepname */ _("@!#%'n Tuba") -); - -#define TUBA_SETTINGS(w_cvar,w_prop) TUBA_SETTINGS_LIST(w_cvar, w_prop, TUBA, tuba) -#define TUBA_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, NONE, animtime) \ - w_cvar(id, sn, NONE, attenuation) \ - w_cvar(id, sn, NONE, damage) \ - w_cvar(id, sn, NONE, edgedamage) \ - w_cvar(id, sn, NONE, force) \ - w_cvar(id, sn, NONE, radius) \ - w_cvar(id, sn, NONE, refire) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifdef SVQC -TUBA_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) -.entity tuba_note; -.float tuba_smoketime; -.float tuba_instrument; - -#define MAX_TUBANOTES 32 -.float tuba_lastnotes_last; -.float tuba_lastnotes_cnt; // over -.vector tuba_lastnotes[MAX_TUBANOTES]; -#endif -#else -#ifdef SVQC -void spawnfunc_weapon_tuba(void) { weapon_defaultspawnfunc(WEP_TUBA); } - -float W_Tuba_HasPlayed(entity pl, string melody, float instrument, float ignorepitch, float mintempo, float maxtempo) -{ - float i, j, mmin, mmax, nolength; - float n = tokenize_console(melody); - if(n > pl.tuba_lastnotes_cnt) - return FALSE; - float pitchshift = 0; - - if(instrument >= 0) - if(pl.tuba_instrument != instrument) - return FALSE; - - // verify notes... - nolength = FALSE; - for(i = 0; i < n; ++i) - { - vector v = pl.(tuba_lastnotes[mod(pl.tuba_lastnotes_last - i + MAX_TUBANOTES, MAX_TUBANOTES)]); - float ai = stof(argv(n - i - 1)); - float np = floor(ai); - if(ai == np) - nolength = TRUE; - // n counts the last played notes BACKWARDS - // _x is start - // _y is end - // _z is note pitch - if(ignorepitch && i == 0) - { - pitchshift = np - v_z; - } - else - { - if(v_z + pitchshift != np) - return FALSE; - } - } - - // now we know the right NOTES were played - if(!nolength) - { - // verify rhythm... - float ti = 0; - if(maxtempo > 0) - mmin = 240 / maxtempo; // 60 = "0.25 means 1 sec", at 120 0.5 means 1 sec, at 240 1 means 1 sec - else - mmin = 0; - if(mintempo > 0) - mmax = 240 / mintempo; // 60 = "0.25 means 1 sec", at 120 0.5 means 1 sec, at 240 1 means 1 sec - else - mmax = 240; // you won't try THAT hard... (tempo 1) - //printf("initial tempo rules: %f %f\n", mmin, mmax); - - for(i = 0; i < n; ++i) - { - vector vi = pl.(tuba_lastnotes[mod(pl.tuba_lastnotes_last - i + MAX_TUBANOTES, MAX_TUBANOTES)]); - float ai = stof(argv(n - i - 1)); - ti -= 1 / (ai - floor(ai)); - float tj = ti; - for(j = i+1; j < n; ++j) - { - vector vj = pl.(tuba_lastnotes[mod(pl.tuba_lastnotes_last - j + MAX_TUBANOTES, MAX_TUBANOTES)]); - float aj = stof(argv(n - j - 1)); - tj -= (aj - floor(aj)); - - // note i should be at m*ti+b - // note j should be at m*tj+b - // so: - // we have a LINE l, so that - // vi_x <= l(ti) <= vi_y - // vj_x <= l(tj) <= vj_y - // what is m? - - // vi_x <= vi_y <= vj_x <= vj_y - // ti <= tj - //printf("first note: %f to %f, should be %f\n", vi_x, vi_y, ti); - //printf("second note: %f to %f, should be %f\n", vj_x, vj_y, tj); - //printf("m1 = %f\n", (vi_x - vj_y) / (ti - tj)); - //printf("m2 = %f\n", (vi_y - vj_x) / (ti - tj)); - mmin = max(mmin, (vi_x - vj_y) / (ti - tj)); // lower bound - mmax = min(mmax, (vi_y - vj_x) / (ti - tj)); // upper bound - } - } - - if(mmin > mmax) // rhythm fail - return FALSE; - } - - pl.tuba_lastnotes_cnt = 0; - - return TRUE; -} - -void W_Tuba_NoteOff(void) -{ - // we have a note: - // on: self.spawnshieldtime - // off: time - // note: self.cnt - if(self.owner.tuba_note == self) - { - self.owner.tuba_lastnotes_last = mod(self.owner.tuba_lastnotes_last + 1, MAX_TUBANOTES); - self.owner.(tuba_lastnotes[self.owner.tuba_lastnotes_last]) = eX * self.spawnshieldtime + eY * time + eZ * self.cnt; - self.owner.tuba_note = world; - self.owner.tuba_lastnotes_cnt = bound(0, self.owner.tuba_lastnotes_cnt + 1, MAX_TUBANOTES); - - string s; - s = trigger_magicear_processmessage_forallears(self.owner, 0, world, string_null); - if(s != "") - { - // simulate a server message - switch(self.tuba_instrument) - { - default: - case 0: // Tuba - bprint(strcat("\{1}\{13}* ^3", self.owner.netname, "^3 played on the @!#%'n Tuba: ^7", s, "\n")); - break; - case 1: - bprint(strcat("\{1}\{13}* ^3", self.owner.netname, "^3 played on the @!#%'n Accordeon: ^7", s, "\n")); - break; - case 2: - bprint(strcat("\{1}\{13}* ^3", self.owner.netname, "^3 played on the @!#%'n Klein Bottle: ^7", s, "\n")); - break; - } - } - } - remove(self); -} - -float W_Tuba_GetNote(entity pl, float hittype) -{ - float note; - float movestate; - movestate = 5; - if(pl.movement_x < 0) movestate -= 3; - if(pl.movement_x > 0) movestate += 3; - if(pl.movement_y < 0) movestate -= 1; - if(pl.movement_y > 0) movestate += 1; -#ifdef GMQCC - note = 0; -#endif - switch(movestate) - { - // layout: originally I wanted - // eb e e#=f - // B c d - // Gb G G# - // but then you only use forward and right key. So to make things more - // interesting, I swapped B with e#. Har har har... - // eb e B - // f=e# c d - // Gb G G# - case 1: note = -6; break; // Gb - case 2: note = -5; break; // G - case 3: note = -4; break; // G# - case 4: note = +5; break; // e# - default: - case 5: note = 0; break; // c - case 6: note = +2; break; // d - case 7: note = +3; break; // eb - case 8: note = +4; break; // e - case 9: note = -1; break; // B - } - if(pl.BUTTON_CROUCH) - note -= 12; - if(pl.BUTTON_JUMP) - note += 12; - if(hittype & HITTYPE_SECONDARY) - note += 7; - - // we support two kinds of tubas, those tuned in Eb and those tuned in C - // kind of tuba currently is player slot number, or team number if in - // teamplay - // that way, holes in the range of notes are "plugged" - if(teamplay) - { - if(pl.team == NUM_TEAM_2 || pl.team == NUM_TEAM_4) - note += 3; - } - else - { - if(pl.clientcolors & 1) - note += 3; - } - - // total range of notes: - // 0 - // *** ** **** - // *** ** **** - // *** ** **** - // *** ** **** - // *** ********************* **** - // -18.........................+12 - // *** ********************* **** - // -18............................+15 - // with jump: ... +24 - // ... +27 - return note; -} - -float W_Tuba_NoteSendEntity(entity to, float sf) -{ - float f; - - msg_entity = to; - if(!sound_allowed(MSG_ONE, self.realowner)) - return FALSE; - - WriteByte(MSG_ENTITY, ENT_CLIENT_TUBANOTE); - WriteByte(MSG_ENTITY, sf); - if(sf & 1) - { - WriteChar(MSG_ENTITY, self.cnt); - f = 0; - if(self.realowner != to) - f |= 1; - f |= 2 * self.tuba_instrument; - WriteByte(MSG_ENTITY, f); - } - if(sf & 2) - { - WriteCoord(MSG_ENTITY, self.origin_x); - WriteCoord(MSG_ENTITY, self.origin_y); - WriteCoord(MSG_ENTITY, self.origin_z); - } - return TRUE; -} - -void W_Tuba_NoteThink(void) -{ - float dist_mult; - float vol0, vol1; - vector dir0, dir1; - vector v; - entity e; - if(time > self.teleport_time) - { - W_Tuba_NoteOff(); - return; - } - self.nextthink = time; - dist_mult = WEP_CVAR(tuba, attenuation) / autocvar_snd_soundradius; - FOR_EACH_REALCLIENT(e) - if(e != self.realowner) - { - v = self.origin - (e.origin + e.view_ofs); - vol0 = max(0, 1 - vlen(v) * dist_mult); - dir0 = normalize(v); - v = self.realowner.origin - (e.origin + e.view_ofs); - vol1 = max(0, 1 - vlen(v) * dist_mult); - dir1 = normalize(v); - if(fabs(vol0 - vol1) > 0.005) // 0.5 percent change in volume - { - setorigin(self, self.realowner.origin); - self.SendFlags |= 2; - break; - } - if(dir0 * dir1 < 0.9994) // 2 degrees change in angle - { - setorigin(self, self.realowner.origin); - self.SendFlags |= 2; - break; - } - } -} - -void W_Tuba_NoteOn(float hittype) -{ - vector o; - float n; - - W_SetupShot(self, FALSE, 2, "", 0, WEP_CVAR(tuba, damage)); - - n = W_Tuba_GetNote(self, hittype); - - hittype = 0; - if(self.tuba_instrument & 1) - hittype |= HITTYPE_SECONDARY; - if(self.tuba_instrument & 2) - hittype |= HITTYPE_BOUNCE; - - if(self.tuba_note) - { - if(self.tuba_note.cnt != n || self.tuba_note.tuba_instrument != self.tuba_instrument) - { - entity oldself = self; - self = self.tuba_note; - W_Tuba_NoteOff(); - self = oldself; - } - } - - if(!self.tuba_note) - { - self.tuba_note = spawn(); - self.tuba_note.owner = self.tuba_note.realowner = self; - self.tuba_note.cnt = n; - self.tuba_note.tuba_instrument = self.tuba_instrument; - self.tuba_note.think = W_Tuba_NoteThink; - self.tuba_note.nextthink = time; - self.tuba_note.spawnshieldtime = time; - Net_LinkEntity(self.tuba_note, FALSE, 0, W_Tuba_NoteSendEntity); - } - - self.tuba_note.teleport_time = time + WEP_CVAR(tuba, refire) * 2 * W_WeaponRateFactor(); // so it can get prolonged safely - - //sound(self, c, TUBA_NOTE(n), bound(0, VOL_BASE * cvar("g_balance_tuba_volume"), 1), autocvar_g_balance_tuba_attenuation); - RadiusDamage(self, self, WEP_CVAR(tuba, damage), WEP_CVAR(tuba, edgedamage), WEP_CVAR(tuba, radius), world, world, WEP_CVAR(tuba, force), hittype | WEP_TUBA, world); - - o = gettaginfo(self.exteriorweaponentity, 0); - if(time > self.tuba_smoketime) - { - pointparticles(particleeffectnum("smoke_ring"), o + v_up * 45 + v_right * -6 + v_forward * 8, v_up * 100, 1); - self.tuba_smoketime = time + 0.25; - } -} - -float W_Tuba(float req) -{ - switch(req) - { - case WR_AIM: - { - // bots cannot play the Tuba well yet - // I think they should start with the recorder first - if(vlen(self.origin - self.enemy.origin) < WEP_CVAR(tuba, radius)) - { - if(random() > 0.5) - self.BUTTON_ATCK = 1; - else - self.BUTTON_ATCK2 = 1; - } - - return TRUE; - } - case WR_THINK: - { - if(self.BUTTON_ATCK) - if(weapon_prepareattack(0, WEP_CVAR(tuba, refire))) - { - W_Tuba_NoteOn(0); - //weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_tuba_animtime, w_ready); - weapon_thinkf(WFRAME_IDLE, WEP_CVAR(tuba, animtime), w_ready); - } - if(self.BUTTON_ATCK2) - if(weapon_prepareattack(1, WEP_CVAR(tuba, refire))) - { - W_Tuba_NoteOn(HITTYPE_SECONDARY); - //weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_tuba_animtime, w_ready); - weapon_thinkf(WFRAME_IDLE, WEP_CVAR(tuba, animtime), w_ready); - } - if(self.tuba_note) - { - if(!self.BUTTON_ATCK && !self.BUTTON_ATCK2) - { - entity oldself = self; - self = self.tuba_note; - W_Tuba_NoteOff(); - self = oldself; - } - } - - return TRUE; - } - case WR_INIT: - { - precache_model("models/weapons/g_tuba.md3"); - precache_model("models/weapons/v_tuba.md3"); - precache_model("models/weapons/h_tuba.iqm"); - precache_model("models/weapons/v_akordeon.md3"); - precache_model("models/weapons/h_akordeon.iqm"); - precache_model("models/weapons/v_kleinbottle.md3"); - precache_model("models/weapons/h_kleinbottle.iqm"); - TUBA_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP) - return TRUE; - } - case WR_SETUP: - { - self.ammo_field = ammo_none; - self.tuba_instrument = 0; - return TRUE; - } - case WR_RELOAD: - { - // switch to alternate instruments :) - if(self.weaponentity.state == WS_READY) - { - switch(self.tuba_instrument) - { - case 0: - self.tuba_instrument = 1; - self.weaponname = "akordeon"; - break; - case 1: - self.tuba_instrument = 2; - self.weaponname = "kleinbottle"; - break; - case 2: - self.tuba_instrument = 0; - self.weaponname = "tuba"; - break; - } - W_SetupShot(self, FALSE, 0, "", 0, 0); - pointparticles(particleeffectnum("teleport"), w_shotorg, '0 0 0', 1); - self.weaponentity.state = WS_INUSE; - weapon_thinkf(WFRAME_RELOAD, 0.5, w_ready); - } - - return TRUE; - } - case WR_CHECKAMMO1: - case WR_CHECKAMMO2: - { - return TRUE; // tuba has infinite ammo - } - case WR_CONFIG: - { - TUBA_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS) - return TRUE; - } - case WR_SUICIDEMESSAGE: - { - if(w_deathtype & HITTYPE_BOUNCE) - return WEAPON_KLEINBOTTLE_SUICIDE; - else if(w_deathtype & HITTYPE_SECONDARY) - return WEAPON_ACCORDEON_SUICIDE; - else - return WEAPON_TUBA_SUICIDE; - } - case WR_KILLMESSAGE: - { - if(w_deathtype & HITTYPE_BOUNCE) - return WEAPON_KLEINBOTTLE_MURDER; - else if(w_deathtype & HITTYPE_SECONDARY) - return WEAPON_ACCORDEON_MURDER; - else - return WEAPON_TUBA_MURDER; - } - } - return FALSE; -} -#endif -#ifdef CSQC -float W_Tuba(float req) -{ - // nothing to do here; particles of tuba are handled differently - // WEAPONTODO - - switch(req) - { - case WR_ZOOMRETICLE: - { - // no weapon specific image for this weapon - return FALSE; - } - } - - return FALSE; -} -#endif -#endif diff --git a/qcsrc/common/weapons/w_vaporizer.qc b/qcsrc/common/weapons/w_vaporizer.qc deleted file mode 100644 index 7ad1e1dd8..000000000 --- a/qcsrc/common/weapons/w_vaporizer.qc +++ /dev/null @@ -1,299 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ VAPORIZER, -/* function */ W_Vaporizer, -/* ammotype */ ammo_cells, -/* impulse */ 7, -/* flags */ WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_FLAG_SUPERWEAPON | WEP_TYPE_HITSCAN, -/* rating */ BOT_PICKUP_RATING_HIGH, -/* color */ '0.5 1 1', -/* modelname */ "minstanex", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairminstanex 0.4", -/* wepimg */ "weaponminstanex", -/* refname */ "vaporizer", -/* wepname */ _("Vaporizer") -); - -#define VAPORIZER_SETTINGS(w_cvar,w_prop) VAPORIZER_SETTINGS_LIST(w_cvar, w_prop, VAPORIZER, vaporizer) -#define VAPORIZER_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, PRI, ammo) \ - w_cvar(id, sn, PRI, animtime) \ - w_cvar(id, sn, PRI, refire) \ - w_cvar(id, sn, SEC, ammo) \ - w_cvar(id, sn, SEC, animtime) \ - w_cvar(id, sn, SEC, damage) \ - w_cvar(id, sn, SEC, delay) \ - w_cvar(id, sn, SEC, edgedamage) \ - w_cvar(id, sn, SEC, force) \ - w_cvar(id, sn, SEC, lifetime) \ - w_cvar(id, sn, SEC, radius) \ - w_cvar(id, sn, SEC, refire) \ - w_cvar(id, sn, SEC, shotangle) \ - w_cvar(id, sn, SEC, speed) \ - w_cvar(id, sn, SEC, spread) \ - w_prop(id, sn, float, reloading_ammo, reload_ammo) \ - w_prop(id, sn, float, reloading_time, reload_time) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifdef SVQC -VAPORIZER_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) -.float vaporizer_lasthit; -.float jump_interval; -#endif -#else -#ifdef SVQC -void spawnfunc_weapon_vaporizer(void) { weapon_defaultspawnfunc(WEP_VAPORIZER); } -void spawnfunc_weapon_minstanex(void) { spawnfunc_weapon_vaporizer(); } - -void W_Vaporizer_Attack(void) -{ - float flying; - flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last - - W_SetupShot(self, TRUE, 0, "weapons/minstanexfire.wav", CH_WEAPON_A, 10000); - - yoda = 0; - damage_goodhits = 0; - FireRailgunBullet(w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, 10000, 800, 0, 0, 0, 0, WEP_VAPORIZER); - - if(yoda && flying) - Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA); - if(damage_goodhits && self.vaporizer_lasthit) - { - Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_ACHIEVEMENT_IMPRESSIVE); - damage_goodhits = 0; // only every second time - } - - self.vaporizer_lasthit = damage_goodhits; - - pointparticles(particleeffectnum("nex_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - // teamcolor / hit beam effect - vector v; - v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos); - switch(self.team) - { - case NUM_TEAM_1: // Red - if(damage_goodhits) - WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED_HIT"), w_shotorg, v); - else - WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED"), w_shotorg, v); - break; - case NUM_TEAM_2: // Blue - if(damage_goodhits) - WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE_HIT"), w_shotorg, v); - else - WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE"), w_shotorg, v); - break; - case NUM_TEAM_3: // Yellow - if(damage_goodhits) - WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW_HIT"), w_shotorg, v); - else - WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW"), w_shotorg, v); - break; - case NUM_TEAM_4: // Pink - if(damage_goodhits) - WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK_HIT"), w_shotorg, v); - else - WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK"), w_shotorg, v); - break; - default: - if(damage_goodhits) - WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3_HIT"), w_shotorg, v); - else - WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3"), w_shotorg, v); - break; - } - - W_DecreaseAmmo(((g_minstagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo))); -} - -float W_Vaporizer(float req) -{ - float ammo_amount; - float vaporizer_ammo; - - // now multiple WR_s use this - vaporizer_ammo = ((g_minstagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo)); - - switch(req) - { - case WR_AIM: - { - if(self.WEP_AMMO(VAPORIZER) > 0) - self.BUTTON_ATCK = bot_aim(1000000, 0, 1, FALSE); - else - self.BUTTON_ATCK2 = bot_aim(WEP_CVAR_SEC(vaporizer, speed), 0, WEP_CVAR_SEC(vaporizer, lifetime), FALSE); // WEAPONTODO: replace with proper vaporizer cvars - - return TRUE; - } - case WR_THINK: - { - // if the laser uses load, we also consider its ammo for reloading - if(WEP_CVAR(vaporizer, reload_ammo) && WEP_CVAR_SEC(vaporizer, ammo) && self.clip_load < min(vaporizer_ammo, WEP_CVAR_SEC(vaporizer, ammo))) // forced reload - WEP_ACTION(self.weapon, WR_RELOAD); - else if(WEP_CVAR(vaporizer, reload_ammo) && self.clip_load < vaporizer_ammo) // forced reload - WEP_ACTION(self.weapon, WR_RELOAD); - else if(self.BUTTON_ATCK) - { - if(weapon_prepareattack(0, WEP_CVAR_PRI(vaporizer, refire))) - { - W_Vaporizer_Attack(); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(vaporizer, animtime), w_ready); - } - } - else if(self.BUTTON_ATCK2) - { - if(self.jump_interval <= time) - if(weapon_prepareattack(1, -1)) - { - // handle refire manually, so that primary and secondary can be fired without conflictions (important for minstagib) - self.jump_interval = time + WEP_CVAR_SEC(vaporizer, refire) * W_WeaponRateFactor(); - - // decrease ammo for the laser? - if(WEP_CVAR_SEC(vaporizer, ammo)) - W_DecreaseAmmo(WEP_CVAR_SEC(vaporizer, ammo)); - - // ugly minstagib hack to reuse the fire mode of the laser - W_Blaster_Attack( - WEP_VAPORIZER | HITTYPE_SECONDARY, - WEP_CVAR_SEC(vaporizer, shotangle), - WEP_CVAR_SEC(vaporizer, damage), - WEP_CVAR_SEC(vaporizer, edgedamage), - WEP_CVAR_SEC(vaporizer, radius), - WEP_CVAR_SEC(vaporizer, force), - WEP_CVAR_SEC(vaporizer, speed), - WEP_CVAR_SEC(vaporizer, spread), - WEP_CVAR_SEC(vaporizer, delay), - WEP_CVAR_SEC(vaporizer, lifetime) - ); - - // now do normal refire - weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(vaporizer, animtime), w_ready); - } - } - - return TRUE; - } - case WR_INIT: - { - precache_model("models/nexflash.md3"); - precache_model("models/weapons/g_minstanex.md3"); - precache_model("models/weapons/v_minstanex.md3"); - precache_model("models/weapons/h_minstanex.iqm"); - precache_sound("weapons/minstanexfire.wav"); - precache_sound("weapons/nexwhoosh1.wav"); - precache_sound("weapons/nexwhoosh2.wav"); - precache_sound("weapons/nexwhoosh3.wav"); - //W_Blaster(WR_INIT); // Samual: Is this really the proper thing to do? Didn't we already run this previously? - VAPORIZER_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP) - return TRUE; - } - case WR_SETUP: - { - self.ammo_field = WEP_AMMO(VAPORIZER); - self.vaporizer_lasthit = 0; - return TRUE; - } - case WR_CHECKAMMO1: - { - ammo_amount = self.WEP_AMMO(VAPORIZER) >= vaporizer_ammo; - ammo_amount += self.(weapon_load[WEP_VAPORIZER]) >= vaporizer_ammo; - return ammo_amount; - } - case WR_CHECKAMMO2: - { - if(!WEP_CVAR_SEC(vaporizer, ammo)) - return TRUE; - ammo_amount = self.WEP_AMMO(VAPORIZER) >= WEP_CVAR_SEC(vaporizer, ammo); - ammo_amount += self.(weapon_load[WEP_VAPORIZER]) >= WEP_CVAR_SEC(vaporizer, ammo); - return ammo_amount; - } - case WR_CONFIG: - { - VAPORIZER_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS) - return TRUE; - } - case WR_RESETPLAYER: - { - self.vaporizer_lasthit = 0; - return TRUE; - } - case WR_RELOAD: - { - float used_ammo; - if(WEP_CVAR_SEC(vaporizer, ammo)) - used_ammo = min(vaporizer_ammo, WEP_CVAR_SEC(vaporizer, ammo)); - else - used_ammo = vaporizer_ammo; - - W_Reload(used_ammo, "weapons/reload.wav"); - return TRUE; - } - case WR_SUICIDEMESSAGE: - { - return WEAPON_THINKING_WITH_PORTALS; - } - case WR_KILLMESSAGE: - { - return WEAPON_VAPORIZER_MURDER; - } - } - return FALSE; -} -#endif -#ifdef CSQC -float W_Vaporizer(float req) -{ - switch(req) - { - case WR_IMPACTEFFECT: - { - vector org2; - org2 = w_org + w_backoff * 6; - if(w_deathtype & HITTYPE_SECONDARY) - { - pointparticles(particleeffectnum("laser_impact"), org2, w_backoff * 1000, 1); - if(!w_issilent) { sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_NORM); } - } - else - { - pointparticles(particleeffectnum("nex_impact"), org2, '0 0 0', 1); - if(!w_issilent) { sound(self, CH_SHOTS, "weapons/neximpact.wav", VOL_BASE, ATTN_NORM); } - } - return TRUE; - } - case WR_INIT: - { - precache_sound("weapons/laserimpact.wav"); - precache_sound("weapons/neximpact.wav"); - if(autocvar_cl_reticle && autocvar_cl_reticle_weapon) - { - precache_pic("gfx/reticle_nex"); - } - return TRUE; - } - case WR_ZOOMRETICLE: - { - if(button_zoom || zoomscript_caught) - { - reticle_image = "gfx/reticle_nex"; - return TRUE; - } - else - { - // no weapon specific image for this weapon - return FALSE; - } - } - } - return FALSE; -} -#endif -#endif diff --git a/qcsrc/common/weapons/w_vortex.qc b/qcsrc/common/weapons/w_vortex.qc deleted file mode 100644 index 6512d0430..000000000 --- a/qcsrc/common/weapons/w_vortex.qc +++ /dev/null @@ -1,341 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ VORTEX, -/* function */ W_Vortex, -/* ammotype */ ammo_cells, -/* impulse */ 7, -/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN, -/* rating */ BOT_PICKUP_RATING_HIGH, -/* color */ '0.5 1 1', -/* modelname */ "nex", -/* simplemdl */ "foobar", -/* crosshair */ "gfx/crosshairnex 0.65", -/* wepimg */ "weaponnex", -/* refname */ "vortex", -/* wepname */ _("Vortex") -); - -#define VORTEX_SETTINGS(w_cvar,w_prop) VORTEX_SETTINGS_LIST(w_cvar, w_prop, VORTEX, vortex) -#define VORTEX_SETTINGS_LIST(w_cvar,w_prop,id,sn) \ - w_cvar(id, sn, BOTH, ammo) \ - w_cvar(id, sn, BOTH, animtime) \ - w_cvar(id, sn, BOTH, damage) \ - w_cvar(id, sn, BOTH, force) \ - w_cvar(id, sn, BOTH, damagefalloff_mindist) \ - w_cvar(id, sn, BOTH, damagefalloff_maxdist) \ - w_cvar(id, sn, BOTH, damagefalloff_halflife) \ - w_cvar(id, sn, BOTH, damagefalloff_forcehalflife) \ - w_cvar(id, sn, BOTH, refire) \ - w_cvar(id, sn, NONE, charge) \ - w_cvar(id, sn, NONE, charge_mindmg) \ - w_cvar(id, sn, NONE, charge_shot_multiplier) \ - w_cvar(id, sn, NONE, charge_animlimit) \ - w_cvar(id, sn, NONE, charge_limit) \ - w_cvar(id, sn, NONE, charge_rate) \ - w_cvar(id, sn, NONE, charge_rot_rate) \ - w_cvar(id, sn, NONE, charge_rot_pause) \ - w_cvar(id, sn, NONE, charge_start) \ - w_cvar(id, sn, NONE, charge_minspeed) \ - w_cvar(id, sn, NONE, charge_maxspeed) \ - w_cvar(id, sn, NONE, charge_velocity_rate) \ - w_cvar(id, sn, NONE, secondary) \ - w_cvar(id, sn, SEC, chargepool) \ - w_cvar(id, sn, SEC, chargepool_regen) \ - w_cvar(id, sn, SEC, chargepool_pause_regen) \ - w_prop(id, sn, float, reloading_ammo, reload_ammo) \ - w_prop(id, sn, float, reloading_time, reload_time) \ - w_prop(id, sn, float, switchdelay_raise, switchdelay_raise) \ - w_prop(id, sn, float, switchdelay_drop, switchdelay_drop) \ - w_prop(id, sn, string, weaponreplace, weaponreplace) \ - w_prop(id, sn, float, weaponstart, weaponstart) \ - w_prop(id, sn, float, weaponstartoverride, weaponstartoverride) \ - w_prop(id, sn, float, weaponthrowable, weaponthrowable) - -#ifdef SVQC -VORTEX_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP) -#endif -#else -#ifdef SVQC -void spawnfunc_weapon_vortex(void) { weapon_defaultspawnfunc(WEP_VORTEX); } -void spawnfunc_weapon_nex(void) { spawnfunc_weapon_vortex(); } - -void SendCSQCVortexBeamParticle(float charge) { - vector v; - v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos); - WriteByte(MSG_BROADCAST, SVC_TEMPENTITY); - WriteByte(MSG_BROADCAST, TE_CSQC_VORTEXBEAMPARTICLE); - WriteCoord(MSG_BROADCAST, w_shotorg_x); - WriteCoord(MSG_BROADCAST, w_shotorg_y); - WriteCoord(MSG_BROADCAST, w_shotorg_z); - WriteCoord(MSG_BROADCAST, v_x); - WriteCoord(MSG_BROADCAST, v_y); - WriteCoord(MSG_BROADCAST, v_z); - WriteByte(MSG_BROADCAST, bound(0, 255 * charge, 255)); -} - -void W_Vortex_Attack(float issecondary) -{ - float mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, myammo, charge; - - mydmg = WEP_CVAR_BOTH(vortex, !issecondary, damage); - myforce = WEP_CVAR_BOTH(vortex, !issecondary, force); - mymindist = WEP_CVAR_BOTH(vortex, !issecondary, damagefalloff_mindist); - mymaxdist = WEP_CVAR_BOTH(vortex, !issecondary, damagefalloff_maxdist); - myhalflife = WEP_CVAR_BOTH(vortex, !issecondary, damagefalloff_halflife); - myforcehalflife = WEP_CVAR_BOTH(vortex, !issecondary, damagefalloff_forcehalflife); - myammo = WEP_CVAR_BOTH(vortex, !issecondary, ammo); - - float flying; - flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last - - if(WEP_CVAR(vortex, charge)) - { - charge = WEP_CVAR(vortex, charge_mindmg) / mydmg + (1 - WEP_CVAR(vortex, charge_mindmg) / mydmg) * self.vortex_charge; - self.vortex_charge *= WEP_CVAR(vortex, charge_shot_multiplier); // do this AFTER setting mydmg/myforce - // O RLY? -- divVerent - // YA RLY -- FruitieX - } - else - charge = 1; - mydmg *= charge; - myforce *= charge; - - W_SetupShot(self, TRUE, 5, "weapons/nexfire.wav", CH_WEAPON_A, mydmg); - if(charge > WEP_CVAR(vortex, charge_animlimit) && WEP_CVAR(vortex, charge_animlimit)) // if the Vortex is overcharged, we play an extra sound - { - sound(self, CH_WEAPON_B, "weapons/nexcharge.wav", VOL_BASE * (charge - 0.5 * WEP_CVAR(vortex, charge_animlimit)) / (1 - 0.5 * WEP_CVAR(vortex, charge_animlimit)), ATTN_NORM); - } - - yoda = 0; - FireRailgunBullet(w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, WEP_VORTEX); - - if(yoda && flying) - Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA); - - //beam and muzzle flash done on client - SendCSQCVortexBeamParticle(charge); - - W_DecreaseAmmo(myammo); -} - -void spawnfunc_weapon_vortex(void); // defined in t_items.qc - -.float vortex_chargepool_pauseregen_finished; -float W_Vortex(float req) -{ - float dt; - float ammo_amount; - switch(req) - { - case WR_AIM: - { - if(bot_aim(1000000, 0, 1, FALSE)) - self.BUTTON_ATCK = TRUE; - else - { - if(WEP_CVAR(vortex, charge)) - self.BUTTON_ATCK2 = TRUE; - } - return TRUE; - } - case WR_THINK: - { - if(WEP_CVAR(vortex, charge) && self.vortex_charge < WEP_CVAR(vortex, charge_limit)) - self.vortex_charge = min(1, self.vortex_charge + WEP_CVAR(vortex, charge_rate) * frametime / W_TICSPERFRAME); - - if(WEP_CVAR_SEC(vortex, chargepool)) - if(self.vortex_chargepool_ammo < 1) - { - if(self.vortex_chargepool_pauseregen_finished < time) - self.vortex_chargepool_ammo = min(1, self.vortex_chargepool_ammo + WEP_CVAR_SEC(vortex, chargepool_regen) * frametime / W_TICSPERFRAME); - self.pauseregen_finished = max(self.pauseregen_finished, time + WEP_CVAR_SEC(vortex, chargepool_pause_regen)); - } - - if(autocvar_g_balance_vortex_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo))) // forced reload - WEP_ACTION(self.weapon, WR_RELOAD); - else - { - if(self.BUTTON_ATCK) - { - if(weapon_prepareattack(0, WEP_CVAR_PRI(vortex, refire))) - { - W_Vortex_Attack(0); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(vortex, animtime), w_ready); - } - } - if((WEP_CVAR(vortex, charge) && !WEP_CVAR(vortex, secondary)) ? (self.BUTTON_ZOOM | self.BUTTON_ZOOMSCRIPT) : self.BUTTON_ATCK2) - { - if(WEP_CVAR(vortex, charge)) - { - self.vortex_charge_rottime = time + WEP_CVAR(vortex, charge_rot_pause); - dt = frametime / W_TICSPERFRAME; - - if(self.vortex_charge < 1) - { - if(WEP_CVAR_SEC(vortex, chargepool)) - { - if(WEP_CVAR_SEC(vortex, ammo)) - { - // always deplete if secondary is held - self.vortex_chargepool_ammo = max(0, self.vortex_chargepool_ammo - WEP_CVAR_SEC(vortex, ammo) * dt); - - dt = min(dt, (1 - self.vortex_charge) / WEP_CVAR(vortex, charge_rate)); - self.vortex_chargepool_pauseregen_finished = time + WEP_CVAR_SEC(vortex, chargepool_pause_regen); - dt = min(dt, self.vortex_chargepool_ammo); - dt = max(0, dt); - - self.vortex_charge += dt * WEP_CVAR(vortex, charge_rate); - } - } - - else if(WEP_CVAR_SEC(vortex, ammo)) - { - if(self.BUTTON_ATCK2) // only eat ammo when the button is pressed - { - dt = min(dt, (1 - self.vortex_charge) / WEP_CVAR(vortex, charge_rate)); - if(!(self.items & IT_UNLIMITED_WEAPON_AMMO)) - { - // if this weapon is reloadable, decrease its load. Else decrease the player's ammo - if(autocvar_g_balance_vortex_reload_ammo) - { - dt = min(dt, (self.clip_load - WEP_CVAR_PRI(vortex, ammo)) / WEP_CVAR_SEC(vortex, ammo)); - dt = max(0, dt); - if(dt > 0) - { - self.clip_load = max(WEP_CVAR_SEC(vortex, ammo), self.clip_load - WEP_CVAR_SEC(vortex, ammo) * dt); - } - self.(weapon_load[WEP_VORTEX]) = self.clip_load; - } - else - { - dt = min(dt, (self.WEP_AMMO(VORTEX) - WEP_CVAR_PRI(vortex, ammo)) / WEP_CVAR_SEC(vortex, ammo)); - dt = max(0, dt); - if(dt > 0) - { - self.WEP_AMMO(VORTEX) = max(WEP_CVAR_SEC(vortex, ammo), self.WEP_AMMO(VORTEX) - WEP_CVAR_SEC(vortex, ammo) * dt); - } - } - } - self.vortex_charge += dt * WEP_CVAR(vortex, charge_rate); - } - } - - else - { - dt = min(dt, (1 - self.vortex_charge) / WEP_CVAR(vortex, charge_rate)); - self.vortex_charge += dt * WEP_CVAR(vortex, charge_rate); - } - } - } - else if(WEP_CVAR(vortex, secondary)) - { - if(weapon_prepareattack(0, WEP_CVAR_SEC(vortex, refire))) - { - W_Vortex_Attack(1); - weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_SEC(vortex, animtime), w_ready); - } - } - } - } - - return TRUE; - } - case WR_INIT: - { - precache_model("models/nexflash.md3"); - precache_model("models/weapons/g_nex.md3"); - precache_model("models/weapons/v_nex.md3"); - precache_model("models/weapons/h_nex.iqm"); - precache_sound("weapons/nexfire.wav"); - precache_sound("weapons/nexcharge.wav"); - precache_sound("weapons/nexwhoosh1.wav"); - precache_sound("weapons/nexwhoosh2.wav"); - precache_sound("weapons/nexwhoosh3.wav"); - VORTEX_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP) - return TRUE; - } - case WR_CHECKAMMO1: - { - ammo_amount = self.WEP_AMMO(VORTEX) >= WEP_CVAR_PRI(vortex, ammo); - ammo_amount += (autocvar_g_balance_vortex_reload_ammo && self.(weapon_load[WEP_VORTEX]) >= WEP_CVAR_PRI(vortex, ammo)); - return ammo_amount; - } - case WR_CHECKAMMO2: - { - if(WEP_CVAR(vortex, secondary)) - { - // don't allow charging if we don't have enough ammo - ammo_amount = self.WEP_AMMO(VORTEX) >= WEP_CVAR_SEC(vortex, ammo); - ammo_amount += self.(weapon_load[WEP_VORTEX]) >= WEP_CVAR_SEC(vortex, ammo); - return ammo_amount; - } - else - { - return FALSE; // zoom is not a fire mode - } - } - case WR_CONFIG: - { - VORTEX_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS) - return TRUE; - } - case WR_RELOAD: - { - W_Reload(min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo)), "weapons/reload.wav"); - return TRUE; - } - case WR_SUICIDEMESSAGE: - { - return WEAPON_THINKING_WITH_PORTALS; - } - case WR_KILLMESSAGE: - { - return WEAPON_VORTEX_MURDER; - } - } - return FALSE; -} -#endif -#ifdef CSQC -var float autocvar_g_balance_vortex_secondary = 0; // WEAPONTODO -float W_Vortex(float req) -{ - switch(req) - { - case WR_IMPACTEFFECT: - { - vector org2; - org2 = w_org + w_backoff * 6; - pointparticles(particleeffectnum("nex_impact"), org2, '0 0 0', 1); - if(!w_issilent) - sound(self, CH_SHOTS, "weapons/neximpact.wav", VOL_BASE, ATTN_NORM); - - return TRUE; - } - case WR_INIT: - { - precache_sound("weapons/neximpact.wav"); - if(autocvar_cl_reticle && autocvar_cl_reticle_weapon) - { - precache_pic("gfx/reticle_nex"); - } - return TRUE; - } - case WR_ZOOMRETICLE: - { - if(button_zoom || zoomscript_caught || (!WEP_CVAR(vortex, secondary) && button_attack2)) - { - reticle_image = "gfx/reticle_nex"; - return TRUE; - } - else - { - // no weapon specific image for this weapon - return FALSE; - } - } - } - return FALSE; -} -#endif -#endif diff --git a/qcsrc/common/weapons/weapons.qc b/qcsrc/common/weapons/weapons.qc deleted file mode 100644 index e45a901c3..000000000 --- a/qcsrc/common/weapons/weapons.qc +++ /dev/null @@ -1,321 +0,0 @@ -#ifndef MENUQC -#include "calculations.qc" -#endif -#include "all.qh" - -// WEAPON PLUGIN SYSTEM -entity weapon_info[WEP_MAXCOUNT]; -entity dummy_weapon_info; - -#if WEP_MAXCOUNT > 72 -# error Kein Weltraum links auf dem Gerät -#endif - -WepSet WepSet_FromWeapon(float a) { - a -= WEP_FIRST; -#if WEP_MAXCOUNT > 24 - if(a >= 24) { - a -= 24; -#if WEP_MAXCOUNT > 48 - if(a >= 24) { - a -= 24; - return '0 0 1' * power2of(a); - } -#endif - return '0 1 0' * power2of(a); - } -#endif - return '1 0 0' * power2of(a); -} -#ifdef SVQC -void WepSet_AddStat() -{ - addstat(STAT_WEAPONS, AS_INT, weapons_x); -#if WEP_MAXCOUNT > 24 - addstat(STAT_WEAPONS2, AS_INT, weapons_y); -#if WEP_MAXCOUNT > 48 - addstat(STAT_WEAPONS3, AS_INT, weapons_z); -#endif -#endif -} -void WriteWepSet(float dst, WepSet w) -{ -#if WEP_MAXCOUNT > 48 - WriteInt72_t(dst, w); -#elif WEP_MAXCOUNT > 24 - WriteInt48_t(dst, w); -#else - WriteInt24_t(dst, w_x); -#endif -} -#endif -#ifdef CSQC -WepSet WepSet_GetFromStat() -{ - WepSet w = '0 0 0'; - w_x = getstati(STAT_WEAPONS); -#if WEP_MAXCOUNT > 24 - w_y = getstati(STAT_WEAPONS2); -#if WEP_MAXCOUNT > 48 - w_z = getstati(STAT_WEAPONS3); -#endif -#endif - return w; -} -WepSet ReadWepSet() -{ -#if WEP_MAXCOUNT > 48 - return ReadInt72_t(); -#elif WEP_MAXCOUNT > 24 - return ReadInt48_t(); -#else - return ReadInt24_t() * '1 0 0'; -#endif -} -#endif - -void register_weapon( - float id, - WepSet bit, - float(float) func, - .float ammotype, - float i, - float weapontype, - float pickupbasevalue, - vector clr, - string modelname, - string simplemdl, - string crosshair, - string wepimg, - string refname, - string wepname) -{ - entity e; - weapon_info[id - 1] = e = spawn(); - e.classname = "weapon_info"; - e.weapon = id; - e.weapons = bit; - e.weapon_func = func; - e.ammo_field = ammotype; - e.impulse = i; - e.spawnflags = weapontype; - e.bot_pickupbasevalue = pickupbasevalue; - e.wpcolor = clr; - e.wpmodel = strzone(strcat("wpn-", ftos(id))); - e.mdl = modelname; - e.model = strzone(strcat("models/weapons/g_", modelname, ".md3")); - e.w_simplemdl = strzone(simplemdl); // simpleitems weapon model/image - e.w_crosshair = strzone(car(crosshair)); - string s = cdr(crosshair); - e.w_crosshair_size = ((s != "") ? stof(s) : 1); // so that we can scale the crosshair from code (for compat) - e.model2 = strzone(wepimg); - e.netname = refname; - e.message = wepname; - - #ifndef MENUQC - func(WR_INIT); - #endif -} -float w_null(float dummy) -{ - return 0; -} -void register_weapons_done() -{ - dummy_weapon_info = spawn(); - dummy_weapon_info.classname = "weapon_info"; - dummy_weapon_info.weapon = 0; // you can recognize dummies by this - dummy_weapon_info.weapons = '0 0 0'; - dummy_weapon_info.netname = ""; - dummy_weapon_info.message = "AOL CD Thrower"; - dummy_weapon_info.weapon_func = w_null; - dummy_weapon_info.wpmodel = ""; - dummy_weapon_info.mdl = ""; - dummy_weapon_info.model = ""; - dummy_weapon_info.spawnflags = 0; - dummy_weapon_info.impulse = -1; - dummy_weapon_info.bot_pickupbasevalue = 0; - dummy_weapon_info.ammo_field = ammo_none; - - dummy_weapon_info.w_crosshair = "gfx/crosshair1"; - dummy_weapon_info.w_crosshair_size = 1; - dummy_weapon_info.model2 = ""; - - float i; - weaponorder_byid = ""; - for(i = WEP_MAXCOUNT; i >= 1; --i) - if(weapon_info[i-1]) - weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i)); - weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1)); -} -entity get_weaponinfo(float id) -{ - entity w; - if(id < WEP_FIRST || id > WEP_LAST) - return dummy_weapon_info; - w = weapon_info[id - 1]; - if(w) - return w; - return dummy_weapon_info; -} -string W_FixWeaponOrder(string order, float complete) -{ - return fixPriorityList(order, WEP_FIRST, WEP_LAST, 230 - WEP_FIRST, complete); -} -string W_NameWeaponOrder_MapFunc(string s) -{ - entity wi; - if(s == "0" || stof(s)) - { - wi = get_weaponinfo(stof(s)); - if(wi != dummy_weapon_info) - return wi.netname; - } - return s; -} - -string W_UndeprecateName(string s) -{ - switch ( s ) - { - case "nex" : return "vortex"; - case "rocketlauncher" : return "devastator"; - case "laser" : return "blaster"; - case "minstanex" : return "vaporizer"; - case "grenadelauncher": return "mortar"; - case "uzi" : return "machinegun"; - default : return s; - } -} -string W_NameWeaponOrder(string order) -{ - return mapPriorityList(order, W_NameWeaponOrder_MapFunc); -} -string W_NumberWeaponOrder_MapFunc(string s) -{ - float i; - if(s == "0" || stof(s)) - return s; - s = W_UndeprecateName(s); - for(i = WEP_FIRST; i <= WEP_LAST; ++i) - if(s == get_weaponinfo(i).netname) - return ftos(i); - return s; -} -string W_NumberWeaponOrder(string order) -{ - return mapPriorityList(order, W_NumberWeaponOrder_MapFunc); -} - -float W_FixWeaponOrder_BuildImpulseList_buf[WEP_MAXCOUNT]; -string W_FixWeaponOrder_BuildImpulseList_order; -void W_FixWeaponOrder_BuildImpulseList_swap(float i, float j, entity pass) -{ - float h; - h = W_FixWeaponOrder_BuildImpulseList_buf[i]; - W_FixWeaponOrder_BuildImpulseList_buf[i] = W_FixWeaponOrder_BuildImpulseList_buf[j]; - W_FixWeaponOrder_BuildImpulseList_buf[j] = h; -} -float W_FixWeaponOrder_BuildImpulseList_cmp(float i, float j, entity pass) -{ - entity e1, e2; - float d; - e1 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[i]); - e2 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[j]); - d = mod(e1.impulse + 9, 10) - mod(e2.impulse + 9, 10); - if(d != 0) - return -d; // high impulse first! - return - strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[i]), 0) - - - strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[j]), 0) - ; // low char index first! -} -string W_FixWeaponOrder_BuildImpulseList(string o) -{ - float i; - W_FixWeaponOrder_BuildImpulseList_order = o; - for(i = WEP_FIRST; i <= WEP_LAST; ++i) - W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST] = i; - heapsort(WEP_LAST - WEP_FIRST + 1, W_FixWeaponOrder_BuildImpulseList_swap, W_FixWeaponOrder_BuildImpulseList_cmp, world); - o = ""; - for(i = WEP_FIRST; i <= WEP_LAST; ++i) - o = strcat(o, " ", ftos(W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST])); - W_FixWeaponOrder_BuildImpulseList_order = string_null; - return substring(o, 1, -1); -} - -string W_FixWeaponOrder_AllowIncomplete(string order) -{ - return W_FixWeaponOrder(order, 0); -} - -string W_FixWeaponOrder_ForceComplete(string order) -{ - if(order == "") - order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority")); - return W_FixWeaponOrder(order, 1); -} - -void W_RandomWeapons(entity e, float n) -{ - float i, j; - WepSet remaining; - WepSet result; - remaining = e.weapons; - result = '0 0 0'; - for(i = 0; i < n; ++i) - { - RandomSelection_Init(); - for(j = WEP_FIRST; j <= WEP_LAST; ++j) - if(remaining & WepSet_FromWeapon(j)) - RandomSelection_Add(world, j, string_null, 1, 1); - result |= WepSet_FromWeapon(RandomSelection_chosen_float); - remaining &= ~WepSet_FromWeapon(RandomSelection_chosen_float); - } - e.weapons = result; -} - -string GetAmmoPicture(.float ammotype) -{ - switch(ammotype) - { - case ammo_shells: return "ammo_shells"; - case ammo_nails: return "ammo_bullets"; - case ammo_rockets: return "ammo_rockets"; - case ammo_cells: return "ammo_cells"; - case ammo_plasma: return "ammo_cells"; - case ammo_fuel: return "ammo_fuel"; - default: return ""; // wtf, no ammo type? - } -} - -#ifdef CSQC -.float GetAmmoFieldFromNum(float i) -{ - switch(i) - { - case 0: return ammo_shells; - case 1: return ammo_nails; - case 2: return ammo_rockets; - case 3: return ammo_cells; - case 4: return ammo_plasma; - case 5: return ammo_fuel; - default: return ammo_none; - } -} - -float GetAmmoStat(.float ammotype) -{ - switch(ammotype) - { - case ammo_shells: return STAT_SHELLS; - case ammo_nails: return STAT_NAILS; - case ammo_rockets: return STAT_ROCKETS; - case ammo_cells: return STAT_CELLS; - case ammo_plasma: return STAT_PLASMA; - case ammo_fuel: return STAT_FUEL; - default: return -1; - } -} -#endif diff --git a/qcsrc/common/weapons/weapons.qh b/qcsrc/common/weapons/weapons.qh deleted file mode 100644 index af031086a..000000000 --- a/qcsrc/common/weapons/weapons.qh +++ /dev/null @@ -1,206 +0,0 @@ -#ifndef MENUQC -#include "calculations.qh" -#endif - -const float MAX_SHOT_DISTANCE = 32768; - -// weapon pickup ratings for bot logic -const float BOT_PICKUP_RATING_LOW = 2500; -const float BOT_PICKUP_RATING_MID = 5000; -const float BOT_PICKUP_RATING_HIGH = 10000; - -// weapon flags -const float WEP_TYPE_OTHER = 0x00; // not for damaging people -const float WEP_TYPE_SPLASH = 0x01; // splash damage -const float WEP_TYPE_HITSCAN = 0x02; // hitscan -const float WEP_TYPEMASK = 0x0F; -const float WEP_FLAG_CANCLIMB = 0x10; // can be used for movement -const float WEP_FLAG_NORMAL = 0x20; // in "most weapons" set -const float WEP_FLAG_HIDDEN = 0x40; // hides from menu -const float WEP_FLAG_RELOADABLE = 0x80; // can has reload -const float WEP_FLAG_SUPERWEAPON = 0x100; // powerup timer -const float WEP_FLAG_MUTATORBLOCKED = 0x200; // hides from impulse 99 etc. (mutators are allowed to clear this flag) - -// weapon requests -const float WR_SETUP = 1; // (SERVER) setup weapon data -const float WR_THINK = 2; // (SERVER) logic to run every frame -const float WR_CHECKAMMO1 = 3; // (SERVER) checks ammo for weapon primary -const float WR_CHECKAMMO2 = 4; // (SERVER) checks ammo for weapon second -const float WR_AIM = 5; // (SERVER) runs bot aiming code for this weapon -const float WR_INIT = 6; // (BOTH) precaches models/sounds used by this weapon, also sets up weapon properties -const float WR_SUICIDEMESSAGE = 7; // (SERVER) notification number for suicide message (may inspect w_deathtype for details) -const float WR_KILLMESSAGE = 8; // (SERVER) notification number for kill message (may inspect w_deathtype for details) -const float WR_RELOAD = 9; // (SERVER) handles reloading for weapon -const float WR_RESETPLAYER = 10; // (SERVER) clears fields that the weapon may use -const float WR_IMPACTEFFECT = 11; // (CLIENT) impact effect for weapon explosion -const float WR_PLAYERDEATH = 12; // (SERVER) called whenever a player dies -const float WR_GONETHINK = 13; // (SERVER) logic to run when weapon is lost -const float WR_CONFIG = 14; // (ALL) dump weapon cvars to config in data directory (see: sv_cmd dumpweapons) -const float WR_ZOOMRETICLE = 15; // (CLIENT) weapon specific zoom reticle - -// variables: -string weaponorder_byid; - -// weapon sets -typedef vector WepSet; -WepSet WepSet_FromWeapon(float a); -#ifdef SVQC -void WepSet_AddStat(); -void WriteWepSet(float dest, WepSet w); -#endif -#ifdef CSQC -WepSet WepSet_GetFromStat(); -WepSet ReadWepSet(); -#endif - -// weapon name macros -#define WEP_FIRST 1 -#define WEP_MAXCOUNT 24 // Increase as needed. Can be up to three times as much. -float WEP_COUNT; -float WEP_LAST; -WepSet WEPSET_ALL; -WepSet WEPSET_SUPERWEAPONS; - -// functions: -entity get_weaponinfo(float id); -string W_FixWeaponOrder(string order, float complete); -string W_NameWeaponOrder(string order); -string W_NumberWeaponOrder(string order); -string W_FixWeaponOrder_BuildImpulseList(string o); -string W_FixWeaponOrder_AllowIncomplete(string order); -string W_FixWeaponOrder_ForceComplete(string order); -void W_RandomWeapons(entity e, float n); - -string GetAmmoPicture(.float ammotype); - -#ifdef CSQC -.float GetAmmoFieldFromNum(float i); -float GetAmmoStat(.float ammotype); -#endif - -// ammo types -.float ammo_shells; -.float ammo_nails; -.float ammo_rockets; -.float ammo_cells; -.float ammo_plasma; -.float ammo_fuel; -.float ammo_none; - -// other useful macros -#define WEP_ACTION(wpn,wrequest) (get_weaponinfo(wpn)).weapon_func(wrequest) -#define WEP_AMMO(wpn) ((get_weaponinfo(WEP_##wpn)).ammo_field) // only used inside weapon files/with direct name, don't duplicate prefix -#define WEP_NAME(wpn) ((get_weaponinfo(wpn)).message) - - -// ====================== -// Configuration Macros -// ====================== - -// create cvars for weapon settings -#define WEP_ADD_CVAR_NONE(wepname,name) [[last]] float autocvar_g_balance_##wepname##_##name; - -#define WEP_ADD_CVAR_PRI(wepname,name) WEP_ADD_CVAR_NONE(wepname, primary_##name) -#define WEP_ADD_CVAR_SEC(wepname,name) WEP_ADD_CVAR_NONE(wepname, secondary_##name) -#define WEP_ADD_CVAR_BOTH(wepname,name) \ - WEP_ADD_CVAR_PRI(wepname, name) \ - WEP_ADD_CVAR_SEC(wepname, name) - -#define WEP_ADD_CVAR(wepid,wepname,mode,name) WEP_ADD_CVAR_##mode(wepname, name) - -// create properties for weapon settings -#define WEP_ADD_PROP(wepid,wepname,type,prop,name) \ - .type prop; \ - [[last]] type autocvar_g_balance_##wepname##_##name; - -// read cvars from weapon settings -#define WEP_CVAR(wepname,name) autocvar_g_balance_##wepname##_##name -#define WEP_CVAR_PRI(wepname,name) WEP_CVAR(wepname, primary_##name) -#define WEP_CVAR_SEC(wepname,name) WEP_CVAR(wepname, secondary_##name) -#define WEP_CVAR_BOTH(wepname,isprimary,name) ((isprimary) ? WEP_CVAR_PRI(wepname, name) : WEP_CVAR_SEC(wepname, name)) - -// set initialization values for weapon settings -#define WEP_SKIP_CVAR(unuseda,unusedb,unusedc,unusedd) /* skip cvars */ -#define WEP_SET_PROP(wepid,wepname,type,prop,name) get_weaponinfo(WEP_##wepid).##prop = autocvar_g_balance_##wepname##_##name; - - -// ===================== -// Weapon Registration -// ===================== - -float w_null(float dummy); - -void register_weapon( - float id, - WepSet bit, - float(float) func, - .float ammotype, - float i, - float weapontype, - float pickupbasevalue, - vector clr, - string modelname, - string simplemdl, - string crosshair, - string wepimg, - string refname, - string wepname); - -void register_weapons_done(); - -// entity properties of weaponinfo: -// fields which are explicitly/manually set are marked with "M", fields set automatically are marked with "A" -.float weapon; // M: WEP_id // WEP_... -.WepSet weapons; // A: WEPSET_id // WEPSET_... -.float(float) weapon_func; // M: function // w_... -..float ammo_field; // M: ammotype // main ammo field -.float impulse; // M: impulse // weapon impulse -.float spawnflags; // M: flags // WEPSPAWNFLAG_... combined -.float bot_pickupbasevalue; // M: rating // bot weapon priority -.vector wpcolor; // M: color // waypointsprite color -.string wpmodel; // A: wpn-id // wpn- sprite name -.string mdl; // M: modelname // name of model (without g_ v_ or h_ prefixes) -.string model; // A: modelname // full path to g_ model -.string w_simplemdl; // M: simplemdl // simpleitems weapon model/image -.string w_crosshair; // M: crosshair // per-weapon crosshair: "CrosshairImage Size" -.float w_crosshair_size; // A: crosshair // per-weapon crosshair size (argument two of "crosshair" field) -.string model2; // M: wepimg // "weaponfoobar" side view image file of weapon // WEAPONTODO: Move out of skin files, move to common files -.string netname; // M: refname // reference name name -.string message; // M: wepname // human readable name - - -// note: the fabs call is just there to hide "if result is constant" warning -#define REGISTER_WEAPON_2(id,bit,function,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname) \ - float id; \ - WepSet bit; \ - float function(float); \ - void RegisterWeapons_##id() \ - { \ - WEP_LAST = (id = WEP_FIRST + WEP_COUNT); \ - bit = WepSet_FromWeapon(id); \ - WEPSET_ALL |= bit; \ - if((flags) & WEP_FLAG_SUPERWEAPON) \ - WEPSET_SUPERWEAPONS |= bit; \ - ++WEP_COUNT; \ - register_weapon(id,bit,function,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname); \ - } \ - ACCUMULATE_FUNCTION(RegisterWeapons, RegisterWeapons_##id) -#ifdef MENUQC -#define REGISTER_WEAPON(id,function,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname) \ - REGISTER_WEAPON_2(WEP_##id,WEPSET_##id,w_null,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname) -#else -#define REGISTER_WEAPON(id,function,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname) \ - REGISTER_WEAPON_2(WEP_##id,WEPSET_##id,function,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname) -#endif - -#include "all.qh" - -#undef WEP_ADD_CVAR_MO_PRI -#undef WEP_ADD_CVAR_MO_SEC -#undef WEP_ADD_CVAR_MO_BOTH -#undef WEP_ADD_CVAR_MO_NONE -#undef WEP_ADD_CVAR -#undef WEP_ADD_PROP -#undef REGISTER_WEAPON - -ACCUMULATE_FUNCTION(RegisterWeapons, register_weapons_done); diff --git a/qcsrc/menu/progs.src b/qcsrc/menu/progs.src index 9d2f69333..86cb9621c 100644 --- a/qcsrc/menu/progs.src +++ b/qcsrc/menu/progs.src @@ -18,7 +18,7 @@ oo/base.h ../common/constants.qh ../common/mapinfo.qh ../common/campaign_common.qh -../common/weapons/weapons.qh // TODO +../common/items.qh ../common/counting.qh ../common/command/markup.qh ../common/command/rpn.qh @@ -51,7 +51,7 @@ xonotic/util.qc ../common/campaign_file.qc ../common/campaign_setup.qc ../common/mapinfo.qc -../common/weapons/weapons.qc // TODO +../common/items.qc ../common/urllib.qc ../common/monsters/monsters.qc diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c b/qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c index 2b4bb6b58..055f5449f 100644 --- a/qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c +++ b/qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c @@ -146,7 +146,7 @@ float checkCompatibility_weaponarena_weapon(entity me) return 0; if(cvar_string("g_weaponarena") == "0") return 0; - if(cvar_string("g_balance_blaster_weaponstart") == "0") + if(cvar_string("g_start_weapon_laser") == "0") return 0; return 1; } @@ -263,9 +263,9 @@ void XonoticMutatorsDialog_fill(entity me) setDependent(e, "g_nix", 1, 1); me.TR(me); me.TDempty(me, 0.2); - me.TD(me, 1, 1.8, e = makeXonoticRadioButton(1, "g_balance_blaster_weaponstart", "0", _("No start weapons"))); + me.TD(me, 1, 1.8, e = makeXonoticRadioButton(1, "g_start_weapon_laser", "0", _("No start weapons"))); e.cvarOffValue = "-1"; - makeMulti(e, "g_balance_shotgun_weaponstart g_balance_machinegun_weaponstart g_balance_devastator_weaponstart g_balance_minelayer_weaponstart g_balance_electro_weaponstart g_balance_crylink_weaponstart g_balance_hagar_weaponstart g_balance_porto_weaponstart g_balance_vaporizer_weaponstart g_balance_hook_weaponstart g_balance_rifle_weaponstart g_balance_fireball_weaponstart g_balance_seeker_weaponstart g_balance_tuba_weaponstart g_balance_shockwave_weaponstart g_balance_arc_weaponstart g_balance_vortex_weaponstart g_balance_mortar_weaponstart"); + 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_porto g_start_weapon_minstanex g_start_weapon_hook g_start_weapon_hlac g_start_weapon_rifle g_start_weapon_fireball g_start_weapon_seeker g_start_weapon_tuba"); me.gotoRC(me, me.rows - 1, 0); me.TD(me, 1, me.columns, e = makeXonoticButton(_("OK"), '0 0 0')); diff --git a/qcsrc/menu/xonotic/util.qc b/qcsrc/menu/xonotic/util.qc index 8b78a0f0a..74b60d30a 100644 --- a/qcsrc/menu/xonotic/util.qc +++ b/qcsrc/menu/xonotic/util.qc @@ -343,6 +343,7 @@ void UpdateNotification_URI_Get_Callback(float id, float status, string data) switch(substring(argv(i), 0, 1)) { + #define APPEND_TO_STRING(list,sep,add) ((list) = (((list) != "") ? strcat(list, sep, add) : (add))) case "V": { un_version = s; diff --git a/qcsrc/server/accuracy.qc b/qcsrc/server/accuracy.qc new file mode 100644 index 000000000..ca837e7d3 --- /dev/null +++ b/qcsrc/server/accuracy.qc @@ -0,0 +1,129 @@ +.float accuracy_hit[WEP_MAXCOUNT]; +.float accuracy_fired[WEP_MAXCOUNT]; +.float accuracy_cnt_hit[WEP_MAXCOUNT]; +.float accuracy_cnt_fired[WEP_MAXCOUNT]; + +float accuracy_byte(float n, float d) +{ + //printf("accuracy: %d / %d\n", n, d); + if(n <= 0) + return 0; + if(n > d) + return 255; + return 1 + rint(n * 100.0 / d); +} + +float accuracy_send(entity to, float sf) +{ + float w, f; + entity a; + WriteByte(MSG_ENTITY, ENT_CLIENT_ACCURACY); + + a = self.owner; + if(IS_SPEC(a)) + a = a.enemy; + a = a.accuracy; + + if(to != a.owner) + if (!(self.owner.cvar_cl_accuracy_data_share && autocvar_sv_accuracy_data_share)) + sf = 0; + // note: zero sendflags can never be sent... so we can use that to say that we send no accuracy! + WriteInt24_t(MSG_ENTITY, sf); + if(sf == 0) + return TRUE; + // note: we know that client and server agree about SendFlags... + for(w = 0, f = 1; w <= WEP_LAST - WEP_FIRST; ++w) + { + if(sf & f) + WriteByte(MSG_ENTITY, accuracy_byte(self.(accuracy_hit[w]), self.(accuracy_fired[w]))); + if(f == 0x800000) + f = 1; + else + f *= 2; + } + return TRUE; +} + +// init/free +void accuracy_init(entity e) +{ + e.accuracy = spawn(); + e.accuracy.owner = e; + e.accuracy.classname = "accuracy"; + e.accuracy.drawonlytoclient = e; + Net_LinkEntity(e.accuracy, FALSE, 0, accuracy_send); +} + +void accuracy_free(entity e) +{ + remove(e.accuracy); +} + +// force a resend of a player's accuracy stats +void accuracy_resend(entity e) +{ + e.accuracy.SendFlags = 0xFFFFFF; +} + +// update accuracy stats +.float hit_time; +.float fired_time; + +void accuracy_add(entity e, float w, float fired, float hit) +{ + entity a; + float b; + if(IS_INDEPENDENT_PLAYER(e)) + return; + a = e.accuracy; + if(!a || !(hit || fired)) + return; + w -= WEP_FIRST; + b = accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w])); + if(hit) + a.(accuracy_hit[w]) += hit; + if(fired) + a.(accuracy_fired[w]) += fired; + + if(hit && a.hit_time != time) // only run this once per frame + { + a.(accuracy_cnt_hit[w]) += 1; + a.hit_time = time; + } + + if(fired && a.fired_time != time) // only run this once per frame + { + a.(accuracy_cnt_fired[w]) += 1; + a.fired_time = time; + } + + if(b == accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w]))) + return; + w = pow(2, mod(w, 24)); + a.SendFlags |= w; + FOR_EACH_CLIENT(a) + if(IS_SPEC(a)) + if(a.enemy == e) + a.SendFlags |= w; +} + +float accuracy_isgooddamage(entity attacker, entity targ) +{ + frag_attacker = attacker; + frag_target = targ; + float mutator_check = MUTATOR_CALLHOOK(AccuracyTargetValid); + + if(!warmup_stage) + if(targ.deadflag == DEAD_NO) + if(mutator_check == MUT_ACCADD_INVALID || (mutator_check == MUT_ACCADD_VALID && IS_CLIENT(targ))) + if(DIFF_TEAM(attacker, targ)) + return TRUE; + return FALSE; +} + +float accuracy_canbegooddamage(entity attacker) +{ + if(!warmup_stage) + return TRUE; + return FALSE; +} diff --git a/qcsrc/server/accuracy.qh b/qcsrc/server/accuracy.qh new file mode 100644 index 000000000..90dbb663d --- /dev/null +++ b/qcsrc/server/accuracy.qh @@ -0,0 +1,15 @@ +.float cvar_cl_accuracy_data_share; + +// init/free +void accuracy_init(entity e); +void accuracy_free(entity e); + +// force a resend of a player's accuracy stats +void accuracy_resend(entity e); + +// update accuracy stats +void accuracy_add(entity e, float w, float fired, float hit); + +// helper +float accuracy_isgooddamage(entity attacker, entity targ); +float accuracy_canbegooddamage(entity attacker); diff --git a/qcsrc/server/antilag.qh b/qcsrc/server/antilag.qh index b89f12bb1..cadb45a14 100644 --- a/qcsrc/server/antilag.qh +++ b/qcsrc/server/antilag.qh @@ -5,7 +5,5 @@ void antilag_takeback(entity e, float t); void antilag_restore(entity e); void antilag_clear(entity e); -.float antilag_debug; - #define ANTILAG_LATENCY(e) min(0.4, e.ping * 0.001) // add one ticrate? diff --git a/qcsrc/server/autocvars.qh b/qcsrc/server/autocvars.qh index 92ff35897..11cf993df 100644 --- a/qcsrc/server/autocvars.qh +++ b/qcsrc/server/autocvars.qh @@ -80,6 +80,33 @@ float autocvar_g_balance_armor_rot; float autocvar_g_balance_armor_rotlinear; float autocvar_g_balance_armor_rotstable; float autocvar_g_balance_armor_start; +float autocvar_g_balance_rifle_bursttime; +float autocvar_g_balance_rifle_primary_ammo; +float autocvar_g_balance_rifle_primary_animtime; +float autocvar_g_balance_rifle_primary_bullethail; +float autocvar_g_balance_rifle_primary_burstcost; +float autocvar_g_balance_rifle_primary_damage; +float autocvar_g_balance_rifle_primary_force; +float autocvar_g_balance_rifle_primary_refire; +float autocvar_g_balance_rifle_primary_shots; +float autocvar_g_balance_rifle_primary_solidpenetration; +float autocvar_g_balance_rifle_primary_spread; +float autocvar_g_balance_rifle_primary_tracer; +float autocvar_g_balance_rifle_secondary; +float autocvar_g_balance_rifle_secondary_ammo; +float autocvar_g_balance_rifle_secondary_animtime; +float autocvar_g_balance_rifle_secondary_bullethail; +float autocvar_g_balance_rifle_secondary_burstcost; +float autocvar_g_balance_rifle_secondary_damage; +float autocvar_g_balance_rifle_secondary_force; +float autocvar_g_balance_rifle_secondary_reload; +float autocvar_g_balance_rifle_secondary_refire; +float autocvar_g_balance_rifle_secondary_shots; +float autocvar_g_balance_rifle_secondary_solidpenetration; +float autocvar_g_balance_rifle_secondary_spread; +float autocvar_g_balance_rifle_secondary_tracer; +float autocvar_g_balance_rifle_reload_ammo; +float autocvar_g_balance_rifle_reload_time; float autocvar_g_balance_cloaked_alpha; float autocvar_g_balance_contents_damagerate; float autocvar_g_balance_contents_drowndelay; @@ -87,11 +114,134 @@ float autocvar_g_balance_contents_playerdamage_drowning; float autocvar_g_balance_contents_playerdamage_lava; float autocvar_g_balance_contents_playerdamage_slime; float autocvar_g_balance_contents_projectiledamage; +float autocvar_g_balance_crylink_primary_ammo; +float autocvar_g_balance_crylink_primary_animtime; +float autocvar_g_balance_crylink_primary_bouncedamagefactor; +float autocvar_g_balance_crylink_primary_bounces; +float autocvar_g_balance_crylink_primary_damage; +float autocvar_g_balance_crylink_primary_edgedamage; +float autocvar_g_balance_crylink_primary_force; +float autocvar_g_balance_crylink_primary_joindelay; +float autocvar_g_balance_crylink_primary_joinexplode; +float autocvar_g_balance_crylink_primary_joinexplode_damage; +float autocvar_g_balance_crylink_primary_joinexplode_edgedamage; +float autocvar_g_balance_crylink_primary_joinexplode_force; +float autocvar_g_balance_crylink_primary_joinexplode_radius; +float autocvar_g_balance_crylink_primary_joinspread; +float autocvar_g_balance_crylink_primary_linkexplode; +float autocvar_g_balance_crylink_primary_middle_fadetime; +float autocvar_g_balance_crylink_primary_middle_lifetime; +float autocvar_g_balance_crylink_primary_other_fadetime; +float autocvar_g_balance_crylink_primary_other_lifetime; +float autocvar_g_balance_crylink_primary_radius; +float autocvar_g_balance_crylink_primary_refire; +float autocvar_g_balance_crylink_primary_shots; +float autocvar_g_balance_crylink_primary_speed; +float autocvar_g_balance_crylink_primary_spread; +float autocvar_g_balance_crylink_secondary; +float autocvar_g_balance_crylink_secondary_ammo; +float autocvar_g_balance_crylink_secondary_animtime; +float autocvar_g_balance_crylink_secondary_bouncedamagefactor; +float autocvar_g_balance_crylink_secondary_bounces; +float autocvar_g_balance_crylink_secondary_damage; +float autocvar_g_balance_crylink_secondary_edgedamage; +float autocvar_g_balance_crylink_secondary_force; +float autocvar_g_balance_crylink_secondary_joindelay; +float autocvar_g_balance_crylink_secondary_joinexplode; +float autocvar_g_balance_crylink_secondary_joinexplode_damage; +float autocvar_g_balance_crylink_secondary_joinexplode_edgedamage; +float autocvar_g_balance_crylink_secondary_joinexplode_force; +float autocvar_g_balance_crylink_secondary_joinexplode_radius; +float autocvar_g_balance_crylink_secondary_joinspread; +float autocvar_g_balance_crylink_secondary_line_fadetime; +float autocvar_g_balance_crylink_secondary_line_lifetime; +float autocvar_g_balance_crylink_secondary_linkexplode; +float autocvar_g_balance_crylink_secondary_middle_fadetime; +float autocvar_g_balance_crylink_secondary_middle_lifetime; +float autocvar_g_balance_crylink_secondary_radius; +float autocvar_g_balance_crylink_secondary_refire; +float autocvar_g_balance_crylink_secondary_shots; +float autocvar_g_balance_crylink_secondary_speed; +float autocvar_g_balance_crylink_secondary_spread; +float autocvar_g_balance_crylink_secondary_spreadtype; +float autocvar_g_balance_crylink_reload_ammo; +float autocvar_g_balance_crylink_reload_time; float autocvar_g_balance_damagepush_speedfactor; +float autocvar_g_balance_electro_combo_comboradius; +float autocvar_g_balance_electro_combo_damage; +float autocvar_g_balance_electro_combo_edgedamage; +float autocvar_g_balance_electro_combo_force; +float autocvar_g_balance_electro_combo_radius; +float autocvar_g_balance_electro_combo_speed; +float autocvar_g_balance_electro_combo_safeammocheck; +float autocvar_g_balance_electro_lightning; +float autocvar_g_balance_electro_primary_ammo; +float autocvar_g_balance_electro_primary_animtime; +float autocvar_g_balance_electro_primary_comboradius; +float autocvar_g_balance_electro_primary_damage; +float autocvar_g_balance_electro_primary_edgedamage; +float autocvar_g_balance_electro_primary_falloff_halflifedist; +float autocvar_g_balance_electro_primary_falloff_maxdist; +float autocvar_g_balance_electro_primary_falloff_mindist; +float autocvar_g_balance_electro_primary_force; +float autocvar_g_balance_electro_primary_force_up; +float autocvar_g_balance_electro_primary_lifetime; +float autocvar_g_balance_electro_primary_radius; +float autocvar_g_balance_electro_primary_range; +float autocvar_g_balance_electro_primary_refire; +float autocvar_g_balance_electro_primary_speed; +float autocvar_g_balance_electro_secondary_ammo; +float autocvar_g_balance_electro_secondary_animtime; +float autocvar_g_balance_electro_secondary_bouncefactor; +float autocvar_g_balance_electro_secondary_bouncestop; +float autocvar_g_balance_electro_secondary_count; +float autocvar_g_balance_electro_secondary_damage; +float autocvar_g_balance_electro_secondary_damageforcescale; +float autocvar_g_balance_electro_secondary_damagedbycontents; +float autocvar_g_balance_electro_secondary_edgedamage; +float autocvar_g_balance_electro_secondary_force; +float autocvar_g_balance_electro_secondary_health; +float autocvar_g_balance_electro_secondary_lifetime; +float autocvar_g_balance_electro_secondary_radius; +float autocvar_g_balance_electro_secondary_refire; +float autocvar_g_balance_electro_secondary_refire2; +float autocvar_g_balance_electro_secondary_speed; +float autocvar_g_balance_electro_reload_ammo; +float autocvar_g_balance_electro_reload_time; float autocvar_g_balance_falldamage_deadminspeed; float autocvar_g_balance_falldamage_factor; float autocvar_g_balance_falldamage_maxdamage; float autocvar_g_balance_falldamage_minspeed; +float autocvar_g_balance_fireball_primary_animtime; +float autocvar_g_balance_fireball_primary_bfgdamage; +float autocvar_g_balance_fireball_primary_bfgforce; +float autocvar_g_balance_fireball_primary_bfgradius; +float autocvar_g_balance_fireball_primary_damage; +float autocvar_g_balance_fireball_primary_damageforcescale; +float autocvar_g_balance_fireball_primary_edgedamage; +float autocvar_g_balance_fireball_primary_force; +float autocvar_g_balance_fireball_primary_health; +float autocvar_g_balance_fireball_primary_laserburntime; +float autocvar_g_balance_fireball_primary_laserdamage; +float autocvar_g_balance_fireball_primary_laseredgedamage; +float autocvar_g_balance_fireball_primary_laserradius; +float autocvar_g_balance_fireball_primary_lifetime; +float autocvar_g_balance_fireball_primary_radius; +float autocvar_g_balance_fireball_primary_refire; +float autocvar_g_balance_fireball_primary_refire2; +float autocvar_g_balance_fireball_primary_speed; +float autocvar_g_balance_fireball_secondary_animtime; +float autocvar_g_balance_fireball_secondary_damage; +float autocvar_g_balance_fireball_secondary_damageforcescale; +float autocvar_g_balance_fireball_secondary_damagetime; +float autocvar_g_balance_fireball_secondary_laserburntime; +float autocvar_g_balance_fireball_secondary_laserdamage; +float autocvar_g_balance_fireball_secondary_laseredgedamage; +float autocvar_g_balance_fireball_secondary_laserradius; +float autocvar_g_balance_fireball_secondary_lifetime; +float autocvar_g_balance_fireball_secondary_refire; +float autocvar_g_balance_fireball_secondary_speed; +float autocvar_g_balance_fireball_secondary_speed_up; float autocvar_g_balance_firetransfer_damage; float autocvar_g_balance_firetransfer_time; float autocvar_g_balance_fuel_limit; @@ -111,6 +261,75 @@ float autocvar_g_balance_grapplehook_speed_pull; float autocvar_g_balance_grapplehook_stretch; float autocvar_g_balance_grapplehook_damagedbycontents; float autocvar_g_balance_grapplehook_refire; +float autocvar_g_balance_grenadelauncher_bouncefactor; +float autocvar_g_balance_grenadelauncher_bouncestop; +float autocvar_g_balance_grenadelauncher_primary_ammo; +float autocvar_g_balance_grenadelauncher_primary_animtime; +float autocvar_g_balance_grenadelauncher_primary_damage; +float autocvar_g_balance_grenadelauncher_primary_damageforcescale; +float autocvar_g_balance_grenadelauncher_primary_edgedamage; +float autocvar_g_balance_grenadelauncher_primary_force; +float autocvar_g_balance_grenadelauncher_primary_health; +float autocvar_g_balance_grenadelauncher_primary_lifetime; +float autocvar_g_balance_grenadelauncher_primary_lifetime_stick; +float autocvar_g_balance_grenadelauncher_primary_radius; +float autocvar_g_balance_grenadelauncher_primary_refire; +float autocvar_g_balance_grenadelauncher_primary_remote_minbouncecnt; +float autocvar_g_balance_grenadelauncher_primary_speed; +float autocvar_g_balance_grenadelauncher_primary_speed_up; +float autocvar_g_balance_grenadelauncher_primary_type; +float autocvar_g_balance_grenadelauncher_secondary_ammo; +float autocvar_g_balance_grenadelauncher_secondary_animtime; +float autocvar_g_balance_grenadelauncher_secondary_damage; +float autocvar_g_balance_grenadelauncher_secondary_damageforcescale; +float autocvar_g_balance_grenadelauncher_secondary_edgedamage; +float autocvar_g_balance_grenadelauncher_secondary_force; +float autocvar_g_balance_grenadelauncher_secondary_health; +float autocvar_g_balance_grenadelauncher_secondary_lifetime; +float autocvar_g_balance_grenadelauncher_secondary_lifetime_bounce; +float autocvar_g_balance_grenadelauncher_secondary_lifetime_stick; +float autocvar_g_balance_grenadelauncher_secondary_radius; +float autocvar_g_balance_grenadelauncher_secondary_refire; +float autocvar_g_balance_grenadelauncher_secondary_speed; +float autocvar_g_balance_grenadelauncher_secondary_speed_up; +float autocvar_g_balance_grenadelauncher_secondary_type; +float autocvar_g_balance_grenadelauncher_reload_ammo; +float autocvar_g_balance_grenadelauncher_reload_time; +float autocvar_g_balance_hagar_primary_ammo; +float autocvar_g_balance_hagar_primary_damage; +float autocvar_g_balance_hagar_primary_edgedamage; +float autocvar_g_balance_hagar_primary_force; +float autocvar_g_balance_hagar_primary_health; +float autocvar_g_balance_hagar_primary_damageforcescale; +float autocvar_g_balance_hagar_primary_lifetime; +float autocvar_g_balance_hagar_primary_radius; +float autocvar_g_balance_hagar_primary_refire; +float autocvar_g_balance_hagar_primary_speed; +float autocvar_g_balance_hagar_secondary; +float autocvar_g_balance_hagar_secondary_load; +float autocvar_g_balance_hagar_secondary_load_speed; +float autocvar_g_balance_hagar_secondary_load_spread; +float autocvar_g_balance_hagar_secondary_load_spread_bias; +float autocvar_g_balance_hagar_secondary_load_max; +float autocvar_g_balance_hagar_secondary_load_hold; +float autocvar_g_balance_hagar_secondary_load_releasedeath; +float autocvar_g_balance_hagar_secondary_load_abort; +float autocvar_g_balance_hagar_secondary_load_linkexplode; +float autocvar_g_balance_hagar_secondary_load_animtime; +float autocvar_g_balance_hagar_secondary_ammo; +float autocvar_g_balance_hagar_secondary_damage; +float autocvar_g_balance_hagar_secondary_edgedamage; +float autocvar_g_balance_hagar_secondary_force; +float autocvar_g_balance_hagar_secondary_health; +float autocvar_g_balance_hagar_secondary_damageforcescale; +float autocvar_g_balance_hagar_secondary_lifetime_min; +float autocvar_g_balance_hagar_secondary_lifetime_rand; +float autocvar_g_balance_hagar_secondary_radius; +float autocvar_g_balance_hagar_secondary_refire; +float autocvar_g_balance_hagar_secondary_speed; +float autocvar_g_balance_hagar_secondary_spread; +float autocvar_g_balance_hagar_reload_ammo; +float autocvar_g_balance_hagar_reload_time; float autocvar_g_balance_health_limit; float autocvar_g_balance_health_regen; float autocvar_g_balance_health_regenlinear; @@ -118,6 +337,54 @@ float autocvar_g_balance_health_regenstable; float autocvar_g_balance_health_rot; float autocvar_g_balance_health_rotlinear; float autocvar_g_balance_health_rotstable; +float autocvar_g_balance_hlac_primary_ammo; +float autocvar_g_balance_hlac_primary_animtime; +float autocvar_g_balance_hlac_primary_damage; +float autocvar_g_balance_hlac_primary_edgedamage; +float autocvar_g_balance_hlac_primary_force; +float autocvar_g_balance_hlac_primary_lifetime; +float autocvar_g_balance_hlac_primary_radius; +float autocvar_g_balance_hlac_primary_refire; +float autocvar_g_balance_hlac_primary_speed; +float autocvar_g_balance_hlac_primary_spread_add; +float autocvar_g_balance_hlac_primary_spread_crouchmod; +float autocvar_g_balance_hlac_primary_spread_max; +float autocvar_g_balance_hlac_primary_spread_min; +float autocvar_g_balance_hlac_secondary; +float autocvar_g_balance_hlac_secondary_ammo; +float autocvar_g_balance_hlac_secondary_animtime; +float autocvar_g_balance_hlac_secondary_damage; +float autocvar_g_balance_hlac_secondary_edgedamage; +float autocvar_g_balance_hlac_secondary_force; +float autocvar_g_balance_hlac_secondary_lifetime; +float autocvar_g_balance_hlac_secondary_radius; +float autocvar_g_balance_hlac_secondary_refire; +float autocvar_g_balance_hlac_secondary_shots; +float autocvar_g_balance_hlac_secondary_speed; +float autocvar_g_balance_hlac_secondary_spread; +float autocvar_g_balance_hlac_secondary_spread_crouchmod; +float autocvar_g_balance_hlac_reload_ammo; +float autocvar_g_balance_hlac_reload_time; +float autocvar_g_balance_hook_primary_animtime; +float autocvar_g_balance_hook_primary_fuel; +float autocvar_g_balance_hook_primary_hooked_fuel; +float autocvar_g_balance_hook_primary_hooked_time_free; +float autocvar_g_balance_hook_primary_hooked_time_max; +float autocvar_g_balance_hook_primary_refire; +float autocvar_g_balance_hook_secondary_ammo; +float autocvar_g_balance_hook_secondary_animtime; +float autocvar_g_balance_hook_secondary_damage; +float autocvar_g_balance_hook_secondary_duration; +float autocvar_g_balance_hook_secondary_edgedamage; +float autocvar_g_balance_hook_secondary_force; +float autocvar_g_balance_hook_secondary_gravity; +float autocvar_g_balance_hook_secondary_lifetime; +float autocvar_g_balance_hook_secondary_power; +float autocvar_g_balance_hook_secondary_radius; +float autocvar_g_balance_hook_secondary_refire; +float autocvar_g_balance_hook_secondary_speed; +float autocvar_g_balance_hook_secondary_health; +float autocvar_g_balance_hook_secondary_damageforcescale; float autocvar_g_balance_keyhunt_damageforcescale; float autocvar_g_balance_keyhunt_delay_collect; float autocvar_g_balance_keyhunt_delay_return; @@ -135,6 +402,102 @@ float autocvar_g_balance_keyhunt_score_push; float autocvar_g_balance_keyhunt_throwvelocity; float autocvar_g_balance_kill_delay; float autocvar_g_balance_kill_antispam; +float autocvar_g_balance_laser_primary_animtime; +float autocvar_g_balance_laser_primary_damage; +float autocvar_g_balance_laser_primary_delay; +float autocvar_g_balance_laser_primary_edgedamage; +float autocvar_g_balance_laser_primary_force; +float autocvar_g_balance_laser_primary_force_other_scale; +float autocvar_g_balance_laser_primary_force_velocitybias; +float autocvar_g_balance_laser_primary_force_zscale; +float autocvar_g_balance_laser_primary_lifetime; +float autocvar_g_balance_laser_primary_radius; +float autocvar_g_balance_laser_primary_refire; +float autocvar_g_balance_laser_primary_shotangle; +float autocvar_g_balance_laser_primary_speed; +float autocvar_g_balance_laser_secondary; +float autocvar_g_balance_laser_secondary_animtime; +float autocvar_g_balance_laser_secondary_damage; +float autocvar_g_balance_laser_secondary_edgedamage; +float autocvar_g_balance_laser_secondary_force; +float autocvar_g_balance_laser_secondary_force_other_scale; +float autocvar_g_balance_laser_secondary_force_velocitybias; +float autocvar_g_balance_laser_secondary_force_zscale; +float autocvar_g_balance_laser_secondary_lifetime; +float autocvar_g_balance_laser_secondary_radius; +float autocvar_g_balance_laser_secondary_speed; +float autocvar_g_balance_laser_reload_ammo; +float autocvar_g_balance_laser_reload_time; +float autocvar_g_balance_minelayer_ammo; +float autocvar_g_balance_minelayer_animtime; +float autocvar_g_balance_minelayer_damage; +float autocvar_g_balance_minelayer_damageforcescale; +float autocvar_g_balance_minelayer_detonatedelay; +float autocvar_g_balance_minelayer_edgedamage; +float autocvar_g_balance_minelayer_force; +float autocvar_g_balance_minelayer_health; +float autocvar_g_balance_minelayer_lifetime; +float autocvar_g_balance_minelayer_lifetime_countdown; +float autocvar_g_balance_minelayer_limit; +float autocvar_g_balance_minelayer_protection; +float autocvar_g_balance_minelayer_proximityradius; +float autocvar_g_balance_minelayer_radius; +float autocvar_g_balance_minelayer_refire; +float autocvar_g_balance_minelayer_remote_damage; +float autocvar_g_balance_minelayer_remote_edgedamage; +float autocvar_g_balance_minelayer_remote_force; +float autocvar_g_balance_minelayer_remote_radius; +float autocvar_g_balance_minelayer_speed; +float autocvar_g_balance_minelayer_time; +float autocvar_g_balance_minelayer_reload_ammo; +float autocvar_g_balance_minelayer_reload_time; +float autocvar_g_balance_minstanex_ammo; +float autocvar_g_balance_minstanex_laser_ammo; +float autocvar_g_balance_minstanex_laser_animtime; +float autocvar_g_balance_minstanex_laser_refire; +float autocvar_g_balance_minstanex_animtime; +float autocvar_g_balance_minstanex_refire; +float autocvar_g_balance_minstanex_reload_ammo; +float autocvar_g_balance_minstanex_reload_time; +float autocvar_g_balance_nex_charge; +float autocvar_g_balance_nex_charge_animlimit; +float autocvar_g_balance_nex_charge_limit; +float autocvar_g_balance_nex_charge_maxspeed; +float autocvar_g_balance_nex_charge_mindmg; +float autocvar_g_balance_nex_charge_minspeed; +float autocvar_g_balance_nex_charge_rate; +float autocvar_g_balance_nex_charge_rot_pause; +float autocvar_g_balance_nex_charge_rot_rate; +float autocvar_g_balance_nex_charge_shot_multiplier; +float autocvar_g_balance_nex_charge_start; +float autocvar_g_balance_nex_charge_velocity_rate; +float autocvar_g_balance_nex_primary_ammo; +float autocvar_g_balance_nex_primary_animtime; +float autocvar_g_balance_nex_primary_damage; +float autocvar_g_balance_nex_primary_damagefalloff_forcehalflife; +float autocvar_g_balance_nex_primary_damagefalloff_halflife; +float autocvar_g_balance_nex_primary_damagefalloff_maxdist; +float autocvar_g_balance_nex_primary_damagefalloff_mindist; +float autocvar_g_balance_nex_primary_force; +float autocvar_g_balance_nex_primary_refire; +float autocvar_g_balance_nex_secondary; +float autocvar_g_balance_nex_secondary_ammo; +float autocvar_g_balance_nex_secondary_animtime; +float autocvar_g_balance_nex_secondary_charge; +float autocvar_g_balance_nex_secondary_charge_rate; +float autocvar_g_balance_nex_secondary_chargepool; +float autocvar_g_balance_nex_secondary_chargepool_pause_health_regen; +float autocvar_g_balance_nex_secondary_chargepool_pause_regen; +float autocvar_g_balance_nex_secondary_chargepool_regen; +float autocvar_g_balance_nex_secondary_damage; +float autocvar_g_balance_nex_secondary_damagefalloff_forcehalflife; +float autocvar_g_balance_nex_secondary_damagefalloff_halflife; +float autocvar_g_balance_nex_secondary_damagefalloff_maxdist; +float autocvar_g_balance_nex_secondary_damagefalloff_mindist; +float autocvar_g_balance_nex_secondary_force; +float autocvar_g_balance_nex_secondary_refire; +float autocvar_g_balance_nex_reload_ammo; +float autocvar_g_balance_nex_reload_time; float autocvar_g_balance_nexball_primary_animtime; float autocvar_g_balance_nexball_primary_refire; float autocvar_g_balance_nexball_primary_speed; @@ -144,13 +507,11 @@ float autocvar_g_balance_nexball_secondary_lifetime; float autocvar_g_balance_nexball_secondary_refire; float autocvar_g_balance_nexball_secondary_speed; float autocvar_g_balance_nix_ammo_cells; -float autocvar_g_balance_nix_ammo_plasma; float autocvar_g_balance_nix_ammo_fuel; float autocvar_g_balance_nix_ammo_nails; float autocvar_g_balance_nix_ammo_rockets; float autocvar_g_balance_nix_ammo_shells; float autocvar_g_balance_nix_ammoincr_cells; -float autocvar_g_balance_nix_ammoincr_plasma; float autocvar_g_balance_nix_ammoincr_fuel; float autocvar_g_balance_nix_ammoincr_nails; float autocvar_g_balance_nix_ammoincr_rockets; @@ -168,6 +529,15 @@ float autocvar_g_balance_pause_health_rot; float autocvar_g_balance_pause_health_rot_spawn; float autocvar_g_balance_portal_health; float autocvar_g_balance_portal_lifetime; +float autocvar_g_balance_porto_primary_animtime; +float autocvar_g_balance_porto_primary_lifetime; +float autocvar_g_balance_porto_primary_refire; +float autocvar_g_balance_porto_primary_speed; +float autocvar_g_balance_porto_secondary; +float autocvar_g_balance_porto_secondary_animtime; +float autocvar_g_balance_porto_secondary_lifetime; +float autocvar_g_balance_porto_secondary_refire; +float autocvar_g_balance_porto_secondary_speed; float autocvar_g_balance_powerup_invincible_takedamage; float autocvar_g_balance_powerup_invincible_time; float autocvar_g_balance_powerup_strength_damage; @@ -176,10 +546,133 @@ float autocvar_g_balance_powerup_strength_selfdamage; float autocvar_g_balance_powerup_strength_selfforce; float autocvar_g_balance_powerup_strength_time; float autocvar_g_balance_superweapons_time; +float autocvar_g_balance_rocketlauncher_ammo; +float autocvar_g_balance_rocketlauncher_animtime; +float autocvar_g_balance_rocketlauncher_damage; +float autocvar_g_balance_rocketlauncher_damageforcescale; +float autocvar_g_balance_rocketlauncher_detonatedelay; +float autocvar_g_balance_rocketlauncher_edgedamage; +float autocvar_g_balance_rocketlauncher_force; +float autocvar_g_balance_rocketlauncher_guidedelay; +float autocvar_g_balance_rocketlauncher_guidegoal; +float autocvar_g_balance_rocketlauncher_guiderate; +float autocvar_g_balance_rocketlauncher_guideratedelay; +float autocvar_g_balance_rocketlauncher_guidestop; +float autocvar_g_balance_rocketlauncher_health; +float autocvar_g_balance_rocketlauncher_lifetime; +float autocvar_g_balance_rocketlauncher_radius; +float autocvar_g_balance_rocketlauncher_refire; +float autocvar_g_balance_rocketlauncher_remote_damage; +float autocvar_g_balance_rocketlauncher_remote_edgedamage; +float autocvar_g_balance_rocketlauncher_remote_force; +float autocvar_g_balance_rocketlauncher_remote_radius; +float autocvar_g_balance_rocketlauncher_speed; +float autocvar_g_balance_rocketlauncher_speedaccel; +float autocvar_g_balance_rocketlauncher_speedstart; +float autocvar_g_balance_rocketlauncher_reload_ammo; +float autocvar_g_balance_rocketlauncher_reload_time; +float autocvar_g_balance_seeker_type; +float autocvar_g_balance_seeker_flac_ammo; +float autocvar_g_balance_seeker_flac_animtime; +float autocvar_g_balance_seeker_flac_damage; +float autocvar_g_balance_seeker_flac_edgedamage; +float autocvar_g_balance_seeker_flac_force; +float autocvar_g_balance_seeker_flac_lifetime; +float autocvar_g_balance_seeker_flac_lifetime_rand; +float autocvar_g_balance_seeker_flac_radius; +float autocvar_g_balance_seeker_flac_refire; +float autocvar_g_balance_seeker_missile_accel; +float autocvar_g_balance_seeker_missile_ammo; +float autocvar_g_balance_seeker_missile_animtime; +float autocvar_g_balance_seeker_missile_count; +float autocvar_g_balance_seeker_missile_damage; +float autocvar_g_balance_seeker_missile_damageforcescale; +float autocvar_g_balance_seeker_missile_decel; +float autocvar_g_balance_seeker_missile_delay; +float autocvar_g_balance_seeker_missile_edgedamage; +float autocvar_g_balance_seeker_missile_force; +float autocvar_g_balance_seeker_missile_health; +float autocvar_g_balance_seeker_missile_lifetime; +float autocvar_g_balance_seeker_missile_proxy; +float autocvar_g_balance_seeker_missile_proxy_delay; +float autocvar_g_balance_seeker_missile_proxy_maxrange; +float autocvar_g_balance_seeker_missile_radius; +float autocvar_g_balance_seeker_missile_refire; +float autocvar_g_balance_seeker_missile_smart; +float autocvar_g_balance_seeker_missile_smart_mindist; +float autocvar_g_balance_seeker_missile_smart_trace_max; +float autocvar_g_balance_seeker_missile_smart_trace_min; +float autocvar_g_balance_seeker_missile_speed_max; +float autocvar_g_balance_seeker_missile_turnrate; +float autocvar_g_balance_seeker_tag_ammo; +float autocvar_g_balance_seeker_tag_animtime; +float autocvar_g_balance_seeker_tag_damageforcescale; +float autocvar_g_balance_seeker_tag_health; +float autocvar_g_balance_seeker_tag_lifetime; +float autocvar_g_balance_seeker_tag_refire; +float autocvar_g_balance_seeker_tag_speed; +float autocvar_g_balance_seeker_tag_tracker_lifetime; +float autocvar_g_balance_seeker_reload_ammo; +float autocvar_g_balance_seeker_reload_time; float autocvar_g_balance_selfdamagepercent; +float autocvar_g_balance_shotgun_primary_ammo; +float autocvar_g_balance_shotgun_primary_animtime; +float autocvar_g_balance_shotgun_primary_bullets; +float autocvar_g_balance_shotgun_primary_damage; +float autocvar_g_balance_shotgun_primary_force; +float autocvar_g_balance_shotgun_primary_refire; +float autocvar_g_balance_shotgun_primary_solidpenetration; +float autocvar_g_balance_shotgun_primary_spread; +float autocvar_g_balance_shotgun_secondary; +float autocvar_g_balance_shotgun_secondary_animtime; +float autocvar_g_balance_shotgun_secondary_damage; +float autocvar_g_balance_shotgun_secondary_force; +float autocvar_g_balance_shotgun_secondary_melee_delay; +float autocvar_g_balance_shotgun_secondary_melee_range; +float autocvar_g_balance_shotgun_secondary_melee_swing_side; +float autocvar_g_balance_shotgun_secondary_melee_swing_up; +float autocvar_g_balance_shotgun_secondary_melee_time; +float autocvar_g_balance_shotgun_secondary_melee_traces; +float autocvar_g_balance_shotgun_secondary_melee_no_doubleslap; +float autocvar_g_balance_shotgun_secondary_melee_nonplayerdamage; +float autocvar_g_balance_shotgun_secondary_melee_multihit; +float autocvar_g_balance_shotgun_secondary_refire; +float autocvar_g_balance_shotgun_reload_ammo; +float autocvar_g_balance_shotgun_reload_time; float autocvar_g_balance_teams; float autocvar_g_balance_teams_prevent_imbalance; float autocvar_g_balance_teams_scorefactor; +float autocvar_g_balance_tuba_animtime; +float autocvar_g_balance_tuba_attenuation; +float autocvar_g_balance_tuba_damage; +float autocvar_g_balance_tuba_edgedamage; +float autocvar_g_balance_tuba_force; +float autocvar_g_balance_tuba_radius; +float autocvar_g_balance_tuba_refire; +float autocvar_g_balance_uzi_burst; +float autocvar_g_balance_uzi_burst_ammo; +float autocvar_g_balance_uzi_burst_animtime; +float autocvar_g_balance_uzi_burst_refire; +float autocvar_g_balance_uzi_burst_refire2; +float autocvar_g_balance_uzi_burst_spread; +float autocvar_g_balance_uzi_first; +float autocvar_g_balance_uzi_first_ammo; +float autocvar_g_balance_uzi_first_damage; +float autocvar_g_balance_uzi_first_force; +float autocvar_g_balance_uzi_first_refire; +float autocvar_g_balance_uzi_first_spread; +float autocvar_g_balance_uzi_mode; +float autocvar_g_balance_uzi_solidpenetration; +float autocvar_g_balance_uzi_spread_add; +float autocvar_g_balance_uzi_spread_max; +float autocvar_g_balance_uzi_spread_min; +float autocvar_g_balance_uzi_sustained_ammo; +float autocvar_g_balance_uzi_sustained_damage; +float autocvar_g_balance_uzi_sustained_force; +float autocvar_g_balance_uzi_sustained_refire; +float autocvar_g_balance_uzi_sustained_spread; +float autocvar_g_balance_uzi_reload_ammo; +float autocvar_g_balance_uzi_reload_time; float autocvar_g_ballistics_density_corpse; float autocvar_g_ballistics_density_player; float autocvar_g_ballistics_mindistance; @@ -438,7 +931,6 @@ float autocvar_g_onslaught_cp_health; float autocvar_g_onslaught_cp_regen; float autocvar_g_onslaught_gen_health; float autocvar_g_pickup_cells_max; -float autocvar_g_pickup_plasma_max; float autocvar_g_pickup_fuel_max; float autocvar_g_pickup_items; float autocvar_g_pickup_nails_max; @@ -479,6 +971,7 @@ float autocvar_g_spawn_furthest; float autocvar_g_spawn_useallspawns; float autocvar_g_spawnpoints_auto_move_out_of_solid; #define autocvar_g_spawnshieldtime cvar("g_spawnshieldtime") +#define autocvar_g_start_weapon_laser cvar("g_start_weapon_laser") float autocvar_g_tdm_team_spawns; float autocvar_g_tdm_point_limit; float autocvar_g_tdm_point_leadlimit; @@ -651,7 +1144,7 @@ float autocvar_sv_maxairstrafespeed; float autocvar_sv_maxspeed; string autocvar_sv_motd; float autocvar_sv_precacheplayermodels; -//float autocvar_sv_precacheweapons; // WEAPONTODO? +float autocvar_sv_precacheweapons; float autocvar_sv_q3acompat_machineshotgunswap; float autocvar_sv_ready_restart; float autocvar_sv_ready_restart_after_countdown; diff --git a/qcsrc/server/bot/aim.qc b/qcsrc/server/bot/aim.qc index 0ae331247..61f4ab5e8 100644 --- a/qcsrc/server/bot/aim.qc +++ b/qcsrc/server/bot/aim.qc @@ -339,12 +339,12 @@ float bot_aim(float shotspeed, float shotspeedupward, float maxshottime, float a shotspeedupward *= g_weaponspeedfactor; if (!shotspeed) { - dprint("bot_aim: WARNING: weapon ", WEP_NAME(self.weapon), " shotspeed is zero!\n"); + dprint("bot_aim: WARNING: weapon ", W_Name(self.weapon), " shotspeed is zero!\n"); shotspeed = 1000000; } if (!maxshottime) { - dprint("bot_aim: WARNING: weapon ", WEP_NAME(self.weapon), " maxshottime is zero!\n"); + dprint("bot_aim: WARNING: weapon ", W_Name(self.weapon), " maxshottime is zero!\n"); maxshottime = 1; } makevectors(self.v_angle); diff --git a/qcsrc/server/bot/havocbot/havocbot.qc b/qcsrc/server/bot/havocbot/havocbot.qc index 2ce9706a2..2e57eecb3 100644 --- a/qcsrc/server/bot/havocbot/havocbot.qc +++ b/qcsrc/server/bot/havocbot/havocbot.qc @@ -92,7 +92,7 @@ void havocbot_ai() if(self.weapons) { - WEP_ACTION(self.weapon, WR_AIM); + weapon_action(self.weapon, WR_AIM); if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(self)) { self.BUTTON_ATCK = FALSE; @@ -164,7 +164,7 @@ void havocbot_ai() for(i = WEP_FIRST; i <= WEP_LAST; ++i) { e = get_weaponinfo(i); - if ((self.weapons & WepSet_FromWeapon(i)) && (e.spawnflags & WEP_FLAG_RELOADABLE) && (self.weapon_load[i] < e.reloading_ammo)) + if ((self.weapons & WepSet_FromWeapon(i)) && (e.spawnflags & WEP_FLAG_RELOADABLE) && (self.weapon_load[i] < cvar(strcat("g_balance_", e.netname, "_reload_ammo")))) self.switchweapon = i; } } @@ -590,10 +590,10 @@ void havocbot_movetogoal() return; } - else if(self.health>WEP_CVAR(devastator, damage)*0.5) + else if(self.health>autocvar_g_balance_rocketlauncher_damage*0.5) { if(self.velocity_z < 0) - if(client_hasweapon(self, WEP_DEVASTATOR, TRUE, FALSE)) + if(client_hasweapon(self, WEP_ROCKET_LAUNCHER, TRUE, FALSE)) { self.movement_x = maxspeed; @@ -607,10 +607,10 @@ void havocbot_movetogoal() return; } - self.switchweapon = WEP_DEVASTATOR; + self.switchweapon = WEP_ROCKET_LAUNCHER; self.v_angle_x = 90; self.BUTTON_ATCK = TRUE; - self.rocketjumptime = time + WEP_CVAR(devastator, detonatedelay); + self.rocketjumptime = time + autocvar_g_balance_rocketlauncher_detonatedelay; return; } } @@ -956,7 +956,7 @@ float havocbot_chooseweapon_checkreload(float new_weapon) for(i = WEP_FIRST; i <= WEP_LAST; ++i) { // if we are out of ammo for all other weapons, it's an emergency to switch to anything else - if (WEP_ACTION(i, WR_CHECKAMMO1) + WEP_ACTION(i, WR_CHECKAMMO2)) + if (weapon_action(i, WR_CHECKAMMO1) + weapon_action(i, WR_CHECKAMMO2)) other_weapon_available = TRUE; } if(other_weapon_available) @@ -982,7 +982,7 @@ void havocbot_chooseweapon() { // If no weapon was chosen get the first available weapon if(self.weapon==0) - for(i=WEP_BLASTER + 1; i < WEP_COUNT ; ++i) // Samual: This seems strange compared to other weapon loops... + for(i=WEP_LASER + 1; i < WEP_COUNT ; ++i) { if(client_hasweapon(self, i, TRUE, FALSE)) { diff --git a/qcsrc/server/bot/havocbot/roles.qc b/qcsrc/server/bot/havocbot/roles.qc index 7e3ddbb43..2104c3443 100644 --- a/qcsrc/server/bot/havocbot/roles.qc +++ b/qcsrc/server/bot/havocbot/roles.qc @@ -98,10 +98,7 @@ void havocbot_goalrating_items(float ratingscale, vector org, float sradius) if (head.ammo_rockets && player.ammo_rockets > self.ammo_rockets) continue; - if (head.ammo_cells && player.ammo_cells > self.ammo_cells) - continue; - - if (head.ammo_plasma && player.ammo_plasma > self.ammo_plasma) + if (head.ammo_cells && player.ammo_cells > self.ammo_cells ) continue; discard = FALSE; diff --git a/qcsrc/server/cheats.qc b/qcsrc/server/cheats.qc index 22b793d39..c4b3fe67d 100644 --- a/qcsrc/server/cheats.qc +++ b/qcsrc/server/cheats.qc @@ -140,7 +140,6 @@ float CheatImpulse(float i) self.personal.ammo_rockets = self.ammo_rockets; self.personal.ammo_nails = self.ammo_nails; self.personal.ammo_cells = self.ammo_cells; - self.personal.ammo_plasma = self.ammo_plasma; self.personal.ammo_shells = self.ammo_shells; self.personal.ammo_fuel = self.ammo_fuel; self.personal.health = self.health; @@ -198,7 +197,6 @@ float CheatImpulse(float i) self.ammo_rockets = self.personal.ammo_rockets; self.ammo_nails = self.personal.ammo_nails; self.ammo_cells = self.personal.ammo_cells; - self.ammo_plasma = self.personal.ammo_plasma; self.ammo_shells = self.personal.ammo_shells; self.ammo_fuel = self.personal.ammo_fuel; self.health = self.personal.health; @@ -266,7 +264,7 @@ float CheatImpulse(float i) e2 = spawn(); setorigin(e2, e.origin); - RadiusDamage(e2, self, 1000, 0, 128, world, world, 500, DEATH_CHEAT, e); + RadiusDamage(e2, self, 1000, 0, 128, world, 500, DEATH_CHEAT, e); remove(e2); print("404 Sportsmanship not found.\n"); diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc index 2167bdb55..b3c6b6577 100644 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@ -417,11 +417,11 @@ void PutClientInServer (void) self.effects |= EF_TELEPORT_BIT | EF_RESTARTANIM_BIT; self.air_finished = time + 12; self.dmg = 2; - if(WEP_CVAR(vortex, charge)) + if(autocvar_g_balance_nex_charge) { - if(WEP_CVAR_SEC(vortex, chargepool)) - self.vortex_chargepool_ammo = 1; - self.vortex_charge = WEP_CVAR(vortex, charge_start); + if(autocvar_g_balance_nex_secondary_chargepool) + self.nex_chargepool_ammo = 1; + self.nex_charge = autocvar_g_balance_nex_charge_start; } if(warmup_stage) @@ -430,7 +430,6 @@ void PutClientInServer (void) self.ammo_nails = warmup_start_ammo_nails; self.ammo_rockets = warmup_start_ammo_rockets; self.ammo_cells = warmup_start_ammo_cells; - self.ammo_plasma = warmup_start_ammo_plasma; self.ammo_fuel = warmup_start_ammo_fuel; self.health = warmup_start_health; self.armorvalue = warmup_start_armorvalue; @@ -442,7 +441,6 @@ void PutClientInServer (void) self.ammo_nails = start_ammo_nails; self.ammo_rockets = start_ammo_rockets; self.ammo_cells = start_ammo_cells; - self.ammo_plasma = start_ammo_plasma; self.ammo_fuel = start_ammo_fuel; self.health = start_health; self.armorvalue = start_armorvalue; @@ -454,13 +452,13 @@ void PutClientInServer (void) else self.superweapons_finished = 0; - if(g_weaponarena_random) // WEAPONTODO: more stuff that should be in a mutator. also: rename those cvars + if(g_weaponarena_random) { if(g_weaponarena_random_with_laser) - self.weapons &= ~WEPSET_BLASTER; + self.weapons &= ~WEPSET_LASER; W_RandomWeapons(self, g_weaponarena_random); if(g_weaponarena_random_with_laser) - self.weapons |= WEPSET_BLASTER; + self.weapons |= WEPSET_LASER; } self.items = start_items; @@ -565,13 +563,13 @@ void PutClientInServer (void) // reset fields the weapons may use for (j = WEP_FIRST; j <= WEP_LAST; ++j) { - WEP_ACTION(j, WR_RESETPLAYER); + weapon_action(j, WR_RESETPLAYER); // all weapons must be fully loaded when we spawn entity e; e = get_weaponinfo(j); if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars - self.(weapon_load[j]) = e.reloading_ammo; + self.(weapon_load[j]) = cvar(strcat("g_balance_", e.netname, "_reload_ammo")); } oldself = self; @@ -625,27 +623,30 @@ float ClientInit_SendEntity(entity to, float sf) WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[1])); WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[2])); WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[3])); - WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[0])); - WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[1])); - WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[2])); - WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[3])); - + WriteInt24_t(MSG_ENTITY, compressShotOrigin(electro_shotorigin[0])); + WriteInt24_t(MSG_ENTITY, compressShotOrigin(electro_shotorigin[1])); + WriteInt24_t(MSG_ENTITY, compressShotOrigin(electro_shotorigin[2])); + WriteInt24_t(MSG_ENTITY, compressShotOrigin(electro_shotorigin[3])); + WriteInt24_t(MSG_ENTITY, compressShotOrigin(gauntlet_shotorigin[0])); + WriteInt24_t(MSG_ENTITY, compressShotOrigin(gauntlet_shotorigin[1])); + WriteInt24_t(MSG_ENTITY, compressShotOrigin(gauntlet_shotorigin[2])); + WriteInt24_t(MSG_ENTITY, compressShotOrigin(gauntlet_shotorigin[3])); if(sv_foginterval && world.fog != "") WriteString(MSG_ENTITY, world.fog); else WriteString(MSG_ENTITY, ""); WriteByte(MSG_ENTITY, self.count * 255.0); // g_balance_armor_blockpercent - WriteCoord(MSG_ENTITY, self.bouncefactor); // g_balance_mortar_bouncefactor // WEAPONTODO - WriteCoord(MSG_ENTITY, self.bouncestop); // g_balance_mortar_bouncestop - WriteCoord(MSG_ENTITY, self.ebouncefactor); // g_balance_mortar_bouncefactor - WriteCoord(MSG_ENTITY, self.ebouncestop); // g_balance_mortar_bouncestop - WriteByte(MSG_ENTITY, WEP_CVAR(vortex, secondary)); // client has to know if it should zoom or not // WEAPONTODO - WriteByte(MSG_ENTITY, WEP_CVAR(rifle, secondary)); // client has to know if it should zoom or not // WEAPONTODO + WriteCoord(MSG_ENTITY, self.bouncefactor); // g_balance_grenadelauncher_bouncefactor + WriteCoord(MSG_ENTITY, self.bouncestop); // g_balance_grenadelauncher_bouncestop + WriteCoord(MSG_ENTITY, self.ebouncefactor); // g_balance_grenadelauncher_bouncefactor + WriteCoord(MSG_ENTITY, self.ebouncestop); // g_balance_grenadelauncher_bouncestop + WriteByte(MSG_ENTITY, autocvar_g_balance_nex_secondary); // client has to know if it should zoom or not + WriteByte(MSG_ENTITY, autocvar_g_balance_rifle_secondary); // client has to know if it should zoom or not WriteByte(MSG_ENTITY, serverflags); // client has to know if it should zoom or not - WriteByte(MSG_ENTITY, WEP_CVAR(minelayer, limit)); // minelayer max mines // WEAPONTODO - WriteByte(MSG_ENTITY, WEP_CVAR_SEC(hagar, load_max)); // hagar max loadable rockets // WEAPONTODO + WriteByte(MSG_ENTITY, autocvar_g_balance_minelayer_limit); // minelayer max mines + WriteByte(MSG_ENTITY, autocvar_g_balance_hagar_secondary_load_max); // hagar max loadable rockets WriteCoord(MSG_ENTITY, autocvar_g_trueaim_minrange); - WriteByte(MSG_ENTITY, WEP_CVAR(porto, secondary)); // WEAPONTODO + WriteByte(MSG_ENTITY, autocvar_g_balance_porto_secondary); return TRUE; } @@ -657,14 +658,14 @@ void ClientInit_CheckUpdate() self.count = autocvar_g_balance_armor_blockpercent; self.SendFlags |= 1; } - if(self.bouncefactor != autocvar_g_balance_mortar_bouncefactor) // WEAPONTODO + if(self.bouncefactor != autocvar_g_balance_grenadelauncher_bouncefactor) { - self.bouncefactor = autocvar_g_balance_mortar_bouncefactor; + self.bouncefactor = autocvar_g_balance_grenadelauncher_bouncefactor; self.SendFlags |= 1; } - if(self.bouncestop != autocvar_g_balance_mortar_bouncestop) + if(self.bouncestop != autocvar_g_balance_grenadelauncher_bouncestop) { - self.bouncestop = autocvar_g_balance_mortar_bouncestop; + self.bouncestop = autocvar_g_balance_grenadelauncher_bouncestop; self.SendFlags |= 1; } if(self.ebouncefactor != autocvar_g_balance_electro_secondary_bouncefactor) @@ -1191,7 +1192,13 @@ void ClientConnect (void) if(!sv_foginterval && world.fog != "") stuffcmd(self, strcat("\nfog ", world.fog, "\nr_fog_exp2 0\nr_drawfog 1\n")); - W_HitPlotOpen(self); + if(autocvar_g_hitplots || strstrofs(strcat(" ", autocvar_g_hitplots_individuals, " "), strcat(" ", self.netaddress, " "), 0) >= 0) + { + self.hitplotfh = fopen(strcat("hits-", matchid, "-", self.netaddress, "-", ftos(self.playerid), ".plot"), FILE_WRITE); + fputs(self.hitplotfh, strcat("#name ", self.netname, "\n")); + } + else + self.hitplotfh = -1; if(autocvar_sv_teamnagger && !(autocvar_bot_vs_human && (c3==-1 && c4==-1)) && !g_ca && !g_cts && !g_race) // teamnagger is currently bad for ca, race & cts send_CSQC_teamnagger(); @@ -1231,7 +1238,11 @@ void ClientDisconnect (void) CheatShutdownClient(); - W_HitPlotClose(self); + if(self.hitplotfh >= 0) + { + fclose(self.hitplotfh); + self.hitplotfh = -1; + } anticheat_report(); anticheat_shutdown(); @@ -1671,7 +1682,6 @@ void SpectateCopy(entity spectatee) { self.armortype = spectatee.armortype; self.armorvalue = spectatee.armorvalue; self.ammo_cells = spectatee.ammo_cells; - self.ammo_plasma = spectatee.ammo_plasma; self.ammo_shells = spectatee.ammo_shells; self.ammo_nails = spectatee.ammo_nails; self.ammo_rockets = spectatee.ammo_rockets; @@ -1692,8 +1702,8 @@ void SpectateCopy(entity spectatee) { self.switchweapon = spectatee.switchweapon; self.switchingweapon = spectatee.switchingweapon; self.weapon = spectatee.weapon; - self.vortex_charge = spectatee.vortex_charge; - self.vortex_chargepool_ammo = spectatee.vortex_chargepool_ammo; + self.nex_charge = spectatee.nex_charge; + self.nex_chargepool_ammo = spectatee.nex_chargepool_ammo; self.hagar_load = spectatee.hagar_load; self.minelayer_mines = spectatee.minelayer_mines; self.punchangle = spectatee.punchangle; @@ -2274,17 +2284,17 @@ void PlayerPreThink (void) if(frametime) { - if(self.weapon == WEP_VORTEX && WEP_CVAR(vortex, charge)) + if(self.weapon == WEP_NEX && autocvar_g_balance_nex_charge) { - self.weaponentity_glowmod_x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit)); - self.weaponentity_glowmod_y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit)); - self.weaponentity_glowmod_z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit)); + self.weaponentity_glowmod_x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_animlimit); + self.weaponentity_glowmod_y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_animlimit); + self.weaponentity_glowmod_z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_animlimit); - if(self.vortex_charge > WEP_CVAR(vortex, charge_animlimit)) + if(self.nex_charge > autocvar_g_balance_nex_charge_animlimit) { - self.weaponentity_glowmod_x = self.weaponentity_glowmod_x + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit)); - self.weaponentity_glowmod_y = self.weaponentity_glowmod_y + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit)); - self.weaponentity_glowmod_z = self.weaponentity_glowmod_z + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit)); + self.weaponentity_glowmod_x = self.weaponentity_glowmod_x + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (self.nex_charge - autocvar_g_balance_nex_charge_animlimit) / (1 - autocvar_g_balance_nex_charge_animlimit); + self.weaponentity_glowmod_y = self.weaponentity_glowmod_y + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (self.nex_charge - autocvar_g_balance_nex_charge_animlimit) / (1 - autocvar_g_balance_nex_charge_animlimit); + self.weaponentity_glowmod_z = self.weaponentity_glowmod_z + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (self.nex_charge - autocvar_g_balance_nex_charge_animlimit) / (1 - autocvar_g_balance_nex_charge_animlimit); } } else @@ -2367,10 +2377,7 @@ void PlayerPreThink (void) do_crouch = 0; if(self.frozen) do_crouch = 0; - - // WEAPONTODO: THIS SHIT NEEDS TO GO EVENTUALLY - // It cannot be predicted by the engine! - if((self.weapon == WEP_SHOCKWAVE || self.weapon == WEP_SHOTGUN) && self.weaponentity.wframe == WFRAME_FIRE2 && time < self.weapon_nextthink) + if(self.weapon == WEP_SHOTGUN && self.weaponentity.wframe == WFRAME_FIRE2 && time < self.weapon_nextthink) do_crouch = 0; if (do_crouch) @@ -2418,10 +2425,9 @@ void PlayerPreThink (void) player_regen(); - // WEAPONTODO: Add a weapon request for this // rot nex charge to the charge limit - if(WEP_CVAR(vortex, charge_rot_rate) && self.vortex_charge > WEP_CVAR(vortex, charge_limit) && self.vortex_charge_rottime < time) - self.vortex_charge = bound(WEP_CVAR(vortex, charge_limit), self.vortex_charge - WEP_CVAR(vortex, charge_rot_rate) * frametime / W_TICSPERFRAME, 1); + if(autocvar_g_balance_nex_charge_rot_rate && self.nex_charge > autocvar_g_balance_nex_charge_limit && self.nex_charge_rottime < time) + self.nex_charge = bound(autocvar_g_balance_nex_charge_limit, self.nex_charge - autocvar_g_balance_nex_charge_rot_rate * frametime / W_TICSPERFRAME, 1); if(frametime) player_anim(); @@ -2445,9 +2451,8 @@ void PlayerPreThink (void) SpectatorThink(); } - // WEAPONTODO: Add weapon request for this if(!zoomstate_set) - SetZoomState(self.BUTTON_ZOOM || self.BUTTON_ZOOMSCRIPT || (self.BUTTON_ATCK2 && self.weapon == WEP_VORTEX) || (self.BUTTON_ATCK2 && self.weapon == WEP_RIFLE && WEP_CVAR(rifle, secondary) == 0)); // WEAPONTODO + SetZoomState(self.BUTTON_ZOOM || self.BUTTON_ZOOMSCRIPT || (self.BUTTON_ATCK2 && self.weapon == WEP_NEX) || (self.BUTTON_ATCK2 && self.weapon == WEP_RIFLE && autocvar_g_balance_rifle_secondary == 0)); float oldspectatee_status; oldspectatee_status = self.spectatee_status; @@ -2487,7 +2492,6 @@ void PlayerPreThink (void) target_voicescript_next(self); - // WEAPONTODO: Move into weaponsystem somehow // if a player goes unarmed after holding a loaded weapon, empty his clip size and remove the crosshair ammo ring if(!self.weapon) self.clip_load = self.clip_size = 0; diff --git a/qcsrc/server/cl_impulse.qc b/qcsrc/server/cl_impulse.qc index c6ede7f98..c9896bc74 100644 --- a/qcsrc/server/cl_impulse.qc +++ b/qcsrc/server/cl_impulse.qc @@ -68,8 +68,8 @@ void ImpulseCommands (void) // weapon switching impulses if(self.deadflag == DEAD_NO) W_NextWeaponOnImpulse(imp); - //else - // self.impulse = imp; // retry in next frame + else + self.impulse = imp; // retry in next frame } else if(imp >= 10 && imp <= 20) { @@ -78,37 +78,37 @@ void ImpulseCommands (void) switch(imp) { case 10: - W_NextWeapon(0); + W_NextWeapon (0); break; case 11: W_LastWeapon(); break; case 12: - W_PreviousWeapon(0); + W_PreviousWeapon (0); break; case 13: - W_SwitchWeapon(w_getbestweapon(self)); + W_SwitchWeapon (w_getbestweapon(self)); break; case 14: W_NextWeaponOnImpulse(0); break; case 15: - W_NextWeapon(2); + W_NextWeapon (2); break; case 16: - W_PreviousWeapon(2); + W_PreviousWeapon (2); break; case 17: W_ThrowWeapon(W_CalculateProjectileVelocity(self.velocity, v_forward * 750, FALSE), '0 0 0', TRUE); break; case 18: - W_NextWeapon(1); + W_NextWeapon (1); break; case 19: - W_PreviousWeapon(1); + W_PreviousWeapon (1); break; case 20: - WEP_ACTION(self.weapon, WR_RELOAD); + W_TriggerReload (); break; } } diff --git a/qcsrc/server/cl_physics.qc b/qcsrc/server/cl_physics.qc index 0cae2a261..14747fa99 100644 --- a/qcsrc/server/cl_physics.qc +++ b/qcsrc/server/cl_physics.qc @@ -1301,16 +1301,15 @@ void SV_PlayerPhysics() } } - // WEAPONTODO float xyspeed; xyspeed = vlen('1 0 0' * self.velocity_x + '0 1 0' * self.velocity_y); - if(self.weapon == WEP_VORTEX && WEP_CVAR(vortex, charge) && WEP_CVAR(vortex, charge_velocity_rate) && xyspeed > WEP_CVAR(vortex, charge_minspeed)) + if(self.weapon == WEP_NEX && autocvar_g_balance_nex_charge && autocvar_g_balance_nex_charge_velocity_rate && xyspeed > autocvar_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, WEP_CVAR(vortex, charge_maxspeed)); - f = (xyspeed - WEP_CVAR(vortex, charge_minspeed)) / (WEP_CVAR(vortex, charge_maxspeed) - WEP_CVAR(vortex, charge_minspeed)); + xyspeed = min(xyspeed, autocvar_g_balance_nex_charge_maxspeed); + f = (xyspeed - autocvar_g_balance_nex_charge_minspeed) / (autocvar_g_balance_nex_charge_maxspeed - autocvar_g_balance_nex_charge_minspeed); // add the extra charge - self.vortex_charge = min(1, self.vortex_charge + WEP_CVAR(vortex, charge_velocity_rate) * f * frametime); + self.nex_charge = min(1, self.nex_charge + autocvar_g_balance_nex_charge_velocity_rate * f * frametime); } :end if(self.flags & FL_ONGROUND) diff --git a/qcsrc/server/cl_player.qc b/qcsrc/server/cl_player.qc index 7d7ba087a..c11e92051 100644 --- a/qcsrc/server/cl_player.qc +++ b/qcsrc/server/cl_player.qc @@ -1,3 +1,126 @@ +.entity accuracy; +.float accuracy_frags[WEP_MAXCOUNT]; + +float weaponstats_buffer; + +void WeaponStats_Init() +{ + if(autocvar_sv_weaponstats_file != "") + weaponstats_buffer = buf_create(); + else + weaponstats_buffer = -1; +} + +#define WEAPONSTATS_GETINDEX(awep,abot,vwep,vbot) (((vwep) + (awep) * (WEP_LAST - WEP_FIRST + 1) - (WEP_FIRST + WEP_FIRST * (WEP_LAST - WEP_FIRST + 1))) * 4 + (abot) * 2 + (vbot)) + +void WeaponStats_ready(entity fh, entity pass, float status) +{ + float i, j, n, ibot, jbot, idx; + vector v; + string prefix, s; + switch(status) + { + case URL_READY_CANWRITE: + // we can write + prefix = strcat(autocvar_hostname, "\t", GetGametype(), "_", GetMapname(), "\t"); + url_fputs(fh, "#begin statsfile\n"); + url_fputs(fh, strcat("#date ", strftime(TRUE, "%a %b %e %H:%M:%S %Z %Y"), "\n")); +#ifdef WATERMARK + url_fputs(fh, strcat("#version ", WATERMARK, "\n")); +#endif + url_fputs(fh, strcat("#config ", ftos(crc16(FALSE, cvar_purechanges)), "\n")); + url_fputs(fh, strcat("#cvar_purechanges ", ftos(cvar_purechanges_count), "\n")); + n = tokenizebyseparator(cvar_purechanges, "\n"); + for(i = 0; i < n; ++i) + url_fputs(fh, strcat("#cvar_purechange ", argv(i), "\n")); + for(i = WEP_FIRST; i <= WEP_LAST; ++i) for(ibot = 0; ibot <= 1; ++ibot) + for(j = WEP_FIRST; j <= WEP_LAST; ++j) for(jbot = 0; jbot <= 1; ++jbot) + { + idx = WEAPONSTATS_GETINDEX(i, ibot, j, jbot); + v = stov(bufstr_get(weaponstats_buffer, idx)); + if(v != '0 0 0') + { + //vector is: kills hits damage + url_fputs(fh, sprintf("%s%d %d\t%d %d\t", prefix, i, ibot, j, jbot)); + url_fputs(fh, sprintf("%d %d %g\n", v_x, v_y, v_z)); + } + } + url_fputs(fh, "#end\n\n"); + url_fclose(fh); + break; + case URL_READY_CANREAD: + // url_fclose is processing, we got a response for writing the data + // this must come from HTTP + print("Got response from weapon stats server:\n"); + while((s = url_fgets(fh))) + print(" ", s, "\n"); + print("End of response.\n"); + url_fclose(fh); + break; + case URL_READY_CLOSED: + // url_fclose has finished + print("Weapon stats written\n"); + buf_del(weaponstats_buffer); + weaponstats_buffer = -1; + break; + case URL_READY_ERROR: + default: + print("Weapon stats writing failed: ", ftos(status), "\n"); + buf_del(weaponstats_buffer); + weaponstats_buffer = -1; + break; + } +} + +void WeaponStats_Shutdown() +{ + if(weaponstats_buffer < 0) + return; + if(autocvar_sv_weaponstats_file != "") + { + url_multi_fopen(autocvar_sv_weaponstats_file, FILE_APPEND, WeaponStats_ready, world); + } + else + { + buf_del(weaponstats_buffer); + weaponstats_buffer = -1; + } +} + +void WeaponStats_LogItem(float awep, float abot, float vwep, float vbot, vector item) +{ + float idx; + if(weaponstats_buffer < 0) + return; + if(awep < WEP_FIRST || vwep < WEP_FIRST) + return; + if(awep > WEP_LAST || vwep > WEP_LAST) + return; + idx = WEAPONSTATS_GETINDEX(awep,abot,vwep,vbot); + bufstr_set(weaponstats_buffer, idx, vtos(stov(bufstr_get(weaponstats_buffer, idx)) + item)); +} +void WeaponStats_LogDamage(float awep, float abot, float vwep, float vbot, float damage) +{ + if(damage < 0) + error("negative damage?"); + WeaponStats_LogItem(awep, abot, vwep, vbot, '0 0 1' * damage + '0 1 0'); +} +void WeaponStats_LogKill(float awep, float abot, float vwep, float vbot) +{ + WeaponStats_LogItem(awep, abot, vwep, vbot, '1 0 0'); +} + +// changes by LordHavoc on 03/29/04 and 03/30/04 at Vermeulen's request +// merged player_run and player_stand to player_anim +// added death animations to player_anim +// can now spawn thrown weapons from anywhere, not just from players +// thrown weapons now fade out after 20 seconds +// created PlayerGib function +// PlayerDie no longer uses hitloc or damage +// PlayerDie now supports dying animations as well as gibbing +// cleaned up PlayerDie a lot +// added CopyBody + .entity pusher; .float pushltime; .float istypefrag; @@ -138,6 +261,13 @@ void player_anim (void) } } +void SpawnThrownWeapon (vector org, float w) +{ + if(self.weapons & WepSet_FromWeapon(self.weapon)) + if(W_IsWeaponThrowable(self.weapon)) + W_ThrowNewWeapon(self, self.weapon, FALSE, org, randomvec() * 125 + '0 0 200'); +} + void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) { float take, save; @@ -424,7 +554,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht } if(sound_allowed(MSG_BROADCAST, attacker)) - if(!DEATH_ISWEAPON(deathtype, WEP_BLASTER) || attacker != self || self.health < 2 * WEP_CVAR_PRI(blaster, damage) * autocvar_g_balance_selfdamagepercent + 1) // WEAPONTODO: create separate limit for pain notification with laser + if(!DEATH_ISWEAPON(deathtype, WEP_LASER) || attacker != self || self.health < 2 * autocvar_g_balance_laser_primary_damage * autocvar_g_balance_selfdamagepercent + 1) if(self.health > 1) // exclude pain sounds for laserjumps as long as you aren't REALLY low on health and would die of the next two { @@ -536,7 +666,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht frag_deathtype = deathtype; MUTATOR_CALLHOOK(PlayerDies); - WEP_ACTION(self.weapon, WR_PLAYERDEATH); + weapon_action(self.weapon, WR_PLAYERDEATH); RemoveGrapplingHook(self); @@ -608,7 +738,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht // reset fields the weapons may use just in case for (j = WEP_FIRST; j <= WEP_LAST; ++j) { - WEP_ACTION(j, WR_RESETPLAYER); + weapon_action(j, WR_RESETPLAYER); ATTACK_FINISHED_FOR(self, j) = 0; } } diff --git a/qcsrc/server/cl_weaponsystem.qc b/qcsrc/server/cl_weaponsystem.qc new file mode 100644 index 000000000..dac383633 --- /dev/null +++ b/qcsrc/server/cl_weaponsystem.qc @@ -0,0 +1,1407 @@ +/* +=========================================================================== + + CLIENT WEAPONSYSTEM CODE + Bring back W_Weaponframe + +=========================================================================== +*/ + +.float weapon_frametime; + +float W_WeaponRateFactor() +{ + float t; + t = 1.0 / g_weaponratefactor; + + weapon_rate = t; + MUTATOR_CALLHOOK(WeaponRateFactor); + t = weapon_rate; + + return t; +} + +void W_SwitchWeapon_Force(entity e, float w) +{ + e.cnt = e.switchweapon; + e.switchweapon = w; + e.selectweapon = w; +} + +.float antilag_debug; + +// VorteX: static frame globals +const float WFRAME_DONTCHANGE = -1; +const float WFRAME_FIRE1 = 0; +const float WFRAME_FIRE2 = 1; +const float WFRAME_IDLE = 2; +const float WFRAME_RELOAD = 3; +.float wframe; + +void(float fr, float t, void() func) weapon_thinkf; + +vector W_HitPlotUnnormalizedUntransform(vector screenforward, vector screenright, vector screenup, vector v) +{ + vector ret; + ret_x = screenright * v; + ret_y = screenup * v; + ret_z = screenforward * v; + return ret; +} + +vector W_HitPlotNormalizedUntransform(vector org, entity targ, vector screenforward, vector screenright, vector screenup, vector v) +{ + float i, j, k; + vector mi, ma, thisv, myv, ret; + + myv = W_HitPlotUnnormalizedUntransform(screenforward, screenright, screenup, org); + + // x = 0..1 relative to hitbox; y = 0..1 relative to hitbox; z = distance + + mi = ma = targ.origin + 0.5 * (targ.mins + targ.maxs); + for(i = 0; i < 2; ++i) for(j = 0; j < 2; ++j) for(k = 0; k < 2; ++k) + { + thisv = targ.origin; + if(i) thisv_x += targ.maxs_x; else thisv_x += targ.mins_x; + if(j) thisv_y += targ.maxs_y; else thisv_y += targ.mins_y; + if(k) thisv_z += targ.maxs_z; else thisv_z += targ.mins_z; + thisv = W_HitPlotUnnormalizedUntransform(screenforward, screenright, screenup, thisv); + if(i || j || k) + { + if(mi_x > thisv_x) mi_x = thisv_x; if(ma_x < thisv_x) ma_x = thisv_x; + if(mi_y > thisv_y) mi_y = thisv_y; if(ma_y < thisv_y) ma_y = thisv_y; + //if(mi_z > thisv_z) mi_z = thisv_z; if(ma_z < thisv_z) ma_y = thisv_z; + } + else + { + // first run + mi = ma = thisv; + } + } + + thisv = W_HitPlotUnnormalizedUntransform(screenforward, screenright, screenup, v); + ret_x = (thisv_x - mi_x) / (ma_x - mi_x); + ret_y = (thisv_y - mi_y) / (ma_y - mi_y); + ret_z = thisv_z - myv_z; + return ret; +} + +void W_HitPlotAnalysis(entity player, vector screenforward, vector screenright, vector screenup) +{ + vector hitplot; + vector org; + float lag; + + if(player.hitplotfh >= 0) + { + lag = ANTILAG_LATENCY(player); + if(lag < 0.001) + lag = 0; + if (!IS_REAL_CLIENT(player)) + lag = 0; // only antilag for clients + + org = player.origin + player.view_ofs; + traceline_antilag_force(player, org, org + screenforward * MAX_SHOT_DISTANCE, MOVE_NORMAL, player, lag); + if(IS_CLIENT(trace_ent) || (trace_ent.flags & FL_MONSTER)) + { + antilag_takeback(trace_ent, time - lag); + hitplot = W_HitPlotNormalizedUntransform(org, trace_ent, screenforward, screenright, screenup, trace_endpos); + antilag_restore(trace_ent); + fputs(player.hitplotfh, strcat(ftos(hitplot_x), " ", ftos(hitplot_y), " ", ftos(hitplot_z), " ", ftos(player.switchweapon), "\n")); + //print(strcat(ftos(hitplot_x), " ", ftos(hitplot_y), " ", ftos(hitplot_z), "\n")); + } + } +} + +vector w_shotorg; +vector w_shotdir; +vector w_shotend; + +.float prevstrengthsound; +.float prevstrengthsoundattempt; +void W_PlayStrengthSound(entity player) // void W_PlayStrengthSound +{ + if((player.items & IT_STRENGTH) + && ((time > player.prevstrengthsound + autocvar_sv_strengthsound_antispam_time) // prevent insane sound spam + || (time > player.prevstrengthsoundattempt + autocvar_sv_strengthsound_antispam_refire_threshold))) + { + sound(player, CH_TRIGGER, "weapons/strength_fire.wav", VOL_BASE, ATTEN_NORM); + player.prevstrengthsound = time; + } + player.prevstrengthsoundattempt = time; +} + +// 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?) +void W_SetupShot_Dir_ProjectileSize_Range(entity ent, vector s_forward, vector mi, vector ma, float antilag, float recoil, string snd, float chan, float maxdamage, float range) +{ + float nudge = 1; // added to traceline target and subtracted from result + float oldsolid; + vector vecs, dv; + oldsolid = ent.dphitcontentsmask; + if(ent.weapon == WEP_RIFLE) + ent.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_CORPSE; + else + ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE; + if(antilag) + WarpZone_traceline_antilag(world, ent.origin + ent.view_ofs, ent.origin + ent.view_ofs + s_forward * range, MOVE_NORMAL, ent, ANTILAG_LATENCY(ent)); + // passing world, because we do NOT want it to touch dphitcontentsmask + else + WarpZone_TraceLine(ent.origin + ent.view_ofs, ent.origin + ent.view_ofs + s_forward * range, MOVE_NOMONSTERS, ent); + ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE; + + vector vf, vr, vu; + vf = v_forward; + vr = v_right; + vu = v_up; + w_shotend = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos); // warpzone support + v_forward = vf; + v_right = vr; + v_up = vu; + + // un-adjust trueaim if shotend is too close + if(vlen(w_shotend - (ent.origin + ent.view_ofs)) < autocvar_g_trueaim_minrange) + w_shotend = ent.origin + ent.view_ofs + s_forward * autocvar_g_trueaim_minrange; + + // track max damage + if(accuracy_canbegooddamage(ent)) + accuracy_add(ent, ent.weapon, maxdamage, 0); + + W_HitPlotAnalysis(ent, v_forward, v_right, v_up); + + if(ent.weaponentity.movedir_x > 0) + vecs = ent.weaponentity.movedir; + else + vecs = '0 0 0'; + + dv = v_right * -vecs_y + v_up * vecs_z; + w_shotorg = ent.origin + ent.view_ofs + dv; + + // now move the shotorg forward as much as requested if possible + if(antilag) + { + if(ent.antilag_debug) + tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + v_forward * (vecs_x + nudge), MOVE_NORMAL, ent, ent.antilag_debug); + else + tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + v_forward * (vecs_x + nudge), MOVE_NORMAL, ent, ANTILAG_LATENCY(ent)); + } + else + tracebox(w_shotorg, mi, ma, w_shotorg + v_forward * (vecs_x + nudge), MOVE_NORMAL, ent); + w_shotorg = trace_endpos - v_forward * nudge; + // calculate the shotdir from the chosen shotorg + w_shotdir = normalize(w_shotend - w_shotorg); + + if (antilag) + if (!ent.cvar_cl_noantilag) + { + if (autocvar_g_antilag == 1) // switch to "ghost" if not hitting original + { + traceline(w_shotorg, w_shotorg + w_shotdir * range, MOVE_NORMAL, ent); + if (!trace_ent.takedamage) + { + traceline_antilag_force (ent, w_shotorg, w_shotorg + w_shotdir * range, MOVE_NORMAL, ent, ANTILAG_LATENCY(ent)); + if (trace_ent.takedamage && IS_PLAYER(trace_ent)) + { + entity e; + e = trace_ent; + traceline(w_shotorg, e.origin, MOVE_NORMAL, ent); + if(trace_ent == e) + w_shotdir = normalize(trace_ent.origin - w_shotorg); + } + } + } + else if(autocvar_g_antilag == 3) // client side hitscan + { + // this part MUST use prydon cursor + if (ent.cursor_trace_ent) // client was aiming at someone + if (ent.cursor_trace_ent != ent) // just to make sure + if (ent.cursor_trace_ent.takedamage) // and that person is killable + if (IS_PLAYER(ent.cursor_trace_ent)) // and actually a player + { + // verify that the shot would miss without antilag + // (avoids an issue where guns would always shoot at their origin) + traceline(w_shotorg, w_shotorg + w_shotdir * range, MOVE_NORMAL, ent); + if (!trace_ent.takedamage) + { + // verify that the shot would hit if altered + traceline(w_shotorg, ent.cursor_trace_ent.origin, MOVE_NORMAL, ent); + if (trace_ent == ent.cursor_trace_ent) + w_shotdir = normalize(ent.cursor_trace_ent.origin - w_shotorg); + else + print("antilag fail\n"); + } + } + } + } + + ent.dphitcontentsmask = oldsolid; // restore solid type (generally SOLID_SLIDEBOX) + + if (!autocvar_g_norecoil) + ent.punchangle_x = recoil * -1; + + if (snd != "") + { + sound (ent, chan, snd, VOL_BASE, ATTEN_NORM); + W_PlayStrengthSound(ent); + } + + // nudge w_shotend so a trace to w_shotend hits + w_shotend = w_shotend + normalize(w_shotend - w_shotorg) * nudge; +} + +#define W_SetupShot_Dir_ProjectileSize(ent,s_forward,mi,ma,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize_Range(ent, s_forward, mi, ma, antilag, recoil, snd, chan, maxdamage, MAX_SHOT_DISTANCE) +#define W_SetupShot_ProjectileSize(ent,mi,ma,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize(ent, v_forward, mi, ma, antilag, recoil, snd, chan, maxdamage) +#define W_SetupShot_Dir(ent,s_forward,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize(ent, s_forward, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage) +#define W_SetupShot(ent,antilag,recoil,snd,chan,maxdamage) W_SetupShot_ProjectileSize(ent, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage) +#define W_SetupShot_Range(ent,antilag,recoil,snd,chan,maxdamage,range) W_SetupShot_Dir_ProjectileSize_Range(ent, v_forward, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage, range) + +float CL_Weaponentity_CustomizeEntityForClient() +{ + self.viewmodelforclient = self.owner; + if(IS_SPEC(other)) + if(other.enemy == self.owner) + self.viewmodelforclient = other; + return TRUE; +} + +/* + * supported formats: + * + * 1. simple animated model, muzzle flash handling on h_ model: + * h_tuba.dpm, h_tuba.dpm.framegroups - invisible model controlling the animation + * tags: + * shot = muzzle end (shot origin, also used for muzzle flashes) + * shell = casings ejection point (must be on the right hand side of the gun) + * weapon = attachment for v_tuba.md3 + * v_tuba.md3 - first and third person model + * g_tuba.md3 - pickup model + * + * 2. simple animated model, muzzle flash handling on v_ model: + * h_tuba.dpm, h_tuba.dpm.framegroups - invisible model controlling the animation + * tags: + * weapon = attachment for v_tuba.md3 + * v_tuba.md3 - first and third person model + * tags: + * shot = muzzle end (shot origin, also used for muzzle flashes) + * shell = casings ejection point (must be on the right hand side of the gun) + * g_tuba.md3 - pickup model + * + * 3. fully animated model, muzzle flash handling on h_ model: + * h_tuba.dpm, h_tuba.dpm.framegroups - animated first person model + * tags: + * shot = muzzle end (shot origin, also used for muzzle flashes) + * shell = casings ejection point (must be on the right hand side of the gun) + * handle = corresponding to the origin of v_tuba.md3 (used for muzzle flashes) + * v_tuba.md3 - third person model + * g_tuba.md3 - pickup model + * + * 4. fully animated model, muzzle flash handling on v_ model: + * h_tuba.dpm, h_tuba.dpm.framegroups - animated first person model + * tags: + * shot = muzzle end (shot origin) + * shell = casings ejection point (must be on the right hand side of the gun) + * v_tuba.md3 - third person model + * tags: + * shot = muzzle end (for muzzle flashes) + * g_tuba.md3 - pickup model + */ + +// writes: +// self.origin, self.angles +// self.weaponentity +// self.movedir, self.view_ofs +// attachment stuff +// anim stuff +// to free: +// call again with "" +// remove the ent +void CL_WeaponEntity_SetModel(string name) +{ + float v_shot_idx; + if (name != "") + { + // if there is a child entity, hide it until we're sure we use it + if (self.weaponentity) + self.weaponentity.model = ""; + setmodel(self, strcat("models/weapons/v_", name, ".md3")); // precision set below + v_shot_idx = gettagindex(self, "shot"); // used later + if(!v_shot_idx) + v_shot_idx = gettagindex(self, "tag_shot"); + + setmodel(self, strcat("models/weapons/h_", name, ".iqm")); // precision set below + // preset some defaults that work great for renamed zym files (which don't need an animinfo) + self.anim_fire1 = animfixfps(self, '0 1 0.01', '0 0 0'); + self.anim_fire2 = animfixfps(self, '1 1 0.01', '0 0 0'); + self.anim_idle = animfixfps(self, '2 1 0.01', '0 0 0'); + self.anim_reload = animfixfps(self, '3 1 0.01', '0 0 0'); + + // if we have a "weapon" tag, let's attach the v_ model to it ("invisible hand" style model) + // if we don't, this is a "real" animated model + if(gettagindex(self, "weapon")) + { + if (!self.weaponentity) + self.weaponentity = spawn(); + setmodel(self.weaponentity, strcat("models/weapons/v_", name, ".md3")); // precision does not matter + setattachment(self.weaponentity, self, "weapon"); + } + else if(gettagindex(self, "tag_weapon")) + { + if (!self.weaponentity) + self.weaponentity = spawn(); + setmodel(self.weaponentity, strcat("models/weapons/v_", name, ".md3")); // precision does not matter + setattachment(self.weaponentity, self, "tag_weapon"); + } + else + { + if(self.weaponentity) + remove(self.weaponentity); + self.weaponentity = world; + } + + setorigin(self,'0 0 0'); + self.angles = '0 0 0'; + self.frame = 0; + self.viewmodelforclient = world; + + float idx; + + if(v_shot_idx) // v_ model attached to invisible h_ model + { + self.movedir = gettaginfo(self.weaponentity, v_shot_idx); + } + else + { + idx = gettagindex(self, "shot"); + if(!idx) + idx = gettagindex(self, "tag_shot"); + if(idx) + self.movedir = gettaginfo(self, idx); + else + { + print("WARNING: weapon model ", self.model, " does not support the 'shot' tag, will display shots TOTALLY wrong\n"); + self.movedir = '0 0 0'; + } + } + + if(self.weaponentity) // v_ model attached to invisible h_ model + { + idx = gettagindex(self.weaponentity, "shell"); + if(!idx) + idx = gettagindex(self.weaponentity, "tag_shell"); + if(idx) + self.spawnorigin = gettaginfo(self.weaponentity, idx); + } + else + idx = 0; + if(!idx) + { + idx = gettagindex(self, "shell"); + if(!idx) + idx = gettagindex(self, "tag_shell"); + if(idx) + self.spawnorigin = gettaginfo(self, idx); + else + { + print("WARNING: weapon model ", self.model, " does not support the 'shell' tag, will display casings wrong\n"); + self.spawnorigin = self.movedir; + } + } + + if(v_shot_idx) + { + self.oldorigin = '0 0 0'; // use regular attachment + } + else + { + if(self.weaponentity) + { + idx = gettagindex(self, "weapon"); + if(!idx) + idx = gettagindex(self, "tag_weapon"); + } + else + { + idx = gettagindex(self, "handle"); + if(!idx) + idx = gettagindex(self, "tag_handle"); + } + if(idx) + { + self.oldorigin = self.movedir - gettaginfo(self, idx); + } + else + { + print("WARNING: weapon model ", self.model, " does not support the 'handle' tag and neither does the v_ model support the 'shot' tag, will display muzzle flashes TOTALLY wrong\n"); + self.oldorigin = '0 0 0'; // there is no way to recover from this + } + } + + self.viewmodelforclient = self.owner; + } + else + { + self.model = ""; + if(self.weaponentity) + remove(self.weaponentity); + self.weaponentity = world; + self.movedir = '0 0 0'; + self.spawnorigin = '0 0 0'; + self.oldorigin = '0 0 0'; + self.anim_fire1 = '0 1 0.01'; + self.anim_fire2 = '0 1 0.01'; + self.anim_idle = '0 1 0.01'; + self.anim_reload = '0 1 0.01'; + } + + self.view_ofs = '0 0 0'; + + if(self.movedir_x >= 0) + { + vector v0; + v0 = self.movedir; + self.movedir = shotorg_adjust(v0, FALSE, FALSE); + self.view_ofs = shotorg_adjust(v0, FALSE, TRUE) - v0; + } + self.owner.stat_shotorg = compressShotOrigin(self.movedir); + self.movedir = decompressShotOrigin(self.owner.stat_shotorg); // make them match perfectly + + self.spawnorigin += self.view_ofs; // offset the casings origin by the same amount + + // check if an instant weapon switch occurred + setorigin(self, self.view_ofs); + // reset animstate now + self.wframe = WFRAME_IDLE; + setanim(self, self.anim_idle, TRUE, FALSE, TRUE); +} + +vector CL_Weapon_GetShotOrg(float wpn) +{ + entity wi, oldself; + vector ret; + wi = get_weaponinfo(wpn); + oldself = self; + self = spawn(); + CL_WeaponEntity_SetModel(wi.mdl); + ret = self.movedir; + CL_WeaponEntity_SetModel(""); + remove(self); + self = oldself; + return ret; +} + +void CL_Weaponentity_Think() +{ + float tb; + self.nextthink = time; + if (intermission_running) + self.frame = self.anim_idle_x; + if (self.owner.weaponentity != self) + { + if (self.weaponentity) + remove(self.weaponentity); + remove(self); + return; + } + if (self.owner.deadflag != DEAD_NO) + { + self.model = ""; + if (self.weaponentity) + self.weaponentity.model = ""; + return; + } + if (self.weaponname != self.owner.weaponname || self.dmg != self.owner.modelindex || self.deadflag != self.owner.deadflag) + { + self.weaponname = self.owner.weaponname; + self.dmg = self.owner.modelindex; + self.deadflag = self.owner.deadflag; + + CL_WeaponEntity_SetModel(self.owner.weaponname); + } + + tb = (self.effects & (EF_TELEPORT_BIT | EF_RESTARTANIM_BIT)); + self.effects = self.owner.effects & EFMASK_CHEAP; + self.effects &= ~EF_LOWPRECISION; + self.effects &= ~EF_FULLBRIGHT; // can mask team color, so get rid of it + self.effects &= ~EF_TELEPORT_BIT; + self.effects &= ~EF_RESTARTANIM_BIT; + self.effects |= tb; + + if(self.owner.alpha == default_player_alpha) + self.alpha = default_weapon_alpha; + else if(self.owner.alpha != 0) + self.alpha = self.owner.alpha; + else + self.alpha = 1; + + self.glowmod = self.owner.weaponentity_glowmod; + self.colormap = self.owner.colormap; + if (self.weaponentity) + { + self.weaponentity.effects = self.effects; + self.weaponentity.alpha = self.alpha; + self.weaponentity.colormap = self.colormap; + self.weaponentity.glowmod = self.glowmod; + } + + self.angles = '0 0 0'; + + float f = (self.owner.weapon_nextthink - time); + if (self.state == WS_RAISE && !intermission_running) + { + entity newwep = get_weaponinfo(self.owner.switchweapon); + f = f * g_weaponratefactor / max(f, cvar(sprintf("g_balance_%s_switchdelay_raise", newwep.netname))); + //printf("CL_Weaponentity_Think(): cvar: %s, value: %f, nextthink: %f\n", sprintf("g_balance_%s_switchdelay_raise", newwep.netname), cvar(sprintf("g_balance_%s_switchdelay_raise", newwep.netname)), (self.owner.weapon_nextthink - time)); + self.angles_x = -90 * f * f; + } + else if (self.state == WS_DROP && !intermission_running) + { + entity oldwep = get_weaponinfo(self.owner.weapon); + f = 1 - f * g_weaponratefactor / max(f, cvar(sprintf("g_balance_%s_switchdelay_drop", oldwep.netname))); + //printf("CL_Weaponentity_Think(): cvar: %s, value: %f, nextthink: %f\n", sprintf("g_balance_%s_switchdelay_drop", oldwep.netname), cvar(sprintf("g_balance_%s_switchdelay_drop", oldwep.netname)), (self.owner.weapon_nextthink - time)); + self.angles_x = -90 * f * f; + } + else if (self.state == WS_CLEAR) + { + f = 1; + self.angles_x = -90 * f * f; + } +} + +void CL_ExteriorWeaponentity_Think() +{ + float tag_found; + self.nextthink = time; + if (self.owner.exteriorweaponentity != self) + { + remove(self); + return; + } + if (self.owner.deadflag != DEAD_NO) + { + self.model = ""; + return; + } + if (self.weaponname != self.owner.weaponname || self.dmg != self.owner.modelindex || self.deadflag != self.owner.deadflag) + { + self.weaponname = self.owner.weaponname; + self.dmg = self.owner.modelindex; + self.deadflag = self.owner.deadflag; + if (self.owner.weaponname != "") + setmodel(self, strcat("models/weapons/v_", self.owner.weaponname, ".md3")); // precision set below + else + self.model = ""; + + if((tag_found = gettagindex(self.owner, "tag_weapon"))) + { + self.tag_index = tag_found; + self.tag_entity = self.owner; + } + else + setattachment(self, self.owner, "bip01 r hand"); + } + self.effects = self.owner.effects; + self.effects |= EF_LOWPRECISION; + self.effects = self.effects & EFMASK_CHEAP; // eat performance + if(self.owner.alpha == default_player_alpha) + self.alpha = default_weapon_alpha; + else if(self.owner.alpha != 0) + self.alpha = self.owner.alpha; + else + self.alpha = 1; + + self.glowmod = self.owner.weaponentity_glowmod; + self.colormap = self.owner.colormap; + + CSQCMODEL_AUTOUPDATE(); +} + +// spawning weaponentity for client +void CL_SpawnWeaponentity() +{ + self.weaponentity = spawn(); + self.weaponentity.classname = "weaponentity"; + self.weaponentity.solid = SOLID_NOT; + self.weaponentity.owner = self; + setmodel(self.weaponentity, ""); // precision set when changed + setorigin(self.weaponentity, '0 0 0'); + self.weaponentity.angles = '0 0 0'; + self.weaponentity.viewmodelforclient = self; + self.weaponentity.flags = 0; + self.weaponentity.think = CL_Weaponentity_Think; + self.weaponentity.customizeentityforclient = CL_Weaponentity_CustomizeEntityForClient; + self.weaponentity.nextthink = time; + + self.exteriorweaponentity = spawn(); + self.exteriorweaponentity.classname = "exteriorweaponentity"; + self.exteriorweaponentity.solid = SOLID_NOT; + self.exteriorweaponentity.exteriorweaponentity = self.exteriorweaponentity; + self.exteriorweaponentity.owner = self; + setorigin(self.exteriorweaponentity, '0 0 0'); + self.exteriorweaponentity.angles = '0 0 0'; + self.exteriorweaponentity.think = CL_ExteriorWeaponentity_Think; + self.exteriorweaponentity.nextthink = time; + + { + entity oldself = self; + self = self.exteriorweaponentity; + CSQCMODEL_AUTOINIT(); + self = oldself; + } +} + +void Send_WeaponComplain (entity e, float wpn, string wpnname, float type) +{ + msg_entity = e; + WriteByte(MSG_ONE, SVC_TEMPENTITY); + WriteByte(MSG_ONE, TE_CSQC_WEAPONCOMPLAIN); + WriteByte(MSG_ONE, wpn); + WriteString(MSG_ONE, wpnname); + WriteByte(MSG_ONE, type); +} + +.float hasweapon_complain_spam; + +float client_hasweapon(entity cl, float wpn, float andammo, float complain) +{ + float f; + entity oldself; + + if(time < self.hasweapon_complain_spam) + complain = 0; + if(complain) + self.hasweapon_complain_spam = time + 0.2; + + if(wpn == WEP_HOOK && !g_grappling_hook && autocvar_g_nades && !((cl.weapons | weaponsInMap) & WepSet_FromWeapon(wpn))) + complain = 0; + + if (wpn < WEP_FIRST || wpn > WEP_LAST) + { + if (complain) + sprint(self, "Invalid weapon\n"); + return FALSE; + } + if (cl.weapons & WepSet_FromWeapon(wpn)) + { + if (andammo) + { + if(cl.items & IT_UNLIMITED_WEAPON_AMMO) + { + f = 1; + } + else + { + oldself = self; + 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 + 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 (complain) + if(IS_REAL_CLIENT(cl)) + { + play2(cl, "weapons/unavailable.wav"); + Send_WeaponComplain (cl, wpn, W_Name(wpn), 0); + } + return FALSE; + } + } + return TRUE; + } + if (complain) + { + // DRESK - 3/16/07 + // Report Proper Weapon Status / Modified Weapon Ownership Message + if (weaponsInMap & WepSet_FromWeapon(wpn)) + { + Send_WeaponComplain(cl, wpn, W_Name(wpn), 1); + + if(autocvar_g_showweaponspawns) + { + entity e; + string s; + + e = get_weaponinfo(wpn); + s = e.model2; + + for(e = world; (e = findfloat(e, weapon, wpn)); ) + { + if(e.classname == "droppedweapon") + continue; + if (!(e.flags & FL_ITEM)) + continue; + WaypointSprite_Spawn( + s, + 1, 0, + world, e.origin, + self, 0, + world, enemy, + 0, + RADARICON_NONE, '0 0 0' + ); + } + } + } + else + { + Send_WeaponComplain (cl, wpn, W_Name(wpn), 2); + } + + play2(cl, "weapons/unavailable.wav"); + } + return FALSE; +} + +// Weapon subs +void w_clear() +{ + if (self.weapon != -1) + { + self.weapon = 0; + self.switchingweapon = 0; + } + if (self.weaponentity) + { + self.weaponentity.state = WS_CLEAR; + self.weaponentity.effects = 0; + } +} + +void w_ready() +{ + if (self.weaponentity) + self.weaponentity.state = WS_READY; + weapon_thinkf(WFRAME_IDLE, 1000000, w_ready); +} + +// Setup weapon for client (after this raise frame will be launched) +void weapon_setup(float windex) +{ + entity e; + e = get_weaponinfo(windex); + self.items &= ~IT_AMMO; + self.items = self.items | (e.items & IT_AMMO); + + // the two weapon entities will notice this has changed and update their models + self.weapon = windex; + self.switchingweapon = windex; // to make sure + self.weaponname = e.mdl; + self.bulletcounter = 0; +} + +// perform weapon to attack (weaponstate and attack_finished check is here) +void W_SwitchToOtherWeapon(entity pl) +{ + // hack to ensure it switches to an OTHER weapon (in case the other fire mode still has ammo, we want that anyway) + float w, ww; + w = pl.weapon; + if(pl.weapons & WepSet_FromWeapon(w)) + { + pl.weapons &= ~WepSet_FromWeapon(w); + ww = w_getbestweapon(pl); + pl.weapons |= WepSet_FromWeapon(w); + } + else + ww = w_getbestweapon(pl); + if(ww) + W_SwitchWeapon_Force(pl, ww); +} + +.float prevdryfire; +.float prevwarntime; +float weapon_prepareattack_checkammo(float secondary) +{ + if (!(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 + 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 && time - self.prevdryfire > 1) // only play once BEFORE starting to switch weapons + { + sound (self, CH_WEAPON_A, "weapons/dryfire.wav", VOL_BASE, ATTEN_NORM); + self.prevdryfire = time; + } + + if(weapon_action(self.weapon, WR_CHECKAMMO2 - secondary)) // check if the other firing mode has enough ammo + { + if(time - self.prevwarntime > 1) + { + Send_Notification( + NOTIF_ONE, + self, + MSG_MULTI, + ITEM_WEAPON_PRIMORSEC, + self.weapon, + secondary, + (1 - secondary) + ); + } + self.prevwarntime = time; + } + else // this weapon is totally unable to fire, switch to another one + { + W_SwitchToOtherWeapon(self); + } + + return FALSE; + } + return TRUE; +} +.float race_penalty; +float weapon_prepareattack_check(float secondary, float attacktime) +{ + if(!weapon_prepareattack_checkammo(secondary)) + return FALSE; + + //if sv_ready_restart_after_countdown is set, don't allow the player to shoot + //if all players readied up and the countdown is running + if(time < game_starttime || time < self.race_penalty) { + return FALSE; + } + + if (timeout_status == TIMEOUT_ACTIVE) //don't allow the player to shoot while game is paused + return FALSE; + + // do not even think about shooting if switching + if(self.switchweapon != self.weapon) + return FALSE; + + if(attacktime >= 0) + { + // don't fire if previous attack is not finished + if (ATTACK_FINISHED(self) > time + self.weapon_frametime * 0.5) + return FALSE; + // don't fire while changing weapon + if (self.weaponentity.state != WS_READY) + return FALSE; + } + + return TRUE; +} +float weapon_prepareattack_do(float secondary, float attacktime) +{ + self.weaponentity.state = WS_INUSE; + + self.spawnshieldtime = min(self.spawnshieldtime, time); // kill spawn shield when you fire + + // if the weapon hasn't been firing continuously, reset the timer + if(attacktime >= 0) + { + if (ATTACK_FINISHED(self) < time - self.weapon_frametime * 1.5) + { + ATTACK_FINISHED(self) = time; + //dprint("resetting attack finished to ", ftos(time), "\n"); + } + ATTACK_FINISHED(self) = ATTACK_FINISHED(self) + attacktime * W_WeaponRateFactor(); + } + self.bulletcounter += 1; + //dprint("attack finished ", ftos(ATTACK_FINISHED(self)), "\n"); + return TRUE; +} +float weapon_prepareattack(float secondary, float attacktime) +{ + if(weapon_prepareattack_check(secondary, attacktime)) + { + weapon_prepareattack_do(secondary, attacktime); + return TRUE; + } + else + return FALSE; +} + +void weapon_thinkf(float fr, float t, void() func) +{ + vector a; + vector of, or, ou; + float restartanim; + + if(fr == WFRAME_DONTCHANGE) + { + fr = self.weaponentity.wframe; + restartanim = FALSE; + } + else if (fr == WFRAME_IDLE) + restartanim = FALSE; + else + restartanim = TRUE; + + of = v_forward; + or = v_right; + ou = v_up; + + if (self.weaponentity) + { + self.weaponentity.wframe = fr; + a = '0 0 0'; + if (fr == WFRAME_IDLE) + a = self.weaponentity.anim_idle; + else if (fr == WFRAME_FIRE1) + a = self.weaponentity.anim_fire1; + else if (fr == WFRAME_FIRE2) + a = self.weaponentity.anim_fire2; + else // if (fr == WFRAME_RELOAD) + a = self.weaponentity.anim_reload; + a_z *= g_weaponratefactor; + setanim(self.weaponentity, a, restartanim == FALSE, restartanim, restartanim); + } + + v_forward = of; + v_right = or; + v_up = ou; + + if(self.weapon_think == w_ready && func != w_ready && self.weaponentity.state == WS_RAISE) + { + backtrace("Tried to override initial weapon think function - should this really happen?"); + } + + t *= W_WeaponRateFactor(); + + // VorteX: haste can be added here + if (self.weapon_think == w_ready) + { + self.weapon_nextthink = time; + //dprint("started firing at ", ftos(time), "\n"); + } + if (self.weapon_nextthink < time - self.weapon_frametime * 1.5 || self.weapon_nextthink > time + self.weapon_frametime * 1.5) + { + self.weapon_nextthink = time; + //dprint("reset weapon animation timer at ", ftos(time), "\n"); + } + self.weapon_nextthink = self.weapon_nextthink + t; + self.weapon_think = func; + //dprint("next ", ftos(self.weapon_nextthink), "\n"); + + if((fr == WFRAME_FIRE1 || fr == WFRAME_FIRE2) && t) + { + if(self.weapon == WEP_SHOTGUN && fr == WFRAME_FIRE2) + animdecide_setaction(self, ANIMACTION_MELEE, restartanim); + else + animdecide_setaction(self, ANIMACTION_SHOOT, restartanim); + } + else + { + if(self.anim_upper_action == ANIMACTION_SHOOT || self.anim_upper_action == ANIMACTION_MELEE) + self.anim_upper_action = 0; + } +} + +void weapon_boblayer1(float spd, vector org) +{ + // VorteX: haste can be added here +} + +vector W_CalculateProjectileVelocity(vector pvelocity, vector mvelocity, float forceAbsolute) +{ + vector mdirection; + float mspeed; + vector outvelocity; + + mvelocity = mvelocity * g_weaponspeedfactor; + + mdirection = normalize(mvelocity); + mspeed = vlen(mvelocity); + + outvelocity = get_shotvelocity(pvelocity, mdirection, mspeed, (forceAbsolute ? 0 : autocvar_g_projectiles_newton_style), autocvar_g_projectiles_newton_style_2_minfactor, autocvar_g_projectiles_newton_style_2_maxfactor); + + return outvelocity; +} + +void W_AttachToShotorg(entity flash, vector offset) +{ + entity xflash; + flash.owner = self; + flash.angles_z = random() * 360; + + if(gettagindex(self.weaponentity, "shot")) + setattachment(flash, self.weaponentity, "shot"); + else + setattachment(flash, self.weaponentity, "tag_shot"); + setorigin(flash, offset); + + xflash = spawn(); + copyentity(flash, xflash); + + flash.viewmodelforclient = self; + + if(self.weaponentity.oldorigin_x > 0) + { + setattachment(xflash, self.exteriorweaponentity, ""); + setorigin(xflash, self.weaponentity.oldorigin + offset); + } + else + { + if(gettagindex(self.exteriorweaponentity, "shot")) + setattachment(xflash, self.exteriorweaponentity, "shot"); + else + setattachment(xflash, self.exteriorweaponentity, "tag_shot"); + setorigin(xflash, offset); + } +} + +vector cliptoplane(vector v, vector p) +{ + return v - (v * p) * p; +} + +vector solve_cubic_pq(float p, float q) +{ + float D, u, v, a; + D = q*q/4.0 + p*p*p/27.0; + if(D < 0) + { + // irreducibilis + a = 1.0/3.0 * acos(-q/2.0 * sqrt(-27.0/(p*p*p))); + u = sqrt(-4.0/3.0 * p); + // a in range 0..pi/3 + // cos(a) + // cos(a + 2pi/3) + // cos(a + 4pi/3) + return + u * + ( + '1 0 0' * cos(a + 2.0/3.0*M_PI) + + + '0 1 0' * cos(a + 4.0/3.0*M_PI) + + + '0 0 1' * cos(a) + ); + } + else if(D == 0) + { + // simple + if(p == 0) + return '0 0 0'; + u = 3*q/p; + v = -u/2; + if(u >= v) + return '1 1 0' * v + '0 0 1' * u; + else + return '0 1 1' * v + '1 0 0' * u; + } + else + { + // cardano + u = cbrt(-q/2.0 + sqrt(D)); + v = cbrt(-q/2.0 - sqrt(D)); + return '1 1 1' * (u + v); + } +} +vector solve_cubic_abcd(float a, float b, float c, float d) +{ + // y = 3*a*x + b + // x = (y - b) / 3a + float p, q; + vector v; + p = (9*a*c - 3*b*b); + q = (27*a*a*d - 9*a*b*c + 2*b*b*b); + v = solve_cubic_pq(p, q); + v = (v - b * '1 1 1') * (1.0 / (3.0 * a)); + if(a < 0) + v += '1 0 -1' * (v_z - v_x); // swap x, z + return v; +} + +vector findperpendicular(vector v) +{ + vector p; + p_x = v_z; + p_y = -v_x; + p_z = v_y; + return normalize(cliptoplane(p, v)); +} + +vector W_CalculateProjectileSpread(vector forward, float spread) +{ + float sigma; + vector v1 = '0 0 0', v2; + float dx, dy, r; + float sstyle; + spread *= g_weaponspreadfactor; + if(spread <= 0) + return forward; + sstyle = autocvar_g_projectiles_spread_style; + + if(sstyle == 0) + { + // this is the baseline for the spread value! + // standard deviation: sqrt(2/5) + // density function: sqrt(1-r^2) + return forward + randomvec() * spread; + } + else if(sstyle == 1) + { + // same thing, basically + return normalize(forward + cliptoplane(randomvec() * spread, forward)); + } + else if(sstyle == 2) + { + // circle spread... has at sigma=1 a standard deviation of sqrt(1/2) + sigma = spread * 0.89442719099991587855; // match baseline stddev + v1 = findperpendicular(forward); + v2 = cross(forward, v1); + // random point on unit circle + dx = random() * 2 * M_PI; + dy = sin(dx); + dx = cos(dx); + // radius in our dist function + r = random(); + r = sqrt(r); + return normalize(forward + (v1 * dx + v2 * dy) * r * sigma); + } + else if(sstyle == 3) // gauss 3d + { + sigma = spread * 0.44721359549996; // match baseline stddev + // note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right + v1 = forward; + v1_x += gsl_ran_gaussian(sigma); + v1_y += gsl_ran_gaussian(sigma); + v1_z += gsl_ran_gaussian(sigma); + return v1; + } + else if(sstyle == 4) // gauss 2d + { + sigma = spread * 0.44721359549996; // match baseline stddev + // note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right + v1_x = gsl_ran_gaussian(sigma); + v1_y = gsl_ran_gaussian(sigma); + v1_z = gsl_ran_gaussian(sigma); + return normalize(forward + cliptoplane(v1, forward)); + } + else if(sstyle == 5) // 1-r + { + sigma = spread * 1.154700538379252; // match baseline stddev + v1 = findperpendicular(forward); + v2 = cross(forward, v1); + // random point on unit circle + dx = random() * 2 * M_PI; + dy = sin(dx); + dx = cos(dx); + // radius in our dist function + r = random(); + r = solve_cubic_abcd(-2, 3, 0, -r) * '0 1 0'; + return normalize(forward + (v1 * dx + v2 * dy) * r * sigma); + } + else if(sstyle == 6) // 1-r^2 + { + sigma = spread * 1.095445115010332; // match baseline stddev + v1 = findperpendicular(forward); + v2 = cross(forward, v1); + // random point on unit circle + dx = random() * 2 * M_PI; + dy = sin(dx); + dx = cos(dx); + // radius in our dist function + r = random(); + r = sqrt(1 - r); + r = sqrt(1 - r); + return normalize(forward + (v1 * dx + v2 * dy) * r * sigma); + } + else if(sstyle == 7) // (1-r) (2-r) + { + sigma = spread * 1.224744871391589; // match baseline stddev + v1 = findperpendicular(forward); + v2 = cross(forward, v1); + // random point on unit circle + dx = random() * 2 * M_PI; + dy = sin(dx); + dx = cos(dx); + // radius in our dist function + r = random(); + r = 1 - sqrt(r); + r = 1 - sqrt(r); + return normalize(forward + (v1 * dx + v2 * dy) * r * sigma); + } + else + error("g_projectiles_spread_style must be 0 (sphere), 1 (flattened sphere), 2 (circle), 3 (gauss 3D), 4 (gauss plane), 5 (linear falloff), 6 (quadratic falloff), 7 (stronger falloff)!"); + return '0 0 0'; + /* + * how to derive falloff functions: + * rho(r) := (2-r) * (1-r); + * a : 0; + * b : 1; + * rhor(r) := r * rho(r); + * cr(t) := integrate(rhor(r), r, a, t); + * scr(t) := integrate(rhor(r) * r^2, r, a, t); + * variance : scr(b) / cr(b); + * solve(cr(r) = rand * cr(b), r), programmmode:false; + * sqrt(0.4 / variance), numer; + */ +} + +#if 0 +float mspercallsum; +float mspercallsstyle; +float mspercallcount; +#endif +void W_SetupProjectileVelocityEx(entity missile, vector dir, vector upDir, float pSpeed, float pUpSpeed, float pZSpeed, float spread, float forceAbsolute) +{ + if(missile.owner == world) + error("Unowned missile"); + + dir = dir + upDir * (pUpSpeed / pSpeed); + dir_z += pZSpeed / pSpeed; + pSpeed *= vlen(dir); + dir = normalize(dir); + +#if 0 + if(autocvar_g_projectiles_spread_style != mspercallsstyle) + { + mspercallsum = mspercallcount = 0; + mspercallsstyle = autocvar_g_projectiles_spread_style; + } + mspercallsum -= gettime(GETTIME_HIRES); +#endif + dir = W_CalculateProjectileSpread(dir, spread); +#if 0 + mspercallsum += gettime(GETTIME_HIRES); + mspercallcount += 1; + print("avg: ", ftos(mspercallcount / mspercallsum), " per sec\n"); +#endif + + missile.velocity = W_CalculateProjectileVelocity(missile.owner.velocity, pSpeed * dir, forceAbsolute); +} + +void W_SetupProjectileVelocity(entity missile, float pSpeed, float spread) +{ + W_SetupProjectileVelocityEx(missile, w_shotdir, v_up, pSpeed, 0, 0, spread, FALSE); +} + +#define W_SETUPPROJECTILEVELOCITY_UP(m,s) W_SetupProjectileVelocityEx(m, w_shotdir, v_up, cvar(#s "_speed"), cvar(#s "_speed_up"), cvar(#s "_speed_z"), cvar(#s "_spread"), FALSE) +#define W_SETUPPROJECTILEVELOCITY(m,s) W_SetupProjectileVelocityEx(m, w_shotdir, v_up, cvar(#s "_speed"), 0, 0, cvar(#s "_spread"), FALSE) + +void W_DecreaseAmmo(.float ammo_type, float ammo_use, float ammo_reload) +{ + if((self.items & IT_UNLIMITED_WEAPON_AMMO) && !ammo_reload) + return; + + // if this weapon is reloadable, decrease its load. Else decrease the player's ammo + if(ammo_reload) + { + self.clip_load -= ammo_use; + self.(weapon_load[self.weapon]) = self.clip_load; + } + else + self.(self.current_ammo) -= ammo_use; +} + +// weapon reloading code + +.float reload_ammo_amount, reload_ammo_min, reload_time; +.float reload_complain; +.string reload_sound; + +void W_ReloadedAndReady() +{ + // finish the reloading process, and do the ammo transfer + + self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading + + // if the gun uses no ammo, max out weapon load, else decrease ammo as we increase weapon load + if(!self.reload_ammo_min || self.items & IT_UNLIMITED_WEAPON_AMMO) + self.clip_load = self.reload_ammo_amount; + else + { + while(self.clip_load < self.reload_ammo_amount && self.(self.current_ammo)) // make sure we don't add more ammo than we have + { + self.clip_load += 1; + self.(self.current_ammo) -= 1; + } + } + self.(weapon_load[self.weapon]) = self.clip_load; + + // do not set ATTACK_FINISHED in reload code any more. This causes annoying delays if eg: You start reloading a weapon, + // then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there, + // so your weapon is disabled for a few seconds without reason + + //ATTACK_FINISHED(self) -= self.reload_time - 1; + + w_ready(); +} + +void W_Reload(float sent_ammo_min, float sent_ammo_amount, float sent_time, string sent_sound) +{ + // set global values to work with + + self.reload_ammo_min = sent_ammo_min; + self.reload_ammo_amount = sent_ammo_amount; + self.reload_time = sent_time; + self.reload_sound = sent_sound; + + // check if we meet the necessary conditions to reload + + entity e; + e = get_weaponinfo(self.weapon); + + // don't reload weapons that don't have the RELOADABLE flag + if (!(e.spawnflags & WEP_FLAG_RELOADABLE)) + { + dprint("Warning: Attempted to reload a weapon that does not have the WEP_FLAG_RELOADABLE flag. Fix your code!\n"); + return; + } + + // return if reloading is disabled for this weapon + if(!self.reload_ammo_amount) + return; + + // our weapon is fully loaded, no need to reload + if (self.clip_load >= self.reload_ammo_amount) + return; + + // no ammo, so nothing to load + if(!self.(self.current_ammo) && self.reload_ammo_min) + if (!(self.items & IT_UNLIMITED_WEAPON_AMMO)) + { + if(IS_REAL_CLIENT(self) && self.reload_complain < time) + { + play2(self, "weapons/unavailable.wav"); + sprint(self, strcat("You don't have enough ammo to reload the ^2", W_Name(self.weapon), "\n")); + self.reload_complain = time + 1; + } + // switch away if the amount of ammo is not enough to keep using this weapon + if (!(weapon_action(self.weapon, WR_CHECKAMMO1) + weapon_action(self.weapon, WR_CHECKAMMO2))) + { + self.clip_load = -1; // reload later + W_SwitchToOtherWeapon(self); + } + return; + } + + if (self.weaponentity) + { + if (self.weaponentity.wframe == WFRAME_RELOAD) + return; + + // allow switching away while reloading, but this will cause a new reload! + self.weaponentity.state = WS_READY; + } + + // now begin the reloading process + + sound (self, CH_WEAPON_SINGLE, self.reload_sound, VOL_BASE, ATTEN_NORM); + + // do not set ATTACK_FINISHED in reload code any more. This causes annoying delays if eg: You start reloading a weapon, + // then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there, + // so your weapon is disabled for a few seconds without reason + + //ATTACK_FINISHED(self) = max(time, ATTACK_FINISHED(self)) + self.reload_time + 1; + + weapon_thinkf(WFRAME_RELOAD, self.reload_time, W_ReloadedAndReady); + + if(self.clip_load < 0) + self.clip_load = 0; + self.old_clip_load = self.clip_load; + self.clip_load = self.(weapon_load[self.weapon]) = -1; +} diff --git a/qcsrc/server/csqceffects.qc b/qcsrc/server/csqceffects.qc index ea13aedd5..4b626546d 100644 --- a/qcsrc/server/csqceffects.qc +++ b/qcsrc/server/csqceffects.qc @@ -1,7 +1,7 @@ void te_csqc_lightningarc(vector from,vector to) { WriteByte(MSG_BROADCAST, SVC_TEMPENTITY); - WriteByte(MSG_BROADCAST, TE_CSQC_ARC); + WriteByte(MSG_BROADCAST, TE_CSQC_LIGHTNINGARC); WriteCoord(MSG_BROADCAST, from_x); WriteCoord(MSG_BROADCAST, from_y); diff --git a/qcsrc/server/csqcprojectile.qc b/qcsrc/server/csqcprojectile.qc new file mode 100644 index 000000000..3c747bdbb --- /dev/null +++ b/qcsrc/server/csqcprojectile.qc @@ -0,0 +1,118 @@ +.float csqcprojectile_type; + +float CSQCProjectile_SendEntity(entity to, float sf) +{ + float ft, fr; + + // note: flag 0x08 = no trail please (teleport bit) + sf = sf & 0x0F; + + if(self.csqcprojectile_clientanimate) + sf |= 0x80; // client animated, not interpolated + + if(self.flags & FL_ONGROUND) + sf |= 0x40; + + ft = fr = 0; + if(self.fade_time != 0 || self.fade_rate != 0) + { + ft = (self.fade_time - time) / sys_frametime; + fr = (1 / self.fade_rate) / sys_frametime; + if(ft <= 255 && fr <= 255 && fr >= 1) + sf |= 0x20; + } + + if(self.gravity != 0) + sf |= 0x10; + + WriteByte(MSG_ENTITY, ENT_CLIENT_PROJECTILE); + WriteByte(MSG_ENTITY, sf); + + if(sf & 1) + { + WriteCoord(MSG_ENTITY, self.origin_x); + WriteCoord(MSG_ENTITY, self.origin_y); + WriteCoord(MSG_ENTITY, self.origin_z); + + if(sf & 0x80) + { + WriteCoord(MSG_ENTITY, self.velocity_x); + WriteCoord(MSG_ENTITY, self.velocity_y); + WriteCoord(MSG_ENTITY, self.velocity_z); + if(sf & 0x10) + WriteCoord(MSG_ENTITY, self.gravity); + } + + if(sf & 0x20) + { + WriteByte(MSG_ENTITY, ft); + WriteByte(MSG_ENTITY, fr); + } + + WriteByte(MSG_ENTITY, self.realowner.team); + } + + if(sf & 2) + WriteByte(MSG_ENTITY, self.csqcprojectile_type); // TODO maybe put this into sf? + + return 1; +} + +.vector csqcprojectile_oldorigin; +void CSQCProjectile_Check(entity e) +{ + if(e.csqcprojectile_clientanimate) + if(e.flags & FL_ONGROUND) + if(e.origin != e.csqcprojectile_oldorigin) + UpdateCSQCProjectile(e); + e.csqcprojectile_oldorigin = e.origin; +} + +void CSQCProjectile(entity e, float clientanimate, float type, float docull) +{ + Net_LinkEntity(e, docull, 0, CSQCProjectile_SendEntity); + + e.csqcprojectile_clientanimate = clientanimate; + + if(e.movetype == MOVETYPE_TOSS || e.movetype == MOVETYPE_BOUNCE) + { + if(e.gravity == 0) + e.gravity = 1; + } + else + e.gravity = 0; + + if(!sound_allowed(MSG_BROADCAST, e)) + type |= 0x80; + e.csqcprojectile_type = type; +} + +// FIXME HACK +float ItemSend(entity to, float sf); +void ItemUpdate(entity item); +// END HACK +void UpdateCSQCProjectile(entity e) +{ + if(e.SendEntity == CSQCProjectile_SendEntity) + { + // send new origin data + e.SendFlags |= 0x01; + } +// FIXME HACK + else if(e.SendEntity == ItemSend) + { + ItemUpdate(e); + } +// END HACK +} + +void UpdateCSQCProjectileAfterTeleport(entity e) +{ + if(e.SendEntity == CSQCProjectile_SendEntity) + { + // send new origin data + e.SendFlags |= 0x01; + // mark as teleported + e.SendFlags |= 0x08; + } +} diff --git a/qcsrc/server/csqcprojectile.qh b/qcsrc/server/csqcprojectile.qh new file mode 100644 index 000000000..e00c0988b --- /dev/null +++ b/qcsrc/server/csqcprojectile.qh @@ -0,0 +1,6 @@ +.float csqcprojectile_clientanimate; + +void CSQCProjectile(entity e, float clientanimate, float type, float docull); +void UpdateCSQCProjectile(entity e); +void UpdateCSQCProjectileAfterTeleport(entity e); +void CSQCProjectile_Check(entity e); diff --git a/qcsrc/server/defs.qh b/qcsrc/server/defs.qh index 0d03d52cc..dd0b5c22b 100644 --- a/qcsrc/server/defs.qh +++ b/qcsrc/server/defs.qh @@ -172,7 +172,7 @@ void setanim(entity e, vector anim, float looping, float override, float restart .string item_pickupsound; // definitions for weaponsystem -// more WEAPONTODO: move these to their proper files + .entity weaponentity; .entity exteriorweaponentity; .vector weaponentity_glowmod; @@ -182,9 +182,8 @@ void setanim(entity e, vector anim, float looping, float override, float restart .float switchingweapon; // weapon currently being switched to (is copied from switchweapon once switch is possible) .string weaponname; // name of .weapon -// WEAPONTODO .float autoswitch; -//float WEP_ACTION(float wpn, float wrequest); +float weapon_action(float wpn, float wrequest); float client_hasweapon(entity cl, float wpn, float andammo, float complain); void w_clear(); void w_ready(); @@ -192,6 +191,9 @@ void w_ready(); .float weapon_nextthink; .void() weapon_think; +//float PLAYER_WEAPONSELECTION_DELAY = ); +const float PLAYER_WEAPONSELECTION_SPEED = 18; +const vector PLAYER_WEAPONSELECTION_RANGE = '0 20 -40'; // weapon states (self.weaponentity.state) const float WS_CLEAR = 0; // no weapon selected @@ -286,12 +288,16 @@ string gamemode_name; float startitem_failed; +typedef .float floatfield; +floatfield Item_CounterField(float it); + +float W_AmmoItemCode(float wpn); +string W_Name(float weaponid); string W_Apply_Weaponreplace(string in); void FixIntermissionClient(entity e); void FixClientCvars(entity e); -// WEAPONTODO: remove this WepSet weaponsInMap; .float respawn_countdown; // next number to count @@ -506,6 +512,7 @@ float servertime, serverprevtime, serverframetime; .float stat_shotorg; // networked stat for trueaim HUD string matchid; +.float hitplotfh; .float last_pickup; @@ -521,6 +528,8 @@ float client_cefc_accumulator; float client_cefc_accumulatortime; #endif +..float current_ammo; + .float weapon_load[WEP_MAXCOUNT]; .float ammo_none; // used by the reloading system, must always be 0 .float clip_load; @@ -529,9 +538,9 @@ float client_cefc_accumulatortime; .entity lastrocket; .float minelayer_mines; -.float vortex_charge; -.float vortex_charge_rottime; -.float vortex_chargepool_ammo; +.float nex_charge; +.float nex_charge_rottime; +.float nex_chargepool_ammo; .float hagar_load; .float grab; // 0 = can't grab, 1 = owner can grab, 2 = owner and team mates can grab, 3 = anyone can grab @@ -551,6 +560,9 @@ string deathmessage; .float just_joined; +.float cvar_cl_accuracy_data_share; +.float cvar_cl_accuracy_data_receive; + .float cvar_cl_weaponimpulsemode; .float selectweapon; // last selected weapon of the player diff --git a/qcsrc/server/func_breakable.qc b/qcsrc/server/func_breakable.qc index 0bf71059e..d67e79cd4 100644 --- a/qcsrc/server/func_breakable.qc +++ b/qcsrc/server/func_breakable.qc @@ -173,7 +173,7 @@ void func_breakable_destroy() { sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM); if(self.dmg) - RadiusDamage(self, activator, self.dmg, self.dmg_edge, self.dmg_radius, self, world, self.dmg_force, DEATH_HURTTRIGGER, world); + RadiusDamage(self, activator, self.dmg, self.dmg_edge, self.dmg_radius, self, self.dmg_force, DEATH_HURTTRIGGER, world); if(self.cnt) pointparticles(self.cnt, self.absmin * 0.5 + self.absmax * 0.5, '0 0 0', self.count); diff --git a/qcsrc/server/g_damage.qc b/qcsrc/server/g_damage.qc index ec8333070..47443e6d7 100644 --- a/qcsrc/server/g_damage.qc +++ b/qcsrc/server/g_damage.qc @@ -115,7 +115,7 @@ void GiveFrags (entity attacker, entity targ, float f, float deathtype) else if(!(attacker.weapons & WepSet_FromWeapon(culprit))) culprit = attacker.weapon; - if(g_weaponarena_random_with_laser && culprit == WEP_BLASTER) // WEAPONTODO: Shouldn't this be in a mutator? + if(g_weaponarena_random_with_laser && culprit == WEP_LASER) { // no exchange } @@ -287,7 +287,7 @@ float Obituary_WeaponDeath( if(death_weapon) { w_deathtype = deathtype; - float death_message = WEP_ACTION(death_weapon, ((murder) ? WR_KILLMESSAGE : WR_SUICIDEMESSAGE)); + float death_message = weapon_action(death_weapon, ((murder) ? WR_KILLMESSAGE : WR_SUICIDEMESSAGE)); w_deathtype = FALSE; if(death_message) @@ -948,10 +948,11 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float } float RadiusDamage_running; -float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float inflictorselfdamage, float forceintensity, float deathtype, entity directhitentity) +float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity ignore, float forceintensity, float deathtype, entity directhitentity) // Returns total damage applies to creatures { entity targ; + vector blastorigin; vector force; float total_damage_to_creatures; entity next; @@ -971,161 +972,202 @@ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector in tfloordmg = autocvar_g_throughfloor_damage; tfloorforce = autocvar_g_throughfloor_force; + blastorigin = (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5); total_damage_to_creatures = 0; if(deathtype != (WEP_HOOK | HITTYPE_SECONDARY | HITTYPE_BOUNCE)) // only send gravity bomb damage once if(DEATH_WEAPONOF(deathtype) != WEP_TUBA) // do not send tuba damage (bandwidth hog) { - force = inflictorvelocity; + force = inflictor.velocity; if(vlen(force) == 0) force = '0 0 -1'; else force = normalize(force); if(forceintensity >= 0) - Damage_DamageInfo(inflictororigin, coredamage, edgedamage, rad, forceintensity * force, deathtype, 0, attacker); + Damage_DamageInfo(blastorigin, coredamage, edgedamage, rad, forceintensity * force, deathtype, 0, attacker); else - Damage_DamageInfo(inflictororigin, coredamage, edgedamage, -rad, (-forceintensity) * force, deathtype, 0, attacker); + Damage_DamageInfo(blastorigin, coredamage, edgedamage, -rad, (-forceintensity) * force, deathtype, 0, attacker); } stat_damagedone = 0; - targ = WarpZone_FindRadius (inflictororigin, rad + MAX_DAMAGEEXTRARADIUS, FALSE); + targ = WarpZone_FindRadius (blastorigin, rad + MAX_DAMAGEEXTRARADIUS, FALSE); while (targ) { next = targ.chain; - if ((targ != inflictor) || inflictorselfdamage) - if (((cantbe != targ) && !mustbe) || (mustbe == targ)) - if (targ.takedamage) - { - vector nearest; - vector diff; - float power; - - // LordHavoc: measure distance to nearest point on target (not origin) - // (this guarentees 100% damage on a touch impact) - nearest = targ.WarpZone_findradius_nearest; - diff = targ.WarpZone_findradius_dist; - // round up a little on the damage to ensure full damage on impacts - // and turn the distance into a fraction of the radius - power = 1 - ((vlen (diff) - bound(MIN_DAMAGEEXTRARADIUS, targ.damageextraradius, MAX_DAMAGEEXTRARADIUS)) / rad); - //bprint(" "); - //bprint(ftos(power)); - //if (targ == attacker) - // print(ftos(power), "\n"); - if (power > 0) + if (targ != inflictor) + if (ignore != targ) if(targ.takedamage) { - float finaldmg; - if (power > 1) - power = 1; - finaldmg = coredamage * power + edgedamage * (1 - power); - if (finaldmg > 0) + vector nearest; + vector diff; + float power; + + // LordHavoc: measure distance to nearest point on target (not origin) + // (this guarentees 100% damage on a touch impact) + nearest = targ.WarpZone_findradius_nearest; + diff = targ.WarpZone_findradius_dist; + // round up a little on the damage to ensure full damage on impacts + // and turn the distance into a fraction of the radius + power = 1 - ((vlen (diff) - bound(MIN_DAMAGEEXTRARADIUS, targ.damageextraradius, MAX_DAMAGEEXTRARADIUS)) / rad); + //bprint(" "); + //bprint(ftos(power)); + //if (targ == attacker) + // print(ftos(power), "\n"); + if (power > 0) { - float a; - float c; - vector hitloc; - vector myblastorigin; - vector center; + float finaldmg; + if (power > 1) + power = 1; + finaldmg = coredamage * power + edgedamage * (1 - power); + if (finaldmg > 0) + { + float a; + float c; + vector hitloc; + vector myblastorigin; + vector center; - myblastorigin = WarpZone_TransformOrigin(targ, inflictororigin); + myblastorigin = WarpZone_TransformOrigin(targ, blastorigin); - // if it's a player, use the view origin as reference - center = CENTER_OR_VIEWOFS(targ); + // if it's a player, use the view origin as reference + center = CENTER_OR_VIEWOFS(targ); - force = normalize(center - myblastorigin); - force = force * (finaldmg / coredamage) * forceintensity; - hitloc = nearest; + force = normalize(center - myblastorigin); + force = force * (finaldmg / coredamage) * forceintensity; + hitloc = nearest; - if(deathtype & WEP_BLASTER) - force *= WEP_CVAR_BOTH(blaster, !(deathtype & HITTYPE_SECONDARY), force_zscale); + if(targ != directhitentity) + { + float hits; + float total; + float hitratio; + float mininv_f, mininv_d; - if(targ != directhitentity) - { - float hits; - float total; - float hitratio; - float mininv_f, mininv_d; + // test line of sight to multiple positions on box, + // and do damage if any of them hit + hits = 0; - // test line of sight to multiple positions on box, - // and do damage if any of them hit - hits = 0; + // we know: max stddev of hitratio = 1 / (2 * sqrt(n)) + // so for a given max stddev: + // n = (1 / (2 * max stddev of hitratio))^2 - // we know: max stddev of hitratio = 1 / (2 * sqrt(n)) - // so for a given max stddev: - // n = (1 / (2 * max stddev of hitratio))^2 + mininv_d = (finaldmg * (1-tfloordmg)) / autocvar_g_throughfloor_damage_max_stddev; + mininv_f = (vlen(force) * (1-tfloorforce)) / autocvar_g_throughfloor_force_max_stddev; - mininv_d = (finaldmg * (1-tfloordmg)) / autocvar_g_throughfloor_damage_max_stddev; - mininv_f = (vlen(force) * (1-tfloorforce)) / autocvar_g_throughfloor_force_max_stddev; + if(autocvar_g_throughfloor_debug) + printf("THROUGHFLOOR: D=%f F=%f max(dD)=1/%f max(dF)=1/%f", finaldmg, vlen(force), mininv_d, mininv_f); - if(autocvar_g_throughfloor_debug) - printf("THROUGHFLOOR: D=%f F=%f max(dD)=1/%f max(dF)=1/%f", finaldmg, vlen(force), mininv_d, mininv_f); + total = 0.25 * pow(max(mininv_f, mininv_d), 2); + if(autocvar_g_throughfloor_debug) + printf(" steps=%f", total); - total = 0.25 * pow(max(mininv_f, mininv_d), 2); + if (IS_PLAYER(targ)) + total = ceil(bound(autocvar_g_throughfloor_min_steps_player, total, autocvar_g_throughfloor_max_steps_player)); + else + total = ceil(bound(autocvar_g_throughfloor_min_steps_other, total, autocvar_g_throughfloor_max_steps_other)); - if(autocvar_g_throughfloor_debug) - printf(" steps=%f", total); + if(autocvar_g_throughfloor_debug) + printf(" steps=%f dD=%f dF=%f", total, finaldmg * (1-tfloordmg) / (2 * sqrt(total)), vlen(force) * (1-tfloorforce) / (2 * sqrt(total))); + for(c = 0; c < total; ++c) + { + //traceline(targ.WarpZone_findradius_findorigin, nearest, MOVE_NOMONSTERS, inflictor); + WarpZone_TraceLine(blastorigin, WarpZone_UnTransformOrigin(targ, nearest), MOVE_NOMONSTERS, inflictor); + if (trace_fraction == 1 || trace_ent == targ) + { + ++hits; + if (hits > 1) + hitloc = hitloc + nearest; + else + hitloc = nearest; + } + nearest_x = targ.origin_x + targ.mins_x + random() * targ.size_x; + nearest_y = targ.origin_y + targ.mins_y + random() * targ.size_y; + nearest_z = targ.origin_z + targ.mins_z + random() * targ.size_z; + } - if (IS_PLAYER(targ)) - total = ceil(bound(autocvar_g_throughfloor_min_steps_player, total, autocvar_g_throughfloor_max_steps_player)); - else - total = ceil(bound(autocvar_g_throughfloor_min_steps_other, total, autocvar_g_throughfloor_max_steps_other)); + nearest = hitloc * (1 / max(1, hits)); + hitratio = (hits / total); + a = bound(0, tfloordmg + (1-tfloordmg) * hitratio, 1); + finaldmg = finaldmg * a; + a = bound(0, tfloorforce + (1-tfloorforce) * hitratio, 1); + force = force * a; - if(autocvar_g_throughfloor_debug) - printf(" steps=%f dD=%f dF=%f", total, finaldmg * (1-tfloordmg) / (2 * sqrt(total)), vlen(force) * (1-tfloorforce) / (2 * sqrt(total))); + if(autocvar_g_throughfloor_debug) + printf(" D=%f F=%f\n", finaldmg, vlen(force)); + } - for(c = 0; c < total; ++c) + // laser force adjustments :P + if(DEATH_WEAPONOF(deathtype) == WEP_LASER) { - //traceline(targ.WarpZone_findradius_findorigin, nearest, MOVE_NOMONSTERS, inflictor); - WarpZone_TraceLine(inflictororigin, WarpZone_UnTransformOrigin(targ, nearest), MOVE_NOMONSTERS, inflictor); - if (trace_fraction == 1 || trace_ent == targ) + if (targ == attacker) { - ++hits; - if (hits > 1) - hitloc = hitloc + nearest; + vector vel; + + float force_zscale; + float force_velocitybiasramp; + float force_velocitybias; + + force_velocitybiasramp = autocvar_sv_maxspeed; + if(deathtype & HITTYPE_SECONDARY) + { + force_zscale = autocvar_g_balance_laser_secondary_force_zscale; + force_velocitybias = autocvar_g_balance_laser_secondary_force_velocitybias; + } else - hitloc = nearest; + { + force_zscale = autocvar_g_balance_laser_primary_force_zscale; + force_velocitybias = autocvar_g_balance_laser_primary_force_velocitybias; + } + + vel = targ.velocity; + vel_z = 0; + vel = normalize(vel) * bound(0, vlen(vel) / force_velocitybiasramp, 1) * force_velocitybias; + force = + vlen(force) + * + normalize(normalize(force) + vel); + + force_z *= force_zscale; + } + else + { + if(deathtype & HITTYPE_SECONDARY) + { + force *= autocvar_g_balance_laser_secondary_force_other_scale; + } + else + { + force *= autocvar_g_balance_laser_primary_force_other_scale; + } } - nearest_x = targ.origin_x + targ.mins_x + random() * targ.size_x; - nearest_y = targ.origin_y + targ.mins_y + random() * targ.size_y; - nearest_z = targ.origin_z + targ.mins_z + random() * targ.size_z; } - nearest = hitloc * (1 / max(1, hits)); - hitratio = (hits / total); - a = bound(0, tfloordmg + (1-tfloordmg) * hitratio, 1); - finaldmg = finaldmg * a; - a = bound(0, tfloorforce + (1-tfloorforce) * hitratio, 1); - force = force * a; - - if(autocvar_g_throughfloor_debug) - printf(" D=%f F=%f\n", finaldmg, vlen(force)); - } - - //if (targ == attacker) - //{ - // print("hits ", ftos(hits), " / ", ftos(total)); - // print(" finaldmg ", ftos(finaldmg), " force ", vtos(force)); - // print(" (", ftos(a), ")\n"); - //} - if(finaldmg || vlen(force)) - { - if(targ.iscreature) + //if (targ == attacker) + //{ + // print("hits ", ftos(hits), " / ", ftos(total)); + // print(" finaldmg ", ftos(finaldmg), " force ", vtos(force)); + // print(" (", ftos(a), ")\n"); + //} + if(finaldmg || vlen(force)) { - total_damage_to_creatures += finaldmg; + if(targ.iscreature) + { + total_damage_to_creatures += finaldmg; - if(accuracy_isgooddamage(attacker, targ)) - stat_damagedone += finaldmg; - } + if(accuracy_isgooddamage(attacker, targ)) + stat_damagedone += finaldmg; + } - if(targ == directhitentity || DEATH_ISSPECIAL(deathtype)) - Damage (targ, inflictor, attacker, finaldmg, deathtype, nearest, force); - else - Damage (targ, inflictor, attacker, finaldmg, deathtype | HITTYPE_SPLASH, nearest, force); + if(targ == directhitentity || DEATH_ISSPECIAL(deathtype)) + Damage (targ, inflictor, attacker, finaldmg, deathtype, nearest, force); + else + Damage (targ, inflictor, attacker, finaldmg, deathtype | HITTYPE_SPLASH, nearest, force); + } } } } - } targ = next; } @@ -1137,11 +1179,6 @@ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector in return total_damage_to_creatures; } -float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, float deathtype, entity directhitentity) -{ - return RadiusDamageForSource (inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker, coredamage, edgedamage, rad, cantbe, mustbe, FALSE, forceintensity, deathtype, directhitentity); -} - .float fire_damagepersec; .float fire_endtime; .float fire_deathtype; diff --git a/qcsrc/server/g_hook.qc b/qcsrc/server/g_hook.qc index 90b91ad3d..4e1b63400 100644 --- a/qcsrc/server/g_hook.qc +++ b/qcsrc/server/g_hook.qc @@ -335,7 +335,7 @@ void FireGrapplingHook (void) missile.state = 0; // not latched onto anything - W_SetupProjVelocity_Explicit(missile, v_forward, v_up, autocvar_g_balance_grapplehook_speed_fly, 0, 0, 0, FALSE); + W_SetupProjectileVelocityEx(missile, v_forward, v_up, autocvar_g_balance_grapplehook_speed_fly, 0, 0, 0, FALSE); missile.angles = vectoangles (missile.velocity); //missile.glow_color = 250; // 244, 250 @@ -476,7 +476,7 @@ void GrappleHookInit() } else { - WEP_ACTION(WEP_HOOK, WR_INIT); + weapon_action(WEP_HOOK, WR_PRECACHE); hook_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK), FALSE, FALSE, 1); hook_shotorigin[1] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK), FALSE, FALSE, 2); hook_shotorigin[2] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK), FALSE, FALSE, 3); diff --git a/qcsrc/server/g_world.qc b/qcsrc/server/g_world.qc index bd685ba1f..a1460ded8 100644 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@ -653,6 +653,8 @@ void spawnfunc_worldspawn (void) InitGameplayMode(); readlevelcvars(); GrappleHookInit(); + ElectroInit(); + LaserInit(); player_count = 0; bot_waypoints_for_items = autocvar_g_waypoints_for_items; @@ -779,7 +781,6 @@ void spawnfunc_worldspawn (void) addstat(STAT_SUPERWEAPONS_FINISHED, AS_FLOAT, superweapons_finished); addstat(STAT_PRESSED_KEYS, AS_FLOAT, pressedkeys); addstat(STAT_FUEL, AS_INT, ammo_fuel); - addstat(STAT_PLASMA, AS_INT, ammo_plasma); addstat(STAT_SHOTORG, AS_INT, stat_shotorg); addstat(STAT_LEADLIMIT, AS_FLOAT, stat_leadlimit); addstat(STAT_WEAPON_CLIPLOAD, AS_INT, clip_load); @@ -789,8 +790,8 @@ void spawnfunc_worldspawn (void) addstat(STAT_TYPEHIT_TIME, AS_FLOAT, typehit_time); addstat(STAT_LAYED_MINES, AS_INT, minelayer_mines); - addstat(STAT_VORTEX_CHARGE, AS_FLOAT, vortex_charge); - addstat(STAT_VORTEX_CHARGEPOOL, AS_FLOAT, vortex_chargepool_ammo); + addstat(STAT_NEX_CHARGE, AS_FLOAT, nex_charge); + addstat(STAT_NEX_CHARGEPOOL, AS_FLOAT, nex_chargepool_ammo); addstat(STAT_HAGAR_LOAD, AS_INT, hagar_load); diff --git a/qcsrc/server/miscfunctions.qc b/qcsrc/server/miscfunctions.qc index 368c27076..40421bbc0 100644 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@ -355,13 +355,12 @@ string formatmessage(string msg) wep = self.switchweapon; if (!wep) wep = self.cnt; - replacement = WEP_NAME(wep); + replacement = W_Name(wep); } else if (escape == "W") { if (self.items & IT_SHELLS) replacement = "shells"; else if (self.items & IT_NAILS) replacement = "bullets"; else if (self.items & IT_ROCKETS) replacement = "rockets"; else if (self.items & IT_CELLS) replacement = "cells"; - else if (self.items & IT_PLASMA) replacement = "plasma"; else replacement = "batteries"; // ;) } else if (escape == "x") { replacement = cursor_ent.netname; @@ -461,6 +460,7 @@ void GetCvars_handleFloatOnce(string thisname, float f, .float field, string nam stuffcmd(self, strcat("cl_cmd sendcvar ", name, "\n")); } } +float w_getbestweapon(entity e); string W_FixWeaponOrder_ForceComplete_AndBuildImpulseList(string wo) { string o; @@ -563,8 +563,6 @@ float g_pickup_rockets; float g_pickup_rockets_max; float g_pickup_cells; float g_pickup_cells_max; -float g_pickup_plasma; -float g_pickup_plasma_max; float g_pickup_fuel; float g_pickup_fuel_jetpack; float g_pickup_fuel_max; @@ -613,7 +611,6 @@ float start_ammo_shells; float start_ammo_nails; float start_ammo_rockets; float start_ammo_cells; -float start_ammo_plasma; float start_ammo_fuel; float start_health; float start_armorvalue; @@ -625,13 +622,14 @@ float warmup_start_ammo_shells; float warmup_start_ammo_nails; float warmup_start_ammo_rockets; float warmup_start_ammo_cells; -float warmup_start_ammo_plasma; float warmup_start_ammo_fuel; float warmup_start_health; float warmup_start_armorvalue; float g_weapon_stay; -float want_weapon(entity weaponinfo, float allguns) // WEAPONTODO: what still needs done? +entity get_weaponinfo(float w); + +float want_weapon(string cvarprefix, entity weaponinfo, float allguns) { var float i = weaponinfo.weapon; var float d = 0; @@ -651,14 +649,14 @@ float want_weapon(entity weaponinfo, float allguns) // WEAPONTODO: what still ne else if (g_nexball) d = 0; // weapon is set a few lines later else - d = !(!weaponinfo.weaponstart); + d = (i == WEP_LASER || i == WEP_SHOTGUN); if(g_grappling_hook) // if possible, redirect off-hand hook to on-hand hook d |= (i == WEP_HOOK); - if(!g_cts && (weaponinfo.spawnflags & WEP_FLAG_MUTATORBLOCKED)) // never default mutator blocked guns + if(weaponinfo.spawnflags & WEP_FLAG_MUTATORBLOCKED) // never default mutator blocked guns d = 0; - var float t = weaponinfo.weaponstartoverride; + var float t = cvar(strcat(cvarprefix, weaponinfo.netname)); //print(strcat("want_weapon: ", weaponinfo.netname, " - d: ", ftos(d), ", t: ", ftos(t), ". \n")); @@ -689,7 +687,6 @@ void readplayerstartcvars() start_ammo_nails = 0; start_ammo_rockets = 0; start_ammo_cells = 0; - start_ammo_plasma = 0; start_health = cvar("g_balance_health_start"); start_armorvalue = cvar("g_balance_armor_start"); @@ -782,7 +779,7 @@ void readplayerstartcvars() for (i = WEP_FIRST; i <= WEP_LAST; ++i) { e = get_weaponinfo(i); - float w = want_weapon(e, FALSE); + float w = want_weapon("g_start_weapon_", e, FALSE); if(w & 1) start_weapons |= WepSet_FromWeapon(i); if(w & 2) @@ -800,7 +797,6 @@ void readplayerstartcvars() start_ammo_rockets = 999; start_ammo_shells = 999; start_ammo_cells = 999; - start_ammo_plasma = 999; start_ammo_nails = 999; start_ammo_fuel = 999; } @@ -810,7 +806,6 @@ void readplayerstartcvars() start_ammo_nails = cvar("g_start_ammo_nails"); start_ammo_rockets = cvar("g_start_ammo_rockets"); start_ammo_cells = cvar("g_start_ammo_cells"); - start_ammo_plasma = cvar("g_start_ammo_plasma"); start_ammo_fuel = cvar("g_start_ammo_fuel"); } @@ -842,7 +837,7 @@ void readplayerstartcvars() for (i = WEP_FIRST; i <= WEP_LAST; ++i) { e = get_weaponinfo(i); - float w = want_weapon(e, g_warmup_allguns); + float w = want_weapon("g_start_weapon_", e, g_warmup_allguns); if(w & 1) warmup_start_weapons |= WepSet_FromWeapon(i); if(w & 2) @@ -873,20 +868,18 @@ void readplayerstartcvars() { e = get_weaponinfo(i); if(precache_weapons & WepSet_FromWeapon(i)) - WEP_ACTION(i, WR_INIT); + weapon_action(i, WR_PRECACHE); } start_ammo_shells = max(0, start_ammo_shells); start_ammo_nails = max(0, start_ammo_nails); start_ammo_cells = max(0, start_ammo_cells); - start_ammo_plasma = max(0, start_ammo_plasma); start_ammo_rockets = max(0, start_ammo_rockets); start_ammo_fuel = max(0, start_ammo_fuel); warmup_start_ammo_shells = max(0, warmup_start_ammo_shells); warmup_start_ammo_nails = max(0, warmup_start_ammo_nails); warmup_start_ammo_cells = max(0, warmup_start_ammo_cells); - warmup_start_ammo_plasma = max(0, warmup_start_ammo_plasma); warmup_start_ammo_rockets = max(0, warmup_start_ammo_rockets); warmup_start_ammo_fuel = max(0, warmup_start_ammo_fuel); } @@ -986,8 +979,6 @@ void readlevelcvars(void) g_pickup_rockets_max = cvar("g_pickup_rockets_max"); g_pickup_cells = cvar("g_pickup_cells"); g_pickup_cells_max = cvar("g_pickup_cells_max"); - g_pickup_plasma = cvar("g_pickup_plasma"); - g_pickup_plasma_max = cvar("g_pickup_plasma_max"); g_pickup_fuel = cvar("g_pickup_fuel"); g_pickup_fuel_jetpack = cvar("g_pickup_fuel_jetpack"); g_pickup_fuel_max = cvar("g_pickup_fuel_max"); @@ -1366,6 +1357,18 @@ void precache() precache_sound ("weapons/hook_impact.wav"); // hook } + if(autocvar_sv_precacheweapons) + { + //precache weapon models/sounds + float wep; + wep = WEP_FIRST; + while (wep <= WEP_LAST) + { + weapon_action(wep, WR_PRECACHE); + wep = wep + 1; + } + } + precache_model("models/elaser.mdl"); precache_model("models/laser.mdl"); precache_model("models/ebomb.mdl"); diff --git a/qcsrc/server/mutators/base.qh b/qcsrc/server/mutators/base.qh index 95d85d793..f4021eb4c 100644 --- a/qcsrc/server/mutators/base.qh +++ b/qcsrc/server/mutators/base.qh @@ -109,7 +109,7 @@ MUTATOR_HOOKABLE(WeaponRateFactor); float weapon_rate; MUTATOR_HOOKABLE(SetStartItems); - // adjusts {warmup_}start_{items,weapons,ammo_{cells,plasma,rockets,nails,shells,fuel}} + // adjusts {warmup_}start_{items,weapons,ammo_{cells,rockets,nails,shells,fuel}} MUTATOR_HOOKABLE(BuildMutatorsString); // appends ":mutatorname" to ret_string for logging diff --git a/qcsrc/server/mutators/gamemode_ca.qc b/qcsrc/server/mutators/gamemode_ca.qc index 0c5e01a6a..8b38ceb09 100644 --- a/qcsrc/server/mutators/gamemode_ca.qc +++ b/qcsrc/server/mutators/gamemode_ca.qc @@ -236,7 +236,6 @@ MUTATOR_HOOKFUNCTION(ca_SetStartItems) start_ammo_nails = warmup_start_ammo_nails = cvar("g_lms_start_ammo_nails"); start_ammo_rockets = warmup_start_ammo_rockets = cvar("g_lms_start_ammo_rockets"); start_ammo_cells = warmup_start_ammo_cells = cvar("g_lms_start_ammo_cells"); - start_ammo_plasma = warmup_start_ammo_plasma = cvar("g_lms_start_ammo_plasma"); start_ammo_fuel = warmup_start_ammo_fuel = cvar("g_lms_start_ammo_fuel"); return 0; diff --git a/qcsrc/server/mutators/gamemode_lms.qc b/qcsrc/server/mutators/gamemode_lms.qc index 0684ac8ed..fb0bb2e86 100644 --- a/qcsrc/server/mutators/gamemode_lms.qc +++ b/qcsrc/server/mutators/gamemode_lms.qc @@ -135,7 +135,6 @@ MUTATOR_HOOKFUNCTION(lms_SetStartItems) start_ammo_nails = warmup_start_ammo_nails = cvar("g_lms_start_ammo_nails"); start_ammo_rockets = warmup_start_ammo_rockets = cvar("g_lms_start_ammo_rockets"); start_ammo_cells = warmup_start_ammo_cells = cvar("g_lms_start_ammo_cells"); - start_ammo_plasma = warmup_start_ammo_plasma = cvar("g_lms_start_ammo_plasma"); start_ammo_fuel = warmup_start_ammo_fuel = cvar("g_lms_start_ammo_fuel"); return FALSE; diff --git a/qcsrc/server/mutators/gamemode_nexball.qc b/qcsrc/server/mutators/gamemode_nexball.qc index 85377836d..8695ca31b 100644 --- a/qcsrc/server/mutators/gamemode_nexball.qc +++ b/qcsrc/server/mutators/gamemode_nexball.qc @@ -142,7 +142,7 @@ void GiveBall(entity plyr, entity ball) self.weaponentity.weapons = self.weapons; self.weaponentity.switchweapon = self.weapon; self.weapons = WEPSET_PORTO; - WEP_ACTION(WEP_PORTO, WR_RESETPLAYER); + weapon_action(WEP_PORTO, WR_RESETPLAYER); self.switchweapon = WEP_PORTO; W_SwitchWeapon(WEP_PORTO); self = ownr; @@ -784,7 +784,7 @@ void W_Nexball_Attack2(void) setsize(missile, '0 0 0', '0 0 0'); setorigin(missile, w_shotorg); - W_SetupProjVelocity_Basic(missile, autocvar_g_balance_nexball_secondary_speed, 0); + W_SetupProjectileVelocity(missile, autocvar_g_balance_nexball_secondary_speed, 0); missile.angles = vectoangles(missile.velocity); missile.touch = W_Nexball_Touch; missile.think = SUB_Remove; @@ -855,7 +855,7 @@ float w_nexball_weapon(float req) weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready); } } - else if(req == WR_INIT) + else if(req == WR_PRECACHE) { precache_model("models/weapons/g_porto.md3"); precache_model("models/weapons/v_porto.md3"); @@ -867,7 +867,7 @@ float w_nexball_weapon(float req) } else if(req == WR_SETUP) { - //weapon_setup(WEP_PORTO); + weapon_setup(WEP_PORTO); } // No need to check WR_CHECKAMMO* or WR_AIM, it should always return TRUE return TRUE; @@ -930,7 +930,7 @@ MUTATOR_HOOKFUNCTION(nexball_PlayerPreThink) if(self.weaponentity.weapons) { self.weapons = self.weaponentity.weapons; - WEP_ACTION(WEP_PORTO, WR_RESETPLAYER); + weapon_action(WEP_PORTO, WR_RESETPLAYER); self.switchweapon = self.weaponentity.switchweapon; W_SwitchWeapon(self.switchweapon); @@ -976,7 +976,7 @@ MUTATOR_HOOKFUNCTION(nexball_SetStartItems) MUTATOR_HOOKFUNCTION(nexball_ForbidThrowing) { - if(self.weapon == WEP_MORTAR) + if(self.weapon == WEP_GRENADE_LAUNCHER) return TRUE; return FALSE; @@ -985,7 +985,7 @@ MUTATOR_HOOKFUNCTION(nexball_ForbidThrowing) MUTATOR_HOOKFUNCTION(nexball_FilterItem) { if(self.classname == "droppedweapon") - if(self.weapon == WEP_MORTAR) + if(self.weapon == WEP_GRENADE_LAUNCHER) return TRUE; return FALSE; @@ -1011,7 +1011,7 @@ MUTATOR_DEFINITION(gamemode_nexball) g_nexball_meter_period = rint(g_nexball_meter_period * 32) / 32; //Round to 1/32ths to send as a byte multiplied by 32 addstat(STAT_NB_METERSTART, AS_FLOAT, metertime); - W_Porto(WR_INIT); // abuse + w_porto(WR_PRECACHE); // abuse // General settings /* diff --git a/qcsrc/server/mutators/mutator_minstagib.qc b/qcsrc/server/mutators/mutator_minstagib.qc index d05e7e9c4..20811ad50 100644 --- a/qcsrc/server/mutators/mutator_minstagib.qc +++ b/qcsrc/server/mutators/mutator_minstagib.qc @@ -6,7 +6,7 @@ void spawnfunc_item_minst_cells (void) StartItem ("models/items/a_cells.md3", "misc/itempickup.wav", 45, 0, - "Vaporizer Ammo", IT_CELLS, 0, 0, generic_pickupevalfunc, 100); + "MinstaNex Ammo", IT_CELLS, 0, 0, generic_pickupevalfunc, 100); } void minstagib_health_mega() @@ -245,7 +245,7 @@ MUTATOR_HOOKFUNCTION(minstagib_PlayerDamage) } if(IS_PLAYER(frag_attacker)) - if(DEATH_ISWEAPON(frag_deathtype, WEP_VAPORIZER)) + if(DEATH_ISWEAPON(frag_deathtype, WEP_MINSTANEX)) if(frag_target.armorvalue) { frag_target.armorvalue -= 1; @@ -256,7 +256,7 @@ MUTATOR_HOOKFUNCTION(minstagib_PlayerDamage) } if(IS_PLAYER(frag_attacker)) - if(DEATH_ISWEAPON(frag_deathtype, WEP_BLASTER)) + if (DEATH_ISWEAPON(frag_deathtype, WEP_LASER)) { frag_damage = 0; frag_mirrordamage = 0; @@ -296,8 +296,8 @@ MUTATOR_HOOKFUNCTION(minstagib_SetStartItems) start_health = 100; start_armorvalue = 0; - start_weapons = WEPSET_VAPORIZER; - warmup_start_weapons = WEPSET_VAPORIZER; + start_weapons = WEPSET_MINSTANEX; + warmup_start_weapons = WEPSET_MINSTANEX; start_items |= IT_UNLIMITED_SUPERWEAPONS; return FALSE; @@ -308,13 +308,13 @@ MUTATOR_HOOKFUNCTION(minstagib_FilterItem) if(self.classname == "item_cells") return TRUE; // no normal cells? - if(self.weapon == WEP_VAPORIZER && self.classname == "droppedweapon") + if(self.weapon == WEP_MINSTANEX && self.classname == "droppedweapon") { self.ammo_cells = autocvar_g_minstagib_ammo_drop; return FALSE; } - if(self.weapon == WEP_DEVASTATOR || self.weapon == WEP_VORTEX) + if(self.weapon == WEP_ROCKET_LAUNCHER || self.weapon == WEP_NEX) { entity e = spawn(); setorigin(e, self.origin); diff --git a/qcsrc/server/mutators/mutator_nades.qc b/qcsrc/server/mutators/mutator_nades.qc index 70c4578bd..da75e25ac 100644 --- a/qcsrc/server/mutators/mutator_nades.qc +++ b/qcsrc/server/mutators/mutator_nades.qc @@ -250,7 +250,7 @@ void nade_ice_think() sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM); RadiusDamage(self, self.realowner, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage, - autocvar_g_nades_nade_radius, self, world, autocvar_g_nades_nade_force, self.projectiledeathtype, self.enemy); + autocvar_g_nades_nade_radius, self, autocvar_g_nades_nade_force, self.projectiledeathtype, self.enemy); Damage_DamageInfo(self.origin, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage, autocvar_g_nades_nade_radius, '1 1 1' * autocvar_g_nades_nade_force, self.projectiledeathtype, 0, self); } @@ -525,10 +525,12 @@ void nade_boom() sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM); sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM); + self.takedamage = DAMAGE_NO; + if(nade_blast) { RadiusDamage(self, self.realowner, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage, - autocvar_g_nades_nade_radius, self, world, autocvar_g_nades_nade_force, self.projectiledeathtype, self.enemy); + autocvar_g_nades_nade_radius, self, autocvar_g_nades_nade_force, self.projectiledeathtype, self.enemy); Damage_DamageInfo(self.origin, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage, autocvar_g_nades_nade_radius, '1 1 1' * autocvar_g_nades_nade_force, self.projectiledeathtype, 0, self); } @@ -573,19 +575,20 @@ void nade_damage(entity inflictor, entity attacker, float damage, float deathtyp if(self.nade_type == NADE_TYPE_TRANSLOCATE || self.nade_type == NADE_TYPE_SPAWN) return; - if(DEATH_ISWEAPON(deathtype, WEP_BLASTER)) + if(DEATH_ISWEAPON(deathtype, WEP_LASER)) return; - if(DEATH_ISWEAPON(deathtype, WEP_VORTEX) || DEATH_ISWEAPON(deathtype, WEP_VAPORIZER)) + if(DEATH_ISWEAPON(deathtype, WEP_NEX) || DEATH_ISWEAPON(deathtype, WEP_MINSTANEX)) { force *= 6; damage = self.max_health * 0.55; } - if(DEATH_ISWEAPON(deathtype, WEP_MACHINEGUN)) + if(DEATH_ISWEAPON(deathtype, WEP_UZI)) damage = self.max_health * 0.1; - if((DEATH_ISWEAPON(deathtype, WEP_SHOCKWAVE) || DEATH_ISWEAPON(deathtype, WEP_SHOTGUN)) && (deathtype & HITTYPE_SECONDARY)) // WEAPONTODO + if(DEATH_ISWEAPON(deathtype, WEP_SHOTGUN)) + if(deathtype & HITTYPE_SECONDARY) { damage = self.max_health * 0.1; force *= 10; diff --git a/qcsrc/server/mutators/mutator_new_toys.qc b/qcsrc/server/mutators/mutator_new_toys.qc index d540adee6..f11298451 100644 --- a/qcsrc/server/mutators/mutator_new_toys.qc +++ b/qcsrc/server/mutators/mutator_new_toys.qc @@ -1,7 +1,7 @@ /* -CORE laser vortex lg rl cry gl elec hagar fireb hook - vaporizer porto +CORE laser nex lg rl cry gl elec hagar fireb hook + minsta porto tuba NEW rifle hlac minel seeker @@ -18,28 +18,28 @@ weaponreplace lists. Entity: { -"classname" "weapon_vortex" +"classname" "weapon_nex" "new_toys" "rifle" } --> This will spawn as Rifle in this mutator ONLY, and as Vortex otherwise. +-> This will spawn as Rifle in this mutator ONLY, and as Nex otherwise. { -"classname" "weapon_vortext" -"new_toys" "vortex rifle" +"classname" "weapon_nex" +"new_toys" "nex rifle" } --> This will spawn as either Vortex or Rifle in this mutator ONLY, and as Vortex otherwise. +-> This will spawn as either Nex or Rifle in this mutator ONLY, and as Nex otherwise. { -"classname" "weapon_vortex" -"new_toys" "vortex" +"classname" "weapon_nex" +"new_toys" "nex" } --> This is always a Vortex. +-> This is always a Nex. If the map specifies no "new_toys" argument There will be two default replacements selectable: "replace all" and "replace random". -In "replace all" mode, e.g. Vortex will have the default replacement "rifle". -In "replace random" mode, Vortex will have the default replacement "vortex rifle". +In "replace all" mode, e.g. Nex will have the default replacement "rifle". +In "replace random" mode, Nex will have the default replacement "nex rifle". This mutator's replacements run BEFORE regular weaponreplace! @@ -87,7 +87,6 @@ float nt_IsNewToy(float w) case WEP_MINE_LAYER: case WEP_HLAC: case WEP_RIFLE: - case WEP_SHOTGUN: return TRUE; default: return FALSE; @@ -101,8 +100,7 @@ string nt_GetFullReplacement(string w) case "hagar": return "seeker"; case "rocketlauncher": return "minelayer"; case "uzi": return "hlac"; - case "vortex": return "rifle"; - case "shockwave": return "shotgun"; + case "nex": return "rifle"; default: return string_null; } } diff --git a/qcsrc/server/mutators/mutator_nix.qc b/qcsrc/server/mutators/mutator_nix.qc index 5ea5f1ad6..dc12b0520 100644 --- a/qcsrc/server/mutators/mutator_nix.qc +++ b/qcsrc/server/mutators/mutator_nix.qc @@ -1,8 +1,10 @@ float g_nix_with_laser; -// WEAPONTODO + float nix_weapon; +float nix_weapon_ammo; float nix_nextchange; float nix_nextweapon; +float nix_nextweapon_ammo; .float nix_lastchange_id; .float nix_lastinfotime; .float nix_nextincr; @@ -20,7 +22,7 @@ float NIX_CanChooseWeapon(float wpn) } else { - if(wpn == WEP_BLASTER && g_nix_with_laser) // WEAPONTODO: rename to g_nix_with_blaster + if(wpn == WEP_LASER && g_nix_with_laser) return FALSE; if(e.spawnflags & WEP_FLAG_MUTATORBLOCKED) return FALSE; @@ -37,6 +39,7 @@ void NIX_ChooseNextWeapon() if(NIX_CanChooseWeapon(j)) RandomSelection_Add(world, j, string_null, 1, (j != nix_weapon)); nix_nextweapon = RandomSelection_chosen_float; + nix_nextweapon_ammo = W_AmmoItemCode(nix_nextweapon); } void NIX_GiveCurrentWeapon() @@ -51,68 +54,65 @@ void NIX_GiveCurrentWeapon() if(dt <= 0) { nix_weapon = nix_nextweapon; + nix_weapon_ammo = nix_nextweapon_ammo; nix_nextweapon = 0; if (!nix_nextchange) // no round played yet? nix_nextchange = time; // start the first round now! else nix_nextchange = time + autocvar_g_balance_nix_roundtime; - //WEP_ACTION(nix_weapon, WR_INIT); // forget it, too slow + //weapon_action(nix_weapon, WR_PRECACHE); // forget it, too slow } - // get weapon info - entity e = get_weaponinfo(nix_weapon); - if(nix_nextchange != self.nix_lastchange_id) // this shall only be called once per round! { - self.ammo_shells = self.ammo_nails = self.ammo_rockets = self.ammo_cells = self.ammo_plasma = self.ammo_fuel = 0; - - if(self.items & IT_UNLIMITED_WEAPON_AMMO) + self.nix_lastchange_id = nix_nextchange; + if (self.items & IT_UNLIMITED_WEAPON_AMMO) { - switch(e.ammo_field) - { - case ammo_shells: self.ammo_shells = autocvar_g_pickup_shells_max; break; - case ammo_nails: self.ammo_nails = autocvar_g_pickup_nails_max; break; - case ammo_rockets: self.ammo_rockets = autocvar_g_pickup_rockets_max; break; - case ammo_cells: self.ammo_cells = autocvar_g_pickup_cells_max; break; - case ammo_plasma: self.ammo_plasma = autocvar_g_pickup_plasma_max; break; - case ammo_fuel: self.ammo_fuel = autocvar_g_pickup_fuel_max; break; - } + self.ammo_shells = (nix_weapon_ammo & IT_SHELLS) ? + autocvar_g_pickup_shells_max : 0; + self.ammo_nails = (nix_weapon_ammo & IT_NAILS) ? + autocvar_g_pickup_nails_max : 0; + self.ammo_rockets = (nix_weapon_ammo & IT_ROCKETS) ? + autocvar_g_pickup_rockets_max : 0; + self.ammo_cells = (nix_weapon_ammo & IT_CELLS) ? + autocvar_g_pickup_cells_max : 0; + self.ammo_fuel = (nix_weapon_ammo & IT_FUEL) ? + autocvar_g_pickup_fuel_max : 0; } else { - switch(e.ammo_field) - { - case ammo_shells: self.ammo_shells = autocvar_g_balance_nix_ammo_shells; break; - case ammo_nails: self.ammo_nails = autocvar_g_balance_nix_ammo_nails; break; - case ammo_rockets: self.ammo_rockets = autocvar_g_balance_nix_ammo_rockets; break; - case ammo_cells: self.ammo_cells = autocvar_g_balance_nix_ammo_cells; break; - case ammo_plasma: self.ammo_plasma = autocvar_g_balance_nix_ammo_plasma; break; - case ammo_fuel: self.ammo_fuel = autocvar_g_balance_nix_ammo_fuel; break; - } + self.ammo_shells = (nix_weapon_ammo & IT_SHELLS) ? + autocvar_g_balance_nix_ammo_shells : 0; + self.ammo_nails = (nix_weapon_ammo & IT_NAILS) ? + autocvar_g_balance_nix_ammo_nails : 0; + self.ammo_rockets = (nix_weapon_ammo & IT_ROCKETS) ? + autocvar_g_balance_nix_ammo_rockets : 0; + self.ammo_cells = (nix_weapon_ammo & IT_CELLS) ? + autocvar_g_balance_nix_ammo_cells : 0; + self.ammo_fuel = (nix_weapon_ammo & IT_FUEL) ? + autocvar_g_balance_nix_ammo_fuel : 0; } - self.nix_nextincr = time + autocvar_g_balance_nix_incrtime; if(dt >= 1 && dt <= 5) self.nix_lastinfotime = -42; else Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_NEWWEAPON, nix_weapon); - WEP_ACTION(nix_weapon, WR_RESETPLAYER); + weapon_action(nix_weapon, WR_RESETPLAYER); // all weapons must be fully loaded when we spawn + entity e; + e = get_weaponinfo(nix_weapon); if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars - self.(weapon_load[nix_weapon]) = e.reloading_ammo; + self.(weapon_load[nix_weapon]) = cvar(strcat("g_balance_", e.netname, "_reload_ammo")); // nex too - if(WEP_CVAR(vortex, charge)) + if(autocvar_g_balance_nex_charge) { - if(WEP_CVAR_SEC(vortex, chargepool)) - self.vortex_chargepool_ammo = 1; - self.vortex_charge = WEP_CVAR(vortex, charge_start); + if(autocvar_g_balance_nex_secondary_chargepool) + self.nex_chargepool_ammo = 1; + self.nex_charge = autocvar_g_balance_nex_charge_start; } - - // set last change info - self.nix_lastchange_id = nix_nextchange; } if(self.nix_lastinfotime != dt) { @@ -123,22 +123,22 @@ void NIX_GiveCurrentWeapon() if(!(self.items & IT_UNLIMITED_WEAPON_AMMO) && time > self.nix_nextincr) { - switch(e.ammo_field) - { - case ammo_shells: self.ammo_shells += autocvar_g_balance_nix_ammoincr_shells; break; - case ammo_nails: self.ammo_nails += autocvar_g_balance_nix_ammoincr_nails; break; - case ammo_rockets: self.ammo_rockets += autocvar_g_balance_nix_ammoincr_rockets; break; - case ammo_cells: self.ammo_cells += autocvar_g_balance_nix_ammoincr_cells; break; - case ammo_plasma: self.ammo_plasma += autocvar_g_balance_nix_ammoincr_plasma; break; - case ammo_fuel: self.ammo_fuel += autocvar_g_balance_nix_ammoincr_fuel; break; - } - + if (nix_weapon_ammo & IT_SHELLS) + self.ammo_shells = self.ammo_shells + autocvar_g_balance_nix_ammoincr_shells; + else if (nix_weapon_ammo & IT_NAILS) + self.ammo_nails = self.ammo_nails + autocvar_g_balance_nix_ammoincr_nails; + else if (nix_weapon_ammo & IT_ROCKETS) + self.ammo_rockets = self.ammo_rockets + autocvar_g_balance_nix_ammoincr_rockets; + else if (nix_weapon_ammo & IT_CELLS) + self.ammo_cells = self.ammo_cells + autocvar_g_balance_nix_ammoincr_cells; + if (nix_weapon_ammo & IT_FUEL) // hook uses cells and fuel + self.ammo_fuel = self.ammo_fuel + autocvar_g_balance_nix_ammoincr_fuel; self.nix_nextincr = time + autocvar_g_balance_nix_incrtime; } self.weapons = '0 0 0'; if(g_nix_with_laser) - self.weapons &= ~WEPSET_BLASTER; + self.weapons &= ~WEPSET_LASER; self.weapons |= WepSet_FromWeapon(nix_weapon); if(self.switchweapon != nix_weapon) @@ -152,7 +152,7 @@ void NIX_precache() float i; for (i = WEP_FIRST; i <= WEP_LAST; ++i) if (NIX_CanChooseWeapon(i)) - WEP_ACTION(i, WR_INIT); + weapon_action(i, WR_PRECACHE); } MUTATOR_HOOKFUNCTION(nix_ForbidThrowCurrentWeapon) @@ -259,7 +259,6 @@ MUTATOR_DEFINITION(mutator_nix) FOR_EACH_PLAYER(e) if(e.deadflag == DEAD_NO) { e.ammo_cells = start_ammo_cells; - e.ammo_plasma = start_ammo_plasma; e.ammo_shells = start_ammo_shells; e.ammo_nails = start_ammo_nails; e.ammo_rockets = start_ammo_rockets; diff --git a/qcsrc/server/mutators/mutator_touchexplode.qc b/qcsrc/server/mutators/mutator_touchexplode.qc index 5f02a8aba..30b01b0da 100644 --- a/qcsrc/server/mutators/mutator_touchexplode.qc +++ b/qcsrc/server/mutators/mutator_touchexplode.qc @@ -12,7 +12,7 @@ void PlayerTouchExplode(entity p1, entity p2) entity e; e = spawn(); setorigin(e, org); - RadiusDamage(e, world, autocvar_g_touchexplode_damage, autocvar_g_touchexplode_edgedamage, autocvar_g_touchexplode_radius, world, world, autocvar_g_touchexplode_force, DEATH_TOUCHEXPLODE, world); + RadiusDamage(e, world, autocvar_g_touchexplode_damage, autocvar_g_touchexplode_edgedamage, autocvar_g_touchexplode_radius, world, autocvar_g_touchexplode_force, DEATH_TOUCHEXPLODE, world); remove(e); } diff --git a/qcsrc/server/progs.src b/qcsrc/server/progs.src index 9cc8c9954..288b24775 100644 --- a/qcsrc/server/progs.src +++ b/qcsrc/server/progs.src @@ -11,6 +11,7 @@ sys-post.qh ../warpzonelib/common.qh ../warpzonelib/util_server.qh ../warpzonelib/server.qh + ../common/constants.qh ../common/stats.qh ../common/teams.qh @@ -19,6 +20,8 @@ sys-post.qh ../common/buffs.qh ../common/test.qh ../common/counting.qh +../common/items.qh +../common/explosion_equation.qh ../common/urllib.qh ../common/command/markup.qh ../common/command/rpn.qh @@ -30,21 +33,6 @@ sys-post.qh ../common/monsters/sv_monsters.qh ../common/monsters/spawn.qh -../common/weapons/config.qh -../common/weapons/weapons.qh // TODO -weapons/accuracy.qh -weapons/common.qh -weapons/csqcprojectile.qh // TODO -weapons/hitplot.qh -weapons/selection.qh -weapons/spawning.qh -weapons/throwing.qh -weapons/tracing.qh -weapons/weaponstats.qh -weapons/weaponsystem.qh - -t_items.qh - autocvars.qh constants.qh defs.qh // Should rename this, it has fields and globals @@ -70,7 +58,8 @@ command/getreplies.qh command/cmd.qh command/sv_cmd.qh - +accuracy.qh +csqcprojectile.qh ../common/csqcmodel_settings.qh ../csqcmodellib/common.qh ../csqcmodellib/sv_model.qh @@ -82,7 +71,9 @@ playerstats.qh portals.qh -g_hook.qh // TODO +g_hook.qh +w_electro.qh +w_laser.qh scores.qh @@ -149,20 +140,13 @@ g_models.qc item_key.qc secret.qc -weapons/accuracy.qc -weapons/common.qc -weapons/csqcprojectile.qc // TODO -weapons/hitplot.qc -weapons/selection.qc -weapons/spawning.qc -weapons/throwing.qc -weapons/tracing.qc -weapons/weaponstats.qc -weapons/weaponsystem.qc -../common/weapons/config.qc -../common/weapons/weapons.qc // TODO +cl_weaponsystem.qc +w_common.qc + +w_all.qc t_items.qc +cl_weapons.qc cl_impulse.qc ent_cs.qc @@ -225,10 +209,15 @@ target_spawn.qc func_breakable.qc target_music.qc +../common/items.qc + ../common/nades.qc ../common/buffs.qc + +accuracy.qc ../csqcmodellib/sv_model.qc +csqcprojectile.qc playerdemo.qc @@ -238,6 +227,8 @@ playerstats.qc round_handler.qc +../common/explosion_equation.qc + ../common/monsters/sv_monsters.qc ../common/monsters/monsters.qc diff --git a/qcsrc/server/t_items.qc b/qcsrc/server/t_items.qc index cc0cb773a..238c6cec5 100644 --- a/qcsrc/server/t_items.qc +++ b/qcsrc/server/t_items.qc @@ -1,4 +1,32 @@ +#define ISF_LOCATION 2 +#define ISF_MODEL 4 +#define ISF_STATUS 8 + #define ITS_STAYWEP 1 + #define ITS_ANIMATE1 2 + #define ITS_ANIMATE2 4 + #define ITS_AVAILABLE 8 + #define ITS_ALLOWFB 16 + #define ITS_ALLOWSI 32 + #define ITS_POWERUP 64 +#define ISF_COLORMAP 16 +#define ISF_DROP 32 +#define ISF_ANGLES 64 + +.float ItemStatus; + #ifdef CSQC + +var float autocvar_cl_animate_items = 1; +var float autocvar_cl_ghost_items = 0.45; +var vector autocvar_cl_ghost_items_color = '-1 -1 -1'; +var float autocvar_cl_fullbright_items = 0; +var vector autocvar_cl_weapon_stay_color = '2 0.5 0.5'; +var float autocvar_cl_weapon_stay_alpha = 0.75; +var float autocvar_cl_simple_items = 0; +var string autocvar_cl_simpleitems_postfix = "_simple"; +.float spawntime; +.float gravity; +.vector colormod; void ItemDraw() { if(self.gravity) @@ -67,17 +95,6 @@ void ItemRead(float _IsNew) self.move_angles = self.angles; } - if(sf & ISF_SIZE) - { - self.mins_x = ReadCoord(); - self.mins_y = ReadCoord(); - self.mins_z = ReadCoord(); - self.maxs_x = ReadCoord(); - self.maxs_y = ReadCoord(); - self.maxs_z = ReadCoord(); - setsize(self, self.mins, self.maxs); - } - if(sf & ISF_STATUS) // need to read/write status frist so model can handle simple, fb etc. { self.ItemStatus = ReadByte(); @@ -121,7 +138,7 @@ void ItemRead(float _IsNew) if(sf & ISF_MODEL) { self.drawmask = MASK_NORMAL; - self.movetype = MOVETYPE_TOSS; + self.movetype = MOVETYPE_NOCLIP; self.draw = ItemDraw; if(self.mdl) @@ -169,7 +186,7 @@ void ItemRead(float _IsNew) if(sf & ISF_DROP) { self.gravity = 1; - //self.move_angles = '0 0 0'; + self.move_angles = '0 0 0'; self.move_movetype = MOVETYPE_TOSS; self.move_velocity_x = ReadCoord(); self.move_velocity_y = ReadCoord(); @@ -199,6 +216,7 @@ void ItemRead(float _IsNew) #endif #ifdef SVQC +float autocvar_sv_simple_items; float ItemSend(entity to, float sf) { if(self.gravity) @@ -224,16 +242,6 @@ float ItemSend(entity to, float sf) WriteCoord(MSG_ENTITY, self.angles_z); } - if(sf & ISF_SIZE) - { - WriteCoord(MSG_ENTITY, self.mins_x); - WriteCoord(MSG_ENTITY, self.mins_y); - WriteCoord(MSG_ENTITY, self.mins_z); - WriteCoord(MSG_ENTITY, self.maxs_x); - WriteCoord(MSG_ENTITY, self.maxs_y); - WriteCoord(MSG_ENTITY, self.maxs_z); - } - if(sf & ISF_STATUS) WriteByte(MSG_ENTITY, self.ItemStatus); @@ -281,12 +289,63 @@ float have_pickup_item(void) if(autocvar_g_pickup_items == 0) return FALSE; if(g_weaponarena) - if(self.weapons || (self.items & IT_AMMO)) // no item or ammo pickups in weaponarena + if(self.weapons || (self.items & IT_AMMO)) return FALSE; } return TRUE; } +#define ITEM_RESPAWN_TICKS 10 + +#define ITEM_RESPAWNTIME(i) ((i).respawntime + crandom() * (i).respawntimejitter) + // range: respawntime - respawntimejitter .. respawntime + respawntimejitter +#define ITEM_RESPAWNTIME_INITIAL(i) (ITEM_RESPAWN_TICKS + random() * ((i).respawntime + (i).respawntimejitter - ITEM_RESPAWN_TICKS)) + // range: 10 .. respawntime + respawntimejitter + +floatfield Item_CounterField(float it) +{ + switch(it) + { + case IT_SHELLS: return ammo_shells; + case IT_NAILS: return ammo_nails; + case IT_ROCKETS: return ammo_rockets; + case IT_CELLS: return ammo_cells; + case IT_FUEL: return ammo_fuel; + case IT_5HP: return health; + case IT_25HP: return health; + case IT_HEALTH: return health; + case IT_ARMOR_SHARD: return armorvalue; + case IT_ARMOR: return armorvalue; + // add more things here (health, armor) + default: error("requested item has no counter field"); + } +#ifdef GMQCC + // should never happen + return health; +#endif +} + +string Item_CounterFieldName(float it) +{ + switch(it) + { + case IT_SHELLS: return "shells"; + case IT_NAILS: return "nails"; + case IT_ROCKETS: return "rockets"; + case IT_CELLS: return "cells"; + case IT_FUEL: return "fuel"; + + // add more things here (health, armor) + default: error("requested item has no counter field name"); + } +#ifdef GMQCC + // should never happen + return string_null; +#endif +} + +.float max_armorvalue; +.float pickup_anyway; /* float Item_Customize() { @@ -371,16 +430,6 @@ void Item_Show (entity e, float mode) e.SendFlags |= ISF_STATUS; } -void Item_Think() -{ - self.nextthink = time; - if(self.origin != self.oldorigin) - { - self.oldorigin = self.origin; - ItemUpdate(self); - } -} - void Item_Respawn (void) { Item_Show(self, 1); @@ -393,9 +442,6 @@ void Item_Respawn (void) sound (self, CH_TRIGGER, "misc/itemrespawn.wav", VOL_BASE, ATTEN_NORM); // play respawn sound setorigin (self, self.origin); - self.think = Item_Think; - self.nextthink = time; - //pointparticles(particleeffectnum("item_respawn"), self.origin + self.mins_z * '0 0 1' + '0 0 48', '0 0 0', 1); pointparticles(particleeffectnum("item_respawn"), self.origin + 0.5 * (self.mins + self.maxs), '0 0 0', 1); } @@ -434,7 +480,7 @@ void Item_RespawnCountdown (void) entity wi = get_weaponinfo(self.weapon); if(wi) { - name = wi.wpmodel; + name = wi.model2; rgb = '1 0 0'; } } @@ -459,19 +505,6 @@ void Item_RespawnCountdown (void) } } -void Item_RespawnThink() -{ - self.nextthink = time; - if(self.origin != self.oldorigin) - { - self.oldorigin = self.origin; - ItemUpdate(self); - } - - if(time >= self.wait) - Item_Respawn(); -} - void Item_ScheduleRespawnIn(entity e, float t) { if((e.flags & FL_POWERUP) || (e.weapons & WEPSET_SUPERWEAPONS)) @@ -482,9 +515,8 @@ void Item_ScheduleRespawnIn(entity e, float t) } else { - e.think = Item_RespawnThink; - e.nextthink = time; - e.wait = time + t; + e.think = Item_Respawn; + e.nextthink = time + t; } } @@ -505,25 +537,29 @@ void Item_ScheduleInitialRespawn(entity e) Item_ScheduleRespawnIn(e, game_starttime - time + ITEM_RESPAWNTIME_INITIAL(e)); } -float Item_GiveAmmoTo(entity item, entity player, .float ammotype, float ammomax, float mode) +const float ITEM_MODE_NONE = 0; +const float ITEM_MODE_HEALTH = 1; +const float ITEM_MODE_ARMOR = 2; +const float ITEM_MODE_FUEL = 3; +float Item_GiveAmmoTo(entity item, entity player, .float ammofield, float ammomax, float mode) { - if (!item.ammotype) + if (!item.ammofield) return FALSE; if (item.spawnshieldtime) { - if ((player.ammotype < ammomax) || item.pickup_anyway) + if ((player.ammofield < ammomax) || item.pickup_anyway) { - player.ammotype = bound(player.ammotype, ammomax, player.ammotype + item.ammotype); + player.ammofield = bound(player.ammofield, ammomax, player.ammofield + item.ammofield); goto YEAH; } } else if(g_weapon_stay == 2) { - float mi = min(item.ammotype, ammomax); - if (player.ammotype < mi) + float mi = min(item.ammofield, ammomax); + if (player.ammofield < mi) { - player.ammotype = mi; + player.ammofield = mi; goto YEAH; } } @@ -573,7 +609,6 @@ float Item_GiveTo(entity item, entity player) pickedup |= Item_GiveAmmoTo(item, player, ammo_nails, g_pickup_nails_max, ITEM_MODE_NONE); pickedup |= Item_GiveAmmoTo(item, player, ammo_rockets, g_pickup_rockets_max, ITEM_MODE_NONE); pickedup |= Item_GiveAmmoTo(item, player, ammo_cells, g_pickup_cells_max, ITEM_MODE_NONE); - pickedup |= Item_GiveAmmoTo(item, player, ammo_plasma, g_pickup_plasma_max, ITEM_MODE_NONE); pickedup |= Item_GiveAmmoTo(item, player, health, item.max_health, ITEM_MODE_HEALTH); pickedup |= Item_GiveAmmoTo(item, player, armorvalue, item.max_armorvalue, ITEM_MODE_ARMOR); @@ -721,8 +756,8 @@ void Item_Reset() if(self.classname != "droppedweapon") { - self.think = Item_Think; - self.nextthink = time; + self.think = func_null; + self.nextthink = 0; if(self.waypointsprite_attached) WaypointSprite_Kill(self.waypointsprite_attached); @@ -784,7 +819,7 @@ float weapon_pickupevalfunc(entity player, entity item) // If I can pick it up if(!item.spawnshieldtime) c = 0; - else if(player.ammo_cells || player.ammo_shells || player.ammo_plasma || player.ammo_nails || player.ammo_rockets) + else if(player.ammo_cells || player.ammo_shells || player.ammo_nails || player.ammo_rockets) { // Skilled bots will grab more c = bound(0, skill / 10, 1) * 0.5; @@ -827,7 +862,7 @@ float weapon_pickupevalfunc(entity player, entity item) float commodity_pickupevalfunc(entity player, entity item) { float c, i; - float need_shells = FALSE, need_nails = FALSE, need_rockets = FALSE, need_cells = FALSE, need_plasma = FALSE, need_fuel = FALSE; + float need_shells = FALSE, need_nails = FALSE, need_rockets = FALSE, need_cells = FALSE, need_fuel = FALSE; entity wi; c = 0; @@ -847,8 +882,6 @@ float commodity_pickupevalfunc(entity player, entity item) need_rockets = TRUE; else if(wi.items & IT_CELLS) need_cells = TRUE; - else if(wi.items & IT_PLASMA) - need_plasma = TRUE; else if(wi.items & IT_FUEL) need_cells = TRUE; } @@ -872,10 +905,6 @@ float commodity_pickupevalfunc(entity player, entity item) if (item.ammo_cells) if (player.ammo_cells < g_pickup_cells_max) c = c + max(0, 1 - player.ammo_cells / g_pickup_cells_max); - if (need_plasma) - if (item.ammo_plasma) - if (player.ammo_plasma < g_pickup_plasma_max) - c = c + max(0, 1 - player.ammo_plasma / g_pickup_plasma_max); if (need_fuel) if (item.ammo_fuel) if (player.ammo_fuel < g_pickup_fuel_max) @@ -896,6 +925,7 @@ void Item_Damage(entity inflictor, entity attacker, float damage, float deathtyp RemoveItem(); } +.float is_item; void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, float defaultrespawntimejitter, string itemname, float itemid, float weaponid, float itemflags, float(entity player, entity item) pickupevalfunc, float pickupbasevalue) { startitem_failed = FALSE; @@ -982,6 +1012,9 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, return; } + if(self.angles != '0 0 0') + self.SendFlags |= ISF_ANGLES; + self.reset = Item_Reset; // it's a level item if(self.spawnflags & 1) @@ -1000,7 +1033,6 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, setsize (self, '-16 -16 0', '16 16 48'); else setsize (self, '-16 -16 0', '16 16 32'); - // note droptofloor returns FALSE if stuck/or would fall too far droptofloor(); waypoint_spawnforitem(self); @@ -1104,10 +1136,6 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, Item_Reset(); Net_LinkEntity(self, FALSE, 0, ItemSend); - - self.SendFlags |= ISF_SIZE; - if(self.angles) - self.SendFlags |= ISF_ANGLES; // call this hook after everything else has been done if(MUTATOR_CALLHOOK(Item_Spawn)) @@ -1117,6 +1145,183 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, return; } } + +float weaponswapping; +float internalteam; + +void weapon_defaultspawnfunc(float wpn) +{ + entity e; + float t; + var .float ammofield; + string s; + entity oldself; + float i, j; + float f; + + if(self.classname != "droppedweapon" && self.classname != "replacedweapon") + { + e = get_weaponinfo(wpn); + + if(e.spawnflags & WEP_FLAG_MUTATORBLOCKED) + { + objerror("Attempted to spawn a mutator-blocked weapon rejected"); + startitem_failed = TRUE; + return; + } + + s = W_Apply_Weaponreplace(e.netname); + ret_string = s; + other = e; + MUTATOR_CALLHOOK(SetWeaponreplace); + s = ret_string; + if(s == "") + { + remove(self); + startitem_failed = TRUE; + return; + } + t = tokenize_console(s); + if(t >= 2) + { + self.team = --internalteam; + oldself = self; + for(i = 1; i < t; ++i) + { + s = argv(i); + for(j = WEP_FIRST; j <= WEP_LAST; ++j) + { + e = get_weaponinfo(j); + if(e.netname == s) + { + self = spawn(); + copyentity(oldself, self); + self.classname = "replacedweapon"; + weapon_defaultspawnfunc(j); + break; + } + } + if(j > WEP_LAST) + { + print("The weapon replace list for ", oldself.classname, " contains an unknown weapon ", s, ". Skipped.\n"); + } + } + self = oldself; + } + if(t >= 1) // always the case! + { + s = argv(0); + wpn = 0; + for(j = WEP_FIRST; j <= WEP_LAST; ++j) + { + e = get_weaponinfo(j); + if(e.netname == s) + { + wpn = j; + break; + } + } + if(j > WEP_LAST) + { + print("The weapon replace list for ", self.classname, " contains an unknown weapon ", s, ". Skipped.\n"); + } + } + if(wpn == 0) + { + remove(self); + startitem_failed = TRUE; + return; + } + } + + e = get_weaponinfo(wpn); + + if(!self.respawntime) + { + if(e.weapons & WEPSET_SUPERWEAPONS) + { + self.respawntime = g_pickup_respawntime_superweapon; + self.respawntimejitter = g_pickup_respawntimejitter_superweapon; + } + else + { + self.respawntime = g_pickup_respawntime_weapon; + self.respawntimejitter = g_pickup_respawntimejitter_weapon; + } + } + + if(e.weapons & WEPSET_SUPERWEAPONS) + if(!self.superweapons_finished) + self.superweapons_finished = autocvar_g_balance_superweapons_time; + + if(e.items) + { + for(i = 0, j = 1; i < 24; ++i, j *= 2) + { + if(e.items & j) + { + ammofield = Item_CounterField(j); + if(!self.ammofield) + self.ammofield = cvar(strcat("g_pickup_", Item_CounterFieldName(j), "_weapon")); + } + } + } + + // pickup anyway + if(g_pickup_weapons_anyway) + self.pickup_anyway = TRUE; + + f = FL_WEAPON; + + // no weapon-stay on superweapons + if(e.weapons & WEPSET_SUPERWEAPONS) + f |= FL_NO_WEAPON_STAY; + + // weapon stay isn't supported for teamed weapons + if(self.team) + f |= FL_NO_WEAPON_STAY; + + StartItem(e.model, "weapons/weaponpickup.wav", self.respawntime, self.respawntimejitter, e.message, 0, e.weapon, f, weapon_pickupevalfunc, e.bot_pickupbasevalue); + if (self.modelindex) // don't precache if self was removed + weapon_action(e.weapon, WR_PRECACHE); +} + +void spawnfunc_weapon_shotgun (void); +void spawnfunc_weapon_uzi (void) { + if(autocvar_sv_q3acompat_machineshotgunswap) + if(self.classname != "droppedweapon") + { + weapon_defaultspawnfunc(WEP_SHOTGUN); + return; + } + weapon_defaultspawnfunc(WEP_UZI); +} + +void spawnfunc_weapon_shotgun (void) { + if(autocvar_sv_q3acompat_machineshotgunswap) + if(self.classname != "droppedweapon") + { + weapon_defaultspawnfunc(WEP_UZI); + return; + } + weapon_defaultspawnfunc(WEP_SHOTGUN); +} + +void spawnfunc_weapon_nex (void) +{ + weapon_defaultspawnfunc(WEP_NEX); +} + +void spawnfunc_weapon_minstanex (void) +{ + weapon_defaultspawnfunc(WEP_MINSTANEX); +} + +void spawnfunc_weapon_rocketlauncher (void) +{ + weapon_defaultspawnfunc(WEP_ROCKET_LAUNCHER); +} + void spawnfunc_item_rockets (void) { if(!self.ammo_rockets) self.ammo_rockets = g_pickup_rockets; @@ -1152,15 +1357,6 @@ void spawnfunc_item_cells (void) { StartItem ("models/items/a_cells.md3", "misc/itempickup.wav", g_pickup_respawntime_ammo, g_pickup_respawntimejitter_ammo, "cells", IT_CELLS, 0, 0, commodity_pickupevalfunc, 2000); } -void spawnfunc_item_plasma() -{ - if(!self.ammo_plasma) - self.ammo_plasma = g_pickup_plasma; - if(!self.pickup_anyway) - self.pickup_anyway = g_pickup_ammo_anyway; - StartItem ("models/items/a_cells.md3", "misc/itempickup.wav", g_pickup_respawntime_ammo, g_pickup_respawntimejitter_ammo, "plasma", IT_PLASMA, 0, 0, commodity_pickupevalfunc, 2000); -} - void spawnfunc_item_shells (void) { if(!weaponswapping) if(autocvar_sv_q3acompat_machineshotgunswap) @@ -1282,6 +1478,7 @@ void spawnfunc_item_invincible (void) { // compatibility: void spawnfunc_item_quad (void) {self.classname = "item_strength";spawnfunc_item_strength();} +float GiveItems(entity e, float beginarg, float endarg); void target_items_use (void) { if(activator.classname == "droppedweapon") @@ -1352,7 +1549,7 @@ void spawnfunc_target_items (void) { self.weapons |= WepSet_FromWeapon(j); if(self.spawnflags == 0 || self.spawnflags == 2) - WEP_ACTION(e.weapon, WR_INIT); + weapon_action(e.weapon, WR_PRECACHE); break; } } @@ -1403,7 +1600,6 @@ void spawnfunc_target_items (void) if(self.ammo_nails != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.ammo_nails), "nails"); if(self.ammo_rockets != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.ammo_rockets), "rockets"); if(self.ammo_cells != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.ammo_cells), "cells"); - if(self.ammo_plasma != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.ammo_plasma), "plasma"); if(self.ammo_fuel != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.ammo_fuel), "fuel"); if(self.health != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.health), "health"); if(self.armorvalue != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.health), "armor"); @@ -1425,7 +1621,7 @@ void spawnfunc_target_items (void) e = get_weaponinfo(j); if(argv(i) == e.netname) { - WEP_ACTION(e.weapon, WR_INIT); + weapon_action(e.weapon, WR_PRECACHE); break; } } @@ -1465,6 +1661,13 @@ void spawnfunc_item_jetpack(void) StartItem ("models/items/g_jetpack.md3", "misc/itempickup.wav", g_pickup_respawntime_powerup, g_pickup_respawntimejitter_powerup, "Jet pack", IT_JETPACK, 0, FL_POWERUP, commodity_pickupevalfunc, BOT_PICKUP_RATING_LOW); } + +#define OP_SET 0 +#define OP_MIN 1 +#define OP_MAX 2 +#define OP_PLUS 3 +#define OP_MINUS 4 + float GiveWeapon(entity e, float wpn, float op, float val) { WepSet v0, v1; @@ -1574,6 +1777,14 @@ void GiveRot(entity e, float v0, float v1, .float rotfield, float rottime, .floa else if(v0 > v1) e.regenfield = max(e.regenfield, time + regentime); } + +#define PREGIVE_WEAPONS(e) WepSet save_weapons; save_weapons = e.weapons +#define PREGIVE(e,f) float save_##f; save_##f = (e).f +#define POSTGIVE_WEAPON(e,b,snd_incr,snd_decr) GiveSound((e), !!(save_weapons & WepSet_FromWeapon(b)), !!(e.weapons & WepSet_FromWeapon(b)), 0, snd_incr, snd_decr) +#define POSTGIVE_BIT(e,f,b,snd_incr,snd_decr) GiveSound((e), save_##f & (b), (e).f & (b), 0, snd_incr, snd_decr) +#define POSTGIVE_VALUE(e,f,t,snd_incr,snd_decr) GiveSound((e), save_##f, (e).f, t, snd_incr, snd_decr) +#define POSTGIVE_VALUE_ROT(e,f,t,rotfield,rottime,regenfield,regentime,snd_incr,snd_decr) GiveRot((e), save_##f, (e).f, rotfield, rottime, regenfield, regentime); GiveSound((e), save_##f, (e).f, t, snd_incr, snd_decr) + float GiveItems(entity e, float beginarg, float endarg) { float got, i, j, val, op; @@ -1602,7 +1813,6 @@ float GiveItems(entity e, float beginarg, float endarg) PREGIVE(e, superweapons_finished); PREGIVE(e, ammo_nails); PREGIVE(e, ammo_cells); - PREGIVE(e, ammo_plasma); PREGIVE(e, ammo_shells); PREGIVE(e, ammo_rockets); PREGIVE(e, ammo_fuel); @@ -1656,7 +1866,6 @@ float GiveItems(entity e, float beginarg, float endarg) } case "allammo": got += GiveValue(e, ammo_cells, op, val); - got += GiveValue(e, ammo_plasma, op, val); got += GiveValue(e, ammo_shells, op, val); got += GiveValue(e, ammo_nails, op, val); got += GiveValue(e, ammo_rockets, op, val); @@ -1689,9 +1898,6 @@ float GiveItems(entity e, float beginarg, float endarg) case "cells": got += GiveValue(e, ammo_cells, op, val); break; - case "plasma": - got += GiveValue(e, ammo_plasma, op, val); - break; case "shells": got += GiveValue(e, ammo_shells, op, val); break; @@ -1741,14 +1947,13 @@ float GiveItems(entity e, float beginarg, float endarg) POSTGIVE_WEAPON(e, j, "weapons/weaponpickup.wav", string_null); if (!(save_weapons & WepSet_FromWeapon(j))) if(e.weapons & WepSet_FromWeapon(j)) - WEP_ACTION(wi.weapon, WR_INIT); + weapon_action(wi.weapon, WR_PRECACHE); } } POSTGIVE_VALUE(e, strength_finished, 1, "misc/powerup.wav", "misc/poweroff.wav"); POSTGIVE_VALUE(e, invincible_finished, 1, "misc/powerup_shield.wav", "misc/poweroff.wav"); POSTGIVE_VALUE(e, ammo_nails, 0, "misc/itempickup.wav", string_null); POSTGIVE_VALUE(e, ammo_cells, 0, "misc/itempickup.wav", string_null); - POSTGIVE_VALUE(e, ammo_plasma, 0, "misc/itempickup.wav", string_null); POSTGIVE_VALUE(e, ammo_shells, 0, "misc/itempickup.wav", string_null); POSTGIVE_VALUE(e, ammo_rockets, 0, "misc/itempickup.wav", string_null); POSTGIVE_VALUE_ROT(e, ammo_fuel, 1, pauserotfuel_finished, autocvar_g_balance_pause_fuel_rot, pauseregen_finished, autocvar_g_balance_pause_fuel_regen, "misc/itempickup.wav", string_null); diff --git a/qcsrc/server/t_items.qh b/qcsrc/server/t_items.qh deleted file mode 100644 index 13cc3796f..000000000 --- a/qcsrc/server/t_items.qh +++ /dev/null @@ -1,169 +0,0 @@ -// constants -#define WANT_CONST /* we WANT these to be constant, but it conflicts with the declaration in dpdefs/progsdefs.qc */ -const float IT_UNLIMITED_WEAPON_AMMO = 1; // when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup. -const float IT_UNLIMITED_SUPERWEAPONS = 2; // when this bit is set, superweapons don't expire. Checkpoints can give this powerup. -const float IT_CTF_SHIELDED = 4; // set for the flag shield -const float IT_USING_JETPACK = 8; // confirmation that button is pressed -const float IT_JETPACK = 16; // actual item -const float IT_FUEL_REGEN = 32; // fuel regeneration trigger -// where is 64... ? -const float IT_FUEL = 128; -WANT_CONST float IT_SHELLS = 256; -WANT_CONST float IT_NAILS = 512; -WANT_CONST float IT_ROCKETS = 1024; -WANT_CONST float IT_CELLS = 2048; -const float IT_SUPERWEAPON = 4096; -const float IT_STRENGTH = 8192; -const float IT_INVINCIBLE = 16384; -const float IT_HEALTH = 32768; -const float IT_PLASMA = 65536; - -// shared value space (union): - // for items: - WANT_CONST float IT_KEY1 = 131072; - WANT_CONST float IT_KEY2 = 262144; - // for players: - const float IT_RED_FLAG_TAKEN = 32768; - const float IT_RED_FLAG_LOST = 65536; - const float IT_RED_FLAG_CARRYING = 98304; - const float IT_BLUE_FLAG_TAKEN = 131072; - const float IT_BLUE_FLAG_LOST = 262144; - const float IT_BLUE_FLAG_CARRYING = 393216; -// end - -const float IT_5HP = 524288; -const float IT_25HP = 1048576; -const float IT_ARMOR_SHARD = 2097152; -const float IT_ARMOR = 4194304; - -// item masks -const float IT_AMMO = 3968; // IT_FUEL | IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS | IT_PLASMA; -const float IT_PICKUPMASK = 51; // IT_FUEL_REGEN | IT_JETPACK | IT_UNLIMITED_AMMO; // strength and invincible are handled separately -const float IT_UNLIMITED_AMMO = 3; // IT_UNLIMITED_SUPERWEAPONS | IT_UNLIMITED_WEAPON_AMMO; - -const float AMMO_COUNT = 4; // amount of ammo types to show in the inventory panel - -// item networking -#define ISF_LOCATION 2 -#define ISF_MODEL 4 -#define ISF_STATUS 8 - #define ITS_STAYWEP 1 - #define ITS_ANIMATE1 2 - #define ITS_ANIMATE2 4 - #define ITS_AVAILABLE 8 - #define ITS_ALLOWFB 16 - #define ITS_ALLOWSI 32 - #define ITS_POWERUP 64 -#define ISF_COLORMAP 16 -#define ISF_DROP 32 -#define ISF_ANGLES 64 -#define ISF_SIZE 128 - -.float ItemStatus; - -#ifdef CSQC - -var float autocvar_cl_animate_items = 1; -var float autocvar_cl_ghost_items = 0.45; -var vector autocvar_cl_ghost_items_color = '-1 -1 -1'; -var float autocvar_cl_fullbright_items = 0; -var vector autocvar_cl_weapon_stay_color = '2 0.5 0.5'; -var float autocvar_cl_weapon_stay_alpha = 0.75; -var float autocvar_cl_simple_items = 0; -var string autocvar_cl_simpleitems_postfix = "_simple"; -.float spawntime; -.float gravity; -.vector colormod; -void ItemDraw(); - -void ItemDrawSimple(); - -void ItemRead(float _IsNew); - -#endif -#ifdef SVQC -float autocvar_sv_simple_items; -float ItemSend(entity to, float sf); - - -float have_pickup_item(void); - -#define ITEM_RESPAWN_TICKS 10 - -#define ITEM_RESPAWNTIME(i) ((i).respawntime + crandom() * (i).respawntimejitter) - // range: respawntime - respawntimejitter .. respawntime + respawntimejitter -#define ITEM_RESPAWNTIME_INITIAL(i) (ITEM_RESPAWN_TICKS + random() * ((i).respawntime + (i).respawntimejitter - ITEM_RESPAWN_TICKS)) - // range: 10 .. respawntime + respawntimejitter - -.float max_armorvalue; -.float pickup_anyway; - -void Item_Show (entity e, float mode); - -void Item_Respawn (void); - -void Item_RespawnCountdown (void); -void Item_ScheduleRespawnIn(entity e, float t); - -void Item_ScheduleRespawn(entity e); - -void Item_ScheduleInitialRespawn(entity e); -float ITEM_MODE_NONE = 0; -float ITEM_MODE_HEALTH = 1; -float ITEM_MODE_ARMOR = 2; -float ITEM_MODE_FUEL = 3; -float Item_GiveAmmoTo(entity item, entity player, .float ammotype, float ammomax, float mode); - -float Item_GiveTo(entity item, entity player); - -void Item_Touch (void); - -void Item_Reset(); - -void Item_FindTeam(); -// Savage: used for item garbage-collection -// TODO: perhaps nice special effect? - -float ItemSend(entity to, float sf); -void ItemUpdate(entity item); - -// pickup evaluation functions -// these functions decide how desirable an item is to the bots - -float generic_pickupevalfunc(entity player, entity item);// {return item.bot_pickupbasevalue;} // WEAPONTODO - -float weapon_pickupevalfunc(entity player, entity item); - -float commodity_pickupevalfunc(entity player, entity item); - -.float is_item; -void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, float defaultrespawntimejitter, string itemname, float itemid, float weaponid, float itemflags, float(entity player, entity item) pickupevalfunc, float pickupbasevalue); - - -void target_items_use (void); - -#define OP_SET 0 -#define OP_MIN 1 -#define OP_MAX 2 -#define OP_PLUS 3 -#define OP_MINUS 4 - -float GiveWeapon(entity e, float wpn, float op, float val); - -float GiveBit(entity e, .float fld, float bit, float op, float val); - -float GiveValue(entity e, .float fld, float op, float val); - -void GiveSound(entity e, float v0, float v1, float t, string snd_incr, string snd_decr); - -void GiveRot(entity e, float v0, float v1, .float rotfield, float rottime, .float regenfield, float regentime); - -#define PREGIVE_WEAPONS(e) WepSet save_weapons; save_weapons = e.weapons -#define PREGIVE(e,f) float save_##f; save_##f = (e).f -#define POSTGIVE_WEAPON(e,b,snd_incr,snd_decr) GiveSound((e), !!(save_weapons & WepSet_FromWeapon(b)), !!(e.weapons & WepSet_FromWeapon(b)), 0, snd_incr, snd_decr) -#define POSTGIVE_BIT(e,f,b,snd_incr,snd_decr) GiveSound((e), save_##f & (b), (e).f & (b), 0, snd_incr, snd_decr) -#define POSTGIVE_VALUE(e,f,t,snd_incr,snd_decr) GiveSound((e), save_##f, (e).f, t, snd_incr, snd_decr) -#define POSTGIVE_VALUE_ROT(e,f,t,rotfield,rottime,regenfield,regentime,snd_incr,snd_decr) GiveRot((e), save_##f, (e).f, rotfield, rottime, regenfield, regentime); GiveSound((e), save_##f, (e).f, t, snd_incr, snd_decr) - -float GiveItems(entity e, float beginarg, float endarg); -#endif diff --git a/qcsrc/server/t_quake.qc b/qcsrc/server/t_quake.qc index 219a6ae23..ab49c6db5 100644 --- a/qcsrc/server/t_quake.qc +++ b/qcsrc/server/t_quake.qc @@ -3,7 +3,7 @@ //*********************** void spawnfunc_weapon_nailgun (void) {spawnfunc_weapon_electro();} void spawnfunc_weapon_supernailgun (void) {spawnfunc_weapon_hagar();} -void spawnfunc_weapon_supershotgun (void) {spawnfunc_weapon_machinegun();} +void spawnfunc_weapon_supershotgun (void) {spawnfunc_weapon_uzi();} void spawnfunc_item_spikes (void) {spawnfunc_item_bullets();} //void spawnfunc_item_armor1 (void) {spawnfunc_item_armor_medium;} // FIXME: in Quake this is green armor, in Xonotic maps it is an armor shard diff --git a/qcsrc/server/t_quake3.qc b/qcsrc/server/t_quake3.qc index 30f1e8f8d..86a87c043 100644 --- a/qcsrc/server/t_quake3.qc +++ b/qcsrc/server/t_quake3.qc @@ -8,12 +8,13 @@ void spawnfunc_ammo_shells() { spawnfunc_item_shells(); } // MG -> MG +void spawnfunc_weapon_machinegun() { spawnfunc_weapon_uzi(); } void spawnfunc_ammo_bullets() { spawnfunc_item_bullets(); } // GL -> Mortar void spawnfunc_ammo_grenades() { spawnfunc_item_rockets(); } -// LG -> Lightning +// LG -> Electro void spawnfunc_weapon_lightning() { spawnfunc_weapon_electro(); } void spawnfunc_ammo_lightning() { spawnfunc_item_cells(); } @@ -21,13 +22,13 @@ void spawnfunc_ammo_lightning() { spawnfunc_item_cells(); } void spawnfunc_weapon_plasmagun() { spawnfunc_weapon_hagar(); } void spawnfunc_ammo_cells() { spawnfunc_item_rockets(); } -// Rail -> Vortex -void spawnfunc_weapon_railgun() { spawnfunc_weapon_vortex(); } -void spawnfunc_ammo_slugs() { spawnfunc_item_plasma(); } +// Rail -> Nex +void spawnfunc_weapon_railgun() { spawnfunc_weapon_nex(); } +void spawnfunc_ammo_slugs() { spawnfunc_item_cells(); } // BFG -> Crylink void spawnfunc_weapon_bfg() { spawnfunc_weapon_crylink(); } -void spawnfunc_ammo_bfg() { spawnfunc_item_plasma(); } +void spawnfunc_ammo_bfg() { spawnfunc_item_cells(); } // RL -> RL void spawnfunc_ammo_rockets() { spawnfunc_item_rockets(); } @@ -71,11 +72,11 @@ void target_give_init() entity targ; for (targ = world; (targ = find(targ, targetname, self.target)); ) { if (targ.classname == "weapon_rocketlauncher") { - self.ammo_rockets += targ.count * WEP_CVAR(devastator, ammo); + self.ammo_rockets += targ.count * autocvar_g_balance_rocketlauncher_ammo; self.netname = "rocketlauncher"; } else if (targ.classname == "weapon_plasmagun") { - self.ammo_rockets += targ.count * WEP_CVAR_PRI(hagar, ammo); // WEAPONTODO + self.ammo_rockets += targ.count * autocvar_g_balance_hagar_primary_ammo; if(self.netname == "") self.netname = "hagar"; else @@ -89,7 +90,7 @@ void target_give_init() self.netname = strcat(self.netname, " crylink"); } else if (targ.classname == "weapon_grenadelauncher") { - self.ammo_rockets += targ.count * autocvar_g_balance_mortar_primary_ammo; // WEAPONTODO + self.ammo_rockets += targ.count * autocvar_g_balance_grenadelauncher_primary_ammo; if(self.netname == "") self.netname = "grenadelauncher"; else diff --git a/qcsrc/server/t_teleporters.qc b/qcsrc/server/t_teleporters.qc index 543c1cf0b..6e7c35b6a 100644 --- a/qcsrc/server/t_teleporters.qc +++ b/qcsrc/server/t_teleporters.qc @@ -80,7 +80,6 @@ void spawn_tdeath(vector v0, entity e, vector v) #define TELEPORT_NORMAL 1 // play sounds/effects etc #define TELEPORT_SIMPLE 2 // only do teleport, nothing special -void Reset_ArcBeam(entity player, vector forward); void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags) { entity telefragger; @@ -118,8 +117,6 @@ void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angle player.velocity = to_velocity; BITXOR_ASSIGN(player.effects, EF_TELEPORT_BIT); - makevectors(player.angles); - Reset_ArcBeam(player, v_forward); UpdateCSQCProjectileAfterTeleport(player); if(IS_PLAYER(player)) @@ -340,8 +337,6 @@ void spawnfunc_trigger_teleport (void) void WarpZone_PostTeleportPlayer_Callback(entity pl) { - makevectors(pl.angles); - Reset_ArcBeam(pl, v_forward); UpdateCSQCProjectileAfterTeleport(pl); { entity oldself = self; diff --git a/qcsrc/server/teamplay.qc b/qcsrc/server/teamplay.qc index d7d833a64..ee91a9dcc 100644 --- a/qcsrc/server/teamplay.qc +++ b/qcsrc/server/teamplay.qc @@ -291,7 +291,7 @@ string getwelcomemessage(void) else modifications = strcat(modifications, ", ", g_weaponarena_list, " Arena"); } - if(cvar("g_balance_blaster_weaponstart") == 0) + if(autocvar_g_start_weapon_laser == 0) modifications = strcat(modifications, ", No start weapons"); if(cvar("sv_gravity") < stof(cvar_defstring("sv_gravity"))) modifications = strcat(modifications, ", Low gravity"); diff --git a/qcsrc/server/tturrets/system/system_main.qc b/qcsrc/server/tturrets/system/system_main.qc index d56a81bbf..d35573b54 100644 --- a/qcsrc/server/tturrets/system/system_main.qc +++ b/qcsrc/server/tturrets/system/system_main.qc @@ -148,11 +148,11 @@ void turret_projectile_explode() self.event_damage = func_null; #ifdef TURRET_DEBUG float d; - d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world); + d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world); self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg; #else - RadiusDamage (self, self.realowner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world); + RadiusDamage (self, self.realowner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world); #endif remove(self); } diff --git a/qcsrc/server/tturrets/units/unit_ewheel.qc b/qcsrc/server/tturrets/units/unit_ewheel.qc index e8e677ac8..b98388984 100644 --- a/qcsrc/server/tturrets/units/unit_ewheel.qc +++ b/qcsrc/server/tturrets/units/unit_ewheel.qc @@ -13,7 +13,7 @@ void ewheel_attack() { turret_do_updates(self); - _mis = turret_projectile("weapons/lasergun_fire.wav", 1, 0, DEATH_TURRET_EWHEEL, PROJECTILE_BLASTER, TRUE, TRUE); // WEAPONTODO: this is not a projectile made by the blaster, add separate effect for it + _mis = turret_projectile("weapons/lasergun_fire.wav", 1, 0, DEATH_TURRET_EWHEEL, PROJECTILE_LASER, TRUE, TRUE); _mis.missile_flags = MIF_SPLASH; pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1); diff --git a/qcsrc/server/tturrets/units/unit_flac.qc b/qcsrc/server/tturrets/units/unit_flac.qc index 3c9e55863..8a01a9752 100644 --- a/qcsrc/server/tturrets/units/unit_flac.qc +++ b/qcsrc/server/tturrets/units/unit_flac.qc @@ -10,11 +10,11 @@ void turret_flac_projectile_think_explode() #ifdef TURRET_DEBUG float d; - d = RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world); + d = RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world); self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d; self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg; #else - RadiusDamage (self, self.realowner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world); + RadiusDamage (self, self.realowner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world); #endif remove(self); } diff --git a/qcsrc/server/tturrets/units/unit_machinegun.qc b/qcsrc/server/tturrets/units/unit_machinegun.qc index d235dfb32..eccc37f03 100644 --- a/qcsrc/server/tturrets/units/unit_machinegun.qc +++ b/qcsrc/server/tturrets/units/unit_machinegun.qc @@ -7,7 +7,7 @@ void turret_machinegun_attack() { fireBullet (self.tur_shotorg, self.tur_shotdir_updated,self.shot_spread, 0, self.shot_dmg, self.shot_force, DEATH_TURRET_MACHINEGUN, 0); - W_MachineGun_MuzzleFlash(); // WEAPONTODO + UziFlash(); setattachment(self.muzzle_flash, self.tur_head, "tag_fire"); } diff --git a/qcsrc/server/tturrets/units/unit_walker.qc b/qcsrc/server/tturrets/units/unit_walker.qc index a91daa190..2eeb08b8f 100644 --- a/qcsrc/server/tturrets/units/unit_walker.qc +++ b/qcsrc/server/tturrets/units/unit_walker.qc @@ -51,8 +51,7 @@ void walker_setnoanim() } void walker_rocket_explode() { - RadiusDamage (self, self.owner, autocvar_g_turrets_unit_walker_std_rocket_dmg, 0, autocvar_g_turrets_unit_walker_std_rocket_radius, self, world, autocvar_g_turrets_unit_walker_std_rocket_force, DEATH_TURRET_WALK_ROCKET, world); - + RadiusDamage (self, self.owner, autocvar_g_turrets_unit_walker_std_rocket_dmg, 0, autocvar_g_turrets_unit_walker_std_rocket_radius, self, autocvar_g_turrets_unit_walker_std_rocket_force, DEATH_TURRET_WALK_ROCKET, world); remove (self); } diff --git a/qcsrc/server/vehicles/bumblebee.qc b/qcsrc/server/vehicles/bumblebee.qc index 8b8d308f9..657d22705 100644 --- a/qcsrc/server/vehicles/bumblebee.qc +++ b/qcsrc/server/vehicles/bumblebee.qc @@ -702,7 +702,7 @@ void bumb_blowup() { RadiusDamage(self, self.enemy, autocvar_g_vehicle_bumblebee_blowup_coredamage, autocvar_g_vehicle_bumblebee_blowup_edgedamage, - autocvar_g_vehicle_bumblebee_blowup_radius, self, world, + autocvar_g_vehicle_bumblebee_blowup_radius, self, autocvar_g_vehicle_bumblebee_blowup_forceintensity, DEATH_VH_BUMB_DEATH, world); @@ -787,6 +787,7 @@ void bumb_die() self.nextthink = 0; setorigin(self, self.pos1); + } void bumb_impact() diff --git a/qcsrc/server/vehicles/racer.qc b/qcsrc/server/vehicles/racer.qc index fc9cee865..f009723b7 100644 --- a/qcsrc/server/vehicles/racer.qc +++ b/qcsrc/server/vehicles/racer.qc @@ -539,7 +539,7 @@ void racer_blowup() RadiusDamage (self, self.enemy, autocvar_g_vehicle_racer_blowup_coredamage, autocvar_g_vehicle_racer_blowup_edgedamage, - autocvar_g_vehicle_racer_blowup_radius, world, world, + autocvar_g_vehicle_racer_blowup_radius, world, autocvar_g_vehicle_racer_blowup_forceintensity, DEATH_VH_WAKI_DEATH, world); diff --git a/qcsrc/server/vehicles/raptor.qc b/qcsrc/server/vehicles/raptor.qc index 53e4d35f7..a6ef52649 100644 --- a/qcsrc/server/vehicles/raptor.qc +++ b/qcsrc/server/vehicles/raptor.qc @@ -97,7 +97,7 @@ void raptor_bomblet_boom() { RadiusDamage (self, self.realowner, autocvar_g_vehicle_raptor_bomblet_damage, autocvar_g_vehicle_raptor_bomblet_edgedamage, - autocvar_g_vehicle_raptor_bomblet_radius, world, world, + autocvar_g_vehicle_raptor_bomblet_radius, world, autocvar_g_vehicle_raptor_bomblet_force, DEATH_VH_RAPT_BOMB, world); remove(self); } @@ -695,10 +695,9 @@ void raptor_blowup() { self.deadflag = DEAD_DEAD; self.vehicle_exit(VHEF_NORMAL); - RadiusDamage(self, self.enemy, autocvar_g_vehicle_raptor_blowup_coredamage, autocvar_g_vehicle_raptor_blowup_edgedamage, - autocvar_g_vehicle_raptor_blowup_radius, world, world, + autocvar_g_vehicle_raptor_blowup_radius, world, autocvar_g_vehicle_raptor_blowup_forceintensity, DEATH_VH_RAPT_DEATH, world); self.alpha = -1; diff --git a/qcsrc/server/vehicles/spiderbot.qc b/qcsrc/server/vehicles/spiderbot.qc index d78ae30a2..1085a904e 100644 --- a/qcsrc/server/vehicles/spiderbot.qc +++ b/qcsrc/server/vehicles/spiderbot.qc @@ -725,7 +725,7 @@ void spiderbot_blowup() RadiusDamage(self, self.enemy, autocvar_g_vehicle_spiderbot_blowup_coredamage, autocvar_g_vehicle_spiderbot_blowup_edgedamage, - autocvar_g_vehicle_spiderbot_blowup_radius, world, world, + autocvar_g_vehicle_spiderbot_blowup_radius, world, autocvar_g_vehicle_spiderbot_blowup_forceintensity, DEATH_VH_SPID_DEATH, world); self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = -1; diff --git a/qcsrc/server/vehicles/vehicles.qc b/qcsrc/server/vehicles/vehicles.qc index 898274f09..2ee34b928 100644 --- a/qcsrc/server/vehicles/vehicles.qc +++ b/qcsrc/server/vehicles/vehicles.qc @@ -3,10 +3,10 @@ float autocvar_g_vehicles_crush_force; float autocvar_g_vehicles_delayspawn; float autocvar_g_vehicles_delayspawn_jitter; -var float autocvar_g_vehicles_vortex_damagerate = 0.5; -var float autocvar_g_vehicles_machinegun_damagerate = 0.5; +var float autocvar_g_vehicles_nex_damagerate = 0.5; +var float autocvar_g_vehicles_uzi_damagerate = 0.5; var float autocvar_g_vehicles_rifle_damagerate = 0.75; -var float autocvar_g_vehicles_vaporizer_damagerate = 0.001; +var float autocvar_g_vehicles_minstanex_damagerate = 0.001; var float autocvar_g_vehicles_tag_damagerate = 5; float autocvar_g_vehicles; @@ -397,7 +397,7 @@ void vehicles_projectile_explode() PROJECTILE_TOUCH; self.event_damage = func_null; - RadiusDamage (self, self.realowner, self.shot_dmg, 0, self.shot_radius, self, world, self.shot_force, self.totalfrags, other); + RadiusDamage (self, self.realowner, self.shot_dmg, 0, self.shot_radius, self, self.shot_force, self.totalfrags, other); remove (self); } @@ -908,18 +908,17 @@ void vehicles_damage(entity inflictor, entity attacker, float damage, float deat { self.dmg_time = time; - // WEAPONTODO - if(DEATH_ISWEAPON(deathtype, WEP_VORTEX)) - damage *= autocvar_g_vehicles_vortex_damagerate; + if(DEATH_ISWEAPON(deathtype, WEP_NEX)) + damage *= autocvar_g_vehicles_nex_damagerate; - if(DEATH_ISWEAPON(deathtype, WEP_MACHINEGUN)) - damage *= autocvar_g_vehicles_machinegun_damagerate; + if(DEATH_ISWEAPON(deathtype, WEP_UZI)) + damage *= autocvar_g_vehicles_uzi_damagerate; if(DEATH_ISWEAPON(deathtype, WEP_RIFLE)) damage *= autocvar_g_vehicles_rifle_damagerate; - if(DEATH_ISWEAPON(deathtype, WEP_VAPORIZER)) - damage *= autocvar_g_vehicles_vaporizer_damagerate; + if(DEATH_ISWEAPON(deathtype, WEP_MINSTANEX)) + damage *= autocvar_g_vehicles_minstanex_damagerate; if(DEATH_ISWEAPON(deathtype, WEP_SEEKER)) damage *= autocvar_g_vehicles_tag_damagerate; diff --git a/qcsrc/server/w_all.qc b/qcsrc/server/w_all.qc new file mode 100644 index 000000000..ac4ef47ed --- /dev/null +++ b/qcsrc/server/w_all.qc @@ -0,0 +1,21 @@ +// ONLY EVER ADD NEW WEAPONS AT THE END. IF YOU REMOVE ONE, PUT THE LAST ONE ON +// ITS PLACE. THIS IS TO AVOID UNNECESSARY RENUMBERING OF WEAPON IMPULSES. +// IF YOU DISREGARD THIS NOTICE, I'LL KILL YOU WITH THE @!#%'N TUBA +#include "w_laser.qc" +#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" +#include "w_hagar.qc" +#include "w_rocketlauncher.qc" +#include "w_porto.qc" +#include "w_minstanex.qc" +#include "w_hook.qc" +#include "w_hlac.qc" +#include "w_tuba.qc" +#include "w_rifle.qc" +#include "w_fireball.qc" +#include "w_seeker.qc" diff --git a/qcsrc/server/w_common.qc b/qcsrc/server/w_common.qc new file mode 100644 index 000000000..a7ae4d326 --- /dev/null +++ b/qcsrc/server/w_common.qc @@ -0,0 +1,376 @@ + +void W_GiveWeapon (entity e, float wep) +{ + entity oldself; + + if (!wep) + return; + + e.weapons |= WepSet_FromWeapon(wep); + + oldself = self; + self = e; + + if(IS_PLAYER(other)) + { Send_Notification(NOTIF_ONE, other, MSG_MULTI, ITEM_WEAPON_GOT, wep); } + + self = oldself; +} + +.float railgundistance; +.vector railgunforce; +void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, float deathtype) +{ + vector hitloc, force, endpoint, dir; + entity ent, endent; + float endq3surfaceflags; + float totaldmg; + entity o; + + float length; + vector beampos; + string snd; + entity pseudoprojectile; + float f, ffs; + + pseudoprojectile = world; + + dir = normalize(end - start); + length = vlen(end - start); + force = dir * bforce; + + // go a little bit into the wall because we need to hit this wall later + end = end + dir; + + totaldmg = 0; + + // trace multiple times until we hit a wall, each obstacle will be made + // non-solid so we can hit the next, while doing this we spawn effects and + // note down which entities were hit so we can damage them later + o = self; + while (1) + { + if(self.antilag_debug) + WarpZone_traceline_antilag (self, start, end, FALSE, o, self.antilag_debug); + else + WarpZone_traceline_antilag (self, start, end, FALSE, o, ANTILAG_LATENCY(self)); + if(o && WarpZone_trace_firstzone) + { + o = world; + continue; + } + + if(trace_ent.solid == SOLID_BSP || trace_ent.solid == SOLID_SLIDEBOX) + Damage_DamageInfo(trace_endpos, bdamage, 0, 0, force, deathtype, trace_ent.species, self); + + // if it is world we can't hurt it so stop now + if (trace_ent == world || trace_fraction == 1) + break; + + // make the entity non-solid so we can hit the next one + trace_ent.railgunhit = TRUE; + trace_ent.railgunhitloc = end; + trace_ent.railgunhitsolidbackup = trace_ent.solid; + trace_ent.railgundistance = vlen(WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos) - start); + trace_ent.railgunforce = WarpZone_TransformVelocity(WarpZone_trace_transform, force); + + // stop if this is a wall + if (trace_ent.solid == SOLID_BSP) + break; + + // make the entity non-solid + trace_ent.solid = SOLID_NOT; + } + + endpoint = trace_endpos; + endent = trace_ent; + endq3surfaceflags = trace_dphitq3surfaceflags; + + // find all the entities the railgun hit and restore their solid state + ent = findfloat(world, railgunhit, TRUE); + while (ent) + { + // restore their solid type + ent.solid = ent.railgunhitsolidbackup; + ent = findfloat(ent, railgunhit, TRUE); + } + + // spawn a temporary explosion entity for RadiusDamage calls + //explosion = spawn(); + + // Find all non-hit players the beam passed close by + if(deathtype == WEP_MINSTANEX || deathtype == WEP_NEX) + { + FOR_EACH_REALCLIENT(msg_entity) + if(msg_entity != self) + if(!msg_entity.railgunhit) + if(!(IS_SPEC(msg_entity) && msg_entity.enemy == self)) // we use realclient, so spectators can hear the whoosh too + { + // nearest point on the beam + beampos = start + dir * bound(0, (msg_entity.origin - start) * dir, length); + + f = bound(0, 1 - vlen(beampos - msg_entity.origin) / 512, 1); + if(f <= 0) + continue; + + snd = strcat("weapons/nexwhoosh", ftos(floor(random() * 3) + 1), ".wav"); + + if(!pseudoprojectile) + pseudoprojectile = spawn(); // we need this so the sound uses the "entchannel4" volume + soundtoat(MSG_ONE, pseudoprojectile, beampos, CH_SHOTS, snd, VOL_BASE * f, ATTEN_NONE); + } + + if(pseudoprojectile) + remove(pseudoprojectile); + } + + // find all the entities the railgun hit and hurt them + ent = findfloat(world, railgunhit, TRUE); + while (ent) + { + // get the details we need to call the damage function + hitloc = ent.railgunhitloc; + + f = ExponentialFalloff(mindist, maxdist, halflifedist, ent.railgundistance); + ffs = ExponentialFalloff(mindist, maxdist, forcehalflifedist, ent.railgundistance); + + if(accuracy_isgooddamage(self.realowner, ent)) + totaldmg += bdamage * f; + + // apply the damage + if (ent.takedamage) + Damage (ent, self, self, bdamage * f, deathtype, hitloc, ent.railgunforce * ffs); + + // create a small explosion to throw gibs around (if applicable) + //setorigin (explosion, hitloc); + //RadiusDamage (explosion, self, 10, 0, 50, world, 300, deathtype); + + ent.railgunhitloc = '0 0 0'; + ent.railgunhitsolidbackup = SOLID_NOT; + ent.railgunhit = FALSE; + ent.railgundistance = 0; + + // advance to the next entity + ent = findfloat(ent, railgunhit, TRUE); + } + + // calculate hits and fired shots for hitscan + accuracy_add(self, self.weapon, 0, min(bdamage, totaldmg)); + + trace_endpos = endpoint; + trace_ent = endent; + trace_dphitq3surfaceflags = endq3surfaceflags; +} + +float fireBullet_trace_callback_eff; +entity fireBullet_last_hit; +void fireBullet_trace_callback(vector start, vector hit, vector end) +{ + if(vlen(hit - start) > 16) + trailparticles(world, fireBullet_trace_callback_eff, start, hit); + WarpZone_trace_forent = world; + fireBullet_last_hit = world; +} + +void fireBullet(vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, float tracereffects) +{ + // TODO antilag takeback + vector end; + + dir = normalize(dir + randomvec() * spread); + end = start + dir * MAX_SHOT_DISTANCE; + + entity pl; + fireBullet_last_hit = world; + float solid_penetration_left = 1; + float total_damage = 0; + + if(tracereffects & EF_RED) + fireBullet_trace_callback_eff = particleeffectnum("tr_rifle"); + else if(tracereffects & EF_BLUE) + fireBullet_trace_callback_eff = particleeffectnum("tr_rifle_weak"); + else + fireBullet_trace_callback_eff = particleeffectnum("tr_bullet"); + + float lag = ANTILAG_LATENCY(self); + if(lag < 0.001) + lag = 0; + if (!IS_REAL_CLIENT(self)) + lag = 0; + if(autocvar_g_antilag == 0 || self.cvar_cl_noantilag) + lag = 0; // only do hitscan, but no antilag + if(lag) + { + FOR_EACH_PLAYER(pl) + if(pl != self) + antilag_takeback(pl, time - lag); + FOR_EACH_MONSTER(pl) + antilag_takeback(pl, time - lag); + } + + WarpZone_trace_forent = self; + + for (;;) + { + // TODO also show effect while tracing + WarpZone_TraceBox_ThroughZone(start, '0 0 0', '0 0 0', end, FALSE, WarpZone_trace_forent, world, fireBullet_trace_callback); + dir = WarpZone_TransformVelocity(WarpZone_trace_transform, dir); + end = WarpZone_TransformOrigin(WarpZone_trace_transform, end); + start = trace_endpos; + entity hit = trace_ent; + + // When hitting sky, stop. + if (pointcontents(start) == CONTENT_SKY) + break; + + if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) + break; + + // if we hit "weapclip", bail out + // + // rationale of this check: + // + // any shader that is solid, nodraw AND trans is meant to clip weapon + // shots and players, but has no other effect! + // + // if it is not trans, it is caulk and should not have this side effect + // + // matching shaders: + // common/weapclip (intended) + // common/noimpact (is supposed to eat projectiles, but is erased anyway) + float is_weapclip = 0; + if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NODRAW) + if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NONSOLID)) + if (!(trace_dphitcontents & DPCONTENTS_OPAQUE)) + is_weapclip = 1; + + if(!hit || hit.solid == SOLID_BSP || hit.solid == SOLID_SLIDEBOX) + Damage_DamageInfo(start, damage * solid_penetration_left, 0, 0, max(1, force) * dir * solid_penetration_left, dtype, hit.species, self); + + if (hit && hit != WarpZone_trace_forent && hit != fireBullet_last_hit) // Avoid self-damage (except after going through a warp); avoid hitting the same entity twice (engine bug). + { + fireBullet_last_hit = hit; + yoda = 0; + float g = accuracy_isgooddamage(self, hit); + Damage(hit, self, self, damage * solid_penetration_left, dtype, start, force * dir * solid_penetration_left); + // calculate hits for ballistic weapons + if(g) + { + // do not exceed 100% + float added_damage = min(damage - total_damage, damage * solid_penetration_left); + total_damage += damage * solid_penetration_left; + accuracy_add(self, self.weapon, 0, added_damage); + } + } + + if (is_weapclip) + break; + + // go through solid! + // outside the world? forget it + if(start_x > world.maxs_x || start_y > world.maxs_y || start_z > world.maxs_z || start_x < world.mins_x || start_y < world.mins_y || start_z < world.mins_z) + break; + + float maxdist; + if(max_solid_penetration < 0) + break; + else if(hit.ballistics_density < -1) + break; // -2: no solid penetration, ever + else if(hit.ballistics_density < 0) + maxdist = vlen(hit.maxs - hit.mins) + 1; // -1: infinite travel distance + else if(hit.ballistics_density == 0) + maxdist = max_solid_penetration * solid_penetration_left; + else + maxdist = max_solid_penetration * solid_penetration_left * hit.ballistics_density; + + if(maxdist <= autocvar_g_ballistics_mindistance) + break; + + // move the entity along its velocity until it's out of solid, then let it resume + // The previously hit entity is ignored here! + traceline_inverted (start, start + dir * maxdist, MOVE_NORMAL, WarpZone_trace_forent, TRUE, hit); + if(trace_fraction == 1) // 1: we never got out of solid + break; + + float dist_taken = max(autocvar_g_ballistics_mindistance, vlen(trace_endpos - start)); + solid_penetration_left *= (dist_taken / maxdist); + + // Only show effect when going through a player (invisible otherwise) + if (hit && (hit.solid != SOLID_BSP)) + if(vlen(trace_endpos - start) > 4) + trailparticles(self, fireBullet_trace_callback_eff, start, trace_endpos); + + start = trace_endpos; + + if(hit.solid == SOLID_BSP) + Damage_DamageInfo(start, 0, 0, 0, max(1, force) * normalize(dir) * -solid_penetration_left, dtype, 0, self); + } + + if(lag) + { + FOR_EACH_PLAYER(pl) + if(pl != self) + antilag_restore(pl); + FOR_EACH_MONSTER(pl) + antilag_restore(pl); + } +} + +float W_CheckProjectileDamage(entity inflictor, entity projowner, float deathtype, float exception) +{ + float is_from_contents = (deathtype == DEATH_SLIME || deathtype == DEATH_LAVA); + float is_from_owner = (inflictor == projowner); + float is_from_exception = (exception != -1); + + //dprint(strcat("W_CheckProjectileDamage: from_contents ", ftos(is_from_contents), " : from_owner ", ftos(is_from_owner), " : exception ", strcat(ftos(is_from_exception), " (", ftos(exception), "). \n"))); + + if(autocvar_g_projectiles_damage <= -2) + { + return FALSE; // no damage to projectiles at all, not even with the exceptions + } + else if(autocvar_g_projectiles_damage == -1) + { + if(is_from_exception) + return (exception); // if exception is detected, allow it to override + else + return FALSE; // otherwise, no other damage is allowed + } + else if(autocvar_g_projectiles_damage == 0) + { + if(is_from_exception) + return (exception); // if exception is detected, allow it to override + else if (!is_from_contents) + return FALSE; // otherwise, only allow damage from contents + } + else if(autocvar_g_projectiles_damage == 1) + { + if(is_from_exception) + return (exception); // if exception is detected, allow it to override + else if (!(is_from_contents || is_from_owner)) + return FALSE; // otherwise, only allow self damage and damage from contents + } + else if(autocvar_g_projectiles_damage == 2) // allow any damage, but override for exceptions + { + if(is_from_exception) + return (exception); // if exception is detected, allow it to override + } + + return TRUE; // if none of these return, then allow damage anyway. +} + +void W_PrepareExplosionByDamage(entity attacker, void() explode) +{ + self.takedamage = DAMAGE_NO; + self.event_damage = func_null; + + if(IS_CLIENT(attacker) && !autocvar_g_projectiles_keep_owner) + { + self.owner = attacker; + self.realowner = attacker; + } + + // do not explode NOW but in the NEXT FRAME! + // because recursive calls to RadiusDamage are not allowed + self.nextthink = time; + self.think = explode; +} diff --git a/qcsrc/server/w_crylink.qc b/qcsrc/server/w_crylink.qc new file mode 100644 index 000000000..f7ad7583d --- /dev/null +++ b/qcsrc/server/w_crylink.qc @@ -0,0 +1,727 @@ +#ifdef REGISTER_WEAPON +REGISTER_WEAPON( +/* WEP_##id */ CRYLINK, +/* function */ w_crylink, +/* ammotype */ IT_CELLS, +/* impulse */ 6, +/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH, +/* rating */ BOT_PICKUP_RATING_MID, +/* model */ "crylink", +/* shortname */ "crylink", +/* fullname */ _("Crylink") +); +#else +#ifdef SVQC +.float gravity; +.float crylink_waitrelease; +.entity crylink_lastgroup; + +.entity queuenext; +.entity queueprev; + +void W_Crylink_CheckLinks(entity e) +{ + float i; + entity p; + + if(e == world) + error("W_Crylink_CheckLinks: entity is world"); + if(e.classname != "spike" || wasfreed(e)) + error(sprintf("W_Crylink_CheckLinks: entity is not a spike but a %s (freed: %d)", e.classname, wasfreed(e))); + + p = e; + for(i = 0; i < 1000; ++i) + { + if(p.queuenext.queueprev != p || p.queueprev.queuenext != p) + error("W_Crylink_CheckLinks: queue is inconsistent"); + p = p.queuenext; + if(p == e) + break; + } + if(i >= 1000) + error("W_Crylink_CheckLinks: infinite chain"); +} + +void W_Crylink_Dequeue_Raw(entity own, entity prev, entity me, entity next) +{ + W_Crylink_CheckLinks(next); + if(me == own.crylink_lastgroup) + own.crylink_lastgroup = ((me == next) ? world : next); + prev.queuenext = next; + next.queueprev = prev; + me.classname = "spike_oktoremove"; + if(me != next) + W_Crylink_CheckLinks(next); +} + +void W_Crylink_Dequeue(entity e) +{ + W_Crylink_Dequeue_Raw(e.realowner, e.queueprev, e, e.queuenext); +} + +void W_Crylink_Reset(void) +{ + W_Crylink_Dequeue(self); + remove(self); +} + +// force projectile to explode +void W_Crylink_LinkExplode (entity e, entity e2) +{ + float a; + + if(e == e2) + return; + + a = bound(0, 1 - (time - e.fade_time) * e.fade_rate, 1); + + if(e == e.realowner.crylink_lastgroup) + e.realowner.crylink_lastgroup = world; + + if(e.projectiledeathtype & HITTYPE_SECONDARY) + RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_secondary_damage * a, autocvar_g_balance_crylink_secondary_edgedamage * a, autocvar_g_balance_crylink_secondary_radius, world, autocvar_g_balance_crylink_secondary_force * a, e.projectiledeathtype, other); + else + RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_primary_damage * a, autocvar_g_balance_crylink_primary_edgedamage * a, autocvar_g_balance_crylink_primary_radius, world, autocvar_g_balance_crylink_primary_force * a, e.projectiledeathtype, other); + + W_Crylink_LinkExplode(e.queuenext, e2); + + e.classname = "spike_oktoremove"; + remove (e); +} + +// adjust towards center +// returns the origin where they will meet... and the time till the meeting is +// stored in w_crylink_linkjoin_time. +// could possibly network this origin and time, and display a special particle +// effect when projectiles meet there :P +// jspeed: joining speed (calculate this as join spread * initial speed) +float w_crylink_linkjoin_time; +vector W_Crylink_LinkJoin(entity e, float jspeed) +{ + vector avg_origin, avg_velocity; + vector targ_origin; + float avg_dist, n; + entity p; + + // FIXME remove this debug code + W_Crylink_CheckLinks(e); + + w_crylink_linkjoin_time = 0; + + avg_origin = e.origin; + avg_velocity = e.velocity; + n = 1; + for(p = e; (p = p.queuenext) != e; ) + { + avg_origin += WarpZone_RefSys_TransformOrigin(p, e, p.origin); + avg_velocity += WarpZone_RefSys_TransformVelocity(p, e, p.velocity); + ++n; + } + avg_origin *= (1.0 / n); + avg_velocity *= (1.0 / n); + + if(n < 2) + return avg_origin; // nothing to do + + // yes, mathematically we can do this in ONE step, but beware of 32bit floats... + avg_dist = pow(vlen(e.origin - avg_origin), 2); + for(p = e; (p = p.queuenext) != e; ) + avg_dist += pow(vlen(WarpZone_RefSys_TransformOrigin(p, e, p.origin) - avg_origin), 2); + avg_dist *= (1.0 / n); + avg_dist = sqrt(avg_dist); + + if(avg_dist == 0) + return avg_origin; // no change needed + + if(jspeed == 0) + { + e.velocity = avg_velocity; + UpdateCSQCProjectile(e); + for(p = e; (p = p.queuenext) != e; ) + { + p.velocity = WarpZone_RefSys_TransformVelocity(e, p, avg_velocity); + UpdateCSQCProjectile(p); + } + targ_origin = avg_origin + 1000000000 * normalize(avg_velocity); // HUUUUUUGE + } + else + { + w_crylink_linkjoin_time = avg_dist / jspeed; + targ_origin = avg_origin + w_crylink_linkjoin_time * avg_velocity; + + e.velocity = (targ_origin - e.origin) * (1.0 / w_crylink_linkjoin_time); + UpdateCSQCProjectile(e); + for(p = e; (p = p.queuenext) != e; ) + { + p.velocity = WarpZone_RefSys_TransformVelocity(e, p, (targ_origin - WarpZone_RefSys_TransformOrigin(p, e, p.origin)) * (1.0 / w_crylink_linkjoin_time)); + UpdateCSQCProjectile(p); + } + + // analysis: + // jspeed -> +infinity: + // w_crylink_linkjoin_time -> +0 + // targ_origin -> avg_origin + // p->velocity -> HUEG towards center + // jspeed -> 0: + // w_crylink_linkjoin_time -> +/- infinity + // targ_origin -> avg_velocity * +/- infinity + // p->velocity -> avg_velocity + // jspeed -> -infinity: + // w_crylink_linkjoin_time -> -0 + // targ_origin -> avg_origin + // p->velocity -> HUEG away from center + } + + W_Crylink_CheckLinks(e); + + return targ_origin; +} + +void W_Crylink_LinkJoinEffect_Think() +{ + // is there at least 2 projectiles very close? + entity e, p; + float n; + e = self.owner.crylink_lastgroup; + n = 0; + if(e) + { + if(vlen(e.origin - self.origin) < vlen(e.velocity) * frametime) + ++n; + for(p = e; (p = p.queuenext) != e; ) + { + if(vlen(p.origin - self.origin) < vlen(p.velocity) * frametime) + ++n; + } + if(n >= 2) + { + if(e.projectiledeathtype & HITTYPE_SECONDARY) + { + if(autocvar_g_balance_crylink_secondary_joinexplode) + { + n = n / autocvar_g_balance_crylink_secondary_shots; + RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_secondary_joinexplode_damage * n, + autocvar_g_balance_crylink_secondary_joinexplode_edgedamage * n, + autocvar_g_balance_crylink_secondary_joinexplode_radius * n, e.realowner, + autocvar_g_balance_crylink_secondary_joinexplode_force * n, e.projectiledeathtype, other); + + pointparticles(particleeffectnum("crylink_joinexplode"), self.origin, '0 0 0', n); + } + } + else + { + if(autocvar_g_balance_crylink_primary_joinexplode) + { + n = n / autocvar_g_balance_crylink_primary_shots; + RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_primary_joinexplode_damage * n, + autocvar_g_balance_crylink_primary_joinexplode_edgedamage * n, + autocvar_g_balance_crylink_primary_joinexplode_radius * n, e.realowner, + autocvar_g_balance_crylink_primary_joinexplode_force * n, e.projectiledeathtype, other); + + pointparticles(particleeffectnum("crylink_joinexplode"), self.origin, '0 0 0', n); + } + } + } + } + remove(self); +} + +float W_Crylink_Touch_WouldHitFriendly(entity projectile, float rad) +{ + entity head = WarpZone_FindRadius((projectile.origin + (projectile.mins + projectile.maxs) * 0.5), rad + MAX_DAMAGEEXTRARADIUS, FALSE); + float hit_friendly = 0; + float hit_enemy = 0; + + while(head) + { + if((head.takedamage != DAMAGE_NO) && (head.deadflag == DEAD_NO)) + { + if(SAME_TEAM(head, projectile.realowner)) + ++hit_friendly; + else + ++hit_enemy; + } + + head = head.chain; + } + + return (hit_enemy ? FALSE : hit_friendly); +} + +// NO bounce protection, as bounces are limited! +void W_Crylink_Touch (void) +{ + float finalhit; + float f; + PROJECTILE_TOUCH; + + float a; + a = bound(0, 1 - (time - self.fade_time) * self.fade_rate, 1); + + finalhit = ((self.cnt <= 0) || (other.takedamage != DAMAGE_NO)); + if(finalhit) + f = 1; + else + f = autocvar_g_balance_crylink_primary_bouncedamagefactor; + if(a) + f *= a; + + float totaldamage = RadiusDamage(self, self.realowner, autocvar_g_balance_crylink_primary_damage * f, autocvar_g_balance_crylink_primary_edgedamage * f, autocvar_g_balance_crylink_primary_radius, world, autocvar_g_balance_crylink_primary_force * f, self.projectiledeathtype, other); + + if(totaldamage && ((autocvar_g_balance_crylink_primary_linkexplode == 2) || ((autocvar_g_balance_crylink_primary_linkexplode == 1) && !W_Crylink_Touch_WouldHitFriendly(self, autocvar_g_balance_crylink_primary_radius)))) + { + if(self == self.realowner.crylink_lastgroup) + self.realowner.crylink_lastgroup = world; + W_Crylink_LinkExplode(self.queuenext, self); + self.classname = "spike_oktoremove"; + remove (self); + return; + } + else if(finalhit) + { + // just unlink + W_Crylink_Dequeue(self); + remove(self); + return; + } + self.cnt = self.cnt - 1; + self.angles = vectoangles(self.velocity); + self.owner = world; + self.projectiledeathtype |= HITTYPE_BOUNCE; + // commented out as it causes a little hitch... + //if(proj.cnt == 0) + // CSQCProjectile(proj, TRUE, PROJECTILE_CRYLINK, TRUE); +} + +void W_Crylink_Touch2 (void) +{ + float finalhit; + float f; + PROJECTILE_TOUCH; + + float a; + a = bound(0, 1 - (time - self.fade_time) * self.fade_rate, 1); + + finalhit = ((self.cnt <= 0) || (other.takedamage != DAMAGE_NO)); + if(finalhit) + f = 1; + else + f = autocvar_g_balance_crylink_secondary_bouncedamagefactor; + if(a) + f *= a; + + float totaldamage = RadiusDamage(self, self.realowner, autocvar_g_balance_crylink_secondary_damage * f, autocvar_g_balance_crylink_secondary_edgedamage * f, autocvar_g_balance_crylink_secondary_radius, world, autocvar_g_balance_crylink_secondary_force * f, self.projectiledeathtype, other); + + if(totaldamage && ((autocvar_g_balance_crylink_secondary_linkexplode == 2) || ((autocvar_g_balance_crylink_secondary_linkexplode == 1) && !W_Crylink_Touch_WouldHitFriendly(self, autocvar_g_balance_crylink_secondary_radius)))) + { + if(self == self.realowner.crylink_lastgroup) + self.realowner.crylink_lastgroup = world; + W_Crylink_LinkExplode(self.queuenext, self); + self.classname = "spike_oktoremove"; + remove (self); + return; + } + else if(finalhit) + { + // just unlink + W_Crylink_Dequeue(self); + remove(self); + return; + } + self.cnt = self.cnt - 1; + self.angles = vectoangles(self.velocity); + self.owner = world; + self.projectiledeathtype |= HITTYPE_BOUNCE; + // commented out as it causes a little hitch... + //if(proj.cnt == 0) + // CSQCProjectile(proj, TRUE, PROJECTILE_CRYLINK, TRUE); +} + +void W_Crylink_Fadethink (void) +{ + W_Crylink_Dequeue(self); + remove(self); +} + +void W_Crylink_Attack (void) +{ + float counter, shots; + entity proj, prevproj, firstproj; + vector s; + vector forward, right, up; + float maxdmg; + + W_DecreaseAmmo(ammo_cells, autocvar_g_balance_crylink_primary_ammo, autocvar_g_balance_crylink_reload_ammo); + + maxdmg = autocvar_g_balance_crylink_primary_damage*autocvar_g_balance_crylink_primary_shots; + maxdmg *= 1 + autocvar_g_balance_crylink_primary_bouncedamagefactor * autocvar_g_balance_crylink_primary_bounces; + if(autocvar_g_balance_crylink_primary_joinexplode) + maxdmg += autocvar_g_balance_crylink_primary_joinexplode_damage; + + W_SetupShot (self, FALSE, 2, "weapons/crylink_fire.wav", CH_WEAPON_A, maxdmg); + forward = v_forward; + right = v_right; + up = v_up; + + shots = autocvar_g_balance_crylink_primary_shots; + pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots); + proj = prevproj = firstproj = world; + for(counter = 0; counter < shots; ++counter) + { + proj = spawn (); + proj.reset = W_Crylink_Reset; + proj.realowner = proj.owner = self; + proj.classname = "spike"; + proj.bot_dodge = TRUE; + proj.bot_dodgerating = autocvar_g_balance_crylink_primary_damage; + if(shots == 1) { + proj.queuenext = proj; + proj.queueprev = proj; + } + else if(counter == 0) { // first projectile, store in firstproj for now + firstproj = proj; + } + else if(counter == shots - 1) { // last projectile, link up with first projectile + prevproj.queuenext = proj; + firstproj.queueprev = proj; + proj.queuenext = firstproj; + proj.queueprev = prevproj; + } + else { // else link up with previous projectile + prevproj.queuenext = proj; + proj.queueprev = prevproj; + } + + prevproj = proj; + + proj.movetype = MOVETYPE_BOUNCEMISSILE; + PROJECTILE_MAKETRIGGER(proj); + proj.projectiledeathtype = WEP_CRYLINK; + //proj.gravity = 0.001; + + setorigin (proj, w_shotorg); + setsize(proj, '0 0 0', '0 0 0'); + + + s = '0 0 0'; + if (counter == 0) + s = '0 0 0'; + else + { + makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1))); + s_y = v_forward_x; + s_z = v_forward_y; + } + s = s * autocvar_g_balance_crylink_primary_spread * g_weaponspreadfactor; + W_SetupProjectileVelocityEx(proj, w_shotdir + right * s_y + up * s_z, v_up, autocvar_g_balance_crylink_primary_speed, 0, 0, 0, FALSE); + proj.touch = W_Crylink_Touch; + + proj.think = W_Crylink_Fadethink; + if(counter == 0) + { + proj.fade_time = time + autocvar_g_balance_crylink_primary_middle_lifetime; + proj.fade_rate = 1 / autocvar_g_balance_crylink_primary_middle_fadetime; + proj.nextthink = time + autocvar_g_balance_crylink_primary_middle_lifetime + autocvar_g_balance_crylink_primary_middle_fadetime; + } + else + { + proj.fade_time = time + autocvar_g_balance_crylink_primary_other_lifetime; + proj.fade_rate = 1 / autocvar_g_balance_crylink_primary_other_fadetime; + proj.nextthink = time + autocvar_g_balance_crylink_primary_other_lifetime + autocvar_g_balance_crylink_primary_other_fadetime; + } + proj.teleport_time = time + autocvar_g_balance_crylink_primary_joindelay; + proj.cnt = autocvar_g_balance_crylink_primary_bounces; + //proj.scale = 1 + 1 * proj.cnt; + + proj.angles = vectoangles (proj.velocity); + + //proj.glow_size = 20; + + proj.flags = FL_PROJECTILE; + proj.missile_flags = MIF_SPLASH; + + CSQCProjectile(proj, TRUE, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), TRUE); + + other = proj; MUTATOR_CALLHOOK(EditProjectile); + } + if(autocvar_g_balance_crylink_primary_joinspread != 0) + { + self.crylink_lastgroup = proj; + W_Crylink_CheckLinks(proj); + self.crylink_waitrelease = 1; + } +} + +void W_Crylink_Attack2 (void) +{ + float counter, shots; + entity proj, prevproj, firstproj; + vector s; + vector forward, right, up; + float maxdmg; + + W_DecreaseAmmo(ammo_cells, autocvar_g_balance_crylink_secondary_ammo, autocvar_g_balance_crylink_reload_ammo); + + maxdmg = autocvar_g_balance_crylink_secondary_damage*autocvar_g_balance_crylink_secondary_shots; + maxdmg *= 1 + autocvar_g_balance_crylink_secondary_bouncedamagefactor * autocvar_g_balance_crylink_secondary_bounces; + if(autocvar_g_balance_crylink_secondary_joinexplode) + maxdmg += autocvar_g_balance_crylink_secondary_joinexplode_damage; + + W_SetupShot (self, FALSE, 2, "weapons/crylink_fire2.wav", CH_WEAPON_A, maxdmg); + forward = v_forward; + right = v_right; + up = v_up; + + shots = autocvar_g_balance_crylink_secondary_shots; + pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots); + proj = prevproj = firstproj = world; + for(counter = 0; counter < shots; ++counter) + { + proj = spawn (); + proj.reset = W_Crylink_Reset; + proj.realowner = proj.owner = self; + proj.classname = "spike"; + proj.bot_dodge = TRUE; + proj.bot_dodgerating = autocvar_g_balance_crylink_secondary_damage; + if(shots == 1) { + proj.queuenext = proj; + proj.queueprev = proj; + } + else if(counter == 0) { // first projectile, store in firstproj for now + firstproj = proj; + } + else if(counter == shots - 1) { // last projectile, link up with first projectile + prevproj.queuenext = proj; + firstproj.queueprev = proj; + proj.queuenext = firstproj; + proj.queueprev = prevproj; + } + else { // else link up with previous projectile + prevproj.queuenext = proj; + proj.queueprev = prevproj; + } + + prevproj = proj; + + proj.movetype = MOVETYPE_BOUNCEMISSILE; + PROJECTILE_MAKETRIGGER(proj); + proj.projectiledeathtype = WEP_CRYLINK | HITTYPE_SECONDARY; + //proj.gravity = 0.001; + + setorigin (proj, w_shotorg); + setsize(proj, '0 0 0', '0 0 0'); + + if(autocvar_g_balance_crylink_secondary_spreadtype == 1) + { + s = '0 0 0'; + if (counter == 0) + s = '0 0 0'; + else + { + makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1))); + s_y = v_forward_x; + s_z = v_forward_y; + } + s = s * autocvar_g_balance_crylink_secondary_spread * g_weaponspreadfactor; + s = w_shotdir + right * s_y + up * s_z; + } + else + { + s = (w_shotdir + (((counter + 0.5) / shots) * 2 - 1) * v_right * autocvar_g_balance_crylink_secondary_spread * g_weaponspreadfactor); + } + + W_SetupProjectileVelocityEx(proj, s, v_up, autocvar_g_balance_crylink_secondary_speed, 0, 0, 0, FALSE); + proj.touch = W_Crylink_Touch2; + proj.think = W_Crylink_Fadethink; + if(counter == (shots - 1) / 2) + { + proj.fade_time = time + autocvar_g_balance_crylink_secondary_middle_lifetime; + proj.fade_rate = 1 / autocvar_g_balance_crylink_secondary_middle_fadetime; + proj.nextthink = time + autocvar_g_balance_crylink_secondary_middle_lifetime + autocvar_g_balance_crylink_secondary_middle_fadetime; + } + else + { + proj.fade_time = time + autocvar_g_balance_crylink_secondary_line_lifetime; + proj.fade_rate = 1 / autocvar_g_balance_crylink_secondary_line_fadetime; + proj.nextthink = time + autocvar_g_balance_crylink_secondary_line_lifetime + autocvar_g_balance_crylink_secondary_line_fadetime; + } + proj.teleport_time = time + autocvar_g_balance_crylink_secondary_joindelay; + proj.cnt = autocvar_g_balance_crylink_secondary_bounces; + //proj.scale = 1 + 1 * proj.cnt; + + proj.angles = vectoangles (proj.velocity); + + //proj.glow_size = 20; + + proj.flags = FL_PROJECTILE; + proj.missile_flags = MIF_SPLASH; + + CSQCProjectile(proj, TRUE, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), TRUE); + + other = proj; MUTATOR_CALLHOOK(EditProjectile); + } + if(autocvar_g_balance_crylink_secondary_joinspread != 0) + { + self.crylink_lastgroup = proj; + W_Crylink_CheckLinks(proj); + self.crylink_waitrelease = 2; + } +} + +void spawnfunc_weapon_crylink (void) +{ + weapon_defaultspawnfunc(WEP_CRYLINK); +} + +float w_crylink(float req) +{ + float ammo_amount; + if (req == WR_AIM) + { + if (random() < 0.10) + self.BUTTON_ATCK = bot_aim(autocvar_g_balance_crylink_primary_speed, 0, autocvar_g_balance_crylink_primary_middle_lifetime, FALSE); + else + self.BUTTON_ATCK2 = bot_aim(autocvar_g_balance_crylink_secondary_speed, 0, autocvar_g_balance_crylink_secondary_middle_lifetime, FALSE); + } + else if (req == WR_THINK) + { + if(autocvar_g_balance_crylink_reload_ammo && self.clip_load < min(autocvar_g_balance_crylink_primary_ammo, autocvar_g_balance_crylink_secondary_ammo)) // forced reload + weapon_action(self.weapon, WR_RELOAD); + + if (self.BUTTON_ATCK) + { + if (self.crylink_waitrelease != 1) + if (weapon_prepareattack(0, autocvar_g_balance_crylink_primary_refire)) + { + W_Crylink_Attack(); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_crylink_primary_animtime, w_ready); + } + } + + if(self.BUTTON_ATCK2 && autocvar_g_balance_crylink_secondary) + { + if (self.crylink_waitrelease != 2) + if (weapon_prepareattack(1, autocvar_g_balance_crylink_secondary_refire)) + { + W_Crylink_Attack2(); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_crylink_secondary_animtime, w_ready); + } + } + + if ((self.crylink_waitrelease == 1 && !self.BUTTON_ATCK) || (self.crylink_waitrelease == 2 && !self.BUTTON_ATCK2)) + { + if (!self.crylink_lastgroup || time > self.crylink_lastgroup.teleport_time) + { + // fired and released now! + if(self.crylink_lastgroup) + { + vector pos; + entity linkjoineffect; + + if(self.crylink_waitrelease == 1) + { + pos = W_Crylink_LinkJoin(self.crylink_lastgroup, autocvar_g_balance_crylink_primary_joinspread * autocvar_g_balance_crylink_primary_speed); + + } + else + { + pos = W_Crylink_LinkJoin(self.crylink_lastgroup, autocvar_g_balance_crylink_secondary_joinspread * autocvar_g_balance_crylink_secondary_speed); + } + + linkjoineffect = spawn(); + linkjoineffect.think = W_Crylink_LinkJoinEffect_Think; + linkjoineffect.classname = "linkjoineffect"; + linkjoineffect.nextthink = time + w_crylink_linkjoin_time; + linkjoineffect.owner = self; + setorigin(linkjoineffect, pos); + } + self.crylink_waitrelease = 0; + if(!w_crylink(WR_CHECKAMMO1) && !w_crylink(WR_CHECKAMMO2)) + if (!(self.items & IT_UNLIMITED_WEAPON_AMMO)) + { + // ran out of ammo! + self.cnt = WEP_CRYLINK; + self.switchweapon = w_getbestweapon(self); + } + } + } + } + else if (req == WR_PRECACHE) + { + precache_model ("models/weapons/g_crylink.md3"); + precache_model ("models/weapons/v_crylink.md3"); + precache_model ("models/weapons/h_crylink.iqm"); + precache_sound ("weapons/crylink_fire.wav"); + precache_sound ("weapons/crylink_fire2.wav"); + precache_sound ("weapons/crylink_linkjoin.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else + } + else if (req == WR_SETUP) + { + weapon_setup(WEP_CRYLINK); + self.current_ammo = ammo_cells; + } + else if (req == WR_CHECKAMMO1) + { + // don't "run out of ammo" and switch weapons while waiting for release + if(self.crylink_lastgroup && self.crylink_waitrelease) + return TRUE; + + ammo_amount = self.ammo_cells >= autocvar_g_balance_crylink_primary_ammo; + ammo_amount += self.(weapon_load[WEP_CRYLINK]) >= autocvar_g_balance_crylink_primary_ammo; + return ammo_amount; + } + else if (req == WR_CHECKAMMO2) + { + // don't "run out of ammo" and switch weapons while waiting for release + if(self.crylink_lastgroup && self.crylink_waitrelease) + return TRUE; + + ammo_amount = self.ammo_cells >= autocvar_g_balance_crylink_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_CRYLINK]) >= autocvar_g_balance_crylink_secondary_ammo; + return ammo_amount; + } + else if (req == WR_RELOAD) + { + W_Reload(min(autocvar_g_balance_crylink_primary_ammo, autocvar_g_balance_crylink_secondary_ammo), autocvar_g_balance_crylink_reload_ammo, autocvar_g_balance_crylink_reload_time, "weapons/reload.wav"); + } + else if (req == WR_SUICIDEMESSAGE) + { + return WEAPON_CRYLINK_SUICIDE; + } + else if (req == WR_KILLMESSAGE) + { + return WEAPON_CRYLINK_MURDER; + } + return TRUE; +} +#endif +#ifdef CSQC +float w_crylink(float req) +{ + if(req == WR_IMPACTEFFECT) + { + vector org2; + org2 = w_org + w_backoff * 2; + if(w_deathtype & HITTYPE_SECONDARY) + { + pointparticles(particleeffectnum("crylink_impact"), org2, '0 0 0', 1); + if(!w_issilent) + sound(self, CH_SHOTS, "weapons/crylink_impact2.wav", VOL_BASE, ATTEN_NORM); + } + else + { + pointparticles(particleeffectnum("crylink_impactbig"), org2, '0 0 0', 1); + if(!w_issilent) + sound(self, CH_SHOTS, "weapons/crylink_impact.wav", VOL_BASE, ATTEN_NORM); + } + } + else if(req == WR_PRECACHE) + { + precache_sound("weapons/crylink_impact2.wav"); + precache_sound("weapons/crylink_impact.wav"); + } + return TRUE; +} +#endif +#endif diff --git a/qcsrc/server/w_electro.qh b/qcsrc/server/w_electro.qh new file mode 100644 index 000000000..98c0be13e --- /dev/null +++ b/qcsrc/server/w_electro.qh @@ -0,0 +1,2 @@ +void ElectroInit(); +vector electro_shotorigin[4]; diff --git a/qcsrc/server/w_fireball.qc b/qcsrc/server/w_fireball.qc new file mode 100644 index 000000000..88e9d770f --- /dev/null +++ b/qcsrc/server/w_fireball.qc @@ -0,0 +1,434 @@ +#ifdef REGISTER_WEAPON +REGISTER_WEAPON( +/* WEP_##id */ FIREBALL, +/* function */ w_fireball, +/* ammotype */ 0, +/* impulse */ 9, +/* flags */ WEP_FLAG_SUPERWEAPON | WEP_TYPE_SPLASH, +/* rating */ BOT_PICKUP_RATING_MID, +/* model */ "fireball", +/* shortname */ "fireball", +/* fullname */ _("Fireball") +); +#else +#ifdef SVQC +.float bot_primary_fireballmooth; // whatever a mooth is +.vector fireball_impactvec; +.float fireball_primarytime; + +void W_Fireball_Explode (void) +{ + entity e; + float dist; + float points; + vector dir; + float d; + + self.event_damage = func_null; + self.takedamage = DAMAGE_NO; + + // 1. dist damage + d = (self.realowner.health + self.realowner.armorvalue); + RadiusDamage (self, self.realowner, autocvar_g_balance_fireball_primary_damage, autocvar_g_balance_fireball_primary_edgedamage, autocvar_g_balance_fireball_primary_radius, world, autocvar_g_balance_fireball_primary_force, self.projectiledeathtype, other); + if(self.realowner.health + self.realowner.armorvalue >= d) + if(!self.cnt) + { + modeleffect_spawn("models/sphere/sphere.md3", 0, 0, self.origin, '0 0 0', '0 0 0', '0 0 0', 0, autocvar_g_balance_fireball_primary_bfgradius, 0.2, 0.05, 0.25); + + // 2. bfg effect + // NOTE: this cannot be made warpzone aware by design. So, better intentionally ignore warpzones here. + for(e = findradius(self.origin, autocvar_g_balance_fireball_primary_bfgradius); e; e = e.chain) + if(e != self.realowner) if(e.takedamage == DAMAGE_AIM) if(!IS_PLAYER(e) || !self.realowner || DIFF_TEAM(e, self)) + { + // can we see fireball? + traceline(e.origin + e.view_ofs, self.origin, MOVE_NORMAL, e); + if(/* trace_startsolid || */ trace_fraction != 1) // startsolid should be never happening anyway + continue; + // can we see player who shot fireball? + traceline(e.origin + e.view_ofs, self.realowner.origin + self.realowner.view_ofs, MOVE_NORMAL, e); + if(trace_ent != self.realowner) + if(/* trace_startsolid || */ trace_fraction != 1) + continue; + dist = vlen(self.origin - e.origin - e.view_ofs); + points = (1 - sqrt(dist / autocvar_g_balance_fireball_primary_bfgradius)); + if(points <= 0) + continue; + dir = normalize(e.origin + e.view_ofs - self.origin); + + if(accuracy_isgooddamage(self.realowner, e)) + accuracy_add(self.realowner, WEP_FIREBALL, 0, autocvar_g_balance_fireball_primary_bfgdamage * points); + + Damage(e, self, self.realowner, autocvar_g_balance_fireball_primary_bfgdamage * points, self.projectiledeathtype | HITTYPE_BOUNCE | HITTYPE_SPLASH, e.origin + e.view_ofs, autocvar_g_balance_fireball_primary_bfgforce * dir); + pointparticles(particleeffectnum("fireball_bfgdamage"), e.origin, -1 * dir, 1); + } + } + + remove (self); +} + +void W_Fireball_TouchExplode (void) +{ + PROJECTILE_TOUCH; + W_Fireball_Explode (); +} + +void W_Fireball_LaserPlay(float dt, float dist, float damage, float edgedamage, float burntime) +{ + entity e; + float d; + vector p; + + if(damage <= 0) + return; + + RandomSelection_Init(); + for(e = WarpZone_FindRadius(self.origin, dist, TRUE); e; e = e.chain) + if(e != self.realowner) if(e.takedamage == DAMAGE_AIM) if(!IS_PLAYER(e) || !self.realowner || DIFF_TEAM(e, self)) + { + p = e.origin; + p_x += e.mins_x + random() * (e.maxs_x - e.mins_x); + p_y += e.mins_y + random() * (e.maxs_y - e.mins_y); + p_z += e.mins_z + random() * (e.maxs_z - e.mins_z); + d = vlen(WarpZone_UnTransformOrigin(e, self.origin) - p); + if(d < dist) + { + e.fireball_impactvec = p; + RandomSelection_Add(e, 0, string_null, 1 / (1 + d), !Fire_IsBurning(e)); + } + } + if(RandomSelection_chosen_ent) + { + d = vlen(WarpZone_UnTransformOrigin(RandomSelection_chosen_ent, self.origin) - RandomSelection_chosen_ent.fireball_impactvec); + d = damage + (edgedamage - damage) * (d / dist); + Fire_AddDamage(RandomSelection_chosen_ent, self.realowner, d * burntime, burntime, self.projectiledeathtype | HITTYPE_BOUNCE); + //trailparticles(self, particleeffectnum("fireball_laser"), self.origin, RandomSelection_chosen_ent.fireball_impactvec); + pointparticles(particleeffectnum("fireball_laser"), self.origin, RandomSelection_chosen_ent.fireball_impactvec - self.origin, 1); + } +} + +void W_Fireball_Think() +{ + if(time > self.pushltime) + { + self.cnt = 1; + self.projectiledeathtype |= HITTYPE_SPLASH; + W_Fireball_Explode(); + return; + } + + W_Fireball_LaserPlay(0.1, autocvar_g_balance_fireball_primary_laserradius, autocvar_g_balance_fireball_primary_laserdamage, autocvar_g_balance_fireball_primary_laseredgedamage, autocvar_g_balance_fireball_primary_laserburntime); + + self.nextthink = time + 0.1; +} + +void W_Fireball_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) +{ + if(self.health <= 0) + return; + + if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions + return; // g_projectiles_damage says to halt + + self.health = self.health - damage; + if (self.health <= 0) + { + self.cnt = 1; + W_PrepareExplosionByDamage(attacker, W_Fireball_Explode); + } +} + +void W_Fireball_Attack1() +{ + entity proj; + + W_SetupShot_ProjectileSize (self, '-16 -16 -16', '16 16 16', FALSE, 2, "weapons/fireball_fire2.wav", CH_WEAPON_A, autocvar_g_balance_fireball_primary_damage + autocvar_g_balance_fireball_primary_bfgdamage); + + pointparticles(particleeffectnum("fireball_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); + + proj = spawn (); + proj.classname = "plasma_prim"; + proj.owner = proj.realowner = self; + proj.bot_dodge = TRUE; + proj.bot_dodgerating = autocvar_g_balance_fireball_primary_damage; + proj.pushltime = time + autocvar_g_balance_fireball_primary_lifetime; + proj.use = W_Fireball_Explode; + proj.think = W_Fireball_Think; + proj.nextthink = time; + proj.health = autocvar_g_balance_fireball_primary_health; + proj.team = self.team; + proj.event_damage = W_Fireball_Damage; + proj.takedamage = DAMAGE_YES; + proj.damageforcescale = autocvar_g_balance_fireball_primary_damageforcescale; + PROJECTILE_MAKETRIGGER(proj); + proj.projectiledeathtype = WEP_FIREBALL; + setorigin(proj, w_shotorg); + + proj.movetype = MOVETYPE_FLY; + W_SETUPPROJECTILEVELOCITY(proj, g_balance_fireball_primary); + proj.angles = vectoangles(proj.velocity); + proj.touch = W_Fireball_TouchExplode; + setsize(proj, '-16 -16 -16', '16 16 16'); + proj.flags = FL_PROJECTILE; + proj.missile_flags = MIF_SPLASH | MIF_PROXY; + + CSQCProjectile(proj, TRUE, PROJECTILE_FIREBALL, TRUE); + + other = proj; MUTATOR_CALLHOOK(EditProjectile); +} + +void W_Fireball_AttackEffect(float i, vector f_diff) +{ + W_SetupShot_ProjectileSize (self, '-16 -16 -16', '16 16 16', FALSE, 0, "", 0, 0); + w_shotorg += f_diff_x * v_up + f_diff_y * v_right; + pointparticles(particleeffectnum("fireball_preattack_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); +} + +void W_Fireball_Attack1_Frame4() +{ + W_Fireball_Attack1(); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_fireball_primary_animtime, w_ready); +} + +void W_Fireball_Attack1_Frame3() +{ + W_Fireball_AttackEffect(0, '+1.25 +3.75 0'); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_fireball_primary_animtime, W_Fireball_Attack1_Frame4); +} + +void W_Fireball_Attack1_Frame2() +{ + W_Fireball_AttackEffect(0, '-1.25 +3.75 0'); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_fireball_primary_animtime, W_Fireball_Attack1_Frame3); +} + +void W_Fireball_Attack1_Frame1() +{ + W_Fireball_AttackEffect(1, '+1.25 -3.75 0'); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_fireball_primary_animtime, W_Fireball_Attack1_Frame2); +} + +void W_Fireball_Attack1_Frame0() +{ + W_Fireball_AttackEffect(0, '-1.25 -3.75 0'); + sound (self, CH_WEAPON_SINGLE, "weapons/fireball_prefire2.wav", VOL_BASE, ATTEN_NORM); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_fireball_primary_animtime, W_Fireball_Attack1_Frame1); +} + +void W_Firemine_Think() +{ + if(time > self.pushltime) + { + remove(self); + return; + } + + // make it "hot" once it leaves its owner + if(self.owner) + { + if(vlen(self.origin - self.owner.origin - self.owner.view_ofs) > autocvar_g_balance_fireball_secondary_laserradius) + { + self.cnt += 1; + if(self.cnt == 3) + self.owner = world; + } + else + self.cnt = 0; + } + + W_Fireball_LaserPlay(0.1, autocvar_g_balance_fireball_secondary_laserradius, autocvar_g_balance_fireball_secondary_laserdamage, autocvar_g_balance_fireball_secondary_laseredgedamage, autocvar_g_balance_fireball_secondary_laserburntime); + + self.nextthink = time + 0.1; +} + +void W_Firemine_Touch (void) +{ + PROJECTILE_TOUCH; + if (other.takedamage == DAMAGE_AIM) + if(Fire_AddDamage(other, self.realowner, autocvar_g_balance_fireball_secondary_damage, autocvar_g_balance_fireball_secondary_damagetime, self.projectiledeathtype) >= 0) + { + remove(self); + return; + } + self.projectiledeathtype |= HITTYPE_BOUNCE; +} + +void W_Fireball_Attack2() +{ + entity proj; + vector f_diff; + float c; + + c = mod(self.bulletcounter, 4); + switch(c) + { + case 0: + f_diff = '-1.25 -3.75 0'; + break; + case 1: + f_diff = '+1.25 -3.75 0'; + break; + case 2: + f_diff = '-1.25 +3.75 0'; + break; + case 3: + default: + f_diff = '+1.25 +3.75 0'; + break; + } + W_SetupShot_ProjectileSize(self, '-4 -4 -4', '4 4 4', FALSE, 2, "weapons/fireball_fire.wav", CH_WEAPON_A, autocvar_g_balance_fireball_secondary_damage); + traceline(w_shotorg, w_shotorg + f_diff_x * v_up + f_diff_y * v_right, MOVE_NORMAL, self); + w_shotorg = trace_endpos; + + pointparticles(particleeffectnum("fireball_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); + + proj = spawn (); + proj.owner = proj.realowner = self; + proj.classname = "grenade"; + proj.bot_dodge = TRUE; + proj.bot_dodgerating = autocvar_g_balance_fireball_secondary_damage; + proj.movetype = MOVETYPE_BOUNCE; + proj.projectiledeathtype = WEP_FIREBALL | HITTYPE_SECONDARY; + proj.touch = W_Firemine_Touch; + PROJECTILE_MAKETRIGGER(proj); + setsize(proj, '-4 -4 -4', '4 4 4'); + setorigin(proj, w_shotorg); + proj.think = W_Firemine_Think; + proj.nextthink = time; + proj.damageforcescale = autocvar_g_balance_fireball_secondary_damageforcescale; + proj.pushltime = time + autocvar_g_balance_fireball_secondary_lifetime; + W_SETUPPROJECTILEVELOCITY_UP(proj, g_balance_fireball_secondary); + + proj.angles = vectoangles(proj.velocity); + proj.flags = FL_PROJECTILE; + proj.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_ARC; + + CSQCProjectile(proj, TRUE, PROJECTILE_FIREMINE, TRUE); + + other = proj; MUTATOR_CALLHOOK(EditProjectile); +} + +void spawnfunc_weapon_fireball (void) +{ + weapon_defaultspawnfunc(WEP_FIREBALL); +} + +float w_fireball(float req) +{ + //float ammo_amount; + if (req == WR_AIM) + { + self.BUTTON_ATCK = FALSE; + self.BUTTON_ATCK2 = FALSE; + if (self.bot_primary_fireballmooth == 0) + { + if(bot_aim(autocvar_g_balance_fireball_primary_speed, 0, autocvar_g_balance_fireball_primary_lifetime, FALSE)) + { + self.BUTTON_ATCK = TRUE; + if(random() < 0.02) self.bot_primary_fireballmooth = 0; + } + } + else + { + if(bot_aim(autocvar_g_balance_fireball_secondary_speed, autocvar_g_balance_fireball_secondary_speed_up, autocvar_g_balance_fireball_secondary_lifetime, TRUE)) + { + self.BUTTON_ATCK2 = TRUE; + if(random() < 0.01) self.bot_primary_fireballmooth = 1; + } + } + } + else if (req == WR_THINK) + { + if (self.BUTTON_ATCK) + { + if (time >= self.fireball_primarytime) + if (weapon_prepareattack(0, autocvar_g_balance_fireball_primary_refire)) + { + W_Fireball_Attack1_Frame0(); + self.fireball_primarytime = time + autocvar_g_balance_fireball_primary_refire2 * W_WeaponRateFactor(); + } + } + else if (self.BUTTON_ATCK2) + { + if (weapon_prepareattack(1, autocvar_g_balance_fireball_secondary_refire)) + { + W_Fireball_Attack2(); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_fireball_secondary_animtime, w_ready); + } + } + } + else if (req == WR_PRECACHE) + { + precache_model ("models/weapons/g_fireball.md3"); + precache_model ("models/weapons/v_fireball.md3"); + precache_model ("models/weapons/h_fireball.iqm"); + precache_model ("models/sphere/sphere.md3"); + precache_sound ("weapons/fireball_fire.wav"); + precache_sound ("weapons/fireball_fire2.wav"); + precache_sound ("weapons/fireball_prefire2.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else + } + else if (req == WR_SETUP) + { + weapon_setup(WEP_FIREBALL); + self.current_ammo = ammo_none; + } + else if (req == WR_CHECKAMMO1) + { + return 1; + } + else if (req == WR_CHECKAMMO2) + { + return 1; + } + else if (req == WR_RESETPLAYER) + { + self.fireball_primarytime = time; + } + else if (req == WR_SUICIDEMESSAGE) + { + if(w_deathtype & HITTYPE_SECONDARY) + return WEAPON_FIREBALL_SUICIDE_FIREMINE; + else + return WEAPON_FIREBALL_SUICIDE_BLAST; + } + else if (req == WR_KILLMESSAGE) + { + if(w_deathtype & HITTYPE_SECONDARY) + { + return WEAPON_FIREBALL_MURDER_FIREMINE; + } + else + { + return WEAPON_FIREBALL_MURDER_BLAST; + } + } + return TRUE; +} +#endif +#ifdef CSQC +float w_fireball(float req) +{ + if(req == WR_IMPACTEFFECT) + { + vector org2; + if(w_deathtype & HITTYPE_SECONDARY) + { + // firemine goes out silently + } + else + { + org2 = w_org + w_backoff * 16; + pointparticles(particleeffectnum("fireball_explode"), org2, '0 0 0', 1); + if(!w_issilent) + sound(self, CH_SHOTS, "weapons/fireball_impact2.wav", VOL_BASE, ATTEN_NORM * 0.25); // long range boom + } + } + else if(req == WR_PRECACHE) + { + precache_sound("weapons/fireball_impact2.wav"); + } + + return TRUE; +} +#endif +#endif diff --git a/qcsrc/server/w_grenadelauncher.qc b/qcsrc/server/w_grenadelauncher.qc new file mode 100644 index 000000000..17144d3a5 --- /dev/null +++ b/qcsrc/server/w_grenadelauncher.qc @@ -0,0 +1,414 @@ +#ifdef REGISTER_WEAPON +REGISTER_WEAPON( +/* WEP_##id */ GRENADE_LAUNCHER, +/* function */ w_glauncher, +/* ammotype */ IT_ROCKETS, +/* impulse */ 4, +/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, +/* rating */ BOT_PICKUP_RATING_MID, +/* model */ "gl", +/* shortname */ "grenadelauncher", +/* fullname */ _("Mortar") +); +#else +#ifdef SVQC +.float gl_detonate_later; +.float gl_bouncecnt; + +void W_Grenade_Explode (void) +{ + if(other.takedamage == DAMAGE_AIM) + if(IS_PLAYER(other)) + if(DIFF_TEAM(self.realowner, other)) + if(other.deadflag == DEAD_NO) + if(IsFlying(other)) + Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT); + + self.event_damage = func_null; + self.takedamage = DAMAGE_NO; + + if(self.movetype == MOVETYPE_NONE) + self.velocity = self.oldvelocity; + + RadiusDamage (self, self.realowner, autocvar_g_balance_grenadelauncher_primary_damage, autocvar_g_balance_grenadelauncher_primary_edgedamage, autocvar_g_balance_grenadelauncher_primary_radius, world, autocvar_g_balance_grenadelauncher_primary_force, self.projectiledeathtype, other); + + remove (self); +} + +void W_Grenade_Explode2 (void) +{ + if(other.takedamage == DAMAGE_AIM) + if(IS_PLAYER(other)) + if(DIFF_TEAM(self.realowner, other)) + if(other.deadflag == DEAD_NO) + if(IsFlying(other)) + Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT); + + self.event_damage = func_null; + self.takedamage = DAMAGE_NO; + + if(self.movetype == MOVETYPE_NONE) + self.velocity = self.oldvelocity; + + RadiusDamage (self, self.realowner, autocvar_g_balance_grenadelauncher_secondary_damage, autocvar_g_balance_grenadelauncher_secondary_edgedamage, autocvar_g_balance_grenadelauncher_secondary_radius, world, autocvar_g_balance_grenadelauncher_secondary_force, self.projectiledeathtype, other); + + remove (self); +} + +void W_Grenade_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) +{ + if (self.health <= 0) + return; + + if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions + return; // g_projectiles_damage says to halt + + self.health = self.health - damage; + + if (self.health <= 0) + W_PrepareExplosionByDamage(attacker, self.use); +} + +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 >= autocvar_g_balance_grenadelauncher_primary_remote_minbouncecnt) + W_Grenade_Explode(); +} + +void W_Grenade_Touch1 (void) +{ + PROJECTILE_TOUCH; + if (other.takedamage == DAMAGE_AIM || autocvar_g_balance_grenadelauncher_primary_type == 0) // always explode when hitting a player, or if normal mortar projectile + { + self.use (); + } + else if (autocvar_g_balance_grenadelauncher_primary_type == 1) // bounce + { + float r; + r = random() * 6; + if(r < 1) + spamsound (self, CH_SHOTS, "weapons/grenade_bounce1.wav", VOL_BASE, ATTEN_NORM); + else if(r < 2) + spamsound (self, CH_SHOTS, "weapons/grenade_bounce2.wav", VOL_BASE, ATTEN_NORM); + else if(r < 3) + spamsound (self, CH_SHOTS, "weapons/grenade_bounce3.wav", VOL_BASE, ATTEN_NORM); + else if(r < 4) + spamsound (self, CH_SHOTS, "weapons/grenade_bounce4.wav", VOL_BASE, ATTEN_NORM); + else if(r < 5) + spamsound (self, CH_SHOTS, "weapons/grenade_bounce5.wav", VOL_BASE, ATTEN_NORM); + else + spamsound (self, CH_SHOTS, "weapons/grenade_bounce6.wav", VOL_BASE, ATTEN_NORM); + self.projectiledeathtype |= HITTYPE_BOUNCE; + self.gl_bouncecnt += 1; + } + else if(autocvar_g_balance_grenadelauncher_primary_type == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick + { + spamsound (self, CH_SHOTS, "weapons/grenade_stick.wav", VOL_BASE, ATTEN_NORM); + + // let it stick whereever it is + self.oldvelocity = self.velocity; + self.velocity = '0 0 0'; + self.movetype = MOVETYPE_NONE; // also disables gravity + self.gravity = 0; // nope, it does NOT! maybe a bug in CSQC code? TODO + UpdateCSQCProjectile(self); + + // do not respond to any more touches + self.solid = SOLID_NOT; + + self.nextthink = min(self.nextthink, time + autocvar_g_balance_grenadelauncher_primary_lifetime_stick); + } +} + +void W_Grenade_Touch2 (void) +{ + PROJECTILE_TOUCH; + if (other.takedamage == DAMAGE_AIM || autocvar_g_balance_grenadelauncher_secondary_type == 0) // always explode when hitting a player, or if normal mortar projectile + { + self.use (); + } + else if (autocvar_g_balance_grenadelauncher_secondary_type == 1) // bounce + { + float r; + r = random() * 6; + if(r < 1) + spamsound (self, CH_SHOTS, "weapons/grenade_bounce1.wav", VOL_BASE, ATTEN_NORM); + else if(r < 2) + spamsound (self, CH_SHOTS, "weapons/grenade_bounce2.wav", VOL_BASE, ATTEN_NORM); + else if(r < 3) + spamsound (self, CH_SHOTS, "weapons/grenade_bounce3.wav", VOL_BASE, ATTEN_NORM); + else if(r < 4) + spamsound (self, CH_SHOTS, "weapons/grenade_bounce4.wav", VOL_BASE, ATTEN_NORM); + else if(r < 5) + spamsound (self, CH_SHOTS, "weapons/grenade_bounce5.wav", VOL_BASE, ATTEN_NORM); + else + spamsound (self, CH_SHOTS, "weapons/grenade_bounce6.wav", VOL_BASE, ATTEN_NORM); + self.projectiledeathtype |= HITTYPE_BOUNCE; + self.gl_bouncecnt += 1; + + if (autocvar_g_balance_grenadelauncher_secondary_lifetime_bounce && self.gl_bouncecnt == 1) + self.nextthink = time + autocvar_g_balance_grenadelauncher_secondary_lifetime_bounce; + + } + else if(autocvar_g_balance_grenadelauncher_secondary_type == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick + { + spamsound (self, CH_SHOTS, "weapons/grenade_stick.wav", VOL_BASE, ATTEN_NORM); + + // let it stick whereever it is + self.oldvelocity = self.velocity; + self.velocity = '0 0 0'; + self.movetype = MOVETYPE_NONE; // also disables gravity + self.gravity = 0; // nope, it does NOT! maybe a bug in CSQC code? TODO + UpdateCSQCProjectile(self); + + // do not respond to any more touches + self.solid = SOLID_NOT; + + self.nextthink = min(self.nextthink, time + autocvar_g_balance_grenadelauncher_secondary_lifetime_stick); + } +} + +void W_Grenade_Attack (void) +{ + entity gren; + + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_grenadelauncher_primary_ammo, autocvar_g_balance_grenadelauncher_reload_ammo); + + W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CH_WEAPON_A, autocvar_g_balance_grenadelauncher_primary_damage); + w_shotdir = v_forward; // no TrueAim for grenades please + + pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); + + gren = spawn (); + gren.owner = gren.realowner = self; + gren.classname = "grenade"; + gren.bot_dodge = TRUE; + gren.bot_dodgerating = autocvar_g_balance_grenadelauncher_primary_damage; + gren.movetype = MOVETYPE_BOUNCE; + gren.bouncefactor = autocvar_g_balance_grenadelauncher_bouncefactor; + gren.bouncestop = autocvar_g_balance_grenadelauncher_bouncestop; + PROJECTILE_MAKETRIGGER(gren); + gren.projectiledeathtype = WEP_GRENADE_LAUNCHER; + setorigin(gren, w_shotorg); + setsize(gren, '-3 -3 -3', '3 3 3'); + + gren.cnt = time + autocvar_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 = autocvar_g_balance_grenadelauncher_primary_health; + gren.damageforcescale = autocvar_g_balance_grenadelauncher_primary_damageforcescale; + gren.event_damage = W_Grenade_Damage; + gren.damagedbycontents = TRUE; + gren.missile_flags = MIF_SPLASH | MIF_ARC; + W_SETUPPROJECTILEVELOCITY_UP(gren, g_balance_grenadelauncher_primary); + + gren.angles = vectoangles (gren.velocity); + gren.flags = FL_PROJECTILE; + + if(autocvar_g_balance_grenadelauncher_primary_type == 0 || autocvar_g_balance_grenadelauncher_primary_type == 2) + CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE, TRUE); + else + CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE_BOUNCING, TRUE); + + other = gren; MUTATOR_CALLHOOK(EditProjectile); +} + +void W_Grenade_Attack2 (void) +{ + entity gren; + + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_grenadelauncher_secondary_ammo, autocvar_g_balance_grenadelauncher_reload_ammo); + + W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CH_WEAPON_A, autocvar_g_balance_grenadelauncher_secondary_damage); + w_shotdir = v_forward; // no TrueAim for grenades please + + pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); + + gren = spawn (); + gren.owner = gren.realowner = self; + gren.classname = "grenade"; + gren.bot_dodge = TRUE; + gren.bot_dodgerating = autocvar_g_balance_grenadelauncher_secondary_damage; + gren.movetype = MOVETYPE_BOUNCE; + gren.bouncefactor = autocvar_g_balance_grenadelauncher_bouncefactor; + gren.bouncestop = autocvar_g_balance_grenadelauncher_bouncestop; + PROJECTILE_MAKETRIGGER(gren); + gren.projectiledeathtype = WEP_GRENADE_LAUNCHER | HITTYPE_SECONDARY; + setorigin(gren, w_shotorg); + setsize(gren, '-3 -3 -3', '3 3 3'); + + gren.nextthink = time + autocvar_g_balance_grenadelauncher_secondary_lifetime; + gren.think = adaptor_think2use_hittype_splash; + gren.use = W_Grenade_Explode2; + gren.touch = W_Grenade_Touch2; + + gren.takedamage = DAMAGE_YES; + gren.health = autocvar_g_balance_grenadelauncher_secondary_health; + gren.damageforcescale = autocvar_g_balance_grenadelauncher_secondary_damageforcescale; + gren.event_damage = W_Grenade_Damage; + gren.damagedbycontents = TRUE; + gren.missile_flags = MIF_SPLASH | MIF_ARC; + W_SETUPPROJECTILEVELOCITY_UP(gren, g_balance_grenadelauncher_secondary); + + gren.angles = vectoangles (gren.velocity); + gren.flags = FL_PROJECTILE; + + if(autocvar_g_balance_grenadelauncher_secondary_type == 0 || autocvar_g_balance_grenadelauncher_secondary_type == 2) + CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE, TRUE); + else + CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE_BOUNCING, TRUE); + + other = gren; MUTATOR_CALLHOOK(EditProjectile); +} + +void spawnfunc_weapon_grenadelauncher (void) +{ + weapon_defaultspawnfunc(WEP_GRENADE_LAUNCHER); +} + +.float bot_secondary_grenademooth; +float w_glauncher(float req) +{ + entity nade; + float nadefound; + float ammo_amount; + + if (req == WR_AIM) + { + self.BUTTON_ATCK = FALSE; + self.BUTTON_ATCK2 = FALSE; + if (self.bot_secondary_grenademooth == 0) + { + if(bot_aim(autocvar_g_balance_grenadelauncher_primary_speed, autocvar_g_balance_grenadelauncher_primary_speed_up, autocvar_g_balance_grenadelauncher_primary_lifetime, TRUE)) + { + self.BUTTON_ATCK = TRUE; + if(random() < 0.01) self.bot_secondary_grenademooth = 1; + } + } + else + { + if(bot_aim(autocvar_g_balance_grenadelauncher_secondary_speed, autocvar_g_balance_grenadelauncher_secondary_speed_up, autocvar_g_balance_grenadelauncher_secondary_lifetime, TRUE)) + { + self.BUTTON_ATCK2 = TRUE; + if(random() < 0.02) self.bot_secondary_grenademooth = 0; + } + } + } + else if (req == WR_THINK) + { + if(autocvar_g_balance_grenadelauncher_reload_ammo && self.clip_load < min(autocvar_g_balance_grenadelauncher_primary_ammo, autocvar_g_balance_grenadelauncher_secondary_ammo)) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else if (self.BUTTON_ATCK) + { + if (weapon_prepareattack(0, autocvar_g_balance_grenadelauncher_primary_refire)) + { + W_Grenade_Attack(); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_grenadelauncher_primary_animtime, w_ready); + } + } + else if (self.BUTTON_ATCK2) + { + if (cvar("g_balance_grenadelauncher_secondary_remote_detonateprimary")) + { + nadefound = 0; + for(nade = world; (nade = find(nade, classname, "grenade")); ) if(nade.realowner == self) + { + if(!nade.gl_detonate_later) + { + nade.gl_detonate_later = TRUE; + nadefound = 1; + } + } + if(nadefound) + sound (self, CH_WEAPON_B, "weapons/rocket_det.wav", VOL_BASE, ATTEN_NORM); + } + else if (weapon_prepareattack(1, autocvar_g_balance_grenadelauncher_secondary_refire)) + { + W_Grenade_Attack2(); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_grenadelauncher_secondary_animtime, w_ready); + } + } + } + else if (req == WR_PRECACHE) + { + precache_model ("models/weapons/g_gl.md3"); + precache_model ("models/weapons/v_gl.md3"); + precache_model ("models/weapons/h_gl.iqm"); + precache_sound ("weapons/grenade_bounce1.wav"); + precache_sound ("weapons/grenade_bounce2.wav"); + precache_sound ("weapons/grenade_bounce3.wav"); + precache_sound ("weapons/grenade_bounce4.wav"); + precache_sound ("weapons/grenade_bounce5.wav"); + precache_sound ("weapons/grenade_bounce6.wav"); + precache_sound ("weapons/grenade_stick.wav"); + precache_sound ("weapons/grenade_fire.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else + } + else if (req == WR_SETUP) + { + weapon_setup(WEP_GRENADE_LAUNCHER); + self.current_ammo = ammo_rockets; + } + else if (req == WR_CHECKAMMO1) + { + ammo_amount = self.ammo_rockets >= autocvar_g_balance_grenadelauncher_primary_ammo; + ammo_amount += self.(weapon_load[WEP_GRENADE_LAUNCHER]) >= autocvar_g_balance_grenadelauncher_primary_ammo; + return ammo_amount; + } + else if (req == WR_CHECKAMMO2) + { + ammo_amount = self.ammo_rockets >= autocvar_g_balance_grenadelauncher_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_GRENADE_LAUNCHER]) >= autocvar_g_balance_grenadelauncher_secondary_ammo; + return ammo_amount; + } + else if (req == WR_RELOAD) + { + W_Reload(min(autocvar_g_balance_grenadelauncher_primary_ammo, autocvar_g_balance_grenadelauncher_secondary_ammo), autocvar_g_balance_grenadelauncher_reload_ammo, autocvar_g_balance_grenadelauncher_reload_time, "weapons/reload.wav"); + } + else if (req == WR_SUICIDEMESSAGE) + { + if(w_deathtype & HITTYPE_SECONDARY) + return WEAPON_MORTAR_SUICIDE_BOUNCE; + else + return WEAPON_MORTAR_SUICIDE_EXPLODE; + } + else if (req == WR_KILLMESSAGE) + { + if(w_deathtype & HITTYPE_SECONDARY) + return WEAPON_MORTAR_MURDER_BOUNCE; + else + return WEAPON_MORTAR_MURDER_EXPLODE; + } + return TRUE; +} +#endif +#ifdef CSQC +float w_glauncher(float req) +{ + if(req == WR_IMPACTEFFECT) + { + vector org2; + org2 = w_org + w_backoff * 12; + pointparticles(particleeffectnum("grenade_explode"), org2, '0 0 0', 1); + if(!w_issilent) + sound(self, CH_SHOTS, "weapons/grenade_impact.wav", VOL_BASE, ATTEN_NORM); + } + else if(req == WR_PRECACHE) + { + precache_sound("weapons/grenade_impact.wav"); + } + return TRUE; +} +#endif +#endif diff --git a/qcsrc/server/w_hagar.qc b/qcsrc/server/w_hagar.qc new file mode 100644 index 000000000..05768fc50 --- /dev/null +++ b/qcsrc/server/w_hagar.qc @@ -0,0 +1,489 @@ +#ifdef REGISTER_WEAPON +REGISTER_WEAPON( +/* WEP_##id */ HAGAR, +/* function */ w_hagar, +/* ammotype */ IT_ROCKETS, +/* impulse */ 8, +/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, +/* rating */ BOT_PICKUP_RATING_MID, +/* model */ "hagar", +/* shortname */ "hagar", +/* fullname */ _("Hagar") +); +#else +#ifdef SVQC +// NO bounce protection, as bounces are limited! + +void W_Hagar_Explode (void) +{ + self.event_damage = func_null; + RadiusDamage (self, self.realowner, autocvar_g_balance_hagar_primary_damage, autocvar_g_balance_hagar_primary_edgedamage, autocvar_g_balance_hagar_primary_radius, world, autocvar_g_balance_hagar_primary_force, self.projectiledeathtype, other); + + remove (self); +} + +void W_Hagar_Explode2 (void) +{ + self.event_damage = func_null; + RadiusDamage (self, self.realowner, autocvar_g_balance_hagar_secondary_damage, autocvar_g_balance_hagar_secondary_edgedamage, autocvar_g_balance_hagar_secondary_radius, world, autocvar_g_balance_hagar_secondary_force, self.projectiledeathtype, other); + + remove (self); +} + +void W_Hagar_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) +{ + if (self.health <= 0) + return; + + float is_linkexplode = ( ((inflictor.owner != world) ? (inflictor.owner == self.owner) : TRUE) + && (inflictor.projectiledeathtype & HITTYPE_SECONDARY) + && (self.projectiledeathtype & HITTYPE_SECONDARY)); + + if(is_linkexplode) + is_linkexplode = (is_linkexplode && autocvar_g_balance_hagar_secondary_load_linkexplode); + else + is_linkexplode = -1; // not secondary load, so continue as normal without exception. + + if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, is_linkexplode)) + return; // g_projectiles_damage says to halt + + self.health = self.health - damage; + self.angles = vectoangles(self.velocity); + + if (self.health <= 0) + W_PrepareExplosionByDamage(attacker, self.think); +} + +void W_Hagar_Touch (void) +{ + PROJECTILE_TOUCH; + self.use (); +} + +void W_Hagar_Touch2 (void) +{ + PROJECTILE_TOUCH; + + if(self.cnt > 0 || other.takedamage == DAMAGE_AIM) { + self.use(); + } else { + self.cnt++; + pointparticles(particleeffectnum("hagar_bounce"), self.origin, self.velocity, 1); + self.angles = vectoangles (self.velocity); + self.owner = world; + self.projectiledeathtype |= HITTYPE_BOUNCE; + } +} + +void W_Hagar_Attack (void) +{ + entity missile; + + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_hagar_primary_ammo, autocvar_g_balance_hagar_reload_ammo); + + W_SetupShot (self, FALSE, 2, "weapons/hagar_fire.wav", CH_WEAPON_A, autocvar_g_balance_hagar_primary_damage); + + pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); + + missile = spawn (); + missile.owner = missile.realowner = self; + missile.classname = "missile"; + missile.bot_dodge = TRUE; + missile.bot_dodgerating = autocvar_g_balance_hagar_primary_damage; + + missile.takedamage = DAMAGE_YES; + missile.health = autocvar_g_balance_hagar_primary_health; + missile.damageforcescale = autocvar_g_balance_hagar_primary_damageforcescale; + missile.event_damage = W_Hagar_Damage; + missile.damagedbycontents = TRUE; + + missile.touch = W_Hagar_Touch; + missile.use = W_Hagar_Explode; + missile.think = adaptor_think2use_hittype_splash; + missile.nextthink = time + autocvar_g_balance_hagar_primary_lifetime; + PROJECTILE_MAKETRIGGER(missile); + missile.projectiledeathtype = WEP_HAGAR; + setorigin (missile, w_shotorg); + setsize(missile, '0 0 0', '0 0 0'); + + missile.movetype = MOVETYPE_FLY; + W_SETUPPROJECTILEVELOCITY(missile, g_balance_hagar_primary); + + missile.angles = vectoangles (missile.velocity); + missile.flags = FL_PROJECTILE; + missile.missile_flags = MIF_SPLASH; + + CSQCProjectile(missile, TRUE, PROJECTILE_HAGAR, TRUE); + + other = missile; MUTATOR_CALLHOOK(EditProjectile); +} + +void W_Hagar_Attack2 (void) +{ + entity missile; + + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_hagar_secondary_ammo, autocvar_g_balance_hagar_reload_ammo); + + W_SetupShot (self, FALSE, 2, "weapons/hagar_fire.wav", CH_WEAPON_A, autocvar_g_balance_hagar_secondary_damage); + + pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); + + missile = spawn (); + missile.owner = missile.realowner = self; + missile.classname = "missile"; + missile.bot_dodge = TRUE; + missile.bot_dodgerating = autocvar_g_balance_hagar_secondary_damage; + + missile.takedamage = DAMAGE_YES; + missile.health = autocvar_g_balance_hagar_secondary_health; + missile.damageforcescale = autocvar_g_balance_hagar_secondary_damageforcescale; + missile.event_damage = W_Hagar_Damage; + missile.damagedbycontents = TRUE; + + missile.touch = W_Hagar_Touch2; + missile.cnt = 0; + missile.use = W_Hagar_Explode2; + missile.think = adaptor_think2use_hittype_splash; + missile.nextthink = time + autocvar_g_balance_hagar_secondary_lifetime_min + random() * autocvar_g_balance_hagar_secondary_lifetime_rand; + PROJECTILE_MAKETRIGGER(missile); + missile.projectiledeathtype = WEP_HAGAR | HITTYPE_SECONDARY; + setorigin (missile, w_shotorg); + setsize(missile, '0 0 0', '0 0 0'); + + missile.movetype = MOVETYPE_BOUNCEMISSILE; + W_SETUPPROJECTILEVELOCITY(missile, g_balance_hagar_secondary); + + missile.angles = vectoangles (missile.velocity); + missile.flags = FL_PROJECTILE; + missile.missile_flags = MIF_SPLASH; + + CSQCProjectile(missile, TRUE, PROJECTILE_HAGAR_BOUNCING, TRUE); + + other = missile; MUTATOR_CALLHOOK(EditProjectile); +} + +.float hagar_loadstep, hagar_loadblock, hagar_loadbeep, hagar_warning; +void W_Hagar_Attack2_Load_Release (void) +{ + // time to release the rockets we've loaded + + entity missile; + float counter, shots, spread_pershot; + vector s; + vector forward, right, up; + + if(!self.hagar_load) + return; + + weapon_prepareattack_do(1, autocvar_g_balance_hagar_secondary_refire); + + W_SetupShot (self, FALSE, 2, "weapons/hagar_fire.wav", CH_WEAPON_A, autocvar_g_balance_hagar_secondary_damage); + pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); + + forward = v_forward; + right = v_right; + up = v_up; + + shots = self.hagar_load; + missile = world; + for(counter = 0; counter < shots; ++counter) + { + missile = spawn (); + missile.owner = missile.realowner = self; + missile.classname = "missile"; + missile.bot_dodge = TRUE; + missile.bot_dodgerating = autocvar_g_balance_hagar_secondary_damage; + + missile.takedamage = DAMAGE_YES; + missile.health = autocvar_g_balance_hagar_secondary_health; + missile.damageforcescale = autocvar_g_balance_hagar_secondary_damageforcescale; + missile.event_damage = W_Hagar_Damage; + missile.damagedbycontents = TRUE; + + missile.touch = W_Hagar_Touch; // not bouncy + missile.use = W_Hagar_Explode2; + missile.think = adaptor_think2use_hittype_splash; + missile.nextthink = time + autocvar_g_balance_hagar_secondary_lifetime_min + random() * autocvar_g_balance_hagar_secondary_lifetime_rand; + PROJECTILE_MAKETRIGGER(missile); + missile.projectiledeathtype = WEP_HAGAR | HITTYPE_SECONDARY; + setorigin (missile, w_shotorg); + setsize(missile, '0 0 0', '0 0 0'); + missile.movetype = MOVETYPE_FLY; + missile.missile_flags = MIF_SPLASH; + + // per-shot spread calculation: the more shots there are, the less spread is applied (based on the bias cvar) + spread_pershot = ((shots - 1) / (autocvar_g_balance_hagar_secondary_load_max - 1)); + spread_pershot = (1 - (spread_pershot * autocvar_g_balance_hagar_secondary_load_spread_bias)); + spread_pershot = (autocvar_g_balance_hagar_secondary_spread * spread_pershot * g_weaponspreadfactor); + + // pattern spread calculation + s = '0 0 0'; + if (counter == 0) + s = '0 0 0'; + else + { + makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1))); + s_y = v_forward_x; + s_z = v_forward_y; + } + s = s * autocvar_g_balance_hagar_secondary_load_spread * g_weaponspreadfactor; + + W_SetupProjectileVelocityEx(missile, w_shotdir + right * s_y + up * s_z, v_up, autocvar_g_balance_hagar_secondary_speed, 0, 0, spread_pershot, FALSE); + + missile.angles = vectoangles (missile.velocity); + missile.flags = FL_PROJECTILE; + + CSQCProjectile(missile, TRUE, PROJECTILE_HAGAR, TRUE); + + other = missile; MUTATOR_CALLHOOK(EditProjectile); + } + + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_hagar_secondary_load_animtime, w_ready); + self.hagar_loadstep = time + autocvar_g_balance_hagar_secondary_refire * W_WeaponRateFactor(); + self.hagar_load = 0; +} + +void W_Hagar_Attack2_Load (void) +{ + // loadable hagar secondary attack, must always run each frame + + if(time < game_starttime) + return; + + float loaded, enough_ammo; + loaded = self.hagar_load >= autocvar_g_balance_hagar_secondary_load_max; + + // this is different than WR_CHECKAMMO when it comes to reloading + if(autocvar_g_balance_hagar_reload_ammo) + enough_ammo = self.(weapon_load[WEP_HAGAR]) >= autocvar_g_balance_hagar_secondary_ammo; + else + enough_ammo = self.ammo_rockets >= autocvar_g_balance_hagar_secondary_ammo; + + if(self.BUTTON_ATCK2) + { + if(self.BUTTON_ATCK && autocvar_g_balance_hagar_secondary_load_abort) + { + if(self.hagar_load) + { + // if we pressed primary fire while loading, unload all rockets and abort + self.weaponentity.state = WS_READY; + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_hagar_secondary_ammo * self.hagar_load * -1, autocvar_g_balance_hagar_reload_ammo); // give back ammo + self.hagar_load = 0; + sound(self, CH_WEAPON_A, "weapons/hagar_beep.wav", VOL_BASE, ATTEN_NORM); + + // pause until we can load rockets again, once we re-press the alt fire button + self.hagar_loadstep = time + autocvar_g_balance_hagar_secondary_load_speed * W_WeaponRateFactor(); + + // require letting go of the alt fire button before we can load again + self.hagar_loadblock = TRUE; + } + } + else + { + // check if we can attempt to load another rocket + if(!loaded && enough_ammo) + { + if(!self.hagar_loadblock && self.hagar_loadstep < time) + { + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_hagar_secondary_ammo, autocvar_g_balance_hagar_reload_ammo); + self.weaponentity.state = WS_INUSE; + self.hagar_load += 1; + sound(self, CH_WEAPON_B, "weapons/hagar_load.wav", VOL_BASE * 0.8, ATTEN_NORM); // sound is too loud according to most + + if (self.hagar_load >= autocvar_g_balance_hagar_secondary_load_max) + self.hagar_loadstep = time + autocvar_g_balance_hagar_secondary_load_hold * W_WeaponRateFactor(); + else + self.hagar_loadstep = time + autocvar_g_balance_hagar_secondary_load_speed * W_WeaponRateFactor(); + } + } + else if(!self.hagar_loadbeep && self.hagar_load) // prevents the beep from playing each frame + { + // if this is the last rocket we can load, play a beep sound to notify the player + sound(self, CH_WEAPON_A, "weapons/hagar_beep.wav", VOL_BASE, ATTEN_NORM); + self.hagar_loadbeep = TRUE; + } + } + } + else if(self.hagar_loadblock) + { + // the alt fire button has been released, so re-enable loading if blocked + self.hagar_loadblock = FALSE; + } + + if(self.hagar_load) + { + // play warning sound if we're about to release + if((loaded || !enough_ammo) && self.hagar_loadstep - 0.5 < time && autocvar_g_balance_hagar_secondary_load_hold >= 0) + { + if(!self.hagar_warning && self.hagar_load) // prevents the beep from playing each frame + { + // we're about to automatically release after holding time, play a beep sound to notify the player + sound(self, CH_WEAPON_A, "weapons/hagar_beep.wav", VOL_BASE, ATTEN_NORM); + self.hagar_warning = TRUE; + } + } + + // release if player let go of button or if they've held it in too long + if(!self.BUTTON_ATCK2 || ((loaded || !enough_ammo) && self.hagar_loadstep < time && autocvar_g_balance_hagar_secondary_load_hold >= 0)) + { + self.weaponentity.state = WS_READY; + W_Hagar_Attack2_Load_Release(); + } + } + else + { + self.hagar_loadbeep = FALSE; + self.hagar_warning = FALSE; + } + + // we aren't checking ammo during an attack, so we must do it here + if (!(weapon_action(self.weapon, WR_CHECKAMMO1) + weapon_action(self.weapon, WR_CHECKAMMO2))) + { + // note: this doesn't force the switch + W_SwitchToOtherWeapon(self); + return; + } +} + +void spawnfunc_weapon_hagar (void) +{ + weapon_defaultspawnfunc(WEP_HAGAR); +} + +float w_hagar(float req) +{ + float ammo_amount; + if (req == WR_AIM) + if (random()>0.15) + self.BUTTON_ATCK = bot_aim(autocvar_g_balance_hagar_primary_speed, 0, autocvar_g_balance_hagar_primary_lifetime, FALSE); + else + { + // not using secondary_speed since these are only 15% and should cause some ricochets without re-aiming + self.BUTTON_ATCK2 = bot_aim(autocvar_g_balance_hagar_primary_speed, 0, autocvar_g_balance_hagar_primary_lifetime, FALSE); + } + else if (req == WR_THINK) + { + float loadable_secondary; + loadable_secondary = (autocvar_g_balance_hagar_secondary_load && autocvar_g_balance_hagar_secondary); + + if (loadable_secondary) + W_Hagar_Attack2_Load(); // must always run each frame + if(autocvar_g_balance_hagar_reload_ammo && self.clip_load < min(autocvar_g_balance_hagar_primary_ammo, autocvar_g_balance_hagar_secondary_ammo)) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else if (self.BUTTON_ATCK && !self.hagar_load && !self.hagar_loadblock) // not while secondary is loaded or awaiting reset + { + if (weapon_prepareattack(0, autocvar_g_balance_hagar_primary_refire)) + { + W_Hagar_Attack(); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hagar_primary_refire, w_ready); + } + } + else if (self.BUTTON_ATCK2 && !loadable_secondary && autocvar_g_balance_hagar_secondary) + { + if (weapon_prepareattack(1, autocvar_g_balance_hagar_secondary_refire)) + { + W_Hagar_Attack2(); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_hagar_secondary_refire, w_ready); + } + } + } + else if (req == WR_GONETHINK) + { + // we lost the weapon and want to prepare switching away + if(self.hagar_load) + { + self.weaponentity.state = WS_READY; + W_Hagar_Attack2_Load_Release(); + } + } + else if (req == WR_PRECACHE) + { + precache_model ("models/weapons/g_hagar.md3"); + precache_model ("models/weapons/v_hagar.md3"); + precache_model ("models/weapons/h_hagar.iqm"); + precache_sound ("weapons/hagar_fire.wav"); + precache_sound ("weapons/hagar_load.wav"); + precache_sound ("weapons/hagar_beep.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else + } + else if (req == WR_SETUP) + { + weapon_setup(WEP_HAGAR); + self.current_ammo = ammo_rockets; + self.hagar_loadblock = FALSE; + + if(self.hagar_load) + { + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_hagar_secondary_ammo * self.hagar_load * -1, autocvar_g_balance_hagar_reload_ammo); // give back ammo if necessary + self.hagar_load = 0; + } + } + else if (req == WR_CHECKAMMO1) + { + ammo_amount = self.ammo_rockets >= autocvar_g_balance_hagar_primary_ammo; + ammo_amount += self.(weapon_load[WEP_HAGAR]) >= autocvar_g_balance_hagar_primary_ammo; + return ammo_amount; + } + else if (req == WR_CHECKAMMO2) + { + ammo_amount = self.ammo_rockets >= autocvar_g_balance_hagar_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_HAGAR]) >= autocvar_g_balance_hagar_secondary_ammo; + return ammo_amount; + } + else if (req == WR_RESETPLAYER) + { + self.hagar_load = 0; + } + else if (req == WR_PLAYERDEATH) + { + // if we have any rockets loaded when we die, release them + if(self.hagar_load && autocvar_g_balance_hagar_secondary_load_releasedeath) + W_Hagar_Attack2_Load_Release(); + } + else if (req == WR_RELOAD) + { + if (!self.hagar_load) // require releasing loaded rockets first + W_Reload(min(autocvar_g_balance_hagar_primary_ammo, autocvar_g_balance_hagar_secondary_ammo), autocvar_g_balance_hagar_reload_ammo, autocvar_g_balance_hagar_reload_time, "weapons/reload.wav"); + } + else if (req == WR_SUICIDEMESSAGE) + { + return WEAPON_HAGAR_SUICIDE; + } + else if (req == WR_KILLMESSAGE) + { + if(w_deathtype & HITTYPE_SECONDARY) + return WEAPON_HAGAR_MURDER_BURST; + else + return WEAPON_HAGAR_MURDER_SPRAY; + } + return TRUE; +} +#endif +#ifdef CSQC +float w_hagar(float req) +{ + if(req == WR_IMPACTEFFECT) + { + vector org2; + org2 = w_org + w_backoff * 6; + pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1); + if(!w_issilent) + { + if (w_random<0.15) + sound(self, CH_SHOTS, "weapons/hagexp1.wav", VOL_BASE, ATTEN_NORM); + else if (w_random<0.7) + sound(self, CH_SHOTS, "weapons/hagexp2.wav", VOL_BASE, ATTEN_NORM); + else + sound(self, CH_SHOTS, "weapons/hagexp3.wav", VOL_BASE, ATTEN_NORM); + } + } + else if(req == WR_PRECACHE) + { + precache_sound("weapons/hagexp1.wav"); + precache_sound("weapons/hagexp2.wav"); + precache_sound("weapons/hagexp3.wav"); + } + return TRUE; +} +#endif +#endif diff --git a/qcsrc/server/w_hlac.qc b/qcsrc/server/w_hlac.qc new file mode 100644 index 000000000..5642ef057 --- /dev/null +++ b/qcsrc/server/w_hlac.qc @@ -0,0 +1,261 @@ +#ifdef REGISTER_WEAPON +REGISTER_WEAPON( +/* WEP_##id */ HLAC, +/* function */ w_hlac, +/* ammotype */ IT_CELLS, +/* impulse */ 6, +/* flags */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH, +/* rating */ BOT_PICKUP_RATING_MID, +/* model */ "hlac", +/* shortname */ "hlac", +/* fullname */ _("Heavy Laser Assault Cannon") +); +#else +#ifdef SVQC + +void W_HLAC_Touch (void) +{ + PROJECTILE_TOUCH; + + self.event_damage = func_null; + + if(self.projectiledeathtype & HITTYPE_SECONDARY) + RadiusDamage (self, self.realowner, autocvar_g_balance_hlac_secondary_damage, autocvar_g_balance_hlac_secondary_edgedamage, autocvar_g_balance_hlac_secondary_radius, world, autocvar_g_balance_hlac_secondary_force, self.projectiledeathtype, other); + else + RadiusDamage (self, self.realowner, autocvar_g_balance_hlac_primary_damage, autocvar_g_balance_hlac_primary_edgedamage, autocvar_g_balance_hlac_primary_radius, world, autocvar_g_balance_hlac_primary_force, self.projectiledeathtype, other); + + remove (self); +} + +void W_HLAC_Attack (void) +{ + entity missile; + float spread; + + W_DecreaseAmmo(ammo_cells, autocvar_g_balance_hlac_primary_ammo, autocvar_g_balance_hlac_reload_ammo); + + spread = autocvar_g_balance_hlac_primary_spread_min + (autocvar_g_balance_hlac_primary_spread_add * self.misc_bulletcounter); + spread = min(spread,autocvar_g_balance_hlac_primary_spread_max); + if(self.crouch) + spread = spread * autocvar_g_balance_hlac_primary_spread_crouchmod; + + W_SetupShot (self, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_A, autocvar_g_balance_hlac_primary_damage); + pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); + if (!autocvar_g_norecoil) + { + self.punchangle_x = random () - 0.5; + self.punchangle_y = random () - 0.5; + } + + missile = spawn (); + missile.owner = missile.realowner = self; + missile.classname = "hlacbolt"; + missile.bot_dodge = TRUE; + + missile.bot_dodgerating = autocvar_g_balance_hlac_primary_damage; + + missile.movetype = MOVETYPE_FLY; + PROJECTILE_MAKETRIGGER(missile); + + setorigin (missile, w_shotorg); + setsize(missile, '0 0 0', '0 0 0'); + + W_SetupProjectileVelocity(missile, autocvar_g_balance_hlac_primary_speed, spread); + //missile.angles = vectoangles (missile.velocity); // csqc + + missile.touch = W_HLAC_Touch; + missile.think = SUB_Remove; + + missile.nextthink = time + autocvar_g_balance_hlac_primary_lifetime; + + missile.flags = FL_PROJECTILE; + missile.projectiledeathtype = WEP_HLAC; + + CSQCProjectile(missile, TRUE, PROJECTILE_HLAC, TRUE); + + other = missile; MUTATOR_CALLHOOK(EditProjectile); +} + +void W_HLAC_Attack2f (void) +{ + entity missile; + float spread; + + spread = autocvar_g_balance_hlac_secondary_spread; + + + if(self.crouch) + spread = spread * autocvar_g_balance_hlac_secondary_spread_crouchmod; + + W_SetupShot (self, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_A, autocvar_g_balance_hlac_secondary_damage); + pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); + + missile = spawn (); + missile.owner = missile.realowner = self; + missile.classname = "hlacbolt"; + missile.bot_dodge = TRUE; + + missile.bot_dodgerating = autocvar_g_balance_hlac_secondary_damage; + + missile.movetype = MOVETYPE_FLY; + PROJECTILE_MAKETRIGGER(missile); + + setorigin (missile, w_shotorg); + setsize(missile, '0 0 0', '0 0 0'); + + W_SetupProjectileVelocity(missile, autocvar_g_balance_hlac_secondary_speed, spread); + //missile.angles = vectoangles (missile.velocity); // csqc + + missile.touch = W_HLAC_Touch; + missile.think = SUB_Remove; + + missile.nextthink = time + autocvar_g_balance_hlac_secondary_lifetime; + + missile.flags = FL_PROJECTILE; + missile.missile_flags = MIF_SPLASH; + missile.projectiledeathtype = WEP_HLAC | HITTYPE_SECONDARY; + + CSQCProjectile(missile, TRUE, PROJECTILE_HLAC, TRUE); + + other = missile; MUTATOR_CALLHOOK(EditProjectile); +} + +void W_HLAC_Attack2 (void) +{ + float i; + + W_DecreaseAmmo(ammo_cells, autocvar_g_balance_hlac_secondary_ammo, autocvar_g_balance_hlac_reload_ammo); + + for(i=autocvar_g_balance_hlac_secondary_shots;i>0;--i) + W_HLAC_Attack2f(); + + if (!autocvar_g_norecoil) + { + self.punchangle_x = random () - 0.5; + self.punchangle_y = random () - 0.5; + } +} + +// weapon frames +void HLAC_fire1_02() +{ + if(self.weapon != self.switchweapon) // abort immediately if switching + { + w_ready(); + return; + } + + if (self.BUTTON_ATCK) + { + if (!weapon_action(self.weapon, WR_CHECKAMMO1)) + if (!(self.items & IT_UNLIMITED_WEAPON_AMMO)) + { + W_SwitchWeapon_Force(self, w_getbestweapon(self)); + w_ready(); + return; + } + + ATTACK_FINISHED(self) = time + autocvar_g_balance_hlac_primary_refire * W_WeaponRateFactor(); + W_HLAC_Attack(); + self.misc_bulletcounter = self.misc_bulletcounter + 1; + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hlac_primary_refire, HLAC_fire1_02); + } + else + { + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hlac_primary_animtime, w_ready); + } +} + +void spawnfunc_weapon_hlac (void) +{ + weapon_defaultspawnfunc(WEP_HLAC); +} + +float w_hlac(float req) +{ + float ammo_amount; + if (req == WR_AIM) + self.BUTTON_ATCK = bot_aim(autocvar_g_balance_hlac_primary_speed, 0, autocvar_g_balance_hlac_primary_lifetime, FALSE); + else if (req == WR_THINK) + { + if(autocvar_g_balance_hlac_reload_ammo && self.clip_load < min(autocvar_g_balance_hlac_primary_ammo, autocvar_g_balance_hlac_secondary_ammo)) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else if (self.BUTTON_ATCK) + { + if (weapon_prepareattack(0, autocvar_g_balance_hlac_primary_refire)) + { + self.misc_bulletcounter = 0; + W_HLAC_Attack(); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hlac_primary_refire, HLAC_fire1_02); + } + } + + else if (self.BUTTON_ATCK2 && autocvar_g_balance_hlac_secondary) + { + if (weapon_prepareattack(1, autocvar_g_balance_hlac_secondary_refire)) + { + W_HLAC_Attack2(); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_hlac_secondary_animtime, w_ready); + } + } + } + else if (req == WR_PRECACHE) + { + precache_model ("models/weapons/g_hlac.md3"); + precache_model ("models/weapons/v_hlac.md3"); + precache_model ("models/weapons/h_hlac.iqm"); + precache_sound ("weapons/lasergun_fire.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else + + } + else if (req == WR_SETUP) + { + weapon_setup(WEP_HLAC); + self.current_ammo = ammo_cells; + } + else if (req == WR_CHECKAMMO1) + { + ammo_amount = self.ammo_cells >= autocvar_g_balance_hlac_primary_ammo; + ammo_amount += self.(weapon_load[WEP_HLAC]) >= autocvar_g_balance_hlac_primary_ammo; + return ammo_amount; + } + else if (req == WR_CHECKAMMO2) + { + ammo_amount = self.ammo_cells >= autocvar_g_balance_hlac_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_HLAC]) >= autocvar_g_balance_hlac_secondary_ammo; + return ammo_amount; + } + else if (req == WR_RELOAD) + { + W_Reload(min(autocvar_g_balance_hlac_primary_ammo, autocvar_g_balance_hlac_secondary_ammo), autocvar_g_balance_hlac_reload_ammo, autocvar_g_balance_hlac_reload_time, "weapons/reload.wav"); + } + else if (req == WR_SUICIDEMESSAGE) + { + return WEAPON_HLAC_SUICIDE; + } + else if (req == WR_KILLMESSAGE) + { + return WEAPON_HLAC_MURDER; + } + return TRUE; +} +#endif +#ifdef CSQC +float w_hlac(float req) +{ + if(req == WR_IMPACTEFFECT) + { + vector org2; + org2 = w_org + w_backoff * 6; + pointparticles(particleeffectnum("laser_impact"), org2, w_backoff * 1000, 1); + if(!w_issilent) + sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTEN_NORM); + } + else if(req == WR_PRECACHE) + { + precache_sound("weapons/laserimpact.wav"); + } + return TRUE; +} +#endif +#endif diff --git a/qcsrc/server/w_hook.qc b/qcsrc/server/w_hook.qc new file mode 100644 index 000000000..f0310c702 --- /dev/null +++ b/qcsrc/server/w_hook.qc @@ -0,0 +1,307 @@ +#ifdef REGISTER_WEAPON +REGISTER_WEAPON( +/* WEP_##id */ HOOK, +/* function */ w_hook, +/* ammotype */ IT_CELLS|IT_FUEL, +/* impulse */ 0, +/* flags */ WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, +/* rating */ 0, +/* model */ "hookgun", +/* shortname */ "hook", +/* fullname */ _("Grappling Hook") +); +#else +#ifdef SVQC +.float dmg; +.float dmg_edge; +.float dmg_radius; +.float dmg_force; +.float dmg_power; +.float dmg_duration; +.float dmg_last; +.float hook_refire; +.float hook_time_hooked; +.float hook_time_fueldecrease; + +void W_Hook_ExplodeThink (void) +{ + float dt, dmg_remaining_next, f; + + dt = time - self.teleport_time; + dmg_remaining_next = pow(bound(0, 1 - dt / self.dmg_duration, 1), self.dmg_power); + + f = self.dmg_last - dmg_remaining_next; + self.dmg_last = dmg_remaining_next; + + RadiusDamage (self, self.realowner, self.dmg * f, self.dmg_edge * f, self.dmg_radius, self.realowner, self.dmg_force * f, self.projectiledeathtype, world); + self.projectiledeathtype |= HITTYPE_BOUNCE; + //RadiusDamage (self, world, self.dmg * f, self.dmg_edge * f, self.dmg_radius, world, self.dmg_force * f, self.projectiledeathtype, world); + + if(dt < self.dmg_duration) + self.nextthink = time + 0.05; // soon + else + remove(self); +} + +void W_Hook_Explode2 (void) +{ + self.event_damage = func_null; + self.touch = func_null; + self.effects |= EF_NODRAW; + + self.think = W_Hook_ExplodeThink; + self.nextthink = time; + self.dmg = autocvar_g_balance_hook_secondary_damage; + self.dmg_edge = autocvar_g_balance_hook_secondary_edgedamage; + self.dmg_radius = autocvar_g_balance_hook_secondary_radius; + self.dmg_force = autocvar_g_balance_hook_secondary_force; + self.dmg_power = autocvar_g_balance_hook_secondary_power; + self.dmg_duration = autocvar_g_balance_hook_secondary_duration; + self.teleport_time = time; + self.dmg_last = 1; + self.movetype = MOVETYPE_NONE; +} + +void W_Hook_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) +{ + if (self.health <= 0) + return; + + if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions + return; // g_projectiles_damage says to halt + + self.health = self.health - damage; + + if (self.health <= 0) + W_PrepareExplosionByDamage(self.realowner, W_Hook_Explode2); +} + +void W_Hook_Touch2 (void) +{ + PROJECTILE_TOUCH; + self.use(); +} + +void W_Hook_Attack2() +{ + entity gren; + + W_DecreaseAmmo(ammo_cells, autocvar_g_balance_hook_secondary_ammo, FALSE); + W_SetupShot (self, FALSE, 4, "weapons/hookbomb_fire.wav", CH_WEAPON_A, autocvar_g_balance_hook_secondary_damage); + + gren = spawn (); + gren.owner = gren.realowner = self; + gren.classname = "hookbomb"; + gren.bot_dodge = TRUE; + gren.bot_dodgerating = autocvar_g_balance_hook_secondary_damage; + gren.movetype = MOVETYPE_TOSS; + PROJECTILE_MAKETRIGGER(gren); + gren.projectiledeathtype = WEP_HOOK | HITTYPE_SECONDARY; + setorigin(gren, w_shotorg); + setsize(gren, '0 0 0', '0 0 0'); + + gren.nextthink = time + autocvar_g_balance_hook_secondary_lifetime; + gren.think = adaptor_think2use_hittype_splash; + gren.use = W_Hook_Explode2; + gren.touch = W_Hook_Touch2; + + gren.takedamage = DAMAGE_YES; + gren.health = autocvar_g_balance_hook_secondary_health; + gren.damageforcescale = autocvar_g_balance_hook_secondary_damageforcescale; + gren.event_damage = W_Hook_Damage; + gren.damagedbycontents = TRUE; + gren.missile_flags = MIF_SPLASH | MIF_ARC; + + gren.velocity = '0 0 1' * autocvar_g_balance_hook_secondary_speed; + if(autocvar_g_projectiles_newton_style) + gren.velocity = gren.velocity + self.velocity; + + gren.gravity = autocvar_g_balance_hook_secondary_gravity; + //W_SetupProjectileVelocity(gren); // just falling down! + + gren.angles = '0 0 0'; + gren.flags = FL_PROJECTILE; + + CSQCProjectile(gren, TRUE, PROJECTILE_HOOKBOMB, TRUE); + + other = gren; MUTATOR_CALLHOOK(EditProjectile); +} + +void spawnfunc_weapon_hook (void) +{ + if(g_grappling_hook) // offhand hook + { + startitem_failed = TRUE; + remove(self); + return; + } + weapon_defaultspawnfunc(WEP_HOOK); +} + +float w_hook(float req) +{ + float hooked_time_max, hooked_fuel; + + if (req == WR_AIM) + { + // ... sorry ... + } + else if (req == WR_THINK) + { + if (self.BUTTON_ATCK || (!(self.items & IT_JETPACK) && self.BUTTON_HOOK)) + { + if(!self.hook) + if (!(self.hook_state & HOOK_WAITING_FOR_RELEASE)) + if (!(self.hook_state & HOOK_FIRING)) + if (time > self.hook_refire) + if (weapon_prepareattack(0, -1)) + { + W_DecreaseAmmo(ammo_fuel, autocvar_g_balance_hook_primary_fuel, FALSE); + self.hook_state |= HOOK_FIRING; + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hook_primary_animtime, w_ready); + } + } + + if (self.BUTTON_ATCK2) + { + if (weapon_prepareattack(1, autocvar_g_balance_hook_secondary_refire)) + { + W_Hook_Attack2(); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_hook_secondary_animtime, w_ready); + } + } + + if(self.hook) + { + // if hooked, no bombs, and increase the timer + self.hook_refire = max(self.hook_refire, time + autocvar_g_balance_hook_primary_refire * W_WeaponRateFactor()); + + // hook also inhibits health regeneration, but only for 1 second + if (!(self.items & IT_UNLIMITED_WEAPON_AMMO)) + self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen); + } + + if(self.hook && self.hook.state == 1) + { + hooked_time_max = autocvar_g_balance_hook_primary_hooked_time_max; + if (hooked_time_max > 0) + { + if ( time > self.hook_time_hooked + hooked_time_max ) + self.hook_state |= HOOK_REMOVING; + } + + hooked_fuel = autocvar_g_balance_hook_primary_hooked_fuel; + if (hooked_fuel > 0) + { + if ( time > self.hook_time_fueldecrease ) + { + if (!(self.items & IT_UNLIMITED_WEAPON_AMMO)) + { + if ( self.ammo_fuel >= (time - self.hook_time_fueldecrease) * hooked_fuel ) + { + W_DecreaseAmmo(ammo_fuel, (time - self.hook_time_fueldecrease) * hooked_fuel, FALSE); + self.hook_time_fueldecrease = time; + // decrease next frame again + } + else + { + self.ammo_fuel = 0; + self.hook_state |= HOOK_REMOVING; + W_SwitchWeapon_Force(self, w_getbestweapon(self)); + } + } + } + } + } + else + { + self.hook_time_hooked = time; + self.hook_time_fueldecrease = time + autocvar_g_balance_hook_primary_hooked_time_free; + } + + if (self.BUTTON_CROUCH) + { + self.hook_state &= ~HOOK_PULLING; + if (self.BUTTON_ATCK || (!(self.items & IT_JETPACK) && self.BUTTON_HOOK)) + self.hook_state &= ~HOOK_RELEASING; + else + self.hook_state |= HOOK_RELEASING; + } + else + { + self.hook_state |= HOOK_PULLING; + self.hook_state &= ~HOOK_RELEASING; + + if (self.BUTTON_ATCK || (!(self.items & IT_JETPACK) && self.BUTTON_HOOK)) + { + // already fired + if(self.hook) + self.hook_state |= HOOK_WAITING_FOR_RELEASE; + } + else + { + self.hook_state |= HOOK_REMOVING; + self.hook_state &= ~HOOK_WAITING_FOR_RELEASE; + } + } + } + else if (req == WR_PRECACHE) + { + precache_model ("models/weapons/g_hookgun.md3"); + precache_model ("models/weapons/v_hookgun.md3"); + precache_model ("models/weapons/h_hookgun.iqm"); + precache_sound ("weapons/hook_impact.wav"); // done by g_hook.qc + precache_sound ("weapons/hook_fire.wav"); + precache_sound ("weapons/hookbomb_fire.wav"); + } + else if (req == WR_SETUP) + { + weapon_setup(WEP_HOOK); + self.current_ammo = ammo_fuel; + self.hook_state &= ~HOOK_WAITING_FOR_RELEASE; + } + else if (req == WR_CHECKAMMO1) + { + if(self.hook) + return self.ammo_fuel > 0; + else + return self.ammo_fuel >= autocvar_g_balance_hook_primary_fuel; + } + else if (req == WR_CHECKAMMO2) + { + return self.ammo_cells >= autocvar_g_balance_hook_secondary_ammo; + } + else if (req == WR_RESETPLAYER) + { + self.hook_refire = time; + } + else if (req == WR_SUICIDEMESSAGE) + { + return FALSE; + } + else if (req == WR_KILLMESSAGE) + { + return WEAPON_HOOK_MURDER; + } + return TRUE; +} +#endif +#ifdef CSQC +float w_hook(float req) +{ + if(req == WR_IMPACTEFFECT) + { + vector org2; + org2 = w_org + w_backoff * 2; + pointparticles(particleeffectnum("hookbomb_explode"), org2, '0 0 0', 1); + if(!w_issilent) + sound(self, CH_SHOTS, "weapons/hookbomb_impact.wav", VOL_BASE, ATTEN_NORM); + } + else if(req == WR_PRECACHE) + { + precache_sound("weapons/hookbomb_impact.wav"); + } + return TRUE; +} +#endif +#endif diff --git a/qcsrc/server/w_laser.qc b/qcsrc/server/w_laser.qc new file mode 100644 index 000000000..0a0704638 --- /dev/null +++ b/qcsrc/server/w_laser.qc @@ -0,0 +1,322 @@ +#ifdef REGISTER_WEAPON +REGISTER_WEAPON( +/* WEP_##id */ LASER, +/* function */ w_laser, +/* ammotype */ 0, +/* impulse */ 1, +/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, +/* rating */ 0, +/* model */ "laser", +/* shortname */ "laser", +/* fullname */ _("Laser") +); +#else +#ifdef SVQC +void(float imp) W_SwitchWeapon; +void() W_LastWeapon; + +void W_Laser_Touch (void) +{ + PROJECTILE_TOUCH; + + self.event_damage = func_null; + if (self.dmg) + RadiusDamage (self, self.realowner, autocvar_g_balance_laser_secondary_damage, autocvar_g_balance_laser_secondary_edgedamage, autocvar_g_balance_laser_secondary_radius, world, autocvar_g_balance_laser_secondary_force, self.projectiledeathtype, other); + else + RadiusDamage (self, self.realowner, autocvar_g_balance_laser_primary_damage, autocvar_g_balance_laser_primary_edgedamage, autocvar_g_balance_laser_primary_radius, world, autocvar_g_balance_laser_primary_force, self.projectiledeathtype, other); + + remove (self); +} + +void W_Laser_Think() +{ + self.movetype = MOVETYPE_FLY; + self.think = SUB_Remove; + if (self.dmg) + self.nextthink = time + autocvar_g_balance_laser_secondary_lifetime; + else + self.nextthink = time + autocvar_g_balance_laser_primary_lifetime; + CSQCProjectile(self, TRUE, PROJECTILE_LASER, TRUE); +} + +void W_Laser_Attack (float issecondary) +{ + entity missile; + vector s_forward; + float a; + + a = autocvar_g_balance_laser_primary_shotangle; + s_forward = v_forward * cos(a * DEG2RAD) + v_up * sin(a * DEG2RAD); + + if(issecondary == 1) + W_SetupShot_Dir (self, s_forward, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_B, autocvar_g_balance_laser_secondary_damage); + else + W_SetupShot_Dir (self, s_forward, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_B, autocvar_g_balance_laser_primary_damage); + pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); + + missile = spawn (); + missile.owner = missile.realowner = self; + missile.classname = "laserbolt"; + missile.dmg = 0; + missile.bot_dodge = TRUE; + missile.bot_dodgerating = autocvar_g_balance_laser_primary_damage; + + PROJECTILE_MAKETRIGGER(missile); + missile.projectiledeathtype = WEP_LASER; + + setorigin (missile, w_shotorg); + setsize(missile, '0 0 0', '0 0 0'); + + W_SETUPPROJECTILEVELOCITY(missile, g_balance_laser_primary); + missile.angles = vectoangles (missile.velocity); + //missile.glow_color = 250; // 244, 250 + //missile.glow_size = 120; + missile.touch = W_Laser_Touch; + + missile.flags = FL_PROJECTILE; + missile.missile_flags = MIF_SPLASH; + + missile.think = W_Laser_Think; + missile.nextthink = time + autocvar_g_balance_laser_primary_delay; + + other = missile; MUTATOR_CALLHOOK(EditProjectile); + + if(time >= missile.nextthink) + { + entity oldself; + oldself = self; + self = missile; + self.think(); + self = oldself; + } +} + +.vector hook_start, hook_end; +float gauntletbeam_send(entity to, float sf) +{ + WriteByte(MSG_ENTITY, ENT_CLIENT_GAUNTLET); + sf = sf & 0x7F; + if(sound_allowed(MSG_BROADCAST, self.realowner)) + sf |= 0x80; + WriteByte(MSG_ENTITY, sf); + if(sf & 1) + { + WriteByte(MSG_ENTITY, num_for_edict(self.realowner)); + } + if(sf & 2) + { + WriteCoord(MSG_ENTITY, self.hook_start_x); + WriteCoord(MSG_ENTITY, self.hook_start_y); + WriteCoord(MSG_ENTITY, self.hook_start_z); + } + if(sf & 4) + { + WriteCoord(MSG_ENTITY, self.hook_end_x); + WriteCoord(MSG_ENTITY, self.hook_end_y); + WriteCoord(MSG_ENTITY, self.hook_end_z); + } + return TRUE; +} +.entity gauntletbeam; +.float prevgauntletfire; +entity lgbeam_owner_ent; +void gauntletbeam_think() +{ + float damage, myforce, myradius; + damage = autocvar_g_balance_laser_secondary_damage; + myforce = autocvar_g_balance_laser_secondary_force; + myradius = autocvar_g_balance_laser_secondary_radius; + + self.realowner.prevgauntletfire = time; + if (self.realowner.weaponentity.state != WS_INUSE || self != self.realowner.gauntletbeam || self.realowner.deadflag != DEAD_NO || !self.realowner.BUTTON_ATCK2) + { + remove(self); + return; + } + + self.nextthink = time; + + makevectors(self.realowner.v_angle); + + float dt; + dt = frametime; + + W_SetupShot_Range(self.realowner, TRUE, 0, "", 0, damage * dt, myradius); + if(!lgbeam_owner_ent) + { + lgbeam_owner_ent = spawn(); + lgbeam_owner_ent.classname = "lgbeam_owner_ent"; + } + WarpZone_traceline_antilag(lgbeam_owner_ent, w_shotorg, w_shotend, MOVE_NORMAL, lgbeam_owner_ent, ANTILAG_LATENCY(self.owner)); + + // apply the damage + if(trace_ent) + { + vector force; + force = w_shotdir * myforce; + if(accuracy_isgooddamage(self.owner, trace_ent)) + accuracy_add(self.owner, WEP_LASER, 0, damage * dt); + Damage (trace_ent, self.owner, self.owner, damage * dt, WEP_LASER | HITTYPE_SECONDARY, trace_endpos, force * dt); + } + + // draw effect + if(w_shotorg != self.hook_start) + { + self.SendFlags |= 2; + self.hook_start = w_shotorg; + } + if(w_shotend != self.hook_end) + { + self.SendFlags |= 4; + self.hook_end = w_shotend; + } +} + +// experimental gauntlet +void W_Laser_Attack2 () +{ + // only play fire sound if 0.5 sec has passed since player let go the fire button + if(time - self.prevgauntletfire > 0.5) + { + sound (self, CH_WEAPON_A, "weapons/gauntlet_fire.wav", VOL_BASE, ATTEN_NORM); + } + + entity beam, oldself; + + self.gauntletbeam = beam = spawn(); + beam.solid = SOLID_NOT; + beam.think = gauntletbeam_think; + beam.owner = self; + beam.movetype = MOVETYPE_NONE; + beam.shot_spread = 0; + beam.bot_dodge = TRUE; + beam.bot_dodgerating = autocvar_g_balance_laser_primary_damage; + Net_LinkEntity(beam, FALSE, 0, gauntletbeam_send); + + oldself = self; + self = beam; + self.think(); + self = oldself; +} + +void LaserInit() +{ + weapon_action(WEP_LASER, WR_PRECACHE); + gauntlet_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_LASER), FALSE, FALSE, 1); + gauntlet_shotorigin[1] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_LASER), FALSE, FALSE, 2); + gauntlet_shotorigin[2] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_LASER), FALSE, FALSE, 3); + gauntlet_shotorigin[3] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_LASER), FALSE, FALSE, 4); +} + +void spawnfunc_weapon_laser (void) +{ + weapon_defaultspawnfunc(WEP_LASER); +} + +float w_laser(float req) +{ + float r1; + float r2; + if (req == WR_AIM) + { + if(autocvar_g_balance_laser_secondary) + { + r1 = autocvar_g_balance_laser_primary_damage; + r2 = autocvar_g_balance_laser_secondary_damage; + if (random() * (r2 + r1) > r1) + self.BUTTON_ATCK2 = bot_aim(autocvar_g_balance_laser_secondary_speed, 0, autocvar_g_balance_laser_secondary_lifetime, FALSE); + else + self.BUTTON_ATCK = bot_aim(autocvar_g_balance_laser_primary_speed, 0, autocvar_g_balance_laser_primary_lifetime, FALSE); + } + else + self.BUTTON_ATCK = bot_aim(autocvar_g_balance_laser_primary_speed, 0, autocvar_g_balance_laser_primary_lifetime, FALSE); + } + else if (req == WR_THINK) + { + if(autocvar_g_balance_laser_reload_ammo && self.clip_load < 1) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else if (self.BUTTON_ATCK) + { + if (weapon_prepareattack(0, autocvar_g_balance_laser_primary_refire)) + { + W_DecreaseAmmo(ammo_none, 1, TRUE); + + W_Laser_Attack(0); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_laser_primary_animtime, w_ready); + } + } + else if (self.BUTTON_ATCK2) + { + if(autocvar_g_balance_laser_secondary) + { + W_DecreaseAmmo(ammo_none, 1, TRUE); + + if (weapon_prepareattack(0, 0)) + { + W_Laser_Attack2(); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_laser_secondary_animtime, w_ready); + } + } + else + { + if(self.switchweapon == WEP_LASER) // don't do this if already switching + W_LastWeapon(); + } + } + } + else if (req == WR_PRECACHE) + { + precache_model ("models/weapons/g_laser.md3"); + precache_model ("models/weapons/v_laser.md3"); + precache_model ("models/weapons/h_laser.iqm"); + precache_sound ("weapons/lasergun_fire.wav"); + precache_sound ("weapons/gauntlet_fire.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else + } + else if (req == WR_SETUP) + { + weapon_setup(WEP_LASER); + self.current_ammo = ammo_none; + } + else if (req == WR_CHECKAMMO1) + { + return TRUE; + } + else if (req == WR_CHECKAMMO2) + { + return TRUE; + } + else if (req == WR_RELOAD) + { + W_Reload(0, autocvar_g_balance_laser_reload_ammo, autocvar_g_balance_laser_reload_time, "weapons/reload.wav"); + } + else if (req == WR_SUICIDEMESSAGE) + { + return WEAPON_LASER_SUICIDE; + } + else if (req == WR_KILLMESSAGE) + { + return WEAPON_LASER_MURDER; + } + return TRUE; +} +#endif +#ifdef CSQC +float w_laser(float req) +{ + if(req == WR_IMPACTEFFECT) + { + vector org2; + org2 = w_org + w_backoff * 6; + pointparticles(particleeffectnum("laser_impact"), org2, w_backoff * 1000, 1); + if(!w_issilent) + sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTEN_NORM); + } + else if(req == WR_PRECACHE) + { + precache_sound("weapons/laserimpact.wav"); + } + return TRUE; +} +#endif +#endif diff --git a/qcsrc/server/w_laser.qh b/qcsrc/server/w_laser.qh new file mode 100644 index 000000000..0f2c13703 --- /dev/null +++ b/qcsrc/server/w_laser.qh @@ -0,0 +1,2 @@ +void LaserInit(); +vector gauntlet_shotorigin[4]; diff --git a/qcsrc/server/w_minstanex.qc b/qcsrc/server/w_minstanex.qc new file mode 100644 index 000000000..9fb80c6d5 --- /dev/null +++ b/qcsrc/server/w_minstanex.qc @@ -0,0 +1,213 @@ +#ifdef REGISTER_WEAPON +REGISTER_WEAPON( +/* WEP_##id */ MINSTANEX, +/* function */ w_minstanex, +/* ammotype */ IT_CELLS, +/* impulse */ 7, +/* flags */ WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_FLAG_SUPERWEAPON | WEP_TYPE_HITSCAN, +/* rating */ BOT_PICKUP_RATING_HIGH, +/* model */ "minstanex", +/* shortname */ "minstanex", +/* fullname */ _("MinstaNex") +); +#else +#ifdef SVQC +.float minstanex_lasthit; +.float jump_interval; + +void W_MinstaNex_Attack (void) +{ + float flying; + flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last + + W_SetupShot (self, TRUE, 0, "weapons/minstanexfire.wav", CH_WEAPON_A, 10000); + + yoda = 0; + damage_goodhits = 0; + FireRailgunBullet (w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, 10000, 800, 0, 0, 0, 0, WEP_MINSTANEX); + + if(yoda && flying) + Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA); + if(damage_goodhits && self.minstanex_lasthit) + { + Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_ACHIEVEMENT_IMPRESSIVE); + damage_goodhits = 0; // only every second time + } + + self.minstanex_lasthit = damage_goodhits; + + pointparticles(particleeffectnum("nex_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); + + // teamcolor / hit beam effect + vector v; + v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos); + switch(self.team) + { + case NUM_TEAM_1: // Red + if(damage_goodhits) + WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED_HIT"), w_shotorg, v); + else + WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED"), w_shotorg, v); + break; + case NUM_TEAM_2: // Blue + if(damage_goodhits) + WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE_HIT"), w_shotorg, v); + else + WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE"), w_shotorg, v); + break; + case NUM_TEAM_3: // Yellow + if(damage_goodhits) + WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW_HIT"), w_shotorg, v); + else + WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW"), w_shotorg, v); + break; + case NUM_TEAM_4: // Pink + if(damage_goodhits) + WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK_HIT"), w_shotorg, v); + else + WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK"), w_shotorg, v); + break; + default: + if(damage_goodhits) + WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3_HIT"), w_shotorg, v); + else + WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3"), w_shotorg, v); + break; + } + + W_DecreaseAmmo(ammo_cells, ((g_minstagib) ? 1 : autocvar_g_balance_minstanex_ammo), autocvar_g_balance_minstanex_reload_ammo); +} + +void spawnfunc_weapon_minstanex (void); // defined in t_items.qc + +float w_minstanex(float req) +{ + float ammo_amount; + float minstanex_ammo; + + // now multiple WR_s use this + minstanex_ammo = ((g_minstagib) ? 1 : autocvar_g_balance_minstanex_ammo); + + if (req == WR_AIM) + { + if(self.ammo_cells > 0) + self.BUTTON_ATCK = bot_aim(1000000, 0, 1, FALSE); + else + self.BUTTON_ATCK2 = bot_aim(autocvar_g_balance_laser_primary_speed, 0, autocvar_g_balance_laser_primary_lifetime, FALSE); + } + else if (req == WR_THINK) + { + // if the laser uses load, we also consider its ammo for reloading + if(autocvar_g_balance_minstanex_reload_ammo && autocvar_g_balance_minstanex_laser_ammo && self.clip_load < min(minstanex_ammo, autocvar_g_balance_minstanex_laser_ammo)) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else if(autocvar_g_balance_minstanex_reload_ammo && self.clip_load < minstanex_ammo) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else if (self.BUTTON_ATCK) + { + if (weapon_prepareattack(0, autocvar_g_balance_minstanex_refire)) + { + W_MinstaNex_Attack(); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_minstanex_animtime, w_ready); + } + } + else if (self.BUTTON_ATCK2) + { + if (self.jump_interval <= time) + if (weapon_prepareattack(1, -1)) + { + // handle refire manually, so that primary and secondary can be fired without conflictions (important for minstagib) + self.jump_interval = time + autocvar_g_balance_minstanex_laser_refire * W_WeaponRateFactor(); + + // decrease ammo for the laser? + if(autocvar_g_balance_minstanex_laser_ammo) + W_DecreaseAmmo(ammo_cells, autocvar_g_balance_minstanex_laser_ammo, autocvar_g_balance_minstanex_reload_ammo); + + // ugly minstagib hack to reuse the fire mode of the laser + float w; + w = self.weapon; + self.weapon = WEP_LASER; + W_Laser_Attack(2); + self.weapon = w; + + // now do normal refire + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_minstanex_laser_animtime, w_ready); + } + } + } + else if (req == WR_PRECACHE) + { + precache_model ("models/nexflash.md3"); + precache_model ("models/weapons/g_minstanex.md3"); + precache_model ("models/weapons/v_minstanex.md3"); + precache_model ("models/weapons/h_minstanex.iqm"); + precache_sound ("weapons/minstanexfire.wav"); + precache_sound ("weapons/nexwhoosh1.wav"); + precache_sound ("weapons/nexwhoosh2.wav"); + precache_sound ("weapons/nexwhoosh3.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else + w_laser(WR_PRECACHE); + } + else if (req == WR_SETUP) + { + weapon_setup(WEP_MINSTANEX); + self.current_ammo = ammo_cells; + self.minstanex_lasthit = 0; + } + else if (req == WR_CHECKAMMO1) + { + ammo_amount = self.ammo_cells >= minstanex_ammo; + ammo_amount += self.(weapon_load[WEP_MINSTANEX]) >= minstanex_ammo; + return ammo_amount; + } + else if (req == WR_CHECKAMMO2) + { + if(!autocvar_g_balance_minstanex_laser_ammo) + return TRUE; + ammo_amount = self.ammo_cells >= autocvar_g_balance_minstanex_laser_ammo; + ammo_amount += self.(weapon_load[WEP_MINSTANEX]) >= autocvar_g_balance_minstanex_laser_ammo; + return ammo_amount; + } + else if (req == WR_RESETPLAYER) + { + self.minstanex_lasthit = 0; + } + else if (req == WR_RELOAD) + { + float used_ammo; + if(autocvar_g_balance_minstanex_laser_ammo) + used_ammo = min(minstanex_ammo, autocvar_g_balance_minstanex_laser_ammo); + else + used_ammo = minstanex_ammo; + + W_Reload(used_ammo, autocvar_g_balance_minstanex_reload_ammo, autocvar_g_balance_minstanex_reload_time, "weapons/reload.wav"); + } + else if (req == WR_SUICIDEMESSAGE) + { + return WEAPON_THINKING_WITH_PORTALS; + } + else if (req == WR_KILLMESSAGE) + { + return WEAPON_MINSTANEX_MURDER; + } + return TRUE; +} +#endif +#ifdef CSQC +float w_minstanex(float req) +{ + if(req == WR_IMPACTEFFECT) + { + vector org2; + org2 = w_org + w_backoff * 6; + pointparticles(particleeffectnum("nex_impact"), org2, '0 0 0', 1); + if(!w_issilent) + sound(self, CH_SHOTS, "weapons/neximpact.wav", VOL_BASE, ATTEN_NORM); + } + else if(req == WR_PRECACHE) + { + precache_sound("weapons/neximpact.wav"); + } + return TRUE; +} +#endif +#endif diff --git a/qcsrc/server/w_nex.qc b/qcsrc/server/w_nex.qc new file mode 100644 index 000000000..919e27e5a --- /dev/null +++ b/qcsrc/server/w_nex.qc @@ -0,0 +1,275 @@ +#ifdef REGISTER_WEAPON +REGISTER_WEAPON( +/* WEP_##id */ NEX, +/* function */ w_nex, +/* ammotype */ IT_CELLS, +/* impulse */ 7, +/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN, +/* rating */ BOT_PICKUP_RATING_HIGH, +/* model */ "nex", +/* shortname */ "nex", +/* fullname */ _("Nex") +); +#else +#ifdef SVQC + +void SendCSQCNexBeamParticle(float charge) { + vector v; + v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos); + WriteByte(MSG_BROADCAST, SVC_TEMPENTITY); + WriteByte(MSG_BROADCAST, TE_CSQC_NEXGUNBEAMPARTICLE); + WriteCoord(MSG_BROADCAST, w_shotorg_x); + WriteCoord(MSG_BROADCAST, w_shotorg_y); + WriteCoord(MSG_BROADCAST, w_shotorg_z); + WriteCoord(MSG_BROADCAST, v_x); + WriteCoord(MSG_BROADCAST, v_y); + WriteCoord(MSG_BROADCAST, v_z); + WriteByte(MSG_BROADCAST, bound(0, 255 * charge, 255)); +} + +void W_Nex_Attack (float issecondary) +{ + float mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, myammo, charge; + if(issecondary) + { + mydmg = autocvar_g_balance_nex_secondary_damage; + myforce = autocvar_g_balance_nex_secondary_force; + mymindist = autocvar_g_balance_nex_secondary_damagefalloff_mindist; + mymaxdist = autocvar_g_balance_nex_secondary_damagefalloff_maxdist; + myhalflife = autocvar_g_balance_nex_secondary_damagefalloff_halflife; + myforcehalflife = autocvar_g_balance_nex_secondary_damagefalloff_forcehalflife; + myammo = autocvar_g_balance_nex_secondary_ammo; + } + else + { + mydmg = autocvar_g_balance_nex_primary_damage; + myforce = autocvar_g_balance_nex_primary_force; + mymindist = autocvar_g_balance_nex_primary_damagefalloff_mindist; + mymaxdist = autocvar_g_balance_nex_primary_damagefalloff_maxdist; + myhalflife = autocvar_g_balance_nex_primary_damagefalloff_halflife; + myforcehalflife = autocvar_g_balance_nex_primary_damagefalloff_forcehalflife; + myammo = autocvar_g_balance_nex_primary_ammo; + } + + float flying; + flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last + + if(autocvar_g_balance_nex_charge) + { + charge = autocvar_g_balance_nex_charge_mindmg / mydmg + (1 - autocvar_g_balance_nex_charge_mindmg / mydmg) * self.nex_charge; + self.nex_charge *= autocvar_g_balance_nex_charge_shot_multiplier; // do this AFTER setting mydmg/myforce + // O RLY? -- divVerent + // YA RLY -- FruitieX + } + else + charge = 1; + mydmg *= charge; + myforce *= charge; + + W_SetupShot (self, TRUE, 5, "weapons/nexfire.wav", CH_WEAPON_A, mydmg); + if(charge > autocvar_g_balance_nex_charge_animlimit && autocvar_g_balance_nex_charge_animlimit) // if the Nex is overcharged, we play an extra sound + { + sound (self, CH_WEAPON_B, "weapons/nexcharge.wav", VOL_BASE * (charge - 0.5 * autocvar_g_balance_nex_charge_animlimit) / (1 - 0.5 * autocvar_g_balance_nex_charge_animlimit), ATTEN_NORM); + } + + yoda = 0; + FireRailgunBullet (w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, WEP_NEX); + + if(yoda && flying) + Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA); + + //beam and muzzle flash done on client + SendCSQCNexBeamParticle(charge); + + W_DecreaseAmmo(ammo_cells, myammo, autocvar_g_balance_nex_reload_ammo); +} + +void spawnfunc_weapon_nex (void); // defined in t_items.qc + +.float nex_chargepool_pauseregen_finished; +float w_nex(float req) +{ + float dt; + float ammo_amount; + if (req == WR_AIM) + { + if(bot_aim(1000000, 0, 1, FALSE)) + self.BUTTON_ATCK = TRUE; + else + { + if(autocvar_g_balance_nex_charge) + self.BUTTON_ATCK2 = TRUE; + } + } + else if (req == WR_THINK) + { + if(autocvar_g_balance_nex_charge && self.nex_charge < autocvar_g_balance_nex_charge_limit) + self.nex_charge = min(1, self.nex_charge + autocvar_g_balance_nex_charge_rate * frametime / W_TICSPERFRAME); + + if(autocvar_g_balance_nex_secondary_chargepool) + if(self.nex_chargepool_ammo < 1) + { + if(self.nex_chargepool_pauseregen_finished < time) + self.nex_chargepool_ammo = min(1, self.nex_chargepool_ammo + autocvar_g_balance_nex_secondary_chargepool_regen * frametime / W_TICSPERFRAME); + self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_nex_secondary_chargepool_pause_health_regen); + } + + if(autocvar_g_balance_nex_reload_ammo && self.clip_load < min(autocvar_g_balance_nex_primary_ammo, autocvar_g_balance_nex_secondary_ammo)) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else + { + if (self.BUTTON_ATCK) + { + if (weapon_prepareattack(0, autocvar_g_balance_nex_primary_refire)) + { + W_Nex_Attack(0); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nex_primary_animtime, w_ready); + } + } + if ((autocvar_g_balance_nex_secondary_charge && !autocvar_g_balance_nex_secondary) ? (self.BUTTON_ZOOM | self.BUTTON_ZOOMSCRIPT) : self.BUTTON_ATCK2) + { + if(autocvar_g_balance_nex_secondary_charge) + { + self.nex_charge_rottime = time + autocvar_g_balance_nex_charge_rot_pause; + dt = frametime / W_TICSPERFRAME; + + if(self.nex_charge < 1) + { + if(autocvar_g_balance_nex_secondary_chargepool) + { + if(autocvar_g_balance_nex_secondary_ammo) + { + // always deplete if secondary is held + self.nex_chargepool_ammo = max(0, self.nex_chargepool_ammo - autocvar_g_balance_nex_secondary_ammo * dt); + + dt = min(dt, (1 - self.nex_charge) / autocvar_g_balance_nex_secondary_charge_rate); + self.nex_chargepool_pauseregen_finished = time + autocvar_g_balance_nex_secondary_chargepool_pause_regen; + dt = min(dt, self.nex_chargepool_ammo); + dt = max(0, dt); + + self.nex_charge += dt * autocvar_g_balance_nex_secondary_charge_rate; + } + } + + else if(autocvar_g_balance_nex_secondary_ammo) + { + if(self.BUTTON_ATCK2) // only eat ammo when the button is pressed + { + dt = min(dt, (1 - self.nex_charge) / autocvar_g_balance_nex_secondary_charge_rate); + if (!(self.items & IT_UNLIMITED_WEAPON_AMMO)) + { + // if this weapon is reloadable, decrease its load. Else decrease the player's ammo + if(autocvar_g_balance_nex_reload_ammo) + { + dt = min(dt, (self.clip_load - autocvar_g_balance_nex_primary_ammo) / autocvar_g_balance_nex_secondary_ammo); + dt = max(0, dt); + if(dt > 0) + { + self.clip_load = max(autocvar_g_balance_nex_secondary_ammo, self.clip_load - autocvar_g_balance_nex_secondary_ammo * dt); + } + self.(weapon_load[WEP_NEX]) = self.clip_load; + } + else + { + dt = min(dt, (self.ammo_cells - autocvar_g_balance_nex_primary_ammo) / autocvar_g_balance_nex_secondary_ammo); + dt = max(0, dt); + if(dt > 0) + { + self.ammo_cells = max(autocvar_g_balance_nex_secondary_ammo, self.ammo_cells - autocvar_g_balance_nex_secondary_ammo * dt); + } + } + } + self.nex_charge += dt * autocvar_g_balance_nex_secondary_charge_rate; + } + } + + else + { + dt = min(dt, (1 - self.nex_charge) / autocvar_g_balance_nex_secondary_charge_rate); + self.nex_charge += dt * autocvar_g_balance_nex_secondary_charge_rate; + } + } + } + else if(autocvar_g_balance_nex_secondary) + { + if (weapon_prepareattack(0, autocvar_g_balance_nex_secondary_refire)) + { + W_Nex_Attack(1); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nex_secondary_animtime, w_ready); + } + } + } + } + } + else if (req == WR_PRECACHE) + { + precache_model ("models/nexflash.md3"); + precache_model ("models/weapons/g_nex.md3"); + precache_model ("models/weapons/v_nex.md3"); + precache_model ("models/weapons/h_nex.iqm"); + precache_sound ("weapons/nexfire.wav"); + precache_sound ("weapons/nexcharge.wav"); + precache_sound ("weapons/nexwhoosh1.wav"); + precache_sound ("weapons/nexwhoosh2.wav"); + precache_sound ("weapons/nexwhoosh3.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else + } + else if (req == WR_SETUP) + { + weapon_setup(WEP_NEX); + self.current_ammo = ammo_cells; + } + else if (req == WR_CHECKAMMO1) + { + ammo_amount = self.ammo_cells >= autocvar_g_balance_nex_primary_ammo; + ammo_amount += (autocvar_g_balance_nex_reload_ammo && self.(weapon_load[WEP_NEX]) >= autocvar_g_balance_nex_primary_ammo); + return ammo_amount; + } + else if (req == WR_CHECKAMMO2) + { + if(autocvar_g_balance_nex_secondary) + { + // don't allow charging if we don't have enough ammo + ammo_amount = self.ammo_cells >= autocvar_g_balance_nex_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_NEX]) >= autocvar_g_balance_nex_secondary_ammo; + return ammo_amount; + } + else + { + return FALSE; // zoom is not a fire mode + } + } + else if (req == WR_RELOAD) + { + W_Reload(min(autocvar_g_balance_nex_primary_ammo, autocvar_g_balance_nex_secondary_ammo), autocvar_g_balance_nex_reload_ammo, autocvar_g_balance_nex_reload_time, "weapons/reload.wav"); + } + else if (req == WR_SUICIDEMESSAGE) + { + return WEAPON_THINKING_WITH_PORTALS; + } + else if (req == WR_KILLMESSAGE) + { + return WEAPON_NEX_MURDER; + } + return TRUE; +} +#endif +#ifdef CSQC +float w_nex(float req) +{ + if(req == WR_IMPACTEFFECT) + { + vector org2; + org2 = w_org + w_backoff * 6; + pointparticles(particleeffectnum("nex_impact"), org2, '0 0 0', 1); + if(!w_issilent) + sound(self, CH_SHOTS, "weapons/neximpact.wav", VOL_BASE, ATTEN_NORM); + } + else if(req == WR_PRECACHE) + { + precache_sound("weapons/neximpact.wav"); + } + return TRUE; +} +#endif +#endif diff --git a/qcsrc/server/w_porto.qc b/qcsrc/server/w_porto.qc new file mode 100644 index 000000000..1eb0f4b0b --- /dev/null +++ b/qcsrc/server/w_porto.qc @@ -0,0 +1,391 @@ +#ifdef REGISTER_WEAPON +REGISTER_WEAPON( +/* WEP_##id */ PORTO, +/* function */ w_porto, +/* ammotype */ 0, +/* impulse */ 0, +/* flags */ WEP_TYPE_OTHER | WEP_FLAG_SUPERWEAPON, +/* rating */ 0, +/* model */ "porto" , +/* shortname */ "porto", +/* fullname */ _("Port-O-Launch") +); +#else +#ifdef SVQC +.entity porto_current; +.vector porto_v_angle; // holds "held" view angles +.float porto_v_angle_held; +.vector right_vector; + +void W_Porto_Success (void) +{ + if(self.realowner == world) + { + objerror("Cannot succeed successfully: no owner\n"); + return; + } + + self.realowner.porto_current = world; + remove(self); +} + +string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo); +void W_Porto_Fail (float failhard) +{ + if(self.realowner == world) + { + objerror("Cannot fail successfully: no owner\n"); + return; + } + + // no portals here! + if(self.cnt < 0) + { + Portal_ClearWithID(self.realowner, self.portal_id); + } + + self.realowner.porto_current = world; + + if(self.cnt < 0 && !failhard && self.realowner.playerid == self.playerid && self.realowner.deadflag == DEAD_NO && !(self.realowner.weapons & WEPSET_PORTO)) + { + setsize (self, '-16 -16 0', '16 16 32'); + setorigin(self, self.origin + trace_plane_normal); + if(move_out_of_solid(self)) + { + self.flags = FL_ITEM; + self.velocity = trigger_push_calculatevelocity(self.origin, self.realowner, 128); + tracetoss(self, self); + if(vlen(trace_endpos - self.realowner.origin) < 128) + { + W_ThrowNewWeapon(self.realowner, WEP_PORTO, 0, self.origin, self.velocity); + centerprint(self.realowner, "^1Portal deployment failed.\n\n^2Catch it to try again!"); + } + } + } + remove(self); +} + +void W_Porto_Remove (entity p) +{ + if(p.porto_current.realowner == p && p.porto_current.classname == "porto") + { + entity oldself; + oldself = self; + self = p.porto_current; + W_Porto_Fail(1); + self = oldself; + } +} + +void W_Porto_Think (void) +{ + trace_plane_normal = '0 0 0'; + if(self.realowner.playerid != self.playerid) + remove(self); + else + W_Porto_Fail(0); +} + +void W_Porto_Touch (void) +{ + vector norm; + + // do not use PROJECTILE_TOUCH here + // FIXME but DO handle warpzones! + + if(other.classname == "portal") + return; // handled by the portal + + norm = trace_plane_normal; + if(trace_ent.iscreature) + { + traceline(trace_ent.origin, trace_ent.origin + '0 0 2' * PL_MIN_z, MOVE_WORLDONLY, self); + if(trace_fraction >= 1) + return; + if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP) + return; + if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) + return; + } + + if(self.realowner.playerid != self.playerid) + { + sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM); + remove(self); + } + else if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP) + { + spamsound(self, CH_SHOTS, "porto/bounce.wav", VOL_BASE, ATTEN_NORM); + // just reflect + self.right_vector = self.right_vector - 2 * trace_plane_normal * (self.right_vector * trace_plane_normal); + self.angles = vectoangles(self.velocity - 2 * trace_plane_normal * (self.velocity * trace_plane_normal)); + } + else if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) + { + sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM); + W_Porto_Fail(0); + if(self.cnt < 0) + Portal_ClearAll_PortalsOnly(self.realowner); + } + else if(self.cnt == 0) + { + // in-portal only + if(Portal_SpawnInPortalAtTrace(self.realowner, self.right_vector, self.portal_id)) + { + sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM); + trace_plane_normal = norm; + centerprint(self.realowner, "^1In^7-portal created."); + W_Porto_Success(); + } + else + { + sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM); + trace_plane_normal = norm; + W_Porto_Fail(0); + } + } + else if(self.cnt == 1) + { + // out-portal only + if(Portal_SpawnOutPortalAtTrace(self.realowner, self.right_vector, self.portal_id)) + { + sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM); + trace_plane_normal = norm; + centerprint(self.realowner, "^4Out^7-portal created."); + W_Porto_Success(); + } + else + { + sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM); + trace_plane_normal = norm; + W_Porto_Fail(0); + } + } + else if(self.effects & EF_RED) + { + self.effects += EF_BLUE - EF_RED; + if(Portal_SpawnInPortalAtTrace(self.realowner, self.right_vector, self.portal_id)) + { + sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM); + trace_plane_normal = norm; + centerprint(self.realowner, "^1In^7-portal created."); + self.right_vector = self.right_vector - 2 * trace_plane_normal * (self.right_vector * norm); + self.angles = vectoangles(self.velocity - 2 * trace_plane_normal * (self.velocity * norm)); + CSQCProjectile(self, TRUE, PROJECTILE_PORTO_BLUE, TRUE); // change type + } + else + { + sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM); + trace_plane_normal = norm; + Portal_ClearAll_PortalsOnly(self.realowner); + W_Porto_Fail(0); + } + } + else + { + if(self.realowner.portal_in.portal_id == self.portal_id) + { + if(Portal_SpawnOutPortalAtTrace(self.realowner, self.right_vector, self.portal_id)) + { + sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM); + trace_plane_normal = norm; + centerprint(self.realowner, "^4Out^7-portal created."); + W_Porto_Success(); + } + else + { + sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM); + Portal_ClearAll_PortalsOnly(self.realowner); + W_Porto_Fail(0); + } + } + else + { + sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM); + Portal_ClearAll_PortalsOnly(self.realowner); + W_Porto_Fail(0); + } + } +} + +void W_Porto_Attack (float type) +{ + entity gren; + + W_SetupShot (self, FALSE, 4, "porto/fire.wav", CH_WEAPON_A, 0); + // always shoot from the eye + w_shotdir = v_forward; + w_shotorg = self.origin + self.view_ofs + ((w_shotorg - self.origin - self.view_ofs) * v_forward) * v_forward; + + //pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); + + gren = spawn (); + gren.cnt = type; + gren.owner = gren.realowner = self; + gren.playerid = self.playerid; + gren.classname = "porto"; + gren.bot_dodge = TRUE; + gren.bot_dodgerating = 200; + gren.movetype = MOVETYPE_BOUNCEMISSILE; + PROJECTILE_MAKETRIGGER(gren); + gren.effects = EF_RED; + gren.scale = 4; + setorigin(gren, w_shotorg); + setsize(gren, '0 0 0', '0 0 0'); + + if(type > 0) + gren.nextthink = time + autocvar_g_balance_porto_secondary_lifetime; + else + gren.nextthink = time + autocvar_g_balance_porto_primary_lifetime; + gren.think = W_Porto_Think; + gren.touch = W_Porto_Touch; + + if(type > 0) + { + if(self.items & IT_STRENGTH) + W_SetupProjectileVelocity(gren, autocvar_g_balance_porto_secondary_speed * autocvar_g_balance_powerup_strength_force, 0); + else + W_SetupProjectileVelocity(gren, autocvar_g_balance_porto_secondary_speed, 0); + } + else + { + if(self.items & IT_STRENGTH) + W_SetupProjectileVelocity(gren, autocvar_g_balance_porto_primary_speed * autocvar_g_balance_powerup_strength_force, 0); + else + W_SetupProjectileVelocity(gren, autocvar_g_balance_porto_primary_speed, 0); + } + + gren.angles = vectoangles (gren.velocity); + gren.flags = FL_PROJECTILE; + + gren.portal_id = time; + self.porto_current = gren; + gren.playerid = self.playerid; + fixedmakevectors(fixedvectoangles(gren.velocity)); + gren.right_vector = v_right; + + gren.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP; + + if(type > 0) + CSQCProjectile(gren, TRUE, PROJECTILE_PORTO_BLUE, TRUE); + else + CSQCProjectile(gren, TRUE, PROJECTILE_PORTO_RED, TRUE); + + other = gren; MUTATOR_CALLHOOK(EditProjectile); +} + +void spawnfunc_weapon_porto (void) +{ + weapon_defaultspawnfunc(WEP_PORTO); +} + +float w_nexball_weapon(float req); +float w_porto(float req) +{ + //vector v_angle_save; + + if (g_nexball) { return w_nexball_weapon(req); } + if (req == WR_AIM) + { + self.BUTTON_ATCK = FALSE; + self.BUTTON_ATCK2 = FALSE; + if(!autocvar_g_balance_porto_secondary) + if(bot_aim(autocvar_g_balance_porto_primary_speed, 0, autocvar_g_balance_grenadelauncher_primary_lifetime, FALSE)) + self.BUTTON_ATCK = TRUE; + } + else if (req == WR_THINK) + { + if(autocvar_g_balance_porto_secondary) + { + if (self.BUTTON_ATCK) + if (!self.porto_current) + if (!self.porto_forbidden) + if (weapon_prepareattack(0, autocvar_g_balance_porto_primary_refire)) + { + W_Porto_Attack(0); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_porto_primary_animtime, w_ready); + } + + if (self.BUTTON_ATCK2) + if (!self.porto_current) + if (!self.porto_forbidden) + if (weapon_prepareattack(1, autocvar_g_balance_porto_secondary_refire)) + { + W_Porto_Attack(1); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_porto_secondary_animtime, w_ready); + } + } + else + { + if(self.porto_v_angle_held) + { + if(!self.BUTTON_ATCK2) + { + self.porto_v_angle_held = 0; + + ClientData_Touch(self); + } + } + else + { + if(self.BUTTON_ATCK2) + { + self.porto_v_angle = self.v_angle; + self.porto_v_angle_held = 1; + + ClientData_Touch(self); + } + } + if(self.porto_v_angle_held) + makevectors(self.porto_v_angle); // override the previously set angles + + if (self.BUTTON_ATCK) + if (!self.porto_current) + if (!self.porto_forbidden) + if (weapon_prepareattack(0, autocvar_g_balance_porto_primary_refire)) + { + W_Porto_Attack(-1); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_porto_primary_animtime, w_ready); + } + } + } + else if (req == WR_PRECACHE) + { + precache_model ("models/weapons/g_porto.md3"); + precache_model ("models/weapons/v_porto.md3"); + precache_model ("models/weapons/h_porto.iqm"); + precache_model ("models/portal.md3"); + precache_sound ("porto/bounce.wav"); + precache_sound ("porto/create.wav"); + precache_sound ("porto/expire.wav"); + precache_sound ("porto/explode.wav"); + precache_sound ("porto/fire.wav"); + precache_sound ("porto/unsupported.wav"); + } + else if (req == WR_SETUP) + { + weapon_setup(WEP_PORTO); + self.current_ammo = ammo_none; + } + else if (req == WR_RESETPLAYER) + { + self.porto_current = world; + } + return TRUE; +} +#endif +#ifdef CSQC +float w_porto(float req) +{ + if(req == WR_IMPACTEFFECT) + { + print("Since when does Porto send DamageInfo?\n"); + } + else if(req == WR_PRECACHE) + { + // nothing to do + } + return TRUE; +} +#endif +#endif diff --git a/qcsrc/server/w_rifle.qc b/qcsrc/server/w_rifle.qc new file mode 100644 index 000000000..0e3a5c0b0 --- /dev/null +++ b/qcsrc/server/w_rifle.qc @@ -0,0 +1,264 @@ +#ifdef REGISTER_WEAPON +REGISTER_WEAPON( +/* WEP_##id */ RIFLE, +/* function */ w_rifle, +/* ammotype */ IT_NAILS, +/* impulse */ 7, +/* flags */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN, +/* rating */ BOT_PICKUP_RATING_MID, +/* model */ "campingrifle", +/* shortname */ "rifle", +/* fullname */ _("Rifle") +); +#else +#ifdef SVQC + +.float rifle_accumulator; + +void W_Rifle_FireBullet(float pSpread, float pDamage, float pForce, float pSolidPenetration, float pAmmo, float deathtype, float pTracer, float pShots, string pSound) +{ + float i; + + W_DecreaseAmmo(ammo_nails, pAmmo, autocvar_g_balance_rifle_reload_ammo); + + W_SetupShot (self, TRUE, 2, pSound, CH_WEAPON_A, pDamage * pShots); + + pointparticles(particleeffectnum("rifle_muzzleflash"), w_shotorg, w_shotdir * 2000, 1); + + if(self.BUTTON_ZOOM | self.BUTTON_ZOOMSCRIPT) // if zoomed, shoot from the eye + { + w_shotdir = v_forward; + w_shotorg = self.origin + self.view_ofs + ((w_shotorg - self.origin - self.view_ofs) * v_forward) * v_forward; + } + + for(i = 0; i < pShots; ++i) + fireBullet(w_shotorg, w_shotdir, pSpread, pSolidPenetration, pDamage, pForce, deathtype, (pTracer ? EF_RED : EF_BLUE)); + + if (autocvar_g_casings >= 2) + SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self); +} + +void W_Rifle_Attack() +{ + W_Rifle_FireBullet(autocvar_g_balance_rifle_primary_spread, autocvar_g_balance_rifle_primary_damage, autocvar_g_balance_rifle_primary_force, autocvar_g_balance_rifle_primary_solidpenetration, autocvar_g_balance_rifle_primary_ammo, WEP_RIFLE, autocvar_g_balance_rifle_primary_tracer, autocvar_g_balance_rifle_primary_shots, "weapons/campingrifle_fire.wav"); +} + +void W_Rifle_Attack2() +{ + W_Rifle_FireBullet(autocvar_g_balance_rifle_secondary_spread, autocvar_g_balance_rifle_secondary_damage, autocvar_g_balance_rifle_secondary_force, autocvar_g_balance_rifle_secondary_solidpenetration, autocvar_g_balance_rifle_secondary_ammo, WEP_RIFLE | HITTYPE_SECONDARY, autocvar_g_balance_rifle_secondary_tracer, autocvar_g_balance_rifle_secondary_shots, "weapons/campingrifle_fire2.wav"); +} + +void spawnfunc_weapon_rifle (void) +{ + weapon_defaultspawnfunc(WEP_RIFLE); +} + +// compatibility alias +void spawnfunc_weapon_campingrifle (void) +{ + spawnfunc_weapon_rifle(); +} +void spawnfunc_weapon_sniperrifle (void) +{ + spawnfunc_weapon_rifle(); +} + +.void(void) rifle_bullethail_attackfunc; +.float rifle_bullethail_frame; +.float rifle_bullethail_animtime; +.float rifle_bullethail_refire; +void W_Rifle_BulletHail_Continue() +{ + float r, sw, af; + + sw = self.switchweapon; // make it not detect weapon changes as reason to abort firing + af = ATTACK_FINISHED(self); + self.switchweapon = self.weapon; + ATTACK_FINISHED(self) = time; + print(ftos(self.ammo_nails), "\n"); + r = weapon_prepareattack(self.rifle_bullethail_frame == WFRAME_FIRE2, self.rifle_bullethail_refire); + if(self.switchweapon == self.weapon) + self.switchweapon = sw; + if(r) + { + self.rifle_bullethail_attackfunc(); + weapon_thinkf(self.rifle_bullethail_frame, self.rifle_bullethail_animtime, W_Rifle_BulletHail_Continue); + print("thinkf set\n"); + } + else + { + ATTACK_FINISHED(self) = af; // reset attack_finished if we didn't fire, so the last shot enforces the refire time + print("out of ammo... ", ftos(self.weaponentity.state), "\n"); + } +} + +void W_Rifle_BulletHail(float mode, void(void) AttackFunc, float fr, float animtime, float refire) +{ + // if we get here, we have at least one bullet to fire + AttackFunc(); + if(mode) + { + // continue hail + self.rifle_bullethail_attackfunc = AttackFunc; + self.rifle_bullethail_frame = fr; + self.rifle_bullethail_animtime = animtime; + self.rifle_bullethail_refire = refire; + weapon_thinkf(fr, animtime, W_Rifle_BulletHail_Continue); + } + else + { + // just one shot + weapon_thinkf(fr, animtime, w_ready); + } +} + +.float bot_secondary_riflemooth; +float w_rifle(float req) +{ + float ammo_amount; + + if (req == WR_AIM) + { + self.BUTTON_ATCK=FALSE; + self.BUTTON_ATCK2=FALSE; + if(vlen(self.origin-self.enemy.origin) > 1000) + self.bot_secondary_riflemooth = 0; + if(self.bot_secondary_riflemooth == 0) + { + if(bot_aim(1000000, 0, 0.001, FALSE)) + { + self.BUTTON_ATCK = TRUE; + if(random() < 0.01) self.bot_secondary_riflemooth = 1; + } + } + else + { + if(bot_aim(1000000, 0, 0.001, FALSE)) + { + self.BUTTON_ATCK2 = TRUE; + if(random() < 0.03) self.bot_secondary_riflemooth = 0; + } + } + } + else if (req == WR_THINK) + { + if(autocvar_g_balance_rifle_reload_ammo && self.clip_load < min(autocvar_g_balance_rifle_primary_ammo, autocvar_g_balance_rifle_secondary_ammo)) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else + { + self.rifle_accumulator = bound(time - autocvar_g_balance_rifle_bursttime, self.rifle_accumulator, time); + if (self.BUTTON_ATCK) + if (weapon_prepareattack_check(0, autocvar_g_balance_rifle_primary_refire)) + if (time >= self.rifle_accumulator + autocvar_g_balance_rifle_primary_burstcost) + { + weapon_prepareattack_do(0, autocvar_g_balance_rifle_primary_refire); + W_Rifle_BulletHail(autocvar_g_balance_rifle_primary_bullethail, W_Rifle_Attack, WFRAME_FIRE1, autocvar_g_balance_rifle_primary_animtime, autocvar_g_balance_rifle_primary_refire); + self.rifle_accumulator += autocvar_g_balance_rifle_primary_burstcost; + } + if (self.BUTTON_ATCK2) + { + if (autocvar_g_balance_rifle_secondary) + { + if(autocvar_g_balance_rifle_secondary_reload) + weapon_action(self.weapon, WR_RELOAD); + else + { + if (weapon_prepareattack_check(1, autocvar_g_balance_rifle_secondary_refire)) + if (time >= self.rifle_accumulator + autocvar_g_balance_rifle_secondary_burstcost) + { + weapon_prepareattack_do(1, autocvar_g_balance_rifle_secondary_refire); + W_Rifle_BulletHail(autocvar_g_balance_rifle_secondary_bullethail, W_Rifle_Attack2, WFRAME_FIRE2, autocvar_g_balance_rifle_secondary_animtime, autocvar_g_balance_rifle_primary_refire); + self.rifle_accumulator += autocvar_g_balance_rifle_secondary_burstcost; + } + } + } + } + } + } + else if (req == WR_PRECACHE) + { + precache_model ("models/weapons/g_campingrifle.md3"); + precache_model ("models/weapons/v_campingrifle.md3"); + precache_model ("models/weapons/h_campingrifle.iqm"); + precache_sound ("weapons/campingrifle_fire.wav"); + precache_sound ("weapons/campingrifle_fire2.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else + } + else if (req == WR_SETUP) + { + weapon_setup(WEP_RIFLE); + self.current_ammo = ammo_nails; + } + else if (req == WR_CHECKAMMO1) + { + ammo_amount = self.ammo_nails >= autocvar_g_balance_rifle_primary_ammo; + ammo_amount += self.(weapon_load[WEP_RIFLE]) >= autocvar_g_balance_rifle_primary_ammo; + return ammo_amount; + } + else if (req == WR_CHECKAMMO2) + { + ammo_amount = self.ammo_nails >= autocvar_g_balance_rifle_secondary_ammo; + ammo_amount += self.(weapon_load[WEP_RIFLE]) >= autocvar_g_balance_rifle_secondary_ammo; + return ammo_amount; + } + else if (req == WR_RESETPLAYER) + { + self.rifle_accumulator = time - autocvar_g_balance_rifle_bursttime; + } + else if (req == WR_RELOAD) + { + W_Reload(min(autocvar_g_balance_rifle_primary_ammo, autocvar_g_balance_rifle_secondary_ammo), autocvar_g_balance_rifle_reload_ammo, autocvar_g_balance_rifle_reload_time, "weapons/reload.wav"); + } + else if (req == WR_SUICIDEMESSAGE) + { + return WEAPON_THINKING_WITH_PORTALS; + } + else if (req == WR_KILLMESSAGE) + { + if(w_deathtype & HITTYPE_SECONDARY) + { + if(w_deathtype & HITTYPE_BOUNCE) + return WEAPON_RIFLE_MURDER_HAIL_PIERCING; + else + return WEAPON_RIFLE_MURDER_HAIL; + } + else + { + if(w_deathtype & HITTYPE_BOUNCE) + return WEAPON_RIFLE_MURDER_PIERCING; + else + return WEAPON_RIFLE_MURDER; + } + } + return TRUE; +} +#endif +#ifdef CSQC +float w_rifle(float req) +{ + if(req == WR_IMPACTEFFECT) + { + vector org2; + org2 = w_org + w_backoff * 2; + pointparticles(particleeffectnum("machinegun_impact"), org2, w_backoff * 1000, 1); + if(!w_issilent) + { + if(w_random < 0.2) + sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTEN_NORM); + else if(w_random < 0.4) + sound(self, CH_SHOTS, "weapons/ric2.wav", VOL_BASE, ATTEN_NORM); + else if(w_random < 0.5) + sound(self, CH_SHOTS, "weapons/ric3.wav", VOL_BASE, ATTEN_NORM); + } + } + else if(req == WR_PRECACHE) + { + precache_sound("weapons/ric1.wav"); + precache_sound("weapons/ric2.wav"); + precache_sound("weapons/ric3.wav"); + } + + return TRUE; +} +#endif +#endif diff --git a/qcsrc/server/w_rocketlauncher.qc b/qcsrc/server/w_rocketlauncher.qc new file mode 100644 index 000000000..6cd8929f6 --- /dev/null +++ b/qcsrc/server/w_rocketlauncher.qc @@ -0,0 +1,491 @@ +#ifdef REGISTER_WEAPON +REGISTER_WEAPON( +/* WEP_##id */ ROCKET_LAUNCHER, +/* function */ w_rlauncher, +/* ammotype */ IT_ROCKETS, +/* impulse */ 9, +/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, +/* rating */ BOT_PICKUP_RATING_HIGH, +/* model */ "rl", +/* shortname */ "rocketlauncher", +/* fullname */ _("Rocket Launcher") +); +#else +#ifdef SVQC +.float rl_release; +.float rl_detonate_later; + +void W_Rocket_Unregister() +{ + if(self.realowner && self.realowner.lastrocket == self) + { + self.realowner.lastrocket = world; + // self.realowner.rl_release = 1; + } +} + +void W_Rocket_Explode () +{ + W_Rocket_Unregister(); + + if(other.takedamage == DAMAGE_AIM) + if(IS_PLAYER(other)) + if(DIFF_TEAM(self.realowner, other)) + if(other.deadflag == DEAD_NO) + if(IsFlying(other)) + Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT); + + self.event_damage = func_null; + self.takedamage = DAMAGE_NO; + + RadiusDamage (self, self.realowner, autocvar_g_balance_rocketlauncher_damage, autocvar_g_balance_rocketlauncher_edgedamage, autocvar_g_balance_rocketlauncher_radius, world, autocvar_g_balance_rocketlauncher_force, self.projectiledeathtype, other); + + if (self.realowner.weapon == WEP_ROCKET_LAUNCHER) + { + if(self.realowner.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo) + { + self.realowner.cnt = WEP_ROCKET_LAUNCHER; + ATTACK_FINISHED(self.realowner) = time; + self.realowner.switchweapon = w_getbestweapon(self.realowner); + } + } + remove (self); +} + +void W_Rocket_DoRemoteExplode () +{ + W_Rocket_Unregister(); + + self.event_damage = func_null; + self.takedamage = DAMAGE_NO; + + RadiusDamage (self, self.realowner, autocvar_g_balance_rocketlauncher_remote_damage, autocvar_g_balance_rocketlauncher_remote_edgedamage, autocvar_g_balance_rocketlauncher_remote_radius, world, autocvar_g_balance_rocketlauncher_remote_force, self.projectiledeathtype | HITTYPE_BOUNCE, world); + + if (self.realowner.weapon == WEP_ROCKET_LAUNCHER) + { + if(self.realowner.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo) + { + self.realowner.cnt = WEP_ROCKET_LAUNCHER; + ATTACK_FINISHED(self.realowner) = time; + self.realowner.switchweapon = w_getbestweapon(self.realowner); + } + } + remove (self); +} + +void W_Rocket_RemoteExplode() +{ + if(self.realowner.deadflag == DEAD_NO) + if(self.realowner.lastrocket) + { + if((self.spawnshieldtime >= 0) + ? (time >= self.spawnshieldtime) // timer + : (vlen(NearestPointOnBox(self.realowner, self.origin) - self.origin) > autocvar_g_balance_rocketlauncher_remote_radius) // safety device + ) + { + W_Rocket_DoRemoteExplode(); + } + } +} + +vector rocket_steerto(vector thisdir, vector goaldir, float maxturn_cos) +{ + if(thisdir * goaldir > maxturn_cos) + return goaldir; + if(thisdir * goaldir < -0.9998) // less than 1 degree and opposite + return thisdir; // refuse to guide (better than letting a numerical error happen) + float f, m2; + vector v; + // solve: + // g = normalize(thisdir + goaldir * X) + // thisdir * g = maxturn + // + // gg = thisdir + goaldir * X + // (thisdir * gg)^2 = maxturn^2 * (gg * gg) + // + // (1 + (thisdir * goaldir) * X)^2 = maxturn^2 * (1 + X*X + 2 * X * thisdir * goaldir) + f = thisdir * goaldir; + // (1 + f * X)^2 = maxturn^2 * (1 + X*X + 2 * X * f) + // 0 = (m^2 - f^2) * x^2 + (2 * f * (m^2 - 1)) * x + (m^2 - 1) + m2 = maxturn_cos * maxturn_cos; + v = solve_quadratic(m2 - f * f, 2 * f * (m2 - 1), m2 - 1); + return normalize(thisdir + goaldir * v_y); // the larger solution! +} +// assume thisdir == -goaldir: +// f == -1 +// v = solve_qadratic(m2 - 1, -2 * (m2 - 1), m2 - 1) +// (m2 - 1) x^2 - 2 * (m2 - 1) * x + (m2 - 1) = 0 +// x^2 - 2 * x + 1 = 0 +// (x - 1)^2 = 0 +// x = 1 +// normalize(thisdir + goaldir) +// normalize(0) + +void W_Rocket_Think (void) +{ + vector desireddir, olddir, newdir, desiredorigin, goal; +#if 0 + float cosminang, cosmaxang, cosang; +#endif + float velspeed, f; + self.nextthink = time; + if (time > self.cnt) + { + other = world; + self.projectiledeathtype |= HITTYPE_BOUNCE; + W_Rocket_Explode (); + return; + } + + // accelerate + makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0'); + velspeed = autocvar_g_balance_rocketlauncher_speed * g_weaponspeedfactor - (self.velocity * v_forward); + if (velspeed > 0) + self.velocity = self.velocity + v_forward * min(autocvar_g_balance_rocketlauncher_speedaccel * g_weaponspeedfactor * frametime, velspeed); + + // laser guided, or remote detonation + if (self.realowner.weapon == WEP_ROCKET_LAUNCHER) + { + if(self == self.realowner.lastrocket) + if (!self.realowner.rl_release) + if (!self.BUTTON_ATCK2) + if(autocvar_g_balance_rocketlauncher_guiderate) + if(time > self.pushltime) + if(self.realowner.deadflag == DEAD_NO) + { + f = autocvar_g_balance_rocketlauncher_guideratedelay; + if(f) + f = bound(0, (time - self.pushltime) / f, 1); + else + f = 1; + + velspeed = vlen(self.velocity); + + makevectors(self.realowner.v_angle); + desireddir = WarpZone_RefSys_TransformVelocity(self.realowner, self, v_forward); + desiredorigin = WarpZone_RefSys_TransformOrigin(self.realowner, self, self.realowner.origin + self.realowner.view_ofs); + olddir = normalize(self.velocity); + + // now it gets tricky... we want to move like some curve to approximate the target direction + // but we are limiting the rate at which we can turn! + goal = desiredorigin + ((self.origin - desiredorigin) * desireddir + autocvar_g_balance_rocketlauncher_guidegoal) * desireddir; + newdir = rocket_steerto(olddir, normalize(goal - self.origin), cos(autocvar_g_balance_rocketlauncher_guiderate * f * frametime * DEG2RAD)); + + self.velocity = newdir * velspeed; + self.angles = vectoangles(self.velocity); + + if(!self.count) + { + pointparticles(particleeffectnum("rocket_guide"), self.origin, self.velocity, 1); + // TODO add a better sound here + sound (self.realowner, CH_WEAPON_B, "weapons/rocket_mode.wav", VOL_BASE, ATTEN_NORM); + self.count = 1; + } + } + + if(self.rl_detonate_later) + W_Rocket_RemoteExplode(); + } + + if(self.csqcprojectile_clientanimate == 0) + UpdateCSQCProjectile(self); +} + +void W_Rocket_Touch (void) +{ + if(WarpZone_Projectile_Touch()) + { + if(wasfreed(self)) + W_Rocket_Unregister(); + return; + } + W_Rocket_Unregister(); + W_Rocket_Explode (); +} + +void W_Rocket_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) +{ + if (self.health <= 0) + return; + + if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions + return; // g_projectiles_damage says to halt + + self.health = self.health - damage; + self.angles = vectoangles(self.velocity); + + if (self.health <= 0) + W_PrepareExplosionByDamage(attacker, W_Rocket_Explode); +} + +void W_Rocket_Attack (void) +{ + entity missile; + entity flash; + + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_rocketlauncher_ammo, autocvar_g_balance_rocketlauncher_reload_ammo); + + W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 5, "weapons/rocket_fire.wav", CH_WEAPON_A, autocvar_g_balance_rocketlauncher_damage); + pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); + + missile = WarpZone_RefSys_SpawnSameRefSys(self); + missile.owner = missile.realowner = self; + self.lastrocket = missile; + if(autocvar_g_balance_rocketlauncher_detonatedelay >= 0) + missile.spawnshieldtime = time + autocvar_g_balance_rocketlauncher_detonatedelay; + else + missile.spawnshieldtime = -1; + missile.pushltime = time + autocvar_g_balance_rocketlauncher_guidedelay; + missile.classname = "rocket"; + missile.bot_dodge = TRUE; + missile.bot_dodgerating = autocvar_g_balance_rocketlauncher_damage * 2; // * 2 because it can be detonated inflight which makes it even more dangerous + + missile.takedamage = DAMAGE_YES; + missile.damageforcescale = autocvar_g_balance_rocketlauncher_damageforcescale; + missile.health = autocvar_g_balance_rocketlauncher_health; + missile.event_damage = W_Rocket_Damage; + missile.damagedbycontents = TRUE; + + missile.movetype = MOVETYPE_FLY; + PROJECTILE_MAKETRIGGER(missile); + missile.projectiledeathtype = WEP_ROCKET_LAUNCHER; + setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot + + setorigin (missile, w_shotorg - v_forward * 3); // move it back so it hits the wall at the right point + W_SetupProjectileVelocity(missile, autocvar_g_balance_rocketlauncher_speedstart, 0); + missile.angles = vectoangles (missile.velocity); + + missile.touch = W_Rocket_Touch; + missile.think = W_Rocket_Think; + missile.nextthink = time; + missile.cnt = time + autocvar_g_balance_rocketlauncher_lifetime; + missile.flags = FL_PROJECTILE; + missile.missile_flags = MIF_SPLASH; + + CSQCProjectile(missile, autocvar_g_balance_rocketlauncher_guiderate == 0 && autocvar_g_balance_rocketlauncher_speedaccel == 0, PROJECTILE_ROCKET, FALSE); // because of fly sound + + // 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 + other = missile; MUTATOR_CALLHOOK(EditProjectile); +} + +void spawnfunc_weapon_rocketlauncher (void); // defined in t_items.qc + +float w_rlauncher(float req) +{ + entity rock; + float rockfound; + float ammo_amount; + + if (req == WR_AIM) + { + // aim and decide to fire if appropriate + self.BUTTON_ATCK = bot_aim(autocvar_g_balance_rocketlauncher_speed, 0, autocvar_g_balance_rocketlauncher_lifetime, FALSE); + if(skill >= 2) // skill 0 and 1 bots won't detonate rockets! + { + // decide whether to detonate rockets + entity missile, targetlist, targ; + float edgedamage, coredamage, edgeradius, recipricoledgeradius, d; + float selfdamage, teamdamage, enemydamage; + edgedamage = autocvar_g_balance_rocketlauncher_edgedamage; + coredamage = autocvar_g_balance_rocketlauncher_damage; + edgeradius = autocvar_g_balance_rocketlauncher_radius; + recipricoledgeradius = 1 / edgeradius; + selfdamage = 0; + teamdamage = 0; + enemydamage = 0; + targetlist = findchainfloat(bot_attack, TRUE); + missile = find(world, classname, "rocket"); + while (missile) + { + if (missile.realowner != self) + { + missile = find(missile, classname, "rocket"); + continue; + } + targ = targetlist; + while (targ) + { + d = vlen(targ.origin + (targ.mins + targ.maxs) * 0.5 - missile.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 && teamplay) + teamdamage = teamdamage + d; + else if (bot_shouldattack(targ)) + enemydamage = enemydamage + d; + targ = targ.chain; + } + missile = find(missile, classname, "rocket"); + } + float desirabledamage; + desirabledamage = enemydamage; + if (time > self.invincible_finished && time > self.spawnshieldtime) + desirabledamage = desirabledamage - selfdamage * autocvar_g_balance_selfdamagepercent; + if (teamplay && self.team) + desirabledamage = desirabledamage - teamdamage; + + missile = find(world, classname, "rocket"); + while (missile) + { + if (missile.realowner != self) + { + missile = find(missile, classname, "rocket"); + continue; + } + makevectors(missile.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(missile.origin - targ.origin)< 0.1) + && desirabledamage > 0.1*coredamage + )self.BUTTON_ATCK2 = TRUE; + targ = targ.chain; + } + }else{ + 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 rocket spawnfunc_light to see if the rocket gets near a player + if(v_forward * normalize(missile.origin - self.enemy.origin)< 0.1) + if(IS_PLAYER(self.enemy)) + 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"); + } + + missile = find(missile, classname, "rocket"); + } + // 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(autocvar_g_balance_rocketlauncher_reload_ammo && self.clip_load < autocvar_g_balance_rocketlauncher_ammo) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else + { + if (self.BUTTON_ATCK) + { + if(self.rl_release || autocvar_g_balance_rocketlauncher_guidestop) + if(weapon_prepareattack(0, autocvar_g_balance_rocketlauncher_refire)) + { + W_Rocket_Attack(); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_rocketlauncher_animtime, w_ready); + self.rl_release = 0; + } + } + else + self.rl_release = 1; + + if (self.BUTTON_ATCK2) + { + rockfound = 0; + for(rock = world; (rock = find(rock, classname, "rocket")); ) if(rock.realowner == self) + { + if(!rock.rl_detonate_later) + { + rock.rl_detonate_later = TRUE; + rockfound = 1; + } + } + if(rockfound) + sound (self, CH_WEAPON_B, "weapons/rocket_det.wav", VOL_BASE, ATTEN_NORM); + } + } + } + else if (req == WR_PRECACHE) + { + precache_model ("models/flash.md3"); + precache_model ("models/weapons/g_rl.md3"); + precache_model ("models/weapons/v_rl.md3"); + precache_model ("models/weapons/h_rl.iqm"); + precache_sound ("weapons/rocket_det.wav"); + precache_sound ("weapons/rocket_fire.wav"); + precache_sound ("weapons/rocket_mode.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else + } + else if (req == WR_SETUP) + { + weapon_setup(WEP_ROCKET_LAUNCHER); + self.current_ammo = ammo_rockets; + self.rl_release = 1; + } + else if (req == WR_CHECKAMMO1) + { + // don't switch while guiding a missile + if (ATTACK_FINISHED(self) <= time || self.weapon != WEP_ROCKET_LAUNCHER) + { + ammo_amount = FALSE; + if(autocvar_g_balance_rocketlauncher_reload_ammo) + { + if(self.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo && self.(weapon_load[WEP_ROCKET_LAUNCHER]) < autocvar_g_balance_rocketlauncher_ammo) + ammo_amount = TRUE; + } + else if(self.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo) + ammo_amount = TRUE; + return !ammo_amount; + } + } + else if (req == WR_CHECKAMMO2) + return FALSE; + else if (req == WR_RESETPLAYER) + { + self.rl_release = 0; + } + else if (req == WR_RELOAD) + { + W_Reload(autocvar_g_balance_rocketlauncher_ammo, autocvar_g_balance_rocketlauncher_reload_ammo, autocvar_g_balance_rocketlauncher_reload_time, "weapons/reload.wav"); + } + else if (req == WR_SUICIDEMESSAGE) + { + return WEAPON_ROCKETLAUNCHER_SUICIDE; + } + else if (req == WR_KILLMESSAGE) + { + if((w_deathtype & HITTYPE_BOUNCE) || (w_deathtype & HITTYPE_SPLASH)) + return WEAPON_ROCKETLAUNCHER_MURDER_SPLASH; + else + return WEAPON_ROCKETLAUNCHER_MURDER_DIRECT; + } + return TRUE; +} +#endif +#ifdef CSQC +float w_rlauncher(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, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM); + } + else if(req == WR_PRECACHE) + { + precache_sound("weapons/rocket_impact.wav"); + } + return TRUE; +} +#endif +#endif diff --git a/qcsrc/server/w_seeker.qc b/qcsrc/server/w_seeker.qc new file mode 100644 index 000000000..c870f0868 --- /dev/null +++ b/qcsrc/server/w_seeker.qc @@ -0,0 +1,712 @@ +#ifdef REGISTER_WEAPON +REGISTER_WEAPON( +/* WEP_##id */ SEEKER, +/* function */ w_seeker, +/* ammotype */ IT_ROCKETS, +/* impulse */ 8, +/* flags */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH, +/* rating */ BOT_PICKUP_RATING_MID, +/* model */ "seeker", +/* shortname */ "seeker", +/* fullname */ _("T.A.G. Seeker") +); +#else +#ifdef SVQC +//.float proxytime; = autoswitch +//.float tl; = wait +.entity tag_target, wps_tag_tracker; +.float tag_time; + +// ============================ +// Begin: Missile functions, these are general functions to be manipulated by other code +// ============================ +void Seeker_Missile_Explode () +{ + self.event_damage = func_null; + RadiusDamage (self, self.realowner, autocvar_g_balance_seeker_missile_damage, autocvar_g_balance_seeker_missile_edgedamage, autocvar_g_balance_seeker_missile_radius, world, autocvar_g_balance_seeker_missile_force, self.projectiledeathtype, other); + + remove (self); +} + +void Seeker_Missile_Touch() +{ + PROJECTILE_TOUCH; + + Seeker_Missile_Explode(); +} + +void Seeker_Missile_Think() +{ + entity e; + vector desireddir, olddir, newdir, eorg; + float turnrate; + float dist; + float spd; + + if (time > self.cnt) + { + self.projectiledeathtype |= HITTYPE_SPLASH; + Seeker_Missile_Explode(); + } + + spd = vlen(self.velocity); + spd = bound( + spd - autocvar_g_balance_seeker_missile_decel * frametime, + autocvar_g_balance_seeker_missile_speed_max, + spd + autocvar_g_balance_seeker_missile_accel * frametime + ); + + if (self.enemy != world) + if (self.enemy.takedamage != DAMAGE_AIM || self.enemy.deadflag != DEAD_NO) + self.enemy = world; + + if (self.enemy != world) + { + e = self.enemy; + eorg = 0.5 * (e.absmin + e.absmax); + turnrate = autocvar_g_balance_seeker_missile_turnrate; // how fast to turn + desireddir = normalize(eorg - self.origin); + olddir = normalize(self.velocity); // get my current direction + dist = vlen(eorg - self.origin); + + // Do evasive maneuvers for world objects? ( this should be a cpu hog. :P ) + if (autocvar_g_balance_seeker_missile_smart && (dist > autocvar_g_balance_seeker_missile_smart_mindist)) + { + // Is it a better idea (shorter distance) to trace to the target itself? + if ( vlen(self.origin + olddir * self.wait) < dist) + traceline(self.origin, self.origin + olddir * self.wait, FALSE, self); + else + traceline(self.origin, eorg, FALSE, self); + + // Setup adaptive tracelength + self.wait = bound(autocvar_g_balance_seeker_missile_smart_trace_min, vlen(self.origin - trace_endpos), self.wait = autocvar_g_balance_seeker_missile_smart_trace_max); + + // Calc how important it is that we turn and add this to the desierd (enemy) dir. + desireddir = normalize(((trace_plane_normal * (1 - trace_fraction)) + (desireddir * trace_fraction)) * 0.5); + } + + newdir = normalize(olddir + desireddir * turnrate); // take the average of the 2 directions; not the best method but simple & easy + self.velocity = newdir * spd; // make me fly in the new direction at my flight speed + } + else + dist = 0; + + // Proxy + if (autocvar_g_balance_seeker_missile_proxy) + { + if ( dist <= autocvar_g_balance_seeker_missile_proxy_maxrange) + { + if (self.autoswitch == 0) + { + self.autoswitch = time + autocvar_g_balance_seeker_missile_proxy_delay; + } + else + { + if (self.autoswitch <= time) + { + Seeker_Missile_Explode(); + self.autoswitch = 0; + } + } + } + else + { + if (self.autoswitch != 0) + self.autoswitch = 0; + } + } + /////////////// + + if (self.enemy.deadflag != DEAD_NO) + { + self.enemy = world; + self.cnt = time + 1 + (random() * 4); + self.nextthink = self.cnt; + return; + } + + //self.angles = vectoangles(self.velocity); // turn model in the new flight direction + self.nextthink = time;// + 0.05; // csqc projectiles + UpdateCSQCProjectile(self); +} + + + +void Seeker_Missile_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) +{ + if (self.health <= 0) + return; + + if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions + return; // g_projectiles_damage says to halt + + if (self.realowner == attacker) + self.health = self.health - (damage * 0.25); + else + self.health = self.health - damage; + + if (self.health <= 0) + W_PrepareExplosionByDamage(attacker, Seeker_Missile_Explode); +} + +/* +void Seeker_Missile_Animate() +{ + self.frame = self.frame +1; + self.nextthink = time + 0.05; + + if (self.enemy != world) + if (self.enemy.takedamage != DAMAGE_AIM || self.enemy.deadflag != DEAD_NO) + self.enemy = world; + + if(self.frame == 5) + { + self.think = Seeker_Missile_Think; + self.nextthink = time;// + cvar("g_balance_seeker_missile_activate_delay"); // cant dealy with csqc projectiles + + if (autocvar_g_balance_seeker_missile_proxy) + self.movetype = MOVETYPE_BOUNCEMISSILE; + else + self.movetype = MOVETYPE_FLYMISSILE; + } + + UpdateCSQCProjectile(self); +} +*/ + +void Seeker_Fire_Missile(vector f_diff, entity m_target) +{ + entity missile; + + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_seeker_missile_ammo, autocvar_g_balance_seeker_reload_ammo); + + makevectors(self.v_angle); + W_SetupShot_ProjectileSize (self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/seeker_fire.wav", CH_WEAPON_A, 0); + w_shotorg += f_diff; + pointparticles(particleeffectnum("seeker_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); + + //self.detornator = FALSE; + + missile = spawn(); + missile.owner = missile.realowner = self; + missile.classname = "seeker_missile"; + missile.bot_dodge = TRUE; + missile.bot_dodgerating = autocvar_g_balance_seeker_missile_damage; + + missile.think = Seeker_Missile_Think; + missile.touch = Seeker_Missile_Touch; + missile.event_damage = Seeker_Missile_Damage; + missile.nextthink = time;// + 0.2;// + cvar("g_balance_seeker_missile_activate_delay"); + missile.cnt = time + autocvar_g_balance_seeker_missile_lifetime; + missile.enemy = m_target; + missile.solid = SOLID_BBOX; + missile.scale = 2; + missile.takedamage = DAMAGE_YES; + missile.health = autocvar_g_balance_seeker_missile_health; + missile.damageforcescale = autocvar_g_balance_seeker_missile_damageforcescale; + missile.damagedbycontents = TRUE; + //missile.think = Seeker_Missile_Animate; // csqc projectiles. + + if (missile.enemy != world) + missile.projectiledeathtype = WEP_SEEKER | HITTYPE_SECONDARY; + else + missile.projectiledeathtype = WEP_SEEKER; + + + setorigin (missile, w_shotorg); + setsize (missile, '-4 -4 -4', '4 4 4'); + missile.movetype = MOVETYPE_FLYMISSILE; + missile.flags = FL_PROJECTILE; + missile.missile_flags = MIF_SPLASH | MIF_GUIDED_TAG; + + W_SETUPPROJECTILEVELOCITY_UP(missile, g_balance_seeker_missile); + + missile.angles = vectoangles (missile.velocity); + + CSQCProjectile(missile, FALSE, PROJECTILE_SEEKER, TRUE); + + other = missile; MUTATOR_CALLHOOK(EditProjectile); +} + +// ============================ +// Begin: FLAC, close range attack meant for defeating rockets which are coming at you. +// ============================ +void Seeker_Flac_Explode () +{ + self.event_damage = func_null; + + RadiusDamage (self, self.realowner, autocvar_g_balance_seeker_flac_damage, autocvar_g_balance_seeker_flac_edgedamage, autocvar_g_balance_seeker_flac_radius, world, autocvar_g_balance_seeker_flac_force, self.projectiledeathtype, other); + + remove (self); +} + +void Seeker_Flac_Touch() +{ + PROJECTILE_TOUCH; + + Seeker_Flac_Explode(); +} + +void Seeker_Fire_Flac() +{ + entity missile; + vector f_diff; + float c; + + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_seeker_flac_ammo, autocvar_g_balance_seeker_reload_ammo); + + c = mod(self.bulletcounter, 4); + switch(c) + { + case 0: + f_diff = '-1.25 -3.75 0'; + break; + case 1: + f_diff = '+1.25 -3.75 0'; + break; + case 2: + f_diff = '-1.25 +3.75 0'; + break; + case 3: + default: + f_diff = '+1.25 +3.75 0'; + break; + } + W_SetupShot_ProjectileSize (self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/flac_fire.wav", CH_WEAPON_A, autocvar_g_balance_seeker_flac_damage); + w_shotorg += f_diff; + + pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); + + missile = spawn (); + missile.owner = missile.realowner = self; + missile.classname = "missile"; + missile.bot_dodge = TRUE; + missile.bot_dodgerating = autocvar_g_balance_seeker_flac_damage; + missile.touch = Seeker_Flac_Explode; + missile.use = Seeker_Flac_Explode; + missile.think = adaptor_think2use_hittype_splash; + missile.nextthink = time + autocvar_g_balance_seeker_flac_lifetime + autocvar_g_balance_seeker_flac_lifetime_rand; + missile.solid = SOLID_BBOX; + missile.movetype = MOVETYPE_FLY; + missile.projectiledeathtype = WEP_SEEKER; + missile.projectiledeathtype = WEP_SEEKER | HITTYPE_SECONDARY; + missile.flags = FL_PROJECTILE; + missile.missile_flags = MIF_SPLASH; + + // csqc projectiles + //missile.angles = vectoangles (missile.velocity); + //missile.scale = 0.4; // BUG: the model is too big + + setorigin (missile, w_shotorg); + setsize (missile, '-2 -2 -2', '2 2 2'); + + W_SETUPPROJECTILEVELOCITY_UP(missile, g_balance_seeker_flac); + CSQCProjectile(missile, TRUE, PROJECTILE_FLAC, TRUE); + + other = missile; MUTATOR_CALLHOOK(EditProjectile); +} + +// ============================ +// Begin: Tag and rocket controllers +// ============================ +entity Seeker_Tagged_Info(entity isowner, entity istarget) +{ + entity tag; + for(tag = world; (tag = find(tag, classname, "tag_tracker")); ) + if ((tag.realowner == isowner) && (tag.tag_target == istarget)) + return tag; + + return world; +} + +void Seeker_Attack() +{ + entity tracker, closest_target; + + closest_target = world; + for(tracker = world; (tracker = find(tracker, classname, "tag_tracker")); ) if (tracker.realowner == self) + { + if (closest_target) + { + if (vlen(self.origin - tracker.tag_target.origin) < vlen(self.origin - closest_target.origin)) + closest_target = tracker.tag_target; + } + else + closest_target = tracker.tag_target; + } + + traceline(self.origin + self.view_ofs, closest_target.origin, MOVE_NOMONSTERS, self); + if ((!closest_target) || ((trace_fraction < 1) && (trace_ent != closest_target))) + closest_target = world; + + Seeker_Fire_Missile('0 0 0', closest_target); +} + +void Seeker_Vollycontroller_Think() // TODO: Merge this with Seeker_Attack +{ + float c; + entity oldself,oldenemy; + self.cnt = self.cnt - 1; + + if((!(self.realowner.items & IT_UNLIMITED_AMMO) && self.realowner.ammo_rockets < autocvar_g_balance_seeker_missile_ammo) || (self.cnt <= -1) || (self.realowner.deadflag != DEAD_NO) || (self.realowner.switchweapon != WEP_SEEKER)) + { + remove(self); + return; + } + + self.nextthink = time + autocvar_g_balance_seeker_missile_delay * W_WeaponRateFactor(); + + oldself = self; + self = self.realowner; + + oldenemy = self.enemy; + self.enemy = oldself.enemy; + + c = mod(self.cnt, 4); + switch(c) + { + case 0: + Seeker_Fire_Missile('-1.25 -3.75 0', self.enemy); + break; + case 1: + Seeker_Fire_Missile('+1.25 -3.75 0', self.enemy); + break; + case 2: + Seeker_Fire_Missile('-1.25 +3.75 0', self.enemy); + break; + case 3: + default: + Seeker_Fire_Missile('+1.25 +3.75 0', self.enemy); + break; + } + + self.enemy = oldenemy; + self = oldself; +} + +void Seeker_Tracker_Think() +{ + // commit suicide if: You die OR target dies OR you switch away from the seeker OR commit suicide if lifetime is up + if ((self.realowner.deadflag != DEAD_NO) || (self.tag_target.deadflag != DEAD_NO) || (self.realowner.switchweapon != WEP_SEEKER) + || (time > self.tag_time + autocvar_g_balance_seeker_tag_tracker_lifetime)) + { + if (self) + { + WaypointSprite_Kill(self.tag_target.wps_tag_tracker); + remove(self); + } + return; + } + + // Update the think method information + self.nextthink = time; +} + +// ============================ +// Begin: Tag projectile +// ============================ +void Seeker_Tag_Explode () +{ + //if(other==self.realowner) + // return; + Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER | HITTYPE_BOUNCE, other.species, self); + + remove (self); +} + +void Seeker_Tag_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) +{ + if (self.health <= 0) + return; + self.health = self.health - damage; + if (self.health <= 0) + Seeker_Tag_Explode(); +} + +void Seeker_Tag_Touch() +{ + vector dir; + vector org2; + entity e; + + PROJECTILE_TOUCH; + + dir = normalize (self.realowner.origin - self.origin); + org2 = findbetterlocation (self.origin, 8); + + te_knightspike(org2); + + self.event_damage = func_null; + Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER | HITTYPE_BOUNCE | HITTYPE_SECONDARY, other.species, self); + + if (other.takedamage == DAMAGE_AIM && other.deadflag == DEAD_NO) + { + // check to see if this person is already tagged by me + entity tag = Seeker_Tagged_Info(self.realowner, other); + + if (tag != world) + { + if (other.wps_tag_tracker && (autocvar_g_balance_seeker_type == 1)) // don't attach another waypointsprite without killing the old one first + WaypointSprite_Kill(other.wps_tag_tracker); + + tag.tag_time = time; + } + else + { + //sprint(self.realowner, strcat("You just tagged ^2", other.netname, "^7 with a tracking device!\n")); + e = spawn(); + e.cnt = autocvar_g_balance_seeker_missile_count; + e.classname = "tag_tracker"; + e.owner = self.owner; + e.realowner = self.realowner; + + if (autocvar_g_balance_seeker_type == 1) + { + e.tag_target = other; + e.tag_time = time; + e.think = Seeker_Tracker_Think; + } + else + { + e.enemy = other; + e.think = Seeker_Vollycontroller_Think; + } + + e.nextthink = time; + } + + if (autocvar_g_balance_seeker_type == 1) + { + WaypointSprite_Spawn("tagged-target", autocvar_g_balance_seeker_tag_tracker_lifetime, 0, other, '0 0 64', self.realowner, 0, other, wps_tag_tracker, TRUE, RADARICON_TAGGED, '0.5 1 0'); + WaypointSprite_UpdateRule(other.wps_tag_tracker, 0, SPRITERULE_DEFAULT); + } + } + + remove(self); + return; +} + +void Seeker_Fire_Tag() +{ + entity missile; + W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_seeker_tag_ammo, autocvar_g_balance_seeker_reload_ammo); + + W_SetupShot_ProjectileSize (self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/tag_fire.wav", CH_WEAPON_A, autocvar_g_balance_seeker_missile_damage * autocvar_g_balance_seeker_missile_count); + + missile = spawn(); + missile.owner = missile.realowner = self; + missile.classname = "seeker_tag"; + missile.bot_dodge = TRUE; + missile.bot_dodgerating = 50; + missile.touch = Seeker_Tag_Touch; + missile.think = SUB_Remove; + missile.nextthink = time + autocvar_g_balance_seeker_tag_lifetime; + missile.movetype = MOVETYPE_FLY; + missile.solid = SOLID_BBOX; + + missile.takedamage = DAMAGE_YES; + missile.event_damage = Seeker_Tag_Damage; + missile.health = autocvar_g_balance_seeker_tag_health; + missile.damageforcescale = autocvar_g_balance_seeker_tag_damageforcescale; + + setorigin (missile, w_shotorg); + setsize (missile, '-2 -2 -2', '2 2 2'); + + missile.flags = FL_PROJECTILE; + //missile.missile_flags = MIF_..?; + + missile.movetype = MOVETYPE_FLY; + W_SETUPPROJECTILEVELOCITY(missile, g_balance_seeker_tag); + missile.angles = vectoangles (missile.velocity); + + CSQCProjectile(missile, TRUE, PROJECTILE_TAG, FALSE); // has sound + + other = missile; MUTATOR_CALLHOOK(EditProjectile); +} + +// ============================ +// Begin: Genereal weapon functions +// ============================ +void spawnfunc_weapon_seeker (void) +{ + weapon_defaultspawnfunc(WEP_SEEKER); +} + +float w_seeker(float req) +{ + float ammo_amount; + + if (req == WR_AIM) + { + if (autocvar_g_balance_seeker_type == 1) + if (Seeker_Tagged_Info(self, self.enemy) != world) + self.BUTTON_ATCK = bot_aim(autocvar_g_balance_seeker_missile_speed_max, 0, autocvar_g_balance_seeker_missile_lifetime, FALSE); + else + self.BUTTON_ATCK2 = bot_aim(autocvar_g_balance_seeker_tag_speed, 0, autocvar_g_balance_seeker_tag_lifetime, FALSE); + else + self.BUTTON_ATCK = bot_aim(autocvar_g_balance_seeker_tag_speed, 0, autocvar_g_balance_seeker_tag_lifetime, FALSE); + } + else if (req == WR_THINK) + { + if(autocvar_g_balance_seeker_reload_ammo && self.clip_load < min(autocvar_g_balance_seeker_missile_ammo, autocvar_g_balance_seeker_tag_ammo)) // forced reload + weapon_action(self.weapon, WR_RELOAD); + + else if (self.BUTTON_ATCK) + { + if (autocvar_g_balance_seeker_type == 1) + { + if (weapon_prepareattack(0, autocvar_g_balance_seeker_missile_refire)) + { + Seeker_Attack(); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_seeker_missile_animtime, w_ready); + } + } + else + { + if (weapon_prepareattack(0, autocvar_g_balance_seeker_tag_refire)) + { + Seeker_Fire_Tag(); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_seeker_tag_animtime, w_ready); + } + } + } + + else if (self.BUTTON_ATCK2) + { + if (autocvar_g_balance_seeker_type == 1) + { + if (weapon_prepareattack(0, autocvar_g_balance_seeker_tag_refire)) + { + Seeker_Fire_Tag(); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_seeker_tag_animtime, w_ready); + } + } + else + { + if (weapon_prepareattack(0, autocvar_g_balance_seeker_flac_refire)) + { + Seeker_Fire_Flac(); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_seeker_flac_animtime, w_ready); + } + } + } + } + else if (req == WR_PRECACHE) + { + precache_model ("models/weapons/g_seeker.md3"); + precache_model ("models/weapons/v_seeker.md3"); + precache_model ("models/weapons/h_seeker.iqm"); + precache_sound ("weapons/tag_fire.wav"); + precache_sound ("weapons/flac_fire.wav"); + precache_sound ("weapons/seeker_fire.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else + } + else if (req == WR_SETUP) + { + weapon_setup(WEP_SEEKER); + self.current_ammo = ammo_rockets; + } + else if (req == WR_CHECKAMMO1) + { + if (autocvar_g_balance_seeker_type == 1) + { + ammo_amount = self.ammo_rockets >= autocvar_g_balance_seeker_missile_ammo; + ammo_amount += self.(weapon_load[WEP_SEEKER]) >= autocvar_g_balance_seeker_missile_ammo; + } + else + { + ammo_amount = self.ammo_rockets >= autocvar_g_balance_seeker_tag_ammo; + ammo_amount += self.(weapon_load[WEP_SEEKER]) >= autocvar_g_balance_seeker_tag_ammo; + } + + return ammo_amount; + } + else if (req == WR_CHECKAMMO2) + { + if (autocvar_g_balance_seeker_type == 1) + { + ammo_amount = self.ammo_rockets >= autocvar_g_balance_seeker_tag_ammo; + ammo_amount += self.(weapon_load[WEP_SEEKER]) >= autocvar_g_balance_seeker_tag_ammo; + } + else + { + ammo_amount = self.ammo_rockets >= autocvar_g_balance_seeker_flac_ammo; + ammo_amount += self.(weapon_load[WEP_SEEKER]) >= autocvar_g_balance_seeker_flac_ammo; + } + + return ammo_amount; + } + else if (req == WR_RELOAD) + { + W_Reload(min(autocvar_g_balance_seeker_missile_ammo, autocvar_g_balance_seeker_tag_ammo), autocvar_g_balance_seeker_reload_ammo, autocvar_g_balance_seeker_reload_time, "weapons/reload.wav"); + } + else if (req == WR_SUICIDEMESSAGE) + { + return WEAPON_SEEKER_SUICIDE; + } + else if (req == WR_KILLMESSAGE) + { + if(w_deathtype & HITTYPE_SECONDARY) + return WEAPON_SEEKER_MURDER_TAG; + else + return WEAPON_SEEKER_MURDER_SPRAY; + } + return TRUE; +} +#endif +#ifdef CSQC +float w_seeker(float req) +{ + if(req == WR_IMPACTEFFECT) + { + vector org2; + org2 = w_org + w_backoff * 6; + if(w_deathtype & HITTYPE_BOUNCE) + { + if(w_deathtype & HITTYPE_SECONDARY) + { + if(!w_issilent) + sound(self, CH_SHOTS, "weapons/tag_impact.wav", 1, ATTEN_NORM); + } + else + { + pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1); + if(!w_issilent) + { + if (w_random<0.15) + sound(self, CH_SHOTS, "weapons/tagexp1.wav", 1, ATTEN_NORM); + else if (w_random<0.7) + sound(self, CH_SHOTS, "weapons/tagexp2.wav", 1, ATTEN_NORM); + else + sound(self, CH_SHOTS, "weapons/tagexp3.wav", 1, ATTEN_NORM); + } + } + } + else + { + pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1); + if(!w_issilent) + { + if (w_random<0.15) + sound(self, CH_SHOTS, "weapons/seekerexp1.wav", 1, ATTEN_NORM); + else if (w_random<0.7) + sound(self, CH_SHOTS, "weapons/seekerexp2.wav", 1, ATTEN_NORM); + else + sound(self, CH_SHOTS, "weapons/seekerexp3.wav", 1, ATTEN_NORM); + } + } + } + else if(req == WR_PRECACHE) + { + precache_sound("weapons/seekerexp1.wav"); + precache_sound("weapons/seekerexp2.wav"); + precache_sound("weapons/seekerexp3.wav"); + precache_sound("weapons/tagexp1.wav"); + precache_sound("weapons/tagexp2.wav"); + precache_sound("weapons/tagexp3.wav"); + precache_sound("weapons/tag_impact.wav"); + } + return TRUE; +} +#endif +#endif diff --git a/qcsrc/server/w_shotgun.qc b/qcsrc/server/w_shotgun.qc new file mode 100644 index 000000000..173f8c1a5 --- /dev/null +++ b/qcsrc/server/w_shotgun.qc @@ -0,0 +1,287 @@ +#ifdef REGISTER_WEAPON +REGISTER_WEAPON( +/* WEP_##id */ SHOTGUN, +/* function */ w_shotgun, +/* ammotype */ IT_SHELLS, +/* impulse */ 2, +/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN, +/* rating */ BOT_PICKUP_RATING_LOW, +/* model */ "shotgun", +/* shortname */ "shotgun", +/* fullname */ _("Shotgun") +); +#else +#ifdef SVQC + +void W_Shotgun_Attack (void) +{ + float sc; + float ammoamount; + float bullets; + float d; + float f; + float spread; + float solidpenetration; + entity flash; + + ammoamount = autocvar_g_balance_shotgun_primary_ammo; + bullets = autocvar_g_balance_shotgun_primary_bullets; + d = autocvar_g_balance_shotgun_primary_damage; + f = autocvar_g_balance_shotgun_primary_force; + spread = autocvar_g_balance_shotgun_primary_spread; + solidpenetration = autocvar_g_balance_shotgun_primary_solidpenetration; + + W_DecreaseAmmo(ammo_shells, ammoamount, autocvar_g_balance_shotgun_reload_ammo); + + W_SetupShot (self, TRUE, 5, "weapons/shotgun_fire.wav", CH_WEAPON_A, d * bullets); + for (sc = 0;sc < bullets;sc = sc + 1) + fireBullet(w_shotorg, w_shotdir, spread, solidpenetration, d, f, WEP_SHOTGUN, 0); + + pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 1000, autocvar_g_balance_shotgun_primary_ammo); + + // casing code + if (autocvar_g_casings >= 1) + for (sc = 0;sc < ammoamount;sc = sc + 1) + SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 30) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 1, self); + + // muzzle flash for 1st person view + flash = spawn(); + setmodel(flash, "models/uziflash.md3"); // precision set below + flash.think = SUB_Remove; + flash.nextthink = time + 0.06; + flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION; + W_AttachToShotorg(flash, '5 0 0'); +} + +.float swing_prev; +.entity swing_alreadyhit; +void shotgun_meleethink (void) +{ + // declarations + float i, f, swing, swing_factor, swing_damage, meleetime, is_player, is_monster; + entity target_victim; + vector targpos; + + if(!self.cnt) // set start time of melee + { + self.cnt = time; + W_PlayStrengthSound(self.realowner); + } + + makevectors(self.realowner.v_angle); // update values for v_* vectors + + // calculate swing percentage based on time + meleetime = autocvar_g_balance_shotgun_secondary_melee_time * W_WeaponRateFactor(); + swing = bound(0, (self.cnt + meleetime - time) / meleetime, 10); + f = ((1 - swing) * autocvar_g_balance_shotgun_secondary_melee_traces); + + // check to see if we can still continue, otherwise give up now + if((self.realowner.deadflag != DEAD_NO) && autocvar_g_balance_shotgun_secondary_melee_no_doubleslap) + { + remove(self); + return; + } + + // if okay, perform the traces needed for this frame + for(i=self.swing_prev; i < f; ++i) + { + swing_factor = ((1 - (i / autocvar_g_balance_shotgun_secondary_melee_traces)) * 2 - 1); + + targpos = (self.realowner.origin + self.realowner.view_ofs + + (v_forward * autocvar_g_balance_shotgun_secondary_melee_range) + + (v_up * swing_factor * autocvar_g_balance_shotgun_secondary_melee_swing_up) + + (v_right * swing_factor * autocvar_g_balance_shotgun_secondary_melee_swing_side)); + + WarpZone_traceline_antilag(self, self.realowner.origin + self.realowner.view_ofs, targpos, FALSE, self, ANTILAG_LATENCY(self.realowner)); + + // draw lightning beams for debugging + //te_lightning2(world, targpos, self.realowner.origin + self.realowner.view_ofs + v_forward * 5 - v_up * 5); + //te_customflash(targpos, 40, 2, '1 1 1'); + + is_player = (IS_PLAYER(trace_ent) || trace_ent.classname == "body"); + is_monster = (trace_ent.flags & FL_MONSTER); + + if((trace_fraction < 1) // if trace is good, apply the damage and remove self + && (trace_ent.takedamage == DAMAGE_AIM) + && (trace_ent != self.swing_alreadyhit) + && ((is_player || is_monster) || autocvar_g_balance_shotgun_secondary_melee_nonplayerdamage)) + { + target_victim = trace_ent; // so it persists through other calls + + if(is_player || is_monster) // this allows us to be able to nerf the non-player damage done in e.g. assault or onslaught. + swing_damage = (autocvar_g_balance_shotgun_secondary_damage * min(1, swing_factor + 1)); + else + swing_damage = (autocvar_g_balance_shotgun_secondary_melee_nonplayerdamage * min(1, swing_factor + 1)); + + //print(strcat(self.realowner.netname, " hitting ", target_victim.netname, " with ", strcat(ftos(swing_damage), " damage (factor: ", ftos(swing_factor), ") at "), ftos(time), " seconds.\n")); + + Damage(target_victim, self.realowner, self.realowner, + swing_damage, WEP_SHOTGUN | HITTYPE_SECONDARY, + self.realowner.origin + self.realowner.view_ofs, + v_forward * autocvar_g_balance_shotgun_secondary_force); + + if(accuracy_isgooddamage(self.realowner, target_victim)) { accuracy_add(self.realowner, WEP_SHOTGUN, 0, swing_damage); } + + // draw large red flash for debugging + //te_customflash(targpos, 200, 2, '15 0 0'); + + if(autocvar_g_balance_shotgun_secondary_melee_multihit) // allow multiple hits with one swing, but not against the same player twice. + { + self.swing_alreadyhit = target_victim; + continue; // move along to next trace + } + else + { + remove(self); + return; + } + } + } + + if(time >= self.cnt + meleetime) + { + // melee is finished + remove(self); + return; + } + else + { + // set up next frame + self.swing_prev = i; + self.nextthink = time; + } +} + +void W_Shotgun_Attack2 (void) +{ + sound (self, CH_WEAPON_A, "weapons/shotgun_melee.wav", VOL_BASE, ATTEN_NORM); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_shotgun_secondary_animtime, w_ready); + + entity meleetemp; + meleetemp = spawn(); + meleetemp.realowner = self; + meleetemp.think = shotgun_meleethink; + meleetemp.nextthink = time + autocvar_g_balance_shotgun_secondary_melee_delay * W_WeaponRateFactor(); + W_SetupShot_Range(self, TRUE, 0, "", 0, autocvar_g_balance_shotgun_secondary_damage, autocvar_g_balance_shotgun_secondary_melee_range); +} + +void spawnfunc_weapon_shotgun(); // defined in t_items.qc + +.float shotgun_primarytime; + +float w_shotgun(float req) +{ + float ammo_amount; + if (req == WR_AIM) + if(vlen(self.origin-self.enemy.origin) <= autocvar_g_balance_shotgun_secondary_melee_range) + self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, FALSE); + else + self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, FALSE); + + else if (req == WR_THINK) + { + if(autocvar_g_balance_shotgun_reload_ammo && self.clip_load < autocvar_g_balance_shotgun_primary_ammo) // forced reload + { + // don't force reload an empty shotgun if its melee attack is active + if (!(autocvar_g_balance_shotgun_secondary && self.ammo_shells < autocvar_g_balance_shotgun_primary_ammo)) + weapon_action(self.weapon, WR_RELOAD); + } + else + { + if (self.BUTTON_ATCK) + { + if (time >= self.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary + { + if(weapon_prepareattack(0, autocvar_g_balance_shotgun_primary_animtime)) + { + W_Shotgun_Attack(); + self.shotgun_primarytime = time + autocvar_g_balance_shotgun_primary_refire * W_WeaponRateFactor(); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_shotgun_primary_animtime, w_ready); + } + } + } + } + if (self.clip_load >= 0) // we are not currently reloading + if (!self.crouch) // no crouchmelee please + if (self.BUTTON_ATCK2 && autocvar_g_balance_shotgun_secondary) + if (weapon_prepareattack(1, autocvar_g_balance_shotgun_secondary_refire)) + { + // attempt forcing playback of the anim by switching to another anim (that we never play) here... + weapon_thinkf(WFRAME_FIRE1, 0, W_Shotgun_Attack2); + } + } + else if (req == WR_PRECACHE) + { + precache_model ("models/uziflash.md3"); + precache_model ("models/weapons/g_shotgun.md3"); + precache_model ("models/weapons/v_shotgun.md3"); + precache_model ("models/weapons/h_shotgun.iqm"); + precache_sound ("misc/itempickup.wav"); + precache_sound ("weapons/shotgun_fire.wav"); + precache_sound ("weapons/shotgun_melee.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else + } + else if (req == WR_SETUP) + { + weapon_setup(WEP_SHOTGUN); + self.current_ammo = ammo_shells; + } + else if (req == WR_CHECKAMMO1) + { + ammo_amount = self.ammo_shells >= autocvar_g_balance_shotgun_primary_ammo; + ammo_amount += self.(weapon_load[WEP_SHOTGUN]) >= autocvar_g_balance_shotgun_primary_ammo; + return ammo_amount; + } + else if (req == WR_CHECKAMMO2) + { + // melee attack is always available + return TRUE; + } + else if (req == WR_RELOAD) + { + W_Reload(autocvar_g_balance_shotgun_primary_ammo, autocvar_g_balance_shotgun_reload_ammo, autocvar_g_balance_shotgun_reload_time, "weapons/reload.wav"); + } + else if (req == WR_SUICIDEMESSAGE) + { + return WEAPON_THINKING_WITH_PORTALS; + } + else if (req == WR_KILLMESSAGE) + { + if(w_deathtype & HITTYPE_SECONDARY) + return WEAPON_SHOTGUN_MURDER_SLAP; + else + return WEAPON_SHOTGUN_MURDER; + } + return TRUE; +} +#endif +#ifdef CSQC +.float prevric; +float w_shotgun(float req) +{ + if(req == WR_IMPACTEFFECT) + { + vector org2; + org2 = w_org + w_backoff * 2; + pointparticles(particleeffectnum("shotgun_impact"), org2, w_backoff * 1000, 1); + if(!w_issilent && time - self.prevric > 0.25) + { + if(w_random < 0.0165) + sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTEN_NORM); + else if(w_random < 0.033) + sound(self, CH_SHOTS, "weapons/ric2.wav", VOL_BASE, ATTEN_NORM); + else if(w_random < 0.05) + sound(self, CH_SHOTS, "weapons/ric3.wav", VOL_BASE, ATTEN_NORM); + self.prevric = time; + } + } + else if(req == WR_PRECACHE) + { + precache_sound("weapons/ric1.wav"); + precache_sound("weapons/ric2.wav"); + precache_sound("weapons/ric3.wav"); + } + return TRUE; +} +#endif +#endif diff --git a/qcsrc/server/w_tuba.qc b/qcsrc/server/w_tuba.qc new file mode 100644 index 000000000..2e081095f --- /dev/null +++ b/qcsrc/server/w_tuba.qc @@ -0,0 +1,466 @@ +#ifdef REGISTER_WEAPON +REGISTER_WEAPON( +/* WEP_##id */ TUBA, +/* function */ w_tuba, +/* ammotype */ 0, +/* impulse */ 1, +/* flags */ WEP_FLAG_HIDDEN | WEP_TYPE_SPLASH, +/* rating */ BOT_PICKUP_RATING_MID, +/* model */ "tuba", +/* shortname */ "tuba", +/* xgettext:no-c-format */ +/* fullname */ _("@!#%'n Tuba") +); +#else +#ifdef SVQC +//#define TUBA_NOTE(n) strcat("weapons/tuba_note", ftos(n), ".wav") +.entity tuba_note; +.float tuba_smoketime; +.float tuba_instrument; + +#define MAX_TUBANOTES 32 +.float tuba_lastnotes_last; +.float tuba_lastnotes_cnt; // over +.vector tuba_lastnotes[MAX_TUBANOTES]; + +float W_Tuba_HasPlayed(entity pl, string melody, float instrument, float ignorepitch, float mintempo, float maxtempo) +{ + float i, j, mmin, mmax, nolength; + float n = tokenize_console(melody); + if(n > pl.tuba_lastnotes_cnt) + return FALSE; + float pitchshift = 0; + + if(instrument >= 0) + if(pl.tuba_instrument != instrument) + return FALSE; + + // verify notes... + nolength = FALSE; + for(i = 0; i < n; ++i) + { + vector v = pl.(tuba_lastnotes[mod(pl.tuba_lastnotes_last - i + MAX_TUBANOTES, MAX_TUBANOTES)]); + float ai = stof(argv(n - i - 1)); + float np = floor(ai); + if(ai == np) + nolength = TRUE; + // n counts the last played notes BACKWARDS + // _x is start + // _y is end + // _z is note pitch + if(ignorepitch && i == 0) + { + pitchshift = np - v_z; + } + else + { + if(v_z + pitchshift != np) + return FALSE; + } + } + + // now we know the right NOTES were played + if(!nolength) + { + // verify rhythm... + float ti = 0; + if(maxtempo > 0) + mmin = 240 / maxtempo; // 60 = "0.25 means 1 sec", at 120 0.5 means 1 sec, at 240 1 means 1 sec + else + mmin = 0; + if(mintempo > 0) + mmax = 240 / mintempo; // 60 = "0.25 means 1 sec", at 120 0.5 means 1 sec, at 240 1 means 1 sec + else + mmax = 240; // you won't try THAT hard... (tempo 1) + //printf("initial tempo rules: %f %f\n", mmin, mmax); + + for(i = 0; i < n; ++i) + { + vector vi = pl.(tuba_lastnotes[mod(pl.tuba_lastnotes_last - i + MAX_TUBANOTES, MAX_TUBANOTES)]); + float ai = stof(argv(n - i - 1)); + ti -= 1 / (ai - floor(ai)); + float tj = ti; + for(j = i+1; j < n; ++j) + { + vector vj = pl.(tuba_lastnotes[mod(pl.tuba_lastnotes_last - j + MAX_TUBANOTES, MAX_TUBANOTES)]); + float aj = stof(argv(n - j - 1)); + tj -= (aj - floor(aj)); + + // note i should be at m*ti+b + // note j should be at m*tj+b + // so: + // we have a LINE l, so that + // vi_x <= l(ti) <= vi_y + // vj_x <= l(tj) <= vj_y + // what is m? + + // vi_x <= vi_y <= vj_x <= vj_y + // ti <= tj + //printf("first note: %f to %f, should be %f\n", vi_x, vi_y, ti); + //printf("second note: %f to %f, should be %f\n", vj_x, vj_y, tj); + //printf("m1 = %f\n", (vi_x - vj_y) / (ti - tj)); + //printf("m2 = %f\n", (vi_y - vj_x) / (ti - tj)); + mmin = max(mmin, (vi_x - vj_y) / (ti - tj)); // lower bound + mmax = min(mmax, (vi_y - vj_x) / (ti - tj)); // upper bound + } + } + + if(mmin > mmax) // rhythm fail + return FALSE; + } + + pl.tuba_lastnotes_cnt = 0; + + return TRUE; +} + +void W_Tuba_NoteOff() +{ + // we have a note: + // on: self.spawnshieldtime + // off: time + // note: self.cnt + if(self.owner.tuba_note == self) + { + self.owner.tuba_lastnotes_last = mod(self.owner.tuba_lastnotes_last + 1, MAX_TUBANOTES); + self.owner.(tuba_lastnotes[self.owner.tuba_lastnotes_last]) = eX * self.spawnshieldtime + eY * time + eZ * self.cnt; + self.owner.tuba_note = world; + self.owner.tuba_lastnotes_cnt = bound(0, self.owner.tuba_lastnotes_cnt + 1, MAX_TUBANOTES); + + string s; + s = trigger_magicear_processmessage_forallears(self.owner, 0, world, string_null); + if(s != "") + { + // simulate a server message + switch(self.tuba_instrument) + { + default: + case 0: // Tuba + bprint(strcat("\{1}\{13}* ^3", self.owner.netname, "^3 played on the @!#%'n Tuba: ^7", s, "\n")); + break; + case 1: + bprint(strcat("\{1}\{13}* ^3", self.owner.netname, "^3 played on the @!#%'n Accordeon: ^7", s, "\n")); + break; + case 2: + bprint(strcat("\{1}\{13}* ^3", self.owner.netname, "^3 played on the @!#%'n Klein Bottle: ^7", s, "\n")); + break; + } + } + } + remove(self); +} + +float Tuba_GetNote(entity pl, float hittype) +{ + float note; + float movestate; + movestate = 5; + if(pl.movement_x < 0) movestate -= 3; + if(pl.movement_x > 0) movestate += 3; + if(pl.movement_y < 0) movestate -= 1; + if(pl.movement_y > 0) movestate += 1; +#ifdef GMQCC + note = 0; +#endif + switch(movestate) + { + // layout: originally I wanted + // eb e e#=f + // B c d + // Gb G G# + // but then you only use forward and right key. So to make things more + // interesting, I swapped B with e#. Har har har... + // eb e B + // f=e# c d + // Gb G G# + case 1: note = -6; break; // Gb + case 2: note = -5; break; // G + case 3: note = -4; break; // G# + case 4: note = +5; break; // e# + default: + case 5: note = 0; break; // c + case 6: note = +2; break; // d + case 7: note = +3; break; // eb + case 8: note = +4; break; // e + case 9: note = -1; break; // B + } + if(pl.BUTTON_CROUCH) + note -= 12; + if(pl.BUTTON_JUMP) + note += 12; + if(hittype & HITTYPE_SECONDARY) + note += 7; + + // we support two kinds of tubas, those tuned in Eb and those tuned in C + // kind of tuba currently is player slot number, or team number if in + // teamplay + // that way, holes in the range of notes are "plugged" + if(teamplay) + { + if(pl.team == NUM_TEAM_2 || pl.team == NUM_TEAM_4) + note += 3; + } + else + { + if(pl.clientcolors & 1) + note += 3; + } + + // total range of notes: + // 0 + // *** ** **** + // *** ** **** + // *** ** **** + // *** ** **** + // *** ********************* **** + // -18.........................+12 + // *** ********************* **** + // -18............................+15 + // with jump: ... +24 + // ... +27 + return note; +} + +float W_Tuba_NoteSendEntity(entity to, float sf) +{ + float f; + + msg_entity = to; + if(!sound_allowed(MSG_ONE, self.realowner)) + return FALSE; + + WriteByte(MSG_ENTITY, ENT_CLIENT_TUBANOTE); + WriteByte(MSG_ENTITY, sf); + if(sf & 1) + { + WriteChar(MSG_ENTITY, self.cnt); + f = 0; + if(self.realowner != to) + f |= 1; + f |= 2 * self.tuba_instrument; + WriteByte(MSG_ENTITY, f); + } + if(sf & 2) + { + WriteCoord(MSG_ENTITY, self.origin_x); + WriteCoord(MSG_ENTITY, self.origin_y); + WriteCoord(MSG_ENTITY, self.origin_z); + } + return TRUE; +} + +void W_Tuba_NoteThink() +{ + float dist_mult; + float vol0, vol1; + vector dir0, dir1; + vector v; + entity e; + if(time > self.teleport_time) + { + W_Tuba_NoteOff(); + return; + } + self.nextthink = time; + dist_mult = autocvar_g_balance_tuba_attenuation / autocvar_snd_soundradius; + FOR_EACH_REALCLIENT(e) + if(e != self.realowner) + { + v = self.origin - (e.origin + e.view_ofs); + vol0 = max(0, 1 - vlen(v) * dist_mult); + dir0 = normalize(v); + v = self.realowner.origin - (e.origin + e.view_ofs); + vol1 = max(0, 1 - vlen(v) * dist_mult); + dir1 = normalize(v); + if(fabs(vol0 - vol1) > 0.005) // 0.5 percent change in volume + { + setorigin(self, self.realowner.origin); + self.SendFlags |= 2; + break; + } + if(dir0 * dir1 < 0.9994) // 2 degrees change in angle + { + setorigin(self, self.realowner.origin); + self.SendFlags |= 2; + break; + } + } +} + +void W_Tuba_NoteOn(float hittype) +{ + vector o; + float n; + + W_SetupShot(self, FALSE, 2, "", 0, autocvar_g_balance_tuba_damage); + + n = Tuba_GetNote(self, hittype); + + hittype = 0; + if(self.tuba_instrument & 1) + hittype |= HITTYPE_SECONDARY; + if(self.tuba_instrument & 2) + hittype |= HITTYPE_BOUNCE; + + if(self.tuba_note) + { + if(self.tuba_note.cnt != n || self.tuba_note.tuba_instrument != self.tuba_instrument) + { + entity oldself = self; + self = self.tuba_note; + W_Tuba_NoteOff(); + self = oldself; + } + } + + if (!self.tuba_note) + { + self.tuba_note = spawn(); + self.tuba_note.owner = self.tuba_note.realowner = self; + self.tuba_note.cnt = n; + self.tuba_note.tuba_instrument = self.tuba_instrument; + self.tuba_note.think = W_Tuba_NoteThink; + self.tuba_note.nextthink = time; + self.tuba_note.spawnshieldtime = time; + Net_LinkEntity(self.tuba_note, FALSE, 0, W_Tuba_NoteSendEntity); + } + + self.tuba_note.teleport_time = time + autocvar_g_balance_tuba_refire * 2 * W_WeaponRateFactor(); // so it can get prolonged safely + + //sound(self, c, TUBA_NOTE(n), bound(0, VOL_BASE * cvar("g_balance_tuba_volume"), 1), autocvar_g_balance_tuba_attenuation); + RadiusDamage(self, self, autocvar_g_balance_tuba_damage, autocvar_g_balance_tuba_edgedamage, autocvar_g_balance_tuba_radius, world, autocvar_g_balance_tuba_force, hittype | WEP_TUBA, world); + + o = gettaginfo(self.exteriorweaponentity, 0); + if(time > self.tuba_smoketime) + { + pointparticles(particleeffectnum("smoke_ring"), o + v_up * 45 + v_right * -6 + v_forward * 8, v_up * 100, 1); + self.tuba_smoketime = time + 0.25; + } +} + +void spawnfunc_weapon_tuba (void) +{ + weapon_defaultspawnfunc(WEP_TUBA); +} + +float w_tuba(float req) +{ + if (req == WR_AIM) + { + // bots cannot play the Tuba well yet + // I think they should start with the recorder first + if(vlen(self.origin - self.enemy.origin) < autocvar_g_balance_tuba_radius) + { + if(random() > 0.5) + self.BUTTON_ATCK = 1; + else + self.BUTTON_ATCK2 = 1; + } + } + else if (req == WR_THINK) + { + if (self.BUTTON_ATCK) + if (weapon_prepareattack(0, autocvar_g_balance_tuba_refire)) + { + W_Tuba_NoteOn(0); + //weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_tuba_animtime, w_ready); + weapon_thinkf(WFRAME_IDLE, autocvar_g_balance_tuba_animtime, w_ready); + } + if (self.BUTTON_ATCK2) + if (weapon_prepareattack(1, autocvar_g_balance_tuba_refire)) + { + W_Tuba_NoteOn(HITTYPE_SECONDARY); + //weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_tuba_animtime, w_ready); + weapon_thinkf(WFRAME_IDLE, autocvar_g_balance_tuba_animtime, w_ready); + } + if(self.tuba_note) + { + if(!self.BUTTON_ATCK && !self.BUTTON_ATCK2) + { + entity oldself = self; + self = self.tuba_note; + W_Tuba_NoteOff(); + self = oldself; + } + } + } + else if (req == WR_PRECACHE) + { + precache_model ("models/weapons/g_tuba.md3"); + precache_model ("models/weapons/v_tuba.md3"); + precache_model ("models/weapons/h_tuba.iqm"); + precache_model ("models/weapons/v_akordeon.md3"); + precache_model ("models/weapons/h_akordeon.iqm"); + precache_model ("models/weapons/v_kleinbottle.md3"); + precache_model ("models/weapons/h_kleinbottle.iqm"); + + //float i; + //for(i = -18; i <= +27; ++i) + // precache_sound(TUBA_NOTE(i)); + } + else if (req == WR_SETUP) + { + weapon_setup(WEP_TUBA); + self.current_ammo = ammo_none; + self.tuba_instrument = 0; + } + else if (req == WR_RELOAD) + { + // switch to alternate instruments :) + if(self.weaponentity.state == WS_READY) + { + switch(self.tuba_instrument) + { + case 0: + self.tuba_instrument = 1; + self.weaponname = "akordeon"; + break; + case 1: + self.tuba_instrument = 2; + self.weaponname = "kleinbottle"; + break; + case 2: + self.tuba_instrument = 0; + self.weaponname = "tuba"; + break; + } + W_SetupShot(self, FALSE, 0, "", 0, 0); + pointparticles(particleeffectnum("teleport"), w_shotorg, '0 0 0', 1); + self.weaponentity.state = WS_INUSE; + weapon_thinkf(WFRAME_RELOAD, 0.5, w_ready); + } + } + else if (req == WR_CHECKAMMO1) + return TRUE; // TODO use fuel? + else if (req == WR_CHECKAMMO2) + return TRUE; // TODO use fuel? + else if (req == WR_SUICIDEMESSAGE) + { + if(w_deathtype & HITTYPE_BOUNCE) + return WEAPON_KLEINBOTTLE_SUICIDE; + else if(w_deathtype & HITTYPE_SECONDARY) + return WEAPON_ACCORDEON_SUICIDE; + else + return WEAPON_TUBA_SUICIDE; + } + else if (req == WR_KILLMESSAGE) + { + if(w_deathtype & HITTYPE_BOUNCE) + return WEAPON_KLEINBOTTLE_MURDER; + else if(w_deathtype & HITTYPE_SECONDARY) + return WEAPON_ACCORDEON_MURDER; + else + return WEAPON_TUBA_MURDER; + } + return TRUE; +} +#endif +#ifdef CSQC +float w_tuba(float req) +{ + // nothing to do here; particles of tuba are handled differently + + return TRUE; +} +#endif +#endif diff --git a/qcsrc/server/w_uzi.qc b/qcsrc/server/w_uzi.qc new file mode 100644 index 000000000..4fb604743 --- /dev/null +++ b/qcsrc/server/w_uzi.qc @@ -0,0 +1,337 @@ +#ifdef REGISTER_WEAPON +REGISTER_WEAPON( +/* WEP_##id */ UZI, +/* function */ w_uzi, +/* ammotype */ IT_NAILS, +/* impulse */ 3, +/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN, +/* rating */ BOT_PICKUP_RATING_MID, +/* model */ "uzi", +/* shortname */ "uzi", +/* fullname */ _("Machine Gun") +); +#else +#ifdef SVQC + +// leilei's fancy muzzleflash stuff +void UZI_Flash_Go() +{ + self.frame = self.frame + 2; + self.scale = self.scale * 0.5; + self.alpha = self.alpha - 0.25; + self.nextthink = time + 0.05; + + if (self.alpha <= 0) + { + self.think = SUB_Remove; + self.nextthink = time; + self.realowner.muzzle_flash = world; + return; + } + +} + +void UziFlash() +{ + if (self.muzzle_flash == world) + self.muzzle_flash = spawn(); + + // muzzle flash for 1st person view + setmodel(self.muzzle_flash, "models/uziflash.md3"); // precision set below + + self.muzzle_flash.scale = 0.75; + self.muzzle_flash.think = UZI_Flash_Go; + self.muzzle_flash.nextthink = time + 0.02; + self.muzzle_flash.frame = 2; + self.muzzle_flash.alpha = 0.75; + self.muzzle_flash.angles_z = random() * 180; + self.muzzle_flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION; + self.muzzle_flash.owner = self.muzzle_flash.realowner = self; +} + +void W_UZI_Attack (float deathtype) +{ + W_SetupShot (self, TRUE, 0, "weapons/uzi_fire.wav", CH_WEAPON_A, ((self.misc_bulletcounter == 1) ? autocvar_g_balance_uzi_first_damage : autocvar_g_balance_uzi_sustained_damage)); + if (!autocvar_g_norecoil) + { + self.punchangle_x = random () - 0.5; + self.punchangle_y = random () - 0.5; + } + + // this attack_finished just enforces a cooldown at the end of a burst + ATTACK_FINISHED(self) = time + autocvar_g_balance_uzi_first_refire * W_WeaponRateFactor(); + + if (self.misc_bulletcounter == 1) + fireBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_first_spread, autocvar_g_balance_uzi_solidpenetration, autocvar_g_balance_uzi_first_damage, autocvar_g_balance_uzi_first_force, deathtype, 0); + else + fireBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_sustained_spread, autocvar_g_balance_uzi_solidpenetration, autocvar_g_balance_uzi_sustained_damage, autocvar_g_balance_uzi_sustained_force, deathtype, 0); + + pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); + + UziFlash(); + W_AttachToShotorg(self.muzzle_flash, '5 0 0'); + + // casing code + if (autocvar_g_casings >= 2) + SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self); + + if (self.misc_bulletcounter == 1) + W_DecreaseAmmo(ammo_nails, autocvar_g_balance_uzi_first_ammo, autocvar_g_balance_uzi_reload_ammo); + else + W_DecreaseAmmo(ammo_nails, autocvar_g_balance_uzi_sustained_ammo, autocvar_g_balance_uzi_reload_ammo); +} + +// weapon frames +void uzi_fire1_02() +{ + if(self.weapon != self.switchweapon) // abort immediately if switching + { + w_ready(); + return; + } + if (self.BUTTON_ATCK) + { + if (!weapon_action(self.weapon, WR_CHECKAMMO2)) + if (!(self.items & IT_UNLIMITED_WEAPON_AMMO)) + { + W_SwitchWeapon_Force(self, w_getbestweapon(self)); + w_ready(); + return; + } + self.misc_bulletcounter = self.misc_bulletcounter + 1; + W_UZI_Attack(WEP_UZI); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, uzi_fire1_02); + } + else + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, w_ready); +} + + +void uzi_mode1_fire_auto() +{ + float uzi_spread; + + if (!self.BUTTON_ATCK) + { + w_ready(); + return; + } + + if (!weapon_action(self.weapon, WR_CHECKAMMO1)) + if (!(self.items & IT_UNLIMITED_WEAPON_AMMO)) + { + W_SwitchWeapon_Force(self, w_getbestweapon(self)); + w_ready(); + return; + } + + W_DecreaseAmmo(ammo_nails, autocvar_g_balance_uzi_sustained_ammo, autocvar_g_balance_uzi_reload_ammo); + + W_SetupShot (self, TRUE, 0, "weapons/uzi_fire.wav", CH_WEAPON_A, autocvar_g_balance_uzi_sustained_damage); + if (!autocvar_g_norecoil) + { + self.punchangle_x = random () - 0.5; + self.punchangle_y = random () - 0.5; + } + + uzi_spread = bound(autocvar_g_balance_uzi_spread_min, autocvar_g_balance_uzi_spread_min + (autocvar_g_balance_uzi_spread_add * self.misc_bulletcounter), autocvar_g_balance_uzi_spread_max); + fireBullet(w_shotorg, w_shotdir, uzi_spread, autocvar_g_balance_uzi_solidpenetration, autocvar_g_balance_uzi_sustained_damage, autocvar_g_balance_uzi_sustained_force, WEP_UZI, 0); + + self.misc_bulletcounter = self.misc_bulletcounter + 1; + + pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); + + UziFlash(); + W_AttachToShotorg(self.muzzle_flash, '5 0 0'); + + if (autocvar_g_casings >= 2) // casing code + SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self); + + ATTACK_FINISHED(self) = time + autocvar_g_balance_uzi_first_refire * W_WeaponRateFactor(); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, uzi_mode1_fire_auto); +} + +void uzi_mode1_fire_burst() +{ + W_SetupShot (self, TRUE, 0, "weapons/uzi_fire.wav", CH_WEAPON_A, autocvar_g_balance_uzi_sustained_damage); + if (!autocvar_g_norecoil) + { + self.punchangle_x = random () - 0.5; + self.punchangle_y = random () - 0.5; + } + + fireBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_burst_spread, autocvar_g_balance_uzi_solidpenetration, autocvar_g_balance_uzi_sustained_damage, autocvar_g_balance_uzi_sustained_force, WEP_UZI, 0); + + pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); + + UziFlash(); + W_AttachToShotorg(self.muzzle_flash, '5 0 0'); + + if (autocvar_g_casings >= 2) // casing code + SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self); + + self.misc_bulletcounter = self.misc_bulletcounter + 1; + if (self.misc_bulletcounter == 0) + { + ATTACK_FINISHED(self) = time + autocvar_g_balance_uzi_burst_refire2 * W_WeaponRateFactor(); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_uzi_burst_animtime, w_ready); + } + else + { + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_uzi_burst_refire, uzi_mode1_fire_burst); + } + +} + +void spawnfunc_weapon_machinegun(); // defined in t_items.qc + +float w_uzi(float req) +{ + float ammo_amount; + if (req == WR_AIM) + if(vlen(self.origin-self.enemy.origin) < 3000 - bound(0, skill, 10) * 200) + self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, FALSE); + else + { + self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, FALSE); + } + else if (req == WR_THINK) + { + if(autocvar_g_balance_uzi_reload_ammo && self.clip_load < min(max(autocvar_g_balance_uzi_sustained_ammo, autocvar_g_balance_uzi_first_ammo), autocvar_g_balance_uzi_burst_ammo)) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else if(autocvar_g_balance_uzi_mode == 1) + { + if (self.BUTTON_ATCK) + if (weapon_prepareattack(0, 0)) + { + self.misc_bulletcounter = 0; + uzi_mode1_fire_auto(); + } + + if(self.BUTTON_ATCK2) + if(weapon_prepareattack(1, 0)) + { + if (!weapon_action(self.weapon, WR_CHECKAMMO2)) + if (!(self.items & IT_UNLIMITED_WEAPON_AMMO)) + { + W_SwitchWeapon_Force(self, w_getbestweapon(self)); + w_ready(); + return FALSE; + } + + W_DecreaseAmmo(ammo_nails, autocvar_g_balance_uzi_burst_ammo, autocvar_g_balance_uzi_reload_ammo); + + self.misc_bulletcounter = autocvar_g_balance_uzi_burst * -1; + uzi_mode1_fire_burst(); + } + } + else + { + + if (self.BUTTON_ATCK) + if (weapon_prepareattack(0, 0)) + { + self.misc_bulletcounter = 1; + W_UZI_Attack(WEP_UZI); // sets attack_finished + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, uzi_fire1_02); + } + + if (self.BUTTON_ATCK2 && autocvar_g_balance_uzi_first) + if (weapon_prepareattack(1, 0)) + { + self.misc_bulletcounter = 1; + W_UZI_Attack(WEP_UZI | HITTYPE_SECONDARY); // sets attack_finished + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_uzi_first_refire, w_ready); + } + } + } + else if (req == WR_PRECACHE) + { + precache_model ("models/uziflash.md3"); + precache_model ("models/weapons/g_uzi.md3"); + precache_model ("models/weapons/v_uzi.md3"); + precache_model ("models/weapons/h_uzi.iqm"); + precache_sound ("weapons/uzi_fire.wav"); + //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else + } + else if (req == WR_SETUP) + { + weapon_setup(WEP_UZI); + self.current_ammo = ammo_nails; + } + else if (req == WR_CHECKAMMO1) + { + if(autocvar_g_balance_uzi_mode == 1) + ammo_amount = self.ammo_nails >= autocvar_g_balance_uzi_sustained_ammo; + else + ammo_amount = self.ammo_nails >= autocvar_g_balance_uzi_first_ammo; + + if(autocvar_g_balance_uzi_reload_ammo) + { + if(autocvar_g_balance_uzi_mode == 1) + ammo_amount += self.(weapon_load[WEP_UZI]) >= autocvar_g_balance_uzi_sustained_ammo; + else + ammo_amount += self.(weapon_load[WEP_UZI]) >= autocvar_g_balance_uzi_first_ammo; + } + return ammo_amount; + } + else if (req == WR_CHECKAMMO2) + { + if(autocvar_g_balance_uzi_mode == 1) + ammo_amount = self.ammo_nails >= autocvar_g_balance_uzi_burst_ammo; + else + ammo_amount = self.ammo_nails >= autocvar_g_balance_uzi_first_ammo; + + if(autocvar_g_balance_uzi_reload_ammo) + { + if(autocvar_g_balance_uzi_mode == 1) + ammo_amount += self.(weapon_load[WEP_UZI]) >= autocvar_g_balance_uzi_burst_ammo; + else + ammo_amount += self.(weapon_load[WEP_UZI]) >= autocvar_g_balance_uzi_first_ammo; + } + return ammo_amount; + } + else if (req == WR_RELOAD) + { + W_Reload(min(max(autocvar_g_balance_uzi_sustained_ammo, autocvar_g_balance_uzi_first_ammo), autocvar_g_balance_uzi_burst_ammo), autocvar_g_balance_uzi_reload_ammo, autocvar_g_balance_uzi_reload_time, "weapons/reload.wav"); + } + else if (req == WR_SUICIDEMESSAGE) + { + return WEAPON_THINKING_WITH_PORTALS; + } + else if (req == WR_KILLMESSAGE) + { + if(w_deathtype & HITTYPE_SECONDARY) + return WEAPON_UZI_MURDER_SNIPE; + else + return WEAPON_UZI_MURDER_SPRAY; + } + return TRUE; +} +#endif +#ifdef CSQC +float w_uzi(float req) +{ + if(req == WR_IMPACTEFFECT) + { + vector org2; + org2 = w_org + w_backoff * 2; + pointparticles(particleeffectnum("machinegun_impact"), org2, w_backoff * 1000, 1); + if(!w_issilent) + if(w_random < 0.05) + sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTEN_NORM); + else if(w_random < 0.1) + sound(self, CH_SHOTS, "weapons/ric2.wav", VOL_BASE, ATTEN_NORM); + else if(w_random < 0.2) + sound(self, CH_SHOTS, "weapons/ric3.wav", VOL_BASE, ATTEN_NORM); + } + else if(req == WR_PRECACHE) + { + precache_sound("weapons/ric1.wav"); + precache_sound("weapons/ric2.wav"); + precache_sound("weapons/ric3.wav"); + } + return TRUE; +} +#endif +#endif diff --git a/qcsrc/server/weapons/accuracy.qc b/qcsrc/server/weapons/accuracy.qc deleted file mode 100644 index 09d42332a..000000000 --- a/qcsrc/server/weapons/accuracy.qc +++ /dev/null @@ -1,124 +0,0 @@ -float accuracy_byte(float n, float d) -{ - //printf("accuracy: %d / %d\n", n, d); - if(n <= 0) - return 0; - if(n > d) - return 255; - return 1 + rint(n * 100.0 / d); -} - -float accuracy_send(entity to, float sf) -{ - float w, f; - entity a; - WriteByte(MSG_ENTITY, ENT_CLIENT_ACCURACY); - - a = self.owner; - if(IS_SPEC(a)) - a = a.enemy; - a = a.accuracy; - - if(to != a.owner) - if (!(self.owner.cvar_cl_accuracy_data_share && autocvar_sv_accuracy_data_share)) - sf = 0; - // note: zero sendflags can never be sent... so we can use that to say that we send no accuracy! - WriteInt24_t(MSG_ENTITY, sf); - if(sf == 0) - return TRUE; - // note: we know that client and server agree about SendFlags... - for(w = 0, f = 1; w <= WEP_LAST - WEP_FIRST; ++w) - { - if(sf & f) - WriteByte(MSG_ENTITY, accuracy_byte(self.(accuracy_hit[w]), self.(accuracy_fired[w]))); - if(f == 0x800000) - f = 1; - else - f *= 2; - } - return TRUE; -} - -// init/free -void accuracy_init(entity e) -{ - e.accuracy = spawn(); - e.accuracy.owner = e; - e.accuracy.classname = "accuracy"; - e.accuracy.drawonlytoclient = e; - Net_LinkEntity(e.accuracy, FALSE, 0, accuracy_send); -} - -void accuracy_free(entity e) -{ - remove(e.accuracy); -} - -// force a resend of a player's accuracy stats -void accuracy_resend(entity e) -{ - e.accuracy.SendFlags = 0xFFFFFF; -} - -// update accuracy stats -.float hit_time; -.float fired_time; - -void accuracy_add(entity e, float w, float fired, float hit) -{ - entity a; - float b; - if(IS_INDEPENDENT_PLAYER(e)) - return; - a = e.accuracy; - if(!a || !(hit || fired)) - return; - w -= WEP_FIRST; - b = accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w])); - if(hit) - a.(accuracy_hit[w]) += hit; - if(fired) - a.(accuracy_fired[w]) += fired; - - if(hit && a.hit_time != time) // only run this once per frame - { - a.(accuracy_cnt_hit[w]) += 1; - a.hit_time = time; - } - - if(fired && a.fired_time != time) // only run this once per frame - { - a.(accuracy_cnt_fired[w]) += 1; - a.fired_time = time; - } - - if(b == accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w]))) - return; - w = pow(2, mod(w, 24)); - a.SendFlags |= w; - FOR_EACH_CLIENT(a) - if(IS_SPEC(a)) - if(a.enemy == e) - a.SendFlags |= w; -} - -float accuracy_isgooddamage(entity attacker, entity targ) -{ - frag_attacker = attacker; - frag_target = targ; - float mutator_check = MUTATOR_CALLHOOK(AccuracyTargetValid); - - if(!warmup_stage) - if(targ.deadflag == DEAD_NO) - if(mutator_check == MUT_ACCADD_INVALID || (mutator_check == MUT_ACCADD_VALID && IS_CLIENT(targ))) - if(DIFF_TEAM(attacker, targ)) - return TRUE; - return FALSE; -} - -float accuracy_canbegooddamage(entity attacker) -{ - if(!warmup_stage) - return TRUE; - return FALSE; -} diff --git a/qcsrc/server/weapons/accuracy.qh b/qcsrc/server/weapons/accuracy.qh deleted file mode 100644 index 4cd43ee8a..000000000 --- a/qcsrc/server/weapons/accuracy.qh +++ /dev/null @@ -1,25 +0,0 @@ -.float cvar_cl_accuracy_data_share; -.float cvar_cl_accuracy_data_receive; - -.entity accuracy; -.float accuracy_frags[WEP_MAXCOUNT]; - -.float accuracy_hit[WEP_MAXCOUNT]; -.float accuracy_fired[WEP_MAXCOUNT]; -.float accuracy_cnt_hit[WEP_MAXCOUNT]; -.float accuracy_cnt_fired[WEP_MAXCOUNT]; - - -// init/free -void accuracy_init(entity e); -void accuracy_free(entity e); - -// force a resend of a player's accuracy stats -void accuracy_resend(entity e); - -// update accuracy stats -void accuracy_add(entity e, float w, float fired, float hit); - -// helper -float accuracy_isgooddamage(entity attacker, entity targ); -float accuracy_canbegooddamage(entity attacker); diff --git a/qcsrc/server/weapons/common.qc b/qcsrc/server/weapons/common.qc deleted file mode 100644 index 6e54cb060..000000000 --- a/qcsrc/server/weapons/common.qc +++ /dev/null @@ -1,89 +0,0 @@ - -void W_GiveWeapon (entity e, float wep) -{ - entity oldself; - - if (!wep) - return; - - e.weapons |= WepSet_FromWeapon(wep); - - oldself = self; - self = e; - - if(IS_PLAYER(other)) - { Send_Notification(NOTIF_ONE, other, MSG_MULTI, ITEM_WEAPON_GOT, wep); } - - self = oldself; -} - -void W_PlayStrengthSound(entity player) // void W_PlayStrengthSound -{ - if((player.items & IT_STRENGTH) - && ((time > player.prevstrengthsound + autocvar_sv_strengthsound_antispam_time) // prevent insane sound spam - || (time > player.prevstrengthsoundattempt + autocvar_sv_strengthsound_antispam_refire_threshold))) - { - sound(player, CH_TRIGGER, "weapons/strength_fire.wav", VOL_BASE, ATTEN_NORM); - player.prevstrengthsound = time; - } - player.prevstrengthsoundattempt = time; -} - -float W_CheckProjectileDamage(entity inflictor, entity projowner, float deathtype, float exception) -{ - float is_from_contents = (deathtype == DEATH_SLIME || deathtype == DEATH_LAVA); - float is_from_owner = (inflictor == projowner); - float is_from_exception = (exception != -1); - - //dprint(strcat("W_CheckProjectileDamage: from_contents ", ftos(is_from_contents), " : from_owner ", ftos(is_from_owner), " : exception ", strcat(ftos(is_from_exception), " (", ftos(exception), "). \n"))); - - if(autocvar_g_projectiles_damage <= -2) - { - return FALSE; // no damage to projectiles at all, not even with the exceptions - } - else if(autocvar_g_projectiles_damage == -1) - { - if(is_from_exception) - return (exception); // if exception is detected, allow it to override - else - return FALSE; // otherwise, no other damage is allowed - } - else if(autocvar_g_projectiles_damage == 0) - { - if(is_from_exception) - return (exception); // if exception is detected, allow it to override - else if(!is_from_contents) - return FALSE; // otherwise, only allow damage from contents - } - else if(autocvar_g_projectiles_damage == 1) - { - if(is_from_exception) - return (exception); // if exception is detected, allow it to override - else if(!(is_from_contents || is_from_owner)) - return FALSE; // otherwise, only allow self damage and damage from contents - } - else if(autocvar_g_projectiles_damage == 2) // allow any damage, but override for exceptions - { - if(is_from_exception) - return (exception); // if exception is detected, allow it to override - } - - return TRUE; // if none of these return, then allow damage anyway. -} - -void W_PrepareExplosionByDamage(entity attacker, void() explode) -{ - self.takedamage = DAMAGE_NO; - self.event_damage = func_null; - - if(IS_CLIENT(attacker) && !autocvar_g_projectiles_keep_owner) - { - self.owner = attacker; - self.realowner = attacker; - } - - // do not explode NOW but in the NEXT FRAME! - // because recursive calls to RadiusDamage are not allowed - self.nextthink = time; - self.think = explode; -} diff --git a/qcsrc/server/weapons/common.qh b/qcsrc/server/weapons/common.qh deleted file mode 100644 index 8f9454ed5..000000000 --- a/qcsrc/server/weapons/common.qh +++ /dev/null @@ -1,7 +0,0 @@ - -void W_GiveWeapon (entity e, float wep); -.float prevstrengthsound; -.float prevstrengthsoundattempt; -void W_PlayStrengthSound(entity player); -float W_CheckProjectileDamage(entity inflictor, entity projowner, float deathtype, float exception); -void W_PrepareExplosionByDamage(entity attacker, void() explode); diff --git a/qcsrc/server/weapons/csqcprojectile.qc b/qcsrc/server/weapons/csqcprojectile.qc deleted file mode 100644 index 3dd93c058..000000000 --- a/qcsrc/server/weapons/csqcprojectile.qc +++ /dev/null @@ -1,114 +0,0 @@ -.float csqcprojectile_type; - -float CSQCProjectile_SendEntity(entity to, float sf) -{ - float ft, fr; - - // note: flag 0x08 = no trail please (teleport bit) - sf = sf & 0x0F; - - if(self.csqcprojectile_clientanimate) - sf |= 0x80; // client animated, not interpolated - - if(self.flags & FL_ONGROUND) - sf |= 0x40; - - ft = fr = 0; - if(self.fade_time != 0 || self.fade_rate != 0) - { - ft = (self.fade_time - time) / sys_frametime; - fr = (1 / self.fade_rate) / sys_frametime; - if(ft <= 255 && fr <= 255 && fr >= 1) - sf |= 0x20; - } - - if(self.gravity != 0) - sf |= 0x10; - - WriteByte(MSG_ENTITY, ENT_CLIENT_PROJECTILE); - WriteByte(MSG_ENTITY, sf); - - if(sf & 1) - { - WriteCoord(MSG_ENTITY, self.origin_x); - WriteCoord(MSG_ENTITY, self.origin_y); - WriteCoord(MSG_ENTITY, self.origin_z); - - if(sf & 0x80) - { - WriteCoord(MSG_ENTITY, self.velocity_x); - WriteCoord(MSG_ENTITY, self.velocity_y); - WriteCoord(MSG_ENTITY, self.velocity_z); - if(sf & 0x10) - WriteCoord(MSG_ENTITY, self.gravity); - } - - if(sf & 0x20) - { - WriteByte(MSG_ENTITY, ft); - WriteByte(MSG_ENTITY, fr); - } - - WriteByte(MSG_ENTITY, self.realowner.team); - } - - if(sf & 2) - WriteByte(MSG_ENTITY, self.csqcprojectile_type); // TODO maybe put this into sf? - - return 1; -} - -.vector csqcprojectile_oldorigin; -void CSQCProjectile_Check(entity e) -{ - if(e.csqcprojectile_clientanimate) - if(e.flags & FL_ONGROUND) - if(e.origin != e.csqcprojectile_oldorigin) - UpdateCSQCProjectile(e); - e.csqcprojectile_oldorigin = e.origin; -} - -void CSQCProjectile(entity e, float clientanimate, float type, float docull) -{ - Net_LinkEntity(e, docull, 0, CSQCProjectile_SendEntity); - - e.csqcprojectile_clientanimate = clientanimate; - - if(e.movetype == MOVETYPE_TOSS || e.movetype == MOVETYPE_BOUNCE) - { - if(e.gravity == 0) - e.gravity = 1; - } - else - e.gravity = 0; - - if(!sound_allowed(MSG_BROADCAST, e)) - type |= 0x80; - e.csqcprojectile_type = type; -} - -void UpdateCSQCProjectile(entity e) -{ - if(e.SendEntity == CSQCProjectile_SendEntity) - { - // send new origin data - e.SendFlags |= 0x01; - } -// FIXME HACK - else if(e.SendEntity == ItemSend) - { - ItemUpdate(e); - } -// END HACK -} - -void UpdateCSQCProjectileAfterTeleport(entity e) -{ - if(e.SendEntity == CSQCProjectile_SendEntity) - { - // send new origin data - e.SendFlags |= 0x01; - // mark as teleported - e.SendFlags |= 0x08; - } -} diff --git a/qcsrc/server/weapons/csqcprojectile.qh b/qcsrc/server/weapons/csqcprojectile.qh deleted file mode 100644 index e00c0988b..000000000 --- a/qcsrc/server/weapons/csqcprojectile.qh +++ /dev/null @@ -1,6 +0,0 @@ -.float csqcprojectile_clientanimate; - -void CSQCProjectile(entity e, float clientanimate, float type, float docull); -void UpdateCSQCProjectile(entity e); -void UpdateCSQCProjectileAfterTeleport(entity e); -void CSQCProjectile_Check(entity e); diff --git a/qcsrc/server/weapons/hitplot.qc b/qcsrc/server/weapons/hitplot.qc deleted file mode 100644 index 685741dab..000000000 --- a/qcsrc/server/weapons/hitplot.qc +++ /dev/null @@ -1,91 +0,0 @@ -vector W_HitPlotUnnormalizedUntransform(vector screenforward, vector screenright, vector screenup, vector v) -{ - vector ret; - ret_x = screenright * v; - ret_y = screenup * v; - ret_z = screenforward * v; - return ret; -} - -vector W_HitPlotNormalizedUntransform(vector org, entity targ, vector screenforward, vector screenright, vector screenup, vector v) -{ - float i, j, k; - vector mi, ma, thisv, myv, ret; - - myv = W_HitPlotUnnormalizedUntransform(screenforward, screenright, screenup, org); - - // x = 0..1 relative to hitbox; y = 0..1 relative to hitbox; z = distance - - mi = ma = targ.origin + 0.5 * (targ.mins + targ.maxs); - for(i = 0; i < 2; ++i) for(j = 0; j < 2; ++j) for(k = 0; k < 2; ++k) - { - thisv = targ.origin; - if(i) thisv_x += targ.maxs_x; else thisv_x += targ.mins_x; - if(j) thisv_y += targ.maxs_y; else thisv_y += targ.mins_y; - if(k) thisv_z += targ.maxs_z; else thisv_z += targ.mins_z; - thisv = W_HitPlotUnnormalizedUntransform(screenforward, screenright, screenup, thisv); - if(i || j || k) - { - if(mi_x > thisv_x) mi_x = thisv_x; if(ma_x < thisv_x) ma_x = thisv_x; - if(mi_y > thisv_y) mi_y = thisv_y; if(ma_y < thisv_y) ma_y = thisv_y; - //if(mi_z > thisv_z) mi_z = thisv_z; if(ma_z < thisv_z) ma_y = thisv_z; - } - else - { - // first run - mi = ma = thisv; - } - } - - thisv = W_HitPlotUnnormalizedUntransform(screenforward, screenright, screenup, v); - ret_x = (thisv_x - mi_x) / (ma_x - mi_x); - ret_y = (thisv_y - mi_y) / (ma_y - mi_y); - ret_z = thisv_z - myv_z; - return ret; -} - -void W_HitPlotAnalysis(entity player, vector screenforward, vector screenright, vector screenup) -{ - vector hitplot; - vector org; - float lag; - - if(player.hitplotfh >= 0) - { - lag = ANTILAG_LATENCY(player); - if(lag < 0.001) - lag = 0; - if(!IS_REAL_CLIENT(player)) - lag = 0; // only antilag for clients - - org = player.origin + player.view_ofs; - traceline_antilag_force(player, org, org + screenforward * MAX_SHOT_DISTANCE, MOVE_NORMAL, player, lag); - if(IS_CLIENT(trace_ent) || (trace_ent.flags & FL_MONSTER)) - { - antilag_takeback(trace_ent, time - lag); - hitplot = W_HitPlotNormalizedUntransform(org, trace_ent, screenforward, screenright, screenup, trace_endpos); - antilag_restore(trace_ent); - fputs(player.hitplotfh, strcat(ftos(hitplot_x), " ", ftos(hitplot_y), " ", ftos(hitplot_z), " ", ftos(player.switchweapon), "\n")); - //print(strcat(ftos(hitplot_x), " ", ftos(hitplot_y), " ", ftos(hitplot_z), "\n")); - } - } -} - -void W_HitPlotOpen(entity player) -{ - if(autocvar_g_hitplots || strstrofs(strcat(" ", autocvar_g_hitplots_individuals, " "), strcat(" ", player.netaddress, " "), 0) >= 0) - { - player.hitplotfh = fopen(strcat("hits-", matchid, "-", player.netaddress, "-", ftos(player.playerid), ".plot"), FILE_WRITE); - fputs(player.hitplotfh, strcat("#name ", player.netname, "\n")); - } - else { player.hitplotfh = -1; } -} - -void W_HitPlotClose(entity player) -{ - if(player.hitplotfh >= 0) - { - fclose(player.hitplotfh); - player.hitplotfh = -1; - } -} diff --git a/qcsrc/server/weapons/hitplot.qh b/qcsrc/server/weapons/hitplot.qh deleted file mode 100644 index 9bc8ff303..000000000 --- a/qcsrc/server/weapons/hitplot.qh +++ /dev/null @@ -1,5 +0,0 @@ -.float hitplotfh; - -void W_HitPlotAnalysis(entity player, vector screenforward, vector screenright, vector screenup); -void W_HitPlotOpen(entity player); -void W_HitPlotClose(entity player); diff --git a/qcsrc/server/weapons/selection.qc b/qcsrc/server/weapons/selection.qc deleted file mode 100644 index 482b3180a..000000000 --- a/qcsrc/server/weapons/selection.qc +++ /dev/null @@ -1,283 +0,0 @@ -// switch between weapons -void Send_WeaponComplain(entity e, float wpn, float type) -{ - msg_entity = e; - WriteByte(MSG_ONE, SVC_TEMPENTITY); - WriteByte(MSG_ONE, TE_CSQC_WEAPONCOMPLAIN); - WriteByte(MSG_ONE, wpn); - WriteByte(MSG_ONE, type); -} - -float client_hasweapon(entity cl, float wpn, float andammo, float complain) -{ - float f; - entity oldself; - - if(time < self.hasweapon_complain_spam) - complain = 0; - - if(wpn == WEP_HOOK && !g_grappling_hook && autocvar_g_nades && !((cl.weapons | weaponsInMap) & WepSet_FromWeapon(wpn))) - complain = 0; - - if(complain) - self.hasweapon_complain_spam = time + 0.2; - - if (wpn < WEP_FIRST || wpn > WEP_LAST) - { - if (complain) - sprint(self, "Invalid weapon\n"); - return FALSE; - } - if (cl.weapons & WepSet_FromWeapon(wpn)) - { - if (andammo) - { - if(cl.items & IT_UNLIMITED_WEAPON_AMMO) - { - f = 1; - } - else - { - oldself = self; - self = cl; - f = WEP_ACTION(wpn, WR_CHECKAMMO1); - f = f + WEP_ACTION(wpn, WR_CHECKAMMO2); - - // always allow selecting the Mine Layer if we placed mines, so that we can detonate them - 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 (complain) - if(IS_REAL_CLIENT(cl)) - { - play2(cl, "weapons/unavailable.wav"); - Send_WeaponComplain (cl, wpn, 0); - } - return FALSE; - } - } - return TRUE; - } - if (complain) - { - // DRESK - 3/16/07 - // Report Proper Weapon Status / Modified Weapon Ownership Message - if (weaponsInMap & WepSet_FromWeapon(wpn)) - { - Send_WeaponComplain(cl, wpn, 1); - - if(autocvar_g_showweaponspawns) - { - entity e; - - for(e = world; (e = findfloat(e, weapon, wpn)); ) - { - if(e.classname == "droppedweapon") - continue; - if(!(e.flags & FL_ITEM)) - continue; - WaypointSprite_Spawn( - (get_weaponinfo(wpn)).wpmodel, - 1, 0, - world, e.origin, - self, 0, - world, enemy, - 0, - RADARICON_NONE, '0 0 0' - ); - } - } - } - else - { - Send_WeaponComplain (cl, wpn, 2); - } - - play2(cl, "weapons/unavailable.wav"); - } - return FALSE; -} - -float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain, float skipmissing) -{ - // We cannot tokenize in this function, as GiveItems calls this - // function. Thus we must use car/cdr. - float weaponwant, first_valid, prev_valid, switchtonext, switchtolast, c; - string rest; - switchtonext = switchtolast = 0; - first_valid = prev_valid = 0; - float weaponcur; - entity wep; - - if(skipmissing || pl.selectweapon == 0) - weaponcur = pl.switchweapon; - else - weaponcur = pl.selectweapon; - - if(dir == 0) - switchtonext = 1; - - c = 0; - - rest = weaponorder; - while(rest != "") - { - weaponwant = stof(car(rest)); rest = cdr(rest); - wep = get_weaponinfo(weaponwant); - if(imp >= 0) - if(wep.impulse != imp) - continue; - - // skip weapons we don't own that aren't normal and aren't in the map - if(!(pl.weapons & WepSet_FromWeapon(weaponwant))) - if(!((get_weaponinfo(weaponwant)).spawnflags & WEP_FLAG_NORMAL)) - if(!(weaponsInMap & WepSet_FromWeapon(weaponwant))) - continue; - - ++c; - - if(!skipmissing || client_hasweapon(pl, weaponwant, TRUE, FALSE)) - { - if(switchtonext) - return weaponwant; - if(!first_valid) - first_valid = weaponwant; - if(weaponwant == weaponcur) - { - if(dir >= 0) - switchtonext = 1; - else if(prev_valid) - return prev_valid; - else - switchtolast = 1; - } - prev_valid = weaponwant; - } - } - if(first_valid) - { - if(switchtolast) - return prev_valid; - else - return first_valid; - } - // complain (but only for one weapon on the button that has been pressed) - if(complain) - { - self.weaponcomplainindex += 1; - c = mod(self.weaponcomplainindex, c) + 1; - rest = weaponorder; - while(rest != "") - { - weaponwant = stof(car(rest)); rest = cdr(rest); - wep = get_weaponinfo(weaponwant); - if(imp >= 0) - if(wep.impulse != imp) - continue; - - // skip weapons we don't own that aren't normal and aren't in the map - if(!(pl.weapons & WepSet_FromWeapon(weaponwant))) - if(!((get_weaponinfo(weaponwant)).spawnflags & WEP_FLAG_NORMAL)) - if(!(weaponsInMap & WepSet_FromWeapon(weaponwant))) - continue; - - --c; - if(c == 0) - { - client_hasweapon(pl, weaponwant, TRUE, TRUE); - break; - } - } - } - return 0; -} - -void W_SwitchWeapon_Force(entity e, float w) -{ - e.cnt = e.switchweapon; - e.switchweapon = w; - e.selectweapon = w; -} - -// perform weapon to attack (weaponstate and attack_finished check is here) -void W_SwitchToOtherWeapon(entity pl) -{ - // hack to ensure it switches to an OTHER weapon (in case the other fire mode still has ammo, we want that anyway) - float w, ww; - w = pl.weapon; - if(pl.weapons & WepSet_FromWeapon(w)) - { - pl.weapons &= ~WepSet_FromWeapon(w); - ww = w_getbestweapon(pl); - pl.weapons |= WepSet_FromWeapon(w); - } - else - ww = w_getbestweapon(pl); - if(ww) - W_SwitchWeapon_Force(pl, ww); -} - -void W_SwitchWeapon(float imp) -{ - if (self.switchweapon != imp) - { - if (client_hasweapon(self, imp, TRUE, TRUE)) - W_SwitchWeapon_Force(self, imp); - else - self.selectweapon = imp; // update selectweapon ANYWAY - } - else { WEP_ACTION(self.weapon, WR_RELOAD); } -} - -void W_CycleWeapon(string weaponorder, float dir) -{ - float w; - w = W_GetCycleWeapon(self, weaponorder, dir, -1, 1, TRUE); - if(w > 0) - W_SwitchWeapon(w); -} - -void W_NextWeaponOnImpulse(float imp) -{ - float w; - w = W_GetCycleWeapon(self, self.cvar_cl_weaponpriority, +1, imp, 1, (self.cvar_cl_weaponimpulsemode == 0)); - if(w > 0) - W_SwitchWeapon(w); -} - -// next weapon -void W_NextWeapon(float list) -{ - if(list == 0) - W_CycleWeapon(weaponorder_byid, -1); - else if(list == 1) - W_CycleWeapon(self.weaponorder_byimpulse, -1); - else if(list == 2) - W_CycleWeapon(self.cvar_cl_weaponpriority, -1); -} - -// prev weapon -void W_PreviousWeapon(float list) -{ - if(list == 0) - W_CycleWeapon(weaponorder_byid, +1); - else if(list == 1) - W_CycleWeapon(self.weaponorder_byimpulse, +1); - else if(list == 2) - W_CycleWeapon(self.cvar_cl_weaponpriority, +1); -} - -// previously used if exists and has ammo, (second) best otherwise -void W_LastWeapon(void) -{ - if(client_hasweapon(self, self.cnt, TRUE, FALSE)) - W_SwitchWeapon(self.cnt); - else - W_SwitchToOtherWeapon(self); -} diff --git a/qcsrc/server/weapons/selection.qh b/qcsrc/server/weapons/selection.qh deleted file mode 100644 index 8e2937f0c..000000000 --- a/qcsrc/server/weapons/selection.qh +++ /dev/null @@ -1,29 +0,0 @@ -// switch between weapons -void Send_WeaponComplain(entity e, float wpn, float type); - -.float hasweapon_complain_spam; -float client_hasweapon(entity cl, float wpn, float andammo, float complain); - -.float weaponcomplainindex; -float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain, float skipmissing); - -#define w_getbestweapon(ent) W_GetCycleWeapon(ent, ent.cvar_cl_weaponpriority, 0, -1, FALSE, TRUE) - -void W_SwitchWeapon_Force(entity e, float w); - -// perform weapon to attack (weaponstate and attack_finished check is here) -void W_SwitchToOtherWeapon(entity pl); -void W_SwitchWeapon(float imp); - -void W_CycleWeapon(string weaponorder, float dir); - -void W_NextWeaponOnImpulse(float imp); - -// next weapon -void W_NextWeapon(float list); - -// prev weapon -void W_PreviousWeapon(float list); - -// previously used if exists and has ammo, (second) best otherwise -void W_LastWeapon(void); diff --git a/qcsrc/server/weapons/spawning.qc b/qcsrc/server/weapons/spawning.qc deleted file mode 100644 index 04dd3f6f2..000000000 --- a/qcsrc/server/weapons/spawning.qc +++ /dev/null @@ -1,181 +0,0 @@ -string W_Apply_Weaponreplace(string in) -{ - float n = tokenize_console(in); - string out = "", s, replacement; - float i, j; - entity e; - for(i = 0; i < n; ++i) - { - replacement = ""; - s = argv(i); - - for(j = WEP_FIRST; j <= WEP_LAST; ++j) - { - e = get_weaponinfo(j); - if(e.netname == s) - { - replacement = e.weaponreplace; - } - } - - if(replacement == "") - out = strcat(out, " ", s); - else if(replacement != "0") - out = strcat(out, " ", replacement); - } - return substring(out, 1, -1); -} - -void weapon_defaultspawnfunc(float wpn) -{ - entity e; - float t; - string s; - entity oldself; - float i, j; - float f; - - if(self.classname != "droppedweapon" && self.classname != "replacedweapon") - { - e = get_weaponinfo(wpn); - - if(e.spawnflags & WEP_FLAG_MUTATORBLOCKED) - { - objerror("Attempted to spawn a mutator-blocked weapon rejected"); - startitem_failed = TRUE; - return; - } - - s = W_Apply_Weaponreplace(e.netname); - ret_string = s; - other = e; - MUTATOR_CALLHOOK(SetWeaponreplace); - s = ret_string; - if(s == "") - { - remove(self); - startitem_failed = TRUE; - return; - } - t = tokenize_console(s); - if(t >= 2) - { - self.team = --internalteam; - oldself = self; - for(i = 1; i < t; ++i) - { - s = argv(i); - for(j = WEP_FIRST; j <= WEP_LAST; ++j) - { - e = get_weaponinfo(j); - if(e.netname == s) - { - self = spawn(); - copyentity(oldself, self); - self.classname = "replacedweapon"; - weapon_defaultspawnfunc(j); - break; - } - } - if(j > WEP_LAST) - { - print("The weapon replace list for ", oldself.classname, " contains an unknown weapon ", s, ". Skipped.\n"); - } - } - self = oldself; - } - if(t >= 1) // always the case! - { - s = argv(0); - wpn = 0; - for(j = WEP_FIRST; j <= WEP_LAST; ++j) - { - e = get_weaponinfo(j); - if(e.netname == s) - { - wpn = j; - break; - } - } - if(j > WEP_LAST) - { - print("The weapon replace list for ", self.classname, " contains an unknown weapon ", s, ". Skipped.\n"); - } - } - if(wpn == 0) - { - remove(self); - startitem_failed = TRUE; - return; - } - } - - e = get_weaponinfo(wpn); - - if(!self.respawntime) - { - if(e.weapons & WEPSET_SUPERWEAPONS) - { - self.respawntime = g_pickup_respawntime_superweapon; - self.respawntimejitter = g_pickup_respawntimejitter_superweapon; - } - else - { - self.respawntime = g_pickup_respawntime_weapon; - self.respawntimejitter = g_pickup_respawntimejitter_weapon; - } - } - - if(e.weapons & WEPSET_SUPERWEAPONS) - if(!self.superweapons_finished) - self.superweapons_finished = autocvar_g_balance_superweapons_time; - - // if we don't already have ammo, give us some ammo - if(!self.(e.ammo_field)) - { - switch(e.ammo_field) - { - case ammo_shells: self.ammo_shells = cvar("g_pickup_shells_weapon"); break; - case ammo_nails: self.ammo_nails = cvar("g_pickup_nails_weapon"); break; - case ammo_rockets: self.ammo_rockets = cvar("g_pickup_rockets_weapon"); break; - case ammo_cells: self.ammo_cells = cvar("g_pickup_cells_weapon"); break; - case ammo_plasma: self.ammo_plasma = cvar("g_pickup_plasma_weapon"); break; - case ammo_fuel: self.ammo_fuel = cvar("g_pickup_fuel_weapon"); break; - } - } - - #if 0 // WEAPONTODO - if(e.items) - { - for(i = 0, j = 1; i < 24; ++i, j *= 2) - { - if(e.items & j) - { - ammotype = Item_CounterField(j); - if(!self.ammotype) - self.ammotype = cvar(strcat("g_pickup_", Item_CounterFieldName(j), "_weapon")); - } - } - } - #endif - - // pickup anyway - if(g_pickup_weapons_anyway) - self.pickup_anyway = TRUE; - - f = FL_WEAPON; - - // no weapon-stay on superweapons - if(e.weapons & WEPSET_SUPERWEAPONS) - f |= FL_NO_WEAPON_STAY; - - // weapon stay isn't supported for teamed weapons - if(self.team) - f |= FL_NO_WEAPON_STAY; - - StartItem(e.model, "weapons/weaponpickup.wav", self.respawntime, self.respawntimejitter, e.message, 0, e.weapon, f, weapon_pickupevalfunc, e.bot_pickupbasevalue); - #if 0 // WEAPONTODO - if (self.modelindex) // don't precache if self was removed - WEP_ACTION(e.weapon, WR_INIT); - #endif -} diff --git a/qcsrc/server/weapons/spawning.qh b/qcsrc/server/weapons/spawning.qh deleted file mode 100644 index c6939e53a..000000000 --- a/qcsrc/server/weapons/spawning.qh +++ /dev/null @@ -1,3 +0,0 @@ -string W_Apply_Weaponreplace(string in); - -void weapon_defaultspawnfunc(float wpn); diff --git a/qcsrc/server/weapons/throwing.qc b/qcsrc/server/weapons/throwing.qc deleted file mode 100644 index 2d5a83118..000000000 --- a/qcsrc/server/weapons/throwing.qc +++ /dev/null @@ -1,187 +0,0 @@ -void thrown_wep_think() -{ - self.nextthink = time; - if(self.oldorigin != self.origin) - { - self.SendFlags |= ISF_LOCATION; - self.oldorigin = self.origin; - } - self.owner = world; - float timeleft = self.savenextthink - time; - if(timeleft > 1) - SUB_SetFade(self, self.savenextthink - 1, 1); - else if(timeleft > 0) - SUB_SetFade(self, time, timeleft); - else - SUB_VanishOrRemove(self); -} - -// returns amount of ammo used as string, or -1 for failure, or 0 for no ammo count -string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo) -{ - entity oldself, wep; - float thisammo, i; - string s; - var .float ammotype = (get_weaponinfo(wpn)).ammo_field; - - wep = spawn(); - - setorigin(wep, org); - wep.classname = "droppedweapon"; - wep.velocity = velo; - wep.owner = wep.enemy = own; - wep.flags |= FL_TOSSED; - wep.colormap = own.colormap; - - if(WepSet_FromWeapon(wpn) & WEPSET_SUPERWEAPONS) - { - if(own.items & IT_UNLIMITED_SUPERWEAPONS) - { - wep.superweapons_finished = time + autocvar_g_balance_superweapons_time; - } - else - { - float superweapons = 1; - for(i = WEP_FIRST; i <= WEP_LAST; ++i) - if(WepSet_FromWeapon(i) & WEPSET_SUPERWEAPONS) - if(own.weapons & WepSet_FromWeapon(i)) - ++superweapons; - if(superweapons <= 1) - { - wep.superweapons_finished = own.superweapons_finished; - own.superweapons_finished = 0; - } - else - { - float timeleft = own.superweapons_finished - time; - float weptimeleft = timeleft / superweapons; - wep.superweapons_finished = time + weptimeleft; - own.superweapons_finished -= weptimeleft; - } - } - } - - oldself = self; - self = wep; - weapon_defaultspawnfunc(wpn); - self = oldself; - if(startitem_failed) - return string_null; - wep.glowmod = own.weaponentity_glowmod; - wep.think = thrown_wep_think; - wep.savenextthink = wep.nextthink; - wep.nextthink = min(wep.nextthink, time + 0.5); - wep.pickup_anyway = TRUE; // these are ALWAYS pickable - - //wa = W_AmmoItemCode(wpn); - if(ammotype == ammo_none) - { - return ""; - } - else - { - s = ""; - - if(doreduce && g_weapon_stay == 2) - { - // if our weapon is loaded, give its load back to the player - if(self.(weapon_load[self.weapon]) > 0) - { - own.ammotype += self.(weapon_load[self.weapon]); - self.(weapon_load[self.weapon]) = -1; // schedule the weapon for reloading - } - - wep.ammotype = 0; - } - else if(doreduce) - { - // if our weapon is loaded, give its load back to the player - if(self.(weapon_load[self.weapon]) > 0) - { - own.ammotype += self.(weapon_load[self.weapon]); - self.(weapon_load[self.weapon]) = -1; // schedule the weapon for reloading - } - - thisammo = min(own.ammotype, wep.ammotype); - wep.ammotype = thisammo; - own.ammotype -= thisammo; - - switch(ammotype) - { - case ammo_shells: s = sprintf("%s and %d shells", s, thisammo); break; - case ammo_nails: s = sprintf("%s and %d nails", s, thisammo); break; - case ammo_rockets: s = sprintf("%s and %d rockets", s, thisammo); break; - case ammo_cells: s = sprintf("%s and %d cells", s, thisammo); break; - case ammo_plasma: s = sprintf("%s and %d plasma", s, thisammo); break; - case ammo_fuel: s = sprintf("%s and %d fuel", s, thisammo); break; - } - - s = substring(s, 5, -1); - } - return s; - } -} - -float W_IsWeaponThrowable(float w) -{ - if (!autocvar_g_pickup_items) - return 0; - if (g_weaponarena) - return 0; - if (g_cts) - return 0; - if (g_nexball && w == WEP_MORTAR) - return 0; - if(w == 0) - return 0; - - #if 0 - if(start_weapons & WepSet_FromWeapon(w)) - { - // start weapons that take no ammo can't be dropped (this prevents dropping the laser, as long as it continues to use no ammo) - if(start_items & IT_UNLIMITED_WEAPON_AMMO) - return 0; - if((get_weaponinfo(w)).ammo_field == ammo_none) - return 0; - } - return 1; - #else - return (get_weaponinfo(w)).weaponthrowable; - #endif -} - -// toss current weapon -void W_ThrowWeapon(vector velo, vector delta, float doreduce) -{ - float w; - string a; - - w = self.weapon; - if (w == 0) - return; // just in case - if(MUTATOR_CALLHOOK(ForbidThrowCurrentWeapon)) - return; - if(!autocvar_g_weapon_throwable) - return; - if(self.weaponentity.state != WS_READY) - return; - if(!W_IsWeaponThrowable(w)) - return; - - if(!(self.weapons & WepSet_FromWeapon(w))) - return; - self.weapons &= ~WepSet_FromWeapon(w); - - W_SwitchWeapon_Force(self, w_getbestweapon(self)); - a = W_ThrowNewWeapon(self, w, doreduce, self.origin + delta, velo); - - if(!a) return; - Send_Notification(NOTIF_ONE, self, MSG_MULTI, ITEM_WEAPON_DROP, a, w); -} - -void SpawnThrownWeapon(vector org, float w) -{ - if(self.weapons & WepSet_FromWeapon(self.weapon)) - if(W_IsWeaponThrowable(self.weapon)) - W_ThrowNewWeapon(self, self.weapon, FALSE, org, randomvec() * 125 + '0 0 200'); -} diff --git a/qcsrc/server/weapons/throwing.qh b/qcsrc/server/weapons/throwing.qh deleted file mode 100644 index c09a8f882..000000000 --- a/qcsrc/server/weapons/throwing.qh +++ /dev/null @@ -1,12 +0,0 @@ -.float savenextthink; -void thrown_wep_think(); - -// returns amount of ammo used as string, or -1 for failure, or 0 for no ammo count -string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo); - -float W_IsWeaponThrowable(float w); - -// toss current weapon -void W_ThrowWeapon(vector velo, vector delta, float doreduce); - -void SpawnThrownWeapon(vector org, float w); diff --git a/qcsrc/server/weapons/tracing.qc b/qcsrc/server/weapons/tracing.qc deleted file mode 100644 index 755ab59e5..000000000 --- a/qcsrc/server/weapons/tracing.qc +++ /dev/null @@ -1,470 +0,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?) -void W_SetupShot_Dir_ProjectileSize_Range(entity ent, vector s_forward, vector mi, vector ma, float antilag, float recoil, string snd, float chan, float maxdamage, float range) -{ - float nudge = 1; // added to traceline target and subtracted from result TOOD(divVerent): do we still need this? Doesn't the engine do this now for us? - float oldsolid; - vector vecs, dv; - oldsolid = ent.dphitcontentsmask; - if(ent.weapon == WEP_RIFLE) - ent.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_CORPSE; - else - ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE; - if(antilag) - WarpZone_traceline_antilag(world, ent.origin + ent.view_ofs, ent.origin + ent.view_ofs + s_forward * range, MOVE_NORMAL, ent, ANTILAG_LATENCY(ent)); - // passing world, because we do NOT want it to touch dphitcontentsmask - else - WarpZone_TraceLine(ent.origin + ent.view_ofs, ent.origin + ent.view_ofs + s_forward * range, MOVE_NOMONSTERS, ent); - ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE; - - vector vf, vr, vu; - vf = v_forward; - vr = v_right; - vu = v_up; - w_shotend = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos); // warpzone support - v_forward = vf; - v_right = vr; - v_up = vu; - - // un-adjust trueaim if shotend is too close - if(vlen(w_shotend - (ent.origin + ent.view_ofs)) < autocvar_g_trueaim_minrange) - w_shotend = ent.origin + ent.view_ofs + s_forward * autocvar_g_trueaim_minrange; - - // track max damage - if(accuracy_canbegooddamage(ent)) - accuracy_add(ent, ent.weapon, maxdamage, 0); - - W_HitPlotAnalysis(ent, v_forward, v_right, v_up); - - if(ent.weaponentity.movedir_x > 0) - vecs = ent.weaponentity.movedir; - else - vecs = '0 0 0'; - - dv = v_right * -vecs_y + v_up * vecs_z; - w_shotorg = ent.origin + ent.view_ofs + dv; - - // now move the shotorg forward as much as requested if possible - if(antilag) - { - if(ent.antilag_debug) - tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + v_forward * (vecs_x + nudge), MOVE_NORMAL, ent, ent.antilag_debug); - else - tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + v_forward * (vecs_x + nudge), MOVE_NORMAL, ent, ANTILAG_LATENCY(ent)); - } - else - tracebox(w_shotorg, mi, ma, w_shotorg + v_forward * (vecs_x + nudge), MOVE_NORMAL, ent); - w_shotorg = trace_endpos - v_forward * nudge; - // calculate the shotdir from the chosen shotorg - w_shotdir = normalize(w_shotend - w_shotorg); - - //vector prevdir = w_shotdir; - //vector prevorg = w_shotorg; - //vector prevend = w_shotend; - - if (antilag) - if (!ent.cvar_cl_noantilag) - { - if (autocvar_g_antilag == 1) // switch to "ghost" if not hitting original - { - traceline(w_shotorg, w_shotorg + w_shotdir * range, MOVE_NORMAL, ent); - if (!trace_ent.takedamage) - { - traceline_antilag_force (ent, w_shotorg, w_shotorg + w_shotdir * range, MOVE_NORMAL, ent, ANTILAG_LATENCY(ent)); - if (trace_ent.takedamage && IS_PLAYER(trace_ent)) - { - entity e; - e = trace_ent; - traceline(w_shotorg, e.origin, MOVE_NORMAL, ent); - if(trace_ent == e) - w_shotdir = normalize(trace_ent.origin - w_shotorg); - } - } - } - else if(autocvar_g_antilag == 3) // client side hitscan - { - // this part MUST use prydon cursor - if (ent.cursor_trace_ent) // client was aiming at someone - if (ent.cursor_trace_ent != ent) // just to make sure - if (ent.cursor_trace_ent.takedamage) // and that person is killable - if (IS_PLAYER(ent.cursor_trace_ent)) // and actually a player - { - // verify that the shot would miss without antilag - // (avoids an issue where guns would always shoot at their origin) - traceline(w_shotorg, w_shotorg + w_shotdir * range, MOVE_NORMAL, ent); - if (!trace_ent.takedamage) - { - // verify that the shot would hit if altered - traceline(w_shotorg, ent.cursor_trace_ent.origin, MOVE_NORMAL, ent); - if (trace_ent == ent.cursor_trace_ent) - w_shotdir = normalize(ent.cursor_trace_ent.origin - w_shotorg); - else - print("antilag fail\n"); - } - } - } - } - - ent.dphitcontentsmask = oldsolid; // restore solid type (generally SOLID_SLIDEBOX) - - if (!autocvar_g_norecoil) - ent.punchangle_x = recoil * -1; - - if (snd != "") - { - sound (ent, chan, snd, VOL_BASE, ATTN_NORM); - W_PlayStrengthSound(ent); - } - - // nudge w_shotend so a trace to w_shotend hits - w_shotend = w_shotend + normalize(w_shotend - w_shotorg) * nudge; - //if(w_shotend != prevend) { printf("SERVER: shotEND differs: %s - %s\n", vtos(w_shotend), vtos(prevend)); } - //if(w_shotorg != prevorg) { printf("SERVER: shotORG differs: %s - %s\n", vtos(w_shotorg), vtos(prevorg)); } - //if(w_shotdir != prevdir) { printf("SERVER: shotDIR differs: %s - %s\n", vtos(w_shotdir), vtos(prevdir)); } -} - -vector W_CalculateProjectileVelocity(vector pvelocity, vector mvelocity, float forceAbsolute) -{ - vector mdirection; - float mspeed; - vector outvelocity; - - mvelocity = mvelocity * g_weaponspeedfactor; - - mdirection = normalize(mvelocity); - mspeed = vlen(mvelocity); - - outvelocity = get_shotvelocity(pvelocity, mdirection, mspeed, (forceAbsolute ? 0 : autocvar_g_projectiles_newton_style), autocvar_g_projectiles_newton_style_2_minfactor, autocvar_g_projectiles_newton_style_2_maxfactor); - - return outvelocity; -} - -void W_SetupProjVelocity_Explicit(entity proj, vector dir, vector upDir, float pSpeed, float pUpSpeed, float pZSpeed, float spread, float forceAbsolute) -{ - if(proj.owner == world) - error("Unowned missile"); - - dir = dir + upDir * (pUpSpeed / pSpeed); - dir_z += pZSpeed / pSpeed; - pSpeed *= vlen(dir); - dir = normalize(dir); - - #if 0 - if(autocvar_g_projectiles_spread_style != mspercallsstyle) - { - mspercallsum = mspercallcount = 0; - mspercallsstyle = autocvar_g_projectiles_spread_style; - } - mspercallsum -= gettime(GETTIME_HIRES); - #endif - - dir = W_CalculateSpread(dir, spread, g_weaponspreadfactor, autocvar_g_projectiles_spread_style); - - #if 0 - mspercallsum += gettime(GETTIME_HIRES); - mspercallcount += 1; - print("avg: ", ftos(mspercallcount / mspercallsum), " per sec\n"); - #endif - - proj.velocity = W_CalculateProjectileVelocity(proj.owner.velocity, pSpeed * dir, forceAbsolute); -} - - -// ==================== -// Ballistics Tracing -// ==================== - -void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, float deathtype) -{ - vector hitloc, force, endpoint, dir; - entity ent, endent; - float endq3surfaceflags; - float totaldmg; - entity o; - - float length; - vector beampos; - string snd; - entity pseudoprojectile; - float f, ffs; - - pseudoprojectile = world; - - dir = normalize(end - start); - length = vlen(end - start); - force = dir * bforce; - - // go a little bit into the wall because we need to hit this wall later - end = end + dir; - - totaldmg = 0; - - // trace multiple times until we hit a wall, each obstacle will be made - // non-solid so we can hit the next, while doing this we spawn effects and - // note down which entities were hit so we can damage them later - o = self; - while (1) - { - if(self.antilag_debug) - WarpZone_traceline_antilag (self, start, end, FALSE, o, self.antilag_debug); - else - WarpZone_traceline_antilag (self, start, end, FALSE, o, ANTILAG_LATENCY(self)); - if(o && WarpZone_trace_firstzone) - { - o = world; - continue; - } - - if(trace_ent.solid == SOLID_BSP || trace_ent.solid == SOLID_SLIDEBOX) - Damage_DamageInfo(trace_endpos, bdamage, 0, 0, force, deathtype, trace_ent.species, self); - - // if it is world we can't hurt it so stop now - if (trace_ent == world || trace_fraction == 1) - break; - - // make the entity non-solid so we can hit the next one - trace_ent.railgunhit = TRUE; - trace_ent.railgunhitloc = end; - trace_ent.railgunhitsolidbackup = trace_ent.solid; - trace_ent.railgundistance = vlen(WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos) - start); - trace_ent.railgunforce = WarpZone_TransformVelocity(WarpZone_trace_transform, force); - - // stop if this is a wall - if (trace_ent.solid == SOLID_BSP) - break; - - // make the entity non-solid - trace_ent.solid = SOLID_NOT; - } - - endpoint = trace_endpos; - endent = trace_ent; - endq3surfaceflags = trace_dphitq3surfaceflags; - - // find all the entities the railgun hit and restore their solid state - ent = findfloat(world, railgunhit, TRUE); - while (ent) - { - // restore their solid type - ent.solid = ent.railgunhitsolidbackup; - ent = findfloat(ent, railgunhit, TRUE); - } - - // spawn a temporary explosion entity for RadiusDamage calls - //explosion = spawn(); - - // Find all non-hit players the beam passed close by - if(deathtype == WEP_VAPORIZER || deathtype == WEP_VORTEX) - { - FOR_EACH_REALCLIENT(msg_entity) - if(msg_entity != self) - if(!msg_entity.railgunhit) - if(!(IS_SPEC(msg_entity) && msg_entity.enemy == self)) // we use realclient, so spectators can hear the whoosh too - { - // nearest point on the beam - beampos = start + dir * bound(0, (msg_entity.origin - start) * dir, length); - - f = bound(0, 1 - vlen(beampos - msg_entity.origin) / 512, 1); - if(f <= 0) - continue; - - snd = strcat("weapons/nexwhoosh", ftos(floor(random() * 3) + 1), ".wav"); - - if(!pseudoprojectile) - pseudoprojectile = spawn(); // we need this so the sound uses the "entchannel4" volume - soundtoat(MSG_ONE, pseudoprojectile, beampos, CH_SHOTS, snd, VOL_BASE * f, ATTEN_NONE); - } - - if(pseudoprojectile) - remove(pseudoprojectile); - } - - // find all the entities the railgun hit and hurt them - ent = findfloat(world, railgunhit, TRUE); - while (ent) - { - // get the details we need to call the damage function - hitloc = ent.railgunhitloc; - - f = ExponentialFalloff(mindist, maxdist, halflifedist, ent.railgundistance); - ffs = ExponentialFalloff(mindist, maxdist, forcehalflifedist, ent.railgundistance); - - if(accuracy_isgooddamage(self.realowner, ent)) - totaldmg += bdamage * f; - - // apply the damage - if (ent.takedamage) - Damage (ent, self, self, bdamage * f, deathtype, hitloc, ent.railgunforce * ffs); - - // create a small explosion to throw gibs around (if applicable) - //setorigin (explosion, hitloc); - //RadiusDamage (explosion, self, 10, 0, 50, world, world, 300, deathtype); - - ent.railgunhitloc = '0 0 0'; - ent.railgunhitsolidbackup = SOLID_NOT; - ent.railgunhit = FALSE; - ent.railgundistance = 0; - - // advance to the next entity - ent = findfloat(ent, railgunhit, TRUE); - } - - // calculate hits and fired shots for hitscan - accuracy_add(self, self.weapon, 0, min(bdamage, totaldmg)); - - trace_endpos = endpoint; - trace_ent = endent; - trace_dphitq3surfaceflags = endq3surfaceflags; -} - -void fireBullet_trace_callback(vector start, vector hit, vector end) -{ - if(vlen(hit - start) > 16) - trailparticles(world, fireBullet_trace_callback_eff, start, hit); - WarpZone_trace_forent = world; - fireBullet_last_hit = world; -} - -void fireBullet(vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, float tracereffects) -{ - vector end; - - dir = normalize(dir + randomvec() * spread); - end = start + dir * MAX_SHOT_DISTANCE; - - entity pl; - fireBullet_last_hit = world; - float solid_penetration_left = 1; - float total_damage = 0; - - if(tracereffects & EF_RED) - fireBullet_trace_callback_eff = particleeffectnum("tr_rifle"); - else if(tracereffects & EF_BLUE) - fireBullet_trace_callback_eff = particleeffectnum("tr_rifle_weak"); - else - fireBullet_trace_callback_eff = particleeffectnum("tr_bullet"); - - float lag = ANTILAG_LATENCY(self); - if(lag < 0.001) - lag = 0; - if (!IS_REAL_CLIENT(self)) - lag = 0; - if(autocvar_g_antilag == 0 || self.cvar_cl_noantilag) - lag = 0; // only do hitscan, but no antilag - if(lag) - { - FOR_EACH_PLAYER(pl) - if(pl != self) - antilag_takeback(pl, time - lag); - FOR_EACH_MONSTER(pl) - antilag_takeback(pl, time - lag); - } - - WarpZone_trace_forent = self; - - for (;;) - { - // TODO also show effect while tracing - WarpZone_TraceBox_ThroughZone(start, '0 0 0', '0 0 0', end, FALSE, WarpZone_trace_forent, world, fireBullet_trace_callback); - dir = WarpZone_TransformVelocity(WarpZone_trace_transform, dir); - end = WarpZone_TransformOrigin(WarpZone_trace_transform, end); - start = trace_endpos; - entity hit = trace_ent; - - // When hitting sky, stop. - if (pointcontents(start) == CONTENT_SKY) - break; - - if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT) - break; - - // if we hit "weapclip", bail out - // - // rationale of this check: - // - // any shader that is solid, nodraw AND trans is meant to clip weapon - // shots and players, but has no other effect! - // - // if it is not trans, it is caulk and should not have this side effect - // - // matching shaders: - // common/weapclip (intended) - // common/noimpact (is supposed to eat projectiles, but is erased anyway) - float is_weapclip = 0; - if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NODRAW) - if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NONSOLID)) - if (!(trace_dphitcontents & DPCONTENTS_OPAQUE)) - is_weapclip = 1; - - if(!hit || hit.solid == SOLID_BSP || hit.solid == SOLID_SLIDEBOX) - Damage_DamageInfo(start, damage * solid_penetration_left, 0, 0, max(1, force) * dir * solid_penetration_left, dtype, hit.species, self); - - if (hit && hit != WarpZone_trace_forent && hit != fireBullet_last_hit) // Avoid self-damage (except after going through a warp); avoid hitting the same entity twice (engine bug). - { - fireBullet_last_hit = hit; - yoda = 0; - float g = accuracy_isgooddamage(self, hit); - Damage(hit, self, self, damage * solid_penetration_left, dtype, start, force * dir * solid_penetration_left); - // calculate hits for ballistic weapons - if(g) - { - // do not exceed 100% - float added_damage = min(damage - total_damage, damage * solid_penetration_left); - total_damage += damage * solid_penetration_left; - accuracy_add(self, self.weapon, 0, added_damage); - } - } - - if (is_weapclip) - break; - - // go through solid! - // outside the world? forget it - if(start_x > world.maxs_x || start_y > world.maxs_y || start_z > world.maxs_z || start_x < world.mins_x || start_y < world.mins_y || start_z < world.mins_z) - break; - - float maxdist; - if(max_solid_penetration < 0) - break; - else if(hit.ballistics_density < -1) - break; // -2: no solid penetration, ever - else if(hit.ballistics_density < 0) - maxdist = vlen(hit.maxs - hit.mins) + 1; // -1: infinite travel distance - else if(hit.ballistics_density == 0) - maxdist = max_solid_penetration * solid_penetration_left; - else - maxdist = max_solid_penetration * solid_penetration_left * hit.ballistics_density; - - if(maxdist <= autocvar_g_ballistics_mindistance) - break; - - // move the entity along its velocity until it's out of solid, then let it resume - // The previously hit entity is ignored here! - traceline_inverted (start, start + dir * maxdist, MOVE_NORMAL, WarpZone_trace_forent, TRUE, hit); - if(trace_fraction == 1) // 1: we never got out of solid - break; - - float dist_taken = max(autocvar_g_ballistics_mindistance, vlen(trace_endpos - start)); - solid_penetration_left *= (dist_taken / maxdist); - - // Only show effect when going through a player (invisible otherwise) - if (hit && (hit.solid != SOLID_BSP)) - if(vlen(trace_endpos - start) > 4) - trailparticles(self, fireBullet_trace_callback_eff, start, trace_endpos); - - start = trace_endpos; - - if(hit.solid == SOLID_BSP) - Damage_DamageInfo(start, 0, 0, 0, max(1, force) * normalize(dir) * -solid_penetration_left, dtype, 0, self); - } - - if(lag) - { - FOR_EACH_PLAYER(pl) - if(pl != self) - antilag_restore(pl); - FOR_EACH_MONSTER(pl) - antilag_restore(pl); - } -} diff --git a/qcsrc/server/weapons/tracing.qh b/qcsrc/server/weapons/tracing.qh deleted file mode 100644 index 49605e8f2..000000000 --- a/qcsrc/server/weapons/tracing.qh +++ /dev/null @@ -1,55 +0,0 @@ -vector w_shotorg; -vector w_shotdir; -vector w_shotend; - -// 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?) -void W_SetupShot_Dir_ProjectileSize_Range(entity ent, vector s_forward, vector mi, vector ma, float antilag, float recoil, string snd, float chan, float maxdamage, float range); - -#define W_SetupShot_Dir_ProjectileSize(ent,s_forward,mi,ma,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize_Range(ent, s_forward, mi, ma, antilag, recoil, snd, chan, maxdamage, MAX_SHOT_DISTANCE) -#define W_SetupShot_ProjectileSize(ent,mi,ma,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize(ent, v_forward, mi, ma, antilag, recoil, snd, chan, maxdamage) -#define W_SetupShot_Dir(ent,s_forward,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize(ent, s_forward, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage) -#define W_SetupShot(ent,antilag,recoil,snd,chan,maxdamage) W_SetupShot_ProjectileSize(ent, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage) -#define W_SetupShot_Range(ent,antilag,recoil,snd,chan,maxdamage,range) W_SetupShot_Dir_ProjectileSize_Range(ent, v_forward, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage, range) - -vector W_CalculateProjectileVelocity(vector pvelocity, vector mvelocity, float forceAbsolute); - -#if 0 -float mspercallsum; -float mspercallsstyle; -float mspercallcount; -#endif - -void W_SetupProjVelocity_Explicit(entity proj, vector dir, vector upDir, float pSpeed, float pUpSpeed, float pZSpeed, float spread, float forceAbsolute); - -#define W_SetupProjVelocity_Basic(ent,pspeed,pspread) W_SetupProjVelocity_Explicit(ent, w_shotdir, v_up, pspeed, 0, 0, pspread, FALSE) - -#define W_SetupProjVelocity_UP_PRE(ent,wepname,prefix) W_SetupProjVelocity_Explicit(ent, w_shotdir, v_up, WEP_CVAR(wepname, prefix##speed), WEP_CVAR(wepname, prefix##speed_up), WEP_CVAR(wepname, prefix##speed_z), WEP_CVAR(wepname, prefix##spread), FALSE) -#define W_SetupProjVelocity_UP_PRI(ent,wepname) W_SetupProjVelocity_Explicit(ent, w_shotdir, v_up, WEP_CVAR_PRI(wepname, speed), WEP_CVAR_PRI(wepname, speed_up), WEP_CVAR_PRI(wepname, speed_z), WEP_CVAR_PRI(wepname, spread), FALSE) -#define W_SetupProjVelocity_UP_SEC(ent,wepname) W_SetupProjVelocity_Explicit(ent, w_shotdir, v_up, WEP_CVAR_SEC(wepname, speed), WEP_CVAR_SEC(wepname, speed_up), WEP_CVAR_SEC(wepname, speed_z), WEP_CVAR_SEC(wepname, spread), FALSE) - -#define W_SetupProjVelocity_UP_BOTH(ent,wepname,isprimary) \ - if(isprimary) { W_SetupProjVelocity_UP_PRI(ent, wepname); } \ - else { W_SetupProjVelocity_UP_SEC(ent, wepname); } - -#define W_SetupProjVelocity_PRE(ent,wepname,prefix) W_SetupProjVelocity_Explicit(ent, w_shotdir, v_up, WEP_CVAR(wepname, prefix##speed), 0, 0, WEP_CVAR(wepname, prefix##spread), FALSE) -#define W_SetupProjVelocity_PRI(ent,wepname) W_SetupProjVelocity_Explicit(ent, w_shotdir, v_up, WEP_CVAR_PRI(wepname, speed), 0, 0, WEP_CVAR_PRI(wepname, spread), FALSE) -#define W_SetupProjVelocity_SEC(ent,wepname) W_SetupProjVelocity_Explicit(ent, w_shotdir, v_up, WEP_CVAR_SEC(wepname, speed), 0, 0, WEP_CVAR_SEC(wepname, spread), FALSE) - -#define W_SetupProjVelocity_BOTH(ent,wepname,isprimary) \ - if(isprimary) { W_SetupProjVelocity_PRI(ent, wepname); } \ - else { W_SetupProjVelocity_SEC(ent, wepname); } - -// ==================== -// Ballistics Tracing -// ==================== - -.float railgundistance; -.vector railgunforce; -void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, float deathtype); - -float fireBullet_trace_callback_eff; -entity fireBullet_last_hit; -void fireBullet_trace_callback(vector start, vector hit, vector end); -void fireBullet(vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, float tracereffects); diff --git a/qcsrc/server/weapons/weaponstats.qc b/qcsrc/server/weapons/weaponstats.qc deleted file mode 100644 index d83db8b82..000000000 --- a/qcsrc/server/weapons/weaponstats.qc +++ /dev/null @@ -1,103 +0,0 @@ -void WeaponStats_Init() -{ - weaponstats_buffer = ((autocvar_sv_weaponstats_file != "") ? buf_create() : -1); -} - -void WeaponStats_ready(entity fh, entity pass, float status) -{ - float i, j, n, ibot, jbot, idx; - vector v; - string prefix, s; - switch(status) - { - case URL_READY_CANWRITE: - // we can write - prefix = strcat(autocvar_hostname, "\t", GetGametype(), "_", GetMapname(), "\t"); - url_fputs(fh, "#begin statsfile\n"); - url_fputs(fh, strcat("#date ", strftime(TRUE, "%a %b %e %H:%M:%S %Z %Y"), "\n")); -#ifdef WATERMARK - url_fputs(fh, strcat("#version ", WATERMARK, "\n")); -#endif - url_fputs(fh, strcat("#config ", ftos(crc16(FALSE, cvar_purechanges)), "\n")); - url_fputs(fh, strcat("#cvar_purechanges ", ftos(cvar_purechanges_count), "\n")); - n = tokenizebyseparator(cvar_purechanges, "\n"); - for(i = 0; i < n; ++i) - url_fputs(fh, strcat("#cvar_purechange ", argv(i), "\n")); - for(i = WEP_FIRST; i <= WEP_LAST; ++i) for(ibot = 0; ibot <= 1; ++ibot) - for(j = WEP_FIRST; j <= WEP_LAST; ++j) for(jbot = 0; jbot <= 1; ++jbot) - { - idx = WEAPONSTATS_GETINDEX(i, ibot, j, jbot); - v = stov(bufstr_get(weaponstats_buffer, idx)); - if(v != '0 0 0') - { - //vector is: kills hits damage - url_fputs(fh, sprintf("%s%d %d\t%d %d\t", prefix, i, ibot, j, jbot)); - url_fputs(fh, sprintf("%d %d %g\n", v_x, v_y, v_z)); - } - } - url_fputs(fh, "#end\n\n"); - url_fclose(fh); - break; - case URL_READY_CANREAD: - // url_fclose is processing, we got a response for writing the data - // this must come from HTTP - print("Got response from weapon stats server:\n"); - while((s = url_fgets(fh))) - print(" ", s, "\n"); - print("End of response.\n"); - url_fclose(fh); - break; - case URL_READY_CLOSED: - // url_fclose has finished - print("Weapon stats written\n"); - buf_del(weaponstats_buffer); - weaponstats_buffer = -1; - break; - case URL_READY_ERROR: - default: - print("Weapon stats writing failed: ", ftos(status), "\n"); - buf_del(weaponstats_buffer); - weaponstats_buffer = -1; - break; - } -} - -void WeaponStats_Shutdown() -{ - if(weaponstats_buffer < 0) - return; - if(autocvar_sv_weaponstats_file != "") - { - url_multi_fopen(autocvar_sv_weaponstats_file, FILE_APPEND, WeaponStats_ready, world); - } - else - { - buf_del(weaponstats_buffer); - weaponstats_buffer = -1; - } -} - -void WeaponStats_LogItem(float awep, float abot, float vwep, float vbot, vector item) -{ - float idx; - if(weaponstats_buffer < 0) - return; - if(awep < WEP_FIRST || vwep < WEP_FIRST) - return; - if(awep > WEP_LAST || vwep > WEP_LAST) - return; - idx = WEAPONSTATS_GETINDEX(awep,abot,vwep,vbot); - bufstr_set(weaponstats_buffer, idx, vtos(stov(bufstr_get(weaponstats_buffer, idx)) + item)); -} - -void WeaponStats_LogDamage(float awep, float abot, float vwep, float vbot, float damage) -{ - if(damage < 0) - error("negative damage?"); - WeaponStats_LogItem(awep, abot, vwep, vbot, '0 0 1' * damage + '0 1 0'); -} - -void WeaponStats_LogKill(float awep, float abot, float vwep, float vbot) -{ - WeaponStats_LogItem(awep, abot, vwep, vbot, '1 0 0'); -} diff --git a/qcsrc/server/weapons/weaponstats.qh b/qcsrc/server/weapons/weaponstats.qh deleted file mode 100644 index 08ae8dd0a..000000000 --- a/qcsrc/server/weapons/weaponstats.qh +++ /dev/null @@ -1,10 +0,0 @@ -float weaponstats_buffer; - -void WeaponStats_Init(); -void WeaponStats_ready(entity fh, entity pass, float status); -void WeaponStats_Shutdown(); -void WeaponStats_LogItem(float awep, float abot, float vwep, float vbot, vector item); -void WeaponStats_LogDamage(float awep, float abot, float vwep, float vbot, float damage); -void WeaponStats_LogKill(float awep, float abot, float vwep, float vbot); - -#define WEAPONSTATS_GETINDEX(awep,abot,vwep,vbot) (((vwep) + (awep) * (WEP_LAST - WEP_FIRST + 1) - (WEP_FIRST + WEP_FIRST * (WEP_LAST - WEP_FIRST + 1))) * 4 + (abot) * 2 + (vbot)) diff --git a/qcsrc/server/weapons/weaponsystem.qc b/qcsrc/server/weapons/weaponsystem.qc deleted file mode 100644 index 4eb6a7364..000000000 --- a/qcsrc/server/weapons/weaponsystem.qc +++ /dev/null @@ -1,942 +0,0 @@ -/* -=========================================================================== - - CLIENT WEAPONSYSTEM CODE - Bring back W_Weaponframe - -=========================================================================== -*/ - -.float weapon_frametime; - -float W_WeaponRateFactor() -{ - float t; - t = 1.0 / g_weaponratefactor; - - weapon_rate = t; - MUTATOR_CALLHOOK(WeaponRateFactor); - t = weapon_rate; - - return t; -} - -// VorteX: static frame globals -const float WFRAME_DONTCHANGE = -1; -const float WFRAME_FIRE1 = 0; -const float WFRAME_FIRE2 = 1; -const float WFRAME_IDLE = 2; -const float WFRAME_RELOAD = 3; -.float wframe; - -void(float fr, float t, void() func) weapon_thinkf; - -float CL_Weaponentity_CustomizeEntityForClient() -{ - self.viewmodelforclient = self.owner; - if(IS_SPEC(other)) - if(other.enemy == self.owner) - self.viewmodelforclient = other; - return TRUE; -} - -/* - * supported formats: - * - * 1. simple animated model, muzzle flash handling on h_ model: - * h_tuba.dpm, h_tuba.dpm.framegroups - invisible model controlling the animation - * tags: - * shot = muzzle end (shot origin, also used for muzzle flashes) - * shell = casings ejection point (must be on the right hand side of the gun) - * weapon = attachment for v_tuba.md3 - * v_tuba.md3 - first and third person model - * g_tuba.md3 - pickup model - * - * 2. simple animated model, muzzle flash handling on v_ model: - * h_tuba.dpm, h_tuba.dpm.framegroups - invisible model controlling the animation - * tags: - * weapon = attachment for v_tuba.md3 - * v_tuba.md3 - first and third person model - * tags: - * shot = muzzle end (shot origin, also used for muzzle flashes) - * shell = casings ejection point (must be on the right hand side of the gun) - * g_tuba.md3 - pickup model - * - * 3. fully animated model, muzzle flash handling on h_ model: - * h_tuba.dpm, h_tuba.dpm.framegroups - animated first person model - * tags: - * shot = muzzle end (shot origin, also used for muzzle flashes) - * shell = casings ejection point (must be on the right hand side of the gun) - * handle = corresponding to the origin of v_tuba.md3 (used for muzzle flashes) - * v_tuba.md3 - third person model - * g_tuba.md3 - pickup model - * - * 4. fully animated model, muzzle flash handling on v_ model: - * h_tuba.dpm, h_tuba.dpm.framegroups - animated first person model - * tags: - * shot = muzzle end (shot origin) - * shell = casings ejection point (must be on the right hand side of the gun) - * v_tuba.md3 - third person model - * tags: - * shot = muzzle end (for muzzle flashes) - * g_tuba.md3 - pickup model - */ - -// writes: -// self.origin, self.angles -// self.weaponentity -// self.movedir, self.view_ofs -// attachment stuff -// anim stuff -// to free: -// call again with "" -// remove the ent -void CL_WeaponEntity_SetModel(string name) -{ - float v_shot_idx; - if (name != "") - { - // if there is a child entity, hide it until we're sure we use it - if (self.weaponentity) - self.weaponentity.model = ""; - setmodel(self, strcat("models/weapons/v_", name, ".md3")); // precision set below - v_shot_idx = gettagindex(self, "shot"); // used later - if(!v_shot_idx) - v_shot_idx = gettagindex(self, "tag_shot"); - - setmodel(self, strcat("models/weapons/h_", name, ".iqm")); // precision set below - // preset some defaults that work great for renamed zym files (which don't need an animinfo) - self.anim_fire1 = animfixfps(self, '0 1 0.01', '0 0 0'); - self.anim_fire2 = animfixfps(self, '1 1 0.01', '0 0 0'); - self.anim_idle = animfixfps(self, '2 1 0.01', '0 0 0'); - self.anim_reload = animfixfps(self, '3 1 0.01', '0 0 0'); - - // if we have a "weapon" tag, let's attach the v_ model to it ("invisible hand" style model) - // if we don't, this is a "real" animated model - if(gettagindex(self, "weapon")) - { - if (!self.weaponentity) - self.weaponentity = spawn(); - setmodel(self.weaponentity, strcat("models/weapons/v_", name, ".md3")); // precision does not matter - setattachment(self.weaponentity, self, "weapon"); - } - else if(gettagindex(self, "tag_weapon")) - { - if (!self.weaponentity) - self.weaponentity = spawn(); - setmodel(self.weaponentity, strcat("models/weapons/v_", name, ".md3")); // precision does not matter - setattachment(self.weaponentity, self, "tag_weapon"); - } - else - { - if(self.weaponentity) - remove(self.weaponentity); - self.weaponentity = world; - } - - setorigin(self,'0 0 0'); - self.angles = '0 0 0'; - self.frame = 0; - self.viewmodelforclient = world; - - float idx; - - if(v_shot_idx) // v_ model attached to invisible h_ model - { - self.movedir = gettaginfo(self.weaponentity, v_shot_idx); - } - else - { - idx = gettagindex(self, "shot"); - if(!idx) - idx = gettagindex(self, "tag_shot"); - if(idx) - self.movedir = gettaginfo(self, idx); - else - { - print("WARNING: weapon model ", self.model, " does not support the 'shot' tag, will display shots TOTALLY wrong\n"); - self.movedir = '0 0 0'; - } - } - - if(self.weaponentity) // v_ model attached to invisible h_ model - { - idx = gettagindex(self.weaponentity, "shell"); - if(!idx) - idx = gettagindex(self.weaponentity, "tag_shell"); - if(idx) - self.spawnorigin = gettaginfo(self.weaponentity, idx); - } - else - idx = 0; - if(!idx) - { - idx = gettagindex(self, "shell"); - if(!idx) - idx = gettagindex(self, "tag_shell"); - if(idx) - self.spawnorigin = gettaginfo(self, idx); - else - { - print("WARNING: weapon model ", self.model, " does not support the 'shell' tag, will display casings wrong\n"); - self.spawnorigin = self.movedir; - } - } - - if(v_shot_idx) - { - self.oldorigin = '0 0 0'; // use regular attachment - } - else - { - if(self.weaponentity) - { - idx = gettagindex(self, "weapon"); - if(!idx) - idx = gettagindex(self, "tag_weapon"); - } - else - { - idx = gettagindex(self, "handle"); - if(!idx) - idx = gettagindex(self, "tag_handle"); - } - if(idx) - { - self.oldorigin = self.movedir - gettaginfo(self, idx); - } - else - { - print("WARNING: weapon model ", self.model, " does not support the 'handle' tag and neither does the v_ model support the 'shot' tag, will display muzzle flashes TOTALLY wrong\n"); - self.oldorigin = '0 0 0'; // there is no way to recover from this - } - } - - self.viewmodelforclient = self.owner; - } - else - { - self.model = ""; - if(self.weaponentity) - remove(self.weaponentity); - self.weaponentity = world; - self.movedir = '0 0 0'; - self.spawnorigin = '0 0 0'; - self.oldorigin = '0 0 0'; - self.anim_fire1 = '0 1 0.01'; - self.anim_fire2 = '0 1 0.01'; - self.anim_idle = '0 1 0.01'; - self.anim_reload = '0 1 0.01'; - } - - self.view_ofs = '0 0 0'; - - if(self.movedir_x >= 0) - { - vector v0; - v0 = self.movedir; - self.movedir = shotorg_adjust(v0, FALSE, FALSE); - self.view_ofs = shotorg_adjust(v0, FALSE, TRUE) - v0; - } - self.owner.stat_shotorg = compressShotOrigin(self.movedir); - self.movedir = decompressShotOrigin(self.owner.stat_shotorg); // make them match perfectly - - self.spawnorigin += self.view_ofs; // offset the casings origin by the same amount - - // check if an instant weapon switch occurred - setorigin(self, self.view_ofs); - // reset animstate now - self.wframe = WFRAME_IDLE; - setanim(self, self.anim_idle, TRUE, FALSE, TRUE); -} - -vector CL_Weapon_GetShotOrg(float wpn) -{ - entity wi, oldself; - vector ret; - wi = get_weaponinfo(wpn); - oldself = self; - self = spawn(); - CL_WeaponEntity_SetModel(wi.mdl); - ret = self.movedir; - CL_WeaponEntity_SetModel(""); - remove(self); - self = oldself; - return ret; -} - -void CL_Weaponentity_Think() -{ - float tb; - self.nextthink = time; - if (intermission_running) - self.frame = self.anim_idle_x; - if (self.owner.weaponentity != self) - { - if (self.weaponentity) - remove(self.weaponentity); - remove(self); - return; - } - if (self.owner.deadflag != DEAD_NO) - { - self.model = ""; - if (self.weaponentity) - self.weaponentity.model = ""; - return; - } - if (self.weaponname != self.owner.weaponname || self.dmg != self.owner.modelindex || self.deadflag != self.owner.deadflag) - { - self.weaponname = self.owner.weaponname; - self.dmg = self.owner.modelindex; - self.deadflag = self.owner.deadflag; - - CL_WeaponEntity_SetModel(self.owner.weaponname); - } - - tb = (self.effects & (EF_TELEPORT_BIT | EF_RESTARTANIM_BIT)); - self.effects = self.owner.effects & EFMASK_CHEAP; - self.effects &= ~EF_LOWPRECISION; - self.effects &= ~EF_FULLBRIGHT; // can mask team color, so get rid of it - self.effects &= ~EF_TELEPORT_BIT; - self.effects &= ~EF_RESTARTANIM_BIT; - self.effects |= tb; - - if(self.owner.alpha == default_player_alpha) - self.alpha = default_weapon_alpha; - else if(self.owner.alpha != 0) - self.alpha = self.owner.alpha; - else - self.alpha = 1; - - self.glowmod = self.owner.weaponentity_glowmod; - self.colormap = self.owner.colormap; - if (self.weaponentity) - { - self.weaponentity.effects = self.effects; - self.weaponentity.alpha = self.alpha; - self.weaponentity.colormap = self.colormap; - self.weaponentity.glowmod = self.glowmod; - } - - self.angles = '0 0 0'; - - float f = (self.owner.weapon_nextthink - time); - if (self.state == WS_RAISE && !intermission_running) - { - entity newwep = get_weaponinfo(self.owner.switchweapon); - f = f * g_weaponratefactor / max(f, newwep.switchdelay_raise); - self.angles_x = -90 * f * f; - } - else if (self.state == WS_DROP && !intermission_running) - { - entity oldwep = get_weaponinfo(self.owner.weapon); - f = 1 - f * g_weaponratefactor / max(f, oldwep.switchdelay_drop); - self.angles_x = -90 * f * f; - } - else if (self.state == WS_CLEAR) - { - f = 1; - self.angles_x = -90 * f * f; - } -} - -void CL_ExteriorWeaponentity_Think() -{ - float tag_found; - self.nextthink = time; - if (self.owner.exteriorweaponentity != self) - { - remove(self); - return; - } - if (self.owner.deadflag != DEAD_NO) - { - self.model = ""; - return; - } - if (self.weaponname != self.owner.weaponname || self.dmg != self.owner.modelindex || self.deadflag != self.owner.deadflag) - { - self.weaponname = self.owner.weaponname; - self.dmg = self.owner.modelindex; - self.deadflag = self.owner.deadflag; - if (self.owner.weaponname != "") - setmodel(self, strcat("models/weapons/v_", self.owner.weaponname, ".md3")); // precision set below - else - self.model = ""; - - if((tag_found = gettagindex(self.owner, "tag_weapon"))) - { - self.tag_index = tag_found; - self.tag_entity = self.owner; - } - else - setattachment(self, self.owner, "bip01 r hand"); - } - self.effects = self.owner.effects; - self.effects |= EF_LOWPRECISION; - self.effects = self.effects & EFMASK_CHEAP; // eat performance - if(self.owner.alpha == default_player_alpha) - self.alpha = default_weapon_alpha; - else if(self.owner.alpha != 0) - self.alpha = self.owner.alpha; - else - self.alpha = 1; - - self.glowmod = self.owner.weaponentity_glowmod; - self.colormap = self.owner.colormap; - - CSQCMODEL_AUTOUPDATE(); -} - -// spawning weaponentity for client -void CL_SpawnWeaponentity() -{ - self.weaponentity = spawn(); - self.weaponentity.classname = "weaponentity"; - self.weaponentity.solid = SOLID_NOT; - self.weaponentity.owner = self; - setmodel(self.weaponentity, ""); // precision set when changed - setorigin(self.weaponentity, '0 0 0'); - self.weaponentity.angles = '0 0 0'; - self.weaponentity.viewmodelforclient = self; - self.weaponentity.flags = 0; - self.weaponentity.think = CL_Weaponentity_Think; - self.weaponentity.customizeentityforclient = CL_Weaponentity_CustomizeEntityForClient; - self.weaponentity.nextthink = time; - - self.exteriorweaponentity = spawn(); - self.exteriorweaponentity.classname = "exteriorweaponentity"; - self.exteriorweaponentity.solid = SOLID_NOT; - self.exteriorweaponentity.exteriorweaponentity = self.exteriorweaponentity; - self.exteriorweaponentity.owner = self; - setorigin(self.exteriorweaponentity, '0 0 0'); - self.exteriorweaponentity.angles = '0 0 0'; - self.exteriorweaponentity.think = CL_ExteriorWeaponentity_Think; - self.exteriorweaponentity.nextthink = time; - - { - entity oldself = self; - self = self.exteriorweaponentity; - CSQCMODEL_AUTOINIT(); - self = oldself; - } -} - -// Weapon subs -void w_clear() -{ - if (self.weapon != -1) - { - self.weapon = 0; - self.switchingweapon = 0; - } - if (self.weaponentity) - { - self.weaponentity.state = WS_CLEAR; - self.weaponentity.effects = 0; - } -} - -void w_ready() -{ - if (self.weaponentity) - self.weaponentity.state = WS_READY; - weapon_thinkf(WFRAME_IDLE, 1000000, w_ready); -} - -.float prevdryfire; -.float prevwarntime; -float weapon_prepareattack_checkammo(float secondary) -{ - if (!(self.items & IT_UNLIMITED_WEAPON_AMMO)) - if (!WEP_ACTION(self.weapon, WR_CHECKAMMO1 + secondary)) - { - // always keep the Mine Layer if we placed mines, so that we can detonate them - 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 && time - self.prevdryfire > 1) // only play once BEFORE starting to switch weapons - { - sound (self, CH_WEAPON_A, "weapons/dryfire.wav", VOL_BASE, ATTEN_NORM); - self.prevdryfire = time; - } - - if(WEP_ACTION(self.weapon, WR_CHECKAMMO2 - secondary)) // check if the other firing mode has enough ammo - { - if(time - self.prevwarntime > 1) - { - Send_Notification( - NOTIF_ONE, - self, - MSG_MULTI, - ITEM_WEAPON_PRIMORSEC, - self.weapon, - secondary, - (1 - secondary) - ); - } - self.prevwarntime = time; - } - else // this weapon is totally unable to fire, switch to another one - { - W_SwitchToOtherWeapon(self); - } - - return FALSE; - } - return TRUE; -} -.float race_penalty; -float weapon_prepareattack_check(float secondary, float attacktime) -{ - if(!weapon_prepareattack_checkammo(secondary)) - return FALSE; - - //if sv_ready_restart_after_countdown is set, don't allow the player to shoot - //if all players readied up and the countdown is running - if(time < game_starttime || time < self.race_penalty) { - return FALSE; - } - - if (timeout_status == TIMEOUT_ACTIVE) //don't allow the player to shoot while game is paused - return FALSE; - - // do not even think about shooting if switching - if(self.switchweapon != self.weapon) - return FALSE; - - if(attacktime >= 0) - { - // don't fire if previous attack is not finished - if (ATTACK_FINISHED(self) > time + self.weapon_frametime * 0.5) - return FALSE; - // don't fire while changing weapon - if (self.weaponentity.state != WS_READY) - return FALSE; - } - - return TRUE; -} -float weapon_prepareattack_do(float secondary, float attacktime) -{ - self.weaponentity.state = WS_INUSE; - - self.spawnshieldtime = min(self.spawnshieldtime, time); // kill spawn shield when you fire - - // if the weapon hasn't been firing continuously, reset the timer - if(attacktime >= 0) - { - if (ATTACK_FINISHED(self) < time - self.weapon_frametime * 1.5) - { - ATTACK_FINISHED(self) = time; - //dprint("resetting attack finished to ", ftos(time), "\n"); - } - ATTACK_FINISHED(self) = ATTACK_FINISHED(self) + attacktime * W_WeaponRateFactor(); - } - self.bulletcounter += 1; - //dprint("attack finished ", ftos(ATTACK_FINISHED(self)), "\n"); - return TRUE; -} -float weapon_prepareattack(float secondary, float attacktime) -{ - if(weapon_prepareattack_check(secondary, attacktime)) - { - weapon_prepareattack_do(secondary, attacktime); - return TRUE; - } - else - return FALSE; -} - -void weapon_thinkf(float fr, float t, void() func) -{ - vector a; - vector of, or, ou; - float restartanim; - - if(fr == WFRAME_DONTCHANGE) - { - fr = self.weaponentity.wframe; - restartanim = FALSE; - } - else if (fr == WFRAME_IDLE) - restartanim = FALSE; - else - restartanim = TRUE; - - of = v_forward; - or = v_right; - ou = v_up; - - if (self.weaponentity) - { - self.weaponentity.wframe = fr; - a = '0 0 0'; - if (fr == WFRAME_IDLE) - a = self.weaponentity.anim_idle; - else if (fr == WFRAME_FIRE1) - a = self.weaponentity.anim_fire1; - else if (fr == WFRAME_FIRE2) - a = self.weaponentity.anim_fire2; - else // if (fr == WFRAME_RELOAD) - a = self.weaponentity.anim_reload; - a_z *= g_weaponratefactor; - setanim(self.weaponentity, a, restartanim == FALSE, restartanim, restartanim); - } - - v_forward = of; - v_right = or; - v_up = ou; - - if(self.weapon_think == w_ready && func != w_ready && self.weaponentity.state == WS_RAISE) - { - backtrace("Tried to override initial weapon think function - should this really happen?"); - } - - t *= W_WeaponRateFactor(); - - // VorteX: haste can be added here - if (self.weapon_think == w_ready) - { - self.weapon_nextthink = time; - //dprint("started firing at ", ftos(time), "\n"); - } - if (self.weapon_nextthink < time - self.weapon_frametime * 1.5 || self.weapon_nextthink > time + self.weapon_frametime * 1.5) - { - self.weapon_nextthink = time; - //dprint("reset weapon animation timer at ", ftos(time), "\n"); - } - self.weapon_nextthink = self.weapon_nextthink + t; - self.weapon_think = func; - //dprint("next ", ftos(self.weapon_nextthink), "\n"); - - if((fr == WFRAME_FIRE1 || fr == WFRAME_FIRE2) && t) - { - if((self.weapon == WEP_SHOCKWAVE || self.weapon == WEP_SHOTGUN) && fr == WFRAME_FIRE2) - animdecide_setaction(self, ANIMACTION_MELEE, restartanim); - else - animdecide_setaction(self, ANIMACTION_SHOOT, restartanim); - } - else - { - if(self.anim_upper_action == ANIMACTION_SHOOT || self.anim_upper_action == ANIMACTION_MELEE) - self.anim_upper_action = 0; - } -} - -float forbidWeaponUse() -{ - if(time < game_starttime && !autocvar_sv_ready_restart_after_countdown) - return 1; - if(round_handler_IsActive() && !round_handler_IsRoundStarted()) - return 1; - if(self.player_blocked) - return 1; - if(self.frozen) - return 1; - return 0; -} - -void W_WeaponFrame() -{ - vector fo, ri, up; - - if (frametime) - self.weapon_frametime = frametime; - - if (!self.weaponentity || self.health < 1) - return; // Dead player can't use weapons and injure impulse commands - - if(forbidWeaponUse()) - if(self.weaponentity.state != WS_CLEAR) - { - w_ready(); - return; - } - - if(!self.switchweapon) - { - self.weapon = 0; - self.switchingweapon = 0; - self.weaponentity.state = WS_CLEAR; - self.weaponname = ""; - //self.items &= ~IT_AMMO; - return; - } - - makevectors(self.v_angle); - fo = v_forward; // save them in case the weapon think functions change it - ri = v_right; - up = v_up; - - // Change weapon - if (self.weapon != self.switchweapon) - { - if (self.weaponentity.state == WS_CLEAR) - { - // end switching! - self.switchingweapon = self.switchweapon; - entity newwep = get_weaponinfo(self.switchweapon); - - // the two weapon entities will notice this has changed and update their models - self.weapon = self.switchweapon; - self.weaponname = newwep.mdl; - self.bulletcounter = 0; - //self.ammo_field = newwep.ammo_field; - WEP_ACTION(self.switchweapon, WR_SETUP); - self.weaponentity.state = WS_RAISE; - - // set our clip load to the load of the weapon we switched to, if it's reloadable - if(newwep.spawnflags & WEP_FLAG_RELOADABLE && newwep.reloading_ammo) // prevent accessing undefined cvars - { - self.clip_load = self.(weapon_load[self.switchweapon]); - self.clip_size = newwep.reloading_ammo; - } - else - self.clip_load = self.clip_size = 0; - - weapon_thinkf(WFRAME_IDLE, newwep.switchdelay_raise, w_ready); - } - else if (self.weaponentity.state == WS_DROP) - { - // in dropping phase we can switch at any time - self.switchingweapon = self.switchweapon; - } - else if (self.weaponentity.state == WS_READY) - { - // start switching! - self.switchingweapon = self.switchweapon; - entity oldwep = get_weaponinfo(self.weapon); - - // set up weapon switch think in the future, and start drop anim - #ifndef INDEPENDENT_ATTACK_FINISHED - if(ATTACK_FINISHED(self) <= time + self.weapon_frametime * 0.5) - { - #endif - sound(self, CH_WEAPON_SINGLE, "weapons/weapon_switch.wav", VOL_BASE, ATTN_NORM); - self.weaponentity.state = WS_DROP; - weapon_thinkf(WFRAME_DONTCHANGE, oldwep.switchdelay_drop, w_clear); - #ifndef INDEPENDENT_ATTACK_FINISHED - } - #endif - } - } - - // LordHavoc: network timing test code - //if (self.button0) - // print(ftos(frametime), " ", ftos(time), " >= ", ftos(ATTACK_FINISHED(self)), " >= ", ftos(self.weapon_nextthink), "\n"); - - float w; - w = self.weapon; - - // call the think code which may fire the weapon - // and do so multiple times to resolve framerate dependency issues if the - // server framerate is very low and the weapon fire rate very high - float c; - c = 0; - while (c < W_TICSPERFRAME) - { - c = c + 1; - if(w && !(self.weapons & WepSet_FromWeapon(w))) - { - if(self.weapon == self.switchweapon) - W_SwitchWeapon_Force(self, w_getbestweapon(self)); - w = 0; - } - - v_forward = fo; - v_right = ri; - v_up = up; - - if(w) - WEP_ACTION(self.weapon, WR_THINK); - else - WEP_ACTION(self.weapon, WR_GONETHINK); - - if (time + self.weapon_frametime * 0.5 >= self.weapon_nextthink) - { - if(self.weapon_think) - { - v_forward = fo; - v_right = ri; - v_up = up; - self.weapon_think(); - } - else - bprint("\{1}^1ERROR: undefined weapon think function for ", self.netname, "\n"); - } - } -} - -void W_AttachToShotorg(entity flash, vector offset) -{ - entity xflash; - flash.owner = self; - flash.angles_z = random() * 360; - - if(gettagindex(self.weaponentity, "shot")) - setattachment(flash, self.weaponentity, "shot"); - else - setattachment(flash, self.weaponentity, "tag_shot"); - setorigin(flash, offset); - - xflash = spawn(); - copyentity(flash, xflash); - - flash.viewmodelforclient = self; - - if(self.weaponentity.oldorigin_x > 0) - { - setattachment(xflash, self.exteriorweaponentity, ""); - setorigin(xflash, self.weaponentity.oldorigin + offset); - } - else - { - if(gettagindex(self.exteriorweaponentity, "shot")) - setattachment(xflash, self.exteriorweaponentity, "shot"); - else - setattachment(xflash, self.exteriorweaponentity, "tag_shot"); - setorigin(xflash, offset); - } -} - -void W_DecreaseAmmo(float ammo_use) -{ - entity wep = get_weaponinfo(self.weapon); - - if((self.items & IT_UNLIMITED_WEAPON_AMMO) && !wep.reloading_ammo) - return; - - // if this weapon is reloadable, decrease its load. Else decrease the player's ammo - if(wep.reloading_ammo) - { - self.clip_load -= ammo_use; - self.(weapon_load[self.weapon]) = self.clip_load; - } - else if(wep.ammo_field != ammo_none) - { - self.(wep.ammo_field) -= ammo_use; - if(self.(wep.ammo_field) < 0) - { - backtrace(sprintf( - "W_DecreaseAmmo(%.2f): '%s' subtracted too much %s from '%s', resulting with '%.2f' left... " - "Please notify Samual immediately with a copy of this backtrace!\n", - ammo_use, - wep.netname, - GetAmmoPicture(wep.ammo_field), - self.netname, - self.(wep.ammo_field) - )); - } - } -} - -// weapon reloading code - -.float reload_ammo_amount, reload_ammo_min, reload_time; -.float reload_complain; -.string reload_sound; - -void W_ReloadedAndReady() -{ - // finish the reloading process, and do the ammo transfer - - self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading - - // if the gun uses no ammo, max out weapon load, else decrease ammo as we increase weapon load - if(!self.reload_ammo_min || self.items & IT_UNLIMITED_WEAPON_AMMO || self.ammo_field == ammo_none) - self.clip_load = self.reload_ammo_amount; - else - { - while(self.clip_load < self.reload_ammo_amount && self.(self.ammo_field)) // make sure we don't add more ammo than we have - { - self.clip_load += 1; - self.(self.ammo_field) -= 1; - } - } - self.(weapon_load[self.weapon]) = self.clip_load; - - // do not set ATTACK_FINISHED in reload code any more. This causes annoying delays if eg: You start reloading a weapon, - // then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there, - // so your weapon is disabled for a few seconds without reason - - //ATTACK_FINISHED(self) -= self.reload_time - 1; - - w_ready(); -} - -void W_Reload(float sent_ammo_min, string sent_sound) -{ - // set global values to work with - entity e; - e = get_weaponinfo(self.weapon); - - self.reload_ammo_min = sent_ammo_min; - self.reload_ammo_amount = e.reloading_ammo;; - self.reload_time = e.reloading_time; - self.reload_sound = sent_sound; - - // don't reload weapons that don't have the RELOADABLE flag - if (!(e.spawnflags & WEP_FLAG_RELOADABLE)) - { - dprint("Warning: Attempted to reload a weapon that does not have the WEP_FLAG_RELOADABLE flag. Fix your code!\n"); - return; - } - - // return if reloading is disabled for this weapon - if(!self.reload_ammo_amount) - return; - - // our weapon is fully loaded, no need to reload - if (self.clip_load >= self.reload_ammo_amount) - return; - - // no ammo, so nothing to load - if(self.ammo_field != ammo_none) - if(!self.(self.ammo_field) && self.reload_ammo_min) - if (!(self.items & IT_UNLIMITED_WEAPON_AMMO)) - { - if(IS_REAL_CLIENT(self) && self.reload_complain < time) - { - play2(self, "weapons/unavailable.wav"); - sprint(self, strcat("You don't have enough ammo to reload the ^2", WEP_NAME(self.weapon), "\n")); - self.reload_complain = time + 1; - } - // switch away if the amount of ammo is not enough to keep using this weapon - if (!(WEP_ACTION(self.weapon, WR_CHECKAMMO1) + WEP_ACTION(self.weapon, WR_CHECKAMMO2))) - { - self.clip_load = -1; // reload later - W_SwitchToOtherWeapon(self); - } - return; - } - - if (self.weaponentity) - { - if (self.weaponentity.wframe == WFRAME_RELOAD) - return; - - // allow switching away while reloading, but this will cause a new reload! - self.weaponentity.state = WS_READY; - } - - // now begin the reloading process - - sound(self, CH_WEAPON_SINGLE, self.reload_sound, VOL_BASE, ATTEN_NORM); - - // do not set ATTACK_FINISHED in reload code any more. This causes annoying delays if eg: You start reloading a weapon, - // then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there, - // so your weapon is disabled for a few seconds without reason - - //ATTACK_FINISHED(self) = max(time, ATTACK_FINISHED(self)) + self.reload_time + 1; - - weapon_thinkf(WFRAME_RELOAD, self.reload_time, W_ReloadedAndReady); - - if(self.clip_load < 0) - self.clip_load = 0; - self.old_clip_load = self.clip_load; - self.clip_load = self.(weapon_load[self.weapon]) = -1; -} diff --git a/qcsrc/server/weapons/weaponsystem.qh b/qcsrc/server/weapons/weaponsystem.qh deleted file mode 100644 index 47ae74b42..000000000 --- a/qcsrc/server/weapons/weaponsystem.qh +++ /dev/null @@ -1,2 +0,0 @@ -float weaponswapping; -float internalteam; diff --git a/qcsrc/warpzonelib/TODO b/qcsrc/warpzonelib/TODO index 89f527790..5c9a55fc1 100644 --- a/qcsrc/warpzonelib/TODO +++ b/qcsrc/warpzonelib/TODO @@ -6,7 +6,7 @@ Weapon support: - laser: YES - shotgun: YES -- machinegun: YES +- uzi: YES - grenadelauncher: YES - electro: YES - crylink: YES @@ -15,7 +15,7 @@ Weapon support: - rocketlauncher: YES (except for trail bug) - porto: YES (bwahahahaha) - hlac: YES -- vaporizer: YES +- minstanex: YES - rifle: YES - fireball: YES (BFG effect cannot work through warpzones by design, so it's not available through warpzones) - hook: YES diff --git a/qcsrc/warpzonelib/client.qc b/qcsrc/warpzonelib/client.qc index c2a110b4a..f55cec1d5 100644 --- a/qcsrc/warpzonelib/client.qc +++ b/qcsrc/warpzonelib/client.qc @@ -239,8 +239,8 @@ void WarpZone_FixView() vector org, ang, nearclip, corner0, corner1, corner2, corner3, o; float f; - warpzone_save_view_origin = org = getpropertyvec(VF_ORIGIN); - warpzone_save_view_angles = ang = getpropertyvec(VF_ANGLES); + org = getpropertyvec(VF_ORIGIN); + ang = getpropertyvec(VF_ANGLES); #ifdef WORKAROUND_XON010 float dirty; dirty = checkextension("DP_CSQC_ROTATEMOVES"); diff --git a/qcsrc/warpzonelib/client.qh b/qcsrc/warpzonelib/client.qh index c0a4ca0f0..446c917db 100644 --- a/qcsrc/warpzonelib/client.qh +++ b/qcsrc/warpzonelib/client.qh @@ -7,6 +7,3 @@ void WarpZone_FixView(); void WarpZone_Init(); void WarpZone_Shutdown(); - -vector warpzone_save_view_origin; -vector warpzone_save_view_angles; diff --git a/scripts/weapons.shader b/scripts/weapons.shader index c5c673fbf..a6dcfaab8 100644 --- a/scripts/weapons.shader +++ b/scripts/weapons.shader @@ -103,11 +103,3 @@ minelayer rgbgen lightingDiffuse } } -shotgun -{ - dpreflectcube cubemaps/default/sky - { - map textures/arc.tga - rgbgen lightingDiffuse - } -} diff --git a/sound/weapons/gauntlet_fire.ogg b/sound/weapons/gauntlet_fire.ogg new file mode 100644 index 000000000..03802f65d Binary files /dev/null and b/sound/weapons/gauntlet_fire.ogg differ diff --git a/sound/weapons/gauntletbeam_fly.ogg b/sound/weapons/gauntletbeam_fly.ogg new file mode 100644 index 000000000..874d246f5 Binary files /dev/null and b/sound/weapons/gauntletbeam_fly.ogg differ diff --git a/textures/arc.tga b/textures/arc.tga deleted file mode 100644 index 55d2f34b3..000000000 Binary files a/textures/arc.tga and /dev/null differ diff --git a/textures/arc_gloss.tga b/textures/arc_gloss.tga deleted file mode 100644 index 45734a7ef..000000000 Binary files a/textures/arc_gloss.tga and /dev/null differ diff --git a/textures/arc_glow.tga b/textures/arc_glow.tga deleted file mode 100644 index 2b3575116..000000000 Binary files a/textures/arc_glow.tga and /dev/null differ diff --git a/textures/arc_norm.tga b/textures/arc_norm.tga deleted file mode 100644 index 39e183148..000000000 Binary files a/textures/arc_norm.tga and /dev/null differ diff --git a/textures/arc_reflect.tga b/textures/arc_reflect.tga deleted file mode 100644 index b60f891b0..000000000 Binary files a/textures/arc_reflect.tga and /dev/null differ diff --git a/textures/arc_shirt.tga b/textures/arc_shirt.tga deleted file mode 100644 index 90107daa1..000000000 Binary files a/textures/arc_shirt.tga and /dev/null differ diff --git a/vehicles.cfg b/vehicles.cfg index ea296146d..d28aa4cad 100644 --- a/vehicles.cfg +++ b/vehicles.cfg @@ -18,9 +18,9 @@ set cl_vehicles_hudscale 0.5 set g_vehicles_delayspawn 1 set g_vehicles_delayspawn_jitter 10 -set g_vehicles_vortex_damagerate 0.5 -set g_vehicles_machinegun_damagerate 0.65 +set g_vehicles_nex_damagerate 0.5 +set g_vehicles_uzi_damagerate 0.65 set g_vehicles_rifle_damagerate 1 -set g_vehicles_vaporizer_damagerate 0.007 +set g_vehicles_minstanex_damagerate 0.007 set g_vehicles_tag_damagerate 2