Explorar o código

* Fixed mob control commands.
* Fixed memory leak in scripts (again). Still have a few lying.

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@6749 54d463be-8e91-2dee-dedb-b68131a5f0ec

Lance %!s(int64=19) %!d(string=hai) anos
pai
achega
c7535fdff4
Modificáronse 6 ficheiros con 109 adicións e 55 borrados
  1. 3 0
      Changelog-Trunk.txt
  2. 1 1
      src/map/battle.c
  3. 1 0
      src/map/map.h
  4. 29 1
      src/map/mob.c
  5. 73 53
      src/map/script.c
  6. 2 0
      src/map/unit.c

+ 3 - 0
Changelog-Trunk.txt

@@ -3,6 +3,9 @@ Date	Added
 AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
+2006/05/25
+	* Fixed mob control commands.
+	* Fixed memory leak in scripts (again). Still have a few lying. [Lance]
 2006/05/24
 	* Fix to the slave AI problem. [erKURITA], by [Skotlex], reported by Niktout.
 	* Item sharing now shares the same rules as exp sharing (no sharing when

+ 1 - 1
src/map/battle.c

@@ -3439,7 +3439,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
 				else
 					state |= BCT_ENEMY; //However, all else are enemies.
 			} else {
-				if (t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai)
+				//if (t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai)
 					state |= BCT_ENEMY; //Natural enemy for AI mobs are normal mobs.
 			}
 			if (md->master_id && (s_bl = map_id2bl(md->master_id)) == NULL)

+ 1 - 0
src/map/map.h

@@ -870,6 +870,7 @@ struct mob_data {
 		unsigned steal_coin_flag : 1;
 		unsigned soul_change_flag : 1; // Celest
 		unsigned alchemist: 1;
+		unsigned no_random_walk: 1;
 		int provoke_flag; // Celest
 	} state;
 	struct guardian_data* guardian_data; 

+ 29 - 1
src/map/mob.c

@@ -906,6 +906,9 @@ 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]
 		
@@ -997,7 +1000,7 @@ int mob_randomwalk(struct mob_data *md,int tick)
 
 	nullpo_retr(0, md);
 
-	if(DIFF_TICK(md->next_walktime,tick)>0 || !unit_can_move(&md->bl))
+	if(DIFF_TICK(md->next_walktime,tick)>0 || md->state.no_random_walk || !unit_can_move(&md->bl))
 		return 0;
 	
 	d =12-md->move_fail_count;
@@ -1509,6 +1512,23 @@ int mob_deleteslave_sub(struct block_list *bl,va_list ap)
 		mob_damage(NULL,md,md->hp,1);
 	return 0;
 }
+
+int mob_convertslave_sub(struct block_list *bl,va_list ap)
+{
+	struct mob_data *md;
+	int id, master;
+
+	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;
+	return 0;
+}
 /*==========================================
  *
  *------------------------------------------
@@ -1520,6 +1540,14 @@ 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 )
 {

+ 73 - 53
src/map/script.c

@@ -425,6 +425,7 @@ int buildin_mobwalk(struct script_state *st);
 int buildin_getmobdata(struct script_state *st);
 int buildin_setmobdata(struct script_state *st);
 int buildin_mobattack(struct script_state *st);
+int buildin_mobrandomwalk(struct script_state *st);
 int buildin_mobstop(struct script_state *st);
 int buildin_mobassist(struct script_state *st);
 int buildin_mobtalk(struct script_state *st);
@@ -761,6 +762,7 @@ struct {
 	{buildin_spawnmob,"spawnmob","*"},
 	{buildin_removemob,"removemob","*"},
 	{buildin_mobwalk,"mobwalk","*"},
+	{buildin_mobrandomwalk,"mobrandomwalk","*"},
 	{buildin_getmobdata,"getmobdata","*"},
 	{buildin_setmobdata,"setmobdata","*"},
 	{buildin_mobattack,"mobattack","*"},
@@ -10469,18 +10471,23 @@ int buildin_removemob(struct script_state *st) {
 }
 
 int buildin_mobwalk(struct script_state *st){
-	int id,x,y;
+	int id,x,y = 0;
 	struct block_list *bl = NULL;
 
 	id = conv_num(st, & (st->stack->stack_data[st->start+2]));
 	x = conv_num(st, & (st->stack->stack_data[st->start+3]));
-	y = conv_num(st, & (st->stack->stack_data[st->start+4]));
+	if(st->end > st->start+4)
+		y = conv_num(st, & (st->stack->stack_data[st->start+4]));
 
 	bl = map_id2bl(id);
-	if(bl && bl->type == BL_MOB)
-		push_val(st->stack,C_INT,unit_walktoxy(bl,x,y,0)); // We'll use harder calculations.
-	else
+	if(bl && bl->type == BL_MOB){
+		if(y)
+			push_val(st->stack,C_INT,unit_walktoxy(bl,x,y,0)); // We'll use harder calculations.
+		else
+			push_val(st->stack,C_INT,unit_walktobl(bl,map_id2bl(x),1,65025));
+	} else {
 		push_val(st->stack,C_INT,0);
+	}
 
 	return 0;
 }
@@ -10491,9 +10498,9 @@ int buildin_getmobdata(struct script_state *st) {
 	struct mob_data *md = NULL;
 	id = conv_num(st, & (st->stack->stack_data[st->start+2]));
 	if(!(md = (struct mob_data *)map_id2bl(id)) || st->stack->stack_data[st->start+3].type!=C_NAME ){
-		ShowWarning("buildin_getmobdata: Error in argiment!\n");
+		ShowWarning("buildin_getmobdata: Error in argument!\n");
 	} else {
-		num=st->stack->stack_data[st->start+2].u.num;
+		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);
@@ -10626,9 +10633,10 @@ int buildin_mobattack(struct script_state *st) {
 		if (sd) bl = &sd->bl;
 		md = (struct mob_data *)map_id2bl(id);
 		if (md && md->bl.type == BL_MOB) {
-			md->target_id = sd->bl.id;
+			md->target_id = bl->id;
 			md->special_state.ai = 1;
-			md->min_chase = distance_bl(bl,&md->bl) + md->db->range2;
+			//md->min_chase = distance_bl(&md->bl,map_id2bl(md->target_id)) + md->db->range2;
+			unit_walktobl(&md->bl, bl, 65025, 2);
 		}
 	}
 
@@ -10645,12 +10653,22 @@ int buildin_mobstop(struct script_state *st) {
 	if(bl && bl->type == BL_MOB){
 		unit_stop_attack(bl);
 		unit_stop_walking(bl,0);
-		((TBL_MOB*)bl)->master_id = bl->id; // Quick hack to stop random walking.
+		((TBL_MOB *)bl)->target_id = 0;
 	}
 
 	return 0;
 }
 
+int buildin_mobrandomwalk(struct script_state *st){
+	int id = conv_num(st, &(st->stack->stack_data[st->start+2]));
+	int flag = conv_num(st, &(st->stack->stack_data[st->start+3]));
+	struct mob_data *md = (struct mob_data *)map_id2bl(id);
+	if(md->bl.type == BL_MOB){
+		md->state.no_random_walk = flag>0?0:1;
+	}
+	return 0;
+}
+
 int buildin_mobassist(struct script_state *st) {
 	int id;
 	char *target;
@@ -10671,7 +10689,8 @@ int buildin_mobassist(struct script_state *st) {
 					md->target_id = ud->target;
 				else if (ud->skilltarget)
 					md->target_id = ud->skilltarget;
-				md->min_chase = distance_bl(&md->bl,map_id2bl(md->target_id)) + md->db->range2;
+				if(md->target_id)
+					unit_walktobl(&md->bl, map_id2bl(md->target_id), 65025, 2);
 			}
 		}
 	}
@@ -11353,9 +11372,12 @@ int run_script_main(struct script_state *st)
 	if(st->state == END) {
 		script_free_stack (st->stack);
 		st->stack = NULL;
+		aFree(st);
+		st = NULL;
+		return 0;
 	}
 
-	return 0;
+	return 1;
 }
 
 /*==========================================
@@ -11411,52 +11433,50 @@ int run_script(struct script_code *rootscript,int pos,int rid,int oid)
 	st->rid = rid;
 	st->oid = oid;
 	st->sleep.timer = -1;
-	// let's run that stuff
-	run_script_main(st);
 
-	if(st->state != END){ 
-		if(st->sleep.tick > 0)
-	  	{	//Delay execution
-			st->sleep.charid = sd?sd->char_id:0;
-			st->sleep.timer  = add_timer(gettick()+st->sleep.tick,
-				run_script_timer, st->sleep.charid, (int)st);
-			linkdb_insert(&sleep_db, (void*)st->oid, st);
-		} else if (sd) {
-			// script is not finished, store data in sd.
-			sd->npc_script      = st->script;
-			sd->npc_scriptroot  = rootscript;
-			sd->npc_scriptstate = st->state;
-			sd->stack           = st->stack;
-			if (bck_stack) //Get rid of the backup as it can't be restored.
-				script_free_stack (bck_stack);
-		}
-		return st->pos;
-	}
-	//Script finished.
-	if (sd)
-  	{	//Clear or restore previous script.
-		sd->npc_script      = bck_script;
-		sd->npc_scriptroot  = bck_scriptroot;
-		sd->npc_scriptstate = bck_scriptstate;
-		sd->stack = bck_stack;
-		//Since the script is done, save any changed account variables [Skotlex]
-		if (sd->state.reg_dirty&2)
-			intif_saveregistry(sd,2);
-		if (sd->state.reg_dirty&1)
-			intif_saveregistry(sd,1);
-	}
-	if(st->stack) {
-		script_free_stack (st->stack);
-		st->stack = NULL;
+	if(run_script_main(st)){
+		if(st->state != END){ 
+			pos = st->pos;
+			if(st->sleep.tick > 0)
+	  		{	//Delay execution
+				st->sleep.charid = sd?sd->char_id:0;
+				st->sleep.timer  = add_timer(gettick()+st->sleep.tick,
+					run_script_timer, st->sleep.charid, (int)st);
+				linkdb_insert(&sleep_db, (void*)st->oid, st);
+			} else if (sd) {
+				// script is not finished, store data in sd.
+				sd->npc_script      = st->script;
+				sd->npc_scriptroot  = rootscript;
+				sd->npc_scriptstate = st->state;
+				sd->stack           = st->stack;
+				if (bck_stack) //Get rid of the backup as it can't be restored.
+					script_free_stack (bck_stack);
+				aFree(st);
+			}
+			return pos;
+		} else {
+			if(st->stack)
+				script_free_stack(st->stack);
+			aFree(st);
+		}
+	} else {
+		//Script finished.
+		if (sd)
+  		{	//Clear or restore previous script.
+			sd->npc_script      = bck_script;
+			sd->npc_scriptroot  = bck_scriptroot;
+			sd->npc_scriptstate = bck_scriptstate;
+			sd->stack = bck_stack;
+			//Since the script is done, save any changed account variables [Skotlex]
+			if (sd->state.reg_dirty&2)
+				intif_saveregistry(sd,2);
+			if (sd->state.reg_dirty&1)
+				intif_saveregistry(sd,1);
+		}
 	}
-	aFree(st);
 	return 0;
 }
 
-/*==========================================
- * 指定ノードをsleep_dbから削除
- *------------------------------------------
- */
 /*==========================================
  * 指定ノードをsleep_dbから削除
  *------------------------------------------

+ 2 - 0
src/map/unit.c

@@ -1041,6 +1041,7 @@ int unit_stop_attack(struct block_list *bl)
 
 	delete_timer( ud->attacktimer, unit_attack_timer );
 	ud->attacktimer = -1;
+	ud->target = 0;
 	return 0;
 }
 
@@ -1086,6 +1087,7 @@ int unit_attack(struct block_list *src,int target_id,int type)
 	if(battle_check_target(src,target,BCT_ENEMY)<=0 ||
 		!status_check_skilluse(src, target, 0, 0)
 	) {
+		ShowWarning("%d can't attack. :(",src->id);
 		unit_unattackable(src);
 		return 1;
 	}