public override void Tick()
    {
        if (!alert)
        {
            if (decisionTime > 0f)
            {
                decisionTime -= Time.deltaTime;
                return;
            }
            decisionTime = Random.Range(.4f, .6f);

            int distance = AxMath.WeightedDistance(owner.cell, GameManager.Instance.Player[0].cell);
            if (distance > SeeDistance)
            {
                return;
            }

            if (Random.value <= NearSoundChanceSleeping)
            {
                if (mc.NearSounds.Length > 0)
                {
                    if (!mc.audioSource.isPlaying)
                    {
                        mc.audioSource.clip = mc.NearSounds[Random.Range(0, mc.NearSounds.Length)];
                        mc.audioSource.Play();
                    }
                }
            }

            if (SeePlayerRay())
            {
                alert        = true;
                decisionTime = 0f;
            }

            if (!alert)
            {
                return;
            }
        }

        if (painFrame)
        {
            mc.moveVector = Vector3.zero;
            painFrame     = false;
            attackTime    = 0f;
            decisionTime  = 0f;
            return;
        }

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

            Vector3 aimAt = (GameManager.Instance.Player[0].transform.position - mc.transform.position).normalized;
            //mc.transform.rotation = Quaternion.LookRotation(Vector3.Lerp(mc.transform.forward, new Vector3(aimAt.x, 0, aimAt.z), Time.deltaTime * mc.turnSpeed), Vector3.up);
            //instantenous rotation towards target
            mc.transform.rotation = Quaternion.LookRotation(new Vector3(aimAt.x, 0, aimAt.z), Vector3.up);

            if (attackTime < AttackHappenTime && !attacked)
            {
                attacked = true;

                float distance = (owner.transform.position + Vector3.up * AttackHeight - GameManager.Instance.Player[0].transform.position).magnitude;
                if (distance < meleeAttackRange)
                {
                    if (CanMeleeRay(distance))
                    {
                        if (mc.AttackSounds.Length > 0)
                        {
                            GameManager.Create3DSound(mc.transform.position, mc.AttackSounds[0], 5f);
                        }

                        Damageable d = GameManager.Instance.Player[0].GetComponent <Damageable>();
                        if (d != null)
                        {
                            d.Damage(Random.Range(MeleeDamageMin, MeleeDamageMax + 1), DamageType.Generic, owner.gameObject);
                        }
                    }
                }
            }

            return;
        }

        if (wantDirection != Vector3.zero)
        {
            mc.transform.rotation = Quaternion.LookRotation(Vector3.Lerp(mc.transform.forward, wantDirection, Time.deltaTime * mc.turnSpeed), Vector3.up);
        }

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

        if (Random.value <= NearSoundChanceAwake)
        {
            if (mc.NearSounds.Length > 0)
            {
                if (!mc.audioSource.isPlaying)
                {
                    mc.audioSource.clip = mc.NearSounds[Random.Range(0, mc.NearSounds.Length)];
                    mc.audioSource.Play();
                }
            }
        }

        decisionTime  = Random.Range(.2f, .3f);
        wantDirection = Vector3.zero;

        bool aggro = false;

        {
            float distance = (owner.transform.position + Vector3.up * AttackHeight - GameManager.Instance.Player[0].transform.position).magnitude;
            if (distance < meleeAttackRange)
            {
                wantMove     = false;
                aggro        = true;
                attacked     = false;
                attackTime   = .7f;
                decisionTime = 0f;
                mc.InitAttackAnimation();
                mc.frametime = .2f;
            }
        }

        if (!aggro)
        {
            if (!MoveToRandomClosestBreath())
            {
                if (!MoveTowardsBreath())
                {
                    MoveToRandomNearbyCell();
                }
            }
        }

        if (Random.value < IdleChance)
        {
            wantMove = false;
        }

        if (wantMove)
        {
            mc.moveVector.x = 1;
        }
        else
        {
            mc.moveVector.x = 0;
        }
    }
Ejemplo n.º 2
0
    public static void CreateMeshes()
    {
        Transform holder = new GameObject("MapMeshes").transform;

        holder.transform.SetParent(GameManager.Instance.transform);

        //walls
        {
            int index = 0;
            foreach (Linedef l in MapLoader.linedefs)
            {
                //if (l.lineType > 0 || l.lineTag > 0)
                //Debug.Log("Line " + index + " type: " + l.lineType + " tag: " + l.lineTag);

                //add linedef to the fast lookup cache
                AxMath.CartesianLineF(l.start.Position, l.end.Position).Perform((n) =>
                {
                    int gridX = n.Data.x - TheGrid.origoX;
                    int gridY = n.Data.y - TheGrid.origoY;

                    TheGrid.linedefs[gridX, gridY].Add(l);
                    TheGrid.existenceBox.data[gridX, gridY] = true;
                });

                if (l.Back != null)
                {
                    //top part (front)
                    if (l.Front.Sector.ceilingHeight > l.Back.Sector.ceilingHeight)
                    {
                        l.TopFrontObject = CreateLineQuad
                                           (
                            l.Front,
                            l.Back.Sector.ceilingHeight,
                            l.Front.Sector.ceilingHeight + (l.Back.Sector.ceilingHeight - l.Back.Sector.minimumCeilingHeight),
                            l.Front.tHigh,
                            l.Front.offsetX,
                            (l.flags & (1 << 3)) != 0 ? l.Front.offsetY : -l.Front.offsetY,
                            (l.flags & (1 << 3)) != 0 ? 0 : 1,
                            false,
                            l.Front.Sector.brightness,
                            true,
                            "Wall_" + index + "_top_front",
                            holder
                                           );
                    }
                    //lowering ceiling (front)
                    else if (l.Front.Sector.ceilingHeight > l.Back.Sector.minimumCeilingHeight)
                    {
                        l.TopFrontObject = CreateLineQuad
                                           (
                            l.Front,
                            l.Back.Sector.ceilingHeight,
                            l.Front.Sector.ceilingHeight + (l.Back.Sector.ceilingHeight - l.Back.Sector.minimumCeilingHeight),
                            l.Front.tHigh,
                            l.Front.offsetX,
                            (l.flags & (1 << 3)) != 0 ? l.Front.offsetY : -l.Front.offsetY,
                            (l.flags & (1 << 3)) != 0 ? 0 : 1,
                            false,
                            l.Front.Sector.brightness,
                            true,
                            "Wall_" + index + "_top_front",
                            holder
                                           );
                    }

                    //top part (back)
                    if (l.Front.Sector.ceilingHeight < l.Back.Sector.ceilingHeight)
                    {
                        l.TopBackObject = CreateLineQuad
                                          (
                            l.Back,
                            l.Front.Sector.ceilingHeight,
                            l.Back.Sector.ceilingHeight,
                            l.Back.tHigh,
                            l.Back.offsetX,
                            (l.flags & (1 << 3)) != 0 ? l.Back.offsetY : l.Back.offsetY,
                            (l.flags & (1 << 3)) != 0 ? 0 : 1,
                            true,
                            l.Back.Sector.brightness,
                            true,
                            "Wall_" + index + "_top_back",
                            holder
                                          );
                    }

                    //bottom part (front)
                    if (l.Front.Sector.minimumFloorHeight < l.Back.Sector.floorHeight)
                    {
                        l.BotFrontObject = CreateLineQuad
                                           (
                            l.Front,
                            l.Front.Sector.minimumFloorHeight,
                            l.Back.Sector.floorHeight,
                            l.Front.tLow,
                            l.Front.offsetX,
                            l.Front.offsetY,
                            ((l.flags & (1 << 4)) != 0) ? 2 : 0,
                            false,
                            l.Front.Sector.brightness,
                            true,
                            "Wall_" + index + "_bot_front",
                            holder
                                           );
                    }
                    //rising floor (front)
                    else if (l.Front.Sector.maximumFloorHeight > l.Back.Sector.floorHeight && l.Front.Sector.maximumFloorHeight > l.Front.Sector.floorHeight)
                    {
                        l.BotFrontObject = CreateLineQuad
                                           (
                            l.Front,
                            l.Front.Sector.floorHeight - (l.Front.Sector.maximumFloorHeight - l.Back.Sector.floorHeight),
                            l.Front.Sector.floorHeight,
                            l.Front.tLow,
                            l.Front.offsetX,
                            l.Front.offsetY,
                            ((l.flags & (1 << 4)) != 0) ? 2 : 0,
                            false,
                            l.Front.Sector.brightness,
                            true,
                            "Wall_" + index + "_bot_front",
                            holder
                                           );
                    }

                    //bottom part (back)
                    if (l.Front.Sector.floorHeight > l.Back.Sector.minimumFloorHeight)
                    {
                        l.BotBackObject = CreateLineQuad
                                          (
                            l.Back,
                            l.Back.Sector.minimumFloorHeight,
                            l.Front.Sector.floorHeight,
                            l.Back.tLow,
                            l.Back.offsetX,
                            l.Front.offsetY,
                            ((l.flags & (1 << 4)) != 0) ? 2 : 0,
                            true,
                            l.Back.Sector.brightness,
                            true,
                            "Wall_" + index + "_bot_back",
                            holder
                                          );
                    }
                    //rising floor (back)
                    else if (l.Back.Sector.maximumFloorHeight > l.Front.Sector.floorHeight && l.Back.Sector.maximumFloorHeight > l.Back.Sector.floorHeight)
                    {
                        l.BotBackObject = CreateLineQuad
                                          (
                            l.Front,
                            l.Back.Sector.floorHeight - (l.Back.Sector.maximumFloorHeight - l.Front.Sector.floorHeight),
                            l.Back.Sector.floorHeight,
                            l.Front.tLow,
                            l.Front.offsetX,
                            l.Front.offsetY,
                            ((l.flags & (1 << 4)) != 0) ? 2 : 0,
                            false,
                            l.Front.Sector.brightness,
                            true,
                            "Wall_" + index + "_bot_front",
                            holder
                                          );
                    }

                    //middle (front)
                    if (l.Front.tMid != "-")
                    {
                        l.MidFrontObject = CreateLineQuad
                                           (
                            l.Front,
                            Mathf.Max(l.Front.Sector.floorHeight, l.Back.Sector.floorHeight),
                            Mathf.Min(l.Front.Sector.ceilingHeight, l.Back.Sector.ceilingHeight),
                            l.Front.tMid,
                            l.Front.offsetX,
                            l.Front.offsetY,
                            ((l.flags & (1 << 4)) != 0) ? 1 : 0,
                            false,
                            l.Front.Sector.brightness,
                            false,
                            "Wall_" + index + "_mid_front",
                            holder
                                           );
                    }

                    //middle (back)
                    if (l.Back.tMid != "-")
                    {
                        l.MidBackObject = CreateLineQuad
                                          (
                            l.Back,
                            Mathf.Max(l.Front.Sector.floorHeight, l.Back.Sector.floorHeight),
                            Mathf.Min(l.Front.Sector.ceilingHeight, l.Back.Sector.ceilingHeight),
                            l.Back.tMid,
                            l.Back.offsetX,
                            l.Back.offsetY,
                            ((l.flags & (1 << 4)) != 0) ? 1 : 0,
                            true,
                            l.Back.Sector.brightness,
                            false,
                            "Wall_" + index + "_mid_back",
                            holder
                                          );
                    }

                    if ((l.flags & (1 << 0)) != 0)
                    {
                        CreateInvisibleBlocker
                        (
                            l,
                            Mathf.Max(l.Front.Sector.floorHeight, l.Back.Sector.floorHeight),
                            Mathf.Min(l.Front.Sector.ceilingHeight, l.Back.Sector.ceilingHeight),
                            "Wall_" + index + "_blocker",
                            holder
                        );
                    }
                }
                else //solid wall
                {
                    l.MidFrontObject = CreateLineQuad
                                       (
                        l.Front,
                        l.Front.Sector.minimumFloorHeight,
                        l.Front.Sector.maximumCeilingHeight,
                        l.Front.tMid,
                        l.Front.offsetX,
                        l.Front.offsetY,
                        ((l.flags & (1 << 4)) != 0) ? 1 : 0,
                        false,
                        l.Front.Sector.brightness,
                        true,
                        "Wall_" + index,
                        holder
                                       );
                }

                index++;
            }
        }

        //sectors
        {
            Triangulator triangulator = new Triangulator();

            int index = 0;
            foreach (Sector s in MapLoader.sectors)
            {
                //if (s.specialType > 0 || s.tag > 0)
                //Debug.Log("Sector " + index + " type: " + s.specialType + " tag: " + s.tag);

                triangulator.Triangulate(s);

                if (Triangulator.vertices.Count == 0)
                {
                    Debug.Log("Triangulation failed for sector " + index);
                }

                //floor
                {
                    GameObject sectorObject = new GameObject("Sector_" + index + "_floor");
                    s.floorObject = sectorObject.AddComponent <SectorController>();
                    sectorObject.transform.SetParent(holder);
                    MeshRenderer mr         = sectorObject.AddComponent <MeshRenderer>();
                    MeshFilter   meshFilter = sectorObject.AddComponent <MeshFilter>();
                    Mesh         mesh       = new Mesh();
                    meshFilter.mesh = mesh;

                    if (!MaterialManager.Instance.OverridesFlat(s.floorTexture, sectorObject, mr))
                    {
                        mr.material = MaterialManager.Instance.defaultMaterial;
                    }

                    if (mr.material.mainTexture == null)
                    {
                        MaterialPropertyBlock materialProperties = new MaterialPropertyBlock();
                        materialProperties.SetTexture("_MainTex", TextureLoader.Instance.GetFlatTexture(s.floorTexture));
                        mr.SetPropertyBlock(materialProperties);
                    }

                    mesh.name = "Sector_" + index + "_floor_mesh";

                    int vc = Triangulator.vertices.Count;

                    Vector3[] vertices = new Vector3[vc];
                    Vector3[] normals  = new Vector3[vc];
                    Vector2[] uvs      = new Vector2[vc];
                    Color[]   colors   = new Color[vc];
                    int[]     indices  = new int[vc];

                    int          v      = 0;
                    int          i      = 0;
                    int          g      = 0;
                    Triangle     t      = null;
                    BooleanBox[] bboxes = new BooleanBox[Triangulator.vertices.Count / 3];
                    foreach (Vector2 p in Triangulator.vertices)
                    {
                        vertices[v] = new Vector3(p.x, s.floorHeight, p.y);
                        indices[v]  = v;
                        normals[v]  = Vector3.up;
                        uvs[v]      = new Vector2(p.x / MapLoader.flatUVdividor, 1 - (p.y / MapLoader.flatUVdividor));
                        colors[v]   = Color.white * s.brightness;

                        v++;

                        //add the triangle to the fast lookup cache
                        if (i == 0)
                        {
                            t = new Triangle();
                        }

                        t.vertices[i] = p;

                        i++;
                        if (i == 3)
                        {
                            i        = 0;
                            t.sector = s;
                            s.triangles.Add(t);

                            BooleanBox bbox = t.SelectBox;
                            if (bbox != null)
                            {
                                for (int y = 0; y < bbox.size.y; y++)
                                {
                                    for (int x = 0; x < bbox.size.x; x++)
                                    {
                                        if (bbox.data[x, y])
                                        {
                                            int gridX = bbox.origo.x - TheGrid.origoX + x;
                                            int gridY = bbox.origo.y - TheGrid.origoY + y;
                                            TheGrid.triangles[gridX, gridY].Add(t);
                                            TheGrid.existenceBox.data[gridX, gridY] = true;
                                        }
                                    }
                                }
                            }

                            bboxes[g++] = bbox;
                        }
                    }

                    //combine all triangles and add the sector to the fast lookup cache
                    BooleanBox sectorBox = BooleanBox.Combine(bboxes);
                    for (int y = 0; y < sectorBox.size.y; y++)
                    {
                        for (int x = 0; x < sectorBox.size.x; x++)
                        {
                            if (sectorBox.data[x, y])
                            {
                                int gridX = sectorBox.origo.x - TheGrid.origoX + x;
                                int gridY = sectorBox.origo.y - TheGrid.origoY + y;
                                TheGrid.sectors[gridX, gridY].Add(s);
                                TheGrid.existenceBox.data[gridX, gridY] = true;
                            }
                        }
                    }

                    mesh.vertices  = vertices;
                    mesh.triangles = indices;
                    mesh.normals   = normals;
                    mesh.uv        = uvs;
                    mesh.colors    = colors;

                    mesh.RecalculateBounds();

                    MeshCollider mc = sectorObject.AddComponent <MeshCollider>();
                    mc.sharedMesh = mesh;
                }

                //ceiling
                Triangulator.vertices.Reverse();
                {
                    GameObject sectorObject = new GameObject("Sector_" + index + "_ceiling");
                    s.ceilingObject = sectorObject;
                    sectorObject.transform.SetParent(holder);
                    MeshRenderer mr         = sectorObject.AddComponent <MeshRenderer>();
                    MeshFilter   meshFilter = sectorObject.AddComponent <MeshFilter>();
                    Mesh         mesh       = new Mesh();
                    meshFilter.mesh = mesh;
                    mesh.name       = "Sector_" + index + "_ceiling_mesh";

                    if (!MaterialManager.Instance.OverridesFlat(s.ceilingTexture, sectorObject, mr))
                    {
                        mr.material = MaterialManager.Instance.defaultMaterial;
                    }

                    if (mr.material.mainTexture == null)
                    {
                        MaterialPropertyBlock materialProperties = new MaterialPropertyBlock();
                        materialProperties.SetTexture("_MainTex", TextureLoader.Instance.GetFlatTexture(s.ceilingTexture));
                        mr.SetPropertyBlock(materialProperties);
                    }

                    int vc = Triangulator.vertices.Count;

                    Vector3[] vertices = new Vector3[vc];
                    Vector3[] normals  = new Vector3[vc];
                    Vector2[] uvs      = new Vector2[vc];
                    Color[]   colors   = new Color[vc];
                    int[]     indices  = new int[vc];

                    int v = 0;
                    foreach (Vector2 p in Triangulator.vertices)
                    {
                        vertices[v] = new Vector3(p.x, s.ceilingHeight, p.y);
                        indices[v]  = v;
                        normals[v]  = -Vector3.up;
                        uvs[v]      = new Vector2(p.x / MapLoader.flatUVdividor, 1 - (p.y / MapLoader.flatUVdividor));
                        colors[v]   = Color.white * s.brightness;
                        v++;
                    }

                    mesh.vertices  = vertices;
                    mesh.triangles = indices;
                    mesh.normals   = normals;
                    mesh.uv        = uvs;
                    mesh.colors    = colors;

                    mesh.RecalculateBounds();

                    MeshCollider mc = sectorObject.AddComponent <MeshCollider>();
                    mc.sharedMesh = mesh;
                }

                s.floorObject.sector = s;
                s.floorObject.Init();

                index++;
            }
        }
    }
Ejemplo n.º 3
0
    void Update()
    {
        if (GameManager.Paused)
        {
            return;
        }

        if (dynamic)
        {
            ApplySimpleGravity();
        }

        if (dead)
        {
            frametime += Time.deltaTime;
            if (frametime > .15f)
            {
                frametime = 0f;

                frameindex++;

                if (frameindex == 2)
                {
                    Collider[] hits = Physics.OverlapSphere(transform.position, explosionRadius, ~(1 << 9), QueryTriggerInteraction.Ignore);
                    foreach (Collider hit in hits)
                    {
                        Damageable d = hit.GetComponent <Damageable>();
                        if (d != null)
                        {
                            float distance = (hit.transform.position - transform.position).magnitude;
                            d.Damage(AxMath.Lerp(blastDamage, 1, distance / explosionRadius), DamageType.Explosion, gameObject);
                            d.Impulse((hit.transform.position - transform.position).normalized, Mathf.Lerp(pushForce, 100, distance / explosionRadius));
                        }
                    }
                }

                if (frameindex >= ExplodeTextures.Length)
                {
                    Destroy(gameObject);

                    for (int y = -1; y <= 1; y++)
                    {
                        for (int x = -1; x <= 1; x++)
                        {
                            AI.CalculateHeat(cell.x + x, cell.y + y);
                        }
                    }

                    if (GameManager.Instance.Player[0].playerBreath.GetBreath(cell) != null)
                    {
                        GameManager.Instance.Player[0].RecastBreath();
                    }

                    return;
                }

                SetSprite(ExplodeTextures[frameindex]);
            }
            return;
        }

        frametime += Time.deltaTime;
        if (frametime > .25f)
        {
            frametime = 0;

            frameindex++;
            if (frameindex >= IdleTextures.Length)
            {
                frameindex = 0;
            }

            SetSprite(IdleTextures[frameindex]);
        }
    }
Ejemplo n.º 4
0
    public Quaternion TowardsPosition(Vector3 position)
    {
        Vector2 dif = (position - transform.position);

        return(Quaternion.Euler(0, 0, AxMath.SafeAtan2(dif.y, dif.x) * Mathf.Rad2Deg));
    }
Ejemplo n.º 5
0
 public bool ContainsPoint(float x, float y)
 {
     return(AxMath.PointInTriangle(new Vector2(x, y), vertices[0], vertices[1], vertices[2]));
 }
Ejemplo n.º 6
0
 public float GetAreaSigned()
 {
     return(AxMath.TriangleAreaSigned(vertices[0], vertices[1], vertices[2]));
 }
Ejemplo n.º 7
0
    public static void NaturalizePath(ref Vec2I[] path, int maxSteps)
    {
        if (path.Length < 3)
        {
            return;
        }
        if (maxSteps < 2)
        {
            return;
        }

        SingleLinkedList <Vec2I> naturalized = new SingleLinkedList <Vec2I>();

        naturalized.InsertBack(path[0]);

        int s = 0;
        int e = 2;

        Vec2I[] lastLine = new Vec2I[0];

        while (e < path.Length)
        {
            int steps = 0;

again:
            Vec2I[] line = AxMath.CartesianLine(path[s], path[e]);

            for (int i = 0; i < line.Length; i++)
            {
                HeatmapNode n = Heatmap.GetNode(line[i]);
                if (n == null)
                {
                    goto failed;
                }
                if (!n.WideOpen)
                {
                    goto failed;
                }
            }

            if (steps <= maxSteps)
            {
                if (e == path.Length - 1)
                {
                    naturalized.InsertBack(path[e]);
                    path = naturalized.ToArray();
                    return;
                }

                lastLine = line;
                steps++;
                e++;

                goto again;
            }

failed:
            if (e > s + 2)
            {
                naturalized.InsertBack(lastLine[lastLine.Length - 1]);

                s = e;
                e = s + 2;
                continue;
            }

            naturalized.InsertBack(path[++s]);
            e = s + 2;
        }

        while (s < path.Length)
        {
            naturalized.InsertBack(path[s++]);
        }

        path = naturalized.ToArray();
    }
Ejemplo n.º 8
0
 public bool ContainsPoint(Vector2 point)
 {
     return(AxMath.PointInTriangle(point, vertices[0], vertices[1], vertices[2]));
 }
    public override void Tick()
    {
        if (!alert)
        {
            if (decisionTime > 0f)
            {
                decisionTime -= Time.deltaTime;
                return;
            }

            decisionTime = .5f;

            int distance = AxMath.WeightedDistance(owner.cell, GameManager.Instance.Player[0].cell);

            if (distance > 400)
            {
                return;
            }

            Vector3 eyePos   = owner.transform.position + Vector3.up * 1.55f;
            Vector3 toPlayer = ((GameManager.Instance.Player[0].transform.position + Random.onUnitSphere * .5f) - eyePos).normalized;

            if (Vector3.Dot(owner.transform.forward, toPlayer) < -.15f)
            {
                return;
            }

            Ray        ray = new Ray(eyePos, toPlayer);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, 400, ~((1 << 9) | (1 << 11) | (1 << 14)), QueryTriggerInteraction.Ignore))
            {
                if (hit.collider.GetComponent <PlayerThing>() != null)
                {
                    alert = true;
                }
            }

            if (!alert)
            {
                return;
            }
        }

        /*float mag = (lastpos - owner.transform.position).magnitude;
         * if (mag > 0.001f && mag < .02f)
         *  Debug.Log("hug");
         * lastpos = owner.transform.position;*/

        if (painFrame)
        {
            mc.moveVector = Vector3.zero;
            painFrame     = false;
            return;
        }

        if (wantDirection != Vector3.zero)
        {
            mc.transform.rotation = Quaternion.LookRotation(Vector3.Lerp(mc.transform.forward, wantDirection, Time.deltaTime * mc.turnSpeed), Vector3.up);
            mc.moveVector         = mc.transform.forward;
        }

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

        decisionTime = Random.Range(.6f, 2f);

        wantDirection = Vector3.zero;

        if (!MoveToRandomClosestBreath())
        {
            if (!MoveTowardsBreath())
            {
                MoveToRandomNearbyCell();
            }
        }
    }
    public override void Tick()
    {
        if (!alert)
        {
            if (decisionTime > 0f)
            {
                decisionTime -= Time.deltaTime;
                return;
            }
            decisionTime = Random.Range(.4f, .6f);

            int distance = AxMath.WeightedDistance(owner.cell, GameManager.Instance.Player[0].cell);
            if (distance > SeeDistance)
            {
                return;
            }

            if (Random.value <= NearSoundChanceSleeping)
            {
                if (mc.NearSounds.Length > 0)
                {
                    if (!mc.audioSource.isPlaying)
                    {
                        mc.audioSource.clip = mc.NearSounds[Random.Range(0, mc.NearSounds.Length)];
                        mc.audioSource.Play();
                    }
                }
            }

            if (SeePlayerRay())
            {
                alert        = true;
                decisionTime = 0f;
            }

            if (!alert)
            {
                return;
            }
        }

        if (painFrame)
        {
            mc.moveVector = Vector3.zero;
            painFrame     = false;
            attackTime    = 0f;
            decisionTime  = 0f;
            return;
        }

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

            Vector3 aimAt = (GameManager.Instance.Player[0].transform.position - mc.transform.position).normalized;
            //mc.transform.rotation = Quaternion.LookRotation(Vector3.Lerp(mc.transform.forward, new Vector3(aimAt.x, 0, aimAt.z), Time.deltaTime * mc.turnSpeed), Vector3.up);
            //instantenous rotation towards target
            mc.transform.rotation = Quaternion.LookRotation(new Vector3(aimAt.x, 0, aimAt.z), Vector3.up);

            if (attackTime < AttackHappenTime && !attacked)
            {
                attacked = true;

                float distance = (owner.transform.position + Vector3.up * AttackHeight - GameManager.Instance.Player[0].transform.position).magnitude;
                if (distance < meleeAttackRange)
                {
                    if (CanMeleeRay(distance))
                    {
                        if (mc.AttackSounds.Length > 0)
                        {
                            GameManager.Create3DSound(mc.transform.position, mc.AttackSounds[1], 5f);
                        }

                        Damageable d = GameManager.Instance.Player[0].GetComponent <Damageable>();
                        if (d != null)
                        {
                            d.Damage(Random.Range(MeleeDamageMin, MeleeDamageMax + 1), DamageType.Generic, owner.gameObject);
                        }
                    }
                }
                else
                {
                    if (mc.AttackSounds.Length > 0)
                    {
                        GameManager.Create3DSound(mc.transform.position, mc.AttackSounds[0], 5f);
                    }

                    if (mc.AttackProjectile != null)
                    {
                        FireballProjectile fireball = GameObject.Instantiate(mc.AttackProjectile).GetComponent <FireballProjectile>();
                        if (fireball != null)
                        {
                            fireball.transform.position = owner.transform.position + Vector3.up * AttackHeight;
                            fireball.owner = owner.gameObject;
                            fireball.transform.LookAt(GameManager.Instance.Player[0].transform.position + Random.insideUnitSphere * AttackSpread);
                            fireball.transform.SetParent(GameManager.Instance.TemporaryObjectsHolder);
                        }
                    }
                }
            }

            return;
        }

        if (wantDirection != Vector3.zero)
        {
            mc.transform.rotation = Quaternion.LookRotation(Vector3.Lerp(mc.transform.forward, wantDirection, Time.deltaTime * mc.turnSpeed), Vector3.up);
        }

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

        if (Random.value <= PokeChance)
        {
            Ray        ray = new Ray(owner.transform.position + Vector3.up, owner.transform.forward);
            RaycastHit hit;
            if (Physics.Raycast(ray, out hit, 2, ~((1 << 9) | (1 << 11)), QueryTriggerInteraction.Ignore))
            {
                Pokeable lc = hit.collider.gameObject.GetComponent <Pokeable>();
                if (lc != null)
                {
                    if (lc.AllowMonsters())
                    {
                        lc.Poke(owner.gameObject);
                    }
                }
            }
        }

        if (Random.value <= NearSoundChanceAwake)
        {
            if (mc.NearSounds.Length > 0)
            {
                if (!mc.audioSource.isPlaying)
                {
                    mc.audioSource.clip = mc.NearSounds[Random.Range(0, mc.NearSounds.Length)];
                    mc.audioSource.Play();
                }
            }
        }

        decisionTime  = Random.Range(.4f, .6f);
        wantDirection = Vector3.zero;

        bool aggro = false;

        {
            float distance = (owner.transform.position + Vector3.up * AttackHeight - GameManager.Instance.Player[0].transform.position).magnitude;
            if (distance < meleeAttackRange)
            {
                wantMove     = false;
                aggro        = true;
                attacked     = false;
                attackTime   = .7f;
                decisionTime = 0f;
                mc.InitAttackAnimation();
                mc.frametime = .2f;
            }
            else if (Random.value < AggroChance)
            {
                Ray toPlayer;
                if (SeePlayerRay(out toPlayer))
                {
                    wantDirection = new Vector3(toPlayer.direction.x, 0, toPlayer.direction.z);
                    wantMove      = false;
                    aggro         = true;
                    attacked      = false;
                    attackTime    = 1f;
                    decisionTime  = 0f;
                    mc.InitAttackAnimation();
                }
            }
        }

        if (!aggro)
        {
            float moveRoll = Random.value;
            if (moveRoll < randomMoveChance)
            {
                MoveToRandomNearbyCell();
            }
            else if (moveRoll < closestMoveChance)
            {
                if (!MoveToRandomClosestBreath())
                {
                    MoveToRandomNearbyCell();
                }
            }
            else
            {
                if (!MoveTowardsBreath())
                {
                    if (!MoveToRandomClosestBreath())
                    {
                        MoveToRandomNearbyCell();
                    }
                }
            }
        }

        if (Random.value < IdleChance)
        {
            wantMove = false;
        }

        if (wantMove)
        {
            mc.moveVector.x = 1;
        }
        else
        {
            mc.moveVector.x = 0;
        }
    }
Ejemplo n.º 11
0
    /// <summary>
    /// Tries to make pathfinding more natural like, instead of hugging walls the object tries to move toward corners and doors.
    /// </summary>
    public static void NaturalizePath(ref Vec2I[] path, int maxSteps)
    {
        if (path.Length < 3)
        {
            return;
        }

        if (maxSteps < 2)
        {
            return;
        }

        SingleLinkedList <Vec2I> naturalized = new SingleLinkedList <Vec2I>();

        int s = 0;
        int e = 2;

        Vec2I[] lastLine = new Vec2I[0];

        while (e < path.Length)
        {
            int steps = 0;

again:
            Vec2I[] line = AxMath.RogueLine(path[s], path[e]).ToArray();
            for (int i = 0; i < line.Length; i++)
            {
                if (!CanPath(line[i]))
                {
                    goto failed;
                }
            }

            if (e < path.Length - 1 && steps <= maxSteps)
            {
                lastLine = line;
                steps++;
                e++;
                goto again;
            }

failed:
            if (e > s + 2)
            {
                for (int i = 0; i < lastLine.Length; i++)
                {
                    naturalized.InsertBack(lastLine[i]);
                }

                s = e;
                e = s + 2;
                continue;
            }

            naturalized.InsertBack(path[s]);
            s++;
            e = s + 2;
        }

        while (s < path.Length)
        {
            naturalized.InsertBack(path[s++]);
        }

        path = naturalized.ToArray();
    }
Ejemplo n.º 12
0
    public static void FillPlayerBreath(ref BreathArea breath, ref List <ThingController> monstersList, bool cullByTrueDistance = false)
    {
        int   maxDistance = breath.maxDistance;
        int   arraySize   = breath.size;
        Vec2I StartPoint  = breath.position;

        breath.Invalidate();
        monstersList.Clear();

        if (GetHeat(StartPoint).x == -1)
        {
            return;
        }

        //init arrays
        bool[,] closedCheck   = new bool[arraySize, arraySize];
        bool[,] openCheck     = new bool[arraySize, arraySize];
        PathStep[,] openArray = new PathStep[arraySize, arraySize];

        //set start point
        BinaryHeap <PathStep> openList = new BinaryHeap <PathStep>(arraySize * arraySize);

        openList.Add(new PathStep(StartPoint, 0));
        openCheck[maxDistance, maxDistance] = true;

        breath.exist[maxDistance, maxDistance]     = true;
        breath.steps[maxDistance, maxDistance]     = 0;
        breath.distance[maxDistance, maxDistance]  = 0;
        breath.direction[maxDistance, maxDistance] = 0;

        List <ThingController> monsters = new List <ThingController>();

        int maxStepDistance = maxDistance * 10;

        while (openList.ItemCount > 0)
        {
            //get top of heap
            PathStep current         = openList.RemoveFirst();
            int      ax              = current.position.x - StartPoint.x + maxDistance;
            int      ay              = current.position.y - StartPoint.y + maxDistance;
            int      currentDistance = breath.distance[ax, ay];
            int      currentSteps    = breath.steps[ax, ay];
            closedCheck[ax, ay] = true;

            TheGrid.GetNearbyMonsters(current.position, 0).Perform((n) => { monsters.Add(n.Data); });

            if (cullByTrueDistance)
            {
                if (currentDistance >= maxStepDistance)
                {
                    continue;
                }
            }

            Vector3 currentHeat = GetHeat(current.position);

            //no propagation through solids
            if (currentHeat.x >= 1f)
            {
                if (current.position != StartPoint)
                {
                    continue;
                }
            }

            for (int i = 1; i < 9; i++)
            {
                Vec2I neighbor = current.position + Vec2I.directions[i];

                //calculate array position
                int arrayX = neighbor.x - StartPoint.x + maxDistance;
                int arrayY = neighbor.y - StartPoint.y + maxDistance;

                //cull disallowed
                if (AxMath.RogueDistance(neighbor, StartPoint) > maxDistance)
                {
                    continue;
                }
                if (openCheck[arrayX, arrayY])
                {
                    continue;
                }
                if (closedCheck[arrayX, arrayY])
                {
                    continue;
                }

                if (!CanPath(neighbor))
                {
                    continue;
                }

                if (HasLedge(current.position, neighbor, false))
                {
                    continue;
                }

                //calculate cost
                int travelCost = current.travelCost + GetTravelCost(neighbor);
                int heuristic  = AxMath.WeightedDistance(neighbor, StartPoint);
                int fullCost   = travelCost + heuristic;

                //reverse direction to point towards the source of breath
                int p = i + 4;
                if (p > 8)
                {
                    p -= 8;
                }

                //check if we can update parent to better
                if (openCheck[arrayX, arrayY])
                {
                    if (openArray[arrayX, arrayY].travelCost > travelCost)
                    {
                        openArray[arrayX, arrayY].travelCost = travelCost;
                        openArray[arrayX, arrayY].heuristic  = heuristic;
                        openArray[arrayX, arrayY].fullCost   = fullCost;
                        breath.direction[arrayX, arrayY]     = p;
                        breath.distance[arrayX, arrayY]      = currentDistance + StepDistance(i);
                        breath.steps[arrayX, arrayY]         = currentSteps + 1;
                        openList.UpdateItem(openArray[arrayX, arrayY]);
                        continue;
                    }
                    else
                    {
                        continue;
                    }
                }

                //priority sorted by heap
                PathStep step = new PathStep(neighbor, travelCost, heuristic);
                openList.Add(step);
                openArray[arrayX, arrayY] = step;
                openCheck[arrayX, arrayY] = true;

                breath.exist[arrayX, arrayY]     = true;
                breath.direction[arrayX, arrayY] = p;
                breath.distance[arrayX, arrayY]  = currentDistance + StepDistance(i);
                breath.steps[arrayX, arrayY]     = currentSteps + 1;
            }
        }

        monstersList = monsters;
    }
Ejemplo n.º 13
0
    public static void FillBreath(ref BreathArea breath, ref List <ThingController> monstersList, bool cullByTrueDistance = false)
    {
        int   maxDistance = breath.maxDistance;
        int   arraySize   = breath.size;
        Vec2I StartPoint  = breath.position;

        breath.Invalidate();

        if (GetHeat(StartPoint).x == -1)
        {
            return;
        }

        //init arrays
        bool[,] closedCheck = new bool[arraySize, arraySize];
        bool[,] openCheck   = new bool[arraySize, arraySize];

        //set start point
        SingleLinkedList <Vec2I> openList = new SingleLinkedList <Vec2I>();

        openList.InsertFront(StartPoint);
        openCheck[maxDistance, maxDistance] = true;

        breath.exist[maxDistance, maxDistance]     = true;
        breath.steps[maxDistance, maxDistance]     = 0;
        breath.distance[maxDistance, maxDistance]  = 0;
        breath.direction[maxDistance, maxDistance] = 0;

        List <ThingController> monsters = new List <ThingController>();

        SingleLinkedList <int> randomNeighbors = new SingleLinkedList <int>();
        int maxStepDistance = maxDistance * 10;

        while (openList.Count > 0)
        {
            //get top of heap
            Vec2I current         = openList.RemoveHead();
            int   ax              = current.x - StartPoint.x + maxDistance;
            int   ay              = current.y - StartPoint.y + maxDistance;
            int   currentDistance = breath.distance[ax, ay];
            int   currentSteps    = breath.steps[ax, ay];
            closedCheck[ax, ay] = true;

            TheGrid.GetNearbyMonsters(current, 0).Perform((n) => { monsters.Add(n.Data); });

            if (cullByTrueDistance)
            {
                if (currentDistance >= maxStepDistance)
                {
                    continue;
                }
            }

            Vector3 currentHeat = GetHeat(current);

            //no propagation through solids
            if (currentHeat.x >= 1f)
            {
                if (current != StartPoint)
                {
                    continue;
                }
            }

            //don't hassle, shuffle
            for (int i = 1; i < 9; i++)
            {
                if (Random.value > .5f)
                {
                    randomNeighbors.InsertFront(i);
                }
                else
                {
                    randomNeighbors.InsertBack(i);
                }
            }

            while (randomNeighbors.Count > 0)
            {
                int   i        = randomNeighbors.RemoveHead();
                Vec2I neighbor = current + Vec2I.directions[i];

                //calculate array position
                int arrayX = neighbor.x - StartPoint.x + maxDistance;
                int arrayY = neighbor.y - StartPoint.y + maxDistance;

                //cull disallowed
                if (AxMath.RogueDistance(neighbor, StartPoint) > maxDistance)
                {
                    continue;
                }
                if (openCheck[arrayX, arrayY])
                {
                    continue;
                }
                if (closedCheck[arrayX, arrayY])
                {
                    continue;
                }

                if (!CanPath(neighbor))
                {
                    continue;
                }

                openList.InsertBack(neighbor);
                openCheck[arrayX, arrayY] = true;

                //reverse direction to point towards the source of breath
                int p = i + 4;
                if (p > 8)
                {
                    p -= 8;
                }

                breath.exist[arrayX, arrayY]     = true;
                breath.direction[arrayX, arrayY] = p;
                breath.distance[arrayX, arrayY]  = currentDistance + StepDistance(i);
                breath.steps[arrayX, arrayY]     = currentSteps + 1;
            }
        }

        monstersList = monsters;
    }
Ejemplo n.º 14
0
    public static bool GetPath(Vec2I StartPoint, Vec2I EndPoint, int maxDistance, out Vec2I[] path)
    {
        if (StartPoint == EndPoint)
        {
            path    = new Vec2I[1];
            path[0] = EndPoint;
            return(true);
        }

        path = null;

        if (AxMath.RogueDistance(StartPoint, EndPoint) > maxDistance)
        {
            return(false);
        }
        if (GetHeat(StartPoint).x == -1)
        {
            return(false);
        }
        if (GetHeat(EndPoint).x == -1)
        {
            return(false);
        }

        //init arrays
        int arraySize = maxDistance * 2 + 1;

        bool[,] closedCheck   = new bool[arraySize, arraySize];
        bool[,] openCheck     = new bool[arraySize, arraySize];
        Vec2I[,] parents      = new Vec2I[arraySize, arraySize];
        PathStep[,] openArray = new PathStep[arraySize, arraySize];

        //set start point
        BinaryHeap <PathStep> openList = new BinaryHeap <PathStep>(arraySize * arraySize);

        openList.Add(new PathStep(StartPoint, AxMath.WeightedDistance(StartPoint, EndPoint)));
        openCheck[maxDistance, maxDistance] = true;
        parents[maxDistance, maxDistance]   = StartPoint;

        bool found = false;

        while (openList.ItemCount > 0)
        {
            //get top of heap
            PathStep current = openList.RemoveFirst();
            closedCheck[current.position.x - StartPoint.x + maxDistance, current.position.y - StartPoint.y + maxDistance] = true;

            foreach (Vec2I neighbor in current.position.neighbors)
            {
                //calculate array position
                int arrayX = neighbor.x - StartPoint.x + maxDistance;
                int arrayY = neighbor.y - StartPoint.y + maxDistance;

                //cull disallowed
                if (AxMath.RogueDistance(neighbor, StartPoint) > maxDistance)
                {
                    continue;
                }
                if (closedCheck[arrayX, arrayY])
                {
                    continue;
                }

                //found target
                if (neighbor == EndPoint)
                {
                    parents[arrayX, arrayY] = current.position;
                    found = true;
                    goto finalize;
                }

                if (!CanPath(neighbor))
                {
                    continue;
                }

                //calculate cost
                int travelCost = current.travelCost + AxMath.WeightedDistance(current.position, neighbor);
                int heuristic  = AxMath.WeightedDistance(neighbor, EndPoint);
                int fullCost   = travelCost + heuristic;

                //check if we can update parent to better
                if (openCheck[arrayX, arrayY])
                {
                    if (openArray[arrayX, arrayY].travelCost > travelCost)
                    {
                        openArray[arrayX, arrayY].travelCost = travelCost;
                        openArray[arrayX, arrayY].heuristic  = heuristic;
                        openArray[arrayX, arrayY].fullCost   = fullCost;
                        parents[arrayX, arrayY] = current.position;
                        openList.UpdateItem(openArray[arrayX, arrayY]);
                        continue;
                    }
                    else
                    {
                        continue;
                    }
                }

                //priority sorted by heap
                PathStep step = new PathStep(neighbor, travelCost, heuristic);
                openList.Add(step);
                openCheck[arrayX, arrayY] = true;
                openArray[arrayX, arrayY] = step;
                parents[arrayX, arrayY]   = current.position;
            }
        }

finalize:
        if (found)
        {
            SingleLinkedList <Vec2I> list = new SingleLinkedList <Vec2I>();

            Vec2I current = EndPoint;
            while (current != StartPoint)
            {
                list.InsertFront(current);
                current = parents[current.x - StartPoint.x + maxDistance, current.y - StartPoint.y + maxDistance];
            }
            //list.InsertFront(current); //adds the starting point to the path
            path = list.ToArray();
            return(true);
        }

        return(false);
    }
Ejemplo n.º 15
0
        public override void UpdateFrame()
        {
            var keyboardState = WindowContext.Current.Window.KeyboardState;

            if (keyboardState.IsKeyDown(Key.R))
            {
                Reset();
            }

            if (StartMovement)
            {
                var speed = Speed;
                if (keyboardState[Key.ControlLeft])
                {
                    speed = speed * 0.1f;
                }

                var delta           = (float)Application.Current.UpdateCounter.Elapsed.TotalMilliseconds / 1000.0f;
                var movement        = direction * speed * delta;
                var updatedPosition = gfx.RelativeTranslation + new Vector3(movement.X, movement.Y, 0);

                var collision  = false;
                var ballRadius = gfx.RelativeScale.X / 2;

                if (updatedPosition.X + ballRadius > WorldSize.X / 2 ||
                    updatedPosition.X - ballRadius < -WorldSize.X / 2)
                {
                    Reset();
                    return;
                }

                if (updatedPosition.Y + ballRadius > WorldSize.Y / 2 ||
                    updatedPosition.Y - ballRadius < -WorldSize.Y / 2)
                {
                    direction.Y = -direction.Y;
                    collision   = true;
                }

                bool firstPlayCollision    = FirstPlayer.CollidesWithBall(updatedPosition.Xy, ballRadius);
                bool secondPlayerCollision = SecondPlayer.CollidesWithBall(updatedPosition.Xy, ballRadius);
                if (firstPlayCollision || secondPlayerCollision)
                {
                    if ((firstPlayCollision && direction.X < 0) || (secondPlayerCollision && direction.X > 0))
                    {
                        var player = firstPlayCollision ? FirstPlayer : SecondPlayer;
                        direction.X = -direction.X;
                        collision   = true;

                        var normalizedBounds = player.Bounds;
                        normalizedBounds.Center = Vector2.Zero;
                        var translatedDiff = player.Bounds.Center.Y;

                        var translatedBallPos        = gfx.RelativeTranslation.Y - translatedDiff;
                        var scaledPaddleCollisionPos = translatedBallPos / player.Bounds.HalfSize.Y; // 0..1
                        scaledPaddleCollisionPos *= 0.5f;
                        var posY    = AxMath.SinNorm(scaledPaddleCollisionPos / 4f);
                        var posX    = AxMath.CosNorm(scaledPaddleCollisionPos / 4f);
                        var pos     = new Vector2(posX, posY).Normalized();
                        var newDirX = AxMath.SetSign(pos.X, direction.X);
                        //var newDirY = AxMath.SetSign(pos.Y, direction.Y);
                        direction = new Vector2(newDirX, pos.Y);
                    }
                }

                if (collision)
                {
                    AudioManager.Default.PlayAsync("Audio/collision.rack.json");
                }
                else
                {
                    gfx.RelativeTranslation = updatedPosition;
                }
            }
        }