document most quest opcodes
This commit is contained in:
+81
-55
@@ -882,7 +882,7 @@ struct SC_GameGuardCheck_BB_0022 {
|
||||
struct S_ExchangeSecretLotteryTicketResult_BB_24 {
|
||||
// These fields map to unknown_a1 and unknown_a2 in the 6xDE command (but
|
||||
// their order is swapped here).
|
||||
le_uint16_t function_id = 0;
|
||||
le_uint16_t label = 0;
|
||||
uint8_t start_index = 0;
|
||||
uint8_t unused = 0;
|
||||
parray<le_uint32_t, 8> unknown_a3;
|
||||
@@ -892,7 +892,7 @@ struct S_ExchangeSecretLotteryTicketResult_BB_24 {
|
||||
// Sent in response to a 6xE1 command from the client.
|
||||
|
||||
struct S_GallonPlanResult_BB_25 {
|
||||
le_uint16_t function_id = 0;
|
||||
le_uint16_t label = 0;
|
||||
uint8_t offset1 = 0;
|
||||
uint8_t offset2 = 0;
|
||||
uint8_t value1 = 0;
|
||||
@@ -1227,20 +1227,21 @@ struct S_JoinGameT_DC_PC {
|
||||
// field when sending this command to start an Episode 3 tournament game. This
|
||||
// can be misleading when reading old logs from those days, but the Episode 3
|
||||
// client really does ignore it.
|
||||
parray<le_uint32_t, 0x20> variations;
|
||||
/* 0004 */ parray<le_uint32_t, 0x20> variations;
|
||||
// Unlike lobby join commands, these are filled in in their slot positions.
|
||||
// That is, if there's only one player in a game with ID 2, then the first two
|
||||
// of these are blank and the player's data is in the third entry here.
|
||||
parray<LobbyDataT, 4> lobby_data;
|
||||
uint8_t client_id = 0;
|
||||
uint8_t leader_id = 0;
|
||||
uint8_t disable_udp = 1;
|
||||
uint8_t difficulty = 0;
|
||||
uint8_t battle_mode = 0;
|
||||
uint8_t event = 0;
|
||||
uint8_t section_id = 0;
|
||||
uint8_t challenge_mode = 0;
|
||||
le_uint32_t rare_seed = 0;
|
||||
/* 0084 */ parray<LobbyDataT, 4> lobby_data;
|
||||
/* 0104 */ uint8_t client_id = 0;
|
||||
/* 0105 */ uint8_t leader_id = 0;
|
||||
/* 0106 */ uint8_t disable_udp = 1;
|
||||
/* 0107 */ uint8_t difficulty = 0;
|
||||
/* 0108 */ uint8_t battle_mode = 0;
|
||||
/* 0109 */ uint8_t event = 0;
|
||||
/* 010A */ uint8_t section_id = 0;
|
||||
/* 010B */ uint8_t challenge_mode = 0;
|
||||
/* 010C */ le_uint32_t rare_seed = 0;
|
||||
/* 0110 */
|
||||
} __packed__;
|
||||
|
||||
struct S_JoinGame_DCNTE_64 {
|
||||
@@ -1454,6 +1455,8 @@ struct S_GenerateID_DC_PC_V3_80 {
|
||||
// On GC (and probably other versions too) the unused space after the text
|
||||
// contains uninitialized memory when the client sends this command. newserv
|
||||
// clears the uninitialized data for security reasons before forwarding.
|
||||
// The maximum length of the message is 170 characters, despite the field being
|
||||
// able to hold triple that amount.
|
||||
|
||||
struct SC_SimpleMail_PC_81 {
|
||||
// If player_tag and from_guild_card_number are zero, the message cannot be
|
||||
@@ -2131,10 +2134,10 @@ struct S_QuestMenuEntry_BB_A2_A4 {
|
||||
// because the following command (AB) is definitely not valid on that version.
|
||||
|
||||
struct C_SendQuestStatistic_V3_BB_AA {
|
||||
le_uint16_t stat_id1 = 0;
|
||||
le_uint16_t stat_id = 0;
|
||||
le_uint16_t unused = 0;
|
||||
le_uint16_t function_id1 = 0;
|
||||
le_uint16_t function_id2 = 0;
|
||||
le_uint16_t label1 = 0;
|
||||
le_uint16_t label2 = 0;
|
||||
parray<le_uint32_t, 8> params;
|
||||
} __packed_ws__(C_SendQuestStatistic_V3_BB_AA, 0x28);
|
||||
|
||||
@@ -2146,7 +2149,7 @@ struct C_SendQuestStatistic_V3_BB_AA {
|
||||
// presumably use this command to call any function at any time during a quest.
|
||||
|
||||
struct S_CallQuestFunction_V3_BB_AB {
|
||||
le_uint16_t function_id = 0;
|
||||
le_uint16_t label = 0;
|
||||
parray<uint8_t, 2> unused;
|
||||
} __packed_ws__(S_CallQuestFunction_V3_BB_AB, 4);
|
||||
|
||||
@@ -4105,17 +4108,17 @@ struct G_DarkFalzActions_6x19 {
|
||||
|
||||
// 6x1A: Invalid subcommand
|
||||
|
||||
// 6x1B: Unknown (not valid on Episode 3) (protected on V3/V4)
|
||||
// 6x1B: Enable PK mode for player (not valid on Episode 3) (protected on V3/V4)
|
||||
|
||||
struct G_Unknown_6x1B {
|
||||
struct G_EnablePKModeForPlayer_6x1B {
|
||||
G_ClientIDHeader header;
|
||||
} __packed_ws__(G_Unknown_6x1B, 4);
|
||||
} __packed_ws__(G_EnablePKModeForPlayer_6x1B, 4);
|
||||
|
||||
// 6x1C: Destroy NPC (protected on V3/V4)
|
||||
// 6x1C: Disable PK mode for player (protected on V3/V4)
|
||||
|
||||
struct G_DestroyNPC_6x1C {
|
||||
struct G_DisablePKModeForPlayer_6x1C {
|
||||
G_ClientIDHeader header;
|
||||
} __packed_ws__(G_DestroyNPC_6x1C, 4);
|
||||
} __packed_ws__(G_DisablePKModeForPlayer_6x1C, 4);
|
||||
|
||||
// 6x1D: Invalid subcommand
|
||||
// 6x1E: Invalid subcommand
|
||||
@@ -4753,6 +4756,24 @@ struct G_SetTelepipeState_6x68 {
|
||||
// 6x69: NPC control
|
||||
// Note: NPCs cannot be destroyed with 6x69; 6x1C is used instead for that.
|
||||
|
||||
// For commands 0 and 3, the template indexes are:
|
||||
// 0: NOL 1: CICIL 2: CICIL 3: MARACA 4: ELLY
|
||||
// 5: SHINO 6: DONOPH 7: MOME 8: ALICIA 9: ASH
|
||||
// 10: ASH 11: SUE 12: KIREEK 13: BERNIE 14: GILLIAM
|
||||
// 15: ELENOR 16: ALICIA 17: MONTAGUE 18: RUPIKA 19: MATHA
|
||||
// 20: ANNA 21: TONZLAR 22: TOBOKKE 23: GEKIGASKY 24: TYPE:O
|
||||
// 25: TYPE:W 26: GIZEL 27: DACCI 28: HOPKINS 29: DORONBO
|
||||
// 30: KROE 31: MUJO 32: RACTON 33: LIONEL 34: ZOKE
|
||||
// 35: SUE 36: NADJA 37: ELENOR 38: KIREEK 39: BERNIE
|
||||
// 40: CHRIS 41: RENEE 42: KAREN 43: BEIRON 44: NAKA
|
||||
// 45: LEO 46: HOUND 47: MADELEINE 48: VALLETTA 49: BOGARDE
|
||||
// 50: ULT 51: TYPE:I 52: TYPE:V 53: TACHIBANA 54: OSMAN
|
||||
// 55: VIVIENNE 56: BP 57: SHINTARO 58: KEN 59: TAKUYA
|
||||
// 60: SOKON 61: UKON 62: CANTONA 63: HASE
|
||||
// Created NPCs have a base level according to their template index. On Hard,
|
||||
// 25 is added to their base level; on Very Hard, 50 is added; on Ultimate, 150
|
||||
// is added. In all cases the NPC's level is clamped to [1, 199].
|
||||
|
||||
struct G_NPCControl_6x69 {
|
||||
G_UnusedHeader header;
|
||||
le_uint16_t param1; // Commands 0/3: state; command 1: npc_entity_id; command 2: unknown
|
||||
@@ -5219,17 +5240,17 @@ struct G_TriggerTrap_6x80 {
|
||||
le_uint16_t unknown_a2 = 0;
|
||||
} __packed_ws__(G_TriggerTrap_6x80, 8);
|
||||
|
||||
// 6x81: Set drop weapon on death flag (protected on V3/V4)
|
||||
// 6x81: Disable drop weapon on death (protected on V3/V4)
|
||||
|
||||
struct G_SetDropWeaponOnDeathFlag_6x81 {
|
||||
struct G_DisableDropWeaponOnDeath_6x81 {
|
||||
G_ClientIDHeader header;
|
||||
} __packed_ws__(G_SetDropWeaponOnDeathFlag_6x81, 4);
|
||||
} __packed_ws__(G_DisableDropWeaponOnDeath_6x81, 4);
|
||||
|
||||
// 6x82: Clear drop weapon on death flag (protected on V3/V4)
|
||||
// 6x82: Enable drop weapon on death (protected on V3/V4)
|
||||
|
||||
struct G_ClearDropWeaponOnDeathFlag_6x82 {
|
||||
struct G_EnableDropWeaponOnDeath_6x82 {
|
||||
G_ClientIDHeader header;
|
||||
} __packed_ws__(G_ClearDropWeaponOnDeathFlag_6x82, 4);
|
||||
} __packed_ws__(G_EnableDropWeaponOnDeath_6x82, 4);
|
||||
|
||||
// 6x83: Place trap (protected on V3/V4)
|
||||
|
||||
@@ -5445,7 +5466,7 @@ struct G_Unknown_6x9C {
|
||||
|
||||
struct G_Unknown_6x9D {
|
||||
G_UnusedHeader header;
|
||||
le_uint32_t client_id2 = 0;
|
||||
le_uint32_t client_id = 0;
|
||||
} __packed_ws__(G_Unknown_6x9D, 8);
|
||||
|
||||
// 6x9E: Play camera shutter sound
|
||||
@@ -6084,8 +6105,8 @@ struct G_ExchangeItemInQuest_BB_6xD5 {
|
||||
G_ClientIDHeader header;
|
||||
ItemData find_item; // Only data1[0]-[2] are used
|
||||
ItemData replace_item; // Only data1[0]-[2] are used
|
||||
le_uint16_t success_function_id = 0;
|
||||
le_uint16_t failure_function_id = 0;
|
||||
le_uint16_t success_label = 0;
|
||||
le_uint16_t failure_label = 0;
|
||||
} __packed_ws__(G_ExchangeItemInQuest_BB_6xD5, 0x30);
|
||||
|
||||
// 6xD6: Wrap item (BB; handled by server)
|
||||
@@ -6093,7 +6114,7 @@ struct G_ExchangeItemInQuest_BB_6xD5 {
|
||||
struct G_WrapItem_BB_6xD6 {
|
||||
G_ClientIDHeader header;
|
||||
ItemData item;
|
||||
uint8_t unknown_a1 = 0;
|
||||
uint8_t present_color = 0; // 00-0F
|
||||
parray<uint8_t, 3> unused;
|
||||
} __packed_ws__(G_WrapItem_BB_6xD6, 0x1C);
|
||||
|
||||
@@ -6103,8 +6124,8 @@ struct G_WrapItem_BB_6xD6 {
|
||||
struct G_PaganiniPhotonDropExchange_BB_6xD7 {
|
||||
G_ClientIDHeader header;
|
||||
ItemData new_item; // Only data1[0]-[2] are used
|
||||
le_uint16_t success_function_id = 0;
|
||||
le_uint16_t failure_function_id = 0;
|
||||
le_uint16_t success_label = 0;
|
||||
le_uint16_t failure_label = 0;
|
||||
} __packed_ws__(G_PaganiniPhotonDropExchange_BB_6xD7, 0x1C);
|
||||
|
||||
// 6xD8: Add S-rank weapon special (BB; handled by server)
|
||||
@@ -6115,8 +6136,8 @@ struct G_AddSRankWeaponSpecial_BB_6xD8 {
|
||||
ItemData unknown_a1; // Only data1[0]-[2] are used
|
||||
le_uint32_t item_id = 0;
|
||||
le_uint32_t special_type = 0;
|
||||
le_uint16_t success_function_id = 0;
|
||||
le_uint16_t failure_function_id = 0;
|
||||
le_uint16_t success_label = 0;
|
||||
le_uint16_t failure_label = 0;
|
||||
} __packed_ws__(G_AddSRankWeaponSpecial_BB_6xD8, 0x24);
|
||||
|
||||
// 6xD9: Momoka item exchange (BB; handled by server)
|
||||
@@ -6128,8 +6149,8 @@ struct G_MomokaItemExchange_BB_6xD9 {
|
||||
ItemData replace_item; // Only data1[0]-[2] are used
|
||||
le_uint32_t unknown_a3 = 0;
|
||||
le_uint32_t unknown_a4 = 0;
|
||||
le_uint16_t unknown_a5 = 0;
|
||||
le_uint16_t unknown_a6 = 0;
|
||||
le_uint16_t success_label = 0;
|
||||
le_uint16_t failure_label = 0;
|
||||
} __packed_ws__(G_MomokaItemExchange_BB_6xD9, 0x38);
|
||||
|
||||
// 6xDA: Upgrade weapon attribute (BB; handled by server)
|
||||
@@ -6137,13 +6158,13 @@ struct G_MomokaItemExchange_BB_6xD9 {
|
||||
|
||||
struct G_UpgradeWeaponAttribute_BB_6xDA {
|
||||
G_ClientIDHeader header;
|
||||
ItemData item; // Only data1[0-2] are used (argsA[1-3])
|
||||
le_uint32_t item_id = 0; // argsA[0]
|
||||
le_uint32_t attribute = 0; // argsA[4]
|
||||
le_uint32_t payment_count = 0; // Number of PD or PS (argsA[5])
|
||||
ItemData item; // Only data1[0-2] are used (valueB-valueD)
|
||||
le_uint32_t item_id = 0; // valueA
|
||||
le_uint32_t attribute = 0; // valueE
|
||||
le_uint32_t payment_count = 0; // Number of PD or PS (valueF)
|
||||
le_uint32_t payment_type = 0; // 0 = Photon Drops, 1 = Photon Spheres
|
||||
le_uint16_t success_function_id = 0; // argsA[6]
|
||||
le_uint16_t failure_function_id = 0; // argsA[7]
|
||||
le_uint16_t success_label = 0; // labelG
|
||||
le_uint16_t failure_label = 0; // labelH
|
||||
} __packed_ws__(G_UpgradeWeaponAttribute_BB_6xDA, 0x2C);
|
||||
|
||||
// 6xDB: Exchange item in quest (BB)
|
||||
@@ -6173,12 +6194,17 @@ struct G_SetEXPMultiplier_BB_6xDD {
|
||||
|
||||
// 6xDE: Exchange Secret Lottery Ticket (BB; handled by server)
|
||||
// The client sends this when it executes an F95C quest opcode.
|
||||
// There appears to be a bug in the client here: it sets the subcommand size to
|
||||
// 2 instead of 3, so the last relevant field (failure_label) is not sent to
|
||||
// the server.
|
||||
|
||||
struct G_ExchangeSecretLotteryTicket_BB_6xDE {
|
||||
G_ClientIDHeader header;
|
||||
uint8_t index = 0;
|
||||
uint8_t function_id1 = 0;
|
||||
le_uint16_t function_id2 = 0;
|
||||
uint8_t unknown_a1 = 0;
|
||||
le_uint16_t success_label = 0;
|
||||
// le_uint16_t failure_label = 0;
|
||||
// parray<uint8_t, 2> unused;
|
||||
} __packed_ws__(G_ExchangeSecretLotteryTicket_BB_6xDE, 8);
|
||||
|
||||
// 6xDF: Exchange Photon Crystals (BB; handled by server)
|
||||
@@ -6194,11 +6220,11 @@ struct G_ExchangePhotonCrystals_BB_6xDF {
|
||||
struct G_RequestItemDropFromQuest_BB_6xE0 {
|
||||
G_ClientIDHeader header;
|
||||
uint8_t floor = 0;
|
||||
uint8_t type = 0; // argsA[0]
|
||||
uint8_t type = 0; // valueA
|
||||
uint8_t unknown_a3 = 0;
|
||||
uint8_t unused = 0;
|
||||
le_float x = 0.0f; // argsA[1]
|
||||
le_float z = 0.0f; // argsA[2]
|
||||
le_float x = 0.0f; // valueB
|
||||
le_float z = 0.0f; // valueC
|
||||
} __packed_ws__(G_RequestItemDropFromQuest_BB_6xE0, 0x10);
|
||||
|
||||
// 6xE1: Exchange Photon Tickets (BB; handled by server)
|
||||
@@ -6206,12 +6232,12 @@ struct G_RequestItemDropFromQuest_BB_6xE0 {
|
||||
|
||||
struct G_ExchangePhotonTickets_BB_6xE1 {
|
||||
G_ClientIDHeader header;
|
||||
uint8_t unknown_a1 = 0; // argsA[0]
|
||||
uint8_t unknown_a2 = 0; // argsA[1]
|
||||
uint8_t result_index = 0; // argsA[2]
|
||||
uint8_t unknown_a1 = 0; // valueA
|
||||
uint8_t unknown_a2 = 0; // valueB
|
||||
uint8_t result_index = 0; // valueC
|
||||
uint8_t unused = 0;
|
||||
le_uint16_t function_id1 = 0; // argsA[3]
|
||||
le_uint16_t unknown_a5 = 0; // argsA[4]
|
||||
le_uint16_t success_label = 0; // valueD
|
||||
le_uint16_t failure_label = 0; // valueE
|
||||
} __packed_ws__(G_ExchangePhotonTickets_BB_6xE1, 0x0C);
|
||||
|
||||
// 6xE2: Get Meseta slot prize (BB)
|
||||
|
||||
+10
-6
@@ -142,18 +142,22 @@ bool ItemData::is_wrapped(const StackLimits& limits) const {
|
||||
}
|
||||
}
|
||||
|
||||
void ItemData::wrap(const StackLimits& limits) {
|
||||
void ItemData::wrap(const StackLimits& limits, uint8_t present_color) {
|
||||
switch (this->data1[0]) {
|
||||
case 0:
|
||||
case 1:
|
||||
this->data1[4] |= 0x40;
|
||||
this->data1[5] = (this->data1[5] & 0xF0) | (present_color & 0x0F);
|
||||
break;
|
||||
case 1:
|
||||
this->data1[4] = (this->data1[4] & 0xF0) | 0x40 | (present_color & 0x0F);
|
||||
break;
|
||||
case 2:
|
||||
// Mags cannot have custom present colors
|
||||
this->data2[2] |= 0x40;
|
||||
break;
|
||||
case 3:
|
||||
if (!this->is_stackable(limits)) {
|
||||
this->data1[3] |= 0x40;
|
||||
this->data1[3] = (this->data1[3] & 0xF0) | 0x40 | (present_color & 0x0F);
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
@@ -167,14 +171,14 @@ void ItemData::unwrap(const StackLimits& limits) {
|
||||
switch (this->data1[0]) {
|
||||
case 0:
|
||||
case 1:
|
||||
this->data1[4] &= 0xBF;
|
||||
this->data1[4] &= 0xB0;
|
||||
break;
|
||||
case 2:
|
||||
this->data2[2] &= 0xBF;
|
||||
this->data2[2] &= 0xB0;
|
||||
break;
|
||||
case 3:
|
||||
if (!this->is_stackable(limits)) {
|
||||
this->data1[3] &= 0xBF;
|
||||
this->data1[3] &= 0xB0;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
|
||||
+6
-4
@@ -77,19 +77,19 @@ struct ItemData {
|
||||
|
||||
// QUICK ITEM FORMAT REFERENCE
|
||||
// data1/0 data1/4 data1/8 data2
|
||||
// Weapon: 00ZZZZGG SS00AABB AABBAABB 00000000
|
||||
// Weapon: 00ZZZZGG SSNNAABB AABBAABB 00000000
|
||||
// Armor: 0101ZZ00 FFTTDDDD EEEE0000 00000000
|
||||
// Shield: 0102ZZ00 FFTTDDDD EEEE0000 00000000
|
||||
// Unit: 0103ZZ00 FF00RRRR 00000000 00000000
|
||||
// Mag: 02ZZLLWW HHHHIIII JJJJKKKK YYQQPPVV
|
||||
// Tool: 03ZZZZFF 00CC0000 00000000 00000000
|
||||
// Tool: 03ZZZZUU 00CC0000 00000000 00000000
|
||||
// Meseta: 04000000 00000000 00000000 MMMMMMMM
|
||||
// A = attribute type (for S-ranks, custom name)
|
||||
// B = attribute amount (for S-ranks, custom name)
|
||||
// C = stack size (for tools)
|
||||
// D = DEF bonus
|
||||
// E = EVP bonus
|
||||
// F = flags (40=present; for tools, unused if item is stackable)
|
||||
// F = armor/shield/unit flags (40=present; low 16 bits are present color)
|
||||
// G = weapon grind
|
||||
// H = mag DEF
|
||||
// I = mag POW
|
||||
@@ -97,11 +97,13 @@ struct ItemData {
|
||||
// K = mag MIND
|
||||
// L = mag level
|
||||
// M = meseta amount
|
||||
// N = present color (weapon only; for other types this is in the flags field)
|
||||
// P = mag flags (40=present, 04=has left pb, 02=has right pb, 01=has center pb)
|
||||
// Q = mag IQ
|
||||
// R = unit modifier (little-endian)
|
||||
// S = weapon flags (80=unidentified, 40=present) and special (low 6 bits)
|
||||
// T = slot count
|
||||
// U = tool flags (40=present; unused if item is stackable)
|
||||
// V = mag color
|
||||
// W = photon blasts
|
||||
// Y = mag synchro
|
||||
@@ -150,7 +152,7 @@ struct ItemData {
|
||||
uint32_t primary_identifier() const;
|
||||
|
||||
bool is_wrapped(const StackLimits& limits) const;
|
||||
void wrap(const StackLimits& limits);
|
||||
void wrap(const StackLimits& limits, uint8_t present_color);
|
||||
void unwrap(const StackLimits& limits);
|
||||
|
||||
bool is_stackable(const StackLimits& limits) const;
|
||||
|
||||
@@ -135,7 +135,7 @@ std::string ItemNameIndex::describe_item(const ItemData& item, bool include_colo
|
||||
// Armors, shields, and units (0x01) can be wrapped, as can mags (0x02) and
|
||||
// non-stackable tools (0x03). However, each of these item classes has its
|
||||
// flags in a different location.
|
||||
if (((item.data1[1] == 0x01) && (item.data1[4] & 0x40)) ||
|
||||
if (((item.data1[0] == 0x01) && (item.data1[4] & 0x40)) ||
|
||||
((item.data1[0] == 0x02) && (item.data2[2] & 0x40)) ||
|
||||
((item.data1[0] == 0x03) && !item.is_stackable(*this->limits) && (item.data1[3] & 0x40))) {
|
||||
ret_tokens.emplace_back("Wrapped");
|
||||
|
||||
+23
-47
@@ -881,78 +881,54 @@ struct BattleRules {
|
||||
LIMIT_LIVES = 2,
|
||||
};
|
||||
|
||||
// Set by quest opcode F812, but values are remapped.
|
||||
// F812 00 => FORBID_ALL
|
||||
// F812 01 => ALLOW
|
||||
// F812 02 => LIMIT_LEVEL
|
||||
// Set by quest opcode F812, but values are remapped
|
||||
/* 00 */ TechDiskMode tech_disk_mode = TechDiskMode::ALLOW;
|
||||
// Set by quest opcode F813, but values are remapped.
|
||||
// F813 00 => FORBID_ALL
|
||||
// F813 01 => ALLOW
|
||||
// F813 02 => CLEAR_AND_ALLOW
|
||||
// F813 03 => FORBID_RARES
|
||||
// Set by quest opcode F813, but values are remapped
|
||||
/* 01 */ WeaponAndArmorMode weapon_and_armor_mode = WeaponAndArmorMode::ALLOW;
|
||||
// Set by quest opcode F814, but values are remapped.
|
||||
// F814 00 => FORBID_ALL
|
||||
// F814 01 => ALLOW
|
||||
// Set by quest opcode F814, but values are remapped
|
||||
/* 02 */ MagMode mag_mode = MagMode::ALLOW;
|
||||
// Set by quest opcode F815, but values are remapped.
|
||||
// F815 00 => FORBID_ALL
|
||||
// F815 01 => ALLOW
|
||||
// F815 02 => CLEAR_AND_ALLOW
|
||||
// Set by quest opcode F815, but values are remapped
|
||||
/* 03 */ ToolMode tool_mode = ToolMode::ALLOW;
|
||||
// Set by quest opcode F816. Values are not remapped.
|
||||
// F816 00 => DEFAULT
|
||||
// F816 01 => ALL_PLAYERS
|
||||
// Set by quest opcode F816. Values are not remapped
|
||||
/* 04 */ TrapMode trap_mode = TrapMode::DEFAULT;
|
||||
// Set by quest opcode F817. Value appears to be unused in all PSO versions.
|
||||
/* 05 */ uint8_t unused_F817 = 0;
|
||||
// Set by quest opcode F818, but values are remapped.
|
||||
// F818 00 => 01
|
||||
// F818 01 => 00
|
||||
// F818 02 => 02
|
||||
// Set by quest opcode F818, but values are remapped
|
||||
/* 06 */ RespawnMode respawn_mode = RespawnMode::ALLOW;
|
||||
// Set by quest opcode F819.
|
||||
// Set by quest opcode F819
|
||||
/* 07 */ uint8_t replace_char = 0;
|
||||
// Set by quest opcode F81A, but value is inverted.
|
||||
// Set by quest opcode F81A, but value is inverted
|
||||
/* 08 */ uint8_t drop_weapon = 0;
|
||||
// Set by quest opcode F81B.
|
||||
// Set by quest opcode F81B
|
||||
/* 09 */ uint8_t is_teams = 0;
|
||||
// Set by quest opcode F852.
|
||||
// Set by quest opcode F852
|
||||
/* 0A */ uint8_t hide_target_reticle = 0;
|
||||
// Set by quest opcode F81E. Values are not remapped.
|
||||
// F81E 00 => ALLOW
|
||||
// F81E 01 => FORBID_ALL
|
||||
// F81E 02 => CLEAR_AND_ALLOW
|
||||
// Set by quest opcode F81E. Values are not remapped
|
||||
/* 0B */ MesetaMode meseta_mode = MesetaMode::ALLOW;
|
||||
// Set by quest opcode F81D.
|
||||
// Set by quest opcode F81D
|
||||
/* 0C */ uint8_t death_level_up = 0;
|
||||
// Set by quest opcode F851. The trap type is remapped:
|
||||
// F851 00 XX => set count to XX for trap type 00
|
||||
// F851 01 XX => set count to XX for trap type 02
|
||||
// F851 02 XX => set count to XX for trap type 03
|
||||
// F851 03 XX => set count to XX for trap type 01
|
||||
// Set by quest opcode F851. The trap type is remapped
|
||||
/* 0D */ parray<uint8_t, 4> trap_counts;
|
||||
// Set by quest opcode F85E.
|
||||
// Set by quest opcode F85E
|
||||
/* 11 */ uint8_t enable_sonar = 0;
|
||||
// Set by quest opcode F85F.
|
||||
// Set by quest opcode F85F
|
||||
/* 12 */ uint8_t sonar_count = 0;
|
||||
// Set by quest opcode F89E.
|
||||
// Set by quest opcode F89E
|
||||
/* 13 */ uint8_t forbid_scape_dolls = 0;
|
||||
// This value does not appear to be set by any quest opcode.
|
||||
// This value does not appear to be set by any quest opcode
|
||||
/* 14 */ le_uint32_t unknown_a1 = 0;
|
||||
// Set by quest opcode F86F.
|
||||
// Set by quest opcode F86F
|
||||
/* 18 */ le_uint32_t lives = 0;
|
||||
// Set by quest opcode F870.
|
||||
// Set by quest opcode F870
|
||||
/* 1C */ le_uint32_t max_tech_level = 0;
|
||||
// Set by quest opcode F871.
|
||||
// Set by quest opcode F871
|
||||
/* 20 */ le_uint32_t char_level = 0;
|
||||
// Set by quest opcode F872.
|
||||
// Set by quest opcode F872
|
||||
/* 24 */ le_uint32_t time_limit = 0;
|
||||
// Set by quest opcode F8A8.
|
||||
// Set by quest opcode F8A8
|
||||
/* 28 */ le_uint16_t death_tech_level_up = 0;
|
||||
/* 2A */ parray<uint8_t, 2> unused;
|
||||
// Set by quest opcode F86B.
|
||||
// Set by quest opcode F86B
|
||||
/* 2C */ le_uint32_t box_drop_area = 0;
|
||||
/* 30 */
|
||||
|
||||
|
||||
+1897
-502
File diff suppressed because it is too large
Load Diff
@@ -3031,8 +3031,8 @@ static void on_AA(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Send the right value here. (When should we send function_id2?)
|
||||
send_quest_function_call(c, cmd.function_id1);
|
||||
// TODO: Send the right value here. (When should we send label2?)
|
||||
send_quest_function_call(c, cmd.label1);
|
||||
}
|
||||
|
||||
static void on_D7_GC(shared_ptr<Client> c, uint16_t, uint32_t, string& data) {
|
||||
|
||||
+11
-11
@@ -4214,11 +4214,11 @@ static void on_quest_exchange_item_bb(shared_ptr<Client> c, uint8_t, uint8_t, vo
|
||||
p->add_item(new_item, limits);
|
||||
send_create_inventory_item_to_lobby(c, c->lobby_client_id, new_item);
|
||||
|
||||
send_quest_function_call(c, cmd.success_function_id);
|
||||
send_quest_function_call(c, cmd.success_label);
|
||||
|
||||
} catch (const exception& e) {
|
||||
c->log.warning("Quest item exchange failed: %s", e.what());
|
||||
send_quest_function_call(c, cmd.failure_function_id);
|
||||
send_quest_function_call(c, cmd.failure_label);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4232,7 +4232,7 @@ static void on_wrap_item_bb(shared_ptr<Client> c, uint8_t, uint8_t, void* data,
|
||||
auto p = c->character();
|
||||
auto item = p->remove_item(cmd.item.id, 1, *s->item_stack_limits(c->version()));
|
||||
send_destroy_item_to_lobby(c, item.id, 1);
|
||||
item.wrap(*s->item_stack_limits(c->version()));
|
||||
item.wrap(*s->item_stack_limits(c->version()), cmd.present_color);
|
||||
p->add_item(item, *s->item_stack_limits(c->version()));
|
||||
send_create_inventory_item_to_lobby(c, c->lobby_client_id, item);
|
||||
}
|
||||
@@ -4260,11 +4260,11 @@ static void on_photon_drop_exchange_for_item_bb(shared_ptr<Client> c, uint8_t, u
|
||||
p->add_item(new_item, limits);
|
||||
send_create_inventory_item_to_lobby(c, c->lobby_client_id, new_item);
|
||||
|
||||
send_quest_function_call(c, cmd.success_function_id);
|
||||
send_quest_function_call(c, cmd.success_label);
|
||||
|
||||
} catch (const exception& e) {
|
||||
c->log.warning("Quest Photon Drop exchange for item failed: %s", e.what());
|
||||
send_quest_function_call(c, cmd.failure_function_id);
|
||||
send_quest_function_call(c, cmd.failure_label);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4296,11 +4296,11 @@ static void on_photon_drop_exchange_for_s_rank_special_bb(shared_ptr<Client> c,
|
||||
p->add_item(item, limits);
|
||||
send_create_inventory_item_to_lobby(c, c->lobby_client_id, item);
|
||||
|
||||
send_quest_function_call(c, cmd.success_function_id);
|
||||
send_quest_function_call(c, cmd.success_label);
|
||||
|
||||
} catch (const exception& e) {
|
||||
c->log.warning("Quest Photon Drop exchange for S-rank special failed: %s", e.what());
|
||||
send_quest_function_call(c, cmd.failure_function_id);
|
||||
send_quest_function_call(c, cmd.failure_label);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4350,7 +4350,7 @@ static void on_secret_lottery_ticket_exchange_bb(shared_ptr<Client> c, uint8_t,
|
||||
|
||||
S_ExchangeSecretLotteryTicketResult_BB_24 out_cmd;
|
||||
out_cmd.start_index = cmd.index;
|
||||
out_cmd.function_id = cmd.function_id1;
|
||||
out_cmd.label = cmd.success_label;
|
||||
if (s->secret_lottery_results.empty()) {
|
||||
out_cmd.unknown_a3.clear(0);
|
||||
} else if (s->secret_lottery_results.size() == 1) {
|
||||
@@ -4448,7 +4448,7 @@ static void on_quest_F95F_result_bb(shared_ptr<Client> c, uint8_t, uint8_t, void
|
||||
send_create_inventory_item_to_lobby(c, c->lobby_client_id, new_item);
|
||||
|
||||
S_GallonPlanResult_BB_25 out_cmd;
|
||||
out_cmd.function_id = cmd.function_id1;
|
||||
out_cmd.label = cmd.success_label;
|
||||
out_cmd.offset1 = 0x3C;
|
||||
out_cmd.offset2 = 0x08;
|
||||
out_cmd.value1 = 0x00;
|
||||
@@ -4605,11 +4605,11 @@ static void on_upgrade_weapon_attribute_bb(shared_ptr<Client> c, uint8_t, uint8_
|
||||
|
||||
send_destroy_item_to_lobby(c, item.id, 1);
|
||||
send_create_inventory_item_to_lobby(c, c->lobby_client_id, item);
|
||||
send_quest_function_call(c, cmd.success_function_id);
|
||||
send_quest_function_call(c, cmd.success_label);
|
||||
|
||||
} catch (const exception& e) {
|
||||
c->log.warning("Weapon attribute upgrade failed: %s", e.what());
|
||||
send_quest_function_call(c, cmd.failure_function_id);
|
||||
send_quest_function_call(c, cmd.failure_label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -3132,14 +3132,14 @@ void send_rare_enemy_index_list(shared_ptr<Client> c, const vector<size_t>& inde
|
||||
send_command_t(c, 0xDE, 0x00, cmd);
|
||||
}
|
||||
|
||||
void send_quest_function_call(Channel& ch, uint16_t function_id) {
|
||||
void send_quest_function_call(Channel& ch, uint16_t label) {
|
||||
S_CallQuestFunction_V3_BB_AB cmd;
|
||||
cmd.function_id = function_id;
|
||||
cmd.label = label;
|
||||
ch.send(0xAB, 0x00, &cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
void send_quest_function_call(shared_ptr<Client> c, uint16_t function_id) {
|
||||
send_quest_function_call(c->channel, function_id);
|
||||
void send_quest_function_call(shared_ptr<Client> c, uint16_t label) {
|
||||
send_quest_function_call(c->channel, label);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+2
-2
@@ -373,8 +373,8 @@ void send_give_experience(std::shared_ptr<Client> c, uint32_t amount);
|
||||
void send_set_exp_multiplier(std::shared_ptr<Lobby> l);
|
||||
void send_rare_enemy_index_list(std::shared_ptr<Client> c, const std::vector<size_t>& indexes);
|
||||
|
||||
void send_quest_function_call(Channel& ch, uint16_t function_id);
|
||||
void send_quest_function_call(std::shared_ptr<Client> c, uint16_t function_id);
|
||||
void send_quest_function_call(Channel& ch, uint16_t label);
|
||||
void send_quest_function_call(std::shared_ptr<Client> c, uint16_t label);
|
||||
|
||||
void send_ep3_card_list_update(std::shared_ptr<Client> c);
|
||||
void send_ep3_media_update(
|
||||
|
||||
Reference in New Issue
Block a user