diff options
Diffstat (limited to 'src/map/status.c')
-rw-r--r-- | src/map/status.c | 561 |
1 files changed, 511 insertions, 50 deletions
diff --git a/src/map/status.c b/src/map/status.c index 4d798b606..589acff5c 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -696,6 +696,7 @@ static void initChangeTables(void) status->set_sc( WM_BEYOND_OF_WARCRY , SC_BEYOND_OF_WARCRY , SCB_STR|SCB_CRI|SCB_MAXHP ); status->set_sc( WM_UNLIMITED_HUMMING_VOICE, SC_UNLIMITED_HUMMING_VOICE, SCB_NONE ); status->set_sc( WM_FRIGG_SONG , SC_FRIGG_SONG , SCB_MAXHP ); + status->set_sc( WM_SEVERE_RAINSTORM , SC_NO_SWITCH_EQUIP , SCB_NONE ); /** * Sorcerer @@ -865,6 +866,10 @@ static void initChangeTables(void) status->dbs->ChangeFlagTable[SC_WEDDING] |= SCB_SPEED; status->dbs->ChangeFlagTable[SC_ARMORPROPERTY] |= SCB_ALL; status->dbs->ChangeFlagTable[SC_ARMOR_RESIST] |= SCB_ALL; + status->dbs->ChangeFlagTable[SC_RESIST_PROPERTY_WATER] |= SCB_ALL; + status->dbs->ChangeFlagTable[SC_RESIST_PROPERTY_GROUND] |= SCB_ALL; + status->dbs->ChangeFlagTable[SC_RESIST_PROPERTY_FIRE] |= SCB_ALL; + status->dbs->ChangeFlagTable[SC_RESIST_PROPERTY_WIND] |= SCB_ALL; status->dbs->ChangeFlagTable[SC_ATKER_BLOOD] |= SCB_ALL; status->dbs->ChangeFlagTable[SC_WALKSPEED] |= SCB_SPEED; status->dbs->ChangeFlagTable[SC_TARGET_BLOOD] |= SCB_ALL; @@ -884,6 +889,13 @@ static void initChangeTables(void) status->dbs->ChangeFlagTable[SC_PHI_DEMON] |= SCB_ALL; status->dbs->ChangeFlagTable[SC_MAGIC_CANDY] |= SCB_MATK | SCB_ALL; status->dbs->ChangeFlagTable[SC_MYSTICPOWDER] |= SCB_FLEE | SCB_LUK; + status->dbs->ChangeFlagTable[SC_POPECOOKIE] |= SCB_BASE | SCB_BATK | SCB_MATK; + status->dbs->ChangeFlagTable[SC_VITALIZE_POTION] |= SCB_BATK | SCB_MATK; + status->dbs->ChangeFlagTable[SC_SKF_MATK] |= SCB_MATK; + status->dbs->ChangeFlagTable[SC_SKF_ATK] |= SCB_BATK; + status->dbs->ChangeFlagTable[SC_SKF_ASPD] |= SCB_ASPD; + status->dbs->ChangeFlagTable[SC_SKF_CAST] |= SCB_NONE; + status->dbs->ChangeFlagTable[SC_ALMIGHTY] |= SCB_BATK | SCB_MATK; // Cash Items status->dbs->ChangeFlagTable[SC_FOOD_STR_CASH] |= SCB_STR; @@ -1189,7 +1201,7 @@ static int status_damage(struct block_list *src, struct block_list *target, int6 if ((sce=sc->data[SC_GRAVITATION]) && sce->val3 == BCT_SELF) { struct skill_unit_group* sg = skill->id2group(sce->val4); if (sg) { - skill->del_unitgroup(sg, ALC_MARK); + skill->del_unitgroup(sg); sce->val4 = 0; status_change_end(target, SC_GRAVITATION, INVALID_TIMER); } @@ -1584,7 +1596,7 @@ static int status_check_skilluse(struct block_list *src, struct block_list *targ } if( skill_id ) { - if (src != NULL && (sd == NULL || sd->skillitem == 0)) { + if (src != NULL && (sd == NULL || sd->auto_cast_current.type != AUTOCAST_ITEM)) { // Items that cast skills using 'itemskill' will not be handled by map_zone_db. int i; @@ -1628,7 +1640,7 @@ static int status_check_skilluse(struct block_list *src, struct block_list *targ if (src != NULL && map->getcell(src->m, src, src->x, src->y, CELL_CHKLANDPROTECTOR) && !(st->mode&MD_BOSS) - && (src->type != BL_PC || sd->skillitem != skill_id)) + && (src->type != BL_PC || sd->auto_cast_current.type != AUTOCAST_ITEM)) return 0; break; default: @@ -1707,7 +1719,7 @@ static int status_check_skilluse(struct block_list *src, struct block_list *targ return 0; //Can't amp out of Wand of Hermode :/ [Skotlex] } - if (skill_id != 0 /* Do not block item-casted skills.*/ && (src->type != BL_PC || sd->skillitem != skill_id)) { + if (skill_id != 0 /* Do not block item-casted skills.*/ && (src->type != BL_PC || sd->auto_cast_current.type != AUTOCAST_ITEM)) { //Skills blocked through status changes... if (!flag && ( //Blocked only from using the skill (stuff like autospell may still go through sc->data[SC_SILENCE] || @@ -1725,6 +1737,7 @@ static int status_check_skilluse(struct block_list *src, struct block_list *targ (sc->data[SC_MARIONETTE] && skill_id == CG_MARIONETTE) || //Cannot use marionette if you are being buffed by another (sc->data[SC_STASIS] && skill->block_check(src, SC_STASIS, skill_id)) || (sc->data[SC_KG_KAGEHUMI] && skill->block_check(src, SC_KG_KAGEHUMI, skill_id)) + || sc->data[SC_ALL_RIDING] != NULL // New mounts can't attack nor use skills in the client; this check makes it cheat-safe. [Ind] )) return 0; @@ -1773,8 +1786,6 @@ static int status_check_skilluse(struct block_list *src, struct block_list *targ } else if ( skill_id != ST_CHASEWALK ) return 0; } - if( sc->data[SC_ALL_RIDING] ) - return 0;//New mounts can't attack nor use skills in the client; this check makes it cheat-safe [Ind] } if (target == NULL || target == src) //No further checking needed. @@ -2572,12 +2583,16 @@ static int status_calc_pc_(struct map_session_data *sd, enum e_status_calc_opt o status->calc_pc_additional(sd, opt); - if( sd->pd ) { // Pet Bonus + if (sd->pd != NULL) { // Pet bonus. struct pet_data *pd = sd->pd; - if( pd && pd->petDB && pd->petDB->equip_script && pd->pet.intimate >= battle_config.pet_equip_min_friendly ) - script->run(pd->petDB->equip_script,0,sd->bl.id,0); - if( pd && pd->pet.intimate > 0 && (!battle_config.pet_equip_required || pd->pet.equip > 0) && pd->state.skillbonus == 1 && pd->bonus ) - pc->bonus(sd,pd->bonus->type, pd->bonus->val); + + if (pd->petDB != NULL && pd->petDB->equip_script != NULL) + script->run(pd->petDB->equip_script, 0, sd->bl.id, 0); + + if (pd->pet.intimate > PET_INTIMACY_NONE && pd->state.skillbonus == 1 && pd->bonus != NULL + && (battle_config.pet_equip_required == 0 || pd->pet.equip > 0)) { + pc->bonus(sd, pd->bonus->type, pd->bonus->val); + } } //param_bonus now holds card bonuses. @@ -3018,6 +3033,22 @@ static int status_calc_pc_(struct map_session_data *sd, enum e_status_calc_opt o sd->subele[ELE_FIRE] += sc->data[SC_ARMOR_RESIST]->val3; sd->subele[ELE_WIND] += sc->data[SC_ARMOR_RESIST]->val4; } + if (sc->data[SC_RESIST_PROPERTY_WATER] != NULL) { // Coldproof Potion + sd->subele[ELE_WATER] += sc->data[SC_RESIST_PROPERTY_WATER]->val1; + sd->subele[ELE_WIND] += sc->data[SC_RESIST_PROPERTY_WATER]->val2; + } + if (sc->data[SC_RESIST_PROPERTY_GROUND] != NULL) { // Earthproof Potion + sd->subele[ELE_EARTH] += sc->data[SC_RESIST_PROPERTY_GROUND]->val1; + sd->subele[ELE_FIRE] += sc->data[SC_RESIST_PROPERTY_GROUND]->val2; + } + if (sc->data[SC_RESIST_PROPERTY_FIRE] != NULL) { // Fireproof Potion + sd->subele[ELE_FIRE] += sc->data[SC_RESIST_PROPERTY_FIRE]->val1; + sd->subele[ELE_WATER] += sc->data[SC_RESIST_PROPERTY_FIRE]->val2; + } + if (sc->data[SC_RESIST_PROPERTY_WIND] != NULL) { // Thunderproof Potion + sd->subele[ELE_WIND] += sc->data[SC_RESIST_PROPERTY_WIND]->val1; + sd->subele[ELE_EARTH] += sc->data[SC_RESIST_PROPERTY_WIND]->val2; + } if (sc->data[SC_FIRE_CLOAK_OPTION]) { i = sc->data[SC_FIRE_CLOAK_OPTION]->val2; sd->subele[ELE_FIRE] += i; @@ -3038,6 +3069,18 @@ static int status_calc_pc_(struct map_session_data *sd, enum e_status_calc_opt o sd->subele[ELE_EARTH] += i; sd->subele[ELE_FIRE] -= i; } + if (sc->data[SC_POPECOOKIE] != NULL) { + i = sc->data[SC_POPECOOKIE]->val3; + sd->subele[ELE_WATER] += i; + sd->subele[ELE_EARTH] += i; + sd->subele[ELE_FIRE] += i; + sd->subele[ELE_WIND] += i; + sd->subele[ELE_POISON] += i; + sd->subele[ELE_HOLY] += i; + sd->subele[ELE_DARK] += i; + sd->subele[ELE_GHOST] += i; + sd->subele[ELE_UNDEAD] += i; + } if (sc->data[SC_MTF_MLEATKED]) sd->subele[ELE_NEUTRAL] += sc->data[SC_MTF_MLEATKED]->val1; if (sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 3) @@ -4801,6 +4844,10 @@ static int status_calc_batk(struct block_list *bl, struct status_change *sc, int /* some statuses that are hidden in the status window */ if(sc->data[SC_PLUSATTACKPOWER]) batk += sc->data[SC_PLUSATTACKPOWER]->val1; + if (sc->data[SC_POPECOOKIE] != NULL) + batk += batk * sc->data[SC_POPECOOKIE]->val1 / 100; + if (sc->data[SC_VITALIZE_POTION] != NULL) + batk += batk * sc->data[SC_VITALIZE_POTION]->val1 / 100; return cap_value(batk, battle_config.batk_min, battle_config.batk_max); } #ifndef RENEWAL @@ -4880,6 +4927,10 @@ static int status_calc_batk(struct block_list *bl, struct status_change *sc, int batk += batk * sc->data[SC_2011RWC]->val2 / 100; if (sc->data[SC_STEAMPACK]) batk += sc->data[SC_STEAMPACK]->val1; + if (sc->data[SC_SKF_ATK] != NULL) + batk += sc->data[SC_SKF_ATK]->val1; + if (sc->data[SC_ALMIGHTY] != NULL) + batk += sc->data[SC_ALMIGHTY]->val1; if (sc->data[SC_SHRIMP]) batk += batk * sc->data[SC_SHRIMP]->val2 / 100; @@ -5020,6 +5071,10 @@ static int status_calc_matk(struct block_list *bl, struct status_change *sc, int /* some statuses that are hidden in the status window */ if (sc->data[SC_MINDBREAKER]) matk += matk * sc->data[SC_MINDBREAKER]->val2 / 100; + if (sc->data[SC_POPECOOKIE] != NULL) + matk += matk * sc->data[SC_POPECOOKIE]->val2 / 100; + if (sc->data[SC_VITALIZE_POTION] != NULL) + matk += matk * sc->data[SC_VITALIZE_POTION]->val2 / 100; return cap_value(matk, battle_config.matk_min, battle_config.matk_max); } @@ -5077,6 +5132,10 @@ static int status_calc_matk(struct block_list *bl, struct status_change *sc, int matk += matk * sc->data[SC_2011RWC]->val2 / 100; if (sc->data[SC_MAGIC_CANDY]) matk += sc->data[SC_MAGIC_CANDY]->val1; + if (sc->data[SC_SKF_MATK] != NULL) + matk += sc->data[SC_SKF_MATK]->val1; + if (sc->data[SC_ALMIGHTY] != NULL) + matk += sc->data[SC_ALMIGHTY]->val2; return cap_value(matk, battle_config.matk_min, battle_config.matk_max); } @@ -5901,6 +5960,8 @@ static short status_calc_aspd(struct block_list *bl, struct status_change *sc, s bonus += sc->data[SC_BATTLESCROLL]->val1; if (sc->data[SC_STEAMPACK]) bonus += sc->data[SC_STEAMPACK]->val2; + if (sc->data[SC_SKF_ASPD] != NULL) + bonus += sc->data[SC_SKF_ASPD]->val1; } return (bonus + pots); @@ -6068,6 +6129,8 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change * aspd_rate += sc->data[SC_BATTLESCROLL]->val1 * 10; if (sc->data[SC_STEAMPACK]) aspd_rate += sc->data[SC_STEAMPACK]->val2 * 10; + if (sc->data[SC_SKF_ASPD] != NULL) + aspd_rate -= sc->data[SC_SKF_ASPD]->val1 * 10; return (short)cap_value(aspd_rate,0,SHRT_MAX); } @@ -6344,13 +6407,24 @@ static int status_get_class(const struct block_list *bl) { nullpo_ret(bl); switch (bl->type) { - case BL_PC: return BL_UCCAST(BL_PC, bl)->status.class; - case BL_MOB: return BL_UCCAST(BL_MOB, bl)->vd->class; //Class used on all code should be the view class of the mob. - case BL_PET: return BL_UCCAST(BL_PET, bl)->pet.class_; - case BL_HOM: return BL_UCCAST(BL_HOM, bl)->homunculus.class_; - case BL_MER: return BL_UCCAST(BL_MER, bl)->mercenary.class_; - case BL_NPC: return BL_UCCAST(BL_NPC, bl)->class_; - case BL_ELEM: return BL_UCCAST(BL_ELEM, bl)->elemental.class_; + case BL_PC: + return BL_UCCAST(BL_PC, bl)->status.class; + case BL_MOB: + { + const struct view_data *const vd = BL_UCCAST(BL_MOB, bl)->vd; + nullpo_ret(vd); + return vd->class; //Class used on all code should be the view class of the mob. + } + case BL_PET: + return BL_UCCAST(BL_PET, bl)->pet.class_; + case BL_HOM: + return BL_UCCAST(BL_HOM, bl)->homunculus.class_; + case BL_MER: + return BL_UCCAST(BL_MER, bl)->mercenary.class_; + case BL_NPC: + return BL_UCCAST(BL_NPC, bl)->class_; + case BL_ELEM: + return BL_UCCAST(BL_ELEM, bl)->elemental.class_; } return 0; } @@ -6440,7 +6514,7 @@ static defType status_get_def(struct block_list *bl) int def = st ? st->def : 0; ud = unit->bl2ud(bl); if (ud && ud->skilltimer != INVALID_TIMER) - def -= def * skill->get_castdef(ud->skill_id)/100; + def -= def * skill->get_castdef(ud->skill_id, ud->skill_lv) / 100; return cap_value(def, DEFTYPE_MIN, DEFTYPE_MAX); } @@ -7710,6 +7784,10 @@ static int status_change_start_sub(struct block_list *src, struct block_list *bl case SC_ENCHANTARMS: case SC_ARMORPROPERTY: case SC_ARMOR_RESIST: + case SC_RESIST_PROPERTY_WATER: + case SC_RESIST_PROPERTY_GROUND: + case SC_RESIST_PROPERTY_FIRE: + case SC_RESIST_PROPERTY_WIND: break; case SC_GOSPEL: //Must not override a casting gospel char. @@ -7765,6 +7843,9 @@ static int status_change_start_sub(struct block_list *src, struct block_list *bl calc_flag = status->dbs->ChangeFlagTable[type]; if(!(flag&SCFLAG_LOADED)) { // Do not parse val settings when loading SCs switch(type) { + case SC_AUTOTRADE: + case SC_KSPROTECTED: + break; // Prevent calling status_change_start_unknown_sc(). case SC_ADORAMUS: sc_start(src,bl,SC_BLIND,100,val1,skill->get_time(status->sc2skill(type),val1)); // Fall through to SC_INC_AGI @@ -8009,7 +8090,6 @@ static int status_change_start_sub(struct block_list *src, struct block_list *bl // This is done this way because the message that the client displays is hardcoded, and only // shows how many minutes are remaining. [Panikon] total_tick = 60000; - val1 = battle_config.manner_system; //Mute filters. if (sd) { clif->changestatus(sd,SP_MANNER,sd->status.manner); @@ -8656,6 +8736,210 @@ static int status_change_start_sub(struct block_list *src, struct block_list *bl //associated, and yet are not wrong/unknown. [Skotlex] //break; } + case SC_ARMOR_RESIST: { + struct status_change_entry *sce_water = sc->data[SC_RESIST_PROPERTY_WATER]; + struct status_change_entry *sce_ground = sc->data[SC_RESIST_PROPERTY_GROUND]; + struct status_change_entry *sce_fire = sc->data[SC_RESIST_PROPERTY_FIRE]; + struct status_change_entry *sce_wind = sc->data[SC_RESIST_PROPERTY_WIND]; + + // Water + int sum_water = val1 + ((sce_fire != NULL) ? sce_fire->val2 : 0); + bool show_icon = true; + if (sce_water != NULL && sce_water->timer != INVALID_TIMER) { + const struct TimerData *td = timer->get(sce_water->timer); + if (td != NULL) { + sum_water += sce_water->val1; + int left = (int)DIFF_TICK(td->tick, timer->gettick()); + if (left > total_tick && sum_water - val1 > 0) + show_icon = false; + } + } + if (val1 > 0 && sum_water > 0 && show_icon) { + int sc_icn = status->get_sc_icon(SC_RESIST_PROPERTY_WATER); + int sc_typ = status->get_sc_relevant_bl_types(SC_RESIST_PROPERTY_WATER); + clif->status_change(bl, sc_icn, sc_typ, 1, total_tick, 0, 0, 0); + } else if (sum_water <= 0) { + clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(SC_RESIST_PROPERTY_WATER)); + } + + // Ground + int sum_ground = val2 + ((sce_wind != NULL) ? sce_wind->val2 : 0); + show_icon = true; + if (sce_ground != NULL && sce_ground->timer != INVALID_TIMER) { + const struct TimerData *td = timer->get(sce_ground->timer); + if (td != NULL) { + sum_ground += sce_ground->val1; + int left = (int)DIFF_TICK(td->tick, timer->gettick()); + if (left > total_tick && sum_ground - val2 > 0) + show_icon = false; + } + } + if (val2 > 0 && sum_ground > 0 && show_icon) { + int sc_icn = status->get_sc_icon(SC_RESIST_PROPERTY_GROUND); + int sc_typ = status->get_sc_relevant_bl_types(SC_RESIST_PROPERTY_GROUND); + clif->status_change(bl, sc_icn, sc_typ, 1, total_tick, 0, 0, 0); + } else if (sum_ground <= 0) { + clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(SC_RESIST_PROPERTY_GROUND)); + } + + // Fire + int sum_fire = val3 + ((sce_ground != NULL) ? sce_ground->val2 : 0); + show_icon = true; + if (sce_fire != NULL && sce_fire->timer != INVALID_TIMER) { + const struct TimerData *td = timer->get(sce_fire->timer); + if (td != NULL) { + sum_fire += sce_fire->val1; + int left = (int)DIFF_TICK(td->tick, timer->gettick()); + if (left > total_tick && sum_fire - val3 > 0) + show_icon = false; + } + } + if (val3 > 0 && sum_fire > 0 && show_icon) { + int sc_icn = status->get_sc_icon(SC_RESIST_PROPERTY_FIRE); + int sc_typ = status->get_sc_relevant_bl_types(SC_RESIST_PROPERTY_FIRE); + clif->status_change(bl, sc_icn, sc_typ, 1, total_tick, 0, 0, 0); + } else if (sum_fire <= 0) { + clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(SC_RESIST_PROPERTY_FIRE)); + } + + // Wind + int sum_wind = val4 + ((sce_water != NULL) ? sce_water->val2 : 0); + show_icon = true; + if (sce_wind != NULL && sce_wind->timer != INVALID_TIMER) { + const struct TimerData *td = timer->get(sce_wind->timer); + if (td != NULL) { + sum_wind += sce_wind->val1; + int left = (int)DIFF_TICK(td->tick, timer->gettick()); + if (left > total_tick && sum_wind - val4 > 0) + show_icon = false; + } + } + if (val4 > 0 && sum_wind > 0 && show_icon) { + int sc_icn = status->get_sc_icon(SC_RESIST_PROPERTY_WIND); + int sc_typ = status->get_sc_relevant_bl_types(SC_RESIST_PROPERTY_WIND); + clif->status_change(bl, sc_icn, sc_typ, 1, total_tick, 0, 0, 0); + } else if (sum_wind <= 0) { + clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(SC_RESIST_PROPERTY_WIND)); + } + + break; + } + case SC_RESIST_PROPERTY_WATER: { + struct status_change_entry *sce_all = sc->data[SC_ARMOR_RESIST]; + struct status_change_entry *sce_fire = sc->data[SC_RESIST_PROPERTY_FIRE]; + struct status_change_entry *sce_wind = sc->data[SC_RESIST_PROPERTY_WIND]; + + // Water + int sum_water = val1 + ((sce_fire != NULL) ? sce_fire->val2 : 0); + if (sce_all != NULL && sce_all->timer != INVALID_TIMER) { + const struct TimerData *td = timer->get(sce_all->timer); + if (td != NULL) { + sum_water += sce_all->val1; + int left = (int)DIFF_TICK(td->tick, timer->gettick()); + if (left > total_tick && sum_water - val1 > 0) + flag |= SCFLAG_NOICON; + } + } + if (sum_water <= 0) { + clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(SC_RESIST_PROPERTY_WATER)); + flag |= SCFLAG_NOICON; + } + + // Wind + int sum_wind = val2 + ((sce_wind != NULL) ? sce_wind->val1 : 0); + sum_wind += (sce_all != NULL) ? sce_all->val4 : 0; + if (sum_wind <= 0) + clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(SC_RESIST_PROPERTY_WIND)); + + break; + } + case SC_RESIST_PROPERTY_GROUND: { + struct status_change_entry *sce_all = sc->data[SC_ARMOR_RESIST]; + struct status_change_entry *sce_wind = sc->data[SC_RESIST_PROPERTY_WIND]; + struct status_change_entry *sce_fire = sc->data[SC_RESIST_PROPERTY_FIRE]; + + // Ground + int sum_ground = val1 + ((sce_wind != NULL) ? sce_wind->val2 : 0); + if (sce_all != NULL && sce_all->timer != INVALID_TIMER) { + const struct TimerData *td = timer->get(sce_all->timer); + if (td != NULL) { + sum_ground += sce_all->val2; + int left = (int)DIFF_TICK(td->tick, timer->gettick()); + if (left > total_tick && sum_ground - val1 > 0) + flag |= SCFLAG_NOICON; + } + } + if (sum_ground <= 0) { + clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(SC_RESIST_PROPERTY_GROUND)); + flag |= SCFLAG_NOICON; + } + + // Fire + int sum_fire = val2 + ((sce_fire != NULL) ? sce_fire->val1 : 0); + sum_fire += (sce_all != NULL) ? sce_all->val3 : 0; + if (sum_fire <= 0) + clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(SC_RESIST_PROPERTY_FIRE)); + + break; + } + case SC_RESIST_PROPERTY_FIRE: { + struct status_change_entry *sce_all = sc->data[SC_ARMOR_RESIST]; + struct status_change_entry *sce_ground = sc->data[SC_RESIST_PROPERTY_GROUND]; + struct status_change_entry *sce_water = sc->data[SC_RESIST_PROPERTY_WATER]; + + // Fire + int sum_fire = val1 + ((sce_ground != NULL) ? sce_ground->val2 : 0); + if (sce_all != NULL && sce_all->timer != INVALID_TIMER) { + const struct TimerData *td = timer->get(sce_all->timer); + if (td != NULL) { + sum_fire += sce_all->val3; + int left = (int)DIFF_TICK(td->tick, timer->gettick()); + if (left > total_tick && sum_fire - val1 > 0) + flag |= SCFLAG_NOICON; + } + } + if (sum_fire <= 0) { + clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(SC_RESIST_PROPERTY_FIRE)); + flag |= SCFLAG_NOICON; + } + + // Water + int sum_water = val2 + ((sce_water != NULL) ? sce_water->val1 : 0); + sum_water += (sce_all != NULL) ? sce_all->val1 : 0; + if (sum_water <= 0) + clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(SC_RESIST_PROPERTY_WATER)); + + break; + } + case SC_RESIST_PROPERTY_WIND: { + struct status_change_entry *sce_all = sc->data[SC_ARMOR_RESIST]; + struct status_change_entry *sce_water = sc->data[SC_RESIST_PROPERTY_WATER]; + struct status_change_entry *sce_ground = sc->data[SC_RESIST_PROPERTY_GROUND]; + + // Wind + int sum_wind = val1 + ((sce_water != NULL) ? sce_water->val2 : 0); + if (sce_all != NULL && sce_all->timer != INVALID_TIMER) { + const struct TimerData *td = timer->get(sce_all->timer); + if (td != NULL) { + sum_wind += sce_all->val4; + int left = (int)DIFF_TICK(td->tick, timer->gettick()); + if (left > total_tick && sum_wind - val1 > 0) + flag |= SCFLAG_NOICON; + } + } + if (sum_wind <= 0) { + clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(SC_RESIST_PROPERTY_WIND)); + flag |= SCFLAG_NOICON; + } + + // Ground + int sum_ground = val2 + ((sce_ground != NULL) ? sce_ground->val1 : 0); + sum_ground += (sce_all != NULL) ? sce_all->val2 : 0; + if (sum_ground <= 0) + clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(SC_RESIST_PROPERTY_GROUND)); + + break; + } case SC_MER_FLEE: case SC_MER_ATK: case SC_MER_HIT: @@ -10514,7 +10798,7 @@ static int status_change_clear(struct block_list *bl, int type) /*========================================== * 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) +static int status_change_end_(struct block_list *bl, enum sc_type type, int tid) { struct map_session_data *sd; struct status_change *sc; @@ -10582,6 +10866,9 @@ static int status_change_end_(struct block_list *bl, enum sc_type type, int tid, vd = status->get_viewdata(bl); calc_flag = status->dbs->ChangeFlagTable[type]; + + bool remove_icon = true; + switch(type) { case SC_GRANITIC_ARMOR: { @@ -10681,23 +10968,9 @@ static int status_change_end_(struct block_list *bl, enum sc_type type, int tid, break; case SC_DANCING: { - const char* prevfile = "<unknown>"; - int prevline = 0; struct map_session_data *dsd; struct status_change_entry *dsc; - if (sd) { - if (sd->delunit_prevfile) { - // initially this is NULL, when a character logs in - prevfile = sd->delunit_prevfile; - prevline = sd->delunit_prevline; - } else { - prevfile = "<none>"; - } - sd->delunit_prevfile = file; - sd->delunit_prevline = line; - } - if (sce->val4 && sce->val4 != BCT_SELF && (dsd=map->id2sd(sce->val4)) != NULL) { // end status on partner as well dsc = dsd->sc.data[SC_DANCING]; @@ -10713,19 +10986,10 @@ static int status_change_end_(struct block_list *bl, enum sc_type type, int tid, // erase associated land skill struct skill_unit_group *group = skill->id2group(sce->val2); - if (group == NULL) { - ShowDebug("status_change_end: SC_DANCING is missing skill unit group (val1=%d, val2=%d, val3=%d, val4=%d, timer=%d, tid=%d, char_id=%d, map=%s, x=%d, y=%d, prev=%s:%d, from=%s:%d). Please report this! (#3504)\n", - sce->val1, sce->val2, sce->val3, sce->val4, sce->timer, tid, - sd ? sd->status.char_id : 0, - mapindex_id2name(map_id2index(bl->m)), bl->x, bl->y, - prevfile, prevline, - file, line); - } - sce->val2 = 0; if( group ) - skill->del_unitgroup(group,ALC_MARK); + skill->del_unitgroup(group); } if ((sce->val1&0xFFFF) == CG_MOONLIT) @@ -10829,7 +11093,7 @@ static int status_change_end_(struct block_list *bl, enum sc_type type, int tid, struct skill_unit_group* group = skill->id2group(sce->val3); sce->val3 = 0; if( group ) - skill->del_unitgroup(group,ALC_MARK); + skill->del_unitgroup(group); } break; case SC_HERMODE: @@ -10848,7 +11112,7 @@ static int status_change_end_(struct block_list *bl, enum sc_type type, int tid, struct skill_unit_group* group = skill->id2group(sce->val4); sce->val4 = 0; if( group ) /* might have been cleared before status ended, e.g. land protector */ - skill->del_unitgroup(group,ALC_MARK); + skill->del_unitgroup(group); } break; case SC_KAAHI: @@ -10946,7 +11210,7 @@ static int status_change_end_(struct block_list *bl, enum sc_type type, int tid, struct skill_unit_group* group = skill->id2group(sce->val2); sce->val2 = 0; if (group) /* might have been cleared before status ended, e.g. land protector */ - skill->del_unitgroup(group,ALC_MARK); + skill->del_unitgroup(group); } break; case SC_BANDING: @@ -10954,7 +11218,7 @@ static int status_change_end_(struct block_list *bl, enum sc_type type, int tid, struct skill_unit_group *group = skill->id2group(sce->val4); sce->val4 = 0; if( group ) /* might have been cleared before status ended, e.g. land protector */ - skill->del_unitgroup(group,ALC_MARK); + skill->del_unitgroup(group); } break; case SC_CURSEDCIRCLE_ATKER: @@ -11013,6 +11277,202 @@ static int status_change_end_(struct block_list *bl, enum sc_type type, int tid, break; } break; + case SC_ARMOR_RESIST: { + struct status_change_entry *sce_water = sc->data[SC_RESIST_PROPERTY_WATER]; + struct status_change_entry *sce_ground = sc->data[SC_RESIST_PROPERTY_GROUND]; + struct status_change_entry *sce_fire = sc->data[SC_RESIST_PROPERTY_FIRE]; + struct status_change_entry *sce_wind = sc->data[SC_RESIST_PROPERTY_WIND]; + + // Water + clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(SC_RESIST_PROPERTY_WATER)); + if (sce_water != NULL && sce_water->timer != INVALID_TIMER) { + int sum_water = sce_water->val1 + ((sce_fire != NULL) ? sce_fire->val2 : 0); + const struct TimerData *td = timer->get(sce_water->timer); + if (td != NULL && sce_water->val1 > 0 && sum_water > 0) { + int sc_icn = status->get_sc_icon(SC_RESIST_PROPERTY_WATER); + int sc_typ = status->get_sc_relevant_bl_types(SC_RESIST_PROPERTY_WATER); + int sc_tck = (int)DIFF_TICK(td->tick, timer->gettick()); + int sc_ttl = sce_water->total_tick; + clif->status_change_sub(bl, sc_icn, sc_typ, 1, sc_tck, sc_ttl, 0, 0, 0); + } + } + + // Ground + clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(SC_RESIST_PROPERTY_GROUND)); + if (sce_ground != NULL && sce_ground->timer != INVALID_TIMER) { + int sum_ground = sce_ground->val1 + ((sce_wind != NULL) ? sce_wind->val2 : 0); + const struct TimerData *td = timer->get(sce_ground->timer); + if (td != NULL && sce_ground->val1 > 0 && sum_ground > 0) { + int sc_icn = status->get_sc_icon(SC_RESIST_PROPERTY_GROUND); + int sc_typ = status->get_sc_relevant_bl_types(SC_RESIST_PROPERTY_GROUND); + int sc_tck = (int)DIFF_TICK(td->tick, timer->gettick()); + int sc_ttl = sce_ground->total_tick; + clif->status_change_sub(bl, sc_icn, sc_typ, 1, sc_tck, sc_ttl, 0, 0, 0); + } + } + + // Fire + clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(SC_RESIST_PROPERTY_FIRE)); + if (sce_fire != NULL && sce_fire->timer != INVALID_TIMER) { + int sum_fire = sce_fire->val1 + ((sce_ground != NULL) ? sce_ground->val2 : 0); + const struct TimerData *td = timer->get(sce_fire->timer); + if (td != NULL && sce_fire->val1 > 0 && sum_fire > 0) { + int sc_icn = status->get_sc_icon(SC_RESIST_PROPERTY_FIRE); + int sc_typ = status->get_sc_relevant_bl_types(SC_RESIST_PROPERTY_FIRE); + int sc_tck = (int)DIFF_TICK(td->tick, timer->gettick()); + int sc_ttl = sce_fire->total_tick; + clif->status_change_sub(bl, sc_icn, sc_typ, 1, sc_tck, sc_ttl, 0, 0, 0); + } + } + + // Wind + clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(SC_RESIST_PROPERTY_WIND)); + if (sce_wind != NULL && sce_wind->timer != INVALID_TIMER) { + int sum_wind = sce_wind->val1 + ((sce_water != NULL) ? sce_water->val2 : 0); + const struct TimerData *td = timer->get(sce_wind->timer); + if (td != NULL && sce_wind->val1 > 0 && sum_wind > 0) { + int sc_icn = status->get_sc_icon(SC_RESIST_PROPERTY_WIND); + int sc_typ = status->get_sc_relevant_bl_types(SC_RESIST_PROPERTY_WIND); + int sc_tck = (int)DIFF_TICK(td->tick, timer->gettick()); + int sc_ttl = sce_wind->total_tick; + clif->status_change_sub(bl, sc_icn, sc_typ, 1, sc_tck, sc_ttl, 0, 0, 0); + } + } + + break; + } + case SC_RESIST_PROPERTY_WATER: + if (sc->data[SC_ARMOR_RESIST] != NULL && sc->data[SC_ARMOR_RESIST]->timer != INVALID_TIMER) { + const struct TimerData *td = timer->get(sc->data[SC_ARMOR_RESIST]->timer); + if (td == NULL) + break; + + // Water + int sum_water = sc->data[SC_ARMOR_RESIST]->val1; + if (sc->data[SC_RESIST_PROPERTY_FIRE] != NULL) + sum_water += sc->data[SC_RESIST_PROPERTY_FIRE]->val2; + if (sc->data[SC_ARMOR_RESIST]->val1 > 0 && sum_water > 0) { + int sc_icn = status->get_sc_icon(SC_RESIST_PROPERTY_WATER); + int sc_typ = status->get_sc_relevant_bl_types(SC_RESIST_PROPERTY_WATER); + int sc_tck = (int)DIFF_TICK(td->tick, timer->gettick()); + int sc_ttl = sc->data[SC_ARMOR_RESIST]->total_tick; + clif->status_change_sub(bl, sc_icn, sc_typ, 1, sc_tck, sc_ttl, 0, 0, 0); + remove_icon = false; + } + + // Wind + int sum_wind = sc->data[SC_ARMOR_RESIST]->val4; + if (sc->data[SC_RESIST_PROPERTY_WIND] != NULL) + sum_wind += sc->data[SC_RESIST_PROPERTY_WIND]->val1; + if (sc->data[SC_ARMOR_RESIST]->val4 > 0 && sum_wind > 0) { + int sc_icn = status->get_sc_icon(SC_RESIST_PROPERTY_WIND); + int sc_typ = status->get_sc_relevant_bl_types(SC_RESIST_PROPERTY_WIND); + int sc_tck = (int)DIFF_TICK(td->tick, timer->gettick()); + int sc_ttl = sc->data[SC_ARMOR_RESIST]->total_tick; + clif->status_change_sub(bl, sc_icn, sc_typ, 1, sc_tck, sc_ttl, 0, 0, 0); + } + } + + break; + case SC_RESIST_PROPERTY_GROUND: + if (sc->data[SC_ARMOR_RESIST] != NULL && sc->data[SC_ARMOR_RESIST]->timer != INVALID_TIMER) { + const struct TimerData *td = timer->get(sc->data[SC_ARMOR_RESIST]->timer); + if (td == NULL) + break; + + // Ground + int sum_ground = sc->data[SC_ARMOR_RESIST]->val2; + if (sc->data[SC_RESIST_PROPERTY_WIND] != NULL) + sum_ground += sc->data[SC_RESIST_PROPERTY_WIND]->val2; + if (sc->data[SC_ARMOR_RESIST]->val2 > 0 && sum_ground > 0) { + int sc_icn = status->get_sc_icon(SC_RESIST_PROPERTY_GROUND); + int sc_typ = status->get_sc_relevant_bl_types(SC_RESIST_PROPERTY_GROUND); + int sc_tck = (int)DIFF_TICK(td->tick, timer->gettick()); + int sc_ttl = sc->data[SC_ARMOR_RESIST]->total_tick; + clif->status_change_sub(bl, sc_icn, sc_typ, 1, sc_tck, sc_ttl, 0, 0, 0); + remove_icon = false; + } + + // Fire + int sum_fire = sc->data[SC_ARMOR_RESIST]->val3; + if (sc->data[SC_RESIST_PROPERTY_FIRE] != NULL) + sum_fire += sc->data[SC_RESIST_PROPERTY_FIRE]->val1; + if (sc->data[SC_ARMOR_RESIST]->val3 > 0 && sum_fire > 0) { + int sc_icn = status->get_sc_icon(SC_RESIST_PROPERTY_FIRE); + int sc_typ = status->get_sc_relevant_bl_types(SC_RESIST_PROPERTY_FIRE); + int sc_tck = (int)DIFF_TICK(td->tick, timer->gettick()); + int sc_ttl = sc->data[SC_ARMOR_RESIST]->total_tick; + clif->status_change_sub(bl, sc_icn, sc_typ, 1, sc_tck, sc_ttl, 0, 0, 0); + } + } + + break; + case SC_RESIST_PROPERTY_FIRE: + if (sc->data[SC_ARMOR_RESIST] != NULL && sc->data[SC_ARMOR_RESIST]->timer != INVALID_TIMER) { + const struct TimerData *td = timer->get(sc->data[SC_ARMOR_RESIST]->timer); + if (td == NULL) + break; + + // Fire + int sum_fire = sc->data[SC_ARMOR_RESIST]->val3; + if (sc->data[SC_RESIST_PROPERTY_GROUND] != NULL) + sum_fire += sc->data[SC_RESIST_PROPERTY_GROUND]->val2; + if (sc->data[SC_ARMOR_RESIST]->val3 > 0 && sum_fire > 0) { + int sc_icn = status->get_sc_icon(SC_RESIST_PROPERTY_FIRE); + int sc_typ = status->get_sc_relevant_bl_types(SC_RESIST_PROPERTY_FIRE); + int sc_tck = (int)DIFF_TICK(td->tick, timer->gettick()); + int sc_ttl = sc->data[SC_ARMOR_RESIST]->total_tick; + clif->status_change_sub(bl, sc_icn, sc_typ, 1, sc_tck, sc_ttl, 0, 0, 0); + remove_icon = false; + } + + // Water + int sum_water = sc->data[SC_ARMOR_RESIST]->val1; + if (sc->data[SC_RESIST_PROPERTY_WATER] != NULL) + sum_water += sc->data[SC_RESIST_PROPERTY_WATER]->val1; + if (sc->data[SC_ARMOR_RESIST]->val1 > 0 && sum_water > 0) { + int sc_icn = status->get_sc_icon(SC_RESIST_PROPERTY_WATER); + int sc_typ = status->get_sc_relevant_bl_types(SC_RESIST_PROPERTY_WATER); + int sc_tck = (int)DIFF_TICK(td->tick, timer->gettick()); + int sc_ttl = sc->data[SC_ARMOR_RESIST]->total_tick; + clif->status_change_sub(bl, sc_icn, sc_typ, 1, sc_tck, sc_ttl, 0, 0, 0); + } + } + + break; + case SC_RESIST_PROPERTY_WIND: + if (sc->data[SC_ARMOR_RESIST] != NULL && sc->data[SC_ARMOR_RESIST]->timer != INVALID_TIMER) { + const struct TimerData *td = timer->get(sc->data[SC_ARMOR_RESIST]->timer); + if (td == NULL) + break; + + // Wind + int sum_wind = sc->data[SC_ARMOR_RESIST]->val4; + if (sc->data[SC_RESIST_PROPERTY_WATER] != NULL) + sum_wind += sc->data[SC_RESIST_PROPERTY_WATER]->val2; + if (sc->data[SC_ARMOR_RESIST]->val4 > 0 && sum_wind > 0) { + int sc_icn = status->get_sc_icon(SC_RESIST_PROPERTY_WIND); + int sc_typ = status->get_sc_relevant_bl_types(SC_RESIST_PROPERTY_WIND); + int sc_tck = (int)DIFF_TICK(td->tick, timer->gettick()); + int sc_ttl = sc->data[SC_ARMOR_RESIST]->total_tick; + clif->status_change_sub(bl, sc_icn, sc_typ, 1, sc_tck, sc_ttl, 0, 0, 0); + remove_icon = false; + } + + // Ground + int sum_ground = sc->data[SC_ARMOR_RESIST]->val2; + if (sc->data[SC_RESIST_PROPERTY_GROUND] != NULL) + sum_ground += sc->data[SC_RESIST_PROPERTY_GROUND]->val1; + if (sc->data[SC_ARMOR_RESIST]->val2 > 0 && sum_ground > 0) { + int sc_icn = status->get_sc_icon(SC_RESIST_PROPERTY_GROUND); + int sc_typ = status->get_sc_relevant_bl_types(SC_RESIST_PROPERTY_GROUND); + int sc_tck = (int)DIFF_TICK(td->tick, timer->gettick()); + int sc_ttl = sc->data[SC_ARMOR_RESIST]->total_tick; + clif->status_change_sub(bl, sc_icn, sc_typ, 1, sc_tck, sc_ttl, 0, 0, 0); + } + } + + break; } opt_flag = 1; @@ -11226,7 +11686,8 @@ static int status_change_end_(struct block_list *bl, enum sc_type type, int tid, #endif //On Aegis, when turning off a status change, first goes the sc packet, then the option packet. - clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(type)); + if (remove_icon) + clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(type)); if( opt_flag&8 ) //bugreport:681 clif->changeoption2(bl); |