فهرست منبع

Overweight checks cleanup and fixes (#9177)

Daegaladh 1 ماه پیش
والد
کامیت
1a85e1c925
12فایلهای تغییر یافته به همراه84 افزوده شده و 70 حذف شده
  1. 13 4
      conf/battle/player.conf
  2. 4 0
      db/pre-re/status.yml
  3. 4 0
      db/re/status.yml
  4. 8 2
      src/map/battle.cpp
  5. 2 1
      src/map/battle.hpp
  6. 1 1
      src/map/buyingstore.cpp
  7. 2 6
      src/map/clif.cpp
  8. 36 36
      src/map/pc.cpp
  9. 2 4
      src/map/pc.hpp
  10. 7 11
      src/map/skill.cpp
  11. 4 4
      src/map/status.cpp
  12. 1 1
      src/map/status.hpp

+ 13 - 4
conf/battle/player.conf

@@ -60,10 +60,19 @@ natural_healsp_interval: 8000
 // Automatic healing skill's time interval. (in milliseconds)
 natural_heal_skill_interval: 10000
 
-// The maximum weight for a character to carry when the character stops healing naturally. (in %)
-// For renewal: Requires client 20171025 or newer to display properly
-natural_heal_weight_rate: 50
-natural_heal_weight_rate_renewal: 70
+// The maximum weight for a character to carry before it stops healing naturally. (Note 2)
+// Depending on this configuration you may need to change the corresponding TGA image file
+// in your data in order to show the proper percentage in the status icon.
+// Default on official servers: 50 for Pre-renewal, 70 for Renewal
+//natural_heal_weight_rate: 70
+
+// The maximum weight for a character to get an item from item boxes. (Note 2)
+// Default on official servers: 70 for Pre-renewal, 90 for Renewal
+//open_box_weight_rate: 90
+
+// The maximum weight for a character to carry before entering the major overweight state. (Note 2)
+// In this state the character cannot heal naturally, attack or use skills.
+major_overweight_rate: 90
 
 // Maximum atk speed. (Default 190, Highest allowed 199)
 max_aspd: 190

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

@@ -662,6 +662,8 @@ Body:
       NoBanishingBuster: true
       NoClearance: true
       NoForcedEnd: true
+    EndOnStart:
+      Weight90: true
   - Status: Weight90
     Icon: EFST_WEIGHTOVER90
     Flags:
@@ -673,6 +675,8 @@ Body:
       NoBanishingBuster: true
       NoClearance: true
       NoForcedEnd: true
+    EndOnStart:
+      Weight50: true
   - Status: Aspdpotion0
     Icon: EFST_ATTHASTE_POTION1
     CalcFlags:

+ 4 - 0
db/re/status.yml

@@ -689,6 +689,8 @@ Body:
       NoBanishingBuster: true
       NoClearance: true
       NoForcedEnd: true
+    EndOnStart:
+      Weight90: true
   - Status: Weight90
     Icon: EFST_WEIGHTOVER90
     Flags:
@@ -700,6 +702,8 @@ Body:
       NoBanishingBuster: true
       NoClearance: true
       NoForcedEnd: true
+    EndOnStart:
+      Weight50: true
   - Status: Aspdpotion0
     Icon: EFST_ATTHASTE_POTION1
     CalcFlags:

+ 8 - 2
src/map/battle.cpp

@@ -5498,7 +5498,7 @@ static int32 battle_calc_attack_skill_ratio(struct Damage* wd, struct block_list
 			if (wd->miscflag&4) { // ATK [(Skill Level x 150) + (1000 x Target current weight / Maximum weight) + (Target Base Level x 5) x (Caster Base Level / 150)] %
 				skillratio += -100 + 150 * skill_lv + status_get_lv(target) * 5;
 				if (tsd && tsd->weight)
-					skillratio += 100 * tsd->weight / tsd->max_weight;
+					skillratio += pc_getpercentweight(*tsd);
 				RE_LVL_DMOD(150);
 			} else {
 				if (status_get_class_(target) == CLASS_BOSS)
@@ -11612,8 +11612,13 @@ static const struct _battle_data {
 	{ "natural_healhp_interval",            &battle_config.natural_healhp_interval,         6000,   NATURAL_HEAL_INTERVAL, INT_MAX, },
 	{ "natural_healsp_interval",            &battle_config.natural_healsp_interval,         8000,   NATURAL_HEAL_INTERVAL, INT_MAX, },
 	{ "natural_heal_skill_interval",        &battle_config.natural_heal_skill_interval,     10000,  NATURAL_HEAL_INTERVAL, INT_MAX, },
+#ifdef RENEWAL
+	{ "natural_heal_weight_rate",           &battle_config.natural_heal_weight_rate,        70,     0,      100             },
+	{ "open_box_weight_rate",               &battle_config.open_box_weight_rate,            90,     0,      100             },
+#else
 	{ "natural_heal_weight_rate",           &battle_config.natural_heal_weight_rate,        50,     0,      100             },
-	{ "natural_heal_weight_rate_renewal",   &battle_config.natural_heal_weight_rate_renewal,70,     0,      100             },
+	{ "open_box_weight_rate",               &battle_config.open_box_weight_rate,            70,     0,      100             },
+#endif
 	{ "arrow_decrement",                    &battle_config.arrow_decrement,                 1,      0,      2,              },
 	{ "ammo_unequip",                       &battle_config.ammo_unequip,                    1,      0,      1,              },
 	{ "ammo_check_weapon",                  &battle_config.ammo_check_weapon,               1,      0,      1,              },
@@ -12120,6 +12125,7 @@ static const struct _battle_data {
 #endif
 	{ "loot_range",                         &battle_config.loot_range,                      12,     1,      MAX_WALKPATH,   },
 	{ "assist_range",                       &battle_config.assist_range,                    11,     1,      MAX_WALKPATH,   },
+	{ "major_overweight_rate",              &battle_config.major_overweight_rate,           90,     0,      100             },
 
 #include <custom/battle_config_init.inc>
 };

+ 2 - 1
src/map/battle.hpp

@@ -283,7 +283,6 @@ struct Battle_Config
 	int32 natural_healsp_interval;
 	int32 natural_heal_skill_interval;
 	int32 natural_heal_weight_rate;
-	int32 natural_heal_weight_rate_renewal;
 	int32 arrow_decrement;
 	int32 ammo_unequip;
 	int32 ammo_check_weapon;
@@ -771,6 +770,8 @@ struct Battle_Config
 	int32 alchemist_summon_setting;
 	int32 loot_range;
 	int32 assist_range;
+	int32 open_box_weight_rate;
+	int32 major_overweight_rate;
 
 #include <custom/battle_config_struct.inc>
 };

+ 1 - 1
src/map/buyingstore.cpp

@@ -215,7 +215,7 @@ int8 buyingstore_create( map_session_data* sd, int32 zenylimit, unsigned char re
 		return 5;
 	}
 
-	if( (sd->max_weight*90)/100 < weight )
+	if( pc_getpercentweight(*sd, weight) >= battle_config.major_overweight_rate )
 	{// not able to carry all wanted items without getting overweight (90%)
 		sd->buyingstore.slots = 0;
 		clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE_OVERWEIGHT, weight);

+ 2 - 6
src/map/clif.cpp

@@ -3647,7 +3647,7 @@ static void clif_longlongpar_change(map_session_data& sd, uint16 varId, int64 am
 void clif_updatestatus( map_session_data& sd, enum _sp type ){
 	switch(type){
 		case SP_WEIGHT:
-			pc_updateweightstatus(&sd);
+			pc_updateweightstatus(sd);
 			clif_par_change(sd, type, sd.weight);
 			break;
 		case SP_MAXWEIGHT:
@@ -22003,11 +22003,7 @@ void clif_weight_limit( map_session_data* sd ){
 
 	WFIFOHEAD(fd, packet_len(0xADE));
 	WFIFOW(fd, 0) = 0xADE;
-#ifdef RENEWAL
-	WFIFOL(fd, 2) = battle_config.natural_heal_weight_rate_renewal;
-#else
 	WFIFOL(fd, 2) = battle_config.natural_heal_weight_rate;
-#endif
 	WFIFOSET(fd, packet_len(0xADE));
 #endif
 }
@@ -24439,7 +24435,7 @@ void clif_parse_item_reform_start( int32 fd, map_session_data* sd ){
 void clif_enchantwindow_open( map_session_data& sd, uint64 clientLuaIndex ){
 #if PACKETVER_RE_NUM >= 20211103 || PACKETVER_MAIN_NUM >= 20220330
 	// Hardcoded clientside check
-	if( sd.weight > ( ( sd.max_weight * 70 ) / 100 ) ){
+	if( pc_getpercentweight(sd) >= 70 ){
 		clif_msg_color( sd, MSI_ENCHANT_FAILED_OVER_WEIGHT, color_table[COLOR_RED] );
 		sd.state.item_enchant_index = 0;
 		return;

+ 36 - 36
src/map/pc.cpp

@@ -2942,44 +2942,50 @@ uint64 pc_calc_skilltree_normalize_job( map_session_data *sd ){
 	return c;
 }
 
+/**
+ * Calculate the weight percentage of a player
+ * @param sd: Player data
+ * @param weight: (optional) Weight to check, if 0, player's current weight is used
+ */
+uint16 pc_getpercentweight(map_session_data& sd, uint32 weight)
+{
+	if (weight == 0)
+		weight = sd.weight;
+	return static_cast<uint16>(weight * 100 / sd.max_weight);
+}
+
 /*==========================================
  * Updates the weight status
  *------------------------------------------
  * 1: overweight 50% for pre-renewal and 70% for renewal
- * 2: overweight 90%
+ * 2: major overweight 90%
  * It's assumed that SC_WEIGHT50 and SC_WEIGHT90 are only started/stopped here.
  */
-void pc_updateweightstatus(map_session_data *sd)
+void pc_updateweightstatus(map_session_data& sd)
 {
-	int32 old_overweight;
-	int32 new_overweight;
-
-	nullpo_retv(sd);
-
-	old_overweight = (sd->sc.getSCE(SC_WEIGHT90)) ? 2 : (sd->sc.getSCE(SC_WEIGHT50)) ? 1 : 0;
-#ifdef RENEWAL
-	new_overweight = (pc_is90overweight(sd)) ? 2 : (pc_is70overweight(sd)) ? 1 : 0;
-#else
-	new_overweight = (pc_is90overweight(sd)) ? 2 : (pc_is50overweight(sd)) ? 1 : 0;
-#endif
+	uint8 old_overweight = (sd.sc.getSCE(SC_WEIGHT90) != nullptr) ? 2 : (sd.sc.getSCE(SC_WEIGHT50) != nullptr) ? 1 : 0;
+	uint16 overweight_percent = pc_getpercentweight(sd);
+	uint8 new_overweight = (overweight_percent >= battle_config.major_overweight_rate) ? 2 : (overweight_percent >= battle_config.natural_heal_weight_rate) ? 1 : 0;
 
+	// No change
 	if( old_overweight == new_overweight )
-		return; // no change
-
-	// stop old status change
-	if( old_overweight == 1 )
-		status_change_end(&sd->bl, SC_WEIGHT50);
-	else if( old_overweight == 2 )
-		status_change_end(&sd->bl, SC_WEIGHT90);
+		return;
 
-	// start new status change
-	if( new_overweight == 1 )
-		sc_start(&sd->bl,&sd->bl, SC_WEIGHT50, 100, 0, 0);
-	else if( new_overweight == 2 )
-		sc_start(&sd->bl,&sd->bl, SC_WEIGHT90, 100, 0, 0);
+	switch (new_overweight) {
+	case 0:
+		status_change_end(&sd.bl, SC_WEIGHT50);
+		status_change_end(&sd.bl, SC_WEIGHT90);
+		break;
+	case 1:
+		sc_start(&sd.bl, &sd.bl, SC_WEIGHT50, 100, 0, 0);
+		break;
+	case 2:
+		sc_start(&sd.bl, &sd.bl, SC_WEIGHT90, 100, 0, 0);
+		break;
+	}
 
-	// update overweight status
-	sd->regen.state.overweight = new_overweight;
+	// Update overweight status
+	sd.regen.state.overweight = new_overweight != 0;
 }
 
 int32 pc_disguise(map_session_data *sd, int32 class_)
@@ -6268,21 +6274,15 @@ bool pc_isUseitem(map_session_data *sd,int32 n)
 
 	// Safe check type cash disappear when overweight [Napster]
 	if( item->flag.group || item->type == IT_CASH ){
-#ifdef RENEWAL
 		// Check if the player is not overweighted
-		// In Renewal the limit is 70% weight and gives the same error message
-		if (pc_is70overweight(sd)) {
+		if (pc_getpercentweight(*sd) >= battle_config.open_box_weight_rate) {
+#ifdef RENEWAL
 			clif_msg_color( *sd, MSI_PICKUP_FAILED_ITEMCREATE, color_table[COLOR_RED] );
-			return 0;
-		}
 #else
-		// Check if the player is not overweighted
-		// In Pre-Renewal the limit is 50% weight and gives a specific error message
-		if (pc_is50overweight(sd)) {
 			clif_msg_color( *sd, MSI_CANT_GET_ITEM_BECAUSE_WEIGHT, color_table[COLOR_RED] );
+#endif
 			return 0;
 		}
-#endif
 
 		// Check if the player has enough free spaces in the inventory
 		// Official servers use 10 as the minimum amount of slots required to get the items

+ 2 - 4
src/map/pc.hpp

@@ -1189,9 +1189,6 @@ static bool pc_cant_act( map_session_data* sd ){
 #define pc_isfalcon(sd)       ( (sd)->sc.option&OPTION_FALCON )
 #define pc_isriding(sd)       ( (sd)->sc.option&OPTION_RIDING )
 #define pc_isinvisible(sd)    ( (sd)->sc.option&OPTION_INVISIBLE )
-#define pc_is50overweight(sd) ( (sd)->weight * 100 >= (sd)->max_weight * battle_config.natural_heal_weight_rate )
-#define pc_is70overweight(sd) ( (sd)->weight * 100 >= (sd)->max_weight * battle_config.natural_heal_weight_rate_renewal )
-#define pc_is90overweight(sd) ( (sd)->weight * 10 >= (sd)->max_weight * 9 )
 
 static inline bool pc_hasprogress(map_session_data *sd, enum e_wip_block progress) {
 	return sd == nullptr || (sd->state.workinprogress&progress) == progress;
@@ -1472,7 +1469,8 @@ bool pc_isequipped(map_session_data *sd, t_itemid nameid);
 enum adopt_responses pc_try_adopt(map_session_data *p1_sd, map_session_data *p2_sd, map_session_data *b_sd);
 bool pc_adoption(map_session_data *p1_sd, map_session_data *p2_sd, map_session_data *b_sd);
 
-void pc_updateweightstatus(map_session_data *sd);
+uint16 pc_getpercentweight(map_session_data& sd, uint32 weight = 0);
+void pc_updateweightstatus(map_session_data& sd);
 
 bool pc_addautobonus(std::vector<std::shared_ptr<s_autobonus>> &bonus, const char *script, int16 rate, uint32 dur, uint16 atk_type, const char *o_script, uint32 pos, bool onskill);
 void pc_exeautobonus(map_session_data &sd, std::vector<std::shared_ptr<s_autobonus>> *bonus, std::shared_ptr<s_autobonus> autobonus);

+ 7 - 11
src/map/skill.cpp

@@ -18423,7 +18423,7 @@ bool skill_check_condition_castbegin( map_session_data& sd, uint16 skill_id, uin
 			return true;
 	}
 
-	if( pc_is90overweight(&sd) ) {
+	if( sc != nullptr && sc->getSCE(SC_WEIGHT90) != nullptr ) {
 		clif_skill_fail( sd, skill_id, USESKILL_FAIL_WEIGHTOVER );
 		return false;
 	}
@@ -19160,11 +19160,7 @@ bool skill_check_condition_castbegin( map_session_data& sd, uint16 skill_id, uin
 			}
 			break;
 		case ST_RECOVER_WEIGHT_RATE:
-#ifdef RENEWAL
-			if(pc_is70overweight(&sd)) {
-#else
-			if(pc_is50overweight(&sd)) {
-#endif
+			if( sd.regen.state.overweight ) {
 				clif_skill_fail( sd, skill_id );
 				return false;
 			}
@@ -19463,15 +19459,15 @@ bool skill_check_condition_castend( map_session_data& sd, uint16 skill_id, uint1
 	if( sd.skillitem == skill_id && !sd.skillitem_keep_requirement ) // Casting finished (Item skill or Hocus-Pocus)
 		return true;
 
-	if( pc_is90overweight(&sd) ) {
-		clif_skill_fail( sd, skill_id, USESKILL_FAIL_WEIGHTOVER );
-		return false;
-	}
-
 	status_change* sc = &sd.sc;
 	if (sc->empty())
 		sc = nullptr;
 
+	if ( sc != nullptr && sc->getSCE(SC_WEIGHT90) != nullptr ) {
+		clif_skill_fail(sd, skill_id, USESKILL_FAIL_WEIGHTOVER);
+		return false;
+	}
+
 	// perform skill-specific checks (and actions)
 	switch( skill_id ) {
 		case PR_BENEDICTIO:

+ 4 - 4
src/map/status.cpp

@@ -3647,7 +3647,7 @@ bool status_calc_weight(map_session_data *sd, enum e_status_calc_weight_opt flag
 		clif_updatestatus(*sd, SP_WEIGHT);
 	if (b_max_weight != sd->max_weight) {
 		clif_updatestatus(*sd, SP_MAXWEIGHT);
-		pc_updateweightstatus(sd);
+		pc_updateweightstatus(*sd);
 	}
 
 	return true;
@@ -5381,8 +5381,8 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, sta
 		regen->flag &= ~RGN_SP;
 
 	if (sc->getSCE(SC_TENSIONRELAX)) {
-		if (sc->getSCE(SC_WEIGHT50) || sc->getSCE(SC_WEIGHT90))
-			regen->state.overweight = 0; // 1x HP regen
+		if (regen->state.overweight)
+			regen->state.overweight = false; // 1x HP regen
 		else {
 			regen->rate.hp += 200;
 			if (regen->sregen)
@@ -13419,7 +13419,7 @@ int32 status_change_end(struct block_list* bl, enum sc_type type, int32 tid)
 			break;
 		case SC_TENSIONRELAX:
 			if (sc && (sc->getSCE(SC_WEIGHT50) || sc->getSCE(SC_WEIGHT90)))
-				status_get_regen_data(bl)->state.overweight = 1; // Add the overweight flag back
+				status_get_regen_data(bl)->state.overweight = true; // Add the overweight flag back
 			break;
 		case SC_MONSTER_TRANSFORM:
 		case SC_ACTIVE_MONSTER_TRANSFORM:

+ 1 - 1
src/map/status.hpp

@@ -3413,7 +3413,7 @@ struct regen_data {
 	struct {
 		unsigned walk:1; //Can you regen even when walking?
 		unsigned gc:1;	//Tags when you should have double regen due to GVG castle
-		unsigned overweight :2; //overweight state (1: 50%, 2: 90%)
+		bool overweight; //overweight state
 		unsigned block :2; //Block regen flag (1: Hp, 2: Sp)
 	} state;