From 15618414a680c7d91650d2afe56e19a64dbecdc9 Mon Sep 17 00:00:00 2001 From: Melledy <121644117+Melledy@users.noreply.github.com> Date: Wed, 3 Dec 2025 23:15:25 -0800 Subject: [PATCH] Implement monolith shop discounts --- .../nebula/game/tower/StarTowerModifiers.java | 8 ++++ .../nebula/game/tower/StarTowerShopGoods.java | 16 +++++++ .../game/tower/cases/StarTowerHawkerCase.java | 46 ++++++++++++++++++- src/main/java/emu/nebula/util/Utils.java | 24 +++++++++- 4 files changed, 91 insertions(+), 3 deletions(-) diff --git a/src/main/java/emu/nebula/game/tower/StarTowerModifiers.java b/src/main/java/emu/nebula/game/tower/StarTowerModifiers.java index 947676b..67aaf4e 100644 --- a/src/main/java/emu/nebula/game/tower/StarTowerModifiers.java +++ b/src/main/java/emu/nebula/game/tower/StarTowerModifiers.java @@ -25,6 +25,10 @@ public class StarTowerModifiers { private int shopRerollCount; private int shopRerollPrice; + private boolean shopDiscountTier1; + private boolean shopDiscountTier2; + private boolean shopDiscountTier3; + public StarTowerModifiers(StarTowerGame game) { this.game = game; @@ -69,6 +73,10 @@ public class StarTowerModifiers { if (this.shopRerollCount > 0) { this.shopRerollPrice = 100; } + + this.shopDiscountTier1 = this.hasGrowthNode(20202) && game.getDifficulty() >= 3; + this.shopDiscountTier2 = this.hasGrowthNode(20502) && game.getDifficulty() >= 4; + this.shopDiscountTier3 = this.hasGrowthNode(20802) && game.getDifficulty() >= 5; } public boolean hasGrowthNode(int nodeId) { diff --git a/src/main/java/emu/nebula/game/tower/StarTowerShopGoods.java b/src/main/java/emu/nebula/game/tower/StarTowerShopGoods.java index 33078b4..042efd9 100644 --- a/src/main/java/emu/nebula/game/tower/StarTowerShopGoods.java +++ b/src/main/java/emu/nebula/game/tower/StarTowerShopGoods.java @@ -9,6 +9,7 @@ public class StarTowerShopGoods { private int type; private int goodsId; private int price; + private int discount; private boolean sold; public StarTowerShopGoods(int type, int goodsId, int price) { @@ -21,4 +22,19 @@ public class StarTowerShopGoods { this.sold = true; } + public boolean hasDiscount() { + return this.getDiscount() > 0; + } + + public void applyDiscount(double percentage) { + this.discount = (int) Math.ceil(this.price * (1.0 - percentage)); + } + + public int getPrice() { + return this.price - this.discount; + } + + public int getDisplayPrice() { + return this.price; + } } diff --git a/src/main/java/emu/nebula/game/tower/cases/StarTowerHawkerCase.java b/src/main/java/emu/nebula/game/tower/cases/StarTowerHawkerCase.java index 28ec1ba..20a8792 100644 --- a/src/main/java/emu/nebula/game/tower/cases/StarTowerHawkerCase.java +++ b/src/main/java/emu/nebula/game/tower/cases/StarTowerHawkerCase.java @@ -2,6 +2,7 @@ package emu.nebula.game.tower.cases; import java.util.HashMap; import java.util.Map; +import java.util.stream.Collectors; import emu.nebula.GameConstants; import emu.nebula.game.tower.StarTowerShopGoods; @@ -10,6 +11,8 @@ import emu.nebula.proto.PublicStarTower.HawkerGoods; import emu.nebula.proto.PublicStarTower.StarTowerRoomCase; import emu.nebula.proto.StarTowerInteract.StarTowerInteractReq; import emu.nebula.proto.StarTowerInteract.StarTowerInteractResp; +import emu.nebula.util.Utils; + import lombok.Getter; @Getter @@ -39,7 +42,42 @@ public class StarTowerHawkerCase extends StarTowerBaseCase { this.addGoods(new StarTowerShopGoods(1, 1, 200)); } - // TODO apply discounts based on star tower talents + // Apply discounts based on star tower talents + if (getModifiers().isShopDiscountTier1()) { + this.applyDiscount(1.0, 2, 0.8); + } + if (getModifiers().isShopDiscountTier2()) { + this.applyDiscount(0.3, 1, 0.5); + } + if (getModifiers().isShopDiscountTier3()) { + this.applyDiscount(1.0, 1, 0.5); + } + } + + private void applyDiscount(double chance, int times, double percentage) { + // Check chance + double random = Utils.generateRandomDouble(); + + if (random > chance) { + return; + } + + // Create goods list + var list = this.getGoods().values().stream() + .filter(g -> !g.hasDiscount()) + .collect(Collectors.toList()); + + // Apply discounts + for (int i = 0; i < times; i++) { + // Sanity check + if (list.isEmpty()) { + break; + } + + // Get goods and apply discount + var goods = Utils.randomElement(list, true); + goods.applyDiscount(percentage); + } } public void addGoods(StarTowerShopGoods goods) { @@ -145,9 +183,13 @@ public class StarTowerHawkerCase extends StarTowerBaseCase { .setSid(sid) .setType(goods.getType()) .setGoodsId(102) // ? - .setPrice(goods.getPrice()) + .setPrice(goods.getDisplayPrice()) .setTag(1); + if (goods.hasDiscount()) { + info.setDiscount(goods.getPrice()); + } + hawker.addList(info); } diff --git a/src/main/java/emu/nebula/util/Utils.java b/src/main/java/emu/nebula/util/Utils.java index d4884b7..f2fed2c 100644 --- a/src/main/java/emu/nebula/util/Utils.java +++ b/src/main/java/emu/nebula/util/Utils.java @@ -179,12 +179,34 @@ public class Utils { } public static T randomElement(List list) { - return list.get(ThreadLocalRandom.current().nextInt(0, list.size())); + return randomElement(list, false); + } + + public static T randomElement(List list, boolean remove) { + int index = ThreadLocalRandom.current().nextInt(0, list.size()); + var object = list.get(index); + + if (remove) { + list.remove(index); + } + + return object; } public static int randomElement(IntList list) { return list.getInt(ThreadLocalRandom.current().nextInt(0, list.size())); } + + public static int randomElement(IntList list, boolean remove) { + int index = ThreadLocalRandom.current().nextInt(0, list.size()); + int object = list.getInt(index); + + if (remove) { + list.removeInt(index); + } + + return object; + } /** * Checks if an integer array contains a value