mirror of
https://github.com/EpinelPS/EpinelPS.git
synced 2025-12-14 16:04:36 +01:00
Synchro device
This commit is contained in:
@@ -3,6 +3,8 @@ using EpinelPS.LobbyServer;
|
||||
using EpinelPS.StaticInfo;
|
||||
using EpinelPS.Utils;
|
||||
using Swan.Logging;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using static Google.Rpc.Context.AttributeContext.Types;
|
||||
|
||||
namespace EpinelPS.Database
|
||||
{
|
||||
@@ -64,6 +66,21 @@ namespace EpinelPS.Database
|
||||
public List<string> CompletedScenarios = new();
|
||||
}
|
||||
|
||||
public class SynchroSlot
|
||||
{
|
||||
/// <summary>
|
||||
/// Index of slot, 1 based
|
||||
/// </summary>
|
||||
public int Slot;
|
||||
/// <summary>
|
||||
/// Character CSN
|
||||
/// </summary>
|
||||
public long CharacterSerialNumber;
|
||||
/// <summary>
|
||||
/// Time when slot cooldown expires
|
||||
/// </summary>
|
||||
public long AvailableAt;
|
||||
}
|
||||
public class User
|
||||
{
|
||||
// User info
|
||||
@@ -94,6 +111,9 @@ namespace EpinelPS.Database
|
||||
public Dictionary<CurrencyType, long> Currency = new() {
|
||||
{ CurrencyType.ContentStamina, 2 }
|
||||
};
|
||||
public List<SynchroSlot> SynchroSlots = new List<SynchroSlot>();
|
||||
public bool SynchroDeviceUpgraded = false;
|
||||
public int SynchroDeviceLevel = 200;
|
||||
|
||||
public List<ItemData> Items = new();
|
||||
public List<Character> Characters = [];
|
||||
@@ -219,6 +239,45 @@ namespace EpinelPS.Database
|
||||
{
|
||||
return Characters.Where(x => x.Csn == value).FirstOrDefault();
|
||||
}
|
||||
|
||||
internal bool GetSynchro(long csn)
|
||||
{
|
||||
return SynchroSlots.Where(x => x.CharacterSerialNumber == csn).Count() >= 1;
|
||||
}
|
||||
internal int GetCharacterLevel(int csn)
|
||||
{
|
||||
var c = GetCharacterBySerialNumber(csn);
|
||||
if (c == null) throw new Exception("failed to lookup character");
|
||||
|
||||
return GetCharacterLevel(csn, c.Level);
|
||||
}
|
||||
internal int GetCharacterLevel(int csn, int characterLevel)
|
||||
{
|
||||
foreach (var item in SynchroSlots)
|
||||
{
|
||||
if (item.CharacterSerialNumber == csn)
|
||||
{
|
||||
return GetSynchroLevel();
|
||||
}
|
||||
}
|
||||
return characterLevel;
|
||||
}
|
||||
internal int GetSynchroLevel()
|
||||
{
|
||||
if (SynchroDeviceUpgraded)
|
||||
return SynchroDeviceLevel;
|
||||
var highestLevelCharacters = Characters.OrderByDescending(x => x.Level).Take(5).ToList();
|
||||
|
||||
|
||||
if (highestLevelCharacters.Count > 0)
|
||||
{
|
||||
return highestLevelCharacters.Last().Level;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
public class CoreInfo
|
||||
{
|
||||
|
||||
54
EpinelPS/LobbyServer/Msgs/Character/ChangeSynchroDevice.cs
Normal file
54
EpinelPS/LobbyServer/Msgs/Character/ChangeSynchroDevice.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using EpinelPS.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
{
|
||||
[PacketPath("/character/SynchroDevice/Change")]
|
||||
public class ChangeSynchroDevice : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqSynchroChange>();
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResSynchroChange();
|
||||
|
||||
var highestLevelCharacters = user.Characters.OrderByDescending(x => x.Level).Take(5).ToList();
|
||||
|
||||
int slot = 1;
|
||||
foreach (var item in highestLevelCharacters)
|
||||
{
|
||||
if (item.Level != 200)
|
||||
{
|
||||
throw new Exception("expected level to be 200");
|
||||
}
|
||||
|
||||
response.Characters.Add(new NetUserCharacterData() { Default = new() { Csn = item.Csn, Skill1Lv = item.Skill1Lvl, Skill2Lv = item.Skill2Lvl, CostumeId = item.CostumeId, Level = item.Level, Grade = item.Grade, Tid = item.Tid, UltiSkillLv = item.UltimateLevel }, IsSynchro = user.GetSynchro(item.Csn) });
|
||||
|
||||
|
||||
|
||||
foreach (var s in user.SynchroSlots)
|
||||
{
|
||||
if (s.Slot == slot)
|
||||
{
|
||||
s.CharacterSerialNumber = item.Csn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
slot++;
|
||||
}
|
||||
|
||||
user.SynchroDeviceUpgraded = true;
|
||||
|
||||
foreach (var item in user.SynchroSlots)
|
||||
{
|
||||
response.Slots.Add(new NetSynchroSlot() { Slot = item.Slot, AvailableRegisterAt = item.AvailableAt, Csn = item.CharacterSerialNumber });
|
||||
}
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,10 @@ namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResGetCharacterData();
|
||||
// TODO: When Squad view opens in the game, or this request is sent, all character levels reset to 1 as well as cusume IDs
|
||||
// TODO: When Squad view opens in the game, or this request is sent, all character levels reset to 1 as well as costume IDs
|
||||
//foreach (var item in user.Characters)
|
||||
//{
|
||||
// response.Character.Add(new NetUserCharacterData() { Default = new() { Csn = item.Csn, Skill1Lv = item.Skill1Lvl, Skill2Lv = item.Skill2Lvl, CostumeId = item.CostumeId, Lv = item.Level, Grade = item.Grade, Tid = item.Tid, UltiSkillLv = item.UltimateLevel }, IsSynchro = false, Artifact = 0 });
|
||||
// response.Character.Add(new NetUserCharacterData() { Default = new() { Csn = item.Csn, Skill1Lv = item.Skill1Lvl, Skill2Lv = item.Skill2Lvl, CostumeId = item.CostumeId, Level = user.GetCharacterLevel(item.Csn, item.Level), Grade = item.Grade, Tid = item.Tid, UltiSkillLv = item.UltimateLevel }, IsSynchro = user.GetSynchro(item.Csn) });
|
||||
//}
|
||||
|
||||
var highestLevelCharacters = user.Characters.OrderByDescending(x => x.Level).Take(5).ToList();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using EpinelPS.Utils;
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
{
|
||||
@@ -10,6 +11,24 @@ namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
var req = await ReadData<ReqGetSynchroData>();
|
||||
var user = GetUser();
|
||||
|
||||
if (user.SynchroSlots.Count == 0)
|
||||
{
|
||||
|
||||
user.SynchroSlots = new() {
|
||||
new SynchroSlot() { Slot = 1 },
|
||||
new SynchroSlot() { Slot = 2},
|
||||
new SynchroSlot() { Slot = 3 },
|
||||
new SynchroSlot() { Slot = 4 },
|
||||
new SynchroSlot() { Slot = 5 },
|
||||
|
||||
new SynchroSlot() { Slot = 6 },
|
||||
new SynchroSlot() { Slot = 7 },
|
||||
new SynchroSlot() { Slot = 8 },
|
||||
new SynchroSlot() { Slot = 9 },
|
||||
new SynchroSlot() { Slot = 10 },
|
||||
};
|
||||
}
|
||||
|
||||
var highestLevelCharacters = user.Characters.OrderByDescending(x => x.Level).Take(5).ToList();
|
||||
|
||||
var response = new ResGetSynchroData();
|
||||
@@ -17,26 +36,18 @@ namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
|
||||
foreach (var item in highestLevelCharacters)
|
||||
{
|
||||
response.Synchro.StandardCharacters.Add(new NetUserCharacterData() { Default = new() { Csn = item.Csn, Skill1Lv = item.Skill1Lvl, Skill2Lv = item.Skill2Lvl, CostumeId = item.CostumeId, Level = item.Level, Grade = item.Grade, Tid = item.Tid, UltiSkillLv = item.UltimateLevel } });
|
||||
response.Synchro.StandardCharacters.Add(new NetUserCharacterData() { Default = new() { Csn = item.Csn, Skill1Lv = item.Skill1Lvl, Skill2Lv = item.Skill2Lvl, CostumeId = item.CostumeId, Level = item.Level, Grade = item.Grade, Tid = item.Tid, UltiSkillLv = item.UltimateLevel }, IsSynchro = user.GetSynchro(item.Csn) });
|
||||
}
|
||||
|
||||
response.Synchro.Slots.Add(new NetSynchroSlot() { Slot = 1 });
|
||||
response.Synchro.Slots.Add(new NetSynchroSlot() { Slot = 2 });
|
||||
response.Synchro.Slots.Add(new NetSynchroSlot() { Slot = 3 });
|
||||
response.Synchro.Slots.Add(new NetSynchroSlot() { Slot = 4 });
|
||||
response.Synchro.Slots.Add(new NetSynchroSlot() { Slot = 5 });
|
||||
|
||||
if (highestLevelCharacters.Count > 0)
|
||||
foreach (var item in user.SynchroSlots)
|
||||
{
|
||||
response.Synchro.SynchroMaxLv = highestLevelCharacters.First().Level;
|
||||
response.Synchro.SynchroLv = highestLevelCharacters.Last().Level;
|
||||
}
|
||||
else
|
||||
{
|
||||
response.Synchro.SynchroLv = 1;
|
||||
response.Synchro.Slots.Add(new NetSynchroSlot() { Slot = item.Slot, AvailableRegisterAt = 1, Csn = item.CharacterSerialNumber });
|
||||
}
|
||||
|
||||
// TODO: Validate response from real server and pull info from user info
|
||||
response.Synchro.SynchroMaxLv = 1000;
|
||||
response.Synchro.SynchroLv = user.GetSynchroLevel();
|
||||
response.Synchro.IsChanged = user.SynchroDeviceUpgraded;
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
};
|
||||
var highestLevelCharacters = user.Characters.OrderByDescending(x => x.Level).Take(5).ToList();
|
||||
|
||||
response.SynchroLv = highestLevelCharacters.Last().Level;
|
||||
response.SynchroLv = user.GetSynchroLevel();
|
||||
|
||||
foreach (var c in highestLevelCharacters)
|
||||
{
|
||||
|
||||
54
EpinelPS/LobbyServer/Msgs/Character/RegisterSynchroDevice.cs
Normal file
54
EpinelPS/LobbyServer/Msgs/Character/RegisterSynchroDevice.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using EpinelPS.Utils;
|
||||
using Swan.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
{
|
||||
[PacketPath("/character/SynchroDevice/Regist")]
|
||||
public class RegisterSynchroDevice : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqSynchroRegister>();
|
||||
var user = GetUser();
|
||||
var targetCharacter = user.GetCharacterBySerialNumber(req.Csn);
|
||||
if (targetCharacter == null) throw new Exception("target character does not exist");
|
||||
|
||||
var response = new ResSynchroRegister();
|
||||
foreach (var item in user.SynchroSlots)
|
||||
{
|
||||
if (item.Slot == req.Slot)
|
||||
{
|
||||
if (item.CharacterSerialNumber != 0)
|
||||
{
|
||||
Logger.Warn("must remove character from synchrodevice first");
|
||||
}
|
||||
else
|
||||
{
|
||||
item.CharacterSerialNumber = req.Csn;
|
||||
response.IsSynchro = true;
|
||||
response.Character = new NetUserCharacterDefaultData()
|
||||
{
|
||||
Csn = item.CharacterSerialNumber,
|
||||
CostumeId = targetCharacter.CostumeId,
|
||||
Grade = targetCharacter.Grade,
|
||||
Level = user.GetSynchroLevel(),
|
||||
Skill1Lv = targetCharacter.Skill1Lvl,
|
||||
Skill2Lv = targetCharacter.Skill2Lvl,
|
||||
Tid = targetCharacter.Tid,
|
||||
UltiSkillLv = targetCharacter.UltimateLevel
|
||||
};
|
||||
response.Slot = new NetSynchroSlot() { AvailableRegisterAt = item.AvailableAt, Csn = item.CharacterSerialNumber, Slot = item.Slot };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,11 @@ namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
Logger.Warn("Character level is already 1 - cannot reset");
|
||||
return;
|
||||
}
|
||||
if (item.Level == 200)
|
||||
{
|
||||
Logger.Warn("Character level is 200 - cannot reset");
|
||||
return;
|
||||
}
|
||||
|
||||
int requiredCredit = 0;
|
||||
int requiredBattleData = 0;
|
||||
|
||||
60
EpinelPS/LobbyServer/Msgs/Character/SynchroLevelUp.cs
Normal file
60
EpinelPS/LobbyServer/Msgs/Character/SynchroLevelUp.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.StaticInfo;
|
||||
using EpinelPS.Utils;
|
||||
using Swan.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
{
|
||||
[PacketPath("/character/SynchroDevice/LevelUp")]
|
||||
public class SynchroLevelUp : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqSynchroLevelUp>();
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResSynchroLevelUp();
|
||||
var data = GameData.Instance.GetCharacterLevelUpData();
|
||||
|
||||
|
||||
int requiredCredit = 0;
|
||||
int requiredBattleData = 0;
|
||||
int requiredCoreDust = 0;
|
||||
var levelUpData = data[user.SynchroDeviceLevel + 1];
|
||||
requiredCredit += levelUpData.gold;
|
||||
requiredBattleData += levelUpData.character_exp;
|
||||
requiredCoreDust += levelUpData.character_exp2;
|
||||
|
||||
if (user.CanSubtractCurrency(CurrencyType.Gold, requiredCredit) &&
|
||||
user.CanSubtractCurrency(CurrencyType.CharacterExp, requiredBattleData) &&
|
||||
user.CanSubtractCurrency(CurrencyType.CharacterExp2, requiredCoreDust))
|
||||
{
|
||||
user.SubtractCurrency(CurrencyType.Gold, requiredCredit);
|
||||
user.SubtractCurrency(CurrencyType.CharacterExp, requiredBattleData);
|
||||
user.SubtractCurrency(CurrencyType.CharacterExp2, requiredCoreDust);
|
||||
user.SynchroDeviceLevel++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TOOD: log this
|
||||
Logger.Error("ERROR: Not enough currency for upgrade");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
foreach (var currency in user.Currency)
|
||||
{
|
||||
response.Currencies.Add(new NetUserCurrencyData() { Type = (int)currency.Key, Value = currency.Value });
|
||||
}
|
||||
response.SynchroLv = user.SynchroDeviceLevel;
|
||||
|
||||
JsonDb.Save();
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using EpinelPS.Database;
|
||||
using EpinelPS.Utils;
|
||||
using Swan.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EpinelPS.LobbyServer.Msgs.Character
|
||||
{
|
||||
[PacketPath("/character/SynchroDevice/Unregist")]
|
||||
public class UnregisterSynchroDevice : LobbyMsgHandler
|
||||
{
|
||||
protected override async Task HandleAsync()
|
||||
{
|
||||
var req = await ReadData<ReqSynchroUnregist>();
|
||||
var user = GetUser();
|
||||
|
||||
var response = new ResSynchroUnregist();
|
||||
|
||||
foreach (var item in user.SynchroSlots)
|
||||
{
|
||||
if (item.Slot == req.Slot)
|
||||
{
|
||||
if (item.CharacterSerialNumber == 0)
|
||||
{
|
||||
Logger.Warn("must add character from synchrodevice first");
|
||||
}
|
||||
else
|
||||
{
|
||||
var oldCSN = item.CharacterSerialNumber;
|
||||
item.CharacterSerialNumber = 0;
|
||||
var data = user.GetCharacterBySerialNumber(oldCSN);
|
||||
if (data == null) throw new Exception("failed to lookup character");
|
||||
|
||||
response.Character = new NetUserCharacterDefaultData()
|
||||
{
|
||||
Csn = data.Csn,
|
||||
CostumeId = data.CostumeId,
|
||||
Grade = data.Grade,
|
||||
Level = data.Level,
|
||||
Skill1Lv = data.Skill1Lvl,
|
||||
Skill2Lv = data.Skill2Lvl,
|
||||
Tid = data.Tid,
|
||||
UltiSkillLv = data.UltimateLevel
|
||||
};
|
||||
response.Slot = new NetSynchroSlot() { AvailableRegisterAt = item.AvailableAt, Csn = item.CharacterSerialNumber, Slot = item.Slot };
|
||||
|
||||
response.IsSynchro = false;
|
||||
var highestLevelCharacters = user.Characters.OrderByDescending(x => x.Level).Take(5).ToList();
|
||||
|
||||
|
||||
foreach (var item2 in highestLevelCharacters)
|
||||
{
|
||||
response.SynchroStandardCharacters.Add(item2.Csn);
|
||||
}
|
||||
|
||||
response.SynchroLv = user.GetSynchroLevel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JsonDb.Save();
|
||||
|
||||
|
||||
await WriteDataAsync(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,7 +125,7 @@ namespace EpinelPS.LobbyServer.Msgs.Stage
|
||||
var newXp = rewardData.user_exp + user.userPointData.ExperiencePoint;
|
||||
|
||||
var oldXpData = GameData.Instance.GetUserLevelFromUserExp(user.userPointData.ExperiencePoint);
|
||||
var newLevelExp = GameData.Instance.GetUserMinXpForLevel(user.userPointData.UserLevel + 1);
|
||||
var newLevelExp = GameData.Instance.GetUserMinXpForLevel(user.userPointData.UserLevel);
|
||||
var newLevel = user.userPointData.UserLevel;
|
||||
|
||||
if (newLevelExp == -1)
|
||||
@@ -143,7 +143,7 @@ namespace EpinelPS.LobbyServer.Msgs.Stage
|
||||
else
|
||||
user.Currency.Add(CurrencyType.FreeCash, 30);
|
||||
|
||||
newLevelExp = GameData.Instance.GetUserMinXpForLevel(newLevel + 1);
|
||||
newLevelExp = GameData.Instance.GetUserMinXpForLevel(newLevel);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace EpinelPS.LobbyServer.Msgs.User
|
||||
|
||||
foreach (var item in user.Characters)
|
||||
{
|
||||
response.Character.Add(new NetUserCharacterData() { Default = new() { Csn = item.Csn, Skill1Lv = item.Skill1Lvl, Skill2Lv = item.Skill2Lvl, CostumeId = item.CostumeId, Level = item.Level, Grade = item.Grade, Tid = item.Tid, UltiSkillLv = item.UltimateLevel } });
|
||||
response.Character.Add(new NetUserCharacterData() { Default = new() { Csn = item.Csn, Skill1Lv = item.Skill1Lvl, Skill2Lv = item.Skill2Lvl, CostumeId = item.CostumeId, Level = user.GetCharacterLevel(item.Csn, item.Level), Grade = item.Grade, Tid = item.Tid, UltiSkillLv = item.UltimateLevel}, IsSynchro = user.GetSynchro(item.Csn) });
|
||||
}
|
||||
|
||||
foreach (var item in NetUtils.GetUserItems(user))
|
||||
@@ -58,7 +58,8 @@ namespace EpinelPS.LobbyServer.Msgs.User
|
||||
if (user.Characters.Count > 0)
|
||||
{
|
||||
var highestLevelCharacters = user.Characters.OrderByDescending(x => x.Level).Take(5).ToList();
|
||||
response.SynchroLv = highestLevelCharacters.Last().Level;
|
||||
response.SynchroLv = user.GetSynchroLevel();
|
||||
|
||||
foreach (var item in highestLevelCharacters)
|
||||
{
|
||||
response.SynchroStandardCharacters.Add(item.Csn);
|
||||
|
||||
Reference in New Issue
Block a user