summaryrefslogtreecommitdiff
path: root/data/scripts
diff options
context:
space:
mode:
authorGuillaume Melquiond <guillaume.melquiond@gmail.com>2007-08-28 17:03:44 +0000
committerGuillaume Melquiond <guillaume.melquiond@gmail.com>2007-08-28 17:03:44 +0000
commite678c7cc1574d5739f83da2b0d493b44e3a7a42e (patch)
treea184372b02622d82bc85a9827a835de186b0e2ed /data/scripts
parentc4a2cd54d72f776d6e37eae7a8c67caa81269f4f (diff)
downloadmanaserv-e678c7cc1574d5739f83da2b0d493b44e3a7a42e.tar.gz
manaserv-e678c7cc1574d5739f83da2b0d493b44e3a7a42e.tar.bz2
manaserv-e678c7cc1574d5739f83da2b0d493b44e3a7a42e.tar.xz
manaserv-e678c7cc1574d5739f83da2b0d493b44e3a7a42e.zip
Implemented quest variables.
Diffstat (limited to 'data/scripts')
-rw-r--r--data/scripts/libtmw.lua110
1 files changed, 75 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