Properly handle crestless players building crest decorations

This commit is contained in:
Bishop 2026-06-28 09:08:41 -05:00
parent 9bf2321974
commit 6972629d77
5 changed files with 54 additions and 11 deletions

View file

@ -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;
}

View file

@ -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)
}

View file

@ -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.

View file

@ -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;
}

View file

@ -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)));
}