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