mirror of
https://github.com/redstrate/Kawari.git
synced 2025-07-01 12:17:46 +00:00
Document some opcodes related to shops and implement a generic gil shopkeeper script (#85)
Document some opcodes related to shops and implement a generic gil shopkeeper script * You can now interact with shopkeepers, and if you have enough gil, you can attempt to purchase items * Upon trying to buy items the event will auto-cancel for now, because we're missing implementations of several opcodes related to inventory management
This commit is contained in:
parent
f778f9a571
commit
5a580149b4
5 changed files with 82 additions and 0 deletions
|
@ -224,6 +224,11 @@
|
|||
"name": "UnkCall",
|
||||
"opcode": 886,
|
||||
"size": 32
|
||||
},
|
||||
{
|
||||
"name": "InventoryActionAck",
|
||||
"opcode": 483,
|
||||
"size": 16
|
||||
}
|
||||
],
|
||||
"ClientZoneIpcType": [
|
||||
|
@ -361,6 +366,11 @@
|
|||
"name": "EventUnkRequest",
|
||||
"opcode": 448,
|
||||
"size": 16
|
||||
},
|
||||
{
|
||||
"name": "GilShopTransaction",
|
||||
"opcode": 108,
|
||||
"size": 24
|
||||
}
|
||||
],
|
||||
"ServerLobbyIpcType": [
|
||||
|
|
|
@ -304,6 +304,11 @@ common_events = {
|
|||
-- [721620] = "GenericGemstoneTrader.lua", -- Generic Endwalker & Dawntrail in-city gemstone traders, but they do nothing when interacted with right now
|
||||
}
|
||||
|
||||
-- NPC shops that accept gil for purchasing items
|
||||
generic_gil_shops = {
|
||||
263220, -- Neon <Air-wheeler dealer>, Solution Nine
|
||||
}
|
||||
|
||||
-- Not all Hunt NPCs are spawning right now, unfortunately.
|
||||
generic_currency_exchange = {
|
||||
1769533, -- Gold Saucer Attendant <Prize Claim> (behind counter) -> Prize Exchange (Gear)
|
||||
|
@ -377,6 +382,10 @@ for _, event_id in pairs(generic_anetshards) do
|
|||
registerEvent(event_id, "events/common/GenericAethernetShard.lua")
|
||||
end
|
||||
|
||||
for _, event_id in pairs(generic_gil_shops) do
|
||||
registerEvent(event_id, "events/common/GenericShopkeeper.lua") --TODO: It might be okay to combine gil shops with battle currency shops, still unclear
|
||||
end
|
||||
|
||||
for _, event_id in pairs(generic_currency_exchange) do
|
||||
registerEvent(event_id, "events/common/GenericHuntCurrencyExchange.lua") --TODO: Should probably rename this since it now covers other generic currency vendors like Gold Saucer ones
|
||||
end
|
||||
|
|
27
resources/scripts/events/common/GenericShopkeeper.lua
Normal file
27
resources/scripts/events/common/GenericShopkeeper.lua
Normal file
|
@ -0,0 +1,27 @@
|
|||
-- TODO: actually implement this menu
|
||||
|
||||
-- Scene 00000: NPC greeting (usually an animation, sometimes text too?)
|
||||
-- Scene 00010: Displays shop interface
|
||||
-- Scene 00255: Unknown, but this was also observed when capturing gil shop transaction packets. When used standalone it softlocks.
|
||||
|
||||
function onTalk(target, player)
|
||||
--[[ Params observed:
|
||||
Gil shops: [0, 1]
|
||||
Non- shops: [1, 0]
|
||||
MGP shops: [1, 100]
|
||||
It's unclear what these mean since shops seem to open fine without these.
|
||||
]]
|
||||
player:play_scene(target, EVENT_ID, 00000, 8192, {0})
|
||||
end
|
||||
|
||||
function onReturn(scene, results, player)
|
||||
if scene == 0 then
|
||||
--[[ Retail sends 221 zeroes as u32s as the params to the shop cutscene, but it opens fine with a single zero u32.
|
||||
Perhaps they are leftovers from earlier expansions? According to Sapphire, the params used to be significantly more complex.
|
||||
Historically, it also seems cutscene 00040 was used instead of 00010 as it is now.
|
||||
]]
|
||||
player:play_scene(player.id, EVENT_ID, 00010, 1 | 0x2000, {0})
|
||||
elseif scene == 10 then
|
||||
player:finish_event(EVENT_ID)
|
||||
end
|
||||
end
|
|
@ -786,6 +786,16 @@ async fn client_loop(
|
|||
connection.player_data.inventory.process_action(action);
|
||||
connection.send_inventory(true).await;
|
||||
}
|
||||
// TODO: Likely rename this opcode if non-gil shops also use this same opcode
|
||||
ClientZoneIpcData::GilShopTransaction { event_id, unk1: _, buy_sell_mode, item_index, item_quantity, unk2: _ } => {
|
||||
tracing::info!("Client is interacting with a shop! {event_id:#?} {buy_sell_mode:#?} {item_quantity:#?} {item_index:#?}");
|
||||
|
||||
// TODO: update the client's inventory, adjust their gil, and send the proper response packets!
|
||||
connection.send_message("Shops are not implemented yet. Cancelling event...").await;
|
||||
|
||||
// Cancel the event for now so the client doesn't get stuck
|
||||
connection.event_finish(*event_id).await;
|
||||
}
|
||||
ClientZoneIpcData::StartTalkEvent { actor_id, event_id } => {
|
||||
// load event
|
||||
{
|
||||
|
@ -811,6 +821,11 @@ async fn client_loop(
|
|||
.await;
|
||||
}
|
||||
|
||||
/* TODO: ServerZoneIpcType::Unk18 with data [64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
|
||||
* was observed to always be sent by the server upon interacting with shops. They open and function fine without
|
||||
* it, but should we send it anyway, for the sake of accuracy? It's also still unclear if this
|
||||
* happens for -every- NPC/actor. */
|
||||
|
||||
let mut should_cancel = false;
|
||||
{
|
||||
let lua = lua.lock().unwrap();
|
||||
|
|
|
@ -315,6 +315,12 @@ pub enum ServerZoneIpcData {
|
|||
#[brw(pad_after = 8)]
|
||||
unk3: u8,
|
||||
},
|
||||
#[br(pre_assert(*magic == ServerZoneIpcType::InventoryActionAck))]
|
||||
InventoryActionAck {
|
||||
sequence: u32,
|
||||
#[brw(pad_after = 12)]
|
||||
action_type: u16,
|
||||
},
|
||||
#[br(pre_assert(*magic == ServerZoneIpcType::UnkCall))]
|
||||
UnkCall {
|
||||
unk1: u32,
|
||||
|
@ -455,6 +461,21 @@ pub enum ClientZoneIpcData {
|
|||
#[brw(pad_after = 4)] // padding
|
||||
event_id: u32,
|
||||
},
|
||||
#[br(pre_assert(*magic == ClientZoneIpcType::GilShopTransaction))]
|
||||
GilShopTransaction {
|
||||
event_id: u32,
|
||||
/// Seems to always be 0x300000a at gil shops
|
||||
unk1: u32,
|
||||
/// 1 is buy, 2 is sell
|
||||
buy_sell_mode: u32,
|
||||
/// Index into the shopkeeper's or the player's inventory
|
||||
item_index: u32,
|
||||
/// Quantity of items being bought or sold
|
||||
item_quantity: u32,
|
||||
/// unk 2: Flags? These change quite a bit when dealing with stackable items, but are apparently always 0 when buying non-stackable
|
||||
/// Observed values so far: 0xDDDDDDDD (when buying 99 of a stackable item), 0xFFFFFFFF, 0xFFE0FFD0, 0xfffefffe, 0x0000FF64
|
||||
unk2: u32,
|
||||
},
|
||||
#[br(pre_assert(*magic == ClientZoneIpcType::EventYieldHandler))]
|
||||
EventYieldHandler(EventYieldHandler<2>),
|
||||
#[br(pre_assert(*magic == ClientZoneIpcType::EventYieldHandler8))]
|
||||
|
|
Loading…
Add table
Reference in a new issue