瀏覽代碼

- Added support for OnTouchNPC event, required for Monster Race. Script commands need to be tested. Already tested sc_start.
- Added status SC_WALKSPEED required in monster Race.

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

zephyrus 17 年之前
父節點
當前提交
5c7a1807e4
共有 6 個文件被更改,包括 65 次插入25 次删除
  1. 1 0
      db/const.txt
  2. 1 0
      src/map/mob.h
  3. 54 19
      src/map/npc.c
  4. 4 3
      src/map/status.c
  5. 1 0
      src/map/status.h
  6. 4 3
      src/map/unit.c

+ 1 - 0
db/const.txt

@@ -790,6 +790,7 @@ SC_COMMONSC_RESIST	273
 SC_SEVENWIND	274
 SC_DEF_RATE	275
 SC_SPREGEN	276
+SC_WALKSPEED	277
 
 e_gasp	0
 e_what	1

+ 1 - 0
src/map/mob.h

@@ -125,6 +125,7 @@ struct mob_data {
 	unsigned int tdmg; //Stores total damage given to the mob, for exp calculations. [Skotlex]
 	int level;
 	int target_id,attacked_id;
+	int areanpc_id; //Required in OnTouchNPC (to avoid multiple area touchs)
 
 	unsigned int next_walktime,last_thinktime,last_linktime,last_pcneartime;
 	short move_fail_count;

+ 54 - 19
src/map/npc.c

@@ -777,35 +777,70 @@ int npc_touch_areanpc(struct map_session_data* sd, int m, int x, int y)
 	return 0;
 }
 
-int npc_touch_areanpc2(struct block_list* bl)
+int npc_touch_areanpc2(struct mob_data *md)
 {
-	int i,m=bl->m;
-	int xs,ys;
+	int i, m = md->bl.m, x = md->bl.x, y = md->bl.y;
+	char eventname[NAME_LENGTH*2+3];
+	struct event_data* ev;
+	int xs, ys;
 
-	for(i=0;i<map[m].npc_num;i++)
+	for( i = 0; i < map[m].npc_num; i++ )
 	{
-		if (map[m].npc[i]->sc.option&OPTION_INVISIBLE)
+		if( map[m].npc[i]->sc.option&OPTION_INVISIBLE )
 			continue;
 
-		if (map[m].npc[i]->subtype!=WARP)
+		switch( map[m].npc[i]->subtype )
+		{
+		case WARP:
+			if( battle_config.mob_warp&1 )
+			{
+				xs = map[m].npc[i]->u.warp.xs;
+				ys = map[m].npc[i]->u.warp.ys;
+			}
+			else
+				continue;
+			break;
+		case SCRIPT:
+			xs = map[m].npc[i]->u.scr.xs;
+			ys = map[m].npc[i]->u.scr.ys;
+			snprintf(eventname, ARRAYLENGTH(eventname), "%s::OnTouchNPC", map[m].npc[i]->exname);
+			break;
+		default:
 			continue;
-	
-		xs=map[m].npc[i]->u.warp.xs;
-		ys=map[m].npc[i]->u.warp.ys;
+		}
+		if( x >= map[m].npc[i]->bl.x-xs && x <= map[m].npc[i]->bl.x+xs && y >= map[m].npc[i]->bl.y-ys && y <= map[m].npc[i]->bl.y+ys )
+		{
+			if( map[m].npc[i]->subtype == SCRIPT
+				&& ((ev = (struct event_data*)strdb_get(ev_db, eventname)) == NULL || ev->nd == NULL) )
+				continue; // No OnTouchNPC Event found
 
-		if( bl->x >= map[m].npc[i]->bl.x-xs && bl->x <= map[m].npc[i]->bl.x+xs
-		&&  bl->y >= map[m].npc[i]->bl.y-ys && bl->y <= map[m].npc[i]->bl.y+ys )
 			break;
+		}
 	}
-	if (i==map[m].npc_num)
-		return 0;
-	
-	xs = map_mapindex2mapid(map[m].npc[i]->u.warp.mapindex);
-	if (xs < 0) // Can't warp object between map servers...
-		return 0;
 
-	if (unit_warp(bl, xs, map[m].npc[i]->u.warp.x,map[m].npc[i]->u.warp.y,0))
-		return 0; //Failed to warp.
+	if( i == map[m].npc_num ) return 0;
+
+	switch( map[m].npc[i]->subtype )
+	{
+		case WARP:
+			xs = map_mapindex2mapid(map[m].npc[i]->u.warp.mapindex);
+			if( xs < 0 )
+				return 0; // Can't warp object between map servers...
+			if( unit_warp(&md->bl, xs, map[m].npc[i]->u.warp.x, map[m].npc[i]->u.warp.y, 0) )
+				return 0; // Failed to warp.
+			break;
+		case SCRIPT:
+		{
+			if( md->areanpc_id == map[m].npc[i]->bl.id )
+				return 0; // Allready touch this NPC
+
+			md->areanpc_id = map[m].npc[i]->bl.id;
+			run_script(ev->nd->u.scr.script, ev->pos, md->bl.id, ev->nd->bl.id);
+
+			return 0;
+			break;
+		}
+	}
 
 	return 1;
 }

+ 4 - 3
src/map/status.c

@@ -502,6 +502,7 @@ void initChangeTables(void)
 	StatusChangeFlagTable[SC_ARMOR_ELEMENT] |= SCB_PC;
 	StatusChangeFlagTable[SC_ARMOR_RESIST] |= SCB_PC;
 	StatusChangeFlagTable[SC_SPCOST_RATE] |= SCB_PC;
+	StatusChangeFlagTable[SC_WALKSPEED] |= SCB_SPEED;
 
 	if (!battle_config.display_hallucination) //Disable Hallucination.
 		StatusIconChangeTable[SC_HALLUCINATION] = SI_BLANK;
@@ -3706,7 +3707,6 @@ static signed short status_calc_mdef2(struct block_list *bl, struct status_chang
 
 static unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc, int speed)
 {
-
 	//Default speed coming in means there's no speed_rate adjustments. 
 	int new_speed = speed;
 	bool default_speed = (speed == DEFAULT_WALK_SPEED);
@@ -3714,6 +3714,9 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
 	if(!sc || !sc->count)
 		return cap_value(speed,10,USHRT_MAX);
 
+	if(sc->data[SC_WALKSPEED])
+		new_speed = sc->data[SC_WALKSPEED]->val1;
+
 	// Fixed reductions
 	if(sc->data[SC_CURSE])
 		new_speed += 450;
@@ -3739,8 +3742,6 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha
 		if(sc->data[SC_FUSION])
 			new_speed -= new_speed * 25/100;
 
-
-
 		//These only apply if you don't have increase agi and/or fusion and/or sprint
 		if(speed == new_speed)
 		{

+ 1 - 0
src/map/status.h

@@ -294,6 +294,7 @@ typedef enum sc_type {
 	SC_SEVENWIND,
 	SC_DEF_RATE,
 	SC_SPREGEN,
+	SC_WALKSPEED,
 	SC_MAX, //Automatically updated max, used in for's to check we are within bounds.
 } sc_type;
 

+ 4 - 3
src/map/unit.c

@@ -183,9 +183,10 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr data)
 					bl->id, sd->status.guild_id, strvit, agidex);
 		}
 	} else if (md) {
-		if(battle_config.mob_warp&1 && map_getcell(bl->m,x,y,CELL_CHKNPC) &&
-			npc_touch_areanpc2(bl)) // Enable mobs to step on warps. [Skotlex]
-	  		return 0;
+		if( map_getcell(bl->m,x,y,CELL_CHKNPC) ) {
+			if( npc_touch_areanpc2(md) ) return 0; // Warped
+		} else
+			md->areanpc_id = 0;
 		if (md->min_chase > md->db->range3) md->min_chase--;
 		//Walk skills are triggered regardless of target due to the idle-walk mob state.
 		//But avoid triggering on stop-walk calls.