public JunimoFamiliar(Vector2 position, long ownerId) : base("Junimo", position, new AnimatedSprite("Characters\\Junimo", 0, 16, 16)) { friendly.Value = true; nextPosition.Value = GetBoundingBox(); Breather = false; speed = 3; forceUpdateTimer = 9999; collidesWithOtherCharacters.Value = true; farmerPassesThrough = true; ignoreMovementAnimations = true; color.Value = FamiliarsUtils.GetJunimoColor(); }
public override void reloadSprite() { if (Sprite == null) { Sprite = new AnimatedSprite(ModEntry.Config.DustTexture); } else { Sprite.textureName.Value = ModEntry.Config.DustTexture; } if (ModEntry.Config.DustColorType.ToLower() != "default") { Sprite.spriteTexture = FamiliarsUtils.ColorFamiliar(Sprite.Texture, mainColor, redColor, greenColor, blueColor); } }
public override void reloadSprite() { ModEntry.SMonitor.Log($"reloading bat familiar sprite for {Name} {ModEntry.Config.BatTexture}"); if (Sprite == null) { ModEntry.SMonitor.Log($"creating new sprite"); Sprite = new AnimatedSprite(ModEntry.Config.BatTexture); } else { ModEntry.SMonitor.Log($"updating sprite texture"); Sprite.textureName.Value = ModEntry.Config.BatTexture; } if (ModEntry.Config.BatColorType.ToLower() != "default") { Sprite.spriteTexture = FamiliarsUtils.ColorFamiliar(Sprite.Texture, mainColor, redColor, greenColor, blueColor); } HideShadow = true; }
public static void Player_Warped(object sender, WarpedEventArgs e) { if (e.OldLocation.characters == null) { return; } e.OldLocation.characters.OnValueRemoved -= Characters_OnValueRemoved; e.NewLocation.characters.OnValueRemoved += Characters_OnValueRemoved; for (int i = e.OldLocation.characters.Count - 1; i >= 0; i--) { NPC npc = e.OldLocation.characters[i]; if (npc is Familiar) { Farmer owner = Game1.getFarmer(Helper.Reflection.GetField <long>(npc, "ownerId").GetValue()); if (owner == Game1.player && (npc as Familiar).followingOwner) { FamiliarsUtils.warpFamiliar(npc, e.NewLocation, Game1.player.getTileLocation()); } } } }
public static void GameLoop_DayStarted(object sender, DayStartedEventArgs e) { FamiliarsUtils.LoadFamiliars(); ModEntry.receivedJunimoEggToday = false; }
/// <summary>The mod entry point, called after the mod is first loaded.</summary> /// <param name="helper">Provides simplified APIs for writing mods.</param> public override void Entry(IModHelper helper) { context = this; Config = Helper.ReadConfig <ModConfig>(); SHelper = helper; SMonitor = Monitor; if (!Config.EnableMod) { return; } mp = helper.Reflection.GetField <Multiplayer>(typeof(Game1), "multiplayer").GetValue(); FamiliarsPatches.Initialize(Monitor, Helper, Config); FamiliarsHelperEvents.Initialize(Monitor, Helper, Config); FamiliarsUtils.Initialize(Monitor, Helper, Config); Helper.ConsoleCommands.Add("DispelFamiliars", "Dispel all familiars.", new Action <string, string[]>(DispelFamiliars)); Helper.ConsoleCommands.Add("DF", "Dispel all familiars.", new System.Action <string, string[]>(DispelFamiliars)); Helper.ConsoleCommands.Add("SummonFamiliars", "Summon all familiars to you.", new System.Action <string, string[]>(SummonFamiliars)); Helper.ConsoleCommands.Add("SF", "Summon all familiars to you.", new System.Action <string, string[]>(SummonFamiliars)); if (Config.IAmAStinkyCheater) { Helper.ConsoleCommands.Add("CallFamiliar", "Call a familiar. Usage: CallFamiliar <familiarType>", new System.Action <string, string[]>(CallFamiliar)); Helper.ConsoleCommands.Add("CF", "Call a familiar. Usage: CF <familiarType>", new System.Action <string, string[]>(CallFamiliar)); } Helper.Events.GameLoop.GameLaunched += FamiliarsHelperEvents.GameLoop_GameLaunched; Helper.Events.GameLoop.SaveLoaded += FamiliarsHelperEvents.GameLoop_SaveLoaded; Helper.Events.GameLoop.Saving += FamiliarsHelperEvents.GameLoop_Saving; Helper.Events.GameLoop.DayStarted += FamiliarsHelperEvents.GameLoop_DayStarted; Helper.Events.Input.ButtonPressed += FamiliarsHelperEvents.Input_ButtonPressed; Helper.Events.Player.Warped += FamiliarsHelperEvents.Player_Warped; var harmony = HarmonyInstance.Create(ModManifest.UniqueID); harmony.Patch( original: AccessTools.Method(typeof(GameLocation), nameof(GameLocation.drawAboveFrontLayer)), postfix: new HarmonyMethod(typeof(FamiliarsPatches), nameof(FamiliarsPatches.GameLocation_drawAboveFrontLayer_Postfix)) ); harmony.Patch( original: AccessTools.Method(typeof(Object), nameof(Object.performObjectDropInAction)), prefix: new HarmonyMethod(typeof(FamiliarsPatches), nameof(FamiliarsPatches.Object_performObjectDropInAction_Prefix)) ); harmony.Patch( original: AccessTools.Method(typeof(Object), nameof(Object.minutesElapsed)), postfix: new HarmonyMethod(typeof(FamiliarsPatches), nameof(FamiliarsPatches.Object_minutesElapsed_Postfix)) ); harmony.Patch( original: AccessTools.Method(typeof(GameLocation), nameof(GameLocation.performTouchAction)), postfix: new HarmonyMethod(typeof(FamiliarsPatches), nameof(FamiliarsPatches.GameLocation_performTouchAction_Postfix)) ); harmony.Patch( original: AccessTools.Method(typeof(Utility), nameof(Utility.checkForCharacterInteractionAtTile)), postfix: new HarmonyMethod(typeof(FamiliarsPatches), nameof(FamiliarsPatches.Utility_checkForCharacterInteractionAtTile_Postfix)) ); harmony.Patch( original: AccessTools.Method(typeof(NPC), nameof(NPC.isVillager)), prefix: new HarmonyMethod(typeof(FamiliarsPatches), nameof(FamiliarsPatches.NPC_isVillager_Prefix)) ); harmony.Patch( original: AccessTools.Method(typeof(Character), nameof(Character.checkForFootstep)), prefix: new HarmonyMethod(typeof(FamiliarsPatches), nameof(FamiliarsPatches.Character_checkForFootstep_Prefix)) ); harmony.Patch( original: AccessTools.Method(typeof(Bush), "shake"), prefix: new HarmonyMethod(typeof(FamiliarsPatches), nameof(FamiliarsPatches.Bush_shake_Prefix)) ); harmony.Patch( original: AccessTools.Method(typeof(GameLocation), "updateCharacters"), prefix: new HarmonyMethod(typeof(FamiliarsPatches), nameof(FamiliarsPatches.GameLocation_updateCharacters_Prefix)) ); harmony.Patch( original: AccessTools.Method(typeof(GameLocation), "drawCharacters"), prefix: new HarmonyMethod(typeof(FamiliarsPatches), nameof(FamiliarsPatches.GameLocation_drawCharacters_Prefix)) ); harmony.Patch( original: AccessTools.Method(typeof(AnimalHouse), nameof(AnimalHouse.incubator)), prefix: new HarmonyMethod(typeof(FamiliarsPatches), nameof(FamiliarsPatches.AnimalHouse_incubator_Prefix)) ); harmony.Patch( original: AccessTools.Method(typeof(Utility), nameof(Utility.isThereAFarmerOrCharacterWithinDistance)), postfix: new HarmonyMethod(typeof(FamiliarsPatches), nameof(FamiliarsPatches.Utility_isThereAFarmerOrCharacterWithinDistance_Postfix)) ); }
public override void behaviorAtGameTick(GameTime time) { invincibleCountdown = 1000; if (timeBeforeAIMovementAgain > 0f) { timeBeforeAIMovementAgain -= (float)time.ElapsedGameTime.Milliseconds; } if (yJumpOffset == 0) { if (Game1.random.NextDouble() < DestroyRockChance()) { ModEntry.SHelper.Reflection.GetField <Multiplayer>(typeof(Game1), "multiplayer").GetValue().broadcastSprites(base.currentLocation, new TemporaryAnimatedSprite[] { new TemporaryAnimatedSprite("TileSheets\\animations", new Rectangle(0, 128, 64, 64), 40f, 4, 0, base.getStandingPosition(), false, false) }); foreach (Vector2 v in Utility.getAdjacentTileLocations(base.getTileLocation())) { if (currentLocation is MineShaft && currentLocation.objects.ContainsKey(v) && base.currentLocation.objects[v].Name.Equals("Stone")) { AddExp(1); currentLocation.destroyObject(v, null); } } yJumpVelocity *= 2f; } if (!chargingFarmer && !chargingMonster) { xVelocity = (float)Game1.random.Next(-20, 21) / 5f; } } if (lastHitCounter >= 0) { lastHitCounter.Value -= time.ElapsedGameTime.Milliseconds; } chargingMonster = false; if (lastHitCounter < 0) { foreach (NPC npc in currentLocation.characters) { if (npc is Familiar) { continue; } if (npc is Monster && FamiliarsUtils.monstersColliding(this, (Monster)npc) && Game1.random.NextDouble() < StealChance()) { ModEntry.SMonitor.Log("Stealing loot"); FamiliarsUtils.monsterDrop(this, (Monster)npc, GetOwner()); lastHitCounter.Value = StealInterval(); chargingMonster = false; AddExp(1); break; } else if (npc is Monster && FamiliarsUtils.withinMonsterThreshold(this, (Monster)npc, 5)) { chargingMonster = true; if (currentTarget == null || Vector2.Distance(npc.position, position) < Vector2.Distance(currentTarget.position, position)) { currentTarget = (Monster)npc; } } } } if (chargingMonster && currentTarget != null) { base.Slipperiness = 10; Vector2 v2 = FamiliarsUtils.getAwayFromNPCTrajectory(GetBoundingBox(), currentTarget); xVelocity += -v2.X / 150f + ((Game1.random.NextDouble() < 0.01) ? ((float)Game1.random.Next(-50, 50) / 10f) : 0f); if (Math.Abs(xVelocity) > 5f) { xVelocity = (float)(Math.Sign(xVelocity) * 5); } yVelocity += -v2.Y / 150f + ((Game1.random.NextDouble() < 0.01) ? ((float)Game1.random.Next(-50, 50) / 10f) : 0f); if (Math.Abs(yVelocity) > 5f) { yVelocity = (float)(Math.Sign(yVelocity) * 5); } return; } chargingFarmer = false; if (!followingOwner) { return; } if (!seenFarmer && withinPlayerThreshold()) { seenFarmer = true; return; } if (seenFarmer && controller == null && !runningAwayFromFarmer) { base.addedSpeed = 2; controller = new PathFindController(this, base.currentLocation, new PathFindController.isAtEnd(Utility.isOffScreenEndFunction), -1, false, new PathFindController.endBehavior(offScreenBehavior), 350, Point.Zero, true); runningAwayFromFarmer = true; return; } if (controller == null && runningAwayFromFarmer) { chargingFarmer = true; } if (chargingFarmer) { base.Slipperiness = 10; Vector2 v2 = Utility.getAwayFromPlayerTrajectory(GetBoundingBox(), GetOwner()); xVelocity += -v2.X / 150f + ((Game1.random.NextDouble() < 0.01) ? ((float)Game1.random.Next(-50, 50) / 10f) : 0f); if (Math.Abs(xVelocity) > 5f) { xVelocity = (float)(Math.Sign(xVelocity) * 5); } yVelocity += -v2.Y / 150f + ((Game1.random.NextDouble() < 0.01) ? ((float)Game1.random.Next(-50, 50) / 10f) : 0f); if (Math.Abs(yVelocity) > 5f) { yVelocity = (float)(Math.Sign(yVelocity) * 5); } if (Game1.random.NextDouble() < 0.0001) { controller = new PathFindController(this, base.currentLocation, new Point((int)GetOwner().getTileLocation().X, (int)GetOwner().getTileLocation().Y), Game1.random.Next(4), null, 300); chargingFarmer = false; return; } } }
internal static void LoadFamiliars() { FamiliarSaveData fsd = Helper.Data.ReadSaveData <FamiliarSaveData>("familiars") ?? new FamiliarSaveData(); foreach (FamiliarData f in fsd.dustSpriteFamiliars) { Monitor.Log($"Got saved Dust Familiar at {f.currentLocation}"); GameLocation l = null; if (Game1.getLocationFromName(f.currentLocation) != null) { l = Game1.getLocationFromName(f.currentLocation); } else { l = Game1.getFarm().buildings.FirstOrDefault(b => b.buildingType == "Slime Hutch")?.indoors.Value; } if (l == null) { continue; } Monitor.Log($"Returning saved Dust Familiar to {l.Name}"); DustSpriteFamiliar d = new DustSpriteFamiliar(f.position, f.ownerId); d.followingOwner = f.followingOwner; d.daysOld.Value = f.daysOld; d.exp.Value = f.exp; d.mainColor = f.mainColor; d.redColor = f.redColor; d.greenColor = f.greenColor; d.blueColor = f.blueColor; d.SetScale(); d.currentLocation = l; l.characters.Add(d); } foreach (FamiliarData f in fsd.dinoFamiliars) { Monitor.Log($"Got saved Dino Familiar at {f.currentLocation}"); GameLocation l = null; if (Game1.getLocationFromName(f.currentLocation) != null) { l = Game1.getLocationFromName(f.currentLocation); } else { l = Game1.getFarm().buildings.FirstOrDefault(b => b.buildingType == "Slime Hutch")?.indoors.Value; } if (l == null) { continue; } Monitor.Log($"Returning saved Dino Familiar to {l.Name}"); DinoFamiliar d = new DinoFamiliar(f.position, f.ownerId); d.followingOwner = f.followingOwner; d.daysOld.Value = f.daysOld; d.exp.Value = f.exp; d.mainColor = f.mainColor; d.redColor = f.redColor; d.greenColor = f.greenColor; d.blueColor = f.blueColor; d.SetScale(); d.currentLocation = l; l.characters.Add(d); } foreach (FamiliarData f in fsd.batFamiliars) { Monitor.Log($"Got saved Bat Familiar at {f.currentLocation}"); GameLocation l = null; if (Game1.getLocationFromName(f.currentLocation) != null) { l = Game1.getLocationFromName(f.currentLocation); } else { l = Game1.getFarm().buildings.FirstOrDefault(b => b.buildingType == "Slime Hutch")?.indoors.Value; } if (l == null) { continue; } Monitor.Log($"Returning saved Bat Familiar to {l.Name}"); BatFamiliar d = new BatFamiliar(f.position, f.ownerId); d.followingOwner = f.followingOwner; d.daysOld.Value = f.daysOld; d.exp.Value = f.exp; d.mainColor = f.mainColor; d.redColor = f.redColor; d.greenColor = f.greenColor; d.blueColor = f.blueColor; d.SetScale(); d.currentLocation = l; l.characters.Add(d); } foreach (FamiliarData f in fsd.junimoFamiliars) { Monitor.Log($"Got saved Junimo Familiar at {f.currentLocation}"); GameLocation l = null; if (Game1.getLocationFromName(f.currentLocation) != null) { l = Game1.getLocationFromName(f.currentLocation); } else { l = Game1.getFarm().buildings.FirstOrDefault(b => b.buildingType == "Slime Hutch")?.indoors.Value; } if (l == null) { continue; } Monitor.Log($"Returning saved Junimo Familiar to {l.Name}"); JunimoFamiliar d = new JunimoFamiliar(f.position, f.ownerId); d.followingOwner = f.followingOwner; d.daysOld.Value = f.daysOld; d.exp.Value = f.exp; d.mainColor = f.mainColor; d.redColor = f.redColor; d.greenColor = f.greenColor; d.blueColor = f.blueColor; if (f.color != null && f.color.A == 255) { d.color.Value = f.color; } else { d.color.Value = FamiliarsUtils.GetJunimoColor(); } d.SetScale(); d.currentLocation = l; l.characters.Add(d); } foreach (FamiliarData f in fsd.butterflyFamiliars) { Monitor.Log($"Got saved Butterfly Familiar at {f.currentLocation}"); GameLocation l = null; if (Game1.getLocationFromName(f.currentLocation) != null) { l = Game1.getLocationFromName(f.currentLocation); } else { l = Game1.getFarm().buildings.FirstOrDefault(b => b.buildingType == "Slime Hutch")?.indoors.Value; } if (l == null) { continue; } Monitor.Log($"Returning saved Butterfly Familiar to {l.Name}"); ButterflyFamiliar d = new ButterflyFamiliar(f.position, f.ownerId); d.followingOwner = f.followingOwner; d.daysOld.Value = f.daysOld; d.exp.Value = f.exp; d.mainColor = f.mainColor; d.redColor = f.redColor; d.greenColor = f.greenColor; d.blueColor = f.blueColor; d.baseFrame = f.baseFrame; d.SetScale(); d.currentLocation = l; d.baseFrame = f.baseFrame; d.reloadSprite(); l.characters.Add(d); } }
public override void reloadSprite() { ModEntry.SMonitor.Log($"reloading bat familiar sprite for {Name} {ModEntry.Config.BatTexture}"); if (this.Sprite == null) { ModEntry.SMonitor.Log($"creating new sprite"); this.Sprite = new AnimatedSprite(ModEntry.Config.BatTexture); } else { ModEntry.SMonitor.Log($"updating sprite texture"); this.Sprite.textureName.Value = ModEntry.Config.BatTexture; } if (ModEntry.Config.BatColorType.ToLower() != "default") { typeof(AnimatedSprite).GetField("spriteTexture", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(Sprite, FamiliarsUtils.ColorFamiliar(Sprite.Texture, mainColor, redColor, greenColor, blueColor)); } base.HideShadow = true; }
public override void behaviorAtGameTick(GameTime time) { invincibleCountdown = 1000; if (this.timeBeforeAIMovementAgain > 0f) { this.timeBeforeAIMovementAgain -= (float)time.ElapsedGameTime.Milliseconds; } if (lastHitCounter >= 0) { lastHitCounter.Value -= time.ElapsedGameTime.Milliseconds; } if (lastScreechCounter >= 0) { lastScreechCounter.Value -= time.ElapsedGameTime.Milliseconds; } if (lastScreechCounter < 0 && GetBoundingBox().Intersects(GetOwner().GetBoundingBox())) { if (ModEntry.Config.BatSoundEffects) { currentLocation.playSound("batScreech", NetAudio.SoundContext.Default); } lastScreechCounter.Value = 10000; } chargingMonster = false; if (lastHitCounter < 0) { foreach (NPC npc in currentLocation.characters) { if (npc is Familiar) { continue; } if (npc is Monster && FamiliarsUtils.monstersColliding(this, (Monster)npc)) { if (BaseDamage() >= 0) { int damageAmount = Game1.random.Next(BaseDamage(), BaseDamage() * 2 + 1); damageAmount = (npc as Monster).takeDamage(damageAmount, 0, 0, false, 0, GetOwner()); if ((npc as Monster).Health <= 0) { AddExp(10); } else { AddExp(1); } } lastHitCounter.Value = AttackInterval(); chargingMonster = false; break; } else if (npc is Monster && FamiliarsUtils.withinMonsterThreshold(this, (Monster)npc, 2)) { chargingMonster = true; if (currentTarget == null || Vector2.Distance(npc.position, position) < Vector2.Distance(currentTarget.position, position)) { currentTarget = (Monster)npc; } } } } if (this.wasHitCounter >= 0) { this.wasHitCounter.Value -= time.ElapsedGameTime.Milliseconds; } if (chargingMonster || followingOwner) { this.seenPlayer.Value = true; Vector2 center = Position + new Vector2(8, 8); Vector2 playerCenter = GetOwner().position + new Vector2(64, 92); if (Vector2.Distance(playerCenter, center) > 256) { Position = Vector2.Distance(playerCenter, center) * 0.03f * Vector2.Normalize(playerCenter - center) + center - new Vector2(8, 8); } float xSlope = (float)(-(float)(playerCenter.X - center.X)); float ySlope = (float)(playerCenter.Y - center.Y); float t = Math.Max(1f, Math.Abs(xSlope) + Math.Abs(ySlope)); if (t < (float)((this.extraVelocity > 0f) ? 192 : 64)) { this.xVelocity = Math.Max(-this.maxSpeed, Math.Min(this.maxSpeed, this.xVelocity * 1.05f)); this.yVelocity = Math.Max(-this.maxSpeed, Math.Min(this.maxSpeed, this.yVelocity * 1.05f)); } xSlope /= t; ySlope /= t; if (this.wasHitCounter <= 0) { this.targetRotation = (float)Math.Atan2((double)(-(double)ySlope), (double)xSlope) - 1.57079637f; if ((double)(Math.Abs(this.targetRotation) - Math.Abs(this.rotation)) > 2.748893571891069 && Game1.random.NextDouble() < 0.5) { this.turningRight.Value = true; } else if ((double)(Math.Abs(this.targetRotation) - Math.Abs(this.rotation)) < 0.39269908169872414) { this.turningRight.Value = false; } if (this.turningRight) { this.rotation -= (float)Math.Sign(this.targetRotation - this.rotation) * 0.0490873866f; } else { this.rotation += (float)Math.Sign(this.targetRotation - this.rotation) * 0.0490873866f; } this.rotation %= 6.28318548f; this.wasHitCounter.Value = 0; } float maxAccel = Math.Min(5f, Math.Max(1f, 5f - t / 64f / 2f)) + this.extraVelocity; xSlope = (float)Math.Cos((double)this.rotation + 1.5707963267948966); ySlope = -(float)Math.Sin((double)this.rotation + 1.5707963267948966); this.xVelocity += -xSlope * maxAccel / 6f + (float)Game1.random.Next(-10, 10) / 100f; this.yVelocity += -ySlope * maxAccel / 6f + (float)Game1.random.Next(-10, 10) / 100f; if (Math.Abs(this.xVelocity) > Math.Abs(-xSlope * this.maxSpeed)) { this.xVelocity -= -xSlope * maxAccel / 6f; } if (Math.Abs(this.yVelocity) > Math.Abs(-ySlope * this.maxSpeed)) { this.yVelocity -= -ySlope * maxAccel / 6f; } } }
public override void reloadSprite() { if (Sprite == null) { Sprite = new AnimatedSprite(ModEntry.Config.ButterflyTexture, baseFrame, 16, 16); } else { Sprite.textureName.Value = ModEntry.Config.ButterflyTexture; } if (ModEntry.Config.DustColorType.ToLower() != "default") { typeof(AnimatedSprite).GetField("spriteTexture", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(Sprite, FamiliarsUtils.ColorFamiliar(Sprite.Texture, mainColor, redColor, greenColor, blueColor)); } }