public static Banner GetClosestBanner(Players.Player p, Vector3Int currentPos)
        {
            Banner closest  = null;
            float  distance = float.MaxValue;

            var banners = BannerTracker.GetBanners();

            for (int i = 0; i < banners.Count; i++)
            {
                var banner = banners.GetValueAtIndex(i);

                if (banner.Owner == p)
                {
                    var bannerDistance = Vector3.Distance(currentPos.Vector, banner.KeyLocation.Vector);

                    if (closest == null)
                    {
                        closest  = banner;
                        distance = bannerDistance;
                    }
                    else
                    {
                        if (bannerDistance < distance)
                        {
                            closest  = banner;
                            distance = bannerDistance;
                        }
                    }
                }
            }

            return(closest);
        }
示例#2
0
        public void Update()
        {
            if (!World.Initialized || AIManager.IsBusy())
            {
                return;
            }

            WorldSettings wsettings         = ServerManager.WorldSettings;
            bool          toSpawnZombies    = wsettings.ZombiesEnabled && (TimeCycle.ShouldSpawnMonsters || wsettings.MonstersDayTime);
            int           monsterMultiplier = wsettings.MonstersDoubled ? 2 : 1;
            double        timeSinceStart    = Pipliz.Time.SecondsSinceStartDouble;

            var banners = BannerTracker.GetBanners();

            for (int i = 0; i < banners.Count; i++)
            {
                Banner banner = banners.GetValueAtIndex(i);

                if (banner == null || !banner.KeyLocation.IsValid)
                {
                    continue;
                }

                Colony colony = Colony.Get(banner.Owner);

                if (toSpawnZombies)
                {
                    float zombiesMax = GetMaxZombieCount(colony.FollowerCount) * monsterMultiplier;

                    if (zombiesMax > 0f)
                    {
                        if (MonsterTracker.MonstersPerPlayer(banner.Owner) < zombiesMax)
                        {
                            if (colony.InSiegeMode)
                            {
                                if (timeSinceStart - colony.LastSiegeModeSpawn < siegeModeCooldown)
                                {
                                    continue;
                                }
                                else
                                {
                                    colony.LastSiegeModeSpawn = timeSinceStart;
                                }
                            }

                            SpawnZombie(colony, banner, GetMosterType(colony.FollowerCount, zombiesMax));
                        }
                    }
                    else
                    {
                        colony.OnZombieSpawn(true);
                    }
                }
                else
                {
                    colony.OnZombieSpawn(true);
                }
            }
        }
示例#3
0
 public override void OnResearchComplete(ScienceManagerPlayer manager, EResearchCompletionReason reason)
 {
     manager.Player.GetTempValues(true).Set("pipliz.bannersaferadius", 100);
     if (reason == EResearchCompletionReason.ProgressCompleted)
     {
         BannerTracker.SendPacket(manager.Player);
     }
 }
示例#4
0
        public static AIColony AddColony(Banner banner)
        {
            AIColony newAiColony = new AIColony(banner.Owner);

            BannerTracker.Add(banner.KeyLocation, BuiltinBlocks.Banner, banner.Owner);
            Instance.Colonies.Add(newAiColony);

            return(newAiColony);
        }
示例#5
0
        public override Vector3Int GetJobLocation()
        {
            var currentPos = usedNPC.Position;

            if (_playerState.CallToArmsEnabled && _weapon != null)
            {
                _target = MonsterTracker.Find(currentPos, _weapon.range, _weapon.shootDamage);

                if (_target != null)
                {
                    return(currentPos);
                }

                _target = MonsterTracker.Find(currentPos, CALL_RAD, _weapon.shootDamage);

                if (_target != null)
                {
                    var ranged = _weapon.range - 5;

                    if (ranged < 0)
                    {
                        ranged = 1;
                    }

                    position = new Vector3Int(_target.Position).Add(ranged, 0, ranged);
                    position = AIManager.ClosestPosition(position, currentPos);

                    if (!AIManager.CanStandAt(position))
                    {
                        _tmpVals.Set(COOLDOWN_KEY, _weapon.cooldownMissingItem);
                        _waitingFor++;
                    }
                    else
                    {
                        return(position);
                    }
                }
                else
                {
                    _tmpVals.Set(COOLDOWN_KEY, _weapon.cooldownMissingItem);
                    _waitingFor++;
                }
            }

            if (_waitingFor > 10)
            {
                var banner = BannerTracker.GetClosest(usedNPC.Colony.Owner, currentPos);

                if (banner != null)
                {
                    return(banner.KeyLocation);
                }
            }

            return(currentPos);
        }
示例#6
0
        public static bool OnTryChangeBlockUser(ModLoader.OnTryChangeBlockUserData userData)
        {
            Players.Player requestedBy = userData.requestedBy;
            Vector3Int     position    = userData.VoxelToChange;
            Vector3Int     spawn       = TerrainGenerator.GetSpawnLocation();
            int            ox          = position.x - spawn.x;
            int            oz          = position.z - spawn.z;

            if (((ox >= 0 && ox <= SpawnProtectionRangeXPos) || (ox < 0 && ox >= -SpawnProtectionRangeXNeg)) && ((oz >= 0 && oz <= SpawnProtectionRangeZPos) || (oz < 0 && oz >= -SpawnProtectionRangeZNeg)))
            {
                if (!PermissionsManager.HasPermission(requestedBy, PERMISSION_SPAWN_CHANGE))
                {
                    Chat.Send(requestedBy, "<color=red>You don't have permission to change the spawn area!</color>");
                    // TODO add counter and report to admins or auto-kick
                    return(false);
                }
            }
            else
            {
                Banner homeBanner = BannerTracker.Get(requestedBy);
                if (homeBanner != null)
                {
                    Vector3Int homeBannerLocation = homeBanner.KeyLocation;
                    if (System.Math.Abs(homeBannerLocation.x - position.x) <= BannerProtectionRangeX && System.Math.Abs(homeBannerLocation.z - position.z) <= BannerProtectionRangeZ)
                    {
                        return(true);
                    }
                }
                int checkRangeX = BannerProtectionRangeX;
                int checkRangeZ = BannerProtectionRangeZ;
                if (userData.typeToBuild == BlockTypes.Builtin.BuiltinBlocks.Banner)
                {
                    checkRangeX *= 2;
                    checkRangeZ *= 2;
                }
                foreach (Banner b in BannerTracker.GetBanners())
                {
                    Vector3Int bannerLocation = b.KeyLocation;
                    if (System.Math.Abs(bannerLocation.x - position.x) <= checkRangeX && System.Math.Abs(bannerLocation.z - position.z) <= checkRangeZ)
                    {
                        if (b.Owner != requestedBy && !PermissionsManager.HasPermission(requestedBy, PERMISSION_BANNER_PREFIX + b.Owner.ID.steamID))
                        {
                            Chat.Send(requestedBy, "<color=red>You don't have permission to change this area!</color>");
                            return(false);
                        }
                        break;
                    }
                }
            }
            return(true);
        }
 public static void AfterNetworkSetup()
 {
     new Thread(() => {
         Thread.CurrentThread.IsBackground = true;
         Log.Write("Started kingdom spawner thread");
         while (true)
         {
             Thread.Sleep(DelayBetweenPlacingAttempts);
             try {
                 if (KingdomsTracker.Count < MaxNumberOfKingdoms)
                 {
                     for (int c = 0; c < NumOfSpotsToCheckPerAttempt; c++)
                     {
                         var kingdomPosition = GetRandomSpot(MaxRangeFromSpawn);
                         var farmSize        = 1 + Pipliz.Random.Next(NpcFarmBuilder.MAX_SIZE);
                         var npcKingdom      = NpcFarm.Create(kingdomPosition, farmSize);
                         var closestBanner   = BannerTracker.GetClosest(kingdomPosition, MinDistanceToBanners);
                         if (closestBanner == null)
                         {
                             LoadChunksBlocking(npcKingdom.GetPrimaryChunkPositions());
                             if (npcKingdom.IsAreaClear())
                             {
                                 LoadChunksBlocking(npcKingdom.GetTotalChunkPositions());
                                 npcKingdom.InitNew();
                                 if (KingdomsTracker.Count >= MaxNumberOfKingdoms)
                                 {
                                     Log.Write($"Reached maximum number ({MaxNumberOfKingdoms}) of kingdoms");
                                 }
                                 break;
                             }
                             try {
                                 currentlyUsedChunksLock.EnterWriteLock();
                                 currentlyUsedChunks.Clear();
                             } finally {
                                 if (currentlyUsedChunksLock.IsWriteLockHeld)
                                 {
                                     currentlyUsedChunksLock.ExitWriteLock();
                                 }
                             }
                         }
                         Thread.Sleep(DelayBetweenSpotChecks);
                     }
                 }
             } catch (Exception exception) {
                 Log.WriteError($"Exception in kingdom update thread; {exception.Message}");
             }
         }
     }).Start();
 }
示例#8
0
        protected override bool RunCommand(Players.Player ply, string[] args, NetworkID target)
        {
            if (PermissionsManager.CheckAndWarnPermission(ply, "locate"))
            {
                var player = Players.GetPlayer(target);

                var banner = (from b in BannerTracker.GetBanners()
                              where b.Owner == player
                              select b).FirstOrDefault();

                Chat.sendSilent(ply,
                                banner != null
                        ? $"{player.Name} has a banner at x:{banner.KeyLocation.x} y:{banner.KeyLocation.y} z:{banner.KeyLocation.z}"
                        : $"{player.Name} doesn't have a banner", Chat.ChatColour.magenta);
            }
            return(true);
        }
        public void CalculateColoniesThatRequireMonsters()
        {
            int bannerCount = BannerTracker.GetCount();

            coloniesRequiringZombies.Clear();

            for (int i = 0; i < bannerCount; i++)
            {
                Banner banner;

                if (!BannerTracker.TryGetAtIndex(i, out banner) || !banner.KeyLocation.IsValid)
                {
                    continue;
                }

                Colony colony = Colony.Get(banner.Owner);

                if (colony.FollowerCount == 0)
                {
                    colony.OnZombieSpawn(true);
                    continue;
                }

                var ps = PlayerState.GetPlayerState(banner.Owner);
                IDifficultySetting difficultyColony = colony.Owner.DifficultySetting;

                if (!MonsterManager.BossActive)
                {
                    if (!ps.MonstersEnabled || !difficultyColony.ShouldSpawnZombies(colony))
                    {
                        colony.OnZombieSpawn(true);
                        continue;
                    }
                }

                double nextZombieSpawnTime = NextZombieSpawnTimes.GetValueOrDefault(colony, 0.0);

                if (nextZombieSpawnTime > Pipliz.Time.SecondsSinceStartDoubleThisFrame)
                {
                    continue;
                }

                if (colony.InSiegeMode)
                {
                    if (Pipliz.Time.SecondsSinceStartDoubleThisFrame - colony.LastSiegeModeSpawn < siegeModeCooldown)
                    {
                        continue;
                    }
                    else
                    {
                        colony.LastSiegeModeSpawn = Pipliz.Time.SecondsSinceStartDoubleThisFrame;
                    }
                }

                // lagging behind, or no cooldown set: teleport to current time
                if (Pipliz.Time.SecondsSinceStartDoubleThisFrame - nextZombieSpawnTime > MONSTERS_DELAY_THRESHOLD_SECONDS)
                {
                    NextZombieSpawnTimes[colony] = Pipliz.Time.SecondsSinceStartDoubleThisFrame;
                }

                coloniesRequiringZombies.Add(TupleStruct.Create(colony, banner));
            }
        }
示例#10
0
        public static bool EvaluateSettlers(Players.Player p)
        {
            var update = false;

            if (p.IsConnected)
            {
                var colony = Colony.Get(p);
                var state  = PlayerState.GetPlayerState(p);

                if (state.NextGenTime == 0)
                {
                    state.NextGenTime = Time.SecondsSinceStartDouble +
                                        Random.Next(8,
                                                    16 - Pipliz.Math.RoundToInt(p.GetTempValues(true)
                                                                                .GetOrDefault(PandaResearch.GetResearchKey(PandaResearch.TimeBetween),
                                                                                              0f))) * TimeCycle
                                        .SecondsPerHour;
                }

                if (Time.SecondsSinceStartDouble > state.NextGenTime && colony.FollowerCount >= MAX_BUYABLE)
                {
                    var chance =
                        p.GetTempValues(true)
                        .GetOrDefault(PandaResearch.GetResearchKey(PandaResearch.SettlerChance), 0f) +
                        state.Difficulty.AdditionalChance;

                    chance += SettlerEvaluation.SpawnChance(p, colony, state);

                    var rand = Random.NextFloat();

                    if (chance > rand)
                    {
                        var addCount = Math.Floor(state.MaxPerSpawn * chance);

                        // if we lost alot of colonists add extra to help build back up.
                        if (colony.FollowerCount < state.HighestColonistCount)
                        {
                            var diff = state.HighestColonistCount - colony.FollowerCount;
                            addCount += Math.Floor(diff * .25);
                        }

                        try
                        {
                            var skillChance = p.GetTempValues(true)
                                              .GetOrDefault(PandaResearch.GetResearchKey(PandaResearch.SkilledLaborer),
                                                            0f);

                            var numbSkilled = 0;

                            rand = Random.NextFloat();

                            try
                            {
                                if (skillChance > rand)
                                {
                                    numbSkilled =
                                        state.Rand.Next(1,
                                                        2 + Pipliz.Math.RoundToInt(p.GetTempValues(true)
                                                                                   .GetOrDefault(PandaResearch.GetResearchKey(PandaResearch.NumberSkilledLaborer),
                                                                                                 0f)));
                                }
                            }
                            catch (Exception ex)
                            {
                                PandaLogger.Log("NumberSkilledLaborer");
                                PandaLogger.LogError(ex);
                            }


                            if (addCount > 0)
                            {
                                if (addCount > 30)
                                {
                                    addCount = 30;
                                }

                                var reason = string.Format(SettlerReasoning.GetSettleReason(), addCount);

                                if (numbSkilled > 0)
                                {
                                    if (numbSkilled == 1)
                                    {
                                        reason += string.Format(" {0} of them is skilled!", numbSkilled);
                                    }
                                    else
                                    {
                                        reason += string.Format(" {0} of them are skilled!", numbSkilled);
                                    }
                                }

                                PandaChat.Send(p, reason, ChatColor.magenta);
                                var playerPos = new Vector3Int(p.Position);

                                for (var i = 0; i < addCount; i++)
                                {
                                    var newGuy = new NPCBase(NPCType.GetByKeyNameOrDefault("pipliz.laborer"),
                                                             BannerTracker.GetClosest(p, playerPos).KeyLocation.Vector,
                                                             colony);

                                    SettlerInventory.GetSettlerInventory(newGuy);
                                    newGuy.GetTempValues().Set(ISSETTLER, true);

                                    if (i <= numbSkilled)
                                    {
                                        var npcTemp = newGuy.GetTempValues(true);
                                        npcTemp.Set(GameLoader.ALL_SKILLS, state.Rand.Next(1, 10) * 0.002f);
                                    }

                                    update = true;
                                    ModLoader.TriggerCallbacks(ModLoader.EModCallbackType.OnNPCRecruited, newGuy);
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            PandaLogger.Log("SkilledLaborer");
                            PandaLogger.LogError(ex);
                        }

                        if (colony.FollowerCount > state.HighestColonistCount)
                        {
                            state.HighestColonistCount = colony.FollowerCount;
                        }
                    }


                    state.NextGenTime = Time.SecondsSinceStartDouble +
                                        Random.Next(8,
                                                    16 - Pipliz.Math.RoundToInt(p.GetTempValues(true)
                                                                                .GetOrDefault(PandaResearch.GetResearchKey(PandaResearch.TimeBetween),
                                                                                              0f))) * TimeCycle
                                        .SecondsPerHour;

                    colony.SendUpdate();
                }
            }

            return(update);
        }
示例#11
0
        public static MonsterSpawner.ESpawnResult TryGetSpawnLocation(Banner primaryBanner, float maxSpawnWalkDistance, out Vector3Int positionFinal)
        {
            Vector3Int bannerPos   = primaryBanner.KeyLocation;
            var        bannerList  = BannerTracker.GetBanners();
            int        safeRadius  = primaryBanner.SafeRadius;
            int        spawnRadius = Pipliz.Math.RoundToInt(Pipliz.Math.Min(maxSpawnWalkDistance, primaryBanner.MaxSpawnRadius));

            positionFinal = Vector3Int.invalidPos;

            for (int spawnTry = 0; spawnTry < MAX_TRIES; spawnTry++)
            {
                Vector3Int possiblePosition;
                Vector3Int dif;

                while (true)
                {
                    possiblePosition.x = bannerPos.x + Pipliz.Random.Next(-spawnRadius, spawnRadius);
                    possiblePosition.z = bannerPos.z + Pipliz.Random.Next(-spawnRadius, spawnRadius);
                    possiblePosition.y = Pipliz.Math.RoundToInt(TerrainGenerator.UsedGenerator.GetHeight(possiblePosition.x, possiblePosition.z));

                    dif = bannerPos - possiblePosition;

                    if (dif.MaxPartAbs > safeRadius && Pipliz.Math.Abs(dif.x) + Pipliz.Math.Abs(dif.z) < spawnRadius)
                    {
                        break;
                    }
                }

                for (int idxBanner = 0; idxBanner < bannerList.Count; idxBanner++)
                {
                    var    otherBanner = bannerList.GetValueAtIndex(idxBanner);
                    Colony otherColony = Colony.Get(otherBanner.Owner);

                    if (otherColony.FollowerCount > 0 && (otherBanner.KeyLocation - possiblePosition).MaxPartAbs <= otherBanner.SafeRadius)
                    {
                        goto NEXT_TRY;
                    }
                }

                if (!AIManager.Loaded(possiblePosition))
                {
                    return(MonsterSpawner.ESpawnResult.NotLoaded);
                }

                for (int idxOffset = 0; idxOffset < offsets.Length; idxOffset++)
                {
                    Vector3Int positionAITest = possiblePosition.Add(0, offsets[idxOffset], 0);

                    if (AIManager.CanStandAt(positionAITest))
                    {
                        positionFinal = positionAITest;
                        return(MonsterSpawner.ESpawnResult.Success);
                    }
                }

NEXT_TRY:
                continue;
            }

            return(MonsterSpawner.ESpawnResult.Fail);
        }
示例#12
0
 private ITrackableBlock GetScoutBanner()
 {
     return(BannerTracker.Get(GetColonyOwner()));
 }
示例#13
0
        public override void OnNPCAtJob(ref NPCBase.NPCState state)
        {
            state.SetCooldown(2);

            getScoutChunkManager().RemoveDoublePositions();

            if (Activity == ScoutActivity.Scouting)
            {
                getScoutChunkManager().RegisterPositionScouted(currentDestination.ToChunk());
            }

            if (Activity == ScoutActivity.Walking)
            {
                SetActivity(ScoutActivity.Scouting);
                Vector3Int positionToScout = NPC.Position;
                getScoutChunkManager().RegisterPositionScouted(positionToScout);
                state.SetCooldown(2);
            }

            //WriteLog("OnNPCAtJob");

            if (!StockedUp)
            {
                StockedUp = true;
                SetActivity(ScoutActivity.Scouting);
            }

            var commenceBaseBuild = false;

            if (!IsOutsideMinimumRange(NPC.Position, BannerTracker.Get(GetColonyOwner())))
            {
                return;
            }

            //Check the surrounding area and calculate its average flatness, to determine if it's suitable for a base
            var suitability = calculateAreaSuitability();

            switch (suitability)
            {
            case Suitability.None:
                break;

            case Suitability.Bad:
                break;

            case Suitability.Decent:
                break;

            case Suitability.Good:
                WriteLog("Suitable location found for new base.");
                commenceBaseBuild = true;
                break;

            case Suitability.Excellent:
                break;

            default:
                Log.WriteWarning("Invalid Area Suitability received: {0}", suitability);
                break;
            }

            //Only actually build base if the area is suitable enough
            if (commenceBaseBuild)
            {
                PrepareBase();
            }
        }
示例#14
0
        protected override void ReconsiderDecision()
        {
            switch (decision.GoalType)
            {
            case ZombieGoal.Banner:

                if ((!decision.IsValid || decision.PathDistance > MinDistanceToReconsiderBanner) &&
                    (ConsiderPlayerTarget(ref decision) || ConsiderNPCTarget(ref decision)))
                {
                    return;
                }

                if (!BannerTracker.Contains(decision.GoalLocation))
                {
                    var closest = BannerTracker.GetClosest(originalGoal, position);

                    if (closest != null &&
                        AIManager.ZombiePathFinder.TryFindPath(position, closest.KeyLocation, out var path,
                                                               2000000000) == EPathFindingResult.Success)
                    {
                        decision.Clear();
                        decision = new ZombieDecision(this, path);
                        return;
                    }

                    SetCooldown(3.0);
                }

                break;

            case ZombieGoal.NPC:

                if (!decision.IsValid || decision.PathDistance > MinDistanceToReconsiderNPC)
                {
                    if (ConsiderPlayerTarget(ref decision))
                    {
                        return;
                    }

                    NPCBase nPCBase;

                    if (NPCTracker.TryGetNear(position.Vector, MaxRadiusToNPCToConsider, out nPCBase))
                    {
                        if (decision.IsGoingTo(nPCBase) && IsMovingTargetPathOkay(nPCBase.Position))
                        {
                            decision.Reconsidered();
                            return;
                        }

                        if (AIManager.ZombiePathFinder.TryFindPath(position, nPCBase.Position, out var path2,
                                                                   decision.PathDistance / 2) ==
                            EPathFindingResult.Success)
                        {
                            decision.Clear();
                            decision = new ZombieDecision(this, nPCBase, path2);
                        }
                    }

                    if (ConsiderBannerTarget(ref decision))
                    {
                        return;
                    }
                }

                break;

            case ZombieGoal.Player:

                if (Players.FindClosestAlive(position.Vector, out var player, out var num))
                {
                    if (decision.IsGoingTo(player) && IsMovingTargetPathOkay(player.VoxelPosition))
                    {
                        decision.Reconsidered();
                        return;
                    }

                    if (num < MaxSqrdRadiusToPlayerToConsider && AIManager.CanStandAt(player.VoxelPosition) &&
                        AIManager.ZombiePathFinder.TryFindPath(position, player.VoxelPosition, out var path3,
                                                               2000000000) == EPathFindingResult.Success)
                    {
                        decision.Clear();
                        decision = new ZombieDecision(this, player, path3);
                    }
                }

                if (ConsiderNPCTarget(ref decision) || ConsiderBannerTarget(ref decision))
                {
                    return;
                }

                break;


            default:

                if (ConsiderPlayerTarget(ref decision) || ConsiderNPCTarget(ref decision) ||
                    ConsiderBannerTarget(ref decision))
                {
                    return;
                }

                break;
            }

            decision.Reconsidered();
        }
示例#15
0
        public static void EvaluateBanners()
        {
            if (!GameLoader.WorldLoaded)
            {
                return;
            }

            _bannerCounts.Clear();

            var banners = BannerTracker.GetCount();

            if (banners > 0)
            {
                for (var i = 0; i < banners; i++)
                {
                    if (BannerTracker.TryGetAtIndex(i, out var banner))
                    {
                        if (!_bannerCounts.ContainsKey(banner.Owner))
                        {
                            _bannerCounts.Add(banner.Owner, 1);
                        }
                        else
                        {
                            _bannerCounts[banner.Owner]++;
                        }
                    }
                }
            }

            foreach (var p in _bannerCounts)
            {
                var ps = PlayerState.GetPlayerState(p.Key);

                if (ps == null)
                {
                    continue;
                }

                var numberOfBanners = p.Key.GetTempValues(true)
                                      .GetOrDefault(PandaResearch.GetLevelKey(PandaResearch.Settlement), 0) + 1;

                var inv        = Inventory.GetInventory(p.Key);
                var sockBanner = Stockpile.GetStockPile(p.Key).AmountContained(BuiltinBlocks.Banner);

                var inventoryBanners = 0;

                if (inv != null)
                {
                    foreach (var item in inv.Items)
                    {
                        if (item.Type == BuiltinBlocks.Banner)
                        {
                            inventoryBanners = item.Amount;
                        }
                    }
                }

                var totalBanners = p.Value + sockBanner + inventoryBanners;

#if Debug
                PandaLogger.Log($"Number of research banners: {numberOfBanners}");
                PandaLogger.Log($"Number of banners: {p.Value}");
                PandaLogger.Log($"Number of stockpile banners: {sockBanner}");
                PandaLogger.Log($"Number of Inventory banners: {inventoryBanners}");
                PandaLogger.Log($"Total banners: {totalBanners}");
                PandaLogger.Log($"Add Banner: {totalBanners < numberOfBanners}");
#endif

                if (totalBanners < numberOfBanners)
                {
                    if (!Inventory.GetInventory(p.Key).TryAdd(BuiltinBlocks.Banner))
                    {
                        Stockpile.GetStockPile(p.Key).Add(BuiltinBlocks.Banner);
                    }
                }
            }
        }
示例#16
0
        public static void OnUpdate()
        {
            if (!World.Initialized || AIManager.IsBusy())
            {
                return;
            }

            var secondsSinceStartDouble = Time.SecondsSinceStartDouble;

            if (_nextUpdateTime < secondsSinceStartDouble)
            {
                IMonster m = null;

                foreach (var monster in GetAllMonsters())
                {
                    if (m == null || Vector3.Distance(monster.Value.Position, m.Position) > 15 && Random.NextBool())
                    {
                        m = monster.Value;
                        ServerManager.SendAudio(monster.Value.Position, GameLoader.NAMESPACE + ".ZombieAudio");
                    }
                }

                _nextUpdateTime = secondsSinceStartDouble + 5;
            }

            IPandaBoss bossType = null;

            if (World.Initialized &&
                !AIManager.IsBusy())
            {
                if (!BossActive &&
                    _nextBossUpdateTime <= secondsSinceStartDouble)
                {
                    BossActive = true;
                    bossType   = GetMonsterType();

                    if (Players.CountConnected != 0)
                    {
                        PandaLogger.Log(ChatColor.yellow, $"Boss Active! Boss is: {bossType.Name}");
                    }
                }

                if (BossActive)
                {
                    var turnOffBoss   = true;
                    var worldSettings = ServerManager.WorldSettings;

                    Dictionary <PlayerState, List <Banner> > banners = new Dictionary <PlayerState, List <Banner> >();
                    var spawnBanners = new List <Banner>();

                    for (var i = 0; i < BannerTracker.GetCount(); i++)
                    {
                        if (BannerTracker.TryGetAtIndex(i, out var newBanner))
                        {
                            var bps = PlayerState.GetPlayerState(newBanner.Owner);

                            if (!banners.ContainsKey(bps))
                            {
                                banners.Add(bps, new List <Banner>());
                            }

                            banners[bps].Add(newBanner);
                        }
                    }


                    foreach (var bkvp in banners)
                    {
                        if (bkvp.Value.Count > 1)
                        {
                            var next = Pipliz.Random.Next(bkvp.Value.Count);
                            spawnBanners.Add(bkvp.Value[next]);
                        }
                        else if (bkvp.Value.Count == 1)
                        {
                            spawnBanners.Add(bkvp.Value[0]);
                        }
                    }

                    foreach (var bannerGoal in spawnBanners)
                    {
                        var ps     = PlayerState.GetPlayerState(bannerGoal.Owner);
                        var colony = Colony.Get(ps.Player);

                        if (ps.BossesEnabled &&
                            ps.Player.IsConnected &&
                            colony.FollowerCount > Configuration.GetorDefault("MinColonistsCountForBosses", 15))
                        {
                            if (bossType != null &&
                                !_spawnedBosses.ContainsKey(ps))
                            {
                                Vector3Int positionFinal;
                                switch (MonsterSpawner.TryGetSpawnLocation(bannerGoal, 500f, out positionFinal))
                                {
                                case MonsterSpawner.ESpawnResult.Success:
                                    if (AIManager.ZombiePathFinder.TryFindPath(positionFinal, bannerGoal.KeyLocation, out var path, 2000000000) == EPathFindingResult.Success)
                                    {
                                        var pandaboss = bossType.GetNewBoss(path, ps.Player);
                                        _spawnedBosses.Add(ps, pandaboss);

                                        BossSpawned?.Invoke(MonsterTracker.MonsterSpawner,
                                                            new BossSpawnedEvent(ps, pandaboss));

                                        ModLoader.TriggerCallbacks <IMonster>(ModLoader.EModCallbackType.OnMonsterSpawned,
                                                                              pandaboss);

                                        MonsterTracker.Add(pandaboss);
                                        colony.OnZombieSpawn(true);
                                        ps.FaiedBossSpawns = 0;

                                        PandaChat.Send(ps.Player, $"[{pandaboss.Name}] {pandaboss.AnnouncementText}",
                                                       ChatColor.red);

                                        if (!string.IsNullOrEmpty(pandaboss.AnnouncementAudio))
                                        {
                                            ServerManager.SendAudio(ps.Player.Position, pandaboss.AnnouncementAudio);
                                        }
                                    }

                                    break;

                                case MonsterSpawner.ESpawnResult.NotLoaded:
                                case MonsterSpawner.ESpawnResult.Impossible:
                                    colony.OnZombieSpawn(true);
                                    break;

                                case MonsterSpawner.ESpawnResult.Fail:
                                    CantSpawnBoss(ps, colony);
                                    break;
                                }

                                if (_spawnedBosses.ContainsKey(ps) &&
                                    _spawnedBosses[ps].IsValid &&
                                    _spawnedBosses[ps].CurrentHealth > 0)
                                {
                                    if (ps.Player.GetTempValues(true).GetOrDefault("BossIndicator", 0) <
                                        Time.SecondsSinceStartInt)
                                    {
                                        Indicator.SendIconIndicatorNear(new Vector3Int(_spawnedBosses[ps].Position),
                                                                        _spawnedBosses[ps].ID,
                                                                        new IndicatorState(1, GameLoader.Poisoned_Icon,
                                                                                           false, false));

                                        ps.Player.GetTempValues(true)
                                        .Set("BossIndicator", Time.SecondsSinceStartInt + 1);
                                    }

                                    turnOffBoss = false;
                                }
                            }
                        }


                        if (turnOffBoss)
                        {
                            if (Players.CountConnected != 0 && _spawnedBosses.Count != 0)
                            {
                                PandaLogger.Log(ChatColor.yellow, $"All bosses cleared!");
                                var boss = _spawnedBosses.FirstOrDefault().Value;
                                PandaChat.SendToAll($"[{boss.Name}] {boss.DeathText}", ChatColor.red);
                            }

                            BossActive = false;
                            _spawnedBosses.Clear();
                            GetNextBossSpawnTime();
                        }
                    }
                }
            }
        }