diff options
Diffstat (limited to 'src/map/status.c')
-rw-r--r-- | src/map/status.c | 2398 |
1 files changed, 1357 insertions, 1041 deletions
diff --git a/src/map/status.c b/src/map/status.c index 926bdb40a..f06bb0330 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2016 Hercules Dev Team + * Copyright (C) 2012-2018 Hercules Dev Team * Copyright (C) Athena Dev Teams * * Hercules is free software: you can redistribute it and/or modify @@ -25,6 +25,7 @@ #include "map/battle.h" #include "map/chrif.h" +#include "map/clan.h" #include "map/clif.h" #include "map/elemental.h" #include "map/guild.h" @@ -60,17 +61,17 @@ #include <string.h> #include <time.h> -struct status_interface status_s; -struct s_status_dbs statusdbs; +static struct status_interface status_s; +static struct s_status_dbs statusdbs; struct status_interface *status; /** -* Returns the status change associated with a skill. -* @param skill The skill to look up -* @return The status registered for this skill -**/ -sc_type status_skill2sc(int skill_id) + * Returns the status change associated with a skill. + * @param skill The skill to look up + * @return The status registered for this skill + */ +static sc_type status_skill2sc(int skill_id) { int idx; if( (idx = skill->get_index(skill_id)) == 0 ) { @@ -81,12 +82,12 @@ sc_type status_skill2sc(int skill_id) } /** -* Returns the FIRST skill (in order of definition in initChangeTables) to use a given status change. -* Utilized for various duration lookups. Use with caution! -* @param sc The status to look up -* @return A skill associated with the status -**/ -int status_sc2skill(sc_type sc) + * Returns the FIRST skill (in order of definition in initChangeTables) to use a given status change. + * Utilized for various duration lookups. Use with caution! + * @param sc The status to look up + * @return A skill associated with the status + */ +static int status_sc2skill(sc_type sc) { if( sc < 0 || sc >= SC_MAX ) { ShowError("status_sc2skill: Unsupported status change id %d\n", sc); @@ -97,11 +98,11 @@ int status_sc2skill(sc_type sc) } /** -* Returns the status calculation flag associated with a given status change. -* @param sc The status to look up -* @return The scb_flag registered for this status (see enum scb_flag) -**/ -unsigned int status_sc2scb_flag(sc_type sc) + * Returns the status calculation flag associated with a given status change. + * @param sc The status to look up + * @return The scb_flag registered for this status (see enum scb_flag) + */ +static unsigned int status_sc2scb_flag(sc_type sc) { if( sc < 0 || sc >= SC_MAX ) { ShowError("status_sc2scb_flag: Unsupported status change id %d\n", sc); @@ -112,11 +113,11 @@ unsigned int status_sc2scb_flag(sc_type sc) } /** -* Returns the bl types which require a status change packet to be sent for a given client status identifier. -* @param type The client-side status identifier to look up (see enum si_type) -* @return The bl types relevant to the type (see enum bl_type) -**/ -int status_type2relevant_bl_types(int type) + * Returns the bl types which require a status change packet to be sent for a given client status identifier. + * @param type The client-side status identifier to look up (see enum si_type) + * @return The bl types relevant to the type (see enum bl_type) + */ +static int status_type2relevant_bl_types(int type) { if( type < 0 || type >= SI_MAX ) { ShowError("status_type2relevant_bl_types: Unsupported type %d\n", type); @@ -126,7 +127,7 @@ int status_type2relevant_bl_types(int type) return status->dbs->RelevantBLTypes[type]; } -void status_set_sc(uint16 skill_id, sc_type sc, int icon, unsigned int flag) +static void status_set_sc(uint16 skill_id, sc_type sc, int icon, unsigned int flag) { uint16 idx; if( (idx = skill->get_index(skill_id)) == 0 ) { @@ -148,7 +149,7 @@ void status_set_sc(uint16 skill_id, sc_type sc, int icon, unsigned int flag) status->dbs->Skill2SCTable[idx] = sc; } -void initChangeTables(void) +static void initChangeTables(void) { #define add_sc(skill,sc) status->set_sc((skill),(sc),SI_BLANK,SCB_NONE) // indicates that the status displays a visual effect for the affected unit, and should be sent to the client for all supported units @@ -159,7 +160,7 @@ void initChangeTables(void) for (i = 0; i < SC_MAX; i++) status->dbs->IconChangeTable[i] = SI_BLANK; - for (i = 0; i < MAX_SKILL; i++) + for (i = 0; i < MAX_SKILL_DB; i++) status->dbs->Skill2SCTable[i] = SC_NONE; for (i = 0; i < SI_MAX; i++) @@ -1000,6 +1001,7 @@ void initChangeTables(void) status->dbs->IconChangeTable[SC_MONSTER_TRANSFORM] = SI_MONSTER_TRANSFORM; // Costumes + status->dbs->IconChangeTable[SC_DRESS_UP] = SI_DRESS_UP; status->dbs->IconChangeTable[SC_MOONSTAR] = SI_MOONSTAR; status->dbs->IconChangeTable[SC_SUPER_STAR] = SI_SUPER_STAR; status->dbs->IconChangeTable[SC_STRANGELIGHTS] = SI_STRANGELIGHTS; @@ -1018,6 +1020,12 @@ void initChangeTables(void) // Summoner status->dbs->IconChangeTable[SC_SPRITEMABLE] = SI_SPRITEMABLE; + // Clan System + status->dbs->IconChangeTable[SC_CLAN_INFO] = SI_CLAN_INFO; + + // RoDEX + status->dbs->IconChangeTable[SC_DAILYSENDMAILCNT] = SI_DAILYSENDMAILCNT; + // Other SC which are not necessarily associated to skills. status->dbs->ChangeFlagTable[SC_ATTHASTE_POTION1] |= SCB_ASPD; status->dbs->ChangeFlagTable[SC_ATTHASTE_POTION2] |= SCB_ASPD; @@ -1177,7 +1185,11 @@ void initChangeTables(void) status->dbs->ChangeFlagTable[SC_MVPCARD_ORCHERO] |= SCB_ALL; status->dbs->ChangeFlagTable[SC_MVPCARD_ORCLORD] |= SCB_ALL; + // Clan System + status->dbs->ChangeFlagTable[SC_CLAN_INFO] |= SCB_NONE; + // Costumes + status->dbs->ChangeFlagTable[SC_DRESS_UP] |= SCB_NONE; status->dbs->ChangeFlagTable[SC_MOONSTAR] |= SCB_NONE; status->dbs->ChangeFlagTable[SC_SUPER_STAR] |= SCB_NONE; status->dbs->ChangeFlagTable[SC_STRANGELIGHTS] |= SCB_NONE; @@ -1199,7 +1211,7 @@ void initChangeTables(void) #undef set_sc_with_vfx } -void initDummyData(void) +static void initDummyData(void) { memset(&status->dummy, 0, sizeof(status->dummy)); status->dummy.hp = @@ -1221,17 +1233,22 @@ void initDummyData(void) } //For copying a status_data structure from b to a, without overwriting current Hp and Sp -void status_copy(struct status_data *a, const struct status_data *b) +static void status_copy(struct status_data *a, const struct status_data *b) { nullpo_retv(a); nullpo_retv(b); memcpy((void*)&a->max_hp, (const void*)&b->max_hp, sizeof(struct status_data)-(sizeof(a->hp)+sizeof(a->sp))); } -//Sets HP to given value. Flag is the flag passed to status->heal in case -//final value is higher than current (use 2 to make a healing effect display -//on players) It will always succeed (overrides Berserk block), but it can't kill. -int status_set_hp(struct block_list *bl, unsigned int hp, int flag) +/** + * Sets HP to the given value. + * + * @param bl The target unit. + * @param hp The desired HP value. + * @param flag Additional options. @see enum status_heal_flag. STATUS_HEAL_FORCED is always implied. + * @return The amount of HP gained. + */ +static int status_set_hp(struct block_list *bl, unsigned int hp, enum status_heal_flag flag) { struct status_data *st; if (hp < 1) return 0; @@ -1242,14 +1259,19 @@ int status_set_hp(struct block_list *bl, unsigned int hp, int flag) if (hp > st->max_hp) hp = st->max_hp; if (hp == st->hp) return 0; if (hp > st->hp) - return status->heal(bl, hp - st->hp, 0, 1|flag); + return status->heal(bl, hp - st->hp, 0, STATUS_HEAL_FORCED | flag); return status_zap(bl, st->hp - hp, 0); } -//Sets SP to given value. Flag is the flag passed to status->heal in case -//final value is higher than current (use 2 to make a healing effect display -//on players) -int status_set_sp(struct block_list *bl, unsigned int sp, int flag) +/** + * Sets SP to the given value. + * + * @param bl The target unit. + * @param hp The desired SP value. + * @param flag Additional options. @see enum status_heal_flag. STATUS_HEAL_FORCED is always implied. + * @return The amount of SP gained. + */ +static int status_set_sp(struct block_list *bl, unsigned int sp, enum status_heal_flag flag) { struct status_data *st; @@ -1260,11 +1282,11 @@ int status_set_sp(struct block_list *bl, unsigned int sp, int flag) if (sp > st->max_sp) sp = st->max_sp; if (sp == st->sp) return 0; if (sp > st->sp) - return status->heal(bl, 0, sp - st->sp, 1|flag); + return status->heal(bl, 0, sp - st->sp, STATUS_HEAL_FORCED | flag); return status_zap(bl, 0, st->sp - sp); } -int status_charge(struct block_list* bl, int64 hp, int64 sp) +static int status_charge(struct block_list *bl, int64 hp, int64 sp) { nullpo_retr((int)(hp + sp), bl); if(!(bl->type&BL_CONSUME)) @@ -1277,7 +1299,7 @@ int status_charge(struct block_list* bl, int64 hp, int64 sp) //If flag&2, fail if target does not has enough to subtract. //If flag&4, if killed, mob must not give exp/loot. //flag will be set to &8 when damaging sp of a dead character -int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, int64 in_sp, int walkdelay, int flag) +static int status_damage(struct block_list *src, struct block_list *target, int64 in_hp, int64 in_sp, int walkdelay, int flag) { struct status_data *st; struct status_change *sc; @@ -1292,12 +1314,12 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, sp = 0; //Not a valid SP target. if (hp < 0) { //Assume absorbed damage. - status->heal(target, -hp, 0, 1); + status->heal(target, -hp, 0, STATUS_HEAL_FORCED); hp = 0; } if (sp < 0) { - status->heal(target, 0, -sp, 1); + status->heal(target, 0, -sp, STATUS_HEAL_FORCED); sp = 0; } @@ -1515,9 +1537,16 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, return (int)(hp+sp); } -//Heals a character. If flag&1, this is forced healing (otherwise stuff like Berserk can block it) -//If flag&2, when the player is healed, show the HP/SP heal effect. -int status_heal(struct block_list *bl, int64 in_hp, int64 in_sp, int flag) +/** + * Heals a character. + * + * @param bl The target unit. + * @param in_hp Amount of HP to recover. + * @param in_sp Amount of SP to recover. + * @param flag Additional options, @see enum status_heal_flag. + * @return The amount of HP + SP healed. + */ +static int status_heal(struct block_list *bl, int64 in_hp, int64 in_sp, enum status_heal_flag flag) { struct status_data *st; struct status_change *sc; @@ -1526,7 +1555,9 @@ int status_heal(struct block_list *bl, int64 in_hp, int64 in_sp, int flag) nullpo_ret(bl); st = status->get_status_data(bl); - if (st == &status->dummy || !st->hp) + if (st == &status->dummy) + return 0; + if (st->hp == 0 && (flag & STATUS_HEAL_ALLOWREVIVE) == 0) return 0; /* From here onwards, we consider it a 32-type as the client does not support higher and the value doesn't get through percentage modifiers */ @@ -1543,10 +1574,10 @@ int status_heal(struct block_list *bl, int64 in_hp, int64 in_sp, int flag) hp = 0; } - if(hp) { - if( sc && sc->data[SC_BERSERK] ) { - if( flag&1 ) - flag &= ~2; + if (hp != 0) { + if (sc && sc->data[SC_BERSERK] != NULL) { + if ((flag & STATUS_HEAL_FORCED) != 0) + flag &= ~STATUS_HEAL_SHOWEFFECT; else hp = 0; } @@ -1581,7 +1612,7 @@ int status_heal(struct block_list *bl, int64 in_hp, int64 in_sp, int flag) // send hp update to client switch(bl->type) { - case BL_PC: pc->heal(BL_UCAST(BL_PC, bl), hp, sp, (flag&2) ? 1 : 0); break; + case BL_PC: pc->heal(BL_UCAST(BL_PC, bl), hp, sp, (flag & STATUS_HEAL_SHOWEFFECT) != 0 ? 1 : 0); break; case BL_MOB: mob->heal(BL_UCAST(BL_MOB, bl), hp); break; case BL_HOM: homun->healed(BL_UCAST(BL_HOM, bl)); break; case BL_MER: mercenary->heal(BL_UCAST(BL_MER, bl), hp, sp); break; @@ -1597,7 +1628,7 @@ int status_heal(struct block_list *bl, int64 in_hp, int64 in_sp, int flag) //If rates are < 0, percent is of max HP/SP //If !flag, this is heal, otherwise it is damage. //Furthermore, if flag==2, then the target must not die from the subtraction. -int status_percent_change(struct block_list *src, struct block_list *target, signed char hp_rate, signed char sp_rate, int flag) +static int status_percent_change(struct block_list *src, struct block_list *target, signed char hp_rate, signed char sp_rate, int flag) { struct status_data *st; unsigned int hp = 0, sp = 0; @@ -1636,21 +1667,21 @@ int status_percent_change(struct block_list *src, struct block_list *target, sig if (flag) status->damage(src, target, INT_MAX, 0, 0, (!src||src==target?5:1)); else - status->heal(target, INT_MAX, 0, 0); + status->heal(target, INT_MAX, 0, STATUS_HEAL_DEFAULT); } if (sp > INT_MAX) { sp -= INT_MAX; if (flag) status->damage(src, target, 0, INT_MAX, 0, (!src||src==target?5:1)); else - status->heal(target, 0, INT_MAX, 0); + status->heal(target, 0, INT_MAX, STATUS_HEAL_DEFAULT); } if (flag) return status->damage(src, target, hp, sp, 0, (!src||src==target?5:1)); - return status->heal(target, hp, sp, 0); + return status->heal(target, hp, sp, STATUS_HEAL_DEFAULT); } -int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per_sp) +static int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per_sp) { struct status_data *st; unsigned int hp, sp; @@ -1689,7 +1720,7 @@ int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per return 1; } -int status_fixed_revive(struct block_list *bl, unsigned int per_hp, unsigned int per_sp) +static int status_fixed_revive(struct block_list *bl, unsigned int per_hp, unsigned int per_sp) { struct status_data *st; unsigned int hp, sp; @@ -1727,17 +1758,17 @@ int status_fixed_revive(struct block_list *bl, unsigned int per_hp, unsigned int } /*========================================== -* Checks whether the src can use the skill on the target, -* taking into account status/option of both source/target. [Skotlex] -* flag: -* 0 - Trying to use skill on target. -* 1 - Cast bar is done. -* 2 - Skill already pulled off, check is due to ground-based skills or splash-damage ones. -* src MAY be null to indicate we shouldn't check it, this is a ground-based skill attack. -* target MAY Be null, in which case the checks are only to see -* whether the source can cast or not the skill on the ground. -*------------------------------------------*/ -int status_check_skilluse(struct block_list *src, struct block_list *target, uint16 skill_id, int flag) + * Checks whether the src can use the skill on the target, + * taking into account status/option of both source/target. [Skotlex] + * flag: + * 0 - Trying to use skill on target. + * 1 - Cast bar is done. + * 2 - Skill already pulled off, check is due to ground-based skills or splash-damage ones. + * src MAY be null to indicate we shouldn't check it, this is a ground-based skill attack. + * target MAY Be null, in which case the checks are only to see + * whether the source can cast or not the skill on the ground. + *------------------------------------------*/ +static int status_check_skilluse(struct block_list *src, struct block_list *target, uint16 skill_id, int flag) { struct status_data *st; struct status_change *sc=NULL, *tsc; @@ -1749,6 +1780,9 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin if (src != NULL && src->type != BL_PC && status->isdead(src)) return 0; + if (sd != NULL && sd->block_action.skill && skill_id) // *pcblock script command + return 0; + if (!skill_id) { //Normal attack checks. if (!(st->mode&MD_CANATTACK)) return 0; //This mode is only needed for melee attacking. @@ -1768,7 +1802,11 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin for(i = 0; i < map->list[src->m].zone->disabled_skills_count; i++) { if( skill_id == map->list[src->m].zone->disabled_skills[i]->nameid && (map->list[src->m].zone->disabled_skills[i]->type&src->type) ) { if (src->type == BL_PC) { - clif->msgtable(sd, MSG_SKILL_CANT_USE_AREA); // This skill cannot be used within this area +#if PACKETVER >= 20080311 + clif->skill_mapinfomessage(sd, 2); +#else + clif->messagecolor_self(sd->fd, COLOR_CYAN, msg_sd(sd, 50)); +#endif } else if (src->type == BL_MOB && map->list[src->m].zone->disabled_skills[i]->subtype != MZS_NONE) { if( st->mode&MD_BOSS ) { /* is boss */ if( !( map->list[src->m].zone->disabled_skills[i]->subtype&MZS_BOSS ) ) @@ -2030,7 +2068,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin //Skotlex: Calculates the initial status for the given mob //first will only be false when the mob leveled up or got a GuardUp level. -int status_calc_mob_(struct mob_data *md, enum e_status_calc_opt opt) +static int status_calc_mob_(struct mob_data *md, enum e_status_calc_opt opt) { struct status_data *mstatus; struct block_list *mbl = NULL; @@ -2201,7 +2239,7 @@ int status_calc_mob_(struct mob_data *md, enum e_status_calc_opt opt) } //Skotlex: Calculates the stats of the given pet. -int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt) +static int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt) { nullpo_ret(pd); @@ -2263,7 +2301,7 @@ int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt) return 1; } -unsigned int status_get_base_maxsp(const struct map_session_data *sd, const struct status_data *st) +static unsigned int status_get_base_maxsp(const struct map_session_data *sd, const struct status_data *st) { uint64 val; @@ -2284,7 +2322,7 @@ unsigned int status_get_base_maxsp(const struct map_session_data *sd, const stru return (unsigned int)cap_value(val, 0, UINT_MAX); } -unsigned int status_get_base_maxhp(const struct map_session_data *sd, const struct status_data *st) +static unsigned int status_get_base_maxhp(const struct map_session_data *sd, const struct status_data *st) { uint64 val; @@ -2311,20 +2349,77 @@ unsigned int status_get_base_maxhp(const struct map_session_data *sd, const stru return (unsigned int)cap_value(val,0,UINT_MAX); } -void status_calc_pc_additional(struct map_session_data* sd, enum e_status_calc_opt opt) +/** + * Calculates the HP that a character will have after death, on respawn. + * + * @param sd The character to calculate. + * @param st The character's status data. + */ +static unsigned int status_get_restart_hp(const struct map_session_data *sd, const struct status_data *st) +{ + unsigned int hp = 0; + + if (sd->special_state.restart_full_recover) + return st->max_hp; + + if ((sd->job & MAPID_BASEMASK) == MAPID_NOVICE && (sd->job & JOBL_2) == 0 && battle_config.restart_hp_rate < 50) + hp = st->max_hp / 2; + else + hp = APPLY_RATE(st->max_hp, battle_config.restart_hp_rate); + + if (hp > 0) + return hp; + + return 1; +} + +/** + * Calculates the SP that a character will have after death, on respawn. + * + * @param sd The character to calculate. + * @param st The character's status data. + */ +static unsigned int status_get_restart_sp(const struct map_session_data *sd, const struct status_data *st) +{ + unsigned int sp = 0; + + if (sd->special_state.restart_full_recover) + return st->max_sp; + + sp = APPLY_RATE(st->max_sp, battle_config.restart_sp_rate); + + if (sp > 0) + return sp; + + return 1; // the minimum for the respawn setting is SP:1 +} + +static void status_calc_pc_additional(struct map_session_data *sd, enum e_status_calc_opt opt) { /* Just used for Plugin to give bonuses. */ return; } +static void status_calc_pc_recover_hp(struct map_session_data *sd, struct status_data *bstatus) +{ + nullpo_retv(sd); + nullpo_retv(bstatus); + + if ((sd->job & MAPID_BASEMASK) == MAPID_NOVICE && (sd->job & JOBL_2) == 0 + && battle_config.restart_hp_rate < 50) + bstatus->hp = bstatus->max_hp>>1; + else + bstatus->hp = APPLY_RATE(bstatus->max_hp, battle_config.restart_hp_rate); +} + //Calculates player data from scratch without counting SC adjustments. //Should be invoked whenever players raise stats, learn passive skills or change equipment. -int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) +static 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 *bstatus; // pointer to the player's base status const struct status_change *sc; - struct s_skill b_skill[MAX_SKILL]; // previous skill tree + struct s_skill b_skill[MAX_SKILL_DB]; // previous skill tree int b_weight, b_max_weight, b_cart_weight_max, // previous weight i, k, index, skill_lv,refinedef=0; int64 i64; @@ -2351,7 +2446,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) sd->regen.sregen = &sd->sregen; sd->regen.ssregen = &sd->ssregen; sd->weight=0; - for(i=0;i<MAX_INVENTORY;i++){ + for (i = 0; i < sd->status.inventorySize; i++) { if(sd->status.inventory[i].nameid==0 || sd->inventory_data[i] == NULL) continue; sd->weight += sd->inventory_data[i]->weight*sd->status.inventory[i].amount; @@ -2400,8 +2495,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) bstatus->speed = pSpeed; } - //FIXME: Most of these stuff should be calculated once, but how do I fix the memset above to do that? [Skotlex] - //Give them all modes except these (useful for clones) + // FIXME: Most of these stuff should be calculated once, but how do I fix the memset above to do that? [Skotlex] + // Give them all modes except these (useful for clones) bstatus->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK); bstatus->size = ((sd->job & JOBL_BABY) != 0 || (sd->job & MAPID_BASEMASK) == MAPID_SUMMONER)?SZ_SMALL:SZ_MEDIUM; @@ -2647,6 +2742,45 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) } } + /* parse item options [Smokexyz] */ + for (i = 0; i < EQI_MAX; i++) { + status->current_equip_item_index = index = sd->equip_index[i]; + status->current_equip_option_index = -1; + + if (i == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) + continue; + else if (i == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) + continue; + else if (i == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) + continue; + + if (index >= 0 && sd->inventory_data[index]) { + int j = 0; + for (j = 0; j < MAX_ITEM_OPTIONS; j++) { + int16 option_index = sd->status.inventory[index].option[j].index; + struct itemdb_option *ito = NULL; + + if (option_index == 0 || (ito = itemdb->option_exists(option_index)) == NULL || ito->script == NULL) + continue; + + status->current_equip_option_index = j; + script->run(ito->script, 0, sd->bl.id, 0); + + if (calculating == 0) //Abort, script->run his function. [Skotlex] + return 1; + } + } + } + + status->current_equip_option_index = -1; + status->current_equip_item_index = -1; + + // Clan Buffs + if (sd->status.clan_id > 0) { + struct clan *c = clan->search(sd->status.clan_id); + clan->buff_start(sd, c); + } + status->calc_pc_additional(sd, opt); if( sd->pd ) { // Pet Bonus @@ -2675,9 +2809,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) sd->left_weapon.atkmods[1] = status->dbs->atkmods[1][sd->weapontype2]; sd->left_weapon.atkmods[2] = status->dbs->atkmods[2][sd->weapontype2]; - if ((pc_isridingpeco(sd) || pc_isridingdragon(sd)) - && (sd->status.weapon==W_1HSPEAR || sd->status.weapon==W_2HSPEAR) - ) { + if ((pc_isridingpeco(sd) || pc_isridingdragon(sd)) && (sd->weapontype == W_1HSPEAR || sd->weapontype == W_2HSPEAR)) { //When Riding with spear, damage modifier to mid-class becomes //same as versus large size. sd->right_weapon.atkmods[1] = sd->right_weapon.atkmods[2]; @@ -2741,8 +2873,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) // Base batk value is set on status->calc_misc // weapon-type bonus (FIXME: Why is the weapon_atk bonus applied to base attack?) - if (sd->status.weapon < MAX_SINGLE_WEAPON_TYPE && sd->weapon_atk[sd->status.weapon]) - bstatus->batk += sd->weapon_atk[sd->status.weapon]; + if (sd->weapontype < MAX_SINGLE_WEAPON_TYPE && sd->weapon_atk[sd->weapontype]) + bstatus->batk += sd->weapon_atk[sd->weapontype]; // Absolute modifiers from passive skills #ifndef RENEWAL if((skill_lv=pc->checkskill(sd,BS_HILTBINDING))>0) // it doesn't work in RE. @@ -2816,24 +2948,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) // ----- RESPAWN HP/SP ----- // //Calc respawn hp and store it on base_status - if (sd->special_state.restart_full_recover) - { - bstatus->hp = bstatus->max_hp; - bstatus->sp = bstatus->max_sp; - } else { - if ((sd->job & MAPID_BASEMASK) == MAPID_NOVICE && (sd->job & JOBL_2) == 0 - && battle_config.restart_hp_rate < 50) - bstatus->hp = bstatus->max_hp>>1; - else - bstatus->hp = APPLY_RATE(bstatus->max_hp, battle_config.restart_hp_rate); - if(!bstatus->hp) - bstatus->hp = 1; - - bstatus->sp = APPLY_RATE(bstatus->max_sp, battle_config.restart_sp_rate); - - if( !bstatus->sp ) /* the minimum for the respawn setting is SP:1 */ - bstatus->sp = 1; - } + bstatus->hp = status->get_restart_hp(sd, bstatus); + bstatus->sp = status->get_restart_sp(sd, bstatus); // ----- MISC CALCULATION ----- status->calc_misc(&sd->bl, bstatus, sd->status.base_level); @@ -2890,10 +3006,10 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) #ifndef RENEWAL bstatus->hit += skill_lv; #endif - if(sd->status.weapon == W_BOW) + if (sd->weapontype == W_BOW) bstatus->rhw.range += skill_lv; } - if(sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE) { + if (sd->weapontype >= W_REVOLVER && sd->weapontype <= W_GRENADE) { if((skill_lv=pc->checkskill(sd,GS_SINGLEACTION))>0) bstatus->hit += 2*skill_lv; if((skill_lv=pc->checkskill(sd,GS_SNAKEEYE))>0) { @@ -2901,9 +3017,9 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) bstatus->rhw.range += skill_lv; } } - if( (sd->status.weapon == W_1HAXE || sd->status.weapon == W_2HAXE) && (skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0 ) + if ((sd->weapontype == W_1HAXE || sd->weapontype == W_2HAXE) && (skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0) bstatus->hit += 3*skill_lv; - if((sd->status.weapon == W_MACE || sd->status.weapon == W_2HMACE) && (skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0) + if ((sd->weapontype == W_MACE || sd->weapontype == W_2HMACE) && (skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0) bstatus->hit += 2*skill_lv; if (pc->checkskill(sd, SU_POWEROFLIFE) > 0) bstatus->hit += 20; @@ -2963,12 +3079,11 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) // Relative modifiers from passive skills #ifndef RENEWAL_ASPD - if((skill_lv=pc->checkskill(sd,SA_ADVANCEDBOOK))>0 && sd->status.weapon == W_BOOK) + if (sd->weapontype == W_BOOK && (skill_lv=pc->checkskill(sd,SA_ADVANCEDBOOK)) > 0) bstatus->aspd_rate -= 5*skill_lv; if((skill_lv = pc->checkskill(sd,SG_DEVIL)) > 0 && !pc->nextjobexp(sd)) bstatus->aspd_rate -= 30*skill_lv; - if((skill_lv=pc->checkskill(sd,GS_SINGLEACTION))>0 && - (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)) + if (sd->weapontype >= W_REVOLVER && sd->weapontype <= W_GRENADE && (skill_lv=pc->checkskill(sd,GS_SINGLEACTION)) > 0) bstatus->aspd_rate -= ((skill_lv+1)/2) * 10; if (pc_isridingpeco(sd)) bstatus->aspd_rate += 500-100*pc->checkskill(sd,KN_CAVALIERMASTERY); @@ -3223,7 +3338,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) return 0; } -int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt) +static int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt) { struct status_data *mstatus; struct s_mercenary *merc; @@ -3246,7 +3361,7 @@ int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt return 0; } -int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt) +static int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt) { struct status_data *estatus; struct s_elemental *ele; @@ -3290,7 +3405,7 @@ int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt return 0; } -int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt) +static int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt) { struct status_data *nstatus; @@ -3327,7 +3442,7 @@ int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt) return 0; } -int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) +static int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) { struct status_data *hstatus; struct s_homunculus *hom; @@ -3417,7 +3532,7 @@ int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) } //Calculates base regen values. -void status_calc_regen(struct block_list *bl, struct status_data *st, struct regen_data *regen) +static void status_calc_regen(struct block_list *bl, struct status_data *st, struct regen_data *regen) { struct map_session_data *sd; int val, skill_lv, reg_flag; @@ -3518,7 +3633,7 @@ void status_calc_regen(struct block_list *bl, struct status_data *st, struct reg } //Calculates SC related regen rates. -void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, struct status_change *sc) +static void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, struct status_change *sc) { nullpo_retv(bl); if (!(bl->type&BL_REGEN) || !regen) @@ -3642,7 +3757,7 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str /// Recalculates parts of an object's battle status according to the specified flags. /// @param flag bitfield of values from enum scb_flag -void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) +static void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) { const struct status_data *bst = status->get_base_status(bl); struct status_data *st = status->get_status_data(bl); @@ -3858,7 +3973,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) } else { st->cri = status->calc_critical(bl, sc, bst->cri + 3*(st->luk - bst->luk), true); } - if (battle_config.show_katar_crit_bonus && bl->type == BL_PC && BL_UCAST(BL_PC, bl)->status.weapon == W_KATAR) { + if (battle_config.show_katar_crit_bonus && bl->type == BL_PC && BL_UCAST(BL_PC, bl)->weapontype == W_KATAR) { st->cri *= 2; } } @@ -4041,7 +4156,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) /// Also sends updates to the client wherever applicable. /// @param flag bitfield of values from enum scb_flag /// @param first 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, enum e_status_calc_opt opt) +static void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_calc_opt opt) { struct status_data bst; // previous battle status struct status_data *st; // pointer to current battle status @@ -4226,7 +4341,7 @@ void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_ca } //Checks whether the source can see and chase target. -int status_check_visibility(struct block_list *src, struct block_list *target) +static int status_check_visibility(struct block_list *src, struct block_list *target) { int view_range; struct status_change *tsc = NULL; @@ -4278,7 +4393,7 @@ int status_check_visibility(struct block_list *src, struct block_list *target) } // Basic ASPD value -int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) +static int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) { int amotion; #ifdef RENEWAL_ASPD /* [malufett/Hercules] */ @@ -4289,11 +4404,11 @@ int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) nullpo_ret(st); amotion = status->dbs->aspd_base[pc->class2idx(sd->status.class)][sd->weapontype1]; - if ( sd->status.weapon > MAX_SINGLE_WEAPON_TYPE) + if (sd->weapontype > MAX_SINGLE_WEAPON_TYPE) amotion += status->dbs->aspd_base[pc->class2idx(sd->status.class)][sd->weapontype2] / 4; - if ( sd->status.shield ) + if (sd->has_shield) amotion += status->dbs->aspd_base[pc->class2idx(sd->status.class)][MAX_SINGLE_WEAPON_TYPE]; - switch ( sd->status.weapon ) { + switch (sd->weapontype) { case W_BOW: case W_MUSICAL: case W_WHIP: @@ -4308,15 +4423,15 @@ int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) temp = st->dex * st->dex / 5.0f + st->agi * st->agi * 0.5f; } temp = (float)(sqrt(temp) * 0.25f) + 0xc4; - if ( (skill_lv = pc->checkskill(sd, SA_ADVANCEDBOOK)) > 0 && sd->status.weapon == W_BOOK ) + if (sd->weapontype == W_BOOK && (skill_lv = pc->checkskill(sd, SA_ADVANCEDBOOK)) > 0) val += (skill_lv - 1) / 2 + 1; if ( (skill_lv = pc->checkskill(sd, GS_SINGLEACTION)) > 0 ) val += ((skill_lv + 1) / 2); amotion = ((int)(temp + ((float)(status->calc_aspd(&sd->bl, &sd->sc, 1) + val) * st->agi / 200)) - min(amotion, 200)); #else // base weapon delay - amotion = (sd->status.weapon < MAX_SINGLE_WEAPON_TYPE) - ? (status->dbs->aspd_base[pc->class2idx(sd->status.class)][sd->status.weapon]) // single weapon + amotion = (sd->weapontype < MAX_SINGLE_WEAPON_TYPE) + ? (status->dbs->aspd_base[pc->class2idx(sd->status.class)][sd->weapontype]) // single weapon : (status->dbs->aspd_base[pc->class2idx(sd->status.class)][sd->weapontype1] + status->dbs->aspd_base[pc->class2idx(sd->status.class)][sd->weapontype2]) * 7 / 10; // dual-wield // percentual delay reduction from stats @@ -4333,7 +4448,7 @@ int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) return amotion; } -unsigned short status_base_atk(const struct block_list *bl, const struct status_data *st) +static unsigned short status_base_atk(const struct block_list *bl, const struct status_data *st) { int flag = 0, str, dex, dstr; @@ -4343,7 +4458,7 @@ unsigned short status_base_atk(const struct block_list *bl, const struct status_ return 0; if (bl->type == BL_PC) { - switch (BL_UCCAST(BL_PC, bl)->status.weapon) { + switch (BL_UCCAST(BL_PC, bl)->weapontype) { case W_BOW: case W_MUSICAL: case W_WHIP: @@ -4393,19 +4508,24 @@ unsigned short status_base_atk(const struct block_list *bl, const struct status_ return cap_value(str, 0, USHRT_MAX); } -unsigned short status_base_matk_min(const struct status_data *st) +static unsigned short status_base_matk_min(const struct status_data *st) { nullpo_ret(st); +#ifdef RENEWAL + Assert_ret(0); + return 0; +#else // not RENEWAL return st->int_ + (st->int_ / 7) * (st->int_ / 7); +#endif // RENEWAL } -unsigned short status_base_matk_max(const struct status_data *st) +static unsigned short status_base_matk_max(const struct status_data *st) { nullpo_ret(st); return st->int_ + (st->int_ / 5)*(st->int_ / 5); } -unsigned short status_base_matk(struct block_list *bl, const struct status_data *st, int level) +static unsigned short status_base_matk(struct block_list *bl, const struct status_data *st, int level) { #ifdef RENEWAL nullpo_ret(bl); @@ -4422,12 +4542,13 @@ unsigned short status_base_matk(struct block_list *bl, const struct status_data return st->int_ + (st->int_ / 2) + (st->dex / 5) + (st->luk / 3) + (level / 4); } #else + Assert_ret(0); return 0; #endif } //Fills in the misc data that can be calculated from the other status info (except for level) -void status_calc_misc(struct block_list *bl, struct status_data *st, int level) +static void status_calc_misc(struct block_list *bl, struct status_data *st, int level) { nullpo_retv(bl); nullpo_retv(st); @@ -4509,9 +4630,9 @@ void status_calc_misc(struct block_list *bl, struct status_data *st, int level) } /*========================================== -* Apply shared stat mods from status changes [DracoRPG] -*------------------------------------------*/ -unsigned short status_calc_str(struct block_list *bl, struct status_change *sc, int str) + * Apply shared stat mods from status changes [DracoRPG] + *------------------------------------------*/ +static unsigned short status_calc_str(struct block_list *bl, struct status_change *sc, int str) { if(!sc || !sc->count) return cap_value(str,0,USHRT_MAX); @@ -4574,7 +4695,7 @@ unsigned short status_calc_str(struct block_list *bl, struct status_change *sc, return (unsigned short)cap_value(str,0,USHRT_MAX); } -unsigned short status_calc_agi(struct block_list *bl, struct status_change *sc, int agi) +static unsigned short status_calc_agi(struct block_list *bl, struct status_change *sc, int agi) { if(!sc || !sc->count) return cap_value(agi,0,USHRT_MAX); @@ -4637,7 +4758,7 @@ unsigned short status_calc_agi(struct block_list *bl, struct status_change *sc, return (unsigned short)cap_value(agi,0,USHRT_MAX); } -unsigned short status_calc_vit(struct block_list *bl, struct status_change *sc, int vit) +static unsigned short status_calc_vit(struct block_list *bl, struct status_change *sc, int vit) { if(!sc || !sc->count) return cap_value(vit,0,USHRT_MAX); @@ -4688,7 +4809,7 @@ unsigned short status_calc_vit(struct block_list *bl, struct status_change *sc, return (unsigned short)cap_value(vit,0,USHRT_MAX); } -unsigned short status_calc_int(struct block_list *bl, struct status_change *sc, int int_) +static unsigned short status_calc_int(struct block_list *bl, struct status_change *sc, int int_) { nullpo_ret(bl); if(!sc || !sc->count) @@ -4755,7 +4876,7 @@ unsigned short status_calc_int(struct block_list *bl, struct status_change *sc, return (unsigned short)cap_value(int_,0,USHRT_MAX); } -unsigned short status_calc_dex(struct block_list *bl, struct status_change *sc, int dex) +static unsigned short status_calc_dex(struct block_list *bl, struct status_change *sc, int dex) { nullpo_ret(bl); if(!sc || !sc->count) @@ -4818,7 +4939,7 @@ unsigned short status_calc_dex(struct block_list *bl, struct status_change *sc, return (unsigned short)cap_value(dex,0,USHRT_MAX); } -unsigned short status_calc_luk(struct block_list *bl, struct status_change *sc, int luk) +static unsigned short status_calc_luk(struct block_list *bl, struct status_change *sc, int luk) { nullpo_ret(bl); @@ -4873,7 +4994,7 @@ unsigned short status_calc_luk(struct block_list *bl, struct status_change *sc, return (unsigned short)cap_value(luk, 0, USHRT_MAX); } -unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc, int batk, bool viewable) +static unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc, int batk, bool viewable) { nullpo_ret(bl); if(!sc || !sc->count) @@ -4922,9 +5043,6 @@ unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc, #ifndef RENEWAL if(sc->data[SC_LKCONCENTRATION]) batk += batk * sc->data[SC_LKCONCENTRATION]->val2/100; -#else - if ( sc->data[SC_NOEQUIPWEAPON] && bl->type != BL_PC ) - batk -= batk * sc->data[SC_NOEQUIPWEAPON]->val2 / 100; #endif if(sc->data[SC_SKE]) batk += batk * 3; @@ -4972,7 +5090,7 @@ unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc, return (unsigned short)cap_value(batk,0,USHRT_MAX); } -unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc, int watk, bool viewable) +static unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc, int watk, bool viewable) { nullpo_ret(bl); if(!sc || !sc->count) @@ -5027,7 +5145,7 @@ unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc, if(sc->data[SC_LKCONCENTRATION]) watk += watk * sc->data[SC_LKCONCENTRATION]->val2/100; #endif - if(sc->data[SC_INCATKRATE] && bl->type != BL_MOB) + if(sc->data[SC_INCATKRATE]) watk += watk * sc->data[SC_INCATKRATE]->val1/100; if(sc->data[SC_PROVOKE]) watk += watk * sc->data[SC_PROVOKE]->val3/100; @@ -5037,10 +5155,8 @@ unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc, watk += watk * sc->data[SC_HLIF_FLEET]->val3/100; if(sc->data[SC_CURSE]) watk -= watk * 25/100; -#ifndef RENEWAL if(sc->data[SC_NOEQUIPWEAPON] && bl->type != BL_PC) watk -= watk * sc->data[SC_NOEQUIPWEAPON]->val2/100; -#endif if(sc->data[SC__ENERVATION]) watk -= watk * sc->data[SC__ENERVATION]->val2 / 100; if(sc->data[SC_RUSH_WINDMILL]) @@ -5067,7 +5183,7 @@ unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc, return (unsigned short)cap_value(watk,0,USHRT_MAX); } -unsigned short status_calc_ematk(struct block_list *bl, struct status_change *sc, int matk) +static unsigned short status_calc_ematk(struct block_list *bl, struct status_change *sc, int matk) { #ifdef RENEWAL if (!sc || !sc->count) @@ -5098,7 +5214,7 @@ unsigned short status_calc_ematk(struct block_list *bl, struct status_change *sc #endif } -unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc, int matk, bool viewable) +static unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc, int matk, bool viewable) { if (!sc || !sc->count) return cap_value(matk,0,USHRT_MAX); @@ -5168,7 +5284,7 @@ unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc, return (unsigned short)cap_value(matk, 0, USHRT_MAX); } -signed short status_calc_critical(struct block_list *bl, struct status_change *sc, int critical, bool viewable) +static signed short status_calc_critical(struct block_list *bl, struct status_change *sc, int critical, bool viewable) { if (!sc || !sc->count) return cap_value(critical, 10, SHRT_MAX); @@ -5209,7 +5325,7 @@ signed short status_calc_critical(struct block_list *bl, struct status_change *s return (short)cap_value(critical, 10, SHRT_MAX); } -signed short status_calc_hit(struct block_list *bl, struct status_change *sc, int hit, bool viewable) +static signed short status_calc_hit(struct block_list *bl, struct status_change *sc, int hit, bool viewable) { if (!sc || !sc->count) @@ -5264,7 +5380,7 @@ signed short status_calc_hit(struct block_list *bl, struct status_change *sc, in return (short)cap_value(hit, 1, SHRT_MAX); } -signed short status_calc_flee(struct block_list *bl, struct status_change *sc, int flee, bool viewable) +static signed short status_calc_flee(struct block_list *bl, struct status_change *sc, int flee, bool viewable) { nullpo_retr(1, bl); @@ -5361,7 +5477,7 @@ signed short status_calc_flee(struct block_list *bl, struct status_change *sc, i return (short)cap_value(flee, 1, SHRT_MAX); } -signed short status_calc_flee2(struct block_list *bl, struct status_change *sc, int flee2, bool viewable) +static signed short status_calc_flee2(struct block_list *bl, struct status_change *sc, int flee2, bool viewable) { if(!sc || !sc->count) return cap_value(flee2,10,SHRT_MAX); @@ -5383,7 +5499,7 @@ signed short status_calc_flee2(struct block_list *bl, struct status_change *sc, return (short)cap_value(flee2,10,SHRT_MAX); } -defType status_calc_def(struct block_list *bl, struct status_change *sc, int def, bool viewable) +static defType status_calc_def(struct block_list *bl, struct status_change *sc, int def, bool viewable) { nullpo_retr(DEFTYPE_MIN, bl); @@ -5488,7 +5604,7 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX); } -signed short status_calc_def2(struct block_list *bl, struct status_change *sc, int def2, bool viewable) +static signed short status_calc_def2(struct block_list *bl, struct status_change *sc, int def2, bool viewable) { nullpo_retr(1, bl); if(!sc || !sc->count) @@ -5565,7 +5681,7 @@ signed short status_calc_def2(struct block_list *bl, struct status_change *sc, i #endif } -defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int mdef, bool viewable) +static defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int mdef, bool viewable) { if(!sc || !sc->count) @@ -5622,7 +5738,7 @@ defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int md return (defType)cap_value(mdef,DEFTYPE_MIN,DEFTYPE_MAX); } -signed short status_calc_mdef2(struct block_list *bl, struct status_change *sc, int mdef2, bool viewable) +static signed short status_calc_mdef2(struct block_list *bl, struct status_change *sc, int mdef2, bool viewable) { if(!sc || !sc->count) #ifdef RENEWAL @@ -5661,7 +5777,7 @@ signed short status_calc_mdef2(struct block_list *bl, struct status_change *sc, #endif } -unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc, int speed) +static unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc, int speed) { struct map_session_data *sd = BL_CAST(BL_PC, bl); int speed_rate = -1; @@ -5864,7 +5980,7 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc // flag&1 - fixed value [malufett] // flag&2 - percentage value -short status_calc_aspd(struct block_list *bl, struct status_change *sc, short flag) +static short status_calc_aspd(struct block_list *bl, struct status_change *sc, short flag) { #ifdef RENEWAL_ASPD int pots = 0, bonus = 0; @@ -5904,7 +6020,7 @@ short status_calc_aspd(struct block_list *bl, struct status_change *sc, short fl if (bl->type != BL_PC) { bonus = sc->data[SC_ASSNCROS]->val2; } else { - switch (BL_UCCAST(BL_PC, bl)->status.weapon) { + switch (BL_UCCAST(BL_PC, bl)->weapontype) { case W_BOW: case W_REVOLVER: case W_RIFLE: @@ -5996,7 +6112,7 @@ short status_calc_aspd(struct block_list *bl, struct status_change *sc, short fl #endif } -short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int aspd) +static short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int aspd) { nullpo_ret(bl); if (!sc || !sc->count) @@ -6016,7 +6132,7 @@ short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int /// Calculates an object's ASPD modifier (alters the base amotion value). /// Note that the scale of aspd_rate is 1000 = 100%. -short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int aspd_rate) +static short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int aspd_rate) { int i; @@ -6065,7 +6181,7 @@ short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int if (bl->type != BL_PC) { max = sc->data[SC_ASSNCROS]->val2; } else { - switch (BL_UCCAST(BL_PC, bl)->status.weapon) { + switch (BL_UCCAST(BL_PC, bl)->weapontype) { case W_BOW: case W_REVOLVER: case W_RIFLE: @@ -6159,7 +6275,7 @@ short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int return (short)cap_value(aspd_rate,0,SHRT_MAX); } -unsigned short status_calc_dmotion(struct block_list *bl, struct status_change *sc, int dmotion) +static unsigned short status_calc_dmotion(struct block_list *bl, struct status_change *sc, int dmotion) { nullpo_ret(bl); // It has been confirmed on official servers that MvP mobs have no dmotion even without endure @@ -6177,7 +6293,7 @@ unsigned short status_calc_dmotion(struct block_list *bl, struct status_change * return (unsigned short)cap_value(dmotion,0,USHRT_MAX); } -unsigned int status_calc_maxhp(struct block_list *bl, struct status_change *sc, uint64 maxhp) +static unsigned int status_calc_maxhp(struct block_list *bl, struct status_change *sc, uint64 maxhp) { if (!sc || !sc->count) @@ -6257,7 +6373,7 @@ unsigned int status_calc_maxhp(struct block_list *bl, struct status_change *sc, return (unsigned int)cap_value(maxhp, 1, UINT_MAX); } -unsigned int status_calc_maxsp(struct block_list *bl, struct status_change *sc, unsigned int maxsp) +static unsigned int status_calc_maxsp(struct block_list *bl, struct status_change *sc, unsigned int maxsp) { if (!sc || !sc->count) return cap_value(maxsp, 1, UINT_MAX); @@ -6296,7 +6412,7 @@ unsigned int status_calc_maxsp(struct block_list *bl, struct status_change *sc, return cap_value(maxsp, 1, UINT_MAX); } -unsigned char status_calc_element(struct block_list *bl, struct status_change *sc, int element) +static unsigned char status_calc_element(struct block_list *bl, struct status_change *sc, int element) { if(!sc || !sc->count) return element; @@ -6317,7 +6433,7 @@ unsigned char status_calc_element(struct block_list *bl, struct status_change *s return (unsigned char)cap_value(element,0,UCHAR_MAX); } -unsigned char status_calc_element_lv(struct block_list *bl, struct status_change *sc, int lv) +static unsigned char status_calc_element_lv(struct block_list *bl, struct status_change *sc, int lv) { if(!sc || !sc->count) return lv; @@ -6340,7 +6456,7 @@ unsigned char status_calc_element_lv(struct block_list *bl, struct status_change return (unsigned char)cap_value(lv,1,4); } -unsigned char status_calc_attack_element(struct block_list *bl, struct status_change *sc, int element) +static unsigned char status_calc_attack_element(struct block_list *bl, struct status_change *sc, int element) { if(!sc || !sc->count) return element; @@ -6381,7 +6497,7 @@ unsigned char status_calc_attack_element(struct block_list *bl, struct status_ch * @param mode The starting mode. * @return The calculated mode. */ -uint32 status_calc_mode(const struct block_list *bl, const struct status_change *sc, uint32 mode) +static uint32 status_calc_mode(const struct block_list *bl, const struct status_change *sc, uint32 mode) { if (sc == NULL || sc->count == 0) return mode & MD_MASK; @@ -6402,7 +6518,7 @@ uint32 status_calc_mode(const struct block_list *bl, const struct status_change * @param bl The requested bl. * @return The bl's name or NULL if not available. */ -const char *status_get_name(const struct block_list *bl) +static const char *status_get_name(const struct block_list *bl) { nullpo_ret(bl); switch (bl->type) { @@ -6422,12 +6538,12 @@ const char *status_get_name(const struct block_list *bl) } /*========================================== -* Get the class of the current bl -* return -* 0 = fail -* class_id = success -*------------------------------------------*/ -int status_get_class(const struct block_list *bl) + * Get the class of the current bl + * return + * 0 = fail + * class_id = success + *------------------------------------------*/ +static int status_get_class(const struct block_list *bl) { nullpo_ret(bl); switch (bl->type) { @@ -6442,12 +6558,12 @@ int status_get_class(const struct block_list *bl) return 0; } /*========================================== -* Get the base level of the current bl -* return -* 1 = fail -* level = success -*------------------------------------------*/ -int status_get_lv(const struct block_list *bl) + * Get the base level of the current bl + * return + * 1 = fail + * level = success + *------------------------------------------*/ +static int status_get_lv(const struct block_list *bl) { nullpo_ret(bl); switch (bl->type) { @@ -6462,7 +6578,7 @@ int status_get_lv(const struct block_list *bl) return 1; } -struct regen_data *status_get_regen_data(struct block_list *bl) +static struct regen_data *status_get_regen_data(struct block_list *bl) { nullpo_retr(NULL, bl); switch (bl->type) { @@ -6475,7 +6591,7 @@ struct regen_data *status_get_regen_data(struct block_list *bl) } } -struct status_data *status_get_status_data(struct block_list *bl) +static struct status_data *status_get_status_data(struct block_list *bl) { nullpo_retr(&status->dummy, bl); @@ -6496,7 +6612,7 @@ struct status_data *status_get_status_data(struct block_list *bl) } } -struct status_data *status_get_base_status(struct block_list *bl) +static struct status_data *status_get_base_status(struct block_list *bl) { nullpo_retr(NULL, bl); switch (bl->type) { @@ -6520,7 +6636,7 @@ struct status_data *status_get_base_status(struct block_list *bl) } } -defType status_get_def(struct block_list *bl) +static defType status_get_def(struct block_list *bl) { struct unit_data *ud; struct status_data *st = status->get_status_data(bl); @@ -6532,7 +6648,7 @@ defType status_get_def(struct block_list *bl) return cap_value(def, DEFTYPE_MIN, DEFTYPE_MAX); } -unsigned short status_get_speed(struct block_list *bl) +static unsigned short status_get_speed(struct block_list *bl) { nullpo_ret(bl); if (bl->type == BL_NPC) //Only BL with speed data but no status_data [Skotlex] @@ -6540,7 +6656,7 @@ unsigned short status_get_speed(struct block_list *bl) return status->get_status_data(bl)->speed; } -int status_get_party_id(const struct block_list *bl) +static int status_get_party_id(const struct block_list *bl) { nullpo_ret(bl); switch (bl->type) { @@ -6596,7 +6712,7 @@ int status_get_party_id(const struct block_list *bl) return 0; } -int status_get_guild_id(const struct block_list *bl) +static int status_get_guild_id(const struct block_list *bl) { nullpo_ret(bl); switch (bl->type) { @@ -6662,7 +6778,7 @@ int status_get_guild_id(const struct block_list *bl) return 0; } -int status_get_emblem_id(const struct block_list *bl) +static int status_get_emblem_id(const struct block_list *bl) { nullpo_ret(bl); switch (bl->type) { @@ -6724,7 +6840,7 @@ int status_get_emblem_id(const struct block_list *bl) return 0; } -int status_get_mexp(const struct block_list *bl) +static int status_get_mexp(const struct block_list *bl) { nullpo_ret(bl); if (bl->type == BL_MOB) @@ -6734,7 +6850,7 @@ int status_get_mexp(const struct block_list *bl) return 0; } -int status_get_race2(const struct block_list *bl) +static int status_get_race2(const struct block_list *bl) { nullpo_ret(bl); if (bl->type == BL_MOB) @@ -6744,13 +6860,13 @@ int status_get_race2(const struct block_list *bl) return 0; } -int status_isdead(struct block_list *bl) +static int status_isdead(struct block_list *bl) { nullpo_ret(bl); return status->get_status_data(bl)->hp == 0; } -int status_isimmune(struct block_list *bl) +static int status_isimmune(struct block_list *bl) { struct status_change *sc = NULL; nullpo_ret(bl); @@ -6767,14 +6883,14 @@ int status_isimmune(struct block_list *bl) return 0; } -struct view_data *status_get_viewdata(struct block_list *bl) +static struct view_data *status_get_viewdata(struct block_list *bl) { nullpo_retr(NULL, bl); switch (bl->type) { case BL_PC: return &BL_UCAST(BL_PC, bl)->vd; case BL_MOB: return BL_UCAST(BL_MOB, bl)->vd; case BL_PET: return &BL_UCAST(BL_PET, bl)->vd; - case BL_NPC: return BL_UCAST(BL_NPC, bl)->vd; + case BL_NPC: return &BL_UCAST(BL_NPC, bl)->vd; case BL_HOM: return BL_UCAST(BL_HOM, bl)->vd; case BL_MER: return BL_UCAST(BL_MER, bl)->vd; case BL_ELEM: return BL_UCAST(BL_ELEM, bl)->vd; @@ -6782,7 +6898,7 @@ struct view_data *status_get_viewdata(struct block_list *bl) return NULL; } -void status_set_viewdata(struct block_list *bl, int class_) +static void status_set_viewdata(struct block_list *bl, int class_) { struct view_data* vd; nullpo_retv(bl); @@ -6829,34 +6945,31 @@ void status_set_viewdata(struct block_list *bl, int class_) } sd->vd.class = class_; clif->get_weapon_view(sd, &sd->vd.weapon, &sd->vd.shield); - sd->vd.head_top = sd->status.head_top; - sd->vd.head_mid = sd->status.head_mid; - sd->vd.head_bottom = sd->status.head_bottom; + sd->vd.head_top = sd->status.look.head_top; + sd->vd.head_mid = sd->status.look.head_mid; + sd->vd.head_bottom = sd->status.look.head_bottom; sd->vd.hair_style = cap_value(sd->status.hair,0,battle_config.max_hair_style); sd->vd.hair_color = cap_value(sd->status.hair_color,0,battle_config.max_hair_color); sd->vd.cloth_color = cap_value(sd->status.clothes_color,0,battle_config.max_cloth_color); - sd->vd.robe = sd->status.robe; + sd->vd.robe = sd->status.look.robe; sd->vd.body_style = sd->status.body; sd->vd.sex = sd->status.sex; if (sd->vd.cloth_color) { - if (sd->sc.option&OPTION_WEDDING && battle_config.wedding_ignorepalette) - sd->vd.cloth_color = 0; - if (sd->sc.option&OPTION_XMAS && battle_config.xmas_ignorepalette) - sd->vd.cloth_color = 0; - if (sd->sc.option&OPTION_SUMMER && battle_config.summer_ignorepalette) - sd->vd.cloth_color = 0; - if (sd->sc.option&OPTION_HANBOK && battle_config.hanbok_ignorepalette) - sd->vd.cloth_color = 0; - if (sd->sc.option&OPTION_OKTOBERFEST /* TODO: config? */) + if ((sd->sc.option & OPTION_WEDDING) != 0 && battle_config.wedding_ignorepalette == true) + sd->vd.cloth_color = 0; + if ((sd->sc.option & OPTION_XMAS) != 0 && battle_config.xmas_ignorepalette == true) + sd->vd.cloth_color = 0; + if ((sd->sc.option & OPTION_SUMMER) != 0 && battle_config.summer_ignorepalette == true) + sd->vd.cloth_color = 0; + if ((sd->sc.option & OPTION_HANBOK) != 0 && battle_config.hanbok_ignorepalette == true) + sd->vd.cloth_color = 0; + if ((sd->sc.option & OPTION_OKTOBERFEST) != 0 && battle_config.oktoberfest_ignorepalette == true) + sd->vd.cloth_color = 0; + if ((sd->sc.option & OPTION_SUMMER2) != 0 && battle_config.summer2_ignorepalette == true) sd->vd.cloth_color = 0; } - if (sd->vd.body_style - && (sd->sc.option&OPTION_WEDDING - || sd->sc.option&OPTION_XMAS - || sd->sc.option&OPTION_SUMMER - || sd->sc.option&OPTION_HANBOK - || sd->sc.option&OPTION_OKTOBERFEST)) + if (sd->vd.body_style != 0 && (sd->sc.option & OPTION_COSTUME) != 0) sd->vd.body_style = 0; } else if (vd != NULL) { memcpy(&sd->vd, vd, sizeof(struct view_data)); @@ -6895,10 +7008,14 @@ void status_set_viewdata(struct block_list *bl, int class_) case BL_NPC: { struct npc_data *nd = BL_UCAST(BL_NPC, bl); - if (vd != NULL) - nd->vd = vd; - else + if (vd != NULL) { + memcpy(&nd->vd, vd, sizeof(struct view_data)); + } else if (pc->db_checkid(class_)) { + memset(&nd->vd, 0, sizeof(struct view_data)); + nd->vd.class = class_; + } else { ShowError("status_set_viewdata (NPC): No view data for class %d (name=%s)\n", class_, nd->name); + } } break; case BL_HOM: //[blackhole89] @@ -6932,7 +7049,7 @@ void status_set_viewdata(struct block_list *bl, int class_) } /// Returns the status_change data of bl or NULL if it doesn't exist. -struct status_change *status_get_sc(struct block_list *bl) +static struct status_change *status_get_sc(struct block_list *bl) { if (bl != NULL) { switch (bl->type) { @@ -6947,7 +7064,7 @@ struct status_change *status_get_sc(struct block_list *bl) return NULL; } -void status_change_init(struct block_list *bl) +static void status_change_init(struct block_list *bl) { struct status_change *sc = status->get_sc(bl); nullpo_retv(sc); @@ -6960,7 +7077,7 @@ void status_change_init(struct block_list *bl) * @see status_change_start for the expected parameters. * @return the adjusted duration based on flag values. */ -int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int tick, int flag) +static int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int tick, int flag) { //Percentual resistance: 10000 = 100% Resist //Example: 50% -> sc_def=5000 -> 25%; 5000ms -> tick_def=5000 -> 2500ms @@ -7324,7 +7441,7 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ } /* [Ind/Hercules] fast-checkin sc-display array */ -void status_display_add(struct map_session_data *sd, enum sc_type type, int dval1, int dval2, int dval3) +static void status_display_add(struct map_session_data *sd, enum sc_type type, int dval1, int dval2, int dval3) { struct sc_display_entry *entry; int i; @@ -7353,7 +7470,7 @@ void status_display_add(struct map_session_data *sd, enum sc_type type, int dval sd->sc_display[ sd->sc_display_count - 1 ] = entry; } -void status_display_remove(struct map_session_data *sd, enum sc_type type) +static void status_display_remove(struct map_session_data *sd, enum sc_type type) { int i; @@ -7387,6 +7504,7 @@ void status_display_remove(struct map_session_data *sd, enum sc_type type) } } } + /** * Starts a status change. * @@ -7404,7 +7522,7 @@ void status_display_remove(struct map_session_data *sd, enum sc_type type) * @retval 0 if no status change happened. * @retval 1 if the status change was successfully applied. */ -int status_change_start(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int flag) +static int status_change_start(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int flag) { struct map_session_data *sd = NULL; struct status_change* sc; @@ -7438,73 +7556,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t #endif // 0 } - if( sc->data[SC_REFRESH] ) { - if( type >= SC_COMMON_MIN && type <= SC_COMMON_MAX) // Confirmed. - return 0; // Immune to status ailements - switch( type ) { - case SC_DEEP_SLEEP: - case SC__CHAOS: - case SC_BURNING: - case SC_STUN: - case SC_SLEEP: - case SC_CURSE: - case SC_STONE: - case SC_POISON: - case SC_BLIND: - case SC_SILENCE: - case SC_BLOODING: - case SC_FREEZE: - case SC_FROSTMISTY: - case SC_COLD: - case SC_TOXIN: - case SC_PARALYSE: - case SC_VENOMBLEED: - case SC_MAGICMUSHROOM: - case SC_DEATHHURT: - case SC_PYREXIA: - case SC_OBLIVIONCURSE: - case SC_MARSHOFABYSS: - case SC_MANDRAGORA: - return 0; - } - } else if( sc->data[SC_INSPIRATION] ) { - if( type >= SC_COMMON_MIN && type <= SC_COMMON_MAX ) - return 0; // Immune to status ailements - switch( type ) { - case SC_POISON: - case SC_BLIND: - case SC_STUN: - case SC_SILENCE: - case SC__CHAOS: - case SC_STONE: - case SC_SLEEP: - case SC_BLOODING: - case SC_CURSE: - case SC_BURNING: - case SC_FROSTMISTY: - case SC_FREEZE: - case SC_COLD: - case SC_FEAR: - case SC_TOXIN: - case SC_PARALYSE: - case SC_VENOMBLEED: - case SC_MAGICMUSHROOM: - case SC_DEATHHURT: - case SC_PYREXIA: - case SC_OBLIVIONCURSE: - case SC_LEECHESEND: - case SC_DEEP_SLEEP: - case SC_SATURDAY_NIGHT_FEVER: - case SC__BODYPAINT: - case SC__ENERVATION: - case SC__GROOMY: - case SC__IGNORANCE: - case SC__LAZINESS: - case SC__UNLUCKY: - case SC__WEAKNESS: - return 0; - } - } + if (status->is_immune_to_status(sc, type)) + return 0; sd = BL_CAST(BL_PC, bl); @@ -7514,8 +7567,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t if( !tick ) return 0; } - undead_flag = battle->check_undead(st->race,st->def_ele); - //Check for inmunities / sc fails + undead_flag = battle->check_undead(st->race, st->def_ele); + // Check for inmunities / sc fails switch (type) { case SC_DRUMBATTLE: case SC_NIBELUNGEN: @@ -7737,30 +7790,6 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t if (sc->data[SC_FOOD_LUK_CASH] && sc->data[SC_FOOD_LUK_CASH]->val1 > val1) return 0; break; - case SC_FOOD_STR_CASH: - if (sc->data[SC_FOOD_STR] && sc->data[SC_FOOD_STR]->val1 > val1) - return 0; - break; - case SC_FOOD_AGI_CASH: - if (sc->data[SC_FOOD_AGI] && sc->data[SC_FOOD_AGI]->val1 > val1) - return 0; - break; - case SC_FOOD_VIT_CASH: - if (sc->data[SC_FOOD_VIT] && sc->data[SC_FOOD_VIT]->val1 > val1) - return 0; - break; - case SC_FOOD_INT_CASH: - if (sc->data[SC_FOOD_INT] && sc->data[SC_FOOD_INT]->val1 > val1) - return 0; - break; - case SC_FOOD_DEX_CASH: - if (sc->data[SC_FOOD_DEX] && sc->data[SC_FOOD_DEX]->val1 > val1) - return 0; - break; - case SC_FOOD_LUK_CASH: - if (sc->data[SC_FOOD_LUK] && sc->data[SC_FOOD_LUK]->val1 > val1) - return 0; - break; case SC_CAMOUFLAGE: if( sd && pc->checkskill(sd, RA_CAMOUFLAGE) < 3 && !skill->check_camouflage(bl,NULL) ) return 0; @@ -7804,310 +7833,14 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t } //Check for BOSS resistances - if(st->mode&MD_BOSS && !(flag&SCFLAG_NOAVOID)) { - if (type>=SC_COMMON_MIN && type <= SC_COMMON_MAX) + if (st->mode & MD_BOSS && !(flag & SCFLAG_NOAVOID)) { + if (status->is_boss_resist_sc(type)) return 0; - switch (type) { - case SC_BLESSING: - case SC_DEC_AGI: - case SC_PROVOKE: - case SC_COMA: - case SC_GRAVITATION: - case SC_NJ_SUITON: - case SC_RICHMANKIM: - case SC_ROKISWEIL: - case SC_FOGWALL: - case SC_FROSTMISTY: - case SC_BURNING: - case SC_MARSHOFABYSS: - case SC_ADORAMUS: - case SC_NEEDLE_OF_PARALYZE: - case SC_DEEP_SLEEP: - case SC_COLD: - - // Exploit prevention - kRO Fix - case SC_PYREXIA: - case SC_DEATHHURT: - case SC_TOXIN: - case SC_PARALYSE: - case SC_VENOMBLEED: - case SC_MAGICMUSHROOM: - case SC_OBLIVIONCURSE: - case SC_LEECHESEND: - - // Ranger Effects - case SC_WUGBITE: - case SC_ELECTRICSHOCKER: - case SC_MAGNETICFIELD: - - // Masquerades - case SC__ENERVATION: - case SC__GROOMY: - case SC__LAZINESS: - case SC__UNLUCKY: - case SC__WEAKNESS: - case SC__IGNORANCE: - - // Other Effects - case SC_VACUUM_EXTREME: - case SC_NETHERWORLD: - case SC_FRESHSHRIMP: - case SC_SV_ROOTTWIST: - case SC_BITESCAR: - return 0; - } } //Before overlapping fail, one must check for status cured. - switch (type) { - case SC_BLESSING: - //TO-DO Blessing and Agi up should do 1 damage against players on Undead Status, even on PvM - //but cannot be plagiarized (this requires aegis investigation on packets and official behavior) [Brainstorm] - if ((!undead_flag && st->race!=RC_DEMON) || bl->type == BL_PC) { - status_change_end(bl, SC_CURSE, INVALID_TIMER); - if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) - status_change_end(bl, SC_STONE, INVALID_TIMER); - } - if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH) - status_change_end(bl, SC_SOULLINK, INVALID_TIMER); - break; - case SC_INC_AGI: - status_change_end(bl, SC_DEC_AGI, INVALID_TIMER); - if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH) - status_change_end(bl, SC_SOULLINK, INVALID_TIMER); - break; - case SC_QUAGMIRE: - status_change_end(bl, SC_CONCENTRATION, INVALID_TIMER); - status_change_end(bl, SC_TRUESIGHT, INVALID_TIMER); - status_change_end(bl, SC_WINDWALK, INVALID_TIMER); - FALLTHROUGH - //Also blocks the ones below... - case SC_DEC_AGI: - case SC_ADORAMUS: - status_change_end(bl, SC_CARTBOOST, INVALID_TIMER); - //Also blocks the ones below... - FALLTHROUGH - case SC_DONTFORGETME: - status_change_end(bl, SC_INC_AGI, INVALID_TIMER); - status_change_end(bl, SC_ADRENALINE, INVALID_TIMER); - status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER); - status_change_end(bl, SC_SPEARQUICKEN, INVALID_TIMER); - status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); - status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER); - status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER); - status_change_end(bl, SC_ACCELERATION, INVALID_TIMER); - break; - case SC_ONEHANDQUICKEN: - //Removes the Aspd potion effect, as reported by Vicious. [Skotlex] - status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER); - break; - case SC_OVERTHRUSTMAX: - //Cancels Normal Overthrust. [Skotlex] - status_change_end(bl, SC_OVERTHRUST, INVALID_TIMER); - break; - case SC_KYRIE: - //Cancels Assumptio - status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); - break; - case SC_MAGNIFICAT: - //Cancels Offertorium - status_change_end(bl, SC_OFFERTORIUM, INVALID_TIMER); - break; - case SC_OFFERTORIUM: - //Cancels Magnificat - status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER); - break; - case SC_DELUGE: - if (sc->data[SC_FOGWALL] && sc->data[SC_BLIND]) - status_change_end(bl, SC_BLIND, INVALID_TIMER); - break; - case SC_SILENCE: - if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) - status_change_end(bl, SC_GOSPEL, INVALID_TIMER); - break; - case SC_HIDING: - status_change_end(bl, SC_RG_CCONFINE_M, INVALID_TIMER); - status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER); - break; - case SC_BERSERK: - if( val3 == SC__BLOODYLUST ) - break; - if(battle_config.berserk_cancels_buffs) { - status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER); - status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); - status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER); - status_change_end(bl, SC_PARRYING, INVALID_TIMER); - status_change_end(bl, SC_AURABLADE, INVALID_TIMER); - status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER); - } - #ifdef RENEWAL - else { - status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); - } - #endif - break; - case SC_ASSUMPTIO: - status_change_end(bl, SC_KYRIE, INVALID_TIMER); - status_change_end(bl, SC_KAITE, INVALID_TIMER); - break; - case SC_KAITE: - status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); - break; - case SC_CARTBOOST: - if (sc->data[SC_DEC_AGI] || sc->data[SC_ADORAMUS]) { - //Cancel Decrease Agi, but take no further effect [Skotlex] - status_change_end(bl, SC_DEC_AGI, INVALID_TIMER); - status_change_end(bl, SC_ADORAMUS, INVALID_TIMER); - return 0; - } - break; - case SC_FUSION: - status_change_end(bl, SC_SOULLINK, INVALID_TIMER); - break; - case SC_GS_ADJUSTMENT: - status_change_end(bl, SC_GS_MADNESSCANCEL, INVALID_TIMER); - break; - case SC_GS_MADNESSCANCEL: - status_change_end(bl, SC_GS_ADJUSTMENT, INVALID_TIMER); - break; - //NPC_CHANGEUNDEAD will debuff Blessing and Agi Up - case SC_PROPERTYUNDEAD: - status_change_end(bl, SC_BLESSING, INVALID_TIMER); - status_change_end(bl, SC_INC_AGI, INVALID_TIMER); - break; - case SC_FOOD_STR: - status_change_end(bl, SC_FOOD_STR_CASH, INVALID_TIMER); - break; - case SC_FOOD_AGI: - status_change_end(bl, SC_FOOD_AGI_CASH, INVALID_TIMER); - break; - case SC_FOOD_VIT: - status_change_end(bl, SC_FOOD_VIT_CASH, INVALID_TIMER); - break; - case SC_FOOD_INT: - status_change_end(bl, SC_FOOD_INT_CASH, INVALID_TIMER); - break; - case SC_FOOD_DEX: - status_change_end(bl, SC_FOOD_DEX_CASH, INVALID_TIMER); - break; - case SC_FOOD_LUK: - status_change_end(bl, SC_FOOD_LUK_CASH, INVALID_TIMER); - break; - case SC_FOOD_STR_CASH: - status_change_end(bl, SC_FOOD_STR, INVALID_TIMER); - break; - case SC_FOOD_AGI_CASH: - status_change_end(bl, SC_FOOD_AGI, INVALID_TIMER); - break; - case SC_FOOD_VIT_CASH: - status_change_end(bl, SC_FOOD_VIT, INVALID_TIMER); - break; - case SC_FOOD_INT_CASH: - status_change_end(bl, SC_FOOD_INT, INVALID_TIMER); - break; - case SC_FOOD_DEX_CASH: - status_change_end(bl, SC_FOOD_DEX, INVALID_TIMER); - break; - case SC_FOOD_LUK_CASH: - status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER); - break; - case SC_GM_BATTLE: - status_change_end(bl, SC_GM_BATTLE2, INVALID_TIMER); - break; - case SC_GM_BATTLE2: - status_change_end(bl, SC_GM_BATTLE, INVALID_TIMER); - break; - case SC_ENDURE: - if( val4 == 1 ) - status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER); - break; - case SC_FIGHTINGSPIRIT: - case SC_OVERED_BOOST: - status_change_end(bl, type, INVALID_TIMER); // Remove previous one. - break; - case SC_MARSHOFABYSS: - status_change_end(bl, SC_INCAGI, INVALID_TIMER); - status_change_end(bl, SC_WINDWALK, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER); - break; - //Group A Status (doesn't overlap) - case SC_SWING: - case SC_SYMPHONY_LOVE: - case SC_MOONLIT_SERENADE: - case SC_RUSH_WINDMILL: - case SC_ECHOSONG: - case SC_HARMONIZE: - case SC_FRIGG_SONG: - if (type != SC_SWING) status_change_end(bl, SC_SWING, INVALID_TIMER); - if (type != SC_SYMPHONY_LOVE) status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER); - if (type != SC_MOONLIT_SERENADE) status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER); - if (type != SC_RUSH_WINDMILL) status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER); - if (type != SC_ECHOSONG) status_change_end(bl, SC_ECHOSONG, INVALID_TIMER); - if (type != SC_HARMONIZE) status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); - if (type != SC_FRIGG_SONG) status_change_end(bl, SC_FRIGG_SONG, INVALID_TIMER); - break; - //Group B Status - case SC_SIREN: - case SC_DEEP_SLEEP: - case SC_SIRCLEOFNATURE: - case SC_LERADS_DEW: - case SC_MELODYOFSINK: - case SC_BEYOND_OF_WARCRY: - case SC_UNLIMITED_HUMMING_VOICE: - case SC_GLOOMYDAY: - case SC_SONG_OF_MANA: - case SC_DANCE_WITH_WUG: - if (type != SC_SIREN) status_change_end(bl, SC_SIREN, INVALID_TIMER); - if (type != SC_DEEP_SLEEP) status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER); - if (type != SC_SIRCLEOFNATURE) status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER); - if (type != SC_LERADS_DEW) status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER); - if (type != SC_MELODYOFSINK) status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER); - if (type != SC_BEYOND_OF_WARCRY) status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER); - if (type != SC_UNLIMITED_HUMMING_VOICE) status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER); - if (type != SC_GLOOMYDAY) status_change_end(bl, SC_GLOOMYDAY, INVALID_TIMER); - if (type != SC_SONG_OF_MANA) status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER); - if (type != SC_DANCE_WITH_WUG) status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER); - break; - case SC_REFLECTSHIELD: - status_change_end(bl, SC_LG_REFLECTDAMAGE, INVALID_TIMER); - break; - case SC_LG_REFLECTDAMAGE: - status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER); - break; - case SC_SHIELDSPELL_DEF: - case SC_SHIELDSPELL_MDEF: - case SC_SHIELDSPELL_REF: - status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER); - status_change_end(bl, SC_SHIELDSPELL_DEF, INVALID_TIMER); - status_change_end(bl, SC_SHIELDSPELL_MDEF, INVALID_TIMER); - status_change_end(bl, SC_SHIELDSPELL_REF, INVALID_TIMER); - break; - case SC_GENTLETOUCH_ENERGYGAIN: - case SC_GENTLETOUCH_CHANGE: - case SC_GENTLETOUCH_REVITALIZE: - if( type != SC_GENTLETOUCH_REVITALIZE ) - status_change_end(bl, SC_GENTLETOUCH_REVITALIZE, INVALID_TIMER); - if( type != SC_GENTLETOUCH_ENERGYGAIN ) - status_change_end(bl, SC_GENTLETOUCH_ENERGYGAIN, INVALID_TIMER); - if( type != SC_GENTLETOUCH_CHANGE ) - status_change_end(bl, SC_GENTLETOUCH_CHANGE, INVALID_TIMER); - break; - case SC_INVINCIBLE: - status_change_end(bl, SC_INVINCIBLEOFF, INVALID_TIMER); - break; - case SC_INVINCIBLEOFF: - status_change_end(bl, SC_INVINCIBLE, INVALID_TIMER); - break; - case SC_MAGICPOWER: - status_change_end(bl, type, INVALID_TIMER); - break; - } + if (status->end_sc_before_start(bl, st, sc, type, undead_flag, val1, val2, val3, val4)) + return 0; //Check for overlapping fails if( (sce = sc->data[type]) ) { @@ -8463,8 +8196,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_SUMMER: case SC_HANBOK: case SC_OKTOBERFEST: - if (!vd) return 0; - //Store previous values as they could be removed. + case SC_DRESS_UP: + if (vd == NULL) + return 0; + // Store previous values as they could be removed. unit->stop_attack(bl); break; case SC_NOCHAT: @@ -8599,6 +8334,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_TURNKICK_READY: case SC_DODGE_READY: case SC_PUSH_CART: + case SC_DAILYSENDMAILCNT: tick = INFINITE_DURATION; break; @@ -9729,10 +9465,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t return 0; PER( 100 / (status_get_max_hp(bl) / hp), lv ); - status->heal(bl, (!(hp%2) ? (6-lv) *4 / 100 : -(lv*4) / 100), 0, 1); + status->heal(bl, (!(hp%2) ? (6-lv) *4 / 100 : -(lv*4) / 100), 0, STATUS_HEAL_FORCED); PER( 100 / (status_get_max_sp(bl) / sp), lv ); - status->heal(bl, 0,(!(sp%2) ? (6-lv) *3 / 100 : -(lv*3) / 100), 1); + status->heal(bl, 0,(!(sp%2) ? (6-lv) *3 / 100 : -(lv*3) / 100), STATUS_HEAL_FORCED); } #undef PER break; @@ -9853,25 +9589,25 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val3 = 25 * val1; // Move speed reduction break; default: - if (calc_flag == SCB_NONE && status->dbs->SkillChangeTable[type] == 0 && status->dbs->IconChangeTable[type] == 0) { - //Status change with no calc, no icon, and no skill associated...? - ShowError("UnknownStatusChange [%d]\n", type); + if (status->change_start_unknown_sc(src, bl, type, calc_flag, rate, val1, val2, val3, val4, tick, flag)) { return 0; } } - } else { //Special considerations when loading SC data. - switch( type ) { + } else { // Special considerations when loading SC data. + switch (type) { case SC_WEDDING: case SC_XMAS: case SC_SUMMER: case SC_HANBOK: case SC_OKTOBERFEST: - if( !vd ) break; + case SC_DRESS_UP: + if (vd == NULL) + break; clif->changelook(bl, LOOK_BASE, vd->class); - clif->changelook(bl,LOOK_WEAPON,0); - clif->changelook(bl,LOOK_SHIELD,0); - clif->changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); - clif->changelook(bl,LOOK_BODY2,0); + clif->changelook(bl, LOOK_WEAPON, 0); + clif->changelook(bl, LOOK_SHIELD, 0); + clif->changelook(bl, LOOK_CLOTHES_COLOR, vd->cloth_color); + clif->changelook(bl, LOOK_BODY2, 0); break; case SC_KAAHI: val4 = INVALID_TIMER; @@ -9880,27 +9616,247 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t } /* values that must be set regardless of SCFLAG_LOADED e.g. val_flag */ - switch(type) { + val_flag = status->get_val_flag(type); + + /* [Ind/Hercules] */ + status->change_start_display(sd, type, val1, val2, val3, val4); + + //Those that make you stop attacking/walking.... + status->change_start_stop_action(bl, type); + + // Set option as needed. + opt_flag = status->change_start_set_option(bl, sc, type, val1, val2, val3, val4); + + //On Aegis, when turning on a status change, first goes the option packet, then the sc packet. + if(opt_flag) { + clif->changeoption(bl); + if( sd && opt_flag&0x4 ) { + if (vd) + clif->changelook(bl, LOOK_BASE, vd->class); + clif->changelook(bl,LOOK_WEAPON,0); + clif->changelook(bl,LOOK_SHIELD,0); + if (vd) + clif->changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); + } + } + if (calc_flag&SCB_DYE) { + //Reset DYE color + if (vd && vd->cloth_color) { + val4 = vd->cloth_color; + clif->changelook(bl,LOOK_CLOTHES_COLOR,0); + } + calc_flag&=~SCB_DYE; + } + +#if 0 //Currently No SC's use this + if (calc_flag&SCB_BODY) { + //Reset Body Style + if (vd && vd->body_style) { + val4 = vd->body_style; + clif->changelook(bl,LOOK_BODY2,0); + } + calc_flag&=~SCB_BODY; + } +#endif + + if(!(flag&SCFLAG_NOICON) && !(flag&SCFLAG_LOADED && status->dbs->DisplayType[type])) + clif->status_change(bl,status->dbs->IconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0); + + /** + * used as temporary storage for scs with interval ticks, so that the actual duration is sent to the client first. + **/ + if( tick_time ) + tick = tick_time; + + //Don't trust the previous sce assignment, in case the SC ended somewhere between there and here. + if((sce=sc->data[type])) {// reuse old sc + if( sce->timer != INVALID_TIMER ) + timer->delete(sce->timer, status->change_timer); + } else {// new sc + ++(sc->count); + sce = sc->data[type] = ers_alloc(status->data_ers, struct status_change_entry); + } + + sce->val1 = val1; + sce->val2 = val2; + sce->val3 = val3; + sce->val4 = val4; + + if (tick >= 0) { + sce->timer = timer->add(timer->gettick() + tick, status->change_timer, bl->id, type); + sce->infinite_duration = false; + } else { + sce->timer = INVALID_TIMER; //Infinite duration + sce->infinite_duration = true; + if( sd ) + chrif->save_scdata_single(sd->status.account_id,sd->status.char_id,type,sce); + } + + if (calc_flag) + status_calc_bl(bl,calc_flag); + + if(sd && sd->pd) + pet->sc_check(sd, type); //Skotlex: Pet Status Effect Healing + + switch (type) { + case SC_BERSERK: + if (!(sce->val2)) { //don't heal if already set + status->heal(bl, st->max_hp, 0, STATUS_HEAL_FORCED); //Do not use percent_heal as this healing must override BERSERK's block. + status->set_sp(bl, 0, STATUS_HEAL_DEFAULT); //Damage all SP + } + sce->val2 = 5 * st->max_hp / 100; + break; + case SC_HLIF_CHANGE: + status_percent_heal(bl, 100, 100); + break; + case SC_RUN: + { + struct unit_data *ud = unit->bl2ud(bl); + if( ud ) + ud->state.running = unit->run(bl, NULL, SC_RUN); + } + break; + case SC_CASH_BOSS_ALARM: + if( sd ) + clif->bossmapinfo(sd->fd, map->id2boss(sce->val1), 0); // First Message + break; + case SC_MER_HP: + status_percent_heal(bl, 100, 0); // Recover Full HP + break; + case SC_MER_SP: + status_percent_heal(bl, 0, 100); // Recover Full SP + break; + case SC_PROMOTE_HEALTH_RESERCH: + status_percent_heal(bl, sce->val4, 0); + break; + case SC_ENERGY_DRINK_RESERCH: + status_percent_heal(bl, 0, sce->val4); + break; + /** + * Ranger + **/ + case SC_WUGDASH: + { + struct unit_data *ud = unit->bl2ud(bl); + if( ud ) + ud->state.running = unit->run(bl, sd, SC_WUGDASH); + } + break; + case SC_COMBOATTACK: + switch (sce->val1) { + case TK_STORMKICK: + clif->skill_nodamage(bl,bl,TK_READYSTORM,1,1); + break; + case TK_DOWNKICK: + clif->skill_nodamage(bl,bl,TK_READYDOWN,1,1); + break; + case TK_TURNKICK: + clif->skill_nodamage(bl,bl,TK_READYTURN,1,1); + break; + case TK_COUNTER: + clif->skill_nodamage(bl,bl,TK_READYCOUNTER,1,1); + break; + case MO_COMBOFINISH: + case CH_TIGERFIST: + case CH_CHAINCRUSH: + if (sd) + clif->skillinfo(sd,MO_EXTREMITYFIST, INF_SELF_SKILL); + break; + case TK_JUMPKICK: + if (sd) + clif->skillinfo(sd,TK_JUMPKICK, INF_SELF_SKILL); + break; + case MO_TRIPLEATTACK: + if (sd && pc->checkskill(sd, SR_DRAGONCOMBO) > 0) + clif->skillinfo(sd,SR_DRAGONCOMBO, INF_SELF_SKILL); + break; + case SR_FALLENEMPIRE: + if (sd){ + clif->skillinfo(sd,SR_GATEOFHELL, INF_SELF_SKILL); + clif->skillinfo(sd,SR_TIGERCANNON, INF_SELF_SKILL); + } + break; + } + break; + case SC_RAISINGDRAGON: + sce->val2 = st->max_hp / 100;// Officially tested its 1%hp drain. [Jobbie] + break; + } + + if( opt_flag&2 && sd && sd->touching_id ) + npc->touchnext_areanpc(sd,false); // run OnTouch_ on next char in range + + return 1; +} + +static bool status_change_start_unknown_sc(struct block_list *src, struct block_list *bl, enum sc_type type, int calc_flag, int rate, int val1, int val2, int val3, int val4, int tick, int flag) +{ + Assert_retr(false, type >= SC_NONE && type < SC_MAX); + if (calc_flag == SCB_NONE && status->dbs->SkillChangeTable[type] == 0 && status->dbs->IconChangeTable[type] == 0) { + //Status change with no calc, no icon, and no skill associated...? + ShowError("UnknownStatusChange [%d]\n", type); + return true; + } + return false; +} + +static void status_change_start_display(struct map_session_data *sd, enum sc_type type, int val1, int val2, int val3, int val4) +{ + Assert_retv(type >= SC_NONE && type < SC_MAX); + + if (sd && status->dbs->DisplayType[type]) { + int dval1 = 0, dval2 = 0, dval3 = 0; + switch (type) { + case SC_ALL_RIDING: + dval1 = 1; + break; + case SC_CLAN_INFO: + dval1 = val1; + dval2 = val2; + dval3 = val3; + break; + default: /* all others: just copy val1 */ + dval1 = val1; + break; + } + status->display_add(sd, type, dval1, dval2, dval3); + } +} + +/** + * Return val_flag based on sc type. + * + * @param type Status change type. + * + * @retval val_flag. + */ +static int status_get_val_flag(enum sc_type type) +{ + int val_flag = 0; + switch (type) { + case SC_CLAN_INFO: + val_flag |= 1 | 2; + break; case SC_FIGHTINGSPIRIT: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_VENOMIMPRESS: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_POISONINGWEAPON: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_WEAPONBLOCKING: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_ROLLINGCUTTER: val_flag |= 1; break; case SC_CLOAKINGEXCEED: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_HALLUCINATIONWALK: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_SUMMON1: case SC_SUMMON2: @@ -9910,34 +9866,34 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val_flag |= 1; break; case SC__SHADOWFORM: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC__INVISIBILITY: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC__ENERVATION: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC__GROOMY: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC__LAZINESS: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC__UNLUCKY: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC__WEAKNESS: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_PROPERTYWALK: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_FORCEOFVANGUARD: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_PRESTIGE: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_BANDING: val_flag |= 1; @@ -9945,56 +9901,56 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_SHIELDSPELL_DEF: case SC_SHIELDSPELL_MDEF: case SC_SHIELDSPELL_REF: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_SPELLFIST: case SC_CURSEDCIRCLE_ATKER: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_CRESCENTELBOW: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_LIGHTNINGWALK: val_flag |= 1; break; case SC_PYROTECHNIC_OPTION: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_HEATER_OPTION: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_AQUAPLAY_OPTION: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_COOLER_OPTION: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_CHILLY_AIR_OPTION: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_GUST_OPTION: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_BLAST_OPTION: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_WILD_STORM_OPTION: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_PETROLOGY_OPTION: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_CURSED_SOIL_OPTION: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_UPHEAVAL_OPTION: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_CIRCLE_OF_FIRE_OPTION: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_WATER_BARRIER: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_KYOUGAKU: val_flag |= 1; @@ -10006,91 +9962,33 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_OVERLAPEXPUP: val_flag |= 1; break; + case SC_DAILYSENDMAILCNT: + val_flag |= 1 | 2; + break; } + return val_flag; +} - /* [Ind/Hercules] */ - if( sd && status->dbs->DisplayType[type] ) { - int dval1 = 0, dval2 = 0, dval3 = 0; - switch( type ) { - case SC_ALL_RIDING: - dval1 = 1; - break; - default: /* all others: just copy val1 */ - dval1 = val1; - break; - } - status->display_add(sd,type,dval1,dval2,dval3); - } +/** + * Set new status values. + * + * @param bl Status change target bl. + * @param sc Current statuses. + * @param type Status change type. + * @param val1 Additional value (meaning depends on type). + * @param val2 Additional value (meaning depends on type). + * @param val3 Additional value (meaning depends on type). + * @param val4 Additional value (meaning depends on type). + * + * @retval option flag. + */ +static int status_change_start_set_option(struct block_list *bl, struct status_change *sc, enum sc_type type, int val1, int val2, int val3, int val4) +{ + int opt_flag = 1; - //Those that make you stop attacking/walking.... + nullpo_retr(true, bl); + nullpo_retr(true, sc); switch (type) { - case SC_VACUUM_EXTREME: - if(!map_flag_gvg(bl->m)) - unit->stop_walking(bl,1); - break; - case SC_FREEZE: - case SC_STUN: - case SC_SLEEP: - case SC_STONE: - case SC_DEEP_SLEEP: - if (sd && pc_issit(sd)) //Avoid sprite sync problems. - pc->setstand(sd); - FALLTHROUGH - case SC_TRICKDEAD: - status_change_end(bl, SC_DANCING, INVALID_TIMER); - // Cancel cast when get status [LuzZza] - if (battle_config.sc_castcancel&bl->type) - unit->skillcastcancel(bl, 0); - FALLTHROUGH - case SC_FALLENEMPIRE: - case SC_WHITEIMPRISON: - unit->stop_attack(bl); - FALLTHROUGH - case SC_STOP: - case SC_CONFUSION: - case SC_RG_CCONFINE_M: - case SC_RG_CCONFINE_S: - case SC_SPIDERWEB: - case SC_ELECTRICSHOCKER: - case SC_WUGBITE: - case SC_THORNS_TRAP: - case SC__MANHOLE: - case SC__CHAOS: - case SC_COLD: - case SC_CURSEDCIRCLE_ATKER: - case SC_CURSEDCIRCLE_TARGET: - case SC_FEAR: - case SC_MEIKYOUSISUI: - case SC_NEEDLE_OF_PARALYZE: - case SC_DEATHBOUND: - case SC_NETHERWORLD: - case SC_SV_ROOTTWIST: - unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); - break; - case SC_ANKLESNARE: - if( battle_config.skill_trap_type || !map_flag_gvg(bl->m) ) - unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); - break; - case SC_HIDING: - case SC_CLOAKING: - case SC_CLOAKINGEXCEED: - case SC_CHASEWALK: - case SC_WEIGHTOVER90: - case SC_CAMOUFLAGE: - case SC_SIREN: - case SC_ALL_RIDING: - case SC_SUHIDE: - unit->stop_attack(bl); - break; - case SC_SILENCE: - if (battle_config.sc_castcancel&bl->type) - unit->skillcastcancel(bl, 0); - break; - } - - // Set option as needed. - opt_flag = 1; - switch(type) { //OPT1 case SC_STONE: sc->opt1 = OPT1_STONEWAIT; break; case SC_FREEZE: sc->opt1 = OPT1_FREEZE; break; @@ -10168,7 +10066,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t break; #endif // 0 case SC_DANCING: - if ((val1&0xFFFF) == CG_MOONLIT) + if ((val1 & 0xFFFF) == CG_MOONLIT) sc->opt3 |= OPT3_MOONLIT; opt_flag = 0; break; @@ -10254,6 +10152,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t sc->option |= OPTION_OKTOBERFEST; opt_flag |= 0x4; break; + case SC_DRESS_UP: + sc->option |= OPTION_SUMMER2; + opt_flag |= 0x4; + break; case SC__FEINTBOMB_MASTER: sc->option |= OPTION_INVISIBLE; opt_flag |= 0x4; @@ -10261,179 +10163,508 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t default: opt_flag = 0; } + return opt_flag; +} - //On Aegis, when turning on a status change, first goes the option packet, then the sc packet. - if(opt_flag) { - clif->changeoption(bl); - if( sd && opt_flag&0x4 ) { - if (vd) - clif->changelook(bl, LOOK_BASE, vd->class); - clif->changelook(bl,LOOK_WEAPON,0); - clif->changelook(bl,LOOK_SHIELD,0); - if (vd) - clif->changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); - } - } - if (calc_flag&SCB_DYE) { - //Reset DYE color - if (vd && vd->cloth_color) { - val4 = vd->cloth_color; - clif->changelook(bl,LOOK_CLOTHES_COLOR,0); - } - calc_flag&=~SCB_DYE; - } - -#if 0 //Currently No SC's use this - if (calc_flag&SCB_BODY) { - //Reset Body Style - if (vd && vd->body_style) { - val4 = vd->body_style; - clif->changelook(bl,LOOK_BODY2,0); +/** + * Stop actions before start new sc. + * + * @param bl Status change target bl. + * @param type Status change type. + */ +static void status_change_start_stop_action(struct block_list *bl, enum sc_type type) +{ + nullpo_retv(bl); + switch (type) { + case SC_VACUUM_EXTREME: + if (!map_flag_gvg(bl->m)) + unit->stop_walking(bl,1); + break; + case SC_FREEZE: + case SC_STUN: + case SC_SLEEP: + case SC_STONE: + case SC_DEEP_SLEEP: { + struct map_session_data *sd = BL_CAST(BL_PC, bl); + if (sd && pc_issit(sd)) //Avoid sprite sync problems. + pc->setstand(sd); + FALLTHROUGH } - calc_flag&=~SCB_BODY; - } -#endif - - if(!(flag&SCFLAG_NOICON) && !(flag&SCFLAG_LOADED && status->dbs->DisplayType[type])) - clif->status_change(bl,status->dbs->IconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0); - - /** - * used as temporary storage for scs with interval ticks, so that the actual duration is sent to the client first. - **/ - if( tick_time ) - tick = tick_time; - - //Don't trust the previous sce assignment, in case the SC ended somewhere between there and here. - if((sce=sc->data[type])) {// reuse old sc - if( sce->timer != INVALID_TIMER ) - timer->delete(sce->timer, status->change_timer); - } else {// new sc - ++(sc->count); - sce = sc->data[type] = ers_alloc(status->data_ers, struct status_change_entry); - } - - sce->val1 = val1; - sce->val2 = val2; - sce->val3 = val3; - sce->val4 = val4; - - if (tick >= 0) { - sce->timer = timer->add(timer->gettick() + tick, status->change_timer, bl->id, type); - sce->infinite_duration = false; - } else { - sce->timer = INVALID_TIMER; //Infinite duration - sce->infinite_duration = true; - if( sd ) - chrif->save_scdata_single(sd->status.account_id,sd->status.char_id,type,sce); + case SC_TRICKDEAD: + status_change_end(bl, SC_DANCING, INVALID_TIMER); + // Cancel cast when get status [LuzZza] + if (battle_config.sc_castcancel&bl->type) + unit->skillcastcancel(bl, 0); + FALLTHROUGH + case SC_FALLENEMPIRE: + case SC_WHITEIMPRISON: + unit->stop_attack(bl); + FALLTHROUGH + case SC_STOP: + case SC_CONFUSION: + case SC_RG_CCONFINE_M: + case SC_RG_CCONFINE_S: + case SC_SPIDERWEB: + case SC_ELECTRICSHOCKER: + case SC_WUGBITE: + case SC_THORNS_TRAP: + case SC__MANHOLE: + case SC__CHAOS: + case SC_COLD: + case SC_CURSEDCIRCLE_ATKER: + case SC_CURSEDCIRCLE_TARGET: + case SC_FEAR: + case SC_MEIKYOUSISUI: + case SC_NEEDLE_OF_PARALYZE: + case SC_DEATHBOUND: + case SC_NETHERWORLD: + case SC_SV_ROOTTWIST: + unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); + break; + case SC_ANKLESNARE: + if (battle_config.skill_trap_type || !map_flag_gvg(bl->m)) + unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); + break; + case SC_HIDING: + case SC_CLOAKING: + case SC_CLOAKINGEXCEED: + case SC_CHASEWALK: + case SC_WEIGHTOVER90: + case SC_CAMOUFLAGE: + case SC_SIREN: + case SC_ALL_RIDING: + case SC_SUHIDE: + unit->stop_attack(bl); + break; + case SC_SILENCE: + if (battle_config.sc_castcancel & bl->type) + unit->skillcastcancel(bl, 0); + break; } +} - if (calc_flag) - status_calc_bl(bl,calc_flag); - - if(sd && sd->pd) - pet->sc_check(sd, type); //Skotlex: Pet Status Effect Healing +/** + * End sc before starting other sc. + * + * @param bl Status change target bl. + * @param st Status change data. + * @param sc Current statuses. + * @param type Status change type. + * @param undead_flag is bl undead. + * @param val1 Additional value (meaning depends on type). + * @param val2 Additional value (meaning depends on type). + * @param val3 Additional value (meaning depends on type). + * @param val4 Additional value (meaning depends on type). + * + * @retval false if no status change happened, or the other sc can be started regardless. + * @retval true if the status change was successfully applied and the other sc shouldn't be started. + */ +static bool status_end_sc_before_start(struct block_list *bl, struct status_data *st, struct status_change *sc, enum sc_type type, int undead_flag, int val1, int val2, int val3, int val4) +{ + nullpo_retr(true, bl); + nullpo_retr(true, st); + nullpo_retr(true, sc); switch (type) { - case SC_BERSERK: - if (!(sce->val2)) { //don't heal if already set - status->heal(bl, st->max_hp, 0, 1); //Do not use percent_heal as this healing must override BERSERK's block. - status->set_sp(bl, 0, 0); //Damage all SP + case SC_BLESSING: + // TODO: Blessing and Agi up should do 1 damage against players on Undead Status, even on PvM + // but cannot be plagiarized (this requires aegis investigation on packets and official behavior) [Brainstorm] + if ((undead_flag == 0 && st->race != RC_DEMON) || bl->type == BL_PC) { + bool prevent_start = false; + if (sc->data[SC_CURSE] != NULL) { + prevent_start = true; + status_change_end(bl, SC_CURSE, INVALID_TIMER); + } + if (sc->data[SC_STONE] != NULL && sc->opt1 == OPT1_STONE) { + prevent_start = true; + status_change_end(bl, SC_STONE, INVALID_TIMER); + } + if (prevent_start) + return true; } - sce->val2 = 5 * st->max_hp / 100; + if (sc->data[SC_SOULLINK] != NULL && sc->data[SC_SOULLINK]->val2 == SL_HIGH) + status_change_end(bl, SC_SOULLINK, INVALID_TIMER); break; - case SC_HLIF_CHANGE: - status_percent_heal(bl, 100, 100); + case SC_INC_AGI: + status_change_end(bl, SC_DEC_AGI, INVALID_TIMER); + if (sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH) + status_change_end(bl, SC_SOULLINK, INVALID_TIMER); break; - case SC_RUN: - { - struct unit_data *ud = unit->bl2ud(bl); - if( ud ) - ud->state.running = unit->run(bl, NULL, SC_RUN); - } + case SC_QUAGMIRE: + status_change_end(bl, SC_CONCENTRATION, INVALID_TIMER); + status_change_end(bl, SC_TRUESIGHT, INVALID_TIMER); + status_change_end(bl, SC_WINDWALK, INVALID_TIMER); + FALLTHROUGH + //Also blocks the ones below... + case SC_DEC_AGI: + case SC_ADORAMUS: + status_change_end(bl, SC_CARTBOOST, INVALID_TIMER); + //Also blocks the ones below... + FALLTHROUGH + case SC_DONTFORGETME: + status_change_end(bl, SC_INC_AGI, INVALID_TIMER); + status_change_end(bl, SC_ADRENALINE, INVALID_TIMER); + status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER); + status_change_end(bl, SC_SPEARQUICKEN, INVALID_TIMER); + status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); + status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER); + status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER); + status_change_end(bl, SC_ACCELERATION, INVALID_TIMER); break; - case SC_CASH_BOSS_ALARM: - if( sd ) - clif->bossmapinfo(sd->fd, map->id2boss(sce->val1), 0); // First Message + case SC_ONEHANDQUICKEN: + //Removes the Aspd potion effect, as reported by Vicious. [Skotlex] + status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER); break; - case SC_MER_HP: - status_percent_heal(bl, 100, 0); // Recover Full HP + case SC_OVERTHRUSTMAX: + //Cancels Normal Overthrust. [Skotlex] + status_change_end(bl, SC_OVERTHRUST, INVALID_TIMER); break; - case SC_MER_SP: - status_percent_heal(bl, 0, 100); // Recover Full SP + case SC_KYRIE: + //Cancels Assumptio + status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); break; - case SC_PROMOTE_HEALTH_RESERCH: - status_percent_heal(bl, sce->val4, 0); + case SC_MAGNIFICAT: + //Cancels Offertorium + status_change_end(bl, SC_OFFERTORIUM, INVALID_TIMER); break; - case SC_ENERGY_DRINK_RESERCH: - status_percent_heal(bl, 0, sce->val4); + case SC_OFFERTORIUM: + //Cancels Magnificat + status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER); break; - /** - * Ranger - **/ - case SC_WUGDASH: - { - struct unit_data *ud = unit->bl2ud(bl); - if( ud ) - ud->state.running = unit->run(bl, sd, SC_WUGDASH); - } + case SC_DELUGE: + if (sc->data[SC_FOGWALL] && sc->data[SC_BLIND]) + status_change_end(bl, SC_BLIND, INVALID_TIMER); break; - case SC_COMBOATTACK: - switch (sce->val1) { - case TK_STORMKICK: - clif->skill_nodamage(bl,bl,TK_READYSTORM,1,1); - break; - case TK_DOWNKICK: - clif->skill_nodamage(bl,bl,TK_READYDOWN,1,1); - break; - case TK_TURNKICK: - clif->skill_nodamage(bl,bl,TK_READYTURN,1,1); - break; - case TK_COUNTER: - clif->skill_nodamage(bl,bl,TK_READYCOUNTER,1,1); - break; - case MO_COMBOFINISH: - case CH_TIGERFIST: - case CH_CHAINCRUSH: - if (sd) - clif->skillinfo(sd,MO_EXTREMITYFIST, INF_SELF_SKILL); - break; - case TK_JUMPKICK: - if (sd) - clif->skillinfo(sd,TK_JUMPKICK, INF_SELF_SKILL); - break; - case MO_TRIPLEATTACK: - if (sd && pc->checkskill(sd, SR_DRAGONCOMBO) > 0) - clif->skillinfo(sd,SR_DRAGONCOMBO, INF_SELF_SKILL); - break; - case SR_FALLENEMPIRE: - if (sd){ - clif->skillinfo(sd,SR_GATEOFHELL, INF_SELF_SKILL); - clif->skillinfo(sd,SR_TIGERCANNON, INF_SELF_SKILL); - } + case SC_SILENCE: + if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) + status_change_end(bl, SC_GOSPEL, INVALID_TIMER); + break; + case SC_HIDING: + status_change_end(bl, SC_RG_CCONFINE_M, INVALID_TIMER); + status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER); + break; + case SC_BERSERK: + if (val3 == SC__BLOODYLUST) break; + if (battle_config.berserk_cancels_buffs) { + status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER); + status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); + status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER); + status_change_end(bl, SC_PARRYING, INVALID_TIMER); + status_change_end(bl, SC_AURABLADE, INVALID_TIMER); + status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER); + } + #ifdef RENEWAL + else { + status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); } + #endif break; - case SC_RAISINGDRAGON: - sce->val2 = st->max_hp / 100;// Officially tested its 1%hp drain. [Jobbie] + case SC_ASSUMPTIO: + status_change_end(bl, SC_KYRIE, INVALID_TIMER); + status_change_end(bl, SC_KAITE, INVALID_TIMER); + break; + case SC_KAITE: + status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); + break; + case SC_CARTBOOST: + if (sc->data[SC_DEC_AGI] || sc->data[SC_ADORAMUS]) { + //Cancel Decrease Agi, but take no further effect [Skotlex] + status_change_end(bl, SC_DEC_AGI, INVALID_TIMER); + status_change_end(bl, SC_ADORAMUS, INVALID_TIMER); + return true; + } + break; + case SC_FUSION: + status_change_end(bl, SC_SOULLINK, INVALID_TIMER); + break; + case SC_GS_ADJUSTMENT: + status_change_end(bl, SC_GS_MADNESSCANCEL, INVALID_TIMER); + break; + case SC_GS_MADNESSCANCEL: + status_change_end(bl, SC_GS_ADJUSTMENT, INVALID_TIMER); + break; + //NPC_CHANGEUNDEAD will debuff Blessing and Agi Up + case SC_PROPERTYUNDEAD: + status_change_end(bl, SC_BLESSING, INVALID_TIMER); + status_change_end(bl, SC_INC_AGI, INVALID_TIMER); + break; + case SC_FOOD_STR: + status_change_end(bl, SC_FOOD_STR, INVALID_TIMER); + break; + case SC_FOOD_AGI: + status_change_end(bl, SC_FOOD_AGI, INVALID_TIMER); + break; + case SC_FOOD_VIT: + status_change_end(bl, SC_FOOD_VIT, INVALID_TIMER); + break; + case SC_FOOD_INT: + status_change_end(bl, SC_FOOD_INT, INVALID_TIMER); + break; + case SC_FOOD_DEX: + status_change_end(bl, SC_FOOD_DEX, INVALID_TIMER); + break; + case SC_FOOD_LUK: + status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER); + break; + case SC_FOOD_STR_CASH: + status_change_end(bl, SC_FOOD_STR, INVALID_TIMER); + status_change_end(bl, SC_FOOD_STR_CASH, INVALID_TIMER); + break; + case SC_FOOD_AGI_CASH: + status_change_end(bl, SC_FOOD_AGI, INVALID_TIMER); + status_change_end(bl, SC_FOOD_AGI_CASH, INVALID_TIMER); + break; + case SC_FOOD_VIT_CASH: + status_change_end(bl, SC_FOOD_VIT, INVALID_TIMER); + status_change_end(bl, SC_FOOD_VIT_CASH, INVALID_TIMER); + break; + case SC_FOOD_INT_CASH: + status_change_end(bl, SC_FOOD_INT, INVALID_TIMER); + status_change_end(bl, SC_FOOD_INT_CASH, INVALID_TIMER); + break; + case SC_FOOD_DEX_CASH: + status_change_end(bl, SC_FOOD_DEX, INVALID_TIMER); + status_change_end(bl, SC_FOOD_DEX_CASH, INVALID_TIMER); + break; + case SC_FOOD_LUK_CASH: + status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER); + status_change_end(bl, SC_FOOD_LUK_CASH, INVALID_TIMER); + break; + case SC_GM_BATTLE: + status_change_end(bl, SC_GM_BATTLE2, INVALID_TIMER); + break; + case SC_GM_BATTLE2: + status_change_end(bl, SC_GM_BATTLE, INVALID_TIMER); + break; + case SC_ENDURE: + if (val4 == 1) + status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER); + break; + case SC_FIGHTINGSPIRIT: + case SC_OVERED_BOOST: + status_change_end(bl, type, INVALID_TIMER); // Remove previous one. + break; + case SC_MARSHOFABYSS: + status_change_end(bl, SC_INCAGI, INVALID_TIMER); + status_change_end(bl, SC_WINDWALK, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER); + break; + //Group A Status (doesn't overlap) + case SC_SWING: + case SC_SYMPHONY_LOVE: + case SC_MOONLIT_SERENADE: + case SC_RUSH_WINDMILL: + case SC_ECHOSONG: + case SC_HARMONIZE: + case SC_FRIGG_SONG: + if (type != SC_SWING) status_change_end(bl, SC_SWING, INVALID_TIMER); + if (type != SC_SYMPHONY_LOVE) status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER); + if (type != SC_MOONLIT_SERENADE) status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER); + if (type != SC_RUSH_WINDMILL) status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER); + if (type != SC_ECHOSONG) status_change_end(bl, SC_ECHOSONG, INVALID_TIMER); + if (type != SC_HARMONIZE) status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); + if (type != SC_FRIGG_SONG) status_change_end(bl, SC_FRIGG_SONG, INVALID_TIMER); + break; + //Group B Status + case SC_SIREN: + case SC_DEEP_SLEEP: + case SC_SIRCLEOFNATURE: + case SC_LERADS_DEW: + case SC_MELODYOFSINK: + case SC_BEYOND_OF_WARCRY: + case SC_UNLIMITED_HUMMING_VOICE: + case SC_GLOOMYDAY: + case SC_SONG_OF_MANA: + case SC_DANCE_WITH_WUG: + if (type != SC_SIREN) status_change_end(bl, SC_SIREN, INVALID_TIMER); + if (type != SC_DEEP_SLEEP) status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER); + if (type != SC_SIRCLEOFNATURE) status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER); + if (type != SC_LERADS_DEW) status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER); + if (type != SC_MELODYOFSINK) status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER); + if (type != SC_BEYOND_OF_WARCRY) status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER); + if (type != SC_UNLIMITED_HUMMING_VOICE) status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER); + if (type != SC_GLOOMYDAY) status_change_end(bl, SC_GLOOMYDAY, INVALID_TIMER); + if (type != SC_SONG_OF_MANA) status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER); + if (type != SC_DANCE_WITH_WUG) status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER); + break; + case SC_REFLECTSHIELD: + status_change_end(bl, SC_LG_REFLECTDAMAGE, INVALID_TIMER); + break; + case SC_LG_REFLECTDAMAGE: + status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER); + break; + case SC_SHIELDSPELL_DEF: + case SC_SHIELDSPELL_MDEF: + case SC_SHIELDSPELL_REF: + status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER); + status_change_end(bl, SC_SHIELDSPELL_DEF, INVALID_TIMER); + status_change_end(bl, SC_SHIELDSPELL_MDEF, INVALID_TIMER); + status_change_end(bl, SC_SHIELDSPELL_REF, INVALID_TIMER); + break; + case SC_GENTLETOUCH_ENERGYGAIN: + case SC_GENTLETOUCH_CHANGE: + case SC_GENTLETOUCH_REVITALIZE: + if (type != SC_GENTLETOUCH_REVITALIZE) + status_change_end(bl, SC_GENTLETOUCH_REVITALIZE, INVALID_TIMER); + if (type != SC_GENTLETOUCH_ENERGYGAIN) + status_change_end(bl, SC_GENTLETOUCH_ENERGYGAIN, INVALID_TIMER); + if (type != SC_GENTLETOUCH_CHANGE) + status_change_end(bl, SC_GENTLETOUCH_CHANGE, INVALID_TIMER); + break; + case SC_INVINCIBLE: + status_change_end(bl, SC_INVINCIBLEOFF, INVALID_TIMER); + break; + case SC_INVINCIBLEOFF: + status_change_end(bl, SC_INVINCIBLE, INVALID_TIMER); + break; + case SC_MAGICPOWER: + status_change_end(bl, type, INVALID_TIMER); break; } - if( opt_flag&2 && sd && sd->touching_id ) - npc->touchnext_areanpc(sd,false); // run OnTouch_ on next char in range + return false; +} - return 1; +/** + * Check is boss resist to given sc. + * + * @param type Status change type. + * + * @retval true if boss resist. + * @retval false if boss not resist. + */ +static bool status_is_boss_resist_sc(enum sc_type type) +{ + if (type >= SC_COMMON_MIN && type <= SC_COMMON_MAX) + return true; + switch (type) { + case SC_BLESSING: + case SC_DEC_AGI: + case SC_PROVOKE: + case SC_COMA: + case SC_GRAVITATION: + case SC_NJ_SUITON: + case SC_RICHMANKIM: + case SC_ROKISWEIL: + case SC_FOGWALL: + case SC_FROSTMISTY: + case SC_BURNING: + case SC_MARSHOFABYSS: + case SC_ADORAMUS: + case SC_NEEDLE_OF_PARALYZE: + case SC_DEEP_SLEEP: + case SC_COLD: + + // Exploit prevention - kRO Fix + case SC_PYREXIA: + case SC_DEATHHURT: + case SC_TOXIN: + case SC_PARALYSE: + case SC_VENOMBLEED: + case SC_MAGICMUSHROOM: + case SC_OBLIVIONCURSE: + case SC_LEECHESEND: + + // Ranger Effects + case SC_WUGBITE: + case SC_ELECTRICSHOCKER: + case SC_MAGNETICFIELD: + + // Masquerades + case SC__ENERVATION: + case SC__GROOMY: + case SC__LAZINESS: + case SC__UNLUCKY: + case SC__WEAKNESS: + case SC__IGNORANCE: + + // Other Effects + case SC_VACUUM_EXTREME: + case SC_NETHERWORLD: + case SC_FRESHSHRIMP: + case SC_SV_ROOTTWIST: + case SC_BITESCAR: + return true; + } + return false; +} + +/** + * Initial check for current statuses immune to given sc. + * + * @param sc Current statuses. + * @param type Status change type. + * + * @retval true if immune resist. + * @retval false if not immune resist. + */ +static bool status_is_immune_to_status(struct status_change *sc, enum sc_type type) +{ + nullpo_retr(true, sc); + if (sc->data[SC_REFRESH]) { + if (type >= SC_COMMON_MIN && type <= SC_COMMON_MAX) // Confirmed. + return true; // Immune to status ailements + switch (type) { + case SC__CHAOS: + case SC_STONE: + case SC_FROSTMISTY: + case SC_TOXIN: + case SC_PARALYSE: + case SC_VENOMBLEED: + case SC_MAGICMUSHROOM: + case SC_DEATHHURT: + case SC_PYREXIA: + case SC_OBLIVIONCURSE: + case SC_MARSHOFABYSS: + case SC_MANDRAGORA: + return true; + } + } else if (sc->data[SC_INSPIRATION]) { + if (type >= SC_COMMON_MIN && type <= SC_COMMON_MAX) + return true; // Immune to status ailements + switch (type) { + case SC__CHAOS: + case SC_STONE: + case SC_FROSTMISTY: + case SC_TOXIN: + case SC_PARALYSE: + case SC_VENOMBLEED: + case SC_MAGICMUSHROOM: + case SC_DEATHHURT: + case SC_PYREXIA: + case SC_OBLIVIONCURSE: + case SC_LEECHESEND: + case SC_SATURDAY_NIGHT_FEVER: + case SC__BODYPAINT: + case SC__ENERVATION: + case SC__GROOMY: + case SC__IGNORANCE: + case SC__LAZINESS: + case SC__UNLUCKY: + case SC__WEAKNESS: + return true; + } + } + return false; } /*========================================== -* Ending all status except those listed. -* @TODO maybe usefull for dispel instead reseting a liste there. -* type: -* 0 - PC killed -> Place here statuses that do not dispel on death. -* 1 - If for some reason status_change_end decides to still keep the status when quitting. -* 2 - Do clif -* 3 - Do not remove some permanent/time-independent effects -*------------------------------------------*/ -int status_change_clear(struct block_list* bl, int type) + * Ending all status except those listed. + * @TODO maybe usefull for dispel instead reseting a liste there. + * type: + * 0 - PC killed -> Place here statuses that do not dispel on death. + * 1 - If for some reason status_change_end decides to still keep the status when quitting. + * 2 - Do clif + * 3 - Do not remove some permanent/time-independent effects + *------------------------------------------*/ +static int status_change_clear(struct block_list *bl, int type) { struct status_change* sc; int i; @@ -10490,9 +10721,9 @@ int status_change_clear(struct block_list* bl, int type) } /*========================================== -* Special condition we want to effectuate, check before ending a status. -*------------------------------------------*/ -int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const char* file, int line) + * Special condition we want to effectuate, check before ending a status. + *------------------------------------------*/ +static int status_change_end_(struct block_list *bl, enum sc_type type, int tid, const char *file, int line) { struct map_session_data *sd; struct status_change *sc; @@ -10594,7 +10825,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const } if (begin_spurt && sce->val1 >= 7 && DIFF_TICK(timer->gettick(), starttick) <= 1000 - && (!sd || (sd->weapontype1 == 0 && sd->weapontype2 == 0)) + && (!sd || (sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST)) ) sc_start(bl, bl,SC_STRUP,100,sce->val1,skill->get_time2(status->sc2skill(type), sce->val1)); } @@ -10797,7 +11028,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const status_percent_heal(bl, 100, 0); status_change_end(bl, SC__BLOODYLUST, INVALID_TIMER); } else if(st->hp > 100 && sce->val2) //If val2 is removed, no HP penalty (dispelled?) [Skotlex] - status->set_hp(bl, 100, 0); + status->set_hp(bl, 100, STATUS_HEAL_DEFAULT); if(sc->data[SC_ENDURE] && sc->data[SC_ENDURE]->val4 == 2) { sc->data[SC_ENDURE]->val4 = 0; status_change_end(bl, SC_ENDURE, INVALID_TIMER); @@ -10849,8 +11080,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const if (tid == INVALID_TIMER) break; // "lose almost all their HP and SP" on natural expiration. - status->set_hp(bl, 10, 0); - status->set_sp(bl, 10, 0); + status->set_hp(bl, 10, STATUS_HEAL_DEFAULT); + status->set_sp(bl, 10, STATUS_HEAL_DEFAULT); break; case SC_AUTOTRADE: if (tid == INVALID_TIMER) @@ -11062,6 +11293,10 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const sc->option &= ~OPTION_OKTOBERFEST; opt_flag |= 0x4; break; + case SC_DRESS_UP: + sc->option &= ~OPTION_SUMMER2; + opt_flag |= 0x4; + break; case SC__FEINTBOMB_MASTER: sc->option &= ~OPTION_INVISIBLE; opt_flag |= 0x4; @@ -11231,7 +11466,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const return 1; } -int kaahi_heal_timer(int tid, int64 tick, int id, intptr_t data) { +static int kaahi_heal_timer(int tid, int64 tick, int id, intptr_t data) +{ struct block_list *bl; struct status_change *sc; struct status_change_entry *sce; @@ -11256,17 +11492,17 @@ int kaahi_heal_timer(int tid, int64 tick, int id, intptr_t data) { hp = st->max_hp - st->hp; if (hp > sce->val2) hp = sce->val2; - if (hp) - status->heal(bl, hp, 0, 2); + if (hp != 0) + status->heal(bl, hp, 0, STATUS_HEAL_SHOWEFFECT); sce->val4 = INVALID_TIMER; return 1; } /*========================================== -* For recusive status, like for each 5s we drop sp etc. -* Reseting the end timer. -*------------------------------------------*/ -int status_change_timer(int tid, int64 tick, int id, intptr_t data) + * For recusive status, like for each 5s we drop sp etc. + * Reseting the end timer. + *------------------------------------------*/ +static int status_change_timer(int tid, int64 tick, int id, intptr_t data) { enum sc_type type = (sc_type)data; struct block_list *bl; @@ -11388,24 +11624,26 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) break; case SC_POISON: - if(st->hp <= max(st->max_hp>>2, sce->val4)) //Stop damaging after 25% HP left. + if (st->hp <= max(st->max_hp / 4, sce->val4)) //Stop damaging after 25% HP left. break; FALLTHROUGH case SC_DPOISON: if (--(sce->val3) > 0) { - if (!sc->data[SC_SLOWPOISON]) { - if( sce->val2 && bl->type == BL_MOB ) { - struct block_list* src = map->id2bl(sce->val2); - if (src != NULL) - mob->log_damage(BL_UCAST(BL_MOB, bl), src, sce->val4); - } - map->freeblock_lock(); - status_zap(bl, sce->val4, 0); - if (sc->data[type]) { // Check if the status still last ( can be dead since then ). - sc_timer_next(1000 + tick, status->change_timer, bl->id, data ); - } - map->freeblock_unlock(); + if (sc->data[SC_SLOWPOISON] != NULL) { + sc_timer_next(1000 + tick, status->change_timer, bl->id, data); + return 0; + } + if (sce->val2 != 0 && bl->type == BL_MOB) { + struct block_list* src = map->id2bl(sce->val2); + if (src != NULL) + mob->log_damage(BL_UCAST(BL_MOB, bl), src, sce->val4); + } + map->freeblock_lock(); + status_zap(bl, sce->val4, 0); + if (sc->data[type] != NULL) { // Check if the status still last (can be dead since then). + sc_timer_next(1000 + tick, status->change_timer, bl->id, data); } + map->freeblock_unlock(); return 0; } break; @@ -11461,7 +11699,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) int hp = 0; if (st->hp < st->max_hp) hp = (sce->val1 < 0) ? (int)(sd->status.max_hp * -1 * sce->val1 / 100.) : sce->val1 ; - status->heal(bl, hp, 0, 2); + status->heal(bl, hp, 0, STATUS_HEAL_SHOWEFFECT); sc_timer_next((sce->val2 * 1000) + tick, status->change_timer, bl->id, data); return 0; } @@ -11610,7 +11848,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) break; case SC_ABUNDANCE: if(--(sce->val4) > 0) { - status->heal(bl,0,60,0); + status->heal(bl, 0, 60, STATUS_HEAL_DEFAULT); sc_timer_next(10000+tick, status->change_timer, bl->id, data); } break; @@ -11726,7 +11964,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) heal = ~heal + 1; map->freeblock_lock(); - status->heal(bl, heal, 0, 2); + status->heal(bl, heal, 0, STATUS_HEAL_SHOWEFFECT); if( sc->data[type] ) { sc_timer_next(5000 + tick, status->change_timer, bl->id, data); } @@ -11849,7 +12087,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) if ( sc->data[type] ) { sc_timer_next(1000 + tick, status->change_timer, bl->id, data); } - status->heal(src, damage*(5 + 5 * sce->val1)/100, 0, 0); // 5 + 5% per level + status->heal(src, damage*(5 + 5 * sce->val1)/100, 0, STATUS_HEAL_DEFAULT); // 5 + 5% per level map->freeblock_unlock(); return 0; } @@ -11866,7 +12104,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) case SC_DEEP_SLEEP: if( --(sce->val4) >= 0 ) {// Recovers 3% of the player's MaxHP/MaxSP every 2 seconds. - status->heal(bl, st->max_hp * 3 / 100, st->max_sp * 3 / 100, 2); + status->heal(bl, st->max_hp * 3 / 100, st->max_sp * 3 / 100, STATUS_HEAL_SHOWEFFECT); sc_timer_next(2000 + tick, status->change_timer, bl->id, data); return 0; } @@ -11876,7 +12114,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) if( --(sce->val4) >= 0 ) { if( !status->charge(bl,0,sce->val3) ) break; - status->heal(bl, sce->val2, 0, 1); + status->heal(bl, sce->val2, 0, STATUS_HEAL_FORCED); sc_timer_next(1000 + tick, status->change_timer, bl->id, data); return 0; } @@ -11884,7 +12122,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) case SC_SONG_OF_MANA: if( --(sce->val4) >= 0 ) { - status->heal(bl,0,sce->val3,3); + status->heal(bl, 0, sce->val3, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT); sc_timer_next(5000 + tick, status->change_timer, bl->id, data); return 0; } @@ -12078,7 +12316,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) return 0; case SC_MEIKYOUSISUI: if( --(sce->val4) > 0 ) { - status->heal(bl, st->max_hp * (sce->val1+1) / 100, st->max_sp * sce->val1 / 100, 0); + status->heal(bl, st->max_hp * (sce->val1+1) / 100, st->max_sp * sce->val1 / 100, STATUS_HEAL_DEFAULT); sc_timer_next(1000 + tick, status->change_timer, bl->id, data); return 0; } @@ -12114,7 +12352,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) break; case SC_FRIGG_SONG: if( --(sce->val4) > 0 ) { - status->heal(bl, sce->val3, 0, 0); + status->heal(bl, sce->val3, 0, STATUS_HEAL_DEFAULT); sc_timer_next(1000 + tick, status->change_timer, bl->id, data); return 0; } @@ -12140,9 +12378,9 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) } /*========================================== -* Foreach iteration of repetitive status -*------------------------------------------*/ -int status_change_timer_sub(struct block_list* bl, va_list ap) + * Foreach iteration of repetitive status + *------------------------------------------*/ +static int status_change_timer_sub(struct block_list *bl, va_list ap) { struct status_change* tsc; @@ -12218,10 +12456,17 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) return 0; } -int status_get_total_def(struct block_list *src) { return status->get_status_data(src)->def2 + (short)status->get_def(src); } -int status_get_total_mdef(struct block_list *src) { return status->get_status_data(src)->mdef2 + (short)status_get_mdef(src); } +static int status_get_total_def(struct block_list *src) +{ + return status->get_status_data(src)->def2 + (short)status->get_def(src); +} + +static int status_get_total_mdef(struct block_list *src) +{ + return status->get_status_data(src)->mdef2 + (short)status_get_mdef(src); +} -int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int flag) +static int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int flag) { #ifdef RENEWAL int min = 0, max = 0; @@ -12284,13 +12529,13 @@ int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int fl } /** -* Get bl's matk_max and matk_min values depending on flag -* @param flag -* 0 - Get MATK -* 1 - Get MATK w/o SC bonuses -* 3 - Get MATK w/o EATK & SC bonuses -**/ -void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_max, unsigned short *matk_min) + * Get bl's matk_max and matk_min values depending on flag + * @param flag + * 0 - Get MATK + * 1 - Get MATK w/o SC bonuses + * 3 - Get MATK w/o EATK & SC bonuses + */ +static void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_max, unsigned short *matk_min) { struct status_data *st; struct status_change *sc; @@ -12402,9 +12647,9 @@ void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_m #undef status_get_homluk /** -* Gets a random matk value depending on min matk and max matk -**/ -unsigned short status_get_rand_matk(unsigned short matk_max, unsigned short matk_min) + * Gets a random matk value depending on min matk and max matk + */ +static unsigned short status_get_rand_matk(unsigned short matk_max, unsigned short matk_min) { if ( matk_max > matk_min ) return matk_min + rnd() % (matk_max - matk_min); @@ -12413,17 +12658,17 @@ unsigned short status_get_rand_matk(unsigned short matk_max, unsigned short matk } /** -* Get bl's matk value depending on flag -* @param flag [malufett] -* 1 - Get MATK w/o SC bonuses -* 2 - Get modified MATK -* 3 - Get MATK w/o eATK & SC bonuses -* @retval 1 failure -* @retval MATK success -* -* Shouldn't change _any_ value! [Panikon] -**/ -int status_get_matk(struct block_list *bl, int flag) + * Get bl's matk value depending on flag + * @param flag [malufett] + * 1 - Get MATK w/o SC bonuses + * 2 - Get modified MATK + * 3 - Get MATK w/o eATK & SC bonuses + * @retval 1 failure + * @retval MATK success + * + * Shouldn't change _any_ value! [Panikon] + */ +static int status_get_matk(struct block_list *bl, int flag) { struct status_data *st; unsigned short matk_max, matk_min; @@ -12450,9 +12695,9 @@ int status_get_matk(struct block_list *bl, int flag) } /** -* Updates bl's MATK values -**/ -void status_update_matk(struct block_list *bl) + * Updates bl's MATK values + */ +static void status_update_matk(struct block_list *bl) { struct status_data *st; struct status_change *sc; @@ -12477,11 +12722,11 @@ void status_update_matk(struct block_list *bl) } /*========================================== -* Clears buffs/debuffs of a character. -* type&1 -> buffs, type&2 -> debuffs -* type&4 -> especific debuffs(implemented with refresh) -*------------------------------------------*/ -int status_change_clear_buffs (struct block_list* bl, int type) + * Clears buffs/debuffs of a character. + * type&1 -> buffs, type&2 -> debuffs + * type&4 -> especific debuffs(implemented with refresh) + *------------------------------------------*/ +static int status_change_clear_buffs(struct block_list *bl, int type) { int i; struct status_change *sc= status->get_sc(bl); @@ -12543,7 +12788,7 @@ int status_change_clear_buffs (struct block_list* bl, int type) return 0; } -int status_change_spread(struct block_list *src, struct block_list *bl) +static int status_change_spread(struct block_list *src, struct block_list *bl) { int i, flag = 0; struct status_change *sc = status->get_sc(src); @@ -12634,7 +12879,7 @@ int status_change_spread(struct block_list *src, struct block_list *bl) } //Natural regen related stuff. -int status_natural_heal(struct block_list* bl, va_list args) +static int status_natural_heal(struct block_list *bl, va_list args) { struct regen_data *regen; struct status_data *st; @@ -12689,7 +12934,7 @@ int status_natural_heal(struct block_list* bl, va_list args) sregen->tick.hp += val; while(sregen->tick.hp >= (unsigned int)battle_config.natural_heal_skill_interval) { sregen->tick.hp -= battle_config.natural_heal_skill_interval; - if(status->heal(bl, sregen->hp, 0, 3) < sregen->hp) { + if (status->heal(bl, sregen->hp, 0, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT) < sregen->hp) { //Full flag&=~(RGN_HP|RGN_SHP); break; @@ -12704,7 +12949,7 @@ int status_natural_heal(struct block_list* bl, va_list args) sregen->tick.sp += val; while(sregen->tick.sp >= (unsigned int)battle_config.natural_heal_skill_interval) { sregen->tick.sp -= battle_config.natural_heal_skill_interval; - if(status->heal(bl, 0, sregen->sp, 3) < sregen->sp) { + if (status->heal(bl, 0, sregen->sp, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT) < sregen->sp) { //Full flag&=~(RGN_SP|RGN_SSP); break; @@ -12753,7 +12998,7 @@ int status_natural_heal(struct block_list* bl, va_list args) val += regen->hp; regen->tick.hp -= battle_config.natural_healhp_interval; } while(regen->tick.hp >= (unsigned int)battle_config.natural_healhp_interval); - if (status->heal(bl, val, 0, 1) < val) + if (status->heal(bl, val, 0, STATUS_HEAL_FORCED) < val) flag&=~RGN_SHP; //full. } } @@ -12772,7 +13017,7 @@ int status_natural_heal(struct block_list* bl, va_list args) val += regen->sp; regen->tick.sp -= battle_config.natural_healsp_interval; } while(regen->tick.sp >= (unsigned int)battle_config.natural_healsp_interval); - if (status->heal(bl, 0, val, 1) < val) + if (status->heal(bl, 0, val, STATUS_HEAL_FORCED) < val) flag&=~RGN_SSP; //full. } } @@ -12789,7 +13034,7 @@ int status_natural_heal(struct block_list* bl, va_list args) while(sregen->tick.hp >= (unsigned int)battle_config.natural_heal_skill_interval) { sregen->tick.hp -= battle_config.natural_heal_skill_interval; - if(status->heal(bl, sregen->hp, 0, 3) < sregen->hp) + if (status->heal(bl, sregen->hp, 0, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT) < sregen->hp) break; //Full } } @@ -12814,7 +13059,7 @@ int status_natural_heal(struct block_list* bl, va_list args) } } sregen->tick.sp -= battle_config.natural_heal_skill_interval; - if(status->heal(bl, 0, val, 3) < val) + if (status->heal(bl, 0, val, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT) < val) break; //Full } } @@ -12822,7 +13067,7 @@ int status_natural_heal(struct block_list* bl, va_list args) } //Natural heal main timer. -int status_natural_heal_timer(int tid, int64 tick, int id, intptr_t data) +static int status_natural_heal_timer(int tid, int64 tick, int id, intptr_t data) { // This difference is always positive and lower than UINT_MAX (~24 days) status->natural_heal_diff_tick = (unsigned int)cap_value(DIFF_TICK(tick,status->natural_heal_prev_tick), 0, UINT_MAX); @@ -12832,21 +13077,25 @@ int status_natural_heal_timer(int tid, int64 tick, int id, intptr_t data) } /** -* Get the chance to upgrade a piece of equipment. -* @param wlv The weapon type of the item to refine (see see enum refine_type) -* @param refine The target refine level -* @return The chance to refine the item, in percent (0~100) -**/ -int status_get_refine_chance(enum refine_type wlv, int refine) + * Get the chance to upgrade a piece of equipment. + * @param wlv The weapon type of the item to refine (see see enum refine_type) + * @param refine The target refine level + * @return The chance to refine the item, in percent (0~100) + */ +static int status_get_refine_chance(enum refine_type wlv, int refine, enum refine_chance_type type) { Assert_ret((int)wlv >= REFINE_TYPE_ARMOR && wlv < REFINE_TYPE_MAX); - if ( refine < 0 || refine >= MAX_REFINE) - return 0; - return status->dbs->refine_info[wlv].chance[refine]; + if (refine < 0 || refine >= MAX_REFINE) + return 0; + + if (type >= REFINE_CHANCE_TYPE_MAX) + return 0; + + return status->dbs->refine_info[wlv].chance[type][refine]; } -int status_get_sc_type(sc_type type) +static int status_get_sc_type(sc_type type) { if( type <= SC_NONE || type >= SC_MAX ) @@ -12855,10 +13104,11 @@ int status_get_sc_type(sc_type type) return status->dbs->sc_conf[type]; } -void status_read_job_db_sub(int idx, const char *name, struct config_setting_t *jdb) +static void status_read_job_db_sub(int idx, const char *name, struct config_setting_t *jdb) { struct config_setting_t *temp = NULL; int i32 = 0; + const char *str = NULL; struct { const char *name; @@ -12893,6 +13143,38 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t * #endif }; + /** + * @field BaseExpGroup must be read before any other that deal with exp tables. + */ + if (libconfig->setting_lookup_string(jdb, "BaseExpGroup", &str) != 0) { + int i = 0; + ARR_FIND(0, VECTOR_LENGTH(pc->class_exp_groups[CLASS_EXP_TABLE_BASE]), i, strcmp(str, VECTOR_INDEX(pc->class_exp_groups[CLASS_EXP_TABLE_BASE], i).name) == 0); + if (i == VECTOR_LENGTH(pc->class_exp_groups[CLASS_EXP_TABLE_BASE])) { + ShowError("status_read_job_db: Unknown Base Exp Group '%s' provided for entry '%s'\n", str, name); + } else { + pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE] = &VECTOR_INDEX(pc->class_exp_groups[CLASS_EXP_TABLE_BASE], i); + } + } else { + ShowError("status_read_job_db: BaseExpGroup setting not found for entry '%s', skipping..\n", name); + return; + } + + /** + * @field JobExpGroup must be read before any other that deal with exp tables. + */ + if (libconfig->setting_lookup_string(jdb, "JobExpGroup", &str) != 0) { + int i = 0; + ARR_FIND(0, VECTOR_LENGTH(pc->class_exp_groups[CLASS_EXP_TABLE_JOB]), i, strcmp(str, VECTOR_INDEX(pc->class_exp_groups[CLASS_EXP_TABLE_JOB], i).name) == 0); + if (i == VECTOR_LENGTH(pc->class_exp_groups[CLASS_EXP_TABLE_JOB])) { + ShowError("status_read_job_db: Unknown Job Exp Group '%s' provided for entry '%s'\n", str, name); + } else { + pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_JOB] = &VECTOR_INDEX(pc->class_exp_groups[CLASS_EXP_TABLE_JOB], i); + } + } else { + ShowError("status_read_job_db: JobExpGroup setting not found for entry '%s', skipping..\n", name); + return; + } + if ((temp = libconfig->setting_get_member(jdb, "Inherit"))) { int nidx = 0; const char *iname; @@ -12917,7 +13199,7 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t * } else { avg_increment = 5; } - for ( ; i <= pc->max_level[idx][0]; i++) { + for ( ; i <= pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE]->max_level; i++) { status->dbs->HP_table[idx][i] = min(base + avg_increment * i, battle_config.max_hp); } @@ -12932,7 +13214,7 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t * } else { avg_increment = 1; } - for ( ; i <= pc->max_level[idx][0]; i++) { + for ( ; i <= pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE]->max_level; i++) { status->dbs->SP_table[idx][i] = min(base + avg_increment * i, battle_config.max_sp); } } @@ -12958,7 +13240,7 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t * } else { avg_increment = 5; } - for ( ; i <= pc->max_level[idx][0]; i++) { + for ( ; i <= pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE]->max_level; i++) { status->dbs->HP_table[idx][i] = min(base + avg_increment * i, battle_config.max_hp); } } @@ -12984,7 +13266,7 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t * } else { avg_increment = 1; } - for ( ; i <= pc->max_level[idx][0]; i++) { + for ( ; i <= pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE]->max_level; i++) { status->dbs->SP_table[idx][i] = min(base + avg_increment * i, battle_config.max_sp); } } @@ -13026,7 +13308,7 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t * } else { avg_increment = 5; } - for (++level; level <= pc->max_level[idx][0]; ++level) { /* limit only to possible maximum level of the given class */ + for (++level; level <= pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE]->max_level; ++level) { /* limit only to possible maximum level of the given class */ status->dbs->HP_table[idx][level] = min(base + avg_increment * level, battle_config.max_hp); /* some are still empty? then let's use the average increase */ } } @@ -13046,20 +13328,21 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t * } else { avg_increment = 1; } - for (++level; level <= pc->max_level[idx][0]; level++ ) { + for (++level; level <= pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE]->max_level; level++) { status->dbs->SP_table[idx][level] = min(base + avg_increment * level, battle_config.max_sp); } } } +/* [malufett/Hercules] */ /*------------------------------------------ -* DB reading. -* job_db.conf - weight, hp, sp, aspd -* job_db2.txt - job level stat bonuses -* size_fix.txt - size adjustment table for weapons -* refine_db.txt - refining data table -*------------------------------------------*/ -void status_read_job_db(void) /* [malufett/Hercules] */ + * DB reading. + * job_db.conf - weight, hp, sp, aspd + * job_db2.txt - job level stat bonuses + * size_fix.txt - size adjustment table for weapons + * refine_db.txt - refining data table + *------------------------------------------*/ +static void status_read_job_db(void) { int i = 0; struct config_t job_db_conf; @@ -13073,7 +13356,7 @@ void status_read_job_db(void) /* [malufett/Hercules] */ if (!libconfig->load_file(&job_db_conf, config_filename)) return; - while ( (jdb = libconfig->setting_get_elem(job_db_conf.root, i++)) ) { + while ((jdb = libconfig->setting_get_elem(job_db_conf.root, i++))) { int class, idx; const char *name = config_setting_name(jdb); @@ -13085,11 +13368,12 @@ void status_read_job_db(void) /* [malufett/Hercules] */ idx = pc->class2idx(class); status->read_job_db_sub(idx, name, jdb); } + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", i, config_filename); libconfig->destroy(&job_db_conf); } -bool status_readdb_job2(char* fields[], int columns, int current) +static bool status_readdb_job2(char *fields[], int columns, int current) { int idx, class, i; @@ -13109,7 +13393,7 @@ bool status_readdb_job2(char* fields[], int columns, int current) return true; } -bool status_readdb_sizefix(char* fields[], int columns, int current) +static bool status_readdb_sizefix(char *fields[], int columns, int current) { unsigned int i; @@ -13133,7 +13417,7 @@ bool status_readdb_sizefix(char* fields[], int columns, int current) * validation errors. * @return # of the validated entry, or 0 in case of failure. */ -int status_readdb_refine_libconfig_sub(struct config_setting_t *r, const char *name, const char *source) +static int status_readdb_refine_libconfig_sub(struct config_setting_t *r, const char *name, const char *source) { struct config_setting_t *rate = NULL; int type = REFINE_TYPE_ARMOR, bonus_per_level = 0, rnd_bonus_v = 0, rnd_bonus_lv = 0; @@ -13168,54 +13452,84 @@ int status_readdb_refine_libconfig_sub(struct config_setting_t *r, const char *n if ((rate=libconfig->setting_get_member(r, "Rates")) != NULL && config_setting_is_group(rate)) { struct config_setting_t *t = NULL; bool duplicate[MAX_REFINE]; - int bonus[MAX_REFINE], rnd_bonus[MAX_REFINE], chance[MAX_REFINE]; - int i; + int bonus[MAX_REFINE], rnd_bonus[MAX_REFINE]; + int chance[REFINE_CHANCE_TYPE_MAX][MAX_REFINE]; + int i, j; + memset(&duplicate, 0, sizeof(duplicate)); memset(&bonus, 0, sizeof(bonus)); memset(&rnd_bonus, 0, sizeof(rnd_bonus)); - for (i = 0; i < MAX_REFINE; i++) { - chance[i] = 100; - } + for (i = 0; i < REFINE_CHANCE_TYPE_MAX; i++) + for (j = 0; j < MAX_REFINE; j++) + chance[i][j] = 100; // default value for all rates. + i = 0; + j = 0; while ((t = libconfig->setting_get_elem(rate,i++)) != NULL && config_setting_is_group(t)) { int level = 0, i32; char *rlvl = config_setting_name(t); memset(&lv, 0, sizeof(lv)); - if (!strspn(&rlvl[strlen(rlvl)-1], "0123456789") || (level = atoi(strncpy(lv, rlvl+2, 3))) <= 0) { + + if (!strspn(&rlvl[strlen(rlvl) - 1], "0123456789") || (level = atoi(strncpy(lv, rlvl + 2, 3))) <= 0) { ShowError("status_readdb_refine_libconfig_sub: Invalid refine level format '%s' for entry %s in \"%s\"... skipping.\n", rlvl, name, source); continue; } + if (level <= 0 || level > MAX_REFINE) { ShowError("status_readdb_refine_libconfig_sub: Out of range refine level '%s' for entry %s in \"%s\"... skipping.\n", rlvl, name, source); continue; } + level--; + if (duplicate[level]) { ShowWarning("status_readdb_refine_libconfig_sub: duplicate rate '%s' for entry %s in \"%s\", overwriting previous entry...\n", rlvl, name, source); } else { duplicate[level] = true; } - if (libconfig->setting_lookup_int(t, "Chance", &i32)) - chance[level] = i32; + + if (libconfig->setting_lookup_int(t, "NormalChance", &i32) != 0) + chance[REFINE_CHANCE_TYPE_NORMAL][level] = i32; + else + chance[REFINE_CHANCE_TYPE_NORMAL][level] = 100; + + if (libconfig->setting_lookup_int(t, "EnrichedChance", &i32) != 0) + chance[REFINE_CHANCE_TYPE_ENRICHED][level] = i32; + else + chance[REFINE_CHANCE_TYPE_ENRICHED][level] = level > 10 ? 0 : 100; // enriched ores up to +10 only. + + if (libconfig->setting_lookup_int(t, "EventNormalChance", &i32) != 0) + chance[REFINE_CHANCE_TYPE_E_NORMAL][level] = i32; else - chance[level] = 100; - if (libconfig->setting_lookup_int(t, "Bonus", &i32)) + chance[REFINE_CHANCE_TYPE_E_NORMAL][level] = 100; + + if (libconfig->setting_lookup_int(t, "EventEnrichedChance", &i32) != 0) + chance[REFINE_CHANCE_TYPE_E_ENRICHED][level] = i32; + else + chance[REFINE_CHANCE_TYPE_E_ENRICHED][level] = level > 10 ? 0 : 100; // enriched ores up to +10 only. + + if (libconfig->setting_lookup_int(t, "Bonus", &i32) != 0) bonus[level] += i32; + if (level >= rnd_bonus_lv - 1) rnd_bonus[level] = rnd_bonus_v * (level - rnd_bonus_lv + 2); } for (i = 0; i < MAX_REFINE; i++) { - status->dbs->refine_info[type].chance[i] = chance[i]; + status->dbs->refine_info[type].chance[REFINE_CHANCE_TYPE_NORMAL][i] = chance[REFINE_CHANCE_TYPE_NORMAL][i]; + status->dbs->refine_info[type].chance[REFINE_CHANCE_TYPE_E_NORMAL][i] = chance[REFINE_CHANCE_TYPE_E_NORMAL][i]; + status->dbs->refine_info[type].chance[REFINE_CHANCE_TYPE_ENRICHED][i] = chance[REFINE_CHANCE_TYPE_ENRICHED][i]; + status->dbs->refine_info[type].chance[REFINE_CHANCE_TYPE_E_ENRICHED][i] = chance[REFINE_CHANCE_TYPE_E_ENRICHED][i]; status->dbs->refine_info[type].randombonus_max[i] = rnd_bonus[i]; - bonus[i] += bonus_per_level + (i > 0 ? bonus[i-1] : 0); + bonus[i] += bonus_per_level + (i > 0 ? bonus[i - 1] : 0); status->dbs->refine_info[type].bonus[i] = bonus[i]; } } else { ShowWarning("status_readdb_refine_libconfig_sub: Missing refine rates for entry '%s' in \"%s\", skipping.\n", name, source); return 0; } - return type+1; + + return type + 1; } /** @@ -13224,7 +13538,7 @@ int status_readdb_refine_libconfig_sub(struct config_setting_t *r, const char *n * @param *filename File name, relative to the database path. * @return The number of found entries. */ -int status_readdb_refine_libconfig(const char *filename) +static int status_readdb_refine_libconfig(const char *filename) { bool duplicate[REFINE_TYPE_MAX]; struct config_t refine_db_conf; @@ -13232,7 +13546,7 @@ int status_readdb_refine_libconfig(const char *filename) char filepath[256]; int i = 0, count = 0; - sprintf(filepath, "%s/%s", map->db_path, filename); + safesnprintf(filepath, sizeof(filepath), "%s/%s", map->db_path, filename); if (!libconfig->load_file(&refine_db_conf, filepath)) return 0; @@ -13256,7 +13570,7 @@ int status_readdb_refine_libconfig(const char *filename) return count; } -bool status_readdb_scconfig(char* fields[], int columns, int current) +static bool status_readdb_scconfig(char *fields[], int columns, int current) { int val = 0; char* type = fields[0]; @@ -13282,7 +13596,7 @@ bool status_readdb_scconfig(char* fields[], int columns, int current) * size_fixe.txt * refine_db.txt **/ -int status_readdb(void) +static int status_readdb(void) { int i, j; @@ -13309,15 +13623,6 @@ int status_readdb(void) for(j = 0; j < MAX_SINGLE_WEAPON_TYPE; j++) status->dbs->atkmods[i][j] = 100; - // refine_db.txt - for(i=0;i<ARRAYLENGTH(status->dbs->refine_info);i++) { - for(j=0;j<MAX_REFINE; j++) { - status->dbs->refine_info[i].chance[j] = 100; - status->dbs->refine_info[i].bonus[j] = 0; - status->dbs->refine_info[i].randombonus_max[j] = 0; - } - } - // read databases // sv->readdb(map->db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, status->readdb_job2); @@ -13326,13 +13631,15 @@ int status_readdb(void) sv->readdb(map->db_path, "sc_config.txt", ',', 2, 2, SC_MAX, status->readdb_scconfig); status->read_job_db(); + pc->validate_levels(); + return 0; } /*========================================== -* Status db init and destroy. -*------------------------------------------*/ -int do_init_status(bool minimal) + * Status db init and destroy. + *------------------------------------------*/ +static int do_init_status(bool minimal) { if (minimal) return 0; @@ -13349,16 +13656,16 @@ int do_init_status(bool minimal) return 0; } -void do_final_status(void) +static void do_final_status(void) { ers_destroy(status->data_ers); } /*===================================== -* Default Functions : status.h -* Generated by HerculesInterfaceMaker -* created by Susu -*-------------------------------------*/ + * Default Functions : status.h + * Generated by HerculesInterfaceMaker + * created by Susu + *-------------------------------------*/ void status_defaults(void) { status = &status_s; @@ -13429,11 +13736,18 @@ void status_defaults(void) status->change_clear = status_change_clear; status->change_clear_buffs = status_change_clear_buffs; + status->is_immune_to_status = status_is_immune_to_status; + status->is_boss_resist_sc = status_is_boss_resist_sc; + status->end_sc_before_start = status_end_sc_before_start; + status->change_start_stop_action = status_change_start_stop_action; + status->change_start_set_option = status_change_start_set_option; + status->get_val_flag = status_get_val_flag; status->calc_bl_ = status_calc_bl_; status->calc_mob_ = status_calc_mob_; status->calc_pet_ = status_calc_pet_; status->calc_pc_ = status_calc_pc_; status->calc_pc_additional = status_calc_pc_additional; + status->calc_pc_recover_hp = status_calc_pc_recover_hp; status->calc_homunculus_ = status_calc_homunculus_; status->calc_mercenary_ = status_calc_mercenary_; status->calc_elemental_ = status_calc_elemental_; @@ -13470,6 +13784,8 @@ void status_defaults(void) status->base_atk = status_base_atk; status->get_base_maxhp = status_get_base_maxhp; status->get_base_maxsp = status_get_base_maxsp; + status->get_restart_hp = status_get_restart_hp; + status->get_restart_sp = status_get_restart_sp; status->calc_npc_ = status_calc_npc_; status->calc_str = status_calc_str; status->calc_agi = status_calc_agi; @@ -13496,6 +13812,8 @@ void status_defaults(void) status->calc_ematk = status_calc_ematk; status->calc_bl_main = status_calc_bl_main; status->display_add = status_display_add; + status->change_start_display = status_change_start_display; + status->change_start_unknown_sc = status_change_start_unknown_sc; status->display_remove = status_display_remove; status->natural_heal = status_natural_heal; status->natural_heal_timer = status_natural_heal_timer; @@ -13508,8 +13826,6 @@ void status_defaults(void) status->read_job_db_sub = status_read_job_db_sub; status->set_sc = status_set_sc; status->copy = status_copy; -#ifndef RENEWAL status->base_matk_min = status_base_matk_min; -#endif // RENEWAL status->base_matk_max = status_base_matk_max; } |