private void DestroyTarget() { if (this.targetWillBeHit) { foreach (Thing thing in this.target.contents.containedThings) { if (thing is Pawn) { // Spawn a dead copy of the pawn as the original one will be destroyed with the incoming drop pod. Pawn pawn = thing as Pawn; Pawn pawnCopy = PawnGenerator.GeneratePawn(pawn.kindDef, pawn.Faction); GenPlace.TryPlaceThing(pawnCopy, this.target.Position, ThingPlaceMode.Near); if (pawnCopy.equipment.Primary != null) { pawnCopy.equipment.Primary.HitPoints = (int)(Rand.Range(0.05f, 0.30f) * pawnCopy.equipment.Primary.MaxHitPoints); } HealthUtility.GiveInjuriesToKill(pawnCopy); // TODO: add tale. Destroyed drop pod. /*TaleRecorder.RecordTale(TaleDef.Named("LandedInPod"), new object[] * { * pawnCopy * });*/ break; } } for (int slagIndex = 0; slagIndex < 3; slagIndex++) { GenPlace.TryPlaceThing(ThingMaker.MakeThing(ThingDefOf.ChunkSlagSteel), this.target.Position + new IntVec3(Rand.Range(-3, 3), 0, Rand.Range(-3, 3)), ThingPlaceMode.Near); } FireUtility.TryStartFireIn(this.target.Position + new IntVec3(Rand.Range(-3, 3), 0, Rand.Range(-3, 3)), 0.3f); this.target.Destroy(DestroyMode.Vanish); } }
public static void KillAndRotPawn(Pawn pawn, float rotProgressInTicks) { HealthUtility.GiveInjuriesToKill(pawn); foreach (Thing thing in pawn.Position.GetThingList(pawn.MapHeld)) { if (thing.def.defName.Contains("Corpse")) { CompRottable rotComp = thing.TryGetComp <CompRottable>(); if (rotComp != null) { rotComp.RotProgress = rotProgressInTicks; } } } }
public void GenerateWarfield(int battleZoneAbs, int battleZoneOrd, OG_OutpostData outpostData) { // Get a random hostile faction. int securityForcesCorpseNumber = Rand.Range(2, 4); int hostilesCorpseNumber = 0; FactionDef hostileFactionDef = null; Faction hostileFaction = null; float hostileFactionSelector = Rand.Value; if (hostileFactionSelector < 0.25f) { hostileFactionDef = FactionDefOf.Tribe; hostileFaction = Find.FactionManager.FirstFactionOfDef(hostileFactionDef); hostilesCorpseNumber = Rand.Range(6, 8); } else if (hostileFactionSelector < 0.5f) { hostileFactionDef = FactionDefOf.Pirate; hostileFaction = Find.FactionManager.FirstFactionOfDef(hostileFactionDef); hostilesCorpseNumber = Rand.Range(3, 5); } else if (hostileFactionSelector < 0.75f) { hostileFactionDef = FactionDefOf.SpacerHostile; hostileFaction = Find.FactionManager.FirstFactionOfDef(hostileFactionDef); hostilesCorpseNumber = Rand.Range(3, 5); } else { hostileFactionDef = FactionDefOf.Mechanoid; hostileFaction = Find.FactionManager.FirstFactionOfDef(hostileFactionDef); hostilesCorpseNumber = Rand.Range(1, 3); } // Spawn corpses. IntVec3 zoneOrigin = Zone.GetZoneOrigin(outpostData.areaSouthWestOrigin, battleZoneAbs, battleZoneOrd); for (int corpseIndex = 0; corpseIndex < securityForcesCorpseNumber + hostilesCorpseNumber; corpseIndex++) { int tries = 3; // Max 3 tries per corpse. bool validPositionIsFound = false; IntVec3 corpsePosition = new IntVec3(); for (int tryIndex = 0; tryIndex < tries; tryIndex++) { corpsePosition = zoneOrigin + new IntVec3(Rand.Range(1, Genstep_GenerateOutpost.zoneSideSize - 1), 0, Rand.Range(1, Genstep_GenerateOutpost.zoneSideSize - 1)); if (corpsePosition.GetEdifice() == null) { validPositionIsFound = true; break; } } if (validPositionIsFound == false) { continue; } // Generate the corpse according to the faction. Pawn corpse = null; if (corpseIndex < securityForcesCorpseNumber) { corpse = PawnGenerator.GeneratePawn(OG_Util.OutpostScoutDef, OG_Util.FactionOfMAndCo); } else { float pawnKindSelector = Rand.Value; PawnKindDef corpseKindDef = null; if (hostileFactionDef == FactionDefOf.Tribe) { if (pawnKindSelector < 0.4f) { corpseKindDef = PawnKindDef.Named("TribalWarrior"); } else if (pawnKindSelector < 0.8f) { corpseKindDef = PawnKindDef.Named("TribalArcher"); } else { corpseKindDef = PawnKindDef.Named("TribalChief"); } } else if (hostileFactionDef == FactionDefOf.Pirate) { if (pawnKindSelector < 0.25f) { corpseKindDef = PawnKindDef.Named("Drifter"); } else if (pawnKindSelector < 0.50f) { corpseKindDef = PawnKindDef.Named("Scavenger"); } else if (pawnKindSelector < 0.75f) { corpseKindDef = PawnKindDef.Named("Thrasher"); } else { corpseKindDef = PawnKindDef.Named("Pirate"); } } else if (hostileFactionDef == FactionDefOf.SpacerHostile) { if (pawnKindSelector < 0.25f) { corpseKindDef = PawnKindDef.Named("SpaceSoldier"); } else if (pawnKindSelector < 0.50f) { corpseKindDef = PawnKindDef.Named("MercenaryGunner"); } else if (pawnKindSelector < 0.75f) { corpseKindDef = PawnKindDef.Named("GrenadierDestructive"); } else { corpseKindDef = PawnKindDef.Named("MercenaryElite"); } } else if (hostileFactionDef == FactionDefOf.Mechanoid) { if (pawnKindSelector < 0.6f) { corpseKindDef = PawnKindDef.Named("Scyther"); } else { corpseKindDef = PawnKindDef.Named("Centipede"); } } corpse = PawnGenerator.GeneratePawn(corpseKindDef, hostileFaction); } GenSpawn.Spawn(corpse, corpsePosition); // Damage the weapon so the warfield effect is not too exploitable (otherwise, player can get good guns at game start). if (corpse.equipment.Primary != null) { corpse.equipment.Primary.HitPoints = (int)(Rand.Range(0.05f, 0.30f) * corpse.equipment.Primary.MaxHitPoints); } // "Kill the corpse". HealthUtility.GiveInjuriesToKill(corpse); // Make it rotten if outpost is abandonned. if (this.outpostData.isInhabited == false) { List <Thing> thingsList = corpsePosition.GetThingList(); foreach (Thing thing in thingsList) { if (thing.def.defName.Contains("Corpse")) { CompRottable rotComp = thing.TryGetComp <CompRottable>(); if (rotComp != null) { rotComp.rotProgress = 20f * GenDate.TicksPerDay; // 20 days so the corpse is dessicated. } } } } } // Destroy some sandbags in the zone. List <Thing> sandbagsList = Find.ListerThings.ThingsOfDef(ThingDefOf.Sandbags); for (int sandbagIndex = sandbagsList.Count - 1; sandbagIndex >= 0; sandbagIndex--) { Thing sandbag = sandbagsList[sandbagIndex]; if (sandbag.Position.InHorDistOf(this.Position, Genstep_GenerateOutpost.zoneSideSize / 2f) && (Rand.Value < 0.1f)) { // Manually spawn sandbag rubble and use Vanish instead of Kill to avoid spawning ugly metal remains. GenSpawn.Spawn(ThingDef.Named("SandbagRubble"), sandbag.Position); sandbag.Destroy(DestroyMode.Vanish); } } }
private void AddPsionicShock(Pawn pawn) { System.Random rand = new System.Random(); int psychicSensitivity = 0; bool?shouldGiveHeartAttack = null; bool?shouldSedate = null; if (pawn.story?.traits != null && pawn.story.traits.HasTrait(TraitDef.Named("PsychicSensitivity"))) { Trait psychicSensitivityTrait = pawn.story.traits.GetTrait(TraitDef.Named("PsychicSensitivity")); psychicSensitivity = psychicSensitivityTrait.Degree; } // If they're Psychically Deaf, do nothing: if (psychicSensitivity == -2) { return; } // If they're Psychically Dull, don't give them a heart attack. else if (psychicSensitivity == -1) { shouldGiveHeartAttack = false; } // If they're Psychically Sensitive, make sure they're passed out for a few hours. else if (psychicSensitivity == 1) { shouldSedate = true; } // If they're Psychically Hypersensitive, unfortunately, it will mean instant death :-( else if (psychicSensitivity >= 2) { Messages.Message(pawn.NameStringShort + " was psychically supersensitive and died because of the psionic blast.", MessageSound.SeriousAlert); HealthUtility.GiveInjuriesToKill(pawn); } Hediff shock = HediffMaker.MakeHediff(HediffDefOf.PsychicShock, pawn, null); pawn.health.AddHediff(shock, null, null); if (shouldGiveHeartAttack == null) { shouldGiveHeartAttack = rand.Next(1, 11) >= 3; } if (shouldGiveHeartAttack == true) { this.CauseHeartAttack(pawn); } if (shouldSedate == null) { int likelihood = rand.Next(1, 11); Log.Message(pawn.NameStringShort + " should sedate? " + likelihood); shouldSedate = likelihood >= 6; } if (shouldSedate == true) { this.CauseSedation(pawn); } DamageInfo psionicIntensity = new DamageInfo(DamageDefOf.Stun, 50); pawn.TakeDamage(psionicIntensity); }
protected override IEnumerable <Toil> MakeNewToils() { QualityCategory fishingEquipmentQuality = QualityCategory.Normal; float catchSomethingThreshold = 0f; Building_FishingPier fishingPier = this.TargetThingA as Building_FishingPier; Passion passion = Passion.None; int fishingDuration = 1000; const float skillGainPerTick = 0.15f; float skillGainFactor = 0f; this.AddEndCondition(() => { var targ = this.pawn.jobs.curJob.GetTarget(fishingPierIndex).Thing; if (targ is Building && !targ.Spawned) { return(JobCondition.Incompletable); } return(JobCondition.Ongoing); }); this.FailOnBurningImmobile(fishingPierIndex); // Bill giver or product burning in carry phase. yield return(Toils_Reserve.Reserve(fishingPierIndex)); float statValue = this.pawn.GetStatValue(Util_FishIndustry.FishingSpeedDef, true); fishingDuration = (int)Math.Round((double)(800f / statValue)); yield return(Toils_Goto.GotoThing(fishingPierIndex, fishingPier.riverCell).FailOnDespawnedOrNull(fishingPierIndex)); Toil verifyFisherHasFishingEquipmentToil = new Toil() { initAction = () => { if ((this.pawn.equipment.Primary != null) && (this.pawn.equipment.Primary.def == Util_FishIndustry.HarpoonDef)) { this.fishingEquipment = FishingEquipment.Harpoon; this.pawn.equipment.Primary.TryGetQuality(out fishingEquipmentQuality); } foreach (Apparel apparel in this.pawn.apparel.WornApparel) { if (apparel.def == Util_FishIndustry.FishingRodDef) { this.fishingEquipment = FishingEquipment.FishingRod; apparel.TryGetQuality(out fishingEquipmentQuality); break; } } if (this.fishingEquipment == FishingEquipment.NoEquipment) { this.pawn.jobs.EndCurrentJob(JobCondition.Incompletable); } } }; yield return(verifyFisherHasFishingEquipmentToil); Toil fishToil = new Toil() { initAction = () => { ThingDef moteDef = null; if (fishingEquipment == FishingEquipment.FishingRod) { 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; } } if (moteDef != null) { this.fishingRodMote = (Mote)ThingMaker.MakeThing(moteDef, null); this.fishingRodMote.exactPosition = fishingPier.fishingSpotCell.ToVector3Shifted(); this.fishingRodMote.Scale = 1f; GenSpawn.Spawn(this.fishingRodMote, fishingPier.fishingSpotCell); } WorkTypeDef fishingWorkDef = DefDatabase <WorkTypeDef> .GetNamed("Fishing"); passion = this.pawn.skills.MaxPassionOfRelevantSkillsFor(fishingWorkDef); if (passion == Passion.None) { skillGainFactor = 0.3f; } else if (passion == Passion.Minor) { skillGainFactor = 1f; } else { skillGainFactor = 1.5f; } }, tickAction = () => { if (fishingEquipment == FishingEquipment.Harpoon) { if (Find.TickManager.TicksGame % GenTicks.TickRareInterval == 0) { Bullet thrownHarpoon = GenSpawn.Spawn(Util_FishIndustry.HarpoonDef.Verbs.First().projectileDef, this.pawn.Position) as Bullet; TargetInfo targetCell = new TargetInfo(fishingPier.fishingSpotCell + new IntVec3(Rand.RangeInclusive(-1, 1), 0, Rand.RangeInclusive(0, 2)).RotatedBy(fishingPier.Rotation)); thrownHarpoon.Launch(this.pawn, targetCell); } } this.pawn.Drawer.rotator.FaceCell(fishingPier.fishingSpotCell); if (passion == Passion.Minor) { this.pawn.needs.joy.GainJoy(NeedTunings.JoyPerXpForPassionMinor, JoyKindDefOf.Work); } else if (passion == Passion.Major) { this.pawn.needs.joy.GainJoy(NeedTunings.JoyPerXpForPassionMajor, JoyKindDefOf.Work); } SkillDef fishingSkillDef = DefDatabase <SkillDef> .GetNamed("Fishing"); this.pawn.skills.Learn(fishingSkillDef, skillGainPerTick * skillGainFactor); if (this.ticksLeftThisToil == 1) { if (this.fishingRodMote != null) { Log.Message("destroy mote"); this.fishingRodMote.Destroy(); } } }, defaultDuration = fishingDuration, defaultCompleteMode = ToilCompleteMode.Delay }; yield return(fishToil.WithProgressBarToilDelay(fishingPierIndex)); yield return(verifyFisherHasFishingEquipmentToil); // Could be dropped during fishToil. Toil computeChanceToCatchToil = new Toil() { initAction = () => { float fishingSkillLevel = 0f; WorkTypeDef fishingWorkDef = DefDatabase <WorkTypeDef> .GetNamed("Fishing"); fishingSkillLevel = this.pawn.skills.AverageOfRelevantSkillsFor(fishingWorkDef); float fishingEquipmentQualityFactor = (float)fishingEquipmentQuality / (float)QualityCategory.Legendary; float fishingSkillFactor = fishingSkillLevel / 20f; float snowFactor = 1 - Find.SnowGrid.GetDepth(fishingPier.fishingSpotCell); float fishingEquipmentOffset = 0f; switch (this.fishingEquipment) { case FishingEquipment.Harpoon: fishingEquipmentOffset = 0.2f; break; case FishingEquipment.FishingRod: fishingEquipmentOffset = 0.5f; break; } catchSomethingThreshold = ((fishingEquipmentOffset * fishingEquipmentQualityFactor) + 0.4f * fishingSkillFactor) * (0.25f + 0.75f * snowFactor); // Reframe min and max chance (min 5%, max 75 % chance of success). catchSomethingThreshold = catchSomethingThreshold * 0.75f; catchSomethingThreshold = Math.Max(catchSomethingThreshold, 0.05f); }, defaultCompleteMode = ToilCompleteMode.Instant }; yield return(computeChanceToCatchToil); Toil catchFishToil = new Toil() { initAction = () => { Job curJob = this.pawn.jobs.curJob; Thing fishingCatch = null; bool catchIsSuccessful = Rand.Value <= catchSomethingThreshold; if (catchIsSuccessful == false) { MoteMaker.ThrowMetaIcon(this.pawn.Position, ThingDefOf.Mote_IncapIcon); this.pawn.jobs.EndCurrentJob(JobCondition.Incompletable); return; } float catchSelectorValue = Rand.Value; if (catchSelectorValue > 0.04f) { // Catch a fish. bool fishSpotIsMarshy = (Find.TerrainGrid.TerrainAt(fishingPier.fishingSpotCell) == TerrainDef.Named("Marsh")); bool isDaytime = (SkyManager.CurSkyGlow >= 0.4f); ThingDef caugthFishDef = Util_FishIndustry.TailteethDef; if (fishSpotIsMarshy && isDaytime) { caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList() where fishSpecies.livesInMarsh where fishSpecies.catchableDuringDay select fishSpecies).RandomElementByWeight((ThingDef_FishSpecies def) => def.commonality); } else if (fishSpotIsMarshy && !isDaytime) { caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList() where fishSpecies.livesInMarsh where fishSpecies.catchableDuringNight select fishSpecies).RandomElementByWeight((ThingDef_FishSpecies def) => def.commonality); } else if (!fishSpotIsMarshy && isDaytime) { caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList() where fishSpecies.livesInSea where fishSpecies.catchableDuringDay select fishSpecies).RandomElementByWeight((ThingDef_FishSpecies def) => def.commonality); } else { caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList() where fishSpecies.livesInSea where fishSpecies.catchableDuringNight select fishSpecies).RandomElementByWeight((ThingDef_FishSpecies def) => def.commonality); } /*TerrainDef fishSpotType = Find.TerrainGrid.TerrainAt(fishingPier.fishingSpotCell); * List<ThingDef> fishSpeciesList = null; * ThingDef_FishSpecies.AquaticEnvironment aquaticEnvironment; * ThingDef_FishSpecies.LivingTime livingTime; * float fishSpeciesTotalCommonality = 0f; * float fishSpeciesCommonalitySum = 0f; * * // Aquatic environment. * if (fishSpotType == TerrainDef.Named("Marsh")) * { * aquaticEnvironment = ThingDef_FishSpecies.AquaticEnvironment.Marsh; * } * else * { * aquaticEnvironment = ThingDef_FishSpecies.AquaticEnvironment.Sea; * } * // Day time. * if (SkyManager.CurSkyGlow >= 0.4f) * { * livingTime = ThingDef_FishSpecies.LivingTime.Day; * } * else * { * livingTime = ThingDef_FishSpecies.LivingTime.Night; * } * * fishSpeciesList = Util_FishIndustry.GetFishSpeciesList(aquaticEnvironment, livingTime); * fishSpeciesTotalCommonality = Util_FishIndustry.GetFishSpeciesTotalCommonality(aquaticEnvironment, livingTime); * * float randomSelector = Rand.Range(0f, fishSpeciesTotalCommonality); * ThingDef selectedFishSpecies = null; * for (int fishSpeciesIndex = 0; fishSpeciesIndex < fishSpeciesList.Count; fishSpeciesIndex++) * { * ThingDef_FishSpecies currentFishSpecies = fishSpeciesList[fishSpeciesIndex] as ThingDef_FishSpecies; * fishSpeciesCommonalitySum += currentFishSpecies.commonality; * * if (randomSelector <= fishSpeciesCommonalitySum) * { * selectedFishSpecies = currentFishSpecies; * break; * } * }*/ fishingCatch = GenSpawn.Spawn(caugthFishDef, this.pawn.Position); fishingCatch.stackCount = (caugthFishDef as ThingDef_FishSpecies).catchQuantity; fishingPier.fishStock--; } else if (catchSelectorValue > 0.02) { fishingCatch = GenSpawn.Spawn(Util_FishIndustry.OysterDef, this.pawn.Position); fishingCatch.stackCount = Rand.RangeInclusive(5, 27); } else { float bonusCatchValue = Rand.Value; if (bonusCatchValue < 0.01f) { // Really small chance to find a sunken treasure!!! fishingCatch = GenSpawn.Spawn(ThingDefOf.Gold, this.pawn.Position); fishingCatch.stackCount = Rand.RangeInclusive(58, 289); Thing treasureSilver = GenSpawn.Spawn(ThingDefOf.Silver, fishingPier.middleCell); treasureSilver.stackCount = Rand.RangeInclusive(237, 2154); string eventText = this.pawn.Name.ToStringShort.CapitalizeFirst() + " has found a sunken treasure while fishing! What a good catch!\n"; Find.LetterStack.ReceiveLetter("Sunken treasure!", eventText, LetterType.Good, this.pawn.Position); } 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); fishingCatch = powerArmor; // Used to carry the power armor. Thing powerArmorHelmet = GenSpawn.Spawn(ThingDef.Named("Apparel_PowerArmorHelmet"), this.pawn.Position); Thing rifle = null; if (Rand.Value < 0.5f) { rifle = GenSpawn.Spawn(ThingDef.Named("Gun_ChargeRifle"), this.pawn.Position); } else { rifle = GenSpawn.Spawn(ThingDef.Named("Gun_SniperRifle"), this.pawn.Position); } 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.SpacerHostile); Pawn deadMarine = PawnGenerator.GeneratePawn(PawnKindDefOf.SpaceSoldier, faction); GenSpawn.Spawn(deadMarine, fishingPier.bankCell); HealthUtility.GiveInjuriesToKill(deadMarine); List <Thing> thingsList = deadMarine.Position.GetThingList(); foreach (Thing thing in thingsList) { if (thing.def.defName.Contains("Corpse")) { CompRottable rotComp = thing.TryGetComp <CompRottable>(); if (rotComp != null) { rotComp.RotProgress = 20f * GenDate.TicksPerDay; // 20 days so the corpse is dessicated. } } } string eventText = this.pawn.Name.ToStringShort.CapitalizeFirst() + " has cought a dead body while fishing!\n\n'This is really disgusting but look at his gear! This guy was probably a Mining & Co. security member. I wonder what happend to him...'\n"; Find.LetterStack.ReceiveLetter("Dead marine", eventText, LetterType.Good, this.pawn.Position); } else { // Find a small amount of gold. fishingCatch = GenSpawn.Spawn(ThingDefOf.Gold, this.pawn.Position); fishingCatch.stackCount = Rand.RangeInclusive(1, 7); } // TODO: add chance to get hurt by a tailteeth (missing finger or even hand!). } IntVec3 storageCell; if (StoreUtility.TryFindBestBetterStoreCellFor(fishingCatch, this.pawn, StoragePriority.Unstored, this.pawn.Faction, out storageCell, true)) { this.pawn.carrier.TryStartCarry(fishingCatch); curJob.targetB = storageCell; curJob.targetC = fishingCatch; curJob.maxNumToCarry = 99999; } else { this.pawn.jobs.EndCurrentJob(JobCondition.Succeeded); } } }; yield return(catchFishToil); // Reserve the product and storage cell. yield return(Toils_Reserve.Reserve(TargetIndex.B)); yield return(Toils_Reserve.Reserve(TargetIndex.C)); Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.B); yield return(carryToCell); yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, true)); yield return(Toils_Reserve.Release(fishingPierIndex)); }
protected override IEnumerable <Toil> MakeNewToils() { const float baseFishingDuration = 2000f; int fishingDuration = (int)baseFishingDuration; float catchSomethingThreshold = 0f; Building_FishingPier fishingPier = this.TargetThingA as Building_FishingPier; Passion passion = Passion.None; const float skillGainPerTick = 0.15f; float skillGainFactor = 0f; this.AddEndCondition(() => { var targ = this.pawn.jobs.curJob.GetTarget(fishingPierIndex).Thing; if (targ is Building && !targ.Spawned) { return(JobCondition.Incompletable); } return(JobCondition.Ongoing); }); this.FailOnBurningImmobile(fishingPierIndex); // Bill giver or product burning in carry phase. this.rotateToFace = TargetIndex.B; yield return(Toils_Reserve.Reserve(fishingPierIndex)); 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).FailOnDespawnedOrNull(fishingPierIndex)); 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); WorkTypeDef fishingWorkDef = WorkTypeDefOf.Hunting; passion = this.pawn.skills.MaxPassionOfRelevantSkillsFor(fishingWorkDef); if (passion == Passion.None) { skillGainFactor = 0.3f; } else if (passion == Passion.Minor) { skillGainFactor = 1f; } else { skillGainFactor = 1.5f; } }, tickAction = () => { if (passion == Passion.Minor) { this.pawn.needs.joy.GainJoy(NeedTunings.JoyPerXpForPassionMinor, JoyKindDefOf.Work); } else if (passion == Passion.Major) { this.pawn.needs.joy.GainJoy(NeedTunings.JoyPerXpForPassionMajor, JoyKindDefOf.Work); } this.pawn.skills.Learn(SkillDefOf.Shooting, skillGainPerTick * skillGainFactor); if (this.ticksLeftThisToil == 1) { if (this.fishingRodMote != null) { this.fishingRodMote.Destroy(); } } }, defaultDuration = fishingDuration, defaultCompleteMode = ToilCompleteMode.Delay }; yield return(fishToil.WithProgressBarToilDelay(fishingPierIndex)); Toil computeChanceToCatchToil = new Toil() { initAction = () => { catchSomethingThreshold = fishingSkillLevel / 20f; // Reframe min and max chance (min 5%, max 75 % chance of success). Mathf.Clamp(catchSomethingThreshold, 0.05f, 0.75f); }, defaultCompleteMode = ToilCompleteMode.Instant }; yield return(computeChanceToCatchToil); Toil catchFishToil = new Toil() { initAction = () => { Job curJob = this.pawn.jobs.curJob; Thing fishingCatch = null; // 90% chance to successfully catch something. bool catchIsSuccessful = (Rand.Value >= 0.1f); 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.04f) { // Catch a fish. bool fishSpotIsMarshy = (this.Map.terrainGrid.TerrainAt(fishingPier.fishingSpotCell) == TerrainDef.Named("Marsh")); bool isDaytime = (this.Map.skyManager.CurSkyGlow >= 0.4f); PawnKindDef caugthFishDef = null; if (fishSpotIsMarshy && isDaytime) { caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList() where fishSpecies.livesInMarsh where fishSpecies.catchableDuringDay select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality); } else if (fishSpotIsMarshy && !isDaytime) { caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList() where fishSpecies.livesInMarsh where fishSpecies.catchableDuringNight select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality); } else if (!fishSpotIsMarshy && isDaytime) { caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList() where fishSpecies.livesInSea where fishSpecies.catchableDuringDay select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality); } else { caugthFishDef = (from fishSpecies in Util_FishIndustry.GetFishSpeciesList() where fishSpecies.livesInSea where fishSpecies.catchableDuringNight select fishSpecies).RandomElementByWeight((PawnKindDef_FishSpecies def) => def.commonality); } Pawn caughtFish = PawnGenerator.GeneratePawn(caugthFishDef); GenSpawn.Spawn(caughtFish, this.pawn.Position, this.Map); HealthUtility.GiveInjuriesToKill(caughtFish); foreach (Thing thing in this.pawn.Position.GetThingList(this.Map)) { Corpse fishCorpse = thing as Corpse; if (fishCorpse != null) { fishingCatch = fishCorpse; } } if (caughtFish.BodySize >= 0.1f) { fishingPier.fishStock--; fishingPier.UpdateMaxFishStock(); } } else if (catchSelectorValue > 0.02) { fishingCatch = GenSpawn.Spawn(Util_FishIndustry.OysterDef, this.pawn.Position, this.Map); fishingCatch.stackCount = Rand.RangeInclusive(5, 27); } else { 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); string eventText = this.pawn.Name.ToStringShort.CapitalizeFirst() + " has found a sunken treasure while fishing! What a good catch!\n"; Find.LetterStack.ReceiveLetter("Sunken treasure!", eventText, LetterType.Good, 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.SpacerHostile); Pawn deadMarine = PawnGenerator.GeneratePawn(PawnKindDefOf.SpaceSoldier, faction); GenSpawn.Spawn(deadMarine, fishingPier.bankCell, this.Map); HealthUtility.GiveInjuriesToKill(deadMarine); List <Thing> thingsList = deadMarine.Position.GetThingList(this.Map); foreach (Thing thing in thingsList) { if (thing.def.defName.Contains("Corpse")) { CompRottable rotComp = thing.TryGetComp <CompRottable>(); if (rotComp != null) { rotComp.RotProgress = 20f * GenDate.TicksPerDay; // 20 days so the corpse is dessicated. } } } string eventText = this.pawn.Name.ToStringShort.CapitalizeFirst() + " has cought a dead body while fishing!\n\n'This is really disgusting but look at his gear! This guy was probably a MiningCo. security member. I wonder what happend to him...'\n"; Find.LetterStack.ReceiveLetter("Dead marine", eventText, LetterType.Good, 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); } // TODO: add chance to get hurt by a tailteeth (missing finger or even hand!). } IntVec3 storageCell; if (StoreUtility.TryFindBestBetterStoreCellFor(fishingCatch, this.pawn, this.Map, StoragePriority.Unstored, this.pawn.Faction, out storageCell, true)) { this.pawn.carryTracker.TryStartCarry(fishingCatch); curJob.targetB = storageCell; curJob.targetC = fishingCatch; curJob.count = 99999; } else { this.pawn.jobs.EndCurrentJob(JobCondition.Succeeded); } } }; yield return(catchFishToil); // Reserve the product and storage cell. yield return(Toils_Reserve.Reserve(TargetIndex.B)); yield return(Toils_Reserve.Reserve(TargetIndex.C)); Toil carryToCell = Toils_Haul.CarryHauledThingToCell(TargetIndex.B); yield return(carryToCell); yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.B, carryToCell, true)); yield return(Toils_Reserve.Release(fishingPierIndex)); }
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); }