mirror of
https://github.com/EggLinks/DanhengServer-OpenSource.git
synced 2026-01-02 12:16:03 +08:00
337 lines
12 KiB
C#
337 lines
12 KiB
C#
using EggLink.DanhengServer.Data;
|
|
using EggLink.DanhengServer.Data.Excel;
|
|
using EggLink.DanhengServer.Database.Friend;
|
|
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 },
|
|
BossGroupConst = 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);
|
|
|
|
// save
|
|
Player.ChallengeManager.SaveBattleRecord(this);
|
|
|
|
// add development
|
|
Player.FriendRecordData!.AddAndRemoveOld(new FriendDevelopmentInfoPb
|
|
{
|
|
DevelopmentType = DevelopmentType.DevelopmentBossChallenge,
|
|
Params = { { "ChallengeId", (uint)Config.ID } }
|
|
});
|
|
}
|
|
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!.SetExtraLineup((ExtraLineupType)GetCurrentExtraLineupType());
|
|
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
|
|
} |