Files
DanhengServer-OpenSource/GameServer/Game/Raid/RaidManager.cs

288 lines
11 KiB
C#

using EggLink.DanhengServer.Data;
using EggLink.DanhengServer.Database;
using EggLink.DanhengServer.Database.Scene;
using EggLink.DanhengServer.Enums.Mission;
using EggLink.DanhengServer.Enums.Scene;
using EggLink.DanhengServer.GameServer.Game.Player;
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Lineup;
using EggLink.DanhengServer.GameServer.Server.Packet.Send.Raid;
using EggLink.DanhengServer.Proto;
using RaidData = EggLink.DanhengServer.Database.Scene.RaidData;
namespace EggLink.DanhengServer.GameServer.Game.Raid;
public class RaidManager : BasePlayerManager
{
public RaidManager(PlayerInstance player) : base(player)
{
RaidData = DatabaseHelper.Instance!.GetInstanceOrCreateNew<RaidData>(player.Uid);
}
public RaidData RaidData { get; }
#region Information
public RaidStatus GetRaidStatus(int raidId, int worldLevel = 0)
{
if (!RaidData.RaidRecordDatas.TryGetValue(raidId, out var dict)) return RaidStatus.None;
if (!dict.TryGetValue(worldLevel, out var record)) return RaidStatus.None;
return record.Status;
}
#endregion
#region Player Handler
public async ValueTask OnLogin()
{
// try resume
if (RaidData.CurRaidId > 0 && RaidData.RaidRecordDatas.TryGetValue(RaidData.CurRaidId, out var value))
{
if (value.TryGetValue(RaidData.CurRaidWorldLevel, out var record))
{
await Player.SendPacket(new PacketRaidInfoNotify(record));
}
else
{
RaidData.CurRaidId = 0;
RaidData.CurRaidWorldLevel = 0;
await Player.SendPacket(new PacketRaidInfoNotify());
}
}
else
{
RaidData.CurRaidId = 0;
RaidData.CurRaidWorldLevel = 0;
await Player.SendPacket(new PacketRaidInfoNotify());
}
}
#endregion
#region Player Action
public async ValueTask<RaidRecord?> EnterRaid(int raidId, int worldLevel, List<int>? avatarList = null, bool enterSaved = false)
{
if (RaidData.CurRaidId != 0) return null;
GameData.RaidConfigData.TryGetValue(raidId * 100 + worldLevel, out var excel);
if (excel == null) return null; // not exist
RaidData.RaidRecordDatas.TryGetValue(raidId, out var dict);
dict ??= [];
if (dict.ContainsKey(worldLevel) && !enterSaved)
// clear old record
await ClearRaid(raidId, worldLevel);
dict.TryGetValue(worldLevel, out var record);
RaidData.CurRaidId = excel.RaidID;
RaidData.CurRaidWorldLevel = worldLevel;
if (record == null)
{
// first enter
var entranceId = 0;
var firstMission = excel.MainMissionIDList[0];
var subMissionId =
GameData.MainMissionData[firstMission].MissionInfo!.StartSubMissionList[0]; // get the first sub mission
var subMission = GameData.SubMissionInfoData[subMissionId];
entranceId =
int.Parse(subMission.SubMissionInfo!.LevelFloorID.ToString()
.Replace("00", "0")); // get entrance id ( need to find a better way to do it )
if (!GameData.MapEntranceData.ContainsKey(entranceId)) entranceId = subMission.SubMissionInfo!.LevelFloorID;
if (avatarList?.Count > 0)
{
Player.LineupManager!.SetExtraLineup(ExtraLineupType.LineupHeliobus, avatarList);
await Player.SendPacket(new PacketSyncLineupNotify(Player.LineupManager!.GetCurLineup()!));
}
else if (excel.TeamType == RaidTeamTypeEnum.TrialOnly)
{
// set lineup
List<int> list = [..excel.TrialAvatarList];
if (list.Count > 0)
{
if (Player.Data.CurrentGender == Gender.Man)
{
foreach (var avatar in excel.TrialAvatarList)
if (avatar > 10000) // else is Base Avatar
if (avatar.ToString().EndsWith("8002") ||
avatar.ToString().EndsWith("8004") ||
avatar.ToString().EndsWith("8006"))
list.Remove(avatar);
}
else
{
foreach (var avatar in excel.TrialAvatarList)
if (avatar > 10000) // else is Base Avatar
if (avatar.ToString().EndsWith("8001") ||
avatar.ToString().EndsWith("8003") ||
avatar.ToString().EndsWith("8005"))
list.Remove(avatar);
}
}
Player.LineupManager!.SetExtraLineup(ExtraLineupType.LineupHeliobus, list);
if (excel.LockCaptain) Player.LineupManager!.GetCurLineup()!.LeaderAvatarId = excel.LockCaptainAvatarID;
await Player.SendPacket(new PacketSyncLineupNotify(Player.LineupManager!.GetCurLineup()!));
}
else
{
// set cur lineup
var lineup = Player.LineupManager!.GetCurLineup()!;
Player.LineupManager!.SetExtraLineup(ExtraLineupType.LineupHeliobus,
lineup.BaseAvatars!.Select(x => x.SpecialAvatarId > 0 ? x.SpecialAvatarId / 10 : x.BaseAvatarId)
.ToList());
await Player.SendPacket(new PacketSyncLineupNotify(Player.LineupManager!.GetCurLineup()!));
}
var oldEntryId = Player.Data.EntryId;
var oldPos = Player.Data.Pos;
var oldRot = Player.Data.Rot;
await Player.MissionManager!.AcceptMainMission(firstMission);
await Player.EnterScene(entranceId, 0, false);
record = new RaidRecord
{
PlaneId = Player.Data.PlaneId,
FloorId = Player.Data.FloorId,
EntryId = entranceId,
Pos = Player.Data.Pos!,
Rot = Player.Data.Rot!,
Status = RaidStatus.Doing,
WorldLevel = worldLevel,
RaidId = raidId,
Lineup = Player.LineupManager!.GetCurLineup()!.BaseAvatars!,
OldEntryId = oldEntryId,
OldPos = oldPos!,
OldRot = oldRot!
};
if (RaidData.RaidRecordDatas.TryGetValue(raidId, out var value))
value[worldLevel] = record;
else
RaidData.RaidRecordDatas[raidId] = new Dictionary<int, RaidRecord> { { worldLevel, record } };
}
else
{
// just resume
record.Status = RaidStatus.Doing;
Player.LineupManager!.SetExtraLineup(ExtraLineupType.LineupHeliobus,
record.Lineup.Select(x => x.SpecialAvatarId > 0 ? x.SpecialAvatarId : x.BaseAvatarId).ToList());
await Player.LoadScene(record.PlaneId, record.FloorId, record.EntryId, record.Pos, record.Rot, false);
}
await Player.SendPacket(new PacketRaidInfoNotify(record));
return record;
}
public async ValueTask CheckIfLeaveRaid()
{
if (RaidData.CurRaidId == 0) return;
var record = RaidData.RaidRecordDatas[RaidData.CurRaidId][RaidData.CurRaidWorldLevel];
GameData.RaidConfigData.TryGetValue(RaidData.CurRaidId * 100 + record.WorldLevel, out var excel);
if (excel == null) return;
var leave = true;
foreach (var id in excel.MainMissionIDList)
if (Player.MissionManager!.GetMainMissionStatus(id) != MissionPhaseEnum.Finish)
leave = false;
if (leave)
{
await FinishRaid();
// finish
await Player.MissionManager!.HandleFinishType(MissionFinishTypeEnum.RaidFinishCnt);
}
}
public async ValueTask FinishRaid()
{
if (RaidData.CurRaidId == 0) return;
var record = RaidData.RaidRecordDatas[RaidData.CurRaidId][RaidData.CurRaidWorldLevel];
GameData.RaidConfigData.TryGetValue(RaidData.CurRaidId * 100 + record.WorldLevel, out var config);
if (config == null) return;
record.Status = RaidStatus.Finish;
await Player.SendPacket(new PacketRaidInfoNotify(record));
}
public async ValueTask LeaveRaid(bool save)
{
if (RaidData.CurRaidId == 0) return;
var record = RaidData.RaidRecordDatas[RaidData.CurRaidId][RaidData.CurRaidWorldLevel];
GameData.RaidConfigData.TryGetValue(RaidData.CurRaidId * 100 + record.WorldLevel, out var config);
if (config == null) return;
record.PlaneId = Player.Data.PlaneId;
record.FloorId = Player.Data.FloorId;
record.EntryId = Player.Data.EntryId;
record.Pos = Player.Data.Pos!;
record.Rot = Player.Data.Rot!;
if (Player.LineupManager!.GetCurLineup()!.IsExtraLineup())
{
Player.LineupManager!.SetExtraLineup(ExtraLineupType.LineupNone, []);
await Player.SendPacket(new PacketSyncLineupNotify(Player.LineupManager!.GetCurLineup()!));
}
if (record.Status == RaidStatus.Finish)
{
await Player.SendPacket(new PacketRaidInfoNotify());
if (config.FinishEntranceID > 0)
{
await Player.EnterScene(config.FinishEntranceID, 0, true);
}
else
{
await Player.EnterScene(record.OldEntryId, 0, true);
await Player.MoveTo(record.OldPos, record.OldRot);
}
}
else
{
await Player.EnterScene(record.OldEntryId, 0, true);
await Player.MoveTo(record.OldPos, record.OldRot);
// reset raid info
await Player.SendPacket(new PacketRaidInfoNotify());
if (!save) await ClearRaid(record.RaidId, record.WorldLevel);
}
RaidData.CurRaidId = 0;
RaidData.CurRaidWorldLevel = 0;
}
public async ValueTask ClearRaid(int raidId, int worldLevel)
{
if (!RaidData.RaidRecordDatas.TryGetValue(raidId, out var dict)) return;
if (!dict.TryGetValue(worldLevel, out var record)) return;
GameData.RaidConfigData.TryGetValue(raidId * 100 + worldLevel, out var config);
if (config == null) return;
config.MainMissionIDList.ForEach(async missionId =>
{
await Player.MissionManager!.RemoveMainMission(missionId);
});
dict.Remove(worldLevel);
if (dict.Count == 0) RaidData.RaidRecordDatas.Remove(raidId);
await Player.SendPacket(new PacketDelSaveRaidScNotify(raidId, worldLevel));
}
#endregion
}