ackfuss-4.4.1/
ackfuss-4.4.1/board/
ackfuss-4.4.1/help/k/
ackfuss-4.4.1/help/n/
ackfuss-4.4.1/help/s/
ackfuss-4.4.1/help/u/
ackfuss-4.4.1/help/v/
ackfuss-4.4.1/help/x/
ackfuss-4.4.1/help/y/
ackfuss-4.4.1/help/z/
ackfuss-4.4.1/src/areaconvert/
ackfuss-4.4.1/src/areaconvert/h/
/***************************************************************************
 * _/_/_/_/  _/    _/  _/_/_/_/ _/_/_/_/ AckFUSS is modified ACK!MUD 4.3.1 *
 * _/        _/    _/  _/       _/       copyright Matt Goff (Kline) 2008  *
 * _/_/      _/    _/  _/_/_/_/ _/_/_/_/                                   *
 * _/        _/    _/        _/       _/ Support for this code is provided *
 * _/        _/_/_/_/  _/_/_/_/ _/_/_/_/ at www.ackmud.net -- check it out!*
 ***************************************************************************/
/* Lua embedding inspired by Nick Gammon's work on Smaug                   */

#include "h/globals.h"

#ifndef DEC_ACT_WIZ_H
#include "h/act_wiz.h"
#endif

#ifndef DEC_COMM_H
#include "h/comm.h"
#endif

#ifndef DEC_DB_H
#include "h/db.h"
#endif

#ifndef DEC_HANDLER_H
#include "h/handler.h"
#endif

#ifndef DEC_LUASCRIPT_H
#include "h/luascript.h"
#endif

#define CH_STATE     "ch.state"
#define OBJ_STATE    "obj.state"
#define ROOM_STATE   "room.state"
#define MUD_LIBRARY  "mud"
#define CH_STARTUP   SCRIPT_DIR "ch_startup.lua"
#define OBJ_STARTUP  SCRIPT_DIR "obj_startup.lua"
#define ROOM_STARTUP SCRIPT_DIR "room_startup.lua"

#define PUSH_STR(from,x) \
 lua_pushstring(L,from->x); \
 lua_setfield(L,-2,#x)

#define PUSH_STRA(from,x,max) \
 lua_newtable(L); \
 for( int i = 0; i < max; ) \
 { \
  lua_pushstring(L,from->x[i]); \
  i++; \
  lua_rawseti(L,-2,i); \
 } \
 lua_setfield(L,-2,#x)

#define PUSH_NUM(from,x) \
 lua_pushnumber(L,from->x); \
 lua_setfield(L,-2,#x)

#define PUSH_NUMA(from,x,max) \
 lua_newtable(L); \
 for( int i = 0; i < max; ) \
 { \
  lua_pushnumber(L,from->x[i]); \
  i++; \
  lua_rawseti(L,-2,i); \
 } \
 lua_setfield(L,-2,#x)

static const struct luaL_reg mudlib [] = 
{
 {"char_info",    L_character_info},
 {"obj_info",     L_obj_info      },
 {"room_info",    L_room_info     },
 {"send_to_char", L_send_to_char  },
 {"recho",        L_recho         },
 {NULL, NULL}
};

void init_lua( CHAR_DATA *ch )
{
 ch->lua->owner = ch;
 ch->lua->type = LUA_TYPE_CH;
 luaL_openlibs(ch->lua->L); /* open all standard libraries */

 /* call as Lua function because we need the environment  */
 lua_pushcfunction(ch->lua->L,RegisterLuaRoutines);
 lua_pushstring(ch->lua->L,CH_STATE);  /* push address */
 lua_pushlightuserdata(ch->lua->L,(void *)ch);    /* push value */
 lua_call(ch->lua->L,2,0);
 
 /* run initialiation script */
 if( luaL_loadfile(ch->lua->L,CH_STARTUP) || CallLuaWithTraceBack(ch->lua->L,0,0) )
 {
  const char * sError = lua_tostring(ch->lua->L,-1);

  snprintf(log_buf,(2 * MIL),"Error loading ch Lua startup file:\n %s\n",sError);
  monitor_chan(log_buf,MONITOR_DEBUG);
 }

 lua_settop(ch->lua->L,0); /* get rid of stuff lying around */
 return;
}

void init_lua( OBJ_DATA *obj )
{
 obj->lua->owner = obj;
 obj->lua->type = LUA_TYPE_OB;
 luaL_openlibs(obj->lua->L);

 lua_pushcfunction(obj->lua->L,RegisterLuaRoutines);
 lua_pushstring(obj->lua->L,OBJ_STATE);
 lua_pushlightuserdata(obj->lua->L,(void *)obj);
 lua_call(obj->lua->L,2,0);

 if( luaL_loadfile(obj->lua->L,OBJ_STARTUP) || CallLuaWithTraceBack(obj->lua->L,0,0) )
 {
  const char * sError = lua_tostring(obj->lua->L,-1);

  snprintf(log_buf,(2 * MIL),"Error loading obj Lua startup file:\n %s\n",sError);
  monitor_chan(log_buf,MONITOR_DEBUG);
 }

 lua_settop(obj->lua->L,0);
 return;
}

void init_lua( ROOM_INDEX_DATA *room )
{
 room->lua->owner = room;
 room->lua->type = LUA_TYPE_RM;
 luaL_openlibs(room->lua->L);

 lua_pushcfunction(room->lua->L,RegisterLuaRoutines);
 lua_pushstring(room->lua->L,ROOM_STATE);
 lua_pushlightuserdata(room->lua->L,(void *)room);
 lua_call(room->lua->L,2,0);

 if( luaL_loadfile(room->lua->L,ROOM_STARTUP) || CallLuaWithTraceBack(room->lua->L,0,0) )
 {
  const char * sError = lua_tostring(room->lua->L,-1);

  snprintf(log_buf,(2 * MIL),"Error loading room Lua startup file:\n %s\n",sError);
  monitor_chan(log_buf,MONITOR_DEBUG);
 }

 lua_settop(room->lua->L,0);
 return;
}

lua_State *find_lua_function( CHAR_DATA *ch, string arg )
{
 lua_State *L = ch->lua->L;
  
 if( !L || arg.empty() )
  return NULL;  /* can't do it */
    
 /* find requested function */
  
 lua_getglobal(L,arg.c_str());  
 if( !lua_isfunction(L,-1) )
 {
  lua_pop(L,1);
  snprintf(log_buf,(2 * MIL),"Warning: Lua script function '%s' does not exist",arg.c_str());
  monitor_chan(log_buf,MONITOR_DEBUG);
  return NULL;  /* not there */
 }
      
 return L;  
}

lua_State *find_lua_function( OBJ_DATA *ob, string arg )
{
 lua_State *L = ob->lua->L;

 if( !L || arg.empty() )
  return NULL;  /* can't do it */

 /* find requested function */

 lua_getglobal(L,arg.c_str());
 if( !lua_isfunction(L,-1) )
 {
  lua_pop(L,1);
  snprintf(log_buf,(2 * MIL),"Warning: Lua script function '%s' does not exist",arg.c_str());
  monitor_chan(log_buf,MONITOR_DEBUG);
  return NULL;  /* not there */
 }

 return L;
}

lua_State *find_lua_function( ROOM_INDEX_DATA *rm, string arg )
{
 lua_State *L = rm->lua->L;

 if( !L || arg.empty() )
  return NULL;  /* can't do it */

 /* find requested function */

 lua_getglobal(L,arg.c_str());
 if( !lua_isfunction(L,-1) )
 {
  lua_pop(L,1);
  snprintf(log_buf,(2 * MIL),"Warning: Lua script function '%s' does not exist",arg.c_str());
  monitor_chan(log_buf,MONITOR_DEBUG);
  return NULL;  /* not there */
 }

 return L;
}

void call_lua_function( lua_State *L, string str, const int nArgs )
{
 if( CallLuaWithTraceBack(L,nArgs,0) )
 {
  snprintf(log_buf,(2 * MIL),"Error executing Lua function %s:\n %s",str.c_str(),lua_tostring(L,-1));
  monitor_chan(log_buf,MONITOR_DEBUG);
  lua_pop(L,1);  /* pop error */
 }  /* end of error */

 return;   
}

int RegisterLuaRoutines( lua_State *L )
{
 lua_newtable(L);  /* environment */
 lua_replace(L,LUA_ENVIRONINDEX);

 /* this makes environment variable "ch.state" by the pointer to our character */
 lua_settable(L,LUA_ENVIRONINDEX);

 /* register all mud.xxx routines */
 luaL_register(L,MUD_LIBRARY,mudlib);
  
 /* using interpret now
 RegisterLuaCommands (L);
 */

 return 0;
}

int CallLuaWithTraceBack( lua_State *L, const int iArguments, const int iReturn )
{
 int error;
 int base = lua_gettop(L) - iArguments;  /* function index */

 GetTracebackFunction(L);
 if( lua_isnil(L,-1) )
 {
  lua_pop(L,1);   /* pop non-existent function  */
  error = lua_pcall(L,iArguments,iReturn,0);
 }  
 else
 {
  lua_insert(L,base);  /* put it under chunk and args */
  error = lua_pcall(L,iArguments,iReturn,base);
  lua_remove(L,base);  /* remove traceback function */
 }

 return error;
}

void GetTracebackFunction( lua_State *L )
{
 lua_pushliteral(L,LUA_DBLIBNAME);  /* "debug"   */
 lua_rawget(L,LUA_GLOBALSINDEX);    /* get debug library   */

 if( !lua_istable(L,-1) )
 {
  lua_pop(L,2);   /* pop result and debug table  */
  lua_pushnil(L);
  return;
 }

 /* get debug.traceback  */
 lua_pushstring(L,"traceback");  
 lua_rawget(L,-2);               /* get traceback function  */
  
 if( !lua_isfunction(L,-1) )
 {
  lua_pop(L,2);   /* pop result and debug table  */
  lua_pushnil(L);
  return;
 }

 lua_remove (L, -2);   /* remove debug table, leave traceback function  */
}

ROOM_INDEX_DATA *L_getroom( lua_State *L )
{
 CHAR_DATA *ch;
 OBJ_DATA *ob;
 ROOM_INDEX_DATA *rm;
 LUA_DATA *lua;
 list<LUA_DATA *>::iterator li;

 for( li = lua_list.begin(); li != lua_list.end(); li++ )
 {
  lua = *li;

  switch( lua->type )
  {
   default:
   {
    snprintf(log_buf,(2 * MIL),"Invalid Lua owner type in lua_list: %d",lua->type);
    monitor_chan(log_buf,MONITOR_DEBUG);
    return NULL;
   }
   case LUA_TYPE_CH:
   {
    ch = static_cast<CHAR_DATA *>(lua->owner);
    if( ch->lua->L == L )
    {
     lua_pushstring(L,CH_STATE);
     lua_gettable(L,LUA_ENVIRONINDEX);
     lua_pop(L,1);
     return ch->in_room;
    }
   }
   case LUA_TYPE_OB:
   {
    ob = static_cast<OBJ_DATA *>(lua->owner);
    if( ob->lua->L == L )
    {
     lua_pushstring(L,OBJ_STATE);
     lua_gettable(L,LUA_ENVIRONINDEX);
     lua_pop(L,1);
     return in_loc(ob);
    }
   }
   case LUA_TYPE_RM:
   {
    rm = static_cast<ROOM_INDEX_DATA *>(lua->owner);
    if( rm->lua->L == L )
    {
     lua_pushstring(L,ROOM_STATE);
     lua_gettable(L,LUA_ENVIRONINDEX);
     lua_pop(L,1);
     return rm;
    }
   }
  }
 }

 return NULL;
}

CHAR_DATA *L_getchar( lua_State *L )
{
 /* retrieve our character */
  CHAR_DATA * ch;
  
 /* retrieve the character */
 lua_pushstring(L,CH_STATE);  /* push address */
 lua_gettable(L,LUA_ENVIRONINDEX);  /* retrieve value */

 ch = (CHAR_DATA *)lua_touserdata(L,-1);  /* convert to data */
 lua_pop(L,1);  /* pop result */

 return ch;
}

int L_character_info( lua_State *L )
{
 CHAR_DATA *ch = NULL;
 bool found = false;
 list<LUA_DATA *>::iterator li;
 LUA_DATA *lua = NULL;

 for( li = lua_list.begin(); li != lua_list.end(); li++ )
 {
  lua = *li;
  if( lua->type == LUA_TYPE_CH )
  {
   ch = static_cast<CHAR_DATA *>(lua->owner);

   if( ch->lua->L == L )
    found = true;
  }
 }

 if( !found )
  return 0;

 lua_newtable(L);  /* table for the info */
  
 /* strings */
 PUSH_STR(ch,description.c_str());
 PUSH_STR(ch,long_descr.c_str());
 PUSH_STR(ch,long_descr_orig.c_str());
 PUSH_STR(ch,name.c_str());
 PUSH_STR(ch,old_prompt.c_str());
 PUSH_STR(ch,prompt.c_str());
 PUSH_STR(ch,searching.c_str());

 /* numbers */
 PUSH_NUM(ch,alignment);
 PUSH_NUM(ch,armor);
 PUSH_NUM(ch,carry_number);
 PUSH_NUM(ch,carry_weight);
 PUSH_NUM(ch,clan);
 PUSH_NUMA(ch,cooldown,MAX_COOLDOWN);
 PUSH_NUM(ch,damroll);
 PUSH_NUM(ch,exp);
 PUSH_NUM(ch,hit);
 PUSH_NUM(ch,hitroll);
 PUSH_NUM(ch,level);
 PUSH_NUMA(ch,lvl,MAX_CLASS);
 PUSH_NUMA(ch,lvl2,MAX_CLASS);
 PUSH_NUM(ch,mana);
 PUSH_NUM(ch,max_hit);
 PUSH_NUM(ch,max_mana);
 PUSH_NUM(ch,max_move);
 PUSH_NUM(ch,move);
 PUSH_NUM(ch,npc);
 PUSH_NUM(ch,num_followers);
 PUSH_NUM(ch,played);
 PUSH_NUM(ch,poly_level);
 PUSH_NUM(ch,position);
 PUSH_NUM(ch,p_class);
 PUSH_NUM(ch,race);
 PUSH_NUM(ch,saving_throw);
 PUSH_NUM(ch,sex);
 PUSH_NUMA(ch,speed,MAX_SPEED);
 PUSH_NUM(ch,stance);
 PUSH_NUM(ch,stun_timer);
 PUSH_NUM(ch,switched);
 PUSH_NUM(ch,timer);
 PUSH_NUM(ch,trust);
 PUSH_NUM(ch,wait);
 PUSH_NUM(ch,wimpy);
 PUSH_NUM(ch,wizbit);

 if( !IS_NPC(ch) )
 {
  lua_newtable(L);
  /* strings */
  PUSH_STR(ch->pcdata,assist_msg);
  PUSH_STR(ch->pcdata,bamfin);
  PUSH_STR(ch->pcdata,bamfout);
  PUSH_STR(ch->pcdata,email_address);
  PUSH_STR(ch->pcdata,load_msg);
  PUSH_STR(ch->pcdata,room_enter);
  PUSH_STR(ch->pcdata,room_exit);
  PUSH_STR(ch->pcdata,title);
  PUSH_STR(ch->pcdata,who_name);

  /* numbers */
  PUSH_NUM(ch->pcdata,adept_level);
  PUSH_NUMA(ch->pcdata,condition,MAX_COND);
  PUSH_NUM(ch->pcdata,death_cnt);
  PUSH_NUM(ch->pcdata,invis);
  PUSH_NUMA(ch->pcdata,learned,MAX_SKILL);
  PUSH_NUM(ch->pcdata,max_con);
  PUSH_NUM(ch->pcdata,max_dex);
  PUSH_NUM(ch->pcdata,max_int);
  PUSH_NUM(ch->pcdata,max_str);
  PUSH_NUM(ch->pcdata,max_wis);
  PUSH_NUM(ch->pcdata,mod_con);
  PUSH_NUM(ch->pcdata,mod_dex);
  PUSH_NUM(ch->pcdata,mod_int);
  PUSH_NUM(ch->pcdata,mod_str);
  PUSH_NUM(ch->pcdata,mod_wis);
  PUSH_NUMA(ch->pcdata,order,MAX_CLASS);
  PUSH_NUM(ch->pcdata,perm_con);
  PUSH_NUM(ch->pcdata,perm_dex);
  PUSH_NUM(ch->pcdata,perm_int);
  PUSH_NUM(ch->pcdata,perm_str);
  PUSH_NUM(ch->pcdata,perm_wis);
  PUSH_NUM(ch->pcdata,practice);
  PUSH_NUM(ch->pcdata,quest_points);
  PUSH_NUM(ch->pcdata,recall_vnum);
  PUSH_NUM(ch->pcdata,ruler_rank);
  PUSH_NUM(ch->pcdata,sentence);

  lua_setfield(L,-2,"pcdata");
 }
 else
 {
  lua_newtable(L);
  /* strings */
  PUSH_STR(ch->npcdata,short_descr);

  /* numbers */
  PUSH_NUM(ch->npcdata,cast);
  PUSH_NUM(ch->npcdata,def);
  PUSH_NUM(ch->npcdata,extract_timer);
  PUSH_NUM(ch->npcdata,resist);
  PUSH_NUM(ch->npcdata,skills);
  PUSH_NUM(ch->npcdata,strong_magic);
  PUSH_NUM(ch->npcdata,suscept);
  PUSH_NUM(ch->npcdata,weak_magic);

  lua_setfield(L,-2,"npcdata");
 }

 return 1;
}

int L_obj_info( lua_State *L )
{
 OBJ_DATA *ob = NULL;
 bool found = false;
 list<LUA_DATA *>::iterator li;
 LUA_DATA *lua = NULL;

 for( li = lua_list.begin(); li != lua_list.end(); li++ )
 {
  lua = *li;
  if( lua->type == LUA_TYPE_OB )
  {
   ob = static_cast<OBJ_DATA *>(lua->owner);

   if( ob->lua->L == L )
    found = true;
  }
 }

 if( !found )
  return 0;

 lua_newtable(L);

 PUSH_STR(ob,owner);
 PUSH_STR(ob,name);
 PUSH_STR(ob,script_name);
 PUSH_STR(ob,short_descr);
 PUSH_STR(ob,long_descr);

 PUSH_NUM(ob,item_type);
 PUSH_NUM(ob,item_apply);
 PUSH_NUM(ob,wear_loc);
 PUSH_NUM(ob,weight);
 PUSH_NUM(ob,cost);
 PUSH_NUM(ob,level);
 PUSH_NUM(ob,timer);
 PUSH_NUMA(ob,value,MAX_OBJ_VALUE);
 PUSH_NUM(ob,durability);
 PUSH_NUM(ob,max_durability);
 PUSH_NUM(ob,speed);

 return 1;
}

int L_room_info( lua_State *L )
{
 ROOM_INDEX_DATA *rm = NULL;
 bool found = false;
 list<LUA_DATA *>::iterator li;
 LUA_DATA *lua = NULL;

 for( li = lua_list.begin(); li != lua_list.end(); li++ )
 {
  lua = *li;
  if( lua->type == LUA_TYPE_RM )
  {
   rm = static_cast<ROOM_INDEX_DATA *>(lua->owner);

   if( rm->lua->L == L )
    found = true;
  }
 }

 if( !found )
  return 0;

 lua_newtable(L);

 PUSH_STR(rm,description);
 PUSH_STR(rm,name);
 PUSH_STR(rm,script_name);

 PUSH_NUM(rm,affected_by);
 PUSH_NUM(rm,light);
 PUSH_NUM(rm,sector_type);
 PUSH_NUM(rm,vnum);

 return 1;
}

int L_send_to_char( lua_State *L )
{
 send_to_char(luaL_checkstring(L,1),L_getchar(L));
 return 0;
}

int L_recho( lua_State *L )
{
 recho(L_getroom(L),luaL_checkstring(L,1));
 return 0;
}

void call_lua( LUA_DATA *lua, string str, string arg )
{
 if( lua )
 {
  if( lua->type == LUA_TYPE_CH )
   call_lua(static_cast<CHAR_DATA *>(lua->owner),str,arg);
  else if( lua->type == LUA_TYPE_OB )
   call_lua(static_cast<OBJ_DATA *>(lua->owner),str,arg);
  else if( lua->type == LUA_TYPE_RM )
   call_lua(static_cast<ROOM_INDEX_DATA *>(lua->owner),str,arg);
  else
   monitor_chan("Invalid Lua type in call_lua().",MONITOR_DEBUG);
 }
}

void call_lua( CHAR_DATA *ch, string str, string arg )
{
 int cnt = 0;

 if( !ch || str.empty() )  /* note, argument is OPTIONAL */
  return;

 lua_State *L = find_lua_function(ch,str.c_str());
   
 if( !L )
  return;
  
 /* if they want to send an argument, push it now */  
 if( !arg.empty() )
 {
  cnt++;
  lua_pushstring(L,arg.c_str());  /* push argument, if any */
 }

 call_lua_function(L,str,cnt);

 return;
}

void call_lua( OBJ_DATA *ob, string str, string arg )
{
 int cnt = 0;

 if( !ob || str.empty() )  /* note, argument is OPTIONAL */
  return;

 lua_State *L = find_lua_function(ob,str.c_str());

 if( !L )
  return;

 /* if they want to send an argument, push it now */
 if( !arg.empty() )
 {
  cnt++;
  lua_pushstring(L,arg.c_str());  /* push argument, if any */
 }

 call_lua_function(L,str,cnt);

 return;
}

void call_lua( ROOM_INDEX_DATA *rm, string str, string arg )
{
 int cnt = 0;

 if( !rm || str.empty() )  /* note, argument is OPTIONAL */
  return;

 lua_State *L = find_lua_function(rm,str.c_str());

 if( !L )
  return;

 /* if they want to send an argument, push it now */
 if( !arg.empty() )
 {
  cnt++;
  lua_pushstring(L,arg.c_str());  /* push argument, if any */
 }

 call_lua_function(L,str,cnt);

 return;
}