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.c1559
1 files changed, 993 insertions, 566 deletions
diff --git a/src/map/pc.c b/src/map/pc.c
index 8d1df71a9..2303a83ca 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -63,6 +63,7 @@
#include "common/random.h"
#include "common/showmsg.h"
#include "common/socket.h"
+#include "common/sql.h"
#include "common/strlib.h" // safestrncpy()
#include "common/sysinfo.h"
#include "common/timer.h"
@@ -79,10 +80,13 @@ struct pc_interface *pc;
//Converts a class to its array index for CLASS_COUNT defined arrays.
//Note that it does not do a validity check for speed purposes, where parsing
//player input make sure to use a pc->db_checkid first!
-int pc_class2idx(int class_) {
- if (class_ >= JOB_NOVICE_HIGH)
- return class_- JOB_NOVICE_HIGH+JOB_MAX_BASIC;
- return class_;
+int pc_class2idx(int class)
+{
+ if (class >= JOB_NOVICE_HIGH) {
+ class += - JOB_NOVICE_HIGH + JOB_MAX_BASIC;
+ }
+ Assert_ret(class >= 0 && class < CLASS_COUNT);
+ return class;
}
/**
@@ -108,6 +112,7 @@ struct map_session_data* pc_get_dummy_sd(void)
int pc_set_group(struct map_session_data *sd, int group_id)
{
GroupSettings *group = pcg->id2group(group_id);
+ nullpo_retr(1, sd);
if (group == NULL)
return 1;
sd->group_id = group_id;
@@ -120,6 +125,7 @@ int pc_set_group(struct map_session_data *sd, int group_id)
*/
bool pc_should_log_commands(struct map_session_data *sd)
{
+ nullpo_retr(true, sd);
return pcg->should_log_commands(sd->group);
}
@@ -140,7 +146,8 @@ int pc_invincible_timer(int tid, int64 tick, int id, intptr_t data)
return 0;
}
-void pc_setinvincibletimer(struct map_session_data* sd, int val) {
+void pc_setinvincibletimer(struct map_session_data* sd, int val)
+{
nullpo_retv(sd);
val += map->list[sd->bl.m].invincible_time_inc;
@@ -241,7 +248,7 @@ int pc_addspiritball(struct map_session_data *sd,int interval,int max)
memmove(sd->spirit_timer+i+1, sd->spirit_timer+i, (sd->spiritball-i)*sizeof(int));
sd->spirit_timer[i] = tid;
sd->spiritball++;
- if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
+ if ((sd->job & MAPID_THIRDMASK) == MAPID_ROYAL_GUARD)
clif->millenniumshield(&sd->bl,sd->spiritball);
else
clif->spiritball(&sd->bl);
@@ -280,7 +287,7 @@ int pc_delspiritball(struct map_session_data *sd,int count,int type)
}
if(!type) {
- if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
+ if ((sd->job & MAPID_THIRDMASK) == MAPID_ROYAL_GUARD)
clif->millenniumshield(&sd->bl,sd->spiritball);
else
clif->spiritball(&sd->bl);
@@ -380,52 +387,108 @@ int pc_banding(struct map_session_data *sd, uint16 skill_lv) {
return c;
}
-// Increases a player's fame points and displays a notice to him
-void pc_addfame(struct map_session_data *sd,int count)
+/**
+ * Increases a player's fame points and displays a notice to them.
+ *
+ * If the character's job class doesn't allow the specified rank type, nothing
+ * happens and the request is ignored.
+ *
+ * @param sd The target character.
+ * @param type The fame list type (@see enum fame_list_type).
+ * @param count The amount of points to add.
+ */
+void pc_addfame(struct map_session_data *sd, int ranktype, int count)
{
- int ranktype = -1;
nullpo_retv(sd);
+
+ switch (ranktype) {
+ case RANKTYPE_BLACKSMITH:
+ if ((sd->job & MAPID_UPPERMASK) != MAPID_BLACKSMITH)
+ return;
+ break;
+ case RANKTYPE_ALCHEMIST:
+ if ((sd->job & MAPID_UPPERMASK) != MAPID_ALCHEMIST)
+ return;
+ break;
+ case RANKTYPE_TAEKWON:
+ if ((sd->job & MAPID_UPPERMASK) != MAPID_TAEKWON)
+ return;
+ break;
+ case RANKTYPE_PK:
+ // Not supported
+ FALLTHROUGH
+ default:
+ Assert_retv(0);
+ }
+
sd->status.fame += count;
- if(sd->status.fame > MAX_FAME)
+ if (sd->status.fame > MAX_FAME)
sd->status.fame = MAX_FAME;
- switch(sd->class_&MAPID_UPPERMASK){
- case MAPID_BLACKSMITH: ranktype = RANKTYPE_BLACKSMITH; break;
- case MAPID_ALCHEMIST: ranktype = RANKTYPE_ALCHEMIST; break;
- case MAPID_TAEKWON: ranktype = RANKTYPE_TAEKWON; break;
- }
+
clif->update_rankingpoint(sd, ranktype, count);
chrif->updatefamelist(sd);
}
-// Check whether a player ID is in the fame rankers' list of its job, returns his/her position if so, 0 else
-unsigned char pc_famerank(int char_id, int job)
+/**
+ * Returns a character's rank in the specified fame list.
+ *
+ * @param char_id The character ID.
+ * @param ranktype The rank list type (@see enum fame_list_type).
+ * @return The rank position (1-based index)
+ * @retval 0 if the character isn't in the specified list.
+ */
+int pc_fame_rank(int char_id, int ranktype)
{
int i;
- switch(job){
- case MAPID_BLACKSMITH: // Blacksmith
- for(i = 0; i < MAX_FAME_LIST; i++){
- if(pc->smith_fame_list[i].id == char_id)
- return i + 1;
- }
- break;
- case MAPID_ALCHEMIST: // Alchemist
- for(i = 0; i < MAX_FAME_LIST; i++){
- if(pc->chemist_fame_list[i].id == char_id)
- return i + 1;
- }
- break;
- case MAPID_TAEKWON: // Taekwon
- for(i = 0; i < MAX_FAME_LIST; i++){
- if(pc->taekwon_fame_list[i].id == char_id)
- return i + 1;
- }
- break;
+ switch (ranktype) {
+ case RANKTYPE_BLACKSMITH:
+ for (i = 0; i < MAX_FAME_LIST; i++) {
+ if (pc->smith_fame_list[i].id == char_id)
+ return i + 1;
+ }
+ break;
+ case RANKTYPE_ALCHEMIST:
+ for (i = 0; i < MAX_FAME_LIST; i++) {
+ if (pc->chemist_fame_list[i].id == char_id)
+ return i + 1;
+ }
+ break;
+ case RANKTYPE_TAEKWON:
+ for (i = 0; i < MAX_FAME_LIST; i++) {
+ if (pc->taekwon_fame_list[i].id == char_id)
+ return i + 1;
+ }
+ break;
+ case RANKTYPE_PK: // Not implemented
+ FALLTHROUGH
+ default:
+ Assert_ret(0);
}
return 0;
}
+/**
+ * Returns the appropriate fame list type for the given job.
+ *
+ * @param job_mapid The job (in MapID format)
+ * @return the appropriate fame list type (@see enum fame_list_type).
+ * @retval RANKTYPE_UNKNOWN if no appropriate type exists.
+ */
+int pc_famelist_type(uint16 job_mapid) {
+ switch (job_mapid & MAPID_UPPERMASK) {
+ case MAPID_BLACKSMITH:
+ return RANKTYPE_BLACKSMITH;
+ case MAPID_ALCHEMIST:
+ return RANKTYPE_ALCHEMIST;
+ case MAPID_TAEKWON:
+ return RANKTYPE_TAEKWON;
+ default:
+ return RANKTYPE_UNKNOWN;
+ }
+}
+
int pc_setrestartvalue(struct map_session_data *sd,int type) {
struct status_data *st, *bst;
nullpo_ret(sd);
@@ -465,6 +528,7 @@ int pc_inventory_rental_end(int tid, int64 tick, int id, intptr_t data) {
int pc_inventory_rental_clear(struct map_session_data *sd)
{
+ nullpo_ret(sd);
if( sd->rental_timer != INVALID_TIMER )
{
timer->delete(sd->rental_timer, pc->inventory_rental_end);
@@ -475,11 +539,15 @@ int pc_inventory_rental_clear(struct map_session_data *sd)
}
/* assumes i is valid (from default areas where it is called, it is) */
void pc_rental_expire(struct map_session_data *sd, int i) {
- short nameid = sd->status.inventory[i].nameid;
+ short nameid;
+
+ nullpo_retv(sd);
+ Assert_retv(i >= 0 && i < MAX_INVENTORY);
+ nameid = sd->status.inventory[i].nameid;
/* Soon to be dropped, we got plans to integrate it with item db */
switch( nameid ) {
- case ITEMID_REINS_OF_MOUNT:
+ case ITEMID_BOARDING_HALTER:
status_change_end(&sd->bl,SC_ALL_RIDING,INVALID_TIMER);
break;
case ITEMID_LOVE_ANGEL:
@@ -539,13 +607,14 @@ void pc_rental_expire(struct map_session_data *sd, int i) {
}
clif->rental_expired(sd->fd, i, sd->status.inventory[i].nameid);
- pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_OTHER);
+ pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_RENTAL);
}
void pc_inventory_rentals(struct map_session_data *sd)
{
int i, c = 0;
int64 expire_tick, next_tick = INT64_MAX;
+ nullpo_retv(sd);
for( i = 0; i < MAX_INVENTORY; i++ )
{ // Check for Rentals on Inventory
if( sd->status.inventory[i].nameid == 0 )
@@ -672,10 +741,12 @@ int pc_setnewpc(struct map_session_data *sd, int account_id, int char_id, int lo
sd->client_tick = client_tick;
sd->state.active = 0; //to be set to 1 after player is fully authed and loaded.
sd->bl.type = BL_PC;
- sd->canlog_tick = timer->gettick();
+ if (battle_config.prevent_logout_trigger & PLT_LOGIN)
+ sd->canlog_tick = timer->gettick();
//Required to prevent homunculus copuing a base speed of 0.
sd->battle_status.speed = sd->base_status.speed = DEFAULT_WALK_SPEED;
sd->state.warp_clean = 1;
+ sd->catch_target_class = -1;
return 0;
}
@@ -684,6 +755,7 @@ int pc_equippoint(struct map_session_data *sd,int n)
int ep = 0;
nullpo_ret(sd);
+ Assert_ret(n >= 0 && n < MAX_INVENTORY);
if(!sd->inventory_data[n])
return 0;
@@ -697,8 +769,8 @@ int pc_equippoint(struct map_session_data *sd,int n)
|| sd->inventory_data[n]->look == W_1HAXE
) {
if (pc->checkskill(sd,AS_LEFT) > 0
- || (sd->class_&MAPID_UPPERMASK) == MAPID_ASSASSIN
- || (sd->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO
+ || (sd->job & MAPID_UPPERMASK) == MAPID_ASSASSIN
+ || (sd->job & MAPID_UPPERMASK) == MAPID_KAGEROUOBORO
) {
//Kagerou and Oboro can dual wield daggers. [Rytech]
if( ep == EQP_HAND_R )
@@ -810,6 +882,7 @@ bool pc_isequipped(struct map_session_data *sd, int nameid)
{
int i, j;
+ nullpo_retr(false, sd);
for (i = 0; i < EQI_MAX; i++) {
int index = sd->equip_index[i];
if( index < 0 ) continue;
@@ -872,7 +945,7 @@ bool pc_can_Adopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd
return false;
}
- if( !( ( b_sd->status.class_ >= JOB_NOVICE && b_sd->status.class_ <= JOB_THIEF ) || b_sd->status.class_ == JOB_SUPER_NOVICE ) )
+ if (!(b_sd->status.class >= JOB_NOVICE && b_sd->status.class <= JOB_THIEF) && b_sd->status.class != JOB_SUPER_NOVICE)
return false;
return true;
@@ -883,19 +956,20 @@ bool pc_can_Adopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd
*------------------------------------------*/
bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd)
{
- int job, joblevel;
+ int class, joblevel;
unsigned int jobexp;
if( !pc->can_Adopt(p1_sd, p2_sd, b_sd) )
return false;
+ nullpo_retr(false, b_sd);
// Preserve current job levels and progress
joblevel = b_sd->status.job_level;
jobexp = b_sd->status.job_exp;
- job = pc->mapid2jobid(b_sd->class_|JOBL_BABY, b_sd->status.sex);
- if( job != -1 && !pc->jobchange(b_sd, job, 0) )
- { // Success, proceed to configure parents and baby skills
+ class = pc->mapid2jobid(b_sd->job | JOBL_BABY, b_sd->status.sex);
+ if (class != -1 && !pc->jobchange(b_sd, class, 0)) {
+ // Success, proceed to configure parents and baby skills
p1_sd->status.child = b_sd->status.char_id;
p2_sd->status.child = b_sd->status.char_id;
b_sd->status.father = p1_sd->status.char_id;
@@ -944,11 +1018,11 @@ int pc_isequip(struct map_session_data *sd,int n)
if(pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT))
return 1;
- if (item->elv && sd->status.base_level < (unsigned int)item->elv) {
+ if (item->elv && sd->status.base_level < item->elv) {
clif->msgtable(sd, MSG_ITEM_CANT_EQUIP_LVL);
return 0;
}
- if (item->elvmax && sd->status.base_level > (unsigned int)item->elvmax) {
+ if (item->elvmax && sd->status.base_level > item->elvmax) {
clif->msgtable(sd, MSG_ITEM_CANT_EQUIP_LVL);
return 0;
}
@@ -956,12 +1030,11 @@ int pc_isequip(struct map_session_data *sd,int n)
return 0;
if ( item->equip & EQP_AMMO ) {
- if ( (sd->state.active && !pc_iscarton(sd)) // check if sc data is already loaded.
- && (sd->status.class_ == JOB_GENETIC_T || sd->status.class_ == JOB_GENETIC) ) {
+ if (sd->state.active && !pc_iscarton(sd) && (sd->job & MAPID_THIRDMASK) == MAPID_GENETIC) { // check if sc data is already loaded.
clif->msgtable(sd, MSG_ITEM_NEED_CART);
return 0;
}
- if ( !pc_ismadogear(sd) && (sd->status.class_ == JOB_MECHANIC_T || sd->status.class_ == JOB_MECHANIC) ) {
+ if (!pc_ismadogear(sd) && (sd->job & MAPID_THIRDMASK) == MAPID_MECHANIC) {
clif->msgtable(sd, MSG_ITEM_NEED_MADO);
return 0;
}
@@ -998,14 +1071,26 @@ int pc_isequip(struct map_session_data *sd,int n)
}
}
//Not equipable by class. [Skotlex]
- if (!(1<<(sd->class_&MAPID_BASEMASK)&item->class_base[(sd->class_&JOBL_2_1)?1:((sd->class_&JOBL_2_2)?2:0)]))
+ if (((1ULL<<(sd->job & MAPID_BASEMASK)) & item->class_base[(sd->job & JOBL_2_1) != 0 ? 1 : ((sd->job & JOBL_2_2) != 0 ? 2 : 0)]) == 0)
return 0;
//Not usable by upper class. [Inkfish]
while( 1 ) {
- if( item->class_upper&ITEMUPPER_NORMAL && !(sd->class_&(JOBL_UPPER|JOBL_THIRD|JOBL_BABY)) ) break;
- if( item->class_upper&ITEMUPPER_UPPER && sd->class_&(JOBL_UPPER|JOBL_THIRD) ) break;
- if( item->class_upper&ITEMUPPER_BABY && sd->class_&JOBL_BABY ) break;
- if( item->class_upper&ITEMUPPER_THIRD && sd->class_&JOBL_THIRD ) break;
+ if ((item->class_upper & ITEMUPPER_NORMAL) != 0) {
+ if ((sd->job & (JOBL_UPPER|JOBL_THIRD|JOBL_BABY)) == 0)
+ break;
+ }
+ if ((item->class_upper & ITEMUPPER_UPPER) != 0) {
+ if ((sd->job & (JOBL_UPPER|JOBL_THIRD)) != 0)
+ break;
+ }
+ if ((item->class_upper & ITEMUPPER_BABY) != 0) {
+ if ((sd->job & JOBL_BABY) != 0)
+ break;
+ }
+ if ((item->class_upper & ITEMUPPER_THIRD) != 0) {
+ if ((sd->job & JOBL_THIRD) != 0)
+ break;
+ }
return 0;
}
@@ -1033,10 +1118,14 @@ int pc_isequip(struct map_session_data *sd,int n)
* No problem with the session id
* set the status that has been sent from char server
*------------------------------------------*/
-bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, struct mmo_charstatus *st, bool changing_mapservers) {
+bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, const struct mmo_charstatus *st, bool changing_mapservers)
+{
int i;
int64 tick = timer->gettick();
- uint32 ip = sockt->session[sd->fd]->client_addr;
+ uint32 ip;
+
+ nullpo_retr(false, sd);
+ ip = sockt->session[sd->fd]->client_addr;
sd->login_id2 = login_id2;
@@ -1055,13 +1144,16 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
}
//Set the map-server used job id. [Skotlex]
- i = pc->jobid2mapid(sd->status.class_);
- if (i == -1) { //Invalid class?
- ShowError("pc_authok: Invalid class %d for player %s (%d:%d). Class was changed to novice.\n", sd->status.class_, sd->status.name, sd->status.account_id, sd->status.char_id);
- sd->status.class_ = JOB_NOVICE;
- sd->class_ = MAPID_NOVICE;
- } else
- sd->class_ = i;
+ {
+ int job = pc->jobid2mapid(sd->status.class);
+ if (job == -1) {
+ ShowError("pc_authok: Invalid class %d for player %s (%d:%d). Class was changed to novice.\n", sd->status.class, sd->status.name, sd->status.account_id, sd->status.char_id);
+ sd->status.class = JOB_NOVICE;
+ sd->job = MAPID_NOVICE;
+ } else {
+ sd->job = job;
+ }
+ }
// Checks and fixes to character status data, that are required
// in case of configuration change or stuff, which cannot be
@@ -1142,7 +1234,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
sd->sc.option = sd->status.option; //This is the actual option used in battle.
//Set here because we need the inventory data for weapon sprite parsing.
- status->set_viewdata(&sd->bl, sd->status.class_);
+ status->set_viewdata(&sd->bl, sd->status.class);
unit->dataset(&sd->bl);
sd->guild_x = -1;
@@ -1159,13 +1251,14 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
sd->bg_queue.type = 0;
VECTOR_INIT(sd->script_queues);
+ VECTOR_INIT(sd->storage.item); // initialize storage item vector.
sd->state.dialog = 0;
sd->delayed_damage = 0;
- if( battle_config.item_check )
- sd->state.itemcheck = 1;
+ if (battle->bc->item_check != PCCHECKITEM_NONE) // Check and flag items for inspection.
+ sd->itemcheck = (enum pc_checkitem_types) battle->bc->item_check;
// Event Timers
for( i = 0; i < MAX_EVENTTIMER; i++ )
@@ -1212,7 +1305,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
//display login notice
ShowInfo("'"CL_WHITE"%s"CL_RESET"' logged in."
" (AID/CID: '"CL_WHITE"%d/%d"CL_RESET"',"
- " IP: '"CL_WHITE"%d.%d.%d.%d"CL_RESET"',"
+ " IP: '"CL_WHITE"%u.%u.%u.%u"CL_RESET"',"
" Group '"CL_WHITE"%d"CL_RESET"').\n",
sd->status.name, sd->status.account_id, sd->status.char_id,
CONVIP(ip), sd->group_id);
@@ -1266,6 +1359,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
*------------------------------------------*/
void pc_authfail(struct map_session_data *sd)
{
+ nullpo_retv(sd);
clif->authfail_fd(sd->fd, 0);
return;
}
@@ -1303,6 +1397,7 @@ int pc_reg_received(struct map_session_data *sd)
{
int i, idx = 0;
+ nullpo_ret(sd);
sd->vars_ok = true;
sd->change_level_2nd = pc_readglobalreg(sd,script->add_str("jobchange_level"));
@@ -1316,7 +1411,7 @@ int pc_reg_received(struct map_session_data *sd)
// Cooking Exp
sd->cook_mastery = pc_readglobalreg(sd,script->add_str("COOK_MASTERY"));
- if( (sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON ) {
+ if ((sd->job & MAPID_BASEMASK) == MAPID_TAEKWON) {
// Better check for class rather than skill to prevent "skill resets" from unsetting this
sd->mission_mobid = pc_readglobalreg(sd,script->add_str("TK_MISSION_ID"));
sd->mission_count = pc_readglobalreg(sd,script->add_str("TK_MISSION_COUNT"));
@@ -1389,6 +1484,9 @@ int pc_reg_received(struct map_session_data *sd)
status_calc_pc(sd,SCO_FIRST|SCO_FORCE);
chrif->scdata_request(sd->status.account_id, sd->status.char_id);
+ // Storage Request
+ intif->request_account_storage(sd);
+
intif->Mail_requestinbox(sd->status.char_id, 0); // MAIL SYSTEM - Request Mail Inbox
intif->request_questlog(sd);
@@ -1398,7 +1496,7 @@ int pc_reg_received(struct map_session_data *sd)
}
if (pc_isinvisible(sd)) {
- sd->vd.class_ = INVISIBLE_CLASS;
+ sd->vd.class = INVISIBLE_CLASS;
clif->message(sd->fd, msg_sd(sd,11)); // Invisible: On
// decrement the number of pvp players on the map
map->list[sd->bl.m].users_pvp--;
@@ -1445,17 +1543,17 @@ int pc_calc_skillpoint(struct map_session_data* sd) {
int pc_calc_skilltree(struct map_session_data *sd)
{
int i,id=0,flag;
- int c=0;
+ int class = 0, classidx = 0;
nullpo_ret(sd);
i = pc->calc_skilltree_normalize_job(sd);
- c = pc->mapid2jobid(i, sd->status.sex);
- if( c == -1 )
- { //Unable to normalize job??
+ class = pc->mapid2jobid(i, sd->status.sex);
+ if (class == -1) {
+ //Unable to normalize job??
ShowError("pc_calc_skilltree: Unable to normalize job %d for character %s (%d:%d)\n", i, sd->status.name, sd->status.account_id, sd->status.char_id);
return 1;
}
- c = pc->class2idx(c);
+ classidx = pc->class2idx(class);
for( i = 0; i < MAX_SKILL; i++ ) {
if( sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED ) //Don't touch these
@@ -1464,10 +1562,10 @@ int pc_calc_skilltree(struct map_session_data *sd)
if( sd->status.skill[i].flag == SKILL_FLAG_PERMANENT ) {
switch( skill->dbs->db[i].nameid ) {
case NV_TRICKDEAD:
- if( (sd->class_&(MAPID_BASEMASK|JOBL_2)) != MAPID_NOVICE ) {
- sd->status.skill[i].id = 0;
- sd->status.skill[i].lv = 0;
- sd->status.skill[i].flag = 0;
+ if ((sd->job & MAPID_UPPERMASK) != MAPID_NOVICE) {
+ sd->status.skill[i].id = 0;
+ sd->status.skill[i].lv = 0;
+ sd->status.skill[i].flag = 0;
}
break;
}
@@ -1537,16 +1635,16 @@ int pc_calc_skilltree(struct map_session_data *sd)
do {
flag = 0;
- for (i = 0; i < MAX_SKILL_TREE && (id = pc->skill_tree[c][i].id) > 0; i++) {
- int idx = pc->skill_tree[c][i].idx;
+ for (i = 0; i < MAX_SKILL_TREE && (id = pc->skill_tree[classidx][i].id) > 0; i++) {
+ int idx = pc->skill_tree[classidx][i].idx;
bool satisfied = true;
if (sd->status.skill[idx].id > 0)
continue; //Skill already known.
if (!battle_config.skillfree) {
int j;
- for (j = 0; j < VECTOR_LENGTH(pc->skill_tree[c][i].need); j++) {
- struct skill_tree_requirement *req = &VECTOR_INDEX(pc->skill_tree[c][i].need, j);
+ for (j = 0; j < VECTOR_LENGTH(pc->skill_tree[classidx][i].need); j++) {
+ struct skill_tree_requirement *req = &VECTOR_INDEX(pc->skill_tree[classidx][i].need, j);
int level;
if (sd->status.skill[req->idx].id == 0
|| sd->status.skill[req->idx].flag == SKILL_FLAG_TEMPORARY
@@ -1561,8 +1659,8 @@ int pc_calc_skilltree(struct map_session_data *sd)
break;
}
}
- if (sd->status.job_level < pc->skill_tree[c][i].joblv) {
- int jobid = pc->mapid2jobid(sd->class_, sd->status.sex); // need to get its own skilltree
+ if (sd->status.job_level < (int)pc->skill_tree[classidx][i].joblv) {
+ int jobid = pc->mapid2jobid(sd->job, sd->status.sex); // need to get its own skilltree
if (jobid > -1) {
if (!pc->skill_tree[pc->class2idx(jobid)][i].inherited)
satisfied = false; // job level requirement wasn't satisfied
@@ -1593,16 +1691,17 @@ int pc_calc_skilltree(struct map_session_data *sd)
} while(flag);
//
- if( c > 0 && (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && sd->status.skill_point == 0 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) )
- {
- /* Taekwon Ranger Bonus Skill Tree
+ if (classidx > 0 && (sd->job & MAPID_UPPERMASK) == MAPID_TAEKWON
+ && sd->status.base_level >= 90 && sd->status.skill_point == 0
+ && pc->fame_rank(sd->status.char_id, RANKTYPE_TAEKWON) > 0) {
+ /* Taekwon Ranker Bonus Skill Tree
============================================
- Grant All Taekwon Tree, but only as Bonus Skills in case they drop from ranking.
- (c > 0) to avoid grant Novice Skill Tree in case of Skill Reset (need more logic)
- (sd->status.skill_point == 0) to wait until all skill points are asigned to avoid problems with Job Change quest. */
- for( i = 0; i < MAX_SKILL_TREE && (id = pc->skill_tree[c][i].id) > 0; i++ ) {
- int idx = pc->skill_tree[c][i].idx;
+ for (i = 0; i < MAX_SKILL_TREE && (id = pc->skill_tree[classidx][i].id) > 0; i++) {
+ int idx = pc->skill_tree[classidx][i].idx;
if( (skill->dbs->db[idx].inf2&(INF2_QUEST_SKILL|INF2_WEDDING_SKILL)) )
continue; //Do not include Quest/Wedding skills.
@@ -1613,7 +1712,7 @@ int pc_calc_skilltree(struct map_session_data *sd)
sd->status.skill[idx].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[idx].lv; // Remember original level
}
- sd->status.skill[idx].lv = skill->tree_get_max(id, sd->status.class_);
+ sd->status.skill[idx].lv = skill->tree_get_max(id, sd->status.class);
}
}
@@ -1629,6 +1728,7 @@ void pc_check_skilltree(struct map_session_data *sd, int skill_id)
if(battle_config.skillfree)
return; //Function serves no purpose if this is set
+ nullpo_retv(sd);
i = pc->calc_skilltree_normalize_job(sd);
c = pc->mapid2jobid(i, sd->status.sex);
if (c == -1) { //Unable to normalize job??
@@ -1664,8 +1764,8 @@ void pc_check_skilltree(struct map_session_data *sd, int skill_id)
if (!satisfied)
continue;
- if (sd->status.job_level < pc->skill_tree[c][i].joblv) {
- int jobid = pc->mapid2jobid(sd->class_, sd->status.sex); // need to get its own skilltree
+ if (sd->status.job_level < (int)pc->skill_tree[c][i].joblv) {
+ int jobid = pc->mapid2jobid(sd->job, sd->status.sex); // need to get its own skilltree
if (jobid > -1) {
if (!pc->skill_tree[pc->class2idx(jobid)][i].inherited)
continue;
@@ -1694,6 +1794,7 @@ void pc_check_skilltree(struct map_session_data *sd, int skill_id)
int pc_clean_skilltree(struct map_session_data *sd)
{
int i;
+ nullpo_ret(sd);
for (i = 0; i < MAX_SKILL; i++){
if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED) {
sd->status.skill[i].id = 0;
@@ -1711,10 +1812,12 @@ int pc_clean_skilltree(struct map_session_data *sd)
int pc_calc_skilltree_normalize_job(struct map_session_data *sd)
{
int skill_point, novice_skills;
- int c = sd->class_;
+ uint16 job;
+ nullpo_ret(sd);
+ job = sd->job;
if (!battle_config.skillup_limit || pc_has_permission(sd, PC_PERM_ALL_SKILL))
- return c;
+ return job;
skill_point = pc->calc_skillpoint(sd);
@@ -1722,62 +1825,57 @@ int pc_calc_skilltree_normalize_job(struct map_session_data *sd)
sd->sktree.second = sd->sktree.third = 0;
- // limit 1st class and above to novice job levels
- if(skill_point < novice_skills) {
- c = MAPID_NOVICE;
- }
- // limit 2nd class and above to first class job levels (super novices are exempt)
- else if ((sd->class_&JOBL_2) && (sd->class_&MAPID_UPPERMASK) != MAPID_SUPER_NOVICE)
- {
+ if (skill_point < novice_skills && (sd->job & MAPID_BASEMASK) != MAPID_SUMMONER) {
+ // limit 1st class and above to novice job levels
+ job = MAPID_NOVICE;
+ } else if ((sd->job & JOBL_2) != 0 && (sd->job & MAPID_UPPERMASK) != MAPID_SUPER_NOVICE) {
+ // limit 2nd class and above to first class job levels (super novices are exempt)
// regenerate change_level_2nd
- if (!sd->change_level_2nd)
- {
- if (sd->class_&JOBL_THIRD)
- {
+ if (sd->change_level_2nd == 0) {
+ if ((sd->job & JOBL_THIRD) != 0) {
// if neither 2nd nor 3rd jobchange levels are known, we have to assume a default for 2nd
- if (!sd->change_level_3rd)
- sd->change_level_2nd = pc->max_level[pc->class2idx(pc->mapid2jobid(sd->class_&MAPID_UPPERMASK, sd->status.sex))][1];
- else
+ if (sd->change_level_3rd == 0) {
+ sd->change_level_2nd = pc->max_level[pc->class2idx(pc->mapid2jobid(sd->job & MAPID_UPPERMASK, sd->status.sex))][1];
+ } else {
sd->change_level_2nd = 1 + skill_point + sd->status.skill_point
- (sd->status.job_level - 1)
- (sd->change_level_3rd - 1)
- novice_skills;
- }
- else
- {
+ }
+ } else {
sd->change_level_2nd = 1 + skill_point + sd->status.skill_point
- (sd->status.job_level - 1)
- novice_skills;
}
- pc_setglobalreg (sd, script->add_str("jobchange_level"), sd->change_level_2nd);
+ pc_setglobalreg(sd, script->add_str("jobchange_level"), sd->change_level_2nd);
}
if (skill_point < novice_skills + (sd->change_level_2nd - 1)) {
- c &= MAPID_BASEMASK;
+ job &= MAPID_BASEMASK;
sd->sktree.second = ( novice_skills + (sd->change_level_2nd - 1) ) - skill_point;
- } else if(sd->class_&JOBL_THIRD) { // limit 3rd class to 2nd class/trans job levels
+ } else if ((sd->job & JOBL_THIRD) != 0) { // limit 3rd class to 2nd class/trans job levels
// regenerate change_level_3rd
- if (!sd->change_level_3rd) {
+ if (sd->change_level_3rd == 0) {
sd->change_level_3rd = 1 + skill_point + sd->status.skill_point
- (sd->status.job_level - 1)
- (sd->change_level_2nd - 1)
- novice_skills;
- pc_setglobalreg (sd, script->add_str("jobchange_level_3rd"), sd->change_level_3rd);
+ pc_setglobalreg(sd, script->add_str("jobchange_level_3rd"), sd->change_level_3rd);
}
if (skill_point < novice_skills + (sd->change_level_2nd - 1) + (sd->change_level_3rd - 1)) {
- c &= MAPID_UPPERMASK;
+ job &= MAPID_UPPERMASK;
sd->sktree.third = (novice_skills + (sd->change_level_2nd - 1) + (sd->change_level_3rd - 1)) - skill_point;
}
}
}
// restore non-limiting flags
- c |= sd->class_&(JOBL_UPPER|JOBL_BABY);
+ job |= sd->job & (JOBL_UPPER|JOBL_BABY);
- return c;
+ return job;
}
/*==========================================
@@ -1818,37 +1916,40 @@ int pc_updateweightstatus(struct map_session_data *sd)
return 0;
}
-int pc_disguise(struct map_session_data *sd, int class_) {
- if (class_ == -1 && sd->disguise == -1)
+int pc_disguise(struct map_session_data *sd, int class)
+{
+ nullpo_ret(sd);
+ if (class == -1 && sd->disguise == -1)
return 0;
- if (class_ >= 0 && sd->disguise == class_)
+ if (class >= 0 && sd->disguise == class)
return 0;
if (pc_isinvisible(sd)) { //Character is invisible. Stealth class-change. [Skotlex]
- sd->disguise = class_; //viewdata is set on uncloaking.
+ sd->disguise = class; //viewdata is set on uncloaking.
return 2;
}
if (sd->bl.prev != NULL) {
- if( class_ == -1 && sd->disguise == sd->status.class_ ) {
+ if (class == -1 && sd->disguise == sd->status.class) {
clif->clearunit_single(-sd->bl.id,CLR_OUTSIGHT,sd->fd);
- } else if ( class_ != sd->status.class_ ) {
+ } else if (class != sd->status.class) {
pc_stop_walking(sd, STOPWALKING_FLAG_NONE);
clif->clearunit_area(&sd->bl, CLR_OUTSIGHT);
}
}
- if (class_ == -1) {
+ if (class == -1) {
sd->disguise = -1;
- class_ = sd->status.class_;
- } else
- sd->disguise = class_;
+ class = sd->status.class;
+ } else {
+ sd->disguise = class;
+ }
- status->set_viewdata(&sd->bl, class_);
+ status->set_viewdata(&sd->bl, class);
clif->changeoption(&sd->bl);
// We need to update the client so it knows that a costume is being used
if( sd->sc.option&OPTION_COSTUME ) {
- clif->changelook(&sd->bl,LOOK_BASE,sd->vd.class_);
+ clif->changelook(&sd->bl, LOOK_BASE, sd->vd.class);
clif->changelook(&sd->bl,LOOK_WEAPON,0);
clif->changelook(&sd->bl,LOOK_SHIELD,0);
clif->changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color);
@@ -1856,13 +1957,13 @@ int pc_disguise(struct map_session_data *sd, int class_) {
if (sd->bl.prev != NULL) {
clif->spawn(&sd->bl);
- if (class_ == sd->status.class_ && pc_iscarton(sd)) {
+ if (class == sd->status.class && pc_iscarton(sd)) {
//It seems the cart info is lost on undisguise.
clif->cartlist(sd);
clif->updatestatus(sd,SP_CARTINFO);
}
- if (sd->chatID) {
- struct chat_data *cd = map->id2cd(sd->chatID);
+ if (sd->chat_id != 0) {
+ struct chat_data *cd = map->id2cd(sd->chat_id);
if (cd != NULL)
clif->dispchat(cd,0);
@@ -1878,6 +1979,8 @@ int pc_bonus_autospell(struct s_autospell *spell, int max, short id, short lv, s
if( !rate )
return 0;
+ nullpo_ret(spell);
+ Assert_ret(max <= 15); // autospell array size
for( i = 0; i < max && spell[i].id; i++ )
{
if( (spell[i].card_id == card_id || spell[i].rate < 0 || rate < 0) && spell[i].id == id && spell[i].lv == lv )
@@ -1914,6 +2017,8 @@ int pc_bonus_autospell_onskill(struct s_autospell *spell, int max, short src_ski
if( !rate )
return 0;
+ nullpo_ret(spell);
+ Assert_ret(max <= 15); // autospell array size
for( i = 0; i < max && spell[i].id; i++ )
{
; // each autospell works independently
@@ -1949,6 +2054,8 @@ int pc_bonus_autospell_onskill(struct s_autospell *spell, int max, short src_ski
int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id, int16 rate, int16 arrow_rate, uint8 flag, uint16 duration)
{
int i;
+
+ nullpo_ret(effect);
if (!(flag&(ATF_SHORT|ATF_LONG)))
flag|=ATF_SHORT|ATF_LONG; //Default range: both
if (!(flag&(ATF_TARGET|ATF_SELF)))
@@ -1978,6 +2085,8 @@ int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id, int16
int pc_bonus_addeff_onskill(struct s_addeffectonskill* effect, int max, enum sc_type id, short rate, short skill_id, unsigned char target) {
int i;
+
+ nullpo_ret(effect);
for( i = 0; i < max && effect[i].skill; i++ ) {
if( effect[i].id == id && effect[i].skill == skill_id && effect[i].target == target ) {
effect[i].rate += rate;
@@ -1998,6 +2107,7 @@ int pc_bonus_addeff_onskill(struct s_addeffectonskill* effect, int max, enum sc_
int pc_bonus_item_drop(struct s_add_drop *drop, const short max, short id, short group, int race_mask, int rate) {
int i;
+ nullpo_ret(drop);
//Apply config rate adjustment settings.
if (rate >= 0) { //Absolute drop.
if (battle_config.item_rate_adddrop != 100)
@@ -2045,6 +2155,8 @@ int pc_bonus_item_drop(struct s_add_drop *drop, const short max, short id, short
int pc_addautobonus(struct s_autobonus *bonus,char max,const char *bonus_script,short rate,unsigned int dur,short flag,const char *other_script,unsigned short pos,bool onskill) {
int i;
+ nullpo_ret(bonus);
+ nullpo_ret(bonus_script);
ARR_FIND(0, max, i, bonus[i].rate == 0);
if( i == max )
{
@@ -2081,6 +2193,7 @@ int pc_delautobonus(struct map_session_data* sd, struct s_autobonus *autobonus,c
{
int i;
nullpo_ret(sd);
+ nullpo_ret(autobonus);
for( i = 0; i < max; i++ )
{
@@ -2152,6 +2265,7 @@ int pc_bonus_addele(struct map_session_data* sd, unsigned char ele, short rate,
int i;
struct weapon_data* wd;
+ nullpo_ret(sd);
wd = (sd->state.lr_flag ? &sd->left_weapon : &sd->right_weapon);
ARR_FIND(0, MAX_PC_BONUS, i, wd->addele2[i].rate == 0);
@@ -2185,6 +2299,7 @@ int pc_bonus_subele(struct map_session_data* sd, unsigned char ele, short rate,
{
int i;
+ nullpo_ret(sd);
ARR_FIND(0, MAX_PC_BONUS, i, sd->subele2[i].rate == 0);
if (i == MAX_PC_BONUS)
@@ -2883,6 +2998,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val) {
break;
default:
ShowWarning("pc_bonus: unknown type %d %d !\n",type,val);
+ Assert_report(0);
break;
}
return 0;
@@ -3675,6 +3791,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
#endif
default:
ShowWarning("pc_bonus2: unknown type %d %d %d!\n",type,type2,val);
+ Assert_report(0);
break;
}
return 0;
@@ -3847,6 +3964,7 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val)
default:
ShowWarning("pc_bonus3: unknown type %d %d %d %d!\n",type,type2,type3,val);
+ Assert_report(0);
break;
}
@@ -3941,6 +4059,7 @@ int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4
default:
ShowWarning("pc_bonus4: unknown type %d %d %d %d %d!\n",type,type2,type3,type4,val);
+ Assert_report(0);
break;
}
@@ -3968,6 +4087,7 @@ int pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type4
default:
ShowWarning("pc_bonus5: unknown type %d %d %d %d %d %d!\n",type,type2,type3,type4,type5,val);
+ Assert_report(0);
break;
}
@@ -4085,7 +4205,7 @@ bool pc_can_insert_card_into(struct map_session_data* sd, int idx_card, int idx_
ARR_FIND( 0, sd->inventory_data[idx_equip]->slot, i, sd->status.inventory[idx_equip].card[i] == 0);
if (i == sd->inventory_data[idx_equip]->slot)
return false; // no free slots
- return true;
+ return true;
}
/**
@@ -4105,7 +4225,7 @@ bool pc_can_insert_card(struct map_session_data* sd, int idx_card)
return false; // target card missing
if (sd->inventory_data[idx_card]->type != IT_CARD)
return false; // must be a card
- return true;
+ return true;
}
/*==========================================
@@ -4129,7 +4249,7 @@ int pc_insert_card(struct map_session_data* sd, int idx_card, int idx_equip)
// remember the card id to insert
nameid = sd->status.inventory[idx_card].nameid;
- if( pc->delitem(sd, idx_card, 1, 1, DELITEM_NORMAL, LOG_TYPE_OTHER) == 1 )
+ if( pc->delitem(sd, idx_card, 1, 1, DELITEM_NORMAL, LOG_TYPE_CARD) == 1 )
{// failed
clif->insert_card(sd,idx_equip,idx_card,1);
}
@@ -4139,9 +4259,9 @@ int pc_insert_card(struct map_session_data* sd, int idx_card, int idx_equip)
ARR_FIND( 0, sd->inventory_data[idx_equip]->slot, i, sd->status.inventory[idx_equip].card[i] == 0);
if (i == sd->inventory_data[idx_equip]->slot)
return 0; // no free slots
- logs->pick_pc(sd, LOG_TYPE_OTHER, -1, &sd->status.inventory[idx_equip],sd->inventory_data[idx_equip]);
+ logs->pick_pc(sd, LOG_TYPE_CARD, -1, &sd->status.inventory[idx_equip],sd->inventory_data[idx_equip]);
sd->status.inventory[idx_equip].card[i] = nameid;
- logs->pick_pc(sd, LOG_TYPE_OTHER, 1, &sd->status.inventory[idx_equip],sd->inventory_data[idx_equip]);
+ logs->pick_pc(sd, LOG_TYPE_CARD, 1, &sd->status.inventory[idx_equip],sd->inventory_data[idx_equip]);
clif->insert_card(sd,idx_equip,idx_card,0);
return 1;
}
@@ -4268,7 +4388,7 @@ int pc_payzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type,
if( zeny > 0 && sd->state.showzeny ) {
char output[255];
sprintf(output, "Removed %dz.", zeny);
- clif_disp_onlyself(sd,output,strlen(output));
+ clif_disp_onlyself(sd, output);
}
return 0;
@@ -4310,7 +4430,7 @@ int pc_paycash(struct map_session_data *sd, int price, int points)
{
char output[128];
sprintf(output, msg_sd(sd,504), points, cash, sd->kafraPoints, sd->cashPoints);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
}
return cash+points;
}
@@ -4335,7 +4455,7 @@ int pc_getcash(struct map_session_data *sd, int cash, int points)
if( battle_config.cashshop_show_points )
{
sprintf(output, msg_sd(sd,505), cash, sd->cashPoints);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
}
return cash;
}
@@ -4358,7 +4478,7 @@ int pc_getcash(struct map_session_data *sd, int cash, int points)
if( battle_config.cashshop_show_points )
{
sprintf(output, msg_sd(sd,506), points, sd->kafraPoints);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
}
return points;
}
@@ -4396,7 +4516,7 @@ int pc_getzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type,
if( zeny > 0 && sd->state.showzeny ) {
char output[255];
sprintf(output, "Gained %dz.", zeny);
- clif_disp_onlyself(sd,output,strlen(output));
+ clif_disp_onlyself(sd, output);
}
return 0;
@@ -4555,6 +4675,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
int pc_delitem(struct map_session_data *sd,int n,int amount,int type, short reason, e_log_pick_type log_type)
{
nullpo_retr(1, sd);
+ Assert_retr(1, n >= 0 && n < MAX_INVENTORY);
if(sd->status.inventory[n].nameid==0 || amount <= 0 || sd->status.inventory[n].amount<amount || sd->inventory_data[n] == NULL)
return 1;
@@ -4602,13 +4723,13 @@ int pc_dropitem(struct map_session_data *sd,int n,int amount)
return 0;
if( map->list[sd->bl.m].flag.nodrop ) {
- clif->message (sd->fd, msg_sd(sd,271));
- return 0; //Can't drop items in nodrop mapflag maps.
+ clif->message (sd->fd, msg_sd(sd,271)); // You can't drop items in this map
+ return 0;
}
if( !pc->candrop(sd,&sd->status.inventory[n]) )
{
- clif->message (sd->fd, msg_sd(sd,263));
+ clif->message (sd->fd, msg_sd(sd,263)); // This item cannot be dropped.
return 0;
}
@@ -4698,6 +4819,7 @@ int pc_isUseitem(struct map_session_data *sd,int n)
int nameid;
nullpo_ret(sd);
+ Assert_ret(n >= 0 && n < MAX_INVENTORY);
item = sd->inventory_data[n];
nameid = sd->status.inventory[n].nameid;
@@ -4723,17 +4845,43 @@ int pc_isUseitem(struct map_session_data *sd,int n)
switch( nameid ) { // TODO: Is there no better way to handle this, other than hardcoding item IDs?
case ITEMID_ANODYNE:
- if( map_flag_gvg2(sd->bl.m) )
- return 0;
- /* Fall through */
- case ITEMID_ALOEBERA:
- if( pc_issit(sd) )
+ if (map_flag_gvg2(sd->bl.m))
return 0;
break;
+
+ case ITEMID_GIANT_FLY_WING: {
+ struct party_data *p;
+
+ if (!sd->status.party_id) {
+ clif->msgtable(sd, MSG_PARTY_MEMBER_NOT_SUMMONED);
+ break;
+ }
+
+ if ((p = party->search(sd->status.party_id)) != NULL) {
+ int i;
+ int16 m;
+
+ ARR_FIND(0, MAX_PARTY, i, p->data[i].sd == sd);
+
+ if (i == MAX_PARTY || !p->party.member[i].leader) {
+ clif->msgtable(sd, MSG_PARTY_MEMBER_NOT_SUMMONED);
+ break;
+ }
+
+ m = sd->bl.m;
+
+ ARR_FIND(0, MAX_PARTY, i, p->data[i].sd && p->data[i].sd != sd && p->data[i].sd->bl.m == m);
+
+ if (i == MAX_PARTY || pc_isdead(p->data[i].sd)) {
+ clif->msgtable(sd, MSG_PARTY_NO_MEMBER_IN_MAP);
+ break;
+ }
+ }
+ }
+ FALLTHROUGH
case ITEMID_WING_OF_FLY:
- case ITEMID_GIANT_FLY_WING:
- if( map->list[sd->bl.m].flag.noteleport || map_flag_gvg2(sd->bl.m) ) {
- clif->skill_mapinfomessage(sd,0);
+ if (map->list[sd->bl.m].flag.noteleport || map_flag_gvg2(sd->bl.m)) {
+ clif->skill_mapinfomessage(sd, 0);
return 0;
}
/* Fall through */
@@ -4759,25 +4907,6 @@ int pc_isUseitem(struct map_session_data *sd,int n)
if( map->list[sd->bl.m].flag.nobranch || map_flag_gvg2(sd->bl.m) )
return 0;
break;
- case ITEMID_BUBBLE_GUM:
- case ITEMID_COMP_BUBBLE_GUM:
- if( sd->sc.data[SC_CASH_RECEIVEITEM] )
- return 0;
- break;
- case ITEMID_BATTLE_MANUAL:
- case ITEMID_COMP_BATTLE_MANUAL:
- case ITEMID_THICK_MANUAL50:
- case ITEMID_NOBLE_NAMEPLATE:
- case ITEMID_BATTLE_MANUAL25:
- case ITEMID_BATTLE_MANUAL100:
- case ITEMID_BATTLE_MANUAL_X3:
- if( sd->sc.data[SC_CASH_PLUSEXP] )
- return 0;
- break;
- case ITEMID_JOB_MANUAL50:
- if( sd->sc.data[SC_CASH_PLUSONLYJOBEXP] )
- return 0;
- break;
// Mercenary Items
case ITEMID_MERCENARY_RED_POTION:
@@ -4804,17 +4933,6 @@ int pc_isUseitem(struct map_session_data *sd,int n)
if( nameid >= ITEMID_BOW_MERCENARY_SCROLL1 && nameid <= ITEMID_SPEARMERCENARY_SCROLL10 && sd->md != NULL ) // Mercenary Scrolls
return 0;
- /**
- * Only Rune Knights may use runes
- **/
- if( itemdb_is_rune(nameid) && (sd->class_&MAPID_THIRDMASK) != MAPID_RUNE_KNIGHT )
- return 0;
- /**
- * Only GCross may use poisons
- **/
- else if( itemdb_is_poison(nameid) && (sd->class_&MAPID_THIRDMASK) != MAPID_GUILLOTINE_CROSS )
- return 0;
-
if( item->package || item->group ) {
if (pc_is90overweight(sd)) {
clif->msgtable(sd, MSG_ITEM_CANT_OBTAIN_WEIGHT);
@@ -4830,42 +4948,58 @@ int pc_isUseitem(struct map_session_data *sd,int n)
if(item->sex != 2 && sd->status.sex != item->sex)
return 0;
//Required level check
- if (item->elv && sd->status.base_level < (unsigned int)item->elv) {
+ if (item->elv && sd->status.base_level < item->elv) {
clif->msgtable(sd, MSG_ITEM_CANT_USE_LVL);
return 0;
}
- if (item->elvmax && sd->status.base_level > (unsigned int)item->elvmax) {
+ if (item->elvmax && sd->status.base_level > item->elvmax) {
clif->msgtable(sd, MSG_ITEM_CANT_USE_LVL);
return 0;
}
//Not equipable by class. [Skotlex]
- if (!(
- (1<<(sd->class_&MAPID_BASEMASK)) &
- (item->class_base[(sd->class_&JOBL_2_1) ? 1 : ((sd->class_&JOBL_2_2) ? 2 : 0)])
- ))
+ if (((1ULL << (sd->job & MAPID_BASEMASK)) & (item->class_base[(sd->job & JOBL_2_1) ? 1 : ((sd->job & JOBL_2_2) ? 2 : 0)])) == 0)
return 0;
//Not usable by upper class. [Haru]
while( 1 ) {
// Normal classes (no upper, no baby, no third classes)
- if( item->class_upper&ITEMUPPER_NORMAL && !(sd->class_&(JOBL_UPPER|JOBL_THIRD|JOBL_BABY)) ) break;
+ if ((item->class_upper & ITEMUPPER_NORMAL) != 0) {
+ if ((sd->job & (JOBL_UPPER|JOBL_THIRD|JOBL_BABY)) == 0)
+ break;
+ }
+ if ((item->class_upper & ITEMUPPER_UPPER) != 0) {
#ifdef RENEWAL
- // Upper classes (no third classes)
- if( item->class_upper&ITEMUPPER_UPPER && sd->class_&JOBL_UPPER && !(sd->class_&JOBL_THIRD) ) break;
+ // Upper classes (no third classes)
+ if ((sd->job & JOBL_UPPER) != 0 && (sd->job&JOBL_THIRD) == 0)
+ break;
#else
- //pre-re has no use for the extra, so we maintain the previous for backwards compatibility
- if( item->class_upper&ITEMUPPER_UPPER && sd->class_&(JOBL_UPPER|JOBL_THIRD) ) break;
+ //pre-re has no use for the extra, so we maintain the previous for backwards compatibility
+ if ((sd->job & (JOBL_UPPER|JOBL_THIRD)) != 0)
+ break;
#endif
+ }
// Baby classes (no third classes)
- if( item->class_upper&ITEMUPPER_BABY && sd->class_&JOBL_BABY && !(sd->class_&JOBL_THIRD) ) break;
+ if ((item->class_upper & ITEMUPPER_BABY) != 0) {
+ if ((sd->job & JOBL_BABY) != 0 && (sd->job&JOBL_THIRD) == 0)
+ break;
+ }
// Third classes (no upper, no baby classes)
- if( item->class_upper&ITEMUPPER_THIRD && sd->class_&JOBL_THIRD && !(sd->class_&(JOBL_UPPER|JOBL_BABY)) ) break;
+ if ((item->class_upper & ITEMUPPER_THIRD) != 0) {
+ if ((sd->job & JOBL_THIRD) != 0 && (sd->job & (JOBL_UPPER|JOBL_BABY)) == 0)
+ break;
+ }
// Upper third classes
- if( item->class_upper&ITEMUPPER_THURDUPPER && sd->class_&JOBL_THIRD && sd->class_&JOBL_UPPER ) break;
+ if ((item->class_upper & ITEMUPPER_THURDUPPER) != 0) {
+ if ((sd->job & JOBL_THIRD) != 0 && (sd->job & JOBL_UPPER) != 0)
+ break;
+ }
// Baby third classes
- if( item->class_upper&ITEMUPPER_THIRDBABY && sd->class_&JOBL_THIRD && sd->class_&JOBL_BABY ) break;
+ if ((item->class_upper & ITEMUPPER_THIRDBABY) != 0) {
+ if ((sd->job & JOBL_THIRD) != 0 && (sd->job & JOBL_BABY) != 0)
+ break;
+ }
return 0;
}
@@ -4884,11 +5018,13 @@ int pc_useitem(struct map_session_data *sd,int n) {
bool removeItem = false;
nullpo_ret(sd);
+ Assert_ret(n >= 0 && n < MAX_INVENTORY);
- if( sd->npc_id || sd->state.workinprogress&1 ){
- /* TODO: add to clif->messages enum */
-#ifdef RENEWAL
- clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); // TODO look for the client date that has this message.
+ if (sd->npc_id || sd->state.workinprogress & 1) {
+#if PACKETVER >= 20110309
+ clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS);
+#else
+ clif->messagecolor_self(sd->fd, COLOR_WHITE, msg_sd(sd, 48));
#endif
return 0;
}
@@ -4919,18 +5055,17 @@ int pc_useitem(struct map_session_data *sd,int n) {
sd->sc.data[SC_DEEP_SLEEP] ||
sd->sc.data[SC_SATURDAY_NIGHT_FEVER] ||
sd->sc.data[SC_COLD] ||
+ sd->sc.data[SC_SUHIDE] ||
pc_ismuted(&sd->sc, MANNER_NOITEM)
))
return 0;
- //Prevent mass item usage. [Skotlex]
- if( DIFF_TICK(sd->canuseitem_tick, tick) > 0 ||
- (itemdb_iscashfood(nameid) && DIFF_TICK(sd->canusecashfood_tick, tick) > 0)
- )
+ // Prevent mass item usage. [Skotlex]
+ if (DIFF_TICK(sd->canuseitem_tick, tick) > 0)
return 0;
/* Items with delayed consume are not meant to work while in mounts except reins of mount(12622) */
- if( sd->inventory_data[n]->flag.delay_consume && nameid != ITEMID_REINS_OF_MOUNT ) {
+ if (sd->inventory_data[n]->flag.delay_consume && nameid != ITEMID_BOARDING_HALTER) {
if( sd->sc.data[SC_ALL_RIDING] )
return 0;
else if( pc_issit(sd) )
@@ -4943,21 +5078,28 @@ int pc_useitem(struct map_session_data *sd,int n) {
if( sd->inventory_data[n]->flag.delay_consume && ( sd->ud.skilltimer != INVALID_TIMER /*|| !status->check_skilluse(&sd->bl, &sd->bl, ALL_RESURRECTION, 0)*/ ) )
return 0;
- if( sd->inventory_data[n]->delay > 0 ) {
- ARR_FIND(0, MAX_ITEMDELAYS, i, sd->item_delay[i].nameid == nameid );
- if( i == MAX_ITEMDELAYS ) /* item not found. try first empty now */
- ARR_FIND(0, MAX_ITEMDELAYS, i, !sd->item_delay[i].nameid );
- if( i < MAX_ITEMDELAYS ) {
- if( sd->item_delay[i].nameid ) {// found
- if( DIFF_TICK(sd->item_delay[i].tick, tick) > 0 ) {
- int e_tick = (int)(DIFF_TICK(sd->item_delay[i].tick, tick)/1000);
- clif->msgtable_num(sd, MSG_SECONDS_UNTIL_USE, e_tick + 1); // [%d] seconds left until you can use
+ if (sd->inventory_data[n]->delay > 0) {
+ ARR_FIND(0, MAX_ITEMDELAYS, i, sd->item_delay[i].nameid == nameid);
+ if (i == MAX_ITEMDELAYS) /* item not found. try first empty now */
+ ARR_FIND(0, MAX_ITEMDELAYS, i, sd->item_delay[i].nameid == 0);
+ if (i < MAX_ITEMDELAYS) {
+ if (sd->item_delay[i].nameid != 0) {// found
+ if (DIFF_TICK(sd->item_delay[i].tick, tick) > 0) {
+ int delay_tick = (int)(DIFF_TICK(sd->item_delay[i].tick, tick) / 1000);
+#if PACKETVER >= 20101123
+ clif->msgtable_num(sd, MSG_SECONDS_UNTIL_USE, delay_tick + 1); // [%d] seconds left until you can use
+#else
+ char delay_msg[100];
+ clif->msgtable_num(sd, MSG_SECONDS_UNTIL_USE, delay_tick + 1); // [%d] seconds left until you can use
+ sprintf(delay_msg, msg_sd(sd, 26), delay_tick + 1);
+ clif->messagecolor_self(sd->fd, COLOR_YELLOW, delay_msg);
+#endif
return 0; // Delay has not expired yet
}
} else {// not yet used item (all slots are initially empty)
sd->item_delay[i].nameid = nameid;
}
- if (!(nameid == ITEMID_REINS_OF_MOUNT && pc_hasmount(sd)))
+ if (!(nameid == ITEMID_BOARDING_HALTER && pc_hasmount(sd)))
sd->item_delay[i].tick = tick + sd->inventory_data[n]->delay;
} else {// should not happen
ShowError("pc_useitem: Exceeded item delay array capacity! (nameid=%d, char_id=%d)\n", nameid, sd->status.char_id);
@@ -5005,18 +5147,15 @@ int pc_useitem(struct map_session_data *sd,int n) {
}
}
- if(sd->status.inventory[n].card[0]==CARD0_CREATE &&
- pc->famerank(MakeDWord(sd->status.inventory[n].card[2],sd->status.inventory[n].card[3]), MAPID_ALCHEMIST))
- {
+ if (sd->status.inventory[n].card[0] == CARD0_CREATE
+ && pc->fame_rank(MakeDWord(sd->status.inventory[n].card[2], sd->status.inventory[n].card[3]), RANKTYPE_ALCHEMIST) > 0) {
script->potion_flag = 2; // Famous player's potions have 50% more efficiency
if (sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_ROGUE)
script->potion_flag = 3; //Even more effective potions.
}
- //Update item use time.
+ // Update item use time.
sd->canuseitem_tick = tick + battle_config.item_use_interval;
- if( itemdb_iscashfood(nameid) )
- sd->canusecashfood_tick = tick + battle_config.cashfood_use_interval;
script->run_use_script(sd, sd->inventory_data[n], npc->fake_nd->bl.id);
script->potion_flag = 0;
@@ -5051,7 +5190,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
if (!itemdb_cancartstore(item_data, pc_get_group_level(sd)) || (item_data->bound > IBT_ACCOUNT && !pc_can_give_bound_items(sd))) {
// Check item trade restrictions
- clif->message (sd->fd, msg_sd(sd,264));
+ clif->message (sd->fd, msg_sd(sd,264)); // This item cannot be stored.
return 1;/* TODO: there is no official response to this? */
}
@@ -5104,6 +5243,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
int pc_cart_delitem(struct map_session_data *sd,int n,int amount,int type,e_log_pick_type log_type) {
struct item_data * data;
nullpo_retr(1, sd);
+ Assert_retr(1, n >= 0 && n < MAX_INVENTORY);
if( sd->status.cart[n].nameid == 0 || sd->status.cart[n].amount < amount || !(data = itemdb->exists(sd->status.cart[n].nameid)) )
return 1;
@@ -5162,6 +5302,7 @@ int pc_cartitem_amount(struct map_session_data* sd, int idx, int amount)
struct item* item_data;
nullpo_retr(-1, sd);
+ Assert_retr(-1, idx >= 0 && idx < MAX_CART);
item_data = &sd->status.cart[idx];
if( item_data->nameid == 0 || item_data->amount == 0 )
@@ -5196,9 +5337,12 @@ int pc_getitemfromcart(struct map_session_data *sd,int idx,int amount)
return flag;
}
-void pc_bound_clear(struct map_session_data *sd, enum e_item_bound_type type) {
+
+void pc_bound_clear(struct map_session_data *sd, enum e_item_bound_type type)
+{
int i;
+ nullpo_retv(sd);
switch( type ) {
/* both restricted to inventory */
case IBT_PARTY:
@@ -5328,26 +5472,21 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skil
//Logs items, Stolen from mobs [Lupus]
logs->pick_mob(md, LOG_TYPE_STEAL, -1, &tmp_item, data);
- //A Rare Steal Global Announce by Lupus
- if(md->db->dropitem[i].p<=battle_config.rare_drop_announce) {
- char message[128];
- sprintf (message, msg_txt(542), sd->status.name, md->db->jname, data->jname, (float)md->db->dropitem[i].p / 100);
- //MSG: "'%s' stole %s's %s (chance: %0.02f%%)"
- intif->broadcast(message, strlen(message)+1, BC_DEFAULT);
- }
return 1;
}
/**
* Steals zeny from a monster through the RG_STEALCOIN skill.
*
- * @param sd Source character
- * @param target Target monster
+ * @param sd Source character
+ * @param target Target monster
+ * @param skill_lv Skill Level
*
* @return Amount of stolen zeny (0 in case of failure)
- **/
-int pc_steal_coin(struct map_session_data *sd, struct block_list *target) {
- int rate, skill_lv;
+ */
+int pc_steal_coin(struct map_session_data *sd, struct block_list *target, uint16 skill_lv)
+{
+ int rate;
struct mob_data *md = BL_CAST(BL_MOB, target);
if (sd == NULL || md == NULL)
@@ -5359,7 +5498,6 @@ int pc_steal_coin(struct map_session_data *sd, struct block_list *target) {
if (mob_is_treasure(md))
return 0;
- skill_lv = pc->checkskill(sd, RG_STEALCOIN);
rate = skill_lv * 10 + (sd->status.base_level - md->level) * 2 + sd->battle_status.dex / 2 + sd->battle_status.luk / 2;
if(rnd()%1000 < rate) {
int amount = md->level * skill_lv / 10 + md->level * 8 + rnd()%(md->level * 2 + 1); // mob_lv * skill_lv / 10 + random [mob_lv*8; mob_lv*10]
@@ -5526,6 +5664,8 @@ int pc_setpos(struct map_session_data* sd, unsigned short map_index, int x, int
npc->script_event(sd, NPCE_LOGOUT);
//remove from map, THEN change x/y coordinates
unit->remove_map_pc(sd,clrtype);
+ if (battle_config.player_warp_keep_direction == 0)
+ sd->ud.dir = 0; // makes character face north
sd->mapindex = map_index;
sd->bl.x=x;
sd->bl.y=y;
@@ -5556,6 +5696,9 @@ int pc_setpos(struct map_session_data* sd, unsigned short map_index, int x, int
vending->close(sd);
}
+ if (battle_config.player_warp_keep_direction == 0)
+ sd->ud.dir = 0; // makes character face north
+
if(sd->bl.prev != NULL){
unit->remove_map_pc(sd,clrtype);
clif->changemap(sd,m,x,y); // [MouseJstr]
@@ -5805,10 +5948,9 @@ int pc_checkequip(struct map_session_data *sd,int pos)
* Convert's from the client's lame Job ID system
* to the map server's 'makes sense' system. [Skotlex]
*------------------------------------------*/
-int pc_jobid2mapid(unsigned short b_class)
+int pc_jobid2mapid(int16 class)
{
- switch(b_class)
- {
+ switch (class) {
//Novice And 1-1 Jobs
case JOB_NOVICE: return MAPID_NOVICE;
case JOB_SWORDMAN: return MAPID_SWORDMAN;
@@ -5824,6 +5966,7 @@ int pc_jobid2mapid(unsigned short b_class)
case JOB_XMAS: return MAPID_XMAS;
case JOB_SUMMER: return MAPID_SUMMER;
case JOB_GANGSI: return MAPID_GANGSI;
+ case JOB_SUMMONER: return MAPID_SUMMONER;
//2-1 Jobs
case JOB_SUPER_NOVICE: return MAPID_SUPER_NOVICE;
case JOB_KNIGHT: return MAPID_KNIGHT;
@@ -5947,10 +6090,9 @@ int pc_jobid2mapid(unsigned short b_class)
}
//Reverts the map-style class id to the client-style one.
-int pc_mapid2jobid(unsigned short class_, int sex)
+int pc_mapid2jobid(uint16 job, int sex)
{
- switch(class_)
- {
+ switch (job) {
//Novice And 1-1 Jobs
case MAPID_NOVICE: return JOB_NOVICE;
case MAPID_SWORDMAN: return JOB_SWORDMAN;
@@ -5966,6 +6108,7 @@ int pc_mapid2jobid(unsigned short class_, int sex)
case MAPID_XMAS: return JOB_XMAS;
case MAPID_SUMMER: return JOB_SUMMER;
case MAPID_GANGSI: return JOB_GANGSI;
+ case MAPID_SUMMONER: return JOB_SUMMONER;
//2-1 Jobs
case MAPID_SUPER_NOVICE: return JOB_SUPER_NOVICE;
case MAPID_KNIGHT: return JOB_KNIGHT;
@@ -6084,9 +6227,9 @@ int pc_mapid2jobid(unsigned short class_, int sex)
/*====================================================
* This function return the name of the job (by [Yor])
*----------------------------------------------------*/
-const char* job_name(int class_)
+const char *job_name(int class)
{
- switch (class_) {
+ switch (class) {
case JOB_NOVICE: // 550
case JOB_SWORDMAN: // 551
case JOB_MAGE: // 552
@@ -6094,7 +6237,7 @@ const char* job_name(int class_)
case JOB_ACOLYTE: // 554
case JOB_MERCHANT: // 555
case JOB_THIEF: // 556
- return msg_txt(550 - JOB_NOVICE+class_);
+ return msg_txt(550 - JOB_NOVICE + class);
case JOB_KNIGHT: // 557
case JOB_PRIEST: // 558
@@ -6102,7 +6245,7 @@ const char* job_name(int class_)
case JOB_BLACKSMITH: // 560
case JOB_HUNTER: // 561
case JOB_ASSASSIN: // 562
- return msg_txt(557 - JOB_KNIGHT+class_);
+ return msg_txt(557 - JOB_KNIGHT + class);
case JOB_KNIGHT2:
return msg_txt(557);
@@ -6114,7 +6257,7 @@ const char* job_name(int class_)
case JOB_ALCHEMIST: // 567
case JOB_BARD: // 568
case JOB_DANCER: // 569
- return msg_txt(563 - JOB_CRUSADER+class_);
+ return msg_txt(563 - JOB_CRUSADER + class);
case JOB_CRUSADER2:
return msg_txt(563);
@@ -6124,7 +6267,7 @@ const char* job_name(int class_)
case JOB_GUNSLINGER: // 572
case JOB_NINJA: // 573
case JOB_XMAS: // 574
- return msg_txt(570 - JOB_WEDDING+class_);
+ return msg_txt(570 - JOB_WEDDING + class);
case JOB_SUMMER:
return msg_txt(621);
@@ -6136,7 +6279,7 @@ const char* job_name(int class_)
case JOB_ACOLYTE_HIGH: // 579
case JOB_MERCHANT_HIGH: // 580
case JOB_THIEF_HIGH: // 581
- return msg_txt(575 - JOB_NOVICE_HIGH+class_);
+ return msg_txt(575 - JOB_NOVICE_HIGH + class);
case JOB_LORD_KNIGHT: // 582
case JOB_HIGH_PRIEST: // 583
@@ -6144,7 +6287,7 @@ const char* job_name(int class_)
case JOB_WHITESMITH: // 585
case JOB_SNIPER: // 586
case JOB_ASSASSIN_CROSS: // 587
- return msg_txt(582 - JOB_LORD_KNIGHT+class_);
+ return msg_txt(582 - JOB_LORD_KNIGHT + class);
case JOB_LORD_KNIGHT2:
return msg_txt(582);
@@ -6156,7 +6299,7 @@ const char* job_name(int class_)
case JOB_CREATOR: // 592
case JOB_CLOWN: // 593
case JOB_GYPSY: // 594
- return msg_txt(588 - JOB_PALADIN + class_);
+ return msg_txt(588 - JOB_PALADIN + class);
case JOB_PALADIN2:
return msg_txt(588);
@@ -6168,7 +6311,7 @@ const char* job_name(int class_)
case JOB_BABY_ACOLYTE: // 599
case JOB_BABY_MERCHANT: // 600
case JOB_BABY_THIEF: // 601
- return msg_txt(595 - JOB_BABY + class_);
+ return msg_txt(595 - JOB_BABY + class);
case JOB_BABY_KNIGHT: // 602
case JOB_BABY_PRIEST: // 603
@@ -6176,7 +6319,7 @@ const char* job_name(int class_)
case JOB_BABY_BLACKSMITH: // 605
case JOB_BABY_HUNTER: // 606
case JOB_BABY_ASSASSIN: // 607
- return msg_txt(602 - JOB_BABY_KNIGHT + class_);
+ return msg_txt(602 - JOB_BABY_KNIGHT + class);
case JOB_BABY_KNIGHT2:
return msg_txt(602);
@@ -6188,7 +6331,7 @@ const char* job_name(int class_)
case JOB_BABY_ALCHEMIST: // 612
case JOB_BABY_BARD: // 613
case JOB_BABY_DANCER: // 614
- return msg_txt(608 - JOB_BABY_CRUSADER + class_);
+ return msg_txt(608 - JOB_BABY_CRUSADER + class);
case JOB_BABY_CRUSADER2:
return msg_txt(608);
@@ -6207,7 +6350,7 @@ const char* job_name(int class_)
case JOB_GANGSI: // 622
case JOB_DEATH_KNIGHT: // 623
case JOB_DARK_COLLECTOR: // 624
- return msg_txt(622 - JOB_GANGSI+class_);
+ return msg_txt(622 - JOB_GANGSI + class);
case JOB_RUNE_KNIGHT: // 625
case JOB_WARLOCK: // 626
@@ -6215,7 +6358,7 @@ const char* job_name(int class_)
case JOB_ARCH_BISHOP: // 628
case JOB_MECHANIC: // 629
case JOB_GUILLOTINE_CROSS: // 630
- return msg_txt(625 - JOB_RUNE_KNIGHT+class_);
+ return msg_txt(625 - JOB_RUNE_KNIGHT + class);
case JOB_RUNE_KNIGHT_T: // 656
case JOB_WARLOCK_T: // 657
@@ -6223,7 +6366,7 @@ const char* job_name(int class_)
case JOB_ARCH_BISHOP_T: // 659
case JOB_MECHANIC_T: // 660
case JOB_GUILLOTINE_CROSS_T: // 661
- return msg_txt(656 - JOB_RUNE_KNIGHT_T+class_);
+ return msg_txt(656 - JOB_RUNE_KNIGHT_T + class);
case JOB_ROYAL_GUARD: // 631
case JOB_SORCERER: // 632
@@ -6232,7 +6375,7 @@ const char* job_name(int class_)
case JOB_SURA: // 635
case JOB_GENETIC: // 636
case JOB_SHADOW_CHASER: // 637
- return msg_txt(631 - JOB_ROYAL_GUARD+class_);
+ return msg_txt(631 - JOB_ROYAL_GUARD + class);
case JOB_ROYAL_GUARD_T: // 662
case JOB_SORCERER_T: // 663
@@ -6241,7 +6384,7 @@ const char* job_name(int class_)
case JOB_SURA_T: // 666
case JOB_GENETIC_T: // 667
case JOB_SHADOW_CHASER_T: // 668
- return msg_txt(662 - JOB_ROYAL_GUARD_T+class_);
+ return msg_txt(662 - JOB_ROYAL_GUARD_T + class);
case JOB_RUNE_KNIGHT2:
return msg_txt(625);
@@ -6280,7 +6423,7 @@ const char* job_name(int class_)
case JOB_BABY_SURA: // 648
case JOB_BABY_GENETIC: // 649
case JOB_BABY_CHASER: // 650
- return msg_txt(638 - JOB_BABY_RUNE+class_);
+ return msg_txt(638 - JOB_BABY_RUNE + class);
case JOB_BABY_RUNE2:
return msg_txt(638);
@@ -6296,15 +6439,18 @@ const char* job_name(int class_)
case JOB_SUPER_NOVICE_E: // 651
case JOB_SUPER_BABY_E: // 652
- return msg_txt(651 - JOB_SUPER_NOVICE_E+class_);
+ return msg_txt(651 - JOB_SUPER_NOVICE_E + class);
case JOB_KAGEROU: // 653
case JOB_OBORO: // 654
- return msg_txt(653 - JOB_KAGEROU+class_);
+ return msg_txt(653 - JOB_KAGEROU + class);
case JOB_REBELLION:
return msg_txt(655);
+ case JOB_SUMMONER:
+ return msg_txt(669);
+
default:
return msg_txt(620); // "Unknown Job"
}
@@ -6430,8 +6576,10 @@ int pc_check_job_name(const char *name) {
{ "Kagerou", JOB_KAGEROU },
{ "Oboro", JOB_OBORO },
{ "Rebellion", JOB_REBELLION },
+ { "Summoner", JOB_SUMMONER },
};
+ nullpo_retr(-1, name);
len = ARRAYLENGTH(names);
ARR_FIND(0, len, i, strcmpi(names[i].name, name) == 0);
@@ -6498,6 +6646,7 @@ int pc_stop_following (struct map_session_data *sd)
int pc_follow(struct map_session_data *sd,int target_id) {
struct block_list *bl = map->id2bl(target_id);
+ nullpo_retr(1, sd);
if (bl == NULL /*|| bl->type != BL_PC*/)
return 1;
if (sd->followtimer != INVALID_TIMER)
@@ -6512,18 +6661,20 @@ int pc_follow(struct map_session_data *sd,int target_id) {
int pc_checkbaselevelup(struct map_session_data *sd) {
unsigned int next = pc->nextbaseexp(sd);
+ nullpo_ret(sd);
if (!next || sd->status.base_exp < next)
return 0;
do {
+ int status_points = 0;
sd->status.base_exp -= next;
//Kyoki pointed out that the max overcarry exp is the exp needed for the previous level -1. [Skotlex]
if(!battle_config.multi_level_up && sd->status.base_exp > next-1)
sd->status.base_exp = next-1;
- next = pc->gets_status_point(sd->status.base_level);
- sd->status.base_level ++;
- sd->status.status_point += next;
+ status_points = pc->gets_status_point(sd->status.base_level);
+ sd->status.base_level++;
+ sd->status.status_point += status_points;
} while ((next=pc->nextbaseexp(sd)) > 0 && sd->status.base_exp >= next);
@@ -6537,7 +6688,7 @@ int pc_checkbaselevelup(struct map_session_data *sd) {
status_calc_pc(sd,SCO_FORCE);
status_percent_heal(&sd->bl,100,100);
- if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE) {
+ if ((sd->job & MAPID_UPPERMASK) == MAPID_SUPER_NOVICE) {
sc_start(NULL,&sd->bl,status->skill2sc(PR_KYRIE),100,1,skill->get_time(PR_KYRIE,1));
sc_start(NULL,&sd->bl,status->skill2sc(PR_IMPOSITIO),100,1,skill->get_time(PR_IMPOSITIO,1));
sc_start(NULL,&sd->bl,status->skill2sc(PR_MAGNIFICAT),100,1,skill->get_time(PR_MAGNIFICAT,1));
@@ -6545,7 +6696,7 @@ int pc_checkbaselevelup(struct map_session_data *sd) {
sc_start(NULL,&sd->bl,status->skill2sc(PR_SUFFRAGIUM),100,1,skill->get_time(PR_SUFFRAGIUM,1));
if (sd->state.snovice_dead_flag)
sd->state.snovice_dead_flag = 0; //Reenable steelbody resurrection on dead.
- } else if( (sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON ) {
+ } else if ((sd->job & MAPID_BASEMASK) == MAPID_TAEKWON) {
sc_start(NULL,&sd->bl,status->skill2sc(AL_INCAGI),100,10,600000);
sc_start(NULL,&sd->bl,status->skill2sc(AL_BLESSING),100,10,600000);
}
@@ -6561,9 +6712,10 @@ int pc_checkbaselevelup(struct map_session_data *sd) {
void pc_baselevelchanged(struct map_session_data *sd) {
int i;
+ nullpo_retv(sd);
for( i = 0; i < EQI_MAX; i++ ) {
if( sd->equip_index[i] >= 0 ) {
- if( sd->inventory_data[ sd->equip_index[i] ]->elvmax && sd->status.base_level > (unsigned int)sd->inventory_data[ sd->equip_index[i] ]->elvmax )
+ if (sd->inventory_data[sd->equip_index[i]]->elvmax != 0 && sd->status.base_level > sd->inventory_data[ sd->equip_index[i] ]->elvmax)
pc->unequipitem(sd, sd->equip_index[i], PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE);
}
}
@@ -6583,8 +6735,8 @@ int pc_checkjoblevelup(struct map_session_data *sd)
if(!battle_config.multi_level_up && sd->status.job_exp > next-1)
sd->status.job_exp = next-1;
- sd->status.job_level ++;
- sd->status.skill_point ++;
+ sd->status.job_level++;
+ sd->status.skill_point++;
} while ((next=pc->nextjobexp(sd)) > 0 && sd->status.job_exp >= next);
@@ -6605,34 +6757,72 @@ int pc_checkjoblevelup(struct map_session_data *sd)
* Alters EXP based on self bonuses that do not get shared with the party
**/
void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned int *job_exp, struct block_list *src) {
- int bonus = 0;
- struct status_data *st = status->get_status_data(src);
+ int buff_ratio = 0, buff_job_ratio = 0, race_ratio = 0, pk_ratio = 0;
+ int64 jexp, bexp;
- if (sd->expaddrace[st->race])
- bonus += sd->expaddrace[st->race];
- bonus += sd->expaddrace[(st->mode&MD_BOSS) ? RC_BOSS : RC_NONBOSS];
+ nullpo_retv(sd);
+ nullpo_retv(base_exp);
+ nullpo_retv(job_exp);
+
+ jexp = *job_exp;
+ bexp = *base_exp;
+
+ if (src != NULL) {
+ const struct status_data *st = status->get_status_data(src);
+
+#ifdef RENEWAL_EXP //should happen first before we caluclate any modifiers
+ if (src->type == BL_MOB) {
+ const struct mob_data *md = BL_UCAST(BL_MOB, src);
+ int re_mod;
+ re_mod = pc->level_penalty_mod(md->level - sd->status.base_level, md->status.race, md->status.mode, 1);
+ jexp = apply_percentrate64(jexp, re_mod, 100);
+ bexp = apply_percentrate64(bexp, re_mod, 100);
+ }
+#endif
- if (battle_config.pk_mode
- && (int)(status->get_lv(src) - sd->status.base_level) >= 20)
- bonus += 15; // pk_mode additional exp if monster >20 levels [Valaris]
+ //Race modifier
+ if (sd->expaddrace[st->race])
+ race_ratio += sd->expaddrace[st->race];
+ race_ratio += sd->expaddrace[(st->mode&MD_BOSS) ? RC_BOSS : RC_NONBOSS];
+ }
- if (sd->sc.data[SC_CASH_PLUSEXP])
- bonus += sd->sc.data[SC_CASH_PLUSEXP]->val1;
- if (sd->sc.data[SC_OVERLAPEXPUP])
- bonus += sd->sc.data[SC_OVERLAPEXPUP]->val1;
- *base_exp = (unsigned int) cap_value(*base_exp + apply_percentrate64(*base_exp, bonus, 100), 1, UINT_MAX);
+ //PK modifier
+ /* this doesn't exist in Aegis, instead there's a CrazyKiller check which double all EXP from this point */
+ if (battle_config.pk_mode && status->get_lv(src) - sd->status.base_level >= 20)
+ pk_ratio += 15; // pk_mode additional exp if monster >20 levels [Valaris]
+
+ //Buffs modifier
+ if (sd->sc.data[SC_CASH_PLUSEXP]) {
+ buff_job_ratio += sd->sc.data[SC_CASH_PLUSEXP]->val1;
+ buff_ratio += sd->sc.data[SC_CASH_PLUSEXP]->val1;
+ }
+ if (sd->sc.data[SC_OVERLAPEXPUP]) {
+ buff_job_ratio += sd->sc.data[SC_OVERLAPEXPUP]->val1;
+ buff_ratio += sd->sc.data[SC_OVERLAPEXPUP]->val1;
+ }
if (sd->sc.data[SC_CASH_PLUSONLYJOBEXP])
- bonus += sd->sc.data[SC_CASH_PLUSONLYJOBEXP]->val1;
+ buff_job_ratio += sd->sc.data[SC_CASH_PLUSONLYJOBEXP]->val1;
- *job_exp = (unsigned int) cap_value(*job_exp + apply_percentrate64(*job_exp, bonus, 100), 1, UINT_MAX);
+ //Applying Race and PK modifier First then Premium (Perment modifier) and finally buff modifier
+ jexp += apply_percentrate64(jexp, race_ratio, 100);
+ jexp += apply_percentrate64(jexp, pk_ratio, 100);
+
+ bexp += apply_percentrate64(bexp, race_ratio, 100);
+ bexp += apply_percentrate64(bexp, pk_ratio, 100);
- if (sd->status.mod_exp != 100) {
- *base_exp = (unsigned int) cap_value(apply_percentrate64(*base_exp, sd->status.mod_exp, 100), 1, UINT_MAX);
- *job_exp = (unsigned int) cap_value(apply_percentrate64(*job_exp, sd->status.mod_exp, 100), 1, UINT_MAX);
+ if (sd->status.mod_exp != 100) {
+ jexp = apply_percentrate64(jexp, sd->status.mod_exp, 100);
+ bexp = apply_percentrate64(bexp, sd->status.mod_exp, 100);
}
+
+ bexp += apply_percentrate64(bexp, buff_ratio, 100);
+ jexp += apply_percentrate64(jexp, buff_ratio + buff_job_ratio, 100);
+
+ *job_exp = (unsigned int)cap_value(jexp, 1, UINT_MAX);
+ *base_exp = (unsigned int)cap_value(bexp, 1, UINT_MAX);
}
/**
@@ -6646,24 +6836,25 @@ bool pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned in
unsigned int nextb=0, nextj=0;
nullpo_ret(sd);
- if(sd->bl.prev == NULL || pc_isdead(sd))
+ if (sd->bl.prev == NULL || pc_isdead(sd))
return false;
- if(!battle_config.pvp_exp && map->list[sd->bl.m].flag.pvp) // [MouseJstr]
+ if (!battle_config.pvp_exp && map->list[sd->bl.m].flag.pvp) // [MouseJstr]
return false; // no exp on pvp maps
- if( pc_has_permission(sd,PC_PERM_DISABLE_EXP) )
+ if (pc_has_permission(sd,PC_PERM_DISABLE_EXP))
return false;
- if(sd->status.guild_id>0)
- base_exp-=guild->payexp(sd,base_exp);
+ if (src)
+ pc->calcexp(sd, &base_exp, &job_exp, src);
- if(src) pc->calcexp(sd, &base_exp, &job_exp, src);
+ if (sd->status.guild_id > 0)
+ base_exp -= guild->payexp(sd,base_exp);
nextb = pc->nextbaseexp(sd);
nextj = pc->nextjobexp(sd);
- if(sd->state.showexp || battle_config.max_exp_gain_rate){
+ if (sd->state.showexp || battle_config.max_exp_gain_rate) {
if (nextb > 0)
nextbp = (float) base_exp / (float) nextb;
if (nextj > 0)
@@ -6718,7 +6909,7 @@ bool pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned in
char output[256];
sprintf(output,
"Experience Gained Base:%u (%.2f%%) Job:%u (%.2f%%)",base_exp,nextbp*(float)100,job_exp,nextjp*(float)100);
- clif_disp_onlyself(sd,output,strlen(output));
+ clif_disp_onlyself(sd, output);
}
return true;
@@ -6727,14 +6918,14 @@ bool pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned in
/*==========================================
* Returns max level for this character.
*------------------------------------------*/
-unsigned int pc_maxbaselv(struct map_session_data *sd)
+int pc_maxbaselv(const struct map_session_data *sd)
{
- return pc->max_level[pc->class2idx(sd->status.class_)][0];
+ return pc->max_level[pc->class2idx(sd->status.class)][0];
}
-unsigned int pc_maxjoblv(struct map_session_data *sd)
+int pc_maxjoblv(const struct map_session_data *sd)
{
- return pc->max_level[pc->class2idx(sd->status.class_)][1];
+ return pc->max_level[pc->class2idx(sd->status.class)][1];
}
/*==========================================
@@ -6742,23 +6933,23 @@ unsigned int pc_maxjoblv(struct map_session_data *sd)
*------------------------------------------*/
//Base exp needed for next level.
-unsigned int pc_nextbaseexp(struct map_session_data *sd)
+unsigned int pc_nextbaseexp(const struct map_session_data *sd)
{
nullpo_ret(sd);
- if(sd->status.base_level>=pc->maxbaselv(sd) || sd->status.base_level<=0)
+ if (sd->status.base_level >= pc->maxbaselv(sd) || sd->status.base_level <= 0)
return 0;
- return pc->exp_table[pc->class2idx(sd->status.class_)][0][sd->status.base_level-1];
+ return pc->exp_table[pc->class2idx(sd->status.class)][0][sd->status.base_level-1];
}
//Base exp needed for this level.
-unsigned int pc_thisbaseexp(struct map_session_data *sd)
+unsigned int pc_thisbaseexp(const struct map_session_data *sd)
{
- if(sd->status.base_level>pc->maxbaselv(sd) || sd->status.base_level<=1)
+ if (sd->status.base_level > pc->maxbaselv(sd) || sd->status.base_level <= 1)
return 0;
- return pc->exp_table[pc->class2idx(sd->status.class_)][0][sd->status.base_level-2];
+ return pc->exp_table[pc->class2idx(sd->status.class)][0][sd->status.base_level-2];
}
/*==========================================
@@ -6769,21 +6960,21 @@ unsigned int pc_thisbaseexp(struct map_session_data *sd)
*------------------------------------------*/
//Job exp needed for next level.
-unsigned int pc_nextjobexp(struct map_session_data *sd)
+unsigned int pc_nextjobexp(const struct map_session_data *sd)
{
nullpo_ret(sd);
- if(sd->status.job_level>=pc->maxjoblv(sd) || sd->status.job_level<=0)
+ if (sd->status.job_level >= pc->maxjoblv(sd) || sd->status.job_level <= 0)
return 0;
- return pc->exp_table[pc->class2idx(sd->status.class_)][1][sd->status.job_level-1];
+ return pc->exp_table[pc->class2idx(sd->status.class)][1][sd->status.job_level-1];
}
//Job exp needed for this level.
-unsigned int pc_thisjobexp(struct map_session_data *sd)
+unsigned int pc_thisjobexp(const struct map_session_data *sd)
{
- if(sd->status.job_level>pc->maxjoblv(sd) || sd->status.job_level<=1)
+ if (sd->status.job_level > pc->maxjoblv(sd) || sd->status.job_level <= 1)
return 0;
- return pc->exp_table[pc->class2idx(sd->status.class_)][1][sd->status.job_level-2];
+ return pc->exp_table[pc->class2idx(sd->status.class)][1][sd->status.job_level-2];
}
/// Returns the value of the specified stat.
@@ -7014,13 +7205,14 @@ int pc_skillup(struct map_session_data *sd,uint16 skill_id) {
if( sd->status.skill_point > 0 &&
sd->status.skill[index].id &&
sd->status.skill[index].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex]
- sd->status.skill[index].lv < skill->tree_get_max(skill_id, sd->status.class_) )
+ sd->status.skill[index].lv < skill->tree_get_max(skill_id, sd->status.class) )
{
sd->status.skill[index].lv++;
sd->status.skill_point--;
if( !skill->dbs->db[index].inf )
status_calc_pc(sd,SCO_NONE); // Only recalculate for passive skills.
- else if( sd->status.skill_point == 0 && (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) )
+ else if (sd->status.skill_point == 0 && (sd->job & MAPID_UPPERMASK) == MAPID_TAEKWON
+ && sd->status.base_level >= 90 && pc->fame_rank(sd->status.char_id, RANKTYPE_TAEKWON) > 0)
pc->calc_skilltree(sd); // Required to grant all TK Ranger skills.
else
pc->check_skilltree(sd, skill_id); // Check if a new skill can Lvlup
@@ -7032,9 +7224,9 @@ int pc_skillup(struct map_session_data *sd,uint16 skill_id) {
if (!pc_has_permission(sd, PC_PERM_ALL_SKILL)) // may skill everything at any time anyways, and this would cause a huge slowdown
clif->skillinfoblock(sd);
} else if( battle_config.skillup_limit ){
- if (sd->sktree.second)
+ if (sd->sktree.second != 0)
clif->msgtable_num(sd, MSG_SKILL_POINTS_LEFT_JOB1, sd->sktree.second);
- else if (sd->sktree.third)
+ else if (sd->sktree.third != 0)
clif->msgtable_num(sd, MSG_SKILL_POINTS_LEFT_JOB2, sd->sktree.third);
else if (pc->calc_skillpoint(sd) < 9) /* TODO: official response? */
clif->messagecolor_self(sd->fd, COLOR_RED, "You need the basic skills");
@@ -7076,8 +7268,8 @@ int pc_allskillup(struct map_session_data *sd)
}
} else {
int id;
- for (i = 0; i < MAX_SKILL_TREE && (id=pc->skill_tree[pc->class2idx(sd->status.class_)][i].id) > 0; i++) {
- int idx = pc->skill_tree[pc->class2idx(sd->status.class_)][i].idx;
+ for (i = 0; i < MAX_SKILL_TREE && (id=pc->skill_tree[pc->class2idx(sd->status.class)][i].id) > 0; i++) {
+ int idx = pc->skill_tree[pc->class2idx(sd->status.class)][i].idx;
int inf2 = skill->dbs->db[idx].inf2;
if (
(inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) ||
@@ -7087,7 +7279,7 @@ int pc_allskillup(struct map_session_data *sd)
continue; //Cannot be learned normally.
sd->status.skill[idx].id = id;
- sd->status.skill[idx].lv = skill->tree_get_max(id, sd->status.class_); // celest
+ sd->status.skill[idx].lv = skill->tree_get_max(id, sd->status.class); // celest
}
}
status_calc_pc(sd,SCO_NONE);
@@ -7124,7 +7316,7 @@ int pc_resetlvl(struct map_session_data* sd,int type)
sd->status.int_=1;
sd->status.dex=1;
sd->status.luk=1;
- if(sd->status.class_ == JOB_NOVICE_HIGH) {
+ if (sd->status.class == JOB_NOVICE_HIGH) {
sd->status.status_point=100; // not 88 [celest]
// give platinum skills upon changing
pc->skill(sd, NV_FIRSTAID, 1, SKILL_GRANT_PERMANENT);
@@ -7201,7 +7393,7 @@ int pc_resetstate(struct map_session_data* sd)
return 0;
}
- sd->status.status_point = pc->statp[sd->status.base_level] + ((sd->class_&JOBL_UPPER) ? 52 : 0); // extra 52+48=100 stat points
+ sd->status.status_point = pc->statp[sd->status.base_level] + ((sd->job & JOBL_UPPER) != 0 ? 52 : 0); // extra 52+48=100 stat points
}
else
{
@@ -7259,7 +7451,7 @@ int pc_resetskill(struct map_session_data* sd, int flag)
int i, inf2, skill_point=0;
nullpo_ret(sd);
- if( flag&PCRESETSKILL_CHSEX && (sd->class_&MAPID_UPPERMASK) != MAPID_BARDDANCER )
+ if (flag&PCRESETSKILL_CHSEX && (sd->job & MAPID_UPPERMASK) != MAPID_BARDDANCER)
return 0;
if( !(flag&PCRESETSKILL_RECOUNT) ) { //Remove stuff lost when resetting skills.
@@ -7267,7 +7459,7 @@ int pc_resetskill(struct map_session_data* sd, int flag)
/**
* It has been confirmed on official server that when you reset skills with a ranked tweakwon your skills are not reset (because you have all of them anyway)
**/
- if( (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) )
+ if ((sd->job & MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->fame_rank(sd->status.char_id, RANKTYPE_TAEKWON))
return 0;
if( pc->checkskill(sd, SG_DEVIL) && !pc->nextjobexp(sd) ) //Remove perma blindness due to skill-reset. [Skotlex]
@@ -7283,7 +7475,7 @@ int pc_resetskill(struct map_session_data* sd, int flag)
i &= ~OPTION_WUG;
if( i&OPTION_WUGRIDER && pc->checkskill(sd, RA_WUGRIDER) )
i &= ~OPTION_WUGRIDER;
- if( i&OPTION_MADOGEAR && ( sd->class_&MAPID_THIRDMASK ) == MAPID_MECHANIC )
+ if (i&OPTION_MADOGEAR && (sd->job & MAPID_THIRDMASK) == MAPID_MECHANIC)
i &= ~OPTION_MADOGEAR;
#ifndef NEW_CARTS
if( i&OPTION_CART && pc->checkskill(sd, MC_PUSHCART) )
@@ -7297,6 +7489,9 @@ int pc_resetskill(struct map_session_data* sd, int flag)
if( homun_alive(sd->hd) && pc->checkskill(sd, AM_CALLHOMUN) )
homun->vaporize(sd, HOM_ST_REST);
+
+ if ((sd->sc.data[SC_SPRITEMABLE] && pc->checkskill(sd, SU_SPRITEMABLE)))
+ status_change_end(&sd->bl, SC_SPRITEMABLE, INVALID_TIMER);
}
for( i = 1; i < MAX_SKILL; i++ ) {
@@ -7314,14 +7509,16 @@ int pc_resetskill(struct map_session_data* sd, int flag)
skill_id = skill->dbs->db[i].nameid;
// Don't reset trick dead if not a novice/baby
- if( skill_id == NV_TRICKDEAD && (sd->class_&(MAPID_BASEMASK|JOBL_2)) != MAPID_NOVICE ) {
+ if (skill_id == NV_TRICKDEAD && (sd->job & MAPID_UPPERMASK) != MAPID_NOVICE) {
sd->status.skill[i].lv = 0;
sd->status.skill[i].flag = 0;
continue;
}
// do not reset basic skill
- if( skill_id == NV_BASIC && (sd->class_&(MAPID_BASEMASK|JOBL_2)) != MAPID_NOVICE )
+ if (skill_id == NV_BASIC && (sd->job & MAPID_UPPERMASK) != MAPID_NOVICE)
+ continue;
+ if (skill_id == SU_BASIC_SKILL && (sd->job & MAPID_BASEMASK) != MAPID_SUMMONER)
continue;
if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED )
@@ -7420,22 +7617,42 @@ int pc_skillatk_bonus(struct map_session_data *sd, uint16 skill_id)
return bonus;
}
-int pc_skillheal_bonus(struct map_session_data *sd, uint16 skill_id) {
+int pc_skillheal_bonus(struct map_session_data *sd, uint16 skill_id)
+{
int i, bonus = sd->bonus.add_heal_rate;
- if( bonus ) {
- switch( skill_id ) {
- case AL_HEAL: if( !(battle_config.skill_add_heal_rate&1) ) bonus = 0; break;
- case PR_SANCTUARY: if( !(battle_config.skill_add_heal_rate&2) ) bonus = 0; break;
- case AM_POTIONPITCHER: if( !(battle_config.skill_add_heal_rate&4) ) bonus = 0; break;
- case CR_SLIMPITCHER: if( !(battle_config.skill_add_heal_rate&8) ) bonus = 0; break;
- case BA_APPLEIDUN: if( !(battle_config.skill_add_heal_rate&16)) bonus = 0; break;
+ if (bonus) {
+ switch (skill_id) {
+ case AL_HEAL:
+ if ((battle_config.skill_add_heal_rate & 1) == 0)
+ bonus = 0;
+ break;
+ case PR_SANCTUARY:
+ if ((battle_config.skill_add_heal_rate & 2) == 0)
+ bonus = 0;
+ break;
+ case AM_POTIONPITCHER:
+ if ((battle_config.skill_add_heal_rate & 4) == 0)
+ bonus = 0;
+ break;
+ case CR_SLIMPITCHER:
+ if ((battle_config.skill_add_heal_rate & 8) == 0)
+ bonus = 0;
+ break;
+ case BA_APPLEIDUN:
+ if ((battle_config.skill_add_heal_rate & 16) == 0)
+ bonus = 0;
+ break;
+ case AB_HIGHNESSHEAL:
+ if ((battle_config.skill_add_heal_rate & 32) == 0)
+ bonus = 0;
+ break;
}
}
ARR_FIND(0, ARRAYLENGTH(sd->skillheal), i, sd->skillheal[i].id == skill_id);
- if( i < ARRAYLENGTH(sd->skillheal) )
+ if (i < ARRAYLENGTH(sd->skillheal))
bonus += sd->skillheal[i].val;
return bonus;
@@ -7504,7 +7721,8 @@ void pc_damage(struct map_session_data *sd,struct block_list *src,unsigned int h
if( sd->status.ele_id > 0 )
elemental->set_target(sd,src);
- sd->canlog_tick = timer->gettick();
+ if (battle_config.prevent_logout_trigger & PLT_DAMAGE)
+ sd->canlog_tick = timer->gettick();
}
/*==========================================
@@ -7620,7 +7838,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
if (md->target_id==sd->bl.id)
mob->unlocktarget(md,tick);
if (battle_config.mobs_level_up && md->status.hp
- && (unsigned int)md->level < pc->maxbaselv(sd)
+ && md->level < pc->maxbaselv(sd)
&& !md->guardian_data && md->special_state.ai == AI_NONE// Guardians/summons should not level. [Skotlex]
) {
// monster level up [Valaris]
@@ -7699,7 +7917,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
}
// activate Steel body if a super novice dies at 99+% exp [celest]
- if ((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && !sd->state.snovice_dead_flag) {
+ if ((sd->job & MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && !sd->state.snovice_dead_flag) {
unsigned int next = pc->nextbaseexp(sd);
if( next == 0 ) next = pc->thisbaseexp(sd);
if( get_percentage(sd->status.base_exp,next) >= 99 ) {
@@ -7718,7 +7936,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
// changed penalty options, added death by player if pk_mode [Valaris]
if( battle_config.death_penalty_type
- && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE // only novices will receive no penalty
+ && (sd->job & MAPID_UPPERMASK) != MAPID_NOVICE // only novices will receive no penalty
&& !map->list[sd->bl.m].flag.noexppenalty && !map_flag_gvg2(sd->bl.m)
&& !sd->sc.data[SC_BABY] && !sd->sc.data[SC_CASH_DEATHPENALTY]
) {
@@ -7867,6 +8085,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
}
void pc_revive(struct map_session_data *sd,unsigned int hp, unsigned int sp) {
+ nullpo_retv(sd);
if(hp) clif->updatestatus(sd,SP_HP);
if(sp) clif->updatestatus(sd,SP_SP);
@@ -7886,7 +8105,7 @@ void pc_revive(struct map_session_data *sd,unsigned int hp, unsigned int sp) {
/*==========================================
* script reading pc status registry
*------------------------------------------*/
-int pc_readparam(struct map_session_data* sd,int type)
+int pc_readparam(const struct map_session_data *sd, int type)
{
int val = 0;
@@ -7896,12 +8115,13 @@ int pc_readparam(struct map_session_data* sd,int type)
case SP_SKILLPOINT: val = sd->status.skill_point; break;
case SP_STATUSPOINT: val = sd->status.status_point; break;
case SP_ZENY: val = sd->status.zeny; break;
+ case SP_BANKVAULT: val = sd->status.bank_vault; break;
case SP_BASELEVEL: val = sd->status.base_level; break;
case SP_JOBLEVEL: val = sd->status.job_level; break;
- case SP_CLASS: val = sd->status.class_; break;
- case SP_BASEJOB: val = pc->mapid2jobid(sd->class_&MAPID_UPPERMASK, sd->status.sex); break; //Base job, extracting upper type.
- case SP_UPPER: val = (sd->class_&JOBL_UPPER) ? 1 : ((sd->class_&JOBL_BABY) ? 2 : 0); break;
- case SP_BASECLASS: val = pc->mapid2jobid(sd->class_&MAPID_BASEMASK, sd->status.sex); break; //Extract base class tree. [Skotlex]
+ case SP_CLASS: val = sd->status.class; break;
+ case SP_BASEJOB: val = pc->mapid2jobid(sd->job & MAPID_UPPERMASK, sd->status.sex); break; //Base job, extracting upper type.
+ case SP_UPPER: val = (sd->job & JOBL_UPPER) != 0 ? 1 : ((sd->job & JOBL_BABY) != 0 ? 2 : 0); break;
+ case SP_BASECLASS: val = pc->mapid2jobid(sd->job & MAPID_BASEMASK, sd->status.sex); break; //Extract base class tree. [Skotlex]
case SP_SEX: val = sd->status.sex; break;
case SP_WEIGHT: val = sd->weight; break;
case SP_MAXWEIGHT: val = sd->max_weight; break;
@@ -7944,7 +8164,7 @@ int pc_readparam(struct map_session_data* sd,int type)
case SP_VARCASTRATE:
#endif
case SP_CASTRATE:
- val = sd->castrate+=val;
+ val = sd->castrate;
break;
case SP_MAXHPRATE: val = sd->hprate; break;
case SP_MAXSPRATE: val = sd->sprate; break;
@@ -8040,19 +8260,20 @@ int pc_readparam(struct map_session_data* sd,int type)
*------------------------------------------*/
int pc_setparam(struct map_session_data *sd,int type,int val)
{
+ int delta;
nullpo_ret(sd);
switch(type){
case SP_BASELEVEL:
- if ((unsigned int)val > pc->maxbaselv(sd)) //Capping to max
+ if (val > pc->maxbaselv(sd)) //Capping to max
val = pc->maxbaselv(sd);
- if ((unsigned int)val > sd->status.base_level) {
+ if (val > sd->status.base_level) {
int stat = 0, i;
- for (i = 0; i < (int)((unsigned int)val - sd->status.base_level); i++)
+ for (i = 0; i < val - sd->status.base_level; i++)
stat += pc->gets_status_point(sd->status.base_level + i);
sd->status.status_point += stat;
}
- sd->status.base_level = (unsigned int)val;
+ sd->status.base_level = val;
sd->status.base_exp = 0;
// clif->updatestatus(sd, SP_BASELEVEL); // Gets updated at the bottom
clif->updatestatus(sd, SP_NEXTBASEEXP);
@@ -8065,12 +8286,13 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
}
break;
case SP_JOBLEVEL:
- if ((unsigned int)val >= sd->status.job_level) {
- if ((unsigned int)val > pc->maxjoblv(sd)) val = pc->maxjoblv(sd);
+ if (val >= sd->status.job_level) {
+ if (val > pc->maxjoblv(sd))
+ val = pc->maxjoblv(sd);
sd->status.skill_point += val - sd->status.job_level;
clif->updatestatus(sd, SP_SKILLPOINT);
}
- sd->status.job_level = (unsigned int)val;
+ sd->status.job_level = val;
sd->status.job_exp = 0;
// clif->updatestatus(sd, SP_JOBLEVEL); // Gets updated at the bottom
clif->updatestatus(sd, SP_NEXTJOBEXP);
@@ -8089,6 +8311,19 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
logs->zeny(sd, LOG_TYPE_SCRIPT, sd, -(sd->status.zeny - cap_value(val, 0, MAX_ZENY)));
sd->status.zeny = cap_value(val, 0, MAX_ZENY);
break;
+ case SP_BANKVAULT:
+ val = cap_value(val, 0, MAX_BANK_ZENY);
+ delta = (val - sd->status.bank_vault);
+ sd->status.bank_vault = val;
+ if (map->save_settings & 256) {
+ chrif->save(sd, 0); // send to char server
+ }
+ if (delta > 0) {
+ clif->bank_deposit(sd, BDA_SUCCESS);
+ } else if (delta < 0) {
+ clif->bank_withdraw(sd, BWA_SUCCESS);
+ }
+ return 1; // the vault uses a different packet
case SP_BASEEXP:
if(pc->nextbaseexp(sd) > 0) {
sd->status.base_exp = val;
@@ -8202,6 +8437,7 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
*------------------------------------------*/
void pc_heal(struct map_session_data *sd,unsigned int hp,unsigned int sp, int type)
{
+ nullpo_retv(sd);
if (type) {
if (hp)
clif->heal(sd->fd,SP_HP,hp);
@@ -8225,6 +8461,7 @@ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp)
{
int bonus, tmp;
+ nullpo_ret(sd);
if(hp) {
int i;
bonus = 100 + (sd->battle_status.vit<<1)
@@ -8291,6 +8528,9 @@ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp)
if( sd->sc.data[SC_EXTREMITYFIST2] )
sp = 0;
#endif
+ if (sd->sc.data[SC_BITESCAR]) {
+ hp = 0;
+ }
}
return status->heal(&sd->bl, hp, sp, 1);
@@ -8353,46 +8593,45 @@ int jobchange_killclone(struct block_list *bl, va_list ap)
* Called when player changes job
* Rewrote to make it tidider [Celest]
*------------------------------------------*/
-int pc_jobchange(struct map_session_data *sd,int job, int upper)
+int pc_jobchange(struct map_session_data *sd, int class, int upper)
{
int i, fame_flag=0;
- int b_class, idx = 0;
+ int job, idx = 0;
nullpo_ret(sd);
- if (job < 0)
+ if (class < 0)
return 1;
//Normalize job.
- b_class = pc->jobid2mapid(job);
- if (b_class == -1)
+ job = pc->jobid2mapid(class);
+ if (job == -1)
return 1;
switch (upper) {
case 1:
- b_class|= JOBL_UPPER;
+ job |= JOBL_UPPER;
break;
case 2:
- b_class|= JOBL_BABY;
+ job |= JOBL_BABY;
break;
}
//This will automatically adjust bard/dancer classes to the correct gender
//That is, if you try to jobchange into dancer, it will turn you to bard.
- job = pc->mapid2jobid(b_class, sd->status.sex);
- if (job == -1)
+ class = pc->mapid2jobid(job, sd->status.sex);
+ if (class == -1)
return 1;
- if ((unsigned short)b_class == sd->class_)
+ if ((uint16)job == sd->job)
return 1; //Nothing to change.
- // changing from 1st to 2nd job
- if ((b_class&JOBL_2) && !(sd->class_&JOBL_2) && (b_class&MAPID_UPPERMASK) != MAPID_SUPER_NOVICE) {
+ if ((job & JOBL_2) != 0 && (sd->job & JOBL_2) == 0 && (job & MAPID_UPPERMASK) != MAPID_SUPER_NOVICE) {
+ // changing from 1st to 2nd job
sd->change_level_2nd = sd->status.job_level;
- pc_setglobalreg (sd, script->add_str("jobchange_level"), sd->change_level_2nd);
- }
- // changing from 2nd to 3rd job
- else if((b_class&JOBL_THIRD) && !(sd->class_&JOBL_THIRD)) {
+ pc_setglobalreg(sd, script->add_str("jobchange_level"), sd->change_level_2nd);
+ } else if((job & JOBL_THIRD) != 0 && (sd->job & JOBL_THIRD) == 0) {
+ // changing from 2nd to 3rd job
sd->change_level_3rd = sd->status.job_level;
- pc_setglobalreg (sd, script->add_str("jobchange_level_3rd"), sd->change_level_3rd);
+ pc_setglobalreg(sd, script->add_str("jobchange_level_3rd"), sd->change_level_3rd);
}
if(sd->cloneskill_id) {
@@ -8421,10 +8660,10 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
pc_setglobalreg(sd, script->add_str("REPRODUCE_SKILL_LV"),0);
}
- if ( (b_class&MAPID_UPPERMASK) != (sd->class_&MAPID_UPPERMASK) ) { //Things to remove when changing class tree.
- const int class_ = pc->class2idx(sd->status.class_);
+ if ((job & MAPID_UPPERMASK) != (sd->job & MAPID_UPPERMASK)) { //Things to remove when changing class tree.
+ const int class_idx = pc->class2idx(sd->status.class);
short id;
- for(i = 0; i < MAX_SKILL_TREE && (id = pc->skill_tree[class_][i].id) > 0; i++) {
+ for (i = 0; i < MAX_SKILL_TREE && (id = pc->skill_tree[class_idx][i].id) > 0; i++) {
//Remove status specific to your current tree skills.
enum sc_type sc = status->skill2sc(id);
if (sc > SC_COMMON_MAX && sd->sc.data[sc])
@@ -8432,14 +8671,18 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
}
}
- if( (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR && (b_class&MAPID_UPPERMASK) != MAPID_STAR_GLADIATOR) {
+ if ((sd->job & MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR && (job & MAPID_UPPERMASK) != MAPID_STAR_GLADIATOR) {
/* going off star glad lineage, reset feel to not store no-longer-used vars in the database */
pc->resetfeel(sd);
}
- sd->status.class_ = job;
- fame_flag = pc->famerank(sd->status.char_id,sd->class_&MAPID_UPPERMASK);
- sd->class_ = (unsigned short)b_class;
+ sd->status.class = class;
+ {
+ int fame_list_type = pc->famelist_type(sd->job);
+ if (fame_list_type != RANKTYPE_UNKNOWN)
+ fame_flag = pc->fame_rank(sd->status.char_id, fame_list_type);
+ }
+ sd->job = (uint16)job;
sd->status.job_level=1;
sd->status.job_exp=0;
@@ -8468,8 +8711,8 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
if (sd->disguise != -1)
pc->disguise(sd, -1);
- status->set_viewdata(&sd->bl, job);
- clif->changelook(&sd->bl,LOOK_BASE,sd->vd.class_); // move sprite update to prevent client crashes with incompatible equipment [Valaris]
+ status->set_viewdata(&sd->bl, class);
+ clif->changelook(&sd->bl, LOOK_BASE, sd->vd.class); // move sprite update to prevent client crashes with incompatible equipment [Valaris]
if(sd->vd.cloth_color)
clif->changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color);
if (sd->vd.body_style)
@@ -8488,7 +8731,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
//Remove peco/cart/falcon
i = sd->sc.option;
- if( i&OPTION_RIDING && (!pc->checkskill(sd, KN_RIDING) || (sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT) )
+ if (i&OPTION_RIDING && (!pc->checkskill(sd, KN_RIDING) || (sd->job & MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT))
i&=~OPTION_RIDING;
if( i&OPTION_FALCON && !pc->checkskill(sd, HT_FALCON) )
i&=~OPTION_FALCON;
@@ -8513,6 +8756,9 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
if(homun_alive(sd->hd) && !pc->checkskill(sd, AM_CALLHOMUN))
homun->vaporize(sd, HOM_ST_REST);
+ if ((sd->sc.data[SC_SPRITEMABLE] && pc->checkskill(sd, SU_SPRITEMABLE)))
+ status_change_end(&sd->bl, SC_SPRITEMABLE, INVALID_TIMER);
+
if(sd->status.manner < 0)
clif->changestatus(sd,SP_MANNER,sd->status.manner);
@@ -8521,12 +8767,12 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
pc->equiplookall(sd);
//if you were previously famous, not anymore.
- if (fame_flag) {
+ if (fame_flag != 0) {
chrif->save(sd,0);
chrif->buildfamelist();
} else if (sd->status.fame > 0) {
//It may be that now they are famous?
- switch (sd->class_&MAPID_UPPERMASK) {
+ switch (sd->job & MAPID_UPPERMASK) {
case MAPID_BLACKSMITH:
case MAPID_ALCHEMIST:
case MAPID_TAEKWON:
@@ -8566,7 +8812,7 @@ int pc_changelook(struct map_session_data *sd,int type,int val)
switch(type){
case LOOK_BASE:
status->set_viewdata(&sd->bl, val);
- clif->changelook(&sd->bl,LOOK_BASE,sd->vd.class_);
+ clif->changelook(&sd->bl, LOOK_BASE, sd->vd.class);
clif->changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
if (sd->vd.cloth_color)
clif->changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color);
@@ -8712,8 +8958,8 @@ int pc_setoption(struct map_session_data *sd,int type)
return 0; //Disguises break sprite changes
if (new_look < 0) { //Restore normal look.
- status->set_viewdata(&sd->bl, sd->status.class_);
- new_look = sd->vd.class_;
+ status->set_viewdata(&sd->bl, sd->status.class);
+ new_look = sd->vd.class;
}
pc_stop_attack(sd); //Stop attacking on new view change (to prevent wedding/santa attacks.
@@ -8795,6 +9041,7 @@ int pc_setcart(struct map_session_data *sd,int type) {
**/
void pc_setfalcon(struct map_session_data *sd, bool flag)
{
+ nullpo_retv(sd);
if (flag) {
if (pc->checkskill(sd,HT_FALCON) > 0) // add falcon if he have the skill
pc->setoption(sd,sd->sc.option|OPTION_FALCON);
@@ -8813,6 +9060,7 @@ void pc_setfalcon(struct map_session_data *sd, bool flag)
**/
void pc_setridingpeco(struct map_session_data *sd, bool flag)
{
+ nullpo_retv(sd);
if (flag) {
if (pc->checkskill(sd, KN_RIDING))
pc->setoption(sd, sd->sc.option|OPTION_RIDING);
@@ -8831,8 +9079,9 @@ void pc_setridingpeco(struct map_session_data *sd, bool flag)
**/
void pc_setmadogear(struct map_session_data *sd, bool flag)
{
+ nullpo_retv(sd);
if (flag) {
- if ((sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC)
+ if ((sd->job & MAPID_THIRDMASK) == MAPID_MECHANIC)
pc->setoption(sd, sd->sc.option|OPTION_MADOGEAR);
} else if (pc_ismadogear(sd)) {
pc->setoption(sd, sd->sc.option&~OPTION_MADOGEAR);
@@ -8849,6 +9098,7 @@ void pc_setmadogear(struct map_session_data *sd, bool flag)
**/
void pc_setridingdragon(struct map_session_data *sd, unsigned int type)
{
+ nullpo_retv(sd);
if (type&OPTION_DRAGON) {
// Ensure only one dragon is set at a time.
if (type&OPTION_DRAGON1)
@@ -8881,6 +9131,7 @@ void pc_setridingdragon(struct map_session_data *sd, unsigned int type)
**/
void pc_setridingwug(struct map_session_data *sd, bool flag)
{
+ nullpo_retv(sd);
if (flag) {
if (pc->checkskill(sd, RA_WUGRIDER) > 0)
pc->setoption(sd,sd->sc.option|OPTION_WUGRIDER);
@@ -8948,6 +9199,7 @@ int pc_candrop(struct map_session_data *sd, struct item *item)
* For '@type' variables (temporary numeric char reg)
**/
int pc_readreg(struct map_session_data* sd, int64 reg) {
+ nullpo_ret(sd);
return i64db_iget(sd->regs.vars, reg);
}
/**
@@ -8956,6 +9208,7 @@ int pc_readreg(struct map_session_data* sd, int64 reg) {
void pc_setreg(struct map_session_data* sd, int64 reg, int val) {
unsigned int index = script_getvaridx(reg);
+ nullpo_retv(sd);
if( val ) {
i64db_iput(sd->regs.vars, reg, val);
if( index )
@@ -8973,6 +9226,7 @@ void pc_setreg(struct map_session_data* sd, int64 reg, int val) {
char* pc_readregstr(struct map_session_data* sd, int64 reg) {
struct script_reg_str *p = NULL;
+ nullpo_retr(NULL, sd);
p = i64db_get(sd->regs.vars, reg);
return p ? p->value : NULL;
@@ -8983,8 +9237,10 @@ char* pc_readregstr(struct map_session_data* sd, int64 reg) {
void pc_setregstr(struct map_session_data* sd, int64 reg, const char* str) {
struct script_reg_str *p = NULL;
unsigned int index = script_getvaridx(reg);
- DBData prev;
+ struct DBData prev;
+ nullpo_retv(sd);
+ nullpo_retv(str);
if( str[0] ) {
p = ers_alloc(pc->str_reg_ers, struct script_reg_str);
@@ -9020,6 +9276,7 @@ void pc_setregstr(struct map_session_data* sd, int64 reg, const char* str) {
int pc_readregistry(struct map_session_data *sd, int64 reg) {
struct script_reg_num *p = NULL;
+ nullpo_ret(sd);
if (!sd->vars_ok) {
ShowError("pc_readregistry: Trying to read reg %s before it's been loaded!\n", script->get_str(script_getvarid(reg)));
//This really shouldn't happen, so it's possible the data was lost somewhere, we should request it again.
@@ -9041,6 +9298,7 @@ int pc_readregistry(struct map_session_data *sd, int64 reg) {
char* pc_readregistry_str(struct map_session_data *sd, int64 reg) {
struct script_reg_str *p = NULL;
+ nullpo_retr(NULL, sd);
if (!sd->vars_ok) {
ShowError("pc_readregistry_str: Trying to read reg %s before it's been loaded!\n", script->get_str(script_getvarid(reg)));
//This really shouldn't happen, so it's possible the data was lost somewhere, we should request it again.
@@ -9064,11 +9322,12 @@ int pc_setregistry(struct map_session_data *sd, int64 reg, int val) {
const char *regname = script->get_str( script_getvarid(reg) );
unsigned int index = script_getvaridx(reg);
+ nullpo_ret(sd);
/* SAAD! those things should be stored elsewhere e.g. char ones in char table, the cash ones in account_data table! */
switch( regname[0] ) {
default: //Char reg
if( !strcmp(regname,"PC_DIE_COUNTER") && sd->die_counter != val ) {
- int i = (!sd->die_counter && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE);
+ int i = (!sd->die_counter && (sd->job & MAPID_UPPERMASK) == MAPID_SUPER_NOVICE);
sd->die_counter = val;
if( i )
status_calc_pc(sd,SCO_NONE); // Lost the bonus.
@@ -9106,7 +9365,7 @@ int pc_setregistry(struct map_session_data *sd, int64 reg, int val) {
if( !pc->reg_load )
p->flag.update = 1;/* either way, it will require either delete or replace */
} else if( val ) {
- DBData prev;
+ struct DBData prev;
if( index )
script->array_update(&sd->regs, reg, false);
@@ -9139,6 +9398,8 @@ int pc_setregistry_str(struct map_session_data *sd, int64 reg, const char *val)
const char *regname = script->get_str( script_getvarid(reg) );
unsigned int index = script_getvaridx(reg);
+ nullpo_ret(sd);
+ nullpo_ret(val);
if ( !pc->reg_load && !sd->vars_ok ) {
ShowError("pc_setregistry_str : refusing to set %s until vars are received.\n", regname);
return 0;
@@ -9159,7 +9420,7 @@ int pc_setregistry_str(struct map_session_data *sd, int64 reg, const char *val)
if( !pc->reg_load )
p->flag.update = 1;/* either way, it will require either delete or replace */
} else if( val[0] ) {
- DBData prev;
+ struct DBData prev;
if( index )
script->array_update(&sd->regs, reg, false);
@@ -9216,6 +9477,7 @@ int pc_addeventtimer(struct map_session_data *sd,int tick,const char *name)
{
int i;
nullpo_ret(sd);
+ nullpo_ret(name);
ARR_FIND( 0, MAX_EVENTTIMER, i, sd->eventtimer[i] == INVALID_TIMER );
if( i == MAX_EVENTTIMER )
@@ -9236,6 +9498,7 @@ int pc_deleventtimer(struct map_session_data *sd,const char *name)
int i;
nullpo_ret(sd);
+ nullpo_ret(name);
if (sd->eventcount <= 0)
return 0;
@@ -9304,6 +9567,8 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
int index, success = 0;
struct pc_combos *combo;
+ nullpo_ret(sd);
+ nullpo_ret(data);
for( i = 0; i < data->combos_count; i++ ) {
/* ensure this isn't a duplicate combo */
@@ -9379,6 +9644,8 @@ 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;
+ nullpo_ret(sd);
+ nullpo_ret(data);
if( !sd->combos )
return 0;/* nothing to do here, player has no combos */
@@ -9423,6 +9690,7 @@ int pc_removecombo(struct map_session_data *sd, struct item_data *data ) {
}
int pc_load_combo(struct map_session_data *sd) {
int i, ret = 0;
+ nullpo_ret(sd);
for( i = 0; i < EQI_MAX; i++ ) {
struct item_data *id = NULL;
int idx = sd->equip_index[i];
@@ -9455,6 +9723,7 @@ int pc_load_combo(struct map_session_data *sd) {
**/
void pc_equipitem_pos(struct map_session_data *sd, struct item_data *id, int n, int pos)
{
+ nullpo_retv(sd);
if ((!map_no_view(sd->bl.m,EQP_SHADOW_WEAPON) && pos & EQP_SHADOW_WEAPON) ||
(pos & EQP_HAND_R)) {
if(id)
@@ -9565,8 +9834,8 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
pos = pc->equippoint(sd,n); //With a few exceptions, item should go in all specified slots.
if(battle_config.battle_log)
- ShowInfo("equip %d(%d) %x:%x\n",sd->status.inventory[n].nameid,n,id?id->equip:0,req_pos);
- if(!pc->isequip(sd,n) || !(pos&req_pos) || sd->status.inventory[n].equip != 0 || sd->status.inventory[n].attribute==1 ) { // [Valaris]
+ ShowInfo("equip %d(%d) %x:%x\n", sd->status.inventory[n].nameid, n, (unsigned int)(id ? id->equip : 0), (unsigned int)req_pos);
+ if(!pc->isequip(sd,n) || !(pos&req_pos) || sd->status.inventory[n].equip != 0 || (sd->status.inventory[n].attribute & ATTR_BROKEN) != 0 ) { // [Valaris]
// FIXME: pc->isequip: equip level failure uses 2 instead of 0
clif->equipitemack(sd,n,0,EIA_FAIL); // fail
return 0;
@@ -9685,6 +9954,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
**/
void pc_unequipitem_pos(struct map_session_data *sd, int n, int pos)
{
+ nullpo_retv(sd);
if (pos & EQP_HAND_R) {
sd->weapontype1 = 0;
sd->status.weapon = sd->weapontype2;
@@ -9749,127 +10019,142 @@ void pc_unequipitem_pos(struct map_session_data *sd, int n, int pos)
*------------------------------------------*/
int pc_unequipitem(struct map_session_data *sd,int n,int flag)
{
- int i,iflag;
- bool status_cacl = false;
+ int i, iflag;
+ bool status_calc = false;
int pos;
+
nullpo_ret(sd);
- if( n < 0 || n >= MAX_INVENTORY ) {
- clif->unequipitemack(sd,0,0,UIA_FAIL);
+ if (n < 0 || n >= MAX_INVENTORY) {
+ clif->unequipitemack(sd, 0, 0, UIA_FAIL);
return 0;
}
// if player is berserk then cannot unequip
- if (!(flag&PCUNEQUIPITEM_FORCE) && sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_NO_SWITCH_EQUIP]) )
- {
- clif->unequipitemack(sd,n,0,UIA_FAIL);
+ if (!(flag & PCUNEQUIPITEM_FORCE) && sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_NO_SWITCH_EQUIP])) {
+ clif->unequipitemack(sd, n, 0, UIA_FAIL);
return 0;
}
- if( !(flag&PCUNEQUIPITEM_FORCE) && sd->sc.count && sd->sc.data[SC_KYOUGAKU] )
- {
- clif->unequipitemack(sd,n,0,UIA_FAIL);
+ if (!(flag & PCUNEQUIPITEM_FORCE) && sd->sc.count && sd->sc.data[SC_KYOUGAKU]) {
+ clif->unequipitemack(sd, n, 0, UIA_FAIL);
return 0;
}
- if(battle_config.battle_log)
- ShowInfo("unequip %d %x:%x\n",n,pc->equippoint(sd,n),sd->status.inventory[n].equip);
+ if (battle_config.battle_log)
+ ShowInfo("unequip %d %x:%x\n", n, (unsigned int)(pc->equippoint(sd, n)), sd->status.inventory[n].equip);
- if(!sd->status.inventory[n].equip){ //Nothing to unequip
- clif->unequipitemack(sd,n,0,UIA_FAIL);
+ if (sd->status.inventory[n].equip == 0) { //Nothing to unequip
+ clif->unequipitemack(sd, n, 0, UIA_FAIL);
return 0;
}
- for(i=0;i<EQI_MAX;i++) {
- if(sd->status.inventory[n].equip & pc->equip_pos[i])
+
+ for (i = 0; i < EQI_MAX; i++) {
+ if (sd->status.inventory[n].equip & pc->equip_pos[i])
sd->equip_index[i] = -1;
}
pos = sd->status.inventory[n].equip;
pc->unequipitem_pos(sd, n, pos);
- clif->unequipitemack(sd,n,pos,UIA_SUCCESS);
+ clif->unequipitemack(sd, n, pos, UIA_SUCCESS);
- if((pos & EQP_ARMS) &&
- sd->weapontype1 == 0 && sd->weapontype2 == 0 && (!sd->sc.data[SC_TK_SEVENWIND] || sd->sc.data[SC_ASPERSIO])) //Check for seven wind (but not level seven!)
- skill->enchant_elemental_end(&sd->bl,-1);
+ if ((pos & EQP_ARMS) &&
+ sd->weapontype1 == 0 && sd->weapontype2 == 0 && (sd->sc.data[SC_TK_SEVENWIND] == 0 || sd->sc.data[SC_ASPERSIO])) //Check for seven wind (but not level seven!)
+ skill->enchant_elemental_end(&sd->bl, -1);
- if(pos & EQP_ARMOR) {
+ if (pos & EQP_ARMOR) {
// On Armor Change...
status_change_end(&sd->bl, SC_BENEDICTIO, INVALID_TIMER);
status_change_end(&sd->bl, SC_ARMOR_RESIST, INVALID_TIMER);
}
+#ifdef RENEWAL
+ if (battle->bc->bow_unequip_arrow && pos&EQP_ARMS && sd->equip_index[EQI_AMMO] > 0)
+ pc->unequipitem(sd, sd->equip_index[EQI_AMMO], PCUNEQUIPITEM_FORCE);
+#endif
+
if( sd->state.autobonus&pos )
sd->state.autobonus &= ~sd->status.inventory[n].equip; //Check for activated autobonus [Inkfish]
- sd->status.inventory[n].equip=0;
+ sd->status.inventory[n].equip = 0;
iflag = sd->npc_item_flag;
/* check for combos (MUST be before status_calc_pc) */
- if ( sd->inventory_data[n] ) {
- if( sd->inventory_data[n]->combos_count ) {
- if( pc->removecombo(sd,sd->inventory_data[n]) )
- status_cacl = true;
- } if(itemdb_isspecial(sd->status.inventory[n].card[0]))
- ; //No cards
- else {
- for( i = 0; i < sd->inventory_data[n]->slot; i++ ) {
+ if (sd->inventory_data[n] != NULL) {
+ if (sd->inventory_data[n]->combos_count) {
+ if (pc->removecombo(sd, sd->inventory_data[n]))
+ status_calc = true;
+ }
+ if (itemdb_isspecial(sd->status.inventory[n].card[0]) == false) {
+ for (i = 0; i < sd->inventory_data[n]->slot; i++) {
struct item_data *data;
- if (!sd->status.inventory[n].card[i])
+ if (sd->status.inventory[n].card[i] == 0)
continue;
- if ( ( data = itemdb->exists(sd->status.inventory[n].card[i]) ) != NULL ) {
- if( data->combos_count ) {
- if( pc->removecombo(sd,data) )
- status_cacl = true;
+ if ((data = itemdb->exists(sd->status.inventory[n].card[i])) != NULL) {
+ if (data->combos_count) {
+ if (pc->removecombo(sd, data))
+ status_calc = true;
}
}
}
}
+ /* Item Options checking */
+ for (i = 0; i < MAX_ITEM_OPTIONS; i++) {
+ struct item_option *ito = NULL;
+ int16 item_option = sd->status.inventory[n].option[i].index;
+
+ if (item_option <= 0)
+ continue;
+ if ((ito = itemdb->option_exists(sd->status.inventory[n].option[i].index)) == NULL)
+ continue;
+
+ status_calc = true;
+ }
}
- if(flag&PCUNEQUIPITEM_RECALC || status_cacl) {
+ if (flag & PCUNEQUIPITEM_RECALC || status_calc) {
pc->checkallowskill(sd);
- status_calc_pc(sd,SCO_NONE);
+ status_calc_pc(sd, SCO_NONE);
}
- if(sd->sc.data[SC_CRUCIS] && !battle->check_undead(sd->battle_status.race,sd->battle_status.def_ele))
+ if (sd->sc.data[SC_CRUCIS] && battle->check_undead(sd->battle_status.race, sd->battle_status.def_ele) == false)
status_change_end(&sd->bl, SC_CRUCIS, INVALID_TIMER);
//OnUnEquip script [Skotlex]
- if (sd->inventory_data[n]) {
- if (sd->inventory_data[n]->unequip_script) {
- if ( battle_config.unequip_restricted_equipment & 1 ) {
- ARR_FIND(0, map->list[sd->bl.m].zone->disabled_items_count, i, map->list[sd->bl.m].zone->disabled_items[i] == sd->status.inventory[n].nameid);
- if ( i == map->list[sd->bl.m].zone->disabled_items_count )
+ if (sd->inventory_data[n] != NULL) {
+ if (sd->inventory_data[n]->unequip_script != NULL) {
+ if (battle_config.unequip_restricted_equipment & 1) {
+ ARR_FIND(0, map->list[sd->bl.m].zone->disabled_items_count, i, map->list[sd->bl.m].zone->disabled_items[i] == sd->status.inventory[n].nameid);
+ if (i == map->list[sd->bl.m].zone->disabled_items_count)
script->run_item_unequip_script(sd, sd->inventory_data[n], npc->fake_nd->bl.id);
}
else
script->run_item_unequip_script(sd, sd->inventory_data[n], npc->fake_nd->bl.id);
}
- if(itemdb_isspecial(sd->status.inventory[n].card[0]))
- ; //No cards
- else {
- for( i = 0; i < sd->inventory_data[n]->slot; i++ ) {
- struct item_data *data;
- if (!sd->status.inventory[n].card[i])
+ if (itemdb_isspecial(sd->status.inventory[n].card[0]) == false) {
+ for (i = 0; i < sd->inventory_data[n]->slot; i++) {
+ struct item_data *data = NULL;
+ if (sd->status.inventory[n].card[i] == 0)
continue;
- if ( ( data = itemdb->exists(sd->status.inventory[n].card[i]) ) != NULL ) {
- if ( data->unequip_script ) {
- if ( battle_config.unequip_restricted_equipment & 2 ) {
+ if ((data = itemdb->exists(sd->status.inventory[n].card[i])) != NULL) {
+ if (data->unequip_script) {
+ if (battle_config.unequip_restricted_equipment & 2) {
int j;
- ARR_FIND(0, map->list[sd->bl.m].zone->disabled_items_count, j, map->list[sd->bl.m].zone->disabled_items[j] == sd->status.inventory[n].card[i]);
- if ( j == map->list[sd->bl.m].zone->disabled_items_count )
+ ARR_FIND(0, map->list[sd->bl.m].zone->disabled_items_count, j, map->list[sd->bl.m].zone->disabled_items[j] == sd->status.inventory[n].card[i]);
+ if (j == map->list[sd->bl.m].zone->disabled_items_count)
script->run_item_unequip_script(sd, data, npc->fake_nd->bl.id);
- }
- else
+ } else {
script->run_item_unequip_script(sd, data, npc->fake_nd->bl.id);
+ }
}
}
}
}
}
+
sd->npc_item_flag = iflag;
return 1;
@@ -9885,99 +10170,108 @@ int pc_checkitem(struct map_session_data *sd)
nullpo_ret(sd);
- if (sd->state.vending) //Avoid reorganizing items when we are vending, as that leads to exploits (pointed out by End of Exam)
+ if (sd->state.vending == 1) // Avoid reorganizing items when we are vending, as that leads to exploits (pointed out by End of Exam)
return 0;
- if (sd->state.itemcheck) { // check for invalid(ated) items
- int id;
- for (i = 0; i < MAX_INVENTORY; i++) {
- id = sd->status.inventory[i].nameid;
+ if (sd->itemcheck != PCCHECKITEM_NONE) { // check for invalid(ated) items
+ int id = 0;
- if (!id)
- continue;
+ if (sd->itemcheck & PCCHECKITEM_INVENTORY) {
+ for (i = 0; i < MAX_INVENTORY; i++) {
+ if ((id = sd->status.inventory[i].nameid) == 0)
+ continue;
- if (!itemdb_available(id)) {
- ShowWarning("Removed invalid/disabled item id %d from inventory (amount=%d, char_id=%d).\n", id, sd->status.inventory[i].amount, sd->status.char_id);
- pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_OTHER);
- continue;
+ if (!itemdb_available(id)) {
+ ShowWarning("pc_checkitem: Removed invalid/disabled item id %d from inventory (amount=%d, char_id=%d).\n", id, sd->status.inventory[i].amount, sd->status.char_id);
+ pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_INV_INVALID);
+ continue;
+ }
+
+ if (sd->status.inventory[i].unique_id == 0 && !itemdb->isstackable(id))
+ sd->status.inventory[i].unique_id = itemdb->unique_id(sd);
}
- if (!sd->status.inventory[i].unique_id && !itemdb->isstackable(id))
- sd->status.inventory[i].unique_id = itemdb->unique_id(sd);
+ sd->itemcheck &= ~PCCHECKITEM_INVENTORY;
}
- for( i = 0; i < MAX_CART; i++ ) {
- id = sd->status.cart[i].nameid;
+ if (sd->itemcheck & PCCHECKITEM_CART) {
+ for (i = 0; i < MAX_CART; i++) {
+ if ((id = sd->status.cart[i].nameid) == 0)
+ continue;
- if (!id)
- continue;
+ if( !itemdb_available(id) ) {
+ ShowWarning("pc_checkitem: Removed invalid/disabled item id %d from cart (amount=%d, char_id=%d).\n", id, sd->status.cart[i].amount, sd->status.char_id);
+ pc->cart_delitem(sd, i, sd->status.cart[i].amount, 0, LOG_TYPE_CART_INVALID);
+ continue;
+ }
- if( !itemdb_available(id) ) {
- ShowWarning("Removed invalid/disabled item id %d from cart (amount=%d, char_id=%d).\n", id, sd->status.cart[i].amount, sd->status.char_id);
- pc->cart_delitem(sd, i, sd->status.cart[i].amount, 0, LOG_TYPE_OTHER);
- continue;
+ if (sd->status.cart[i].unique_id == 0 && !itemdb->isstackable(id))
+ sd->status.cart[i].unique_id = itemdb->unique_id(sd);
}
- if ( !sd->status.cart[i].unique_id && !itemdb->isstackable(id) )
- sd->status.cart[i].unique_id = itemdb->unique_id(sd);
+ sd->itemcheck &= ~PCCHECKITEM_CART;
}
- for( i = 0; i < MAX_STORAGE; i++ ) {
- id = sd->status.storage.items[i].nameid;
+ if (sd->itemcheck & PCCHECKITEM_STORAGE && sd->storage.received == true) {
+ for (i = 0; i < VECTOR_LENGTH(sd->storage.item); i++) {
+ struct item *it = &VECTOR_INDEX(sd->storage.item, i);
- if (!id)
- continue;
+ if ((id = it->nameid) == 0)
+ continue;
- if( id && !itemdb_available(id) ) {
- ShowWarning("Removed invalid/disabled item id %d from storage (amount=%d, char_id=%d).\n", id, sd->status.storage.items[i].amount, sd->status.char_id);
- storage->delitem(sd, i, sd->status.storage.items[i].amount);
- storage->close(sd);
- continue;
+ if (!itemdb_available(id)) {
+ ShowWarning("pc_checkitem: Removed invalid/disabled item id %d from storage (amount=%d, char_id=%d).\n", id, it->amount, sd->status.char_id);
+ storage->delitem(sd, i, it->amount);
+ continue;
+ }
+
+ if (it->unique_id == 0 && itemdb->isstackable(id) == 0)
+ it->unique_id = itemdb->unique_id(sd);
}
- if ( !sd->status.storage.items[i].unique_id && !itemdb->isstackable(id) )
- sd->status.storage.items[i].unique_id = itemdb->unique_id(sd);
+ storage->close(sd);
+
+ sd->itemcheck &= ~PCCHECKITEM_STORAGE;
}
- if (sd->guild) {
+ if (sd->guild && sd->itemcheck & PCCHECKITEM_GSTORAGE) {
struct guild_storage *guild_storage = idb_get(gstorage->db,sd->guild->guild_id);
if (guild_storage) {
- for( i = 0; i < MAX_GUILD_STORAGE; i++ ) {
- id = guild_storage->items[i].nameid;
-
- if (!id)
+ for (i = 0; i < MAX_GUILD_STORAGE; i++) {
+ if ((id = guild_storage->items[i].nameid) == 0)
continue;
- if( !itemdb_available(id) ) {
- ShowWarning("Removed invalid/disabled item id %d from guild storage (amount=%d, char_id=%d, guild_id=%d).\n", id, guild_storage->items[i].amount, sd->status.char_id, sd->guild->guild_id);
+ if (!itemdb_available(id)) {
+ ShowWarning("pc_checkitem: Removed invalid/disabled item id %d from guild storage (amount=%d, char_id=%d, guild_id=%d).\n", id, guild_storage->items[i].amount, sd->status.char_id, sd->guild->guild_id);
gstorage->delitem(sd, guild_storage, i, guild_storage->items[i].amount);
gstorage->close(sd); // force closing
continue;
}
- if (!guild_storage->items[i].unique_id && !itemdb->isstackable(id))
+ if (guild_storage->items[i].unique_id == 0 && !itemdb->isstackable(id))
guild_storage->items[i].unique_id = itemdb->unique_id(sd);
}
}
+
+ sd->itemcheck &= ~PCCHECKITEM_GSTORAGE;
}
- sd->state.itemcheck = 0;
}
- for( i = 0; i < MAX_INVENTORY; i++) {
+ for (i = 0; i < MAX_INVENTORY; i++) {
- if( sd->status.inventory[i].nameid == 0 )
+ if (sd->status.inventory[i].nameid == 0)
continue;
- if( !sd->status.inventory[i].equip )
+ if (sd->status.inventory[i].equip == 0)
continue;
- if( sd->status.inventory[i].equip&~pc->equippoint(sd,i) ) {
+ if (sd->status.inventory[i].equip & ~pc->equippoint(sd,i)) {
pc->unequipitem(sd, i, PCUNEQUIPITEM_FORCE);
calc_flag = 1;
continue;
}
- if (battle_config.unequip_restricted_equipment&1) {
+ if (battle_config.unequip_restricted_equipment & 1) {
int j;
for (j = 0; j < map->list[sd->bl.m].zone->disabled_items_count; j++) {
if (map->list[sd->bl.m].zone->disabled_items[j] == sd->status.inventory[i].nameid) {
@@ -9987,7 +10281,7 @@ int pc_checkitem(struct map_session_data *sd)
}
}
- if (battle_config.unequip_restricted_equipment&2) {
+ if (battle_config.unequip_restricted_equipment & 2) {
if (!itemdb_isspecial(sd->status.inventory[i].card[0])) {
int j, slot;
for (slot = 0; slot < MAX_SLOTS; slot++) {
@@ -10003,9 +10297,9 @@ int pc_checkitem(struct map_session_data *sd)
}
- if( calc_flag && sd->state.active ) {
+ if (calc_flag != 0 && sd->state.active == 1) {
pc->checkallowskill(sd);
- status_calc_pc(sd,SCO_NONE);
+ status_calc_pc(sd, SCO_NONE);
}
return 0;
@@ -10040,6 +10334,7 @@ int pc_calc_pvprank_sub(struct block_list *bl, va_list ap)
int pc_calc_pvprank(struct map_session_data *sd) {
int old;
struct map_data *m;
+ nullpo_ret(sd);
m=&map->list[sd->bl.m];
old=sd->pvp_rank;
sd->pvp_rank=1;
@@ -10094,7 +10389,7 @@ int pc_marriage(struct map_session_data *sd,struct map_session_data *dstsd)
{
if(sd == NULL || dstsd == NULL ||
sd->status.partner_id > 0 || dstsd->status.partner_id > 0 ||
- (sd->class_&JOBL_BABY) || (dstsd->class_&JOBL_BABY))
+ (sd->job & JOBL_BABY) != 0 || (dstsd->job & JOBL_BABY) != 0)
return -1;
sd->status.partner_id = dstsd->status.char_id;
dstsd->status.partner_id = sd->status.char_id;
@@ -10132,9 +10427,9 @@ int pc_divorce(struct map_session_data *sd)
for( i = 0; i < MAX_INVENTORY; i++ )
{
if( sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F )
- pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER);
+ pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_DIVORCE);
if( p_sd->status.inventory[i].nameid == WEDDING_RING_M || p_sd->status.inventory[i].nameid == WEDDING_RING_F )
- pc->delitem(p_sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER);
+ pc->delitem(p_sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_DIVORCE);
}
clif->divorced(sd, p_sd->status.name);
@@ -10158,7 +10453,7 @@ struct map_session_data *pc_get_partner(struct map_session_data *sd) {
* Get sd father charid. (Need to be baby)
*------------------------------------------*/
struct map_session_data *pc_get_father(struct map_session_data *sd) {
- if (sd && sd->class_&JOBL_BABY && sd->status.father > 0)
+ if (sd && (sd->job & JOBL_BABY) != 0 && sd->status.father > 0)
// charid2sd returns NULL if not found
return map->charid2sd(sd->status.father);
@@ -10169,7 +10464,7 @@ struct map_session_data *pc_get_father(struct map_session_data *sd) {
* Get sd mother charid. (Need to be baby)
*------------------------------------------*/
struct map_session_data *pc_get_mother(struct map_session_data *sd) {
- if (sd && sd->class_&JOBL_BABY && sd->status.mother > 0)
+ if (sd && (sd->job & JOBL_BABY) != 0 && sd->status.mother > 0)
// charid2sd returns NULL if not found
return map->charid2sd(sd->status.mother);
@@ -10194,6 +10489,7 @@ void pc_bleeding (struct map_session_data *sd, unsigned int diff_tick)
{
int hp = 0, sp = 0;
+ nullpo_retv(sd);
if( pc_isdead(sd) )
return;
@@ -10227,6 +10523,7 @@ void pc_bleeding (struct map_session_data *sd, unsigned int diff_tick)
void pc_regen (struct map_session_data *sd, unsigned int diff_tick) {
int hp = 0, sp = 0;
+ nullpo_retv(sd);
if (sd->hp_regen.value) {
sd->hp_regen.tick += diff_tick;
while (sd->hp_regen.tick >= sd->hp_regen.rate) {
@@ -10304,6 +10601,7 @@ int pc_autosave(int tid, int64 tick, int id, intptr_t data) {
}
int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap) {
+ nullpo_ret(sd);
if (sd->state.night != map->night_flag && map->list[sd->bl.m].flag.nightenabled) { //Night/day state does not match.
clif->status_change(&sd->bl, SI_SKE, map->night_flag, 0, 0, 0, 0); //New night effect by dynamix [Skotlex]
sd->state.night = map->night_flag;
@@ -10327,7 +10625,7 @@ int map_day_timer(int tid, int64 tick, int id, intptr_t data) {
map->night_flag = 0; // 0=day, 1=night [Yor]
map->foreachpc(pc->daynight_timer_sub);
safestrncpy(tmp_soutput, (data == 0) ? msg_txt(502) : msg_txt(60), sizeof(tmp_soutput)); // The day has arrived!
- intif->broadcast(tmp_soutput, strlen(tmp_soutput) + 1, BC_DEFAULT);
+ intif->broadcast(tmp_soutput, (int)strlen(tmp_soutput) + 1, BC_DEFAULT);
return 0;
}
@@ -10347,7 +10645,7 @@ int map_night_timer(int tid, int64 tick, int id, intptr_t data) {
map->night_flag = 1; // 0=day, 1=night [Yor]
map->foreachpc(pc->daynight_timer_sub);
safestrncpy(tmp_soutput, (data == 0) ? msg_txt(503) : msg_txt(59), sizeof(tmp_soutput)); // The night has fallen...
- intif->broadcast(tmp_soutput, strlen(tmp_soutput) + 1, BC_DEFAULT);
+ intif->broadcast(tmp_soutput, (int)strlen(tmp_soutput) + 1, BC_DEFAULT);
return 0;
}
@@ -10368,6 +10666,7 @@ void pc_overheat(struct map_session_data *sd, int val) {
int heat = val, skill_lv,
limit[] = { 10, 20, 28, 46, 66 };
+ nullpo_retv(sd);
if( !pc_ismadogear(sd) || sd->sc.data[SC_OVERHEAT] )
return; // already burning
@@ -10393,6 +10692,7 @@ bool pc_isautolooting(struct map_session_data *sd, int nameid)
{
int i = 0;
+ nullpo_ret(sd);
if (sd->state.autoloottype && sd->state.autoloottype&(1<<itemdb_type(nameid)))
return true;
@@ -10538,11 +10838,18 @@ void pc_del_charm(struct map_session_data *sd, int count, int type)
clif->spiritcharm(sd);
}
-/*==========================================
- * Renewal EXP/Itemdrop rate modifier base on level penalty
- * 1=exp 2=itemdrop
- *------------------------------------------*/
-int pc_level_penalty_mod(int diff, unsigned char race, unsigned short mode, int type) {
+
+/**
+ * Renewal EXP/Itemdrop rate modifier base on level penalty.
+ *
+ * @param diff Level difference.
+ * @param race Monster race.
+ * @param mode Monster mode.
+ * @param type Modifier type (1=exp 2=itemdrop)
+ * @return The percent rate modifier (100 = 100%)
+ */
+int pc_level_penalty_mod(int diff, unsigned char race, uint32 mode, int type)
+{
#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
int rate = 100, i;
@@ -10574,6 +10881,7 @@ int pc_split_str(char *str,char **val,int num)
{
int i;
+ nullpo_ret(val);
for (i=0; i<num && str; i++){
val[i] = str;
str = strchr(str,',');
@@ -10586,6 +10894,7 @@ int pc_split_str(char *str,char **val,int num)
int pc_split_atoi(char* str, int* val, char sep, int max)
{
int i,j;
+ nullpo_ret(val);
for (i=0; i<max; i++) {
if (!str) break;
val[i] = atoi(str);
@@ -10603,6 +10912,7 @@ int pc_split_atoui(char* str, unsigned int* val, char sep, int max)
{
static int warning=0;
int i,j;
+ nullpo_ret(val);
for (i=0; i<max; i++) {
double f;
if (!str) break;
@@ -10642,8 +10952,8 @@ int pc_split_atoui(char* str, unsigned int* val, char sep, int max)
*/
void pc_read_skill_tree(void)
{
- config_t skill_tree_conf;
- config_setting_t *skt = NULL;
+ struct config_t skill_tree_conf;
+ struct config_setting_t *skt = NULL;
char config_filename[128];
int i = 0;
struct s_mapiterator *iter;
@@ -10651,14 +10961,12 @@ void pc_read_skill_tree(void)
bool loaded[CLASS_COUNT] = { false };
safesnprintf(config_filename, sizeof(config_filename), "%s/"DBPATH"skill_tree.conf", map->db_path);
- if (libconfig->read_file(&skill_tree_conf, config_filename)) {
- ShowError("can't read %s\n", config_filename);
+ if (!libconfig->load_file(&skill_tree_conf, config_filename))
return;
- }
// Foreach job
while ((skt = libconfig->setting_get_elem(skill_tree_conf.root, i++))) {
- config_setting_t *t = NULL;
+ struct config_setting_t *t = NULL;
int job_idx;
const char *job_name = config_setting_name(skt);
int job_id = pc->check_job_name(job_name);
@@ -10748,11 +11056,11 @@ void pc_read_skill_tree(void)
}
if ((t = libconfig->setting_get_member(skt, "skills")) != NULL) {
int j = 0;
- config_setting_t *sk = NULL;
+ struct config_setting_t *sk = NULL;
// Foreach skill
while ((sk = libconfig->setting_get_elem(t, j++)) != NULL) {
int skill_id, sk_idx;
- config_setting_t *rsk = NULL;
+ struct config_setting_t *rsk = NULL;
const char *sk_name = config_setting_name(sk);
struct skill_tree_entry *tree_entry = NULL;
@@ -10857,6 +11165,7 @@ bool pc_readdb_levelpenalty(char* fields[], int columns, int current) {
#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
int type, race, diff;
+ nullpo_retr(false, fields);
type = atoi(fields[0]);
race = atoi(fields[1]);
diff = atoi(fields[2]);
@@ -10907,7 +11216,7 @@ int pc_readdb(void) {
while(fgets(line, sizeof(line), fp)) {
int jobs[CLASS_COUNT], job_count, job, job_id;
int type;
- unsigned int ui,maxlv;
+ int maxlv;
char *split[4];
if(line[0]=='/' && line[1]=='/')
continue;
@@ -10929,7 +11238,7 @@ int pc_readdb(void) {
}
maxlv = atoi(split[0]);
if (maxlv > MAX_LEVEL) {
- ShowWarning("pc_readdb: Specified max level %u for job %d is beyond server's limit (%u).\n ", maxlv, job_id, MAX_LEVEL);
+ ShowWarning("pc_readdb: Specified max level %d for job %d is beyond server's limit (%d).\n ", maxlv, job_id, MAX_LEVEL);
maxlv = MAX_LEVEL;
}
count++;
@@ -10940,15 +11249,15 @@ int pc_readdb(void) {
//The reasoning behind the -2 is this... if the max level is 5, then the array
//should look like this:
//0: x, 1: x, 2: x: 3: x 4: 0 <- last valid value is at 3.
- while ((ui = pc->max_level[job][type]) >= 2 && pc->exp_table[job][type][ui-2] <= 0)
+ while ((i = pc->max_level[job][type]) >= 2 && pc->exp_table[job][type][i-2] <= 0)
pc->max_level[job][type]--;
if (pc->max_level[job][type] < maxlv) {
- ShowWarning("pc_readdb: Specified max %u for job %d, but that job's exp table only goes up to level %u.\n", maxlv, job_id, pc->max_level[job][type]);
+ ShowWarning("pc_readdb: Specified max %d for job %d, but that job's exp table only goes up to level %d.\n", maxlv, job_id, pc->max_level[job][type]);
ShowInfo("Filling the missing values with the last exp entry.\n");
//Fill the requested values with the last entry.
- ui = (pc->max_level[job][type] <= 2? 0: pc->max_level[job][type]-2);
- for (; ui+2 < maxlv; ui++)
- pc->exp_table[job][type][ui] = pc->exp_table[job][type][ui-1];
+ i = (pc->max_level[job][type] <= 2 ? 0: pc->max_level[job][type]-2);
+ for (; i+2 < maxlv; i++)
+ pc->exp_table[job][type][i] = pc->exp_table[job][type][i-1];
pc->max_level[job][type] = maxlv;
}
//ShowDebug("%s - Class %d: %d\n", type?"Job":"Base", job_id, pc->max_level[job][type]);
@@ -10961,7 +11270,7 @@ int pc_readdb(void) {
job = pc->class2idx(job_id);
memcpy(pc->exp_table[job][type], pc->exp_table[jobs[0]][type], sizeof(pc->exp_table[0][0]));
pc->max_level[job][type] = maxlv;
- //ShowDebug("%s - Class %d: %u\n", type?"Job":"Base", job_id, pc->max_level[job][type]);
+ //ShowDebug("%s - Class %d: %d\n", type?"Job":"Base", job_id, pc->max_level[job][type]);
}
}
fclose(fp);
@@ -11001,18 +11310,18 @@ int pc_readdb(void) {
ShowError("can't read %s\n", line);
return 1;
}
- while(fgets(line, sizeof(line), fp))
- {
+ while (fgets(line, sizeof(line), fp)) {
char *split[10];
int lv,n;
- if(line[0]=='/' && line[1]=='/')
+ if (line[0]=='/' && line[1]=='/')
continue;
- for(j=0,p=line;j<3 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
+ for (j = 0, p = line; j < 3 && p != NULL; j++) {
+ split[j] = p;
+ p = strchr(p,',');
+ if (p != NULL)
+ *p++ = 0;
}
- if( j < 2 )
+ if (j < 2)
continue;
lv=atoi(split[0]);
@@ -11024,8 +11333,8 @@ int pc_readdb(void) {
if(line[0]=='/' && line[1]=='/')
continue;
- for ( j = ELE_NEUTRAL, p = line; j<n && j<ELE_MAX && p; j++ ) {
- while(*p==32 && *p>0)
+ for (j = ELE_NEUTRAL, p = line; j < n && j < ELE_MAX && p != NULL; j++) {
+ while (*p == ' ')
p++;
battle->attr_fix_table[lv-1][i][j]=atoi(p);
#ifndef RENEWAL
@@ -11033,7 +11342,8 @@ int pc_readdb(void) {
battle->attr_fix_table[lv-1][i][j] = 0;
#endif
p=strchr(p,',');
- if(p) *p++=0;
+ if (p != NULL)
+ *p++ = 0;
}
i++;
@@ -11088,9 +11398,9 @@ void pc_validate_levels(void) {
if (i == JOB_WEDDING || i == JOB_XMAS || i == JOB_SUMMER)
continue; //Classes that do not need exp tables.
j = pc->class2idx(i);
- if (!pc->max_level[j][0])
+ if (pc->max_level[j][0] == 0)
ShowWarning("Class %s (%d) does not has a base exp table.\n", pc->job_name(i), i);
- if (!pc->max_level[j][1])
+ if (pc->max_level[j][1] == 0)
ShowWarning("Class %s (%d) does not has a job exp table.\n", pc->job_name(i), i);
}
}
@@ -11099,6 +11409,7 @@ void pc_itemcd_do(struct map_session_data *sd, bool load) {
int i,cursor = 0;
struct item_cd* cd = NULL;
+ nullpo_retv(sd);
if( load ) {
if( !(cd = idb_get(pc->itemcd_db, sd->status.char_id)) ) {
// no skill cooldown is associated with this character
@@ -11130,7 +11441,10 @@ void pc_itemcd_do(struct map_session_data *sd, bool load) {
}
void pc_bank_deposit(struct map_session_data *sd, int money) {
- unsigned int limit_check = money+sd->status.bank_vault;
+ unsigned int limit_check;
+
+ nullpo_retv(sd);
+ limit_check = money + sd->status.bank_vault;
if( money <= 0 || limit_check > MAX_BANK_ZENY ) {
clif->bank_deposit(sd,BDA_OVERFLOW);
@@ -11150,8 +11464,10 @@ void pc_bank_deposit(struct map_session_data *sd, int money) {
}
}
void pc_bank_withdraw(struct map_session_data *sd, int money) {
- unsigned int limit_check = money+sd->status.zeny;
+ unsigned int limit_check;
+ nullpo_retv(sd);
+ limit_check = money + sd->status.zeny;
if (money <= 0) {
clif->bank_withdraw(sd,BWA_UNKNOWN_ERROR);
return;
@@ -11175,6 +11491,7 @@ void pc_bank_withdraw(struct map_session_data *sd, int money) {
}
/* status change data arrived from char-server */
void pc_scdata_received(struct map_session_data *sd) {
+ nullpo_retv(sd);
pc->inventory_rentals(sd);
clif->show_modifiers(sd);
@@ -11182,7 +11499,7 @@ void pc_scdata_received(struct map_session_data *sd) {
time_t exp_time = sd->expiration_time;
char tmpstr[1024];
strftime(tmpstr, sizeof(tmpstr) - 1, msg_sd(sd,501), localtime(&exp_time)); // "Your account time limit is: %d-%m-%Y %H:%M:%S."
- clif->wis_message(sd->fd, map->wisp_server_name, tmpstr, strlen(tmpstr)+1);
+ clif->wis_message(sd->fd, map->wisp_server_name, tmpstr, (int)strlen(tmpstr));
pc->expire_check(sd);
}
@@ -11223,6 +11540,7 @@ int pc_global_expiration_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
void pc_expire_check(struct map_session_data *sd) {
+ nullpo_retv(sd);
/* ongoing timer */
if( sd->expiration_tid != INVALID_TIMER )
return;
@@ -11280,6 +11598,7 @@ void pc_autotrade_start(struct map_session_data *sd) {
int i;
char *data;
+ nullpo_retv(sd);
if (SQL_ERROR == SQL->Query(map->mysql_handle, "SELECT `itemkey`,`amount`,`price` FROM `%s` WHERE `char_id` = '%d'",map->autotrade_data_db,sd->status.char_id))
Sql_ShowDebug(map->mysql_handle);
@@ -11324,6 +11643,7 @@ void pc_autotrade_start(struct map_session_data *sd) {
void pc_autotrade_update(struct map_session_data *sd, enum e_pc_autotrade_update_action action) {
int i;
+ nullpo_retv(sd);
/* either way, this goes down */
if( action != PAUC_START ) {
if (SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'",map->autotrade_data_db,sd->status.char_id))
@@ -11349,13 +11669,13 @@ void pc_autotrade_update(struct map_session_data *sd, enum e_pc_autotrade_update
))
Sql_ShowDebug(map->mysql_handle);
}
- /* yes we want it to fall */
+ FALLTHROUGH
case PAUC_REFRESH:
for( i = 0; i < sd->vend_num; i++ ) {
if( sd->vending[i].amount == 0 )
continue;
- if (SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `%s` (`char_id`,`itemkey`,`amount`,`price`) VALUES ('%d','%d','%d','%d')",
+ if (SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `%s` (`char_id`,`itemkey`,`amount`,`price`) VALUES ('%d','%d','%d','%u')",
map->autotrade_data_db,
sd->status.char_id,
sd->status.cart[sd->vending[i].index].id,
@@ -11377,6 +11697,7 @@ void pc_autotrade_prepare(struct map_session_data *sd) {
char title[MESSAGE_SIZE];
unsigned char sex;
+ nullpo_retv(sd);
CREATE(data, struct autotrade_vending, 1);
memcpy(data->vending, sd->vending, sizeof(sd->vending));
@@ -11423,6 +11744,7 @@ void pc_autotrade_populate(struct map_session_data *sd) {
struct autotrade_vending *data;
int i, j, k, cursor = 0;
+ nullpo_retv(sd);
if( !(data = idb_get(pc->at_db,sd->status.char_id)) )
return;
@@ -11462,8 +11784,10 @@ void pc_autotrade_populate(struct map_session_data *sd) {
/**
* @see DBApply
*/
-int pc_autotrade_final(DBKey key, DBData *data, va_list ap) {
+int pc_autotrade_final(union DBKey key, struct DBData *data, va_list ap)
+{
struct autotrade_vending* at_v = DB->data2ptr(data);
+ nullpo_ret(at_v);
HPM->data_store_destroy(&at_v->hdata);
return 0;
}
@@ -11476,16 +11800,17 @@ void pc_update_idle_time(struct map_session_data* sd, enum e_battle_config_idlet
}
//Checks if the given class value corresponds to a player class. [Skotlex]
-//JOB_NOVICE isn't checked for class_ is supposed to be unsigned
-bool pc_db_checkid(unsigned int class_)
+//JOB_NOVICE isn't checked for class is supposed to be unsigned
+bool pc_db_checkid(int class)
{
- return class_ < JOB_MAX_BASIC
- || (class_ >= JOB_NOVICE_HIGH && class_ <= JOB_DARK_COLLECTOR )
- || (class_ >= JOB_RUNE_KNIGHT && class_ <= JOB_MECHANIC_T2 )
- || (class_ >= JOB_BABY_RUNE && class_ <= JOB_BABY_MECHANIC2 )
- || (class_ >= JOB_SUPER_NOVICE_E && class_ <= JOB_SUPER_BABY_E )
- || (class_ >= JOB_KAGEROU && class_ <= JOB_OBORO )
- || (class_ >= JOB_REBELLION && class_ < JOB_MAX );
+ return class < JOB_MAX_BASIC
+ || (class >= JOB_NOVICE_HIGH && class <= JOB_DARK_COLLECTOR )
+ || (class >= JOB_RUNE_KNIGHT && class <= JOB_MECHANIC_T2 )
+ || (class >= JOB_BABY_RUNE && class <= JOB_BABY_MECHANIC2 )
+ || (class >= JOB_SUPER_NOVICE_E && class <= JOB_SUPER_BABY_E )
+ || (class >= JOB_KAGEROU && class <= JOB_OBORO )
+ || (class == JOB_REBELLION)
+ || (class >= JOB_SUMMONER && class < JOB_MAX );
}
/**
@@ -11496,12 +11821,108 @@ bool pc_db_checkid(unsigned int class_)
int pc_have_magnifier(struct map_session_data *sd)
{
int n;
- n = pc->search_inventory(sd, ITEMID_MAGNIFIER);
+ n = pc->search_inventory(sd, ITEMID_SPECTACLES);
if (n == INDEX_NOT_FOUND)
- n = pc->search_inventory(sd, ITEMID_NOVICE_MAGNIFIER);
+ n = pc->search_inventory(sd, ITEMID_N_MAGNIFIER);
return n;
}
+/**
+ * Checks if player have basic skills learned.
+ * @param sd Player Data
+ * @param level Required Level of Novice Skill
+ * @return bool true, if requirement is satisfied
+ */
+bool pc_check_basicskill(struct map_session_data *sd, int level) {
+ if (pc->checkskill(sd, NV_BASIC) >= level || pc->checkskill(sd, SU_BASIC_SKILL))
+ return true;
+ return false;
+}
+
+/**
+ * Verifies a chat message, searching for atcommands, checking if the sender
+ * character can chat, and updating the idle timer.
+ *
+ * @param sd The sender character.
+ * @param message The message text.
+ * @return Whether the message is a valid chat message.
+ */
+bool pc_process_chat_message(struct map_session_data *sd, const char *message)
+{
+ nullpo_retr(false, sd);
+ if (atcommand->exec(sd->fd, sd, message, true)) {
+ return false;
+ }
+
+ if (!pc->can_talk(sd)) {
+ return false;
+ }
+
+ if (battle_config.min_chat_delay != 0) {
+ if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0) {
+ return false;
+ }
+ sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
+ }
+
+ pc->update_idle_time(sd, BCIDLE_CHAT);
+
+ return true;
+}
+
+/**
+ * Checks a chat message, scanning for the Super Novice prayer sequence.
+ *
+ * If a match is found, the angel is invoked or the counter is incremented as
+ * appropriate.
+ *
+ * @param sd The sender character.
+ * @param message The message text.
+ */
+void pc_check_supernovice_call(struct map_session_data *sd, const char *message)
+{
+ unsigned int next = pc->nextbaseexp(sd);
+ int percent = 0;
+
+ nullpo_retv(sd);
+ nullpo_retv(message);
+ if ((sd->job & MAPID_UPPERMASK) != MAPID_SUPER_NOVICE)
+ return;
+ if (next == 0)
+ next = pc->thisbaseexp(sd);
+ if (next == 0)
+ return;
+
+ // 0%, 10%, 20%, ...
+ percent = (int)( ( (float)sd->status.base_exp/(float)next )*1000. );
+ if ((battle_config.snovice_call_type != 0 || percent != 0) && (percent%100) == 0) {
+ // 10.0%, 20.0%, ..., 90.0%
+ switch (sd->state.snovice_call_flag) {
+ case 0:
+ if (strstr(message, msg_txt(1479))) // "Dear angel, can you hear my voice?"
+ sd->state.snovice_call_flag = 1;
+ break;
+ case 1:
+ {
+ char buf[256];
+ snprintf(buf, 256, msg_txt(1480), sd->status.name);
+ if (strstr(message, buf)) // "I am %s Super Novice~"
+ sd->state.snovice_call_flag = 2;
+ }
+ break;
+ case 2:
+ if (strstr(message, msg_txt(1481))) // "Help me out~ Please~ T_T"
+ sd->state.snovice_call_flag = 3;
+ break;
+ case 3:
+ sc_start(NULL, &sd->bl, status->skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill->get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex]
+ clif->skill_nodamage(&sd->bl, &sd->bl, MO_EXPLOSIONSPIRITS, 5, 1); // prayer always shows successful Lv5 cast and disregards noskill restrictions
+ sd->state.snovice_call_flag = 0;
+ break;
+ }
+ }
+}
+
void do_final_pc(void) {
db_destroy(pc->itemcd_db);
pc->at_db->destroy(pc->at_db,pc->autotrade_final);
@@ -11785,7 +12206,8 @@ void pc_defaults(void) {
pc->addspiritball = pc_addspiritball;
pc->delspiritball = pc_delspiritball;
pc->addfame = pc_addfame;
- pc->famerank = pc_famerank;
+ pc->fame_rank = pc_fame_rank;
+ pc->famelist_type = pc_famelist_type;
pc->set_hate_mob = pc_set_hate_mob;
pc->getmaxspiritball = pc_getmaxspiritball;
@@ -11857,6 +12279,9 @@ void pc_defaults(void) {
pc->db_checkid = pc_db_checkid;
pc->validate_levels = pc_validate_levels;
+ pc->check_supernovice_call = pc_check_supernovice_call;
+ pc->process_chat_message = pc_process_chat_message;
+
/**
* Autotrade persistency [Ind/Hercules <3]
**/
@@ -11869,6 +12294,8 @@ void pc_defaults(void) {
pc->check_job_name = pc_check_job_name;
pc->update_idle_time = pc_update_idle_time;
-
+
pc->have_magnifier = pc_have_magnifier;
+
+ pc->check_basicskill = pc_check_basicskill;
}