// $Id: script.c 148 2004-09-30 14:05:37Z MouseJstr $
//#define DEBUG_FUNCIN
//#define DEBUG_DISP
//#define DEBUG_RUN
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifndef LCCWIN32
#include <sys/time.h>
#endif
#include <time.h>
#include <math.h>
#include "../common/socket.h"
#include "../common/timer.h"
#include "../common/lock.h"
#include "../common/mt_rand.h"
#include "atcommand.h"
#include "battle.h"
#include "chat.h"
#include "chrif.h"
#include "clif.h"
#include "../common/db.h"
#include "guild.h"
#include "intif.h"
#include "itemdb.h"
#include "../common/lock.h"
#include "map.h"
#include "mob.h"
#include "npc.h"
#include "party.h"
#include "pc.h"
#include "script.h"
#include "skill.h"
#include "storage.h"
#ifdef MEMWATCH
#include "memwatch.h"
#endif
#define SCRIPT_BLOCK_SIZE 256
enum
{ LABEL_NEXTLINE = 1, LABEL_START };
static unsigned char *script_buf;
static int script_pos, script_size;
char *str_buf;
int str_pos, str_size;
static struct str_data_t
{
int type;
int str;
int backpatch;
int label;
int (*func) (struct script_state *);
int val;
int next;
} *str_data;
int str_num = LABEL_START, str_data_size;
int str_hash[16];
static struct dbt *mapreg_db = NULL;
static struct dbt *mapregstr_db = NULL;
static int mapreg_dirty = -1;
char mapreg_txt[256] = "save/mapreg.txt";
#define MAPREG_AUTOSAVE_INTERVAL (10*1000)
static struct dbt *scriptlabel_db = NULL;
static struct dbt *userfunc_db = NULL;
struct dbt *script_get_label_db (void)
{
return scriptlabel_db;
}
struct dbt *script_get_userfunc_db (void)
{
if (!userfunc_db)
userfunc_db = strdb_init (50);
return userfunc_db;
}
static char pos[11][100] =
{ "頭", "体", "左手", "右手", "ローブ", "靴", "アクセサリー1",
"アクセサリー2", "頭2", "頭3", "装着していない"
};
static struct Script_Config
{
int warn_func_no_comma;
int warn_cmd_no_comma;
int warn_func_mismatch_paramnum;
int warn_cmd_mismatch_paramnum;
int check_cmdcount;
int check_gotocount;
} script_config;
static int parse_cmd_if = 0;
static int parse_cmd;
/*==========================================
* ローカルプロトタイプ宣言 (必要な物のみ)
*------------------------------------------
*/
unsigned char *parse_subexpr (unsigned char *, int);
int buildin_mes (struct script_state *st);
int buildin_goto (struct script_state *st);
int buildin_callsub (struct script_state *st);
int buildin_callfunc (struct script_state *st);
int buildin_return (struct script_state *st);
int buildin_getarg (struct script_state *st);
int buildin_next (struct script_state *st);
int buildin_close (struct script_state *st);
int buildin_close2 (struct script_state *st);
int buildin_menu (struct script_state *st);
int buildin_rand (struct script_state *st);
int buildin_pow (struct script_state *st);
int buildin_warp (struct script_state *st);
int buildin_isat (struct script_state *st);
int buildin_areawarp (struct script_state *st);
int buildin_heal (struct script_state *st);
int buildin_itemheal (struct script_state *st);
int buildin_percentheal (struct script_state *st);
int buildin_jobchange (struct script_state *st);
int buildin_input (struct script_state *st);
int buildin_setlook (struct script_state *st);
int buildin_set (struct script_state *st);
int buildin_setarray (struct script_state *st);
int buildin_cleararray (struct script_state *st);
int buildin_copyarray (struct script_state *st);
int buildin_getarraysize (struct script_state *st);
int buildin_deletearray (struct script_state *st);
int buildin_getelementofarray (struct script_state *st);
int buildin_if (struct script_state *st);
int buildin_getitem (struct script_state *st);
int buildin_getitem2 (struct script_state *st);
int buildin_makeitem (struct script_state *st);
int buildin_delitem (struct script_state *st);
int buildin_viewpoint (struct script_state *st);
int buildin_countitem (struct script_state *st);
int buildin_checkweight (struct script_state *st);
int buildin_readparam (struct script_state *st);
int buildin_getcharid (struct script_state *st);
int buildin_getpartyname (struct script_state *st);
int buildin_getpartymember (struct script_state *st);
int buildin_getguildname (struct script_state *st);
int buildin_getguildmaster (struct script_state *st);
int buildin_getguildmasterid (struct script_state *st);
int buildin_strcharinfo (struct script_state *st);
int buildin_getequipid (struct script_state *st);
int buildin_getequipname (struct script_state *st);
int buildin_getbrokenid (struct script_state *st); // [Valaris]
int buildin_repair (struct script_state *st); // [Valaris]
int buildin_getequipisequiped (struct script_state *st);
int buildin_getequipisenableref (struct script_state *st);
int buildin_getequipisidentify (struct script_state *st);
int buildin_getequiprefinerycnt (struct script_state *st);
int buildin_getequipweaponlv (struct script_state *st);
int buildin_getequippercentrefinery (struct script_state *st);
int buildin_successrefitem (struct script_state *st);
int buildin_failedrefitem (struct script_state *st);
int buildin_cutin (struct script_state *st);
int buildin_cutincard (struct script_state *st);
int buildin_statusup (struct script_state *st);
int buildin_statusup2 (struct script_state *st);
int buildin_bonus (struct script_state *st);
int buildin_bonus2 (struct script_state *st);
int buildin_bonus3 (struct script_state *st);
int buildin_skill (struct script_state *st);
int buildin_setskill (struct script_state *st);
int buildin_guildskill (struct script_state *st);
int buildin_getskilllv (struct script_state *st);
int buildin_getgdskilllv (struct script_state *st);
int buildin_basicskillcheck (struct script_state *st);
int buildin_getgmlevel (struct script_state *st);
int buildin_end (struct script_state *st);
int buildin_getopt2 (struct script_state *st);
int buildin_setopt2 (struct script_state *st);
int buildin_checkoption (struct script_state *st);
int buildin_setoption (struct script_state *st);
int buildin_setcart (struct script_state *st);
int buildin_checkcart (struct script_state *st); // check cart [Valaris]
int buildin_setfalcon (struct script_state *st);
int buildin_checkfalcon (struct script_state *st); // check falcon [Valaris]
int buildin_setriding (struct script_state *st);
int buildin_checkriding (struct script_state *st); // check for pecopeco [Valaris]
int buildin_savepoint (struct script_state *st);
int buildin_gettimetick (struct script_state *st);
int buildin_gettime (struct script_state *st);
int buildin_gettimestr (struct script_state *st);
int buildin_openstorage (struct script_state *st);
int buildin_guildopenstorage (struct script_state *st);
int buildin_itemskill (struct script_state *st);
int buildin_monster (struct script_state *st);
int buildin_areamonster (struct script_state *st);
int buildin_killmonster (struct script_state *st);
int buildin_killmonsterall (struct script_state *st);
int buildin_doevent (struct script_state *st);
int buildin_donpcevent (struct script_state *st);
int buildin_addtimer (struct script_state *st);
int buildin_deltimer (struct script_state *st);
int buildin_addtimercount (struct script_state *st);
int buildin_initnpctimer (struct script_state *st);
int buildin_stopnpctimer (struct script_state *st);
int buildin_startnpctimer (struct script_state *st);
int buildin_setnpctimer (struct script_state *st);
int buildin_getnpctimer (struct script_state *st);
int buildin_announce (struct script_state *st);
int buildin_mapannounce (struct script_state *st);
int buildin_areaannounce (struct script_state *st);
int buildin_getusers (struct script_state *st);
int buildin_getmapusers (struct script_state *st);
int buildin_getareausers (struct script_state *st);
int buildin_getareadropitem (struct script_state *st);
int buildin_enablenpc (struct script_state *st);
int buildin_disablenpc (struct script_state *st);
int buildin_enablearena (struct script_state *st); // Added by RoVeRT
int buildin_disablearena (struct script_state *st); // Added by RoVeRT
int buildin_hideoffnpc (struct script_state *st);
int buildin_hideonnpc (struct script_state *st);
int buildin_sc_start (struct script_state *st);
int buildin_sc_start2 (struct script_state *st);
int buildin_sc_end (struct script_state *st);
int buildin_sc_check (struct script_state *st); // [Fate]
int buildin_getscrate (struct script_state *st);
int buildin_debugmes (struct script_state *st);
int buildin_resetlvl (struct script_state *st);
int buildin_resetstatus (struct script_state *st);
int buildin_resetskill (struct script_state *st);
int buildin_changebase (struct script_state *st);
int buildin_changesex (struct script_state *st);
int buildin_waitingroom (struct script_state *st);
int buildin_delwaitingroom (struct script_state *st);
int buildin_enablewaitingroomevent (struct script_state *st);
int buildin_disablewaitingroomevent (struct script_state *st);
int buildin_getwaitingroomstate (struct script_state *st);
int buildin_warpwaitingpc (struct script_state *st);
int buildin_attachrid (struct script_state *st);
int buildin_detachrid (struct script_state *st);
int buildin_isloggedin (struct script_state *st);
int buildin_setmapflagnosave (struct script_state *st);
int buildin_setmapflag (struct script_state *st);
int buildin_removemapflag (struct script_state *st);
int buildin_pvpon (struct script_state *st);
int buildin_pvpoff (struct script_state *st);
int buildin_gvgon (struct script_state *st);
int buildin_gvgoff (struct script_state *st);
int buildin_emotion (struct script_state *st);
int buildin_maprespawnguildid (struct script_state *st);
int buildin_agitstart (struct script_state *st); // <Agit>
int buildin_agitend (struct script_state *st);
int buildin_agitcheck (struct script_state *st); // <Agitcheck>
int buildin_flagemblem (struct script_state *st); // Flag Emblem
int buildin_getcastlename (struct script_state *st);
int buildin_getcastledata (struct script_state *st);
int buildin_setcastledata (struct script_state *st);
int buildin_requestguildinfo (struct script_state *st);
int buildin_getequipcardcnt (struct script_state *st);
int buildin_successremovecards (struct script_state *st);
int buildin_failedremovecards (struct script_state *st);
int buildin_marriage (struct script_state *st);
int buildin_wedding_effect (struct script_state *st);
int buildin_divorce (struct script_state *st);
int buildin_getitemname (struct script_state *st);
int buildin_getspellinvocation (struct script_state *st); // [Fate]
int buildin_getanchorinvocation (struct script_state *st); // [Fate]
int buildin_getexp (struct script_state *st);
int buildin_getinventorylist (struct script_state *st);
int buildin_getskilllist (struct script_state *st);
int buildin_get_pool_skills (struct script_state *st); // [fate]
int buildin_get_activated_pool_skills (struct script_state *st); // [fate]
int buildin_get_unactivated_pool_skills (struct script_state *st); // [PO]
int buildin_activate_pool_skill (struct script_state *st); // [fate]
int buildin_deactivate_pool_skill (struct script_state *st); // [fate]
int buildin_check_pool_skill (struct script_state *st); // [fate]
int buildin_getskilllist (struct script_state *st);
int buildin_getskilllist (struct script_state *st);
int buildin_clearitem (struct script_state *st);
int buildin_classchange (struct script_state *st);
int buildin_misceffect (struct script_state *st);
int buildin_soundeffect (struct script_state *st);
int buildin_setcastledata (struct script_state *st);
int buildin_mapwarp (struct script_state *st);
int buildin_inittimer (struct script_state *st);
int buildin_stoptimer (struct script_state *st);
int buildin_cmdothernpc (struct script_state *st);
int buildin_mobcount (struct script_state *st);
int buildin_strmobinfo (struct script_state *st); // Script for displaying mob info [Valaris]
int buildin_guardian (struct script_state *st); // Script for displaying mob info [Valaris]
int buildin_guardianinfo (struct script_state *st); // Script for displaying mob info [Valaris]
int buildin_npcskilleffect (struct script_state *st); // skill effects for npcs [Valaris]
int buildin_specialeffect (struct script_state *st); // special effect script [Valaris]
int buildin_specialeffect2 (struct script_state *st); // special effect script [Valaris]
int buildin_nude (struct script_state *st); // nude [Valaris]
int buildin_gmcommand (struct script_state *st); // [MouseJstr]
int buildin_movenpc (struct script_state *st); // [MouseJstr]
int buildin_npcwarp (struct script_state *st); // [remoitnane]
int buildin_message (struct script_state *st); // [MouseJstr]
int buildin_npctalk (struct script_state *st); // [Valaris]
int buildin_hasitems (struct script_state *st); // [Valaris]
int buildin_getlook (struct script_state *st); //Lorky [Lupus]
int buildin_getsavepoint (struct script_state *st); //Lorky [Lupus]
int buildin_getpartnerid (struct script_state *st); // [Fate]
int buildin_areatimer (struct script_state *st); // [Jaxad0127]
int buildin_isin (struct script_state *st); // [Jaxad0127]
int buildin_shop (struct script_state *st); // [MadCamel]
int buildin_isdead (struct script_state *st); // [Jaxad0127]
int buildin_fakenpcname (struct script_state *st); //[Kage]
int buildin_unequip_by_id (struct script_state *st); // [Freeyorp]
int buildin_getx (struct script_state *st); // [Kage]
int buildin_gety (struct script_state *st); // [Kage]
void push_val (struct script_stack *stack, int type, int val);
int run_func (struct script_state *st);
int mapreg_setreg (int num, int val);
int mapreg_setregstr (int num, const char *str);
struct
{
int (*func) (struct script_state *);
char *name;
char *arg;
} buildin_func[] =
{
{
buildin_mes, "mes", "s"},
{
buildin_next, "next", ""},
{
buildin_close, "close", ""},
{
buildin_close2, "close2", ""},
{
buildin_menu, "menu", "sL*"},
{
buildin_goto, "goto", "L"},
{
buildin_callsub, "callsub", "L*"},
{
buildin_callfunc, "callfunc", "F*"},
{
buildin_return, "return", "*"},
{
buildin_getarg, "getarg", "i"},
{
buildin_jobchange, "jobchange", "i*"},
{
buildin_input, "input", "N"},
{
buildin_warp, "warp", "Mxy"},
{
buildin_isat, "isat", "Mxy"},
{
buildin_areawarp, "areawarp", "MxyxyMxy"},
{
buildin_setlook, "setlook", "ii"},
{
buildin_set, "set", "Ne"},
{
buildin_setarray, "setarray", "Ne*"},
{
buildin_cleararray, "cleararray", "Nei"},
{
buildin_copyarray, "copyarray", "NNi"},
{
buildin_getarraysize, "getarraysize", "N"},
{
buildin_deletearray, "deletearray", "N*"},
{
buildin_getelementofarray, "getelementofarray", "Ni"},
{
buildin_if, "if", "iF*"},
{
buildin_getitem, "getitem", "Ii**"},
{
buildin_getitem2, "getitem2", "iiiiiiiii*"},
{
buildin_makeitem, "makeitem", "IiMxy"},
{
buildin_delitem, "delitem", "Ii"},
{
buildin_cutin, "cutin", "si"},
{
buildin_cutincard, "cutincard", "i"},
{
buildin_viewpoint, "viewpoint", "iiiii"},
{
buildin_heal, "heal", "ii"},
{
buildin_itemheal, "itemheal", "ii"},
{
buildin_percentheal, "percentheal", "ii"},
{
buildin_rand, "rand", "i*"},
{
buildin_pow, "pow", "ii"},
{
buildin_countitem, "countitem", "I"},
{
buildin_checkweight, "checkweight", "Ii"},
{
buildin_readparam, "readparam", "i*"},
{
buildin_getcharid, "getcharid", "i*"},
{
buildin_getpartyname, "getpartyname", "i"},
{
buildin_getpartymember, "getpartymember", "i"},
{
buildin_getguildname, "getguildname", "i"},
{
buildin_getguildmaster, "getguildmaster", "i"},
{
buildin_getguildmasterid, "getguildmasterid", "i"},
{
buildin_strcharinfo, "strcharinfo", "i"},
{
buildin_getequipid, "getequipid", "i"},
{
buildin_getequipname, "getequipname", "i"},
{
buildin_getbrokenid, "getbrokenid", "i"}, // [Valaris]
{
buildin_repair, "repair", "i"}, // [Valaris]
{
buildin_getequipisequiped, "getequipisequiped", "i"},
{
buildin_getequipisenableref, "getequipisenableref", "i"},
{
buildin_getequipisidentify, "getequipisidentify", "i"},
{
buildin_getequiprefinerycnt, "getequiprefinerycnt", "i"},
{
buildin_getequipweaponlv, "getequipweaponlv", "i"},
{
buildin_getequippercentrefinery, "getequippercentrefinery", "i"},
{
buildin_successrefitem, "successrefitem", "i"},
{
buildin_failedrefitem, "failedrefitem", "i"},
{
buildin_statusup, "statusup", "i"},
{
buildin_statusup2, "statusup2", "ii"},
{
buildin_bonus, "bonus", "ii"},
{
buildin_bonus2, "bonus2", "iii"},
{
buildin_bonus3, "bonus3", "iiii"},
{
buildin_skill, "skill", "ii*"},
{
buildin_setskill, "setskill", "ii"}, // [Fate]
{
buildin_guildskill, "guildskill", "ii"},
{
buildin_getskilllv, "getskilllv", "i"},
{
buildin_getgdskilllv, "getgdskilllv", "ii"},
{
buildin_basicskillcheck, "basicskillcheck", "*"},
{
buildin_getgmlevel, "getgmlevel", ""},
{
buildin_end, "end", ""},
{
buildin_getopt2, "getopt2", ""},
{
buildin_setopt2, "setopt2", "i"},
{
buildin_end, "break", ""},
{
buildin_checkoption, "checkoption", "i"},
{
buildin_setoption, "setoption", "i"},
{
buildin_setcart, "setcart", ""},
{
buildin_checkcart, "checkcart", "*"}, //fixed by Lupus (added '*')
{
buildin_setfalcon, "setfalcon", ""},
{
buildin_checkfalcon, "checkfalcon", "*"}, //fixed by Lupus (fixed wrong pointer, added '*')
{
buildin_setriding, "setriding", ""},
{
buildin_checkriding, "checkriding", "*"}, //fixed by Lupus (fixed wrong pointer, added '*')
{
buildin_savepoint, "save", "sii"},
{
buildin_savepoint, "savepoint", "Mxy"},
{
buildin_gettimetick, "gettimetick", "i"},
{
buildin_gettime, "gettime", "i"},
{
buildin_gettimestr, "gettimestr", "si"},
{
buildin_openstorage, "openstorage", "*"},
{
buildin_guildopenstorage, "guildopenstorage", "*"},
{
buildin_itemskill, "itemskill", "iis"},
{
buildin_monster, "monster", "Mxysmi*"},
{
buildin_areamonster, "areamonster", "Mxyxysmi*"},
{
buildin_killmonster, "killmonster", "ME"},
{
buildin_killmonsterall, "killmonsterall", "M"},
{
buildin_doevent, "doevent", "E"},
{
buildin_donpcevent, "donpcevent", "E"},
{
buildin_addtimer, "addtimer", "tE"},
{
buildin_deltimer, "deltimer", "E"},
{
buildin_addtimercount, "addtimercount", "si"},
{
buildin_initnpctimer, "initnpctimer", ""},
{
buildin_stopnpctimer, "stopnpctimer", ""},
{
buildin_startnpctimer, "startnpctimer", "*"},
{
buildin_setnpctimer, "setnpctimer", "i"},
{
buildin_getnpctimer, "getnpctimer", "i"},
{
buildin_announce, "announce", "si"},
{
buildin_mapannounce, "mapannounce", "Msi"},
{
buildin_areaannounce, "areaannounce", "Mxyxysi"},
{
buildin_getusers, "getusers", "i"},
{
buildin_getmapusers, "getmapusers", "M"},
{
buildin_getareausers, "getareausers", "Mxyxy"},
{
buildin_getareadropitem, "getareadropitem", "Mxyxyi*"},
{
buildin_enablenpc, "enablenpc", "s"},
{
buildin_disablenpc, "disablenpc", "s"},
{
buildin_enablearena, "enablearena", ""}, // Added by RoVeRT
{
buildin_disablearena, "disablearena", ""}, // Added by RoVeRT
{
buildin_hideoffnpc, "hideoffnpc", "s"},
{
buildin_hideonnpc, "hideonnpc", "s"},
{
buildin_sc_start, "sc_start", "iTi*"},
{
buildin_sc_start2, "sc_start2", "iTii*"},
{
buildin_sc_end, "sc_end", "i"},
{
buildin_sc_check, "sc_check", "i"},
{
buildin_getscrate, "getscrate", "ii*"},
{
buildin_debugmes, "debugmes", "s"},
{
buildin_resetlvl, "resetlvl", "i"},
{
buildin_resetstatus, "resetstatus", ""},
{
buildin_resetskill, "resetskill", ""},
{
buildin_changebase, "changebase", "i"},
{
buildin_changesex, "changesex", ""},
{
buildin_waitingroom, "waitingroom", "si*"},
{
buildin_warpwaitingpc, "warpwaitingpc", "sii"},
{
buildin_delwaitingroom, "delwaitingroom", "*"},
{
buildin_enablewaitingroomevent, "enablewaitingroomevent", "*"},
{
buildin_disablewaitingroomevent, "disablewaitingroomevent", "*"},
{
buildin_getwaitingroomstate, "getwaitingroomstate", "i*"},
{
buildin_warpwaitingpc, "warpwaitingpc", "sii*"},
{
buildin_attachrid, "attachrid", "i"},
{
buildin_detachrid, "detachrid", ""},
{
buildin_isloggedin, "isloggedin", "i"},
{
buildin_setmapflagnosave, "setmapflagnosave", "MMxy"},
{
buildin_setmapflag, "setmapflag", "Mi"},
{
buildin_removemapflag, "removemapflag", "Mi"},
{
buildin_pvpon, "pvpon", "M"},
{
buildin_pvpoff, "pvpoff", "M"},
{
buildin_gvgon, "gvgon", "s"},
{
buildin_gvgoff, "gvgoff", "s"},
{
buildin_emotion, "emotion", "i"},
{
buildin_maprespawnguildid, "maprespawnguildid", "sii"},
{
buildin_agitstart, "agitstart", ""}, // <Agit>
{
buildin_agitend, "agitend", ""},
{
buildin_agitcheck, "agitcheck", "i"}, // <Agitcheck>
{
buildin_flagemblem, "flagemblem", "i"}, // Flag Emblem
{
buildin_getcastlename, "getcastlename", "s"},
{
buildin_getcastledata, "getcastledata", "si*"},
{
buildin_setcastledata, "setcastledata", "sii"},
{
buildin_requestguildinfo, "requestguildinfo", "i*"},
{
buildin_getequipcardcnt, "getequipcardcnt", "i"},
{
buildin_successremovecards, "successremovecards", "i"},
{
buildin_failedremovecards, "failedremovecards", "ii"},
{
buildin_marriage, "marriage", "P"},
{
buildin_wedding_effect, "wedding", ""},
{
buildin_divorce, "divorce", ""},
{
buildin_getitemname, "getitemname", "I"},
{
buildin_getspellinvocation, "getspellinvocation", "s"},
{
buildin_getanchorinvocation, "getanchorinvocation", "s"},
{
buildin_getpartnerid, "getpartnerid2", ""},
{
buildin_getexp, "getexp", "ii"},
{
buildin_getinventorylist, "getinventorylist", ""},
{
buildin_getskilllist, "getskilllist", ""},
{
buildin_get_pool_skills, "getpoolskilllist", ""},
{
buildin_get_activated_pool_skills, "getactivatedpoolskilllist", ""},
{
buildin_get_unactivated_pool_skills, "getunactivatedpoolskilllist", ""},
{
buildin_activate_pool_skill, "poolskill", "i"},
{
buildin_deactivate_pool_skill, "unpoolskill", "i"},
{
buildin_check_pool_skill, "checkpoolskill", "i"},
{
buildin_clearitem, "clearitem", ""},
{
buildin_classchange, "classchange", "ii"},
{
buildin_misceffect, "misceffect", "i*"},
{
buildin_soundeffect, "soundeffect", "si"},
{
buildin_strmobinfo, "strmobinfo", "im"}, // display mob data [Valaris]
{
buildin_guardian, "guardian", "siisii*i"}, // summon guardians
{
buildin_guardianinfo, "guardianinfo", "i"}, // display guardian data [Valaris]
{
buildin_npcskilleffect, "npcskilleffect", "iiii"}, // npc skill effect [Valaris]
{
buildin_specialeffect, "specialeffect", "i"}, // npc skill effect [Valaris]
{
buildin_specialeffect2, "specialeffect2", "i"}, // skill effect on players[Valaris]
{
buildin_nude, "nude", ""}, // nude command [Valaris]
{
buildin_mapwarp, "mapwarp", "MMxy"}, // Added by RoVeRT
{
buildin_inittimer, "inittimer", ""},
{
buildin_stoptimer, "stoptimer", ""},
{
buildin_cmdothernpc, "cmdothernpc", "ss"},
{
buildin_gmcommand, "gmcommand", "s"}, // [MouseJstr]
// {buildin_movenpc,"movenpc","siis"}, // [MouseJstr]
{
buildin_npcwarp, "npcwarp", "xys"}, // [remoitnane]
{
buildin_message, "message", "Ps"}, // [MouseJstr]
{
buildin_npctalk, "npctalk", "s"}, // [Valaris]
{
buildin_hasitems, "hasitems", ""}, // [Valaris]
{
buildin_mobcount, "mobcount", "ME"},
{
buildin_getlook, "getlook", "i"},
{
buildin_getsavepoint, "getsavepoint", "i"},
{
buildin_areatimer, "areatimer", "MxyxytE"},
{
buildin_isin, "isin", "Mxyxy"},
{
buildin_shop, "shop", "s"},
{
buildin_isdead, "isdead", ""},
{
buildin_fakenpcname, "fakenpcname", "ssi"},
{
buildin_unequip_by_id, "unequipbyid", "i"}, // [Freeyorp]
{
buildin_getx, "getx", ""}, // [Kage]
{
buildin_gety, "gety", ""}, // [Kage]
// End Additions
{
NULL, NULL, NULL},};
int buildin_message (struct script_state *st); // [MouseJstr]
enum
{
C_NOP, C_POS, C_INT, C_PARAM, C_FUNC, C_STR, C_CONSTSTR, C_ARG,
C_NAME, C_EOL, C_RETINFO,
C_LOR, C_LAND, C_LE, C_LT, C_GE, C_GT, C_EQ, C_NE, //operator
C_XOR, C_OR, C_AND, C_ADD, C_SUB, C_MUL, C_DIV, C_MOD, C_NEG, C_LNOT,
C_NOT, C_R_SHIFT, C_L_SHIFT
};
/*==========================================
* 文字列のハッシュを計算
*------------------------------------------
*/
static int calc_hash (const unsigned char *p)
{
int h = 0;
while (*p)
{
h = (h << 1) + (h >> 3) + (h >> 5) + (h >> 8);
h += *p++;
}
return h & 15;
}
/*==========================================
* str_dataの中に名前があるか検索する
*------------------------------------------
*/
// 既存のであれば番号、無ければ-1
static int search_str (const unsigned char *p)
{
int i;
i = str_hash[calc_hash (p)];
while (i)
{
if (strcmp (str_buf + str_data[i].str, p) == 0)
{
return i;
}
i = str_data[i].next;
}
return -1;
}
/*==========================================
* str_dataに名前を登録
*------------------------------------------
*/
// 既存のであれば番号、無ければ登録して新規番号
static int add_str (const unsigned char *p)
{
int i;
char *lowcase;
lowcase = strdup (p);
for (i = 0; lowcase[i]; i++)
lowcase[i] = tolower (lowcase[i]);
if ((i = search_str (lowcase)) >= 0)
{
free (lowcase);
return i;
}
free (lowcase);
i = calc_hash (p);
if (str_hash[i] == 0)
{
str_hash[i] = str_num;
}
else
{
i = str_hash[i];
for (;;)
{
if (strcmp (str_buf + str_data[i].str, p) == 0)
{
return i;
}
if (str_data[i].next == 0)
break;
i = str_data[i].next;
}
str_data[i].next = str_num;
}
if (str_num >= str_data_size)
{
str_data_size += 128;
RECREATE (str_data, struct str_data_t, str_data_size);
memset (str_data + (str_data_size - 128), '\0', 128);
}
while (str_pos + strlen (p) + 1 >= str_size)
{
str_size += 256;
str_buf = (char *) realloc (str_buf, str_size);
memset (str_buf + (str_size - 256), '\0', 256);
}
strcpy (str_buf + str_pos, p);
str_data[str_num].type = C_NOP;
str_data[str_num].str = str_pos;
str_data[str_num].next = 0;
str_data[str_num].func = NULL;
str_data[str_num].backpatch = -1;
str_data[str_num].label = -1;
str_pos += strlen (p) + 1;
return str_num++;
}
/*==========================================
* スクリプトバッファサイズの確認と拡張
*------------------------------------------
*/
static void check_script_buf (int size)
{
if (script_pos + size >= script_size)
{
script_size += SCRIPT_BLOCK_SIZE;
script_buf = (char *) realloc (script_buf, script_size);
memset (script_buf + script_size - SCRIPT_BLOCK_SIZE, '\0',
SCRIPT_BLOCK_SIZE);
}
}
/*==========================================
* スクリプトバッファに1バイト書き込む
*------------------------------------------
*/
static void add_scriptb (int a)
{
check_script_buf (1);
script_buf[script_pos++] = a;
}
/*==========================================
* スクリプトバッファにデータタイプを書き込む
*------------------------------------------
*/
static void add_scriptc (int a)
{
while (a >= 0x40)
{
add_scriptb ((a & 0x3f) | 0x40);
a = (a - 0x40) >> 6;
}
add_scriptb (a & 0x3f);
}
/*==========================================
* スクリプトバッファに整数を書き込む
*------------------------------------------
*/
static void add_scripti (int a)
{
while (a >= 0x40)
{
add_scriptb (a | 0xc0);
a = (a - 0x40) >> 6;
}
add_scriptb (a | 0x80);
}
/*==========================================
* スクリプトバッファにラベル/変数/関数を書き込む
*------------------------------------------
*/
// 最大16Mまで
static void add_scriptl (int l)
{
int backpatch = str_data[l].backpatch;
switch (str_data[l].type)
{
case C_POS:
add_scriptc (C_POS);
add_scriptb (str_data[l].label);
add_scriptb (str_data[l].label >> 8);
add_scriptb (str_data[l].label >> 16);
break;
case C_NOP:
// ラベルの可能性があるのでbackpatch用データ埋め込み
add_scriptc (C_NAME);
str_data[l].backpatch = script_pos;
add_scriptb (backpatch);
add_scriptb (backpatch >> 8);
add_scriptb (backpatch >> 16);
break;
case C_INT:
add_scripti (str_data[l].val);
break;
default:
// もう他の用途と確定してるので数字をそのまま
add_scriptc (C_NAME);
add_scriptb (l);
add_scriptb (l >> 8);
add_scriptb (l >> 16);
break;
}
}
/*==========================================
* ラベルを解決する
*------------------------------------------
*/
void set_label (int l, int pos)
{
int i, next;
str_data[l].type = C_POS;
str_data[l].label = pos;
for (i = str_data[l].backpatch; i >= 0 && i != 0x00ffffff;)
{
next = (*(int *) (script_buf + i)) & 0x00ffffff;
script_buf[i - 1] = C_POS;
script_buf[i] = pos;
script_buf[i + 1] = pos >> 8;
script_buf[i + 2] = pos >> 16;
i = next;
}
}
/*==========================================
* スペース/コメント読み飛ばし
*------------------------------------------
*/
static unsigned char *skip_space (unsigned char *p)
{
while (1)
{
while (isspace (*p))
p++;
if (p[0] == '/' && p[1] == '/')
{
while (*p && *p != '\n')
p++;
}
else if (p[0] == '/' && p[1] == '*')
{
p++;
while (*p && (p[-1] != '*' || p[0] != '/'))
p++;
if (*p)
p++;
}
else
break;
}
return p;
}
/*==========================================
* 1単語スキップ
*------------------------------------------
*/
static unsigned char *skip_word (unsigned char *p)
{
// prefix
if (*p == '$')
p++; // MAP鯖内共有変数用
if (*p == '@')
p++; // 一時的変数用(like weiss)
if (*p == '#')
p++; // account変数用
if (*p == '#')
p++; // ワールドaccount変数用
if (*p == 'l')
p++; // 一時的変数用(like weiss)
while (isalnum (*p) || *p == '_' || *p >= 0x81)
if (*p >= 0x81 && p[1])
{
p += 2;
}
else
p++;
// postfix
if (*p == '$')
p++; // 文字列変数
return p;
}
static unsigned char *startptr;
static int startline;
/*==========================================
* エラーメッセージ出力
*------------------------------------------
*/
static void disp_error_message (const char *mes, const unsigned char *pos)
{
int line, c = 0, i;
unsigned char *p, *linestart, *lineend;
for (line = startline, p = startptr; p && *p; line++)
{
linestart = p;
lineend = strchr (p, '\n');
if (lineend)
{
c = *lineend;
*lineend = 0;
}
if (lineend == NULL || pos < lineend)
{
printf ("%s line %d : ", mes, line);
for (i = 0;
(linestart[i] != '\r') && (linestart[i] != '\n')
&& linestart[i]; i++)
{
if (linestart + i != pos)
printf ("%c", linestart[i]);
else
printf ("\'%c\'", linestart[i]);
}
printf ("\a\n");
if (lineend)
*lineend = c;
return;
}
*lineend = c;
p = lineend + 1;
}
}
/*==========================================
* 項の解析
*------------------------------------------
*/
unsigned char *parse_simpleexpr (unsigned char *p)
{
int i;
p = skip_space (p);
#ifdef DEBUG_FUNCIN
if (battle_config.etc_log)
printf ("parse_simpleexpr %s\n", p);
#endif
if (*p == ';' || *p == ',')
{
disp_error_message ("unexpected expr end", p);
exit (1);
}
if (*p == '(')
{
p = parse_subexpr (p + 1, -1);
p = skip_space (p);
if ((*p++) != ')')
{
disp_error_message ("unmatch ')'", p);
exit (1);
}
}
else if (isdigit (*p) || ((*p == '-' || *p == '+') && isdigit (p[1])))
{
char *np;
i = strtoul (p, &np, 0);
add_scripti (i);
p = np;
}
else if (*p == '"')
{
add_scriptc (C_STR);
p++;
while (*p && *p != '"')
{
if (p[-1] <= 0x7e && *p == '\\')
p++;
else if (*p == '\n')
{
disp_error_message ("unexpected newline @ string", p);
exit (1);
}
add_scriptb (*p++);
}
if (!*p)
{
disp_error_message ("unexpected eof @ string", p);
exit (1);
}
add_scriptb (0);
p++; //'"'
}
else
{
int c, l;
char *p2;
// label , register , function etc
if (skip_word (p) == p)
{
disp_error_message ("unexpected character", p);
exit (1);
}
p2 = skip_word (p);
c = *p2;
*p2 = 0; // 名前をadd_strする
l = add_str (p);
parse_cmd = l; // warn_*_mismatch_paramnumのために必要
if (l == search_str ("if")) // warn_cmd_no_commaのために必要
parse_cmd_if++;
/*
// 廃止予定のl14/l15,およびプレフィックスlの警告
if( strcmp(str_buf+str_data[l].str,"l14")==0 ||
strcmp(str_buf+str_data[l].str,"l15")==0 ){
disp_error_message("l14 and l15 is DEPRECATED. use @menu instead of l15.",p);
}else if(str_buf[str_data[l].str]=='l'){
disp_error_message("prefix 'l' is DEPRECATED. use prefix '@' instead.",p2);
}
*/
*p2 = c;
p = p2;
if (str_data[l].type != C_FUNC && c == '[')
{
// array(name[i] => getelementofarray(name,i) )
add_scriptl (search_str ("getelementofarray"));
add_scriptc (C_ARG);
add_scriptl (l);
p = parse_subexpr (p + 1, -1);
p = skip_space (p);
if ((*p++) != ']')
{
disp_error_message ("unmatch ']'", p);
exit (1);
}
add_scriptc (C_FUNC);
}
else
add_scriptl (l);
}
#ifdef DEBUG_FUNCIN
if (battle_config.etc_log)
printf ("parse_simpleexpr end %s\n", p);
#endif
return p;
}
/*==========================================
* 式の解析
*------------------------------------------
*/
unsigned char *parse_subexpr (unsigned char *p, int limit)
{
int op, opl, len;
char *tmpp;
#ifdef DEBUG_FUNCIN
if (battle_config.etc_log)
printf ("parse_subexpr %s\n", p);
#endif
p = skip_space (p);
if (*p == '-')
{
tmpp = skip_space (p + 1);
if (*tmpp == ';' || *tmpp == ',')
{
add_scriptl (LABEL_NEXTLINE);
p++;
return p;
}
}
tmpp = p;
if ((op = C_NEG, *p == '-') || (op = C_LNOT, *p == '!')
|| (op = C_NOT, *p == '~'))
{
p = parse_subexpr (p + 1, 100);
add_scriptc (op);
}
else
p = parse_simpleexpr (p);
p = skip_space (p);
while (((op = C_ADD, opl = 6, len = 1, *p == '+') ||
(op = C_SUB, opl = 6, len = 1, *p == '-') ||
(op = C_MUL, opl = 7, len = 1, *p == '*') ||
(op = C_DIV, opl = 7, len = 1, *p == '/') ||
(op = C_MOD, opl = 7, len = 1, *p == '%') ||
(op = C_FUNC, opl = 8, len = 1, *p == '(') ||
(op = C_LAND, opl = 1, len = 2, *p == '&' && p[1] == '&') ||
(op = C_AND, opl = 5, len = 1, *p == '&') ||
(op = C_LOR, opl = 0, len = 2, *p == '|' && p[1] == '|') ||
(op = C_OR, opl = 4, len = 1, *p == '|') ||
(op = C_XOR, opl = 3, len = 1, *p == '^') ||
(op = C_EQ, opl = 2, len = 2, *p == '=' && p[1] == '=') ||
(op = C_NE, opl = 2, len = 2, *p == '!' && p[1] == '=') ||
(op = C_R_SHIFT, opl = 5, len = 2, *p == '>' && p[1] == '>') ||
(op = C_GE, opl = 2, len = 2, *p == '>' && p[1] == '=') ||
(op = C_GT, opl = 2, len = 1, *p == '>') ||
(op = C_L_SHIFT, opl = 5, len = 2, *p == '<' && p[1] == '<') ||
(op = C_LE, opl = 2, len = 2, *p == '<' && p[1] == '=') ||
(op = C_LT, opl = 2, len = 1, *p == '<')) && opl > limit)
{
p += len;
if (op == C_FUNC)
{
int i = 0, func = parse_cmd;
const char *plist[128];
if (str_data[func].type != C_FUNC)
{
disp_error_message ("expect function", tmpp);
exit (0);
}
add_scriptc (C_ARG);
while (*p && *p != ')' && i < 128)
{
plist[i] = p;
p = parse_subexpr (p, -1);
p = skip_space (p);
if (*p == ',')
p++;
else if (*p != ')' && script_config.warn_func_no_comma)
{
disp_error_message ("expect ',' or ')' at func params",
p);
}
p = skip_space (p);
i++;
}
plist[i] = p;
if (*(p++) != ')')
{
disp_error_message ("func request '(' ')'", p);
exit (1);
}
if (str_data[func].type == C_FUNC
&& script_config.warn_func_mismatch_paramnum)
{
const char *arg = buildin_func[str_data[func].val].arg;
int j = 0;
for (j = 0; arg[j]; j++)
if (arg[j] == '*')
break;
if ((arg[j] == 0 && i != j) || (arg[j] == '*' && i < j))
{
disp_error_message ("illegal number of parameters",
plist[(i < j) ? i : j]);
}
}
}
else // not op == C_FUNC
{
p = parse_subexpr (p, opl);
}
add_scriptc (op);
p = skip_space (p);
}
#ifdef DEBUG_FUNCIN
if (battle_config.etc_log)
printf ("parse_subexpr end %s\n", p);
#endif
return p; /* return first untreated operator */
}
/*==========================================
* 式の評価
*------------------------------------------
*/
unsigned char *parse_expr (unsigned char *p)
{
#ifdef DEBUG_FUNCIN
if (battle_config.etc_log)
printf ("parse_expr %s\n", p);
#endif
switch (*p)
{
case ')':
case ';':
case ':':
case '[':
case ']':
case '}':
disp_error_message ("unexpected char", p);
exit (1);
}
p = parse_subexpr (p, -1);
#ifdef DEBUG_FUNCIN
if (battle_config.etc_log)
printf ("parse_expr end %s\n", p);
#endif
return p;
}
/*==========================================
* 行の解析
*------------------------------------------
*/
unsigned char *parse_line (unsigned char *p)
{
int i = 0, cmd;
const char *plist[128];
char *p2;
p = skip_space (p);
if (*p == ';')
return p;
parse_cmd_if = 0; // warn_cmd_no_commaのために必要
// 最初は関数名
p2 = p;
p = parse_simpleexpr (p);
p = skip_space (p);
cmd = parse_cmd;
if (str_data[cmd].type != C_FUNC)
{
disp_error_message ("expect command", p2);
// exit(0);
}
add_scriptc (C_ARG);
while (p && *p && *p != ';' && i < 128)
{
plist[i] = p;
p = parse_expr (p);
p = skip_space (p);
// 引数区切りの,処理
if (*p == ',')
p++;
else if (*p != ';' && script_config.warn_cmd_no_comma
&& parse_cmd_if * 2 <= i)
{
disp_error_message ("expect ',' or ';' at cmd params", p);
}
p = skip_space (p);
i++;
}
plist[i] = p;
if (!p || *(p++) != ';')
{
disp_error_message ("need ';'", p);
exit (1);
}
add_scriptc (C_FUNC);
if (str_data[cmd].type == C_FUNC
&& script_config.warn_cmd_mismatch_paramnum)
{
const char *arg = buildin_func[str_data[cmd].val].arg;
int j = 0;
for (j = 0; arg[j]; j++)
if (arg[j] == '*')
break;
if ((arg[j] == 0 && i != j) || (arg[j] == '*' && i < j))
{
disp_error_message ("illegal number of parameters",
plist[(i < j) ? i : j]);
}
}
return p;
}
/*==========================================
* 組み込み関数の追加
*------------------------------------------
*/
static void add_buildin_func (void)
{
int i, n;
for (i = 0; buildin_func[i].func; i++)
{
n = add_str (buildin_func[i].name);
str_data[n].type = C_FUNC;
str_data[n].val = i;
str_data[n].func = buildin_func[i].func;
}
}
/*==========================================
* 定数データベースの読み込み
*------------------------------------------
*/
static void read_constdb (void)
{
FILE *fp;
char line[1024], name[1024];
int val, n, i, type;
fp = fopen_ ("db/const.txt", "r");
if (fp == NULL)
{
printf ("can't read db/const.txt\n");
return;
}
while (fgets (line, 1020, fp))
{
if (line[0] == '/' && line[1] == '/')
continue;
type = 0;
if (sscanf (line, "%[A-Za-z0-9_],%d,%d", name, &val, &type) >= 2 ||
sscanf (line, "%[A-Za-z0-9_] %d %d", name, &val, &type) >= 2)
{
for (i = 0; name[i]; i++)
name[i] = tolower (name[i]);
n = add_str (name);
if (type == 0)
str_data[n].type = C_INT;
else
str_data[n].type = C_PARAM;
str_data[n].val = val;
}
}
fclose_ (fp);
}
/*==========================================
* スクリプトの解析
*------------------------------------------
*/
unsigned char *parse_script (unsigned char *src, int line)
{
unsigned char *p, *tmpp;
int i;
static int first = 1;
if (first)
{
add_buildin_func ();
read_constdb ();
}
first = 0;
script_buf = (unsigned char *) calloc (SCRIPT_BLOCK_SIZE, 1);
script_pos = 0;
script_size = SCRIPT_BLOCK_SIZE;
str_data[LABEL_NEXTLINE].type = C_NOP;
str_data[LABEL_NEXTLINE].backpatch = -1;
str_data[LABEL_NEXTLINE].label = -1;
for (i = LABEL_START; i < str_num; i++)
{
if (str_data[i].type == C_POS || str_data[i].type == C_NAME)
{
str_data[i].type = C_NOP;
str_data[i].backpatch = -1;
str_data[i].label = -1;
}
}
// 外部用label dbの初期化
if (scriptlabel_db != NULL)
strdb_final (scriptlabel_db, NULL);
scriptlabel_db = strdb_init (50);
// for error message
startptr = src;
startline = line;
p = src;
p = skip_space (p);
if (*p != '{')
{
disp_error_message ("not found '{'", p);
return NULL;
}
for (p++; p && *p && *p != '}';)
{
p = skip_space (p);
// labelだけ特殊処理
tmpp = skip_space (skip_word (p));
if (*tmpp == ':')
{
int l, c;
c = *skip_word (p);
*skip_word (p) = 0;
l = add_str (p);
if (str_data[l].label != -1)
{
*skip_word (p) = c;
disp_error_message ("dup label ", p);
exit (1);
}
set_label (l, script_pos);
strdb_insert (scriptlabel_db, (const char*)p, script_pos); // 外部用label db登録
*skip_word (p) = c;
p = tmpp + 1;
continue;
}
// 他は全部一緒くた
p = parse_line (p);
p = skip_space (p);
add_scriptc (C_EOL);
set_label (LABEL_NEXTLINE, script_pos);
str_data[LABEL_NEXTLINE].type = C_NOP;
str_data[LABEL_NEXTLINE].backpatch = -1;
str_data[LABEL_NEXTLINE].label = -1;
}
add_scriptc (C_NOP);
script_size = script_pos;
script_buf = (char *) realloc (script_buf, script_pos + 1);
// 未解決のラベルを解決
for (i = LABEL_START; i < str_num; i++)
{
if (str_data[i].type == C_NOP)
{
int j, next;
str_data[i].type = C_NAME;
str_data[i].label = i;
for (j = str_data[i].backpatch; j >= 0 && j != 0x00ffffff;)
{
next = (*(int *) (script_buf + j)) & 0x00ffffff;
script_buf[j] = i;
script_buf[j + 1] = i >> 8;
script_buf[j + 2] = i >> 16;
j = next;
}
}
}
#ifdef DEBUG_DISP
for (i = 0; i < script_pos; i++)
{
if ((i & 15) == 0)
printf ("%04x : ", i);
printf ("%02x ", script_buf[i]);
if ((i & 15) == 15)
printf ("\n");
}
printf ("\n");
#endif
return script_buf;
}
//
// 実行系
//
enum
{ STOP = 1, END, RERUNLINE, GOTO, RETFUNC };
/*==========================================
* ridからsdへの解決
*------------------------------------------
*/
struct map_session_data *script_rid2sd (struct script_state *st)
{
struct map_session_data *sd = map_id2sd (st->rid);
if (!sd)
{
printf ("script_rid2sd: fatal error ! player not attached!\n");
}
return sd;
}
/*==========================================
* 変数の読み取り
*------------------------------------------
*/
int get_val (struct script_state *st, struct script_data *data)
{
struct map_session_data *sd = NULL;
if (data->type == C_NAME)
{
char *name = str_buf + str_data[data->u.num & 0x00ffffff].str;
char prefix = *name;
char postfix = name[strlen (name) - 1];
if (prefix != '$')
{
if ((sd = script_rid2sd (st)) == NULL)
printf ("get_val error name?:%s\n", name);
}
if (postfix == '$')
{
data->type = C_CONSTSTR;
if (prefix == '@' || prefix == 'l')
{
if (sd)
data->u.str = pc_readregstr (sd, data->u.num);
}
else if (prefix == '$')
{
data->u.str =
(char *) numdb_search (mapregstr_db, data->u.num);
}
else
{
printf ("script: get_val: illegal scope string variable.\n");
data->u.str = "!!ERROR!!";
}
if (data->u.str == NULL)
data->u.str = "";
}
else
{
data->type = C_INT;
if (str_data[data->u.num & 0x00ffffff].type == C_INT)
{
data->u.num = str_data[data->u.num & 0x00ffffff].val;
}
else if (str_data[data->u.num & 0x00ffffff].type == C_PARAM)
{
if (sd)
data->u.num =
pc_readparam (sd,
str_data[data->u.num & 0x00ffffff].val);
}
else if (prefix == '@' || prefix == 'l')
{
if (sd)
data->u.num = pc_readreg (sd, data->u.num);
}
else if (prefix == '$')
{
data->u.num = (int) numdb_search (mapreg_db, data->u.num);
}
else if (prefix == '#')
{
if (name[1] == '#')
{
if (sd)
data->u.num = pc_readaccountreg2 (sd, name);
}
else
{
if (sd)
data->u.num = pc_readaccountreg (sd, name);
}
}
else
{
if (sd)
data->u.num = pc_readglobalreg (sd, name);
}
}
}
return 0;
}
/*==========================================
* 変数の読み取り2
*------------------------------------------
*/
void *get_val2 (struct script_state *st, int num)
{
struct script_data dat;
dat.type = C_NAME;
dat.u.num = num;
get_val (st, &dat);
if (dat.type == C_INT)
return (void *) dat.u.num;
else
return (void *) dat.u.str;
}
/*==========================================
* 変数設定用
*------------------------------------------
*/
static int set_reg (struct map_session_data *sd, int num, char *name, void *v)
{
char prefix = *name;
char postfix = name[strlen (name) - 1];
if (postfix == '$')
{
char *str = (char *) v;
if (prefix == '@' || prefix == 'l')
{
pc_setregstr (sd, num, str);
}
else if (prefix == '$')
{
mapreg_setregstr (num, str);
}
else
{
printf ("script: set_reg: illegal scope string variable !");
}
}
else
{
// 数値
int val = (int) v;
if (str_data[num & 0x00ffffff].type == C_PARAM)
{
pc_setparam (sd, str_data[num & 0x00ffffff].val, val);
}
else if (prefix == '@' || prefix == 'l')
{
pc_setreg (sd, num, val);
}
else if (prefix == '$')
{
mapreg_setreg (num, val);
}
else if (prefix == '#')
{
if (name[1] == '#')
pc_setaccountreg2 (sd, name, val);
else
pc_setaccountreg (sd, name, val);
}
else
{
pc_setglobalreg (sd, name, val);
}
}
return 0;
}
/*==========================================
* 文字列への変換
*------------------------------------------
*/
char *conv_str (struct script_state *st, struct script_data *data)
{
get_val (st, data);
if (data->type == C_INT)
{
char *buf;
buf = (char *) calloc (16, 1);
sprintf (buf, "%d", data->u.num);
data->type = C_STR;
data->u.str = buf;
#if 1
}
else if (data->type == C_NAME)
{
// テンポラリ。本来無いはず
data->type = C_CONSTSTR;
data->u.str = str_buf + str_data[data->u.num].str;
#endif
}
return data->u.str;
}
/*==========================================
* 数値へ変換
*------------------------------------------
*/
int conv_num (struct script_state *st, struct script_data *data)
{
char *p;
get_val (st, data);
if (data->type == C_STR || data->type == C_CONSTSTR)
{
p = data->u.str;
data->u.num = atoi (p);
if (data->type == C_STR)
free (p);
data->type = C_INT;
}
return data->u.num;
}
/*==========================================
* スタックへ数値をプッシュ
*------------------------------------------
*/
void push_val (struct script_stack *stack, int type, int val)
{
if (stack->sp >= stack->sp_max)
{
stack->sp_max += 64;
stack->stack_data = (struct script_data *)
realloc (stack->stack_data, sizeof (stack->stack_data[0]) *
stack->sp_max);
memset (stack->stack_data + (stack->sp_max - 64), 0,
64 * sizeof (*(stack->stack_data)));
}
// if(battle_config.etc_log)
// printf("push (%d,%d)-> %d\n",type,val,stack->sp);
stack->stack_data[stack->sp].type = type;
stack->stack_data[stack->sp].u.num = val;
stack->sp++;
}
/*==========================================
* スタックへ文字列をプッシュ
*------------------------------------------
*/
void push_str (struct script_stack *stack, int type, unsigned char *str)
{
if (stack->sp >= stack->sp_max)
{
stack->sp_max += 64;
stack->stack_data = (struct script_data *)
realloc (stack->stack_data, sizeof (stack->stack_data[0]) *
stack->sp_max);
memset (stack->stack_data + (stack->sp_max - 64), '\0',
64 * sizeof (*(stack->stack_data)));
}
// if(battle_config.etc_log)
// printf("push (%d,%x)-> %d\n",type,str,stack->sp);
stack->stack_data[stack->sp].type = type;
stack->stack_data[stack->sp].u.str = str;
stack->sp++;
}
/*==========================================
* スタックへ複製をプッシュ
*------------------------------------------
*/
void push_copy (struct script_stack *stack, int pos)
{
switch (stack->stack_data[pos].type)
{
case C_CONSTSTR:
push_str (stack, C_CONSTSTR, stack->stack_data[pos].u.str);
break;
case C_STR:
push_str (stack, C_STR, strdup (stack->stack_data[pos].u.str));
break;
default:
push_val (stack, stack->stack_data[pos].type,
stack->stack_data[pos].u.num);
break;
}
}
/*==========================================
* スタックからポップ
*------------------------------------------
*/
void pop_stack (struct script_stack *stack, int start, int end)
{
int i;
for (i = start; i < end; i++)
{
if (stack->stack_data[i].type == C_STR)
{
free (stack->stack_data[i].u.str);
}
}
if (stack->sp > end)
{
memmove (&stack->stack_data[start], &stack->stack_data[end],
sizeof (stack->stack_data[0]) * (stack->sp - end));
}
stack->sp -= end - start;
}
//
// 埋め込み関数
//
/*==========================================
*
*------------------------------------------
*/
int buildin_mes (struct script_state *st)
{
conv_str (st, &(st->stack->stack_data[st->start + 2]));
clif_scriptmes (script_rid2sd (st), st->oid,
st->stack->stack_data[st->start + 2].u.str);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_goto (struct script_state *st)
{
int pos;
if (st->stack->stack_data[st->start + 2].type != C_POS)
{
printf ("script: goto: not label !\n");
st->state = END;
return 0;
}
pos = conv_num (st, &(st->stack->stack_data[st->start + 2]));
st->pos = pos;
st->state = GOTO;
return 0;
}
/*==========================================
* ユーザー定義関数の呼び出し
*------------------------------------------
*/
int buildin_callfunc (struct script_state *st)
{
char *scr;
char *str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
if ((scr = (char*)strdb_search (script_get_userfunc_db (), str)))
{
int i, j;
for (i = st->start + 3, j = 0; i < st->end; i++, j++)
push_copy (st->stack, i);
push_val (st->stack, C_INT, j); // 引数の数をプッシュ
push_val (st->stack, C_INT, st->defsp); // 現在の基準スタックポインタをプッシュ
push_val (st->stack, C_INT, (int) st->script); // 現在のスクリプトをプッシュ
push_val (st->stack, C_RETINFO, st->pos); // 現在のスクリプト位置をプッシュ
st->pos = 0;
st->script = scr;
st->defsp = st->start + 4 + j;
st->state = GOTO;
}
else
{
printf ("script:callfunc: function not found! [%s]\n", str);
st->state = END;
}
return 0;
}
/*==========================================
* サブルーティンの呼び出し
*------------------------------------------
*/
int buildin_callsub (struct script_state *st)
{
int pos = conv_num (st, &(st->stack->stack_data[st->start + 2]));
int i, j;
for (i = st->start + 3, j = 0; i < st->end; i++, j++)
push_copy (st->stack, i);
push_val (st->stack, C_INT, j); // 引数の数をプッシュ
push_val (st->stack, C_INT, st->defsp); // 現在の基準スタックポインタをプッシュ
push_val (st->stack, C_INT, (int) st->script); // 現在のスクリプトをプッシュ
push_val (st->stack, C_RETINFO, st->pos); // 現在のスクリプト位置をプッシュ
st->pos = pos;
st->defsp = st->start + 4 + j;
st->state = GOTO;
return 0;
}
/*==========================================
* 引数の所得
*------------------------------------------
*/
int buildin_getarg (struct script_state *st)
{
int num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
int max, stsp;
if (st->defsp < 4
|| st->stack->stack_data[st->defsp - 1].type != C_RETINFO)
{
printf ("script:getarg without callfunc or callsub!\n");
st->state = END;
return 0;
}
max = conv_num (st, &(st->stack->stack_data[st->defsp - 4]));
stsp = st->defsp - max - 4;
if (num >= max)
{
printf ("script:getarg arg1(%d) out of range(%d) !\n", num, max);
st->state = END;
return 0;
}
push_copy (st->stack, stsp + num);
return 0;
}
/*==========================================
* サブルーチン/ユーザー定義関数の終了
*------------------------------------------
*/
int buildin_return (struct script_state *st)
{
if (st->end > st->start + 2)
{ // 戻り値有り
push_copy (st->stack, st->start + 2);
}
st->state = RETFUNC;
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_next (struct script_state *st)
{
st->state = STOP;
clif_scriptnext (script_rid2sd (st), st->oid);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_close (struct script_state *st)
{
st->state = END;
clif_scriptclose (script_rid2sd (st), st->oid);
return 0;
}
int buildin_close2 (struct script_state *st)
{
st->state = STOP;
clif_scriptclose (script_rid2sd (st), st->oid);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_menu (struct script_state *st)
{
char *buf;
int i, len = 0; // [fate] len is the total # of bytes we need to transmit the string choices
int menu_choices = 0;
int finished_menu_items = 0; // [fate] set to 1 after we hit the first empty string
struct map_session_data *sd;
sd = script_rid2sd (st);
// We don't need to do this iteration if the player cancels, strictly speaking.
for (i = st->start + 2; i < st->end; i += 2)
{
int choice_len;
conv_str (st, &(st->stack->stack_data[i]));
choice_len = strlen (st->stack->stack_data[i].u.str);
len += choice_len + 1; // count # of bytes we'll need for packet. Only used if menu_or_input = 0.
if (choice_len && !finished_menu_items)
++menu_choices;
else
finished_menu_items = 1;
}
if (sd->state.menu_or_input == 0)
{
st->state = RERUNLINE;
sd->state.menu_or_input = 1;
buf = (char *) calloc (len + 1, 1);
buf[0] = 0;
for (i = st->start + 2; menu_choices > 0; i += 2, --menu_choices)
{
strcat (buf, st->stack->stack_data[i].u.str);
strcat (buf, ":");
}
clif_scriptmenu (script_rid2sd (st), st->oid, buf);
free (buf);
}
else if (sd->npc_menu == 0xff)
{ // cansel
sd->state.menu_or_input = 0;
st->state = END;
}
else
{ // goto動作
// ragemu互換のため
pc_setreg (sd, add_str ("l15"), sd->npc_menu);
pc_setreg (sd, add_str ("@menu"), sd->npc_menu);
sd->state.menu_or_input = 0;
if (sd->npc_menu > 0 && sd->npc_menu <= menu_choices)
{
int pos;
if (st->stack->
stack_data[st->start + sd->npc_menu * 2 + 1].type != C_POS)
{
st->state = END;
return 0;
}
pos =
conv_num (st,
&(st->
stack->stack_data[st->start + sd->npc_menu * 2 +
1]));
st->pos = pos;
st->state = GOTO;
}
}
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_rand (struct script_state *st)
{
int range, min, max;
if (st->end > st->start + 3)
{
min = conv_num (st, &(st->stack->stack_data[st->start + 2]));
max = conv_num (st, &(st->stack->stack_data[st->start + 3]));
if (max < min)
{
int tmp;
tmp = min;
min = max;
max = tmp;
}
range = max - min + 1;
push_val (st->stack, C_INT, (range <= 0 ? 0 : MRAND (range)) + min);
}
else
{
range = conv_num (st, &(st->stack->stack_data[st->start + 2]));
push_val (st->stack, C_INT, range <= 0 ? 0 : MRAND (range));
}
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_pow (struct script_state *st)
{
int a, b;
a = conv_num (st, &(st->stack->stack_data[st->start + 2]));
b = conv_num (st, &(st->stack->stack_data[st->start + 3]));
push_val (st->stack, C_INT, (int) pow (a * 0.001, b));
return 0;
}
/*==========================================
* Check whether the PC is at the specified location
*------------------------------------------
*/
int buildin_isat (struct script_state *st)
{
int x, y;
char *str;
struct map_session_data *sd = script_rid2sd (st);
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
if (!sd)
return 1;
push_val (st->stack, C_INT,
(x == sd->bl.x)
&& (y == sd->bl.y) && (!strcmp (str, map[sd->bl.m].name)));
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_warp (struct script_state *st)
{
int x, y;
char *str;
struct map_session_data *sd = script_rid2sd (st);
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
if (strcmp (str, "Random") == 0)
pc_randomwarp (sd, 3);
else if (strcmp (str, "SavePoint") == 0)
{
if (map[sd->bl.m].flag.noreturn) // 蝶禁止
return 0;
pc_setpos (sd, sd->status.save_point.map,
sd->status.save_point.x, sd->status.save_point.y, 3);
}
else if (strcmp (str, "Save") == 0)
{
if (map[sd->bl.m].flag.noreturn) // 蝶禁止
return 0;
pc_setpos (sd, sd->status.save_point.map,
sd->status.save_point.x, sd->status.save_point.y, 3);
}
else
pc_setpos (sd, str, x, y, 0);
return 0;
}
/*==========================================
* エリア指定ワープ
*------------------------------------------
*/
int buildin_areawarp_sub (struct block_list *bl, va_list ap)
{
int x, y;
char *map;
map = va_arg (ap, char *);
x = va_arg (ap, int);
y = va_arg (ap, int);
if (strcmp (map, "Random") == 0)
pc_randomwarp ((struct map_session_data *) bl, 3);
else
pc_setpos ((struct map_session_data *) bl, map, x, y, 0);
return 0;
}
int buildin_areawarp (struct script_state *st)
{
int x, y, m;
char *str;
char *mapname;
int x0, y0, x1, y1;
mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
x0 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
y0 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
x1 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
y1 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
str = conv_str (st, &(st->stack->stack_data[st->start + 7]));
x = conv_num (st, &(st->stack->stack_data[st->start + 8]));
y = conv_num (st, &(st->stack->stack_data[st->start + 9]));
if ((m = map_mapname2mapid (mapname)) < 0)
return 0;
map_foreachinarea (buildin_areawarp_sub,
m, x0, y0, x1, y1, BL_PC, str, x, y);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_heal (struct script_state *st)
{
int hp, sp;
hp = conv_num (st, &(st->stack->stack_data[st->start + 2]));
sp = conv_num (st, &(st->stack->stack_data[st->start + 3]));
pc_heal (script_rid2sd (st), hp, sp);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_itemheal (struct script_state *st)
{
int hp, sp;
hp = conv_num (st, &(st->stack->stack_data[st->start + 2]));
sp = conv_num (st, &(st->stack->stack_data[st->start + 3]));
pc_itemheal (script_rid2sd (st), hp, sp);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_percentheal (struct script_state *st)
{
int hp, sp;
hp = conv_num (st, &(st->stack->stack_data[st->start + 2]));
sp = conv_num (st, &(st->stack->stack_data[st->start + 3]));
pc_percentheal (script_rid2sd (st), hp, sp);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_jobchange (struct script_state *st)
{
int job, upper = -1;
job = conv_num (st, &(st->stack->stack_data[st->start + 2]));
if (st->end > st->start + 3)
upper = conv_num (st, &(st->stack->stack_data[st->start + 3]));
if ((job >= 0 && job < MAX_PC_CLASS))
pc_jobchange (script_rid2sd (st), job, upper);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_input (struct script_state *st)
{
struct map_session_data *sd = NULL;
int num =
(st->end >
st->start + 2) ? st->stack->stack_data[st->start + 2].u.num : 0;
char *name =
(st->end >
st->start + 2) ? str_buf + str_data[num & 0x00ffffff].str : "";
// char prefix=*name;
char postfix = name[strlen (name) - 1];
sd = script_rid2sd (st);
if (sd->state.menu_or_input)
{
sd->state.menu_or_input = 0;
if (postfix == '$')
{
// 文字列
if (st->end > st->start + 2)
{ // 引数1個
set_reg (sd, num, name, (void *) sd->npc_str);
}
else
{
printf ("buildin_input: string discarded !!\n");
}
}
else
{
//commented by Lupus (check Value Number Input fix in clif.c)
//** Fix by fritz :X keeps people from abusing old input bugs
if (sd->npc_amount < 0) //** If input amount is less then 0
{
clif_tradecancelled (sd); // added "Deal has been cancelled" message by Valaris
buildin_close (st); //** close
}
// 数値
if (st->end > st->start + 2)
{ // 引数1個
set_reg (sd, num, name, (void *) sd->npc_amount);
}
else
{
// ragemu互換のため
pc_setreg (sd, add_str ("l14"), sd->npc_amount);
}
}
}
else
{
st->state = RERUNLINE;
if (postfix == '$')
clif_scriptinputstr (sd, st->oid);
else
clif_scriptinput (sd, st->oid);
sd->state.menu_or_input = 1;
}
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_if (struct script_state *st)
{
int sel, i;
sel = conv_num (st, &(st->stack->stack_data[st->start + 2]));
if (!sel)
return 0;
// 関数名をコピー
push_copy (st->stack, st->start + 3);
// 間に引数マーカを入れて
push_val (st->stack, C_ARG, 0);
// 残りの引数をコピー
for (i = st->start + 4; i < st->end; i++)
{
push_copy (st->stack, i);
}
run_func (st);
return 0;
}
/*==========================================
* 変数設定
*------------------------------------------
*/
int buildin_set (struct script_state *st)
{
struct map_session_data *sd = NULL;
int num = st->stack->stack_data[st->start + 2].u.num;
char *name = str_buf + str_data[num & 0x00ffffff].str;
char prefix = *name;
char postfix = name[strlen (name) - 1];
if (st->stack->stack_data[st->start + 2].type != C_NAME)
{
printf ("script: buildin_set: not name\n");
return 0;
}
if (prefix != '$')
sd = script_rid2sd (st);
if (postfix == '$')
{
// 文字列
char *str = conv_str (st, &(st->stack->stack_data[st->start + 3]));
set_reg (sd, num, name, (void *) str);
}
else
{
// 数値
int val = conv_num (st, &(st->stack->stack_data[st->start + 3]));
set_reg (sd, num, name, (void *) val);
}
return 0;
}
/*==========================================
* 配列変数設定
*------------------------------------------
*/
int buildin_setarray (struct script_state *st)
{
struct map_session_data *sd = NULL;
int num = st->stack->stack_data[st->start + 2].u.num;
char *name = str_buf + str_data[num & 0x00ffffff].str;
char prefix = *name;
char postfix = name[strlen (name) - 1];
int i, j;
if (prefix != '$' && prefix != '@')
{
printf ("buildin_setarray: illegal scope !\n");
return 0;
}
if (prefix != '$')
sd = script_rid2sd (st);
for (j = 0, i = st->start + 3; i < st->end && j < 128; i++, j++)
{
void *v;
if (postfix == '$')
v = (void *) conv_str (st, &(st->stack->stack_data[i]));
else
v = (void *) conv_num (st, &(st->stack->stack_data[i]));
set_reg (sd, num + (j << 24), name, v);
}
return 0;
}
/*==========================================
* 配列変数クリア
*------------------------------------------
*/
int buildin_cleararray (struct script_state *st)
{
struct map_session_data *sd = NULL;
int num = st->stack->stack_data[st->start + 2].u.num;
char *name = str_buf + str_data[num & 0x00ffffff].str;
char prefix = *name;
char postfix = name[strlen (name) - 1];
int sz = conv_num (st, &(st->stack->stack_data[st->start + 4]));
int i;
void *v;
if (prefix != '$' && prefix != '@')
{
printf ("buildin_cleararray: illegal scope !\n");
return 0;
}
if (prefix != '$')
sd = script_rid2sd (st);
if (postfix == '$')
v = (void *) conv_str (st, &(st->stack->stack_data[st->start + 3]));
else
v = (void *) conv_num (st, &(st->stack->stack_data[st->start + 3]));
for (i = 0; i < sz; i++)
set_reg (sd, num + (i << 24), name, v);
return 0;
}
/*==========================================
* 配列変数コピー
*------------------------------------------
*/
int buildin_copyarray (struct script_state *st)
{
struct map_session_data *sd = NULL;
int num = st->stack->stack_data[st->start + 2].u.num;
char *name = str_buf + str_data[num & 0x00ffffff].str;
char prefix = *name;
char postfix = name[strlen (name) - 1];
int num2 = st->stack->stack_data[st->start + 3].u.num;
char *name2 = str_buf + str_data[num2 & 0x00ffffff].str;
char prefix2 = *name2;
char postfix2 = name2[strlen (name2) - 1];
int sz = conv_num (st, &(st->stack->stack_data[st->start + 4]));
int i;
if (prefix != '$' && prefix != '@' && prefix2 != '$' && prefix2 != '@')
{
printf ("buildin_copyarray: illegal scope !\n");
return 0;
}
if ((postfix == '$' || postfix2 == '$') && postfix != postfix2)
{
printf ("buildin_copyarray: type mismatch !\n");
return 0;
}
if (prefix != '$' || prefix2 != '$')
sd = script_rid2sd (st);
for (i = 0; i < sz; i++)
set_reg (sd, num + (i << 24), name, get_val2 (st, num2 + (i << 24)));
return 0;
}
/*==========================================
* 配列変数のサイズ所得
*------------------------------------------
*/
static int getarraysize (struct script_state *st, int num, int postfix)
{
int i = (num >> 24), c = i;
for (; i < 128; i++)
{
void *v = get_val2 (st, num + (i << 24));
if (postfix == '$' && *((char *) v))
c = i;
if (postfix != '$' && (int) v)
c = i;
}
return c + 1;
}
int buildin_getarraysize (struct script_state *st)
{
int num = st->stack->stack_data[st->start + 2].u.num;
char *name = str_buf + str_data[num & 0x00ffffff].str;
char prefix = *name;
char postfix = name[strlen (name) - 1];
if (prefix != '$' && prefix != '@')
{
printf ("buildin_copyarray: illegal scope !\n");
return 0;
}
push_val (st->stack, C_INT, getarraysize (st, num, postfix));
return 0;
}
/*==========================================
* 配列変数から要素削除
*------------------------------------------
*/
int buildin_deletearray (struct script_state *st)
{
struct map_session_data *sd = NULL;
int num = st->stack->stack_data[st->start + 2].u.num;
char *name = str_buf + str_data[num & 0x00ffffff].str;
char prefix = *name;
char postfix = name[strlen (name) - 1];
int count = 1;
int i, sz = getarraysize (st, num, postfix) - (num >> 24) - count + 1;
if ((st->end > st->start + 3))
count = conv_num (st, &(st->stack->stack_data[st->start + 3]));
if (prefix != '$' && prefix != '@')
{
printf ("buildin_deletearray: illegal scope !\n");
return 0;
}
if (prefix != '$')
sd = script_rid2sd (st);
for (i = 0; i < sz; i++)
{
set_reg (sd, num + (i << 24), name,
get_val2 (st, num + ((i + count) << 24)));
}
for (; i < (128 - (num >> 24)); i++)
{
if (postfix != '$')
set_reg (sd, num + (i << 24), name, 0);
if (postfix == '$')
set_reg (sd, num + (i << 24), name, "");
}
return 0;
}
/*==========================================
* 指定要素を表す値(キー)を所得する
*------------------------------------------
*/
int buildin_getelementofarray (struct script_state *st)
{
if (st->stack->stack_data[st->start + 2].type == C_NAME)
{
int i = conv_num (st, &(st->stack->stack_data[st->start + 3]));
if (i > 127 || i < 0)
{
printf
("script: getelementofarray (operator[]): param2 illegal number %d\n",
i);
push_val (st->stack, C_INT, 0);
}
else
{
push_val (st->stack, C_NAME,
(i << 24) | st->stack->stack_data[st->start + 2].u.num);
}
}
else
{
printf
("script: getelementofarray (operator[]): param1 not name !\n");
push_val (st->stack, C_INT, 0);
}
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_setlook (struct script_state *st)
{
int type, val;
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
val = conv_num (st, &(st->stack->stack_data[st->start + 3]));
pc_changelook (script_rid2sd (st), type, val);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_cutin (struct script_state *st)
{
int type;
conv_str (st, &(st->stack->stack_data[st->start + 2]));
type = conv_num (st, &(st->stack->stack_data[st->start + 3]));
clif_cutin (script_rid2sd (st),
st->stack->stack_data[st->start + 2].u.str, type);
return 0;
}
/*==========================================
* カードのイラストを表示する
*------------------------------------------
*/
int buildin_cutincard (struct script_state *st)
{
int itemid;
itemid = conv_num (st, &(st->stack->stack_data[st->start + 2]));
clif_cutin (script_rid2sd (st), itemdb_search (itemid)->cardillustname,
4);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_viewpoint (struct script_state *st)
{
int type, x, y, id, color;
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
id = conv_num (st, &(st->stack->stack_data[st->start + 5]));
color = conv_num (st, &(st->stack->stack_data[st->start + 6]));
clif_viewpoint (script_rid2sd (st), st->oid, type, x, y, id, color);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_countitem (struct script_state *st)
{
int nameid = 0, count = 0, i;
struct map_session_data *sd;
struct script_data *data;
sd = script_rid2sd (st);
data = &(st->stack->stack_data[st->start + 2]);
get_val (st, data);
if (data->type == C_STR || data->type == C_CONSTSTR)
{
const char *name = conv_str (st, data);
struct item_data *item_data;
if ((item_data = itemdb_searchname (name)) != NULL)
nameid = item_data->nameid;
}
else
nameid = conv_num (st, data);
if (nameid >= 500) //if no such ID then skip this iteration
for (i = 0; i < MAX_INVENTORY; i++)
{
if (sd->status.inventory[i].nameid == nameid)
count += sd->status.inventory[i].amount;
}
else
{
if (battle_config.error_log)
printf ("wrong item ID : countitem(%i)\n", nameid);
}
push_val (st->stack, C_INT, count);
return 0;
}
/*==========================================
* 重量チェック
*------------------------------------------
*/
int buildin_checkweight (struct script_state *st)
{
int nameid = 0, amount;
struct map_session_data *sd;
struct script_data *data;
sd = script_rid2sd (st);
data = &(st->stack->stack_data[st->start + 2]);
get_val (st, data);
if (data->type == C_STR || data->type == C_CONSTSTR)
{
const char *name = conv_str (st, data);
struct item_data *item_data = itemdb_searchname (name);
if (item_data)
nameid = item_data->nameid;
}
else
nameid = conv_num (st, data);
amount = conv_num (st, &(st->stack->stack_data[st->start + 3]));
if (amount <= 0 || nameid < 500)
{ //if get wrong item ID or amount<=0, don't count weight of non existing items
push_val (st->stack, C_INT, 0);
}
sd = script_rid2sd (st);
if (itemdb_weight (nameid) * amount + sd->weight > sd->max_weight)
{
push_val (st->stack, C_INT, 0);
}
else
{
push_val (st->stack, C_INT, 1);
}
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_getitem (struct script_state *st)
{
int nameid, amount, flag = 0;
struct item item_tmp;
struct map_session_data *sd;
struct script_data *data;
sd = script_rid2sd (st);
data = &(st->stack->stack_data[st->start + 2]);
get_val (st, data);
if (data->type == C_STR || data->type == C_CONSTSTR)
{
const char *name = conv_str (st, data);
struct item_data *item_data = itemdb_searchname (name);
nameid = 727; //Default to iten
if (item_data != NULL)
nameid = item_data->nameid;
}
else
nameid = conv_num (st, data);
if ((amount =
conv_num (st, &(st->stack->stack_data[st->start + 3]))) <= 0)
{
return 0; //return if amount <=0, skip the useles iteration
}
//Violet Box, Blue Box, etc - random item pick
if (nameid < 0)
{ // ランダム
nameid = itemdb_searchrandomid (-nameid);
flag = 1;
}
if (nameid > 0)
{
memset (&item_tmp, 0, sizeof (item_tmp));
item_tmp.nameid = nameid;
if (!flag)
item_tmp.identify = 1;
else
item_tmp.identify = !itemdb_isequip3 (nameid);
if (st->end > st->start + 5) //アイテムを指定したIDに渡す
sd = map_id2sd (conv_num
(st, &(st->stack->stack_data[st->start + 5])));
if (sd == NULL) //アイテムを渡す相手がいなかったらお帰り
return 0;
if ((flag = pc_additem (sd, &item_tmp, amount)))
{
clif_additem (sd, 0, 0, flag);
map_addflooritem (&item_tmp, amount, sd->bl.m, sd->bl.x, sd->bl.y,
NULL, NULL, NULL, 0);
}
}
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_getitem2 (struct script_state *st)
{
int nameid, amount, flag = 0;
int iden, ref, attr, c1, c2, c3, c4;
struct item_data *item_data;
struct item item_tmp;
struct map_session_data *sd;
struct script_data *data;
sd = script_rid2sd (st);
data = &(st->stack->stack_data[st->start + 2]);
get_val (st, data);
if (data->type == C_STR || data->type == C_CONSTSTR)
{
const char *name = conv_str (st, data);
struct item_data *item_data = itemdb_searchname (name);
nameid = 512; //Apple item ID
if (item_data)
nameid = item_data->nameid;
}
else
nameid = conv_num (st, data);
amount = conv_num (st, &(st->stack->stack_data[st->start + 3]));
iden = conv_num (st, &(st->stack->stack_data[st->start + 4]));
ref = conv_num (st, &(st->stack->stack_data[st->start + 5]));
attr = conv_num (st, &(st->stack->stack_data[st->start + 6]));
c1 = conv_num (st, &(st->stack->stack_data[st->start + 7]));
c2 = conv_num (st, &(st->stack->stack_data[st->start + 8]));
c3 = conv_num (st, &(st->stack->stack_data[st->start + 9]));
c4 = conv_num (st, &(st->stack->stack_data[st->start + 10]));
if (st->end > st->start + 11) //アイテムを指定したIDに渡す
sd = map_id2sd (conv_num
(st, &(st->stack->stack_data[st->start + 11])));
if (sd == NULL) //アイテムを渡す相手がいなかったらお帰り
return 0;
if (nameid < 0)
{ // ランダム
nameid = itemdb_searchrandomid (-nameid);
flag = 1;
}
if (nameid > 0)
{
memset (&item_tmp, 0, sizeof (item_tmp));
item_data = itemdb_search (nameid);
if (item_data->type == 4 || item_data->type == 5)
{
if (ref > 10)
ref = 10;
}
else if (item_data->type == 7)
{
iden = 1;
ref = 0;
}
else
{
iden = 1;
ref = attr = 0;
}
item_tmp.nameid = nameid;
if (!flag)
item_tmp.identify = iden;
else if (item_data->type == 4 || item_data->type == 5)
item_tmp.identify = 0;
item_tmp.refine = ref;
item_tmp.attribute = attr;
item_tmp.card[0] = c1;
item_tmp.card[1] = c2;
item_tmp.card[2] = c3;
item_tmp.card[3] = c4;
if ((flag = pc_additem (sd, &item_tmp, amount)))
{
clif_additem (sd, 0, 0, flag);
map_addflooritem (&item_tmp, amount, sd->bl.m, sd->bl.x, sd->bl.y,
NULL, NULL, NULL, 0);
}
}
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_makeitem (struct script_state *st)
{
int nameid, amount, flag = 0;
int x, y, m;
char *mapname;
struct item item_tmp;
struct map_session_data *sd;
struct script_data *data;
sd = script_rid2sd (st);
data = &(st->stack->stack_data[st->start + 2]);
get_val (st, data);
if (data->type == C_STR || data->type == C_CONSTSTR)
{
const char *name = conv_str (st, data);
struct item_data *item_data = itemdb_searchname (name);
nameid = 512; //Apple Item ID
if (item_data)
nameid = item_data->nameid;
}
else
nameid = conv_num (st, data);
amount = conv_num (st, &(st->stack->stack_data[st->start + 3]));
mapname = conv_str (st, &(st->stack->stack_data[st->start + 4]));
x = conv_num (st, &(st->stack->stack_data[st->start + 5]));
y = conv_num (st, &(st->stack->stack_data[st->start + 6]));
if (sd && strcmp (mapname, "this") == 0)
m = sd->bl.m;
else
m = map_mapname2mapid (mapname);
if (nameid < 0)
{ // ランダム
nameid = itemdb_searchrandomid (-nameid);
flag = 1;
}
if (nameid > 0)
{
memset (&item_tmp, 0, sizeof (item_tmp));
item_tmp.nameid = nameid;
if (!flag)
item_tmp.identify = 1;
else
item_tmp.identify = !itemdb_isequip3 (nameid);
// clif_additem(sd,0,0,flag);
map_addflooritem (&item_tmp, amount, m, x, y, NULL, NULL, NULL, 0);
}
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_delitem (struct script_state *st)
{
int nameid = 0, amount, i;
struct map_session_data *sd;
struct script_data *data;
sd = script_rid2sd (st);
data = &(st->stack->stack_data[st->start + 2]);
get_val (st, data);
if (data->type == C_STR || data->type == C_CONSTSTR)
{
const char *name = conv_str (st, data);
struct item_data *item_data = itemdb_searchname (name);
//nameid=512;
if (item_data)
nameid = item_data->nameid;
}
else
nameid = conv_num (st, data);
amount = conv_num (st, &(st->stack->stack_data[st->start + 3]));
if (nameid < 500 || amount <= 0)
{ //by Lupus. Don't run FOR if u got wrong item ID or amount<=0
//printf("wrong item ID or amount<=0 : delitem %i,\n",nameid,amount);
return 0;
}
sd = script_rid2sd (st);
for (i = 0; i < MAX_INVENTORY; i++)
{
if (sd->status.inventory[i].nameid <= 0
|| sd->inventory_data[i] == NULL
|| sd->inventory_data[i]->type != 7
|| sd->status.inventory[i].amount <= 0)
continue;
}
for (i = 0; i < MAX_INVENTORY; i++)
{
if (sd->status.inventory[i].nameid == nameid)
{
if (sd->status.inventory[i].amount >= amount)
{
pc_delitem (sd, i, amount, 0);
break;
}
else
{
amount -= sd->status.inventory[i].amount;
if (amount == 0)
amount = sd->status.inventory[i].amount;
pc_delitem (sd, i, amount, 0);
break;
}
}
}
return 0;
}
/*==========================================
*キャラ関係のパラメータ取得
*------------------------------------------
*/
int buildin_readparam (struct script_state *st)
{
int type;
struct map_session_data *sd;
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
if (st->end > st->start + 3)
sd = map_nick2sd (conv_str
(st, &(st->stack->stack_data[st->start + 3])));
else
sd = script_rid2sd (st);
if (sd == NULL)
{
push_val (st->stack, C_INT, -1);
return 0;
}
push_val (st->stack, C_INT, pc_readparam (sd, type));
return 0;
}
/*==========================================
*キャラ関係のID取得
*------------------------------------------
*/
int buildin_getcharid (struct script_state *st)
{
int num;
struct map_session_data *sd;
num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
if (st->end > st->start + 3)
sd = map_nick2sd (conv_str
(st, &(st->stack->stack_data[st->start + 3])));
else
sd = script_rid2sd (st);
if (sd == NULL)
{
push_val (st->stack, C_INT, -1);
return 0;
}
if (num == 0)
push_val (st->stack, C_INT, sd->status.char_id);
if (num == 1)
push_val (st->stack, C_INT, sd->status.party_id);
if (num == 2)
push_val (st->stack, C_INT, sd->status.guild_id);
if (num == 3)
push_val (st->stack, C_INT, sd->status.account_id);
return 0;
}
/*==========================================
*指定IDのPT名取得
*------------------------------------------
*/
char *buildin_getpartyname_sub (int party_id)
{
struct party *p;
p = NULL;
p = party_search (party_id);
if (p != NULL)
{
char *buf;
buf = (char *) calloc (24, 1);
strcpy (buf, p->name);
return buf;
}
return 0;
}
int buildin_getpartyname (struct script_state *st)
{
char *name;
int party_id;
party_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
name = buildin_getpartyname_sub (party_id);
if (name != 0)
push_str (st->stack, C_STR, name);
else
push_str (st->stack, C_CONSTSTR, "null");
return 0;
}
/*==========================================
*指定IDのPT人数とメンバーID取得
*------------------------------------------
*/
int buildin_getpartymember (struct script_state *st)
{
struct party *p;
int i, j = 0;
p = NULL;
p = party_search (conv_num (st, &(st->stack->stack_data[st->start + 2])));
if (p != NULL)
{
for (i = 0; i < MAX_PARTY; i++)
{
if (p->member[i].account_id)
{
// printf("name:%s %d\n",p->member[i].name,i);
mapreg_setregstr (add_str ("$@partymembername$") + (i << 24),
p->member[i].name);
j++;
}
}
}
mapreg_setreg (add_str ("$@partymembercount"), j);
return 0;
}
/*==========================================
*指定IDのギルド名取得
*------------------------------------------
*/
char *buildin_getguildname_sub (int guild_id)
{
struct guild *g = NULL;
g = guild_search (guild_id);
if (g != NULL)
{
char *buf;
buf = (char *) calloc (24, 1);
strcpy (buf, g->name);
return buf;
}
return 0;
}
int buildin_getguildname (struct script_state *st)
{
char *name;
int guild_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
name = buildin_getguildname_sub (guild_id);
if (name != 0)
push_str (st->stack, C_STR, name);
else
push_str (st->stack, C_CONSTSTR, "null");
return 0;
}
/*==========================================
*指定IDのGuildMaster名取得
*------------------------------------------
*/
char *buildin_getguildmaster_sub (int guild_id)
{
struct guild *g = NULL;
g = guild_search (guild_id);
if (g != NULL)
{
char *buf;
buf = (char *) calloc (24, 1);
strncpy (buf, g->master, 23);
return buf;
}
return 0;
}
int buildin_getguildmaster (struct script_state *st)
{
char *master;
int guild_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
master = buildin_getguildmaster_sub (guild_id);
if (master != 0)
push_str (st->stack, C_STR, master);
else
push_str (st->stack, C_CONSTSTR, "null");
return 0;
}
int buildin_getguildmasterid (struct script_state *st)
{
char *master;
struct map_session_data *sd = NULL;
int guild_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
master = buildin_getguildmaster_sub (guild_id);
if (master != 0)
{
if ((sd = map_nick2sd (master)) == NULL)
{
push_val (st->stack, C_INT, 0);
return 0;
}
push_val (st->stack, C_INT, sd->status.char_id);
}
else
{
push_val (st->stack, C_INT, 0);
}
return 0;
}
/*==========================================
* キャラクタの名前
*------------------------------------------
*/
int buildin_strcharinfo (struct script_state *st)
{
struct map_session_data *sd;
int num;
sd = script_rid2sd (st);
num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
if (num == 0)
{
char *buf;
buf = (char *) calloc (24, 1);
strncpy (buf, sd->status.name, 23);
push_str (st->stack, C_STR, buf);
}
if (num == 1)
{
char *buf;
buf = buildin_getpartyname_sub (sd->status.party_id);
if (buf != 0)
push_str (st->stack, C_STR, buf);
else
push_str (st->stack, C_CONSTSTR, "");
}
if (num == 2)
{
char *buf;
buf = buildin_getguildname_sub (sd->status.guild_id);
if (buf != 0)
push_str (st->stack, C_STR, buf);
else
push_str (st->stack, C_CONSTSTR, "");
}
return 0;
}
unsigned int equip[10] =
{ 0x0100, 0x0010, 0x0020, 0x0002, 0x0004, 0x0040, 0x0008, 0x0080, 0x0200,
0x0001
};
/*==========================================
* GetEquipID(Pos); Pos: 1-10
*------------------------------------------
*/
int buildin_getequipid (struct script_state *st)
{
int i, num;
struct map_session_data *sd;
struct item_data *item;
sd = script_rid2sd (st);
if (sd == NULL)
{
printf ("getequipid: sd == NULL\n");
return 0;
}
num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
i = pc_checkequip (sd, equip[num - 1]);
if (i >= 0)
{
item = sd->inventory_data[i];
if (item)
push_val (st->stack, C_INT, item->nameid);
else
push_val (st->stack, C_INT, 0);
}
else
{
push_val (st->stack, C_INT, -1);
}
return 0;
}
/*==========================================
* 装備名文字列(精錬メニュー用)
*------------------------------------------
*/
int buildin_getequipname (struct script_state *st)
{
int i, num;
struct map_session_data *sd;
struct item_data *item;
char *buf;
buf = (char *) calloc (64, 1);
sd = script_rid2sd (st);
num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
i = pc_checkequip (sd, equip[num - 1]);
if (i >= 0)
{
item = sd->inventory_data[i];
if (item)
sprintf (buf, "%s-[%s]", pos[num - 1], item->jname);
else
sprintf (buf, "%s-[%s]", pos[num - 1], pos[10]);
}
else
{
sprintf (buf, "%s-[%s]", pos[num - 1], pos[10]);
}
push_str (st->stack, C_STR, buf);
return 0;
}
/*==========================================
* getbrokenid [Valaris]
*------------------------------------------
*/
int buildin_getbrokenid (struct script_state *st)
{
int i, num, id = 0, brokencounter = 0;
struct map_session_data *sd;
sd = script_rid2sd (st);
num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
for (i = 0; i < MAX_INVENTORY; i++)
{
if (sd->status.inventory[i].broken == 1)
{
brokencounter++;
if (num == brokencounter)
{
id = sd->status.inventory[i].nameid;
break;
}
}
}
push_val (st->stack, C_INT, id);
return 0;
}
/*==========================================
* repair [Valaris]
*------------------------------------------
*/
int buildin_repair (struct script_state *st)
{
int i, num;
int repaircounter = 0;
struct map_session_data *sd;
sd = script_rid2sd (st);
num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
for (i = 0; i < MAX_INVENTORY; i++)
{
if (sd->status.inventory[i].broken == 1)
{
repaircounter++;
if (num == repaircounter)
{
sd->status.inventory[i].broken = 0;
clif_equiplist (sd);
clif_produceeffect (sd, 0, sd->status.inventory[i].nameid);
clif_misceffect (&sd->bl, 3);
clif_displaymessage (sd->fd, "Item has been repaired.");
break;
}
}
}
return 0;
}
/*==========================================
* 装備チェック
*------------------------------------------
*/
int buildin_getequipisequiped (struct script_state *st)
{
int i, num;
struct map_session_data *sd;
num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
sd = script_rid2sd (st);
i = pc_checkequip (sd, equip[num - 1]);
if (i >= 0)
{
push_val (st->stack, C_INT, 1);
}
else
{
push_val (st->stack, C_INT, 0);
}
return 0;
}
/*==========================================
* 装備品精錬可能チェック
*------------------------------------------
*/
int buildin_getequipisenableref (struct script_state *st)
{
int i, num;
struct map_session_data *sd;
num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
sd = script_rid2sd (st);
i = pc_checkequip (sd, equip[num - 1]);
if (i >= 0 && num < 7 && sd->inventory_data[i]
&& (num != 1 || sd->inventory_data[i]->def > 1
|| (sd->inventory_data[i]->def == 1
&& sd->inventory_data[i]->equip_script == NULL)
|| (sd->inventory_data[i]->def <= 0
&& sd->inventory_data[i]->equip_script != NULL)))
{
push_val (st->stack, C_INT, 1);
}
else
{
push_val (st->stack, C_INT, 0);
}
return 0;
}
/*==========================================
* 装備品鑑定チェック
*------------------------------------------
*/
int buildin_getequipisidentify (struct script_state *st)
{
int i, num;
struct map_session_data *sd;
num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
sd = script_rid2sd (st);
i = pc_checkequip (sd, equip[num - 1]);
if (i >= 0)
push_val (st->stack, C_INT, sd->status.inventory[i].identify);
else
push_val (st->stack, C_INT, 0);
return 0;
}
/*==========================================
* 装備品精錬度
*------------------------------------------
*/
int buildin_getequiprefinerycnt (struct script_state *st)
{
int i, num;
struct map_session_data *sd;
num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
sd = script_rid2sd (st);
i = pc_checkequip (sd, equip[num - 1]);
if (i >= 0)
push_val (st->stack, C_INT, sd->status.inventory[i].refine);
else
push_val (st->stack, C_INT, 0);
return 0;
}
/*==========================================
* 装備品武器LV
*------------------------------------------
*/
int buildin_getequipweaponlv (struct script_state *st)
{
int i, num;
struct map_session_data *sd;
num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
sd = script_rid2sd (st);
i = pc_checkequip (sd, equip[num - 1]);
if (i >= 0 && sd->inventory_data[i])
push_val (st->stack, C_INT, sd->inventory_data[i]->wlv);
else
push_val (st->stack, C_INT, 0);
return 0;
}
/*==========================================
* 装備品精錬成功率
*------------------------------------------
*/
int buildin_getequippercentrefinery (struct script_state *st)
{
int i, num;
struct map_session_data *sd;
num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
sd = script_rid2sd (st);
i = pc_checkequip (sd, equip[num - 1]);
if (i >= 0)
push_val (st->stack, C_INT,
pc_percentrefinery (sd, &sd->status.inventory[i]));
else
push_val (st->stack, C_INT, 0);
return 0;
}
/*==========================================
* 精錬成功
*------------------------------------------
*/
int buildin_successrefitem (struct script_state *st)
{
int i, num, ep;
struct map_session_data *sd;
num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
sd = script_rid2sd (st);
i = pc_checkequip (sd, equip[num - 1]);
if (i >= 0)
{
ep = sd->status.inventory[i].equip;
sd->status.inventory[i].refine++;
pc_unequipitem (sd, i, 0);
clif_refine (sd->fd, sd, 0, i, sd->status.inventory[i].refine);
clif_delitem (sd, i, 1);
clif_additem (sd, i, 1, 0);
pc_equipitem (sd, i, ep);
clif_misceffect (&sd->bl, 3);
}
return 0;
}
/*==========================================
* 精錬失敗
*------------------------------------------
*/
int buildin_failedrefitem (struct script_state *st)
{
int i, num;
struct map_session_data *sd;
num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
sd = script_rid2sd (st);
i = pc_checkequip (sd, equip[num - 1]);
if (i >= 0)
{
sd->status.inventory[i].refine = 0;
pc_unequipitem (sd, i, 0);
// 精錬失敗エフェクトのパケット
clif_refine (sd->fd, sd, 1, i, sd->status.inventory[i].refine);
pc_delitem (sd, i, 1, 0);
// 他の人にも失敗を通知
clif_misceffect (&sd->bl, 2);
}
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_statusup (struct script_state *st)
{
int type;
struct map_session_data *sd;
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
sd = script_rid2sd (st);
pc_statusup (sd, type);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_statusup2 (struct script_state *st)
{
int type, val;
struct map_session_data *sd;
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
val = conv_num (st, &(st->stack->stack_data[st->start + 3]));
sd = script_rid2sd (st);
pc_statusup2 (sd, type, val);
return 0;
}
/*==========================================
* 装備品による能力値ボーナス
*------------------------------------------
*/
int buildin_bonus (struct script_state *st)
{
int type, val;
struct map_session_data *sd;
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
val = conv_num (st, &(st->stack->stack_data[st->start + 3]));
sd = script_rid2sd (st);
pc_bonus (sd, type, val);
return 0;
}
/*==========================================
* 装備品による能力値ボーナス
*------------------------------------------
*/
int buildin_bonus2 (struct script_state *st)
{
int type, type2, val;
struct map_session_data *sd;
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
type2 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
val = conv_num (st, &(st->stack->stack_data[st->start + 4]));
sd = script_rid2sd (st);
pc_bonus2 (sd, type, type2, val);
return 0;
}
/*==========================================
* 装備品による能力値ボーナス
*------------------------------------------
*/
int buildin_bonus3 (struct script_state *st)
{
int type, type2, type3, val;
struct map_session_data *sd;
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
type2 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
type3 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
val = conv_num (st, &(st->stack->stack_data[st->start + 5]));
sd = script_rid2sd (st);
pc_bonus3 (sd, type, type2, type3, val);
return 0;
}
/*==========================================
* スキル所得
*------------------------------------------
*/
int buildin_skill (struct script_state *st)
{
int id, level, flag = 1;
struct map_session_data *sd;
id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
level = conv_num (st, &(st->stack->stack_data[st->start + 3]));
if (st->end > st->start + 4)
flag = conv_num (st, &(st->stack->stack_data[st->start + 4]));
sd = script_rid2sd (st);
pc_skill (sd, id, level, flag);
clif_skillinfoblock (sd);
return 0;
}
/*==========================================
* [Fate] Sets the skill level permanently
*------------------------------------------
*/
int buildin_setskill (struct script_state *st)
{
int id, level;
struct map_session_data *sd;
id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
level = conv_num (st, &(st->stack->stack_data[st->start + 3]));
sd = script_rid2sd (st);
sd->status.skill[id].id = level ? id : 0;
sd->status.skill[id].lv = level;
clif_skillinfoblock (sd);
return 0;
}
/*==========================================
* ギルドスキル取得
*------------------------------------------
*/
int buildin_guildskill (struct script_state *st)
{
int id, level;
struct map_session_data *sd;
int i = 0;
id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
level = conv_num (st, &(st->stack->stack_data[st->start + 3]));
// if( st->end>st->start+4 )
// flag=conv_num(st,&(st->stack->stack_data[st->start+4]) );
sd = script_rid2sd (st);
for (i = 0; i < level; i++)
guild_skillup (sd, id);
return 0;
}
/*==========================================
* スキルレベル所得
*------------------------------------------
*/
int buildin_getskilllv (struct script_state *st)
{
int id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
push_val (st->stack, C_INT, pc_checkskill (script_rid2sd (st), id));
return 0;
}
/*==========================================
* getgdskilllv(Guild_ID, Skill_ID);
* skill_id = 10000 : GD_APPROVAL
* 10001 : GD_KAFRACONTACT
* 10002 : GD_GUARDIANRESEARCH
* 10003 : GD_CHARISMA
* 10004 : GD_EXTENSION
*------------------------------------------
*/
int buildin_getgdskilllv (struct script_state *st)
{
int guild_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
int skill_id = conv_num (st, &(st->stack->stack_data[st->start + 3]));
struct guild *g = guild_search (guild_id);
push_val (st->stack, C_INT,
(g == NULL) ? -1 : guild_checkskill (g, skill_id));
return 0;
/*
struct map_session_data *sd=NULL;
struct guild *g=NULL;
int skill_id;
skill_id=conv_num(st,& (st->stack->stack_data[st->start+2]));
sd=script_rid2sd(st);
if(sd && sd->status.guild_id > 0) g=guild_search(sd->status.guild_id);
if(sd && g) {
push_val(st->stack,C_INT, guild_checkskill(g,skill_id+9999) );
} else {
push_val(st->stack,C_INT,-1);
}
return 0;
*/
}
/*==========================================
*
*------------------------------------------
*/
int buildin_basicskillcheck (struct script_state *st)
{
push_val (st->stack, C_INT, battle_config.basic_skill_check);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_getgmlevel (struct script_state *st)
{
push_val (st->stack, C_INT, pc_isGM (script_rid2sd (st)));
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_end (struct script_state *st)
{
st->state = END;
return 0;
}
/*==========================================
* [Freeyorp] Return the current opt2
*------------------------------------------
*/
int buildin_getopt2 (struct script_state *st)
{
struct map_session_data *sd;
sd = script_rid2sd (st);
push_val (st->stack, C_INT, sd->opt2);
return 0;
}
/*==========================================
* [Freeyorp] Sets opt2
*------------------------------------------
*/
int buildin_setopt2 (struct script_state *st)
{
int new_opt2;
struct map_session_data *sd;
new_opt2 = conv_num (st, &(st->stack->stack_data[st->start + 2]));
sd = script_rid2sd (st);
if (new_opt2 == sd->opt2)
return 0;
sd->opt2 = new_opt2;
clif_changeoption (&sd->bl);
pc_calcstatus (sd, 0);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_checkoption (struct script_state *st)
{
int type;
struct map_session_data *sd;
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
sd = script_rid2sd (st);
if (sd->status.option & type)
{
push_val (st->stack, C_INT, 1);
}
else
{
push_val (st->stack, C_INT, 0);
}
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_setoption (struct script_state *st)
{
int type;
struct map_session_data *sd;
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
sd = script_rid2sd (st);
pc_setoption (sd, type);
return 0;
}
/*==========================================
* Checkcart [Valaris]
*------------------------------------------
*/
int buildin_checkcart (struct script_state *st)
{
struct map_session_data *sd;
sd = script_rid2sd (st);
if (pc_iscarton (sd))
{
push_val (st->stack, C_INT, 1);
}
else
{
push_val (st->stack, C_INT, 0);
}
return 0;
}
/*==========================================
* カートを付ける
*------------------------------------------
*/
int buildin_setcart (struct script_state *st)
{
struct map_session_data *sd;
sd = script_rid2sd (st);
pc_setcart (sd, 1);
return 0;
}
/*==========================================
* checkfalcon [Valaris]
*------------------------------------------
*/
int buildin_checkfalcon (struct script_state *st)
{
struct map_session_data *sd;
sd = script_rid2sd (st);
if (pc_isfalcon (sd))
{
push_val (st->stack, C_INT, 1);
}
else
{
push_val (st->stack, C_INT, 0);
}
return 0;
}
/*==========================================
* 鷹を付ける
*------------------------------------------
*/
int buildin_setfalcon (struct script_state *st)
{
struct map_session_data *sd;
sd = script_rid2sd (st);
pc_setfalcon (sd);
return 0;
}
/*==========================================
* Checkcart [Valaris]
*------------------------------------------
*/
int buildin_checkriding (struct script_state *st)
{
struct map_session_data *sd;
sd = script_rid2sd (st);
if (pc_isriding (sd))
{
push_val (st->stack, C_INT, 1);
}
else
{
push_val (st->stack, C_INT, 0);
}
return 0;
}
/*==========================================
* ペコペコ乗り
*------------------------------------------
*/
int buildin_setriding (struct script_state *st)
{
struct map_session_data *sd;
sd = script_rid2sd (st);
pc_setriding (sd);
return 0;
}
/*==========================================
* セーブポイントの保存
*------------------------------------------
*/
int buildin_savepoint (struct script_state *st)
{
int x, y;
char *str;
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
pc_setsavepoint (script_rid2sd (st), str, x, y);
return 0;
}
/*==========================================
* gettimetick(type)
*
* type The type of time measurement.
* Specify 0 for the system tick, 1 for
* seconds elapsed today, or 2 for seconds
* since Unix epoch. Defaults to 0 for any
* other value.
*------------------------------------------
*/
int buildin_gettimetick (struct script_state *st) /* Asgard Version */
{
int type;
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
switch (type)
{
/* Number of seconds elapsed today (0-86399, 00:00:00-23:59:59). */
case 1:
{
time_t timer;
struct tm *t;
time (&timer);
t = gmtime (&timer);
push_val (st->stack, C_INT,
((t->tm_hour) * 3600 + (t->tm_min) * 60 + t->tm_sec));
break;
}
/* Seconds since Unix epoch. */
case 2:
push_val (st->stack, C_INT, (int) time (NULL));
break;
/* System tick (unsigned int, and yes, it will wrap). */
case 0:
default:
push_val (st->stack, C_INT, gettick ());
break;
}
return 0;
}
/*==========================================
* GetTime(Type);
* 1: Sec 2: Min 3: Hour
* 4: WeekDay 5: MonthDay 6: Month
* 7: Year
*------------------------------------------
*/
int buildin_gettime (struct script_state *st) /* Asgard Version */
{
int type;
time_t timer;
struct tm *t;
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
time (&timer);
t = gmtime (&timer);
switch (type)
{
case 1: //Sec(0~59)
push_val (st->stack, C_INT, t->tm_sec);
break;
case 2: //Min(0~59)
push_val (st->stack, C_INT, t->tm_min);
break;
case 3: //Hour(0~23)
push_val (st->stack, C_INT, t->tm_hour);
break;
case 4: //WeekDay(0~6)
push_val (st->stack, C_INT, t->tm_wday);
break;
case 5: //MonthDay(01~31)
push_val (st->stack, C_INT, t->tm_mday);
break;
case 6: //Month(01~12)
push_val (st->stack, C_INT, t->tm_mon + 1);
break;
case 7: //Year(20xx)
push_val (st->stack, C_INT, t->tm_year + 1900);
break;
default: //(format error)
push_val (st->stack, C_INT, -1);
break;
}
return 0;
}
/*==========================================
* GetTimeStr("TimeFMT", Length);
*------------------------------------------
*/
int buildin_gettimestr (struct script_state *st)
{
char *tmpstr;
char *fmtstr;
int maxlen;
time_t now = time (NULL);
fmtstr = conv_str (st, &(st->stack->stack_data[st->start + 2]));
maxlen = conv_num (st, &(st->stack->stack_data[st->start + 3]));
tmpstr = (char *) calloc (maxlen + 1, 1);
strftime (tmpstr, maxlen, fmtstr, gmtime (&now));
tmpstr[maxlen] = '\0';
push_str (st->stack, C_STR, tmpstr);
return 0;
}
/*==========================================
* カプラ倉庫を開く
*------------------------------------------
*/
int buildin_openstorage (struct script_state *st)
{
// int sync = 0;
// if (st->end >= 3) sync = conv_num(st,& (st->stack->stack_data[st->start+2]));
struct map_session_data *sd = script_rid2sd (st);
// if (sync) {
st->state = STOP;
sd->npc_flags.storage = 1;
// } else st->state = END;
storage_storageopen (sd);
return 0;
}
int buildin_guildopenstorage (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
int ret;
st->state = STOP;
ret = storage_guild_storageopen (sd);
push_val (st->stack, C_INT, ret);
return 0;
}
/*==========================================
* アイテムによるスキル発動
*------------------------------------------
*/
int buildin_itemskill (struct script_state *st)
{
int id, lv;
char *str;
struct map_session_data *sd = script_rid2sd (st);
id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
lv = conv_num (st, &(st->stack->stack_data[st->start + 3]));
str = conv_str (st, &(st->stack->stack_data[st->start + 4]));
// 詠唱中にスキルアイテムは使用できない
if (sd->skilltimer != -1)
return 0;
sd->skillitem = id;
sd->skillitemlv = lv;
clif_item_skill (sd, id, lv, str);
return 0;
}
/*==========================================
* NPCで経験値上げる
*------------------------------------------
*/
int buildin_getexp (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
int base = 0, job = 0;
base = conv_num (st, &(st->stack->stack_data[st->start + 2]));
job = conv_num (st, &(st->stack->stack_data[st->start + 3]));
if (base < 0 || job < 0)
return 0;
if (sd)
pc_gainexp_reason (sd, base, job, PC_GAINEXP_REASON_SCRIPT);
return 0;
}
/*==========================================
* モンスター発生
*------------------------------------------
*/
int buildin_monster (struct script_state *st)
{
int mob_class, amount, x, y;
char *str, *map, *event = "";
map = conv_str (st, &(st->stack->stack_data[st->start + 2]));
x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
str = conv_str (st, &(st->stack->stack_data[st->start + 5]));
mob_class = conv_num (st, &(st->stack->stack_data[st->start + 6]));
amount = conv_num (st, &(st->stack->stack_data[st->start + 7]));
if (st->end > st->start + 8)
event = conv_str (st, &(st->stack->stack_data[st->start + 8]));
mob_once_spawn (map_id2sd (st->rid), map, x, y, str, mob_class, amount,
event);
return 0;
}
/*==========================================
* モンスター発生
*------------------------------------------
*/
int buildin_areamonster (struct script_state *st)
{
int mob_class, amount, x0, y0, x1, y1;
char *str, *map, *event = "";
map = conv_str (st, &(st->stack->stack_data[st->start + 2]));
x0 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
y0 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
x1 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
y1 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
str = conv_str (st, &(st->stack->stack_data[st->start + 7]));
mob_class = conv_num (st, &(st->stack->stack_data[st->start + 8]));
amount = conv_num (st, &(st->stack->stack_data[st->start + 9]));
if (st->end > st->start + 10)
event = conv_str (st, &(st->stack->stack_data[st->start + 10]));
mob_once_spawn_area (map_id2sd (st->rid), map, x0, y0, x1, y1, str, mob_class,
amount, event);
return 0;
}
/*==========================================
* モンスター削除
*------------------------------------------
*/
int buildin_killmonster_sub (struct block_list *bl, va_list ap)
{
char *event = va_arg (ap, char *);
int allflag = va_arg (ap, int);
if (!allflag)
{
if (strcmp (event, ((struct mob_data *) bl)->npc_event) == 0)
mob_delete ((struct mob_data *) bl);
return 0;
}
else if (allflag)
{
if (((struct mob_data *) bl)->spawndelay1 == -1
&& ((struct mob_data *) bl)->spawndelay2 == -1)
mob_delete ((struct mob_data *) bl);
return 0;
}
return 0;
}
int buildin_killmonster (struct script_state *st)
{
char *mapname, *event;
int m, allflag = 0;
mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
event = conv_str (st, &(st->stack->stack_data[st->start + 3]));
if (strcmp (event, "All") == 0)
allflag = 1;
if ((m = map_mapname2mapid (mapname)) < 0)
return 0;
map_foreachinarea (buildin_killmonster_sub,
m, 0, 0, map[m].xs, map[m].ys, BL_MOB, event, allflag);
return 0;
}
int buildin_killmonsterall_sub (struct block_list *bl, va_list ap)
{
mob_delete ((struct mob_data *) bl);
return 0;
}
int buildin_killmonsterall (struct script_state *st)
{
char *mapname;
int m;
mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
if ((m = map_mapname2mapid (mapname)) < 0)
return 0;
map_foreachinarea (buildin_killmonsterall_sub,
m, 0, 0, map[m].xs, map[m].ys, BL_MOB);
return 0;
}
/*==========================================
* イベント実行
*------------------------------------------
*/
int buildin_doevent (struct script_state *st)
{
char *event;
event = conv_str (st, &(st->stack->stack_data[st->start + 2]));
npc_event (map_id2sd (st->rid), event, 0);
return 0;
}
/*==========================================
* NPC主体イベント実行
*------------------------------------------
*/
int buildin_donpcevent (struct script_state *st)
{
char *event;
event = conv_str (st, &(st->stack->stack_data[st->start + 2]));
npc_event_do (event);
return 0;
}
/*==========================================
* イベントタイマー追加
*------------------------------------------
*/
int buildin_addtimer (struct script_state *st)
{
char *event;
int tick;
tick = conv_num (st, &(st->stack->stack_data[st->start + 2]));
event = conv_str (st, &(st->stack->stack_data[st->start + 3]));
pc_addeventtimer (script_rid2sd (st), tick, event);
return 0;
}
/*==========================================
* イベントタイマー削除
*------------------------------------------
*/
int buildin_deltimer (struct script_state *st)
{
char *event;
event = conv_str (st, &(st->stack->stack_data[st->start + 2]));
pc_deleventtimer (script_rid2sd (st), event);
return 0;
}
/*==========================================
* イベントタイマーのカウント値追加
*------------------------------------------
*/
int buildin_addtimercount (struct script_state *st)
{
char *event;
int tick;
event = conv_str (st, &(st->stack->stack_data[st->start + 2]));
tick = conv_num (st, &(st->stack->stack_data[st->start + 3]));
pc_addeventtimercount (script_rid2sd (st), event, tick);
return 0;
}
/*==========================================
* NPCタイマー初期化
*------------------------------------------
*/
int buildin_initnpctimer (struct script_state *st)
{
struct npc_data *nd;
if (st->end > st->start + 2)
nd = npc_name2id (conv_str
(st, &(st->stack->stack_data[st->start + 2])));
else
nd = (struct npc_data *) map_id2bl (st->oid);
npc_settimerevent_tick (nd, 0);
npc_timerevent_start (nd);
return 0;
}
/*==========================================
* NPCタイマー開始
*------------------------------------------
*/
int buildin_startnpctimer (struct script_state *st)
{
struct npc_data *nd;
if (st->end > st->start + 2)
nd = npc_name2id (conv_str
(st, &(st->stack->stack_data[st->start + 2])));
else
nd = (struct npc_data *) map_id2bl (st->oid);
npc_timerevent_start (nd);
return 0;
}
/*==========================================
* NPCタイマー停止
*------------------------------------------
*/
int buildin_stopnpctimer (struct script_state *st)
{
struct npc_data *nd;
if (st->end > st->start + 2)
nd = npc_name2id (conv_str
(st, &(st->stack->stack_data[st->start + 2])));
else
nd = (struct npc_data *) map_id2bl (st->oid);
npc_timerevent_stop (nd);
return 0;
}
/*==========================================
* NPCタイマー情報所得
*------------------------------------------
*/
int buildin_getnpctimer (struct script_state *st)
{
struct npc_data *nd;
int type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
int val = 0;
if (st->end > st->start + 3)
nd = npc_name2id (conv_str
(st, &(st->stack->stack_data[st->start + 3])));
else
nd = (struct npc_data *) map_id2bl (st->oid);
switch (type)
{
case 0:
val = npc_gettimerevent_tick (nd);
break;
case 1:
val = (nd->u.scr.nexttimer >= 0);
break;
case 2:
val = nd->u.scr.timeramount;
break;
}
push_val (st->stack, C_INT, val);
return 0;
}
/*==========================================
* NPCタイマー値設定
*------------------------------------------
*/
int buildin_setnpctimer (struct script_state *st)
{
int tick;
struct npc_data *nd;
tick = conv_num (st, &(st->stack->stack_data[st->start + 2]));
if (st->end > st->start + 3)
nd = npc_name2id (conv_str
(st, &(st->stack->stack_data[st->start + 3])));
else
nd = (struct npc_data *) map_id2bl (st->oid);
npc_settimerevent_tick (nd, tick);
return 0;
}
/*==========================================
* 天の声アナウンス
*------------------------------------------
*/
int buildin_announce (struct script_state *st)
{
char *str;
int flag;
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
flag = conv_num (st, &(st->stack->stack_data[st->start + 3]));
if (flag & 0x0f)
{
struct block_list *bl = (flag & 0x08) ? map_id2bl (st->oid) :
(struct block_list *) script_rid2sd (st);
clif_GMmessage (bl, str, strlen (str) + 1, flag);
}
else
intif_GMmessage (str, strlen (str) + 1, flag);
return 0;
}
/*==========================================
* 天の声アナウンス(特定マップ)
*------------------------------------------
*/
int buildin_mapannounce_sub (struct block_list *bl, va_list ap)
{
char *str;
int len, flag;
str = va_arg (ap, char *);
len = va_arg (ap, int);
flag = va_arg (ap, int);
clif_GMmessage (bl, str, len, flag | 3);
return 0;
}
int buildin_mapannounce (struct script_state *st)
{
char *mapname, *str;
int flag, m;
mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
str = conv_str (st, &(st->stack->stack_data[st->start + 3]));
flag = conv_num (st, &(st->stack->stack_data[st->start + 4]));
if ((m = map_mapname2mapid (mapname)) < 0)
return 0;
map_foreachinarea (buildin_mapannounce_sub,
m, 0, 0, map[m].xs, map[m].ys, BL_PC, str,
strlen (str) + 1, flag & 0x10);
return 0;
}
/*==========================================
* 天の声アナウンス(特定エリア)
*------------------------------------------
*/
int buildin_areaannounce (struct script_state *st)
{
char *map, *str;
int flag, m;
int x0, y0, x1, y1;
map = conv_str (st, &(st->stack->stack_data[st->start + 2]));
x0 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
y0 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
x1 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
y1 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
str = conv_str (st, &(st->stack->stack_data[st->start + 7]));
flag = conv_num (st, &(st->stack->stack_data[st->start + 8]));
if ((m = map_mapname2mapid (map)) < 0)
return 0;
map_foreachinarea (buildin_mapannounce_sub,
m, x0, y0, x1, y1, BL_PC, str, strlen (str) + 1,
flag & 0x10);
return 0;
}
/*==========================================
* ユーザー数所得
*------------------------------------------
*/
int buildin_getusers (struct script_state *st)
{
int flag = conv_num (st, &(st->stack->stack_data[st->start + 2]));
struct block_list *bl = map_id2bl ((flag & 0x08) ? st->oid : st->rid);
int val = 0;
switch (flag & 0x07)
{
case 0:
val = map[bl->m].users;
break;
case 1:
val = map_getusers ();
break;
}
push_val (st->stack, C_INT, val);
return 0;
}
/*==========================================
* マップ指定ユーザー数所得
*------------------------------------------
*/
int buildin_getmapusers (struct script_state *st)
{
char *str;
int m;
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
if ((m = map_mapname2mapid (str)) < 0)
{
push_val (st->stack, C_INT, -1);
return 0;
}
push_val (st->stack, C_INT, map[m].users);
return 0;
}
/*==========================================
* エリア指定ユーザー数所得
*------------------------------------------
*/
int buildin_getareausers_sub (struct block_list *bl, va_list ap)
{
int *users = va_arg (ap, int *);
(*users)++;
return 0;
}
int buildin_getareausers (struct script_state *st)
{
char *str;
int m, x0, y0, x1, y1, users = 0;
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
x0 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
y0 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
x1 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
y1 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
if ((m = map_mapname2mapid (str)) < 0)
{
push_val (st->stack, C_INT, -1);
return 0;
}
map_foreachinarea (buildin_getareausers_sub,
m, x0, y0, x1, y1, BL_PC, &users);
push_val (st->stack, C_INT, users);
return 0;
}
/*==========================================
* エリア指定ドロップアイテム数所得
*------------------------------------------
*/
int buildin_getareadropitem_sub (struct block_list *bl, va_list ap)
{
int item = va_arg (ap, int);
int *amount = va_arg (ap, int *);
struct flooritem_data *drop = (struct flooritem_data *) bl;
if (drop->item_data.nameid == item)
(*amount) += drop->item_data.amount;
return 0;
}
int buildin_getareadropitem_sub_anddelete (struct block_list *bl, va_list ap)
{
int item = va_arg (ap, int);
int *amount = va_arg (ap, int *);
struct flooritem_data *drop = (struct flooritem_data *) bl;
if (drop->item_data.nameid == item) {
(*amount) += drop->item_data.amount;
clif_clearflooritem(drop, 0);
map_delobject(drop->bl.id, drop->bl.type);
}
return 0;
}
int buildin_getareadropitem (struct script_state *st)
{
char *str;
int m, x0, y0, x1, y1, item, amount = 0, delitems = 0;
struct script_data *data;
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
x0 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
y0 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
x1 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
y1 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
data = &(st->stack->stack_data[st->start + 7]);
get_val (st, data);
if (data->type == C_STR || data->type == C_CONSTSTR)
{
const char *name = conv_str (st, data);
struct item_data *item_data = itemdb_searchname (name);
item = 512;
if (item_data)
item = item_data->nameid;
}
else
item = conv_num (st, data);
if (st->end > st->start + 8)
delitems = conv_num (st, &(st->stack->stack_data[st->start + 8]));
if ((m = map_mapname2mapid (str)) < 0)
{
push_val (st->stack, C_INT, -1);
return 0;
}
if (delitems)
map_foreachinarea (buildin_getareadropitem_sub_anddelete,
m, x0, y0, x1, y1, BL_ITEM, item, &amount);
else
map_foreachinarea (buildin_getareadropitem_sub,
m, x0, y0, x1, y1, BL_ITEM, item, &amount);
push_val (st->stack, C_INT, amount);
return 0;
}
/*==========================================
* NPCの有効化
*------------------------------------------
*/
int buildin_enablenpc (struct script_state *st)
{
char *str;
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
npc_enable (str, 1);
return 0;
}
/*==========================================
* NPCの無効化
*------------------------------------------
*/
int buildin_disablenpc (struct script_state *st)
{
char *str;
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
npc_enable (str, 0);
return 0;
}
int buildin_enablearena (struct script_state *st) // Added by RoVeRT
{
struct npc_data *nd = (struct npc_data *) map_id2bl (st->oid);
struct chat_data *cd;
if (nd == NULL
|| (cd = (struct chat_data *) map_id2bl (nd->chat_id)) == NULL)
return 0;
npc_enable (nd->name, 1);
nd->arenaflag = 1;
if (cd->users >= cd->trigger && cd->npc_event[0])
npc_timer_event (cd->npc_event);
return 0;
}
int buildin_disablearena (struct script_state *st) // Added by RoVeRT
{
struct npc_data *nd = (struct npc_data *) map_id2bl (st->oid);
nd->arenaflag = 0;
return 0;
}
/*==========================================
* 隠れているNPCの表示
*------------------------------------------
*/
int buildin_hideoffnpc (struct script_state *st)
{
char *str;
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
npc_enable (str, 2);
return 0;
}
/*==========================================
* NPCをハイディング
*------------------------------------------
*/
int buildin_hideonnpc (struct script_state *st)
{
char *str;
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
npc_enable (str, 4);
return 0;
}
/*==========================================
* 状態異常にかかる
*------------------------------------------
*/
int buildin_sc_start (struct script_state *st)
{
struct block_list *bl;
int type, tick, val1;
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
tick = conv_num (st, &(st->stack->stack_data[st->start + 3]));
val1 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
if (st->end > st->start + 5) //指定したキャラを状態異常にする
bl = map_id2bl (conv_num
(st, &(st->stack->stack_data[st->start + 5])));
else
bl = map_id2bl (st->rid);
if (bl->type == BL_PC
&& ((struct map_session_data *) bl)->state.potionpitcher_flag)
bl = map_id2bl (((struct map_session_data *) bl)->skilltarget);
skill_status_change_start (bl, type, val1, 0, 0, 0, tick, 0);
return 0;
}
/*==========================================
* 状態異常にかかる(確率指定)
*------------------------------------------
*/
int buildin_sc_start2 (struct script_state *st)
{
struct block_list *bl;
int type, tick, val1, per;
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
tick = conv_num (st, &(st->stack->stack_data[st->start + 3]));
val1 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
per = conv_num (st, &(st->stack->stack_data[st->start + 5]));
if (st->end > st->start + 6) //指定したキャラを状態異常にする
bl = map_id2bl (conv_num
(st, &(st->stack->stack_data[st->start + 6])));
else
bl = map_id2bl (st->rid);
if (bl->type == BL_PC
&& ((struct map_session_data *) bl)->state.potionpitcher_flag)
bl = map_id2bl (((struct map_session_data *) bl)->skilltarget);
if (MRAND (10000) < per)
skill_status_change_start (bl, type, val1, 0, 0, 0, tick, 0);
return 0;
}
/*==========================================
* 状態異常が直る
*------------------------------------------
*/
int buildin_sc_end (struct script_state *st)
{
struct block_list *bl;
int type;
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
bl = map_id2bl (st->rid);
if (bl->type == BL_PC
&& ((struct map_session_data *) bl)->state.potionpitcher_flag)
bl = map_id2bl (((struct map_session_data *) bl)->skilltarget);
skill_status_change_end (bl, type, -1);
// if(battle_config.etc_log)
// printf("sc_end : %d %d\n",st->rid,type);
return 0;
}
int buildin_sc_check (struct script_state *st)
{
struct block_list *bl;
int type;
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
bl = map_id2bl (st->rid);
if (bl->type == BL_PC
&& ((struct map_session_data *) bl)->state.potionpitcher_flag)
bl = map_id2bl (((struct map_session_data *) bl)->skilltarget);
push_val (st->stack, C_INT, skill_status_change_active (bl, type));
return 0;
}
/*==========================================
* 状態異常耐性を計算した確率を返す
*------------------------------------------
*/
int buildin_getscrate (struct script_state *st)
{
struct block_list *bl;
int sc_def = 100, sc_def_mdef2, sc_def_vit2, sc_def_int2, sc_def_luk2;
int type, rate, luk;
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
rate = conv_num (st, &(st->stack->stack_data[st->start + 3]));
if (st->end > st->start + 4) //指定したキャラの耐性を計算する
bl = map_id2bl (conv_num
(st, &(st->stack->stack_data[st->start + 6])));
else
bl = map_id2bl (st->rid);
luk = battle_get_luk (bl);
sc_def_mdef2 = 100 - (3 + battle_get_mdef (bl) + luk / 3);
sc_def_vit2 = 100 - (3 + battle_get_vit (bl) + luk / 3);
sc_def_int2 = 100 - (3 + battle_get_int (bl) + luk / 3);
sc_def_luk2 = 100 - (3 + luk);
if (type == SC_STONE || type == SC_FREEZE)
sc_def = sc_def_mdef2;
else if (type == SC_STAN || type == SC_POISON || type == SC_SILENCE)
sc_def = sc_def_vit2;
else if (type == SC_SLEEP || type == SC_CONFUSION || type == SC_BLIND)
sc_def = sc_def_int2;
else if (type == SC_CURSE)
sc_def = sc_def_luk2;
rate = rate * sc_def / 100;
push_val (st->stack, C_INT, rate);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_debugmes (struct script_state *st)
{
conv_str (st, &(st->stack->stack_data[st->start + 2]));
printf ("script debug : %d %d : %s\n", st->rid, st->oid,
st->stack->stack_data[st->start + 2].u.str);
return 0;
}
/*==========================================
* Added - AppleGirl For Advanced Classes, (Updated for Cleaner Script Purposes)
*------------------------------------------
*/
int buildin_resetlvl (struct script_state *st)
{
struct map_session_data *sd;
int type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
sd = script_rid2sd (st);
pc_resetlvl (sd, type);
return 0;
}
/*==========================================
* ステータスリセット
*------------------------------------------
*/
int buildin_resetstatus (struct script_state *st)
{
struct map_session_data *sd;
sd = script_rid2sd (st);
pc_resetstate (sd);
return 0;
}
/*==========================================
* スキルリセット
*------------------------------------------
*/
int buildin_resetskill (struct script_state *st)
{
struct map_session_data *sd;
sd = script_rid2sd (st);
pc_resetskill (sd);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
int buildin_changebase (struct script_state *st)
{
struct map_session_data *sd = NULL;
int vclass;
if (st->end > st->start + 3)
sd = map_id2sd (conv_num
(st, &(st->stack->stack_data[st->start + 3])));
else
sd = script_rid2sd (st);
if (sd == NULL)
return 0;
vclass = conv_num (st, &(st->stack->stack_data[st->start + 2]));
if (vclass == 22 && !battle_config.wedding_modifydisplay)
return 0;
// if(vclass==22) {
// pc_unequipitem(sd,sd->equip_index[9],0); // 装備外
// }
sd->view_class = vclass;
return 0;
}
/*==========================================
* 性別変換
*------------------------------------------
*/
int buildin_changesex (struct script_state *st)
{
struct map_session_data *sd = NULL;
sd = script_rid2sd (st);
if (sd->status.sex == 0)
{
sd->status.sex = 1;
sd->sex = 1;
if (sd->status.pc_class == 20 || sd->status.pc_class == 4021)
sd->status.pc_class -= 1;
}
else if (sd->status.sex == 1)
{
sd->status.sex = 0;
sd->sex = 0;
if (sd->status.pc_class == 19 || sd->status.pc_class == 4020)
sd->status.pc_class += 1;
}
chrif_char_ask_name (-1, sd->status.name, 5, 0, 0, 0, 0, 0, 0); // type: 5 - changesex
chrif_save (sd);
return 0;
}
/*==========================================
* npcチャット作成
*------------------------------------------
*/
int buildin_waitingroom (struct script_state *st)
{
char *name, *ev = "";
int limit, trigger = 0, pub = 1;
name = conv_str (st, &(st->stack->stack_data[st->start + 2]));
limit = conv_num (st, &(st->stack->stack_data[st->start + 3]));
if (limit == 0)
pub = 3;
if ((st->end > st->start + 5))
{
struct script_data *data = &(st->stack->stack_data[st->start + 5]);
get_val (st, data);
if (data->type == C_INT)
{
// 新Athena仕様(旧Athena仕様と互換性あり)
ev = conv_str (st, &(st->stack->stack_data[st->start + 4]));
trigger = conv_num (st, &(st->stack->stack_data[st->start + 5]));
}
else
{
// eathena仕様
trigger = conv_num (st, &(st->stack->stack_data[st->start + 4]));
ev = conv_str (st, &(st->stack->stack_data[st->start + 5]));
}
}
else
{
// 旧Athena仕様
if (st->end > st->start + 4)
ev = conv_str (st, &(st->stack->stack_data[st->start + 4]));
}
chat_createnpcchat ((struct npc_data *) map_id2bl (st->oid),
limit, pub, trigger, name, strlen (name) + 1, ev);
return 0;
}
/*==========================================
* npcチャット削除
*------------------------------------------
*/
int buildin_delwaitingroom (struct script_state *st)
{
struct npc_data *nd;
if (st->end > st->start + 2)
nd = npc_name2id (conv_str
(st, &(st->stack->stack_data[st->start + 2])));
else
nd = (struct npc_data *) map_id2bl (st->oid);
chat_deletenpcchat (nd);
return 0;
}
/*==========================================
* npcチャット全員蹴り出す
*------------------------------------------
*/
int buildin_waitingroomkickall (struct script_state *st)
{
struct npc_data *nd;
struct chat_data *cd;
if (st->end > st->start + 2)
nd = npc_name2id (conv_str
(st, &(st->stack->stack_data[st->start + 2])));
else
nd = (struct npc_data *) map_id2bl (st->oid);
if (nd == NULL
|| (cd = (struct chat_data *) map_id2bl (nd->chat_id)) == NULL)
return 0;
chat_npckickall (cd);
return 0;
}
/*==========================================
* npcチャットイベント有効化
*------------------------------------------
*/
int buildin_enablewaitingroomevent (struct script_state *st)
{
struct npc_data *nd;
struct chat_data *cd;
if (st->end > st->start + 2)
nd = npc_name2id (conv_str
(st, &(st->stack->stack_data[st->start + 2])));
else
nd = (struct npc_data *) map_id2bl (st->oid);
if (nd == NULL
|| (cd = (struct chat_data *) map_id2bl (nd->chat_id)) == NULL)
return 0;
chat_enableevent (cd);
return 0;
}
/*==========================================
* npcチャットイベント無効化
*------------------------------------------
*/
int buildin_disablewaitingroomevent (struct script_state *st)
{
struct npc_data *nd;
struct chat_data *cd;
if (st->end > st->start + 2)
nd = npc_name2id (conv_str
(st, &(st->stack->stack_data[st->start + 2])));
else
nd = (struct npc_data *) map_id2bl (st->oid);
if (nd == NULL
|| (cd = (struct chat_data *) map_id2bl (nd->chat_id)) == NULL)
return 0;
chat_disableevent (cd);
return 0;
}
/*==========================================
* npcチャット状態所得
*------------------------------------------
*/
int buildin_getwaitingroomstate (struct script_state *st)
{
struct npc_data *nd;
struct chat_data *cd;
int val = 0, type;
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
if (st->end > st->start + 3)
nd = npc_name2id (conv_str
(st, &(st->stack->stack_data[st->start + 3])));
else
nd = (struct npc_data *) map_id2bl (st->oid);
if (nd == NULL
|| (cd = (struct chat_data *) map_id2bl (nd->chat_id)) == NULL)
{
push_val (st->stack, C_INT, -1);
return 0;
}
switch (type)
{
case 0:
val = cd->users;
break;
case 1:
val = cd->limit;
break;
case 2:
val = cd->trigger & 0x7f;
break;
case 3:
val = ((cd->trigger & 0x80) > 0);
break;
case 32:
val = (cd->users >= cd->limit);
break;
case 33:
val = (cd->users >= cd->trigger);
break;
case 4:
push_str (st->stack, C_CONSTSTR, cd->title);
return 0;
case 5:
push_str (st->stack, C_CONSTSTR, cd->pass);
return 0;
case 16:
push_str (st->stack, C_CONSTSTR, cd->npc_event);
return 0;
}
push_val (st->stack, C_INT, val);
return 0;
}
/*==========================================
* チャットメンバー(規定人数)ワープ
*------------------------------------------
*/
int buildin_warpwaitingpc (struct script_state *st)
{
int x, y, i, n;
char *str;
struct npc_data *nd = (struct npc_data *) map_id2bl (st->oid);
struct chat_data *cd;
if (nd == NULL
|| (cd = (struct chat_data *) map_id2bl (nd->chat_id)) == NULL)
return 0;
n = cd->trigger & 0x7f;
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
if (st->end > st->start + 5)
n = conv_num (st, &(st->stack->stack_data[st->start + 5]));
for (i = 0; i < n; i++)
{
struct map_session_data *sd = cd->usersd[0]; // リスト先頭のPCを次々に。
mapreg_setreg (add_str ("$@warpwaitingpc") + (i << 24), sd->bl.id);
if (strcmp (str, "Random") == 0)
pc_randomwarp (sd, 3);
else if (strcmp (str, "SavePoint") == 0)
{
if (map[sd->bl.m].flag.noteleport) // テレポ禁止
return 0;
pc_setpos (sd, sd->status.save_point.map,
sd->status.save_point.x, sd->status.save_point.y, 3);
}
else
pc_setpos (sd, str, x, y, 0);
}
mapreg_setreg (add_str ("$@warpwaitingpcnum"), n);
return 0;
}
/*==========================================
* RIDのアタッチ
*------------------------------------------
*/
int buildin_attachrid (struct script_state *st)
{
st->rid = conv_num (st, &(st->stack->stack_data[st->start + 2]));
push_val (st->stack, C_INT, (map_id2sd (st->rid) != NULL));
return 0;
}
/*==========================================
* RIDのデタッチ
*------------------------------------------
*/
int buildin_detachrid (struct script_state *st)
{
st->rid = 0;
return 0;
}
/*==========================================
* 存在チェック
*------------------------------------------
*/
int buildin_isloggedin (struct script_state *st)
{
push_val (st->stack, C_INT,
map_id2sd (conv_num
(st,
&(st->stack->stack_data[st->start + 2]))) != NULL);
return 0;
}
/*==========================================
*
*------------------------------------------
*/
enum
{ MF_NOMEMO, MF_NOTELEPORT, MF_NOSAVE, MF_NOBRANCH, MF_NOPENALTY,
MF_NOZENYPENALTY, MF_PVP, MF_PVP_NOPARTY, MF_PVP_NOGUILD, MF_GVG,
MF_GVG_NOPARTY, MF_NOTRADE, MF_NOSKILL, MF_NOWARP, MF_NOPVP,
MF_NOICEWALL,
MF_SNOW, MF_FOG, MF_SAKURA, MF_LEAVES, MF_RAIN
};
int buildin_setmapflagnosave (struct script_state *st)
{
int m, x, y;
char *str, *str2;
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
str2 = conv_str (st, &(st->stack->stack_data[st->start + 3]));
x = conv_num (st, &(st->stack->stack_data[st->start + 4]));
y = conv_num (st, &(st->stack->stack_data[st->start + 5]));
m = map_mapname2mapid (str);
if (m >= 0)
{
map[m].flag.nosave = 1;
memcpy (map[m].save.map, str2, 16);
map[m].save.x = x;
map[m].save.y = y;
}
return 0;
}
int buildin_setmapflag (struct script_state *st)
{
int m, i;
char *str;
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
i = conv_num (st, &(st->stack->stack_data[st->start + 3]));
m = map_mapname2mapid (str);
if (m >= 0)
{
switch (i)
{
case MF_NOMEMO:
map[m].flag.nomemo = 1;
break;
case MF_NOTELEPORT:
map[m].flag.noteleport = 1;
break;
case MF_NOBRANCH:
map[m].flag.nobranch = 1;
break;
case MF_NOPENALTY:
map[m].flag.nopenalty = 1;
break;
case MF_PVP_NOPARTY:
map[m].flag.pvp_noparty = 1;
break;
case MF_PVP_NOGUILD:
map[m].flag.pvp_noguild = 1;
break;
case MF_GVG_NOPARTY:
map[m].flag.gvg_noparty = 1;
break;
case MF_NOZENYPENALTY:
map[m].flag.nozenypenalty = 1;
break;
case MF_NOTRADE:
map[m].flag.notrade = 1;
break;
case MF_NOSKILL:
map[m].flag.noskill = 1;
break;
case MF_NOWARP:
map[m].flag.nowarp = 1;
break;
case MF_NOPVP:
map[m].flag.nopvp = 1;
break;
case MF_NOICEWALL: // [Valaris]
map[m].flag.noicewall = 1;
break;
case MF_SNOW: // [Valaris]
map[m].flag.snow = 1;
break;
case MF_FOG: // [Valaris]
map[m].flag.fog = 1;
break;
case MF_SAKURA: // [Valaris]
map[m].flag.sakura = 1;
break;
case MF_LEAVES: // [Valaris]
map[m].flag.leaves = 1;
break;
case MF_RAIN: // [Valaris]
map[m].flag.rain = 1;
break;
}
}
return 0;
}
int buildin_removemapflag (struct script_state *st)
{
int m, i;
char *str;
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
i = conv_num (st, &(st->stack->stack_data[st->start + 3]));
m = map_mapname2mapid (str);
if (m >= 0)
{
switch (i)
{
case MF_NOMEMO:
map[m].flag.nomemo = 0;
break;
case MF_NOTELEPORT:
map[m].flag.noteleport = 0;
break;
case MF_NOSAVE:
map[m].flag.nosave = 0;
break;
case MF_NOBRANCH:
map[m].flag.nobranch = 0;
break;
case MF_NOPENALTY:
map[m].flag.nopenalty = 0;
break;
case MF_PVP_NOPARTY:
map[m].flag.pvp_noparty = 0;
break;
case MF_PVP_NOGUILD:
map[m].flag.pvp_noguild = 0;
break;
case MF_GVG_NOPARTY:
map[m].flag.gvg_noparty = 0;
break;
case MF_NOZENYPENALTY:
map[m].flag.nozenypenalty = 0;
break;
case MF_NOSKILL:
map[m].flag.noskill = 0;
break;
case MF_NOWARP:
map[m].flag.nowarp = 0;
break;
case MF_NOPVP:
map[m].flag.nopvp = 0;
break;
case MF_NOICEWALL: // [Valaris]
map[m].flag.noicewall = 0;
break;
case MF_SNOW: // [Valaris]
map[m].flag.snow = 0;
break;
case MF_FOG: // [Valaris]
map[m].flag.fog = 0;
break;
case MF_SAKURA: // [Valaris]
map[m].flag.sakura = 0;
break;
case MF_LEAVES: // [Valaris]
map[m].flag.leaves = 0;
break;
case MF_RAIN: // [Valaris]
map[m].flag.rain = 0;
break;
}
}
return 0;
}
int buildin_pvpon (struct script_state *st)
{
int m, i;
char *str;
struct map_session_data *pl_sd = NULL;
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
m = map_mapname2mapid (str);
if (m >= 0 && !map[m].flag.pvp && !map[m].flag.nopvp)
{
map[m].flag.pvp = 1;
clif_send0199 (m, 1);
if (battle_config.pk_mode) // disable ranking functions if pk_mode is on [Valaris]
return 0;
for (i = 0; i < fd_max; i++)
{ //人数分ループ
if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
&& pl_sd->state.auth)
{
if (m == pl_sd->bl.m && pl_sd->pvp_timer == -1)
{
pl_sd->pvp_timer =
add_timer (gettick () + 200, pc_calc_pvprank_timer,
pl_sd->bl.id, 0);
pl_sd->pvp_rank = 0;
pl_sd->pvp_lastusers = 0;
pl_sd->pvp_point = 5;
}
}
}
}
return 0;
}
int buildin_pvpoff (struct script_state *st)
{
int m, i;
char *str;
struct map_session_data *pl_sd = NULL;
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
m = map_mapname2mapid (str);
if (m >= 0 && map[m].flag.pvp && map[m].flag.nopvp)
{
map[m].flag.pvp = 0;
clif_send0199 (m, 0);
if (battle_config.pk_mode) // disable ranking options if pk_mode is on [Valaris]
return 0;
for (i = 0; i < fd_max; i++)
{ //人数分ループ
if (session[i] && (pl_sd = (struct map_session_data *)session[i]->session_data)
&& pl_sd->state.auth)
{
if (m == pl_sd->bl.m)
{
clif_pvpset (pl_sd, 0, 0, 2);
if (pl_sd->pvp_timer != -1)
{
delete_timer (pl_sd->pvp_timer,
pc_calc_pvprank_timer);
pl_sd->pvp_timer = -1;
}
}
}
}
}
return 0;
}
int buildin_gvgon (struct script_state *st)
{
int m;
char *str;
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
m = map_mapname2mapid (str);
if (m >= 0 && !map[m].flag.gvg)
{
map[m].flag.gvg = 1;
clif_send0199 (m, 3);
}
return 0;
}
int buildin_gvgoff (struct script_state *st)
{
int m;
char *str;
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
m = map_mapname2mapid (str);
if (m >= 0 && map[m].flag.gvg)
{
map[m].flag.gvg = 0;
clif_send0199 (m, 0);
}
return 0;
}
/*==========================================
* NPCエモーション
*------------------------------------------
*/
int buildin_emotion (struct script_state *st)
{
int type;
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
if (type < 0 || type > 100)
return 0;
clif_emotion (map_id2bl (st->oid), type);
return 0;
}
int buildin_maprespawnguildid_sub (struct block_list *bl, va_list ap)
{
int g_id = va_arg (ap, int);
int flag = va_arg (ap, int);
struct map_session_data *sd = NULL;
struct mob_data *md = NULL;
if (bl->type == BL_PC)
sd = (struct map_session_data *) bl;
if (bl->type == BL_MOB)
md = (struct mob_data *) bl;
if (sd)
{
if ((sd->status.guild_id == g_id) && (flag & 1))
pc_setpos (sd, sd->status.save_point.map, sd->status.save_point.x,
sd->status.save_point.y, 3);
else if ((sd->status.guild_id != g_id) && (flag & 2))
pc_setpos (sd, sd->status.save_point.map, sd->status.save_point.x,
sd->status.save_point.y, 3);
else if (sd->status.guild_id == 0) // Warp out players not in guild [Valaris]
pc_setpos (sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, 3); // end addition [Valaris]
}
if (md && flag & 4)
{
if (md->mob_class < 1285 || md->mob_class > 1288)
mob_delete (md);
}
return 0;
}
int buildin_maprespawnguildid (struct script_state *st)
{
char *mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
int g_id = conv_num (st, &(st->stack->stack_data[st->start + 3]));
int flag = conv_num (st, &(st->stack->stack_data[st->start + 4]));
int m = map_mapname2mapid (mapname);
if (m)
map_foreachinarea (buildin_maprespawnguildid_sub, m, 0, 0,
map[m].xs - 1, map[m].ys - 1, BL_NUL, g_id, flag);
return 0;
}
int buildin_agitstart (struct script_state *st)
{
if (agit_flag == 1)
return 1; // Agit already Start.
agit_flag = 1;
guild_agit_start ();
return 0;
}
int buildin_agitend (struct script_state *st)
{
if (agit_flag == 0)
return 1; // Agit already End.
agit_flag = 0;
guild_agit_end ();
return 0;
}
/*==========================================
* agitcheck 1; // choice script
* if(@agit_flag == 1) goto agit;
* if(agitcheck(0) == 1) goto agit;
*------------------------------------------
*/
int buildin_agitcheck (struct script_state *st)
{
struct map_session_data *sd;
int cond;
sd = script_rid2sd (st);
cond = conv_num (st, &(st->stack->stack_data[st->start + 2]));
if (cond == 0)
{
if (agit_flag == 1)
push_val (st->stack, C_INT, 1);
if (agit_flag == 0)
push_val (st->stack, C_INT, 0);
}
else
{
if (agit_flag == 1)
pc_setreg (sd, add_str ("@agit_flag"), 1);
if (agit_flag == 0)
pc_setreg (sd, add_str ("@agit_flag"), 0);
}
return 0;
}
int buildin_flagemblem (struct script_state *st)
{
int g_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
if (g_id < 0)
return 0;
// printf("Script.c: [FlagEmblem] GuildID=%d, Emblem=%d.\n", g->guild_id, g->emblem_id);
((struct npc_data *) map_id2bl (st->oid))->u.scr.guild_id = g_id;
return 1;
}
int buildin_getcastlename (struct script_state *st)
{
char *mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
struct guild_castle *gc;
int i;
char *buf = NULL;
for (i = 0; i < MAX_GUILDCASTLE; i++)
{
if ((gc = guild_castle_search (i)) != NULL)
{
if (strcmp (mapname, gc->map_name) == 0)
{
buf = (char *) calloc (24, 1);
strncpy (buf, gc->castle_name, 23);
break;
}
}
}
if (buf)
push_str (st->stack, C_STR, buf);
else
push_str (st->stack, C_CONSTSTR, "");
return 0;
}
int buildin_getcastledata (struct script_state *st)
{
char *mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
int index = conv_num (st, &(st->stack->stack_data[st->start + 3]));
char *event = NULL;
struct guild_castle *gc;
int i, j;
if (st->end > st->start + 4 && index == 0)
{
for (i = 0, j = -1; i < MAX_GUILDCASTLE; i++)
if ((gc = guild_castle_search (i)) != NULL &&
strcmp (mapname, gc->map_name) == 0)
j = i;
if (j >= 0)
{
event = conv_str (st, &(st->stack->stack_data[st->start + 4]));
guild_addcastleinfoevent (j, 17, event);
}
}
for (i = 0; i < MAX_GUILDCASTLE; i++)
{
if ((gc = guild_castle_search (i)) != NULL)
{
if (strcmp (mapname, gc->map_name) == 0)
{
switch (index)
{
case 0:
for (j = 1; j < 26; j++)
guild_castledataload (gc->castle_id, j);
break; // Initialize[AgitInit]
case 1:
push_val (st->stack, C_INT, gc->guild_id);
break;
case 2:
push_val (st->stack, C_INT, gc->economy);
break;
case 3:
push_val (st->stack, C_INT, gc->defense);
break;
case 4:
push_val (st->stack, C_INT, gc->triggerE);
break;
case 5:
push_val (st->stack, C_INT, gc->triggerD);
break;
case 6:
push_val (st->stack, C_INT, gc->nextTime);
break;
case 7:
push_val (st->stack, C_INT, gc->payTime);
break;
case 8:
push_val (st->stack, C_INT, gc->createTime);
break;
case 9:
push_val (st->stack, C_INT, gc->visibleC);
break;
case 10:
push_val (st->stack, C_INT, gc->visibleG0);
break;
case 11:
push_val (st->stack, C_INT, gc->visibleG1);
break;
case 12:
push_val (st->stack, C_INT, gc->visibleG2);
break;
case 13:
push_val (st->stack, C_INT, gc->visibleG3);
break;
case 14:
push_val (st->stack, C_INT, gc->visibleG4);
break;
case 15:
push_val (st->stack, C_INT, gc->visibleG5);
break;
case 16:
push_val (st->stack, C_INT, gc->visibleG6);
break;
case 17:
push_val (st->stack, C_INT, gc->visibleG7);
break;
case 18:
push_val (st->stack, C_INT, gc->Ghp0);
break;
case 19:
push_val (st->stack, C_INT, gc->Ghp1);
break;
case 20:
push_val (st->stack, C_INT, gc->Ghp2);
break;
case 21:
push_val (st->stack, C_INT, gc->Ghp3);
break;
case 22:
push_val (st->stack, C_INT, gc->Ghp4);
break;
case 23:
push_val (st->stack, C_INT, gc->Ghp5);
break;
case 24:
push_val (st->stack, C_INT, gc->Ghp6);
break;
case 25:
push_val (st->stack, C_INT, gc->Ghp7);
break;
default:
push_val (st->stack, C_INT, 0);
break;
}
return 0;
}
}
}
push_val (st->stack, C_INT, 0);
return 0;
}
int buildin_setcastledata (struct script_state *st)
{
char *mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
int index = conv_num (st, &(st->stack->stack_data[st->start + 3]));
int value = conv_num (st, &(st->stack->stack_data[st->start + 4]));
struct guild_castle *gc;
int i;
for (i = 0; i < MAX_GUILDCASTLE; i++)
{
if ((gc = guild_castle_search (i)) != NULL)
{
if (strcmp (mapname, gc->map_name) == 0)
{
// Save Data byself First
switch (index)
{
case 1:
gc->guild_id = value;
break;
case 2:
gc->economy = value;
break;
case 3:
gc->defense = value;
break;
case 4:
gc->triggerE = value;
break;
case 5:
gc->triggerD = value;
break;
case 6:
gc->nextTime = value;
break;
case 7:
gc->payTime = value;
break;
case 8:
gc->createTime = value;
break;
case 9:
gc->visibleC = value;
break;
case 10:
gc->visibleG0 = value;
break;
case 11:
gc->visibleG1 = value;
break;
case 12:
gc->visibleG2 = value;
break;
case 13:
gc->visibleG3 = value;
break;
case 14:
gc->visibleG4 = value;
break;
case 15:
gc->visibleG5 = value;
break;
case 16:
gc->visibleG6 = value;
break;
case 17:
gc->visibleG7 = value;
break;
case 18:
gc->Ghp0 = value;
break;
case 19:
gc->Ghp1 = value;
break;
case 20:
gc->Ghp2 = value;
break;
case 21:
gc->Ghp3 = value;
break;
case 22:
gc->Ghp4 = value;
break;
case 23:
gc->Ghp5 = value;
break;
case 24:
gc->Ghp6 = value;
break;
case 25:
gc->Ghp7 = value;
break;
default:
return 0;
}
guild_castledatasave (gc->castle_id, index, value);
return 0;
}
}
}
return 0;
}
/* =====================================================================
* ギルド情報を要求する
* ---------------------------------------------------------------------
*/
int buildin_requestguildinfo (struct script_state *st)
{
int guild_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
char *event = NULL;
if (st->end > st->start + 3)
event = conv_str (st, &(st->stack->stack_data[st->start + 3]));
if (guild_id > 0)
guild_npc_request_info (guild_id, event);
return 0;
}
/* =====================================================================
* カードの数を得る
* ---------------------------------------------------------------------
*/
int buildin_getequipcardcnt (struct script_state *st)
{
int i, num;
struct map_session_data *sd;
int c = 4;
num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
sd = script_rid2sd (st);
i = pc_checkequip (sd, equip[num - 1]);
if (sd->status.inventory[i].card[0] == 0x00ff)
{ // 製造武器はカードなし
push_val (st->stack, C_INT, 0);
return 0;
}
do
{
if ((sd->status.inventory[i].card[c - 1] > 4000) &&
(sd->status.inventory[i].card[c - 1] < 5000))
{
push_val (st->stack, C_INT, (c));
return 0;
}
}
while (c--);
push_val (st->stack, C_INT, 0);
return 0;
}
/* ================================================================
* カード取り外し成功
* ----------------------------------------------------------------
*/
int buildin_successremovecards (struct script_state *st)
{
int i, num, cardflag = 0, flag;
struct map_session_data *sd;
struct item item_tmp;
int c = 4;
num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
sd = script_rid2sd (st);
i = pc_checkequip (sd, equip[num - 1]);
if (sd->status.inventory[i].card[0] == 0x00ff)
{ // 製造武器は処理しない
return 0;
}
do
{
if ((sd->status.inventory[i].card[c - 1] > 4000) &&
(sd->status.inventory[i].card[c - 1] < 5000))
{
cardflag = 1;
item_tmp.id = 0, item_tmp.nameid =
sd->status.inventory[i].card[c - 1];
item_tmp.equip = 0, item_tmp.identify = 1, item_tmp.refine = 0;
item_tmp.attribute = 0;
item_tmp.card[0] = 0, item_tmp.card[1] = 0, item_tmp.card[2] =
0, item_tmp.card[3] = 0;
if ((flag = pc_additem (sd, &item_tmp, 1)))
{ // 持てないならドロップ
clif_additem (sd, 0, 0, flag);
map_addflooritem (&item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y,
NULL, NULL, NULL, 0);
}
}
}
while (c--);
if (cardflag == 1)
{ // カードを取り除いたアイテム所得
flag = 0;
item_tmp.id = 0, item_tmp.nameid = sd->status.inventory[i].nameid;
item_tmp.equip = 0, item_tmp.identify = 1, item_tmp.refine =
sd->status.inventory[i].refine;
item_tmp.attribute = sd->status.inventory[i].attribute;
item_tmp.card[0] = 0, item_tmp.card[1] = 0, item_tmp.card[2] =
0, item_tmp.card[3] = 0;
pc_delitem (sd, i, 1, 0);
if ((flag = pc_additem (sd, &item_tmp, 1)))
{ // もてないならドロップ
clif_additem (sd, 0, 0, flag);
map_addflooritem (&item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y,
NULL, NULL, NULL, 0);
}
clif_misceffect (&sd->bl, 3);
return 0;
}
return 0;
}
/* ================================================================
* カード取り外し失敗 slot,type
* type=0: 両方損失、1:カード損失、2:武具損失、3:損失無し
* ----------------------------------------------------------------
*/
int buildin_failedremovecards (struct script_state *st)
{
int i, num, cardflag = 0, flag, typefail;
struct map_session_data *sd;
struct item item_tmp;
int c = 4;
num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
typefail = conv_num (st, &(st->stack->stack_data[st->start + 3]));
sd = script_rid2sd (st);
i = pc_checkequip (sd, equip[num - 1]);
if (sd->status.inventory[i].card[0] == 0x00ff)
{ // 製造武器は処理しない
return 0;
}
do
{
if ((sd->status.inventory[i].card[c - 1] > 4000) &&
(sd->status.inventory[i].card[c - 1] < 5000))
{
cardflag = 1;
if (typefail == 2)
{ // 武具のみ損失なら、カードは受け取らせる
item_tmp.id = 0, item_tmp.nameid =
sd->status.inventory[i].card[c - 1];
item_tmp.equip = 0, item_tmp.identify = 1, item_tmp.refine =
0;
item_tmp.attribute = 0;
item_tmp.card[0] = 0, item_tmp.card[1] = 0, item_tmp.card[2] =
0, item_tmp.card[3] = 0;
if ((flag = pc_additem (sd, &item_tmp, 1)))
{
clif_additem (sd, 0, 0, flag);
map_addflooritem (&item_tmp, 1, sd->bl.m, sd->bl.x,
sd->bl.y, NULL, NULL, NULL, 0);
}
}
}
}
while (c--);
if (cardflag == 1)
{
if (typefail == 0 || typefail == 2)
{ // 武具損失
pc_delitem (sd, i, 1, 0);
clif_misceffect (&sd->bl, 2);
return 0;
}
if (typefail == 1)
{ // カードのみ損失(武具を返す)
flag = 0;
item_tmp.id = 0, item_tmp.nameid = sd->status.inventory[i].nameid;
item_tmp.equip = 0, item_tmp.identify = 1, item_tmp.refine =
sd->status.inventory[i].refine;
item_tmp.attribute = sd->status.inventory[i].attribute;
item_tmp.card[0] = 0, item_tmp.card[1] = 0, item_tmp.card[2] =
0, item_tmp.card[3] = 0;
pc_delitem (sd, i, 1, 0);
if ((flag = pc_additem (sd, &item_tmp, 1)))
{
clif_additem (sd, 0, 0, flag);
map_addflooritem (&item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y,
NULL, NULL, NULL, 0);
}
}
clif_misceffect (&sd->bl, 2);
return 0;
}
return 0;
}
int buildin_mapwarp (struct script_state *st) // Added by RoVeRT
{
int x, y, m;
char *str;
char *mapname;
int x0, y0, x1, y1;
mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
x0 = 0;
y0 = 0;
x1 = map[map_mapname2mapid (mapname)].xs;
y1 = map[map_mapname2mapid (mapname)].ys;
str = conv_str (st, &(st->stack->stack_data[st->start + 3]));
x = conv_num (st, &(st->stack->stack_data[st->start + 4]));
y = conv_num (st, &(st->stack->stack_data[st->start + 5]));
if ((m = map_mapname2mapid (mapname)) < 0)
return 0;
map_foreachinarea (buildin_areawarp_sub,
m, x0, y0, x1, y1, BL_PC, str, x, y);
return 0;
}
int buildin_cmdothernpc (struct script_state *st) // Added by RoVeRT
{
char *npc, *command;
npc = conv_str (st, &(st->stack->stack_data[st->start + 2]));
command = conv_str (st, &(st->stack->stack_data[st->start + 3]));
npc_command (map_id2sd (st->rid), npc, command);
return 0;
}
int buildin_inittimer (struct script_state *st) // Added by RoVeRT
{
// struct npc_data *nd=(struct npc_data*)map_id2bl(st->oid);
// nd->lastaction=nd->timer=gettick();
npc_do_ontimer (st->oid, map_id2sd (st->rid), 1);
return 0;
}
int buildin_stoptimer (struct script_state *st) // Added by RoVeRT
{
// struct npc_data *nd=(struct npc_data*)map_id2bl(st->oid);
// nd->lastaction=nd->timer=-1;
npc_do_ontimer (st->oid, map_id2sd (st->rid), 0);
return 0;
}
int buildin_mobcount_sub (struct block_list *bl, va_list ap) // Added by RoVeRT
{
char *event = va_arg (ap, char *);
int *c = va_arg (ap, int *);
if (strcmp (event, ((struct mob_data *) bl)->npc_event) == 0)
(*c)++;
return 0;
}
int buildin_mobcount (struct script_state *st) // Added by RoVeRT
{
char *mapname, *event;
int m, c = 0;
mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
event = conv_str (st, &(st->stack->stack_data[st->start + 3]));
if ((m = map_mapname2mapid (mapname)) < 0)
{
push_val (st->stack, C_INT, -1);
return 0;
}
map_foreachinarea (buildin_mobcount_sub,
m, 0, 0, map[m].xs, map[m].ys, BL_MOB, event, &c);
push_val (st->stack, C_INT, (c - 1));
return 0;
}
int buildin_marriage (struct script_state *st)
{
char *partner = conv_str (st, &(st->stack->stack_data[st->start + 2]));
struct map_session_data *sd = script_rid2sd (st);
struct map_session_data *p_sd = map_nick2sd (partner);
if (sd == NULL || p_sd == NULL || pc_marriage (sd, p_sd) < 0)
{
push_val (st->stack, C_INT, 0);
return 0;
}
push_val (st->stack, C_INT, 1);
return 0;
}
int buildin_wedding_effect (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
if (sd == NULL)
return 0;
clif_wedding_effect (&sd->bl);
return 0;
}
int buildin_divorce (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
st->state = STOP; // rely on pc_divorce to restart
sd->npc_flags.divorce = 1;
if (sd == NULL || pc_divorce (sd) < 0)
{
push_val (st->stack, C_INT, 0);
return 0;
}
push_val (st->stack, C_INT, 1);
return 0;
}
/*================================================
* Script for Displaying MOB Information [Valaris]
*------------------------------------------------
*/
int buildin_strmobinfo (struct script_state *st)
{
int num = conv_num (st, &(st->stack->stack_data[st->start + 2]));
int mob_class = conv_num (st, &(st->stack->stack_data[st->start + 3]));
if (num <= 0 || num >= 8 || (mob_class >= 0 && mob_class <= 1000) || mob_class > 2000)
return 0;
if (num == 1)
{
char *buf;
buf = mob_db[mob_class].name;
push_str (st->stack, C_STR, buf);
return 0;
}
else if (num == 2)
{
char *buf;
buf = mob_db[mob_class].jname;
push_str (st->stack, C_STR, buf);
return 0;
}
else if (num == 3)
push_val (st->stack, C_INT, mob_db[mob_class].lv);
else if (num == 4)
push_val (st->stack, C_INT, mob_db[mob_class].max_hp);
else if (num == 5)
push_val (st->stack, C_INT, mob_db[mob_class].max_sp);
else if (num == 6)
push_val (st->stack, C_INT, mob_db[mob_class].base_exp);
else if (num == 7)
push_val (st->stack, C_INT, mob_db[mob_class].job_exp);
return 0;
}
/*==========================================
* Summon guardians [Valaris]
*------------------------------------------
*/
int buildin_guardian (struct script_state *st)
{
int mob_class = 0, amount = 1, x = 0, y = 0, guardian = 0;
char *str, *map, *event = "";
map = conv_str (st, &(st->stack->stack_data[st->start + 2]));
x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
str = conv_str (st, &(st->stack->stack_data[st->start + 5]));
mob_class = conv_num (st, &(st->stack->stack_data[st->start + 6]));
amount = conv_num (st, &(st->stack->stack_data[st->start + 7]));
event = conv_str (st, &(st->stack->stack_data[st->start + 8]));
if (st->end > st->start + 9)
guardian = conv_num (st, &(st->stack->stack_data[st->start + 9]));
mob_spawn_guardian (map_id2sd (st->rid), map, x, y, str, mob_class, amount,
event, guardian);
return 0;
}
/*================================================
* Script for Displaying Guardian Info [Valaris]
*------------------------------------------------
*/
int buildin_guardianinfo (struct script_state *st)
{
int guardian = conv_num (st, &(st->stack->stack_data[st->start + 2]));
struct map_session_data *sd = script_rid2sd (st);
struct guild_castle *gc = guild_mapname2gc (map[sd->bl.m].name);
if (guardian == 0 && gc->visibleG0 == 1)
push_val (st->stack, C_INT, gc->Ghp0);
if (guardian == 1 && gc->visibleG1 == 1)
push_val (st->stack, C_INT, gc->Ghp1);
if (guardian == 2 && gc->visibleG2 == 1)
push_val (st->stack, C_INT, gc->Ghp2);
if (guardian == 3 && gc->visibleG3 == 1)
push_val (st->stack, C_INT, gc->Ghp3);
if (guardian == 4 && gc->visibleG4 == 1)
push_val (st->stack, C_INT, gc->Ghp4);
if (guardian == 5 && gc->visibleG5 == 1)
push_val (st->stack, C_INT, gc->Ghp5);
if (guardian == 6 && gc->visibleG6 == 1)
push_val (st->stack, C_INT, gc->Ghp6);
if (guardian == 7 && gc->visibleG7 == 1)
push_val (st->stack, C_INT, gc->Ghp7);
else
push_val (st->stack, C_INT, -1);
return 0;
}
/*==========================================
* IDからItem名
*------------------------------------------
*/
int buildin_getitemname (struct script_state *st)
{
struct item_data *i_data;
char *item_name;
struct script_data *data;
data = &(st->stack->stack_data[st->start + 2]);
get_val (st, data);
if (data->type == C_STR || data->type == C_CONSTSTR)
{
const char *name = conv_str (st, data);
i_data = itemdb_searchname (name);
}
else
{
int item_id = conv_num (st, data);
i_data = itemdb_search (item_id);
}
item_name = (char *) calloc (24, 1);
if (i_data)
strncpy (item_name, i_data->jname, 23);
else
strncpy (item_name, "Unknown Item", 23);
push_str (st->stack, C_STR, item_name);
return 0;
}
int buildin_getspellinvocation (struct script_state *st)
{
char *name;
char *invocation;
name = conv_str (st, &(st->stack->stack_data[st->start + 2]));
invocation = magic_find_invocation (name);
if (!invocation)
invocation = "...";
push_str (st->stack, C_STR, strdup (invocation));
return 0;
}
int buildin_getanchorinvocation (struct script_state *st)
{
char *name;
char *invocation;
name = conv_str (st, &(st->stack->stack_data[st->start + 2]));
invocation = magic_find_anchor_invocation (name);
if (!invocation)
invocation = "...";
push_str (st->stack, C_STR, strdup (invocation));
return 0;
}
int buildin_getpartnerid (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
push_val (st->stack, C_INT, sd->status.partner_id);
return 0;
}
/*==========================================
* PCの所持品情報読み取り
*------------------------------------------
*/
int buildin_getinventorylist (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
int i, j = 0;
if (!sd)
return 0;
for (i = 0; i < MAX_INVENTORY; i++)
{
if (sd->status.inventory[i].nameid > 0
&& sd->status.inventory[i].amount > 0)
{
pc_setreg (sd, add_str ("@inventorylist_id") + (j << 24),
sd->status.inventory[i].nameid);
pc_setreg (sd, add_str ("@inventorylist_amount") + (j << 24),
sd->status.inventory[i].amount);
pc_setreg (sd, add_str ("@inventorylist_equip") + (j << 24),
sd->status.inventory[i].equip);
pc_setreg (sd, add_str ("@inventorylist_refine") + (j << 24),
sd->status.inventory[i].refine);
pc_setreg (sd, add_str ("@inventorylist_identify") + (j << 24),
sd->status.inventory[i].identify);
pc_setreg (sd, add_str ("@inventorylist_attribute") + (j << 24),
sd->status.inventory[i].attribute);
pc_setreg (sd, add_str ("@inventorylist_card1") + (j << 24),
sd->status.inventory[i].card[0]);
pc_setreg (sd, add_str ("@inventorylist_card2") + (j << 24),
sd->status.inventory[i].card[1]);
pc_setreg (sd, add_str ("@inventorylist_card3") + (j << 24),
sd->status.inventory[i].card[2]);
pc_setreg (sd, add_str ("@inventorylist_card4") + (j << 24),
sd->status.inventory[i].card[3]);
j++;
}
}
pc_setreg (sd, add_str ("@inventorylist_count"), j);
return 0;
}
int buildin_getskilllist (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
int i, j = 0;
if (!sd)
return 0;
for (i = 0; i < MAX_SKILL; i++)
{
if (sd->status.skill[i].id > 0 && sd->status.skill[i].lv > 0)
{
pc_setreg (sd, add_str ("@skilllist_id") + (j << 24),
sd->status.skill[i].id);
pc_setreg (sd, add_str ("@skilllist_lv") + (j << 24),
sd->status.skill[i].lv);
pc_setreg (sd, add_str ("@skilllist_flag") + (j << 24),
sd->status.skill[i].flags);
j++;
}
}
pc_setreg (sd, add_str ("@skilllist_count"), j);
return 0;
}
int buildin_get_activated_pool_skills (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
int pool_skills[MAX_SKILL_POOL];
int skill_pool_size = skill_pool (sd, pool_skills);
int i, count = 0;
if (!sd)
return 0;
for (i = 0; i < skill_pool_size; i++)
{
int skill_id = pool_skills[i];
if (sd->status.skill[skill_id].id == skill_id)
{
pc_setreg (sd, add_str ("@skilllist_id") + (count << 24),
sd->status.skill[skill_id].id);
pc_setreg (sd, add_str ("@skilllist_lv") + (count << 24),
sd->status.skill[skill_id].lv);
pc_setreg (sd, add_str ("@skilllist_flag") + (count << 24),
sd->status.skill[skill_id].flags);
pc_setregstr (sd, add_str ("@skilllist_name$") + (count << 24),
skill_name (skill_id));
++count;
}
}
pc_setreg (sd, add_str ("@skilllist_count"), count);
return 0;
}
extern int skill_pool_skills[];
extern int skill_pool_skills_size;
int buildin_get_unactivated_pool_skills (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
int i, count = 0;
if (!sd)
return 0;
for (i = 0; i < skill_pool_skills_size; i++)
{
int skill_id = skill_pool_skills[i];
if (sd->status.skill[skill_id].id == skill_id && !(sd->status.skill[skill_id].flags & SKILL_POOL_ACTIVATED))
{
pc_setreg (sd, add_str ("@skilllist_id") + (count << 24),
sd->status.skill[skill_id].id);
pc_setreg (sd, add_str ("@skilllist_lv") + (count << 24),
sd->status.skill[skill_id].lv);
pc_setreg (sd, add_str ("@skilllist_flag") + (count << 24),
sd->status.skill[skill_id].flags);
pc_setregstr (sd, add_str ("@skilllist_name$") + (count << 24),
skill_name (skill_id));
++count;
}
}
pc_setreg (sd, add_str ("@skilllist_count"), count);
return 0;
}
int buildin_get_pool_skills (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
int i, count = 0;
if (!sd)
return 0;
for (i = 0; i < skill_pool_skills_size; i++)
{
int skill_id = skill_pool_skills[i];
if (sd->status.skill[skill_id].id == skill_id)
{
pc_setreg (sd, add_str ("@skilllist_id") + (count << 24),
sd->status.skill[skill_id].id);
pc_setreg (sd, add_str ("@skilllist_lv") + (count << 24),
sd->status.skill[skill_id].lv);
pc_setreg (sd, add_str ("@skilllist_flag") + (count << 24),
sd->status.skill[skill_id].flags);
pc_setregstr (sd, add_str ("@skilllist_name$") + (count << 24),
skill_name (skill_id));
++count;
}
}
pc_setreg (sd, add_str ("@skilllist_count"), count);
return 0;
}
int buildin_activate_pool_skill (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
int skill_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
skill_pool_activate (sd, skill_id);
clif_skillinfoblock (sd);
return 0;
}
int buildin_deactivate_pool_skill (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
int skill_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
skill_pool_deactivate (sd, skill_id);
clif_skillinfoblock (sd);
return 0;
}
int buildin_check_pool_skill (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
int skill_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
push_val (st->stack, C_INT, skill_pool_is_activated (sd, skill_id));
return 0;
}
int buildin_clearitem (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
int i;
if (sd == NULL)
return 0;
for (i = 0; i < MAX_INVENTORY; i++)
{
if (sd->status.inventory[i].amount)
pc_delitem (sd, i, sd->status.inventory[i].amount, 0);
}
return 0;
}
/*==========================================
* NPCクラスチェンジ
* classは変わりたいclass
* typeは通常0なのかな?
*------------------------------------------
*/
int buildin_classchange (struct script_state *st)
{
int npc_class, type;
struct block_list *bl = map_id2bl (st->oid);
if (bl == NULL)
return 0;
npc_class = conv_num (st, &(st->stack->stack_data[st->start + 2]));
type = conv_num (st, &(st->stack->stack_data[st->start + 3]));
clif_npc_class_change (bl, npc_class, type);
return 0;
}
/*==========================================
* NPCから発生するエフェクト
* misceffect(effect, [target])
*
* effect The effect type/ID.
* target The player name or being ID on
* which to display the effect. If not
* specified, it attempts to default to
* the current NPC or invoking PC.
*------------------------------------------
*/
int buildin_misceffect (struct script_state *st)
{
int type;
int id = 0;
char *name = NULL;
struct block_list *bl = NULL;
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
if (st->end > st->start + 3)
{
struct script_data *sdata = &(st->stack->stack_data[st->start + 3]);
get_val (st, sdata);
if (sdata->type == C_STR || sdata->type == C_CONSTSTR)
name = conv_str (st, sdata);
else
id = conv_num (st, sdata);
}
if (name)
{
struct map_session_data *sd = map_nick2sd (name);
if (sd)
bl = &sd->bl;
}
else if (id)
bl = map_id2bl (id);
else if (st->oid)
bl = map_id2bl (st->oid);
else
{
struct map_session_data *sd = script_rid2sd (st);
if (sd)
bl = &sd->bl;
}
if (bl)
clif_misceffect (bl, type);
return 0;
}
/*==========================================
* サウンドエフェクト
*------------------------------------------
*/
int buildin_soundeffect (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
char *name;
int type = 0;
name = conv_str (st, &(st->stack->stack_data[st->start + 2]));
type = conv_num (st, &(st->stack->stack_data[st->start + 3]));
if (sd)
{
if (st->oid)
clif_soundeffect (sd, map_id2bl (st->oid), name, type);
else
{
clif_soundeffect (sd, &sd->bl, name, type);
}
}
return 0;
}
/*==========================================
* NPC skill effects [Valaris]
*------------------------------------------
*/
int buildin_npcskilleffect (struct script_state *st)
{
struct npc_data *nd = (struct npc_data *) map_id2bl (st->oid);
int skillid = conv_num (st, &(st->stack->stack_data[st->start + 2]));
int skilllv = conv_num (st, &(st->stack->stack_data[st->start + 3]));
int x = conv_num (st, &(st->stack->stack_data[st->start + 4]));
int y = conv_num (st, &(st->stack->stack_data[st->start + 5]));
clif_skill_poseffect (&nd->bl, skillid, skilllv, x, y, gettick ());
return 0;
}
/*==========================================
* Special effects [Valaris]
*------------------------------------------
*/
int buildin_specialeffect (struct script_state *st)
{
struct block_list *bl = map_id2bl (st->oid);
if (bl == NULL)
return 0;
clif_specialeffect (bl,
conv_num (st,
&(st->stack->stack_data[st->start + 2])),
0);
return 0;
}
int buildin_specialeffect2 (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
if (sd == NULL)
return 0;
clif_specialeffect (&sd->bl,
conv_num (st,
&(st->stack->stack_data[st->start + 2])),
0);
return 0;
}
/*==========================================
* Nude [Valaris]
*------------------------------------------
*/
int buildin_nude (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
int i;
if (sd == NULL)
return 0;
for (i = 0; i < 11; i++)
if (sd->equip_index[i] >= 0)
pc_unequipitem (sd, sd->equip_index[i], i);
pc_calcstatus (sd, 0);
return 0;
}
/*==========================================
* UnequipById [Freeyorp]
*------------------------------------------
*/
int buildin_unequip_by_id (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
if (sd == NULL)
return 0;
int slot_id = conv_num (st, &(st->stack->stack_data[st->start + 2]));
if (slot_id >= 0 && slot_id < 11 && sd->equip_index[slot_id] >= 0)
pc_unequipitem (sd, sd->equip_index[slot_id], slot_id);
pc_calcstatus (sd, 0);
return 0;
}
/*==========================================
* gmcommand [MouseJstr]
*
* suggested on the forums...
*------------------------------------------
*/
int buildin_gmcommand (struct script_state *st)
{
struct map_session_data *sd;
char *cmd;
sd = script_rid2sd (st);
cmd = conv_str (st, &(st->stack->stack_data[st->start + 2]));
is_atcommand (sd->fd, sd, cmd, 99);
return 0;
}
/*==========================================
* movenpc [MouseJstr]
*------------------------------------------
*/
int buildin_movenpc (struct script_state *st)
{
struct map_session_data *sd;
char *map, *npc;
int x, y;
sd = script_rid2sd (st);
map = conv_str (st, &(st->stack->stack_data[st->start + 2]));
x = conv_num (st, &(st->stack->stack_data[st->start + 3]));
y = conv_num (st, &(st->stack->stack_data[st->start + 4]));
npc = conv_str (st, &(st->stack->stack_data[st->start + 5]));
return 0;
}
/*==========================================
* npcwarp [remoitnane]
* Move NPC to a new position on the same map.
*------------------------------------------
*/
int buildin_npcwarp (struct script_state *st)
{
int x, y;
char *npc;
struct npc_data *nd = NULL;
x = conv_num (st, &(st->stack->stack_data[st->start + 2]));
y = conv_num (st, &(st->stack->stack_data[st->start + 3]));
npc = conv_str (st, &(st->stack->stack_data[st->start + 4]));
nd = npc_name2id (npc);
if (!nd)
return -1;
short m = nd->bl.m;
/* Crude sanity checks. */
if (m < 0 || !nd->bl.prev
|| x < 0 || x > map[m].xs -1
|| y < 0 || y > map[m].ys - 1)
return -1;
npc_enable (npc, 0);
map_delblock(&nd->bl); /* [Freeyorp] */
nd->bl.x = x;
nd->bl.y = y;
map_addblock(&nd->bl);
npc_enable (npc, 1);
return 0;
}
/*==========================================
* message [MouseJstr]
*------------------------------------------
*/
int buildin_message (struct script_state *st)
{
char *msg, *player;
struct map_session_data *pl_sd = NULL;
player = conv_str (st, &(st->stack->stack_data[st->start + 2]));
msg = conv_str (st, &(st->stack->stack_data[st->start + 3]));
if ((pl_sd = map_nick2sd ((char *) player)) == NULL)
return 1;
clif_displaymessage (pl_sd->fd, msg);
return 0;
}
/*==========================================
* npctalk (sends message to surrounding
* area) [Valaris]
*------------------------------------------
*/
int buildin_npctalk (struct script_state *st)
{
char *str;
char message[255];
struct npc_data *nd = (struct npc_data *) map_id2bl (st->oid);
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
if (nd)
{
memcpy (message, nd->name, 24);
strcat (message, " : ");
strcat (message, str);
clif_message (&(nd->bl), message);
}
return 0;
}
/*==========================================
* hasitems (checks to see if player has any
* items on them, if so will return a 1)
* [Valaris]
*------------------------------------------
*/
int buildin_hasitems (struct script_state *st)
{
int i;
struct map_session_data *sd;
sd = script_rid2sd (st);
for (i = 0; i < MAX_INVENTORY; i++)
{
if (sd->status.inventory[i].amount)
{
push_val (st->stack, C_INT, 1);
return 0;
}
}
push_val (st->stack, C_INT, 0);
return 0;
}
/*==========================================
* getlook char info. getlook(arg)
*------------------------------------------
*/
int buildin_getlook (struct script_state *st)
{
int type, val;
struct map_session_data *sd;
sd = script_rid2sd (st);
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
val = -1;
switch (type)
{
case LOOK_HAIR: //1
val = sd->status.hair;
break;
case LOOK_WEAPON: //2
val = sd->status.weapon;
break;
case LOOK_HEAD_BOTTOM: //3
val = sd->status.head_bottom;
break;
case LOOK_HEAD_TOP: //4
val = sd->status.head_top;
break;
case LOOK_HEAD_MID: //5
val = sd->status.head_mid;
break;
case LOOK_HAIR_COLOR: //6
val = sd->status.hair_color;
break;
case LOOK_CLOTHES_COLOR: //7
val = sd->status.clothes_color;
break;
case LOOK_SHIELD: //8
val = sd->status.shield;
break;
case LOOK_SHOES: //9
break;
}
push_val (st->stack, C_INT, val);
return 0;
}
/*==========================================
* get char save point. argument: 0- map name, 1- x, 2- y
*------------------------------------------
*/
int buildin_getsavepoint (struct script_state *st)
{
int x, y, type;
char *mapname;
struct map_session_data *sd;
sd = script_rid2sd (st);
type = conv_num (st, &(st->stack->stack_data[st->start + 2]));
x = sd->status.save_point.x;
y = sd->status.save_point.y;
switch (type)
{
case 0:
mapname = (char*)calloc (24, 1);
strncpy (mapname, sd->status.save_point.map, 23);
push_str (st->stack, C_STR, mapname);
break;
case 1:
push_val (st->stack, C_INT, x);
break;
case 2:
push_val (st->stack, C_INT, y);
break;
}
return 0;
}
/*==========================================
* areatimer
*------------------------------------------
*/
int buildin_areatimer_sub (struct block_list *bl, va_list ap)
{
int tick;
char *event;
tick = va_arg (ap, int);
event = va_arg (ap, char *);
pc_addeventtimer ((struct map_session_data *) bl, tick, event);
return 0;
}
int buildin_areatimer (struct script_state *st)
{
int tick, m;
char *event;
char *mapname;
int x0, y0, x1, y1;
mapname = conv_str (st, &(st->stack->stack_data[st->start + 2]));
x0 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
y0 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
x1 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
y1 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
tick = conv_num (st, &(st->stack->stack_data[st->start + 7]));
event = conv_str (st, &(st->stack->stack_data[st->start + 8]));
if ((m = map_mapname2mapid (mapname)) < 0)
return 0;
map_foreachinarea (buildin_areatimer_sub,
m, x0, y0, x1, y1, BL_PC, tick, event);
return 0;
}
/*==========================================
* Check whether the PC is in the specified rectangle
*------------------------------------------
*/
int buildin_isin (struct script_state *st)
{
int x1, y1, x2, y2;
char *str;
struct map_session_data *sd = script_rid2sd (st);
str = conv_str (st, &(st->stack->stack_data[st->start + 2]));
x1 = conv_num (st, &(st->stack->stack_data[st->start + 3]));
y1 = conv_num (st, &(st->stack->stack_data[st->start + 4]));
x2 = conv_num (st, &(st->stack->stack_data[st->start + 5]));
y2 = conv_num (st, &(st->stack->stack_data[st->start + 6]));
if (!sd)
return 1;
push_val (st->stack, C_INT,
(sd->bl.x >= x1 && sd->bl.x <= x2)
&& (sd->bl.y >= y1 && sd->bl.y <= y2)
&& (!strcmp (str, map[sd->bl.m].name)));
return 0;
}
// Trigger the shop on a (hopefully) nearby shop NPC
int buildin_shop (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
struct npc_data *nd;
if (!sd)
return 1;
nd = npc_name2id (conv_str (st, &(st->stack->stack_data[st->start + 2])));
if (!nd)
return 1;
buildin_close (st);
clif_npcbuysell (sd, nd->bl.id);
return 0;
}
/*==========================================
* Check whether the PC is dead
*------------------------------------------
*/
int buildin_isdead (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
push_val (st->stack, C_INT, pc_isdead (sd));
return 0;
}
/*========================================
* Changes a NPC name, and sprite
*----------------------------------------
*/
int buildin_fakenpcname (struct script_state *st)
{
char *name, *newname;
int newsprite;
struct npc_data *nd;
name = conv_str (st, &(st->stack->stack_data[st->start + 2]));
newname = conv_str (st, &(st->stack->stack_data[st->start + 3]));
newsprite = conv_num (st, &(st->stack->stack_data[st->start + 4]));
nd = npc_name2id (name);
if (!nd)
return 1;
strncpy (nd->name, newname, sizeof(nd->name)-1);
nd->name[sizeof(nd->name)-1] = '\0';
nd->npc_class = newsprite;
// Refresh this npc
npc_enable (name, 0);
npc_enable (name, 1);
return 0;
}
/*============================
* Gets the PC's x pos
*----------------------------
*/
int buildin_getx (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
push_val (st->stack, C_INT, sd->bl.x);
return 0;
}
/*============================
* Gets the PC's y pos
*----------------------------
*/
int buildin_gety (struct script_state *st)
{
struct map_session_data *sd = script_rid2sd (st);
push_val (st->stack, C_INT, sd->bl.y);
return 0;
}
//
// 実行部main
//
/*==========================================
* コマンドの読み取り
*------------------------------------------
*/
static int unget_com_data = -1;
int get_com (unsigned char *script, int *pos)
{
int i, j;
if (unget_com_data >= 0)
{
i = unget_com_data;
unget_com_data = -1;
return i;
}
if (script[*pos] >= 0x80)
{
return C_INT;
}
i = 0;
j = 0;
while (script[*pos] >= 0x40)
{
i = script[(*pos)++] << j;
j += 6;
}
return i + (script[(*pos)++] << j);
}
/*==========================================
* コマンドのプッシュバック
*------------------------------------------
*/
void unget_com (int c)
{
if (unget_com_data != -1)
{
if (battle_config.error_log)
printf ("unget_com can back only 1 data\n");
}
unget_com_data = c;
}
/*==========================================
* 数値の所得
*------------------------------------------
*/
int get_num (unsigned char *script, int *pos)
{
int i, j;
i = 0;
j = 0;
while (script[*pos] >= 0xc0)
{
i += (script[(*pos)++] & 0x7f) << j;
j += 6;
}
return i + ((script[(*pos)++] & 0x7f) << j);
}
/*==========================================
* スタックから値を取り出す
*------------------------------------------
*/
int pop_val (struct script_state *st)
{
if (st->stack->sp <= 0)
return 0;
st->stack->sp--;
get_val (st, &(st->stack->stack_data[st->stack->sp]));
if (st->stack->stack_data[st->stack->sp].type == C_INT)
return st->stack->stack_data[st->stack->sp].u.num;
return 0;
}
#define isstr(c) ((c).type==C_STR || (c).type==C_CONSTSTR)
/*==========================================
* 加算演算子
*------------------------------------------
*/
void op_add (struct script_state *st)
{
st->stack->sp--;
get_val (st, &(st->stack->stack_data[st->stack->sp]));
get_val (st, &(st->stack->stack_data[st->stack->sp - 1]));
if (isstr (st->stack->stack_data[st->stack->sp])
|| isstr (st->stack->stack_data[st->stack->sp - 1]))
{
conv_str (st, &(st->stack->stack_data[st->stack->sp]));
conv_str (st, &(st->stack->stack_data[st->stack->sp - 1]));
}
if (st->stack->stack_data[st->stack->sp].type == C_INT)
{ // ii
st->stack->stack_data[st->stack->sp - 1].u.num +=
st->stack->stack_data[st->stack->sp].u.num;
}
else
{ // ssの予定
char *buf;
buf = (char *)
calloc (strlen (st->stack->stack_data[st->stack->sp - 1].u.str) +
strlen (st->stack->stack_data[st->stack->sp].u.str) + 1,
1);
strcpy (buf, st->stack->stack_data[st->stack->sp - 1].u.str);
strcat (buf, st->stack->stack_data[st->stack->sp].u.str);
if (st->stack->stack_data[st->stack->sp - 1].type == C_STR)
free (st->stack->stack_data[st->stack->sp - 1].u.str);
if (st->stack->stack_data[st->stack->sp].type == C_STR)
free (st->stack->stack_data[st->stack->sp].u.str);
st->stack->stack_data[st->stack->sp - 1].type = C_STR;
st->stack->stack_data[st->stack->sp - 1].u.str = buf;
}
}
/*==========================================
* 二項演算子(文字列)
*------------------------------------------
*/
void op_2str (struct script_state *st, int op, int sp1, int sp2)
{
char *s1 = st->stack->stack_data[sp1].u.str,
*s2 = st->stack->stack_data[sp2].u.str;
int a = 0;
switch (op)
{
case C_EQ:
a = (strcmp (s1, s2) == 0);
break;
case C_NE:
a = (strcmp (s1, s2) != 0);
break;
case C_GT:
a = (strcmp (s1, s2) > 0);
break;
case C_GE:
a = (strcmp (s1, s2) >= 0);
break;
case C_LT:
a = (strcmp (s1, s2) < 0);
break;
case C_LE:
a = (strcmp (s1, s2) <= 0);
break;
default:
printf ("illegal string operater\n");
break;
}
push_val (st->stack, C_INT, a);
if (st->stack->stack_data[sp1].type == C_STR)
free (s1);
if (st->stack->stack_data[sp2].type == C_STR)
free (s2);
}
/*==========================================
* 二項演算子(数値)
*------------------------------------------
*/
void op_2num (struct script_state *st, int op, int i1, int i2)
{
switch (op)
{
case C_SUB:
i1 -= i2;
break;
case C_MUL:
i1 *= i2;
break;
case C_DIV:
i1 /= i2;
break;
case C_MOD:
i1 %= i2;
break;
case C_AND:
i1 &= i2;
break;
case C_OR:
i1 |= i2;
break;
case C_XOR:
i1 ^= i2;
break;
case C_LAND:
i1 = i1 && i2;
break;
case C_LOR:
i1 = i1 || i2;
break;
case C_EQ:
i1 = i1 == i2;
break;
case C_NE:
i1 = i1 != i2;
break;
case C_GT:
i1 = i1 > i2;
break;
case C_GE:
i1 = i1 >= i2;
break;
case C_LT:
i1 = i1 < i2;
break;
case C_LE:
i1 = i1 <= i2;
break;
case C_R_SHIFT:
i1 = i1 >> i2;
break;
case C_L_SHIFT:
i1 = i1 << i2;
break;
}
push_val (st->stack, C_INT, i1);
}
/*==========================================
* 二項演算子
*------------------------------------------
*/
void op_2 (struct script_state *st, int op)
{
int i1, i2;
char *s1 = NULL, *s2 = NULL;
i2 = pop_val (st);
if (isstr (st->stack->stack_data[st->stack->sp]))
s2 = st->stack->stack_data[st->stack->sp].u.str;
i1 = pop_val (st);
if (isstr (st->stack->stack_data[st->stack->sp]))
s1 = st->stack->stack_data[st->stack->sp].u.str;
if (s1 != NULL && s2 != NULL)
{
// ss => op_2str
op_2str (st, op, st->stack->sp, st->stack->sp + 1);
}
else if (s1 == NULL && s2 == NULL)
{
// ii => op_2num
op_2num (st, op, i1, i2);
}
else
{
// si,is => error
printf ("script: op_2: int&str, str&int not allow.");
push_val (st->stack, C_INT, 0);
}
}
/*==========================================
* 単項演算子
*------------------------------------------
*/
void op_1num (struct script_state *st, int op)
{
int i1;
i1 = pop_val (st);
switch (op)
{
case C_NEG:
i1 = -i1;
break;
case C_NOT:
i1 = ~i1;
break;
case C_LNOT:
i1 = !i1;
break;
}
push_val (st->stack, C_INT, i1);
}
/*==========================================
* 関数の実行
*------------------------------------------
*/
int run_func (struct script_state *st)
{
int i, start_sp, end_sp, func;
end_sp = st->stack->sp;
for (i = end_sp - 1; i >= 0 && st->stack->stack_data[i].type != C_ARG;
i--);
if (i == 0)
{
if (battle_config.error_log)
printf ("function not found\n");
// st->stack->sp=0;
st->state = END;
return 0;
}
start_sp = i - 1;
st->start = i - 1;
st->end = end_sp;
func = st->stack->stack_data[st->start].u.num;
if (st->stack->stack_data[st->start].type != C_NAME
|| str_data[func].type != C_FUNC)
{
printf ("run_func: not function and command! \n");
// st->stack->sp=0;
st->state = END;
return 0;
}
#ifdef DEBUG_RUN
if (battle_config.etc_log)
{
printf ("run_func : %s? (%d(%d))\n", str_buf + str_data[func].str,
func, str_data[func].type);
printf ("stack dump :");
for (i = 0; i < end_sp; i++)
{
switch (st->stack->stack_data[i].type)
{
case C_INT:
printf (" int(%d)", st->stack->stack_data[i].u.num);
break;
case C_NAME:
printf (" name(%s)",
str_buf +
str_data[st->stack->stack_data[i].u.num].str);
break;
case C_ARG:
printf (" arg");
break;
case C_POS:
printf (" pos(%d)", st->stack->stack_data[i].u.num);
break;
default:
printf (" %d,%d", st->stack->stack_data[i].type,
st->stack->stack_data[i].u.num);
}
}
printf ("\n");
}
#endif
if (str_data[func].func)
{
str_data[func].func (st);
}
else
{
if (battle_config.error_log)
printf ("run_func : %s? (%d(%d))\n", str_buf + str_data[func].str,
func, str_data[func].type);
push_val (st->stack, C_INT, 0);
}
pop_stack (st->stack, start_sp, end_sp);
if (st->state == RETFUNC)
{
// ユーザー定義関数からの復帰
int olddefsp = st->defsp;
int i;
pop_stack (st->stack, st->defsp, start_sp); // 復帰に邪魔なスタック削除
if (st->defsp < 4
|| st->stack->stack_data[st->defsp - 1].type != C_RETINFO)
{
printf
("script:run_func(return) return without callfunc or callsub!\n");
st->state = END;
return 0;
}
i = conv_num (st, &(st->stack->stack_data[st->defsp - 4])); // 引数の数所得
st->pos = conv_num (st, &(st->stack->stack_data[st->defsp - 1])); // スクリプト位置の復元
st->script = (char *) conv_num (st, &(st->stack->stack_data[st->defsp - 2])); // スクリプトを復元
st->defsp = conv_num (st, &(st->stack->stack_data[st->defsp - 3])); // 基準スタックポインタを復元
pop_stack (st->stack, olddefsp - 4 - i, olddefsp); // 要らなくなったスタック(引数と復帰用データ)削除
st->state = GOTO;
}
return 0;
}
/*==========================================
* スクリプトの実行メイン部分
*------------------------------------------
*/
int run_script_main (unsigned char *script, int pos, int rid, int oid,
struct script_state *st, unsigned char *rootscript)
{
int c, rerun_pos;
int cmdcount = script_config.check_cmdcount;
int gotocount = script_config.check_gotocount;
struct script_stack *stack = st->stack;
st->defsp = stack->sp;
st->script = script;
rerun_pos = st->pos;
for (st->state = 0; st->state == 0;)
{
switch (c = get_com (script, &st->pos))
{
case C_EOL:
if (stack->sp != st->defsp)
{
if (battle_config.error_log)
printf ("stack.sp(%d) != default(%d)\n", stack->sp,
st->defsp);
stack->sp = st->defsp;
}
rerun_pos = st->pos;
break;
case C_INT:
push_val (stack, C_INT, get_num (script, &st->pos));
break;
case C_POS:
case C_NAME:
push_val (stack, c, (*(int *) (script + st->pos)) & 0xffffff);
st->pos += 3;
break;
case C_ARG:
push_val (stack, c, 0);
break;
case C_STR:
push_str (stack, C_CONSTSTR, script + st->pos);
while (script[st->pos++]);
break;
case C_FUNC:
run_func (st);
if (st->state == GOTO)
{
rerun_pos = st->pos;
script = st->script;
st->state = 0;
if (gotocount > 0 && (--gotocount) <= 0)
{
printf ("run_script: infinity loop !\n");
st->state = END;
}
}
break;
case C_ADD:
op_add (st);
break;
case C_SUB:
case C_MUL:
case C_DIV:
case C_MOD:
case C_EQ:
case C_NE:
case C_GT:
case C_GE:
case C_LT:
case C_LE:
case C_AND:
case C_OR:
case C_XOR:
case C_LAND:
case C_LOR:
case C_R_SHIFT:
case C_L_SHIFT:
op_2 (st, c);
break;
case C_NEG:
case C_NOT:
case C_LNOT:
op_1num (st, c);
break;
case C_NOP:
st->state = END;
break;
default:
if (battle_config.error_log)
printf ("unknown command : %d @ %d\n", c, pos);
st->state = END;
break;
}
if (cmdcount > 0 && (--cmdcount) <= 0)
{
printf ("run_script: infinity loop !\n");
st->state = END;
}
}
switch (st->state)
{
case STOP:
break;
case END:
{
struct map_session_data *sd = map_id2sd (st->rid);
st->pos = -1;
if (sd && sd->npc_id == st->oid)
npc_event_dequeue (sd);
}
break;
case RERUNLINE:
{
st->pos = rerun_pos;
}
break;
}
if (st->state != END)
{
// 再開するためにスタック情報を保存
struct map_session_data *sd = map_id2sd (st->rid);
if (sd /* && sd->npc_stackbuf==NULL */ )
{
if (sd->npc_stackbuf)
free (sd->npc_stackbuf);
sd->npc_stackbuf = (char *)
calloc (sizeof (stack->stack_data[0]) * stack->sp_max, 1);
memcpy (sd->npc_stackbuf, stack->stack_data,
sizeof (stack->stack_data[0]) * stack->sp_max);
sd->npc_stack = stack->sp;
sd->npc_stackmax = stack->sp_max;
sd->npc_script = script;
sd->npc_scriptroot = rootscript;
}
}
return 0;
}
/*==========================================
* スクリプトの実行
*------------------------------------------
*/
int run_script (unsigned char *script, int pos, int rid, int oid)
{
return run_script_l (script, pos, rid, oid, 0, NULL);
}
int run_script_l (unsigned char *script, int pos, int rid, int oid,
int args_nr, argrec_t * args)
{
struct script_stack stack;
struct script_state st;
struct map_session_data *sd = map_id2sd (rid);
unsigned char *rootscript = script;
int i;
if (script == NULL || pos < 0)
return -1;
if (sd && sd->npc_stackbuf && sd->npc_scriptroot == (char *) rootscript)
{
// 前回のスタックを復帰
script = sd->npc_script;
stack.sp = sd->npc_stack;
stack.sp_max = sd->npc_stackmax;
stack.stack_data = (struct script_data *)
calloc (stack.sp_max, sizeof (stack.stack_data[0]));
memcpy (stack.stack_data, sd->npc_stackbuf,
sizeof (stack.stack_data[0]) * stack.sp_max);
free (sd->npc_stackbuf);
sd->npc_stackbuf = NULL;
}
else
{
// スタック初期化
stack.sp = 0;
stack.sp_max = 64;
stack.stack_data = (struct script_data *)
calloc (stack.sp_max, sizeof (stack.stack_data[0]));
}
st.stack = &stack;
st.pos = pos;
st.rid = rid;
st.oid = oid;
for (i = 0; i < args_nr; i++)
{
if (args[i].name[strlen (args[i].name) - 1] == '$')
pc_setregstr (sd, add_str (args[i].name), args[i].v.s);
else
pc_setreg (sd, add_str (args[i].name), args[i].v.i);
}
run_script_main (script, pos, rid, oid, &st, rootscript);
free (stack.stack_data);
stack.stack_data = NULL;
return st.pos;
}
/*==========================================
* マップ変数の変更
*------------------------------------------
*/
int mapreg_setreg (int num, int val)
{
if (val != 0)
numdb_insert (mapreg_db, num, val);
else
numdb_erase (mapreg_db, num);
mapreg_dirty = 1;
return 0;
}
/*==========================================
* 文字列型マップ変数の変更
*------------------------------------------
*/
int mapreg_setregstr (int num, const char *str)
{
char *p;
if ((p = (char *)numdb_search (mapregstr_db, num)) != NULL)
free (p);
if (str == NULL || *str == 0)
{
numdb_erase (mapregstr_db, num);
mapreg_dirty = 1;
return 0;
}
p = (char *) calloc (strlen (str) + 1, 1);
strcpy (p, str);
numdb_insert (mapregstr_db, num, p);
mapreg_dirty = 1;
return 0;
}
/*==========================================
* 永続的マップ変数の読み込み
*------------------------------------------
*/
static int script_load_mapreg (void)
{
FILE *fp;
char line[1024];
if ((fp = fopen_ (mapreg_txt, "rt")) == NULL)
return -1;
while (fgets (line, sizeof (line), fp))
{
char buf1[256], buf2[1024], *p;
int n, v, s, i;
if (sscanf (line, "%255[^,],%d\t%n", buf1, &i, &n) != 2 &&
(i = 0, sscanf (line, "%[^\t]\t%n", buf1, &n) != 1))
continue;
if (buf1[strlen (buf1) - 1] == '$')
{
if (sscanf (line + n, "%[^\n\r]", buf2) != 1)
{
printf ("%s: %s broken data !\n", mapreg_txt, buf1);
continue;
}
p = (char *) calloc (strlen (buf2) + 1, 1);
strcpy (p, buf2);
s = add_str (buf1);
numdb_insert (mapregstr_db, (i << 24) | s, p);
}
else
{
if (sscanf (line + n, "%d", &v) != 1)
{
printf ("%s: %s broken data !\n", mapreg_txt, buf1);
continue;
}
s = add_str (buf1);
numdb_insert (mapreg_db, (i << 24) | s, v);
}
}
fclose_ (fp);
mapreg_dirty = 0;
return 0;
}
/*==========================================
* 永続的マップ変数の書き込み
*------------------------------------------
*/
static void script_save_mapreg_intsub (db_key_t key, db_val_t data, va_list ap)
{
FILE *fp = va_arg (ap, FILE *);
int num = key.i & 0x00ffffff, i = key.i >> 24;
char *name = str_buf + str_data[num].str;
if (name[1] != '@')
{
if (i == 0)
fprintf (fp, "%s\t%d\n", name, (int) data);
else
fprintf (fp, "%s,%d\t%d\n", name, i, (int) data);
}
}
static void script_save_mapreg_strsub (db_key_t key, db_val_t data, va_list ap)
{
FILE *fp = va_arg (ap, FILE *);
int num = key.i & 0x00ffffff, i = key.i >> 24;
char *name = str_buf + str_data[num].str;
if (name[1] != '@')
{
if (i == 0)
fprintf (fp, "%s\t%s\n", name, (char *) data);
else
fprintf (fp, "%s,%d\t%s\n", name, i, (char *) data);
}
}
static int script_save_mapreg (void)
{
FILE *fp;
int lock;
if ((fp = lock_fopen (mapreg_txt, &lock)) == NULL)
return -1;
numdb_foreach (mapreg_db, script_save_mapreg_intsub, fp);
numdb_foreach (mapregstr_db, script_save_mapreg_strsub, fp);
lock_fclose (fp, mapreg_txt, &lock);
mapreg_dirty = 0;
return 0;
}
static void script_autosave_mapreg (timer_id tid, tick_t tick, custom_id_t id,
custom_data_t data)
{
if (mapreg_dirty)
script_save_mapreg ();
}
/*==========================================
*
*------------------------------------------
*/
static int set_posword (char *p)
{
char *np, *str[15];
int i = 0;
for (i = 0; i < 11; i++)
{
if ((np = strchr (p, ',')) != NULL)
{
str[i] = p;
*np = 0;
p = np + 1;
}
else
{
str[i] = p;
p += strlen (p);
}
if (str[i])
strcpy (pos[i], str[i]);
}
return 0;
}
int script_config_read (char *cfgName)
{
int i;
char line[1024], w1[1024], w2[1024];
FILE *fp;
script_config.warn_func_no_comma = 1;
script_config.warn_cmd_no_comma = 1;
script_config.warn_func_mismatch_paramnum = 1;
script_config.warn_cmd_mismatch_paramnum = 1;
script_config.check_cmdcount = 8192;
script_config.check_gotocount = 512;
fp = fopen_ (cfgName, "r");
if (fp == NULL)
{
printf ("file not found: %s\n", cfgName);
return 1;
}
while (fgets (line, 1020, fp))
{
if (line[0] == '/' && line[1] == '/')
continue;
i = sscanf (line, "%[^:]: %[^\r\n]", w1, w2);
if (i != 2)
continue;
if (strcasecmp (w1, "refine_posword") == 0)
{
set_posword (w2);
}
if (strcasecmp (w1, "import") == 0)
{
script_config_read (w2);
}
}
fclose_ (fp);
return 0;
}
/*==========================================
* 終了
*------------------------------------------
*/
static void mapregstr_db_final (db_key_t key, db_val_t data, va_list ap)
{
free (data);
}
static void userfunc_db_final (db_key_t key, db_val_t data, va_list ap)
{
free ((char*)key.s);
free (data);
}
int do_final_script (void)
{
if (mapreg_dirty >= 0)
script_save_mapreg ();
if (script_buf)
free (script_buf);
if (mapreg_db)
numdb_final (mapreg_db, NULL);
if (mapregstr_db)
strdb_final (mapregstr_db, mapregstr_db_final);
if (scriptlabel_db)
strdb_final (scriptlabel_db, NULL);
if (userfunc_db)
strdb_final (userfunc_db, userfunc_db_final);
if (str_data)
free (str_data);
if (str_buf)
free (str_buf);
return 0;
}
/*==========================================
* 初期化
*------------------------------------------
*/
int do_init_script (void)
{
mapreg_db = numdb_init ();
mapregstr_db = numdb_init ();
script_load_mapreg ();
add_timer_interval (gettick () + MAPREG_AUTOSAVE_INTERVAL,
script_autosave_mapreg, 0, 0,
MAPREG_AUTOSAVE_INTERVAL);
scriptlabel_db = strdb_init (50);
return 0;
}