mirror of
https://github.com/Melledy/Nebula.git
synced 2025-12-13 12:54:36 +01:00
Compare commits
3 Commits
be84e0f406
...
86c607c0b3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86c607c0b3 | ||
|
|
3710f0a697 | ||
|
|
c19aa5d0a1 |
@@ -34,7 +34,6 @@ public class GameConstants {
|
|||||||
public static final int GEM_ITEM_ID = 2;
|
public static final int GEM_ITEM_ID = 2;
|
||||||
public static final int PREM_GEM_ITEM_ID = 3;
|
public static final int PREM_GEM_ITEM_ID = 3;
|
||||||
public static final int ENERGY_BUY_ITEM_ID = GEM_ITEM_ID;
|
public static final int ENERGY_BUY_ITEM_ID = GEM_ITEM_ID;
|
||||||
public static final int STAR_TOWER_COIN_ITEM_ID = 11;
|
|
||||||
public static final int EXP_ITEM_ID = 21;
|
public static final int EXP_ITEM_ID = 21;
|
||||||
|
|
||||||
public static final int MAX_ENERGY = 240;
|
public static final int MAX_ENERGY = 240;
|
||||||
@@ -52,6 +51,14 @@ public class GameConstants {
|
|||||||
public static final int MAX_FRIENDSHIPS = 50;
|
public static final int MAX_FRIENDSHIPS = 50;
|
||||||
public static final int MAX_PENDING_FRIENDSHIPS = 30;
|
public static final int MAX_PENDING_FRIENDSHIPS = 30;
|
||||||
|
|
||||||
|
public static final int TOWER_COIN_ITEM_ID = 11;
|
||||||
|
public static final int[] TOWER_COMMON_SUB_NOTE_SKILLS = new int[] {
|
||||||
|
90011, 90012, 90013, 90014, 90015, 90016, 90017
|
||||||
|
};
|
||||||
|
public static final int[] TOWER_EVENTS_IDS = new int[] {
|
||||||
|
101, 102, 104, 105, 106, 107, 108, 114, 115, 116, 126, 127, 128
|
||||||
|
};
|
||||||
|
|
||||||
public static int[][] VAMPIRE_SURVIVOR_BONUS_POWER = new int[][] {
|
public static int[][] VAMPIRE_SURVIVOR_BONUS_POWER = new int[][] {
|
||||||
new int[] {100, 120},
|
new int[] {100, 120},
|
||||||
new int[] {200, 150},
|
new int[] {200, 150},
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ public class GameData {
|
|||||||
@Getter private static DataTable<DiscPromoteDef> DiscPromoteDataTable = new DataTable<>();
|
@Getter private static DataTable<DiscPromoteDef> DiscPromoteDataTable = new DataTable<>();
|
||||||
@Getter private static DataTable<DiscPromoteLimitDef> DiscPromoteLimitDataTable = new DataTable<>();
|
@Getter private static DataTable<DiscPromoteLimitDef> DiscPromoteLimitDataTable = new DataTable<>();
|
||||||
|
|
||||||
|
@Getter private static DataTable<SecondarySkillDef> SecondarySkillDataTable = new DataTable<>();
|
||||||
|
|
||||||
// Items
|
// Items
|
||||||
@Getter private static DataTable<ItemDef> ItemDataTable = new DataTable<>();
|
@Getter private static DataTable<ItemDef> ItemDataTable = new DataTable<>();
|
||||||
@Getter private static DataTable<ProductionDef> ProductionDataTable = new DataTable<>();
|
@Getter private static DataTable<ProductionDef> ProductionDataTable = new DataTable<>();
|
||||||
@@ -114,6 +116,7 @@ public class GameData {
|
|||||||
@Getter private static DataTable<StarTowerGrowthNodeDef> StarTowerGrowthNodeDataTable = new DataTable<>();
|
@Getter private static DataTable<StarTowerGrowthNodeDef> StarTowerGrowthNodeDataTable = new DataTable<>();
|
||||||
@Getter private static DataTable<StarTowerFloorExpDef> StarTowerFloorExpDataTable = new DataTable<>();
|
@Getter private static DataTable<StarTowerFloorExpDef> StarTowerFloorExpDataTable = new DataTable<>();
|
||||||
@Getter private static DataTable<StarTowerTeamExpDef> StarTowerTeamExpDataTable = new DataTable<>();
|
@Getter private static DataTable<StarTowerTeamExpDef> StarTowerTeamExpDataTable = new DataTable<>();
|
||||||
|
@Getter private static DataTable<StarTowerEventDef> StarTowerEventDataTable = new DataTable<>();
|
||||||
@Getter private static DataTable<SubNoteSkillPromoteGroupDef> SubNoteSkillPromoteGroupDataTable = new DataTable<>();
|
@Getter private static DataTable<SubNoteSkillPromoteGroupDef> SubNoteSkillPromoteGroupDataTable = new DataTable<>();
|
||||||
|
|
||||||
@Getter private static DataTable<PotentialDef> PotentialDataTable = new DataTable<>();
|
@Getter private static DataTable<PotentialDef> PotentialDataTable = new DataTable<>();
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ public class DiscDef extends BaseDef {
|
|||||||
private int TransformItemId;
|
private int TransformItemId;
|
||||||
private int[] MaxStarTransformItem;
|
private int[] MaxStarTransformItem;
|
||||||
private int[] ReadReward;
|
private int[] ReadReward;
|
||||||
|
|
||||||
|
private int SecondarySkillGroupId1;
|
||||||
|
private int SecondarySkillGroupId2;
|
||||||
private int SubNoteSkillGroupId;
|
private int SubNoteSkillGroupId;
|
||||||
|
|
||||||
private transient ElementType elementType;
|
private transient ElementType elementType;
|
||||||
|
|||||||
34
src/main/java/emu/nebula/data/resources/EventOptionsDef.java
Normal file
34
src/main/java/emu/nebula/data/resources/EventOptionsDef.java
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package emu.nebula.data.resources;
|
||||||
|
|
||||||
|
import emu.nebula.data.BaseDef;
|
||||||
|
import emu.nebula.data.GameData;
|
||||||
|
import emu.nebula.data.ResourceType;
|
||||||
|
import emu.nebula.data.ResourceType.LoadPriority;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We don't need a DataTable for this, since we are only using this class to verify event options for the client
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@ResourceType(name = "EventOptions.json", loadPriority = LoadPriority.LOW)
|
||||||
|
public class EventOptionsDef extends BaseDef {
|
||||||
|
private int Id;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoad() {
|
||||||
|
// Get event
|
||||||
|
var event = GameData.getStarTowerEventDataTable().get(this.Id / 100);
|
||||||
|
if (event == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to avaliable options
|
||||||
|
event.getOptionIds().add(this.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
118
src/main/java/emu/nebula/data/resources/SecondarySkillDef.java
Normal file
118
src/main/java/emu/nebula/data/resources/SecondarySkillDef.java
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
package emu.nebula.data.resources;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import emu.nebula.data.BaseDef;
|
||||||
|
import emu.nebula.data.GameData;
|
||||||
|
import emu.nebula.data.ResourceType;
|
||||||
|
import emu.nebula.game.inventory.ItemParamMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ResourceType(name = "SecondarySkill.json")
|
||||||
|
public class SecondarySkillDef extends BaseDef {
|
||||||
|
private int Id;
|
||||||
|
private int GroupId;
|
||||||
|
private int Score;
|
||||||
|
private String NeedSubNoteSkills;
|
||||||
|
|
||||||
|
private transient ItemParamMap reqSubNotes;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private static transient Int2ObjectMap<List<SecondarySkillDef>> groups = new Int2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean match(ItemParamMap subNotes) {
|
||||||
|
for (var item : this.reqSubNotes) {
|
||||||
|
int reqId = item.getIntKey();
|
||||||
|
int reqCount = item.getIntValue();
|
||||||
|
|
||||||
|
int curCount = subNotes.get(reqId);
|
||||||
|
if (curCount < reqCount) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoad() {
|
||||||
|
// Setup required subnotes
|
||||||
|
this.reqSubNotes = ItemParamMap.fromJsonString(this.NeedSubNoteSkills);
|
||||||
|
|
||||||
|
// Add to group cache
|
||||||
|
var group = groups.computeIfAbsent(this.GroupId, id -> new ArrayList<>());
|
||||||
|
group.add(this);
|
||||||
|
|
||||||
|
// Clear to save memory
|
||||||
|
this.NeedSubNoteSkills = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Static sub note skill group group
|
||||||
|
|
||||||
|
public static List<SecondarySkillDef> getGroup(int id) {
|
||||||
|
return groups.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IntSet calculateSecondarySkills(int[] discIds, ItemParamMap subNotes) {
|
||||||
|
var secondarySkills = new IntOpenHashSet();
|
||||||
|
|
||||||
|
// Get first 3 discs
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
// Disc id
|
||||||
|
int discId = discIds[i];
|
||||||
|
|
||||||
|
// Get disc data
|
||||||
|
var data = GameData.getDiscDataTable().get(discId);
|
||||||
|
if (data == null) continue;
|
||||||
|
|
||||||
|
// Add secondary skills
|
||||||
|
int s1= getSecondarySkill(subNotes, data.getSecondarySkillGroupId1());
|
||||||
|
if (s1 > 0) {
|
||||||
|
secondarySkills.add(s1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int s2 = getSecondarySkill(subNotes, data.getSecondarySkillGroupId2());
|
||||||
|
if (s2 > 0) {
|
||||||
|
secondarySkills.add(s2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return secondarySkills;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getSecondarySkill(ItemParamMap subNotes, int groupId) {
|
||||||
|
// Check group id
|
||||||
|
if (groupId <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get group
|
||||||
|
var group = SecondarySkillDef.getGroup(groupId);
|
||||||
|
if (group == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reverse iterator to try and match highest secondary skill first
|
||||||
|
for (int i = group.size() - 1; i >= 0; i--) {
|
||||||
|
var data = group.get(i);
|
||||||
|
|
||||||
|
if (data.match(subNotes)) {
|
||||||
|
return data.getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Failure
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package emu.nebula.data.resources;
|
||||||
|
|
||||||
|
import emu.nebula.data.BaseDef;
|
||||||
|
import emu.nebula.data.ResourceType;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntList;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@ResourceType(name = "StarTowerEvent.json")
|
||||||
|
public class StarTowerEventDef extends BaseDef {
|
||||||
|
private int Id;
|
||||||
|
private int[] RelatedNPCs;
|
||||||
|
|
||||||
|
private transient IntList optionIds;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a deep copy of our option ids
|
||||||
|
*/
|
||||||
|
public IntList getClonedOptionIds() {
|
||||||
|
var list = new IntArrayList();
|
||||||
|
list.addAll(this.getOptionIds());
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onLoad() {
|
||||||
|
this.optionIds = new IntArrayList();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import dev.morphia.annotations.Id;
|
|||||||
import dev.morphia.annotations.Indexed;
|
import dev.morphia.annotations.Indexed;
|
||||||
import emu.nebula.Nebula;
|
import emu.nebula.Nebula;
|
||||||
import emu.nebula.data.GameData;
|
import emu.nebula.data.GameData;
|
||||||
|
import emu.nebula.data.resources.SecondarySkillDef;
|
||||||
import emu.nebula.database.GameDatabaseObject;
|
import emu.nebula.database.GameDatabaseObject;
|
||||||
import emu.nebula.game.character.GameCharacter;
|
import emu.nebula.game.character.GameCharacter;
|
||||||
import emu.nebula.game.character.GameDisc;
|
import emu.nebula.game.character.GameDisc;
|
||||||
@@ -20,6 +21,7 @@ import emu.nebula.proto.PublicStarTower.StarTowerBuildInfo;
|
|||||||
import emu.nebula.proto.PublicStarTower.TowerBuildChar;
|
import emu.nebula.proto.PublicStarTower.TowerBuildChar;
|
||||||
import emu.nebula.util.Snowflake;
|
import emu.nebula.util.Snowflake;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@@ -42,6 +44,8 @@ public class StarTowerBuild implements GameDatabaseObject {
|
|||||||
private ItemParamMap potentials;
|
private ItemParamMap potentials;
|
||||||
private ItemParamMap subNoteSkills;
|
private ItemParamMap subNoteSkills;
|
||||||
|
|
||||||
|
private IntSet secondarySkills;
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public StarTowerBuild() {
|
public StarTowerBuild() {
|
||||||
|
|
||||||
@@ -60,17 +64,9 @@ public class StarTowerBuild implements GameDatabaseObject {
|
|||||||
// Initialize basic variables
|
// Initialize basic variables
|
||||||
this(game.getPlayer());
|
this(game.getPlayer());
|
||||||
|
|
||||||
// Characters
|
// Set char/disc ids
|
||||||
this.charIds = game.getChars().stream()
|
this.charIds = game.getCharIds();
|
||||||
.filter(c -> c.getId() > 0)
|
this.discIds = game.getDiscIds();
|
||||||
.mapToInt(c -> c.getId())
|
|
||||||
.toArray();
|
|
||||||
|
|
||||||
// Discs
|
|
||||||
this.discIds = game.getDiscs().stream()
|
|
||||||
.filter(d -> d.getId() > 0)
|
|
||||||
.mapToInt(d -> d.getId())
|
|
||||||
.toArray();
|
|
||||||
|
|
||||||
// Add potentials
|
// Add potentials
|
||||||
for (var entry : game.getPotentials()) {
|
for (var entry : game.getPotentials()) {
|
||||||
@@ -94,6 +90,9 @@ public class StarTowerBuild implements GameDatabaseObject {
|
|||||||
this.getSubNoteSkills().put(entry.getIntKey(), entry.getIntValue());
|
this.getSubNoteSkills().put(entry.getIntKey(), entry.getIntValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set secondary skills
|
||||||
|
this.secondarySkills = game.getSecondarySkills();
|
||||||
|
|
||||||
// Caclulate record score and cache it
|
// Caclulate record score and cache it
|
||||||
this.calculateScore();
|
this.calculateScore();
|
||||||
}
|
}
|
||||||
@@ -135,7 +134,7 @@ public class StarTowerBuild implements GameDatabaseObject {
|
|||||||
// Clear score
|
// Clear score
|
||||||
this.score = 0;
|
this.score = 0;
|
||||||
|
|
||||||
// Potentials
|
// Add score from potentials
|
||||||
for (var potential : this.getPotentials().int2IntEntrySet()) {
|
for (var potential : this.getPotentials().int2IntEntrySet()) {
|
||||||
var data = GameData.getPotentialDataTable().get(potential.getIntKey());
|
var data = GameData.getPotentialDataTable().get(potential.getIntKey());
|
||||||
if (data == null) continue;
|
if (data == null) continue;
|
||||||
@@ -143,11 +142,24 @@ public class StarTowerBuild implements GameDatabaseObject {
|
|||||||
this.score += data.getBuildScore(potential.getIntValue());
|
this.score += data.getBuildScore(potential.getIntValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sub note skills
|
// Add score from sub note skills
|
||||||
for (var item : this.getSubNoteSkills()) {
|
for (var item : this.getSubNoteSkills()) {
|
||||||
this.score += item.getIntValue() * 15;
|
this.score += item.getIntValue() * 15;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check secondary skills
|
||||||
|
if (this.getSecondarySkills() == null) {
|
||||||
|
this.secondarySkills = SecondarySkillDef.calculateSecondarySkills(this.getDiscIds(), this.getSubNoteSkills());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add score from secondary skills
|
||||||
|
for (int id : this.getSecondarySkills()) {
|
||||||
|
var data = GameData.getSecondarySkillDataTable().get(id);
|
||||||
|
if (data == null) continue;
|
||||||
|
|
||||||
|
this.score += data.getScore();
|
||||||
|
}
|
||||||
|
|
||||||
// Complete
|
// Complete
|
||||||
return this.score;
|
return this.score;
|
||||||
}
|
}
|
||||||
@@ -204,6 +216,11 @@ public class StarTowerBuild implements GameDatabaseObject {
|
|||||||
proto.addSubNoteSkills(skill);
|
proto.addSubNoteSkills(skill);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Secondary skills
|
||||||
|
for (int id : this.getSecondarySkills()) {
|
||||||
|
proto.addActiveSecondaryIds(id);
|
||||||
|
}
|
||||||
|
|
||||||
return proto;
|
return proto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,11 @@ import dev.morphia.annotations.Entity;
|
|||||||
|
|
||||||
import emu.nebula.GameConstants;
|
import emu.nebula.GameConstants;
|
||||||
import emu.nebula.data.GameData;
|
import emu.nebula.data.GameData;
|
||||||
|
import emu.nebula.data.resources.SecondarySkillDef;
|
||||||
import emu.nebula.data.resources.StarTowerDef;
|
import emu.nebula.data.resources.StarTowerDef;
|
||||||
import emu.nebula.data.resources.StarTowerStageDef;
|
import emu.nebula.data.resources.StarTowerStageDef;
|
||||||
|
import emu.nebula.game.character.GameCharacter;
|
||||||
|
import emu.nebula.game.character.GameDisc;
|
||||||
import emu.nebula.game.formation.Formation;
|
import emu.nebula.game.formation.Formation;
|
||||||
import emu.nebula.game.inventory.ItemParamMap;
|
import emu.nebula.game.inventory.ItemParamMap;
|
||||||
import emu.nebula.game.player.Player;
|
import emu.nebula.game.player.Player;
|
||||||
@@ -34,7 +37,8 @@ import emu.nebula.util.Utils;
|
|||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||||
import it.unimi.dsi.fastutil.ints.IntList;
|
import it.unimi.dsi.fastutil.ints.IntList;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import us.hebi.quickbuf.RepeatedMessage;
|
import us.hebi.quickbuf.RepeatedMessage;
|
||||||
@@ -64,9 +68,8 @@ public class StarTowerGame {
|
|||||||
private int nextLevelExp;
|
private int nextLevelExp;
|
||||||
private int charHp;
|
private int charHp;
|
||||||
private int battleTime;
|
private int battleTime;
|
||||||
private List<StarTowerChar> chars;
|
private int[] charIds;
|
||||||
private List<StarTowerDisc> discs;
|
private int[] discIds;
|
||||||
private IntList charIds;
|
|
||||||
|
|
||||||
private int pendingPotentialCases = 0;
|
private int pendingPotentialCases = 0;
|
||||||
private int pendingSubNotes = 0;
|
private int pendingSubNotes = 0;
|
||||||
@@ -75,6 +78,7 @@ public class StarTowerGame {
|
|||||||
private ItemParamMap items;
|
private ItemParamMap items;
|
||||||
private ItemParamMap res;
|
private ItemParamMap res;
|
||||||
private ItemParamMap potentials;
|
private ItemParamMap potentials;
|
||||||
|
private IntSet secondarySkills;
|
||||||
|
|
||||||
// Sub note skill drop list
|
// Sub note skill drop list
|
||||||
private IntList subNoteDropList;
|
private IntList subNoteDropList;
|
||||||
@@ -86,10 +90,6 @@ public class StarTowerGame {
|
|||||||
private transient StarTowerBuild build;
|
private transient StarTowerBuild build;
|
||||||
private transient ItemParamMap newInfos;
|
private transient ItemParamMap newInfos;
|
||||||
|
|
||||||
private static final int[] COMMON_SUB_NOTE_SKILLS = new int[] {
|
|
||||||
90011, 90012, 90013, 90014, 90015, 90016, 90017
|
|
||||||
};
|
|
||||||
|
|
||||||
@Deprecated // Morphia only
|
@Deprecated // Morphia only
|
||||||
public StarTowerGame() {
|
public StarTowerGame() {
|
||||||
|
|
||||||
@@ -114,70 +114,75 @@ public class StarTowerGame {
|
|||||||
this.teamExp = 0;
|
this.teamExp = 0;
|
||||||
this.nextLevelExp = GameData.getStarTowerTeamExpDataTable().get(2).getNeedExp();
|
this.nextLevelExp = GameData.getStarTowerTeamExpDataTable().get(2).getNeedExp();
|
||||||
this.charHp = -1;
|
this.charHp = -1;
|
||||||
this.chars = new ArrayList<>();
|
|
||||||
this.discs = new ArrayList<>();
|
|
||||||
this.charIds = new IntArrayList();
|
|
||||||
|
|
||||||
this.items = new ItemParamMap();
|
this.items = new ItemParamMap();
|
||||||
this.res = new ItemParamMap();
|
this.res = new ItemParamMap();
|
||||||
this.potentials = new ItemParamMap();
|
this.potentials = new ItemParamMap();
|
||||||
|
this.secondarySkills = new IntOpenHashSet();
|
||||||
|
|
||||||
this.newInfos = new ItemParamMap();
|
this.newInfos = new ItemParamMap();
|
||||||
|
|
||||||
// Melody skill drop list
|
// Init melody drop list
|
||||||
this.subNoteDropList = new IntArrayList();
|
this.subNoteDropList = new IntArrayList();
|
||||||
|
|
||||||
// Init modifiers
|
// Init modifiers
|
||||||
this.modifiers = new StarTowerModifiers(this);
|
this.modifiers = new StarTowerModifiers(this);
|
||||||
|
|
||||||
// Init formation
|
// Init formation
|
||||||
|
IntList charList = new IntArrayList();
|
||||||
|
IntList discList = new IntArrayList();
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
int id = formation.getCharIdAt(i);
|
int id = formation.getCharIdAt(i);
|
||||||
var character = getPlayer().getCharacters().getCharacterById(id);
|
var character = getPlayer().getCharacters().getCharacterById(id);
|
||||||
|
|
||||||
if (character != null) {
|
if (character == null) {
|
||||||
// Add to character id list
|
continue;
|
||||||
this.charIds.add(id);
|
|
||||||
|
|
||||||
// Add sub note skill id to drop list
|
|
||||||
int subNoteSkill = character.getData().getElementType().getSubNoteSkillItemId();
|
|
||||||
if (subNoteSkill > 0 && !this.subNoteDropList.contains(subNoteSkill)) {
|
|
||||||
this.subNoteDropList.add(subNoteSkill);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.chars.add(character.toStarTowerProto());
|
|
||||||
} else {
|
|
||||||
this.chars.add(StarTowerChar.newInstance());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add sub note skill id to drop list
|
||||||
|
int subNoteSkill = character.getData().getElementType().getSubNoteSkillItemId();
|
||||||
|
if (subNoteSkill > 0 && !this.subNoteDropList.contains(subNoteSkill)) {
|
||||||
|
this.subNoteDropList.add(subNoteSkill);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to character list
|
||||||
|
charList.add(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
int id = formation.getDiscIdAt(i);
|
int id = formation.getDiscIdAt(i);
|
||||||
var disc = getPlayer().getCharacters().getDiscById(id);
|
var disc = getPlayer().getCharacters().getDiscById(id);
|
||||||
|
|
||||||
if (disc != null) {
|
if (disc == null) {
|
||||||
this.discs.add(disc.toStarTowerProto());
|
continue;
|
||||||
|
|
||||||
// Add star tower sub note skills
|
|
||||||
if (i >= 3) {
|
|
||||||
var subNoteData = disc.getSubNoteSkillDef();
|
|
||||||
if (subNoteData != null) {
|
|
||||||
this.getItems().add(subNoteData.getItems());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.discs.add(StarTowerDisc.newInstance());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add star tower sub note skills from disc
|
||||||
|
if (i >= 3) {
|
||||||
|
var subNoteData = disc.getSubNoteSkillDef();
|
||||||
|
if (subNoteData != null) {
|
||||||
|
this.getItems().add(subNoteData.getItems());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add to disc list
|
||||||
|
discList.add(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge char/disc ids into an array for optimization
|
||||||
|
this.charIds = charList.toIntArray();
|
||||||
|
this.discIds = discList.toIntArray();
|
||||||
|
|
||||||
// Finish setting up droppable sub note skills
|
// Finish setting up droppable sub note skills
|
||||||
for (int id : COMMON_SUB_NOTE_SKILLS) {
|
for (int id : GameConstants.TOWER_COMMON_SUB_NOTE_SKILLS) {
|
||||||
this.subNoteDropList.add(id);
|
this.subNoteDropList.add(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add starting coin directly
|
// Add starting coin directly
|
||||||
int coin = this.getModifiers().getStartingCoin();
|
int coin = this.getModifiers().getStartingCoin();
|
||||||
if (coin > 0) {
|
if (coin > 0) {
|
||||||
this.getRes().add(GameConstants.STAR_TOWER_COIN_ITEM_ID, coin);
|
this.getRes().add(GameConstants.TOWER_COIN_ITEM_ID, coin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,6 +202,24 @@ public class StarTowerGame {
|
|||||||
return this.getData().getDifficulty();
|
return this.getData().getDifficulty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GameCharacter getCharByIndex(int index) {
|
||||||
|
if (index < 0 || index >= this.getCharIds().length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int id = this.getCharIds()[index];
|
||||||
|
return this.getPlayer().getCharacters().getCharacterById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameDisc getDiscByIndex(int index) {
|
||||||
|
if (index < 0 || index >= this.getDiscIds().length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
int id = this.getDiscIds()[index];
|
||||||
|
return this.getPlayer().getCharacters().getDiscById(id);
|
||||||
|
}
|
||||||
|
|
||||||
public int getRandomCharId() {
|
public int getRandomCharId() {
|
||||||
return Utils.randomElement(this.getCharIds());
|
return Utils.randomElement(this.getCharIds());
|
||||||
}
|
}
|
||||||
@@ -372,6 +395,11 @@ public class StarTowerGame {
|
|||||||
change.add(info);
|
change.add(info);
|
||||||
}
|
}
|
||||||
case SubNoteSkill -> {
|
case SubNoteSkill -> {
|
||||||
|
// Sanity check to make sure we dont remove more than what we have
|
||||||
|
if (count < 0) {
|
||||||
|
count = Math.max(count, -this.getItems().get(id));
|
||||||
|
}
|
||||||
|
|
||||||
// Add to items
|
// Add to items
|
||||||
this.getItems().add(id, count);
|
this.getItems().add(id, count);
|
||||||
|
|
||||||
@@ -386,6 +414,11 @@ public class StarTowerGame {
|
|||||||
this.getNewInfos().add(id, count);
|
this.getNewInfos().add(id, count);
|
||||||
}
|
}
|
||||||
case Res -> {
|
case Res -> {
|
||||||
|
// Sanity check to make sure we dont remove more than what we have
|
||||||
|
if (count < 0) {
|
||||||
|
count = Math.max(count, -this.getRes().get(id));
|
||||||
|
}
|
||||||
|
|
||||||
// Add to res
|
// Add to res
|
||||||
this.getRes().add(id, count);
|
this.getRes().add(id, count);
|
||||||
|
|
||||||
@@ -461,10 +494,14 @@ public class StarTowerGame {
|
|||||||
return this.createPotentialSelector(0);
|
return this.createPotentialSelector(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public StarTowerBaseCase createPotentialSelector(int charId) {
|
||||||
|
return this.createPotentialSelector(charId, false);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a potential selector for the specified character
|
* Creates a potential selector for the specified character
|
||||||
*/
|
*/
|
||||||
public StarTowerBaseCase createPotentialSelector(int charId) {
|
public StarTowerBaseCase createPotentialSelector(int charId, boolean rareOnly) {
|
||||||
// Check character id
|
// Check character id
|
||||||
if (charId <= 0) {
|
if (charId <= 0) {
|
||||||
charId = this.getRandomCharId();
|
charId = this.getRandomCharId();
|
||||||
@@ -480,17 +517,25 @@ public class StarTowerGame {
|
|||||||
var list = new IntArrayList();
|
var list = new IntArrayList();
|
||||||
|
|
||||||
// Add potentials based on character role
|
// Add potentials based on character role
|
||||||
boolean isMainCharacter = this.getCharIds().getInt(0) == charId;
|
boolean isMainCharacter = this.getCharIds()[0] == charId;
|
||||||
|
|
||||||
if (isMainCharacter) {
|
if (isMainCharacter) {
|
||||||
list.addElements(0, data.getMasterSpecificPotentialIds());
|
list.addElements(0, data.getMasterSpecificPotentialIds());
|
||||||
list.addElements(0, data.getMasterNormalPotentialIds());
|
|
||||||
|
if (!rareOnly) {
|
||||||
|
list.addElements(0, data.getMasterNormalPotentialIds());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
list.addElements(0, data.getAssistSpecificPotentialIds());
|
list.addElements(0, data.getAssistSpecificPotentialIds());
|
||||||
list.addElements(0, data.getAssistNormalPotentialIds());
|
|
||||||
|
if (!rareOnly) {
|
||||||
|
list.addElements(0, data.getAssistNormalPotentialIds());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list.addElements(0, data.getCommonPotentialIds());
|
if (!rareOnly) {
|
||||||
|
list.addElements(0, data.getCommonPotentialIds());
|
||||||
|
}
|
||||||
|
|
||||||
// Remove potentials we already have maxed out
|
// Remove potentials we already have maxed out
|
||||||
var potentials = new IntArrayList();
|
var potentials = new IntArrayList();
|
||||||
@@ -590,9 +635,13 @@ public class StarTowerGame {
|
|||||||
this.pendingSubNotes = amount;
|
this.pendingSubNotes = amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getRandomSubNoteId() {
|
||||||
|
return Utils.randomElement(this.getSubNoteDropList());
|
||||||
|
}
|
||||||
|
|
||||||
private PlayerChangeInfo addRandomSubNoteSkills(PlayerChangeInfo change) {
|
private PlayerChangeInfo addRandomSubNoteSkills(PlayerChangeInfo change) {
|
||||||
|
int id = this.getRandomSubNoteId();
|
||||||
int count = Utils.randomRange(1, 3);
|
int count = Utils.randomRange(1, 3);
|
||||||
int id = Utils.randomElement(this.getSubNoteDropList());
|
|
||||||
|
|
||||||
this.addItem(id, count, change);
|
this.addItem(id, count, change);
|
||||||
|
|
||||||
@@ -637,11 +686,11 @@ public class StarTowerGame {
|
|||||||
rsp.getMutableNilResp();
|
rsp.getMutableNilResp();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add any items
|
// Add any sub note skills
|
||||||
var data = rsp.getMutableData();
|
var data = rsp.getMutableData();
|
||||||
|
|
||||||
if (this.getNewInfos().size() > 0) {
|
if (this.getNewInfos().size() > 0) {
|
||||||
// Add item protos
|
// Add sub note skills to the proto
|
||||||
for (var entry : this.getNewInfos()) {
|
for (var entry : this.getNewInfos()) {
|
||||||
var info = SubNoteSkillInfo.newInstance()
|
var info = SubNoteSkillInfo.newInstance()
|
||||||
.setTid(entry.getIntKey())
|
.setTid(entry.getIntKey())
|
||||||
@@ -650,11 +699,39 @@ public class StarTowerGame {
|
|||||||
data.getMutableInfos().add(info);
|
data.getMutableInfos().add(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear
|
// Refresh secondary skills
|
||||||
|
var newSecondarySkills = SecondarySkillDef.calculateSecondarySkills(this.getDiscIds(), this.getItems());
|
||||||
|
|
||||||
|
// Add any new secondary skills to the data proto
|
||||||
|
for (int id : newSecondarySkills) {
|
||||||
|
if (!this.getSecondarySkills().contains(id)) {
|
||||||
|
var info = ActiveSecondaryChange.newInstance()
|
||||||
|
.setSecondaryId(id)
|
||||||
|
.setActive(true);
|
||||||
|
|
||||||
|
data.addSecondaries(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inform the client that these skills are no longer active
|
||||||
|
for (int id : this.getSecondarySkills()) {
|
||||||
|
if (!newSecondarySkills.contains(id)) {
|
||||||
|
var info = ActiveSecondaryChange.newInstance()
|
||||||
|
.setSecondaryId(id)
|
||||||
|
.setActive(false);
|
||||||
|
|
||||||
|
data.addSecondaries(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set new secondary skills
|
||||||
|
this.secondarySkills = newSecondarySkills;
|
||||||
|
|
||||||
|
// Clear new infos
|
||||||
this.getNewInfos().clear();
|
this.getNewInfos().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set these protos
|
// Always add this proto
|
||||||
rsp.getMutableChange();
|
rsp.getMutableChange();
|
||||||
|
|
||||||
// Return response proto
|
// Return response proto
|
||||||
@@ -687,15 +764,38 @@ public class StarTowerGame {
|
|||||||
public StarTowerInfo toProto() {
|
public StarTowerInfo toProto() {
|
||||||
var proto = StarTowerInfo.newInstance();
|
var proto = StarTowerInfo.newInstance();
|
||||||
|
|
||||||
proto.getMutableMeta()
|
var meta = proto.getMutableMeta()
|
||||||
.setId(this.getId())
|
.setId(this.getId())
|
||||||
.setCharHp(this.getCharHp())
|
.setCharHp(this.getCharHp())
|
||||||
.setTeamLevel(this.getTeamLevel())
|
.setTeamLevel(this.getTeamLevel())
|
||||||
.setNPCInteractions(1)
|
.setNPCInteractions(0)
|
||||||
|
.setTotalTime(this.getBattleTime())
|
||||||
.setBuildId(this.getBuildId());
|
.setBuildId(this.getBuildId());
|
||||||
|
|
||||||
this.getChars().forEach(proto.getMutableMeta()::addChars);
|
// Set characters + discs
|
||||||
this.getDiscs().forEach(proto.getMutableMeta()::addDiscs);
|
for (int i = 0; i < 3; i++) {
|
||||||
|
var character = this.getCharByIndex(i);
|
||||||
|
|
||||||
|
if (character != null) {
|
||||||
|
meta.addChars(character.toStarTowerProto());
|
||||||
|
} else {
|
||||||
|
meta.addChars(StarTowerChar.newInstance());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
var disc = this.getDiscByIndex(i);
|
||||||
|
|
||||||
|
if (disc != null) {
|
||||||
|
meta.addDiscs(disc.toStarTowerProto());
|
||||||
|
} else {
|
||||||
|
meta.addDiscs(StarTowerDisc.newInstance());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add secondary skills
|
||||||
|
for (int id : this.getSecondarySkills()) {
|
||||||
|
meta.addActiveSecondaryIds(id);
|
||||||
|
}
|
||||||
|
|
||||||
// Set room data
|
// Set room data
|
||||||
proto.setRoom(this.getRoom().toProto());
|
proto.setRoom(this.getRoom().toProto());
|
||||||
|
|||||||
@@ -327,9 +327,18 @@ public class StarTowerManager extends PlayerManager {
|
|||||||
// Database
|
// Database
|
||||||
|
|
||||||
public void loadFromDatabase() {
|
public void loadFromDatabase() {
|
||||||
|
// Init builds
|
||||||
this.builds = new Long2ObjectOpenHashMap<>();
|
this.builds = new Long2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
|
// Load builds with the current player's uid
|
||||||
Nebula.getGameDatabase().getObjects(StarTowerBuild.class, "playerUid", getPlayerUid()).forEach(build -> {
|
Nebula.getGameDatabase().getObjects(StarTowerBuild.class, "playerUid", getPlayerUid()).forEach(build -> {
|
||||||
|
// Fix outdated builds
|
||||||
|
if (build.getSecondarySkills() == null) {
|
||||||
|
build.calculateScore();
|
||||||
|
build.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add build
|
||||||
this.builds.put(build.getUid(), build);
|
this.builds.put(build.getUid(), build);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,6 @@ public class StarTowerShopGoods {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int index = this.getCharPos() - 1;
|
int index = this.getCharPos() - 1;
|
||||||
return game.getCharIds().getInt(index);
|
return game.getCharIds()[index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ public class StarTowerBattleCase extends StarTowerBaseCase {
|
|||||||
// Add coin
|
// Add coin
|
||||||
int coin = this.getRoom().getStage().getInteriorCurrencyQuantity();
|
int coin = this.getRoom().getStage().getInteriorCurrencyQuantity();
|
||||||
|
|
||||||
this.getGame().addItem(GameConstants.STAR_TOWER_COIN_ITEM_ID, coin, change);
|
this.getGame().addItem(GameConstants.TOWER_COIN_ITEM_ID, coin, change);
|
||||||
|
|
||||||
// Handle pending potential selectors
|
// Handle pending potential selectors
|
||||||
var nextCases = this.getGame().handlePendingPotentialSelectors();
|
var nextCases = this.getGame().handlePendingPotentialSelectors();
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ public class StarTowerHawkerCase extends StarTowerBaseCase {
|
|||||||
this.addGoods(goods);
|
this.addGoods(goods);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply discounts based on star tower talents
|
// Apply discounts based on star tower growth nodes
|
||||||
if (getModifiers().isShopDiscountTier1()) {
|
if (getModifiers().isShopDiscountTier1()) {
|
||||||
this.applyDiscount(1.0, 2, 0.8);
|
this.applyDiscount(1.0, 2, 0.8);
|
||||||
}
|
}
|
||||||
@@ -141,7 +141,7 @@ public class StarTowerHawkerCase extends StarTowerBaseCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we have enough currency
|
// Make sure we have enough currency
|
||||||
int coin = this.getGame().getResCount(GameConstants.STAR_TOWER_COIN_ITEM_ID);
|
int coin = this.getGame().getResCount(GameConstants.TOWER_COIN_ITEM_ID);
|
||||||
int price = this.getModifiers().getShopRerollPrice();
|
int price = this.getModifiers().getShopRerollPrice();
|
||||||
|
|
||||||
if (coin < price) {
|
if (coin < price) {
|
||||||
@@ -159,7 +159,7 @@ public class StarTowerHawkerCase extends StarTowerBaseCase {
|
|||||||
.setHawkerCase(this.toHawkerCaseProto());
|
.setHawkerCase(this.toHawkerCaseProto());
|
||||||
|
|
||||||
// Remove coins
|
// Remove coins
|
||||||
var change = this.getGame().addItem(GameConstants.STAR_TOWER_COIN_ITEM_ID, -price);
|
var change = this.getGame().addItem(GameConstants.TOWER_COIN_ITEM_ID, -price);
|
||||||
|
|
||||||
// Set change info
|
// Set change info
|
||||||
rsp.setChange(change.toProto());
|
rsp.setChange(change.toProto());
|
||||||
@@ -173,7 +173,7 @@ public class StarTowerHawkerCase extends StarTowerBaseCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we have enough currency
|
// Make sure we have enough currency
|
||||||
int coin = this.getGame().getResCount(GameConstants.STAR_TOWER_COIN_ITEM_ID);
|
int coin = this.getGame().getResCount(GameConstants.TOWER_COIN_ITEM_ID);
|
||||||
int price = goods.getPrice();
|
int price = goods.getPrice();
|
||||||
|
|
||||||
if (coin < price || goods.isSold()) {
|
if (coin < price || goods.isSold()) {
|
||||||
@@ -197,7 +197,7 @@ public class StarTowerHawkerCase extends StarTowerBaseCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove coins
|
// Remove coins
|
||||||
this.getGame().addItem(GameConstants.STAR_TOWER_COIN_ITEM_ID, -price, change);
|
this.getGame().addItem(GameConstants.TOWER_COIN_ITEM_ID, -price, change);
|
||||||
|
|
||||||
// Set change info
|
// Set change info
|
||||||
rsp.setChange(change.toProto());
|
rsp.setChange(change.toProto());
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
package emu.nebula.game.tower.cases;
|
package emu.nebula.game.tower.cases;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import emu.nebula.GameConstants;
|
||||||
|
import emu.nebula.data.resources.StarTowerEventDef;
|
||||||
|
import emu.nebula.game.player.PlayerChangeInfo;
|
||||||
|
import emu.nebula.proto.PublicStarTower.NPCAffinityInfo;
|
||||||
import emu.nebula.proto.PublicStarTower.StarTowerRoomCase;
|
import emu.nebula.proto.PublicStarTower.StarTowerRoomCase;
|
||||||
import emu.nebula.proto.StarTowerInteract.StarTowerInteractReq;
|
import emu.nebula.proto.StarTowerInteract.StarTowerInteractReq;
|
||||||
import emu.nebula.proto.StarTowerInteract.StarTowerInteractResp;
|
import emu.nebula.proto.StarTowerInteract.StarTowerInteractResp;
|
||||||
|
import emu.nebula.util.Utils;
|
||||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||||
import it.unimi.dsi.fastutil.ints.IntList;
|
import it.unimi.dsi.fastutil.ints.IntList;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@@ -12,11 +19,32 @@ public class StarTowerNpcEventCase extends StarTowerBaseCase {
|
|||||||
private int npcId;
|
private int npcId;
|
||||||
private int eventId;
|
private int eventId;
|
||||||
private IntList options;
|
private IntList options;
|
||||||
|
private boolean completed;
|
||||||
|
|
||||||
public StarTowerNpcEventCase(int npcId, int eventId) {
|
public StarTowerNpcEventCase(int npcId, StarTowerEventDef event) {
|
||||||
this.npcId = npcId;
|
this.npcId = npcId;
|
||||||
this.eventId = eventId;
|
this.eventId = event.getId();
|
||||||
this.options = new IntArrayList();
|
this.options = new IntArrayList();
|
||||||
|
|
||||||
|
// Add up to 4 random options
|
||||||
|
var randomOptions = event.getClonedOptionIds();
|
||||||
|
int maxOptions = Math.min(randomOptions.size(), 4);
|
||||||
|
|
||||||
|
for (int i = 0; i < maxOptions; i++) {
|
||||||
|
int optionId = Utils.randomElement(randomOptions, true);
|
||||||
|
this.options.add(optionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix for question type events to always include the answer
|
||||||
|
if (this.eventId >= 114 && this.eventId <= 116) {
|
||||||
|
int answerId = (this.eventId * 100) + 3;
|
||||||
|
if (!this.getOptions().contains(answerId)) {
|
||||||
|
this.getOptions().set(0, answerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shuffle
|
||||||
|
Collections.shuffle(this.getOptions());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -24,18 +52,267 @@ public class StarTowerNpcEventCase extends StarTowerBaseCase {
|
|||||||
return CaseType.NpcEvent;
|
return CaseType.NpcEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getOption(int index) {
|
||||||
|
if (index < 0 || index >= this.getOptions().size()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.getOptions().getInt(index);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public StarTowerInteractResp interact(StarTowerInteractReq req, StarTowerInteractResp rsp) {
|
public StarTowerInteractResp interact(StarTowerInteractReq req, StarTowerInteractResp rsp) {
|
||||||
|
// Sanity check to make sure we cant do the event multiple times
|
||||||
|
if (this.isCompleted()) {
|
||||||
|
return rsp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get option from selection index
|
||||||
|
int option = this.getOption(req.getSelectReq().getIndex());
|
||||||
|
|
||||||
|
// Get select response proto
|
||||||
|
var selectRsp = rsp.getMutableSelectResp();
|
||||||
|
var success = selectRsp.getMutableResp();
|
||||||
|
var change = new PlayerChangeInfo();
|
||||||
|
|
||||||
|
// Completed event flag
|
||||||
|
boolean completed = true;
|
||||||
|
|
||||||
|
// Handle option id
|
||||||
|
switch (option) {
|
||||||
|
case 10101 -> {
|
||||||
|
if (this.spendCoin(100, change)) {
|
||||||
|
this.addPotentialSelector(rsp);
|
||||||
|
} else {
|
||||||
|
completed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 10102 -> {
|
||||||
|
if (this.spendCoin(120, change)) {
|
||||||
|
this.addPotentialSelector(rsp);
|
||||||
|
} else {
|
||||||
|
completed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 10103 -> {
|
||||||
|
this.addCoin(30, change);
|
||||||
|
}
|
||||||
|
case 10201 -> {
|
||||||
|
if (this.spendCoin(120, change)) {
|
||||||
|
this.addPotentialSelector(rsp, this.getRandomSupportCharId());
|
||||||
|
} else {
|
||||||
|
completed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 10202 -> {
|
||||||
|
if (this.spendCoin(160, change)) {
|
||||||
|
this.addPotentialSelector(rsp, this.getMainCharId());
|
||||||
|
} else {
|
||||||
|
completed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 10203 -> {
|
||||||
|
if (this.spendCoin(200, change)) {
|
||||||
|
this.addRarePotentialSelector(rsp);
|
||||||
|
} else {
|
||||||
|
completed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 10204 -> {
|
||||||
|
this.addCoin(30, change);
|
||||||
|
}
|
||||||
|
case 10302 -> {
|
||||||
|
// TODO
|
||||||
|
if (this.spendSubNotes(5, change)) {
|
||||||
|
this.addCoin(150, change);
|
||||||
|
} else {
|
||||||
|
completed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 10303 -> {
|
||||||
|
this.addCoin(30, change);
|
||||||
|
}
|
||||||
|
case 10401 -> {
|
||||||
|
// TODO
|
||||||
|
completed = false;
|
||||||
|
}
|
||||||
|
case 10402 -> {
|
||||||
|
if (this.spendCoin(200, change)) {
|
||||||
|
this.addRarePotentialSelector(rsp);
|
||||||
|
} else {
|
||||||
|
completed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 10403 -> {
|
||||||
|
this.addCoin(30, change);
|
||||||
|
}
|
||||||
|
case 10501 -> {
|
||||||
|
if (Utils.randomChance(.5)) {
|
||||||
|
this.addCoin(200, change);
|
||||||
|
} else {
|
||||||
|
this.addCoin(-100, change);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 10502 -> {
|
||||||
|
if (Utils.randomChance(.3)) {
|
||||||
|
this.addCoin(650, change);
|
||||||
|
} else {
|
||||||
|
this.addCoin(-200, change);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 10503 -> {
|
||||||
|
this.addCoin(30, change);
|
||||||
|
}
|
||||||
|
case 10601 -> {
|
||||||
|
if (Utils.randomChance(.5)) {
|
||||||
|
this.addRarePotentialSelector(rsp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 10602 -> {
|
||||||
|
this.addPotentialSelector(rsp);
|
||||||
|
}
|
||||||
|
case 10603 -> {
|
||||||
|
this.addCoin(30, change);
|
||||||
|
}
|
||||||
|
case 10701, 10702, 10703, 10704, 10705, 10706, 10707 -> {
|
||||||
|
int subNoteId = (option % 100) + 90010;
|
||||||
|
this.getGame().addItem(subNoteId, 5, change);
|
||||||
|
}
|
||||||
|
case 10708 -> {
|
||||||
|
int subNoteId = this.getGame().getRandomSubNoteId();
|
||||||
|
this.getGame().addItem(subNoteId, 5, change);
|
||||||
|
}
|
||||||
|
case 10801, 10802, 10803, 10804, 10805, 10806, 10807 -> {
|
||||||
|
if (this.spendCoin(140, change)) {
|
||||||
|
int subNoteId = (option % 100) + 90010;
|
||||||
|
this.getGame().addItem(subNoteId, 10, change);
|
||||||
|
} else {
|
||||||
|
completed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 10808 -> {
|
||||||
|
if (this.spendCoin(90, change)) {
|
||||||
|
int subNoteId = this.getGame().getRandomSubNoteId();
|
||||||
|
this.getGame().addItem(subNoteId, 10, change);
|
||||||
|
} else {
|
||||||
|
completed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 10809 -> {
|
||||||
|
this.addCoin(30, change);
|
||||||
|
}
|
||||||
|
case 11401, 11402, 11403, 11404, 11405 -> {
|
||||||
|
if (option == 11403) {
|
||||||
|
int subNoteId = this.getGame().getRandomSubNoteId();
|
||||||
|
this.getGame().addItem(subNoteId, 10, change);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 11501, 11502, 11503, 11504, 11505 -> {
|
||||||
|
if (option == 11503) {
|
||||||
|
this.addPotentialSelector(rsp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 11601, 11602, 11603, 11604, 11605 -> {
|
||||||
|
if (option == 11603) {
|
||||||
|
this.addRarePotentialSelector(rsp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 12601 -> {
|
||||||
|
this.addPotentialSelector(rsp, this.getRandomSupportCharId());
|
||||||
|
}
|
||||||
|
case 12602 -> {
|
||||||
|
// Recover 20% hp
|
||||||
|
}
|
||||||
|
case 12701 -> {
|
||||||
|
this.addPotentialSelector(rsp, this.getRandomSupportCharId());
|
||||||
|
}
|
||||||
|
case 12702 -> {
|
||||||
|
int subNoteId = this.getGame().getRandomSubNoteId();
|
||||||
|
this.getGame().addItem(subNoteId, 5, change);
|
||||||
|
}
|
||||||
|
case 12801 -> {
|
||||||
|
this.addRarePotentialSelector(rsp, this.getRandomSupportCharId());
|
||||||
|
}
|
||||||
|
case 12802 -> {
|
||||||
|
this.addCoin(30, change);
|
||||||
|
}
|
||||||
|
default -> {
|
||||||
|
// Ignored
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set change info
|
||||||
|
rsp.setChange(change.toProto());
|
||||||
|
|
||||||
|
// Set success result
|
||||||
|
success.setOptionsResult(completed);
|
||||||
|
this.completed = completed;
|
||||||
|
|
||||||
|
// Complete
|
||||||
return rsp;
|
return rsp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper functions
|
||||||
|
|
||||||
|
private boolean spendCoin(int amount, PlayerChangeInfo change) {
|
||||||
|
int coin = this.getGame().getResCount(GameConstants.TOWER_COIN_ITEM_ID);
|
||||||
|
|
||||||
|
if (coin < amount) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.addCoin(-amount, change);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PlayerChangeInfo addCoin(int amount, PlayerChangeInfo change) {
|
||||||
|
return this.getGame().addItem(GameConstants.TOWER_COIN_ITEM_ID, amount, change);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean spendSubNotes(int amount, PlayerChangeInfo change) {
|
||||||
|
// TODO
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addPotentialSelector(StarTowerInteractResp rsp) {
|
||||||
|
this.addPotentialSelector(rsp, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addPotentialSelector(StarTowerInteractResp rsp, int charId) {
|
||||||
|
var selectorCase = this.getGame().createPotentialSelector(charId);
|
||||||
|
this.getRoom().addCase(rsp.getMutableCases(), selectorCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addRarePotentialSelector(StarTowerInteractResp rsp) {
|
||||||
|
this.addRarePotentialSelector(rsp, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addRarePotentialSelector(StarTowerInteractResp rsp, int charId) {
|
||||||
|
var selectorCase = this.getGame().createPotentialSelector(charId, true);
|
||||||
|
this.getRoom().addCase(rsp.getMutableCases(), selectorCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getMainCharId() {
|
||||||
|
return this.getGame().getCharIds()[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getRandomSupportCharId() {
|
||||||
|
return this.getGame().getCharIds()[Utils.randomRange(1, 2)];
|
||||||
|
}
|
||||||
|
|
||||||
// Proto
|
// Proto
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void encodeProto(StarTowerRoomCase proto) {
|
public void encodeProto(StarTowerRoomCase proto) {
|
||||||
|
var info = NPCAffinityInfo.newInstance()
|
||||||
|
.setNPCId(this.getNpcId())
|
||||||
|
.setAffinity(0);
|
||||||
|
|
||||||
proto.getMutableSelectOptionsEventCase()
|
proto.getMutableSelectOptionsEventCase()
|
||||||
.setEvtId(this.getEventId())
|
.setEvtId(this.getEventId())
|
||||||
.setNPCId(this.getNpcId())
|
.setNPCId(this.getNpcId())
|
||||||
|
.addInfos(info)
|
||||||
.addAllOptions(this.getOptions().toIntArray());
|
.addAllOptions(this.getOptions().toIntArray());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public class StarTowerStrengthenMachineCase extends StarTowerBaseCase {
|
|||||||
StarTowerBaseCase towerCase = null;
|
StarTowerBaseCase towerCase = null;
|
||||||
|
|
||||||
// Check coin
|
// Check coin
|
||||||
int coin = getGame().getResCount(GameConstants.STAR_TOWER_COIN_ITEM_ID);
|
int coin = getGame().getResCount(GameConstants.TOWER_COIN_ITEM_ID);
|
||||||
int price = this.getPrice();
|
int price = this.getPrice();
|
||||||
|
|
||||||
if (coin >= price) {
|
if (coin >= price) {
|
||||||
@@ -62,7 +62,7 @@ public class StarTowerStrengthenMachineCase extends StarTowerBaseCase {
|
|||||||
this.getRoom().addCase(rsp.getMutableCases(), towerCase);
|
this.getRoom().addCase(rsp.getMutableCases(), towerCase);
|
||||||
|
|
||||||
// Remove coins
|
// Remove coins
|
||||||
var change = this.getGame().addItem(GameConstants.STAR_TOWER_COIN_ITEM_ID, -price);
|
var change = this.getGame().addItem(GameConstants.TOWER_COIN_ITEM_ID, -price);
|
||||||
|
|
||||||
// Set change info
|
// Set change info
|
||||||
rsp.setChange(change.toProto());
|
rsp.setChange(change.toProto());
|
||||||
|
|||||||
@@ -90,6 +90,11 @@ public class StarTowerBaseRoom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public StarTowerBaseCase addCase(RepeatedMessage<StarTowerRoomCase> cases, StarTowerBaseCase towerCase) {
|
public StarTowerBaseCase addCase(RepeatedMessage<StarTowerRoomCase> cases, StarTowerBaseCase towerCase) {
|
||||||
|
// Sanity check
|
||||||
|
if (towerCase == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// Set game for tower case
|
// Set game for tower case
|
||||||
towerCase.register(this);
|
towerCase.register(this);
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,17 @@
|
|||||||
package emu.nebula.game.tower.room;
|
package emu.nebula.game.tower.room;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import emu.nebula.GameConstants;
|
||||||
|
import emu.nebula.data.GameData;
|
||||||
|
import emu.nebula.data.resources.StarTowerEventDef;
|
||||||
import emu.nebula.data.resources.StarTowerStageDef;
|
import emu.nebula.data.resources.StarTowerStageDef;
|
||||||
import emu.nebula.game.tower.StarTowerGame;
|
import emu.nebula.game.tower.StarTowerGame;
|
||||||
|
import emu.nebula.game.tower.cases.StarTowerBaseCase;
|
||||||
|
import emu.nebula.game.tower.cases.StarTowerNpcEventCase;
|
||||||
import emu.nebula.game.tower.cases.StarTowerSyncHPCase;
|
import emu.nebula.game.tower.cases.StarTowerSyncHPCase;
|
||||||
|
import emu.nebula.util.Utils;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
@@ -12,9 +21,47 @@ public class StarTowerEventRoom extends StarTowerBaseRoom {
|
|||||||
public StarTowerEventRoom(StarTowerGame game, StarTowerStageDef stage) {
|
public StarTowerEventRoom(StarTowerGame game, StarTowerStageDef stage) {
|
||||||
super(game, stage);
|
super(game, stage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private StarTowerEventDef getRandomEvent() {
|
||||||
|
/*
|
||||||
|
var list = GameData.getStarTowerEventDataTable()
|
||||||
|
.values()
|
||||||
|
.stream()
|
||||||
|
.toList();
|
||||||
|
*/
|
||||||
|
|
||||||
|
var list = Arrays.stream(GameConstants.TOWER_EVENTS_IDS)
|
||||||
|
.mapToObj(GameData.getStarTowerEventDataTable()::get)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
if (list.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Utils.randomElement(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StarTowerBaseCase createNpcEvent() {
|
||||||
|
// Get random event
|
||||||
|
var event = this.getRandomEvent();
|
||||||
|
|
||||||
|
if (event == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get random npc
|
||||||
|
int npcId = Utils.randomElement(event.getRelatedNPCs());
|
||||||
|
|
||||||
|
// Create case with event
|
||||||
|
return new StarTowerNpcEventCase(npcId, event);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnter() {
|
public void onEnter() {
|
||||||
|
// Create npc
|
||||||
|
this.addCase(this.createNpcEvent());
|
||||||
|
|
||||||
// Create sync hp case
|
// Create sync hp case
|
||||||
this.addCase(new StarTowerSyncHPCase());
|
this.addCase(new StarTowerSyncHPCase());
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public class HandlerStarTowerApplyReq extends NetHandler {
|
|||||||
// Create response
|
// Create response
|
||||||
var rsp = StarTowerApplyResp.newInstance()
|
var rsp = StarTowerApplyResp.newInstance()
|
||||||
.setLastId(req.getId())
|
.setLastId(req.getId())
|
||||||
.setCoinQty(game.getResCount(GameConstants.STAR_TOWER_COIN_ITEM_ID))
|
.setCoinQty(game.getResCount(GameConstants.TOWER_COIN_ITEM_ID))
|
||||||
.setInfo(game.toProto())
|
.setInfo(game.toProto())
|
||||||
.setChange(change.toProto());
|
.setChange(change.toProto());
|
||||||
|
|
||||||
|
|||||||
@@ -173,6 +173,10 @@ public class Utils {
|
|||||||
public static int randomRange(int min, int max) {
|
public static int randomRange(int min, int max) {
|
||||||
return ThreadLocalRandom.current().nextInt(min, max + 1);
|
return ThreadLocalRandom.current().nextInt(min, max + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean randomChance(double chance) {
|
||||||
|
return ThreadLocalRandom.current().nextDouble() < chance;
|
||||||
|
}
|
||||||
|
|
||||||
public static int randomElement(int[] array) {
|
public static int randomElement(int[] array) {
|
||||||
return array[ThreadLocalRandom.current().nextInt(0, array.length)];
|
return array[ThreadLocalRandom.current().nextInt(0, array.length)];
|
||||||
|
|||||||
Reference in New Issue
Block a user