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.c1973
1 files changed, 1227 insertions, 746 deletions
diff --git a/src/map/pc.c b/src/map/pc.c
index 6b7d6c735..284a459e7 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -72,20 +72,11 @@ struct map_session_data* pc_get_dummy_sd(void)
{
struct map_session_data *dummy_sd;
CREATE(dummy_sd, struct map_session_data, 1);
- dummy_sd->group = pc_group_get_dummy_group(); // map_session_data.group is expected to be non-NULL at all times
+ dummy_sd->group = pcg->get_dummy_group(); // map_session_data.group is expected to be non-NULL at all times
return dummy_sd;
}
/**
- * Gets player's group level.
- * @see pc_group_get_level()
- */
-int pc_get_group_level(struct map_session_data *sd)
-{
- return pc_group_get_level(sd->group);
-}
-
-/**
* Sets player's group.
* Caller should handle error (preferably display message and disconnect).
* @param group_id Group ID
@@ -93,7 +84,7 @@ int pc_get_group_level(struct map_session_data *sd)
*/
int pc_set_group(struct map_session_data *sd, int group_id)
{
- GroupSettings *group = pc_group_id2group(group_id);
+ GroupSettings *group = pcg->id2group(group_id);
if (group == NULL)
return 1;
sd->group_id = group_id;
@@ -102,22 +93,14 @@ int pc_set_group(struct map_session_data *sd, int group_id)
}
/**
- * Checks if player has permission to perform action.
- */
-bool pc_has_permission(struct map_session_data *sd, enum e_pc_permission permission)
-{
- return ((sd->extra_temp_permissions&permission) != 0 || pc_group_has_permission(sd->group, permission));
-}
-
-/**
* Checks if commands used by player should be logged.
*/
bool pc_should_log_commands(struct map_session_data *sd)
{
- return pc_group_should_log_commands(sd->group);
+ return pcg->should_log_commands(sd->group);
}
-int pc_invincible_timer(int tid, unsigned int tick, int id, intptr_t data) {
+int pc_invincible_timer(int tid, int64 tick, int id, intptr_t data) {
struct map_session_data *sd;
if( (sd=(struct map_session_data *)map->id2sd(id)) == NULL || sd->bl.type!=BL_PC )
@@ -155,7 +138,7 @@ void pc_delinvincibletimer(struct map_session_data* sd)
}
}
-int pc_spiritball_timer(int tid, unsigned int tick, int id, intptr_t data) {
+int pc_spiritball_timer(int tid, int64 tick, int id, intptr_t data) {
struct map_session_data *sd;
int i;
@@ -213,7 +196,7 @@ int pc_addspiritball(struct map_session_data *sd,int interval,int max)
sd->spirit_timer[i] = tid;
sd->spiritball++;
if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
- clif->millenniumshield(sd,sd->spiritball);
+ clif->millenniumshield(&sd->bl,sd->spiritball);
else
clif->spiritball(&sd->bl);
@@ -252,7 +235,7 @@ int pc_delspiritball(struct map_session_data *sd,int count,int type)
if(!type) {
if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD )
- clif->millenniumshield(sd,sd->spiritball);
+ clif->millenniumshield(&sd->bl,sd->spiritball);
else
clif->spiritball(&sd->bl);
}
@@ -419,7 +402,7 @@ int pc_setrestartvalue(struct map_session_data *sd,int type) {
/*==========================================
Rental System
*------------------------------------------*/
-int pc_inventory_rental_end(int tid, unsigned int tick, int id, intptr_t data) {
+int pc_inventory_rental_end(int tid, int64 tick, int id, intptr_t data) {
struct map_session_data *sd = map->id2sd(id);
if( sd == NULL )
return 0;
@@ -443,11 +426,78 @@ int pc_inventory_rental_clear(struct map_session_data *sd)
return 1;
}
+/* 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;
+ /* Soon to be dropped, we got plans to integrate it with item db */
+ switch( nameid ) {
+ case ITEMID_REINS_OF_MOUNT:
+ status_change_end(&sd->bl,SC_ALL_RIDING,INVALID_TIMER);
+ break;
+ case ITEMID_LOVE_ANGEL:
+ if( sd->status.font == 1 ) {
+ sd->status.font = 0;
+ clif->font(sd);
+ }
+ break;
+ case ITEMID_SQUIRREL:
+ if( sd->status.font == 2 ) {
+ sd->status.font = 0;
+ clif->font(sd);
+ }
+ break;
+ case ITEMID_GOGO:
+ if( sd->status.font == 3 ) {
+ sd->status.font = 0;
+ clif->font(sd);
+ }
+ break;
+ case ITEMID_PICTURE_DIARY:
+ if( sd->status.font == 4 ) {
+ sd->status.font = 0;
+ clif->font(sd);
+ }
+ break;
+ case ITEMID_MINI_HEART:
+ if( sd->status.font == 5 ) {
+ sd->status.font = 0;
+ clif->font(sd);
+ }
+ break;
+ case ITEMID_NEWCOMER:
+ if( sd->status.font == 6 ) {
+ sd->status.font = 0;
+ clif->font(sd);
+ }
+ break;
+ case ITEMID_KID:
+ if( sd->status.font == 7 ) {
+ sd->status.font = 0;
+ clif->font(sd);
+ }
+ break;
+ case ITEMID_MAGIC_CASTLE:
+ if( sd->status.font == 8 ) {
+ sd->status.font = 0;
+ clif->font(sd);
+ }
+ break;
+ case ITEMID_BULGING_HEAD:
+ if( sd->status.font == 9 ) {
+ sd->status.font = 0;
+ clif->font(sd);
+ }
+ break;
+ }
+
+ clif->rental_expired(sd->fd, i, sd->status.inventory[i].nameid);
+ pc->delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER);
+}
void pc_inventory_rentals(struct map_session_data *sd)
{
int i, c = 0;
- unsigned int expire_tick, next_tick = UINT_MAX;
+ int64 expire_tick, next_tick = INT64_MAX;
for( i = 0; i < MAX_INVENTORY; i++ )
{ // Check for Rentals on Inventory
@@ -457,14 +507,9 @@ void pc_inventory_rentals(struct map_session_data *sd)
continue;
if( sd->status.inventory[i].expire_time <= time(NULL) ) {
- if( sd->status.inventory[i].nameid == ITEMID_REINS_OF_MOUNT
- && sd->sc.data[SC_ALL_RIDING] ) {
- status_change_end(&sd->bl,SC_ALL_RIDING,INVALID_TIMER);
- }
- clif->rental_expired(sd->fd, i, sd->status.inventory[i].nameid);
- pc->delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER);
+ pc->rental_expire(sd,i);
} else {
- expire_tick = (unsigned int)(sd->status.inventory[i].expire_time - time(NULL)) * 1000;
+ expire_tick = (int64)(sd->status.inventory[i].expire_time - time(NULL)) * 1000;
clif->rental_time(sd->fd, sd->status.inventory[i].nameid, (int)(expire_tick / 1000));
next_tick = min(expire_tick, next_tick);
c++;
@@ -498,14 +543,6 @@ void pc_inventory_rental_add(struct map_session_data *sd, int seconds)
sd->rental_timer = timer->add(timer->gettick() + min(tick,3600000), pc->inventory_rental_end, sd->bl.id, 0);
}
-/**
- * Determines if player can give / drop / trade / vend items
- */
-bool pc_can_give_items(struct map_session_data *sd)
-{
- return pc->has_permission(sd, PC_PERM_TRADE);
-}
-
/*==========================================
* prepares character for saving.
*------------------------------------------*/
@@ -608,9 +645,14 @@ int pc_equippoint(struct map_session_data *sd,int n)
if(sd->inventory_data[n]->look == W_DAGGER ||
sd->inventory_data[n]->look == W_1HSWORD ||
sd->inventory_data[n]->look == W_1HAXE) {
- if(ep == EQP_HAND_R && (pc->checkskill(sd,AS_LEFT) > 0 || (sd->class_&MAPID_UPPERMASK) == MAPID_ASSASSIN ||
- (sd->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO))//Kagerou and Oboro can dual wield daggers. [Rytech]
- return EQP_ARMS;
+ if( (pc->checkskill(sd,AS_LEFT) > 0 ||
+ (sd->class_&MAPID_UPPERMASK) == MAPID_ASSASSIN ||
+ (sd->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO) ) { //Kagerou and Oboro can dual wield daggers. [Rytech]
+ if( ep == EQP_HAND_R )
+ return EQP_ARMS;
+ if( ep == EQP_SHADOW_WEAPON )
+ return EQP_SHADOW_ARMS;
+ }
}
return ep;
}
@@ -857,7 +899,7 @@ int pc_isequip(struct map_session_data *sd,int n)
item = sd->inventory_data[n];
- if(pc->has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT))
+ if(pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT))
return 1;
if(item == NULL)
@@ -866,12 +908,10 @@ int pc_isequip(struct map_session_data *sd,int n)
clif->msg(sd, 0x6ED);
return 0;
}
-#ifdef RENEWAL
if(item->elvmax && sd->status.base_level > (unsigned int)item->elvmax){
clif->msg(sd, 0x6ED);
return 0;
}
-#endif
if(item->sex != 2 && sd->status.sex != item->sex)
return 0;
@@ -911,10 +951,10 @@ int pc_isequip(struct map_session_data *sd,int n)
return 0;
//Not usable by upper class. [Inkfish]
while( 1 ) {
- if( item->class_upper&1 && !(sd->class_&(JOBL_UPPER|JOBL_THIRD|JOBL_BABY)) ) break;
- if( item->class_upper&2 && sd->class_&(JOBL_UPPER|JOBL_THIRD) ) break;
- if( item->class_upper&4 && sd->class_&JOBL_BABY ) break;
- if( item->class_upper&8 && sd->class_&JOBL_THIRD ) break;
+ 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;
return 0;
}
@@ -927,11 +967,11 @@ int pc_isequip(struct map_session_data *sd,int n)
*------------------------------------------*/
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) {
int i;
- unsigned long tick = timer->gettick();
+ int64 tick = timer->gettick();
uint32 ip = session[sd->fd]->client_addr;
sd->login_id2 = login_id2;
-
+
if (pc->set_group(sd, group_id) != 0) {
ShowWarning("pc_authok: %s (AID:%d) logged in with unknown group id (%d)! kicking...\n",
st->name, sd->status.account_id, group_id);
@@ -977,6 +1017,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
sd->npc_timer_id = INVALID_TIMER;
sd->pvp_timer = INVALID_TIMER;
sd->fontcolor_tid = INVALID_TIMER;
+ sd->expiration_tid = INVALID_TIMER;
/**
* For the Secure NPC Timeout option (check config/Secure.h) [RR]
**/
@@ -997,7 +1038,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
sd->cansendmail_tick = tick;
sd->hchsysch_tick = tick;
- sd->idletime = last_tick;
+ sd->idletime = sockt->last_tick;
for(i = 0; i < MAX_SPIRITBALL; i++)
sd->spirit_timer[i] = INVALID_TIMER;
@@ -1053,6 +1094,9 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
sd->delayed_damage = 0;
+ if( battle_config.item_check )
+ sd->state.itemcheck = 1;
+
// Event Timers
for( i = 0; i < MAX_EVENTTIMER; i++ )
sd->eventtimer[i] = INVALID_TIMER;
@@ -1062,12 +1106,22 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
for( i = 0; i < 3; i++ )
sd->hate_mob[i] = -1;
- //warp player
+ sd->quest_log = NULL;
+ sd->num_quests = 0;
+ sd->avail_quests = 0;
+ sd->save_quest = false;
+
+ sd->var_db = i64db_alloc(DB_OPT_BASE);
+ sd->vars_dirty = false;
+ sd->vars_ok = false;
+ sd->vars_received = 0x0;
+
+ //warp player
if ((i=pc->setpos(sd,sd->status.last_point.map, sd->status.last_point.x, sd->status.last_point.y, CLR_OUTSIGHT)) != 0) {
ShowError ("Last_point_map %s - id %d not found (error code %d)\n", mapindex_id2name(sd->status.last_point.map), sd->status.last_point.map, i);
// try warping to a default map instead (church graveyard)
- if (pc->setpos(sd, mapindex_name2id(MAP_PRONTERA), 273, 354, CLR_OUTSIGHT) != 0) {
+ if (pc->setpos(sd, mapindex->name2id(MAP_PRONTERA), 273, 354, CLR_OUTSIGHT) != 0) {
// if we fail again
clif->authfail_fd(sd->fd, 0);
return false;
@@ -1104,11 +1158,8 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
clif->message(sd->fd, buf);
}
- // message of the limited time of the account
- if (expiration_time != 0) { // don't display if it's unlimited or unknow value
- char tmpstr[1024];
- strftime(tmpstr, sizeof(tmpstr) - 1, msg_txt(501), localtime(&expiration_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);
+ if (expiration_time != 0) {
+ sd->expiration_time = expiration_time;
}
/**
@@ -1126,7 +1177,12 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
* Check if player have any item cooldowns on
**/
pc->itemcd_do(sd,true);
-
+
+#ifdef GP_BOUND_ITEMS
+ if( sd->status.party_id == 0 )
+ pc->bound_clear(sd,IBT_PARTY);
+#endif
+
/* [Ind/Hercules] */
sd->sc_display = NULL;
sd->sc_display_count = 0;
@@ -1166,7 +1222,7 @@ int pc_set_hate_mob(struct map_session_data *sd, int pos, struct block_list *bl)
return 0; //Wrong size
}
sd->hate_mob[pos] = class_;
- pc_setglobalreg(sd,pc->sg_info[pos].hate_var,class_+1);
+ pc_setglobalreg(sd,script->add_str(pc->sg_info[pos].hate_var),class_+1);
clif->hate_info(sd, pos, class_, 1);
return 1;
}
@@ -1178,55 +1234,58 @@ int pc_reg_received(struct map_session_data *sd)
{
int i,j, idx = 0;
- sd->change_level_2nd = pc_readglobalreg(sd,"jobchange_level");
- sd->change_level_3rd = pc_readglobalreg(sd,"jobchange_level_3rd");
- sd->die_counter = pc_readglobalreg(sd,"PC_DIE_COUNTER");
+ sd->vars_ok = true;
+
+ sd->change_level_2nd = pc_readglobalreg(sd,script->add_str("jobchange_level"));
+ sd->change_level_3rd = pc_readglobalreg(sd,script->add_str("jobchange_level_3rd"));
+ sd->die_counter = pc_readglobalreg(sd,script->add_str("PC_DIE_COUNTER"));
// Cash shop
- sd->cashPoints = pc_readaccountreg(sd,"#CASHPOINTS");
- sd->kafraPoints = pc_readaccountreg(sd,"#KAFRAPOINTS");
+ sd->cashPoints = pc_readaccountreg(sd,script->add_str("#CASHPOINTS"));
+ sd->kafraPoints = pc_readaccountreg(sd,script->add_str("#KAFRAPOINTS"));
// Cooking Exp
- sd->cook_mastery = pc_readglobalreg(sd,"COOK_MASTERY");
+ sd->cook_mastery = pc_readglobalreg(sd,script->add_str("COOK_MASTERY"));
if( (sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON ) {
// Better check for class rather than skill to prevent "skill resets" from unsetting this
- sd->mission_mobid = pc_readglobalreg(sd,"TK_MISSION_ID");
- sd->mission_count = pc_readglobalreg(sd,"TK_MISSION_COUNT");
+ sd->mission_mobid = pc_readglobalreg(sd,script->add_str("TK_MISSION_ID"));
+ sd->mission_count = pc_readglobalreg(sd,script->add_str("TK_MISSION_COUNT"));
}
//SG map and mob read [Komurka]
for(i=0;i<MAX_PC_FEELHATE;i++) { //for now - someone need to make reading from txt/sql
- if ((j = pc_readglobalreg(sd,pc->sg_info[i].feel_var))!=0) {
+ if ((j = pc_readglobalreg(sd,script->add_str(pc->sg_info[i].feel_var)))!=0) {
sd->feel_map[i].index = j;
sd->feel_map[i].m = map->mapindex2mapid(j);
} else {
sd->feel_map[i].index = 0;
sd->feel_map[i].m = -1;
}
- sd->hate_mob[i] = pc_readglobalreg(sd,pc->sg_info[i].hate_var)-1;
+ sd->hate_mob[i] = pc_readglobalreg(sd,script->add_str(pc->sg_info[i].hate_var))-1;
}
if ((i = pc->checkskill(sd,RG_PLAGIARISM)) > 0) {
- sd->cloneskill_id = pc_readglobalreg(sd,"CLONE_SKILL");
+ sd->cloneskill_id = pc_readglobalreg(sd,script->add_str("CLONE_SKILL"));
if (sd->cloneskill_id > 0 && (idx = skill->get_index(sd->cloneskill_id))) {
sd->status.skill[idx].id = sd->cloneskill_id;
- sd->status.skill[idx].lv = pc_readglobalreg(sd,"CLONE_SKILL_LV");
+ sd->status.skill[idx].lv = pc_readglobalreg(sd,script->add_str("CLONE_SKILL_LV"));
if (sd->status.skill[idx].lv > i)
sd->status.skill[idx].lv = i;
sd->status.skill[idx].flag = SKILL_FLAG_PLAGIARIZED;
}
}
if ((i = pc->checkskill(sd,SC_REPRODUCE)) > 0) {
- sd->reproduceskill_id = pc_readglobalreg(sd,"REPRODUCE_SKILL");
+ sd->reproduceskill_id = pc_readglobalreg(sd,script->add_str("REPRODUCE_SKILL"));
if( sd->reproduceskill_id > 0 && (idx = skill->get_index(sd->reproduceskill_id))) {
sd->status.skill[idx].id = sd->reproduceskill_id;
- sd->status.skill[idx].lv = pc_readglobalreg(sd,"REPRODUCE_SKILL_LV");
+ sd->status.skill[idx].lv = pc_readglobalreg(sd,script->add_str("REPRODUCE_SKILL_LV"));
if( i < sd->status.skill[idx].lv)
sd->status.skill[idx].lv = i;
sd->status.skill[idx].flag = SKILL_FLAG_PLAGIARIZED;
}
}
+
//Weird... maybe registries were reloaded?
if (sd->state.active)
return 0;
@@ -1256,7 +1315,7 @@ int pc_reg_received(struct map_session_data *sd)
pc->load_combo(sd);
- status_calc_pc(sd,1);
+ status_calc_pc(sd,SCO_FIRST|SCO_FORCE);
chrif->scdata_request(sd->status.account_id, sd->status.char_id);
intif->Mail_requestinbox(sd->status.char_id, 0); // MAIL SYSTEM - Request Mail Inbox
@@ -1267,8 +1326,6 @@ int pc_reg_received(struct map_session_data *sd)
clif->pLoadEndAck(sd->fd, sd);
}
- pc->inventory_rentals(sd);
-
if( sd->sc.option & OPTION_INVISIBLE ) {
sd->vd.class_ = INVISIBLE_CLASS;
clif->message(sd->fd, msg_txt(11)); // Invisible: On
@@ -1284,7 +1341,7 @@ int pc_reg_received(struct map_session_data *sd)
if( npc->motd ) /* [Ind/Hercules] */
script->run(npc->motd->u.scr.script, 0, sd->bl.id, npc->fake_nd->bl.id);
-
+
return 1;
}
@@ -1372,7 +1429,7 @@ int pc_calc_skilltree(struct map_session_data *sd)
}
}
- if( pc->has_permission(sd, PC_PERM_ALL_SKILL) ) {
+ if( pc_has_permission(sd, PC_PERM_ALL_SKILL) ) {
for( i = 0; i < MAX_SKILL; i++ ) {
switch(skill->db[i].nameid) {
/**
@@ -1393,7 +1450,6 @@ int pc_calc_skilltree(struct map_session_data *sd)
case WL_SUMMON_ATK_GROUND:
case LG_OVERBRAND_BRANDISH:
case LG_OVERBRAND_PLUSATK:
- case WM_SEVERE_RAINSTORM_MELEE:
continue;
default:
break;
@@ -1568,7 +1624,7 @@ int pc_calc_skilltree_normalize_job(struct map_session_data *sd)
int skill_point, novice_skills;
int c = sd->class_;
- if (!battle_config.skillup_limit || pc->has_permission(sd, PC_PERM_ALL_SKILL))
+ if (!battle_config.skillup_limit || pc_has_permission(sd, PC_PERM_ALL_SKILL))
return c;
skill_point = pc->calc_skillpoint(sd);
@@ -1606,7 +1662,7 @@ int pc_calc_skilltree_normalize_job(struct map_session_data *sd)
}
- pc_setglobalreg (sd, "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)) {
@@ -1619,7 +1675,7 @@ int pc_calc_skilltree_normalize_job(struct map_session_data *sd)
- (sd->status.job_level - 1)
- (sd->change_level_2nd - 1)
- novice_skills;
- pc_setglobalreg (sd, "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)) {
@@ -1663,9 +1719,9 @@ int pc_updateweightstatus(struct map_session_data *sd)
// start new status change
if( new_overweight == 1 )
- sc_start(&sd->bl, SC_WEIGHTOVER50, 100, 0, 0);
+ sc_start(NULL,&sd->bl, SC_WEIGHTOVER50, 100, 0, 0);
else if( new_overweight == 2 )
- sc_start(&sd->bl, SC_WEIGHTOVER90, 100, 0, 0);
+ sc_start(NULL,&sd->bl, SC_WEIGHTOVER90, 100, 0, 0);
// update overweight status
sd->regen.state.overweight = new_overweight;
@@ -1711,9 +1767,8 @@ int pc_disguise(struct map_session_data *sd, int class_) {
}
if (sd->chatID) {
struct chat_data* cd;
- nullpo_retr(1, sd);
- cd = (struct chat_data*)map->id2bl(sd->chatID);
- if( cd != NULL || (struct block_list*)sd == cd->owner )
+
+ if( (cd = (struct chat_data*)map->id2bl(sd->chatID)) )
clif->dispchat(cd,0);
}
}
@@ -1928,8 +1983,8 @@ int pc_delautobonus(struct map_session_data* sd, struct s_autobonus *autobonus,c
if( autobonus[i].bonus_script )
{
int j;
- ARR_FIND( 0, EQI_MAX-1, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus[i].pos );
- if( j < EQI_MAX-1 )
+ ARR_FIND( 0, EQI_MAX, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus[i].pos );
+ if( j < EQI_MAX )
script->run_autobonus(autobonus[i].bonus_script,sd->bl.id,sd->equip_index[j]);
}
continue;
@@ -1959,19 +2014,19 @@ int pc_exeautobonus(struct map_session_data *sd,struct s_autobonus *autobonus)
if( autobonus->other_script )
{
int j;
- ARR_FIND( 0, EQI_MAX-1, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus->pos );
- if( j < EQI_MAX-1 )
+ ARR_FIND( 0, EQI_MAX, j, sd->equip_index[j] >= 0 && sd->status.inventory[sd->equip_index[j]].equip == autobonus->pos );
+ if( j < EQI_MAX )
script->run_autobonus(autobonus->other_script,sd->bl.id,sd->equip_index[j]);
}
autobonus->active = timer->add(timer->gettick()+autobonus->duration, pc->endautobonus, sd->bl.id, (intptr_t)autobonus);
sd->state.autobonus |= autobonus->pos;
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
return 0;
}
-int pc_endautobonus(int tid, unsigned int tick, int id, intptr_t data) {
+int pc_endautobonus(int tid, int64 tick, int id, intptr_t data) {
struct map_session_data *sd = map->id2sd(id);
struct s_autobonus *autobonus = (struct s_autobonus *)data;
@@ -1980,7 +2035,7 @@ int pc_endautobonus(int tid, unsigned int tick, int id, intptr_t data) {
autobonus->active = INVALID_TIMER;
sd->state.autobonus &= ~autobonus->pos;
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
return 0;
}
@@ -3487,7 +3542,7 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) {
} else
clif->addskill(sd,id);
if( !skill->db[index].inf ) //Only recalculate for passive skills.
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_NONE);
break;
case 1: //Item bonus skill.
if( sd->status.skill[index].id == id ) {
@@ -3521,7 +3576,7 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) {
} else
clif->addskill(sd,id);
if( !skill->db[index].inf ) //Only recalculate for passive skills.
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_NONE);
break;
default: //Unknown flag?
return 0;
@@ -3697,7 +3752,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,strlen(output));
}
return 0;
@@ -3732,14 +3787,14 @@ int pc_paycash(struct map_session_data *sd, int price, int points)
return -1;
}
- pc_setaccountreg(sd, "#CASHPOINTS", sd->cashPoints-cash);
- pc_setaccountreg(sd, "#KAFRAPOINTS", sd->kafraPoints-points);
+ pc_setaccountreg(sd, script->add_str("#CASHPOINTS"), sd->cashPoints-cash);
+ pc_setaccountreg(sd, script->add_str("#KAFRAPOINTS"), sd->kafraPoints-points);
if( battle_config.cashshop_show_points )
{
char output[128];
sprintf(output, msg_txt(504), points, cash, sd->kafraPoints, sd->cashPoints);
- clif->disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output, strlen(output));
}
return cash+points;
}
@@ -3759,12 +3814,12 @@ int pc_getcash(struct map_session_data *sd, int cash, int points)
cash = MAX_ZENY-sd->cashPoints;
}
- pc_setaccountreg(sd, "#CASHPOINTS", sd->cashPoints+cash);
+ pc_setaccountreg(sd, script->add_str("#CASHPOINTS"), sd->cashPoints+cash);
if( battle_config.cashshop_show_points )
{
sprintf(output, msg_txt(505), cash, sd->cashPoints);
- clif->disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output, strlen(output));
}
return cash;
}
@@ -3782,12 +3837,12 @@ int pc_getcash(struct map_session_data *sd, int cash, int points)
points = MAX_ZENY-sd->kafraPoints;
}
- pc_setaccountreg(sd, "#KAFRAPOINTS", sd->kafraPoints+points);
+ pc_setaccountreg(sd, script->add_str("#KAFRAPOINTS"), sd->kafraPoints+points);
if( battle_config.cashshop_show_points )
{
sprintf(output, msg_txt(506), points, sd->kafraPoints);
- clif->disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output, strlen(output));
}
return points;
}
@@ -3825,7 +3880,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,strlen(output));
}
return 0;
@@ -3880,14 +3935,37 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
if(sd->weight + w > sd->max_weight)
return 2;
+ if( item_data->bound ) {
+ switch( (enum e_item_bound_type)item_data->bound ) {
+ case IBT_CHARACTER:
+ case IBT_ACCOUNT:
+ break; /* no restrictions */
+ case IBT_PARTY:
+ if( !sd->status.party_id ) {
+ ShowError("pc_additem: can't add party_bound item to character without party!\n");
+ ShowError("pc_additem: %s - x%d %s (%d)\n",sd->status.name,amount,data->jname,data->nameid);
+ return 7;/* need proper code? */
+ }
+ break;
+ case IBT_GUILD:
+ if( !sd->status.guild_id ) {
+ ShowError("pc_additem: can't add guild_bound item to character without guild!\n");
+ ShowError("pc_additem: %s - x%d %s (%d)\n",sd->status.name,amount,data->jname,data->nameid);
+ return 7;/* need proper code? */
+ }
+ break;
+ }
+ }
+
i = MAX_INVENTORY;
- if( itemdb->isstackable2(data) && item_data->expire_time == 0 )
- { // Stackable | Non Rental
- for( i = 0; i < MAX_INVENTORY; i++ )
- {
- if( sd->status.inventory[i].nameid == item_data->nameid && memcmp(&sd->status.inventory[i].card, &item_data->card, sizeof(item_data->card)) == 0 )
- {
+ // Stackable | Non Rental
+ if( itemdb->isstackable2(data) && item_data->expire_time == 0 ) {
+ for( i = 0; i < MAX_INVENTORY; i++ ) {
+ if( sd->status.inventory[i].nameid == item_data->nameid &&
+ sd->status.inventory[i].bound == item_data->bound &&
+ sd->status.inventory[i].expire_time == 0 &&
+ memcmp(&sd->status.inventory[i].card, &item_data->card, sizeof(item_data->card)) == 0 ) {
if( amount > MAX_AMOUNT - sd->status.inventory[i].amount || ( data->stack.inventory && amount > data->stack.amount - sd->status.inventory[i].amount ) )
return 5;
sd->status.inventory[i].amount += amount;
@@ -3904,9 +3982,11 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
return 4;
memcpy(&sd->status.inventory[i], item_data, sizeof(sd->status.inventory[0]));
- // clear equips field first, just in case
+ // clear equip and favorite fields first, just in case
if( item_data->equip )
sd->status.inventory[i].equip = 0;
+ if( item_data->favorite )
+ sd->status.inventory[i].favorite = 0;
sd->status.inventory[i].amount = amount;
sd->inventory_data[i] = data;
@@ -3927,8 +4007,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
/* rental item check */
if( item_data->expire_time ) {
if( time(NULL) > item_data->expire_time ) {
- clif->rental_expired(sd->fd, i, sd->status.inventory[i].nameid);
- pc->delitem(sd, i, sd->status.inventory[i].amount, 1, 0, LOG_TYPE_OTHER);
+ pc->rental_expire(sd,i);
} else {
int seconds = (int)( item_data->expire_time - time(NULL) );
clif->rental_time(sd->fd, sd->status.inventory[i].nameid, seconds);
@@ -4026,7 +4105,7 @@ int pc_dropitem(struct map_session_data *sd,int n,int amount)
int pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem)
{
int flag=0;
- unsigned int tick = timer->gettick();
+ int64 tick = timer->gettick();
struct map_session_data *first_sd = NULL,*second_sd = NULL,*third_sd = NULL;
struct party_data *p=NULL;
@@ -4109,95 +4188,98 @@ int pc_isUseitem(struct map_session_data *sd,int n)
if( !item->script ) //if it has no script, you can't really consume it!
return 0;
- if( (item->item_usage.flag&NOUSE_SITTING) && (pc_issit(sd) == 1) && (pc->get_group_level(sd) < item->item_usage.override) ) {
+ if( (item->item_usage.flag&NOUSE_SITTING) && (pc_issit(sd) == 1) && (pc_get_group_level(sd) < item->item_usage.override) ) {
clif->msgtable(sd->fd,0x297);
//clif->colormes(sd->fd,COLOR_WHITE,msg_txt(1474));
return 0; // You cannot use this item while sitting.
}
- switch( nameid ) //@TODO, lot oh harcoded nameid here
- {
- case 605: // Anodyne
+ if (sd->state.storage_flag && item->type != IT_CASH) {
+ clif->colormes(sd->fd, COLOR_RED, msg_txt(1475));
+ return 0; // You cannot use this item while storage is open.
+ }
+
+ 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;
- case 606:
+ case ITEMID_ALOEBERA:
if( pc_issit(sd) )
return 0;
break;
- case 601: // Fly Wing
- case 12212: // Giant Fly Wing
+ 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);
return 0;
}
- case 602: // ButterFly Wing
- case 14527: // Dungeon Teleport Scroll
- case 14581: // Dungeon Teleport Scroll
- case 14582: // Yellow Butterfly Wing
- case 14583: // Green Butterfly Wing
- case 14584: // Red Butterfly Wing
- case 14585: // Blue Butterfly Wing
- case 14591: // Siege Teleport Scroll
+ case ITEMID_WING_OF_BUTTERFLY:
+ case ITEMID_DUN_TELE_SCROLL1:
+ case ITEMID_DUN_TELE_SCROLL2:
+ case ITEMID_WOB_RUNE: // Yellow Butterfly Wing
+ case ITEMID_WOB_SCHWALTZ: // Green Butterfly Wing
+ case ITEMID_WOB_RACHEL: // Red Butterfly Wing
+ case ITEMID_WOB_LOCAL: // Blue Butterfly Wing
+ case ITEMID_SIEGE_TELEPORT_SCROLL:
if( sd->duel_group && !battle_config.duel_allow_teleport )
{
clif->message(sd->fd, msg_txt(663));
return 0;
}
- if( nameid != 601 && nameid != 12212 && map->list[sd->bl.m].flag.noreturn )
+ if( nameid != ITEMID_WING_OF_FLY && nameid != ITEMID_GIANT_FLY_WING && map->list[sd->bl.m].flag.noreturn )
return 0;
break;
- case 604: // Dead Branch
- case 12024: // Red Pouch
- case 12103: // Bloody Branch
- case 12109: // Poring Box
+ case ITEMID_BRANCH_OF_DEAD_TREE:
+ case ITEMID_RED_POUCH_OF_SURPRISE:
+ case ITEMID_BLOODY_DEAD_BRANCH:
+ case ITEMID_PORING_BOX:
if( map->list[sd->bl.m].flag.nobranch || map_flag_gvg2(sd->bl.m) )
return 0;
break;
- case 12210: // Bubble Gum
- case 12264: // Comp Bubble Gum
+ case ITEMID_BUBBLE_GUM:
+ case ITEMID_COMP_BUBBLE_GUM:
if( sd->sc.data[SC_CASH_RECEIVEITEM] )
return 0;
break;
- case 12208: // Battle Manual
- case 12263: // Comp Battle Manual
- case 12312: // Thick Battle Manual
- case 12705: // Noble Nameplate
- case 14532: // Battle_Manual25
- case 14533: // Battle_Manual100
- case 14545: // Battle_Manual300
+ case ITEMID_BATTLE_MANUAL:
+ case ITEMID_COMP_BATTLE_MANUAL:
+ case ITEMID_THICK_MANUAL50:
+ case ITEMID_NOBLE_NAMEPLATE:
+ case ITEMID_BATTLE_MANUAL25:
+ case ITEMIDBATTLE_MANUAL100:
+ case ITEMID_BATTLE_MANUAL_X3:
if( sd->sc.data[SC_CASH_PLUSEXP] )
return 0;
break;
- case 14592: // JOB_Battle_Manual
+ case ITEMID_JOB_MANUAL50:
if( sd->sc.data[SC_CASH_PLUSONLYJOBEXP] )
return 0;
break;
// Mercenary Items
-
- case 12184: // Mercenary's Red Potion
- case 12185: // Mercenary's Blue Potion
- case 12241: // Mercenary's Concentration Potion
- case 12242: // Mercenary's Awakening Potion
- case 12243: // Mercenary's Berserk Potion
+ case ITEMID_MERCENARY_RED_POTION:
+ case ITEMID_MERCENARY_BLUE_POTION:
+ case ITEMID_M_CENTER_POTION:
+ case ITEMID_M_AWAKENING_POTION:
+ case ITEMID_M_BERSERK_POTION:
if( sd->md == NULL || sd->md->db == NULL )
return 0;
- if (sd->md->sc.data[SC_BERSERK] || sd->md->sc.data[SC_SATURDAY_NIGHT_FEVER])
+ if (sd->md->sc.data[SC_BERSERK])
return 0;
- if( nameid == 12242 && sd->md->db->lv < 40 )
+ if( nameid == ITEMID_M_AWAKENING_POTION && sd->md->db->lv < 40 )
return 0;
- if( nameid == 12243 && sd->md->db->lv < 80 )
+ if( nameid == ITEMID_M_BERSERK_POTION && sd->md->db->lv < 80 )
return 0;
break;
- case 12213: //Neuralizer
+ case ITEMID_NEURALIZER:
if( !map->list[sd->bl.m].flag.reset )
return 0;
break;
}
- if( nameid >= 12153 && nameid <= 12182 && sd->md != NULL )
- return 0; // Mercenary Scrolls
+ if( nameid >= ITEMID_BOW_MERCENARY_SCROLL1 && nameid <= ITEMID_SPEARMERCENARY_SCROLL10 && sd->md != NULL ) // Mercenary Scrolls
+ return 0;
/**
* Only Rune Knights may use runes
@@ -4210,10 +4292,15 @@ int pc_isUseitem(struct map_session_data *sd,int n)
else if( itemdb_is_poison(nameid) && (sd->class_&MAPID_THIRDMASK) != MAPID_GUILLOTINE_CROSS )
return 0;
- if( (item->package || item->group) && pc_is90overweight(sd) ) {
- //##TODO## find official response to this
- clif->colormes(sd->fd,COLOR_RED,msg_txt(1477));// Item cannot be open when overweight by 90%
- return 0;
+ if( item->package || item->group ) {
+ if( pc_is90overweight(sd) ) {
+ clif->msgtable(sd->fd,ITEM_CANT_OBTAIN_WEIGHT);
+ return 0;
+ }
+ if( !pc->inventoryblank(sd) ) {
+ clif->colormes(sd->fd,COLOR_RED,msg_txt(1477));
+ return 0;
+ }
}
//Gender check
@@ -4225,12 +4312,10 @@ int pc_isUseitem(struct map_session_data *sd,int n)
return 0;
}
-#ifdef RENEWAL
if(item->elvmax && sd->status.base_level > (unsigned int)item->elvmax){
clif->msg(sd, 0x6EE);
return 0;
}
-#endif
//Not equipable by class. [Skotlex]
if (!(
@@ -4242,30 +4327,25 @@ int pc_isUseitem(struct map_session_data *sd,int n)
//Not usable by upper class. [Haru]
while( 1 ) {
// Normal classes (no upper, no baby, no third classes)
- if( item->class_upper&0x01 && !(sd->class_&(JOBL_UPPER|JOBL_THIRD|JOBL_BABY)) ) break;
+ if( item->class_upper&ITEMUPPER_NORMAL && !(sd->class_&(JOBL_UPPER|JOBL_THIRD|JOBL_BABY)) ) break;
#ifdef RENEWAL
// Upper classes (no third classes)
- if( item->class_upper&0x02 && sd->class_&JOBL_UPPER && !(sd->class_&JOBL_THIRD) ) break;
+ if( item->class_upper&ITEMUPPER_UPPER && sd->class_&JOBL_UPPER && !(sd->class_&JOBL_THIRD) ) break;
#else
//pre-re has no use for the extra, so we maintain the previous for backwards compatibility
- if( item->class_upper&0x02 && sd->class_&(JOBL_UPPER|JOBL_THIRD) ) break;
+ if( item->class_upper&ITEMUPPER_UPPER && sd->class_&(JOBL_UPPER|JOBL_THIRD) ) break;
#endif
// Baby classes (no third classes)
- if( item->class_upper&0x04 && sd->class_&JOBL_BABY && !(sd->class_&JOBL_THIRD) ) break;
+ if( item->class_upper&ITEMUPPER_BABY && sd->class_&JOBL_BABY && !(sd->class_&JOBL_THIRD) ) break;
// Third classes (no upper, no baby classes)
- if( item->class_upper&0x08 && sd->class_&JOBL_THIRD && !(sd->class_&(JOBL_UPPER|JOBL_BABY)) ) break;
+ if( item->class_upper&ITEMUPPER_THIRD && sd->class_&JOBL_THIRD && !(sd->class_&(JOBL_UPPER|JOBL_BABY)) ) break;
// Upper third classes
- if( item->class_upper&0x10 && sd->class_&JOBL_THIRD && sd->class_&JOBL_UPPER ) break;
+ if( item->class_upper&ITEMUPPER_THURDUPPER && sd->class_&JOBL_THIRD && sd->class_&JOBL_UPPER ) break;
// Baby third classes
- if( item->class_upper&0x20 && sd->class_&JOBL_THIRD && sd->class_&JOBL_BABY ) break;
+ if( item->class_upper&ITEMUPPER_THIRDBABY && sd->class_&JOBL_THIRD && sd->class_&JOBL_BABY ) break;
return 0;
}
- //Dead Branch & Bloody Branch & Porings Box
- // FIXME: outdated, use constants or database
- if( nameid == 604 || nameid == 12103 || nameid == 12109 )
- logs->branch(sd);
-
return 1;
}
@@ -4276,7 +4356,7 @@ int pc_isUseitem(struct map_session_data *sd,int n)
* 1 = success
*------------------------------------------*/
int pc_useitem(struct map_session_data *sd,int n) {
- unsigned int tick = timer->gettick();
+ int64 tick = timer->gettick();
int amount, nameid, i;
struct script_code *item_script;
@@ -4308,9 +4388,12 @@ int pc_useitem(struct map_session_data *sd,int n) {
sd->sc.data[SC_TRICKDEAD] ||
sd->sc.data[SC_HIDING] ||
sd->sc.data[SC__SHADOWFORM] ||
+ sd->sc.data[SC__INVISIBILITY] ||
sd->sc.data[SC__MANHOLE] ||
sd->sc.data[SC_KG_KAGEHUMI] ||
sd->sc.data[SC_WHITEIMPRISON] ||
+ sd->sc.data[SC_DEEP_SLEEP] ||
+ sd->sc.data[SC_SATURDAY_NIGHT_FEVER] ||
(sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOITEM)
))
return 0;
@@ -4336,14 +4419,13 @@ int pc_useitem(struct map_session_data *sd,int n) {
return 0;
if( sd->inventory_data[n]->delay > 0 ) {
- int i;
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 = DIFF_TICK(sd->item_delay[i].tick, tick)/1000;
+ int e_tick = (int)(DIFF_TICK(sd->item_delay[i].tick, tick)/1000);
clif->msgtable_num(sd->fd, 0x746, e_tick + 1); // [%d] seconds left until you can use
return 0; // Delay has not expired yet
}
@@ -4376,6 +4458,10 @@ int pc_useitem(struct map_session_data *sd,int n) {
}
}
+ //Dead Branch & Bloody Branch & Porings Box
+ if( nameid == ITEMID_BRANCH_OF_DEAD_TREE || nameid == ITEMID_BLOODY_DEAD_BRANCH || nameid == ITEMID_PORING_BOX )
+ logs->branch(sd);
+
sd->itemid = sd->status.inventory[n].nameid;
sd->itemindex = n;
if(sd->catch_target_class != -1) //Abort pet catching.
@@ -4439,8 +4525,8 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
return 1;
}
- if( !itemdb_cancartstore(item_data, pc->get_group_level(sd)) )
- { // Check item trade restrictions [Skotlex]
+ 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 [Skotlex]
clif->message (sd->fd, msg_txt(264));
return 1;/* TODO: there is no official response to this? */
}
@@ -4452,8 +4538,8 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
if( itemdb->isstackable2(data) && !item_data->expire_time )
{
ARR_FIND( 0, MAX_CART, i,
- sd->status.cart[i].nameid == item_data->nameid &&
- sd->status.cart[i].card[0] == item_data->card[0] && sd->status.cart[i].card[1] == item_data->card[1] &&
+ sd->status.cart[i].nameid == item_data->nameid && sd->status.cart[i].bound == item_data->bound &&
+ sd->status.cart[i].card[0] == item_data->card[0] && sd->status.cart[i].card[1] == item_data->card[1] &&
sd->status.cart[i].card[2] == item_data->card[2] && sd->status.cart[i].card[3] == item_data->card[3] );
};
@@ -4586,7 +4672,39 @@ 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) {
+ int i;
+
+ switch( type ) {
+ /* both restricted to inventory */
+ case IBT_PARTY:
+ case IBT_CHARACTER:
+ for( i = 0; i < MAX_INVENTORY; i++ ){
+ if( sd->status.inventory[i].bound == type ) {
+ pc->delitem(sd,i,sd->status.inventory[i].amount,0,1,LOG_TYPE_OTHER);
+ }
+ }
+ break;
+ case IBT_ACCOUNT:
+ ShowError("Helllo! You reached pc_bound_clear for IBT_ACCOUNT, unfortunately no scenario was expected for this!\n");
+ break;
+ case IBT_GUILD: {
+ struct guild_storage *gstor = gstorage->id2storage(sd->status.guild_id);
+
+ for( i = 0; i < MAX_INVENTORY; i++ ){
+ if(sd->status.inventory[i].bound == type) {
+ if( gstor )
+ gstorage->additem(sd,gstor,&sd->status.inventory[i],sd->status.inventory[i].amount);
+ pc->delitem(sd,i,sd->status.inventory[i].amount,0,1,gstor?LOG_TYPE_GSTORAGE:LOG_TYPE_OTHER);
+ }
+ }
+ if( gstor )
+ gstorage->close(sd);
+ }
+ break;
+ }
+
+}
/*==========================================
* Display item stolen msg to player sd
*------------------------------------------*/
@@ -4690,14 +4808,16 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skil
return 1;
}
-/*==========================================
- * Stole zeny from bl (mob)
- * return
- * 0 = fail
- * 1 = success
- *------------------------------------------*/
-int pc_steal_coin(struct map_session_data *sd,struct block_list *target) {
- int rate,skill_lv;
+/**
+ * Steals zeny from a monster through the RG_STEALCOIN skill.
+ *
+ * @param sd Source character
+ * @param target Target monster
+ *
+ * @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;
struct mob_data *md;
if(!sd || !target || target->type != BL_MOB)
return 0;
@@ -4709,15 +4829,14 @@ int pc_steal_coin(struct map_session_data *sd,struct block_list *target) {
if( mob_is_treasure(md) )
return 0;
- // FIXME: This formula is either custom or outdated.
- skill_lv = pc->checkskill(sd,RG_STEALCOIN)*10;
- rate = skill_lv + (sd->status.base_level - md->level)*3 + sd->battle_status.dex*2 + sd->battle_status.luk*2;
+ 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*10 + rnd()%100;
+ 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]
pc->getzeny(sd, amount, LOG_TYPE_STEAL, NULL);
md->state.steal_coin_flag = 1;
- return 1;
+ return amount;
}
return 0;
}
@@ -4729,13 +4848,13 @@ int pc_steal_coin(struct map_session_data *sd,struct block_list *target) {
* 1 - Invalid map index.
* 2 - Map not in this map-server, and failed to locate alternate map-server.
*------------------------------------------*/
-int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y, clr_type clrtype) {
+int pc_setpos(struct map_session_data* sd, unsigned short map_index, int x, int y, clr_type clrtype) {
int16 m;
nullpo_ret(sd);
- if( !mapindex || !mapindex_id2name(mapindex) || ( m = map->mapindex2mapid(mapindex) ) == -1 ) {
- ShowDebug("pc_setpos: Passed mapindex(%d) is invalid!\n", mapindex);
+ if( !map_index || !mapindex_id2name(map_index) || ( m = map->mapindex2mapid(map_index) ) == -1 ) {
+ ShowDebug("pc_setpos: Passed mapindex(%d) is invalid!\n", map_index);
return 1;
}
@@ -4759,7 +4878,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
}
if( i != sd->instances ) {
m = instance->list[sd->instance[i]].map[j];
- mapindex = map_id2index(m);
+ map_index = map_id2index(m);
stop = true;
}
}
@@ -4773,7 +4892,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
}
if( i != p->instances ) {
m = instance->list[p->instance[i]].map[j];
- mapindex = map_id2index(m);
+ map_index = map_id2index(m);
stop = true;
}
}
@@ -4787,13 +4906,22 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
}
if( i != sd->guild->instances ) {
m = instance->list[sd->guild->instance[i]].map[j];
- mapindex = map_id2index(m);
- stop = true;
+ map_index = map_id2index(m);
+ //stop = true; Uncomment if adding new checks
}
}
+
+ /* we hit a instance, if empty we populate the spawn data */
+ if( map->list[m].instance_id >= 0 && instance->list[map->list[m].instance_id].respawn.map == 0 &&
+ instance->list[map->list[m].instance_id].respawn.x == 0 &&
+ instance->list[map->list[m].instance_id].respawn.y == 0) {
+ instance->list[map->list[m].instance_id].respawn.map = map_index;
+ instance->list[map->list[m].instance_id].respawn.x = x;
+ instance->list[map->list[m].instance_id].respawn.y = y;
+ }
}
- sd->state.changemap = (sd->mapindex != mapindex);
+ sd->state.changemap = (sd->mapindex != map_index);
sd->state.warping = 1;
sd->state.workinprogress = 0;
if( sd->state.changemap ) { // Misc map-changing settings
@@ -4819,6 +4947,10 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
status_change_end(&sd->bl, SC_MOON_COMFORT, INVALID_TIMER);
status_change_end(&sd->bl, SC_STAR_COMFORT, INVALID_TIMER);
status_change_end(&sd->bl, SC_MIRACLE, INVALID_TIMER);
+ status_change_end(&sd->bl, SC_NEUTRALBARRIER_MASTER, INVALID_TIMER);//Will later check if this is needed. [Rytech]
+ status_change_end(&sd->bl, SC_NEUTRALBARRIER, INVALID_TIMER);
+ status_change_end(&sd->bl, SC_STEALTHFIELD_MASTER, INVALID_TIMER);
+ status_change_end(&sd->bl, SC_STEALTHFIELD, INVALID_TIMER);
if (sd->sc.data[SC_KNOWLEDGE]) {
struct status_change_entry *sce = sd->sc.data[SC_KNOWLEDGE];
if (sce->timer != INVALID_TIMER)
@@ -4856,7 +4988,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
uint32 ip;
uint16 port;
//if can't find any map-servers, just abort setting position.
- if(!sd->mapindex || map->mapname2ipport(mapindex,&ip,&port))
+ if(!sd->mapindex || map->mapname2ipport(map_index,&ip,&port))
return 2;
if (sd->npc_id)
@@ -4864,7 +4996,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
npc->script_event(sd, NPCE_LOGOUT);
//remove from map, THEN change x/y coordinates
unit->remove_map_pc(sd,clrtype);
- sd->mapindex = mapindex;
+ sd->mapindex = map_index;
sd->bl.x=x;
sd->bl.y=y;
pc->clean_skilltree(sd);
@@ -4878,7 +5010,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
}
if( x < 0 || x >= map->list[m].xs || y < 0 || y >= map->list[m].ys ) {
- ShowError("pc_setpos: attempt to place player %s (%d:%d) on invalid coordinates (%s-%d,%d)\n", sd->status.name, sd->status.account_id, sd->status.char_id, mapindex_id2name(mapindex),x,y);
+ ShowError("pc_setpos: attempt to place player %s (%d:%d) on invalid coordinates (%s-%d,%d)\n", sd->status.name, sd->status.account_id, sd->status.char_id, mapindex_id2name(map_index),x,y);
x = y = 0; // make it random
}
@@ -4901,7 +5033,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
//Tag player for rewarping after map-loading is done. [Skotlex]
sd->state.rewarp = 1;
- sd->mapindex = mapindex;
+ sd->mapindex = map_index;
sd->bl.m = m;
sd->bl.x = sd->ud.to_x = x;
sd->bl.y = sd->ud.to_y = y;
@@ -4932,6 +5064,10 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y
sd->md->bl.y = sd->md->ud.to_y = y;
sd->md->ud.dir = sd->ud.dir;
}
+
+ /* given autotrades have no clients you have to trigger this manually otherwise they get stuck in memory limbo bugreport:7495 */
+ if( sd->state.autotrade )
+ clif->pLoadEndAck(0,sd);
return 0;
}
@@ -4975,7 +5111,7 @@ int pc_memo(struct map_session_data* sd, int pos) {
nullpo_ret(sd);
// check mapflags
- if( sd->bl.m >= 0 && (map->list[sd->bl.m].flag.nomemo || map->list[sd->bl.m].flag.nowarpto) && !pc->has_permission(sd, PC_PERM_WARP_ANYWHERE) ) {
+ if( sd->bl.m >= 0 && (map->list[sd->bl.m].flag.nomemo || map->list[sd->bl.m].flag.nowarpto) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE) ) {
clif->skill_mapinfomessage(sd, 1); // "Saved point cannot be memorized."
return 0;
}
@@ -5079,7 +5215,8 @@ int pc_checkallowskill(struct map_session_data *sd)
SC_LKCONCENTRATION,
SC_EDP,
#endif
- SC_FEARBREEZE
+ SC_FEARBREEZE,
+ SC_EXEEDBREAK,
};
const enum sc_type scs_list[] = {
SC_AUTOGUARD,
@@ -5626,15 +5763,16 @@ const char* job_name(int class_)
case JOB_KAGEROU:
case JOB_OBORO:
return msg_txt(653 - JOB_KAGEROU+class_);
+
case JOB_REBELLION:
- return msg_txt(694);
+ return msg_txt(655);
default:
- return msg_txt(655);
+ return msg_txt(656);
}
}
-int pc_follow_timer(int tid, unsigned int tick, int id, intptr_t data) {
+int pc_follow_timer(int tid, int64 tick, int id, intptr_t data) {
struct map_session_data *sd;
struct block_list *tbl;
@@ -5720,26 +5858,26 @@ int pc_checkbaselevelup(struct map_session_data *sd) {
} while ((next=pc->nextbaseexp(sd)) > 0 && sd->status.base_exp >= next);
if (battle_config.pet_lv_rate && sd->pd) //<Skotlex> update pet's level
- status_calc_pet(sd->pd,0);
+ status_calc_pet(sd->pd,SCO_NONE);
clif->updatestatus(sd,SP_STATUSPOINT);
clif->updatestatus(sd,SP_BASELEVEL);
clif->updatestatus(sd,SP_BASEEXP);
clif->updatestatus(sd,SP_NEXTBASEEXP);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_FORCE);
status_percent_heal(&sd->bl,100,100);
if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE) {
- sc_start(&sd->bl,status->skill2sc(PR_KYRIE),100,1,skill->get_time(PR_KYRIE,1));
- sc_start(&sd->bl,status->skill2sc(PR_IMPOSITIO),100,1,skill->get_time(PR_IMPOSITIO,1));
- sc_start(&sd->bl,status->skill2sc(PR_MAGNIFICAT),100,1,skill->get_time(PR_MAGNIFICAT,1));
- sc_start(&sd->bl,status->skill2sc(PR_GLORIA),100,1,skill->get_time(PR_GLORIA,1));
- sc_start(&sd->bl,status->skill2sc(PR_SUFFRAGIUM),100,1,skill->get_time(PR_SUFFRAGIUM,1));
+ 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));
+ sc_start(NULL,&sd->bl,status->skill2sc(PR_GLORIA),100,1,skill->get_time(PR_GLORIA,1));
+ 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 ) {
- sc_start(&sd->bl,status->skill2sc(AL_INCAGI),100,10,600000);
- sc_start(&sd->bl,status->skill2sc(AL_BLESSING),100,10,600000);
+ sc_start(NULL,&sd->bl,status->skill2sc(AL_INCAGI),100,10,600000);
+ sc_start(NULL,&sd->bl,status->skill2sc(AL_BLESSING),100,10,600000);
}
clif->misceffect(&sd->bl,0);
npc->script_event(sd, NPCE_BASELVUP); //LORDALFA - LVLUPEVENT
@@ -5752,7 +5890,6 @@ int pc_checkbaselevelup(struct map_session_data *sd) {
}
void pc_baselevelchanged(struct map_session_data *sd) {
-#ifdef RENEWAL
int i;
for( i = 0; i < EQI_MAX; i++ ) {
if( sd->equip_index[i] >= 0 ) {
@@ -5760,9 +5897,8 @@ void pc_baselevelchanged(struct map_session_data *sd) {
pc->unequipitem(sd, sd->equip_index[i], 3);
}
}
-#endif
-
}
+
int pc_checkjoblevelup(struct map_session_data *sd)
{
unsigned int next = pc->nextjobexp(sd);
@@ -5786,7 +5922,7 @@ int pc_checkjoblevelup(struct map_session_data *sd)
clif->updatestatus(sd,SP_JOBEXP);
clif->updatestatus(sd,SP_NEXTJOBEXP);
clif->updatestatus(sd,SP_SKILLPOINT);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_FORCE);
clif->misceffect(&sd->bl,1);
if (pc->checkskill(sd, SG_DEVIL) && !pc->nextjobexp(sd))
clif->status_change(&sd->bl,SI_DEVIL1, 1, 0, 0, 0, 1); //Permanent blind effect from SG_DEVIL.
@@ -5820,6 +5956,12 @@ void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned in
*job_exp = (unsigned int) cap_value(*job_exp + (double)*job_exp * bonus/100., 1, UINT_MAX);
+ if( sd->status.mod_exp != 100 ) {
+ *base_exp = (unsigned int) cap_value((double)*base_exp * sd->status.mod_exp/100., 1, UINT_MAX);
+ *job_exp = (unsigned int) cap_value((double)*job_exp * sd->status.mod_exp/100., 1, UINT_MAX);
+
+ }
+
return;
}
/*==========================================
@@ -5898,7 +6040,7 @@ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int
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,strlen(output));
}
return 1;
@@ -6043,52 +6185,88 @@ int pc_need_status_point(struct map_session_data* sd, int type, int val)
return sp;
}
-/// Raises a stat by 1.
-/// Obeys max_parameter limits.
-/// Subtracts stat points.
-///
-/// @param type The stat to change (see enum _sp)
-int pc_statusup(struct map_session_data* sd, int type)
-{
- int max, need, val;
+/**
+ * Returns the value the specified stat can be increased by with the current
+ * amount of available status points for the current character's class.
+ *
+ * @param sd The target character.
+ * @param type Stat to verify.
+ * @return Maximum value the stat could grow by.
+ */
+int pc_maxparameterincrease(struct map_session_data* sd, int type) {
+ int base, final, status_points = sd->status.status_point;
+
+ base = final = pc->getstat(sd, type);
+
+ while (final <= pc_maxparameter(sd) && status_points >= 0) {
+#ifdef RENEWAL // renewal status point cost formula
+ status_points -= (final < 100) ? (2 + (final - 1) / 10) : (16 + 4 * ((final - 100) / 5));
+#else
+ status_points -= ( 1 + (final + 9) / 10 );
+#endif
+ final++;
+ }
+ final--;
+
+ return final > base ? final-base : 0;
+}
+
+/**
+ * Raises a stat by the specified amount.
+ * Obeys max_parameter limits.
+ * Subtracts stat points.
+ *
+ * @param sd The target character.
+ * @param type The stat to change (see enum _sp)
+ * @param increase The stat increase amount.
+ * @return true if the stat was increased by any amount, false if there were no
+ * changes.
+ */
+bool pc_statusup(struct map_session_data* sd, int type, int increase) {
+ int max_increase = 0, current = 0, needed_points = 0, final_value = 0;
nullpo_ret(sd);
// check conditions
- need = pc->need_status_point(sd,type,1);
- if( type < SP_STR || type > SP_LUK || need < 0 || need > sd->status.status_point )
- {
- clif->statusupack(sd,type,0,0);
- return 1;
+ if (type < SP_STR || type > SP_LUK || increase <= 0) {
+ clif->statusupack(sd, type, 0, 0);
+ return false;
}
// check limits
- max = pc_maxparameter(sd);
- if( pc->getstat(sd,type) >= max )
- {
- clif->statusupack(sd,type,0,0);
- return 1;
+ current = pc->getstat(sd, type);
+ max_increase = pc->maxparameterincrease(sd, type);
+ increase = cap_value(increase, 0, max_increase); // cap to the maximum status points available
+ if (increase <= 0 || current + increase > pc_maxparameter(sd)) {
+ clif->statusupack(sd, type, 0, 0);
+ return false;
+ }
+
+ // check status points
+ needed_points = pc->need_status_point(sd, type, increase);
+ if (needed_points < 0 || needed_points > sd->status.status_point) { // Sanity check
+ clif->statusupack(sd, type, 0, 0);
+ return false;
}
// set new values
- val = pc->setstat(sd, type, pc->getstat(sd,type) + 1);
- sd->status.status_point -= need;
+ final_value = pc->setstat(sd, type, current + increase);
+ sd->status.status_point -= needed_points;
- status_calc_pc(sd,0);
+ status_calc_pc(sd, SCO_NONE);
// update increase cost indicator
- if( need != pc->need_status_point(sd,type,1) )
- clif->updatestatus(sd, SP_USTR + type-SP_STR);
+ clif->updatestatus(sd, SP_USTR + type-SP_STR);
// update statpoint count
- clif->updatestatus(sd,SP_STATUSPOINT);
+ clif->updatestatus(sd, SP_STATUSPOINT);
// update stat value
- clif->statusupack(sd,type,1,val); // required
- if( val > 255 )
- clif->updatestatus(sd,type); // send after the 'ack' to override the truncated value
+ clif->statusupack(sd, type, 1, final_value); // required
+ if (final_value > 255)
+ clif->updatestatus(sd, type); // send after the 'ack' to override the truncated value
- return 0;
+ return true;
}
/// Raises a stat by the specified amount.
@@ -6114,7 +6292,7 @@ int pc_statusup2(struct map_session_data* sd, int type, int val)
max = pc_maxparameter(sd);
val = pc->setstat(sd, type, cap_value(pc->getstat(sd,type) + val, 1, max));
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
// update increase cost indicator
if( need != pc->need_status_point(sd,type,1) )
@@ -6157,17 +6335,17 @@ int pc_skillup(struct map_session_data *sd,uint16 skill_id) {
sd->status.skill[index].lv++;
sd->status.skill_point--;
if( !skill->db[index].inf )
- status_calc_pc(sd,0); // Only recalculate for passive skills.
+ 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) )
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
- clif->skillup(sd,skill_id);
+ clif->skillup(sd,skill_id, sd->status.skill[index].lv, 1);
clif->updatestatus(sd,SP_SKILLPOINT);
if( skill_id == GN_REMODELING_CART ) /* cart weight info was updated by status_calc_pc */
clif->updatestatus(sd,SP_CARTINFO);
- if (!pc->has_permission(sd, PC_PERM_ALL_SKILL)) // may skill everything at any time anyways, and this would cause a huge slowdown
+ 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 )
@@ -6200,7 +6378,7 @@ int pc_allskillup(struct map_session_data *sd)
}
}
- if (pc->has_permission(sd, PC_PERM_ALL_SKILL)) { //Get ALL skills except npc/guild ones. [Skotlex]
+ if (pc_has_permission(sd, PC_PERM_ALL_SKILL)) { //Get ALL skills except npc/guild ones. [Skotlex]
//and except SG_DEVIL [Komurka] and MO_TRIPLEATTACK and RG_SNATCHER [ultramage]
for(i=0;i<MAX_SKILL;i++){
switch( skill->db[i].nameid ) {
@@ -6230,7 +6408,7 @@ int pc_allskillup(struct map_session_data *sd)
sd->status.skill[idx].lv = skill->tree_get_max(id, sd->status.class_); // celest
}
}
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
//Required because if you could level up all skills previously,
//the update will not be sent as only the lv variable changes.
clif->skillinfoblock(sd);
@@ -6320,7 +6498,7 @@ int pc_resetlvl(struct map_session_data* sd,int type)
if ((type == 1 || type == 2 || type == 3) && sd->status.party_id)
party->send_levelup(sd);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_FORCE);
clif->skillinfoblock(sd);
return 0;
@@ -6382,10 +6560,10 @@ int pc_resetstate(struct map_session_data* sd)
if( sd->mission_mobid ) { //bugreport:2200
sd->mission_mobid = 0;
sd->mission_count = 0;
- pc_setglobalreg(sd,"TK_MISSION_ID", 0);
+ pc_setglobalreg(sd,script->add_str("TK_MISSION_ID"), 0);
}
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
return 1;
}
@@ -6438,7 +6616,7 @@ int pc_resetskill(struct map_session_data* sd, int flag)
pc->setoption(sd, i);
if( homun_alive(sd->hd) && pc->checkskill(sd, AM_CALLHOMUN) )
- homun->vaporize(sd, 0);
+ homun->vaporize(sd, HOM_ST_REST);
}
for( i = 1; i < MAX_SKILL; i++ ) {
@@ -6496,7 +6674,7 @@ int pc_resetskill(struct map_session_data* sd, int flag)
if( flag&1 ) {
clif->updatestatus(sd,SP_SKILLPOINT);
clif->skillinfoblock(sd);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_FORCE);
}
return skill_point;
@@ -6514,7 +6692,7 @@ int pc_resetfeel(struct map_session_data* sd)
{
sd->feel_map[i].m = -1;
sd->feel_map[i].index = 0;
- pc_setglobalreg(sd,pc->sg_info[i].feel_var,0);
+ pc_setglobalreg(sd,script->add_str(pc->sg_info[i].feel_var),0);
}
return 0;
@@ -6528,7 +6706,7 @@ int pc_resethate(struct map_session_data* sd)
for (i=0; i<3; i++)
{
sd->hate_mob[i] = -1;
- pc_setglobalreg(sd,pc->sg_info[i].hate_var,0);
+ pc_setglobalreg(sd,script->add_str(pc->sg_info[i].hate_var),0);
}
return 0;
}
@@ -6592,7 +6770,7 @@ void pc_respawn(struct map_session_data* sd, clr_type clrtype)
clif->resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet.
}
-int pc_respawn_timer(int tid, unsigned int tick, int id, intptr_t data) {
+int pc_respawn_timer(int tid, int64 tick, int id, intptr_t data) {
struct map_session_data *sd = map->id2sd(id);
if( sd != NULL )
{
@@ -6638,15 +6816,15 @@ void pc_damage(struct map_session_data *sd,struct block_list *src,unsigned int h
* Invoked when a player has negative current hp
*------------------------------------------*/
int pc_dead(struct map_session_data *sd,struct block_list *src) {
- int i=0,j=0,k=0;
- unsigned int tick = timer->gettick();
+ int i=0,j=0;
+ int64 tick = timer->gettick();
- for(k = 0; k < 5; k++)
- if (sd->devotion[k]){
- struct map_session_data *devsd = map->id2sd(sd->devotion[k]);
+ for(j = 0; j < 5; j++)
+ if (sd->devotion[j]){
+ struct map_session_data *devsd = map->id2sd(sd->devotion[j]);
if (devsd)
status_change_end(&devsd->bl, SC_DEVOTION, INVALID_TIMER);
- sd->devotion[k] = 0;
+ sd->devotion[j] = 0;
}
if(sd->status.pet_id > 0 && sd->pd) {
@@ -6663,7 +6841,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
if (sd->status.hom_id > 0){
if(battle_config.homunculus_auto_vapor && sd->hd && !sd->hd->sc.data[SC_LIGHT_OF_REGENE])
- homun->vaporize(sd, 0);
+ homun->vaporize(sd, HOM_ST_REST);
}
if( sd->md )
@@ -6683,7 +6861,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
if (sd->npc_id && sd->st && sd->st->state != RUN)
npc->event_dequeue(sd);
- pc_setglobalreg(sd,"PC_DIE_COUNTER",sd->die_counter+1);
+ pc_setglobalreg(sd,script->add_str("PC_DIE_COUNTER"),sd->die_counter+1);
pc->setparam(sd, SP_KILLERRID, src?src->id:0);
if( sd->bg_id ) {/* TODO: purge when bgqueue is deemed ok */
@@ -6750,7 +6928,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
) { // monster level up [Valaris]
clif->misceffect(&md->bl,0);
md->level++;
- status_calc_mob(md, 0);
+ status_calc_mob(md, SCO_NONE);
status_percent_heal(src,10,0);
if( battle_config.show_mob_info&4 )
@@ -6781,7 +6959,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
if (battle_config.pk_mode&2) {
ssd->status.manner -= 5;
if(ssd->status.manner < 0)
- sc_start(src,SC_NOCHAT,100,0,0);
+ sc_start(NULL,src,SC_NOCHAT,100,0,0);
#if 0
// PK/Karma system code (not enabled yet) [celest]
// originally from Kade Online, so i don't know if any of these is correct ^^;
@@ -6833,7 +7011,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
clif->resurrection(&sd->bl, 1);
if(battle_config.pc_invincible_time)
pc->setinvincibletimer(sd, battle_config.pc_invincible_time);
- sc_start(&sd->bl,status->skill2sc(MO_STEELBODY),100,1,skill->get_time(MO_STEELBODY,1));
+ sc_start(NULL,&sd->bl,status->skill2sc(MO_STEELBODY),100,1,skill->get_time(MO_STEELBODY,1));
if(map_flag_gvg2(sd->bl.m))
pc->respawn_timer(INVALID_TIMER, timer->gettick(), sd->bl.id, 0);
return 0;
@@ -6842,47 +7020,55 @@ 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
- && !map->list[sd->bl.m].flag.noexppenalty && !map_flag_gvg2(sd->bl.m)
- && !sd->sc.data[SC_BABY] && !sd->sc.data[SC_CASH_DEATHPENALTY]
- ) {
- unsigned int base_penalty =0;
+ && (sd->class_&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]
+ ) {
+ unsigned int base_penalty = 0;
if (battle_config.death_penalty_base > 0) {
+
switch (battle_config.death_penalty_type) {
case 1:
base_penalty = (unsigned int) ((double)pc->nextbaseexp(sd) * (double)battle_config.death_penalty_base/10000);
- break;
+ break;
case 2:
base_penalty = (unsigned int) ((double)sd->status.base_exp * (double)battle_config.death_penalty_base/10000);
- break;
+ break;
}
+
if(base_penalty) {
if (battle_config.pk_mode && src && src->type==BL_PC)
base_penalty*=2;
+ if( sd->status.mod_death != 100 )
+ base_penalty = base_penalty * sd->status.mod_death / 100;
sd->status.base_exp -= min(sd->status.base_exp, base_penalty);
clif->updatestatus(sd,SP_BASEEXP);
}
}
- if(battle_config.death_penalty_job > 0)
- {
+
+ if(battle_config.death_penalty_job > 0) {
base_penalty = 0;
+
switch (battle_config.death_penalty_type) {
case 1:
base_penalty = (unsigned int) ((double)pc->nextjobexp(sd) * (double)battle_config.death_penalty_job/10000);
- break;
+ break;
case 2:
base_penalty = (unsigned int) ((double)sd->status.job_exp * (double)battle_config.death_penalty_job/10000);
- break;
+ break;
}
+
if(base_penalty) {
if (battle_config.pk_mode && src && src->type==BL_PC)
base_penalty*=2;
+ if( sd->status.mod_death != 100 )
+ base_penalty = base_penalty * sd->status.mod_death / 100;
sd->status.job_exp -= min(sd->status.job_exp, base_penalty);
clif->updatestatus(sd,SP_JOBEXP);
}
}
- if(battle_config.zeny_penalty > 0 && !map->list[sd->bl.m].flag.nozenypenalty)
- {
+
+ if(battle_config.zeny_penalty > 0 && !map->list[sd->bl.m].flag.nozenypenalty) {
base_penalty = (unsigned int)((double)sd->status.zeny * (double)battle_config.zeny_penalty / 10000.);
if(base_penalty)
pc->payzeny(sd, base_penalty, LOG_TYPE_PICKDROP_PLAYER, NULL);
@@ -6898,14 +7084,13 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
if(id == 0)
continue;
if(id == -1){
- int eq_num=0,eq_n[MAX_INVENTORY];
+ int eq_num=0,eq_n[MAX_INVENTORY],k;
memset(eq_n,0,sizeof(eq_n));
for(i=0;i<MAX_INVENTORY;i++){
if( (type == 1 && !sd->status.inventory[i].equip)
|| (type == 2 && sd->status.inventory[i].equip)
|| type == 3)
{
- int k;
ARR_FIND( 0, MAX_INVENTORY, k, eq_n[k] <= 0 );
if( k < MAX_INVENTORY )
eq_n[k] = i;
@@ -7034,6 +7219,9 @@ int pc_readparam(struct map_session_data* sd,int type)
case SP_KILLEDRID: val = sd->killedrid; break;
case SP_SLOTCHANGE: val = sd->status.slotchange; break;
case SP_CHARRENAME: val = sd->status.rename; break;
+ case SP_MOD_EXP: val = sd->status.mod_exp; break;
+ case SP_MOD_DROP: val = sd->status.mod_drop; break;
+ case SP_MOD_DEATH: val = sd->status.mod_death; break;
case SP_CRITICAL: val = sd->battle_status.cri/10; break;
case SP_ASPD: val = (2000-sd->battle_status.amotion)/10; break;
case SP_BASE_ATK: val = sd->battle_status.batk; break;
@@ -7166,7 +7354,7 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
clif->updatestatus(sd, SP_NEXTBASEEXP);
clif->updatestatus(sd, SP_STATUSPOINT);
clif->updatestatus(sd, SP_BASEEXP);
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_FORCE);
if(sd->status.party_id)
{
party->send_levelup(sd);
@@ -7183,7 +7371,7 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
// clif->updatestatus(sd, SP_JOBLEVEL); // Gets updated at the bottom
clif->updatestatus(sd, SP_NEXTJOBEXP);
clif->updatestatus(sd, SP_JOBEXP);
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_FORCE);
break;
case SP_SKILLPOINT:
sd->status.skill_point = val;
@@ -7281,6 +7469,15 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
case SP_CHARRENAME:
sd->status.rename = val;
return 1;
+ case SP_MOD_EXP:
+ sd->status.mod_exp = val;
+ return 1;
+ case SP_MOD_DROP:
+ sd->status.mod_drop = val;
+ return 1;
+ case SP_MOD_DEATH:
+ sd->status.mod_death = val;
+ return 1;
default:
ShowError("pc_setparam: Attempted to set unknown parameter '%d'.\n", type);
return 0;
@@ -7358,6 +7555,11 @@ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp)
sp -= sp * sd->sc.data[SC_CRITICALWOUND]->val2 / 100;
}
+ if( sd->sc.data[SC_VITALITYACTIVATION] ){
+ hp += hp / 2; // 1.5 times
+ sp -= sp / 2;
+ }
+
if ( sd->sc.data[SC_DEATHHURT] ) {
hp -= hp * 20 / 100;
sp -= sp * 20 / 100;
@@ -7466,12 +7668,12 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
// changing from 1st to 2nd job
if ((b_class&JOBL_2) && !(sd->class_&JOBL_2) && (b_class&MAPID_UPPERMASK) != MAPID_SUPER_NOVICE) {
sd->change_level_2nd = sd->status.job_level;
- pc_setglobalreg (sd, "jobchange_level", sd->change_level_2nd);
+ 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)) {
sd->change_level_3rd = sd->status.job_level;
- pc_setglobalreg (sd, "jobchange_level_3rd", sd->change_level_3rd);
+ pc_setglobalreg (sd, script->add_str("jobchange_level_3rd"), sd->change_level_3rd);
}
if(sd->cloneskill_id) {
@@ -7483,8 +7685,8 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
clif->deleteskill(sd,sd->cloneskill_id);
}
sd->cloneskill_id = 0;
- pc_setglobalreg(sd, "CLONE_SKILL", 0);
- pc_setglobalreg(sd, "CLONE_SKILL_LV", 0);
+ pc_setglobalreg(sd, script->add_str("CLONE_SKILL"), 0);
+ pc_setglobalreg(sd, script->add_str("CLONE_SKILL_LV"), 0);
}
if(sd->reproduceskill_id) {
@@ -7496,8 +7698,8 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
clif->deleteskill(sd,sd->reproduceskill_id);
}
sd->reproduceskill_id = 0;
- pc_setglobalreg(sd, "REPRODUCE_SKILL",0);
- pc_setglobalreg(sd, "REPRODUCE_SKILL_LV",0);
+ pc_setglobalreg(sd, script->add_str("REPRODUCE_SKILL"),0);
+ 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.
@@ -7588,12 +7790,12 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
pc->setoption(sd, i);
if(homun_alive(sd->hd) && !pc->checkskill(sd, AM_CALLHOMUN))
- homun->vaporize(sd, 0);
+ homun->vaporize(sd, HOM_ST_REST);
if(sd->status.manner < 0)
clif->changestatus(sd,SP_MANNER,sd->status.manner);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_FORCE);
pc->checkallowskill(sd);
pc->equiplookall(sd);
@@ -7716,11 +7918,11 @@ int pc_setoption(struct map_session_data *sd,int type)
if( (type&OPTION_RIDING && !(p_type&OPTION_RIDING)) || (type&OPTION_DRAGON && !(p_type&OPTION_DRAGON) && pc->checkskill(sd,RK_DRAGONTRAINING) > 0) ) {
// Mounting
clif->sc_load(&sd->bl,sd->bl.id,AREA,SI_RIDING, 0, 0, 0);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
} else if( (!(type&OPTION_RIDING) && p_type&OPTION_RIDING) || (!(type&OPTION_DRAGON) && p_type&OPTION_DRAGON) ) {
// Dismount
clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_RIDING);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
}
#ifndef NEW_CARTS
@@ -7728,11 +7930,11 @@ int pc_setoption(struct map_session_data *sd,int type)
clif->cartlist(sd);
clif->updatestatus(sd, SP_CARTINFO);
if(pc->checkskill(sd, MC_PUSHCART) < 10)
- status_calc_pc(sd,0); //Apply speed penalty.
+ status_calc_pc(sd,SCO_NONE); //Apply speed penalty.
} else if( !( type&OPTION_CART ) && p_type&OPTION_CART ){ //Cart Off
clif->clearcart(sd->fd);
if(pc->checkskill(sd, MC_PUSHCART) < 10)
- status_calc_pc(sd,0); //Remove speed penalty.
+ status_calc_pc(sd,SCO_NONE); //Remove speed penalty.
}
#endif
@@ -7744,18 +7946,18 @@ int pc_setoption(struct map_session_data *sd,int type)
if( (sd->class_&MAPID_THIRDMASK) == MAPID_RANGER ) {
if( type&OPTION_WUGRIDER && !(p_type&OPTION_WUGRIDER) ) { // Mounting
clif->sc_load(&sd->bl,sd->bl.id,AREA,SI_WUGRIDER, 0, 0, 0);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
} else if( !(type&OPTION_WUGRIDER) && p_type&OPTION_WUGRIDER ) { // Dismount
clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_WUGRIDER);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
}
}
if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC ) {
int i;
if( type&OPTION_MADOGEAR && !(p_type&OPTION_MADOGEAR) )
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_NONE);
else if( !(type&OPTION_MADOGEAR) && p_type&OPTION_MADOGEAR )
- status_calc_pc(sd, 0);
+ status_calc_pc(sd, SCO_NONE);
for( i = 0; i < SC_MAX; i++ ){
if ( !sd->sc.data[i] || !status->get_sc_type(i) )
continue;
@@ -7826,7 +8028,7 @@ int pc_setcart(struct map_session_data *sd,int type) {
if( !sd->sc.data[SC_PUSH_CART] ) /* first time, so fill cart data */
clif->cartlist(sd);
clif->updatestatus(sd, SP_CARTINFO);
- sc_start(&sd->bl, SC_PUSH_CART, 100, type, 0);
+ sc_start(NULL,&sd->bl, SC_PUSH_CART, 100, type, 0);
clif->sc_load(&sd->bl, sd->bl.id, AREA, SI_ON_PUSH_CART, type, 0, 0);
if( sd->sc.data[SC_PUSH_CART] )/* forcefully update */
sd->sc.data[SC_PUSH_CART]->val1 = type;
@@ -7834,7 +8036,7 @@ int pc_setcart(struct map_session_data *sd,int type) {
}
if(pc->checkskill(sd, MC_PUSHCART) < 10)
- status_calc_pc(sd,0); //Recalc speed penalty.
+ status_calc_pc(sd,SCO_NONE); //Recalc speed penalty.
#else
// Update option
option = sd->sc.option;
@@ -7896,353 +8098,258 @@ int pc_setmadogear(TBL_PC* sd, int flag)
*------------------------------------------*/
int pc_candrop(struct map_session_data *sd, struct item *item)
{
- if( item && item->expire_time )
+ if( item && (item->expire_time || (item->bound && !pc_can_give_bound_items(sd))) )
+ return 0;
+ if( !pc_can_give_items(sd) ) //check if this GM level can drop items
return 0;
- if( !pc->can_give_items(sd) ) //check if this GM level can drop items
- return 0;
- return (itemdb_isdropable(item, pc->get_group_level(sd)));
+ return (itemdb_isdropable(item, pc_get_group_level(sd)));
}
-
-/*==========================================
- * Read ram register for player sd
- * get val (int) from reg for player sd
- *------------------------------------------*/
-int pc_readreg(struct map_session_data* sd, int reg)
-{
- int i;
-
- nullpo_ret(sd);
-
- ARR_FIND( 0, sd->reg_num, i, sd->reg[i].index == reg );
- return ( i < sd->reg_num ) ? sd->reg[i].data : 0;
+/**
+ * For '@type' variables (temporary numeric char reg)
+ **/
+int pc_readreg(struct map_session_data* sd, int64 reg) {
+ return i64db_iget(sd->var_db, reg);
}
-/*==========================================
- * Set ram register for player sd
- * memo val(int) at reg for player sd
- *------------------------------------------*/
-int pc_setreg(struct map_session_data* sd, int reg, int val)
-{
- int i;
-
- nullpo_ret(sd);
-
- ARR_FIND( 0, sd->reg_num, i, sd->reg[i].index == reg );
- if( i < sd->reg_num )
- {// overwrite existing entry
- sd->reg[i].data = val;
- return 1;
- }
-
- ARR_FIND( 0, sd->reg_num, i, sd->reg[i].data == 0 );
- if( i == sd->reg_num )
- {// nothing free, increase size
- sd->reg_num++;
- RECREATE(sd->reg, struct script_reg, sd->reg_num);
+/**
+ * For '@type' variables (temporary numeric char reg)
+ **/
+void pc_setreg(struct map_session_data* sd, int64 reg, int val) {
+ unsigned int index = script_getvaridx(reg);
+
+ if( val ) {
+ i64db_iput(sd->var_db, reg, val);
+ if( index )
+ script->array_update(&sd->array_db,reg,false);
+ } else {
+ i64db_remove(sd->var_db, reg);
+ if( index )
+ script->array_update(&sd->array_db,reg,true);
}
- sd->reg[i].index = reg;
- sd->reg[i].data = val;
-
- return 1;
}
-/*==========================================
- * Read ram register for player sd
- * get val (str) from reg for player sd
- *------------------------------------------*/
-char* pc_readregstr(struct map_session_data* sd, int reg)
-{
- int i;
-
- nullpo_ret(sd);
+/**
+ * For '@type$' variables (temporary string char reg)
+ **/
+char* pc_readregstr(struct map_session_data* sd, int64 reg) {
+ struct script_reg_str *p = NULL;
- ARR_FIND( 0, sd->regstr_num, i, sd->regstr[i].index == reg );
- return ( i < sd->regstr_num ) ? sd->regstr[i].data : NULL;
+ p = i64db_get(sd->var_db, reg);
+
+ return p ? p->value : NULL;
}
-/*==========================================
- * Set ram register for player sd
- * memo val(str) at reg for player sd
- *------------------------------------------*/
-int pc_setregstr(struct map_session_data* sd, int reg, const char* str)
-{
- int i;
-
- nullpo_ret(sd);
+/**
+ * For '@type$' variables (temporary string char 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;
- ARR_FIND( 0, sd->regstr_num, i, sd->regstr[i].index == reg );
- if( i < sd->regstr_num )
- {// found entry, update
- if( str == NULL || *str == '\0' )
- {// empty string
- if( sd->regstr[i].data != NULL )
- aFree(sd->regstr[i].data);
- sd->regstr[i].data = NULL;
- }
- else if( sd->regstr[i].data )
- {// recreate
- size_t len = strlen(str)+1;
- RECREATE(sd->regstr[i].data, char, len);
- memcpy(sd->regstr[i].data, str, len*sizeof(char));
+ if( str[0] ) {
+ p = ers_alloc(pc->str_reg_ers, struct script_reg_str);
+
+ p->value = aStrdup(str);
+ p->flag.type = 1;
+
+ if( sd->var_db->put(sd->var_db,DB->i642key(reg),DB->ptr2data(p),&prev) ) {
+ p = DB->data2ptr(&prev);
+ if( p->value )
+ aFree(p->value);
+ ers_free(pc->str_reg_ers, p);
+ } else {
+ if( index )
+ script->array_update(&sd->array_db,reg,false);
}
- else
- {// create
- sd->regstr[i].data = aStrdup(str);
+ } else {
+ if( sd->var_db->remove(sd->var_db,DB->i642key(reg),&prev) ) {
+ p = DB->data2ptr(&prev);
+ if( p->value )
+ aFree(p->value);
+ ers_free(pc->str_reg_ers, p);
+ if( index )
+ script->array_update(&sd->array_db,reg,true);
}
- return 1;
- }
-
- if( str == NULL || *str == '\0' )
- return 1;// nothing to add, empty string
-
- ARR_FIND( 0, sd->regstr_num, i, sd->regstr[i].data == NULL );
- if( i == sd->regstr_num )
- {// nothing free, increase size
- sd->regstr_num++;
- RECREATE(sd->regstr, struct script_regstr, sd->regstr_num);
}
- sd->regstr[i].index = reg;
- sd->regstr[i].data = aStrdup(str);
-
- return 1;
}
-
-int pc_readregistry(struct map_session_data *sd,const char *reg,int type)
-{
- struct global_reg *sd_reg;
- int i,max;
-
- nullpo_ret(sd);
- switch (type) {
- case 3: //Char reg
- sd_reg = sd->save_reg.global;
- max = sd->save_reg.global_num;
- break;
- case 2: //Account reg
- sd_reg = sd->save_reg.account;
- max = sd->save_reg.account_num;
- break;
- case 1: //Account2 reg
- sd_reg = sd->save_reg.account2;
- max = sd->save_reg.account2_num;
- break;
- default:
- return 0;
- }
- if (max == -1) {
- ShowError("pc_readregistry: Trying to read reg value %s (type %d) before it's been loaded!\n", reg, type);
+/**
+ * Serves the following variable types:
+ * - 'type' (permanent nuneric char reg)
+ * - '#type' (permanent numeric account reg)
+ * - '##type' (permanent numeric account reg2)
+ **/
+int pc_readregistry(struct map_session_data *sd, int64 reg) {
+ struct script_reg_num *p = NULL;
+
+ 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.
- intif->request_registry(sd,type==3?4:type);
+ //intif->request_registry(sd,type==3?4:type);
+ set_eof(sd->fd);
return 0;
}
+
+ p = i64db_get(sd->var_db, reg);
- ARR_FIND( 0, max, i, strcmp(sd_reg[i].str,reg) == 0 );
- return ( i < max ) ? atoi(sd_reg[i].value) : 0;
+ return p ? p->value : 0;
}
-
-char* pc_readregistry_str(struct map_session_data *sd,const char *reg,int type)
-{
- struct global_reg *sd_reg;
- int i,max;
-
- nullpo_ret(sd);
- switch (type) {
- case 3: //Char reg
- sd_reg = sd->save_reg.global;
- max = sd->save_reg.global_num;
- break;
- case 2: //Account reg
- sd_reg = sd->save_reg.account;
- max = sd->save_reg.account_num;
- break;
- case 1: //Account2 reg
- sd_reg = sd->save_reg.account2;
- max = sd->save_reg.account2_num;
- break;
- default:
- return NULL;
- }
- if (max == -1) {
- ShowError("pc_readregistry: Trying to read reg value %s (type %d) before it's been loaded!\n", reg, type);
+/**
+ * Serves the following variable types:
+ * - 'type$' (permanent str char reg)
+ * - '#type$' (permanent str account reg)
+ * - '##type$' (permanent str account reg2)
+ **/
+char* pc_readregistry_str(struct map_session_data *sd, int64 reg) {
+ struct script_reg_str *p = NULL;
+
+ 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.
- intif->request_registry(sd,type==3?4:type);
+ //intif->request_registry(sd,type==3?4:type);
+ set_eof(sd->fd);
return NULL;
}
- ARR_FIND( 0, max, i, strcmp(sd_reg[i].str,reg) == 0 );
- return ( i < max ) ? sd_reg[i].value : NULL;
+ p = i64db_get(sd->var_db, reg);
+
+ return p ? p->value : NULL;
}
+/**
+ * Serves the following variable types:
+ * - 'type' (permanent nuneric char reg)
+ * - '#type' (permanent numeric account reg)
+ * - '##type' (permanent numeric account reg2)
+ **/
+int pc_setregistry(struct map_session_data *sd, int64 reg, int val) {
+ struct script_reg_num *p = NULL;
+ int i;
+ const char *regname = script->get_str( script_getvarid(reg) );
+ unsigned int index = script_getvaridx(reg);
-int pc_setregistry(struct map_session_data *sd,const char *reg,int val,int type)
-{
- struct global_reg *sd_reg;
- int i,*max, regmax;
-
- nullpo_ret(sd);
-
- switch( type )
- {
- case 3: //Char reg
- if( !strcmp(reg,"PC_DIE_COUNTER") && sd->die_counter != val )
- {
- i = (!sd->die_counter && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE);
- sd->die_counter = val;
- if( i )
- status_calc_pc(sd,0); // Lost the bonus.
- }
- else if( !strcmp(reg,"COOK_MASTERY") && sd->cook_mastery != val )
- {
- val = cap_value(val, 0, 1999);
- sd->cook_mastery = val;
- }
- sd_reg = sd->save_reg.global;
- max = &sd->save_reg.global_num;
- regmax = GLOBAL_REG_NUM;
- break;
- case 2: //Account reg
- if( !strcmp(reg,"#CASHPOINTS") && sd->cashPoints != val )
- {
- val = cap_value(val, 0, MAX_ZENY);
- sd->cashPoints = val;
- }
- else if( !strcmp(reg,"#KAFRAPOINTS") && sd->kafraPoints != val )
- {
- val = cap_value(val, 0, MAX_ZENY);
- sd->kafraPoints = val;
- }
- sd_reg = sd->save_reg.account;
- max = &sd->save_reg.account_num;
- regmax = ACCOUNT_REG_NUM;
- break;
- case 1: //Account2 reg
- sd_reg = sd->save_reg.account2;
- max = &sd->save_reg.account2_num;
- regmax = ACCOUNT_REG2_NUM;
- break;
- default:
- return 0;
+ /* 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 ) {
+ i = (!sd->die_counter && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE);
+ sd->die_counter = val;
+ if( i )
+ status_calc_pc(sd,SCO_NONE); // Lost the bonus.
+ } else if( !strcmp(regname,"COOK_MASTERY") && sd->cook_mastery != val ) {
+ val = cap_value(val, 0, 1999);
+ sd->cook_mastery = val;
+ }
+ break;
+ case '#':
+ if( !strcmp(regname,"#CASHPOINTS") && sd->cashPoints != val ) {
+ val = cap_value(val, 0, MAX_ZENY);
+ sd->cashPoints = val;
+ } else if( !strcmp(regname,"#KAFRAPOINTS") && sd->kafraPoints != val ) {
+ val = cap_value(val, 0, MAX_ZENY);
+ sd->kafraPoints = val;
+ }
+ break;
}
- if (*max == -1) {
- ShowError("pc_setregistry : refusing to set %s (type %d) until vars are received.\n", reg, type);
- return 1;
+
+ if ( !pc->reg_load && !sd->vars_ok ) {
+ ShowError("pc_setregistry : refusing to set %s until vars are received.\n", regname);
+ return 0;
}
-
- // delete reg
- if (val == 0) {
- ARR_FIND( 0, *max, i, strcmp(sd_reg[i].str, reg) == 0 );
- if( i < *max )
- {
- if (i != *max - 1)
- memcpy(&sd_reg[i], &sd_reg[*max - 1], sizeof(struct global_reg));
- memset(&sd_reg[*max - 1], 0, sizeof(struct global_reg));
- (*max)--;
- sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved"
+
+ if( (p = i64db_get(sd->var_db, reg) ) ) {
+ if( val ) {
+ if( !p->value && index ) /* its a entry that was deleted, so we reset array */
+ script->array_update(&sd->array_db,reg,false);
+ p->value = val;
+ } else {
+ p->value = 0;
+ if( index )
+ script->array_update(&sd->array_db,reg,true);
+ }
+ if( !pc->reg_load )
+ p->flag.update = 1;/* either way, it will require either delete or replace */
+ } else if( val ) {
+ DBData prev;
+
+ if( index )
+ script->array_update(&sd->array_db,reg,false);
+
+ p = ers_alloc(pc->num_reg_ers, struct script_reg_num);
+
+ p->value = val;
+ if( !pc->reg_load )
+ p->flag.update = 1;
+
+ if( sd->var_db->put(sd->var_db,DB->i642key(reg),DB->ptr2data(p),&prev) ) {
+ p = DB->data2ptr(&prev);
+ ers_free(pc->num_reg_ers, p);
}
- return 1;
}
- // change value if found
- ARR_FIND( 0, *max, i, strcmp(sd_reg[i].str, reg) == 0 );
- if( i < *max )
- {
- safesnprintf(sd_reg[i].value, sizeof(sd_reg[i].value), "%d", val);
- sd->state.reg_dirty |= 1<<(type-1);
- return 1;
- }
-
- // add value if not found
- if (i < regmax) {
- memset(&sd_reg[i], 0, sizeof(struct global_reg));
- safestrncpy(sd_reg[i].str, reg, sizeof(sd_reg[i].str));
- safesnprintf(sd_reg[i].value, sizeof(sd_reg[i].value), "%d", val);
- (*max)++;
- sd->state.reg_dirty |= 1<<(type-1);
- return 1;
- }
-
- ShowError("pc_setregistry : couldn't set %s, limit of registries reached (%d)\n", reg, regmax);
+
+ if( !pc->reg_load && p )
+ sd->vars_dirty = true;
- return 0;
+ return 1;
}
+/**
+ * Serves the following variable types:
+ * - 'type$' (permanent str char reg)
+ * - '#type$' (permanent str account reg)
+ * - '##type$' (permanent str account reg2)
+ **/
+int pc_setregistry_str(struct map_session_data *sd, int64 reg, const char *val) {
+ struct script_reg_str *p = NULL;
+ const char *regname = script->get_str( script_getvarid(reg) );
+ unsigned int index = script_getvaridx(reg);
-int pc_setregistry_str(struct map_session_data *sd,const char *reg,const char *val,int type)
-{
- struct global_reg *sd_reg;
- int i,*max, regmax;
-
- nullpo_ret(sd);
- if (reg[strlen(reg)-1] != '$') {
- ShowError("pc_setregistry_str : reg %s must be string (end in '$') to use this!\n", reg);
- return 0;
- }
-
- switch (type) {
- case 3: //Char reg
- sd_reg = sd->save_reg.global;
- max = &sd->save_reg.global_num;
- regmax = GLOBAL_REG_NUM;
- break;
- case 2: //Account reg
- sd_reg = sd->save_reg.account;
- max = &sd->save_reg.account_num;
- regmax = ACCOUNT_REG_NUM;
- break;
- case 1: //Account2 reg
- sd_reg = sd->save_reg.account2;
- max = &sd->save_reg.account2_num;
- regmax = ACCOUNT_REG2_NUM;
- break;
- default:
- return 0;
- }
- if (*max == -1) {
- ShowError("pc_setregistry_str : refusing to set %s (type %d) until vars are received.\n", reg, type);
+ if ( !pc->reg_load && !sd->vars_ok ) {
+ ShowError("pc_setregistry_str : refusing to set %s until vars are received.\n", regname);
return 0;
}
- // delete reg
- if (!val || strcmp(val,"")==0)
- {
- ARR_FIND( 0, *max, i, strcmp(sd_reg[i].str, reg) == 0 );
- if( i < *max )
- {
- if (i != *max - 1)
- memcpy(&sd_reg[i], &sd_reg[*max - 1], sizeof(struct global_reg));
- memset(&sd_reg[*max - 1], 0, sizeof(struct global_reg));
- (*max)--;
- sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved"
- if (type!=3) intif->saveregistry(sd,type);
+ if( (p = i64db_get(sd->var_db, reg) ) ) {
+ if( val[0] ) {
+ if( p->value )
+ aFree(p->value);
+ else if ( index ) /* a entry that was deleted, so we reset */
+ script->array_update(&sd->array_db,reg,false);
+ p->value = aStrdup(val);
+ } else {
+ p->value = NULL;
+ if( index )
+ script->array_update(&sd->array_db,reg,true);
}
- return 1;
- }
+ if( !pc->reg_load )
+ p->flag.update = 1;/* either way, it will require either delete or replace */
+ } else if( val[0] ) {
+ DBData prev;
- // change value if found
- ARR_FIND( 0, *max, i, strcmp(sd_reg[i].str, reg) == 0 );
- if( i < *max )
- {
- safestrncpy(sd_reg[i].value, val, sizeof(sd_reg[i].value));
- sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved"
- if (type!=3) intif->saveregistry(sd,type);
- return 1;
- }
+ if( index )
+ script->array_update(&sd->array_db,reg,false);
- // add value if not found
- if (i < regmax) {
- memset(&sd_reg[i], 0, sizeof(struct global_reg));
- safestrncpy(sd_reg[i].str, reg, sizeof(sd_reg[i].str));
- safestrncpy(sd_reg[i].value, val, sizeof(sd_reg[i].value));
- (*max)++;
- sd->state.reg_dirty |= 1<<(type-1); //Mark this registry as "need to be saved"
- if (type!=3) intif->saveregistry(sd,type);
- return 1;
+ p = ers_alloc(pc->str_reg_ers, struct script_reg_str);
+
+ p->value = aStrdup(val);
+ if( !pc->reg_load )
+ p->flag.update = 1;
+ p->flag.type = 1;
+
+ if( sd->var_db->put(sd->var_db,DB->i642key(reg),DB->ptr2data(p),&prev) ) {
+ p = DB->data2ptr(&prev);
+ if( p->value )
+ aFree(p->value);
+ ers_free(pc->str_reg_ers, p);
+ }
}
-
- ShowError("pc_setregistry : couldn't set %s, limit of registries reached (%d)\n", reg, regmax);
-
- return 0;
+
+ if( !pc->reg_load && p )
+ sd->vars_dirty = true;
+
+ return 1;
}
/*==========================================
* Exec eventtimer for player sd (retrieved from map_session (id))
*------------------------------------------*/
-int pc_eventtimer(int tid, unsigned int tick, int id, intptr_t data) {
+int pc_eventtimer(int tid, int64 tick, int id, intptr_t data) {
struct map_session_data *sd=map->id2sd(id);
char *p = (char *)data;
int i;
@@ -8355,17 +8462,19 @@ int pc_cleareventtimer(struct map_session_data *sd)
/* called when a item with combo is worn */
int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
int i, j, k, z;
- int index, idx, success = 0;
+ int index, success = 0;
+ struct pc_combos *combo;
for( i = 0; i < data->combos_count; i++ ) {
/* ensure this isn't a duplicate combo */
- if( sd->combos.bonus != NULL ) {
+ if( sd->combos != NULL ) {
int x;
- ARR_FIND( 0, sd->combos.count, x, sd->combos.id[x] == data->combos[i]->id );
+
+ ARR_FIND( 0, sd->combo_count, x, sd->combos[x].id == data->combos[i]->id );
/* found a match, skip this combo */
- if( x < sd->combos.count )
+ if( x < sd->combo_count )
continue;
}
@@ -8382,7 +8491,7 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
if(!sd->inventory_data[index])
continue;
-
+
if ( itemdb_type(id) != IT_CARD ) {
if ( sd->inventory_data[index]->nameid != id )
continue;
@@ -8416,24 +8525,16 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
/* we got here, means all items in the combo are matching */
- idx = sd->combos.count;
-
- if( sd->combos.bonus == NULL ) {
- CREATE(sd->combos.bonus, struct script_code *, 1);
- CREATE(sd->combos.id, unsigned short, 1);
- sd->combos.count = 1;
- } else {
- RECREATE(sd->combos.bonus, struct script_code *, ++sd->combos.count);
- RECREATE(sd->combos.id, unsigned short, sd->combos.count);
- }
-
- /* we simply copy the pointer */
- sd->combos.bonus[idx] = data->combos[i]->script;
- /* save this combo's id */
- sd->combos.id[idx] = data->combos[i]->id;
-
+ RECREATE(sd->combos, struct pc_combos, ++sd->combo_count);
+
+ combo = &sd->combos[sd->combo_count - 1];
+
+ combo->bonus = data->combos[i]->script;
+ combo->id = data->combos[i]->id;
+
success++;
}
+
return success;
}
@@ -8441,45 +8542,45 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
int pc_removecombo(struct map_session_data *sd, struct item_data *data ) {
int i, retval = 0;
- if( sd->combos.bonus == NULL )
+ if( !sd->combos )
return 0;/* nothing to do here, player has no combos */
+
for( i = 0; i < data->combos_count; i++ ) {
/* check if this combo exists in this user */
int x = 0, cursor = 0, j;
- ARR_FIND( 0, sd->combos.count, x, sd->combos.id[x] == data->combos[i]->id );
+
+ ARR_FIND( 0, sd->combo_count, x, sd->combos[x].id == data->combos[i]->id );
/* no match, skip this combo */
- if( !(x < sd->combos.count) )
+ if( x == sd->combo_count )
continue;
- sd->combos.bonus[x] = NULL;
- sd->combos.id[x] = 0;
+ sd->combos[x].bonus = NULL;
+ sd->combos[x].id = 0;
+
retval++;
- for( j = 0, cursor = 0; j < sd->combos.count; j++ ) {
- if( sd->combos.bonus[j] == NULL )
+
+ for( j = 0, cursor = 0; j < sd->combo_count; j++ ) {
+ if( sd->combos[j].bonus == NULL )
continue;
if( cursor != j ) {
- sd->combos.bonus[cursor] = sd->combos.bonus[j];
- sd->combos.id[cursor] = sd->combos.id[j];
+ sd->combos[cursor].bonus = sd->combos[j].bonus;
+ sd->combos[cursor].id = sd->combos[j].id;
}
cursor++;
}
- /* check if combo requirements still fit */
- if( pc->checkcombo( sd, data ) )
- continue;
-
/* it's empty, we can clear all the memory */
- if( (sd->combos.count = cursor) == 0 ) {
- aFree(sd->combos.bonus);
- aFree(sd->combos.id);
- sd->combos.bonus = NULL;
- sd->combos.id = NULL;
- return retval; /* we also can return at this point for we have no more combos to check */
+ if( (sd->combo_count = cursor) == 0 ) {
+ aFree(sd->combos);
+ sd->combos = NULL;
+ break;
}
-
}
+
+ /* check if combo requirements still fit -- don't touch retval! */
+ pc->checkcombo( sd, data );
return retval;
}
@@ -8518,13 +8619,13 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
nullpo_ret(sd);
if( n < 0 || n >= MAX_INVENTORY ) {
- clif->equipitemack(sd,0,0,0);
+ clif->equipitemack(sd,0,0,EIA_FAIL);
return 0;
}
if( DIFF_TICK(sd->canequip_tick,timer->gettick()) > 0 )
{
- clif->equipitemack(sd,n,0,0);
+ clif->equipitemack(sd,n,0,EIA_FAIL);
return 0;
}
@@ -8535,27 +8636,38 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
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]
// FIXME: pc->isequip: equip level failure uses 2 instead of 0
- clif->equipitemack(sd,n,0,0); // fail
+ clif->equipitemack(sd,n,0,EIA_FAIL); // fail
return 0;
}
- if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAY_NIGHT_FEVER])
+ if (sd->sc.data[SC_BERSERK])
{
- clif->equipitemack(sd,n,0,0); // fail
+ clif->equipitemack(sd,n,0,EIA_FAIL); // fail
return 0;
}
+ /* won't fail from this point onwards */
+ if( id->flag.bindonequip && !sd->status.inventory[n].bound ) {
+ sd->status.inventory[n].bound = (unsigned char)IBT_CHARACTER;
+ clif->notify_bounditem(sd,n);
+ }
+
if(pos == EQP_ACC) { //Accesories should only go in one of the two,
pos = req_pos&EQP_ACC;
if (pos == EQP_ACC) //User specified both slots..
pos = sd->equip_index[EQI_ACC_R] >= 0 ? EQP_ACC_L : EQP_ACC_R;
- }
-
- if(pos == EQP_ARMS && id->equip == EQP_HAND_R)
- { //Dual wield capable weapon.
+ } else if(pos == EQP_ARMS && id->equip == EQP_HAND_R) { //Dual wield capable weapon.
pos = (req_pos&EQP_ARMS);
if (pos == EQP_ARMS) //User specified both slots, pick one for them.
pos = sd->equip_index[EQI_HAND_R] >= 0 ? EQP_HAND_L : EQP_HAND_R;
+ } else if(pos == EQP_SHADOW_ACC) { //Accesories should only go in one of the two,
+ pos = req_pos&EQP_SHADOW_ACC;
+ if (pos == EQP_SHADOW_ACC) //User specified both slots..
+ pos = sd->equip_index[EQI_SHADOW_ACC_R] >= 0 ? EQP_SHADOW_ACC_L : EQP_SHADOW_ACC_R;
+ } else if( pos == EQP_SHADOW_ARMS && id->equip == EQP_SHADOW_WEAPON) { //Dual wield capable weapon.
+ pos = (req_pos&EQP_SHADOW_ARMS);
+ if (pos == EQP_SHADOW_ARMS) //User specified both slots, pick one for them.
+ pos = sd->equip_index[EQI_SHADOW_WEAPON] >= 0 ? EQP_SHADOW_SHIELD : EQP_SHADOW_WEAPON;
}
if (pos&EQP_HAND_R && battle_config.use_weapon_skill_range&BL_PC)
@@ -8581,11 +8693,11 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
clif->arrow_fail(sd,3);
}
else
- clif->equipitemack(sd,n,pos,1);
+ clif->equipitemack(sd,n,pos,EIA_SUCCESS);
sd->status.inventory[n].equip=pos;
- if(pos & EQP_HAND_R) {
+ if(pos & (EQP_HAND_R|EQP_SHADOW_WEAPON)) {
if(id)
sd->weapontype1 = id->look;
else
@@ -8593,19 +8705,16 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
pc->calcweapontype(sd);
clif->changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
}
- if(pos & EQP_HAND_L) {
+ if(pos & (EQP_HAND_L|EQP_SHADOW_SHIELD)) {
if(id) {
if(id->type == IT_WEAPON) {
sd->status.shield = 0;
sd->weapontype2 = id->look;
- }
- else
- if(id->type == IT_ARMOR) {
+ } else if(id->type == IT_ARMOR) {
sd->status.shield = id->look;
sd->weapontype2 = 0;
}
- }
- else
+ } else
sd->status.shield = sd->weapontype2 = 0;
pc->calcweapontype(sd);
clif->changelook(&sd->bl,LOOK_SHIELD,sd->status.shield);
@@ -8690,7 +8799,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
}
}
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
if (flag) //Update skill data
clif->skillinfoblock(sd);
@@ -8730,20 +8839,20 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
nullpo_ret(sd);
if( n < 0 || n >= MAX_INVENTORY ) {
- clif->unequipitemack(sd,0,0,0);
+ clif->unequipitemack(sd,0,0,UIA_FAIL);
return 0;
}
// if player is berserk then cannot unequip
- if (!(flag & 2) && sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAY_NIGHT_FEVER]))
+ if (!(flag & 2) && sd->sc.count && (sd->sc.data[SC_BERSERK]))
{
- clif->unequipitemack(sd,n,0,0);
+ clif->unequipitemack(sd,n,0,UIA_FAIL);
return 0;
}
if( !(flag&2) && sd->sc.count && sd->sc.data[SC_KYOUGAKU] )
{
- clif->unequipitemack(sd,n,0,0);
+ clif->unequipitemack(sd,n,0,UIA_FAIL);
return 0;
}
@@ -8751,7 +8860,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
ShowInfo("unequip %d %x:%x\n",n,pc->equippoint(sd,n),sd->status.inventory[n].equip);
if(!sd->status.inventory[n].equip){ //Nothing to unequip
- clif->unequipitemack(sd,n,0,0);
+ clif->unequipitemack(sd,n,0,UIA_FAIL);
return 0;
}
for(i=0;i<EQI_MAX;i++) {
@@ -8813,7 +8922,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
clif->changelook(&sd->bl,LOOK_ROBE,sd->status.robe);
}
- clif->unequipitemack(sd,n,sd->status.inventory[n].equip,1);
+ clif->unequipitemack(sd,n,sd->status.inventory[n].equip,UIA_SUCCESS);
if((sd->status.inventory[n].equip & 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!)
@@ -8855,7 +8964,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
if(flag&1 || status_cacl) {
pc->checkallowskill(sd);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
}
if(sd->sc.data[SC_CRUCIS] && !battle->check_undead(sd->battle_status.race,sd->battle_status.def_ele))
@@ -8892,14 +9001,14 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
*------------------------------------------*/
int pc_checkitem(struct map_session_data *sd)
{
- int i,id,calc_flag = 0;
+ int i, id, calc_flag = 0;
nullpo_ret(sd);
if( sd->state.vending ) //Avoid reorganizing items when we are vending, as that leads to exploits (pointed out by End of Exam)
return 0;
- if( battle_config.item_check ) { // check for invalid(ated) items
+ if( sd->state.itemcheck ) { // check for invalid(ated) items
for( i = 0; i < MAX_INVENTORY; i++ ) {
id = sd->status.inventory[i].nameid;
@@ -8927,7 +9036,7 @@ int pc_checkitem(struct map_session_data *sd)
}
}
- if (sd->state.gmaster_flag) {
+ if (sd->guild) {
struct guild_storage *guild_storage = gstorage->id2storage2(sd->guild->guild_id);
if (guild_storage) {
for( i = 0; i < MAX_GUILD_STORAGE; i++ ) {
@@ -8940,6 +9049,7 @@ int pc_checkitem(struct map_session_data *sd)
}
}
}
+ sd->state.itemcheck = 0;
}
for( i = 0; i < MAX_INVENTORY; i++) {
@@ -8957,10 +9067,10 @@ int pc_checkitem(struct map_session_data *sd)
}
}
-
+
if( calc_flag && sd->state.active ) {
pc->checkallowskill(sd);
- status_calc_pc(sd,0);
+ status_calc_pc(sd,SCO_NONE);
}
return 0;
@@ -9003,7 +9113,7 @@ int pc_calc_pvprank(struct map_session_data *sd) {
/*==========================================
* Calculate next sd ranking calculation from config
*------------------------------------------*/
-int pc_calc_pvprank_timer(int tid, unsigned int tick, int id, intptr_t data) {
+int pc_calc_pvprank_timer(int tid, int64 tick, int id, intptr_t data) {
struct map_session_data *sd;
sd=map->id2sd(id);
@@ -9204,11 +9314,10 @@ void pc_regen (struct map_session_data *sd, unsigned int diff_tick) {
/*==========================================
* Memo player sd savepoint. (map,x,y)
*------------------------------------------*/
-int pc_setsavepoint(struct map_session_data *sd, short mapindex,int x,int y)
-{
+int pc_setsavepoint(struct map_session_data *sd, short map_index, int x, int y) {
nullpo_ret(sd);
- sd->status.save_point.map = mapindex;
+ sd->status.save_point.map = map_index;
sd->status.save_point.x = x;
sd->status.save_point.y = y;
@@ -9216,10 +9325,9 @@ int pc_setsavepoint(struct map_session_data *sd, short mapindex,int x,int y)
}
/*==========================================
- * Save 1 player data at autosave intervalle
+ * Save 1 player data at autosave intervall
*------------------------------------------*/
-int pc_autosave(int tid, unsigned int tick, int id, intptr_t data)
-{
+int pc_autosave(int tid, int64 tick, int id, intptr_t data) {
int interval;
struct s_mapiterator* iter;
struct map_session_data* sd;
@@ -9270,7 +9378,7 @@ int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap) {
* timer to do the day [Yor]
* data: 0 = called by timer, 1 = gmcommand/script
*------------------------------------------------*/
-int map_day_timer(int tid, unsigned int tick, int id, intptr_t data) {
+int map_day_timer(int tid, int64 tick, int id, intptr_t data) {
char tmp_soutput[1024];
if (data == 0 && battle_config.day_duration <= 0) // if we want a day
@@ -9290,7 +9398,7 @@ int map_day_timer(int tid, unsigned int tick, int id, intptr_t data) {
* timer to do the night [Yor]
* data: 0 = called by timer, 1 = gmcommand/script
*------------------------------------------------*/
-int map_night_timer(int tid, unsigned int tick, int id, intptr_t data) {
+int map_night_timer(int tid, int64 tick, int id, intptr_t data) {
char tmp_soutput[1024];
if (data == 0 && battle_config.night_duration <= 0) // if we want a night
@@ -9334,9 +9442,9 @@ void pc_overheat(struct map_session_data *sd, int val) {
heat = max(0,heat); // Avoid negative HEAT
if( heat >= limit[skill_lv] )
- sc_start(&sd->bl,SC_OVERHEAT,100,0,1000);
+ sc_start(NULL,&sd->bl,SC_OVERHEAT,100,0,1000);
else
- sc_start(&sd->bl,SC_OVERHEAT_LIMITPOINT,100,heat,30000);
+ sc_start(NULL,&sd->bl,SC_OVERHEAT_LIMITPOINT,100,heat,30000);
return;
}
@@ -9346,10 +9454,16 @@ void pc_overheat(struct map_session_data *sd, int val) {
*/
bool pc_isautolooting(struct map_session_data *sd, int nameid)
{
- int i;
- if( !sd->state.autolooting )
+ int i = 0;
+
+ if (sd->state.autoloottype && sd->state.autoloottype&(1<<itemdb_type(nameid)))
+ return true;
+
+ if (!sd->state.autolooting)
return false;
+
ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] == nameid);
+
return (i != AUTOLOOTITEM_SIZE);
}
@@ -9362,7 +9476,7 @@ bool pc_can_use_command(struct map_session_data *sd, const char *command) {
return atcommand->can_use(sd,command);
}
-int pc_charm_timer(int tid, unsigned int tick, int id, intptr_t data) {
+int pc_charm_timer(int tid, int64 tick, int id, intptr_t data) {
struct map_session_data *sd;
int i, type;
@@ -9680,14 +9794,14 @@ void pc_read_skill_tree(void) {
{ "Rebellion", JOB_REBELLION },
};
- if (conf_read_file(&skill_tree_conf, config_filename)) {
+ if (libconfig->read_file(&skill_tree_conf, config_filename)) {
ShowError("can't read %s\n", config_filename);
return;
}
jnamelen = ARRAYLENGTH(jnames);
- while( (skt = config_setting_get_elem(skill_tree_conf.root,i++)) ) {
+ while( (skt = libconfig->setting_get_elem(skill_tree_conf.root,i++)) ) {
int k, idx;
const char *name = config_setting_name(skt);
@@ -9699,12 +9813,12 @@ void pc_read_skill_tree(void) {
}
- if( ( skills = config_setting_get_member(skt,"skills") ) ) {
+ if( ( skills = libconfig->setting_get_member(skt,"skills") ) ) {
int c = 0;
idx = pc->class2idx(jnames[k].id);
- while( ( sk = config_setting_get_elem(skills,c++) ) ) {
+ while( ( sk = libconfig->setting_get_elem(skills,c++) ) ) {
const char *sk_name = config_setting_name(sk);
int skill_id;
@@ -9724,23 +9838,23 @@ void pc_read_skill_tree(void) {
if( config_setting_is_group(sk) ) {
int max = 0, jlevel = 0;
- config_setting_lookup_int(sk, "MaxLevel", &max);
- config_setting_lookup_int(sk, "MinJobLevel", &jlevel);
+ libconfig->setting_lookup_int(sk, "MaxLevel", &max);
+ libconfig->setting_lookup_int(sk, "MinJobLevel", &jlevel);
pc->skill_tree[idx][skidx].max = (unsigned char)max;
pc->skill_tree[idx][skidx].joblv = (unsigned char)jlevel;
- rlen = config_setting_length(sk);
+ rlen = libconfig->setting_length(sk);
offset += jlevel ? 2 : 1;
} else {
- pc->skill_tree[idx][skidx].max = (unsigned char)config_setting_get_int(sk);
+ pc->skill_tree[idx][skidx].max = (unsigned char)libconfig->setting_get_int(sk);
pc->skill_tree[idx][skidx].joblv = 0;
}
for( h = offset; h < rlen && h < MAX_PC_SKILL_REQUIRE; h++ ) {
- config_setting_t *rsk = config_setting_get_elem(sk,h);
+ config_setting_t *rsk = libconfig->setting_get_elem(sk,h);
if( rsk && ( rskid = skill->name2id(config_setting_name(rsk)) ) ) {
pc->skill_tree[idx][skidx].need[h].id = rskid;
pc->skill_tree[idx][skidx].need[h].idx = skill->get_index(rskid);
- pc->skill_tree[idx][skidx].need[h].lv = (unsigned char)config_setting_get_int(rsk);
+ pc->skill_tree[idx][skidx].need[h].lv = (unsigned char)libconfig->setting_get_int(rsk);
} else if( rsk ) {
ShowWarning("pc_read_skill_tree: unknown requirement '%s' for '%s' in '%s'\n",config_setting_name(rsk),sk_name,name);
} else {
@@ -9756,7 +9870,7 @@ void pc_read_skill_tree(void) {
}
i = 0;
- while( (skt = config_setting_get_elem(skill_tree_conf.root,i++)) ) {
+ while( (skt = libconfig->setting_get_elem(skill_tree_conf.root,i++)) ) {
int k, idx, v = 0;
const char *name = config_setting_name(skt);
const char *iname;
@@ -9770,8 +9884,8 @@ void pc_read_skill_tree(void) {
}
idx = pc->class2idx(jnames[k].id);
- if( ( inherit = config_setting_get_member(skt,"inherit") ) ) {
- while( ( iname = config_setting_get_string_elem(inherit, v++) ) ) {
+ if( ( inherit = libconfig->setting_get_member(skt,"inherit") ) ) {
+ while( ( iname = libconfig->setting_get_string_elem(inherit, v++) ) ) {
int b = 0, a, d, f, fidx;
ARR_FIND(0, jnamelen, b, strcmpi(jnames[b].name,iname) == 0 );
@@ -9803,7 +9917,7 @@ void pc_read_skill_tree(void) {
}
- config_destroy(&skill_tree_conf);
+ libconfig->destroy(&skill_tree_conf);
/* lets update all players skill tree */
iter = mapit_getallusers();
@@ -9995,8 +10109,10 @@ int pc_readdb(void) {
while(*p==32 && *p>0)
p++;
battle->attr_fix_table[lv-1][i][j]=atoi(p);
+#ifndef RENEWAL
if(battle_config.attr_recover == 0 && battle->attr_fix_table[lv-1][i][j] < 0)
battle->attr_fix_table[lv-1][i][j] = 0;
+#endif
p=strchr(p,',');
if(p) *p++=0;
}
@@ -10022,7 +10138,7 @@ int pc_readdb(void) {
int stat;
if(line[0]=='/' && line[1]=='/')
continue;
- if ((stat=strtoul(line,NULL,10))<0)
+ if ((stat=(int)strtol(line,NULL,10))<0)
stat=0;
if (i > MAX_LEVEL)
break;
@@ -10079,25 +10195,357 @@ void pc_itemcd_do(struct map_session_data *sd, bool load) {
return;
}
-/*==========================================
- * pc Init/Terminate
- *------------------------------------------*/
-void do_final_pc(void) {
+void pc_bank_deposit(struct map_session_data *sd, int money) {
+ unsigned int limit_check = money+sd->status.bank_vault;
+
+ if( money <= 0 || limit_check > MAX_BANK_ZENY ) {
+ clif->bank_deposit(sd,BDA_OVERFLOW);
+ return;
+ } else if ( money > sd->status.zeny ) {
+ clif->bank_deposit(sd,BDA_NO_MONEY);
+ return;
+ }
- db_destroy(pc->itemcd_db);
+ if( pc->payzeny(sd,money, LOG_TYPE_BANK, NULL) )
+ clif->bank_deposit(sd,BDA_NO_MONEY);
+ else {
+ sd->status.bank_vault += money;
+ if( map->save_settings&256 )
+ chrif->save(sd,0);
+ clif->bank_deposit(sd,BDA_SUCCESS);
+ }
+}
+void pc_bank_withdraw(struct map_session_data *sd, int money) {
+ unsigned int limit_check = money+sd->status.zeny;
+
+ if( money <= 0 ) {
+ clif->bank_withdraw(sd,BWA_UNKNOWN_ERROR);
+ return;
+ } else if ( money > sd->status.bank_vault ) {
+ clif->bank_withdraw(sd,BWA_NO_MONEY);
+ return;
+ } else if ( limit_check > MAX_ZENY ) {
+ /* no official response for this scenario exists. */
+ clif->colormes(sd->fd,COLOR_RED,msg_txt(1482));
+ return;
+ }
+
+ if( pc->getzeny(sd,money, LOG_TYPE_BANK, NULL) )
+ clif->bank_withdraw(sd,BWA_NO_MONEY);
+ else {
+ sd->status.bank_vault -= money;
+ if( map->save_settings&256 )
+ chrif->save(sd,0);
+ clif->bank_withdraw(sd,BWA_SUCCESS);
+ }
+}
+/* status change data arrived from char-server */
+void pc_scdata_received(struct map_session_data *sd) {
+ pc->inventory_rentals(sd);
+ clif->show_modifiers(sd);
+
+ if (sd->expiration_time != 0) { // don't display if it's unlimited or unknow value
+ time_t exp_time = sd->expiration_time;
+ char tmpstr[1024];
+ strftime(tmpstr, sizeof(tmpstr) - 1, msg_txt(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);
+
+ pc->expire_check(sd);
+ }
+
+ if( sd->state.standalone ) {
+ clif->pLoadEndAck(0,sd);
+ pc->autotrade_populate(sd);
+ pc->autotrade_start(sd);
+ }
+}
+int pc_expiration_timer(int tid, int64 tick, int id, intptr_t data) {
+ struct map_session_data *sd = map->id2sd(id);
+
+ if( !sd ) return 0;
+
+ sd->expiration_tid = INVALID_TIMER;
+
+ if( sd->fd )
+ clif->authfail_fd(sd->fd,10);
+
+ map->quit(sd);
+
+ return 0;
+}
+/* this timer exists only when a character with a expire timer > 24h is online */
+/* it loops thru online players once an hour to check whether a new < 24h is available */
+int pc_global_expiration_timer(int tid, int64 tick, int id, intptr_t data) {
+ struct s_mapiterator* iter;
+ struct map_session_data* sd;
- do_final_pc_groups();
+ iter = mapit_getallusers();
+
+ for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) {
+ if( sd->expiration_time )
+ pc->expire_check(sd);
+ }
+
+ mapit->free(iter);
+
+ return 0;
+}
+void pc_expire_check(struct map_session_data *sd) {
+ /* ongoing timer */
+ if( sd->expiration_tid != INVALID_TIMER )
+ return;
+
+ /* not within the next 24h, enable the global check */
+ if( sd->expiration_time > ( time(NULL) + ( ( 60 * 60 ) * 24 ) ) ) {
+
+ /* global check not running, enable */
+ if( pc->expiration_tid == INVALID_TIMER ) {
+ /* starts in 1h, repeats every hour */
+ pc->expiration_tid = timer->add_interval(timer->gettick() + ((1000*60)*60), pc->global_expiration_timer, 0, 0, ((1000*60)*60));
+ }
+
+ return;
+ }
+
+ sd->expiration_tid = timer->add(timer->gettick() + (int64)(sd->expiration_time - time(NULL))*1000, pc->expiration_timer, sd->bl.id, 0);
+}
+/**
+ * Loads autotraders
+ ***/
+void pc_autotrade_load(void) {
+ struct map_session_data *sd;
+ char *data;
+
+ if (SQL_ERROR == SQL->Query(map->mysql_handle, "SELECT `account_id`,`char_id`,`sex`,`title` FROM `%s`",map->autotrade_merchants_db))
+ Sql_ShowDebug(map->mysql_handle);
+
+ while( SQL_SUCCESS == SQL->NextRow(map->mysql_handle) ) {
+ int account_id, char_id;
+ char title[MESSAGE_SIZE];
+ unsigned char sex;
+
+ SQL->GetData(map->mysql_handle, 0, &data, NULL); account_id = atoi(data);
+ SQL->GetData(map->mysql_handle, 1, &data, NULL); char_id = atoi(data);
+ SQL->GetData(map->mysql_handle, 2, &data, NULL); sex = atoi(data);
+ SQL->GetData(map->mysql_handle, 3, &data, NULL); safestrncpy(title, data, sizeof(title));
+
+ CREATE(sd, TBL_PC, 1);
+
+ pc->setnewpc(sd, account_id, char_id, 0, 0, sex, 0);
+
+ safestrncpy(sd->message, title, MESSAGE_SIZE);
+
+ sd->state.standalone = 1;
+ sd->group = pcg->get_dummy_group();
+
+ chrif->authreq(sd,true);
+ }
+
+ SQL->FreeResult(map->mysql_handle);
+}
+/**
+ * Loads vending data and sets it up, is triggered when char server data that pc_autotrade_load requested arrives
+ **/
+void pc_autotrade_start(struct map_session_data *sd) {
+ unsigned int count = 0;
+ int i;
+ char *data;
+
+ 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);
+
+ while( SQL_SUCCESS == SQL->NextRow(map->mysql_handle) ) {
+ int itemkey, amount, price;
+
+ SQL->GetData(map->mysql_handle, 0, &data, NULL); itemkey = atoi(data);
+ SQL->GetData(map->mysql_handle, 1, &data, NULL); amount = atoi(data);
+ SQL->GetData(map->mysql_handle, 2, &data, NULL); price = atoi(data);
+
+ ARR_FIND(0, MAX_CART, i, sd->status.cart[i].id == itemkey);
+
+ if( i != MAX_CART && itemdb_cantrade(&sd->status.cart[i], 0, 0) ) {
+ if( amount > sd->status.cart[i].amount )
+ amount = sd->status.cart[i].amount;
+
+ if( amount ) {
+ sd->vending[count].index = i;
+ sd->vending[count].amount = amount;
+ sd->vending[count].value = cap_value(price, 0, (unsigned int)battle_config.vending_max_value);
+
+ count++;
+ }
+ }
+ }
+
+ if( !count ) {
+ pc->autotrade_update(sd,PAUC_REMOVE);
+ map->quit(sd);
+ } else {
+ sd->state.autotrade = 1;
+ sd->vender_id = ++vending->next_id;
+ sd->vend_num = count;
+ sd->state.vending = true;
+ idb_put(vending->db, sd->status.char_id, sd);
+ if( map->list[sd->bl.m].users )
+ clif->showvendingboard(&sd->bl,sd->message,0);
+ }
+}
+/**
+ * Perform a autotrade action
+ **/
+void pc_autotrade_update(struct map_session_data *sd, enum e_pc_autotrade_update_action action) {
+ int i;
+
+ /* 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))
+ Sql_ShowDebug(map->mysql_handle);
+ }
+
+ switch( action ) {
+ case PAUC_REMOVE:
+ if (SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d' LIMIT 1",map->autotrade_merchants_db,sd->status.char_id))
+ Sql_ShowDebug(map->mysql_handle);
+ break;
+ case PAUC_START: {
+ char title[MESSAGE_SIZE*2+1];
+
+ SQL->EscapeStringLen(map->mysql_handle, title, sd->message, strnlen(sd->message, MESSAGE_SIZE));
+
+ if (SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `%s` (`account_id`,`char_id`,`sex`,`title`) VALUES ('%d','%d','%d','%s')",
+ map->autotrade_merchants_db,
+ sd->status.account_id,
+ sd->status.char_id,
+ sd->status.sex,
+ title
+ ))
+ Sql_ShowDebug(map->mysql_handle);
+ }
+ /* yes we want it to fall */
+ 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')",
+ map->autotrade_data_db,
+ sd->status.char_id,
+ sd->status.cart[sd->vending[i].index].id,
+ sd->vending[i].amount,
+ sd->vending[i].value
+ ))
+ Sql_ShowDebug(map->mysql_handle);
+ }
+ break;
+ }
+}
+/**
+ * Handles characters upon @autotrade usage
+ **/
+void pc_autotrade_prepare(struct map_session_data *sd) {
+ struct autotrade_vending *data;
+ int i, cursor = 0;
+ int account_id, char_id;
+ char title[MESSAGE_SIZE];
+ unsigned char sex;
+
+ CREATE(data, struct autotrade_vending, 1);
+
+ memcpy(data->vending, sd->vending, sizeof(sd->vending));
+
+ for(i = 0; i < sd->vend_num; i++) {
+ if( sd->vending[i].amount ) {
+ memcpy(&data->list[cursor],&sd->status.cart[sd->vending[i].index],sizeof(struct item));
+ cursor++;
+ }
+ }
+
+ data->vend_num = (unsigned char)cursor;
+
+ idb_put(pc->at_db, sd->status.char_id, data);
+
+ account_id = sd->status.account_id;
+ char_id = sd->status.char_id;
+ sex = sd->status.sex;
+ safestrncpy(title, sd->message, sizeof(title));
+
+ map->quit(sd);
+ chrif->auth_delete(account_id, char_id, ST_LOGOUT);
+
+ CREATE(sd, TBL_PC, 1);
+
+ pc->setnewpc(sd, account_id, char_id, 0, 0, sex, 0);
+
+ safestrncpy(sd->message, title, MESSAGE_SIZE);
+
+ sd->state.standalone = 1;
+ sd->group = pcg->get_dummy_group();
+
+ chrif->authreq(sd,true);
+}
+/**
+ * Prepares autotrade data from pc->at_db from a player that has already returned from char server
+ **/
+void pc_autotrade_populate(struct map_session_data *sd) {
+ struct autotrade_vending *data;
+ int i, j, k, cursor = 0;
+
+ if( !(data = idb_get(pc->at_db,sd->status.char_id)) )
+ return;
+
+ for(i = 0; i < data->vend_num; i++) {
+ if( !data->vending[i].amount )
+ continue;
+
+ for(j = 0; j < MAX_CART; j++) {
+ if( !memcmp((char*)(&data->list[i]) + sizeof(data->list[0].id), (char*)(&sd->status.cart[j]) + sizeof(data->list[0].id), sizeof(struct item) - sizeof(data->list[0].id)) ) {
+ if( cursor ) {
+ ARR_FIND(0, cursor, k, sd->vending[k].index == j);
+ if( k != cursor )
+ continue;
+ }
+ break;
+ }
+ }
+
+ if( j != MAX_CART ) {
+ sd->vending[cursor].index = j;
+ sd->vending[cursor].amount = data->vending[i].amount;
+ sd->vending[cursor].value = data->vending[i].value;
+
+ cursor++;
+ }
+ }
+
+ sd->vend_num = cursor;
+
+ pc->autotrade_update(sd,PAUC_START);
+
+ idb_remove(pc->at_db, sd->status.char_id);
+}
+void do_final_pc(void) {
+
+ db_destroy(pc->itemcd_db);
+ db_destroy(pc->at_db);
+
+ pcg->final();
ers_destroy(pc->sc_display_ers);
+ ers_destroy(pc->num_reg_ers);
+ ers_destroy(pc->str_reg_ers);
+
return;
}
-void do_init_pc(void) {
-
+void do_init_pc(bool minimal) {
+ if (minimal)
+ return;
+
pc->itemcd_db = idb_alloc(DB_OPT_RELEASE_DATA);
-
+ pc->at_db = idb_alloc(DB_OPT_RELEASE_DATA);
+
pc->readdb();
-
+
timer->add_func_list(pc->invincible_timer, "pc_invincible_timer");
timer->add_func_list(pc->eventtimer, "pc_eventtimer");
timer->add_func_list(pc->inventory_rental_end, "pc_inventory_rental_end");
@@ -10107,28 +10555,35 @@ void do_init_pc(void) {
timer->add_func_list(pc->follow_timer, "pc_follow_timer");
timer->add_func_list(pc->endautobonus, "pc_endautobonus");
timer->add_func_list(pc->charm_timer, "pc_charm_timer");
-
+ timer->add_func_list(pc->global_expiration_timer,"pc_global_expiration_timer");
+ timer->add_func_list(pc->expiration_timer,"pc_expiration_timer");
+
timer->add(timer->gettick() + map->autosave_interval, pc->autosave, 0, 0);
-
+
// 0=day, 1=night [Yor]
map->night_flag = battle_config.night_at_start ? 1 : 0;
-
+
if (battle_config.day_duration > 0 && battle_config.night_duration > 0) {
int day_duration = battle_config.day_duration;
int night_duration = battle_config.night_duration;
// add night/day timer [Yor]
timer->add_func_list(pc->map_day_timer, "pc_map_day_timer");
timer->add_func_list(pc->map_night_timer, "pc_map_night_timer");
-
+
pc->day_timer_tid = timer->add_interval(timer->gettick() + (map->night_flag ? 0 : day_duration) + night_duration, pc->map_day_timer, 0, 0, day_duration + night_duration);
pc->night_timer_tid = timer->add_interval(timer->gettick() + day_duration + (map->night_flag ? night_duration : 0), pc->map_night_timer, 0, 0, day_duration + night_duration);
}
-
- do_init_pc_groups();
- pc->sc_display_ers = ers_new(sizeof(struct sc_display_entry), "pc.c:sc_display_ers", ERS_OPT_NONE);
-}
+ pcg->init();
+
+ pc->sc_display_ers = ers_new(sizeof(struct sc_display_entry), "pc.c:sc_display_ers", ERS_OPT_FLEX_CHUNK);
+ pc->num_reg_ers = ers_new(sizeof(struct script_reg_num), "pc.c::num_reg_ers", ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK);
+ pc->str_reg_ers = ers_new(sizeof(struct script_reg_str), "pc.c::str_reg_ers", ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK);
+ ers_chunk_size(pc->sc_display_ers, 150);
+ ers_chunk_size(pc->num_reg_ers, 300);
+ ers_chunk_size(pc->str_reg_ers, 50);
+}
/*=====================================
* Default Functions : pc.h
* Generated by HerculesInterfaceMaker
@@ -10140,12 +10595,12 @@ void pc_defaults(void) {
{ SG_MOON_ANGER, SG_MOON_BLESS, SG_MOON_COMFORT, "PC_FEEL_MOON", "PC_HATE_MOB_MOON", is_day_of_moon },
{ SG_STAR_ANGER, SG_STAR_BLESS, SG_STAR_COMFORT, "PC_FEEL_STAR", "PC_HATE_MOB_STAR", is_day_of_star }
};
- unsigned short equip_pos[EQI_MAX]={EQP_ACC_L,EQP_ACC_R,EQP_SHOES,EQP_GARMENT,EQP_HEAD_LOW,EQP_HEAD_MID,EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_GARMENT,EQP_AMMO};
-
+ unsigned int equip_pos[EQI_MAX]={EQP_ACC_L,EQP_ACC_R,EQP_SHOES,EQP_GARMENT,EQP_HEAD_LOW,EQP_HEAD_MID,EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_GARMENT,EQP_AMMO, EQP_SHADOW_ARMOR, EQP_SHADOW_WEAPON, EQP_SHADOW_SHIELD, EQP_SHADOW_SHOES, EQP_SHADOW_ACC_R, EQP_SHADOW_ACC_L };
pc = &pc_s;
/* vars */
+ pc->at_db = NULL;
pc->itemcd_db = NULL;
/* */
pc->day_timer_tid = INVALID_TIMER;
@@ -10168,17 +10623,21 @@ void pc_defaults(void) {
memcpy(pc->sg_info, sg_info, sizeof(pc->sg_info));
/* */
pc->sc_display_ers = NULL;
+ /* */
+ pc->expiration_tid = INVALID_TIMER;
+ /* */
+ pc->num_reg_ers = NULL;
+ pc->str_reg_ers = NULL;
+ /* */
+ pc->reg_load = false;
/* funcs */
pc->init = do_init_pc;
pc->final = do_final_pc;
pc->get_dummy_sd = pc_get_dummy_sd;
pc->class2idx = pc_class2idx;
- pc->get_group_level = pc_get_group_level;
- pc->can_give_items = pc_can_give_items;
pc->can_use_command = pc_can_use_command;
- pc->has_permission = pc_has_permission;
pc->set_group = pc_set_group;
pc->should_log_commands = pc_should_log_commands;
@@ -10268,6 +10727,7 @@ void pc_defaults(void) {
pc->thisjobexp = pc_thisjobexp;
pc->gets_status_point = pc_gets_status_point;
pc->need_status_point = pc_need_status_point;
+ pc->maxparameterincrease = pc_maxparameterincrease;
pc->statusup = pc_statusup;
pc->statusup2 = pc_statusup2;
pc->skillup = pc_skillup;
@@ -10402,4 +10862,25 @@ void pc_defaults(void) {
pc->checkcombo = pc_checkcombo;
pc->calcweapontype = pc_calcweapontype;
pc->removecombo = pc_removecombo;
+
+ pc->bank_withdraw = pc_bank_withdraw;
+ pc->bank_deposit = pc_bank_deposit;
+
+ pc->rental_expire = pc_rental_expire;
+ pc->scdata_received = pc_scdata_received;
+
+ pc->bound_clear = pc_bound_clear;
+
+ pc->expiration_timer = pc_expiration_timer;
+ pc->global_expiration_timer = pc_global_expiration_timer;
+ pc->expire_check = pc_expire_check;
+
+ /**
+ * Autotrade persistency [Ind/Hercules <3]
+ **/
+ pc->autotrade_load = pc_autotrade_load;
+ pc->autotrade_update = pc_autotrade_update;
+ pc->autotrade_start = pc_autotrade_start;
+ pc->autotrade_prepare = pc_autotrade_prepare;
+ pc->autotrade_populate = pc_autotrade_populate;
}