diff --git a/src/SB/Game/zTalkBox.cpp b/src/SB/Game/zTalkBox.cpp index 9e54f6fa..3e9ac625 100644 --- a/src/SB/Game/zTalkBox.cpp +++ b/src/SB/Game/zTalkBox.cpp @@ -1,6 +1,7 @@ #include "xstransvc.h" #include "zTalkBox.h" - +#include "xDebug.h" +#include "zEntPlayer.h" #include namespace @@ -105,10 +106,6 @@ namespace { } - void reset_auto_wait() - { - } - void deactivate() { stop_audio_effect(); @@ -366,33 +363,205 @@ void ztalkbox::permit(U32 add_flags, U32 remove_flags) shared.permit |= add_flags; } -void ztalkbox::load(xBase& data, xDynAsset& asset, unsigned long) +void ztalkbox::load(xBase& data, xDynAsset& asset, u32) { ((ztalkbox&)data).load((const ztalkbox::asset_type&)asset); } +void ztalkbox::load_settings(xIniFile& ini) +{ + shared.volume = xIniGetFloat(&ini, "talk_box.volume", 2.0f); + xDebugAddTweak("Talk Box|\01GlobalsGlobals|volume", &shared.volume, 0.1f, 10.0f, NULL, NULL, 0); +} + namespace { + static U8 read_bool(const substr& s, bool def) + { + extern const substr negative[6]; + extern const substr positive[6]; + if (def) + { + for (U32 i = 0; i < 6; ++i) + { + if (icompare(s, negative[i]) == 0) + return 0; + } + return 1; + } + else + { + for (U32 i = 0; i < 6; ++i) + { + if (icompare(s, positive[i]) == 0) + return 1; + } + } + return 0; + } static void parse_tag_pause(xtextbox::jot&, const xtextbox&, const xtextbox&, const xtextbox::split_tag&) { } + static void parse_tag_trap(xtextbox::jot& j, const xtextbox&, const xtextbox&, + const xtextbox::split_tag& ti) + { + bool c = 0; + + if (ti.action.size == 1 && ti.action.text[0] == '=') + { + if (read_bool(ti.value, 1) != 0) + { + c = 1; + } + } + + *(bool*)&j.context = c; + } + static void reset_tag_pause(xtextbox::jot&, const xtextbox&, const xtextbox&, const xtextbox::split_tag&) { } + static void reset_tag_sound(xtextbox::jot& j, const xtextbox&, const xtextbox& tb, + const xtextbox::split_tag&) + { + if (!shared.active) + { + return; + } + + if (&shared.active->dialog_box->tb != &tb) + { + return; + } + + sound_context& c = *(sound_context*)j.context; + + j.context_size = 24; + + c.id = 0; + c.action = sound_context::ACTION_SET; + } + static void reset_tag_trap(xtextbox::jot& j, const xtextbox&, const xtextbox& ctb, + const xtextbox::split_tag&) + { + if (!shared.active) + { + return; + } + + if (&shared.active->dialog_box->tb != &ctb) + { + return; + } + + *(bool*)&j.context = (shared.active->asset->trap != 0); + } + + static void reset_tag_allow_quit(xtextbox::jot& j, const xtextbox&, const xtextbox& ctb, + const xtextbox::split_tag&) + { + if (!shared.active) + { + return; + } + + if (&shared.active->dialog_box->tb != &ctb) + { + return; + } + + *(bool*)&j.context = (shared.active->asset->allow_quit != 0); + } U8 trigger_pause(const xtextbox::jot&) { return 1; } + U8 trigger_allow_quit(const xtextbox::jot& j) + { + shared.allow_quit = (j.context != NULL); + + return 1; + } + U8 trigger_auto_wait(const xtextbox::jot& j) + { + shared.auto_wait = *(const wait_context*)j.context; + + return 1; + } state_type::state_type(state_enum t) { type = t; } + wait_context& wait_context::operator=(const wait_context& rhs) //FIXME + { + type = rhs.type; + need = rhs.need; + delay = rhs.delay; + event_mask = rhs.event_mask; + query = rhs.query; + return *this; + } + + void stop_audio_effect() + { + if (!shared.active) + { + return; + } + + if (shared.active->asset == 0) + { + return; + } + } + static void reset_auto_wait() + { + const ztalkbox::asset_type* a = shared.active->asset; + + shared.auto_wait.type.time = a->auto_wait.type.time; + shared.auto_wait.type.prompt = a->auto_wait.type.prompt; + shared.auto_wait.type.sound = a->auto_wait.type.sound; + shared.auto_wait.type.event = a->auto_wait.type.event; + + shared.auto_wait.delay = a->auto_wait.delay; + + shared.auto_wait.need = 0; + + if (a->auto_wait.which_event <= 0 || a->auto_wait.which_event >= 32) + { + shared.auto_wait.event_mask = -1; + } + else + { + shared.auto_wait.event_mask = 1u << a->auto_wait.which_event; + } + + shared.auto_wait.query = Q_SKIP; + } + static void reset_tag_auto_wait(xtextbox::jot& j, const xtextbox&, const xtextbox& ctb, + const xtextbox::split_tag&) + { + if (!shared.active) + { + return; + } + if (&shared.active->dialog_box->tb != &ctb) + { + return; + } + + wait_context& c = *(wait_context*)j.context; + j.context_size = sizeof(wait_context); + reset_auto_wait(); + c = shared.auto_wait; + } + } // namespace void start_state_type::stop() @@ -425,3 +594,16 @@ void wait_context::reset_type() { *(U16*)&this->type = 0; } + +static U8 trigger_trap(const xtextbox::jot& j) +{ + if (j.context != 0) + { + zEntPlayerControlOff(CONTROL_OWNER_TALK_BOX); + } + else + { + zEntPlayerControlOn(CONTROL_OWNER_TALK_BOX); + } + return 1; +} diff --git a/src/SB/Game/zTalkBox.h b/src/SB/Game/zTalkBox.h index 879f4458..93b33b16 100644 --- a/src/SB/Game/zTalkBox.h +++ b/src/SB/Game/zTalkBox.h @@ -34,8 +34,8 @@ struct ztalkbox : xBase bool sound : 8; bool event : 8; } type; - F32 delay; - S32 which_event; + F32 delay; //Offset 8d3c + S32 which_event; //Offset 0x8d40 } auto_wait; struct { @@ -85,9 +85,9 @@ struct ztalkbox : xBase bool visible : 1; } flag; const asset_type* asset; - ztextbox* dialog_box; - ztextbox* prompt_box; - ztextbox* quit_box; + ztextbox* dialog_box; //Offset 0x18 + ztextbox* prompt_box; //Offset 0x1c + ztextbox* quit_box; //Offset 0x20 struct { const char* skip; @@ -145,7 +145,7 @@ namespace struct state_type { state_enum type; - + state_type(state_enum t); virtual void start(); virtual void stop(); @@ -262,11 +262,12 @@ namespace U8 event : 1; U16 pad : 12; } type; - U8 need; + U8 need; //Offset 08d3a F32 delay; - U32 event_mask; - query_enum query; + U32 event_mask; //Offset 08d40 + query_enum query; //Offset 08d44 void reset_type(); + wait_context& operator=(const wait_context& rhs); }; struct trigger_pair @@ -277,7 +278,7 @@ namespace struct shared_type { - S32 flags; + S32 flags; U32 permit; ztalkbox* active; // 0x8 state_type* state; // 0xC @@ -305,6 +306,43 @@ namespace zNPCCommon* speak_npc; // 0x8694 U32 speak_player; // 0x8698 }; + + struct sound_context + { + // total size: 0x18 + U32 id; // offset 0x0, size 0x4 + enum + { + ACTION_SET, + ACTION_PUSH, + ACTION_POP, + } action : 8; // offset 0x4, size 0x4 + enum + { + TYPE_INVALID, + TYPE_VOLUME, + TYPE_TARGET, + TYPE_ORIGIN, + } type : 8; // offset 0x4, size 0x4 + enum + { + SOURCE_MEMORY, + SOURCE_STREAM, + } source : 8; // offset 0x4, size 0x4 + U8 anim; // offset 0x7, size 0x1 + union + { // inferred + struct + { + // total size: 0x8 + float left; // offset 0x0, size 0x4 + float right; // offset 0x4, size 0x4 + } volume; // offset 0x8, size 0x8 + unsigned int target; // offset 0x8, size 0x4 + class xVec3 origin; // offset 0x8, size 0xC + }; + U32 speaker; // offset 0x14, size 0x4 + }; } // namespace #endif