summaryrefslogtreecommitdiff
path: root/src/map/pc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/pc.c')
-rw-r--r--src/map/pc.c192
1 files changed, 116 insertions, 76 deletions
diff --git a/src/map/pc.c b/src/map/pc.c
index b6c354189..e29ef343f 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -196,7 +196,7 @@ int pc_addspiritball(struct map_session_data *sd,int interval,int max)
sd->spirit_timer[i] = tid;
sd->spiritball++;
if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
- clif->millenniumshield(sd,sd->spiritball);
+ clif->millenniumshield(&sd->bl,sd->spiritball);
else
clif->spiritball(&sd->bl);
@@ -235,7 +235,7 @@ int pc_delspiritball(struct map_session_data *sd,int count,int type)
if(!type) {
if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
- clif->millenniumshield(sd,sd->spiritball);
+ clif->millenniumshield(&sd->bl,sd->spiritball);
else
clif->spiritball(&sd->bl);
}
@@ -3957,12 +3957,13 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
i = MAX_INVENTORY;
- if( itemdb->isstackable2(data) && item_data->expire_time == 0 )
- { // Stackable | Non Rental
- for( i = 0; i < MAX_INVENTORY; i++ )
- {
- if( sd->status.inventory[i].nameid == item_data->nameid && sd->status.inventory[i].bound == item_data->bound && memcmp(&sd->status.inventory[i].card, &item_data->card, sizeof(item_data->card)) == 0 )
- {
+ // Stackable | Non Rental
+ if( itemdb->isstackable2(data) && item_data->expire_time == 0 ) {
+ for( i = 0; i < MAX_INVENTORY; i++ ) {
+ if( sd->status.inventory[i].nameid == item_data->nameid &&
+ sd->status.inventory[i].bound == item_data->bound &&
+ sd->status.inventory[i].expire_time == 0 &&
+ memcmp(&sd->status.inventory[i].card, &item_data->card, sizeof(item_data->card)) == 0 ) {
if( amount > MAX_AMOUNT - sd->status.inventory[i].amount || ( data->stack.inventory && amount > data->stack.amount - sd->status.inventory[i].amount ) )
return 5;
sd->status.inventory[i].amount += amount;
@@ -5205,7 +5206,8 @@ int pc_checkallowskill(struct map_session_data *sd)
SC_LKCONCENTRATION,
SC_EDP,
#endif
- SC_FEARBREEZE
+ SC_FEARBREEZE,
+ SC_EXEEDBREAK,
};
const enum sc_type scs_list[] = {
SC_AUTOGUARD,
@@ -6174,52 +6176,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.
@@ -8410,17 +8448,19 @@ int pc_cleareventtimer(struct map_session_data *sd)
/* called when a item with combo is worn */
int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
int i, j, k, z;
- int index, idx, success = 0;
+ int index, success = 0;
+ struct pc_combos *combo;
for( i = 0; i < data->combos_count; i++ ) {
/* ensure this isn't a duplicate combo */
- if( sd->combos.bonus != NULL ) {
+ if( sd->combos != NULL ) {
int x;
- ARR_FIND( 0, sd->combos.count, x, sd->combos.id[x] == data->combos[i]->id );
+
+ ARR_FIND( 0, sd->combo_count, x, sd->combos[x].id == data->combos[i]->id );
/* found a match, skip this combo */
- if( x < sd->combos.count )
+ if( x < sd->combo_count )
continue;
}
@@ -8437,7 +8477,7 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
if(!sd->inventory_data[index])
continue;
-
+
if ( itemdb_type(id) != IT_CARD ) {
if ( sd->inventory_data[index]->nameid != id )
continue;
@@ -8471,22 +8511,13 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
/* we got here, means all items in the combo are matching */
- idx = sd->combos.count;
-
- if( sd->combos.bonus == NULL ) {
- CREATE(sd->combos.bonus, struct script_code *, 1);
- CREATE(sd->combos.id, unsigned short, 1);
- sd->combos.count = 1;
- } else {
- RECREATE(sd->combos.bonus, struct script_code *, ++sd->combos.count);
- RECREATE(sd->combos.id, unsigned short, sd->combos.count);
- }
-
- /* we simply copy the pointer */
- sd->combos.bonus[idx] = data->combos[i]->script;
- /* save this combo's id */
- sd->combos.id[idx] = data->combos[i]->id;
-
+ RECREATE(sd->combos, struct pc_combos, ++sd->combo_count);
+
+ combo = &sd->combos[sd->combo_count - 1];
+
+ combo->bonus = data->combos[i]->script;
+ combo->id = data->combos[i]->id;
+
success++;
}
return success;
@@ -8496,26 +8527,30 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
int pc_removecombo(struct map_session_data *sd, struct item_data *data ) {
int i, retval = 0;
- if( sd->combos.bonus == NULL )
+ if( !sd->combos )
return 0;/* nothing to do here, player has no combos */
+
for( i = 0; i < data->combos_count; i++ ) {
/* check if this combo exists in this user */
int x = 0, cursor = 0, j;
- ARR_FIND( 0, sd->combos.count, x, sd->combos.id[x] == data->combos[i]->id );
+
+ ARR_FIND( 0, sd->combo_count, x, sd->combos[x].id == data->combos[i]->id );
/* no match, skip this combo */
- if( !(x < sd->combos.count) )
+ if( !(x < sd->combo_count) )
continue;
- sd->combos.bonus[x] = NULL;
- sd->combos.id[x] = 0;
+ sd->combos[x].bonus = NULL;
+ sd->combos[x].id = 0;
+
retval++;
- for( j = 0, cursor = 0; j < sd->combos.count; j++ ) {
- if( sd->combos.bonus[j] == NULL )
+
+ for( j = 0, cursor = 0; j < sd->combo_count; j++ ) {
+ if( sd->combos[j].bonus == NULL )
continue;
if( cursor != j ) {
- sd->combos.bonus[cursor] = sd->combos.bonus[j];
- sd->combos.id[cursor] = sd->combos.id[j];
+ sd->combos[cursor].bonus = sd->combos[j].bonus;
+ sd->combos[cursor].id = sd->combos[j].id;
}
cursor++;
@@ -8526,11 +8561,10 @@ int pc_removecombo(struct map_session_data *sd, struct item_data *data ) {
continue;
/* it's empty, we can clear all the memory */
- if( (sd->combos.count = cursor) == 0 ) {
- aFree(sd->combos.bonus);
- aFree(sd->combos.id);
- sd->combos.bonus = NULL;
- sd->combos.id = NULL;
+ if( (sd->combo_count = cursor) == 0 ) {
+ aFree(sd->combos);
+ sd->combos = NULL;
+
return retval; /* we also can return at this point for we have no more combos to check */
}
@@ -8953,7 +8987,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
*------------------------------------------*/
int pc_checkitem(struct map_session_data *sd)
{
- int i,id,calc_flag = 0;
+ int i, id, calc_flag = 0;
nullpo_ret(sd);
@@ -9019,7 +9053,7 @@ int pc_checkitem(struct map_session_data *sd)
}
}
-
+
if( calc_flag && sd->state.active ) {
pc->checkallowskill(sd);
status_calc_pc(sd,SCO_NONE);
@@ -10359,15 +10393,20 @@ void pc_autotrade_update(struct map_session_data *sd, enum e_pc_autotrade_update
if (SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d' LIMIT 1",map->autotrade_merchants_db,sd->status.char_id))
Sql_ShowDebug(map->mysql_handle);
break;
- case PAUC_START:
+ case PAUC_START: {
+ char title[MESSAGE_SIZE*2+1];
+
+ SQL->EscapeStringLen(map->mysql_handle, title, sd->message, strnlen(sd->message, MESSAGE_SIZE));
+
if (SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `%s` (`account_id`,`char_id`,`sex`,`title`) VALUES ('%d','%d','%d','%s')",
map->autotrade_merchants_db,
sd->status.account_id,
sd->status.char_id,
sd->status.sex,
- sd->message
+ title
))
Sql_ShowDebug(map->mysql_handle);
+ }
/* yes we want it to fall */
case PAUC_REFRESH:
for( i = 0; i < sd->vend_num; i++ ) {
@@ -10674,6 +10713,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;