Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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;
        }
Esempio n. 3
0
        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);
            }
        }