Ejemplo n.º 1
0
        private static bool ShouldMob(Entity self, EntityBeliefs ent)
        {
            var trace = new TraceLine(self.World);
            trace.Origin = ent.LastPos;
            trace.HitGeometry = true;
            trace.HitEntities = false;
            trace.HullSize = self.GetComponent<Collision>().Size;

            int survivors = 1;
            int zombies = 1;

            var it = new NearbyEntityEnumerator(self.World, ent.LastPos, MobRadius);
            while (it.MoveNext()) {
                var cur = it.Current;

                if (cur == self || cur == ent.Entity) continue;

                if (!cur.HasComponent<Human>() || !cur.HasComponent<Health>()) continue;
                if (!cur.GetComponent<Health>().IsAlive) continue;

                trace.Target = cur.Position2D;

                if (trace.GetResult().Hit) continue;

                if (cur.HasComponent<Survivor>()) {
                    survivors += cur.GetComponent<Health>().Value;
                } else {
                    zombies += cur.GetComponent<Health>().Value;
                }
            }

            return zombies <= MaxMobRatio * survivors;
        }
Ejemplo n.º 2
0
        public override IEnumerable<Action> GetActions()
        {
            yield return new DropItemAction(3f);

            var diff = Entity.World.Difference(Entity.Position2D, Target.LastPos);

            var trace = new TraceLine(World);
            trace.Origin = Target.LastPos;
            trace.HitGeometry = true;
            trace.HitEntities = false;
            trace.HullSize = Entity.GetComponent<Collision>().Size;

            bool closest = true;

            var it = new NearbyEntityEnumerator(World, Target.LastPos, diff.Length);
            while (it.MoveNext()) {
                var cur = it.Current;

                if (cur == Entity || !cur.HasComponent<Human>() || !cur.GetComponent<Health>().IsAlive) continue;

                trace.Target = cur.Position2D;

                if (trace.GetResult().Hit) continue;

                closest = false;
                break;
            }

            if (!closest) {
                yield return new MovementAction(diff.Normalized() * 128f);
            }

            if (diff.LengthSquared < 1.5f) {
                yield return new AttackAction(Target.Entity);
            }
        }
Ejemplo n.º 3
0
        private Entity EntityTrace(ref Vector2 vec)
        {
            NearbyEntityEnumerator it = new NearbyEntityEnumerator(
                    World, Origin + vec / 2.0f, vec.Length / 2.0f + 2.0f);

            float ratio = 1.0f;
            float dydx = vec.Y / vec.X;
            float dxdy = vec.X / vec.Y;

            Entity hitEnt = null;

            while (it.MoveNext()) {
                Entity ent = it.Current;
                if (ent.HasComponent<Collision>()) {
                    Collision col = ent.GetComponent<Collision>();
                    if (col.Model != CollisionModel.None &&
                        (HitEntityPredicate == null || HitEntityPredicate(ent))) {
                        Vector2 diff = World.Difference(Origin, ent.Position2D);

                        float lt = diff.X + col.Offset.X;
                        float rt = lt + col.Size.X;
                        float tp = diff.Y + col.Offset.Y;
                        float bt = tp + col.Size.Y;

                        if (lt < 0f && rt > 0f && tp < 0f && bt > 0f) {
                            hitEnt = ent;
                            ratio = 0f;
                            break;
                        }

                        if (vec.X != 0.0f) {
                            float dx = 0.0f;
                            bool hit = false;
                            if (vec.X > 0.0f && lt >= 0.0f && vec.X * ratio > lt) {
                                dx = lt;
                                hit = true;
                            } else if (vec.X < 0.0f && rt <= 0.0f && vec.X * ratio < rt) {
                                dx = rt;
                                hit = true;
                            }

                            if (hit) {
                                float y = dydx * dx;

                                if (y > tp && y < bt) {
                                    ratio = dx / vec.X;
                                    hitEnt = ent;
                                }
                            }
                        }

                        if (vec.Y != 0.0f) {
                            float dy = 0.0f;
                            bool hit = false;
                            if (vec.Y > 0.0f && tp >= 0.0f && vec.Y * ratio > tp) {
                                dy = tp;
                                hit = true;
                            } else if (vec.Y < 0.0f && bt <= 0.0f && vec.Y * ratio < bt) {
                                dy = bt;
                                hit = true;
                            }

                            if (hit) {
                                float x = dxdy * dy;

                                if (x > lt && x < rt) {
                                    ratio = dy / vec.Y;
                                    hitEnt = ent;
                                }
                            }
                        }
                    }
                }
            }

            if (hitEnt != null)
                vec *= ratio;

            return hitEnt;
        }
Ejemplo n.º 4
0
        public Vector2 TryMove(Vector2 move)
        {
            if (Model == CollisionModel.None)
                return Position2D + move;

            if (Model.HasFlag(CollisionModel.Entity)) {
                NearbyEntityEnumerator iter = new NearbyEntityEnumerator(Entity.World,
                    new Vector2(Position2D.X, Position2D.Y), 2.0f + move.Length);

                while (iter.MoveNext())
                    move = TryMove(iter.Current, move);
            }

            float xm = Position2D.X + move.X, ym = Position2D.Y + move.Y;

            float error = 1.0f / 32.0f;

            if (move.X != 0.0f) {
                float dydx = move.Y / move.X;

                float startX = move.X > 0.0f ? Right : Left;
                int startIX = (int) (move.X > 0.0f ? Math.Ceiling(startX) : Math.Floor(startX));
                float y = Position.Z + (startIX - startX) * dydx;

                int xa = Math.Sign(move.X);
                int wxa = (move.X > 0.0f ? -1 : 0);
                int sxa = (move.X > 0.0f ? 0 : -1);
                int xe = (int) (move.X > 0.0f ? Math.Ceiling(startX + move.X) : Math.Floor(startX + move.X));

                Face face = move.X > 0.0f ? Face.East : Face.West;

                Block blk = null;

                for (int ix = startIX; ix != xe; ix += xa, y += xa * dydx) {
                    int wx = (ix + wxa) - (int) Math.Floor((double) (ix + wxa) / World.Width) * World.Width;
                    int sx = (ix + sxa) - (int) Math.Floor((double) (ix + sxa) / World.Width) * World.Width;

                    int minY = (int) Math.Floor(y + Offset.Y + error);
                    int maxY = (int) Math.Floor(y + Offset.Y + Size.Y - error);

                    for (int iy = minY; iy <= maxY; ++iy) {
                        int wy = iy - (int) Math.Floor((double) iy / World.Height) * World.Height;

                        if (blk == null || wx < blk.X || wy < blk.Y ||
                                wx >= blk.X + blk.Width || wy >= blk.Y + blk.Height)
                            blk = World.GetBlock(wx, wy);

                        bool hit = false;

                        Tile tw = blk[wx, wy];

                        hit = tw.IsWallSolid(face);

                        if (!hit) {
                            if (sx < blk.X || wy < blk.Y ||
                                    sx >= blk.X + blk.Width || wy >= blk.Y + blk.Height)
                                blk = World.GetBlock(sx, wy);

                            Tile ts = blk[sx, wy];

                            hit = (iy > minY && ts.IsWallSolid(Face.North) && !tw.IsWallSolid(Face.North)) ||
                                (iy < maxY && ts.IsWallSolid(Face.South) && !tw.IsWallSolid(Face.South));
                        }

                        if (hit) {
                            xm = move.X > 0 ? ix - Offset.X - Size.X : ix - Offset.X;
                            ix = xe - xa;
                            break;
                        }
                    }
                }
            }

            if (move.Y != 0.0f) {
                float dxdy = move.X / move.Y;

                float startY = move.Y > 0.0f ? Bottom : Top;
                int startIY = (int) (move.Y > 0.0f ? Math.Ceiling(startY) : Math.Floor(startY));
                float x = Position.X + (startIY - startY) * dxdy;

                int ya = Math.Sign(move.Y);
                int wya = (move.Y > 0.0f ? -1 : 0);
                int sya = (move.Y > 0.0f ? 0 : -1);
                int ye = (int) (move.Y > 0.0f ? Math.Ceiling(startY + move.Y) : Math.Floor(startY + move.Y));

                Face face = move.Y > 0.0f ? Face.South : Face.North;

                Block blk = null;

                for (int iy = startIY; iy != ye; iy += ya, x += ya * dxdy) {
                    int wy = (iy + wya) - (int) Math.Floor((double) (iy + wya) / World.Height) * World.Height;
                    int sy = (iy + sya) - (int) Math.Floor((double) (iy + sya) / World.Height) * World.Height;

                    int minX = (int) Math.Floor(x + Offset.X + error);
                    int maxX = (int) Math.Floor(x + Offset.X + Size.X - error);

                    for (int ix = minX; ix <= maxX; ++ix) {
                        int wx = ix - (int) Math.Floor((double) ix / World.Width) * World.Width;

                        if (blk == null || wx < blk.X || wy < blk.Y ||
                                wx >= blk.X + blk.Width || wy >= blk.Y + blk.Height)
                            blk = World.GetBlock(wx, wy);

                        bool hit = false;

                        Tile tw = blk[wx, wy];

                        hit = tw.IsWallSolid(face);

                        if (!hit) {
                            if (wx < blk.X || sy < blk.Y ||
                                    wx >= blk.X + blk.Width || sy >= blk.Y + blk.Height)
                                blk = World.GetBlock(wx, sy);

                            Tile ts = blk[wx, sy];

                            hit = (ix > minX && ts.IsWallSolid(Face.West) && !tw.IsWallSolid(Face.West)) ||
                                (ix < maxX && ts.IsWallSolid(Face.East) && !tw.IsWallSolid(Face.East));
                        }

                        if (hit) {
                            ym = move.Y > 0 ? iy - Offset.Y - Size.Y : iy - Offset.Y;
                            iy = ye - ya;
                            break;
                        }
                    }
                }
            }

            return new Vector2(xm, ym);
        }
Ejemplo n.º 5
0
        public void Repel(Movement movement, double dt)
        {
            NearbyEntityEnumerator iter = new NearbyEntityEnumerator(Entity.World,
                new Vector2(Position2D.X, Position2D.Y), 2.0f);

            while (iter.MoveNext()) {
                var obstacle = iter.Current;

                if (obstacle == Entity || !obstacle.HasComponent<Collision>())
                    continue;

                var that = obstacle.GetComponent<Collision>();

                if (!that.Model.HasFlag(CollisionModel.Entity | CollisionModel.Repel))
                    continue;

                Vector2 diff = World.Difference(Position2D, that.Position2D);

                float ar = (float) Math.Sqrt(this.Size.X * this.Size.X * 0.25 + this.Size.Y * this.Size.Y * 0.25);
                float br = (float) Math.Sqrt(that.Size.X * that.Size.X * 0.25 + that.Size.Y * that.Size.Y * 0.25);

                if (ar + br < diff.Length) continue;

                float mag = Math.Min(1f, (float) ((ar + br) * dt) / diff.LengthSquared);

                movement.Velocity -= diff.Normalized() * mag;
            }
        }
Ejemplo n.º 6
0
        public override void OnMouseButtonUp(MouseButtonEventArgs e)
        {
            var pos = Camera.ScreenToWorld(new Vector2(e.X, e.Y) / _upScale, .5f);

            if (e.Button == MouseButton.Left && _isSelecting) {
                var diff = World.Difference(pos, _selectionStart);

                _isSelecting = false;

                if (diff.LengthSquared < 0.25f) {
                    foreach (var ent in World.Entities) {
                        var human = ent.GetComponentOrNull<Human>();
                        if (human == null || !human.IsSelected) continue;

                        human.Deselect();
                    }

                    var best = new NearbyEntityEnumerator(World, pos, 2f)
                        .Where(x => x.HasComponent<Survivor>())
                        .OrderBy(x => World.Difference(pos, x.Position2D).LengthSquared)
                        .FirstOrDefault();

                    if (best != null) {
                        best.GetComponent<Human>().Select();
                    }
                } else {
                    if (diff.X < 0) {
                        var temp = _selectionStart.X;
                        _selectionStart.X = pos.X;
                        pos.X = temp;
                        diff.X = -diff.X;
                    }
                    
                    if (diff.Y < 0) {
                        var temp = _selectionStart.Y;
                        _selectionStart.Y = pos.Y;
                        pos.Y = temp;
                        diff.Y = -diff.Y;
                    }

                    foreach (var ent in World.Entities) {
                        var human = ent.GetComponentOrNull<Survivor>();
                        if (human == null || human.IsSelected || !human.Health.IsAlive) continue;

                        var edif = World.Difference(pos, ent.Position2D);

                        if (edif.X < 0 || edif.Y < 0 || edif.X > diff.X || edif.Y > diff.Y) continue;

                        human.Select();
                    }
                }
            }
        }