protected static void Postfix(ref Tool __instance, ref List <Vector2> __result, Vector2 tileLocation, int power, Farmer who) { if (__instance.UpgradeLevel < Tool.copper) { return; } if (__instance is Axe || __instance is Pickaxe) { __result.Clear(); int radius = __instance is Axe ? _axeAffectedTilesRadii[Math.Min(power - 2, 4)] : _pickaxeAffectedTilesRadii[Math.Min(power - 2, 4)]; if (radius == 0) { return; } CircleTileGrid grid = new CircleTileGrid(tileLocation, radius); __result.AddRange(grid); } }
/// <summary>Spreads the effects of Axe and Pickaxe to an area around the player.</summary> /// <param name="origin">The center of the shockwave (i.e. the tool's tile location).</param> /// <param name="radii">Array of radii values at each charge level.</param> /// <param name="tool">The tool select by the player.</param> /// <param name="location">The current location.</param> /// <param name="who">The current player.</param> public void SpreadToolEffect(Tool tool, Vector2 origin, List <int> radii, float multiplier, GameLocation location, Farmer who) { int radius = radii[Math.Min(who.toolPower - 1, radii.Count() - 1)]; who.stamina -= (who.toolPower - (tool is Axe ? who.ForagingLevel : who.MiningLevel) * 0.1f) * (who.toolPower - 1) * multiplier; CircleTileGrid grid = new CircleTileGrid(origin, radius, excludeOrigin: true); foreach (Vector2 tile in grid) { TemporarilyFakeInteraction(() => { // face tile to avoid game skipping interaction GetRadialAdjacentTile(origin, tile, out Vector2 adjacentTile, out int facingDirection); who.Position = adjacentTile * Game1.tileSize; who.FacingDirection = facingDirection; // apply tool effects location.objects.TryGetValue(tile, out SObject tileObj); location.terrainFeatures.TryGetValue(tile, out TerrainFeature tileFeature); Apply(tile, tileObj, tileFeature, tool, location, who); }); } }
/// <summary>Patch for Blaster double coal chance + Demolitionist speed burst.</summary> private static void GameLocationExplodePostfix(ref GameLocation __instance, Vector2 tileLocation, int radius, Farmer who) { try { var isBlaster = Utility.SpecificPlayerHasProfession("Blaster", who); var isDemolitionist = Utility.SpecificPlayerHasProfession("Demolitionist", who); if (!isBlaster && !isDemolitionist) { return; } var grid = new CircleTileGrid(tileLocation, radius); foreach (var tile in grid) { if (!__instance.objects.TryGetValue(tile, out var tileObj) || !Utility.IsStone(tileObj)) { continue; } if (isBlaster) { if (!__instance.Name.StartsWith("UndergroundMine")) { var chanceModifier = who.DailyLuck / 2.0 + who.LuckLevel * 0.001 + who.MiningLevel * 0.005; var r = new Random((int)tile.X * 1000 + (int)tile.Y + (int)Game1.stats.DaysPlayed + (int)Game1.uniqueIDForThisGame / 2); if (tileObj.ParentSheetIndex == 343 || tileObj.ParentSheetIndex == 450) { if (r.NextDouble() < 0.035 && Game1.stats.DaysPlayed > 1) { Game1.createObjectDebris(SObject.coal, (int)tile.X, (int)tile.Y, who.UniqueMultiplayerID, __instance); } } else if (r.NextDouble() < 0.05 * (1.0 + chanceModifier)) { Game1.createObjectDebris(SObject.coal, (int)tile.X, (int)tile.Y, who.UniqueMultiplayerID, __instance); } } else { var r = new Random((int)tile.X * 1000 + (int)tile.Y + ((MineShaft)__instance).mineLevel + (int)Game1.uniqueIDForThisGame / 2); if (r.NextDouble() < 0.25) { Game1.createObjectDebris(382, (int)tile.X, (int)tile.Y, who.UniqueMultiplayerID, __instance); AwesomeProfessions.Reflection.GetField <Multiplayer>(typeof(Game1), "multiplayer") .GetValue() .broadcastSprites(__instance, new TemporaryAnimatedSprite(25, new Vector2(tile.X * Game1.tileSize, tile.Y * Game1.tileSize), Color.White, 8, Game1.random.NextDouble() < 0.5, 80f, 0, -1, -1f, 128)); } } } if (isDemolitionist && Game1.random.NextDouble() < 0.20) { if (Utility.ResourceFromStoneId.TryGetValue(tileObj.ParentSheetIndex, out var resourceIndex)) { Game1.createObjectDebris(resourceIndex, (int)tile.X, (int)tile.Y, who.UniqueMultiplayerID, __instance); } else { switch (tileObj.ParentSheetIndex) { case 44: // gem node { Game1.createObjectDebris(Game1.random.Next(1, 8) * 2, (int)tile.X, (int)tile.Y, who.UniqueMultiplayerID, __instance); break; } case 46: // mystic stone { switch (Game1.random.NextDouble()) { case < 0.25: Game1.createObjectDebris(74, (int)tile.X, (int)tile.Y, who.UniqueMultiplayerID, __instance); // drop prismatic shard break; case < 0.6: Game1.createObjectDebris(765, (int)tile.X, (int)tile.Y, who.UniqueMultiplayerID, __instance); // drop iridium ore break; default: Game1.createObjectDebris(764, (int)tile.X, (int)tile.Y, who.UniqueMultiplayerID, __instance); // drop gold ore break; } break; } default: { if (845 <= tileObj.ParentSheetIndex & tileObj.ParentSheetIndex <= 847 && Game1.random.NextDouble() < 0.005) { Game1.createObjectDebris(827, (int)tile.X, (int)tile.Y, who.UniqueMultiplayerID, __instance); } break; } } } } } if (!who.IsLocalPlayer || !isDemolitionist) { return; } // get excited speed buff var distanceFromEpicenter = (int)(tileLocation - who.getTileLocation()).Length(); if (distanceFromEpicenter < radius * 2 + 1) { AwesomeProfessions.demolitionistBuffMagnitude = 4; } if (distanceFromEpicenter < radius + 1) { AwesomeProfessions.demolitionistBuffMagnitude += 2; } } catch (Exception ex) { Monitor.Log($"Failed in {nameof(GameLocationExplodePostfix)}:\n{ex}"); } }