diff options
Diffstat (limited to 'src/map/skill.c')
-rw-r--r-- | src/map/skill.c | 348 |
1 files changed, 200 insertions, 148 deletions
diff --git a/src/map/skill.c b/src/map/skill.c index 4eaab5457..c19a684af 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -44,6 +44,7 @@ #include "map/path.h" #include "map/pc.h" #include "map/pet.h" +#include "map/refine.h" #include "map/script.h" #include "map/status.h" #include "map/unit.h" @@ -81,7 +82,7 @@ #endif static struct skill_interface skill_s; -struct s_skill_dbs skilldbs; +static struct s_skill_dbs skilldbs; struct skill_interface *skill; @@ -2042,7 +2043,7 @@ static int skill_additional_effect(struct block_list *src, struct block_list *bl if (DIFF_TICK(ud->canact_tick, tick + rate) < 0){ ud->canact_tick = tick+rate; if ( battle_config.display_status_timers ) - clif->status_change(src, SI_POSTDELAY, 1, rate, 0, 0, 0); + clif->status_change(src, status->get_sc_icon(SC_POSTDELAY), status->get_sc_relevant_bl_types(SC_POSTDELAY), 1, rate, 0, 0, 0); } } } @@ -2128,7 +2129,7 @@ static int skill_additional_effect(struct block_list *src, struct block_list *bl if (DIFF_TICK(ud->canact_tick, tick + rate) < 0){ ud->canact_tick = tick+rate; if (battle_config.display_status_timers) - clif->status_change(src, SI_POSTDELAY, 1, rate, 0, 0, 0); + clif->status_change(src, status->get_sc_icon(SC_POSTDELAY), status->get_sc_relevant_bl_types(SC_POSTDELAY), 1, rate, 0, 0, 0); } } } @@ -2361,11 +2362,11 @@ static int skill_counter_additional_effect(struct block_list *src, struct block_ ) { // Soul Drain should only work on targeted spells [Skotlex] if( pc_issit(sd) ) pc->setstand(sd); // Character stuck in attacking animation while 'sitting' fix. [Skotlex] - if( skill->get_nk(skill_id)&NK_SPLASH && skill->area_temp[1] != bl->id ) + if (skill->get_nk(skill_id)&NK_SPLASH && skill->area_temp[1] != bl->id) { ; - else { + } else { clif->skill_nodamage(src,bl,HW_SOULDRAIN,rate,1); - status->heal(src, 0, status->get_lv(bl)*(95+15*rate)/100, 2); + status->heal(src, 0, status->get_lv(bl)*(95+15*rate)/100, STATUS_HEAL_SHOWEFFECT); } } @@ -2388,9 +2389,9 @@ static int skill_counter_additional_effect(struct block_list *src, struct block_ sc->data[SC_SOULLINK]->val3 = 0; //Clear bounced spell check. } } - if( hp || sp ) { + if (hp != 0 || sp != 0) { // updated to force healing to allow healing through berserk - status->heal(src, hp, sp, battle_config.show_hp_sp_gain ? 3 : 1); + status->heal(src, hp, sp, STATUS_HEAL_FORCED | (battle_config.show_hp_sp_gain ? STATUS_HEAL_SHOWEFFECT : STATUS_HEAL_DEFAULT)); } } @@ -2469,7 +2470,7 @@ static int skill_counter_additional_effect(struct block_list *src, struct block_ if (DIFF_TICK(ud->canact_tick, tick + rate) < 0){ ud->canact_tick = tick+rate; if (battle_config.display_status_timers) - clif->status_change(bl, SI_POSTDELAY, 1, rate, 0, 0, 0); + clif->status_change(bl, status->get_sc_icon(SC_POSTDELAY), status->get_sc_relevant_bl_types(SC_POSTDELAY), 1, rate, 0, 0, 0); } } } @@ -2892,14 +2893,28 @@ static int skill_attack(int attack_type, struct block_list *src, struct block_li } #endif /* MAGIC_REFLECTION_TYPE */ } - if(sc && sc->data[SC_MAGICROD] && src == dsrc) { - int sp = skill->get_sp(skill_id,skill_lv); + if (sc && sc->data[SC_MAGICROD] && src == dsrc) { + int sp = skill->get_sp(skill_id, skill_lv); dmg.damage = dmg.damage2 = 0; dmg.dmg_lv = ATK_MISS; //This will prevent skill additional effect from taking effect. [Skotlex] sp = sp * sc->data[SC_MAGICROD]->val2 / 100; - if(skill_id == WZ_WATERBALL && skill_lv > 1) - sp = sp/((skill_lv|1)*(skill_lv|1)); //Estimate SP cost of a single water-ball - status->heal(bl, 0, sp, 2); + if (skill_id == WZ_WATERBALL && skill_lv > 1) + sp = sp / ((skill_lv | 1) * (skill_lv | 1)); //Estimate SP cost of a single water-ball + status->heal(bl, 0, sp, STATUS_HEAL_SHOWEFFECT); + if (battle->bc->magicrod_type == 1) + clif->skill_nodamage(bl, bl, SA_MAGICROD, sc->data[SC_MAGICROD]->val1, 1); // Animation used here in eAthena [Wolfie] + } + } + + if (bl->type == BL_MOB) { + struct mob_data *md = BL_CAST(BL_MOB, bl); + if (md != NULL) { + if (md->db->dmg_taken_rate != 100) { + if (dmg.damage > 0) + dmg.damage = apply_percentrate64(dmg.damage, md->db->dmg_taken_rate, 100); + if (dmg.damage2 > 0) + dmg.damage2 = apply_percentrate64(dmg.damage2, md->db->dmg_taken_rate, 100); + } } } @@ -3774,7 +3789,7 @@ static int skill_check_condition_mercenary(struct block_list *bl, int skill_id, if (itemid[i] < 1) continue; // No item index[i] = pc->search_inventory(sd, itemid[i]); if (index[i] == INDEX_NOT_FOUND || sd->status.inventory[index[i]].amount < amount[i]) { - clif->skill_fail(sd, skill_id, USESKILL_FAIL_NEED_ITEM, amount[i], itemid[i] << 16); + clif->skill_fail(sd, skill_id, USESKILL_FAIL_NEED_ITEM, amount[i], itemid[i]); return 0; } } @@ -4138,7 +4153,7 @@ static int skill_activate_reverberation(struct block_list *bl, va_list ap) if( su->alive && (sg = su->group) != NULL && sg->skill_id == WM_REVERBERATION && sg->unit_id == UNT_REVERBERATION ) { int64 tick = timer->gettick(); clif->changetraplook(bl,UNT_USED_TRAPS); - map->foreachinrange(skill->trap_splash, bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, bl, tick); + skill->trap_do_splash(bl, sg->skill_id, sg->skill_lv, sg->bl_flag, tick); su->limit = DIFF_TICK32(tick,sg->tick)+1500; sg->unit_id = UNT_USED_TRAPS; } @@ -4153,10 +4168,9 @@ static int skill_reveal_trap(struct block_list *bl, va_list ap) Assert_ret(bl->type == BL_SKILL); su = BL_UCAST(BL_SKILL, bl); - if (su->alive && su->group && skill->get_inf2(su->group->skill_id)&INF2_TRAP) { //Reveal trap. - //Change look is not good enough, the client ignores it as an actual trap still. [Skotlex] - //clif->changetraplook(bl, su->group->unit_id); - clif->getareachar_skillunit(&su->bl,su,AREA); + if (su->alive && su->group && skill->get_inf2(su->group->skill_id) & INF2_HIDDEN_TRAP) { //Reveal trap. + su->visible = true; + clif->skillunit_update(bl); return 1; } return 0; @@ -4477,7 +4491,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl if( skill_id == MO_EXTREMITYFIST ) { mbl = src; i = 3; // for Asura(from caster) - status->set_sp(src, 0, 0); + status->set_sp(src, 0, STATUS_HEAL_DEFAULT); status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER); status_change_end(src, SC_BLADESTOP, INVALID_TIMER); #ifdef RENEWAL @@ -4487,9 +4501,9 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl status_change_end(src, SC_NJ_NEN, INVALID_TIMER); status_change_end(src, SC_HIDING, INVALID_TIMER); #ifdef RENEWAL - status->set_hp(src, max(status_get_max_hp(src)/100, 1), 0); + status->set_hp(src, max(status_get_max_hp(src)/100, 1), STATUS_HEAL_DEFAULT); #else // not RENEWAL - status->set_hp(src, 1, 0); + status->set_hp(src, 1, STATUS_HEAL_DEFAULT); #endif // RENEWAL } dir = map->calc_dir(src,bl->x,bl->y); @@ -4603,7 +4617,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl heal = skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, sflag); if (skill_id == NPC_VAMPIRE_GIFT && heal > 0) { clif->skill_nodamage(NULL, src, AL_HEAL, heal, 1); - status->heal(src,heal,0,0); + status->heal(src, heal, 0, STATUS_HEAL_DEFAULT); } if (skill_id == SU_SCRATCH && status->get_lv(src) >= 30 && (rnd() % 100 < (int)(status->get_lv(src) / 30) + 10)) // TODO: Need activation chance. skill->addtimerskill(src, tick + skill->get_delay(skill_id, skill_lv), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag); @@ -4971,7 +4985,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl src, src, bl, skill_id, skill_lv, tick, flag); if (heal > 0){ clif->skill_nodamage(NULL, src, AL_HEAL, heal, 1); - status->heal(src, heal, 0, 0); + status->heal(src, heal, 0, STATUS_HEAL_DEFAULT); } } break; @@ -5082,7 +5096,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl heal = 0; // Don't absorb heal from Ice Walls or other skill units. if( heal && rnd()%100 < rate ) { - status->heal(src, heal, 0, 0); + status->heal(src, heal, 0, STATUS_HEAL_DEFAULT); clif->skill_nodamage(NULL, src, AL_HEAL, heal, 1); } } @@ -5154,7 +5168,7 @@ static int skill_castend_damage_id(struct block_list *src, struct block_list *bl skill->castend_type(skill->get_casttype(spell_skill_id), src, bl, spell_skill_id, spell_skill_lv, tick, 0); sd->ud.canact_tick = tick + skill->delay_fix(src, spell_skill_id, spell_skill_lv); - clif->status_change(src, SI_POSTDELAY, 1, skill->delay_fix(src, spell_skill_id, spell_skill_lv), 0, 0, 0); + clif->status_change(src, status->get_sc_icon(SC_POSTDELAY), status->get_sc_relevant_bl_types(SC_POSTDELAY), 1, skill->delay_fix(src, spell_skill_id, spell_skill_lv), 0, 0, 0); cooldown = skill->get_cooldown(spell_skill_id, spell_skill_lv); for (i = 0; i < ARRAYLENGTH(sd->skillcooldown) && sd->skillcooldown[i].id; i++) { @@ -5768,7 +5782,7 @@ static int skill_castend_id(int tid, int64 tick, int id, intptr_t data) skill->blockpc_start(sd, ud->skill_id, cooldown); } if( battle_config.display_status_timers && sd ) - clif->status_change(src, SI_POSTDELAY, 1, skill->delay_fix(src, ud->skill_id, ud->skill_lv), 0, 0, 0); + clif->status_change(src, status->get_sc_icon(SC_POSTDELAY), status->get_sc_relevant_bl_types(SC_POSTDELAY), 1, skill->delay_fix(src, ud->skill_id, ud->skill_lv), 0, 0, 0); if( sd ) { switch( ud->skill_id ) @@ -5843,7 +5857,7 @@ static int skill_castend_id(int tid, int64 tick, int id, intptr_t data) //When Asura fails... (except when it fails from Fog of Wall) //Consume SP/spheres skill->consume_requirement(sd,ud->skill_id, ud->skill_lv,1); - status->set_sp(src, 0, 0); + status->set_sp(src, 0, STATUS_HEAL_DEFAULT); sc = &sd->sc; if (sc->count) { //End states @@ -6126,7 +6140,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * clif->skill_nodamage (src, bl, skill_id, heal, 1); if( tsc && tsc->data[SC_AKAITSUKI] && heal && skill_id != HLIF_HEAL ) heal = ~heal + 1; - heal_get_jobexp = status->heal(bl,heal,0,0); + heal_get_jobexp = status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT); if(sd && dstsd && heal > 0 && sd != dstsd && battle_config.heal_exp > 0){ heal_get_jobexp = heal_get_jobexp * battle_config.heal_exp / 100; @@ -6159,8 +6173,8 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * clif->updatestatus(sd,SP_BASEEXP); clif->updatestatus(sd,SP_JOBEXP); } - status->set_hp(src, 1, 0); - status->set_sp(src, 0, 0); + status->set_hp(src, 1, STATUS_HEAL_DEFAULT); + status->set_sp(src, 0, STATUS_HEAL_DEFAULT); break; } else if (status->isdead(bl) && flag&1) { //Revive skill->area_temp[0]++; //Count it in, then fall-through to the Resurrection code. @@ -6333,7 +6347,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * break; case SA_INSTANTDEATH: clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - status->set_hp(bl,1,0); + status->set_hp(bl, 1, STATUS_HEAL_DEFAULT); break; case SA_QUESTION: case SA_GRAVITY: @@ -6516,10 +6530,6 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * clif->skill_nodamage (src,src,skill_id,skill_lv,1); // Initiate 10% of your damage becomes fire element. sc_start4(src,src,SC_SUB_WEAPONPROPERTY,100,3,20,0,0,skill->get_time2(skill_id, skill_lv)); - if( sd ) - skill->blockpc_start(sd, skill_id, skill->get_time(skill_id, skill_lv)); - else if( bl->type == BL_MER ) - skill->blockmerc_start(BL_UCAST(BL_MER, bl), skill_id, skill->get_time(skill_id, skill_lv)); break; case TK_JUMPKICK: @@ -6911,7 +6921,8 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * if (dstsd && dstsd->charm_type != CHARM_TYPE_NONE && dstsd->charm_count > 0) { pc->del_charm(dstsd, dstsd->charm_count, dstsd->charm_type); } - if (sp) status->heal(src, 0, sp, 3); + if (sp != 0) + status->heal(src, 0, sp, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT); clif->skill_nodamage(src,bl,skill_id,skill_lv,sp?1:0); } break; @@ -7190,7 +7201,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * // custom hack to make the mob display the skill, because these skills don't show the skill use text themselves //NOTE: mobs don't have the sprite animation that is used when performing this skill (will cause glitches) char temp[70]; - snprintf(temp, sizeof(temp), "%s : %s !!", md->name, skill->get_desc(skill_id)); + snprintf(temp, sizeof(temp), msg_txt(882), md->name, skill->get_desc(skill_id)); // %s : %s !! clif->disp_overhead(&md->bl, temp, AREA_CHAT_WOC, NULL); } break; @@ -7273,7 +7284,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * case NV_FIRSTAID: clif->skill_nodamage(src,bl,skill_id,5,1); - status->heal(bl,5,0,0); + status->heal(bl, 5, 0, STATUS_HEAL_DEFAULT); break; case AL_CURE: @@ -7350,7 +7361,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * case MER_SCAPEGOAT: if( mer && mer->master ) { - status->heal(&mer->master->bl, mer->battle_status.hp, 0, 2); + status->heal(&mer->master->bl, mer->battle_status.hp, 0, STATUS_HEAL_SHOWEFFECT); status->damage(src, src, mer->battle_status.max_hp, 0, 0, 1); } break; @@ -7667,7 +7678,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * if( tsc && tsc->data[SC_EXTREMITYFIST2] ) sp = 0; #endif - status->heal(bl,(int)hp,sp,0); + status->heal(bl, (int)hp, sp, STATUS_HEAL_DEFAULT); } break; case AM_CP_WEAPON: @@ -7842,7 +7853,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * sp = skill->get_sp(skill_id,skill_lv); sp = sp * tsc->data[SC_MAGICROD]->val2 / 100; if(sp < 1) sp = 1; - status->heal(bl,0,sp,2); + status->heal(bl, 0, sp, STATUS_HEAL_SHOWEFFECT); status_percent_damage(bl, src, 0, -20, false); //20% max SP damage. } else { struct unit_data *ud = unit->bl2ud(bl); @@ -7874,14 +7885,15 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * if (sp) //Recover some of the SP used sp = sp*(25*(skill_lv-1))/100; - if(hp || sp) - status->heal(src, hp, sp, 2); + if (hp != 0 || sp != 0) + status->heal(src, hp, sp, STATUS_HEAL_SHOWEFFECT); } } break; case SA_MAGICROD: - clif->skill_nodamage(src,src,SA_MAGICROD,skill_lv,1); - sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + if (battle->bc->magicrod_type == 0) + clif->skill_nodamage(src, src, SA_MAGICROD, skill_lv, 1); // Animation used here in official [Wolfie] + sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); break; case SA_AUTOSPELL: clif->skill_nodamage(src,bl,skill_id,skill_lv,1); @@ -8118,14 +8130,14 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * { int hp_rate = skill_lv == 0 ? 0 : skill->get_hp_rate(skill_id, skill_lv); int gain_hp = tstatus->max_hp*abs(hp_rate)/100; // The earned is the same % of the target HP than it cost the caster. [Skotlex] - clif->skill_nodamage(src,bl,skill_id,status->heal(bl, gain_hp, 0, 0),1); + clif->skill_nodamage(src, bl, skill_id, status->heal(bl, gain_hp, 0, STATUS_HEAL_DEFAULT), 1); } break; case WE_FEMALE: { int sp_rate = skill_lv == 0 ? 0 : skill->get_sp_rate(skill_id, skill_lv); int gain_sp = tstatus->max_sp*abs(sp_rate)/100;// The earned is the same % of the target SP than it cost the caster. [Skotlex] - clif->skill_nodamage(src,bl,skill_id,status->heal(bl, 0, gain_sp, 0),1); + clif->skill_nodamage(src, bl, skill_id, status->heal(bl, 0, gain_sp, STATUS_HEAL_DEFAULT), 1); } break; @@ -8165,7 +8177,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * break; } clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); - status->heal(bl,0,sp,2); + status->heal(bl, 0, sp, STATUS_HEAL_SHOWEFFECT); } break; @@ -8320,7 +8332,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * } dstmd->state.soul_change_flag = 1; sp2 = sstatus->max_sp * 3 /100; - status->heal(src, 0, sp2, 2); + status->heal(src, 0, sp2, STATUS_HEAL_SHOWEFFECT); clif->skill_nodamage(src,bl,skill_id,skill_lv,1); break; } @@ -8332,8 +8344,8 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * if( tsc && tsc->data[SC_EXTREMITYFIST2] ) sp1 = tstatus->sp; #endif // RENEWAL - status->set_sp(src, sp2, 3); - status->set_sp(bl, sp1, 3); + status->set_sp(src, sp2, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT); + status->set_sp(bl, sp1, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT); clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } break; @@ -8371,7 +8383,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * clif->skill_nodamage(NULL,bl,AL_HEAL,hp,1); if(sp > 0) clif->skill_nodamage(NULL,bl,MG_SRECOVERY,sp,1); - status->heal(bl,hp,sp,0); + status->heal(bl, hp, sp, STATUS_HEAL_DEFAULT); } break; // Full Chemical Protection @@ -8451,7 +8463,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * status_fix_damage(src, bl, 1000, 0); clif->damage(src,bl,0,0,1000,0,BDT_NORMAL,0); if( !status->isdead(bl) ) { - int where[] = { EQP_ARMOR, EQP_SHIELD, EQP_HELM, EQP_SHOES, EQP_GARMENT }; + int where[] = {EQP_ARMOR, EQP_SHIELD, EQP_HELM}; skill->break_equip(bl, where[rnd() % ARRAYLENGTH(where)], 10000, BCT_ENEMY); } } @@ -8460,7 +8472,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * sc_start(src,bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); break; case 5: // 2000HP heal, random teleported - status->heal(src, 2000, 0, 0); + status->heal(src, 2000, 0, STATUS_HEAL_DEFAULT); if( !map_flag_vs(bl->m) ) unit->warp(bl, -1,-1,-1, CLR_TELEPORT); break; @@ -8694,7 +8706,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * case AM_REST: if (sd) { - if (homun->vaporize(sd,HOM_ST_REST)) + if (homun->vaporize(sd, HOM_ST_REST, false)) clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); else clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0, 0); @@ -8742,19 +8754,27 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * int r = rnd()%100; int target = (skill_lv-1)%5; int hp; - if(r<per[target][0]) //Self + if (r < per[target][0]) { //Self bl = src; - else if(r<per[target][1]) //Master + } else if (r < per[target][1]) { //Master bl = battle->get_master(src); - else //Enemy - bl = map->id2bl(battle->get_target(src)); + } else if ((per[target][1] - per[target][0]) < per[target][0] + && bl == battle->get_master(src)) { + /** + * Skill rolled for enemy, but there's nothing the Homunculus is attacking. + * So bl has been set to its master in unit->skilluse_id2. + * If it's more likely that it will heal itself, + * we let it heal itself. + */ + bl = src; + } if (!bl) bl = src; hp = skill->calc_heal(src, bl, skill_id, 1+rnd()%skill_lv, true); //Eh? why double skill packet? clif->skill_nodamage(src,bl,AL_HEAL,hp,1); clif->skill_nodamage(src,bl,skill_id,hp,1); - status->heal(bl, hp, 0, 0); + status->heal(bl, hp, 0, STATUS_HEAL_DEFAULT); } break; // Homun single-target support skills [orn] @@ -8901,7 +8921,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * int heal = status_get_max_hp(bl) * 25 / 100; clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - status->heal(bl,heal,0,1); + status->heal(bl, heal, 0, STATUS_HEAL_FORCED); status->change_clear_buffs(bl,4); } break; @@ -8955,7 +8975,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * value = status_get_max_hp(bl) * 25 / 100; status->change_clear_buffs(bl,4); skill->area_temp[5] &= ~0x20; - status->heal(bl,value,0,1); + status->heal(bl, value, 0, STATUS_HEAL_FORCED); type = SC_REFRESH; }else if( skill->area_temp[5]&0x40 ){ skill->area_temp[5] &= ~0x40; @@ -9140,7 +9160,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * clif->skill_nodamage(bl, bl, skill_id, heal, 1); if( tsc && tsc->data[SC_AKAITSUKI] && heal ) heal = ~heal + 1; - status->heal(bl, heal, 0, 1); + status->heal(bl, heal, 0, STATUS_HEAL_FORCED); } } else if( sd ) party->foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); @@ -9416,7 +9436,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * pc->setmadogear(sd, false); clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); skill->castend_damage_id(src, src, skill_id, skill_lv, tick, flag); - status->set_sp(src, 0, 0); + status->set_sp(src, 0, STATUS_HEAL_DEFAULT); } break; @@ -9455,7 +9475,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * case 5: hp = 23; break; } heal = tstatus->max_hp * hp / 100; - status->heal(bl,heal,0,2); + status->heal(bl, heal, 0, STATUS_HEAL_SHOWEFFECT); clif->skill_nodamage(src, bl, skill_id, skill_lv, heal); } break; @@ -9533,7 +9553,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * int sp = 100 * skill_lv; if( dstmd ) sp = dstmd->level * 2; if( status_zap(bl,0,sp) ) - status->heal(src,0,sp/2,3);//What does flag 3 do? [Rytech] + status->heal(src, 0, sp / 2, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT); } if ( tsc && tsc->data[SC__UNLUCKY] && skill_id == SC_UNLUCKY) { //If the target was successfully inflected with the Unlucky status, give 1 of 3 random status's. @@ -9657,7 +9677,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * case 3: sc_start(src, bl, SC_SHIELDSPELL_REF, 100, opt, INFINITE_DURATION); // HP Recovery val = sstatus->max_hp * ((status->get_lv(src) / 10) + (shield->refine + 1)) / 100; - status->heal(bl, val, 0, 2); + status->heal(bl, val, 0, STATUS_HEAL_SHOWEFFECT); status_change_end(bl,SC_SHIELDSPELL_REF,INVALID_TIMER); break; } @@ -9800,7 +9820,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * } heal = 120 * skill_lv + status_get_max_hp(bl) * (2 + skill_lv) / 100; - status->heal(bl, heal, 0, 0); + status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT); if( (tsc && tsc->opt1) && (rnd()%100 < ((skill_lv * 5) + (status_get_dex(src) + status->get_lv(src)) / 4) - (1 + (rnd() % 10))) ) { status_change_end(bl, SC_STONE, INVALID_TIMER); @@ -9871,7 +9891,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * heal = 1; status->fixed_revive(bl, heal, 0); clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - status->set_sp(bl, 0, 0); + status->set_sp(bl, 0, STATUS_HEAL_DEFAULT); } } break; @@ -10208,7 +10228,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * } e_hp = ed->battle_status.max_hp * 10 / 100; e_sp = ed->battle_status.max_sp * 10 / 100; - status->heal(&ed->bl,e_hp,e_sp,3); + status->heal(&ed->bl, e_hp, e_sp, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT); clif->skill_nodamage(src,&ed->bl,skill_id,skill_lv,1); } break; @@ -10518,7 +10538,7 @@ static int skill_castend_nodamage_id(struct block_list *src, struct block_list * } } heal = 5 * status->get_lv(&hd->bl) + status->base_matk(&hd->bl, &hd->battle_status, status->get_lv(&hd->bl)); - status->heal(bl, heal, 0, 0); + status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT); clif->skill_nodamage(src, src, skill_id, skill_lv, clif->skill_nodamage(src, bl, AL_HEAL, heal, 1)); status->change_start(src, src, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE); status->change_start(src, bl, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE); @@ -10763,7 +10783,7 @@ static int skill_castend_pos(int tid, int64 tick, int id, intptr_t data) skill->blockpc_start(sd, ud->skill_id, cooldown); } if( battle_config.display_status_timers && sd ) - clif->status_change(src, SI_POSTDELAY, 1, skill->delay_fix(src, ud->skill_id, ud->skill_lv), 0, 0, 0); + clif->status_change(src, status->get_sc_icon(SC_POSTDELAY), status->get_sc_relevant_bl_types(SC_POSTDELAY), 1, skill->delay_fix(src, ud->skill_id, ud->skill_lv), 0, 0, 0); #if 0 if (sd) { switch (ud->skill_id) { @@ -11040,9 +11060,10 @@ static int skill_castend_pos2(struct block_list *src, int x, int y, uint16 skill map->foreachinarea(status->change_timer_sub, src->m, x-r, y-r, x+r,y+r,BL_CHAR, src,NULL,SC_SIGHT,tick); - if(battle_config.traps_setting&1) - map->foreachinarea(skill_reveal_trap, - src->m, x-r, y-r, x+r, y+r, BL_SKILL); + if (battle_config.trap_visibility != 0) { + map->foreachinarea(skill_reveal_trap, + src->m, x - r, y - r, x + r, y + r, BL_SKILL); + } break; case SR_RIDEINLIGHTNING: @@ -12644,7 +12665,7 @@ static int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int if (sg->src_id == bl->id) break; //Does not affect the caster. clif->changetraplook(&src->bl,UNT_USED_TRAPS); - map->foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick); + skill->trap_do_splash(&src->bl, sg->skill_id, sg->skill_lv, sg->bl_flag, tick); sg->unit_id = UNT_USED_TRAPS; sg->limit = DIFF_TICK32(tick,sg->tick) + 1500; break; @@ -12759,6 +12780,13 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b ts->tick += sg->interval*(map->count_oncell(bl->m,bl->x,bl->y,BL_CHAR,0)-1); } + if (sg->skill_id == HT_ANKLESNARE + || (battle_config.trap_trigger == 1 && skill->get_inf2(sg->skill_id) & INF2_HIDDEN_TRAP) + ) { + src->visible = true; + clif->skillunit_update(&src->bl); + } + switch (sg->unit_id) { case UNT_FIREWALL: case UNT_KAEN: { @@ -12800,7 +12828,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); if (tsc && tsc->data[SC_AKAITSUKI] && heal) heal = ~heal + 1; - status->heal(bl, heal, 0, 0); + status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT); if (diff >= 500) sg->val1--; } @@ -12821,7 +12849,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b if (status->isimmune(bl)) heal = 0; clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); - status->heal(bl, heal, 0, 0); + status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT); } break; @@ -12911,10 +12939,11 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b clif->fixpos(bl); } sg->val2 = bl->id; - } else + } else { sec = 3000; //Couldn't trap it? + } + if( sg->unit_id == UNT_ANKLESNARE ) { - clif->skillunit_update(&src->bl); /** * If you're snared from a trap that was invisible this makes the trap be * visible again -- being you stepped on it (w/o this the trap remains invisible and you go "WTF WHY I CANT MOVE") @@ -12938,7 +12967,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b } - map->foreachinrange(skill->trap_splash, &src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl, tick); + skill->trap_do_splash(&src->bl, sg->skill_id, sg->skill_lv, sg->bl_flag, tick); sg->unit_id = UNT_USED_TRAPS; //Changed ID so it does not invoke a for each in area again. } break; @@ -12969,10 +12998,10 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b case UNT_FREEZINGTRAP: case UNT_FIREPILLAR_ACTIVE: case UNT_CLAYMORETRAP: - if( sg->unit_id == UNT_FIRINGTRAP || sg->unit_id == UNT_ICEBOUNDTRAP || sg->unit_id == UNT_CLAYMORETRAP ) - map->foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag|BL_SKILL|~BCT_SELF, &src->bl,tick); + if (sg->unit_id == UNT_FIRINGTRAP || sg->unit_id == UNT_ICEBOUNDTRAP || sg->unit_id == UNT_CLAYMORETRAP) + skill->trap_do_splash(&src->bl, sg->skill_id, sg->skill_lv, sg->bl_flag | BL_SKILL | ~BCT_SELF, tick); else - map->foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick); + skill->trap_do_splash(&src->bl, sg->skill_id, sg->skill_lv, sg->bl_flag, tick); if (sg->unit_id != UNT_FIREPILLAR_ACTIVE) clif->changetraplook(&src->bl, sg->unit_id==UNT_LANDMINE?UNT_FIREPILLAR_ACTIVE:UNT_USED_TRAPS); sg->limit=DIFF_TICK32(tick,sg->tick)+1500 + @@ -13032,7 +13061,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b if( tsc && tsc->data[SC_AKAITSUKI] && heal ) heal = ~heal + 1; clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); - status->heal(bl, heal, 0, 0); + status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT); } } break; @@ -13086,7 +13115,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b case 0: // Heal 1~9999 HP heal = rnd() %9999+1; clif->skill_nodamage(ss,bl,AL_HEAL,heal,1); - status->heal(bl,heal,0,0); + status->heal(bl, heal, 0, STATUS_HEAL_DEFAULT); break; case 1: // End all negative status status->change_clear_buffs(bl,2); @@ -13203,9 +13232,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b case UNT_GROUNDDRIFT_POISON: case UNT_GROUNDDRIFT_WATER: case UNT_GROUNDDRIFT_FIRE: - map->foreachinrange(skill->trap_splash,&src->bl, - skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, - &src->bl,tick); + skill->trap_do_splash(&src->bl, sg->skill_id, sg->skill_lv, sg->bl_flag, tick); sg->unit_id = UNT_USED_TRAPS; //clif->changetraplook(&src->bl, UNT_FIREPILLAR_ACTIVE); sg->limit=DIFF_TICK32(tick,sg->tick)+1500; @@ -13233,7 +13260,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b } hp = tstatus->max_hp * hp / 100; sp = tstatus->max_sp * sp / 100; - status->heal(bl, hp, sp, 2); + status->heal(bl, hp, sp, STATUS_HEAL_SHOWEFFECT); sc_start(ss, bl, type, 100, sg->skill_lv, (sg->interval * 3) + 100); } // Reveal hidden players every 5 seconds. @@ -13266,7 +13293,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b case UNT_REVERBERATION: clif->changetraplook(&src->bl,UNT_USED_TRAPS); - map->foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick); + skill->trap_do_splash(&src->bl, sg->skill_id, sg->skill_lv, sg->bl_flag, tick); sg->limit = DIFF_TICK32(tick,sg->tick)+1500; sg->unit_id = UNT_USED_TRAPS; break; @@ -13355,7 +13382,7 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b clif->skill_nodamage(&src->bl, bl, AL_HEAL, hp, 0); if( tsc && tsc->data[SC_AKAITSUKI] && hp ) hp = ~hp + 1; - status->heal(bl, hp, 0, 0); + status->heal(bl, hp, 0, STATUS_HEAL_DEFAULT); sc_start(ss, bl, type, 100, sg->skill_lv, sg->interval + 100); } break; @@ -13369,13 +13396,13 @@ static int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *b int hp = tstatus->max_hp / 100; //+1% each 5s if ((sg->val3) % 5) { //each 5s if (tstatus->def_ele == skill->get_ele(sg->skill_id,sg->skill_lv)) { - status->heal(bl, hp, 0, 2); + status->heal(bl, hp, 0, STATUS_HEAL_SHOWEFFECT); } else if( (sg->unit_id == UNT_FIRE_INSIGNIA && tstatus->def_ele == ELE_EARTH) || (sg->unit_id == UNT_WATER_INSIGNIA && tstatus->def_ele == ELE_FIRE) || (sg->unit_id == UNT_WIND_INSIGNIA && tstatus->def_ele == ELE_WATER) || (sg->unit_id == UNT_EARTH_INSIGNIA && tstatus->def_ele == ELE_WIND) ) { - status->heal(bl, -hp, 0, 0); + status->heal(bl, -hp, 0, STATUS_HEAL_DEFAULT); } } sg->val3++; //timer @@ -13935,27 +13962,9 @@ static int skill_isammotype(struct map_session_data *sd, int skill_id) **/ static bool skill_is_combo(int skill_id) { - switch( skill_id ) - { - case MO_CHAINCOMBO: - case MO_COMBOFINISH: - case CH_TIGERFIST: - case CH_CHAINCRUSH: - case MO_EXTREMITYFIST: - case TK_TURNKICK: - case TK_STORMKICK: - case TK_DOWNKICK: - case TK_COUNTER: - case TK_JUMPKICK: - case HT_POWER: - case GC_COUNTERSLASH: - case GC_WEAPONCRUSH: - case SR_FALLENEMPIRE: - case SR_DRAGONCOMBO: - case SR_TIGERCANNON: - case SR_GATEOFHELL: - return true; - } + if (skill->get_inf2(skill_id) & INF2_IS_COMBO_SKILL) + return true; + return false; } @@ -14491,8 +14500,8 @@ static int skill_check_condition_castbegin(struct map_session_data *sd, uint16 s **/ case AB_ANCILLA: { - int count = 0, i; - for( i = 0; i < MAX_INVENTORY; i ++ ) + int count = 0; + for (int i = 0; i < sd->status.inventorySize; i ++) if (sd->status.inventory[i].nameid == ITEMID_ANSILA) count += sd->status.inventory[i].amount; if( count >= 3 ) { @@ -14646,7 +14655,7 @@ static int skill_check_condition_castbegin(struct map_session_data *sd, uint16 s if (map->foreachinrange(mob->count_sub, &sd->bl, skill->get_splash(skill_id, skill_lv), BL_MOB, MOBID_EMPELIUM, MOBID_S_EMPEL_1, MOBID_S_EMPEL_2)) { char output[128]; - sprintf(output, "You're too close to a stone or emperium to do this skill"); /* TODO official response? or message.conf it */ + sprintf(output, "%s", msg_txt(883)); /* TODO official response */ // You are too close to a stone or emperium to do this skill clif->messagecolor_self(sd->fd, COLOR_RED, output); return 0; } @@ -15093,7 +15102,7 @@ static int skill_check_condition_castend(struct map_session_data *sd, uint16 ski return 0; } else if( sd->status.inventory[i].amount < require.ammo_qty ) { char e_msg[100]; - sprintf(e_msg,"Skill Failed. [%s] requires %dx %s.", + sprintf(e_msg, msg_txt(884), // Skill Failed. [%s] requires %dx %s. skill->get_desc(skill_id), require.ammo_qty, itemdb_jname(sd->status.inventory[i].nameid)); @@ -16110,7 +16119,7 @@ static void skill_repairweapon(struct map_session_data *sd, int idx) if (idx == 0xFFFF || idx == -1) // No item selected ('Cancel' clicked) return; - if( idx < 0 || idx >= MAX_INVENTORY ) + if (idx < 0 || idx >= sd->status.inventorySize) return; //Invalid index?? item = &target_sd->status.inventory[idx]; @@ -16158,7 +16167,7 @@ static void skill_identify(struct map_session_data *sd, int idx) nullpo_retv(sd); sd->state.workinprogress = 0; - if(idx >= 0 && idx < MAX_INVENTORY) { + if (idx >= 0 && idx < sd->status.inventorySize) { if(sd->status.inventory[idx].nameid > 0 && sd->status.inventory[idx].identify == 0 ){ flag=0; sd->status.inventory[idx].identify=1; @@ -16174,7 +16183,7 @@ static void skill_weaponrefine(struct map_session_data *sd, int idx) { nullpo_retv(sd); - if (idx >= 0 && idx < MAX_INVENTORY) { + if (idx >= 0 && idx < sd->status.inventorySize) { struct item *item; struct item_data *ditem = sd->inventory_data[idx]; item = &sd->status.inventory[idx]; @@ -16202,7 +16211,7 @@ static void skill_weaponrefine(struct map_session_data *sd, int idx) return; } - per = status->get_refine_chance(ditem->wlv, (int)item->refine, REFINE_CHANCE_TYPE_NORMAL) * 10; + per = refine->get_refine_chance(ditem->wlv, (int)item->refine, REFINE_CHANCE_TYPE_NORMAL) * 10; // Aegis leaked formula. [malufett] if (sd->status.class == JOB_MECHANIC_T) @@ -16386,9 +16395,9 @@ static int skill_sit(struct map_session_data *sd, int type) } if( type ) { - clif->sc_load(&sd->bl,sd->bl.id,SELF,SI_SIT,0,0,0); + clif->sc_load(&sd->bl, sd->bl.id, SELF, status->get_sc_icon(SC_SIT), 0, 0, 0); } else { - clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_SIT); + clif->sc_end(&sd->bl, sd->bl.id, SELF, status->get_sc_icon(SC_SIT)); } if (!flag) return 0; @@ -16630,10 +16639,10 @@ static int skill_detonator(struct block_list *bl, va_list ap) case UNT_CLAYMORETRAP: case UNT_FIRINGTRAP: case UNT_ICEBOUNDTRAP: - map->foreachinrange(skill->trap_splash,bl,skill->get_splash(su->group->skill_id,su->group->skill_lv),su->group->bl_flag|BL_SKILL|~BCT_SELF,bl,su->group->tick); + skill->trap_do_splash(bl, su->group->skill_id, su->group->skill_lv, su->group->bl_flag | BL_SKILL | ~BCT_SELF, su->group->tick); break; default: - map->foreachinrange(skill->trap_splash,bl,skill->get_splash(su->group->skill_id,su->group->skill_lv),su->group->bl_flag,bl,su->group->tick); + skill->trap_do_splash(bl, su->group->skill_id, su->group->skill_lv, su->group->bl_flag, su->group->tick); } clif->changetraplook(bl, UNT_USED_TRAPS); su->group->limit = DIFF_TICK32(timer->gettick(),su->group->tick) + @@ -16766,6 +16775,27 @@ static int skill_chastle_mob_changetarget(struct block_list *bl, va_list ap) return 0; } +/** + * Does final adjustments (e.g. count enemies affected by splash) then runs trap splash function (skill_trap_splash). + * + * @param bl : trap skill unit's bl + * @param skill_id : Trap Skill ID + * @param skill_lv : Trap Skill Level + * @param bl_flag : Flag representing units affected by this trap + * @param tick : tick related to this trap + */ +static void skill_trap_do_splash(struct block_list *bl, uint16 skill_id, uint16 skill_lv, int bl_flag, int64 tick) +{ + int enemy_count = 0; + + if (skill->get_nk(skill_id) & NK_SPLASHSPLIT) { + enemy_count = map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR, bl, skill_id, skill_lv, tick, BCT_ENEMY, skill->area_sub_count); + enemy_count = max(1, enemy_count); // Don't let enemy_count be 0 when spliting trap damage + } + + map->foreachinrange(skill->trap_splash, bl, skill->get_splash(skill_id, skill_lv), bl_flag, bl, tick, enemy_count); +} + /*========================================== * *------------------------------------------*/ @@ -16776,6 +16806,7 @@ static int skill_trap_splash(struct block_list *bl, va_list ap) struct skill_unit *src_su = NULL; struct skill_unit_group *sg; struct block_list *ss; + int enemy_count = va_arg(ap, int); nullpo_ret(bl); nullpo_ret(src); @@ -16870,7 +16901,7 @@ static int skill_trap_splash(struct block_list *bl, va_list ap) } /* Fall through */ default: - skill->attack(skill->get_type(sg->skill_id),ss,src,bl,sg->skill_id,sg->skill_lv,tick,0); + skill->attack(skill->get_type(sg->skill_id), ss, src, bl, sg->skill_id, sg->skill_lv, tick, enemy_count); break; } return 1; @@ -17051,6 +17082,14 @@ static struct skill_unit *skill_initunit(struct skill_unit_group *group, int idx su->val1=val1; su->val2 = val2; su->prev = 0; + su->visible = true; + + if (skill->get_inf2(group->skill_id) & INF2_HIDDEN_TRAP + && ((battle_config.trap_visibility == 1 && map_flag_vs(group->map)) // invisible in PvP/GvG + || battle_config.trap_visibility == 2 // always invisible + )) { + su->visible = false; + } idb_put(skill->unit_db, su->bl.id, su); map->addiddb(&su->bl); @@ -17585,7 +17624,7 @@ static int skill_unit_timer_sub(union DBKey key, struct DBData *data, va_list ap break; } clif->changetraplook(bl,UNT_USED_TRAPS); - map->foreachinrange(skill->trap_splash, bl, skill->get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick); + skill->trap_do_splash(bl, group->skill_id, group->skill_lv, group->bl_flag, tick); group->limit = DIFF_TICK32(tick,group->tick)+1500; su->limit = DIFF_TICK32(tick,group->tick)+1500; group->unit_id = UNT_USED_TRAPS; @@ -17971,8 +18010,8 @@ static int skill_can_produce_mix(struct map_session_data *sd, int nameid, int tr if (pc->search_inventory(sd,id) == INDEX_NOT_FOUND) return 0; } else { - int x, y; - for(y=0,x=0;y<MAX_INVENTORY;y++) + int x = 0; + for (int y = 0; y < sd->status.inventorySize; y++) if( sd->status.inventory[y].nameid == id ) x+=sd->status.inventory[y].amount; if(x<qty*skill->dbs->produce_db[i].mat_amount[j]) @@ -18043,7 +18082,7 @@ static int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int n else temp_qty = 1; if (data->stack.inventory) { - for( i = 0; i < MAX_INVENTORY; i++ ) { + for (i = 0; i < sd->status.inventorySize; i++ ) { if( sd->status.inventory[i].nameid == nameid ) { if( sd->status.inventory[i].amount >= data->stack.amount ) { #if PACKETVER >= 20090729 @@ -18851,7 +18890,7 @@ static int skill_elementalanalysis(struct map_session_data *sd, uint16 skill_lv, del_amount -= (del_amount % 10); add_amount = (skill_lv == 1) ? del_amount * (5 + rnd()%5) : del_amount / 10 ; - if (idx < 0 || idx >= MAX_INVENTORY + if (idx < 0 || idx >= sd->status.inventorySize || (nameid = sd->status.inventory[idx].nameid) <= 0 || del_amount < 0 || del_amount > sd->status.inventory[idx].amount) { clif->skill_fail(sd, SO_EL_ANALYSIS, USESKILL_FAIL_LEVEL, 0, 0); @@ -18922,7 +18961,7 @@ static int skill_changematerial(struct map_session_data *sd, const struct itemli for (k = 0; k < VECTOR_LENGTH(*item_list); k++) { const struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, k); int idx = entry->id; - Assert_ret(idx >= 0 && idx < MAX_INVENTORY); + Assert_ret(idx >= 0 && idx < sd->status.inventorySize); amount = entry->amount; nameid = sd->status.inventory[idx].nameid; if (nameid > 0 && sd->status.inventory[idx].identify == 0) { @@ -18973,7 +19012,7 @@ static int skill_destroy_trap(struct block_list *bl, va_list ap) case UNT_CLAYMORETRAP: case UNT_FIRINGTRAP: case UNT_ICEBOUNDTRAP: - map->foreachinrange(skill->trap_splash,&su->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag|BL_SKILL|~BCT_SELF, &su->bl,tick); + skill->trap_do_splash(&su->bl, sg->skill_id, sg->skill_lv, sg->bl_flag | BL_SKILL | ~BCT_SELF, tick); break; case UNT_LANDMINE: case UNT_BLASTMINE: @@ -18982,7 +19021,7 @@ static int skill_destroy_trap(struct block_list *bl, va_list ap) case UNT_FLASHER: case UNT_FREEZINGTRAP: case UNT_CLUSTERBOMB: - map->foreachinrange(skill->trap_splash,&su->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &su->bl,tick); + skill->trap_do_splash(&su->bl, sg->skill_id, sg->skill_lv, sg->bl_flag, tick); break; } // Traps aren't recovered. @@ -19719,23 +19758,23 @@ static int skill_get_elemental_type(uint16 skill_id, uint16 skill_lv) static void skill_cooldown_save(struct map_session_data *sd) { int i; - struct skill_cd* cd = NULL; + struct skill_cd *cd = NULL; int64 now = 0; - // always check to make sure the session properly exists nullpo_retv(sd); - if( !(cd = idb_get(skill->cd_db, sd->status.char_id)) ) {// no skill cooldown is associated with this character + if ((cd = idb_get(skill->cd_db, sd->status.char_id)) == NULL) return; - } now = timer->gettick(); - // process each individual cooldown associated with the character - for( i = 0; i < cd->cursor; i++ ) { - cd->entry[i]->duration = DIFF_TICK32(cd->entry[i]->started+cd->entry[i]->duration,now); - if( cd->entry[i]->timer != INVALID_TIMER ) { - timer->delete(cd->entry[i]->timer,skill->blockpc_end); + for (i = 0; i < cd->cursor; i++) { + if (battle_config.guild_skill_relog_delay == 1 && cd->entry[i]->skill_id > GD_SKILLBASE && cd->entry[i]->skill_id < GD_MAX) + continue; + + cd->entry[i]->duration = DIFF_TICK32(cd->entry[i]->started + cd->entry[i]->duration, now); + if (cd->entry[i]->timer != INVALID_TIMER) { + timer->delete(cd->entry[i]->timer, skill->blockpc_end); cd->entry[i]->timer = INVALID_TIMER; } } @@ -20216,6 +20255,18 @@ static void skill_validate_skillinfo(struct config_setting_t *conf, struct s_ski } else { sk->inf2 &= ~INF2_ALLOW_REPRODUCE; } + } else if (strcmpi(type, "HiddenTrap") == 0) { + if (on) { + sk->inf2 |= INF2_HIDDEN_TRAP; + } else { + sk->inf2 &= ~INF2_HIDDEN_TRAP; + } + } else if (strcmpi(type, "IsCombo") == 0) { + if (on) { + sk->inf2 |= INF2_IS_COMBO_SKILL; + } else { + sk->inf2 &= ~INF2_IS_COMBO_SKILL; + } } else if (strcmpi(type, "None") != 0) { skilldb_invalid_error(type, config_setting_name(t), sk->nameid); } @@ -21046,7 +21097,7 @@ static bool skill_read_skilldb(const char *filename) nullpo_retr(false, filename); - sprintf(filepath,"db/%s",filename); + libconfig->format_db_path(filename, filepath, sizeof(filepath)); if (!libconfig->load_file(&skilldb, filepath)) { return false; // Libconfig error report. @@ -21578,6 +21629,7 @@ void skill_defaults(void) skill->onskillusage = skill_onskillusage; skill->cell_overlap = skill_cell_overlap; skill->timerskill = skill_timerskill; + skill->trap_do_splash = skill_trap_do_splash; skill->trap_splash = skill_trap_splash; skill->check_condition_mercenary = skill_check_condition_mercenary; skill->locate_element_field = skill_locate_element_field; |