summaryrefslogtreecommitdiff
path: root/src/map/script.c
diff options
context:
space:
mode:
authorai4rei <ai4rei@54d463be-8e91-2dee-dedb-b68131a5f0ec>2010-12-26 22:36:41 +0000
committerai4rei <ai4rei@54d463be-8e91-2dee-dedb-b68131a5f0ec>2010-12-26 22:36:41 +0000
commit6096ce0b42a3eee07dc70ae5ef489aa4c30bf515 (patch)
treee91f8afd3b7b8b80f0c55aae07f7a478f469c37a /src/map/script.c
parent23e1b7db5ba2277a406fc84c30e87c324a83097c (diff)
downloadhercules-6096ce0b42a3eee07dc70ae5ef489aa4c30bf515.tar.gz
hercules-6096ce0b42a3eee07dc70ae5ef489aa4c30bf515.tar.bz2
hercules-6096ce0b42a3eee07dc70ae5ef489aa4c30bf515.tar.xz
hercules-6096ce0b42a3eee07dc70ae5ef489aa4c30bf515.zip
* Merged changes from trunk [14496:14630/trunk].
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/branches/renewal@14632 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/map/script.c')
-rw-r--r--src/map/script.c1384
1 files changed, 825 insertions, 559 deletions
diff --git a/src/map/script.c b/src/map/script.c
index c71debc0d..773f8d6c4 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -67,7 +67,6 @@
// - 'function FuncName;' function declarations reverting to global functions
// if local label isn't found
// - join callfunc and callsub's functionality
-// - use script_op2name in the DEBUG_DISASM block
// - remove dynamic allocation in add_word()
// - remove GETVALUE / SETVALUE
// - clean up the set_reg / set_val / setd_sub mess
@@ -160,6 +159,9 @@
if( script_hasdata(st,n) ) \
(t)=script_getnum(st,n);
+/// Maximum amount of elements in script arrays
+#define SCRIPT_MAX_ARRAYSIZE 128
+
#define SCRIPT_BLOCK_SIZE 512
enum { LABEL_NEXTLINE=1,LABEL_START };
@@ -210,6 +212,7 @@ DBMap* script_get_userfunc_db(){ return userfunc_db; }
static DBMap* autobonus_db=NULL; // char* script -> char* bytecode
struct Script_Config script_config = {
+ 1, // warn_func_mismatch_argtypes
1, 65535, 2048, //warn_func_mismatch_paramnum/check_cmdcount/check_gotocount
0, INT_MAX, // input_min_value/input_max_value
"OnPCDieEvent", //die_event_name
@@ -281,13 +284,11 @@ typedef struct script_function {
extern script_function buildin_func[];
static struct linkdb_node* sleep_db;// int oid -> struct script_state*
-uint32 crctab[256];
/*==========================================
* ローカルプロトタイプ宣言 (必要な物のみ)
*------------------------------------------*/
const char* parse_subexpr(const char* p,int limit);
-void push_val(struct script_stack *stack,int type,int val);
int run_func(struct script_state *st);
enum {
@@ -515,6 +516,44 @@ static void script_reportdata(struct script_data* data)
}
}
+
+/// Reports on the console information about the current built-in function.
+static void script_reportfunc(struct script_state* st)
+{
+ int i, params, id;
+ struct script_data* data;
+
+ if( !script_hasdata(st,0) )
+ {// no stack
+ return;
+ }
+
+ data = script_getdata(st,0);
+
+ if( !data_isreference(data) || str_data[reference_getid(data)].type != C_FUNC )
+ {// script currently not executing a built-in function or corrupt stack
+ return;
+ }
+
+ id = reference_getid(data);
+ params = script_lastdata(st)-1;
+
+ if( params > 0 )
+ {
+ ShowDebug("Function: %s (%d parameter%s):\n", get_str(id), params, ( params == 1 ) ? "" : "s");
+
+ for( i = 2; i <= script_lastdata(st); i++ )
+ {
+ script_reportdata(script_getdata(st,i));
+ }
+ }
+ else
+ {
+ ShowDebug("Function: %s (no parameters)\n", get_str(id));
+ }
+}
+
+
/*==========================================
* エラーメッセージ出力
*------------------------------------------*/
@@ -741,8 +780,8 @@ void set_label(int l,int pos, const char* script_pos)
{
int i,next;
- if(str_data[l].type==C_INT || str_data[l].type==C_PARAM)
- { //Prevent overwriting constants values and parameters [Skotlex]
+ if(str_data[l].type==C_INT || str_data[l].type==C_PARAM || str_data[l].type==C_FUNC)
+ { //Prevent overwriting constants values, parameters and built-in functions [Skotlex]
disp_error_message("set_label: invalid label name",script_pos);
return;
}
@@ -842,7 +881,7 @@ int add_word(const char* p)
disp_error_message("script:add_word: invalid word. A word consists of undercores and/or alfanumeric characters, and valid variable prefixes/postfixes.", p);
// Duplicate the word
- CREATE(word, char, len+1);
+ word = aMalloc(len+1);
memcpy(word, p, len);
word[len] = 0;
@@ -1502,7 +1541,7 @@ const char* parse_syntax(const char* p)
// function declaration - just register the name
int l;
l = add_word(func_name);
- if( str_data[l].type == C_NOP )//## ??? [FlavioJS]
+ if( str_data[l].type == C_NOP )// set type only if the name did not exist before
str_data[l].type = C_USERFUNC;
// if, for , while の閉じ判定
@@ -1528,7 +1567,7 @@ const char* parse_syntax(const char* p)
// Set the position of the function (label)
l=add_word(func_name);
- if( str_data[l].type == C_NOP )//## ??? [FlavioJS]
+ if( str_data[l].type == C_NOP )// set type only if the name did not exist before
str_data[l].type = C_USERFUNC;
set_label(l, script_pos, p);
if( parse_options&SCRIPT_USE_LABEL_DB )
@@ -2078,54 +2117,30 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
{
int i = 0,j;
while(i < script_pos) {
- ShowMessage("%06x ",i);
+ c_op op = get_com(script_buf,&i);
+
+ ShowMessage("%06x %s", i, script_op2name(op));
j = i;
- switch(get_com(script_buf,&i)) {
- case C_EOL: printf("C_EOL"); break;
- case C_INT: printf("C_INT %d",get_num(script_buf,&i)); break;
+ switch(op) {
+ case C_INT:
+ ShowMessage(" %d", get_num(script_buf,&i));
+ break;
case C_POS:
- ShowMessage("C_POS 0x%06x",*(int*)(script_buf+i)&0xffffff);
+ ShowMessage(" 0x%06x", *(int*)(script_buf+i)&0xffffff);
i += 3;
break;
case C_NAME:
j = (*(int*)(script_buf+i)&0xffffff);
- ShowMessage("C_NAME %s",j == 0xffffff ? "?? unknown ??" : get_str(j));
+ ShowMessage(" %s", ( j == 0xffffff ) ? "?? unknown ??" : get_str(j));
i += 3;
break;
- case C_ARG: ShowMessage("C_ARG"); break;
- case C_FUNC: ShowMessage("C_FUNC"); break;
- case C_ADD: ShowMessage("C_ADD"); break;
- case C_SUB: ShowMessage("C_SUB"); break;
- case C_MUL: ShowMessage("C_MUL"); break;
- case C_DIV: ShowMessage("C_DIV"); break;
- case C_MOD: ShowMessage("C_MOD"); break;
- case C_EQ: ShowMessage("C_EQ"); break;
- case C_NE: ShowMessage("C_NE"); break;
- case C_GT: ShowMessage("C_GT"); break;
- case C_GE: ShowMessage("C_GE"); break;
- case C_LT: ShowMessage("C_LT"); break;
- case C_LE: ShowMessage("C_LE"); break;
- case C_AND: ShowMessage("C_AND"); break;
- case C_OR: ShowMessage("C_OR"); break;
- case C_XOR: ShowMessage("C_XOR"); break;
- case C_LAND: ShowMessage("C_LAND"); break;
- case C_LOR: ShowMessage("C_LOR"); break;
- case C_R_SHIFT: ShowMessage("C_R_SHIFT"); break;
- case C_L_SHIFT: ShowMessage("C_L_SHIFT"); break;
- case C_NEG: ShowMessage("C_NEG"); break;
- case C_NOT: ShowMessage("C_NOT"); break;
- case C_LNOT: ShowMessage("C_LNOT"); break;
- case C_NOP: ShowMessage("C_NOP"); break;
- case C_OP3: ShowMessage("C_OP3"); break;
case C_STR:
j = strlen(script_buf + i);
- ShowMessage("C_STR %s",script_buf + i);
- i+= j+1;
+ ShowMessage(" %s", script_buf + i);
+ i += j+1;
break;
- default:
- ShowMessage("unknown");
}
- ShowMessage(CL_CLL "\n");
+ ShowMessage(CL_CLL"\n");
}
}
#endif
@@ -2144,6 +2159,7 @@ TBL_PC *script_rid2sd(struct script_state *st)
TBL_PC *sd=map_id2sd(st->rid);
if(!sd){
ShowError("script_rid2sd: fatal error ! player not attached!\n");
+ script_reportfunc(st);
script_reportsrc(st);
st->state = END;
}
@@ -2694,6 +2710,10 @@ struct script_state* script_alloc_state(struct script_code* script, int pos, int
/// @param st Script state
void script_free_state(struct script_state* st)
{
+ if(st->bk_st)
+ {// backup was not restored
+ ShowDebug("script_free_state: Previous script state lost (rid=%d, oid=%d, state=%d, bk_npcid=%d).\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid);
+ }
if( st->sleep.timer != INVALID_TIMER )
delete_timer(st->sleep.timer, run_script_timer);
script_free_vars(st->stack->var_function);
@@ -2977,6 +2997,94 @@ void op_1(struct script_state* st, int op)
}
+/// Checks the type of all arguments passed to a built-in function.
+///
+/// @param st Script state whose stack arguments should be inspected.
+/// @param func Built-in function for which the arguments are intended.
+static void script_check_buildin_argtype(struct script_state* st, int func)
+{
+ char type;
+ int idx, invalid = 0;
+ script_function* sf = &buildin_func[str_data[func].val];
+
+ for( idx = 2; script_hasdata(st, idx); idx++ )
+ {
+ struct script_data* data = script_getdata(st, idx);
+
+ type = sf->arg[idx-2];
+
+ if( type == '?' || type == '*' )
+ {// optional argument or unknown number of optional parameters ( no types are after this )
+ break;
+ }
+ else if( type == 0 )
+ {// more arguments than necessary ( should not happen, as it is checked before )
+ ShowWarning("Found more arguments than necessary.\n");
+ invalid++;
+ break;
+ }
+ else
+ {
+ const char* name = NULL;
+
+ if( data_isreference(data) )
+ {// get name for variables to determine the type they refer to
+ name = reference_getname(data);
+ }
+
+ switch( type )
+ {
+ case 'v':
+ if( !data_isstring(data) && !data_isint(data) && !data_isreference(data) )
+ {// variant
+ ShowWarning("Unexpected type for argument %d. Expected string, number or variable.\n", idx-1);
+ script_reportdata(data);
+ invalid++;
+ }
+ break;
+ case 's':
+ if( !data_isstring(data) && !( data_isreference(data) && is_string_variable(name) ) )
+ {// string
+ ShowWarning("Unexpected type for argument %d. Expected string.\n", idx-1);
+ script_reportdata(data);
+ invalid++;
+ }
+ break;
+ case 'i':
+ if( !data_isint(data) && !( data_isreference(data) && ( reference_toparam(data) || reference_toconstant(data) || !is_string_variable(name) ) ) )
+ {// int ( params and constants are always int )
+ ShowWarning("Unexpected type for argument %d. Expected number.\n", idx-1);
+ script_reportdata(data);
+ invalid++;
+ }
+ break;
+ case 'r':
+ if( !data_isreference(data) )
+ {// variables
+ ShowWarning("Unexpected type for argument %d. Expected variable.\n", idx-1);
+ script_reportdata(data);
+ invalid++;
+ }
+ break;
+ case 'l':
+ if( !data_islabel(data) && !data_isfunclabel(data) )
+ {// label
+ ShowWarning("Unexpected type for argument %d. Expected label.\n", idx-1);
+ script_reportdata(data);
+ invalid++;
+ }
+ break;
+ }
+ }
+ }
+
+ if(invalid)
+ {
+ ShowDebug("Function: %s\n", get_str(func));
+ script_reportsrc(st);
+ }
+}
+
/// Executes a buildin command.
/// Stack: C_NAME(<command>) C_ARG <arg0> <arg1> ... <argN>
@@ -3012,6 +3120,11 @@ int run_func(struct script_state *st)
return 1;
}
+ if( script_config.warn_func_mismatch_argtypes )
+ {
+ script_check_buildin_argtype(st, func);
+ }
+
if(str_data[func].func){
if (str_data[func].func(st)) //Report error
script_reportsrc(st);
@@ -3062,8 +3175,6 @@ int run_func(struct script_state *st)
/*==========================================
* script execution
*------------------------------------------*/
-void run_script_main(struct script_state *st);
-
void run_script(struct script_code *rootscript,int pos,int rid,int oid)
{
struct script_state *st;
@@ -3138,6 +3249,63 @@ int run_script_timer(int tid, unsigned int tick, int id, intptr data)
return 0;
}
+/// Detaches script state from possibly attached character and restores it's previous script if any.
+///
+/// @param st Script state to detach.
+/// @param dequeue_event Whether to schedule any queued events, when there was no previous script.
+static void script_detach_state(struct script_state* st, bool dequeue_event)
+{
+ struct map_session_data* sd;
+
+ if(st->rid && (sd = map_id2sd(st->rid))!=NULL)
+ {
+ sd->st = st->bk_st;
+ sd->npc_id = st->bk_npcid;
+
+ if(st->bk_st)
+ {
+ //Remove tag for removal.
+ st->bk_st = NULL;
+ st->bk_npcid = 0;
+ }
+ else if(dequeue_event)
+ {
+ npc_event_dequeue(sd);
+ }
+ }
+ else if(st->bk_st)
+ {// rid was set to 0, before detaching the script state
+ ShowError("script_detach_state: Found previous script state without attached player (rid=%d, oid=%d, state=%d, bk_npcid=%d)\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid);
+ script_reportsrc(st->bk_st);
+
+ script_free_state(st->bk_st);
+ st->bk_st = NULL;
+ }
+}
+
+/// Attaches script state to possibly attached character and backups it's previous script, if any.
+///
+/// @param st Script state to attach.
+static void script_attach_state(struct script_state* st)
+{
+ struct map_session_data* sd;
+
+ if(st->rid && (sd = map_id2sd(st->rid))!=NULL)
+ {
+ if(st!=sd->st)
+ {
+ if(st->bk_st)
+ {// there is already a backup
+ ShowDebug("script_free_state: Previous script state lost (rid=%d, oid=%d, state=%d, bk_npcid=%d).\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid);
+ }
+ st->bk_st = sd->st;
+ st->bk_npcid = sd->npc_id;
+ }
+ sd->st = st;
+ sd->npc_id = st->oid;
+ }
+}
+
/*==========================================
* スクリプトの実行メイン部分
*------------------------------------------*/
@@ -3146,22 +3314,10 @@ void run_script_main(struct script_state *st)
int cmdcount=script_config.check_cmdcount;
int gotocount=script_config.check_gotocount;
TBL_PC *sd;
- //For backing up purposes
- struct script_state *bk_st = NULL;
- int bk_npcid = 0;
struct script_stack *stack=st->stack;
struct npc_data *nd;
- sd = map_id2sd(st->rid);
-
- if(sd){
- if(sd->st != st){
- bk_st = sd->st;
- bk_npcid = sd->npc_id;
- }
- sd->st = st;
- sd->npc_id = st->oid;
- }
+ script_attach_state(st);
nd = map_id2nd(st->oid);
if( nd && map[nd->bl.m].instance_id > 0 )
@@ -3260,43 +3416,37 @@ void run_script_main(struct script_state *st)
if(st->sleep.tick > 0) {
//Restore previous script
- if (sd) {
- sd->st = bk_st;
- sd->npc_id = bk_npcid;
- bk_st = NULL; //Remove tag for removal.
- }
+ script_detach_state(st, false);
//Delay execution
- sd = map_id2sd(st->rid); // Refresh sd since script might have attached someone while running. [Inkfish]
+ sd = map_id2sd(st->rid); // Get sd since script might have attached someone while running. [Inkfish]
st->sleep.charid = sd?sd->status.char_id:0;
st->sleep.timer = add_timer(gettick()+st->sleep.tick,
run_script_timer, st->sleep.charid, (intptr)st);
linkdb_insert(&sleep_db, (void*)st->oid, st);
}
- else if(st->state != END && sd){
+ else if(st->state != END && st->rid){
//Resume later (st is already attached to player).
- if(bk_st) {
+ if(st->bk_st) {
ShowWarning("Unable to restore stack! Double continuation!\n");
//Report BOTH scripts to see if that can help somehow.
ShowDebug("Previous script (lost):\n");
- script_reportsrc(bk_st);
+ script_reportsrc(st->bk_st);
ShowDebug("Current script:\n");
script_reportsrc(st);
+
+ script_free_state(st->bk_st);
+ st->bk_st = NULL;
}
} else {
//Dispose of script.
- if (sd)
+ if ((sd = map_id2sd(st->rid))!=NULL)
{ //Restore previous stack and save char.
if(sd->state.using_fake_npc){
- clif_clearunit_single(sd->npc_id, 0, sd->fd);
+ clif_clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd);
sd->state.using_fake_npc = 0;
}
//Restore previous script if any.
- sd->st = bk_st;
- sd->npc_id = bk_npcid;
- if (!bk_st)
- npc_event_dequeue(sd);
- else
- bk_st = NULL; //Remove tag for removal.
+ script_detach_state(st, true);
if (sd->state.reg_dirty&2)
intif_saveregistry(sd,2);
if (sd->state.reg_dirty&1)
@@ -3305,13 +3455,6 @@ void run_script_main(struct script_state *st)
script_free_state(st);
st = NULL;
}
-
- if (bk_st)
- { //Remove previous script
- script_free_state(bk_st);
- bk_st = NULL;
- }
-
}
int script_config_read(char *cfgName)
@@ -3349,6 +3492,9 @@ int script_config_read(char *cfgName)
else if(strcmpi(w1,"input_max_value")==0) {
script_config.input_max_value = config_switch(w2);
}
+ else if(strcmpi(w1,"warn_func_mismatch_argtypes")==0) {
+ script_config.warn_func_mismatch_argtypes = config_switch(w2);
+ }
else if(strcmpi(w1,"import")==0){
script_config_read(w2);
}
@@ -3401,6 +3547,74 @@ void script_add_autobonus(const char *autobonus)
}
}
+
+/// resets a temporary character array variable to given value
+void script_cleararray_pc(struct map_session_data* sd, const char* varname, void* value)
+{
+ int key;
+ uint8 idx;
+
+ if( not_array_variable(varname[0]) || !not_server_variable(varname[0]) )
+ {
+ ShowError("script_cleararray_pc: Variable '%s' has invalid scope (char_id=%d).\n", varname, sd->status.char_id);
+ return;
+ }
+
+ key = add_str(varname);
+
+ if( is_string_variable(varname) )
+ {
+ for( idx = 0; idx < SCRIPT_MAX_ARRAYSIZE; idx++ )
+ {
+ pc_setregstr(sd, reference_uid(key, idx), (const char*)value);
+ }
+ }
+ else
+ {
+ for( idx = 0; idx < SCRIPT_MAX_ARRAYSIZE; idx++ )
+ {
+ pc_setreg(sd, reference_uid(key, idx), (int)value);
+ }
+ }
+}
+
+
+/// sets a temporary character array variable element idx to given value
+/// @param refcache Pointer to an int variable, which keeps a copy of the reference to varname and must be initialized to 0. Can be NULL if only one element is set.
+void script_setarray_pc(struct map_session_data* sd, const char* varname, uint8 idx, void* value, int* refcache)
+{
+ int key;
+
+ if( not_array_variable(varname[0]) || !not_server_variable(varname[0]) )
+ {
+ ShowError("script_setarray_pc: Variable '%s' has invalid scope (char_id=%d).\n", varname, sd->status.char_id);
+ return;
+ }
+
+ if( idx >= SCRIPT_MAX_ARRAYSIZE )
+ {
+ ShowError("script_setarray_pc: Variable '%s' has invalid index '%d' (char_id=%d).\n", varname, (int)idx, sd->status.char_id);
+ return;
+ }
+
+ key = ( refcache && refcache[0] ) ? refcache[0] : add_str(varname);
+
+ if( is_string_variable(varname) )
+ {
+ pc_setregstr(sd, reference_uid(key, idx), (const char*)value);
+ }
+ else
+ {
+ pc_setreg(sd, reference_uid(key, idx), (int)value);
+ }
+
+ if( refcache )
+ {// save to avoid repeated add_str calls
+ refcache[0] = key;
+ }
+}
+
+
/*==========================================
* 終了
*------------------------------------------*/
@@ -3698,7 +3912,12 @@ BUILDIN_FUNC(menu)
sd->state.menu_or_input = 1;
clif_scriptmenu(sd, st->oid, StringBuf_Value(&buf));
StringBuf_Destroy(&buf);
- //TODO what's the maximum number of options that can be displayed and/or received? -> give warning
+
+ if( sd->npc_menu >= 0xff )
+ {// client supports only up to 254 entries; 0 is not used and 255 is reserved for cancel; excess entries are displayed but cause 'uint8' overflow
+ ShowWarning("buildin_menu: Too many options specified (current=%d, max=254).\n", sd->npc_menu);
+ script_reportsrc(st);
+ }
}
else if( sd->npc_menu == 0xff )
{// Cancel was pressed
@@ -3780,6 +3999,12 @@ BUILDIN_FUNC(select)
sd->state.menu_or_input = 1;
clif_scriptmenu(sd, st->oid, StringBuf_Value(&buf));
StringBuf_Destroy(&buf);
+
+ if( sd->npc_menu >= 0xff )
+ {
+ ShowWarning("buildin_select: Too many options specified (current=%d, max=254).\n", sd->npc_menu);
+ script_reportsrc(st);
+ }
}
else if( sd->npc_menu == 0xff )
{// Cancel was pressed
@@ -3842,6 +4067,12 @@ BUILDIN_FUNC(prompt)
sd->state.menu_or_input = 1;
clif_scriptmenu(sd, st->oid, StringBuf_Value(&buf));
StringBuf_Destroy(&buf);
+
+ if( sd->npc_menu >= 0xff )
+ {
+ ShowWarning("buildin_prompt: Too many options specified (current=%d, max=254).\n", sd->npc_menu);
+ script_reportsrc(st);
+ }
}
else if( sd->npc_menu == 0xff )
{// Cancel was pressed
@@ -4100,11 +4331,11 @@ BUILDIN_FUNC(warp)
y = script_getnum(st,4);
if(strcmp(str,"Random")==0)
- ret = pc_randomwarp(sd,3);
+ ret = pc_randomwarp(sd,CLR_TELEPORT);
else if(strcmp(str,"SavePoint")==0 || strcmp(str,"Save")==0)
- ret = pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,3);
+ ret = pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
else
- ret = pc_setpos(sd,mapindex_name2id(str),x,y,0);
+ ret = pc_setpos(sd,mapindex_name2id(str),x,y,CLR_OUTSIGHT);
if( ret ) {
ShowError("buildin_warp: moving player '%s' to \"%s\",%d,%d failed.\n", sd->status.name, str, x, y);
@@ -4124,9 +4355,9 @@ static int buildin_areawarp_sub(struct block_list *bl,va_list ap)
x=va_arg(ap,int);
y=va_arg(ap,int);
if(map == 0)
- pc_randomwarp((TBL_PC *)bl,3);
+ pc_randomwarp((TBL_PC *)bl,CLR_TELEPORT);
else
- pc_setpos((TBL_PC *)bl,map,x,y,0);
+ pc_setpos((TBL_PC *)bl,map,x,y,CLR_OUTSIGHT);
return 0;
}
BUILDIN_FUNC(areawarp)
@@ -4212,12 +4443,12 @@ BUILDIN_FUNC(warpchar)
return 0;
if(strcmp(str, "Random") == 0)
- pc_randomwarp(sd, 3);
+ pc_randomwarp(sd, CLR_TELEPORT);
else
if(strcmp(str, "SavePoint") == 0)
- pc_setpos(sd, sd->status.save_point.map,sd->status.save_point.x, sd->status.save_point.y, 3);
+ pc_setpos(sd, sd->status.save_point.map,sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT);
else
- pc_setpos(sd, mapindex_name2id(str), x, y, 3);
+ pc_setpos(sd, mapindex_name2id(str), x, y, CLR_TELEPORT);
return 0;
}
@@ -4274,15 +4505,15 @@ BUILDIN_FUNC(warpparty)
{
case 0: // Random
if(!map[pl_sd->bl.m].flag.nowarp)
- pc_randomwarp(pl_sd,3);
+ pc_randomwarp(pl_sd,CLR_TELEPORT);
break;
case 1: // SavePointAll
if(!map[pl_sd->bl.m].flag.noreturn)
- pc_setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,3);
+ pc_setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,CLR_TELEPORT);
break;
case 2: // SavePoint
if(!map[pl_sd->bl.m].flag.noreturn)
- pc_setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,3);
+ pc_setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
break;
case 3: // Leader
for(j = 0; j < MAX_PARTY && !p->party.member[j].leader; j++);
@@ -4298,12 +4529,12 @@ BUILDIN_FUNC(warpparty)
continue;
if(map[pl_sd->bl.m].flag.noreturn || map[pl_sd->bl.m].flag.nowarp)
continue;
- pc_setpos(pl_sd,mapindex,x,y,3);
+ pc_setpos(pl_sd,mapindex,x,y,CLR_TELEPORT);
}
break;
case 4: // m,x,y
if(!map[pl_sd->bl.m].flag.noreturn && !map[pl_sd->bl.m].flag.nowarp)
- pc_setpos(pl_sd,mapindex_name2id(str),x,y,3);
+ pc_setpos(pl_sd,mapindex_name2id(str),x,y,CLR_TELEPORT);
break;
}
}
@@ -4352,19 +4583,19 @@ BUILDIN_FUNC(warpguild)
{
case 0: // Random
if(!map[pl_sd->bl.m].flag.nowarp)
- pc_randomwarp(pl_sd,3);
+ pc_randomwarp(pl_sd,CLR_TELEPORT);
break;
case 1: // SavePointAll
if(!map[pl_sd->bl.m].flag.noreturn)
- pc_setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,3);
+ pc_setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,CLR_TELEPORT);
break;
case 2: // SavePoint
if(!map[pl_sd->bl.m].flag.noreturn)
- pc_setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,3);
+ pc_setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
break;
case 3: // m,x,y
if(!map[pl_sd->bl.m].flag.noreturn && !map[pl_sd->bl.m].flag.nowarp)
- pc_setpos(pl_sd,mapindex_name2id(str),x,y,3);
+ pc_setpos(pl_sd,mapindex_name2id(str),x,y,CLR_TELEPORT);
break;
}
}
@@ -4588,7 +4819,7 @@ static int32 getarraysize(struct script_state* st, int32 id, int32 idx, int isst
if( isstring )
{
- for( ; idx < 128; ++idx )
+ for( ; idx < SCRIPT_MAX_ARRAYSIZE; ++idx )
{
char* str = (char*)get_val2(st, reference_uid(id, idx), ref);
if( str && *str )
@@ -4598,7 +4829,7 @@ static int32 getarraysize(struct script_state* st, int32 id, int32 idx, int isst
}
else
{
- for( ; idx < 128; ++idx )
+ for( ; idx < SCRIPT_MAX_ARRAYSIZE; ++idx )
{
int32 num = (int32)get_val2(st, reference_uid(id, idx), ref);
if( num )
@@ -4651,8 +4882,8 @@ BUILDIN_FUNC(setarray)
}
end = start + script_lastdata(st) - 2;
- if( end > 127 )
- end = 127;
+ if( end >= SCRIPT_MAX_ARRAYSIZE )
+ end = SCRIPT_MAX_ARRAYSIZE-1;
if( is_string_variable(name) )
{// string array
@@ -4714,8 +4945,8 @@ BUILDIN_FUNC(cleararray)
v = (void*)script_getnum(st, 3);
end = start + script_getnum(st, 4);
- if( end > 127 )
- end = 127;
+ if( end >= SCRIPT_MAX_ARRAYSIZE )
+ end = SCRIPT_MAX_ARRAYSIZE-1;
for( ; start <= end; ++start )
set_reg(st, sd, reference_uid(id, start), name, v, script_getref(st,2));
@@ -4784,8 +5015,8 @@ BUILDIN_FUNC(copyarray)
}
count = script_getnum(st, 4);
- if( count > 128 - idx1 )
- count = 128 - idx1;
+ if( count >= SCRIPT_MAX_ARRAYSIZE - idx1 )
+ count = (SCRIPT_MAX_ARRAYSIZE-1) - idx1;
if( count <= 0 || (id1 == id2 && idx1 == idx2) )
return 0;// nothing to copy
@@ -4802,7 +5033,7 @@ BUILDIN_FUNC(copyarray)
{// normal copy
for( i = 0; i < count; ++i )
{
- if( idx2 + i < 128 )
+ if( idx2 + i < SCRIPT_MAX_ARRAYSIZE )
{
v = get_val2(st, reference_uid(id2, idx2 + i), reference_getref(data2));
set_reg(st, sd, reference_uid(id1, idx1 + i), name1, v, reference_getref(data1));
@@ -4958,7 +5189,7 @@ BUILDIN_FUNC(getelementofarray)
}
i = script_getnum(st, 3);
- if( i < 0 || i >= 128 )
+ if( i < 0 || i >= SCRIPT_MAX_ARRAYSIZE )
{
ShowWarning("script:getelementofarray: index out of range (%d)\n", i);
script_reportdata(data);
@@ -5154,48 +5385,80 @@ BUILDIN_FUNC(countitem2)
*------------------------------------------*/
BUILDIN_FUNC(checkweight)
{
- int nameid=0,amount,i;
- unsigned long weight;
- TBL_PC *sd;
- struct script_data *data;
+ int nameid, amount, slots;
+ unsigned int weight;
+ struct item_data* id = NULL;
+ struct map_session_data* sd;
+ struct script_data* data;
- sd = script_rid2sd(st);
- if( sd == NULL )
+ if( ( sd = script_rid2sd(st) ) == NULL )
+ {
return 0;
+ }
- data=script_getdata(st,2);
- get_val(st,data);
- if( data_isstring(data) ){
- 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);
+ data = script_getdata(st,2);
+ get_val(st, data); // convert into value in case of a variable
- amount=script_getnum(st,3);
- if ( amount<=0 || nameid<500 ) { //if get wrong item ID or amount<=0, don't count weight of non existing items
- script_pushint(st,0);
- ShowError("buildin_checkweight: Wrong item ID or amount.\n");
+ if( data_isstring(data) )
+ {// item name
+ id = itemdb_searchname(conv_str(st, data));
+ }
+ else
+ {// item id
+ id = itemdb_exists(conv_num(st, data));
+ }
+
+ if( id == NULL )
+ {
+ ShowError("buildin_checkweight: Invalid item '%s'.\n", script_getstr(st,2)); // returns string, regardless of what it was
+ return 1;
+ }
+
+ nameid = id->nameid;
+ amount = script_getnum(st,3);
+
+ if( amount < 1 )
+ {
+ ShowError("buildin_checkweight: Invalid amount '%d'.\n", amount);
return 1;
}
weight = itemdb_weight(nameid)*amount;
- if( amount > MAX_AMOUNT || weight + sd->weight > sd->max_weight )
+
+ if( weight + sd->weight > sd->max_weight )
+ {// too heavy
script_pushint(st,0);
- else if( itemdb_isstackable(nameid) )
- {
- if( (i = pc_search_inventory(sd,nameid)) >= 0 )
- script_pushint(st,amount + sd->status.inventory[i].amount > MAX_AMOUNT ? 0 : 1);
- else
- script_pushint(st,pc_search_inventory(sd,0) >= 0 ? 1 : 0);
+ return 0;
}
- else
+
+ switch( pc_checkadditem(sd, nameid, amount) )
{
- for( i = 0; i < MAX_INVENTORY && amount; ++i )
- if( sd->status.inventory[i].nameid == 0 )
- amount--;
- script_pushint(st,amount ? 0 : 1);
+ case ADDITEM_EXIST:
+ // item is already in inventory, but there is still space for the requested amount
+ break;
+ case ADDITEM_NEW:
+ slots = pc_inventoryblank(sd);
+
+ if( itemdb_isstackable(nameid) )
+ {// stackable
+ if( slots < 1 )
+ {
+ script_pushint(st,0);
+ return 0;
+ }
+ }
+ else
+ {// non-stackable
+ if( slots < amount )
+ {
+ script_pushint(st,0);
+ return 0;
+ }
+ }
+ break;
+ case ADDITEM_OVERAMOUNT:
+ script_pushint(st,0);
+ return 0;
}
return 0;
@@ -5390,8 +5653,8 @@ BUILDIN_FUNC(getitem2)
}
/*==========================================
- * rentitem <item id>
- * rentitem "<item name>"
+ * rentitem <item id>,<seconds>
+ * rentitem "<item name>",<seconds>
*------------------------------------------*/
BUILDIN_FUNC(rentitem)
{
@@ -5596,6 +5859,156 @@ BUILDIN_FUNC(makeitem)
return 0;
}
+
+/// Counts / deletes the current item given by idx.
+/// Used by buildin_delitem_search
+/// Relies on all input data being already fully valid.
+static void buildin_delitem_delete(struct map_session_data* sd, int idx, int* amount, bool delete_items)
+{
+ int delamount;
+ struct item* inv = &sd->status.inventory[idx];
+
+ delamount = ( amount[0] < inv->amount ) ? amount[0] : inv->amount;
+
+ if( delete_items )
+ {
+ if( sd->inventory_data[idx]->type == IT_PETEGG && inv->card[0] == CARD0_PET )
+ {// delete associated pet
+ intif_delete_petdata(MakeDWord(inv->card[1], inv->card[2]));
+ }
+
+ //Logs items, got from (N)PC scripts [Lupus]
+ if( log_config.enable_logs&0x40 )
+ {
+ log_pick_pc(sd, "N", inv->nameid, -delamount, inv);
+ }
+ //Logs
+
+ pc_delitem(sd, idx, delamount, 0, 0);
+ }
+
+ amount[0]-= delamount;
+}
+
+
+/// Searches for item(s) and checks, if there is enough of them.
+/// Used by delitem and delitem2
+/// Relies on all input data being already fully valid.
+/// @param exact_match will also match item attributes and cards, not just name id
+/// @return true when all items could be deleted, false when there were not enough items to delete
+static bool buildin_delitem_search(struct map_session_data* sd, struct item* it, bool exact_match)
+{
+ bool delete_items = false;
+ int i, amount, important;
+ struct item* inv;
+
+ // prefer always non-equipped items
+ it->equip = 0;
+
+ // when searching for nameid only, prefer additionally
+ if( !exact_match )
+ {
+ // non-refined items
+ it->refine = 0;
+ // card-less items
+ memset(it->card, 0, sizeof(it->card));
+ }
+
+ for(;;)
+ {
+ amount = it->amount;
+ important = 0;
+
+ // 1st pass -- less important items / exact match
+ for( i = 0; amount && i < ARRAYLENGTH(sd->status.inventory); i++ )
+ {
+ inv = &sd->status.inventory[i];
+
+ if( !inv->nameid || !sd->inventory_data[i] || inv->nameid != it->nameid )
+ {// wrong/invalid item
+ continue;
+ }
+
+ if( inv->equip != it->equip || inv->refine != it->refine )
+ {// not matching attributes
+ important++;
+ continue;
+ }
+
+ if( exact_match )
+ {
+ if( inv->identify != it->identify || inv->attribute != it->attribute || memcmp(inv->card, it->card, sizeof(inv->card)) )
+ {// not matching exact attributes
+ continue;
+ }
+ }
+ else
+ {
+ if( sd->inventory_data[i]->type == IT_PETEGG )
+ {
+ if( inv->card[0] == CARD0_PET && CheckForCharServer() )
+ {// pet which cannot be deleted
+ continue;
+ }
+ }
+ else if( memcmp(inv->card, it->card, sizeof(inv->card)) )
+ {// named/carded item
+ important++;
+ continue;
+ }
+ }
+
+ // count / delete item
+ buildin_delitem_delete(sd, i, &amount, delete_items);
+ }
+
+ // 2nd pass -- any matching item
+ if( amount == 0 || important == 0 )
+ {// either everything was already consumed or no items were skipped
+ ;
+ }
+ else for( i = 0; amount && i < ARRAYLENGTH(sd->status.inventory); i++ )
+ {
+ inv = &sd->status.inventory[i];
+
+ if( !inv->nameid || !sd->inventory_data[i] || inv->nameid != it->nameid )
+ {// wrong/invalid item
+ continue;
+ }
+
+ if( sd->inventory_data[i]->type == IT_PETEGG && inv->card[0] == CARD0_PET && CheckForCharServer() )
+ {// pet which cannot be deleted
+ continue;
+ }
+
+ if( exact_match )
+ {
+ if( inv->refine != it->refine || inv->identify != it->identify || inv->attribute != it->attribute || memcmp(inv->card, it->card, sizeof(inv->card)) )
+ {// not matching attributes
+ continue;
+ }
+ }
+
+ // count / delete item
+ buildin_delitem_delete(sd, i, &amount, delete_items);
+ }
+
+ if( amount )
+ {// not enough items
+ return false;
+ }
+ else if( delete_items )
+ {// we are done with the work
+ return true;
+ }
+ else
+ {// get rid of the items now
+ delete_items = true;
+ }
+ }
+}
+
+
/// Deletes items from the target/attached player.
/// Prioritizes ordinary items.
///
@@ -5603,8 +6016,8 @@ BUILDIN_FUNC(makeitem)
/// delitem "<item name>",<amount>{,<account id>}
BUILDIN_FUNC(delitem)
{
- int nameid=0,amount,i,important_item=0;
TBL_PC *sd;
+ struct item it;
struct script_data *data;
if( script_hasdata(st,4) )
@@ -5637,89 +6050,30 @@ BUILDIN_FUNC(delitem)
st->state = END;
return 1;
}
- nameid = id->nameid;// "<item name>"
+ it.nameid = id->nameid;// "<item name>"
}
else
- nameid = conv_num(st,data);// <item id>
-
- amount=script_getnum(st,3);
-
- if( amount <= 0 )
- return 0;// nothing to do
-
- //1st pass
- //here we won't delete items with CARDS, named items but we count them
- for(i=0;i<MAX_INVENTORY;i++){
- //we don't delete wrong item or equipped item
- if(sd->status.inventory[i].nameid<=0 || sd->inventory_data[i] == NULL ||
- sd->status.inventory[i].amount<=0 || sd->status.inventory[i].nameid!=nameid)
- continue;
- //1 egg uses 1 cell in the inventory. so it's ok to delete 1 pet / per cycle
- if(sd->inventory_data[i]->type==IT_PETEGG &&
- sd->status.inventory[i].card[0] == CARD0_PET)
+ {
+ it.nameid = conv_num(st,data);// <item id>
+ if( !itemdb_exists( it.nameid ) )
{
- if (!intif_delete_petdata(MakeDWord(sd->status.inventory[i].card[1], sd->status.inventory[i].card[2])))
- continue; //pet couldn't be sent for deletion.
- } else
- //is this item important? does it have cards? or Player's name? or Refined/Upgraded
- if(itemdb_isspecial(sd->status.inventory[i].card[0]) ||
- sd->status.inventory[i].card[0] ||
- sd->status.inventory[i].refine) {
- //this is important item, count it (except for pet eggs)
- if(sd->status.inventory[i].card[0] != CARD0_PET)
- important_item++;
- continue;
- }
-
- if(sd->status.inventory[i].amount>=amount){
-
- //Logs items, got from (N)PC scripts [Lupus]
- if(log_config.enable_logs&0x40)
- log_pick_pc(sd, "N", sd->status.inventory[i].nameid, -amount, &sd->status.inventory[i]);
-
- pc_delitem(sd,i,amount,0,0);
- return 0; //we deleted exact amount of items. now exit
- } else {
- amount-=sd->status.inventory[i].amount;
-
- //Logs items, got from (N)PC scripts [Lupus]
- if(log_config.enable_logs&0x40) {
- log_pick_pc(sd, "N", sd->status.inventory[i].nameid, -sd->status.inventory[i].amount, &sd->status.inventory[i]);
- }
- //Logs
-
- pc_delitem(sd,i,sd->status.inventory[i].amount,0,0);
+ ShowError("script:delitem: unknown item \"%d\".\n", it.nameid);
+ st->state = END;
+ return 1;
}
}
- //2nd pass
- //now if there WERE items with CARDs/REFINED/NAMED... and if we still have to delete some items. we'll delete them finally
- if (important_item>0 && amount>0)
- for(i=0;i<MAX_INVENTORY;i++){
- //we don't delete wrong item
- if(sd->status.inventory[i].nameid<=0 || sd->inventory_data[i] == NULL ||
- sd->status.inventory[i].amount<=0 || sd->status.inventory[i].nameid!=nameid )
- continue;
- if(sd->status.inventory[i].amount>=amount){
+ it.amount=script_getnum(st,3);
- //Logs items, got from (N)PC scripts [Lupus]
- if(log_config.enable_logs&0x40)
- log_pick_pc(sd, "N", sd->status.inventory[i].nameid, -amount, &sd->status.inventory[i]);
-
- pc_delitem(sd,i,amount,0,0);
- return 0; //we deleted exact amount of items. now exit
- } else {
- amount-=sd->status.inventory[i].amount;
-
- //Logs items, got from (N)PC scripts [Lupus]
- if(log_config.enable_logs&0x40)
- log_pick_pc(sd, "N", sd->status.inventory[i].nameid, -sd->status.inventory[i].amount, &sd->status.inventory[i]);
+ if( it.amount <= 0 )
+ return 0;// nothing to do
- pc_delitem(sd,i,sd->status.inventory[i].amount,0,0);
- }
- }
+ if( buildin_delitem_search(sd, &it, false) )
+ {// success
+ return 0;
+ }
- ShowError("script:delitem: failed to delete %d items (AID=%d item_id=%d).\n", amount, sd->status.account_id, nameid);
+ ShowError("script:delitem: failed to delete %d items (AID=%d item_id=%d).\n", it.amount, sd->status.account_id, it.nameid);
st->state = END;
clif_scriptclose(sd, st->oid);
return 1;
@@ -5731,9 +6085,8 @@ BUILDIN_FUNC(delitem)
/// delitem2 "<Item name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>}
BUILDIN_FUNC(delitem2)
{
- int nameid=0,amount,i=0;
- int iden,ref,attr,c1,c2,c3,c4;
TBL_PC *sd;
+ struct item it;
struct script_data *data;
if( script_hasdata(st,11) )
@@ -5766,59 +6119,37 @@ BUILDIN_FUNC(delitem2)
st->state = END;
return 1;
}
- nameid = id->nameid;// "<item name>"
+ it.nameid = id->nameid;// "<item name>"
}
else
- nameid = conv_num(st,data);// <item id>
-
- amount=script_getnum(st,3);
- iden=script_getnum(st,4);
- ref=script_getnum(st,5);
- attr=script_getnum(st,6);
- c1=(short)script_getnum(st,7);
- c2=(short)script_getnum(st,8);
- c3=(short)script_getnum(st,9);
- c4=(short)script_getnum(st,10);
-
- if( amount <= 0 )
- return 0;// nothing to do
-
- for(i=0;i<MAX_INVENTORY;i++){
- //we don't delete wrong item or equipped item
- if(sd->status.inventory[i].nameid<=0 || sd->inventory_data[i] == NULL ||
- sd->status.inventory[i].amount<=0 || sd->status.inventory[i].nameid!=nameid ||
- sd->status.inventory[i].identify!=iden || sd->status.inventory[i].refine!=ref ||
- sd->status.inventory[i].attribute!=attr || sd->status.inventory[i].card[0]!=c1 ||
- sd->status.inventory[i].card[1]!=c2 || sd->status.inventory[i].card[2]!=c3 ||
- sd->status.inventory[i].card[3]!=c4)
- continue;
- //1 egg uses 1 cell in the inventory. so it's ok to delete 1 pet / per cycle
- if(sd->inventory_data[i]->type==IT_PETEGG && sd->status.inventory[i].card[0] == CARD0_PET)
+ {
+ it.nameid = conv_num(st,data);// <item id>
+ if( !itemdb_exists( it.nameid ) )
{
- if (!intif_delete_petdata( MakeDWord(sd->status.inventory[i].card[1], sd->status.inventory[i].card[2])))
- continue; //Failed to send delete the pet.
+ ShowError("script:delitem: unknown item \"%d\".\n", it.nameid);
+ st->state = END;
+ return 1;
}
+ }
- if(sd->status.inventory[i].amount>=amount){
-
- //Logs items, got from (N)PC scripts [Lupus]
- if(log_config.enable_logs&0x40)
- log_pick_pc(sd, "N", sd->status.inventory[i].nameid, -amount, &sd->status.inventory[i]);
-
- pc_delitem(sd,i,amount,0,0);
- return 0; //we deleted exact amount of items. now exit
- } else {
- amount-=sd->status.inventory[i].amount;
+ it.amount=script_getnum(st,3);
+ it.identify=script_getnum(st,4);
+ it.refine=script_getnum(st,5);
+ it.attribute=script_getnum(st,6);
+ it.card[0]=(short)script_getnum(st,7);
+ it.card[1]=(short)script_getnum(st,8);
+ it.card[2]=(short)script_getnum(st,9);
+ it.card[3]=(short)script_getnum(st,10);
- //Logs items, got from (N)PC scripts [Lupus]
- if(log_config.enable_logs&0x40)
- log_pick_pc(sd, "N", sd->status.inventory[i].nameid, -sd->status.inventory[i].amount, &sd->status.inventory[i]);
+ if( it.amount <= 0 )
+ return 0;// nothing to do
- pc_delitem(sd,i,sd->status.inventory[i].amount,0,0);
- }
+ if( buildin_delitem_search(sd, &it, true) )
+ {// success
+ return 0;
}
- ShowError("script:delitem2: failed to delete %d items (AID=%d item_id=%d).\n", amount, sd->status.account_id, nameid);
+ ShowError("script:delitem2: failed to delete %d items (AID=%d item_id=%d).\n", it.amount, sd->status.account_id, it.nameid);
st->state = END;
clif_scriptclose(sd, st->oid);
return 1;
@@ -5904,34 +6235,21 @@ BUILDIN_FUNC(getcharid)
/*==========================================
*指定IDのPT名取得
*------------------------------------------*/
-char *buildin_getpartyname_sub(int party_id)
-{
- struct party_data *p;
-
- p=party_search(party_id);
-
- if(p!=NULL){
- char *buf;
- buf=(char *)aMallocA(NAME_LENGTH*sizeof(char));
- memcpy(buf, p->party.name, NAME_LENGTH);
- buf[NAME_LENGTH-1] = '\0';
- return buf;
- }
-
- return 0;
-}
BUILDIN_FUNC(getpartyname)
{
- char *name;
int party_id;
+ struct party_data* p;
- party_id=script_getnum(st,2);
- name=buildin_getpartyname_sub(party_id);
- if(name != NULL)
- script_pushstr(st,name);
+ party_id = script_getnum(st,2);
+
+ if( ( p = party_search(party_id) ) != NULL )
+ {
+ script_pushstrcopy(st,p->party.name);
+ }
else
+ {
script_pushconststr(st,"null");
-
+ }
return 0;
}
/*==========================================
@@ -5952,13 +6270,13 @@ BUILDIN_FUNC(getpartymember)
if(p->party.member[i].account_id){
switch (type) {
case 2:
- mapreg_setreg(add_str("$@partymemberaid")+(j<<24),p->party.member[i].account_id);
+ mapreg_setreg(reference_uid(add_str("$@partymemberaid"), j),p->party.member[i].account_id);
break;
case 1:
- mapreg_setreg(add_str("$@partymembercid")+(j<<24),p->party.member[i].char_id);
+ mapreg_setreg(reference_uid(add_str("$@partymembercid"), j),p->party.member[i].char_id);
break;
default:
- mapreg_setregstr(add_str("$@partymembername$")+(j<<24),p->party.member[i].name);
+ mapreg_setregstr(reference_uid(add_str("$@partymembername$"), j),p->party.member[i].name);
}
j++;
}
@@ -6009,75 +6327,58 @@ BUILDIN_FUNC(getpartyleader)
/*==========================================
*指定IDのギルド名取得
*------------------------------------------*/
-char *buildin_getguildname_sub(int guild_id)
+BUILDIN_FUNC(getguildname)
{
- struct guild *g=NULL;
- g=guild_search(guild_id);
+ int guild_id;
+ struct guild* g;
- if(g!=NULL){
- char *buf;
- buf=(char *)aMallocA(NAME_LENGTH*sizeof(char));
- memcpy(buf, g->name, NAME_LENGTH);
- buf[NAME_LENGTH-1] = '\0';
- return buf;
+ guild_id = script_getnum(st,2);
+
+ if( ( g = guild_search(guild_id) ) != NULL )
+ {
+ script_pushstrcopy(st,g->name);
}
- return NULL;
-}
-BUILDIN_FUNC(getguildname)
-{
- char *name;
- int guild_id=script_getnum(st,2);
- name=buildin_getguildname_sub(guild_id);
- if(name != NULL)
- script_pushstr(st,name);
else
+ {
script_pushconststr(st,"null");
+ }
return 0;
}
/*==========================================
*指定IDのGuildMaster名取得
*------------------------------------------*/
-char *buildin_getguildmaster_sub(int guild_id)
+BUILDIN_FUNC(getguildmaster)
{
- struct guild *g=NULL;
- g=guild_search(guild_id);
+ int guild_id;
+ struct guild* g;
- if(g!=NULL){
- char *buf;
- buf=(char *)aMallocA(NAME_LENGTH*sizeof(char));
- memcpy(buf, g->master, NAME_LENGTH);
- buf[NAME_LENGTH-1] = '\0';
- return buf;
- }
+ guild_id = script_getnum(st,2);
- return 0;
-}
-BUILDIN_FUNC(getguildmaster)
-{
- char *master;
- int guild_id=script_getnum(st,2);
- master=buildin_getguildmaster_sub(guild_id);
- if(master!=0)
- script_pushstr(st,master);
+ if( ( g = guild_search(guild_id) ) != NULL )
+ {
+ script_pushstrcopy(st,g->member[0].name);
+ }
else
+ {
script_pushconststr(st,"null");
+ }
return 0;
}
BUILDIN_FUNC(getguildmasterid)
{
- char *master;
- TBL_PC *sd=NULL;
- int guild_id=script_getnum(st,2);
- master=buildin_getguildmaster_sub(guild_id);
- if(master!=0){
- if((sd=map_nick2sd(master)) == NULL){
- script_pushint(st,0);
- return 0;
- }
- script_pushint(st,sd->status.char_id);
- }else{
+ int guild_id;
+ struct guild* g;
+
+ guild_id = script_getnum(st,2);
+
+ if( ( g = guild_search(guild_id) ) != NULL )
+ {
+ script_pushint(st,g->member[0].char_id);
+ }
+ else
+ {
script_pushint(st,0);
}
return 0;
@@ -6090,7 +6391,8 @@ BUILDIN_FUNC(strcharinfo)
{
TBL_PC *sd;
int num;
- char *buf;
+ struct guild* g;
+ struct party_data* p;
sd=script_rid2sd(st);
if (!sd) { //Avoid crashing....
@@ -6103,18 +6405,24 @@ BUILDIN_FUNC(strcharinfo)
script_pushstrcopy(st,sd->status.name);
break;
case 1:
- buf=buildin_getpartyname_sub(sd->status.party_id);
- if(buf!=0)
- script_pushstr(st,buf);
+ if( ( p = party_search(sd->status.party_id) ) != NULL )
+ {
+ script_pushstrcopy(st,p->party.name);
+ }
else
+ {
script_pushconststr(st,"");
+ }
break;
case 2:
- buf=buildin_getguildname_sub(sd->status.guild_id);
- if(buf != NULL)
- script_pushstr(st,buf);
+ if( ( g = guild_search(sd->status.guild_id) ) != NULL )
+ {
+ script_pushstrcopy(st,g->name);
+ }
else
+ {
script_pushconststr(st,"");
+ }
break;
case 3:
script_pushconststr(st,map[sd->bl.m].name);
@@ -7534,8 +7842,8 @@ BUILDIN_FUNC(getmobdrops)
if( itemdb_exists(mob->dropitem[i].nameid) == NULL )
continue;
- mapreg_setreg(add_str("$@MobDrop_item") + (j<<24), mob->dropitem[i].nameid);
- mapreg_setreg(add_str("$@MobDrop_rate") + (j<<24), mob->dropitem[i].p);
+ mapreg_setreg(reference_uid(add_str("$@MobDrop_item"), j), mob->dropitem[i].nameid);
+ mapreg_setreg(reference_uid(add_str("$@MobDrop_rate"), j), mob->dropitem[i].p);
j++;
}
@@ -7750,8 +8058,15 @@ BUILDIN_FUNC(clone)
BUILDIN_FUNC(doevent)
{
const char* event = script_getstr(st,2);
+ struct map_session_data* sd;
+
+ if( ( sd = script_rid2sd(st) ) == NULL )
+ {
+ return 0;
+ }
+
check_event(st, event);
- npc_event(map_id2sd(st->rid),event,0);
+ npc_event(sd, event, 0);
return 0;
}
/*==========================================
@@ -8226,18 +8541,18 @@ BUILDIN_FUNC(getusers)
flag = script_getnum(st,2);
- if(flag&0x8)
- {// npc
- bl = map_id2bl(st->oid);
- }
- else if((sd = script_rid2sd(st))!=NULL)
- {// pc
- bl = &sd->bl;
- }
-
switch(flag&0x07)
{
case 0:
+ if(flag&0x8)
+ {// npc
+ bl = map_id2bl(st->oid);
+ }
+ else if((sd = script_rid2sd(st))!=NULL)
+ {// pc
+ bl = &sd->bl;
+ }
+
if(bl)
{
val = map[bl->m].users;
@@ -8657,7 +8972,7 @@ BUILDIN_FUNC(homunculus_evolution)
if (sd->hd->homunculus.intimacy > 91000)
merc_hom_evolution(sd->hd);
else
- clif_emotion(&sd->hd->bl, 4) ; //swt
+ clif_emotion(&sd->hd->bl, E_SWT);
}
return 0;
}
@@ -9061,23 +9376,23 @@ BUILDIN_FUNC(warpwaitingpc)
if( sd == NULL )
{
ShowDebug("script:warpwaitingpc: no user in chat room position 0 (cd->users=%d,%d/%d)\n", cd->users, i, n);
- mapreg_setreg(add_str("$@warpwaitingpc")+(i<<24), 0);
+ mapreg_setreg(reference_uid(add_str("$@warpwaitingpc"), i), 0);
continue;// Broken npc chat room?
}
- mapreg_setreg(add_str("$@warpwaitingpc")+(i<<24), sd->bl.id);
+ mapreg_setreg(reference_uid(add_str("$@warpwaitingpc"), i), sd->bl.id);
if( strcmp(map_name,"Random") == 0 )
- pc_randomwarp(sd,3);
+ pc_randomwarp(sd,CLR_TELEPORT);
else if( strcmp(map_name,"SavePoint") == 0 )
{
if( map[sd->bl.m].flag.noteleport )
return 0;// can't teleport on this map
- pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, 3);
+ pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT);
}
else
- pc_setpos(sd, mapindex_name2id(map_name), x, y, 0);
+ pc_setpos(sd, mapindex_name2id(map_name), x, y, CLR_OUTSIGHT);
}
mapreg_setreg(add_str("$@warpwaitingpcnum"), i);
return 0;
@@ -9087,15 +9402,31 @@ BUILDIN_FUNC(warpwaitingpc)
// ...
//
+/// Detaches a character from a script.
+///
+/// @param st Script state to detach the character from.
+static void script_detach_rid(struct script_state* st)
+{
+ if(st->rid)
+ {
+ script_detach_state(st, false);
+ st->rid = 0;
+ }
+}
+
/*==========================================
* RIDのアタッチ
*------------------------------------------*/
BUILDIN_FUNC(attachrid)
{
int rid = script_getnum(st,2);
-
- if (map_id2sd(rid)) {
+ struct map_session_data* sd;
+
+ if ((sd = map_id2sd(rid))!=NULL) {
+ script_detach_rid(st);
+
st->rid = rid;
+ script_attach_state(st);
script_pushint(st,1);
} else
script_pushint(st,0);
@@ -9106,7 +9437,7 @@ BUILDIN_FUNC(attachrid)
*------------------------------------------*/
BUILDIN_FUNC(detachrid)
{
- st->rid=0;
+ script_detach_rid(st);
return 0;
}
/*==========================================
@@ -9495,7 +9826,7 @@ static int buildin_maprespawnguildid_sub_pc(struct map_session_data* sd, va_list
(sd->status.guild_id != g_id && flag&2) || //Warp out outsiders
(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);
+ pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT);
return 1;
}
@@ -9969,7 +10300,7 @@ BUILDIN_FUNC(mapwarp) // Added by RoVeRT
for( i=0; i < g->max_member; i++)
{
if(g->member[i].sd && g->member[i].sd->bl.m==m){
- pc_setpos(g->member[i].sd,index,x,y,3);
+ pc_setpos(g->member[i].sd,index,x,y,CLR_TELEPORT);
}
}
}
@@ -9979,7 +10310,7 @@ BUILDIN_FUNC(mapwarp) // Added by RoVeRT
if(p){
for(i=0;i<MAX_PARTY; i++){
if(p->data[i].sd && p->data[i].sd->bl.m == m){
- pc_setpos(p->data[i].sd,index,x,y,3);
+ pc_setpos(p->data[i].sd,index,x,y,CLR_TELEPORT);
}
}
}
@@ -10142,7 +10473,7 @@ BUILDIN_FUNC(warppartner)
mapindex = mapindex_name2id(str);
if (mapindex) {
- pc_setpos(p_sd,mapindex,x,y,0);
+ pc_setpos(p_sd,mapindex,x,y,CLR_OUTSIGHT);
script_pushint(st,1);
} else
script_pushint(st,0);
@@ -10356,7 +10687,7 @@ BUILDIN_FUNC(getitemslots)
2 type;
3 maxchance = Max drop chance of this item e.g. 1 = 0.01% , etc..
if = 0, then monsters don't drop it at all (rare or a quest item)
- if = 10000, then this item is sold in NPC shops only
+ if = -1, then this item is sold in NPC shops only
4 sex;
5 equip;
6 weight;
@@ -10396,7 +10727,7 @@ BUILDIN_FUNC(getiteminfo)
2 type;
3 maxchance = Max drop chance of this item e.g. 1 = 0.01% , etc..
if = 0, then monsters don't drop it at all (rare or a quest item)
- if = 10000, then this item is sold in NPC shops only
+ if = -1, then this item is sold in NPC shops only
4 sex;
5 equip;
6 weight;
@@ -10545,18 +10876,18 @@ BUILDIN_FUNC(getinventorylist)
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,reference_uid(add_str("@inventorylist_id"), j),sd->status.inventory[i].nameid);
+ pc_setreg(sd,reference_uid(add_str("@inventorylist_amount"), j),sd->status.inventory[i].amount);
+ pc_setreg(sd,reference_uid(add_str("@inventorylist_equip"), j),sd->status.inventory[i].equip);
+ pc_setreg(sd,reference_uid(add_str("@inventorylist_refine"), j),sd->status.inventory[i].refine);
+ pc_setreg(sd,reference_uid(add_str("@inventorylist_identify"), j),sd->status.inventory[i].identify);
+ pc_setreg(sd,reference_uid(add_str("@inventorylist_attribute"), j),sd->status.inventory[i].attribute);
for (k = 0; k < MAX_SLOTS; k++)
{
sprintf(card_var, "@inventorylist_card%d",k+1);
- pc_setreg(sd,add_str(card_var)+(j<<24),sd->status.inventory[i].card[k]);
+ pc_setreg(sd,reference_uid(add_str(card_var), j),sd->status.inventory[i].card[k]);
}
- pc_setreg(sd,add_str("@inventorylist_expire")+(j<<24),sd->status.inventory[i].expire_time);
+ pc_setreg(sd,reference_uid(add_str("@inventorylist_expire"), j),sd->status.inventory[i].expire_time);
j++;
}
}
@@ -10571,9 +10902,9 @@ BUILDIN_FUNC(getskilllist)
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].flag);
+ pc_setreg(sd,reference_uid(add_str("@skilllist_id"), j),sd->status.skill[i].id);
+ pc_setreg(sd,reference_uid(add_str("@skilllist_lv"), j),sd->status.skill[i].lv);
+ pc_setreg(sd,reference_uid(add_str("@skilllist_flag"), j),sd->status.skill[i].flag);
j++;
}
}
@@ -10665,11 +10996,11 @@ BUILDIN_FUNC(misceffect)
if(st->oid && st->oid != fake_nd->bl.id) {
struct block_list *bl = map_id2bl(st->oid);
if (bl)
- clif_misceffect2(bl,type);
+ clif_specialeffect(bl,type,AREA);
} else{
TBL_PC *sd=script_rid2sd(st);
if(sd)
- clif_misceffect2(&sd->bl,type);
+ clif_specialeffect(&sd->bl,type,AREA);
}
return 0;
}
@@ -10678,27 +11009,34 @@ BUILDIN_FUNC(misceffect)
*------------------------------------------*/
BUILDIN_FUNC(playBGM)
{
- TBL_PC* sd = script_rid2sd(st);
- const char* name = script_getstr(st,2);
+ const char* name;
+ struct map_session_data* sd;
- if(sd)
+ if( ( sd = script_rid2sd(st) ) != NULL )
{
- if(!st->rid)
- clif_playBGM(sd,map_id2bl(st->oid),name);
- else
- clif_playBGM(sd,&sd->bl,name);
+ name = script_getstr(st,2);
+
+ clif_playBGM(sd, name);
}
return 0;
}
-int playBGM_sub(struct block_list* bl,va_list ap)
+static int playBGM_sub(struct block_list* bl,va_list ap)
{
- char* name = va_arg(ap,char*);
+ const char* name = va_arg(ap,const char*);
- clif_playBGM((TBL_PC *)bl, bl, name);
+ clif_playBGM(BL_CAST(BL_PC, bl), name);
- return 0;
+ return 0;
+}
+
+static int playBGM_foreachpc_sub(struct map_session_data* sd, va_list args)
+{
+ const char* name = va_arg(args, const char*);
+
+ clif_playBGM(sd, name);
+ return 0;
}
/*==========================================
@@ -10706,33 +11044,29 @@ int playBGM_sub(struct block_list* bl,va_list ap)
*------------------------------------------*/
BUILDIN_FUNC(playBGMall)
{
- struct block_list* bl;
const char* name;
- bl = (st->rid) ? &(script_rid2sd(st)->bl) : map_id2bl(st->oid);
- if (!bl)
- return 0;
-
name = script_getstr(st,2);
- if(script_hasdata(st,7))
- { // specified part of map
+ if( script_hasdata(st,7) )
+ {// specified part of map
const char* map = script_getstr(st,3);
int x0 = script_getnum(st,4);
int y0 = script_getnum(st,5);
int x1 = script_getnum(st,6);
int y1 = script_getnum(st,7);
+
map_foreachinarea(playBGM_sub, map_mapname2mapid(map), x0, y0, x1, y1, BL_PC, name);
}
- else
- if(!script_hasdata(st,7))
- { // entire map
+ else if( script_hasdata(st,3) )
+ {// entire map
const char* map = script_getstr(st,3);
+
map_foreachinmap(playBGM_sub, map_mapname2mapid(map), BL_PC, name);
}
else
- {
- ShowError("buildin_playBGMall: insufficient arguments for specific area broadcast.\n");
+ {// entire server
+ map_foreachpc(&playBGM_foreachpc_sub, name);
}
return 0;
@@ -10749,10 +11083,7 @@ BUILDIN_FUNC(soundeffect)
if(sd)
{
- if(!st->rid)
- clif_soundeffect(sd,map_id2bl(st->oid),name,type);
- else
- clif_soundeffect(sd,&sd->bl,name,type);
+ clif_soundeffect(sd,&sd->bl,name,type);
}
return 0;
}
@@ -11702,7 +12033,7 @@ BUILDIN_FUNC(summon)
delete_timer(md->deletetimer, mob_timer_delete);
md->deletetimer = add_timer(tick+(timeout>0?timeout*1000:60000),mob_timer_delete,md->bl.id,0);
mob_spawn (md); //Now it is ready for spawning.
- clif_misceffect2(&md->bl,344);
+ clif_specialeffect(&md->bl,344,AREA);
sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000);
}
return 0;
@@ -11724,68 +12055,6 @@ BUILDIN_FUNC(isday)
}
/*================================================
- * Check whether another item/card has been
- * equipped - used for 2/15's cards patch [celest]
- *------------------------------------------------*/
-// leave this here, just in case
-#if 0
-BUILDIN_FUNC(isequipped)
-{
- TBL_PC *sd;
- int i, j, k, id = 1;
- int ret = -1;
-
- sd = script_rid2sd(st);
-
- for (i=0; id!=0; i++) {
- int flag = 0;
-
- FETCH (i+2, id) else id = 0;
- if (id <= 0)
- continue;
-
- for (j=0; j<EQI_MAX; j++) {
- int index;
- index = sd->equip_index[j];
- if(index < 0) continue;
- if(j == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) continue;
- if(j == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) continue;
- if(j == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) continue;
-
- if(!sd->inventory_data[index])
- continue;
-
- if(itemdb_type(id) != IT_CARD) { //Non card
- if (sd->inventory_data[index]->nameid != id)
- continue;
- flag = 1;
- break;
- } else { //Card
- if (itemdb_isspecial(sd->status.inventory[index].card[0]))
- continue;
- for(k=0; k<sd->inventory_data[index]->slot; k++) {
- if (sd->status.inventory[index].card[k] == id)
- {
- flag = 1;
- break;
- }
- }
- }
- if (flag) break;
- }
- if (ret == -1)
- ret = flag;
- else
- ret &= flag;
- if (!ret) break;
- }
-
- script_pushint(st,ret);
- return 0;
-}
-#endif
-
-/*================================================
* Check how many items/cards in the list are
* equipped - used for 2/15's cards patch [celest]
*------------------------------------------------*/
@@ -12051,7 +12320,7 @@ BUILDIN_FUNC(setbattleflag)
const char *flag, *value;
flag = script_getstr(st,2);
- value = script_getstr(st,3);
+ value = script_getstr(st,3); // HACK: Retrieve number as string (auto-converted) for battle_set_value
if (battle_set_value(flag, value) == 0)
ShowWarning("buildin_setbattleflag: unknown battle_config flag '%s'\n",flag);
@@ -12142,7 +12411,7 @@ BUILDIN_FUNC(setnpcdisplay)
if( newname )
npc_setdisplayname(nd, newname);
- if( size != -1 && size != nd->size )
+ if( size != -1 && size != (int)nd->size )
nd->size = size;
else
size = -1;
@@ -12151,7 +12420,7 @@ BUILDIN_FUNC(setnpcdisplay)
npc_setclass(nd, class_);
else if( size != -1 )
{ // Required to update the visual size
- clif_clearunit_area(&nd->bl, 0);
+ clif_clearunit_area(&nd->bl, CLR_OUTSIGHT);
clif_spawn(&nd->bl);
}
@@ -12231,10 +12500,9 @@ BUILDIN_FUNC(setd)
{
TBL_PC *sd=NULL;
char varname[100];
- const char *value, *buffer;
+ const char *buffer;
int elem;
buffer = script_getstr(st, 2);
- value = script_getstr(st, 3);
if(sscanf(buffer, "%99[^[][%d]", varname, &elem) < 2)
elem = 0;
@@ -12249,10 +12517,10 @@ BUILDIN_FUNC(setd)
}
}
- if(varname[strlen(varname)-1] != '$') {
- setd_sub(st,sd, varname, elem, (void *)atoi(value),NULL);
+ if( is_string_variable(varname) ) {
+ setd_sub(st, sd, varname, elem, (void *)script_getstr(st, 3), NULL);
} else {
- setd_sub(st,sd, varname, elem, (void *)value,NULL);
+ setd_sub(st, sd, varname, elem, (void *)script_getnum(st, 3), NULL);
}
return 0;
@@ -12266,7 +12534,7 @@ int buildin_query_sql_sub(struct script_state* st, Sql* handle)
const char* query;
struct script_data* data;
const char* name;
- int max_rows = 128;// maximum number of rows
+ int max_rows = SCRIPT_MAX_ARRAYSIZE;// maximum number of rows
int num_vars;
int num_cols;
@@ -12413,7 +12681,7 @@ BUILDIN_FUNC(getd)
elem = 0;
// Push the 'pointer' so it's more flexible [Lance]
- push_val(st->stack, C_NAME, (elem<<24) | add_str(varname));
+ push_val(st->stack, C_NAME, reference_uid(add_str(varname), elem));
return 0;
}
@@ -12548,6 +12816,7 @@ BUILDIN_FUNC(npcshopdelitem)
{
const char* npcname = script_getstr(st,2);
struct npc_data* nd = npc_name2id(npcname);
+ unsigned int nameid;
int n, i;
int amount;
int size;
@@ -12564,7 +12833,9 @@ BUILDIN_FUNC(npcshopdelitem)
// remove specified items from the shop item list
for( i = 3; i < 3 + amount; i++ )
{
- ARR_FIND( 0, size, n, nd->u.shop.shop_item[n].nameid == script_getnum(st,i) );
+ nameid = script_getnum(st,i);
+
+ ARR_FIND( 0, size, n, nd->u.shop.shop_item[n].nameid == nameid );
if( n < size )
{
memmove(&nd->u.shop.shop_item[n], &nd->u.shop.shop_item[n+1], sizeof(nd->u.shop.shop_item[0])*(size-n));
@@ -13016,7 +13287,7 @@ BUILDIN_FUNC(unitwarp)
bl = map_id2bl(unit_id);
if( map >= 0 && bl != NULL )
- script_pushint(st, unit_warp(bl,map,x,y,0));
+ script_pushint(st, unit_warp(bl,map,x,y,CLR_OUTSIGHT));
else
script_pushint(st, 0);
@@ -13212,17 +13483,11 @@ BUILDIN_FUNC(unitskillusepos)
BUILDIN_FUNC(sleep)
{
int ticks;
- TBL_PC* sd;
ticks = script_getnum(st,2);
- sd = map_id2sd(st->rid);
// detach the player
- if( sd && sd->npc_id == st->oid )
- {
- sd->npc_id = 0;
- }
- st->rid = 0;
+ script_detach_rid(st);
if( ticks <= 0 )
{// do nothing
@@ -13779,9 +14044,9 @@ BUILDIN_FUNC(waitingroom2bg)
for( i = 0; i < n && i < MAX_BG_MEMBERS; i++ )
{
if( (sd = cd->usersd[i]) != NULL && bg_team_join(bg_id, sd) )
- mapreg_setreg(add_str("$@arenamembers") + (i<<24), sd->bl.id);
+ mapreg_setreg(reference_uid(add_str("$@arenamembers"), i), sd->bl.id);
else
- mapreg_setreg(add_str("$@arenamembers") + (i<<24), 0);
+ mapreg_setreg(reference_uid(add_str("$@arenamembers"), i), 0);
}
mapreg_setreg(add_str("$@arenamembersnum"), i);
@@ -13814,7 +14079,7 @@ BUILDIN_FUNC(waitingroom2bg_single)
if( bg_team_join(bg_id, sd) )
{
- pc_setpos(sd, mapindex, x, y, 3);
+ pc_setpos(sd, mapindex, x, y, CLR_TELEPORT);
script_pushint(st,1);
}
else
@@ -14283,7 +14548,7 @@ BUILDIN_FUNC(instance_warpall)
mapindex = map_id2index(m);
for( i = 0; i < MAX_PARTY; i++ )
- if( (pl_sd = p->data[i].sd) && map[pl_sd->bl.m].instance_id == st->instance_id ) pc_setpos(pl_sd,mapindex,x,y,3);
+ if( (pl_sd = p->data[i].sd) && map[pl_sd->bl.m].instance_id == st->instance_id ) pc_setpos(pl_sd,mapindex,x,y,CLR_TELEPORT);
return 0;
}
@@ -14451,7 +14716,8 @@ BUILDIN_FUNC(deactivatepset);
BUILDIN_FUNC(deletepset);
#endif
-
+/// script command definitions
+/// for an explanation on args, see add_buildin_func
struct script_function buildin_func[] = {
// NPC interaction
BUILDIN_DEF(mes,"s"),
@@ -14463,21 +14729,21 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(prompt,"s*"),
//
BUILDIN_DEF(goto,"l"),
- BUILDIN_DEF(callsub,"i*"),
+ BUILDIN_DEF(callsub,"l*"),
BUILDIN_DEF(callfunc,"s*"),
BUILDIN_DEF(return,"?"),
BUILDIN_DEF(getarg,"i?"),
- BUILDIN_DEF(jobchange,"i*"),
+ BUILDIN_DEF(jobchange,"i?"),
BUILDIN_DEF(jobname,"i"),
- BUILDIN_DEF(input,"v??"),
+ BUILDIN_DEF(input,"r??"),
BUILDIN_DEF(warp,"sii"),
BUILDIN_DEF(areawarp,"siiiisii"),
BUILDIN_DEF(warpchar,"siii"), // [LuzZza]
- BUILDIN_DEF(warpparty,"siii*"), // [Fredzilla] [Paradox924X]
+ BUILDIN_DEF(warpparty,"siii?"), // [Fredzilla] [Paradox924X]
BUILDIN_DEF(warpguild,"siii"), // [Fredzilla]
BUILDIN_DEF(setlook,"ii"),
BUILDIN_DEF(changelook,"ii"), // Simulates but don't Store it
- BUILDIN_DEF(set,"ii"),
+ BUILDIN_DEF(set,"rv"),
BUILDIN_DEF(setarray,"rv*"),
BUILDIN_DEF(cleararray,"rvi"),
BUILDIN_DEF(copyarray,"rri"),
@@ -14486,12 +14752,12 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(getelementofarray,"ri"),
BUILDIN_DEF(getitem,"vi?"),
BUILDIN_DEF(rentitem,"vi"),
- BUILDIN_DEF(getitem2,"iiiiiiiii*"),
- BUILDIN_DEF(getnameditem,"is"),
+ BUILDIN_DEF(getitem2,"viiiiiiii?"),
+ BUILDIN_DEF(getnameditem,"vv"),
BUILDIN_DEF2(grouprandomitem,"groupranditem","i"),
- BUILDIN_DEF(makeitem,"iisii"),
- BUILDIN_DEF(delitem,"ii?"),
- BUILDIN_DEF(delitem2,"iiiiiiiii?"),
+ BUILDIN_DEF(makeitem,"visii"),
+ BUILDIN_DEF(delitem,"vi?"),
+ BUILDIN_DEF(delitem2,"viiiiiiii?"),
BUILDIN_DEF2(enableitemuse,"enable_items",""),
BUILDIN_DEF2(disableitemuse,"disable_items",""),
BUILDIN_DEF(cutin,"si"),
@@ -14500,13 +14766,13 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(itemheal,"ii"),
BUILDIN_DEF(percentheal,"ii"),
BUILDIN_DEF(rand,"i?"),
- BUILDIN_DEF(countitem,"i"),
- BUILDIN_DEF(countitem2,"iiiiiiii"),
- BUILDIN_DEF(checkweight,"ii"),
- BUILDIN_DEF(readparam,"i*"),
- BUILDIN_DEF(getcharid,"i*"),
+ BUILDIN_DEF(countitem,"v"),
+ BUILDIN_DEF(countitem2,"viiiiiii"),
+ BUILDIN_DEF(checkweight,"vi"),
+ BUILDIN_DEF(readparam,"i?"),
+ BUILDIN_DEF(getcharid,"i?"),
BUILDIN_DEF(getpartyname,"i"),
- BUILDIN_DEF(getpartymember,"i*"),
+ BUILDIN_DEF(getpartymember,"i?"),
BUILDIN_DEF(getpartyleader,"i?"),
BUILDIN_DEF(getguildname,"i"),
BUILDIN_DEF(getguildmaster,"i"),
@@ -14557,16 +14823,16 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(gettime,"i"),
BUILDIN_DEF(gettimestr,"si"),
BUILDIN_DEF(openstorage,""),
- BUILDIN_DEF(guildopenstorage,"*"),
+ BUILDIN_DEF(guildopenstorage,""),
BUILDIN_DEF(itemskill,"vi"),
BUILDIN_DEF(produce,"i"),
BUILDIN_DEF(cooking,"i"),
- BUILDIN_DEF(monster,"siisii*"),
+ BUILDIN_DEF(monster,"siisii?"),
BUILDIN_DEF(getmobdrops,"i"),
- BUILDIN_DEF(areamonster,"siiiisii*"),
+ BUILDIN_DEF(areamonster,"siiiisii?"),
BUILDIN_DEF(killmonster,"ss?"),
BUILDIN_DEF(killmonsterall,"s?"),
- BUILDIN_DEF(clone,"siisi*"),
+ BUILDIN_DEF(clone,"siisi????"),
BUILDIN_DEF(doevent,"s"),
BUILDIN_DEF(donpcevent,"s"),
BUILDIN_DEF(cmdothernpc,"ss"),
@@ -14581,14 +14847,14 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(attachnpctimer,"?"), // attached the player id to the npc timer [Celest]
BUILDIN_DEF(detachnpctimer,"?"), // detached the player id from the npc timer [Celest]
BUILDIN_DEF(playerattached,""), // returns id of the current attached player. [Skotlex]
- BUILDIN_DEF(announce,"si*"),
- BUILDIN_DEF(mapannounce,"ssi*"),
- BUILDIN_DEF(areaannounce,"siiiisi*"),
+ BUILDIN_DEF(announce,"si?????"),
+ BUILDIN_DEF(mapannounce,"ssi?????"),
+ BUILDIN_DEF(areaannounce,"siiiisi?????"),
BUILDIN_DEF(getusers,"i"),
BUILDIN_DEF(getmapguildusers,"si"),
BUILDIN_DEF(getmapusers,"s"),
BUILDIN_DEF(getareausers,"siiii"),
- BUILDIN_DEF(getareadropitem,"siiiii"),
+ BUILDIN_DEF(getareadropitem,"siiiiv"),
BUILDIN_DEF(enablenpc,"s"),
BUILDIN_DEF(disablenpc,"s"),
BUILDIN_DEF(hideoffnpc,"s"),
@@ -14597,7 +14863,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(sc_start2,"iiii?"),
BUILDIN_DEF(sc_start4,"iiiiii?"),
BUILDIN_DEF(sc_end,"i?"),
- BUILDIN_DEF(getscrate,"ii*"),
+ BUILDIN_DEF(getscrate,"ii?"),
BUILDIN_DEF(debugmes,"s"),
BUILDIN_DEF2(catchpet,"pet","i"),
BUILDIN_DEF2(birthpet,"bpet",""),
@@ -14605,7 +14871,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(resetstatus,""),
BUILDIN_DEF(resetskill,""),
BUILDIN_DEF(skillpointcount,""),
- BUILDIN_DEF(changebase,"i"),
+ BUILDIN_DEF(changebase,"i?"),
BUILDIN_DEF(changesex,""),
BUILDIN_DEF(waitingroom,"si??"),
BUILDIN_DEF(delwaitingroom,"?"),
@@ -14621,22 +14887,22 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(isloggedin,"i?"),
BUILDIN_DEF(setmapflagnosave,"ssii"),
BUILDIN_DEF(getmapflag,"si"),
- BUILDIN_DEF(setmapflag,"si*"),
+ BUILDIN_DEF(setmapflag,"si?"),
BUILDIN_DEF(removemapflag,"si"),
BUILDIN_DEF(pvpon,"s"),
BUILDIN_DEF(pvpoff,"s"),
BUILDIN_DEF(gvgon,"s"),
BUILDIN_DEF(gvgoff,"s"),
- BUILDIN_DEF(emotion,"i*"),
+ BUILDIN_DEF(emotion,"i??"),
BUILDIN_DEF(maprespawnguildid,"sii"),
BUILDIN_DEF(agitstart,""), // <Agit>
BUILDIN_DEF(agitend,""),
BUILDIN_DEF(agitcheck,""), // <Agitcheck>
BUILDIN_DEF(flagemblem,"i"), // Flag Emblem
BUILDIN_DEF(getcastlename,"s"),
- BUILDIN_DEF(getcastledata,"si*"),
+ BUILDIN_DEF(getcastledata,"si?"),
BUILDIN_DEF(setcastledata,"sii"),
- BUILDIN_DEF(requestguildinfo,"i*"),
+ BUILDIN_DEF(requestguildinfo,"i?"),
BUILDIN_DEF(getequipcardcnt,"i"),
BUILDIN_DEF(successremovecards,"i"),
BUILDIN_DEF(failedremovecards,"ii"),
@@ -14649,7 +14915,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(getmotherid,""),
BUILDIN_DEF(getfatherid,""),
BUILDIN_DEF(warppartner,"sii"),
- BUILDIN_DEF(getitemname,"i"),
+ BUILDIN_DEF(getitemname,"v"),
BUILDIN_DEF(getitemslots,"i"),
BUILDIN_DEF(makepet,"i"),
BUILDIN_DEF(getexp,"ii"),
@@ -14659,9 +14925,9 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(classchange,"ii"),
BUILDIN_DEF(misceffect,"i"),
BUILDIN_DEF(playBGM,"s"),
- BUILDIN_DEF(playBGMall,"s*"),
+ BUILDIN_DEF(playBGMall,"s?????"),
BUILDIN_DEF(soundeffect,"si"),
- BUILDIN_DEF(soundeffectall,"si*"), // SoundEffectAll [Codemaster]
+ BUILDIN_DEF(soundeffectall,"si?????"), // SoundEffectAll [Codemaster]
BUILDIN_DEF(strmobinfo,"ii"), // display mob data [Valaris]
BUILDIN_DEF(guardian,"siisi??"), // summon guardians
BUILDIN_DEF(guardianinfo,"sii"), // display guardian data [Valaris]
@@ -14674,34 +14940,34 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(petskillsupport,"viiii"), // [Skotlex]
BUILDIN_DEF(skilleffect,"vi"), // skill effect [Celest]
BUILDIN_DEF(npcskilleffect,"viii"), // npc skill effect [Valaris]
- BUILDIN_DEF(specialeffect,"i*"), // npc skill effect [Valaris]
- BUILDIN_DEF(specialeffect2,"i*"), // skill effect on players[Valaris]
+ BUILDIN_DEF(specialeffect,"i??"), // npc skill effect [Valaris]
+ BUILDIN_DEF(specialeffect2,"i??"), // skill effect on players[Valaris]
BUILDIN_DEF(nude,""), // nude command [Valaris]
- BUILDIN_DEF(mapwarp,"ssii*"), // Added by RoVeRT
- BUILDIN_DEF(atcommand,"*"), // [MouseJstr]
- BUILDIN_DEF(charcommand,"*"), // [MouseJstr]
+ BUILDIN_DEF(mapwarp,"ssii??"), // Added by RoVeRT
+ BUILDIN_DEF(atcommand,"s"), // [MouseJstr]
+ BUILDIN_DEF(charcommand,"s"), // [MouseJstr]
BUILDIN_DEF(movenpc,"sii"), // [MouseJstr]
- BUILDIN_DEF(message,"s*"), // [MouseJstr]
- BUILDIN_DEF(npctalk,"*"), // [Valaris]
+ BUILDIN_DEF(message,"ss"), // [MouseJstr]
+ BUILDIN_DEF(npctalk,"s"), // [Valaris]
BUILDIN_DEF(mobcount,"ss"),
BUILDIN_DEF(getlook,"i"),
BUILDIN_DEF(getsavepoint,"i"),
BUILDIN_DEF(npcspeed,"i"), // [Valaris]
BUILDIN_DEF(npcwalkto,"ii"), // [Valaris]
BUILDIN_DEF(npcstop,""), // [Valaris]
- BUILDIN_DEF(getmapxy,"siii*"), //by Lorky [Lupus]
+ BUILDIN_DEF(getmapxy,"rrri?"), //by Lorky [Lupus]
BUILDIN_DEF(checkoption1,"i"),
BUILDIN_DEF(checkoption2,"i"),
BUILDIN_DEF(guildgetexp,"i"),
BUILDIN_DEF(guildchangegm,"is"),
BUILDIN_DEF(logmes,"s"), //this command actls as MES but rints info into LOG file either SQL/TXT [Lupus]
- BUILDIN_DEF(summon,"si*"), // summons a slave monster [Celest]
+ BUILDIN_DEF(summon,"si??"), // summons a slave monster [Celest]
BUILDIN_DEF(isnight,""), // check whether it is night time [Celest]
BUILDIN_DEF(isday,""), // check whether it is day time [Celest]
BUILDIN_DEF(isequipped,"i*"), // check whether another item/card has been equipped [Celest]
BUILDIN_DEF(isequippedcnt,"i*"), // check how many items/cards are being equipped [Celest]
BUILDIN_DEF(cardscnt,"i*"), // check how many items/cards are being equipped in the same arm [Lupus]
- BUILDIN_DEF(getrefine,"*"), // returns the refined number of the current item, or an item with index specified [celest]
+ BUILDIN_DEF(getrefine,""), // returns the refined number of the current item, or an item with index specified [celest]
BUILDIN_DEF(night,""), // sets the server to night time
BUILDIN_DEF(day,""), // sets the server to day time
#ifdef PCRE_SUPPORT
@@ -14711,13 +14977,13 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(deletepset,"i"), // Delete a pattern set [MouseJstr]
#endif
BUILDIN_DEF(dispbottom,"s"), //added from jA [Lupus]
- BUILDIN_DEF(getusersname,"*"),
+ BUILDIN_DEF(getusersname,""),
BUILDIN_DEF(recovery,""),
BUILDIN_DEF(getpetinfo,"i"),
BUILDIN_DEF(gethominfo,"i"),
BUILDIN_DEF(checkequipedcard,"i"),
- BUILDIN_DEF(jump_zero,"ii"), //for future jA script compatibility
- BUILDIN_DEF(globalmes,"s*"),
+ BUILDIN_DEF(jump_zero,"il"), //for future jA script compatibility
+ BUILDIN_DEF(globalmes,"s?"),
BUILDIN_DEF(getmapmobs,"s"), //end jA addition
BUILDIN_DEF(unequip,"i"), // unequip command [Spectre]
BUILDIN_DEF(getstrlen,"s"), //strlen [Valaris]
@@ -14734,22 +15000,22 @@ struct script_function buildin_func[] = {
// <--- [zBuffer] List of mathematics commands
BUILDIN_DEF(md5,"s"),
// [zBuffer] List of dynamic var commands --->
- BUILDIN_DEF(getd,"*"),
- BUILDIN_DEF(setd,"*"),
+ BUILDIN_DEF(getd,"s"),
+ BUILDIN_DEF(setd,"sv"),
// <--- [zBuffer] List of dynamic var commands
BUILDIN_DEF(petstat,"i"),
- BUILDIN_DEF(callshop,"si"), // [Skotlex]
+ BUILDIN_DEF(callshop,"s?"), // [Skotlex]
BUILDIN_DEF(npcshopitem,"sii*"), // [Lance]
BUILDIN_DEF(npcshopadditem,"sii*"),
BUILDIN_DEF(npcshopdelitem,"si*"),
BUILDIN_DEF(npcshopattach,"s?"),
BUILDIN_DEF(equip,"i"),
BUILDIN_DEF(autoequip,"ii"),
- BUILDIN_DEF(setbattleflag,"ss"),
+ BUILDIN_DEF(setbattleflag,"si"),
BUILDIN_DEF(getbattleflag,"s"),
- BUILDIN_DEF(setitemscript,"is*"), //Set NEW item bonus script. Lupus
+ BUILDIN_DEF(setitemscript,"is?"), //Set NEW item bonus script. Lupus
BUILDIN_DEF(disguise,"i"), //disguise player. Lupus
- BUILDIN_DEF(undisguise,"*"), //undisguise player. Lupus
+ BUILDIN_DEF(undisguise,""), //undisguise player. Lupus
BUILDIN_DEF(getmonsterinfo,"ii"), //Lupus
BUILDIN_DEF(axtoi,"s"),
BUILDIN_DEF(query_sql,"s*"),
@@ -14780,10 +15046,10 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(warpportal,"iisii"),
BUILDIN_DEF2(homunculus_evolution,"homevolution",""), //[orn]
BUILDIN_DEF2(homunculus_shuffle,"homshuffle",""), //[Zephyrus]
- BUILDIN_DEF(eaclass,"*"), //[Skotlex]
- BUILDIN_DEF(roclass,"i*"), //[Skotlex]
- BUILDIN_DEF(checkvending,"*"),
- BUILDIN_DEF(checkchatting,"*"),
+ BUILDIN_DEF(eaclass,"?"), //[Skotlex]
+ BUILDIN_DEF(roclass,"i?"), //[Skotlex]
+ BUILDIN_DEF(checkvending,"?"),
+ BUILDIN_DEF(checkchatting,"?"),
BUILDIN_DEF(openmail,""),
BUILDIN_DEF(openauction,""),
BUILDIN_DEF(checkcell,"siii"),
@@ -14801,7 +15067,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(readbook,"ii"),
BUILDIN_DEF(setfont,"i"),
BUILDIN_DEF(areamobuseskill,"siiiiviiiii"),
- BUILDIN_DEF(progressbar, "si"),
+ BUILDIN_DEF(progressbar,"si"),
BUILDIN_DEF(pushpc,"ii"),
// WoE SE
BUILDIN_DEF(agitstart2,""),
@@ -14812,7 +15078,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(waitingroom2bg_single,"isiis"),
BUILDIN_DEF(bg_team_setxy,"iii"),
BUILDIN_DEF(bg_warp,"isii"),
- BUILDIN_DEF(bg_monster,"isiisi*"),
+ BUILDIN_DEF(bg_monster,"isiisi?"),
BUILDIN_DEF(bg_monster_set_team,"ii"),
BUILDIN_DEF(bg_leave,""),
BUILDIN_DEF(bg_destroy,"i"),
@@ -14830,7 +15096,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(instance_id,"?"),
BUILDIN_DEF(instance_set_timeout,"ii?"),
BUILDIN_DEF(instance_init,"i"),
- BUILDIN_DEF(instance_announce,"isi*"),
+ BUILDIN_DEF(instance_announce,"isi?????"),
BUILDIN_DEF(instance_npcname,"s?"),
BUILDIN_DEF(has_instance,"s?"),
BUILDIN_DEF(instance_warpall,"sii?"),
@@ -14839,7 +15105,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(setquest, "i"),
BUILDIN_DEF(erasequest, "i"),
BUILDIN_DEF(completequest, "i"),
- BUILDIN_DEF(checkquest, "i*"),
+ BUILDIN_DEF(checkquest, "i?"),
BUILDIN_DEF(changequest, "ii"),
BUILDIN_DEF(showevent, "ii"),
{NULL,NULL,NULL},