Explorar el Código

Corrected Soul Reaper soul energy Matk bonus (#8767)

Fixed #8766
Atemo hace 6 meses
padre
commit
3b40c922cc
Se han modificado 8 ficheros con 58 adiciones y 54 borrados
  1. 2 0
      db/pre-re/status.yml
  2. 2 0
      db/re/status.yml
  3. 2 2
      src/map/atcommand.cpp
  4. 1 5
      src/map/battle.cpp
  5. 27 35
      src/map/pc.cpp
  6. 2 2
      src/map/pc.hpp
  7. 1 1
      src/map/skill.cpp
  8. 21 9
      src/map/status.cpp

+ 2 - 0
db/pre-re/status.yml

@@ -6944,6 +6944,8 @@ Body:
     DurationLookup: SP_SOULDIVISION
   - Status: Soulenergy
     Icon: EFST_SOULENERGY
+    CalcFlags:
+      Matk: true
   - Status: Use_Skill_Sp_Spa
     Icon: EFST_USE_SKILL_SP_SPA
     Flags:

+ 2 - 0
db/re/status.yml

@@ -7294,6 +7294,8 @@ Body:
     DurationLookup: SP_SOULDIVISION
   - Status: Soulenergy
     Icon: EFST_SOULENERGY
+    CalcFlags:
+      Matk: true
     Flags:
       NoRemoveOnDead: true
       NoClearbuff: true

+ 2 - 2
src/map/atcommand.cpp

@@ -3836,8 +3836,8 @@ ACMD_FUNC(soulball)
 	}
 
 	if (sd->soulball > 0)
-		pc_delsoulball(sd, sd->soulball, true);
-	sd->soulball = number;
+		pc_delsoulball( *sd, sd->soulball, true );
+	pc_addsoulball( *sd, number );
 	clif_soulball(sd);
 
 	return 0;

+ 1 - 5
src/map/battle.cpp

@@ -1996,7 +1996,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
 		if (tsd && (sce = sc->getSCE(SC_SOULREAPER))) {
 			if (rnd()%100 < sce->val2 && tsd->soulball < MAX_SOUL_BALL) {
 				clif_specialeffect(src, 1208, AREA);
-				pc_addsoulball(tsd, 5 + 3 * pc_checkskill(tsd, SP_SOULENERGY));
+				pc_addsoulball( *tsd, 1, 5 + 3 * pc_checkskill(tsd, SP_SOULENERGY) );
 			}
 		}
 	} //End of caster SC_ check
@@ -7934,10 +7934,6 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
 					MATK_ADD(sstatus->matk_min);
 				}
 
-				if (sd) { // Soul energy spheres adds MATK.
-					MATK_ADD(3*sd->soulball);
-				}
-
 				if (nk[NK_SPLASHSPLIT]) { // Divide MATK in case of multiple targets skill
 					if (mflag>0)
 						ad.damage /= mflag;

+ 27 - 35
src/map/pc.cpp

@@ -907,61 +907,53 @@ void pc_delspiritball(map_session_data *sd,int count,int type)
 /**
  * Adds a soulball to player
  * @param sd: Player data
+ * @param number: Amount to give
  * @param max: Max amount of soulballs
  */
-int pc_addsoulball(map_session_data *sd, int max)
-{
-	nullpo_ret(sd);
+void pc_addsoulball( map_session_data& sd, int32 number, int32 max ) {
+	status_change *sc = status_get_sc(&sd.bl);
 
-	status_change *sc = status_get_sc(&sd->bl);
+	// Save previous soulball number
+	int32 val = sd.soulball;
 
-	if (sc == nullptr || sc->getSCE(SC_SOULENERGY) == nullptr) {
-		sc_start(&sd->bl, &sd->bl, SC_SOULENERGY, 100, 0, skill_get_time2(SP_SOULCOLLECT, 1));
-		sd->soulball = 0;
-	}
+	if (sc == nullptr || sc->getSCE(SC_SOULENERGY) == nullptr)
+		sd.soulball = 0;
 
 	max = min(max, MAX_SOUL_BALL);
-	sd->soulball = cap_value(sd->soulball, 0, MAX_SOUL_BALL);
+	sd.soulball += number;
+	sd.soulball = cap_value(sd.soulball, 0, max);
 
-	if (sd->soulball && sd->soulball >= max)
-		sd->soulball--;
+	// Refresh the SC_SOULENERGY timer (which is 10 minutes by default) if the number has changed. The soul is removed when the timer expire.
+	if (sd.soulball != val)
+		sc_start( &sd.bl, &sd.bl, SC_SOULENERGY, 100, sd.soulball, skill_get_time2(SP_SOULCOLLECT, 1));
 
-	sd->soulball++;
-	sc_start(&sd->bl, &sd->bl, SC_SOULENERGY, 100, sd->soulball, skill_get_time2(SP_SOULCOLLECT, 1));
-	clif_soulball(sd);
-
-	return 0;
+	clif_soulball(&sd);
 }
 
 /**
  * Removes number of soulball from player
  * @param sd: Player data
  * @param count: Amount to remove
- * @param type: true = doesn't give client effect
+ * @param no_client_effect: true = doesn't give client effect
  */
-int pc_delsoulball(map_session_data *sd, int count, bool type)
-{
-	nullpo_ret(sd);
-
+void pc_delsoulball( map_session_data& sd, int32 count, bool no_client_effect ) {
 	if (count <= 0)
-		return 0;
+		return;
 
-	status_change *sc = status_get_sc(&sd->bl);
+	status_change *sc = status_get_sc(&sd.bl);
 
-	if (sd->soulball <= 0 || sc == nullptr || sc->getSCE(SC_SOULENERGY) == nullptr) {
-		sd->soulball = 0;
-	}else{
-		sd->soulball -= cap_value(count, 0, sd->soulball);
-		if (sd->soulball == 0)
-			status_change_end(&sd->bl, SC_SOULENERGY);
+	if (sd.soulball <= 0)
+		sd.soulball = 0;
+	else {
+		sd.soulball -= cap_value(count, 0, sd.soulball);
+		if (sd.soulball == 0)
+			status_change_end(&sd.bl, SC_SOULENERGY);
 		else
-			sc->getSCE(SC_SOULENERGY)->val1 = sd->soulball;
+			sc_start( &sd.bl, &sd.bl, SC_SOULENERGY, 100, sd.soulball, skill_get_time2(SP_SOULCOLLECT, 1));	// refresh val1 and status MATK
 	}
 
-	if (!type)
-		clif_soulball(sd);
-
-	return 0;
+	if (!no_client_effect)
+		clif_soulball(&sd);
 }
 
 /**
@@ -9769,7 +9761,7 @@ int pc_dead(map_session_data *sd,struct block_list *src)
 	if ( sd->spiritball !=0 )
 		pc_delspiritball(sd,sd->spiritball,0);
 	if (sd->soulball != 0)
-		pc_delsoulball(sd, sd->soulball, false);
+		pc_delsoulball( *sd, sd->soulball );
 	if (sd->servantball != 0)
 		pc_delservantball( *sd, sd->servantball );
 	if (sd->abyssball != 0)

+ 2 - 2
src/map/pc.hpp

@@ -1655,8 +1655,8 @@ void pc_delinvincibletimer(map_session_data* sd);
 
 void pc_addspiritball(map_session_data *sd,int interval,int max);
 void pc_delspiritball(map_session_data *sd,int count,int type);
-int pc_addsoulball(map_session_data *sd, int max);
-int pc_delsoulball(map_session_data *sd, int count, bool type);
+void pc_addsoulball( map_session_data& sd, int32 number, int32 max = MAX_SOUL_BALL );
+void pc_delsoulball( map_session_data& sd, int32 count, bool no_client_effect = false );
 void pc_addservantball( map_session_data& sd, int count = 1 );
 void pc_delservantball( map_session_data& sd, int count = 1 );
 void pc_addabyssball( map_session_data& sd, int count = 1 );

+ 1 - 1
src/map/skill.cpp

@@ -18749,7 +18749,7 @@ void skill_consume_requirement(map_session_data *sd, uint16 skill_id, uint16 ski
 				case SP_SOULREAPER:
 				case SP_SOULEXPLOSION:
 				case SP_KAUTE:
-					pc_delsoulball(sd, require.spiritball, false);
+					pc_delsoulball( *sd, require.spiritball );
 					break;
 
 				// Skills that require servants.

+ 21 - 9
src/map/status.cpp

@@ -6164,6 +6164,12 @@ void status_calc_bl_main(struct block_list& bl, std::bitset<SCB_MAX> flag)
 			matk_max += matk_max * sc->getSCE(SC_MAGICPOWER)->val3 / 100;
 		}
 
+		// Custom since JOB_SOUL_REAPER does not exist in pre-renewal
+		if (sd != nullptr) {
+			matk_min += 3 * sd->soulball;
+			matk_max += 3 * sd->soulball;
+		}
+
 		status->matk_min = static_cast<uint16>( cap_value(matk_min,0,USHRT_MAX) );
 		status->matk_max = static_cast<uint16>( cap_value(matk_max,0,USHRT_MAX) );
 #else
@@ -6175,6 +6181,10 @@ void status_calc_bl_main(struct block_list& bl, std::bitset<SCB_MAX> flag)
 		int32 matk_max = status_base_matk_max(&bl, status, lv);
 
 		if (sd != nullptr) {
+			// Soul energy spheres increase MATK (not displayed in status window).
+			matk_min += 3 * sd->soulball;
+			matk_max += 3 * sd->soulball;
+
 			// Weapon magic attack modifiers. WeaponMATK = BaseWeaponDamage + Variance + RefinementBonus
 			// RefinementBonus is currently included with BaseWeaponDamage in status->lhw.matk and status->rhw.matk
 			// BaseWeaponDamage and RefinementBonus are visible on the player status window.
@@ -12767,7 +12777,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			val2 = 5 + 3 * val2; // Max Soul Sphere's.
 			val3 = tick > 0 ? tick : 60000;
 			tick_time = tick;
-			tick = INFINITE_TICK;
+			tick = INFINITE_TICK; // Duration sent to the client should be infinite
 			break;
 		case SC_SP_SHA:
 			val2 = 50; // Move speed reduction
@@ -13915,8 +13925,13 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
 				pc_delspiritball(sd, 1, 0);
 			break;
 		case SC_SOULENERGY:
-			if (sd)
-				pc_delsoulball(sd, sd->soulball, false);
+			if (sd != nullptr && sd->soulball > 0) {
+				// When SC_SOULENERGY ends, removes all soulball if SC_SOULCOLLECT is active otherwise 1
+				if (sc->getSCE(SC_SOULCOLLECT))
+					pc_delsoulball( *sd, sd->soulball );
+				else
+					pc_delsoulball( *sd, 1 );
+			}
 			break;
 		case SC_MADOGEAR:
 			status_db.removeByStatusFlag(bl, { SCF_MADOENDCANCEL });
@@ -15030,12 +15045,9 @@ TIMER_FUNC(status_change_timer){
 		}
 		break;
 	case SC_SOULCOLLECT:
-		pc_addsoulball(sd, sce->val2);
-		if (sd->soulball < sce->val2) {
-			sc_timer_next(sce->val3 + tick);
-			return 0;
-		}
-		break;
+		pc_addsoulball( *sd, 1, sce->val2 );
+		sc_timer_next(sce->val3 + tick);
+		return 0;
 	case SC_HELPANGEL:
 		if (--(sce->val4) >= 0) {
 			status_heal(bl, 1000, 350, 0);	// Heal amount not displayed