예제 #1
0
        void ProcessWorldEvent(ZombieAgent zombie, WorldEvent ev)
        {
            if (ev == null)
            {
                return;
            }

            var dist = Vector3.Distance(zombie.pos, ev.Pos);

            if (dist <= ev.Radius)
            {
                Vector3 soundDir = new Vector3();
                soundDir.x = _prng.Get(-1.0f, 1.0f);
                soundDir.z = _prng.Get(-1.0f, 1.0f);

                // Pick a random position within 75% of the radius.
                soundDir.Normalize();
                soundDir *= (dist * 0.75f);

                zombie.targetPos = ev.Pos + soundDir;
                zombie.target    = _worldZones.FindByPos2D(zombie.targetPos);

                zombie.state = ZombieAgent.State.Investigating;
            }
        }
예제 #2
0
        void UpdateInactiveZombie(ZombieAgent zombie, float dt, WorldEvent ev)
        {
            zombie.simulationTime += dt;

            ProcessWorldEvent(zombie, ev);
            UpdateTarget(zombie);
            UpdateApproachTarget(zombie, dt);
        }
예제 #3
0
        private void UpdateInactiveZombie(ZombieAgent zombie, float dt, WorldEvent ev)
        {
            UpdateTarget(zombie, ev);

            zombie.dir = zombie.targetPos - zombie.pos;
            zombie.dir.Normalize();

            float speed = _worldState.GetZombieSpeed() * dt;

            zombie.pos = Vector3.MoveTowards(zombie.pos, zombie.targetPos, speed);
        }
예제 #4
0
        private void UpdateTarget(ZombieAgent zombie, WorldEvent ev)
        {
            if (ev != null)
            {
                var dist = Vector3.Distance(zombie.pos, ev.Pos);
                if (dist <= ev.Radius)
                {
                    Vector3 soundDir = new Vector3();
                    soundDir.x = _prng.Get(-1.0f, 1.0f);
                    soundDir.z = _prng.Get(-1.0f, 1.0f);

                    soundDir.Normalize();
                    soundDir *= (dist * 0.75f);

                    zombie.targetPos = ev.Pos + soundDir;

#if DEBUG
                    Log.Out("Reacting to sound at {0}", ev.Pos);
#endif
                    return;
                }
            }

            // If we have an activate target wait for arrival.
            if (!zombie.ReachedTarget())
            {
                return;
            }

            if (_worldState.IsBloodMoon())
            {
                zombie.target = _playerZones.GetRandomClosest(zombie.pos, _prng, 200.0f);
                if (zombie.target == null)
                {
                    zombie.target = GetNextTarget(zombie);
                }
            }
            else
            {
                zombie.target = GetNextTarget(zombie);
            }

            zombie.targetPos = GetTargetPos(zombie.target);
        }
예제 #5
0
        void UpdateInactiveZombies(float dt)
        {
            // Repopulate
            lock (_inactiveZombies)
            {
                lock (_inactiveQueue)
                {
                    while (_inactiveQueue.Count > 0)
                    {
                        var zombie = _inactiveQueue.Dequeue();
                        _inactiveZombies.Add(zombie);
                    }
                }
            }

            // Simulate
            int activatedZombies = 0;
            int maxUpdates       = _maxZombies;
            int maxPerZone       = MaxZombiesPerZone();

            WorldEvent ev = null;

            lock (_worldEvents)
            {
                if (_worldEvents.Count > 0)
                {
                    ev = _worldEvents.Dequeue();
                }
            }

            for (int i = 0; ; i++)
            {
                lock (_inactiveZombies)
                {
                    if (i >= _inactiveZombies.Count)
                    {
                        break;
                    }

                    var world = GameManager.Instance.World;
                    if (world == null)
                    {
                        Log.Out("[WalkerSim] World no longer exists, bailing");
                        break;
                    }

                    bool removeZombie    = false;
                    bool activatedZombie = false;

                    ZombieAgent zombie = _inactiveZombies[i];

                    UpdateInactiveZombie(zombie, dt, ev);

                    //Log.Out("New Zombie Position: {0}, Target: {1}", zombie.pos, zombie.targetPos);

                    if (!CanSpawnActiveZombie())
                    {
                        continue;
                    }

                    List <PlayerZone> zones = _playerZones.FindAllByPos2D(zombie.pos);
                    if (zones.Count <= 0)
                    {
                        continue;
                    }

                    foreach (var zone in zones)
                    {
                        var player = world.GetEntity(zone.entityId) as EntityPlayer;

                        // Use players spawn border.
                        if (zone.IsInside2D(zombie.pos))
                        {
                            if (!zone.InsideSpawnArea2D(zombie.pos))
                            {
                                removeZombie = true;
                                continue;
                            }
                        }
                        else
                        {
                            continue;
                        }

                        if (zone.numZombies >= maxPerZone)
                        {
#if DEBUG
                            Log.Out("[WalkerSim] Zone {0} is full: {1} / {2}", zombie.pos, zone.numZombies, maxPerZone);
#endif
                            continue;
                        }

                        RequestActiveZombie(zombie, zone);
                        activatedZombie = true;
                        activatedZombies++;
                        break;
                    }

                    // Zombie inside one or more zones will be always removed.
                    if (activatedZombie)
                    {
                        removeZombie = true;
                    }

                    if (removeZombie)
                    {
                        _inactiveZombies.RemoveAt(i);
                        i--;

                        // If the zombie was not activated begin a new cycle.
                        if (!activatedZombie)
                        {
                            RespawnInactiveZombie(zombie);
                        }

                        // NOTE: This should never happen.
                        if (_inactiveZombies.Count == 0)
                        {
                            Log.Error("Population is empty, this should not happen.");
                            break;
                        }
                    }
                }
            }

#if DEBUG
            if (activatedZombies > 0)
            {
                Log.Out("[WalkerSim] Activated {0} zombies", activatedZombies);
            }
#endif
        }