public static void RebuffDemandAndSmiteThePlayer(TravelingIncidentCaravan caravan, Pawn pawn) { if (!(caravan.incident is InterceptedIncident_HumanCrowd_RaidEnemy incident)) { return; } caravan.Communicable = false; if (incident.raidGoalType == RaidGoalType.Rescue) { RaidingGoal_Rescue goal = incident.goal as RaidingGoal_Rescue; foreach (var p in goal.Prisoners) { p.guilt.lastGuiltyTick = Find.TickManager.TicksGame; ExecutionUtility.DoExecutionByCut(pawn, p); } } incident.goal = new RaidingGoal_Smite(); if (pawn.skills.GetSkill(SkillDefOf.Social).Level < 5) { incident.CombatMoral = -1; } else if (pawn.skills.GetSkill(SkillDefOf.Social).Level < 10) { incident.CombatMoral = 0; } else { incident.CombatMoral = 1; } }
protected override IEnumerable <Toil> MakeNewToils() { yield return(Toils_Goto.Goto(TargetIndex.A, PathEndMode.Touch).FailOn(() => !Victim.Downed)); Toil execute = new Toil(); execute.initAction = delegate { ExecutionUtility.DoExecutionByCut(execute.actor, Victim); }; execute.defaultCompleteMode = ToilCompleteMode.Instant; execute.activeSkill = (() => SkillDefOf.Melee); yield return(execute); }
// Token: 0x06002BEA RID: 11242 RVA: 0x000FF850 File Offset: 0x000FDA50 public override IEnumerable <Toil> MakeNewToils() { this.FailOnAggroMentalState(TargetIndex.A); this.FailOnThingMissingDesignation(TargetIndex.A, DesignationDefOf.Slaughter); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch)); yield return(Toils_General.WaitWith(TargetIndex.A, 180, true, false)); yield return(Toils_General.Do(delegate { ExecutionUtility.DoExecutionByCut(this.pawn, this.Victim); this.pawn.records.Increment(RecordDefOf.AnimalsSlaughtered); if (this.pawn.InMentalState) { this.pawn.MentalState.Notify_SlaughteredAnimal(); } })); yield break; }
protected override IEnumerable <Toil> MakeNewToils() { this.FailOnAggroMentalState(TargetIndex.A); yield return(Toils_Interpersonal.GotoPrisoner(pawn, Victim, PrisonerInteractionModeDefOf.Execution).FailOn(() => !Victim.IsPrisonerOfColony || !Victim.guest.PrisonerIsSecure)); Toil execute = new Toil(); execute.initAction = delegate { ExecutionUtility.DoExecutionByCut(execute.actor, Victim); ThoughtUtility.GiveThoughtsForPawnExecuted(Victim, PawnExecutionKind.GenericBrutal); TaleRecorder.RecordTale(TaleDefOf.ExecutedPrisoner, new object[] { pawn, Victim }); }; execute.defaultCompleteMode = ToilCompleteMode.Instant; yield return(execute); }
private Toil Sacrifce(TargetIndex sacrificable) { return(new Toil() { initAction = delegate { Thing sacrificableThing = pawn.CurJob.GetTarget(sacrificable).Thing; if (sacrificableThing != null) { Pawn sacrificablePawn = sacrificableThing as Pawn; if (sacrificablePawn != null) { ExecutionUtility.DoExecutionByCut(pawn, sacrificablePawn); pawn.Reserve(sacrificablePawn.Corpse, this.job); } else { sacrificableThing.Destroy(DestroyMode.Vanish); } } } }); }
protected override IEnumerable <Toil> MakeNewToils() { this.FailOn(delegate { if (!job.ignoreDesignations) { Pawn victim = Victim; if (victim != null && !victim.Dead && Map.designationManager.DesignationOn(victim, DesignationDefOf.Hunt) == null) { return(true); } } return(false); }); yield return(Toils_Reserve.Reserve(VictimInd, 1)); var init = new Toil(); init.initAction = delegate { jobStartTick = Find.TickManager.TicksGame; }; yield return(init); yield return(Toils_Combat.TrySetJobToUseAttackVerb(TargetIndex.A)); var comp = (pawn.equipment != null && pawn.equipment.Primary != null) ? pawn.equipment.Primary.TryGetComp <CompAmmoUser>() : null; var startCollectCorpse = StartCollectCorpseToil(); var gotoCastPos = GotoCastPosition(VictimInd, true).JumpIfDespawnedOrNull(VictimInd, startCollectCorpse).FailOn(() => Find.TickManager.TicksGame > jobStartTick + MaxHuntTicks); yield return(gotoCastPos); //var moveIfCannotHit = Toils_Jump.JumpIfTargetNotHittable(VictimInd, gotoCastPos); var moveIfCannotHit = Toils_Jump.JumpIf(gotoCastPos, delegate { var verb = pawn.CurJob.verbToUse; var optimalRange = HuntRangePerBodysize(Victim.RaceProps.baseBodySize, Victim.RaceProps.executionRange, verb.verbProps.range); if (pawn.Position.DistanceTo(Victim.Position) > optimalRange) { return(true); } return(!verb.CanHitTarget(Victim)); }); yield return(moveIfCannotHit); yield return(Toils_Jump.JumpIfTargetDespawnedOrNull(VictimInd, startCollectCorpse)); var startExecuteDowned = Toils_Goto.GotoThing(VictimInd, PathEndMode.Touch).JumpIfDespawnedOrNull(VictimInd, startCollectCorpse); yield return(Toils_Jump.JumpIf(startExecuteDowned, () => Victim.Downed && Victim.RaceProps.executionRange <= 2)); yield return(Toils_Jump.JumpIfTargetDowned(VictimInd, gotoCastPos)); yield return(Toils_Combat.CastVerb(VictimInd, false).JumpIfDespawnedOrNull(VictimInd, startCollectCorpse) .FailOn(() => { if (Find.TickManager.TicksGame <= jobStartTick + MaxHuntTicks) { if (comp == null || comp.HasAndUsesAmmoOrMagazine) { return false; } } return true; })); yield return(Toils_Jump.Jump(moveIfCannotHit)); // Execute downed animal - adapted from JobDriver_Slaughter yield return(startExecuteDowned); yield return(Toils_General.WaitWith(VictimInd, 180, true).JumpIfDespawnedOrNull(VictimInd, startCollectCorpse)); yield return(new Toil { initAction = delegate { ExecutionUtility.DoExecutionByCut(pawn, Victim); }, defaultCompleteMode = ToilCompleteMode.Instant }); // Haul corpse to stockpile yield return(startCollectCorpse); yield return(Toils_Goto.GotoCell(VictimInd, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(VictimInd).FailOnSomeonePhysicallyInteracting(VictimInd)); yield return(Toils_Haul.StartCarryThing(VictimInd)); var carryToCell = Toils_Haul.CarryHauledThingToCell(StoreCellInd); yield return(carryToCell); yield return(Toils_Haul.PlaceHauledThingInCell(StoreCellInd, carryToCell, true)); }
protected override IEnumerable <Toil> MakeNewToils() { this.FailOn(delegate { if (!job.ignoreDesignations) { Pawn victim2 = Victim; if (victim2 != null && !victim2.Dead && base.Map.designationManager.DesignationOn(victim2, DesignationDefOf.Hunt) == null) { return(true); } } return(false); }); Toil toil = new Toil(); toil.initAction = delegate { jobStartTick = Find.TickManager.TicksGame; }; yield return(toil); yield return(Toils_Combat.TrySetJobToUseAttackVerb(TargetIndex.A)); Toil startCollectCorpseLabel = Toils_General.Label(); Toil slaughterLabel = Toils_General.Label(); Toil gotoCastPos = Toils_Combat.GotoCastPosition(TargetIndex.A, TargetIndex.None, closeIfDowned: true, 0.95f).JumpIfDespawnedOrNull(TargetIndex.A, startCollectCorpseLabel).FailOn(() => Find.TickManager.TicksGame > jobStartTick + 5000); yield return(gotoCastPos); Toil slaughterIfPossible = Toils_Jump.JumpIf(slaughterLabel, delegate { Pawn victim = Victim; if (victim.RaceProps.DeathActionWorker != null && victim.RaceProps.DeathActionWorker.DangerousInMelee) { return(false); } return(victim.Downed ? true : false); }); yield return(slaughterIfPossible); yield return(Toils_Jump.JumpIfTargetNotHittable(TargetIndex.A, gotoCastPos)); yield return(Toils_Combat.CastVerb(TargetIndex.A, canHitNonTargetPawns: false).JumpIfDespawnedOrNull(TargetIndex.A, startCollectCorpseLabel).FailOn(() => Find.TickManager.TicksGame > jobStartTick + 5000)); yield return(Toils_Jump.JumpIfTargetDespawnedOrNull(TargetIndex.A, startCollectCorpseLabel)); yield return(Toils_Jump.Jump(slaughterIfPossible)); yield return(slaughterLabel); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch).FailOnMobile(TargetIndex.A)); yield return(Toils_General.WaitWith(TargetIndex.A, 180, useProgressBar: true).FailOnMobile(TargetIndex.A)); yield return(Toils_General.Do(delegate { if (!Victim.Dead) { ExecutionUtility.DoHuntingExecution(pawn, Victim); pawn.records.Increment(RecordDefOf.AnimalsSlaughtered); if (pawn.InMentalState) { pawn.MentalState.Notify_SlaughteredAnimal(); } } })); yield return(Toils_Jump.Jump(startCollectCorpseLabel)); yield return(startCollectCorpseLabel); yield return(StartCollectCorpseToil()); yield return(Toils_Goto.GotoCell(TargetIndex.A, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.A).FailOnSomeonePhysicallyInteracting(TargetIndex.A)); yield return(Toils_Haul.StartCarryThing(TargetIndex.A)); Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.B); yield return(carryToCell); yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, storageMode: true)); }
protected override IEnumerable <Toil> MakeNewToils() { var checkIncaseJobWasCancelledPreviously = new Toil { initAction = () => { var curMap = this.GetActor().MapHeld; var lastCorpse = curMap.listerThings.AllThings.FirstOrDefault(x => x is Corpse c && c.InnerPawn.health.hediffSet.HasHediff(UvhashDefOf.Uvhash_TattooParalysis)); if (lastCorpse != null) { this.job.SetTarget(TargetIndex.A, lastCorpse); } } }; var prepareToTransformCorpse = new Toil(); prepareToTransformCorpse.initAction = delegate { Pawn actor = prepareToTransformCorpse.actor; Corpse corpse = this.Corpse; if (corpse == null) { Pawn prey = this.Prey; if (prey == null) { actor.jobs.EndCurrentJob(JobCondition.Incompletable, true); return; } corpse = prey.Corpse; if (corpse == null || !corpse.Spawned) { actor.jobs.EndCurrentJob(JobCondition.Incompletable, true); return; } } corpse.SetForbidden(actor.Faction != Faction.OfPlayer, false); actor.CurJob.SetTarget(TargetIndex.A, corpse); }; var goToCorpse = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch); var goToPreyPos = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch); var gotoCastPos = Toils_Combat.GotoCastPosition(TargetIndex.A, true).JumpIfDespawnedOrNull(TargetIndex.A, prepareToTransformCorpse).FailOn(() => Find.TickManager.TicksGame > this.jobStartTick + 5000); var moveIfCannotHit = Toils_Jump.JumpIfTargetNotHittable(TargetIndex.A, goToPreyPos); var castSpell = new Toil { defaultCompleteMode = ToilCompleteMode.Delay }; castSpell.WithProgressBarToilDelay(TargetIndex.A); castSpell.defaultDuration = 1200; castSpell.AddPreInitAction(() => { curReport = "BloodMage_CastingOn".Translate(TargetA.Thing.Label); moteThrown = UvhashUtility.ThrowMagicMote(1f, this.GetActor()); moteThrown.LifeSpanOffset += 99999f; moteTarget.LifeSpanOffset += 99999f; moteTarget = UvhashUtility.ThrowMagicMote(TargetA.Thing.def.race.baseBodySize, TargetA.Thing); }); castSpell.tickAction = () => { if (moteThrown != null) { moteThrown.exactPosition = this.GetActor().DrawPos; } if (moteTarget != null) { moteTarget.exactPosition = TargetA.Thing.DrawPos; } if (Find.TickManager.TicksGame % 15 == 0) { MoteMaker.ThrowText(this.GetActor().DrawPos + new Vector3(new FloatRange(-1, 1).RandomInRange, 0, new FloatRange(-1, 1).RandomInRange), this.GetActor().MapHeld, cultMadText.RandomElement(), Color.red); //MoteMaker.ThrowText(this.TargetA.Thing.DrawPos + new Vector3(new FloatRange(-1, 1).RandomInRange, 0, new FloatRange(-1, 1).RandomInRange), this.GetActor().MapHeld, cultMadText.RandomElement(), Color.red); } }; castSpell.PlaySustainerOrSound(UvhashDefOf.Uvhash_BloodMagicCastingSustainer); castSpell.AddFinishAction(() => { if (!Prey.Downed) { HealthUtility.AdjustSeverity(Prey, UvhashDefOf.Uvhash_TattooParalysis, 1.0f); } curReport = ""; if (moteThrown != null) { moteThrown.LifeSpanOffset -= 999999f; } if (moteTarget != null) { moteTarget.LifeSpanOffset -= 999999f; } }); var executeTarget = new Toil { defaultCompleteMode = ToilCompleteMode.Delay }; executeTarget.WithProgressBarToilDelay(TargetIndex.B); executeTarget.defaultDuration = 200; executeTarget.AddFinishAction(() => { ExecutionUtility.DoExecutionByCut(this.GetActor(), Prey); }); Toil transformCorpse = new Toil(); transformCorpse.defaultCompleteMode = ToilCompleteMode.Delay; transformCorpse.WithEffect(() => EffecterDef.Named("ButcherFlesh"), TargetIndex.A); transformCorpse.WithProgressBarToilDelay(TargetIndex.A); transformCorpse.defaultDuration = 800; transformCorpse.AddPreInitAction(() => { Messages.Message("BloodBookCreation_Message".Translate(new object[] { this.pawn.LabelCap, this.Prey.Label }), MessageTypeDefOf.NeutralEvent); }); var destroyCorpseAndSpawnBook = new Toil(); destroyCorpseAndSpawnBook.initAction = () => { var corpsePos = Corpse.PositionHeld; var corpseMap = Corpse.MapHeld; Corpse.Destroy(); FilthMaker.MakeFilth(corpsePos, corpseMap, ThingDefOf.FilthBlood, Rand.Range(1, 2)); for (int i = 0; i < 10; i++) { FilthMaker.MakeFilth(corpsePos.RandomAdjacentCell8Way(), corpseMap, ThingDefOf.FilthBlood, Rand.Range(1, 2)); this.GetActor().filth.GainFilth(ThingDefOf.FilthBlood); } var book = (ThingWithComps_LiberCruoris)ThingMaker.MakeThing(UvhashDefOf.Uvhash_LiberCruoris); GenPlace.TryPlaceThing(book, corpsePos, corpseMap, ThingPlaceMode.Near); Find.World.GetComponent <WorldComponent_Uvhash>().CurrentCrystalStage = CrystalStage.BookCreated; this.GetActor().MentalState.RecoverFromState(); this.GetActor().TryGetComp <CompBloodMage>().BloodMageLevel = 1; UvhashUtility.ShowMessageBox("BloodBookCreatedDesc".Translate(this.GetActor()).AdjustedFor(this.GetActor()), "BloodBookCreated".Translate()); }; yield return(new Toil { initAction = delegate { this.jobStartTick = Find.TickManager.TicksGame; } }); yield return(checkIncaseJobWasCancelledPreviously); yield return(Toils_Jump.JumpIf(goToCorpse, () => Prey.Dead)); yield return(Toils_Jump.JumpIf(goToPreyPos, () => Prey.Downed)); yield return(Toils_Combat.TrySetJobToUseAttackVerb()); yield return(gotoCastPos.FailOn(() => this.GetActor().IsFighting())); yield return(castSpell); yield return(goToPreyPos); yield return(executeTarget); yield return(prepareToTransformCorpse); yield return(goToCorpse); yield return(transformCorpse); yield return(destroyCorpseAndSpawnBook); this.AddFinishAction(() => { if (moteThrown != null) { moteThrown.LifeSpanOffset -= 999999f; } if (moteTarget != null) { moteTarget.LifeSpanOffset -= 999999f; } }); yield break; }
protected override IEnumerable <Toil> MakeNewToils() { const float baseFishingDuration = 1600f; const float catchSuccessRateOnPier = 0.90f; const float skillGainPerTick = 0.15f; int fishingDuration = (int)baseFishingDuration; Building_FishingPier fishingPier = this.TargetThingA as Building_FishingPier; int thrownCornCount = 0; int nextCornThrowTick = 0; this.FailOnBurningImmobile(fishingPierIndex); // Drawing. this.rotateToFace = TargetIndex.B; this.pawn.CurJob.SetTarget(TargetIndex.C, fishingPier.riverCell); TargetIndex riverCellIndex = TargetIndex.C; // Compute fishing duration. float fishingSkillLevel = 0f; fishingSkillLevel = this.pawn.skills.AverageOfRelevantSkillsFor(WorkTypeDefOf.Hunting); float fishingSkillDurationFactor = fishingSkillLevel / 20f; fishingDuration = (int)(baseFishingDuration * (1.5f - fishingSkillDurationFactor)); yield return(Toils_Goto.GotoThing(fishingPierIndex, fishingPier.riverCell).FailOn(FishingForbiddenOrPierDestroyedOrNoFish)); Toil attractfishesToil = new Toil() { tickAction = () => { if (fishingPier.allowUsingGrain == false) { this.ReadyForNextToil(); return; } if (Find.TickManager.TicksGame >= nextCornThrowTick) { nextCornThrowTick = Find.TickManager.TicksGame + 3 * GenTicks.TicksPerRealSecond; // Look for corn in inventory. Thing corn = null; foreach (Thing thing in this.pawn.inventory.innerContainer) { if (thing.def == Util_FishIndustry.RawCornDef) { corn = thing; break; } } if ((corn == null) || (thrownCornCount >= grainCountToAttractFishes)) { fishingDuration -= Mathf.CeilToInt((float)fishingDuration * 0.75f * ((float)thrownCornCount / (float)grainCountToAttractFishes)); this.ReadyForNextToil(); return; } // Throw corn grains. thrownCornCount++; this.pawn.inventory.innerContainer.Take(corn, 1); for (int cornGrainIndex = 0; cornGrainIndex < 5; cornGrainIndex++) { if (!this.pawn.Position.ShouldSpawnMotesAt(this.pawn.Map) || this.pawn.Map.moteCounter.Saturated) { break; } float speed = Rand.Range(1.5f, 3f); Vector3 targetPosition = this.pawn.Position.ToVector3Shifted() + new Vector3(0f, 0f, 2f).RotatedBy(fishingPier.Rotation.AsAngle) + Vector3Utility.RandomHorizontalOffset(1.5f); targetPosition.y = this.pawn.DrawPos.y; MoteThrown moteThrown = (MoteThrown)ThingMaker.MakeThing(ThingDefOf.Mote_Stone, null); moteThrown.Scale = 0.2f; moteThrown.rotationRate = (float)Rand.Range(-300, 300); moteThrown.exactPosition = this.pawn.DrawPos; moteThrown.SetVelocity((targetPosition - moteThrown.exactPosition).AngleFlat(), speed); moteThrown.airTimeLeft = (float)Mathf.RoundToInt((moteThrown.exactPosition - targetPosition).MagnitudeHorizontal() / speed); GenSpawn.Spawn(moteThrown, this.pawn.Position, this.pawn.Map); MoteMaker.MakeWaterSplash(targetPosition, this.pawn.Map, 1.8f, 0.5f); } } }, defaultDuration = fishingDuration, defaultCompleteMode = ToilCompleteMode.Delay }; yield return(attractfishesToil.FailOn(FishingForbiddenOrPierDestroyedOrNoFish)); Toil fishToil = new Toil() { initAction = () => { ThingDef moteDef = null; if (fishingPier.Rotation == Rot4.North) { moteDef = Util_FishIndustry.MoteFishingRodNorthDef; } else if (fishingPier.Rotation == Rot4.East) { moteDef = Util_FishIndustry.MoteFishingRodEastDef; } else if (fishingPier.Rotation == Rot4.South) { moteDef = Util_FishIndustry.MoteFishingRodSouthDef; } else { moteDef = Util_FishIndustry.MoteFishingRodWestDef; } this.fishingRodMote = (Mote)ThingMaker.MakeThing(moteDef, null); this.fishingRodMote.exactPosition = fishingPier.fishingSpotCell.ToVector3Shifted(); this.fishingRodMote.Scale = 1f; GenSpawn.Spawn(this.fishingRodMote, fishingPier.fishingSpotCell, this.Map); }, tickAction = () => { this.pawn.skills.Learn(SkillDefOf.Shooting, skillGainPerTick); if (this.fishingRodMote != null) { this.fishingRodMote.Maintain(); } }, defaultDuration = fishingDuration, defaultCompleteMode = ToilCompleteMode.Delay }; yield return(fishToil.WithProgressBarToilDelay(riverCellIndex).FailOn(FishingForbiddenOrPierDestroyedOrNoFish)); Toil catchFishToil = new Toil() { initAction = () => { Thing fishingCatch = null; bool catchIsSuccessful = (Rand.Value <= catchSuccessRateOnPier); if (catchIsSuccessful == false) { MoteMaker.ThrowMetaIcon(this.pawn.Position, this.Map, ThingDefOf.Mote_IncapIcon); this.pawn.jobs.EndCurrentJob(JobCondition.Incompletable); return; } float catchSelectorValue = Rand.Value; if (catchSelectorValue < 0.02) { float bonusCatchValue = Rand.Value; if (bonusCatchValue < 0.01f) { // Really small chance to find a sunken treasure!!! fishingCatch = GenSpawn.Spawn(ThingDefOf.Gold, this.pawn.Position, this.Map); fishingCatch.stackCount = Rand.RangeInclusive(58, 289); Thing treasureSilver = GenSpawn.Spawn(ThingDefOf.Silver, fishingPier.middleCell, this.Map); treasureSilver.stackCount = Rand.RangeInclusive(237, 2154); Find.LetterStack.ReceiveLetter("FishIndustry.LetterLabelSunkenTreasure".Translate(), "FishIndustry.SunkenTreasure".Translate(this.pawn.Name.ToStringShort.CapitalizeFirst()), LetterDefOf.PositiveEvent, this.pawn); } else if (bonusCatchValue < 0.02f) { // Really small chance to find a complete power armor set + sniper or charge rifle. Thing powerArmor = GenSpawn.Spawn(ThingDef.Named("Apparel_PowerArmor"), this.pawn.Position, this.Map); fishingCatch = powerArmor; // Used to carry the power armor. Thing powerArmorHelmet = GenSpawn.Spawn(ThingDef.Named("Apparel_PowerArmorHelmet"), this.pawn.Position, this.Map); Thing rifle = null; if (Rand.Value < 0.5f) { rifle = GenSpawn.Spawn(ThingDef.Named("Gun_ChargeRifle"), this.pawn.Position, this.Map); } else { rifle = GenSpawn.Spawn(ThingDef.Named("Gun_SniperRifle"), this.pawn.Position, this.Map); } CompQuality qualityComp = powerArmor.TryGetComp <CompQuality>(); if (qualityComp != null) { qualityComp.SetQuality(QualityCategory.Masterwork, ArtGenerationContext.Outsider); } qualityComp = powerArmorHelmet.TryGetComp <CompQuality>(); if (qualityComp != null) { qualityComp.SetQuality(QualityCategory.Masterwork, ArtGenerationContext.Outsider); } qualityComp = rifle.TryGetComp <CompQuality>(); if (qualityComp != null) { qualityComp.SetQuality(QualityCategory.Masterwork, ArtGenerationContext.Outsider); } Faction faction = Find.FactionManager.FirstFactionOfDef(FactionDefOf.AncientsHostile); Pawn deadMarine = PawnGenerator.GeneratePawn(PawnKindDefOf.AncientSoldier, faction); HealthUtility.DamageUntilDead(deadMarine); Corpse corpse = deadMarine.ParentHolder as Corpse; CompRottable rotComp = corpse.TryGetComp <CompRottable>(); if (rotComp != null) { rotComp.RotProgress = 20f * GenDate.TicksPerDay; // 20 days so the corpse is dessicated. } GenSpawn.Spawn(corpse, fishingPier.bankCell, this.Map); string eventText = "FishIndustry.LetterDescDeadMarine".Translate(this.pawn.Name.ToStringShort.CapitalizeFirst()); Find.LetterStack.ReceiveLetter("FishIndustry.LetterLabelDeadMarine".Translate(), eventText, LetterDefOf.PositiveEvent, this.pawn); } else { // Find a small amount of gold. fishingCatch = GenSpawn.Spawn(ThingDefOf.Gold, this.pawn.Position, this.Map); fishingCatch.stackCount = Rand.RangeInclusive(1, 7); } } else if (catchSelectorValue < 0.04) { // Find oysters. fishingCatch = GenSpawn.Spawn(Util_FishIndustry.OysterDef, this.pawn.Position, this.Map); fishingCatch.stackCount = Rand.RangeInclusive(2, 9); } else { // Catch a fish. IntVec3 fishSpot = fishingPier.aquaticCells.RandomElement(); bool fishSpotIsOcean = (this.Map.terrainGrid.TerrainAt(fishSpot) == TerrainDefOf.WaterOceanShallow) || (this.Map.terrainGrid.TerrainAt(fishSpot) == TerrainDefOf.WaterOceanDeep); bool fishSpotIsMarshy = (this.Map.terrainGrid.TerrainAt(fishSpot) == TerrainDef.Named("Marsh")); PawnKindDef caugthFishDef = null; if (fishSpotIsOcean) { caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList(this.Map.Biome) where fishSpecies.livesInOcean select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality); } else if (fishSpotIsMarshy) { caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList(this.Map.Biome) where fishSpecies.livesInMarsh select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality); } else { caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList(this.Map.Biome) where fishSpecies.livesInRiver select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality); } Pawn caughtFish = PawnGenerator.GeneratePawn(caugthFishDef); ExecutionUtility.DoExecutionByCut(this.pawn, caughtFish); Corpse corpse = caughtFish.ParentHolder as Corpse; GenSpawn.Spawn(corpse, this.pawn.Position, this.Map); fishingCatch = corpse; fishingCatch.SetForbidden(false); if (caughtFish.BodySize >= 0.1f) { fishingPier.fishStock--; } } IntVec3 storageCell; if (StoreUtility.TryFindBestBetterStoreCellFor(fishingCatch, this.pawn, this.Map, StoragePriority.Unstored, this.pawn.Faction, out storageCell, true)) { this.pawn.Reserve(fishingCatch, this.job); this.pawn.Reserve(storageCell, this.job); this.pawn.CurJob.SetTarget(TargetIndex.B, storageCell); this.pawn.CurJob.SetTarget(TargetIndex.A, fishingCatch); this.pawn.CurJob.count = 9999; this.pawn.CurJob.haulMode = HaulMode.ToCellStorage; } else { this.pawn.jobs.EndCurrentJob(JobCondition.Succeeded); } } }; yield return(catchFishToil); yield return(Toils_Haul.StartCarryThing(TargetIndex.A)); Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.B); yield return(carryToCell); yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, true)); }
protected override IEnumerable <Toil> MakeNewToils() { Toil startJobToil = new Toil(); startJobToil.initAction = delegate { jobStartTick = Find.TickManager.TicksGame; }; yield return(startJobToil); yield return(Toils_Combat.TrySetJobToUseAttackVerb(TargetIndex.A)); Toil startCollectCorpseLabel = Toils_General.Label(); Toil slaughterLabel = Toils_General.Label(); Toil meleeLabel = Toils_General.Label(); Toil checkTargetToil = new Toil(); checkTargetToil.initAction = delegate { targetCheckTick = Find.TickManager.TicksGame; //if (pawn.equipment.Primary == null || pawn.equipment.Primary.def.IsMeleeWeapon) // pawn.jobs.curDriver.JumpToToil(meleeLabel); }; yield return(checkTargetToil); //Toil gotoCastPos = Toils_Combat.GotoCastPosition(TargetIndex.A, true, 0.95f).JumpIfDespawnedOrNull(TargetIndex.A, startCollectCorpseLabel).FailOn(() => Find.TickManager.TicksGame > jobStartTick + 5000); Toil gotoCastPos = Toils_Combat.GotoCastPosition(TargetIndex.A, true, 4.0f) .JumpIfDespawnedOrNull(TargetIndex.A, startCollectCorpseLabel) .JumpIf(() => Find.TickManager.TicksGame > targetCheckTick + targetCheckInterval, checkTargetToil); yield return(gotoCastPos); Toil selectAttack = new Toil(); selectAttack.initAction = delegate { if (pawn.CanReachImmediate(TargetA, PathEndMode.Touch)) { pawn.jobs.curDriver.JumpToToil(meleeLabel); } else if (Victim.Downed) { if (Victim.AnimalOrWildMan()) { pawn.jobs.curDriver.JumpToToil(slaughterLabel); } else { pawn.jobs.curDriver.JumpToToil(meleeLabel); } } }; yield return(selectAttack); // Ranged attack yield return(Toils_Jump.JumpIfTargetNotHittable(TargetIndex.A, checkTargetToil)); yield return(Toils_Combat.CastVerb(TargetIndex.A, canHitNonTargetPawns: false).JumpIfDespawnedOrNull(TargetIndex.A, startCollectCorpseLabel).FailOn(() => Find.TickManager.TicksGame > jobStartTick + 5000)); yield return(Toils_Jump.JumpIfTargetDespawnedOrNull(TargetIndex.A, startCollectCorpseLabel)); yield return(Toils_Jump.Jump(selectAttack)); // Melee yield return(meleeLabel); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch).JumpIf(() => Find.TickManager.TicksGame > targetCheckTick + targetCheckInterval, checkTargetToil)); //yield return Toils_Goto.GotoCell(TargetIndex.A, PathEndMode.OnCell).JumpIf(() => Find.TickManager.TicksGame > targetCheckTick + targetCheckInterval, checkTargetToil); Toil meleeAttack = new Toil(); meleeAttack.tickAction = delegate { if (Victim == null || !Victim.Spawned || Victim.IsForbidden(pawn) || !pawn.CanReachImmediate(TargetA, PathEndMode.Touch)) { pawn.jobs.curDriver.JumpToToil(checkTargetToil); } else if (Victim.Downed && Victim.AnimalOrWildMan()) { pawn.jobs.curDriver.JumpToToil(slaughterLabel); } pawn.pather.StopDead(); pawn.meleeVerbs.TryMeleeAttack(Victim); }; meleeAttack.activeSkill = () => SkillDefOf.Melee; meleeAttack.defaultCompleteMode = ToilCompleteMode.Never; yield return(meleeAttack); yield return(Toils_Jump.JumpIfCannotTouch(TargetIndex.A, PathEndMode.Touch, checkTargetToil)); // Slaughter target yield return(slaughterLabel); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.Touch).FailOnMobile(TargetIndex.A)); yield return(Toils_General.WaitWith(TargetIndex.A, 180, useProgressBar: true).FailOnMobile(TargetIndex.A)); yield return(Toils_General.Do(delegate { if (!Victim.Dead) { ExecutionUtility.DoExecutionByCut(pawn, Victim); pawn.records.Increment(RecordDefOf.AnimalsSlaughtered); if (pawn.InMentalState) { pawn.MentalState.Notify_SlaughteredAnimal(); } } })); yield return(Toils_Jump.Jump(startCollectCorpseLabel)); yield return(startCollectCorpseLabel); //yield return Toils_Misc.ThrowColonistAttackingMote(TargetIndex.A); //yield return Toils_Combat.FollowAndMeleeAttack(TargetIndex.A, delegate //{ // Thing thing = job.GetTarget(TargetIndex.A).Thing; // Pawn p; // if (job.reactingToMeleeThreat && (p = thing as Pawn) != null && !p.Awake()) // { // EndJobWith(JobCondition.InterruptForced); // } // else if (pawn.meleeVerbs.TryMeleeAttack(thing, job.verbToUse) && pawn.CurJob != null && pawn.jobs.curDriver == this) // { // numMeleeAttacksMade++; // if (numMeleeAttacksMade >= job.maxNumMeleeAttacks) // { // EndJobWith(JobCondition.Succeeded); // } // } //}).FailOnDespawnedOrNull(TargetIndex.A); }
protected override IEnumerable <Toil> MakeNewToils() { const float baseFishingDuration = 2400f; const float skillGainPerTick = 0.15f; const float catchSuccessRateInZone = 0.70f; int fishingDuration = (int)baseFishingDuration; // Compute fishing duration. float fishingSkillLevel = 0f; fishingSkillLevel = this.pawn.skills.AverageOfRelevantSkillsFor(WorkTypeDefOf.Hunting); float fishingSkillDurationFactor = fishingSkillLevel / 20f; fishingDuration = (int)(baseFishingDuration * (1.5f - fishingSkillDurationFactor)); Toil faceWaterToil = new Toil() { initAction = () => { // Compute pawn rotation during fishing. foreach (IntVec3 offset in GenAdj.CardinalDirections.InRandomOrder()) { IntVec3 adjacentCell = this.TargetLocA + offset; Zone_Fishing fishingZone = adjacentCell.GetZone(this.Map) as Zone_Fishing; if ((fishingZone != null) && fishingZone.fishingSpots.Contains(this.TargetLocA)) { this.cardinalDir = offset; this.pawn.CurJob.SetTarget(TargetIndex.B, adjacentCell); this.rotateToFace = TargetIndex.B; break; } } }, defaultCompleteMode = ToilCompleteMode.Instant }; yield return(faceWaterToil); yield return(Toils_Goto.GotoCell(this.TargetLocA, this.pathEndMode).FailOn(FishingForbiddenOrInvalidSpot)); Toil fishToil = new Toil() { tickAction = () => { this.pawn.skills.Learn(SkillDefOf.Shooting, skillGainPerTick); // Spawn mote or maintain it. if (this.fishingRodMote.DestroyedOrNull()) { IntVec3 motePosition = this.TargetB.Cell; ThingDef moteDef = null; if (cardinalDir == IntVec3.North) { moteDef = Util_FishIndustry.MoteFishingRodNorthDef; } else if (cardinalDir == IntVec3.East) { moteDef = Util_FishIndustry.MoteFishingRodEastDef; } else if (cardinalDir == IntVec3.South) { moteDef = Util_FishIndustry.MoteFishingRodSouthDef; } else { moteDef = Util_FishIndustry.MoteFishingRodWestDef; } this.fishingRodMote = (Mote)ThingMaker.MakeThing(moteDef, null); this.fishingRodMote.exactPosition = motePosition.ToVector3Shifted(); this.fishingRodMote.Scale = 1f; GenSpawn.Spawn(this.fishingRodMote, motePosition, this.Map); } else { this.fishingRodMote.Maintain(); } }, defaultDuration = fishingDuration, defaultCompleteMode = ToilCompleteMode.Delay }; yield return(fishToil.WithProgressBarToilDelay(this.fishPositionIndex, true).FailOn(FishingForbiddenOrInvalidSpot)); Toil catchFishToil = new Toil() { initAction = () => { Thing fishingCatch = null; bool catchIsSuccessful = (Rand.Value <= catchSuccessRateInZone); if (catchIsSuccessful == false) { MoteMaker.ThrowMetaIcon(this.pawn.Position, this.Map, ThingDefOf.Mote_IncapIcon); this.pawn.jobs.EndCurrentJob(JobCondition.Incompletable); return; } float catchSelectorValue = Rand.Value; if ((catchSelectorValue < 0.02) && Util_FishIndustry.GetFishSpeciesList(this.Map.Biome).Contains(Util_FishIndustry.TailteethPawnKindDef as PawnKindDef_FishSpecies)) { // Get hurt by a tailteeth. this.pawn.TakeDamage(new DamageInfo(DamageDefOf.Bite, Rand.Range(5, 12))); Messages.Message(this.pawn.Name.ToStringShort + "FishIndustry.FisherBitten".Translate(), this.pawn, MessageTypeDefOf.NegativeHealthEvent); this.pawn.jobs.EndCurrentJob(JobCondition.Incompletable); return; } else if (catchSelectorValue < 0.04) { // Find oysters. fishingCatch = GenSpawn.Spawn(Util_FishIndustry.OysterDef, this.pawn.Position, this.Map); fishingCatch.stackCount = Rand.RangeInclusive(5, 27); } else { // Catch a fish. bool fishSpotIsOcean = (this.Map.terrainGrid.TerrainAt(this.TargetLocA) == TerrainDefOf.WaterOceanShallow) || (this.Map.terrainGrid.TerrainAt(this.TargetLocA) == TerrainDefOf.WaterOceanDeep); bool fishSpotIsMarshy = (this.Map.terrainGrid.TerrainAt(this.TargetLocA) == TerrainDef.Named("Marsh")); PawnKindDef caugthFishDef = null; if (fishSpotIsOcean) { caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList(this.Map.Biome) where fishSpecies.livesInOcean select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality); } else if (fishSpotIsMarshy) { caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList(this.Map.Biome) where fishSpecies.livesInMarsh select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality); } else { caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList(this.Map.Biome) where fishSpecies.livesInRiver select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality); } Pawn caughtFish = PawnGenerator.GeneratePawn(caugthFishDef); ExecutionUtility.DoExecutionByCut(this.pawn, caughtFish); Corpse corpse = caughtFish.ParentHolder as Corpse; GenSpawn.Spawn(corpse, this.pawn.Position, this.Map); fishingCatch = corpse; fishingCatch.SetForbidden(false); if (caughtFish.BodySize >= 0.1f) { Zone_Fishing fishingZone = this.TargetB.Cell.GetZone(this.Map) as Zone_Fishing; if ((fishingZone != null) && fishingZone.fishingSpots.Contains(this.TargetLocA)) { fishingZone.fishingSpots.Remove(this.TargetLocA); } } } IntVec3 storageCell; if (StoreUtility.TryFindBestBetterStoreCellFor(fishingCatch, this.pawn, this.Map, StoragePriority.Unstored, this.pawn.Faction, out storageCell, true)) { this.pawn.Reserve(fishingCatch, this.job); this.pawn.Reserve(storageCell, this.job); this.pawn.CurJob.SetTarget(TargetIndex.B, storageCell); this.pawn.CurJob.SetTarget(TargetIndex.A, fishingCatch); this.pawn.CurJob.count = 9999; this.pawn.CurJob.haulMode = HaulMode.ToCellStorage; } else { this.pawn.jobs.EndCurrentJob(JobCondition.Succeeded); } } }; yield return(catchFishToil); yield return(Toils_Haul.StartCarryThing(TargetIndex.A)); Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.B); yield return(carryToCell); yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, true)); }