From 6972629d773ce2f26c70874ac8c82f54022342ae Mon Sep 17 00:00:00 2001 From: Bishop Date: Sun, 28 Jun 2026 09:08:41 -0500 Subject: [PATCH] Properly handle crestless players building crest decorations --- .../skill/construction/BuildingUtils.java | 20 ++++++++++++--- .../global/skill/construction/CrestType.kt | 5 +++- .../global/skill/construction/Decoration.java | 25 ++++++++++++++++--- .../skill/construction/HouseManager.java | 5 +++- .../global/skill/construction/Room.java | 10 ++++++-- 5 files changed, 54 insertions(+), 11 deletions(-) diff --git a/Server/src/main/content/global/skill/construction/BuildingUtils.java b/Server/src/main/content/global/skill/construction/BuildingUtils.java index 59e116afd..03cdd009d 100644 --- a/Server/src/main/content/global/skill/construction/BuildingUtils.java +++ b/Server/src/main/content/global/skill/construction/BuildingUtils.java @@ -276,7 +276,7 @@ public final class BuildingUtils { } break; case CREST: - SceneryBuilder.replace(object, object.transform(deco.getObjectId(style) + player.getHouseManager().getCrest().ordinal())); + SceneryBuilder.replace(object, object.transform(deco.getCrestAdjustedId(style, player.getHouseManager().getCrest()))); hotspot.setDecorationIndex(decIndex); break; case INDIVIDUAL: @@ -341,9 +341,13 @@ public final class BuildingUtils { HousingStyle style = player.getHouseManager().getStyle(); for (int i = 0; i < room.getHotspots().length; i++) { Hotspot hotspot = room.getHotspots()[i]; - int objectId = hotspot.getDecorationIndex() < 0 ? -1 : hotspot.getHotspot().getDecorations()[hotspot.getDecorationIndex()].getObjectId(style); - if (hotspot.getHotspot().getType() == BuildHotspotType.CREST) { - objectId += player.getHouseManager().getCrest().ordinal(); + int objectId; + if (hotspot.getDecorationIndex() < 0) { + objectId = -1; + } else if (hotspot.getHotspot().getType() == BuildHotspotType.CREST) { + objectId = hotspot.getHotspot().getDecorations()[hotspot.getDecorationIndex()].getCrestAdjustedId(style, player.getHouseManager().getCrest()); + } else { + objectId = hotspot.getHotspot().getDecorations()[hotspot.getDecorationIndex()].getObjectId(style); } if (objectId == object.getId() && hotspot.getCurrentX() == l.getChunkOffsetX() && hotspot.getCurrentY() == l.getChunkOffsetY()) { Decoration decoration = hotspot.getHotspot().getDecorations()[hotspot.getDecorationIndex()]; @@ -472,6 +476,14 @@ public final class BuildingUtils { return false; } return true; + case ROUND_SHIELD: + case SQUARE_SHIELD: + case KITE_SHIELD: + if (player.getHouseManager().getCrest() == CrestType.NULL) { + sendDialogue(player, "You need a crest to build heraldic shields."); // Placeholder + return false; + } + return true; default: return true; } diff --git a/Server/src/main/content/global/skill/construction/CrestType.kt b/Server/src/main/content/global/skill/construction/CrestType.kt index c9bfc22fd..6998d4193 100644 --- a/Server/src/main/content/global/skill/construction/CrestType.kt +++ b/Server/src/main/content/global/skill/construction/CrestType.kt @@ -8,6 +8,7 @@ import org.rs09.consts.Items /** * Enumerates the various crests the player can purchase for the Construction skill, as well as their requirements. + * The NULL CrestType represents players who have yet to receive a crest from Sir Renitee. * ORDINAL BOUND * @author Bishop */ @@ -39,7 +40,9 @@ enum class CrestType(val crestName: String, val cost: Int = 5000, private val re requirement = { it.skullManager.isSkulled }), VARROCK("the symbol of Varrock"), ZAMORAK("the symbol of Zamorak", - requirement = { hasLevelStat(it, Skills.PRAYER, 70) }); + requirement = { hasLevelStat(it, Skills.PRAYER, 70) }), + NULL("no crest", + cost = 0, requirement = { false }); fun eligible(player: Player): Boolean = requirement(player) } \ No newline at end of file diff --git a/Server/src/main/content/global/skill/construction/Decoration.java b/Server/src/main/content/global/skill/construction/Decoration.java index b86a78cd5..8719d3bbb 100644 --- a/Server/src/main/content/global/skill/construction/Decoration.java +++ b/Server/src/main/content/global/skill/construction/Decoration.java @@ -255,7 +255,7 @@ public enum Decoration { * Wall-mounted decorations */ OAK_DECORATION (13606, 8102, 16, 120, new Item[] { new Item(Items.OAK_PLANK_8778, 2) }), - TEAK_DECORATION (13606, 8103, 36, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }), + TEAK_DECORATION (13608, 8103, 36, 180, new Item[] { new Item(Items.TEAK_PLANK_8780, 2) }), GILDED_DECORATION(13607, 8104, 56, 1020, new Item[] { new Item(Items.MAHOGANY_PLANK_8782, 3), new Item(Items.GOLD_LEAF_8784, 2) }), /** @@ -899,9 +899,11 @@ public enum Decoration { if (h.getCurrentX() == l.getChunkOffsetX() && h.getCurrentY() == l.getChunkOffsetY()) { if (h.getDecorationIndex() != -1) { Decoration deco = h.getHotspot().getDecorations()[h.getDecorationIndex()]; - int id = deco.getObjectId(player.getHouseManager().getStyle()); + int id; if (h.getHotspot().getType() == BuildHotspotType.CREST) { - id += player.getHouseManager().getCrest().ordinal(); + id = deco.getCrestAdjustedId(player.getHouseManager().getStyle(), player.getHouseManager().getCrest()); + } else { + id = deco.getObjectId(player.getHouseManager().getStyle()); } if (id == object.getId()) { return deco; @@ -968,6 +970,23 @@ public enum Decoration { return objectId; } + /** + * Returns the object ID adjusted for the player's crest. + * For CrestType.NULL, maps _DECO decorations to their blank _DECORATION counterparts. + * Returns -1 for shield decorations with NULL crest (no blank variant exists). + */ + public int getCrestAdjustedId(HousingStyle style, CrestType crest) { + if (crest == CrestType.NULL) { + switch (this) { + case OAK_DECO: return OAK_DECORATION.getObjectId(style); + case TEAK_DECO: return TEAK_DECORATION.getObjectId(style); + case GILDED_DECO: return GILDED_DECORATION.getObjectId(style); + default: return -1; + } + } + return getObjectId(style) + crest.ordinal(); + } + /** * Gets the level. * @return The level. diff --git a/Server/src/main/content/global/skill/construction/HouseManager.java b/Server/src/main/content/global/skill/construction/HouseManager.java index 5a46876e2..fa9e399fe 100644 --- a/Server/src/main/content/global/skill/construction/HouseManager.java +++ b/Server/src/main/content/global/skill/construction/HouseManager.java @@ -86,7 +86,7 @@ public final class HouseManager { /** * The player's crest. */ - private CrestType crest = CrestType.ASGARNIA; + private CrestType crest = CrestType.NULL; /** * Constructs a new {@code HouseManager} {@code Object}. @@ -104,6 +104,8 @@ public final class HouseManager { Object crestRaw = data.get("crest"); if (crestRaw != null) { crest = CrestType.values()[Integer.parseInt(crestRaw.toString())]; + } else { + crest = CrestType.ASGARNIA; } Object servRaw = data.get("servant"); if(servRaw != null){ @@ -352,6 +354,7 @@ public final class HouseManager { room.configure(style); room.getHotspots()[0].setDecorationIndex(0); redecorate(HousingStyle.BASIC_WOOD); + crest = CrestType.NULL; this.location = location; } diff --git a/Server/src/main/content/global/skill/construction/Room.java b/Server/src/main/content/global/skill/construction/Room.java index ac7b56cec..ee6c68300 100644 --- a/Server/src/main/content/global/skill/construction/Room.java +++ b/Server/src/main/content/global/skill/construction/Room.java @@ -140,9 +140,15 @@ public final class Room { Scenery object = objects[x][y]; if (object != null && object.getId() == spot.getHotspot().getObjectId(house.getStyle())) { if (spot.getDecorationIndex() > -1 && spot.getDecorationIndex() < spot.getHotspot().getDecorations().length) { - int id = spot.getHotspot().getDecorations()[spot.getDecorationIndex()].getObjectId(house.getStyle()); + int id; if (spot.getHotspot().getType() == BuildHotspotType.CREST) { - id += house.getCrest().ordinal(); + id = spot.getHotspot().getDecorations()[spot.getDecorationIndex()].getCrestAdjustedId(house.getStyle(), house.getCrest()); + if (id == -1) { + spot.setDecorationIndex(-1); + continue; + } + } else { + id = spot.getHotspot().getDecorations()[spot.getDecorationIndex()].getObjectId(house.getStyle()); } SceneryBuilder.replace(object, object.transform(id, object.getRotation(), chunk.getCurrentBase().transform(x, y, 0))); }