private Toil dismount() { ExtendedDataStorage store = Base.Instance.GetExtendedDataStorage(); Toil toil = new Toil(); toil.defaultCompleteMode = ToilCompleteMode.Never; toil.initAction = delegate { if (store == null) { ReadyForNextToil(); return; } ExtendedPawnData pawnData = store.GetExtendedDataFor(pawn); if (pawnData.mount != null) { pawnData.mount.jobs.EndCurrentJob(JobCondition.InterruptForced); } ReadyForNextToil(); }; return(toil); }
public static void RemoveAllLinks(this Pawn pawn) { ExtendedDataStorage store = Base.Instance.GetExtendedDataStorage(); if (store == null) { return; } ExtendedPawnData pawnData = store.GetExtendedDataFor(pawn); pawnData.isActive = false; pawn.RemoveRemoteControlLink(); if (pawn.ControllingAI() != null) { pawn.ControllingAI().controlledMechs.Remove(pawn); pawn.ControllingAI().hackedMechs.Remove(pawn); if (pawnData.originalFaction != null) { pawn.RevertToFaction(pawnData.originalFaction); } } }
static bool Prefix(Pawn __instance, ref List <WorkTypeDef> __result) { if (__instance.IsHacked()) { List <WorkTypeDef> shouldForbid = new List <WorkTypeDef>(); ExtendedDataStorage store = Base.Instance.GetExtendedDataStorage(); if (store != null) { ExtendedPawnData pawnData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(__instance); foreach (WorkTypeDef def in DefDatabase <WorkTypeDef> .AllDefs) { if (pawnData.workTypes == null || !pawnData.workTypes.Contains(def)) { shouldForbid.Add(def); } } __result = shouldForbid; return(false); } } return(true); }
public static void InitWorkTypesAndSkills(Pawn pawn, ExtendedPawnData pawnData) { if (pawnData.workTypes == null) { pawnData.workTypes = new List <WorkTypeDef>(); } if (pawn.skills == null) { pawn.skills = new Pawn_SkillTracker(pawn); } if (pawn.workSettings == null) { pawn.workSettings = new Pawn_WorkSettings(pawn); pawn.workSettings.EnableAndInitialize(); } if (pawn.skills != null) { if (pawn.skills.GetSkill(SkillDefOf.Shooting).Level == 0) { pawn.skills.GetSkill(SkillDefOf.Shooting).Level = 8; } if (pawn.skills.GetSkill(SkillDefOf.Melee).Level == 0) { pawn.skills.GetSkill(SkillDefOf.Melee).Level = 4; } } if (pawn.workSettings != null) { var huntingWorkType = WorkTypeDefOf.Hunting; if (pawnData.workTypes == null) { // Log.Message("WTHACK: " + pawn.Name); pawnData.workTypes = new List <WorkTypeDef>(); } pawnData.workTypes.Add(huntingWorkType); pawn.workSettings.SetPriority(huntingWorkType, 3); } }
static void Postfix(TransferableOneWayWidget __instance, ref bool anythingChanged) { //Reflection is needed here to access the private struct inside TransferableOneWayWidget Type sectionType = Traverse.Create(__instance).Type("Section").GetValue <Type>(); IList sections = Traverse.Create(__instance).Field("sections").GetValue <IList>(); foreach (object s in sections) { List <TransferableOneWay> tf = sectionType.GetField("cachedTransferables").GetValue(s) as List <TransferableOneWay>; } if (sections.Count < 4) { return; } object section = sections[3]; //section 3 only yields animals, which are needed in this case List <TransferableOneWay> cachedTransferables = sectionType.GetField("cachedTransferables").GetValue(section) as List <TransferableOneWay>; if (cachedTransferables != null) { foreach (TransferableOneWay tow in cachedTransferables) { Pawn towPawn = tow.AnyThing as Pawn; if (towPawn == null) { continue; } if (tow.CountToTransfer == -1) { ExtendedPawnData PawnData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(towPawn); if (PawnData.selectedForCaravan == true) { anythingChanged = true; Traverse.Create(tow).Property("CountToTransfer").SetValue(1); } } } } }
private static void parkAnimal(Pawn_JobTracker __instance, Pawn pawn, ExtendedPawnData pawnData) { Area_Stable areaFound = (Area_Stable)pawn.Map.areaManager.GetLabeled(Base.STABLE_LABEL); IntVec3 targetLoc = pawn.Position; if (areaFound != null) { targetLoc = DistanceUtility.getClosestAreaLoc(pawn, areaFound); } Job dismountJob = new Job(GUC_JobDefOf.Dismount); dismountJob.count = 1; __instance.jobQueue.EnqueueFirst(dismountJob); __instance.jobQueue.EnqueueFirst(new Job(JobDefOf.Goto, targetLoc)); PawnDuty animalDuty = pawnData.mount.mindState.duty; if (animalDuty != null) { animalDuty.focus = new LocalTargetInfo(targetLoc); } }
private static Gizmo GetRemoteControlActivateGizmo(Pawn pawn) { Command_Target command_Target = new Command_Target(); command_Target.defaultLabel = "WTH_Gizmo_RemoteControlActivate_Label".Translate(); command_Target.defaultDesc = "WTH_Gizmo_RemoteControlActivate_Description".Translate(); command_Target.targetingParams = GetTargetingParametersForHacking(); command_Target.hotKey = KeyBindingDefOf.Misc5; if (pawn.Drafted) { command_Target.Disable("WTH_Reason_PawnCannotBeDrafted".Translate()); } command_Target.icon = ContentFinder <Texture2D> .Get(("Things/MechControllerBelt")); command_Target.action = delegate(Thing target) { if (target is Pawn) { pawn.jobs.EndCurrentJob(JobCondition.InterruptForced, false); Pawn mech = (Pawn)target; ExtendedPawnData pawnData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(pawn); ExtendedPawnData mechData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(mech); pawnData.remoteControlLink = mech; mechData.remoteControlLink = pawn; mechData.isActive = true; mech.drafter.Drafted = true; Find.Selector.ClearSelection(); Find.Selector.Select(mech); if (pawn.GetLord() == null || pawn.GetLord().LordJob == null) { LordMaker.MakeNewLord(Faction.OfPlayer, new LordJob_ControlMechanoid(), pawn.Map, new List <Pawn> { pawn }); pawn.mindState.duty.focus = mech; } } }; return(command_Target); }
public override bool TryMakePreToilReservations(bool errorOnFailed) { //For automatic mounting, reserve the mount aswell as targets of the job the pawn is riding to (target B and possibly C). bool result = true; ExtendedDataStorage store = Base.Instance.GetExtendedDataStorage(); if (store == null) { return(true); } ExtendedPawnData pawnData = store.GetExtendedDataFor(this.pawn); if (pawnData.targetJob == null) { return(true); } result = ReserveUtility.ReserveEveryThingOfJob(pawnData.targetJob, this); pawnData.targetJob = null; return(result); }
static bool Prefix(ShieldBelt __instance) { bool ShouldDisplay = Traverse.Create(__instance).Property("ShouldDisplay").GetValue <bool>(); ExtendedPawnData pawnData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(__instance.Wearer); Pawn mount = pawnData.mount; if (mount == null) { return(true); } if (__instance.ShieldState == ShieldState.Active && ShouldDisplay) { float energy = Traverse.Create(__instance).Field("energy").GetValue <float>(); int lastAbsorbDamageTick = Traverse.Create(__instance).Field("lastAbsorbDamageTick").GetValue <int>(); Vector3 impactAngleVect = Traverse.Create(__instance).Field("impactAngleVect").GetValue <Vector3>(); Material BubbleMat = MaterialPool.MatFrom("Other/ShieldBubble", ShaderDatabase.Transparent); ; float num = Mathf.Lerp(1.2f, 1.55f, energy); Vector3 vector = __instance.Wearer.Drawer.DrawPos; vector.z += pawnData.drawOffset; vector.y = Altitudes.AltitudeFor(AltitudeLayer.MoteOverhead); int num2 = Find.TickManager.TicksGame - lastAbsorbDamageTick; if (num2 < 8) { float num3 = (float)(8 - num2) / 8f * 0.05f; vector += impactAngleVect * num3; num -= num3; } float angle = (float)Rand.Range(0, 360); Vector3 s = new Vector3(num, 1f, num); Matrix4x4 matrix = default(Matrix4x4); matrix.SetTRS(vector, Quaternion.AngleAxis(angle, Vector3.up), s); Graphics.DrawMesh(MeshPool.plane10, matrix, BubbleMat, 0); } return(false); }
private static void Cleanup(Pawn pawn, HediffDef removedHediff) { if (removedHediff == WTH_DefOf.WTH_TurretModule && pawn.health.hediffSet.HasHediff(WTH_DefOf.WTH_MountedTurret)) { pawn.health.RemoveHediff(pawn.health.hediffSet.hediffs.FirstOrDefault((Hediff h) => h.def == WTH_DefOf.WTH_MountedTurret)); } ExtendedPawnData pawnData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(pawn); if (removedHediff.GetModExtension <DefModExtension_Hediff_WorkModule>() is DefModExtension_Hediff_WorkModule ext) { pawnData.workTypes.RemoveAll((WorkTypeDef def) => ext.workTypes.Contains(def)); } if (!pawn.health.hediffSet.hediffs.Exists((Hediff h) => h.def.HasModExtension <DefModExtension_Hediff_WorkModule>())) { pawnData.workTypes = null; pawn.skills = null; pawn.workSettings = null; } if (removedHediff == WTH_DefOf.WTH_RepairModule) { Base.RemoveComps(pawn); } }
private Toil TalkToAnimal(TargetIndex tameeInd) { Toil toil = new Toil(); toil.AddFailCondition(delegate { return(Mount.CurJob.def != BM_JobDefOf.Mounted_BattleMount); }); toil.initAction = delegate { Pawn actor = toil.GetActor(); actor.interactions.TryInteractWith(Mount, InteractionDefOf.AnimalChat); }; toil.defaultCompleteMode = ToilCompleteMode.Delay; toil.defaultDuration = 150; toil.AddFinishAction(delegate { if (Mount.CurJob != null && Mount.CurJob.def == BM_JobDefOf.Mounted_BattleMount) { Pawn actor = toil.GetActor(); ExtendedPawnData pawnData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(actor); pawnData.mount = (Pawn)((Thing)actor.CurJob.GetTarget(tameeInd)); TextureUtility.setDrawOffset(pawnData); } }); return(toil); }
public static int adjustTicksPerMove(int num2, int index, List <Pawn> pawns) { ExtendedDataStorage store = GiddyUpCore.Base.Instance.GetExtendedDataStorage(); if (store == null || pawns == null || pawns.Count == 0) { return(num2); } Pawn pawn = pawns[index]; ExtendedPawnData pawnData = store.GetExtendedDataFor(pawn); if (pawnData != null && pawnData.caravanMount != null && pawn.ridingCaravanMount()) { //Log.Message("Returning adjusted ticks per move: " + "TicsPerMove was: " + num2 + ", but now: " + TicksPerMoveUtility.adjustedTicksPerMove(pawn, pawnData.caravanMount, true)); return(TicksPerMoveUtility.adjustedTicksPerMove(pawn, pawnData.caravanMount, true)); } else { //Log.Message("Returning default ticks per move: " + num2); return(num2); } }
private static ThinkResult InsertMountingJobs(Pawn pawn, Pawn closestAnimal, LocalTargetInfo target, LocalTargetInfo secondTarget, ref ExtendedPawnData pawnData, ExtendedPawnData animalData, Pawn_JobTracker __instance, ThinkResult __result) { ExtendedDataStorage store = Base.Instance.GetExtendedDataStorage(); //__instance.jobQueue.EnqueueFirst(dismountJob); if (pawn.CanReserve(target) && pawn.CanReserve(closestAnimal)) { Job oldJob = __result.Job; ExtendedPawnData pawnDataTest = store.GetExtendedDataFor(pawn); pawnDataTest.targetJob = oldJob; Job mountJob = new Job(GUC_JobDefOf.Mount, closestAnimal); Job rideToJob = new Job(GU_RR_DefOf.RideToJob, closestAnimal, target); if (pawnData.mount != null) { __instance.jobQueue.EnqueueFirst(oldJob); if (__result.Job.def != JobDefOf.Hunt)//Don't ride to job when hunting. { __result = new ThinkResult(rideToJob, __result.SourceNode, __result.Tag, false); } } else { __instance.jobQueue.EnqueueFirst(oldJob); if (__result.Job.def != JobDefOf.Hunt)//Don't ride to job when hunting. { __instance.jobQueue.EnqueueFirst(rideToJob); } __result = new ThinkResult(mountJob, __result.SourceNode, __result.Tag, false); } } return(__result); }
static bool Prefix(Pawn_StoryTracker __instance, ref List <WorkTypeDef> __result) { Pawn pawn = Traverse.Create(__instance).Field("pawn").GetValue <Pawn>(); if (pawn.RaceProps.IsMechanoid && pawn.IsHacked()) { List <WorkTypeDef> shouldForbid = new List <WorkTypeDef>(); ExtendedDataStorage store = Base.Instance.GetExtendedDataStorage(); if (store != null) { ExtendedPawnData pawnData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(pawn); foreach (WorkTypeDef def in DefDatabase <WorkTypeDef> .AllDefs) { if (pawnData.workTypes == null || !pawnData.workTypes.Contains(def)) { shouldForbid.Add(def); } } __result = shouldForbid; return(false); } } return(true); }
static void Postfix(Pawn_JobTracker __instance, ref ThinkResult __result) { Pawn pawn = Traverse.Create(__instance).Field("pawn").GetValue <Pawn>(); if (!pawn.IsColonistPlayerControlled) { return; } ExtendedDataStorage store = Base.Instance.GetExtendedDataStorage(); ExtendedPawnData pawnData = store.GetExtendedDataFor(pawn); if (store == null || pawnData == null) { return; } if (pawnData.owning == null || !pawnData.owning.Spawned || pawnData.owning.Downed || pawnData.owning.Dead || pawnData.mount != null) { return; } LocalTargetInfo target = DistanceUtility.GetFirstTarget(__result.Job, TargetIndex.A); float pawnTargetDistance = DistanceUtility.QuickDistance(pawnData.owning.Position, target.Cell); float riderMountDistance = DistanceUtility.QuickDistance(pawnData.owning.Position, pawn.Position); if (riderMountDistance > 12 || pawnTargetDistance > 12 || __result.Job.def == JobDefOf.LayDown || __result.Job.def == JobDefOf.Research || pawn.InMentalState || pawn.Dead || pawn.Downed) { if (pawnData.owning.jobs.curJob != null && pawnData.owning.jobs.curJob.def == JobDefOf.Wait) { pawnData.owning.jobs.EndCurrentJob(JobCondition.InterruptForced); } ExtendedPawnData animalData = store.GetExtendedDataFor(pawnData.owning); pawnData.owning = null; animalData.ownedBy = null; } }
protected override void PostSuccessfulApply(Pawn pawn, BodyPartRecord part, Pawn billDoer, List <Thing> ingredients, Bill bill) { base.PostSuccessfulApply(pawn, part, billDoer, ingredients, bill); ExtendedPawnData pawnData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(pawn); if (pawnData.workTypes == null) { pawnData.workTypes = new List <WorkTypeDef>(); } if (pawn.skills == null) { pawn.skills = new Pawn_SkillTracker(pawn); } if (pawn.workSettings == null) { pawn.workSettings = new Pawn_WorkSettings(pawn); pawn.workSettings.EnableAndInitialize(); } Utilities.InitWorkTypesAndSkills(pawn, pawnData); if (bill.recipe.addsHediff.GetModExtension <DefModExtension_Hediff_WorkModule>() is DefModExtension_Hediff_WorkModule modExt) { foreach (WorkTypeDef workType in modExt.workTypes) { pawnData.workTypes.Add(workType); pawn.workSettings.SetPriority(workType, 3); if (modExt.skillLevel > 0) { foreach (SkillDef skillDef in workType.relevantSkills) { pawn.skills.GetSkill(skillDef).Level = modExt.skillLevel; } } } } }
private static Gizmo CreateGizmo_Work(Pawn __instance, ExtendedPawnData pawnData) { string disabledReason = ""; bool disabled = false; Gizmo gizmo = new Command_Toggle { defaultLabel = "WTH_Gizmo_Work_Label".Translate(), defaultDesc = "WTH_Gizmo_Work_Description".Translate(), disabled = disabled, disabledReason = disabledReason, icon = ContentFinder <Texture2D> .Get(("UI/" + "MechanoidWork"), true), isActive = () => pawnData.canWorkNow, toggleAction = () => { pawnData.canWorkNow = !pawnData.canWorkNow; if (__instance.CurJob.def != WTH_DefOf.WTH_Mechanoid_Rest) { __instance.jobs.EndCurrentJob(JobCondition.InterruptForced); } } }; return(gizmo); }
private Toil waitForRider() { Toil toil = new Toil(); toil.defaultCompleteMode = ToilCompleteMode.Never; toil.tickAction = delegate { //Log.Message("waiting for rider"); riderData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(Rider); if (riderData.mount != null && riderData.mount == pawn) { ReadyForNextToil(); } if (Rider.CurJob.def != GUC_JobDefOf.Mount && Rider.CurJob.def != JobDefOf.Vomit && Rider.CurJob.def != JobDefOf.WaitMaintainPosture && Rider.CurJob.def != JobDefOf.SocialRelax && riderData.mount == null) { Log.Message("cancel wait for rider, rider is not mounting, curJob: " + Rider.CurJob.def.defName); shouldEnd = true; ReadyForNextToil(); } }; return(toil); }
static void Postfix(Pawn_HealthTracker __instance) { Pawn pawn = Traverse.Create(__instance).Field("pawn").GetValue <Pawn>(); //If an enemy animal is downed, make it a wild animal so it can be rescued. if (pawn.RaceProps.Animal && pawn.Faction != null && !pawn.Faction.IsPlayer) { pawn.SetFaction(null); } //If the owner of an NPC mount is downed, let the animal flee if (pawn.RaceProps.Humanlike && pawn.Faction != null && !pawn.Faction.IsPlayer) { ExtendedDataStorage dataStorage = Base.Instance.GetExtendedDataStorage(); if (dataStorage != null) { ExtendedPawnData pawnData = dataStorage.GetExtendedDataFor(pawn); if (pawnData != null && pawnData.owning != null && !pawnData.owning.Dead && pawnData.owning.Spawned && pawnData.owning.RaceProps.Animal) { pawnData.owning.mindState.mentalStateHandler.TryStartMentalState(MentalStateDefOf.PanicFlee); } } } }
private bool shouldCancelJob(ExtendedPawnData riderData) { if (interrupted) { //Log.Message("cancel job, shouldEnd called"); return(true); } if (riderData == null || riderData.mount == null) { //Log.Message("riderData is null or riderData.mount is null"); return(true); } Thing thing = pawn as Thing; if (Rider.Downed || Rider.Dead || pawn.Downed || pawn.Dead || pawn.IsBurning() || Rider.IsBurning()) { //Log.Message("cancel job, rider downed or dead"); return(true); } if (pawn.InMentalState || (Rider.InMentalState && Rider.MentalState.def != MentalStateDefOf.PanicFlee)) { //Log.Message("cancel job, rider or mount in mental state"); return(true); } if (!Rider.Spawned) { if (!Rider.IsColonist && !Rider.Dead) { //Log.Message("rider not spawned, despawn"); pawn.ExitMap(false, CellRect.WholeMap(base.Map).GetClosestEdge(this.pawn.Position)); return(true); } else if (Rider.IsColonist && (Rider.CurJob == null || Rider.CurJob.def != JobDefOf.EnterTransporter)) { //Log.Message("rider moved to map, despawn"); pawn.ExitMap(true, CellRect.WholeMap(base.Map).GetClosestEdge(this.pawn.Position)); return(true); } else { //Log.Message("rider died, dismount"); return(true); } } if (!Rider.Drafted && Rider.IsColonist) //TODO refactor this as a postfix in Giddy-up Caravan. { if ((Rider.mindState != null && Rider.mindState.duty != null && (Rider.mindState.duty.def == DutyDefOf.TravelOrWait || Rider.mindState.duty.def == DutyDefOf.TravelOrLeave))) { if (riderData.caravanMount == pawn) { return(false); } return(true); //if forming caravan, stay mounted. } else if (riderData.owning == pawn) { //Log.Message("cancel job, rider not drafted while being colonist"); //Log.Message("riderData.owning: " + riderData.owning); return(false); } else { return(true); } } if (riderData.mount == null) { //Log.Message("cancel job, rider has no mount"); return(true); } return(false); }
protected override void SetValue(Pawn pawn, bool value) { ExtendedPawnData pawnData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(pawn); pawnData.mountableByMaster = value; }
static void Postfix(Pawn_JobTracker __instance, ref ThinkResult __result, ref Pawn ___pawn) { if (!___pawn.IsColonistPlayerControlled || !___pawn.RaceProps.Humanlike) { return; } if (__result.Job == null) { return; } if (__result.Job.def == GUC_JobDefOf.Mount) { return; } if (___pawn.Drafted) { return; } if (___pawn.InMentalState) { return; } if (___pawn.IsBorrowedByAnyFaction()) { return; } ExtendedDataStorage store = Base.Instance.GetExtendedDataStorage(); if (store == null) { return; } ExtendedPawnData pawnData = store.GetExtendedDataFor(___pawn); if (pawnData.mount != null) { return; } LocalTargetInfo firstTarget = null; LocalTargetInfo secondTarget = null; //For some jobs the first target is B, and the second A. if (__result.Job.def == JobDefOf.TendPatient || __result.Job.def == JobDefOf.Refuel || __result.Job.def == JobDefOf.FixBrokenDownBuilding) { firstTarget = DistanceUtility.GetFirstTarget(__result.Job, TargetIndex.B); secondTarget = DistanceUtility.GetFirstTarget(__result.Job, TargetIndex.A); } else if (__result.Job.def == JobDefOf.DoBill && !__result.Job.targetQueueB.NullOrEmpty()) { firstTarget = __result.Job.targetQueueB[0]; secondTarget = DistanceUtility.GetFirstTarget(__result.Job, TargetIndex.A); } else { firstTarget = DistanceUtility.GetFirstTarget(__result.Job, TargetIndex.A); secondTarget = DistanceUtility.GetFirstTarget(__result.Job, TargetIndex.B); } if (!firstTarget.IsValid) { return; } if (Base.Instance == null) { return; } if (store == null || pawnData == null) { return; } if (pawnData.wasRidingToJob) { pawnData.wasRidingToJob = false; return; } if (___pawn.mindState != null && ___pawn.mindState.duty != null && (___pawn.mindState.duty.def == DutyDefOf.TravelOrWait || ___pawn.mindState.duty.def == DutyDefOf.TravelOrLeave)) { return; } Pawn bestChoiceAnimal = null; float pawnTargetDistance = DistanceUtility.QuickDistance(___pawn.Position, firstTarget.Cell); float firstToSecondTargetDistance = 0; if (__result.Job.def == JobDefOf.HaulToCell || __result.Job.def == JobDefOf.HaulToContainer) { if (secondTarget.IsValid) { firstToSecondTargetDistance = DistanceUtility.QuickDistance(firstTarget.Cell, secondTarget.Cell); } } float totalDistance = pawnTargetDistance + firstToSecondTargetDistance; if (totalDistance > Base.minAutoMountDistance) { bestChoiceAnimal = GetBestChoiceAnimal(___pawn, firstTarget, secondTarget, pawnTargetDistance, firstToSecondTargetDistance, store); if (bestChoiceAnimal != null) { __result = InsertMountingJobs(___pawn, bestChoiceAnimal, firstTarget, secondTarget, ref pawnData, store.GetExtendedDataFor(bestChoiceAnimal), __instance, __result); } //Log.Message("timeNeededOriginal: " + timeNeededOriginal); //Log.Message("adjusted ticks per move: " + TicksPerMoveUtility.adjustedTicksPerMove(pawn, closestAnimal, true)); //Log.Message("original ticks per move: " + pawn.TicksPerMoveDiagonal); } }
private static void handleAnimal(float num, Rect buttonRect, Pawn animal, List <Pawn> pawns) { ExtendedPawnData animalData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(animal); Text.Anchor = TextAnchor.MiddleLeft; List <FloatMenuOption> list = new List <FloatMenuOption>(); string buttonText = "GU_Car_Set_Rider".Translate(); bool canMount = true; if (!animalData.selectedForCaravan) { buttonText = "GU_Car_AnimalNotSelected".Translate(); canMount = false; } if (animal.ageTracker.CurLifeStageIndex != animal.RaceProps.lifeStageAges.Count - 1) { buttonText = "GU_Car_NotFullyGrown".Translate(); canMount = false; } if (!(animal.training != null && animal.training.IsCompleted(TrainableDefOf.Obedience))) { buttonText = "GU_Car_NeedsObedience".Translate(); canMount = false; } bool found = GiddyUpCore.Base.animalSelecter.Value.InnerList.TryGetValue(animal.def.defName, out AnimalRecord value); if (found && !value.isSelected) { buttonText = "GU_Car_NotInModOptions".Translate(); canMount = false; } if (animalData.caravanRider != null) { ExtendedPawnData riderData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(animalData.caravanRider); if (riderData.selectedForCaravan) { buttonText = animalData.caravanRider.Name.ToStringShort; } } if (!canMount) { Widgets.ButtonText(buttonRect, buttonText, false, false, false); } else if (Widgets.ButtonText(buttonRect, buttonText, true, false, true)) { foreach (Pawn pawn in pawns) { if (pawn.IsColonist) { ExtendedPawnData pawnData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(pawn); if (!pawnData.selectedForCaravan) { list.Add(new FloatMenuOption(pawn.Name.ToStringShort + " (" + "GU_Car_PawnNotSelected".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null)); continue; } if (pawnData.caravanMount != null) { continue; } list.Add(new FloatMenuOption(pawn.Name.ToStringShort, delegate { { if (animalData.caravanRider != null) { ExtendedPawnData riderData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(animalData.caravanRider); riderData.caravanMount = null; } pawnData.caravanMount = animal; animalData.caravanRider = pawn; } }, MenuOptionPriority.High, null, null, 0f, null, null)); } } list.Add(new FloatMenuOption("GU_Car_No_Rider".Translate(), delegate { { if (animalData.caravanRider != null) { ExtendedPawnData riderData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(animalData.caravanRider); riderData.caravanMount = null; } animalData.caravanRider = null; } }, MenuOptionPriority.Low, null, null, 0f, null, null)); Find.WindowStack.Add(new FloatMenu(list)); } }
private static void handleAnimal(float num, Rect buttonRect, Pawn animal, List <Pawn> pawns, TransferableOneWay trad) { ExtendedPawnData animalData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(animal); Text.Anchor = TextAnchor.MiddleLeft; List <FloatMenuOption> list = new List <FloatMenuOption>(); string buttonText = "GU_Car_Set_Rider".Translate(); bool canMount = true; if (!animalData.selectedForCaravan) { buttonText = "GU_Car_AnimalNotSelected".Translate(); canMount = false; } bool isMountable = IsMountableUtility.isMountable(animal, out IsMountableUtility.Reason reason); if (!isMountable) { if (reason == IsMountableUtility.Reason.NotFullyGrown) { buttonText = "GU_Car_NotFullyGrown".Translate(); canMount = false; } if (reason == IsMountableUtility.Reason.NeedsObedience) { buttonText = "GU_Car_NeedsObedience".Translate(); canMount = false; } if (reason == IsMountableUtility.Reason.NotInModOptions) { buttonText = "GU_Car_NotInModOptions".Translate(); canMount = false; } } if (animalData.caravanRider != null) { ExtendedPawnData riderData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(animalData.caravanRider); if (riderData.selectedForCaravan) { buttonText = animalData.caravanRider.Name.ToStringShort; } } if (!canMount) { Widgets.ButtonText(buttonRect, buttonText, false, false, false); } else if (Widgets.ButtonText(buttonRect, buttonText, true, false, true)) { foreach (Pawn pawn in pawns) { if (pawn.IsColonist) { ExtendedPawnData pawnData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(pawn); if (!pawnData.selectedForCaravan) { list.Add(new FloatMenuOption(pawn.Name.ToStringShort + " (" + "GU_Car_PawnNotSelected".Translate() + ")", null, MenuOptionPriority.Default, null, null, 0f, null, null)); continue; } if (pawnData.caravanMount != null) { continue; } list.Add(new FloatMenuOption(pawn.Name.ToStringShort, delegate { { SelectMountRider(animalData, pawnData, animal, pawn); Traverse.Create(trad).Property("CountToTransfer").SetValue(-1); //Setting this to -1 will make sure total weight is calculated again. it's set back to 1 shortly after Log.Message("setting CountToTransfer to -1"); //if (animalData.caravanRider != null) //{ // ExtendedPawnData riderData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(animalData.caravanRider); // riderData.caravanMount = null; //} //pawnData.caravanMount = animal; //animalData.caravanRider = pawn; //Traverse.Create(trad).Property("CountToTransfer").SetValue(-1); //Setting this to -1 will make sure total weight is calculated again. it's set back to 1 shortly after //Log.Message("setting CountToTransfer to -1"); //animalData.selectedForCaravan = true; } }, MenuOptionPriority.High, null, null, 0f, null, null)); } } list.Add(new FloatMenuOption("GU_Car_No_Rider".Translate(), delegate { { ClearMountRider(animalData); Traverse.Create(trad).Property("CountToTransfer").SetValue(-1); //Setting this to -1 will make sure total weight is calculated again. it's set back to 1 shortly after Log.Message("setting CountToTransfer to -1"); //if (animalData.caravanRider != null) //{ // ExtendedPawnData riderData = GiddyUpCore.Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(animalData.caravanRider); // riderData.caravanMount = null; //} //animalData.caravanRider = null; //Traverse.Create(trad).Property("CountToTransfer").SetValue(-1); //Setting this to -1 will make sure total weight is calculated again. it's set back to 1 shortly after //Log.Message("setting CountToTransfer to -1"); //animalData.selectedForCaravan = true; } }, MenuOptionPriority.Low, null, null, 0f, null, null)); Find.WindowStack.Add(new FloatMenu(list)); } }
static void Postfix(JobDriver __instance) { if (__instance.pawn.Map == null) { return; } List <Toil> toils = Traverse.Create(__instance).Field("toils").GetValue <List <Toil> >(); if (__instance.pawn.Faction != Faction.OfPlayer || __instance.pawn.Drafted) { return; } ExtendedDataStorage store = Base.Instance.GetExtendedDataStorage(); if (store == null) { return; } ExtendedPawnData pawnData = store.GetExtendedDataFor(__instance.pawn); Area_GU areaNoMount = (Area_GU)__instance.pawn.Map.areaManager.GetLabeled(Base.NOMOUNT_LABEL); Area_GU areaDropAnimal = (Area_GU)__instance.pawn.Map.areaManager.GetLabeled(Base.DROPANIMAL_LABEL); bool startedPark = false; IntVec3 originalLoc = new IntVec3(); IntVec3 parkLoc = new IntVec3(); if (pawnData.mount != null && areaNoMount != null && areaDropAnimal != null) { foreach (Toil toil in toils) { //checkedToil makes sure the ActiveCells.Contains is only called once, preventing performance impact. bool checkedToil = false; toil.AddPreTickAction(delegate { if (!checkedToil && pawnData.mount != null && areaDropAnimal.ActiveCells.Count() > 0 && areaNoMount.ActiveCells.Contains(toil.actor.pather.Destination.Cell)) { //Toil parkToil = ParkToil(__instance, toils, pawnData, areaDropAnimal, toils[__instance.CurToilIndex]); //toils.Add(parkToil); parkLoc = DistanceUtility.getClosestAreaLoc(toil.actor.pather.Destination.Cell, areaDropAnimal); originalLoc = toil.actor.pather.Destination.Cell; if (toil.actor.Map.reachability.CanReach(toil.actor.Position, parkLoc, PathEndMode.OnCell, TraverseParms.For(TraverseMode.PassDoors, Danger.Deadly, false))) { toil.actor.pather.StartPath(parkLoc, PathEndMode.OnCell); startedPark = true; } else { Messages.Message("GU_RR_NotReachable_DropAnimal_Message".Translate(), new RimWorld.Planet.GlobalTargetInfo(parkLoc, toil.actor.Map), MessageTypeDefOf.NegativeEvent); } } checkedToil = true; if (startedPark && toil.actor.pather.nextCell == parkLoc) { pawnData.mount = null; toil.actor.pather.StartPath(originalLoc, PathEndMode.ClosestTouch); if (pawnData.owning != null) { ExtendedPawnData animalData = store.GetExtendedDataFor(pawnData.owning); animalData.ownedBy = null; pawnData.owning = null; } } }); } } }
public override void SetValue(Pawn pawn, bool value, PawnTable table) { ExtendedPawnData pawnData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(pawn); pawnData.mountableByAnyone = value; }
public override bool GetValue(Pawn pawn) { ExtendedPawnData pawnData = Base.Instance.GetExtendedDataStorage().GetExtendedDataFor(pawn); return(pawnData.mountableByAnyone); }
static void Postfix(Pawn_JobTracker __instance, ref ThinkResult __result, ref Pawn ___pawn) { if (___pawn.RaceProps.Animal && ___pawn.Faction != Faction.OfPlayer && ___pawn.Faction != null) { if (___pawn.GetLord() != null && (___pawn.GetLord().CurLordToil is LordToil_DefendPoint || ___pawn.GetLord().CurLordToil.GetType().Name == "LordToil_DefendTraderCaravan")) { if (__result.SourceNode is JobGiver_Wander) { JobGiver_Wander jgWander = (JobGiver_Wander)__result.SourceNode; Traverse.Create(__result.SourceNode).Field("wanderRadius").SetValue(5f); } } } if (___pawn.IsColonistPlayerControlled || ___pawn.RaceProps.Animal || ___pawn.Faction.HostileTo(Faction.OfPlayer)) { return; } if (___pawn.IsPrisoner) { return; } LocalTargetInfo target = DistanceUtility.GetFirstTarget(__result.Job, TargetIndex.A); if (!target.IsValid) { return; } ExtendedDataStorage store = Base.GetExtendedDataStorage(); if (store == null) { return; } //Log.Message("wrong duty"); ExtendedPawnData PawnData = store.GetExtendedDataFor(___pawn); Lord lord = ___pawn.GetLord(); if (lord == null) { return; } if (__result.Job.def == GUC_JobDefOf.Dismount || __result.Job.def == GUC_JobDefOf.Mount) { return; } QueuedJob qJob = ___pawn.jobs.jobQueue.FirstOrFallback(null); if (qJob != null && (qJob.job.def == GUC_JobDefOf.Dismount || qJob.job.def == GUC_JobDefOf.Mount)) { return; } if (lord.CurLordToil is LordToil_ExitMapAndEscortCarriers || lord.CurLordToil is LordToil_Travel || lord.CurLordToil is LordToil_ExitMap || lord.CurLordToil is LordToil_ExitMapTraderFighting) { if (PawnData.owning != null && PawnData.owning.Faction == ___pawn.Faction && PawnData.mount == null && !PawnData.owning.Downed && PawnData.owning.Spawned && !___pawn.IsBurning() && !___pawn.Downed) { mountAnimal(__instance, ___pawn, PawnData, ref __result); } } else if (lord.CurLordToil.GetType().Name == "LordToil_DefendTraderCaravan" || lord.CurLordToil is LordToil_DefendPoint) //first option is internal class, hence this way of accessing. { if (PawnData.mount != null) { parkAnimal(__instance, ___pawn, PawnData); } } }
static void Postfix(Pawn_JobTracker __instance, ref ThinkResult __result) { Pawn pawn = Traverse.Create(__instance).Field("pawn").GetValue <Pawn>(); if (!pawn.IsColonistPlayerControlled) { return; } if (__result.Job == null) { return; } if (__result.Job.def == GUC_JobDefOf.Mount) { return; } if (pawn.Drafted) { return; } if (pawn.InMentalState) { return; } LocalTargetInfo target = null; LocalTargetInfo targetB = null; //For some jobs the first target is B, and the second A. if (__result.Job.def == JobDefOf.TendPatient || __result.Job.def == JobDefOf.Refuel) { target = DistanceUtility.GetFirstTarget(__result.Job, TargetIndex.B); targetB = DistanceUtility.GetFirstTarget(__result.Job, TargetIndex.A); } else if (__result.Job.def == JobDefOf.DoBill && !__result.Job.targetQueueB.NullOrEmpty()) { target = __result.Job.targetQueueB[0]; targetB = DistanceUtility.GetFirstTarget(__result.Job, TargetIndex.A); } else { target = DistanceUtility.GetFirstTarget(__result.Job, TargetIndex.A); targetB = DistanceUtility.GetFirstTarget(__result.Job, TargetIndex.B); } if (!target.IsValid) { return; } Area_GU area = (Area_GU)pawn.Map.areaManager.GetLabeled(Base.NOMOUNT_LABEL); //TODO: make sure mounts are parked of when pawn wants to enter area with mount. if (Base.Instance == null) { return; } ExtendedDataStorage store = Base.Instance.GetExtendedDataStorage(); ExtendedPawnData pawnData = store.GetExtendedDataFor(pawn); if (store == null || pawnData == null) { return; } if (pawnData.wasRidingToJob) { pawnData.wasRidingToJob = false; return; } if (pawn.mindState != null && pawn.mindState.duty != null && (pawn.mindState.duty.def == DutyDefOf.TravelOrWait || pawn.mindState.duty.def == DutyDefOf.TravelOrLeave)) { return; } Pawn bestChoiceAnimal = pawnData.mount; //Pawn bestChoiceAnimal = null; float pawnTargetDistance = DistanceUtility.QuickDistance(pawn.Position, target.Cell); //Log.Message("pawnTargetDistance: " + pawnTargetDistance); float firstToSecondTargetDistance = 0; if (__result.Job.def == JobDefOf.HaulToCell || __result.Job.def == JobDefOf.HaulToContainer) { if (targetB.IsValid) { firstToSecondTargetDistance = DistanceUtility.QuickDistance(target.Cell, targetB.Cell); } } float totalDistance = pawnTargetDistance + firstToSecondTargetDistance; if (totalDistance > Base.minAutoMountDistance) { if (pawnData.mount == null) { bestChoiceAnimal = GetBestChoiceAnimal(pawn, target, targetB, pawnTargetDistance, firstToSecondTargetDistance, store); } if (bestChoiceAnimal != null) { __result = InsertMountingJobs(pawn, bestChoiceAnimal, target, targetB, ref pawnData, store.GetExtendedDataFor(bestChoiceAnimal), __instance, __result); } //Log.Message("timeNeededOriginal: " + timeNeededOriginal); //Log.Message("adjusted ticks per move: " + TicksPerMoveUtility.adjustedTicksPerMove(pawn, closestAnimal, true)); //Log.Message("original ticks per move: " + pawn.TicksPerMoveDiagonal); } }
//Gets animal that'll get the pawn to the target the quickest. Returns null if no animal is found or if walking is faster. static Pawn GetBestChoiceAnimal(Pawn pawn, LocalTargetInfo target, LocalTargetInfo secondTarget, float pawnTargetDistance, float firstToSecondTargetDistance, ExtendedDataStorage store) { //float minDistance = float.MaxValue; Pawn closestAnimal = null; float timeNeededMin = (pawnTargetDistance + firstToSecondTargetDistance) * pawn.TicksPerMoveDiagonal; ExtendedPawnData pawnData = store.GetExtendedDataFor(pawn); bool firstTargetNoMount = false; bool secondTargetNoMount = false; Area_GU areaNoMount = (Area_GU)pawn.Map.areaManager.GetLabeled(Base.NOMOUNT_LABEL); Area_GU areaDropAnimal = (Area_GU)pawn.Map.areaManager.GetLabeled(Base.DROPANIMAL_LABEL); if (areaNoMount != null && areaNoMount.ActiveCells.Contains(target.Cell)) { firstTargetNoMount = true; if (pawnTargetDistance < Base.minAutoMountDistance) { return(null); } } //If owning an animal, prefer this animal if it still gets you to the goal quicker than walking. //This'll make sure pawns prefer the animals they were already riding previously. if (pawnData.owning != null && pawnData.owning.Spawned && !AnimalNotAvailable(pawnData.owning) && pawn.CanReserve(pawnData.owning)) { if (CalculateTimeNeeded(pawn, ref target, secondTarget, firstToSecondTargetDistance, pawnData.owning, firstTargetNoMount, secondTargetNoMount, areaDropAnimal) < timeNeededMin) { return(pawnData.owning); } } //Otherwise search the animal on the map that gets you to the goal the quickest foreach (Pawn animal in from p in pawn.Map.mapPawns.AllPawnsSpawned where p.RaceProps.Animal && IsMountableUtility.isMountable(p) && p.CurJob != null && p.CurJob.def != GUC_JobDefOf.Mounted select p) { if (AnimalNotAvailable(animal) || !pawn.CanReserve(animal)) { continue; } float distanceFromAnimal = DistanceUtility.QuickDistance(animal.Position, target.Cell); if (!firstTargetNoMount) { distanceFromAnimal += firstToSecondTargetDistance; } if (distanceFromAnimal < Base.minAutoMountDistanceFromAnimal) { continue; } ExtendedPawnData animalData = store.GetExtendedDataFor(animal); if (animalData.ownedBy != null) { continue; } if (!animalData.mountableByMaster && !animalData.mountableByAnyone) { continue; } else if (!animalData.mountableByAnyone && animalData.mountableByMaster) { if (animal.playerSettings != null && animal.playerSettings.master != pawn) { continue; } } float timeNeeded = CalculateTimeNeeded(pawn, ref target, secondTarget, firstToSecondTargetDistance, animal, firstTargetNoMount, secondTargetNoMount, areaDropAnimal); if (timeNeeded < timeNeededMin) { closestAnimal = animal; timeNeededMin = timeNeeded; } } return(closestAnimal); }