From ef8846445cc44dc96cd35309eeeec2cb797093ab Mon Sep 17 00:00:00 2001 From: Melledy <121644117+Melledy@users.noreply.github.com> Date: Wed, 3 Dec 2025 19:36:47 -0800 Subject: [PATCH] Implement monolith enhancement machines --- src/main/java/emu/nebula/GameConstants.java | 2 +- .../emu/nebula/game/tower/StarTowerGame.java | 99 +++++++++++++++---- .../nebula/game/tower/StarTowerModifiers.java | 56 +++++++++++ .../game/tower/cases/StarTowerBaseCase.java | 5 + .../game/tower/cases/StarTowerBattleCase.java | 7 +- .../game/tower/cases/StarTowerHawkerCase.java | 11 ++- .../tower/cases/StarTowerPotentialCase.java | 2 +- .../cases/StarTowerStrengthenMachineCase.java | 94 ++++++++++++++++++ .../game/tower/room/StarTowerBaseRoom.java | 17 +++- .../game/tower/room/StarTowerBattleRoom.java | 4 +- .../game/tower/room/StarTowerEventRoom.java | 8 +- .../game/tower/room/StarTowerHawkerRoom.java | 14 ++- .../handlers/HandlerStarTowerApplyReq.java | 2 + 13 files changed, 280 insertions(+), 41 deletions(-) create mode 100644 src/main/java/emu/nebula/game/tower/StarTowerModifiers.java create mode 100644 src/main/java/emu/nebula/game/tower/cases/StarTowerStrengthenMachineCase.java diff --git a/src/main/java/emu/nebula/GameConstants.java b/src/main/java/emu/nebula/GameConstants.java index 3e630b0..363bb55 100644 --- a/src/main/java/emu/nebula/GameConstants.java +++ b/src/main/java/emu/nebula/GameConstants.java @@ -34,7 +34,7 @@ public class GameConstants { public static final int GEM_ITEM_ID = 2; public static final int PREM_GEM_ITEM_ID = 3; public static final int ENERGY_BUY_ITEM_ID = GEM_ITEM_ID; - public static final int STAR_TOWER_GOLD_ITEM_ID = 11; + public static final int STAR_TOWER_COIN_ITEM_ID = 11; public static final int EXP_ITEM_ID = 21; public static final int MAX_ENERGY = 240; diff --git a/src/main/java/emu/nebula/game/tower/StarTowerGame.java b/src/main/java/emu/nebula/game/tower/StarTowerGame.java index 19b9e0d..050ba65 100644 --- a/src/main/java/emu/nebula/game/tower/StarTowerGame.java +++ b/src/main/java/emu/nebula/game/tower/StarTowerGame.java @@ -19,6 +19,7 @@ import emu.nebula.game.tower.cases.StarTowerDoorCase; import emu.nebula.game.tower.cases.StarTowerHawkerCase; import emu.nebula.game.tower.cases.StarTowerNpcRecoveryHPCase; import emu.nebula.game.tower.cases.StarTowerPotentialCase; +import emu.nebula.game.tower.cases.StarTowerStrengthenMachineCase; import emu.nebula.game.tower.room.RoomType; import emu.nebula.game.tower.room.StarTowerBaseRoom; import emu.nebula.game.tower.room.StarTowerBattleRoom; @@ -78,6 +79,9 @@ public class StarTowerGame { // Sub note skill drop list private IntList subNoteDropList; + // Modifiers + private StarTowerModifiers modifiers; + // Cached build private transient StarTowerBuild build; private transient ItemParamMap newInfos; @@ -122,6 +126,9 @@ public class StarTowerGame { // Melody skill drop list this.subNoteDropList = new IntArrayList(); + // Init modifiers + this.modifiers = new StarTowerModifiers(this); + // Init formation for (int i = 0; i < 3; i++) { int id = formation.getCharIdAt(i); @@ -167,10 +174,10 @@ public class StarTowerGame { this.subNoteDropList.add(id); } - // Starting gold - int money = this.getStartingGold(); - if (money > 0) { - this.getRes().add(GameConstants.STAR_TOWER_GOLD_ITEM_ID, money); + // Add starting coin directly + int coin = this.getModifiers().getStartingCoin(); + if (coin > 0) { + this.getRes().add(GameConstants.STAR_TOWER_COIN_ITEM_ID, coin); } } @@ -186,6 +193,10 @@ public class StarTowerGame { return this.build; } + public int getDifficulty() { + return this.getData().getDifficulty(); + } + public int getRandomCharId() { return Utils.randomElement(this.getCharIds()); } @@ -250,20 +261,6 @@ public class StarTowerGame { this.room.onEnter(); } - public int getStartingGold() { - int gold = 0; - - if (this.getManager().hasGrowthNode(10103)) { - gold += 50; - } if (this.getManager().hasGrowthNode(10403)) { - gold += 100; - } if (this.getManager().hasGrowthNode(10702)) { - gold += 200; - } - - return gold; - } - public void addExp(int amount) { this.teamExp += amount; } @@ -322,12 +319,25 @@ public class StarTowerGame { return this.getItems().get(id); } + public int getResCount(int id) { + return this.getRes().get(id); + } + + public PlayerChangeInfo addItem(int id, int count) { + return this.addItem(id, count, null); + } + public PlayerChangeInfo addItem(int id, int count, PlayerChangeInfo change) { // Create changes if null if (change == null) { change = new PlayerChangeInfo(); } + // Sanity check + if (count == 0) { + return change; + } + // Get item data var itemData = GameData.getItemDataTable().get(id); if (itemData == null) { @@ -431,6 +441,10 @@ public class StarTowerGame { if (this.isOnFinalFloor()) { // Create hawker case (shop) cases.add(new StarTowerHawkerCase(this)); + // Create strengthen machine + if (this.getModifiers().isEnableEndStrengthen()) { + cases.add(new StarTowerStrengthenMachineCase()); + } } else if (this.getRoom() instanceof StarTowerBattleRoom) { // Create recovery npc cases.add(new StarTowerNpcRecoveryHPCase()); @@ -503,6 +517,55 @@ public class StarTowerGame { return new StarTowerPotentialCase(this.getTeamLevel(), selector); } + public StarTowerBaseCase createStrengthenSelector() { + // Random potentials list + var potentials = new IntArrayList(); + + // Get upgradable potentials + for (var item : this.getPotentials()) { + // Get potential data + var potential = GameData.getPotentialDataTable().get(item.getIntKey()); + if (potential == null) continue; + + // Check max level + int level = item.getIntValue(); + if (level >= potential.getMaxLevel()) { + continue; + } + + // Add + potentials.add(potential.getId()); + } + + // Get up to 3 random potentials + IntList selector = new IntArrayList(); + + for (int i = 0; i < 3; i++) { + // Sanity check + if (potentials.isEmpty()) { + break; + } + + // Get random potential id + int index = ThreadLocalRandom.current().nextInt(0, potentials.size()); + int potentialId = potentials.getInt(index); + + // Add to selector + selector.add(potentialId); + + // Remove potential id from the selector + potentials.removeInt(index); + } + + // Sanity check + if (selector.isEmpty()) { + return null; + } + + // Creator potential selector case + return new StarTowerPotentialCase(this.getTeamLevel(), selector); + } + public void setPendingSubNotes(int amount) { this.pendingSubNotes = amount; } diff --git a/src/main/java/emu/nebula/game/tower/StarTowerModifiers.java b/src/main/java/emu/nebula/game/tower/StarTowerModifiers.java new file mode 100644 index 0000000..5c32524 --- /dev/null +++ b/src/main/java/emu/nebula/game/tower/StarTowerModifiers.java @@ -0,0 +1,56 @@ +package emu.nebula.game.tower; + +import lombok.Getter; + +/** + * Data class to hold various modifiers for star tower. + */ +@Getter +public class StarTowerModifiers { + private StarTowerGame game; + + // Strengthen machines + private boolean enableEndStrengthen; + private boolean enableShopStrengthen; + + private boolean freeStrengthen; + private int strengthenDiscount; + + public StarTowerModifiers(StarTowerGame game) { + this.game = game; + + // Strengthen machines + this.enableEndStrengthen = this.hasGrowthNode(10601) && game.getDifficulty() >= 2; + this.enableShopStrengthen = this.hasGrowthNode(20301) && game.getDifficulty() >= 4; + + this.freeStrengthen = this.hasGrowthNode(10801); + + if (this.hasGrowthNode(30402)) { + this.strengthenDiscount += 60; + } else if (this.hasGrowthNode(30102)) { + this.strengthenDiscount += 30; + } + } + + public boolean hasGrowthNode(int nodeId) { + return this.getGame().getManager().hasGrowthNode(nodeId); + } + + public int getStartingCoin() { + int gold = 0; + + if (this.hasGrowthNode(10103)) { + gold += 50; + } if (this.hasGrowthNode(10403)) { + gold += 100; + } if (this.hasGrowthNode(10702)) { + gold += 200; + } + + return gold; + } + + public void setFreeStrengthen(boolean b) { + this.freeStrengthen = b; + } +} diff --git a/src/main/java/emu/nebula/game/tower/cases/StarTowerBaseCase.java b/src/main/java/emu/nebula/game/tower/cases/StarTowerBaseCase.java index 07d6cbc..f6acbce 100644 --- a/src/main/java/emu/nebula/game/tower/cases/StarTowerBaseCase.java +++ b/src/main/java/emu/nebula/game/tower/cases/StarTowerBaseCase.java @@ -1,6 +1,7 @@ package emu.nebula.game.tower.cases; import emu.nebula.game.tower.StarTowerGame; +import emu.nebula.game.tower.StarTowerModifiers; import emu.nebula.game.tower.room.StarTowerBaseRoom; import emu.nebula.proto.PublicStarTower.StarTowerRoomCase; import emu.nebula.proto.StarTowerInteract.StarTowerInteractReq; @@ -22,6 +23,10 @@ public abstract class StarTowerBaseCase { public StarTowerBaseRoom getRoom() { return this.getGame().getRoom(); } + + public StarTowerModifiers getModifiers() { + return this.getGame().getModifiers(); + } public void register(StarTowerBaseRoom room) { this.game = room.getGame(); diff --git a/src/main/java/emu/nebula/game/tower/cases/StarTowerBattleCase.java b/src/main/java/emu/nebula/game/tower/cases/StarTowerBattleCase.java index e5f74d0..eae950a 100644 --- a/src/main/java/emu/nebula/game/tower/cases/StarTowerBattleCase.java +++ b/src/main/java/emu/nebula/game/tower/cases/StarTowerBattleCase.java @@ -6,6 +6,7 @@ import emu.nebula.game.player.PlayerChangeInfo; import emu.nebula.proto.PublicStarTower.StarTowerRoomCase; import emu.nebula.proto.StarTowerInteract.StarTowerInteractReq; import emu.nebula.proto.StarTowerInteract.StarTowerInteractResp; + import lombok.Getter; @Getter @@ -78,10 +79,10 @@ public class StarTowerBattleCase extends StarTowerBaseCase { .setLv(this.getGame().getTeamLevel()) .setBattleTime(this.getGame().getBattleTime()); - // Add money - int money = this.getRoom().getStage().getInteriorCurrencyQuantity(); + // Add coin + int coin = this.getRoom().getStage().getInteriorCurrencyQuantity(); - this.getGame().addItem(GameConstants.STAR_TOWER_GOLD_ITEM_ID, money, change); + this.getGame().addItem(GameConstants.STAR_TOWER_COIN_ITEM_ID, coin, change); // Handle pending potential selectors var nextCases = this.getGame().handlePendingPotentialSelectors(); 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 5f8b399..6eff4d9 100644 --- a/src/main/java/emu/nebula/game/tower/cases/StarTowerHawkerCase.java +++ b/src/main/java/emu/nebula/game/tower/cases/StarTowerHawkerCase.java @@ -42,15 +42,18 @@ public class StarTowerHawkerCase extends StarTowerBaseCase { @Override public StarTowerInteractResp interact(StarTowerInteractReq req, StarTowerInteractResp rsp) { - // Set nil resp + // Set nil resp rsp.getMutableNilResp(); // Get goods var goods = this.getGoods().get(req.getHawkerReq().getSid()); + if (goods == null) { + return rsp; + } // Make sure we have enough currency - int gold = this.getGame().getRes().get(GameConstants.STAR_TOWER_GOLD_ITEM_ID); - if (gold < goods.getPrice() || goods.isSold()) { + int coin = this.getGame().getRes().get(GameConstants.STAR_TOWER_COIN_ITEM_ID); + if (coin < goods.getPrice() || goods.isSold()) { return rsp; } @@ -61,7 +64,7 @@ public class StarTowerHawkerCase extends StarTowerBaseCase { this.getGame().addCase(rsp.getMutableCases(), this.getGame().createPotentialSelector()); // Remove items - var change = this.getGame().addItem(GameConstants.STAR_TOWER_GOLD_ITEM_ID, -goods.getPrice(), null); + var change = this.getGame().addItem(GameConstants.STAR_TOWER_COIN_ITEM_ID, -goods.getPrice()); // Set change info rsp.setChange(change.toProto()); diff --git a/src/main/java/emu/nebula/game/tower/cases/StarTowerPotentialCase.java b/src/main/java/emu/nebula/game/tower/cases/StarTowerPotentialCase.java index a883182..6f744b0 100644 --- a/src/main/java/emu/nebula/game/tower/cases/StarTowerPotentialCase.java +++ b/src/main/java/emu/nebula/game/tower/cases/StarTowerPotentialCase.java @@ -44,7 +44,7 @@ public class StarTowerPotentialCase extends StarTowerBaseCase { } // Add item - var change = this.getGame().addItem(id, 1, null); + var change = this.getGame().addItem(id, 1); // Set change rsp.setChange(change.toProto()); diff --git a/src/main/java/emu/nebula/game/tower/cases/StarTowerStrengthenMachineCase.java b/src/main/java/emu/nebula/game/tower/cases/StarTowerStrengthenMachineCase.java new file mode 100644 index 0000000..571cf37 --- /dev/null +++ b/src/main/java/emu/nebula/game/tower/cases/StarTowerStrengthenMachineCase.java @@ -0,0 +1,94 @@ +package emu.nebula.game.tower.cases; + +import emu.nebula.GameConstants; +import emu.nebula.game.tower.room.StarTowerBaseRoom; +import emu.nebula.proto.PublicStarTower.StarTowerRoomCase; +import emu.nebula.proto.StarTowerInteract.StarTowerInteractReq; +import emu.nebula.proto.StarTowerInteract.StarTowerInteractResp; +import lombok.Getter; + +@Getter +public class StarTowerStrengthenMachineCase extends StarTowerBaseCase { + private boolean free; + private int discount; + private int times; + + @Override + public void register(StarTowerBaseRoom room) { + super.register(room); + + // Also set strengthen price + this.free = this.getModifiers().isFreeStrengthen(); + this.discount = this.getModifiers().getStrengthenDiscount(); + } + + public int getPrice() { + if (this.free) { + return 0; + } + + int price = 120 + (this.times * 60) - this.discount; + + return Math.max(price, 0); + } + + public void increasePrice() { + if (this.free) { + this.free = false; + this.getModifiers().setFreeStrengthen(false); + } else { + this.times++; + } + } + + @Override + public CaseType getType() { + return CaseType.StrengthenMachine; + } + + @Override + public StarTowerInteractResp interact(StarTowerInteractReq req, StarTowerInteractResp rsp) { + // Init case + StarTowerBaseCase towerCase = null; + + // Check coin + int coin = getGame().getResCount(GameConstants.STAR_TOWER_COIN_ITEM_ID); + int price = this.getPrice(); + + if (coin >= price) { + towerCase = getGame().createStrengthenSelector(); + } + + if (towerCase != null) { + // Add enhancement selector case + this.getRoom().addCase(rsp.getMutableCases(), towerCase); + + // Remove coins + var change = this.getGame().addItem(GameConstants.STAR_TOWER_COIN_ITEM_ID, -price); + + // Set change info + rsp.setChange(change.toProto()); + + // Increment price + this.increasePrice(); + } + + // Set success result + rsp.getMutableStrengthenMachineResp() + .setBuySucceed(towerCase != null); + + // Complete + return rsp; + } + + // Proto + + @Override + public void encodeProto(StarTowerRoomCase proto) { + // Set field in the proto + proto.getMutableStrengthenMachineCase() + .setFirstFree(this.isFree()) + .setDiscount(this.getDiscount()) + .setTimes(this.getTimes()); + } +} diff --git a/src/main/java/emu/nebula/game/tower/room/StarTowerBaseRoom.java b/src/main/java/emu/nebula/game/tower/room/StarTowerBaseRoom.java index b7821b3..e532096 100644 --- a/src/main/java/emu/nebula/game/tower/room/StarTowerBaseRoom.java +++ b/src/main/java/emu/nebula/game/tower/room/StarTowerBaseRoom.java @@ -5,6 +5,7 @@ import java.util.List; import emu.nebula.data.resources.StarTowerStageDef; import emu.nebula.game.tower.StarTowerGame; +import emu.nebula.game.tower.StarTowerModifiers; import emu.nebula.game.tower.cases.CaseType; import emu.nebula.game.tower.cases.StarTowerBaseCase; import emu.nebula.game.tower.cases.StarTowerSyncHPCase; @@ -48,6 +49,14 @@ public class StarTowerBaseRoom { return this.hasDoor; } + public StarTowerModifiers getModifiers() { + return this.getGame().getModifiers(); + } + + public StarTowerBaseCase createExit() { + return this.getGame().createExit(); + } + // Map info public void setMapInfo(StarTowerApplyReq req) { @@ -105,11 +114,11 @@ public class StarTowerBaseRoom { // Events public void onEnter() { - // Create door case - this.getGame().createExit(); - // Create sync hp case - this.getGame().addCase(new StarTowerSyncHPCase()); + this.addCase(new StarTowerSyncHPCase()); + + // Create door case + this.createExit(); } // Proto diff --git a/src/main/java/emu/nebula/game/tower/room/StarTowerBattleRoom.java b/src/main/java/emu/nebula/game/tower/room/StarTowerBattleRoom.java index dd6ab55..96c0a8a 100644 --- a/src/main/java/emu/nebula/game/tower/room/StarTowerBattleRoom.java +++ b/src/main/java/emu/nebula/game/tower/room/StarTowerBattleRoom.java @@ -18,9 +18,9 @@ public class StarTowerBattleRoom extends StarTowerBaseRoom { public void onEnter() { // Create battle case this.getGame().setPendingSubNotes(Utils.randomRange(1, 3)); - this.getGame().addCase(new StarTowerBattleCase(this.getGame().getPendingSubNotes())); + this.addCase(new StarTowerBattleCase(this.getGame().getPendingSubNotes())); // Create sync hp case - this.getGame().addCase(new StarTowerSyncHPCase()); + this.addCase(new StarTowerSyncHPCase()); } } diff --git a/src/main/java/emu/nebula/game/tower/room/StarTowerEventRoom.java b/src/main/java/emu/nebula/game/tower/room/StarTowerEventRoom.java index 33d47f0..b92cc56 100644 --- a/src/main/java/emu/nebula/game/tower/room/StarTowerEventRoom.java +++ b/src/main/java/emu/nebula/game/tower/room/StarTowerEventRoom.java @@ -15,10 +15,10 @@ public class StarTowerEventRoom extends StarTowerBaseRoom { @Override public void onEnter() { - // Create door case - this.getGame().createExit(); - // Create sync hp case - this.getGame().addCase(new StarTowerSyncHPCase()); + this.addCase(new StarTowerSyncHPCase()); + + // Create door case + this.createExit(); } } diff --git a/src/main/java/emu/nebula/game/tower/room/StarTowerHawkerRoom.java b/src/main/java/emu/nebula/game/tower/room/StarTowerHawkerRoom.java index 2e4e144..084127b 100644 --- a/src/main/java/emu/nebula/game/tower/room/StarTowerHawkerRoom.java +++ b/src/main/java/emu/nebula/game/tower/room/StarTowerHawkerRoom.java @@ -3,6 +3,7 @@ package emu.nebula.game.tower.room; import emu.nebula.data.resources.StarTowerStageDef; import emu.nebula.game.tower.StarTowerGame; import emu.nebula.game.tower.cases.StarTowerHawkerCase; +import emu.nebula.game.tower.cases.StarTowerStrengthenMachineCase; import emu.nebula.game.tower.cases.StarTowerSyncHPCase; import lombok.Getter; @@ -16,12 +17,17 @@ public class StarTowerHawkerRoom extends StarTowerBaseRoom { @Override public void onEnter() { // Create hawker case (shop) - this.getGame().addCase(new StarTowerHawkerCase(this.getGame())); + this.addCase(new StarTowerHawkerCase(this.getGame())); - // Create door case - this.getGame().createExit(); + // Create strengthen machine + if (this.getModifiers().isEnableShopStrengthen()) { + this.addCase(new StarTowerStrengthenMachineCase()); + } // Create sync hp case - this.getGame().addCase(new StarTowerSyncHPCase()); + this.addCase(new StarTowerSyncHPCase()); + + // Create door case + this.createExit(); } } diff --git a/src/main/java/emu/nebula/server/handlers/HandlerStarTowerApplyReq.java b/src/main/java/emu/nebula/server/handlers/HandlerStarTowerApplyReq.java index 9d60eab..bd6e97f 100644 --- a/src/main/java/emu/nebula/server/handlers/HandlerStarTowerApplyReq.java +++ b/src/main/java/emu/nebula/server/handlers/HandlerStarTowerApplyReq.java @@ -5,6 +5,7 @@ import emu.nebula.net.NetMsgId; import emu.nebula.proto.StarTowerApply.StarTowerApplyReq; import emu.nebula.proto.StarTowerApply.StarTowerApplyResp; import emu.nebula.net.HandlerId; +import emu.nebula.GameConstants; import emu.nebula.game.tower.StarTowerGame; import emu.nebula.net.GameSession; @@ -29,6 +30,7 @@ public class HandlerStarTowerApplyReq extends NetHandler { // Create response var rsp = StarTowerApplyResp.newInstance() .setLastId(req.getId()) + .setCoinQty(game.getResCount(GameConstants.STAR_TOWER_COIN_ITEM_ID)) .setInfo(game.toProto()) .setChange(change.toProto());