コード例 #1
0
    patrolPath;     //&& smartMonster.timeSinceArrivedAtWaypoint > waypointDwellTime;

    // states //////////////////////////////////////////////////////////////////
    string UpdateServer_IDLE(SmartMonster smartMonster)
    {
        // events sorted by priority (e.g. target doesn't matter if we died)
        if (EventDied(smartMonster))
        {
            // we died.
            return("DEAD");
        }
        if (EventStunned(smartMonster))
        {
            smartMonster.movement.Reset();
            return("STUNNED");
        }
        if (EventTargetDied(smartMonster))
        {
            // we had a target before, but it died now. clear it.
            smartMonster.target = null;
            smartMonster.skills.CancelCast();
            return("IDLE");
        }
        if (EventTargetTooFarToFollow(smartMonster))
        {
            // we had a target before, but it's out of follow range now.
            // clear it and go back to start. don't stay here.
            smartMonster.target = null;
            smartMonster.skills.CancelCast();
            smartMonster.movement.Navigate(smartMonster.startPosition, 0);
            return("MOVING");
        }
        if (EventTargetTooFarToAttack(smartMonster))
        {
            // we had a target before, but it's out of attack range now.
            // follow it. (use collider point(s) to also work with big entities)
            float   stoppingDistance = ((MonsterSkills)smartMonster.skills).CurrentCastRange() * attackToMoveRangeRatio;
            Vector3 destination      = Utils.ClosestPoint(smartMonster.target, smartMonster.transform.position);
            smartMonster.movement.Navigate(destination, stoppingDistance);
            return("MOVING");
        }
        if (EventTargetEnteredSafeZone(smartMonster))
        {
            // if our target entered the safe zone, we need to be really careful
            // to avoid kiting.
            // -> players could pull a smartMonster near a safe zone and then step in
            //    and out of it before/after attacks without ever getting hit by
            //    the smartMonster
            // -> running back to start won't help, can still kit while running
            // -> warping back to start won't help, we might accidentally placed
            //    a smartMonster in attack range of a safe zone
            // -> the 100% secure way is to die and hide it immediately. many
            //    popular MMOs do it the same way to avoid exploits.
            // => call Entity.OnDeath without rewards etc. and hide immediately
            smartMonster.OnDeath();                                                    // no looting
            smartMonster.respawnTimeEnd = NetworkTime.time + smartMonster.respawnTime; // respawn in a while
            return("DEAD");
        }
        if (EventSkillRequest(smartMonster))
        {
            // we had a target in attack range before and trying to cast a skill
            // on it. check self (alive, mana, weapon etc.) and target
            Skill skill = smartMonster.skills.skills[smartMonster.skills.currentSkill];
            if (smartMonster.skills.CastCheckSelf(skill))
            {
                if (smartMonster.skills.CastCheckTarget(skill))
                {
                    // start casting
                    smartMonster.skills.StartCast(skill);
                    return("CASTING");
                }
                else
                {
                    // invalid target. clear the attempted current skill.
                    smartMonster.target = null;
                    smartMonster.skills.currentSkill = -1;
                    return("IDLE");
                }
            }
            else
            {
                // we can't cast this skill at the moment (cooldown/low mana/...)
                // -> clear the attempted current skill, but keep the target to
                // continue later
                smartMonster.skills.currentSkill = -1;
                return("IDLE");
            }
        }
        if (EventAggro(smartMonster))
        {
            // target in attack range. try to cast a first skill on it
            if (smartMonster.skills.skills.Count > 0)
            {
                smartMonster.skills.currentSkill = ((MonsterSkills)smartMonster.skills).NextSkill();
            }
            else
            {
                Debug.LogError(name + " has no skills to attack with.");
            }
            return("IDLE");
        }
        if (EventMoveRandomly(smartMonster))
        {
            // walk to a random position in movement radius (from 'start')
            // note: circle y is 0 because we add it to start.y
            Vector2 circle2D = Random.insideUnitCircle * moveDistance;
            smartMonster.movement.Navigate(smartMonster.startPosition + new Vector3(circle2D.x, 0, circle2D.y), 0);
            return("MOVING");
        }
        if (EventPatrolPath(smartMonster))
        {
            Vector3 currentWaypoint    = smartMonster.patrolPath.GetWaypoint(smartMonster.currentWaypointIndex);
            float   distanceToWaypoint = Vector3.Distance(smartMonster.transform.position, currentWaypoint);
            bool    atWaypoint         = distanceToWaypoint < waypointTolerance;
            if (atWaypoint)
            {
                //smartMonster.SetTimeSinceArrivedAtWaypoint(0);
                smartMonster.CycleWaypoint();
                Vector3 nextPosition = smartMonster.patrolPath.GetWaypoint(smartMonster.currentWaypointIndex);
                smartMonster.movement.Navigate(nextPosition, 0);
                return("MOVING");
            }
            smartMonster.movement.Navigate(currentWaypoint, 0);
            return("MOVING");
        }
        if (EventDeathTimeElapsed(smartMonster))
        {
        }                                            // don't care
        if (EventRespawnTimeElapsed(smartMonster))
        {
        }                                              // don't care
        if (EventMoveEnd(smartMonster))
        {
        }                                   // don't care
        if (EventSkillFinished(smartMonster))
        {
        }                                         // don't care
        if (EventTargetDisappeared(smartMonster))
        {
        }               // don't care

        return("IDLE"); // nothing interesting happened
    }