Skip to content

Commit

Permalink
add on_quest_step callbacks
Browse files Browse the repository at this point in the history
  • Loading branch information
jube committed Nov 12, 2024
1 parent ccfb075 commit 5a11910
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 5 deletions.
24 changes: 23 additions & 1 deletion code/bits/Script.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#include "Akagoria.h"
#include "QuestState.h"
#include "agate.h"

namespace akgr {

Expand Down Expand Up @@ -129,7 +130,7 @@ namespace akgr {

Script::~Script()
{
for (auto* handle : { m_method_on_dialog, m_method_on_message, m_method_on_quest, m_method_start, m_method_initialize, m_class_adventure }) {
for (auto* handle : { m_method_on_dialog, m_method_on_message, m_method_on_quest, m_method_on_quest_step, m_method_start, m_method_initialize, m_class_adventure }) {
if (handle != nullptr) {
agateReleaseHandle(m_vm, handle);
}
Expand Down Expand Up @@ -184,6 +185,8 @@ namespace akgr {
assert(m_method_on_dialog);
m_method_on_quest = agateMakeCallHandle(m_vm, "on_quest(_)");
assert(m_method_on_quest);
m_method_on_quest_step = agateMakeCallHandle(m_vm, "on_quest_step(_,_)");
assert(m_method_on_quest_step);
}

const char* Script::load_module(std::filesystem::path name)
Expand Down Expand Up @@ -275,6 +278,25 @@ namespace akgr {
}
}

void Script::on_quest_step(const std::string& name, std::size_t step)
{
gf::Log::info("[SCRIPT] Adventure.on_quest_step({}, {})", name, step);

agateStackStart(m_vm);
ptrdiff_t arg0 = agateSlotAllocate(m_vm);
agateSlotSetHandle(m_vm, arg0, m_class_adventure);
ptrdiff_t arg1 = agateSlotAllocate(m_vm);
agateSlotSetString(m_vm, arg1, name.c_str());
ptrdiff_t arg2 = agateSlotAllocate(m_vm);
agateSlotSetInt(m_vm, arg2, int64_t(step));
AgateStatus result = agateCallHandle(m_vm, m_method_on_quest_step);
agateStackFinish(m_vm);

if (result != AGATE_STATUS_OK) {
gf::Log::error("Could not execute 'Adventure.on_quest_step(_,_)'");
}
}

void Script::on_message_deferred(std::string name)
{
m_messages.push(std::move(name));
Expand Down
2 changes: 2 additions & 0 deletions code/bits/Script.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ namespace akgr {
void on_message(const std::string& name);
void on_dialog(const std::string& name);
void on_quest(const std::string& name);
void on_quest_step(const std::string& name, std::size_t step);

void on_message_deferred(std::string name);
void handle_deferred_messages();
Expand Down Expand Up @@ -82,6 +83,7 @@ namespace akgr {
AgateHandle* m_method_on_message = nullptr;
AgateHandle* m_method_on_dialog = nullptr;
AgateHandle* m_method_on_quest = nullptr;
AgateHandle* m_method_on_quest_step = nullptr;

std::queue<std::string> m_messages;
};
Expand Down
12 changes: 12 additions & 0 deletions code/bits/WorldModel.cc
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,13 @@ namespace akgr {
template<typename Predicate>
void WorldModel::check_quest(QuestType type, Predicate predicate)
{
struct QuestStepInfo {
std::string name;
std::size_t step;
};

std::optional<std::string> finished_quest;
std::optional<QuestStepInfo> finished_quest_step;

for (auto& quest : state.hero.quests) {
if (quest.status == QuestStatus::Finished) {
Expand All @@ -270,13 +276,19 @@ namespace akgr {
finished_quest = quest.data->label.tag;
}

finished_quest_step = { quest.data->label.tag, quest.current_step };
break;
}
}

// get out of the loop because the script can add a new quest
// and invalidate the current iterator

if (finished_quest_step) {
const QuestStepInfo& info = *finished_quest_step;
runtime.script.on_quest_step(info.name, info.step);
}

if (finished_quest) {
// TODO: automatic notification for the end of the quest?
runtime.script.on_quest(*finished_quest);
Expand Down
31 changes: 31 additions & 0 deletions data/akagoria/scripts/adventure.agate
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class Adventure {
@@messages = { }
@@dialogs = { }
@@quests = { }
@@quest_steps = { }

# special messages

Expand Down Expand Up @@ -81,6 +82,21 @@ class Adventure {
}
}

static on_quest_step(quest, step) {
def callback_array = @@quest_steps[quest]

if (callback_array) {
def callback = callback_array[step]

if (callback) {
callback()
return
}
}

IO.println("No callback for quest step '%(quest)/%(step)'")
}

#
# Others
#
Expand All @@ -96,4 +112,19 @@ class Adventure {
static add_quest_callback(quest, fn) {
@@quests[quest] = fn
}

static add_quest_step_callback(quest, step, fn) {
def quest_steps = @@quest_steps[quest]

if (!quest_steps) {
quest_steps = @@quest_steps[quest] = []
}

while (step >= quest_steps.size) {
quest_steps.append(nil)
}

quest_steps[step] = fn
}

}
7 changes: 7 additions & 0 deletions data/akagoria/scripts/chapter1.agate
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ class Chapter1 {
A.add_message_callback("ShagirConversation1") {
# W.add_dialog_to_character("ShagirConversation1", "Shagir")
}

A.add_quest_step_callback("Intro0", 1) {
W.add_item("GemRuby#1", "GemRuby", "GemRubyLocation#1")
W.add_item("GemRuby#2", "GemRuby", "GemRubyLocation#2")
W.add_item("GemRuby#3", "GemRuby", "GemRubyLocation#3")
W.add_item("GemRuby#4", "GemRuby", "GemRubyLocation#4")
}
}

}
4 changes: 0 additions & 4 deletions data/akagoria/scripts/kickoff.agate
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ class Kickoff {
W.post_notification("Welcome")
W.start_quest("Intro0")

W.add_item("GemRuby#1", "GemRuby", "GemRubyLocation#1")
W.add_item("GemRuby#2", "GemRuby", "GemRubyLocation#2")
W.add_item("GemRuby#3", "GemRuby", "GemRubyLocation#3")
W.add_item("GemRuby#4", "GemRuby", "GemRubyLocation#4")
# W.add_item("GemEmerald", "Emerald #1")
# W.add_item_to_inventory("GemEmerald")
# W.add_item_to_inventory("GemRuby")
Expand Down

0 comments on commit 5a11910

Please sign in to comment.