mirror of
https://github.com/EggLinks/DanhengServer-OpenSource.git
synced 2026-01-02 12:16:03 +08:00
refactor: challenge
This commit is contained in:
@@ -98,4 +98,29 @@ public class CommandUnlockAll : ICommand
|
||||
await arg.Target!.Player!.SendPacket(new PacketPlayerKickOutScNotify());
|
||||
arg.Target!.Stop();
|
||||
}
|
||||
|
||||
[CommandMethod("0 challenge")]
|
||||
public async ValueTask UnlockAllChallenge(CommandArg arg)
|
||||
{
|
||||
if (arg.Target == null)
|
||||
{
|
||||
await arg.SendMsg(I18NManager.Translate("Game.Command.Notice.PlayerNotFound"));
|
||||
return;
|
||||
}
|
||||
|
||||
var player = arg.Target!.Player!;
|
||||
List<int> peakList = [2200503, 2200504, 2200505, 2200506];
|
||||
|
||||
List<int> allList = [.. peakList];
|
||||
|
||||
foreach (var id in allList)
|
||||
{
|
||||
// finish mission
|
||||
await player.QuestManager!.AcceptQuest(id);
|
||||
await player.QuestManager!.FinishQuest(id);
|
||||
}
|
||||
|
||||
await arg.SendMsg(I18NManager.Translate("Game.Command.UnlockAll.UnlockedAll",
|
||||
I18NManager.Translate("Word.TypesOfChallenge")));
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Proto\Proto.csproj" />
|
||||
<ProjectReference Include="..\ServerSideProto\ServerSideProto.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
18
Common/Data/Excel/BattleTargetConfigExcel.cs
Normal file
18
Common/Data/Excel/BattleTargetConfigExcel.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace EggLink.DanhengServer.Data.Excel;
|
||||
|
||||
[ResourceEntity("BattleTargetConfig.json")]
|
||||
public class BattleTargetConfigExcel : ExcelResource
|
||||
{
|
||||
public int ID { get; set; }
|
||||
public int TargetParam { get; set; }
|
||||
|
||||
public override int GetId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public override void Loaded()
|
||||
{
|
||||
GameData.BattleTargetConfigData.TryAdd(ID, this);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Newtonsoft.Json;
|
||||
using System.Threading;
|
||||
|
||||
namespace EggLink.DanhengServer.Data.Excel;
|
||||
|
||||
@@ -31,9 +32,9 @@ public class ChallengeConfigExcel : ExcelResource
|
||||
public List<int>? NpcMonsterIDList2 { get; set; } = [];
|
||||
public List<int>? EventIDList2 { get; set; } = [];
|
||||
|
||||
[JsonIgnore] public Dictionary<int, ChallengeMonsterInfo> ChallengeMonsters1 { get; set; } = new();
|
||||
[JsonIgnore] public Dictionary<int, List<ChallengeMonsterInfo>> ChallengeMonsters1 { get; set; } = new();
|
||||
|
||||
[JsonIgnore] public Dictionary<int, ChallengeMonsterInfo> ChallengeMonsters2 { get; set; } = new();
|
||||
[JsonIgnore] public Dictionary<int, List<ChallengeMonsterInfo>> ChallengeMonsters2 { get; set; } = new();
|
||||
|
||||
public override int GetId()
|
||||
{
|
||||
@@ -53,7 +54,7 @@ public class ChallengeConfigExcel : ExcelResource
|
||||
public void SetStoryExcel(ChallengeStoryExtraExcel storyExcel)
|
||||
{
|
||||
StoryExcel = storyExcel;
|
||||
ChallengeCountDown = storyExcel.TurnLimit;
|
||||
ChallengeCountDown = (int)storyExcel.TurnLimit;
|
||||
}
|
||||
|
||||
public void SetBossExcel(ChallengeBossExtraExcel bossExcel)
|
||||
@@ -68,16 +69,18 @@ public class ChallengeConfigExcel : ExcelResource
|
||||
{
|
||||
if (ConfigList1[i] == 0) break;
|
||||
|
||||
var Monster = new ChallengeMonsterInfo(ConfigList1[i], NpcMonsterIDList1![i], EventIDList1![i]);
|
||||
ChallengeMonsters1.Add(Monster.ConfigId, Monster);
|
||||
var monster = new ChallengeMonsterInfo(ConfigList1[i], NpcMonsterIDList1![i], EventIDList1![i]);
|
||||
ChallengeMonsters1.TryAdd(MazeGroupID1, []);
|
||||
ChallengeMonsters1[MazeGroupID1].Add(monster);
|
||||
}
|
||||
|
||||
for (var i = 0; i < ConfigList2?.Count; i++)
|
||||
{
|
||||
if (ConfigList2[i] == 0) break;
|
||||
|
||||
var Monster = new ChallengeMonsterInfo(ConfigList2[i], NpcMonsterIDList2![i], EventIDList2![i]);
|
||||
ChallengeMonsters2.Add(Monster.ConfigId, Monster);
|
||||
var monster = new ChallengeMonsterInfo(ConfigList2[i], NpcMonsterIDList2![i], EventIDList2![i]);
|
||||
ChallengeMonsters2.TryAdd(MazeGroupID2, []);
|
||||
ChallengeMonsters2[MazeGroupID2].Add(monster);
|
||||
}
|
||||
|
||||
ConfigList1 = null;
|
||||
@@ -91,10 +94,10 @@ public class ChallengeConfigExcel : ExcelResource
|
||||
}
|
||||
|
||||
[method: JsonConstructor]
|
||||
public class ChallengeMonsterInfo(int ConfigId, int NpcMonsterId, int EventId)
|
||||
public class ChallengeMonsterInfo(int configId, int npcMonsterId, int eventId)
|
||||
{
|
||||
public int ConfigId = ConfigId;
|
||||
public int EventId = EventId;
|
||||
public int NpcMonsterId = NpcMonsterId;
|
||||
public int ConfigId = configId;
|
||||
public int EventId = eventId;
|
||||
public int NpcMonsterId = npcMonsterId;
|
||||
}
|
||||
}
|
||||
30
Common/Data/Excel/ChallengePeakBossConfigExcel.cs
Normal file
30
Common/Data/Excel/ChallengePeakBossConfigExcel.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using EggLink.DanhengServer.Data.Custom;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace EggLink.DanhengServer.Data.Excel;
|
||||
|
||||
[ResourceEntity("ChallengePeakBossConfig.json")]
|
||||
public class ChallengePeakBossConfigExcel : ExcelResource
|
||||
{
|
||||
public int ID { get; set; }
|
||||
public int HardTarget { get; set; }
|
||||
public int ColorMedalTarget { get; set; }
|
||||
public List<int> HardEventIDList { get; set; } = [];
|
||||
public List<int> HardTagList { get; set; } = [];
|
||||
public List<int> BuffList { get; set; } = [];
|
||||
|
||||
public override int GetId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public override void Loaded()
|
||||
{
|
||||
GameData.ChallengePeakBossConfigData.TryAdd(ID, this);
|
||||
}
|
||||
|
||||
public override void AfterAllDone()
|
||||
{
|
||||
GameData.ChallengePeakConfigData[ID].BossExcel = this;
|
||||
}
|
||||
}
|
||||
38
Common/Data/Excel/ChallengePeakConfigExcel.cs
Normal file
38
Common/Data/Excel/ChallengePeakConfigExcel.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using EggLink.DanhengServer.Data.Custom;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace EggLink.DanhengServer.Data.Excel;
|
||||
|
||||
[ResourceEntity("ChallengePeakConfig.json")]
|
||||
public class ChallengePeakConfigExcel : ExcelResource
|
||||
{
|
||||
public int ID { get; set; }
|
||||
public int MazeGroupID { get; set; }
|
||||
public int MapEntranceID { get; set; }
|
||||
public List<int> TagList { get; set; } = [];
|
||||
public List<int> HPProgressValueList { get; set; } = [];
|
||||
public List<int> ProgressValueList { get; set; } = [];
|
||||
public List<int> ConfigIDList { get; set; } = [];
|
||||
public List<int> EventIDList { get; set; } = [];
|
||||
public List<int> NpcMonsterIDList { get; set; } = [];
|
||||
public List<int> NormalTargetList { get; set; } = [];
|
||||
|
||||
[JsonIgnore] public Dictionary<int, List<ChallengeConfigExcel.ChallengeMonsterInfo>> ChallengeMonsters { get; } = [];
|
||||
[JsonIgnore] public ChallengePeakBossConfigExcel? BossExcel { get; set; }
|
||||
|
||||
public override int GetId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public override void Loaded()
|
||||
{
|
||||
GameData.ChallengePeakConfigData.TryAdd(ID, this);
|
||||
|
||||
ChallengeMonsters.Add(MazeGroupID, []);
|
||||
for (var i = 0; i < ConfigIDList.Count; i++)
|
||||
{
|
||||
ChallengeMonsters[MazeGroupID].Add(new ChallengeConfigExcel.ChallengeMonsterInfo(ConfigIDList[i], NpcMonsterIDList[i], EventIDList[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
22
Common/Data/Excel/ChallengePeakGroupConfigExcel.cs
Normal file
22
Common/Data/Excel/ChallengePeakGroupConfigExcel.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
namespace EggLink.DanhengServer.Data.Excel;
|
||||
|
||||
[ResourceEntity("ChallengePeakGroupConfig.json")]
|
||||
public class ChallengePeakGroupConfigExcel : ExcelResource
|
||||
{
|
||||
public int ID { get; set; }
|
||||
public int RewardGroupID { get; set; }
|
||||
public int MapEntranceID { get; set; }
|
||||
public int MapEntranceBoss { get; set; }
|
||||
public int BossLevelID { get; set; }
|
||||
public List<int> PreLevelIDList { get; set; } = [];
|
||||
|
||||
public override int GetId()
|
||||
{
|
||||
return ID;
|
||||
}
|
||||
|
||||
public override void Loaded()
|
||||
{
|
||||
GameData.ChallengePeakGroupConfigData.TryAdd(ID, this);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
public class ChallengeStoryExtraExcel : ExcelResource
|
||||
{
|
||||
public int ID { get; set; }
|
||||
public int TurnLimit { get; set; }
|
||||
public uint TurnLimit { get; set; }
|
||||
public int ClearScore { get; set; }
|
||||
public List<int>? BattleTargetID { get; set; }
|
||||
|
||||
|
||||
@@ -76,6 +76,9 @@ public static class GameData
|
||||
public static Dictionary<int, ChallengeConfigExcel> ChallengeConfigData { get; private set; } = [];
|
||||
public static Dictionary<int, ChallengeTargetExcel> ChallengeTargetData { get; private set; } = [];
|
||||
public static Dictionary<int, ChallengeGroupExcel> ChallengeGroupData { get; private set; } = [];
|
||||
public static Dictionary<int, ChallengePeakGroupConfigExcel> ChallengePeakGroupConfigData { get; private set; } = [];
|
||||
public static Dictionary<int, ChallengePeakConfigExcel> ChallengePeakConfigData { get; private set; } = [];
|
||||
public static Dictionary<int, ChallengePeakBossConfigExcel> ChallengePeakBossConfigData { get; private set; } = [];
|
||||
public static Dictionary<int, List<ChallengeRewardExcel>> ChallengeRewardData { get; private set; } = [];
|
||||
|
||||
#endregion
|
||||
@@ -91,6 +94,7 @@ public static class GameData
|
||||
public static Dictionary<int, MonsterConfigExcel> MonsterConfigData { get; private set; } = [];
|
||||
public static Dictionary<int, MonsterDropExcel> MonsterDropData { get; private set; } = [];
|
||||
public static Dictionary<int, BattleCollegeConfigExcel> BattleCollegeConfigData { get; private set; } = [];
|
||||
public static Dictionary<int, BattleTargetConfigExcel> BattleTargetConfigData { get; private set; } = [];
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -268,6 +268,22 @@ public class FormalAvatarInfo : BaseAvatarInfo
|
||||
return proto;
|
||||
}
|
||||
|
||||
public ChallengePeakAvatar ToPeakAvatarProto()
|
||||
{
|
||||
return new ChallengePeakAvatar
|
||||
{
|
||||
AvatarId = (uint)AvatarId,
|
||||
EquipmentUniqueId = (uint)GetCurPathInfo().EquipId,
|
||||
RelicList =
|
||||
{
|
||||
GetCurPathInfo().Relic.Select(relic => new EquipRelic
|
||||
{
|
||||
Type = (uint)relic.Key,
|
||||
RelicUniqueId = (uint)relic.Value
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
public List<MultiPathAvatarInfo> ToAvatarPathProto()
|
||||
{
|
||||
var res = new List<MultiPathAvatarInfo>();
|
||||
|
||||
@@ -9,16 +9,25 @@ public class ChallengeData : BaseDatabaseDataHelper
|
||||
{
|
||||
[SugarColumn(IsJson = true)] public Dictionary<int, ChallengeHistoryData> History { get; set; } = new();
|
||||
|
||||
[SugarColumn(IsJson = true)] public ChallengeInstanceData Instance { get; set; } = new();
|
||||
[SugarColumn(IsNullable = true)] public string? ChallengeInstance { get; set; }
|
||||
[SugarColumn(IsNullable = true)] public string? Instance { get; set; } = null; // placeholder
|
||||
|
||||
[SugarColumn(IsJson = true)] public Dictionary<int, ChallengeGroupReward> TakenRewards { get; set; } = new();
|
||||
[SugarColumn(IsJson = true)] public Dictionary<int, ChallengePeakLevelData> PeakLevelDatas { get; set; } = new();
|
||||
|
||||
public void delete(int ChallengeId)
|
||||
public void Delete(int challengeId)
|
||||
{
|
||||
History.Remove(ChallengeId);
|
||||
History.Remove(challengeId);
|
||||
}
|
||||
}
|
||||
|
||||
public class ChallengePeakLevelData
|
||||
{
|
||||
public int LevelId { get; set; }
|
||||
public uint PeakStar { get; set; }
|
||||
public List<uint> BaseAvatarList { get; set; } = [];
|
||||
}
|
||||
|
||||
public class ChallengeHistoryData(int uid, int challengeId)
|
||||
{
|
||||
public int OwnerId { get; set; } = uid;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Buffers.Binary;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
using EggLink.DanhengServer.Proto.ServerSide;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace EggLink.DanhengServer.Util;
|
||||
@@ -16,6 +17,36 @@ public static class Extensions
|
||||
};
|
||||
}
|
||||
|
||||
public static Position ToPosition(this Vector3Pb vector)
|
||||
{
|
||||
return new Position
|
||||
{
|
||||
X = vector.X,
|
||||
Y = vector.Y,
|
||||
Z = vector.Z
|
||||
};
|
||||
}
|
||||
|
||||
public static Vector ToVector(this Position position)
|
||||
{
|
||||
return new Vector
|
||||
{
|
||||
X = position.X,
|
||||
Y = position.Y,
|
||||
Z = position.Z
|
||||
};
|
||||
}
|
||||
|
||||
public static Vector3Pb ToVector3Pb(this Position position)
|
||||
{
|
||||
return new Vector3Pb
|
||||
{
|
||||
X = position.X,
|
||||
Y = position.Y,
|
||||
Z = position.Z
|
||||
};
|
||||
}
|
||||
|
||||
public static T RandomElement<T>(this List<T> values)
|
||||
{
|
||||
var index = new Random().Next(values.Count);
|
||||
|
||||
@@ -16,6 +16,7 @@ public static class GameConstants
|
||||
public const int LAST_TRAIN_WORLD_ID = 501;
|
||||
public const int AMBUSH_BUFF_ID = 1000102;
|
||||
public const int CHALLENGE_ENTRANCE = 100000103;
|
||||
public const int CHALLENGE_PEAK_ENTRANCE = 100000352;
|
||||
public const int CHALLENGE_STORY_ENTRANCE = 102020107;
|
||||
public const int CHALLENGE_BOSS_ENTRANCE = 1030402;
|
||||
public const int CURRENT_ROGUE_TOURN_SEASON = 2;
|
||||
|
||||
@@ -27,6 +27,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Proto", "Proto\Proto.csproj
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DanhengKcpSharp", "DanhengKcpSharp\DanhengKcpSharp.csproj", "{CD7EFAA3-C655-40EE-8F6A-A8E2DA3B0FCB}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServerSideProto", "ServerSideProto\ServerSideProto.csproj", "{1F94D996-0E35-4A56-9437-00949576D6B8}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -61,6 +63,10 @@ Global
|
||||
{CD7EFAA3-C655-40EE-8F6A-A8E2DA3B0FCB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CD7EFAA3-C655-40EE-8F6A-A8E2DA3B0FCB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CD7EFAA3-C655-40EE-8F6A-A8E2DA3B0FCB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1F94D996-0E35-4A56-9437-00949576D6B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1F94D996-0E35-4A56-9437-00949576D6B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1F94D996-0E35-4A56-9437-00949576D6B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1F94D996-0E35-4A56-9437-00949576D6B8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using EggLink.DanhengServer.Data;
|
||||
using EggLink.DanhengServer.Data.Config.Scene;
|
||||
using EggLink.DanhengServer.Data.Excel;
|
||||
using EggLink.DanhengServer.Enums.Scene;
|
||||
using EggLink.DanhengServer.GameServer.Game.Player;
|
||||
using EggLink.DanhengServer.GameServer.Game.Scene;
|
||||
using EggLink.DanhengServer.GameServer.Game.Scene.Entity;
|
||||
using EggLink.DanhengServer.Proto.ServerSide;
|
||||
using EggLink.DanhengServer.Util;
|
||||
|
||||
namespace EggLink.DanhengServer.GameServer.Game.Challenge;
|
||||
@@ -23,16 +23,23 @@ public class ChallengeEntityLoader(SceneInstance scene, PlayerInstance player) :
|
||||
LoadGroups.SafeAddRange(Scene.FloorInfo!.Groups.Keys.ToList());
|
||||
|
||||
// Setup first stage
|
||||
var excel = instance.Excel;
|
||||
Scene.FloorInfo.Groups.TryGetValue(excel.MazeGroupID1, out var groupData);
|
||||
if (groupData != null) await LoadGroup(groupData);
|
||||
var stages = instance.GetStageMonsters();
|
||||
|
||||
// Set leave entry
|
||||
Scene.LeaveEntryId =
|
||||
instance.IsStory() ? GameConstants.CHALLENGE_STORY_ENTRANCE : GameConstants.CHALLENGE_ENTRANCE;
|
||||
foreach (var stage in stages)
|
||||
{
|
||||
Scene.FloorInfo.Groups.TryGetValue(stage.Key, out var groupData);
|
||||
if (groupData != null) await LoadGroup(groupData);
|
||||
}
|
||||
|
||||
if (instance.IsBoss())
|
||||
Scene.LeaveEntryId = GameConstants.CHALLENGE_BOSS_ENTRANCE;
|
||||
Scene.LeaveEntryId = instance.Data.ChallengeTypeCase switch
|
||||
{
|
||||
// Set leave entry
|
||||
ChallengeDataPb.ChallengeTypeOneofCase.Boss => GameConstants.CHALLENGE_BOSS_ENTRANCE,
|
||||
ChallengeDataPb.ChallengeTypeOneofCase.Memory => GameConstants.CHALLENGE_ENTRANCE,
|
||||
ChallengeDataPb.ChallengeTypeOneofCase.Peak => GameConstants.CHALLENGE_PEAK_ENTRANCE,
|
||||
ChallengeDataPb.ChallengeTypeOneofCase.Story => GameConstants.CHALLENGE_STORY_ENTRANCE,
|
||||
_ => Scene.LeaveEntryId
|
||||
};
|
||||
|
||||
foreach (var group in Scene.FloorInfo.Groups.Values)
|
||||
{
|
||||
@@ -40,7 +47,7 @@ public class ChallengeEntityLoader(SceneInstance scene, PlayerInstance player) :
|
||||
if (group.LoadSide != GroupLoadSideEnum.Server) continue;
|
||||
|
||||
// Dont load the groups that have monsters in them
|
||||
if (group.PropList.Count > 0 && group.MonsterList.Count > 0) await LoadGroup(group);
|
||||
if (group.PropList.Count > 0 && group.MonsterList.Count == 0) await LoadGroup(group);
|
||||
}
|
||||
|
||||
Scene.IsLoaded = true;
|
||||
@@ -56,21 +63,19 @@ public class ChallengeEntityLoader(SceneInstance scene, PlayerInstance player) :
|
||||
var instance = Player.ChallengeManager.ChallengeInstance;
|
||||
|
||||
// Get current stage monster infos
|
||||
Dictionary<int, ChallengeConfigExcel.ChallengeMonsterInfo> challengeMonsters;
|
||||
if (instance.Excel.MazeGroupID1 == group.Id || instance.Excel.MazeGroupID2 == group.Id)
|
||||
challengeMonsters = instance.CurrentStage == 1
|
||||
? instance.Excel.ChallengeMonsters1
|
||||
: instance.Excel.ChallengeMonsters2;
|
||||
else
|
||||
var stages = instance.GetStageMonsters();
|
||||
|
||||
if (!stages.TryGetValue(group.Id, out var challengeMonsters))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get challenge monster info
|
||||
if (!challengeMonsters.ContainsKey(info.ID)) return null;
|
||||
var challengeMonsterInfo = challengeMonsters[info.ID];
|
||||
if (challengeMonsters.All(x => x.ConfigId != info.ID)) return null;
|
||||
var challengeMonsterInfo = challengeMonsters.First(x => x.ConfigId == info.ID);
|
||||
|
||||
// Get excels from game data
|
||||
if (!GameData.NpcMonsterDataData.ContainsKey(challengeMonsterInfo.NpcMonsterId)) return null;
|
||||
var npcMonsterExcel = GameData.NpcMonsterDataData[challengeMonsterInfo.NpcMonsterId];
|
||||
if (!GameData.NpcMonsterDataData.TryGetValue(challengeMonsterInfo.NpcMonsterId, out var npcMonsterExcel)) return null;
|
||||
|
||||
// Create monster from group monster info
|
||||
var entity = new EntityMonster(Scene, info.ToPositionProto(), info.ToRotationProto(), group.Id, info.ID,
|
||||
@@ -79,6 +84,7 @@ public class ChallengeEntityLoader(SceneInstance scene, PlayerInstance player) :
|
||||
EventId = challengeMonsterInfo.EventId,
|
||||
CustomStageId = challengeMonsterInfo.EventId
|
||||
};
|
||||
|
||||
await Scene.AddEntity(entity, sendPacket);
|
||||
|
||||
return entity;
|
||||
|
||||
@@ -1,452 +0,0 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using EggLink.DanhengServer.Data;
|
||||
using EggLink.DanhengServer.Data.Excel;
|
||||
using EggLink.DanhengServer.Database.Challenge;
|
||||
using EggLink.DanhengServer.Enums.Item;
|
||||
using EggLink.DanhengServer.Enums.Mission;
|
||||
using EggLink.DanhengServer.GameServer.Game.Battle;
|
||||
using EggLink.DanhengServer.GameServer.Game.Player;
|
||||
using EggLink.DanhengServer.GameServer.Game.Scene;
|
||||
using EggLink.DanhengServer.GameServer.Game.Scene.Entity;
|
||||
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Challenge;
|
||||
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Lineup;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
using EggLink.DanhengServer.Util;
|
||||
|
||||
namespace EggLink.DanhengServer.GameServer.Game.Challenge;
|
||||
|
||||
public class ChallengeInstance
|
||||
{
|
||||
public ChallengeInstance(PlayerInstance player, ChallengeConfigExcel excel)
|
||||
{
|
||||
Player = player;
|
||||
Excel = excel;
|
||||
ChallengeId = excel.GetId();
|
||||
StartPos = new Position();
|
||||
StartRot = new Position();
|
||||
CurrentStage = 1;
|
||||
RoundsLeft = Excel.IsStory() ? 5 : Excel.ChallengeCountDown;
|
||||
SetStatus(ChallengeStatus.ChallengeDoing);
|
||||
SetCurrentExtraLineup(ExtraLineupType.LineupChallenge);
|
||||
}
|
||||
|
||||
public ChallengeInstance(PlayerInstance player, ChallengeConfigExcel excel, ChallengeInstanceData data)
|
||||
{
|
||||
Player = player;
|
||||
Excel = excel;
|
||||
|
||||
StartPos = data.StartPos;
|
||||
StartRot = data.StartRot;
|
||||
ChallengeId = data.ChallengeId;
|
||||
CurrentStage = data.CurrentStage;
|
||||
CurrentExtraLineup = data.CurrentExtraLineup;
|
||||
Status = data.Status;
|
||||
HasAvatarDied = data.HasAvatarDied;
|
||||
SavedMp = data.SavedMp;
|
||||
RoundsLeft = data.RoundsLeft;
|
||||
Stars = data.Stars;
|
||||
ScoreStage1 = data.ScoreStage1;
|
||||
ScoreStage2 = data.ScoreStage2;
|
||||
StoryBuffs = data.StoryBuffs;
|
||||
BossBuffs = data.BossBuffs;
|
||||
}
|
||||
|
||||
public Position StartPos { get; set; }
|
||||
public Position StartRot { get; set; }
|
||||
public int ChallengeId { get; set; }
|
||||
public int CurrentStage { get; set; }
|
||||
public int CurrentExtraLineup { get; set; }
|
||||
public int Status { get; set; }
|
||||
public bool HasAvatarDied { get; set; }
|
||||
|
||||
public int SavedMp { get; set; }
|
||||
public int RoundsLeft { get; set; }
|
||||
public int Stars { get; set; }
|
||||
public int ScoreStage1 { get; set; }
|
||||
public int ScoreStage2 { get; set; }
|
||||
|
||||
[JsonIgnore] public List<BattleTarget>? BossTarget1 { get; set; }
|
||||
|
||||
[JsonIgnore] public List<BattleTarget>? BossTarget2 { get; set; }
|
||||
|
||||
[JsonIgnore] private PlayerInstance Player { get; }
|
||||
|
||||
[JsonIgnore] public ChallengeConfigExcel Excel { get; set; }
|
||||
|
||||
public List<int> StoryBuffs { get; set; } = [];
|
||||
public List<int> BossBuffs { get; set; } = [];
|
||||
|
||||
public SceneInstance GetScene()
|
||||
{
|
||||
return Player.SceneInstance!;
|
||||
}
|
||||
|
||||
public int GetChallengeId()
|
||||
{
|
||||
return Excel.GetId();
|
||||
}
|
||||
|
||||
public bool IsStory()
|
||||
{
|
||||
return Excel.IsStory();
|
||||
}
|
||||
|
||||
public bool IsBoss()
|
||||
{
|
||||
return Excel.IsBoss();
|
||||
}
|
||||
|
||||
public void SetStatus(ChallengeStatus status)
|
||||
{
|
||||
Status = (int)status;
|
||||
}
|
||||
|
||||
public void SetCurrentExtraLineup(ExtraLineupType type)
|
||||
{
|
||||
CurrentExtraLineup = (int)type;
|
||||
}
|
||||
|
||||
public int GetRoundsElapsed()
|
||||
{
|
||||
return Excel.ChallengeCountDown - RoundsLeft;
|
||||
}
|
||||
|
||||
public int GetTotalScore()
|
||||
{
|
||||
return ScoreStage1 + ScoreStage2;
|
||||
}
|
||||
|
||||
public bool IsWin()
|
||||
{
|
||||
return Status == (int)ChallengeStatus.ChallengeFinish;
|
||||
}
|
||||
|
||||
#region Serialization
|
||||
|
||||
public CurChallenge ToProto()
|
||||
{
|
||||
var proto = new CurChallenge
|
||||
{
|
||||
ChallengeId = (uint)Excel.GetId(),
|
||||
Status = (ChallengeStatus)Status,
|
||||
ScoreId = (uint)ScoreStage1,
|
||||
ScoreTwo = (uint)ScoreStage2,
|
||||
RoundCount = (uint)GetRoundsElapsed(),
|
||||
ExtraLineupType = (ExtraLineupType)CurrentExtraLineup,
|
||||
StageInfo = new ChallengeCurBuffInfo()
|
||||
};
|
||||
|
||||
if (Excel.IsBoss())
|
||||
proto.StageInfo.CurBossBuffs = new ChallengeBossBuffList
|
||||
{
|
||||
ChallengeBossConst = 1
|
||||
};
|
||||
|
||||
if (Excel.IsStory()) proto.StageInfo.CurStoryBuffs = new ChallengeStoryBuffList();
|
||||
|
||||
if (StoryBuffs.Count >= CurrentStage)
|
||||
proto.StageInfo.CurStoryBuffs.BuffList.Add(StoryBuffs.Select(x => (uint)x));
|
||||
|
||||
if (BossBuffs.Count >= CurrentStage)
|
||||
proto.StageInfo.CurBossBuffs.BuffList.Add(BossBuffs.Select(x => (uint)x));
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
||||
public ChallengeStageInfo ToStageInfo()
|
||||
{
|
||||
var proto = new ChallengeStageInfo();
|
||||
|
||||
if (Excel.IsBoss())
|
||||
{
|
||||
proto.BossInfo = new ChallengeBossInfo
|
||||
{
|
||||
FirstNode = new ChallengeBossSingleNodeInfo
|
||||
{
|
||||
BuffId = (uint)BossBuffs[0]
|
||||
},
|
||||
SecondNode = new ChallengeBossSingleNodeInfo
|
||||
{
|
||||
BuffId = (uint)BossBuffs[1]
|
||||
},
|
||||
NCBDNPGPEAI = true
|
||||
};
|
||||
|
||||
foreach (var lineupAvatar in Player.LineupManager?.GetExtraLineup(ExtraLineupType.LineupChallenge)
|
||||
?.BaseAvatars ?? [])
|
||||
{
|
||||
var avatar = Player.AvatarManager?.GetFormalAvatar(lineupAvatar.BaseAvatarId);
|
||||
if (avatar == null) continue;
|
||||
proto.BossInfo.FirstLineup.Add((uint)avatar.AvatarId);
|
||||
var equip = Player.InventoryManager?.GetItem(0, avatar.GetCurPathInfo().EquipId,
|
||||
ItemMainTypeEnum.Equipment);
|
||||
if (equip != null)
|
||||
proto.BossInfo.ChallengeAvatarEquipmentMap.Add((uint)avatar.AvatarId,
|
||||
equip.ToChallengeEquipmentProto());
|
||||
|
||||
var relicProto = new ChallengeBossAvatarRelicInfo();
|
||||
|
||||
foreach (var relicUniqueId in avatar.GetCurPathInfo().Relic)
|
||||
{
|
||||
var relic = Player.InventoryManager?.GetItem(0, relicUniqueId.Value, ItemMainTypeEnum.Relic);
|
||||
if (relic == null) continue;
|
||||
relicProto.AvatarRelicSlotMap.Add((uint)relicUniqueId.Key, relic.ToChallengeRelicProto());
|
||||
}
|
||||
|
||||
proto.BossInfo.ChallengeAvatarRelicMap.Add((uint)avatar.AvatarId, relicProto);
|
||||
}
|
||||
|
||||
foreach (var lineupAvatar in Player.LineupManager?.GetExtraLineup(ExtraLineupType.LineupChallenge2)
|
||||
?.BaseAvatars ?? [])
|
||||
{
|
||||
var avatar = Player.AvatarManager?.GetFormalAvatar(lineupAvatar.BaseAvatarId);
|
||||
if (avatar == null) continue;
|
||||
proto.BossInfo.SecondLineup.Add((uint)avatar.AvatarId);
|
||||
var equip = Player.InventoryManager?.GetItem(0, avatar.GetCurPathInfo().EquipId,
|
||||
ItemMainTypeEnum.Equipment);
|
||||
if (equip != null)
|
||||
proto.BossInfo.ChallengeAvatarEquipmentMap.Add((uint)avatar.AvatarId,
|
||||
equip.ToChallengeEquipmentProto());
|
||||
|
||||
var relicProto = new ChallengeBossAvatarRelicInfo();
|
||||
|
||||
foreach (var relicUniqueId in avatar.GetCurPathInfo().Relic)
|
||||
{
|
||||
var relic = Player.InventoryManager?.GetItem(0, relicUniqueId.Value, ItemMainTypeEnum.Relic);
|
||||
if (relic == null) continue;
|
||||
relicProto.AvatarRelicSlotMap.Add((uint)relicUniqueId.Key, relic.ToChallengeRelicProto());
|
||||
}
|
||||
|
||||
proto.BossInfo.ChallengeAvatarRelicMap.Add((uint)avatar.AvatarId, relicProto);
|
||||
}
|
||||
}
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Management
|
||||
|
||||
public void OnBattleStart(BattleInstance battle)
|
||||
{
|
||||
battle.RoundLimit = RoundsLeft;
|
||||
|
||||
battle.Buffs.Add(new MazeBuff(Excel.MazeBuffID, 1, -1));
|
||||
|
||||
if (StoryBuffs.Count >= CurrentStage)
|
||||
{
|
||||
var buffId = StoryBuffs[CurrentStage - 1];
|
||||
battle.Buffs.Add(new MazeBuff(buffId, 1, -1));
|
||||
}
|
||||
|
||||
if (Excel.StoryExcel != null)
|
||||
{
|
||||
battle.AddBattleTarget(1, 10002, GetTotalScore());
|
||||
|
||||
foreach (var id in Excel.StoryExcel.BattleTargetID!) battle.AddBattleTarget(5, id, GetTotalScore());
|
||||
}
|
||||
|
||||
if (Excel.BossExcel != null)
|
||||
{
|
||||
battle.AddBattleTarget(1, 90004, 0);
|
||||
battle.AddBattleTarget(1, 90005, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual async ValueTask OnBattleEnd(BattleInstance battle, PVEBattleResultCsReq req)
|
||||
{
|
||||
if (IsStory())
|
||||
{
|
||||
// Calculate score for current stage
|
||||
var stageScore = (int)req.Stt.ChallengeScore - GetTotalScore();
|
||||
|
||||
// Set score
|
||||
if (CurrentStage == 1)
|
||||
ScoreStage1 = stageScore;
|
||||
else
|
||||
ScoreStage2 = stageScore;
|
||||
}
|
||||
|
||||
if (IsBoss())
|
||||
{
|
||||
// Calculate score for current stage
|
||||
var stageScore = 0;
|
||||
foreach (var battleTarget in req.Stt.BattleTargetInfo[1].BattleTargetList_)
|
||||
stageScore += (int)battleTarget.Progress;
|
||||
|
||||
// Set score
|
||||
if (CurrentStage == 1)
|
||||
ScoreStage1 = stageScore;
|
||||
else
|
||||
ScoreStage2 = stageScore;
|
||||
}
|
||||
|
||||
switch (req.EndStatus)
|
||||
{
|
||||
case BattleEndStatus.BattleEndWin:
|
||||
// Check if any avatar in the lineup has died
|
||||
foreach (var avatar in battle.Lineup.AvatarData!.FormalAvatars)
|
||||
if (avatar.CurrentHp <= 0)
|
||||
HasAvatarDied = true;
|
||||
|
||||
// Get monster count in stage
|
||||
long monsters = Player.SceneInstance!.Entities.Values.OfType<EntityMonster>().Count();
|
||||
|
||||
if (monsters == 0) await AdvanceStage(req);
|
||||
|
||||
// Calculate rounds left
|
||||
if (!(IsStory() && IsBoss()))
|
||||
RoundsLeft = (int)Math.Min(Math.Max(RoundsLeft - req.Stt.RoundCnt, 1), RoundsLeft);
|
||||
|
||||
// Set saved technique points (This will be restored if the player resets the challenge)
|
||||
SavedMp = Player.LineupManager!.GetCurLineup()!.Mp;
|
||||
break;
|
||||
case BattleEndStatus.BattleEndQuit:
|
||||
// Reset technique points and move back to start position
|
||||
var lineup = Player.LineupManager!.GetCurLineup()!;
|
||||
lineup.Mp = SavedMp;
|
||||
await Player.MoveTo(StartPos, StartRot);
|
||||
await Player.SendPacket(new PacketSyncLineupNotify(lineup));
|
||||
break;
|
||||
default:
|
||||
// Determine challenge result
|
||||
if ((IsStory() || IsBoss()) && req.Stt.EndReason == BattleEndReason.TurnLimit)
|
||||
{
|
||||
await AdvanceStage(req);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fail challenge
|
||||
Status = (int)ChallengeStatus.ChallengeFailed;
|
||||
|
||||
// Send challenge result data
|
||||
await Player.SendPacket(new PacketChallengeSettleNotify(this));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private async ValueTask AdvanceStage(PVEBattleResultCsReq req)
|
||||
{
|
||||
if (CurrentStage >= Excel.StageNum)
|
||||
{
|
||||
// Last stage
|
||||
Status = (int)ChallengeStatus.ChallengeFinish;
|
||||
Stars = CalculateStars();
|
||||
|
||||
// Save history
|
||||
Player.ChallengeManager!.AddHistory(ChallengeId, Stars, GetTotalScore());
|
||||
|
||||
// Send challenge result data
|
||||
if (IsBoss())
|
||||
await Player.SendPacket(new PacketChallengeBossPhaseSettleNotify(this, req.Stt.BattleTargetInfo[1]));
|
||||
else
|
||||
await Player.SendPacket(new PacketChallengeSettleNotify(this));
|
||||
|
||||
// Call MissionManager
|
||||
await Player.MissionManager!.HandleFinishType(MissionFinishTypeEnum.ChallengeFinish, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IsBoss())
|
||||
{
|
||||
await Player.SendPacket(new PacketChallengeBossPhaseSettleNotify(this, req.Stt.BattleTargetInfo[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Increment and reset stage
|
||||
CurrentStage++;
|
||||
// Unload scene group for stage 1
|
||||
await Player.SceneInstance!.EntityLoader!.UnloadGroup(Excel.MazeGroupID1);
|
||||
|
||||
// Load scene group for stage 2
|
||||
await Player.SceneInstance!.EntityLoader!.LoadGroup(Excel.MazeGroupID2);
|
||||
|
||||
// Change player line up
|
||||
SetCurrentExtraLineup(ExtraLineupType.LineupChallenge2);
|
||||
await Player.LineupManager!.SetCurLineup(CurrentExtraLineup + 10);
|
||||
await Player.SendPacket(new PacketChallengeLineupNotify((ExtraLineupType)CurrentExtraLineup));
|
||||
SavedMp = Player.LineupManager.GetCurLineup()!.Mp;
|
||||
|
||||
// Move player
|
||||
if (Excel.MapEntranceID2 != 0 && Excel.MapEntranceID2 != Excel.MapEntranceID)
|
||||
{
|
||||
await Player.EnterScene(Excel.MapEntranceID2, 0, true);
|
||||
StartPos = Player.Data.Pos!;
|
||||
StartRot = Player.Data.Rot!;
|
||||
await Player.SceneInstance!.EntityLoader!.UnloadGroup(Excel.MazeGroupID1);
|
||||
await Player.SceneInstance!.EntityLoader!.LoadGroup(Excel.MazeGroupID2);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Player.MoveTo(StartPos, StartRot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask NextPhase()
|
||||
{
|
||||
// Increment and reset stage
|
||||
CurrentStage++;
|
||||
// Load scene group for stage 2
|
||||
await Player.SceneInstance!.EntityLoader!.LoadGroup(Excel.MazeGroupID2);
|
||||
|
||||
// Change player line up
|
||||
SetCurrentExtraLineup(ExtraLineupType.LineupChallenge2);
|
||||
await Player.LineupManager!.SetCurLineup(CurrentExtraLineup + 10);
|
||||
await Player.SendPacket(new PacketChallengeLineupNotify((ExtraLineupType)CurrentExtraLineup));
|
||||
SavedMp = Player.LineupManager.GetCurLineup()!.Mp;
|
||||
|
||||
// Move player
|
||||
if (Excel.MapEntranceID2 != 0)
|
||||
{
|
||||
await Player.EnterScene(Excel.MapEntranceID2, 0, false);
|
||||
StartPos = Player.Data.Pos!;
|
||||
StartRot = Player.Data.Rot!;
|
||||
await Player.SceneInstance!.EntityLoader!.LoadGroup(Excel.MazeGroupID2);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Player.MoveTo(StartPos, StartRot);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnUpdate()
|
||||
{
|
||||
// End challenge if its done
|
||||
if (Status != (int)ChallengeStatus.ChallengeDoing) Player.ChallengeManager!.ChallengeInstance = null;
|
||||
}
|
||||
|
||||
public int CalculateStars()
|
||||
{
|
||||
var targets = Excel.ChallengeTargetID!;
|
||||
var stars = 0;
|
||||
|
||||
for (var i = 0; i < targets.Count; i++)
|
||||
{
|
||||
if (!GameData.ChallengeTargetData.ContainsKey(targets[i])) continue;
|
||||
|
||||
var target = GameData.ChallengeTargetData[targets[i]];
|
||||
|
||||
switch (target.ChallengeTargetType)
|
||||
{
|
||||
case ChallengeTargetExcel.ChallengeType.ROUNDS_LEFT:
|
||||
if (RoundsLeft >= target.ChallengeTargetParam1) stars += 1 << i;
|
||||
break;
|
||||
case ChallengeTargetExcel.ChallengeType.DEAD_AVATAR:
|
||||
if (!HasAvatarDied) stars += 1 << i;
|
||||
break;
|
||||
case ChallengeTargetExcel.ChallengeType.TOTAL_SCORE:
|
||||
if (GetTotalScore() >= target.ChallengeTargetParam1) stars += 1 << i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Math.Min(stars, 7);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -2,9 +2,13 @@
|
||||
using EggLink.DanhengServer.Database;
|
||||
using EggLink.DanhengServer.Database.Challenge;
|
||||
using EggLink.DanhengServer.Database.Inventory;
|
||||
using EggLink.DanhengServer.GameServer.Game.Challenge.Definitions;
|
||||
using EggLink.DanhengServer.GameServer.Game.Challenge.Instances;
|
||||
using EggLink.DanhengServer.GameServer.Game.Player;
|
||||
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Challenge;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
using EggLink.DanhengServer.Proto.ServerSide;
|
||||
using Google.Protobuf;
|
||||
using static EggLink.DanhengServer.GameServer.Plugin.Event.PluginEvent;
|
||||
|
||||
namespace EggLink.DanhengServer.GameServer.Game.Challenge;
|
||||
@@ -13,7 +17,7 @@ public class ChallengeManager(PlayerInstance player) : BasePlayerManager(player)
|
||||
{
|
||||
#region Properties
|
||||
|
||||
public ChallengeInstance? ChallengeInstance { get; set; }
|
||||
public BaseChallengeInstance? ChallengeInstance { get; set; }
|
||||
|
||||
public ChallengeData ChallengeData { get; } =
|
||||
DatabaseHelper.Instance!.GetInstanceOrCreateNew<ChallengeData>(player.Uid);
|
||||
@@ -82,11 +86,52 @@ public class ChallengeManager(PlayerInstance player) : BasePlayerManager(player)
|
||||
}
|
||||
|
||||
// Set challenge data for player
|
||||
ChallengeInstance instance = new(Player, excel);
|
||||
var data = new ChallengeDataPb();
|
||||
BaseLegacyChallengeInstance instance;
|
||||
|
||||
// Set challenge type
|
||||
if (excel.IsBoss())
|
||||
{
|
||||
data.Boss = new ChallengeBossDataPb
|
||||
{
|
||||
ChallengeMazeId = (uint)excel.ID,
|
||||
CurStatus = 1,
|
||||
CurrentStage = 1,
|
||||
CurrentExtraLineup = ChallengeLineupTypePb.Challenge1
|
||||
};
|
||||
|
||||
instance = new ChallengeBossInstance(Player, data);
|
||||
}
|
||||
else if (excel.IsStory())
|
||||
{
|
||||
data.Story = new ChallengeStoryDataPb
|
||||
{
|
||||
ChallengeMazeId = (uint)excel.ID,
|
||||
CurStatus = 1,
|
||||
CurrentStage = 1,
|
||||
CurrentExtraLineup = ChallengeLineupTypePb.Challenge1
|
||||
};
|
||||
|
||||
instance = new ChallengeStoryInstance(Player, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
data.Memory = new ChallengeMemoryDataPb
|
||||
{
|
||||
ChallengeMazeId = (uint)excel.ID,
|
||||
CurStatus = 1,
|
||||
CurrentStage = 1,
|
||||
CurrentExtraLineup = ChallengeLineupTypePb.Challenge1,
|
||||
RoundsLeft = (uint)excel.ChallengeCountDown
|
||||
};
|
||||
|
||||
instance = new ChallengeMemoryInstance(Player, data);
|
||||
}
|
||||
|
||||
ChallengeInstance = instance;
|
||||
|
||||
// Set first lineup before we enter scenes
|
||||
await Player.LineupManager!.SetCurLineup(instance.CurrentExtraLineup + 10);
|
||||
await Player.LineupManager!.SetCurLineup(instance.GetCurrentExtraLineupType() + 10);
|
||||
|
||||
// Enter scene
|
||||
try
|
||||
@@ -104,20 +149,20 @@ public class ChallengeManager(PlayerInstance player) : BasePlayerManager(player)
|
||||
}
|
||||
|
||||
// Save start positions
|
||||
instance.StartPos = Player.Data.Pos!;
|
||||
instance.StartRot = Player.Data.Rot!;
|
||||
instance.SavedMp = Player.LineupManager.GetCurLineup()!.Mp;
|
||||
instance.SetStartPos(Player.Data.Pos!);
|
||||
instance.SetStartRot(Player.Data.Rot!);
|
||||
instance.SetSavedMp(Player.LineupManager.GetCurLineup()!.Mp);
|
||||
|
||||
if (excel.IsStory() && storyBuffs != null)
|
||||
{
|
||||
instance.StoryBuffs.Add((int)storyBuffs.BuffOne);
|
||||
instance.StoryBuffs.Add((int)storyBuffs.BuffTwo);
|
||||
instance.Data.Story.Buffs.Add(storyBuffs.BuffOne);
|
||||
instance.Data.Story.Buffs.Add(storyBuffs.BuffTwo);
|
||||
}
|
||||
|
||||
if (bossBuffs != null)
|
||||
{
|
||||
instance.BossBuffs.Add((int)bossBuffs.BuffOne);
|
||||
instance.BossBuffs.Add((int)bossBuffs.BuffTwo);
|
||||
instance.Data.Boss.Buffs.Add(bossBuffs.BuffOne);
|
||||
instance.Data.Boss.Buffs.Add(bossBuffs.BuffTwo);
|
||||
}
|
||||
|
||||
InvokeOnPlayerEnterChallenge(Player, instance);
|
||||
@@ -220,40 +265,37 @@ public class ChallengeManager(PlayerInstance player) : BasePlayerManager(player)
|
||||
return rewardInfos;
|
||||
}
|
||||
|
||||
public void SaveInstance(ChallengeInstance instance)
|
||||
public void SaveInstance(BaseChallengeInstance instance)
|
||||
{
|
||||
ChallengeData.Instance.StartPos = instance.StartPos;
|
||||
ChallengeData.Instance.StartRot = instance.StartRot;
|
||||
ChallengeData.Instance.ChallengeId = instance.ChallengeId;
|
||||
ChallengeData.Instance.CurrentStage = instance.CurrentStage;
|
||||
ChallengeData.Instance.CurrentExtraLineup = instance.CurrentExtraLineup;
|
||||
ChallengeData.Instance.Status = instance.Status;
|
||||
ChallengeData.Instance.HasAvatarDied = instance.HasAvatarDied;
|
||||
ChallengeData.Instance.SavedMp = instance.SavedMp;
|
||||
ChallengeData.Instance.RoundsLeft = instance.RoundsLeft;
|
||||
ChallengeData.Instance.Stars = instance.Stars;
|
||||
ChallengeData.Instance.ScoreStage1 = instance.ScoreStage1;
|
||||
ChallengeData.Instance.ScoreStage2 = instance.ScoreStage2;
|
||||
ChallengeData.Instance.StoryBuffs = instance.StoryBuffs;
|
||||
ChallengeData.Instance.BossBuffs = instance.BossBuffs;
|
||||
ChallengeData.ChallengeInstance = Convert.ToBase64String(instance.Data.ToByteArray());
|
||||
}
|
||||
|
||||
public void ClearInstance()
|
||||
{
|
||||
ChallengeData.Instance.ChallengeId = 0;
|
||||
ChallengeData.ChallengeInstance = null;
|
||||
ChallengeInstance = null;
|
||||
}
|
||||
|
||||
public void ResurrectInstance()
|
||||
{
|
||||
if (ChallengeData.Instance != null && ChallengeData.Instance.ChallengeId != 0)
|
||||
if (ChallengeData.ChallengeInstance == null) return;
|
||||
var protoByte = Convert.FromBase64String(ChallengeData.ChallengeInstance);
|
||||
var proto = ChallengeDataPb.Parser.ParseFrom(protoByte);
|
||||
|
||||
if (proto != null)
|
||||
{
|
||||
var ChallengeId = ChallengeData.Instance.ChallengeId;
|
||||
if (GameData.ChallengeConfigData.TryGetValue(ChallengeId, out var value))
|
||||
ChallengeInstance = proto.ChallengeTypeCase switch
|
||||
{
|
||||
var Excel = value;
|
||||
var instance = new ChallengeInstance(Player, Excel, ChallengeData.Instance);
|
||||
ChallengeInstance = instance;
|
||||
}
|
||||
ChallengeDataPb.ChallengeTypeOneofCase.Memory => new ChallengeMemoryInstance(Player, proto),
|
||||
ChallengeDataPb.ChallengeTypeOneofCase.Peak => new ChallengePeakInstance(Player, proto),
|
||||
ChallengeDataPb.ChallengeTypeOneofCase.Story => new ChallengeStoryInstance(Player, proto),
|
||||
ChallengeDataPb.ChallengeTypeOneofCase.Boss => new ChallengeBossInstance(Player, proto),
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
ChallengeData.ChallengeInstance = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
using EggLink.DanhengServer.Data.Excel;
|
||||
using EggLink.DanhengServer.GameServer.Game.Battle;
|
||||
using EggLink.DanhengServer.GameServer.Game.Player;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
using EggLink.DanhengServer.Proto.ServerSide;
|
||||
|
||||
namespace EggLink.DanhengServer.GameServer.Game.Challenge.Definitions;
|
||||
|
||||
public abstract class BaseChallengeInstance(PlayerInstance player, ChallengeDataPb data)
|
||||
{
|
||||
public PlayerInstance Player { get; } = player;
|
||||
public ChallengeDataPb Data { get; } = data;
|
||||
|
||||
public virtual void OnBattleStart(BattleInstance battle)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual async ValueTask OnBattleEnd(BattleInstance battle, PVEBattleResultCsReq req)
|
||||
{
|
||||
await ValueTask.CompletedTask;
|
||||
}
|
||||
|
||||
public abstract Dictionary<int, List<ChallengeConfigExcel.ChallengeMonsterInfo>> GetStageMonsters();
|
||||
|
||||
public virtual void OnUpdate() { }
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
using EggLink.DanhengServer.Data.Excel;
|
||||
using EggLink.DanhengServer.GameServer.Game.Player;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
using EggLink.DanhengServer.Proto.ServerSide;
|
||||
using EggLink.DanhengServer.Util;
|
||||
|
||||
namespace EggLink.DanhengServer.GameServer.Game.Challenge.Definitions;
|
||||
|
||||
public abstract class BaseLegacyChallengeInstance(PlayerInstance player, ChallengeDataPb data) : BaseChallengeInstance(player, data)
|
||||
{
|
||||
public abstract CurChallenge ToProto();
|
||||
public bool IsWin { get; set; }
|
||||
public abstract ChallengeConfigExcel Config { get; }
|
||||
|
||||
public abstract uint GetStars();
|
||||
public abstract int GetCurrentExtraLineupType();
|
||||
public abstract void SetStartPos(Position pos);
|
||||
public abstract void SetStartRot(Position rot);
|
||||
public abstract void SetSavedMp(int mp);
|
||||
|
||||
public virtual uint GetScore1()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public virtual uint GetScore2()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public virtual ChallengeStageInfo ToStageInfo()
|
||||
{
|
||||
return new ChallengeStageInfo();
|
||||
}
|
||||
}
|
||||
326
GameServer/Game/Challenge/Instances/ChallengeBossInstance.cs
Normal file
326
GameServer/Game/Challenge/Instances/ChallengeBossInstance.cs
Normal file
@@ -0,0 +1,326 @@
|
||||
using EggLink.DanhengServer.Data;
|
||||
using EggLink.DanhengServer.Data.Excel;
|
||||
using EggLink.DanhengServer.Enums.Item;
|
||||
using EggLink.DanhengServer.Enums.Mission;
|
||||
using EggLink.DanhengServer.GameServer.Game.Battle;
|
||||
using EggLink.DanhengServer.GameServer.Game.Challenge.Definitions;
|
||||
using EggLink.DanhengServer.GameServer.Game.Player;
|
||||
using EggLink.DanhengServer.GameServer.Game.Scene.Entity;
|
||||
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Challenge;
|
||||
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Lineup;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
using EggLink.DanhengServer.Proto.ServerSide;
|
||||
using EggLink.DanhengServer.Util;
|
||||
|
||||
namespace EggLink.DanhengServer.GameServer.Game.Challenge.Instances;
|
||||
|
||||
public class ChallengeBossInstance(PlayerInstance player, ChallengeDataPb data) : BaseLegacyChallengeInstance(player, data)
|
||||
{
|
||||
#region Properties
|
||||
|
||||
public override ChallengeConfigExcel Config { get; } = GameData.ChallengeConfigData[(int)data.Boss.ChallengeMazeId];
|
||||
|
||||
#endregion
|
||||
|
||||
#region Setter & Getter
|
||||
|
||||
public override uint GetStars()
|
||||
{
|
||||
return Data.Boss.Stars;
|
||||
}
|
||||
|
||||
public override uint GetScore1()
|
||||
{
|
||||
return Data.Boss.ScoreStage1;
|
||||
}
|
||||
|
||||
public override uint GetScore2()
|
||||
{
|
||||
return Data.Boss.ScoreStage2;
|
||||
}
|
||||
|
||||
public void SetCurrentExtraLineup(ExtraLineupType type)
|
||||
{
|
||||
Data.Boss.CurrentExtraLineup = (ChallengeLineupTypePb)type;
|
||||
}
|
||||
|
||||
public int GetTotalScore()
|
||||
{
|
||||
return (int)(Data.Boss.ScoreStage1 + Data.Boss.ScoreStage2);
|
||||
}
|
||||
|
||||
public override int GetCurrentExtraLineupType()
|
||||
{
|
||||
return (int)Data.Boss.CurrentExtraLineup;
|
||||
}
|
||||
|
||||
public override void SetStartPos(Position pos)
|
||||
{
|
||||
Data.Boss.StartPos = pos.ToVector3Pb();
|
||||
}
|
||||
|
||||
public override void SetStartRot(Position rot)
|
||||
{
|
||||
Data.Boss.StartRot = rot.ToVector3Pb();
|
||||
}
|
||||
|
||||
public override void SetSavedMp(int mp)
|
||||
{
|
||||
Data.Boss.SavedMp = (uint)mp;
|
||||
}
|
||||
|
||||
public override Dictionary<int, List<ChallengeConfigExcel.ChallengeMonsterInfo>> GetStageMonsters()
|
||||
{
|
||||
return Data.Boss.CurrentStage == 1
|
||||
? Config.ChallengeMonsters1
|
||||
: Config.ChallengeMonsters2;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Serialization
|
||||
|
||||
public override CurChallenge ToProto()
|
||||
{
|
||||
return new CurChallenge
|
||||
{
|
||||
ChallengeId = Data.Boss.ChallengeMazeId,
|
||||
ExtraLineupType = (ExtraLineupType)Data.Boss.CurrentExtraLineup,
|
||||
Status = (ChallengeStatus)Data.Boss.CurStatus,
|
||||
StageInfo = new ChallengeCurBuffInfo
|
||||
{
|
||||
CurBossBuffs = new ChallengeBossBuffList
|
||||
{
|
||||
BuffList = { Data.Boss.Buffs },
|
||||
ChallengeBossConst = 1
|
||||
}
|
||||
},
|
||||
RoundCount = (uint)Config.ChallengeCountDown,
|
||||
ScoreId = Data.Boss.ScoreStage1,
|
||||
ScoreTwo = Data.Boss.ScoreStage2,
|
||||
};
|
||||
}
|
||||
|
||||
public override ChallengeStageInfo ToStageInfo()
|
||||
{
|
||||
var proto = new ChallengeStageInfo
|
||||
{
|
||||
BossInfo = new ChallengeBossInfo
|
||||
{
|
||||
FirstNode = new ChallengeBossSingleNodeInfo
|
||||
{
|
||||
BuffId = Data.Boss.Buffs[0]
|
||||
},
|
||||
SecondNode = new ChallengeBossSingleNodeInfo
|
||||
{
|
||||
BuffId = Data.Boss.Buffs[1]
|
||||
},
|
||||
NCBDNPGPEAI = true
|
||||
}
|
||||
};
|
||||
|
||||
foreach (var lineupAvatar in Player.LineupManager?.GetExtraLineup(ExtraLineupType.LineupChallenge)
|
||||
?.BaseAvatars ?? [])
|
||||
{
|
||||
var avatar = Player.AvatarManager?.GetFormalAvatar(lineupAvatar.BaseAvatarId);
|
||||
if (avatar == null) continue;
|
||||
proto.BossInfo.FirstLineup.Add((uint)avatar.AvatarId);
|
||||
var equip = Player.InventoryManager?.GetItem(0, avatar.GetCurPathInfo().EquipId,
|
||||
ItemMainTypeEnum.Equipment);
|
||||
if (equip != null)
|
||||
proto.BossInfo.ChallengeAvatarEquipmentMap.Add((uint)avatar.AvatarId,
|
||||
equip.ToChallengeEquipmentProto());
|
||||
|
||||
var relicProto = new ChallengeBossAvatarRelicInfo();
|
||||
|
||||
foreach (var relicUniqueId in avatar.GetCurPathInfo().Relic)
|
||||
{
|
||||
var relic = Player.InventoryManager?.GetItem(0, relicUniqueId.Value, ItemMainTypeEnum.Relic);
|
||||
if (relic == null) continue;
|
||||
relicProto.AvatarRelicSlotMap.Add((uint)relicUniqueId.Key, relic.ToChallengeRelicProto());
|
||||
}
|
||||
|
||||
proto.BossInfo.ChallengeAvatarRelicMap.Add((uint)avatar.AvatarId, relicProto);
|
||||
}
|
||||
|
||||
foreach (var lineupAvatar in Player.LineupManager?.GetExtraLineup(ExtraLineupType.LineupChallenge2)
|
||||
?.BaseAvatars ?? [])
|
||||
{
|
||||
var avatar = Player.AvatarManager?.GetFormalAvatar(lineupAvatar.BaseAvatarId);
|
||||
if (avatar == null) continue;
|
||||
proto.BossInfo.SecondLineup.Add((uint)avatar.AvatarId);
|
||||
var equip = Player.InventoryManager?.GetItem(0, avatar.GetCurPathInfo().EquipId,
|
||||
ItemMainTypeEnum.Equipment);
|
||||
if (equip != null)
|
||||
proto.BossInfo.ChallengeAvatarEquipmentMap.Add((uint)avatar.AvatarId,
|
||||
equip.ToChallengeEquipmentProto());
|
||||
|
||||
var relicProto = new ChallengeBossAvatarRelicInfo();
|
||||
|
||||
foreach (var relicUniqueId in avatar.GetCurPathInfo().Relic)
|
||||
{
|
||||
var relic = Player.InventoryManager?.GetItem(0, relicUniqueId.Value, ItemMainTypeEnum.Relic);
|
||||
if (relic == null) continue;
|
||||
relicProto.AvatarRelicSlotMap.Add((uint)relicUniqueId.Key, relic.ToChallengeRelicProto());
|
||||
}
|
||||
|
||||
proto.BossInfo.ChallengeAvatarRelicMap.Add((uint)avatar.AvatarId, relicProto);
|
||||
}
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Handlers
|
||||
|
||||
public override void OnBattleStart(BattleInstance battle)
|
||||
{
|
||||
battle.RoundLimit = Config.ChallengeCountDown;
|
||||
|
||||
battle.Buffs.Add(new MazeBuff(Config.MazeBuffID, 1, -1)
|
||||
{
|
||||
WaveFlag = -1
|
||||
});
|
||||
|
||||
battle.AddBattleTarget(1, 90004, 0);
|
||||
battle.AddBattleTarget(1, 90005, 0);
|
||||
|
||||
if (Data.Boss.Buffs.Count < Data.Boss.CurrentStage) return;
|
||||
var buffId = Data.Boss.Buffs[(int)(Data.Boss.CurrentStage - 1)];
|
||||
battle.Buffs.Add(new MazeBuff((int)buffId, 1, -1)
|
||||
{
|
||||
WaveFlag = -1
|
||||
});
|
||||
}
|
||||
|
||||
public override async ValueTask OnBattleEnd(BattleInstance battle, PVEBattleResultCsReq req)
|
||||
{
|
||||
// Calculate score for current stage
|
||||
var stageScore = 0;
|
||||
foreach (var battleTarget in req.Stt.BattleTargetInfo[1].BattleTargetList_)
|
||||
stageScore += (int)battleTarget.Progress;
|
||||
|
||||
// Set score
|
||||
if (Data.Boss.CurrentStage == 1)
|
||||
Data.Boss.ScoreStage1 = (uint)stageScore;
|
||||
else
|
||||
Data.Boss.ScoreStage2 = (uint)stageScore;
|
||||
|
||||
switch (req.EndStatus)
|
||||
{
|
||||
case BattleEndStatus.BattleEndWin:
|
||||
// Get monster count in stage
|
||||
long monsters = Player.SceneInstance!.Entities.Values.OfType<EntityMonster>().Count();
|
||||
|
||||
if (monsters == 0) await AdvanceStage(req);
|
||||
|
||||
// Set saved technique points (This will be restored if the player resets the challenge)
|
||||
Data.Boss.SavedMp = (uint)Player.LineupManager!.GetCurLineup()!.Mp;
|
||||
break;
|
||||
case BattleEndStatus.BattleEndQuit:
|
||||
// Reset technique points and move back to start position
|
||||
var lineup = Player.LineupManager!.GetCurLineup()!;
|
||||
lineup.Mp = (int)Data.Boss.SavedMp;
|
||||
await Player.MoveTo(Data.Boss.StartPos.ToPosition(), Data.Boss.StartRot.ToPosition());
|
||||
await Player.SendPacket(new PacketSyncLineupNotify(lineup));
|
||||
break;
|
||||
default:
|
||||
// Determine challenge result
|
||||
if (req.Stt.EndReason == BattleEndReason.TurnLimit)
|
||||
{
|
||||
await AdvanceStage(req);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fail challenge
|
||||
Data.Boss.CurStatus = (int)ChallengeStatus.ChallengeFailed;
|
||||
|
||||
// Send challenge result data
|
||||
await Player.SendPacket(new PacketChallengeBossPhaseSettleNotify(this));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public uint CalculateStars()
|
||||
{
|
||||
var targets = Config.ChallengeTargetID!;
|
||||
var stars = 0u;
|
||||
|
||||
for (var i = 0; i < targets.Count; i++)
|
||||
{
|
||||
if (!GameData.ChallengeTargetData.ContainsKey(targets[i])) continue;
|
||||
|
||||
var target = GameData.ChallengeTargetData[targets[i]];
|
||||
|
||||
switch (target.ChallengeTargetType)
|
||||
{
|
||||
case ChallengeTargetExcel.ChallengeType.TOTAL_SCORE:
|
||||
if (GetTotalScore() >= target.ChallengeTargetParam1) stars += 1u << i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Math.Min(stars, 7);
|
||||
}
|
||||
|
||||
private async ValueTask AdvanceStage(PVEBattleResultCsReq req)
|
||||
{
|
||||
if (Data.Boss.CurrentStage >= Config.StageNum)
|
||||
{
|
||||
// Last stage
|
||||
Data.Boss.CurStatus = (int)ChallengeStatus.ChallengeFinish;
|
||||
Data.Boss.Stars = CalculateStars();
|
||||
|
||||
// Save history
|
||||
Player.ChallengeManager!.AddHistory((int)Data.Boss.ChallengeMazeId, (int)GetStars(), GetTotalScore());
|
||||
|
||||
// Send challenge result data
|
||||
await Player.SendPacket(new PacketChallengeBossPhaseSettleNotify(this, req.Stt.BattleTargetInfo[1]));
|
||||
|
||||
// Call MissionManager
|
||||
await Player.MissionManager!.HandleFinishType(MissionFinishTypeEnum.ChallengeFinish, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Player.SendPacket(new PacketChallengeBossPhaseSettleNotify(this, req.Stt.BattleTargetInfo[1]));
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask NextPhase()
|
||||
{
|
||||
// Increment and reset stage
|
||||
Data.Boss.CurrentStage++;
|
||||
|
||||
// unload current scene group
|
||||
await Player.SceneInstance!.EntityLoader!.UnloadGroup(Config.MazeGroupID1);
|
||||
// Load scene group for stage 2
|
||||
await Player.SceneInstance!.EntityLoader!.LoadGroup(Config.MazeGroupID2);
|
||||
|
||||
// Change player line up
|
||||
SetCurrentExtraLineup(ExtraLineupType.LineupChallenge2);
|
||||
await Player.LineupManager!.SetCurLineup(GetCurrentExtraLineupType() + 10);
|
||||
await Player.SendPacket(new PacketChallengeLineupNotify((ExtraLineupType)GetCurrentExtraLineupType()));
|
||||
Data.Boss.SavedMp = (uint)Player.LineupManager.GetCurLineup()!.Mp;
|
||||
|
||||
// Move player
|
||||
if (Config.MapEntranceID2 != 0)
|
||||
{
|
||||
await Player.EnterScene(Config.MapEntranceID2, 0, false);
|
||||
Data.Boss.StartPos = Player.Data.Pos!.ToVector3Pb();
|
||||
Data.Boss.StartRot = Player.Data.Rot!.ToVector3Pb();
|
||||
await Player.SceneInstance!.EntityLoader!.LoadGroup(Config.MazeGroupID2);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Player.MoveTo(Data.Boss.StartPos.ToPosition(), Data.Boss.StartRot.ToPosition());
|
||||
}
|
||||
|
||||
Player.ChallengeManager!.SaveInstance(this);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
210
GameServer/Game/Challenge/Instances/ChallengeMemoryInstance.cs
Normal file
210
GameServer/Game/Challenge/Instances/ChallengeMemoryInstance.cs
Normal file
@@ -0,0 +1,210 @@
|
||||
using EggLink.DanhengServer.Data;
|
||||
using EggLink.DanhengServer.Data.Excel;
|
||||
using EggLink.DanhengServer.Enums.Mission;
|
||||
using EggLink.DanhengServer.GameServer.Game.Battle;
|
||||
using EggLink.DanhengServer.GameServer.Game.Challenge.Definitions;
|
||||
using EggLink.DanhengServer.GameServer.Game.Player;
|
||||
using EggLink.DanhengServer.GameServer.Game.Scene.Entity;
|
||||
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Challenge;
|
||||
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Lineup;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
using EggLink.DanhengServer.Proto.ServerSide;
|
||||
using EggLink.DanhengServer.Util;
|
||||
|
||||
namespace EggLink.DanhengServer.GameServer.Game.Challenge.Instances;
|
||||
|
||||
public class ChallengeMemoryInstance(PlayerInstance player, ChallengeDataPb data) : BaseLegacyChallengeInstance(player, data)
|
||||
{
|
||||
#region Properties
|
||||
|
||||
public override ChallengeConfigExcel Config { get; } = GameData.ChallengeConfigData[(int)data.Memory.ChallengeMazeId];
|
||||
|
||||
#endregion
|
||||
|
||||
#region Getter & Setter
|
||||
|
||||
public void SetCurrentExtraLineup(ExtraLineupType type)
|
||||
{
|
||||
Data.Memory.CurrentExtraLineup = (ChallengeLineupTypePb)type;
|
||||
}
|
||||
|
||||
public override Dictionary<int, List<ChallengeConfigExcel.ChallengeMonsterInfo>> GetStageMonsters()
|
||||
{
|
||||
return Data.Memory.CurrentStage == 1 ? Config.ChallengeMonsters1 : Config.ChallengeMonsters2;
|
||||
}
|
||||
|
||||
public override uint GetStars()
|
||||
{
|
||||
return Data.Memory.Stars;
|
||||
}
|
||||
|
||||
public override int GetCurrentExtraLineupType()
|
||||
{
|
||||
return (int)Data.Memory.CurrentExtraLineup;
|
||||
}
|
||||
|
||||
public override void SetStartPos(Position pos)
|
||||
{
|
||||
Data.Memory.StartPos = pos.ToVector3Pb();
|
||||
}
|
||||
|
||||
public override void SetStartRot(Position rot)
|
||||
{
|
||||
Data.Memory.StartRot = rot.ToVector3Pb();
|
||||
}
|
||||
|
||||
public override void SetSavedMp(int mp)
|
||||
{
|
||||
Data.Memory.SavedMp = (uint)mp;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Serialization
|
||||
|
||||
public override CurChallenge ToProto()
|
||||
{
|
||||
return new CurChallenge
|
||||
{
|
||||
ChallengeId = Data.Memory.ChallengeMazeId,
|
||||
DeadAvatarNum = Data.Memory.DeadAvatarNum,
|
||||
ExtraLineupType = (ExtraLineupType)Data.Memory.CurrentExtraLineup,
|
||||
Status = (ChallengeStatus)Data.Memory.CurStatus,
|
||||
StageInfo = new ChallengeCurBuffInfo(),
|
||||
RoundCount = (uint)(Config.ChallengeCountDown - Data.Memory.RoundsLeft)
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Handlers
|
||||
|
||||
public override void OnBattleStart(BattleInstance battle)
|
||||
{
|
||||
battle.RoundLimit = (int)Data.Memory.RoundsLeft;
|
||||
|
||||
battle.Buffs.Add(new MazeBuff(Config.MazeBuffID, 1, -1)
|
||||
{
|
||||
WaveFlag = -1
|
||||
});
|
||||
}
|
||||
|
||||
public override async ValueTask OnBattleEnd(BattleInstance battle, PVEBattleResultCsReq req)
|
||||
{
|
||||
switch (req.EndStatus)
|
||||
{
|
||||
case BattleEndStatus.BattleEndWin:
|
||||
// Check if any avatar in the lineup has died
|
||||
foreach (var avatar in battle.Lineup.AvatarData!.FormalAvatars)
|
||||
if (avatar.CurrentHp <= 0)
|
||||
Data.Memory.DeadAvatarNum++;
|
||||
|
||||
// Get monster count in stage
|
||||
long monsters = Player.SceneInstance!.Entities.Values.OfType<EntityMonster>().Count();
|
||||
|
||||
if (monsters == 0) await AdvanceStage();
|
||||
|
||||
// Calculate rounds left
|
||||
Data.Memory.RoundsLeft = Math.Min(Math.Max(Data.Memory.RoundsLeft - req.Stt.RoundCnt, 1),
|
||||
Data.Memory.RoundsLeft);
|
||||
|
||||
// Set saved technique points (This will be restored if the player resets the challenge)
|
||||
Data.Memory.SavedMp = (uint)Player.LineupManager!.GetCurLineup()!.Mp;
|
||||
break;
|
||||
case BattleEndStatus.BattleEndQuit:
|
||||
// Reset technique points and move back to start position
|
||||
var lineup = Player.LineupManager!.GetCurLineup()!;
|
||||
lineup.Mp = (int)Data.Memory.SavedMp;
|
||||
await Player.MoveTo(Data.Memory.StartPos.ToPosition(), Data.Memory.StartRot.ToPosition());
|
||||
await Player.SendPacket(new PacketSyncLineupNotify(lineup));
|
||||
break;
|
||||
default:
|
||||
// Determine challenge result
|
||||
// Fail challenge
|
||||
Data.Memory.CurStatus = (int)ChallengeStatus.ChallengeFailed;
|
||||
|
||||
// Send challenge result data
|
||||
await Player.SendPacket(new PacketChallengeSettleNotify(this));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public uint CalculateStars()
|
||||
{
|
||||
var targets = Config.ChallengeTargetID!;
|
||||
var stars = 0u;
|
||||
|
||||
for (var i = 0; i < targets.Count; i++)
|
||||
{
|
||||
if (!GameData.ChallengeTargetData.ContainsKey(targets[i])) continue;
|
||||
|
||||
var target = GameData.ChallengeTargetData[targets[i]];
|
||||
|
||||
switch (target.ChallengeTargetType)
|
||||
{
|
||||
case ChallengeTargetExcel.ChallengeType.ROUNDS_LEFT:
|
||||
if (Data.Memory.RoundsLeft >= target.ChallengeTargetParam1) stars += 1u << i;
|
||||
break;
|
||||
case ChallengeTargetExcel.ChallengeType.DEAD_AVATAR:
|
||||
if (Data.Memory.DeadAvatarNum == 0) stars += 1u << i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Math.Min(stars, 7);
|
||||
}
|
||||
|
||||
private async ValueTask AdvanceStage()
|
||||
{
|
||||
if (Data.Memory.CurrentStage >= Config.StageNum)
|
||||
{
|
||||
// Last stage
|
||||
Data.Memory.CurStatus = (int)ChallengeStatus.ChallengeFinish;
|
||||
Data.Memory.Stars = CalculateStars();
|
||||
|
||||
// Save history
|
||||
Player.ChallengeManager!.AddHistory((int)Data.Memory.ChallengeMazeId, (int)Data.Memory.Stars, 0);
|
||||
|
||||
// Send challenge result data
|
||||
await Player.SendPacket(new PacketChallengeSettleNotify(this));
|
||||
|
||||
// Call MissionManager
|
||||
await Player.MissionManager!.HandleFinishType(MissionFinishTypeEnum.ChallengeFinish, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Increment and reset stage
|
||||
Data.Memory.CurrentStage++;
|
||||
// Unload scene group for stage 1
|
||||
await Player.SceneInstance!.EntityLoader!.UnloadGroup(Config.MazeGroupID1);
|
||||
|
||||
// Load scene group for stage 2
|
||||
await Player.SceneInstance!.EntityLoader!.LoadGroup(Config.MazeGroupID2);
|
||||
|
||||
// Change player line up
|
||||
SetCurrentExtraLineup(ExtraLineupType.LineupChallenge2);
|
||||
await Player.LineupManager!.SetCurLineup((int)(Data.Memory.CurrentExtraLineup + 10));
|
||||
await Player.SendPacket(new PacketChallengeLineupNotify((ExtraLineupType)Data.Memory.CurrentExtraLineup));
|
||||
Data.Memory.SavedMp = (uint)Player.LineupManager.GetCurLineup()!.Mp;
|
||||
|
||||
// Move player
|
||||
if (Config.MapEntranceID2 != 0 && Config.MapEntranceID2 != Config.MapEntranceID)
|
||||
{
|
||||
await Player.EnterScene(Config.MapEntranceID2, 0, true);
|
||||
Data.Memory.StartPos = Player.Data.Pos!.ToVector3Pb();
|
||||
Data.Memory.StartRot = Player.Data.Rot!.ToVector3Pb();
|
||||
await Player.SceneInstance!.EntityLoader!.UnloadGroup(Config.MazeGroupID1);
|
||||
await Player.SceneInstance!.EntityLoader!.LoadGroup(Config.MazeGroupID2);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Player.MoveTo(Data.Memory.StartPos.ToPosition(), Data.Memory.StartRot.ToPosition());
|
||||
}
|
||||
|
||||
Player.ChallengeManager!.SaveInstance(this);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
250
GameServer/Game/Challenge/Instances/ChallengeStoryInstance.cs
Normal file
250
GameServer/Game/Challenge/Instances/ChallengeStoryInstance.cs
Normal file
@@ -0,0 +1,250 @@
|
||||
using EggLink.DanhengServer.Data;
|
||||
using EggLink.DanhengServer.Data.Excel;
|
||||
using EggLink.DanhengServer.Enums.Mission;
|
||||
using EggLink.DanhengServer.GameServer.Game.Battle;
|
||||
using EggLink.DanhengServer.GameServer.Game.Challenge.Definitions;
|
||||
using EggLink.DanhengServer.GameServer.Game.Player;
|
||||
using EggLink.DanhengServer.GameServer.Game.Scene.Entity;
|
||||
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Challenge;
|
||||
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Lineup;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
using EggLink.DanhengServer.Proto.ServerSide;
|
||||
using EggLink.DanhengServer.Util;
|
||||
|
||||
namespace EggLink.DanhengServer.GameServer.Game.Challenge.Instances;
|
||||
|
||||
public class ChallengeStoryInstance(PlayerInstance player, ChallengeDataPb data) : BaseLegacyChallengeInstance(player, data)
|
||||
{
|
||||
#region Properties
|
||||
|
||||
public override ChallengeConfigExcel Config { get; } = GameData.ChallengeConfigData[(int)data.Story.ChallengeMazeId];
|
||||
|
||||
#endregion
|
||||
|
||||
#region Setter & Getter
|
||||
|
||||
public override uint GetStars()
|
||||
{
|
||||
return Data.Story.Stars;
|
||||
}
|
||||
|
||||
public override uint GetScore1()
|
||||
{
|
||||
return Data.Story.ScoreStage1;
|
||||
}
|
||||
|
||||
public override uint GetScore2()
|
||||
{
|
||||
return Data.Story.ScoreStage2;
|
||||
}
|
||||
|
||||
public void SetCurrentExtraLineup(ExtraLineupType type)
|
||||
{
|
||||
Data.Story.CurrentExtraLineup = (ChallengeLineupTypePb)type;
|
||||
}
|
||||
|
||||
public int GetTotalScore()
|
||||
{
|
||||
return (int)(Data.Story.ScoreStage1 + Data.Story.ScoreStage2);
|
||||
}
|
||||
|
||||
public override int GetCurrentExtraLineupType()
|
||||
{
|
||||
return (int)Data.Story.CurrentExtraLineup;
|
||||
}
|
||||
|
||||
public override void SetStartPos(Position pos)
|
||||
{
|
||||
Data.Story.StartPos = pos.ToVector3Pb();
|
||||
}
|
||||
|
||||
public override void SetStartRot(Position rot)
|
||||
{
|
||||
Data.Story.StartRot = rot.ToVector3Pb();
|
||||
}
|
||||
|
||||
public override void SetSavedMp(int mp)
|
||||
{
|
||||
Data.Story.SavedMp = (uint)mp;
|
||||
}
|
||||
|
||||
public override Dictionary<int, List<ChallengeConfigExcel.ChallengeMonsterInfo>> GetStageMonsters()
|
||||
{
|
||||
return Data.Story.CurrentStage == 1
|
||||
? Config.ChallengeMonsters1
|
||||
: Config.ChallengeMonsters2;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Serialization
|
||||
|
||||
public override CurChallenge ToProto()
|
||||
{
|
||||
return new CurChallenge
|
||||
{
|
||||
ChallengeId = Data.Story.ChallengeMazeId,
|
||||
ExtraLineupType = (ExtraLineupType)Data.Story.CurrentExtraLineup,
|
||||
Status = (ChallengeStatus)Data.Story.CurStatus,
|
||||
StageInfo = new ChallengeCurBuffInfo
|
||||
{
|
||||
CurStoryBuffs = new ChallengeStoryBuffList
|
||||
{
|
||||
BuffList = { Data.Story.Buffs }
|
||||
}
|
||||
},
|
||||
RoundCount = (uint)Config.ChallengeCountDown,
|
||||
ScoreId = Data.Story.ScoreStage1,
|
||||
ScoreTwo = Data.Story.ScoreStage2
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Handlers
|
||||
|
||||
public override void OnBattleStart(BattleInstance battle)
|
||||
{
|
||||
battle.RoundLimit = Config.ChallengeCountDown;
|
||||
|
||||
battle.Buffs.Add(new MazeBuff(Config.MazeBuffID, 1, -1)
|
||||
{
|
||||
WaveFlag = -1
|
||||
});
|
||||
|
||||
if (Config.StoryExcel == null) return;
|
||||
battle.AddBattleTarget(1, 10002, GetTotalScore());
|
||||
|
||||
foreach (var id in Config.StoryExcel.BattleTargetID!) battle.AddBattleTarget(5, id, GetTotalScore());
|
||||
|
||||
if (Data.Story.Buffs.Count < Data.Story.CurrentStage) return;
|
||||
var buffId = Data.Story.Buffs[(int)(Data.Story.CurrentStage - 1)];
|
||||
battle.Buffs.Add(new MazeBuff((int)buffId, 1, -1)
|
||||
{
|
||||
WaveFlag = -1
|
||||
});
|
||||
}
|
||||
|
||||
public override async ValueTask OnBattleEnd(BattleInstance battle, PVEBattleResultCsReq req)
|
||||
{
|
||||
// Calculate score for current stage
|
||||
var stageScore = (int)req.Stt.ChallengeScore - GetTotalScore();
|
||||
|
||||
// Set score
|
||||
if (Data.Story.CurrentStage == 1)
|
||||
Data.Story.ScoreStage1 = (uint)stageScore;
|
||||
else
|
||||
Data.Story.ScoreStage2 = (uint)stageScore;
|
||||
|
||||
switch (req.EndStatus)
|
||||
{
|
||||
case BattleEndStatus.BattleEndWin:
|
||||
// Get monster count in stage
|
||||
long monsters = Player.SceneInstance!.Entities.Values.OfType<EntityMonster>().Count();
|
||||
|
||||
if (monsters == 0) await AdvanceStage();
|
||||
|
||||
// Set saved technique points (This will be restored if the player resets the challenge)
|
||||
Data.Story.SavedMp = (uint)Player.LineupManager!.GetCurLineup()!.Mp;
|
||||
break;
|
||||
case BattleEndStatus.BattleEndQuit:
|
||||
// Reset technique points and move back to start position
|
||||
var lineup = Player.LineupManager!.GetCurLineup()!;
|
||||
lineup.Mp = (int)Data.Story.SavedMp;
|
||||
await Player.MoveTo(Data.Story.StartPos.ToPosition(), Data.Story.StartRot.ToPosition());
|
||||
await Player.SendPacket(new PacketSyncLineupNotify(lineup));
|
||||
break;
|
||||
default:
|
||||
// Determine challenge result
|
||||
if (req.Stt.EndReason == BattleEndReason.TurnLimit)
|
||||
{
|
||||
await AdvanceStage();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fail challenge
|
||||
Data.Story.CurStatus = (int)ChallengeStatus.ChallengeFailed;
|
||||
|
||||
// Send challenge result data
|
||||
await Player.SendPacket(new PacketChallengeSettleNotify(this));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public uint CalculateStars()
|
||||
{
|
||||
var targets = Config.ChallengeTargetID!;
|
||||
var stars = 0u;
|
||||
|
||||
for (var i = 0; i < targets.Count; i++)
|
||||
{
|
||||
if (!GameData.ChallengeTargetData.ContainsKey(targets[i])) continue;
|
||||
|
||||
var target = GameData.ChallengeTargetData[targets[i]];
|
||||
|
||||
switch (target.ChallengeTargetType)
|
||||
{
|
||||
case ChallengeTargetExcel.ChallengeType.TOTAL_SCORE:
|
||||
if (GetTotalScore() >= target.ChallengeTargetParam1) stars += 1u << i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Math.Min(stars, 7);
|
||||
}
|
||||
|
||||
private async ValueTask AdvanceStage()
|
||||
{
|
||||
if (Data.Story.CurrentStage >= Config.StageNum)
|
||||
{
|
||||
// Last stage
|
||||
Data.Story.CurStatus = (int)ChallengeStatus.ChallengeFinish;
|
||||
Data.Story.Stars = CalculateStars();
|
||||
|
||||
// Save history
|
||||
Player.ChallengeManager!.AddHistory((int)Data.Story.ChallengeMazeId, (int)GetStars(), GetTotalScore());
|
||||
|
||||
// Send challenge result data
|
||||
await Player.SendPacket(new PacketChallengeSettleNotify(this));
|
||||
|
||||
// Call MissionManager
|
||||
await Player.MissionManager!.HandleFinishType(MissionFinishTypeEnum.ChallengeFinish, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Increment and reset stage
|
||||
Data.Story.CurrentStage++;
|
||||
// Unload scene group for stage 1
|
||||
await Player.SceneInstance!.EntityLoader!.UnloadGroup(Config.MazeGroupID1);
|
||||
|
||||
// Load scene group for stage 2
|
||||
await Player.SceneInstance!.EntityLoader!.LoadGroup(Config.MazeGroupID2);
|
||||
|
||||
// Change player line up
|
||||
SetCurrentExtraLineup(ExtraLineupType.LineupChallenge2);
|
||||
await Player.LineupManager!.SetCurLineup((int)(Data.Story.CurrentExtraLineup + 10));
|
||||
await Player.SendPacket(new PacketChallengeLineupNotify((ExtraLineupType)Data.Story.CurrentExtraLineup));
|
||||
Data.Story.SavedMp = (uint)Player.LineupManager.GetCurLineup()!.Mp;
|
||||
|
||||
// Move player
|
||||
if (Config.MapEntranceID2 != 0 && Config.MapEntranceID2 != Config.MapEntranceID)
|
||||
{
|
||||
await Player.EnterScene(Config.MapEntranceID2, 0, true);
|
||||
Data.Story.StartPos = Player.Data.Pos!.ToVector3Pb();
|
||||
Data.Story.StartRot = Player.Data.Rot!.ToVector3Pb();
|
||||
await Player.SceneInstance!.EntityLoader!.UnloadGroup(Config.MazeGroupID1);
|
||||
await Player.SceneInstance!.EntityLoader!.LoadGroup(Config.MazeGroupID2);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Player.MoveTo(Data.Story.StartPos.ToPosition(), Data.Story.StartRot.ToPosition());
|
||||
}
|
||||
|
||||
Player.ChallengeManager!.SaveInstance(this);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using EggLink.DanhengServer.Data.Excel;
|
||||
using EggLink.DanhengServer.Enums.Mission;
|
||||
using EggLink.DanhengServer.GameServer.Game.Challenge;
|
||||
using EggLink.DanhengServer.GameServer.Game.Challenge.Definitions;
|
||||
using EggLink.DanhengServer.GameServer.Game.Player;
|
||||
|
||||
namespace EggLink.DanhengServer.GameServer.Game.Mission.FinishType.Handler;
|
||||
@@ -11,16 +12,16 @@ public class MissionHandlerChallengeFinish : MissionFinishTypeHandler
|
||||
{
|
||||
public override async ValueTask HandleMissionFinishType(PlayerInstance player, SubMissionInfo info, object? arg)
|
||||
{
|
||||
if (arg is ChallengeInstance challenge)
|
||||
if (challenge.Excel.ID == info.ParamInt1 && challenge.IsWin())
|
||||
if (arg is BaseLegacyChallengeInstance challenge)
|
||||
if (challenge.Config.ID == info.ParamInt1 && challenge.IsWin)
|
||||
await player.MissionManager!.FinishSubMission(info.ID);
|
||||
}
|
||||
|
||||
public override async ValueTask HandleQuestFinishType(PlayerInstance player, QuestDataExcel quest,
|
||||
FinishWayExcel excel, object? arg)
|
||||
{
|
||||
if (arg is ChallengeInstance challenge)
|
||||
if (challenge.Excel.ID == excel.ParamInt1 && challenge.IsWin())
|
||||
if (arg is BaseLegacyChallengeInstance challenge)
|
||||
if (challenge.Config.ID == excel.ParamInt1 && challenge.IsWin)
|
||||
await player.QuestManager!.AddQuestProgress(quest.QuestID, 1);
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ using EggLink.DanhengServer.GameServer.Game.Activity;
|
||||
using EggLink.DanhengServer.GameServer.Game.Avatar;
|
||||
using EggLink.DanhengServer.GameServer.Game.Battle;
|
||||
using EggLink.DanhengServer.GameServer.Game.Challenge;
|
||||
using EggLink.DanhengServer.GameServer.Game.ChallengePeak;
|
||||
using EggLink.DanhengServer.GameServer.Game.ChessRogue;
|
||||
using EggLink.DanhengServer.GameServer.Game.Friend;
|
||||
using EggLink.DanhengServer.GameServer.Game.Gacha;
|
||||
@@ -93,6 +94,7 @@ public partial class PlayerInstance(PlayerData data)
|
||||
public MailManager? MailManager { get; private set; }
|
||||
public FriendManager? FriendManager { get; private set; }
|
||||
public ChallengeManager? ChallengeManager { get; private set; }
|
||||
public ChallengePeakManager? ChallengePeakManager { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -180,6 +182,7 @@ public partial class PlayerInstance(PlayerData data)
|
||||
RogueTournManager = new RogueTournManager(this);
|
||||
RogueMagicManager = new RogueMagicManager(this);
|
||||
ChallengeManager = new ChallengeManager(this);
|
||||
ChallengePeakManager = new ChallengePeakManager(this);
|
||||
TaskManager = new TaskManager(this);
|
||||
RaidManager = new RaidManager(this);
|
||||
StoryLineManager = new StoryLineManager(this);
|
||||
@@ -274,9 +277,6 @@ public partial class PlayerInstance(PlayerData data)
|
||||
AvatarManager!.GetTrialAvatar(e.SpecialAvatarID)?.CheckLevel(Data.WorldLevel);
|
||||
}
|
||||
|
||||
await LoadScene(Data.PlaneId, Data.FloorId, Data.EntryId, Data.Pos!, Data.Rot!, false);
|
||||
if (SceneInstance == null) await EnterScene(2000101, 0, false);
|
||||
|
||||
if (ConfigManager.Config.ServerOption.EnableMission) await MissionManager!.AcceptMainMissionByCondition();
|
||||
|
||||
await QuestManager!.AcceptQuestByCondition();
|
||||
@@ -308,6 +308,9 @@ public partial class PlayerInstance(PlayerData data)
|
||||
if (RaidManager != null)
|
||||
await RaidManager.OnLogin();
|
||||
|
||||
await LoadScene(Data.PlaneId, Data.FloorId, Data.EntryId, Data.Pos!, Data.Rot!, false);
|
||||
if (SceneInstance == null) await EnterScene(2000101, 0, false);
|
||||
|
||||
InvokeOnPlayerLogin(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
<ProjectReference Include="..\Common\Common.csproj" />
|
||||
<ProjectReference Include="..\DanhengKcpSharp\DanhengKcpSharp.csproj" />
|
||||
<ProjectReference Include="..\Proto\Proto.csproj" />
|
||||
<ProjectReference Include="..\ServerSideProto\ServerSideProto.csproj" />
|
||||
<PackageReference Include="Google.Protobuf" Version="3.29.1" />
|
||||
<PackageReference Include="Google.Protobuf.Tools" Version="3.29.1" />
|
||||
<PackageReference Include="McMaster.NETCore.Plugins" Version="1.4.0" />
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using EggLink.DanhengServer.Command;
|
||||
using EggLink.DanhengServer.GameServer.Game.Battle;
|
||||
using EggLink.DanhengServer.GameServer.Game.Challenge;
|
||||
using EggLink.DanhengServer.GameServer.Game.Challenge.Definitions;
|
||||
using EggLink.DanhengServer.GameServer.Game.Player;
|
||||
using EggLink.DanhengServer.GameServer.Game.Scene;
|
||||
using EggLink.DanhengServer.GameServer.Game.Scene.Entity;
|
||||
@@ -56,12 +57,12 @@ public static class PluginEvent
|
||||
OnPlayerQuitBattle?.Invoke(player, result);
|
||||
}
|
||||
|
||||
public static void InvokeOnPlayerEnterChallenge(PlayerInstance player, ChallengeInstance challenge)
|
||||
public static void InvokeOnPlayerEnterChallenge(PlayerInstance player, BaseChallengeInstance challenge)
|
||||
{
|
||||
OnPlayerEnterChallenge?.Invoke(player, challenge);
|
||||
}
|
||||
|
||||
public static void InvokeOnPlayerQuitChallenge(PlayerInstance player, ChallengeInstance? challenge)
|
||||
public static void InvokeOnPlayerQuitChallenge(PlayerInstance player, BaseChallengeInstance? challenge)
|
||||
{
|
||||
OnPlayerQuitChallenge?.Invoke(player, challenge);
|
||||
}
|
||||
@@ -96,9 +97,9 @@ public static class PluginEvent
|
||||
|
||||
public delegate void OnPlayerQuitBattleHandler(PlayerInstance player, PVEBattleResultCsReq result);
|
||||
|
||||
public delegate void OnPlayerEnterChallengeHandler(PlayerInstance player, ChallengeInstance challenge);
|
||||
public delegate void OnPlayerEnterChallengeHandler(PlayerInstance player, BaseChallengeInstance challenge);
|
||||
|
||||
public delegate void OnPlayerQuitChallengeHandler(PlayerInstance player, ChallengeInstance? challenge);
|
||||
public delegate void OnPlayerQuitChallengeHandler(PlayerInstance player, BaseChallengeInstance? challenge);
|
||||
|
||||
public delegate void OnPlayerSyncLineupHandler(PlayerInstance player, LineupInfo? lineup);
|
||||
|
||||
|
||||
@@ -146,6 +146,7 @@ public class Connection(KcpConversation conversation, IPEndPoint remote) : Danhe
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error("An error occured ", e);
|
||||
|
||||
// get the packet rsp and set retCode to Retcode.RetFail
|
||||
var curPacket = LogMap.GetValueOrDefault(opcode);
|
||||
if (curPacket == null) return;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Challenge;
|
||||
using EggLink.DanhengServer.GameServer.Game.Challenge.Instances;
|
||||
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Challenge;
|
||||
using EggLink.DanhengServer.Kcp;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
|
||||
@@ -9,13 +10,13 @@ public class HandlerEnterChallengeNextPhaseCsReq : Handler
|
||||
{
|
||||
public override async Task OnHandle(Connection connection, byte[] header, byte[] data)
|
||||
{
|
||||
if (connection.Player!.ChallengeManager?.ChallengeInstance == null)
|
||||
if (connection.Player!.ChallengeManager?.ChallengeInstance is not ChallengeBossInstance boss)
|
||||
{
|
||||
await connection.SendPacket(new PacketEnterChallengeNextPhaseScRsp(Retcode.RetChallengeNotDoing));
|
||||
return;
|
||||
}
|
||||
|
||||
await connection.Player.ChallengeManager.ChallengeInstance.NextPhase();
|
||||
await boss.NextPhase();
|
||||
await connection.SendPacket(new PacketEnterChallengeNextPhaseScRsp(connection.Player));
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using EggLink.DanhengServer.GameServer.Game.Challenge;
|
||||
using EggLink.DanhengServer.GameServer.Game.Challenge.Instances;
|
||||
using EggLink.DanhengServer.Kcp;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
|
||||
@@ -6,20 +7,20 @@ namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.Challenge;
|
||||
|
||||
public class PacketChallengeBossPhaseSettleNotify : BasePacket
|
||||
{
|
||||
public PacketChallengeBossPhaseSettleNotify(ChallengeInstance challenge, BattleTargetList? targetLists = null) :
|
||||
public PacketChallengeBossPhaseSettleNotify(ChallengeBossInstance challenge, BattleTargetList? targetLists = null) :
|
||||
base(CmdIds
|
||||
.ChallengeBossPhaseSettleNotify)
|
||||
{
|
||||
var proto = new ChallengeBossPhaseSettleNotify
|
||||
{
|
||||
ChallengeId = (uint)challenge.Excel.ID,
|
||||
IsWin = challenge.IsWin(),
|
||||
ChallengeScore = (uint)challenge.ScoreStage1,
|
||||
ScoreTwo = (uint)challenge.ScoreStage2,
|
||||
Star = (uint)challenge.Stars,
|
||||
Phase = (uint)challenge.CurrentStage,
|
||||
ChallengeId = (uint)challenge.Config.ID,
|
||||
IsWin = challenge.IsWin,
|
||||
ChallengeScore = challenge.Data.Boss.ScoreStage1,
|
||||
ScoreTwo = challenge.Data.Boss.ScoreStage2,
|
||||
Star = challenge.Data.Boss.Stars,
|
||||
Phase = challenge.Data.Boss.CurrentStage,
|
||||
IsReward = true,
|
||||
IsSecondHalf = challenge.CurrentStage == challenge.Excel.StageNum,
|
||||
IsSecondHalf = challenge.Data.Boss.CurrentStage == challenge.Config.StageNum,
|
||||
PageType = 1
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using EggLink.DanhengServer.GameServer.Game.Challenge;
|
||||
using EggLink.DanhengServer.GameServer.Game.Challenge.Definitions;
|
||||
using EggLink.DanhengServer.Kcp;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
|
||||
@@ -6,15 +7,15 @@ namespace EggLink.DanhengServer.GameServer.Server.Packet.Send.Challenge;
|
||||
|
||||
public class PacketChallengeSettleNotify : BasePacket
|
||||
{
|
||||
public PacketChallengeSettleNotify(ChallengeInstance challenge) : base(CmdIds.ChallengeSettleNotify)
|
||||
public PacketChallengeSettleNotify(BaseLegacyChallengeInstance challenge) : base(CmdIds.ChallengeSettleNotify)
|
||||
{
|
||||
var proto = new ChallengeSettleNotify
|
||||
{
|
||||
ChallengeId = (uint)challenge.Excel.ID,
|
||||
IsWin = challenge.IsWin(),
|
||||
ChallengeScore = (uint)challenge.ScoreStage1,
|
||||
ScoreTwo = (uint)challenge.ScoreStage2,
|
||||
Star = (uint)challenge.Stars,
|
||||
ChallengeId = (uint)challenge.Config.ID,
|
||||
IsWin = challenge.IsWin,
|
||||
ChallengeScore = challenge.GetScore1(),
|
||||
ScoreTwo = challenge.GetScore2(),
|
||||
Star = challenge.GetStars(),
|
||||
Reward = new ItemList()
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using EggLink.DanhengServer.GameServer.Game.Player;
|
||||
using EggLink.DanhengServer.GameServer.Game.Challenge.Definitions;
|
||||
using EggLink.DanhengServer.GameServer.Game.Player;
|
||||
using EggLink.DanhengServer.Kcp;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
|
||||
@@ -10,13 +11,12 @@ public class PacketGetCurChallengeScRsp : BasePacket
|
||||
{
|
||||
var proto = new GetCurChallengeScRsp();
|
||||
|
||||
if (player.ChallengeManager!.ChallengeInstance != null)
|
||||
if (player.ChallengeManager!.ChallengeInstance is BaseLegacyChallengeInstance inst)
|
||||
{
|
||||
proto.CurChallenge = player.ChallengeManager.ChallengeInstance.ToProto();
|
||||
proto.CurChallenge = inst.ToProto();
|
||||
Task.Run(async () =>
|
||||
{
|
||||
await player.LineupManager!.SetCurLineup(player.ChallengeManager.ChallengeInstance
|
||||
.CurrentExtraLineup + 10);
|
||||
await player.LineupManager!.SetCurLineup(inst.GetCurrentExtraLineupType() + 10);
|
||||
}).Wait();
|
||||
var proto1 = player.LineupManager?.GetExtraLineup(ExtraLineupType.LineupChallenge)?.ToProto();
|
||||
if (proto1 != null)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using EggLink.DanhengServer.GameServer.Game.Player;
|
||||
using EggLink.DanhengServer.GameServer.Game.Challenge.Definitions;
|
||||
using EggLink.DanhengServer.GameServer.Game.Player;
|
||||
using EggLink.DanhengServer.Kcp;
|
||||
using EggLink.DanhengServer.Proto;
|
||||
|
||||
@@ -22,8 +23,12 @@ public class PacketStartChallengeScRsp : BasePacket
|
||||
|
||||
if (player.ChallengeManager!.ChallengeInstance != null)
|
||||
{
|
||||
proto.CurChallenge = player.ChallengeManager.ChallengeInstance.ToProto();
|
||||
proto.StageInfo = player.ChallengeManager.ChallengeInstance.ToStageInfo();
|
||||
if (player.ChallengeManager.ChallengeInstance is BaseLegacyChallengeInstance inst)
|
||||
{
|
||||
proto.CurChallenge = inst.ToProto();
|
||||
proto.StageInfo = inst.ToStageInfo();
|
||||
}
|
||||
|
||||
proto.LineupList.Add(player.LineupManager!.GetExtraLineup(ExtraLineupType.LineupChallenge)!.ToProto());
|
||||
proto.LineupList.Add(player.LineupManager!.GetExtraLineup(ExtraLineupType.LineupChallenge2)!.ToProto());
|
||||
if (sendScene) proto.Scene = player.SceneInstance!.ToProto();
|
||||
|
||||
@@ -23,7 +23,7 @@ public class PacketGetMissionDataScRsp : BasePacket
|
||||
Status = MissionStatus.MissionDoing
|
||||
});
|
||||
|
||||
foreach (var mission in GameData.SubMissionInfoData.Keys)
|
||||
foreach (var mission in GameData.SubMissionInfoData.Keys.Concat(GameData.SubMissionData.Keys))
|
||||
if (player.MissionManager!.GetSubMissionStatus(mission) == MissionPhaseEnum.Accept)
|
||||
proto.MissionList.Add(new Proto.Mission
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@ using EggLink.DanhengServer.Database.Avatar;
|
||||
using EggLink.DanhengServer.Enums;
|
||||
using EggLink.DanhengServer.Enums.Rogue;
|
||||
using EggLink.DanhengServer.GameServer.Command;
|
||||
using EggLink.DanhengServer.GameServer.Game.Challenge.Definitions;
|
||||
using EggLink.DanhengServer.GameServer.Plugin;
|
||||
using EggLink.DanhengServer.GameServer.Server;
|
||||
using EggLink.DanhengServer.GameServer.Server.Packet;
|
||||
@@ -280,13 +281,14 @@ public class EntryPoint
|
||||
_ => PlayerStatusEnum.Rogue
|
||||
};
|
||||
}
|
||||
else if ((con as Connection)!.Player!.ChallengeManager?.ChallengeInstance != null)
|
||||
else if ((con as Connection)!.Player!.ChallengeManager?.ChallengeInstance is
|
||||
BaseLegacyChallengeInstance inst)
|
||||
{
|
||||
status = PlayerStatusEnum.Challenge;
|
||||
if ((con as Connection)!.Player?.ChallengeManager?.ChallengeInstance?.Excel.StoryExcel != null)
|
||||
|
||||
if (inst.Config.StoryExcel != null)
|
||||
status = PlayerStatusEnum.ChallengeStory;
|
||||
else if ((con as Connection)!.Player?.ChallengeManager?.ChallengeInstance?.Excel.BossExcel !=
|
||||
null)
|
||||
else if (inst.Config.BossExcel != null)
|
||||
status = PlayerStatusEnum.ChallengeBoss;
|
||||
}
|
||||
else if ((con as Connection)!.Player!.RaidManager?.RaidData.CurRaidId != 0)
|
||||
|
||||
2920
ServerSideProto/ChallengeData.cs
Normal file
2920
ServerSideProto/ChallengeData.cs
Normal file
File diff suppressed because it is too large
Load Diff
78
ServerSideProto/ProtoFile/ChallengeData.proto
Normal file
78
ServerSideProto/ProtoFile/ChallengeData.proto
Normal file
@@ -0,0 +1,78 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option csharp_namespace = "EggLink.DanhengServer.Proto.ServerSide";
|
||||
|
||||
enum ChallengeLineupTypePb {
|
||||
None = 0;
|
||||
Challenge1 = 1;
|
||||
Challenge2 = 3;
|
||||
Challenge3 = 4;
|
||||
}
|
||||
|
||||
message Vector3Pb {
|
||||
int32 x = 1;
|
||||
int32 y = 2;
|
||||
int32 z = 3;
|
||||
}
|
||||
|
||||
message ChallengeMemoryDataPb {
|
||||
uint32 ChallengeMazeId = 1;
|
||||
Vector3Pb StartPos = 2;
|
||||
Vector3Pb StartRot = 3;
|
||||
uint32 CurrentStage = 4;
|
||||
uint32 CurStatus = 5;
|
||||
uint32 DeadAvatarNum = 6;
|
||||
uint32 SavedMp = 7;
|
||||
ChallengeLineupTypePb CurrentExtraLineup = 8;
|
||||
uint32 RoundsLeft = 9;
|
||||
uint32 Stars = 10;
|
||||
}
|
||||
|
||||
message ChallengeStoryDataPb {
|
||||
uint32 ChallengeMazeId = 1;
|
||||
Vector3Pb StartPos = 2;
|
||||
Vector3Pb StartRot = 3;
|
||||
uint32 CurrentStage = 4;
|
||||
uint32 CurStatus = 5;
|
||||
uint32 SavedMp = 6;
|
||||
ChallengeLineupTypePb CurrentExtraLineup = 7;
|
||||
uint32 Stars = 8;
|
||||
uint32 ScoreStage1 = 9;
|
||||
uint32 ScoreStage2 = 10;
|
||||
repeated uint32 Buffs = 11;
|
||||
}
|
||||
|
||||
message ChallengeBossDataPb {
|
||||
uint32 ChallengeMazeId = 1;
|
||||
Vector3Pb StartPos = 2;
|
||||
Vector3Pb StartRot = 3;
|
||||
uint32 CurrentStage = 4;
|
||||
uint32 CurStatus = 5;
|
||||
uint32 SavedMp = 6;
|
||||
ChallengeLineupTypePb CurrentExtraLineup = 7;
|
||||
uint32 Stars = 8;
|
||||
uint32 ScoreStage1 = 9;
|
||||
uint32 ScoreStage2 = 10;
|
||||
repeated uint32 Buffs = 11;
|
||||
}
|
||||
|
||||
message ChallengePeakDataPb {
|
||||
uint32 CurrentPeakLevelId = 2;
|
||||
repeated uint32 Buffs = 3;
|
||||
uint32 CurStatus = 4;
|
||||
Vector3Pb StartPos = 5;
|
||||
Vector3Pb StartRot = 6;
|
||||
uint32 SavedMp = 7;
|
||||
uint32 Stars = 8;
|
||||
ChallengeLineupTypePb CurrentExtraLineup = 9;
|
||||
bool IsHard = 10;
|
||||
}
|
||||
|
||||
message ChallengeDataPb {
|
||||
oneof challenge_type {
|
||||
ChallengeMemoryDataPb memory = 1;
|
||||
ChallengeStoryDataPb story = 2;
|
||||
ChallengeBossDataPb boss = 3;
|
||||
ChallengePeakDataPb peak = 4;
|
||||
}
|
||||
}
|
||||
4
ServerSideProto/RefreshProto.bat
Normal file
4
ServerSideProto/RefreshProto.bat
Normal file
@@ -0,0 +1,4 @@
|
||||
@echo off
|
||||
del /s /f .\*.cs
|
||||
cd ProtoFile
|
||||
protoc ".\*" --csharp_out=..\
|
||||
15
ServerSideProto/ServerSideProto.csproj
Normal file
15
ServerSideProto/ServerSideProto.csproj
Normal file
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>EggLink.DanhengServer.Proto.ServerSide</RootNamespace>
|
||||
<AssemblyName>DanhengSProto</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Google.Protobuf" Version="3.29.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user