implement miracles in rogue, fix some bugs in mission

This commit is contained in:
Somebody
2024-04-21 14:05:39 +08:00
parent 7bdea29545
commit 8f7a713316
28 changed files with 732 additions and 220 deletions

View File

@@ -59,6 +59,7 @@ namespace EggLink.DanhengServer.Configuration
public int StartTrailblazerLevel { get; set; } = 1;
public bool AutoUpgradeWorldLevel { get; set; } = true;
public bool EnableMission { get; set; } = true; // experimental
public bool AutoLightSection { get; set; } = true;
public string Language { get; set; } = "EN";
public List<string> DefaultPermissions { get; set; } = ["*"];
public ServerProfile ServerProfile { get; set; } = new ServerProfile();

View File

@@ -23,6 +23,8 @@ namespace EggLink.DanhengServer.Data.Custom
[JsonConverter(typeof(StringEnumConverter))]
public RogueMiracleEffectTypeEnum Type { get; set; }
public string DynamicKey { get; set; } = ""; // for arguments
public List<int> Params { get; set; } = [];
}
}

View File

@@ -106,7 +106,7 @@ namespace EggLink.DanhengServer.Data
public static Dictionary<int, List<int>> RogueMapGenData { get; set; } = [];
public static Dictionary<int, RogueMazeBuffExcel> RogueMazeBuffData { get; private set; } = [];
public static Dictionary<int, RogueMiracleExcel> RogueMiracleData { get; private set; } = [];
public static Dictionary<int, RogueMiracleEffectConfig> RogueMiracleEffectData { get; private set; } = [];
public static RogueMiracleEffectConfig RogueMiracleEffectData { get; set; } = new();
public static Dictionary<int, List<int>> RogueMiracleGroupData { get; set; } = [];
public static Dictionary<int, RogueMiracleDisplayExcel> RogueMiracleDisplayData { get; private set; } = [];
public static Dictionary<int, RogueMonsterExcel> RogueMonsterData { get; private set; } = [];

View File

@@ -24,6 +24,7 @@ namespace EggLink.DanhengServer.Data
GameData.BannersConfig = LoadCustomFile<BannersConfig>("Banner", "Banners") ?? new();
GameData.RogueMapGenData = LoadCustomFile<Dictionary<int, List<int>>>("Rogue Map", "RogueMapGen") ?? [];
GameData.RogueMiracleGroupData = LoadCustomFile<Dictionary<int, List<int>>>("Rogue Miracle Group", "RogueMiracleGroup") ?? [];
GameData.RogueMiracleEffectData = LoadCustomFile<RogueMiracleEffectConfig>("Rogue Miracle Effect", "RogueMiracleEffectGen") ?? new();
}
public static void LoadExcel()
@@ -295,6 +296,9 @@ namespace EggLink.DanhengServer.Data
} else if (customFile is BannersConfig c)
{
Logger.Info("Loaded " + c.Banners.Count + $" {filetype}s.");
} else if (customFile is RogueMiracleEffectConfig r)
{
Logger.Info("Loaded " + r.Miracles.Count + $" {filetype}s.");
}
else
{

View File

@@ -76,10 +76,33 @@ namespace EggLink.DanhengServer.Database.Avatar
{
Excel = excel;
SkillTree = [];
excel.DefaultSkillTree.ForEach(skill =>
if (AvatarId == 8001)
{
SkillTree.Add(skill.PointID, skill.Level);
});
//bool isMan = HeroId % 2 != 0;
//SkillTreeExtra.Add(isMan ? 8001: 8002, []);
//SkillTreeExtra.Add(isMan ? 8003 : 8004, []);
//var warriorExcel = GameData.AvatarConfigData[8001];
//var defenseExcel = GameData.AvatarConfigData[8003];
//warriorExcel.DefaultSkillTree.ForEach(skill =>
//{
// SkillTreeExtra[isMan ? 8001 : 8002].Add(skill.PointID, skill.Level);
//});
//defenseExcel.DefaultSkillTree.ForEach(skill =>
//{
// SkillTreeExtra[isMan ? 8003 : 8004].Add(skill.PointID, skill.Level);
//});
// create them in GetSkillTree
}
else
{
excel.DefaultSkillTree.ForEach(skill =>
{
SkillTree.Add(skill.PointID, skill.Level);
});
}
}
public bool HasTakenReward(int promotion)
@@ -104,7 +127,7 @@ namespace EggLink.DanhengServer.Database.Avatar
public int GetAvatarId()
{
return HeroId > 0 ? 8001 : AvatarId;
return HeroId > 0 ? HeroId : AvatarId;
}
public int GetSpecialAvatarId()
@@ -112,6 +135,26 @@ namespace EggLink.DanhengServer.Database.Avatar
return SpecialBaseAvatarId > 0 ? SpecialBaseAvatarId : GetAvatarId();
}
public Dictionary<int, int> GetSkillTree()
{
var value = SkillTree;
if (HeroId > 0)
{
if (!SkillTreeExtra.TryGetValue(HeroId, out value))
{
value = ([]);
// for old data
SkillTreeExtra[HeroId] = value;
var excel = GameData.AvatarConfigData[HeroId];
excel.DefaultSkillTree.ForEach(skill =>
{
SkillTreeExtra[HeroId].Add(skill.PointID, skill.Level);
});
}
}
return value;
}
public void SetCurHp(int value, bool isExtraLineup)
{
if (isExtraLineup)
@@ -238,7 +281,7 @@ namespace EggLink.DanhengServer.Database.Avatar
WorldLevel = (uint)(PlayerData?.WorldLevel ?? 0),
};
foreach (var skill in SkillTree)
foreach (var skill in GetSkillTree())
{
proto.SkilltreeList.Add(new AvatarSkillTree()
{
@@ -299,24 +342,33 @@ namespace EggLink.DanhengServer.Database.Avatar
return proto;
}
public PlayerHeroBasicTypeInfo ToHeroProto()
public List<PlayerHeroBasicTypeInfo> ToHeroProto()
{
var proto = new PlayerHeroBasicTypeInfo()
{
BasicType = (HeroBasicType)HeroId,
Rank = (uint)Rank,
};
var res = new List<PlayerHeroBasicTypeInfo>();
foreach (var skill in SkillTree)
GetSkillTree();
foreach (var hero in SkillTreeExtra)
{
proto.SkillTreeList.Add(new AvatarSkillTree()
var proto = new PlayerHeroBasicTypeInfo()
{
PointId = (uint)skill.Key,
Level = (uint)skill.Value
});
BasicType = (HeroBasicType)hero.Key,
Rank = (uint)Rank,
};
foreach (var skill in hero.Value)
{
proto.SkillTreeList.Add(new AvatarSkillTree()
{
PointId = (uint)skill.Key,
Level = (uint)skill.Value
});
}
res.Add(proto);
}
return proto;
return res;
}
}
}

View File

@@ -32,13 +32,13 @@ namespace EggLink.DanhengServer.Enums.Rogue
CostDurability = 19,
GetRogueBuffByAeon = 20,
ChangeItemNumByArg = 21,
RankupInBattle = 22,
ChangeItemRatioAndSetVar = 22,
// events
OnGetMiracle = 100,
OnStartBattle = 101,
OnEndBattle = 102,
OnBattleStart = 101,
OnBattleEnd = 102,
OnEnterNextRoom = 103,
OnDestroy = 104,
OnGainMoney = 105,
@@ -49,6 +49,9 @@ namespace EggLink.DanhengServer.Enums.Rogue
CurMoney = 200,
CurDestroyCount = 201,
AvatarWithLeastHP = 202,
CurBrokenMiracleCount = 202,
AvatarWithLeastHP = 203,
UseMoney = 204,
BuffTypeNum = 205,
}
}

View File

@@ -4,6 +4,7 @@ using EggLink.DanhengServer.Server.Packet.Send.Player;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;
@@ -25,6 +26,8 @@ namespace EggLink.DanhengServer.Command.Cmd
arg.SendMsg("Invalid arguments");
return;
}
var Player = arg.Target.Player!;
// change basic type
var avatarId = arg.GetInt(0);
var level = arg.GetInt(1);
if (level < 0 || level > 10)
@@ -37,10 +40,22 @@ namespace EggLink.DanhengServer.Command.Cmd
{
player.AvatarManager!.AvatarData.Avatars.ForEach(avatar =>
{
avatar.Excel?.SkillTree.ForEach(talent =>
if (avatar.HeroId > 0)
{
avatar.SkillTree![talent.PointID] = Math.Min(level, talent.MaxLevel);
});
avatar.SkillTreeExtra.TryGetValue(avatar.HeroId, out var hero);
hero ??= [];
var excel = GameData.AvatarConfigData[avatar.HeroId];
excel.SkillTree.ForEach(talent =>
{
hero[talent.PointID] = Math.Min(level, talent.MaxLevel);
});
} else
{
avatar.Excel?.SkillTree.ForEach(talent =>
{
avatar.SkillTree![talent.PointID] = Math.Min(level, talent.MaxLevel);
});
}
});
arg.SendMsg($"Player has set all avatars' talents to level {level}");

View File

@@ -8,7 +8,7 @@ using System.Threading.Tasks;
namespace EggLink.DanhengServer.Command.Cmd
{
[CommandInfo("rogue", "Manage the resource in rogue", "/rogue <money [money]>/<buff [id/-1]>/<miracle [id/-1]>/<enhance [id/-1]>")]
[CommandInfo("rogue", "Manage the resource in rogue", "/rogue <money [money]>/<buff [id/-1]>/<miracle [id]>/<enhance [id/-1]>")]
public class CommandRogue : ICommand
{
[CommandMethod("0 money")]
@@ -60,21 +60,10 @@ namespace EggLink.DanhengServer.Command.Cmd
return;
}
var id = arg.GetInt(0);
//if (id == -1)
//{
// var miracleList = new List<RogueMiracleExcel>();
// foreach (var miracle in GameData.RogueMiracleData.Values)
// {
// miracleList.Add(miracle);
// }
// arg.Target.Player!.RogueManager!.RogueInstance?.AddMiracleList(miracleList);
// arg.SendMsg("Player has gained all miracles");
//}
//else
//{
// arg.Target.Player!.RogueManager!.RogueInstance?.AddMiracle(id);
// arg.SendMsg($"Player has gained miracle {id}");
//}
arg.Target.Player!.RogueManager!.RogueInstance?.AddMiracle(id);
arg.SendMsg($"Player has gained miracle {id}");
}
[CommandMethod("0 enhance")]

View File

@@ -96,5 +96,23 @@ namespace EggLink.DanhengServer.Command.Cmd
}
arg.SendMsg("All props have been unlocked");
}
[CommandMethod("0 move")]
public void ChangeScene(CommandArg arg)
{
if (arg.Target == null)
{
arg.SendMsg("Player not found");
return;
}
if (arg.GetInt(0) == 0)
{
arg.SendMsg("Invalid scene ID");
return;
}
var player = arg.Target!.Player!;
player.EnterScene(arg.GetInt(0), 0, true);
}
}
}

View File

@@ -325,7 +325,7 @@ namespace EggLink.DanhengServer.Game.Lineup
DatabaseHelper.Instance?.UpdateInstance(LineupData);
if (sendPacket)
{
Player.SendPacket(new PacketSyncLineupNotify(GetCurLineup()!));
Player.SendPacket(new PacketSyncLineupNotify(GetCurLineup()!, Proto.SyncLineupReason.SyncReasonMpAddPropHit));
}
}

View File

@@ -0,0 +1,25 @@
using EggLink.DanhengServer.Data.Config;
using EggLink.DanhengServer.Enums;
using EggLink.DanhengServer.Game.Player;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EggLink.DanhengServer.Game.Mission.FinishType.Handler
{
[MissionFinishType(MissionFinishTypeEnum.EnterRaidScene)]
public class MissionHandlerEnterRaidScene : MissionFinishTypeHandler
{
public override void Init(PlayerInstance player, SubMissionInfo info, object? arg)
{
}
public override void HandleFinishType(PlayerInstance player, SubMissionInfo info, object? arg)
{
player.EnterScene(info.ParamInt2, 0, true);
player.MissionManager!.FinishSubMission(info.ID);
}
}
}

View File

@@ -50,6 +50,7 @@ namespace EggLink.DanhengServer.Game.Mission
public List<Proto.MissionSync?> AcceptMainMission(int missionId, bool sendPacket = true)
{
if (!ConfigManager.Config.ServerOption.EnableMission) return [];
if (Data.MissionInfo.ContainsKey(missionId)) return [];
// Get entry sub mission
GameData.MainMissionData.TryGetValue(missionId, out var mission);
@@ -71,11 +72,13 @@ namespace EggLink.DanhengServer.Game.Mission
public void AcceptSubMission(int missionId)
{
if (!ConfigManager.Config.ServerOption.EnableMission) return;
AcceptSubMission(missionId, true);
}
public Proto.MissionSync? AcceptSubMission(int missionId, bool sendPacket, bool doFinishTypeAction = true)
{
if (!ConfigManager.Config.ServerOption.EnableMission) return null;
GameData.SubMissionData.TryGetValue(missionId, out var subMission);
if (subMission == null) return null;
var mainMissionId = subMission.MainMissionID;
@@ -112,6 +115,7 @@ namespace EggLink.DanhengServer.Game.Mission
public void FinishMainMission(int missionId)
{
if (!ConfigManager.Config.ServerOption.EnableMission) return;
if (!Data.MainMissionInfo.TryGetValue(missionId, out var value)) return;
if (!GameData.MainMissionData.TryGetValue(missionId, out var mainMission)) return;
if (value != MissionPhaseEnum.Doing) return;
@@ -139,6 +143,7 @@ namespace EggLink.DanhengServer.Game.Mission
}
}
}
foreach (var nextMission in GameData.MainMissionData.Values)
{
if (!nextMission.IsEqual(Data)) continue;
@@ -158,10 +163,28 @@ namespace EggLink.DanhengServer.Game.Mission
HandleFinishType(MissionFinishTypeEnum.FinishMission);
DatabaseHelper.Instance?.UpdateInstance(Data);
GameData.RaidConfigData.TryGetValue(Player.CurRaidId, out var raidConfig);
if (raidConfig != null)
{
bool leave = true;
foreach (var id in raidConfig.MainMissionIDList)
{
if (GetMainMissionStatus(id) != MissionPhaseEnum.Finish)
{
leave = false;
}
}
if (leave)
{
Player.LeaveRaid();
}
}
}
public void FinishSubMission(int missionId)
{
if (!ConfigManager.Config.ServerOption.EnableMission) return;
GameData.SubMissionData.TryGetValue(missionId, out var subMission);
if (subMission == null) return;
var mainMissionId = subMission.MainMissionID;
@@ -231,6 +254,17 @@ namespace EggLink.DanhengServer.Game.Mission
}
DatabaseHelper.Instance?.UpdateInstance(Data);
// Hotfix for mission 101140201
if (missionId == 101140201)
{
// change basic type
Player.Data.CurBasicType += 2;
DatabaseHelper.Instance?.UpdateInstance(Player.Data);
Player.AvatarManager!.GetHero()!.HeroId += 2;
DatabaseHelper.Instance?.UpdateInstance(Player.AvatarManager!.AvatarData);
Player.SendPacket(new PacketPlayerSyncScNotify(Player.AvatarManager!.GetHero()!));
}
}
public void HandleFinishAction(Data.Config.MissionInfo info, int subMissionId)

View File

@@ -57,6 +57,8 @@ namespace EggLink.DanhengServer.Game.Player
public bool Initialized { get; set; } = false;
public bool IsNewPlayer { get; set; } = false;
public int NextBattleId { get; set; } = 0;
public int CurRaidId { get; set; } = 0;
public int OldEntryId { get; set; } = 0;
#endregion
@@ -82,6 +84,8 @@ namespace EggLink.DanhengServer.Game.Player
} else
{
LineupManager?.AddAvatarToCurTeam(8001);
Data.CurrentGender = Gender.Man;
Data.CurBasicType = 8001;
}
Initialized = true;
@@ -448,6 +452,10 @@ namespace EggLink.DanhengServer.Game.Player
{
EnterScene(801120102, 0, sendPacket);
return;
} else if (plane.PlaneType == PlaneTypeEnum.Raid && CurRaidId == 0)
{
EnterScene(OldEntryId > 0 ? OldEntryId : 2000101, 0, sendPacket);
return;
}
// TODO: Sanify check
@@ -548,6 +556,24 @@ namespace EggLink.DanhengServer.Game.Player
}
}
public void LeaveRaid()
{
if (CurRaidId == 0) return;
GameData.RaidConfigData.TryGetValue(CurRaidId, out var config);
if (config == null) return;
if (config.FinishEntranceID > 0)
{
EnterScene(config.FinishEntranceID, 0, true);
}
else
{
EnterScene(OldEntryId, 0, true);
}
CurRaidId = 0;
OldEntryId = 0;
}
#endregion
#region Serialization

View File

@@ -0,0 +1,42 @@
using EggLink.DanhengServer.Data;
using EggLink.DanhengServer.Enums.Rogue;
using EggLink.DanhengServer.Util;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EggLink.DanhengServer.Game.Rogue.Event.EffectHandler
{
[RogueEvent(DialogueEventTypeEnum.GetRogueMiracle)]
public class EventHandlerGetRogueMiracle : RogueEventEffectHandler
{
public override void Handle(RogueInstance rogue, RogueEventInstance? eventInstance, List<int> ParamList)
{
var miracleGroupId = ParamList[0];
GameData.RogueMiracleGroupData.TryGetValue(miracleGroupId, out var miracleGroup);
if (miracleGroup == null) return;
var list = new List<int>();
foreach (var id in miracleGroup)
{
if (!rogue.RogueMiracles.ContainsKey(id))
{
// Add the miracle to the list if the player doesn't have it
list.Add(id);
}
}
if (list.Count == 0) return; // If the player already has all the miracles in the group, return
for (int i = 0; i < ParamList[1]; i++)
{
var miracleId = list.RandomElement();
rogue.AddMiracle(miracleId);
list.Remove(i); // Remove the miracle from the list so it can't be added again
}
}
}
}

View File

@@ -0,0 +1,18 @@
using EggLink.DanhengServer.Enums.Rogue;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EggLink.DanhengServer.Game.Rogue.Event.EffectHandler
{
[RogueEvent(DialogueEventTypeEnum.TriggerRogueMiracleSelect)]
public class EventHandlerTriggerRogueMiracleSelect : RogueEventEffectHandler
{
public override void Handle(RogueInstance rogue, RogueEventInstance? eventInstance, List<int> ParamList)
{
rogue.RollMiracle(ParamList[2], ParamList[0]);
}
}
}

View File

@@ -1,5 +1,9 @@
using EggLink.DanhengServer.Game.Battle;
using EggLink.DanhengServer.Data;
using EggLink.DanhengServer.Data.Custom;
using EggLink.DanhengServer.Enums.Rogue;
using EggLink.DanhengServer.Game.Battle;
using EggLink.DanhengServer.Proto;
using EggLink.DanhengServer.Server.Packet.Send.Rogue;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -8,37 +12,118 @@ using System.Threading.Tasks;
namespace EggLink.DanhengServer.Game.Rogue.Miracle
{
public class RogueMiracleInstance(RogueInstance instance)
public class RogueMiracleInstance
{
public RogueInstance Instance { get; } = instance;
public RogueInstance Instance { get; }
public int MiracleId { get; private set; }
public int Durability { get; private set; }
public int UsedTimes { get; set; }
public int UseMoney { get; set; }
public bool IsDestroyed { get; set; } = false;
public RogueMiracleEffect? MiracleEffect { get; private set; }
public RogueMiracleInstance(RogueInstance instance, int miracleId)
{
Instance = instance;
MiracleId = miracleId;
GameData.RogueMiracleEffectData.Miracles.TryGetValue(MiracleId, out var effect);
MiracleEffect = effect;
if (MiracleEffect != null)
{
Durability = MiracleEffect.MaxDurability;
}
OnGetMiracle();
}
public void OnStartBattle(BattleInstance battle)
{
if (IsDestroyed) return;
if (MiracleEffect == null) return;
foreach (var effect in MiracleEffect.Effects.Values)
{
if (effect.Type == RogueMiracleEffectTypeEnum.OnBattleStart)
{
foreach (var param in effect.Params)
{
MiracleEffect.Effects.TryGetValue(param, out var target);
if (target == null) continue;
if (target.Type == RogueMiracleEffectTypeEnum.AddMazeBuff)
{
var buffId = target.Params[0];
var dynamicEffect = target.Params[1];
var buff = new MazeBuff(buffId, 1, -1)
{
WaveFlag = -1
};
if (dynamicEffect != 0)
{
MiracleEffect.Effects.TryGetValue(dynamicEffect, out var dynamic);
if (dynamic != null)
{
buff.DynamicValues.Add(dynamic.DynamicKey, CalculateArg(dynamic.Type));
}
}
battle.Buffs.Add(buff);
}
}
}
}
}
public void OnEndBattle(BattleInstance battle)
{
if (IsDestroyed) return;
if (MiracleEffect == null) return;
}
public void OnEnterNextRoom()
{
if (IsDestroyed) return;
if (MiracleEffect == null) return;
}
public void OnGetMiracle()
{
if (IsDestroyed) return;
if (MiracleEffect == null) return;
}
public void OnDestroy()
{
if (IsDestroyed) return;
if (MiracleEffect == null) return;
}
public int CalculateArg(RogueMiracleEffectTypeEnum type)
{
switch (type)
{
case RogueMiracleEffectTypeEnum.CurMoney:
return Instance.CurMoney;
case RogueMiracleEffectTypeEnum.CurDestroyCount:
return Instance.CurDestroyCount;
case RogueMiracleEffectTypeEnum.CurBrokenMiracleCount:
int count = 0;
foreach (var miracle in Instance.RogueMiracles.Values)
{
if (miracle.IsDestroyed)
{
count++;
}
}
return count;
case RogueMiracleEffectTypeEnum.UseMoney:
return UseMoney;
default:
return 0;
}
}
public void CostDurability(int value)
@@ -51,10 +136,13 @@ namespace EggLink.DanhengServer.Game.Rogue.Miracle
OnDestroy();
IsDestroyed = true;
}
// send packet
Instance.Player.SendPacket(new PacketSyncRogueCommonActionResultScNotify(Instance.RogueVersionId, ToGetResult(), RogueActionDisplayType.RogueCommonActionResultDisplayTypeSingle));
}
}
public RogueMiracle ToProto() // TODO: Implement
public RogueMiracle ToProto()
{
return new()
{
@@ -63,5 +151,30 @@ namespace EggLink.DanhengServer.Game.Rogue.Miracle
UsedTimes = (uint)UsedTimes
};
}
public GameRogueMiracle ToGameMiracleProto()
{
return new()
{
MiracleId = (uint)MiracleId,
Durability = (uint)Durability,
UsedTimes = (uint)UsedTimes
};
}
public RogueCommonActionResult ToGetResult()
{
return new()
{
Source = RogueActionSource.RogueCommonActionResultSourceTypeSelect,
RogueAction = new()
{
GetMiracleList = new()
{
MiracleInfo = ToGameMiracleProto()
},
}
};
}
}
}

View File

@@ -0,0 +1,55 @@
using EggLink.DanhengServer.Proto;
using EggLink.DanhengServer.Util;
using Microsoft.AspNetCore.Routing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EggLink.DanhengServer.Game.Rogue.Miracle
{
public class RogueMiracleSelectMenu(RogueInstance instance)
{
public List<int> Pools { get; set; } = [];
public List<uint> Results { get; set; } = [];
public void RollMiracle(List<int> pools)
{
Pools = pools;
Results.Clear();
for (int i = 0; i < 3; i++)
{
var id = Pools.RandomElement();
Results.Add((uint)id);
Pools.Remove(id);
if (Pools.Count == 0)
{
break;
}
}
}
public RogueActionInstance GetActionInstance()
{
instance.CurActionQueuePosition += 3;
return new()
{
QueuePosition = instance.CurActionQueuePosition,
RogueMiracleSelectMenu = this
};
}
public RogueMiracleSelectInfo ToProto()
{
var info = new RogueMiracleSelectInfo();
info.SelectMiracleList.AddRange(Results);
info.MiracleHandbookList.AddRange(Results);
return info;
}
}
}

View File

@@ -1,5 +1,6 @@
using EggLink.DanhengServer.Data.Excel;
using EggLink.DanhengServer.Game.Rogue.Buff;
using EggLink.DanhengServer.Game.Rogue.Miracle;
using EggLink.DanhengServer.Proto;
using EggLink.DanhengServer.Util;
using System;
@@ -14,7 +15,7 @@ namespace EggLink.DanhengServer.Game.Rogue
{
public int QueuePosition { get; set; } = 0;
public RogueBuffSelectMenu? RogueBuffSelectMenu { get; set; }
public RogueMiracleSelectInfo? RogueMiracleSelectInfo { get; set; }
public RogueMiracleSelectMenu? RogueMiracleSelectMenu { get; set; }
public RogueBonusSelectInfo? RogueBonusSelectInfo { get; set; }
public void SetBonus()
@@ -34,9 +35,9 @@ namespace EggLink.DanhengServer.Game.Rogue
action.BuffSelectInfo = RogueBuffSelectMenu.ToProto();
}
if (RogueMiracleSelectInfo != null)
if (RogueMiracleSelectMenu != null)
{
action.MiracleSelectInfo = RogueMiracleSelectInfo;
action.MiracleSelectInfo = RogueMiracleSelectMenu.ToProto();
}
if (RogueBonusSelectInfo != null)

View File

@@ -30,6 +30,7 @@ namespace EggLink.DanhengServer.Game.Rogue
public int BaseRerollFreeCount { get; set; } = 0;
public int CurReachedRoom { get; set; } = 0;
public int CurMoney { get; set; } = 100;
public int CurDestroyCount { get; set; } = 0;
public int AeonId { get; set; } = 0;
public bool IsWin { get; set; } = false;
public List<RogueBuffInstance> RogueBuffs { get; set; } = [];
@@ -86,13 +87,14 @@ namespace EggLink.DanhengServer.Game.Rogue
#endregion
#region Methods
#region Buffs
public void RollBuff(int amount)
{
if (CurRoom!.Excel.RogueRoomType == 6)
{
RollBuff(amount, 100003, 2);
RollBuff(amount, 100003, 2); // boss room
RollMiracle(1);
}
else
{
@@ -104,16 +106,16 @@ namespace EggLink.DanhengServer.Game.Rogue
{
var buffGroup = GameData.RogueBuffGroupData[buffGroupId];
var buffList = buffGroup.BuffList;
var actualBuffList = new List<RogueBuffExcel>();
foreach (var buff in buffList)
{
if (RogueBuffs.Exists(x => x.BuffExcel.MazeBuffID == buff.MazeBuffID))
if (!RogueBuffs.Exists(x => x.BuffExcel.MazeBuffID == buff.MazeBuffID))
{
buffList.Remove(buff); // remove existing buffs
actualBuffList.Add(buff);
}
}
if (buffList.Count == 0)
if (actualBuffList.Count == 0)
{
return; // no buffs to roll
}
@@ -125,7 +127,7 @@ namespace EggLink.DanhengServer.Game.Rogue
CurCount = i + 1,
TotalCount = amount,
};
menu.RollBuff(buffList);
menu.RollBuff(actualBuffList);
menu.HintId = buffHintType;
var action = menu.GetActionInstance();
RogueActions.Add(action.QueuePosition, action);
@@ -134,7 +136,7 @@ namespace EggLink.DanhengServer.Game.Rogue
UpdateMenu();
}
public RogueCommonActionResult? AddBuff(int buffId, int level = 1, RogueActionSource source = RogueActionSource.RogueCommonActionResultSourceTypeDialogue, RogueActionDisplayType displayType = RogueActionDisplayType.RogueCommonActionResultDisplayTypeSingle, bool updateMenu = true)
public RogueCommonActionResult? AddBuff(int buffId, int level = 1, RogueActionSource source = RogueActionSource.RogueCommonActionResultSourceTypeDialogue, RogueActionDisplayType displayType = RogueActionDisplayType.RogueCommonActionResultDisplayTypeSingle, bool updateMenu = true, bool notify = true)
{
if (RogueBuffs.Exists(x => x.BuffExcel.MazeBuffID == buffId))
{
@@ -152,7 +154,11 @@ namespace EggLink.DanhengServer.Game.Rogue
var buff = new RogueBuffInstance(buffId, level);
RogueBuffs.Add(buff);
var result = buff.ToResultProto(source);
Player.SendPacket(new PacketSyncRogueCommonActionResultScNotify(RogueVersionId, result, displayType));
if (notify)
{
Player.SendPacket(new PacketSyncRogueCommonActionResultScNotify(RogueVersionId, result, displayType));
}
if (updateMenu)
{
@@ -167,7 +173,7 @@ namespace EggLink.DanhengServer.Game.Rogue
List<RogueCommonActionResult> resultList = [];
foreach (var buff in excel)
{
var res = AddBuff(buff.MazeBuffID, buff.MazeBuffLevel, displayType: RogueActionDisplayType.RogueCommonActionResultDisplayTypeMulti, updateMenu: false);
var res = AddBuff(buff.MazeBuffID, buff.MazeBuffLevel, displayType: RogueActionDisplayType.RogueCommonActionResultDisplayTypeMulti, updateMenu: false, notify:false);
if (res != null)
{
resultList.Add(res);
@@ -199,6 +205,129 @@ namespace EggLink.DanhengServer.Game.Rogue
return RogueBuffs.FindAll(x => group.BuffList.Contains(x.BuffExcel));
}
public void HandleBuffSelect(int buffId)
{
if (RogueActions.Count == 0)
{
return;
}
var action = RogueActions.First().Value;
if (action.RogueBuffSelectMenu != null)
{
var buff = action.RogueBuffSelectMenu.Buffs.Find(x => x.MazeBuffID == buffId);
if (buff != null) // check if buff is in the list
{
if (RogueBuffs.Exists(x => x.BuffExcel.MazeBuffID == buffId)) // check if buff already exists
{
// enhance
EnhanceBuff(buffId, RogueActionSource.RogueCommonActionResultSourceTypeSelect);
}
else
{
var instance = new RogueBuffInstance(buff.MazeBuffID, buff.MazeBuffLevel);
RogueBuffs.Add(instance);
Player.SendPacket(new PacketSyncRogueCommonActionResultScNotify(RogueVersionId, instance.ToResultProto(RogueActionSource.RogueCommonActionResultSourceTypeSelect)));
}
}
RogueActions.Remove(action.QueuePosition);
if (action.RogueBuffSelectMenu.IsAeonBuff)
{
AeonBuffPending = false; // aeon buff added
}
}
UpdateMenu();
Player.SendPacket(new PacketHandleRogueCommonPendingActionScRsp(action.QueuePosition, selectBuff: true));
}
public void HandleRerollBuff()
{
if (RogueActions.Count == 0)
{
return;
}
var action = RogueActions.First().Value;
if (action.RogueBuffSelectMenu != null)
{
action.RogueBuffSelectMenu.RerollBuff(); // reroll
Player.SendPacket(new PacketHandleRogueCommonPendingActionScRsp(RogueVersionId, menu: action.RogueBuffSelectMenu));
}
}
public void AddAeonBuff()
{
if (AeonBuffPending) return;
if (CurAeonBuffCount + CurAeonEnhanceCount >= 4)
{
// max aeon buff count
return;
}
int curAeonBuffCount = 0; // current path buff count
int hintId = AeonId * 100 + 1;
var enhanceData = GameData.RogueAeonEnhanceData[AeonId];
var buffData = GameData.RogueAeonBuffData[AeonId];
foreach (var buff in RogueBuffs)
{
if (buff.BuffExcel.RogueBuffType == AeonExcel.RogueBuffType)
{
if (!buff.BuffExcel.IsAeonBuff)
{
curAeonBuffCount++;
}
else
{
hintId++; // next hint
enhanceData.Remove(buff.BuffExcel);
}
}
}
var needAeonBuffCount = (CurAeonBuffCount + CurAeonEnhanceCount) switch
{
0 => 3,
1 => 6,
2 => 10,
3 => 14,
_ => 100,
};
if (curAeonBuffCount >= needAeonBuffCount)
{
RogueBuffSelectMenu menu = new(this)
{
QueueAppend = 2,
HintId = hintId,
RollMaxCount = 0,
RollFreeCount = 0,
IsAeonBuff = true,
};
if (CurAeonBuffCount < 1)
{
CurAeonBuffCount++;
// add aeon buff
menu.RollBuff([buffData], 1);
}
else
{
CurAeonEnhanceCount++;
// add enhance buff
menu.RollBuff(enhanceData, enhanceData.Count);
}
var action = menu.GetActionInstance();
RogueActions.Add(action.QueuePosition, action);
AeonBuffPending = true;
UpdateMenu();
}
}
#endregion
#region Methods
public void UpdateMenu()
{
if (RogueActions.Count > 0)
@@ -262,8 +391,107 @@ namespace EggLink.DanhengServer.Game.Rogue
{
Status = RogueStatus.Finish;
Player.SendPacket(new PacketSyncRogueStatusScNotify(Status));
Player.SendPacket(new PacketSyncRogueFinishScNotify(ToFinishInfo()));
}
public void HandleBonusSelect(int bonusId)
{
if (RogueActions.Count == 0)
{
return;
}
var action = RogueActions.First().Value;
// TODO: handle bonus
GameData.RogueBonusData.TryGetValue(bonusId, out var bonus);
if (bonus != null)
{
TriggerEvent(null, bonus.BonusEvent);
}
RogueActions.Remove(action.QueuePosition);
UpdateMenu();
Player.SendPacket(new PacketHandleRogueCommonPendingActionScRsp(action.QueuePosition, selectBonus: true));
}
#endregion
#region Miracles
public void RollMiracle(int amount, int groupId = 10002)
{
GameData.RogueMiracleGroupData.TryGetValue(groupId, out var group);
if (group == null) return;
for (int i = 0; i < amount; i++)
{
var list = new List<int>();
foreach (var miracle in group)
{
if (RogueMiracles.ContainsKey(miracle))
{
continue;
}
list.Add(miracle);
}
if (list.Count == 0) return;
var menu = new RogueMiracleSelectMenu(this);
menu.RollMiracle(list);
var action = menu.GetActionInstance();
RogueActions.Add(action.QueuePosition, action);
}
UpdateMenu();
}
public void HandleMiracleSelect(uint miracleId)
{
if (RogueActions.Count == 0)
{
return;
}
var action = RogueActions.First().Value;
if (action.RogueMiracleSelectMenu != null)
{
var miracle = action.RogueMiracleSelectMenu.Results.Find(x => x == miracleId);
if (miracle != 0)
{
AddMiracle((int)miracle);
}
RogueActions.Remove(action.QueuePosition);
}
UpdateMenu();
Player.SendPacket(new PacketHandleRogueCommonPendingActionScRsp(action.QueuePosition, selectMiracle: true));
}
public void AddMiracle(int miracleId)
{
if (RogueMiracles.ContainsKey(miracleId))
{
return;
}
GameData.RogueMiracleData.TryGetValue(miracleId, out var excel);
if (excel == null) return;
var miracle = new RogueMiracleInstance(this, miracleId);
RogueMiracles.Add(miracleId, miracle);
Player.SendPacket(new PacketSyncRogueCommonActionResultScNotify(RogueVersionId, miracle.ToGetResult(), RogueActionDisplayType.RogueCommonActionResultDisplayTypeSingle));
}
#endregion
#region Money
public void CostMoney(int amount, RogueActionDisplayType displayType = RogueActionDisplayType.RogueCommonActionResultDisplayTypeNone)
{
CurMoney -= amount;
@@ -307,163 +535,15 @@ namespace EggLink.DanhengServer.Game.Rogue
}, display));
}
public void HandleBuffSelect(int buffId)
{
if (RogueActions.Count == 0)
{
return;
}
#endregion
var action = RogueActions.First().Value;
if (action.RogueBuffSelectMenu != null)
{
var buff = action.RogueBuffSelectMenu.Buffs.Find(x => x.MazeBuffID == buffId);
if (buff != null) // check if buff is in the list
{
if (RogueBuffs.Exists(x => x.BuffExcel.MazeBuffID == buffId)) // check if buff already exists
{
// enhance
EnhanceBuff(buffId, RogueActionSource.RogueCommonActionResultSourceTypeSelect);
} else
{
var instance = new RogueBuffInstance(buff.MazeBuffID, buff.MazeBuffLevel);
RogueBuffs.Add(instance);
Player.SendPacket(new PacketSyncRogueCommonActionResultScNotify(RogueVersionId, instance.ToResultProto(RogueActionSource.RogueCommonActionResultSourceTypeSelect)));
}
}
RogueActions.Remove(action.QueuePosition);
if (action.RogueBuffSelectMenu.IsAeonBuff)
{
AeonBuffPending = false; // aeon buff added
}
}
UpdateMenu();
Player.SendPacket(new PacketHandleRogueCommonPendingActionScRsp(action.QueuePosition, selectBuff: true));
}
public void HandleBonusSelect(int bonusId)
{
if (RogueActions.Count == 0)
{
return;
}
var action = RogueActions.First().Value;
// TODO: handle bonus
GameData.RogueBonusData.TryGetValue(bonusId, out var bonus);
if (bonus != null)
{
TriggerEvent(null, bonus.BonusEvent);
}
RogueActions.Remove(action.QueuePosition);
UpdateMenu();
Player.SendPacket(new PacketHandleRogueCommonPendingActionScRsp(action.QueuePosition, selectBonus: true));
}
public void HandleRerollBuff()
{
if (RogueActions.Count == 0)
{
return;
}
var action = RogueActions.First().Value;
if (action.RogueBuffSelectMenu != null)
{
action.RogueBuffSelectMenu.RerollBuff(); // reroll
Player.SendPacket(new PacketHandleRogueCommonPendingActionScRsp(RogueVersionId, menu:action.RogueBuffSelectMenu));
}
}
public void AddAeonBuff()
{
if (AeonBuffPending) return;
if (CurAeonBuffCount + CurAeonEnhanceCount >= 4)
{
// max aeon buff count
return;
}
int curAeonBuffCount = 0; // current path buff count
int needAeonBuffCount; // need path buff count
int hintId = AeonId * 100 + 1;
var enhanceData = GameData.RogueAeonEnhanceData[AeonId];
var buffData = GameData.RogueAeonBuffData[AeonId];
foreach (var buff in RogueBuffs)
{
if (buff.BuffExcel.RogueBuffType == AeonExcel.RogueBuffType)
{
if (!buff.BuffExcel.IsAeonBuff)
{
curAeonBuffCount++;
} else
{
hintId++; // next hint
enhanceData.Remove(buff.BuffExcel);
}
}
}
switch (CurAeonBuffCount + CurAeonEnhanceCount)
{
case 0:
needAeonBuffCount = 3;
break;
case 1:
needAeonBuffCount = 6;
break;
case 2:
needAeonBuffCount = 10;
break;
case 3:
needAeonBuffCount = 14;
break;
default:
needAeonBuffCount = 100;
break;
}
if (curAeonBuffCount >= needAeonBuffCount)
{
RogueBuffSelectMenu menu = new(this)
{
QueueAppend = 2,
HintId = hintId,
RollMaxCount = 0,
RollFreeCount = 0,
IsAeonBuff = true,
};
if (CurAeonBuffCount < 1)
{
CurAeonBuffCount++;
// add aeon buff
menu.RollBuff([buffData], 1);
} else
{
CurAeonEnhanceCount++;
// add enhance buff
menu.RollBuff(enhanceData, enhanceData.Count);
}
var action = menu.GetActionInstance();
RogueActions.Add(action.QueuePosition, action);
AeonBuffPending = true;
UpdateMenu();
}
}
#region Events
public void TriggerEvent(RogueEventInstance? rogueEvent, int eventId)
{
EventManager.TriggerEvent(rogueEvent, eventId);
}
#endregion
#region Events
public RogueEventInstance GenerateEvent(RogueNpc npc)
{
RogueNPCDialogueExcel? dialogue;
@@ -570,6 +650,8 @@ namespace EggLink.DanhengServer.Game.Rogue
// gain money
GainMoney(Random.Shared.Next(20, 60));
}
CurDestroyCount++;
}
#endregion

View File

@@ -273,12 +273,21 @@ namespace EggLink.DanhengServer.Game.Scene
}
// unlock section
Player.SceneData!.UnlockSectionIdList.TryGetValue(FloorId, out var unlockSectionList);
if (unlockSectionList != null)
if (!ConfigManager.Config.ServerOption.AutoLightSection)
{
foreach (var sectionId in unlockSectionList)
Player.SceneData!.UnlockSectionIdList.TryGetValue(FloorId, out var unlockSectionList);
if (unlockSectionList != null)
{
sceneInfo.LightenSectionList.Add((uint)sectionId);
foreach (var sectionId in unlockSectionList)
{
sceneInfo.LightenSectionList.Add((uint)sectionId);
}
}
} else
{
for (uint i = 1; i <= 100; i++)
{
sceneInfo.LightenSectionList.Add(i);
}
}

View File

@@ -28,6 +28,11 @@ namespace EggLink.DanhengServer.Server.Packet.Recv.Rogue
{
rogue.HandleBonusSelect((int)req.BonusSelectResult.BonusId);
}
if (req.MiracleSelectResult != null)
{
rogue.HandleMiracleSelect(req.MiracleSelectResult.MiracleId);
}
}
}
}

View File

@@ -18,6 +18,8 @@ namespace EggLink.DanhengServer.Server.Packet.Recv.Scene
GameData.RaidConfigData.TryGetValue((int)(req.RaidId * 100 + req.WorldLevel), out var raidConfig);
if (raidConfig != null)
{
player.OldEntryId = player.Data.EntryId;
player.CurRaidId = raidConfig.RaidID;
raidConfig.MainMissionIDList.ForEach(missionId =>
{
player.MissionManager!.AcceptMainMission(missionId);

View File

@@ -1,4 +1,5 @@
using EggLink.DanhengServer.Server.Packet.Send.Tutorial;
using EggLink.DanhengServer.Util;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -12,7 +13,8 @@ namespace EggLink.DanhengServer.Server.Packet.Recv.Tutorial
{
public override void OnHandle(Connection connection, byte[] header, byte[] data)
{
connection.SendPacket(new PacketGetTutorialScRsp(connection.Player!));
if (ConfigManager.Config.ServerOption.EnableMission) // If missions are enabled
connection.SendPacket(new PacketGetTutorialScRsp(connection.Player!));
}
}
}

View File

@@ -1,4 +1,5 @@
using EggLink.DanhengServer.Server.Packet.Send.Tutorial;
using EggLink.DanhengServer.Util;
namespace EggLink.DanhengServer.Server.Packet.Recv.Tutorial
{
@@ -7,7 +8,8 @@ namespace EggLink.DanhengServer.Server.Packet.Recv.Tutorial
{
public override void OnHandle(Connection connection, byte[] header, byte[] data)
{
connection.SendPacket(new PacketGetTutorialGuideScRsp(connection.Player!)); // some bug
if (ConfigManager.Config.ServerOption.EnableMission) // If missions are enabled
connection.SendPacket(new PacketGetTutorialGuideScRsp(connection.Player!)); // some bug
}
}
}

View File

@@ -14,7 +14,7 @@ namespace EggLink.DanhengServer.Server.Packet.Send.Avatar
};
if (player.AvatarManager?.GetHero() != null)
proto.BasicTypeInfoList.Add(player.AvatarManager?.GetHero()?.ToHeroProto());
proto.BasicTypeInfoList.AddRange(player.AvatarManager?.GetHero()?.ToHeroProto());
SetData(proto);
}

View File

@@ -4,11 +4,12 @@ namespace EggLink.DanhengServer.Server.Packet.Send.Lineup
{
public class PacketSyncLineupNotify : BasePacket
{
public PacketSyncLineupNotify(Database.Lineup.LineupInfo info) : base(CmdIds.SyncLineupNotify)
public PacketSyncLineupNotify(Database.Lineup.LineupInfo info, SyncLineupReason reason = SyncLineupReason.SyncReasonNone) : base(CmdIds.SyncLineupNotify)
{
var proto = new SyncLineupNotify()
{
Lineup = info.ToProto(),
ReasonList = { reason }
};
SetData(proto);

View File

@@ -20,6 +20,8 @@ namespace EggLink.DanhengServer.Server.Packet.Send.Rogue
return;
}
proto.BuffEnhanceInfo = player.RogueManager.RogueInstance.ToEnhanceInfo();
SetData(proto);
}
}
}

View File

@@ -3,6 +3,7 @@ using EggLink.DanhengServer.Data.Config;
using EggLink.DanhengServer.Enums.Scene;
using EggLink.DanhengServer.Game.Player;
using EggLink.DanhengServer.Proto;
using EggLink.DanhengServer.Util;
namespace EggLink.DanhengServer.Server.Packet.Send.Scene
{
@@ -74,11 +75,19 @@ namespace EggLink.DanhengServer.Server.Packet.Send.Scene
mazeMap.MazePropList.Add(mazeProp);
}
player.SceneData!.UnlockSectionIdList.TryGetValue(mapData.FloorID, out var sections);
foreach (var section in sections ?? [])
if (!ConfigManager.Config.ServerOption.AutoLightSection)
{
mazeMap.LightenSectionList.Add((uint)section);
player.SceneData!.UnlockSectionIdList.TryGetValue(mapData.FloorID, out var sections);
foreach (var section in sections ?? [])
{
mazeMap.LightenSectionList.Add((uint)section);
}
} else
{
for (uint i = 0; i < 100; i++)
mazeMap.LightenSectionList.Add(i);
}
rsp.SceneMapInfo.Add(mazeMap);
}
SetData(rsp);