diff --git a/CHANGELOG.md b/CHANGELOG.md index 1505337c..aacf4297 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,8 @@ This is the rolling changelog for TShock for Terraria. Use past tense when addin * Update for OTAPI 2.0.0.36 and Terraria 1.4.0.4. (@hakusaro, @Patrikkk, @DeathCradle) * Fixed /wind command. (@AxeelAnder) * Fixed NPC buff bouncer. (@AxeelAnder) -* Fixed lava, wet, and honey bombs. (@Olink) +* Fixed players are unable to remove an NPC. Change `byte NPCHomeChangeEventArgs.Homeless` to `HouseholdStatus NPCHomeChangeEventArgs.HouseholdStatus`. (@AxeelAnder) +* Fixed lava, wet, and honey bombs/grenades/rockets. (@Olink) ## TShock 4.4.0 (Pre-release 7 (Entangled)) * Fixed bed spawn issues when trying to remove spawn point in SSC. (@Olink) diff --git a/TShockAPI/Bouncer.cs b/TShockAPI/Bouncer.cs index 7dde6776..d7cf65e0 100644 --- a/TShockAPI/Bouncer.cs +++ b/TShockAPI/Bouncer.cs @@ -1290,15 +1290,21 @@ namespace TShockAPI } bool wasThereABombNearby = false; -// The +/- 16 is compensation for maximum detonation distance, but it might be possible to drop to 5 and be conservative lock (args.Player.RecentlyCreatedProjectiles) { - var keys = projectileCreatesLiquid.Where(k => k.Value == type).Select(k => k.Key); - var recentBombs = args.Player.RecentlyCreatedProjectiles.Where(p => keys.Contains(Main.projectile[p.Index].type)); - wasThereABombNearby = recentBombs.Any(r => (args.TileX > (Main.projectile[r.Index].position.X / 16.0f) - TShock.Config.BombExplosionRadius - && args.TileX < (Main.projectile[r.Index].position.X / 16.0f) + TShock.Config.BombExplosionRadius) - && (args.TileY > (Main.projectile[r.Index].position.Y / 16.0f) - TShock.Config.BombExplosionRadius - && args.TileY < (Main.projectile[r.Index].position.Y / 16.0f) + TShock.Config.BombExplosionRadius)); + IEnumerable projectileTypesThatPerformThisOperation; + if (amount > 0) //handle the projectiles that create fluid. + { + projectileTypesThatPerformThisOperation = projectileCreatesLiquid.Where(k => k.Value == type).Select(k => k.Key); + } + else //handle the scenario where we are removing liquid + { + projectileTypesThatPerformThisOperation = projectileCreatesLiquid.Where(k => k.Value == LiquidType.Removal).Select(k => k.Key); + } + + var recentBombs = args.Player.RecentlyCreatedProjectiles.Where(p => projectileTypesThatPerformThisOperation.Contains(Main.projectile[p.Index].type)); + wasThereABombNearby = recentBombs.Any(r => Math.Abs(args.TileX - (Main.projectile[r.Index].position.X / 16.0f)) < TShock.Config.BombExplosionRadius + && Math.Abs(args.TileY - (Main.projectile[r.Index].position.Y / 16.0f)) < TShock.Config.BombExplosionRadius); } // Liquid anti-cheat @@ -1558,7 +1564,6 @@ namespace TShockAPI int id = args.ID; short x = args.X; short y = args.Y; - byte homeless = args.Homeless; if (!args.Player.HasBuildPermission(x, y)) { @@ -1569,7 +1574,8 @@ namespace TShockAPI return; } - if (!args.Player.IsInRange(x, y)) + // When kicking out an npc, x and y in args are 0, we shouldn't check range at this case + if (args.HouseholdStatus != HouseholdStatus.Homeless && !args.Player.IsInRange(x, y)) { args.Player.SendData(PacketTypes.UpdateNPCHome, "", id, Main.npc[id].homeTileX, Main.npc[id].homeTileY, Convert.ToByte(Main.npc[id].homeless)); diff --git a/TShockAPI/GetDataHandlers.cs b/TShockAPI/GetDataHandlers.cs index 7d76a0d4..0e426783 100644 --- a/TShockAPI/GetDataHandlers.cs +++ b/TShockAPI/GetDataHandlers.cs @@ -125,7 +125,7 @@ namespace TShockAPI { PacketTypes.NpcSpecial, HandleSpecial }, { PacketTypes.NpcAddBuff, HandleNPCAddBuff }, { PacketTypes.PlayerAddBuff, HandlePlayerAddBuff }, - { PacketTypes.UpdateNPCHome, UpdateNPCHome }, + { PacketTypes.UpdateNPCHome, HandleUpdateNPCHome }, { PacketTypes.SpawnBossorInvasion, HandleSpawnBoss }, { PacketTypes.PaintTile, HandlePaintTile }, { PacketTypes.PaintWall, HandlePaintWall }, @@ -1141,7 +1141,8 @@ namespace TShockAPI { Water = 0, Lava = 1, - Honey = 2 + Honey = 2, + Removal = 255 //@Olink: lets hope they never invent 255 fluids or decide to also use this :( } /// @@ -1307,6 +1308,13 @@ namespace TShockAPI return args.Handled; } + public enum HouseholdStatus : byte + { + None = 0, + Homeless = 1, + HasRoom = 2, + } + /// /// For use in a NPCHome event /// @@ -1325,15 +1333,15 @@ namespace TShockAPI /// public short Y { get; set; } /// - /// ByteBool homeless + /// HouseholdStatus of the NPC /// - public byte Homeless { get; set; } + public HouseholdStatus HouseholdStatus { get; set; } } /// /// NPCHome - Called when an NPC's home is changed /// public static HandlerList NPCHome = new HandlerList(); - private static bool OnUpdateNPCHome(TSPlayer player, MemoryStream data, short id, short x, short y, byte homeless) + private static bool OnUpdateNPCHome(TSPlayer player, MemoryStream data, short id, short x, short y, byte houseHoldStatus) { if (NPCHome == null) return false; @@ -1345,7 +1353,7 @@ namespace TShockAPI ID = id, X = x, Y = y, - Homeless = homeless, + HouseholdStatus = (HouseholdStatus) houseHoldStatus, }; NPCHome.Invoke(null, args); return args.Handled; @@ -2322,18 +2330,17 @@ namespace TShockAPI if (OnNewProjectile(args.Data, ident, pos, vel, knockback, dmg, owner, type, index, args.Player)) return true; - if (projectileCreatesLiquid.ContainsKey(type)) + lock (args.Player.RecentlyCreatedProjectiles) { - lock (args.Player.RecentlyCreatedProjectiles) + if (!args.Player.RecentlyCreatedProjectiles.Any(p => p.Index == index)) { - args.Player.RecentlyCreatedProjectiles.Add(new ProjectileStruct() + args.Player.RecentlyCreatedProjectiles.Add(new GetDataHandlers.ProjectileStruct() { - Index = ident, + Index = index, CreatedAt = DateTime.Now }); } } - return false; } @@ -2779,14 +2786,14 @@ namespace TShockAPI return true; } - private static bool UpdateNPCHome(GetDataHandlerArgs args) + private static bool HandleUpdateNPCHome(GetDataHandlerArgs args) { var id = args.Data.ReadInt16(); var x = args.Data.ReadInt16(); var y = args.Data.ReadInt16(); - var homeless = args.Data.ReadInt8(); + var householdStatus = args.Data.ReadInt8(); - if (OnUpdateNPCHome(args.Player, args.Data, id, x, y, homeless)) + if (OnUpdateNPCHome(args.Player, args.Data, id, x, y, householdStatus)) return true; if (!args.Player.HasPermission(Permissions.movenpc)) @@ -3466,10 +3473,24 @@ namespace TShockAPI { {ProjectileID.LavaBomb, LiquidType.Lava}, {ProjectileID.LavaRocket, LiquidType.Lava }, + {ProjectileID.LavaGrenade, LiquidType.Lava }, + {ProjectileID.LavaMine, LiquidType.Lava }, + //{ProjectileID.LavaSnowmanRocket, LiquidType.Lava }, //these require additional checks. {ProjectileID.WetBomb, LiquidType.Water}, {ProjectileID.WetRocket, LiquidType.Water }, + {ProjectileID.WetGrenade, LiquidType.Water}, + {ProjectileID.WetMine, LiquidType.Water}, + //{ProjectileID.WetSnowmanRocket, LiquidType.Water}, //these require additional checks. {ProjectileID.HoneyBomb, LiquidType.Honey}, - {ProjectileID.HoneyRocket, LiquidType.Honey } + {ProjectileID.HoneyRocket, LiquidType.Honey }, + {ProjectileID.HoneyGrenade, LiquidType.Honey }, + {ProjectileID.HoneyMine, LiquidType.Honey }, + //{ProjectileID.HoneySnowmanRocket, LiquidType.Honey }, //these require additional checks. + {ProjectileID.DryBomb, LiquidType.Removal }, + {ProjectileID.DryRocket, LiquidType.Removal }, + {ProjectileID.DryGrenade, LiquidType.Removal }, + {ProjectileID.DryMine, LiquidType.Removal }, + //{ProjectileID.DrySnowmanRocket, LiquidType.Removal } //these require additional checks. }; internal static Dictionary ropeCoilPlacements = new Dictionary diff --git a/TShockAPI/TShock.cs b/TShockAPI/TShock.cs index 6f685654..6e0ed31c 100644 --- a/TShockAPI/TShock.cs +++ b/TShockAPI/TShock.cs @@ -1622,6 +1622,32 @@ namespace TShockAPI e.Handled = true; return; } + } else if (e.MsgId == PacketTypes.ProjectileNew) + { + if (e.number >= 0 && e.number < Main.projectile.Length) + { + var projectile = Main.projectile[e.number]; + if (projectile.active && projectile.owner >= 0 && GetDataHandlers.projectileCreatesLiquid.ContainsKey(projectile.type)) + { + var player = Players[projectile.owner]; + if (player != null) + { + if (player.RecentlyCreatedProjectiles.Any(p => p.Index == e.number && p.Killed)) + { + player.RecentlyCreatedProjectiles.RemoveAll(p => p.Index == e.number && p.Killed); + } + + if (!player.RecentlyCreatedProjectiles.Any(p => p.Index == e.number)) { + player.RecentlyCreatedProjectiles.Add(new GetDataHandlers.ProjectileStruct() + { + Index = e.number, + CreatedAt = DateTime.Now + }); + } + } + } + } + } }