/// <summary>Fix the player's magic spells and mana pool to match their skill level if needed.</summary> /// <param name="player">The player to fix.</param> /// <param name="overrideMagicLevel">The magic skill level, or <c>null</c> to get it from the player.</param> public static void FixMagicIfNeeded(Farmer player, int?overrideMagicLevel = null) { // skip if player hasn't learned magic if (!Magic.LearnedMagic && overrideMagicLevel is not > 0) { return; } // get magic info int magicLevel = overrideMagicLevel ?? player.GetCustomSkillLevel(Skill.MagicSkillId); SpellBook spellBook = Game1.player.GetSpellBook(); // fix mana pool { int expectedPoints = magicLevel * MagicConstants.ManaPointsPerLevel; if (player.GetMaxMana() < expectedPoints) { player.SetMaxMana(expectedPoints); player.AddMana(expectedPoints); } } // fix spell bars if (spellBook.Prepared.Count < MagicConstants.SpellBarCount) { spellBook.Mutate(data => { while (spellBook.Prepared.Count < MagicConstants.SpellBarCount) { data.Prepared.Add(new PreparedSpellBar()); } }); } // fix learned spells foreach (string spellId in new[] { "arcane:analyze", "arcane:magicmissle", "arcane:enchant", "arcane:disenchant" }) { spellBook.LearnSpell(spellId, 0, true); } }
private static void OnAnalyze(object sender, AnalyzeEventArgs e) { var farmer = sender as Farmer; if (farmer != Game1.player) { return; } SpellBook spellBook = farmer.GetSpellBook(); List <string> spellsLearnt = new List <string>(); if (farmer.CurrentItem != null) { if (farmer.CurrentTool != null) { if (farmer.CurrentTool is StardewValley.Tools.Axe || farmer.CurrentTool is StardewValley.Tools.Pickaxe) { spellsLearnt.Add("toil:cleardebris"); } else if (farmer.CurrentTool is StardewValley.Tools.Hoe) { spellsLearnt.Add("toil:till"); } else if (farmer.CurrentTool is StardewValley.Tools.WateringCan) { spellsLearnt.Add("toil:water"); } } else if (farmer.CurrentItem is Boots) { spellsLearnt.Add("life:evac"); } else if (farmer.ActiveObject != null) { if (!farmer.ActiveObject.bigCraftable.Value) { int index = farmer.ActiveObject.ParentSheetIndex; if (index == 395) // Coffee { spellsLearnt.Add("life:haste"); } else if (index == 773) // Life elixir { spellsLearnt.Add("life:heal"); } else if (index == 86) // Earth crystal { spellsLearnt.Add("nature:shockwave"); } else if (index == 82) // Fire quartz { spellsLearnt.Add("elemental:fireball"); } else if (index == 161) // Ice Pip { spellsLearnt.Add("elemental:frostbolt"); } } } } foreach (var lightSource in farmer.currentLocation.sharedLights.Values) { if (Utility.distance(e.TargetX, lightSource.position.X, e.TargetY, lightSource.position.Y) < lightSource.radius.Value * Game1.tileSize) { spellsLearnt.Add("nature:lantern"); break; } } var tilePos = new Vector2(e.TargetX / Game1.tileSize, e.TargetY / Game1.tileSize); if (farmer.currentLocation.terrainFeatures.TryGetValue(tilePos, out TerrainFeature feature) && feature is HoeDirt dirt && dirt.crop != null) { spellsLearnt.Add("nature:tendrils"); } // TODO: Add proper tilesheet check var tile = farmer.currentLocation.map.GetLayer("Buildings").Tiles[(int)tilePos.X, (int)tilePos.Y]; if (tile != null && tile.TileIndex == 173) { spellsLearnt.Add("elemental:descend"); } if (farmer.currentLocation is Farm farm) { foreach (var clump in farm.resourceClumps) { if (clump.parentSheetIndex.Value == 622 && new Rectangle((int)clump.tile.Value.X, (int)clump.tile.Value.Y, clump.width.Value, clump.height.Value).Contains((int)tilePos.X, (int)tilePos.Y)) { spellsLearnt.Add("eldritch:meteor"); } } } if (farmer.currentLocation.doesTileHaveProperty((int)tilePos.X, (int)tilePos.Y, "Action", "Buildings") == "EvilShrineLeft") { spellsLearnt.Add("eldritch:lucksteal"); } if (farmer.currentLocation is StardewValley.Locations.MineShaft { mineLevel : 100 } ms&& ms.waterTiles[(int)tilePos.X, (int)tilePos.Y]) { spellsLearnt.Add("eldritch:bloodmana"); } for (int i = spellsLearnt.Count - 1; i >= 0; --i) { if (spellBook.KnowsSpell(spellsLearnt[i], 0)) { spellsLearnt.RemoveAt(i); } } if (spellsLearnt.Count > 0) { Game1.playSound("secret1"); foreach (string spell in spellsLearnt) { Log.Debug("Player learnt spell: " + spell); spellBook.LearnSpell(spell, 0, true); //Game1.drawObjectDialogue(Mod.instance.Helper.Translation.Get("spell.learn", new { spellName = Mod.instance.Helper.Translation.Get("spell." + spell + ".name") })); Game1.addHUDMessage(new HUDMessage(Mod.Instance.Helper.Translation.Get("spell.learn", new { spellName = SpellManager.Get(spell).GetTranslatedName() }))); } } // Temporary - 0.3.0 will add dungeons to get these bool knowsAll = true; foreach (string schoolId in School.GetSchoolList()) { var school = School.GetSchool(schoolId); bool knowsAllSchool = true; foreach (var spell in school.GetSpellsTier1()) { if (!spellBook.KnowsSpell(spell, 0)) { knowsAll = knowsAllSchool = false; break; } } foreach (var spell in school.GetSpellsTier2()) { if (!spellBook.KnowsSpell(spell, 0)) { knowsAll = knowsAllSchool = false; break; } } // Have to know all other spells for the arcane one if (schoolId == SchoolId.Arcane) { continue; } var ancientSpell = school.GetSpellsTier3()[0]; if (knowsAllSchool && !spellBook.KnowsSpell(ancientSpell, 0)) { Log.Debug("Player learnt ancient spell: " + ancientSpell); spellBook.LearnSpell(ancientSpell, 0, true); Game1.addHUDMessage(new HUDMessage(Mod.Instance.Helper.Translation.Get("spell.learn.ancient", new { spellName = ancientSpell.GetTranslatedName() }))); } } var rewindSpell = School.GetSchool(SchoolId.Arcane).GetSpellsTier3()[0]; if (knowsAll && !spellBook.KnowsSpell(rewindSpell, 0)) { Log.Debug("Player learnt ancient spell: " + rewindSpell); spellBook.LearnSpell(rewindSpell, 0, true); Game1.addHUDMessage(new HUDMessage(Mod.Instance.Helper.Translation.Get("spell.learn.ancient", new { spellName = rewindSpell.GetTranslatedName() }))); } }