From b302871630d7f4db8a10c4e2caafe28660e1ffed Mon Sep 17 00:00:00 2001 From: Melledy <121644117+Melledy@users.noreply.github.com> Date: Mon, 19 Oct 2026 20:59:01 -0700 Subject: [PATCH] Implement monolith research quests --- README.md | 2 +- src/main/java/emu/nebula/data/GameData.java | 2 +- .../data/custom/StarTowerQuestParamDef.java | 36 ++ .../data/resources/StarTowerBuildRankDef.java | 1 + .../data/resources/StarTowerQuestDef.java | 78 +++ .../java/emu/nebula/game/quest/GameQuest.java | 56 ++ .../emu/nebula/game/quest/QuestManager.java | 202 ++++++- .../game/quest/StarTowerQuestHelper.java | 48 ++ .../emu/nebula/game/tower/StarTowerGame.java | 21 +- .../nebula/game/tower/StarTowerManager.java | 36 ++ .../game/tower/cases/StarTowerBattleCase.java | 4 + .../game/tower/cases/StarTowerHawkerCase.java | 12 +- .../tower/cases/StarTowerPotentialCase.java | 12 +- .../cases/StarTowerStrengthenMachineCase.java | 6 +- .../HandlerQuestTowerRewardReceiveReq.java | 28 + .../resources/defs/StarTowerQuestParam.json | 515 ++++++++++++++++++ 16 files changed, 1024 insertions(+), 35 deletions(-) create mode 100644 src/main/java/emu/nebula/data/custom/StarTowerQuestParamDef.java create mode 100644 src/main/java/emu/nebula/data/resources/StarTowerQuestDef.java create mode 100644 src/main/java/emu/nebula/game/quest/StarTowerQuestHelper.java create mode 100644 src/main/java/emu/nebula/server/handlers/HandlerQuestTowerRewardReceiveReq.java create mode 100644 src/main/resources/defs/StarTowerQuestParam.json diff --git a/README.md b/README.md index 5df7b80..9f40986 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Latest nightly compiled server jar: [Nightly](https://nightly.link/Melledy/Nebul - Commissions - Heartlink - Achievements -- Monoliths (research quests not implemented) +- Monoliths - Bounty Trials - Menance Arena - Proving Grounds diff --git a/src/main/java/emu/nebula/data/GameData.java b/src/main/java/emu/nebula/data/GameData.java index 982156e..cdcd1a6 100644 --- a/src/main/java/emu/nebula/data/GameData.java +++ b/src/main/java/emu/nebula/data/GameData.java @@ -4,7 +4,6 @@ import emu.nebula.data.custom.CharGemAttrGroupDef; import emu.nebula.data.resources.*; import lombok.Getter; -@SuppressWarnings("unused") public class GameData { // ===== Characters ===== @Getter private static DataTable CharacterDataTable = new DataTable<>(); @@ -117,6 +116,7 @@ public class GameData { @Getter private static DataTable StarTowerFloorExpDataTable = new DataTable<>(); @Getter private static DataTable StarTowerTeamExpDataTable = new DataTable<>(); @Getter private static DataTable StarTowerEventDataTable = new DataTable<>(); + @Getter private static DataTable StarTowerQuestDataTable = new DataTable<>(); @Getter private static DataTable StarTowerBuildRankDataTable = new DataTable<>(); @Getter private static DataTable StarTowerBookPotentialRewardDataTable = new DataTable<>(); @Getter private static DataTable SubNoteSkillPromoteGroupDataTable = new DataTable<>(); diff --git a/src/main/java/emu/nebula/data/custom/StarTowerQuestParamDef.java b/src/main/java/emu/nebula/data/custom/StarTowerQuestParamDef.java new file mode 100644 index 0000000..49db603 --- /dev/null +++ b/src/main/java/emu/nebula/data/custom/StarTowerQuestParamDef.java @@ -0,0 +1,36 @@ +package emu.nebula.data.custom; + +import emu.nebula.data.BaseDef; +import emu.nebula.data.GameData; +import emu.nebula.data.ResourceType; +import emu.nebula.data.ResourceType.LoadPriority; +import lombok.Getter; + +@Getter +@ResourceType(name = "StarTowerQuestParam.json", useInternal = true, loadPriority = LoadPriority.LOW) +public class StarTowerQuestParamDef extends BaseDef { + private int Id; + + private int CompleteCond; + private int Aim; + + private int Param1; + private int ParamCond1; + private int Param2; + private int ParamCond2; + + @Override + public int getId() { + return Id; + } + + @Override + public void onLoad() { + var quest = GameData.getStarTowerQuestDataTable().get(this.Id); + if (quest == null) { + return; + } + + quest.setParams(this); + } +} diff --git a/src/main/java/emu/nebula/data/resources/StarTowerBuildRankDef.java b/src/main/java/emu/nebula/data/resources/StarTowerBuildRankDef.java index 56748fd..c146658 100644 --- a/src/main/java/emu/nebula/data/resources/StarTowerBuildRankDef.java +++ b/src/main/java/emu/nebula/data/resources/StarTowerBuildRankDef.java @@ -9,6 +9,7 @@ import lombok.Getter; public class StarTowerBuildRankDef extends BaseDef { private int Id; private int MinGrade; + private int Level; private int Rarity; @Override diff --git a/src/main/java/emu/nebula/data/resources/StarTowerQuestDef.java b/src/main/java/emu/nebula/data/resources/StarTowerQuestDef.java new file mode 100644 index 0000000..d362fb2 --- /dev/null +++ b/src/main/java/emu/nebula/data/resources/StarTowerQuestDef.java @@ -0,0 +1,78 @@ +package emu.nebula.data.resources; + +import emu.nebula.data.BaseDef; +import emu.nebula.data.ResourceType; +import emu.nebula.data.custom.StarTowerQuestParamDef; +import emu.nebula.game.quest.QuestData; +import emu.nebula.game.quest.QuestType; +import lombok.Getter; + +@Getter +@ResourceType(name = "StarTowerQuest.json") +public class StarTowerQuestDef extends BaseDef implements QuestData { + private int Id; + private String Title; + private int TowerQuestType; // 1 = Core, 2 = Normal + private int[] PreTowerQuestIds; + + // Rewards + private int Reward1; + private int RewardQty1; + private int Reward2; + private int RewardQty2; + + // Custom params (loaded from defs/StarTowerQuestParam.json) + private transient int completeCond; + private transient int aim; + private transient int param1; + private transient int paramCond1; + private transient int param2; + private transient int paramCond2; + private transient int[] condParams; + + @Override + public int getId() { + return Id; + } + + @Override + public int getQuestType() { + return QuestType.Tower; + } + + @Override + public int getCompleteCond() { + return this.completeCond; + } + + @Override + public int[] getCompleteCondParams() { + if (this.condParams == null) { + this.condParams = new int[] { 1, 0, 0 }; + } + + return this.condParams; + } + + /** + * Applies the generated condition params from the internal defs file. + */ + public void setParams(StarTowerQuestParamDef params) { + this.completeCond = params.getCompleteCond(); + this.aim = params.getAim(); + this.param1 = params.getParam1(); + this.paramCond1 = params.getParamCond1(); + this.param2 = params.getParam2(); + this.paramCond2 = params.getParamCond2(); + + this.condParams = new int[] { this.aim, this.param1, this.param2 }; + } + + @Override + public void onLoad() { + // Quests without prerequisites have no array in the data file + if (this.PreTowerQuestIds == null) { + this.PreTowerQuestIds = new int[0]; + } + } +} diff --git a/src/main/java/emu/nebula/game/quest/GameQuest.java b/src/main/java/emu/nebula/game/quest/GameQuest.java index 94c0555..cfbf838 100644 --- a/src/main/java/emu/nebula/game/quest/GameQuest.java +++ b/src/main/java/emu/nebula/game/quest/GameQuest.java @@ -65,6 +65,62 @@ public class GameQuest { return 0; } + /** + * Refreshes condition data from a resource definition while preserving progress. + */ + public boolean refreshData(QuestData data) { + int oldCond = this.cond; + int oldMax = this.maxProgress; + int oldParam = this.param; + + this.cond = data.getCompleteCond(); + + int[] params = data.getCompleteCondParams(); + this.maxProgress = params.length > 0 ? params[0] : 0; + this.param = params.length > 1 ? params[1] : 0; + + return oldCond != this.cond || oldMax != this.maxProgress || oldParam != this.param; + } + + /** + * Adds progress without applying condition/param checks. + * Used by quest systems that perform their own matching. + */ + public boolean addProgress(int progress) { + if (this.isComplete() || progress <= 0) { + return false; + } + + int newProgress = Math.min(this.curProgress + progress, this.maxProgress); + + if (newProgress == this.curProgress) { + return false; + } + + this.curProgress = newProgress; + + return true; + } + + /** + * Directly sets quest progress + */ + public boolean setProgress(int progress) { + if (this.isComplete() || progress < 0) { + return false; + } + + int newProgress = Math.min(progress, this.maxProgress); + + if (newProgress == this.curProgress) { + return false; + } + + this.curProgress = newProgress; + + return true; + } + public boolean trigger(int condition, int progress, int param1, int param2) { // Sanity check if (this.isComplete()) { diff --git a/src/main/java/emu/nebula/game/quest/QuestManager.java b/src/main/java/emu/nebula/game/quest/QuestManager.java index c5963bb..eb78289 100644 --- a/src/main/java/emu/nebula/game/quest/QuestManager.java +++ b/src/main/java/emu/nebula/game/quest/QuestManager.java @@ -60,6 +60,8 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject { this.list = new HashMap<>(); this.levelRewards = new Bitset(); + this.initStarTowerQuests(); + this.resetDailyQuests(true); this.save(); @@ -71,7 +73,34 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject { } public synchronized GameQuest addQuest(GameQuest quest) { + // Add to quest list this.list.put(quest.getKey(), quest); + + // Star Tower growth-node quests can complete retroactively if the player + // already unlocked the required node(s) before the quest was added + if (quest.getType() == QuestType.Tower) { + var data = GameData.getStarTowerQuestDataTable().get(quest.getId()); + int cond = data != null ? data.getCompleteCond() : 0; + + if (cond == QuestCondition.TowerGrowthSpecificNote.getValue() || cond == QuestCondition.TowerGrowthWithSpecificNote.getValue()) { + var manager = this.getPlayer().getStarTowerManager(); + int progress = 0; + + if (data.getParam1() != 0 && manager.hasGrowthNode(data.getParam1())) { + progress++; + } + + if (data.getParam2() != 0 && manager.hasGrowthNode(data.getParam2())) { + progress++; + } + + if (progress > 0) { + quest.setProgress(progress); + } + } + } + + // Return quest return quest; } @@ -146,14 +175,39 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject { // Get quest from entry var quest = entry.getValue(); - // Try to trigger quest - boolean result = quest.trigger(condition, progress, param1, param2); - - // Skip if quest progress wasn't changed - if (!result) { + // Skip completed quests + if (quest.isComplete()) { continue; } + // Star Tower quests use their own generated params and matching rules + // TODO clean this code up to look nice + if (quest.getType() == QuestType.Tower) { + // Get quest data + var data = GameData.getStarTowerQuestDataTable().get(quest.getId()); + if (data == null || data.getCompleteCond() != condition) { + continue; + } + + // Check params + if (!StarTowerQuestHelper.matches(data, param1, param2)) { + continue; + } + + // Add progress + if (!quest.addProgress(progress)) { + continue; + } + } else { + // Now we try to trigger regular daily/weekly quests + boolean result = quest.trigger(condition, progress, param1, param2); + + // Skip if quest progress wasn't changed + if (!result) { + continue; + } + } + // Sync quest with player client this.syncQuest(quest); @@ -176,6 +230,132 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject { ); } + // Star Tower quests + + /** + * Adds all currently unlocked Star Tower quests. + * Returns true if any quest was added or refreshed. + */ + public synchronized boolean initStarTowerQuests() { + boolean changed = false; + + for (var data : GameData.getStarTowerQuestDataTable()) { + // Only add quests whose prerequisites have been claimed + if (!StarTowerQuestHelper.isUnlocked(this, data)) { + continue; + } + + // Get existing quest + var quest = this.getList().get(data.getQuestKey()); + + if (quest == null) { + this.addQuest(new GameQuest(data)); + changed = true; + } else if (quest.refreshData(data)) { + changed = true; + } + } + + return changed; + } + + /** + * Adds quests that became available after a prerequisite was claimed. + */ + public synchronized void unlockStarTowerQuests() { + boolean changed = false; + + for (var data : GameData.getStarTowerQuestDataTable()) { + // Skip quests that already exist + if (this.getList().containsKey(data.getQuestKey())) { + continue; + } + + // Only add quests whose prerequisites have been claimed + if (!StarTowerQuestHelper.isUnlocked(this, data)) { + continue; + } + + // Add quest and sync it with the client + var quest = this.addQuest(new GameQuest(data)); + + // Syncs quest with client + this.syncQuest(quest); + + // Set changed flag + changed = true; + } + + // Persist new quests + if (changed) { + this.save(); + } + } + + public synchronized PlayerChangeInfo receiveStarTowerQuestReward(int questId) { + // Get received quests + var claimList = new ArrayList(); + + if (questId > 0) { + // Claim specific quest + var quest = this.getQuest(QuestType.Tower, questId); + + if (quest != null && quest.canClaim()) { + claimList.add(quest); + } + } else { + // Claim all + for (var quest : this.getQuests()) { + if (quest.getType() != QuestType.Tower) { + continue; + } + + if (!quest.canClaim()) { + continue; + } + + claimList.add(quest); + } + } + + // Sanity check + if (claimList.isEmpty()) { + return null; + } + + // Create change info + var change = new PlayerChangeInfo(); + + // Claim + for (var quest : claimList) { + // Get data + var data = GameData.getStarTowerQuestDataTable().get(quest.getId()); + + if (data != null) { + // Add rewards + if (data.getReward1() > 0 && data.getRewardQty1() > 0) { + this.getPlayer().getInventory().addItem(data.getReward1(), data.getRewardQty1(), change); + } + + if (data.getReward2() > 0 && data.getRewardQty2() > 0) { + this.getPlayer().getInventory().addItem(data.getReward2(), data.getRewardQty2(), change); + } + } + + // Set claimed + quest.setClaimed(true); + + // Update in database + Nebula.getGameDatabase().update(this, this.getUid(), "list." + quest.getKey(), quest); + } + + // Unlock newly available quests + this.unlockStarTowerQuests(); + + // Success + return change.setSuccess(true); + } + // Daily quests public synchronized int getDailyActivity() { @@ -525,11 +705,23 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject { // Fix quest lists if (this.getList() == null) { + // Create quest list this.list = new HashMap<>(); + + // Add missing Star Tower quests and refresh their condition data + // We do not need to save here because QuestManager::resetDailyQuests will save to the database + this.initStarTowerQuests(); + + // Reset daily quests this.resetDailyQuests(true); // QuestManager::resetDailyQuests will save to the database, so we dont need to set the shouldSave flag shouldSave = false; + } else { + // Add missing Star Tower quests and refresh their condition data + if (this.initStarTowerQuests()) { + shouldSave = true; + } } // Save to database diff --git a/src/main/java/emu/nebula/game/quest/StarTowerQuestHelper.java b/src/main/java/emu/nebula/game/quest/StarTowerQuestHelper.java new file mode 100644 index 0000000..7493d22 --- /dev/null +++ b/src/main/java/emu/nebula/game/quest/StarTowerQuestHelper.java @@ -0,0 +1,48 @@ +package emu.nebula.game.quest; + +import emu.nebula.data.resources.StarTowerQuestDef; +import emu.nebula.game.achievement.AchievementParamCond; + +// TODO clean up and merge with other quest helpers +public class StarTowerQuestHelper { + + /** + * Checks if all prerequisite quests for the specified quest have been claimed. + */ + public static boolean isUnlocked(QuestManager manager, StarTowerQuestDef data) { + for (int preId : data.getPreTowerQuestIds()) { + var quest = manager.getQuest(QuestType.Tower, preId); + + if (quest == null || !quest.isClaimed()) { + return false; + } + } + + return true; + } + + /** + * Checks whether a trigger payload matches the quest's generated params. + */ + public static boolean matches(StarTowerQuestDef data, int param1, int param2) { + // Growth node quests can require one or two specific nodes. + // The trigger payload puts the unlocked node id in param1. + if (data.getCompleteCond() == QuestCondition.TowerGrowthWithSpecificNote.getValue()) { + boolean matchesFirst = data.getParam1() != 0 && param1 == data.getParam1(); + boolean matchesSecond = data.getParam2() != 0 && param1 == data.getParam2(); + + return matchesFirst || matchesSecond; + } + + return matchesParam(data.getParam1(), data.getParamCond1(), param1) && matchesParam(data.getParam2(), data.getParamCond2(), param2); + } + + private static boolean matchesParam(int param, int cond, int value) { + // A param of zero is a wildcard, matching the existing GameQuest behavior + if (param == 0) { + return true; + } + + return AchievementParamCond.getByValue(cond).test(param, value); + } +} diff --git a/src/main/java/emu/nebula/game/tower/StarTowerGame.java b/src/main/java/emu/nebula/game/tower/StarTowerGame.java index ca22f61..02760a4 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.formation.Formation; import emu.nebula.game.inventory.ItemParamMap; import emu.nebula.game.player.Player; import emu.nebula.game.player.PlayerChangeInfo; +import emu.nebula.game.quest.QuestCondition; import emu.nebula.game.tower.cases.StarTowerBaseCase; import emu.nebula.game.tower.cases.StarTowerDoorCase; import emu.nebula.game.tower.cases.StarTowerHawkerCase; @@ -463,9 +464,11 @@ public class StarTowerGame { // Add to new infos this.getNewInfos().add(id, count); - // Achievment + // Achievement + Star Tower quests (Musical Notes). + // The quest treats param1 as a wildcard, so passing the item id keeps + // the per-note achievements working while counting every sub-note. if (count > 0) { - this.getAchievementManager().trigger(AchievementCondition.TowerItemsGet, count, id, 0); + this.getPlayer().trigger(QuestCondition.TowerItemsGet, count, id); } } case Res -> { @@ -866,15 +869,7 @@ public class StarTowerGame { int tickets = this.getModifiers().calculateTickets(); rewards.add(12, tickets); - // (Custom) Add research materials since tower quests are not implemented yet - int research = 50 + (Utils.randomRange(this.getDifficulty() - 1, this.getDifficulty() * 2) * 10); - rewards.add(51, research); - - // Add to inventory - var change = this.getPlayer().getInventory().addItem(51, research); - // Set proto data - settle.setChange(change.toProto()); rewards.toItemTemplateStream().forEach(settle::addTowerRewards); // Save tower tickets @@ -920,10 +915,10 @@ public class StarTowerGame { // Set new secondary skills this.secondarySkills = newSecondarySkills; - // Achievement trigger + // Achievement + Star Tower quests if (newSecondaryCount > 0) { - this.getAchievementManager().trigger( - AchievementCondition.TowerSpecificSecondarySkillActivateTotal, + this.getPlayer().trigger( + QuestCondition.TowerSpecificSecondarySkillActivateTotal, newSecondaryCount ); } diff --git a/src/main/java/emu/nebula/game/tower/StarTowerManager.java b/src/main/java/emu/nebula/game/tower/StarTowerManager.java index 7c63969..d661902 100644 --- a/src/main/java/emu/nebula/game/tower/StarTowerManager.java +++ b/src/main/java/emu/nebula/game/tower/StarTowerManager.java @@ -102,6 +102,10 @@ public class StarTowerManager extends PlayerManager { this.getProgress().getStarTowerGrowth() ); + // Star Tower quests + this.getPlayer().trigger(QuestCondition.TowerGrowthSpecificNote, 1, data.getId()); + this.getPlayer().trigger(QuestCondition.TowerGrowthWithSpecificNote, 1, data.getId()); + // Remove items return getPlayer().getInventory().removeItem(data.getItemId1(), data.getItemQty1()); } @@ -147,6 +151,14 @@ public class StarTowerManager extends PlayerManager { "starTowerGrowth", this.getProgress().getStarTowerGrowth() ); + + // Star Tower quests + for (int i = 0; i < unlocked.size(); i++) { + int nodeId = unlocked.getInt(i); + + this.getPlayer().trigger(QuestCondition.TowerGrowthSpecificNote, 1, nodeId); + this.getPlayer().trigger(QuestCondition.TowerGrowthWithSpecificNote, 1, nodeId); + } } // Set unlocked list @@ -190,6 +202,17 @@ public class StarTowerManager extends PlayerManager { rank.getRarity(), 0 ); + + // Star Tower quests use the record's rating level, not its rarity. + // NOTE: This must stay on the quest manager directly. Condition 504 is also + // used by the build-rarity achievements (param1 = rarity), so routing this + // through Player::trigger would feed them the level instead of the rarity. + this.getPlayer().getQuestManager().trigger( + QuestCondition.TowerBuildSpecificScoreWithTotal.getValue(), + 1, + rank.getLevel(), + 0 + ); } } @@ -415,6 +438,7 @@ public class StarTowerManager extends PlayerManager { // Trigger quest this.getPlayer().trigger(QuestCondition.TowerEnterFloor, 1); + this.getPlayer().trigger(QuestCondition.TowerEnterTotal, 1); // Success return change.setExtraData(this.game); @@ -439,6 +463,18 @@ public class StarTowerManager extends PlayerManager { // Add star tower history this.getPlayer().getProgress().addStarTowerLog(game.getId()); + // Star Tower quests (group + difficulty) + // NOTE: This must stay on the quest manager directly. Condition 506 is also + // used by the "Monolith Conqueror" achievements, but they interpret the + // params as (difficulty, 0) instead of (groupId, difficulty), so routing + // this through Player::trigger would corrupt them. + this.getPlayer().getQuestManager().trigger( + QuestCondition.TowerClearSpecificGroupIdAndDifficulty.getValue(), + 1, + game.getData().getGroupId(), + game.getDifficulty() + ); + // Achievement conditions var achievements = this.getPlayer().getAchievementManager(); 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 135cbe0..c12491e 100644 --- a/src/main/java/emu/nebula/game/tower/cases/StarTowerBattleCase.java +++ b/src/main/java/emu/nebula/game/tower/cases/StarTowerBattleCase.java @@ -4,6 +4,7 @@ import emu.nebula.GameConstants; import emu.nebula.data.GameData; import emu.nebula.game.inventory.ItemParamMap; import emu.nebula.game.player.PlayerChangeInfo; +import emu.nebula.game.quest.QuestCondition; import emu.nebula.game.tower.room.RoomType; import emu.nebula.proto.PublicStarTower.StarTowerRoomCase; import emu.nebula.proto.StarTowerInteract.StarTowerInteractReq; @@ -162,6 +163,9 @@ public class StarTowerBattleCase extends StarTowerBaseCase { // Bonus sub note chance (Note of Surprise) if (Utils.randomChance(this.getModifiers().getBonusSubNoteChance())) { subNotes += this.getModifiers().getBonusSubNotes(); + + // Star Tower quests + this.getGame().getPlayer().trigger(QuestCondition.TowerSpecificNoteActivateTotal, 1); } // Regular sub note drops 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 6fdd398..e7c7e37 100644 --- a/src/main/java/emu/nebula/game/tower/cases/StarTowerHawkerCase.java +++ b/src/main/java/emu/nebula/game/tower/cases/StarTowerHawkerCase.java @@ -5,8 +5,8 @@ import java.util.Map; import java.util.stream.Collectors; import emu.nebula.GameConstants; -import emu.nebula.game.achievement.AchievementCondition; import emu.nebula.game.player.PlayerChangeInfo; +import emu.nebula.game.quest.QuestCondition; import emu.nebula.game.tower.StarTowerShopGoods; import emu.nebula.proto.PublicStarTower.HawkerCaseData; import emu.nebula.proto.PublicStarTower.HawkerGoods; @@ -176,8 +176,8 @@ public class StarTowerHawkerCase extends StarTowerBaseCase { // Set change info rsp.setChange(change.toProto()); - // Achievement - this.getGame().getAchievementManager().trigger(AchievementCondition.TowerSpecificShopReRollTotal, 1); + // Achievement + Star Tower quests + this.getGame().getPlayer().trigger(QuestCondition.TowerSpecificShopReRollTotal, 1); } private void buy(int sid, StarTowerInteractResp rsp) { @@ -214,11 +214,11 @@ public class StarTowerHawkerCase extends StarTowerBaseCase { // Remove coins this.getGame().addItem(GameConstants.TOWER_COIN_ITEM_ID, -price, change); - // Achievements - this.getGame().getAchievementManager().trigger(AchievementCondition.TowerSpecificDifficultyShopBuyTimes, 1); + // Achievement + Star Tower quests + this.getGame().getPlayer().trigger(QuestCondition.TowerSpecificDifficultyShopBuyTimes, 1); if (goods.hasDiscount()) { - this.getGame().getAchievementManager().trigger(AchievementCondition.TowerSpecificShopBuyDiscountTotal, 1); + this.getGame().getPlayer().trigger(QuestCondition.TowerSpecificShopBuyDiscountTotal, 1); } // Set change info 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 ccf84ee..44d388b 100644 --- a/src/main/java/emu/nebula/game/tower/cases/StarTowerPotentialCase.java +++ b/src/main/java/emu/nebula/game/tower/cases/StarTowerPotentialCase.java @@ -3,7 +3,7 @@ package emu.nebula.game.tower.cases; import java.util.List; import emu.nebula.GameConstants; -import emu.nebula.game.achievement.AchievementCondition; +import emu.nebula.game.quest.QuestCondition; import emu.nebula.game.tower.StarTowerGame; import emu.nebula.game.tower.StarTowerPotentialInfo; import emu.nebula.proto.PublicStarTower.StarTowerRoomCase; @@ -118,8 +118,8 @@ public class StarTowerPotentialCase extends StarTowerBaseCase { rsp.setChange(change.toProto()); - // Achievement - this.getGame().getAchievementManager().trigger(AchievementCondition.TowerSpecificPotentialReRollTotal, 1); + // Achievement + Star Tower quests + this.getGame().getPlayer().trigger(QuestCondition.TowerSpecificPotentialReRollTotal, 1); } private void select(int index, StarTowerInteractResp rsp) { @@ -152,12 +152,12 @@ public class StarTowerPotentialCase extends StarTowerBaseCase { return; } - if (this.getGame().getPotentials().containsKey(charId)) { + if (this.getGame().getPotentials().containsKey(potential.getId())) { // Enhancing potentials - this.getGame().getAchievementManager().trigger(AchievementCondition.TowerSpecificPotentialLuckyTotal, 1); + this.getGame().getPlayer().trigger(QuestCondition.TowerSpecificPotentialLuckyTotal, 1); } else { // Adding new potential - this.getGame().getAchievementManager().trigger(AchievementCondition.TowerSpecificPotentialBonusTotal, 1); + this.getGame().getPlayer().trigger(QuestCondition.TowerSpecificPotentialBonusTotal, 1); } } diff --git a/src/main/java/emu/nebula/game/tower/cases/StarTowerStrengthenMachineCase.java b/src/main/java/emu/nebula/game/tower/cases/StarTowerStrengthenMachineCase.java index a9bfbc4..dc4359e 100644 --- a/src/main/java/emu/nebula/game/tower/cases/StarTowerStrengthenMachineCase.java +++ b/src/main/java/emu/nebula/game/tower/cases/StarTowerStrengthenMachineCase.java @@ -1,7 +1,7 @@ package emu.nebula.game.tower.cases; import emu.nebula.GameConstants; -import emu.nebula.game.achievement.AchievementCondition; +import emu.nebula.game.quest.QuestCondition; import emu.nebula.proto.PublicStarTower.StarTowerRoomCase; import emu.nebula.proto.StarTowerInteract.StarTowerInteractReq; import emu.nebula.proto.StarTowerInteract.StarTowerInteractResp; @@ -76,8 +76,8 @@ public class StarTowerStrengthenMachineCase extends StarTowerBaseCase { // Increment price this.increasePrice(); - // Achievement - this.getGame().getAchievementManager().trigger(AchievementCondition.TowerSpecificDifficultyStrengthenMachineTotal, 1); + // Trigger quests + achievements + this.getGame().getPlayer().trigger(QuestCondition.TowerSpecificDifficultyStrengthenMachineTotal, 1, 0); } // Set success result diff --git a/src/main/java/emu/nebula/server/handlers/HandlerQuestTowerRewardReceiveReq.java b/src/main/java/emu/nebula/server/handlers/HandlerQuestTowerRewardReceiveReq.java new file mode 100644 index 0000000..fd896d9 --- /dev/null +++ b/src/main/java/emu/nebula/server/handlers/HandlerQuestTowerRewardReceiveReq.java @@ -0,0 +1,28 @@ +package emu.nebula.server.handlers; + +import emu.nebula.net.NetHandler; +import emu.nebula.net.NetMsgId; +import emu.nebula.proto.Public.UI32; +import emu.nebula.net.HandlerId; +import emu.nebula.net.GameSession; + +@HandlerId(NetMsgId.quest_tower_reward_receive_req) +public class HandlerQuestTowerRewardReceiveReq extends NetHandler { + + @Override + public byte[] handle(GameSession session, byte[] message) throws Exception { + // Parse request + var req = UI32.parseFrom(message); + + // Receive rewards + var change = session.getPlayer().getQuestManager().receiveStarTowerQuestReward(req.getValue()); + + if (change == null) { + return session.encodeMsg(NetMsgId.quest_tower_reward_receive_failed_ack); + } + + // Encode and send + return session.encodeMsg(NetMsgId.quest_tower_reward_receive_succeed_ack, change.toProto()); + } + +} diff --git a/src/main/resources/defs/StarTowerQuestParam.json b/src/main/resources/defs/StarTowerQuestParam.json new file mode 100644 index 0000000..78886fb --- /dev/null +++ b/src/main/resources/defs/StarTowerQuestParam.json @@ -0,0 +1,515 @@ +[ + { + "Id": 100, + "CompleteCond": 515, + "Aim": 1, + "Param1": 10101, + "ParamCond1": 0, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 200, + "CompleteCond": 515, + "Aim": 1, + "Param1": 10301, + "ParamCond1": 0, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 300, + "CompleteCond": 527, + "Aim": 2, + "Param1": 10601, + "ParamCond1": 0, + "Param2": 10602, + "ParamCond2": 0 + }, + { + "Id": 400, + "CompleteCond": 515, + "Aim": 1, + "Param1": 10901, + "ParamCond1": 0, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 500, + "CompleteCond": 527, + "Aim": 2, + "Param1": 20301, + "ParamCond1": 0, + "Param2": 20302, + "ParamCond2": 0 + }, + { + "Id": 600, + "CompleteCond": 515, + "Aim": 1, + "Param1": 20601, + "ParamCond1": 0, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 700, + "CompleteCond": 527, + "Aim": 2, + "Param1": 20901, + "ParamCond1": 0, + "Param2": 20902, + "ParamCond2": 0 + }, + { + "Id": 800, + "CompleteCond": 515, + "Aim": 1, + "Param1": 30301, + "ParamCond1": 0, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 900, + "CompleteCond": 515, + "Aim": 1, + "Param1": 30601, + "ParamCond1": 0, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 1000, + "CompleteCond": 515, + "Aim": 1, + "Param1": 30901, + "ParamCond1": 0, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 1100, + "CompleteCond": 515, + "Aim": 1, + "Param1": 40401, + "ParamCond1": 0, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 101, + "CompleteCond": 510, + "Aim": 1, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 102, + "CompleteCond": 506, + "Aim": 1, + "Param1": 2, + "ParamCond1": 0, + "Param2": 1, + "ParamCond2": 4 + }, + { + "Id": 103, + "CompleteCond": 506, + "Aim": 1, + "Param1": 0, + "ParamCond1": 1, + "Param2": 2, + "ParamCond2": 4 + }, + { + "Id": 201, + "CompleteCond": 506, + "Aim": 2, + "Param1": 0, + "ParamCond1": 1, + "Param2": 2, + "ParamCond2": 4 + }, + { + "Id": 202, + "CompleteCond": 514, + "Aim": 10, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 203, + "CompleteCond": 513, + "Aim": 30, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 301, + "CompleteCond": 504, + "Aim": 1, + "Param1": 5, + "ParamCond1": 4, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 302, + "CompleteCond": 513, + "Aim": 80, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 303, + "CompleteCond": 517, + "Aim": 10, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 401, + "CompleteCond": 506, + "Aim": 1, + "Param1": 0, + "ParamCond1": 1, + "Param2": 3, + "ParamCond2": 4 + }, + { + "Id": 402, + "CompleteCond": 514, + "Aim": 20, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 403, + "CompleteCond": 522, + "Aim": 6, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 501, + "CompleteCond": 535, + "Aim": 8, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 502, + "CompleteCond": 504, + "Aim": 1, + "Param1": 10, + "ParamCond1": 4, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 503, + "CompleteCond": 513, + "Aim": 150, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 504, + "CompleteCond": 536, + "Aim": 10, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 505, + "CompleteCond": 517, + "Aim": 20, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 601, + "CompleteCond": 506, + "Aim": 1, + "Param1": 0, + "ParamCond1": 1, + "Param2": 4, + "ParamCond2": 4 + }, + { + "Id": 602, + "CompleteCond": 514, + "Aim": 50, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 603, + "CompleteCond": 522, + "Aim": 20, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 605, + "CompleteCond": 531, + "Aim": 3, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 701, + "CompleteCond": 533, + "Aim": 3, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 702, + "CompleteCond": 504, + "Aim": 1, + "Param1": 20, + "ParamCond1": 4, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 703, + "CompleteCond": 513, + "Aim": 500, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 704, + "CompleteCond": 536, + "Aim": 25, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 705, + "CompleteCond": 517, + "Aim": 30, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 801, + "CompleteCond": 506, + "Aim": 5, + "Param1": 0, + "ParamCond1": 1, + "Param2": 4, + "ParamCond2": 4 + }, + { + "Id": 802, + "CompleteCond": 514, + "Aim": 100, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 803, + "CompleteCond": 522, + "Aim": 80, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 804, + "CompleteCond": 529, + "Aim": 20, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 901, + "CompleteCond": 506, + "Aim": 2, + "Param1": 0, + "ParamCond1": 1, + "Param2": 5, + "ParamCond2": 4 + }, + { + "Id": 902, + "CompleteCond": 504, + "Aim": 1, + "Param1": 25, + "ParamCond1": 4, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 903, + "CompleteCond": 513, + "Aim": 2000, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 904, + "CompleteCond": 536, + "Aim": 50, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 905, + "CompleteCond": 517, + "Aim": 40, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 906, + "CompleteCond": 530, + "Aim": 10, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 1001, + "CompleteCond": 506, + "Aim": 2, + "Param1": 0, + "ParamCond1": 1, + "Param2": 6, + "ParamCond2": 4 + }, + { + "Id": 1002, + "CompleteCond": 514, + "Aim": 200, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 1003, + "CompleteCond": 522, + "Aim": 150, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 1004, + "CompleteCond": 533, + "Aim": 10, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 1005, + "CompleteCond": 534, + "Aim": 5, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 1101, + "CompleteCond": 506, + "Aim": 3, + "Param1": 0, + "ParamCond1": 1, + "Param2": 8, + "ParamCond2": 4 + }, + { + "Id": 1102, + "CompleteCond": 513, + "Aim": 3000, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 1103, + "CompleteCond": 504, + "Aim": 1, + "Param1": 31, + "ParamCond1": 4, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 1104, + "CompleteCond": 536, + "Aim": 80, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + }, + { + "Id": 1105, + "CompleteCond": 533, + "Aim": 30, + "Param1": 0, + "ParamCond1": 1, + "Param2": 0, + "ParamCond2": 1 + } +]