示例#1
0
        public override void MapComponentTick()
        {
            // No Rare version of MapComponentTick, so this will do.
            if (!AncestorUtils.IsIntervalTick())
            {
                return;
            }
            if (!this.initialized)
            {
                this.Initialize();
            }

            for (int i = this.despawnBuffer.Count - 1; i >= 0; i--)
            {
                this.DespawnVisitor(this.despawnBuffer[i]);
            }

            if (!this.visitSchedule.IsScheduledForCurrentSeason)
            {
                this.visitSchedule = AncestorVisitScheduler.BuildSeasonScheduleForCurrentSeason();
            }

            this.visitSchedule.VisitScheduleTickInterval();
            this.approval.ApprovalTrackerTickInterval(this);
            this.timer.AncestorMemoTimerTickInterval(this.approval);
        }
示例#2
0
        public override void Init()
        {
            // Set duration to 1 less than "Permenant" because this will end when visitors despawned
            this.originalDuration = this.duration;
            this.duration         = 999999999;

            var introDef = DefDatabase <ConceptDef> .GetNamed("MTW_AncestorVisit");

            LessonAutoActivator.TeachOpportunity(introDef, OpportunityType.Important);

            var spawnController = AncestorUtils.GetMapComponent();

            for (int i = 0; i < AncestorConstants.ANCESTORS_PER_VISIT; i++)
            {
                var spawned = spawnController.TrySpawnRandomVisitor();
                if (spawned != null)
                {
                    this.visitors.Add(spawned);
                    this.visitInfoMap.Add(spawned.thingIDNumber, new PawnVisitInfo(spawned, this.EstDurationDays));
                }
            }

            var loiterPoint = spawnController.CurrentSpawner.Position;
            var lordJob     = new LordJob_HauntColony(loiterPoint, this.duration);
            var lord        = LordMaker.MakeNewLord(spawnController.AncestorFaction, lordJob, this.visitors);
        }
示例#3
0
        public override void MapConditionTick()
        {
            if (!AncestorUtils.IsIntervalTick())
            {
                return;
            }

            // Remove despawned visitors
            this.visitors = visitors.Where(p => p.Spawned).ToList();

            if (this.visitors.Count == 0)
            {
                this.duration = 0;
                this.SubmitApprovalChanges();
            }
            else
            {
                foreach (Pawn p in this.visitors)
                {
                    this.PawnApprovalTickInterval(p);
                }

                if (this.EstRemainingDays < -1f)
                {
                    this.QueueForcedEnd();
                }
            }
        }
        protected override ThoughtState CurrentStateInternal(Pawn p)
        {
            // TODO: There's gotta be a better way of doin' this!
            if (!AncestorUtils.IsAncestor(p))
            {
                return(ThoughtState.Inactive);
            }

            var shrine = AncestorUtils.GetMapComponent().CurrentSpawner;

            if (shrine == null)
            {
                return(ThoughtState.ActiveAtStage(1));
            }

            // HACK ALERT! Change Shrines to have an Interaction cell, and use that instead of a random one!
            var room = RoomQuery.RoomAtFast(shrine.RandomAdjacentCellCardinal());

            if (room == null)
            {
                return(ThoughtState.ActiveAtStage(1));
            }
            else if (room.Role != shrineRoomDef)
            {
                return(ThoughtState.ActiveAtStage(1));
            }
            else
            {
                return(ThoughtState.Inactive);
            }
        }
        private void DespawnAllPawnsAndTerminate()
        {
            var ancestorTicker = AncestorUtils.GetMapComponent();
            var pawns          = this.lord.ownedPawns.ToList();

            for (int i = pawns.Count - 1; i >= 0; i--)
            {
                ancestorTicker.Notify_ShouldDespawn(pawns[i], AncestorLeftCondition.AnchorDestroyed);
            }
        }
示例#6
0
        public override string GetInspectString()
        {
            int magic = AncestorUtils.GetMapComponent().CurrentMagic;

            StringBuilder builder = new StringBuilder();

            builder.AppendLine("Magic available: " + magic);
            builder.AppendLine("Magic for next ritual: " + this.MagicForNextRitual);
            builder.Append(base.GetInspectString());

            return(builder.ToString());
        }
示例#7
0
 public void QueueForcedEnd()
 {
     if (!this.forcedEnd)
     {
         var spawnController = AncestorUtils.GetMapComponent();
         foreach (var visitor in this.visitors.Where(p => p.Spawned))
         {
             spawnController.Notify_ShouldDespawn(visitor, AncestorLeftCondition.LeftVoluntarily);
         }
         this.forcedEnd = true;
     }
 }
示例#8
0
 public override void CompTick()
 {
     base.CompTick();
     if (this.parent is Pawn)
     {
         if (!this.hasSet)
         {
             AncestorUtils.SetAncestorGraphics((Pawn)this.parent);
             this.hasSet = true;
         }
     }
     else
     {
         Log.ErrorOnce("Cannot add SpiritGraphics to non-Pawn Thing " + this.parent.Label, 65447891);
     }
 }
        public override float GetScore(Room room)
        {
            // I don't know if there should be some "If it's full of joy objects/work benches, *don't* classify it as
            // a Shrine - if you Shrine room wall gets broken down by a bug, this will probably push all the attached
            // rooms into the "Shrine Room" - is that a desired behaviour?

            var shrine = AncestorUtils.GetMapComponent().CurrentSpawner;

            if (shrine != null && room.AllContainedThings.Contains <Thing>(shrine))
            {
                return(9999.0f);
            }
            else
            {
                return(0.0f);
            }
        }
示例#10
0
        public void TryFireVisit()
        {
            if (AncestorUtils.GetMapComponent().CurrentSpawner != null)
            {
                this.FireVisit();
            }
            else if (Find.TickManager.TicksGame < AncestorVisitScheduler.BufferGameStartTicks)
            {
                this.FireVisitNoAnchorButNewColony();
            }
            else
            {
                this.FireVisitImpossibleWithoutAnchor();
            }

            this.HasFired = true;
        }
示例#11
0
        public override bool TryExecute(IncidentParms parms)
        {
            // Force a transition
            WeatherDef weatherDef = DefDatabase <WeatherDef> .GetNamed("MTW_HeavyWind");

            Find.WeatherManager.TransitionTo(weatherDef);

            // Set the duration using reflection
            int weatherDuration = AncestorUtils.DaysToTicks(this.def.durationDays.RandomInRange);
            var decider         = Find.Storyteller.weatherDecider;

            typeof(WeatherDecider)
            .GetField("curWeatherDuration", BindingFlags.Instance | BindingFlags.NonPublic)
            .SetValue(decider, weatherDuration);

            return(true);
        }
示例#12
0
        public override void ExposeData()
        {
            base.ExposeData();

            Scribe_Values.LookValue <bool>(ref initialized, "initialized", false);
            Scribe_Values.LookValue <int>(ref numAncestorsToVisit, "numAncestorsToVisit", 3);
            Scribe_Deep.LookDeep <ApprovalTracker>(ref this.approval, "approval", new object[0]);
            Scribe_Deep.LookDeep <AncestorMemoTimer>(ref this.timer, "timer", new object[0]);
            Scribe_Collections.LookList <Pawn>(ref this.unspawnedAncestors, "unspawnedAncestors", LookMode.Deep, new object[0]);
            Scribe_Collections.LookList <Building>(ref this.spawners, "spawners", LookMode.MapReference);
            // Probably there's a better way to do this!
            if (this.visitSchedule == null)
            {
                var seasonStart = AncestorUtils.EstStartOfSeasonAt(Find.TickManager.TicksGame);
                this.visitSchedule = AncestorVisitScheduler.BuildSeasonSchedule(seasonStart);
            }
            Scribe_Deep.LookDeep <VisitScheduleForSeason>(ref this.visitSchedule, "visitSchedule", new object[0]);
        }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            //Set fail conditions
            this.FailOnDestroyedNullOrForbidden(ShrineIndex);

            yield return(Toils_Reserve.Reserve(ShrineIndex));

            yield return(Toils_Goto.GotoThing(ShrineIndex, PathEndMode.ClosestTouch));

            Toil toilPetition = new Toil();

            toilPetition.initAction = () =>
            {
                this.ticksElapsed = 0;
            };

            toilPetition.AddPreTickAction(() =>
            {
                if (this.ticksElapsed > this.PetitionJob.PetitionTicks)
                {
                    ReadyForNextToil();
                }
            });

            toilPetition.tickAction = () =>
            {
                this.ticksElapsed++;
            };

            toilPetition.AddFinishAction(() =>
            {
                AncestorUtils.GetMapComponent().Notify_PetitionMade(this.PetitionDef, this.pawn);
            });

            toilPetition.defaultCompleteMode = ToilCompleteMode.Never;

            yield return(toilPetition);
        }
示例#14
0
        protected override IEnumerable <Toil> MakeNewToils()
        {
            //Set fail conditions
            this.FailOnDestroyedNullOrForbidden(ShrineIndex);

            yield return(Toils_Goto.GotoThing(ShrineIndex, PathEndMode.ClosestTouch));

            Toil toilReturn = new Toil();

            toilReturn.initAction = () =>
            {
                this.ticksElapsed = 0;
            };

            // We don't do it in the "ending" action because it'll cause a NPE - when you despawn the pawn it finishes
            // all the toils it has, and by then the pawn already has been despawned, so this.pawn is null.
            //
            // There's probably a more elegant way of fixing this.
            toilReturn.AddPreTickAction(() =>
            {
                if (this.ticksElapsed > returnDurationTicks)
                {
                    var ticker = AncestorUtils.GetMapComponent();
                    ticker.Notify_ShouldDespawn(this.pawn, AncestorLeftCondition.LeftVoluntarily);
                    ReadyForNextToil();
                }
            });

            toilReturn.tickAction = () =>
            {
                this.ticksElapsed++;
            };

            toilReturn.defaultCompleteMode = ToilCompleteMode.Never;

            yield return(toilReturn);
        }
        protected override Job TryGiveJob(Pawn pawn)
        {
            if (pawn.CurJob != null)
            {
                return(pawn.CurJob);
            }

            var spawner = AncestorUtils.GetMapComponent().CurrentSpawner;

            if (spawner == null)
            {
                return(null);
            }

            IntVec3 anchorCell;

            GenAdj.TryFindRandomWalkableAdjacentCell8Way(spawner, out anchorCell);
            if (anchorCell == null)
            {
                return(null);
            }

            var path = PathFinder.FindPath(pawn.Position, anchorCell,
                                           TraverseParms.For(pawn, Danger.Deadly, TraverseMode.PassAnything));
            IntVec3 cellBeforeBlocker;
            Thing   blocker = path.FirstBlockingBuilding(out cellBeforeBlocker, pawn);

            if (blocker != null)
            {
                var ticker = AncestorUtils.GetMapComponent();
                ticker.Notify_ShouldDespawn(pawn, AncestorLeftCondition.AnchorBlocked);
            }
            path.Dispose();

            Find.PawnDestinationManager.ReserveDestinationFor(pawn, anchorCell);
            return(new Job(DefDatabase <JobDef> .GetNamed("MTW_ReturnAnchor"), spawner));
        }
示例#16
0
 public override void PostMake()
 {
     base.PostMake();
     AncestorUtils.GetMapComponent().Notify_SpawnerCreated(this);
 }
示例#17
0
        private void SubmitApprovalChanges()
        {
            var summary = new AncestralVisitSummary(this.visitors, this.visitInfoMap);

            AncestorUtils.GetMapComponent().Notify_VisitEnded(summary);
        }
示例#18
0
 public override void DeSpawn()
 {
     base.DeSpawn();
     AncestorUtils.GetMapComponent().Notify_SpawnerDestroyed(this);
 }
        public override StateGraph CreateGraph()
        {
            StateGraph graph          = new StateGraph();
            var        hauntPointToil = new LordToil_Relax();

            graph.StartingToil = hauntPointToil;

            // Return to Anchor
            LordToil returnAnchorToil = new LordToil_ReturnAnchor();

            graph.lordToils.Add(returnAnchorToil);
            Transition t1 = new Transition(hauntPointToil, returnAnchorToil);

            t1.triggers.Add(new Trigger_TicksPassed(this.duration));
            t1.preActions.Add(new TransitionAction_Message("Your Ancestors are leaving!"));
            graph.transitions.Add(t1);

            // Link ALL nodes to Exit if Anchor Destroyed
            LordToil endToil = new LordToil_End();

            graph.lordToils.Add(endToil);
            var ancestorTicker = AncestorUtils.GetMapComponent();

            foreach (var toil in graph.lordToils.Where(t => t != endToil))
            {
                Transition endTransition = new Transition(toil, endToil);
                endTransition.triggers.Add(new Trigger_TickCondition(() => ancestorTicker.CurrentSpawner == null));
                endTransition.preActions.Add(new TransitionAction_Message(
                                                 "The Anchor has been destroyed! Your Ancestors will be torn from the mortal plane! They won't forget this!"));
                endTransition.preActions.Add(new TransitionAction_Custom(this.DespawnAllPawnsAndTerminate));
                graph.transitions.Add(endTransition);
            }

            return(graph);

            /* wowee thar's a doozy
             * StateGraph graphArrive = new StateGraph();
             * var travelGraph = new LordJob_Travel(chillSpot).CreateGraph();
             * travelGraph.StartingToil = new LordToil_CustomTravel(chillSpot, 0.49f); // CHANGED: override StartingToil
             * LordToil toilArrive = graphArrive.AttachSubgraph(travelGraph).StartingToil;
             * var toilVisit = new LordToil_VisitPoint(chillSpot); // CHANGED
             * graphArrive.lordToils.Add(toilVisit);
             * LordToil toilTakeWounded = new LordToil_TakeWoundedGuest();
             * graphArrive.lordToils.Add(toilTakeWounded);
             * StateGraph graphExit = new LordJob_TravelAndExit(IntVec3.Invalid).CreateGraph();
             * LordToil toilExit = graphArrive.AttachSubgraph(graphExit).StartingToil;
             * LordToil toilLeaveMap = graphExit.lordToils[1];
             * LordToil toilLost = new LordToil_End();
             * graphExit.AddToil(toilLost);
             * Transition t1 = new Transition(toilArrive, toilVisit);
             * t1.triggers.Add(new Trigger_Memo("TravelArrived"));
             * graphArrive.transitions.Add(t1);
             * LordToil_ExitMapBest toilExitCold = new LordToil_ExitMapBest(); // ADDED TOIL
             * graphArrive.AddToil(toilExitCold);
             * Transition t6 = new Transition(toilArrive, toilExitCold); // ADDED TRANSITION
             * t6.triggers.Add(new Trigger_UrgentlyCold());
             * t6.preActions.Add(new TransitionAction_Message("MessageVisitorsLeavingCold".Translate(new object[] { faction.Name })));
             * t6.preActions.Add(new TransitionAction_Custom(() => StopPawns(lord.ownedPawns)));
             * graphArrive.transitions.Add(t6);
             * Transition t2 = new Transition(toilVisit, toilTakeWounded);
             * t2.triggers.Add(new Trigger_WoundedGuestPresent());
             * t2.preActions.Add(new TransitionAction_Message("MessageVisitorsTakingWounded".Translate(new object[] { faction.def.pawnsPlural.CapitalizeFirst(), faction.Name })));
             * graphArrive.transitions.Add(t2);
             * Transition t3 = new Transition(toilVisit, toilLeaveMap);
             * t3.triggers.Add(new Trigger_BecameColonyEnemy());
             * t3.preActions.Add(new TransitionAction_WakeAll());
             * t3.preActions.Add(new TransitionAction_SetDefendLocalGroup());
             * graphArrive.transitions.Add(t3);
             * Transition t4 = new Transition(toilArrive, toilExit);
             * t4.triggers.Add(new Trigger_BecameColonyEnemy());
             * //t4.triggers.Add(new Trigger_VisitorsPleasedMax(MaxPleaseAmount(faction.ColonyGoodwill))); // CHANGED
             * t4.triggers.Add(new Trigger_VisitorsAngeredMax(IncidentWorker_VisitorGroup.MaxAngerAmount(faction.PlayerGoodwill))); // CHANGED
             * t4.preActions.Add(new TransitionAction_WakeAll());
             * t4.preActions.Add(new TransitionAction_EnsureHaveExitDestination());
             * graphArrive.transitions.Add(t4);
             * Transition t5 = new Transition(toilVisit, toilExit);
             * t5.triggers.Add(new Trigger_TicksPassed(Rand.Range(16000, 44000)));
             * t5.preActions.Add(new TransitionAction_Message("VisitorsLeaving".Translate(new object[] { faction.Name })));
             * t5.preActions.Add(new TransitionAction_WakeAll());
             * t5.preActions.Add(new TransitionAction_EnsureHaveExitDestination());
             * graphArrive.transitions.Add(t5);
             * return graphArrive;
             */
        }
示例#20
0
        public static VisitScheduleForSeason BuildSeasonScheduleForCurrentSeason()
        {
            long seasonStartTicks = AncestorUtils.EstStartOfSeasonAt(Find.TickManager.TicksAbs);

            return(BuildSeasonSchedule(seasonStartTicks));
        }
示例#21
0
 private void FireVisitImpossibleWithoutAnchor()
 {
     Messages.Message("Your Ancestors wanted to visit, but you have no Shrine! They are very displeased.",
                      MessageSound.Negative);
     AncestorUtils.GetMapComponent().Notify_VisitImpossibleWithoutAnchor();
 }