Files
DanhengServer-OpenSource/GameServer/Game/RogueMagic/RogueMagicInstance.cs
2024-10-06 23:02:27 +08:00

497 lines
16 KiB
C#

using EggLink.DanhengServer.Data;
using EggLink.DanhengServer.Data.Excel;
using EggLink.DanhengServer.Enums.Rogue;
using EggLink.DanhengServer.Enums.RogueMagic;
using EggLink.DanhengServer.GameServer.Game.Battle;
using EggLink.DanhengServer.GameServer.Game.Player;
using EggLink.DanhengServer.GameServer.Game.Rogue;
using EggLink.DanhengServer.GameServer.Game.Rogue.Event;
using EggLink.DanhengServer.GameServer.Game.RogueMagic.Adventure;
using EggLink.DanhengServer.GameServer.Game.RogueMagic.MagicUnit;
using EggLink.DanhengServer.GameServer.Game.RogueMagic.Scene;
using EggLink.DanhengServer.GameServer.Game.RogueMagic.Scepter;
using EggLink.DanhengServer.GameServer.Game.Scene.Entity;
using EggLink.DanhengServer.GameServer.Server.Packet.Send.RogueCommon;
using EggLink.DanhengServer.GameServer.Server.Packet.Send.RogueMagic;
using EggLink.DanhengServer.Proto;
using EggLink.DanhengServer.Util;
namespace EggLink.DanhengServer.GameServer.Game.RogueMagic;
public class RogueMagicInstance : BaseRogueInstance
{
#region Initializer
public RogueMagicInstance(PlayerInstance player, int areaId, List<int> difficultyIds, int styleType) : base(player, RogueSubModeEnum.MagicRogue, 0)
{
// generate levels
AreaExcel = GameData.RogueMagicAreaData.GetValueOrDefault(areaId) ??
throw new Exception("Invalid area id"); // wont be null because of validation in RogueMagicManager
foreach (var index in Enumerable.Range(1, AreaExcel.LayerIDList.Count))
{
var layerId = AreaExcel.LayerIDList[index - 1];
var levelInstance = new RogueMagicLevelInstance(index, layerId, GameData.RogueMagicLayerIdRoomCountDict.GetValueOrDefault(layerId));
Levels.Add(levelInstance.LayerId, levelInstance);
}
CurLayerId = AreaExcel.LayerIDList[0];
EventManager = new RogueEventManager(player, this);
BaseRerollCount = 0;
foreach (var id in difficultyIds)
{
GameData.RogueMagicDifficultyCompData.TryGetValue(id, out var excel);
if (excel != null)
DifficultyCompExcels.Add(excel);
}
foreach (var id in AreaExcel.DifficultyIDList) // need to find a better way to get difficulty excels
{
GameData.RogueTournDifficultyData.TryGetValue(1000 + id, out var excel);
if (excel != null)
DifficultyExcels.Add(excel);
}
StyleType = (RogueMagicStyleTypeEnum)styleType;
var t = RollScepter(1, 1);
t.AsTask().Wait();
}
#endregion
#region Properties
public RogueMagicAreaExcel AreaExcel { get; set; }
public List<RogueMagicDifficultyCompExcel> DifficultyCompExcels { get; set; } = [];
public Dictionary<int, RogueMagicLevelInstance> Levels { get; set; } = [];
public List<RogueTournDifficultyExcel> DifficultyExcels { get; set; } = []; // for battle
public int CurLayerId { get; set; }
public RogueMagicLevelInstance? CurLevel => Levels.GetValueOrDefault(CurLayerId);
public RogueMagicLevelStatus LevelStatus { get; set; } = RogueMagicLevelStatus.Processing;
public RogueMagicStyleTypeEnum StyleType { get; set; }
public Dictionary<int, RogueScepterInstance> RogueScepters { get; set; } = [];
public Dictionary<int, RogueMagicUnitInstance> RogueMagicUnits { get; set; } = [];
public int CurMagicUnitUniqueId { get; set; } = 1;
public Dictionary<RogueMagicRoomTypeEnum, int> RoomTypeWeight { get; set; } = new()
{
{ RogueMagicRoomTypeEnum.Battle, 15 },
{ RogueMagicRoomTypeEnum.Wealth, 4 },
{ RogueMagicRoomTypeEnum.Shop, 4 },
{ RogueMagicRoomTypeEnum.Event, 7 },
{ RogueMagicRoomTypeEnum.Adventure, 60 },
{ RogueMagicRoomTypeEnum.Reward, 5 },
{ RogueMagicRoomTypeEnum.Elite, 1 }
};
#endregion
#region Scene
public async ValueTask EnterNextLayer(int roomIndex, RogueMagicRoomTypeEnum type)
{
var curIndex = CurLevel?.LevelIndex ?? 0;
if (curIndex == 3)
{
// last layer
return;
}
CurLayerId = AreaExcel.LayerIDList[curIndex];
await EnterRoom(1, type);
}
public async ValueTask EnterRoom(int roomIndex, RogueMagicRoomTypeEnum type)
{
if (CurLevel == null) return;
//if (CurLevel.CurRoomIndex == roomIndex)
// // same room
// return;
//if (CurLevel.CurRoomIndex + 1 != roomIndex) // only allow to enter next room
// // invalid room
// return;
if (CurLevel.CurRoom != null)
CurLevel.CurRoom.Status = RogueMagicRoomStatus.Finish;
// enter room
CurLevel.CurRoomIndex = roomIndex;
CurLevel.CurRoom?.Init(type);
// next room
var next = CurLevel.Rooms.Find(x => x.RoomIndex == roomIndex + 1);
if (next != null)
next.Status = RogueMagicRoomStatus.Inited;
// scene
var entrance = CurLevel.CurRoom?.Config?.EntranceId ?? 0;
var group = CurLevel.CurRoom?.Config?.AnchorGroup ?? 0;
var anchor = CurLevel.CurRoom?.Config?.AnchorId ?? 1;
// call event
EventManager?.OnNextRoom();
foreach (var miracle in RogueMiracles.Values) miracle.OnEnterNextRoom();
await Player.EnterMissionScene(entrance, group, anchor, false);
// sync
await Player.SendPacket(new PacketRogueMagicLevelInfoUpdateScNotify(this, [CurLevel], [next?.RoomIndex ?? 0,
(next?.RoomIndex ?? 0) - 1]));
}
public async ValueTask QuitRogue()
{
await Player.EnterMissionScene(801120102, 0, 0, false);
Player.RogueMagicManager!.RogueMagicInstance = null;
}
#endregion
#region Scepter
public async ValueTask RollScepter(int amount, int level)
{
var scepterExcels = GameData.RogueMagicScepterData.Values.Where(x => !RogueScepters.ContainsKey(x.ScepterID) && x.ScepterLevel == level).ToList();
for (var i = 0; i < amount; i++)
{
var menu = new RogueScepterSelectMenu(this);
menu.SetScepterPool(scepterExcels);
var action = menu.GetActionInstance();
RogueActions.Add(action.QueuePosition, action);
await UpdateMenu(action.QueuePosition);
}
}
public async ValueTask HandleScepterSelect(RogueMagicScepter selectScepter, int location)
{
if (RogueActions.Count == 0) return;
var action = RogueActions.First().Value;
if (action.RogueScepterSelectMenu != null)
{
var scepterExcel = action.RogueScepterSelectMenu.Scepters.Find(x => x.ScepterID == selectScepter.ScepterId);
if (scepterExcel != null) await AddScepter(scepterExcel);
RogueActions.Remove(action.QueuePosition);
}
await UpdateMenu();
await Player.SendPacket(
new PacketHandleRogueCommonPendingActionScRsp(action.QueuePosition, location, selectScepter: true));
}
public async ValueTask AddScepter(RogueMagicScepterExcel excel, RogueCommonActionResultSourceType source = RogueCommonActionResultSourceType.Select)
{
var scepter = new RogueScepterInstance(excel);
RogueScepters.Add(excel.ScepterID, scepter);
await Player.SendPacket(new PacketSyncRogueCommonActionResultScNotify(RogueSubMode, scepter.ToGetInfo(source)));
}
public async ValueTask DressScepter(int scepterId, int slot, int unitUniqueId)
{
var scepter = RogueScepters.GetValueOrDefault(scepterId);
if (scepter == null) return;
var unit = RogueMagicUnits.GetValueOrDefault(unitUniqueId);
if (unit == null) return;
// add
scepter.AddUnit(slot, unit);
await Player.SendPacket(new PacketSyncRogueCommonActionResultScNotify(RogueSubMode, scepter.ToDressInfo(RogueCommonActionResultSourceType.None)));
}
#endregion
#region MagicUnit
public async ValueTask RollMagicUnit(int amount, int level, List<RogueMagicUnitCategoryEnum> categories)
{
var unitExcels = GameData.RogueMagicUnitData.Values.Where(x => !RogueMagicUnits.ContainsKey(x.MagicUnitID) && x.MagicUnitLevel == level && categories.Contains(x.MagicUnitCategory) && x.MagicUnitType != RogueMagicMountTypeEnum.Active).ToList();
for (var i = 0; i < amount; i++)
{
var menu = new RogueMagicUnitSelectMenu(this);
menu.SetPool(unitExcels);
var action = menu.GetActionInstance();
RogueActions.Add(action.QueuePosition, action);
await UpdateMenu(action.QueuePosition);
}
}
public async ValueTask HandleMagicUnitSelect(RogueMagicGameUnit selectMagicUnit, int location)
{
if (RogueActions.Count == 0) return;
var action = RogueActions.First().Value;
if (action.RogueMagicUnitSelectMenu != null)
{
var unitExcel = action.RogueMagicUnitSelectMenu.MagicUnits.Find(x => x.MagicUnitID == selectMagicUnit.MagicUnitId);
if (unitExcel != null) await AddMagicUnit(unitExcel);
RogueActions.Remove(action.QueuePosition);
}
await UpdateMenu();
await Player.SendPacket(
new PacketHandleRogueCommonPendingActionScRsp(action.QueuePosition, location, selectMagicUnit: true));
}
public async ValueTask AddMagicUnit(RogueMagicUnitExcel excel, RogueCommonActionResultSourceType source = RogueCommonActionResultSourceType.Select)
{
var unit = new RogueMagicUnitInstance(excel)
{
UniqueId = CurMagicUnitUniqueId++
};
RogueMagicUnits.Add(unit.UniqueId, unit);
await Player.SendPacket(new PacketSyncRogueCommonActionResultScNotify(RogueSubMode, unit.ToGetInfo(source)));
}
#endregion
#region Adventure
public async ValueTask HandleStopWolfGunAdventure(List<int> targetIndex, RogueMagicAdventureInstance instance)
{
if (instance.WolfGunTargets.Count == 0) return;
var result = (from index in targetIndex
where index >= 0 && index < instance.WolfGunTargets.Count
select instance.WolfGunTargets[index]).ToList();
foreach (var target in result)
{
if (target.IsMoney)
{
// money
await GainMoney(target.TargetId, 2);
}
else if (target.IsMiracle)
{
// miracle
await AddMiracle(target.TargetId);
}
else if (target.IsRuanmei)
{
// ruanmei
foreach (var unused in Enumerable.Range(0, 10))
{
var unitExcels = GameData.RogueMagicUnitData.Values
.Where(x => !RogueMagicUnits.ContainsKey(x.MagicUnitID) && x.MagicUnitLevel == 1 && x.MagicUnitType != RogueMagicMountTypeEnum.Active).ToList();
var unit = unitExcels.RandomElement();
await AddMagicUnit(unit, RogueCommonActionResultSourceType.None);
}
}
}
}
#endregion
#region Handlers
public override void OnBattleStart(BattleInstance battle)
{
base.OnBattleStart(battle);
if (DifficultyExcels.Count > 0)
{
var excel = DifficultyExcels.RandomElement();
if (excel.LevelList.Count > 0)
battle.CustomLevel = excel.LevelList.RandomElement();
}
battle.MagicInfo = new BattleRogueMagicInfo
{
ModifierContent = new IGEFNGNCKOG
{
OJIBOBNAIKH = 5
},
DetailInfo = new BattleRogueMagicDetailInfo
{
ILAPCDFJHNH = new BattleRogueMagicItemInfo
{
BattleRoundCount = new BattleRogueMagicRoundCount(),
BattleScepterList = { RogueScepters.Select(x => x.Value.ToBattleScepterInfo()) }
}
}
};
}
public async ValueTask HitMonsterInAdventure(List<EntityMonster> monsters)
{
await ValueTask.CompletedTask;
}
public override async ValueTask OnBattleEnd(BattleInstance battle, PVEBattleResultCsReq req)
{
if (battle.BattleEndStatus != BattleEndStatus.BattleEndWin)
{
// quit
return;
}
if (CurLevel!.CurRoom!.RoomType == RogueMagicRoomTypeEnum.Boss)
{
await RollScepter(battle.Stages.Count, 1);
await RollMagicUnit(battle.Stages.Count, 1, [RogueMagicUnitCategoryEnum.Ultra]);
}
else
{
await RollMagicUnit(battle.Stages.Count, 1, [RogueMagicUnitCategoryEnum.Common]);
}
}
public override async ValueTask OnPropDestruct(EntityProp prop)
{
await base.OnPropDestruct(prop);
var inst = CurLevel?.CurRoom?.AdventureInstance;
if (inst != null && inst.Excel.AdventureType == RogueAdventureGameplayTypeEnum.RogueDestroyProp)
{
inst.Score++;
await Player.SendPacket(new PacketSyncRogueAdventureRoomInfoScNotify(inst));
}
}
#endregion
#region Serialization
public RogueMagicCurInfo ToProto()
{
var proto = new RogueMagicCurInfo
{
Lineup = ToLineupInfo(),
Level = ToLevelInfo(),
ItemValue = ToGameItemValueInfo(),
MiracleInfo = ToMiracleInfo(),
GameDifficultyInfo = ToDifficultyInfo(),
MagicItem = ToMagicItemInfo(),
BasicInfo = ToCurAreaInfo(),
JDMGJDBMHEJ = new LKJMDOAHGIN()
};
return proto;
}
public RogueTournCurAreaInfo ToCurAreaInfo()
{
var proto = new RogueTournCurAreaInfo
{
RogueSubMode = (uint)RogueSubMode,
SubAreaId = (uint)AreaExcel.AreaID,
PendingAction = RogueActions.Count > 0
? RogueActions.First().Value.ToProto()
: new RogueCommonPendingAction() // to serialize empty action
};
return proto;
}
public RogueMagicGameItemInfo ToMagicItemInfo()
{
var proto = new RogueMagicGameItemInfo
{
GameStyleType = (uint)StyleType
};
return proto;
}
public RogueMagicGameDifficultyInfo ToDifficultyInfo()
{
var proto = new RogueMagicGameDifficultyInfo
{
DifficultyIdList = { DifficultyCompExcels.Select(x => (uint)x.DifficultyCompID) }
};
return proto;
}
public RogueGameItemValue ToGameItemValueInfo()
{
return new RogueGameItemValue
{
VirtualItem = { { 31, (uint)CurMoney } }
};
}
public RogueTournLineupInfo ToLineupInfo()
{
return new RogueTournLineupInfo
{
AvatarIdList = { Player.LineupManager!.GetCurLineup()!.BaseAvatars!.Select(x => (uint)x.BaseAvatarId) },
RogueReviveCost = new ItemCostData
{
ItemList =
{
new ItemCost
{
PileItem = new PileItem
{
ItemId = 31,
ItemNum = (uint)CurReviveCost
}
}
}
}
};
}
public ChessRogueMiracleInfo ToMiracleInfo()
{
var proto = new ChessRogueMiracleInfo
{
ChessRogueMiracleInfo_ = new ChessRogueMiracle()
};
proto.ChessRogueMiracleInfo_.MiracleList.AddRange(RogueMiracles.Select(x => x.Value.ToGameMiracleProto())
.ToList());
return proto;
}
public RogueMagicGameLevelInfo ToLevelInfo()
{
var proto = new RogueMagicGameLevelInfo
{
Status = LevelStatus,
CurLevelIndex = (uint)(CurLevel?.CurRoomIndex ?? 0),
Reason = RogueMagicSettleReason.None
};
foreach (var levelInstance in Levels.Values) proto.LevelInfoList.Add(levelInstance.ToProto());
return proto;
}
public RogueMagicCurSceneInfo ToCurSceneInfo()
{
return new RogueMagicCurSceneInfo
{
Lineup = Player.LineupManager!.GetCurLineup()!.ToProto(),
Scene = Player.SceneInstance!.ToProto(),
//RotateInfo = new RogueMapRotateInfo
//{
// IsRotate = CurLevel?.CurRoom?.Config?.RotateInfo.IsRotate ?? false,
// BJPBAJECKFO = (uint)(CurLevel?.CurRoom?.Config?.RotateInfo.RotateNum ?? 0) // HDEHHKEMOCD
//}
RotateInfo = new RogueMapRotateInfo()
};
}
#endregion
}