Forráskód Böngészése

* Cleaned up some nasty code related to skill_blown
- split 'direction' value from flags
- moved (almost) entire direction calculating code to the outside
- bowling bash now has the 'suck-in' effect (knockback is now done in the direction you were last facing, not in your-target direction)

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

ultramage 18 éve
szülő
commit
d07ad9e31c
6 módosított fájl, 98 hozzáadás és 90 törlés
  1. 6 0
      Changelog-Trunk.txt
  2. 5 4
      src/map/battle.c
  3. 37 27
      src/map/map.c
  4. 46 56
      src/map/skill.c
  5. 1 1
      src/map/skill.h
  6. 3 2
      src/map/unit.c

+ 6 - 0
Changelog-Trunk.txt

@@ -3,6 +3,12 @@ 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.
 
+2007/07/06
+	* Cleaned up some nasty code related to skill_blown
+	- split 'direction' value from flags
+	- moved (almost) entire direction calculating code to the outside
+	- bowling bash now has the 'suck-in' effect (knockback is now done
+	  in the direction you were last facing, not in your-target direction)
 2007/07/05
 	* Fixed pet equip and pet hairstyle packet sends [ultramage]
 	* Fixed NPC_STOP's visual effect not clearing when the status ends

+ 5 - 4
src/map/battle.c

@@ -307,7 +307,8 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
 	
 		if(sc->data[SC_AUTOGUARD].timer != -1 && flag&BF_WEAPON &&
 			!(skill_get_nk(skill_num)&NK_NO_CARDFIX_ATK) &&
-			rand()%100 < sc->data[SC_AUTOGUARD].val2) {
+			rand()%100 < sc->data[SC_AUTOGUARD].val2)
+		{
 			int delay;
 			clif_skill_nodamage(bl,bl,CR_AUTOGUARD,sc->data[SC_AUTOGUARD].val1,1);
 			// different delay depending on skill level [celest]
@@ -320,7 +321,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
 			unit_set_walkdelay(bl, gettick(), delay, 1);
 
 			if(sc->data[SC_SHRINK].timer != -1 && rand()%100<5*sc->data[SC_AUTOGUARD].val1)
-				skill_blown(bl,src,skill_get_blewcount(CR_SHRINK,1));
+				skill_blown(bl,src,skill_get_blewcount(CR_SHRINK,1),-1,0);
 			return 0;
 		}
 
@@ -366,8 +367,8 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
 		{
 			if (sc->data[SC_UTSUSEMI].timer != -1) {
 				clif_specialeffect(bl, 462, AREA);
-				skill_blown (src, bl, sc->data[SC_UTSUSEMI].val3);
-			};
+				skill_blown(src,bl,sc->data[SC_UTSUSEMI].val3,-1,0);
+			}
 			//Both need to be consumed if they are active.
 			if (sc->data[SC_UTSUSEMI].timer != -1 &&
 				--sc->data[SC_UTSUSEMI].val2 <= 0)

+ 37 - 27
src/map/map.c

@@ -2146,36 +2146,46 @@ int map_check_dir(int s_dir,int t_dir)
 }
 
 /*==========================================
- * Returns the direction of the given cell in absolute relation to the char
- * (regardless of where the char is facing)
+ * Returns the direction of the given cell, relative to 'src'
  *------------------------------------------*/
-int map_calc_dir( struct block_list *src,int x,int y)
+int map_calc_dir(struct block_list* src, int x, int y)
 {
-	int dir=0;
-	int dx,dy;
-
+	int dir = 0;
+	int dx, dy;
+	
 	nullpo_retr(0, src);
-
-	dx=x-src->x;
-	dy=y-src->y;
-	if( dx==0 && dy==0 ){	// 彼我の場所一致
-		dir=0;	// 上
-	}else if( dx>=0 && dy>=0 ){	// 方向的に右上
-		dir=7;						// 右上
-		if( dx*2-1<dy ) dir=0;		// 上
-		if( dx>dy*2 ) dir=6;		// 右
-	}else if( dx>=0 && dy<=0 ){	// 方向的に右下
-		dir=5;						// 右下
-		if( dx*2-1<-dy ) dir=4;		// 下
-		if( dx>-dy*2 ) dir=6;		// 右
-	}else if( dx<=0 && dy<=0 ){ // 方向的に左下
-		dir=3;						// 左下
-		if( dx*2+1>dy ) dir=4;		// 下
-		if( dx<dy*2 ) dir=2;		// 左
-	}else{						// 方向的に左上
-		dir=1;						// 左上
-		if( -dx*2-1<dy ) dir=0;		// 上
-		if( -dx>dy*2 ) dir=2;		// 左
+	
+	dx = x-src->x;
+	dy = y-src->y;
+	if( dx == 0 && dy == 0 )
+	{	// both are standing on the same spot
+		//dir = 6; // aegis-style, causes knockback to the left
+		dir = unit_getdir(src); // athena-style, causes knockback opposite to src's current direction
+	}
+	else if( dx >= 0 && dy >=0 )
+	{	// upper-right
+		if( dx*2-1 < dy )     dir = 0;	// up
+		else if( dx > dy*2 )  dir = 6;	// right
+		else                  dir = 7;	// up-right
+	}
+	else if( dx >= 0 && dy <= 0 )
+	{	// lower-right
+		if( dx*2-1 < -dy )    dir = 4;	// down
+		else if( dx > -dy*2 ) dir = 6;	// right
+		else                  dir = 5;	// down-right
+	}
+	else if( dx <= 0 && dy <= 0 )
+	{	// lower-left
+		if( dx*2+1 > dy )     dir = 4;	// down
+		else if( dx < dy*2 )  dir = 2;	// left
+		else                  dir = 3;	// down-left
+	}
+	else
+	{	// upper-left
+		if( -dx*2-1 < dy )    dir = 0;	// up
+		else if( -dx > dy*2 ) dir = 2;	// left
+		else                  dir = 1;	// up-left
+	
 	}
 	return dir;
 }

+ 46 - 56
src/map/skill.c

@@ -1759,25 +1759,25 @@ int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int
 
 /*=========================================================================
  Used to knock back players, monsters, traps, etc
- If count&0xf00000, the direction is send in the 6th byte.
- If count&0x10000, the direction is to the back of the target, otherwise is away from the src.
- If count&0x20000, position update packets must not be sent.
- IF count&0X40000, direction is random.
---------------------------------------------------------------------------*/
-int skill_blown (struct block_list *src, struct block_list *target, int count)
+ - 'count' is the number of squares to knock back
+ - 'direction' indicates the way OPPOSITE to the knockback direction (or -1 for default behavior)
+ - if 'flag&0x1', position update packets must not be sent.
+ -------------------------------------------------------------------------*/
+int skill_blown(struct block_list* src, struct block_list* target, int count, int direction, int flag)
 {
-	int dx=0,dy=0,nx,ny;
-	int dir,ret;
-	struct skill_unit *su=NULL;
+	int dx = 0, dy = 0, nx, ny;
+	int ret;
+	struct skill_unit* su = NULL;
 
 	nullpo_retr(0, src);
 
 	if (src != target && map_flag_gvg(target->m))
 		return 0; //No knocking back in WoE
-	if (!(count&0xffff))
+	if (count == 0)
 		return 0; //Actual knockback distance is 0.
 	
-	switch (target->type) {
+	switch (target->type)
+	{
 		case BL_MOB:
 			if (((TBL_MOB*)target)->class_ == MOBID_EMPERIUM)
 				return 0;
@@ -1789,26 +1789,22 @@ int skill_blown (struct block_list *src, struct block_list *target, int count)
 				return 0;
 			break;
 		case BL_SKILL:
-			su=(struct skill_unit *)target;
+			su = (struct skill_unit *)target;
 			break;
 	}
 
-	if (count&0xf00000)
-		dir = (count>>20)&0xf;
-	else if (count&0x10000 || (target->x==src->x && target->y==src->y))
-		dir = unit_getdir(target);
-	else if (count&0x40000) //Flag for random pushing.
-		dir = rand()%8;
-	else
-		dir = map_calc_dir(target,src->x,src->y);
-	if (dir>=0 && dir<8){
-		dx = -dirx[dir];
-		dy = -diry[dir];
+	if (direction == -1) // <optimized>: do the computation here instead of outside
+		direction = map_calc_dir(target, src->x, src->y); // direction from src to target, reversed
+
+	if (direction >= 0 && direction < 8)
+	{	// take the reversed 'direction' and reverse it
+		dx = -dirx[direction];
+		dy = -diry[direction];
 	}
 
-	ret=path_blownpos(target->m,target->x,target->y,dx,dy,count&0xffff);
-	nx=ret>>16;
-	ny=ret&0xffff;
+	ret=path_blownpos(target->m,target->x,target->y,dx,dy,count);
+	nx = ret>>16;
+	ny = ret&0xffff;
 
 	if (!su)
 		unit_stop_walking(target,0); 
@@ -1819,25 +1815,22 @@ int skill_blown (struct block_list *src, struct block_list *target, int count)
 	if (!dx && !dy) //Could not knockback.
 		return 0;
 
-	map_foreachinmovearea(clif_outsight, target, AREA_SIZE,
-		dx, dy, target->type==BL_PC?BL_ALL:BL_PC, target);
+	map_foreachinmovearea(clif_outsight, target, AREA_SIZE, dx, dy, target->type == BL_PC ? BL_ALL : BL_PC, target);
 
 	if(su)
 		skill_unit_move_unit_group(su->group,target->m,dx,dy);
 	else
 		map_moveblock(target, nx, ny, gettick());
 
-	map_foreachinmovearea(clif_insight, target, AREA_SIZE,
-		-dx, -dy, target->type==BL_PC?BL_ALL:BL_PC, target);
+	map_foreachinmovearea(clif_insight, target, AREA_SIZE, -dx, -dy, target->type == BL_PC ? BL_ALL : BL_PC, target);
 
-	if(!(count&0x20000)) 
+	if(!(flag&0x1)) 
 		clif_blown(target);
 
-	if(target->type == BL_PC &&
-		map_getcell(target->m, target->x, target->y, CELL_CHKNPC))
+	if(target->type == BL_PC && map_getcell(target->m, target->x, target->y, CELL_CHKNPC))
 		npc_touch_areanpc((TBL_PC*)target, target->m, target->x, target->y); //Invoke area NPC
 
-	return (count&0xFFFF); //Return amount of knocked back cells.
+	return count; //Return amount of knocked back cells.
 }
 
 /*
@@ -2148,7 +2141,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
 
 	//Only knockback if it's still alive, otherwise a "ghost" is left behind. [Skotlex]
 	if (dmg.blewcount > 0 && !status_isdead(bl))
-		skill_blown(dsrc,bl,dmg.blewcount);
+		skill_blown(dsrc,bl,dmg.blewcount,-1,0);
 	
 	//Delayed damage must be dealt after the knockback (it needs to know actual position of target)
 	if (dmg.amotion)
@@ -3043,23 +3036,20 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 		} else {
 			int i,c;
 			c = skill_get_blewcount(skillid,skilllv);
+			// keep moving target in the direction that src is looking, square by square
 			for(i=0;i<c;i++){
-				if (!skill_blown(src,bl,0x20000|1))
+				if (!skill_blown(src,bl,1,(unit_getdir(src)+4)%8,0x1))
 					break; //Can't knockback
 				skill_area_temp[0]=0;
-				map_foreachinrange(skill_area_sub,bl,
-					skill_get_splash(skillid, skilllv),BL_CHAR,
-					src,skillid,skilllv,tick, flag|BCT_ENEMY,
-					skill_area_sub_count);
-				if(skill_area_temp[0]>1) break;
+				map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), BL_CHAR,
+					src, skillid, skilllv, tick, flag|BCT_ENEMY, skill_area_sub_count);
+				if(skill_area_temp[0]>1) break; // collision
 			}
 			clif_blown(bl); //Update target pos.
 			if (i!=c) { //Splash
 				skill_area_temp[1]=bl->id;
-				map_foreachinrange(skill_area_sub,bl,
-					skill_get_splash(skillid, skilllv),BL_CHAR,
-					src,skillid,skilllv,tick, flag|BCT_ENEMY|1,
-					skill_castend_damage_id);
+				map_foreachinrange(skill_area_sub, bl, skill_get_splash(skillid, skilllv), BL_CHAR,
+					src, skillid, skilllv, tick, flag|BCT_ENEMY|1, skill_castend_damage_id);
 			}
 			//Weirdo dual-hit property, two attacks for 500%
 			skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0);
@@ -3068,22 +3058,22 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int
 		break;
 
 	case KN_SPEARSTAB:
-		if(flag&1){
+		if(flag&1) {
 			if (bl->id==skill_area_temp[1])
 				break;
 			if (skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,SD_ANIMATION))
-				skill_blown(src,bl,skill_area_temp[2]);
+				skill_blown(src,bl,skill_area_temp[2],-1,0);
 		} else {
 			int x=bl->x,y=bl->y,i,dir;
 			dir = map_calc_dir(bl,src->x,src->y);
 			skill_area_temp[1] = bl->id;
-			skill_area_temp[2] = skill_get_blewcount(skillid,skilllv)|dir<<20;
+			skill_area_temp[2] = skill_get_blewcount(skillid,skilllv);
+			// all the enemies between the caster and the target are hit, as well as the target
 			if (skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0))
-				skill_blown(src,bl,skill_area_temp[2]);
+				skill_blown(src,bl,skill_area_temp[2],-1,0);
 			for (i=0;i<4;i++) {
 				map_foreachincell(skill_area_sub,bl->m,x,y,BL_CHAR,
-					src,skillid,skilllv,tick,flag|BCT_ENEMY|1,
-					skill_castend_damage_id);
+					src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id);
 				x += dirx[dir];
 				y += diry[dir];
 			}
@@ -4003,7 +3993,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 	case TK_TURNKICK:
 	case MO_BALKYOUNG: //Passive part of the attack. Splash knock-back+stun. [Skotlex]
 		if (skill_area_temp[1] != bl->id) {
-			skill_blown(src,bl,skill_get_blewcount(skillid,skilllv));
+			skill_blown(src,bl,skill_get_blewcount(skillid,skilllv),-1,0);
 			skill_additional_effect(src,bl,skillid,skilllv,BF_MISC,tick); //Use Misc rather than weapon to signal passive pushback
 		}
 		break;	
@@ -4701,7 +4691,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 
 	case TF_BACKSLIDING: //This is the correct implementation as per packet logging information. [Skotlex]
 		clif_skill_nodamage(src,bl,skillid,skilllv,1);
-		skill_blown(src,bl,skill_get_blewcount(skillid,skilllv)|0x10000);
+		skill_blown(src,bl,skill_get_blewcount(skillid,skilllv),unit_getdir(bl),0);
 		break;
 
 	case TK_HIGHJUMP:
@@ -7056,7 +7046,7 @@ int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned
 			break;
 		if (ss == bl) //Also needed to prevent infinite loop crash.
 			break;
-		skill_blown(ss, bl, 0x10000|skill_get_blewcount(sg->skill_id,sg->skill_lv));
+		skill_blown(ss,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv),unit_getdir(bl),0);
 		break;
 	}
 	return skillid;
@@ -7225,7 +7215,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
 
 		case UNT_SKIDTRAP:
 			{
-				skill_blown(&src->bl,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv)|0x10000);
+				skill_blown(&src->bl,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv),unit_getdir(bl),0);
 				sg->unit_id = UNT_USED_TRAPS;
 				clif_changetraplook(&src->bl, UNT_USED_TRAPS);
 				sg->limit=DIFF_TICK(tick,sg->tick)+1500;
@@ -9561,7 +9551,7 @@ int skill_trap_splash (struct block_list *bl, va_list ap)
 			break;
 		case UNT_GROUNDDRIFT_FIRE:
 			if(skill_attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1))
-				skill_blown(src,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv));
+				skill_blown(src,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv),-1,0);
 			break;
 		default:
 			return 0;

+ 1 - 1
src/map/skill.h

@@ -197,7 +197,7 @@ int skill_addtimerskill(struct block_list *src,unsigned int tick,int target,int
 // ’ljÁ?‰Ê
 int skill_additional_effect( struct block_list* src, struct block_list *bl,int skillid,int skilllv,int attack_type,unsigned int tick);
 int skill_counter_additional_effect( struct block_list* src, struct block_list *bl,int skillid,int skilllv,int attack_type,unsigned int tick);
-int skill_blown( struct block_list *src, struct block_list *target,int count);
+int skill_blown(struct block_list* src, struct block_list* target, int count, int direction, int flag);
 int skill_break_equip(struct block_list *bl, unsigned short where, int rate, int flag);
 int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int lv, int time);
 // ƒ†ƒjƒbƒgƒXƒLƒ‹

+ 3 - 2
src/map/unit.c

@@ -429,7 +429,7 @@ int unit_run(struct block_list *bl)
 		//If you can't run forward, you must be next to a wall, so bounce back. [Skotlex]
 		clif_status_change(bl, SI_BUMP, 1);
 		status_change_end(bl,SC_RUN,-1);
-		skill_blown(bl,bl,skill_get_blewcount(TK_RUN,sc->data[SC_RUN].val1)|0x10000);
+		skill_blown(bl,bl,skill_get_blewcount(TK_RUN,sc->data[SC_RUN].val1),unit_getdir(bl),0);
 		clif_fixpos(bl); //Why is a clif_slide (skill_blown) AND a fixpos needed? Ask Aegis.
 		clif_status_change(bl, SI_BUMP, 0);
 		return 0;
@@ -442,9 +442,10 @@ int unit_run(struct block_list *bl)
 		to_y -= dir_y;
 	} while (--i > 0 && !unit_walktoxy(bl, to_x, to_y, 1));
 	if (i==0) {
+		// copy-paste from above
 		clif_status_change(bl, SI_BUMP, 1);
 		status_change_end(bl,SC_RUN,-1);
-		skill_blown(bl,bl,skill_get_blewcount(TK_RUN,sc->data[SC_RUN].val1)|0x10000);
+		skill_blown(bl,bl,skill_get_blewcount(TK_RUN,sc->data[SC_RUN].val1),unit_getdir(bl),0);
 		clif_fixpos(bl);
 		clif_status_change(bl, SI_BUMP, 0);
 		return 0;