public override void OnAssignedNPC(NPCBase npc)
 {
     owner        = npc.Colony.Owner;
     _tmpVals     = npc.GetTempValues(true);
     _colony      = npc.Colony;
     _playerState = PlayerState.GetPlayerState(_colony.Owner);
     _stock       = Stockpile.GetStockPile(_colony.Owner);
     base.OnAssignedNPC(npc);
 }
 public void OnAssignedNPC(NPCBase npc)
 {
     _usedNPC     = npc;
     _tmpVals     = npc.GetTempValues(true);
     _colony      = npc.Colony;
     _inv         = SettlerInventory.GetSettlerInventory(npc);
     _playerState = PlayerState.GetPlayerState(_colony.Owner);
     _stock       = Stockpile.GetStockPile(_colony.Owner);
 }
        public static void OnNPCRecruited(NPCBase npc)
        {
            if (npc.GetTempValues().TryGet(ISSETTLER, out bool settler) && settler)
            {
                return;
            }

            var ps = PlayerState.GetPlayerState(npc.Colony.Owner);

            if (ps.SettlersEnabled)
            {
                if (Configuration.GetorDefault("ColonistsRecruitment", true))
                {
                    if (ps.SettlersEnabled && npc.Colony.FollowerCount > MAX_BUYABLE)
                    {
                        var cost = Configuration.GetorDefault("CompoundingFoodRecruitmentCost", 5) * ps.ColonistsBought;
                        var num  = 0f;

                        if (cost < 1)
                        {
                            cost = 1;
                        }

                        if (npc.Colony.UsedStockpile.TotalFood < cost ||
                            !npc.Colony.UsedStockpile.TryRemoveFood(ref num, cost))
                        {
                            Chat.Send(npc.Colony.Owner,
                                      $"<color=red>Could not recruit a new colonist; not enough food in stockpile. {cost + ServerManager.ServerVariables.LaborerCost} food required.</color>",
                                      ChatSenderType.Server);

                            npc.Colony.UsedStockpile.Add(BuiltinBlocks.Bread,
                                                         (int)Math.Floor(ServerManager.ServerVariables.LaborerCost /
                                                                         3));

                            npc.health = 0;
                            npc.Update();
                            return;
                        }

                        ps.ColonistsBought++;
                        ps.NextColonistBuyTime = TimeCycle.TotalTime + 24;
                    }

                    SettlerInventory.GetSettlerInventory(npc);
                    UpdateFoodUse(npc.Colony.Owner);
                }
                else
                {
                    PandaChat.Send(npc.Colony.Owner,
                                   "The server administrator has disabled recruitment of colonists while settlers are enabled.");
                }
            }
        }
        public static SettlerInventory GetSettlerInventory(NPCBase npc)
        {
            var tempVals = npc.GetTempValues(true);

            if (!tempVals.TryGet(GameLoader.SETTLER_INV, out SettlerInventory inv))
            {
                inv = new SettlerInventory(npc.ID);
                tempVals.Set(GameLoader.SETTLER_INV, inv);
            }

            return(inv);
        }
        public static void OnNPCLoaded(NPCBase npc, JSONNode node)
        {
            if (node.TryGetAs <JSONNode>(GameLoader.SETTLER_INV, out var invNode))
            {
                npc.GetTempValues(true).Set(GameLoader.SETTLER_INV, new SettlerInventory(invNode));
            }

            var tmpVals = npc.GetTempValues();

            if (node.TryGetAs <double>(LEAVETIME_JOB, out var leaveTime))
            {
                tmpVals.Set(LEAVETIME_JOB, leaveTime);
            }

            if (node.TryGetAs <float>(GameLoader.ALL_SKILLS, out var skills))
            {
                tmpVals.Set(GameLoader.ALL_SKILLS, skills);
            }

            if (node.TryGetAs <int>(KNOWN_ITTERATIONS, out var jobItterations))
            {
                tmpVals.Set(KNOWN_ITTERATIONS, jobItterations);
            }
        }
        public static void OnNPCSaved(NPCBase npc, JSONNode node)
        {
            var tmpVals = npc.GetTempValues();

            node.SetAs(GameLoader.SETTLER_INV, SettlerInventory.GetSettlerInventory(npc).ToJsonNode());

            if (npc.NPCType.IsLaborer && tmpVals.Contains(LEAVETIME_JOB))
            {
                node.SetAs(LEAVETIME_JOB, tmpVals.Get <double>(LEAVETIME_JOB));
            }

            if (tmpVals.Contains(GameLoader.ALL_SKILLS))
            {
                node.SetAs(GameLoader.ALL_SKILLS, tmpVals.Get <float>(GameLoader.ALL_SKILLS));
            }

            if (tmpVals.Contains(KNOWN_ITTERATIONS))
            {
                node.SetAs(KNOWN_ITTERATIONS, tmpVals.Get <int>(KNOWN_ITTERATIONS));
            }
        }
        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);
        }