diff --git a/client.qc b/client.qc index 2c288bf..ec7bd49 100644 --- a/client.qc +++ b/client.qc @@ -2841,6 +2841,8 @@ void() PlayerPreThink = if (self.health > 0 && self.solid != SOLID_NOT) { + trace_ent = NIL; + // do a quick checkmove checkmove (self.origin, self.mins, self.maxs, self.origin - '0 0 8192', MOVE_NORMAL, self); @@ -2856,6 +2858,13 @@ void() PlayerPreThink = if (self.stucktime && self.stucktime < time && (trace_ent.solid == SOLID_BSP || trace_ent.classname == "player")) { +#ifdef DEBUG + dprint ("Stuck kill, self: \n"); + eprint (self); + dprint ("trace_ent: \n"); + eprint (trace_ent); +#endif + TF_T_Damage (self, NIL, NIL, self.health + 100, TF_TD_IGNOREARMOUR, TF_TD_OTHER); } @@ -2863,6 +2872,13 @@ void() PlayerPreThink = { if (trace_ent.takedamage && trace_ent.classname != "player") { +#ifdef DEBUG + dprint ("Physics kill, self: \n"); + eprint (self); + dprint ("trace_ent: "); + eprint (trace_ent); +#endif + TF_T_Damage (trace_ent, NIL, NIL, self.health + 100, TF_TD_IGNOREARMOUR, TF_TD_OTHER); } diff --git a/combat.qc b/combat.qc index b1572d9..d56c870 100644 --- a/combat.qc +++ b/combat.qc @@ -542,18 +542,18 @@ void(entity targ, entity inflictor, entity attacker, float damage, float T_flags } } - else if ((targ.armorclass & AT_SAVEMELEE) && (deathmsg == DMSG_JUDOKA || deathmsg == DMSG_AXE || deathmsg == DMSG_BACKSTAB || deathmsg == DMSG_SPANNER)) + else if ((targ.armorclass & AT_SAVEMELEE) && (T_AttackType = TF_TD_MELEE)) { - // This crap should all be in the weapon function. Stupid morons. damage = floor(damage * 0.5); + if ((targ.velocity_x > 0 || targ.velocity_y > 0 || targ.velocity_z > 0) && random() > 0.6) return; - if (deathmsg == DMSG_BACKSTAB) // O_O, why is this here? - T_flags = T_flags - (T_flags & TF_TD_IGNOREARMOUR); } else if ((targ.armorclass & AT_SAVEEXPLOSION) && (T_AttackType == TF_TD_EXPLOSION)) damage = floor(damage * 0.5); - else if ((targ.armorclass & AT_SAVEELECTRICITY) && (T_AttackType == TF_TD_ELECTRICITY || T_AttackType == TF_TD_NAIL)) + else if ((targ.armorclass & AT_SAVEELECTRICITY) && (T_AttackType == TF_TD_ELECTRICITY)) + damage = floor(damage * 0.5); + else if ((targ.armorclass & AT_SAVENAIL) && (T_AttackType == TF_TD_NAIL)) damage = floor(damage * 0.5); else if ((targ.armorclass & AT_SAVEFIRE) && (T_AttackType == TF_TD_FIRE)) damage = floor(damage * 0.5); diff --git a/defs.qh b/defs.qh index 5a2cc44..6c9b6cb 100644 --- a/defs.qh +++ b/defs.qh @@ -269,6 +269,7 @@ float (entity e) EF_GlowColor; #define TF_TD_ELECTRICITY 8 // Electric damage #define TF_TD_FIRE 16 // Fire damage #define TF_TD_NOSOUND 256 // Special damage. Makes no sound/painframe, etc +#define TF_TD_MELEE 512 //WK 152 Default, must be > 6. @@ -866,10 +867,12 @@ float (entity e) EF_GlowColor; // Armor Classes : Bitfields. Use the "armorclass" of armor for the Armor Type. #define AT_SAVESHOT 1 // Kevlar : Reduces bullet damage by 15% -#define AT_SAVEMELEE 2 // Gel : Reduces melee attacks by 15% +#define AT_SAVENAIL 2 // Wood : Reduces nail damage 15% #define AT_SAVEEXPLOSION 4 // Blast : Reduces explosion damage 15% #define AT_SAVEELECTRICITY 8 // Shock : Reduces electricity damage by 15% #define AT_SAVEFIRE 16 // Asbestos : Reduces fire damage by 15% +#define AT_SAVEMELEE 32 // Gel : Reduces melee attacks by 15% + /*==========================================================================*/ /* TEAMFORTRESS CLASS DETAILS */ diff --git a/items.qc b/items.qc index 3e8ac4a..c3895c6 100644 --- a/items.qc +++ b/items.qc @@ -375,7 +375,21 @@ void() armor_touch = bit = IT_ARMOR3; } - if (other.armortype * other.armorvalue >= type*value) + local string st = infokey (NIL, "armor_add"); + if (!st) + st = infokey (NIL, "ara"); + + if (other.armortype > type && (!st || (st != "no" && st != "0" && st != "off"))) { + value *= type / other.armortype; + type = other.armortype; + + if (type == 0.8) + bit = IT_ARMOR3; + else if (type == 0.6) + bit = IT_ARMOR2; + } + + if (other.armorvalue >= value) { // Engineers can still grab the metal //WK - My 'Engineers' can too @@ -390,7 +404,7 @@ void() armor_touch = } } - if (other.armor_allowed * other.maxarmor <= type*value) + if (other.maxarmor * other.armor_allowed <= type * value) { if (other.armor_allowed == other.armortype) { @@ -451,7 +465,7 @@ void() armor_touch = value = other.maxarmor; } - if (other.armortype * other.armorvalue < type*value) + if (other.armortype * other.armorvalue < type * value) { other.armortype = type; other.armorvalue = value; @@ -459,6 +473,21 @@ void() armor_touch = other.items = other.items & ~(IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3) | bit; } + if (other.armorvalue) { + // always get their bought armorclass back + + if (other.tf_items & NIT_KEVLAR) + other.armorclass |= AT_SAVESHOT; + if (other.tf_items & NIT_GEL) + other.armorclass |= AT_SAVEMELEE; + if (other.tf_items & NIT_BLAST) + other.armorclass |= AT_SAVEEXPLOSION; + if (other.tf_items & NIT_CERAMIC) + other.armorclass |= AT_SAVEELECTRICITY; + if (other.tf_items & NIT_ASBESTOS) + other.armorclass |= AT_SAVEFIRE; + } + self.solid = SOLID_NOT; self.model = ""; if (deathmatch != 2) diff --git a/jobs.qc b/jobs.qc index 061ea30..c14b81c 100644 --- a/jobs.qc +++ b/jobs.qc @@ -61,6 +61,7 @@ float(entity thing) IsMonsterNonArmy; float(entity thing) IsMonster; // for mines void() JobArmy; void() JobHacker; +void(entity e, boolean b, float f) find_melee; // // Functions for handling our "professions" @@ -569,7 +570,6 @@ void() JobJudoka = { //Take the weapon of any person in front of you and force a reload self.job_finished = time + MISS_DELAY; //Delay if we don't hit - local vector source; local vector dir; local float chance; local entity tWeapon,oself; @@ -578,13 +578,7 @@ void() JobJudoka = if (self.attack_finished > time) return; - makevectors(self.v_angle); - source = self.origin + '0 0 16'; - - if (self.cutf_items & CUTF_CLOSECOMBAT) - traceline(source, source + v_forward*96, FALSE, self); - else - traceline(source, source + v_forward*64, FALSE, self); + find_melee (self, TRUE, 48); if (trace_fraction != 1.0 && trace_ent.classname == "player" && !Teammate(trace_ent.team_no, self.team_no) && trace_ent.playerclass != PC_UNDEFINED) { @@ -665,14 +659,14 @@ void() JobJudoka = //Hit fellow judoka or chaplan sprint (self, PRINT_HIGH, "You throw him with a mighty Seoi Otoshi\n"); deathmsg = DMSG_JUDOKA; - TF_T_Damage (trace_ent, self, self, 150, TF_TD_NOTTEAM, TF_TD_OTHER); + TF_T_Damage (trace_ent, self, self, 150, TF_TD_NOTTEAM, TF_TD_MELEE); } else if (self.weapons_carried & trace_ent.current_weapon) { sprint (self, PRINT_HIGH, "You knock his weapon out of his hands\n"); tWeapon.heat = 0; //I.e., we didn't take a weapon trace_ent.attack_finished = time + DISARM_TIME; deathmsg = DMSG_JUDOKA; - TF_T_Damage (trace_ent, self, self, 100, TF_TD_NOTTEAM, TF_TD_OTHER); + TF_T_Damage (trace_ent, self, self, 100, TF_TD_NOTTEAM, TF_TD_MELEE); } else if (trace_ent.current_weapon != 0 && trace_ent.current_weapon != WEAP_AXE){ //Steal their weapon if they have one @@ -719,7 +713,7 @@ void() JobJudoka = trace_ent.current_weapon = 0; deathmsg = DMSG_JUDOKA; - TF_T_Damage (trace_ent, self, self, 65, TF_TD_NOTTEAM, TF_TD_OTHER); + TF_T_Damage (trace_ent, self, self, 65, TF_TD_NOTTEAM, TF_TD_MELEE); } self.job_finished = time + HIT_DELAY; diff --git a/player.qc b/player.qc index fe94505..46f6d2d 100644 --- a/player.qc +++ b/player.qc @@ -323,7 +323,7 @@ void() player_axeb3 = [$axattb3, player_axeb4 ] { self.weaponframe=7; if (self.current_weapon == WEAP_AXE) - W_FireAxe(); + W_FireBackstab(); else // if (self.current_weapon == WEAP_SPANNER) W_FireSpanner(); }; @@ -347,7 +347,7 @@ void() player_axed3 = [$axattd3, player_axed4 ] { self.weaponframe=7; if (self.current_weapon == WEAP_AXE) - W_FireAxe(); + W_FireBackstab(); else // if (self.current_weapon == WEAP_SPANNER) W_FireSpanner(); }; @@ -1112,7 +1112,6 @@ void(string gibname, float dm) ThrowGib = newmis = spawn(); newmis.origin = self.origin; setmodel (newmis, gibname); - setsize (newmis, '0 0 0', '0 0 0'); newmis.velocity = VelocityForDamage (dm); newmis.movetype = MOVETYPE_BOUNCE; newmis.solid = SOLID_NOT; @@ -1129,6 +1128,8 @@ void(string gibname, float dm) ThrowGib = newmis.skin=dm; newmis.velocity = VelocityForDamage (-70); } + + setsize (newmis, '0 0 0', '0 0 0'); }; void(string gibname, float dm) ThrowHead = @@ -1158,6 +1159,8 @@ void(string gibname, float dm) ThrowHead = self.nextthink = time + 20 + 20 * random(); } */ + + setorigin (self, self.origin); //-OfN }; @@ -1175,6 +1178,8 @@ void(string gibname) HeadShotThrowHead = self.origin_z = self.origin_z + 24; self.flags = self.flags - (self.flags & FL_ONGROUND); self.avelocity = '0 0 0'; + + setorigin (self, self.origin); }; void() KillPlayer = diff --git a/tfort.qc b/tfort.qc index 34459ba..2a783da 100644 --- a/tfort.qc +++ b/tfort.qc @@ -2416,6 +2416,10 @@ float(entity Player, float Armorclass) TeamFortress_DescribeArmor = sprint (Player, PRINT_HIGH, "Kevlar "); num = num + 1; } + if (Armorclass & AT_SAVENAIL) { + sprint (Player, PRINT_HIGH, "Wood "); + num = num + 1; + } sprint (Player, PRINT_HIGH, "armor"); return num; diff --git a/tfortmap.qc b/tfortmap.qc index c35d911..b305b85 100644 --- a/tfortmap.qc +++ b/tfortmap.qc @@ -989,25 +989,40 @@ void(entity Goal, entity Player, entity AP, float addb) Apply_Results = { if (Goal.armortype) Player.armortype = Goal.armortype; + else if (!Player.armorvalue || !Player.armortype) + Player.armortype = Player.armor_allowed; + Player.armorvalue = Player.armorvalue + Goal.armorvalue; if (Goal.armorclass) { //WK Modify to | it with bought armor //TODO: Make this a map specific option //WK Don't give wooden armor since it doesn't exist // any more. And we don't want gel for free, right? - Player.armorclass = Goal.armorclass - (Goal.armorclass & AT_SAVEMELEE); - if (Player.tf_items & NIT_KEVLAR) - Player.armorclass = Player.armorclass | AT_SAVESHOT; - if (Player.tf_items & NIT_GEL) - Player.armorclass = Player.armorclass | AT_SAVEMELEE; - if (Player.tf_items & NIT_BLAST) - Player.armorclass = Player.armorclass | AT_SAVEEXPLOSION; - if (Player.tf_items & NIT_CERAMIC) - Player.armorclass = Player.armorclass | AT_SAVEELECTRICITY; - if (Player.tf_items & NIT_ASBESTOS) - Player.armorclass = Player.armorclass | AT_SAVEFIRE; + Player.armorclass = Goal.armorclass; } + // always get their bought armorclass back + + if (Player.tf_items & NIT_KEVLAR) + Player.armorclass = Player.armorclass | AT_SAVESHOT; + if (Player.tf_items & NIT_GEL) + Player.armorclass = Player.armorclass | AT_SAVEMELEE; + if (Player.tf_items & NIT_BLAST) + Player.armorclass = Player.armorclass | AT_SAVEEXPLOSION; + if (Player.tf_items & NIT_CERAMIC) + Player.armorclass = Player.armorclass | AT_SAVEELECTRICITY; + if (Player.tf_items & NIT_ASBESTOS) + Player.armorclass = Player.armorclass | AT_SAVEFIRE; + + Player.items &= ~(IT_ARMOR3 | IT_ARMOR2 | IT_ARMOR1); + + if (Player.armortype >= 0.8) + Player.items |= IT_ARMOR3; + else if (Player.armortype >= 0.6) + Player.items |= IT_ARMOR2; + else if (Player.armortype >= 0.3) + Player.items |= IT_ARMOR1; + Player.ammo_shells = Player.ammo_shells + Goal.ammo_shells; Player.ammo_nails = Player.ammo_nails + Goal.ammo_nails; Player.ammo_rockets = Player.ammo_rockets + Goal.ammo_rockets; diff --git a/weapons.qc b/weapons.qc index 9406e40..c789304 100644 --- a/weapons.qc +++ b/weapons.qc @@ -239,11 +239,50 @@ void(float att_delay) Attack_Finished = if (self.tfstate & TFSTATE_TRANQUILISED) self.attack_finished = time + (att_delay * 1.5); else if (self.aura == AURA_HASTE) - self.attack_finished = time + (att_delay * 0.75); + self.attack_finished = time + (att_delay * 0.5); else self.attack_finished = time + att_delay; }; +void (entity atk, boolean do_cc, float dist) find_melee = +{ + local vector dir; + + if (self.classname == "player") { + makevectors (atk.v_angle); + dir = v_forward; + } else { + dir = normalize (atk.enemy.origin - atk.origin); + } + + local vector source = atk.origin + '0 0 16'; + + traceline (source, source + dir*dist, FALSE, atk); + + if (trace_fraction != 1.0) + return; + + if (do_cc && (atk.cutf_items & CUTF_CLOSECOMBAT)) { + local entity te = findradius (source, dist); + local float tdist = -0.6; + + do { + local vector diff = source - (te.origin + '0 0 16'); + diff_z *= 0.75; //hack + + local float l; + + l = (normalize (diff) * dir); + + if (l < tdist && te.takedamage == DAMAGE_AIM) { + tdist = l; + trace_ent = te; + trace_fraction = 0.5; + } + } while ((te = te.chain)); + } +}; + /* ================ W_FireAxe @@ -251,49 +290,32 @@ W_FireAxe */ void() W_FireAxe = { - local vector source; - local vector org, def; - local vector dir = NIL; //XXX false +ve on uninit - - if (self.classname == "player") - makevectors(self.v_angle); - else - dir = normalize (self.enemy.origin - self.origin); - source = self.origin + '0 0 16'; + local vector org; - if (self.classname == "player") { - if (!(self.cutf_items & CUTF_CLOSECOMBAT)) - traceline (source, source + v_forward*64, FALSE, self); - else - traceline (source, source + v_forward*96, FALSE, self); - } - else - traceline (source, source + dir*64, FALSE, self); + find_melee (self, TRUE, 64); if (trace_fraction == 1.0) return; - + org = trace_endpos - v_forward*4; - if (trace_ent.classname == "force_field") { - FieldExplosion(trace_ent,trace_endpos,trace_ent); - PutFieldWork(trace_ent); - - return; - } + if (trace_ent.classname == "force_field") { + FieldExplosion(trace_ent,trace_endpos,trace_ent); + PutFieldWork(trace_ent); + + return; + } if (trace_ent.takedamage) { trace_ent.axhitme = 1; SpawnBlood (org, 20); - if (!(self.cutf_items & CUTF_KNIFE) || trace_ent.classname != "player") { - deathmsg = DMSG_AXE; - if (!(self.cutf_items & CUTF_CLOSECOMBAT)) - TF_T_Damage (trace_ent, self, self, 30, TF_TD_NOTTEAM, TF_TD_OTHER); - else - TF_T_Damage (trace_ent, self, self, 60, TF_TD_NOTTEAM, TF_TD_OTHER); - } else { // spy can try for the backstab! + deathmsg = DMSG_AXE; + + if (!(self.cutf_items & CUTF_KNIFE)) { + TF_T_Damage (trace_ent, self, self, 30, TF_TD_NOTTEAM, TF_TD_MELEE); + } else { //WK Only give blood if you hit an enemy when being a warlock if ((!Teammate(trace_ent.team_no, self.team_no) || !(self.job & JOB_WARLOCK)) && prematch < time) { self.job = self.job | JOB_BLOODY_KNIFE; @@ -303,35 +325,7 @@ void() W_FireAxe = sprint(self,PRINT_HIGH,"You may only draw blood from enemies\n"); } - // Check direction of Attack - makevectors(trace_ent.v_angle); - def = v_right; - if (self.classname == "player") - makevectors(self.v_angle); - else - makevectors(self.angles); - - // Backstab - if ((crossproduct(def,v_forward) * '0 0 1') > 0) { - deathmsg = DMSG_BACKSTAB; - ThrowGib("progs/gib1.mdl", -50); - ThrowGib("progs/gib2.mdl", 10); - ThrowGib("progs/gib3.mdl", 50); - ThrowGib ("progs/gib2.mdl", 25); //-added - -//WK 120 & no IGNOREARMOR - if (!(self.cutf_items & CUTF_CLOSECOMBAT)) - TF_T_Damage (trace_ent, self, self, 100, TF_TD_IGNOREARMOUR | TF_TD_NOTTEAM, TF_TD_OTHER); - else - TF_T_Damage (trace_ent, self, self, 200, TF_TD_IGNOREARMOUR | TF_TD_NOTTEAM, TF_TD_OTHER); - } else { - deathmsg = DMSG_AXE; -//WK 40 - if (!(self.cutf_items & CUTF_CLOSECOMBAT)) - TF_T_Damage (trace_ent, self, self, 50, TF_TD_NOTTEAM, TF_TD_OTHER); - else - TF_T_Damage (trace_ent, self, self, 100, TF_TD_NOTTEAM, TF_TD_OTHER); - } + TF_T_Damage (trace_ent, self, self, 50, TF_TD_NOTTEAM, TF_TD_MELEE); } } else { // hit wall sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM); @@ -345,6 +339,130 @@ void() W_FireAxe = } }; +boolean (boolean strict) is_backstab = +{ + local float d; + local vector dir; + + makevectors (trace_ent.angles); + + dir = trace_ent.origin - self.origin; + + dir_z *= 0.75; // hack + + d = normalize (dir) * v_forward; + + if (d < 0.3) + return FALSE; + + if (!strict) + return TRUE; + + if (d < 0.7) + return FALSE; + + d = normalize (trace_ent.origin - trace_endpos) * v_forward; + + if (d < 0.8) + return FALSE; + + return TRUE; +}; + +/* +================ +W_FireBackstab +================ +*/ + +void() W_FireBackstab = +{ + local vector org; + + if (!(self.cutf_items & CUTF_KNIFE)) { + W_FireAxe (); + return; + } + + find_melee (self, FALSE, 64); + + if (trace_fraction == 1.0) + return; + + org = trace_endpos - v_forward*4; + + if (trace_ent.classname == "force_field") { + FieldExplosion(trace_ent,trace_endpos,trace_ent); + PutFieldWork(trace_ent); + + return; + } + + local boolean living = FALSE; + + if (trace_ent.classname == "player" || IsMonster (trace_ent)) + living = TRUE; + + if (trace_ent.takedamage) { + trace_ent.axhitme = 1; + + deathmsg = DMSG_BACKSTAB; + + if (living) { + if (trace_ent.classname != "player" && trace_ent.real_owner) + trace_ent.team_no = trace_ent.real_owner.team_no; + + //WK Only give blood if you hit an enemy when being a warlock + if ((!Teammate(trace_ent.team_no, self.team_no) || !(self.job & JOB_WARLOCK)) && prematch < time) { + self.job = self.job | JOB_BLOODY_KNIFE; + self.weaponmode = 1; + self.weaponmodel = "progs/v_knife2.mdl"; + } else if (self.job & JOB_WARLOCK) { + sprint(self,PRINT_HIGH,"You may only draw blood from enemies\n"); + } + } + + if (is_backstab (TRUE) && living) { + + SpawnBlood (org, 50); + + local entity oself = self; + self = trace_ent; + + ThrowGib ("progs/gib1.mdl", -50); + ThrowGib ("progs/gib2.mdl", 10); + ThrowGib ("progs/gib3.mdl", 50); + ThrowGib ("progs/gib2.mdl", 25); + + self = oself; + + if (trace_ent.classname == "player") + stuffcmd (trace_ent, "bf; bf\n"); + + if (!(trace_ent.armorclass & AT_SAVEMELEE)) + TF_T_Damage (trace_ent, self, self, 100, TF_TD_NOTTEAM | TF_TD_IGNOREARMOUR, + TF_TD_MELEE); + else + TF_T_Damage (trace_ent, self, self, 100, TF_TD_NOTTEAM, TF_TD_MELEE); + } else { + deathmsg = DMSG_AXE; + + SpawnBlood (org, 10); + + TF_T_Damage (trace_ent, self, self, 30, TF_TD_NOTTEAM, TF_TD_MELEE); + } + + } else { // hit wall + sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM); + WriteByte (MSG_MULTICAST, SVC_TEMPENTITY); + WriteByte (MSG_MULTICAST, TE_GUNSHOT); + WriteByte (MSG_MULTICAST, 3); + WriteCoord (MSG_MULTICAST, org_x); + WriteCoord (MSG_MULTICAST, org_y); + WriteCoord (MSG_MULTICAST, org_z); + multicast (org, MULTICAST_PVS); + } +} /* ================ W_FireSpanner @@ -352,17 +470,11 @@ W_FireSpanner */ void() W_FireSpanner = { - local vector source; local vector org; local float healam; local entity te; - makevectors(self.v_angle); - source = self.origin + '0 0 16'; - if (self.cutf_items & CUTF_CLOSECOMBAT) - traceline (source, source + v_forward*96, FALSE, self); - else - traceline (source, source + v_forward*64, FALSE, self); + find_melee (self, TRUE, 64); if (trace_fraction == 1.0) return; @@ -419,8 +531,9 @@ void() W_FireSpanner = // auto-repair/dismantle if hit twice if (trace_ent == self.building) { Engineer_AutoUse(); - return; - } else if (trace_ent.classname == "building_dispenser") { + } + + if (trace_ent.classname == "building_dispenser") { Engineer_UseDispenser(trace_ent); return; } else if (trace_ent.classname == "building_sentrygun") { @@ -492,10 +605,7 @@ void() W_FireSpanner = deathmsg = DMSG_SPANNER; //WK 20 - if (!(self.cutf_items & CUTF_CLOSECOMBAT)) - TF_T_Damage (trace_ent, self, self, 20, TF_TD_NOTTEAM, TF_TD_OTHER); - else - TF_T_Damage (trace_ent, self, self, 40, TF_TD_NOTTEAM, TF_TD_OTHER); + TF_T_Damage (trace_ent, self, self, 20, TF_TD_NOTTEAM, TF_TD_MELEE); } } else { // hit wall sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM); @@ -520,18 +630,11 @@ void(float tno, entity ignore, entity ignore2) teamprefixsprintbi; void(float inAuto) W_FireMedikit = { - local vector source; local vector org; local float healam; local entity te, BioInfection; - makevectors (self.v_angle); - - source = self.origin + '0 0 16'; - if (self.cutf_items & CUTF_CLOSECOMBAT) - traceline (source, source + v_forward*96, FALSE, self); - else - traceline (source, source + v_forward*64, FALSE, self); + find_melee (self, TRUE, 64); if (trace_fraction == 1.0) return; @@ -2784,6 +2887,12 @@ void() player_axe1; void() player_axeb1; void() player_axec1; void() player_axed1; + +void() player_axe2; +void() player_axeb2; +void() player_axec2; +void() player_axed2; + void() player_shot1; void() player_nail1; @@ -2848,21 +2957,46 @@ void() W_Attack = self.show_hostile = time + 1; // wake monsters up if (self.current_weapon == WEAP_AXE) { - //if (self.cutf_items & CUTF_KNIFE) //WK Go berserk with the knife - // Attack_Finished(0.5); // no, don't (0.35) - //else - Attack_Finished(0.5); + local float af = 0.5; sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM); r = random(); - if (r < 0.25) - player_axe1 (); - else if (r<0.5) - player_axeb1 (); - else if (r<0.75) - player_axec1 (); - else - player_axed1 (); + + if (self.cutf_items & CUTF_KNIFE) { + find_melee (self, TRUE, 72); + + if (!is_backstab (FALSE) || !trace_ent.takedamage || + (trace_ent.classname != "player" && !IsMonster (trace_ent))) { + af -= 0.1; + + if (r < 0.5) + player_axe2 (); + else + player_axec2 (); + } else { + af += 0.3; + + if (r < 0.5) + player_axeb1 (); + else + player_axed1 (); + } + } else { + if (r < 0.25) + player_axe1 (); + else if (r<0.5) + player_axeb1 (); + else if (r<0.75) + player_axec1 (); + else + player_axed1 (); + } + + if (self.cutf_items & CUTF_CLOSECOMBAT) + af -= 0.1; + + Attack_Finished (af); + } else if (self.current_weapon == WEAP_SPANNER) { Attack_Finished(0.35); //WK Berserk with spanner sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);