Przeglądaj źródła

Bug Fixes:
* Fixed #433, fixed SR_TIGERCANNON splash damage.
* Fixed #458, fixed SR_TIGERCANNON behavior as auto-cast by SR_FLASHCOMBO. SR_TIGERCANNON consumes no HP/SP anymore, deal damage WITHOUT the SR_FALLENEMPIRE combo bonus.

Thank @aleos89, @jeanroyce, @SuezoSilver, @firecroll

Signed-off-by: Cydh Ramdh <cydh@pservero.com>

Cydh Ramdh 10 lat temu
rodzic
commit
1ea4655140
7 zmienionych plików z 127 dodań i 70 usunięć
  1. 4 4
      db/re/skill_db.txt
  2. 5 5
      db/re/skill_require_db.txt
  3. 49 26
      src/map/battle.c
  4. 1 0
      src/map/battle.h
  5. 62 28
      src/map/skill.c
  6. 4 4
      src/map/skill.h
  7. 2 3
      src/map/status.c

+ 4 - 4
db/re/skill_db.txt

@@ -1325,10 +1325,10 @@
 5012,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,0x0, WL_TELEKINESIS_INTENSE,Intense Telekinesis
 5013,0,6,4,0,0x3,0,5,1,no,0,0,0,none,0,0x0, LG_KINGS_GRACE,King's Grace
 5014,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,0x0, ALL_FULL_THROTTLE,Full Throttle
-5015,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,0x0, SR_FLASHCOMBO_ATK_STEP1,Flash Combo Attack Step 1
-5016,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,0x0, SR_FLASHCOMBO_ATK_STEP2,Flash Combo Attack Step 2
-5017,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,0x0, SR_FLASHCOMBO_ATK_STEP3,Flash Combo Attack Step 3
-5018,0,6,4,0,0x1,0,5,1,no,0,0,0,none,0,0x0, SR_FLASHCOMBO_ATK_STEP4,Flash Combo Attack Step 4
+5015,-2,8,1,-1,0,0,10,-2,no,0,0,0,weapon,0,0x0,                     	SR_FLASHCOMBO_ATK_STEP1,Flash Combo Attack Step 1
+5016,-2,8,4,-1,0,0,5,-2,no,0,0x200,0,weapon,0,0x0,                  	SR_FLASHCOMBO_ATK_STEP2,Flash Combo Attack Step 2
+5017,-2,6,1,-1,0x42,1:1:1:1:1:2:2:2:2:2,10,1,yes,0,0,0,weapon,0,0x0,	SR_FLASHCOMBO_ATK_STEP3,Flash Combo Attack Step 3
+5018,0,8,4,-1,0x2,2,5,-3,no,0,0,0,weapon,3,0x0,                     	SR_FLASHCOMBO_ATK_STEP4,Flash Combo Attack Step 4
 
 //****
 // Homunculus S

+ 5 - 5
db/re/skill_require_db.txt

@@ -759,7 +759,7 @@
 2327,0,0,8:9:10:11:12,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0					//SR_SKYNETBLOW
 2328,0,0,36:40:44:48:52,0,0,0,99,0,0,none,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0					//SR_EARTHSHAKER
 2329,0,0,20:30:40:50:60,0,0,0,99,0,0,none,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0					//SR_FALLENEMPIRE
-2330,0,0,1:2:3:4:5:6:7:8:9:10,0,0,0,99,0,0,none,SC_EXPLOSIONSPIRITS,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//SR_TIGERCANNON
+2330,0,0,1:2:3:4:5:6:7:8:9:10,-12:-14:-16:-18:-20:-22:-24:-26:-28:-30,-6:-7:-8:-9:-10:-11:-12:-13:-14:-15,0,99,0,0,none,SC_EXPLOSIONSPIRITS,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//SR_TIGERCANNON
 2331,0,0,1,0,-11:-12:-13:-14:-15:-16:-17:-18:-19:-20,0,99,0,0,none,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0	//SR_HELLGATE
 2332,0,0,150,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0							//SR_RAMPAGEBLASTER
 2333,0,0,80,0,0,0,99,0,0,none,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0								//SR_CRESCENTELBOW
@@ -971,10 +971,10 @@
 5012,0,0,100:150:200:250:300,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0			//WL_TELEKINESIS_INTENSE
 5013,0,0,200:180:160:140:120,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0			//LG_KINGS_GRACE
 5014,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0								//ALL_FULL_THROTTLE
-5015,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0								//SR_FLASHCOMBO_ATK_STEP1 //All 4 steps are using temp req SP values for now.
-5016,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0								//SR_FLASHCOMBO_ATK_STEP2
-5017,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0								//SR_FLASHCOMBO_ATK_STEP3
-5018,0,0,1,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0								//SR_FLASHCOMBO_ATK_STEP4
+5015,0,0,0,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0								//SR_FLASHCOMBO_ATK_STEP1 //All 4 steps are using temp req SP values for now.
+5016,0,0,0,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0								//SR_FLASHCOMBO_ATK_STEP2
+5017,0,0,0,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0								//SR_FLASHCOMBO_ATK_STEP3
+5018,0,0,0,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0								//SR_FLASHCOMBO_ATK_STEP4
 
 8001,0,0,13:16:19:22:25,0,0,0,99,0,0,none,0,0,545,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0				//HLIF_HEAL
 8002,0,0,20:25:30:35:40,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0					//HLIF_AVOID

+ 49 - 26
src/map/battle.c

@@ -3881,17 +3881,6 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
 			if( sc && sc->data[SC_INSPIRATION] )
 				skillratio += 600;
 			break;
-		case SR_DRAGONCOMBO:
-			skillratio += 40 * skill_lv;
-			RE_LVL_DMOD(100);
-			break;
-		case SR_SKYNETBLOW:
-			//ATK [{(Skill Level x 80) + (Caster AGI)} x Caster Base Level / 100] %
-			skillratio = 80 * skill_lv + status_get_agi(src);
-			if( sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_DRAGONCOMBO )//ATK [{(Skill Level x 100) + (Caster AGI) + 150} x Caster Base Level / 100] %
-				skillratio = 100 * skill_lv + status_get_agi(src) + 150;
-			RE_LVL_DMOD(100);
-			break;
 		case SR_EARTHSHAKER:
 			if( tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING] || // [(Skill Level x 150) x (Caster Base Level / 100) + (Caster INT x 3)] %
 				tsc->data[SC_CHASEWALK] || tsc->data[SC_CLOAKINGEXCEED] || tsc->data[SC__INVISIBILITY]) ){
@@ -3904,21 +3893,43 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
 				skillratio += status_get_int(src) * 2;
 			}
 			break;
-		case SR_FALLENEMPIRE:// ATK [(Skill Level x 150 + 100) x Caster Base Level / 150] %
-			skillratio += 150 *skill_lv;
+
+		case SR_DRAGONCOMBO:
+		case SR_FLASHCOMBO_ATK_STEP1:
+			skillratio += 40 * skill_lv;
+			RE_LVL_DMOD(100);
+			break;
+		case SR_FALLENEMPIRE:
+		case SR_FLASHCOMBO_ATK_STEP2:
+			// ATK [(Skill Level x 150 + 100) x Caster Base Level / 150] %
+			skillratio += 150 * skill_lv;
 			RE_LVL_DMOD(150);
  			break;
-		case SR_TIGERCANNON:// ATK [((Caster consumed HP + SP) / 4) x Caster Base Level / 100] %
+		case SR_TIGERCANNON:
+		case SR_FLASHCOMBO_ATK_STEP3:
 			{
-				int hp = (int64)status_get_max_hp(src) * (10 + 2 * skill_lv) / 100,
-					sp = (int64)status_get_max_sp(src) * (5 + 1 * skill_lv) / 100;
-				if( sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE ) // ATK [((Caster consumed HP + SP) / 2) x Caster Base Level / 100] %
-					skillratio = ((int64)hp+sp) / 2;
+				int hp = sstatus->max_hp * (10 + 2 * skill_lv) / 100, // skill_get_hp_rate(SR_TIGERCANNON, skill_lv)
+					sp = sstatus->max_sp * (5 + 1 * skill_lv) / 100; // skill_get_sp_rate(SR_TIGERCANNON, skill_lv)
+				if( sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE )
+					// Base_Damage = [((Caster consumed HP + SP) / 2) x Caster Base Level / 100] %
+					skillratio += ((hp+sp) / 2);
 				else
-					skillratio = ((int64)hp+sp) / 4;
+					// Base_Damage = [((Caster consumed HP + SP) / 4) x Caster Base Level / 100] %
+					skillratio += ((hp+sp) / 4);
 				RE_LVL_DMOD(100);
 			}
 			break;
+		case SR_SKYNETBLOW:
+		case SR_FLASHCOMBO_ATK_STEP4:
+			if( sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_DRAGONCOMBO )
+				//ATK [{(Skill Level x 100) + (Caster AGI) + 150} x Caster Base Level / 100] %
+				skillratio += (100 * skill_lv + sstatus->agi + 150);
+			else
+				//ATK [{(Skill Level x 80) + (Caster AGI)} x Caster Base Level / 100] %
+				skillratio += (80 * skill_lv + sstatus->agi);
+			RE_LVL_DMOD(100);
+			break;
+
 		case SR_RAMPAGEBLASTER:
 			skillratio = 20 * skill_lv * ((sd) ? sd->spiritball_old : 5);
 			if( sc && sc->data[SC_EXPLOSIONSPIRITS] ) {
@@ -4245,16 +4256,20 @@ static int battle_calc_skill_constant_addition(struct Damage wd, struct block_li
 				atk = damagevalue;
 			}
 			break;
-		case SR_TIGERCANNON: // (Tiger Cannon skill level x 240) + (Target Base Level x 40)
-			if( sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE ) // (Tiger Cannon skill level x 500) + (Target Base Level x 40)
+		case SR_TIGERCANNON:
+		case SR_FLASHCOMBO_ATK_STEP3:
+			// (Tiger Cannon skill level x 240) + (Target Base Level x 40)
+			if( skill_id == SR_FLASHCOMBO_ATK_STEP3 || (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE) )
 				atk = ( skill_lv * 500 + status_get_lv(target) * 40 );
 			else
 				atk = ( skill_lv * 240 + status_get_lv(target) * 40 );
 			break;
-		case SR_FALLENEMPIRE:// [(Target Size value + Skill Level - 1) x Caster STR] + [(Target current weight x Caster DEX / 120)]
-			atk = ( ((tstatus->size+1)*2 + skill_lv - 1) * status_get_str(src));
+		case SR_FALLENEMPIRE:
+		case SR_FLASHCOMBO_ATK_STEP2:
+			// [(Target Size value + Skill Level - 1) x Caster STR] + [(Target current weight x Caster DEX / 120)]
+			atk = ( ((tstatus->size+1)*2 + skill_lv - 1) * sstatus->str);
 			if( tsd && tsd->weight )
-				atk += ( (tsd->weight/10) * status_get_dex(src) / 120 );
+				atk += ( (tsd->weight/10) * sstatus->dex / 120 );
 			else
 				atk += ( status_get_lv(target) * 50 ); //mobs
 			break;
@@ -4399,6 +4414,14 @@ struct Damage battle_attack_sc_bonus(struct Damage wd, struct block_list *src, s
 					break;
 			}
 		}
+
+		if (sc->data[SC_FLASHCOMBO]) {
+			ATK_ADD(wd.damage, wd.damage2, sc->data[SC_FLASHCOMBO]->val2);
+#ifdef RENEWAL
+			ATK_ADD(wd.equipAtk, wd.equipAtk2, sc->data[SC_FLASHCOMBO]->val2);
+#endif
+		}
+
 		if((wd.flag&(BF_LONG|BF_MAGIC)) == BF_LONG) { // Monster Transformation bonus
 			if (sc->data[SC_MTF_RANGEATK]) {
 				ATK_ADDRATE(wd.damage, wd.damage2, sc->data[SC_MTF_RANGEATK]->val1);
@@ -5140,7 +5163,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 	// check if we're landing a hit
 	if(!is_attack_hitting(wd, src, target, skill_id, skill_lv, true))
 		wd.dmg_lv = ATK_FLEE;
-	else if(!is_infinite_defense(target, wd.flag)) { //no need for math against plants
+	else if(wd.miscflag&8 || !is_infinite_defense(target, wd.flag)) { //no need for math against plants
 		int ratio, i = 0;
 
 		wd = battle_calc_skill_base_damage(wd, src, target, skill_id, skill_lv); // base skill damage
@@ -5382,7 +5405,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
 	DAMAGE_DIV_FIX_RENEWAL(wd, wd.div_);
 #endif
 	// only do 1 dmg to plant, no need to calculate rest
-	if(is_infinite_defense(target, wd.flag))
+	if(!(wd.miscflag&8) && is_infinite_defense(target, wd.flag))
 		return battle_calc_attack_plant(wd, src, target, skill_id, skill_lv);
 
 	//Apply DAMAGE_DIV_FIX and check for min damage

+ 1 - 0
src/map/battle.h

@@ -81,6 +81,7 @@ struct block_list;
 // Damage Calculation
 
 struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct block_list *target,uint16 skill_id,uint16 skill_lv,int flag);
+struct Damage battle_calc_attack_plant(struct Damage wd, struct block_list *src,struct block_list *target, uint16 skill_id, uint16 skill_lv);
 
 int64 battle_calc_return_damage(struct block_list *bl, struct block_list *src, int64 *, int flag, uint16 skill_id, bool status_reflect);
 

+ 62 - 28
src/map/skill.c

@@ -1464,10 +1464,12 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
 			skill_castend_damage_id(src,bl,LG_PINPOINTATTACK,rnd_value(1, pc_checkskill(sd,LG_PINPOINTATTACK)),tick,0);
 		break;
 	case SR_DRAGONCOMBO:
-		sc_start(src,bl, SC_STUN, 1 + skill_lv, skill_lv, skill_get_time(skill_id, skill_lv));
+	case SR_FLASHCOMBO_ATK_STEP1:
+		sc_start(src,bl, SC_STUN, 1 + skill_lv, skill_lv, skill_get_time(SR_DRAGONCOMBO, skill_lv));
 		break;
 	case SR_FALLENEMPIRE:
-		sc_start(src,bl, SC_STOP, 100, skill_lv, skill_get_time(skill_id, skill_lv));
+	case SR_FLASHCOMBO_ATK_STEP2:
+		sc_start(src,bl, SC_STOP, 100, skill_lv, skill_get_time(SR_FALLENEMPIRE, skill_lv));
 		break;
 	case SR_WINDMILL:
 		if( dstsd )
@@ -2421,6 +2423,7 @@ int skill_strip_equip(struct block_list *src,struct block_list *bl, unsigned sho
 * [2] counts how many targets have been processed. counter is added in skill_area_sub if the foreach function flag is: flag&(SD_SPLASH|SD_PREAMBLE)
 */
 static int skill_area_temp[8];
+static int64 skill_area_temp_i64[1];
 
 /**
  Used to knock back players, monsters, traps, etc
@@ -2891,8 +2894,10 @@ void skill_attack_blow(struct block_list *src, struct block_list *dsrc, struct b
  *        flag&1
  *        flag&2 - Disable re-triggered by double casting
  *        flag&4 - Skip to blow target (because already knocked back before skill_attack somewhere)
+ *        flag&8 - Force assume the target is not as is_infinite_defense() on in battle_calc_attack() first.
+ *                 Once it's done, store the damage to skill_area_temp_i64[0] then re-calcuate for real against 'plant'.
  *
- *        flag&0xFFF is passed to the underlying battle_calc_attack for processing
+ *        flag&0xFFF is passed to the underlying battle_calc_attack for processing.
  *             (usually holds number of targets, or just 1 for simple splash attacks)
  *
  *        flag&0xF000 - Values from enum e_skill_display
@@ -3059,6 +3064,14 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
 		skill_id == MER_INCAGI || skill_id == MER_BLESSING) && tsd->sc.data[SC_CHANGEUNDEAD] )
 		damage = 1;
 
+	if (flag&8) {
+		skill_area_temp_i64[0] = damage;
+		if (is_infinite_defense(bl, dmg.flag)) {
+			dmg = battle_calc_attack_plant(dmg, src, bl, skill_id, skill_lv);
+			damage = dmg.damage + dmg.damage2;
+		}
+	}
+
 	if( damage && tsc && tsc->data[SC_GENSOU] && dmg.flag&BF_MAGIC ){
 		struct block_list *nbl;
 		nbl = battle_getenemyarea(bl,bl->x,bl->y,2,BL_CHAR,bl->id);
@@ -3760,10 +3773,10 @@ static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data)
 					case WL_TETRAVORTEX_WIND:
 					case WL_TETRAVORTEX_GROUND:
 					// For SR_FLASHCOMBO
-					case SR_DRAGONCOMBO:
-					case SR_FALLENEMPIRE:
-					case SR_TIGERCANNON:
-					case SR_SKYNETBLOW:
+					case SR_FLASHCOMBO_ATK_STEP1:
+					case SR_FLASHCOMBO_ATK_STEP2:
+					case SR_FLASHCOMBO_ATK_STEP3:
+					case SR_FLASHCOMBO_ATK_STEP4:
 						break; // Exceptions
 					default:
 						continue; // Caster is Dead
@@ -3913,14 +3926,15 @@ static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data)
 						break;
 					}
 				// For SR_FLASHCOMBO
-				case SR_DRAGONCOMBO:
-				case SR_FALLENEMPIRE:
-				case SR_TIGERCANNON:
-				case SR_SKYNETBLOW:
+				case SR_FLASHCOMBO_ATK_STEP1:
+				case SR_FLASHCOMBO_ATK_STEP2:
+				case SR_FLASHCOMBO_ATK_STEP3:
+				case SR_FLASHCOMBO_ATK_STEP4:
 					if( src->type == BL_PC ) {
+						const int use_skill_lv[] = { SR_DRAGONCOMBO, SR_FALLENEMPIRE, SR_TIGERCANNON, SR_SKYNETBLOW };
 						if( distance_xy(src->x, src->y, target->x, target->y) >= 3 )
 							break;
-						skill_castend_damage_id(src, target, skl->skill_id, pc_checkskill(((TBL_PC *)src), skl->skill_id), tick, 0);
+						skill_castend_damage_id(src, target, skl->skill_id, pc_checkskill(((TBL_PC *)src), use_skill_lv[skl->skill_id-SR_FLASHCOMBO_ATK_STEP1]), tick, 0);
 					}
 					break;
 				case SC_ESCAPE:
@@ -4041,10 +4055,10 @@ int skill_cleartimerskill (struct block_list *src)
 				case WL_TETRAVORTEX_WIND:
 				case WL_TETRAVORTEX_GROUND:
 				// For SR_FLASHCOMBO
-				case SR_DRAGONCOMBO:
-				case SR_FALLENEMPIRE:
-				case SR_TIGERCANNON:
-				case SR_SKYNETBLOW:
+				case SR_FLASHCOMBO_ATK_STEP1:
+				case SR_FLASHCOMBO_ATK_STEP2:
+				case SR_FLASHCOMBO_ATK_STEP3:
+				case SR_FLASHCOMBO_ATK_STEP4:
 					continue;
 			}
 			delete_timer(ud->skilltimerskill[i]->timer, skill_timerskill);
@@ -4237,6 +4251,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
 	case LG_OVERBRAND:
 	case LG_OVERBRAND_BRANDISH:
 	case SR_FALLENEMPIRE:
+	case SR_FLASHCOMBO_ATK_STEP2:
 	case SR_CRESCENTELBOW_AUTOSPELL:
 	case SR_GATEOFHELL:
 	case SR_GENTLETOUCH_QUIET:
@@ -4467,6 +4482,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
 	case LG_EARTHDRIVE:
 	case SR_RAMPAGEBLASTER:
 	case SR_SKYNETBLOW:
+	case SR_FLASHCOMBO_ATK_STEP4:
 	case SR_WINDMILL:
 	case SR_RIDEINLIGHTNING:
 	case WM_SOUND_OF_DESTRUCTION:
@@ -5247,6 +5263,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
 		break;
 
 	case SR_DRAGONCOMBO:
+	case SR_FLASHCOMBO_ATK_STEP1:
 		skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
 		break;
 
@@ -5298,17 +5315,30 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
 		break;
 
 	case SR_TIGERCANNON:
-		if ( flag&1 ) {
-			skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
-			status_zap(bl, 0, status_get_max_sp(bl) * 10 / 100);
-		} else if ( sd ) {
-			int hpcost = 10 + 2 * skill_lv, spcost = 5 + 1 * skill_lv;
-			if (!status_charge(src, status_get_max_hp(src) * hpcost / 100, status_get_max_sp(src) * spcost / 100)) {
-				if (sd)
-					clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
-				break;
+	case SR_FLASHCOMBO_ATK_STEP3:
+		if (flag&1) {
+			if (skill_area_temp[3] == skill_id && skill_area_temp_i64[0]) { // Safe check
+				if (skill_area_temp[1] != bl->id) {
+					int64 dmg = skill_area_temp_i64[0];
+					bool infdef = is_infinite_defense(bl, skill_get_type(skill_id));
+					if (infdef)
+						dmg = 1;
+					status_damage(src, bl, dmg, 0, 0, 0);
+					status_zap(bl, 0, status_get_max_sp(bl) * 10 / 100);
+					clif_skill_damage(src, bl, tick, status_get_amotion(bl), 0, dmg, 1, skill_id, skill_lv, 6);
+				}
 			}
-			map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_damage_id);
+			else { // Somehow, we failed
+				skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
+				status_zap(bl, 0, status_get_max_sp(bl) * 10 / 100);
+			}
+		}
+		else if (sd) {
+			skill_area_temp[1] = bl->id;
+			skill_area_temp[3] = skill_id;
+			skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag|8); // Only do attack calculation once
+			status_zap(bl, 0, status_get_max_sp(bl) * 10 / 100);
+			map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id);
 		}
 		break;
 
@@ -6557,6 +6587,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 	case NC_AXETORNADO:
 	case GC_COUNTERSLASH:
 	case SR_SKYNETBLOW:
+	case SR_FLASHCOMBO_ATK_STEP4:
 	case SR_RAMPAGEBLASTER:
 	case SR_HOWLINGOFLION:
 	case KO_HAPPOKUNAI:
@@ -9519,14 +9550,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 			sc_start(src,bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)));
 		break;
 	case SR_FLASHCOMBO: {
-		const int combo[] = { SR_DRAGONCOMBO, SR_FALLENEMPIRE, SR_TIGERCANNON, SR_SKYNETBLOW };
+		const int combo[] = { SR_FLASHCOMBO_ATK_STEP1, SR_FLASHCOMBO_ATK_STEP2, SR_FLASHCOMBO_ATK_STEP3, SR_FLASHCOMBO_ATK_STEP4 };
+		const int delay[] = { 0, 250, 500, 2000 };
 
 		if (sd)
 			sd->ud.attackabletime = sd->canuseitem_tick = sd->ud.canact_tick;
 		clif_skill_nodamage(src,bl,skill_id,skill_lv,
 			sc_start2(src,bl,type,100,skill_lv,bl->id,skill_get_time(skill_id,skill_lv)));
 		for (i = 0; i < ARRAYLENGTH(combo); i++)
-			skill_addtimerskill(src,tick + 500 * i,bl->id,0,0,combo[i],skill_lv,BF_WEAPON,flag|SD_LEVEL);
+			skill_addtimerskill(src,tick + delay[i],bl->id,0,0,combo[i],skill_lv,BF_WEAPON,flag|SD_LEVEL);
 	}
 	break;
 
@@ -15820,6 +15852,8 @@ int skill_delayfix (struct block_list *bl, uint16 skill_id, uint16 skill_lv)
 	case CH_CHAINCRUSH:
 	case SR_DRAGONCOMBO:
 	case SR_FALLENEMPIRE:
+	case SR_FLASHCOMBO_ATK_STEP1:
+	case SR_FLASHCOMBO_ATK_STEP2:
 		//If delay not specified, it will be 1000 - 4*agi - 2*dex
 		if (time == 0)
 			time = 1000;

+ 4 - 4
src/map/skill.h

@@ -1720,10 +1720,10 @@ enum e_skill {
 	WL_TELEKINESIS_INTENSE,
 	LG_KINGS_GRACE,
 	ALL_FULL_THROTTLE,
-	SR_FLASHCOMBO_ATK_STEP1,
-	SR_FLASHCOMBO_ATK_STEP2,
-	SR_FLASHCOMBO_ATK_STEP3,
-	SR_FLASHCOMBO_ATK_STEP4,
+	SR_FLASHCOMBO_ATK_STEP1, // SR_DRAGONCOMBO
+	SR_FLASHCOMBO_ATK_STEP2, // SR_FALLENEMPIRE
+	SR_FLASHCOMBO_ATK_STEP3, // SR_TIGERCANNON
+	SR_FLASHCOMBO_ATK_STEP4, // SR_SKYNETBLOW
 
 	HLIF_HEAL = 8001,
 	HLIF_AVOID,

+ 2 - 3
src/map/status.c

@@ -709,7 +709,8 @@ void initChangeTables(void)
 	set_sc( SR_GENTLETOUCH_ENERGYGAIN	, SC_GT_ENERGYGAIN	, SI_GENTLETOUCH_ENERGYGAIN	, SCB_NONE );
 	set_sc( SR_GENTLETOUCH_CHANGE		, SC_GT_CHANGE		, SI_GENTLETOUCH_CHANGE		, SCB_WATK|SCB_MDEF|SCB_ASPD );
 	set_sc( SR_GENTLETOUCH_REVITALIZE	, SC_GT_REVITALIZE	, SI_GENTLETOUCH_REVITALIZE	, SCB_MAXHP|SCB_REGEN );
-	set_sc( SR_FLASHCOMBO			, SC_FLASHCOMBO		, SI_FLASHCOMBO			, SCB_WATK );
+	set_sc( SR_FLASHCOMBO			, SC_FLASHCOMBO		, SI_FLASHCOMBO			, SCB_NONE );
+	add_sc( SR_FLASHCOMBO_ATK_STEP1	, SC_STUN		);
 
 	/* Wanderer / Minstrel */
 	set_sc( WA_SWING_DANCE			, SC_SWINGDANCE			, SI_SWINGDANCE			, SCB_SPEED|SCB_ASPD );
@@ -5467,8 +5468,6 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan
 		watk += sc->data[SC_PYROCLASTIC]->val2;
 	if(sc->data[SC_ANGRIFFS_MODUS])
 		watk += watk * sc->data[SC_ANGRIFFS_MODUS]->val2/100;
-	if( sc->data[SC_FLASHCOMBO] )
-		watk += sc->data[SC_FLASHCOMBO]->val2;
 	if(sc->data[SC_ODINS_POWER])
 		watk += 40 + 30 * sc->data[SC_ODINS_POWER]->val1;