예제 #1
0
        public override void Update(GuidedVob vob, long now)
        {
            if (Target == null)
            {
                return;
            }

            if (!Cast.Try(vob.ScriptObject, out NPCInst npc))
            {
                throw new Exception("Vob used with GoToVobLookAtCommand is no NPC!");
            }

            if (npc.IsDead)
            {
                return;
            }

            var gNpc = npc.BaseInst.gVob;

            gNpc.RbtTimer     = 500;
            gNpc.RbtTargetVob = Target.BaseInst.gVob;
            gNpc.RbtBitfield  = gNpc.RbtBitfield | (1 << 4); // stand when reached
            Target.GetPosition().SetGVec(gNpc.RbtTargetPos);
            gNpc.RbtMaxTargetDist = Distance * Distance;
            gNpc.RbtGotoFollowPosition();

            Vec3f npcPos    = npc.GetPosition();
            Vec3f targetPos = Target.GetPosition();

            if (npcPos.GetDistance(targetPos) <= Distance)
            {
                const float maxTurnFightSpeed = 0.08f;

                float  bestYaw   = Angles.GetYawFromAtVector(targetPos - npcPos);
                Angles curAngles = npc.GetAngles();

                float yawDiff = Angles.Difference(bestYaw, curAngles.Yaw);
                curAngles.Yaw += Alg.Clamp(-maxTurnFightSpeed, yawDiff, maxTurnFightSpeed);

                npc.SetAngles(curAngles);
            }
        }
예제 #2
0
        private void CalcHit()
        {
            try
            {
                if (IsDead || FightAnimation == null || IsUnconscious)
                {
                    return;
                }

                Vec3f  attPos = GetPosition();
                Angles attAng = GetAngles();

                int baseDamage = 5 + Damage;

                ItemInst weapon;
                if ((weapon = GetDrawnWeapon()) != null)
                {
                    baseDamage += weapon.Damage;
                }

                // two weapons
                if ((weapon = GetLeftHand()) != null && weapon.ItemType == ItemTypes.Wep1H)
                {
                    baseDamage += weapon.Damage / 4;
                }

                float weaponRange = GetFightRange();
                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) ||
                        !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 + 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 = BaseInst.GetScriptVobStream();
                        strm.Write((byte)ScriptVobMessageIDs.ParryMessage);
                        strm.Write((ushort)npc.ID);
                        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 " + ID + " " + BaseInst.HP + " " + e);
            }
        }
예제 #3
0
        static void Update()
        {
            NPCInst hero = currentPlayer;

            if (hero == null)
            {
                Deactivate();
                return;
            }

            float maxYaw    = Angles.Deg2Rad(60);
            bool  fightMode = hero.IsInFightMode;

            ItemInst wep      = hero.GetDrawnWeapon();
            float    maxRange = (fightMode && wep != null && wep.IsWepRanged) ? 3000 : 400;

            Vec3f  heroPos = hero.GetPosition();
            Angles heroAng = hero.GetAngles();

            float       bestFit = 2.0f;
            BaseVobInst bestVob = null;

            if (hero?.World?.BaseWorld != null)
            {
                hero.World.BaseWorld.ForEachVob(v =>
                {
                    BaseVobInst vob = (BaseVobInst)v.ScriptObject;
                    if (vob == hero)
                    {
                        return;
                    }

                    bool hasPriority = false;
                    if (fightMode)
                    {
                        if (!(vob is NPCInst npc))
                        {
                            return;
                        }

                        if (npc.IsDead)
                        {
                            return;
                        }

                        if (bestVob != null)
                        {
                            NPCInst bestNPC = (NPCInst)bestVob;
                            if (npc.IsUnconscious)
                            {
                                if (!bestNPC.IsUnconscious)
                                {
                                    return; // alive targets are more important
                                }
                            }
                            else
                            {
                                if (bestNPC.IsUnconscious)
                                {
                                    hasPriority = true;
                                }
                            }

                            if (npc.TeamID == hero.TeamID)
                            {
                                if (bestNPC.TeamID != hero.TeamID)
                                {
                                    return;
                                }
                            }
                            else
                            {
                                if (bestNPC.TeamID == hero.TeamID)
                                {
                                    hasPriority = true;
                                }
                            }
                        }
                    }

                    Vec3f targetPos;
                    using (zVec3 z = zVec3.Create())
                    {
                        vob.BaseInst.gVob.BBox3D.GetCenter(z);
                        targetPos = (Vec3f)z;
                    }

                    float distance = heroPos.GetDistance(targetPos);
                    if (distance > maxRange)
                    {
                        return;
                    }

                    float yaw = Angles.GetYawFromAtVector(targetPos - heroPos);
                    yaw       = Math.Abs(Angles.Difference(yaw, heroAng.Yaw));
                    if (yaw > maxYaw)
                    {
                        return; // target is not in front of hero
                    }
                    if (!CanSee(heroPos, targetPos, vob))
                    {
                        return;
                    }

                    float fit = distance / maxRange + yaw / maxYaw;
                    if (hasPriority || fit < bestFit)
                    {
                        bestVob = vob;
                        bestFit = fit;
                    }
                });

                SetFocus(bestVob);
            }
        }
예제 #4
0
        static void DoTurning(NPCInst hero)
        {
            if (hero.BaseInst.gAI.GetFoundLedge())
            {
                return;
            }

            const float maxTurnFightSpeed = 0.07f;

            NPCInst enemy = PlayerFocus.LockedTarget;

            if (enemy != null)
            {
                Vec3f heroPos  = hero.GetPosition();
                Vec3f enemyPos = enemy.GetPosition();

                float  bestYaw   = Angles.GetYawFromAtVector(enemyPos - heroPos);
                Angles curAngles = hero.GetAngles();

                float yawDiff = Angles.Difference(bestYaw, curAngles.Yaw);
                curAngles.Yaw += Alg.Clamp(-maxTurnFightSpeed, yawDiff, maxTurnFightSpeed);

                hero.SetAngles(curAngles);
                CheckCombineAim(hero, enemyPos - heroPos);
                return;
            }

            const float maxLookupSpeed = 2f;
            float       rotSpeed       = 0;

            if (InputHandler.MouseDistY != 0)
            {
                rotSpeed = Alg.Clamp(-maxLookupSpeed, InputHandler.MouseDistY * 0.35f * MouseSpeed, maxLookupSpeed);

                if (hero.Environment.WaterLevel >= 1)
                {
                    hero.BaseInst.gAI.DiveRotateX(rotSpeed);
                }
                else
                {
                    var cam = zCAICamera.CurrentCam;
                    cam.BestElevation = Alg.Clamp(-50, cam.BestElevation + rotSpeed, 85);
                }
            }

            // Fixme: do own turning
            const float maxTurnSpeed = 2f;

            if (!KeyBind.Action.IsPressed())
            {
                float turn = 0;
                if (KeyBind.TurnLeft.IsPressed())
                {
                    turn = -maxTurnSpeed;
                }
                else if (KeyBind.TurnRight.IsPressed())
                {
                    turn = maxTurnSpeed;
                }
                else if (Math.Abs(InputHandler.MouseDistX) > ((rotSpeed > 0.5f && hero.Movement == NPCMovement.Stand) ? 18 : 2))
                {
                    turn = Alg.Clamp(-maxTurnSpeed, InputHandler.MouseDistX * 0.45f * MouseSpeed, maxTurnSpeed);
                }

                if (turn != 0)
                {
                    hero.BaseInst.gAI.Turn(turn, !hero.ModelInst.IsInAnimation());
                    return;
                }
            }
            hero.BaseInst.gVob.AniCtrl.StopTurnAnis();
        }