// {{{ weapon properties
// {{{ laser
+set g_balance_laser_melee_animtime 0.3
+set g_balance_laser_melee_damage 80
+set g_balance_laser_melee_delay 0.25
+set g_balance_laser_melee_force 200
+set g_balance_laser_melee_multihit 1
+set g_balance_laser_melee_no_doubleslap 1
+set g_balance_laser_melee_nonplayerdamage 40
+set g_balance_laser_melee_range 120
+set g_balance_laser_melee_refire 1.25
+set g_balance_laser_melee_swing_side 120
+set g_balance_laser_melee_swing_up 30
+set g_balance_laser_melee_time 0.15
+set g_balance_laser_melee_traces 10
+
+set g_balance_laser_primary 1 // 0 = shockwave attack, 1 = projectile primary
set g_balance_laser_primary_damage 35
set g_balance_laser_primary_edgedamage 10
set g_balance_laser_primary_force 400
set g_balance_laser_primary_lifetime 30
set g_balance_laser_primary_shotangle 0
set g_balance_laser_primary_delay 0.05
-set g_balance_laser_primary_gauntlet 0
set g_balance_laser_primary_force_zscale 1
set g_balance_laser_primary_force_velocitybias 0
set g_balance_laser_primary_force_other_scale 1
-set g_balance_laser_secondary 0 // when 1, a secondary laser mode exists
+
+set g_balance_laser_secondary 0 // 0 = switch away to last used weapon, 1 = projectile secondary, 2 = melee secondary
set g_balance_laser_secondary_damage 35
set g_balance_laser_secondary_edgedamage 10
set g_balance_laser_secondary_force 400
set g_balance_laser_secondary_lifetime 30
set g_balance_laser_secondary_shotangle 0
set g_balance_laser_secondary_delay 0
-set g_balance_laser_secondary_gauntlet 0
set g_balance_laser_secondary_force_zscale 1
set g_balance_laser_secondary_force_velocitybias 0
set g_balance_laser_secondary_force_other_scale 1
+
+set g_balance_laser_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
// {{{ weapon properties
// {{{ laser
+set g_balance_laser_melee_animtime 0.3
+set g_balance_laser_melee_damage 80
+set g_balance_laser_melee_delay 0.25
+set g_balance_laser_melee_force 200
+set g_balance_laser_melee_multihit 1
+set g_balance_laser_melee_no_doubleslap 1
+set g_balance_laser_melee_nonplayerdamage 40
+set g_balance_laser_melee_range 120
+set g_balance_laser_melee_refire 1.25
+set g_balance_laser_melee_swing_side 120
+set g_balance_laser_melee_swing_up 30
+set g_balance_laser_melee_time 0.15
+set g_balance_laser_melee_traces 10
+
+set g_balance_laser_primary 1 // 0 = shockwave attack, 1 = projectile primary
set g_balance_laser_primary_damage 20 // dps 33, hope that's not too high
set g_balance_laser_primary_edgedamage 20
set g_balance_laser_primary_force 150 // this looks insanely low, but actually isn't with zscale and velocitybias
set g_balance_laser_primary_lifetime 5
set g_balance_laser_primary_shotangle 0
set g_balance_laser_primary_delay 0
-set g_balance_laser_primary_gauntlet 0
set g_balance_laser_primary_force_zscale 2 // 300 upforce
set g_balance_laser_primary_force_velocitybias 0.3
set g_balance_laser_primary_force_other_scale 2.5 // force 375 when pushing others around
-set g_balance_laser_secondary 0 // when 1, a secondary laser mode exists
+
+set g_balance_laser_secondary 0 // 0 = switch away to last used weapon, 1 = projectile secondary, 2 = melee secondary
set g_balance_laser_secondary_damage 200 // dps
set g_balance_laser_secondary_edgedamage 0
set g_balance_laser_secondary_force 1300
set g_balance_laser_secondary_lifetime 0
set g_balance_laser_secondary_shotangle 0
set g_balance_laser_secondary_delay 0
-set g_balance_laser_secondary_gauntlet 1
set g_balance_laser_secondary_force_zscale 1.25
set g_balance_laser_secondary_force_velocitybias 0
set g_balance_laser_secondary_force_other_scale 0
+
+set g_balance_laser_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
// {{{ 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_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_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
// {{{ weapon properties
// {{{ laser
+set g_balance_laser_melee_animtime 0.3
+set g_balance_laser_melee_damage 80
+set g_balance_laser_melee_delay 0.25
+set g_balance_laser_melee_force 200
+set g_balance_laser_melee_multihit 1
+set g_balance_laser_melee_no_doubleslap 1
+set g_balance_laser_melee_nonplayerdamage 40
+set g_balance_laser_melee_range 120
+set g_balance_laser_melee_refire 1.25
+set g_balance_laser_melee_swing_side 120
+set g_balance_laser_melee_swing_up 30
+set g_balance_laser_melee_time 0.15
+set g_balance_laser_melee_traces 10
+
+set g_balance_laser_primary 0 // 0 = shockwave attack, 1 = projectile primary
set g_balance_laser_primary_damage 25
set g_balance_laser_primary_edgedamage 12.5
set g_balance_laser_primary_force 300
set g_balance_laser_primary_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.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_secondary 2 // 0 = switch away to last used weapon, 1 = projectile secondary, 2 = melee secondary
set g_balance_laser_secondary_damage 25
set g_balance_laser_secondary_edgedamage 12.5
set g_balance_laser_secondary_force 400
set g_balance_laser_secondary_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.15
set g_balance_laser_switchdelay_raise 0.15
set g_balance_laser_reload_ammo 0 //default: 6
// {{{ weapon properties
// {{{ laser
+set g_balance_laser_melee_animtime 0.3
+set g_balance_laser_melee_damage 80
+set g_balance_laser_melee_delay 0.25
+set g_balance_laser_melee_force 200
+set g_balance_laser_melee_multihit 1
+set g_balance_laser_melee_no_doubleslap 1
+set g_balance_laser_melee_nonplayerdamage 40
+set g_balance_laser_melee_range 120
+set g_balance_laser_melee_refire 1.25
+set g_balance_laser_melee_swing_side 120
+set g_balance_laser_melee_swing_up 30
+set g_balance_laser_melee_time 0.15
+set g_balance_laser_melee_traces 10
+
+set g_balance_laser_primary 0 // 0 = shockwave attack, 1 = projectile primary
set g_balance_laser_primary_damage 25
set g_balance_laser_primary_edgedamage 12.5
set g_balance_laser_primary_force 300
set g_balance_laser_primary_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.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_secondary 2 // 0 = switch away to last used weapon, 1 = projectile secondary, 2 = melee secondary
set g_balance_laser_secondary_damage 25
set g_balance_laser_secondary_edgedamage 12.5
set g_balance_laser_secondary_force 400
set g_balance_laser_secondary_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.15
set g_balance_laser_switchdelay_raise 0.15
set g_balance_laser_reload_ammo 0 //default: 6
//lightcolor 1 0.9 0.7
//lightshadow 1
-// heal ray muzzleflash
+// heal ray muzzleflash
effect healray_muzzleflash
countabsolute 1
type smoke
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
float ClientProgsDB;
vector hook_shotorigin[4];
vector electro_shotorigin[4];
-vector gauntlet_shotorigin[4];
#ifdef BLURTEST
float blurtest_time0, blurtest_time1, blurtest_radius, blurtest_power;
case ENT_CLIENT_TRIGGER_MUSIC: Ent_ReadTriggerMusic(); break;
case ENT_CLIENT_HOOK: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_HOOK); break;
case ENT_CLIENT_LGBEAM: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_LGBEAM); break;
- case ENT_CLIENT_GAUNTLET: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_GAUNTLET); break;
case ENT_CLIENT_ACCURACY: Ent_ReadAccuracy(); break;
case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break;
case ENT_CLIENT_TURRET: ent_turret(); break;
electro_shotorigin[1] = decompressShotOrigin(ReadInt24_t());
electro_shotorigin[2] = decompressShotOrigin(ReadInt24_t());
electro_shotorigin[3] = decompressShotOrigin(ReadInt24_t());
- gauntlet_shotorigin[0] = decompressShotOrigin(ReadInt24_t());
- gauntlet_shotorigin[1] = decompressShotOrigin(ReadInt24_t());
- gauntlet_shotorigin[2] = decompressShotOrigin(ReadInt24_t());
- gauntlet_shotorigin[3] = decompressShotOrigin(ReadInt24_t());
if(forcefog)
strunzone(forcefog);
cl_notice_read();
bHandled = true;
break;
+ case TE_CSQC_SHOCKWAVEPARTICLE:
+ Net_ReadShockwaveParticle();
+ bHandled = true;
+ break;
default:
// No special logic for this temporary entity; return 0 so the engine can handle it
bHandled = false;
case ENT_CLIENT_LGBEAM:
vs = electro_shotorigin[s];
break;
- case ENT_CLIENT_GAUNTLET:
- vs = gauntlet_shotorigin[s];
- break;
}
if((self.owner.sv_entnum == player_localentnum - 1))
b = self.origin;
break;
case ENT_CLIENT_LGBEAM:
- case ENT_CLIENT_GAUNTLET:
if(self.HookRange)
b = view_origin + view_forward * self.HookRange;
else
b = self.origin;
break;
case ENT_CLIENT_LGBEAM:
- case ENT_CLIENT_GAUNTLET:
a = self.origin;
b = self.velocity;
break;
tex = "particles/lgbeam";
rgb = '1 1 1';
break;
- case ENT_CLIENT_GAUNTLET:
- intensity = 1;
- offset = Noise_White(self, frametime);
- tex = "particles/gauntletbeam";
- rgb = '1 1 1';
- break;
}
Draw_GrapplingHook_trace_callback_tex = tex;
}
break;
case ENT_CLIENT_LGBEAM:
- case ENT_CLIENT_GAUNTLET:
setorigin(self, a); // beam origin!
break;
}
case ENT_CLIENT_LGBEAM:
pointparticles(particleeffectnum("electro_lightning"), trace_endpos, normalize(atrans - trace_endpos), frametime * intensity);
break;
- case ENT_CLIENT_GAUNTLET:
- pointparticles(particleeffectnum("gauntlet_lightning"), b, normalize(a - b), frametime * intensity);
- break;
}
}
{
default:
case ENT_CLIENT_HOOK:
- case ENT_CLIENT_GAUNTLET:
self.HookRange = 0;
break;
case ENT_CLIENT_LGBEAM:
case ENT_CLIENT_LGBEAM:
sound (self, CH_SHOTS_SINGLE, "weapons/lgbeam_fly.wav", VOL_BASE, ATTN_NORM);
break;
- case ENT_CLIENT_GAUNTLET:
- sound (self, CH_SHOTS_SINGLE, "weapons/gauntletbeam_fly.wav", VOL_BASE, ATTN_NORM);
- break;
}
}
void Hook_Precache()
{
precache_sound("weapons/lgbeam_fly.wav");
- precache_sound("weapons/gauntletbeam_fly.wav");
precache_model("models/hook.md3");
}
return GETPLAYERORIGIN_ERROR;
}
+vector getcsqcplayercolor(float pl)
+{
+ entity e;
+
+ e = CSQCModel_server2csqc(pl);
+ if(e)
+ {
+ if(e.colormap > 0)
+ return colormapPaletteColor(((e.colormap >= 1024) ? e.colormap : stof(getplayerkeyvalue(e.colormap - 1, "colors"))) & 0x0F, TRUE);
+ }
+
+ return '1 1 1';
+}
+
float getplayerisdead(float pl)
{
entity e;
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 = '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;
+}
+
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;
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;
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 = '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)
+{
+ 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)
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);
+#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__
//self = self.owner;
setorigin(self,self.owner.origin + v_forward * 32);
- RadiusDamage(self, self.owner, autocvar_g_monster_zombie_attack_stand_damage,autocvar_g_monster_zombie_attack_stand_damage,16,self, autocvar_g_monster_zombie_attack_stand_force,DEATH_TURRET,world);
- //float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity ignore, float forceintensity, float deathtype, entity directhitentity)
+ RadiusDamage(self, self.owner, autocvar_g_monster_zombie_attack_stand_damage,autocvar_g_monster_zombie_attack_stand_damage,16,self, world, autocvar_g_monster_zombie_attack_stand_force,DEATH_TURRET,world);
+ //float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, float deathtype, entity directhitentity)
//self = oldself;
float autocvar_g_balance_keyhunt_throwvelocity;
float autocvar_g_balance_kill_delay;
float autocvar_g_balance_kill_antispam;
+float autocvar_g_balance_laser_melee_animtime;
+float autocvar_g_balance_laser_melee_damage;
+float autocvar_g_balance_laser_melee_delay;
+float autocvar_g_balance_laser_melee_force;
+float autocvar_g_balance_laser_melee_multihit;
+float autocvar_g_balance_laser_melee_no_doubleslap;
+float autocvar_g_balance_laser_melee_nonplayerdamage;
+float autocvar_g_balance_laser_melee_range;
+float autocvar_g_balance_laser_melee_refire;
+float autocvar_g_balance_laser_melee_swing_side;
+float autocvar_g_balance_laser_melee_swing_up;
+float autocvar_g_balance_laser_melee_time;
+float autocvar_g_balance_laser_melee_traces;
+float autocvar_g_balance_laser_primary;
float autocvar_g_balance_laser_primary_animtime;
float autocvar_g_balance_laser_primary_damage;
float autocvar_g_balance_laser_primary_delay;
float autocvar_g_balance_laser_primary_edgedamage;
float autocvar_g_balance_laser_primary_force;
-float autocvar_g_balance_laser_primary_force_other_scale;
-float autocvar_g_balance_laser_primary_force_velocitybias;
-float autocvar_g_balance_laser_primary_force_zscale;
+//float autocvar_g_balance_laser_primary_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_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_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;
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);
print("404 Sportsmanship not found.\n");
WriteInt24_t(MSG_ENTITY, compressShotOrigin(electro_shotorigin[1]));
WriteInt24_t(MSG_ENTITY, compressShotOrigin(electro_shotorigin[2]));
WriteInt24_t(MSG_ENTITY, compressShotOrigin(electro_shotorigin[3]));
- WriteInt24_t(MSG_ENTITY, compressShotOrigin(gauntlet_shotorigin[0]));
- WriteInt24_t(MSG_ENTITY, compressShotOrigin(gauntlet_shotorigin[1]));
- WriteInt24_t(MSG_ENTITY, compressShotOrigin(gauntlet_shotorigin[2]));
- WriteInt24_t(MSG_ENTITY, compressShotOrigin(gauntlet_shotorigin[3]));
+
if(sv_foginterval && world.fog != "")
WriteString(MSG_ENTITY, world.fog);
else
}
}
-vector cliptoplane(vector v, vector p)
-{
- return v - (v * p) * p;
-}
-
-vector solve_cubic_pq(float p, float q)
-{
- float D, u, v, a;
- D = q*q/4.0 + p*p*p/27.0;
- if(D < 0)
- {
- // irreducibilis
- a = 1.0/3.0 * acos(-q/2.0 * sqrt(-27.0/(p*p*p)));
- u = sqrt(-4.0/3.0 * p);
- // a in range 0..pi/3
- // cos(a)
- // cos(a + 2pi/3)
- // cos(a + 4pi/3)
- return
- u *
- (
- '1 0 0' * cos(a + 2.0/3.0*M_PI)
- +
- '0 1 0' * cos(a + 4.0/3.0*M_PI)
- +
- '0 0 1' * cos(a)
- );
- }
- else if(D == 0)
- {
- // simple
- if(p == 0)
- return '0 0 0';
- u = 3*q/p;
- v = -u/2;
- if(u >= v)
- return '1 1 0' * v + '0 0 1' * u;
- else
- return '0 1 1' * v + '1 0 0' * u;
- }
- else
- {
- // cardano
- u = cbrt(-q/2.0 + sqrt(D));
- v = cbrt(-q/2.0 - sqrt(D));
- return '1 1 1' * (u + v);
- }
-}
-vector solve_cubic_abcd(float a, float b, float c, float d)
-{
- // y = 3*a*x + b
- // x = (y - b) / 3a
- float p, q;
- vector v;
- p = (9*a*c - 3*b*b);
- q = (27*a*a*d - 9*a*b*c + 2*b*b*b);
- v = solve_cubic_pq(p, q);
- v = (v - b * '1 1 1') * (1.0 / (3.0 * a));
- if(a < 0)
- v += '1 0 -1' * (v_z - v_x); // swap x, z
- return v;
-}
-
-vector findperpendicular(vector v)
-{
- vector p;
- p_x = v_z;
- p_y = -v_x;
- p_z = v_y;
- return normalize(cliptoplane(p, v));
-}
-
-vector W_CalculateProjectileSpread(vector forward, float spread)
-{
- float sigma;
- vector v1 = '0 0 0', v2;
- float dx, dy, r;
- float sstyle;
- spread *= g_weaponspreadfactor;
- if(spread <= 0)
- return forward;
- sstyle = autocvar_g_projectiles_spread_style;
-
- if(sstyle == 0)
- {
- // this is the baseline for the spread value!
- // standard deviation: sqrt(2/5)
- // density function: sqrt(1-r^2)
- return forward + randomvec() * spread;
- }
- else if(sstyle == 1)
- {
- // same thing, basically
- return normalize(forward + cliptoplane(randomvec() * spread, forward));
- }
- else if(sstyle == 2)
- {
- // circle spread... has at sigma=1 a standard deviation of sqrt(1/2)
- sigma = spread * 0.89442719099991587855; // match baseline stddev
- v1 = findperpendicular(forward);
- v2 = cross(forward, v1);
- // random point on unit circle
- dx = random() * 2 * M_PI;
- dy = sin(dx);
- dx = cos(dx);
- // radius in our dist function
- r = random();
- r = sqrt(r);
- return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
- }
- else if(sstyle == 3) // gauss 3d
- {
- sigma = spread * 0.44721359549996; // match baseline stddev
- // note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right
- v1 = forward;
- v1_x += gsl_ran_gaussian(sigma);
- v1_y += gsl_ran_gaussian(sigma);
- v1_z += gsl_ran_gaussian(sigma);
- return v1;
- }
- else if(sstyle == 4) // gauss 2d
- {
- sigma = spread * 0.44721359549996; // match baseline stddev
- // note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right
- v1_x = gsl_ran_gaussian(sigma);
- v1_y = gsl_ran_gaussian(sigma);
- v1_z = gsl_ran_gaussian(sigma);
- return normalize(forward + cliptoplane(v1, forward));
- }
- else if(sstyle == 5) // 1-r
- {
- sigma = spread * 1.154700538379252; // match baseline stddev
- v1 = findperpendicular(forward);
- v2 = cross(forward, v1);
- // random point on unit circle
- dx = random() * 2 * M_PI;
- dy = sin(dx);
- dx = cos(dx);
- // radius in our dist function
- r = random();
- r = solve_cubic_abcd(-2, 3, 0, -r) * '0 1 0';
- return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
- }
- else if(sstyle == 6) // 1-r^2
- {
- sigma = spread * 1.095445115010332; // match baseline stddev
- v1 = findperpendicular(forward);
- v2 = cross(forward, v1);
- // random point on unit circle
- dx = random() * 2 * M_PI;
- dy = sin(dx);
- dx = cos(dx);
- // radius in our dist function
- r = random();
- r = sqrt(1 - r);
- r = sqrt(1 - r);
- return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
- }
- else if(sstyle == 7) // (1-r) (2-r)
- {
- sigma = spread * 1.224744871391589; // match baseline stddev
- v1 = findperpendicular(forward);
- v2 = cross(forward, v1);
- // random point on unit circle
- dx = random() * 2 * M_PI;
- dy = sin(dx);
- dx = cos(dx);
- // radius in our dist function
- r = random();
- r = 1 - sqrt(r);
- r = 1 - sqrt(r);
- return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
- }
- else
- error("g_projectiles_spread_style must be 0 (sphere), 1 (flattened sphere), 2 (circle), 3 (gauss 3D), 4 (gauss plane), 5 (linear falloff), 6 (quadratic falloff), 7 (stronger falloff)!");
- return '0 0 0';
- /*
- * how to derive falloff functions:
- * rho(r) := (2-r) * (1-r);
- * a : 0;
- * b : 1;
- * rhor(r) := r * rho(r);
- * cr(t) := integrate(rhor(r), r, a, t);
- * scr(t) := integrate(rhor(r) * r^2, r, a, t);
- * variance : scr(b) / cr(b);
- * solve(cr(r) = rand * cr(b), r), programmmode:false;
- * sqrt(0.4 / variance), numer;
- */
-}
-
#if 0
float mspercallsum;
float mspercallsstyle;
}
mspercallsum -= gettime(GETTIME_HIRES);
#endif
- dir = W_CalculateProjectileSpread(dir, spread);
+ dir = W_CalculateSpread(dir, spread, g_weaponspreadfactor, autocvar_g_projectiles_spread_style);
#if 0
mspercallsum += gettime(GETTIME_HIRES);
mspercallcount += 1;
sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTN_NORM);
if(self.dmg)
- RadiusDamage(self, activator, self.dmg, self.dmg_edge, self.dmg_radius, self, self.dmg_force, DEATH_HURTTRIGGER, world);
+ RadiusDamage(self, activator, self.dmg, self.dmg_edge, self.dmg_radius, self, world, self.dmg_force, DEATH_HURTTRIGGER, world);
if(self.cnt)
pointparticles(self.cnt, self.absmin * 0.5 + self.absmax * 0.5, '0 0 0', self.count);
}
float RadiusDamage_running;
-float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity ignore, float forceintensity, float deathtype, entity directhitentity)
+float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float inflictorselfdamage, float forceintensity, float deathtype, entity directhitentity)
// Returns total damage applies to creatures
{
entity targ;
- vector blastorigin;
vector force;
float total_damage_to_creatures;
entity next;
tfloordmg = autocvar_g_throughfloor_damage;
tfloorforce = autocvar_g_throughfloor_force;
- blastorigin = (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5);
total_damage_to_creatures = 0;
if(deathtype != (WEP_HOOK | HITTYPE_SECONDARY | HITTYPE_BOUNCE)) // only send gravity bomb damage once
if(DEATH_WEAPONOF(deathtype) != WEP_TUBA) // do not send tuba damage (bandwidth hog)
{
- force = inflictor.velocity;
+ force = inflictorvelocity;
if(vlen(force) == 0)
force = '0 0 -1';
else
force = normalize(force);
if(forceintensity >= 0)
- Damage_DamageInfo(blastorigin, coredamage, edgedamage, rad, forceintensity * force, deathtype, 0, attacker);
+ Damage_DamageInfo(inflictororigin, coredamage, edgedamage, rad, forceintensity * force, deathtype, 0, attacker);
else
- Damage_DamageInfo(blastorigin, coredamage, edgedamage, -rad, (-forceintensity) * force, deathtype, 0, attacker);
+ Damage_DamageInfo(inflictororigin, coredamage, edgedamage, -rad, (-forceintensity) * force, deathtype, 0, attacker);
}
stat_damagedone = 0;
- targ = WarpZone_FindRadius (blastorigin, rad + MAX_DAMAGEEXTRARADIUS, FALSE);
+ targ = WarpZone_FindRadius (inflictororigin, rad + MAX_DAMAGEEXTRARADIUS, FALSE);
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
+ 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));
- 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);
}
}
}
+ }
targ = next;
}
return total_damage_to_creatures;
}
+float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, float deathtype, entity directhitentity)
+{
+ return RadiusDamageForSource (inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker, coredamage, edgedamage, rad, cantbe, mustbe, FALSE, forceintensity, deathtype, directhitentity);
+}
+
.float fire_damagepersec;
.float fire_endtime;
.float fire_deathtype;
readlevelcvars();
GrappleHookInit();
ElectroInit();
- LaserInit();
player_count = 0;
bot_waypoints_for_items = autocvar_g_waypoints_for_items;
d = FALSE;
}
else if (g_cts)
- d = (i == WEP_SHOTGUN);
+ d = (i == WEP_SHOTGUN); // todo: how to handle shotgun in CTS mode? we're removing it.. so....
else if (g_nexball)
d = 0; // weapon is set a few lines later
else
- d = (i == WEP_LASER || i == WEP_SHOTGUN);
+ d = (i == WEP_LASER);
if(g_grappling_hook) // if possible, redirect off-hand hook to on-hand hook
d |= (i == WEP_HOOK);
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);
}
g_hook.qh
w_electro.qh
-w_laser.qh
scores.qh
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
- RadiusDamage (self, self.realowner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world);
+ RadiusDamage (self, self.realowner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
#endif
remove(self);
}
#ifdef TURRET_DEBUG
float d;
- d = RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world);
+ d = RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d;
self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
#else
- RadiusDamage (self, self.realowner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world);
+ RadiusDamage (self, self.realowner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
#endif
remove(self);
}
}
void walker_rocket_explode()
{
- RadiusDamage (self, self.owner, autocvar_g_turrets_unit_walker_std_rocket_dmg, 0, autocvar_g_turrets_unit_walker_std_rocket_radius, self, autocvar_g_turrets_unit_walker_std_rocket_force, DEATH_TURRET_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);
}
{
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_VH_BUMB_DEATH, world);
self.nextthink = 0;
setorigin(self, self.pos1);
-
}
void bumb_impact()
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_VH_WAKI_DEATH, world);
{
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_VH_RAPT_BOMB, world);
remove(self);
}
{
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_VH_RAPT_DEATH, world);
self.alpha = -1;
self.movetype = MOVETYPE_NONE;
SUB_SetFade(g1, time, min(autocvar_g_vehicle_spiderbot_respawntime, 10));
SUB_SetFade(g2, time, min(autocvar_g_vehicle_spiderbot_respawntime, 10));
- RadiusDamage (self, self.enemy, 250, 15, 250, world, 250, DEATH_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;
PROJECTILE_TOUCH;
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);
}
// create a small explosion to throw gibs around (if applicable)
//setorigin (explosion, hitloc);
- //RadiusDamage (explosion, self, 10, 0, 50, world, 300, deathtype);
+ //RadiusDamage (explosion, self, 10, 0, 50, world, world, 300, deathtype);
ent.railgunhitloc = '0 0 0';
ent.railgunhitsolidbackup = SOLID_NOT;
e.realowner.crylink_lastgroup = world;
if(e.projectiledeathtype & HITTYPE_SECONDARY)
- RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_secondary_damage * a, autocvar_g_balance_crylink_secondary_edgedamage * a, autocvar_g_balance_crylink_secondary_radius, world, autocvar_g_balance_crylink_secondary_force * a, e.projectiledeathtype, other);
+ RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_secondary_damage * a, autocvar_g_balance_crylink_secondary_edgedamage * a, autocvar_g_balance_crylink_secondary_radius, world, world, autocvar_g_balance_crylink_secondary_force * a, e.projectiledeathtype, other);
else
- RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_primary_damage * a, autocvar_g_balance_crylink_primary_edgedamage * a, autocvar_g_balance_crylink_primary_radius, world, autocvar_g_balance_crylink_primary_force * a, e.projectiledeathtype, other);
+ RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_primary_damage * a, autocvar_g_balance_crylink_primary_edgedamage * a, autocvar_g_balance_crylink_primary_radius, world, world, autocvar_g_balance_crylink_primary_force * a, e.projectiledeathtype, other);
W_Crylink_LinkExplode(e.queuenext, e2);
n = n / autocvar_g_balance_crylink_secondary_shots;
RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_secondary_joinexplode_damage * n,
autocvar_g_balance_crylink_secondary_joinexplode_edgedamage * n,
- autocvar_g_balance_crylink_secondary_joinexplode_radius * n, e.realowner,
+ autocvar_g_balance_crylink_secondary_joinexplode_radius * n, e.realowner, world,
autocvar_g_balance_crylink_secondary_joinexplode_force * n, e.projectiledeathtype, other);
pointparticles(particleeffectnum("crylink_joinexplode"), self.origin, '0 0 0', n);
n = n / autocvar_g_balance_crylink_primary_shots;
RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_primary_joinexplode_damage * n,
autocvar_g_balance_crylink_primary_joinexplode_edgedamage * n,
- autocvar_g_balance_crylink_primary_joinexplode_radius * n, e.realowner,
+ autocvar_g_balance_crylink_primary_joinexplode_radius * n, e.realowner, world,
autocvar_g_balance_crylink_primary_joinexplode_force * n, e.projectiledeathtype, other);
pointparticles(particleeffectnum("crylink_joinexplode"), self.origin, '0 0 0', n);
if(a)
f *= a;
- float totaldamage = RadiusDamage(self, self.realowner, autocvar_g_balance_crylink_primary_damage * f, autocvar_g_balance_crylink_primary_edgedamage * f, autocvar_g_balance_crylink_primary_radius, world, autocvar_g_balance_crylink_primary_force * f, self.projectiledeathtype, other);
+ 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(a)
f *= a;
- float totaldamage = RadiusDamage(self, self.realowner, autocvar_g_balance_crylink_secondary_damage * f, autocvar_g_balance_crylink_secondary_edgedamage * f, autocvar_g_balance_crylink_secondary_radius, world, autocvar_g_balance_crylink_secondary_force * f, self.projectiledeathtype, other);
+ 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))))
{
self.takedamage = DAMAGE_NO;
if (self.movetype == MOVETYPE_BOUNCE)
{
- RadiusDamage (self, self.realowner, autocvar_g_balance_electro_secondary_damage, autocvar_g_balance_electro_secondary_edgedamage, autocvar_g_balance_electro_secondary_radius, world, autocvar_g_balance_electro_secondary_force, self.projectiledeathtype, other);
+ RadiusDamage (self, self.realowner, autocvar_g_balance_electro_secondary_damage, autocvar_g_balance_electro_secondary_edgedamage, autocvar_g_balance_electro_secondary_radius, world, world, autocvar_g_balance_electro_secondary_force, self.projectiledeathtype, other);
}
else
{
W_Plasma_TriggerCombo(self.origin, autocvar_g_balance_electro_primary_comboradius, self.realowner);
- RadiusDamage (self, self.realowner, autocvar_g_balance_electro_primary_damage, autocvar_g_balance_electro_primary_edgedamage, autocvar_g_balance_electro_primary_radius, world, autocvar_g_balance_electro_primary_force, self.projectiledeathtype, other);
+ RadiusDamage (self, self.realowner, autocvar_g_balance_electro_primary_damage, autocvar_g_balance_electro_primary_edgedamage, autocvar_g_balance_electro_primary_radius, world, world, autocvar_g_balance_electro_primary_force, self.projectiledeathtype, other);
}
remove (self);
W_Plasma_TriggerCombo(self.origin, autocvar_g_balance_electro_combo_comboradius, self.realowner);
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);
}
// 1. dist damage
d = (self.realowner.health + self.realowner.armorvalue);
- RadiusDamage (self, self.realowner, autocvar_g_balance_fireball_primary_damage, autocvar_g_balance_fireball_primary_edgedamage, autocvar_g_balance_fireball_primary_radius, world, autocvar_g_balance_fireball_primary_force, self.projectiledeathtype, other);
+ RadiusDamage (self, self.realowner, autocvar_g_balance_fireball_primary_damage, autocvar_g_balance_fireball_primary_edgedamage, autocvar_g_balance_fireball_primary_radius, world, world, autocvar_g_balance_fireball_primary_force, self.projectiledeathtype, other);
if(self.realowner.health + self.realowner.armorvalue >= d)
if(!self.cnt)
{
if(self.movetype == MOVETYPE_NONE)
self.velocity = self.oldvelocity;
- RadiusDamage (self, self.realowner, autocvar_g_balance_grenadelauncher_primary_damage, autocvar_g_balance_grenadelauncher_primary_edgedamage, autocvar_g_balance_grenadelauncher_primary_radius, world, autocvar_g_balance_grenadelauncher_primary_force, self.projectiledeathtype, other);
+ RadiusDamage (self, self.realowner, autocvar_g_balance_grenadelauncher_primary_damage, autocvar_g_balance_grenadelauncher_primary_edgedamage, autocvar_g_balance_grenadelauncher_primary_radius, world, world, autocvar_g_balance_grenadelauncher_primary_force, self.projectiledeathtype, other);
remove (self);
}
if(self.movetype == MOVETYPE_NONE)
self.velocity = self.oldvelocity;
- RadiusDamage (self, self.realowner, autocvar_g_balance_grenadelauncher_secondary_damage, autocvar_g_balance_grenadelauncher_secondary_edgedamage, autocvar_g_balance_grenadelauncher_secondary_radius, world, autocvar_g_balance_grenadelauncher_secondary_force, self.projectiledeathtype, other);
+ RadiusDamage (self, self.realowner, autocvar_g_balance_grenadelauncher_secondary_damage, autocvar_g_balance_grenadelauncher_secondary_edgedamage, autocvar_g_balance_grenadelauncher_secondary_radius, world, world, autocvar_g_balance_grenadelauncher_secondary_force, self.projectiledeathtype, other);
remove (self);
}
void W_Hagar_Explode (void)
{
self.event_damage = func_null;
- RadiusDamage (self, self.realowner, autocvar_g_balance_hagar_primary_damage, autocvar_g_balance_hagar_primary_edgedamage, autocvar_g_balance_hagar_primary_radius, world, autocvar_g_balance_hagar_primary_force, self.projectiledeathtype, other);
+ 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 = 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);
}
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);
}
f = self.dmg_last - dmg_remaining_next;
self.dmg_last = dmg_remaining_next;
- RadiusDamage (self, self.realowner, self.dmg * f, self.dmg_edge * f, self.dmg_radius, self.realowner, self.dmg_force * f, self.projectiledeathtype, world);
+ RadiusDamage (self, self.realowner, self.dmg * f, self.dmg_edge * f, self.dmg_radius, self.realowner, world, self.dmg_force * f, self.projectiledeathtype, world);
self.projectiledeathtype |= HITTYPE_BOUNCE;
- //RadiusDamage (self, world, self.dmg * f, self.dmg_edge * f, self.dmg_radius, world, self.dmg_force * f, self.projectiledeathtype, world);
+ //RadiusDamage (self, world, self.dmg * f, self.dmg_edge * f, self.dmg_radius, world, world, self.dmg_force * f, self.projectiledeathtype, world);
if(dt < self.dmg_duration)
self.nextthink = time + 0.05; // soon
/* rating */ 0,
/* model */ "laser",
/* shortname */ "laser",
-/* fullname */ _("Laser")
+/* fullname */ _("Blaster")
);
#else
#ifdef SVQC
void(float imp) W_SwitchWeapon;
void() W_LastWeapon;
+.float swing_prev;
+.entity swing_alreadyhit;
-void W_Laser_Touch (void)
+void SendCSQCShockwaveParticle(vector endpos)
+{
+ //endpos = WarpZone_UnTransformOrigin(transform, endpos);
+
+ WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
+ WriteByte(MSG_BROADCAST, TE_CSQC_SHOCKWAVEPARTICLE);
+ WriteCoord(MSG_BROADCAST, w_shotorg_x);
+ WriteCoord(MSG_BROADCAST, w_shotorg_y);
+ WriteCoord(MSG_BROADCAST, w_shotorg_z);
+ WriteCoord(MSG_BROADCAST, endpos_x);
+ WriteCoord(MSG_BROADCAST, endpos_y);
+ WriteCoord(MSG_BROADCAST, endpos_z);
+ WriteByte(MSG_BROADCAST, bound(0, autocvar_g_balance_laser_shockwave_spread_max, 255));
+ WriteByte(MSG_BROADCAST, bound(0, autocvar_g_balance_laser_shockwave_spread_min, 255));
+ WriteByte(MSG_BROADCAST, num_for_edict(self));
+}
+
+void W_Laser_Touch()
{
PROJECTILE_TOUCH;
self.event_damage = func_null;
- if (self.dmg)
- RadiusDamage (self, self.realowner, autocvar_g_balance_laser_secondary_damage, autocvar_g_balance_laser_secondary_edgedamage, autocvar_g_balance_laser_secondary_radius, world, autocvar_g_balance_laser_secondary_force, self.projectiledeathtype, other);
+
+ 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()
{
self.movetype = MOVETYPE_FLY;
self.think = SUB_Remove;
- if (self.dmg)
+
+ if(self.dmg)
self.nextthink = time + autocvar_g_balance_laser_secondary_lifetime;
else
self.nextthink = time + autocvar_g_balance_laser_primary_lifetime;
+
CSQCProjectile(self, TRUE, PROJECTILE_LASER, TRUE);
}
-void W_Laser_Attack (float issecondary)
+
+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;
+ vector final_force, center, vel;
+ entity head, next;
+
+ 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;
+
+ // 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[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;
a = autocvar_g_balance_laser_primary_shotangle;
s_forward = v_forward * cos(a * DEG2RAD) + v_up * sin(a * DEG2RAD);
- if(issecondary == 1)
- W_SetupShot_Dir (self, s_forward, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_B, autocvar_g_balance_laser_secondary_damage);
+ //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;
PROJECTILE_MAKETRIGGER(missile);
missile.projectiledeathtype = WEP_LASER;
- setorigin (missile, w_shotorg);
+ setorigin(missile, w_shotorg);
setsize(missile, '0 0 0', '0 0 0');
W_SETUPPROJECTILEVELOCITY(missile, g_balance_laser_primary);
- missile.angles = vectoangles (missile.velocity);
+ missile.angles = vectoangles(missile.velocity);
//missile.glow_color = 250; // 244, 250
//missile.glow_size = 120;
missile.touch = W_Laser_Touch;
}
}
-.vector hook_start, hook_end;
-float gauntletbeam_send(entity to, float sf)
-{
- WriteByte(MSG_ENTITY, ENT_CLIENT_GAUNTLET);
- sf = sf & 0x7F;
- if(sound_allowed(MSG_BROADCAST, self.realowner))
- sf |= 0x80;
- WriteByte(MSG_ENTITY, sf);
- if(sf & 1)
- {
- WriteByte(MSG_ENTITY, num_for_edict(self.realowner));
- }
- if(sf & 2)
- {
- WriteCoord(MSG_ENTITY, self.hook_start_x);
- WriteCoord(MSG_ENTITY, self.hook_start_y);
- WriteCoord(MSG_ENTITY, self.hook_start_z);
- }
- if(sf & 4)
- {
- WriteCoord(MSG_ENTITY, self.hook_end_x);
- WriteCoord(MSG_ENTITY, self.hook_end_y);
- WriteCoord(MSG_ENTITY, self.hook_end_z);
- }
- return TRUE;
-}
-.entity gauntletbeam;
-.float prevgauntletfire;
-entity lgbeam_owner_ent;
-void gauntletbeam_think()
-{
- float damage, myforce, myradius;
- damage = autocvar_g_balance_laser_secondary_damage;
- myforce = autocvar_g_balance_laser_secondary_force;
- myradius = autocvar_g_balance_laser_secondary_radius;
-
- self.realowner.prevgauntletfire = time;
- if (self.realowner.weaponentity.state != WS_INUSE || self != self.realowner.gauntletbeam || self.realowner.deadflag != DEAD_NO || !self.realowner.BUTTON_ATCK2)
- {
- remove(self);
- return;
- }
-
- self.nextthink = time;
-
- makevectors(self.realowner.v_angle);
-
- float dt;
- dt = frametime;
-
- W_SetupShot_Range(self.realowner, TRUE, 0, "", 0, damage * dt, myradius);
- if(!lgbeam_owner_ent)
- {
- lgbeam_owner_ent = spawn();
- lgbeam_owner_ent.classname = "lgbeam_owner_ent";
- }
- WarpZone_traceline_antilag(lgbeam_owner_ent, w_shotorg, w_shotend, MOVE_NORMAL, lgbeam_owner_ent, ANTILAG_LATENCY(self.owner));
-
- // apply the damage
- if(trace_ent)
- {
- vector force;
- force = w_shotdir * myforce;
- if(accuracy_isgooddamage(self.owner, trace_ent))
- accuracy_add(self.owner, WEP_LASER, 0, damage * dt);
- Damage (trace_ent, self.owner, self.owner, damage * dt, WEP_LASER | HITTYPE_SECONDARY, trace_endpos, force * dt);
- }
-
- // draw effect
- if(w_shotorg != self.hook_start)
- {
- self.SendFlags |= 2;
- self.hook_start = w_shotorg;
- }
- if(w_shotend != self.hook_end)
- {
- self.SendFlags |= 4;
- self.hook_end = w_shotend;
- }
-}
-
-// experimental gauntlet
-void W_Laser_Attack2 ()
-{
- // only play fire sound if 0.5 sec has passed since player let go the fire button
- if(time - self.prevgauntletfire > 0.5)
- {
- sound (self, CH_WEAPON_A, "weapons/gauntlet_fire.wav", VOL_BASE, ATTN_NORM);
- }
-
- entity beam, oldself;
-
- self.gauntletbeam = beam = spawn();
- beam.solid = SOLID_NOT;
- beam.think = gauntletbeam_think;
- beam.owner = self;
- beam.movetype = MOVETYPE_NONE;
- beam.shot_spread = 0;
- beam.bot_dodge = TRUE;
- beam.bot_dodgerating = autocvar_g_balance_laser_primary_damage;
- Net_LinkEntity(beam, FALSE, 0, gauntletbeam_send);
-
- oldself = self;
- self = beam;
- self.think();
- self = oldself;
-}
-
-void LaserInit()
-{
- weapon_action(WEP_LASER, WR_PRECACHE);
- gauntlet_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_LASER), FALSE, FALSE, 1);
- gauntlet_shotorigin[1] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_LASER), FALSE, FALSE, 2);
- gauntlet_shotorigin[2] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_LASER), FALSE, FALSE, 3);
- gauntlet_shotorigin[3] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_LASER), FALSE, FALSE, 4);
-}
-
-void spawnfunc_weapon_laser (void)
+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;
+ }
}
+
return TRUE;
}
#endif
+++ /dev/null
-void LaserInit();
-vector gauntlet_shotorigin[4];
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)
{
if(self.movetype == MOVETYPE_NONE || self.movetype == MOVETYPE_FOLLOW)
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)
{
float w;
w = self.weapon;
self.weapon = WEP_LASER;
- W_Laser_Attack(2);
+ W_Laser_Shockwave();
self.weapon = w;
// now do normal refire
precache_sound ("weapons/nexwhoosh2.wav");
precache_sound ("weapons/nexwhoosh3.wav");
//precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else
- w_laser(WR_PRECACHE);
+ W_Laser(WR_PRECACHE);
}
else if (req == WR_SETUP)
{
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)
{
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)
{
void Seeker_Missile_Explode ()
{
self.event_damage = func_null;
- RadiusDamage (self, self.realowner, autocvar_g_balance_seeker_missile_damage, autocvar_g_balance_seeker_missile_edgedamage, autocvar_g_balance_seeker_missile_radius, world, autocvar_g_balance_seeker_missile_force, self.projectiledeathtype, other);
+ 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);
}
{
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);
}
self.tuba_note.teleport_time = time + autocvar_g_balance_tuba_refire * 2 * W_WeaponRateFactor(); // so it can get prolonged safely
//sound(self, c, TUBA_NOTE(n), bound(0, VOL_BASE * cvar("g_balance_tuba_volume"), 1), autocvar_g_balance_tuba_attenuation);
- RadiusDamage(self, self, autocvar_g_balance_tuba_damage, autocvar_g_balance_tuba_edgedamage, autocvar_g_balance_tuba_radius, world, autocvar_g_balance_tuba_force, hittype | WEP_TUBA, world);
+ RadiusDamage(self, self, autocvar_g_balance_tuba_damage, autocvar_g_balance_tuba_edgedamage, autocvar_g_balance_tuba_radius, world, world, autocvar_g_balance_tuba_force, hittype | WEP_TUBA, world);
o = gettaginfo(self.exteriorweaponentity, 0);
if(time > self.tuba_smoketime)