Parcourir la source

Bug Fixes
* Updated /stats+ to support 2013-12 and newer clients. (bugreport:8726) (Hercules 42b5c04)
* Guild auras will no longer be removed on Land Protector. (Hercules 186fbc5)
* Fixed the animation for logout. (Hercules 3f473c2)

aleos89 il y a 11 ans
Parent
commit
df1b99212b
6 fichiers modifiés avec 79 ajouts et 36 suppressions
  1. 6 5
      src/map/clif.c
  2. 65 28
      src/map/pc.c
  3. 2 1
      src/map/pc.h
  4. 1 1
      src/map/script.c
  5. 3 0
      src/map/skill.c
  6. 2 1
      src/map/unit.c

+ 6 - 5
src/map/clif.c

@@ -10320,7 +10320,7 @@ void clif_parse_Restart(int fd, struct map_session_data *sd)
 {
 	switch(RFIFOB(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])) {
 	case 0x00:
-		pc_respawn(sd,CLR_RESPAWN);
+		pc_respawn(sd,CLR_OUTSIGHT);
 		break;
 	case 0x01:
 		/*	Rovert's Prevent logout option - Fixed [Valaris]	*/
@@ -11073,12 +11073,13 @@ void clif_parse_ChangeCart(int fd,struct map_session_data *sd)
 /// status id:
 ///     SP_STR ~ SP_LUK
 /// amount:
-///     client sends always 1 for this, even when using /str+ and
-///     the like
+///     Old client send always 1 for this, even when using /str+ and the like.
+///     Newer clients (2013-12-23 and newer) send the correct amount.
 void clif_parse_StatusUp(int fd,struct map_session_data *sd)
 {
-	//char amount = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]);
-	pc_statusup(sd,RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]));
+	struct s_packet_db* info = &packet_db[sd->packet_ver][RFIFOW(fd,0)];
+
+	pc_statusup(sd, RFIFOW(fd,info->pos[0]), RFIFOB(fd,info->pos[1]));
 }
 
 

+ 65 - 28
src/map/pc.c

@@ -6213,53 +6213,90 @@ int pc_need_status_point(struct map_session_data* sd, int type, int val)
 	return sp;
 }
 
-/// Raises a stat by 1.
-/// Obeys max_parameter limits.
-/// Subtracts stat points.
-///
-/// @param type The stat to change (see enum _sp)
-int pc_statusup(struct map_session_data* sd, int type)
+/**
+ * Returns the value the specified stat can be increased by with the current
+ * amount of available status points for the current character's class.
+ *
+ * @param sd   The target character.
+ * @param type Stat to verify.
+ * @return Maximum value the stat could grow by.
+ */
+int pc_maxparameterincrease(struct map_session_data* sd, int type)
+{
+	int base, final_val, status_points = sd->status.status_point;
+
+	base = final_val = pc_getstat(sd, type);
+
+	while (final_val <= pc_maxparameter(sd, (enum e_params)(type-SP_STR)) && status_points >= 0) {
+#ifdef RENEWAL // renewal status point cost formula
+		status_points -= (final_val < 100) ? (2 + (final_val - 1) / 10) : (16 + 4 * ((final_val - 100) / 5));
+#else
+		status_points -= ( 1 + (final_val + 9) / 10 );
+#endif
+		final_val++;
+	}
+	final_val--;
+
+	return final_val > base ? final_val-base : 0;
+}
+
+/**
+ * Raises a stat by the specified amount.
+ * Obeys max_parameter limits.
+ * Subtracts stat points.
+ *
+ * @param sd       The target character.
+ * @param type     The stat to change (see enum _sp)
+ * @param increase The stat increase amount.
+ * @return true if the stat was increased by any amount, false if there were no
+ *         changes.
+ */
+bool pc_statusup(struct map_session_data* sd, int type, int increase)
 {
-	int max, need, val;
+	int max_increase = 0, current = 0, needed_points = 0, final_value = 0;
 
 	nullpo_ret(sd);
 
 	// check conditions
-	need = pc_need_status_point(sd,type,1);
-	if( type < SP_STR || type > SP_LUK || need < 0 || need > sd->status.status_point )
-	{
-		clif_statusupack(sd,type,0,0);
-		return 1;
+	if (type < SP_STR || type > SP_LUK || increase <= 0) {
+		clif_statusupack(sd, type, 0, 0);
+		return false;
 	}
 
 	// check limits
-	max = pc_maxparameter(sd,(enum e_params)(type-SP_STR));
-
-	if( pc_getstat(sd,type) >= max )
-	{
-		clif_statusupack(sd,type,0,0);
-		return 1;
+	current = pc_getstat(sd, type);
+	max_increase = pc_maxparameterincrease(sd, type);
+	increase = cap_value(increase, 0, max_increase); // cap to the maximum status points available
+	if (increase <= 0 || current + increase > pc_maxparameter(sd, (enum e_params)(type-SP_STR))) {
+		clif_statusupack(sd, type, 0, 0);
+		return false;
+	}
+	
+	// check status points
+	needed_points = pc_need_status_point(sd, type, increase);
+	if (needed_points < 0 || needed_points > sd->status.status_point) { // Sanity check
+		clif_statusupack(sd, type, 0, 0);
+		return false;
 	}
 
 	// set new values
-	val = pc_setstat(sd, type, pc_getstat(sd,type) + 1);
-	sd->status.status_point -= need;
+	final_value = pc_setstat(sd, type, current + increase);
+	sd->status.status_point -= needed_points;
 
-	status_calc_pc(sd,0);
+	status_calc_pc(sd, 0);
 
 	// update increase cost indicator
-	if( need != pc_need_status_point(sd,type,1) )
-		clif_updatestatus(sd, SP_USTR + type-SP_STR);
+	clif_updatestatus(sd, SP_USTR + type-SP_STR);
 
 	// update statpoint count
-	clif_updatestatus(sd,SP_STATUSPOINT);
+	clif_updatestatus(sd, SP_STATUSPOINT);
 
 	// update stat value
-	clif_statusupack(sd,type,1,val); // required
-	if( val > 255 )
-		clif_updatestatus(sd,type); // send after the 'ack' to override the truncated value
+	clif_statusupack(sd, type, 1, final_value); // required
+	if( final_value > 255 )
+		clif_updatestatus(sd, type); // send after the 'ack' to override the truncated value
 
-	return 0;
+	return true;
 }
 
 /// Raises a stat by the specified amount.

+ 2 - 1
src/map/pc.h

@@ -906,7 +906,8 @@ unsigned int pc_nextjobexp(struct map_session_data *);
 unsigned int pc_thisjobexp(struct map_session_data *);
 int pc_gets_status_point(int);
 int pc_need_status_point(struct map_session_data *,int,int);
-int pc_statusup(struct map_session_data*,int);
+int pc_maxparameterincrease(struct map_session_data*,int);
+bool pc_statusup(struct map_session_data*,int,int);
 int pc_statusup2(struct map_session_data*,int,int);
 int pc_skillup(struct map_session_data*,uint16 skill_id);
 int pc_allskillup(struct map_session_data*);

+ 1 - 1
src/map/script.c

@@ -8061,7 +8061,7 @@ BUILDIN_FUNC(statusup)
 	if( sd == NULL )
 		return 0;
 
-	pc_statusup(sd,type);
+	pc_statusup(sd, type, 1);
 
 	return SCRIPT_CMD_SUCCESS;
 }

+ 3 - 0
src/map/skill.c

@@ -15886,6 +15886,9 @@ static int skill_cell_overlap(struct block_list *bl, va_list ap)
 	if (unit == NULL || unit->group == NULL || (*alive) == 0)
 		return 0;
 
+	if (unit->group->state.guildaura) /* guild auras are not cancelled! */
+		return 0;
+
 	switch (skill_id) {
 		case SA_LANDPROTECTOR:
 			if( unit->group->skill_id == SA_LANDPROTECTOR ) {//Check for offensive Land Protector to delete both. [Skotlex]

+ 2 - 1
src/map/unit.c

@@ -2551,7 +2551,8 @@ void unit_remove_map_pc(struct map_session_data *sd, clr_type clrtype)
 {
 	unit_remove_map(&sd->bl,clrtype);
 
-	if (clrtype == CLR_TELEPORT) clrtype = CLR_OUTSIGHT; // CLR_TELEPORT is the warp from logging out, but pets/homunc need to just 'vanish' instead of showing the warping out animation.
+	//CLR_RESPAWN is the warp from logging out, CLR_TELEPORT is the warp from teleporting, but pets/homunc need to just 'vanish' instead of showing the warping animation.
+	if (clrtype == CLR_RESPAWN || clrtype == CLR_TELEPORT) clrtype = CLR_OUTSIGHT;
 
 	if(sd->pd)
 		unit_remove_map(&sd->pd->bl, clrtype);