diff --git a/CHANGELOG.md b/CHANGELOG.md index c1b74c21..5542efda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -58,6 +58,7 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin * Removed the config options `TileRectangleSizeThreshold` and `KickOnTileRectangleSizeThresholdBroken` because they are made obsolete by the new system, which will only allow valid rectangle sizes (at a maximum of only 4 by 4 tiles in 1.4.3.6). (@punchready) * Bumped Newtonsoft Json to 13.0.1. (@dependabot) * Allow the Cool Whip to apply `CoolWhipNPCDebuff` for `240` ticks, fixing abnormal NPC buff add rejects in Bouncer. (@drunderscore) +* Fixed Bouncer rejecting Explosive Bunny critter release when using the Bunny Cannon, if the player had since stopped selecting the Explosive Bunny. (@drunderscore) ## TShock 4.5.17 * Fixed duplicate characters (twins) after repeatedly logging in as the same character due to connection not being immediately closed during `NetHooks_NameCollision`. (@PotatoCider) diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs index 1fd7d6db..fb78510b 100644 --- a/TShockAPI/Bouncer.cs +++ b/TShockAPI/Bouncer.cs @@ -1899,14 +1899,48 @@ namespace TShockAPI return; } - // if released npc not from its item (from crafted packet) - // e.g. using bunny item to release golden bunny - if (args.Player.TPlayer.lastVisualizedSelectedItem.makeNPC != type && args.Player.TPlayer.lastVisualizedSelectedItem.placeStyle != style) + void rejectForCritterNotReleasedFromItem() { TShock.Log.ConsoleDebug("Bouncer / OnReleaseNPC released different critter from {0}", args.Player.Name); args.Player.Kick("Released critter was not from its item.", true); args.Handled = true; - return; + } + + // if released npc not from its item (from crafted packet) + // e.g. using bunny item to release golden bunny + if (args.Player.TPlayer.lastVisualizedSelectedItem.makeNPC != type || args.Player.TPlayer.lastVisualizedSelectedItem.placeStyle != style) + { + // If the critter is an Explosive Bunny, check if we've recently created an Explosive Bunny projectile. + // If we have, check if the critter we are trying to create is within range of the projectile + // If we have at least one of those, then this wasn't a crafted packet, but simply a delayed critter release from an + // Explosive Bunny projectile. + if (type == NPCID.ExplosiveBunny) + { + bool areAnyBunnyProjectilesInRange; + + lock (args.Player.RecentlyCreatedProjectiles) + { + areAnyBunnyProjectilesInRange = args.Player.RecentlyCreatedProjectiles.Any(projectile => + { + if (projectile.Type != ProjectileID.ExplosiveBunny) + return false; + + var projectileInstance = Main.projectile[projectile.Index]; + return projectileInstance.active && projectileInstance.WithinRange(new Vector2(args.X, args.Y), 32.0f); + }); + } + + if (!areAnyBunnyProjectilesInRange) + { + rejectForCritterNotReleasedFromItem(); + return; + } + } + else + { + rejectForCritterNotReleasedFromItem(); + return; + } } if (args.Player.IsBouncerThrottled())