Procházet zdrojové kódy

- Corrected cloaking not ending on attack if you are near a wall.
- Moved define cap_value to map.h as it's quite handy.
- Updated pc_bonus to use cap_value on all status_data modifiers to prevent overflows/underflows.


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

skotlex před 19 roky
rodič
revize
87f9a3668b
5 změnil soubory, kde provedl 76 přidání a 48 odebrání
  1. 4 0
      Changelog-Trunk.txt
  2. 3 3
      src/map/battle.c
  3. 3 0
      src/map/map.h
  4. 65 42
      src/map/pc.c
  5. 1 3
      src/map/status.c

+ 4 - 0
Changelog-Trunk.txt

@@ -3,6 +3,10 @@ Date	Added
 AS OF SVN REV. 5091, WE ARE NOW USING TRUNK.  ALL UNTESTED BUGFIXES/FEATURES GO INTO TRUNK.
 IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
 
+2006/06/05
+	* Corrected cloaking not ending on attack if you are near a wall. [Skotlex]
+	* Updated pc_bonus to use cap_value on all status_data modifiers to prevent
+	  overflows/underflows. [Skotlex]
 2006/06/03
 	* Fixed @mi/@mobinfo not showing the name collumns correcly [shadow]
 	* Solved the bug that made firewalls only castable a few times until [MasterOfMuppets]

+ 3 - 3
src/map/battle.c

@@ -2070,9 +2070,9 @@ struct Damage battle_calc_magic_attack(
 		case MG_FIREWALL:
 			if(mflag) //mflag has a value when it was checked against an undead in skill.c [Skotlex]
 				ad.blewcount = 0; //No knockback
-            else
+			else
 				ad.blewcount |= 0x10000;
-	          ad.dmotion = 0; //No flinch animation.
+			ad.dmotion = 0; //No flinch animation.
 			break;
 		case WZ_STORMGUST: //Should knockback randomly.
 			ad.blewcount|=0x40000;
@@ -2769,7 +2769,7 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target,
 		}
 	}
 
-	if (sc && sc->data[SC_CLOAKING].timer != -1 && !sc->data[SC_CLOAKING].val4)
+	if (sc && sc->data[SC_CLOAKING].timer != -1 && !(sc->data[SC_CLOAKING].val4&1))
 		status_change_end(src,SC_CLOAKING,-1);
 
 	//Check for counter attacks that block your attack. [Skotlex]

+ 3 - 0
src/map/map.h

@@ -162,6 +162,9 @@ enum {
 //Specifies maps that have special GvG/WoE restrictions
 #define map_flag_gvg(m) (map[m].flag.gvg || (agit_flag && map[m].flag.gvg_castle))
 
+//Caps values to min/max
+#define cap_value(a, min, max) (a>max?max:a<min?min:a)
+
 //This stackable implementation does not means a BL can be more than one type at a time, but it's 
 //meant to make it easier to check for multiple types at a time on invocations such as
 // map_foreach* calls [Skotlex]

+ 65 - 42
src/map/pc.c

@@ -1200,6 +1200,7 @@ static int pc_bonus_item_drop(struct s_add_drop *drop, short *count, short id, s
 int pc_bonus(struct map_session_data *sd,int type,int val)
 {
 	struct status_data *status;
+	int bonus;
 	nullpo_retr(0, sd);
 
 	status = &sd->base_status;
@@ -1246,50 +1247,52 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 		break;
 	case SP_DEF1:
 		if(sd->state.lr_flag != 2) {
-			if (val < 0 && status->def < -val)
-				status->def = 0;
-			else if (val > 0 && val > UCHAR_MAX - status->def)
-				status->def = UCHAR_MAX;
-			else
-				status->def+=val;
+			bonus = status->def + val;
+			status->def = cap_value(bonus, 0, UCHAR_MAX);
 		}
 		break;
 	case SP_DEF2:
-		if(sd->state.lr_flag != 2)
-			status->def2+=val;
+		if(sd->state.lr_flag != 2) {
+			bonus = status->def2 + val;
+			status->def2 = cap_value(bonus, 0, USHRT_MAX);
+		}
 		break;
 	case SP_MDEF1:
-		if(sd->state.lr_flag != 2)
-			status->mdef+=val;
+		if(sd->state.lr_flag != 2) {
+			bonus = status->mdef + val;
+			status->mdef = cap_value(bonus, 0, UCHAR_MAX);
+		}
 		break;
 	case SP_MDEF2:
 		if(sd->state.lr_flag != 2) {
-			if (val < 0 && status->mdef < -val)
-				status->mdef = 0;
-			else if (val > 0 && val > UCHAR_MAX - status->mdef)
-				status->mdef = UCHAR_MAX;
-			else
-				status->mdef+=val;
+			bonus = status->mdef2 + val;
+			status->mdef2 = cap_value(bonus, 0, USHRT_MAX);
 		}
 		break;
 	case SP_HIT:
-		if(sd->state.lr_flag != 2)
-			status->hit+=val;
-		else
+		if(sd->state.lr_flag != 2) {
+			bonus = status->hit + val;
+			status->hit = cap_value(bonus, 0, USHRT_MAX);
+		} else
 			sd->arrow_hit+=val;
 		break;
 	case SP_FLEE1:
-		if(sd->state.lr_flag != 2)
-			status->flee+=val;
+		if(sd->state.lr_flag != 2) {
+			bonus = status->flee + val;
+			status->flee = cap_value(bonus, 0, USHRT_MAX);
+		}
 		break;
 	case SP_FLEE2:
-		if(sd->state.lr_flag != 2)
-			status->flee2+=val*10;
+		if(sd->state.lr_flag != 2) {
+			bonus = status->flee2 + val*10;
+			status->flee2 = cap_value(bonus, 0, USHRT_MAX);
+		}
 		break;
 	case SP_CRITICAL:
-		if(sd->state.lr_flag != 2)
-			status->cri+=val*10;
-		else
+		if(sd->state.lr_flag != 2) {
+			bonus = status->cri + val*10;
+			status->cri = cap_value(bonus, 0, USHRT_MAX);
+		} else
 			sd->arrow_cri += val*10;
 		break;
 	case SP_ATKELE:
@@ -1298,12 +1301,18 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 				ShowError("pc_bonus: SP_ATKELE: Invalid element %d\n", val);
 			break;
 		}
-		if(!sd->state.lr_flag)
-			status->rhw.ele=val;
-		else if(sd->state.lr_flag == 1)
-			status->lhw->ele=val;
-		else if(sd->state.lr_flag == 2)
+		switch (sd->state.lr_flag)
+		{
+		case 2:
 			sd->arrow_ele=val;
+			break;
+		case 1:
+			status->lhw->ele=val;
+			break;
+		default:
+			status->rhw.ele=val;
+			break;
+		}
 		break;
 	case SP_DEFELE:
 		if(val >= ELE_MAX) {
@@ -1315,12 +1324,20 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 			status->def_ele=val;
 		break;
 	case SP_MAXHP:
-		if(sd->state.lr_flag != 2)
-			status->max_hp+=val;
+		if(sd->state.lr_flag != 2) {
+			if (val < 0 && status->max_hp <= -val)
+				status->max_hp = 1;
+			else
+				status->max_hp+=val;
+		}
 		break;
 	case SP_MAXSP:
-		if(sd->state.lr_flag != 2)
-			status->max_sp+=val;
+		if(sd->state.lr_flag != 2) {
+			if (val < 0 && status->max_sp <= -val)
+				status->max_sp = 1;
+			else
+				status->max_sp+=val;
+		}
 		break;
 	case SP_CASTRATE:
 		if(sd->state.lr_flag != 2)
@@ -1339,11 +1356,8 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 			sd->dsprate+=val;
 		break;
 	case SP_ATTACKRANGE:
-		if(!sd->state.lr_flag)
-			status->rhw.range += val;
-		else if(sd->state.lr_flag == 1)
-			status->lhw->range += val;
-		else if(sd->state.lr_flag == 2) {
+		switch (sd->state.lr_flag) {
+		case 2:
 			switch (sd->status.weapon) {
 				case W_BOW:
 				case W_REVOLVER:
@@ -1353,11 +1367,20 @@ int pc_bonus(struct map_session_data *sd,int type,int val)
 				case W_GRENADE:
 					status->rhw.range += val;
 			}
+			break;
+		case 1:
+			status->lhw->range += val;
+			break;
+		default:
+			status->rhw.range += val;
+			break;
 		}
 		break;
 	case SP_ADD_SPEED:	//Raw increase
-		if(sd->state.lr_flag != 2)
-			status->speed -= val;
+		if(sd->state.lr_flag != 2) {
+			bonus = status->speed - val;
+			status->speed = cap_value(bonus, 0, USHRT_MAX);
+		}
 		break;
 	case SP_SPEED_RATE:	//Non stackable increase
 		if(sd->state.lr_flag != 2 && sd->speed_rate > 100-val)

+ 1 - 3
src/map/status.c

@@ -52,9 +52,6 @@ int current_equip_card_id; //To prevent card-stacking (from jA) [Skotlex]
 //we need it for new cards 15 Feb 2005, to check if the combo cards are insrerted into the CURRENT weapon only
 //to avoid cards exploits
 
-//Caps values to min/max
-#define cap_value(a, min, max) (a>max?max:a<min?min:a)
-
 //Initializes the StatusIconChangeTable variable. May seem somewhat slower than directly defining the array,
 //but it is much less prone to errors. [Skotlex]
 void initChangeTables(void) {
@@ -4815,6 +4812,7 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val
 			break;
 
 		case SC_GRAVITATION:
+			//val2 = aspd reduction
 			if (val3 == BCT_SELF) {
 				struct unit_data *ud = unit_bl2ud(bl);
 				if (ud) {