From 3075e30f2f0ac99b1e4bc961bd3eadabfa619359 Mon Sep 17 00:00:00 2001 From: HuLiNap Date: Tue, 29 Apr 2025 22:34:15 +0700 Subject: [PATCH] added useless stuffs in added useless stuffs in added useless stuffs in added useless stuffs in added useless stuffs in added useless stuffs in added useless stuffs in added useless stuffs in added useless stuffs in added useless stuffs in added useless stuffs in added useless stuffs in added useless stuffs in added useless stuffs in added useless stuffs in --- config.json | 172 +++++- gameserver/src/commands/sync.zig | 73 ++- gameserver/src/handlers.zig | 9 +- gameserver/src/manager/battle_mgr.zig | 746 +++++++++-------------- gameserver/src/manager/challenge_mgr.zig | 158 +++++ gameserver/src/manager/lineup_mgr.zig | 68 ++- gameserver/src/manager/scene_mgr.zig | 23 + gameserver/src/services/avatar.zig | 7 + gameserver/src/services/battle.zig | 50 +- gameserver/src/services/challenge.zig | 282 ++++----- gameserver/src/services/config.zig | 21 +- gameserver/src/services/item.zig | 6 +- gameserver/src/services/lineup.zig | 16 +- gameserver/src/services/scene.zig | 22 + hotfix.json | 10 +- 15 files changed, 974 insertions(+), 689 deletions(-) create mode 100644 gameserver/src/manager/challenge_mgr.zig diff --git a/config.json b/config.json index ea46987..fba2ccc 100644 --- a/config.json +++ b/config.json @@ -2,15 +2,15 @@ "avatar_config": [ { "name": "Acheron", - "id": 1308, + "id": 1304, "hp": 100, "sp": 0, "level": 80, "promotion": 6, - "rank": 2, + "rank": 6, "lightcone": { - "id": 23024, - "rank": 1, + "id": 23000, + "rank": 2, "level": 80, "promotion": 6 }, @@ -26,15 +26,15 @@ }, { "name": "Hyacine", - "id": 1409, + "id": 1313, "hp": 100, "sp": 50, "level": 80, "promotion": 6, - "rank": 0, + "rank": 6, "lightcone": { - "id": 23042, - "rank": 1, + "id": 23001, + "rank": 2, "level": 80, "promotion": 6 }, @@ -55,10 +55,10 @@ "sp": 50, "level": 80, "promotion": 6, - "rank": 0, + "rank": 6, "lightcone": { - "id": 23043, - "rank": 1, + "id": 23004, + "rank": 2, "level": 80, "promotion": 6 }, @@ -79,10 +79,10 @@ "sp": 0, "level": 80, "promotion": 6, - "rank": 0, + "rank": 6, "lightcone": { - "id": 23038, - "rank": 1, + "id": 23006, + "rank": 2, "level": 80, "promotion": 6 }, @@ -95,6 +95,150 @@ "63196,15,3,4,7:2:1,8:4:7,9:2:1,10:1:1" ], "use_technique": true + }, + { + "name": "Castorice", + "id": 1407, + "hp": 100, + "sp": 50, + "level": 80, + "promotion": 6, + "rank": 6, + "lightcone": { + "id": 23015, + "rank": 2, + "level": 80, + "promotion": 6 + }, + "relics": [ + "61241,15,1,4,8:2:2,6:2:2,4:2:2,2:3:3", + "61242,15,1,4,3:3:3,9:2:2,7:2:2,8:2:2", + "61243,15,5,4,6:2:2,4:2:2,12:1:1,2:4:4", + "61244,15,1,4,5:4:4,8:2:2,1:2:2,6:1:1", + "63195,15,1,4,9:2:2,2:1:1,8:1:1,11:5:5", + "63196,15,3,4,7:1:1,1:3:3,11:4:4,2:1:1" + ], + "use_technique": true + }, + { + "name": "Castorice", + "id": 8008, + "hp": 100, + "sp": 50, + "level": 80, + "promotion": 6, + "rank": 6, + "lightcone": { + "id": 23009, + "rank": 2, + "level": 80, + "promotion": 6 + }, + "relics": [ + "61241,15,1,4,8:2:2,6:2:2,4:2:2,2:3:3", + "61242,15,1,4,3:3:3,9:2:2,7:2:2,8:2:2", + "61243,15,5,4,6:2:2,4:2:2,12:1:1,2:4:4", + "61244,15,1,4,5:4:4,8:2:2,1:2:2,6:1:1", + "63195,15,1,4,9:2:2,2:1:1,8:1:1,11:5:5", + "63196,15,3,4,7:1:1,1:3:3,11:4:4,2:1:1" + ], + "use_technique": true + }, + { + "name": "Castorice", + "id": 1001, + "hp": 100, + "sp": 50, + "level": 80, + "promotion": 6, + "rank": 6, + "lightcone": { + "id": 23012, + "rank": 2, + "level": 80, + "promotion": 6 + }, + "relics": [ + "61241,15,1,4,8:2:2,6:2:2,4:2:2,2:3:3", + "61242,15,1,4,3:3:3,9:2:2,7:2:2,8:2:2", + "61243,15,5,4,6:2:2,4:2:2,12:1:1,2:4:4", + "61244,15,1,4,5:4:4,8:2:2,1:2:2,6:1:1", + "63195,15,1,4,9:2:2,2:1:1,8:1:1,11:5:5", + "63196,15,3,4,7:1:1,1:3:3,11:4:4,2:1:1" + ], + "use_technique": true + }, + { + "name": "The Herta", + "id": 1401, + "hp": 100, + "sp": 50, + "level": 80, + "promotion": 6, + "rank": 6, + "lightcone": { + "id": 23013, + "rank": 2, + "level": 80, + "promotion": 6 + }, + "relics": [ + "61221,15,1,4,12:2:2,3:1:1,10:4:4,5:2:2", + "61222,15,1,4,3:4:4,4:1:1,10:3:3,8:1:1", + "61223,15,5,4,3:3:3,2:3:3,12:1:1,8:2:2", + "61224,15,4,4,6:3:3,2:1:1,12:3:3,8:2:2", + "63145,15,6,4,11:2:2,5:1:1,9:2:2,8:4:4", + "63146,15,4,4,6:3:3,10:1:1,12:4:4,11:1:1" + ], + "use_technique": true + }, + { + "name": "Aglaea", + "id": 1402, + "hp": 100, + "sp": 50, + "level": 80, + "promotion": 6, + "rank": 6, + "lightcone": { + "id": 23033, + "rank": 2, + "level": 80, + "promotion": 6 + }, + "relics": [ + "61221,15,1,4,12:2:2,3:1:1,10:4:4,5:2:2", + "61222,15,1,4,3:4:4,4:1:1,10:3:3,8:1:1", + "61223,15,5,4,3:3:3,2:3:3,12:1:1,8:2:2", + "61224,15,4,4,6:3:3,2:1:1,12:3:3,8:2:2", + "63145,15,6,4,11:2:2,5:1:1,9:2:2,8:4:4", + "63146,15,4,4,6:3:3,10:1:1,12:4:4,11:1:1" + ], + "use_technique": true + }, + { + "name": "Yunli", + "id": 1221, + "hp": 100, + "sp": 50, + "level": 80, + "promotion": 6, + "rank": 6, + "lightcone": { + "id": 23018, + "rank": 2, + "level": 80, + "promotion": 6 + }, + "relics": [ + "61221,15,1,4,12:2:2,3:1:1,10:4:4,5:2:2", + "61222,15,1,4,3:4:4,4:1:1,10:3:3,8:1:1", + "61223,15,5,4,3:3:3,2:3:3,12:1:1,8:2:2", + "61224,15,4,4,6:3:3,2:1:1,12:3:3,8:2:2", + "63145,15,6,4,11:2:2,5:1:1,9:2:2,8:4:4", + "63146,15,4,4,6:3:3,10:1:1,12:4:4,11:1:1" + ], + "use_technique": true } ], "battle_config": { diff --git a/gameserver/src/commands/sync.zig b/gameserver/src/commands/sync.zig index 093973e..fb564fe 100644 --- a/gameserver/src/commands/sync.zig +++ b/gameserver/src/commands/sync.zig @@ -21,13 +21,16 @@ fn isInList(id: u32, list: []const u32) bool { return false; } +pub var max_avatar_list: u32 = 0; + fn syncItems(session: *Session, allocator: Allocator, equip_avatar: bool) !void { + resetGlobalUidGens(); var sync = protocol.PlayerSyncScNotify.init(allocator); const config = try Config.loadGameConfig(allocator, "config.json"); for (config.avatar_config.items) |avatarConf| { const equip_avatar_id: u32 = if (equip_avatar) avatarConf.id else 0; const lc = protocol.Equipment{ - .unique_id = if (equip_avatar) nextGlobalId(.Default) else nextGlobalId(.Undress), + .unique_id = if (equip_avatar) nextGlobalId() else nextGlobalId(), .tid = avatarConf.lightcone.id, .is_protected = true, .level = avatarConf.lightcone.level, @@ -40,7 +43,7 @@ fn syncItems(session: *Session, allocator: Allocator, equip_avatar: bool) !void var r = protocol.Relic{ .tid = input.id, .main_affix_id = input.main_affix_id, - .unique_id = if (equip_avatar) nextGlobalId(.Default) else nextGlobalId(.Undress), + .unique_id = if (equip_avatar) nextGlobalId() else nextGlobalId(), .exp = 0, .equip_avatar_id = equip_avatar_id, .is_protected = true, @@ -58,12 +61,15 @@ fn syncItems(session: *Session, allocator: Allocator, equip_avatar: bool) !void try session.send(CmdID.CmdPlayerSyncScNotify, sync); } -pub fn onSyncEquipment(session: *Session, _: []const u8, allocator: Allocator) Error!void { +pub fn onUndressEquipment(session: *Session, _: []const u8, allocator: Allocator) Error!void { try syncItems(session, allocator, false); +} +pub fn onSyncEquipment(session: *Session, _: []const u8, allocator: Allocator) Error!void { try syncItems(session, allocator, true); } pub fn onSyncAvatar(session: *Session, _: []const u8, allocator: Allocator) Error!void { + resetGlobalUidGens(); var sync = protocol.PlayerSyncScNotify.init(allocator); const config = try Config.loadGameConfig(allocator, "config.json"); var char = protocol.AvatarSync.init(allocator); @@ -103,15 +109,13 @@ pub fn onSyncAvatar(session: *Session, _: []const u8, allocator: Allocator) Erro avatar.level = avatarConf.level; avatar.promotion = avatarConf.promotion; avatar.rank = avatarConf.rank; - avatar.equipment_unique_id = nextGlobalId(.Avatar); - std.debug.print("LIGHTCONE SYNC {}\n", .{avatar.equipment_unique_id}); + avatar.equipment_unique_id = nextGlobalId(); avatar.equip_relic_list = ArrayList(protocol.EquipRelic).init(allocator); for (0..6) |i| { try avatar.equip_relic_list.append(.{ - .relic_unique_id = nextGlobalId(.Avatar), // uid + .relic_unique_id = nextGlobalId(), // uid .type = @intCast(i), // slot }); - std.debug.print("EQUIPING SYNC {}:{}:{}\n", .{ avatarConf.id, avatar.equip_relic_list.items[i].relic_unique_id, i }); } var talentLevel: u32 = 0; const skill_list: []const u32 = if (isInList(avatar.base_avatar_id, &Data.Rem)) &Data.skills else &Data.skills_old; @@ -128,13 +132,13 @@ pub fn onSyncAvatar(session: *Session, _: []const u8, allocator: Allocator) Erro try char.avatar_list.append(avatar); const avatarType: protocol.MultiPathAvatarType = @enumFromInt(avatarConf.id); if (@intFromEnum(avatarType) > 1) { - std.debug.print("setting avatar type: {}\n", .{avatarConf.id}); try session.send(CmdID.CmdSetAvatarPathScRsp, protocol.SetAvatarPathScRsp{ .retcode = 0, .avatar_id = avatarType, }); } } + max_avatar_list = @intCast(config.avatar_config.items.len); sync.avatar_sync = char; try session.send(CmdID.CmdPlayerSyncScNotify, sync); } @@ -142,7 +146,7 @@ pub fn onSyncAvatar(session: *Session, _: []const u8, allocator: Allocator) Erro pub fn onSyncMultiPath(session: *Session, _: []const u8, allocator: Allocator) Error!void { var sync = protocol.PlayerSyncScNotify.init(allocator); const config = try Config.loadGameConfig(allocator, "config.json"); - const currentAvatarId = getCurrentGlobalId(.Avatar); + const currentAvatarId = getCurrentGlobalId(); const GeneratorType = UidGen(); const avatar_ids = [_][]const u32{ &[_]u32{ 8001, 8002 }, @@ -173,7 +177,7 @@ pub fn onSyncMultiPath(session: *Session, _: []const u8, allocator: Allocator) E for (avatar_ids[i]) |id| { if (avatar.id == id) { multis[i].rank = avatar.rank; - indexes[i] = 5 - counts[i]; + indexes[i] = max_avatar_list + 1 - counts[i]; } } } @@ -215,30 +219,25 @@ pub fn onSyncMultiPath(session: *Session, _: []const u8, allocator: Allocator) E try session.send(CmdID.CmdPlayerSyncScNotify, sync); } -pub const UidType = enum { Default, Undress, Avatar }; -pub var global_uid_gen = UidGenerator.init(.Default, 28); -pub var global_uid_gen_undress = UidGenerator.init(.Undress, 0); -pub var global_uid_gen_avatar = UidGenerator.init(.Avatar, 28); -pub fn nextGlobalId(uid_type: UidType) u32 { - return switch (uid_type) { - .Default => global_uid_gen.nextId(), - .Undress => global_uid_gen_undress.nextId(), - .Avatar => global_uid_gen_avatar.nextId(), - }; +pub var global_uid_gen: UidGenerator = undefined; + +fn resetGlobalUidGens() void { + global_uid_gen = UidGenerator.init(0); } -pub fn getCurrentGlobalId(uid_type: UidType) u32 { - return switch (uid_type) { - .Default => global_uid_gen.getCurrentId(), - .Undress => global_uid_gen_undress.getCurrentId(), - .Avatar => global_uid_gen_avatar.getCurrentId(), - }; + +pub fn nextGlobalId() u32 { + return global_uid_gen.nextId(); } + +pub fn getCurrentGlobalId() u32 { + return global_uid_gen.getCurrentId(); +} + pub const UidGenerator = struct { current_id: u32, - uid_type: UidType, - pub fn init(uid_type: UidType, start_id: u32) UidGenerator { - return UidGenerator{ .uid_type = uid_type, .current_id = start_id }; + pub fn init(start_id: u32) UidGenerator { + return UidGenerator{ .current_id = start_id }; } pub fn nextId(self: *UidGenerator) u32 { @@ -250,22 +249,30 @@ pub const UidGenerator = struct { return self.current_id; } }; + pub fn UidGen() type { return struct { current_id: u32, const Self = @This(); - pub fn init(initial_id: u32) Self { - return Self{ .current_id = initial_id }; + + pub fn init(start_id: u32) Self { + return Self{ .current_id = start_id }; } + pub fn nextId(self: *Self) u32 { - self.current_id +%= 1; + self.current_id += 1; + return self.current_id; + } + + pub fn getCurrentId(self: *const Self) u32 { return self.current_id; } }; } pub fn onGenerateAndSync(session: *Session, placeholder: []const u8, allocator: Allocator) Error!void { try commandhandler.sendMessage(session, "Sync items with config\n", allocator); - try onSyncEquipment(session, placeholder, allocator); try onSyncAvatar(session, placeholder, allocator); + try syncItems(session, allocator, false); + try syncItems(session, allocator, true); try onSyncMultiPath(session, placeholder, allocator); } diff --git a/gameserver/src/handlers.zig b/gameserver/src/handlers.zig index 0b53a14..8b5a805 100644 --- a/gameserver/src/handlers.zig +++ b/gameserver/src/handlers.zig @@ -42,6 +42,7 @@ const HandlerList = [_]struct { CmdID, Action }{ .{ CmdID.CmdDressAvatarSkinCsReq, avatar.onDressAvatarSkin }, .{ CmdID.CmdGetBigDataAllRecommendCsReq, avatar.onGetBigDataAll }, .{ CmdID.CmdGetBigDataRecommendCsReq, avatar.onGetBigData }, + .{ CmdID.CmdGetPreAvatarGrowthInfoCsReq, avatar.onGetPreAvatarGrowthInfo }, //bag .{ CmdID.CmdGetBagCsReq, item.onGetBag }, .{ CmdID.CmdUseItemCsReq, item.onUseItem }, @@ -57,6 +58,8 @@ const HandlerList = [_]struct { CmdID, Action }{ .{ CmdID.CmdQuickStartCocoonStageCsReq, battle.onQuickStartCocoonStage }, .{ CmdID.CmdQuickStartFarmElementCsReq, battle.onQuickStartFarmElement }, .{ CmdID.CmdStartBattleCollegeCsReq, battle.onStartBattleCollege }, + .{ CmdID.CmdGetCurBattleInfoCsReq, battle.onGetCurBattleInfo }, + .{ CmdID.CmdSyncClientResVersionCsReq, battle.onSyncClientResVersion }, //gacha .{ CmdID.CmdGetGachaInfoCsReq, gacha.onGetGachaInfo }, .{ CmdID.CmdBuyGoodsCsReq, gacha.onBuyGoods }, @@ -104,6 +107,7 @@ const HandlerList = [_]struct { CmdID, Action }{ .{ CmdID.CmdChangePropTimelineInfoCsReq, scene.onChangePropTimeline }, .{ CmdID.CmdDeactivateFarmElementCsReq, scene.onDeactivateFarmElement }, .{ CmdID.CmdSetGroupCustomSaveDataCsReq, scene.onSetGroupCustomSaveData }, + .{ CmdID.CmdGetEnteredSceneCsReq, scene.onGetEnteredScene }, //events .{ CmdID.CmdGetActivityScheduleConfigCsReq, events.onGetActivity }, .{ CmdID.CmdUpdateServerPrefsDataCsReq, events.onUpdateServerPrefsData }, @@ -112,6 +116,7 @@ const HandlerList = [_]struct { CmdID, Action }{ .{ CmdID.CmdGetChallengeGroupStatisticsCsReq, challenge.onGetChallengeGroupStatistics }, .{ CmdID.CmdStartChallengeCsReq, challenge.onStartChallenge }, .{ CmdID.CmdLeaveChallengeCsReq, challenge.onLeaveChallenge }, + .{ CmdID.CmdGetCurChallengeCsReq, challenge.onGetCurChallengeScRsp }, }; const DummyCmdList = [_]struct { CmdID, CmdID }{ @@ -123,21 +128,18 @@ const DummyCmdList = [_]struct { CmdID, CmdID }{ .{ CmdID.CmdGetAllServerPrefsDataCsReq, CmdID.CmdGetAllServerPrefsDataScRsp }, .{ CmdID.CmdGetMissionDataCsReq, CmdID.CmdGetMissionDataScRsp }, .{ CmdID.CmdGetQuestDataCsReq, CmdID.CmdGetQuestDataScRsp }, - .{ CmdID.CmdGetCurChallengeCsReq, CmdID.CmdGetCurChallengeScRsp }, .{ CmdID.CmdGetRogueCommonDialogueDataCsReq, CmdID.CmdGetRogueCommonDialogueDataScRsp }, .{ CmdID.CmdGetRogueInfoCsReq, CmdID.CmdGetRogueInfoScRsp }, .{ CmdID.CmdGetRogueHandbookDataCsReq, CmdID.CmdGetRogueHandbookDataScRsp }, .{ CmdID.CmdGetRogueEndlessActivityDataCsReq, CmdID.CmdGetRogueEndlessActivityDataScRsp }, .{ CmdID.CmdChessRogueQueryCsReq, CmdID.CmdChessRogueQueryScRsp }, .{ CmdID.CmdRogueTournQueryCsReq, CmdID.CmdRogueTournQueryScRsp }, - .{ CmdID.CmdSyncClientResVersionCsReq, CmdID.CmdSyncClientResVersionScRsp }, .{ CmdID.CmdDailyFirstMeetPamCsReq, CmdID.CmdDailyFirstMeetPamScRsp }, .{ CmdID.CmdGetBattleCollegeDataCsReq, CmdID.CmdGetBattleCollegeDataScRsp }, .{ CmdID.CmdGetNpcStatusCsReq, CmdID.CmdGetNpcStatusScRsp }, .{ CmdID.CmdGetSecretKeyInfoCsReq, CmdID.CmdGetSecretKeyInfoScRsp }, .{ CmdID.CmdGetHeartDialInfoCsReq, CmdID.CmdGetHeartDialInfoScRsp }, .{ CmdID.CmdGetVideoVersionKeyCsReq, CmdID.CmdGetVideoVersionKeyScRsp }, - .{ CmdID.CmdGetCurBattleInfoCsReq, CmdID.CmdGetCurBattleInfoScRsp }, .{ CmdID.CmdHeliobusActivityDataCsReq, CmdID.CmdHeliobusActivityDataScRsp }, .{ CmdID.CmdGetAetherDivideInfoCsReq, CmdID.CmdGetAetherDivideInfoScRsp }, .{ CmdID.CmdGetMapRotationDataCsReq, CmdID.CmdGetMapRotationDataScRsp }, @@ -162,7 +164,6 @@ const DummyCmdList = [_]struct { CmdID, CmdID }{ .{ CmdID.CmdRogueArcadeGetInfoCsReq, CmdID.CmdRogueArcadeGetInfoScRsp }, .{ CmdID.CmdGetMissionMessageInfoCsReq, CmdID.CmdGetMissionMessageInfoScRsp }, .{ CmdID.CmdTrainPartyGetDataCsReq, CmdID.CmdTrainPartyGetDataScRsp }, - .{ CmdID.CmdGetEnteredSceneCsReq, CmdID.CmdGetEnteredSceneScRsp }, .{ CmdID.CmdQueryProductInfoCsReq, CmdID.CmdQueryProductInfoScRsp }, .{ CmdID.CmdGetPamSkinDataCsReq, CmdID.CmdGetPamSkinDataScRsp }, .{ CmdID.CmdGetRogueScoreRewardInfoCsReq, CmdID.CmdGetRogueScoreRewardInfoScRsp }, diff --git a/gameserver/src/manager/battle_mgr.zig b/gameserver/src/manager/battle_mgr.zig index 8ebc07b..208e6df 100644 --- a/gameserver/src/manager/battle_mgr.zig +++ b/gameserver/src/manager/battle_mgr.zig @@ -10,7 +10,9 @@ const ArrayList = std.ArrayList; const Allocator = std.mem.Allocator; const CmdID = protocol.CmdID; -// function to check the list if true +pub var selectedAvatarID = [_]u32{ 1304, 1313, 1406, 1004 }; + +// Function to check if an ID is in a list fn isInList(id: u32, list: []const u32) bool { for (list) |item| { if (item == id) { @@ -19,446 +21,7 @@ fn isInList(id: u32, list: []const u32) bool { } return false; } -pub const BattleManager = struct { - allocator: std.mem.Allocator, - pub fn init(allocator: std.mem.Allocator) BattleManager { - return BattleManager{ .allocator = allocator }; - } - pub fn createBattle(self: *BattleManager) !protocol.SceneBattleInfo { - const config = try Config.loadGameConfig(self.allocator, "config.json"); - - var battle = protocol.SceneBattleInfo.init(self.allocator); - const BattleBuff = protocol.BattleBuff; - - // Avatar handler - for (config.avatar_config.items, 0..) |avatarConf, idx| { - var avatar = protocol.BattleAvatar.init(self.allocator); - avatar.id = avatarConf.id; - avatar.hp = avatarConf.hp * 100; - avatar.sp_bar = .{ .sp_cur = avatarConf.sp * 100, .sp_max = 10000 }; - avatar.level = avatarConf.level; - avatar.rank = avatarConf.rank; - avatar.promotion = avatarConf.promotion; - avatar.avatar_type = .AVATAR_FORMAL_TYPE; - - // Relics - for (avatarConf.relics.items) |relic| { - const r = try relicCoder(self.allocator, relic.id, relic.level, relic.main_affix_id, relic.stat1, relic.cnt1, relic.step1, relic.stat2, relic.cnt2, relic.step2, relic.stat3, relic.cnt3, relic.step3, relic.stat4, relic.cnt4, relic.step4); - try avatar.relic_list.append(r); - } - - // Lightcone (LC) - const lc = protocol.BattleEquipment{ - .id = avatarConf.lightcone.id, - .rank = avatarConf.lightcone.rank, - .level = avatarConf.lightcone.level, - .promotion = avatarConf.lightcone.promotion, - }; - try avatar.equipment_list.append(lc); - //max trace - var talentLevel: u32 = 0; - const skill_list: []const u32 = if (isInList(avatar.id, &Data.Rem)) &Data.skills else &Data.skills_old; - for (skill_list) |elem| { - talentLevel = switch (elem) { - 1 => 6, - 2...4 => 10, - 301, 302 => if (isInList(avatar.id, &Data.Rem)) 6 else 1, - else => 1, - }; - const talent = protocol.AvatarSkillTree{ .point_id = avatar.id * 1000 + elem, .level = talentLevel }; - try avatar.skilltree_list.append(talent); - } - // enable technique - if (avatarConf.use_technique) { - var targetIndexList = ArrayList(u32).init(self.allocator); - try targetIndexList.append(0); - //Add new ID when modifying for new patch - - var buffedAvatarId = avatar.id; - if (avatar.id == 8004) { - buffedAvatarId = 8003; - } else if (avatar.id == 8006) { - buffedAvatarId = 8005; - } else if (avatar.id == 8008) { - buffedAvatarId = 8007; - } - - for (Data.buffs_unlocked) |buffId| { - const idPrefix = buffId / 100; - if (idPrefix == buffedAvatarId) { - var buff = BattleBuff{ - .id = buffId, - .level = 1, - .owner_index = @intCast(idx), - .wave_flag = 1, - .target_index_list = targetIndexList, - .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(self.allocator), - }; - - try buff.dynamic_values.append(.{ .key = .{ .Const = "SkillIndex" }, .value = 0 }); - try battle.buff_list.append(buff); - } - } - - if (isInList(buffedAvatarId, &Data.IgnoreToughness)) { - var buff_tough = BattleBuff{ - .id = 1000119, //for is_ignore toughness - .level = 1, - .owner_index = @intCast(idx), - .wave_flag = 1, - .target_index_list = targetIndexList, - .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(self.allocator), - }; - try buff_tough.dynamic_values.append(.{ .key = .{ .Const = "SkillIndex" }, .value = 0 }); - try battle.buff_list.append(buff_tough); - } - - if (buffedAvatarId == 1224) { - var buff_march = protocol.BattleBuff{ - .id = 122401, //for hunt march 7th tech - .level = 1, - .owner_index = @intCast(idx), - .wave_flag = 1, - .target_index_list = targetIndexList, - .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(self.allocator), - }; - - try buff_march.dynamic_values.appendSlice(&[_]protocol.BattleBuff.DynamicValuesEntry{ - .{ .key = .{ .Const = "#ADF_1" }, .value = 3 }, - .{ .key = .{ .Const = "#ADF_2" }, .value = 3 }, - }); - try battle.buff_list.append(buff_march); - } - - if (buffedAvatarId == 1310) { - var buff_firefly = BattleBuff{ - .id = 1000112, //for firefly tech - .level = 1, - .owner_index = @intCast(idx), - .wave_flag = 1, - .target_index_list = targetIndexList, - .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(self.allocator), - }; - try buff_firefly.dynamic_values.append(.{ .key = .{ .Const = "SkillIndex" }, .value = 0 }); - try battle.buff_list.append(buff_firefly); - } - - if (buffedAvatarId == 8007) { - var buff_rmc = BattleBuff{ - .id = 800701, //for rmc tech - .level = 1, - .owner_index = @intCast(idx), - .wave_flag = 1, - .target_index_list = targetIndexList, - .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(self.allocator), - }; - try buff_rmc.dynamic_values.append(.{ .key = .{ .Const = "SkillIndex" }, .value = 0 }); - try battle.buff_list.append(buff_rmc); - } - } - - try battle.pve_avatar_list.append(avatar); - } - - // Basic battle info - battle.battle_id = config.battle_config.battle_id; - battle.stage_id = config.battle_config.stage_id; - battle.logic_random_seed = @intCast(@mod(std.time.timestamp(), 0xFFFFFFFF)); - battle.rounds_limit = config.battle_config.cycle_count; - battle.monster_wave_length = @intCast(config.battle_config.monster_wave.items.len); - battle.world_level = 6; - - // Monster handler - for (config.battle_config.monster_wave.items) |wave| { - var monster_wave = protocol.SceneMonsterWave.init(self.allocator); - monster_wave.wave_param = protocol.SceneMonsterWaveParam{ .level = config.battle_config.monster_level }; - for (wave.items) |mob_id| { - try monster_wave.monster_list.append(.{ .monster_id = mob_id }); - } - try battle.monster_wave_list.append(monster_wave); - } - // stage blessings - for (config.battle_config.blessings.items) |blessing| { - var targetIndexList = ArrayList(u32).init(self.allocator); - try targetIndexList.append(0); - var buff = protocol.BattleBuff{ - .id = blessing, - .level = 1, - .owner_index = 0xffffffff, - .wave_flag = 0xffffffff, - .target_index_list = targetIndexList, - .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(self.allocator), - }; - try buff.dynamic_values.append(.{ .key = .{ .Const = "SkillIndex" }, .value = 0 }); - try battle.buff_list.append(buff); - } - if (isInList(1407, Data.AllAvatars)) { //support Castorice - var targetIndexList = ArrayList(u32).init(self.allocator); - try targetIndexList.append(0); - var mazebuff_data = BattleBuff{ - .id = 140703, - .level = 1, - .owner_index = 1, - .wave_flag = @intCast(config.battle_config.monster_wave.items.len), - .target_index_list = targetIndexList, - .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(self.allocator), - }; - try mazebuff_data.dynamic_values.append(.{ .key = .{ .Const = "SkillIndex" }, .value = 0 }); - try battle.buff_list.append(mazebuff_data); - } - - // PF/AS scoring - const BattleTargetInfoEntry = protocol.SceneBattleInfo.BattleTargetInfoEntry; - battle.battle_target_info = ArrayList(BattleTargetInfoEntry).init(self.allocator); - - // target hardcode - var pfTargetHead = protocol.BattleTargetList{ .battle_target_list = ArrayList(protocol.BattleTarget).init(self.allocator) }; - try pfTargetHead.battle_target_list.append(.{ .id = 10002, .progress = 0, .total_progress = 0 }); - var pfTargetTail = protocol.BattleTargetList{ .battle_target_list = ArrayList(protocol.BattleTarget).init(self.allocator) }; - try pfTargetTail.battle_target_list.append(.{ .id = 2001, .progress = 0, .total_progress = 0 }); - try pfTargetTail.battle_target_list.append(.{ .id = 2002, .progress = 0, .total_progress = 0 }); - var asTargetHead = protocol.BattleTargetList{ .battle_target_list = ArrayList(protocol.BattleTarget).init(self.allocator) }; - try asTargetHead.battle_target_list.append(.{ .id = 90005, .progress = 0, .total_progress = 0 }); - - switch (battle.stage_id) { - // PF - 30019000...30019100, 30021000...30021100, 30301000...30319000 => { - try battle.battle_target_info.append(.{ .key = 1, .value = pfTargetHead }); - // fill blank target - for (2..5) |i| { - try battle.battle_target_info.append(.{ .key = @intCast(i) }); - } - try battle.battle_target_info.append(.{ .key = 5, .value = pfTargetTail }); - }, - // AS - 420100...420300 => { - try battle.battle_target_info.append(.{ .key = 1, .value = asTargetHead }); - }, - else => {}, - } - return battle; - } -}; -pub const ChallegeStageManager = struct { - allocator: std.mem.Allocator, - pub fn init(allocator: std.mem.Allocator) ChallegeStageManager { - return ChallegeStageManager{ .allocator = allocator }; - } - pub fn createChallegeStage( - self: *ChallegeStageManager, - ) !protocol.SceneBattleInfo { - const config = try Config.loadGameConfig(self.allocator, "config.json"); - const stage = try Config.loadStageConfig(self.allocator, "resources/StageConfig.json"); - var battle = protocol.SceneBattleInfo.init(self.allocator); - const BattleBuff = protocol.BattleBuff; - for (stage.stage_config.items) |stageConf| { - if (stageConf.stage_id == ChallengeData.challenge_stageID) { - for (config.avatar_config.items, 0..) |avatarConf, idx| { - var avatar = protocol.BattleAvatar.init(self.allocator); - avatar.id = avatarConf.id; - avatar.hp = avatarConf.hp * 100; - avatar.sp_bar = .{ .sp_cur = avatarConf.sp * 100, .sp_max = 10000 }; - avatar.level = avatarConf.level; - avatar.rank = avatarConf.rank; - avatar.promotion = avatarConf.promotion; - avatar.avatar_type = .AVATAR_FORMAL_TYPE; - - for (avatarConf.relics.items) |relic| { - const r = try relicCoder(self.allocator, relic.id, relic.level, relic.main_affix_id, relic.stat1, relic.cnt1, relic.step1, relic.stat2, relic.cnt2, relic.step2, relic.stat3, relic.cnt3, relic.step3, relic.stat4, relic.cnt4, relic.step4); - try avatar.relic_list.append(r); - } - - const lc = protocol.BattleEquipment{ - .id = avatarConf.lightcone.id, - .rank = avatarConf.lightcone.rank, - .level = avatarConf.lightcone.level, - .promotion = avatarConf.lightcone.promotion, - }; - try avatar.equipment_list.append(lc); - var talentLevel: u32 = 0; - const skill_list: []const u32 = if (isInList(avatar.id, &Data.Rem)) &Data.skills else &Data.skills_old; - for (skill_list) |elem| { - talentLevel = switch (elem) { - 1 => 6, - 2...4 => 10, - 301, 302 => if (isInList(avatar.id, &Data.Rem)) 6 else 1, - else => 1, - }; - const talent = protocol.AvatarSkillTree{ .point_id = avatar.id * 1000 + elem, .level = talentLevel }; - try avatar.skilltree_list.append(talent); - } - if (avatarConf.use_technique) { - var targetIndexList = ArrayList(u32).init(self.allocator); - try targetIndexList.append(0); - - var buffedAvatarId = avatar.id; - if (avatar.id == 8004) { - buffedAvatarId = 8003; - } else if (avatar.id == 8006) { - buffedAvatarId = 8005; - } else if (avatar.id == 8008) { - buffedAvatarId = 8007; - } - - for (Data.buffs_unlocked) |buffId| { - const idPrefix = buffId / 100; - if (idPrefix == buffedAvatarId) { - var buff = BattleBuff{ - .id = buffId, - .level = 1, - .owner_index = @intCast(idx), - .wave_flag = 1, - .target_index_list = targetIndexList, - .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(self.allocator), - }; - - try buff.dynamic_values.append(.{ .key = .{ .Const = "SkillIndex" }, .value = 0 }); - try battle.buff_list.append(buff); - } - } - - if (isInList(buffedAvatarId, &Data.IgnoreToughness)) { - var buff_tough = BattleBuff{ - .id = 1000119, //for is_ignore toughness - .level = 1, - .owner_index = @intCast(idx), - .wave_flag = 1, - .target_index_list = targetIndexList, - .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(self.allocator), - }; - try buff_tough.dynamic_values.append(.{ .key = .{ .Const = "SkillIndex" }, .value = 0 }); - try battle.buff_list.append(buff_tough); - } - - if (buffedAvatarId == 1224) { - var buff_march = protocol.BattleBuff{ - .id = 122401, //for hunt march 7th tech - .level = 1, - .owner_index = @intCast(idx), - .wave_flag = 1, - .target_index_list = targetIndexList, - .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(self.allocator), - }; - - try buff_march.dynamic_values.appendSlice(&[_]protocol.BattleBuff.DynamicValuesEntry{ - .{ .key = .{ .Const = "#ADF_1" }, .value = 3 }, - .{ .key = .{ .Const = "#ADF_2" }, .value = 3 }, - }); - try battle.buff_list.append(buff_march); - } - - if (buffedAvatarId == 1310) { - var buff_firefly = BattleBuff{ - .id = 1000112, //for firefly tech - .level = 1, - .owner_index = @intCast(idx), - .wave_flag = 1, - .target_index_list = targetIndexList, - .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(self.allocator), - }; - try buff_firefly.dynamic_values.append(.{ .key = .{ .Const = "SkillIndex" }, .value = 0 }); - try battle.buff_list.append(buff_firefly); - } - - if (buffedAvatarId == 8007) { - var buff_rmc = BattleBuff{ - .id = 800701, //for rmc tech - .level = 1, - .owner_index = @intCast(idx), - .wave_flag = 1, - .target_index_list = targetIndexList, - .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(self.allocator), - }; - try buff_rmc.dynamic_values.append(.{ .key = .{ .Const = "SkillIndex" }, .value = 0 }); - try battle.buff_list.append(buff_rmc); - } - } - - try battle.pve_avatar_list.append(avatar); - } - - battle.battle_id = 1; - battle.stage_id = stageConf.stage_id; - battle.logic_random_seed = @intCast(@mod(std.time.timestamp(), 0xFFFFFFFF)); - battle.rounds_limit = if (ChallengeData.challenge_mode != 1) 30 else 4; - battle.monster_wave_length = @intCast(stageConf.monster_list.items.len); - battle.world_level = 6; - - // Monster handler - for (stageConf.monster_list.items) |wave| { - var monster_wave = protocol.SceneMonsterWave.init(self.allocator); - monster_wave.wave_param = protocol.SceneMonsterWaveParam{ .level = stageConf.level }; - for (wave.items) |mob_id| { - try monster_wave.monster_list.append(.{ .monster_id = mob_id }); - } - try battle.monster_wave_list.append(monster_wave); - } - // stage blessings - for (ChallengeData.challenge_blessing) |blessing| { - var targetIndexList = ArrayList(u32).init(self.allocator); - try targetIndexList.append(0); - var buff = protocol.BattleBuff{ - .id = blessing, - .level = 1, - .owner_index = 0xffffffff, - .wave_flag = 0xffffffff, - .target_index_list = targetIndexList, - .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(self.allocator), - }; - try buff.dynamic_values.append(.{ .key = .{ .Const = "SkillIndex" }, .value = 0 }); - try battle.buff_list.append(buff); - } - if (isInList(1407, Data.AllAvatars)) { //support Castorice - var targetIndexList = ArrayList(u32).init(self.allocator); - try targetIndexList.append(0); - var mazebuff_data = BattleBuff{ - .id = 140703, - .level = 1, - .owner_index = 1, - .wave_flag = @intCast(stageConf.monster_list.items.len), - .target_index_list = targetIndexList, - .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(self.allocator), - }; - try mazebuff_data.dynamic_values.append(.{ .key = .{ .Const = "SkillIndex" }, .value = 0 }); - try battle.buff_list.append(mazebuff_data); - } - - // PF/AS scoring - const BattleTargetInfoEntry = protocol.SceneBattleInfo.BattleTargetInfoEntry; - battle.battle_target_info = ArrayList(BattleTargetInfoEntry).init(self.allocator); - - // target hardcode - var pfTargetHead = protocol.BattleTargetList{ .battle_target_list = ArrayList(protocol.BattleTarget).init(self.allocator) }; - try pfTargetHead.battle_target_list.append(.{ .id = 10002, .progress = 0, .total_progress = 0 }); - var pfTargetTail = protocol.BattleTargetList{ .battle_target_list = ArrayList(protocol.BattleTarget).init(self.allocator) }; - try pfTargetTail.battle_target_list.append(.{ .id = 2001, .progress = 0, .total_progress = 0 }); - try pfTargetTail.battle_target_list.append(.{ .id = 2002, .progress = 0, .total_progress = 0 }); - var asTargetHead = protocol.BattleTargetList{ .battle_target_list = ArrayList(protocol.BattleTarget).init(self.allocator) }; - try asTargetHead.battle_target_list.append(.{ .id = 90005, .progress = 0, .total_progress = 0 }); - - switch (battle.stage_id) { - // PF - 30019000...30019100, 30021000...30021100, 30301000...30319000 => { - try battle.battle_target_info.append(.{ .key = 1, .value = pfTargetHead }); - // fill blank target - for (2..5) |i| { - try battle.battle_target_info.append(.{ .key = @intCast(i) }); - } - try battle.battle_target_info.append(.{ .key = 5, .value = pfTargetTail }); - }, - // AS - 420100...420300 => { - try battle.battle_target_info.append(.{ .key = 1, .value = asTargetHead }); - }, - else => {}, - } - } - } - return battle; - } -}; - -pub fn relicCoder(allocator: Allocator, id: u32, level: u32, main_affix_id: u32, stat1: u32, cnt1: u32, step1: u32, stat2: u32, cnt2: u32, step2: u32, stat3: u32, cnt3: u32, step3: u32, stat4: u32, cnt4: u32, step4: u32) !protocol.BattleRelic { +fn createBattleRelic(allocator: Allocator, id: u32, level: u32, main_affix_id: u32, stat1: u32, cnt1: u32, step1: u32, stat2: u32, cnt2: u32, step2: u32, stat3: u32, cnt3: u32, step3: u32, stat4: u32, cnt4: u32, step4: u32) !protocol.BattleRelic { var relic = protocol.BattleRelic{ .id = id, .main_affix_id = main_affix_id, @@ -469,6 +32,305 @@ pub fn relicCoder(allocator: Allocator, id: u32, level: u32, main_affix_id: u32, try relic.sub_affix_list.append(protocol.RelicAffix{ .affix_id = stat2, .cnt = cnt2, .step = step2 }); try relic.sub_affix_list.append(protocol.RelicAffix{ .affix_id = stat3, .cnt = cnt3, .step = step3 }); try relic.sub_affix_list.append(protocol.RelicAffix{ .affix_id = stat4, .cnt = cnt4, .step = step4 }); - return relic; } +fn createBattleAvatar(allocator: Allocator, avatarConf: Config.Avatar) !protocol.BattleAvatar { + var avatar = protocol.BattleAvatar.init(allocator); + avatar.id = avatarConf.id; + avatar.hp = avatarConf.hp * 100; + avatar.sp_bar = .{ .sp_cur = avatarConf.sp * 100, .sp_max = 10000 }; + avatar.level = avatarConf.level; + avatar.rank = avatarConf.rank; + avatar.promotion = avatarConf.promotion; + avatar.avatar_type = .AVATAR_FORMAL_TYPE; + + // Relics + for (avatarConf.relics.items) |relic| { + const r = try createBattleRelic(allocator, relic.id, relic.level, relic.main_affix_id, relic.stat1, relic.cnt1, relic.step1, relic.stat2, relic.cnt2, relic.step2, relic.stat3, relic.cnt3, relic.step3, relic.stat4, relic.cnt4, relic.step4); + try avatar.relic_list.append(r); + } + + // Lightcone + const lc = protocol.BattleEquipment{ + .id = avatarConf.lightcone.id, + .rank = avatarConf.lightcone.rank, + .level = avatarConf.lightcone.level, + .promotion = avatarConf.lightcone.promotion, + }; + try avatar.equipment_list.append(lc); + + // Skills + var talentLevel: u32 = 0; + const skill_list: []const u32 = if (isInList(avatar.id, &Data.Rem)) &Data.skills else &Data.skills_old; + for (skill_list) |elem| { + talentLevel = switch (elem) { + 1 => 6, + 2...4 => 10, + 301, 302 => if (isInList(avatar.id, &Data.Rem)) 6 else 1, + else => 1, + }; + const talent = protocol.AvatarSkillTree{ .point_id = avatar.id * 1000 + elem, .level = talentLevel }; + try avatar.skilltree_list.append(talent); + } + return avatar; +} + +// Function to add technique buffs +fn addTechniqueBuffs(allocator: Allocator, battle: *protocol.SceneBattleInfo, avatar: protocol.BattleAvatar, avatarConf: Config.Avatar, avatar_index: u32) !void { + if (!avatarConf.use_technique) return; + + var targetIndexList = ArrayList(u32).init(allocator); + try targetIndexList.append(0); + + var buffedAvatarId = avatar.id; + if (avatar.id == 8004) { + buffedAvatarId = 8003; + } else if (avatar.id == 8006) { + buffedAvatarId = 8005; + } else if (avatar.id == 8008) { + buffedAvatarId = 8007; + } + + for (Data.buffs_unlocked) |buffId| { + const idPrefix = buffId / 100; + if (idPrefix == buffedAvatarId) { + var buff = protocol.BattleBuff{ + .id = buffId, + .level = 1, + .owner_index = @intCast(avatar_index), + .wave_flag = 1, + .target_index_list = targetIndexList, + .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(allocator), + }; + try buff.dynamic_values.append(.{ .key = .{ .Const = "SkillIndex" }, .value = 0 }); + try battle.buff_list.append(buff); + } + } + + if (isInList(buffedAvatarId, &Data.IgnoreToughness)) { + var buff_tough = protocol.BattleBuff{ + .id = 1000119, //for is_ignore toughness + .level = 1, + .owner_index = @intCast(avatar_index), + .wave_flag = 1, + .target_index_list = targetIndexList, + .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(allocator), + }; + try buff_tough.dynamic_values.append(.{ .key = .{ .Const = "SkillIndex" }, .value = 0 }); + try battle.buff_list.append(buff_tough); + } + + if (buffedAvatarId == 1224) { + var buff_march = protocol.BattleBuff{ + .id = 122401, //for hunt march 7th tech + .level = 1, + .owner_index = @intCast(avatar_index), + .wave_flag = 1, + .target_index_list = targetIndexList, + .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(allocator), + }; + try buff_march.dynamic_values.appendSlice(&[_]protocol.BattleBuff.DynamicValuesEntry{ + .{ .key = .{ .Const = "#ADF_1" }, .value = 3 }, + .{ .key = .{ .Const = "#ADF_2" }, .value = 3 }, + }); + try battle.buff_list.append(buff_march); + } + + if (buffedAvatarId == 1310) { + var buff_firefly = protocol.BattleBuff{ + .id = 1000112, //for firefly tech + .level = 1, + .owner_index = @intCast(avatar_index), + .wave_flag = 1, + .target_index_list = targetIndexList, + .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(allocator), + }; + try buff_firefly.dynamic_values.append(.{ .key = .{ .Const = "SkillIndex" }, .value = 0 }); + try battle.buff_list.append(buff_firefly); + } + + if (buffedAvatarId == 8007) { + var buff_rmc = protocol.BattleBuff{ + .id = 800701, //for rmc tech + .level = 1, + .owner_index = @intCast(avatar_index), + .wave_flag = 1, + .target_index_list = targetIndexList, + .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(allocator), + }; + try buff_rmc.dynamic_values.append(.{ .key = .{ .Const = "SkillIndex" }, .value = 0 }); + try battle.buff_list.append(buff_rmc); + } +} + +// Function to add future global buff. +fn addGolbalPassive(allocator: Allocator, battle: *protocol.SceneBattleInfo, wave_flag: u32) !void { + if (isInList(1407, Data.AllAvatars)) { //support Castorice + var targetIndexList = ArrayList(u32).init(allocator); + try targetIndexList.append(0); + var mazebuff_data = protocol.BattleBuff{ + .id = 140703, + .level = 1, + .owner_index = 1, + .wave_flag = wave_flag, + .target_index_list = targetIndexList, + .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(allocator), + }; + try mazebuff_data.dynamic_values.append(.{ .key = .{ .Const = "SkillIndex" }, .value = 0 }); + try battle.buff_list.append(mazebuff_data); + } +} +fn createBattleInfo(allocator: Allocator, config: Config.GameConfig, stage_monster_wave_len: u32, stage_id: u32, rounds_limit: u32) protocol.SceneBattleInfo { + var battle = protocol.SceneBattleInfo.init(allocator); + battle.battle_id = config.battle_config.battle_id; + battle.stage_id = stage_id; + battle.logic_random_seed = @intCast(@mod(std.time.timestamp(), 0xFFFFFFFF)); + battle.rounds_limit = rounds_limit; + battle.monster_wave_length = @intCast(stage_monster_wave_len); + battle.world_level = 6; + return battle; +} +fn addMonsterWaves(allocator: Allocator, battle: *protocol.SceneBattleInfo, monster_wave_configs: std.ArrayList(std.ArrayList(u32)), monster_level: u32) !void { // Added monster_level + for (monster_wave_configs.items) |wave| { + var monster_wave = protocol.SceneMonsterWave.init(allocator); + monster_wave.wave_param = protocol.SceneMonsterWaveParam{ .level = monster_level }; + for (wave.items) |mob_id| { + try monster_wave.monster_list.append(.{ .monster_id = mob_id }); + } + try battle.monster_wave_list.append(monster_wave); + } +} +fn addStageBlessings(allocator: Allocator, battle: *protocol.SceneBattleInfo, blessings: []const u32) !void { + for (blessings) |blessing| { + var targetIndexList = ArrayList(u32).init(allocator); + try targetIndexList.append(0); + var buff = protocol.BattleBuff{ + .id = blessing, + .level = 1, + .owner_index = 0xffffffff, + .wave_flag = 0xffffffff, + .target_index_list = targetIndexList, + .dynamic_values = ArrayList(protocol.BattleBuff.DynamicValuesEntry).init(allocator), + }; + try buff.dynamic_values.append(.{ .key = .{ .Const = "SkillIndex" }, .value = 0 }); + try battle.buff_list.append(buff); + } +} +fn addBattleTargets(allocator: Allocator, battle: *protocol.SceneBattleInfo) !void { + // PF/AS scoring + battle.battle_target_info = ArrayList(protocol.SceneBattleInfo.BattleTargetInfoEntry).init(allocator); + + // target hardcode + var pfTargetHead = protocol.BattleTargetList{ .battle_target_list = ArrayList(protocol.BattleTarget).init(allocator) }; + try pfTargetHead.battle_target_list.append(.{ .id = 10002, .progress = 0, .total_progress = 0 }); + var pfTargetTail = protocol.BattleTargetList{ .battle_target_list = ArrayList(protocol.BattleTarget).init(allocator) }; + try pfTargetTail.battle_target_list.append(.{ .id = 2001, .progress = 0, .total_progress = 0 }); + try pfTargetTail.battle_target_list.append(.{ .id = 2002, .progress = 0, .total_progress = 0 }); + var asTargetHead = protocol.BattleTargetList{ .battle_target_list = ArrayList(protocol.BattleTarget).init(allocator) }; + try asTargetHead.battle_target_list.append(.{ .id = 90005, .progress = 0, .total_progress = 0 }); + + switch (battle.stage_id) { + // PF + 30019000...30019100, 30021000...30021100, 30301000...30319000 => { + try battle.battle_target_info.append(.{ .key = 1, .value = pfTargetHead }); + // fill blank target + for (2..5) |i| { + try battle.battle_target_info.append(.{ .key = @intCast(i) }); + } + try battle.battle_target_info.append(.{ .key = 5, .value = pfTargetTail }); + }, + // AS + 420100...420300 => { + try battle.battle_target_info.append(.{ .key = 1, .value = asTargetHead }); + }, + else => {}, + } +} +pub const BattleManager = struct { + allocator: Allocator, + + pub fn init(allocator: Allocator) BattleManager { + return BattleManager{ .allocator = allocator }; + } + + pub fn createBattle(self: *BattleManager) !protocol.SceneBattleInfo { + const config = try Config.loadGameConfig(self.allocator, "config.json"); + var battle = createBattleInfo(self.allocator, config, @intCast(config.battle_config.monster_wave.items.len), config.battle_config.stage_id, config.battle_config.cycle_count); + var avatarIndex: u32 = 0; + var initial_mode = false; + while (true) { + for (config.avatar_config.items) |avatarConf| { + if (!initial_mode) { + if (!isInList(avatarConf.id, &selectedAvatarID)) { + continue; + } + } + const avatar = try createBattleAvatar(self.allocator, avatarConf); + try addTechniqueBuffs(self.allocator, &battle, avatar, avatarConf, avatarIndex); + try battle.pve_avatar_list.append(avatar); + avatarIndex += 1; + if (avatarIndex >= 4) { + break; + } + } + if (avatarIndex == 0 and !initial_mode) { + initial_mode = true; + continue; + } + break; + } + try addMonsterWaves(self.allocator, &battle, config.battle_config.monster_wave, config.battle_config.monster_level); + try addStageBlessings(self.allocator, &battle, config.battle_config.blessings.items); + try addGolbalPassive(self.allocator, &battle, @intCast(config.battle_config.monster_wave.items.len)); + try addBattleTargets(self.allocator, &battle); + return battle; + } +}; + +pub const ChallegeStageManager = struct { + allocator: Allocator, + + pub fn init(allocator: Allocator) ChallegeStageManager { + return ChallegeStageManager{ .allocator = allocator }; + } + + pub fn createChallegeStage(self: *ChallegeStageManager) !protocol.SceneBattleInfo { + const config = try Config.loadGameConfig(self.allocator, "config.json"); + const stage = try Config.loadStageConfig(self.allocator, "resources/StageConfig.json"); + var battle: protocol.SceneBattleInfo = undefined; + for (stage.stage_config.items) |stageConf| { + if (stageConf.stage_id == ChallengeData.challenge_stageID) { + battle = createBattleInfo(self.allocator, config, @intCast(stageConf.monster_list.items.len), stageConf.stage_id, if (ChallengeData.challenge_mode != 1) 30 else 4); + var avatarIndex: u32 = 0; + var initial_mode = false; + while (true) { + for (config.avatar_config.items) |avatarConf| { + if (!initial_mode) { + if (!isInList(avatarConf.id, &selectedAvatarID)) { + continue; + } + } + const avatar = try createBattleAvatar(self.allocator, avatarConf); + try addTechniqueBuffs(self.allocator, &battle, avatar, avatarConf, avatarIndex); + try battle.pve_avatar_list.append(avatar); + avatarIndex += 1; + if (avatarIndex >= 4) { + break; + } + } + if (avatarIndex == 0 and !initial_mode) { + initial_mode = true; + continue; + } + break; + } + try addMonsterWaves(self.allocator, &battle, stageConf.monster_list, stageConf.level); + try addStageBlessings(self.allocator, &battle, ChallengeData.challenge_blessing); + try addGolbalPassive(self.allocator, &battle, @intCast(stageConf.monster_list.items.len)); + try addBattleTargets(self.allocator, &battle); + break; + } + } + return battle; + } +}; diff --git a/gameserver/src/manager/challenge_mgr.zig b/gameserver/src/manager/challenge_mgr.zig new file mode 100644 index 0000000..41f3e8a --- /dev/null +++ b/gameserver/src/manager/challenge_mgr.zig @@ -0,0 +1,158 @@ +const std = @import("std"); +const protocol = @import("protocol"); +const Session = @import("../Session.zig"); +const Packet = @import("../Packet.zig"); +const Config = @import("../services/config.zig"); +const Data = @import("../data.zig"); +const ChallengeData = @import("../services/challenge.zig"); +const NodeCheck = @import("../commands/value.zig"); + +const ArrayList = std.ArrayList; +const Allocator = std.mem.Allocator; +const CmdID = protocol.CmdID; + +fn contains(list: *const std.ArrayListAligned(u32, null), value: u32) bool { + for (list.items) |item| { + if (item == value) { + return true; + } + } + return false; +} + +pub const ChallengeManager = struct { + allocator: std.mem.Allocator, + pub fn init(allocator: std.mem.Allocator) ChallengeManager { + return ChallengeManager{ .allocator = allocator }; + } + pub fn createChallenge( + self: *ChallengeManager, + challenge_id: u32, + buff_id: u32, + ) !protocol.CurChallenge { + const challenge_config = try Config.loadChallengeConfig(self.allocator, "resources/ChallengeMazeConfig.json"); + const entrance_config = try Config.loadMapEntranceConfig(self.allocator, "resources/MapEntrance.json"); + const maze_config = try Config.loadMazePlaneConfig(self.allocator, "resources/MazePlane.json"); + + var challenge_blessing_list = ChallengeData.ChallengeBlessing{ + .allocator = std.heap.page_allocator, + .items = &.{}, + .capacity = 0, + }; + + var cur_challenge_info = protocol.CurChallenge.init(self.allocator); + cur_challenge_info.challenge_id = challenge_id; + cur_challenge_info.score_id = if (challenge_id > 20000 and challenge_id < 30000) 40000 else 0; + cur_challenge_info.score_two = 0; + cur_challenge_info.status = protocol.ChallengeStatus.CHALLENGE_DOING; + cur_challenge_info.extra_lineup_type = if (NodeCheck.challenge_node == 0) protocol.ExtraLineupType.LINEUP_CHALLENGE else protocol.ExtraLineupType.LINEUP_CHALLENGE_2; + if (NodeCheck.challenge_node == 0) { + for (challenge_config.challenge_config.items) |challengeConf| { + if (challengeConf.id == challenge_id) { + std.debug.print("TRACING CONFIG ID {} WITH CHALLENGE ID {}\n", .{ challengeConf.id, challenge_id }); + for (entrance_config.map_entrance_config.items) |entrance| { + if (entrance.id == challengeConf.map_entrance_id) { + for (maze_config.maze_plane_config.items) |maze| { + if (contains(&maze.floor_id_list, entrance.floor_id)) { + if (challenge_id > 20000 and challenge_id < 30000) { + var story_buff = protocol.ChallengeStoryBuffList{ + .buff_list = ArrayList(u32).init(self.allocator), + }; + try story_buff.buff_list.append(challengeConf.maze_buff_id); + try story_buff.buff_list.append(buff_id); + try challenge_blessing_list.appendSlice(story_buff.buff_list.items); + cur_challenge_info.stage_info = .{ + .IEICDGGELNE = .{ + .cur_story_buffs = story_buff, + }, + }; + ChallengeData.challenge_mode = 1; + } else if (challenge_id > 30000) { + var boss_buff = protocol.ChallengeBossBuffList{ + .buff_list = ArrayList(u32).init(self.allocator), + .challenge_boss_const = 1, + }; + try boss_buff.buff_list.append(challengeConf.maze_buff_id); + try boss_buff.buff_list.append(buff_id); + try challenge_blessing_list.appendSlice(boss_buff.buff_list.items); + cur_challenge_info.stage_info = .{ + .IEICDGGELNE = .{ + .cur_boss_buffs = boss_buff, + }, + }; + ChallengeData.challenge_mode = 2; + } + ChallengeData.challenge_floorID = entrance.floor_id; + ChallengeData.challenge_worldID = maze.world_id; + ChallengeData.challenge_monsterID = challengeConf.npc_monster_id_list1.items[challengeConf.npc_monster_id_list1.items.len - 1]; + ChallengeData.challenge_eventID = challengeConf.event_id_list1.items[challengeConf.event_id_list1.items.len - 1]; + ChallengeData.challenge_groupID = challengeConf.maze_group_id1; + ChallengeData.challenge_maze_groupID = challengeConf.maze_group_id1; + ChallengeData.challenge_planeID = maze.challenge_plane_id; + ChallengeData.challenge_entryID = challengeConf.map_entrance_id; + } + } + } + } + } + } + } else { + for (challenge_config.challenge_config.items) |challengeConf| { + if (challengeConf.id == challenge_id) { + std.debug.print("TRACING CONFIG ID {} WITH CHALLENGE ID {}\n", .{ challengeConf.id, challenge_id }); + for (entrance_config.map_entrance_config.items) |entrance| { + if (entrance.id == challengeConf.map_entrance_id2) { + for (maze_config.maze_plane_config.items) |maze| { + if (contains(&maze.floor_id_list, entrance.floor_id)) { + if (challengeConf.maze_group_id2) |id| { + if (challenge_id > 20000 and challenge_id < 30000) { + var story_buff = protocol.ChallengeStoryBuffList{ + .buff_list = ArrayList(u32).init(self.allocator), + }; + try story_buff.buff_list.append(challengeConf.maze_buff_id); + try story_buff.buff_list.append(buff_id); + try challenge_blessing_list.appendSlice(story_buff.buff_list.items); + cur_challenge_info.stage_info = .{ + .IEICDGGELNE = .{ + .cur_story_buffs = story_buff, + }, + }; + ChallengeData.challenge_mode = 1; + } else if (challenge_id > 30000) { + var boss_buff = protocol.ChallengeBossBuffList{ + .buff_list = ArrayList(u32).init(self.allocator), + .challenge_boss_const = 1, + }; + try boss_buff.buff_list.append(challengeConf.maze_buff_id); + try boss_buff.buff_list.append(buff_id); + try challenge_blessing_list.appendSlice(boss_buff.buff_list.items); + cur_challenge_info.stage_info = .{ + .IEICDGGELNE = .{ + .cur_boss_buffs = boss_buff, + }, + }; + ChallengeData.challenge_mode = 2; + } + ChallengeData.challenge_floorID = entrance.floor_id; + ChallengeData.challenge_worldID = maze.world_id; + ChallengeData.challenge_monsterID = challengeConf.npc_monster_id_list2.items[challengeConf.npc_monster_id_list2.items.len - 1]; + ChallengeData.challenge_eventID = challengeConf.event_id_list2.items[challengeConf.event_id_list2.items.len - 1]; + ChallengeData.challenge_groupID = id; + ChallengeData.challenge_maze_groupID = id; + ChallengeData.challenge_planeID = maze.challenge_plane_id; + ChallengeData.challenge_entryID = challengeConf.map_entrance_id2; + } else { + std.debug.print("THIS CHALLENGE ID: {} DOES NOT SUPPORT 2ND NODE. PLEASE DO COMMAND /node TO SWITCH BACK TO FIRST NODE\n", .{challenge_id}); + } + } + } + } + } + } + } + } + ChallengeData.challenge_blessing = challenge_blessing_list.items[0..challenge_blessing_list.items.len]; + ChallengeData.challenge_stageID = ChallengeData.challenge_eventID; + return cur_challenge_info; + } +}; diff --git a/gameserver/src/manager/lineup_mgr.zig b/gameserver/src/manager/lineup_mgr.zig index 65465df..b7dc9f7 100644 --- a/gameserver/src/manager/lineup_mgr.zig +++ b/gameserver/src/manager/lineup_mgr.zig @@ -4,6 +4,9 @@ const Session = @import("../Session.zig"); const Packet = @import("../Packet.zig"); const Config = @import("../services/config.zig"); const Data = @import("../data.zig"); +const ChallengeData = @import("../services/challenge.zig"); +const NodeCheck = @import("../commands/value.zig"); +const BattleManager = @import("../manager/battle_mgr.zig"); const UidGenerator = @import("../services/item.zig").UidGenerator; const ArrayList = std.ArrayList; @@ -24,6 +27,9 @@ pub const LineupManager = struct { lineup.name = .{ .Const = "CipherSR" }; for (config.avatar_config.items, 0..) |avatarConf, idx| { + if (idx >= 4) { + break; + } var avatar = protocol.LineupAvatar.init(self.allocator); avatar.id = avatarConf.id; avatar.slot = @intCast(idx); @@ -33,7 +39,67 @@ pub const LineupManager = struct { avatar.avatar_type = protocol.AvatarType.AVATAR_FORMAL_TYPE; try lineup.avatar_list.append(avatar); } - + var id_list = try self.allocator.alloc(u32, config.avatar_config.items.len); + defer self.allocator.free(id_list); + for (config.avatar_config.items, 0..) |slot, idx| { + if (idx >= 4) { + break; + } + id_list[idx] = slot.id; + } + try getSelectedAvatarID(self.allocator, id_list); return lineup; } }; + +pub const ChallengeLineupManager = struct { + allocator: std.mem.Allocator, + pub fn init(allocator: std.mem.Allocator) ChallengeLineupManager { + return ChallengeLineupManager{ .allocator = allocator }; + } + pub fn createLineup( + self: *ChallengeLineupManager, + avatar_list: ArrayList(u32), + ) !protocol.LineupInfo { + var lineup = protocol.LineupInfo.init(self.allocator); + lineup.mp = 5; + lineup.max_mp = 5; + lineup.extra_lineup_type = if (NodeCheck.challenge_node == 0) protocol.ExtraLineupType.LINEUP_CHALLENGE else protocol.ExtraLineupType.LINEUP_CHALLENGE_2; + + for (avatar_list.items, 0..) |avatarlist, idx| { + var avatar = protocol.LineupAvatar.init(self.allocator); + avatar.id = avatarlist; + avatar.slot = @intCast(idx); + avatar.satiety = 0; + avatar.hp = 10000; + avatar.sp_bar = .{ .sp_cur = 10000, .sp_max = 10000 }; + avatar.avatar_type = protocol.AvatarType.AVATAR_FORMAL_TYPE; + try lineup.avatar_list.append(avatar); + } + var id_list = try self.allocator.alloc(u32, avatar_list.items.len); + defer self.allocator.free(id_list); + for (avatar_list.items, 0..) |slot, idx| { + if (idx >= 4) { + break; + } + id_list[idx] = slot; + } + try getSelectedAvatarID(self.allocator, id_list); + return lineup; + } +}; + +pub fn getSelectedAvatarID(allocator: std.mem.Allocator, input: []const u32) !void { + var tempList = std.ArrayList(u32).init(allocator); + defer tempList.deinit(); + + try tempList.appendSlice(input); + + var i: usize = 0; + while (i < BattleManager.selectedAvatarID.len and i < tempList.items.len) : (i += 1) { + BattleManager.selectedAvatarID[i] = tempList.items[i]; + } + while (i < BattleManager.selectedAvatarID.len) : (i += 1) { + BattleManager.selectedAvatarID[i] = 0; + } +} diff --git a/gameserver/src/manager/scene_mgr.zig b/gameserver/src/manager/scene_mgr.zig index cfd6d13..af4c737 100644 --- a/gameserver/src/manager/scene_mgr.zig +++ b/gameserver/src/manager/scene_mgr.zig @@ -29,6 +29,7 @@ pub const SceneManager = struct { const res_config = try Res_config.anchorLoader(self.allocator, "resources/res.json"); var generator = UidGenerator().init(); var scene_info = protocol.SceneInfo.init(self.allocator); + scene_info.game_mode_type = 1; scene_info.plane_id = plane_id; scene_info.floor_id = floor_id; scene_info.entry_id = entry_id; @@ -37,6 +38,7 @@ pub const SceneManager = struct { scene_info.client_pos_version = 1; var group_map = std.AutoHashMap(u32, protocol.SceneEntityGroupInfo).init(self.allocator); defer group_map.deinit(); + for (res_config.scene_config.items) |sceneConf| { for (sceneConf.teleports.items) |teleConf| { if (teleConf.teleportId == teleport_id) { @@ -100,6 +102,27 @@ pub const SceneManager = struct { var iter = group_map.iterator(); while (iter.next()) |entry| { try scene_info.entity_group_list.append(entry.value_ptr.*); + try scene_info.entity_list.appendSlice(entry.value_ptr.entity_list.items); + try scene_info.DJBIBIJMEBH.append(entry.value_ptr.group_id); + try scene_info.custom_data_list.append(protocol.CustomSaveData{ + .group_id = entry.value_ptr.group_id, + }); + try scene_info.group_state_list.append(protocol.SceneGroupState{ + .group_id = entry.value_ptr.group_id, + .state = 0, + .is_default = true, + }); + } + const ranges = [_][2]usize{ + .{ 0, 101 }, + .{ 10000, 10051 }, + .{ 20000, 20001 }, + .{ 30000, 30020 }, + }; + for (ranges) |range| { + for (range[0]..range[1]) |i| { + try scene_info.lighten_section_list.append(@intCast(i)); + } } return scene_info; } diff --git a/gameserver/src/services/avatar.zig b/gameserver/src/services/avatar.zig index 568f19a..f16eb7f 100644 --- a/gameserver/src/services/avatar.zig +++ b/gameserver/src/services/avatar.zig @@ -182,3 +182,10 @@ pub fn onGetBigData(session: *Session, packet: *const Packet, allocator: Allocat rsp.EIGPMIBCIKG = req.EIGPMIBCIKG; try session.send(CmdID.CmdGetBigDataRecommendScRsp, rsp); } +pub fn onGetPreAvatarGrowthInfo(session: *Session, packet: *const Packet, allocator: Allocator) !void { + const req = try packet.getProto(protocol.GetPreAvatarGrowthInfoCsReq, allocator); + var rsp = protocol.GetPreAvatarGrowthInfoScRsp.init(allocator); + rsp.retcode = 0; + rsp.KJAEOJBJOJD = req.KJAEOJBJOJD; + try session.send(CmdID.CmdGetPreAvatarGrowthInfoScRsp, rsp); +} diff --git a/gameserver/src/services/battle.zig b/gameserver/src/services/battle.zig index b129524..0d4e8bf 100644 --- a/gameserver/src/services/battle.zig +++ b/gameserver/src/services/battle.zig @@ -7,15 +7,19 @@ const Data = @import("../data.zig"); const ChallengeData = @import("challenge.zig"); const BattleManager = @import("../manager/battle_mgr.zig").BattleManager; const ChallegeStageManager = @import("../manager/battle_mgr.zig").ChallegeStageManager; +const NodeCheck = @import("../commands/value.zig"); const ArrayList = std.ArrayList; const Allocator = std.mem.Allocator; const CmdID = protocol.CmdID; +pub var on_battle: bool = false; + pub fn onStartCocoonStage(session: *Session, packet: *const Packet, allocator: Allocator) !void { const req = try packet.getProto(protocol.StartCocoonStageCsReq, allocator); var battle_mgr = BattleManager.init(allocator); const battle = try battle_mgr.createBattle(); + on_battle = true; try session.send(CmdID.CmdStartCocoonStageScRsp, protocol.StartCocoonStageScRsp{ .retcode = 0, .cocoon_id = req.cocoon_id, @@ -28,6 +32,7 @@ pub fn onQuickStartCocoonStage(session: *Session, packet: *const Packet, allocat const req = try packet.getProto(protocol.QuickStartCocoonStageCsReq, allocator); var battle_mgr = BattleManager.init(allocator); const battle = try battle_mgr.createBattle(); + on_battle = true; try session.send(CmdID.CmdQuickStartCocoonStageScRsp, protocol.QuickStartCocoonStageScRsp{ .retcode = 0, .cocoon_id = req.cocoon_id, @@ -39,6 +44,7 @@ pub fn onQuickStartFarmElement(session: *Session, packet: *const Packet, allocat const req = try packet.getProto(protocol.QuickStartFarmElementCsReq, allocator); var battle_mgr = BattleManager.init(allocator); const battle = try battle_mgr.createBattle(); + on_battle = true; try session.send(CmdID.CmdQuickStartFarmElementScRsp, protocol.QuickStartFarmElementScRsp{ .retcode = 0, .world_level = req.world_level, @@ -50,6 +56,7 @@ pub fn onStartBattleCollege(session: *Session, packet: *const Packet, allocator: const req = try packet.getProto(protocol.StartBattleCollegeCsReq, allocator); var battle_mgr = BattleManager.init(allocator); const battle = try battle_mgr.createBattle(); + on_battle = true; try session.send(CmdID.CmdStartBattleCollegeScRsp, protocol.StartBattleCollegeScRsp{ .retcode = 0, .id = req.id, @@ -69,23 +76,47 @@ pub fn onSceneCastSkill(session: *Session, packet: *const Packet, allocator: All .monster_battle_type = protocol.MonsterBattleType.MONSTER_BATTLE_TYPE_TRIGGER_BATTLE, }, }); + + var battle_info: ?protocol.SceneBattleInfo = null; + + if (req.assist_monster_entity_id_list.items.len > 0 or + (req.attacked_by_entity_id >= 1 and req.attacked_by_entity_id <= 99)) + { + if (ChallengeData.on_challenge) { + battle_info = challenge; + } else { + battle_info = battle; + on_battle = true; + } + } + try session.send(CmdID.CmdSceneCastSkillScRsp, protocol.SceneCastSkillScRsp{ .retcode = 0, .cast_entity_id = req.cast_entity_id, .monster_battle_info = monster_battle_info_list, - .battle_info = if (req.assist_monster_entity_id_list.items.len > 0 or - (req.attacked_by_entity_id >= 1 and req.attacked_by_entity_id <= 99)) - (if (ChallengeData.on_challenge) challenge else battle) - else - null, + .battle_info = battle_info, }); } +pub fn onGetCurBattleInfo(session: *Session, _: *const Packet, allocator: Allocator) !void { + var battle_mgr = BattleManager.init(allocator); + const battle = try battle_mgr.createBattle(); + var challege_mgr = ChallegeStageManager.init(allocator); + const challenge = try challege_mgr.createChallegeStage(); + + var rsp = protocol.GetCurBattleInfoScRsp.init(allocator); + rsp.battle_info = if (ChallengeData.on_challenge == true) challenge else if (on_battle == true) battle else null; + rsp.retcode = 0; + try session.send(CmdID.CmdGetCurBattleInfoScRsp, rsp); +} + pub fn onPVEBattleResult(session: *Session, packet: *const Packet, allocator: Allocator) !void { const req = try packet.getProto(protocol.PVEBattleResultCsReq, allocator); var rsp = protocol.PVEBattleResultScRsp.init(allocator); rsp.battle_id = req.battle_id; rsp.end_status = req.end_status; + rsp.stage_id = req.stage_id; + on_battle = false; try session.send(CmdID.CmdPVEBattleResultScRsp, rsp); } @@ -96,3 +127,12 @@ pub fn onSceneCastSkillCostMp(session: *Session, packet: *const Packet, allocato .cast_entity_id = req.cast_entity_id, }); } + +pub fn onSyncClientResVersion(session: *Session, packet: *const Packet, allocator: Allocator) !void { + const req = try packet.getProto(protocol.SyncClientResVersionCsReq, allocator); + std.debug.print("CLIENT RES VERSION: {}\n", .{req.client_res_version}); + try session.send(CmdID.CmdSyncClientResVersionScRsp, protocol.SyncClientResVersionScRsp{ + .retcode = 0, + .client_res_version = req.client_res_version, + }); +} diff --git a/gameserver/src/services/challenge.zig b/gameserver/src/services/challenge.zig index 3a487b1..812694f 100644 --- a/gameserver/src/services/challenge.zig +++ b/gameserver/src/services/challenge.zig @@ -6,9 +6,11 @@ const Config = @import("config.zig"); const Res_config = @import("res_config.zig"); const Data = @import("../data.zig"); const ChallegeStageManager = @import("../manager/battle_mgr.zig").ChallegeStageManager; +const ChallengeManager = @import("../manager/challenge_mgr.zig").ChallengeManager; const SceneManager = @import("../manager/scene_mgr.zig").SceneManager; const ChallengeSceneManager = @import("../manager/scene_mgr.zig").ChallengeSceneManager; const LineupManager = @import("../manager/lineup_mgr.zig").LineupManager; +const ChallengeLineupManager = @import("../manager/lineup_mgr.zig").ChallengeLineupManager; const NodeCheck = @import("../commands/value.zig"); const ArrayList = std.ArrayList; @@ -40,13 +42,45 @@ fn contains(list: *const std.ArrayListAligned(u32, null), value: u32) bool { } return false; } -pub var challenge_stageID: u32 = 0; -pub var challenge_mode: u32 = 0; - pub var on_challenge: bool = false; pub const ChallengeBlessing = ArrayList(u32); pub var challenge_blessing: []const u32 = &.{}; +pub var challenge_mode: u32 = 0; + +pub var challenge_planeID: u32 = 0; +pub var challenge_floorID: u32 = 0; +pub var challenge_entryID: u32 = 0; +pub var challenge_worldID: u32 = 0; +pub var challenge_monsterID: u32 = 0; +pub var challenge_eventID: u32 = 0; +pub var challenge_groupID: u32 = 0; +pub var challenge_maze_groupID: u32 = 0; +pub var challenge_stageID: u32 = 0; + +pub var challengeID: u32 = 0; +pub var challenge_buffID: u32 = 0; + +pub const ChallengeAvatarList = ArrayList(u32); +pub var avatar_list: ChallengeAvatarList = ChallengeAvatarList.init(std.heap.page_allocator); + +pub fn resetChallengeState() void { + on_challenge = false; + challenge_mode = 0; + challenge_planeID = 0; + challenge_floorID = 0; + challenge_entryID = 0; + challenge_worldID = 0; + challenge_monsterID = 0; + challenge_eventID = 0; + challenge_groupID = 0; + challenge_maze_groupID = 0; + challenge_stageID = 0; + challengeID = 0; + challenge_buffID = 0; + challenge_blessing = &.{}; + _ = avatar_list.clearRetainingCapacity(); +} pub fn onGetChallenge(session: *Session, _: *const Packet, allocator: Allocator) !void { const challenge_config = try Config.loadChallengeConfig(allocator, "resources/ChallengeMazeConfig.json"); @@ -71,7 +105,6 @@ pub fn onGetChallengeGroupStatistics(session: *Session, packet: *const Packet, a var rsp = protocol.GetChallengeGroupStatisticsScRsp.init(allocator); rsp.retcode = 0; rsp.group_id = req.group_id; - try session.send(CmdID.CmdGetChallengeGroupStatisticsScRsp, rsp); } pub fn onLeaveChallenge(session: *Session, _: *const Packet, allocator: Allocator) !void { @@ -85,196 +118,99 @@ pub fn onLeaveChallenge(session: *Session, _: *const Packet, allocator: Allocato .lineup = lineup, .scene = scene_info, }); - on_challenge = false; + resetChallengeState(); challenge_mode = 0; try session.send(CmdID.CmdLeaveChallengeScRsp, protocol.LeaveChallengeScRsp{ .retcode = 0, }); } +pub fn onGetCurChallengeScRsp(session: *Session, _: *const Packet, allocator: Allocator) !void { + var rsp = protocol.GetCurChallengeScRsp.init(allocator); + var lineup_manager = ChallengeLineupManager.init(allocator); + const lineup_info = try lineup_manager.createLineup(avatar_list); + var challenge_manager = ChallengeManager.init(allocator); + const cur_challenge_info = try challenge_manager.createChallenge( + challengeID, + challenge_buffID, + ); + rsp.retcode = 0; + if (on_challenge == true) { + rsp.cur_challenge = cur_challenge_info; + try rsp.lineup_list.append(lineup_info); + + std.debug.print("CURRENT CHALLENGE STAGE ID:{}\n", .{challenge_stageID}); + std.debug.print("CURRENT CHALLENGE LINEUP AVATAR ID:{}\n", .{avatar_list}); + std.debug.print("CURRENT CHALLENGE MONSTER ID:{}\n", .{challenge_monsterID}); + if (challenge_mode == 0) { + std.debug.print("CURRENT CHALLENGE: {} MOC\n", .{challenge_mode}); + } else if (challenge_mode == 1) { + std.debug.print("CURRENT CHALLENGE: {} PF\n", .{challenge_mode}); + std.debug.print("CURRENT CHALLENGE STAGE BLESSING ID:{}, SELECTED BLESSING ID:{}\n", .{ challenge_blessing[0], challenge_blessing[1] }); + } else { + std.debug.print("CURRENT CHALLENGE: {} AS\n", .{challenge_mode}); + std.debug.print("CURRENT CHALLENGE STAGE BLESSING ID:{}, SELECTED BLESSING ID:{}\n", .{ challenge_blessing[0], challenge_blessing[1] }); + } + } else { + std.debug.print("CURRENT ON CHALLENGE STATE: {}\n", .{on_challenge}); + } + + try session.send(CmdID.CmdGetCurChallengeScRsp, rsp); +} pub fn onStartChallenge(session: *Session, packet: *const Packet, allocator: Allocator) !void { - var challenge_blessing_list = ChallengeBlessing{ - .allocator = std.heap.page_allocator, - .items = &.{}, - .capacity = 0, - }; const req = try packet.getProto(protocol.StartChallengeCsReq, allocator); var rsp = protocol.StartChallengeScRsp.init(allocator); - const challenge_config = try Config.loadChallengeConfig(allocator, "resources/ChallengeMazeConfig.json"); - const entrance_config = try Config.loadMapEntranceConfig(allocator, "resources/MapEntrance.json"); - const maze_config = try Config.loadMazePlaneConfig(allocator, "resources/MazePlane.json"); - var avatarList = std.ArrayList(u32).init(allocator); - var lineup = protocol.LineupInfo.init(allocator); - lineup.mp = 5; - lineup.max_mp = 5; - lineup.extra_lineup_type = if (NodeCheck.challenge_node == 0) protocol.ExtraLineupType.LINEUP_CHALLENGE else protocol.ExtraLineupType.LINEUP_CHALLENGE_2; + challengeID = req.challenge_id; if (NodeCheck.challenge_node == 0) { - for (req.first_lineup.items, 0..) |avt, idx| { - var list = protocol.LineupAvatar.init(allocator); - try avatarList.append(avt); - list.id = avt; - list.slot = @intCast(idx); - list.satiety = 0; - list.avatar_type = protocol.AvatarType.AVATAR_FORMAL_TYPE; - list.hp = 10000; - list.sp_bar = .{ .sp_cur = 10000, .sp_max = 10000 }; - try lineup.avatar_list.append(list); + for (req.first_lineup.items) |id| { + try avatar_list.append(id); } - try rsp.lineup_list.append(lineup); + if (challengeID > 20000 and challengeID < 30000) + challenge_buffID = req.stage_info.?.IEICDGGELNE.?.story_info.buff_one; + if (challengeID > 30000) + challenge_buffID = req.stage_info.?.IEICDGGELNE.?.boss_info.buff_one; } else { - for (req.second_lineup.items, 0..) |avt, idx| { - var list = protocol.LineupAvatar.init(allocator); - try avatarList.append(avt); - list.id = avt; - list.slot = @intCast(idx); - list.satiety = 0; - list.avatar_type = protocol.AvatarType.AVATAR_FORMAL_TYPE; - list.hp = 10000; - list.sp_bar = .{ .sp_cur = 10000, .sp_max = 10000 }; - try lineup.avatar_list.append(list); + for (req.second_lineup.items) |id| { + try avatar_list.append(id); } - try rsp.lineup_list.append(lineup); + if (challengeID > 20000 and challengeID < 30000) + challenge_buffID = req.stage_info.?.IEICDGGELNE.?.story_info.buff_two; + if (challengeID > 30000) + challenge_buffID = req.stage_info.?.IEICDGGELNE.?.boss_info.buff_two; } + var lineup_manager = ChallengeLineupManager.init(allocator); + const lineup_info = try lineup_manager.createLineup(avatar_list); - var cur_challenge_info = protocol.CurChallenge.init(allocator); - cur_challenge_info.challenge_id = req.challenge_id; - cur_challenge_info.score_id = if (req.challenge_id > 20000 and req.challenge_id < 30000) 40000 else 0; - cur_challenge_info.score_two = 0; - cur_challenge_info.status = protocol.ChallengeStatus.CHALLENGE_DOING; - cur_challenge_info.extra_lineup_type = if (NodeCheck.challenge_node == 0) protocol.ExtraLineupType.LINEUP_CHALLENGE else protocol.ExtraLineupType.LINEUP_CHALLENGE_2; - var planeID: u32 = 0; - var floorID: u32 = 0; - var entryID: u32 = 0; - var worldID: u32 = 0; - var monsterID: u32 = 0; - var eventID: u32 = 0; - var groupID: u32 = 0; - var maze_groupID: u32 = 0; - if (NodeCheck.challenge_node == 0) { - for (challenge_config.challenge_config.items) |challengeConf| { - if (challengeConf.id == req.challenge_id) { - std.debug.print("TRACING CONFIG ID {} WITH CHALLENGE ID {}\n", .{ challengeConf.id, req.challenge_id }); - for (entrance_config.map_entrance_config.items) |entrance| { - if (entrance.id == challengeConf.map_entrance_id) { - for (maze_config.maze_plane_config.items) |maze| { - if (contains(&maze.floor_id_list, entrance.floor_id)) { - if (req.challenge_id > 20000 and req.challenge_id < 30000) { - var story_buff = protocol.ChallengeStoryBuffList{ - .buff_list = ArrayList(u32).init(allocator), - }; - try story_buff.buff_list.append(challengeConf.maze_buff_id); - try story_buff.buff_list.append(req.stage_info.?.IEICDGGELNE.?.story_info.buff_one); - try challenge_blessing_list.appendSlice(story_buff.buff_list.items); - cur_challenge_info.stage_info = .{ - .IEICDGGELNE = .{ - .cur_story_buffs = story_buff, - }, - }; - challenge_mode = 1; - } else if (req.challenge_id > 30000) { - var boss_buff = protocol.ChallengeBossBuffList{ - .buff_list = ArrayList(u32).init(allocator), - .challenge_boss_const = 1, - }; - try boss_buff.buff_list.append(challengeConf.maze_buff_id); - try boss_buff.buff_list.append(req.stage_info.?.IEICDGGELNE.?.boss_info.buff_one); - try challenge_blessing_list.appendSlice(boss_buff.buff_list.items); - cur_challenge_info.stage_info = .{ - .IEICDGGELNE = .{ - .cur_boss_buffs = boss_buff, - }, - }; - challenge_mode = 2; - } - floorID = entrance.floor_id; - worldID = maze.world_id; - monsterID = challengeConf.npc_monster_id_list1.items[challengeConf.npc_monster_id_list1.items.len - 1]; - eventID = challengeConf.event_id_list1.items[challengeConf.event_id_list1.items.len - 1]; - groupID = challengeConf.maze_group_id1; - maze_groupID = challengeConf.maze_group_id1; - planeID = maze.challenge_plane_id; - entryID = challengeConf.map_entrance_id; - } - } - } - } - } - } - } else { - for (challenge_config.challenge_config.items) |challengeConf| { - if (challengeConf.id == req.challenge_id) { - std.debug.print("TRACING CONFIG ID {} WITH CHALLENGE ID {}\n", .{ challengeConf.id, req.challenge_id }); - for (entrance_config.map_entrance_config.items) |entrance| { - if (entrance.id == challengeConf.map_entrance_id2) { - for (maze_config.maze_plane_config.items) |maze| { - if (contains(&maze.floor_id_list, entrance.floor_id)) { - if (challengeConf.maze_group_id2) |id| { - if (req.challenge_id > 20000 and req.challenge_id < 30000) { - var story_buff = protocol.ChallengeStoryBuffList{ - .buff_list = ArrayList(u32).init(allocator), - }; - try story_buff.buff_list.append(challengeConf.maze_buff_id); - try story_buff.buff_list.append(req.stage_info.?.IEICDGGELNE.?.story_info.buff_two); - try challenge_blessing_list.appendSlice(story_buff.buff_list.items); - cur_challenge_info.stage_info = .{ - .IEICDGGELNE = .{ - .cur_story_buffs = story_buff, - }, - }; - challenge_mode = 1; - } else if (req.challenge_id > 30000) { - var boss_buff = protocol.ChallengeBossBuffList{ - .buff_list = ArrayList(u32).init(allocator), - .challenge_boss_const = 1, - }; - try boss_buff.buff_list.append(challengeConf.maze_buff_id); - try boss_buff.buff_list.append(req.stage_info.?.IEICDGGELNE.?.boss_info.buff_two); - try challenge_blessing_list.appendSlice(boss_buff.buff_list.items); - cur_challenge_info.stage_info = .{ - .IEICDGGELNE = .{ - .cur_boss_buffs = boss_buff, - }, - }; - challenge_mode = 2; - } - floorID = entrance.floor_id; - worldID = maze.world_id; - monsterID = challengeConf.npc_monster_id_list2.items[challengeConf.npc_monster_id_list2.items.len - 1]; - eventID = challengeConf.event_id_list2.items[challengeConf.event_id_list2.items.len - 1]; - groupID = id; - maze_groupID = id; - planeID = maze.challenge_plane_id; - entryID = challengeConf.map_entrance_id2; - } else { - std.debug.print("THIS CHALLENGE ID: {} DOES NOT SUPPORT 2ND NODE. PLEASE DO COMMAND /node TO SWITCH BACK TO FIRST NODE\n", .{req.challenge_id}); - } - } - } - } - } - } - } - } - var scene_PF_manager = ChallengeSceneManager.init(allocator); - const scene_info = try scene_PF_manager.createScene( - avatarList, - planeID, - floorID, - entryID, - worldID, - monsterID, - eventID, - groupID, - maze_groupID, + var challenge_manager = ChallengeManager.init(allocator); + const cur_challenge_info = try challenge_manager.createChallenge( + challengeID, + challenge_buffID, + ); + var scene_challenge_manager = ChallengeSceneManager.init(allocator); + const scene_info = try scene_challenge_manager.createScene( + avatar_list, + challenge_planeID, + challenge_floorID, + challenge_entryID, + challenge_worldID, + challenge_monsterID, + challenge_eventID, + challenge_groupID, + challenge_maze_groupID, ); rsp.retcode = 0; rsp.scene = scene_info; rsp.cur_challenge = cur_challenge_info; + try rsp.lineup_list.append(lineup_info); on_challenge = true; - challenge_stageID = eventID; - challenge_blessing = challenge_blessing_list.items[0..challenge_blessing_list.items.len]; try session.send(CmdID.CmdStartChallengeScRsp, rsp); - std.debug.print("SEND PLANE ID {} FLOOR ID {} ENTRY ID {} GROUP ID {} MAZE GROUP ID {}\n", .{ planeID, floorID, entryID, groupID, maze_groupID }); + std.debug.print("SEND PLANE ID {} FLOOR ID {} ENTRY ID {} GROUP ID {} MAZE GROUP ID {}\n", .{ + challenge_planeID, + challenge_floorID, + challenge_entryID, + challenge_groupID, + challenge_maze_groupID, + }); } diff --git a/gameserver/src/services/config.zig b/gameserver/src/services/config.zig index 4cb4ef7..ec6a1ac 100644 --- a/gameserver/src/services/config.zig +++ b/gameserver/src/services/config.zig @@ -3,7 +3,7 @@ const ArrayList = std.ArrayList; const std = @import("std"); -const BattleConfig = struct { +pub const BattleConfig = struct { battle_id: u32, stage_id: u32, cycle_count: u32, @@ -11,7 +11,7 @@ const BattleConfig = struct { monster_level: u32, blessings: ArrayList(u32), }; -const Stage = struct { +pub const Stage = struct { level: u32, stage_id: u32, monster_list: ArrayList(ArrayList(u32)), @@ -47,7 +47,7 @@ pub const Relic = struct { step4: u32, }; -const Avatar = struct { +pub const Avatar = struct { id: u32, hp: u32, sp: u32, @@ -353,10 +353,7 @@ fn parseChallengeConfig(root: std.json.Value, allocator: Allocator) ErrorSet!Cha .map_entrance_id = @intCast(challenge_json.object.get("MapEntranceID").?.integer), .map_entrance_id2 = @intCast(challenge_json.object.get("MapEntranceID2").?.integer), .maze_group_id1 = @intCast(challenge_json.object.get("MazeGroupID1").?.integer), - .maze_group_id2 = if (challenge_json.object.get("MazeGroupID2")) |val| - @intCast(val.integer) - else - null, + .maze_group_id2 = if (challenge_json.object.get("MazeGroupID2")) |val| @intCast(val.integer) else null, }; for (challenge_json.object.get("NpcMonsterIDList1").?.array.items) |npc1| { try challenge.npc_monster_id_list1.append(@intCast(npc1.integer)); @@ -435,15 +432,15 @@ fn parseRelic(relic_str: []const u8, allocator: Allocator) !Relic { const tokens_slice = tokens.items; - if (tokens_slice.len < 8) { - std.debug.print("relic parsing error: {s}\n", .{relic_str}); + if (tokens_slice.len < 5) { + std.debug.print("relic parsing critical error (too few fields): {s}\n", .{relic_str}); return error.InsufficientTokens; } const stat1 = try parseStatCount(tokens_slice[4]); - const stat2 = try parseStatCount(tokens_slice[5]); - const stat3 = try parseStatCount(tokens_slice[6]); - const stat4 = try parseStatCount(tokens_slice[7]); + const stat2 = if (tokens_slice.len > 5) try parseStatCount(tokens_slice[5]) else StatCount{ .stat = 0, .count = 0, .step = 0 }; + const stat3 = if (tokens_slice.len > 6) try parseStatCount(tokens_slice[6]) else StatCount{ .stat = 0, .count = 0, .step = 0 }; + const stat4 = if (tokens_slice.len > 7) try parseStatCount(tokens_slice[7]) else StatCount{ .stat = 0, .count = 0, .step = 0 }; const relic = Relic{ .id = try std.fmt.parseInt(u32, tokens_slice[0], 10), diff --git a/gameserver/src/services/item.zig b/gameserver/src/services/item.zig index 54251ca..a4102e7 100644 --- a/gameserver/src/services/item.zig +++ b/gameserver/src/services/item.zig @@ -5,6 +5,7 @@ const Packet = @import("../Packet.zig"); const Config = @import("config.zig"); const Data = @import("../data.zig"); const LineupManager = @import("../manager/lineup_mgr.zig").LineupManager; +const Sync = @import("../commands/sync.zig"); const ArrayList = std.ArrayList; const Allocator = std.mem.Allocator; const CmdID = protocol.CmdID; @@ -12,7 +13,6 @@ const CmdID = protocol.CmdID; pub fn onGetBag(session: *Session, _: *const Packet, allocator: Allocator) !void { const config = try Config.loadGameConfig(allocator, "config.json"); var generator = UidGenerator().init(); - // fake item inventory // TODO: make real one var rsp = protocol.GetBagScRsp.init(allocator); @@ -81,7 +81,9 @@ pub fn UidGenerator() type { pub fn init() Self { return Self{ .current_id = 0 }; } - + pub fn curId(self: *const Self) u32 { + return self.current_id; + } pub fn nextId(self: *Self) u32 { self.current_id +%= 1; // Using wrapping addition return self.current_id; diff --git a/gameserver/src/services/lineup.zig b/gameserver/src/services/lineup.zig index bdb8c60..bf44fbc 100644 --- a/gameserver/src/services/lineup.zig +++ b/gameserver/src/services/lineup.zig @@ -3,13 +3,14 @@ const protocol = @import("protocol"); const Session = @import("../Session.zig"); const Packet = @import("../Packet.zig"); const Config = @import("config.zig"); -const LineupManager = @import("../manager/lineup_mgr.zig").LineupManager; +const LineupManager = @import("../manager/lineup_mgr.zig"); +const BattleManager = @import("../manager/battle_mgr.zig"); const Allocator = std.mem.Allocator; const CmdID = protocol.CmdID; pub fn onGetCurLineupData(session: *Session, _: *const Packet, allocator: Allocator) !void { - var lineup_mgr = LineupManager.init(allocator); + var lineup_mgr = LineupManager.LineupManager.init(allocator); const lineup = try lineup_mgr.createLineup(); try session.send(CmdID.CmdGetCurLineupDataScRsp, protocol.GetCurLineupDataScRsp{ .retcode = 0, @@ -42,6 +43,17 @@ pub fn onReplaceLineup(session: *Session, packet: *const Packet, allocator: Allo }; try lineup.avatar_list.append(avatar); } + + var id_list = try allocator.alloc(u32, req.lineup_slot_list.items.len); + defer allocator.free(id_list); + for (req.lineup_slot_list.items, 0..) |slot, idx| { + if (idx >= 4) { + break; + } + id_list[idx] = slot.id; + } + try LineupManager.getSelectedAvatarID(allocator, id_list); + var rsp = protocol.SyncLineupNotify.init(allocator); rsp.Lineup = lineup; try session.send(CmdID.CmdSyncLineupNotify, rsp); diff --git a/gameserver/src/services/scene.zig b/gameserver/src/services/scene.zig index f239321..a707b9a 100644 --- a/gameserver/src/services/scene.zig +++ b/gameserver/src/services/scene.zig @@ -89,6 +89,7 @@ pub fn onGetSceneMapInfo(session: *Session, packet: *const Packet, allocator: Al rsp.retcode = 0; rsp.content_id = req.content_id; rsp.entry_story_line_id = req.entry_story_line_id; + rsp.IGFIKGHLLNO = true; var map_info = protocol.SceneMapInfo.init(allocator); try map_info.chest_list.appendSlice(chest_list); map_info.entry_id = @intCast(floor_id); @@ -146,6 +147,27 @@ pub fn onEnterSection(session: *Session, packet: *const Packet, allocator: Alloc std.debug.print("ENTER SECTION Id: {}\n", .{req.section_id}); try session.send(CmdID.CmdEnterSectionScRsp, rsp); } + +pub fn onGetEnteredScene(session: *Session, _: *const Packet, allocator: Allocator) !void { + var rsp = protocol.GetEnteredSceneScRsp.init(allocator); + var noti = protocol.EnteredSceneChangeScNotify.init(allocator); + + const entrance_config = try Config.loadMapEntranceConfig(allocator, "resources/MapEntrance.json"); + for (entrance_config.map_entrance_config.items) |entrance| { + try rsp.entered_scene_info_list.append(protocol.EnteredSceneInfo{ + .floor_id = entrance.floor_id, + .plane_id = entrance.plane_id, + }); + try noti.entered_scene_info_list.append(protocol.EnteredSceneInfo{ + .floor_id = entrance.floor_id, + .plane_id = entrance.plane_id, + }); + } + rsp.retcode = 0; + try session.send(CmdID.CmdEnteredSceneChangeScNotify, noti); + try session.send(CmdID.CmdGetEnteredSceneScRsp, rsp); +} + pub fn onSceneEntityTeleport(session: *Session, packet: *const Packet, allocator: Allocator) !void { const req = try packet.getProto(protocol.SceneEntityTeleportCsReq, allocator); var rsp = protocol.SceneEntityTeleportScRsp.init(allocator); diff --git a/hotfix.json b/hotfix.json index 3561381..9bc294d 100644 --- a/hotfix.json +++ b/hotfix.json @@ -17,10 +17,18 @@ }, "OSBETAWin3.2.53": { "asset_bundle_url": "https://autopatchos.starrails.com/asb/BetaLive/output_10104345_a5535dc0c779_a36b870100988f", - "ex_resource_url": "https://autopatchos.starrails.com/design_data/BetaLive/output_10114007_b191beeb9546_2f88552ee48ab1", + "ex_resource_url": "https://autopatchos.starrails.com/design_data/BetaLive/output_10128229_1abd7f8c3047_3cb3e1bffdb636", "ifix_url": "https://autopatchos.starrails.com/ifix/BetaLive/output_0_40d2ce0253_6d871f8bca6eb4", "ifix_version": "0", "lua_url": "https://autopatchos.starrails.com/lua/BetaLive/output_10104505_31a450a7e7a3_0793e9a5426e39", "lua_version": "" + }, + "OSBETAWin3.2.54": { + "asset_bundle_url": "https://autopatchos.starrails.com/asb/BetaLive/output_10182178_c0cbb41bb650_9e7401ee501684", + "ex_resource_url": "https://autopatchos.starrails.com/design_data/BetaLive/output_10190349_65c2a054220b_3d06b35cecd7a9", + "ifix_url": "https://autopatchos.starrails.com/ifix/BetaLive/output_10208090_dc0587466a83_7fc79b628127d3", + "ifix_version": "0", + "lua_url": "https://autopatchos.starrails.com/lua/BetaLive/output_10182439_b0ec3d3bcfc2_d9d2a226df4dd2", + "lua_version": "" } } \ No newline at end of file