summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2014-02-03 03:17:29 +0100
committerHaru <haru@dotalux.com>2014-02-03 17:59:25 +0100
commit42b5c048e3d97be93c71f81f84ff37c502f96163 (patch)
tree2525ecd27cddf23c11e78e8f8207c41bd63f757a /src
parent2263dc4660c6668c373f6a9e654e21bea8c419e4 (diff)
downloadhercules-42b5c048e3d97be93c71f81f84ff37c502f96163.tar.gz
hercules-42b5c048e3d97be93c71f81f84ff37c502f96163.tar.bz2
hercules-42b5c048e3d97be93c71f81f84ff37c502f96163.tar.xz
hercules-42b5c048e3d97be93c71f81f84ff37c502f96163.zip
Added /stat+ commands support for 2013-12+ clients
- Fixes /str+, /agi+ and the likes, only being able to increase stats by 1 point on 2013-12 and newer clients. - As a bonus, on those clients, processing of the /stat+ commands will be much faster, and the requested points will be added instantly and all at once rather than one at a time like in older clients. Signed-off-by: Haru <haru@dotalux.com>
Diffstat (limited to 'src')
-rw-r--r--src/map/clif.c9
-rw-r--r--src/map/pc.c93
-rw-r--r--src/map/pc.h3
-rw-r--r--src/map/script.c5
4 files changed, 73 insertions, 37 deletions
diff --git a/src/map/clif.c b/src/map/clif.c
index 9ae88200c..1e1a98e09 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -11175,11 +11175,10 @@ 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
-void clif_parse_StatusUp(int fd,struct map_session_data *sd)
-{
- pc->statusup(sd,RFIFOW(fd,2));
+/// Old clients 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) {
+ pc->statusup(sd,RFIFOW(fd,2), RFIFOB(fd, 4));
}
diff --git a/src/map/pc.c b/src/map/pc.c
index b6c354189..acbdd8df5 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -6174,52 +6174,88 @@ 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)
-{
- int max, need, val;
+/**
+ * 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, status_points = sd->status.status_point;
+
+ base = final = pc->getstat(sd, type);
+
+ while (final <= pc_maxparameter(sd) && status_points >= 0) {
+#ifdef RENEWAL // renewal status point cost formula
+ status_points -= (final < 100) ? (2 + (final - 1) / 10) : (16 + 4 * ((final - 100) / 5));
+#else
+ status_points -= ( 1 + (final + 9) / 10 );
+#endif
+ final++;
+ }
+ final--;
+
+ return final > base ? final-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_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);
- 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)) {
+ 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,SCO_NONE);
+ status_calc_pc(sd, SCO_NONE);
// 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.
@@ -10674,6 +10710,7 @@ void pc_defaults(void) {
pc->thisjobexp = pc_thisjobexp;
pc->gets_status_point = pc_gets_status_point;
pc->need_status_point = pc_need_status_point;
+ pc->maxparameterincrease = pc_maxparameterincrease;
pc->statusup = pc_statusup;
pc->statusup2 = pc_statusup2;
pc->skillup = pc_skillup;
diff --git a/src/map/pc.h b/src/map/pc.h
index 487266646..808f6c52c 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -884,7 +884,8 @@ struct pc_interface {
unsigned int (*thisjobexp) (struct map_session_data *sd);
int (*gets_status_point) (int level);
int (*need_status_point) (struct map_session_data *sd,int type,int val);
- int (*statusup) (struct map_session_data *sd,int type);
+ int (*maxparameterincrease) (struct map_session_data* sd, int type);
+ bool (*statusup) (struct map_session_data *sd, int type, int increase);
int (*statusup2) (struct map_session_data *sd,int type,int val);
int (*skillup) (struct map_session_data *sd,uint16 skill_id);
int (*allskillup) (struct map_session_data *sd);
diff --git a/src/map/script.c b/src/map/script.c
index adea269c7..21d55ca77 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -7803,8 +7803,7 @@ BUILDIN(delequip)
/*==========================================
*
*------------------------------------------*/
-BUILDIN(statusup)
-{
+BUILDIN(statusup) {
int type;
TBL_PC *sd;
@@ -7813,7 +7812,7 @@ BUILDIN(statusup)
if( sd == NULL )
return true;
- pc->statusup(sd,type);
+ pc->statusup(sd, type, 1);
return true;
}