示例#1
0
    // FixedUpdate is called once per physics frame
    private void FixedUpdate()
    {
        //print(goal);

        if (style.status.slain || style.status.unconscious)
        {
            BecomeSmall();
            pointTargetFrames = 0;
            attackFrames      = 0;
            evadeFrames       = 0;
            guardFrames       = 0;
            if (navMesh.enabled)
            {
                navMesh.isStopped = true;
            }
            navMesh.enabled = false;
            goal            = GoalStates.nothing;
        }

        if (big && style.stat.MP < 10)
        {
            BecomeSmall();
        }

        if (goalDelay > 0)
        {
            goalDelay--;
        }

        if (pointTargetFrames > 0)
        {
            pointTargetFrames--;
            movementAI.PointTowardTarget(45);
        }

        if (attackFrames > 0)
        {
            attackFrames--;
            if (navMesh.enabled)
            {
                navMesh.isStopped = true;
            }
            navMesh.enabled = false;
            if (movementAI.toTargetAngle < 10f && movementAI.toTargetAngle > -10f && attackFrames > 2)
            {
                attackFrames = 2;
            }
        }

        if (evadeFrames > 0 && style.status.CanMove())
        {
            evadeFrames--;
            if (navMesh.enabled)
            {
                navMesh.isStopped = true;
            }
            navMesh.enabled = false;
        }

        if (guardFrames > 0)
        {
            guardFrames--;
            if (navMesh.enabled)
            {
                navMesh.isStopped = true;
            }
            navMesh.enabled = false;
        }

        behaviourCounter--;
        goalCounter--;

        if (big)
        {
            bigAnimator.SetBool("curious", false);
        }
        smallAnimator.SetBool("curious", false);

        if (behaviour == BehaviourStates.defeated && !(style.status.slain || style.status.unconscious))
        {
            if (big)
            {
                BecomeSmall();
            }
            style.status.guarding = false;
            navMesh.speed         = maxSpeed * 0.2f;
            ChangeGoal(GoalStates.retreat);
            navMesh.enabled   = true;
            navMesh.isStopped = false;
            goalComplete      = false;
            goalStarted       = false;
            if (Vector3.Distance(transform.position, target.transform.position) > 20 && targetStatus.sheathed && !targetStatus.casting)
            {
                pacifiedCounter--;
                ChangeGoal(GoalStates.nothing);
                if (big)
                {
                    bigAnimator.SetBool("curious", true);
                }
                smallAnimator.SetBool("curious", true);
                if (navMesh.enabled)
                {
                    navMesh.isStopped = true;
                }
                navMesh.enabled = false;
                movementAI.PointTowardTarget(4);
            }
            if ((Vector3.Distance(transform.position, target.transform.position) < 5 || !targetStatus.sheathed || targetStatus.casting) && pacifiedCounter < 600)
            {
                pacifiedCounter++;
            }
            if (pacifiedCounter <= 0)
            {
                ChangeBehaviour(BehaviourStates.pacified);
            }
        }

        if (behaviour == BehaviourStates.pacified && !(style.status.slain || style.status.unconscious))
        {
            if (big)
            {
                BecomeSmall();
            }
            gameObject.tag        = "TgtAlyBosIns";
            style.status.guarding = false;
            //navMesh.speed = maxSpeed * 0.2f;
            target            = stump;
            movementAI.target = target;
            if (!castSanctuary)
            {
                source.PlayOneShot(howlClipLong, Random.Range(0.4f, 0.6f));
                currentSpell                    = Instantiate(healingSanctuary).GetComponent <Spell>();
                currentSpell.duration           = 14400; //the Shamanwolf's healing sanctuary is longer, lasting 4 minutes
                currentSpell.mouseTarget        = false;
                currentSpell.target             = target;
                currentSpell.status             = style.status;
                currentSpell.stat               = style.stat;
                currentSpell.movement           = style.movement;
                currentSpell.animator           = style.animator;
                currentSpell.transform.position = transform.position;
                currentSpell.transform.rotation = transform.rotation;
                currentSpell.active             = true;
                currentSpell.ready              = 0;
                currentSpell.Start();
                currentSpell.castTime   += currentSpell.spellCode.Length * 15;
                currentSpell.duration    = 14400; //the Shamanwolf's healing sanctuary is longer, lasting 4 minutes
                style.status.castLock    = currentSpell.castTime + currentSpell.postCastTime;
                style.status.channelLock = currentSpell.castTime + currentSpell.postCastTime + currentSpell.channelTime;
                runningSpells.Add(currentSpell.gameObject);
                style.ForceSpellcast(currentSpell.castTime + currentSpell.postCastTime + 5); //set the spellcast state for a while
                castSanctuary = true;
            }
            else
            {
                if (Vector3.Distance(transform.position, target.transform.position) > 6)
                {
                    navMesh.enabled   = true;
                    navMesh.isStopped = false;
                    goal         = GoalStates.approach;
                    goalComplete = false;
                    goalStarted  = false;
                }
                else
                {
                    if (navMesh.enabled)
                    {
                        navMesh.isStopped = true;
                    }
                    navMesh.enabled = false;
                    goal            = GoalStates.nothing;
                    if (big)
                    {
                        bigAnimator.SetBool("pacified", true);
                    }
                    smallAnimator.SetBool("pacified", true);
                    //have a bit of a lie down
                }
            }
        }
        else
        {
            castSanctuary = false;
        }

        if (style.status.IsFloored() && !(style.status.slain || style.status.unconscious))
        {
            ChangeGoal(GoalStates.evade);
            goalStarted = false;
            //goalDelay = Random.Range(0, 120);
        }

        if (big)
        {
            bigCounter--;
            style.stat.MP -= (style.stat.MPregen + 10) / 60;
            if ((bigCounter <= 0 || style.stat.MP <= 0) && goalStarted == false)
            {
                BecomeSmall();
            }
        }

        if (style.stat.HP < 80 && behaviour != BehaviourStates.pacified)
        {
            ChangeBehaviour(BehaviourStates.defeated);
        }

        if (behaviour == BehaviourStates.preBattle && (Vector3.Distance(transform.position, target.transform.position) < 32 || style.stat.HP < style.stat.MaxHP))
        {
            ChangeBehaviour();
            ChangeGoal();
        }

        if (targetStatus.unconscious || targetStatus.slain)
        {
            ChangeBehaviour(BehaviourStates.pacified);
        }

        if (behaviour != BehaviourStates.defeated && behaviour != BehaviourStates.pacified && behaviour != BehaviourStates.preBattle && !(style.status.slain || style.status.unconscious))
        {
            if (behaviourCounter <= 0)   //behaviour changes every 30 seconds
            {
                CalculateBehaviourPref();
                ChangeBehaviour();
                behaviourCounter = 1800;
            }

            if ((goalCounter <= 0 || goalComplete) && goalDelay <= 0)   //goals change every 10 seconds or every time a goal is completed
            {
                if (navMesh.enabled)
                {
                    navMesh.isStopped = true;
                }
                navMesh.enabled = false;
                CalculateGoalPref();
                ChangeGoal();
                goalCounter  = 600;
                goalComplete = false;
                goalStarted  = false;
            }
        }

        if ((!goalStarted) && goalDelay <= 0)
        {
            switch (goal)
            {
            case GoalStates.attack:
                if (style.status.CanMove())
                {
                    if (big)
                    {
                        bigAnimator.Play("turn", 0, 0f);
                    }
                    smallAnimator.Play("turn", 0, 0f);
                }
                attackFrames = 40;
                goalStarted  = true;
                break;

            case GoalStates.cast:
                if (style.status.CanCast())
                {
                    source.PlayOneShot(howlClipShort, Random.Range(0.4f, 0.6f));
                    goalStarted = true;
                    goalDelay   = 40;
                }
                break;

            case GoalStates.big:
                if (style.status.CanCast())
                {
                    source.PlayOneShot(howlClipShort, Random.Range(0.4f, 0.6f));
                    goalStarted = true;
                    BecomeBig();
                    bigCounter = Random.Range(10 * 60, 30 * 60); //become big for anywhere between 10 and 30 seconds
                    goalDelay  = 120;
                }
                break;

            case GoalStates.approach:
                if (style.status.CanMove())
                {
                    navMesh.enabled   = true;
                    navMesh.isStopped = false;
                    navMesh.SetDestination(target.transform.position);
                    navMesh.SetDestination(new Vector3(navMesh.destination.x, 0, navMesh.destination.z));     //get rid of y
                    goalStarted = true;
                }
                break;

            case GoalStates.retreat:
                if (style.status.CanMove())
                {
                    navMesh.enabled   = true;
                    navMesh.isStopped = false;
                    retreatDist       = Random.Range(Vector3.Distance(transform.position, target.transform.position), 28f);
                    navMesh.SetDestination(transform.position + Vector3.Normalize(transform.position - target.transform.position) * retreatDist);
                    navMesh.SetDestination(new Vector3(navMesh.destination.x, 0, navMesh.destination.z));     //get rid of y
                    goalStarted = true;
                }
                break;

            case GoalStates.evade:
                if (style.status.CanMove())
                {
                    if (big)
                    {
                        bigAnimator.Play("turn", 0, 0f);
                    }
                    smallAnimator.Play("turn", 0, 0f);
                }
                evadeFrames = 15;
                goalStarted = true;
                break;

            case GoalStates.guard:
                guardFrames = Random.Range(60, 180);     //guard for between 1 and 2.5 seconds
                goalStarted = true;
                break;

            case GoalStates.parry:
                if (style.status.CanParry())
                {
                    movementAI.PointTowardTarget(60);
                    decider = Random.Range(0, 2);
                    if (decider > 1)
                    {
                        style.FParry();
                    }
                    else
                    {
                        style.BParry();
                    }
                    goalStarted = true;
                }
                break;
            }
        }

        if (goalStarted && !goalComplete)
        {
            switch (goal)
            {
            case GoalStates.attack:
                if (attackFrames > 1)
                {
                    movementAI.PointTowardTarget(12);
                }
                else
                {
                    if (attackFrames > 0)
                    {
                        if (style.status.CanAttack())
                        {
                            CalculateAttackPref();
                            Attack();
                        }
                    }
                    if (style.instantiatedAttacks.Count <= 0)
                    {
                        goalComplete = true;     //once the boss has attacked, the goal is complete
                    }
                }
                break;

            case GoalStates.cast:
                chosenSpellNumber = Random.Range(0, spellsKnown.Count - 1);
                if (style.status.CanCast() && style.status.castLock <= 0 && !style.status.casting)
                {
                    style.status.casting = true;
                }
                if (style.status.casting && style.status.channelLock <= 0)
                {
                    style.ForceSpellcast(1);
                    currentSpellName = spellsKnown[chosenSpellNumber].GetComponent <Spell>().spellName;
                    repeatSpell      = false;
                    for (int i2 = 0; i2 < runningSpells.Count; i2++)
                    {
                        if (currentSpellName == runningSpells[i2].GetComponent <Spell>().spellName)
                        {
                            repeatSpell = true;
                        }
                    }
                    if (!repeatSpell)
                    {
                        currentSpell                    = Instantiate(spellsKnown[chosenSpellNumber]).GetComponent <Spell>();
                        currentSpell.mouseTarget        = false;
                        currentSpell.target             = target;
                        currentSpell.status             = style.status;
                        currentSpell.stat               = style.stat;
                        currentSpell.movement           = style.movement;
                        currentSpell.animator           = style.animator;
                        currentSpell.transform.position = transform.position;
                        currentSpell.transform.rotation = transform.rotation;
                        currentSpell.active             = true;
                        currentSpell.ready              = 0;
                        currentSpell.Start();
                        currentSpell.castTime   += currentSpell.spellCode.Length * 15;
                        style.status.castLock    = currentSpell.castTime + currentSpell.postCastTime;
                        style.status.channelLock = currentSpell.castTime + currentSpell.postCastTime + currentSpell.channelTime;
                        runningSpells.Add(currentSpell.gameObject);
                        style.ForceSpellcast(currentSpell.castTime + currentSpell.postCastTime + 5);     //set the spellcast state for a while
                    }
                }
                if (style.status.castLock > 0)
                {
                    goalComplete         = true;
                    style.status.casting = false;
                }
                break;

            case GoalStates.big:
                if (big)
                {
                    goalComplete = true;     //becoming big happens instantaneously so the goal is completed
                }
                break;

            case GoalStates.approach:
                if (style.status.CanMove())
                {
                    navMesh.enabled   = true;
                    navMesh.isStopped = false;
                }
                else
                {
                    if (navMesh.enabled)
                    {
                        navMesh.isStopped = true;
                    }
                    navMesh.enabled = false;
                }
                if ((big && Vector3.Distance(transform.position, target.transform.position) < 8) || (!big && Vector3.Distance(transform.position, target.transform.position) < 4) || Vector3.Distance(transform.position, navMesh.destination) < 4)
                {
                    if (navMesh.enabled)
                    {
                        navMesh.isStopped = true;
                    }
                    navMesh.enabled = false;
                    goalComplete    = true;                                                                                     //if the target is more-or-less reached, goal complete
                }
                else if (goalCounter < 180 || navMesh.isPathStale /* || navMesh.pathStatus != NavMeshPathStatus.PathComplete*/) //this goal can potentially be recognised as a failure, in which case try to salvage
                {
                    print("abortApproach");
                    if (navMesh.enabled)
                    {
                        navMesh.isStopped = true;
                    }
                    navMesh.enabled = false;
                    goalStarted     = false;
                    CalculateGoalPref();
                    approachPref = 0;     //welp, messed up last time
                    retreatPref  = 10;    //prolly don't want to retreat that much
                    ChangeGoal();
                    goalCounter = 600;
                }
                break;

            case GoalStates.retreat:
                if (style.status.CanMove())
                {
                    navMesh.enabled   = true;
                    navMesh.isStopped = false;
                }
                else
                {
                    if (navMesh.enabled)
                    {
                        navMesh.isStopped = true;
                    }
                    navMesh.enabled = false;
                }
                if (Vector3.Distance(transform.position, target.transform.position) > 25 || Vector3.Distance(transform.position, navMesh.destination) < 4)
                {
                    print("distReached");
                    if (navMesh.enabled)
                    {
                        navMesh.isStopped = true;
                    }
                    navMesh.enabled = false;
                    goalComplete    = true;                                                                                //similar to approach but the wolf has to be far away
                }
                else if (goalCounter < 150 || navMesh.isPathStale || navMesh.pathStatus != NavMeshPathStatus.PathComplete) //this goal can potentially be recognised as a failure, in which case try to salvage
                {
                    print("abortRetreat");
                    if (navMesh.enabled)
                    {
                        navMesh.isStopped = true;
                    }
                    navMesh.enabled = false;
                    CalculateGoalPref();
                    if (!big)
                    {
                        bigPref += 50; //big chance of going big if not big
                    }
                    castPref     = 1;  //very low chance of casting
                    approachPref = 10; //why approach when you can't even get away?
                    retreatPref  = 10; //why retreat when you already know you can't? Might have just messed up on distance so fair
                    guardPref   += 20; //prefer guard
                    evadePref    = 10; //low chance of evading since that's often backwards
                    ChangeGoal();
                    goalCounter = 600;
                    goalStarted = false;
                }
                break;

            case GoalStates.evade:
                if (evadeFrames > 0 && style.status.CanMove())
                {
                    movementAI.PointAwayFromTarget(Random.Range(3, 5));
                }
                else
                {
                    if (style.status.CanRoll())
                    {
                        style.movement.Evade(evadeSpeed, 0, 0.5f);
                        if (big)
                        {
                            bigAnimator.Play("jump", 0, 0f);
                        }
                        smallAnimator.Play("jump", 0, 0f);
                        goalDelay    = 45;
                        goalComplete = true;     //evade complete
                    }
                }
                break;

            case GoalStates.guard:
                if (guardFrames <= 0)
                {
                    goalComplete          = true;
                    style.status.guarding = false;
                }
                else
                {
                    if (style.status.CanGuard())
                    {
                        style.status.guarding = true;
                        if (!style.status.IsGuardStunned())
                        {
                            movementAI.PointTowardTarget(3);
                        }
                    }
                    else
                    {
                        style.status.guarding = false;
                    }
                }
                break;

            case GoalStates.parry:
                goalComplete = true;     //parry happens instantaneously so it autocompletes
                break;
            }
        }

        if (navMesh.enabled)
        {
            if (!source.isPlaying)
            {
                source.Play();
            }
            source.loop = true;
            if (behaviour == BehaviourStates.defeated)
            {
                source.clip = whimperClip;
            }
            else
            {
                source.clip = moveClip;
            }
        }
        else
        {
            source.clip = null;
            source.loop = false;
        }

        if (!style.status.CanGuard())
        {
            style.status.guarding = false;
        }

        if (big)
        {
            guardBubbleS.material.color = new Color(guardBubbleS.material.color.r, guardBubbleS.material.color.g, guardBubbleS.material.color.b, 0f);
            parryBubbleS.material.color = new Color(parryBubbleS.material.color.r, parryBubbleS.material.color.g, parryBubbleS.material.color.b, 0f);
        }
        else
        {
            guardBubbleL.material.color = new Color(guardBubbleL.material.color.r, guardBubbleL.material.color.g, guardBubbleL.material.color.b, 0f);
            parryBubbleL.material.color = new Color(parryBubbleL.material.color.r, parryBubbleL.material.color.g, parryBubbleL.material.color.b, 0f);
        }

        if ((!style.status.CanMove()))
        {
            if (navMesh.enabled)
            {
                navMesh.isStopped = true;
            }
            navMesh.enabled = false;
        }

        if (style.status.casting || style.status.channelLock > 0)
        {
            if (big)
            {
                bigAnimator.SetBool("trueCasting", true);
            }
            smallAnimator.SetBool("trueCasting", true);
            if (navMesh.enabled)
            {
                navMesh.isStopped = true;
            }
            navMesh.enabled = false;
            movementAI.PointTowardTarget(30); //point to the target while casting
        }
        else
        {
            if (big)
            {
                bigAnimator.SetBool("trueCasting", false);
            }
            smallAnimator.SetBool("trueCasting", false);
        }
        if (style.status.spellFlinchTrigger)
        {
            StopCasting();
            style.status.spellFlinchTrigger = false;
        }


        for (int i = 0; i < runningSpells.Count; i++)
        {
            runningSpellScript = runningSpells[i].GetComponent <Spell>();
            runningSpellScript.castTime--;
            if (runningSpellScript.castTime <= 0 && runningSpellScript.ready == 0)
            {
                runningSpellScript.ready = 1;
                if (!runningSpellScript.costDeducted)
                {
                    style.stat.MP -= runningSpellScript.cost;
                    runningSpellScript.costDeducted = true;
                }
            }
            if (runningSpellScript.castTime <= 0 && runningSpellScript.postCastTime > 0)
            {
                runningSpellScript.postCastTime--;
            }
            if (runningSpellScript.castTime <= 0 && runningSpellScript.postCastTime <= 0 && runningSpellScript.channelTime > 0)
            {
                runningSpellScript.channelTime--;
            }
            if (runningSpellScript.castTime <= 0 && runningSpellScript.postCastTime <= 0 && runningSpellScript.channelTime <= 0)
            {
                runningSpellScript.duration--;
            }
            if (runningSpellScript.duration <= 0)
            {
                toDestroy = runningSpells[i];
                runningSpells.Remove(runningSpells[i]);
                toDestroy.GetComponent <Spell>().DestroySpell();
            }
            else if (runningSpellScript.ready == 1)
            {
                runningSpellScript.CastSpell();
            }
        }
    }