diff --git a/configure.py b/configure.py index 4be6cb5ed..f85055138 100644 --- a/configure.py +++ b/configure.py @@ -492,7 +492,7 @@ def MatchingFor(*versions): Object(NonMatching, "SB/Game/zNPCSupport.cpp"), Object(NonMatching, "SB/Game/zTalkBox.cpp", extra_cflags=["-sym on"]), Object(NonMatching, "SB/Game/zTextBox.cpp"), - Object(NonMatching, "SB/Game/zTaskBox.cpp"), + Object(Equivalent, "SB/Game/zTaskBox.cpp"), Object(Matching, "SB/Core/gc/iCutscene.cpp"), Object(Matching, "SB/Game/zNPCTypeTest.cpp"), Object(NonMatching, "SB/Game/zNPCTypeSubBoss.cpp"), diff --git a/src/SB/Game/zTalkBox.h b/src/SB/Game/zTalkBox.h index 8bb5007ab..c27bfb787 100644 --- a/src/SB/Game/zTalkBox.h +++ b/src/SB/Game/zTalkBox.h @@ -50,6 +50,8 @@ struct ztalkbox : xBase ANSWER_YES, ANSWER_NO, ANSWER_3, + ANSWER_4, + ANSWER_5, }; struct callback diff --git a/src/SB/Game/zTaskBox.cpp b/src/SB/Game/zTaskBox.cpp index 8ad806d17..0c5819344 100644 --- a/src/SB/Game/zTaskBox.cpp +++ b/src/SB/Game/zTaskBox.cpp @@ -1,6 +1,7 @@ #include "zTaskBox.h" #include "xEvent.h" +#include "xGroup.h" #include "xstransvc.h" #include "zBase.h" @@ -9,34 +10,35 @@ #include -extern ztaskbox* shared; +ztaskbox::talk_callback* ztaskbox::tcb; + +namespace +{ + static ztaskbox* shared; +} void ztaskbox::load(const ztaskbox::asset_type& a) { xBaseInit((xBase*)this, &(xBaseAsset)a); - this->baseType = eBaseTypeEnv; - // FIXME: can't force const to non-const? - // this->asset = &a; - - // FIXME: Define cb_dispatch - // this->eventFunc = cb_dispatch; + this->baseType = eBaseTypeTaskBox; + this->asset = &a; + this->eventFunc = cb_dispatch; if (this->linkCount != 0) { this->link = (xLinkAsset*)(&a + 1); } - bool enabled = a.enable; this->state = STATE_INVALID; - if (!enabled) - { - this->flag.enabled = false; - this->current = NULL; - } - else + if (a.enable) { this->flag.enabled = true; this->set_state(STATE_BEGIN); this->current = this; } + else + { + this->flag.enabled = false; + this->current = NULL; + } if (a.persistent) { this->baseFlags |= 2; @@ -56,33 +58,41 @@ void ztaskbox::write(xSerial& s) s.Write((U8)this->state); } -// WIP. +// Equivalent: branching weirdness void ztaskbox::start_talk(zNPCCommon* npc) { ztaskbox* curr = this->current; if (curr != NULL) { - if (curr == this) + if (curr != this) { - if (this->flag.enabled && this->state != STATE_INVALID) - { - //TODO!!! - } + curr->set_callback(this->cb); + this->current->start_talk(NULL); } else { - curr->set_callback(this->cb); - this->current->start_talk(NULL); + if (this->flag.enabled && this->state != STATE_INVALID) + { + if (shared != NULL && shared != this) + { + shared->stop_talk(); + } + ztalkbox* talkbox = (ztalkbox*)zSceneFindObject(asset->talk_box); + if (talkbox != NULL) + { + U32 text = current->get_text(asset->stages[state]); + if (text != 0) + { + shared = this; + tcb->reset(*this); + talkbox->start_talk(text, tcb, npc); + } + } + } } } } -void ztaskbox::talk_callback::reset(ztaskbox& task) -{ - this->task = &task; - this->answer = ztalkbox::ANSWER_CONTINUE; -} - void ztaskbox::stop_talk() { ztaskbox* curr = this->current; @@ -191,15 +201,13 @@ void ztaskbox::set_callback(callback* cb) this->cb = cb; } -// WIP. +// Equivalent: scheduling void ztaskbox::init() { shared = NULL; - // STUFF. -} -ztaskbox::talk_callback::talk_callback() -{ + static talk_callback tcb; + ztaskbox::tcb = &tcb; } void ztaskbox::load(xBase& data, xDynAsset& asset, size_t num) @@ -210,7 +218,46 @@ void ztaskbox::load(xBase& data, xDynAsset& asset, size_t num) bool ztaskbox::exists(state_enum stage) { U32 state = this->asset->stages[stage]; - return state != STATE_BEGIN && xSTFindAsset(state, NULL); + return state != STATE_BEGIN && xSTFindAsset(state, NULL) != NULL; +} + +void ztaskbox::set_state(state_enum stage) +{ + this->state = stage; + this->current = this; + + switch (stage) + { + case STATE_BEGIN: + if (!exists(stage)) + { + set_state(STATE_DESCRIPTION); + } + break; + case STATE_DESCRIPTION: + if (!exists(stage)) + { + set_state(STATE_REMINDER); + } + break; + case STATE_REMINDER: + case STATE_SUCCESS: + case STATE_FAILURE: + if (!exists(stage)) + { + set_state(STATE_END); + } + break; + case STATE_END: + if (!exists(stage)) + { + set_state(STATE_INVALID); + } + break; + default: + complete(); + break; + } } void ztaskbox::on_talk_start() @@ -221,6 +268,76 @@ void ztaskbox::on_talk_start() } } +void ztaskbox::on_talk_stop(ztalkbox::answer_enum answer) +{ + switch (state) + { + case ztalkbox::ANSWER_YES: + set_state(STATE_REMINDER); + break; + case ztalkbox::ANSWER_3: + set_state(STATE_END); + break; + case ztalkbox::ANSWER_4: + if (asset->retry != 0) + { + set_state(STATE_DESCRIPTION); + } + else + { + set_state(STATE_END); + } + break; + default: + if (asset->loop != 0) + { + set_state(STATE_BEGIN); + } + break; + case ztalkbox::ANSWER_CONTINUE: + case ztalkbox::ANSWER_NO: + case ztalkbox::ANSWER_5: + break; + } + + if (cb != NULL) + { + cb->on_talk_stop(); + } +} + +U32 ztaskbox::get_text(U32 textID) +{ + U32 id = textID; + xGroup* group = (xGroup*)zSceneFindObject(textID); + if (group != NULL) + { + if (group->baseType != eBaseTypeGroup) + { + return 0; + } + + id = group->get_any(); + } + + if (id == 0) + { + return 0; + } + + // What type is this? + void* asset = xSTFindAsset(id, NULL); + if (asset == NULL) + { + return 0; + } + else + { + // HACK + return (U32)asset + 4; + } +} + S32 ztaskbox::cb_dispatch(xBase*, xBase* to, U32 event, const F32*, xBase*) { ztaskbox& taskbox = *(ztaskbox*)to; @@ -253,18 +370,3 @@ S32 ztaskbox::cb_dispatch(xBase*, xBase* to, U32 event, const F32*, xBase*) return 1; } - -void ztaskbox::talk_callback::on_start() -{ - this->task->on_talk_start(); -} - -void ztaskbox::talk_callback::on_stop() -{ - this->task->on_talk_stop(answer); -} - -void ztaskbox::talk_callback::on_answer(ztalkbox::answer_enum answer) -{ - this->answer = answer; -} diff --git a/src/SB/Game/zTaskBox.h b/src/SB/Game/zTaskBox.h index fa008550a..1b39f941f 100644 --- a/src/SB/Game/zTaskBox.h +++ b/src/SB/Game/zTaskBox.h @@ -40,11 +40,30 @@ struct ztaskbox : xBase ztaskbox* task; ztalkbox::answer_enum answer; - talk_callback(); - void reset(ztaskbox& task); - void on_start(); - void on_stop(); - void on_answer(ztalkbox::answer_enum answer); + talk_callback() + { + } + + void reset(ztaskbox& task) + { + this->task = &task; + this->answer = ztalkbox::ANSWER_CONTINUE; + } + + void on_start() + { + task->on_talk_start(); + } + + void on_stop() + { + task->on_talk_stop(answer); + } + + void on_answer(ztalkbox::answer_enum answer) + { + this->answer = answer; + } }; struct asset_type : xDynAsset @@ -59,11 +78,13 @@ struct ztaskbox : xBase }; flagData flag; - asset_type* asset; + const asset_type* asset; state_enum state; callback* cb; ztaskbox* current; + static talk_callback* tcb; + void on_talk_start(); void on_talk_stop(ztalkbox::answer_enum answer); static S32 cb_dispatch(xBase*, xBase* to, U32 event, const F32* argf, xBase*); @@ -84,6 +105,7 @@ struct ztaskbox : xBase void complete(); static void init(); bool exists(state_enum stage); + static U32 get_text(U32); }; #endif