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