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); }
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(); }
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); }
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(); }