Browse Source

* Skip partner checking when calculating status with Marionette Control on
* Fixed plagiarised skills become unuseable after saving character
* Fixed double skill fail messages for stone curse
* Added modulus by zero check to rand()

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

celest 20 years ago
parent
commit
eba2fb10e6
9 changed files with 134 additions and 130 deletions
  1. 5 0
      Changelog-SVN.txt
  2. 2 0
      npc/Changelog.txt
  3. 1 1
      npc/npcs_athena.conf
  4. 1 0
      src/map/map.c
  5. 17 11
      src/map/pc.c
  6. 1 0
      src/map/pc.h
  7. 14 12
      src/map/script.c
  8. 89 103
      src/map/skill.c
  9. 4 3
      src/map/status.c

+ 5 - 0
Changelog-SVN.txt

@@ -2,6 +2,10 @@
 Date	Added
 Date	Added
 
 
 04/06
 04/06
+	* Skip partner checking when calculating status with Marionette Control on [celest]
+	* Fixed plagiarised skills become unuseable after saving character [celest]
+	* Fixed double skill fail messages for stone curse, thanks to wind
+	* Added modulus by zero check to rand(), thanks to starlon
         * Improved error messages during npc parsing [MouseJstr]
         * Improved error messages during npc parsing [MouseJstr]
         * Fixed a crash in login_sql [MouseJstr]
         * Fixed a crash in login_sql [MouseJstr]
 	* Added logs filters in more logs [Lupus]
 	* Added logs filters in more logs [Lupus]
@@ -9,6 +13,7 @@ Date	Added
 		Example: (drops log)
 		Example: (drops log)
 		log_drop: 1 = logs ANY items
 		log_drop: 1 = logs ANY items
 		log_drop: 332 = logs only Healing items, Cards and those items which price is >= price_items_log
 		log_drop: 332 = logs only Healing items, Cards and those items which price is >= price_items_log
+
 04/05
 04/05
 	* Fixed damage reflecting (silly typo xP) [celest]
 	* Fixed damage reflecting (silly typo xP) [celest]
 	* Fixed Backstab to not have a push back effect [celest]
 	* Fixed Backstab to not have a push back effect [celest]

+ 2 - 0
npc/Changelog.txt

@@ -33,6 +33,8 @@ Other Ppl
 Date		Added
 Date		Added
 ======
 ======
 
 
+04/06
+	* Set PCLoginEvent.txt to disabled by default [celest]
 04/04
 04/04
 	* Changed "set @TEMP,rand(0);" to set "@TEMP,0;" in the Payon Fortune Teller script [DracoRPG]
 	* Changed "set @TEMP,rand(0);" to set "@TEMP,0;" in the Payon Fortune Teller script [DracoRPG]
 	  We'll have to get all the fortunes, but they are more than 200...
 	  We'll have to get all the fortunes, but they are more than 200...

+ 1 - 1
npc/npcs_athena.conf

@@ -30,7 +30,7 @@ water_height: conf/mapflag/water_height.txt
 //--------------------------------------------------------------
 //--------------------------------------------------------------
 
 
 // PCLoginEvent NPC. NPC which is activated for every player who logs in.
 // PCLoginEvent NPC. NPC which is activated for every player who logs in.
-npc: npc/sample/PCLoginEvent.txt
+//npc: npc/sample/PCLoginEvent.txt
 
 
 
 
 //--------------------------------------------------------------
 //--------------------------------------------------------------

+ 1 - 0
src/map/map.c

@@ -1541,6 +1541,7 @@ int map_quit(struct map_session_data *sd) {
 		if(pc_isdead(sd))
 		if(pc_isdead(sd))
 			pc_setrestartvalue(sd,2);
 			pc_setrestartvalue(sd,2);
 
 
+		pc_clean_skilltree(sd);
 		pc_makesavestatus(sd);
 		pc_makesavestatus(sd);
 		chrif_save(sd);
 		chrif_save(sd);
 		storage_storage_dirty(sd);
 		storage_storage_dirty(sd);

+ 17 - 11
src/map/pc.c

@@ -365,7 +365,6 @@ static int pc_walktoxy_sub(struct map_session_data *);
  */
  */
 int pc_makesavestatus(struct map_session_data *sd)
 int pc_makesavestatus(struct map_session_data *sd)
 {
 {
-        int i;
 	nullpo_retr(0, sd);
 	nullpo_retr(0, sd);
 
 
 	// 秒フ色は色?弊害が多いので保存?象にはしない
 	// 秒フ色は色?弊害が多いので保存?象にはしない
@@ -397,16 +396,6 @@ int pc_makesavestatus(struct map_session_data *sd)
 	if(battle_config.muting_players && sd->status.manner > 0)
 	if(battle_config.muting_players && sd->status.manner > 0)
 		sd->status.manner = 0;
 		sd->status.manner = 0;
 
 
-	// Make sure all the skills are in the correct condition
-	// before persisting to the backend.. [MouseJstr]
-	for(i=0;i<MAX_SKILL;i++){
-	  if(sd->status.skill[i].flag == 13){
-	    sd->status.skill[i].id=0;
-	    sd->status.skill[i].lv=0;
-	    sd->status.skill[i].flag=0;
-	  }
-	}
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1019,6 +1008,21 @@ int pc_calc_skilltree(struct map_session_data *sd)
 	return 0;
 	return 0;
 }
 }
 
 
+// Make sure all the skills are in the correct condition
+// before persisting to the backend.. [MouseJstr]
+int pc_clean_skilltree(struct map_session_data *sd) {
+	int i;
+	for (i = 0; i < MAX_SKILL; i++){
+		if (sd->status.skill[i].flag == 13){
+			sd->status.skill[i].id = 0;
+			sd->status.skill[i].lv = 0;
+			sd->status.skill[i].flag = 0;
+		}
+	}
+
+	return 0;
+}
+
 int pc_calc_skilltree_normalize_job(int c, struct map_session_data *sd) {
 int pc_calc_skilltree_normalize_job(int c, struct map_session_data *sd) {
 	//if((battle_config.skillup_limit) && ((c >= 0 && c < 23) || (c >= 4001 && c < 4023) || (c >= 4023 && c < 4045))) {
 	//if((battle_config.skillup_limit) && ((c >= 0 && c < 23) || (c >= 4001 && c < 4023) || (c >= 4023 && c < 4045))) {
 	if (battle_config.skillup_limit && c >= 0 && c < 23) {
 	if (battle_config.skillup_limit && c >= 0 && c < 23) {
@@ -3007,6 +3011,7 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt
 				sd->bl.x=x;
 				sd->bl.x=x;
 				sd->bl.y=y;
 				sd->bl.y=y;
 				sd->state.waitingdisconnect=1;
 				sd->state.waitingdisconnect=1;
+				pc_clean_skilltree(sd);
 				pc_makesavestatus(sd);
 				pc_makesavestatus(sd);
 				if(sd->status.pet_id > 0 && sd->pd)
 				if(sd->status.pet_id > 0 && sd->pd)
 					intif_save_petdata(sd->status.account_id,&sd->pet);
 					intif_save_petdata(sd->status.account_id,&sd->pet);
@@ -3052,6 +3057,7 @@ int pc_setpos(struct map_session_data *sd,char *mapname_org,int x,int y,int clrt
 				sd->petDB = NULL;
 				sd->petDB = NULL;
 				if(battle_config.pet_status_support)
 				if(battle_config.pet_status_support)
 					status_calc_pc(sd,2);
 					status_calc_pc(sd,2);
+				pc_clean_skilltree(sd);
 				pc_makesavestatus(sd);
 				pc_makesavestatus(sd);
 				chrif_save(sd);
 				chrif_save(sd);
 				storage_storage_save(sd);
 				storage_storage_save(sd);

+ 1 - 0
src/map/pc.h

@@ -52,6 +52,7 @@ int pc_checkequip(struct map_session_data *sd,int pos);
 
 
 int pc_calc_skilltree(struct map_session_data *sd);
 int pc_calc_skilltree(struct map_session_data *sd);
 int pc_calc_skilltree_normalize_job(int c, struct map_session_data *sd);
 int pc_calc_skilltree_normalize_job(int c, struct map_session_data *sd);
+int pc_clean_skilltree(struct map_session_data *sd);
 
 
 int pc_checkoverhp(struct map_session_data*);
 int pc_checkoverhp(struct map_session_data*);
 int pc_checkoversp(struct map_session_data*);
 int pc_checkoversp(struct map_session_data*);

+ 14 - 12
src/map/script.c

@@ -1772,21 +1772,23 @@ int buildin_menu(struct script_state *st)
  */
  */
 int buildin_rand(struct script_state *st)
 int buildin_rand(struct script_state *st)
 {
 {
-	int range,min,max;
-
-	if(st->end>st->start+3){
-		min=conv_num(st,& (st->stack->stack_data[st->start+2]));
-		max=conv_num(st,& (st->stack->stack_data[st->start+3]));
-		if(max<min){
-			int tmp;
-			tmp=min;
-			min=max;
-			max=tmp;
+	int range;
+
+	if (st->end > st->start+3){
+		int min, max;
+		min = conv_num(st,& (st->stack->stack_data[st->start+2]));
+		max = conv_num(st,& (st->stack->stack_data[st->start+3]));
+		if (max < min){
+			int tmp = min;
+			min = max;
+			max = tmp;
 		}
 		}
-		range=max-min+1;
+		range = max - min + 1;
+		if (range == 0) range = 1;
 		push_val(st->stack,C_INT,rand()%range+min);
 		push_val(st->stack,C_INT,rand()%range+min);
 	} else {
 	} else {
-		range=conv_num(st,& (st->stack->stack_data[st->start+2]));
+		range = conv_num(st,& (st->stack->stack_data[st->start+2]));
+		if (range == 0) range = 1;
 		push_val(st->stack,C_INT,rand()%range);
 		push_val(st->stack,C_INT,rand()%range);
 	}
 	}
 	return 0;
 	return 0;

+ 89 - 103
src/map/skill.c

@@ -2090,10 +2090,10 @@ int skill_cleartimerskill(struct block_list *src)
  * (スパゲッティに向けて1?前進!(ダメポ))
  * (スパゲッティに向けて1?前進!(ダメポ))
  *------------------------------------------
  *------------------------------------------
  */
  */
-int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag )
+int skill_castend_damage_id (struct block_list* src, struct block_list *bl,int skillid,int skilllv,unsigned int tick,int flag)
 {
 {
-	struct map_session_data *sd = NULL;
-	struct status_change *sc_data = status_get_sc_data(src);
+	struct map_session_data *sd = NULL, *tsd = NULL;
+	struct status_change *sc_data;
 	int i;
 	int i;
 
 
 	if(skillid < 0)	
 	if(skillid < 0)	
@@ -2107,16 +2107,20 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
 	nullpo_retr(1, src);
 	nullpo_retr(1, src);
 	nullpo_retr(1, bl);
 	nullpo_retr(1, bl);
 
 
-	if(src->type==BL_PC)
-		sd=(struct map_session_data *)src;
-	if(sd && pc_isdead(sd))
+	sc_data = status_get_sc_data(src);
+
+	if (src->type == BL_PC)
+		sd = (struct map_session_data *)src;
+	if (sd && pc_isdead(sd))
 		return 1;
 		return 1;
 
 
-	if((skillid == CR_GRANDCROSS || skillid == NPC_DARKGRANDCROSS) && src != bl)
+	if ((skillid == CR_GRANDCROSS || skillid == NPC_DARKGRANDCROSS) && src != bl)
 		bl = src;
 		bl = src;
-	if(bl->prev == NULL)
+	if (bl->prev == NULL)
 		return 1;
 		return 1;
-	if(bl->type == BL_PC && pc_isdead((struct map_session_data *)bl))
+	if (bl->type == BL_PC)
+		tsd = (struct map_session_data *)bl;
+	if (tsd && pc_isdead(tsd))
 		return 1;
 		return 1;
 	map_freeblock_lock();
 	map_freeblock_lock();
 
 
@@ -2133,7 +2137,6 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
 	case TF_POISON:			/* インベナム */
 	case TF_POISON:			/* インベナム */
 	case TF_SPRINKLESAND:	/* 砂まき */
 	case TF_SPRINKLESAND:	/* 砂まき */
 	case AC_CHARGEARROW:	/* チャ?ジアロ? */
 	case AC_CHARGEARROW:	/* チャ?ジアロ? */
-//	case KN_SPEARSTAB:		/* スピアスタブ */
 	case RG_RAID:		/* サプライズアタック */
 	case RG_RAID:		/* サプライズアタック */
 	case RG_INTIMIDATE:		/* インティミデイト */
 	case RG_INTIMIDATE:		/* インティミデイト */
 	case BA_MUSICALSTRIKE:	/* ミュ?ジカルストライク */
 	case BA_MUSICALSTRIKE:	/* ミュ?ジカルストライク */
@@ -2142,7 +2145,6 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
 	case CR_HOLYCROSS:		/* ホ?リ?クロス */
 	case CR_HOLYCROSS:		/* ホ?リ?クロス */
 	case CR_SHIELDCHARGE:
 	case CR_SHIELDCHARGE:
 	case CR_SHIELDBOOMERANG:
 	case CR_SHIELDBOOMERANG:
-
 	/* 以下MOB?用 */
 	/* 以下MOB?用 */
 	/* ??攻?、SP減少攻?、遠距離攻?、防御無視攻?、多段攻? */
 	/* ??攻?、SP減少攻?、遠距離攻?、防御無視攻?、多段攻? */
 	case NPC_PIERCINGATT:
 	case NPC_PIERCINGATT:
@@ -2180,14 +2182,13 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
 	case LK_SPIRALPIERCE:	/* スパイラルピア?ス */
 	case LK_SPIRALPIERCE:	/* スパイラルピア?ス */
 	case LK_HEADCRUSH:	/* ヘッドクラッシュ */
 	case LK_HEADCRUSH:	/* ヘッドクラッシュ */
 	case LK_JOINTBEAT:	/* ジョイントビ?ト */
 	case LK_JOINTBEAT:	/* ジョイントビ?ト */
-//	case PA_PRESSURE:	/* プレッシャ? */
-//	case PA_SACRIFICE:	/* サクリファイス */
-//	case SN_SHARPSHOOTING:			/* シャ?プシュ?ティング */
 	case CG_ARROWVULCAN:			/* アロ?バルカン */
 	case CG_ARROWVULCAN:			/* アロ?バルカン */
-//	case ASC_BREAKER:				/* ソウルブレ?カ? */
 	case HW_MAGICCRASHER:		/* マジッククラッシャ? */
 	case HW_MAGICCRASHER:		/* マジッククラッシャ? */
 	case ASC_METEORASSAULT:	/* メテオアサルト */
 	case ASC_METEORASSAULT:	/* メテオアサルト */
 	case ITM_TOMAHAWK:
 	case ITM_TOMAHAWK:
+	case MO_COMBOFINISH:	/* 猛龍拳 */
+	case CH_CHAINCRUSH:		/* 連柱崩? */
+	case CH_PALMSTRIKE:		/* 猛虎硬派山 */
 		skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
 		skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
 		break;
 		break;
 
 
@@ -2211,145 +2212,132 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
 			status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(PA_PRESSURE,skilllv),0);
 			status_change_start(bl,SC_STAN,skilllv,0,0,0,skill_get_time2(PA_PRESSURE,skilllv),0);
 		else
 		else
 			status_change_start(bl,SC_BLEEDING,skilllv,0,0,0,skill_get_time2(PA_PRESSURE,skilllv),0);
 			status_change_start(bl,SC_BLEEDING,skilllv,0,0,0,skill_get_time2(PA_PRESSURE,skilllv),0);
-		if (bl->type == BL_PC) {
-			int sp;
-			struct map_session_data *tsd = (struct map_session_data *)bl;
-			nullpo_retb (tsd);
-			sp = tsd->status.max_sp * 10 * skilllv / 100;
+		if (tsd) {
+			int sp = tsd->status.max_sp * 10 * skilllv / 100;
 			if (sp > tsd->status.sp) sp = tsd->status.sp;
 			if (sp > tsd->status.sp) sp = tsd->status.sp;
 			tsd->status.sp -= sp;
 			tsd->status.sp -= sp;
 			clif_updatestatus(tsd,SP_SP);
 			clif_updatestatus(tsd,SP_SP);
 		}
 		}
 		break;
 		break;
+
 	case NPC_DARKBREATH:
 	case NPC_DARKBREATH:
 		clif_emotion(src,7);
 		clif_emotion(src,7);
 		skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag);
 		skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag);
 		break;
 		break;
+
 	case MO_INVESTIGATE:	/* ?勁 */
 	case MO_INVESTIGATE:	/* ?勁 */
 		{
 		{
-			struct status_change *sc_data = status_get_sc_data(src);
 			skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
 			skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
-			if(sc_data && sc_data[SC_BLADESTOP].timer != -1)
+			if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
 				status_change_end(src,SC_BLADESTOP,-1);
 				status_change_end(src,SC_BLADESTOP,-1);
 		}
 		}
 		break;
 		break;
+
 	case SN_FALCONASSAULT:			/* ファルコンアサルト */
 	case SN_FALCONASSAULT:			/* ファルコンアサルト */
 		skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag);
 		skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag);
 		break;
 		break;
 
 
 	case RG_BACKSTAP:		/* バックスタブ */
 	case RG_BACKSTAP:		/* バックスタブ */
 		{
 		{
-			int dir = map_calc_dir(src,bl->x,bl->y),t_dir = status_get_dir(bl);
-			int dist = distance(src->x,src->y,bl->x,bl->y);
-			if((dist > 0 && !map_check_dir(dir,t_dir)) || bl->type == BL_SKILL) {
-				struct status_change *sc_data = status_get_sc_data(src);
-				if(sc_data && sc_data[SC_HIDING].timer != -1)
+			int dir = map_calc_dir(src,bl->x,bl->y), t_dir = status_get_dir(bl);
+			int dist = distance(src->x, src->y, bl->x, bl->y);
+			if ((dist > 0 && !map_check_dir(dir, t_dir)) || bl->type == BL_SKILL) {
+				if (sc_data && sc_data[SC_HIDING].timer != -1)
 					status_change_end(src, SC_HIDING, -1);	// ハイディング解除
 					status_change_end(src, SC_HIDING, -1);	// ハイディング解除
-				skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
+				skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag);
 				dir = dir < 4 ? dir+4 : dir-4; // change direction [Celest]
 				dir = dir < 4 ? dir+4 : dir-4; // change direction [Celest]
-				if (bl->type == BL_PC)
-					((struct map_session_data *)bl)->dir=dir;
-				else if (bl->type == BL_MOB)
-					((struct mob_data *)bl)->dir=dir;
+				if (tsd)
+					tsd->dir = dir;
+				else if (bl->type == BL_MOB) {
+					struct mob_data *md = (struct mob_data *)bl;
+					if (md) md->dir = dir;
+				}
 				clif_changed_dir(bl);
 				clif_changed_dir(bl);
-				//skill_blown(src,bl,skill_get_blewcount(skillid,skilllv));
 			}
 			}
-			else if(src->type == BL_PC)
+			else if (sd)
 				clif_skill_fail(sd,sd->skillid,0,0);
 				clif_skill_fail(sd,sd->skillid,0,0);
 		}
 		}
 		break;
 		break;
 
 
 	case AM_ACIDTERROR:		/* アシッドテラ? */
 	case AM_ACIDTERROR:		/* アシッドテラ? */
-		skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
-		if(bl->type == BL_PC && rand()%100 < skill_get_time(skillid,skilllv) && battle_config.equipment_breaking) {
-			pc_breakarmor((struct map_session_data *)bl);
+		skill_attack(BF_WEAPON, src, src, bl, skillid, skilllv, tick, flag);
+		if (tsd && battle_config.equipment_breaking && rand()%100 < skill_get_time(skillid,skilllv)) {
+			pc_breakarmor(tsd);
 			clif_emotion(bl, 23);
 			clif_emotion(bl, 23);
 		}
 		}
 		break;
 		break;
+
 	case MO_FINGEROFFENSIVE:	/* 指? */
 	case MO_FINGEROFFENSIVE:	/* 指? */
 		{
 		{
-			struct status_change *sc_data = status_get_sc_data(src);
-
-			if(!battle_config.finger_offensive_type)
-				skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
-			else {
-				skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
-				if(sd) {
-					for(i=1;i<sd->spiritball_old;i++)
-						skill_addtimerskill(src,tick+i*200,bl->id,0,0,skillid,skilllv,BF_WEAPON,flag);
-					sd->canmove_tick = tick + (sd->spiritball_old-1)*200;
-				}
+			skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
+			if (battle_config.finger_offensive_type && sd) {
+				for (i = 1; i < sd->spiritball_old; i++)
+					skill_addtimerskill(src, tick + i * 200, bl->id, 0, 0, skillid, skilllv, BF_WEAPON, flag);
+				sd->canmove_tick = tick + (sd->spiritball_old - 1) * 200;
 			}
 			}
-			if(sc_data && sc_data[SC_BLADESTOP].timer != -1)
+			if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
 				status_change_end(src,SC_BLADESTOP,-1);
 				status_change_end(src,SC_BLADESTOP,-1);
 		}
 		}
 		break;
 		break;
+
 	case MO_CHAINCOMBO:		/* 連打掌 */
 	case MO_CHAINCOMBO:		/* 連打掌 */
 		{
 		{
-			struct status_change *sc_data = status_get_sc_data(src);
 			skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
 			skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
-			if(sc_data && sc_data[SC_BLADESTOP].timer != -1)
+			if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
 				status_change_end(src,SC_BLADESTOP,-1);
 				status_change_end(src,SC_BLADESTOP,-1);
 		}
 		}
 		break;
 		break;
-	case MO_COMBOFINISH:	/* 猛龍拳 */
-	case CH_CHAINCRUSH:		/* 連柱崩? */
-	case CH_PALMSTRIKE:		/* 猛虎硬派山 */
-		skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
-		break;
-	
+
 	case CH_TIGERFIST:		/* 伏虎拳 */
 	case CH_TIGERFIST:		/* 伏虎拳 */
-		if (bl->type == BL_PC && !(map[bl->m].flag.gvg || map[bl->m].flag.pvp)) {
+		if (tsd && !(map[bl->m].flag.gvg || map[bl->m].flag.pvp)) {
 			map_freeblock_unlock();
 			map_freeblock_unlock();
 			return 1;
 			return 1;
 		}
 		}
 		skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
 		skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
 		break;
 		break;
 
 
-
 	case MO_EXTREMITYFIST:	/* 阿修羅覇鳳拳 */
 	case MO_EXTREMITYFIST:	/* 阿修羅覇鳳拳 */
 		{
 		{
-			struct status_change *sc_data = status_get_sc_data(src);
+			if(sd) {
+				struct walkpath_data wpd;
+				int dx,dy;
 
 
-		if(sd) {
-			struct walkpath_data wpd;
-			int dx,dy;
-
-			dx = bl->x - sd->bl.x;
-			dy = bl->y - sd->bl.y;
-			if(dx > 0) dx++;
-			else if(dx < 0) dx--;
-			if(dy > 0) dy++;
-			else if(dy < 0) dy--;
-			if(dx == 0 && dy == 0) dx++;
-			if(path_search(&wpd,src->m,sd->bl.x,sd->bl.y,sd->bl.x+dx,sd->bl.y+dy,1) == -1) {
 				dx = bl->x - sd->bl.x;
 				dx = bl->x - sd->bl.x;
 				dy = bl->y - sd->bl.y;
 				dy = bl->y - sd->bl.y;
-				if(path_search(&wpd,src->m,sd->bl.x,sd->bl.y,sd->bl.x+dx,sd->bl.y+dy,1) == -1) {
-					clif_skill_fail(sd,sd->skillid,0,0);
-					break;
+				if(dx > 0) dx++;
+				else if(dx < 0) dx--;
+				if (dy > 0) dy++;
+				else if(dy < 0) dy--;
+				if(dx == 0 && dy == 0) dx++;
+				if (path_search(&wpd,src->m,sd->bl.x,sd->bl.y,sd->bl.x+dx,sd->bl.y+dy,1) == -1) {
+					dx = bl->x - sd->bl.x;
+					dy = bl->y - sd->bl.y;
+					if(path_search(&wpd,src->m,sd->bl.x,sd->bl.y,sd->bl.x+dx,sd->bl.y+dy,1) == -1) {
+						clif_skill_fail(sd,sd->skillid,0,0);
+						break;
+					}
 				}
 				}
+				sd->to_x = sd->bl.x + dx;
+				sd->to_y = sd->bl.y + dy;
+				skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
+				clif_walkok(sd);
+				clif_movechar(sd);
+				if(dx < 0) dx = -dx;
+				if(dy < 0) dy = -dy;
+				sd->attackabletime = sd->canmove_tick = tick + 100 + sd->speed * ((dx > dy)? dx:dy);
+				if(sd->canact_tick < sd->canmove_tick)
+					sd->canact_tick = sd->canmove_tick;
+				pc_movepos(sd,sd->to_x,sd->to_y);
+				status_change_end(&sd->bl,SC_COMBO,-1);
 			}
 			}
-			sd->to_x = sd->bl.x + dx;
-			sd->to_y = sd->bl.y + dy;
-			skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
-			clif_walkok(sd);
-			clif_movechar(sd);
-			if(dx < 0) dx = -dx;
-			if(dy < 0) dy = -dy;
-			sd->attackabletime = sd->canmove_tick = tick + 100 + sd->speed * ((dx > dy)? dx:dy);
-			if(sd->canact_tick < sd->canmove_tick)
-				sd->canact_tick = sd->canmove_tick;
-			pc_movepos(sd,sd->to_x,sd->to_y);
-			status_change_end(&sd->bl,SC_COMBO,-1);
-		}
-		else
-			skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
-		status_change_end(src, SC_EXPLOSIONSPIRITS, -1);
-			if(sc_data && sc_data[SC_BLADESTOP].timer != -1)
+			else
+				skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag);
+			status_change_end(src, SC_EXPLOSIONSPIRITS, -1);
+			if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
 				status_change_end(src,SC_BLADESTOP,-1);
 				status_change_end(src,SC_BLADESTOP,-1);
 		}
 		}
 		break;
 		break;
+
 	/* 武器系範?攻?スキル */
 	/* 武器系範?攻?スキル */
 	case AC_SHOWER:			/* アロ?シャワ? */
 	case AC_SHOWER:			/* アロ?シャワ? */
 	case AS_GRIMTOOTH:		/* グリムトゥ?ス */
 	case AS_GRIMTOOTH:		/* グリムトゥ?ス */
@@ -2600,8 +2588,6 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
 		break;
 		break;
 
 
 	case WZ_FROSTNOVA:			/* フロストノヴァ */
 	case WZ_FROSTNOVA:			/* フロストノヴァ */
-		//skill_castend_pos2(src,bl->x,bl->y,skillid,skilllv,tick,0);
-		//skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,flag);
 		map_foreachinarea(skill_attack_area,src->m,src->x-5,bl->y-5,bl->x+5,bl->y+5,0,BF_MAGIC,src,src,skillid,skilllv,tick,flag,BCT_ENEMY);
 		map_foreachinarea(skill_attack_area,src->m,src->x-5,bl->y-5,bl->x+5,bl->y+5,0,BF_MAGIC,src,src,skillid,skilllv,tick,flag,BCT_ENEMY);
 		break;
 		break;
 
 
@@ -2650,12 +2636,9 @@ int skill_castend_damage_id( struct block_list* src, struct block_list *bl,int s
 				clif_skill_nodamage(src,bl,skillid,skilllv,1);
 				clif_skill_nodamage(src,bl,skillid,skilllv,1);
 				if (skilllv == 5)
 				if (skilllv == 5)
 					skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,0 );
 					skill_attack(BF_MAGIC,src,src,bl,skillid,skilllv,tick,0 );
-				if (bl->type == BL_PC && (map[src->m].flag.pvp || map[src->m].flag.gvg)) {
-					struct map_session_data *tsd = (struct map_session_data *)bl;
-					if (tsd) {
-						tsd->status.sp = 0;
-						clif_updatestatus(tsd,SP_SP);
-					}
+				if (tsd && (map[src->m].flag.pvp || map[src->m].flag.gvg)) {
+					tsd->status.sp = 0;
+					clif_updatestatus(tsd,SP_SP);
 				}
 				}
 			} else {
 			} else {
 				clif_skill_nodamage(src,src,skillid,skilllv,1);
 				clif_skill_nodamage(src,src,skillid,skilllv,1);
@@ -3626,7 +3609,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 		{
 		{
 			struct status_change *sc_data = status_get_sc_data(bl);
 			struct status_change *sc_data = status_get_sc_data(bl);
 			// Level 6-10 doesn't consume a red gem if it fails [celest]
 			// Level 6-10 doesn't consume a red gem if it fails [celest]
-			int i, gem_flag = 1;
+			int i, gem_flag = 1, fail_flag = 0;
 			if (dstmd && status_get_mode(bl)&0x20) {
 			if (dstmd && status_get_mode(bl)&0x20) {
 				clif_skill_fail(sd,sd->skillid,0,0);
 				clif_skill_fail(sd,sd->skillid,0,0);
 				break;
 				break;
@@ -3636,20 +3619,23 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
 				break;
 				break;
 			if (sc_data && sc_data[SC_STONE].timer != -1) {
 			if (sc_data && sc_data[SC_STONE].timer != -1) {
 				status_change_end(bl,SC_STONE,-1);
 				status_change_end(bl,SC_STONE,-1);
-				if (sd)
+				if (sd) {
+					fail_flag = 1;
 					clif_skill_fail(sd,skillid,0,0);
 					clif_skill_fail(sd,skillid,0,0);
+				}
 			}
 			}
 			else if( rand()%100 < skilllv*4+20 && !battle_check_undead(status_get_race(bl),status_get_elem_type(bl)))
 			else if( rand()%100 < skilllv*4+20 && !battle_check_undead(status_get_race(bl),status_get_elem_type(bl)))
 				status_change_start(bl,SC_STONE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
 				status_change_start(bl,SC_STONE,skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
 			else if(sd) {
 			else if(sd) {
 				if (skilllv > 5) gem_flag = 0;
 				if (skilllv > 5) gem_flag = 0;
 				clif_skill_fail(sd,skillid,0,0);
 				clif_skill_fail(sd,skillid,0,0);
+				fail_flag = 1;
 			}
 			}
 			if (dstmd)
 			if (dstmd)
 				mob_target(dstmd,src,skill_get_range(skillid,skilllv));
 				mob_target(dstmd,src,skill_get_range(skillid,skilllv));
 			if (sd && gem_flag) {
 			if (sd && gem_flag) {
 				if ((i=pc_search_inventory(sd, skill_db[skillid].itemid[0])) < 0 ) {
 				if ((i=pc_search_inventory(sd, skill_db[skillid].itemid[0])) < 0 ) {
-					clif_skill_fail(sd,sd->skillid,0,0);
+					if (!fail_flag) clif_skill_fail(sd,sd->skillid,0,0);
 					break;
 					break;
 				}
 				}
 				pc_delitem(sd, i, skill_db[skillid].amount[0], 0);
 				pc_delitem(sd, i, skill_db[skillid].amount[0], 0);

+ 4 - 3
src/map/status.c

@@ -779,15 +779,16 @@ int status_calc_pc(struct map_session_data* sd,int first)
 			sd->paramb[5]+= 5;
 			sd->paramb[5]+= 5;
 		}
 		}
 		if(sd->sc_data[SC_MARIONETTE].timer!=-1){
 		if(sd->sc_data[SC_MARIONETTE].timer!=-1){
-			struct map_session_data *psd = map_id2sd(sd->sc_data[SC_MARIONETTE2].val3);
-			if (psd) {	// if partner is found
+			// skip partner checking -- should be handled in status_change_timer
+			//struct map_session_data *psd = map_id2sd(sd->sc_data[SC_MARIONETTE2].val3);
+			//if (psd) {	// if partner is found
 				sd->paramb[0]-= sd->status.str/2;	// bonuses not included
 				sd->paramb[0]-= sd->status.str/2;	// bonuses not included
 				sd->paramb[1]-= sd->status.agi/2;
 				sd->paramb[1]-= sd->status.agi/2;
 				sd->paramb[2]-= sd->status.vit/2;
 				sd->paramb[2]-= sd->status.vit/2;
 				sd->paramb[3]-= sd->status.int_/2;
 				sd->paramb[3]-= sd->status.int_/2;
 				sd->paramb[4]-= sd->status.dex/2;
 				sd->paramb[4]-= sd->status.dex/2;
 				sd->paramb[5]-= sd->status.luk/2;
 				sd->paramb[5]-= sd->status.luk/2;
-			}
+			//}
 		}
 		}
 		else if(sd->sc_data[SC_MARIONETTE2].timer!=-1){
 		else if(sd->sc_data[SC_MARIONETTE2].timer!=-1){
 			struct map_session_data *psd = map_id2sd(sd->sc_data[SC_MARIONETTE2].val3);
 			struct map_session_data *psd = map_id2sd(sd->sc_data[SC_MARIONETTE2].val3);