private void TalkToDoll() { var symbol = InteractionDefOf.Chitchat.GetSymbol(); if (Rand.Value > 0.5f && pawn?.needs?.joy?.CurCategory <= JoyCategory.Low || (pawn?.story?.traits.HasTrait(TraitDefOf.Abrasive) ?? false)) { symbol = InteractionDefOf.Insult.GetSymbol(); } MoteMaker.MakeInteractionBubble(pawn, null, ThingDefOf.Mote_Speech, symbol); // float extraLuckFromQuality = base.TargetThingA.GetStatValue(StatDefOf.JoyGainFactor, true); // float extraLuckFromSmarts = pawn.skills.GetSkill(SkillDefOf.Intellectual).levelInt; // // float yourLuckyNumber = ((1f + extraLuckFromSmarts) * extraLuckFromQuality) / 100; // // Log.Message("lucky number is: " + yourLuckyNumber.ToString()); // // if (Rand.Chance(yourLuckyNumber) || DebugSettings.godMode) // { // Thing reward = ThingMaker.MakeThing(ThingDefOf.Gold); // reward.stackCount = Rand.RangeInclusive(10, 50); // GenSpawn.Spawn(reward, pawn.Position, pawn.Map); // PuzzleBox.Destroy(); // Letter letter = LetterMaker.MakeLetter("LotRD_PuzzleSolvedLabel".Translate(), "LotRD_PuzzleSolved".Translate(new object[] { // pawn.Label, // reward.Label, // }), LetterDefOf.PositiveEvent); // Find.LetterStack.ReceiveLetter(letter); // } }
private static void TryCreateBubble(Pawn pawn1, Pawn pawn2, Texture2D symbol) { if (pawn1.interactions.InteractedTooRecentlyToInteract()) { return; } MoteMaker.MakeInteractionBubble(pawn1, pawn2, ThingDefOf.Mote_Speech, symbol); }
protected Toil Interact(Pawn talkee, InteractionDef intDef, int duration) { var toil = new Toil { initAction = () => { PawnUtility.ForceWait(talkee, duration, pawn); TargetThingB = pawn; MoteMaker.MakeInteractionBubble(pawn, talkee, intDef.interactionMote, intDef.Symbol); }, socialMode = RandomSocialMode.Normal, defaultCompleteMode = ToilCompleteMode.Delay, defaultDuration = duration }; return(toil.WithProgressBarToilDelay(TargetIndex.B)); }
// Token: 0x06000016 RID: 22 RVA: 0x000023AC File Offset: 0x000005AC private Toil InteractToil() { return(Toils_General.Do(delegate { System.Random rnd = new System.Random(); int rand = rnd.Next(0, 2); bool flag = rand == 0; Pawn _p; if (flag) { _p = ((Building_Bell)this.pawn.mindState.duty.focus.Thing).fighter1.p; } else { _p = ((Building_Bell)this.pawn.mindState.duty.focus.Thing).fighter2.p; } RenderTexture head = PortraitsCache.Get(_p, ColonistBarColonistDrawer.PawnTextureSize, default(Vector3), 1f); Texture2D headIcon = new Texture2D(75, 75); for (int i = 0; i < 75; i++) { for (int j = 0; j < 75; j++) { headIcon.SetPixel(i, j, Color.clear); } } RenderTexture.active = head; headIcon.ReadPixels(new Rect(-10f, 0f, 50f, (float)head.height), 0, 0); headIcon.Apply(); Texture2D cheerIcon = InteractionDefOfArena.Cheer.Symbol; RenderTexture tmp = RenderTexture.GetTemporary(cheerIcon.width, cheerIcon.height, 0, RenderTextureFormat.Default, RenderTextureReadWrite.Default, 1); Graphics.Blit(cheerIcon, tmp); RenderTexture previous = RenderTexture.active; RenderTexture.active = tmp; Texture2D _cheerIcon = new Texture2D(cheerIcon.width, cheerIcon.height); _cheerIcon.ReadPixels(new Rect(0f, 0f, (float)tmp.width, (float)tmp.height), 0, 0); _cheerIcon.Apply(); RenderTexture.active = previous; RenderTexture.ReleaseTemporary(tmp); Texture2D merged = JobDriver_CheerForFighter.MergeTextures(_cheerIcon, headIcon); MoteMaker.MakeInteractionBubble(this.pawn, null, ThingDefOf.Mote_Speech, merged); })); }
public static void TryWorshipInteraction(Pawn preacher, Pawn recipient, InteractionDef intDef) { if (preacher == recipient) { Log.Warning(preacher + " tried to interact with self, interaction=" + intDef.defName); return; } //if (!tracker.CanInteractNowWith(recipient)) // return false; var extraSentencePacks = new List <RulePackDef>(); //if (intDef.initiatorThought != null) // Pawn_InteractionsTracker.AddInteractionThought(preacher, recipient, intDef.initiatorThought); //if (intDef.recipientThought != null && recipient.needs.mood != null) // Pawn_InteractionsTracker.AddInteractionThought(recipient, preacher, intDef.recipientThought); //if (intDef.initiatorXpGainSkill != null) // preacher.skills.Learn(intDef.initiatorXpGainSkill, (float)intDef.initiatorXpGainAmount, false); //if (intDef.recipientXpGainSkill != null && recipient.RaceProps.Humanlike) // recipient.skills.Learn(intDef.recipientXpGainSkill, (float)intDef.recipientXpGainAmount, false); var flag = false; if (recipient.RaceProps.Humanlike) { flag = recipient.interactions.CheckSocialFightStart(intDef, preacher); } if (!flag) { intDef.Worker.Interacted(preacher, recipient, extraSentencePacks, out _, out _, out _, out _); } MoteMaker.MakeInteractionBubble(preacher, recipient, intDef.interactionMote, intDef.Symbol); if (flag) { extraSentencePacks.Add(RulePackDefOf.Sentence_SocialFightStarted); } var entryInteraction = new PlayLogEntry_Interaction(intDef, preacher, recipient, extraSentencePacks); Find.PlayLog.Add(entryInteraction); }
private void DoEffect() { BloodVictim.TransferBloodTo(1, BloodFeeder, false); if (!Victim.InAggroMentalState) { Victim.mindState.mentalStateHandler.TryStartMentalState(MentalStateDefOf.Berserk, "ROMV_AttemptedDiablerie".Translate(this.pawn.Named("PAWN")), false, false, null); } if (DiablerieInteractionGiven) { return; } DiablerieInteractionGiven = true; Find.LetterStack.ReceiveLetter("ROMV_AttemptedDiablerie".Translate(this.pawn.Named("PAWN")), "ROMV_VampireDiablerieAttemptedLetter".Translate(this.pawn.Named("PAWN"), Victim.Named("VICTIM")), LetterDefOf.ThreatSmall, pawn); MoteMaker.MakeInteractionBubble(GetActor(), Victim, VampDefOf.ROMV_VampireDiablerieAttempt.interactionMote, VampDefOf.ROMV_VampireDiablerieAttempt.Symbol); if (this?.Victim?.needs?.mood?.thoughts?.memories is MemoryThoughtHandler m) { m.TryGainMemory(VampDefOf.ROMV_VampireDiablerieAttempt.recipientThought, GetActor()); } Find.PlayLog.Add(new PlayLogEntry_Interaction(VampDefOf.ROMV_VampireDiablerieAttempt, this.GetActor(), this.Victim, null)); }
public override void Tick() { base.Tick(); if (this.realPawn == null) { this.realPawn = this.pawn as PsychologyPawn; } if (this.otherPawn == null) { this.pawn.health.RemoveHediff(this); return; } if (!this.otherPawn.Spawned || !this.pawn.Spawned || !InteractionUtility.CanReceiveInteraction(this.pawn) || !InteractionUtility.CanReceiveInteraction(this.otherPawn)) { this.pawn.health.RemoveHediff(this); return; } if ((this.pawn.Position - this.otherPawn.Position).LengthHorizontalSquared >= 54f || !GenSight.LineOfSight(this.pawn.Position, this.otherPawn.Position, this.pawn.Map, true)) { this.pawn.health.RemoveHediff(this); return; } if (this.otherPawn.Dead || this.otherPawn.Downed || this.otherPawn.InAggroMentalState) { this.pawn.health.RemoveHediff(this); return; } if (this.pawn.IsHashIntervalTick(200)) { if (Rand.Value > 1f - (this.ageTicks / 400000f)) { this.pawn.health.RemoveHediff(this); return; } else if (Rand.Value < 0.2f && this.pawn.Map != null) { MoteMaker.MakeInteractionBubble(this.pawn, otherPawn, InteractionDefOf.DeepTalk.interactionMote, InteractionDefOf.DeepTalk.Symbol); } } }
private void DoEffect() { BloodVictim.TransferBloodTo(1, BloodFeeder, false); if (!Victim.InAggroMentalState) { Victim.mindState.mentalStateHandler.TryStartMentalState(MentalStateDefOf.Berserk, "ROMV_AttemptedDiablerie".Translate(this.pawn), false, false, null); // Victim.mindState.mentalStateHandler.TryStartMentalState(VampDefOf.MurderousRage, // "ROMV_AttemptedDiablerie".Translate(), false, false, GetActor()); } if (DiablerieInteractionGiven) { return; } DiablerieInteractionGiven = true; MoteMaker.MakeInteractionBubble(GetActor(), Victim, VampDefOf.ROMV_VampireDiablerieAttempt.interactionMote, VampDefOf.ROMV_VampireDiablerieAttempt.Symbol); if (this?.Victim?.needs?.mood?.thoughts?.memories is MemoryThoughtHandler m) { m.TryGainMemory(VampDefOf.ROMV_VampireDiablerieAttempt.recipientThought, GetActor()); } Find.PlayLog.Add(new PlayLogEntry_Interaction(VampDefOf.ROMV_VampireDiablerieAttempt, this.GetActor(), this.Victim, null)); }
public override void LordToilTick() { base.LordToilTick(); LordJob_VisitMayor meeting = this.lord.LordJob as LordJob_VisitMayor; for (int i = 0; i < this.lord.ownedPawns.Count; i++) { if (this.lord.ownedPawns[i].Position == null || this.spot == null || this.lord.ownedPawns[i].Map == null || !PartyUtility.InPartyArea(this.lord.ownedPawns[i].Position, this.spot, this.lord.ownedPawns[i].Map)) { return; } } if (meeting != null) { meeting.ticksInSameRoom += 1; if (meeting.ticksInSameRoom % 200 == 0 && Rand.Value < 0.2f) { meeting.mayor.skills.Learn(SkillDefOf.Social, 0.5f); MoteMaker.MakeInteractionBubble(meeting.constituent, meeting.mayor, InteractionDefOf.DeepTalk.interactionMote, InteractionDefOf.DeepTalk.Symbol); } } }
public override void PostRemoved() { base.PostRemoved(); if (this.realPawn == null) { this.realPawn = this.pawn as PsychologyPawn; } if (this.realPawn != null && this.otherPawn != null) { Hediff otherConvo = otherPawn.health.hediffSet.hediffs.Find(h => h is Hediff_Conversation && ((Hediff_Conversation)h).otherPawn == this.realPawn); if (otherConvo != null) { this.otherPawn.health.RemoveHediff(otherConvo); } string talkDesc; if (this.ageTicks < 500) { int numShortTalks = int.Parse("NumberOfShortTalks".Translate()); talkDesc = "ShortTalk" + Rand.RangeInclusive(1, numShortTalks); } else if (this.ageTicks < 1500) { int numNormalTalks = int.Parse("NumberOfNormalTalks".Translate()); talkDesc = "NormalTalk" + Rand.RangeInclusive(1, numNormalTalks); } else if (this.ageTicks < 5000) { int numLongTalks = int.Parse("NumberOfLongTalks".Translate()); talkDesc = "LongTalk" + Rand.RangeInclusive(1, numLongTalks); } else { int numEpicTalks = int.Parse("NumberOfEpicTalks".Translate()); talkDesc = "EpicTalk" + Rand.RangeInclusive(1, numEpicTalks); } //We create a dynamic def to hold this thought so that the game won't worry about it being used anywhere else. ThoughtDef def = new ThoughtDef(); def.defName = this.pawn.GetHashCode() + "Conversation" + topic.defName; def.label = topic.defName; def.durationDays = 60f; def.nullifyingTraits = new List <TraitDef>(); def.nullifyingTraits.Add(TraitDefOf.Psychopath); def.thoughtClass = typeof(Thought_MemorySocialDynamic); ThoughtStage stage = new ThoughtStage(); //Base opinion mod is 5 to the power of controversiality. float opinionMod = Mathf.Pow(5f, topic.controversiality); //Multiplied by difference between their personality ratings, on an exponential scale. opinionMod *= Mathf.Lerp(-1.25f, 1.25f, Mathf.Pow(1f - Mathf.Abs(this.realPawn.psyche.GetPersonalityRating(topic) - this.otherPawn.psyche.GetPersonalityRating(topic)), 3)); //Cool pawns are liked more. opinionMod += Mathf.Pow(2f, topic.controversiality) * (0.5f - this.otherPawn.psyche.GetPersonalityRating(PersonalityNodeDefOf.Cool)); //The length of the talk has a large impact on how much the pawn cares. opinionMod *= 5f * (this.ageTicks / (GenDate.TicksPerHour * 2.25f)); //talkModifier[talkLength] //If they had a bad experience, the more polite the pawn is, the less they're bothered by it. opinionMod *= (opinionMod < 0f ? 0.5f + (1f - this.otherPawn.psyche.GetPersonalityRating(PersonalityNodeDefOf.Polite)) : 1f); //The more judgmental the pawn, the more they're affected by all conversations. opinionMod *= 0.5f + this.realPawn.psyche.GetPersonalityRating(PersonalityNodeDefOf.Judgmental); if (opinionMod < 0f) { opinionMod *= PopulationModifier; } stage.label = "ConversationStage".Translate() + " " + topic.conversationTopic; stage.baseOpinionOffset = Mathf.RoundToInt(opinionMod); def.stages.Add(stage); /* The more they know about someone, the less likely small thoughts are to have an impact on their opinion. * This helps declutter the Social card without preventing pawns from having conversations. * They just won't change their mind about the colonist as a result. */ if (Rand.Value < Mathf.InverseLerp(0f, this.realPawn.psyche.TotalThoughtOpinion(this.otherPawn), 250f + Mathf.Abs(stage.baseOpinionOffset)) && stage.baseOpinionOffset != 0) { this.pawn.needs.mood.thoughts.memories.TryGainMemory(def, this.otherPawn); } if (this.waveGoodbye && this.pawn.Map != null) { InteractionDef endConversation = new InteractionDef(); endConversation.defName = "EndConversation"; RulePack goodbyeText = new RulePack(); FieldInfo RuleStrings = typeof(RulePack).GetField("rulesStrings", BindingFlags.Instance | BindingFlags.NonPublic); List <string> text = new List <string>(1); text.Add("logentry->" + talkDesc.Translate(topic.conversationTopic)); RuleStrings.SetValue(goodbyeText, text); endConversation.logRulesInitiator = goodbyeText; endConversation.logRulesRecipient = goodbyeText; FieldInfo Symbol = typeof(InteractionDef).GetField("symbol", BindingFlags.Instance | BindingFlags.NonPublic); Symbol.SetValue(endConversation, Symbol.GetValue(InteractionDefOf.DeepTalk)); PlayLogEntry_InteractionConversation log = new PlayLogEntry_InteractionConversation(endConversation, realPawn, this.otherPawn, new List <RulePackDef>()); Find.PlayLog.Add(log); MoteMaker.MakeInteractionBubble(this.pawn, this.otherPawn, InteractionDefOf.Chitchat.interactionMote, InteractionDefOf.Chitchat.Symbol); } } }
protected override IEnumerable <Toil> MakeNewToils() { //Commence fail checks! this.FailOnDestroyedOrNull(TargetIndex.A); this.FailOnDestroyedOrNull(TargetIndex.B); this.FailOnAggroMentalState(TargetIndex.A); yield return(Toils_Reserve.Reserve(TakeeIndex)); yield return(Toils_Reserve.Reserve(AltarIndex, Building_SacrificialAltar.LyingSlotsCount)); yield return(new Toil { initAction = delegate { DropAltar.ChangeState(Building_SacrificialAltar.State.sacrificing, Building_SacrificialAltar.SacrificeState.gathering); } }); //Toil 1: Go to prisoner. yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch) .FailOnDespawnedNullOrForbidden(TargetIndex.A).FailOnDespawnedNullOrForbidden(TargetIndex.B) .FailOn(() => job.def == JobDefOf.Arrest && !Takee.CanBeArrestedBy(pawn)) .FailOn(() => !pawn.CanReach(DropAltar, PathEndMode.OnCell, Danger.Deadly)) .FailOnSomeonePhysicallyInteracting(TargetIndex.A)); yield return(new Toil { initAction = delegate { if (!job.def.makeTargetPrisoner) { return; } var targetAThing = (Pawn)job.targetA.Thing; var lord = targetAThing.GetLord(); lord?.Notify_PawnAttemptArrested(targetAThing); GenClamor.DoClamor(targetAThing, 10f, ClamorDefOf.Harm); if (job.def == JobDefOf.Arrest && !targetAThing.CheckAcceptArrest(pawn)) { pawn.jobs.EndCurrentJob(JobCondition.Incompletable); } } }); //Toil 2: Carry prisoner. yield return(Toils_Haul.StartCarryThing(TargetIndex.A)); //Toil 3: Go to the altar. yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.InteractionCell)); //Toil 4: Release the prisoner. yield return(Toils_Reserve.Release(TargetIndex.B)); //Toil 5: Restrain the prisoner. yield return(new Toil { initAction = delegate { //In-case this fails... var position = DropAltar.Position; pawn.carryTracker.TryDropCarriedThing(position, ThingPlaceMode.Direct, out _); if (DropAltar.Destroyed || !DropAltar.AnyUnoccupiedLyingSlot) { return; } Takee.Position = DropAltar.GetLyingSlotPos(); Takee.Notify_Teleported(false); Takee.stances.CancelBusyStanceHard(); var newJob = new Job(CultsDefOf.Cults_WaitTiedDown, DropAltar); Takee.jobs.StartJob(newJob); }, defaultCompleteMode = ToilCompleteMode.Instant }); //Toil 6: Time to chant ominously var chantingTime = new Toil { defaultCompleteMode = ToilCompleteMode.Delay, defaultDuration = CultUtility.ritualDuration }; chantingTime.WithProgressBarToilDelay(TargetIndex.A); chantingTime.PlaySustainerOrSound(CultsDefOf.RitualChanting); var deitySymbol = ((CosmicEntityDef)DropAltar.SacrificeData.Entity.def).Symbol; chantingTime.initAction = delegate { if (deitySymbol != null) { MoteMaker.MakeInteractionBubble(pawn, null, ThingDefOf.Mote_Speech, deitySymbol); } //STATE - SACRIFICING DropAltar.ChangeState(Building_SacrificialAltar.State.sacrificing, Building_SacrificialAltar.SacrificeState.sacrificing); }; yield return(chantingTime); //Toil 8: Execution of Prisoner yield return(new Toil { initAction = delegate { //BodyPartDamageInfo value = new BodyPartDamageInfo(this.Takee.health.hediffSet.GetBrain(), false, quiet); Takee.TakeDamage(new DamageInfo(DamageDefOf.ExecutionCut, 99999, 0f, -1f, pawn, Utility.GetHeart(Takee.health.hediffSet))); if (!Takee.Dead) { Takee.Kill(null); } //ThoughtUtility.GiveThoughtsForPawnExecuted(this.Takee, PawnExecutionKind.GenericHumane); TaleRecorder.RecordTale(TaleDefOf.ExecutedPrisoner, pawn, Takee); CultUtility.SacrificeExecutionComplete(DropAltar); }, defaultCompleteMode = ToilCompleteMode.Instant }); AddFinishAction(() => { //It's a day to remember var taleToAdd = TaleDef.Named("HeldSermon"); if ((pawn.IsColonist || pawn.IsSlaveOfColony || pawn.HostFaction == Faction.OfPlayer) && taleToAdd != null) { TaleRecorder.RecordTale(taleToAdd, pawn); } //When the ritual is finished -- then let's give the thoughts /* * if (DropAltar.currentSacrificeState == Building_SacrificialAltar.SacrificeState.finished) * { * if (this.pawn == null) return; * if (DropAltar.sacrifice != null) * { * CultUtility.AttendSacrificeTickCheckEnd(this.pawn, DropAltar.sacrifice, true); * } * else * { * CultUtility.AttendSacrificeTickCheckEnd(this.pawn, null); * } * } */ }); }
private void Finished() { if (PsycheHelper.PsychologyEnabled(mayor) && PsycheHelper.PsychologyEnabled(constituent)) { if (this.ticksInSameRoom > 0) { if (this.complaint) { ThoughtDef complaintDef = new ThoughtDef(); complaintDef.label = "MayorComplaint"; complaintDef.durationDays = 1f + 4f * this.mayor.GetStatValue(StatDefOf.SocialImpact); //Constituent thought duration affected by mayor's Social stat complaintDef.thoughtClass = typeof(Thought_MemoryDynamic); complaintDef.stackedEffectMultiplier = 1f; complaintDef.stackLimit = 999; ThoughtStage complaintStage = new ThoughtStage(); float complaintMood = 18f * (PsycheHelper.Comp(mayor).Psyche.GetPersonalityRating(PersonalityNodeDefOf.Empathetic) - 0.33f); //Base complaint mood determined by mayor's Empathetic trait complaintMood *= (float)this.ticksInSameRoom / (float)GenDate.TicksPerHour; //Length of meeting also affects mood complaintMood *= (complaintMood < 0f ? Mathf.Lerp(1.25f, 0.75f, PsycheHelper.Comp(constituent).Psyche.GetPersonalityRating(PersonalityNodeDefOf.Polite)) : 1f); //Negative meeting thoughts (unempathetic mayors) mitigated by mayor's politeness complaintMood += (BeautyUtility.AverageBeautyPerceptible(this.constituent.Position, this.constituent.Map) / 10f); //Beauty of the room has a net positive effect on the thought complaintMood *= 0.75f + (PsycheHelper.Comp(constituent).Psyche.GetPersonalityRating(PersonalityNodeDefOf.Judgmental) / 2f); //Constituent's Judgmental trait changes how much the thought affects them complaintStage.label = "ComplaintLabel".Translate(); complaintStage.description = "ComplaintDesc".Translate(); complaintStage.baseMoodEffect = Mathf.RoundToInt(complaintMood); complaintDef.defName = this.constituent.GetHashCode() + "MayorComplaint" + complaintStage.baseMoodEffect; complaintDef.stages.Add(complaintStage); if (complaintStage.baseMoodEffect != 0) { this.constituent.needs.mood.thoughts.memories.TryGainMemory(complaintDef, this.mayor); } } ThoughtDef visitDef = new ThoughtDef(); visitDef.label = "MayorVisited"; visitDef.durationDays = 0.75f + 2f * (1f - PsycheHelper.Comp(mayor).Psyche.GetPersonalityRating(PersonalityNodeDefOf.Independent)); //Mayor thought duration affected by mayor's Independent trait visitDef.thoughtClass = typeof(Thought_MemoryDynamic); visitDef.stackedEffectMultiplier = 1f; visitDef.stackLimit = 999; ThoughtStage stage = new ThoughtStage(); float mood = 7f * (complaint ? -0.5f - (1f - this.constituent.needs.mood.CurLevel) : 0.1f + (this.constituent.needs.mood.CurLevel * 0.65f)); //Base visit mood determined by the mood level of the constituent mood *= (float)this.ticksInSameRoom / (float)GenDate.TicksPerHour; //Length of meeting also affects mood mood *= (mood < 0f ? Mathf.Lerp(1.25f, 0.75f, PsycheHelper.Comp(constituent).Psyche.GetPersonalityRating(PersonalityNodeDefOf.Polite)) : 1f); //Negative meeting thoughts (unhappy constituents) mitigated by constituent's politeness mood *= 0.5f + (1f - PsycheHelper.Comp(this.mayor).Psyche.GetPersonalityRating(PersonalityNodeDefOf.LaidBack)); //Mayor's Laid-Back trait strongly impacts how much the thought affects them stage.label = "VisitLabel".Translate(); stage.description = "VisitDesc".Translate(); stage.baseMoodEffect = Mathf.RoundToInt(mood); visitDef.defName = this.mayor.GetHashCode() + "MayorVisited" + stage.baseMoodEffect; visitDef.stages.Add(stage); if (stage.baseMoodEffect != 0) { this.mayor.needs.mood.thoughts.memories.TryGainMemory(visitDef, this.constituent); } InteractionDef endConversation = new InteractionDef(); endConversation.defName = "EndConversation"; FieldInfo RuleStrings = typeof(RulePack).GetField("rulesStrings", BindingFlags.Instance | BindingFlags.NonPublic); RulePack goodbyeTextInit = new RulePack(); List <string> text = new List <string>(1); if (complaint) { text.Add("r_logentry->" + "Complained".Translate()); } else { text.Add("r_logentry->" + "Supported".Translate()); } RuleStrings.SetValue(goodbyeTextInit, text); endConversation.logRulesInitiator = goodbyeTextInit; FieldInfo Symbol = typeof(InteractionDef).GetField("symbol", BindingFlags.Instance | BindingFlags.NonPublic); Symbol.SetValue(endConversation, Symbol.GetValue(InteractionDefOfPsychology.HangOut)); PlayLogEntry_InteractionConversation log = new PlayLogEntry_InteractionConversation(endConversation, this.constituent, this.mayor, new List <RulePackDef>()); Find.PlayLog.Add(log); MoteMaker.MakeInteractionBubble(this.mayor, this.constituent, InteractionDefOf.Chitchat.interactionMote, InteractionDefOf.Chitchat.Symbol); } } }
public static string InteractWith(Pawn pawn, Pawn recipient, InteractionDef interaction) { if (pawn == recipient) { return(null); } var extraSentencePacks = new List <RulePackDef>(); if (interaction.initiatorThought != null) { Pawn_InteractionsTracker.AddInteractionThought(pawn, recipient, interaction.initiatorThought); } if (interaction.recipientThought != null && recipient.needs.mood != null) { Pawn_InteractionsTracker.AddInteractionThought(recipient, pawn, interaction.recipientThought); } bool isSocialFight = recipient.RaceProps.Humanlike && recipient.interactions.CheckSocialFightStart(interaction, pawn); string letterText = null; string letterLabel = null; LetterDef letterDef = null; LookTargets lookTargets = null; if (!isSocialFight) { interaction.Worker.Interacted(pawn, recipient, extraSentencePacks, out letterText, out letterLabel, out letterDef, out lookTargets); } MoteMaker.MakeInteractionBubble( pawn, recipient, interaction.interactionMote, interaction.GetSymbol(pawn.Faction, pawn.Ideo), interaction.GetSymbolColor(pawn.Faction) ); if (isSocialFight) { extraSentencePacks.Add(RulePackDefOf.Sentence_SocialFightStarted); } var entry = new PlayLogEntry_Interaction(interaction, pawn, recipient, extraSentencePacks); Find.PlayLog.Add(entry); string text = RichTextHelper.StripTags(entry.ToGameStringFromPOV(pawn)); if (letterDef == null) { return(MakeFirstPerson(pawn.LabelShort, text)); } if (!letterText.NullOrEmpty()) { text = text + "\n\n" + RichTextHelper.StripTags(letterText); } Find.LetterStack.ReceiveLetter(letterLabel, text, letterDef, lookTargets ?? pawn); return(MakeFirstPerson(pawn.LabelShort, text.Replace("\n\n", " "))); }
public override void PostRemoved() { base.PostRemoved(); if (this.pawn != null && this.otherPawn != null) { if (this.pawn.Dead || this.otherPawn.Dead || !PsycheHelper.PsychologyEnabled(pawn) || !PsycheHelper.PsychologyEnabled(otherPawn)) { return; } Hediff_Conversation otherConvo = otherPawn.health.hediffSet.hediffs.Find(h => h is Hediff_Conversation && ((Hediff_Conversation)h).otherPawn == this.pawn) as Hediff_Conversation; if (otherConvo != null) { this.otherPawn.health.RemoveHediff(otherConvo); this.startedFight = otherConvo.startedFight; } string talkDesc; if (this.ageTicks < 500) { int numShortTalks = int.Parse("NumberOfShortTalks".Translate()); talkDesc = "ShortTalk" + Rand.RangeInclusive(1, numShortTalks); } else if (this.ageTicks < GenDate.TicksPerHour / 2) { int numNormalTalks = int.Parse("NumberOfNormalTalks".Translate()); talkDesc = "NormalTalk" + Rand.RangeInclusive(1, numNormalTalks); } else if (this.ageTicks < GenDate.TicksPerHour * 2.5) { int numLongTalks = int.Parse("NumberOfLongTalks".Translate()); talkDesc = "LongTalk" + Rand.RangeInclusive(1, numLongTalks); } else { int numEpicTalks = int.Parse("NumberOfEpicTalks".Translate()); talkDesc = "EpicTalk" + Rand.RangeInclusive(1, numEpicTalks); } float opinionMod; ThoughtDef def = CreateSocialThought(out opinionMod); bool mattered = TryGainThought(def, Mathf.RoundToInt(opinionMod)); InteractionDef endConversation = new InteractionDef(); endConversation.socialFightBaseChance = 0.2f * PsycheHelper.Comp(pawn).Psyche.GetPersonalityRating(PersonalityNodeDefOf.Aggressive) * PopulationModifier * Mathf.InverseLerp(0f, -80f, opinionMod); endConversation.defName = "EndConversation"; endConversation.label = def.label; List <RulePackDef> socialFightPacks = new List <RulePackDef>(); if (otherConvo != null && (startedFight || (mattered && this.pawn.interactions.CheckSocialFightStart(endConversation, otherPawn)))) { if (startedFight) { socialFightPacks.Add(RulePackDefOfPsychology.Sentence_SocialFightConvoRecipientStarted); } else { socialFightPacks.Add(RulePackDefOfPsychology.Sentence_SocialFightConvoInitiatorStarted); } this.startedFight = true; if (!this.waveGoodbye && otherConvo.convoLog != null && !otherConvo.startedFight) { //The main conversation hediff was the other conversation, and didn't start a fight, so we have to add the extra sentence in after the fact. Traverse.Create(otherConvo.convoLog).Field("extraSentencePacks").GetValue <List <RulePackDef> >().AddRange(socialFightPacks); } } if (this.waveGoodbye && this.pawn.Map != null) { RulePack goodbyeText = new RulePack(); FieldInfo RuleStrings = typeof(RulePack).GetField("rulesStrings", BindingFlags.Instance | BindingFlags.NonPublic); List <string> text = new List <string>(1); text.Add("r_logentry->" + talkDesc.Translate(convoTopic, pawn.Named("INITIATOR"), otherPawn.Named("RECIPIENT"))); RuleStrings.SetValue(goodbyeText, text); endConversation.logRulesInitiator = goodbyeText; FieldInfo Symbol = typeof(InteractionDef).GetField("symbol", BindingFlags.Instance | BindingFlags.NonPublic); Symbol.SetValue(endConversation, Symbol.GetValue(InteractionDefOfPsychology.EndConversation)); PlayLogEntry_InteractionConversation log = new PlayLogEntry_InteractionConversation(endConversation, pawn, this.otherPawn, socialFightPacks); Find.PlayLog.Add(log); convoLog = log; MoteMaker.MakeInteractionBubble(this.pawn, this.otherPawn, InteractionDefOf.Chitchat.interactionMote, InteractionDefOf.Chitchat.Symbol); } } }
public override void Tick() { base.Tick(); if (this.otherPawn == null) { this.pawn.health.RemoveHediff(this); return; } if (!this.otherPawn.Spawned || !this.pawn.Spawned || !InteractionUtility.CanReceiveInteraction(this.pawn) || !InteractionUtility.CanReceiveInteraction(this.otherPawn)) { this.pawn.health.RemoveHediff(this); return; } if (this.pawn.Map != null && this.otherPawn.Map != null && ((this.pawn.Position - this.otherPawn.Position).LengthHorizontalSquared >= 54f || !GenSight.LineOfSight(this.pawn.Position, this.otherPawn.Position, this.pawn.Map, true))) { this.pawn.health.RemoveHediff(this); return; } if (this.otherPawn.Dead || this.otherPawn.Downed || this.otherPawn.InAggroMentalState) { this.pawn.health.RemoveHediff(this); return; } if (this.pawn.IsHashIntervalTick(200)) { /* When a conversation first starts, the mean time for it to last is 3 hours. * When it reaches half an hour, the mean time for it to continue is 2 hours. * When it reaches an hour, the mean time for it to continue is 1 hour. * When it surpasses 2 hours, it will on average last for half an hour more. * Conversations will thus usually not surpass 2 hours, and very rarely surpass 2 and a half hours, but are very likely to last up to an hour. */ float mtb = 3f; if (this.ageTicks > GenDate.TicksPerHour * 2) { mtb = 0.5f; } else if (this.ageTicks > GenDate.TicksPerHour) { mtb = 1f; } else if (this.ageTicks > (GenDate.TicksPerHour / 2)) { mtb = 2f; } if (pawn.story.traits.HasTrait(TraitDefOfPsychology.Chatty)) { mtb *= 2f; } if (this.otherPawn.story.traits.HasTrait(TraitDefOfPsychology.Chatty)) { mtb *= 2f; } if (Rand.MTBEventOccurs(mtb, GenDate.TicksPerHour, 200)) { this.pawn.health.RemoveHediff(this); return; } else if (Rand.Value < 0.2f && this.pawn.Map != null) { MoteMaker.MakeInteractionBubble(this.pawn, otherPawn, InteractionDefOfPsychology.EndConversation.interactionMote, InteractionDefOfPsychology.EndConversation.Symbol); } } }
protected override IEnumerable <Toil> MakeNewToils() { this.FailOnDestroyedOrNull(TargetIndex.A); yield return(Toils_Reserve.Reserve(SpotIndex, 1, -1, null)); yield return(new Toil { initAction = delegate { Spot.ChangeState(Building_TeachingSpot.State.lesson, Building_TeachingSpot.LessonState.gathering); } }); yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell)); Toil waitingTime = new Toil(); waitingTime.defaultCompleteMode = ToilCompleteMode.Delay; TeachingUtility.remainingDuration = TeachingUtility.ritualDuration; waitingTime.defaultDuration = TeachingUtility.remainingDuration - 360; waitingTime.initAction = delegate { // Spot.lastLessonTick = Find.TickManager.TicksGame; // HediffLeader hediff = TeachingUtility.leaderH(this.pawn); //if (hediff != null) hediff.lastLessonTick = Find.TickManager.TicksGame; report = "WaitingDesc".Translate(); MoteMaker.MakeInteractionBubble(this.pawn, null, ThingDefOf.Mote_Speech, ModTextures.waiting); Spot.ChangeState(Building_TeachingSpot.State.lesson, Building_TeachingSpot.LessonState.teaching); List <Thing> list = GenRadial.RadialDistinctThingsAround(this.pawn.Position, this.pawn.Map, 10f, true).ToList <Thing>(); foreach (Thing current in list) { Building_Chalkboard chalk = current as Building_Chalkboard; bool flag2 = chalk != null; if (flag2) { if (current.def.defName == "ChalkboardCL" && current.Faction == this.pawn.Faction) { if (current.GetRoom() == this.pawn.GetRoom()) { string s = TeachingUtility.getLeaderType(this.pawn); chalkboards.Add(chalk); chalk.frame = -1; this.Map.mapDrawer.MapMeshDirty(chalk.Position, MapMeshFlag.Things, true, false); } } } } }; yield return(waitingTime); for (int i = 0; i < 3; i++) { Toil teachingTime = new Toil(); teachingTime.defaultCompleteMode = ToilCompleteMode.Delay; TeachingUtility.remainingDuration = TeachingUtility.ritualDuration; teachingTime.defaultDuration = TeachingUtility.remainingDuration - 120; teachingTime.initAction = delegate { string s = TeachingUtility.getLeaderType(this.pawn); foreach (Building_Chalkboard chalk in chalkboards) { if (chalk != null) { if (s == "leader1") { chalk.state = 1; } else if (s == "leader2") { chalk.state = 2; } else if (s == "leader3") { chalk.state = 3; } else if (s == "leader4") { chalk.state = 4; } chalk.frame++; this.Map.mapDrawer.MapMeshDirty(chalk.Position, MapMeshFlag.Things, true, false); } } report = "TeachingDesc".Translate(); MoteMaker.MakeInteractionBubble(this.pawn, null, ThingDefOf.Mote_Speech, iconList(this.pawn).RandomElement()); }; teachingTime.tickAction = delegate { Pawn actor = this.pawn; actor.skills.Learn(SkillDefOf.Social, 0.25f); actor.GainComfortFromCellIfPossible(); }; yield return(teachingTime); } Toil finishingTime = new Toil(); finishingTime.defaultCompleteMode = ToilCompleteMode.Delay; TeachingUtility.remainingDuration = TeachingUtility.ritualDuration; finishingTime.defaultDuration = TeachingUtility.remainingDuration - 360; finishingTime.WithProgressBarToilDelay(TargetIndex.A, false, -0.5f); finishingTime.initAction = delegate { report = "FinishLessonDesc".Translate(); MoteMaker.MakeInteractionBubble(this.pawn, null, ThingDefOf.Mote_Speech, iconList(this.pawn).RandomElement()); }; finishingTime.tickAction = delegate { if (tickC == 120 || tickC == 240 || tickC == 360) { foreach (Building_Chalkboard chalk in chalkboards) { if (chalk != null) { if (chalk.frame > -1) { chalk.frame--; } this.Map.mapDrawer.MapMeshDirty(chalk.Position, MapMeshFlag.Things, true, false); } } } Pawn actor = this.pawn; actor.skills.Learn(SkillDefOf.Social, 0.25f); actor.GainComfortFromCellIfPossible(); tickC++; }; yield return(finishingTime); yield return(new Toil { initAction = delegate { tickC = 0; TeachingUtility.TeachingComplete(this.pawn, Spot); }, defaultCompleteMode = ToilCompleteMode.Instant }); yield return(new Toil { initAction = delegate { if (Spot != null) { if (Spot.currentLessonState != Building_TeachingSpot.LessonState.finished) { Spot.ChangeState(Building_TeachingSpot.State.lesson, Building_TeachingSpot.LessonState.finished); //Map.GetComponent<MapComponent_SacrificeTracker>().ClearVariables(); } } }, defaultCompleteMode = ToilCompleteMode.Instant }); this.AddFinishAction(() => { foreach (Building_Chalkboard chalk in chalkboards) { if (chalk != null) { chalk.frame = 0; chalk.state = 0; this.Map.mapDrawer.MapMeshDirty(chalk.Position, MapMeshFlag.Things, true, false); } } if (Spot.currentLessonState == Building_TeachingSpot.LessonState.finishing || Spot.currentLessonState == Building_TeachingSpot.LessonState.finished) { this.pawn.needs.mood.thoughts.memories.TryGainMemory(ThoughtDef.Named("TaughtCL"), null); } }); yield break; }
protected override IEnumerable <Toil> MakeNewToils() { this.AddEndCondition(delegate { Thing thing = this.GetActor().jobs.curJob.GetTarget(TargetIndex.A).Thing; if (thing is Building && !thing.Spawned) { return(JobCondition.Incompletable); } return(JobCondition.Ongoing); }); this.FailOnBurningImmobile(TargetIndex.A); //this.FailOn(delegate //{ // IBillGiver billGiver = this.pawn.jobs.curJob.GetTarget(TargetIndex.A).Thing as IBillGiver; // if (billGiver != null) // { // if (this.pawn.jobs.curJob.bill.DeletedOrDereferenced) // { // return true; // } // if (!billGiver.CurrentlyUsable()) // { // return true; // } // } // return false; //}); //yield return ToilLogMessage("Pass 0 - Start"); Toil toil = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell); yield return(new Toil { initAction = delegate { offerings = new List <Thing>(); } }); yield return(Toils_Reserve.Reserve(TargetIndex.A, 1)); //yield return new Toil {initAction = delegate {Log.Message("Pass 2");}}; yield return(Toils_Reserve.ReserveQueue(TargetIndex.B, 1)); //yield return new Toil {initAction = delegate {Log.Message("Pass 3");}}; yield return(new Toil { initAction = delegate { if (this.job.targetQueueB != null && this.job.targetQueueB.Count == 1) { UnfinishedThing unfinishedThing = this.job.targetQueueB[0].Thing as UnfinishedThing; if (unfinishedThing != null) { unfinishedThing.BoundBill = (Bill_ProductionWithUft)this.job.bill; } } } }); //yield return new Toil {initAction = delegate {Log.Message("Pass 4");}}; yield return(Toils_Jump.JumpIf(toil, () => this.job.GetTargetQueue(TargetIndex.B).NullOrEmpty <LocalTargetInfo>())); //yield return new Toil {initAction = delegate {Log.Message("Pass 5");}}; Toil toil2 = Toils_JobTransforms.ExtractNextTargetFromQueue(TargetIndex.B, false); yield return(toil2); //yield return new Toil {initAction = delegate {Log.Message("Pass 6");}}; Toil toil3 = Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.B).FailOnSomeonePhysicallyInteracting(TargetIndex.B); yield return(toil3); //yield return new Toil {initAction = delegate {Log.Message("Pass 7");}}; yield return(Toils_Haul.StartCarryThing(TargetIndex.B, true, false)); //yield return new Toil {initAction = delegate {Log.Message("Pass 8");}}; yield return(JumpToCollectNextIntoHandsForBill(toil3, TargetIndex.B)); //yield return new Toil {initAction = delegate {Log.Message("Pass 9");}}; yield return(Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.ClosestTouch).FailOnDestroyedOrNull(TargetIndex.B)); //yield return new Toil {initAction = delegate {Log.Message("Pass 10");}}; Toil toil4 = Toils_JobTransforms.SetTargetToIngredientPlaceCell(TargetIndex.A, TargetIndex.B, TargetIndex.C); yield return(toil4); //yield return new Toil {initAction = delegate {Log.Message("Pass 11");}}; yield return(Toils_Haul.PlaceHauledThingInCell(TargetIndex.C, toil4, false)); //yield return new Toil {initAction = delegate {Log.Message("Pass 12");}}; yield return(new Toil { initAction = delegate { if (offerings.Count > 0) { offerings.RemoveAll(x => x.DestroyedOrNull()); } offerings.Add(TargetB.Thing); } }); yield return(Toils_Jump.JumpIfHaveTargetInQueue(TargetIndex.B, toil2)); yield return(toil); //yield return ToilLogMessage("Pass 13"); Toil chantingTime = new Toil(); chantingTime.defaultCompleteMode = ToilCompleteMode.Delay; chantingTime.defaultDuration = CultUtility.ritualDuration; chantingTime.WithProgressBarToilDelay(TargetIndex.A, false, -0.5f); chantingTime.PlaySustainerOrSound(CultsDefOf.RitualChanting); Texture2D deitySymbol = ((CosmicEntityDef)DropAltar.currentOfferingDeity.def).Symbol; chantingTime.initAction = delegate { if (deitySymbol != null) { MoteMaker.MakeInteractionBubble(this.pawn, null, ThingDefOf.Mote_Speech, deitySymbol); } }; yield return(chantingTime); //yield return ToilLogMessage("Pass 14"); //Toil 8: Execution of Prisoner yield return(new Toil { initAction = delegate { CultUtility.OfferingComplete(this.pawn, DropAltar, DropAltar.currentOfferingDeity, offerings); }, defaultCompleteMode = ToilCompleteMode.Instant }); //yield return ToilLogMessage("Pass 15 - Final"); yield break; //this.AddEndCondition(delegate //{ // Thing thing = this.GetActor().jobs.curJob.GetTarget(TargetIndex.A).Thing; // if (thing is Building && !thing.Spawned) // { // return JobCondition.Incompletable; // } // return JobCondition.Ongoing; //}); //this.FailOnBurningImmobile(TargetIndex.A); //Toil toil = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell); //yield return Toils_Reserve.Reserve(TargetIndex.A, 1); //yield return Toils_Reserve.ReserveQueue(TargetIndex.B, 1); //yield return new Toil //{ // initAction = delegate // { // if (this.job.targetQueueB != null && this.job.targetQueueB.Count == 1) // { // UnfinishedThing unfinishedThing = this.job.targetQueueB[0].Thing as UnfinishedThing; // if (unfinishedThing != null) // { // unfinishedThing.BoundBill = (Bill_ProductionWithUft)this.job.bill; // } // } // } //}; //yield return Toils_Jump.JumpIf(toil, () => this.job.GetTargetQueue(TargetIndex.B).NullOrEmpty<LocalTargetInfo>()); //Toil toil2 = Toils_JobTransforms.ExtractNextTargetFromQueue(TargetIndex.B); //yield return toil2; //Toil toil3 = Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch).FailOnDespawnedNullOrForbidden(TargetIndex.B).FailOnSomeonePhysicallyInteracting(TargetIndex.B); //yield return toil3; //yield return Toils_Haul.StartCarryThing(TargetIndex.B); //yield return JumpToCollectNextIntoHandsForBill(toil3, TargetIndex.B); //yield return Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell).FailOnDestroyedOrNull(TargetIndex.B); //Toil toil4 = Toils_JobTransforms.SetTargetToIngredientPlaceCell(TargetIndex.A, TargetIndex.B, TargetIndex.C); //yield return toil4; //yield return Toils_Haul.PlaceHauledThingInCell(TargetIndex.C, toil4, false); //yield return Toils_Jump.JumpIfHaveTargetInQueue(TargetIndex.B, toil2); //yield return toil; //Toil chantingTime = new Toil(); //chantingTime.defaultCompleteMode = ToilCompleteMode.Delay; //CultUtility.remainingDuration = CultUtility.ritualDuration; //chantingTime.defaultDuration = CultUtility.remainingDuration - 360; //chantingTime.WithProgressBarToilDelay(TargetIndex.A, false, -0.5f); //chantingTime.PlaySustainerOrSound(CultDefOfs.RitualChanting); //Texture2D deitySymbol = ((CosmicEntityDef)DropAltar.currentOfferingDeity.def).Symbol; //chantingTime.initAction = delegate //{ // if (deitySymbol != null) // MoteMaker.MakeInteractionBubble(this.pawn, null, ThingDefOf.Mote_Speech, deitySymbol); //}; //yield return chantingTime; ////Toil 8: Execution of Prisoner //yield return new Toil //{ // initAction = delegate // { // CultUtility.OfferingComplete(this.pawn, DropAltar, DropAltar.currentOfferingDeity); // }, // defaultCompleteMode = ToilCompleteMode.Instant //}; ////this.AddFinishAction(() => ////{ //// if (this.pawn.CurJob.targetQueueB.Count == 0 && //// DropAltar.currentOfferingState == Building_SacrificialAltar.OfferingState.started) //// //When the ritual is finished -- then let's give the thoughts //// CultUtility.OfferingReady(this.pawn, DropAltar); ////}); }
protected override IEnumerable <Toil> MakeNewToils() { //Commence fail checks! this.FailOnDestroyedOrNull(TargetIndex.A); yield return(Toils_Reserve.Reserve(AltarIndex, Building_SacrificialAltar.LyingSlotsCount)); yield return(new Toil { initAction = delegate { DropAltar.ChangeState(Building_SacrificialAltar.State.worshipping, Building_SacrificialAltar.WorshipState.gathering); } }); //Who are we worshipping today? var deitySymbol = ((CosmicEntityDef)DropAltar.currentWorshipDeity.def).Symbol; string deityLabel = DropAltar.currentWorshipDeity.Label; Toil goToAltar = Toils_Goto.GotoThing(TargetIndex.A, PathEndMode.InteractionCell); //Toil 0: Activate any nearby Worship Callers. yield return(new Toil { initAction = delegate { Predicate <Thing> validator = (x => x.TryGetComp <CompWorshipCaller>() != null); Thing worshipCaller = GenClosest.ClosestThingReachable(DropAltar.Position, DropAltar.Map, ThingRequest.ForGroup(ThingRequestGroup.BuildingArtificial), PathEndMode.ClosestTouch, TraverseParms.For(this.pawn, Danger.None, TraverseMode.ByPawn), 9999, validator, null, 0, -1, false, RegionType.Set_Passable, false); if (worshipCaller != null) { WorshipCaller = worshipCaller; this.job.SetTarget(TargetIndex.B, worshipCaller); } else { base.JumpToToil(goToAltar); } } }); yield return(Toils_Goto.GotoThing(TargetIndex.B, PathEndMode.ClosestTouch).JumpIfDespawnedOrNullOrForbidden(TargetIndex.B, goToAltar)); yield return(new Toil { initAction = delegate { WorshipCaller.TryGetComp <CompWorshipCaller>().Use(Forced); } }.JumpIfDespawnedOrNullOrForbidden(TargetIndex.B, goToAltar)); //Toil 1: Go to the altar. yield return(goToAltar); //Toil 2: Wait a bit for stragglers. Toil waitingTime = new Toil(); waitingTime.defaultCompleteMode = ToilCompleteMode.Delay; waitingTime.defaultDuration = CultUtility.ritualDuration; waitingTime.initAction = delegate { report = "Cults_WaitingToStartSermon".Translate(); DropAltar.ChangeState(Building_SacrificialAltar.State.worshipping, Building_SacrificialAltar.WorshipState.worshipping); }; yield return(waitingTime); //Toil 3: Preach the sermon. Toil preachingTime = new Toil(); preachingTime.defaultCompleteMode = ToilCompleteMode.Delay; preachingTime.defaultDuration = CultUtility.ritualDuration; preachingTime.initAction = delegate { report = "Cults_PreachingAbout".Translate(new object[] { deityLabel }); if (deitySymbol != null) { MoteMaker.MakeInteractionBubble(this.pawn, null, ThingDefOf.Mote_Speech, deitySymbol); } }; preachingTime.tickAction = delegate { Pawn actor = this.pawn; actor.skills.Learn(SkillDefOf.Social, 0.25f); actor.GainComfortFromCellIfPossible(); }; yield return(preachingTime); //Toil 4: Time to pray Toil chantingTime = new Toil(); chantingTime.defaultCompleteMode = ToilCompleteMode.Delay; chantingTime.defaultDuration = CultUtility.ritualDuration; chantingTime.WithProgressBarToilDelay(TargetIndex.A, false, -0.5f); chantingTime.PlaySustainerOrSound(CultsDefOf.RitualChanting); chantingTime.initAction = delegate { report = "Cults_PrayingTo".Translate(new object[] { deityLabel }); if (deitySymbol != null) { MoteMaker.MakeInteractionBubble(this.pawn, null, ThingDefOf.Mote_Speech, deitySymbol); } }; chantingTime.tickAction = delegate { Pawn actor = this.pawn; actor.skills.Learn(SkillDefOf.Social, 0.25f); actor.GainComfortFromCellIfPossible(); }; yield return(chantingTime); //Toil 8: Execution of Prisoner yield return(new Toil { initAction = delegate { //TaleRecorder.RecordTale( // Of.ExecutedPrisoner, new object[] //{ // this.pawn, // this.Takee //}); CultUtility.WorshipComplete(this.pawn, DropAltar, DropAltar.currentWorshipDeity); }, defaultCompleteMode = ToilCompleteMode.Instant }); yield return(new Toil { initAction = delegate { if (DropAltar != null) { if (DropAltar.currentWorshipState != Building_SacrificialAltar.WorshipState.finished) { DropAltar.ChangeState(Building_SacrificialAltar.State.worshipping, Building_SacrificialAltar.WorshipState.finished); //Map.GetComponent<MapComponent_SacrificeTracker>().ClearVariables(); } } }, defaultCompleteMode = ToilCompleteMode.Instant }); this.AddFinishAction(() => { //When the ritual is finished -- then let's give the thoughts if (DropAltar.currentWorshipState == Building_SacrificialAltar.WorshipState.finishing || DropAltar.currentWorshipState == Building_SacrificialAltar.WorshipState.finished) { Cthulhu.Utility.DebugReport("Called end tick check"); CultUtility.HoldWorshipTickCheckEnd(this.pawn); } }); yield break; }
protected override bool TryCastShot() { bool flag = false; CompAbilityUserMight comp = base.CasterPawn.GetComp <CompAbilityUserMight>(); MightPowerSkill pwr = base.CasterPawn.GetComp <CompAbilityUserMight>().MightData.MightPowerSkill_AnimalFriend.FirstOrDefault((MightPowerSkill x) => x.label == "TM_AnimalFriend_pwr"); MightPowerSkill ver = base.CasterPawn.GetComp <CompAbilityUserMight>().MightData.MightPowerSkill_AnimalFriend.FirstOrDefault((MightPowerSkill x) => x.label == "TM_AnimalFriend_ver"); Pawn pawn = this.CasterPawn; Pawn animal = this.currentTarget.Thing as Pawn; if (animal != null && animal.RaceProps.Animal && animal.RaceProps.IsFlesh) { Pawn oldbond = comp.bondedPet; if (animal == comp.bondedPet) { Hediff animalBondHD = oldbond.health.hediffSet.GetFirstHediffOfDef(HediffDef.Named("TM_RangerBondHD")); if (animalBondHD != null && Rand.Chance(((1f + animalBondHD.ageTicks / 6000000) - oldbond.RaceProps.wildness))) { Messages.Message("TM_BondedAnimalReleaseToColony".Translate( oldbond.LabelShort, pawn.LabelShort ), MessageTypeDefOf.NeutralEvent); MoteMaker.MakeInteractionBubble(oldbond, pawn, InteractionDefOf.Nuzzle.interactionMote, InteractionDefOf.Nuzzle.GetSymbol()); oldbond.health.RemoveHediff(animalBondHD); DefMap <TrainableDef, int> steps = Traverse.Create(root: oldbond.training).Field(name: "steps").GetValue <DefMap <TrainableDef, int> >(); steps[TrainableDefOf.Tameness] = 1; steps[TrainableDefOf.Obedience] = 0; steps[TrainableDefOf.Release] = 0; steps[TorannMagicDefOf.Haul] = 0; steps[TorannMagicDefOf.Rescue] = 0; comp.bondedPet = null; } else { Messages.Message("TM_BondedAnimalRelease".Translate( oldbond.LabelShort, pawn.LabelShort ), MessageTypeDefOf.NeutralEvent); FleckMaker.ThrowSmoke(oldbond.DrawPos, oldbond.Map, 3f); oldbond.Destroy(); } } else if (animal.Faction != null && animal.Faction != pawn.Faction) { Messages.Message("TM_AnimalHasAllegience".Translate( ), MessageTypeDefOf.RejectInput); } else if (animal.health != null && animal.health.hediffSet != null && animal.health.hediffSet.HasHediff(HediffDef.Named("TM_RangerBondHD"))) { Messages.Message("TM_AnimalAlreadyHasBond".Translate(animal.LabelShort ), MessageTypeDefOf.RejectInput); } else { if (animal.RaceProps.intelligence == Intelligence.Animal) // == TrainableIntelligenceDefOf.Intermediate || animal.RaceProps.TrainableIntelligence == TrainableIntelligenceDefOf.Advanced) { if ((animal.RaceProps.wildness <= .7f) || (animal.RaceProps.wildness <= .8f && pwr.level == 1) || (animal.RaceProps.wildness <= .9f && pwr.level == 2) || pwr.level == 3) { if (Rand.Chance(.6f + (.05f * pwr.level)) && Rand.Chance(((.7f + (.1f * pwr.level)) - animal.RaceProps.wildness) * 10)) { if (comp.bondedPet != null && comp.bondedPet != animal) { if (!oldbond.Destroyed) { if (!comp.bondedPet.Dead) { //bonding with another pet without first pet being dead or destroyed comp.bondedPet = null; Messages.Message("TM_BondedAnimalRelease".Translate( oldbond.LabelShort, pawn.LabelShort ), MessageTypeDefOf.NeutralEvent); if (oldbond.Map != null) { FleckMaker.ThrowSmoke(oldbond.DrawPos, oldbond.Map, 3f); } else { oldbond.ParentHolder.GetDirectlyHeldThings().Remove(oldbond); } oldbond.Destroy(); } } } animal.SetFaction(pawn.Faction); HealthUtility.AdjustSeverity(animal, TorannMagicDefOf.TM_RangerBondHD, -4f); HealthUtility.AdjustSeverity(animal, TorannMagicDefOf.TM_RangerBondHD, .5f + ver.level); comp.bondedPet = animal; MoteMaker.MakeInteractionBubble(animal, pawn, InteractionDefOf.Nuzzle.interactionMote, InteractionDefOf.Nuzzle.GetSymbol()); TM_Action.TrainAnimalFull(animal, pawn); } else { Messages.Message("TM_FailedRangerBond".Translate( animal.LabelShort, pawn.LabelShort, (Mathf.Clamp(Mathf.RoundToInt(((.7f + (.1f * pwr.level)) - animal.RaceProps.wildness) * 1000f), 0, 100 - (40 - (5 * pwr.level)))) ), MessageTypeDefOf.NeutralEvent); if (animal.Faction == null && Rand.Chance(animal.RaceProps.manhunterOnTameFailChance)) { animal.mindState.mentalStateHandler.TryStartMentalState(MentalStateDefOf.Manhunter, null, true, false, null); } } } else { Messages.Message("TM_RangerNotExperienced".Translate( animal.LabelShort, pawn.LabelShort, (animal.RaceProps.wildness * 100).ToString("F"), (.7f + .1f * pwr.level) * 100 ), MessageTypeDefOf.NeutralEvent); } } else { Messages.Message("TM_AnimalIncapableOfBond".Translate( animal.LabelShort, pawn.LabelShort ), MessageTypeDefOf.NeutralEvent); } } } this.PostCastShot(flag, out flag); return(flag); }