Просмотр исходного кода

Bug Fixes
* Fixed #376, status def for Voice of Siren effect (WM_VOICEOFSIREN) is calculated twice
* Fixed SC_DEEPSLEEP effect from Deep Sleep Lullaby (WM_LULLABY_DEEPSLEEP) and Arrullo (SO_ARRULLO)
* WM_VOICEOFSIREN & WM_LULLABY_DEEPSLEEP give effect for all targets except self
* Typos

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

Cydh Ramdh 10 лет назад
Родитель
Сommit
20c6149b60
6 измененных файлов с 74 добавлено и 41 удалено
  1. 1 1
      db/re/skill_cast_db.txt
  2. 1 1
      db/re/skill_db.txt
  3. 15 14
      src/map/battle.h
  4. 28 22
      src/map/skill.c
  5. 26 3
      src/map/status.c
  6. 3 0
      src/map/status.h

+ 1 - 1
db/re/skill_cast_db.txt

@@ -1547,7 +1547,7 @@
 2453,1000:1500:2000:2500:3000,1000,0,4000:6000:8000:10000:12000,1000,5000,-1
 //-- SO_VARETYR_SPEAR
 2454,2200:2400:2600:2800:3000,1000,0,0,2200:2400:2600:2800:3000,2000,1800:1600:1400:1200:1000
-//-- SO_ARULLO
+//-- SO_ARRULLO
 2455,2200:2400:2600:2800:3000,1000,0,8000:10000:12000:14000:16000,0,5000:6000:7000:8000:9000,800:600:400:200:-1
 //-- SO_EL_CONTROL
 2456,2000,0,0,0,0,5000,0

+ 1 - 1
db/re/skill_db.txt

@@ -1145,7 +1145,7 @@
 2417,11,6,2,0,0x3,5,1,1,no,0,0,0,none,0,0x0,	WM_DOMINION_IMPULSE,Dominion Impulse
 2418,9,6,2,0,0x1,0,5,1,yes,0,0,0,none,0,0x0,	WM_SEVERE_RAINSTORM,Severe Rainstorm
 2419,9,6,2,0,0x3,1,5,1,yes,0,0x80,5,none,0,0x0,	WM_POEMOFNETHERWORLD,Poem of The Netherworld
-2420,0,6,4,0,0x2,2:3:4:5:6,5,1,yes,0,0,0,none,0,0x0,	WM_VOICEOFSIREN,Voice of Siren
+2420,0,6,4,0,0x3,2:3:4:5:6,5,1,yes,0,0,0,none,0,0x0,	WM_VOICEOFSIREN,Voice of Siren
 2421,7,6,16,0,0x1,0,5,1,yes,0,0,0,none,0,0x0,	WM_DEADHILLHERE,Valley of Death
 2422,0,6,4,0,0x3,5:6:7:8:9,5,1,yes,0,0,0,none,0,0x0,	WM_LULLABY_DEEPSLEEP,Deep Sleep Lullaby
 2423,0,6,4,0,0x3,3:4:5:6:7,5,1,yes,0,0,0,none,0,0x0,	WM_SIRCLEOFNATURE,Circle of Nature's Sound

+ 15 - 14
src/map/battle.h

@@ -37,20 +37,21 @@ enum e_battle_flag {
 
 /// Battle check target [Skotlex]
 enum e_battle_check_target {
-	BCT_NOONE		= 0x000000, /// No one
-	BCT_SELF		= 0x010000, /// Self
-	BCT_ENEMY		= 0x020000, /// Enemy
-	BCT_PARTY		= 0x040000, /// Party members
-	BCT_GUILDALLY	= 0x080000, /// Only allies, NOT guildmates
-	BCT_NEUTRAL		= 0x100000, /// Neutral target
-	BCT_SAMEGUILD	= 0x200000, /// Guildmates, No Guild Allies
-
-	BCT_ALL			= 0x3F0000, /// All targets
-
-	BCT_GUILD		= BCT_SAMEGUILD|BCT_GUILDALLY, /// Guild AND Allies (BCT_SAMEGUILD|BCT_GUILDALLY)
-	BCT_NOGUILD		= BCT_ALL&~BCT_GUILD, /// Except guildmates
-	BCT_NOPARTY		= BCT_ALL&~BCT_PARTY, /// Except party members
-	BCT_NOENEMY		= BCT_ALL&~BCT_ENEMY, /// Except enemy
+	BCT_NOONE		= 0x000000, ///< No one
+	BCT_SELF		= 0x010000, ///< Self
+	BCT_ENEMY		= 0x020000, ///< Enemy
+	BCT_PARTY		= 0x040000, ///< Party members
+	BCT_GUILDALLY	= 0x080000, ///< Only allies, NOT guildmates
+	BCT_NEUTRAL		= 0x100000, ///< Neutral target
+	BCT_SAMEGUILD	= 0x200000, ///< Guildmates, No Guild Allies
+
+	BCT_ALL			= 0x3F0000, ///< All targets
+
+	BCT_ALLWOS		= BCT_ALL&~BCT_SELF,			///< All, except self (currently used for skipping if src == bl in skill_area_sub)
+	BCT_GUILD		= BCT_SAMEGUILD|BCT_GUILDALLY,	///< Guild AND Allies (BCT_SAMEGUILD|BCT_GUILDALLY)
+	BCT_NOGUILD		= BCT_ALL&~BCT_GUILD,			///< Except guildmates
+	BCT_NOPARTY		= BCT_ALL&~BCT_PARTY,			///< Except party members
+	BCT_NOENEMY		= BCT_ALL&~BCT_ENEMY,			///< Except enemy
 };
 
 /// Damage structure

+ 28 - 22
src/map/skill.c

@@ -3382,6 +3382,9 @@ int skill_area_sub(struct block_list *bl, va_list ap)
 	flag = va_arg(ap,int);
 	func = va_arg(ap,SkillFunc);
 
+	if (src == bl && !(flag&BCT_SELF))
+		return 0;
+
 	if(battle_check_target(src,bl,flag) > 0) {
 		// several splash skills need this initial dummy packet to display correctly
 		if (flag&SD_PREAMBLE && skill_area_temp[2] == 0)
@@ -9577,16 +9580,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 		break;
 
 	case WM_VOICEOFSIREN:
-		if( flag&1 ) {
-			tick = (status_get_lv(bl) > 150 ? 150 : status_get_lv(bl)) / 10 + (dstsd ? (dstsd->status.job_level > 50 ? 50 : dstsd->status.job_level) / 5 : 0);
-			sc_start2(src,bl,type,100,skill_lv,src->id,skill_get_time(skill_id,skill_lv) - (1000 * tick));
-		} else {
-			int rate = 6 * skill_lv + ((sd) ? pc_checkskill(sd,WM_LESSON) * 2 + (sd->status.job_level > 50 ? 50 : sd->status.job_level) / 2 : skill_get_max(WM_LESSON));
-
-			if (rnd()%100 < rate) {
-				map_foreachinrange(skill_area_sub, src, skill_get_splash(skill_id,skill_lv), BL_CHAR|BL_SKILL, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id);
-				clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
-			}
+		if (flag&1)
+			sc_start2(src,bl,type,skill_area_temp[5],skill_lv,src->id,skill_area_temp[6]);
+		else {
+			// Success chance: (Skill Level x 6) + (Voice Lesson Skill Level x 2) + (Caster’s Job Level / 2) %
+			skill_area_temp[5] = skill_lv * 6 + ((sd) ? pc_checkskill(sd, WM_LESSON) : skill_get_max(WM_LESSON)) * 2 + (sd ? sd->status.job_level : 50) / 2;
+			skill_area_temp[6] = skill_get_time(skill_id,skill_lv);
+			map_foreachinrange(skill_area_sub, src, skill_get_splash(skill_id,skill_lv), BL_CHAR|BL_SKILL, src, skill_id, skill_lv, tick, flag|BCT_ALLWOS|1, skill_castend_nodamage_id);
+			clif_skill_nodamage(src,bl,skill_id,skill_lv,1);
 		}
 		break;
 
@@ -9794,24 +9795,29 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 
 	case SO_ARRULLO:
 		{
-			// [(15 + 5 * Skill Level) + ( Caster's INT / 5 ) + ( Caster's Job Level / 5 ) - ( Target's INT / 6 ) - ( Target's LUK / 10 )] %
-			int rate = (15 + 5 * skill_lv) + status_get_int(src)/5 + (sd ? sd->status.job_level : 0);
-			rate -= status_get_int(bl)/6 - status_get_luk(bl)/10;
+			// Success chance: [(15 + 5 * Skill Level) + ( Caster's INT / 5 ) + ( Caster's Job Level / 5 ) - ( Target's INT / 6 ) - ( Target's LUK / 10 )] %
+			int rate = (15 + 5 * skill_lv) * 1000 + status_get_int(src) * 200 + (sd ? sd->status.job_level * 200 : 0) - status_get_int(bl) * 1000 / 6 - status_get_luk(bl) * 100;
+			struct status_data *bstatus = status_get_base_status(bl);
+			// Resistance: {(Target’s Base Level / 20) + (Target’s Base INT / 40)} seconds
+			int duration = skill_get_time(skill_id, skill_lv) - (status_get_baselevel_limit(bl, 150) * 50 + bstatus->int_ * 25);
 			clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
-			sc_start2(src,bl, type, rate, skill_lv, 1, skill_get_time(skill_id, skill_lv));
+			status_change_start(src,bl,type,rate,skill_lv,0,0,0,max(duration,5000),SCSTART_NORATEDEF|SCSTART_NOTICKDEF); // Avoid general resistance
 		}
 		break;
 
 	case WM_LULLABY_DEEPSLEEP:
-		if( flag&1 ){
-			//[(Skill Level x 4) + (Voice Lessons Skill Level x 2) + (Caster's Base Level / 15) + (Caster's Job Level / 5)] %
-			int rate = (4 * skill_lv) + ((sd) ? pc_checkskill(sd,WM_LESSON)*2 + sd->status.job_level/5 : skill_get_max(WM_LESSON)) + status_get_lv(src) / 15;
-			if( bl != src )
-				sc_start(src,bl,type,rate,skill_lv,skill_get_time(skill_id,skill_lv));
-		} else {
+		if (flag&1) {
+			struct status_data *bstatus = status_get_base_status(bl);
+			// Resistance: {(Target’s Base Level / 20) + (Target’s Base INT / 20)} seconds
+			int duration = skill_area_temp[6] - (status_get_baselevel_limit(bl, 150) * 50 + bstatus->int_ * 50);
+			status_change_start(src,bl,type,skill_area_temp[5],skill_lv,0,0,0,max(duration,5000),SCSTART_NORATEDEF|SCSTART_NOTICKDEF); // Avoid general resistance
+		}
+		else {
+			// Success chance: [(Skill Level x 4) + (Voice Lessons Skill Level x 2) + (Caster's Base Level / 15) + (Caster's Job Level / 5)] %
+			skill_area_temp[5] = (4 * skill_lv * 1000) + ((sd) ? pc_checkskill(sd,WM_LESSON) : skill_get_max(WM_LESSON)) * 2000 + (status_get_lv(src) * 1000 / 15) + (sd ? sd->status.job_level * 200 : 0);
+			skill_area_temp[6] = skill_get_time(skill_id,skill_lv);
 			clif_skill_nodamage(src, bl, skill_id, skill_lv, 1);
-			map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), BL_CHAR,
-							   src, skill_id, skill_lv, tick, flag|BCT_ALL|1, skill_castend_nodamage_id);
+			map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ALLWOS|1, skill_castend_nodamage_id);
 		}
 		break;
 

+ 26 - 3
src/map/status.c

@@ -7234,6 +7234,28 @@ void status_change_init(struct block_list *bl)
 	memset(sc, 0, sizeof (struct status_change));
 }
 
+/**
+ * Get base level of bl, cap the value by level_limit
+ * @param bl Object [BL_PC|BL_MOB|BL_HOM|BL_MER|BL_ELEM]
+ * @param level_limit Level cap
+ * @return Base level or level_limit
+ **/
+int status_get_baselevel_limit(struct block_list *bl, int level_limit) {
+	int lvl = status_get_lv(bl);
+	return min(lvl, level_limit);
+}
+
+/**
+ * Get job level of player, cap the value by level_limit.
+ * @param sd Player
+ * @param level_limit Level cap
+ * @return Job level or level_limit or 0 if not a player
+ **/
+int status_get_joblevel_limit(struct map_session_data *sd, int level_limit) {
+	int lvl = sd ? sd->status.job_level : 0;
+	return min(lvl, level_limit);
+}
+
 /**
  * Applies SC defense to a given status change
  * This function also determines whether or not the status change will be applied
@@ -7405,8 +7427,8 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
 			tick_def2 = (b_status->int_ + status_get_lv(bl))*50; // kRO balance update lists this formula
 			break;
 		case SC_NETHERWORLD:
-			tick_def2 = (status_get_lv(bl) > 150 ? 150 : status_get_lv(bl)) * 20 +
-				(sd ? (sd->status.job_level > 50 ? 50 : sd->status.job_level) * 100 : 0);
+			// Resistance: {(Target’s Base Level / 50) + (Target’s Job Level / 10)} seconds
+			tick_def2 = status_get_baselevel_limit(bl, 150) * 20 + status_get_joblevel_limit(sd, 50) * 100;
 			break;
 		case SC_MARSHOFABYSS:
 			// 5 second (Fixed) + 25 second - {( INT + LUK ) / 20 second }
@@ -7456,7 +7478,8 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
 			tick_def2 = (status->vit + status->luk)*50;
 			break;
 		case SC_VOICEOFSIREN:
-			tick_def2 = (status_get_lv(bl) * 100) + ((bl->type == BL_PC)?((TBL_PC*)bl)->status.job_level * 200 : 0);
+			// Resistance: {(Target’s Base Level / 10) + (Target’s Job Level / 5)} seconds
+			tick_def2 = status_get_baselevel_limit(bl, 150) * 100 + status_get_joblevel_limit(sd, 50) * 200;
 			break;
 		case SC_B_TRAP:
 			tick_def = b_status->str * 50; // (custom)

+ 3 - 0
src/map/status.h

@@ -2128,6 +2128,9 @@ int status_change_spread( struct block_list *src, struct block_list *bl );
 
 unsigned short status_base_atk(const struct block_list *bl, const struct status_data *status);
 
+int status_get_baselevel_limit(struct block_list *bl, int level_limit);
+int status_get_joblevel_limit(struct map_session_data *sd, int level_limit);
+
 void initChangeTables(void);
 int status_readdb(void);
 int do_init_status(void);