bool DetectHit(Vec3f position) { NPCInst target = null; this.World.BaseWorld.ForEachNPCRoughPredicate(position, GUCScripts.BiggestNPCRadius, baseNPC => { NPCInst npc = (NPCInst)baseNPC.ScriptObject; if (!npc.IsDead && npc != Shooter && NPCInst.AllowHitEvent.TrueForAll(Shooter, npc) && npc.AllowHitTarget.TrueForAll(Shooter, npc) && Shooter.AllowHitAttacker.TrueForAll(Shooter, npc)) { var modelDef = npc.ModelDef; var npcPos = npc.GetPosition() + npc.BaseInst.GetAtVector() * npc.ModelDef.CenterOffset; if (npcPos.GetDistancePlanar(position) <= modelDef.Radius && Math.Abs(npcPos.Y - position.Y) <= modelDef.HalfHeight) { target = npc; return(false); } } return(true); }); if (target != null) { target.Hit(Shooter, Damage); return(true); } return(false); }
public void Hit(NPCInst attacker, int damage, bool fromFront = true) { var strm = this.BaseInst.GetScriptVobStream(); strm.Write((byte)ScriptVobMessageIDs.HitMessage); strm.Write((ushort)attacker.ID); this.BaseInst.SendScriptVobStream(strm); int protection = this.Protection; var armor = this.GetArmor(); if (armor != null) { protection += armor.Protection; } // two weapons ItemInst otherMelee; if ((otherMelee = this.GetLeftHand()) != null && otherMelee.ItemType == ItemTypes.Wep1H) { protection -= otherMelee.Damage / 4; } damage -= protection; // ARENA if (this.TeamID >= 0 && attacker.TeamID == this.TeamID) // same team { damage /= 2; } if (damage <= 0) { damage = 1; } int resultingHP = this.GetHealth() - damage; if (DropUnconsciousOnDeath && resultingHP <= 1) { resultingHP = 1; this.DropUnconscious(UnconsciousDuration, !fromFront); } this.SetHealth(resultingHP); sOnHit?.Invoke(attacker, this, damage); OnHit?.Invoke(attacker, this, damage); lastHitMoveTime = GameTime.Ticks; }
void CalcHit() { try { if (this.IsDead || this.FightAnimation == null || this.IsUnconscious) { return; } Vec3f attPos = this.GetPosition(); Angles attAng = this.GetAngles(); int baseDamage = 5 + this.Damage; ItemInst weapon; if ((weapon = this.GetDrawnWeapon()) != null) { baseDamage += weapon.Damage; } // two weapons if ((weapon = this.GetLeftHand()) != null && weapon.ItemType == ItemTypes.Wep1H) { baseDamage += weapon.Damage / 4; } float weaponRange = GetFightRange(); this.BaseInst.World.ForEachNPCRough(attPos, GUCScripts.BiggestNPCRadius + weaponRange, npc => // fixme: enemy model radius { NPCInst target = (NPCInst)npc.ScriptObject; if (target == this || target.IsDead || target.IsUnconscious) { return; } if (!AllowHitEvent.TrueForAll(this, target) || !this.AllowHitAttacker.TrueForAll(this, target) || !target.AllowHitTarget.TrueForAll(this, target)) { return; } float realRange = weaponRange + target.ModelDef.Radius; if (target.CurrentFightMove == FightMoves.Dodge) { realRange /= 3.0f; // decrease radius if target is backing up } Vec3f targetPos = npc.Position + npc.GetAtVector() * target.ModelDef.CenterOffset; if ((targetPos - attPos).GetLength() > realRange) { return; // not in range } float hitHeight; float hitYaw; if (CurrentFightMove == FightMoves.Left || CurrentFightMove == FightMoves.Right) { hitHeight = target.ModelDef.HalfHeight; hitYaw = Angles.PI * 0.4f; } else { hitHeight = target.ModelDef.HalfHeight + this.ModelDef.HalfHeight; hitYaw = Angles.PI * 0.2f; } if (Math.Abs(targetPos.Y - attPos.Y) > hitHeight) { return; // not same height } float yaw = Angles.GetYawFromAtVector(targetPos - attPos); if (Math.Abs(Angles.Difference(yaw, attAng.Yaw)) > hitYaw) { return; // target is not in front of attacker } float tdiff = Math.Abs(Angles.Difference(target.GetAngles().Yaw, yaw)); if (target.CurrentFightMove == FightMoves.Parry && tdiff > Angles.PI / 2) // parry 180 degrees { var strm = this.BaseInst.GetScriptVobStream(); strm.Write((byte)ScriptVobMessageIDs.ParryMessage); strm.Write((ushort)npc.ID); this.BaseInst.SendScriptVobStream(strm); } else // HIT { int damage = baseDamage; if (CurrentFightMove == FightMoves.Left || CurrentFightMove == FightMoves.Right) { damage -= 2; } else if (CurrentFightMove == FightMoves.Fwd) { damage += (comboNum - 1) * 2; } else if (CurrentFightMove == FightMoves.Run) { damage += 6; if (Environment.InAir) // super jump attack { damage += 2; // not too much because you can always jump } if (target.Environment.InAir) { damage += 2; } } bool frontAttack; if (tdiff < Angles.PI / 4) // backstab { damage += 4; frontAttack = false; } else { frontAttack = true; } target.Hit(this, damage, frontAttack); } }); } catch (Exception e) { Logger.Log("CalcHit of npc " + this.ID + " " + this.BaseInst.HP + " " + e); } }