From 556bbd61b37472ef8cd8d6c36b07d64e1dceb63c Mon Sep 17 00:00:00 2001 From: Raycoms Date: Mon, 23 Dec 2024 11:11:05 +0100 Subject: [PATCH] Raid fixes (#10509) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rework raid messages for raid ending, they now got an individual finished message followed by a general victory message for the whole raid Fix campfires getting spawned incorrectly, due to not loading a chunk when required to Reworked North/South directions util, it is now split into 8 sections a 45° to give proper ranges for North/Northeast etc Fix door break speed, research no longer strengthens normal doors and doors break slightly faster with more raiders hitting it. Improved despawn of few remaining raiders to not stall raids for longer than needed Full raid end is now handled by the raid manager Added more message variants to raid end messages Removed attackspeed scaling from archers, as those already scale in attack damage --- .../colony/colonyEvents/IColonyRaidEvent.java | 5 -- .../managers/interfaces/IRaiderManager.java | 5 +- .../minecolonies/api/util/BlockPosUtil.java | 79 +++++++++++++------ .../util/constant/TranslationConstants.java | 13 ++- .../initializer/ModBlocksInitializer.java | 4 +- .../events/raid/AbstractShipRaidEvent.java | 48 ++++++----- .../colony/events/raid/HordeRaidEvent.java | 53 ++++--------- .../core/colony/events/raid/RaidManager.java | 46 ++++++++++- .../pirateEvent/DrownedPirateRaidEvent.java | 18 +---- .../pirateEvent/PirateGroundRaidEvent.java | 6 -- .../ai/workers/guard/RangerCombatAI.java | 16 ++-- .../mobs/aitasks/EntityAIBreakDoor.java | 2 +- .../minecolonies/lang/manual_en_us.json | 33 ++++++-- 13 files changed, 189 insertions(+), 139 deletions(-) diff --git a/src/main/java/com/minecolonies/api/colony/colonyEvents/IColonyRaidEvent.java b/src/main/java/com/minecolonies/api/colony/colonyEvents/IColonyRaidEvent.java index 511bc895343..6da3f3be0d9 100755 --- a/src/main/java/com/minecolonies/api/colony/colonyEvents/IColonyRaidEvent.java +++ b/src/main/java/com/minecolonies/api/colony/colonyEvents/IColonyRaidEvent.java @@ -51,9 +51,4 @@ default boolean isRaidActive() { return getStatus() == EventStatus.PROGRESSING ||getStatus() == EventStatus.PREPARING; } - - /** - * Set the raid event to mercy. - */ - void setMercyEnd(); } diff --git a/src/main/java/com/minecolonies/api/colony/managers/interfaces/IRaiderManager.java b/src/main/java/com/minecolonies/api/colony/managers/interfaces/IRaiderManager.java index 604b2f16a19..d53bc1a42db 100755 --- a/src/main/java/com/minecolonies/api/colony/managers/interfaces/IRaiderManager.java +++ b/src/main/java/com/minecolonies/api/colony/managers/interfaces/IRaiderManager.java @@ -2,6 +2,7 @@ import com.minecolonies.api.colony.ICitizenData; import com.minecolonies.api.entity.mobs.AbstractEntityMinecoloniesRaider; +import com.minecolonies.api.colony.colonyEvents.IColonyRaidEvent; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; @@ -206,7 +207,7 @@ default RaidSpawnResult raiderEvent(String raidType, final boolean overrideConfi /** * Gets the amount of citizens lost in a raid. * - * @return weighted amount of list citizen + * @return amount */ int getLostCitizen(); @@ -217,6 +218,8 @@ default RaidSpawnResult raiderEvent(String raidType, final boolean overrideConfi */ void onRaiderDeath(AbstractEntityMinecoloniesRaider entity); + void onRaidEventFinished(IColonyRaidEvent event); + /** * Notify raid manager of a passing through raid. */ diff --git a/src/main/java/com/minecolonies/api/util/BlockPosUtil.java b/src/main/java/com/minecolonies/api/util/BlockPosUtil.java index 7819e108dfa..d18c6c8e5f6 100755 --- a/src/main/java/com/minecolonies/api/util/BlockPosUtil.java +++ b/src/main/java/com/minecolonies/api/util/BlockPosUtil.java @@ -144,11 +144,27 @@ public static BlockPos getRandomPosAround(final BlockPos center, final int dista * @return the BlockPos. */ public static BlockPos getRandomPosition(final Level world, final BlockPos currentPosition, final BlockPos def, final int minDist, final int maxDist) + { + return getRandomPosition(world, currentPosition, def, minDist, maxDist, false); + } + + /** + * Gets a random position within a certain range for wandering around. + * + * @param world the world. + * @param currentPosition the current position. + * @param def the default position if none was found. + * @param minDist the minimum distance of the pos. + * @param maxDist the maximum distance. + * @param load whether chunks should get loaded if needed + * @return the BlockPos. + */ + public static BlockPos getRandomPosition(final Level world, final BlockPos currentPosition, final BlockPos def, final int minDist, final int maxDist, final boolean load) { int tries = 0; BlockPos pos = null; while (pos == null - || !WorldUtil.isEntityBlockLoaded(world, pos) + || !load && !WorldUtil.isEntityBlockLoaded(world, pos) || world.getBlockState(pos).liquid() || !BlockUtils.isAnySolid(world.getBlockState(pos.below())) || (!world.isEmptyBlock(pos) || !world.isEmptyBlock(pos.above()))) @@ -893,46 +909,59 @@ public static DirectionResult calcDirection(@NotNull final BlockPos building, @N { if (pos.getY() > building.getY()) { - direction = DirectionResult.UP; + return DirectionResult.UP; } else if (pos.getY() < building.getY()) { - direction = DirectionResult.DOWN; + return DirectionResult.DOWN; + } + else + { + return DirectionResult.SAME; } } - // If a building is greater or smaller in the Z direction, either return north or south - if (pos.getZ() > building.getZ()) + final int xDiff = building.getX() - pos.getX(); + final int zDiff = building.getZ() - pos.getZ(); + int degree = (int) (Math.atan2(xDiff, zDiff) * 180 / Math.PI); + if (degree < 0) { - direction = DirectionResult.SOUTH; + degree += 360; } - else if (pos.getZ() < building.getZ()) + + if (degree <= 22 || degree >= 338) { direction = DirectionResult.NORTH; } - - // If a building is greater or smaller in the X direction, either return west or east - // If previously already north or south was selected, create a compound direction (north/east etc) - if (pos.getX() > building.getX()) + else if (degree > 22 && degree < 67) + { + direction = DirectionResult.NORTH_WEST; + } + else if (degree >= 67 && degree <= 112) + { + direction = DirectionResult.WEST; + } + else if (degree > 112 && degree < 157) { - direction = switch (direction) - { - case NORTH -> DirectionResult.NORTH_EAST; - case SOUTH -> DirectionResult.SOUTH_EAST; - default -> DirectionResult.EAST; - }; + direction = DirectionResult.SOUTH_WEST; } - else if (pos.getX() < building.getX()) + else if (degree >= 157 && degree <= 202) + { + direction = DirectionResult.SOUTH; + } + else if (degree > 202 && degree < 247) + { + direction = DirectionResult.SOUTH_EAST; + } + else if (degree >= 247 && degree <= 292) + { + direction = DirectionResult.EAST; + } + else { - direction = switch (direction) - { - case NORTH -> DirectionResult.NORTH_WEST; - case SOUTH -> DirectionResult.SOUTH_WEST; - default -> DirectionResult.WEST; - }; + direction = DirectionResult.NORTH_EAST; } - // In case that none of the checks pass (XYZ fully identical to the building), return a component saying the positions are identical return direction; } diff --git a/src/main/java/com/minecolonies/api/util/constant/TranslationConstants.java b/src/main/java/com/minecolonies/api/util/constant/TranslationConstants.java index 25ac269c787..97da049b2e2 100755 --- a/src/main/java/com/minecolonies/api/util/constant/TranslationConstants.java +++ b/src/main/java/com/minecolonies/api/util/constant/TranslationConstants.java @@ -206,13 +206,14 @@ public final class TranslationConstants @NonNls public static final String RAID_NORSEMEN = "com.minecolonies.coremod.raid.norsemen.name"; @NonNls - public static final String ONLY_X_BARBARIANS_LEFT_MESSAGE = "com.minecolonies.coremod.barbarians.left"; + public static final String ONLY_X_BARBARIANS_LEFT_MESSAGE = "com.minecolonies.coremod.barbarians.left"; @NonNls - public static final String ALL_BARBARIANS_KILLED_MESSAGE = "com.minecolonies.coremod.barbarians.killed"; + public static final String INDIVIDUAL_RAID_FINISH = "com.minecolonies.coremod.raid.end"; @NonNls - public static final String ALL_BARBARIANS_MERCY_MESSAGE = "com.minecolonies.core.barbarians.mercy"; + public static final String RAID_END_MERCY = "com.minecolonies.core.barbarians.mercy"; + public static final String RAID_END = "com.minecolonies.coremod.barbarians.killed"; @NonNls - public static final String CANT_PLACE_COLONY_TOO_CLOSE_TO_SPAWN = "com.minecolonies.core.founding.tooclosetospawn"; + public static final String CANT_PLACE_COLONY_TOO_CLOSE_TO_SPAWN = "com.minecolonies.core.founding.tooclosetospawn"; @NonNls public static final String CANT_PLACE_COLONY_TOO_FAR_FROM_SPAWN = "com.minecolonies.core.founding.toofarfromspawn"; @NonNls @@ -262,9 +263,7 @@ public final class TranslationConstants @NonNls public static final String CMC_GUI_TOWNHALL_BUILDING_LEVEL = "com.minecolonies.coremod.gui.townhall.buildinglevel"; @NonNls - public static final String PIRATES_SAILING_OFF_MESSAGE = "com.minecolonies.coremod.pirates.sailing.away"; - @NonNls - public static final String DROWNED_PIRATES_SAILING_OFF_MESSAGE = "com.minecolonies.core.drowned_pirates.sailing.away"; + public static final String PIRATES_SAILING_OFF_MESSAGE = "com.minecolonies.coremod.raid.sailing.away"; @NonNls public static final String STRUCTURE_SPAWNER_BREAKS = "com.minecolonies.core.raidevent.spawnerbreaks"; @NonNls diff --git a/src/main/java/com/minecolonies/apiimp/initializer/ModBlocksInitializer.java b/src/main/java/com/minecolonies/apiimp/initializer/ModBlocksInitializer.java index 181452419a7..36ad1a399f0 100755 --- a/src/main/java/com/minecolonies/apiimp/initializer/ModBlocksInitializer.java +++ b/src/main/java/com/minecolonies/apiimp/initializer/ModBlocksInitializer.java @@ -119,8 +119,8 @@ public static void init(final Registry registry) ModBlocks.blockCompostedDirt = new BlockCompostedDirt().registerBlock(registry); ModBlocks.blockColonyBanner = new BlockColonyFlagBanner().registerBlock(registry); ModBlocks.blockColonyWallBanner = new BlockColonyFlagWallBanner().registerBlock(registry); - ModBlocks.blockIronGate = new BlockGate(IRON_GATE, 5f, 6, 8).registerBlock(registry); - ModBlocks.blockWoodenGate = new BlockGate(WOODEN_GATE, 4f, 6, 5).registerBlock(registry); + ModBlocks.blockIronGate = new BlockGate(IRON_GATE, 10f, 6, 8).registerBlock(registry); + ModBlocks.blockWoodenGate = new BlockGate(WOODEN_GATE, 7f, 6, 5).registerBlock(registry); ModBlocks.farmland = new MinecoloniesFarmland(FARMLAND, false, 15.0).registerBlock(registry); ModBlocks.floodedFarmland = new MinecoloniesFarmland(FLOODED_FARMLAND, true, 13.0).registerBlock(registry); diff --git a/src/main/java/com/minecolonies/core/colony/events/raid/AbstractShipRaidEvent.java b/src/main/java/com/minecolonies/core/colony/events/raid/AbstractShipRaidEvent.java index ca3fb40be9f..b1845ad0a9d 100644 --- a/src/main/java/com/minecolonies/core/colony/events/raid/AbstractShipRaidEvent.java +++ b/src/main/java/com/minecolonies/core/colony/events/raid/AbstractShipRaidEvent.java @@ -12,6 +12,9 @@ import com.minecolonies.api.entity.mobs.RaiderMobUtils; import com.minecolonies.api.util.*; import com.minecolonies.api.util.MessageUtils.MessagePriority; +import com.minecolonies.api.util.Tuple; +import com.minecolonies.api.util.WorldUtil; +import com.minecolonies.api.util.constant.ColonyConstants; import com.minecolonies.core.colony.events.raid.pirateEvent.ShipBasedRaiderUtils; import com.minecolonies.core.colony.events.raid.pirateEvent.ShipSize; import com.minecolonies.core.entity.pathfinding.pathresults.PathResult; @@ -310,16 +313,10 @@ public boolean isUnderWater() return false; } - @Override - public void setMercyEnd() - { - // Noop, the sailing away message is fine. - } - @Override public void onFinish() { - MessageUtils.format(PIRATES_SAILING_OFF_MESSAGE, BlockPosUtil.calcDirection(colony.getCenter(), spawnPoint).getLongText(), colony.getName()) + MessageUtils.format(PIRATES_SAILING_OFF_MESSAGE, BlockPosUtil.calcDirection(colony.getCenter(), spawnPoint).getLongText()) .sendTo(colony).forManagers(); for (final Entity entity : raiders.keySet()) { @@ -338,12 +335,22 @@ public void onTileEntityBreak(final BlockEntity te) spawners.remove(te.getBlockPos()); raidBar.setProgress((float) spawners.size() / maxSpawners); - // remove at nightfall after spawners are killed. - if (spawners.isEmpty()) - { - daysToGo = 2; - MessageUtils.format(ALL_PIRATE_SPAWNERS_DESTROYED_MESSAGE, colony.getName()).sendTo(colony).forManagers(); - } + checkRaidEnd(); + } + } + + /** + * Checks if the raid got defeated, announces it and sets the remaining days for the ship + */ + private void checkRaidEnd() + { + if (raiders.isEmpty() && spawners.isEmpty()) + { + status = EventStatus.WAITING; + colony.getRaiderManager().onRaidEventFinished(this); + daysToGo = 1; + MessageUtils.format(INDIVIDUAL_RAID_FINISH + "." + this.getEventTypeID().getPath() + ColonyConstants.rand.nextInt(3), + BlockPosUtil.calcDirection(colony.getCenter(), spawnPoint).getLongText()).sendTo(colony, true).forManagers(); } } @@ -360,26 +367,17 @@ public void onNightFall() @Override public void onEntityDeath(final LivingEntity entity) { - raiders.remove(entity); - if (raiders.isEmpty() && spawners.isEmpty()) - { - status = EventStatus.WAITING; - MessageUtils.format(ALL_PIRATES_KILLED_MESSAGE, colony.getName()).sendTo(colony).forManagers(); - } spawnerThresholdKillTracker++; if (!spawners.isEmpty() && spawnerThresholdKillTracker > maxRaiderCount/maxSpawners) { - MessageUtils.format(STRUCTURE_SPAWNER_BREAKS, colony.getName()).sendTo(colony).forManagers(); colony.getWorld().removeBlock(spawners.remove(0), false); raidBar.setProgress((float) spawners.size() / maxSpawners); spawnerThresholdKillTracker = 0; - if (spawners.isEmpty()) - { - daysToGo = 1; - MessageUtils.format(ALL_PIRATE_SPAWNERS_DESTROYED_MESSAGE, colony.getName()).sendTo(colony).forManagers(); - } } + + raiders.remove(entity); + checkRaidEnd(); } @Override diff --git a/src/main/java/com/minecolonies/core/colony/events/raid/HordeRaidEvent.java b/src/main/java/com/minecolonies/core/colony/events/raid/HordeRaidEvent.java index 166fd082d4b..08c68b0c0b6 100644 --- a/src/main/java/com/minecolonies/core/colony/events/raid/HordeRaidEvent.java +++ b/src/main/java/com/minecolonies/core/colony/events/raid/HordeRaidEvent.java @@ -6,13 +6,12 @@ import com.minecolonies.api.colony.colonyEvents.IColonyCampFireRaidEvent; import com.minecolonies.api.colony.colonyEvents.IColonyEvent; import com.minecolonies.api.colony.colonyEvents.IColonyRaidEvent; -import com.minecolonies.api.entity.citizen.happiness.ExpirationBasedHappinessModifier; -import com.minecolonies.api.entity.citizen.happiness.StaticHappinessSupplier; import com.minecolonies.api.entity.mobs.AbstractEntityMinecoloniesRaider; import com.minecolonies.api.entity.mobs.RaiderMobUtils; import com.minecolonies.api.sounds.RaidSounds; import com.minecolonies.api.util.*; import com.minecolonies.api.util.MessageUtils.MessagePriority; +import com.minecolonies.api.util.constant.ColonyConstants; import com.minecolonies.api.util.constant.NbtTagConstants; import com.minecolonies.core.colony.events.raid.barbarianEvent.Horde; import com.minecolonies.core.colony.events.raid.pirateEvent.ShipBasedRaiderUtils; @@ -43,7 +42,6 @@ import static com.minecolonies.api.util.constant.ColonyConstants.SMALL_HORDE_SIZE; import static com.minecolonies.api.util.constant.Constants.TAG_COMPOUND; -import static com.minecolonies.api.util.constant.HappinessConstants.RAIDWITHOUTDEATH; import static com.minecolonies.api.util.constant.NbtTagConstants.*; import static com.minecolonies.api.util.constant.TranslationConstants.*; import static com.minecolonies.core.colony.events.raid.pirateEvent.PirateRaidEvent.TAG_DAYS_LEFT; @@ -135,11 +133,6 @@ public abstract class HordeRaidEvent implements IColonyRaidEvent, IColonyCampFir */ private PathResult spawnPathResult; - /** - * If this was a mercy end. - */ - private boolean mercyEnd = false; - /** * Waypoints helping raiders travel */ @@ -245,12 +238,6 @@ protected void spawnHorde(final BlockPos spawnPos, final IColony colony, final i RaiderMobUtils.spawn(getArcherRaiderType(), numberOfArchers, spawnPos, colony.getWorld(), colony, id); } - @Override - public void setMercyEnd() - { - this.mercyEnd = true; - } - /** * Prepares the horde event, makes them wait at campfires for a while,deciding on their plans. */ @@ -275,7 +262,7 @@ private void spawnCampFires(final BlockPos pos) { for (int tries = 0; tries < 3; tries++) { - BlockPos spawn = BlockPosUtil.getRandomPosition(colony.getWorld(), pos, BlockPos.ZERO, 3, 7); + BlockPos spawn = BlockPosUtil.getRandomPosition(colony.getWorld(), pos, BlockPos.ZERO, 3, 7, true); if (spawn != BlockPos.ZERO) { colony.getWorld().setBlockAndUpdate(spawn, Blocks.CAMPFIRE.defaultBlockState()); @@ -289,6 +276,7 @@ private void spawnCampFires(final BlockPos pos) @Override public void onFinish() { + colony.getRaiderManager().onRaidEventFinished(this); for (final Entity entity : getEntities()) { entity.remove(Entity.RemovalReason.DISCARDED); @@ -301,18 +289,6 @@ public void onFinish() raidBar.setVisible(false); raidBar.removeAllPlayers(); - - if (horde.hordeSize > 0) - { - if (mercyEnd) - { - MessageUtils.format(ALL_BARBARIANS_MERCY_MESSAGE, colony.getName()).sendTo(colony).forManagers(); - } - else - { - MessageUtils.format(ALL_BARBARIANS_KILLED_MESSAGE, colony.getName()).sendTo(colony).forManagers(); - } - } } @Override @@ -436,6 +412,7 @@ public void onUpdate() if (horde.hordeSize <= 0) { status = EventStatus.DONE; + return; } if (!respawns.isEmpty()) @@ -461,8 +438,9 @@ public void onUpdate() } } - if (horde.numberOfBosses + horde.numberOfRaiders + horde.numberOfArchers < Math.round(horde.initialSize * 0.05)) + if (horde.numberOfBosses + horde.numberOfRaiders + horde.numberOfArchers < Math.floor(horde.initialSize * 0.1)) { + announceWin(); status = EventStatus.DONE; } @@ -482,6 +460,15 @@ public void onUpdate() } } + /** + * Sends the winning message + */ + private void announceWin() + { + MessageUtils.format(INDIVIDUAL_RAID_FINISH + "." + this.getEventTypeID().getPath() + ColonyConstants.rand.nextInt(3), + BlockPosUtil.calcDirection(colony.getCenter(), spawnPoint).getLongText()).sendTo(colony, true).forManagers(); + } + /** * Sends the right horde message. */ @@ -500,15 +487,7 @@ protected void sendHordeMessage() if (total == 0) { - MessageUtils.format(ALL_BARBARIANS_KILLED_MESSAGE, colony.getName()).sendTo(colony).forManagers(); - - PlayAudioMessage audio = new PlayAudioMessage(horde.initialSize <= SMALL_HORDE_SIZE ? RaidSounds.VICTORY_EARLY : RaidSounds.VICTORY, SoundSource.RECORDS); - PlayAudioMessage.sendToAll(getColony(), false, true, audio); - - if (colony.getRaiderManager().getLostCitizen() == 0) - { - colony.getCitizenManager().injectModifier(new ExpirationBasedHappinessModifier(RAIDWITHOUTDEATH, 1.0, new StaticHappinessSupplier(2.0), 3)); - } + announceWin(); } else if (total > 0 && total <= SMALL_HORDE_SIZE) { diff --git a/src/main/java/com/minecolonies/core/colony/events/raid/RaidManager.java b/src/main/java/com/minecolonies/core/colony/events/raid/RaidManager.java index 6b0b9d731d9..8d26219b916 100644 --- a/src/main/java/com/minecolonies/core/colony/events/raid/RaidManager.java +++ b/src/main/java/com/minecolonies/core/colony/events/raid/RaidManager.java @@ -10,7 +10,10 @@ import com.minecolonies.api.colony.colonyEvents.IColonyRaidEvent; import com.minecolonies.api.colony.managers.interfaces.IRaiderManager; import com.minecolonies.api.entity.citizen.AbstractEntityCitizen; +import com.minecolonies.api.entity.citizen.happiness.ExpirationBasedHappinessModifier; +import com.minecolonies.api.entity.citizen.happiness.StaticHappinessSupplier; import com.minecolonies.api.entity.mobs.AbstractEntityMinecoloniesRaider; +import com.minecolonies.api.sounds.RaidSounds; import com.minecolonies.api.util.*; import com.minecolonies.api.util.constant.ColonyConstants; import com.minecolonies.core.MineColonies; @@ -32,6 +35,7 @@ import com.minecolonies.core.entity.pathfinding.PathfindingUtils; import com.minecolonies.core.entity.pathfinding.pathjobs.PathJobRaiderPathing; import com.minecolonies.core.entity.pathfinding.pathresults.PathResult; +import com.minecolonies.core.network.messages.client.PlayAudioMessage; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.nbt.CompoundTag; @@ -39,6 +43,7 @@ import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundSource; import net.minecraft.tags.BiomeTags; import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Player; @@ -57,10 +62,14 @@ import static com.minecolonies.api.util.BlockPosUtil.DOUBLE_AIR_POS_SELECTOR; import static com.minecolonies.api.util.BlockPosUtil.SOLID_AIR_POS_SELECTOR; import static com.minecolonies.api.util.constant.ColonyConstants.BIG_HORDE_SIZE; +import static com.minecolonies.api.util.constant.ColonyConstants.SMALL_HORDE_SIZE; import static com.minecolonies.api.util.constant.ColonyManagerConstants.NO_COLONY_ID; import static com.minecolonies.api.util.constant.Constants.DEFAULT_BARBARIAN_DIFFICULTY; import static com.minecolonies.api.util.constant.Constants.TICKS_SECOND; +import static com.minecolonies.api.util.constant.HappinessConstants.RAIDWITHOUTDEATH; import static com.minecolonies.api.util.constant.NbtTagConstants.*; +import static com.minecolonies.api.util.constant.TranslationConstants.RAID_END; +import static com.minecolonies.api.util.constant.TranslationConstants.RAID_END_MERCY; /** * Handles spawning hostile raid events. @@ -950,7 +959,6 @@ public void onLostCitizen(final ICitizenData citizen) if (event instanceof IColonyRaidEvent raidEvent) { raidEvent.setStatus(EventStatus.DONE); - raidEvent.setMercyEnd(); } } } @@ -1022,6 +1030,42 @@ public void onRaiderDeath(final AbstractEntityMinecoloniesRaider entity) } } + @Override + public void onRaidEventFinished(final IColonyRaidEvent finishedRaid) + { + for (final IColonyEvent event : colony.getEventManager().getEvents().values()) + { + if (event instanceof IColonyRaidEvent raidEvent && raidEvent.getStatus() == EventStatus.PROGRESSING) + { + return; + } + } + + if (((double) raidHistories.get(0).lostCitizens / colony.getCitizenManager().getMaxCitizens()) > 0.5) + { + MessageUtils.format(RAID_END_MERCY, colony.getName()).sendTo(colony).forManagers(); + } + else + { + String msgID = RAID_END; + int rng = ColonyConstants.rand.nextInt(3); + if (rng > 0) + { + msgID += rng; + } + + MessageUtils.format(msgID, colony.getName()).sendTo(colony).forManagers(); + } + + PlayAudioMessage audio = new PlayAudioMessage(raidHistories.get(0).raiderAmount <= SMALL_HORDE_SIZE ? RaidSounds.VICTORY_EARLY : RaidSounds.VICTORY, SoundSource.RECORDS); + PlayAudioMessage.sendToAll(colony, false, true, audio); + + if (colony.getRaiderManager().getLostCitizen() == 0) + { + colony.getCitizenManager().injectModifier(new ExpirationBasedHappinessModifier(RAIDWITHOUTDEATH, 1.0, new StaticHappinessSupplier(2.0), 3)); + } + } + /** * List of raid histories * diff --git a/src/main/java/com/minecolonies/core/colony/events/raid/pirateEvent/DrownedPirateRaidEvent.java b/src/main/java/com/minecolonies/core/colony/events/raid/pirateEvent/DrownedPirateRaidEvent.java index ab53298e712..e0ac7f52b87 100644 --- a/src/main/java/com/minecolonies/core/colony/events/raid/pirateEvent/DrownedPirateRaidEvent.java +++ b/src/main/java/com/minecolonies/core/colony/events/raid/pirateEvent/DrownedPirateRaidEvent.java @@ -17,13 +17,13 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.level.pathfinder.Path; import org.jetbrains.annotations.NotNull; import static com.minecolonies.api.util.constant.Constants.STORAGE_STYLE; -import static com.minecolonies.api.util.constant.TranslationConstants.*; +import static com.minecolonies.api.util.constant.TranslationConstants.RAID_EVENT_MESSAGE_U_PIRATE; +import static com.minecolonies.api.util.constant.TranslationConstants.RAID_PIRATE; /** * The Pirate raid event, spawns a ship with pirate spawners onboard. @@ -166,18 +166,4 @@ protected void updateRaidBar() super.updateRaidBar(); raidBar.setDarkenScreen(true); } - - @Override - public void onFinish() - { - MessageUtils.format(DROWNED_PIRATES_SAILING_OFF_MESSAGE, BlockPosUtil.calcDirection(colony.getCenter(), spawnPoint).getLongText(), colony.getName()) - .sendTo(colony).forManagers(); - for (final Entity entity : raiders.keySet()) - { - entity.remove(Entity.RemovalReason.DISCARDED); - } - - raidBar.setVisible(false); - raidBar.removeAllPlayers(); - } } diff --git a/src/main/java/com/minecolonies/core/colony/events/raid/pirateEvent/PirateGroundRaidEvent.java b/src/main/java/com/minecolonies/core/colony/events/raid/pirateEvent/PirateGroundRaidEvent.java index 3531062c7da..1e5adadade7 100644 --- a/src/main/java/com/minecolonies/core/colony/events/raid/pirateEvent/PirateGroundRaidEvent.java +++ b/src/main/java/com/minecolonies/core/colony/events/raid/pirateEvent/PirateGroundRaidEvent.java @@ -61,12 +61,6 @@ public void onUpdate() super.onUpdate(); } - @Override - public void onFinish() - { - super.onFinish(); - } - @Override public void registerEntity(final Entity entity) { diff --git a/src/main/java/com/minecolonies/core/entity/ai/workers/guard/RangerCombatAI.java b/src/main/java/com/minecolonies/core/entity/ai/workers/guard/RangerCombatAI.java index f6e5b146480..54dde8a99ae 100644 --- a/src/main/java/com/minecolonies/core/entity/ai/workers/guard/RangerCombatAI.java +++ b/src/main/java/com/minecolonies/core/entity/ai/workers/guard/RangerCombatAI.java @@ -6,10 +6,6 @@ import com.minecolonies.api.equipment.ModEquipmentTypes; import com.minecolonies.api.util.*; import com.minecolonies.api.util.constant.ColonyConstants; -import com.minecolonies.core.util.citizenutils.CitizenItemUtils; -import com.minecolonies.core.entity.pathfinding.PathfindingUtils; -import com.minecolonies.core.entity.pathfinding.pathresults.PathResult; -import com.minecolonies.core.entity.pathfinding.PathingOptions; import com.minecolonies.api.util.constant.Constants; import com.minecolonies.core.MineColonies; import com.minecolonies.core.colony.buildings.AbstractBuildingGuards; @@ -19,8 +15,14 @@ import com.minecolonies.core.entity.ai.combat.CombatUtils; import com.minecolonies.core.entity.citizen.EntityCitizen; import com.minecolonies.core.entity.other.CustomArrowEntity; +import com.minecolonies.core.entity.pathfinding.PathfindingUtils; +import com.minecolonies.core.entity.pathfinding.PathingOptions; import com.minecolonies.core.entity.pathfinding.navigation.MinecoloniesAdvancedPathNavigate; -import com.minecolonies.core.entity.pathfinding.pathjobs.*; +import com.minecolonies.core.entity.pathfinding.pathjobs.PathJobCanSee; +import com.minecolonies.core.entity.pathfinding.pathjobs.PathJobMoveAwayFromLocation; +import com.minecolonies.core.entity.pathfinding.pathjobs.PathJobMoveToLocation; +import com.minecolonies.core.entity.pathfinding.pathresults.PathResult; +import com.minecolonies.core.util.citizenutils.CitizenItemUtils; import net.minecraft.network.chat.contents.TranslatableContents; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; @@ -225,9 +227,7 @@ protected double getAttackDistance() @Override protected int getAttackDelay() { - // TODO: Maybe better for balancing to not increase damage and speed, looks odd and drains arrows/bow durability - final int attackDelay = RANGED_ATTACK_DELAY_BASE - (user.getCitizenData().getCitizenSkillHandler().getLevel(Skill.Adaptability)); - return Math.max(attackDelay, PHYSICAL_ATTACK_DELAY_MIN * 2); + return RANGED_ATTACK_DELAY_BASE; } /** diff --git a/src/main/java/com/minecolonies/core/entity/mobs/aitasks/EntityAIBreakDoor.java b/src/main/java/com/minecolonies/core/entity/mobs/aitasks/EntityAIBreakDoor.java index 1715564a7ec..15588eb67da 100755 --- a/src/main/java/com/minecolonies/core/entity/mobs/aitasks/EntityAIBreakDoor.java +++ b/src/main/java/com/minecolonies/core/entity/mobs/aitasks/EntityAIBreakDoor.java @@ -90,7 +90,7 @@ public void tick() } else { - int fasterBreakPerXNearby = 5; + double fasterBreakPerXNearby = 5; if (mob instanceof AbstractEntityMinecoloniesRaider && !mob.level().isClientSide() && mob.level().getBlockState(doorPos).getBlock() instanceof AbstractBlockGate) { diff --git a/src/main/resources/assets/minecolonies/lang/manual_en_us.json b/src/main/resources/assets/minecolonies/lang/manual_en_us.json index 8210b675738..480e8479c1a 100644 --- a/src/main/resources/assets/minecolonies/lang/manual_en_us.json +++ b/src/main/resources/assets/minecolonies/lang/manual_en_us.json @@ -1006,9 +1006,36 @@ "com.minecolonies.coremod.gui.workerhuts.barbpoints": "Last Barbarian Spawns", "com.minecolonies.coremod.gui.workerhuts.barbpoints.current": "Current Barbarian Position", "com.minecolonies.coremod.barbarians.left": "Only %d raiders left!", - "com.minecolonies.coremod.barbarians.killed": "§2Victory! %s successfully defended against the intruders!", + "com.minecolonies.coremod.barbarians.killed": "§2Victory! %s successfully defended against the invaders!", + "com.minecolonies.coremod.barbarians.killed1": "§2You successfully defended %s against an invasion of raiders, they were a poor match for your defences!", + "com.minecolonies.coremod.barbarians.killed2": "§2Together, the brave defenders of %s stood tall and drove the invaders into the shadows!", + "com.minecolonies.coremod.raid.end.amazon_raid0": "The Amazon Warriors from the %s have been pushed back into the forest.", + "com.minecolonies.coremod.raid.end.barbarian_raid0": "The Barbarians from the %s met their match and were defeated.", + "com.minecolonies.coremod.raid.end.egyptian_raid0": "The Ancient Mummies from the %s have returned to dust.", + "com.minecolonies.coremod.raid.end.norsemen_raid0": "The Norsemen from the %s have departed for Valhalla.", + "com.minecolonies.coremod.raid.end.norsemen_ship_raid0": "The Norsemen's ship from the %s got broken, and its crew now sails for Valhalla.", + "com.minecolonies.coremod.raid.end.pirate_raid0": "The Pirate ship from the %s was sent to Davy Jones' locker!", + "com.minecolonies.coremod.raid.end.drowned_pirate_raid0": "The Drowned Pirates from the %s slinked back into the depths.", + "com.minecolonies.coremod.raid.end.pirate_ground_raid0": "The Pirates from the %s decided that without a ship, a pirate’s life is just a poor career choice.", + "com.minecolonies.coremod.raid.end.amazon_raid1": "The Amazon Warriors from the %s were driven back into the shadows of the forest.", + "com.minecolonies.coremod.raid.end.barbarian_raid1": "The Barbarians from the %s were no match for your defenses and met their end.", + "com.minecolonies.coremod.raid.end.egyptian_raid1": "The Ancient Mummies from the %s fell apart, their plans crumbling like dry parchment.", + "com.minecolonies.coremod.raid.end.norsemen_raid1": "The Norsemen from the %s battled fiercely but were sent to the halls of their gods.", + "com.minecolonies.coremod.raid.end.norsemen_ship_raid1": "The Norsemen’s ship from the %s met the sea’s wrath and will sail no more.", + "com.minecolonies.coremod.raid.end.pirate_raid1": "The Pirate ship from the %s remains adrift, its crew routed and scattered.", + "com.minecolonies.coremod.raid.end.drowned_pirate_raid1": "The Drowned Pirates from the %s returned to their watery graves, their attack in vain.", + "com.minecolonies.coremod.raid.end.pirate_ground_raid1": "The Pirates from the %s fled, swearing to never leave the safety of the sea again.", + "com.minecolonies.coremod.raid.end.amazon_raid2": "The Amazon Warriors from the %s fled, vanishing into the mists of the forest.", + "com.minecolonies.coremod.raid.end.barbarian_raid2": "The Barbarians from the %s retreated, their dreams of conquest shattered.", + "com.minecolonies.coremod.raid.end.egyptian_raid2": "The Ancient Mummies from the %s returned to their tombs, defeated and buried.", + "com.minecolonies.coremod.raid.end.norsemen_raid2": "The Norsemen from the %s faced their reckoning and joined their ancestors in Valhalla.", + "com.minecolonies.coremod.raid.end.norsemen_ship_raid2": "The Norsemen’s ship from the %s lies abandoned, its crew defeated and bound for Valhalla.", + "com.minecolonies.coremod.raid.end.pirate_raid2": "The Pirate ship from the %s is deserted, its plundering days ended in shame.", + "com.minecolonies.coremod.raid.end.drowned_pirate_raid2": "The Drowned Pirates from the %s sank back into the ocean’s depths, forgotten and forlorn.", + "com.minecolonies.coremod.raid.end.pirate_ground_raid2": "The Pirates from the %s decided the land wasn’t for them and retreated to the coast.", "com.minecolonies.coremod.pirates.spawners.destroyed": "%s successfully destroyed all the pirate spawners!", "com.minecolonies.coremod.pirates.killed": "§2Victory! %s rid the seas of the intruders!", + "com.minecolonies.coremod.raid.sailing.away": "The defeated ship in %s disappeared into the depths of the ocean.", "com.minecolonies.coremod.gui.workerhuts.deconstruct": "Deconstruct", "com.minecolonies.coremod.gui.workerhuts.pickup": "Pick Up", "com.minecolonies.coremod.gui.workerhuts.pickup.denied": "You cannot pickup this building.", @@ -1098,9 +1125,6 @@ "item.minecolonies.drownedpiratecaptainegg": "Drowned Pirate Captain Spawn Egg", "item.minecolonies.mercegg": "Mercenary Spawn Egg", - "com.minecolonies.coremod.pirates.sailing.away": "A pirate ship %s of %s just sailed away to search for another victim.", - "com.minecolonies.core.drowned_pirates.sailing.away": "The sunk shipwreck %s of %s mysteriously disappears back into the depths of the ocean.", - "com.minecolonies.coremod.cook.serve.player": "%s: Here Governor, take this food!", "item.minecolonies.santa_hat": "Santa Hat", @@ -2617,7 +2641,6 @@ "entity.minecolonies.drownedchiefpirate": "Drowned Pirate Chief", "death.attack.entity.minecolonies.drownedchiefpirate": "%s was put to a watery grave by a drowned Pirate Chief", "com.minecolonies.core.exit_interactions": "Exit Interactions", - "com.minecolonies.core.raidevent.spawnerbreaks": "One of the spawners of the raid misteriously broke, it seems you hit some sort of limit", "com.minecolonies.core.crop.cantplant": "You do not possess the necessary knowledge to plant this crop. You should ask a Farmer to plant this for you!", "com.minecolonies.core.item.crop.tooltip": "Ask a Farmer to plant this for you", "com.minecolonies.core.item.crop.tooltip.biome.coldbiomes": "Only suitable for Cold Biomes",