mirror of
https://github.com/Melledy/Nebula.git
synced 2025-12-14 05:14:46 +01:00
Implement battle pass
This commit is contained in:
@@ -22,4 +22,6 @@ public class GameConstants {
|
||||
|
||||
public static final int MAX_FORMATIONS = 5;
|
||||
public static final int MAX_SHOWCASE_IDS = 5;
|
||||
|
||||
public static final int BATTLE_PASS_ID = 1;
|
||||
}
|
||||
|
||||
@@ -53,6 +53,12 @@ public class GameData {
|
||||
@Getter private static DataTable<ResidentShopDef> ResidentShopDataTable = new DataTable<>();
|
||||
@Getter private static DataTable<ResidentGoodsDef> ResidentGoodsDataTable = new DataTable<>();
|
||||
|
||||
// Battle Pass
|
||||
@Getter private static DataTable<BattlePassDef> BattlePassDataTable = new DataTable<>();
|
||||
@Getter private static DataTable<BattlePassLevelDef> BattlePassLevelDataTable = new DataTable<>();
|
||||
@Getter private static DataTable<BattlePassQuestDef> BattlePassQuestDataTable = new DataTable<>();
|
||||
@Getter private static DataTable<BattlePassRewardDef> BattlePassRewardDataTable = new DataTable<>();
|
||||
|
||||
// Commissions
|
||||
@Getter private static DataTable<AgentDef> AgentDataTable = new DataTable<>();
|
||||
|
||||
|
||||
16
src/main/java/emu/nebula/data/resources/BattlePassDef.java
Normal file
16
src/main/java/emu/nebula/data/resources/BattlePassDef.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package emu.nebula.data.resources;
|
||||
|
||||
import emu.nebula.data.BaseDef;
|
||||
import emu.nebula.data.ResourceType;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@ResourceType(name = "BattlePass.json")
|
||||
public class BattlePassDef extends BaseDef {
|
||||
private int ID;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return ID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package emu.nebula.data.resources;
|
||||
|
||||
import emu.nebula.data.BaseDef;
|
||||
import emu.nebula.data.ResourceType;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@ResourceType(name = "BattlePassLevel.json")
|
||||
public class BattlePassLevelDef extends BaseDef {
|
||||
private int ID;
|
||||
private int Exp;
|
||||
|
||||
private int Tid;
|
||||
private int Qty;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return ID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package emu.nebula.data.resources;
|
||||
|
||||
import emu.nebula.data.BaseDef;
|
||||
import emu.nebula.data.ResourceType;
|
||||
import emu.nebula.game.quest.QuestData;
|
||||
import emu.nebula.game.quest.QuestHelper;
|
||||
import emu.nebula.game.quest.QuestType;
|
||||
import emu.nebula.game.quest.QuestHelper.QuestParams;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@ResourceType(name = "BattlePassQuest.json")
|
||||
public class BattlePassQuestDef extends BaseDef implements QuestData {
|
||||
private int Id;
|
||||
private int Type;
|
||||
private int Exp;
|
||||
|
||||
private transient int questType;
|
||||
private transient QuestParams params;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return Id;
|
||||
}
|
||||
|
||||
public boolean isDaily() {
|
||||
return this.Type == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCompleteCond() {
|
||||
return params.getCompleteCond();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getCompleteCondParams() {
|
||||
return params.getCompleteCondParams();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
this.questType = this.isDaily() ? QuestType.BattlePassDaily : QuestType.BattlePassWeekly;
|
||||
this.params = QuestHelper.getBattlePassQuestParams().getOrDefault(this.getId(), QuestHelper.DEFAULT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package emu.nebula.data.resources;
|
||||
|
||||
import emu.nebula.data.BaseDef;
|
||||
import emu.nebula.data.ResourceType;
|
||||
import emu.nebula.game.inventory.ItemParamMap;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@ResourceType(name = "BattlePassReward.json")
|
||||
public class BattlePassRewardDef extends BaseDef {
|
||||
private int ID;
|
||||
private int Level;
|
||||
|
||||
private int Tid1;
|
||||
private int Qty1;
|
||||
private int Tid2;
|
||||
private int Qty2;
|
||||
private int Tid3;
|
||||
private int Qty3;
|
||||
|
||||
private transient ItemParamMap basicRewards;
|
||||
private transient ItemParamMap premiumRewards;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return (ID << 16) + Level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
this.basicRewards = new ItemParamMap();
|
||||
this.premiumRewards = new ItemParamMap();
|
||||
|
||||
if (this.Tid1 > 0) {
|
||||
this.basicRewards.add(this.Tid1, this.Qty1);
|
||||
}
|
||||
|
||||
if (this.Tid2 > 0) {
|
||||
this.premiumRewards.add(this.Tid2, this.Qty2);
|
||||
}
|
||||
if (this.Tid3 > 0) {
|
||||
this.premiumRewards.add(this.Tid3, this.Qty3);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,13 @@ import java.util.Arrays;
|
||||
|
||||
import emu.nebula.data.BaseDef;
|
||||
import emu.nebula.data.ResourceType;
|
||||
import emu.nebula.game.quest.QuestData;
|
||||
import emu.nebula.game.quest.QuestType;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@ResourceType(name = "DailyQuest.json")
|
||||
public class DailyQuestDef extends BaseDef {
|
||||
public class DailyQuestDef extends BaseDef implements QuestData {
|
||||
private int Id;
|
||||
private boolean Apear;
|
||||
private int Active;
|
||||
@@ -26,6 +28,11 @@ public class DailyQuestDef extends BaseDef {
|
||||
return Id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getQuestType() {
|
||||
return QuestType.Daily;
|
||||
}
|
||||
|
||||
public int[] getCompleteCondParams() {
|
||||
return this.condParams;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ public class AgentManager extends PlayerManager implements GameDatabaseObject {
|
||||
this.getAgents().put(agent.getId(), agent);
|
||||
|
||||
// Quest
|
||||
this.getPlayer().getQuestManager().triggerQuest(QuestCondType.AgentApplyTotal, 1);
|
||||
this.getPlayer().triggerQuest(QuestCondType.AgentApplyTotal, 1);
|
||||
|
||||
// Success
|
||||
return agent;
|
||||
@@ -153,6 +153,9 @@ public class AgentManager extends PlayerManager implements GameDatabaseObject {
|
||||
// Save to database
|
||||
this.save();
|
||||
|
||||
// Quest
|
||||
this.getPlayer().triggerQuest(QuestCondType.AgentFinishTotal, list.size());
|
||||
|
||||
// Success
|
||||
return change.setSuccess(true);
|
||||
}
|
||||
|
||||
339
src/main/java/emu/nebula/game/battlepass/BattlePass.java
Normal file
339
src/main/java/emu/nebula/game/battlepass/BattlePass.java
Normal file
@@ -0,0 +1,339 @@
|
||||
package emu.nebula.game.battlepass;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import dev.morphia.annotations.Entity;
|
||||
import dev.morphia.annotations.Id;
|
||||
|
||||
import emu.nebula.GameConstants;
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.data.GameData;
|
||||
import emu.nebula.data.resources.BattlePassRewardDef;
|
||||
import emu.nebula.database.GameDatabaseObject;
|
||||
import emu.nebula.game.inventory.ItemParamMap;
|
||||
import emu.nebula.game.player.Player;
|
||||
import emu.nebula.game.player.PlayerChangeInfo;
|
||||
import emu.nebula.game.quest.GameQuest;
|
||||
import emu.nebula.game.quest.QuestCondType;
|
||||
import emu.nebula.game.quest.QuestType;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.BattlePassInfoOuterClass.BattlePassInfo;
|
||||
import emu.nebula.util.Bitset;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Entity(value = "battlepass", useDiscriminator = false)
|
||||
public class BattlePass implements GameDatabaseObject {
|
||||
@Id
|
||||
private int uid;
|
||||
private transient BattlePassManager manager;
|
||||
|
||||
private int battlePassId;
|
||||
private int mode;
|
||||
private int level;
|
||||
private int exp;
|
||||
private int expWeek;
|
||||
|
||||
private Bitset basicReward;
|
||||
private Bitset premiumReward;
|
||||
|
||||
private Map<Integer, GameQuest> quests;
|
||||
|
||||
@Deprecated // Morphia only
|
||||
public BattlePass() {
|
||||
|
||||
}
|
||||
|
||||
public BattlePass(BattlePassManager manager) {
|
||||
this.uid = manager.getPlayerUid();
|
||||
this.manager = manager;
|
||||
this.battlePassId = GameConstants.BATTLE_PASS_ID;
|
||||
this.basicReward = new Bitset();
|
||||
this.premiumReward = new Bitset();
|
||||
|
||||
// Setup battle pass quests
|
||||
this.quests = new HashMap<>();
|
||||
for (var data : GameData.getBattlePassQuestDataTable()) {
|
||||
this.quests.put(data.getId(), new GameQuest(data));
|
||||
}
|
||||
|
||||
// Save to database
|
||||
this.save();
|
||||
}
|
||||
|
||||
public void setManager(BattlePassManager manager) {
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
public Player getPlayer() {
|
||||
return manager.getPlayer();
|
||||
}
|
||||
|
||||
public boolean isPremium() {
|
||||
return this.mode > 0;
|
||||
}
|
||||
|
||||
private BattlePassRewardDef getRewardData(int level) {
|
||||
return GameData.getBattlePassRewardDataTable().get((this.getBattlePassId() << 16) + level);
|
||||
}
|
||||
|
||||
public int getMaxExp() {
|
||||
var data = GameData.getBattlePassLevelDataTable().get(this.getLevel() + 1);
|
||||
return data != null ? data.getExp() : 0;
|
||||
}
|
||||
|
||||
public void addExp(int amount) {
|
||||
// Setup
|
||||
int expRequired = this.getMaxExp();
|
||||
|
||||
// Add exp
|
||||
this.exp += amount;
|
||||
|
||||
// Check for level ups
|
||||
while (this.exp >= expRequired && expRequired > 0) {
|
||||
this.level += 1;
|
||||
this.exp -= expRequired;
|
||||
|
||||
expRequired = this.getMaxExp();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void resetDailyQuests() {
|
||||
// Reset daily quests
|
||||
for (var data : GameData.getBattlePassQuestDataTable()) {
|
||||
// Get quest
|
||||
var quest = getQuests().computeIfAbsent(data.getId(), i -> new GameQuest(data));
|
||||
|
||||
// Don't reset weekly quests
|
||||
if (!data.isDaily()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Reset progress
|
||||
quest.resetProgress();
|
||||
|
||||
// Sync quest with player client
|
||||
this.syncQuest(quest);
|
||||
}
|
||||
|
||||
// Persist to database
|
||||
this.save();
|
||||
}
|
||||
|
||||
public synchronized void trigger(QuestCondType condition, int progress, int param) {
|
||||
for (var quest : getQuests().values()) {
|
||||
// Try to trigger quest
|
||||
boolean result = quest.trigger(condition, progress, param);
|
||||
|
||||
// Skip if quest progress wasn't changed
|
||||
if (!result) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Sync quest with player client
|
||||
this.syncQuest(quest);
|
||||
|
||||
// Update in database
|
||||
Nebula.getGameDatabase().update(this, this.getUid(), "quests." + quest.getId(), quest);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update this quest on the player client
|
||||
*/
|
||||
private void syncQuest(GameQuest quest) {
|
||||
if (!getPlayer().hasSession()) {
|
||||
return;
|
||||
}
|
||||
|
||||
getPlayer().addNextPackage(
|
||||
NetMsgId.quest_change_notify,
|
||||
quest.toProto()
|
||||
);
|
||||
}
|
||||
|
||||
public BattlePass receiveQuestReward(int questId) {
|
||||
// Get received quests
|
||||
var claimList = new ArrayList<GameQuest>();
|
||||
|
||||
if (questId > 0) {
|
||||
// Claim specific quest
|
||||
var quest = this.getQuests().get(questId);
|
||||
|
||||
if (quest != null && !quest.isClaimed()) {
|
||||
claimList.add(quest);
|
||||
}
|
||||
} else {
|
||||
// Claim all
|
||||
for (var quest : this.getQuests().values()) {
|
||||
if (!quest.isComplete() || quest.isClaimed()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
claimList.add(quest);
|
||||
}
|
||||
}
|
||||
|
||||
// Sanity check
|
||||
if (claimList.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Init exp
|
||||
int exp = 0;
|
||||
int expWeek = 0;
|
||||
|
||||
// Claim
|
||||
for (var quest : claimList) {
|
||||
// Get data
|
||||
var data = GameData.getBattlePassQuestDataTable().get(quest.getId());
|
||||
if (data == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set claimed
|
||||
quest.setClaimed(true);
|
||||
|
||||
// Add exp
|
||||
exp += data.getExp();
|
||||
|
||||
// Check if quest is weekly
|
||||
if (quest.getType() == QuestType.BattlePassWeekly) {
|
||||
expWeek += data.getExp();
|
||||
}
|
||||
}
|
||||
|
||||
// Add exp
|
||||
if (exp > 0) {
|
||||
this.addExp(exp);
|
||||
}
|
||||
|
||||
if (expWeek > 0) {
|
||||
this.expWeek += expWeek;
|
||||
}
|
||||
|
||||
// Save to database
|
||||
this.save();
|
||||
|
||||
// Success
|
||||
return this;
|
||||
}
|
||||
|
||||
public PlayerChangeInfo receiveReward(boolean premium, int levelId) {
|
||||
// Get bitset
|
||||
Bitset rewards = null;
|
||||
|
||||
if (premium) {
|
||||
rewards = this.getPremiumReward();
|
||||
} else {
|
||||
rewards = this.getBasicReward();
|
||||
}
|
||||
|
||||
// Make sure we haven't already claimed the reward
|
||||
if (rewards.isSet(levelId)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Set claimed
|
||||
rewards.setBit(levelId);
|
||||
|
||||
// Save to database
|
||||
this.save();
|
||||
|
||||
// Get reward data
|
||||
var data = this.getRewardData(levelId);
|
||||
if (data == null) {
|
||||
return new PlayerChangeInfo();
|
||||
}
|
||||
|
||||
// Add items
|
||||
if (premium) {
|
||||
return getPlayer().getInventory().addItems(data.getPremiumRewards());
|
||||
} else {
|
||||
return getPlayer().getInventory().addItems(data.getBasicRewards());
|
||||
}
|
||||
}
|
||||
|
||||
public PlayerChangeInfo receiveReward() {
|
||||
// Init rewards
|
||||
var rewards = new ItemParamMap();
|
||||
|
||||
// Get unclaimed rewards
|
||||
for (int i = 1; i <= this.getLevel(); i++) {
|
||||
// Cache reward data
|
||||
BattlePassRewardDef data = null;
|
||||
|
||||
// Basic reward
|
||||
if (!this.getBasicReward().isSet(i)) {
|
||||
// Set flag
|
||||
this.getBasicReward().setBit(i);
|
||||
|
||||
// Get reward data if we havent already
|
||||
if (data == null) {
|
||||
data = this.getRewardData(i);
|
||||
}
|
||||
|
||||
// Add basic rewards
|
||||
if (data != null) {
|
||||
rewards.add(data.getBasicRewards());
|
||||
}
|
||||
}
|
||||
|
||||
// Premium reward
|
||||
if (this.isPremium() && !this.getPremiumReward().isSet(i)) {
|
||||
// Set flag
|
||||
this.getPremiumReward().setBit(i);
|
||||
|
||||
// Get reward data if we havent already
|
||||
if (data == null) {
|
||||
data = this.getRewardData(i);
|
||||
}
|
||||
|
||||
// Add basic rewards
|
||||
if (data != null) {
|
||||
rewards.add(data.getPremiumRewards());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save if we have any rewards to add
|
||||
if (rewards.size() > 0) {
|
||||
this.save();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Add rewards
|
||||
return getPlayer().getInventory().addItems(rewards);
|
||||
}
|
||||
|
||||
// Proto
|
||||
|
||||
public BattlePassInfo toProto() {
|
||||
var proto = BattlePassInfo.newInstance()
|
||||
.setId(this.getBattlePassId())
|
||||
.setLevel(this.getLevel())
|
||||
.setMode(this.getMode())
|
||||
.setExp(this.getExp())
|
||||
.setExpThisWeek(this.getExpWeek())
|
||||
.setDeadline(Long.MAX_VALUE)
|
||||
.setBasicReward(this.getBasicReward().toByteArray())
|
||||
.setPremiumReward(this.getPremiumReward().toByteArray());
|
||||
|
||||
var daily = proto.getMutableDailyQuests();
|
||||
var weekly = proto.getMutableWeeklyQuests();
|
||||
|
||||
for (var quest : this.getQuests().values()) {
|
||||
if (quest.getType() == QuestType.BattlePassDaily) {
|
||||
daily.addList(quest.toProto());
|
||||
} else if (quest.getType() == QuestType.BattlePassWeekly) {
|
||||
weekly.addList(quest.toProto());
|
||||
}
|
||||
}
|
||||
|
||||
return proto;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package emu.nebula.game.battlepass;
|
||||
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.game.player.Player;
|
||||
import emu.nebula.game.player.PlayerManager;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class BattlePassManager extends PlayerManager {
|
||||
private BattlePass battlePass;
|
||||
|
||||
public BattlePassManager(Player player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
// Database
|
||||
|
||||
public void loadFromDatabase() {
|
||||
this.battlePass = Nebula.getGameDatabase().getObjectByUid(BattlePass.class, getPlayer().getUid());
|
||||
|
||||
if (this.battlePass == null) {
|
||||
this.battlePass = new BattlePass(this);
|
||||
} else {
|
||||
this.battlePass.setManager(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -153,7 +153,7 @@ public class Character implements GameDatabaseObject {
|
||||
// Check if we leveled up
|
||||
if (this.level > oldLevel) {
|
||||
// Trigger quest
|
||||
this.getPlayer().getQuestManager().triggerQuest(QuestCondType.CharacterUpTotal, this.level - oldLevel);
|
||||
this.getPlayer().triggerQuest(QuestCondType.CharacterUpTotal, this.level - oldLevel);
|
||||
}
|
||||
|
||||
// Save to database
|
||||
|
||||
@@ -133,7 +133,7 @@ public class GameDisc implements GameDatabaseObject {
|
||||
// Check if we leveled up
|
||||
if (this.level > oldLevel) {
|
||||
// Trigger quest
|
||||
this.getPlayer().getQuestManager().triggerQuest(QuestCondType.DiscStrengthenTotal, this.level - oldLevel);
|
||||
this.getPlayer().triggerQuest(QuestCondType.DiscStrengthenTotal, this.level - oldLevel);
|
||||
}
|
||||
|
||||
// Save to database
|
||||
|
||||
@@ -63,8 +63,8 @@ public class InstanceManager extends PlayerManager {
|
||||
this.getProgress().saveInstanceLog(log, logName, data.getId(), star);
|
||||
|
||||
// Quest triggers
|
||||
this.getPlayer().getQuestManager().triggerQuest(questCondition, 1);
|
||||
this.getPlayer().getQuestManager().triggerQuest(QuestCondType.BattleTotal, 1);
|
||||
this.getPlayer().triggerQuest(questCondition, 1);
|
||||
this.getPlayer().triggerQuest(QuestCondType.BattleTotal, 1);
|
||||
}
|
||||
|
||||
// Set extra data
|
||||
@@ -131,8 +131,8 @@ public class InstanceManager extends PlayerManager {
|
||||
change.setExtraData(list);
|
||||
|
||||
// Quest triggers
|
||||
this.getPlayer().getQuestManager().triggerQuest(questCondition, count);
|
||||
this.getPlayer().getQuestManager().triggerQuest(QuestCondType.BattleTotal, count);
|
||||
this.getPlayer().triggerQuest(questCondition, count);
|
||||
this.getPlayer().triggerQuest(QuestCondType.BattleTotal, count);
|
||||
|
||||
// Success
|
||||
return change.setSuccess(true);
|
||||
|
||||
@@ -9,6 +9,7 @@ import emu.nebula.Nebula;
|
||||
import emu.nebula.data.GameData;
|
||||
import emu.nebula.database.GameDatabaseObject;
|
||||
import emu.nebula.game.player.PlayerManager;
|
||||
import emu.nebula.game.quest.QuestCondType;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.Notify.Skin;
|
||||
import emu.nebula.proto.Public.Honor;
|
||||
@@ -444,6 +445,13 @@ public class Inventory extends PlayerManager implements GameDatabaseObject {
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger quest
|
||||
if (amount > 0) {
|
||||
this.getPlayer().triggerQuest(QuestCondType.ItemsAdd, amount, id);
|
||||
} else {
|
||||
this.getPlayer().triggerQuest(QuestCondType.ItemsDeplete, Math.abs(amount), id);
|
||||
}
|
||||
|
||||
//
|
||||
return change;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import emu.nebula.data.GameData;
|
||||
import emu.nebula.database.GameDatabaseObject;
|
||||
import emu.nebula.game.account.Account;
|
||||
import emu.nebula.game.agent.AgentManager;
|
||||
import emu.nebula.game.battlepass.BattlePassManager;
|
||||
import emu.nebula.game.character.CharacterStorage;
|
||||
import emu.nebula.game.formation.FormationManager;
|
||||
import emu.nebula.game.gacha.GachaManager;
|
||||
@@ -77,6 +78,7 @@ public class Player implements GameDatabaseObject {
|
||||
// Managers
|
||||
private final transient CharacterStorage characters;
|
||||
private final transient GachaManager gachaManager;
|
||||
private final transient BattlePassManager battlePassManager;
|
||||
private final transient StarTowerManager starTowerManager;
|
||||
private final transient InstanceManager instanceManager;
|
||||
private final transient InfinityTowerManager infinityTowerManager;
|
||||
@@ -100,6 +102,7 @@ public class Player implements GameDatabaseObject {
|
||||
// Init player managers
|
||||
this.characters = new CharacterStorage(this);
|
||||
this.gachaManager = new GachaManager(this);
|
||||
this.battlePassManager = new BattlePassManager(this);
|
||||
this.starTowerManager = new StarTowerManager(this);
|
||||
this.instanceManager = new InstanceManager(this);
|
||||
this.infinityTowerManager = new InfinityTowerManager(this);
|
||||
@@ -475,7 +478,7 @@ public class Player implements GameDatabaseObject {
|
||||
change = modifyEnergy(-amount, change);
|
||||
|
||||
// Trigger quest
|
||||
this.getQuestManager().triggerQuest(QuestCondType.EnergyDeplete, amount);
|
||||
this.triggerQuest(QuestCondType.EnergyDeplete, amount);
|
||||
|
||||
// Complete
|
||||
return change;
|
||||
@@ -535,6 +538,18 @@ public class Player implements GameDatabaseObject {
|
||||
public void resetDailies() {
|
||||
// Reset daily quests
|
||||
this.getQuestManager().resetDailyQuests();
|
||||
this.getBattlePassManager().getBattlePass().resetDailyQuests();
|
||||
}
|
||||
|
||||
// Trigger quests
|
||||
|
||||
public void triggerQuest(QuestCondType condition, int progress) {
|
||||
this.triggerQuest(condition, progress, 0);
|
||||
}
|
||||
|
||||
public void triggerQuest(QuestCondType condition, int progress, int param) {
|
||||
this.getQuestManager().trigger(condition, progress, param);
|
||||
this.getBattlePassManager().getBattlePass().trigger(condition, progress, param);
|
||||
}
|
||||
|
||||
// Login
|
||||
@@ -562,6 +577,7 @@ public class Player implements GameDatabaseObject {
|
||||
// Load from database
|
||||
this.getCharacters().loadFromDatabase();
|
||||
this.getStarTowerManager().loadFromDatabase();
|
||||
this.getBattlePassManager().loadFromDatabase();
|
||||
|
||||
// Load inventory before referenced classes
|
||||
if (this.inventory == null) {
|
||||
@@ -589,7 +605,7 @@ public class Player implements GameDatabaseObject {
|
||||
this.checkResetDailies();
|
||||
|
||||
// Trigger quest login
|
||||
this.getQuestManager().triggerQuest(QuestCondType.LoginTotal, 1);
|
||||
this.triggerQuest(QuestCondType.LoginTotal, 1);
|
||||
}
|
||||
|
||||
// Next packages
|
||||
@@ -684,7 +700,9 @@ public class Player implements GameDatabaseObject {
|
||||
state.getMutableMail()
|
||||
.setNew(this.getMailbox().hasNewMail());
|
||||
|
||||
state.getMutableBattlePass();
|
||||
state.getMutableBattlePass()
|
||||
.setState(1);
|
||||
|
||||
state.getMutableFriendEnergy();
|
||||
state.getMutableMallPackage();
|
||||
state.getMutableAchievement();
|
||||
@@ -732,17 +750,7 @@ public class Player implements GameDatabaseObject {
|
||||
}
|
||||
|
||||
// Quests
|
||||
var quests = proto.getMutableQuests();
|
||||
for (var quest : this.getQuestManager().getQuests().values()) {
|
||||
quests.addList(quest.toProto());
|
||||
}
|
||||
|
||||
for (int id : this.getQuestManager().getClaimedActiveIds()) {
|
||||
proto.addDailyActiveIds(id);
|
||||
}
|
||||
|
||||
state.getMutableWorldClassReward()
|
||||
.setFlag(this.getQuestManager().getLevelRewards().toBigEndianByteArray());
|
||||
this.getQuestManager().encodeProto(proto);
|
||||
|
||||
// Add dictionary tabs
|
||||
for (var dictionaryData : GameData.getDictionaryTabDataTable()) {
|
||||
@@ -761,7 +769,7 @@ public class Player implements GameDatabaseObject {
|
||||
}
|
||||
|
||||
// Add progress
|
||||
this.getProgress().toProto(proto);
|
||||
this.getProgress().encodeProto(proto);
|
||||
|
||||
// Handbook
|
||||
proto.addHandbook(this.getCharacters().getCharacterHandbook());
|
||||
|
||||
@@ -108,7 +108,7 @@ public class PlayerProgress extends PlayerManager implements GameDatabaseObject
|
||||
|
||||
// Proto
|
||||
|
||||
public void toProto(PlayerInfo proto) {
|
||||
public void encodeProto(PlayerInfo proto) {
|
||||
// Check if we want to unlock all instances
|
||||
boolean unlockAll = Nebula.getConfig().getServerOptions().unlockInstances;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package emu.nebula.game.quest;
|
||||
|
||||
import dev.morphia.annotations.Entity;
|
||||
import emu.nebula.data.resources.DailyQuestDef;
|
||||
import emu.nebula.proto.Public.Quest;
|
||||
import emu.nebula.proto.Public.QuestProgress;
|
||||
import lombok.Getter;
|
||||
@@ -13,6 +12,7 @@ public class GameQuest {
|
||||
private int id;
|
||||
private int type;
|
||||
private int cond;
|
||||
private int param;
|
||||
|
||||
private int curProgress;
|
||||
private int maxProgress;
|
||||
@@ -25,11 +25,15 @@ public class GameQuest {
|
||||
|
||||
}
|
||||
|
||||
public GameQuest(DailyQuestDef data) {
|
||||
public GameQuest(QuestData data) {
|
||||
this.id = data.getId();
|
||||
this.type = QuestType.Daily;
|
||||
this.type = data.getQuestType();
|
||||
this.cond = data.getCompleteCond();
|
||||
this.maxProgress = data.getCompleteCondParams()[0];
|
||||
|
||||
if (data.getCompleteCondParams().length >= 2) {
|
||||
this.param = data.getCompleteCondParams()[1];
|
||||
}
|
||||
}
|
||||
|
||||
public void resetProgress() {
|
||||
@@ -51,7 +55,7 @@ public class GameQuest {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean trigger(QuestCondType condition, int param) {
|
||||
public boolean trigger(QuestCondType condition, int progress, int param) {
|
||||
// Sanity check
|
||||
if (this.isComplete()) {
|
||||
return false;
|
||||
@@ -62,8 +66,13 @@ public class GameQuest {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check quest param
|
||||
if (this.param != 0 && param != this.param) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get new progress
|
||||
int newProgress = Math.min(this.curProgress + param, this.maxProgress);
|
||||
int newProgress = Math.min(this.curProgress + progress, this.maxProgress);
|
||||
|
||||
// Set
|
||||
if (this.curProgress != newProgress) {
|
||||
|
||||
13
src/main/java/emu/nebula/game/quest/QuestData.java
Normal file
13
src/main/java/emu/nebula/game/quest/QuestData.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package emu.nebula.game.quest;
|
||||
|
||||
public interface QuestData {
|
||||
|
||||
public int getId();
|
||||
|
||||
public int getQuestType();
|
||||
|
||||
public int getCompleteCond();
|
||||
|
||||
public int[] getCompleteCondParams();
|
||||
|
||||
}
|
||||
47
src/main/java/emu/nebula/game/quest/QuestHelper.java
Normal file
47
src/main/java/emu/nebula/game/quest/QuestHelper.java
Normal file
@@ -0,0 +1,47 @@
|
||||
package emu.nebula.game.quest;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.Getter;
|
||||
|
||||
// Because some quests in the data files do not have condition params, we will hardcode them here
|
||||
public class QuestHelper {
|
||||
public static final QuestParams DEFAULT = new QuestParams(0, new int[1]);
|
||||
|
||||
@Getter
|
||||
private static final Int2ObjectMap<QuestParams> battlePassQuestParams = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
static {
|
||||
battlePassQuestParams.put(1001, new QuestParams(QuestCondType.LoginTotal, 1));
|
||||
battlePassQuestParams.put(1002, new QuestParams(QuestCondType.EnergyDeplete, 160));
|
||||
battlePassQuestParams.put(1003, new QuestParams(QuestCondType.BattleTotal, 6));
|
||||
battlePassQuestParams.put(1004, new QuestParams(QuestCondType.QuestWithSpecificType, 5, QuestType.Daily));
|
||||
battlePassQuestParams.put(2001, new QuestParams(QuestCondType.TowerEnterFloor, 1));
|
||||
battlePassQuestParams.put(2002, new QuestParams(QuestCondType.WeekBoosClearSpecificDifficultyAndTotal, 3));
|
||||
battlePassQuestParams.put(2003, new QuestParams(QuestCondType.BattleTotal, 20));
|
||||
battlePassQuestParams.put(2004, new QuestParams(QuestCondType.LoginTotal, 5));
|
||||
battlePassQuestParams.put(2005, new QuestParams(QuestCondType.AgentFinishTotal, 3));
|
||||
battlePassQuestParams.put(2006, new QuestParams(QuestCondType.ItemsDeplete, 100000, 1));
|
||||
battlePassQuestParams.put(2007, new QuestParams(QuestCondType.GiftGiveTotal, 5));
|
||||
battlePassQuestParams.put(2008, new QuestParams(QuestCondType.EnergyDeplete, 1200));
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class QuestParams {
|
||||
public int completeCond;
|
||||
public int[] completeCondParams;
|
||||
|
||||
public QuestParams(int cond, int[] params) {
|
||||
this.completeCond = cond;
|
||||
this.completeCondParams = params;
|
||||
}
|
||||
|
||||
public QuestParams(int cond, int param) {
|
||||
this(cond, new int[] {param});
|
||||
}
|
||||
|
||||
public QuestParams(QuestCondType cond, int... params) {
|
||||
this(cond.getValue(), params);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,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.WorldClassDef;
|
||||
@@ -15,10 +16,13 @@ import emu.nebula.game.player.Player;
|
||||
import emu.nebula.game.player.PlayerChangeInfo;
|
||||
import emu.nebula.game.player.PlayerManager;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.PlayerData.PlayerInfo;
|
||||
import emu.nebula.util.Bitset;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
|
||||
@@ -90,10 +94,10 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
|
||||
this.save();
|
||||
}
|
||||
|
||||
public synchronized void triggerQuest(QuestCondType condition, int param) {
|
||||
public synchronized void trigger(QuestCondType condition, int progress, int param) {
|
||||
for (var quest : getQuests().values()) {
|
||||
// Try to trigger quest
|
||||
boolean result = quest.trigger(condition, param);
|
||||
boolean result = quest.trigger(condition, progress, param);
|
||||
|
||||
// Skip if quest progress wasn't changed
|
||||
if (!result) {
|
||||
@@ -108,6 +112,21 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update this quest on the player client
|
||||
*/
|
||||
private void syncQuest(GameQuest quest) {
|
||||
if (!getPlayer().hasSession()) {
|
||||
return;
|
||||
}
|
||||
|
||||
getPlayer().addNextPackage(
|
||||
NetMsgId.quest_change_notify,
|
||||
quest.toProto()
|
||||
);
|
||||
}
|
||||
|
||||
public PlayerChangeInfo receiveQuestReward(int questId) {
|
||||
// Get received quests
|
||||
var claimList = new ArrayList<GameQuest>();
|
||||
@@ -160,6 +179,9 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
|
||||
// Update in database
|
||||
Nebula.getGameDatabase().update(this, this.getUid(), "activity", this.getActivity());
|
||||
|
||||
// Trigger quest
|
||||
this.getPlayer().triggerQuest(QuestCondType.QuestWithSpecificType, claimList.size(), QuestType.Daily);
|
||||
|
||||
// Success
|
||||
return change.setSuccess(true);
|
||||
}
|
||||
@@ -250,20 +272,6 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
|
||||
return change.setSuccess(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update this quest on the player client
|
||||
*/
|
||||
private void syncQuest(GameQuest quest) {
|
||||
if (!getPlayer().hasSession()) {
|
||||
return;
|
||||
}
|
||||
|
||||
getPlayer().addNextPackage(
|
||||
NetMsgId.quest_change_notify,
|
||||
quest.toProto()
|
||||
);
|
||||
}
|
||||
|
||||
// Daily reward
|
||||
|
||||
public PlayerChangeInfo claimDailyReward() {
|
||||
@@ -281,9 +289,29 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
|
||||
Nebula.getGameDatabase().update(this, this.getUid(), "hasDailyReward", this.hasDailyReward);
|
||||
|
||||
// Trigger quest
|
||||
this.triggerQuest(QuestCondType.DailyShopReceiveShopTotal, 1);
|
||||
this.getPlayer().triggerQuest(QuestCondType.DailyShopReceiveShopTotal, 1);
|
||||
|
||||
// Success
|
||||
return change.setSuccess(true);
|
||||
}
|
||||
|
||||
// Serialization
|
||||
|
||||
public void encodeProto(PlayerInfo proto) {
|
||||
var quests = proto.getMutableQuests();
|
||||
|
||||
for (var quest : this.getQuests().values()) {
|
||||
quests.addList(quest.toProto());
|
||||
}
|
||||
|
||||
for (int id : this.getClaimedActiveIds()) {
|
||||
proto.addDailyActiveIds(id);
|
||||
}
|
||||
|
||||
proto.getMutableState()
|
||||
.getMutableWorldClassReward()
|
||||
.setFlag(this.getLevelRewards().toBigEndianByteArray());
|
||||
|
||||
proto.setTourGuideQuestGroup(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public class StarTowerManager extends PlayerManager {
|
||||
this.game = new StarTowerGame(this, data, formation, req);
|
||||
|
||||
// Trigger quest
|
||||
this.getPlayer().getQuestManager().triggerQuest(QuestCondType.TowerEnterFloor, 1);
|
||||
this.getPlayer().triggerQuest(QuestCondType.TowerEnterFloor, 1);
|
||||
|
||||
// Success
|
||||
return this.game;
|
||||
|
||||
@@ -10,7 +10,11 @@ public class HandlerBattlePassInfoReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
return session.encodeMsg(NetMsgId.battle_pass_info_failed_ack);
|
||||
// Get battle pass proto
|
||||
var info = session.getPlayer().getBattlePassManager().getBattlePass().toProto();
|
||||
|
||||
// Encode and send
|
||||
return session.encodeMsg(NetMsgId.battle_pass_info_succeed_ack, info);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.BattlePassQuestRewardReceive.BattlePassQuestRewardResp;
|
||||
import emu.nebula.proto.Public.UI32;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.battle_pass_quest_reward_receive_req)
|
||||
public class HandlerBattlePassQuestRewardReceiveReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Parse req
|
||||
var req = UI32.parseFrom(message);
|
||||
|
||||
// Recieve reward
|
||||
var battlePass = session.getPlayer().getBattlePassManager().getBattlePass().receiveQuestReward(req.getValue());
|
||||
|
||||
if (battlePass == null) {
|
||||
return session.encodeMsg(NetMsgId.battle_pass_quest_reward_receive_failed_ack);
|
||||
}
|
||||
|
||||
// Build response
|
||||
var rsp = BattlePassQuestRewardResp.newInstance()
|
||||
.setLevel(battlePass.getLevel())
|
||||
.setExp(battlePass.getExp())
|
||||
.setExpThisWeek(battlePass.getExpWeek());
|
||||
|
||||
// Encode and send
|
||||
return session.encodeMsg(NetMsgId.battle_pass_quest_reward_receive_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.BattlePassRewardReceive.BattlePassRewardReceiveReq;
|
||||
import emu.nebula.proto.BattlePassRewardReceive.BattlePassRewardReceiveResp;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.game.player.PlayerChangeInfo;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.battle_pass_reward_receive_req)
|
||||
public class HandlerBattlePassRewardReceiveReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Parse request
|
||||
var req = BattlePassRewardReceiveReq.parseFrom(message);
|
||||
|
||||
// Setup variables
|
||||
PlayerChangeInfo change = null;
|
||||
var battlePass = session.getPlayer().getBattlePassManager().getBattlePass();
|
||||
|
||||
// Claim
|
||||
if (req.getPremium() > 0) {
|
||||
change = session.getPlayer().getBattlePassManager().getBattlePass().receiveReward(true, req.getPremium());
|
||||
} else if (req.getBasic() > 0) {
|
||||
change = session.getPlayer().getBattlePassManager().getBattlePass().receiveReward(false, req.getBasic());
|
||||
} else if (req.hasAll()) {
|
||||
change = session.getPlayer().getBattlePassManager().getBattlePass().receiveReward();
|
||||
}
|
||||
|
||||
// Check
|
||||
if (change == null) {
|
||||
return session.encodeMsg(NetMsgId.battle_pass_reward_receive_failed_ack);
|
||||
}
|
||||
|
||||
// Build response
|
||||
var rsp = BattlePassRewardReceiveResp.newInstance()
|
||||
.setBasicReward(battlePass.getBasicReward().toByteArray())
|
||||
.setPremiumReward(battlePass.getPremiumReward().toByteArray())
|
||||
.setChange(change.toProto());
|
||||
|
||||
// Encode and send
|
||||
return session.encodeMsg(NetMsgId.battle_pass_reward_receive_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,7 +13,7 @@ public class HandlerClientEventReportReq extends NetHandler {
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Interact
|
||||
session.getPlayer().getQuestManager().triggerQuest(QuestCondType.ClientReport, 1);
|
||||
session.getPlayer().triggerQuest(QuestCondType.ClientReport, 1);
|
||||
|
||||
// Encode response
|
||||
return session.encodeMsg(NetMsgId.client_event_report_succeed_ack, Nil.newInstance());
|
||||
|
||||
Reference in New Issue
Block a user