浏览代码

* Mob control engine tested 99% working so far.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@6770 54d463be-8e91-2dee-dedb-b68131a5f0ec
Lance 19 年之前
父节点
当前提交
8320520472
共有 10 个文件被更改,包括 167 次插入76 次删除
  1. 1 0
      Changelog-Trunk.txt
  2. 11 0
      db/const.txt
  3. 33 0
      npc/sample/monster_controller.cpp
  4. 17 1
      src/map/battle.c
  5. 2 2
      src/map/clif.c
  6. 44 35
      src/map/mob.c
  7. 1 0
      src/map/mob.h
  8. 2 2
      src/map/npc.c
  9. 55 35
      src/map/script.c
  10. 1 1
      src/map/script.h

+ 1 - 0
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]

+ 11 - 0
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

+ 33 - 0
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:";

+ 17 - 1
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.

+ 2 - 2
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;

+ 44 - 35
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;

+ 1 - 0
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_);
 

+ 2 - 2
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);

+ 55 - 35
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;
 }
 

+ 1 - 1
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);