继续修正任务载入

This commit is contained in:
Sancaros 2024-12-06 03:42:25 +08:00
parent 7373d98228
commit ecc9ebe098
19 changed files with 946 additions and 493 deletions

View File

@ -6,220 +6,298 @@ namespace PSO2SERVER.Models
{ {
public enum QuestType : byte public enum QuestType : byte
{ {
Unk0 = 0, Unk0 = 0, // 0x00
Extreme = 1, Extreme = 1, // 0x01
ARKS = 3, ARKS = 3, // 0x03
LimitedTime = 4, LimitedTime = 4, // 0x04
ExtremeDebug = 5, ExtremeDebug = 5, // 0x05
Blank1 = 6, Blank1 = 6, // 0x06
NetCafe = 8, NetCafe = 8, // 0x08
WarmingDebug = 9, WarmingDebug = 9, // 0x09
Blank2 = 10, Blank2 = 10, // 0x0A
Advance = 11, Advance = 11, // 0x0B
Expedition = 12, Expedition = 12, // 0x0C
FreeDebug = 13, FreeDebug = 13, // 0x0D
ArksDebug = 14, ArksDebug = 14, // 0x0E
Challenge = 16, Challenge = 16, // 0x10
Urgent = 17, Urgent = 17, // 0x11
UrgentDebug = 18, UrgentDebug = 18, // 0x12
TimeAttack = 19, TimeAttack = 19, // 0x13
TimeDebug = 20, TimeDebug = 20, // 0x14
ArksDebug2 = 21, ArksDebug2 = 21, // 0x15
ArksDebug3 = 22, ArksDebug3 = 22, // 0x16
ArksDebug4 = 23, ArksDebug4 = 23, // 0x17
ArksDebug5 = 24, ArksDebug5 = 24, // 0x18
ArksDebug6 = 25, ArksDebug6 = 25, // 0x19
ArksDebug7 = 26, ArksDebug7 = 26, // 0x1A
ArksDebug8 = 27, ArksDebug8 = 27, // 0x1B
ArksDebug9 = 28, ArksDebug9 = 28, // 0x1C
ArksDebug10 = 29, ArksDebug10 = 29, // 0x1D
Blank3 = 30, Blank3 = 30, // 0x1E
Recommended = 32, Recommended = 32, // 0x20
Ultimate = 33, Ultimate = 33, // 0x21
UltimateDebug = 34, UltimateDebug = 34, // 0x22
AGP = 35, AGP = 35, // 0x23
Bonus = 36, Bonus = 36, // 0x24
StandardTraining = 37, StandardTraining = 37,// 0x25
HunterTraining = 38, HunterTraining = 38, // 0x26
RangerTraining = 39, RangerTraining = 39, // 0x27
ForceTraining = 40, ForceTraining = 40, // 0x28
FighterTraining = 41, FighterTraining = 41, // 0x29
GunnerTraining = 42, GunnerTraining = 42, // 0x2A
TechterTraining = 43, TechterTraining = 43, // 0x2B
BraverTraining = 44, BraverTraining = 44, // 0x2C
BouncerTraining = 45, BouncerTraining = 45, // 0x2D
SummonerTraining = 46, SummonerTraining = 46,// 0x2E
AutoAccept = 47, AutoAccept = 47, // 0x2F
Ridroid = 48, Ridroid = 48, // 0x30
CafeAGP = 49, CafeAGP = 49, // 0x31
BattleBroken = 50, BattleBroken = 50, // 0x32
BusterDebug = 51, BusterDebug = 51, // 0x33
Poka12 = 52, Poka12 = 52, // 0x34
StoryEP1 = 55, StoryEP1 = 55, // 0x37
Buster = 56, Buster = 56, // 0x38
HeroTraining = 57, HeroTraining = 57, // 0x39
Amplified = 58, Amplified = 58, // 0x3A
DarkBlastTraining = 61, DarkBlastTraining = 61,// 0x3D
Endless = 62, Endless = 62, // 0x3E
Blank4 = 64, Blank4 = 64, // 0x40
PhantomTraining = 65, PhantomTraining = 65, // 0x41
AISTraining = 66, AISTraining = 66, // 0x42
DamageCalculation = 68, DamageCalculation = 68,// 0x44
EtoileTraining = 69, EtoileTraining = 69, // 0x45
Divide = 70, Divide = 70, // 0x46
Stars1 = 71, Stars1 = 71, // 0x47
Stars2 = 72, Stars2 = 72, // 0x48
Stars3 = 73, Stars3 = 73, // 0x49
Stars4 = 74, Stars4 = 74, // 0x4A
Stars5 = 75, Stars5 = 75, // 0x4B
Stars6 = 76, Stars6 = 76, // 0x4C
} }
[Flags] [Flags]
public enum QuestTypeAvailable : UInt64 public enum AvailableQuestType : ulong
{ {
None = 0x0000000000000000, EXTREME = 1UL << 1,
All = 0xFFFFFFFFFFFFFFFF, STORY_EP1 = 1UL << 2,
Extreme = 0x0000000000000002, ARKS = 1UL << 3,
StoryEP1 = 0x0000000000000004, LIMITED_TIME = 1UL << 4,
Arks = 0x0000000000000008, EXTREME_DEBUG = 1UL << 5,
Limited = 0x0000000000000010, BLANK1 = 1UL << 6,
ExtremeDebug = 0x0000000000000020, STORY_EP2 = 1UL << 7,
Blank1 = 0x0000000000000040,
StoryEP2 = 0x0000000000000080, NET_CAFE = 1UL << 8,
NetCafeLimited = 0x0000000000000100, WARMING_DEBUG = 1UL << 9,
Debug = 0x0000000000000200, BLANK2 = 1UL << 10,
Blank2 = 0x0000000000000400, ADVANCE = 1UL << 11,
Advance = 0x0000000000000800, EXPEDITION = 1UL << 12,
FreeField = 0x0000000000001000, FREE_DEBUG = 1UL << 13,
FreeDebug = 0x0000000000002000, ARKS_DEBUG = 1UL << 14,
ArksDebug1 = 0x0000000000004000, STORY_DEBUG = 1UL << 15,
StoryDebug = 0x0000000000008000,
Challange = 0x0000010000010000, CHALLENGE = 1UL << 16,
Emergency = 0x0000020000020000, URGENT = 1UL << 17,
EmergencyDebug = 0x0000040000040000, URGENT_DEBUG = 1UL << 18,
TimeAttack = 0x0000080000080000, TIME_ATTACK = 1UL << 19,
TimeDebug = 0x0000000000100000, TIME_DEBUG = 1UL << 20,
ArksDebug2 = 0x0000000000200000, ARKS_DEBUG2 = 1UL << 21,
ArksDebug3 = 0x0000000000400000, ARKS_DEBUG3 = 1UL << 22,
ArksDebug4 = 0x0000000000800000, ARKS_DEBUG4 = 1UL << 23,
ArksDebug5 = 0x0000000001000000,
ArksDebug6 = 0x0000000002000000, ARKS_DEBUG5 = 1UL << 24,
ArksDebug7 = 0x0000000004000000, ARKS_DEBUG6 = 1UL << 25,
ArksDebug8 = 0x0000000008000000, ARKS_DEBUG7 = 1UL << 26,
ArksDebug9 = 0x0000000010000000, ARKS_DEBUG8 = 1UL << 27,
ArksDebug10 = 0x0000000020000000, ARKS_DEBUG9 = 1UL << 28,
Blank3 = 0x0000000040000000, ARKS_DEBUG10 = 1UL << 29,
StoryEP3 = 0x0000000080000000, BLANK3 = 1UL << 30,
Featured = 0x0000000100000000, STORY_EP3 = 1UL << 31,
Ultimate = 0x0000000200000000,
UltimateDebug = 0x0000000400000000, RECOMMENDED = 1UL << 32,
NotSet = 0x0000000800000000, ULTIMATE = 1UL << 33,
ULTIMATE_DEBUG = 1UL << 34,
AGP = 1UL << 35,
BONUS = 1UL << 36,
UNK1 = 1UL << 37,
STANDARD_TRAINING = 1UL << 38,
HUNTER_TRAINING = 1UL << 39,
RANGER_TRAINING = 1UL << 40,
FORCE_TRAINING = 1UL << 41,
FIGHTER_TRAINING = 1UL << 42,
GUNNER_TRAINING = 1UL << 43,
TECHTER_TRAINING = 1UL << 44,
BRAVER_TRAINING = 1UL << 45,
BOUNCER_TRAINING = 1UL << 46,
SUMMONER_TRAINING = 1UL << 47,
AUTO_ACCEPT = 1UL << 48,
RIDROID = 1UL << 49,
NET_CAFE_AGP = 1UL << 50,
BATTLE_BROKEN = 1UL << 51,
BUSTER_DEBUG = 1UL << 52,
POKA12 = 1UL << 53,
UNK2 = 1UL << 54,
UNK3 = 1UL << 55,
BUSTER = 1UL << 56,
HERO_TRAINING = 1UL << 57,
AMPLIFIED = 1UL << 58,
UNK4 = 1UL << 59,
UNK5 = 1UL << 60,
DARK_BLAST_TRAINING = 1UL << 61,
ENDLESS = 1UL << 62,
UNK6 = 1UL << 63,
BLANK4 = 1UL << 64,
PHANTOM_TRAINING = 1UL << 65,
AIS_TRAINING = 1UL << 66,
UNK7 = 1UL << 67,
DAMAGE_CALC = 1UL << 68,
ETOILE_TRAINING = 1UL << 69,
DIVIDE = 1UL << 70,
STARS1 = 1UL << 71,
STARS2 = 1UL << 72,
STARS3 = 1UL << 73,
STARS4 = 1UL << 74,
STARS5 = 1UL << 75,
STARS6 = 1UL << 76,
UNK8 = 1UL << 77
} }
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public unsafe struct QuestDefiniton public unsafe struct QuestDefiniton
{ {
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32 - 8)] [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dateOrSomething; public string dateOrSomething;
public int field_18; public ObjectHeader quest_obj;
public int field_1C; public uint questNameid;
public int needsToBeNonzero; //27个uint
public int alsoGetsSetToDword; public uint field_30;
public UInt16 getsSetToWord; public uint field_34;
public UInt16 moreWordSetting; public uint field_38;
public int questNameString; public uint field_3C;
public int field_30; public uint field_40;
public int field_34; public uint field_44;
public int field_38; public uint field_48;
public int field_3C; public uint field_4C;
public int field_40; public uint field_50;
public int field_44; public uint field_54;
public int field_48; public uint field_58;
public int field_4C; public uint field_5C;
public int field_50; public uint field_60;
public int field_54; public uint field_64;
public int field_58; public uint field_68;
public int field_5C; public uint field_6C;
public int field_60; public uint field_70;
public int field_64; public uint field_74;
public int field_68; public uint field_78;
public int field_6C; public uint field_7C;
public int field_70; public uint field_80;
public int field_74; public uint field_84;
public int field_78; public uint field_88;
public int field_7C; public uint field_8C;
public int field_80; public uint field_90;
public int field_84; public uint field_94;
public int field_88; public uint field_98;
public int field_8C;
public int field_90;
public int field_94;
public int field_98;
public UInt16 field_9C; public UInt16 field_9C;
public byte field_9E; public byte field_9E;
public byte field_9F; public byte field_9F;
public int field_A0; //20个uint
public int field_A4; public uint field_A0;
public int field_A8; public uint field_A4;
public int field_AC; public uint field_A8;
public int field_B0; public uint field_AC;
public int field_B4; public uint field_B0;
public int field_B8; public uint field_B4;
public int field_BC; public uint field_B8;
public int field_C0; public uint field_BC;
public int field_C4; public uint field_C0;
public int field_C8; public uint field_C4;
public int field_CC; public uint field_C8;
public int field_D0; public uint field_CC;
public int field_D4; public uint field_D0;
public int field_D8; public uint field_D4;
public int field_DC; public uint field_D8;
public int field_E0; public uint field_DC;
public int field_E4; public uint field_E0;
public int field_E8; // Maybe a flags public uint field_E4;
public int field_EC; public uint field_E8; // Maybe a flags
public UInt16 field_F0; public uint field_EC;
public UInt16 field_F2;
public UInt16 questBitfield1; public ushort field_F0;
public byte playTime; public ushort field_F2;
public byte partyType; public QuestBitfield1 questBitfield1;
public byte difficulties;
public byte difficultiesCompleted; /// Length of the quest.
public QuestEstimatedTime playTime;
/// Party type of the quest.
public QuestPartyType partyType;
/// Available difficulties.
public QuestDifficultyType difficulties;
/// Completed difficulties.
public QuestDifficultyType difficultiesCompleted;
public byte field_FA; public byte field_FA;
public byte field_FB; /// Required level.
public byte requiredLevel; public byte req_level;
public byte field_FD; /// Required sub level.
public byte sub_class_req_level;
/// Enemy level.
public byte enemy_level;
public byte field_FE; public byte field_FE;
public byte field_FF;
/// Type of the quest.
public QuestType quest_type;
public byte field_100; public byte field_100;
public byte field_101; public byte field_101;
public byte field_102; public byte field_102;
public byte field_103; public byte field_103;
public byte field_104; public byte field_104;
public byte field_105; public byte field_105;
public UInt16 field_106;
public int field_108; public ushort field_106;
public int field_10C;
public short field_110; public uint field_108;
public uint field_10C;
public ushort field_110;
public byte field_112; public byte field_112;
public byte field_113; public byte field_113;
public QuestDefThing field_114_1;
public QuestDefThing field_114_2; //public QuestThing field_114_1;
public QuestDefThing field_114_3; //public QuestThing field_114_2;
public QuestDefThing field_114_4; //public QuestThing field_114_3;
public QuestDefThing field_114_5; //public QuestThing field_114_4;
public QuestDefThing field_114_6; //public QuestThing field_114_5;
public QuestDefThing field_114_7; //public QuestThing field_114_6;
public QuestDefThing field_114_8; //public QuestThing field_114_7;
public QuestDefThing field_114_9; //public QuestThing field_114_8;
public QuestDefThing field_114_10; //public QuestThing field_114_9;
public QuestDefThing field_114_11; //public QuestThing field_114_10;
public QuestDefThing field_114_12; //public QuestThing field_114_11;
public QuestDefThing field_114_13; //public QuestThing field_114_12;
public QuestDefThing field_114_14; //public QuestThing field_114_13;
public QuestDefThing field_114_15; //public QuestThing field_114_14;
public QuestDefThing field_114_16; //public QuestThing field_114_15;
//public QuestThing field_114_16;
public fixed byte field_114[0x320];
}
public enum QuestEstimatedTime : byte
{
Short = 1,
Medium,
Long
} }
public class Quest public class Quest
@ -235,12 +313,85 @@ namespace PSO2SERVER.Models
} }
} }
public struct QuestDefThing public struct QuestThing
{ {
public int field_0; public uint field_0;
public int field_4; public uint field_4;
public byte field_8; public byte field_8;
public byte field_9; public byte field_9;
public UInt16 field_A; public ushort field_A;
}
[Flags]
public enum QuestDifficultyType : byte
{
NORMAL = 1 << 0, // 1 0x01 (0000 0001)
HARD = 1 << 1, // 2 0x02 (0000 0010)
VERY_HARD = 1 << 2, // 4 0x04 (0000 0100)
SUPER_HARD = 1 << 3, // 8 0x08 (0000 1000)
EX_HARD = 1 << 4, // 16 0x10 (0001 0000)
ULTRA_HARD = 1 << 5, // 32 0x20 (0010 0000)
Dummy2 = 1 << 6, // 64 0x40 (0100 0000)
Dummy3 = 1 << 7 // 128 0x80 (1000 0000)
}
public enum QuestPartyType : byte
{
SoloQuest,
/// Only one party can join (up to 4 players).
SinglePartyQuest,
/// Multiple parties can join (up to 12 players).
MultiPartyQuest,
}
[Flags]
public enum QuestBitfield1 : ushort
{
MatterObjectiveQuest = 0x0001,
ClientOrderOnQuest = 0x0008,
NewQuest = 0x0100,
ClientOrder = 0x0800,
UnknownLevel = 0x1000
}
//Size: 308 bytes, confirmed in unpacker
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public unsafe struct QuestDifficulty
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
public string dateOrSomething;
public ObjectHeader quest_obj;
public uint name_id;
public byte area;
public byte planet;
public byte unk1;
public byte unk2;
public QuestDifficultyEntry difficulty1;
public QuestDifficultyEntry difficulty2;
public QuestDifficultyEntry difficulty3;
public QuestDifficultyEntry difficulty4;
public QuestDifficultyEntry difficulty5;
public QuestDifficultyEntry difficulty6;
public QuestDifficultyEntry difficulty7;
public QuestDifficultyEntry difficulty8;
}
//Size: 32, confirmed in ctor TODO
public struct QuestDifficultyEntry
{
public byte ReqLevel;
public byte SubClassReqLevel;
public byte MonsterLevel;
public byte Unk1;
public uint AbilityAdj;
public uint DmgLimit;
public uint TimeLimit;
public uint TimeLimit2;
public uint SuppTarget;
public uint Unk2;
public uint Enemy1;
public uint Unk3;
public uint Enemy2;
public uint Unk4;
} }
} }

View File

@ -76,6 +76,22 @@ namespace PSO2SERVER.Party
{ {
return members; return members;
} }
}
[Flags]
public enum PartyFlags : byte
{
/// Is the party only for friends.
FRIENDS_ONLY = 1 << 0, // 0x01
/// Is the party only for alliance members.
ALLIANCE_ONLY = 1 << 1, // 0x02
/// Limit multiplayer requests from other parties.
LIMIT_OTHERS = 1 << 2, // 0x04
/// Is the party only for a single run.
SINGLE_RUN = 1 << 3, // 0x08
/// Is the party actively looking for members.
OPEN = 1 << 4, // 0x10
/// Is the party voice chat focused.
VC_FOCUS = 1 << 6 // 0x40
} }
} }

View File

@ -0,0 +1,51 @@
using PSO2SERVER.Models;
using PSO2SERVER.Protocol.Packets;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace PSO2SERVER.Protocol.Handlers
{
[PacketHandlerAttr(0x0B, 0x17)]
public class QuestCategoryRequest : PacketHandler
{
public uint unk1 { get; set; }
public QuestType category { get; set; }
public override void HandlePacket(Client context, byte flags, byte[] data, uint position, uint size)
{
var info = string.Format("[<--] 接收到的数据 (hex): {0}字节", data.Length);
Logger.WriteHex(info, data);
var reader = new PacketReader(data, position, size);
unk1 = reader.ReadUInt32();
category = (QuestType)reader.ReadUInt32();
Logger.Write($"unk1 = {unk1} category = {category}");
// What am I doing
QuestDefiniton[] defs = new QuestDefiniton[1];
for (int i = 0; i < defs.Length; i++)
{
defs[i].dateOrSomething = "2012/01/05";
defs[i].quest_obj = new ObjectHeader(0x20, ObjectType.Quest);
defs[i].questNameid = 30010;
defs[i].playTime = QuestEstimatedTime.Short;
defs[i].partyType = QuestPartyType.SinglePartyQuest;
defs[i].difficulties = QuestDifficultyType.NORMAL | QuestDifficultyType.HARD | QuestDifficultyType.VERY_HARD | QuestDifficultyType.SUPER_HARD;
defs[i].req_level = 1;
// Not sure why but these need to be set for the quest to be enabled
defs[i].quest_type = (QuestType)0xF1;
defs[i].field_101 = 1;
}
context.SendPacket(new QuestCategoryPacket(defs));
context.SendPacket(new QuestCategoryStopperPacket());
}
}
}

View File

@ -1,38 +0,0 @@
using PSO2SERVER.Models;
using PSO2SERVER.Protocol.Packets;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace PSO2SERVER.Protocol.Handlers
{
[PacketHandlerAttr(0xB, 0x17)]
public class QuestListRequestHandler : PacketHandler
{
public override void HandlePacket(Client context, byte flags, byte[] data, uint position, uint size)
{
// What am I doing
QuestDefiniton[] defs = new QuestDefiniton[1];
for (int i = 0; i < defs.Length; i++)
{
defs[i].dateOrSomething = "2012/01/05";
defs[i].needsToBeNonzero = 0x00000020;
defs[i].getsSetToWord = 0x0000000B;
defs[i].questNameString = 30010;
defs[i].playTime = (byte)QuestListPacket.EstimatedTime.Short;
defs[i].partyType = (byte)QuestListPacket.PartyType.SinglePartyQuest;
defs[i].difficulties = (byte)QuestListPacket.Difficulties.Normal | (byte)QuestListPacket.Difficulties.hard | (byte)QuestListPacket.Difficulties.VeryHard | (byte)QuestListPacket.Difficulties.SuperHard;
defs[i].requiredLevel = 1;
// Not sure why but these need to be set for the quest to be enabled
defs[i].field_FF = 0xF1;
defs[i].field_101 = 1;
}
context.SendPacket(new QuestListPacket(defs));
context.SendPacket(new NoPayloadPacket(0xB, 0x1B));
}
}
}

View File

@ -1,15 +1,7 @@
using Org.BouncyCastle.Bcpg; using Org.BouncyCastle.Bcpg;
using Org.BouncyCastle.Utilities.Encoders;
using PSO2SERVER.Models; using PSO2SERVER.Models;
using PSO2SERVER.Protocol.Packets; using PSO2SERVER.Protocol.Packets;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using static PSO2SERVER.Protocol.Handlers.CharacterSelected;
using static PSO2SERVER.Protocol.Packets.QuestDifficultyPacket;
namespace PSO2SERVER.Protocol.Handlers namespace PSO2SERVER.Protocol.Handlers
{ {
@ -26,43 +18,50 @@ namespace PSO2SERVER.Protocol.Handlers
var reader = new PacketReader(data, position, size); var reader = new PacketReader(data, position, size);
Quests = reader.ReadList<ObjectHeader>(); var questCount = reader.ReadMagic(0xA36E, 0x10);
for (uint i = 0; i < questCount; i++)
// 现在可以对任务列表Quests进行处理
// 例如,可以记录任务的信息或进行其他处理
foreach (var quest in Quests)
{ {
if(quest.ObjectType == ObjectType.Quest) var qobj = new ObjectHeader();
{ qobj.ReadFromStream(reader);
QuestDifficulty[] diffs = new QuestDifficulty[1]; Quests.Add(qobj);
for (int i = 0; i < diffs.Length; i++)
{ // 打印每个任务的 ID 和类型,方便调试
diffs[i].dateOrSomething = "2017/2/20"; Logger.Write($"任务 ID: {qobj.ID}, 任务类型: {qobj.ObjectType}");
diffs[i].quest_obj.ID = quest.ID;
diffs[i].quest_obj.padding = 0;
diffs[i].quest_obj.ObjectType = ObjectType.Quest;
diffs[i].name_id = 30010;
diffs[i].area = 0x01;
diffs[i].planet = 0x03;
diffs[i].unk1 = 0x03;
diffs[i].unk2 = 0x00;
diffs[i].difficulty1 = new QuestDifficultyEntry();
diffs[i].difficulty2 = new QuestDifficultyEntry();
diffs[i].difficulty3 = new QuestDifficultyEntry();
diffs[i].difficulty4 = new QuestDifficultyEntry();
diffs[i].difficulty5 = new QuestDifficultyEntry();
diffs[i].difficulty6 = new QuestDifficultyEntry();
diffs[i].difficulty7 = new QuestDifficultyEntry();
diffs[i].difficulty8 = new QuestDifficultyEntry();
}
// 打印每个任务的 ID 和类型,方便调试
Logger.Write($"任务 ID: {quest.ID}, 任务类型: {quest.ObjectType}");
context.SendPacket(new QuestDifficultyPacket(diffs));
}
} }
QuestDifficulty[] diffs = new QuestDifficulty[1];
for (int i = 0; i < diffs.Length; i++)
{
diffs[i].dateOrSomething = "2012/01/05";
diffs[i].quest_obj = new ObjectHeader(0x20, ObjectType.Quest);
diffs[i].name_id = 30010;
diffs[i].area = 0x01;
diffs[i].planet = 0x03;
diffs[i].unk1 = 0x03;
diffs[i].unk2 = 0x00;
diffs[i].difficulty1 = new QuestDifficultyEntry();
diffs[i].difficulty2 = new QuestDifficultyEntry();
diffs[i].difficulty3 = new QuestDifficultyEntry();
diffs[i].difficulty4 = new QuestDifficultyEntry();
diffs[i].difficulty5 = new QuestDifficultyEntry();
diffs[i].difficulty6 = new QuestDifficultyEntry();
diffs[i].difficulty7 = new QuestDifficultyEntry();
diffs[i].difficulty8 = new QuestDifficultyEntry();
}
context.SendPacket(new QuestDifficultyPacket(diffs));
// [K873] I believe this is the correct packet, but it causes an infinite send/recieve loop, we're probably just missing something else // [K873] I believe this is the correct packet, but it causes an infinite send/recieve loop, we're probably just missing something else
context.SendPacket(new QuestDifficultySendFinishedPacket()); context.SendPacket(new QuestDifficultySendFinishedPacket());
//// 现在可以对任务列表Quests进行处理
//// 例如,可以记录任务的信息或进行其他处理
//foreach (var quest in Quests)
//{
// if(quest.ObjectType == ObjectType.Quest)
// {
// }
//}
} }
} }

View File

@ -12,7 +12,7 @@ namespace PSO2SERVER.Protocol.Handlers
{ {
public override void HandlePacket(Client context, byte flags, byte[] data, uint position, uint size) public override void HandlePacket(Client context, byte flags, byte[] data, uint position, uint size)
{ {
// Not sure what this does yet //Not sure what this does yet
context.SendPacket(new Unk4901Packet()); context.SendPacket(new Unk4901Packet());
context.SendPacket(new Unk0E65Packet()); context.SendPacket(new Unk0E65Packet());
context.SendPacket(new Unk0B22Packet()); context.SendPacket(new Unk0B22Packet());

View File

@ -1,54 +1,83 @@
using System; using System;
using PSO2SERVER.Models; using PSO2SERVER.Models;
using PSO2SERVER.Protocol.Packets; using PSO2SERVER.Protocol.Packets;
using PSO2SERVER.Party;
namespace PSO2SERVER.Protocol.Handlers namespace PSO2SERVER.Protocol.Handlers
{ {
[PacketHandlerAttr(0x0E, 0x0C)] [PacketHandlerAttr(0x0E, 0x0C)]
public class QuestDifficultyStartHandler : PacketHandler public class QuestDifficultyStartHandler : PacketHandler
{ {
public string name { get; set; }
public string password { get; set; }
public string comments { get; set; }
public string questname { get; set; }
public byte min_level { get; set; }
public byte max_level { get; set; }
public byte playstyle { get; set; }
public PartyFlags partyFlags { get; set; }
public ulong unk { get; set; }
// Go go maximum code duplication (for now) // Go go maximum code duplication (for now)
public override void HandlePacket(Client context, byte flags, byte[] data, uint position, uint size) public override void HandlePacket(Client context, byte flags, byte[] data, uint position, uint size)
{ {
var reader = new PacketReader(data, position, size);
var info = string.Format("[<--] 接收到的数据 (hex): {0}字节", data.Length); var info = string.Format("[<--] 接收到的数据 (hex): {0}字节", data.Length);
Logger.WriteHex(info, data); Logger.WriteHex(info, data);
//QuestDefiniton def = new QuestDefiniton var reader = new PacketReader(data, position, size);
//{ name = reader.ReadUtf16(0x11CB, 0x98);
// dateOrSomething = "2024/09/21", password = reader.ReadUtf16(0x11CB, 0x98);
// needsToBeNonzero = 0x00000020, comments = reader.ReadUtf16(0x11CB, 0x98);
// getsSetToWord = 0x0000000B, questname = reader.ReadUtf16(0x11CB, 0x98);
// questNameString = 30010, min_level = reader.ReadByte();
// playTime = (byte)QuestListPacket.EstimatedTime.Short, max_level = reader.ReadByte();
// partyType = (byte)QuestListPacket.PartyType.SinglePartyQuest, playstyle = reader.ReadByte();
// difficulties = (byte)QuestListPacket.Difficulties.Normal | (byte)QuestListPacket.Difficulties.hard | (byte)QuestListPacket.Difficulties.VeryHard | (byte)QuestListPacket.Difficulties.SuperHard, partyFlags = (PartyFlags)reader.ReadByte();
// requiredLevel = 1, unk = reader.ReadUInt64();
// // Not sure why but these need to be set for the quest to be enabled // 打印输出
// field_FF = 0xF1, Logger.Write($"Name: {name}");
// field_101 = 1 Logger.Write($"Password: {password}");
//}; Logger.Write($"Comments: {comments}");
Logger.Write($"Quest Name: {questname}");
Logger.Write($"Min Level: {min_level}");
Logger.Write($"Max Level: {max_level}");
Logger.Write($"Playstyle: {playstyle}");
Logger.Write($"Party Flags: {partyFlags}"); // 如果 PartyFlags 是枚举类型
Logger.Write($"Unknown Value: {unk}");
//QuestDifficultyPacket.QuestDifficulty diff = new QuestDifficultyPacket.QuestDifficulty QuestDefiniton def = new QuestDefiniton
//{ {
// dateOrSomething = "2024/09/21", dateOrSomething = "2012/01/05",
// something = 0x20, quest_obj = new ObjectHeader(0x20, ObjectType.Quest),
// something2 = 0x0B, questNameid = 30010,
// questNameString = 30010, playTime = QuestEstimatedTime.Short,
partyType = QuestPartyType.SinglePartyQuest,
difficulties = QuestDifficultyType.NORMAL | QuestDifficultyType.HARD | QuestDifficultyType.VERY_HARD | QuestDifficultyType.SUPER_HARD,
sub_class_req_level = 1,
// Not sure why but these need to be set for the quest to be enabled
quest_type = (QuestType)0xF1,
field_101 = 1
};
// // These are likely bitfields QuestDifficulty diff = new QuestDifficulty
// something3 = 0x00030301 {
//}; dateOrSomething = "2012/01/05",
quest_obj = new ObjectHeader(0x20, ObjectType.Quest),
name_id = 30010,
// These are likely bitfields
area = 0x01,
planet = 0x03,
unk1 = 0x03,
unk2 = 0x00
};
var quest = new Quest("arks_010120")
{
questDef = def
};
context.currentParty.currentQuest = quest;
context.SendPacket(new SetQuestInfoPacket(def, context._account.AccountId));
context.SendPacket(new PartySetQuestPacket(0x753A, 0, def, diff, new ObjectHeader((uint)context._account.AccountId, ObjectType.Player)));
//var quest = new Quest("arks_010120")
//{
// questDef = def
//};
//context.currentParty.currentQuest = quest;
//context.SendPacket(new SetQuestInfoPacket(def, context._account.AccountId));
//context.SendPacket(new QuestStartPacket(def, diff));
} }
} }
} }

View File

@ -81,17 +81,6 @@ namespace PSO2SERVER.Protocol
} }
} }
internal void WritePosition(PSOLocation location)
{
Write(Helper.FloatToHalfPrecision(location.RotX));
Write(Helper.FloatToHalfPrecision(location.RotY));
Write(Helper.FloatToHalfPrecision(location.RotZ));
Write(Helper.FloatToHalfPrecision(location.RotW));
Write(Helper.FloatToHalfPrecision(location.PosX));
Write(Helper.FloatToHalfPrecision(location.PosY));
Write(Helper.FloatToHalfPrecision(location.PosZ));
}
public void WriteUtf16(string str, uint xor, uint sub) public void WriteUtf16(string str, uint xor, uint sub)
{ {
if ((str == null) || (str == "") || (str.Length == 0)) if ((str == null) || (str == "") || (str.Length == 0))
@ -151,6 +140,17 @@ namespace PSO2SERVER.Protocol
} }
} }
internal void WritePosition(PSOLocation location)
{
Write(Helper.FloatToHalfPrecision(location.RotX));
Write(Helper.FloatToHalfPrecision(location.RotY));
Write(Helper.FloatToHalfPrecision(location.RotZ));
Write(Helper.FloatToHalfPrecision(location.RotW));
Write(Helper.FloatToHalfPrecision(location.PosX));
Write(Helper.FloatToHalfPrecision(location.PosY));
Write(Helper.FloatToHalfPrecision(location.PosZ));
}
public void WriteAccountHeader(uint AccountId) public void WriteAccountHeader(uint AccountId)
{ {
Write(AccountId); Write(AccountId);
@ -180,12 +180,111 @@ namespace PSO2SERVER.Protocol
return ms.ToArray(); return ms.ToArray();
} }
internal void WriteBytes(byte b, uint count) public void WriteBytes(byte b, uint count)
{ {
for(int i = 0; i < count; i++) for(int i = 0; i < count; i++)
{ {
Write(b); Write(b);
} }
} }
public void WriteByteArray(byte[] b)
{
Write(b);
}
public void WriteUintArray(uint[] array)
{
foreach (var item in array)
{
Write(item);
}
}
public void WriteIntArray(int[] array)
{
foreach (var item in array)
{
Write(item);
}
}
public void WriteFloatArray(float[] array)
{
foreach (var item in array)
{
Write(item);
}
}
public void WriteObjectHeader(ObjectHeader obj)
{
Write(obj.ID);
Write(obj.padding);
Write((ushort)obj.ObjectType);
Write(obj.MapID);
}
public void WriteObjectHeaderArray(ObjectHeader[] objlist)
{
foreach (var obj in objlist)
{
WriteObjectHeader(obj);
}
}
public void WriteObjectHeaderList(List<ObjectHeader> objlist)
{
foreach (var obj in objlist)
{
WriteObjectHeader(obj); // 直接写入每个 ObjectHeader 对象
}
}
// 支持 Guid 类型
public void WriteGuid(Guid guid)
{
Write(guid.ToByteArray());
}
// 支持 DateTime 类型
public void WriteDateTime(DateTime dateTime)
{
var timestamp = new DateTimeOffset(dateTime).ToUnixTimeSeconds();
Write(timestamp);
}
// 支持 List<T>
public void WriteList<T>(List<T> list) where T : struct
{
foreach (var item in list)
{
WriteStruct(item);
}
}
// 支持 2D 数组
public void Write2DIntArray(int[,] array)
{
for (int i = 0; i < array.GetLength(0); i++)
{
for (int j = 0; j < array.GetLength(1); j++)
{
Write(array[i, j]);
}
}
}
// 支持 2D 数组
public void Write2DUIntArray(uint[,] array)
{
for (int i = 0; i < array.GetLength(0); i++)
{
for (int j = 0; j < array.GetLength(1); j++)
{
Write(array[i, j]);
}
}
}
} }
} }

View File

@ -39,17 +39,17 @@ namespace PSO2SERVER.Protocol.Packets
public override byte[] Build() public override byte[] Build()
{ {
PacketWriter output = new PacketWriter(); PacketWriter pkt = new PacketWriter();
output.WriteStruct(new ObjectHeader((uint)_user_playerid, ObjectType.Player)); pkt.WriteStruct(new ObjectHeader((uint)_user_playerid, ObjectType.Player));
output.WriteStruct(_preformer); pkt.WriteStruct(_preformer);
output.Write(_preData); pkt.Write(_preData);
output.WriteAscii(_command, 0x4315, 0x7A); pkt.WriteAscii(_command, 0x4315, 0x7A);
output.Write(_rest); pkt.Write(_rest);
output.WriteMagic(_thingCount, 0x4315, 0x7A); pkt.WriteMagic(_thingCount, 0x4315, 0x7A);
output.Write(_things); pkt.Write(_things);
output.Write(_final); pkt.Write(_final);
return output.ToArray(); return pkt.ToArray();
} }
public override PacketHeader GetHeader() public override PacketHeader GetHeader()

View File

@ -1,4 +1,5 @@
using PSO2SERVER.Models; using Org.BouncyCastle.Utilities;
using PSO2SERVER.Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -8,9 +9,32 @@ namespace PSO2SERVER.Protocol.Packets
{ {
public class StartCutscenePacket : Packet public class StartCutscenePacket : Packet
{ {
public string scene_name { get; set; }
public uint[] unk1 { get; set; } = new uint[9];
public List<ObjectHeader> unk2 { get; set; } = new List<ObjectHeader>();
public ulong unk3 { get; set; }
public uint unk4 { get; set; }
public byte unk5 { get; set; }
public byte unk6 { get; set; }
public byte unk7 { get; set; }
public string unk8 { get; set; }
public string unk9 { get; set; }
public uint unk10 { get; set; }
public ObjectHeader unk11 { get; set; }
public StartCutscenePacket() public StartCutscenePacket(string scene_name, List<ObjectHeader> unk2, ulong unk3, uint unk4, byte unk5, byte unk6, byte unk7, string unk8, string unk9, uint unk10, ObjectHeader unk11)
{ {
this.scene_name = scene_name;
this.unk2 = unk2;
this.unk3 = unk3;
this.unk4 = unk4;
this.unk5 = unk5;
this.unk6 = unk6;
this.unk7 = unk7;
this.unk8 = unk8;
this.unk9 = unk9;
this.unk10 = unk10;
this.unk11 = unk11;
} }
#region implemented abstract members of Packet #region implemented abstract members of Packet
@ -18,6 +42,18 @@ namespace PSO2SERVER.Protocol.Packets
public override byte[] Build() public override byte[] Build()
{ {
var pkt = new PacketWriter(); var pkt = new PacketWriter();
pkt.WriteAscii(scene_name, 0xB65A, 0x7D);
pkt.WriteUintArray(unk1);
pkt.WriteObjectHeaderList(unk2);
pkt.Write(unk3);
pkt.Write(unk4);
pkt.Write(unk5);
pkt.Write(unk6);
pkt.Write(unk7);
pkt.WriteAscii(unk8, 0xB65A, 0x7D);
pkt.WriteAscii(unk9, 0xB65A, 0x7D);
pkt.Write(unk10);
pkt.WriteObjectHeader(unk11);
return pkt.ToArray(); return pkt.ToArray();
} }

View File

@ -4,45 +4,220 @@ using System.Linq;
using System.Text; using System.Text;
using PSO2SERVER.Models; using PSO2SERVER.Models;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.IO;
namespace PSO2SERVER.Protocol.Packets namespace PSO2SERVER.Protocol.Packets
{ {
class QuestAvailablePacket : Packet public class QuestAvailablePacket : Packet
{ {
public short[] amount = new short[Enum.GetValues(typeof(QuestType)).Length]; public ushort Unk1 { get; set; }
QuestTypeAvailable available = QuestTypeAvailable.Arks; public ushort ExtremeCount { get; set; }
public ushort Unk2 { get; set; }
public ushort ArksCount { get; set; }
public ushort LimitedTimeCount { get; set; }
public ushort ExtremeDebugCount { get; set; }
public ushort Blank1Count { get; set; }
public ushort Unk3 { get; set; }
public ushort NetCafeCount { get; set; }
public ushort WarmingDebugCount { get; set; }
public ushort Blank2Count { get; set; }
public ushort AdvanceCount { get; set; }
public ushort ExpeditionCount { get; set; }
public ushort ExpeditionDebugCount { get; set; }
public ushort ArksDebugCount { get; set; }
public ushort Unk4Count { get; set; }
public ushort ChallengeCount { get; set; }
public ushort UrgentCount { get; set; }
public ushort UrgentDebugCount { get; set; }
public ushort TimeAttackCount { get; set; }
public ushort TimeAttackDebugCount { get; set; }
// Array of 9 ushort values (arks_debug2_count)
public ushort[] ArksDebug2Count { get; set; } = new ushort[9];
public ushort Blank3Count { get; set; }
public ushort Unk5 { get; set; }
public ushort RecommendedCount { get; set; }
public ushort Unk6 { get; set; }
public ushort UltimateDebugCount { get; set; }
public ushort AgpCount { get; set; }
public ushort BonusCount { get; set; }
public ushort Unk7 { get; set; }
// Array of 10 ushort values (training_count)
public ushort[] TrainingCount { get; set; } = new ushort[10];
public ushort TriggerCount { get; set; }
public ushort RidroidCount { get; set; }
public ushort NetCafeAgpCount { get; set; }
public ushort BattleBrokenCount { get; set; }
public ushort BusterDebugCount { get; set; }
public ushort Poka12Count { get; set; }
public ushort Unk8 { get; set; }
public ushort Unk9 { get; set; }
public ushort BusterCount { get; set; }
public ushort HeroTrainingCount { get; set; }
public ushort AmplifiedCount { get; set; }
public ushort Unk10 { get; set; }
public ushort Unk11 { get; set; }
public ushort DarkBlastTrainingCount { get; set; }
public ushort EndlessCount { get; set; }
public ushort Unk12 { get; set; }
public ushort Unk13 { get; set; }
public ushort PhantomTrainingCount { get; set; }
public ushort AisTrainingCount { get; set; }
public ushort Unk14 { get; set; }
public ushort DamageCalcCount { get; set; }
public ushort EtoileTrainingCount { get; set; }
public ushort DivideCount { get; set; }
// Unsure fields (stars1_count, stars2_count, stars3_count)
public ushort Stars1Count { get; set; }
public ushort Stars2Count { get; set; }
public ushort Stars3Count { get; set; }
// Array of 2 ushort values (unk15)
public ushort[] Unk15 { get; set; } = new ushort[2];
// NotOn attribute is specific to certain frameworks (e.g., Vita platform)
// You can use attributes like [Obsolete] in C# if needed
public ushort[] Unk16 { get; set; } = new ushort[2];
// AvailableQuestType values
public AvailableQuestType AvailableTypes { get; set; }
public AvailableQuestType Unk19 { get; set; }
// Round boost active flag
public uint RoundBoost { get; set; }
public uint Unk21 { get; set; }
// Constructor
public QuestAvailablePacket()
{
}
//public short[] amount = new short[Enum.GetValues(typeof(QuestType)).Length];
//AvailableQuestType available = AvailableQuestType.ARKS;
public override byte[] Build() public override byte[] Build()
{ {
PacketWriter writer = new PacketWriter(); PacketWriter writer = new PacketWriter();
writer.Write(Unk1);
writer.Write(ExtremeCount);
writer.Write(Unk2);
writer.Write(ArksCount);
writer.Write(LimitedTimeCount);
writer.Write(ExtremeDebugCount);
writer.Write(Blank1Count);
writer.Write(Unk3);
writer.Write(NetCafeCount);
writer.Write(WarmingDebugCount);
writer.Write(Blank2Count);
writer.Write(AdvanceCount);
writer.Write(ExpeditionCount);
writer.Write(ExpeditionDebugCount);
writer.Write(ArksDebugCount);
writer.Write(Unk4Count);
writer.Write(ChallengeCount);
writer.Write(UrgentCount);
writer.Write(UrgentDebugCount);
writer.Write(TimeAttackCount);
writer.Write(TimeAttackDebugCount);
// Filler/Padding? // 写入 ArksDebug2Count 数组
writer.Write((UInt16)0); foreach (var count in ArksDebug2Count)
// Amounts
for (int i = 0; i < amount.Length; i++)
{ {
amount[i] = 1; // Just for testing writer.Write(count);
writer.Write(amount[i]);
} }
// Padding/Blank entries? writer.Write(Blank3Count);
for (int i = 0; i < 2; i++) writer.Write(Unk5);
writer.Write((int)0); writer.Write(RecommendedCount);
writer.Write(Unk6);
writer.Write(UltimateDebugCount);
writer.Write(AgpCount);
writer.Write(BonusCount);
writer.Write(Unk7);
// Available Bitfield // 写入 TrainingCount 数组
writer.Write((UInt64)available); foreach (var count in TrainingCount)
{
writer.Write(count);
}
// Filler/Padding? writer.Write(TriggerCount);
for (int i = 0; i < 2; i++) writer.Write(RidroidCount);
writer.Write((int)0); writer.Write(NetCafeAgpCount);
writer.Write(BattleBrokenCount);
writer.Write(BusterDebugCount);
writer.Write(Poka12Count);
writer.Write(Unk8);
writer.Write(Unk9);
writer.Write(BusterCount);
writer.Write(HeroTrainingCount);
writer.Write(AmplifiedCount);
writer.Write(Unk10);
writer.Write(Unk11);
writer.Write(DarkBlastTrainingCount);
writer.Write(EndlessCount);
writer.Write(Unk12);
writer.Write(Unk13);
writer.Write(PhantomTrainingCount);
writer.Write(AisTrainingCount);
writer.Write(Unk14);
writer.Write(DamageCalcCount);
writer.Write(EtoileTrainingCount);
writer.Write(DivideCount);
writer.Write(Stars1Count);
writer.Write(Stars2Count);
writer.Write(Stars3Count);
// 写入 Unk15 数组
foreach (var count in Unk15)
{
writer.Write(count);
}
// 写入 Unk16 数组
foreach (var count in Unk16)
{
writer.Write(count);
}
// 写入 AvailableTypes 和 Unk19 (作为枚举类型,转换为整数)
writer.Write((ulong)AvailableTypes);
writer.Write((ulong)Unk19);
writer.Write(RoundBoost);
writer.Write(Unk21);
//// Filler/Padding?
//writer.Write((UInt16)0);
//// Amounts
//for (int i = 0; i < amount.Length; i++)
//{
// amount[i] = 1; // Just for testing
// writer.Write(amount[i]);
//}
//// Padding/Blank entries?
//for (int i = 0; i < 2; i++)
// writer.Write((int)0);
//// Available Bitfield
//writer.Write((UInt64)available);
//// Filler/Padding?
//for (int i = 0; i < 2; i++)
// writer.Write((int)0);
return writer.ToArray(); return writer.ToArray();
} }
public override PacketHeader GetHeader() public override PacketHeader GetHeader()
{ {
return new PacketHeader(0x0B, 0x16); return new PacketHeader(0x0B, 0x16, PacketFlags.None);
} }
} }
} }

View File

@ -3,11 +3,11 @@ using PSO2SERVER.Models;
namespace PSO2SERVER.Protocol.Packets namespace PSO2SERVER.Protocol.Packets
{ {
class QuestListPacket : Packet public class QuestCategoryPacket : Packet
{ {
private QuestDefiniton[] questdefs; private QuestDefiniton[] questdefs;
public QuestListPacket(QuestDefiniton[] questdefs) public QuestCategoryPacket(QuestDefiniton[] questdefs)
{ {
this.questdefs = questdefs; this.questdefs = questdefs;
} }
@ -44,42 +44,5 @@ namespace PSO2SERVER.Protocol.Packets
120 -> Item Data 1? 120 -> Item Data 1?
12C -> Item Data 2? 12C -> Item Data 2?
*/ */
[Flags]
public enum QuestBitfield1 : ushort
{
MatterObjectiveQuest = 0x0001,
ClientOrderOnQuest = 0x0008,
NewQuest = 0x0100,
ClientOrder = 0x0800,
UnknownLevel = 0x1000
}
public enum PartyType
{
SoloQuest,
SinglePartyQuest,
MultiPartyQuest,
}
public enum EstimatedTime
{
Short = 1,
Medium,
Long
}
[Flags]
public enum Difficulties
{
Normal = 0x01,
hard = 0x02,
VeryHard = 0x04,
SuperHard = 0x08,
ExtraHard = 0x10,
Dummy1 = 0x20,
Dummy2 = 0x40,
Dummy3 = 0x80,
}
} }
} }

View File

@ -61,46 +61,5 @@ namespace PSO2SERVER.Protocol.Packets
{ {
return new PacketHeader(0x0B, 0x1A, PacketFlags.PACKED); return new PacketHeader(0x0B, 0x1A, PacketFlags.PACKED);
} }
//Size: 308 bytes, confirmed in unpacker
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public unsafe struct QuestDifficulty
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
public string dateOrSomething;
public ObjectHeader quest_obj;
public uint name_id;
public byte area;
public byte planet;
public byte unk1;
public byte unk2;
public QuestDifficultyEntry difficulty1;
public QuestDifficultyEntry difficulty2;
public QuestDifficultyEntry difficulty3;
public QuestDifficultyEntry difficulty4;
public QuestDifficultyEntry difficulty5;
public QuestDifficultyEntry difficulty6;
public QuestDifficultyEntry difficulty7;
public QuestDifficultyEntry difficulty8;
}
//Size: 32, confirmed in ctor TODO
public struct QuestDifficultyEntry
{
public byte ReqLevel;
public byte SubClassReqLevel;
public byte MonsterLevel;
public byte Unk1;
public uint AbilityAdj;
public uint DmgLimit;
public uint TimeLimit;
public uint TimeLimit2;
public uint SuppTarget;
public uint Unk2;
public uint Enemy1;
public uint Unk3;
public uint Enemy2;
public uint Unk4;
}
} }
} }

View File

@ -0,0 +1,24 @@
using System;
using PSO2SERVER.Models;
namespace PSO2SERVER.Protocol.Packets
{
public class QuestCategoryStopperPacket : Packet
{
/// Following: [`crate::protocol::Packet::QuestCategory`]
public QuestCategoryStopperPacket()
{
}
public override byte[] Build()
{
PacketWriter writer = new PacketWriter();
return writer.ToArray();
}
public override PacketHeader GetHeader()
{
return new PacketHeader(0x0B, 0x1B, PacketFlags.None);
}
}
}

View File

@ -49,7 +49,7 @@ namespace PSO2SERVER.Protocol.Packets
public override byte[] Build() public override byte[] Build()
{ {
PacketWriter writer = new PacketWriter(); PacketWriter writer = new PacketWriter();
writer.Write(questdef.questNameString); writer.Write(questdef.questNameid);
writer.Write(Unk1); writer.Write(Unk1);
writer.Write(Unk2); writer.Write(Unk2);
writer.Write(Unk3); writer.Write(Unk3);

View File

@ -0,0 +1,47 @@
using System;
using System.Runtime.InteropServices;
using PSO2SERVER.Models;
namespace PSO2SERVER.Protocol.Packets
{
class PartySetQuestPacket : Packet
{
public uint Name { get; set; }
public uint Difficulty { get; set; }
public QuestType QuestType { get; set; }
public QuestDefiniton QuestDefiniton { get; set; }
public QuestDifficulty QuestDifficulty { get; set; }
public ObjectHeader Player { get; set; }
public ushort unk1 { get; set; } = 0;
public ushort unk2 { get; set; } = 0;
public PartySetQuestPacket(uint name, uint difficulty, QuestDefiniton data, QuestDifficulty Questdifficulty, ObjectHeader player)
{
Name = name;
Difficulty = difficulty;
QuestDefiniton = data;
QuestDifficulty = Questdifficulty;
Player = player;
}
public override byte[] Build()
{
PacketWriter writer = new PacketWriter();
writer.Write(Name); // Unknown
writer.Write(Difficulty); // Unknown
writer.Write((uint)QuestType);
writer.WriteStruct<QuestDefiniton>(QuestDefiniton);
writer.WriteStruct<QuestDifficulty>(QuestDifficulty);
writer.WriteStruct<ObjectHeader>(Player);
writer.Write(unk1);
writer.Write(unk2);
return writer.ToArray();
}
public override PacketHeader GetHeader()
{
return new PacketHeader(0x0E, 0x31, PacketFlags.None);
}
}
}

View File

@ -1,36 +0,0 @@
using System;
using System.Runtime.InteropServices;
using PSO2SERVER.Models;
namespace PSO2SERVER.Protocol.Packets
{
class QuestStartPacket : Packet
{
QuestDefiniton data;
QuestDifficultyPacket.QuestDifficulty difficulty;
public QuestStartPacket(QuestDefiniton data, QuestDifficultyPacket.QuestDifficulty difficulty)
{
this.data = data;
this.difficulty = difficulty;
}
public override byte[] Build()
{
PacketWriter writer = new PacketWriter();
writer.Write(0x753A); // Unknown
writer.Write((int)0); // Unknown
writer.WriteStruct<QuestDefiniton>(data);
writer.WriteStruct<QuestDifficultyPacket.QuestDifficulty>(difficulty);
return writer.ToArray();
}
public override PacketHeader GetHeader()
{
return new PacketHeader(0x0E, 0x31);
}
}
}

View File

@ -206,7 +206,7 @@
<Compile Include="Protocol\Handlers\0B-QuestHandler\0B-CD-AcceptStoryQuestHandler.cs" /> <Compile Include="Protocol\Handlers\0B-QuestHandler\0B-CD-AcceptStoryQuestHandler.cs" />
<Compile Include="Protocol\Handlers\0B-QuestHandler\0B-09-MinimapRevealRequest.cs" /> <Compile Include="Protocol\Handlers\0B-QuestHandler\0B-09-MinimapRevealRequest.cs" />
<Compile Include="Protocol\Handlers\0B-QuestHandler\0B-15-QuestCounterAvailableHander.cs" /> <Compile Include="Protocol\Handlers\0B-QuestHandler\0B-15-QuestCounterAvailableHander.cs" />
<Compile Include="Protocol\Handlers\0B-QuestHandler\0B-17-QuestListRequestHandler.cs" /> <Compile Include="Protocol\Handlers\0B-QuestHandler\0B-17-QuestCategoryRequest.cs" />
<Compile Include="Protocol\Handlers\0B-QuestHandler\0B-19-QuestDifficultyRequestHandler.cs" /> <Compile Include="Protocol\Handlers\0B-QuestHandler\0B-19-QuestDifficultyRequestHandler.cs" />
<Compile Include="Protocol\Handlers\0B-QuestHandler\0B-30-QuestCounterHandler.cs" /> <Compile Include="Protocol\Handlers\0B-QuestHandler\0B-30-QuestCounterHandler.cs" />
<Compile Include="Protocol\Handlers\--UNK.cs" /> <Compile Include="Protocol\Handlers\--UNK.cs" />
@ -241,6 +241,7 @@
<Compile Include="Protocol\Handlers\4A-ARKSMisionsHandler\4A-00-MissionListRequest.cs" /> <Compile Include="Protocol\Handlers\4A-ARKSMisionsHandler\4A-00-MissionListRequest.cs" />
<Compile Include="Protocol\Handlers\4D-ClassicMissionPassHandler\4D-02-MissionPassRequest.cs" /> <Compile Include="Protocol\Handlers\4D-ClassicMissionPassHandler\4D-02-MissionPassRequest.cs" />
<Compile Include="Protocol\Handlers\4D-ClassicMissionPassHandler\4D-00-MissionPassInfoRequest.cs" /> <Compile Include="Protocol\Handlers\4D-ClassicMissionPassHandler\4D-00-MissionPassInfoRequest.cs" />
<Compile Include="Protocol\Packets\0B-QuestPacket\0B-1B-QuestCategoryStopperPacket.cs" />
<Compile Include="Protocol\Packets\1E-UnkPacket\1E-0C-Unk1E0CPacket.cs" /> <Compile Include="Protocol\Packets\1E-UnkPacket\1E-0C-Unk1E0CPacket.cs" />
<Compile Include="Protocol\Packets\0B-QuestPacket\0B-1C-QuestDifficultySendFinishedPacket.cs" /> <Compile Include="Protocol\Packets\0B-QuestPacket\0B-1C-QuestDifficultySendFinishedPacket.cs" />
<Compile Include="Protocol\Packets\0F-ItemPacket\0F-0C-LoadEquipedPacket.cs" /> <Compile Include="Protocol\Packets\0F-ItemPacket\0F-0C-LoadEquipedPacket.cs" />
@ -369,10 +370,10 @@
<Compile Include="Protocol\Packets\21-PalettePacket\21-03-FullPaletteInfoPacket.cs" /> <Compile Include="Protocol\Packets\21-PalettePacket\21-03-FullPaletteInfoPacket.cs" />
<Compile Include="Protocol\Packets\21-PalettePacket\21-01-LoadPalettePacket.cs" /> <Compile Include="Protocol\Packets\21-PalettePacket\21-01-LoadPalettePacket.cs" />
<Compile Include="Protocol\Packets\0E-PartyPacket\0E-02-PartyInitPacket.cs" /> <Compile Include="Protocol\Packets\0E-PartyPacket\0E-02-PartyInitPacket.cs" />
<Compile Include="Protocol\Packets\0E-PartyPacket\0E-31-QuestStartPacket.cs" /> <Compile Include="Protocol\Packets\0E-PartyPacket\0E-31-PartySetQuestPacket.cs" />
<Compile Include="Protocol\Packets\0B-QuestPacket\0B-1A-QuestDifficultyPacket.cs" /> <Compile Include="Protocol\Packets\0B-QuestPacket\0B-1A-QuestDifficultyPacket.cs" />
<Compile Include="Protocol\Packets\0B-QuestPacket\0B-16-QuestAvailablePacket.cs" /> <Compile Include="Protocol\Packets\0B-QuestPacket\0B-16-QuestAvailablePacket.cs" />
<Compile Include="Protocol\Packets\0B-QuestPacket\0B-18-QuestListPacket.cs" /> <Compile Include="Protocol\Packets\0B-QuestPacket\0B-18-QuestCategoryPacket.cs" />
<Compile Include="Protocol\Packets\11-ClientPacket\11-1C-SetCurrencyPacket.cs" /> <Compile Include="Protocol\Packets\11-ClientPacket\11-1C-SetCurrencyPacket.cs" />
<Compile Include="Protocol\Packets\0F-ItemPacket\0F-14-SetMesetaPacket.cs" /> <Compile Include="Protocol\Packets\0F-ItemPacket\0F-14-SetMesetaPacket.cs" />
<Compile Include="Protocol\Packets\03-ServerPacket\03-04-LoadingScreenTransitionPacket.cs" /> <Compile Include="Protocol\Packets\03-ServerPacket\03-04-LoadingScreenTransitionPacket.cs" />

View File

@ -173,25 +173,6 @@ namespace PSO2SERVER.Zone
} }
else else
{ {
//PacketWriter writer = new PacketWriter();
//writer.WriteStruct(new ObjectHeader(3, ObjectType.Map));
//writer.WriteStruct(new ObjectHeader((uint)c._account.AccountId, ObjectType.Accounts));
//writer.Write(0x1); // 8 Zeros
//writer.Write(0); // 8 Zeros
//writer.Write(~(uint)Type); // F4 FF FF FF
//writer.Write(MapID); // Map ID maybe
//writer.Write((uint)Flags);
//writer.Write(GenerationArgs.seed); // 81 8F E6 19 (Maybe seed)
//writer.Write(VariantID); // Randomgen enable / disable maybe
//writer.Write(GenerationArgs.xsize); // X Size
//writer.Write(GenerationArgs.ysize); // Y Size
//writer.Write(1);
//writer.Write(1);
//writer.Write(~0); // FF FF FF FF FF FF FF FF
//writer.Write(0x301);
//c.SendPacket(0x3, 0x0, 0x0, writer.ToArray());
var _map = new Map("", MapID, VariantID, Type, Flags); var _map = new Map("", MapID, VariantID, Type, Flags);
_map.GenerationArgs.seed = GenerationArgs.seed; _map.GenerationArgs.seed = GenerationArgs.seed;
_map.GenerationArgs.xsize = GenerationArgs.xsize; _map.GenerationArgs.xsize = GenerationArgs.xsize;
@ -254,10 +235,6 @@ namespace PSO2SERVER.Zone
foreach (Client other in Clients) foreach (Client other in Clients)
{ {
//PacketWriter writer = new PacketWriter();
//writer.WriteStruct(new ObjectHeader((uint)other._account.AccountId, ObjectType.Accounts));
//writer.WriteStruct(new ObjectHeader((uint)c._account.AccountId, ObjectType.Accounts));
//other.SendPacket(0x4, 0x3B, 0x40, writer.ToArray());
other.SendPacket(new DespawnPlayerPacket(other._account.AccountId, c._account.AccountId)); other.SendPacket(new DespawnPlayerPacket(other._account.AccountId, c._account.AccountId));
} }