mirror of
https://github.com/EpinelPS/EpinelPS.git
synced 2025-12-12 15:04:36 +01:00
Skill upgrade, more commands, fixes (#21)
* add BuyWallpaper * added partial stage clear info handling, no longer fails get check the creation of the clear info still has imperfections, so I've left it disabled for now. no point in letting it clutter the DB until the info is at least accurate in the UI. * unfinished CP calculation stuff still need to impl other tables (equipment), need a better way to capture outputs and compare them to retail, not really worth the excess work currently since CP calc isn't used anywhere critical right now * AddItem command * AddCharacter command * finishalltutorials command * addallmaterials command also load the material items table * skill upgrade impl * update README * potential fix for bodies not being removed properly on limit breaks and core upgrades the client seems to be smart enough to deal with zero count item entries, so there's no real reason to remove zero count item entries from the DB * check to make sure we have the character before adding a body * use CreateWholeUserDataFromDbUser instead of doing a manual copy
This commit is contained in:
@@ -183,6 +183,7 @@ namespace EpinelPS.Database
|
||||
public NetWallpaperJukeboxFavorite[] WallpaperFavoriteList = [];
|
||||
public NetWallpaperPlaylist[] WallpaperPlaylistList = [];
|
||||
public NetWallpaperJukebox[] WallpaperJukeboxList = [];
|
||||
public List<int> LobbyDecoBackgroundList = [];
|
||||
|
||||
|
||||
public Dictionary<int, NetUserTeamData> UserTeams = new Dictionary<int, NetUserTeamData>();
|
||||
@@ -208,6 +209,8 @@ namespace EpinelPS.Database
|
||||
public OutpostBuffs OutpostBuffs = new();
|
||||
public Dictionary<int, UnlockData> ContentsOpenUnlocked = new();
|
||||
|
||||
public List<NetStageClearInfo> StageClearHistorys = [];
|
||||
|
||||
// Event data
|
||||
public Dictionary<int, EventData> EventInfo = new();
|
||||
public MogMinigameInfo MogInfo = new();
|
||||
@@ -382,24 +385,12 @@ namespace EpinelPS.Database
|
||||
|
||||
if (item.Isn == isn)
|
||||
{
|
||||
if (item.Count == 1)
|
||||
removed++;
|
||||
item.Count -= count;
|
||||
|
||||
if (item.Count < 0)
|
||||
{
|
||||
Items.Remove(item);
|
||||
count--;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO test this
|
||||
if (item.Count >= count)
|
||||
{
|
||||
removed++;
|
||||
item.Count -= count;
|
||||
}
|
||||
else
|
||||
{
|
||||
removed += item.Count;
|
||||
Items.Remove(item);
|
||||
}
|
||||
item.Count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,8 +32,9 @@ namespace EpinelPS.StaticInfo
|
||||
private Dictionary<int, CampaignChapterRecord> chapterCampaignData;
|
||||
private JArray characterCostumeTable;
|
||||
public Dictionary<int, CharacterRecord> characterTable;
|
||||
private Dictionary<int, ClearedTutorialData> tutorialTable;
|
||||
private Dictionary<int, ItemEquipRecord> itemEquipTable;
|
||||
public Dictionary<int, ClearedTutorialData> tutorialTable;
|
||||
public Dictionary<int, ItemEquipRecord> itemEquipTable;
|
||||
public Dictionary<int, ItemMaterialRecord> itemMaterialTable;
|
||||
private Dictionary<string, JArray> FieldMapData = new Dictionary<string, JArray>(); // Fixed initialization
|
||||
private Dictionary<int, CharacterLevelData> LevelData = new Dictionary<int, CharacterLevelData>(); // Fixed initialization
|
||||
private Dictionary<int, TacticAcademyLessonRecord> TacticAcademyLessons = new Dictionary<int, TacticAcademyLessonRecord>(); // Fixed initialization
|
||||
@@ -54,6 +55,9 @@ namespace EpinelPS.StaticInfo
|
||||
public Dictionary<int, ArchiveEventDungeonStageRecord> archiveEventDungeonStageRecords = new Dictionary<int, ArchiveEventDungeonStageRecord>();
|
||||
public Dictionary<int, UserTitleRecord> userTitleRecords = new Dictionary<int, UserTitleRecord>();
|
||||
public Dictionary<int, ArchiveMessengerConditionRecord> archiveMessengerConditionRecords;
|
||||
public Dictionary<int, CharacterStatRecord> characterStatTable;
|
||||
public Dictionary<int, SkillInfoRecord> skillInfoTable;
|
||||
public Dictionary<int, CostRecord> costTable;
|
||||
|
||||
|
||||
|
||||
@@ -90,6 +94,10 @@ namespace EpinelPS.StaticInfo
|
||||
ZipStream = new();
|
||||
tutorialTable = new();
|
||||
itemEquipTable = new();
|
||||
itemMaterialTable = new();
|
||||
characterStatTable = new();
|
||||
skillInfoTable = new();
|
||||
costTable = new();
|
||||
|
||||
// Initialize Jukebox data dictionaries
|
||||
jukeboxListDataRecords = new Dictionary<int, JukeboxListRecord>();
|
||||
@@ -320,6 +328,12 @@ namespace EpinelPS.StaticInfo
|
||||
this.itemEquipTable.Add(obj.id, obj);
|
||||
}
|
||||
|
||||
var itemMaterialTable = await LoadZip<ItemMaterialTable>("ItemMaterialTable.json", progress);
|
||||
foreach (var obj in itemMaterialTable.records)
|
||||
{
|
||||
this.itemMaterialTable.Add(obj.id, obj);
|
||||
}
|
||||
|
||||
var characterLevelTable = await LoadZip("CharacterLevelTable.json", progress);
|
||||
|
||||
foreach (JToken item in characterLevelTable)
|
||||
@@ -460,6 +474,24 @@ namespace EpinelPS.StaticInfo
|
||||
// Load Jukebox data
|
||||
await LoadJukeboxListData(progress);
|
||||
await LoadJukeboxThemeData(progress);
|
||||
|
||||
var characterStatTable = await LoadZip<CharacterStatTable>("CharacterStatTable.json", progress);
|
||||
foreach (var obj in characterStatTable.records)
|
||||
{
|
||||
this.characterStatTable.Add(obj.id, obj);
|
||||
}
|
||||
|
||||
var skillinfoTable = await LoadZip<SkillInfoTable>("SkillInfoTable.json", progress);
|
||||
foreach (var obj in skillinfoTable.records)
|
||||
{
|
||||
this.skillInfoTable.Add(obj.id, obj);
|
||||
}
|
||||
|
||||
var costTable = await LoadZip<CostTable>("CostTable.json", progress);
|
||||
foreach (var obj in costTable.records)
|
||||
{
|
||||
this.costTable.Add(obj.id, obj);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task LoadJukeboxListData(ProgressBar bar)
|
||||
|
||||
@@ -131,11 +131,38 @@
|
||||
{
|
||||
public int id;
|
||||
public int piece_id;
|
||||
public string original_rare;
|
||||
public string corporation;
|
||||
public int grade_core_id;
|
||||
public int name_code;
|
||||
public int grow_grade;
|
||||
public string original_rare;
|
||||
public string corporation;
|
||||
public int grade_core_id;
|
||||
public int name_code;
|
||||
public int grow_grade;
|
||||
public int stat_enhance_id;
|
||||
public string character_class;
|
||||
public List<int> element_id;
|
||||
public int critical_ratio;
|
||||
public int critical_damage;
|
||||
public int shot_id;
|
||||
public int bonusrange_min;
|
||||
public int bonusrange_max;
|
||||
public string use_burst_skill;
|
||||
public string change_burst_step;
|
||||
public int burst_apply_delay;
|
||||
public int burst_duration;
|
||||
public int ulti_skill_id;
|
||||
public int skill1_id;
|
||||
public string skill1_table;
|
||||
public int skill2_id;
|
||||
public string skill2_table;
|
||||
public string eff_category_type;
|
||||
public int eff_category_value;
|
||||
public string category_type_1;
|
||||
public string category_type_2;
|
||||
public string category_type_3;
|
||||
public string cv_localkey;
|
||||
public string squad;
|
||||
public bool is_visible;
|
||||
public bool prism_is_active;
|
||||
public bool is_detail_close;
|
||||
}
|
||||
public class CharacterTable
|
||||
{
|
||||
@@ -427,4 +454,82 @@
|
||||
public List<ArchiveMessengerConditionRecord> records;
|
||||
}
|
||||
|
||||
public class CharacterStatRecord
|
||||
{
|
||||
public int id;
|
||||
public int group;
|
||||
public int level;
|
||||
public int level_hp;
|
||||
public int level_attack;
|
||||
public int level_defence;
|
||||
public int level_energy_resist;
|
||||
public int level_bio_resist;
|
||||
}
|
||||
|
||||
public class CharacterStatTable
|
||||
{
|
||||
public List<CharacterStatRecord> records;
|
||||
}
|
||||
|
||||
public class ItemMaterialRecord
|
||||
{
|
||||
public int id;
|
||||
public string name_localkey;
|
||||
public string description_localkey;
|
||||
public string resource_id;
|
||||
public string item_type;
|
||||
public string item_sub_type;
|
||||
public string item_rare;
|
||||
public int item_value;
|
||||
public string material_type;
|
||||
public int material_value;
|
||||
public int stack_max;
|
||||
}
|
||||
|
||||
public class ItemMaterialTable
|
||||
{
|
||||
public List<ItemMaterialRecord> records;
|
||||
}
|
||||
|
||||
public class SkillInfoRecord
|
||||
{
|
||||
public int id;
|
||||
public int group_id;
|
||||
public int skill_level;
|
||||
public int next_level_id;
|
||||
public int level_up_cost_id;
|
||||
public string icon;
|
||||
public string name_localkey;
|
||||
public string description_localkey;
|
||||
public string info_description_localkey;
|
||||
public List<DescriptionValue> description_value_list;
|
||||
}
|
||||
|
||||
public class DescriptionValue
|
||||
{
|
||||
public string description_value;
|
||||
}
|
||||
|
||||
public class SkillInfoTable
|
||||
{
|
||||
public List<SkillInfoRecord> records;
|
||||
}
|
||||
|
||||
public class CostRecord
|
||||
{
|
||||
public int id;
|
||||
public List<CostData> costs;
|
||||
}
|
||||
|
||||
public class CostData
|
||||
{
|
||||
public string item_type;
|
||||
public int item_id;
|
||||
public int item_value;
|
||||
}
|
||||
|
||||
public class CostTable
|
||||
{
|
||||
public List<CostRecord> records;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,12 +55,9 @@ namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
};
|
||||
|
||||
// remove spare body item
|
||||
var bodyItem = user.Items.FirstOrDefault(i => i.Isn == req.Isn);
|
||||
user.RemoveItemBySerialNumber(req.Isn, 1);
|
||||
|
||||
foreach (var item in user.Items)
|
||||
{
|
||||
response.Items.Add(NetUtils.ToNet(item));
|
||||
}
|
||||
response.Items.Add(NetUtils.ToNet(bodyItem));
|
||||
|
||||
// replace any reference to the old character to the new TID
|
||||
// Check if RepresentationTeamData exists and has slots
|
||||
|
||||
87
EpinelPS/LobbyServer/Msgs/Character/SkillLevelUp.cs
Normal file
87
EpinelPS/LobbyServer/Msgs/Character/SkillLevelUp.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.StaticInfo;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
{
|
||||
[PacketPath("/character/skill/levelup")]
|
||||
public class SkillLevelUp : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqCharacterSkillLevelUp>();
|
||||
var user = GetUser();
|
||||
var response = new ResCharacterSkillLevelUp();
|
||||
var character = user.Characters.FirstOrDefault(c => c.Csn == req.Csn);
|
||||
var charRecord = GameData.Instance.characterTable.Values.FirstOrDefault(c => c.id == character.Tid);
|
||||
var skillIdMap = new Dictionary<int, int>
|
||||
{
|
||||
{ 1, charRecord.ulti_skill_id },
|
||||
{ 2, charRecord.skill1_id },
|
||||
{ 3, charRecord.skill2_id }
|
||||
};
|
||||
var skillLevelMap = new Dictionary<int, int>
|
||||
{
|
||||
{ 1, character.UltimateLevel },
|
||||
{ 2, character.Skill1Lvl },
|
||||
{ 3, character.Skill2Lvl }
|
||||
};
|
||||
var skillRecord = GameData.Instance.skillInfoTable.Values.FirstOrDefault(s => s.id == skillIdMap[req.Category] + (skillLevelMap[req.Category] - 1));
|
||||
var costRecord = GameData.Instance.costTable.Values.FirstOrDefault(c => c.id == skillRecord.level_up_cost_id);
|
||||
|
||||
foreach (var cost in costRecord.costs.Where(i => i.item_type != "None"))
|
||||
{
|
||||
var item = user.Items.FirstOrDefault(i => i.ItemType == cost.item_id);
|
||||
|
||||
item.Count -= cost.item_value;
|
||||
|
||||
response.Items.Add(new NetUserItemData
|
||||
{
|
||||
Isn = item.Isn,
|
||||
Tid = cost.item_id,
|
||||
Count = item.Count,
|
||||
Csn = item.Csn,
|
||||
Corporation = item.Corp,
|
||||
Level = item.Level,
|
||||
Exp = item.Exp,
|
||||
Position = item.Position
|
||||
});
|
||||
}
|
||||
|
||||
var newChar = new NetUserCharacterDefaultData
|
||||
{
|
||||
CostumeId = character.CostumeId,
|
||||
Csn = character.Csn,
|
||||
Level = character.Level,
|
||||
Grade = character.Grade,
|
||||
Tid = character.Tid,
|
||||
DispatchTid = character.Tid,
|
||||
Skill1Lv = character.Skill1Lvl,
|
||||
Skill2Lv = character.Skill2Lvl,
|
||||
UltiSkillLv = character.UltimateLevel,
|
||||
};
|
||||
|
||||
if (req.Category == 1)
|
||||
{
|
||||
character.UltimateLevel++;
|
||||
newChar.UltiSkillLv++;
|
||||
}
|
||||
else if (req.Category == 2)
|
||||
{
|
||||
character.Skill1Lvl++;
|
||||
newChar.Skill1Lv++;
|
||||
}
|
||||
else if (req.Category == 3)
|
||||
{
|
||||
character.Skill2Lvl++;
|
||||
newChar.Skill2Lv++;
|
||||
}
|
||||
|
||||
response.Character = newChar;
|
||||
|
||||
JsonDb.Save();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,12 +56,9 @@ namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
};
|
||||
|
||||
// remove spare body item
|
||||
var bodyItem = user.Items.FirstOrDefault(i => i.Isn == req.Isn);
|
||||
user.RemoveItemBySerialNumber(req.Isn, 1);
|
||||
|
||||
foreach (var item in user.Items)
|
||||
{
|
||||
response.Items.Add(NetUtils.ToNet(item));
|
||||
}
|
||||
response.Items.Add(NetUtils.ToNet(bodyItem));
|
||||
|
||||
// replace any reference to the old character to the new TID
|
||||
// Check if RepresentationTeamData exists and has slots
|
||||
|
||||
@@ -64,55 +64,58 @@ namespace EpinelPS.LobbyServer.Msgs.Gacha
|
||||
// Add each character's item to user.Items if the character exists in user.Characters
|
||||
foreach (var characterData in selectedCharacters)
|
||||
{
|
||||
// Check if the item for this character already exists in user.Items based on ItemType
|
||||
var existingItem = user.Items.FirstOrDefault(item => item.ItemType == characterData.piece_id);
|
||||
if (user.HasCharacter(characterData.id))
|
||||
{
|
||||
// Check if the item for this character already exists in user.Items based on ItemType
|
||||
var existingItem = user.Items.FirstOrDefault(item => item.ItemType == characterData.piece_id);
|
||||
|
||||
if (existingItem != null)
|
||||
{
|
||||
// If the item exists, increment the count
|
||||
existingItem.Count += 1;
|
||||
if (existingItem != null)
|
||||
{
|
||||
// If the item exists, increment the count
|
||||
existingItem.Count += 1;
|
||||
|
||||
// Send the updated item in the response
|
||||
response.Items.Add(new NetUserItemData()
|
||||
{
|
||||
Tid = existingItem.ItemType,
|
||||
Csn = existingItem.Csn,
|
||||
Count = existingItem.Count,
|
||||
Level = existingItem.Level,
|
||||
Exp = existingItem.Exp,
|
||||
Position = existingItem.Position,
|
||||
Isn = existingItem.Isn
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the item does not exist, create a new item entry
|
||||
var newItem = new ItemData()
|
||||
{
|
||||
ItemType = characterData.piece_id,
|
||||
Csn = 0,
|
||||
Count = 1, // or any relevant count
|
||||
Level = 0,
|
||||
Exp = 0,
|
||||
Position = 0,
|
||||
Corp = 0,
|
||||
Isn = user.GenerateUniqueItemId()
|
||||
};
|
||||
user.Items.Add(newItem);
|
||||
// Send the updated item in the response
|
||||
response.Items.Add(new NetUserItemData()
|
||||
{
|
||||
Tid = existingItem.ItemType,
|
||||
Csn = existingItem.Csn,
|
||||
Count = existingItem.Count,
|
||||
Level = existingItem.Level,
|
||||
Exp = existingItem.Exp,
|
||||
Position = existingItem.Position,
|
||||
Isn = existingItem.Isn
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the item does not exist, create a new item entry
|
||||
var newItem = new ItemData()
|
||||
{
|
||||
ItemType = characterData.piece_id,
|
||||
Csn = 0,
|
||||
Count = 1, // or any relevant count
|
||||
Level = 0,
|
||||
Exp = 0,
|
||||
Position = 0,
|
||||
Corp = 0,
|
||||
Isn = user.GenerateUniqueItemId()
|
||||
};
|
||||
user.Items.Add(newItem);
|
||||
|
||||
// Add the new item to response
|
||||
response.Items.Add(new NetUserItemData()
|
||||
{
|
||||
Tid = newItem.ItemType,
|
||||
Csn = newItem.Csn,
|
||||
Count = newItem.Count,
|
||||
Level = newItem.Level,
|
||||
Exp = newItem.Exp,
|
||||
Position = newItem.Position,
|
||||
Isn = newItem.Isn
|
||||
});
|
||||
}
|
||||
}
|
||||
// Add the new item to response
|
||||
response.Items.Add(new NetUserItemData()
|
||||
{
|
||||
Tid = newItem.ItemType,
|
||||
Csn = newItem.Csn,
|
||||
Count = newItem.Count,
|
||||
Level = newItem.Level,
|
||||
Exp = newItem.Exp,
|
||||
Position = newItem.Position,
|
||||
Isn = newItem.Isn
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Populate the 2D array with characterId and pieceId for each selected character
|
||||
foreach (var characterData in selectedCharacters)
|
||||
|
||||
@@ -104,6 +104,8 @@ namespace EpinelPS.LobbyServer.Msgs.Stage
|
||||
}
|
||||
}
|
||||
|
||||
// CreateClearInfo(user);
|
||||
|
||||
var key = (clearedStage.chapter_id - 1) + "_" + clearedStage.chapter_mod;
|
||||
if (!user.FieldInfoNew.ContainsKey(key))
|
||||
user.FieldInfoNew.Add(key, new FieldInfoNew());
|
||||
@@ -309,5 +311,29 @@ namespace EpinelPS.LobbyServer.Msgs.Stage
|
||||
}
|
||||
// TODO: add neon
|
||||
}
|
||||
|
||||
private static void CreateClearInfo(Database.User user)
|
||||
{
|
||||
NetStageClearInfo clearInfo = new NetStageClearInfo
|
||||
{
|
||||
User = LobbyHandler.CreateWholeUserDataFromDbUser(user),
|
||||
TeamCombat = user.RepresentationTeamData.TeamCombat,
|
||||
ClearedAt = DateTimeOffset.UtcNow.Ticks
|
||||
};
|
||||
|
||||
foreach (var character in user.RepresentationTeamData.Slots)
|
||||
{
|
||||
clearInfo.Slots.Add(new NetStageClearInfoTeam()
|
||||
{
|
||||
Slot = character.Slot,
|
||||
Tid = character.Tid,
|
||||
Level = character.Level,
|
||||
Combat = FormulaUtils.CalculateCP(user, character.Csn),
|
||||
CharacterType = StageClearInfoTeamCharacterType.StageClearInfoTeamCharacterTypeOwnedCharacter // TODO: how do we get this?
|
||||
});
|
||||
}
|
||||
|
||||
user.StageClearHistorys.Add(clearInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
19
EpinelPS/LobbyServer/Msgs/Stage/GetStageClearInfo.cs
Normal file
19
EpinelPS/LobbyServer/Msgs/Stage/GetStageClearInfo.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Stage
|
||||
{
|
||||
[PacketPath("/stageclearinfo/get")]
|
||||
public class GetStageClearInfo : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqGetStageClearInfo>();
|
||||
var response = new ResGetStageClearInfo();
|
||||
var user = GetUser();
|
||||
|
||||
response.Historys.AddRange(user.StageClearHistorys);
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
24
EpinelPS/LobbyServer/Msgs/User/BuyWallpaper.cs
Normal file
24
EpinelPS/LobbyServer/Msgs/User/BuyWallpaper.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.User
|
||||
{
|
||||
[PacketPath("/user/wallpaper/buy")]
|
||||
public class BuyWallpaper : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqBuyLobbyDecoBackground>();
|
||||
var response = new ResBuyLobbyDecoBackground();
|
||||
var user = GetUser();
|
||||
|
||||
user.LobbyDecoBackgroundList.Add(req.LobbyDecoBackgroundId);
|
||||
|
||||
response.OwnedLobbyDecoBackgroundIdList.Add(user.LobbyDecoBackgroundList);
|
||||
|
||||
JsonDb.Save();
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,6 +85,8 @@ namespace EpinelPS.LobbyServer.Msgs.User
|
||||
response.LastClearedNormalMainStageId = user.LastNormalStageCleared;
|
||||
response.TimeRewardBuffs.AddRange(NetUtils.GetOutpostTimeReward(user));
|
||||
|
||||
response.OwnedLobbyDecoBackgroundIdList.AddRange(user.LobbyDecoBackgroundList);
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace EpinelPS.LobbyServer.Msgs.User
|
||||
response.WallpaperJukeboxList.AddRange(user.WallpaperJukeboxList);
|
||||
response.WallpaperBackgroundList.AddRange(user.WallpaperBackground);
|
||||
response.WallpaperFavoriteList.AddRange(user.WallpaperFavoriteList);
|
||||
response.OwnedLobbyDecoBackgroundIdList.AddRange(user.LobbyDecoBackgroundList);
|
||||
|
||||
// TODO: JukeboxIdList
|
||||
|
||||
|
||||
@@ -217,13 +217,16 @@ namespace EpinelPS
|
||||
Console.WriteLine(" unban - unban selected user from game");
|
||||
Console.WriteLine(" exit - exit server application");
|
||||
Console.WriteLine(" completestage (chapter num)-(stage number) - complete selected stage and get rewards (and all previous ones). Example completestage 15-1. Note that the exact stage number cleared may not be exact.");
|
||||
Console.WriteLine(" sickpulls (requires selecting user first) allows for all characters to have equal chances of getting pulled");
|
||||
Console.WriteLine(" sickpulls (requires selecting user first) allows for all characters to have equal chances of getting pulled");
|
||||
Console.WriteLine(" SetLevel (level) - Set all characters' level (between 1 and 999 takes effect on game and server restart)");
|
||||
Console.WriteLine(" SetSkillLevel (level) - Set all characters' skill levels between 1 and 10 (takes effect on game and server restart)");
|
||||
Console.WriteLine(" addallcharacters - Add all missing characters to the selected user with default levels and skills (takes effect on game and server restart)");
|
||||
Console.WriteLine(" addallmaterials (amount) - Add all materials to the selected user with default levels and skills (takes effect on game and server restart)");
|
||||
Console.WriteLine(" finishalltutorials - finish all tutorials for the selected user (takes effect on game and server restart)");
|
||||
Console.WriteLine(" SetCoreLevel (core level / 0-3 sets stars) - Set all characters' grades based on the input (from 0 to 11)");
|
||||
|
||||
}
|
||||
Console.WriteLine(" AddItem (id) (amount) - Adds an item to the selected user (takes effect on game and server restart)");
|
||||
Console.WriteLine(" AddCharacter (id) - Adds a character to the selected user (takes effect on game and server restart)");
|
||||
}
|
||||
else if (input == "ls /users")
|
||||
{
|
||||
Console.WriteLine("Id,Username,Nickname");
|
||||
@@ -263,299 +266,378 @@ namespace EpinelPS
|
||||
Console.WriteLine("Usage: chroot (user id)");
|
||||
}
|
||||
}
|
||||
else if (input == "addallcharacters")
|
||||
{
|
||||
if (selectedUser == 0)
|
||||
{
|
||||
Console.WriteLine("No user selected");
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser);
|
||||
if (user == null)
|
||||
{
|
||||
Console.WriteLine("Selected user does not exist");
|
||||
selectedUser = 0;
|
||||
prompt = "# ";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Group characters by name_code and always add those with grade_core_id == 11, 103, and include grade_core_id == 201
|
||||
var allCharacters = GameData.Instance.characterTable.Values
|
||||
.GroupBy(c => c.name_code) // Group by name_code to treat same name_code as one character 3999 = marian
|
||||
.SelectMany(g => g.Where(c => c.grade_core_id == 1 || c.grade_core_id == 101 || c.grade_core_id == 201 || c.name_code == 3999)) // Always add characters with grade_core_id == 11 and 103
|
||||
.ToList();
|
||||
else if (input == "addallcharacters")
|
||||
{
|
||||
if (selectedUser == 0)
|
||||
{
|
||||
Console.WriteLine("No user selected");
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser);
|
||||
if (user == null)
|
||||
{
|
||||
Console.WriteLine("Selected user does not exist");
|
||||
selectedUser = 0;
|
||||
prompt = "# ";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Group characters by name_code and always add those with grade_core_id == 11, 103, and include grade_core_id == 201
|
||||
var allCharacters = GameData.Instance.characterTable.Values
|
||||
.GroupBy(c => c.name_code) // Group by name_code to treat same name_code as one character 3999 = marian
|
||||
.SelectMany(g => g.Where(c => c.grade_core_id == 1 || c.grade_core_id == 101 || c.grade_core_id == 201 || c.name_code == 3999)) // Always add characters with grade_core_id == 11 and 103
|
||||
.ToList();
|
||||
|
||||
foreach (var character in allCharacters)
|
||||
{
|
||||
if (!user.HasCharacter(character.id))
|
||||
{
|
||||
user.Characters.Add(new Database.Character()
|
||||
{
|
||||
CostumeId = 0,
|
||||
Csn = user.GenerateUniqueCharacterId(),
|
||||
Grade = 0,
|
||||
Level = 1,
|
||||
Skill1Lvl = 1,
|
||||
Skill2Lvl = 1,
|
||||
Tid = character.id, // Tid is the character ID
|
||||
UltimateLevel = 1
|
||||
});
|
||||
}
|
||||
}
|
||||
foreach (var character in allCharacters)
|
||||
{
|
||||
if (!user.HasCharacter(character.id))
|
||||
{
|
||||
user.Characters.Add(new Database.Character()
|
||||
{
|
||||
CostumeId = 0,
|
||||
Csn = user.GenerateUniqueCharacterId(),
|
||||
Grade = 0,
|
||||
Level = 1,
|
||||
Skill1Lvl = 1,
|
||||
Skill2Lvl = 1,
|
||||
Tid = character.id, // Tid is the character ID
|
||||
UltimateLevel = 1
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("Added all missing characters to user " + user.Username);
|
||||
JsonDb.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (input.StartsWith("SetCoreLevel"))
|
||||
{
|
||||
if (selectedUser == 0)
|
||||
{
|
||||
Console.WriteLine("No user selected");
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser);
|
||||
if (user == null)
|
||||
{
|
||||
Console.WriteLine("Selected user does not exist");
|
||||
selectedUser = 0;
|
||||
prompt = "# ";
|
||||
}
|
||||
else if (args.Length == 2 && int.TryParse(args[1], out int inputGrade) && inputGrade >= 0 && inputGrade <= 11)
|
||||
{
|
||||
foreach (var character in user.Characters)
|
||||
{
|
||||
// Get current character's Tid
|
||||
int tid = character.Tid;
|
||||
Console.WriteLine("Added all missing characters to user " + user.Username);
|
||||
JsonDb.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (input == "addallmaterials")
|
||||
{
|
||||
if (selectedUser == 0)
|
||||
{
|
||||
Console.WriteLine("No user selected");
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser);
|
||||
if (user == null)
|
||||
{
|
||||
Console.WriteLine("Selected user does not exist");
|
||||
selectedUser = 0;
|
||||
prompt = "# ";
|
||||
}
|
||||
else
|
||||
{
|
||||
int amount = 1000000;
|
||||
if (args.Length >= 2)
|
||||
{
|
||||
int.TryParse(args[1], out amount);
|
||||
}
|
||||
|
||||
// Get the character data from the character table
|
||||
if (!GameData.Instance.characterTable.TryGetValue(tid, out var charData))
|
||||
{
|
||||
Console.WriteLine($"Character data not found for Tid {tid}");
|
||||
continue;
|
||||
}
|
||||
foreach (var tableItem in GameData.Instance.itemMaterialTable.Values)
|
||||
{
|
||||
ItemData? item = user.Items.FirstOrDefault(i => i.ItemType == tableItem.id);
|
||||
|
||||
int currentGradeCoreId = charData.grade_core_id;
|
||||
int nameCode = charData.name_code;
|
||||
string originalRare = charData.original_rare;
|
||||
if (item == null)
|
||||
{
|
||||
user.Items.Add(new ItemData
|
||||
{
|
||||
Isn = user.GenerateUniqueItemId(),
|
||||
ItemType = tableItem.id,
|
||||
Level = 1,
|
||||
Exp = 1,
|
||||
Count = amount
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Count += amount;
|
||||
}
|
||||
}
|
||||
|
||||
// Skip characters with original_rare == "R"
|
||||
if (originalRare == "R" || nameCode == 3999)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
Console.WriteLine($"Added {amount} of all materials to user " + user.Username);
|
||||
JsonDb.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (input == "finishalltutorials")
|
||||
{
|
||||
if (selectedUser == 0)
|
||||
{
|
||||
Console.WriteLine("No user selected");
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser);
|
||||
if (user == null)
|
||||
{
|
||||
Console.WriteLine("Selected user does not exist");
|
||||
selectedUser = 0;
|
||||
prompt = "# ";
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var tutorial in GameData.Instance.tutorialTable.Values)
|
||||
{
|
||||
if (!user.ClearedTutorialData.ContainsKey(tutorial.id))
|
||||
{
|
||||
user.ClearedTutorialData.Add(tutorial.id, tutorial);
|
||||
}
|
||||
}
|
||||
|
||||
// Now handle normal SR and SSR characters
|
||||
int maxGradeCoreId = 0;
|
||||
Console.WriteLine("Finished all tutorials for user " + user.Username);
|
||||
JsonDb.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (input.StartsWith("SetCoreLevel"))
|
||||
{
|
||||
if (selectedUser == 0)
|
||||
{
|
||||
Console.WriteLine("No user selected");
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser);
|
||||
if (user == null)
|
||||
{
|
||||
Console.WriteLine("Selected user does not exist");
|
||||
selectedUser = 0;
|
||||
prompt = "# ";
|
||||
}
|
||||
else if (args.Length == 2 && int.TryParse(args[1], out int inputGrade) && inputGrade >= 0 && inputGrade <= 11)
|
||||
{
|
||||
foreach (var character in user.Characters)
|
||||
{
|
||||
// Get current character's Tid
|
||||
int tid = character.Tid;
|
||||
|
||||
// If the character is "SSR", it can have a grade_core_id from 1 to 11
|
||||
if (originalRare == "SSR")
|
||||
{
|
||||
maxGradeCoreId = 11; // SSR characters can go from 1 to 11
|
||||
// Get the character data from the character table
|
||||
if (!GameData.Instance.characterTable.TryGetValue(tid, out var charData))
|
||||
{
|
||||
Console.WriteLine($"Character data not found for Tid {tid}");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calculate the new grade_core_id within the bounds
|
||||
int newGradeCoreId = Math.Min(inputGrade + 1, maxGradeCoreId); // +1 because inputGrade starts from 0 for SSRs
|
||||
int currentGradeCoreId = charData.grade_core_id;
|
||||
int nameCode = charData.name_code;
|
||||
string originalRare = charData.original_rare;
|
||||
|
||||
// Find the character with the same name_code and new grade_core_id
|
||||
var newCharData = GameData.Instance.characterTable.Values.FirstOrDefault(c =>
|
||||
c.name_code == nameCode && c.grade_core_id == newGradeCoreId);
|
||||
// Skip characters with original_rare == "R"
|
||||
if (originalRare == "R" || nameCode == 3999)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (newCharData != null)
|
||||
{
|
||||
// Update the character's Tid and Grade
|
||||
character.Tid = newCharData.id;
|
||||
character.Grade = inputGrade;
|
||||
}
|
||||
// Now handle normal SR and SSR characters
|
||||
int maxGradeCoreId = 0;
|
||||
|
||||
}
|
||||
// If the character is "SSR", it can have a grade_core_id from 1 to 11
|
||||
if (originalRare == "SSR")
|
||||
{
|
||||
maxGradeCoreId = 11; // SSR characters can go from 1 to 11
|
||||
|
||||
// If the character is "SR", it can have a grade_core_id from 101 to 103
|
||||
else if (originalRare == "SR")
|
||||
{
|
||||
maxGradeCoreId = 103; // SR characters can go from 101 to 103
|
||||
// Calculate the new grade_core_id within the bounds
|
||||
int newGradeCoreId = Math.Min(inputGrade + 1, maxGradeCoreId); // +1 because inputGrade starts from 0 for SSRs
|
||||
|
||||
// Start from 101 and increment based on inputGrade (inputGrade 0 -> grade_core_id 101)
|
||||
int newGradeCoreId = Math.Min(101 + inputGrade, maxGradeCoreId); // Starts at 101
|
||||
// Find the character with the same name_code and new grade_core_id
|
||||
var newCharData = GameData.Instance.characterTable.Values.FirstOrDefault(c =>
|
||||
c.name_code == nameCode && c.grade_core_id == newGradeCoreId);
|
||||
|
||||
// Find the character with the same name_code and new grade_core_id
|
||||
var newCharData = GameData.Instance.characterTable.Values.FirstOrDefault(c =>
|
||||
c.name_code == nameCode && c.grade_core_id == newGradeCoreId);
|
||||
if (newCharData != null)
|
||||
{
|
||||
// Update the character's Tid and Grade
|
||||
character.Tid = newCharData.id;
|
||||
character.Grade = inputGrade;
|
||||
}
|
||||
|
||||
if (newCharData != null)
|
||||
{
|
||||
// Update the character's Tid and Grade
|
||||
character.Tid = newCharData.id;
|
||||
character.Grade = inputGrade;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// If the character is "SR", it can have a grade_core_id from 101 to 103
|
||||
else if (originalRare == "SR")
|
||||
{
|
||||
maxGradeCoreId = 103; // SR characters can go from 101 to 103
|
||||
|
||||
}
|
||||
Console.WriteLine($"Core level of all characters have been set to {inputGrade}");
|
||||
JsonDb.Save();
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid argument. Core level must be between 0 and 11.");
|
||||
}
|
||||
}
|
||||
//code above WILL change tids in user.characters so this will update them in representation team
|
||||
foreach (var user in JsonDb.Instance.Users)
|
||||
{
|
||||
// Check if RepresentationTeamData exists and has slots
|
||||
if (user.RepresentationTeamData != null && user.RepresentationTeamData.Slots != null)
|
||||
{
|
||||
// Iterate through RepresentationTeamData slots
|
||||
foreach (var slot in user.RepresentationTeamData.Slots)
|
||||
{
|
||||
// Find the character in user's character list that matches the slot's Csn
|
||||
var correspondingCharacter = user.Characters.FirstOrDefault(c => c.Csn == slot.Csn);
|
||||
// Start from 101 and increment based on inputGrade (inputGrade 0 -> grade_core_id 101)
|
||||
int newGradeCoreId = Math.Min(101 + inputGrade, maxGradeCoreId); // Starts at 101
|
||||
|
||||
if (correspondingCharacter != null)
|
||||
{
|
||||
// Update the Tid value if it differs
|
||||
if (slot.Tid != correspondingCharacter.Tid)
|
||||
{
|
||||
slot.Tid = correspondingCharacter.Tid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Find the character with the same name_code and new grade_core_id
|
||||
var newCharData = GameData.Instance.characterTable.Values.FirstOrDefault(c =>
|
||||
c.name_code == nameCode && c.grade_core_id == newGradeCoreId);
|
||||
|
||||
// Save the updated data
|
||||
JsonDb.Save();
|
||||
if (newCharData != null)
|
||||
{
|
||||
// Update the character's Tid and Grade
|
||||
character.Tid = newCharData.id;
|
||||
character.Grade = inputGrade;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Console.WriteLine($"Core level of all characters have been set to {inputGrade}");
|
||||
JsonDb.Save();
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid argument. Core level must be between 0 and 11.");
|
||||
}
|
||||
}
|
||||
//code above WILL change tids in user.characters so this will update them in representation team
|
||||
foreach (var user in JsonDb.Instance.Users)
|
||||
{
|
||||
// Check if RepresentationTeamData exists and has slots
|
||||
if (user.RepresentationTeamData != null && user.RepresentationTeamData.Slots != null)
|
||||
{
|
||||
// Iterate through RepresentationTeamData slots
|
||||
foreach (var slot in user.RepresentationTeamData.Slots)
|
||||
{
|
||||
// Find the character in user's character list that matches the slot's Csn
|
||||
var correspondingCharacter = user.Characters.FirstOrDefault(c => c.Csn == slot.Csn);
|
||||
|
||||
if (correspondingCharacter != null)
|
||||
{
|
||||
// Update the Tid value if it differs
|
||||
if (slot.Tid != correspondingCharacter.Tid)
|
||||
{
|
||||
slot.Tid = correspondingCharacter.Tid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save the updated data
|
||||
JsonDb.Save();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
else if (input == "sickpulls")
|
||||
{
|
||||
if (selectedUser == 0)
|
||||
{
|
||||
Console.WriteLine("No user selected");
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser);
|
||||
if (user == null)
|
||||
{
|
||||
Console.WriteLine("Selected user does not exist");
|
||||
selectedUser = 0;
|
||||
prompt = "# ";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check current value of sickpulls and toggle it
|
||||
bool currentSickPulls = EpinelPS.Database.JsonDb.IsSickPulls(user);
|
||||
if (currentSickPulls)
|
||||
{
|
||||
user.sickpulls = false;
|
||||
Console.WriteLine("sickpulls is now set to false for user " + user.Username);
|
||||
}
|
||||
else
|
||||
{
|
||||
user.sickpulls = true;
|
||||
Console.WriteLine("sickpulls is now set to true for user " + user.Username);
|
||||
}
|
||||
else if (input == "sickpulls")
|
||||
{
|
||||
if (selectedUser == 0)
|
||||
{
|
||||
Console.WriteLine("No user selected");
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser);
|
||||
if (user == null)
|
||||
{
|
||||
Console.WriteLine("Selected user does not exist");
|
||||
selectedUser = 0;
|
||||
prompt = "# ";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check current value of sickpulls and toggle it
|
||||
bool currentSickPulls = EpinelPS.Database.JsonDb.IsSickPulls(user);
|
||||
if (currentSickPulls)
|
||||
{
|
||||
user.sickpulls = false;
|
||||
Console.WriteLine("sickpulls is now set to false for user " + user.Username);
|
||||
}
|
||||
else
|
||||
{
|
||||
user.sickpulls = true;
|
||||
Console.WriteLine("sickpulls is now set to true for user " + user.Username);
|
||||
}
|
||||
|
||||
// Save the changes to the database
|
||||
JsonDb.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (input.StartsWith("SetLevel"))
|
||||
{
|
||||
if (selectedUser == 0)
|
||||
{
|
||||
Console.WriteLine("No user selected");
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser);
|
||||
if (user == null)
|
||||
{
|
||||
Console.WriteLine("Selected user does not exist");
|
||||
selectedUser = 0;
|
||||
prompt = "# ";
|
||||
}
|
||||
else if (args.Length == 2 && int.TryParse(args[1], out int level) && level >= 1 && level <= 999)
|
||||
{
|
||||
foreach (var character in user.Characters)
|
||||
{
|
||||
character.Level = level;
|
||||
}
|
||||
Console.WriteLine("Set all characters' level to " + level);
|
||||
JsonDb.Save();
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid argument. Level must be between 1 and 999.");
|
||||
}
|
||||
}
|
||||
//code above WILL change levels in user.characters so this will update them in representation team
|
||||
foreach (var user in JsonDb.Instance.Users)
|
||||
{
|
||||
// Check if RepresentationTeamData exists and has slots
|
||||
if (user.RepresentationTeamData != null && user.RepresentationTeamData.Slots != null)
|
||||
{
|
||||
// Iterate through RepresentationTeamData slots
|
||||
foreach (var slot in user.RepresentationTeamData.Slots)
|
||||
{
|
||||
// Find the character in user's character list that matches the slot's Csn
|
||||
var correspondingCharacter = user.Characters.FirstOrDefault(c => c.Csn == slot.Csn);
|
||||
// Save the changes to the database
|
||||
JsonDb.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (input.StartsWith("SetLevel"))
|
||||
{
|
||||
if (selectedUser == 0)
|
||||
{
|
||||
Console.WriteLine("No user selected");
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser);
|
||||
if (user == null)
|
||||
{
|
||||
Console.WriteLine("Selected user does not exist");
|
||||
selectedUser = 0;
|
||||
prompt = "# ";
|
||||
}
|
||||
else if (args.Length == 2 && int.TryParse(args[1], out int level) && level >= 1 && level <= 999)
|
||||
{
|
||||
foreach (var character in user.Characters)
|
||||
{
|
||||
character.Level = level;
|
||||
}
|
||||
Console.WriteLine("Set all characters' level to " + level);
|
||||
JsonDb.Save();
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid argument. Level must be between 1 and 999.");
|
||||
}
|
||||
}
|
||||
//code above WILL change levels in user.characters so this will update them in representation team
|
||||
foreach (var user in JsonDb.Instance.Users)
|
||||
{
|
||||
// Check if RepresentationTeamData exists and has slots
|
||||
if (user.RepresentationTeamData != null && user.RepresentationTeamData.Slots != null)
|
||||
{
|
||||
// Iterate through RepresentationTeamData slots
|
||||
foreach (var slot in user.RepresentationTeamData.Slots)
|
||||
{
|
||||
// Find the character in user's character list that matches the slot's Csn
|
||||
var correspondingCharacter = user.Characters.FirstOrDefault(c => c.Csn == slot.Csn);
|
||||
|
||||
if (correspondingCharacter != null)
|
||||
{
|
||||
// Update the Level value if it differs
|
||||
if (slot.Level != correspondingCharacter.Level)
|
||||
{
|
||||
slot.Level = correspondingCharacter.Level;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (correspondingCharacter != null)
|
||||
{
|
||||
// Update the Level value if it differs
|
||||
if (slot.Level != correspondingCharacter.Level)
|
||||
{
|
||||
slot.Level = correspondingCharacter.Level;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save the updated data
|
||||
JsonDb.Save();
|
||||
}
|
||||
else if (input.StartsWith("SetSkillLevel"))
|
||||
{
|
||||
if (selectedUser == 0)
|
||||
{
|
||||
Console.WriteLine("No user selected");
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser);
|
||||
if (user == null)
|
||||
{
|
||||
Console.WriteLine("Selected user does not exist");
|
||||
selectedUser = 0;
|
||||
prompt = "# ";
|
||||
}
|
||||
else if (args.Length == 2 && int.TryParse(args[1], out int skillLevel) && skillLevel >= 1 && skillLevel <= 10)
|
||||
{
|
||||
foreach (var character in user.Characters)
|
||||
{
|
||||
character.UltimateLevel = skillLevel;
|
||||
character.Skill1Lvl = skillLevel;
|
||||
character.Skill2Lvl = skillLevel;
|
||||
}
|
||||
Console.WriteLine("Set all characters' skill levels to " + skillLevel);
|
||||
JsonDb.Save();
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid argument. Skill level must be between 1 and 10.");
|
||||
}
|
||||
}
|
||||
}
|
||||
// Save the updated data
|
||||
JsonDb.Save();
|
||||
}
|
||||
else if (input.StartsWith("SetSkillLevel"))
|
||||
{
|
||||
if (selectedUser == 0)
|
||||
{
|
||||
Console.WriteLine("No user selected");
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser);
|
||||
if (user == null)
|
||||
{
|
||||
Console.WriteLine("Selected user does not exist");
|
||||
selectedUser = 0;
|
||||
prompt = "# ";
|
||||
}
|
||||
else if (args.Length == 2 && int.TryParse(args[1], out int skillLevel) && skillLevel >= 1 && skillLevel <= 10)
|
||||
{
|
||||
foreach (var character in user.Characters)
|
||||
{
|
||||
character.UltimateLevel = skillLevel;
|
||||
character.Skill1Lvl = skillLevel;
|
||||
character.Skill2Lvl = skillLevel;
|
||||
}
|
||||
Console.WriteLine("Set all characters' skill levels to " + skillLevel);
|
||||
JsonDb.Save();
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid argument. Skill level must be between 1 and 10.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (input.StartsWith("rmuser"))
|
||||
{
|
||||
@@ -591,108 +673,218 @@ namespace EpinelPS
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (input.StartsWith("completestage"))
|
||||
{
|
||||
if (selectedUser == 0)
|
||||
{
|
||||
Console.WriteLine("No user selected");
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser);
|
||||
if (user == null)
|
||||
{
|
||||
Console.WriteLine("Selected user does not exist");
|
||||
selectedUser = 0;
|
||||
prompt = "# ";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (args.Length == 2)
|
||||
{
|
||||
var input2 = args[1];
|
||||
try
|
||||
{
|
||||
var chapterParsed = int.TryParse(input2.Split('-')[0], out int chapterNumber);
|
||||
var stageParsed = int.TryParse(input2.Split('-')[1], out int stageNumber);
|
||||
else if (input.StartsWith("completestage"))
|
||||
{
|
||||
if (selectedUser == 0)
|
||||
{
|
||||
Console.WriteLine("No user selected");
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser);
|
||||
if (user == null)
|
||||
{
|
||||
Console.WriteLine("Selected user does not exist");
|
||||
selectedUser = 0;
|
||||
prompt = "# ";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (args.Length == 2)
|
||||
{
|
||||
var input2 = args[1];
|
||||
try
|
||||
{
|
||||
var chapterParsed = int.TryParse(input2.Split('-')[0], out int chapterNumber);
|
||||
var stageParsed = int.TryParse(input2.Split('-')[1], out int stageNumber);
|
||||
|
||||
if (chapterParsed && stageParsed)
|
||||
{
|
||||
Console.WriteLine($"Chapter number: {chapterNumber}, Stage number: {stageNumber}");
|
||||
if (chapterParsed && stageParsed)
|
||||
{
|
||||
Console.WriteLine($"Chapter number: {chapterNumber}, Stage number: {stageNumber}");
|
||||
|
||||
// Complete main stages
|
||||
for (int i = 0; i <= chapterNumber; i++)
|
||||
{
|
||||
var stages = GameData.Instance.GetStageIdsForChapter(i, true);
|
||||
int target = 1;
|
||||
foreach (var item in stages)
|
||||
{
|
||||
if (!user.IsStageCompleted(item, true))
|
||||
{
|
||||
Console.WriteLine("Completing stage " + item);
|
||||
ClearStage.CompleteStage(user, item, true);
|
||||
}
|
||||
// Complete main stages
|
||||
for (int i = 0; i <= chapterNumber; i++)
|
||||
{
|
||||
var stages = GameData.Instance.GetStageIdsForChapter(i, true);
|
||||
int target = 1;
|
||||
foreach (var item in stages)
|
||||
{
|
||||
if (!user.IsStageCompleted(item, true))
|
||||
{
|
||||
Console.WriteLine("Completing stage " + item);
|
||||
ClearStage.CompleteStage(user, item, true);
|
||||
}
|
||||
|
||||
if (i == chapterNumber && target == stageNumber)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (i == chapterNumber && target == stageNumber)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
target++;
|
||||
}
|
||||
}
|
||||
target++;
|
||||
}
|
||||
}
|
||||
|
||||
// Process scenario and regular stages
|
||||
Console.WriteLine($"Processing stages for chapters 0 to {chapterNumber}");
|
||||
// Process scenario and regular stages
|
||||
Console.WriteLine($"Processing stages for chapters 0 to {chapterNumber}");
|
||||
|
||||
for (int chapter = 0; chapter <= chapterNumber; chapter++)
|
||||
{
|
||||
Console.WriteLine($"Processing chapter: {chapter}");
|
||||
for (int chapter = 0; chapter <= chapterNumber; chapter++)
|
||||
{
|
||||
Console.WriteLine($"Processing chapter: {chapter}");
|
||||
|
||||
var stages = GameData.Instance.GetScenarioStageIdsForChapter(chapter)
|
||||
.Where(stageId => GameData.Instance.IsValidScenarioStage(stageId, chapterNumber, stageNumber))
|
||||
.ToList();
|
||||
var stages = GameData.Instance.GetScenarioStageIdsForChapter(chapter)
|
||||
.Where(stageId => GameData.Instance.IsValidScenarioStage(stageId, chapterNumber, stageNumber))
|
||||
.ToList();
|
||||
|
||||
Console.WriteLine($"Found {stages.Count} stages for chapter {chapter}");
|
||||
Console.WriteLine($"Found {stages.Count} stages for chapter {chapter}");
|
||||
|
||||
foreach (var stage in stages)
|
||||
{
|
||||
if (!user.CompletedScenarios.Contains(stage))
|
||||
{
|
||||
user.CompletedScenarios.Add(stage);
|
||||
Console.WriteLine($"Added stage {stage} to CompletedScenarios");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Stage {stage} is already completed");
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach (var stage in stages)
|
||||
{
|
||||
if (!user.CompletedScenarios.Contains(stage))
|
||||
{
|
||||
user.CompletedScenarios.Add(stage);
|
||||
Console.WriteLine($"Added stage {stage} to CompletedScenarios");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Stage {stage} is already completed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save changes to user data
|
||||
JsonDb.Save();
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Chapter and stage number must be valid integers");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Exception: " + ex.ToString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid argument length, must be 1");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Save changes to user data
|
||||
JsonDb.Save();
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Chapter and stage number must be valid integers");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine("Exception: " + ex.ToString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid argument length, must be 1");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (input.StartsWith("AddItem"))
|
||||
{
|
||||
if (selectedUser == 0)
|
||||
{
|
||||
Console.WriteLine("No user selected");
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser);
|
||||
if (user == null)
|
||||
{
|
||||
Console.WriteLine("Selected user does not exist");
|
||||
selectedUser = 0;
|
||||
prompt = "# ";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (args.Length == 3)
|
||||
{
|
||||
if (int.TryParse(args[1], out int itemId) && int.TryParse(args[2], out int amount))
|
||||
{
|
||||
ItemData? item = user.Items.FirstOrDefault(i => i.ItemType == itemId);
|
||||
|
||||
if (item == null)
|
||||
{
|
||||
user.Items.Add(new ItemData
|
||||
{
|
||||
Isn = user.GenerateUniqueItemId(),
|
||||
ItemType = itemId,
|
||||
Level = 1,
|
||||
Exp = 1,
|
||||
Count = amount
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
item.Count += amount;
|
||||
|
||||
if (item.Count < 0)
|
||||
{
|
||||
item.Count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine($"Added {amount} of item {itemId} to user {user.Username}");
|
||||
JsonDb.Save();
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid item ID or amount");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid argument length, must be 2");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (input.StartsWith("AddCharacter"))
|
||||
{
|
||||
if (selectedUser == 0)
|
||||
{
|
||||
Console.WriteLine("No user selected");
|
||||
}
|
||||
else
|
||||
{
|
||||
var user = JsonDb.Instance.Users.FirstOrDefault(x => x.ID == selectedUser);
|
||||
if (user == null)
|
||||
{
|
||||
Console.WriteLine("Selected user does not exist");
|
||||
selectedUser = 0;
|
||||
prompt = "# ";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (args.Length == 2)
|
||||
{
|
||||
if (int.TryParse(args[1], out int characterId))
|
||||
{
|
||||
if (!user.HasCharacter(characterId))
|
||||
{
|
||||
user.Characters.Add(new Database.Character()
|
||||
{
|
||||
CostumeId = 0,
|
||||
Csn = user.GenerateUniqueCharacterId(),
|
||||
Grade = 0,
|
||||
Level = 1,
|
||||
Skill1Lvl = 1,
|
||||
Skill2Lvl = 1,
|
||||
Tid = characterId,
|
||||
UltimateLevel = 1
|
||||
});
|
||||
|
||||
Console.WriteLine($"Added character {characterId} to user {user.Username}");
|
||||
JsonDb.Save();
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"User {user.Username} already has character {characterId}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid character ID");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Invalid argument length, must be 1");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (input == "exit")
|
||||
{
|
||||
Environment.Exit(0);
|
||||
|
||||
32
EpinelPS/Utils/FormulaUtils.cs
Normal file
32
EpinelPS/Utils/FormulaUtils.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using EpinelPS.StaticInfo;
|
||||
|
||||
namespace EpinelPS.Utils
|
||||
{
|
||||
public class FormulaUtils
|
||||
{
|
||||
public static int CalculateCP(Database.User user, long csn)
|
||||
{
|
||||
var character = user.Characters.FirstOrDefault(c => c.Csn == csn);
|
||||
var charRecord = GameData.Instance.characterTable.Values.FirstOrDefault(c => c.id == character.Tid);
|
||||
var statRecord = GameData.Instance.characterStatTable.Values.FirstOrDefault(s => charRecord.stat_enhance_id == s.group + (character.Level - 1));
|
||||
float coreMult = 1f + character.Grade * 0.02f;
|
||||
float hp = statRecord.level_hp * coreMult;
|
||||
float atk = statRecord.level_attack * coreMult;
|
||||
float def = statRecord.level_defence * coreMult;
|
||||
float critRate = charRecord.critical_ratio;
|
||||
float critDamage = charRecord.critical_damage;
|
||||
float skill1Level = character.Skill1Lvl;
|
||||
float skill2Level = character.Skill2Lvl;
|
||||
float ultSkillLevel = character.UltimateLevel;
|
||||
float critResult = 1 + ((critRate / 10000f) * (critDamage / 10000f - 1));
|
||||
float effHealthResult = (def * 100) + hp;
|
||||
float skillResult = (skill1Level * 0.01f) + (skill2Level * 0.01f) + (ultSkillLevel * 0.02f);
|
||||
float bondResult = 0f; // TODO
|
||||
float equipResult = 0f; // TOD
|
||||
float overloadResult = 0; // TODO
|
||||
float finalResult = (((critResult * atk * 18) + (effHealthResult * 0.7f)) * (1.3f + skillResult) + bondResult + equipResult + overloadResult) / 100f;
|
||||
|
||||
return (int)Math.Round(finalResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,7 @@ To skip stages, a basic command line interface is implemented.
|
||||
- [X] Outpost Rewards
|
||||
- [ ] Admin Panel
|
||||
- [ ] Simulation Room
|
||||
- [ ] Skill level up
|
||||
- [X] Skill level up
|
||||
- [ ] Outpost jukebox
|
||||
- [ ] Event system
|
||||
- [ ] Download all game assets ahead of time
|
||||
@@ -57,7 +57,6 @@ To skip stages, a basic command line interface is implemented.
|
||||
|
||||
## What is not working:
|
||||
- Events
|
||||
- Skill upgrade
|
||||
- Mission reward, daily/weekly missions
|
||||
- Side quests
|
||||
- Lots of things in the outpost
|
||||
|
||||
Reference in New Issue
Block a user