diff options
author | Haru <haru@dotalux.com> | 2014-02-03 03:17:29 +0100 |
---|---|---|
committer | Haru <haru@dotalux.com> | 2014-02-03 17:59:25 +0100 |
commit | 42b5c048e3d97be93c71f81f84ff37c502f96163 (patch) | |
tree | 2525ecd27cddf23c11e78e8f8207c41bd63f757a | |
parent | 2263dc4660c6668c373f6a9e654e21bea8c419e4 (diff) | |
download | hercules-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>
-rw-r--r-- | src/map/clif.c | 9 | ||||
-rw-r--r-- | src/map/pc.c | 93 | ||||
-rw-r--r-- | src/map/pc.h | 3 | ||||
-rw-r--r-- | src/map/script.c | 5 |
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; } |