Example #1
0
        public override bool TryExecute(IncidentParms parms)
        {
            var     map = (Map)parms.target;
            IntVec3 loc;

            if (!CellFinder.TryFindRandomEdgeCellWith(c => map.reachability.CanReachColony(c), map, out loc))
            {
                return(false);
            }

            IntVec3 spawnSpot;

            if (!CellFinder.TryFindRandomEdgeCellWith(c => map.reachability.CanReachColony(c), map, out spawnSpot))
            {
                return(false);
            }

            var pawn = GenericUtility.GetAnyRelatedWorldPawn(other => other.Faction != null && !other.Faction.HostileTo(Faction.OfPlayer), 100) ?? CreateNewPawn();

            if (pawn == null)
            {
                return(false);
            }

            ShowWandererJoinDialog(pawn, spawnSpot, map);
            return(true);
        }
        public override void MapComponentTick()
        {
            base.MapComponentTick();

            if (incidentQueue == null)
            {
                incidentQueue = new IncidentQueue();
            }
            if (incidentQueue.Count <= 1)
            {
                GenericUtility.FillIncidentQueue(map);
            }
            incidentQueue.IncidentQueueTick();

            if (GenTicks.TicksGame > nextQueueInspection)
            {
                nextQueueInspection = GenTicks.TicksGame + GenDate.TicksPerDay;
                GenericUtility.CheckTooManyIncidentsAtOnce(incidentQueue);
            }

            if (GenTicks.TicksGame > nextRogueGuestCheck)
            {
                nextRogueGuestCheck = GenTicks.TicksGame + GenDate.TicksPerHour;
                GuestUtility.CheckForRogueGuests(map);
            }

            if (GenTicks.TicksGame > nextGuestListCheck)
            {
                nextGuestListCheck = GenTicks.TicksGame + GenDate.TicksPerDay / 4;
                PresentLords.Clear();
                RefreshGuestListTotal();
            }
        }
Example #3
0
        private static void TryCreateVisit(Map map, float days, Faction faction, float travelFactor = 1)
        {
            var travelDays = GenericUtility.GetTravelDays(faction, map);

            // ReSharper disable once CompareOfFloatsByEqualityOperator
            if (travelDays == GenericUtility.NoBasesLeft)
            {
                return;
            }

            GuestUtility.PlanNewVisit(map, days + travelDays * travelFactor, faction);
        }
        private bool SpawnGroup(IncidentParms parms, Map map)
        {
            var visitors = new List <Pawn>();

            try
            {
                //Log.Message(string.Format("Spawning visitors from {0}, at {1}.", parms.faction, parms.spawnCenter));
                SpawnPawns(parms, visitors);

                SpawnGroupUtility.CheckVisitorsValid(visitors);

                if (visitors == null || visitors.Count == 0)
                {
                    return(false);
                }

                var area = visitors.First().GetGuestArea() ?? map.GetMapComponent().defaultAreaRestriction;
                var spot = GetSpot(map, area, visitors.First());

                if (!spot.IsValid)
                {
                    throw new Exception($"Visitors from {parms.faction.Name} failed to find a valid travel target from {visitors.First()?.Position} to guest area {area?.Label}.");
                }

                GiveItems(visitors);

                var stayDuration = (int)(Rand.Range(1f, 2.4f) * GenDate.TicksPerDay);
                CreateLord(parms.faction, spot, visitors, map, true, true, stayDuration);
            }
            catch (Exception e)
            {
                var faction     = parms.faction?.Name;
                var factionType = parms.faction?.def.label;
                Log.Error($"Hospitality: Something failed when setting up visitors from faction {faction} ({factionType}):\n{e}");
                foreach (var visitor in visitors)
                {
                    if (visitor?.Spawned == true)
                    {
                        visitor.DeSpawn();
                        visitor.DestroyOrPassToWorld();
                    }
                }
                GenericUtility.PlanNewVisit(map, Rand.Range(1f, 3f), parms.faction);
            }
            return(true); // be gone, event
        }
        private static float PlanRevisit(Faction faction, float targetGoodwill, Map currentMap, bool sentAway)
        {
            float days;

            if (faction.defeated)
            {
                return(100);
            }
            if (targetGoodwill < -50)
            {
                return(100);
            }
            else if (targetGoodwill > 0)
            {
                days = Mathf.Lerp(Rand.Range(5f, 7f), Rand.Range(0f, 2f), targetGoodwill / 100f);
            }
            else
            {
                days = Mathf.Lerp(Rand.Range(7f, 12f), Rand.Range(25f, 30f), targetGoodwill / -100f);
            }

            if (sentAway)
            {
                days += 10;
            }

            Map randomVisitMap = Rand.Value < 0.1f ? Find.Maps.Where(m => m.IsPlayerHome).RandomElement() : currentMap;

            if (Rand.Value < targetGoodwill / 100f && Rand.Value < 0.2f)
            {
                // Send another friendly faction as well
                Faction newFaction;
                if (Find.FactionManager.AllFactionsVisible.Where(f => f != faction && !f.defeated && !f.HostileTo(Faction.OfPlayer)).TryRandomElement(out newFaction))
                {
                    GuestUtility.PlanNewVisit(currentMap, days * 2 + GenericUtility.GetTravelDays(newFaction, currentMap), newFaction);
                }
            }

            //Log.Message(faction.def.LabelCap + " will visit again in " + days + " days (+" + GenericUtility.GetTravelDays(faction, randomVisitMap)*2 + " days for travel).");
            GuestUtility.PlanNewVisit(randomVisitMap, days + GenericUtility.GetTravelDays(faction, randomVisitMap) * 2, faction);
            return(days);
        }
        private static float PlanRevisit(Faction faction, float targetGoodwill, Map currentMap, bool sentAway)
        {
            float days;

            if (faction.defeated)
            {
                return(100);
            }
            else if (targetGoodwill > 0)
            {
                days = Mathf.Lerp(Rand.Range(6f, 12f), Rand.Range(3f, 6f), targetGoodwill / 100f);
            }
            else
            {
                days = Mathf.Lerp(Rand.Range(12f, 24f), Rand.Range(25f, 30f), targetGoodwill / -100f);
            }

            if (targetGoodwill < -25)
            {
                days += (-targetGoodwill - 25);
            }
            if (sentAway)
            {
                days += 5;
            }

            Map randomVisitMap = Rand.Value < 0.1f ? Find.Maps.Where(m => m.IsPlayerHome).RandomElement() : currentMap;

            if (Rand.Value < targetGoodwill / 100f && Rand.Value < 0.2f)
            {
                // Send another friendly faction as well (start walking now)
                if (Find.FactionManager.AllFactionsVisible.Where(f => f != faction && !f.defeated && !f.HostileTo(Faction.OfPlayer) && !f.IsPlayer).TryRandomElement(out var newFaction))
                {
                    GenericUtility.TryCreateVisit(randomVisitMap, 0, newFaction);
                }
            }

            //Log.Message(faction.def.LabelCap + " will visit again in " + days + " days (+" + GenericUtility.GetTravelDays(faction, randomVisitMap)*2 + " days for travel).");
            GenericUtility.TryCreateVisit(randomVisitMap, days, faction, 2);
            return(days);
        }
        private void FillTabGuest(Rect rect)
        {
            //ConceptDatabase.KnowledgeDemonstrated(ConceptDefOf.PrisonerTab, KnowledgeAmount.GuiFrame);
            var title            = SelPawn.royalty?.MostSeniorTitle;
            var isRoyal          = title != null;
            var friends          = isRoyal ? SelPawn.GetFriendsSeniorityInColony() : SelPawn.GetFriendsInColony();
            var friendsRequired  = isRoyal ? RequiredSeniority : RequiredFriends;
            var friendPercentage = 100f * friends / friendsRequired;


            var tryImprove     = SelPawn.ImproveRelationship();
            var tryMakeFriends = SelPawn.MakeFriends();

            listingStandard.ColumnWidth = size.x - 20;

            var comp = SelPawn.GetComp <CompGuest>();

            // If the lord is not on the map it's invalid!
            if (comp?.lord != null && comp.lord.ownedPawns.Contains(SelPawn) && SelPawn.Map.lordManager.lords.Contains(comp.lord))
            {
                listingStandard.Gap();
                string labelStay     = "AreaToStay".Translate();
                string labelBuy      = "AreaToBuy".Translate();
                var    rectStayLabel = listingStandard.GetRect(Text.CalcHeight(labelStay, listingStandard.ColumnWidth));
                var    rectStay      = listingStandard.GetRect(24);
                var    rectBuyLabel  = listingStandard.GetRect(Text.CalcHeight(labelBuy, listingStandard.ColumnWidth));
                var    rectBuy       = listingStandard.GetRect(24);

                LabelWithTooltip(labelStay, "AreaToStayTooltip".Translate(), rectStayLabel);
                GenericUtility.DoAreaRestriction(SelPawn, rectStay, comp.GuestArea, SetAreaRestriction, AreaUtility.AreaAllowedLabel_Area);
                LabelWithTooltip(labelBuy, "AreaToBuyTooltip".Translate(), rectBuyLabel);
                GenericUtility.DoAreaRestriction(SelPawn, rectBuy, comp.ShoppingArea, SetAreaShopping, GenericUtility.GetShoppingLabel);

                var rectImproveRelationship = listingStandard.GetRect(Text.LineHeight);
                CheckboxLabeled(listingStandard, "ImproveRelationship".Translate(), ref tryImprove, rectImproveRelationship, false, txtImproveTooltip);
                var rectMakeFriends = listingStandard.GetRect(Text.LineHeight);
                CheckboxLabeled(listingStandard, "MakeFriends".Translate(), ref tryMakeFriends, rectMakeFriends, false, txtMakeFriendsTooltip);

                comp.SetEntertain(tryImprove);
                comp.SetMakeFriends(tryMakeFriends);

                listingStandard.Gap(50);

                var mayRecruitAtAll = !SelPawn.InMentalState && comp.arrived;

                var rectSetDefault = new Rect(rect.xMax - buttonSize.x - 10, 160, buttonSize.x, buttonSize.y);
                var rectSendHome   = new Rect(rect.xMin - 10, 160, buttonSize.x, buttonSize.y);
                DrawButton(() => SetAllDefaults(SelPawn), txtMakeDefault, rectSetDefault, txtMakeDefaultTooltip);
                DrawButton(() => SendHomeDialog(SelPawn.GetLord()), txtSendAway, rectSendHome, txtSendAwayTooltip);
                if (mayRecruitAtAll)
                {
                    var rectRecruitButton = new Rect(rect.xMin - 10 + 10 + buttonSize.x, 160, buttonSize.x, buttonSize.y);
                    if (friends >= friendsRequired)
                    {
                        DrawButton(() => RecruitDialog(SelPawn, false), txtRecruit, rectRecruitButton, txtRecruitTooltip);
                    }
                    else if (!isRoyal)
                    {
                        DrawButton(() => RecruitDialog(SelPawn, true), txtForceRecruit, rectRecruitButton, txtForceRecruitTooltip);
                    }
                }

                // Highlight defaults
                if (Mouse.IsOver(rectSetDefault))
                {
                    Widgets.DrawHighlight(rectStay);
                    Widgets.DrawHighlight(rectStayLabel);
                    Widgets.DrawHighlight(rectBuy);
                    Widgets.DrawHighlight(rectBuyLabel);
                    Widgets.DrawHighlight(rectImproveRelationship);
                    Widgets.DrawHighlight(rectMakeFriends);
                }
            }

            if (SelPawn.Faction != null)
            {
                listingStandard.Label(txtRecruitmentPenalty.Translate(SelPawn.RecruitPenalty().ToString("##0"), SelPawn.ForcedRecruitPenalty().ToString("##0")));
                listingStandard.Label(txtFactionGoodwill + ": " + SelPawn.Faction.PlayerGoodwill.ToString("##0"));
            }

            listingStandard.Gap();

            if (isRoyal)
            {
                listingStandard.Label($"{"SeniorityRequirement".Translate(friends / 100, friendsRequired / 100)}:");
            }
            else
            {
                listingStandard.Label($"{"FriendsRequirement".Translate(friends, friendsRequired)}:");
            }

            listingStandard.Slider(Mathf.Clamp(friendPercentage, 0, 100), 0, 100);
            if (friendPercentage <= 99)
            {
                // Remove color from AdjustedFor and then Colorize
                listingStandard.Label(ColoredText.StripTags("NotEnoughFriends".Translate(SelPawn.GetMinRecruitOpinion()).AdjustedFor(SelPawn)).Colorize(Color.red));
            }
            else
            {
                listingStandard.Label("CanNowBeRecruited".Translate().AdjustedFor(SelPawn));
            }


            // Will only have score while "checked in", becomes 0 again when guest leaves
            if (SelPawn.GetVisitScore(out var score))
            {
                listingStandard.Label(txtHospitality + ":");
                listingStandard.Slider(score, 0f, 1f);
            }
        }
        protected override bool TryExecuteWorker(IncidentParms parms)
        {
            if (!TryResolveParms(parms))
            {
                Log.ErrorOnce($"Trying to spawn visitors, but parms couldn't be resolved.", 84289426);
                return(false);
            }

            // Is map not available anymore?
            if (!(parms.target is Map map))
            {
                Log.ErrorOnce("Trying to spawn visitors, but map does not exist anymore.", 43692862);
                return(true);
            }

            if (parms.points < 40)
            {
                Log.Error("Trying to spawn visitors, but points are too low.");
                return(false);
            }

            if (parms.faction == null)
            {
                Log.ErrorOnce("Trying to spawn visitors, but couldn't find valid faction.", 43638973);
                return(true);
            }
            if (!parms.spawnCenter.IsValid)
            {
                Log.ErrorOnce("Trying to spawn visitors, but could not find a valid spawn point.", 94839643);
                return(false);
            }

            if (parms.faction == Faction.OfPlayer)
            {
                Log.ErrorOnce("Trying to spawn visitors, but they are of Faction.OfPlayer.", 3464363);
                return(true);
            }
            if (parms.faction.RelationWith(Faction.OfPlayer).kind == FactionRelationKind.Hostile)
            {
                Log.Message($"Trying to spawn visitors of faction {parms.faction.Name}, but they are hostile to the player (now).");
                return(true);
            }

            if (parms.faction.defeated)
            {
                Log.Message($"Trying to spawn visitors of faction {parms.faction.Name}, but they have been defeated.");
                return(true);
            }

            if (Settings.disableGuests || map.mapPawns.ColonistCount == 0)
            {
                if (Settings.disableGuests)
                {
                    Log.Message($"Guest group arrived, but guests are disabled in the options.");
                }
                else if (map.mapPawns.ColonistCount == 0)
                {
                    Log.Message($"Guest group arrived, but there are no remaining colonists on the map.");
                }

                GenericUtility.PlanNewVisit(map, Rand.Range(5f, 25f), parms.faction);
            }
            else
            {
                // Did the player refuse guests until beds are made and there are no beds yet?
                if (!BedCheck(map))
                {
                    Log.Message("Guest group arrived, but there are no guest beds and the player asked to wait until they are built.");

                    GenericUtility.PlanNewVisit(map, Rand.Range(5f, 10f), parms.faction);
                    return(true);
                }

                // We check here instead of CanFireNow, so we can reschedule the visit.
                // Any reasons not to come?
                if (CheckCanCome(map, parms.faction, out var reasons))
                {
                    // No, spawn
                    return(SpawnGroup(parms, map));
                }

                // Yes, ask the player for permission
                void Allow() => SpawnGroup(parms, map);
                void Refuse() => GenericUtility.PlanNewVisit(map, Rand.Range(2f, 5f), parms.faction);

                AskForPermission(parms, map, reasons, Allow, Refuse);
            }
            return(true);
        }
        public override bool TryExecute(IncidentParms parms)
        {
            Map     map = (Map)parms.target;
            IntVec3 spawnSpot;

            if (!CellFinder.TryFindRandomEdgeCellWith(c => map.reachability.CanReachColony(c), map, out spawnSpot))
            {
                return(false);
            }

            #region CHANGED

            Func <Pawn, bool> selector = other => other.RaceProps.Humanlike && other.Faction != null && other.Faction.HostileTo(Faction.OfPlayer) && HasGroupMakers(other.Faction);

            Pawn refugee = GenericUtility.GetAnyRelatedWorldPawn(selector, 100);
            if (refugee == null)
            {
                // Just ANYONE
                Find.WorldPawns.AllPawnsAlive.Where(selector).TryRandomElement(out refugee);
            }
            if (refugee == null)
            {
                return(false);
            }

            refugee.relations.everSeenByPlayer = true;
            Faction enemyFac = refugee.Faction;

            string text = "RefugeeChasedInitial".Translate(new object[]
            {
                refugee.Name.ToStringFull,
                refugee.GetTitle().ToLower(),
                enemyFac.def.pawnsPlural, enemyFac.Name,
                refugee.ageTracker.AgeBiologicalYears
            });

            text = text.AdjustedFor(refugee);
            PawnRelationUtility.TryAppendRelationsWithColonistsInfo(ref text, refugee);
            DiaNode   diaNode   = new DiaNode(text);
            DiaOption diaOption = new DiaOption("RefugeeChasedInitial_Accept".Translate());
            diaOption.action = delegate
            {
                if (refugee == enemyFac.leader)
                {
                    enemyFac.GenerateNewLeader();
                }

                Find.WorldPawns.RemovePawn(refugee);
                var canDrop = enemyFac.def.techLevel >= TechLevel.Spacer;

                if (canDrop)
                {
                    spawnSpot = DropCellFinder.TradeDropSpot(map);
                    TradeUtility.SpawnDropPod(spawnSpot, map, refugee);
                }
                else
                {
                    GenSpawn.Spawn(refugee, spawnSpot, map);
                }

                refugee.SetFaction(Faction.OfPlayer);
                Find.CameraDriver.JumpTo(spawnSpot);
                IncidentParms incidentParms = StorytellerUtility.DefaultParmsNow(Find.Storyteller.def, IncidentCategory.ThreatBig, map);
                incidentParms.forced          = true;
                incidentParms.faction         = enemyFac;
                incidentParms.raidStrategy    = RaidStrategyDefOf.ImmediateAttack;
                incidentParms.raidArrivalMode = canDrop ? PawnsArriveMode.CenterDrop : PawnsArriveMode.EdgeWalkIn;
                incidentParms.spawnCenter     = spawnSpot;
                incidentParms.points         *= RaidPointsFactor;
                QueuedIncident qi = new QueuedIncident(new FiringIncident(IncidentDefOf.RaidEnemy, null, incidentParms), Find.TickManager.TicksGame + RaidDelay.RandomInRange);
                Find.Storyteller.incidentQueue.Add(qi);
            };
            diaOption.resolveTree = true;
            diaNode.options.Add(diaOption);
            string text2 = "RefugeeChasedRejected".Translate(new object[]
            {
                refugee.NameStringShort
            });
            DiaNode   diaNode2   = new DiaNode(text2);
            DiaOption diaOption2 = new DiaOption("OK".Translate());
            diaOption2.resolveTree = true;
            diaNode2.options.Add(diaOption2);
            DiaOption diaOption3 = new DiaOption("RefugeeChasedInitial_Reject".Translate());
            diaOption3.action = delegate
            {
                HealthUtility.GiveInjuriesToKill(refugee);
                //Log.Message(refugee.Name + " dead? " + refugee.Dead);
                //Find.WorldPawns.PassToWorld(refugee,PawnDiscardDecideMode.Discard);
            };
            #endregion
            diaOption3.link = diaNode2;
            diaNode.options.Add(diaOption3);
            Find.WindowStack.Add(new Dialog_NodeTree(diaNode, true, true));
            return(true);
        }