diff --git a/src/main/java/emu/nebula/data/resources/AchievementDef.java b/src/main/java/emu/nebula/data/resources/AchievementDef.java index 0987d3e..0c2758b 100644 --- a/src/main/java/emu/nebula/data/resources/AchievementDef.java +++ b/src/main/java/emu/nebula/data/resources/AchievementDef.java @@ -20,8 +20,8 @@ public class AchievementDef extends BaseDef { private int Qty1; // Custom params - private transient int param1; - private transient int param2; + private transient int param1; // -1 == any, 0 = no param, 1+ = param required + private transient int param2; // -1 == any, 0 = no param, 1+ = param required @Override public int getId() { @@ -33,12 +33,30 @@ public class AchievementDef extends BaseDef { this.param2 = param2; } - public boolean hasParam1() { - return this.param1 > 0; + /** + * Checks if this achievement requires params to match + */ + public boolean hasParam1(int param) { + if (this.param1 < 0) { + return false; + } else if (this.param1 == 0) { + return param != 0; + } else { + return true; + } } - public boolean hasParam2() { - return this.param2 > 0; + /** + * Checks if this achievement requires params to match + */ + public boolean hasParam2(int param) { + if (this.param2 < 0) { + return false; + } else if (this.param2 == 0) { + return param != 0; + } else { + return true; + } } @Override diff --git a/src/main/java/emu/nebula/game/achievement/AchievementHelper.java b/src/main/java/emu/nebula/game/achievement/AchievementHelper.java index 9cda124..d1dc38e 100644 --- a/src/main/java/emu/nebula/game/achievement/AchievementHelper.java +++ b/src/main/java/emu/nebula/game/achievement/AchievementHelper.java @@ -14,7 +14,7 @@ import lombok.Getter; // Because achievements in the data files do not have params, we will hardcode them here public class AchievementHelper { // Cache - private static IntSet isTotalAchievementSet = new IntOpenHashSet(); + private static IntSet incrementalAchievementSet = new IntOpenHashSet(); @Getter private static Int2ObjectMap> cache = new Int2ObjectOpenHashMap<>(); @@ -25,8 +25,8 @@ public class AchievementHelper { // - public static boolean isTotalAchievement(int condition) { - return isTotalAchievementSet.contains(condition); + public static boolean isIncrementalAchievement(int condition) { + return incrementalAchievementSet.contains(condition); } // Fix params @@ -35,12 +35,14 @@ public class AchievementHelper { // Cache total achievements for (var condition : AchievementCondition.values()) { if (condition.name().endsWith("Total")) { - isTotalAchievementSet.add(condition.getValue()); + incrementalAchievementSet.add(condition.getValue()); } } - isTotalAchievementSet.add(AchievementCondition.ItemsAdd.getValue()); - isTotalAchievementSet.add(AchievementCondition.ItemsDeplete.getValue()); + incrementalAchievementSet.remove(AchievementCondition.AchievementTotal.getValue()); + + incrementalAchievementSet.add(AchievementCondition.ItemsAdd.getValue()); + incrementalAchievementSet.add(AchievementCondition.ItemsDeplete.getValue()); // Fix params fixParams(); @@ -58,6 +60,33 @@ public class AchievementHelper { addParam(27, GameConstants.GOLD_ITEM_ID, 0); addParam(28, GameConstants.GOLD_ITEM_ID, 0); addParam(29, GameConstants.GOLD_ITEM_ID, 0); + + // Ininfite tower + for (int diff = 10, id = 270; diff <= 60; diff += 10) { + addParam(id++, 11000 + diff, 0); // Infinite Arena + addParam(id++, 51000 + diff, 0); // Shake the Floor + addParam(id++, 41000 + diff, 0); // Elegance and Flow + addParam(id++, 71000 + diff, 0); // Upbeat Party + addParam(id++, 31000 + diff, 0); // Thrilling Beat + addParam(id++, 21000 + diff, 0); // Flames and Beats + addParam(id++, 61000 + diff, 0); // Sinister Ritual + } + + // Character count + addParam(393, 1, 0); + addParam(394, 1, 0); + addParam(395, 1, 0); + addParam(396, 1, 0); + addParam(397, 1, 0); + addParam(398, 1, 0); + + // Disc count + addParam(382, 1, 0); + addParam(383, 1, 0); + addParam(384, 1, 0); + addParam(385, 1, 0); + addParam(386, 1, 0); + addParam(387, 1, 0); } private static void addParam(int achievementId, int param1, int param2) { diff --git a/src/main/java/emu/nebula/game/achievement/AchievementManager.java b/src/main/java/emu/nebula/game/achievement/AchievementManager.java index 63d5515..f49f3ae 100644 --- a/src/main/java/emu/nebula/game/achievement/AchievementManager.java +++ b/src/main/java/emu/nebula/game/achievement/AchievementManager.java @@ -85,7 +85,7 @@ public class AchievementManager extends PlayerManager implements GameDatabaseObj // Parse events for (var event : events.getList()) { // Check id - if (event.getId() != 200) { + if (event.getId() != AchievementCondition.ClientReport.getValue()) { continue; } @@ -157,7 +157,7 @@ public class AchievementManager extends PlayerManager implements GameDatabaseObj } // Check what type of achievement condition this is - boolean isTotal = AchievementHelper.isTotalAchievement(condition); + boolean isTotal = AchievementHelper.isIncrementalAchievement(condition); boolean hasCompleted = false; // Parse achievements diff --git a/src/main/java/emu/nebula/game/achievement/GameAchievement.java b/src/main/java/emu/nebula/game/achievement/GameAchievement.java index 2d09039..e7c465c 100644 --- a/src/main/java/emu/nebula/game/achievement/GameAchievement.java +++ b/src/main/java/emu/nebula/game/achievement/GameAchievement.java @@ -75,11 +75,11 @@ public class GameAchievement { var data = this.getData(); if (data == null) return false; - if ((data.hasParam1() || param1 != 0) && data.getParam1() != param1) { + if (data.hasParam1(param1) && data.getParam1() != param1) { return false; } - if ((data.hasParam2() || param2 != 0) && data.getParam2() != param2) { + if (data.hasParam2(param2) && data.getParam2() != param2) { return false; } diff --git a/src/main/java/emu/nebula/game/character/CharacterStorage.java b/src/main/java/emu/nebula/game/character/CharacterStorage.java index 07d75ec..0e72ca4 100644 --- a/src/main/java/emu/nebula/game/character/CharacterStorage.java +++ b/src/main/java/emu/nebula/game/character/CharacterStorage.java @@ -8,8 +8,10 @@ import emu.nebula.data.GameData; import emu.nebula.data.resources.CharacterDef; import emu.nebula.data.resources.DiscDef; import emu.nebula.game.player.PlayerManager; +import emu.nebula.net.NetMsgId; import emu.nebula.proto.Public.HandbookInfo; import emu.nebula.util.Bitset; +import emu.nebula.game.achievement.AchievementCondition; import emu.nebula.game.player.Player; import emu.nebula.game.player.PlayerChangeInfo; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -22,6 +24,10 @@ public class CharacterStorage extends PlayerManager { private final Int2ObjectMap characters; private final Int2ObjectMap discs; + // Flags + @Setter private boolean hasAddedChar; + @Setter private boolean hasAddedDisc; + @Setter private boolean updateCharHandbook; @Setter private boolean updateDiscHandbook; @@ -67,11 +73,14 @@ public class CharacterStorage extends PlayerManager { // Save to database character.save(); - // Set flag for player to update character skins in their handbook - this.setUpdateCharHandbook(true); - // Add to characters this.characters.put(character.getCharId(), character); + + // Set flags for player to update character skins in their handbook + this.setUpdateCharHandbook(true); + this.setHasAddedChar(true); + + // Return character return character; } @@ -79,18 +88,6 @@ public class CharacterStorage extends PlayerManager { return this.getCharacters().values(); } - public int getNewPhoneMessageCount() { - int count = 0; - - for (var character : this.getCharacterCollection()) { - if (character.getContact().hasNew()) { - count++; - } - } - - return count; - } - public HandbookInfo getCharacterHandbook() { var bitset = new Bitset(); @@ -145,11 +142,14 @@ public class CharacterStorage extends PlayerManager { // Save to database disc.save(); - // Set flag for player to update discs in their handbook - this.setUpdateDiscHandbook(true); - // Add to discs this.discs.put(disc.getDiscId(), disc); + + // Set flags for player to update discs in their handbook + this.setUpdateDiscHandbook(true); + this.setHasAddedDisc(true); + + // Return disc return disc; } @@ -215,6 +215,73 @@ public class CharacterStorage extends PlayerManager { return change.setExtraData(modifiedDiscs); } + // Contacts + + public int getNewPhoneMessageCount() { + int count = 0; + + for (var character : this.getCharacterCollection()) { + if (character.getContact().hasNew()) { + count++; + } + } + + return count; + } + + // + + /** + * Checks if we should add next packages for player + */ + public void checkPlayerState() { + // Check if we need to trigger character achievements + if (this.hasAddedChar) { + this.hasAddedChar = false; + this.getPlayer().trigger( + AchievementCondition.CharactersWithSpecificQuantityAndRarity, + getCharacters().size() + ); + this.getPlayer().trigger( + AchievementCondition.CharactersWithSpecificQuantityAndRarity, + (int) getCharacters().values().stream().filter(GameCharacter::isMaster).count(), + 1, + 0 + ); + } + + // Check if we need to send handbook update to player + if (this.updateCharHandbook) { + this.updateCharHandbook = false; + this.getPlayer().addNextPackage( + NetMsgId.handbook_change_notify, + this.getPlayer().getCharacters().getCharacterHandbook()); + } + + // Check if we need to trigger disc achievements + if (this.hasAddedChar) { + this.hasAddedChar = false; + this.getPlayer().trigger( + AchievementCondition.DiscAcquireSpecificQuantityAndRarity, + this.getDiscs().size() + ); + this.getPlayer().trigger( + AchievementCondition.DiscAcquireSpecificQuantityAndRarity, + (int) getDiscs().values().stream().filter(GameDisc::isMaster).count(), + 1, + 0 + ); + } + + // Check if we need to send handbook update to player + if (this.updateDiscHandbook) { + this.updateDiscHandbook = false; + this.getPlayer().addNextPackage( + NetMsgId.handbook_change_notify, + this.getPlayer().getCharacters().getDiscHandbook()); + } + } + // Database public void loadFromDatabase() { diff --git a/src/main/java/emu/nebula/game/character/GameCharacter.java b/src/main/java/emu/nebula/game/character/GameCharacter.java index f14fb2b..089e967 100644 --- a/src/main/java/emu/nebula/game/character/GameCharacter.java +++ b/src/main/java/emu/nebula/game/character/GameCharacter.java @@ -18,6 +18,7 @@ import emu.nebula.data.GameData; import emu.nebula.data.resources.CharacterDef; import emu.nebula.data.resources.TalentGroupDef; import emu.nebula.database.GameDatabaseObject; +import emu.nebula.game.achievement.AchievementCondition; import emu.nebula.game.inventory.ItemParamMap; import emu.nebula.game.player.Player; import emu.nebula.game.player.PlayerChangeInfo; @@ -117,6 +118,10 @@ public class GameCharacter implements GameDatabaseObject { } } + public boolean isMaster() { + return this.getData().getGrade() == 1; + } + public void setLevel(int level) { this.level = level; } @@ -272,6 +277,9 @@ public class GameCharacter implements GameDatabaseObject { // Save to database this.save(); + // Trigger quest/achievement + this.getPlayer().trigger(AchievementCondition.CharacterAdvanceTotal, 1); + // Success return changes.setSuccess(true); } diff --git a/src/main/java/emu/nebula/game/character/GameDisc.java b/src/main/java/emu/nebula/game/character/GameDisc.java index b77cda5..eaa4b0d 100644 --- a/src/main/java/emu/nebula/game/character/GameDisc.java +++ b/src/main/java/emu/nebula/game/character/GameDisc.java @@ -11,6 +11,7 @@ import emu.nebula.data.GameData; import emu.nebula.data.resources.DiscDef; import emu.nebula.data.resources.SubNoteSkillPromoteGroupDef; import emu.nebula.database.GameDatabaseObject; +import emu.nebula.game.achievement.AchievementCondition; import emu.nebula.game.inventory.ItemParamMap; import emu.nebula.game.player.Player; import emu.nebula.game.player.PlayerChangeInfo; @@ -70,6 +71,10 @@ public class GameDisc implements GameDatabaseObject { } } + public boolean isMaster() { + return GameData.getItemDataTable().get(this.getDiscId()).getRarity() == 1; + } + public void setLevel(int level) { this.level = level; } @@ -215,6 +220,9 @@ public class GameDisc implements GameDatabaseObject { // Save to database this.save(); + // Trigger quest/achievement + this.getPlayer().trigger(AchievementCondition.DiscPromoteTotal, 1); + // Success return change.setSuccess(true); } diff --git a/src/main/java/emu/nebula/game/infinitytower/InfinityTowerManager.java b/src/main/java/emu/nebula/game/infinitytower/InfinityTowerManager.java index 40c8209..df8bc41 100644 --- a/src/main/java/emu/nebula/game/infinitytower/InfinityTowerManager.java +++ b/src/main/java/emu/nebula/game/infinitytower/InfinityTowerManager.java @@ -2,6 +2,7 @@ package emu.nebula.game.infinitytower; import emu.nebula.data.GameData; import emu.nebula.data.resources.InfinityTowerLevelDef; +import emu.nebula.game.achievement.AchievementCondition; import emu.nebula.game.player.Player; import emu.nebula.game.player.PlayerChangeInfo; import emu.nebula.game.player.PlayerManager; @@ -75,6 +76,9 @@ public class InfinityTowerManager extends PlayerManager { // Log in player progress this.getPlayer().getProgress().addInfinityArenaLog(this.getLevelId()); + // Trigger achievement + this.getPlayer().trigger(AchievementCondition.InfinityTowerClearSpecificFloor, 10, this.getLevelId(), 0); + // Success return change.setSuccess(true); } diff --git a/src/main/java/emu/nebula/net/GameSession.java b/src/main/java/emu/nebula/net/GameSession.java index 9a0e133..bad390c 100644 --- a/src/main/java/emu/nebula/net/GameSession.java +++ b/src/main/java/emu/nebula/net/GameSession.java @@ -193,18 +193,7 @@ public class GameSession { } // Check handbook states - if (this.getPlayer().getCharacters().isUpdateCharHandbook()) { - getPlayer().getCharacters().setUpdateCharHandbook(false); - getPlayer().addNextPackage( - NetMsgId.handbook_change_notify, - this.getPlayer().getCharacters().getCharacterHandbook()); - } - if (this.getPlayer().getCharacters().isUpdateDiscHandbook()) { - getPlayer().getCharacters().setUpdateDiscHandbook(false); - getPlayer().addNextPackage( - NetMsgId.handbook_change_notify, - this.getPlayer().getCharacters().getDiscHandbook()); - } + this.getPlayer().getCharacters().checkPlayerState(); } private ProtoMessage addNextPackages(ProtoMessage proto) {