private static void NPCLeaving(NPCBase npc)
        {
            if (Random.NextFloat() > .49f)
            {
                float cost = PenalizeFood(npc.Colony, 0.05f);
                PandaChat.Send(npc.Colony, $"A colonist has left your colony taking {cost} food.", ChatColor.red);
            }
            else
            {
                var numberOfItems = Random.Next(1, 10);

                for (var i = 0; i < numberOfItems; i++)
                {
                    var randItem = Random.Next(npc.Colony.Stockpile.ItemCount);
                    var item     = npc.Colony.Stockpile.GetByIndex(randItem);

                    if (item.Type != ColonyBuiltIn.ItemTypes.AIR.Id && item.Amount != 0)
                    {
                        var leaveTax = Pipliz.Math.RoundToInt(item.Amount * .10);
                        npc.Colony.Stockpile.TryRemove(item.Type, leaveTax);

                        PandaChat.Send(npc.Colony, $"A leaving colonist has taken {leaveTax} {Models.ItemId.GetItemId(item.Type).Name}", ChatColor.red);
                    }
                }

                PandaChat.Send(npc.Colony, $"A colonist has left your colony taking 10% of {numberOfItems} items from your stockpile.", ChatColor.red);
            }

            npc.health = 0;
            npc.OnDeath();
        }
        private static void AddNewSettlers(double addCount, int numbSkilled, ColonyState state)
        {
            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(state.ColonyRef, reason, ChatColor.magenta);

            for (var i = 0; i < addCount; i++)
            {
                var newGuy = new NPCBase(state.ColonyRef, state.ColonyRef.GetRandomBanner().Position);

                NPCTracker.Add(newGuy);
                state.ColonyRef.RegisterNPC(newGuy);
                SettlerInventory.GetSettlerInventory(newGuy);
                newGuy.CustomData.SetAs(ISSETTLER, true);

                if (i <= numbSkilled)
                {
                    newGuy.CustomData.SetAs(GameLoader.ALL_SKILLS, Random.Next(1, 10) * 0.002f);
                }

                ModLoader.Callbacks.OnNPCRecruited.Invoke(newGuy);
            }
        }
        public static void OnNPCCraftedRecipe(IJob job, Recipe recipe, List <RecipeResult> results)
        {
            IncrimentSkill(job.NPC);

            var inv = SettlerInventory.GetSettlerInventory(job.NPC);

            inv.IncrimentStat("Number of Crafts");

            double weightSum = 0;
            double roll      = Random.Next() + inv.GetSkillModifier();
            List <RecipeResult> bonusItems = new List <RecipeResult>();

            foreach (var item in results)
            {
                weightSum += 1;

                if (roll > weightSum)
                {
                    bonusItems.Add(new RecipeResult(item.Type, item.Amount));
                }

                inv.IncrimentStat(ItemTypes.GetType(item.Type).Name, item.Amount);
            }

            results.AddRange(bonusItems);
        }
        private static bool EvaluateBeds(ColonyState state)
        {
            var update = false;

            try
            {
                if (!TimeCycle.IsDay && Time.SecondsSinceStartDouble > _nextbedTime)
                {
                    if (state.ColonyRef.OwnerIsOnline())
                    {
                        // TODO Fix bed count
                        var remainingBeds = ServerManager.BlockEntityTracker.BedTracker.CalculateBedCount(state.ColonyRef) - state.ColonyRef.FollowerCount;
                        var left          = 0;

                        if (remainingBeds >= 0)
                        {
                            state.NeedsABed = 0;
                        }
                        else
                        {
                            if (state.NeedsABed == 0)
                            {
                                state.NeedsABed = Time.SecondsSinceStartDouble + LOABOROR_LEAVE_HOURS;
                                PandaChat.Send(state.ColonyRef, SettlerReasoning.GetNeedBed(), ChatColor.grey);
                            }

                            if (state.NeedsABed != 0 && state.NeedsABed < Time.SecondsSinceStartDouble)
                            {
                                foreach (var follower in state.ColonyRef.Followers)
                                {
                                    if (follower.UsedBed == null)
                                    {
                                        left++;
                                        NPCLeaving(follower);
                                    }
                                }

                                state.NeedsABed = 0;
                            }

                            if (left > 0)
                            {
                                PandaChat.Send(state.ColonyRef, string.Concat(SettlerReasoning.GetNoBed(), string.Format(" {0} colonists have left your colony.", left)), ChatColor.red);
                                update = true;
                            }
                        }

                        state.ColonyRef.SendCommonData();
                    }

                    _nextbedTime = Time.SecondsSinceStartDouble + Random.Next(5, 8) * IN_GAME_HOUR_IN_SECONDS * 24;
                }
            }
            catch (Exception ex)
            {
                PandaLogger.LogError(ex, "EvaluateBeds");
            }

            return(update);
        }
Beispiel #5
0
        private static void UpdateMagicItemms(ColonyState state)
        {
            try
            {
                if (state.MagicUpdateTime < Time.SecondsSinceStartDouble)
                {
                    var colony = state.ColonyRef;

                    foreach (var follower in colony.Followers)
                    {
                        var inv = ColonistInventory.Get(follower);

                        if (inv.MagicItemUpdateTime < Time.SecondsSinceStartDouble)
                        {
                            foreach (var item in inv.Armor)
                            {
                                if (item.Value.Id != 0 && ArmorFactory.ArmorLookup.TryGetValue(item.Value.Id, out var armor))
                                {
                                    armor.Update();

                                    if (armor.HPTickRegen != 0)
                                    {
                                        follower.Heal(armor.HPTickRegen);
                                    }
                                }
                            }

                            if (WeaponFactory.WeaponLookup.TryGetValue(inv.Weapon.Id, out var wep))
                            {
                                wep.Update();

                                if (wep.HPTickRegen != 0)
                                {
                                    follower.Heal(wep.HPTickRegen);
                                }
                            }

                            inv.MagicItemUpdateTime = Time.SecondsSinceStartDouble + Random.Next(3, 5);
                        }
                    }

                    state.MagicUpdateTime = Time.SecondsSinceStartDouble + 5;
                }
            }
            catch (Exception ex)
            {
                APILogger.LogError(ex);
            }
        }
Beispiel #6
0
        public static void OnMonsterHit(IMonster monster, ModLoader.OnHitData d)
        {
            var ps         = PlayerState.GetPlayerState(monster.OriginalGoal);
            var pandaArmor = monster as IPandaArmor;
            var turret     = d.HitSourceObject as IPandaDamage;

            if (pandaArmor != null && Random.NextFloat() <= pandaArmor.MissChance)
            {
                d.ResultDamage = 0;
                return;
            }

            if (pandaArmor != null &&
                turret != null)
            {
                var damage = 0f;

                foreach (var dt in turret.Damage)
                {
                    var tmpDmg = dt.Key.CalcDamage(pandaArmor.ElementalArmor, dt.Value);

                    if (pandaArmor.AdditionalResistance.TryGetValue(dt.Key, out var flatResist))
                    {
                        tmpDmg = tmpDmg - tmpDmg * flatResist;
                    }

                    damage += tmpDmg;
                }

                d.ResultDamage = damage;
            }
            else if (pandaArmor != null)
            {
                d.ResultDamage = DamageType.Physical.CalcDamage(pandaArmor.ElementalArmor, d.ResultDamage);

                if (pandaArmor.AdditionalResistance.TryGetValue(DamageType.Physical, out var flatResist))
                {
                    d.ResultDamage = d.ResultDamage - d.ResultDamage * flatResist;
                }
            }

            d.ResultDamage = d.ResultDamage - d.ResultDamage * ps.Difficulty.MonsterDamageReduction;

            if (Random.NextFloat() > .5f)
            {
                ServerManager.SendAudio(monster.Position, GameLoader.NAMESPACE + ".ZombieAudio");
            }
        }
        private static bool EvaluateLaborers(Players.Player p)
        {
            var update = false;

            if (TimeCycle.IsDay && Time.SecondsSinceStartDouble > _nextLaborerTime)
            {
                if (p.IsConnected)
                {
                    var unTrack = new List <NPCBase>();
                    var colony  = Colony.Get(p);
                    var state   = PlayerState.GetPlayerState(p);
                    var left    = 0;

                    for (var i = 0; i < colony.LaborerCount; i++)
                    {
                        var npc     = colony.FindLaborer(i);
                        var tmpVals = npc.GetTempValues();

                        if (!tmpVals.Contains(LEAVETIME_JOB))
                        {
                            tmpVals.Set(LEAVETIME_JOB, Time.SecondsSinceStartDouble + LOABOROR_LEAVE_HOURS);
                        }
                        else if (tmpVals.Get <double>(LEAVETIME_JOB) < TimeCycle.TotalTime)
                        {
                            left++;
                            NPCLeaving(npc);
                        }
                    }

                    if (left > 0)
                    {
                        PandaChat.Send(p,
                                       string.Concat(SettlerReasoning.GetNoJobReason(),
                                                     string.Format(" {0} colonists have left your colony.", left)),
                                       ChatColor.red);
                    }

                    update = unTrack.Count != 0;
                    colony.SendUpdate();
                }

                _nextLaborerTime = Time.SecondsSinceStartDouble + Random.Next(4, 6) * TimeCycle.SecondsPerHour;
            }

            return(update);
        }
        private static bool EvaluateLaborers(ColonyState state)
        {
            var update = false;

            if (TimeCycle.IsDay && Time.SecondsSinceStartDouble > _nextLaborerTime)
            {
                if (state.ColonyRef.OwnerIsOnline())
                {
                    var unTrack = new List <NPCBase>();
                    var left    = 0;

                    for (var i = 0; i < state.ColonyRef.LaborerCount; i++)
                    {
                        var npc = state.ColonyRef.FindLaborer(i);

                        if (!npc.CustomData.TryGetAs(LEAVETIME_JOB, out double leaveTime))
                        {
                            npc.CustomData.SetAs(LEAVETIME_JOB, Time.SecondsSinceStartDouble + LOABOROR_LEAVE_HOURS);
                        }
                        else if (leaveTime < Time.SecondsSinceStartDouble)
                        {
                            left++;
                            NPCLeaving(npc);
                        }
                    }

                    if (left > 0)
                    {
                        PandaChat.Send(state.ColonyRef,
                                       string.Concat(SettlerReasoning.GetNoJobReason(),
                                                     string.Format(" {0} colonists have left your colony.", left)),
                                       ChatColor.red);
                    }

                    update = unTrack.Count != 0;
                    state.ColonyRef.SendCommonData();
                }

                _nextLaborerTime = Time.SecondsSinceStartDouble + Random.Next(4, 6) * IN_GAME_HOUR_IN_SECONDS * 24;
            }

            return(update);
        }
Beispiel #9
0
        private static IPandaBoss GetMonsterType()
        {
            IPandaBoss t = null;

            lock (_bossList)
            {
                var rand = _boss;

                while (rand == _boss)
                {
                    rand = Random.Next(0, _bossList.Count);
                }

                t     = _bossList[rand];
                _boss = rand;
            }

            return(t);
        }
        public static bool EvaluateSettlers(ColonyState state)
        {
            var update = false;

            if (state.ColonyRef.OwnerIsOnline())
            {
                if (state.NextGenTime == 0)
                {
                    state.NextGenTime = Time.SecondsSinceStartDouble + Random.Next(8, 16) * IN_GAME_HOUR_IN_SECONDS;
                }

                if (Time.SecondsSinceStartDouble > state.NextGenTime && state.ColonyRef.FollowerCount >= MAX_BUYABLE)
                {
                    var chance =
                        state.ColonyRef.TemporaryData.GetAsOrDefault(GameLoader.NAMESPACE + ".SettlerChance", 0f) +
                        state.Difficulty.AdditionalChance;

                    chance += SettlerEvaluation.SpawnChance(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 (state.ColonyRef.FollowerCount < state.HighestColonistCount)
                        {
                            var diff = state.HighestColonistCount - state.ColonyRef.FollowerCount;
                            addCount += Math.Floor(diff * .25);
                        }

                        try
                        {
                            var skillChance = state.ColonyRef.TemporaryData.GetAsOrDefault(GameLoader.NAMESPACE + ".SkilledLaborer", 0f);
                            var numbSkilled = 0;
                            rand = Random.NextFloat();

                            try
                            {
                                if (skillChance > rand)
                                {
                                    numbSkilled = Pipliz.Random.Next(1,
                                                                     2 + Pipliz.Math.RoundToInt(state.ColonyRef.TemporaryData.GetAsOrDefault(GameLoader.NAMESPACE + ".NumberSkilledLaborer", 0f)));
                                }
                            }
                            catch (Exception ex)
                            {
                                PandaLogger.Log("NumberSkilledLaborer");
                                PandaLogger.LogError(ex);
                            }


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

                                if (!state.NotifySettlers)
                                {
                                    AddNewSettlers(addCount, numbSkilled, state);
                                }
                                else
                                {
                                    foreach (var p in state.ColonyRef.Owners)
                                    {
                                        if (p.IsConnected())
                                        {
                                            NetworkMenu menu = new NetworkMenu();
                                            menu.LocalStorage.SetAs("header", addCount + _localizationHelper.LocalizeOrDefault("NewSettlers", p));
                                            menu.Width  = 600;
                                            menu.Height = 300;

                                            menu.Items.Add(new ButtonCallback(GameLoader.NAMESPACE + ".NewSettlers.Accept." + addCount + "." + numbSkilled,
                                                                              new LabelData(_localizationHelper.GetLocalizationKey("Accept"),
                                                                                            UnityEngine.Color.black,
                                                                                            UnityEngine.TextAnchor.MiddleCenter)));

                                            menu.Items.Add(new ButtonCallback(GameLoader.NAMESPACE + ".NewSettlers.Decline",
                                                                              new LabelData(_localizationHelper.GetLocalizationKey("Decline"),
                                                                                            UnityEngine.Color.black,
                                                                                            UnityEngine.TextAnchor.MiddleCenter)));

                                            NetworkMenuManager.SendServerPopup(p, menu);
                                        }
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            PandaLogger.Log("SkilledLaborer");
                            PandaLogger.LogError(ex);
                        }

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


                    state.NextGenTime = Time.SecondsSinceStartDouble + Random.Next(8, 16) * IN_GAME_HOUR_IN_SECONDS;

                    state.ColonyRef.SendCommonData();
                }
            }

            return(update);
        }
        public static void OnUpdate()
        {
            if (ServerManager.ColonyTracker != null)
            {
                foreach (var colony in ServerManager.ColonyTracker.ColoniesByID.Values)
                {
                    if (_magicUpdateTime < Time.SecondsSinceStartDouble)
                    {
                        foreach (var follower in colony.Followers)
                        {
                            var inv = SettlerInventory.GetSettlerInventory(follower);

                            if (inv.MagicItemUpdateTime < Time.SecondsSinceStartDouble)
                            {
                                foreach (var item in inv.Armor)
                                {
                                    if (item.Value.Id != 0 && ArmorFactory.ArmorLookup.TryGetValue(item.Value.Id, out var armor))
                                    {
                                        armor.Update();

                                        if (armor.HPTickRegen != 0)
                                        {
                                            follower.Heal(armor.HPTickRegen);
                                        }
                                    }
                                }

                                if (Items.Weapons.WeaponFactory.WeaponLookup.TryGetValue(inv.Weapon.Id, out var wep))
                                {
                                    wep.Update();

                                    if (wep.HPTickRegen != 0)
                                    {
                                        follower.Heal(wep.HPTickRegen);
                                    }
                                }

                                var hasBandages = colony.Stockpile.Contains(TreatedBandage.Item.ItemIndex) ||
                                                  colony.Stockpile.Contains(Bandage.Item.ItemIndex);

                                if (hasBandages &&
                                    follower.health < follower.Colony.NPCHealthMax &&
                                    !HealingOverTimeNPC.NPCIsBeingHealed(follower))
                                {
                                    var healing = false;

                                    if (follower.Colony.NPCHealthMax - follower.health > TreatedBandage.INITIALHEAL)
                                    {
                                        colony.Stockpile.TryRemove(TreatedBandage.Item.ItemIndex);
                                        healing = true;
                                        AudioManager.SendAudio(follower.Position.Vector, GameLoader.NAMESPACE + ".Bandage");

                                        var heal = new HealingOverTimeNPC(follower, TreatedBandage.INITIALHEAL,
                                                                          TreatedBandage.TOTALHOT, 5,
                                                                          TreatedBandage.Item.ItemIndex);
                                    }

                                    if (!healing)
                                    {
                                        colony.Stockpile.TryRemove(Bandage.Item.ItemIndex);
                                        healing = true;
                                        AudioManager.SendAudio(follower.Position.Vector, GameLoader.NAMESPACE + ".Bandage");

                                        var heal = new HealingOverTimeNPC(follower, Bandage.INITIALHEAL, Bandage.TOTALHOT, 5,
                                                                          Bandage.Item.ItemIndex);
                                    }
                                }


                                inv.MagicItemUpdateTime += 5000;
                            }
                        }
                    }


                    if (_updateTime < Time.SecondsSinceStartDouble && colony.OwnerIsOnline())
                    {
                        NPCBase lastNPC = null;

                        foreach (var follower in colony.Followers)
                        {
                            if (TimeCycle.IsDay)
                            {
                                if (lastNPC == null ||
                                    UnityEngine.Vector3.Distance(lastNPC.Position.Vector, follower.Position.Vector) > 15 &&
                                    Random.NextBool())
                                {
                                    lastNPC = follower;
                                    AudioManager.SendAudio(follower.Position.Vector, GameLoader.NAMESPACE + ".TalkingAudio");
                                }
                            }
                        }
                    }

                    var cs = ColonyState.GetColonyState(colony);

                    if (cs.SettlersEnabled)
                    {
                        if (EvaluateSettlers(cs) ||
                            EvaluateLaborers(cs) ||
                            EvaluateBeds(cs))
                        {
                            colony.SendCommonData();
                        }
                    }

                    UpdateFoodUse(cs);
                }
            }

            if (_magicUpdateTime < Time.SecondsSinceStartDouble)
            {
                _magicUpdateTime = Time.SecondsSinceStartDouble + 1;
            }

            if (_updateTime < Time.SecondsSinceStartDouble && TimeCycle.IsDay)
            {
                _updateTime = Time.SecondsSinceStartDouble + _UPDATE_TIME;
            }
        }
        public static void OnUpdate()
        {
            Players.PlayerDatabase.ForeachValue(p =>
            {
                var stockpile = Stockpile.GetStockPile(p);
                var colony    = Colony.Get(p);

                var hasBandages = stockpile.Contains(TreatedBandage.Item.ItemIndex) ||
                                  stockpile.Contains(Bandage.Item.ItemIndex);

                if (hasBandages)
                {
                    foreach (var follower in colony.Followers)
                    {
                        if (follower.health < NPCBase.MaxHealth &&
                            !HealingOverTimeNPC.NPCIsBeingHealed(follower))
                        {
                            var healing = false;

                            if (NPCBase.MaxHealth - follower.health > TreatedBandage.INITIALHEAL)
                            {
                                stockpile.TryRemove(TreatedBandage.Item.ItemIndex);
                                healing = true;
                                ServerManager.SendAudio(follower.Position.Vector, GameLoader.NAMESPACE + ".Bandage");

                                var heal = new HealingOverTimeNPC(follower, TreatedBandage.INITIALHEAL,
                                                                  TreatedBandage.TOTALHOT, 5,
                                                                  TreatedBandage.Item.ItemIndex);
                            }

                            if (!healing)
                            {
                                stockpile.TryRemove(Bandage.Item.ItemIndex);
                                healing = true;
                                ServerManager.SendAudio(follower.Position.Vector, GameLoader.NAMESPACE + ".Bandage");

                                var heal = new HealingOverTimeNPC(follower, Bandage.INITIALHEAL, Bandage.TOTALHOT, 5,
                                                                  Bandage.Item.ItemIndex);
                            }
                        }
                    }
                }

                if (_updateTime < Time.SecondsSinceStartDouble && TimeCycle.IsDay && p.IsConnected)
                {
                    NPCBase lastNPC = null;

                    foreach (var follower in colony.Followers)
                    {
                        if (lastNPC == null ||
                            Vector3.Distance(lastNPC.Position.Vector, follower.Position.Vector) > 15 &&
                            Random.NextBool())
                        {
                            lastNPC = follower;
                            ServerManager.SendAudio(follower.Position.Vector, GameLoader.NAMESPACE + ".TalkingAudio");
                        }
                    }
                }

                var ps = PlayerState.GetPlayerState(p);

                if (ps.SettlersEnabled)
                {
                    if (EvaluateSettlers(p) ||
                        EvaluateLaborers(p) ||
                        EvaluateBeds(p))
                    {
                        colony.SendUpdate();
                    }
                }

                UpdateFoodUse(p);
            });


            if (_updateTime < Time.SecondsSinceStartDouble && TimeCycle.IsDay)
            {
                _updateTime = Time.SecondsSinceStartDouble + 10;
            }
        }
        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);
        }
        public static void OnMonsterHit(IMonster monster, ModLoader.OnHitData d)
        {
            var cs          = ColonyState.GetColonyState(monster.OriginalGoal);
            var pandaArmor  = monster as IPandaArmor;
            var pamdaDamage = d.HitSourceObject as IPandaDamage;
            var skilled     = 0f;

            if (pandaArmor != null && Random.NextFloat() <= pandaArmor.MissChance)
            {
                d.ResultDamage = 0;
                return;
            }

            if (pamdaDamage == null && d.HitSourceType == ModLoader.OnHitData.EHitSourceType.NPC)
            {
                var npc = d.HitSourceObject as NPCBase;
                var inv = ColonistInventory.Get(npc);
                ColonistManager.IncrimentSkill(npc);
                skilled = inv.GetSkillModifier();

                if (inv.Weapon != null && Items.Weapons.WeaponFactory.WeaponLookup.TryGetValue(inv.Weapon.Id, out var wep))
                {
                    pamdaDamage = wep;
                }
            }

            if (pandaArmor != null && pamdaDamage != null)
            {
                d.ResultDamage = Items.Weapons.WeaponFactory.CalcDamage(pandaArmor, pamdaDamage);
            }
            else if (pandaArmor != null)
            {
                d.ResultDamage = DamageType.Physical.CalcDamage(pandaArmor.ElementalArmor, d.ResultDamage);

                if (pandaArmor.AdditionalResistance.TryGetValue(DamageType.Physical, out var flatResist))
                {
                    d.ResultDamage = d.ResultDamage - d.ResultDamage * flatResist;
                }
            }

            double skillRoll = Pipliz.Random.Next() + skilled;

            if (skillRoll < skilled)
            {
                d.ResultDamage += d.ResultDamage;
            }

            d.ResultDamage = d.ResultDamage - d.ResultDamage * cs.Difficulty.MonsterDamageReduction;

            if (d.ResultDamage < 0)
            {
                d.ResultDamage = 0;
            }

            if (d.HitSourceType == ModLoader.OnHitData.EHitSourceType.NPC)
            {
                var npc = d.HitSourceObject as NPCBase;
                var inv = ColonistInventory.Get(npc);
                inv.IncrimentStat("Damage Done", d.ResultDamage);

                if (skillRoll < skilled)
                {
                    inv.IncrimentStat("Double Damage Hits");
                }
            }

            if (d.ResultDamage >= monster.CurrentHealth)
            {
                monster.OnRagdoll();
                var    rewardMonster = monster as IPandaZombie;
                string monsterType   = "zombie";

                if (rewardMonster != null)
                {
                    monsterType = rewardMonster.MosterType;
                }

                if (monster.OriginalGoal.OwnerIsOnline())
                {
                    if (!string.IsNullOrEmpty(monsterType) &&
                        LootTables.Lookup.TryGetValue(monsterType, out var lootTable))
                    {
                        float luck = 0;

                        if (d.HitSourceObject is ILucky luckSrc)
                        {
                            luck = luckSrc.Luck;
                        }
                        else if ((d.HitSourceType == ModLoader.OnHitData.EHitSourceType.PlayerClick ||
                                  d.HitSourceType == ModLoader.OnHitData.EHitSourceType.PlayerProjectile) &&
                                 d.HitSourceObject is Players.Player player)
                        {
                            var ps = PlayerState.GetPlayerState(player);

                            foreach (var armor in ps.Armor)
                            {
                                if (Items.Armor.ArmorFactory.ArmorLookup.TryGetValue(armor.Value.Id, out var a))
                                {
                                    luck += a.Luck;
                                }
                            }

                            if (Items.Weapons.WeaponFactory.WeaponLookup.TryGetValue(ps.Weapon.Id, out var w))
                            {
                                luck += w.Luck;
                            }
                        }
                        else if (d.HitSourceType == ModLoader.OnHitData.EHitSourceType.NPC &&
                                 d.HitSourceObject is NPCBase nPC)
                        {
                            var inv = ColonistInventory.Get(nPC);

                            foreach (var armor in inv.Armor)
                            {
                                if (Items.Armor.ArmorFactory.ArmorLookup.TryGetValue(armor.Value.Id, out var a))
                                {
                                    luck += a.Luck;
                                }
                            }

                            if (Items.Weapons.WeaponFactory.WeaponLookup.TryGetValue(inv.Weapon.Id, out var w))
                            {
                                luck += w.Luck;
                            }
                        }

                        var roll = lootTable.GetDrops(luck);

                        foreach (var item in roll)
                        {
                            monster.OriginalGoal.Stockpile.Add(item.Key, item.Value);
                        }
                    }
                }
            }
        }
 private static void GetNextBossSpawnTime()
 {
     _nextBossUpdateTime = Time.SecondsSinceStartInt + Random.Next(MinBossSpawnTimeSeconds, MaxBossSpawnTimeSeconds);
 }
Beispiel #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();
                        }
                    }
                }
            }
        }
        private static bool EvaluateBeds(Players.Player p)
        {
            var update = false;

            try
            {
                if (!TimeCycle.IsDay && Time.SecondsSinceStartDouble > _nextbedTime)
                {
                    if (p.IsConnected)
                    {
                        var colony        = Colony.Get(p);
                        var state         = PlayerState.GetPlayerState(p);
                        var remainingBeds = BedBlockTracker.GetCount(p) - colony.FollowerCount;
                        var left          = 0;

                        if (remainingBeds >= 0)
                        {
                            state.NeedsABed = 0;
                        }
                        else
                        {
                            if (state.NeedsABed == 0)
                            {
                                state.NeedsABed = Time.SecondsSinceStartDouble + LOABOROR_LEAVE_HOURS;
                                PandaChat.Send(p, SettlerReasoning.GetNeedBed(), ChatColor.grey);
                            }

                            if (state.NeedsABed != 0 && state.NeedsABed < TimeCycle.TotalTime)
                            {
                                foreach (var follower in colony.Followers)
                                {
                                    if (follower.GetFieldValue <BedBlock, NPCBase>("bed") == null)
                                    {
                                        left++;
                                        NPCLeaving(follower);
                                    }
                                }

                                state.NeedsABed = 0;
                            }

                            if (left > 0)
                            {
                                PandaChat.Send(p,
                                               string.Concat(SettlerReasoning.GetNoBed(),
                                                             string.Format(" {0} colonists have left your colony.",
                                                                           left)), ChatColor.red);

                                update = true;
                            }
                        }

                        colony.SendUpdate();
                    }

                    _nextbedTime = Time.SecondsSinceStartDouble + Random.Next(5, 8) * TimeCycle.SecondsPerHour;
                }
            }
            catch (Exception ex)
            {
                PandaLogger.LogError(ex, "EvaluateBeds");
            }

            return(update);
        }
        public static bool EvaluateSettlers(ColonyState state)
        {
            var update = false;

            if (state.ColonyRef.OwnerIsOnline())
            {
                if (state.NextGenTime == 0)
                {
                    state.NextGenTime = Time.SecondsSinceStartDouble + Random.Next(8, 16) * IN_GAME_HOUR_IN_SECONDS;
                }

                if (Time.SecondsSinceStartDouble > state.NextGenTime && state.ColonyRef.FollowerCount >= MAX_BUYABLE)
                {
                    var chance =
                        state.ColonyRef.TemporaryData.GetAsOrDefault(PandaResearch.GetResearchKey(PandaResearch.SettlerChance), 0f) +
                        state.Difficulty.AdditionalChance;

                    chance += SettlerEvaluation.SpawnChance(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 (state.ColonyRef.FollowerCount < state.HighestColonistCount)
                        {
                            var diff = state.HighestColonistCount - state.ColonyRef.FollowerCount;
                            addCount += Math.Floor(diff * .25);
                        }

                        try
                        {
                            var skillChance = state.ColonyRef.TemporaryData.GetAsOrDefault(PandaResearch.GetResearchKey(PandaResearch.SkilledLaborer), 0f);
                            var numbSkilled = 0;
                            rand = Random.NextFloat();

                            try
                            {
                                if (skillChance > rand)
                                {
                                    numbSkilled = Pipliz.Random.Next(1,
                                                                     2 + Pipliz.Math.RoundToInt(state.ColonyRef.TemporaryData.GetAsOrDefault(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(state.ColonyRef, reason, ChatColor.magenta);

                                for (var i = 0; i < addCount; i++)
                                {
                                    var newGuy = new NPCBase(state.ColonyRef, state.ColonyRef.GetRandomBanner().Position);

                                    NPCTracker.Add(newGuy);
                                    state.ColonyRef.RegisterNPC(newGuy);
                                    SettlerInventory.GetSettlerInventory(newGuy);
                                    newGuy.CustomData.SetAs(ISSETTLER, true);

                                    if (i <= numbSkilled)
                                    {
                                        newGuy.CustomData.SetAs(GameLoader.ALL_SKILLS, Random.Next(1, 10) * 0.002f);
                                    }

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

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


                    state.NextGenTime = Time.SecondsSinceStartDouble + Random.Next(8, 16) * IN_GAME_HOUR_IN_SECONDS;

                    state.ColonyRef.SendCommonData();
                }
            }

            return(update);
        }