From 0ffe5cf536ef658d87cad9d500109a731aa22db4 Mon Sep 17 00:00:00 2001 From: Samual Lenks Date: Mon, 23 Jul 2012 01:08:23 -0400 Subject: [PATCH] Crude implementation of melee ripped from shotgun --- qcsrc/server/w_laser.qc | 122 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/qcsrc/server/w_laser.qc b/qcsrc/server/w_laser.qc index ae9c53464..bca80dda0 100644 --- a/qcsrc/server/w_laser.qc +++ b/qcsrc/server/w_laser.qc @@ -185,6 +185,117 @@ void W_Laser_Shockwave (void) } } +.float swing_prev; +.entity swing_alreadyhit; +void W_Laser_Melee_Think(void) +{ + // declarations + float i, f, swing, swing_factor, swing_damage, meleetime, is_player; + entity target_victim; + vector targpos; + + if(!self.cnt) // set start time of melee + { + self.cnt = time; + W_PlayStrengthSound(self.realowner); + } + + makevectors(self.realowner.v_angle); // update values for v_* vectors + + // calculate swing percentage based on time + meleetime = autocvar_g_balance_shotgun_secondary_melee_time * W_WeaponRateFactor(); + swing = bound(0, (self.cnt + meleetime - time) / meleetime, 10); + f = ((1 - swing) * autocvar_g_balance_shotgun_secondary_melee_traces); + + // check to see if we can still continue, otherwise give up now + if((self.realowner.deadflag != DEAD_NO) && autocvar_g_balance_shotgun_secondary_melee_no_doubleslap) + { + remove(self); + return; + } + + // if okay, perform the traces needed for this frame + for(i=self.swing_prev; i < f; ++i) + { + swing_factor = ((1 - (i / autocvar_g_balance_shotgun_secondary_melee_traces)) * 2 - 1); + + targpos = (self.realowner.origin + self.realowner.view_ofs + + (v_forward * autocvar_g_balance_shotgun_secondary_melee_range) + + (v_up * swing_factor * autocvar_g_balance_shotgun_secondary_melee_swing_up) + + (v_right * swing_factor * autocvar_g_balance_shotgun_secondary_melee_swing_side)); + + WarpZone_traceline_antilag(self.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_shotgun_secondary_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_shotgun_secondary_damage * min(1, swing_factor + 1)); + else + swing_damage = (autocvar_g_balance_shotgun_secondary_melee_nonplayerdamage * min(1, swing_factor + 1)); + + //print(strcat(self.realowner.netname, " hitting ", target_victim.netname, " with ", strcat(ftos(swing_damage), " damage (factor: ", ftos(swing_factor), ") at "), ftos(time), " seconds.\n")); + + Damage(target_victim, self.realowner, self.realowner, + swing_damage, WEP_SHOTGUN | HITTYPE_SECONDARY, + self.realowner.origin + self.realowner.view_ofs, + v_forward * autocvar_g_balance_shotgun_secondary_force); + + if(accuracy_isgooddamage(self.realowner, target_victim)) { accuracy_add(self.realowner, WEP_SHOTGUN, 0, swing_damage); } + + // draw large red flash for debugging + //te_customflash(targpos, 200, 2, '15 0 0'); + + if(autocvar_g_balance_shotgun_secondary_melee_multihit) // allow multiple hits with one swing, but not against the same player twice. + { + self.swing_alreadyhit = target_victim; + continue; // move along to next trace + } + else + { + remove(self); + return; + } + } + } + + if(time >= self.cnt + meleetime) + { + // melee is finished + remove(self); + return; + } + else + { + // set up next frame + self.swing_prev = i; + self.nextthink = time; + } +} + +void W_Laser_Melee(void) +{ + sound (self, CH_WEAPON_A, "weapons/shotgun_melee.wav", VOL_BASE, ATTN_NORM); + weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_shotgun_secondary_animtime, w_ready); + + entity meleetemp; + meleetemp = spawn(); + meleetemp.owner = meleetemp.realowner = self; + meleetemp.think = W_Laser_Melee_Think; + meleetemp.nextthink = time + autocvar_g_balance_shotgun_secondary_melee_delay * W_WeaponRateFactor(); + W_SetupShot_Range(self, TRUE, 0, "", 0, autocvar_g_balance_shotgun_secondary_damage, autocvar_g_balance_shotgun_secondary_melee_range); +} + void W_Laser_Attack (float issecondary) { entity missile; @@ -313,6 +424,17 @@ float w_laser(float req) break; } + + case 2: // melee attack secondary + { + if (self.clip_load >= 0) // we are not currently reloading + 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_shotgun_secondary_refire)) + { + // attempt forcing playback of the anim by switching to another anim (that we never play) here... + weapon_thinkf(WFRAME_FIRE1, 0, W_Laser_Melee); + } + } } } } -- 2.39.2