Implement monolith npc affinity

This commit is contained in:
Melledy committed 2026-10-24 03:14:16 -07:00
1 parent 9c0c8b984e
commit e262079d41
15 files changed
+718 -11

No files matched your search

@@ -123,6 +123,7 @@ public class GameData {
@Getter private static DataTable<StarTowerQuestDef> StarTowerQuestDataTable = new DataTable<>();
@Getter private static DataTable<StarTowerBuildRankDef> StarTowerBuildRankDataTable = new DataTable<>();
@Getter private static DataTable<StarTowerBookPotentialRewardDef> StarTowerBookPotentialRewardDataTable = new DataTable<>();
@Getter private static DataTable<StarTowerBookEventRewardDef> StarTowerBookEventRewardDataTable = new DataTable<>();
@Getter private static DataTable<TowerVitaOptionDef> TowerVitaOptionDataTable = new DataTable<>();
@Getter private static DataTable<SubNoteSkillPromoteGroupDef> SubNoteSkillPromoteGroupDataTable = new DataTable<>();
@@ -133,6 +134,11 @@ public class GameData {
@Getter private static DataTable<StarTowerBookFateCardQuestDef> StarTowerBookFateCardQuestDataTable = new DataTable<>();
@Getter private static DataTable<StarTowerBookFateCardDef> StarTowerBookFateCardDataTable = new DataTable<>();
@Getter private static DataTable<FateCardDef> FateCardDataTable = new DataTable<>();
// Star Tower: NPC affinity
@Getter private static DataTable<StarTowerNpcDef> StarTowerNpcDataTable = new DataTable<>();
@Getter private static DataTable<NpcAffinityGroupDef> NpcAffinityGroupDataTable = new DataTable<>();
@Getter private static DataTable<NpcAffinityPlotDef> NpcAffinityPlotDataTable = new DataTable<>();
// ===== Infinity Tower =====
@Getter private static DataTable<InfinityTowerLevelDef> InfinityTowerLevelDataTable = new DataTable<>();
@@ -0,0 +1,19 @@
package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "NPCAffinityGroup.json")
public class NpcAffinityGroupDef extends BaseDef {
private int Id;
private int Level;
private int AffinityValue;
private int AffinityGroupId;
@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 = "NPCAffinityPlot.json")
public class NpcAffinityPlotDef extends BaseDef {
private int Id;
private int NPCId;
private int AffinityLevel;
private int ItemId;
private int ItemQty;
@Override
public int getId() {
return Id;
}
}
@@ -0,0 +1,73 @@
package emu.nebula.data.resources;
import java.util.Arrays;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import emu.nebula.data.ResourceType.LoadPriority;
import emu.nebula.game.quest.QuestData;
import emu.nebula.game.quest.QuestType;
import lombok.Getter;
@Getter
@ResourceType(name = "StarTowerBookEventReward.json", loadPriority = LoadPriority.LOW)
public class StarTowerBookEventRewardDef extends BaseDef implements QuestData {
private int Id;
private int Type; // 1 = Character clear count, 2 = NPC affinity level
private int NPCId;
private int Sort;
private int CompleteCond;
private String CompleteCondParams;
private int ItemId;
private int ItemQty;
// Cached data
private transient int[] condParams;
@Override
public int getId() {
return this.Id;
}
@Override
public int getQuestType() {
return QuestType.TowerEvent;
}
@Override
public int getCompleteCond() {
return this.CompleteCond;
}
@Override
public int[] getCompleteCondParams() {
if (this.condParams == null) {
this.condParams = new int[] { 1, 0 };
}
return this.condParams;
}
@Override
public void onLoad() {
// Flip params
// The data stores params as [target id, required amount]
// while GameQuest expects [required amount, target id]
if (this.CompleteCondParams != null && !this.CompleteCondParams.isBlank()) {
var params = Arrays.stream(this.CompleteCondParams.replaceAll("[\\[\\] ]", "")
.split(","))
.filter(value -> !value.isEmpty())
.mapToInt(Integer::parseInt)
.toArray();
if (params.length >= 2) {
this.condParams = new int[] { params[1], params[0] };
}
}
if (this.condParams == null) {
this.condParams = new int[] { 1, 0 };
}
}
}
@@ -0,0 +1,17 @@
package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import lombok.Getter;
@Getter
@ResourceType(name = "StarTowerNPC.json")
public class StarTowerNpcDef extends BaseDef {
private int Id;
private int AffinityGroupId;
@Override
public int getId() {
return Id;
}
}
@@ -6,10 +6,12 @@ import java.util.Map;
import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Id;
import dev.morphia.annotations.PostLoad;
import emu.nebula.Nebula;
import emu.nebula.data.GameData;
import emu.nebula.data.resources.InfinityTowerLevelDef;
import emu.nebula.database.GameDatabaseObject;
import emu.nebula.game.tower.StarTowerNpcData;
import emu.nebula.game.tower.StarTowerVitaData;
import emu.nebula.game.tutorial.TutorialLevelLog;
import emu.nebula.game.vampire.VampireSurvivorLog;
@@ -21,10 +23,12 @@ import emu.nebula.proto.Public.SkillInstance;
import emu.nebula.proto.Public.VampireSurvivorLevel;
import emu.nebula.proto.Public.WeekBossLevel;
import emu.nebula.util.Bitset;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import lombok.Getter;
@Getter
@@ -38,6 +42,7 @@ public class PlayerProgress extends PlayerManager implements GameDatabaseObject
private int[] starTowerGrowth;
private int towerTickets;
private StarTowerVitaData towerVitaData;
private Map<Integer, StarTowerNpcData> towerNpcs;
// Instances
private Int2IntMap dailyInstanceLog;
@@ -96,6 +101,9 @@ public class PlayerProgress extends PlayerManager implements GameDatabaseObject
// Star Tower Vita
this.towerVitaData = new StarTowerVitaData(this);
// Star Tower NPCs
this.towerNpcs = new HashMap<>();
// Save to database
this.save();
}
@@ -129,6 +137,17 @@ public class PlayerProgress extends PlayerManager implements GameDatabaseObject
// Success
return true;
}
public StarTowerNpcData getStarTowerNpcById(int npcId) {
var npc = this.getTowerNpcs().get(npcId);
if (npc == null) {
npc = new StarTowerNpcData(this.getPlayer(), npcId);
this.getTowerNpcs().put(npcId, npc);
}
return npc;
}
/**
* Returns the maximum amount of weekly tickets that a player can receive without hitting the limit
@@ -341,6 +360,12 @@ public class PlayerProgress extends PlayerManager implements GameDatabaseObject
this.towerVitaData.setPlayerProgress(this);
}
// Set star tower npc data
if (this.towerNpcs == null) {
this.towerNpcs = new HashMap<>();
shouldSave = true;
}
// Carry over infinity tower progress
if (this.infinityArenaLog != null) {
for (int levelId : this.infinityArenaLog.values()) {
@@ -366,4 +391,13 @@ public class PlayerProgress extends PlayerManager implements GameDatabaseObject
this.save();
}
}
@Override
public void onLoad() {
// Set player for all npcs
// This needs to be in onLoad because that is when PlayerProgress's player field is set
for (var npc : this.towerNpcs.values()) {
npc.setPlayer(this.getPlayer());
}
}
}
@@ -10,6 +10,7 @@ import dev.morphia.annotations.Id;
import emu.nebula.GameConstants;
import emu.nebula.Nebula;
import emu.nebula.data.GameData;
import emu.nebula.data.resources.StarTowerBookEventRewardDef;
import emu.nebula.data.resources.WorldClassDef;
import emu.nebula.database.GameDatabaseObject;
import emu.nebula.game.inventory.ItemParamMap;
@@ -61,6 +62,7 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
this.levelRewards = new Bitset();
this.initStarTowerQuests();
this.initStarTowerBookEventQuests();
this.resetDailyQuests(true);
@@ -97,6 +99,8 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
if (progress > 0) {
quest.setProgress(progress);
}
} else if (cond == QuestCondition.TowerBookWithSpecificEvent.getValue()) {
this.syncStarTowerBookEventCountQuest(quest);
}
}
@@ -249,11 +253,16 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
var quest = this.getList().get(data.getQuestKey());
if (quest == null) {
this.addQuest(new GameQuest(data));
quest = this.addQuest(new GameQuest(data));
changed = true;
} else if (quest.refreshData(data)) {
changed = true;
}
// Book collection quests can complete retroactively
if (this.syncStarTowerBookEventCountQuest(quest)) {
changed = true;
}
}
return changed;
@@ -292,6 +301,155 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
}
}
// Star Tower book events (anecdotes)
/**
* Returns the total number of anecdotes the player has collected.
*/
public synchronized int getClaimedStarTowerBookEventCount() {
int count = 0;
for (var quest : this.getQuests()) {
if (quest.getType() == QuestType.TowerEvent && quest.isClaimed()) {
count++;
}
}
return count;
}
/**
* Syncs the progress of Star Tower book collection quests.
*/
private boolean syncStarTowerBookEventCountQuest(GameQuest quest) {
if (quest.getCond() != QuestCondition.TowerBookWithSpecificEvent.getValue()) {
return false;
}
int progress = Math.min(this.getClaimedStarTowerBookEventCount(), quest.getMaxProgress());
if (progress <= quest.getCurProgress()) {
return false;
}
return quest.setProgress(progress);
}
/**
* Adds all Star Tower book event rewards as quests.
* Returns true if any quest was added or refreshed.
*/
public synchronized boolean initStarTowerBookEventQuests() {
boolean changed = false;
for (var data : GameData.getStarTowerBookEventRewardDataTable()) {
// Get existing quest
var quest = this.getList().get(data.getQuestKey());
if (quest == null) {
quest = this.addQuest(new GameQuest(data));
changed = true;
} else if (quest.refreshData(data)) {
changed = true;
}
// NPC affinity quests can complete retroactively
if (this.syncStarTowerBookEventQuest(quest, data)) {
changed = true;
}
}
return changed;
}
/**
* Syncs progress for book event quests that can be completed retroactively.
*/
private boolean syncStarTowerBookEventQuest(GameQuest quest, StarTowerBookEventRewardDef data) {
if (data.getCompleteCond() != QuestCondition.NpcAffinityWithSpecificLevel.getValue()) {
return false;
}
var npc = this.getPlayer().getProgress().getTowerNpcs().get(quest.getParam());
if (npc == null) {
return false;
}
int progress = Math.min(npc.getLevel(), quest.getMaxProgress());
if (progress <= quest.getCurProgress()) {
return false;
}
return quest.setProgress(progress);
}
public synchronized PlayerChangeInfo receiveStarTowerBookEventReward(int questId) {
// Get received quests
var claimList = new ArrayList<GameQuest>();
if (questId > 0) {
// Claim specific quest
var quest = this.getQuest(QuestType.TowerEvent, questId);
if (quest != null && quest.canClaim()) {
claimList.add(quest);
}
} else {
// Claim all
for (var quest : this.getQuests()) {
if (quest.getType() != QuestType.TowerEvent) {
continue;
}
if (!quest.canClaim()) {
continue;
}
claimList.add(quest);
}
}
// Sanity check
if (claimList.isEmpty()) {
return null;
}
// Create change info
var change = new PlayerChangeInfo();
var received = new IntArrayList();
// Claim
for (var quest : claimList) {
// Get data
var data = GameData.getStarTowerBookEventRewardDataTable().get(quest.getId());
if (data != null) {
// Add reward
this.getPlayer().getInventory().addItem(data.getItemId(), data.getItemQty(), change);
}
// Set claimed
quest.setClaimed(true);
// Add received id
received.add(quest.getId());
// Update in database
this.saveQuest(quest);
}
// Update Star Tower book collection quests
this.trigger(QuestCondition.TowerBookWithSpecificEvent.getValue(), claimList.size(), 0, 0);
// Set received ids as extra data
change.setExtraData(received);
// Success
return change.setSuccess(true);
}
public synchronized PlayerChangeInfo receiveStarTowerQuestReward(int questId) {
// Get received quests
var claimList = new ArrayList<GameQuest>();
@@ -340,7 +498,7 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
quest.setClaimed(true);
// Update in database
Nebula.getGameDatabase().update(this, this.getUid(), "list." + quest.getKey(), quest);
this.saveQuest(quest);
}
// Unlock newly available quests
@@ -420,7 +578,7 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
quest.setClaimed(true);
// Update in database
Nebula.getGameDatabase().update(this, this.getUid(), "list." + quest.getKey(), quest);
this.saveQuest(quest);
}
// Trigger quest
@@ -541,7 +699,7 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
quest.setClaimed(true);
// Update in database
Nebula.getGameDatabase().update(this, this.getUid(), "list." + quest.getKey(), quest);
this.saveQuest(quest);
}
// Trigger quest
@@ -705,6 +863,7 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
// 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();
this.initStarTowerBookEventQuests();
// Reset daily quests
this.resetDailyQuests(true);
@@ -713,9 +872,15 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
shouldSave = false;
} else {
// Add missing Star Tower quests and refresh their condition data
if (this.initStarTowerQuests()) {
boolean changed = this.initStarTowerQuests();
if (this.initStarTowerBookEventQuests()) {
changed = true;
}
if (changed) {
shouldSave = true;
}
}
}
// Save to database
@@ -71,6 +71,7 @@ public class StarTowerGame {
private int teamExp;
private int nextLevelExp;
private int charHp;
private int npcInteractions;
private int battleTime;
private int[] charIds;
private int[] discIds;
@@ -85,6 +86,9 @@ public class StarTowerGame {
private ItemParamMap potentials;
private IntSet secondarySkills;
// NPC
private ItemParamMap npcAffinity;
// Modifiers
private StarTowerModifiers modifiers;
@@ -167,6 +171,9 @@ public class StarTowerGame {
// Temp data to cache for rare potential count
this.rarePotentialCount = new ItemParamMap();
// Cached npc affinity map
this.npcAffinity = new ItemParamMap();
// Enter first room
this.enterNextRoom();
this.getRoom().setMapInfo(req);
@@ -258,6 +265,15 @@ public class StarTowerGame {
return Utils.randomElement(this.getCharIds());
}
public StarTowerNpcData getNpc(int npcId) {
return getPlayer().getProgress().getStarTowerNpcById(npcId);
}
public void onNpcAffinityIncrease(int npcId, int increase) {
this.npcInteractions++;
this.npcAffinity.add(npcId, increase);
}
public void setHp(int hp) {
this.charHp = hp;
}
@@ -855,7 +871,8 @@ public class StarTowerGame {
// Settle info
var settle = rsp.getMutableSettle()
.setTotalTime(this.getBattleTime())
.setBuild(this.getBuild().toProto());
.setBuild(this.getBuild().toProto())
.addAllReward(this.getNpcAffinityRewards());
// Set empty change info
settle.getMutableChange();
@@ -933,7 +950,7 @@ public class StarTowerGame {
.setId(this.getId())
.setCharHp(this.getCharHp())
.setTeamLevel(this.getTeamLevel())
.setNPCInteractions(0)
.setNPCInteractions(this.getNpcInteractions())
.setTotalTime(this.getBattleTime())
.setBuildId(this.getBuildId());
@@ -994,5 +1011,26 @@ public class StarTowerGame {
return proto;
}
public NPCAffinityLevelReward[] getNpcAffinityRewards() {
var list = new ArrayList<NPCAffinityLevelReward>();
for (var entry : this.npcAffinity) {
int npcId = entry.getIntKey();
int increase = entry.getIntValue();
var npc = this.getNpc(npcId);
var reward = NPCAffinityLevelReward.newInstance();
reward.getMutableChange()
.setNPCId(npcId)
.setAffinity(npc.getAffinity())
.setIncrease(increase);
list.add(reward);
}
return list.toArray(new NPCAffinityLevelReward[list.size()]);
}
}
@@ -1,5 +1,6 @@
package emu.nebula.game.tower;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
@@ -171,6 +172,42 @@ public class StarTowerManager extends PlayerManager {
return change;
}
// NPC affinities
public Collection<StarTowerNpcData> getNpcAffinities() {
return this.getProgress().getTowerNpcs().values();
}
public PlayerChangeInfo receiveNpcAffinityPlotReward(int plotId) {
// Get plot data
var plot = GameData.getNpcAffinityPlotDataTable().get(plotId);
if (plot == null) {
return null;
}
// Get npc
var npc = this.getProgress().getStarTowerNpcById(plot.getNPCId());
// Check if the plot can be claimed
if (npc.getLevel() < plot.getAffinityLevel() || npc.hasPlot(plotId)) {
return null;
}
// Sanity check item
if (GameData.getItemDataTable().get(plot.getItemId()) == null) {
return null;
}
// Add reward
var change = this.getPlayer().getInventory().addItem(plot.getItemId(), plot.getItemQty());
// Mark plot as received
npc.addPlot(plotId);
// Success
return change;
}
// Builds
public Long2ObjectMap<StarTowerBuild> getBuilds() {
@@ -568,6 +605,11 @@ public class StarTowerManager extends PlayerManager {
game.getDifficulty()
);
// Star Tower book event quests (anecdotes)
for (int charId : game.getCharIds()) {
this.getPlayer().trigger(QuestCondition.CharacterPassedWithSpecificTowerAndCount, 1, charId);
}
// Achievement conditions
var achievements = this.getPlayer().getAchievementManager();
@@ -0,0 +1,183 @@
package emu.nebula.game.tower;
import dev.morphia.annotations.Entity;
import emu.nebula.Nebula;
import emu.nebula.data.GameData;
import emu.nebula.data.resources.NpcAffinityGroupDef;
import emu.nebula.game.player.Player;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.proto.Public.NPCAffinity;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import lombok.Getter;
@Getter
@Entity(useDiscriminator = false)
public class StarTowerNpcData {
private int id;
private int level;
private int affinity;
private IntSet plotIds;
// Cached reference to the player
private transient Player player;
@Deprecated // Morphia only
public StarTowerNpcData() {
}
public StarTowerNpcData(Player player, int id) {
this.id = id;
this.plotIds = new IntOpenHashSet();
this.setPlayer(player);
this.save();
}
public void setPlayer(Player player) {
this.player = player;
// Recalculate the level in case the npc was created before levels were stored
this.refreshLevel();
}
public IntSet getPlotIds() {
return this.plotIds;
}
/**
* Gets the affinity data for this NPC at the specified level.
*/
private NpcAffinityGroupDef getAffinityGroupData(int level) {
var data = GameData.getStarTowerNpcDataTable().get(this.getId());
if (data == null) {
return null;
}
return GameData.getNpcAffinityGroupDataTable().get((data.getAffinityGroupId() * 100) + level);
}
/**
* Calculates the NPC's affinity level from its current affinity.
*/
private int calculateLevel() {
int level = this.level;
var nextLevel = this.getAffinityGroupData(level + 1);
// Level up while the player has enough affinity for the next level
while (nextLevel != null && nextLevel.getAffinityValue() > 0 && this.affinity >= nextLevel.getAffinityValue()) {
level++;
nextLevel = this.getAffinityGroupData(level + 1);
}
return level;
}
/**
* Updates the cached level from the NPC's current affinity.
* @return True if the level changed
*/
public boolean refreshLevel() {
int level = this.calculateLevel();
if (this.level == level) {
return false;
}
this.level = level;
return true;
}
/**
* Returns the maximum amount of affinity this NPC can have.
*/
public int getMaxAffinity() {
int maxAffinity = 0;
int level = 0;
var data = this.getAffinityGroupData(level);
// Only iterate the affinity levels for this NPC's group
while (data != null) {
maxAffinity = Math.max(maxAffinity, data.getAffinityValue());
level++;
data = this.getAffinityGroupData(level);
}
return maxAffinity;
}
public int addAffinity(int amount) {
if (amount <= 0) {
return 0;
}
// Save old affinity
int oldAffinity = this.affinity;
int oldLevel = this.level;
// Cap affinity at the maximum level for this npc
int newAffinity = this.affinity + amount;
int maxAffinity = this.getMaxAffinity();
if (maxAffinity > 0) {
newAffinity = Math.min(newAffinity, maxAffinity);
}
this.affinity = newAffinity;
this.refreshLevel();
// Return changed affinity amount
int change = this.affinity - oldAffinity;
if (change > 0 || this.level != oldLevel) {
this.save();
}
// Trigger affinity level quests for each level gained
if (this.level > oldLevel && this.player != null) {
this.player.trigger(QuestCondition.NpcAffinityWithSpecificLevel, this.level - oldLevel, this.getId());
}
return change;
}
public boolean hasPlot(int plotId) {
return this.getPlotIds().contains(plotId);
}
public boolean addPlot(int plotId) {
if (!this.getPlotIds().add(plotId)) {
return false;
}
this.save();
return true;
}
// Proto
public NPCAffinity toProto() {
var proto = NPCAffinity.newInstance()
.setNPCId(this.getId())
.setAffinity(this.getAffinity());
for (int plotId : this.getPlotIds()) {
proto.addPlotIds(plotId);
}
return proto;
}
// Database
/**
* Saves this npc data to the database
*/
public void save() {
Nebula.getGameDatabase().update(player.getProgress(), player.getUid(), "towerNpcs." + this.getId(), this, true);
}
}
@@ -6,6 +6,7 @@ import emu.nebula.GameConstants;
import emu.nebula.data.resources.StarTowerEventDef;
import emu.nebula.game.achievement.AchievementCondition;
import emu.nebula.game.player.PlayerChangeInfo;
import emu.nebula.proto.PublicStarTower.NPCAffinityChange;
import emu.nebula.proto.PublicStarTower.NPCAffinityInfo;
import emu.nebula.proto.PublicStarTower.StarTowerRoomCase;
import emu.nebula.proto.StarTowerInteract.StarTowerInteractReq;
@@ -268,9 +269,25 @@ public class StarTowerNpcEventCase extends StarTowerBaseCase {
success.setOptionsResult(completed);
this.completed = completed;
// Achievment
if (completed) {
// Trigger achievement
this.getGame().getAchievementManager().trigger(AchievementCondition.TowerEventTimes, 1);
// Add npc affinity if the option succeeded
// We skip the weekly limit on this server
var npc = this.getGame().getNpc(npcId);
int affinityIncrease = npc.addAffinity(100);
// Increment star tower's tracked npc interactions
this.getGame().onNpcAffinityIncrease(npcId, affinityIncrease);
// Create affinity proto
var affinityInfo = NPCAffinityChange.newInstance()
.setNPCId(npc.getId())
.setAffinity(npc.getAffinity())
.setIncrease(affinityIncrease);
success.addAffinityChange(affinityInfo);
}
// Complete
@@ -331,9 +348,11 @@ public class StarTowerNpcEventCase extends StarTowerBaseCase {
@Override
public void encodeProto(StarTowerRoomCase proto) {
var npc = this.getGame().getNpc(npcId);
var info = NPCAffinityInfo.newInstance()
.setNPCId(this.getNpcId())
.setAffinity(0);
.setAffinity(npc.getAffinity());
proto.getMutableSelectOptionsEventCase()
.setEvtId(this.getEventId())
@@ -11,9 +11,15 @@ public class HandlerNpcAffinityBookGetReq extends NetHandler {
@Override
public byte[] handle(GameSession session, byte[] message) throws Exception {
var player = session.getPlayer();
// Build response
var rsp = NPCAffinityBookGetResp.newInstance();
for (var npc : player.getStarTowerManager().getNpcAffinities()) {
rsp.addInfos(npc.toProto());
}
// Encode and send
return session.encodeMsg(NetMsgId.npc_affinity_book_get_succeed_ack, rsp);
}
@@ -0,0 +1,45 @@
package emu.nebula.server.handlers;
import emu.nebula.data.GameData;
import emu.nebula.net.GameSession;
import emu.nebula.net.HandlerId;
import emu.nebula.net.NetHandler;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.NpcAffinityPlotRewardReceive.NPCAffinityPlotRewardReceiveResp;
import emu.nebula.proto.Public.ItemTpl;
import emu.nebula.proto.Public.UI32;
@HandlerId(NetMsgId.npc_affinity_plot_reward_receive_req)
public class HandlerNpcAffinityPlotRewardReceiveReq extends NetHandler {
@Override
public byte[] handle(GameSession session, byte[] message) throws Exception {
// Parse request
var req = UI32.parseFrom(message);
int plotId = req.getValue();
// Get plot data
var plot = GameData.getNpcAffinityPlotDataTable().get(plotId);
if (plot == null) {
return session.encodeMsg(NetMsgId.npc_affinity_plot_reward_receive_failed_ack);
}
// Claim reward
var change = session.getPlayer().getStarTowerManager().receiveNpcAffinityPlotReward(plotId);
if (change == null) {
return session.encodeMsg(NetMsgId.npc_affinity_plot_reward_receive_failed_ack);
}
// Build response
var rsp = NPCAffinityPlotRewardReceiveResp.newInstance()
.setChange(change.toProto())
.addShow(ItemTpl.newInstance()
.setTid(plot.getItemId())
.setQty(plot.getItemQty()));
// Encode and send
return session.encodeMsg(NetMsgId.npc_affinity_plot_reward_receive_succeed_ack, rsp);
}
}
@@ -0,0 +1,38 @@
package emu.nebula.server.handlers;
import emu.nebula.net.GameSession;
import emu.nebula.net.HandlerId;
import emu.nebula.net.NetHandler;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.Public.UI32;
import emu.nebula.proto.StarTowerBookEventRewardReceive.StarTowerBookEventRewardReceiveResp;
import it.unimi.dsi.fastutil.ints.IntList;
@HandlerId(NetMsgId.star_tower_book_event_reward_receive_req)
public class HandlerStarTowerBookEventRewardReceiveReq extends NetHandler {
@Override
public byte[] handle(GameSession session, byte[] message) throws Exception {
// Parse request
var req = UI32.parseFrom(message);
// Claim reward(s)
var change = session.getPlayer().getQuestManager().receiveStarTowerBookEventReward(req.getValue());
if (change == null) {
return session.encodeMsg(NetMsgId.star_tower_book_event_reward_receive_failed_ack);
}
// Build response
var rsp = StarTowerBookEventRewardReceiveResp.newInstance()
.setChange(change.toProto());
// Add list of received reward ids to response
var received = (IntList) change.getExtraData();
received.forEach(rsp::addReceivedIds);
// Encode and send
return session.encodeMsg(NetMsgId.star_tower_book_event_reward_receive_succeed_ack, rsp);
}
}
@@ -19,9 +19,11 @@ public class HandlerStarTowerGiveUpReq extends NetHandler {
// Build response
var rsp = StarTowerGiveUpResp.newInstance()
.setNpcInteraction(game.getNpcInteractions())
.setBuild(game.getBuild().toProto())
.setPotentialCnt(game.getTotalPotentialCount())
.setFloor(game.getFloorCount());
.setFloor(game.getFloorCount())
.addAllReward(game.getNpcAffinityRewards());
rsp.getMutableChange();