summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorThorbjørn Lindeijer <thorbjorn@lindeijer.nl>2010-05-29 22:11:12 +0200
committerThorbjørn Lindeijer <thorbjorn@lindeijer.nl>2010-05-30 17:50:55 +0200
commit3e669831a05c36a38519b6f22cb1ed3c11837f2f (patch)
tree21a2763b425480c909d43efe0856cfbab48e3573 /scripts
parent8a95ed77fec7c2ef3c0fac81258f70db25009b48 (diff)
downloadmanaserv-3e669831a05c36a38519b6f22cb1ed3c11837f2f.tar.gz
manaserv-3e669831a05c36a38519b6f22cb1ed3c11837f2f.tar.xz
manaserv-3e669831a05c36a38519b6f22cb1ed3c11837f2f.zip
Copied basic Lua libs back from tmwserv-data and added dummy data
The dummy data is currently mostly empty data though, so still nothing to see as far as the example content is concerned. Reviewed-by: Bertram
Diffstat (limited to 'scripts')
-rw-r--r--scripts/lua/libmana-constants.lua103
-rw-r--r--scripts/lua/libmana.lua448
-rw-r--r--scripts/lua/npclib.lua103
3 files changed, 654 insertions, 0 deletions
diff --git a/scripts/lua/libmana-constants.lua b/scripts/lua/libmana-constants.lua
new file mode 100644
index 0000000..227b93f
--- /dev/null
+++ b/scripts/lua/libmana-constants.lua
@@ -0,0 +1,103 @@
+-------------------------------------------------------------
+-- Mana Support Library Constants --
+-- --
+-- Some useful numeric values for use by other scripts. --
+-- --
+----------------------------------------------------------------------------------
+-- Copyright 2008 The Mana World Development Team --
+-- --
+-- This file is part of The Mana Server. --
+-- --
+-- The Mana Server is free software; you can redistribute it and/or modify it --
+-- under the terms of the GNU General Public License as published by the Free --
+-- Software Foundation; either version 2 of the License, or any later version. --
+----------------------------------------------------------------------------------
+
+DAMAGE_PHYSICAL = 0
+DAMAGE_MAGICAL = 1
+DAMAGE_OTHER = 2
+
+ELEMENT_NEUTRAL = 0
+ELEMENT_FIRE = 1
+ELEMENT_WATER = 2
+ELEMENT_EARTH = 3
+ELEMENT_AIR = 4
+ELEMENT_LIGHTNING = 5
+ELEMENT_METAL = 6
+ELEMENT_WOOD = 7
+ELEMENT_ICE = 8
+
+ATTR_PHY_ATK_MIN = 0
+ATTR_PHY_ATK_DELTA = 1
+ATTR_MAG_ATK = 2
+ATTR_PHY_RES = 3
+ATTR_MAG_RES = 4
+ATTR_EVADE = 5
+ATTR_HIT = 6
+ATTR_HP = 7
+ATTR_HP_REGEN = 8
+ELEM_NEUTRAL = 9
+ELEM_FIRE = 10
+ELEM_WATER = 11
+ELEM_EARTH = 12
+ELEM_AIR = 13
+ELEM_SACRED = 14
+ELEM_DEATH = 15
+ATTR_STRENGTH = 16
+ATTR_AGILITY = 17
+ATTR_DEXTERITY = 18
+ATTR_VITALITY = 19
+ATTR_INTELLIGENCE = 20
+ATTR_WILLPOWER = 21
+SKILL_WEAPON_NONE = 100
+SKILL_WEAPON_KNIFE = 101
+SKILL_WEAPON_SWORD = 102
+SKILL_WEAPON_POLEARM = 103
+SKILL_WEAPON_STAFF = 104
+SKILL_WEAPON_WHIP = 105
+SKILL_WEAPON_BOW = 106
+SKILL_WEAPON_SHOOTING = 107
+SKILL_WEAPON_MACE = 108
+SKILL_WEAPON_AXE = 109
+SKILL_WEAPON_THROWN = 110
+
+TILESIZE = 32
+HOURS = 3600
+MINUTES = 60
+
+TYPE_ITEM = 0;
+TYPE_ACTOR = 1;
+TYPE_NPC = 2;
+TYPE_MONSTER = 3;
+TYPE_CHARACTER = 4;
+TYPE_EFFECT = 5;
+TYPE_OTHER = 6;
+
+ACTION_STAND = 0;
+ACTION_WALK = 1;
+ACTION_ATTACK = 2;
+ACTION_SIT = 3;
+ACTION_DEAD = 4;
+ACTION_HURT = 5;
+
+DIRECTION_DEFAULT = 0;
+DIRECTION_UP = 1;
+DIRECTION_DOWN = 2;
+DIRECTION_LEFT = 3;
+DIRECTION_RIGHT = 4;
+DIRECTION_INVALID = 5;
+
+EMOTE_DISGUST = 10000;
+EMOTE_SURPRISE = 10001;
+EMOTE_HAPPY = 10002;
+EMOTE_SAD = 10003;
+EMOTE_EVIL = 10004;
+EMOTE_WINK = 10005;
+EMOTE_ANGEL = 10006;
+EMOTE_BLUSH = 10007;
+EMOTE_TONGUE = 10008;
+EMOTE_GRIN = 10009;
+EMOTE_UPSET = 10010;
+EMOTE_PERTURBED = 10011;
+EMOTE_SPEECH = 10012;
+EMOTE_BLAH = 10013;
diff --git a/scripts/lua/libmana.lua b/scripts/lua/libmana.lua
new file mode 100644
index 0000000..8ea5168
--- /dev/null
+++ b/scripts/lua/libmana.lua
@@ -0,0 +1,448 @@
+-------------------------------------------------------------
+-- Mana Support Library --
+-- --
+-- Functions which are called by the game engine and --
+-- helper functions useful for writing other scripts. --
+-- --
+----------------------------------------------------------------------------------
+-- Copyright 2008 The Mana World Development Team --
+-- --
+-- This file is part of The Mana Server. --
+-- --
+-- The Mana Server is free software; you can redistribute it and/or modify it --
+-- under the terms of the GNU General Public License as published by the Free --
+-- Software Foundation; either version 2 of the License, or any later version. --
+----------------------------------------------------------------------------------
+
+require "scripts/lua/libmana-constants"
+
+
+-- Table that associates to each NPC pointer the handler function that is
+-- called when a player starts talking to an NPC.
+local npc_talk_functs = {}
+local npc_update_functs = {}
+
+-- 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 to the NPC the player is currently talking to.
+-- . 2: coroutine running the NPC handler.
+-- . 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.
+local init_fun = {}
+
+-- Tick timer used during update to clean obsolete states.
+local timer
+
+-- Creates an NPC and associates the given handler.
+-- Note: Cannot be called until map initialization has started.
+function create_npc(name, id, x, y, talkfunct, updatefunct)
+ local npc = mana.npc_create(name, id, x, y)
+ if talkfunct then npc_talk_functs[npc] = talkfunct end
+ if updatefunct then npc_update_functs[npc] = updatefunct end
+ return npc
+end
+
+-- Waits for the player to acknowledge the previous message, if any.
+function do_wait()
+ coroutine.yield(0)
+end
+
+-- Sends an npc message to a player.
+-- Note: Does not wait for the player to acknowledge the message.
+function do_message(npc, ch, msg)
+ -- Wait for the arrival of a pending acknowledgment, if any.
+ coroutine.yield(0)
+ mana.npc_message(npc, ch, msg)
+ -- An acknowledgment is pending, but do not wait for its arrival.
+ coroutine.yield(1)
+end
+
+-- Sends an NPC question to a player and waits for its answer.
+function do_choice(npc, ch, ...)
+ -- Wait for the arrival of a pending acknowledgment, if any.
+ coroutine.yield(0)
+ mana.npc_choice(npc, ch, ...)
+ -- Wait for player choice.
+ return coroutine.yield(2)
+end
+
+-- Sends an NPC integer ask to a player and waits for its answer.
+function do_ask_integer(npc, ch, min_num, max_num, ...)
+ -- Wait for the arrival of a pending acknowledgment, if any.
+ coroutine.yield(0)
+ mana.npc_ask_integer(npc, ch, min_num, max_num, ...)
+ -- Wait for player answer.
+ return coroutine.yield(2)
+end
+
+-- Sends an NPC string ask to a player and waits for its answer.
+function do_ask_string(npc, ch)
+ -- Wait for the arrival of a pending acknowledgment, if any.
+ coroutine.yield(0)
+ mana.npc_ask_string(npc, ch)
+ -- Wait for player answer.
+ return coroutine.yield(2)
+end
+
+-- Sends an NPC request to send letter to a player and waits for them to
+-- send the letter.
+function do_post(npc, ch)
+ coroutine.yield(0)
+ mana.npc_post(npc, ch)
+ return coroutine.yield(1)
+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(ch, name)
+ -- Query the server and return immediatly if a value is available.
+ local value = mana.chr_get_quest(ch, name)
+ if value then return value end
+ -- Wait for database reply.
+ return coroutine.yield(3, name)
+end
+
+-- Gets the post for a user.
+function getpost(ch)
+ mana.chr_get_post(ch)
+ return coroutine.yield(3)
+end
+
+-- Processes as much of an NPC handler as possible.
+local function process_npc(w, ...)
+ local co = w[2]
+ local pending = (w[3] == 4)
+ local first = true
+ while true do
+ 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 then print("LUA error: ", v)end
+
+ if not b or not v then
+ -- Either there was an error, or the handler just finished its work.
+ return
+ elseif v == 2 then
+ -- The coroutine needs a user choice from the server, so wait for it.
+ w[3] = 2
+ break
+ elseif 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
+ elseif pending then
+ -- 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
+ elseif 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.
+-- Creates a coroutine based on the registered NPC handler.
+function npc_start(npc, ch)
+ states[ch] = nil
+ local h = npc_talk_functs[npc]
+ if not h then return end
+ local w = { npc, coroutine.create(h) }
+ if process_npc(w, npc, ch) then
+ states[ch] = w
+ if not timer then
+ timer = 600
+ end
+ end
+ -- coroutine.resume(w)
+ -- do_npc_close(npc, ch)
+end
+
+function do_npc_close(npc, ch)
+ mana.npc_end(npc, ch)
+end
+
+-- Called by the game whenever a player keeps talking to an NPC.
+-- Checks that the NPC expects it, and processes the respective coroutine.
+function npc_next(npc, ch)
+ local w = states[ch]
+ if w then
+ local w3 = w[3]
+ if w3 == 4 then
+ w[3] = 3
+ return
+ elseif w3 == 1 and process_npc(w) then
+ return
+ end
+ 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 not (w and w[1] == npc and w[3] == 2 and process_npc(w, u)) then
+ states[ch] = nil
+ end
+end
+
+function npc_integer(npc, ch, u)
+ local w = states[ch]
+ if not (w and w[1] == npc and w[3] == 2 and process_npc(w, u)) then
+ states[ch] = nil
+ end
+end
+
+function npc_string(npc, ch, u)
+ local w = states[ch]
+ 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 when a player sends a letter.
+function npc_post(npc, ch, sender, letter)
+ local w = states[ch]
+ if not (w and w[1] == npc and w[3] == 1 and process_npc(w, sender, letter)) 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
+end
+
+function post_reply(ch, sender, letter)
+ local w = states[ch]
+ if w then
+ local w3 = w[3]
+ if (w3 == 3 or w3 == 4) then
+ if process_npc(w, sender, letter) then
+ return
+ end
+ end
+ end
+ states[ch] = nil
+end
+
+-- Called by the game every tick for each NPC.
+function npc_update(npc)
+ local h = npc_update_functs[npc];
+ if h then h(npc) end;
+end
+
+-- Called by the game every tick.
+-- Checks for scheduled function calls
+-- Cleans obsolete connections.
+function update()
+ -- check the scheduler
+ check_schedule()
+
+ -- Run every minute only, in order not to overload the server.
+ if not timer then return end
+ timer = timer - 1
+ if timer ~= 0 then return end
+ -- Free connections that have been inactive for 3-4 minutes.
+ for k, w in pairs(states) do
+ local t = w[4] - 1
+ if t == 0 then
+ states[k] = nil
+ else
+ w[4] = t
+ end
+ end
+ -- Restart timer if there are still some pending states.
+ if next(states) then
+ timer = 600
+ else
+ timer = nil
+ end
+end
+
+-- Registers a function so that is is executed during map initialization.
+function atinit(f)
+ init_fun[#init_fun + 1] = f
+end
+
+-- Called by the game for creating NPCs embedded into maps.
+-- Delays the creation until map initialization is performed.
+-- Note: Assumes that the "npc_handler" global field contains the NPC handler.
+function create_npc_delayed(name, id, x, y)
+ -- Bind the name to a local variable first, as it will be reused.
+ local h = npc_handler
+ atinit(function() create_npc(name, id, x, y, h, nil) end)
+ npc_handler = nil
+end
+
+-- Called during map initialization.
+-- Executes all the functions registered by atinit.
+function initialize()
+ for i,f in ipairs(init_fun) do
+ f()
+ end
+ init_fun = nil
+end
+
+
+-- SCHEDULER
+
+-- Table of scheduled jobs. A job is an array with 3 elements:
+-- 0: the UNIX timestamp when it is executed
+-- 1: the function which is executed
+-- 2: nil when it is a one-time job. Repetition interval is seconds when it is
+-- a repeated job.
+local scheduler_jobs = {}
+
+-- compare function used to sort the scheduler_jobs table.
+-- the jobs which come first are at the end of the table.
+local function job_cmp(job1, job2)
+ return (job1[0] > job2[0])
+end
+
+-- checks for jobs which have to be executed, executes them and reschedules
+-- them when they are repeated jobs.
+function check_schedule()
+ if #scheduler_jobs==0 then return end
+ while os.time() > scheduler_jobs[#scheduler_jobs][0] do
+ -- retreive the job and remove it from the schedule
+ job = scheduler_jobs[#scheduler_jobs]
+ table.remove(scheduler_jobs)
+ -- reschedule the job when it is a repeated job
+ if job[2] then
+ schedule_every(job[2], job[1])
+ end
+ -- execute the job
+ job[1]()
+ end
+end
+
+-- schedules a function call to be executed once in n seconds
+function schedule_in(seconds, funct)
+ local job = {}
+ job[0] = os.time() + seconds
+ job[1] = funct
+ job[2] = nil
+ table.insert(scheduler_jobs, job)
+ table.sort(scheduler_jobs, job_cmp)
+end
+
+-- schedules a function call to be executed at regular intervals of n seconds
+function schedule_every(seconds, funct)
+ local job = {}
+ job[0] = os.time() + seconds
+ job[1] = funct
+ job[2] = seconds
+ table.insert(scheduler_jobs, job)
+ table.sort(scheduler_jobs, job_cmp)
+end
+
+
+-- DEATH NOTIFICATIONS
+local ondeath_functs = {}
+local onremove_functs = {}
+
+-- requests the gameserver to notify the script engine when the being
+-- dies and adds a script function to be executed in this case.
+function on_death(being, funct)
+ if ondeath_functs[being] == nil then
+ ondeath_functs[being] = {}
+ end
+ table.insert(ondeath_functs[being], funct)
+ mana.being_register(being)
+end
+
+-- requests the gameserver to notify the script engine when the being
+-- dies and adds a script function to be executed in this case.
+function on_remove(being, funct)
+ if onremove_functs[being] == nil then
+ onremove_functs[being] = {}
+ end
+ table.insert(onremove_functs[being], funct)
+ mana.being_register(being)
+end
+
+-- called by the engine when a registred being dies.
+function death_notification(being)
+ if type(ondeath_functs[being]) == "table" then
+ for i,funct in pairs(ondeath_functs[being]) do
+ funct()
+ end
+ ondeath_functs[being] = nil
+ end
+end
+
+-- called by the engine when a registred being is removed.
+function remove_notification(being)
+ if type(onremove_functs[being]) == "table" then
+ for i,funct in pairs(onremove_functs[being]) do
+ funct()
+ end
+ onremove_functs[being] = nil
+ ondeath_functs[being] = nil
+ end
+end
+
+
+-- Below are some convenience methods added to the engine API
+
+mana.chr_money_change = function(ch, amount)
+ return mana.chr_inv_change(ch, 0, amount)
+end
+
+mana.chr_money = function(ch)
+ return mana.chr_inv_count(ch, 0)
+end
+
+
+
+function cast(ch, arg)
+ if arg == 1 then
+ mana.being_say(ch, "Kaaame...Haaame... HAAAAAA!")
+ end
+ if arg == 2 then
+ mana.being_say(ch, "HAA-DOKEN!")
+ end
+ if arg == 3 then
+ mana.being_say(ch, "Sonic BOOM")
+ end
+
+end
diff --git a/scripts/lua/npclib.lua b/scripts/lua/npclib.lua
new file mode 100644
index 0000000..9edfcbd
--- /dev/null
+++ b/scripts/lua/npclib.lua
@@ -0,0 +1,103 @@
+----------------------------------------------------------
+-- Library for commonly used NPC scripts --
+-- --
+-- --
+-- Any NPC update function or talk function which could --
+-- be used for NPCs on more than one map should be --
+-- placed here. --
+-- --
+----------------------------------------------------------------------------------
+-- Copyright 2008 The Mana World Development Team --
+-- --
+-- This file is part of The Mana Server. --
+-- --
+-- The Mana Server is free software; you can redistribute it and/or modify it --
+-- under the terms of the GNU General Public License as published by the Free --
+-- Software Foundation; either version 2 of the License, or any later version. --
+----------------------------------------------------------------------------------
+
+module("npclib", package.seeall);
+
+
+-- Update function walkaround_small
+-- makes the NPC walk around in a 64x64 pixel square around its start location.
+-- Useful for NPCs which are supposed to stay on a specific spot but
+-- move a bit from time to time.
+
+local wasmall_timer = {}
+local wasmall_startx = {}
+local wasmall_starty = {}
+
+function walkaround_small(npc)
+ if not wasmall_timer[npc] then
+ wasmall_timer[npc] = 1
+ wasmall_startx[npc] = mana.posX(npc)
+ wasmall_starty[npc] = mana.posY(npc)
+ end
+
+ wasmall_timer[npc] = wasmall_timer[npc] + 1
+
+ if wasmall_timer[npc] == 100 then
+ wasmall_timer[npc] = math.random(1, 10)
+ local x = math.random(-32, 32) + wasmall_startx[npc]
+ local y = math.random(-32, 32) + wasmall_starty[npc]
+ mana.being_walk(npc, x, y, 2)
+ end
+end
+
+
+-- Update function walkaround_wide
+-- makes the NPC walk around in a 256x256 pixel square around its start
+-- location. Useful for NPCs which are supposed to be found near a specific
+-- location but not nailed to the floor.
+
+local wawide_timer = {}
+local wawide_startx = {}
+local wawide_starty = {}
+
+function walkaround_wide(npc)
+ if not wawide_timer[npc] then
+ wawide_timer[npc] = 1
+ wawide_startx[npc] = mana.posX(npc)
+ wawide_starty[npc] = mana.posY(npc)
+ end
+
+ wawide_timer[npc] = wawide_timer[npc] + 1
+
+ if wawide_timer[npc] == 50 then
+ wawide_timer[npc] = math.random(1, 10)
+ local x = math.random(-128, 128) + wawide_startx[npc]
+ local y = math.random(-128, 128) + wawide_starty[npc]
+ mana.being_walk(npc, x, y, 2)
+ end
+end
+
+
+-- Update function walkaround_map
+-- makes the NPC wander around the whole map. Useful when the players are
+-- supposed to search a bit for the NPC.
+
+local wam_timer = {}
+
+function walkaround_map(npc)
+ if not wam_timer[npc] then
+ wam_timer[npc] = 1
+ end
+
+ wam_timer[npc] = wam_timer[npc] + 1
+
+ if wam_timer[npc] == 50 then
+ wam_timer[npc] = math.random(1, 10)
+ local x = math.random(-128, 128) + mana.posX(npc)
+ local y = math.random(-128, 128) + mana.posY(npc)
+ mana.being_walk(npc, x, y, 2)
+ end
+end
+
+-- Allows passage of more information to an NPC's talk function
+function talk(f, ...)
+ local a = {...}
+ return function(npc, ch)
+ f(npc, ch, a)
+ end
+end