summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt1
-rw-r--r--db/const.txt11
-rw-r--r--npc/sample/monster_controller.cpp33
-rw-r--r--src/map/battle.c18
-rw-r--r--src/map/clif.c4
-rw-r--r--src/map/mob.c79
-rw-r--r--src/map/mob.h1
-rw-r--r--src/map/npc.c4
-rw-r--r--src/map/script.c90
-rw-r--r--src/map/script.h2
10 files changed, 167 insertions, 76 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index 2db105c3b..80314a053 100644
--- a/Changelog-Trunk.txt
+++ b/Changelog-Trunk.txt
@@ -4,6 +4,7 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2006/05/26
+ * Mob control engine tested 99% working so far. [Lance]
* Change scripting engine's NPC scope vars to dot (.) style.
* Improved and (should be fully) fixed the mob control engine. [Lance]
* Fixed typos in char.c [Lance]
diff --git a/db/const.txt b/db/const.txt
index 5b41f0376..07895eb30 100644
--- a/db/const.txt
+++ b/db/const.txt
@@ -698,6 +698,17 @@ MOB_RACE 19
MOB_ELEMENT 20
MOB_MODE 21
+AI_ACTION_TYPE 0
+AI_ACTION_TAR_TYPE 1
+AI_ACTION_TAR 2
+AI_ACTION_SRC 3
+AI_ACTION_TAR_TYPE_PC 1
+AI_ACTION_TAR_TYPE_MOB 2
+AI_ACTION_TAR_TYPE_PET 4
+AI_ACTION_TAR_TYPE_HOMUN 8
+AI_ACTION_TYPE_ATTACK 1
+AI_ACTION_TYPE_DETECT 2
+
ALL_CLIENT 0
ALL_SAMEMAP 1
AREA 2
diff --git a/npc/sample/monster_controller.cpp b/npc/sample/monster_controller.cpp
index 58b5693a8..479320f2f 100644
--- a/npc/sample/monster_controller.cpp
+++ b/npc/sample/monster_controller.cpp
@@ -44,6 +44,39 @@ prontera.gat,180,200,4 script Monster Controller 123,{
return;
}
+ if(getarraysize(.ai_action) == 4){
+ announce "[Mob Control] AI Action Received from " + .ai_action[AI_ACTION_SRC] + "!",bc_all;
+ switch(.ai_action[AI_ACTION_TAR_TYPE]){
+ case AI_ACTION_TAR_TYPE_PC:
+ set .@action_from$, "Player";
+ set .@action_name$, rid2name(.ai_action[AI_ACTION_TAR]);
+ break;
+ case AI_ACTION_TAR_TYPE_MOB:
+ set .@action_from$, "Monster";
+ set .@action_name$, ""+.ai_action[AI_ACTION_TAR];
+ break;
+ case AI_ACTION_TAR_TYPE_PET:
+ set .@action_from$, "Pet";
+ set .@action_name$, ""+.ai_action[AI_ACTION_TAR];
+ break;
+ case AI_ACTION_TAR_TYPE_HOMUN:
+ set .@action_from$, "Homunculus";
+ set .@action_name$, ""+.ai_action[AI_ACTION_TAR];
+ break;
+ default:
+ set .@action_from$, "Unknown";
+ set .@action_name$, ""+.ai_action[AI_ACTION_TAR];
+ break;
+ }
+ if(.ai_action[AI_ACTION_TYPE] == AI_ACTION_TYPE_ATTACK)
+ set .@action_type$, "attacked by";
+ else
+ set .@action_type$, "detected";
+ announce "Action " + .@action_type$ + " [" + .@action_from$ + "] " + .@action_name$ + "!", bc_all;
+ deletearray .ai_action, 4;
+ end;
+ }
+
L_MainMenu:
mes "[Monster Controller]";
mes "Current active monsters:";
diff --git a/src/map/battle.c b/src/map/battle.c
index a263d4874..9bbcce01e 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -3426,8 +3426,24 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
case BL_MOB:
{
TBL_MOB*md = (TBL_MOB*)s_bl;
- if(md->state.killer) // Is on a rampage too :D
+ if(md->state.killer){ // Is on a rampage too :D
+ switch(t_bl->type){
+ case BL_MOB:
+ if(md->master_id != 0 && ((TBL_MOB *)t_bl)->master_id == md->master_id)
+ state |= BCT_PARTY;
+ break;
+ case BL_PC:
+ if(t_bl->id == md->master_id)
+ state |= BCT_PARTY;
+ break;
+ case BL_PET:
+ if(((TBL_PET *)t_bl)->msd->bl.id == md->master_id)
+ state |= BCT_PARTY;
+ break;
+ }
state |= BCT_ENEMY;
+ break;
+ }
if (!agit_flag && md->guardian_data && md->guardian_data->guild_id)
return 0; //Disable guardians/emperium owned by Guilds on non-woe times.
if (!md->special_state.ai) { //Normal mobs.
diff --git a/src/map/clif.c b/src/map/clif.c
index c67321d3c..a4b7ea2f2 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -9386,8 +9386,8 @@ void clif_parse_NpcBuyListSend(int fd,struct map_session_data *sd)
if((nd = ((struct npc_data *)map_id2bl(sd->npc_shopid))->master_nd)){
sprintf(npc_ev, "%s::OnBuyItem", nd->exname);
for(i=0;i<n;i++){
- setd_sub(NULL,sd, "@bought_nameid", i, (void *)((int)item_list[i*2+1]));
- setd_sub(NULL,sd, "@bought_quantity", i, (void *)((int)item_list[i*2]));
+ setd_sub(NULL,sd, "@bought_nameid", i, (void *)((int)item_list[i*2+1]),NULL);
+ setd_sub(NULL,sd, "@bought_quantity", i, (void *)((int)item_list[i*2]),NULL);
}
npc_event(sd, npc_ev, 0);
fail = 0;
diff --git a/src/map/mob.c b/src/map/mob.c
index 3fbe92375..7761e3db9 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -799,7 +799,19 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap)
target= va_arg(ap,struct block_list**);
//If can't seek yet, not an enemy, or you can't attack it, skip.
- if ((*target) == bl || battle_check_target(&md->bl,bl,BCT_ENEMY)<=0 || !status_check_skilluse(&md->bl, bl, 0, 0))
+ if ((*target) == bl || !status_check_skilluse(&md->bl, bl, 0, 0))
+ return 0;
+
+ if(md->nd){
+ setd_sub(NULL, NULL, ".ai_action", 0, (void *)(int)2, &md->nd->u.scr.script->script_vars);
+ setd_sub(NULL, NULL, ".ai_action", 1, (void *)(int)bl->type, &md->nd->u.scr.script->script_vars);
+ setd_sub(NULL, NULL, ".ai_action", 2, (void *)bl->id, &md->nd->u.scr.script->script_vars);
+ setd_sub(NULL, NULL, ".ai_action", 3, (void *)md->bl.id, &md->nd->u.scr.script->script_vars);
+ run_script(md->nd->u.scr.script, 0, 0, md->nd->bl.id);
+ return 0; // We have script handling the work.
+ }
+
+ if(battle_check_target(&md->bl,bl,BCT_ENEMY)<=0)
return 0;
switch (bl->type)
@@ -906,9 +918,6 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick)
return 0;
}
- if(bl->type == BL_MOB && ((TBL_MOB *)bl)->master_id && ((TBL_MOB *)bl)->master_id != md->master_id) // Just in case something screws up
- md->master_id = ((TBL_MOB *)bl)->master_id;
-
if(status_get_mode(&md->bl)&MD_CANMOVE)
{ //If the mob can move, follow around. [Check by Skotlex]
@@ -1320,7 +1329,7 @@ static int mob_ai_sub_lazy(DBKey key,void * data,va_list app)
ap = va_arg(app, va_list);
- if (battle_config.mob_ai&32 && map[md->bl.m].users>0)
+ if (md->nd || (battle_config.mob_ai&32 && map[md->bl.m].users>0))
return mob_ai_sub_hard(&md->bl, ap);
tick=va_arg(ap,unsigned int);
@@ -1494,39 +1503,49 @@ int mob_timer_delete(int tid, unsigned int tick, int id, int data)
return 0;
}
-/*==========================================
- *
- *------------------------------------------
- */
-int mob_deleteslave_sub(struct block_list *bl,va_list ap)
+int mob_convertslave_sub(struct block_list *bl,va_list ap)
{
- struct mob_data *md;
- int id;
+ struct mob_data *md, *md2 = NULL;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, md = (struct mob_data *)bl);
- id=va_arg(ap,int);
- if(md->master_id > 0 && md->master_id == id )
- mob_damage(NULL,md,md->hp,1);
+ md2=va_arg(ap,TBL_MOB *);
+
+ if(md->master_id > 0 && md->master_id == md2->bl.id){
+ md->master_id = md2->master_id;
+ md->state.killer = md2->state.killer;
+ md->special_state.ai = md2->special_state.ai;
+ }
+
return 0;
}
-int mob_convertslave_sub(struct block_list *bl,va_list ap)
+int mob_convertslave(struct mob_data *md)
+{
+ nullpo_retr(0, md);
+
+ map_foreachinmap(mob_convertslave_sub, md->bl.m, BL_MOB, md);
+ return 0;
+}
+
+/*==========================================
+ *
+ *------------------------------------------
+ */
+int mob_deleteslave_sub(struct block_list *bl,va_list ap)
{
struct mob_data *md;
- int id, master;
+ int id;
nullpo_retr(0, bl);
nullpo_retr(0, ap);
nullpo_retr(0, md = (struct mob_data *)bl);
id=va_arg(ap,int);
- master=va_arg(ap,int);
-
if(md->master_id > 0 && md->master_id == id )
- md->master_id = master;
+ mob_damage(NULL,md,md->hp,1);
return 0;
}
/*==========================================
@@ -1540,14 +1559,6 @@ int mob_deleteslave(struct mob_data *md)
map_foreachinmap(mob_deleteslave_sub, md->bl.m, BL_MOB,md->bl.id);
return 0;
}
-
-int mob_convertslave(struct mob_data *md)
-{
- nullpo_retr(0, md);
-
- map_foreachinmap(mob_convertslave_sub, md->bl.m, BL_MOB,md->bl.id,md->master_id);
- return 0;
-}
// Mob respawning through KAIZEL or NPC_REBIRTH [Skotlex]
int mob_respawn(int tid, unsigned int tick, int id,int data )
{
@@ -1592,7 +1603,6 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
int ret, mode;
int drop_rate;
int race;
- char buffer[64];
nullpo_retr(0, md); //srcはNULLで呼ばれる場合もあるので、他でチェック
@@ -1601,12 +1611,11 @@ int mob_damage(struct block_list *src,struct mob_data *md,int damage,int type)
if(src){
if(md->nd){
- sprintf(buffer, "$@%d_attacker", md->bl.id);
- set_var(NULL, buffer, (void *)src->id);
- sprintf(buffer, "$@%d_attacktype", md->bl.id);
- set_var(NULL, buffer, (void *)(int)src->type);
- sprintf(buffer, "%s::OnDamage", md->nd->exname);
- npc_event_do(buffer);
+ setd_sub(NULL, NULL, ".ai_action", 0, (void *)(int)1, &md->nd->u.scr.script->script_vars);
+ setd_sub(NULL, NULL, ".ai_action", 1, (void *)(int)src->type, &md->nd->u.scr.script->script_vars);
+ setd_sub(NULL, NULL, ".ai_action", 2, (void *)src->id, &md->nd->u.scr.script->script_vars);
+ setd_sub(NULL, NULL, ".ai_action", 3, (void *)md->bl.id, &md->nd->u.scr.script->script_vars);
+ run_script(md->nd->u.scr.script, 0, 0, md->nd->bl.id);
}
if(src->type == BL_PC) {
sd = (struct map_session_data *)src;
diff --git a/src/map/mob.h b/src/map/mob.h
index 3eea67ec4..fcd0ac6f5 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -175,6 +175,7 @@ int mobskill_castend_id( int tid, unsigned int tick, int id,int data );
int mobskill_castend_pos( int tid, unsigned int tick, int id,int data );
int mob_summonslave(struct mob_data *md2,int *value,int amount,int skill_id);
int mob_countslave(struct block_list *bl);
+int mob_convertslave(struct mob_data *md);
int mob_is_clone(int class_);
diff --git a/src/map/npc.c b/src/map/npc.c
index 37e47585c..616042811 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -1268,8 +1268,8 @@ int npc_selllist(struct map_session_data *sd,int n,unsigned short *item_list)
log_pick(sd, "S", 0, nameid, qty, &sd->status.inventory[idx]);
if(nd) {
- setd_sub(NULL,sd, "@sold_nameid", i, (void *)(int)sd->status.inventory[idx].nameid);
- setd_sub(NULL,sd, "@sold_quantity", i, (void *)(int)qty);
+ setd_sub(NULL,sd, "@sold_nameid", i, (void *)(int)sd->status.inventory[idx].nameid,NULL);
+ setd_sub(NULL,sd, "@sold_quantity", i, (void *)(int)qty,NULL);
}
itemamount+=qty;
pc_delitem(sd,idx,qty,0);
diff --git a/src/map/script.c b/src/map/script.c
index 88d4ef9e7..04f5532cc 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -9910,9 +9910,9 @@ int buildin_distance(struct script_state *st){
// <--- [zBuffer] List of mathematics commands
// [zBuffer] List of dynamic var commands --->
-void setd_sub(struct script_state *st, struct map_session_data *sd, char *varname, int elem, void *value)
+void setd_sub(struct script_state *st, struct map_session_data *sd, char *varname, int elem, void *value, struct linkdb_node **ref)
{
- set_reg(st, sd, add_str((unsigned char *) varname)+(elem<<24), varname, value,NULL);
+ set_reg(st, sd, add_str((unsigned char *) varname)+(elem<<24), varname, value, ref);
return;
}
@@ -9932,9 +9932,9 @@ int buildin_setd(struct script_state *st)
sd = script_rid2sd(st);
if(varname[strlen(varname)-1] != '$') {
- setd_sub(st,sd, varname, elem, (void *)atoi(value));
+ setd_sub(st,sd, varname, elem, (void *)atoi(value),NULL);
} else {
- setd_sub(st,sd, varname, elem, (void *)value);
+ setd_sub(st,sd, varname, elem, (void *)value,NULL);
}
return 0;
@@ -9963,12 +9963,12 @@ int buildin_query_sql(struct script_state *st) {
if((sql_res = mysql_store_result(&mmysql_handle))){
if(name[strlen(name)-1] != '$') {
while(i<128 && (sql_row = mysql_fetch_row(sql_res))){
- setd_sub(st,sd, name, i, (void *)atoi(sql_row[0]));
+ setd_sub(st,sd, name, i, (void *)atoi(sql_row[0]),NULL);
i++;
}
} else {
while(i<128 && (sql_row = mysql_fetch_row(sql_res))){
- setd_sub(st,sd, name, i, (void *)sql_row[0]);
+ setd_sub(st,sd, name, i, (void *)sql_row[0],NULL);
i++;
}
}
@@ -10298,13 +10298,13 @@ int buildin_rid2name(struct script_state *st){
if((bl = map_id2bl(rid))){
switch(bl->type){
case BL_MOB:
- push_str(st->stack,C_STR,((struct mob_data *)bl)->name);
+ push_str(st->stack,C_CONSTSTR,((struct mob_data *)bl)->name);
break;
case BL_PC:
- push_str(st->stack,C_STR,((struct map_session_data *)bl)->status.name);
+ push_str(st->stack,C_CONSTSTR,((struct map_session_data *)bl)->status.name);
break;
case BL_NPC:
- push_str(st->stack,C_STR,((struct npc_data *)bl)->exname);
+ push_str(st->stack,C_CONSTSTR,((struct npc_data *)bl)->exname);
break;
default:
ShowError("buildin_rid2name: BL type unknown.\n");
@@ -10508,30 +10508,31 @@ int buildin_getmobdata(struct script_state *st) {
} else {
num=st->stack->stack_data[st->start+3].u.num;
name=(char *)(str_buf+str_data[num&0x00ffffff].str);
- setd_sub(st,map_id2sd(st->rid),name,0,(void *)(int)md->class_);
- setd_sub(st,map_id2sd(st->rid),name,1,(void *)(int)md->level);
- setd_sub(st,map_id2sd(st->rid),name,2,(void *)(int)md->hp);
- setd_sub(st,map_id2sd(st->rid),name,3,(void *)(int)md->max_hp);
- setd_sub(st,map_id2sd(st->rid),name,4,(void *)(int)md->master_id);
- setd_sub(st,map_id2sd(st->rid),name,5,(void *)(int)md->bl.m);
- setd_sub(st,map_id2sd(st->rid),name,6,(void *)(int)md->bl.x);
- setd_sub(st,map_id2sd(st->rid),name,7,(void *)(int)md->bl.y);
- setd_sub(st,map_id2sd(st->rid),name,8,(void *)(int)md->speed);
- setd_sub(st,map_id2sd(st->rid),name,9,(void *)(int)md->mode);
- setd_sub(st,map_id2sd(st->rid),name,10,(void *)(int)md->special_state.ai);
- setd_sub(st,map_id2sd(st->rid),name,11,(void *)(int)md->db->option);
- setd_sub(st,map_id2sd(st->rid),name,12,(void *)(int)md->vd->sex);
- setd_sub(st,map_id2sd(st->rid),name,13,(void *)(int)md->vd->class_);
- setd_sub(st,map_id2sd(st->rid),name,14,(void *)(int)md->vd->hair_style);
- setd_sub(st,map_id2sd(st->rid),name,15,(void *)(int)md->vd->hair_color);
- setd_sub(st,map_id2sd(st->rid),name,16,(void *)(int)md->vd->head_bottom);
- setd_sub(st,map_id2sd(st->rid),name,17,(void *)(int)md->vd->head_mid);
- setd_sub(st,map_id2sd(st->rid),name,18,(void *)(int)md->vd->head_top);
- setd_sub(st,map_id2sd(st->rid),name,19,(void *)(int)md->vd->cloth_color);
- setd_sub(st,map_id2sd(st->rid),name,20,(void *)(int)md->vd->shield);
- setd_sub(st,map_id2sd(st->rid),name,21,(void *)(int)md->vd->weapon);
- setd_sub(st,map_id2sd(st->rid),name,22,(void *)(int)md->vd->shield);
- setd_sub(st,map_id2sd(st->rid),name,23,(void *)(int)md->ud.dir);
+ setd_sub(st,map_id2sd(st->rid),name,0,(void *)(int)md->class_,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,1,(void *)(int)md->level,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,2,(void *)(int)md->hp,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,3,(void *)(int)md->max_hp,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,4,(void *)(int)md->master_id,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,5,(void *)(int)md->bl.m,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,6,(void *)(int)md->bl.x,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,7,(void *)(int)md->bl.y,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,8,(void *)(int)md->speed,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,9,(void *)(int)md->mode,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,10,(void *)(int)md->special_state.ai,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,11,(void *)(int)md->db->option,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,12,(void *)(int)md->vd->sex,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,13,(void *)(int)md->vd->class_,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,14,(void *)(int)md->vd->hair_style,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,15,(void *)(int)md->vd->hair_color,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,16,(void *)(int)md->vd->head_bottom,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,17,(void *)(int)md->vd->head_mid,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,18,(void *)(int)md->vd->head_top,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,19,(void *)(int)md->vd->cloth_color,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,20,(void *)(int)md->vd->shield,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,21,(void *)(int)md->vd->weapon,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,22,(void *)(int)md->vd->shield,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,23,(void *)(int)md->ud.dir,NULL);
+ setd_sub(st,map_id2sd(st->rid),name,24,(void *)(int)md->state.killer,NULL);
}
return 0;
}
@@ -10617,6 +10618,9 @@ int buildin_setmobdata(struct script_state *st){
case 23:
md->ud.dir = (unsigned char)value;
break;
+ case 24:
+ md->state.killer = value>0?1:0;
+ break;
default:
ShowError("buildin_setmobdata: argument id is not identified.");
break;
@@ -10647,6 +10651,7 @@ int buildin_mobattack(struct script_state *st) {
if((md = (struct mob_data *)map_id2bl(id))){
if (md && md->bl.type == BL_MOB) {
md->state.killer = 1;
+ md->special_state.ai = 1;
if(bl){
md->target_id = bl->id;
unit_walktobl(&md->bl, bl, 65025, 2);
@@ -10698,6 +10703,8 @@ int buildin_mobassist(struct script_state *st) {
if(md && md->bl.type == BL_MOB) {
ud = unit_bl2ud(bl);
md->master_id = bl->id;
+ md->state.killer = 1;
+ mob_convertslave(md);
if (ud) {
if (ud->target)
md->target_id = ud->target;
@@ -10746,9 +10753,22 @@ int buildin_mobemote(struct script_state *st) {
int buildin_mobattach(struct script_state *st){
int id;
struct mob_data *md = NULL;
+ struct npc_data *nd = NULL;
+ char *npcname = NULL;
id = conv_num(st, & (st->stack->stack_data[st->start+2]));
- if((md = (struct mob_data *)map_id2bl(id)) && md->bl.type == BL_MOB)
- md->nd = (struct npc_data *)map_id2bl(st->oid);
+ if(st->end > st->start + 3){
+ npcname = conv_str(st, & (st->stack->stack_data[st->start+3]));
+ }
+
+ if(npcname)
+ nd = npc_name2id(npcname);
+ else
+ nd = (struct npc_data *)map_id2bl(st->oid);
+
+ if(nd)
+ if((md = (struct mob_data *)map_id2bl(id)) && md->bl.type == BL_MOB)
+ md->nd = nd;
+
return 0;
}
diff --git a/src/map/script.h b/src/map/script.h
index 87b03a5af..47de38c5c 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -69,7 +69,7 @@ int run_script(struct script_code *rootscript,int pos,int rid,int oid);
int set_var(struct map_session_data *sd, char *name, void *val);
int conv_num(struct script_state *st,struct script_data *data);
char* conv_str(struct script_state *st,struct script_data *data);
-void setd_sub(struct script_state *st, struct map_session_data *sd, char *varname, int elem, void *value);
+void setd_sub(struct script_state *st, struct map_session_data *sd, char *varname, int elem, void *value, struct linkdb_node **ref);
int run_script_timer(int tid, unsigned int tick, int id, int data);
int run_script_main(struct script_state *st);