mirror of
https://github.com/Melledy/Nebula.git
synced 2026-09-19 09:09:54 +02:00
Implement Finale Echoing (Permanent)
- Sweeps and quests this game mode are not implemented yet
This commit is contained in:
@@ -22,6 +22,7 @@ public class GameConstants {
|
||||
public static final int ENERGY_BUY_ITEM_ID = GEM_ITEM_ID;
|
||||
public static final int EXP_ITEM_ID = 21;
|
||||
public static final int WEEKLY_ENTRY_ITEM_ID = 28;
|
||||
public static final int JOINT_DRILL_TICKET_ID = 36;
|
||||
|
||||
public static final int MAX_ENERGY = 240;
|
||||
public static final int ENERGY_REGEN_TIME = 360; // Seconds
|
||||
|
||||
@@ -166,6 +166,9 @@ public class GameData {
|
||||
@Getter private static DataTable<TrialControlDef> TrialControlDataTable = new DataTable<>();
|
||||
@Getter private static DataTable<TrialGroupDef> TrialGroupDataTable = new DataTable<>();
|
||||
|
||||
// Activity: Joint Drill
|
||||
@Getter private static DataTable<JointDrill2LevelDef> JointDrill2LevelDataTable = new DataTable<>();
|
||||
|
||||
// Activity: Levels
|
||||
@Getter private static DataTable<ActivityLevelsLevelDef> ActivityLevelsLevelDataTable = new DataTable<>();
|
||||
|
||||
|
||||
@@ -10,8 +10,12 @@ import lombok.Getter;
|
||||
public class ActivityDef extends BaseDef {
|
||||
private int Id;
|
||||
private int ActivityType;
|
||||
//private String StartTime;
|
||||
//private String EndTime;
|
||||
|
||||
private transient emu.nebula.game.activity.ActivityType type;
|
||||
//private transient long startTimeSec;
|
||||
//private transient long endTimeSec;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
@@ -20,6 +24,20 @@ public class ActivityDef extends BaseDef {
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
// Cache activity type
|
||||
this.type = emu.nebula.game.activity.ActivityType.getByValue(this.ActivityType);
|
||||
|
||||
// Parse start/end times
|
||||
/*
|
||||
if (this.StartTime != null) {
|
||||
var start = OffsetDateTime.parse(this.StartTime);
|
||||
this.startTimeSec = start.toEpochSecond();
|
||||
}
|
||||
|
||||
if (this.EndTime != null) {
|
||||
var end = OffsetDateTime.parse(this.EndTime);
|
||||
this.endTimeSec = end.toEpochSecond();
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package emu.nebula.data.resources;
|
||||
|
||||
import emu.nebula.data.BaseDef;
|
||||
import emu.nebula.data.ResourceType;
|
||||
import emu.nebula.game.inventory.ItemRewardList;
|
||||
import emu.nebula.game.inventory.ItemRewardParam;
|
||||
import emu.nebula.util.JsonUtils;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@ResourceType(name = "JointDrill_2_Level.json")
|
||||
public class JointDrill2LevelDef extends BaseDef {
|
||||
private int Id;
|
||||
private int BattleTime;
|
||||
|
||||
private int TimeScore;
|
||||
private int ScorePerSec;
|
||||
private int LevelScore;
|
||||
private int BaseHpScore;
|
||||
|
||||
private String RewardPreview;
|
||||
|
||||
private transient ItemRewardList firstRewards;
|
||||
private transient ItemRewardList rewards;
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return Id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
// Init reward lists
|
||||
this.firstRewards = new ItemRewardList();
|
||||
this.rewards = new ItemRewardList();
|
||||
|
||||
// Parse rewards
|
||||
var awards = JsonUtils.decodeList(this.RewardPreview, int[].class);
|
||||
if (awards == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int[] award : awards) {
|
||||
int itemId = award[0];
|
||||
int min = award[1];
|
||||
int max = min;
|
||||
boolean isFirst = award[award.length - 1] == 1;
|
||||
|
||||
if (min == -1) {
|
||||
min = 0;
|
||||
max = 1;
|
||||
}
|
||||
|
||||
var reward = new ItemRewardParam(itemId, min, max);
|
||||
|
||||
if (isFirst) {
|
||||
this.firstRewards.add(reward);
|
||||
} else {
|
||||
this.rewards.add(reward);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import emu.nebula.Nebula;
|
||||
import emu.nebula.game.activity.ActivityModule;
|
||||
import emu.nebula.game.ban.BanModule;
|
||||
import emu.nebula.game.gacha.GachaModule;
|
||||
import emu.nebula.game.jointdrill.JointDrillModule;
|
||||
import emu.nebula.game.player.PlayerModule;
|
||||
import emu.nebula.game.scoreboss.ScoreBossModule;
|
||||
import emu.nebula.game.tutorial.TutorialModule;
|
||||
@@ -31,6 +32,7 @@ public class GameContext implements Runnable {
|
||||
private final TutorialModule tutorialModule;
|
||||
private final ActivityModule activityModule;
|
||||
private final ScoreBossModule scoreBossModule;
|
||||
private final JointDrillModule jointDrillModule;
|
||||
private final BanModule banModule;
|
||||
|
||||
// Game loop
|
||||
@@ -50,6 +52,7 @@ public class GameContext implements Runnable {
|
||||
this.tutorialModule = new TutorialModule(this);
|
||||
this.activityModule = new ActivityModule(this);
|
||||
this.scoreBossModule = new ScoreBossModule(this);
|
||||
this.jointDrillModule = new JointDrillModule(this);
|
||||
this.banModule = new BanModule(this);
|
||||
|
||||
// Run game loop
|
||||
|
||||
@@ -132,6 +132,7 @@ public class ActivityManager extends PlayerManager implements GameDatabaseObject
|
||||
case LoginReward -> new LoginRewardActivity(this, data);
|
||||
case TowerDefense -> new TowerDefenseActivity(this, data);
|
||||
case Trial -> new TrialActivity(this, data);
|
||||
case JointDrill -> new JointDrillActivity(this, data);
|
||||
case Levels -> new LevelsActivity(this, data);
|
||||
case Task -> new TaskActivity(this, data);
|
||||
case Shop -> new ShopActivity(this, data);
|
||||
|
||||
@@ -44,6 +44,9 @@ public class ActivityModule extends GameContextModule {
|
||||
this.activities.add(1010503);
|
||||
this.activities.add(1010504);
|
||||
|
||||
// ===== Joint Drills (Finale Echoing) =====
|
||||
this.activities.add(510003);
|
||||
|
||||
// ===== Etc Events =====
|
||||
|
||||
// Trial activities
|
||||
|
||||
@@ -31,6 +31,16 @@ public abstract class GameActivity {
|
||||
public Player getPlayer() {
|
||||
return this.getManager().getPlayer();
|
||||
}
|
||||
|
||||
public long getStartTime() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public long getEndTime() {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
// Database
|
||||
|
||||
public void save() {
|
||||
Nebula.getGameDatabase().update(
|
||||
@@ -52,8 +62,8 @@ public abstract class GameActivity {
|
||||
public Activity toProto() {
|
||||
var proto = Activity.newInstance()
|
||||
.setId(this.getId())
|
||||
.setStartTime(1)
|
||||
.setEndTime(Integer.MAX_VALUE);
|
||||
.setStartTime(this.getStartTime())
|
||||
.setEndTime(this.getEndTime());
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,273 @@
|
||||
package emu.nebula.game.activity.type;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import dev.morphia.annotations.Entity;
|
||||
import emu.nebula.GameConstants;
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.data.GameData;
|
||||
import emu.nebula.data.resources.ActivityDef;
|
||||
import emu.nebula.data.resources.JointDrill2LevelDef;
|
||||
import emu.nebula.game.activity.ActivityManager;
|
||||
import emu.nebula.game.activity.GameActivity;
|
||||
import emu.nebula.game.jointdrill.JointDrillBuild;
|
||||
import emu.nebula.game.jointdrill.JointDrillRankEntry;
|
||||
import emu.nebula.game.jointdrill.JointDrillScore;
|
||||
import emu.nebula.game.player.PlayerChangeInfo;
|
||||
import emu.nebula.game.tower.StarTowerBuild;
|
||||
import emu.nebula.proto.ActivityDetail.ActivityMsg;
|
||||
import emu.nebula.proto.PublicJointDrill.JointDrillLevel;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Entity
|
||||
public class JointDrillActivity extends GameActivity {
|
||||
private Int2IntMap passedLevels;
|
||||
|
||||
// Current level
|
||||
private transient JointDrill2LevelDef level;
|
||||
private transient StarTowerBuild build;
|
||||
private transient boolean simulate;
|
||||
|
||||
private transient List<JointDrillBuild> teams;
|
||||
|
||||
// Ranking
|
||||
private transient boolean checkedDatabase;
|
||||
private transient JointDrillRankEntry ranking;
|
||||
|
||||
@Deprecated // Morphia only
|
||||
public JointDrillActivity() {
|
||||
this.teams = new ArrayList<>();
|
||||
}
|
||||
|
||||
public JointDrillActivity(ActivityManager manager, ActivityDef data) {
|
||||
super(manager, data);
|
||||
|
||||
// Give the player starting amount of tickets
|
||||
int tickets = this.getPlayer().getInventory().getResourceCount(GameConstants.JOINT_DRILL_TICKET_ID);
|
||||
if (tickets < 3) {
|
||||
this.getPlayer().getInventory().addItem(GameConstants.JOINT_DRILL_TICKET_ID, 3 - tickets);
|
||||
}
|
||||
}
|
||||
|
||||
public Int2IntMap getPassedLevels() {
|
||||
if (this.passedLevels == null) {
|
||||
this.passedLevels = new Int2IntOpenHashMap();
|
||||
}
|
||||
|
||||
return this.passedLevels;
|
||||
}
|
||||
|
||||
public long getStartTime() {
|
||||
// Force activity to be always open for 6+ days
|
||||
return Nebula.getCurrentServerTime() - TimeUnit.DAYS.toSeconds(1);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
this.level = null;
|
||||
this.build = null;
|
||||
this.teams.clear();
|
||||
}
|
||||
|
||||
// Joint drill
|
||||
|
||||
public JointDrillRankEntry getRankEntry() {
|
||||
if (this.ranking == null && !this.checkedDatabase) {
|
||||
this.ranking = Nebula.getGameDatabase().getObjectByUid(JointDrillRankEntry.class, this.getPlayer().getUid());
|
||||
this.checkedDatabase = true;
|
||||
}
|
||||
|
||||
return this.ranking;
|
||||
}
|
||||
|
||||
public synchronized boolean inProgress() {
|
||||
return this.level != null;
|
||||
}
|
||||
|
||||
public synchronized PlayerChangeInfo apply(int levelId, long buildId, boolean simulate) {
|
||||
// Get level and record used
|
||||
var level = GameData.getJointDrill2LevelDataTable().get(levelId);
|
||||
var build = this.getPlayer().getStarTowerManager().getBuildById(buildId);
|
||||
|
||||
// Verify that level and record exists
|
||||
if (level == null || build == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create result
|
||||
PlayerChangeInfo change = null;
|
||||
|
||||
// Consume ticket IF not simulated
|
||||
if (!simulate) {
|
||||
// Make sure player has a ticket
|
||||
if (!getPlayer().getInventory().hasItem(GameConstants.JOINT_DRILL_TICKET_ID, 1)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
change = getPlayer().getInventory().removeItem(GameConstants.JOINT_DRILL_TICKET_ID, 1);
|
||||
} else {
|
||||
change = new PlayerChangeInfo();
|
||||
}
|
||||
|
||||
// Set level and build
|
||||
this.level = level;
|
||||
this.build = build;
|
||||
this.teams.clear();
|
||||
this.simulate = simulate;
|
||||
|
||||
// Failure - No level or record found
|
||||
return change;
|
||||
}
|
||||
|
||||
public synchronized JointDrillScore settle(int time, int damage, boolean win) {
|
||||
// Make sure we are currently in progress
|
||||
if (!this.inProgress()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create score data
|
||||
var score = new JointDrillScore();
|
||||
|
||||
// Calculate score
|
||||
if (win) {
|
||||
score.calculateScore(this.getLevel(), time);
|
||||
} else {
|
||||
// TODO calculate partial score
|
||||
}
|
||||
|
||||
// Add joint drill team
|
||||
if (this.getBuild() != null) {
|
||||
var team = new JointDrillBuild(this.getBuild(), time, damage);
|
||||
this.getTeams().add(team);
|
||||
}
|
||||
|
||||
// Only update if we are not simulating a challenge
|
||||
if (!this.simulate && win) {
|
||||
// Check if this is our first clear
|
||||
boolean isFirstClear = this.getPassedLevels().containsKey(this.getLevel().getId());
|
||||
|
||||
// Get current score
|
||||
int currentScore = this.getPassedLevels().get(this.getLevel().getId());
|
||||
|
||||
// Update score
|
||||
if (score.getTotal() >= currentScore) {
|
||||
// Update passed levels
|
||||
this.getPassedLevels().put(this.getLevel().getId(), score.getTotal());
|
||||
|
||||
// Save activity to database
|
||||
this.save();
|
||||
}
|
||||
|
||||
// Handle ranking
|
||||
if (this.getTeams().size() > 0) {
|
||||
// Get ranking from database
|
||||
this.getRankEntry();
|
||||
|
||||
// Create ranking if its not in the database
|
||||
if (this.ranking == null) {
|
||||
this.ranking = new JointDrillRankEntry(this.getPlayer(), this.getId());
|
||||
}
|
||||
|
||||
// Settle ranking and save if we have a higher score
|
||||
if (score.getTotal() > this.ranking.getScore()) {
|
||||
this.ranking.settle(this.getPlayer(), this.getTeams(), this.getId(), score.getTotal());
|
||||
this.ranking.save();
|
||||
}
|
||||
}
|
||||
|
||||
// Handle rewards
|
||||
if (isFirstClear) {
|
||||
score.getRewards().add(this.getLevel().getFirstRewards().generate());
|
||||
}
|
||||
|
||||
score.getRewards().add(this.getLevel().getRewards().generate());
|
||||
|
||||
// Add rewards
|
||||
this.getPlayer().getInventory().addItems(score.getRewards(), score.getChange());
|
||||
}
|
||||
|
||||
// Reset level
|
||||
this.reset();
|
||||
|
||||
// Finished
|
||||
return score;
|
||||
}
|
||||
|
||||
public synchronized boolean continueDrill(long buildId) {
|
||||
// Make sure we are currently in progress
|
||||
if (!this.inProgress()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.getTeams().size() >= 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get build
|
||||
var build = this.getPlayer().getStarTowerManager().getBuildById(buildId);
|
||||
|
||||
if (build == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO validate build as unique
|
||||
|
||||
// Set build
|
||||
this.build = build;
|
||||
|
||||
// Complete
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized JointDrillScore giveup(int time, int damage) {
|
||||
// Make sure we are currently in progress
|
||||
if (!this.inProgress() || this.getBuild() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create and calculate score
|
||||
var score = new JointDrillScore();
|
||||
|
||||
// TODO calculate partial score
|
||||
|
||||
// Log joint drill team
|
||||
var team = new JointDrillBuild(this.getBuild(), time, damage);
|
||||
this.getTeams().add(team);
|
||||
|
||||
// Clear build
|
||||
this.build = null;
|
||||
|
||||
// Complete
|
||||
return score;
|
||||
}
|
||||
|
||||
// Proto
|
||||
|
||||
@Override
|
||||
public void encodeActivityMsg(ActivityMsg msg) {
|
||||
var proto = msg.getMutableJointDrill();
|
||||
|
||||
// Mark
|
||||
proto.getMutableMeta();
|
||||
proto.getMutableMode2();
|
||||
|
||||
// Add passed levels
|
||||
if (this.passedLevels != null) {
|
||||
for (var entry : this.passedLevels.int2IntEntrySet()) {
|
||||
int levelId = entry.getIntKey();
|
||||
int score = entry.getIntValue();
|
||||
|
||||
var info = JointDrillLevel.newInstance()
|
||||
.setLevelId(levelId)
|
||||
.setScore(score);
|
||||
|
||||
proto.addPassedLevels(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package emu.nebula.game.jointdrill;
|
||||
|
||||
import emu.nebula.game.tower.StarTowerBuild;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class JointDrillBuild {
|
||||
private StarTowerBuild build;
|
||||
private int time;
|
||||
private int damage;
|
||||
|
||||
public JointDrillBuild(StarTowerBuild build, int time, int damage) {
|
||||
this.build = build;
|
||||
this.time = time;
|
||||
this.damage = damage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package emu.nebula.game.jointdrill;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.game.GameContext;
|
||||
import emu.nebula.game.GameContextModule;
|
||||
import emu.nebula.proto.JointDrillRank.JointDrillRankData;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class JointDrillModule extends GameContextModule {
|
||||
private long lastUpdate;
|
||||
private long nextUpdate;
|
||||
private List<JointDrillRankData> ranking;
|
||||
|
||||
public JointDrillModule(GameContext context) {
|
||||
super(context);
|
||||
this.nextUpdate = -1;
|
||||
this.ranking = new ArrayList<>();
|
||||
}
|
||||
|
||||
private long getRefreshTime() {
|
||||
return Nebula.getConfig().getServerOptions().leaderboardRefreshTime * 1000;
|
||||
}
|
||||
|
||||
public synchronized List<JointDrillRankData> getRanking(int activityId) {
|
||||
if (System.currentTimeMillis() > this.nextUpdate) {
|
||||
this.updateRanking(activityId);
|
||||
}
|
||||
|
||||
return this.ranking;
|
||||
}
|
||||
|
||||
// Cache ranking so we dont query the database too much
|
||||
private void updateRanking(int activityId) {
|
||||
// Clear
|
||||
this.ranking.clear();
|
||||
|
||||
// Get from database
|
||||
var list = Nebula.getGameDatabase().getSortedObjects(JointDrillRankEntry.class, "activityId", activityId, "score", 50);
|
||||
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
// Get rank entry and set proto
|
||||
var entry = list.get(i);
|
||||
entry.setRank(i + 1);
|
||||
|
||||
// Add to ranking
|
||||
this.ranking.add(entry.toProto());
|
||||
}
|
||||
|
||||
this.nextUpdate = System.currentTimeMillis() + this.getRefreshTime();
|
||||
this.lastUpdate = Nebula.getCurrentServerTime();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
package emu.nebula.game.jointdrill;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import dev.morphia.annotations.Entity;
|
||||
import dev.morphia.annotations.Id;
|
||||
|
||||
import emu.nebula.database.GameDatabaseObject;
|
||||
import emu.nebula.game.player.Player;
|
||||
import emu.nebula.game.tower.StarTowerBuild;
|
||||
import emu.nebula.game.character.GameCharacter;
|
||||
import emu.nebula.proto.JointDrillRank.JointDrillRankChar;
|
||||
import emu.nebula.proto.JointDrillRank.JointDrillRankData;
|
||||
import emu.nebula.proto.JointDrillRank.JointDrillRankTeam;
|
||||
import emu.nebula.proto.Public.HonorInfo;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Entity(value = "joint_drill_rank", useDiscriminator = false)
|
||||
public class JointDrillRankEntry implements GameDatabaseObject {
|
||||
@Id
|
||||
private int playerUid;
|
||||
|
||||
private String name;
|
||||
private int level;
|
||||
private int headIcon;
|
||||
private int titlePrefix;
|
||||
private int titleSuffix;
|
||||
private int[] honor;
|
||||
private int score;
|
||||
private IntSet claimedRewards;
|
||||
|
||||
private int activityId;
|
||||
private List<JointDrillTeamEntry> teams;
|
||||
|
||||
@Setter
|
||||
private transient int rank;
|
||||
|
||||
@Deprecated // Morphia only
|
||||
public JointDrillRankEntry() {
|
||||
this.rank = 999;
|
||||
}
|
||||
|
||||
public JointDrillRankEntry(Player player, int activityId) {
|
||||
this.playerUid = player.getUid();
|
||||
this.activityId = activityId;
|
||||
this.teams = new ArrayList<>();
|
||||
}
|
||||
|
||||
public IntSet getClaimedRewards() {
|
||||
if (this.claimedRewards == null) {
|
||||
this.claimedRewards = new IntOpenHashSet();
|
||||
}
|
||||
|
||||
return this.claimedRewards;
|
||||
}
|
||||
|
||||
public void update(Player player) {
|
||||
this.name = player.getName();
|
||||
this.level = player.getLevel();
|
||||
this.headIcon = player.getHeadIcon();
|
||||
this.titlePrefix = player.getTitlePrefix();
|
||||
this.titleSuffix = player.getTitleSuffix();
|
||||
this.honor = player.getHonor();
|
||||
}
|
||||
|
||||
public void settle(Player player, List<JointDrillBuild> builds, int activityId, int score) {
|
||||
// Update player data
|
||||
this.update(player);
|
||||
|
||||
// Reset score entry if activity id doesn't match
|
||||
if (this.activityId != activityId) {
|
||||
this.activityId = activityId;
|
||||
this.reset();
|
||||
}
|
||||
|
||||
// Add teams
|
||||
for (var build : builds) {
|
||||
var team = new JointDrillTeamEntry(player, build.getBuild(), build.getTime(), build.getDamage());
|
||||
this.getTeams().add(team);
|
||||
}
|
||||
|
||||
// Calculate score
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
private void reset() {
|
||||
this.score = 0;
|
||||
this.getClaimedRewards().clear();
|
||||
this.getTeams().clear();
|
||||
}
|
||||
|
||||
// Proto
|
||||
|
||||
public JointDrillRankData toProto() {
|
||||
var proto = JointDrillRankData.newInstance()
|
||||
.setId(this.getPlayerUid())
|
||||
.setNickName(this.getName())
|
||||
.setWorldClass(this.getLevel())
|
||||
.setHeadIcon(this.getHeadIcon())
|
||||
.setScore(this.getScore())
|
||||
.setTitlePrefix(this.getTitlePrefix())
|
||||
.setTitleSuffix(this.getTitleSuffix())
|
||||
.setRank(this.getRank());
|
||||
|
||||
for (int id : this.getHonor()) {
|
||||
proto.addHonors(HonorInfo.newInstance().setId(id));
|
||||
}
|
||||
|
||||
for (var team : this.getTeams()) {
|
||||
proto.addTeams(team.toProto());
|
||||
}
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
||||
// Extra classes
|
||||
|
||||
@Getter
|
||||
@Entity(useDiscriminator = false)
|
||||
public static class JointDrillTeamEntry {
|
||||
private int buildId;
|
||||
private int buildScore;
|
||||
private int damage;
|
||||
private int time;
|
||||
private List<JointDrillCharEntry> characters;
|
||||
|
||||
@Deprecated // Morphia only
|
||||
public JointDrillTeamEntry() {
|
||||
|
||||
}
|
||||
|
||||
public JointDrillTeamEntry(Player player, StarTowerBuild build, int time, int damage) {
|
||||
this.buildId = build.getUid();
|
||||
this.buildScore = build.getScore();
|
||||
this.time = time;
|
||||
this.damage = damage;
|
||||
this.characters = new ArrayList<>();
|
||||
|
||||
for (var charId : build.getCharIds()) {
|
||||
var character = player.getCharacters().getCharacterById(charId);
|
||||
if (character != null) {
|
||||
this.getCharacters().add(new JointDrillCharEntry(character));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public JointDrillRankTeam toProto() {
|
||||
var proto = JointDrillRankTeam.newInstance()
|
||||
.setBuildScore(this.getBuildScore())
|
||||
.setDamage(this.getDamage())
|
||||
.setTime(this.getTime());
|
||||
|
||||
for (var c : this.getCharacters()) {
|
||||
proto.addChars(c.toProto());
|
||||
}
|
||||
|
||||
return proto;
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Entity(useDiscriminator = false)
|
||||
public static class JointDrillCharEntry {
|
||||
private int id;
|
||||
private int level;
|
||||
|
||||
@Deprecated // Morphia only
|
||||
public JointDrillCharEntry() {
|
||||
|
||||
}
|
||||
|
||||
public JointDrillCharEntry(GameCharacter character) {
|
||||
this.id = character.getCharId();
|
||||
this.level = character.getLevel();
|
||||
}
|
||||
|
||||
public JointDrillRankChar toProto() {
|
||||
var proto = JointDrillRankChar.newInstance()
|
||||
.setId(this.getId())
|
||||
.setLevel(this.getLevel());
|
||||
|
||||
return proto;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package emu.nebula.game.jointdrill;
|
||||
|
||||
import emu.nebula.data.resources.JointDrill2LevelDef;
|
||||
import emu.nebula.game.inventory.ItemParamMap;
|
||||
import emu.nebula.game.player.PlayerChangeInfo;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class JointDrillScore {
|
||||
// Scores
|
||||
private int fight;
|
||||
private int hp;
|
||||
private int difficulty;
|
||||
private int total;
|
||||
|
||||
// Items
|
||||
private PlayerChangeInfo change;
|
||||
private ItemParamMap rewards;
|
||||
|
||||
public JointDrillScore() {
|
||||
this.change = new PlayerChangeInfo();
|
||||
this.rewards = new ItemParamMap();
|
||||
}
|
||||
|
||||
public void calculateScore(JointDrill2LevelDef level, int time) {
|
||||
// Clamp time
|
||||
time = Math.max(time, 0);
|
||||
|
||||
// Get time penalty
|
||||
int timePenalty = (int) (level.getScorePerSec() * (time / 1000D));
|
||||
|
||||
// Calculate scores
|
||||
this.difficulty = level.getLevelScore();
|
||||
this.hp = level.getBaseHpScore();
|
||||
this.fight = Math.max(level.getTimeScore() - timePenalty, 0);
|
||||
|
||||
// Calculate total score
|
||||
this.total = this.difficulty + this.hp + this.fight;
|
||||
}
|
||||
}
|
||||
@@ -707,6 +707,12 @@ public class Player implements GameDatabaseObject {
|
||||
this.getQuestManager().resetDailyQuests(resetWeekly);
|
||||
this.getBattlePassManager().getBattlePass().resetDailyQuests(resetWeekly);
|
||||
|
||||
// Add daily joint drill tickets
|
||||
int tickets = this.getInventory().getResourceCount(GameConstants.JOINT_DRILL_TICKET_ID);
|
||||
if (tickets < 3) {
|
||||
this.getInventory().addItem(GameConstants.JOINT_DRILL_TICKET_ID, 3 - tickets);
|
||||
}
|
||||
|
||||
// Check to reset weeklies
|
||||
if (resetWeekly) {
|
||||
// Add weekly boss entry item
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.JointDrill2Apply.JointDrill2ApplyReq;
|
||||
import emu.nebula.proto.JointDrill2Apply.JointDrill2ApplyResp;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.game.activity.type.JointDrillActivity;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.joint_drill_2_apply_req)
|
||||
public class HandlerJointDrill2ApplyReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Get joint drill activity
|
||||
var activity = session.getPlayer().getActivityManager().getFirstActivity(JointDrillActivity.class);
|
||||
|
||||
if (activity == null) {
|
||||
return session.encodeMsg(NetMsgId.joint_drill_2_apply_failed_ack);
|
||||
}
|
||||
|
||||
// Parse request
|
||||
var req = JointDrill2ApplyReq.parseFrom(message);
|
||||
|
||||
// Apply for joint drill stage
|
||||
var change = activity.apply(req.getLevelId(), req.getBuildId(), req.getSimulate());
|
||||
|
||||
if (change == null) {
|
||||
return session.encodeMsg(NetMsgId.joint_drill_2_apply_failed_ack);
|
||||
}
|
||||
|
||||
// Create response packet
|
||||
var rsp = JointDrill2ApplyResp.newInstance()
|
||||
.setStarTime(Nebula.getCurrentServerTime() + activity.getLevel().getBattleTime())
|
||||
.setChange(change.toProto());
|
||||
|
||||
// Encode and send
|
||||
return session.encodeMsg(NetMsgId.joint_drill_2_apply_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.JointDrill2Continue.JointDrill2ContinueReq;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.game.activity.type.JointDrillActivity;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.joint_drill_2_continue_req)
|
||||
public class HandlerJointDrill2ContinueReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Get joint drill activity
|
||||
var activity = session.getPlayer().getActivityManager().getFirstActivity(JointDrillActivity.class);
|
||||
|
||||
if (activity == null) {
|
||||
return session.encodeMsg(NetMsgId.joint_drill_2_continue_failed_ack);
|
||||
}
|
||||
|
||||
// Parse request
|
||||
var req = JointDrill2ContinueReq.parseFrom(message);
|
||||
|
||||
// Continue
|
||||
var success = activity.continueDrill(req.getBuildId());
|
||||
|
||||
// Check
|
||||
if (!success) {
|
||||
return session.encodeMsg(NetMsgId.joint_drill_2_continue_failed_ack);
|
||||
}
|
||||
|
||||
// Encode and send
|
||||
return session.encodeMsg(NetMsgId.joint_drill_2_continue_succeed_ack);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.PublicJointDrill.JointDrillSettle;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.game.activity.type.JointDrillActivity;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.joint_drill_2_game_over_req)
|
||||
public class HandlerJointDrill2GameOverReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Get joint drill activity
|
||||
var activity = session.getPlayer().getActivityManager().getFirstActivity(JointDrillActivity.class);
|
||||
|
||||
if (activity == null) {
|
||||
return session.encodeMsg(NetMsgId.joint_drill_2_game_over_failed_ack);
|
||||
}
|
||||
|
||||
// Give up
|
||||
var score = activity.settle(0, 0, false);
|
||||
|
||||
if (score == null) {
|
||||
return session.encodeMsg(NetMsgId.joint_drill_2_game_over_failed_ack);
|
||||
}
|
||||
|
||||
// Build response
|
||||
var rsp = JointDrillSettle.newInstance()
|
||||
.setFightScore(score.getFight())
|
||||
.setDifficultyScore(score.getDifficulty())
|
||||
.setHpScore(score.getHp())
|
||||
.setChange(score.getChange().toProto());
|
||||
|
||||
// Encode and send
|
||||
return session.encodeMsg(NetMsgId.joint_drill_2_game_over_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.JointDrill2GiveUp.JointDrill2GiveUpReq;
|
||||
import emu.nebula.proto.PublicJointDrill.JointDrillSettle;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.game.activity.type.JointDrillActivity;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.joint_drill_2_give_up_req)
|
||||
public class HandlerJointDrill2GiveUpReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Get joint drill activity
|
||||
var activity = session.getPlayer().getActivityManager().getFirstActivity(JointDrillActivity.class);
|
||||
|
||||
if (activity == null) {
|
||||
return session.encodeMsg(NetMsgId.joint_drill_2_give_up_failed_ack);
|
||||
}
|
||||
|
||||
// Parse request
|
||||
var req = JointDrill2GiveUpReq.parseFrom(message);
|
||||
|
||||
// Give up
|
||||
var score = activity.giveup(req.getTime(), req.getDamage());
|
||||
|
||||
if (score == null) {
|
||||
return session.encodeMsg(NetMsgId.joint_drill_2_give_up_failed_ack);
|
||||
}
|
||||
|
||||
// Build response
|
||||
var rsp = JointDrillSettle.newInstance()
|
||||
.setFightScore(score.getFight())
|
||||
.setDifficultyScore(score.getDifficulty())
|
||||
.setHpScore(score.getHp())
|
||||
.setChange(score.getChange().toProto());
|
||||
|
||||
// Encode and send
|
||||
return session.encodeMsg(NetMsgId.joint_drill_2_give_up_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.joint_drill_2_retreat_req)
|
||||
public class HandlerJointDrill2RetreatReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
return session.encodeMsg(NetMsgId.joint_drill_2_retreat_succeed_ack);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.JointDrill2Settle.JointDrill2SettleReq;
|
||||
import emu.nebula.proto.PublicJointDrill.JointDrillSettle;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.game.activity.type.JointDrillActivity;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.joint_drill_2_settle_req)
|
||||
public class HandlerJointDrill2SettleReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Get joint drill activity
|
||||
var activity = session.getPlayer().getActivityManager().getFirstActivity(JointDrillActivity.class);
|
||||
|
||||
if (activity == null) {
|
||||
return session.encodeMsg(NetMsgId.joint_drill_2_settle_failed_ack);
|
||||
}
|
||||
|
||||
// Parse request
|
||||
var req = JointDrill2SettleReq.parseFrom(message);
|
||||
|
||||
// Settle
|
||||
var score = activity.settle(req.getTime(), req.getDamage(), true);
|
||||
|
||||
if (score == null) {
|
||||
return session.encodeMsg(NetMsgId.joint_drill_2_settle_failed_ack);
|
||||
}
|
||||
|
||||
// Handle client events for achievements
|
||||
session.getPlayer().getAchievementManager().handleClientEvents(req.getEvents());
|
||||
|
||||
// Build response
|
||||
var rsp = JointDrillSettle.newInstance()
|
||||
.setFightScore(score.getFight())
|
||||
.setDifficultyScore(score.getDifficulty())
|
||||
.setHpScore(score.getHp())
|
||||
.setChange(score.getChange().toProto());
|
||||
|
||||
score.getRewards().toItemTemplateStream().forEach(rsp::addItems);
|
||||
|
||||
// Encode and send
|
||||
return session.encodeMsg(NetMsgId.joint_drill_2_settle_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.joint_drill_2_sync_req)
|
||||
public class HandlerJointDrill2SyncReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
return session.encodeMsg(NetMsgId.joint_drill_2_sync_succeed_ack);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.JointDrillRank.JointDrillRankInfo;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.game.activity.type.JointDrillActivity;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.joint_drill_rank_req)
|
||||
public class HandlerJointDrillRankReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Get joint drill activity
|
||||
var activity = session.getPlayer().getActivityManager().getFirstActivity(JointDrillActivity.class);
|
||||
|
||||
if (activity == null) {
|
||||
return session.encodeMsg(NetMsgId.joint_drill_rank_failed_ack);
|
||||
}
|
||||
|
||||
// Build response
|
||||
var rsp = JointDrillRankInfo.newInstance()
|
||||
.setLastRefreshTime(Nebula.getCurrentServerTime());
|
||||
|
||||
// Get self
|
||||
var self = activity.getRankEntry();
|
||||
|
||||
if (self != null) {
|
||||
rsp.setSelf(self.toProto());
|
||||
}
|
||||
|
||||
// Get ranking
|
||||
var ranking = Nebula.getGameContext().getJointDrillModule().getRanking(activity.getId());
|
||||
|
||||
for (var entry : ranking) {
|
||||
// Check self
|
||||
if (self != null && self.getPlayerUid() == entry.getId()) {
|
||||
rsp.getMutableSelf().setRank(entry.getRank());
|
||||
}
|
||||
|
||||
// Add to ranking
|
||||
rsp.addRank(entry);
|
||||
}
|
||||
|
||||
// Set total
|
||||
rsp.setTotal(ranking.size());
|
||||
|
||||
// Encode and send
|
||||
return session.encodeMsg(NetMsgId.joint_drill_rank_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"global": 92,
|
||||
"kr": 98,
|
||||
"jp": 95,
|
||||
"tw": 101,
|
||||
"cn": 94
|
||||
"global": 93,
|
||||
"kr": 99,
|
||||
"jp": 96,
|
||||
"tw": 102,
|
||||
"cn": 95
|
||||
}
|
||||
Reference in New Issue
Block a user