示例#1
0
        public static Toil GotoGuest(Pawn pawn, Pawn talkee, bool mayBeSleeping = false)
        {
            var toil = Toils_Interpersonal.GotoInteractablePosition(TargetIndex.A);

            toil.AddFailCondition(() => !GuestUtility.ViableGuestTarget(talkee, mayBeSleeping));
            return(toil);
        }
示例#2
0
        private void SetAllDefaults(Pawn pawn)
        {
            Map map = SelPawn.MapHeld;

            if (map == null)
            {
                return;
            }

            var mapComp = Hospitality_MapComponent.Instance(map);

            if (pawn.GetComp <CompGuest>() != null)
            {
                mapComp.defaultInteractionMode = pawn.GetComp <CompGuest>().chat ? PrisonerInteractionModeDefOf.ReduceResistance : PrisonerInteractionModeDefOf.NoInteraction;
            }

            mapComp.defaultAreaRestriction = pawn.GetGuestArea();
            mapComp.defaultAreaShopping    = pawn.GetShoppingArea();

            var guests = GuestUtility.GetAllGuests(map);

            foreach (var guest in guests)
            {
                var comp = guest.GetComp <CompGuest>();
                if (comp != null)
                {
                    comp.chat         = mapComp.defaultInteractionMode == PrisonerInteractionModeDefOf.ReduceResistance;
                    comp.GuestArea    = mapComp.defaultAreaRestriction;
                    comp.ShoppingArea = mapComp.defaultAreaShopping;
                }
            }
        }
        protected override bool TryExecuteWorker(IncidentParms parms)
        {
            var map = (Map)parms.target;

            if (!GuestUtility.GetAllGuests(map).Where(IsHappyGuest).TryMaxBy(GetScore, out var happiestGuest))
            {
                return(false);
            }

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

            var title  = "LetterLabelHappyGuestJoins".Translate(happiestGuest.Named("PAWN")).CapitalizeFirst();
            var letter = (ChoiceLetter_GuestJoinRequest)LetterMaker.MakeLetter(title, "HappyGuestJoins".Translate(happiestGuest.Faction.Name, happiestGuest.Named("PAWN")).AdjustedFor(happiestGuest), def.letterDef);

            letter.title          = title;
            letter.radioMode      = true;
            letter.guest          = happiestGuest;
            letter.lookTargets    = happiestGuest;
            letter.relatedFaction = happiestGuest.Faction;
            Find.LetterStack.ReceiveLetter(letter);
            return(true);
        }
示例#4
0
        private void RescuedCheck()
        {
            var pawn = (Pawn)parent;

            if (pawn.Faction == Faction.OfPlayer)
            {
                rescued = false;
                return;
            }
            if (pawn.Downed || pawn.InBed())
            {
                return;
            }

            // Can walk again, make the roll
            rescued = false;

            // Copied from Pawn_GuestTracker
            if (pawn.RaceProps.Humanlike && pawn.HostFaction == Faction.OfPlayer && !pawn.IsPrisoner)
            {
                if (!GuestUtility.WillRescueJoin(pawn))
                {
                    return;
                }

                GuestUtility.ShowRescuedPawnDialog(pawn);
            }
        }
示例#5
0
        private void DoAreaRestriction(Listing_Standard listing, Area area, Action <Area> setArea, Func <Area, string> getLabel)
        {
            var areaRect = listing.GetRect(24);

            // Needed for GUI
            if (SelPawn.playerSettings == null)
            {
                SelPawn.playerSettings = new Pawn_PlayerSettings(SelPawn)
                {
                    AreaRestriction = area
                };
            }

            SelPawn.playerSettings.AreaRestriction = area;
            GuestUtility.DoAllowedAreaSelectors(areaRect, SelPawn, getLabel);
            var newArea = SelPawn.playerSettings.AreaRestriction;

            SelPawn.playerSettings.AreaRestriction = null;
            Text.Anchor = TextAnchor.UpperLeft;

            if (newArea != area)
            {
                setArea(newArea);
            }
        }
        private void Arrive()
        {
            //Log.Message("Init State_VisitPoint "+brain.ownedPawns.Count + " - "+brain.faction.name);
            foreach (var pawn in lord.ownedPawns)
            {
                if (pawn.needs?.mood == null)
                {
                    Data.visitorMoods.Add(pawn.thingIDNumber, 0.5f);
                }
                else
                {
                    Data.visitorMoods.Add(pawn.thingIDNumber, pawn.needs.mood.CurInstantLevel);
                }
                //Log.Message("Added "+pawn.NameStringShort+": "+pawn.needs.mood.CurLevel);

                var tweak      = 0; // -0.1f;
                var regularity = Mathf.Lerp(-0.5f, 0.25f, Mathf.InverseLerp(-100, 100, lord.faction.PlayerGoodwill));
                // negative factions have lower expectations
                float expectations = tweak + regularity;
                Data.visitorMoods[pawn.thingIDNumber] += expectations;

                pawn.Arrive();
            }

            GuestUtility.OnLordArrived(lord);

            // Lessons
            LessonAutoActivator.TeachOpportunity(ConceptDef.Named("GuestBeds"), lord.ownedPawns.FirstOrDefault(), OpportunityType.Important);
            if (PlayerHasSkilledNegotiator)
            {
                LessonAutoActivator.TeachOpportunity(ConceptDef.Named("RecruitGuest"), lord.ownedPawns.FirstOrDefault(), OpportunityType.GoodToKnow);
            }
        }
        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();
            }
        }
 public static void SetupAsVisitor(this Pawn visitor)
 {
     GuestUtility.AddNeedJoy(visitor);
     GuestUtility.AddNeedComfort(visitor);
     visitor.FixTimetable();
     visitor.FixDrugPolicy();
 }
        internal static void SetAllDefaults(Pawn pawn)
        {
            Map map = pawn.MapHeld;

            if (map == null)
            {
                return;
            }

            var mapComp = map.GetMapComponent();

            if (pawn.CompGuest() != null)
            {
                mapComp.defaultEntertain   = pawn.CompGuest().entertain;
                mapComp.defaultMakeFriends = pawn.CompGuest().makeFriends;
            }

            mapComp.defaultAreaRestriction = pawn.GetGuestArea();
            mapComp.defaultAreaShopping    = pawn.GetShoppingArea();

            var guests = GuestUtility.GetAllGuests(map);

            foreach (var guest in guests)
            {
                var comp = guest.CompGuest();
                if (comp != null)
                {
                    comp.entertain    = mapComp.defaultEntertain;
                    comp.makeFriends  = mapComp.defaultMakeFriends;
                    comp.GuestArea    = mapComp.defaultAreaRestriction;
                    comp.ShoppingArea = mapComp.defaultAreaShopping;
                }
            }
        }
示例#10
0
 public override void UpdateAllDuties()
 {
     foreach (Pawn pawn in lord.ownedPawns)
     {
         GuestUtility.AddNeedJoy(pawn);
         GuestUtility.AddNeedComfort(pawn);
         pawn.mindState.duty = new PawnDuty(GuestUtility.relaxDef, pawn.Position, Data.radius);
     }
 }
示例#11
0
        public override void Interacted(Pawn recruiter, Pawn guest, List <RulePackDef> extraSentencePacks)
        {
            if (recruiter == null || guest == null || guest.guest == null)
            {
                return;
            }

            GuestUtility.TryPleaseGuest(recruiter, guest, false, extraSentencePacks);
        }
 public override void WorldLoaded()
 {
     ToggleTabIfNeeded();
     foreach (var map in Find.Maps)
     {
         map.GetMapComponent().RefreshGuestListTotal();
     }
     GuestUtility.Initialize();
 }
        public override bool ActivateOn(Lord lord, TriggerSignal signal)
        {
            bool leave = base.ActivateOn(lord, signal);

            if (GuestUtility.GuestsShouldStayLonger(lord))
            {
                return(false);
            }
            return(leave);
        }
示例#14
0
        protected static bool IsBusy(Pawn p)
        {
            // Non-suspendable job? We're busy!
            if (p.CurJob != null && !p.CurJob.def.suspendable)
            {
                return(true);
            }

            return(p.interactions.InteractedTooRecentlyToInteract() || GuestUtility.IsInTherapy(p));
        }
        private static float GetMissingPercentage(Pawn pawn)
        {
            var friends         = pawn.GetFriendsInColony();
            var friendsRequired = GuestUtility.FriendsRequired(pawn.MapHeld) + pawn.GetEnemiesInColony();

            if (friendsRequired <= 0 || friends >= friendsRequired)
            {
                return(0);
            }
            return(1 - 1f * friends / friendsRequired);
        }
示例#16
0
        public static void RecruitDialog(Pawn pawn, bool forced)
        {
            var penalty       = forced ? pawn.ForcedRecruitPenalty() : pawn.RecruitPenalty();
            int finalGoodwill = Mathf.Clamp(pawn.Faction.PlayerGoodwill - penalty, -100, 100);

            var warning = finalGoodwill <= DiplomacyTuning.BecomeHostileThreshold ? "ForceRecruitWarning".Translate() : TaggedString.Empty;

            var text = (forced ? "ForceRecruitQuestion" : "RecruitQuestion").Translate(penalty.ToString("##0"), ColoredText.Colorize(warning, ColoredText.FactionColor_Hostile), new NamedArgument(pawn, "PAWN"));

            Find.WindowStack.Add(Dialog_MessageBox.CreateConfirmation(text, () => GuestUtility.Recruit(pawn, penalty, forced)));
        }
示例#17
0
        public static Toil GotoGuest(Pawn pawn, Pawn talkee, bool mayBeSleeping = false)
        {
            var toil = new Toil
            {
                initAction          = () => pawn.pather.StartPath(talkee, PathEndMode.Touch),
                defaultCompleteMode = ToilCompleteMode.PatherArrival
            };

            toil.AddFailCondition(() => !GuestUtility.ViableGuestTarget(talkee, mayBeSleeping));
            return(toil);
        }
        protected override bool CanFireNowSub(IncidentParms parms)
        {
            if (!base.CanFireNowSub(parms))
            {
                return(false);
            }

            Map map = (Map)parms.target;

            return(GuestUtility.GetAllGuests(map).Any(IsHappyGuest));
        }
示例#19
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);
        }
示例#20
0
        public override void Interacted(Pawn recruiter, Pawn guest, List <RulePackDef> extraSentencePacks, out string letterText, out string letterLabel, out LetterDef letterDef)
        {
            letterDef   = null;
            letterLabel = null;
            letterText  = null;
            if (recruiter == null || guest == null || guest.guest == null)
            {
                return;
            }

            GuestUtility.TryPleaseGuest(recruiter, guest, false, extraSentencePacks);
        }
示例#21
0
        public static void DoAreaRestriction(Rect rect, Area area, Action <Area> setArea, Func <Area, string> getLabel)
        {
            var newArea = area;

            GuestUtility.DoAllowedAreaSelectors(rect, getLabel, ref newArea);
            Text.Anchor = TextAnchor.UpperLeft;

            if (newArea != area)
            {
                setArea(newArea);
            }
        }
示例#22
0
        private void FillIncidentQueue()
        {
            // Add some visits
            float days = Rand.Range(8f, 15f);

            foreach (var faction in Find.FactionManager.AllFactionsVisible.Where(f => !f.IsPlayer && f != Faction.OfPlayer && f.PlayerGoodwill > 0).OrderByDescending(f => f.PlayerGoodwill))
            {
                Log.Message(faction.GetCallLabel() + " are coming after " + days + " days.");
                GuestUtility.PlanNewVisit(map, days, faction);
                days += Rand.Range(10f, 15f);
            }
        }
示例#23
0
        public override void Interacted(Pawn recruiter, Pawn guest, List <RulePackDef> extraSentencePacks)
        {
            if (recruiter == null || guest == null || guest.guest == null)
            {
                return;
            }

            // TODO: pawn.records.Increment(RecordDefOf.GuestsCharmAttempts);
            //recruiter.skills.Learn(SkillDefOf.Social, 35f);
            float pleaseChance = recruiter.GetStatValue(statPleaseGuestChance);

            pleaseChance = GuestUtility.AdjustPleaseChance(pleaseChance, recruiter, guest);
            pleaseChance = Mathf.Clamp01(pleaseChance);

            if (Rand.Value > pleaseChance)
            {
                var    isAbrasive     = recruiter.story.traits.HasTrait(TraitDefOf.Abrasive);
                int    multiplier     = isAbrasive ? 2 : 1;
                string multiplierText = multiplier > 1 ? " x" + multiplier : string.Empty;

                string textAnger = recruiter.gender == Gender.Female ? "RecruitAngerSelfF" : "RecruitAngerSelfM";
                Messages.Message(
                    textAnger.Translate(new object[]
                                        { recruiter.NameStringShort, guest.NameStringShort, (1 - pleaseChance).ToStringPercent(), multiplierText }),
                    guest, MessageSound.Negative);

                extraSentencePacks.Add(RulePackDef.Named("Sentence_CharmAttemptRejected"));
                for (int i = 0; i < multiplier; i++)
                {
                    GuestUtility.GainSocialThought(recruiter, guest, ThoughtDef.Named("GuestOffended"));
                }
            }
            else
            {
                var    statValue      = recruiter.GetStatValue(statRecruitEffectivity);
                var    floor          = Mathf.FloorToInt(statValue);
                int    multiplier     = floor + (Rand.Value < statValue - floor ? 1 : 0);
                string multiplierText = multiplier > 1 ? " x" + multiplier : string.Empty;

                string textPlease = recruiter.gender == Gender.Female ? "RecruitPleaseSelfF" : "RecruitPleaseSelfM";
                Messages.Message(
                    textPlease.Translate(new object[]
                                         { recruiter.NameStringShort, guest.NameStringShort, (pleaseChance).ToStringPercent(), multiplierText }),
                    guest, MessageSound.Benefit);
                for (int i = 0; i < multiplier; i++)
                {
                    GuestUtility.GainSocialThought(recruiter, guest, ThoughtDef.Named("GuestConvinced"));
                }
                extraSentencePacks.Add(RulePackDef.Named("Sentence_CharmAttemptAccepted"));
            }
            GuestUtility.GainSocialThought(recruiter, guest, ThoughtDef.Named("GuestDismissiveAttitude"));
        }
示例#24
0
        public override void Notify_PawnLost(Pawn pawn, PawnLostCondition condition)
        {
            if (condition == PawnLostCondition.ExitedMap)
            {
                return;
            }

            Log.Message("lord owns " + lord.ownedPawns.Select(p => p.LabelShort).ToCommaList());
            if (!lord.ownedPawns.Any())
            {
                GuestUtility.OnLostEntireGroup(lord);
            }
        }
        public override bool TryExecute(IncidentParms parms)
        {
            if (!TryResolveParms(parms))
            {
                return(false);
            }
            if (parms.faction == Faction.OfPlayer)
            {
                return(false);
            }

            Map map = (Map)parms.target;

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

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

            string reasons;

            // We check here instead of CanFireNow, so we can reschedule the visit.
            // Any reasons not to come?
            if (CheckCanCome(map, parms.faction, out reasons))
            {
                // No, spawn
                return(SpawnGroup(parms, map));
            }
            // Yes, ask the player for permission
            ShowAskMayComeDialog(parms.faction, reasons,
                                 // Permission, spawn
                                 () => SpawnGroup(parms, map),
                                 // No permission, come again later
                                 () => {
                Log.Message("Come back later");

                GuestUtility.PlanNewVisit(map, Rand.Range(2f, 5f), parms.faction);
            });
            return(true);
        }
示例#26
0
        public override void Notify_PawnLost(Pawn pawn, PawnLostCondition condition)
        {
            if (condition == PawnLostCondition.ExitedMap)
            {
                return;
            }

            pawn.ownership.UnclaimAll();

            if (!lord.ownedPawns.Any())
            {
                GuestUtility.OnLostEntireGroup(lord);
            }
        }
        private bool SpawnGroup(IncidentParms parms, Map map)
        {
            List <Pawn> visitors;

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

                CheckVisitorsValid(visitors);
            }
            catch (Exception e)
            {
                Log.ErrorOnce("Something failed when spawning visitors: " + e.Message + "\n" + e.StackTrace, 464365853);
                GuestUtility.PlanNewVisit(map, Rand.Range(1f, 3f), parms.faction);
                return(true); // be gone, event
            }
            if (visitors == null || visitors.Count == 0)
            {
                return(false);
            }

            foreach (var visitor in visitors)
            {
                GuestUtility.AddNeedJoy(visitor);
                GuestUtility.AddNeedComfort(visitor);
                visitor.FixTimetable();
                visitor.FixDrugPolicy();
                //Log.Message(visitor.NameStringShort + ": "
                //            + visitor.drugs.CurrentPolicy[ThingDefOf.Luciferium].allowedForJoy);
                visitor.GetComp <CompGuest>().sentAway = false;
            }

            var spot = GetSpot(map, visitors.First().GetGuestArea());

            if (!spot.IsValid)
            {
                Log.ErrorOnce("Visitors failed to find a valid travel target.", 827358325);
                foreach (var visitor in visitors)
                {
                    visitor.DestroyOrPassToWorld();
                }
                return(false);
            }

            GiveItems(visitors);

            CreateLord(parms.faction, spot, visitors, map);
            return(true);
        }
        private void Leave()
        {
            GuestUtility.OnLordLeft(lord);
            var  pawns   = lord.ownedPawns.ToArray(); // Copy, because recruiting changes lord
            bool hostile = lord.faction.RelationWith(Faction.OfPlayer).kind == FactionRelationKind.Hostile;

            bool sentAway = false;

            foreach (var pawn in pawns)
            {
                var compGuest = pawn.CompGuest();
                if (compGuest != null)
                {
                    if (compGuest.sentAway)
                    {
                        sentAway = true;
                    }
                    if (!hostile)
                    {
                        var score = GetVisitScore(pawn);

                        if (score > 0.99f)
                        {
                            LeaveVerySatisfied(pawn, score);
                        }
                        else if (score > 0.65f)
                        {
                            LeaveSatisfied(pawn, score);
                        }
                    }
                }
                pawn.Leave();
            }

            // Rescued pawns don't factor in here. If the group is only rescued pawns, we want no message
            var nonRescuedPawns = lord.ownedPawns.Where(p => p.CompGuest()?.rescued != true).ToArray();

            if (nonRescuedPawns.Any() && !hostile)
            {
                var avgScore = nonRescuedPawns.Average(GetVisitScore);

                DisplayLeaveMessage(avgScore, lord.faction, lord.ownedPawns.Count, lord.Map, sentAway);
            }
            else
            {
                DisplayNoMessage(lord.faction, lord.Map);
            }
        }
示例#29
0
        public static void ShowWandererJoinDialog(Pawn pawn, IntVec3 spawnSpot, Map map)
        {
            // Added option to reject wanderer

            string textAsk = "WandererInitial".Translate(pawn.Faction.Name, pawn.GetTitle().ToLower(), GenText.ToCommaList(pawn.story.traits.allTraits.Select(t => t.Label)));

            textAsk = textAsk.AdjustedFor(pawn);
            PawnRelationUtility.TryAppendRelationsWithColonistsInfo(ref textAsk, pawn);
            DiaNode nodeAsk    = new DiaNode(textAsk);
            var     textAccept = "RescuedInitial_Accept".Translate();

            textAccept = textAccept.AdjustedFor(pawn);

            DiaOption optionAccept = new DiaOption(textAccept);

            optionAccept.action = () => {
                if (Find.WorldPawns.Contains(pawn))
                {
                    Find.WorldPawns.RemovePawn(pawn);
                }
                GenSpawn.Spawn(pawn, spawnSpot, map);
                if (pawn.Faction != Faction.OfPlayer)
                {
                    if (pawn.Faction != null && pawn == pawn.Faction.leader)
                    {
                        pawn.Faction.GenerateNewLeader();
                    }
                    pawn.SetFaction(Faction.OfPlayer);
                }

                Find.CameraDriver.JumpTo(pawn.Position);
            };
            optionAccept.resolveTree = true;
            nodeAsk.options.Add(optionAccept);

            var textReject = "RescuedInitial_Reject".Translate();

            textReject = textReject.AdjustedFor(pawn);

            DiaOption optionReject = new DiaOption(textReject);

            optionReject.action      = () => { GuestUtility.BreakupRelations(pawn); };
            optionReject.resolveTree = true;

            nodeAsk.options.Add(optionReject);
            Find.WindowStack.Add(new Dialog_NodeTree(nodeAsk, true));
        }
        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);
        }