diff --git a/src/main/java/emu/nebula/game/achievement/AchievementHelper.java b/src/main/java/emu/nebula/game/achievement/AchievementHelper.java index 522db4f..1e3c754 100644 --- a/src/main/java/emu/nebula/game/achievement/AchievementHelper.java +++ b/src/main/java/emu/nebula/game/achievement/AchievementHelper.java @@ -53,11 +53,45 @@ public class AchievementHelper { } private static void fixParams() { - // Star Tower TODO - addParam(78, 0, 2); - addParam(79, 0, 4); + // Clear "Misstep On One" + addParam(56, 401, 0); // Custom trigger + + // Clear "Currents and Shadows" + addParam(57, 102, 0); + addParam(58, 103, 0); + addParam(59, 104, 0); + addParam(60, 105, 0); + addParam(61, 106, 0); + addParam(62, 107, 0); + addParam(63, 108, 0); + + // Clear "Dust and Flames" + addParam(64, 202, 0); + addParam(65, 203, 0); + addParam(66, 204, 0); + addParam(67, 205, 0); + addParam(68, 206, 0); + addParam(69, 207, 0); + addParam(70, 208, 0); + + // Clear "Storm and Thunder" + addParam(71, 302, 0); + addParam(72, 303, 0); + addParam(73, 304, 0); + addParam(74, 305, 0); + addParam(75, 306, 0); + addParam(76, 307, 0); + addParam(77, 308, 0); + + // First Ascension addParam(498, 0, 1); + // Monolith Conqueror + addParam(78, 2, 0); + addParam(79, 4, 0); + addParam(80, 6, 0); + addParam(81, 7, 0); + // Money addParam(25, GameConstants.GOLD_ITEM_ID, 0); addParam(26, GameConstants.GOLD_ITEM_ID, 0); diff --git a/src/main/java/emu/nebula/game/achievement/AchievementManager.java b/src/main/java/emu/nebula/game/achievement/AchievementManager.java index cda3f7e..902b596 100644 --- a/src/main/java/emu/nebula/game/achievement/AchievementManager.java +++ b/src/main/java/emu/nebula/game/achievement/AchievementManager.java @@ -5,6 +5,7 @@ import java.util.Map; import dev.morphia.annotations.Entity; import dev.morphia.annotations.Id; + import emu.nebula.Nebula; import emu.nebula.data.GameData; import emu.nebula.data.resources.AchievementDef; @@ -16,8 +17,8 @@ import emu.nebula.game.player.PlayerManager; import emu.nebula.net.NetMsgId; import emu.nebula.proto.Public.Achievements; import emu.nebula.proto.Public.Events; + import lombok.Getter; -import lombok.Setter; import us.hebi.quickbuf.RepeatedInt; @Getter @@ -29,8 +30,9 @@ public class AchievementManager extends PlayerManager implements GameDatabaseObj // Achievement data private Map achievements; - @Setter + // Flags private transient boolean queueSave; + private transient boolean hasCompleted; @Deprecated // Morphia only public AchievementManager() { @@ -79,9 +81,6 @@ public class AchievementManager extends PlayerManager implements GameDatabaseObj } public synchronized void handleClientEvents(Events events) { - // - boolean hasCompleted = false; - // Parse events for (var event : events.getList()) { // Check id @@ -117,23 +116,15 @@ public class AchievementManager extends PlayerManager implements GameDatabaseObj // Update achievement boolean changed = achievement.trigger(true, progress, 0, 0); - // Only save/update on client if achievement was changed + // Sync with client if achievement was changed if (changed) { - // Sync this.syncAchievement(achievement); - - // Set save flag - this.queueSave = true; - - // Check if achievement was completed - if (achievement.isComplete()) { - hasCompleted = true; - } } } - // Trigger update - if (hasCompleted) { + // Update total achievements + if (this.hasCompleted) { + this.hasCompleted = false; this.getPlayer().trigger(AchievementCondition.AchievementTotal, this.getCompletedAchievementsCount()); } } @@ -166,8 +157,7 @@ public class AchievementManager extends PlayerManager implements GameDatabaseObj // Check what type of achievement condition this is boolean isTotal = AchievementHelper.isIncrementalAchievement(condition); - boolean hasCompleted = false; - + // Parse achievements for (var data : triggerList) { // Get achievement @@ -176,23 +166,41 @@ public class AchievementManager extends PlayerManager implements GameDatabaseObj // Update achievement boolean changed = achievement.trigger(isTotal, progress, param1, param2); - // Only save/update on client if achievement was changed + // Sync with client if achievement was changed if (changed) { - // Sync this.syncAchievement(achievement); - - // Set save flag - this.queueSave = true; - - // Check if achievement was completed - if (achievement.isComplete()) { - hasCompleted = true; - } } } - // Trigger update - if (hasCompleted) { + // Update total achievements + if (this.hasCompleted) { + this.hasCompleted = false; + this.getPlayer().trigger(AchievementCondition.AchievementTotal, this.getCompletedAchievementsCount()); + } + } + + public synchronized void triggerOne(int id, int progress, int param1, int param2) { + // Get achievement data + var data = GameData.getAchievementDataTable().get(id); + if (data == null) return; + + // Get achievement + var achievement = this.getAchievement(data); + + // Check what type of achievement condition this is + boolean isTotal = AchievementHelper.isIncrementalAchievement(data.getCompleteCond()); + + // Update achievement + boolean changed = achievement.trigger(isTotal, progress, param1, param2); + + // Sync with client if achievement was changed + if (changed) { + this.syncAchievement(achievement); + } + + // Update total achievements + if (this.hasCompleted) { + this.hasCompleted = false; this.getPlayer().trigger(AchievementCondition.AchievementTotal, this.getCompletedAchievementsCount()); } } @@ -205,6 +213,15 @@ public class AchievementManager extends PlayerManager implements GameDatabaseObj return; } + // Set save flag + this.queueSave = true; + + // Check if achievement was completed + if (achievement.isComplete()) { + this.hasCompleted = true; + } + + // Send update to player getPlayer().addNextPackage( NetMsgId.achievement_change_notify, achievement.toProto() diff --git a/src/main/java/emu/nebula/game/tower/StarTowerGame.java b/src/main/java/emu/nebula/game/tower/StarTowerGame.java index 6868609..ef0e250 100644 --- a/src/main/java/emu/nebula/game/tower/StarTowerGame.java +++ b/src/main/java/emu/nebula/game/tower/StarTowerGame.java @@ -769,32 +769,7 @@ public class StarTowerGame { } // Refresh secondary skills - var newSecondarySkills = SecondarySkillDef.calculateSecondarySkills(this.getDiscIds(), this.getItems()); - - // Add any new secondary skills to the data proto - for (int id : newSecondarySkills) { - if (!this.getSecondarySkills().contains(id)) { - var info = ActiveSecondaryChange.newInstance() - .setSecondaryId(id) - .setActive(true); - - data.addSecondaries(info); - } - } - - // Inform the client that these skills are no longer active - for (int id : this.getSecondarySkills()) { - if (!newSecondarySkills.contains(id)) { - var info = ActiveSecondaryChange.newInstance() - .setSecondaryId(id) - .setActive(false); - - data.addSecondaries(info); - } - } - - // Set new secondary skills - this.secondarySkills = newSecondarySkills; + this.refreshSecondarySkills(data); // Clear new infos this.getNewInfos().clear(); @@ -826,6 +801,50 @@ public class StarTowerGame { return rsp; } + // Etc + + private void refreshSecondarySkills(TowerChangeData data) { + // Init + var newSecondarySkills = SecondarySkillDef.calculateSecondarySkills(this.getDiscIds(), this.getItems()); + int newSecondaryCount = 0; + + // Add any new secondary skills to the data proto + for (int id : newSecondarySkills) { + if (!this.getSecondarySkills().contains(id)) { + var info = ActiveSecondaryChange.newInstance() + .setSecondaryId(id) + .setActive(true); + + data.addSecondaries(info); + + // Counter + newSecondaryCount++; + } + } + + // Inform the client that these skills are no longer active + for (int id : this.getSecondarySkills()) { + if (!newSecondarySkills.contains(id)) { + var info = ActiveSecondaryChange.newInstance() + .setSecondaryId(id) + .setActive(false); + + data.addSecondaries(info); + } + } + + // Set new secondary skills + this.secondarySkills = newSecondarySkills; + + // Achievement trigger + if (newSecondaryCount > 0) { + this.getAchievementManager().trigger( + AchievementCondition.TowerSpecificSecondarySkillActivateTotal, + newSecondaryCount + ); + } + } + // Proto public StarTowerInfo toProto() { diff --git a/src/main/java/emu/nebula/game/tower/StarTowerManager.java b/src/main/java/emu/nebula/game/tower/StarTowerManager.java index 2229d67..2c21856 100644 --- a/src/main/java/emu/nebula/game/tower/StarTowerManager.java +++ b/src/main/java/emu/nebula/game/tower/StarTowerManager.java @@ -12,6 +12,7 @@ import emu.nebula.game.quest.QuestCondition; import emu.nebula.proto.StarTowerApply.StarTowerApplyReq; import emu.nebula.util.Utils; import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; @@ -34,6 +35,10 @@ public class StarTowerManager extends PlayerManager { return this.getPlayer().getProgress(); } + public IntSet getStarTowerLog() { + return this.getProgress().getStarTowerLog(); + } + // Growth nodes (talents/research) public boolean hasGrowthNode(int id) { @@ -240,23 +245,20 @@ public class StarTowerManager extends PlayerManager { var achievements = this.getPlayer().getAchievementManager(); achievements.trigger(AchievementCondition.TowerClearTotal, 1); - achievements.trigger( - AchievementCondition.TowerClearSpecificGroupIdAndDifficulty, - 1, - game.getData().getGroupId(), - game.getData().getDifficulty() - ); achievements.trigger( AchievementCondition.TowerClearSpecificLevelWithDifficultyAndTotal, 1, game.getData().getId(), - game.getData().getDifficulty() + 0 ); var elementType = game.getTeamElement(); if (elementType != null) { achievements.trigger(AchievementCondition.TowerClearSpecificCharacterTypeWithTotal, 1, elementType.getValue(), 0); } + + // Update tower group achievements + this.updateTowerGroupAchievements(game); } // Return game @@ -290,6 +292,35 @@ public class StarTowerManager extends PlayerManager { return change; } + // Achievements + + private void updateTowerGroupAchievements(StarTowerGame game) { + // Update "First Ascension" achievement + boolean firstAscension = this.getStarTowerLog().contains(401) && this.getStarTowerLog().size() >= 2; + if (firstAscension) { + this.getPlayer().getAchievementManager().triggerOne(498, 1, 0, 1); + } + + // Get total clears on this difficulty + int diff = game.getDifficulty(); + int totalDiffClears = 0; + + for (int i = 1; i <= 3; i++) { + int towerId = (i * 100) + 1 + diff; + if (this.getStarTowerLog().contains(towerId)) { + totalDiffClears++; + } + } + + // Update "Monolith Conqueror" achievements + this.getPlayer().getAchievementManager().trigger( + AchievementCondition.TowerClearSpecificGroupIdAndDifficulty, + totalDiffClears, + diff, + 0 + ); + } + // Build private PlayerChangeInfo dismantleBuild(StarTowerBuild build, PlayerChangeInfo change) { 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 9e7eb15..eac016a 100644 --- a/src/main/java/emu/nebula/game/tower/cases/StarTowerHawkerCase.java +++ b/src/main/java/emu/nebula/game/tower/cases/StarTowerHawkerCase.java @@ -209,9 +209,13 @@ public class StarTowerHawkerCase extends StarTowerBaseCase { // Remove coins this.getGame().addItem(GameConstants.TOWER_COIN_ITEM_ID, -price, change); - // Achievement + // Achievements this.getGame().getAchievementManager().trigger(AchievementCondition.TowerSpecificDifficultyShopBuyTimes, 1); + if (goods.hasDiscount()) { + this.getGame().getAchievementManager().trigger(AchievementCondition.TowerSpecificShopBuyDiscountTotal, 1); + } + // Set change info rsp.setChange(change.toProto()); }