Example #1
0
    protected virtual void Update()
    {
        if (this.copycat)
        {
            renderer.color = new Color(1f, 134f / 255, 97f / 255);
        }
        if (this.state == State.IN_VOID)
        {
            Destroy(this.gameObject);
        }
        if (this.state == State.SENDING_TO_VOID)
        {
            this.MoveToVoidWaypoint(true);
            if (this.IsAtVoidWaypoint())
            {
                this.state = State.IN_VOID;
                this.audioSource.PlayOneShot(this.spawnSound);
            }
            return;
        }
        if (this.state == State.IN_VOID)
        {
            this.ReturnOrbs();
            this.renderer.enabled = false;
        }
        if (this.state == State.SPAWNING_FROM_VOID)
        {
            this.MoveToVoidWaypoint(false);
            if (this.IsAtVoidWaypoint())
            {
                this.state                = State.WANDER;
                this.item.state           = Item.State.ON_GROUND;
                this.transform.localScale = new Vector3(1f, 1f, 1f);
                this.audioSource.PlayOneShot(this.spawnSound);
            }
            return;
        }

        if (this.item.state == Item.State.PICKED_UP && !this.ShouldBeDropped())
        {
            this.main.DropItem();
            return;
        }

        if (this.item.state != Item.State.ON_GROUND)
        {
            return;
        }
        if (this.state == State.WANDER)
        {
            // Sound.
            this.ambientSoundTimer -= Time.deltaTime;
            if (this.ambientSoundTimer < 0f)
            {
                this.ambientSoundTimer = Random.Range(8f, 14f);
                this.PlayAmbientSound();
            }
            // Actions.
            Vector2 displacement = this.waypoint - (Vector2)this.transform.position;
            if (displacement.magnitude > 0.1)
            {
                // Move towards waypoint, avoiding the other monster.
                this.Accel(this.accel * displacement.normalized);
                if (this.avoid != null)
                {
                    Vector2 avoidDisplacement = this.avoid.transform.position - this.transform.position;
                    if (avoidDisplacement.magnitude < this.fleeRadius)
                    {
                        this.Accel(-this.accel * avoidDisplacement.normalized);
                    }
                }
            }
            else
            {
                // Choose a new waypoint.
                if (Random.value > (1 - Time.deltaTime / this.averageWaitTime))
                {
                    this.waypoint = this.ChooseWaypoint(this.pen);
                }
            }
            // Transitions.
            foreach (Monster monster in FindObjectsOfType <Monster>())
            {
                if (monster == this || this.state != State.WANDER || !monster.Initialized() || monster.state != State.WANDER || monster.item.state != Item.State.ON_GROUND)
                {
                    continue;
                }
                Vector2 monsterDisplacement = monster.transform.position - this.transform.position;
                // Can only interact with monsters smaller than threaten radius.
                if (monsterDisplacement.magnitude < this.threatenRadius)
                {
                    State choice        = this.ChooseThreatenOffensive(monster);
                    State monsterChoice = monster.ChooseThreatenOffensive(this);
                    if (choice == State.THREATEN || choice == State.LURE)
                    {
                        monsterChoice = monster.ChooseThreatenDefensive(this);
                    }
                    if (monsterChoice == State.THREATEN || monsterChoice == State.LURE)
                    {
                        choice = this.ChooseThreatenDefensive(monster);
                    }
                    bool isThreaten = (choice == State.THREATEN || monsterChoice == State.THREATEN);
                    bool isLure     = (choice == State.LURE || monsterChoice == State.LURE);
                    if (!isLure)
                    {
                        if (choice == State.FLEE)
                        {
                            this.state  = State.FLEE;
                            this.target = monster;
                            this.audioSource.Stop();
                            this.audioSource.PlayOneShot(this.fleeSound, 0.75f);
                        }
                        if (monsterChoice == State.FLEE)
                        {
                            monster.state  = State.FLEE;
                            monster.target = this;
                            monster.audioSource.Stop();
                            monster.audioSource.PlayOneShot(monster.fleeSound, 0.75f);
                        }
                        if (choice == State.THREATEN)
                        {
                            this.state      = State.THREATEN;
                            this.stateTimer = this.threatenTime;
                            this.target     = monster;
                            monster.Avoid(this);
                            this.Avoid(monster);
                            this.audioSource.Stop();
                            this.audioSource.PlayOneShot(this.threatenSound, 0.75f);
                        }
                        if (monsterChoice == State.THREATEN)
                        {
                            monster.state      = State.THREATEN;
                            monster.stateTimer = monster.threatenTime;
                            monster.target     = this;
                            this.Avoid(monster);
                            monster.Avoid(this);
                            monster.audioSource.Stop();
                            monster.audioSource.PlayOneShot(monster.threatenSound, 0.75f);
                        }
                        if (isThreaten)
                        {
                            if (choice == State.IGNORE)
                            {
                                this.state  = State.IGNORE;
                                this.target = monster;
                            }
                            if (monsterChoice == State.IGNORE)
                            {
                                monster.state  = State.IGNORE;
                                monster.target = this;
                            }
                        }
                    }
                    else
                    {
                        if (choice == State.LURE)
                        {
                            this.state     = State.LURE;
                            monster.state  = State.MESMERIZED;
                            this.target    = monster;
                            monster.target = this;
                            this.audioSource.Stop();
                            monster.audioSource.Stop();
                            this.audioSource.PlayOneShot(this.lureSound, 0.75f);
                        }
                        if (monsterChoice == State.LURE)
                        {
                            this.state     = State.MESMERIZED;
                            monster.state  = State.LURE;
                            this.target    = monster;
                            monster.target = this;
                            this.audioSource.Stop();
                            monster.audioSource.Stop();
                            monster.audioSource.PlayOneShot(monster.lureSound, 0.75f);
                        }
                    }
                }
            }
        }
        else if (this.state == State.IGNORE)
        {
            Monster monster      = this.target;
            Vector2 displacement = this.waypoint - (Vector2)this.transform.position;
            if (displacement.magnitude > 0.1)
            {
                // Move towards waypoint.
                this.Accel(this.accel * displacement.normalized);
            }
            else
            {
                // Choose a new waypoint.
                if (Random.value > (1 - Time.deltaTime / this.averageWaitTime))
                {
                    this.waypoint = this.ChooseWaypoint(this.pen);
                }
            }
        }
        else if (this.state == State.THREATEN)
        {
            if (this.stateTimer < 0f)
            {
                Monster monster  = this.target;
                float   distance = ((Vector2)monster.transform.position - (Vector2)this.transform.position).magnitude;
                if (monster.state != State.FLEE)
                {
                    this.state = State.PRE_FIGHT;
                }
                if (distance > this.fleeRadius && distance > monster.fleeRadius)
                {
                    this.state = State.WANDER;
                }
            }
        }
        else if (this.state == State.PRE_FIGHT)
        {
            Monster monster      = this.target;
            Vector2 displacement = monster.transform.position - this.transform.position;
            if (displacement.magnitude > 0.1)
            {
                this.Accel(this.accel * displacement.normalized);
            }
            else
            {
                this.state         = State.FIGHT;
                this.stateTimer    = Monster.FIGHT_TIME;
                monster.state      = State.FIGHT;
                monster.stateTimer = Monster.FIGHT_TIME;

                // Make fight cloud.
                GameObject fightCloudObj = Instantiate(PrefabManager.FIGHT_CLOUD_PREFAB, this.transform.position, Quaternion.identity);
                this.fightCloud          = fightCloudObj.GetComponent <FightCloud>();
                monster.fightCloud       = this.fightCloud;
                this.fightCloud.fighter1 = this;
                this.fightCloud.fighter2 = monster;
                this.fightNoiseTimer     = 0.2f;
                monster.fightNoiseTimer  = float.PositiveInfinity;
            }
        }
        else if (state == State.FIGHT)
        {
            this.fightNoiseTimer -= Time.deltaTime;
            if (this.fightNoiseTimer < 0f)
            {
                this.fightNoiseTimer   = Random.Range(0.3f, 0.5f);
                this.audioSource.pitch = Random.Range(0.9f, 1.1f);
                this.audioSource.PlayOneShot(this.fightSound, 0.3f);
            }
            Monster monster = this.target;
            this.velocity = Vector2.zero;
            if (Random.value > 1 - Time.deltaTime / 0.2f)
            {
                this.transform.rotation *= Quaternion.Euler(0f, 0f, Random.Range(0, 360f));
            }
            if (this.stateTimer < 0f)
            {
                this.transform.rotation    = Quaternion.identity;
                monster.transform.rotation = Quaternion.identity;
                // Destroy fight cloud.
                Destroy(this.fightCloud.gameObject);
                this.fightCloud = null;
                // Give velocities.
                monster.Shove(new Vector2(
                                  Random.Range(0.4f, 0.6f),
                                  Random.Range(-0.1f, 0.1f)));
                this.Shove(new Vector2(
                               Random.Range(-0.6f, -0.4f),
                               Random.Range(-0.1f, 0.1f)));
                // Burn
                if (this.IsFiery())
                {
                    monster.Enflame();
                }
                if (monster.IsFiery())
                {
                    this.Enflame();
                }
                if (this.KillOpponent(monster))
                {
                    monster.state      = State.DYING;
                    monster.stateTimer = Monster.DYING_TIME;
                    monster.OnDying();
                    monster.target            = null;
                    monster.audioSource.pitch = 1f;
                    monster.audioSource.Stop();
                    monster.audioSource.PlayOneShot(monster.deathSound, 0.6f);
                }
                else
                {
                    monster.state             = State.POST_FIGHT;
                    monster.stateTimer        = Monster.POST_FIGHT_TIME;
                    monster.audioSource.pitch = 1f;
                }
                if (monster.KillOpponent(this))
                {
                    this.state      = State.DYING;
                    this.stateTimer = Monster.DYING_TIME;
                    this.OnDying();
                    this.target            = null;
                    this.audioSource.pitch = 1f;
                    this.audioSource.Stop();
                    this.audioSource.PlayOneShot(this.deathSound, 0.6f);
                }
                else
                {
                    this.state             = State.POST_FIGHT;
                    this.stateTimer        = Monster.POST_FIGHT_TIME;
                    this.audioSource.pitch = 1f;
                }
            }
        }
        else if (this.state == State.POST_FIGHT)
        {
            Monster monster      = this.target;
            Vector2 displacement = monster.transform.position - this.transform.position;
            if (this.stateTimer < 0f)
            {
                bool farEnough   = (displacement.magnitude > this.fleeRadius && displacement.magnitude > monster.fleeRadius);
                bool monsterDead = (monster.state == State.DEAD || monster.state == State.DYING);
                if (farEnough || monsterDead)
                {
                    this.state    = State.WANDER;
                    this.waypoint = this.ChooseWaypoint(this.pen);
                }
            }
            else
            {
                if (displacement.magnitude == 0f)
                {
                    float angle = 2 * Mathf.PI * Random.value;
                    displacement = 0.1f * new Vector2(Mathf.Cos(angle), Mathf.Sin(angle));
                }
                this.Accel(-this.accel * displacement.normalized);
            }
        }
        else if (this.state == State.LURE)
        {
            Monster monster  = this.target;
            float   distance = ((Vector2)monster.transform.position - (Vector2)this.transform.position).magnitude;
            if (distance < 0.5f)
            {
                this.state         = State.DEVOURING;
                monster.state      = State.BEING_DEVOURED;
                this.stateTimer    = Monster.DEVOUR_TIME;
                monster.stateTimer = Monster.DEVOUR_TIME;
            }
        }
        else if (this.state == State.MESMERIZED)
        {
            Monster monster      = this.target;
            Vector2 displacement = monster.transform.position - this.transform.position;
            if (displacement.magnitude == 0f)
            {
                float angle = 2 * Mathf.PI * Random.value;
                displacement = 0.1f * new Vector2(Mathf.Cos(angle), Mathf.Sin(angle));
            }
            this.Accel(this.accel * displacement.normalized);
        }
        else if (this.state == State.DEVOURING)
        {
            Monster monster = this.target;
            if (this.stateTimer < 0f)
            {
                this.state      = State.DIGESTING;
                this.stateTimer = Monster.DIGEST_TIME;
                monster.gameObject.SetActive(false);
            }
        }
        else if (this.state == State.BEING_DEVOURED)
        {
            Monster monster       = this.target;
            float   scale         = this.stateTimer / Monster.DEVOUR_TIME;
            Vector2 mouthPosition = monster.transform.position;
            Vector2 displacement  = mouthPosition - (Vector2)this.transform.position;
            if (displacement.magnitude == 0f)
            {
                float angle = 2 * Mathf.PI * Random.value;
                displacement = 0.1f * new Vector2(Mathf.Cos(angle), Mathf.Sin(angle));
            }
            this.velocity             = Vector2.zero;
            this.transform.position   = mouthPosition - displacement * scale;
            this.transform.localScale = new Vector3((scale + 0.2f) / 1.2f, (scale + 0.2f) / 1.2f, 1f);
        }
        else if (this.state == State.DIGESTING)
        {
            Monster monster = this.target;
            if (this.stateTimer < 0f)
            {
                this.state     = State.WANDER;
                this.target    = null;
                monster.target = null;
                monster.gameObject.SetActive(true);
                monster.transform.localScale = new Vector3(1f, 1f, 1f);
                if (this.KillDigestedOpponent(monster))
                {
                    for (int i = 0; i < monster.orbs.Length; i++)
                    {
                        monster.orbs[i].item.transform.position = this.transform.position;
                        monster.orbs[i].item.ReturnToLab();
                    }
                    Destroy(monster.gameObject);
                }
                else
                {
                    monster.state      = State.GOOED;
                    monster.stateTimer = Monster.GOO_TIME;
                    monster.Extinguish();
                    if (monster.IsFireElemental())
                    {
                        monster.OnDying();
                    }
                    GameObject ectoplasmObj = Instantiate(PrefabManager.ECTOPLASM_PREFAB, monster.transform);
                    ectoplasmObj.transform.localPosition = new Vector3(0f, -0.01f, 0f);
                    float angle = 2f * Mathf.PI * Random.value;
                    monster.Shove(Random.Range(0.2f, 0.3f) * new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)));
                }
            }
        }
        else if (this.state == State.GOOED)
        {
            if (this.stateTimer < 0f)
            {
                if (this.IsFireElemental())
                {
                    this.state = State.DEAD;
                }
                else
                {
                    this.state = State.WANDER;
                }
            }
        }
        else if (this.state == State.FLEE)
        {
            Monster monster      = this.target;
            Vector2 displacement = monster.transform.position - this.transform.position;
            if (displacement.magnitude == 0f)
            {
                float angle = 2 * Mathf.PI * Random.value;
                displacement = 0.1f * new Vector2(Mathf.Cos(angle), Mathf.Sin(angle));
            }
            this.Accel(-this.accel * displacement.normalized);
            if (displacement.magnitude > this.fleeRadius && displacement.magnitude > monster.fleeRadius)
            {
                this.state = State.WANDER;
                if (monster.state == State.THREATEN || monster.state == State.FLEE)
                {
                    monster.state = State.WANDER;
                }
            }
        }
        else if (this.state == State.DYING)
        {
            if (this.stateTimer < 0f)
            {
                this.state    = State.DEAD;
                this.deadTime = Time.realtimeSinceStartup;
                if (this.IsExplosive())
                {
                    Instantiate(PrefabManager.EXPLOSION_PREFAB, this.transform.position, Quaternion.identity);
                }
            }
        }
        else if (this.state == State.DEAD)
        {
            if (Time.realtimeSinceStartup - this.deadTime > this.deadWaitTime)
            {
                if (this.voido != null)
                {
                    this.voido.SendToVoid(this);
                }
            }
        }
        else if (this.state == State.TRAVEL_TO_TRANSFORM_ORB)
        {
            if (this.transformOrb == null)
            {
                this.state = State.WANDER;
            }
            else
            {
                Vector2 displacement = this.transformOrb.transform.position - this.transform.position;
                if (displacement.magnitude > 0.5f)
                {
                    this.Accel(this.accel * displacement.normalized);
                }
                else
                {
                    this.state = State.TRANSFORM_ORB;
                    this.transformOrbStartTime = Time.realtimeSinceStartup;
                }
            }
        }
        else if (this.state == State.TRANSFORM_ORB)
        {
            float delta = Time.realtimeSinceStartup - this.transformOrbStartTime;
            if (delta < this.transformOrbTotalTime)
            {
                float scale = Mathf.Abs((delta / this.transformOrbTotalTime) - 1);
                this.transformOrb.transform.localScale = new Vector3(scale, scale, 1f);
                Vector2 displacement = this.transformOrb.transform.position - this.transform.position;
                if (displacement.magnitude > 0.01f)
                {
                    this.transformOrb.transform.position -= (Vector3)displacement * Time.deltaTime / (delta + 0.01f);
                }
                //this.transform.localScale = new Vector3(scale, scale, 1f);
            }
            else
            {
                // time to transform orb
                this.transformOrb.Extinguish();
                this.transformOrb.transform.localScale = new Vector3(1f, 1f, 0f);
                Orb orb = this.orbManager.MakeGhostOrb(this.transformOrb, this.orbs);
                this.orbs  = new Orb[2];
                this.state = State.ORBED;
                Instantiate(PrefabManager.EXPLOSION_PREFAB, this.transform.position, Quaternion.identity);
                orb.Extinguish();
            }
        }
        else if (this.state == State.ORBED)
        {
            Destroy(this.gameObject);
        }
        else if (this.state == State.IN_VOID)
        {
            Destroy(this.gameObject);
        }

        this.forgetAvoidTimer -= Time.deltaTime;
        if (this.forgetAvoidTimer < 0f)
        {
            this.avoid = null;
        }

        this.stateTimer -= Time.deltaTime;
        // Physics
        float gateX    = this.gate.transform.position.x + this.gate.width;
        float speed    = this.velocity.magnitude;
        float maxSpeed = (this.state == State.WANDER || this.state == State.POST_FIGHT || this.state == State.IGNORE || this.state == State.MESMERIZED || this.state == State.TRAVEL_TO_TRANSFORM_ORB) ?
                         this.wanderSpeed : this.sprintSpeed;

        if (speed != 0f)
        {
            Vector2 frictionChange = this.velocity.normalized * this.friction * Time.deltaTime;
            if (frictionChange.magnitude < speed)
            {
                this.velocity -= frictionChange;
            }
            else
            {
                this.velocity = Vector2.zero;
            }
        }
        speed = this.velocity.magnitude;
        if (speed > maxSpeed && !this.shoved)
        {
            this.velocity *= maxSpeed / speed;
        }
        if (speed < maxSpeed)
        {
            this.shoved = false;
        }
        if (this.transform.position.x < gateX && this.velocity.x < 0)
        {
            this.velocity = new Vector2(-0.5f * this.velocity.x, this.velocity.y);
        }
        this.transform.position += (Vector3)this.velocity * Time.deltaTime;
        this.emotion.UpdateFromState(state);

        // Maintain z ordering.
        Vector2 pos = this.transform.position;

        this.transform.position = new Vector3(pos.x, pos.y, pos.y / 300f);
    }