From 2732176786f3ba91908c747a540b004b345548e2 Mon Sep 17 00:00:00 2001 From: aleos89 Date: Tue, 20 May 2014 10:41:15 -0400 Subject: [PATCH] Modified status_calc_* to support multiple options. (Hercules 6f77d07) --- src/map/atcommand.c | 16 ++++--- src/map/battle.c | 39 +++++++++++----- src/map/chrif.c | 2 +- src/map/clif.c | 2 +- src/map/elemental.c | 2 +- src/map/guild.c | 2 +- src/map/homunculus.c | 19 ++++---- src/map/itemdb.c | 3 +- src/map/mercenary.c | 18 +++----- src/map/mob.c | 9 ++-- src/map/pc.c | 98 ++++++++++++++++++--------------------- src/map/pc.h | 3 ++ src/map/pet.c | 63 ++++++++++++------------- src/map/script.c | 83 +++++++++++++++++---------------- src/map/status.c | 107 ++++++++++++++++++++++++------------------- src/map/status.h | 37 +++++++++------ 16 files changed, 263 insertions(+), 240 deletions(-) diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 7aaccc020a..b5eabbfc5d 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -1398,6 +1398,7 @@ ACMD_FUNC(baselevelup) sd->status.status_point += status_point; sd->status.base_level += (unsigned int)level; + status_calc_pc(sd, SCO_FORCE); status_percent_heal(&sd->bl, 100, 100); clif_misceffect(&sd->bl, 0); clif_displaymessage(fd, msg_txt(sd,21)); // Base level raised. @@ -1419,13 +1420,13 @@ ACMD_FUNC(baselevelup) sd->status.status_point -= status_point; sd->status.base_level -= (unsigned int)level; clif_displaymessage(fd, msg_txt(sd,22)); // Base level lowered. + status_calc_pc(sd, SCO_FORCE); } sd->status.base_exp = 0; 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); pc_baselevelchanged(sd); if(sd->status.party_id) party_send_levelup(sd); @@ -1479,7 +1480,7 @@ ACMD_FUNC(joblevelup) 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); return 0; } @@ -2539,7 +2540,7 @@ ACMD_FUNC(param) *status[i] = new_value; clif_updatestatus(sd, SP_STR + i); clif_updatestatus(sd, SP_USTR + i); - status_calc_pc(sd, 0); + status_calc_pc(sd, SCO_FORCE); clif_displaymessage(fd, msg_txt(sd,42)); // Stat changed. } else { if (value < 0) @@ -2610,7 +2611,7 @@ ACMD_FUNC(stat_all) } if (count > 0) { // if at least 1 stat modified - status_calc_pc(sd, 0); + status_calc_pc(sd, SCO_FORCE); clif_displaymessage(fd, msg_txt(sd,84)); // All stats changed! } else { if (value < 0) @@ -7146,13 +7147,14 @@ ACMD_FUNC(homlevel) for (i = 1; i <= level && hd->exp_next; i++){ hd->homunculus.exp += hd->exp_next; - if( !hom_levelup(hd) ){ + if( !hom_levelup(hd) ) break; - } } - status_calc_homunculus(hd,0); + + status_calc_homunculus(hd, SCO_NONE); status_percent_heal(&hd->bl, 100, 100); clif_specialeffect(&hd->bl,568,AREA); + return 0; } diff --git a/src/map/battle.c b/src/map/battle.c index 0737ca9095..a61a65586e 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -213,16 +213,22 @@ struct delay_damage { enum damage_lv dmg_lv; unsigned short attack_type; bool additional_effects; + enum bl_type src_type; }; int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) { struct delay_damage *dat = (struct delay_damage *)data; if ( dat ) { - struct block_list* src; + struct block_list* src = NULL; struct block_list* target = map_id2bl(dat->target_id); - if( !target || status_isdead(target) ) {/* nothing we can do */ + if( !target || status_isdead(target) ) { /* Nothing we can do */ + if( dat->src_type == BL_PC && (src = map_id2bl(dat->src_id)) && + --((TBL_PC*)src)->delayed_damage == 0 && ((TBL_PC*)src)->state.hold_recalc ) { + ((TBL_PC*)src)->state.hold_recalc = 0; + status_calc_pc(((TBL_PC*)src), SCO_FORCE); + } ers_free(delay_damage_ers, dat); return 0; } @@ -248,12 +254,17 @@ int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) { status_fix_damage(target, target, dat->damage, dat->delay); map_freeblock_unlock(); } + + if( src && src->type == BL_PC && --((TBL_PC*)src)->delayed_damage == 0 && ((TBL_PC*)src)->state.hold_recalc ) { + ((TBL_PC*)src)->state.hold_recalc = 0; + status_calc_pc(((TBL_PC*)src), SCO_FORCE); + } } ers_free(delay_damage_ers, dat); return 0; } -int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects) +int battle_delay_damage(unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects) { struct delay_damage *dat; struct status_change *sc; @@ -286,18 +297,24 @@ int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, dat->delay = ddelay; dat->distance = distance_bl(src, target)+10; //Attack should connect regardless unless you teleported. dat->additional_effects = additional_effects; + dat->src_type = src->type; if (src->type != BL_PC && amotion > 1000) amotion = 1000; //Aegis places a damage-delay cap of 1 sec to non player attacks. [Skotlex] + if( src->type == BL_PC ) + ((TBL_PC*)src)->delayed_damage++; + add_timer(tick+amotion, battle_delay_damage_sub, 0, (intptr_t)dat); return 0; } -int battle_attr_ratio(int atk_elem,int def_type, int def_lv){ + +int battle_attr_ratio(int atk_elem,int def_type, int def_lv) { if (atk_elem < ELE_NEUTRAL || atk_elem >= ELE_ALL) return 100; if (def_type < ELE_NEUTRAL || def_type > ELE_ALL || def_lv < 1 || def_lv > 4) return 100; + return attr_fix_table[def_lv-1][atk_elem][def_type]; } @@ -2569,12 +2586,10 @@ struct Damage battle_calc_damage_parts(struct Damage wd, struct block_list *src, wd.statusAtk += battle_calc_status_attack(sstatus, EQI_HAND_R); wd.statusAtk2 += battle_calc_status_attack(sstatus, EQI_HAND_L); - if (skill_id || (sd && sd->sc.data[SC_SEVENWIND])) { - // Mild Wind applies element to status ATK as well as weapon ATK [helvetica] + if (skill_id || (sd && sd->sc.data[SC_SEVENWIND])) { // Mild Wind applies element to status ATK as well as weapon ATK [helvetica] wd.statusAtk = (int)battle_attr_fix(src, target, wd.statusAtk, right_element, tstatus->def_ele, tstatus->ele_lv); wd.statusAtk2 = (int)battle_attr_fix(src, target, wd.statusAtk, left_element, tstatus->def_ele, tstatus->ele_lv); - } - else { // status atk is considered neutral on normal attacks [helvetica] + } else { // status atk is considered neutral on normal attacks [helvetica] wd.statusAtk = (int)battle_attr_fix(src, target, wd.statusAtk, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv); wd.statusAtk2 = (int)battle_attr_fix(src, target, wd.statusAtk, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv); } @@ -4775,6 +4790,7 @@ void battle_do_reflect(int attack_type, struct Damage *wd, struct block_list* sr } } } + /*============================================ * Calculate "weapon"-type attacks and skills *-------------------------------------------- @@ -5886,7 +5902,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * memset(&md,0,sizeof(md)); - if( src == NULL || target == NULL ){ + if (src == NULL || target == NULL) { nullpo_info(NLP_MARK); return md; } @@ -5918,8 +5934,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * //Skill Range Criteria md.flag |= battle_range_type(src, target, skill_id, skill_lv); - switch( skill_id ) - { + switch (skill_id) { case NC_MAGMA_ERUPTION: md.damage = 1200 + 400 * skill_lv; break; @@ -7281,7 +7296,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f if(s_guild && t_guild && (s_guild == t_guild || (!(flag&BCT_SAMEGUILD) && guild_isallied(s_guild, t_guild)))) state |= BCT_GUILD; } - } //end non pvp/gvg chk rivality + } //end non pvp/gvg chk rivality if( !state ) //If not an enemy, nor a guild, nor party, nor yourself, it's neutral. state = BCT_NEUTRAL; diff --git a/src/map/chrif.c b/src/map/chrif.c index 0cc02f6179..4d00782599 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -1897,7 +1897,7 @@ int chrif_load_bsdata(int fd) { calc = true; } if (calc) - status_calc_pc(sd,false); + status_calc_pc(sd,SCO_NONE); return 0; } diff --git a/src/map/clif.c b/src/map/clif.c index 7671f044ee..1c8dc46ea8 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -9758,7 +9758,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) } map_iwall_get(sd); // Updates Walls Info on this Map to Client - status_calc_pc(sd, false); // Some conditions are map-dependent so we must recalculate + status_calc_pc(sd, SCO_NONE); // Some conditions are map-dependent so we must recalculate sd->state.changemap = false; // Instances do not need their own channels diff --git a/src/map/elemental.c b/src/map/elemental.c index e5c3db22f2..7a73f8eda9 100644 --- a/src/map/elemental.c +++ b/src/map/elemental.c @@ -263,7 +263,7 @@ int elemental_data_received(struct s_elemental *ele, bool flag) { ed->bl.y = ed->ud.to_y; map_addiddb(&ed->bl); - status_calc_elemental(ed,1); + status_calc_elemental(ed,SCO_FIRST); ed->last_spdrain_time = ed->last_thinktime = gettick(); ed->summon_timer = INVALID_TIMER; ed->masterteleport_timer = INVALID_TIMER; diff --git a/src/map/guild.c b/src/map/guild.c index 7fcfa1ea2d..a8b8e7c849 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -1876,7 +1876,7 @@ int guild_castledatasave(int castle_id, int index, int value) { for (i = 0; i < MAX_GUARDIANS; i++){ struct mob_data *gd; if (gc->guardian[i].visible && (gd = map_id2md(gc->guardian[i].id)) != NULL) - status_calc_mob(gd, 0); + status_calc_mob(gd, SCO_NONE); } break; } diff --git a/src/map/homunculus.c b/src/map/homunculus.c index 47d2861d7e..c64f7a7fa4 100644 --- a/src/map/homunculus.c +++ b/src/map/homunculus.c @@ -300,7 +300,7 @@ void hom_skillup(struct homun_data *hd,uint16 skill_id) { hd->homunculus.hskill[i].lv++; hd->homunculus.skillpts-- ; - status_calc_homunculus(hd,0); + status_calc_homunculus(hd, SCO_NONE); if (hd->master) { clif_homskillup(hd->master, skill_id); clif_hominfo(hd->master,hd,0); @@ -417,8 +417,7 @@ int hom_evolution(struct homun_data *hd) struct map_session_data *sd; nullpo_ret(hd); - if(!hd->homunculusDB->evo_class || hd->homunculus.class_ == hd->homunculusDB->evo_class) - { + if(!hd->homunculusDB->evo_class || hd->homunculus.class_ == hd->homunculusDB->evo_class) { clif_emotion(&hd->bl, E_SWT); return 0 ; } @@ -456,7 +455,7 @@ int hom_evolution(struct homun_data *hd) //status_Calc flag&1 will make current HP/SP be reloaded from hom structure hom->hp = hd->battle_status.hp; hom->sp = hd->battle_status.sp; - status_calc_homunculus(hd,1); + status_calc_homunculus(hd, SCO_FIRST); if (!(battle_config.hom_setting&0x2)) skill_unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately @@ -510,7 +509,7 @@ int hom_mutate(struct homun_data *hd, int homun_id) hom->hp = hd->battle_status.hp; hom->sp = hd->battle_status.sp; hom->prev_class = prev_class; - status_calc_homunculus(hd,1); + status_calc_homunculus(hd, SCO_FIRST); if (!(battle_config.hom_setting&0x2)) skill_unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately @@ -556,7 +555,7 @@ int hom_gainexp(struct homun_data *hd,int exp) hd->homunculus.exp = 0 ; clif_specialeffect(&hd->bl,568,AREA); - status_calc_homunculus(hd,0); + status_calc_homunculus(hd, SCO_NONE); status_percent_heal(&hd->bl, 100, 100); return 0; } @@ -785,7 +784,8 @@ int hom_search(int key,int type) } // Create homunc structure -void hom_alloc(struct map_session_data *sd, struct s_homunculus *hom) { +void hom_alloc(struct map_session_data *sd, struct s_homunculus *hom) +{ struct homun_data *hd; int i = 0; @@ -823,7 +823,8 @@ void hom_alloc(struct map_session_data *sd, struct s_homunculus *hom) { hd->bl.y = hd->ud.to_y; map_addiddb(&hd->bl); - status_calc_homunculus(hd,1); + status_calc_homunculus(hd, SCO_FIRST); + status_percent_heal(&hd->bl, 100, 100); hd->hungry_timer = INVALID_TIMER; hd->masterteleport_timer = INVALID_TIMER; @@ -1093,7 +1094,7 @@ int hom_shuffle(struct homun_data *hd) memcpy(&hd->homunculus.hskill, &b_skill, sizeof(b_skill)); hd->homunculus.skillpts = skillpts; clif_homskillinfoblock(sd); - status_calc_homunculus(hd,0); + status_calc_homunculus(hd, SCO_NONE); status_percent_heal(&hd->bl, 100, 100); clif_specialeffect(&hd->bl,568,AREA); diff --git a/src/map/itemdb.c b/src/map/itemdb.c index 2eca1c6068..ad68236bd2 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -1753,14 +1753,13 @@ void itemdb_reload(void) { sd->combos.id = NULL; sd->combos.count = 0; if( pc_load_combo(sd) > 0 ) - status_calc_pc(sd,0); + status_calc_pc(sd, SCO_FORCE); } } mapit_free(iter); } - /** * Finalizing Item DB */ diff --git a/src/map/mercenary.c b/src/map/mercenary.c index 61befd277a..64ccf765ad 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -341,7 +341,8 @@ void merc_contract_init(struct mercenary_data *md) { * @param flag : if inter-serv request was sucessfull * @return false:failure, true:sucess */ -bool mercenary_recv_data(struct s_mercenary *merc, bool flag){ +bool mercenary_recv_data(struct s_mercenary *merc, bool flag) +{ struct map_session_data *sd; struct mercenary_data *md; struct s_mercenary_db *db; @@ -349,15 +350,13 @@ bool mercenary_recv_data(struct s_mercenary *merc, bool flag){ if( (sd = map_charid2sd(merc->char_id)) == NULL ) return false; - if( !flag || i < 0 ) - { // Not created - loaded - DB info + if( !flag || i < 0 ) { // Not created - loaded - DB info sd->status.mer_id = 0; return false; } db = &mercenary_db[i]; - if( !sd->md ) - { + if( !sd->md ) { sd->md = md = (struct mercenary_data*)aCalloc(1,sizeof(struct mercenary_data)); md->bl.type = BL_MER; md->bl.id = npc_get_new_npc_id(); @@ -379,13 +378,11 @@ bool mercenary_recv_data(struct s_mercenary *merc, bool flag){ md->bl.y = md->ud.to_y; map_addiddb(&md->bl); - status_calc_mercenary(md,1); + status_calc_mercenary(md, SCO_FIRST); md->contract_timer = INVALID_TIMER; md->masterteleport_timer = INVALID_TIMER; merc_contract_init(md); - } - else - { + } else { memcpy(&sd->md->mercenary, merc, sizeof(struct s_mercenary)); md = sd->md; } @@ -394,8 +391,7 @@ bool mercenary_recv_data(struct s_mercenary *merc, bool flag){ mercenary_set_calls(md, 1); sd->status.mer_id = merc->mercenary_id; - if( md && md->bl.prev == NULL && sd->bl.prev != NULL ) - { + if( md && md->bl.prev == NULL && sd->bl.prev != NULL ) { if(map_addblock(&md->bl)) return false; clif_spawn(&md->bl); diff --git a/src/map/mob.c b/src/map/mob.c index 9201d14aa0..010cfdcbf9 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -612,7 +612,7 @@ static int mob_spawn_guardian_sub(int tid, unsigned int tick, int id, intptr_t d memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH); md->guardian_data->guardup_lv = guardup_lv; if( guardup_lv ) - status_calc_mob(md, 0); //Give bonuses. + status_calc_mob(md, SCO_NONE); //Give bonuses. return 0; } @@ -943,14 +943,13 @@ int mob_spawn (struct mob_data *md) } memset(&md->state, 0, sizeof(md->state)); - status_calc_mob(md, 1); + status_calc_mob(md, SCO_FIRST); md->attacked_id = 0; md->target_id = 0; md->move_fail_count = 0; md->ud.state.attack_continue = 0; md->ud.target_to = 0; - if( md->spawn_timer != INVALID_TIMER ) - { + if( md->spawn_timer != INVALID_TIMER ) { delete_timer(md->spawn_timer, mob_delayspawn); md->spawn_timer = INVALID_TIMER; } @@ -2796,7 +2795,7 @@ int mob_class_change (struct mob_data *md, int mob_id) unit_skillcastcancel(&md->bl, 0); status_set_viewdata(&md->bl, mob_id); clif_mob_class_change(md,md->vd->class_); - status_calc_mob(md, 1); + status_calc_mob(md,SCO_FIRST); md->ud.state.speed_changed = 1; //Speed change update. if (battle_config.monster_class_change_recover) { diff --git a/src/map/pc.c b/src/map/pc.c index 2a893e614a..6076e1c0a7 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1093,6 +1093,8 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim sd->guild_x = -1; sd->guild_y = -1; + sd->delayed_damage = 0; + // Event Timers for( i = 0; i < MAX_EVENTTIMER; i++ ) sd->eventtimer[i] = INVALID_TIMER; @@ -1313,7 +1315,7 @@ int pc_reg_received(struct map_session_data *sd) pc_check_available_item(sd); // Check for invalid(ated) items. pc_load_combo(sd); - status_calc_pc(sd,1); + status_calc_pc(sd, (enum e_status_calc_opt)(SCO_FIRST|SCO_FORCE)); chrif_scdata_request(sd->status.account_id, sd->status.char_id); chrif_skillcooldown_request(sd->status.account_id, sd->status.char_id); chrif_bsdata_request(sd->status.char_id); @@ -2070,7 +2072,7 @@ void pc_exeautobonus(struct map_session_data *sd,struct s_autobonus *autobonus) autobonus->active = 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); } int pc_endautobonus(int tid, unsigned int tick, int id, intptr_t data) @@ -2083,7 +2085,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; } @@ -3660,10 +3662,10 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) } else clif_addskill(sd,id); if( !skill_get_inf(id) ) //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[id].id == id ){ + if( sd->status.skill[id].id == id ) { if( sd->status.skill[id].lv >= level ) return 0; if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT ) //Non-granted skill, store it's level. @@ -3675,7 +3677,7 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) sd->status.skill[id].lv = level; break; case 2: //Add skill bonus on top of what you had. - if( sd->status.skill[id].id == id ){ + if( sd->status.skill[id].id == id ) { if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT ) sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; // Store previous level. } else { @@ -3694,7 +3696,7 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) } else clif_addskill(sd,id); if( !skill_get_inf(id) ) //Only recalculate for passive skills. - status_calc_pc(sd, 0); + status_calc_pc(sd, SCO_NONE); break; default: //Unknown flag? return 0; @@ -4314,6 +4316,7 @@ int pc_isUseitem(struct map_session_data *sd,int n) return 0; if( (item->item_usage.flag&NOUSE_SITTING) && (pc_issit(sd) == 1) && (pc_get_group_level(sd) < item->item_usage.override) ) { + clif_msgtable(sd->fd,ITEM_NOUSE_SITTING); return 0; // You cannot use this item while sitting. } @@ -4478,7 +4481,7 @@ int pc_useitem(struct map_session_data *sd,int n) nullpo_ret(sd); - if( sd->npc_id ){ + if (sd->npc_id) { #ifdef RENEWAL clif_msg(sd, USAGE_FAIL); // TODO look for the client date that has this message. return 0; @@ -4489,7 +4492,7 @@ int pc_useitem(struct map_session_data *sd,int n) } item = sd->status.inventory[n]; id = sd->inventory_data[n]; - + if (item.nameid <= 0 || item.amount <= 0) return 0; @@ -5933,13 +5936,13 @@ 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) // 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) { @@ -5999,7 +6002,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_DEVIL, 1, 0, 0, 0, 1); //Permanent blind effect from SG_DEVIL. @@ -6336,7 +6339,7 @@ bool pc_statusup(struct map_session_data* sd, int type, int increase) 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 clif_updatestatus(sd, SP_USTR + type-SP_STR); @@ -6380,7 +6383,7 @@ int pc_statusup2(struct map_session_data* sd, int type, int val) 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) ) @@ -6426,7 +6429,7 @@ int pc_skillup(struct map_session_data *sd,uint16 skill_id) sd->status.skill[skill_id].lv++; sd->status.skill_point--; if( !skill_get_inf(skill_id) ) - 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 Ranker skills. else @@ -6494,7 +6497,7 @@ int pc_allskillup(struct map_session_data *sd) sd->status.skill[id].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); @@ -6584,7 +6587,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; @@ -6649,7 +6652,7 @@ int pc_resetstate(struct map_session_data* sd) pc_setglobalreg(sd,"TK_MISSION_ID", 0); } - status_calc_pc(sd,0); + status_calc_pc(sd, SCO_NONE); return 1; } @@ -6760,11 +6763,10 @@ int pc_resetskill(struct map_session_data* sd, int flag) sd->status.skill_point += skill_point; - if( flag&1 ) - { + 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; @@ -7053,7 +7055,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 ) @@ -7450,11 +7452,9 @@ bool 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_NONE); if(sd->status.party_id) - { party_send_levelup(sd); - } break; case SP_JOBLEVEL: if ((unsigned int)val >= sd->status.job_level) { @@ -7900,7 +7900,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) 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); @@ -8012,12 +8012,12 @@ void 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_status_load(&sd->bl,SI_RIDING,1); - 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 && pc_checkskill(sd,RK_DRAGONTRAINING) > 0) ) { // Dismount clif_status_load(&sd->bl,SI_RIDING,0); - status_calc_pc(sd,0); + status_calc_pc(sd,SCO_NONE); } #ifndef NEW_CARTS @@ -8025,7 +8025,7 @@ void 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) @@ -8041,15 +8041,15 @@ void 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_status_load(&sd->bl,SI_WUGRIDER,1); - status_calc_pc(sd,0); + status_calc_pc(sd,SCO_NONE); } else if( !(type&OPTION_WUGRIDER) && p_type&OPTION_WUGRIDER ) { // Dismount clif_status_load(&sd->bl,SI_WUGRIDER,0); - status_calc_pc(sd,0); + status_calc_pc(sd,SCO_NONE); } } if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC ) { if( type&OPTION_MADOGEAR && !(p_type&OPTION_MADOGEAR) ) { - status_calc_pc(sd, 0); + status_calc_pc(sd,SCO_NONE); status_change_end(&sd->bl,SC_MAXIMIZEPOWER,INVALID_TIMER); status_change_end(&sd->bl,SC_OVERTHRUST,INVALID_TIMER); status_change_end(&sd->bl,SC_WEAPONPERFECTION,INVALID_TIMER); @@ -8058,7 +8058,7 @@ void pc_setoption(struct map_session_data *sd,int type) status_change_end(&sd->bl,SC_MELTDOWN,INVALID_TIMER); status_change_end(&sd->bl,SC_MAXOVERTHRUST,INVALID_TIMER); } else if( !(type&OPTION_MADOGEAR) && p_type&OPTION_MADOGEAR ) { - status_calc_pc(sd, 0); + status_calc_pc(sd,SCO_NONE); status_change_end(&sd->bl,SC_SHAPESHIFT,INVALID_TIMER); status_change_end(&sd->bl,SC_HOVERING,INVALID_TIMER); status_change_end(&sd->bl,SC_ACCELERATION,INVALID_TIMER); @@ -8124,7 +8124,7 @@ bool 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; @@ -8368,15 +8368,12 @@ bool pc_setregistry(struct map_session_data *sd,const char *reg,int val,int type switch( type ) { case 3: //Char reg - if( !strcmp(reg,"PC_DIE_COUNTER") && sd->die_counter != val ) - { + 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 ) - { + status_calc_pc(sd,SCO_NONE); // Lost the bonus. + } else if( !strcmp(reg,"COOK_MASTERY") && sd->cook_mastery != val ) { val = cap_value(val, 0, 1999); sd->cook_mastery = val; } @@ -8385,13 +8382,10 @@ bool pc_setregistry(struct map_session_data *sd,const char *reg,int val,int type regmax = GLOBAL_REG_NUM; break; case 2: //Account reg - if( !strcmp(reg,"#CASHPOINTS") && sd->cashPoints != val ) - { + 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 ) - { + } else if( !strcmp(reg,"#KAFRAPOINTS") && sd->kafraPoints != val ) { val = cap_value(val, 0, MAX_ZENY); sd->kafraPoints = val; } @@ -8995,7 +8989,7 @@ bool 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); @@ -9169,7 +9163,7 @@ bool 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_SIGNUMCRUCIS] && !battle_check_undead(sd->battle_status.race,sd->battle_status.def_ele)) @@ -9235,10 +9229,8 @@ void 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; } /*========================================== @@ -9536,7 +9528,7 @@ void 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 interval *------------------------------------------*/ static int pc_autosave(int tid, unsigned int tick, int id, intptr_t data) { @@ -10671,7 +10663,7 @@ int pc_bonus_script_timer(int tid, unsigned int tick, int id, intptr_t data) { } pc_bonus_script_remove(sd,i); - status_calc_pc(sd,false); + status_calc_pc(sd,SCO_NONE); return 0; } @@ -10718,7 +10710,7 @@ void pc_bonus_script_clear(struct map_session_data *sd, uint16 flag) { } } if (count && !(flag&BONUS_FLAG_REM_ON_LOGOUT)) //Don't need to do this if log out - status_calc_pc(sd,false); + status_calc_pc(sd,SCO_NONE); } /** [Cydh] diff --git a/src/map/pc.h b/src/map/pc.h index 99cc6e55ea..f9425990ea 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -207,6 +207,7 @@ struct map_session_data { unsigned int prevend : 1;//used to flag wheather you've spent 40sp to open the vending or not. unsigned int warping : 1;//states whether you're in the middle of a warp processing unsigned int permanent_speed : 1; // When 1, speed cannot be changed through status_calc_pc(). + unsigned int hold_recalc : 1; unsigned int banking : 1; //1 when we using the banking system 0 when closed unsigned int hpmeter_visible : 1; bool disable_atcommand_on_npc; //Prevent to use atcommand while talking with NPC [Kichi] @@ -565,6 +566,8 @@ struct map_session_data { struct sc_display_entry **sc_display; unsigned char sc_display_count; + unsigned char delayed_damage; //[Ind] + // temporary debugging of bug #3504 const char* delunit_prevfile; int delunit_prevline; diff --git a/src/map/pet.c b/src/map/pet.c index a684e96c68..919db63fa6 100644 --- a/src/map/pet.c +++ b/src/map/pet.c @@ -68,7 +68,7 @@ void pet_set_intimate(struct pet_data *pd, int value) pd->pet.intimate = value; if( (intimate >= battle_config.pet_equip_min_friendly && pd->pet.intimate < battle_config.pet_equip_min_friendly) || (intimate < battle_config.pet_equip_min_friendly && pd->pet.intimate >= battle_config.pet_equip_min_friendly) ) - status_calc_pc(sd,0); + status_calc_pc(sd,SCO_NONE); } int pet_create_egg(struct map_session_data *sd, int item_id) @@ -225,7 +225,7 @@ static int pet_hungry(int tid, unsigned int tick, int id, intptr_t data) pd->pet.intimate = 0; pd->status.speed = pd->db->status.speed; } - status_calc_pet(pd, 0); + status_calc_pet(pd,SCO_NONE); clif_send_petdata(sd,pd,1,pd->pet.intimate); } clif_send_petdata(sd,pd,2,pd->pet.hungry); @@ -310,7 +310,7 @@ static int pet_return_egg(struct map_session_data *sd, struct pet_data *pd) pd->pet.incuvate = 1; unit_free(&pd->bl,CLR_OUTSIGHT); - status_calc_pc(sd,0); + status_calc_pc(sd,SCO_NONE); sd->status.pet_id = 0; return 1; @@ -366,19 +366,24 @@ int pet_data_init(struct map_session_data *sd, struct s_pet *pet) pd->bl.y = pd->ud.to_y; map_addiddb(&pd->bl); - status_calc_pet(pd,1); + status_calc_pet(pd,SCO_FIRST); pd->last_thinktime = gettick(); pd->state.skillbonus = 0; + if( battle_config.pet_status_support ) run_script(pet_db[i].pet_script,0,sd->bl.id,0); - if( pd->petDB && pd->petDB->equip_script ) - status_calc_pc(sd,0); - if( battle_config.pet_hungry_delay_rate != 100 ) - interval = (pd->petDB->hungry_delay*battle_config.pet_hungry_delay_rate)/100; - else - interval = pd->petDB->hungry_delay; + if( pd->petDB ) { + if( pd->petDB->equip_script ) + status_calc_pc(sd,SCO_NONE); + + if( battle_config.pet_hungry_delay_rate != 100 ) + interval = pd->petDB->hungry_delay * battle_config.pet_hungry_delay_rate / 100; + else + interval = pd->petDB->hungry_delay; + } + if( interval <= 0 ) interval = 1; pd->pet_hungry_timer = add_timer(gettick() + interval, pet_hungry, sd->bl.id, 0); @@ -717,23 +722,19 @@ static int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd) clif_additem(sd,0,0,flag); map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } - if( battle_config.pet_equip_required ) - { // Skotlex: halt support timers if needed - if( pd->state.skillbonus ) - { + if( battle_config.pet_equip_required ) { // Skotlex: halt support timers if needed + if( pd->state.skillbonus ) { pd->state.skillbonus = 0; - status_calc_pc(sd,0); + status_calc_pc(sd,SCO_NONE); } - if( pd->s_skill && pd->s_skill->timer != INVALID_TIMER ) - { + if( pd->s_skill && pd->s_skill->timer != INVALID_TIMER ) { if( pd->s_skill->id ) delete_timer(pd->s_skill->timer, pet_skill_support_timer); else delete_timer(pd->s_skill->timer, pet_heal_timer); pd->s_skill->timer = INVALID_TIMER; } - if( pd->bonus && pd->bonus->timer != INVALID_TIMER ) - { + if( pd->bonus && pd->bonus->timer != INVALID_TIMER ) { delete_timer(pd->bonus->timer, pet_skill_bonus_timer); pd->bonus->timer = INVALID_TIMER; } @@ -746,9 +747,9 @@ static int pet_food(struct map_session_data *sd, struct pet_data *pd) { int i,k; - k=pd->petDB->FoodID; - i=pc_search_inventory(sd,k); - if(i < 0) { + k = pd->petDB->FoodID; + i = pc_search_inventory(sd,k); + if( i < 0 ) { clif_pet_food(sd,k,0); return 1; } @@ -756,29 +757,25 @@ static int pet_food(struct map_session_data *sd, struct pet_data *pd) if( pd->pet.hungry > 90 ) pet_set_intimate(pd, pd->pet.intimate - pd->petDB->r_full); - else - { + else { if( battle_config.pet_friendly_rate != 100 ) - k = (pd->petDB->r_hungry * battle_config.pet_friendly_rate)/100; + k = (pd->petDB->r_hungry * battle_config.pet_friendly_rate) / 100; else k = pd->petDB->r_hungry; - if( pd->pet.hungry > 75 ) - { + if( pd->pet.hungry > 75 ) { k = k >> 1; if( k <= 0 ) k = 1; } pet_set_intimate(pd, pd->pet.intimate + k); } - if( pd->pet.intimate <= 0 ) - { + if( pd->pet.intimate <= 0 ) { pd->pet.intimate = 0; pet_stop_attack(pd); pd->status.speed = pd->db->status.speed; - } - else if( pd->pet.intimate > 1000 ) + } else if( pd->pet.intimate > 1000 ) pd->pet.intimate = 1000; - status_calc_pet(pd, 0); + status_calc_pet(pd,SCO_NONE); pd->pet.hungry += pd->petDB->fullness; if( pd->pet.hungry > 100 ) pd->pet.hungry = 100; @@ -1087,7 +1084,7 @@ int pet_skill_bonus_timer(int tid, unsigned int tick, int id, intptr_t data) if (pd->state.skillbonus != bonus) { pd->state.skillbonus = bonus; - status_calc_pc(sd, 0); + status_calc_pc(sd,SCO_NONE); } // wait for the next timer pd->bonus->timer=add_timer(tick+timer,pet_skill_bonus_timer,sd->bl.id,0); diff --git a/src/map/script.c b/src/map/script.c index 59f2d2cf47..f834634957 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -10998,7 +10998,6 @@ static void script_detach_rid(struct script_state* st) } } - /*========================================================================= * Attaches a set of RIDs to the current script. [digitalhamster] * addrid({,{,}}); @@ -11016,17 +11015,17 @@ static void script_detach_rid(struct script_state* st) * 0 : Players are always attached. (default) * 1 : Players currently running another script will not be attached. *-------------------------------------------------------------------------*/ - static int buildin_addrid_sub(struct block_list *bl,va_list ap) { int forceflag; struct map_session_data *sd = (TBL_PC *)bl; struct script_state* st; - st=va_arg(ap,struct script_state*); - forceflag=va_arg(ap,int); - if(!forceflag||!sd->st) - if(sd->status.account_id!=st->rid) + st = va_arg(ap,struct script_state*); + forceflag = va_arg(ap,int); + + if(!forceflag || !sd->st) + if(sd->status.account_id != st->rid) run_script(st->script,st->pos,sd->status.account_id,st->oid); return 0; } @@ -11036,46 +11035,48 @@ BUILDIN_FUNC(addrid) struct s_mapiterator* iter; struct block_list *bl; TBL_PC *sd; - if(st->rid<1){ + + if(st->rid < 1) { st->state = END; - bl=map_id2bl(st->oid); + bl = map_id2bl(st->oid); } else - bl=map_id2bl(st->rid); //if run without rid it'd error,also oid if npc, else rid for map + bl = map_id2bl(st->rid); //if run without rid it'd error,also oid if npc, else rid for map iter = mapit_getallusers(); - switch(script_getnum(st,2)){ + + switch(script_getnum(st,2)) { case 0: - for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)){ - if(!script_getnum(st,3)||!sd->st) - if(sd->status.account_id!=st->rid) //attached player already runs. + for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)) { + if(!script_getnum(st,3) || !sd->st) + if(sd->status.account_id != st->rid) //attached player already runs. run_script(st->script,st->pos,sd->status.account_id,st->oid); } break; case 1: - for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)){ - if(!script_getnum(st,3)||!sd->st) - if((sd->bl.m == bl->m)&&(sd->status.account_id!=st->rid)) + for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)) { + if(!script_getnum(st,3) || !sd->st) + if((sd->bl.m == bl->m) && (sd->status.account_id != st->rid)) run_script(st->script,st->pos,sd->status.account_id,st->oid); } break; case 2: - if(script_getnum(st,4)==0){ + if(script_getnum(st,4) == 0) { script_pushint(st,0); return 0; } - for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)){ - if(!script_getnum(st,3)||!sd->st) - if((sd->status.account_id!=st->rid)&&(sd->status.party_id==script_getnum(st,4))) //attached player already runs. + for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)) { + if(!script_getnum(st,3) || !sd->st) + if((sd->status.account_id != st->rid) && (sd->status.party_id == script_getnum(st,4))) //attached player already runs. run_script(st->script,st->pos,sd->status.account_id,st->oid); } break; case 3: - if(script_getnum(st,4)==0){ + if(script_getnum(st,4) == 0) { script_pushint(st,0); return 0; } - for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)){ - if(!script_getnum(st,3)||!sd->st) - if((sd->status.account_id!=st->rid)&&(sd->status.guild_id==script_getnum(st,4))) //attached player already runs. + for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)) { + if(!script_getnum(st,3) || !sd->st) + if((sd->status.account_id != st->rid) && (sd->status.guild_id == script_getnum(st,4))) //attached player already runs. run_script(st->script,st->pos,sd->status.account_id,st->oid); } break; @@ -11085,11 +11086,11 @@ BUILDIN_FUNC(addrid) st,script_getnum(st,3));//4-x0 , 5-y0 , 6-x1, 7-y1 break; default: - if((map_id2sd(script_getnum(st,2)))==NULL){ // Player not found. + if((map_id2sd(script_getnum(st,2))) == NULL) { // Player not found. script_pushint(st,0); return 0; } - if(!script_getnum(st,3)||!map_id2sd(script_getnum(st,2))->st) { + if(!script_getnum(st,3) || !map_id2sd(script_getnum(st,2))->st) { run_script(st->script,st->pos,script_getnum(st,2),st->oid); script_pushint(st,1); } @@ -13170,11 +13171,11 @@ BUILDIN_FUNC(nude) } if( calcflag ) - status_calc_pc(sd,0); + status_calc_pc(sd,SCO_NONE); return SCRIPT_CMD_SUCCESS; } -int atcommand_sub(struct script_state* st,int type){ +int atcommand_sub(struct script_state* st,int type) { TBL_PC dummy_sd; TBL_PC* sd; int fd; @@ -13627,11 +13628,10 @@ BUILDIN_FUNC(npcwalkto) y=script_getnum(st,3); if(nd) { - if (!nd->status.hp) { - status_calc_npc(nd, true); - } else { - status_calc_npc(nd, false); - } + if (!nd->status.hp) + status_calc_npc(nd, SCO_FIRST); + else + status_calc_npc(nd, SCO_NONE); unit_walktoxy(&nd->bl,x,y,0); } return SCRIPT_CMD_SUCCESS; @@ -18123,17 +18123,16 @@ BUILDIN_FUNC(npcskill) nd->level = npc_level; nd->stat_point = stat_point; - if (!nd->status.hp) { - status_calc_npc(nd, true); - } else { - status_calc_npc(nd, false); - } + if (!nd->status.hp) + status_calc_npc(nd, SCO_FIRST); + else + status_calc_npc(nd, SCO_NONE); - if (skill_get_inf(skill_id)&INF_GROUND_SKILL) { + if (skill_get_inf(skill_id)&INF_GROUND_SKILL) unit_skilluse_pos(&nd->bl, sd->bl.x, sd->bl.y, skill_id, skill_level); - } else { + else unit_skilluse_id(&nd->bl, sd->bl.id, skill_id, skill_level); - } + return SCRIPT_CMD_SUCCESS; } @@ -18723,7 +18722,7 @@ BUILDIN_FUNC(bonus_script) { if (sd->bonus_script[i].icon != SI_BLANK) //Gives status icon if exist clif_status_change(&sd->bl,sd->bonus_script[i].icon,1,dur,1,0,0); - status_calc_pc(sd,false); + status_calc_pc(sd,SCO_NONE); return SCRIPT_CMD_SUCCESS; } diff --git a/src/map/status.c b/src/map/status.c index 81e2636541..b02d29c215 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -2282,17 +2282,17 @@ void status_calc_misc(struct block_list *bl, struct status_data *status, int lev /** [Skotlex] * Calculates the initial status for the given mob * @param md: Mob object -* @param first: Whether or not it is the first calculation +* @param opt: Whether or not it is the first calculation This will only be false when a mob levels up (Regular and WoE Guardians) * @return 1 for calculated special statuses or 0 for none **/ -int status_calc_mob_(struct mob_data* md, bool first) +int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) { struct status_data *status; struct block_list *mbl = NULL; int flag=0; - if(first) { // Set basic level on respawn. + if (opt&SCO_FIRST) { // Set basic level on respawn. if (md->level > 0 && md->level <= MAX_LEVEL && md->level != md->db->lv) ; else @@ -2322,7 +2322,7 @@ int status_calc_mob_(struct mob_data* md, bool first) aFree(md->base_status); md->base_status = NULL; } - if(first) + if (opt&SCO_FIRST) memcpy(&md->status, &md->db->status, sizeof(struct status_data)); return 0; } @@ -2476,7 +2476,7 @@ int status_calc_mob_(struct mob_data* md, bool first) } } - if( first ) // Initial battle status + if (opt&SCO_FIRST) // Initial battle status memcpy(&md->status, status, sizeof(struct status_data)); return 1; @@ -2485,15 +2485,15 @@ int status_calc_mob_(struct mob_data* md, bool first) /** [Skotlex] * Calculates the stats of the given pet * @param pd: Pet object -* @param first: Whether or not it is the first calculation +* @param opt: Whether or not it is the first calculation This will only be false when a pet levels up * @return 1 **/ -int status_calc_pet_(struct pet_data *pd, bool first) +int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt) { nullpo_ret(pd); - if (first) { + if (opt&SCO_FIRST) { memcpy(&pd->status, &pd->db->status, sizeof(struct status_data)); pd->status.mode = MD_CANMOVE; // Pets discard all modes, except walking pd->status.class_ = CLASS_NORMAL; @@ -2512,10 +2512,11 @@ int status_calc_pet_(struct pet_data *pd, bool first) lv =sd->status.base_level*battle_config.pet_lv_rate/100; if (lv < 0) lv = 1; - if (lv != pd->pet.level || first) { + if (lv != pd->pet.level || opt&SCO_FIRST) { struct status_data *bstat = &pd->db->status, *status = &pd->status; + pd->pet.level = lv; - if (!first) // Lv Up animation + if (!(opt&SCO_FIRST)) // Lv Up animation clif_misceffect(&pd->bl, 0); status->rhw.atk = (bstat->rhw.atk*lv)/pd->db->lv; status->rhw.atk2 = (bstat->rhw.atk2*lv)/pd->db->lv; @@ -2537,10 +2538,10 @@ int status_calc_pet_(struct pet_data *pd, bool first) status_calc_misc(&pd->bl, &pd->status, lv); - if (!first) // Not done the first time because the pet is not visible yet + if (!(opt&SCO_FIRST)) // Not done the first time because the pet is not visible yet clif_send_petstatus(sd); } - } else if (first) { + } else if (opt&SCO_FIRST) { status_calc_misc(&pd->bl, &pd->status, pd->db->lv); if (!battle_config.pet_lv_rate && pd->pet.level != pd->db->lv) pd->pet.level = pd->db->lv; @@ -2751,7 +2752,7 @@ static unsigned int status_calc_maxhpsp_pc(struct map_session_data* sd, unsigned uint16 idx, level, job_id; nullpo_ret(sd); - + job_id = pc_mapid2jobid(sd->class_,sd->status.sex); idx = pc_class2idx(job_id); level = max(sd->status.base_level,1); @@ -2774,10 +2775,10 @@ static unsigned int status_calc_maxhpsp_pc(struct map_session_data* sd, unsigned * Calculates player data from scratch without counting SC adjustments * Should be invoked whenever players raise stats, learn passive skills or change equipment * @param sd: Player object -* @param first: Whether it is first calc (login) or not +* @param opt: Whether it is first calc (login) or not * @return (-1) for too many recursive calls, (1) recursive call, (0) success **/ -int status_calc_pc_(struct map_session_data* sd, bool first) +int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { static int calculating = 0; ///< Check for recursive call preemption. [Skotlex] struct status_data *status; ///< Pointer to the player's base status @@ -2799,7 +2800,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first) sd->max_weight = job_info[pc_class2idx(sd->status.class_)].max_weight_base+sd->status.str*300; - if(first) { + if (opt&SCO_FIRST) { // Load Hp/SP from char-received data. sd->battle_status.hp = sd->status.hp; sd->battle_status.sp = sd->status.sp; @@ -2961,7 +2962,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first) status->def += sd->inventory_data[index]->def; // Items may be equipped, their effects however are nullified. - if(first && sd->inventory_data[index]->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) + if (opt&SCO_FIRST && sd->inventory_data[index]->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(sd->inventory_data[index],sd->bl.m))) { // Execute equip-script on login run_script(sd->inventory_data[index]->equip_script,0,sd->bl.id,0); if (!calculating) @@ -3112,7 +3113,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first) data = itemdb_exists(c); if(!data) continue; - if(first && data->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(data,sd->bl.m))) {// Execute equip-script on login + if (opt&SCO_FIRST && data->equip_script && (pc_has_permission(sd,PC_PERM_USE_ALL_EQUIPMENT) || !itemdb_isNoEquip(data,sd->bl.m))) {// Execute equip-script on login run_script(data->equip_script,0,sd->bl.id,0); if (!calculating) return 1; @@ -3608,15 +3609,15 @@ int status_calc_pc_(struct map_session_data* sd, bool first) /** * Calculates Mercenary data * @param md: Mercenary object -* @param first: Whether it is first calc or not (0 on level up or status) +* @param opt: Whether it is first calc or not (0 on level up or status) * @return 0 **/ -int status_calc_mercenary_(struct mercenary_data *md, bool first) +int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt) { struct status_data *status = &md->base_status; struct s_mercenary *merc = &md->mercenary; - if( first ) { + if (opt&SCO_FIRST) { memcpy(status, &md->db->status, sizeof(struct status_data)); status->class_ = CLASS_NORMAL; status->mode = MD_CANMOVE|MD_CANATTACK; @@ -3637,10 +3638,10 @@ int status_calc_mercenary_(struct mercenary_data *md, bool first) /** * Calculates Homunculus data * @param hd: Homunculus object -* @param first: Whether it is first calc or not (0 on level up or status) +* @param opt: Whether it is first calc or not (0 on level up or status) * @return 1 **/ -int status_calc_homunculus_(struct homun_data *hd, bool first) +int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) { struct status_data *status = &hd->base_status; struct s_homunculus *hom = &hd->homunculus; @@ -3654,7 +3655,7 @@ int status_calc_homunculus_(struct homun_data *hd, bool first) status->int_ = hom->int_ / 10; status->luk = hom->luk / 10; - if (first) { + if (opt&SCO_FIRST) { const struct s_homunculus_db *db = hd->homunculusDB; status->def_ele = db->element; status->ele_lv = 1; @@ -3710,7 +3711,7 @@ int status_calc_homunculus_(struct homun_data *hd, bool first) if((skill = hom_checkskill(hd,HLIF_BRAIN)) > 0) status->max_sp += (1 +skill/2 -skill/4 +skill/5) * status->max_sp / 100 ; - if (first) { + if (opt&SCO_FIRST) { hd->battle_status.hp = hom->hp ; hd->battle_status.sp = hom->sp ; if(hom->class_ == 6052) // Eleanor @@ -3735,10 +3736,10 @@ int status_calc_homunculus_(struct homun_data *hd, bool first) /** * Calculates Elemental data * @param ed: Elemental object -* @param first: Whether it is first calc or not (0 on status change) +* @param opt: Whether it is first calc or not (0 on status change) * @return 0 **/ -int status_calc_elemental_(struct elemental_data *ed, bool first) +int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt) { struct status_data *status = &ed->base_status; struct s_elemental *ele = &ed->elemental; @@ -3747,7 +3748,7 @@ int status_calc_elemental_(struct elemental_data *ed, bool first) if( !sd ) return 0; - if( first ) { + if (opt&SCO_FIRST) { memcpy(status, &ed->db->status, sizeof(struct status_data)); if( !ele->mode ) status->mode = EL_MODE_PASSIVE; @@ -3785,17 +3786,17 @@ int status_calc_elemental_(struct elemental_data *ed, bool first) /** * Calculates NPC data * @param nd: NPC object -* @param first: Whether it is first calc or not (what?) +* @param opt: Whether it is first calc or not (what?) * @return 0 **/ -int status_calc_npc_(struct npc_data *nd, bool first) +int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt) { struct status_data *status = &nd->status; if (!nd) return 0; - if (first) { + if (opt&SCO_FIRST) { status->hp = 1; status->sp = 1; status->max_hp = 1; @@ -4550,38 +4551,47 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) * See [set_sc] [add_sc] * @param bl: Object whose status has changed [PC|MOB|HOM|MER|ELEM] * @param flag: Which status has changed on bl -* @param first: If true, will cause status_calc_* functions to run their base status initialization code +* @param opt: If true, will cause status_calc_* functions to run their base status initialization code **/ -void status_calc_bl_(struct block_list* bl, enum scb_flag flag, bool first) +void status_calc_bl_(struct block_list* bl, enum scb_flag flag, enum e_status_calc_opt opt) { struct status_data b_status; // Previous battle status struct status_data* status; // Pointer to current battle status + if (bl->type == BL_PC && ((TBL_PC*)bl)->delayed_damage != 0) { + if (opt&SCO_FORCE) + ((TBL_PC*)bl)->state.hold_recalc = 0; /* Clear and move on */ + else { + ((TBL_PC*)bl)->state.hold_recalc = 1; /* Flag and stop */ + return; + } + } + // Remember previous values status = status_get_status_data(bl); memcpy(&b_status, status, sizeof(struct status_data)); if( flag&SCB_BASE ) { // Calculate the object's base status too switch( bl->type ) { - case BL_PC: status_calc_pc_(BL_CAST(BL_PC,bl), first); break; - case BL_MOB: status_calc_mob_(BL_CAST(BL_MOB,bl), first); break; - case BL_PET: status_calc_pet_(BL_CAST(BL_PET,bl), first); break; - case BL_HOM: status_calc_homunculus_(BL_CAST(BL_HOM,bl), first); break; - case BL_MER: status_calc_mercenary_(BL_CAST(BL_MER,bl), first); break; - case BL_ELEM: status_calc_elemental_(BL_CAST(BL_ELEM,bl), first); break; - case BL_NPC: status_calc_npc_(BL_CAST(BL_NPC,bl), first); break; + case BL_PC: status_calc_pc_(BL_CAST(BL_PC,bl), opt); break; + case BL_MOB: status_calc_mob_(BL_CAST(BL_MOB,bl), opt); break; + case BL_PET: status_calc_pet_(BL_CAST(BL_PET,bl), opt); break; + case BL_HOM: status_calc_homunculus_(BL_CAST(BL_HOM,bl), opt); break; + case BL_MER: status_calc_mercenary_(BL_CAST(BL_MER,bl), opt); break; + case BL_ELEM: status_calc_elemental_(BL_CAST(BL_ELEM,bl), opt); break; + case BL_NPC: status_calc_npc_(BL_CAST(BL_NPC,bl), opt); break; } } - if( first && bl->type == BL_MOB ) + if (opt&SCO_FIRST && bl->type == BL_MOB) return; // Assume there will be no statuses active - + if( bl->type == BL_PET ) return; // Pets are not affected by statuses - + status_calc_bl_main(bl, flag); - - if( first && bl->type == BL_HOM ) + + if (opt&SCO_FIRST && bl->type == BL_HOM) return; // Client update handled by caller // Compare against new values and send client updates @@ -10192,8 +10202,11 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty status_calc_state(bl,sc,( enum scs_flag ) StatusChangeStateTable[type],true); - if(sd && sd->pd) - pet_sc_check(sd, type); // Skotlex: Pet Status Effect Healing + if(sd) { + if (sd->pd) + pet_sc_check(sd, type); // Skotlex: Pet Status Effect Healing + status_calc_pc(sd, SCO_NONE); + } // 1st thing to execute when loading status switch (type) { diff --git a/src/map/status.h b/src/map/status.h index 65188ee787..fa52c689e9 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -1725,6 +1725,12 @@ enum scb_flag SCB_ALL = 0x3FFFFFFF }; +enum e_status_calc_opt { + SCO_NONE = 0x0, + SCO_FIRST = 0x1, /* Trigger the calculations that should take place only onspawn/once */ + SCO_FORCE = 0x2, /* Only relevant to BL_PC types, ensures call bypasses the queue caused by delayed damage */ +}; + ///Enum for bonus_script's flag enum e_bonus_script_flags { BONUS_FLAG_REM_ON_DEAD = 0x01, //Remove bonus when dead @@ -1992,22 +1998,23 @@ int status_change_timer_sub(struct block_list* bl, va_list ap); int status_change_clear(struct block_list* bl, int type); void status_change_clear_buffs(struct block_list* bl, int type); -#define status_calc_bl(bl, flag) status_calc_bl_(bl, (enum scb_flag)(flag), false) -#define status_calc_mob(md, first) status_calc_bl_(&(md)->bl, SCB_ALL, first) -#define status_calc_pet(pd, first) status_calc_bl_(&(pd)->bl, SCB_ALL, first) -#define status_calc_pc(sd, first) status_calc_bl_(&(sd)->bl, SCB_ALL, first) -#define status_calc_homunculus(hd, first) status_calc_bl_(&(hd)->bl, SCB_ALL, first) -#define status_calc_mercenary(md, first) status_calc_bl_(&(md)->bl, SCB_ALL, first) -#define status_calc_elemental(ed, first) status_calc_bl_(&(ed)->bl, SCB_ALL, first) -#define status_calc_npc(nd, first) status_calc_bl_(&(nd)->bl, SCB_ALL, first) +#define status_calc_bl(bl, flag) status_calc_bl_(bl, (enum scb_flag)(flag), SCO_NONE) +#define status_calc_mob(md, opt) status_calc_bl_(&(md)->bl, SCB_ALL, opt) +#define status_calc_pet(pd, opt) status_calc_bl_(&(pd)->bl, SCB_ALL, opt) +#define status_calc_pc(sd, opt) status_calc_bl_(&(sd)->bl, SCB_ALL, opt) +#define status_calc_homunculus(hd, opt) status_calc_bl_(&(hd)->bl, SCB_ALL, opt) +#define status_calc_mercenary(md, opt) status_calc_bl_(&(md)->bl, SCB_ALL, opt) +#define status_calc_elemental(ed, opt) status_calc_bl_(&(ed)->bl, SCB_ALL, opt) +#define status_calc_npc(nd, opt) status_calc_bl_(&(nd)->bl, SCB_ALL, opt) -void status_calc_bl_(struct block_list *bl, enum scb_flag flag, bool first); -int status_calc_mob_(struct mob_data* md, bool first); -int status_calc_pet_(struct pet_data* pd, bool first); -int status_calc_pc_(struct map_session_data* sd, bool first); -int status_calc_homunculus_(struct homun_data *hd, bool first); -int status_calc_mercenary_(struct mercenary_data *md, bool first); -int status_calc_elemental_(struct elemental_data *ed, bool first); +void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_calc_opt opt); +int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt); +int status_calc_pet_(struct pet_data* pd, enum e_status_calc_opt opt); +int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt); +int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt); +int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt); +int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt); +int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt); void status_calc_misc(struct block_list *bl, struct status_data *status, int level); void status_calc_regen(struct block_list *bl, struct status_data *status, struct regen_data *regen);