diff --git a/TODO.txt b/TODO.txt index e57deba06..43e8867aa 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,5 +1,5 @@ -1.20.1-1.3.0-beta-8 +1.20.1-1.3.0-beta-9 [✔] Done and tested [🟡] Partially done and/or needs testing @@ -22,21 +22,41 @@ New Heroes Bugfixes -------- -[✔] Heroes can no longer pick up weapons and armour -[✔] Zombies summoned by necromancers no longer drop their weapons on death -[✔] Fixed the player defeated announcement text -[✔] Fixed grunts and villagers dealing too much damage to other units -[✔] Changing /gamerule groundYLevel no longer moves players that aren't in RTS cam (this was killing survival players!) - - This also happened whenever another player logged in -[✔] Destroying a farm now destroys all of its crop blocks +[✔] Campfires no longer do excessive damage +[✔] Creative players out of RTS cam are no longer locked into flying and noclip +[✔] Fixed the blizzard sound effect still continuing sometimes after the spell ends +[✔] Building a bridge overlapping resource blocks no longer makes those resources ungatherable +[✔] Libraries no longer try to autocast Vigor enchantments on Evokers that already have it Quality of Life --------------- -[✔] The Royal Guard and Enchanter now have the collision size of regular illagers (visual size unchanged) +[✔] Warped Nylium now counts as nether terrain for piglins Balance ------- -[✔] All damage dealt to huntable animals by military units is halved +[✔] Wretched Wraith bonus armour during blizzard increased from 30% to 50% +[✔] Wretched Wraith Frostblink mana cost reduced from 40 to 30, and cooldown reduced from (20,16,12) to (20,15,10) +[✔] The Wretched Wraith can no longer cause or receive knockback +[✔] Spider resource cost reduced from (90 food, 25 wood, 25 ore) to (80 food, 20 wood, 20 ore) +[✔] Spiders now glide smoothly up 1-block high steps without having to jump or climb + +[✔] Piglin Merchant TNT Throw range increased from 12 to 14 +[✔] Marauder Cleaving Flail damage to secondary targets reduced from 7 to 5 and stun from 1.5s to 1s +[✔] Piglin units lose their magma block immunity if they are actively on fire +[✔] Wildfire Molten Bomb no longer deals explosion damage (this was actually unintended) +[✔] Scorching gaze no longer causes 2x magma and fire block damage, but fire tick damage is raised to 3x +[✔] Blaze firewalls can now create fire blocks over snow +[✔] Fire Resistance now only affects Wither Skeletons and has been moved to the wither shrine +[✔] Fire Resistance cost reduced from (200 wood, 200 ore, 100s) to (125 wood, 125 ore, 60s) +[✔] Wither Skeletons now prioritise enemies that already have wither on them when autoattacking +[✔] Wither Skeletons now have 50% knockback resistance + +[✔] Witch Water Potions extinguish radius increased from 1 block to 2 blocks +[✔] Raised water potion cooldown from 5s to 8s +[✔] Witch magic resistance reduced from 85% to 60% +[✔] Iron Golem HP reduced from 140 to 120, but ranged armour increased from 20% to 40% + +[✔] Magic resistance now also reduces fire tick damage Languages --------- \ No newline at end of file diff --git a/build.gradle b/build.gradle index a5b65ee36..e8e33851b 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ apply plugin: 'maven-publish' apply plugin: 'org.spongepowered.mixin' apply plugin: 'org.parchmentmc.librarian.forgegradle' -version = '1.3.0-beta-8' +version = '1.3.0-beta-9' group = 'com.solegendary.reignofnether' // http://maven.apache.org/guides/mini/guide-naming-conventions.html archivesBaseName = 'reignofnether' diff --git a/src/main/java/com/solegendary/reignofnether/ReignOfNether.java b/src/main/java/com/solegendary/reignofnether/ReignOfNether.java index fd6a34176..e7a9cf3c5 100644 --- a/src/main/java/com/solegendary/reignofnether/ReignOfNether.java +++ b/src/main/java/com/solegendary/reignofnether/ReignOfNether.java @@ -54,7 +54,7 @@ public class ReignOfNether { public static final Logger LOGGER = LogManager.getLogger(); public static final String MOD_ID = "reignofnether"; - public static final String VERSION_STRING = "1.3.0-beta-8"; + public static final String VERSION_STRING = "1.3.0-beta-9"; // Fields from ClientReset public static final Field handshakeField; diff --git a/src/main/java/com/solegendary/reignofnether/ability/abilities/EnchantVigor.java b/src/main/java/com/solegendary/reignofnether/ability/abilities/EnchantVigor.java index 0be9c28d0..03b758cab 100644 --- a/src/main/java/com/solegendary/reignofnether/ability/abilities/EnchantVigor.java +++ b/src/main/java/com/solegendary/reignofnether/ability/abilities/EnchantVigor.java @@ -20,6 +20,7 @@ import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.BowItem; import net.minecraft.world.item.enchantment.Enchantment; +import net.minecraft.world.item.enchantment.Enchantments; import java.util.List; @@ -75,4 +76,13 @@ public AbilityButton getButton(Keybinding hotkey, BuildingPlacement placement) { public boolean isCorrectUnitAndEquipment(LivingEntity entity) { return entity instanceof EvokerUnit && entity.getItemBySlot(equipmentSlot).getItem() instanceof BowItem; } + + @Override + public Enchantment getMutuallyExclusiveEnchant(LivingEntity entity) { + for (Enchantment enchantment : entity.getItemBySlot(equipmentSlot).getAllEnchantments().keySet()) { + if (enchantment == Enchantments.MULTISHOT || enchantment == getEnchantment()) + return enchantment; + } + return null; + } } diff --git a/src/main/java/com/solegendary/reignofnether/ability/abilities/ThrowWaterPotion.java b/src/main/java/com/solegendary/reignofnether/ability/abilities/ThrowWaterPotion.java index 3fb7b6e53..5ff43c959 100644 --- a/src/main/java/com/solegendary/reignofnether/ability/abilities/ThrowWaterPotion.java +++ b/src/main/java/com/solegendary/reignofnether/ability/abilities/ThrowWaterPotion.java @@ -26,11 +26,10 @@ public class ThrowWaterPotion extends Ability { - public static final int CD_MAX_SECONDS = 5; + public static final int CD_MAX_SECONDS = 8; public final Potion potion = Potions.WATER; - //TODO Fix potionThrowRange for Witches gathering on a building public ThrowWaterPotion(int potionThrowRange) { super( UnitAction.THROW_WATER_POTION, diff --git a/src/main/java/com/solegendary/reignofnether/ability/heroAbilities/piglinmerchant/FancyFeast.java b/src/main/java/com/solegendary/reignofnether/ability/heroAbilities/piglinmerchant/FancyFeast.java index 876507e51..9b2ff95e8 100644 --- a/src/main/java/com/solegendary/reignofnether/ability/heroAbilities/piglinmerchant/FancyFeast.java +++ b/src/main/java/com/solegendary/reignofnether/ability/heroAbilities/piglinmerchant/FancyFeast.java @@ -125,9 +125,9 @@ public List getRankUpTooltipLines(HeroUnit hero) { fcs(I18n.get("abilities.reignofnether.fancy_feast.tooltip1")), fcs(I18n.get("abilities.reignofnether.fancy_feast.tooltip2", BASE_ITEMS, BONUS_ITEMS_PER_100_RESOURCES, MANA_REFUND_PER_100_RESOURCES)), fcs(""), - fcs(I18n.get("abilities.reignofnether.fancy_feast.rank1"), getRank(hero) == 0), - fcs(I18n.get("abilities.reignofnether.fancy_feast.rank2"), getRank(hero) == 1), - fcs(I18n.get("abilities.reignofnether.fancy_feast.rank3"), getRank(hero) == 2) + fcs(I18n.get("abilities.reignofnether.fancy_feast.rank1", HEALTH_PER_BREAD), getRank(hero) == 0), + fcs(I18n.get("abilities.reignofnether.fancy_feast.rank2", HEALTH_PER_CHICKEN), getRank(hero) == 1), + fcs(I18n.get("abilities.reignofnether.fancy_feast.rank3", HEALTH_PER_BEEF), getRank(hero) == 2) ); } diff --git a/src/main/java/com/solegendary/reignofnether/ability/heroAbilities/piglinmerchant/ThrowTNT.java b/src/main/java/com/solegendary/reignofnether/ability/heroAbilities/piglinmerchant/ThrowTNT.java index 0de80c4b2..85fc37ba7 100644 --- a/src/main/java/com/solegendary/reignofnether/ability/heroAbilities/piglinmerchant/ThrowTNT.java +++ b/src/main/java/com/solegendary/reignofnether/ability/heroAbilities/piglinmerchant/ThrowTNT.java @@ -30,7 +30,7 @@ public class ThrowTNT extends HeroAbility { - public static final int RANGE = 12; + public static final int RANGE = 14; public float explosionPower = 2; // for some reason 0 and negative cooldown values cause this to stop working diff --git a/src/main/java/com/solegendary/reignofnether/ability/heroAbilities/wildfire/ScorchingGaze.java b/src/main/java/com/solegendary/reignofnether/ability/heroAbilities/wildfire/ScorchingGaze.java index b0498c1ac..715fccc57 100644 --- a/src/main/java/com/solegendary/reignofnether/ability/heroAbilities/wildfire/ScorchingGaze.java +++ b/src/main/java/com/solegendary/reignofnether/ability/heroAbilities/wildfire/ScorchingGaze.java @@ -31,6 +31,9 @@ public class ScorchingGaze extends HeroAbility { public static final int DURATION_RANK_3 = 14; public int durationSeconds = DURATION_RANK_1; + public static final int MIN_MAGMA_DURATION = 200; + public static final int MAX_MAGMA_DURATION = 300; + public ScorchingGaze() { super(3, 50, UnitAction.SCORCHING_GAZE, 30 * ResourceCost.TICKS_PER_SECOND, RANGE, 0, true); } diff --git a/src/main/java/com/solegendary/reignofnether/ability/heroAbilities/wretchedwraith/FrostBlink.java b/src/main/java/com/solegendary/reignofnether/ability/heroAbilities/wretchedwraith/FrostBlink.java index ba5ff31fa..d7668585d 100644 --- a/src/main/java/com/solegendary/reignofnether/ability/heroAbilities/wretchedwraith/FrostBlink.java +++ b/src/main/java/com/solegendary/reignofnether/ability/heroAbilities/wretchedwraith/FrostBlink.java @@ -32,13 +32,13 @@ public class FrostBlink extends HeroAbility { public static final int RANGE_RANK_3 = 12; public static final int CD_RANK_1 = 20; - public static final int CD_RANK_2 = 16; - public static final int CD_RANK_3 = 12; + public static final int CD_RANK_2 = 15; + public static final int CD_RANK_3 = 10; public static final int RADIUS = 3; public FrostBlink() { - super(3, 40, UnitAction.FROSTBLINK, CD_RANK_1 * ResourceCost.TICKS_PER_SECOND, RANGE_RANK_1, RADIUS, false); + super(3, 30, UnitAction.FROSTBLINK, CD_RANK_1 * ResourceCost.TICKS_PER_SECOND, RANGE_RANK_1, RADIUS, false); } @Override diff --git a/src/main/java/com/solegendary/reignofnether/blocks/WalkableMagmaBlock.java b/src/main/java/com/solegendary/reignofnether/blocks/WalkableMagmaBlock.java index 6866398ba..504c5c3fd 100644 --- a/src/main/java/com/solegendary/reignofnether/blocks/WalkableMagmaBlock.java +++ b/src/main/java/com/solegendary/reignofnether/blocks/WalkableMagmaBlock.java @@ -23,7 +23,6 @@ import net.minecraft.world.level.block.state.BlockState; public class WalkableMagmaBlock extends Block { - private static final int BUBBLE_COLUMN_CHECK_DELAY = 20; public static final int DAMAGE_DELAY = 20; // higher == damage less often public static final int DAMAGE = 3; @@ -32,7 +31,7 @@ public WalkableMagmaBlock(BlockBehaviour.Properties pProperties) { } public void stepOn(Level pLevel, BlockPos pPos, BlockState pState, Entity pEntity) { - boolean isPiglinFaction = pEntity instanceof Unit unit && unit.getFaction() == Faction.PIGLINS; + boolean isPiglinFaction = pEntity instanceof Unit unit && unit.getFaction() == Faction.PIGLINS && !pEntity.isOnFire(); boolean isDamageTick = pEntity.tickCount % DAMAGE_DELAY == 0; if (!pEntity.isSteppingCarefully() && diff --git a/src/main/java/com/solegendary/reignofnether/building/BuildingClientEvents.java b/src/main/java/com/solegendary/reignofnether/building/BuildingClientEvents.java index 5e55cb629..6b650a3ba 100644 --- a/src/main/java/com/solegendary/reignofnether/building/BuildingClientEvents.java +++ b/src/main/java/com/solegendary/reignofnether/building/BuildingClientEvents.java @@ -10,6 +10,7 @@ import com.solegendary.reignofnether.building.buildings.piglins.CentralPortal; import com.solegendary.reignofnether.building.buildings.piglins.PortalBasic; import com.solegendary.reignofnether.building.buildings.placements.BeaconPlacement; +import com.solegendary.reignofnether.building.buildings.placements.BridgePlacement; import com.solegendary.reignofnether.building.buildings.placements.PortalPlacement; import com.solegendary.reignofnether.building.buildings.placements.ProductionPlacement; import com.solegendary.reignofnether.building.buildings.shared.AbstractBridge; @@ -28,6 +29,9 @@ import com.solegendary.reignofnether.orthoview.OrthoviewClientEvents; import com.solegendary.reignofnether.player.PlayerColors; import com.solegendary.reignofnether.research.ResearchClient; +import com.solegendary.reignofnether.resources.BlockUtils; +import com.solegendary.reignofnether.resources.ResourceName; +import com.solegendary.reignofnether.resources.ResourceSources; import com.solegendary.reignofnether.sandbox.SandboxClientEvents; import com.solegendary.reignofnether.tutorial.TutorialClientEvents; import com.solegendary.reignofnether.unit.Relationship; @@ -123,8 +127,12 @@ public static int getTotalPopulationSupply(String playerName) { // can only be one preselected building as you can't box-select them like units public static BuildingPlacement getPreselectedBuilding() { + BlockPos preSelBp = CursorClientEvents.getPreselectedBlockPos(); for (BuildingPlacement building : buildings) - if (building.isPosInsideBuilding(CursorClientEvents.getPreselectedBlockPos())) { + if (building.isPosInsideBuilding(preSelBp)) { + if (building instanceof BridgePlacement && ResourceSources.getBlockResourceName(preSelBp, MC.level) != ResourceName.NONE) { + return null; + } return building; } return null; diff --git a/src/main/java/com/solegendary/reignofnether/building/BuildingUtils.java b/src/main/java/com/solegendary/reignofnether/building/BuildingUtils.java index 5b82e420d..903078b2e 100644 --- a/src/main/java/com/solegendary/reignofnether/building/BuildingUtils.java +++ b/src/main/java/com/solegendary/reignofnether/building/BuildingUtils.java @@ -6,6 +6,7 @@ import com.solegendary.reignofnether.building.buildings.monsters.Stronghold; import com.solegendary.reignofnether.building.buildings.piglins.Fortress; import com.solegendary.reignofnether.building.buildings.placements.BeaconPlacement; +import com.solegendary.reignofnether.building.buildings.placements.BridgePlacement; import com.solegendary.reignofnether.building.buildings.placements.SculkCatalystPlacement; import com.solegendary.reignofnether.building.buildings.shared.AbstractBridge; import com.solegendary.reignofnether.building.buildings.villagers.Castle; @@ -261,6 +262,19 @@ public static boolean isPosInsideAnyBuilding(boolean isClientSide, BlockPos bp) return false; } + public static boolean isPosInsideAnyNonBridgeBuilding(boolean isClientSide, BlockPos bp) { + List buildings; + if (isClientSide) + buildings = BuildingClientEvents.getBuildings(); + else + buildings = BuildingServerEvents.getBuildings(); + + for (BuildingPlacement building : buildings) + if (!(building instanceof BridgePlacement) && building.isPosInsideBuilding(bp)) + return true; + return false; + } + @Nullable public static BuildingPlacement findClosestBuilding(boolean isClientSide, Vec3 pos, Predicate condition) { List buildings; diff --git a/src/main/java/com/solegendary/reignofnether/building/buildings/piglins/FlameSanctuary.java b/src/main/java/com/solegendary/reignofnether/building/buildings/piglins/FlameSanctuary.java index 196af1de4..f2bf7699f 100644 --- a/src/main/java/com/solegendary/reignofnether/building/buildings/piglins/FlameSanctuary.java +++ b/src/main/java/com/solegendary/reignofnether/building/buildings/piglins/FlameSanctuary.java @@ -47,7 +47,6 @@ public FlameSanctuary() { this.explodeChance = 0.2f; this.productions.add(ProductionItems.RESEARCH_BLAZE_FIREWALL, Keybindings.keyQ); - this.productions.add(ProductionItems.RESEARCH_FIRE_RESISTANCE, Keybindings.keyW); } public Faction getFaction() {return Faction.PIGLINS;} diff --git a/src/main/java/com/solegendary/reignofnether/building/buildings/piglins/WitherShrine.java b/src/main/java/com/solegendary/reignofnether/building/buildings/piglins/WitherShrine.java index 925f88378..aee8140bc 100644 --- a/src/main/java/com/solegendary/reignofnether/building/buildings/piglins/WitherShrine.java +++ b/src/main/java/com/solegendary/reignofnether/building/buildings/piglins/WitherShrine.java @@ -39,6 +39,7 @@ public WitherShrine() { this.explodeChance = 0.2f; this.productions.add(ProductionItems.RESEARCH_WITHER_CLOUDS, Keybindings.keyQ); + this.productions.add(ProductionItems.RESEARCH_FIRE_RESISTANCE, Keybindings.keyW); } public Faction getFaction() {return Faction.PIGLINS;} diff --git a/src/main/java/com/solegendary/reignofnether/config/ReignOfNetherCommonConfigs.java b/src/main/java/com/solegendary/reignofnether/config/ReignOfNetherCommonConfigs.java index 5171ec8a2..e75b386a6 100644 --- a/src/main/java/com/solegendary/reignofnether/config/ReignOfNetherCommonConfigs.java +++ b/src/main/java/com/solegendary/reignofnether/config/ReignOfNetherCommonConfigs.java @@ -183,8 +183,8 @@ public static class UnitCosts implements Costs { public static final ResourceCostConfigEntry BOGGED = ResourceCostConfigEntry.Unit(50,45,0,18,1, ResourceCosts.BOGGED, "Bogged Config"); public static final ResourceCostConfigEntry HUSK = ResourceCostConfigEntry.Unit(75,0,0,18,1, ResourceCosts.HUSK, "Husk Config"); public static final ResourceCostConfigEntry DROWNED = ResourceCostConfigEntry.Unit(75,0,0,18,1, ResourceCosts.DROWNED, "Drowned Config"); - public static final ResourceCostConfigEntry SPIDER = ResourceCostConfigEntry.Unit(90,25,25,25,2, ResourceCosts.SPIDER, "Spider Config"); - public static final ResourceCostConfigEntry POISON_SPIDER = ResourceCostConfigEntry.Unit(90,25,25,25,2, ResourceCosts.POISON_SPIDER, "Poison Spider Config"); + public static final ResourceCostConfigEntry SPIDER = ResourceCostConfigEntry.Unit(80,20,20,25,2, ResourceCosts.SPIDER, "Spider Config"); + public static final ResourceCostConfigEntry POISON_SPIDER = ResourceCostConfigEntry.Unit(80,20,20,25,2, ResourceCosts.POISON_SPIDER, "Poison Spider Config"); public static final ResourceCostConfigEntry SLIME = ResourceCostConfigEntry.Unit(40,40,40,25,2, ResourceCosts.SLIME, "Slime Config"); public static final ResourceCostConfigEntry WARDEN = ResourceCostConfigEntry.Unit(275,0,125,50,5, ResourceCosts.WARDEN, "Warden Config"); public static final ResourceCostConfigEntry NECROMANCER = ResourceCostConfigEntry.Unit(0,0,0,30, 5, ResourceCosts.NECROMANCER, "Necromancer Config"); @@ -304,7 +304,7 @@ public static class ResearchCosts implements Costs { public static final ResourceCostConfigEntry RESEARCH_HEAVY_TRIDENTS = ResourceCostConfigEntry.Research(0, 300, 300, 150, ResourceCosts.RESEARCH_HEAVY_TRIDENTS, "Heavy Tridents Research Config"); public static final ResourceCostConfigEntry RESEARCH_CLEAVING_FLAILS = ResourceCostConfigEntry.Research(0, 350, 350, 160, ResourceCosts.RESEARCH_CLEAVING_FLAILS, "Cleaving Flails Research Config"); public static final ResourceCostConfigEntry RESEARCH_BLAZE_FIRE_WALL = ResourceCostConfigEntry.Research(400, 0, 300, 150, ResourceCosts.RESEARCH_BLAZE_FIRE_WALL, "Blaze Fire Wall Research Config"); - public static final ResourceCostConfigEntry RESEARCH_FIRE_RESISTANCE = ResourceCostConfigEntry.Research(0, 200, 200, 100, ResourceCosts.RESEARCH_FIRE_RESISTANCE, "Fire Resistance Research Config"); + public static final ResourceCostConfigEntry RESEARCH_FIRE_RESISTANCE = ResourceCostConfigEntry.Research(0, 125, 125, 60, ResourceCosts.RESEARCH_FIRE_RESISTANCE, "Fire Resistance Research Config"); public static final ResourceCostConfigEntry RESEARCH_WITHER_CLOUDS = ResourceCostConfigEntry.Research(250, 0, 350, 150, ResourceCosts.RESEARCH_WITHER_CLOUDS, "Wither Clouds Research Config"); public static final ResourceCostConfigEntry RESEARCH_BLOODLUST = ResourceCostConfigEntry.Research(250, 250, 250, 150, ResourceCosts.RESEARCH_BLOODLUST, "Bloodlust Research Config"); public static final ResourceCostConfigEntry RESEARCH_ADVANCED_PORTALS = ResourceCostConfigEntry.Research(0, 300, 300, 150, ResourceCosts.RESEARCH_ADVANCED_PORTALS, "Advanced Portals Research Config"); diff --git a/src/main/java/com/solegendary/reignofnether/entities/BlazeUnitFireball.java b/src/main/java/com/solegendary/reignofnether/entities/BlazeUnitFireball.java index b3eae8f50..66f0176de 100644 --- a/src/main/java/com/solegendary/reignofnether/entities/BlazeUnitFireball.java +++ b/src/main/java/com/solegendary/reignofnether/entities/BlazeUnitFireball.java @@ -50,15 +50,24 @@ public void tick() { Block blockBelow = this.level().getBlockState(this.getOnPos().below()).getBlock(); Block blockBelow2 = this.level().getBlockState(this.getOnPos().below().below()).getBlock(); - if (List.of(Blocks.AIR, Blocks.TALL_GRASS, Blocks.GRASS, Blocks.CRIMSON_ROOTS).contains(blockBelow2)) { + List nonSolidBlocks = List.of( + Blocks.AIR, Blocks.TALL_GRASS, Blocks.GRASS, + Blocks.CRIMSON_ROOTS, Blocks.WARPED_ROOTS, + Blocks.DEAD_BUSH, Blocks.SNOW, + BlockRegistrar.WRAITH_SNOW_LAYER.get() + ); + if (nonSolidBlocks.contains(blockBelow2)) { + meltSnow(this.getOnPos().below().below().below()); replacePathWithDirt(this.getOnPos().below().below().below()); this.level().setBlockAndUpdate(this.getOnPos().below().below(), fireState); } - if (List.of(Blocks.AIR, Blocks.TALL_GRASS, Blocks.GRASS, Blocks.CRIMSON_ROOTS).contains(blockBelow)) { + if (nonSolidBlocks.contains(blockBelow)) { + meltSnow(this.getOnPos().below().below()); replacePathWithDirt(this.getOnPos().below().below()); this.level().setBlockAndUpdate(this.getOnPos().below(), fireState); } - else if (List.of(Blocks.AIR, Blocks.TALL_GRASS, Blocks.GRASS, Blocks.CRIMSON_ROOTS).contains(block)) { + else if (nonSolidBlocks.contains(block)) { + meltSnow(this.getOnPos()); replacePathWithDirt(this.getOnPos()); this.level().setBlockAndUpdate(this.getOnPos(), fireState); } @@ -67,6 +76,11 @@ else if (List.of(Blocks.AIR, Blocks.TALL_GRASS, Blocks.GRASS, Blocks.CRIMSON_ROO this.discard(); } + private void meltSnow(BlockPos bp) { + if (this.level().getBlockState(bp).getBlock() == BlockRegistrar.WRAITH_SNOW_LAYER.get() || + this.level().getBlockState(bp).getBlock() == Blocks.SNOW) + this.level().setBlockAndUpdate(bp, Blocks.AIR.defaultBlockState()); + } private void replacePathWithDirt(BlockPos bp) { if (this.level().getBlockState(bp).getBlock() == Blocks.DIRT_PATH) this.level().setBlockAndUpdate(bp, Blocks.DIRT.defaultBlockState()); diff --git a/src/main/java/com/solegendary/reignofnether/entities/MoltenBombProjectile.java b/src/main/java/com/solegendary/reignofnether/entities/MoltenBombProjectile.java index 1f1c82e89..a7bf70d8f 100644 --- a/src/main/java/com/solegendary/reignofnether/entities/MoltenBombProjectile.java +++ b/src/main/java/com/solegendary/reignofnether/entities/MoltenBombProjectile.java @@ -62,7 +62,8 @@ public boolean ignoreExplosion() { } protected void detonate() { - this.level().explode(this, this.getX(), this.getY(), this.getZ(), 2, false, Level.ExplosionInteraction.NONE); + level().explode(null, null, null, this.getX(), this.getEyeY(), this.getZ(), + 2.0f, false, Level.ExplosionInteraction.NONE); HashMap bpAndDists = new HashMap<>(); @@ -101,7 +102,9 @@ protected void detonate() { } List mobs = MiscUtil.getEntitiesWithinRange(position(), moltenBomb.radius, Mob.class, level()); for (Mob mob : mobs) { - mob.hurt(damageSources().explosion(this.getOwner(), this), moltenBomb.damage); + if (mob.hurt(damageSources().explosion(this.getOwner(), this), moltenBomb.damage) && random.nextBoolean()) { + mob.setSecondsOnFire(5); + } if (this.getOwner() instanceof LivingEntity le && le.hasEffect(MobEffectRegistrar.SOULS_AFLAME.get())) { mob.addEffect(new MobEffectInstance(MobEffectRegistrar.SOULS_AFLAME.get(), 120, 0, false, false)); } diff --git a/src/main/java/com/solegendary/reignofnether/mixin/PlayerMixin.java b/src/main/java/com/solegendary/reignofnether/mixin/PlayerMixin.java index f65e32106..337f16b91 100644 --- a/src/main/java/com/solegendary/reignofnether/mixin/PlayerMixin.java +++ b/src/main/java/com/solegendary/reignofnether/mixin/PlayerMixin.java @@ -22,6 +22,7 @@ public abstract class PlayerMixin { @Shadow public abstract int getId(); @Shadow public Level level; + /* @Inject( method = "tick()V", at = @At("HEAD") @@ -46,4 +47,5 @@ private void tick(CallbackInfo ci) { } } } + */ } diff --git a/src/main/java/com/solegendary/reignofnether/mixin/ThrownPotionMixin.java b/src/main/java/com/solegendary/reignofnether/mixin/ThrownPotionMixin.java index 5203cb3a7..48a62f3a4 100644 --- a/src/main/java/com/solegendary/reignofnether/mixin/ThrownPotionMixin.java +++ b/src/main/java/com/solegendary/reignofnether/mixin/ThrownPotionMixin.java @@ -4,10 +4,13 @@ import com.solegendary.reignofnether.entities.AdjustableAreaEffectCloud; import com.solegendary.reignofnether.research.ResearchClient; import com.solegendary.reignofnether.research.ResearchServerEvents; +import com.solegendary.reignofnether.research.researchItems.ResearchWaterPotions; import com.solegendary.reignofnether.unit.units.villagers.WitchUnit; +import com.solegendary.reignofnether.util.MiscUtil; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.entity.AreaEffectCloud; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.projectile.ThrowableItemProjectile; @@ -16,13 +19,20 @@ import net.minecraft.world.item.LingeringPotionItem; import net.minecraft.world.item.alchemy.Potion; import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.item.alchemy.Potions; import net.minecraft.world.level.Level; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.HitResult; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.List; + @Mixin(ThrownPotion.class) public abstract class ThrownPotionMixin extends ThrowableItemProjectile { @@ -77,6 +87,13 @@ private void makeAreaOfEffectCloud(ItemStack pStack, Potion pPotion, CallbackInf this.level().addFreshEntity(aec); } + private boolean isWaterPotion() { + ItemStack item = this.getItem(); + Potion potion = PotionUtils.getPotion(item); + List mei = PotionUtils.getMobEffects(item); + return potion == Potions.WATER && mei.isEmpty(); + } + // lingering potions should not collide with entities so their AOE cloud is better placed @Inject( method = "onHit", @@ -87,8 +104,44 @@ private void onHit(HitResult pResult, CallbackInfo ci) { ItemStack item = this.getItem(); if (pResult.getType() == HitResult.Type.ENTITY && item.getItem() instanceof LingeringPotionItem && - this.getOwner() instanceof WitchUnit witchUnit) { + this.getOwner() instanceof WitchUnit) { ci.cancel(); + } else if (!this.level().isClientSide && isWaterPotion() && pResult.getType() == HitResult.Type.ENTITY) { + reignofnether$dowseNearbyFires(((EntityHitResult)pResult).getEntity().blockPosition()); + } + } + + @Shadow private void dowseFire(BlockPos pPos) { } + + @Inject( + method = "onHitBlock", + at = @At("TAIL") + ) + protected void onHitBlock(BlockHitResult pResult, CallbackInfo ci) { + if (!this.level().isClientSide) { + boolean isWater = isWaterPotion(); + Direction dir = pResult.getDirection(); + BlockPos hitBp = pResult.getBlockPos(); + BlockPos adjBp = hitBp.relative(dir); + if (isWater) { + reignofnether$dowseNearbyFires(adjBp); + } + } + } + + @Unique + private void reignofnether$dowseNearbyFires(BlockPos bp) { + float radius = ResearchWaterPotions.DOWSE_RADIUS; + for (LivingEntity entity : MiscUtil.getEntitiesWithinRange(bp.getCenter(), radius, LivingEntity.class, level())) { + if (entity.isOnFire() && entity.isAlive()) { + entity.extinguishFire(); + } + if (entity.isSensitiveToWater()) { + entity.hurt(this.damageSources().indirectMagic(this, this.getOwner()), 1.0F); + } + } + for (BlockPos bp2 : BlockPos.withinManhattan(bp, (int) radius, (int) radius, (int) radius)) { + dowseFire(bp2); } } } diff --git a/src/main/java/com/solegendary/reignofnether/mixin/fire/BaseFireBlockMixin.java b/src/main/java/com/solegendary/reignofnether/mixin/fire/BaseFireBlockMixin.java index cb3f3f35f..fb8a130b5 100644 --- a/src/main/java/com/solegendary/reignofnether/mixin/fire/BaseFireBlockMixin.java +++ b/src/main/java/com/solegendary/reignofnether/mixin/fire/BaseFireBlockMixin.java @@ -3,6 +3,7 @@ import com.solegendary.reignofnether.building.production.ProductionItems; import com.solegendary.reignofnether.research.ResearchServerEvents; import com.solegendary.reignofnether.unit.interfaces.Unit; +import com.solegendary.reignofnether.unit.units.piglins.WitherSkeletonUnit; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; @@ -26,8 +27,8 @@ private boolean researchImmune(BlockState state, Level level, Entity entity) { if (state.getBlock() instanceof SoulFireBlock) return false; - if (entity instanceof Unit unit) - return ResearchServerEvents.playerHasResearch(unit.getOwnerName(), ProductionItems.RESEARCH_FIRE_RESISTANCE); + if (entity instanceof WitherSkeletonUnit witherSkeletonUnit) + return ResearchServerEvents.playerHasResearch(witherSkeletonUnit.getOwnerName(), ProductionItems.RESEARCH_FIRE_RESISTANCE); return false; } diff --git a/src/main/java/com/solegendary/reignofnether/mixin/fire/CampfireBlockMixin.java b/src/main/java/com/solegendary/reignofnether/mixin/fire/CampfireBlockMixin.java new file mode 100644 index 000000000..97df96218 --- /dev/null +++ b/src/main/java/com/solegendary/reignofnether/mixin/fire/CampfireBlockMixin.java @@ -0,0 +1,39 @@ +package com.solegendary.reignofnether.mixin.fire; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.enchantment.EnchantmentHelper; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.BaseEntityBlock; +import net.minecraft.world.level.block.BaseFireBlock; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.CampfireBlock; +import net.minecraft.world.level.block.state.BlockState; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(CampfireBlock.class) +public abstract class CampfireBlockMixin extends BaseEntityBlock { + + private static final int DAMAGE_DELAY = 20; // higher == damage less often + + protected CampfireBlockMixin(Properties pProperties) { + super(pProperties); + } + + @Inject( + method = "entityInside", + at = @At("HEAD"), + cancellable = true + ) + public void entityInside(BlockState pState, Level pLevel, BlockPos pPos, Entity pEntity, CallbackInfo ci) { + ci.cancel(); + if (pState.getValue(CampfireBlock.LIT) && pEntity instanceof LivingEntity && !EnchantmentHelper.hasFrostWalker((LivingEntity)pEntity) && + pEntity.tickCount % DAMAGE_DELAY == 0) { + pEntity.hurt(pLevel.damageSources().inFire(), pState.getBlock() == Blocks.SOUL_CAMPFIRE ? 2 : 1); + } + } +} diff --git a/src/main/java/com/solegendary/reignofnether/mixin/fire/MagmaBlockMixin.java b/src/main/java/com/solegendary/reignofnether/mixin/fire/MagmaBlockMixin.java index 1f8bc798f..56e44aa6a 100644 --- a/src/main/java/com/solegendary/reignofnether/mixin/fire/MagmaBlockMixin.java +++ b/src/main/java/com/solegendary/reignofnether/mixin/fire/MagmaBlockMixin.java @@ -1,6 +1,7 @@ package com.solegendary.reignofnether.mixin.fire; import com.solegendary.reignofnether.blocks.WalkableMagmaBlock; +import com.solegendary.reignofnether.registrars.MobEffectRegistrar; import com.solegendary.reignofnether.unit.interfaces.Unit; import com.solegendary.reignofnether.unit.units.piglins.GruntUnit; import com.solegendary.reignofnether.faction.Faction; @@ -27,14 +28,14 @@ public abstract class MagmaBlockMixin { public void stepOn(Level pLevel, BlockPos pPos, BlockState pState, Entity pEntity, CallbackInfo ci) { ci.cancel(); - boolean isPiglinFaction = pEntity instanceof Unit unit && unit.getFaction() == Faction.PIGLINS; + boolean piglinImmunity = pEntity instanceof Unit unit && unit.getFaction() == Faction.PIGLINS && !pEntity.isOnFire(); boolean isDamageTick = pEntity.tickCount % WalkableMagmaBlock.DAMAGE_DELAY == 0; if (!pEntity.isSteppingCarefully() && pEntity instanceof LivingEntity && !(pEntity instanceof GruntUnit) && !EnchantmentHelper.hasFrostWalker((LivingEntity)pEntity) && - !isPiglinFaction && isDamageTick) { + !piglinImmunity && isDamageTick) { pEntity.hurt(pEntity.damageSources().hotFloor(), WalkableMagmaBlock.DAMAGE); } } diff --git a/src/main/java/com/solegendary/reignofnether/nether/NetherBlocks.java b/src/main/java/com/solegendary/reignofnether/nether/NetherBlocks.java index 40efdf258..28b297bf6 100644 --- a/src/main/java/com/solegendary/reignofnether/nether/NetherBlocks.java +++ b/src/main/java/com/solegendary/reignofnether/nether/NetherBlocks.java @@ -51,6 +51,7 @@ public static boolean isNetherBlock(Level level, BlockPos bp) { if (bs.getBlock().getName().getContents() instanceof TranslatableContents contents && (contents.getKey().contains("blackstone") || + contents.getKey().contains("nylium") || contents.getKey().contains("nether_brick"))) { return true; } diff --git a/src/main/java/com/solegendary/reignofnether/research/researchItems/ResearchWaterPotions.java b/src/main/java/com/solegendary/reignofnether/research/researchItems/ResearchWaterPotions.java index e27666610..3adbcbb83 100644 --- a/src/main/java/com/solegendary/reignofnether/research/researchItems/ResearchWaterPotions.java +++ b/src/main/java/com/solegendary/reignofnether/research/researchItems/ResearchWaterPotions.java @@ -23,6 +23,8 @@ public class ResearchWaterPotions extends ProductionItem { public final static String itemName = "Water Potions"; public final static ResourceCost cost = ResourceCosts.RESEARCH_WATER_POTIONS; + public final static float DOWSE_RADIUS = 2f; + public ResearchWaterPotions() { super(cost, ProdDupeRule.DISALLOW); this.onComplete = (Level level, ProductionPlacement building) -> { diff --git a/src/main/java/com/solegendary/reignofnether/research/researchItems/ResearchWitherClouds.java b/src/main/java/com/solegendary/reignofnether/research/researchItems/ResearchWitherClouds.java index ee547a1cb..abda6bb19 100644 --- a/src/main/java/com/solegendary/reignofnether/research/researchItems/ResearchWitherClouds.java +++ b/src/main/java/com/solegendary/reignofnether/research/researchItems/ResearchWitherClouds.java @@ -44,7 +44,7 @@ public String getItemName() { public StartProductionButton getStartButton(ProductionPlacement prodBuilding, Keybinding hotkey) { return new StartProductionButton(ResearchWitherClouds.itemName, - ResourceLocation.fromNamespaceAndPath(ReignOfNether.MOD_ID, "textures/mobheads/wither_skeleton.png"), + ResourceLocation.fromNamespaceAndPath(ReignOfNether.MOD_ID, "textures/icons/abilities/wither_cloud.png"), ResourceLocation.fromNamespaceAndPath(ReignOfNether.MOD_ID, "textures/hud/icon_frame_bronze.png"), hotkey, () -> ProductionItems.RESEARCH_WITHER_CLOUDS.itemIsBeingProduced(prodBuilding.ownerName) @@ -65,7 +65,7 @@ public StartProductionButton getStartButton(ProductionPlacement prodBuilding, Ke public StopProductionButton getCancelButton(ProductionPlacement prodBuilding, boolean first) { return new StopProductionButton(ResearchWitherClouds.itemName, - ResourceLocation.fromNamespaceAndPath(ReignOfNether.MOD_ID, "textures/mobheads/wither_skeleton.png"), + ResourceLocation.fromNamespaceAndPath(ReignOfNether.MOD_ID, "textures/icons/abilities/wither_cloud.png"), ResourceLocation.fromNamespaceAndPath(ReignOfNether.MOD_ID, "textures/hud/icon_frame_bronze.png"), prodBuilding, this, diff --git a/src/main/java/com/solegendary/reignofnether/resources/ResourcesClientEvents.java b/src/main/java/com/solegendary/reignofnether/resources/ResourcesClientEvents.java index f3af19a31..d1137e355 100644 --- a/src/main/java/com/solegendary/reignofnether/resources/ResourcesClientEvents.java +++ b/src/main/java/com/solegendary/reignofnether/resources/ResourcesClientEvents.java @@ -60,7 +60,7 @@ public static void onClientTick(ScreenEvent.Render evt) { BlockPos preSelBp = CursorClientEvents.getPreselectedBlockPos(); ResourceSource res = ResourceSources.getFromBlockPos(preSelBp, MC.level); - if (res != null && res.resourceValue > 0 && !BuildingUtils.isPosInsideAnyBuilding(true, preSelBp)) { + if (res != null && res.resourceValue > 0 && !BuildingUtils.isPosInsideAnyNonBridgeBuilding(true, preSelBp)) { String str = switch (res.resourceName) { case FOOD -> "\uE000 " + res.resourceValue; case WOOD -> "\uE001 " + res.resourceValue; diff --git a/src/main/java/com/solegendary/reignofnether/sounds/FadeableSoundInstance.java b/src/main/java/com/solegendary/reignofnether/sounds/FadeableSoundInstance.java index fc7c7d301..a7ff70f4c 100644 --- a/src/main/java/com/solegendary/reignofnether/sounds/FadeableSoundInstance.java +++ b/src/main/java/com/solegendary/reignofnether/sounds/FadeableSoundInstance.java @@ -12,11 +12,11 @@ public class FadeableSoundInstance extends AbstractTickableSoundInstance { private boolean fadingIn; private boolean fadingOut = false; - private BlockPos pos; public final int id; private float volumeMult; + private int ticksLeft; - public FadeableSoundInstance(SoundEvent soundEvent, BlockPos pos, int id, boolean fadeIn, float volumeMult) { + public FadeableSoundInstance(SoundEvent soundEvent, BlockPos pos, int id, boolean fadeIn, float volumeMult, int tickDuration) { super(soundEvent, SoundSource.NEUTRAL, SoundInstance.createUnseededRandom()); this.looping = true; this.delay = 0; @@ -27,10 +27,16 @@ public FadeableSoundInstance(SoundEvent soundEvent, BlockPos pos, int id, boolea this.z = pos.getZ() + 0.5; this.id = id; this.volumeMult = volumeMult; + this.ticksLeft = tickDuration; } @Override public void tick() { + if (ticksLeft > 0) { + ticksLeft -= 1; + if (ticksLeft <= 0) + fadeOut(); + } if (fadingIn) { if (volume < volumeMult) volume += FADE_SPEED * volumeMult; diff --git a/src/main/java/com/solegendary/reignofnether/sounds/SoundClientEvents.java b/src/main/java/com/solegendary/reignofnether/sounds/SoundClientEvents.java index 28c406024..b375b865c 100644 --- a/src/main/java/com/solegendary/reignofnether/sounds/SoundClientEvents.java +++ b/src/main/java/com/solegendary/reignofnether/sounds/SoundClientEvents.java @@ -95,9 +95,9 @@ public static void playSoundAtPos(SoundAction soundAction, BlockPos bp, float vo } } - public static void playFadeableSoundAtPos(SoundAction soundAction, BlockPos bp, float volume, int id) { + public static void playFadeableSoundAtPos(SoundAction soundAction, BlockPos bp, float volume, int id, int tickDuration) { SoundEvent soundEvent = SOUND_MAP.get(soundAction); - FadeableSoundInstance fsi = new FadeableSoundInstance(soundEvent, bp, id,true, volume); + FadeableSoundInstance fsi = new FadeableSoundInstance(soundEvent, bp, id,true, volume, tickDuration); MC.getSoundManager().play(fsi); activeFadeableSounds.add(fsi); } diff --git a/src/main/java/com/solegendary/reignofnether/sounds/SoundClientboundPacket.java b/src/main/java/com/solegendary/reignofnether/sounds/SoundClientboundPacket.java index 420e674e4..db29d3482 100644 --- a/src/main/java/com/solegendary/reignofnether/sounds/SoundClientboundPacket.java +++ b/src/main/java/com/solegendary/reignofnether/sounds/SoundClientboundPacket.java @@ -18,6 +18,7 @@ public class SoundClientboundPacket { String playerName; float volume; int id; + int tickDuration; public static void playSoundAtPos(SoundAction soundAction, BlockPos bp) { PacketHandler.INSTANCE.send(PacketDistributor.ALL.noArg(), @@ -27,7 +28,7 @@ public static void playSoundAtPos(SoundAction soundAction, BlockPos bp, float vo PacketHandler.INSTANCE.send(PacketDistributor.ALL.noArg(), new SoundClientboundPacket(soundAction, bp, "", volume, -1)); } - public static void playFadeableLoopingSoundAtPos(SoundAction soundAction, BlockPos bp, float volume, int id) { + public static void playFadeableLoopingSoundAtPos(SoundAction soundAction, BlockPos bp, float volume, int id, int tickDuration) { PacketHandler.INSTANCE.send(PacketDistributor.ALL.noArg(), new SoundClientboundPacket(soundAction, bp, "", volume, id)); } @@ -58,6 +59,16 @@ public SoundClientboundPacket(SoundAction soundAction, BlockPos bp, String playe this.playerName = playerName; this.volume = volume; this.id = id; + this.tickDuration = -1; + } + + public SoundClientboundPacket(SoundAction soundAction, BlockPos bp, String playerName, float volume, int id, int tickDuration) { + this.soundAction = soundAction; + this.bp = bp; + this.playerName = playerName; + this.volume = volume; + this.id = id; + this.tickDuration = tickDuration; } public SoundClientboundPacket(FriendlyByteBuf buffer) { @@ -66,6 +77,7 @@ public SoundClientboundPacket(FriendlyByteBuf buffer) { this.playerName = buffer.readUtf(); this.volume = buffer.readFloat(); this.id = buffer.readInt(); + this.tickDuration = buffer.readInt(); } public void encode(FriendlyByteBuf buffer) { @@ -74,6 +86,7 @@ public void encode(FriendlyByteBuf buffer) { buffer.writeUtf(this.playerName); buffer.writeFloat(this.volume); buffer.writeInt(this.id); + buffer.writeInt(this.tickDuration); } // server-side packet-consuming functions @@ -86,7 +99,7 @@ public boolean handle(Supplier ctx) { if (soundAction == SoundAction.STOP_SOUND) { SoundClientEvents.stopSound(id); } else if (id >= 0) { - SoundClientEvents.playFadeableSoundAtPos(soundAction, bp, volume, id); + SoundClientEvents.playFadeableSoundAtPos(soundAction, bp, volume, id, tickDuration); } else if (bp.equals(new BlockPos(0,0,0))) { if (playerName.isBlank()) diff --git a/src/main/java/com/solegendary/reignofnether/unit/UnitActionItem.java b/src/main/java/com/solegendary/reignofnether/unit/UnitActionItem.java index 14bc2e0c0..9906cd8d4 100644 --- a/src/main/java/com/solegendary/reignofnether/unit/UnitActionItem.java +++ b/src/main/java/com/solegendary/reignofnether/unit/UnitActionItem.java @@ -8,6 +8,7 @@ import com.solegendary.reignofnether.building.BuildingPlacement; import com.solegendary.reignofnether.building.BuildingUtils; import com.solegendary.reignofnether.building.GarrisonableBuilding; +import com.solegendary.reignofnether.building.buildings.placements.BridgePlacement; import com.solegendary.reignofnether.building.buildings.placements.FarmPlacement; import com.solegendary.reignofnether.building.buildings.placements.PortalPlacement; import com.solegendary.reignofnether.hud.HudClientEvents; @@ -231,7 +232,7 @@ public void action(Level level) { ); if (unit instanceof WorkerUnit workerUnit && resName != ResourceName.NONE - && buildingAtPos == null) { + && (buildingAtPos == null || buildingAtPos instanceof BridgePlacement)) { GatherResourcesGoal goal = workerUnit.getGatherResourceGoal(); goal.setTargetResourceName(resName); goal.setMoveTarget(preselectedBlockPos); diff --git a/src/main/java/com/solegendary/reignofnether/unit/UnitServerEvents.java b/src/main/java/com/solegendary/reignofnether/unit/UnitServerEvents.java index d3629e096..0a0a8933a 100644 --- a/src/main/java/com/solegendary/reignofnether/unit/UnitServerEvents.java +++ b/src/main/java/com/solegendary/reignofnether/unit/UnitServerEvents.java @@ -48,6 +48,9 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.DamageTypeTags; import net.minecraft.util.Mth; +import net.minecraft.world.damagesource.DamageSources; +import net.minecraft.world.damagesource.DamageType; +import net.minecraft.world.damagesource.DamageTypes; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; @@ -775,16 +778,18 @@ public static void onMobSpawn(MobSpawnEvent.FinalizeSpawn evt) { private static boolean shouldIgnoreKnockback(LivingDamageEvent evt) { Entity projectile = evt.getSource().getDirectEntity(); - Entity shooter = evt.getSource().getEntity(); + Entity sourceEntity = evt.getSource().getEntity(); - if (shooter instanceof HeadhunterUnit headhunterUnit && projectile instanceof ThrownTrident) { + if (sourceEntity instanceof HeadhunterUnit headhunterUnit && projectile instanceof ThrownTrident) { return !ResearchServerEvents.playerHasResearch(headhunterUnit.getOwnerName(), ProductionItems.RESEARCH_HEAVY_TRIDENTS ); } - if (shooter instanceof SlimeUnit slimeUnit && slimeUnit.isTiny()) + if (sourceEntity instanceof WretchedWraithUnit) return true; - if (projectile instanceof Fireball && shooter instanceof BlazeUnit) + if (sourceEntity instanceof SlimeUnit slimeUnit && slimeUnit.isTiny()) + return true; + if (projectile instanceof Fireball && sourceEntity instanceof BlazeUnit) return true; if (projectile instanceof AbstractArrow) return true; @@ -792,7 +797,7 @@ private static boolean shouldIgnoreKnockback(LivingDamageEvent evt) { return true; return evt.getSource().is(DamageTypeTags.WITCH_RESISTANT_TO) && evt.getSource().isIndirect() - && (!(shooter instanceof EvokerUnit)); + && (!(sourceEntity instanceof EvokerUnit)); } public static Entity spawnMob( @@ -927,11 +932,11 @@ public static void onEntityDamaged(LivingDamageEvent evt) { } } - if (evt.getEntity().hasEffect(MobEffectRegistrar.SCORCHING_FIRE.get()) && evt.getSource().is(DamageTypeTags.IS_FIRE)) { - evt.setAmount(evt.getAmount() * 2); + if (evt.getEntity().hasEffect(MobEffectRegistrar.SCORCHING_FIRE.get()) && evt.getSource().is(DamageTypes.ON_FIRE)) { + evt.setAmount(evt.getAmount() * 3); } - if (evt.getEntity().hasEffect(MobEffectRegistrar.SOULS_AFLAME.get()) && evt.getSource() == evt.getEntity().damageSources().onFire()) { + if (evt.getEntity().hasEffect(MobEffectRegistrar.SOULS_AFLAME.get()) && evt.getSource().is(DamageTypes.ON_FIRE)) { evt.setAmount(evt.getAmount() * 2); } } diff --git a/src/main/java/com/solegendary/reignofnether/unit/goals/GatherResourcesGoal.java b/src/main/java/com/solegendary/reignofnether/unit/goals/GatherResourcesGoal.java index f599ed1a2..1b3737598 100644 --- a/src/main/java/com/solegendary/reignofnether/unit/goals/GatherResourcesGoal.java +++ b/src/main/java/com/solegendary/reignofnether/unit/goals/GatherResourcesGoal.java @@ -88,7 +88,7 @@ public class GatherResourcesGoal extends MoveToTargetBlockGoal { return false; } // is not part of a building (unless farming) - else if (data.targetFarm == null && BuildingUtils.isPosInsideAnyBuilding(mob.level().isClientSide(), bp)) + else if (data.targetFarm == null && BuildingUtils.isPosInsideAnyNonBridgeBuilding(mob.level().isClientSide(), bp)) return false; // not covered by solid blocks diff --git a/src/main/java/com/solegendary/reignofnether/unit/interfaces/Unit.java b/src/main/java/com/solegendary/reignofnether/unit/interfaces/Unit.java index 04c13d83b..c153ea29b 100644 --- a/src/main/java/com/solegendary/reignofnether/unit/interfaces/Unit.java +++ b/src/main/java/com/solegendary/reignofnether/unit/interfaces/Unit.java @@ -4,6 +4,7 @@ import com.solegendary.reignofnether.ability.Ability; import com.solegendary.reignofnether.ability.heroAbilities.enchanter.ProtectiveEnchantment; import com.solegendary.reignofnether.ability.heroAbilities.piglinmerchant.FancyFeast; +import com.solegendary.reignofnether.ability.heroAbilities.wildfire.ScorchingGaze; import com.solegendary.reignofnether.blocks.BlockServerEvents; import com.solegendary.reignofnether.building.BuildingUtils; import com.solegendary.reignofnether.building.buildings.placements.BridgePlacement; @@ -27,6 +28,7 @@ import com.solegendary.reignofnether.unit.units.piglins.BruteUnit; import com.solegendary.reignofnether.unit.units.piglins.GhastUnit; import com.solegendary.reignofnether.faction.Faction; +import com.solegendary.reignofnether.unit.units.piglins.WitherSkeletonUnit; import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap; import com.solegendary.reignofnether.util.MiscUtil; import net.minecraft.client.resources.language.I18n; @@ -254,11 +256,6 @@ static void tick(Unit unit) { // enact target-following, and stop followTarget being reset if (unit.getFollowTarget() != null && unitMob.tickCount % 20 == 0) unit.setMoveTarget(unit.getFollowTarget().blockPosition()); - - // remove fire from piglin units if they have research - boolean hasImmunityResearch = ResearchServerEvents.playerHasResearch(unit.getOwnerName(), ProductionItems.RESEARCH_FIRE_RESISTANCE); - if (hasImmunityResearch && unit.getFaction() == Faction.PIGLINS) - unitMob.setRemainingFireTicks(0); } // slow regen for monster and piglin units @@ -369,7 +366,8 @@ static void tick(Unit unit) { BlockState bsOn = unitMob.level().getBlockState(unitMob.getOnPos()); BlockState bsMagma = BlockRegistrar.WALKABLE_MAGMA_BLOCK.get().defaultBlockState(); if (bsOn.getBlock() != BlockRegistrar.WALKABLE_MAGMA_BLOCK.get()) { - BlockServerEvents.addTempBlock((ServerLevel) unitMob.level(), unitMob.getOnPos(), bsMagma, bsOn, unitMob.getRandom().nextInt(200,300)); + BlockServerEvents.addTempBlock((ServerLevel) unitMob.level(), unitMob.getOnPos(), bsMagma, bsOn, unitMob.getRandom() + .nextInt(ScorchingGaze.MIN_MAGMA_DURATION, ScorchingGaze.MAX_MAGMA_DURATION)); } MiscUtil.addParticleExplosion(ParticleTypes.LAVA, 1, unitMob.level(), unitMob.position()); if (!unitMob.isOnFire()) { diff --git a/src/main/java/com/solegendary/reignofnether/unit/units/monsters/HuskUnit.java b/src/main/java/com/solegendary/reignofnether/unit/units/monsters/HuskUnit.java index 40c8435aa..d4b930020 100644 --- a/src/main/java/com/solegendary/reignofnether/unit/units/monsters/HuskUnit.java +++ b/src/main/java/com/solegendary/reignofnether/unit/units/monsters/HuskUnit.java @@ -24,6 +24,8 @@ import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.ai.goal.FloatGoal; import net.minecraft.world.entity.ai.goal.Goal; +import net.minecraft.world.entity.ai.navigation.AmphibiousPathNavigation; +import net.minecraft.world.entity.ai.navigation.PathNavigation; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.monster.Husk; import net.minecraft.world.entity.monster.Monster; @@ -232,8 +234,4 @@ protected void pickUpItem(ItemEntity pItemEntity) { } public SpawnGroupData finalizeSpawn(ServerLevelAccessor pLevel, DifficultyInstance pDifficulty, MobSpawnType pReason, @Nullable SpawnGroupData pSpawnData, @Nullable CompoundTag pDataTag) { return pSpawnData; } - - - - } diff --git a/src/main/java/com/solegendary/reignofnether/unit/units/monsters/NecromancerUnit.java b/src/main/java/com/solegendary/reignofnether/unit/units/monsters/NecromancerUnit.java index e631e7d46..4764ac4d6 100644 --- a/src/main/java/com/solegendary/reignofnether/unit/units/monsters/NecromancerUnit.java +++ b/src/main/java/com/solegendary/reignofnether/unit/units/monsters/NecromancerUnit.java @@ -37,6 +37,7 @@ import net.minecraft.sounds.SoundEvents; import net.minecraft.tags.DamageTypeTags; import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.damagesource.DamageTypes; import net.minecraft.world.entity.AnimationState; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EquipmentSlot; @@ -317,7 +318,7 @@ protected void pickUpItem(ItemEntity pItemEntity) { } @Override public float getDamageAfterMagicAbsorb(DamageSource pSource, float pDamage) { pDamage = super.getDamageAfterMagicAbsorb(pSource, pDamage); - if (pSource.is(DamageTypeTags.WITCH_RESISTANT_TO)) + if (pSource.is(DamageTypeTags.WITCH_RESISTANT_TO) || pSource.is(DamageTypes.ON_FIRE)) pDamage *= 0.7F; return pDamage; } diff --git a/src/main/java/com/solegendary/reignofnether/unit/units/monsters/SkeletonUnit.java b/src/main/java/com/solegendary/reignofnether/unit/units/monsters/SkeletonUnit.java index 35c58e9a9..635609728 100644 --- a/src/main/java/com/solegendary/reignofnether/unit/units/monsters/SkeletonUnit.java +++ b/src/main/java/com/solegendary/reignofnether/unit/units/monsters/SkeletonUnit.java @@ -30,6 +30,8 @@ import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.ai.goal.FloatGoal; import net.minecraft.world.entity.ai.goal.Goal; +import net.minecraft.world.entity.ai.navigation.AmphibiousPathNavigation; +import net.minecraft.world.entity.ai.navigation.PathNavigation; import net.minecraft.world.entity.monster.Monster; import net.minecraft.world.entity.monster.Skeleton; import net.minecraft.world.entity.projectile.AbstractArrow; @@ -308,4 +310,9 @@ public void performUnitRangedAttack(LivingEntity pTarget, float velocity) { public SpawnGroupData finalizeSpawn(ServerLevelAccessor pLevel, DifficultyInstance pDifficulty, MobSpawnType pReason, @Nullable SpawnGroupData pSpawnData, @Nullable CompoundTag pDataTag) { return pSpawnData; } + + @Override + protected PathNavigation createNavigation(Level level) { + return new AmphibiousPathNavigation(this, level); + } } diff --git a/src/main/java/com/solegendary/reignofnether/unit/units/monsters/SlimeUnit.java b/src/main/java/com/solegendary/reignofnether/unit/units/monsters/SlimeUnit.java index b732db629..bc648cf2f 100644 --- a/src/main/java/com/solegendary/reignofnether/unit/units/monsters/SlimeUnit.java +++ b/src/main/java/com/solegendary/reignofnether/unit/units/monsters/SlimeUnit.java @@ -26,6 +26,7 @@ import net.minecraft.util.Mth; import net.minecraft.world.DifficultyInstance; import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.damagesource.DamageTypes; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.*; @@ -183,7 +184,6 @@ public ResourceCost getCost() { public SlimeUnit(EntityType entityType, Level level) { super(entityType, level); this.moveControl = new SlimeUnitMoveControl(this); - updateAbilityButtons(); } @@ -230,7 +230,7 @@ public void remove(RemovalReason pReason) { @Override public float getDamageAfterMagicAbsorb(DamageSource pSource, float pDamage) { pDamage = super.getDamageAfterMagicAbsorb(pSource, pDamage); - if (pSource.is(DamageTypeTags.WITCH_RESISTANT_TO)) + if (pSource.is(DamageTypeTags.WITCH_RESISTANT_TO) || pSource.is(DamageTypes.ON_FIRE)) pDamage *= 0.5F; return pDamage; } diff --git a/src/main/java/com/solegendary/reignofnether/unit/units/monsters/SpiderUnit.java b/src/main/java/com/solegendary/reignofnether/unit/units/monsters/SpiderUnit.java index 7fdf8c738..e7e33b57b 100644 --- a/src/main/java/com/solegendary/reignofnether/unit/units/monsters/SpiderUnit.java +++ b/src/main/java/com/solegendary/reignofnether/unit/units/monsters/SpiderUnit.java @@ -188,6 +188,7 @@ public SpinWebs getWebAbility() { public SpiderUnit(EntityType entityType, Level level) { super(entityType, level); + this.setMaxUpStep(1.0F); } public boolean isWallClimbing() { return wallClimbing; } diff --git a/src/main/java/com/solegendary/reignofnether/unit/units/monsters/WretchedWraithUnit.java b/src/main/java/com/solegendary/reignofnether/unit/units/monsters/WretchedWraithUnit.java index 30ab36a92..f97d89af6 100644 --- a/src/main/java/com/solegendary/reignofnether/unit/units/monsters/WretchedWraithUnit.java +++ b/src/main/java/com/solegendary/reignofnether/unit/units/monsters/WretchedWraithUnit.java @@ -43,6 +43,7 @@ import net.minecraft.tags.DamageTypeTags; import net.minecraft.world.damagesource.CombatRules; import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.damagesource.DamageTypes; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.*; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; @@ -337,7 +338,7 @@ public boolean isBlizzardInProgress() { public double getUnitPhysicalArmorPercentage() { double dmgAfterAbsorb = CombatRules.getDamageAfterAbsorb( 1, - getArmorValue() + (isBlizzardInProgress() ? 8 : 0), + getArmorValue() + (isBlizzardInProgress() ? 13 : 0), (float)getAttributeValue(Attributes.ARMOR_TOUGHNESS)); dmgAfterAbsorb += getDamageTakenIncrease(); return Math.round((1 - dmgAfterAbsorb)/ 0.01d) * 0.01d; @@ -357,7 +358,7 @@ protected void pickUpItem(ItemEntity pItemEntity) { } @Override public float getDamageAfterMagicAbsorb(DamageSource pSource, float pDamage) { pDamage = super.getDamageAfterMagicAbsorb(pSource, pDamage); - if (pSource.is(DamageTypeTags.WITCH_RESISTANT_TO)) + if (pSource.is(DamageTypeTags.WITCH_RESISTANT_TO) || pSource.is(DamageTypes.ON_FIRE)) pDamage *= 0.7F; return pDamage; } @@ -386,7 +387,8 @@ public static AttributeSupplier.Builder createAttributes() { .add(Attributes.MAX_HEALTH, WretchedWraithUnit.maxHealth) .add(Attributes.FOLLOW_RANGE, Unit.getFollowRange()) .add(Attributes.ARMOR, WretchedWraithUnit.armorValue) - .add(Attributes.KNOCKBACK_RESISTANCE, 0.5f); + .add(Attributes.ATTACK_KNOCKBACK, 0f) + .add(Attributes.KNOCKBACK_RESISTANCE, 1.0f); } public void tick() { @@ -712,7 +714,7 @@ public void blizzard() { blizzardTicksLeft = Blizzard.CHANNEL_DURATION; if (!level().isClientSide) { AbilityClientboundPacket.doAbility(getId(), UnitAction.BLIZZARD, blizzardTicksLeft); - SoundClientboundPacket.playFadeableLoopingSoundAtPos(SoundAction.WRETCHED_WRAITH_BLIZZARD, blockPosition(), 1.0f, getId()); + SoundClientboundPacket.playFadeableLoopingSoundAtPos(SoundAction.WRETCHED_WRAITH_BLIZZARD, blockPosition(), 1.0f, getId(), Blizzard.CHANNEL_DURATION); } } @@ -740,7 +742,7 @@ public boolean hurt(DamageSource pSource, float pAmount) { @Override public float getBonusMeleeRange() { - return 0.4f; + return 0.6f; } @Override diff --git a/src/main/java/com/solegendary/reignofnether/unit/units/piglins/GhastUnit.java b/src/main/java/com/solegendary/reignofnether/unit/units/piglins/GhastUnit.java index 2810aff4d..5b8ef2b68 100644 --- a/src/main/java/com/solegendary/reignofnether/unit/units/piglins/GhastUnit.java +++ b/src/main/java/com/solegendary/reignofnether/unit/units/piglins/GhastUnit.java @@ -31,6 +31,7 @@ import net.minecraft.util.FormattedCharSequence; import net.minecraft.util.Mth; import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.damagesource.DamageTypes; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EquipmentSlot; @@ -205,7 +206,7 @@ public GhastUnit(EntityType entityType, Level level) { @Override public float getDamageAfterMagicAbsorb(DamageSource pSource, float pDamage) { pDamage = super.getDamageAfterMagicAbsorb(pSource, pDamage); - if (pSource.is(DamageTypeTags.WITCH_RESISTANT_TO)) + if (pSource.is(DamageTypeTags.WITCH_RESISTANT_TO) || pSource.is(DamageTypes.ON_FIRE)) pDamage *= 0.5F; return pDamage; } diff --git a/src/main/java/com/solegendary/reignofnether/unit/units/piglins/MagmaCubeUnit.java b/src/main/java/com/solegendary/reignofnether/unit/units/piglins/MagmaCubeUnit.java index 1de507b18..789e22c4c 100644 --- a/src/main/java/com/solegendary/reignofnether/unit/units/piglins/MagmaCubeUnit.java +++ b/src/main/java/com/solegendary/reignofnether/unit/units/piglins/MagmaCubeUnit.java @@ -163,7 +163,6 @@ public void createMagma() { bps.add(bpOn.west().west().north()); } - // Frostwalker effect provided in LivingEntityMixin, but it only happens on changing block positions on the ground for (BlockPos bp : bps) { BlockState bsOld = level().getBlockState(bp); if (MiscUtil.isSolidBlocking(level(), bp)) { diff --git a/src/main/java/com/solegendary/reignofnether/unit/units/piglins/MarauderUnit.java b/src/main/java/com/solegendary/reignofnether/unit/units/piglins/MarauderUnit.java index ade04800f..a1b24b6c6 100644 --- a/src/main/java/com/solegendary/reignofnether/unit/units/piglins/MarauderUnit.java +++ b/src/main/java/com/solegendary/reignofnether/unit/units/piglins/MarauderUnit.java @@ -12,6 +12,7 @@ import com.solegendary.reignofnether.faction.Faction; import com.solegendary.reignofnether.keybinds.Keybindings; import com.solegendary.reignofnether.registrars.MobEffectRegistrar; +import com.solegendary.reignofnether.research.ResearchClient; import com.solegendary.reignofnether.research.ResearchServerEvents; import com.solegendary.reignofnether.resources.ResourceCost; import com.solegendary.reignofnether.resources.ResourceCosts; @@ -139,7 +140,11 @@ protected void defineSynchedData() { public float getAggroRange() {return aggroRange;} public boolean getAggressiveWhenIdle() {return aggressiveWhenIdle && !isVehicle();} public float getAttackRange() {return attackRange;} - public float getUnitAttackDamage() {return isNextHitBig() ? attackDamage + bigHitDamageBonus : attackDamage;} + public float getUnitAttackDamage() { + if (useCleavingHitDamage) { + return cleavingHitDamage; + } + return isNextHitBig() ? bigHitDamage : attackDamage;} public BlockPos getAttackMoveTarget() { return attackMoveTarget; } public boolean canAttackBuildings() {return getAttackBuildingGoal() != null;} public Goal getAttackGoal() { return attackGoal; } @@ -152,7 +157,8 @@ protected void defineSynchedData() { public float getAttackCooldown() {return ((20 / attacksPerSecond) * getAttackCooldownMultiplier());} final static public float attackDamage = 7.0f; - final static public float bigHitDamageBonus = 3.0f; + final static public float bigHitDamage = 10.0f; + final static public float cleavingHitDamage = 5f; final static public float attacksPerSecond = 0.4f; final static public float attackRange = 2; // only used by ranged units or melee building attackers final static public float aggroRange = 10; @@ -167,6 +173,7 @@ protected void defineSynchedData() { private final int ATTACKS_TO_BIG_HIT_MAX = 2; public int attacksToNextBigHit = 2; + private boolean useCleavingHitDamage = false; private Abilities abilities = ABILITIES.clone(); private final List items = new ArrayList<>(); @@ -284,16 +291,15 @@ public boolean doHurtTarget(@NotNull Entity pEntity) { boolean result; if (isNextHitBig()) { this.getAttribute(Attributes.ATTACK_KNOCKBACK).addTransientModifier(new AttributeModifier("knockback", 1.5f, AttributeModifier.Operation.ADDITION)); - this.getAttribute(Attributes.ATTACK_DAMAGE).addTransientModifier(new AttributeModifier("attackDamage", bigHitDamageBonus, AttributeModifier.Operation.ADDITION)); result = super.doHurtTarget(pEntity); if (pEntity instanceof LivingEntity le) { le.addEffect(new MobEffectInstance(MobEffectRegistrar.STUN.get(), 40)); } this.getAttribute(Attributes.ATTACK_KNOCKBACK).removeModifiers(); - this.getAttribute(Attributes.ATTACK_DAMAGE).removeModifiers(); decrementAttacks(); if (!level().isClientSide() && ResearchServerEvents.playerHasResearch(getOwnerName(), ProductionItems.RESEARCH_CLEAVING_FLAILS)) { + this.useCleavingHitDamage = true; List nearbyMobs = MiscUtil.getEntitiesWithinRange(new Vector3d( pEntity.position().x, pEntity.position().y, @@ -305,13 +311,14 @@ public boolean doHurtTarget(@NotNull Entity pEntity) { for (Mob mob : closestMobs) { if (UnitServerEvents.getUnitToEntityRelationship(this, mob) != Relationship.FRIENDLY && mob.getId() != pEntity.getId()) { super.doHurtTarget(mob); - mob.addEffect(new MobEffectInstance(MobEffectRegistrar.STUN.get(), 30)); + mob.addEffect(new MobEffectInstance(MobEffectRegistrar.STUN.get(), 20)); extraHitsLeft -= 1; if (extraHitsLeft <= 0) { break; } } } + this.useCleavingHitDamage = false; } } else { result = super.doHurtTarget(pEntity); diff --git a/src/main/java/com/solegendary/reignofnether/unit/units/piglins/PiglinMerchantUnit.java b/src/main/java/com/solegendary/reignofnether/unit/units/piglins/PiglinMerchantUnit.java index bee30ffa2..328957f35 100644 --- a/src/main/java/com/solegendary/reignofnether/unit/units/piglins/PiglinMerchantUnit.java +++ b/src/main/java/com/solegendary/reignofnether/unit/units/piglins/PiglinMerchantUnit.java @@ -42,6 +42,7 @@ import net.minecraft.util.Mth; import net.minecraft.world.DifficultyInstance; import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.damagesource.DamageTypes; import net.minecraft.world.entity.*; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; @@ -301,7 +302,7 @@ public PiglinMerchantUnit(EntityType entityType, Level level) @Override public float getDamageAfterMagicAbsorb(DamageSource pSource, float pDamage) { pDamage = super.getDamageAfterMagicAbsorb(pSource, pDamage); - if (pSource.is(DamageTypeTags.WITCH_RESISTANT_TO)) + if (pSource.is(DamageTypeTags.WITCH_RESISTANT_TO) || pSource.is(DamageTypes.ON_FIRE)) pDamage *= 0.7F; return pDamage; } diff --git a/src/main/java/com/solegendary/reignofnether/unit/units/piglins/WildfireUnit.java b/src/main/java/com/solegendary/reignofnether/unit/units/piglins/WildfireUnit.java index 77d627650..9f60785c8 100644 --- a/src/main/java/com/solegendary/reignofnether/unit/units/piglins/WildfireUnit.java +++ b/src/main/java/com/solegendary/reignofnether/unit/units/piglins/WildfireUnit.java @@ -45,6 +45,7 @@ import net.minecraft.util.FormattedCharSequence; import net.minecraft.util.Mth; import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.damagesource.DamageTypes; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.*; @@ -339,7 +340,7 @@ public WildfireUnit(EntityType entityType, Level level) { @Override public float getDamageAfterMagicAbsorb(DamageSource pSource, float pDamage) { pDamage = super.getDamageAfterMagicAbsorb(pSource, pDamage); - if (pSource.is(DamageTypeTags.WITCH_RESISTANT_TO)) + if (pSource.is(DamageTypeTags.WITCH_RESISTANT_TO) || pSource.is(DamageTypes.ON_FIRE)) pDamage *= 0.7F; return pDamage; } diff --git a/src/main/java/com/solegendary/reignofnether/unit/units/piglins/WitherSkeletonUnit.java b/src/main/java/com/solegendary/reignofnether/unit/units/piglins/WitherSkeletonUnit.java index 17297446e..91c373068 100644 --- a/src/main/java/com/solegendary/reignofnether/unit/units/piglins/WitherSkeletonUnit.java +++ b/src/main/java/com/solegendary/reignofnether/unit/units/piglins/WitherSkeletonUnit.java @@ -7,7 +7,10 @@ import com.solegendary.reignofnether.building.BuildingUtils; import com.solegendary.reignofnether.building.buildings.piglins.BasaltSprings; import com.solegendary.reignofnether.building.buildings.piglins.FlameSanctuary; +import com.solegendary.reignofnether.building.production.ProductionItems; import com.solegendary.reignofnether.keybinds.Keybindings; +import com.solegendary.reignofnether.registrars.MobEffectRegistrar; +import com.solegendary.reignofnether.research.ResearchServerEvents; import com.solegendary.reignofnether.resources.ResourceCost; import com.solegendary.reignofnether.resources.ResourceCosts; import com.solegendary.reignofnether.unit.Checkpoint; @@ -181,7 +184,19 @@ public static AttributeSupplier.Builder createAttributes() { .add(Attributes.MOVEMENT_SPEED, WitherSkeletonUnit.movementSpeed) .add(Attributes.MAX_HEALTH, WitherSkeletonUnit.maxHealth) .add(Attributes.FOLLOW_RANGE, Unit.getFollowRange()) - .add(Attributes.ARMOR, WitherSkeletonUnit.armorValue); + .add(Attributes.ATTACK_KNOCKBACK, 0.5f) + .add(Attributes.ARMOR, WitherSkeletonUnit.armorValue) + .add(Attributes.KNOCKBACK_RESISTANCE, 0.5f); + } + + @Override + public void setRemainingFireTicks(int pRemainingFireTicks) { + if (!level().isClientSide()) { + boolean hasImmunityResearch = ResearchServerEvents.playerHasResearch(getOwnerName(), ProductionItems.RESEARCH_FIRE_RESISTANCE); + if (hasImmunityResearch && !hasEffect(MobEffectRegistrar.SOULS_AFLAME.get())) + pRemainingFireTicks = 0; + } + super.setRemainingFireTicks(pRemainingFireTicks); } @Override diff --git a/src/main/java/com/solegendary/reignofnether/unit/units/villagers/EnchanterUnit.java b/src/main/java/com/solegendary/reignofnether/unit/units/villagers/EnchanterUnit.java index c8d6eb848..986f50a25 100644 --- a/src/main/java/com/solegendary/reignofnether/unit/units/villagers/EnchanterUnit.java +++ b/src/main/java/com/solegendary/reignofnether/unit/units/villagers/EnchanterUnit.java @@ -40,6 +40,7 @@ import net.minecraft.util.Mth; import net.minecraft.world.DifficultyInstance; import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.damagesource.DamageTypes; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.*; import net.minecraft.world.entity.ai.attributes.AttributeInstance; @@ -317,7 +318,7 @@ protected void pickUpItem(ItemEntity pItemEntity) { } @Override public float getDamageAfterMagicAbsorb(DamageSource pSource, float pDamage) { pDamage = super.getDamageAfterMagicAbsorb(pSource, pDamage); - if (pSource.is(DamageTypeTags.WITCH_RESISTANT_TO)) + if (pSource.is(DamageTypeTags.WITCH_RESISTANT_TO) || pSource.is(DamageTypes.ON_FIRE)) pDamage *= 0.7F; return pDamage; } diff --git a/src/main/java/com/solegendary/reignofnether/unit/units/villagers/IronGolemUnit.java b/src/main/java/com/solegendary/reignofnether/unit/units/villagers/IronGolemUnit.java index d918d8ec7..e0da0c178 100644 --- a/src/main/java/com/solegendary/reignofnether/unit/units/villagers/IronGolemUnit.java +++ b/src/main/java/com/solegendary/reignofnether/unit/units/villagers/IronGolemUnit.java @@ -130,7 +130,7 @@ protected void defineSynchedData() { final static public float attackDamage = 10.0f; final static public float attacksPerSecond = 0.4f; - final static public float maxHealth = 140.0f; + final static public float maxHealth = 120.0f; final static public float armorValue = 0.0f; final static public float movementSpeed = 0.22f; final static public float attackRange = 3; // only used by ranged units or melee building attackers @@ -156,7 +156,7 @@ public IronGolemUnit(EntityType entityType, Level level) { updateAbilityButtons(); } - final static public float rangedDamageResist = 0.2f; + final static public float rangedDamageResist = 0.4f; @Override public double getUnitRangedArmorPercentage() { return rangedDamageResist; diff --git a/src/main/java/com/solegendary/reignofnether/unit/units/villagers/RoyalGuardUnit.java b/src/main/java/com/solegendary/reignofnether/unit/units/villagers/RoyalGuardUnit.java index 94bcb92c0..906ed8ef1 100644 --- a/src/main/java/com/solegendary/reignofnether/unit/units/villagers/RoyalGuardUnit.java +++ b/src/main/java/com/solegendary/reignofnether/unit/units/villagers/RoyalGuardUnit.java @@ -41,6 +41,7 @@ import net.minecraft.util.Mth; import net.minecraft.world.DifficultyInstance; import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.damagesource.DamageTypes; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.effect.MobEffects; import net.minecraft.world.entity.*; @@ -320,7 +321,7 @@ protected void pickUpItem(ItemEntity pItemEntity) { } @Override public float getDamageAfterMagicAbsorb(DamageSource pSource, float pDamage) { pDamage = super.getDamageAfterMagicAbsorb(pSource, pDamage); - if (pSource.is(DamageTypeTags.WITCH_RESISTANT_TO)) + if (pSource.is(DamageTypeTags.WITCH_RESISTANT_TO) || pSource.is(DamageTypes.ON_FIRE)) pDamage *= 0.7F; return pDamage; } diff --git a/src/main/java/com/solegendary/reignofnether/unit/units/villagers/WitchUnit.java b/src/main/java/com/solegendary/reignofnether/unit/units/villagers/WitchUnit.java index 92e8f9f67..731046cae 100644 --- a/src/main/java/com/solegendary/reignofnether/unit/units/villagers/WitchUnit.java +++ b/src/main/java/com/solegendary/reignofnether/unit/units/villagers/WitchUnit.java @@ -20,6 +20,9 @@ import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.sounds.SoundEvents; +import net.minecraft.tags.DamageTypeTags; +import net.minecraft.world.damagesource.DamageSource; +import net.minecraft.world.damagesource.DamageTypes; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; @@ -155,6 +158,18 @@ public WitchUnit(EntityType entityType, Level level) { updateAbilityButtons(); } + @Override + public float getDamageAfterMagicAbsorb(DamageSource pSource, float pDamage) { + pDamage = super.getDamageAfterMagicAbsorb(pSource, pDamage); + if (pSource.is(DamageTypeTags.WITCH_RESISTANT_TO)) { + pDamage *= 2.67; // 0.4 (60% less damage) after super's * 0.15 + } + if (pSource.is(DamageTypes.ON_FIRE)) { + pDamage *= 0.4; + } + return pDamage; + } + public int getPotionThrowRange() { if (GarrisonableBuilding.getGarrison(this) != null) return 16; diff --git a/src/main/java/com/solegendary/reignofnether/util/MiscUtil.java b/src/main/java/com/solegendary/reignofnether/util/MiscUtil.java index 14a69544d..64cc40ddc 100644 --- a/src/main/java/com/solegendary/reignofnether/util/MiscUtil.java +++ b/src/main/java/com/solegendary/reignofnether/util/MiscUtil.java @@ -26,6 +26,7 @@ import com.solegendary.reignofnether.unit.units.monsters.BoggedUnit; import com.solegendary.reignofnether.unit.units.monsters.PhantomSummon; import com.solegendary.reignofnether.unit.units.piglins.GhastUnit; +import com.solegendary.reignofnether.unit.units.piglins.WitherSkeletonUnit; import com.solegendary.reignofnether.unit.units.villagers.VillagerUnit; import com.solegendary.reignofnether.unit.units.villagers.VillagerUnitProfession; import net.minecraft.client.Minecraft; @@ -337,6 +338,18 @@ public static LivingEntity findClosestAttackableEntity(Mob unitMob, float range, } } } + // prioritise withered enemies for wither skeletons + else if (unitMob instanceof WitherSkeletonUnit) { + for (LivingEntity entity : entities) { + if (!(entity.position().distanceTo(new Vec3(unitPosition.x, unitPosition.y, unitPosition.z)) <= range) || + !entity.level().getWorldBorder().isWithinBounds(entity.blockPosition()) || !entity.hasEffect(MobEffects.WITHER)) { + continue; + } + if (isIdleOrMoveAttackable(unitMob, entity, neutralAggro) && hasLineOfSightForAttacks(unitMob, entity)) { + return entity; + } + } + } for (LivingEntity entity : entities) { if (!(entity.position().distanceTo(new Vec3(unitPosition.x, unitPosition.y, unitPosition.z)) <= range) || !entity.level().getWorldBorder().isWithinBounds(entity.blockPosition())) { diff --git a/src/main/resources/assets/reignofnether/lang/en_us.json b/src/main/resources/assets/reignofnether/lang/en_us.json index 315ee1f73..79f8fad13 100644 --- a/src/main/resources/assets/reignofnether/lang/en_us.json +++ b/src/main/resources/assets/reignofnether/lang/en_us.json @@ -260,9 +260,9 @@ "abilities.reignofnether.fancy_feast.stats": "\uE007 %d \uE004 %ds \uE008 %d", "abilities.reignofnether.fancy_feast.tooltip1": "Throws out a pile of food that units eat to heal.", "abilities.reignofnether.fancy_feast.tooltip2": "Throws %d items + %d & %d mana refund per 100 food spent.", - "abilities.reignofnether.fancy_feast.rank1": "Rank 1: Throws bread for +10 hp per item", - "abilities.reignofnether.fancy_feast.rank2": "Rank 2: Throws chicken for +15 hp per item", - "abilities.reignofnether.fancy_feast.rank3": "Rank 3: Throws beef for +20 hp per item", + "abilities.reignofnether.fancy_feast.rank1": "Rank 1: Throws bread for +%d hp per item", + "abilities.reignofnether.fancy_feast.rank2": "Rank 2: Throws chicken for +%d hp per item", + "abilities.reignofnether.fancy_feast.rank3": "Rank 3: Throws beef for +%d hp per item", "abilities.reignofnether.greed_is_good": "Greed is Good (Passive)", "abilities.reignofnether.greed_is_good.tooltip1": "Other spells spend resources to be empowered and refund mana", "abilities.reignofnether.greed_is_good.tooltip2": "Spends up to %d resources per spell cast.", @@ -286,7 +286,7 @@ "abilities.reignofnether.scorching_gaze": "Scorching Gaze", "abilities.reignofnether.scorching_gaze.stats": "\uE004 %ds \uE005 %ds \uE008 %d", "abilities.reignofnether.scorching_gaze.tooltip1": "Focus a burning hatred for a single enemy, engulfing it in flames", - "abilities.reignofnether.scorching_gaze.tooltip2": "that doubles fire damage taken and leaves a trail of magma.", + "abilities.reignofnether.scorching_gaze.tooltip2": "that triples fire tick damage and leaves a trail of magma.", "abilities.reignofnether.scorching_gaze.tooltip3": "Units that die under this effect pass it to another nearby friendly unit.", "abilities.reignofnether.scorching_gaze.rank1": "Rank 1: Lasts %ds", "abilities.reignofnether.scorching_gaze.rank2": "Rank 2: Lasts %ds", @@ -870,8 +870,8 @@ "research.reignofnether.research_drowned.tooltip3": "Requires a Graveyard.", "research.reignofnether.evoker_vexes": "Vexing Summons", "research.reignofnether.evoker_vexes.tooltip1": "Unlocks the ability for evokers to summon vexes.", - "research.reignofnether.fire_resistance": "Fire Resistance", - "research.reignofnether.fire_resistance.tooltip1": "Your units become immune to regular fire damage.", + "research.reignofnether.fire_resistance": "Charred Bones", + "research.reignofnether.fire_resistance.tooltip1": "Wither Skeletons become immune to regular fire damage.", "research.reignofnether.fire_resistance.tooltip2": "Does not protect against soulfire or lava.", "research.reignofnether.golem_smithing": "Golem Smithing", "research.reignofnether.golem_smithing.tooltip1": "Allows villagers to construct iron golems.", @@ -943,7 +943,7 @@ "research.reignofnether.militia_bows": "Militia Archer Training", "research.reignofnether.militia_bows.tooltip1": "Allows Militia to swap to a ranged bow attack in ", "research.reignofnether.militia_bows.tooltip2": "exchange for lower attack, move speed and armor.", - "research.reignofnether.wither_clouds": "Wither Clouds", + "research.reignofnether.wither_clouds": "Wither Death Clouds", "research.reignofnether.wither_clouds.tooltip1": "Unlocks the ability for Wither Skeletons to produce ", "research.reignofnether.wither_clouds.tooltip2": "clouds of wither around them for a few seconds.", "research.reignofnether.bloodlust": "Bloodlust", diff --git a/src/main/resources/reignofnether.mixins.json b/src/main/resources/reignofnether.mixins.json index ec000cb4b..606c50a43 100644 --- a/src/main/resources/reignofnether.mixins.json +++ b/src/main/resources/reignofnether.mixins.json @@ -30,6 +30,7 @@ "WebBlockMixin", "WitchMixin", "fire.BaseFireBlockMixin", + "fire.CampfireBlockMixin", "fire.FireBlockMixin", "fire.MagmaBlockMixin", "fire.WalkNodeEvaluatorMixin",