Пример #1
0
    private void Move(ref MonsterCharacter.InputFrame frame)
    {
        if (target == null)
        {
            return;
        }

        character.TurnSpeed = MoveTurnSpeedOverride;
        frame.up            = MovementDecision.y;
        frame.right         = MovementDecision.x;

        if (LookAtTargetOverride)
        {
            frame.WantDirection = TowardsTarget;
        }
        else
        {
            frame.WantDirection = DirectionDecision;
        }

        decisionTimer -= Time.deltaTime;
        if (decisionTimer <= 0f)
        {
            character.OnInputRequest = Hesitate;
        }
    }
Пример #2
0
    private void BlipMove(ref MonsterCharacter.InputFrame frame)
    {
        frame.up            = dir.y;
        frame.right         = dir.x;
        frame.WantDirection = Quaternion.Euler(0, 0, AxMath.SafeAtan2(dir.y, dir.x) * Mathf.Rad2Deg);

        if (blipTimer > 0)
        {
            blipTimer -= Time.deltaTime;
            return;
        }

        blipTimer = BlipTime;
        dir       = Vec2I.zero;

        if (Random.value < BlipWaitChance)
        {
            return;
        }

        if (Leashed)
        {
            if ((homePosition - transform.position).sqrMagnitude >= LeashRange * LeashRange)
            {
                Vector2 distance = transform.position - Camera.main.transform.position;
                if (Mathf.Max(distance.x) > Options.AlertDistance.x || Mathf.Max(distance.y) > Options.AlertDistance.y)
                {
                    Destroy(gameObject);
                }
            }
        }

        if (Random.value < BlipRandomChance)
        {
            dir = Vec2I.directions[Random.Range(1, Vec2I.directions.Length)];
            return;
        }

        if (HuntPlayer)
        {
            if (LastKnownPlayerRoom != -1)
            {
                targetRoom = LastKnownPlayerRoom;
            }
        }

        if (targetRoom >= 0 && targetRoom < Room.Rooms.Length)
        {
            //simplistic behavior
            //dir = Room.Rooms[targetRoom].parent[thing.gridPos.x, thing.gridPos.y] - thing.gridPos;
            //return;

            //to avoid monsters piling up on single point
            if (Vec2I.Manhattan(Room.Rooms[targetRoom].gridPos, thing.gridPos) < NearSteps)
            {
                return;
            }

            if (!AI.RoomPath(thing.gridPos, Room.Rooms[targetRoom], MaxSteps, out Vec2I[] path))
Пример #3
0
    private void FillInputFrame(ref MonsterCharacter.InputFrame frame)
    {
        if (Input.GetKeyDown(KeyCode.R))
        {
            destinationRoom = Random.Range(0, Room.Rooms.Length);
            Debug.Log("Moving towards room \"" + Room.Rooms[destinationRoom].gameObject.name + "\"");
        }

        /*int currentRoom = Room.GetRoomIndex(character.thingController.gridPos);
         *
         * if (currentRoom == destinationRoom)
         *  return;*/

        frame.up            = dir.y;
        frame.right         = dir.x;
        frame.WantDirection = Quaternion.Euler(0, 0, AxMath.SafeAtan2(dir.y, dir.x) * Mathf.Rad2Deg);

        if (timer > 0f)
        {
            return;
        }

        timer = DecisionTime;
        dir   = Vec2I.zero;

        /*if (currentRoom == -1 || destinationRoom == -1)
         *  return;
         * int nextRoom = Room.Rooms[currentRoom].ClosestNeighborTowards[destinationRoom];
         * if (nextRoom == -1)
         *  return;
         *
         * Vec2I p = Vec2I.illegalMin;
         *
         * Vec2I p = Room.Parents[nextRoom][thing.gridPos.x, thing.gridPos.y];
         *
         * HeatmapNode h = Heatmap.GetNode(p);
         * if (h != null)
         * {
         *  int closest = Room.Distance[nextRoom][thing.gridPos.x, thing.gridPos.y];
         *
         *  foreach (HeatmapNode n in h.neighbors)
         *  {
         *      int distance = Room.Distance[nextRoom][n.gridPos.x, n.gridPos.y];
         *      if (distance < closest)
         *      {
         *          p = n.gridPos;
         *          closest = distance;
         *      }
         *  }
         * }
         *
         * if (p != Vec2I.illegalMin)
         *  dir = p - thing.gridPos;*/
    }
Пример #4
0
    private void OnInputRequest(ref MonsterCharacter.InputFrame frame)
    {
        if (target == null)
            return;

        if (dualSwingTimer > 0f)
            dualSwingTimer -= Time.deltaTime;

        frame.LocalTransform = true;

        int steps = Vec2I.Max(thing.gridPos, target.thingController.gridPos);

        if (steps <= MaxAttackConsiderationStepCount)
        {
            frame.WantDirection = TowardsTarget;

            if (character.CurrentWeapon.IsReady && character.CurrentOffhand.IsReady)
            {
                if (Random.value > .5f)
                    frame.PrimaryAttackContinuous = true;
                else
                    frame.SecondaryAttackContinuous = true;

                dualSwingTimer = DualSwingDelay;
            }
            else if (dualSwingTimer <= 0f)
            {
                frame.PrimaryAttackContinuous = true;
                frame.SecondaryAttackContinuous = true;
            }

            frame.up = 1f;
            return;
        }
                
        if (CanSeeTargetGrid)
        {
            frame.WantDirection = TowardsTarget;
            if (steps > StopMovingStepCount)
                frame.up = 1f;

            return;
        }

        Vec2I smart = SmartMove;
        if (SmartMove != Vec2I.zero)
        {
            frame.WantDirection = Quaternion.Euler(0, 0, AxMath.SafeAtan2(smart.y, smart.x) * Mathf.Rad2Deg);
            if (steps > StopMovingStepCount)
                frame.up = 1;
        }
    }
Пример #5
0
    private void OnInputRequest(ref MonsterCharacter.InputFrame frame)
    {
        if (target == null)
        {
            return;
        }

        Vec2I smart = SmartMove;

        frame.up    = smart.y;
        frame.right = smart.x;

        //frame.WantDirection = Quaternion.Euler(0, 0, AxMath.SafeAtan2(smart.y, smart.x) * Mathf.Rad2Deg);
        frame.WantDirection = TowardsTarget;
    }
Пример #6
0
    private void StandAround(ref MonsterCharacter.InputFrame frame)
    {
        if (lookatTarget != null)
        {
            Vector2 dif = lookatTarget.transform.position - transform.position;
            frame.WantDirection = Quaternion.Euler(0, 0, AxMath.SafeAtan2(dif.y, dif.x) * Mathf.Rad2Deg);
        }

        if (decisionTimer > 0f)
        {
            decisionTimer -= Time.deltaTime;
            return;
        }

        decisionTimer = Random.Range(DecisionInterval.x, DecisionInterval.y);

        lookatTarget = null;

        //look at player
        Vector2 distance = transform.position - Camera.main.transform.position;

        if (Mathf.Max(distance.x) > Options.AlertDistance.x || Mathf.Max(distance.y) > Options.AlertDistance.y)
        {
            return;
        }

        Collider2D[] hits = Physics2D.OverlapAreaAll(
            (Vector2)transform.position + Options.AlertDistance,
            (Vector2)transform.position - Options.AlertDistance,
            LayerMask.Walkers);

        foreach (Collider2D hit in hits)
        {
            MonsterCharacter monster = hit.GetComponent <MonsterCharacter>();

            if (monster == null)
            {
                continue;
            }

            if (monster.GetComponent <PlayerControls>() != null)
            {
                lookatTarget = monster;
            }
        }
    }
Пример #7
0
    private void StandAround(ref MonsterCharacter.InputFrame frame)
    {
        if (target != null)
        {
            character.OnInputRequest = Hesitate;
            return;
        }

        Vec2I dif = playerGridPos - thing.gridPos;

        frame.WantDirection = Quaternion.Euler(0, 0, AxMath.SafeAtan2(dif.y, dif.x) * Mathf.Rad2Deg);

        if (decisionTimer > 0f)
        {
            decisionTimer -= Time.deltaTime;
            return;
        }

        decisionTimer = Random.Range(DecisionInterval.x, DecisionInterval.y);

        if (activated)
        {
            if (Vec2I.Manhattan(playerGridPos, thing.gridPos) <= PlayerDistance.x)
            {
                character.OnInputRequest = MoveOut;
                return;
            }

            if (targetRoom >= 0 || targetRoom < Room.Rooms.Length)
            {
                Room room = Room.Rooms[targetRoom];

                if (TheGrid.Valid(playerGridPos) && TheGrid.Valid(thing.gridPos))
                {
                    if (room.steps[playerGridPos.x, playerGridPos.y] < room.steps[thing.gridPos.x, thing.gridPos.y])
                    {
                        character.OnInputRequest = MoveOut;
                        return;
                    }
                }
            }
        }
    }
Пример #8
0
    private void MoveOut(ref MonsterCharacter.InputFrame frame)
    {
        Vector2 dif = TheGrid.WorldPosition(moveTarget) - (Vector2)transform.position;

        if (dif != Vector2.zero)
        {
            dir = dif.normalized;
        }

        frame.up    = dir.y;
        frame.right = dir.x;

        if (LookAtMoveDir)
        {
            lookDir = dir;
        }

        frame.WantDirection = Quaternion.Euler(0, 0, AxMath.SafeAtan2(lookDir.y, lookDir.x) * Mathf.Rad2Deg);

        if (decisionTimer > 0f)
        {
            decisionTimer -= Time.deltaTime;
            return;
        }

        decisionTimer = Random.Range(DecisionInterval.x, DecisionInterval.y);

        LookAtMoveDir = Random.value < LookAtMoveDirChance;

        if (targetRoom < 0 || targetRoom >= Room.Rooms.Length)
        {
            return;
        }

        Room room = Room.Rooms[targetRoom];

        if (!AI.RoomPath(thing.gridPos, room, MaxSteps, out Vec2I[] path))
Пример #9
0
    private void FillInputFrame(ref MonsterCharacter.InputFrame frame)
    {
        frame.up            = dir.y;
        frame.right         = dir.x;
        frame.WantDirection = Quaternion.Euler(0, 0, AxMath.SafeAtan2(dir.y, dir.x) * Mathf.Rad2Deg);

        if (timer > 0f)
        {
            return;
        }

        timer = DecisionTime;
        dir   = Vector2.zero;

        Mouse.UpdateWorldPosition();

        if (Mouse.InWorld)
        {
            if (Mouse.GridPosition != lastMouseGrid)
            {
                Vec2I a = thing.gridPos;
                Vec2I b = Mouse.GridPosition;

                if (AI.GetPath(a, b, Vec2I.Max(a, b), out Vec2I[] path))
Пример #10
0
    private void Hesitate(ref MonsterCharacter.InputFrame frame)
    {
        if (target == null)
        {
            return;
        }

        if (character.CurrentWeapon != null &&
            character.CurrentWeapon.IsReady &&
            Random.value < AggroChance &&
            OnScreen &&
            RayToTarget(character.transform.position))
        //RayToTarget(character.CurrentWeapon.AttackRayStartPosition)) //fails on boss and other multi weapon monsters, also the weapon barrel might be inside wall
        {
            character.OnInputRequest = Attack;
            attackTimer       = AttackTime;
            attacked          = false;
            secondaryAttacked = false;
            return;
        }

        if (decisionTimer > 0f)
        {
            if (LookAtTargetOverride)
            {
                frame.WantDirection = TowardsTarget;
            }

            decisionTimer -= Time.deltaTime;
            return;
        }

        decisionTimer = Random.Range(DecisionInterval.x, DecisionInterval.y);

        LookAtTargetOverride = Random.value < LookAtPlayerChance;

        if (Random.value < IdleChance)
        {
            MovementDecision         = Vector2.zero;
            DirectionDecision        = character.LookDirection;
            character.OnInputRequest = Move;
            return;
        }

        if (Random.value < RandomMoveChance)
        {
            float a = Random.value * Mathf.PI * 2f;

            MovementDecision.x       = Mathf.Cos(a);
            MovementDecision.y       = Mathf.Sin(a);
            DirectionDecision        = character.LookDirection;
            character.OnInputRequest = Move;
            return;
        }

        if ((MovementDecision = (Vector2)SmartMove) != Vector2.zero)
        {
            MovementDecision.Normalize();
            DirectionDecision        = Quaternion.Euler(0, 0, AxMath.SafeAtan2(MovementDecision.y, MovementDecision.x) * Mathf.Rad2Deg);
            character.OnInputRequest = Move;
        }
    }
Пример #11
0
    private void Attack(ref MonsterCharacter.InputFrame frame)
    {
        if (target == null)
        {
            return;
        }

        Vector3 predictedPosition = TargetPredictedPosition(EstimatedBulletSpeed, PredictionMultiplier);

        character.TurnSpeed = AttackTurnSpeedOverride;
        frame.WantDirection = TowardsPosition(predictedPosition);

        attackTimer -= Time.deltaTime;

        if (!attacked &&
            attackTimer < AttackHappenTime &&
            OnScreen &&
            AngleToTarget(predictedPosition) < AttackMaxAngle)
        {
            attacked = true;
            character.CurrentWeapon.PointTowards(predictedPosition);
            frame.PrimaryAttackTrigger = true;
        }

        if (UseOffhand &&
            !secondaryAttacked &&
            attackTimer < SecondaryAttackHappenTime &&
            OnScreen &&
            AngleToTarget(predictedPosition) < AttackMaxAngle)
        {
            secondaryAttacked = true;
            character.CurrentOffhand.PointTowards(predictedPosition);
            frame.SecondaryAttackTrigger = true;
        }

        if (MoveWhileShooting)
        {
            if ((MovementDecision = (Vector2)SmartMove) != Vector2.zero)
            {
                MovementDecision.Normalize();
                frame.up    = MovementDecision.y;
                frame.right = MovementDecision.x;
            }
        }

        if (attackTimer <= 0f)
        {
            if (Random.value < BurstChance)
            {
                if (OnScreen && RayToTarget(character.CurrentWeapon.AttackRayStartPosition))
                {
                    character.OnInputRequest = Attack;
                    attackTimer       = AttackTime;
                    attacked          = false;
                    secondaryAttacked = false;
                    return;
                }
            }
            else
            {
                character.OnInputRequest = Hesitate;
            }
        }
    }
Пример #12
0
    void FillInputFrame(ref MonsterCharacter.InputFrame frame)
    {
        if (HotkeyAssigment.Assigments[(int)Hotkey.Attack1].Pressed)
        {
            frame.PrimaryAttackTrigger = true;
        }
        if (HotkeyAssigment.Assigments[(int)Hotkey.Attack2].Pressed)
        {
            frame.SecondaryAttackTrigger = true;
        }
        if (HotkeyAssigment.Assigments[(int)Hotkey.Attack1].Continuous)
        {
            frame.PrimaryAttackContinuous = true;
        }
        if (HotkeyAssigment.Assigments[(int)Hotkey.Attack2].Continuous)
        {
            frame.SecondaryAttackContinuous = true;
        }

        if (HotkeyAssigment.Assigments[(int)Hotkey.Up].Continuous)
        {
            frame.up += 1f;
        }
        if (HotkeyAssigment.Assigments[(int)Hotkey.Down].Continuous)
        {
            frame.up -= 1f;
        }
        if (HotkeyAssigment.Assigments[(int)Hotkey.Right].Continuous)
        {
            frame.right += 1f;
        }
        if (HotkeyAssigment.Assigments[(int)Hotkey.Left].Continuous)
        {
            frame.right -= 1f;
        }

        if (HotkeyAssigment.Assigments[(int)Hotkey.Use].Pressed)
        {
            frame.UseObject = true;
        }

        if (HotkeyAssigment.Assigments[(int)Hotkey.Map].Pressed)
        {
            Messaging.GUI.PauseCurtain.Invoke();
            Messaging.GUI.OpenWindow.Invoke("UIMap");
            Messaging.System.SetTimeScale.Invoke(TimeScale.Paused);
            Messaging.GUI.ChangeCursor.Invoke(0);
        }

        //pretty hacky, should have proper cascading capture :'(
        if (Input.GetKeyDown(KeyCode.Escape) && !TimeScaler.Paused)
        {
            Messaging.GUI.PauseCurtain.Invoke();
            Messaging.GUI.OpenWindow.Invoke("Ingame Menu");
            Messaging.System.SetTimeScale.Invoke(TimeScale.Paused);
            Messaging.GUI.ChangeCursor.Invoke(0);
        }

        if (HotkeyAssigment.Assigments[(int)Hotkey.Weapon1].Pressed)
        {
            frame.SwapWeapon = 0;
        }
        if (HotkeyAssigment.Assigments[(int)Hotkey.Weapon2].Pressed)
        {
            frame.SwapWeapon = 1;
        }
        if (HotkeyAssigment.Assigments[(int)Hotkey.Weapon3].Pressed)
        {
            frame.SwapWeapon = 2;
        }
        if (HotkeyAssigment.Assigments[(int)Hotkey.Weapon4].Pressed)
        {
            frame.SwapWeapon = 3;
        }
        if (HotkeyAssigment.Assigments[(int)Hotkey.Weapon5].Pressed)
        {
            frame.SwapWeapon = 4;
        }

        if (HotkeyAssigment.Assigments[(int)Hotkey.Skill1].Pressed)
        {
            if (character.Skills.Length > 0 && character.Skills[0] != null)
            {
                character.Skills[0].Activate(character, 0);
            }
        }
        if (HotkeyAssigment.Assigments[(int)Hotkey.Skill2].Pressed)
        {
            if (character.Skills.Length > 1 && character.Skills[1] != null)
            {
                character.Skills[1].Activate(character, 1);
            }
        }
        if (HotkeyAssigment.Assigments[(int)Hotkey.Skill3].Pressed)
        {
            if (character.Skills.Length > 2 && character.Skills[2] != null)
            {
                character.Skills[2].Activate(character, 2);
            }
        }
        if (HotkeyAssigment.Assigments[(int)Hotkey.Skill4].Pressed)
        {
            if (character.Skills.Length > 3 && character.Skills[3] != null)
            {
                character.Skills[3].Activate(character, 3);
            }
        }
        if (HotkeyAssigment.Assigments[(int)Hotkey.Skill5].Pressed)
        {
            if (character.Skills.Length > 4 && character.Skills[4] != null)
            {
                character.Skills[4].Activate(character, 4);
            }
        }

        frame.WantDirection = TowardsMouse;
    }
Пример #13
0
    private void MoveOut(ref MonsterCharacter.InputFrame frame)
    {
        if (target != null)
        {
            character.OnInputRequest = Hesitate;
            return;
        }

        if (PlayerTooFar)
        {
            character.OnInputRequest = StandAround;
        }

        if (moveTarget != Vec2I.illegalMin)
        {
            Vector2 dif = TheGrid.WorldPosition(moveTarget) - (Vector2)transform.position;

            if (dif != Vector2.zero)
            {
                dir = dif.normalized;
            }

            frame.up    = dir.y;
            frame.right = dir.x;

            if (LookAtMoveDir)
            {
                lookDir = dir;
            }

            frame.WantDirection = Quaternion.Euler(0, 0, AxMath.SafeAtan2(lookDir.y, lookDir.x) * Mathf.Rad2Deg);
        }

        if (decisionTimer > 0f)
        {
            decisionTimer -= Time.deltaTime;
            return;
        }

        decisionTimer = Random.Range(DecisionInterval.x, DecisionInterval.y);

        LookAtMoveDir = Random.value < LookAtMoveDirChance;

        if (targetRoom < 0 || targetRoom >= Room.Rooms.Length)
        {
            return;
        }

        Room room = Room.Rooms[targetRoom];

        if (Vec2I.Max(room.gridPos, thing.gridPos) < 3)
        {
            if (MissionObjective == 0)
            {
                Messaging.GUI.CommsMessage.Invoke(0, OnExitMessagePortrait, OnExitMessage);
                MissionObjective++;
                Messaging.Mission.MissionStatus.Invoke(true);
            }

            Instantiate(TeleportEffect, transform.position, Quaternion.identity, LevelLoader.TemporaryObjects);

            Destroy(gameObject);
        }

        if (!AI.RoomPath(thing.gridPos, room, MaxSteps, out Vec2I[] path))
Пример #14
0
    private void OnInputRequest(ref MonsterCharacter.InputFrame frame)
    {
        if (target == null)
        {
            return;
        }

        frame.WantDirection = TowardsTarget;

        if (character.ChargePoints >= MinChargePointsForSkill)
        {
            if (character.Skills.Length > 0)
            {
                if (character.Skills[0] != null)
                {
                    if (character.SkillCooldowns[0] <= 0f)
                    {
                        if (CanSeeTargetGrid)
                        {
                            character.Skills[0].Activate(character, 0);
                        }
                    }
                }
            }
        }

        if (dualSwingTimer > 0f)
        {
            dualSwingTimer -= Time.deltaTime;
        }

        int steps = Vec2I.Max(thing.gridPos, target.thingController.gridPos);

        if (steps <= MaxAttackConsiderationStepCount)
        {
            if (character.CurrentWeapon.IsReady && character.CurrentOffhand.IsReady)
            {
                if (Random.value > .5f)
                {
                    frame.PrimaryAttackContinuous = true;
                }
                else
                {
                    frame.SecondaryAttackContinuous = true;
                }

                dualSwingTimer = DualSwingDelay;
            }
            else if (dualSwingTimer <= 0f)
            {
                frame.PrimaryAttackContinuous   = true;
                frame.SecondaryAttackContinuous = true;
            }
        }

        frame.LocalTransform = false;

        if (chargeTimer > 0f)
        {
            if (AngleToTarget(target.transform.position) > MaxChargeAngle)
            {
                chargeTimer = 0f;
            }

            frame.LocalTransform = true;
            chargeTimer         -= Time.deltaTime;
            frame.up             = 1f;
            character.walkSpeed  = RunSpeed;
            character.TurnSpeed  = RunTurnSpeed;
            return;
        }

        if (chargeCooldownTimer > 0f)
        {
            chargeCooldownTimer -= Time.deltaTime;
        }

        character.walkSpeed = walkSpeed;
        character.TurnSpeed = walkTurnSpeed;

        float distanceSqr = (target.transform.position - transform.position).sqrMagnitude;

        if (steps > StopMovingStepCount)
        {
            if (chargeCooldownTimer <= 0f)
            {
                if (distanceSqr >= StopRange * StopRange && distanceSqr <= RunRange * RunRange)
                {
                    if (AngleToTarget(target.transform.position) <= MaxChargeAngle)
                    {
                        if (CanSeeTargetGrid)
                        {
                            chargeTimer         = ChargeTime;
                            chargeCooldownTimer = ChargeCooldown;
                            return;
                        }
                    }
                }
            }
        }

        if (hesitateTimer > 0f)
        {
            hesitateTimer -= Time.deltaTime;
            return;
        }

        if (Random.value < IdleChance)
        {
            frame.up      = 0;
            frame.right   = 0;
            hesitateTimer = Random.Range(IdleTime.x, IdleTime.y);
            return;
        }

        if (Random.value < RandomMoveChance)
        {
            float a = Random.value * Mathf.PI * 2f;
            frame.right = Mathf.Cos(a);
            frame.up    = Mathf.Sin(a);
            return;
        }

        //path find to target
        {
            Vec2I smart = SmartMove;

            frame.up    = smart.y;
            frame.right = smart.x;
        }
    }