Beispiel #1
0
 public void Clear()
 {
     def                            = null;
     targetA                        = LocalTargetInfo.Invalid;
     targetB                        = LocalTargetInfo.Invalid;
     targetC                        = LocalTargetInfo.Invalid;
     targetQueueA                   = null;
     targetQueueB                   = null;
     count                          = -1;
     countQueue                     = null;
     loadID                         = -1;
     startTick                      = -1;
     expiryInterval                 = -1;
     checkOverrideOnExpire          = false;
     playerForced                   = false;
     placedThings                   = null;
     maxNumMeleeAttacks             = int.MaxValue;
     maxNumStaticAttacks            = int.MaxValue;
     locomotionUrgency              = LocomotionUrgency.Jog;
     haulMode                       = HaulMode.Undefined;
     bill                           = null;
     commTarget                     = null;
     plantDefToSow                  = null;
     verbToUse                      = null;
     haulOpportunisticDuplicates    = false;
     exitMapOnArrival               = false;
     failIfCantJoinOrCreateCaravan  = false;
     killIncappedTarget             = false;
     ignoreForbidden                = false;
     ignoreDesignations             = false;
     canBash                        = false;
     canUseRangedWeapon             = true;
     haulDroppedApparel             = false;
     restUntilHealed                = false;
     ignoreJoyTimeAssignment        = false;
     doUntilGatheringEnded          = false;
     overeat                        = false;
     attackDoorIfTargetLost         = false;
     takeExtraIngestibles           = 0;
     expireRequiresEnemiesNearby    = false;
     lord                           = null;
     collideWithPawns               = false;
     forceSleep                     = false;
     interaction                    = null;
     endIfCantShootTargetFromCurPos = false;
     endIfCantShootInMelee          = false;
     checkEncumbrance               = false;
     followRadius                   = 0f;
     endAfterTendedOnce             = false;
     quest                          = null;
     mote                           = null;
     jobGiverThinkTree              = null;
     jobGiver                       = null;
     workGiverDef                   = null;
     if (cachedDriver != null)
     {
         cachedDriver.job = null;
     }
     cachedDriver = null;
 }
Beispiel #2
0
        // Token: 0x060050F1 RID: 20721 RVA: 0x002A45C0 File Offset: 0x002A29C0
        public void DrawMoteInternal(Vector3 loc, Rot4 rot, ThingDef thingDef, Thing thing, int layer)
        {
            Mote  mote  = (Mote)thing;
            float alpha = mote.Alpha;

            if (alpha > 0f)
            {
                Color color = base.Color * mote.instanceColor;
                color.a *= alpha;
                Vector3 exactScale = mote.exactScale;
                exactScale.x *= this.data.drawSize.x;
                exactScale.z *= this.data.drawSize.y;
                Matrix4x4 matrix = default(Matrix4x4);
                matrix.SetTRS(mote.DrawPos, Quaternion.AngleAxis(mote.exactRotation, Vector3.up), exactScale);
                Material matSingle = MaterialFor(thing);

                if (!ForcePropertyBlock && color.IndistinguishableFrom(matSingle.color))
                {
                    Graphics.DrawMesh(MeshPool.plane10, matrix, matSingle, layer, null, 0);
                }
                else
                {
                    Graphic_Mote_Random.propertyBlock.SetColor(ShaderPropertyIDs.Color, color);
                    Graphics.DrawMesh(MeshPool.plane10, matrix, matSingle, layer, null, 0, Graphic_Mote_Random.propertyBlock);
                }
            }
        }
Beispiel #3
0
 public virtual void AbilityTick()
 {
     VerbTracker.VerbsTick();
     if (def.warmupMote != null && verb.WarmingUp)
     {
         if (warmupMote == null || warmupMote.Destroyed)
         {
             warmupMote = MoteMaker.MakeStaticMote(pawn.DrawPos + def.moteDrawOffset, pawn.Map, def.warmupMote);
         }
         else
         {
             warmupMote.Maintain();
         }
     }
     if (verb.WarmingUp && !CanApplyOn(verb.CurrentTarget))
     {
         verb.WarmupStance?.Interrupt();
         verb.Reset();
     }
     if (cooldownTicks > 0)
     {
         cooldownTicks--;
         if (cooldownTicks == 0 && def.sendLetterOnCooldownComplete)
         {
             Find.LetterStack.ReceiveLetter("AbilityReadyLabel".Translate(def.LabelCap), "AbilityReadyText".Translate(pawn, def.label), LetterDefOf.NeutralEvent, new LookTargets(pawn));
         }
     }
 }
            static void Mote_SpawnSetup_Postfix(Mote __instance)
            {
                if (__instance.Graphic is Graphic_AnimatedMote GAM &&
                    CustomTransformation_MoteDef.MyNamed(__instance.def.defName) is CustomTransformation_MoteDef CTMD)
                {
                    GAM.MyDebug = CTMD.debug;

                    if (CTMD.HasMisc)
                    {
                        GAM.Flipped = CTMD.transformation.misc.flipped;
                    }

                    if (CTMD.HasAnimatedMote)
                    {
                        GAM.FrameOffset = CTMD.transformation.animatedMote.frameOffset;
                        //GAM.FrameOffset += CTMD.transformation.animatedMote.randomFrameOffset.RandomInRange;
                        GAM.TicksPerFrame = CTMD.transformation.animatedMote.ticksPerFrame;
                        GAM.Engine        = CTMD.transformation.animatedMote.engine;
                    }
                    if (CTMD.HasRandomRotationRate)
                    {
                        __instance.rotationRate = CTMD.transformation.rotation.randRotRate.range.RandomInRange;
                    }

                    if (CTMD.HasPulsingScale)
                    {
                        GAM.PulsingScaleRange = CTMD.transformation.scale.pulsingScale.range;
                        GAM.PulsingScaleSpeed = CTMD.transformation.scale.pulsingScale.speed;
                    }
                }
            }
Beispiel #5
0
        public int GetAnotherIndex(Mote mote)
        {
            int stairCaseInput = (int)Math.Floor((double)(TickEngine(mote) / TicksPerFrame));
            int curFrame       = stairCaseInput % subGraphics.Length;

            return(curFrame);
        }
Beispiel #6
0
    void SpawnParticle(Vector2 pos, Vector2 targetPos, Color c)
    {
        Vector3 p = pos;

        p.z = transform.position.z + zOffset;

        Gradient g = new Gradient();

        g.FromColor(c);

        GameObject go = new GameObject();

        go.name = "ResourceMote";
        go.transform.position = p;

        TrailRenderer tr = go.AddComponent <TrailRenderer>();

        tr.material        = material;
        tr.time            = trailTime;
        tr.colorGradient   = g;
        tr.widthMultiplier = trailWidth;

        Mote mote = new Mote();

        mote.birthTime = Time.unscaledTime;
        mote.targetPos = targetPos;
        mote.velocity  = Random.insideUnitCircle.normalized * speed;
        mote.trail     = tr;

        motes.Add(mote);
    }
Beispiel #7
0
 protected void MeditationTick()
 {
     pawn.skills.Learn(SkillDefOf.Intellectual, 0.0180000011f);
     pawn.GainComfortFromCellIfPossible();
     if (pawn.needs.joy != null)
     {
         JoyUtility.JoyTickCheckEnd(pawn, JoyTickFullJoyAction.None);
     }
     if (pawn.IsHashIntervalTick(100))
     {
         MoteMaker.ThrowMetaIcon(pawn.Position, pawn.Map, ThingDefOf.Mote_Meditating);
     }
     if (!ModsConfig.RoyaltyActive)
     {
         return;
     }
     pawn.psychicEntropy.Notify_Meditated();
     if (pawn.HasPsylink && pawn.psychicEntropy.PsychicSensitivity > float.Epsilon)
     {
         if (psyfocusMote == null || psyfocusMote.Destroyed)
         {
             psyfocusMote = MoteMaker.MakeAttachedOverlay(pawn, ThingDefOf.Mote_PsyfocusPulse, Vector3.zero);
         }
         psyfocusMote.Maintain();
         if (sustainer == null || sustainer.Ended)
         {
             sustainer = SoundDefOf.MeditationGainPsyfocus.TrySpawnSustainer(SoundInfo.InMap(pawn, MaintenanceType.PerTick));
         }
         sustainer.Maintain();
         pawn.psychicEntropy.GainPsyfocus(Focus.Thing);
     }
 }
Beispiel #8
0
		public override void Apply(LocalTargetInfo target, LocalTargetInfo dest)
		{
			base.Apply(target, dest);
			Map map = parent.pawn.Map;
			foreach (IntVec3 item in AffectedCells(target, map))
			{
				List<Thing> thingList = item.GetThingList(map);
				for (int num = thingList.Count - 1; num >= 0; num--)
				{
					if (thingList[num] is Fire)
					{
						thingList[num].Destroy();
					}
				}
				if (!item.Filled(map))
				{
					FilthMaker.TryMakeFilth(item, map, ThingDefOf.Filth_Water);
				}
				Mote mote = MoteMaker.MakeStaticMote(item.ToVector3Shifted(), map, ThingDefOf.Mote_WaterskipSplashParticles);
				mote.rotationRate = Rand.Range(-30f, 30f);
				mote.exactRotation = 90 * Rand.RangeInclusive(0, 3);
				if (item != target.Cell)
				{
					MoteMaker.MakeStaticMote(item, parent.pawn.Map, ThingDefOf.Mote_PsycastSkipEffect);
				}
			}
		}
Beispiel #9
0
        private void CheckBulletFire(Mote mote)
        {
            if (mote == null)
            {
                return;
            }
            // Launch
            if (mote.def == ThingDefOf.Mote_ShotFlash)
            {
                float heat = mote.exactScale.x * 4f;
                if (this.flammableLinkcomp.TrySparksFly(heat) == SparksFlyResult.Undefine)
                {
                    MoteUtility.DrawHeatedMote(this.flammableLinkcomp.HeatRatio, base.DrawPos, base.Position, base.Map);
                }
#if DEBUG
                Log.Message("Mote_ShotFlash base:" + base.DrawPos + " heat:" + heat + " cap:" + this.flammableLinkcomp.AmountOfHeat);
#endif
            }

            // Impact
            if (mote.def == ThingDefOf.Mote_ShotHit_Dirt)
            {
                if (this.flammableLinkcomp.TrySparksFly(60f) == SparksFlyResult.Undefine)
                {
                    MoteUtility.DrawHeatedMote(this.flammableLinkcomp.HeatRatio, base.DrawPos, base.Position, base.Map);
                }
#if DEBUG
                Log.Message("Mote_ShotHit_Dirt base:" + base.DrawPos + " cap:" + this.flammableLinkcomp.AmountOfHeat);
#endif
            }
        }
Beispiel #10
0
        private void CheckBulletFire(Mote mote)
        {
            if (mote == null)
            {
                return;
            }

            // Launch
            if (mote.def.defName.Contains("ShotFlash"))
            {
                var heat = mote.exactScale.x * 4f;
                if (flammableLinkcomp.TrySparksFly(heat) == SparksFlyResult.Undefine)
                {
                    FleckUtility.DrawHeatedMote(flammableLinkcomp.HeatRatio, base.DrawPos, Position, Map);
                }
#if DEBUG
                Log.Message("Mote_ShotFlash base:" + base.DrawPos + " heat:" + heat + " cap:" + this.flammableLinkcomp.AmountOfHeat);
#endif
            }

            // Impact
            if (!mote.def.defName.Contains("ShotHit_Dirt"))
            {
                return;
            }

            if (flammableLinkcomp.TrySparksFly(60f) == SparksFlyResult.Undefine)
            {
                FleckUtility.DrawHeatedMote(flammableLinkcomp.HeatRatio, base.DrawPos, Position, Map);
            }
#if DEBUG
            Log.Message("Mote_ShotHit_Dirt base:" + base.DrawPos + " cap:" + this.flammableLinkcomp.AmountOfHeat);
#endif
        }
Beispiel #11
0
 public override void QueueCastingJob(LocalTargetInfo target, LocalTargetInfo destination)
 {
     base.QueueCastingJob(target, destination);
     if (moteCast == null || moteCast.Destroyed)
     {
         moteCast = MoteMaker.MakeAttachedOverlay(pawn, ThingDefOf.Mote_CastPsycast, MoteCastOffset, MoteCastScale, base.verb.verbProps.warmupTime - MoteCastFadeTime);
     }
 }
Beispiel #12
0
 protected void Emit()
 {
     mote = MoteMaker.MakeStaticMote(parent.DrawPos + Props.offset, parent.Map, Props.mote);
     if (!Props.soundOnEmission.NullOrUndefined())
     {
         Props.soundOnEmission.PlayOneShot(SoundInfo.InMap(parent));
     }
 }
 public static bool MoteSpawned(RealtimeMoteList __instance, Mote newMote)
 {
     lock (__instance)
     {
         __instance.allMotes.Add(newMote);
     }
     return(false);
 }
Beispiel #14
0
 public static void Postfix(Mote __instance, ref Vector3 __result)
 {
     if (DrawPos_Patch.ChangeDrawPos)
     {
         __result.z += DrawPos_Patch.zLevelOffset;
         __result.y += DrawPos_Patch.yLevelOffset;
     }
 }
 public static bool prefix(ref RealtimeMoteList __instance, Mote oldMote)
 {
     lock (locker)
     {
         __instance.allMotes.Remove(oldMote);
     }
     return(false);
 }
 public static bool prefix(ref RealtimeMoteList __instance, Mote newMote)
 {
     lock (locker)
     {
         __instance.allMotes.Add(newMote);
     }
     return(false);
 }
        public static Mote MakeStunOverlay(Thing stunnedThing)
        {
            Mote obj = (Mote)ThingMaker.MakeThing(ThingDefOf.Mote_Stun);

            obj.Attach(stunnedThing);
            GenSpawn.Spawn(obj, stunnedThing.Position, stunnedThing.Map);
            return(obj);
        }
        public static Mote MakeStunOverlay(Thing stunnedThing)
        {
            Mote mote = (Mote)ThingMaker.MakeThing(ThingDefOf.Mote_Stun, null);

            mote.Attach(stunnedThing);
            GenSpawn.Spawn(mote, stunnedThing.Position, stunnedThing.Map);
            return(mote);
        }
 public SavedJob(Job job)
 {
     def                            = job.def;
     targetA                        = job.targetA;
     targetB                        = job.targetB;
     targetC                        = job.targetC;
     targetQueueA                   = job.targetQueueA;
     targetQueueB                   = job.targetQueueB;
     count                          = job.count;
     countQueue                     = job.countQueue;
     startTick                      = job.startTick;
     expiryInterval                 = job.expiryInterval;
     checkOverrideOnExpire          = job.checkOverrideOnExpire;
     playerForced                   = job.playerForced;
     placedThings                   = job.placedThings;
     maxNumMeleeAttacks             = job.maxNumMeleeAttacks;
     maxNumStaticAttacks            = job.maxNumStaticAttacks;
     locomotionUrgency              = job.locomotionUrgency;
     haulMode                       = job.haulMode;
     bill                           = job.bill;
     commTarget                     = job.commTarget;
     plantDefToSow                  = job.plantDefToSow;
     verbToUse                      = job.verbToUse;
     haulOpportunisticDuplicates    = job.haulOpportunisticDuplicates;
     exitMapOnArrival               = job.exitMapOnArrival;
     failIfCantJoinOrCreateCaravan  = job.failIfCantJoinOrCreateCaravan;
     killIncappedTarget             = job.killIncappedTarget;
     ignoreForbidden                = job.ignoreForbidden;
     ignoreDesignations             = job.ignoreDesignations;
     canBash                        = job.canBash;
     canUseRangedWeapon             = job.canUseRangedWeapon;
     haulDroppedApparel             = job.haulDroppedApparel;
     restUntilHealed                = job.restUntilHealed;
     ignoreJoyTimeAssignment        = job.ignoreJoyTimeAssignment;
     doUntilGatheringEnded          = job.doUntilGatheringEnded;
     overeat                        = job.overeat;
     attackDoorIfTargetLost         = job.attackDoorIfTargetLost;
     takeExtraIngestibles           = job.takeExtraIngestibles;
     expireRequiresEnemiesNearby    = job.expireRequiresEnemiesNearby;
     lord                           = job.lord;
     collideWithPawns               = job.collideWithPawns;
     forceSleep                     = job.forceSleep;
     interaction                    = job.interaction;
     endIfCantShootTargetFromCurPos = job.endIfCantShootTargetFromCurPos;
     endIfCantShootInMelee          = job.endIfCantShootInMelee;
     checkEncumbrance               = job.checkEncumbrance;
     followRadius                   = job.followRadius;
     endAfterTendedOnce             = job.endAfterTendedOnce;
     quest                          = job.quest;
     mote                           = job.mote;
     reactingToMeleeThreat          = job.reactingToMeleeThreat;
     wasOnMeditationTimeAssignment  = job.wasOnMeditationTimeAssignment;
     psyfocusTargetLast             = job.psyfocusTargetLast;
     //jobGiverThinkTree = job.jobGiverThinkTree;
     //jobGiver = job.jobGiver;
     workGiverDef = job.workGiverDef;
     ability      = job.ability;
 }
        protected override IEnumerable <Toil> MakeNewToils()
        {
            if (!ModLister.RoyaltyInstalled)
            {
                Log.ErrorOnce("Bestowing cermonies are a Royalty-specific game system. If you want to use this code please check ModLister.RoyaltyInstalled before calling it. See rules on the Ludeon forum for more info.", 5464564);
                yield break;
            }
            AddFailCondition(() => Bestower.GetLord() == null || Bestower.GetLord().CurLordToil == null || !(Bestower.GetLord().CurLordToil is LordToil_BestowingCeremony_Wait));
            yield return(Toils_Goto.GotoCell(TargetIndex.B, PathEndMode.OnCell));

            Toil waitToil = Toils_General.Wait(471);

            waitToil.AddPreInitAction(delegate
            {
                Messages.Message("MessageBestowingCeremonyStarted".Translate(pawn.Named("PAWN")), Bestower, MessageTypeDefOf.PositiveEvent);
            });
            waitToil.AddPreInitAction(delegate
            {
                if (!AnalyzeThroneRoom(Bestower, pawn))
                {
                    Messages.Message("BestowingCeremonyThroneroomRequirementsNotSatisfied".Translate(pawn.Named("PAWN"), pawn.royalty.GetTitleAwardedWhenUpdating(Bestower.Faction, pawn.royalty.GetFavor(Bestower.Faction)).label.Named("TITLE")), pawn, MessageTypeDefOf.NegativeEvent);
                    ((LordJob_BestowingCeremony)Bestower.GetLord().LordJob).MakeCeremonyFail();
                }
            });
            waitToil.AddPreInitAction(delegate
            {
                SoundDefOf.Bestowing_Start.PlayOneShot(pawn);
            });
            waitToil.tickAction = delegate
            {
                pawn.rotationTracker.FaceTarget(Bestower);
                if (mote == null || mote.Destroyed)
                {
                    Vector3 loc = (pawn.TrueCenter() + Bestower.TrueCenter()) / 2f;
                    mote = MoteMaker.MakeStaticMote(loc, pawn.Map, ThingDefOf.Mote_Bestow);
                }
                mote.Maintain();
                if ((sound == null || sound.Ended) && waitToil.actor.jobs.curDriver.ticksLeftThisToil <= 307)
                {
                    sound = SoundDefOf.Bestowing_Warmup.TrySpawnSustainer(SoundInfo.InMap(new TargetInfo(pawn.Position, pawn.Map), MaintenanceType.PerTick));
                }
                if (sound != null)
                {
                    sound.Maintain();
                }
            };
            waitToil.handlingFacing = false;
            waitToil.socialMode     = RandomSocialMode.Off;
            waitToil.WithProgressBarToilDelay(TargetIndex.A);
            yield return(waitToil);

            yield return(Toils_General.Do(delegate
            {
                CeremonyJob.FinishCeremony(pawn);
                MoteMaker.MakeStaticMote((pawn.TrueCenter() + Bestower.TrueCenter()) / 2f, pawn.Map, ThingDefOf.Mote_PsycastAreaEffect, 2f);
                SoundDefOf.Bestowing_Finished.PlayOneShot(pawn);
            }));
        }
        // Token: 0x060022A7 RID: 8871 RVA: 0x00103CA4 File Offset: 0x001020A4
        public static void MakeMechFallMote(IntVec3 cell, Map map)
        {
            Mote mote = (Mote)ThingMaker.MakeThing(RimWorld.ThingDefOf.Mote_Bombardment, null);

            mote.exactPosition = cell.ToVector3Shifted();
            mote.Scale         = 5f;
            mote.rotationRate  = 0f;
            GenSpawn.Spawn(mote, cell, map);
        }
 public static void PlaceTempRoof(IntVec3 cell, Map map)
 {
     if (cell.ShouldSpawnMotesAt(map))
     {
         Mote mote = (Mote)ThingMaker.MakeThing(ThingDefOf.Mote_TempRoof, null);
         mote.exactPosition = cell.ToVector3Shifted();
         GenSpawn.Spawn(mote, cell, map);
     }
 }
        public static void MakePowerBeamMote(IntVec3 cell, Map map)
        {
            Mote mote = (Mote)ThingMaker.MakeThing(ThingDefOf.Mote_PowerBeam, null);

            mote.exactPosition = cell.ToVector3Shifted();
            mote.Scale         = 90f;
            mote.rotationRate  = 1.2f;
            GenSpawn.Spawn(mote, cell, map);
        }
        public static void MakeBombardmentMote(IntVec3 cell, Map map)
        {
            Mote mote = (Mote)ThingMaker.MakeThing(ThingDefOf.Mote_Bombardment, null);

            mote.exactPosition = cell.ToVector3Shifted();
            mote.Scale         = (float)((float)Mathf.Max(23, 25) * 6.0);
            mote.rotationRate  = 1.2f;
            GenSpawn.Spawn(mote, cell, map);
        }
Beispiel #25
0
        public static void MakeCustomPowerBeamMote(IntVec3 cell, Map map)
        {
            Mote mote = (Mote)ThingMaker.MakeThing(AADefOf.Mote_MeguminBeam_AA);

            mote.exactPosition = cell.ToVector3Shifted();
            mote.Scale         = 90f;
            mote.rotationRate  = 1.2f;
            GenSpawn.Spawn((Thing)mote, cell, map, WipeMode.Vanish);
        }
        public static void MakePowerBeamMote(IntVec3 cell, Map map)
        {
            Mote obj = (Mote)ThingMaker.MakeThing(ThingDefOf.Mote_PowerBeam);

            obj.exactPosition = cell.ToVector3Shifted();
            obj.Scale         = 90f;
            obj.rotationRate  = 1.2f;
            GenSpawn.Spawn(obj, cell, map);
        }
        public static void MakeBombardmentMote_NewTmp(IntVec3 cell, Map map, float scale)
        {
            Mote obj = (Mote)ThingMaker.MakeThing(ThingDefOf.Mote_Bombardment);

            obj.exactPosition = cell.ToVector3Shifted();
            obj.Scale         = 150f * scale;
            obj.rotationRate  = 1.2f;
            GenSpawn.Spawn(obj, cell, map);
        }
        private void DoMuzzleFlash(Vector3 pos)
        {
            Mote mote = (Mote)ThingMaker.MakeThing(AADefOf.Mote_LargeMuzzleFlash_AA, null);

            mote.Scale         = 2.6f;
            mote.exactRotation = base.CurrentRotation;
            mote.exactPosition = pos;
            GenSpawn.Spawn(mote, base.parentTurret.Position, base.parentTurret.Map, WipeMode.Vanish);
        }
Beispiel #29
0
        public static void MakeBombardmentMote(IntVec3 cell, Map map)
        {
            Mote obj = (Mote)ThingMaker.MakeThing(ThingDefOf.Mote_Bombardment);

            obj.exactPosition = cell.ToVector3Shifted();
            obj.Scale         = (float)Mathf.Max(23, 25) * 6f;
            obj.rotationRate  = 1.2f;
            GenSpawn.Spawn(obj, cell, map);
        }
 public static void MakeStaticMote(Vector3 loc, Map map, ThingDef moteDef, float scale = 1f)
 {
     if (loc.ShouldSpawnMotesAt(map) && !map.moteCounter.Saturated)
     {
         Mote mote = (Mote)ThingMaker.MakeThing(moteDef, null);
         mote.exactPosition = loc;
         mote.Scale         = scale;
         GenSpawn.Spawn(mote, loc.ToIntVec3(), map);
     }
 }
        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);
        }