00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <cassert>
00024
00025 extern "C" {
00026 #include <lualib.h>
00027 #include <lauxlib.h>
00028 }
00029
00030 #include "defines.h"
00031 #include "game-server/accountconnection.hpp"
00032 #include "game-server/buysell.hpp"
00033 #include "game-server/character.hpp"
00034 #include "game-server/collisiondetection.hpp"
00035 #include "game-server/effect.hpp"
00036 #include "game-server/gamehandler.hpp"
00037 #include "game-server/inventory.hpp"
00038 #include "game-server/item.hpp"
00039 #include "game-server/itemmanager.hpp"
00040 #include "game-server/mapcomposite.hpp"
00041 #include "game-server/mapmanager.hpp"
00042 #include "game-server/monster.hpp"
00043 #include "game-server/monstermanager.hpp"
00044 #include "game-server/npc.hpp"
00045 #include "game-server/postman.hpp"
00046 #include "game-server/quest.hpp"
00047 #include "game-server/state.hpp"
00048 #include "game-server/trigger.hpp"
00049 #include "net/messageout.hpp"
00050 #include "scripting/luautil.hpp"
00051 #include "scripting/luascript.hpp"
00052 #include "utils/logger.h"
00053
00054
00055
00056
00057
00058
00059
00060
00061
00066 static int npc_message(lua_State *s)
00067 {
00068 NPC *p = getNPC(s, 1);
00069 Character *q = getCharacter(s, 2);
00070 size_t l;
00071 const char *m = lua_tolstring(s, 3, &l);
00072 if (!p || !q || !m)
00073 {
00074 raiseScriptError(s, "npc_message called with incorrect parameters.");
00075 return 0;
00076 }
00077 MessageOut msg(GPMSG_NPC_MESSAGE);
00078 msg.writeShort(p->getPublicID());
00079 msg.writeString(std::string(m), l);
00080 gameHandler->sendTo(q, msg);
00081 return 0;
00082 }
00083
00088 static int npc_choice(lua_State *s)
00089 {
00090 NPC *p = getNPC(s, 1);
00091 Character *q = getCharacter(s, 2);
00092 if (!p || !q)
00093 {
00094 raiseScriptError(s, "npc_Choice called with incorrect parameters.");
00095 return 0;
00096 }
00097 MessageOut msg(GPMSG_NPC_CHOICE);
00098 msg.writeShort(p->getPublicID());
00099 for (int i = 3, i_end = lua_gettop(s); i <= i_end; ++i)
00100 {
00101 const char *m = lua_tostring(s, i);
00102 if (!m)
00103 {
00104 raiseScriptError(s, "npc_Choice called with incorrect parameters.");
00105 return 0;
00106 }
00107 msg.writeString(m);
00108 }
00109 gameHandler->sendTo(q, msg);
00110 return 0;
00111 }
00112
00117 static int npc_create(lua_State *s)
00118 {
00119 if (!lua_isstring(s, 1) || !lua_isnumber(s, 2) || !lua_isnumber(s, 3) || !lua_isnumber(s, 4))
00120 {
00121 raiseScriptError(s, "npc_create called with incorrect parameters.");
00122 return 0;
00123 }
00124 lua_pushlightuserdata(s, (void *)®istryKey);
00125 lua_gettable(s, LUA_REGISTRYINDEX);
00126 Script *t = static_cast<Script *>(lua_touserdata(s, -1));
00127 NPC *q = new NPC(lua_tostring(s, 1), lua_tointeger(s, 2), t);
00128 MapComposite *m = t->getMap();
00129 if (!m)
00130 {
00131 raiseScriptError(s, "npc_create called outside a map.");
00132 return 0;
00133 }
00134 q->setMap(m);
00135 q->setPosition(Point(lua_tointeger(s, 3), lua_tointeger(s, 4)));
00136 bool b = GameState::insert(q);
00137
00138
00139 assert(b); (void)b;
00140 lua_pushlightuserdata(s, q);
00141 return 1;
00142 }
00143
00148 static int npc_post(lua_State *s)
00149 {
00150 NPC *p = getNPC(s, 1);
00151 Character *q = getCharacter(s, 2);
00152
00153 if (!p || !q)
00154 {
00155 raiseScriptError(s, "npc_Choice called with incorrect parameters.");
00156 return 0;
00157 }
00158
00159 MessageOut msg(GPMSG_NPC_POST);
00160 msg.writeShort(p->getPublicID());
00161 gameHandler->sendTo(q, msg);
00162
00163 return 0;
00164 }
00165
00170 static int npc_enable(lua_State *s)
00171 {
00172 NPC *p = getNPC(s, 1);
00173 if (p)
00174 {
00175 p->enable(true);
00176 bool b = GameState::insert(p);
00177 assert(b); (void)b;
00178 }
00179
00180 return 0;
00181 }
00182
00187 static int npc_disable(lua_State *s)
00188 {
00189 NPC *p = getNPC(s, 1);
00190 if (p)
00191 {
00192 p->enable(false);
00193 GameState::remove(p);
00194 }
00195
00196 return 0;
00197 }
00198
00203 static int chr_warp(lua_State *s)
00204 {
00205 Character *q = getCharacter(s, 1);
00206 bool b = lua_isnil(s, 2);
00207 if (!q || !(b || lua_isnumber(s, 2)) ||
00208 !lua_isnumber(s, 3) || !lua_isnumber(s, 4))
00209 {
00210 raiseScriptError(s, "chr_warp called with incorrect parameters.");
00211 return 0;
00212 }
00213 MapComposite *m;
00214 if (b)
00215 {
00216 lua_pushlightuserdata(s, (void *)®istryKey);
00217 lua_gettable(s, LUA_REGISTRYINDEX);
00218 Script *t = static_cast<Script *>(lua_touserdata(s, -1));
00219 m = t->getMap();
00220 }
00221 else
00222 {
00223 m = MapManager::getMap(lua_tointeger(s, 2));
00224 }
00225 if (!m)
00226 {
00227 raiseScriptError(s, "chr_warp called with a non-existing map.");
00228 return 0;
00229 }
00230 GameState::enqueueWarp(q, m, lua_tointeger(s, 3), lua_tointeger(s, 4));
00231 return 0;
00232 }
00233
00246 static int chr_inv_change(lua_State *s)
00247 {
00248 Character *q = getCharacter(s, 1);
00249 if (!q)
00250 {
00251 raiseScriptError(s, "chr_inv_change called with incorrect parameters.");
00252 return 0;
00253 }
00254 int nb_items = (lua_gettop(s) - 1) / 2;
00255 Inventory inv(q, true);
00256 for (int i = 0; i < nb_items; ++i)
00257 {
00258 if (!lua_isnumber(s, i * 2 + 2) || !lua_isnumber(s, i * 2 + 3))
00259 {
00260 raiseScriptError(s, "chr_inv_change called with incorrect parameters.");
00261 return 0;
00262 }
00263 int id = lua_tointeger(s, i * 2 + 2);
00264 int nb = lua_tointeger(s, i * 2 + 3);
00265
00266 if (id == 0)
00267 {
00268 if (!inv.changeMoney(nb))
00269 {
00270 inv.cancel();
00271 lua_pushboolean(s, 0);
00272 return 1;
00273 }
00274 }
00275 else if (nb < 0)
00276 {
00277 nb = inv.remove(id, -nb);
00278 if (nb)
00279 {
00280 inv.cancel();
00281 lua_pushboolean(s, 0);
00282 return 1;
00283 }
00284 }
00285 else
00286 {
00287 ItemClass *ic = ItemManager::getItem(id);
00288 if (!ic)
00289 {
00290 raiseScriptError(s, "chr_inv_change called with an unknown item.");
00291 continue;
00292 }
00293 nb = inv.insert(id, nb);
00294 if (nb)
00295 {
00296 Item *item = new Item(ic, nb);
00297 item->setMap(q->getMap());
00298 item->setPosition(q->getPosition());
00299 GameState::enqueueInsert(item);
00300 }
00301 }
00302 }
00303 lua_pushboolean(s, 1);
00304 return 1;
00305 }
00306
00312 static int chr_inv_count(lua_State *s)
00313 {
00314 Character *q = getCharacter(s, 1);
00315 if (!q)
00316 {
00317 raiseScriptError(s, "chr_inv_count called with incorrect parameters.");
00318 return 0;
00319 }
00320 int nb_items = lua_gettop(s) - 1;
00321 lua_checkstack(s, nb_items);
00322 Inventory inv(q);
00323 for (int i = 2; i <= nb_items + 1; ++i)
00324 {
00325 if (!lua_isnumber(s, i))
00326 {
00327 raiseScriptError(s, "chr_inv_count called with incorrect parameters.");
00328 return 0;
00329 }
00330 int id = lua_tointeger(s, i);
00331 int nb = id ? inv.count(id) : q->getPossessions().money;
00332 lua_pushinteger(s, nb);
00333 }
00334 return nb_items;
00335 }
00336
00341 static int npc_trade(lua_State *s)
00342 {
00343 NPC *p = getNPC(s, 1);
00344 Character *q = getCharacter(s, 2);
00345 if (!p || !q || !lua_isboolean(s, 3) || !lua_istable(s, 4))
00346 {
00347 raiseScriptError(s, "npc_trade called with incorrect parameters.");
00348 return 0;
00349 }
00350 BuySell *t = new BuySell(q, lua_toboolean(s, 3));
00351 lua_pushnil(s);
00352 while (lua_next(s, 4))
00353 {
00354 if (!lua_istable(s, -1))
00355 {
00356 raiseScriptError(s, "npc_trade called with incorrect parameters.");
00357 t->cancel();
00358 return 0;
00359 }
00360 int v[3];
00361 for (int i = 0; i < 3; ++i)
00362 {
00363 lua_rawgeti(s, -1, i + 1);
00364 if (!lua_isnumber(s, -1))
00365 {
00366 raiseScriptError(s, "rpc_trade called with incorrect parameters.");
00367 t->cancel();
00368 return 0;
00369 }
00370 v[i] = lua_tointeger(s, -1);
00371 lua_pop(s, 1);
00372 }
00373 t->registerItem(v[0], v[1], v[2]);
00374 lua_pop(s, 1);
00375 }
00376 t->start(p);
00377 return 0;
00378 }
00379
00384 static int being_type(lua_State *s)
00385 {
00386 if (!lua_isuserdata(s, 1) )
00387 {
00388 raiseScriptError(s, "being_type called with incorrect parameters.");
00389 return 0;
00390 }
00391
00392 Being *being = getBeing(s, 1);
00393 if (!being) return 0;
00394 lua_pushinteger(s, being->getType());
00395 return 1;
00396 }
00397
00402 static int being_walk(lua_State *s)
00403 {
00404 if (!lua_isnumber(s, 2) || !lua_isnumber(s, 3) || !lua_isnumber(s, 4))
00405 {
00406 raiseScriptError(s, "being_walk called with incorrect parameters.");
00407 return 0;
00408 }
00409
00410 lua_pushlightuserdata(s, (void *)®istryKey);
00411 lua_gettable(s, LUA_REGISTRYINDEX);
00412
00413 Being *being = getBeing(s, 1);
00414 Point destination(lua_tointeger(s, 2), lua_tointeger(s, 3));
00415 being->setDestination(destination);
00416 being->setSpeed(lua_tointeger(s, 4));
00417
00418 return 0;
00419 }
00420
00425 static int being_say(lua_State *s)
00426 {
00427 if (!lua_isuserdata(s, 1) || !lua_isstring(s, 2) )
00428 {
00429 raiseScriptError(s, "being_say called with incorrect parameters.");
00430 return 0;
00431 }
00432
00433 Being *being = getBeing(s, 1);
00434 std::string message = lua_tostring(s, 2);
00435
00436 if (being && message != "")
00437 {
00438 GameState::sayAround(being, message);
00439 } else {
00440 raiseScriptError(s, "being_say called with incorrect parameters.");
00441 return 0;
00442 }
00443
00444 return 0;
00445 }
00446
00447
00452 static int being_damage(lua_State *s)
00453 {
00454 Being *being = getBeing(s, 1);
00455
00456 if (!being->canFight())
00457 return 0;
00458
00459 Damage damage;
00460 damage.base = lua_tointeger(s, 2);
00461 damage.delta = lua_tointeger(s, 3);
00462 damage.cth = lua_tointeger(s, 4);
00463 damage.type = lua_tointeger(s, 5);
00464 damage.element = lua_tointeger(s, 6);
00465
00466 being->damage(NULL, damage);
00467
00468 return 0;
00469 }
00470
00475 static int being_get_attribute(lua_State *s)
00476 {
00477 lua_pushlightuserdata(s, (void *)®istryKey);
00478 lua_gettable(s, LUA_REGISTRYINDEX);
00479
00480 Being *being = getBeing(s, 1);
00481
00482 if (being)
00483 {
00484 int attr = lua_tointeger(s, 2);
00485 if (attr == 0)
00486 {
00487 raiseScriptError(s,
00488 "being_get_attribute called with incorrect parameters.");
00489 return 0;
00490 }
00491 else
00492 {
00493 lua_pushinteger(s, being->getModifiedAttribute(attr));
00494 }
00495 }
00496
00497 return 1;
00498 }
00499
00504 static int being_get_name(lua_State *s)
00505 {
00506 lua_pushlightuserdata(s, (void *)®istryKey);
00507 lua_gettable(s, LUA_REGISTRYINDEX);
00508
00509 Being *being = getBeing(s, 1);
00510
00511 if (being)
00512 {
00513 lua_pushstring(s, being->getName().c_str());
00514 }
00515
00516 return 1;
00517 }
00518
00522 static int posX(lua_State *s)
00523 {
00524 lua_pushlightuserdata(s, (void *)®istryKey);
00525 lua_gettable(s, LUA_REGISTRYINDEX);
00526
00527 int x = getBeing(s, 1)->getPosition().x;
00528 lua_pushinteger(s, x);
00529
00530 return 1;
00531 }
00532
00536 static int posY(lua_State *s)
00537 {
00538 lua_pushlightuserdata(s, (void *)®istryKey);
00539 lua_gettable(s, LUA_REGISTRYINDEX);
00540
00541 int y = getBeing(s, 1)->getPosition().y;
00542 lua_pushinteger(s, y);
00543
00544 return 1;
00545 }
00546
00551 static int monster_create(lua_State *s)
00552 {
00553 if (!lua_isnumber(s, 1) || !lua_isnumber(s, 2) || !lua_isnumber(s, 3))
00554 {
00555 raiseScriptError(s, "monster_create called with incorrect parameters.");
00556 return 0;
00557 }
00558
00559 lua_pushlightuserdata(s, (void *)®istryKey);
00560 lua_gettable(s, LUA_REGISTRYINDEX);
00561 Script *t = static_cast<Script *>(lua_touserdata(s, -1));
00562 MapComposite *m = t->getMap();
00563 if (!m)
00564 {
00565 raiseScriptError(s, "monster_create called outside a map.");
00566 return 0;
00567 }
00568
00569 int monsterId = lua_tointeger(s, 1);
00570 MonsterClass *spec = MonsterManager::getMonster(monsterId);
00571 if (!spec)
00572 {
00573 raiseScriptError(s, "monster_create called with invalid monster ID: %d", monsterId);
00574
00575 return 0;
00576 }
00577
00578 Monster *q = new Monster(spec);
00579 q->setMap(m);
00580 q->setPosition(Point(lua_tointeger(s, 2), lua_tointeger(s, 3)));
00581 if (!GameState::insertSafe(q))
00582 {
00583 LOG_WARN("Monster_Create failed to insert monster");
00584 return 0;
00585 }
00586
00587 lua_pushlightuserdata(s, q);
00588 return 1;
00589 }
00590
00596 static int chr_get_quest(lua_State *s)
00597 {
00598 Character *q = getCharacter(s, 1);
00599 if (!q)
00600 {
00601 raiseScriptError(s, "chr_get_quest called for nonexistent character.");
00602 }
00603
00604 const char *m = lua_tostring(s, 2);
00605 if (!m || m[0] == 0)
00606 {
00607 raiseScriptError(s, "chr_get_quest called with incorrect parameters.");
00608 return 0;
00609 }
00610 std::string value, name = m;
00611 bool res = getQuestVar(q, name, value);
00612 if (res)
00613 {
00614 lua_pushstring(s, value.c_str());
00615 return 1;
00616 }
00617 lua_pushlightuserdata(s, (void *)®istryKey);
00618 lua_gettable(s, LUA_REGISTRYINDEX);
00619 Script *t = static_cast<Script *>(lua_touserdata(s, -1));
00620 QuestCallback f = { &LuaScript::getQuestCallback, t };
00621 recoverQuestVar(q, name, f);
00622 return 0;
00623 }
00624
00629 static int chr_set_quest(lua_State *s)
00630 {
00631 Character *q = getCharacter(s, 1);
00632 const char *m = lua_tostring(s, 2);
00633 const char *n = lua_tostring(s, 3);
00634 if (!m || !n || m[0] == 0)
00635 {
00636 raiseScriptError(s, "chr_set_quest called with incorrect parameters.");
00637 return 0;
00638 }
00639 setQuestVar(q, m, n);
00640 return 0;
00641 }
00642
00648 static int trigger_create(lua_State *s)
00649 {
00650
00651 if (!lua_isnumber(s, 1) ||
00652 !lua_isnumber(s, 2) ||
00653 !lua_isnumber(s, 3) ||
00654 !lua_isnumber(s, 4) ||
00655 !lua_isstring(s, 5) ||
00656 !lua_isnumber(s, 6) ||
00657 !lua_isboolean(s, 7))
00658 {
00659 raiseScriptError(s, "trigger_create called with incorrect parameters.");
00660 return 0;
00661 }
00662
00663 lua_pushlightuserdata(s, (void *)®istryKey);
00664 lua_gettable(s, LUA_REGISTRYINDEX);
00665 Script *script = static_cast<Script *>(lua_touserdata(s, -1));
00666 int x = lua_tointeger(s, 1);
00667 int y = lua_tointeger(s, 2);
00668 int width = lua_tointeger(s, 3);
00669 int height = lua_tointeger(s, 4);
00670 std::string function = lua_tostring(s, 5);
00671 int id = lua_tointeger(s, 6);
00672 bool once = lua_toboolean(s, 7);
00673
00674 LOG_INFO("Created script trigger at "<<x<<":"<<y<<" ("<<width<<"x"<<height<<") function: "<<function<<" ("<<id<<")");
00675
00676 MapComposite *m = script->getMap();
00677
00678 if (!m)
00679 {
00680 raiseScriptError(s, "trigger_create called for nonexistent a map.");
00681 return 0;
00682 }
00683
00684 ScriptAction *action = new ScriptAction(script, function, id);
00685 Rectangle r = { x, y, width, height };
00686 TriggerArea *area = new TriggerArea(m, r, action, once);
00687
00688 bool ret = GameState::insert(area);
00689 lua_pushboolean(s, ret);
00690 return 1;
00691 }
00692
00698 static int chatmessage(lua_State *s)
00699 {
00700 if (lua_gettop(s) == 2 && lua_isuserdata(s, 1) && lua_isstring(s, 2) )
00701 {
00702 Being *being = getBeing(s, 1);
00703 std::string message = lua_tostring(s, 2);
00704
00705 if (being && message != "")
00706 {
00707 GameState::sayTo(being, NULL, message);
00708 }
00709 }
00710 else if(lua_gettop(s) == 1 && lua_isstring(s, 1))
00711 {
00712
00713 }
00714 else
00715 {
00716 raiseScriptError(s, "being_say called with incorrect parameters.");
00717 return 0;
00718 }
00719
00720 return 0;
00721 }
00722
00728 static int get_beings_in_circle(lua_State *s)
00729 {
00730 int x = lua_tointeger(s, 1);
00731 int y = lua_tointeger(s, 2);
00732 int r = lua_tointeger(s, 3);
00733
00734 lua_pushlightuserdata(s, (void *)®istryKey);
00735 lua_gettable(s, LUA_REGISTRYINDEX);
00736 Script *t = static_cast<Script *>(lua_touserdata(s, -1));
00737 MapComposite *m = t->getMap();
00738
00739
00740 lua_newtable(s);
00741 int tableStackPosition = lua_gettop(s);
00742 int tableIndex = 1;
00743 for (BeingIterator i(m->getAroundPointIterator(Point(x, y), r)); i; ++i)
00744 {
00745 char t = (*i)->getType();
00746 if (t == OBJECT_NPC || t == OBJECT_CHARACTER || t == OBJECT_MONSTER)
00747 {
00748 Being *b = static_cast<Being *> (*i);
00749 if (Collision::CircleWithCircle(b->getPosition(), b->getSize(),
00750 Point(x, y), r))
00751 {
00752 lua_pushinteger(s, tableIndex);
00753 lua_pushlightuserdata (s, b);
00754 lua_settable (s, tableStackPosition);
00755 tableIndex++;
00756 }
00757 }
00758 }
00759
00760 return 1;
00761 }
00762
00766 static int chr_get_post(lua_State *s)
00767 {
00768 if (lua_isuserdata(s, 1))
00769 {
00770 Character *c = getCharacter(s, 1);
00771
00772 if (c)
00773 {
00774 lua_pushlightuserdata(s, (void *)®istryKey);
00775 lua_gettable(s, LUA_REGISTRYINDEX);
00776 Script *t = static_cast<Script *>(lua_touserdata(s, -1));
00777 PostCallback f = { &LuaScript::getPostCallback, t };
00778 postMan->getPost(c, f);
00779 }
00780 }
00781
00782 return 0;
00783 }
00784
00791 static int being_register(lua_State *s)
00792 {
00793 if (!lua_islightuserdata(s, 1) || lua_gettop(s) != 1)
00794 {
00795 raiseScriptError(s, "being_register called with incorrect parameters.");
00796 return 0;
00797 }
00798
00799 lua_pushlightuserdata(s, (void *)®istryKey);
00800 lua_gettable(s, LUA_REGISTRYINDEX);
00801 Script *t = static_cast<Script *>(lua_touserdata(s, -1));
00802 Being *being = getBeing(s, 1);
00803 if (!being)
00804 {
00805 raiseScriptError(s, "being_register called for nonexistent being.");
00806 return 0;
00807 }
00808
00809 being->addListener(t->getScriptListener());
00810 return 0;
00811 }
00812
00813
00818 static int effect_create(lua_State *s)
00819 {
00820 if (!lua_isnumber(s, 1) ||
00821 !lua_isnumber(s, 2) ||
00822 !lua_isnumber(s, 3))
00823 {
00824 raiseScriptError(s, "effect_create called with incorrect parameters.");
00825 return 0;
00826 }
00827 lua_pushlightuserdata(s, (void *)®istryKey);
00828 lua_gettable(s, LUA_REGISTRYINDEX);
00829 Script *t = static_cast<Script *>(lua_touserdata(s, -1));
00830
00831 MapComposite *m = t->getMap();
00832 int id = lua_tointeger(s, 1);
00833 int x = lua_tointeger(s, 2);
00834 int y = lua_tointeger(s, 3);
00835
00836 Effects::show(id, m, Point(x, y));
00837
00838 return 0;
00839 }
00840
00845 static int chr_get_exp(lua_State *s)
00846 {
00847 Character *c = getCharacter(s, 1);
00848 if (!c)
00849 {
00850 raiseScriptError(s, "luaChr_GetExp called for nonexistent character.");
00851 return 0;
00852 }
00853
00854 int skill = lua_tointeger(s, 2);
00855 if (skill < CHAR_SKILL_BEGIN || skill >= CHAR_SKILL_END)
00856 {
00857 raiseScriptError(s, "luaChr_GetExp called for nonexistent skill number %d.", skill);
00858 return 0;
00859 }
00860
00861 int exp = c->getExperience(skill - CHAR_SKILL_BEGIN);
00862
00863 lua_pushinteger(s, exp);
00864 return 1;
00865 }
00866
00867
00874 static int chr_give_exp(lua_State *s)
00875 {
00876 Character *c = getCharacter(s, 1);
00877 if (!c)
00878 {
00879 raiseScriptError(s, "luaChr_GiveExp called for nonexistent character.");
00880 return 0;
00881 }
00882
00883 int skill = lua_tointeger(s, 2);
00884 if (skill < CHAR_SKILL_BEGIN || skill >= CHAR_SKILL_END)
00885 {
00886 raiseScriptError(s, "luaChr_GiveExp called for nonexistent skill number %d.", skill);
00887 return 0;
00888 }
00889
00890 int exp = lua_tointeger(s, 3);
00891
00892 c->receiveExperience(skill, exp);
00893
00894 return 0;
00895 }
00896
00901 static int chr_set_hair_style(lua_State *s)
00902 {
00903 Character *c = getCharacter(s, 1);
00904 if (!c)
00905 {
00906 raiseScriptError(s, "chr_set_hair_style called for nonexistent character.");
00907 return 0;
00908 }
00909
00910 int style = lua_tointeger(s, 2);
00911 if (style < 0)
00912 {
00913 raiseScriptError(s, "chr_set_hair_style called for nonexistent style id %d.", style);
00914 return 0;
00915 }
00916
00917 c->setHairStyle(style);
00918 c->raiseUpdateFlags(UPDATEFLAG_LOOKSCHANGE);
00919
00920 return 0;
00921 }
00922
00927 static int chr_get_hair_style(lua_State *s)
00928 {
00929 Character *c = getCharacter(s, 1);
00930 if (!c)
00931 {
00932 raiseScriptError(s, "chr_get_hair_style called for nonexistent character.");
00933 return 0;
00934 }
00935
00936 int style = c->getHairStyle();
00937
00938 lua_pushinteger(s, style);
00939 return 1;
00940 }
00941
00946 static int chr_set_hair_color(lua_State *s)
00947 {
00948 Character *c = getCharacter(s, 1);
00949 if (!c)
00950 {
00951 raiseScriptError(s, "chr_set_hair_color called for nonexistent character.");
00952 return 0;
00953 }
00954
00955 int color = lua_tointeger(s, 2);
00956 if (color < 0)
00957 {
00958 raiseScriptError(s, "chr_set_hair_color called for nonexistent style id %d.", color);
00959 return 0;
00960 }
00961
00962 c->setHairColor(color);
00963 c->raiseUpdateFlags(UPDATEFLAG_LOOKSCHANGE);
00964
00965 return 0;
00966 }
00967
00972 static int chr_get_hair_color(lua_State *s)
00973 {
00974 Character *c = getCharacter(s, 1);
00975 if (!c)
00976 {
00977 raiseScriptError(s, "chr_get_hair_color called for nonexistent character.");
00978 return 0;
00979 }
00980
00981 int color = c->getHairColor();
00982
00983 lua_pushinteger(s, color);
00984 return 1;
00985 }
00986
00991 static int chr_get_rights(lua_State *s)
00992 {
00993 Character *c = getCharacter(s, 1);
00994 if (!c)
00995 {
00996 raiseScriptError(s, "chr_get_rights called for nonexistent character.");
00997 return 0;
00998 }
00999 lua_pushinteger(s, c->getAccountLevel());
01000 return 1;
01001 }
01002
01007 static int exp_for_level(lua_State *s)
01008 {
01009 int level = lua_tointeger(s, 1);
01010
01011 int exp = Character::expForLevel(level);
01012
01013 lua_pushinteger(s, exp);
01014 return 1;
01015 }
01016
01022 static int test_tableget(lua_State *s)
01023 {
01024
01025 std::list<float> list;
01026 std::vector<std::string> vector;
01027 std::map<std::string, std::string> map;
01028 std::set<int> set;
01029
01030 LOG_INFO("Pushing List");
01031 list.push_back(12.636);
01032 list.push_back(0.0000000045656);
01033 list.push_back(185645445634566.346);
01034 list.push_back(7835458.11);
01035 pushSTLContainer<float>(s, list);
01036
01037 LOG_INFO("Pushing Vector");
01038 vector.push_back("All");
01039 vector.push_back("your");
01040 vector.push_back("base");
01041 vector.push_back("are");
01042 vector.push_back("belong");
01043 vector.push_back("to");
01044 vector.push_back("us!");
01045 pushSTLContainer<std::string>(s, vector);
01046
01047 LOG_INFO("Pushing Map");
01048 map["Apple"] = "red";
01049 map["Banana"] = "yellow";
01050 map["Lime"] = "green";
01051 map["Plum"] = "blue";
01052 pushSTLContainer<std::string, std::string>(s, map);
01053
01054 LOG_INFO("Pushing Set");
01055 set.insert(12);
01056 set.insert(8);
01057 set.insert(14);
01058 set.insert(10);
01059 pushSTLContainer<int>(s, set);
01060
01061
01062 return 4;
01063 }
01064
01068 static int get_map_id(lua_State *s)
01069 {
01070 lua_pushlightuserdata(s, (void *)®istryKey);
01071 lua_gettable(s, LUA_REGISTRYINDEX);
01072 Script *t = static_cast<Script *>(lua_touserdata(s, -1));
01073 int id = t->getMap()->getID();
01074 lua_pushinteger(s, id);
01075 return 1;
01076 }
01077
01082 static int item_drop(lua_State *s)
01083 {
01084 if (!lua_isnumber(s, 1) ||
01085 !lua_isnumber(s, 2) ||
01086 !lua_isnumber(s, 3))
01087 {
01088 raiseScriptError(s, "trigger_create called with incorrect parameters.");
01089 return 0;
01090 }
01091
01092 int x = lua_tointeger(s, 1);
01093 int y = lua_tointeger(s, 2);
01094 int type = lua_tointeger(s, 3);
01095 int number = 1;
01096 if (lua_isnumber(s, 4))
01097 {
01098 number = lua_tointeger(s, 4);
01099 }
01100
01101 ItemClass *ic = ItemManager::getItem(type);
01102 if (!ic)
01103 {
01104 raiseScriptError(s, "item_drop called with unknown item ID");
01105 }
01106 Item *i = new Item(ic, number);
01107
01108 lua_pushlightuserdata(s, (void *)®istryKey);
01109 lua_gettable(s, LUA_REGISTRYINDEX);
01110 Script *t = static_cast<Script *>(lua_touserdata(s, -1));
01111 MapComposite* map = t->getMap();
01112
01113 i->setMap(map);
01114 Point pos(x, y);
01115 i->setPosition(pos);
01116 GameState::insertSafe(i);
01117
01118 return 0;
01119 }
01120
01121
01122 LuaScript::LuaScript():
01123 nbArgs(-1)
01124 {
01125 mState = luaL_newstate();
01126 luaL_openlibs(mState);
01127
01128
01129 static luaL_reg const callbacks[] = {
01130 { "npc_create", &npc_create },
01131 { "npc_message", &npc_message },
01132 { "npc_choice", &npc_choice },
01133 { "npc_trade", &npc_trade },
01134 { "npc_post", &npc_post },
01135 { "npc_enable", &npc_enable },
01136 { "npc_disable", &npc_disable },
01137 { "chr_warp", &chr_warp },
01138 { "chr_inv_change", &chr_inv_change },
01139 { "chr_inv_count", &chr_inv_count },
01140 { "chr_get_quest", &chr_get_quest },
01141 { "chr_set_quest", &chr_set_quest },
01142 { "chr_get_post", &chr_get_post },
01143 { "chr_get_exp", &chr_get_exp },
01144 { "chr_give_exp", &chr_give_exp },
01145 { "chr_get_rights", &chr_get_rights },
01146 { "chr_set_hair_style", &chr_set_hair_style },
01147 { "chr_get_hair_style", &chr_get_hair_style },
01148 { "chr_set_hair_color", &chr_set_hair_color },
01149 { "chr_get_hair_color", &chr_get_hair_color },
01150 { "exp_for_level", &exp_for_level },
01151 { "monster_create", &monster_create },
01152 { "being_type", &being_type },
01153 { "being_walk", &being_walk },
01154 { "being_say", &being_say },
01155 { "being_damage", &being_damage },
01156 { "being_get_attribute", &being_get_attribute },
01157 { "being_get_name", &being_get_name },
01158 { "posX", &posX },
01159 { "posY", &posY },
01160 { "trigger_create", &trigger_create },
01161 { "chatmessage", &chatmessage },
01162 { "get_beings_in_circle", &get_beings_in_circle },
01163 { "being_register", &being_register },
01164 { "effect_create", &effect_create },
01165 { "test_tableget", &test_tableget },
01166 { "get_map_id", &get_map_id },
01167 { "item_drop", &item_drop },
01168 { NULL, NULL }
01169 };
01170 luaL_register(mState, "tmw", callbacks);
01171
01172
01173 lua_pushlightuserdata(mState, (void *)®istryKey);
01174 lua_pushlightuserdata(mState, this);
01175 lua_settable(mState, LUA_REGISTRYINDEX);
01176
01177 lua_settop(mState, 0);
01178 loadFile("scripts/libs/libtmw.lua");
01179 }
01180