diff options
author | Guillaume Melquiond <guillaume.melquiond@gmail.com> | 2007-08-28 17:03:44 +0000 |
---|---|---|
committer | Guillaume Melquiond <guillaume.melquiond@gmail.com> | 2007-08-28 17:03:44 +0000 |
commit | e678c7cc1574d5739f83da2b0d493b44e3a7a42e (patch) | |
tree | a184372b02622d82bc85a9827a835de186b0e2ed /data | |
parent | c4a2cd54d72f776d6e37eae7a8c67caa81269f4f (diff) | |
download | manaserv-e678c7cc1574d5739f83da2b0d493b44e3a7a42e.tar.gz manaserv-e678c7cc1574d5739f83da2b0d493b44e3a7a42e.tar.bz2 manaserv-e678c7cc1574d5739f83da2b0d493b44e3a7a42e.tar.xz manaserv-e678c7cc1574d5739f83da2b0d493b44e3a7a42e.zip |
Implemented quest variables.
Diffstat (limited to 'data')
-rw-r--r-- | data/scripts/libtmw.lua | 110 | ||||
-rw-r--r-- | data/test.lua | 5 |
2 files changed, 80 insertions, 35 deletions
diff --git a/data/scripts/libtmw.lua b/data/scripts/libtmw.lua index bb724799..3189da6a 100644 --- a/data/scripts/libtmw.lua +++ b/data/scripts/libtmw.lua @@ -8,10 +8,12 @@ local npcs = {} -- Table that associates to each Character pointer its state with respect to -- NPCs (only one at a time). A state is an array with four fields: --- . 1: pointer of the NPC the player is currently talking to. +-- . 1: pointer to the NPC the player is currently talking to. -- . 2: coroutine running the NPC handler. --- . 3: next query the NPC expects from a player (1 = next, 2 = choice). +-- . 3: next event the NPC expects from the server. +-- (1 = npc_next, 2 = npc_choose, 3 = quest_reply, 4 = 1+3) -- . 4: countdown (in minutes) before the state is deleted. +-- . 5: name of the expected quest variable. (optional) local states = {} -- Array containing the function registered by atinit. @@ -46,34 +48,68 @@ function do_choice(npc, ch, ...) return coroutine.yield(2) end +-- Gets the value of a quest variable. +-- Calling this function while an acknowledment is pending is desirable, so +-- that lag cannot be perceived by the player. +function get_quest_var(npc, ch, name) + -- Query the server and return immediatly if a value is available. + local value = tmw.chr_get_quest(ch, name) + if value then return value end + -- Wait for database reply. + return coroutine.yield(3, name) +end + -- Processes as much of an NPC handler as possible. -local function process_npc(co, ...) - -- First, resume with the arguments the coroutine was waiting for. - local b, v = coroutine.resume(co, ...) - if not b or not v then - return - end - if v == 2 then - return 2 - end - -- Then, keep resuming until the coroutine expects the result of a choice - -- or an acknowledgment to a message. - local pending = (v == 1) +local function process_npc(w, ...) + local co = w[2] + local pending = (w[3] == 4) + local first = true while true do - b, v = coroutine.resume(co) + local b, v, u + if first then + -- First time, resume with the arguments the coroutine was waiting for. + b, v, u = coroutine.resume(co, ...) + first = false + else + -- Otherwise, simply resume. + b, v, u = coroutine.resume(co) + end if not b or not v then + -- Either there was an error, or the handler just finished its work. return end if v == 2 then - return 2 + -- The coroutine needs a user choice from the server, so wait for it. + w[3] = 2 + break + end + if v == 3 then + -- The coroutine needs the value of a quest variable from the server. + w[5] = u + if pending then + -- The coroutine has also sent a message to the user, so do not + -- forget about it, as it would flood the user with new messages. + w[3] = 4 + else + w[3] = 3 + end + break end if pending then - return 1 + -- The coroutine is about to interact with the user. But the previous + -- action has not been acknowledged by the user yet, so wait for it. + w[3] = 1 + break end if v == 1 then + -- A message has just been sent. But the coroutine can keep going in case + -- there is still some work to do while waiting for user acknowledgment. pending = true end end + -- Restore the countdown, as there was some activity. + w[4] = 5 + return true end -- Called by the game whenever a player starts talking to an NPC. @@ -82,10 +118,9 @@ function npc_start(npc, ch) states[ch] = nil local h = npcs[npc] if not h then return end - local co = coroutine.create(h) - local v = process_npc(co, npc, ch) - if v then - states[ch] = {npc, co, v, 5} + local w = { npc, coroutine.create(h) } + if process_npc(w, npc, ch) then + states[ch] = w if not timer then timer = 600 end @@ -96,27 +131,32 @@ end -- Checks that the NPC expects it, and processes the respective coroutine. function npc_next(npc, ch) local w = states[ch] - if w and w[1] == npc and w[3] == 1 then - local v = process_npc(w[2]) - if v then - w[3] = v - w[4] = 5 - return - end + if not (w and w[1] == npc and w[3] == 1 and process_npc(w)) then + states[ch] = nil end - states[ch] = nil end -- Called by the game whenever a player selects a particular reply. -- Checks that the NPC expects it, and processes the respective coroutine. function npc_choose(npc, ch, u) local w = states[ch] - if w and w[1] == npc and w[3] == 2 then - local v = process_npc(w[2], u) - if v then - w[3] = v - w[4] = 5 - return + if not (w and w[1] == npc and w[3] == 2 and process_npc(w, u)) then + states[ch] = nil + end +end + +-- Called by the game whenever the value of a quest variable is known. +-- Checks that the NPC expects it, and processes the respective coroutine. +-- Note: the check for NPC correctness is missing, but it should never matter. +function quest_reply(ch, name, value) + local w = states[ch] + if w then + local w3 = w[3] + if (w3 == 3 or w3 == 4) and w[5] == name then + w[5] = nil + if process_npc(w, value) then + return + end end end states[ch] = nil diff --git a/data/test.lua b/data/test.lua index 6254225a..47b06519 100644 --- a/data/test.lua +++ b/data/test.lua @@ -36,6 +36,11 @@ function my_npc1(npc, ch) elseif v == 5 then if tmw.chr_money_change(ch, -100) then do_message(npc, ch, string.format("Thank you for you patronage! You are left with %d gil.", tmw.chr_money(ch))) + local g = tonumber(get_quest_var(npc, ch, "001_donation")) + if not g then g = 0 end + g = g + 100 + tmw.chr_set_quest(ch, "001_donation", g) + do_message(npc, ch, string.format("As of today, you have donated %d gil.", g)) else do_message(npc, ch, "I would feel bad taking money from someone that poor.") end |