From: Samual Lenks Date: Mon, 10 Jun 2013 00:32:18 +0000 (-0400) Subject: Merge remote-tracking branch 'origin/master' into samual/spawn_weapons X-Git-Tag: xonotic-v0.8.0~152^2~408^2~2 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=9d9cf783d3ac428fbbe95553c8f5c7e113d888bb;p=xonotic%2Fxonotic-data.pk3dir.git Merge remote-tracking branch 'origin/master' into samual/spawn_weapons Conflicts: balance25.cfg balanceFruitieX.cfg balanceXPM.cfg balanceXonotic.cfg effectinfo.txt qcsrc/common/constants.qh qcsrc/common/util.qc qcsrc/common/util.qh qcsrc/server/cheats.qc qcsrc/server/cl_client.qc qcsrc/server/cl_weaponsystem.qc qcsrc/server/g_damage.qc qcsrc/server/tturrets/units/unit_walker.qc qcsrc/server/vehicles/raptor.qc qcsrc/server/vehicles/spiderbot.qc qcsrc/server/vehicles/vehicles.qc qcsrc/server/w_crylink.qc qcsrc/server/w_electro.qc qcsrc/server/w_hagar.qc qcsrc/server/w_laser.qc qcsrc/server/w_seeker.qc qcsrc/server/w_shotgun.qc --- 9d9cf783d3ac428fbbe95553c8f5c7e113d888bb diff --cc balance25.cfg index 7b75ebf93,343891810..cf2150bb1 --- a/balance25.cfg +++ b/balance25.cfg @@@ -257,11 -241,8 +256,8 @@@ set g_balance_laser_primary_delay 0.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_reload_ammo 0 //default: 6 - set g_balance_laser_reload_time 2 - +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 @@@ -276,35 -257,11 +272,40 @@@ set g_balance_laser_secondary_delay 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 diff --cc balanceFruitieX.cfg index aad5b3fce,ce125421f..3e6223df7 --- a/balanceFruitieX.cfg +++ b/balanceFruitieX.cfg @@@ -257,11 -241,8 +256,8 @@@ set g_balance_laser_primary_delay 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_reload_ammo 0 //default: 6 - set g_balance_laser_reload_time 2 - +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 @@@ -276,35 -257,11 +272,40 @@@ set g_balance_laser_secondary_delay 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 diff --cc balanceXDF.cfg index 000000000,5745548e2..17b5e88d3 mode 000000,100644..100644 --- a/balanceXDF.cfg +++ b/balanceXDF.cfg @@@ -1,0 -1,709 +1,753 @@@ + 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 + // }}} + + // {{{ 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_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 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.3 ++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_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_speed 8000 + set g_balance_shotgun_primary_bulletconstant 75 // 3.8qu + 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_speed 18000 + set g_balance_uzi_bulletconstant 115 // 13.1qu + + 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_jointime 0 + 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_jointime 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 // 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 --cc balanceXPM.cfg index 5809b4389,8bd086937..daaa0a477 --- a/balanceXPM.cfg +++ b/balanceXPM.cfg @@@ -228,21 -227,6 +227,21 @@@ set g_balance_grapplehook_damagedbycont // {{{ 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 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 @@@ -257,11 -241,8 +256,8 @@@ set g_balance_laser_primary_delay set g_balance_laser_primary_force_zscale 1.25 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_reload_ammo 0 //default: 6 - set g_balance_laser_reload_time 2 - - set g_balance_laser_secondary 0 // 0 = switch away to last used weapon, 1 = projectile secondary, 2 = melee secondary ++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 @@@ -276,35 -257,11 +272,40 @@@ set g_balance_laser_secondary_delay 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 1.5 ++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 100 - set g_balance_laser_shockwave_spread_min 20 ++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 diff --cc balanceXonotic.cfg index 274b59092,930c9dc1f..f1b2426d7 --- a/balanceXonotic.cfg +++ b/balanceXonotic.cfg @@@ -257,11 -241,8 +256,8 @@@ set g_balance_laser_primary_delay set g_balance_laser_primary_force_zscale 1.25 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_reload_ammo 0 //default: 6 - set g_balance_laser_reload_time 2 - +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 @@@ -276,35 -257,11 +272,40 @@@ set g_balance_laser_secondary_delay 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 diff --cc effectinfo.txt index e2491883b,c2f702fa5..980320451 --- a/effectinfo.txt +++ b/effectinfo.txt @@@ -7638,83 -7638,342 +7638,422 @@@ sizeincrease -1 airfriction 0.04 gravity -0.2 + // redflag_touch -- effects for touching the red flag + // used nowhere in code + effect redflag_touch + count 35 + type spark + tex 40 40 + color 0xFF0000 0x970000 + size 1 3 + alpha 0 256 556 + gravity 1 + bounce 1.5 + originjitter 1 1 1 + velocityjitter 300 300 300 + velocitymultiplier 0.5 + airfriction 3 + + // blueflag_touch -- effects for touching the blue flag + // used nowhere in code + effect blueflag_touch + count 35 + type spark + tex 40 40 + color 0x0000FF 0x000097 + size 1 3 + alpha 0 256 556 + gravity 1 + bounce 1.5 + originjitter 1 1 1 + velocityjitter 300 300 300 + velocitymultiplier 0.5 + airfriction 3 + + // red_pass + // used nowhere in code + effect red_pass + trailspacing 64 + color 0xFF0000 0x970000 + size 2 2 + tex 32 32 + alpha 64 128 64 + airfriction 5 + sizeincrease 2 + type static + effect red_pass + trailspacing 12 + color 0xFF0000 0x970000 + size 1 1 + tex 0 8 + alpha 32 64 32 + airfriction 9 + sizeincrease 8 + velocityjitter 64 64 64 + type static + effect red_pass + trailspacing 12 + color 0xFF0000 0x970000 + size 4 4 + //tex 48 55 + alpha 256 256 1280 + type static + + // blue_pass + // used nowhere in code + effect blue_pass + trailspacing 64 + color 0x0000FF 0x000097 + size 2 2 + tex 32 32 + alpha 64 128 64 + airfriction 5 + sizeincrease 2 + type static + effect blue_pass + trailspacing 12 + color 0x0000FF 0x000097 + size 1 1 + tex 0 8 + alpha 32 64 32 + airfriction 9 + sizeincrease 8 + velocityjitter 64 64 64 + type static + effect blue_pass + trailspacing 12 + color 0x0000FF 0x000097 + size 4 4 + //tex 48 55 + alpha 256 256 1280 + type static + + // red_cap -- red team capture effect + effect red_cap + count 500 + type spark + tex 64 64 + color 0xFF0000 0x970000 + size 1 1 + alpha 0 256 100 + stretchfactor 2 + //gravity 1 + bounce 1.5 + originjitter 1 1 1 + velocityjitter 1000 1000 1500 + velocitymultiplier 0.5 + airfriction 2 + stretchfactor 0.6 + effect red_cap + countabsolute 1 + type smoke + tex 65 65 + size 150 150 + alpha 190 190 180 + sizeincrease -80 + color 0xFF0000 0x970000 + + // blue_cap -- blue team capture effect + effect blue_cap + count 500 + type spark + tex 64 64 + color 0x0000FF 0x000097 + size 1 1 + alpha 0 256 100 + stretchfactor 2 + //gravity 1 + bounce 1.5 + originjitter 1 1 1 + velocityjitter 1000 1000 1500 + velocitymultiplier 0.5 + airfriction 2 + stretchfactor 0.6 + effect blue_cap + countabsolute 1 + type smoke + tex 65 65 + size 150 150 + alpha 190 190 180 + sizeincrease -80 + color 0x0000FF 0x000097 + + // spawn_point_red -- red team idle spawn point effect + effect spawn_point_red + count 37.5 + type static + color 0xFF0F0F 0xFF0F0F + size 1.0 2.0 + alpha 64 128 128 + gravity -0.1 + airfriction 0.2 + liquidfriction 0.8 + originjitter 16 16 64 + velocityjitter 32 32 0 + //lightradius 200 + //lighttime 0 + //lightcolor 0.4 0.9 0.9 + + // spawn_point_blue -- blue team idle spawn point effect + effect spawn_point_blue + count 37.5 + type static + color 0x0F0FFF 0x0F0FFF + size 1.0 2.0 + alpha 64 128 128 + gravity -0.1 + airfriction 0.2 + liquidfriction 0.8 + originjitter 16 16 64 + velocityjitter 32 32 0 + //lightradius 200 + //lighttime 0 + //lightcolor 0.4 0.9 0.9 + + // spawn_point_yellow -- yellow team idle spawn point effect + effect spawn_point_yellow + count 37.5 + type static + color 0xFFFF0F 0xFFFF0F + size 1.0 2.0 + alpha 64 128 128 + gravity -0.1 + airfriction 0.2 + liquidfriction 0.8 + originjitter 16 16 64 + velocityjitter 32 32 0 + //lightradius 200 + //lighttime 0 + //lightcolor 0.4 0.9 0.9 + + // spawn_point_pink -- pink team idle spawn point effect + effect spawn_point_pink + count 37.5 + type static + color 0xFF0FFF 0xFF0FFF + size 1.0 2.0 + alpha 64 128 128 + gravity -0.1 + airfriction 0.2 + liquidfriction 0.8 + originjitter 16 16 64 + velocityjitter 32 32 0 + //lightradius 200 + //lighttime 0 + //lightcolor 0.4 0.9 0.9 + + // spawn_point_neutral -- neutral idle spawn point effect + effect spawn_point_neutral + count 37.5 + type static + color 0xFFFFFF 0xFFFFFF + size 1.0 2.0 + alpha 64 128 128 + gravity -0.1 + airfriction 0.2 + liquidfriction 0.8 + originjitter 16 16 64 + velocityjitter 32 32 0 + //lightradius 200 + //lighttime 0 + //lightcolor 0.4 0.9 0.9 + + // spawn_event_red -- red team spawning effect + effect spawn_event_red + count 100 + type spark + tex 64 64 + color 0xFF0F0F 0xFF0F0F + size 1 1 + alpha 0 256 256 + stretchfactor 0.6 + //gravity 1 + bounce 1 + originjitter 1 1 1 + velocityjitter 500 500 500 + velocitymultiplier 0.1 + airfriction 2 + effect spawn_event_red + countabsolute 1 + type smoke + tex 65 65 + size 100 100 + alpha 190 190 180 + sizeincrease -80 + color 0xFF0F0F 0xFF0F0F + + // spawn_event_blue -- blue team spawning effect + effect spawn_event_blue + count 100 + type spark + tex 64 64 + color 0x0F0FFF 0x0F0FFF + size 1 1 + alpha 0 256 256 + stretchfactor 0.6 + //gravity 1 + bounce 1 + originjitter 1 1 1 + velocityjitter 500 500 500 + velocitymultiplier 0.1 + airfriction 2 + effect spawn_event_blue + countabsolute 1 + type smoke + tex 65 65 + size 100 100 + alpha 190 190 180 + sizeincrease -80 + color 0x0F0FFF 0x0F0FFF + + // spawn_event_yellow -- yellow team spawning effect + effect spawn_event_yellow + count 100 + type spark + tex 64 64 + color 0xFFFF0F 0xFFFF0F + size 1 1 + alpha 0 256 256 + stretchfactor 0.6 + //gravity 1 + bounce 1 + originjitter 1 1 1 + velocityjitter 500 500 500 + velocitymultiplier 0.1 + airfriction 2 + effect spawn_event_yellow + countabsolute 1 + type smoke + tex 65 65 + size 100 100 + alpha 190 190 180 + sizeincrease -80 + color 0xFFFF0F 0xFFFF0F + + // spawn_event_pink -- pink team spawning effect + effect spawn_event_pink + count 100 + type spark + tex 64 64 + color 0xFF0FFF 0xFF0FFF + size 1 1 + alpha 0 256 256 + stretchfactor 0.6 + //gravity 1 + bounce 1 + originjitter 1 1 1 + velocityjitter 500 500 500 + velocitymultiplier 0.1 + airfriction 2 + effect spawn_event_pink + countabsolute 1 + type smoke + tex 65 65 + size 100 100 + alpha 190 190 180 + sizeincrease -80 + color 0xFF0FFF 0xFF0FFF + + // spawn_event_neutral -- neutral spawning effect + effect spawn_event_neutral + count 100 + type spark + tex 64 64 + color 0xFFFFFF 0xFFFFFF + size 1 1 + alpha 0 256 256 + stretchfactor 0.6 + //gravity 1 + bounce 1 + originjitter 1 1 1 + velocityjitter 500 500 500 + velocitymultiplier 0.1 + airfriction 2 + effect spawn_event_neutral + countabsolute 1 + type smoke + tex 65 65 + size 100 100 + alpha 190 190 180 + sizeincrease -80 + color 0xFFFFFF 0xFFFFFF + +// laser_shockwave_attack +// used nowhere in code +effect laser_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 +// electricity +effect laser_shockwave_attack +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 +// fire +effect laser_shockwave_attack +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 + +// new_laser_impact +// used nowhere in code +// decal +effect new_laser_impact +countabsolute 1 +type decal +tex 8 16 +size 72 72 +alpha 256 256 0 +originjitter 2 2 2 +// flare effect +//effect new_laser_impact +//countabsolute 1 +//type static +//tex 39 39 +//color 0xFF2010 0xFF2010 +//alpha 256 256 1024 +//size 24 24 +// sparks that rapidly expand and rapidly slow down to form an interesting spherical effect +effect new_laser_impact +count 128 +type spark +color 0x800000 0xFF8020 +alpha 256 256 1024 +size 4 4 +bounce 1.5 +gravity 0.5 +airfriction 1 +liquidfriction 1 +originjitter 20 20 20 +velocityjitter 256 256 256 diff --cc qcsrc/client/particles.qc index 361d244a1,3e2222f4a..0be941217 --- a/qcsrc/client/particles.qc +++ b/qcsrc/client/particles.qc @@@ -301,121 -301,3 +301,121 @@@ void Net_ReadNexgunBeamParticle( else WarpZone_TrailParticles_WithMultiplier(world, particleeffectnum("nex_beam"), shotorg, endpos, charge, 1); } + +.vector sw_shotorg; +.vector sw_endpos; +.float sw_spread_max; +.float sw_spread_min; +.float sw_time; + +void Draw_Shockwave() +{ + float a = bound(0, (0.5 - ((time - self.sw_time) / 0.4)), 0.5); + + if not(a) { remove(self); } + + vector deviation, angle; + + vector sw_color = getcsqcplayercolor(self.sv_entnum); // GetTeamRGB(GetPlayerColor(self.sv_entnum)); + - vector first_min_end, prev_min_end, new_min_end; - vector first_max_end, prev_max_end, new_max_end; ++ 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 shotdir = normalize(self.sw_endpos - self.sw_shotorg); + vectorvectors(shotdir); + vector right = v_right; + vector up = v_up; + + float counter, dist_before_normal = 200, shots = 20; + + vector min_end = ((self.sw_shotorg + (shotdir * dist_before_normal)) + (up * self.sw_spread_min)); + vector max_end = (self.sw_endpos + (up * self.sw_spread_max)); + + float spread_to_min = vlen(normalize(min_end - self.sw_shotorg) - shotdir); + float spread_to_max = vlen(normalize(max_end - min_end) - shotdir); + + for(counter = 0; counter < shots; ++counter) + { + // perfect circle effect lines + angle = '0 0 0'; + makevectors('0 360 0' * (0.75 + (counter - 0.5) / shots)); + angle_y = v_forward_x; + angle_z = v_forward_y; + + // first do the spread_to_min effect + deviation = angle * spread_to_min; + deviation = ((shotdir + (right * deviation_y) + (up * deviation_z))); + new_min_dist = dist_before_normal; + 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 = ((shotdir + (right * deviation_y) + (up * deviation_z))); + new_max_dist = vlen(new_min_end - self.sw_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) + { + 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(); + + 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; + + if((counter + 1) == shots) + { + 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(); + + 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() +{ + 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_endpos_x = ReadCoord(); shockwave.sw_endpos_y = ReadCoord(); shockwave.sw_endpos_z = ReadCoord(); + + shockwave.sw_spread_max = ReadByte(); + shockwave.sw_spread_min = ReadByte(); + + shockwave.sv_entnum = ReadByte(); + + shockwave.sw_time = time; +} + diff --cc qcsrc/common/constants.qh index 903ece9a5,b399f3857..2ff27d743 --- a/qcsrc/common/constants.qh +++ b/qcsrc/common/constants.qh @@@ -30,24 -30,18 +30,19 @@@ const float AS_FLOAT = 8 const float TE_CSQC_PICTURE = 100; const float TE_CSQC_RACE = 101; - const float TE_CSQC_SPAWN = 102; - const float TE_CSQC_ZCURVEPARTICLES = 103; - const float TE_CSQC_NEXGUNBEAMPARTICLE = 104; - const float TE_CSQC_LIGHTNINGARC = 105; - const float TE_CSQC_TEAMNAGGER = 106; - const float TE_CSQC_PINGPLREPORT = 107; - const float TE_CSQC_SHOCKWAVEPARTICLE = 121; - const float TE_CSQC_ANNOUNCE = 110; - const float TE_CSQC_TARGET_MUSIC = 111; - const float TE_CSQC_KILLNOTIFY = 112; - const float TE_CSQC_KILLCENTERPRINT = 113; - const float TE_CSQC_CENTERPRINT_GENERIC = 114; - const float TE_CSQC_WEAPONCOMPLAIN = 115; - const float TE_CSQC_NEX_SCOPE = 116; - const float TE_CSQC_MINELAYER_MAXMINES = 117; - const float TE_CSQC_HAGAR_MAXROCKETS = 118; - const float TE_CSQC_VEHICLESETUP = 119; - const float TE_CSQC_SVNOTICE = 120; + const float TE_CSQC_ZCURVEPARTICLES = 102; + 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_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; @@@ -93,13 -87,16 +88,16 @@@ const float ENT_CLIENT_WARPZONE_CAMERA const float ENT_CLIENT_TRIGGER_MUSIC = 26; const float ENT_CLIENT_HOOK = 27; 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; -const float ENT_CLIENT_MODEL = 33; -const float ENT_CLIENT_ITEM = 34; -const float ENT_CLIENT_BUMBLE_RAYGUN = 35; -const float ENT_CLIENT_SPAWNPOINT = 36; -const float ENT_CLIENT_SPAWNEVENT = 37; -const float ENT_CLIENT_NOTIFICATION = 38; +const float ENT_CLIENT_ACCURACY = 29; +const float ENT_CLIENT_SHOWNAMES = 30; +const float ENT_CLIENT_WARPZONE_TELEPORTED = 31; +const float ENT_CLIENT_MODEL = 32; +const float ENT_CLIENT_ITEM = 33; +const float ENT_CLIENT_BUMBLE_RAYGUN = 34; ++const float ENT_CLIENT_SPAWNPOINT = 35; ++const float ENT_CLIENT_SPAWNEVENT = 36; ++const float ENT_CLIENT_NOTIFICATION = 37; + const float ENT_CLIENT_TURRET = 40; const float ENT_CLIENT_AUXILIARYXHAIR = 50; diff --cc qcsrc/common/util.qc index 11f54c1b1,7fa2f576a..480ebc9fa --- a/qcsrc/common/util.qc +++ b/qcsrc/common/util.qc @@@ -2422,219 -2462,147 +2462,364 @@@ float cubic_speedfunc_is_sane(float sta // (4, 1) } + .float FindConnectedComponent_processing; + void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t nxt, isConnectedFunction_t iscon, entity pass) + { + entity queue_start, queue_end; + + // we build a queue of to-be-processed entities. + // queue_start is the next entity to be checked for neighbors + // queue_end is the last entity added + + if(e.FindConnectedComponent_processing) + error("recursion or broken cleanup"); + + // start with a 1-element queue + queue_start = queue_end = e; + queue_end.fld = world; + queue_end.FindConnectedComponent_processing = 1; + + // for each queued item: + for(; queue_start; queue_start = queue_start.fld) + { + // find all neighbors of queue_start + entity t; + for(t = world; (t = nxt(t, queue_start, pass)); ) + { + if(t.FindConnectedComponent_processing) + continue; + if(iscon(t, queue_start, pass)) + { + // it is connected? ADD IT. It will look for neighbors soon too. + queue_end.fld = t; + queue_end = t; + queue_end.fld = world; + queue_end.FindConnectedComponent_processing = 1; + } + } + } + + // unmark + for(queue_start = e; queue_start; queue_start = queue_start.fld) + queue_start.FindConnectedComponent_processing = 0; + } + ++ +#ifndef MENUQC +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, v2; ++ 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; + */ +} +#endif + +#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) +{ - vector position; + 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) + { + float dev, war; + #ifdef SVQC + dev = autocvar_developer; + war = autocvar_prvm_backtraceforwarnings; + #else + dev = cvar("developer"); + war = cvar("prvm_backtraceforwarnings"); + #endif + cvar_set("developer", "1"); + cvar_set("prvm_backtraceforwarnings", "1"); + print("\n"); + print("--- CUT HERE ---\nWARNING: "); + print(msg); + print("\n"); + remove(world); // isn't there any better way to cause a backtrace? + print("\n--- CUT UNTIL HERE ---\n"); + cvar_set("developer", ftos(dev)); + cvar_set("prvm_backtraceforwarnings", ftos(war)); + } + #endif + + // color code replace, place inside of sprintf and parse the string + string CCR(string input) + { + // See the autocvar declarations in util.qh for default values + + // foreground/normal colors + input = strreplace("^F1", strcat("^", autocvar_hud_colorset_foreground_1), input); + input = strreplace("^F2", strcat("^", autocvar_hud_colorset_foreground_2), input); + input = strreplace("^F3", strcat("^", autocvar_hud_colorset_foreground_3), input); + input = strreplace("^F4", strcat("^", autocvar_hud_colorset_foreground_4), input); + + // "kill" colors + input = strreplace("^K1", strcat("^", autocvar_hud_colorset_kill_1), input); + input = strreplace("^K2", strcat("^", autocvar_hud_colorset_kill_2), input); + input = strreplace("^K3", strcat("^", autocvar_hud_colorset_kill_3), input); + + // background colors + input = strreplace("^BG", strcat("^", autocvar_hud_colorset_background), input); + input = strreplace("^N", "^7", input); // "none"-- reset to white... + return input; + } + + vector vec3(float x, float y, float z) + { + vector v; + v_x = x; + v_y = y; + v_z = z; + return v; + } + + #ifndef MENUQC + vector animfixfps(entity e, vector a, vector b) + { + // multi-frame anim: keep as-is + if(a_y == 1) + { + float dur; + dur = frameduration(e.modelindex, a_x); + if(dur <= 0 && b_y) + { + a = b; + dur = frameduration(e.modelindex, a_x); + } + if(dur > 0) + a_z = 1.0 / dur; + } + return a; + } + #endif + + #ifdef SVQC + void dedicated_print(string input) // print(), but only print if the server is not local + { + if(server_is_dedicated) { print(input); } + } + #endif + + #ifndef MENUQC + float Announcer_PickNumber(float num) + { + switch(num) + { + case 10: num = ANNCE_NUM_10; break; + case 9: num = ANNCE_NUM_9; break; + case 8: num = ANNCE_NUM_8; break; + case 7: num = ANNCE_NUM_7; break; + case 6: num = ANNCE_NUM_6; break; + case 5: num = ANNCE_NUM_5; break; + case 4: num = ANNCE_NUM_4; break; + case 3: num = ANNCE_NUM_3; break; + case 2: num = ANNCE_NUM_2; break; + case 1: num = ANNCE_NUM_1; break; + } + return num; + } + #endif diff --cc qcsrc/common/util.qh index 119ba9830,e9bd01cfa..27cc0ec8b --- a/qcsrc/common/util.qh +++ b/qcsrc/common/util.qh @@@ -334,10 -342,67 +342,75 @@@ float cubic_speedfunc(float startspeedf // as it may exceed 0..1 bounds, or go in reverse float cubic_speedfunc_is_sane(float startspeedfactor, float endspeedfactor); + typedef entity(entity cur, entity near, entity pass) findNextEntityNearFunction_t; + typedef float(entity a, entity b, entity pass) isConnectedFunction_t; + void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t nxt, isConnectedFunction_t iscon, entity pass); + +#ifndef MENUQC - vector W_CalculateSpread(vector forward, float spread, float spreadfactor, float spreadstyle) ++vector W_CalculateSpread(vector forward, float spread, float spreadfactor, float spreadstyle); +#endif + +#ifdef SVQC +vector get_corner_position(entity box, float corner); +#endif ++ + // expand multiple arguments into one argument by stripping parenthesis + #define XPD(...) __VA_ARGS__ + + #ifndef MENUQC + void backtrace(string msg); + #endif + + // color code replace, place inside of sprintf and parse the string... defaults described as constants + // foreground/normal colors + var string autocvar_hud_colorset_foreground_1 = "2"; // F1 - Green // primary priority (important names, etc) + var string autocvar_hud_colorset_foreground_2 = "3"; // F2 - Yellow // secondary priority (items, locations, numbers, etc) + var string autocvar_hud_colorset_foreground_3 = "4"; // F3 - Blue // tertiary priority or relatively inconsequential text + var string autocvar_hud_colorset_foreground_4 = "1"; // F4 - Red // notice/attention grabbing texting + // "kill" colors + var string autocvar_hud_colorset_kill_1 = "1"; // K1 - Red // "bad" or "dangerous" text (death messages against you, kill notifications, etc) + var string autocvar_hud_colorset_kill_2 = "3"; // K2 - Yellow // similar to above, but less important... OR, a highlight out of above message type + var string autocvar_hud_colorset_kill_3 = "4"; // K3 - Blue // "good" or "beneficial" text (you fragging someone, etc) + // background color + var string autocvar_hud_colorset_background = "7"; // BG - White // neutral/unimportant text + + string CCR(string input); + + #ifndef MENUQC + #ifdef CSQC + #define GENTLE (autocvar_cl_gentle || autocvar_cl_gentle_messages) + #else + #define GENTLE autocvar_sv_gentle + #endif + #define normal_or_gentle(normal,gentle) (GENTLE ? ((gentle != "") ? gentle : normal) : normal) + #endif + + // allow writing to also pass through to spectators (like so spectators see the same centerprints as players for example) + #define WRITESPECTATABLE_MSG_ONE_VARNAME(varname,statement) entity varname; varname = msg_entity; FOR_EACH_REALCLIENT(msg_entity) if(msg_entity == varname || (msg_entity.classname == STR_SPECTATOR && msg_entity.enemy == varname)) statement msg_entity = varname + #define WRITESPECTATABLE_MSG_ONE(statement) WRITESPECTATABLE_MSG_ONE_VARNAME(oldmsg_entity, statement) + #define WRITESPECTATABLE(msg,statement) if(msg == MSG_ONE) { WRITESPECTATABLE_MSG_ONE(statement); } else statement float WRITESPECTATABLE_workaround = 0 + + vector vec3(float x, float y, float z); + + #ifndef MENUQC + vector animfixfps(entity e, vector a, vector b); + #endif + + #ifdef SVQC + void dedicated_print(string input); + #endif + + // todo: better way to do this? + #ifdef MENUQC + #define PROGNAME "MENUQC" + #else + #ifdef SVQC + #define PROGNAME "SVQC" + #else + #define PROGNAME "CSQC" + #endif + #endif + + #ifndef MENUQC + float Announcer_PickNumber(float num); + #endif diff --cc qcsrc/server/autocvars.qh index 9819495f9,dead5a9d4..2ae723012 --- a/qcsrc/server/autocvars.qh +++ b/qcsrc/server/autocvars.qh @@@ -446,57 -420,27 +434,57 @@@ float autocvar_g_balance_laser_primary_ 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_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_primary_spread; ++//float autocvar_g_balance_laser_primary_spread; +float autocvar_g_balance_laser_reload_ammo; +float autocvar_g_balance_laser_reload_time; 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_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_laser_secondary_refire; - float autocvar_g_balance_laser_secondary_speed; ++//float autocvar_g_balance_laser_secondary_speed; +float autocvar_g_balance_laser_shockwave_damage; +float autocvar_g_balance_laser_shockwave_distance; +float autocvar_g_balance_laser_shockwave_edgedamage; +float autocvar_g_balance_laser_shockwave_force; +float autocvar_g_balance_laser_shockwave_force_forwardbias; +float autocvar_g_balance_laser_shockwave_force_zscale; +float autocvar_g_balance_laser_shockwave_jump_damage; +float autocvar_g_balance_laser_shockwave_jump_edgedamage; +float autocvar_g_balance_laser_shockwave_jump_force; +float autocvar_g_balance_laser_shockwave_jump_force_velocitybias; +float autocvar_g_balance_laser_shockwave_jump_force_zscale; +float autocvar_g_balance_laser_shockwave_jump_multiplier_accuracy; +float autocvar_g_balance_laser_shockwave_jump_multiplier_distance; +float autocvar_g_balance_laser_shockwave_jump_multiplier_min; +float autocvar_g_balance_laser_shockwave_jump_radius; +float autocvar_g_balance_laser_shockwave_multiplier_accuracy; +float autocvar_g_balance_laser_shockwave_multiplier_distance; +float autocvar_g_balance_laser_shockwave_multiplier_min; +float autocvar_g_balance_laser_shockwave_splash_damage; +float autocvar_g_balance_laser_shockwave_splash_edgedamage; +float autocvar_g_balance_laser_shockwave_splash_force; +float autocvar_g_balance_laser_shockwave_splash_force_forwardbias; +float autocvar_g_balance_laser_shockwave_splash_multiplier_accuracy; +float autocvar_g_balance_laser_shockwave_splash_multiplier_distance; +float autocvar_g_balance_laser_shockwave_splash_multiplier_min; +float autocvar_g_balance_laser_shockwave_splash_radius; +float autocvar_g_balance_laser_shockwave_spread_max; +float autocvar_g_balance_laser_shockwave_spread_min; float autocvar_g_balance_minelayer_ammo; float autocvar_g_balance_minelayer_animtime; float autocvar_g_balance_minelayer_damage; diff --cc qcsrc/server/cheats.qc index deacc0771,017999d76..81b34efa6 --- a/qcsrc/server/cheats.qc +++ b/qcsrc/server/cheats.qc @@@ -271,32 -249,24 +249,24 @@@ float CheatImpulse(float i break; case CHIMPULSE_R00T: IS_CHEAT(i, 0, 0); + RandomSelection_Init(); FOR_EACH_PLAYER(e) - { - get_model_parameters(e.playermodel, e.skin); - if(get_model_parameters_sex == "Female") - { - makevectors(e.angles); - traceline(e.origin, e.origin + v_right * 256, MOVE_NORMAL, e); - } - else - { - org_x = random(); - org_y = random(); - org_z = 0; - org = normalize(org); - traceline(e.origin, e.origin + org * 256, MOVE_NORMAL, e); // random direction - } + if(e.deadflag == DEAD_NO) + if(IsDifferentTeam(e, self)) + RandomSelection_Add(e, 0, string_null, 1, 1); + if(RandomSelection_chosen_ent) + e = RandomSelection_chosen_ent; + else + e = self; - org = findbetterlocation(trace_endpos, 12); + pointparticles(particleeffectnum("rocket_explode"), e.origin, '0 0 0', 1); + sound(e, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); + + e2 = spawn(); + setorigin(e2, e.origin); - RadiusDamage(e2, self, 1000, 0, 128, world, 500, DEATH_CHEAT, e); ++ RadiusDamage(e2, self, 1000, 0, 128, world, world, 500, DEATH_CHEAT, e); + remove(e2); - e2 = spawn(); - setorigin(e2, org); - pointparticles(particleeffectnum("rocket_explode"), org, '0 0 0', 1); - sound(e2, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); - RadiusDamage(e2, e, 1000, 0, 128, e, world, 500, DEATH_CHEAT, world); - remove(e2); - } print("404 Sportsmanship not found.\n"); DID_CHEAT(); break; diff --cc qcsrc/server/g_damage.qc index 848255a89,da013fc75..226e1c69a --- a/qcsrc/server/g_damage.qc +++ b/qcsrc/server/g_damage.qc @@@ -1032,133 -858,176 +856,130 @@@ float RadiusDamageForSource (entity inf while (targ) { next = targ.chain; - if (targ != inflictor) - if (ignore != targ) if(targ.takedamage) + 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) { - 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 finaldmg; + if (power > 1) + power = 1; + finaldmg = coredamage * power + edgedamage * (1 - power); + if (finaldmg > 0) { - 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, blastorigin); - - // if it's a player, use the view origin as reference - center = CENTER_OR_VIEWOFS(targ); + float a; + float c; + vector hitloc; + vector myblastorigin; + vector center; - force = normalize(center - myblastorigin); - force = force * (finaldmg / coredamage) * forceintensity; - hitloc = nearest; + myblastorigin = WarpZone_TransformOrigin(targ, inflictororigin); - if(targ != directhitentity) - { - float hits; - float total; - float hitratio; - float mininv_f, mininv_d; + // if it's a player, use the view origin as reference - if (targ.classname == "player") - center = targ.origin + targ.view_ofs; - else - center = targ.origin + (targ.mins + targ.maxs) * 0.5; ++ center = CENTER_OR_VIEWOFS(targ); - // test line of sight to multiple positions on box, - // and do damage if any of them hit - hits = 0; + force = normalize(center - myblastorigin); + force = force * (finaldmg / coredamage) * forceintensity; + hitloc = nearest; - // we know: max stddev of hitratio = 1 / (2 * sqrt(n)) - // so for a given max stddev: - // n = (1 / (2 * max stddev of hitratio))^2 + if(targ != directhitentity) + { + float hits; + float total; + float hitratio; + float mininv_f, mininv_d; - mininv_d = (finaldmg * (1-tfloordmg)) / autocvar_g_throughfloor_damage_max_stddev; - mininv_f = (vlen(force) * (1-tfloorforce)) / autocvar_g_throughfloor_force_max_stddev; + // test line of sight to multiple positions on box, + // and do damage if any of them hit + hits = 0; - if(autocvar_g_throughfloor_debug) - print(sprintf("THROUGHFLOOR: D=%f F=%f max(dD)=1/%f max(dF)=1/%f", finaldmg, vlen(force), mininv_d, mininv_f)); + // we know: max stddev of hitratio = 1 / (2 * sqrt(n)) + // so for a given max stddev: + // n = (1 / (2 * max stddev of hitratio))^2 - total = 0.25 * pow(max(mininv_f, mininv_d), 2); + 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) - print(sprintf(" steps=%f", total)); + if(autocvar_g_throughfloor_debug) + print(sprintf("THROUGHFLOOR: D=%f F=%f max(dD)=1/%f max(dF)=1/%f", finaldmg, vlen(force), mininv_d, mininv_f)); - 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)); + total = 0.25 * pow(max(mininv_f, mininv_d), 2); - if(autocvar_g_throughfloor_debug) - print(sprintf(" 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) + print(sprintf(" steps=%f", total)); - if (targ.classname == "player") - 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; - } - - 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 (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) - print(sprintf(" D=%f F=%f\n", finaldmg, vlen(force))); - } + if(autocvar_g_throughfloor_debug) + print(sprintf(" steps=%f dD=%f dF=%f", total, finaldmg * (1-tfloordmg) / (2 * sqrt(total)), vlen(force) * (1-tfloorforce) / (2 * sqrt(total)))); - // laser force adjustments :P - if(DEATH_WEAPONOF(deathtype) == WEP_LASER) + for(c = 0; c < total; ++c) { - if (targ == attacker) - { - 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 - { - 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 + //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(deathtype & HITTYPE_SECONDARY) - { - force *= autocvar_g_balance_laser_secondary_force_other_scale; - } + ++hits; + if (hits > 1) + hitloc = hitloc + nearest; else - { - force *= autocvar_g_balance_laser_primary_force_other_scale; - } + 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 (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) - { - total_damage_to_creatures += finaldmg; + 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(accuracy_isgooddamage(attacker, targ)) - stat_damagedone += finaldmg; - } + if(autocvar_g_throughfloor_debug) + print(sprintf(" D=%f F=%f\n", finaldmg, vlen(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); + //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) + { + total_damage_to_creatures += 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); } } } diff --cc qcsrc/server/mutators/mutator_touchexplode.qc index 000000000,f51ed653a..3a9038f51 mode 000000,100644..100644 --- a/qcsrc/server/mutators/mutator_touchexplode.qc +++ b/qcsrc/server/mutators/mutator_touchexplode.qc @@@ -1,0 -1,46 +1,46 @@@ + .float touchexplode_time; + + void PlayerTouchExplode(entity p1, entity p2) + { + vector org; + org = (p1.origin + p2.origin) * 0.5; + org_z += (p1.mins_z + p2.mins_z) * 0.5; + + sound(self, CH_TRIGGER, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM); + pointparticles(particleeffectnum("explosion_small"), org, '0 0 0', 1); + + entity e; + e = spawn(); + setorigin(e, org); - RadiusDamage(e, world, autocvar_g_touchexplode_damage, autocvar_g_touchexplode_edgedamage, autocvar_g_touchexplode_radius, world, autocvar_g_touchexplode_force, DEATH_TOUCHEXPLODE, world); ++ RadiusDamage(e, world, autocvar_g_touchexplode_damage, autocvar_g_touchexplode_edgedamage, autocvar_g_touchexplode_radius, world, world, autocvar_g_touchexplode_force, DEATH_TOUCHEXPLODE, world); + remove(e); + } + + MUTATOR_HOOKFUNCTION(touchexplode_PlayerThink) + { + if(time > self.touchexplode_time) + if not(gameover) + if(IS_PLAYER(self)) + if(self.deadflag == DEAD_NO) + if not(IS_INDEPENDENT_PLAYER(self)) + FOR_EACH_PLAYER(other) if(self != other) + { + if(time > other.touchexplode_time) + if(other.deadflag == DEAD_NO) + if not(IS_INDEPENDENT_PLAYER(other)) + if(boxesoverlap(self.absmin, self.absmax, other.absmin, other.absmax)) + { + PlayerTouchExplode(self, other); + self.touchexplode_time = other.touchexplode_time = time + 0.2; + } + } + + return FALSE; + } + + MUTATOR_DEFINITION(mutator_touchexplode) + { + MUTATOR_HOOK(PlayerPreThink, touchexplode_PlayerThink, CBC_ORDER_ANY); + + return FALSE; + } diff --cc qcsrc/server/tturrets/system/system_main.qc index 12a3fc48e,48a457a57..75ee83250 --- a/qcsrc/server/tturrets/system/system_main.qc +++ b/qcsrc/server/tturrets/system/system_main.qc @@@ -145,10 -145,10 +145,10 @@@ void turret_projectile_explode( { self.takedamage = DAMAGE_NO; - self.event_damage = SUB_Null; + self.event_damage = func_null; #ifdef TURRET_DEBUG float d; - d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world); + d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, world, 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 diff --cc qcsrc/server/tturrets/units/unit_walker.qc index 482e919c2,20100de04..f010a2cdb --- a/qcsrc/server/tturrets/units/unit_walker.qc +++ b/qcsrc/server/tturrets/units/unit_walker.qc @@@ -51,7 -51,7 +51,8 @@@ 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_WALKER_ROCKET, world); - RadiusDamage (self, self.owner, autocvar_g_turrets_unit_walker_std_rocket_dmg, 0, autocvar_g_turrets_unit_walker_std_rocket_radius, self, autocvar_g_turrets_unit_walker_std_rocket_force, DEATH_TURRET_WALK_ROCKET, world); ++ 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); ++ remove (self); } diff --cc qcsrc/server/vehicles/bumblebee.qc index c0e354715,a53068063..b551fd3c7 --- a/qcsrc/server/vehicles/bumblebee.qc +++ b/qcsrc/server/vehicles/bumblebee.qc @@@ -740,9 -731,9 +731,9 @@@ 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, + autocvar_g_vehicle_bumblebee_blowup_radius, self, world, autocvar_g_vehicle_bumblebee_blowup_forceintensity, - DEATH_WAKIBLOWUP, world); + DEATH_VH_BUMB_DEATH, world); sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM); pointparticles(particleeffectnum("explosion_large"), randomvec() * 80 + (self.origin + '0 0 100'), '0 0 0', 1); diff --cc qcsrc/server/vehicles/racer.qc index c52ab5213,f5788c60b..d107dde3f --- a/qcsrc/server/vehicles/racer.qc +++ b/qcsrc/server/vehicles/racer.qc @@@ -540,12 -540,12 +540,12 @@@ 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, + autocvar_g_vehicle_racer_blowup_radius, world, world, autocvar_g_vehicle_racer_blowup_forceintensity, - DEATH_WAKIBLOWUP, world); + DEATH_VH_WAKI_DEATH, world); self.nextthink = time + autocvar_g_vehicle_racer_respawntime; - self.think = racer_spawn; + self.think = racer_spawn_default; self.movetype = MOVETYPE_NONE; self.effects = EF_NODRAW; diff --cc qcsrc/server/vehicles/raptor.qc index b4f597ff5,e899d4a31..a80e1f6dc --- a/qcsrc/server/vehicles/raptor.qc +++ b/qcsrc/server/vehicles/raptor.qc @@@ -92,8 -92,8 +92,8 @@@ void raptor_bomblet_boom( { RadiusDamage (self, self.realowner, autocvar_g_vehicle_raptor_bomblet_damage, autocvar_g_vehicle_raptor_bomblet_edgedamage, - autocvar_g_vehicle_raptor_bomblet_radius, world, + autocvar_g_vehicle_raptor_bomblet_radius, world, world, - autocvar_g_vehicle_raptor_bomblet_force, DEATH_RAPTOR_BOMB, world); + autocvar_g_vehicle_raptor_bomblet_force, DEATH_VH_RAPT_BOMB, world); remove(self); } @@@ -690,8 -690,7 +690,8 @@@ void raptor_blowup( { self.deadflag = DEAD_DEAD; self.vehicle_exit(VHEF_NORMAL); - RadiusDamage (self, self.enemy, 250, 15, 250, world, 250, DEATH_VH_RAPT_DEATH, world); + - RadiusDamage (self, self.enemy, 250, 15, 250, world, world, 250, DEATH_WAKIBLOWUP, world); ++ RadiusDamage (self, self.enemy, 250, 15, 250, world, world, 250, DEATH_VH_RAPT_DEATH, world); self.alpha = -1; self.movetype = MOVETYPE_NONE; diff --cc qcsrc/server/vehicles/spiderbot.qc index 58bf416e3,a66b56477..1f0701cd5 --- a/qcsrc/server/vehicles/spiderbot.qc +++ b/qcsrc/server/vehicles/spiderbot.qc @@@ -723,7 -723,7 +723,7 @@@ void spiderbot_blowup( SUB_SetFade(g1, time, min(autocvar_g_vehicle_spiderbot_respawntime, 10)); SUB_SetFade(g2, time, min(autocvar_g_vehicle_spiderbot_respawntime, 10)); - RadiusDamage (self, self.enemy, 250, 15, 250, world, world, 250, DEATH_SBBLOWUP, world); - RadiusDamage (self, self.enemy, 250, 15, 250, world, 250, DEATH_VH_SPID_DEATH, world); ++ RadiusDamage (self, self.enemy, 250, 15, 250, world, world, 250, DEATH_VH_SPID_DEATH, world); self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = -1; self.movetype = MOVETYPE_NONE; diff --cc qcsrc/server/vehicles/vehicles.qc index 3dcf0fc2f,1e78bd5a2..3b7caf6e2 --- a/qcsrc/server/vehicles/vehicles.qc +++ b/qcsrc/server/vehicles/vehicles.qc @@@ -397,8 -396,8 +396,8 @@@ void vehicles_projectile_explode( PROJECTILE_TOUCH; - self.event_damage = SUB_Null; + self.event_damage = func_null; - RadiusDamage (self, self.realowner, self.shot_dmg, 0, self.shot_radius, self, self.shot_force, self.totalfrags, other); + RadiusDamage (self, self.realowner, self.shot_dmg, 0, self.shot_radius, self, world, self.shot_force, self.totalfrags, other); remove (self); } diff --cc qcsrc/server/w_crylink.qc index 5a19edf36,4cce61bbe..7cfc6c385 --- a/qcsrc/server/w_crylink.qc +++ b/qcsrc/server/w_crylink.qc @@@ -242,7 -274,10 +274,10 @@@ void W_Crylink_Touch (void f = autocvar_g_balance_crylink_primary_bouncedamagefactor; if(a) f *= a; - if (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, world, autocvar_g_balance_crylink_primary_force * f, self.projectiledeathtype, other) && autocvar_g_balance_crylink_primary_linkexplode) + - 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); ++ 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, 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; @@@ -283,7 -318,10 +318,10 @@@ void W_Crylink_Touch2 (void f = autocvar_g_balance_crylink_secondary_bouncedamagefactor; if(a) f *= a; - if (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, world, autocvar_g_balance_crylink_secondary_force * f, self.projectiledeathtype, other) && autocvar_g_balance_crylink_secondary_linkexplode) + - 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); ++ 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, 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; diff --cc qcsrc/server/w_electro.qc index 19f8b4443,649e72374..6634d3ae1 --- a/qcsrc/server/w_electro.qc +++ b/qcsrc/server/w_electro.qc @@@ -54,8 -64,8 +64,9 @@@ void W_Plasma_Explode_Combo (void { W_Plasma_TriggerCombo(self.origin, autocvar_g_balance_electro_combo_comboradius, self.realowner); - self.event_damage = SUB_Null; + self.event_damage = func_null; - RadiusDamage (self, self.realowner, autocvar_g_balance_electro_combo_damage, autocvar_g_balance_electro_combo_edgedamage, autocvar_g_balance_electro_combo_radius, world, autocvar_g_balance_electro_combo_force, WEP_ELECTRO | HITTYPE_BOUNCE, world); // use THIS type for a combo because primary can't bounce + RadiusDamage (self, self.realowner, autocvar_g_balance_electro_combo_damage, autocvar_g_balance_electro_combo_edgedamage, autocvar_g_balance_electro_combo_radius, world, world, autocvar_g_balance_electro_combo_force, WEP_ELECTRO | HITTYPE_BOUNCE, world); // use THIS type for a combo because primary can't bounce ++ remove (self); } diff --cc qcsrc/server/w_hagar.qc index fdf7eaaae,0be6ea527..01a716949 --- a/qcsrc/server/w_hagar.qc +++ b/qcsrc/server/w_hagar.qc @@@ -6,16 -16,16 +16,16 @@@ REGISTER_WEAPON void W_Hagar_Explode (void) { - self.event_damage = SUB_Null; + self.event_damage = func_null; - RadiusDamage (self, self.realowner, autocvar_g_balance_hagar_primary_damage, autocvar_g_balance_hagar_primary_edgedamage, autocvar_g_balance_hagar_primary_radius, world, autocvar_g_balance_hagar_primary_force, self.projectiledeathtype, other); + RadiusDamage (self, self.realowner, autocvar_g_balance_hagar_primary_damage, autocvar_g_balance_hagar_primary_edgedamage, autocvar_g_balance_hagar_primary_radius, world, world, autocvar_g_balance_hagar_primary_force, self.projectiledeathtype, other); remove (self); } void W_Hagar_Explode2 (void) { - self.event_damage = SUB_Null; + self.event_damage = func_null; - RadiusDamage (self, self.realowner, autocvar_g_balance_hagar_secondary_damage, autocvar_g_balance_hagar_secondary_edgedamage, autocvar_g_balance_hagar_secondary_radius, world, autocvar_g_balance_hagar_secondary_force, self.projectiledeathtype, other); + RadiusDamage (self, self.realowner, autocvar_g_balance_hagar_secondary_damage, autocvar_g_balance_hagar_secondary_edgedamage, autocvar_g_balance_hagar_secondary_radius, world, world, autocvar_g_balance_hagar_secondary_force, self.projectiledeathtype, other); remove (self); } diff --cc qcsrc/server/w_hlac.qc index 231832602,0b5d386fd..cc7f05355 --- a/qcsrc/server/w_hlac.qc +++ b/qcsrc/server/w_hlac.qc @@@ -7,12 -17,12 +17,12 @@@ void W_HLAC_Touch (void { PROJECTILE_TOUCH; - self.event_damage = SUB_Null; + self.event_damage = func_null; if(self.projectiledeathtype & HITTYPE_SECONDARY) - RadiusDamage (self, self.realowner, autocvar_g_balance_hlac_secondary_damage, autocvar_g_balance_hlac_secondary_edgedamage, autocvar_g_balance_hlac_secondary_radius, world, autocvar_g_balance_hlac_secondary_force, self.projectiledeathtype, other); + RadiusDamage (self, self.realowner, autocvar_g_balance_hlac_secondary_damage, autocvar_g_balance_hlac_secondary_edgedamage, autocvar_g_balance_hlac_secondary_radius, world, 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); + RadiusDamage (self, self.realowner, autocvar_g_balance_hlac_primary_damage, autocvar_g_balance_hlac_primary_edgedamage, autocvar_g_balance_hlac_primary_radius, world, world, autocvar_g_balance_hlac_primary_force, self.projectiledeathtype, other); remove (self); } diff --cc qcsrc/server/w_laser.qc index 25e240357,d68240c56..5af71d224 --- a/qcsrc/server/w_laser.qc +++ b/qcsrc/server/w_laser.qc @@@ -1,5 -1,15 +1,15 @@@ #ifdef REGISTER_WEAPON - REGISTER_WEAPON(LASER, W_Laser, 0, 1, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, 0, "laser", "laser", _("Blaster")) + 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") ++/* fullname */ _("Blaster") + ); #else #ifdef SVQC void(float imp) W_SwitchWeapon; @@@ -28,14 -19,13 +38,15 @@@ void W_Laser_Touch( { PROJECTILE_TOUCH; - self.event_damage = SUB_Null; + self.event_damage = func_null; - if (self.dmg) - RadiusDamage (self, self.realowner, autocvar_g_balance_laser_secondary_damage, autocvar_g_balance_laser_secondary_edgedamage, autocvar_g_balance_laser_secondary_radius, world, autocvar_g_balance_laser_secondary_force, self.projectiledeathtype, other); + + 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, 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); + RadiusDamage(self, self.realowner, autocvar_g_balance_laser_primary_damage, autocvar_g_balance_laser_primary_edgedamage, autocvar_g_balance_laser_primary_radius, world, world, autocvar_g_balance_laser_primary_force, self.projectiledeathtype, other); - remove (self); + remove(self); } void W_Laser_Think() @@@ -51,324 -39,7 +62,324 @@@ CSQCProjectile(self, TRUE, PROJECTILE_LASER, TRUE); } -void W_Laser_Attack (float issecondary) + +float W_Laser_Shockwave_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 = (autocvar_g_balance_laser_shockwave_spread_min * (1 - spreadlimit) + autocvar_g_balance_laser_shockwave_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_Laser_Shockwave_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_Laser_Shockwave_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_Laser_Shockwave_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_Laser_Shockwave_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; +} + +#define PLAYER_CENTER(ent) (ent.origin + ((ent.classname == "player") ? ent.view_ofs : ((ent.mins + ent.maxs) * 0.5))) + +entity shockwave_hit[32]; +float shockwave_hit_damage[32]; +vector shockwave_hit_force[32]; + +float W_Laser_Shockwave_CheckHit(float queue, entity head, vector final_force, float final_damage) +{ + if not(head) { return FALSE; } + float i; + + ++queue; + + for(i = 1; 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_Laser_Shockwave() +{ + // declarations + float multiplier, multiplier_from_accuracy, multiplier_from_distance; - float final_damage, final_spread; ++ float final_damage; //, final_spread; + vector final_force, center, vel; + entity head, next; + - float i, queue; ++ float i, queue = 0; + + // set up the shot direction + W_SetupShot(self, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_B, autocvar_g_balance_laser_shockwave_damage); + vector attack_endpos = (w_shotorg + (w_shotdir * autocvar_g_balance_laser_shockwave_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; ++ //entity transform = WarpZone_trace_transform; + + // do the firing effect now + SendCSQCShockwaveParticle(attack_endpos); + Damage_DamageInfo(attack_hitpos, autocvar_g_balance_laser_shockwave_splash_damage, autocvar_g_balance_laser_shockwave_splash_edgedamage, autocvar_g_balance_laser_shockwave_splash_radius, w_shotdir * autocvar_g_balance_laser_shockwave_splash_force, WEP_LASER, 0, self); + + // splash damage/jumping trace + head = WarpZone_FindRadius(attack_hitpos, max(autocvar_g_balance_laser_shockwave_splash_radius, autocvar_g_balance_laser_shockwave_jump_radius), FALSE); + while(head) + { + next = head.chain; + + if(head.takedamage) + { + // if it's a player, use the view origin as reference (stolen from RadiusDamage functions in g_damage.qc) + center = PLAYER_CENTER(head); + + float distance_to_head = vlen(attack_hitpos - head.WarpZone_findradius_nearest); + + if((head == self) && (distance_to_head <= autocvar_g_balance_laser_shockwave_jump_radius)) + { + multiplier_from_accuracy = (1 - (distance_to_head ? min(1, (distance_to_head / autocvar_g_balance_laser_shockwave_jump_radius)) : 0)); + multiplier_from_distance = (1 - (distance_to_hit ? min(1, (distance_to_hit / distance_to_end)) : 0)); + multiplier = max(autocvar_g_balance_laser_shockwave_jump_multiplier_min, ((multiplier_from_accuracy * autocvar_g_balance_laser_shockwave_jump_multiplier_accuracy) + (multiplier_from_distance * autocvar_g_balance_laser_shockwave_jump_multiplier_distance))); + + final_force = ((normalize(center - attack_hitpos) * autocvar_g_balance_laser_shockwave_jump_force) * multiplier); + vel = head.velocity; vel_z = 0; + vel = normalize(vel) * bound(0, vlen(vel) / autocvar_sv_maxspeed, 1) * autocvar_g_balance_laser_shockwave_jump_force_velocitybias; + final_force = (vlen(final_force) * normalize(normalize(final_force) + vel)); + final_force_z *= autocvar_g_balance_laser_shockwave_jump_force_zscale; + final_damage = (autocvar_g_balance_laser_shockwave_jump_damage * multiplier + autocvar_g_balance_laser_shockwave_jump_edgedamage * (1 - multiplier)); + + Damage(head, self, self, final_damage, WEP_LASER, head.origin, final_force); + //print("SELF HIT: multiplier = ", ftos(multiplier), strcat(", damage = ", ftos(final_damage), ", force = ", ftos(vlen(final_force))),"... multiplier_from_accuracy = ", ftos(multiplier_from_accuracy), ", multiplier_from_distance = ", ftos(multiplier_from_distance), ".\n"); + } + else if (distance_to_head <= autocvar_g_balance_laser_shockwave_splash_radius) + { + multiplier_from_accuracy = (1 - (distance_to_head ? min(1, (distance_to_head / autocvar_g_balance_laser_shockwave_splash_radius)) : 0)); + multiplier_from_distance = (1 - (distance_to_hit ? min(1, (distance_to_hit / distance_to_end)) : 0)); + multiplier = max(autocvar_g_balance_laser_shockwave_splash_multiplier_min, ((multiplier_from_accuracy * autocvar_g_balance_laser_shockwave_splash_multiplier_accuracy) + (multiplier_from_distance * autocvar_g_balance_laser_shockwave_splash_multiplier_distance))); + + final_force = normalize(center - (attack_hitpos - (w_shotdir * autocvar_g_balance_laser_shockwave_splash_force_forwardbias))); + //te_lightning2(world, attack_hitpos, (attack_hitpos + (final_force * 200))); + final_force = ((final_force * autocvar_g_balance_laser_shockwave_splash_force) * multiplier); + final_force_z *= autocvar_g_balance_laser_shockwave_force_zscale; + final_damage = (autocvar_g_balance_laser_shockwave_splash_damage * multiplier + autocvar_g_balance_laser_shockwave_splash_edgedamage * (1 - multiplier)); + + if(W_Laser_Shockwave_CheckHit(queue, head, final_force, final_damage)) { ++queue; } + //print("SPLASH HIT: multiplier = ", ftos(multiplier), strcat(", damage = ", ftos(final_damage), ", force = ", ftos(vlen(final_force))),"... multiplier_from_accuracy = ", ftos(multiplier_from_accuracy), ", multiplier_from_distance = ", ftos(multiplier_from_distance), ".\n"); + } + } + head = next; + } + + // cone damage trace + head = WarpZone_FindRadius(w_shotorg, autocvar_g_balance_laser_shockwave_distance, FALSE); + while(head) + { + next = head.chain; + + if((head != self) && head.takedamage) + { + // if it's a player, use the view origin as reference (stolen from RadiusDamage functions in g_damage.qc) + center = PLAYER_CENTER(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); + + vector nearest_on_line = (w_shotorg + a * w_shotdir); + vector nearest_to_attacker = WarpZoneLib_NearestPointOnBox(center + head.mins, center + head.maxs, nearest_on_line); + float distance_to_target = vlen(w_shotorg - nearest_to_attacker); // todo: use the findradius function for this + + if((distance_to_target <= autocvar_g_balance_laser_shockwave_distance) + && (W_Laser_Shockwave_IsVisible(head, nearest_on_line, w_shotorg, attack_endpos))) + { + multiplier_from_accuracy = (1 - W_Laser_Shockwave_CheckSpread(nearest_to_attacker, nearest_on_line, w_shotorg, attack_endpos)); + multiplier_from_distance = (1 - (distance_to_hit ? min(1, (distance_to_target / distance_to_end)) : 0)); + multiplier = max(autocvar_g_balance_laser_shockwave_multiplier_min, ((multiplier_from_accuracy * autocvar_g_balance_laser_shockwave_multiplier_accuracy) + (multiplier_from_distance * autocvar_g_balance_laser_shockwave_multiplier_distance))); + + final_force = normalize(center - (nearest_on_line - (w_shotdir * autocvar_g_balance_laser_shockwave_force_forwardbias))); + //te_lightning2(world, nearest_on_line, (attack_hitpos + (final_force * 200))); + final_force = ((final_force * autocvar_g_balance_laser_shockwave_force) * multiplier); + final_force_z *= autocvar_g_balance_laser_shockwave_force_zscale; + final_damage = (autocvar_g_balance_laser_shockwave_damage * multiplier + autocvar_g_balance_laser_shockwave_edgedamage * (1 - multiplier)); + + if(W_Laser_Shockwave_CheckHit(queue, head, final_force, final_damage)) { ++queue; } + //print("CONE HIT: multiplier = ", ftos(multiplier), strcat(", damage = ", ftos(final_damage), ", force = ", ftos(vlen(final_force))),"... multiplier_from_accuracy = ", ftos(multiplier_from_accuracy), ", multiplier_from_distance = ", ftos(multiplier_from_distance), ".\n"); + } + } + head = next; + } + + for(i = 1; i <= queue; ++i) + { + head = shockwave_hit[i]; + final_force = shockwave_hit_force[i]; + final_damage = shockwave_hit_damage[i]; + + Damage(head, self, self, final_damage, WEP_LASER, head.origin, final_force); + print("SHOCKWAVE by ", self.netname, ": damage = ", ftos(final_damage), ", force = ", ftos(vlen(final_force)), ".\n"); + + shockwave_hit[i] = world; - shockwave_hit_force = '0 0 0'; - shockwave_hit_damage = 0; ++ shockwave_hit_force[i] = '0 0 0'; ++ shockwave_hit_damage[i] = 0; + } + //print("queue was ", ftos(queue), ".\n\n"); +} + +void W_Laser_Melee_Think() +{ + // 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 = autocvar_g_balance_laser_melee_time * W_WeaponRateFactor(); + swing = bound(0, (self.cnt + meleetime - time) / meleetime, 10); + f = ((1 - swing) * autocvar_g_balance_laser_melee_traces); + + // check to see if we can still continue, otherwise give up now + if((self.realowner.deadflag != DEAD_NO) && autocvar_g_balance_laser_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_laser_melee_traces)) * 2 - 1); + + targpos = (self.realowner.origin + self.realowner.view_ofs + + (v_forward * autocvar_g_balance_laser_melee_range) + + (v_up * swing_factor * autocvar_g_balance_laser_melee_swing_up) + + (v_right * swing_factor * autocvar_g_balance_laser_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 + 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 = (trace_ent.classname == "player" || trace_ent.classname == "body"); + + 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 || autocvar_g_balance_laser_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 = (autocvar_g_balance_laser_melee_damage * min(1, swing_factor + 1)); + else + swing_damage = (autocvar_g_balance_laser_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_LASER | HITTYPE_SECONDARY, + self.realowner.origin + self.realowner.view_ofs, + v_forward * autocvar_g_balance_laser_melee_force); + + if(accuracy_isgooddamage(self.realowner, target_victim)) { accuracy_add(self.realowner, WEP_LASER, 0, swing_damage); } + + if(autocvar_g_balance_laser_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_Laser_Melee() +{ + sound(self, CH_WEAPON_A, "weapons/shotgun_melee.wav", VOL_BASE, ATTN_NORM); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_laser_melee_animtime, w_ready); + + entity meleetemp; + meleetemp = spawn(); + meleetemp.owner = meleetemp.realowner = self; + meleetemp.think = W_Laser_Melee_Think; + meleetemp.nextthink = time + autocvar_g_balance_laser_melee_delay * W_WeaponRateFactor(); + W_SetupShot_Range(self, TRUE, 0, "", 0, autocvar_g_balance_laser_melee_damage, autocvar_g_balance_laser_melee_range); +} + +void W_Laser_Attack(float issecondary) { entity missile; vector s_forward; @@@ -383,15 -48,13 +388,15 @@@ a = autocvar_g_balance_laser_primary_shotangle; s_forward = v_forward * cos(a * DEG2RAD) + v_up * sin(a * DEG2RAD); - if(nodamage) - W_SetupShot_Dir(self, s_forward, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_B, 0); - else if(issecondary == 1) - if(issecondary == 1) - W_SetupShot_Dir (self, s_forward, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_B, autocvar_g_balance_laser_secondary_damage); ++ //if(nodamage) ++ // W_SetupShot_Dir(self, s_forward, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_B, 0); ++ /*else*/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); + 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 = spawn(); missile.owner = missile.realowner = self; missile.classname = "laserbolt"; missile.dmg = 0; @@@ -436,142 -213,109 +438,139 @@@ void spawnfunc_weapon_laser(void weapon_defaultspawnfunc(WEP_LASER); } -float w_laser(float req) +float W_Laser(float request) { - float r1; - float r2; - if (req == WR_AIM) + switch(request) { - if(autocvar_g_balance_laser_secondary) + case WR_AIM: { - 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); + if((autocvar_g_balance_laser_secondary == 2) && (vlen(self.origin-self.enemy.origin) <= autocvar_g_balance_laser_melee_range)) + self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, FALSE); else - self.BUTTON_ATCK = bot_aim(autocvar_g_balance_laser_primary_speed, 0, autocvar_g_balance_laser_primary_lifetime, FALSE); + self.BUTTON_ATCK = bot_aim(1000000, 0, 1, FALSE); + return TRUE; } - 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) + + case WR_THINK: { - if (weapon_prepareattack(0, autocvar_g_balance_laser_primary_refire)) + if(autocvar_g_balance_laser_reload_ammo && self.clip_load < 1) // forced reload + weapon_action(self.weapon, WR_RELOAD); + else if(self.BUTTON_ATCK) { - W_DecreaseAmmo(ammo_none, 1, TRUE); + 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 not(autocvar_g_balance_laser_primary) + W_Laser_Shockwave(); + else + W_Laser_Attack(FALSE); - if (weapon_prepareattack(0, 0)) - { - W_Laser_Attack2(); - weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_laser_secondary_animtime, w_ready); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_laser_primary_animtime, w_ready); } } - else + else if(self.BUTTON_ATCK2) { - if(self.switchweapon == WEP_LASER) // don't do this if already switching - W_LastWeapon(); + switch(autocvar_g_balance_laser_secondary) + { + case 0: // switch to last used weapon + { + if(self.switchweapon == WEP_LASER) // don't do this if already switching + W_LastWeapon(); + + break; + } + + case 1: // normal projectile secondary + { + if(weapon_prepareattack(1, autocvar_g_balance_laser_secondary_refire)) + { + W_DecreaseAmmo(ammo_none, 1, TRUE); + W_Laser_Attack(TRUE); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_laser_secondary_animtime, w_ready); + } + + break; + } + + case 2: // melee attack secondary + { + if(!self.crouch) // we are not currently crouching; this fixes an exploit where your melee anim is not visible, and besides wouldn't make much sense + if(weapon_prepareattack(1, autocvar_g_balance_laser_melee_refire)) + { + // attempt forcing playback of the anim by switching to another anim (that we never play) here... + W_Laser_Melee(); + weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_laser_melee_animtime, w_ready); + } + } + } } + return TRUE; + } + + case 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"); + return TRUE; + } + + case WR_SETUP: + { + weapon_setup(WEP_LASER); + self.current_ammo = ammo_none; + return TRUE; + } + + case WR_CHECKAMMO1: + case WR_CHECKAMMO2: + { + return TRUE; // laser has infinite ammo + } + + case WR_RELOAD: + { + W_Reload(0, autocvar_g_balance_laser_reload_ammo, autocvar_g_balance_laser_reload_time, "weapons/reload.wav"); + return TRUE; + } ++ ++ case WR_SUICIDEMESSAGE: ++ { ++ return WEAPON_LASER_SUICIDE; ++ } ++ ++ case WR_KILLMESSAGE: ++ { ++ return WEAPON_LASER_MURDER; + } } - 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) +float W_Laser(float request) { - 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, ATTN_NORM); - } - else if(req == WR_PRECACHE) + switch(request) { - precache_sound("weapons/laserimpact.wav"); + case WR_IMPACTEFFECT: + { + vector org2; + org2 = w_org + w_backoff * 6; + pointparticles(particleeffectnum("new_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_PRECACHE: + { + precache_sound("weapons/laserimpact.wav"); + return TRUE; + } - case WR_SUICIDEMESSAGE: - { - w_deathtypestring = _("%s lasered themself to hell"); - return TRUE; - } - case WR_KILLMESSAGE: - { - if(w_deathtype & HITTYPE_SECONDARY) - w_deathtypestring = _("%s was cut in half by %s's gauntlet"); // unchecked: SPLASH // TODO - else - w_deathtypestring = _("%s was lasered to death by %s"); // unchecked: SPLASH - return TRUE; - } } + return TRUE; } #endif diff --cc qcsrc/server/w_minelayer.qc index b83c6f150,2cc464df6..b27d069a3 --- a/qcsrc/server/w_minelayer.qc +++ b/qcsrc/server/w_minelayer.qc @@@ -65,12 -76,12 +76,12 @@@ void W_Mine_Explode ( if(IsDifferentTeam(self.realowner, other)) if(other.deadflag == DEAD_NO) if(IsFlying(other)) - AnnounceTo(self.realowner, "airshot"); + Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT); - self.event_damage = SUB_Null; + self.event_damage = func_null; self.takedamage = DAMAGE_NO; - RadiusDamage (self, self.realowner, autocvar_g_balance_minelayer_damage, autocvar_g_balance_minelayer_edgedamage, autocvar_g_balance_minelayer_radius, world, autocvar_g_balance_minelayer_force, self.projectiledeathtype, other); + RadiusDamage (self, self.realowner, autocvar_g_balance_minelayer_damage, autocvar_g_balance_minelayer_edgedamage, autocvar_g_balance_minelayer_radius, world, world, autocvar_g_balance_minelayer_force, self.projectiledeathtype, other); if (self.realowner.weapon == WEP_MINE_LAYER) { @@@ -95,9 -106,9 +106,9 @@@ void W_Mine_DoRemoteExplode ( self.takedamage = DAMAGE_NO; if(self.movetype == MOVETYPE_NONE || self.movetype == MOVETYPE_FOLLOW) - self.velocity = self.oldvelocity; + self.velocity = self.mine_orientation; // particle fx and decals need .velocity - RadiusDamage (self, self.realowner, autocvar_g_balance_minelayer_remote_damage, autocvar_g_balance_minelayer_remote_edgedamage, autocvar_g_balance_minelayer_remote_radius, world, autocvar_g_balance_minelayer_remote_force, self.projectiledeathtype | HITTYPE_BOUNCE, world); + RadiusDamage (self, self.realowner, autocvar_g_balance_minelayer_remote_damage, autocvar_g_balance_minelayer_remote_edgedamage, autocvar_g_balance_minelayer_remote_radius, world, world, autocvar_g_balance_minelayer_remote_force, self.projectiledeathtype | HITTYPE_BOUNCE, world); if (self.realowner.weapon == WEP_MINE_LAYER) { diff --cc qcsrc/server/w_rocketlauncher.qc index cf2a75191,55b3379fc..504167cda --- a/qcsrc/server/w_rocketlauncher.qc +++ b/qcsrc/server/w_rocketlauncher.qc @@@ -23,12 -33,12 +33,12 @@@ void W_Rocket_Explode ( if(IsDifferentTeam(self.realowner, other)) if(other.deadflag == DEAD_NO) if(IsFlying(other)) - AnnounceTo(self.realowner, "airshot"); + Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT); - self.event_damage = SUB_Null; + self.event_damage = func_null; self.takedamage = DAMAGE_NO; - RadiusDamage (self, self.realowner, autocvar_g_balance_rocketlauncher_damage, autocvar_g_balance_rocketlauncher_edgedamage, autocvar_g_balance_rocketlauncher_radius, world, autocvar_g_balance_rocketlauncher_force, self.projectiledeathtype, other); + RadiusDamage (self, self.realowner, autocvar_g_balance_rocketlauncher_damage, autocvar_g_balance_rocketlauncher_edgedamage, autocvar_g_balance_rocketlauncher_radius, world, world, autocvar_g_balance_rocketlauncher_force, self.projectiledeathtype, other); if (self.realowner.weapon == WEP_ROCKET_LAUNCHER) { @@@ -46,10 -56,10 +56,10 @@@ void W_Rocket_DoRemoteExplode ( { W_Rocket_Unregister(); - self.event_damage = SUB_Null; + self.event_damage = func_null; self.takedamage = DAMAGE_NO; - RadiusDamage (self, self.realowner, autocvar_g_balance_rocketlauncher_remote_damage, autocvar_g_balance_rocketlauncher_remote_edgedamage, autocvar_g_balance_rocketlauncher_remote_radius, world, autocvar_g_balance_rocketlauncher_remote_force, self.projectiledeathtype | HITTYPE_BOUNCE, world); + RadiusDamage (self, self.realowner, autocvar_g_balance_rocketlauncher_remote_damage, autocvar_g_balance_rocketlauncher_remote_edgedamage, autocvar_g_balance_rocketlauncher_remote_radius, world, world, autocvar_g_balance_rocketlauncher_remote_force, self.projectiledeathtype | HITTYPE_BOUNCE, world); if (self.realowner.weapon == WEP_ROCKET_LAUNCHER) { diff --cc qcsrc/server/w_seeker.qc index a6a683389,61d72708c..1683a37e2 --- a/qcsrc/server/w_seeker.qc +++ b/qcsrc/server/w_seeker.qc @@@ -12,9 -22,9 +22,10 @@@ REGISTER_WEAPON // ============================ void Seeker_Missile_Explode () { - self.event_damage = SUB_Null; + self.event_damage = func_null; - RadiusDamage (self, self.realowner, autocvar_g_balance_seeker_missile_damage, autocvar_g_balance_seeker_missile_edgedamage, autocvar_g_balance_seeker_missile_radius, world, autocvar_g_balance_seeker_missile_force, self.projectiledeathtype, other); + RadiusDamage (self, self.realowner, autocvar_g_balance_seeker_missile_damage, autocvar_g_balance_seeker_missile_edgedamage, autocvar_g_balance_seeker_missile_radius, world, world, autocvar_g_balance_seeker_missile_force, self.projectiledeathtype, other); + + remove (self); } @@@ -223,9 -233,9 +234,9 @@@ void Seeker_Fire_Missile(vector f_diff // ============================ void Seeker_Flac_Explode () { - self.event_damage = SUB_Null; + self.event_damage = func_null; - RadiusDamage (self, self.realowner, autocvar_g_balance_seeker_flac_damage, autocvar_g_balance_seeker_flac_edgedamage, autocvar_g_balance_seeker_flac_radius, world, autocvar_g_balance_seeker_flac_force, self.projectiledeathtype, other); + RadiusDamage (self, self.realowner, autocvar_g_balance_seeker_flac_damage, autocvar_g_balance_seeker_flac_edgedamage, autocvar_g_balance_seeker_flac_radius, world, world, autocvar_g_balance_seeker_flac_force, self.projectiledeathtype, other); remove (self); }