Implement monolith research quests

This commit is contained in:
Melledy committed 2026-10-19 20:59:01 -07:00
1 parent 2424496472
commit b302871630
16 files changed
+1024 -35

No files matched your search

+1 -1
View File
@@ -21,7 +21,7 @@ Latest nightly compiled server jar: [Nightly](https://nightly.link/Melledy/Nebul
- Commissions
- Heartlink
- Achievements
- Monoliths (research quests not implemented)
- Monoliths
- Bounty Trials
- Menance Arena
- Proving Grounds
+1 -1
View File
@@ -4,7 +4,6 @@ import emu.nebula.data.custom.CharGemAttrGroupDef;
import emu.nebula.data.resources.*;
import lombok.Getter;
@SuppressWarnings("unused")
public class GameData {
// ===== Characters =====
@Getter private static DataTable<CharacterDef> CharacterDataTable = new DataTable<>();
@@ -117,6 +116,7 @@ public class GameData {
@Getter private static DataTable<StarTowerFloorExpDef> StarTowerFloorExpDataTable = new DataTable<>();
@Getter private static DataTable<StarTowerTeamExpDef> StarTowerTeamExpDataTable = new DataTable<>();
@Getter private static DataTable<StarTowerEventDef> StarTowerEventDataTable = new DataTable<>();
@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<SubNoteSkillPromoteGroupDef> SubNoteSkillPromoteGroupDataTable = new DataTable<>();
@@ -0,0 +1,36 @@
package emu.nebula.data.custom;
import emu.nebula.data.BaseDef;
import emu.nebula.data.GameData;
import emu.nebula.data.ResourceType;
import emu.nebula.data.ResourceType.LoadPriority;
import lombok.Getter;
@Getter
@ResourceType(name = "StarTowerQuestParam.json", useInternal = true, loadPriority = LoadPriority.LOW)
public class StarTowerQuestParamDef extends BaseDef {
private int Id;
private int CompleteCond;
private int Aim;
private int Param1;
private int ParamCond1;
private int Param2;
private int ParamCond2;
@Override
public int getId() {
return Id;
}
@Override
public void onLoad() {
var quest = GameData.getStarTowerQuestDataTable().get(this.Id);
if (quest == null) {
return;
}
quest.setParams(this);
}
}
@@ -9,6 +9,7 @@ import lombok.Getter;
public class StarTowerBuildRankDef extends BaseDef {
private int Id;
private int MinGrade;
private int Level;
private int Rarity;
@Override
@@ -0,0 +1,78 @@
package emu.nebula.data.resources;
import emu.nebula.data.BaseDef;
import emu.nebula.data.ResourceType;
import emu.nebula.data.custom.StarTowerQuestParamDef;
import emu.nebula.game.quest.QuestData;
import emu.nebula.game.quest.QuestType;
import lombok.Getter;
@Getter
@ResourceType(name = "StarTowerQuest.json")
public class StarTowerQuestDef extends BaseDef implements QuestData {
private int Id;
private String Title;
private int TowerQuestType; // 1 = Core, 2 = Normal
private int[] PreTowerQuestIds;
// Rewards
private int Reward1;
private int RewardQty1;
private int Reward2;
private int RewardQty2;
// Custom params (loaded from defs/StarTowerQuestParam.json)
private transient int completeCond;
private transient int aim;
private transient int param1;
private transient int paramCond1;
private transient int param2;
private transient int paramCond2;
private transient int[] condParams;
@Override
public int getId() {
return Id;
}
@Override
public int getQuestType() {
return QuestType.Tower;
}
@Override
public int getCompleteCond() {
return this.completeCond;
}
@Override
public int[] getCompleteCondParams() {
if (this.condParams == null) {
this.condParams = new int[] { 1, 0, 0 };
}
return this.condParams;
}
/**
* Applies the generated condition params from the internal defs file.
*/
public void setParams(StarTowerQuestParamDef params) {
this.completeCond = params.getCompleteCond();
this.aim = params.getAim();
this.param1 = params.getParam1();
this.paramCond1 = params.getParamCond1();
this.param2 = params.getParam2();
this.paramCond2 = params.getParamCond2();
this.condParams = new int[] { this.aim, this.param1, this.param2 };
}
@Override
public void onLoad() {
// Quests without prerequisites have no array in the data file
if (this.PreTowerQuestIds == null) {
this.PreTowerQuestIds = new int[0];
}
}
}
@@ -65,6 +65,62 @@ public class GameQuest {
return 0;
}
/**
* Refreshes condition data from a resource definition while preserving progress.
*/
public boolean refreshData(QuestData data) {
int oldCond = this.cond;
int oldMax = this.maxProgress;
int oldParam = this.param;
this.cond = data.getCompleteCond();
int[] params = data.getCompleteCondParams();
this.maxProgress = params.length > 0 ? params[0] : 0;
this.param = params.length > 1 ? params[1] : 0;
return oldCond != this.cond || oldMax != this.maxProgress || oldParam != this.param;
}
/**
* Adds progress without applying condition/param checks.
* Used by quest systems that perform their own matching.
*/
public boolean addProgress(int progress) {
if (this.isComplete() || progress <= 0) {
return false;
}
int newProgress = Math.min(this.curProgress + progress, this.maxProgress);
if (newProgress == this.curProgress) {
return false;
}
this.curProgress = newProgress;
return true;
}
/**
* Directly sets quest progress
*/
public boolean setProgress(int progress) {
if (this.isComplete() || progress < 0) {
return false;
}
int newProgress = Math.min(progress, this.maxProgress);
if (newProgress == this.curProgress) {
return false;
}
this.curProgress = newProgress;
return true;
}
public boolean trigger(int condition, int progress, int param1, int param2) {
// Sanity check
if (this.isComplete()) {
@@ -60,6 +60,8 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
this.list = new HashMap<>();
this.levelRewards = new Bitset();
this.initStarTowerQuests();
this.resetDailyQuests(true);
this.save();
@@ -71,7 +73,34 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
}
public synchronized GameQuest addQuest(GameQuest quest) {
// Add to quest list
this.list.put(quest.getKey(), quest);
// Star Tower growth-node quests can complete retroactively if the player
// already unlocked the required node(s) before the quest was added
if (quest.getType() == QuestType.Tower) {
var data = GameData.getStarTowerQuestDataTable().get(quest.getId());
int cond = data != null ? data.getCompleteCond() : 0;
if (cond == QuestCondition.TowerGrowthSpecificNote.getValue() || cond == QuestCondition.TowerGrowthWithSpecificNote.getValue()) {
var manager = this.getPlayer().getStarTowerManager();
int progress = 0;
if (data.getParam1() != 0 && manager.hasGrowthNode(data.getParam1())) {
progress++;
}
if (data.getParam2() != 0 && manager.hasGrowthNode(data.getParam2())) {
progress++;
}
if (progress > 0) {
quest.setProgress(progress);
}
}
}
// Return quest
return quest;
}
@@ -146,14 +175,39 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
// Get quest from entry
var quest = entry.getValue();
// Try to trigger quest
boolean result = quest.trigger(condition, progress, param1, param2);
// Skip if quest progress wasn't changed
if (!result) {
// Skip completed quests
if (quest.isComplete()) {
continue;
}
// Star Tower quests use their own generated params and matching rules
// TODO clean this code up to look nice
if (quest.getType() == QuestType.Tower) {
// Get quest data
var data = GameData.getStarTowerQuestDataTable().get(quest.getId());
if (data == null || data.getCompleteCond() != condition) {
continue;
}
// Check params
if (!StarTowerQuestHelper.matches(data, param1, param2)) {
continue;
}
// Add progress
if (!quest.addProgress(progress)) {
continue;
}
} else {
// Now we try to trigger regular daily/weekly quests
boolean result = quest.trigger(condition, progress, param1, param2);
// Skip if quest progress wasn't changed
if (!result) {
continue;
}
}
// Sync quest with player client
this.syncQuest(quest);
@@ -176,6 +230,132 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
);
}
// Star Tower quests
/**
* Adds all currently unlocked Star Tower quests.
* Returns true if any quest was added or refreshed.
*/
public synchronized boolean initStarTowerQuests() {
boolean changed = false;
for (var data : GameData.getStarTowerQuestDataTable()) {
// Only add quests whose prerequisites have been claimed
if (!StarTowerQuestHelper.isUnlocked(this, data)) {
continue;
}
// Get existing quest
var quest = this.getList().get(data.getQuestKey());
if (quest == null) {
this.addQuest(new GameQuest(data));
changed = true;
} else if (quest.refreshData(data)) {
changed = true;
}
}
return changed;
}
/**
* Adds quests that became available after a prerequisite was claimed.
*/
public synchronized void unlockStarTowerQuests() {
boolean changed = false;
for (var data : GameData.getStarTowerQuestDataTable()) {
// Skip quests that already exist
if (this.getList().containsKey(data.getQuestKey())) {
continue;
}
// Only add quests whose prerequisites have been claimed
if (!StarTowerQuestHelper.isUnlocked(this, data)) {
continue;
}
// Add quest and sync it with the client
var quest = this.addQuest(new GameQuest(data));
// Syncs quest with client
this.syncQuest(quest);
// Set changed flag
changed = true;
}
// Persist new quests
if (changed) {
this.save();
}
}
public synchronized PlayerChangeInfo receiveStarTowerQuestReward(int questId) {
// Get received quests
var claimList = new ArrayList<GameQuest>();
if (questId > 0) {
// Claim specific quest
var quest = this.getQuest(QuestType.Tower, questId);
if (quest != null && quest.canClaim()) {
claimList.add(quest);
}
} else {
// Claim all
for (var quest : this.getQuests()) {
if (quest.getType() != QuestType.Tower) {
continue;
}
if (!quest.canClaim()) {
continue;
}
claimList.add(quest);
}
}
// Sanity check
if (claimList.isEmpty()) {
return null;
}
// Create change info
var change = new PlayerChangeInfo();
// Claim
for (var quest : claimList) {
// Get data
var data = GameData.getStarTowerQuestDataTable().get(quest.getId());
if (data != null) {
// Add rewards
if (data.getReward1() > 0 && data.getRewardQty1() > 0) {
this.getPlayer().getInventory().addItem(data.getReward1(), data.getRewardQty1(), change);
}
if (data.getReward2() > 0 && data.getRewardQty2() > 0) {
this.getPlayer().getInventory().addItem(data.getReward2(), data.getRewardQty2(), change);
}
}
// Set claimed
quest.setClaimed(true);
// Update in database
Nebula.getGameDatabase().update(this, this.getUid(), "list." + quest.getKey(), quest);
}
// Unlock newly available quests
this.unlockStarTowerQuests();
// Success
return change.setSuccess(true);
}
// Daily quests
public synchronized int getDailyActivity() {
@@ -525,11 +705,23 @@ public class QuestManager extends PlayerManager implements GameDatabaseObject {
// Fix quest lists
if (this.getList() == null) {
// Create quest list
this.list = new HashMap<>();
// 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();
// Reset daily quests
this.resetDailyQuests(true);
// QuestManager::resetDailyQuests will save to the database, so we dont need to set the shouldSave flag
shouldSave = false;
} else {
// Add missing Star Tower quests and refresh their condition data
if (this.initStarTowerQuests()) {
shouldSave = true;
}
}
// Save to database
@@ -0,0 +1,48 @@
package emu.nebula.game.quest;
import emu.nebula.data.resources.StarTowerQuestDef;
import emu.nebula.game.achievement.AchievementParamCond;
// TODO clean up and merge with other quest helpers
public class StarTowerQuestHelper {
/**
* Checks if all prerequisite quests for the specified quest have been claimed.
*/
public static boolean isUnlocked(QuestManager manager, StarTowerQuestDef data) {
for (int preId : data.getPreTowerQuestIds()) {
var quest = manager.getQuest(QuestType.Tower, preId);
if (quest == null || !quest.isClaimed()) {
return false;
}
}
return true;
}
/**
* Checks whether a trigger payload matches the quest's generated params.
*/
public static boolean matches(StarTowerQuestDef data, int param1, int param2) {
// Growth node quests can require one or two specific nodes.
// The trigger payload puts the unlocked node id in param1.
if (data.getCompleteCond() == QuestCondition.TowerGrowthWithSpecificNote.getValue()) {
boolean matchesFirst = data.getParam1() != 0 && param1 == data.getParam1();
boolean matchesSecond = data.getParam2() != 0 && param1 == data.getParam2();
return matchesFirst || matchesSecond;
}
return matchesParam(data.getParam1(), data.getParamCond1(), param1) && matchesParam(data.getParam2(), data.getParamCond2(), param2);
}
private static boolean matchesParam(int param, int cond, int value) {
// A param of zero is a wildcard, matching the existing GameQuest behavior
if (param == 0) {
return true;
}
return AchievementParamCond.getByValue(cond).test(param, value);
}
}
@@ -19,6 +19,7 @@ import emu.nebula.game.formation.Formation;
import emu.nebula.game.inventory.ItemParamMap;
import emu.nebula.game.player.Player;
import emu.nebula.game.player.PlayerChangeInfo;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.game.tower.cases.StarTowerBaseCase;
import emu.nebula.game.tower.cases.StarTowerDoorCase;
import emu.nebula.game.tower.cases.StarTowerHawkerCase;
@@ -463,9 +464,11 @@ public class StarTowerGame {
// Add to new infos
this.getNewInfos().add(id, count);
// Achievment
// Achievement + Star Tower quests (Musical Notes).
// The quest treats param1 as a wildcard, so passing the item id keeps
// the per-note achievements working while counting every sub-note.
if (count > 0) {
this.getAchievementManager().trigger(AchievementCondition.TowerItemsGet, count, id, 0);
this.getPlayer().trigger(QuestCondition.TowerItemsGet, count, id);
}
}
case Res -> {
@@ -866,15 +869,7 @@ public class StarTowerGame {
int tickets = this.getModifiers().calculateTickets();
rewards.add(12, tickets);
// (Custom) Add research materials since tower quests are not implemented yet
int research = 50 + (Utils.randomRange(this.getDifficulty() - 1, this.getDifficulty() * 2) * 10);
rewards.add(51, research);
// Add to inventory
var change = this.getPlayer().getInventory().addItem(51, research);
// Set proto data
settle.setChange(change.toProto());
rewards.toItemTemplateStream().forEach(settle::addTowerRewards);
// Save tower tickets
@@ -920,10 +915,10 @@ public class StarTowerGame {
// Set new secondary skills
this.secondarySkills = newSecondarySkills;
// Achievement trigger
// Achievement + Star Tower quests
if (newSecondaryCount > 0) {
this.getAchievementManager().trigger(
AchievementCondition.TowerSpecificSecondarySkillActivateTotal,
this.getPlayer().trigger(
QuestCondition.TowerSpecificSecondarySkillActivateTotal,
newSecondaryCount
);
}
@@ -102,6 +102,10 @@ public class StarTowerManager extends PlayerManager {
this.getProgress().getStarTowerGrowth()
);
// Star Tower quests
this.getPlayer().trigger(QuestCondition.TowerGrowthSpecificNote, 1, data.getId());
this.getPlayer().trigger(QuestCondition.TowerGrowthWithSpecificNote, 1, data.getId());
// Remove items
return getPlayer().getInventory().removeItem(data.getItemId1(), data.getItemQty1());
}
@@ -147,6 +151,14 @@ public class StarTowerManager extends PlayerManager {
"starTowerGrowth",
this.getProgress().getStarTowerGrowth()
);
// Star Tower quests
for (int i = 0; i < unlocked.size(); i++) {
int nodeId = unlocked.getInt(i);
this.getPlayer().trigger(QuestCondition.TowerGrowthSpecificNote, 1, nodeId);
this.getPlayer().trigger(QuestCondition.TowerGrowthWithSpecificNote, 1, nodeId);
}
}
// Set unlocked list
@@ -190,6 +202,17 @@ public class StarTowerManager extends PlayerManager {
rank.getRarity(),
0
);
// Star Tower quests use the record's rating level, not its rarity.
// NOTE: This must stay on the quest manager directly. Condition 504 is also
// used by the build-rarity achievements (param1 = rarity), so routing this
// through Player::trigger would feed them the level instead of the rarity.
this.getPlayer().getQuestManager().trigger(
QuestCondition.TowerBuildSpecificScoreWithTotal.getValue(),
1,
rank.getLevel(),
0
);
}
}
@@ -415,6 +438,7 @@ public class StarTowerManager extends PlayerManager {
// Trigger quest
this.getPlayer().trigger(QuestCondition.TowerEnterFloor, 1);
this.getPlayer().trigger(QuestCondition.TowerEnterTotal, 1);
// Success
return change.setExtraData(this.game);
@@ -439,6 +463,18 @@ public class StarTowerManager extends PlayerManager {
// Add star tower history
this.getPlayer().getProgress().addStarTowerLog(game.getId());
// Star Tower quests (group + difficulty)
// NOTE: This must stay on the quest manager directly. Condition 506 is also
// used by the "Monolith Conqueror" achievements, but they interpret the
// params as (difficulty, 0) instead of (groupId, difficulty), so routing
// this through Player::trigger would corrupt them.
this.getPlayer().getQuestManager().trigger(
QuestCondition.TowerClearSpecificGroupIdAndDifficulty.getValue(),
1,
game.getData().getGroupId(),
game.getDifficulty()
);
// Achievement conditions
var achievements = this.getPlayer().getAchievementManager();
@@ -4,6 +4,7 @@ import emu.nebula.GameConstants;
import emu.nebula.data.GameData;
import emu.nebula.game.inventory.ItemParamMap;
import emu.nebula.game.player.PlayerChangeInfo;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.game.tower.room.RoomType;
import emu.nebula.proto.PublicStarTower.StarTowerRoomCase;
import emu.nebula.proto.StarTowerInteract.StarTowerInteractReq;
@@ -162,6 +163,9 @@ public class StarTowerBattleCase extends StarTowerBaseCase {
// Bonus sub note chance (Note of Surprise)
if (Utils.randomChance(this.getModifiers().getBonusSubNoteChance())) {
subNotes += this.getModifiers().getBonusSubNotes();
// Star Tower quests
this.getGame().getPlayer().trigger(QuestCondition.TowerSpecificNoteActivateTotal, 1);
}
// Regular sub note drops
@@ -5,8 +5,8 @@ import java.util.Map;
import java.util.stream.Collectors;
import emu.nebula.GameConstants;
import emu.nebula.game.achievement.AchievementCondition;
import emu.nebula.game.player.PlayerChangeInfo;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.game.tower.StarTowerShopGoods;
import emu.nebula.proto.PublicStarTower.HawkerCaseData;
import emu.nebula.proto.PublicStarTower.HawkerGoods;
@@ -176,8 +176,8 @@ public class StarTowerHawkerCase extends StarTowerBaseCase {
// Set change info
rsp.setChange(change.toProto());
// Achievement
this.getGame().getAchievementManager().trigger(AchievementCondition.TowerSpecificShopReRollTotal, 1);
// Achievement + Star Tower quests
this.getGame().getPlayer().trigger(QuestCondition.TowerSpecificShopReRollTotal, 1);
}
private void buy(int sid, StarTowerInteractResp rsp) {
@@ -214,11 +214,11 @@ public class StarTowerHawkerCase extends StarTowerBaseCase {
// Remove coins
this.getGame().addItem(GameConstants.TOWER_COIN_ITEM_ID, -price, change);
// Achievements
this.getGame().getAchievementManager().trigger(AchievementCondition.TowerSpecificDifficultyShopBuyTimes, 1);
// Achievement + Star Tower quests
this.getGame().getPlayer().trigger(QuestCondition.TowerSpecificDifficultyShopBuyTimes, 1);
if (goods.hasDiscount()) {
this.getGame().getAchievementManager().trigger(AchievementCondition.TowerSpecificShopBuyDiscountTotal, 1);
this.getGame().getPlayer().trigger(QuestCondition.TowerSpecificShopBuyDiscountTotal, 1);
}
// Set change info
@@ -3,7 +3,7 @@ package emu.nebula.game.tower.cases;
import java.util.List;
import emu.nebula.GameConstants;
import emu.nebula.game.achievement.AchievementCondition;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.game.tower.StarTowerGame;
import emu.nebula.game.tower.StarTowerPotentialInfo;
import emu.nebula.proto.PublicStarTower.StarTowerRoomCase;
@@ -118,8 +118,8 @@ public class StarTowerPotentialCase extends StarTowerBaseCase {
rsp.setChange(change.toProto());
// Achievement
this.getGame().getAchievementManager().trigger(AchievementCondition.TowerSpecificPotentialReRollTotal, 1);
// Achievement + Star Tower quests
this.getGame().getPlayer().trigger(QuestCondition.TowerSpecificPotentialReRollTotal, 1);
}
private void select(int index, StarTowerInteractResp rsp) {
@@ -152,12 +152,12 @@ public class StarTowerPotentialCase extends StarTowerBaseCase {
return;
}
if (this.getGame().getPotentials().containsKey(charId)) {
if (this.getGame().getPotentials().containsKey(potential.getId())) {
// Enhancing potentials
this.getGame().getAchievementManager().trigger(AchievementCondition.TowerSpecificPotentialLuckyTotal, 1);
this.getGame().getPlayer().trigger(QuestCondition.TowerSpecificPotentialLuckyTotal, 1);
} else {
// Adding new potential
this.getGame().getAchievementManager().trigger(AchievementCondition.TowerSpecificPotentialBonusTotal, 1);
this.getGame().getPlayer().trigger(QuestCondition.TowerSpecificPotentialBonusTotal, 1);
}
}
@@ -1,7 +1,7 @@
package emu.nebula.game.tower.cases;
import emu.nebula.GameConstants;
import emu.nebula.game.achievement.AchievementCondition;
import emu.nebula.game.quest.QuestCondition;
import emu.nebula.proto.PublicStarTower.StarTowerRoomCase;
import emu.nebula.proto.StarTowerInteract.StarTowerInteractReq;
import emu.nebula.proto.StarTowerInteract.StarTowerInteractResp;
@@ -76,8 +76,8 @@ public class StarTowerStrengthenMachineCase extends StarTowerBaseCase {
// Increment price
this.increasePrice();
// Achievement
this.getGame().getAchievementManager().trigger(AchievementCondition.TowerSpecificDifficultyStrengthenMachineTotal, 1);
// Trigger quests + achievements
this.getGame().getPlayer().trigger(QuestCondition.TowerSpecificDifficultyStrengthenMachineTotal, 1, 0);
}
// Set success result
@@ -0,0 +1,28 @@
package emu.nebula.server.handlers;
import emu.nebula.net.NetHandler;
import emu.nebula.net.NetMsgId;
import emu.nebula.proto.Public.UI32;
import emu.nebula.net.HandlerId;
import emu.nebula.net.GameSession;
@HandlerId(NetMsgId.quest_tower_reward_receive_req)
public class HandlerQuestTowerRewardReceiveReq extends NetHandler {
@Override
public byte[] handle(GameSession session, byte[] message) throws Exception {
// Parse request
var req = UI32.parseFrom(message);
// Receive rewards
var change = session.getPlayer().getQuestManager().receiveStarTowerQuestReward(req.getValue());
if (change == null) {
return session.encodeMsg(NetMsgId.quest_tower_reward_receive_failed_ack);
}
// Encode and send
return session.encodeMsg(NetMsgId.quest_tower_reward_receive_succeed_ack, change.toProto());
}
}
@@ -0,0 +1,515 @@
[
{
"Id": 100,
"CompleteCond": 515,
"Aim": 1,
"Param1": 10101,
"ParamCond1": 0,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 200,
"CompleteCond": 515,
"Aim": 1,
"Param1": 10301,
"ParamCond1": 0,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 300,
"CompleteCond": 527,
"Aim": 2,
"Param1": 10601,
"ParamCond1": 0,
"Param2": 10602,
"ParamCond2": 0
},
{
"Id": 400,
"CompleteCond": 515,
"Aim": 1,
"Param1": 10901,
"ParamCond1": 0,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 500,
"CompleteCond": 527,
"Aim": 2,
"Param1": 20301,
"ParamCond1": 0,
"Param2": 20302,
"ParamCond2": 0
},
{
"Id": 600,
"CompleteCond": 515,
"Aim": 1,
"Param1": 20601,
"ParamCond1": 0,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 700,
"CompleteCond": 527,
"Aim": 2,
"Param1": 20901,
"ParamCond1": 0,
"Param2": 20902,
"ParamCond2": 0
},
{
"Id": 800,
"CompleteCond": 515,
"Aim": 1,
"Param1": 30301,
"ParamCond1": 0,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 900,
"CompleteCond": 515,
"Aim": 1,
"Param1": 30601,
"ParamCond1": 0,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 1000,
"CompleteCond": 515,
"Aim": 1,
"Param1": 30901,
"ParamCond1": 0,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 1100,
"CompleteCond": 515,
"Aim": 1,
"Param1": 40401,
"ParamCond1": 0,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 101,
"CompleteCond": 510,
"Aim": 1,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 102,
"CompleteCond": 506,
"Aim": 1,
"Param1": 2,
"ParamCond1": 0,
"Param2": 1,
"ParamCond2": 4
},
{
"Id": 103,
"CompleteCond": 506,
"Aim": 1,
"Param1": 0,
"ParamCond1": 1,
"Param2": 2,
"ParamCond2": 4
},
{
"Id": 201,
"CompleteCond": 506,
"Aim": 2,
"Param1": 0,
"ParamCond1": 1,
"Param2": 2,
"ParamCond2": 4
},
{
"Id": 202,
"CompleteCond": 514,
"Aim": 10,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 203,
"CompleteCond": 513,
"Aim": 30,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 301,
"CompleteCond": 504,
"Aim": 1,
"Param1": 5,
"ParamCond1": 4,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 302,
"CompleteCond": 513,
"Aim": 80,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 303,
"CompleteCond": 517,
"Aim": 10,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 401,
"CompleteCond": 506,
"Aim": 1,
"Param1": 0,
"ParamCond1": 1,
"Param2": 3,
"ParamCond2": 4
},
{
"Id": 402,
"CompleteCond": 514,
"Aim": 20,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 403,
"CompleteCond": 522,
"Aim": 6,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 501,
"CompleteCond": 535,
"Aim": 8,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 502,
"CompleteCond": 504,
"Aim": 1,
"Param1": 10,
"ParamCond1": 4,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 503,
"CompleteCond": 513,
"Aim": 150,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 504,
"CompleteCond": 536,
"Aim": 10,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 505,
"CompleteCond": 517,
"Aim": 20,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 601,
"CompleteCond": 506,
"Aim": 1,
"Param1": 0,
"ParamCond1": 1,
"Param2": 4,
"ParamCond2": 4
},
{
"Id": 602,
"CompleteCond": 514,
"Aim": 50,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 603,
"CompleteCond": 522,
"Aim": 20,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 605,
"CompleteCond": 531,
"Aim": 3,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 701,
"CompleteCond": 533,
"Aim": 3,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 702,
"CompleteCond": 504,
"Aim": 1,
"Param1": 20,
"ParamCond1": 4,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 703,
"CompleteCond": 513,
"Aim": 500,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 704,
"CompleteCond": 536,
"Aim": 25,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 705,
"CompleteCond": 517,
"Aim": 30,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 801,
"CompleteCond": 506,
"Aim": 5,
"Param1": 0,
"ParamCond1": 1,
"Param2": 4,
"ParamCond2": 4
},
{
"Id": 802,
"CompleteCond": 514,
"Aim": 100,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 803,
"CompleteCond": 522,
"Aim": 80,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 804,
"CompleteCond": 529,
"Aim": 20,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 901,
"CompleteCond": 506,
"Aim": 2,
"Param1": 0,
"ParamCond1": 1,
"Param2": 5,
"ParamCond2": 4
},
{
"Id": 902,
"CompleteCond": 504,
"Aim": 1,
"Param1": 25,
"ParamCond1": 4,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 903,
"CompleteCond": 513,
"Aim": 2000,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 904,
"CompleteCond": 536,
"Aim": 50,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 905,
"CompleteCond": 517,
"Aim": 40,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 906,
"CompleteCond": 530,
"Aim": 10,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 1001,
"CompleteCond": 506,
"Aim": 2,
"Param1": 0,
"ParamCond1": 1,
"Param2": 6,
"ParamCond2": 4
},
{
"Id": 1002,
"CompleteCond": 514,
"Aim": 200,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 1003,
"CompleteCond": 522,
"Aim": 150,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 1004,
"CompleteCond": 533,
"Aim": 10,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 1005,
"CompleteCond": 534,
"Aim": 5,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 1101,
"CompleteCond": 506,
"Aim": 3,
"Param1": 0,
"ParamCond1": 1,
"Param2": 8,
"ParamCond2": 4
},
{
"Id": 1102,
"CompleteCond": 513,
"Aim": 3000,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 1103,
"CompleteCond": 504,
"Aim": 1,
"Param1": 31,
"ParamCond1": 4,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 1104,
"CompleteCond": 536,
"Aim": 80,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
},
{
"Id": 1105,
"CompleteCond": 533,
"Aim": 30,
"Param1": 0,
"ParamCond1": 1,
"Param2": 0,
"ParamCond2": 1
}
]