/// <summary> /// Companion reacts on player's ask /// </summary> /// <param name="companion"></param> /// <param name="leader"></param> /// <param name="action"></param> private void ReactOnAsk(NPC companion, Farmer leader, string action) { switch (action) { case "dismiss": Dialogue dismissalDialogue = new Dialogue( this.StateMachine.Dialogues.GetFriendSpecificDialogueText(leader, "companionDismiss"), companion); this.dismissalDialogue = dismissalDialogue; DialogueProvider.DrawDialogue(dismissalDialogue); break; case "bag": Chest bag = this.StateMachine.Bag; this.StateMachine.Companion.currentLocation.playSound("openBox"); Game1.activeClickableMenu = this.CreateOpenBagMenu(bag); break; } }
private void Player_Warped(object sender, WarpedEventArgs e) { NPC companion = this.StateMachine.Companion; Dictionary <string, string> bubbles = this.StateMachine.ContentLoader.LoadStrings("Strings/SpeechBubbles"); // Warp companion to farmer if it's needed if (companion.currentLocation != e.NewLocation) { this.ai.ChangeLocation(e.NewLocation); } // Show above head bubble text for location if (Game1.random.NextDouble() > .66f && DialogueProvider.GetAmbientBubbleString(bubbles, companion, e.NewLocation, out string bubble)) { companion.showTextAboveHead(bubble, preTimer: 250); } // Push new location dialogue this.TryPushLocationDialogue(e.NewLocation, true); }
private void GiveLove() { for (int i = 0; i < this.lovedMonsters.Count; i++) { if (this.lovedMonsters[i].TTL <= 0) { this.lovedMonsters[i].RevokeLove(); if (this.lovedMonsters[i].TTL < -this.lovedMonsters[i].LoveInvicibility) { this.lovedMonsters.RemoveAt(i--); } continue; } if (!Compat.IsModLoaded(ModUids.PACIFISTMOD_UID) && this.lovedMonsters[i].LastHealth != this.lovedMonsters[i].Monster.Health) { int lostPoints = 10; this.follower.doEmote(12); if (this.lovedMonsters[i].Monster.Health <= 0) { lostPoints = 75; if (DialogueProvider.GetBubbleString(this.bubbles, this.follower, "spiritualKilledMonster", out string bubble)) { this.follower.showTextAboveHead(bubble); } } if (this.leader is Farmer farmer) { farmer.changeFriendship(-lostPoints, this.follower); } } this.lovedMonsters[i].AcceptLove(); } }
private void GameLoop_TimeChanged(object sender, TimeChangedEventArgs e) { this.StateMachine.Companion.clearSchedule(); this.UpdateFriendship(e.NewTime); if (e.NewTime >= this.TimeToBye) { NPC companion = this.StateMachine.Companion; Dialogue dismissalDialogue = new Dialogue( this.StateMachine.Dialogues.GetFriendSpecificDialogueText( this.StateMachine.CompanionManager.Farmer, "companionDismissAuto"), companion); this.dismissalDialogue = dismissalDialogue; this.StateMachine.Companion.doEmote(24); this.StateMachine.Companion.updateEmote(Game1.currentGameTime); DialogueProvider.DrawDialogue(dismissalDialogue); } // Fix spawn ladder if area is infested and all monsters is killed but NPC following us if (this.StateMachine.Companion.currentLocation is MineShaft mines && mines.mustKillAllMonstersToAdvance()) { var monsters = from c in mines.characters where c.IsMonster && !this.ai.IsLovedMonster(c as Monster) select c; if (monsters.Count() == 0) { Vector2 vector2 = this.StateMachine.Reflection.GetProperty <Vector2>(mines, "tileBeneathLadder").GetValue(); if (mines.getTileIndexAt(Utility.Vector2ToPoint(vector2), "Buildings") == -1) { mines.createLadderAt(vector2, "newArtifact"); } } } // Try to push new or change location dialogue randomly until or no location dialogue was pushed int until = this.dialoguePushTime + (Game1.random.Next(1, 5) * 10); if ((e.NewTime > until || this.currentLocationDialogue == null)) { this.TryPushLocationDialogue(this.StateMachine.Companion.currentLocation); } // Remove recruited dialogue if this dialogue not spoken until a hour from while companion was recruited if (this.recruitedDialogue != null && e.NewTime > this.timeOfRecruit + 100) { // TODO: Use here Remove old dialogue method when rebased onto branch or merged branch which has this util Stack <Dialogue> temp = new Stack <Dialogue>(this.StateMachine.Companion.CurrentDialogue.Count); while (this.StateMachine.Companion.CurrentDialogue.Count > 0) { Dialogue d = this.StateMachine.Companion.CurrentDialogue.Pop(); if (!d.Equals(this.recruitedDialogue)) { temp.Push(d); } else { this.monitor.Log($"Recruited dialogue was removed from {this.StateMachine.Name}'s stack due to NPC was recruited a hour ago and dialogue still not spoken."); } } while (temp.Count > 0) { this.StateMachine.Companion.CurrentDialogue.Push(temp.Pop()); } } }
private void DoFightSpeak(bool onlyEmote = false) { // Cooldown not expired? Say nothing if (this.fightBubbleCooldown != 0) { return; } if (!onlyEmote && Game1.random.NextDouble() < this.fightSpeechTriggerThres && DialogueProvider.GetBubbleString(this.bubbles, this.follower, "fight", out string text)) { bool isRed = this.ai.Csm.HasSkill("warrior") && Game1.random.NextDouble() < 0.1; this.follower.showTextAboveHead(text, isRed ? 2 : -1); this.fightBubbleCooldown = 600; } else if (this.ai.Csm.HasSkill("warrior") && Game1.random.NextDouble() < this.fightSpeechTriggerThres / 2) { if (Compat.IsModLoaded(ModUids.PACIFISTMOD_UID)) { return; } this.follower.clearTextAboveHead(); this.follower.doEmote(12); this.fightBubbleCooldown = 550; } else if (Game1.random.NextDouble() > (this.fightSpeechTriggerThres + this.fightSpeechTriggerThres * .33f)) { if (Compat.IsModLoaded(ModUids.PACIFISTMOD_UID)) { return; } this.follower.clearTextAboveHead(); this.follower.doEmote(16); this.fightBubbleCooldown = 500; } }