diff options
Diffstat (limited to 'src/map/skill.c')
-rw-r--r-- | src/map/skill.c | 205 |
1 files changed, 144 insertions, 61 deletions
diff --git a/src/map/skill.c b/src/map/skill.c index 4daf3f753..36a509876 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -460,7 +460,7 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd) return 1; } - if (sd->blockskill[idx] > 0) { + if (sd->blockskill[idx]) { clif->skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0); return 1; } @@ -1139,12 +1139,12 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 sc_start4(bl,SC_BURNING,100,skill_lv,0,src->id,0,skill->get_time2(skill_id,skill_lv)); break; case WL_EARTHSTRAIN: - { - // lv 1 & 2 = Strip Helm, lv 3 = Strip Armor, lv 4 = Strip Weapon and lv 5 = Strip Accessory. [malufett] - const int pos[5] = { EQP_HELM, EQP_HELM, EQP_ARMOR, EQP_WEAPON, EQP_ACC }; - skill->strip_equip(bl, pos[skill_lv], 6 * skill_lv + status->get_lv(src) / 4 + status_get_dex(src) / 10, - skill_lv, skill->get_time2(skill_id,skill_lv)); - } + { + // lv 1 & 2 = Strip Helm, lv 3 = Strip Armor, lv 4 = Strip Weapon and lv 5 = Strip Accessory. [malufett] + const int pos[5] = { EQP_HELM, EQP_HELM, EQP_ARMOR, EQP_WEAPON, EQP_ACC }; + skill->strip_equip(bl, pos[skill_lv-1], 6 * skill_lv + status->get_lv(src) / 4 + status_get_dex(src) / 10, + skill_lv, skill->get_time2(skill_id,skill_lv)); + } break; case WL_JACKFROST: sc_start(bl,SC_FREEZE,100,skill_lv,skill->get_time(skill_id,skill_lv)); @@ -2117,7 +2117,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds int type; int64 damage; int8 rmdamage=0;//magic reflected - bool additional_effects = true; + bool additional_effects = true, shadow_flag = false; if(skill_id > 0 && !skill_lv) return 0; @@ -2574,10 +2574,12 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds if (ud && DIFF_TICK(ud->attackabletime, tick + type) < 0) ud->attackabletime = tick + type; } + + shadow_flag = skill->check_shadowform(bl, damage, dmg.div_); if( !dmg.amotion ) { //Instant damage - if( !sc || (!sc->data[SC_DEVOTION] && skill_id != CR_REFLECTSHIELD) ) + if( (!sc || (!sc->data[SC_DEVOTION] && skill_id != CR_REFLECTSHIELD)) && !shadow_flag) status_fix_damage(src,bl,damage,dmg.dmotion); //Deal damage before knockback to allow stuff like firewall+storm gust combo. if( !status->isdead(bl) && additional_effects ) skill->additional_effect(src,bl,skill_id,skill_lv,dmg.flag,dmg.dmg_lv,tick); @@ -2657,8 +2659,15 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds } //Delayed damage must be dealt after the knockback (it needs to know actual position of target) - if (dmg.amotion) - battle->delay_damage(tick, dmg.amotion,src,bl,dmg.flag,skill_id,skill_lv,damage,dmg.dmg_lv,dmg.dmotion, additional_effects); + if (dmg.amotion){ + if( shadow_flag ){ + if( !status->isdead(bl) && additional_effects ) + skill->additional_effect(src,bl,skill_id,skill_lv,dmg.flag,dmg.dmg_lv,tick); + if( dmg.flag > ATK_BLOCK ) + skill->counter_additional_effect(src,bl,skill_id,skill_lv,dmg.flag,tick); + }else + battle->delay_damage(tick, dmg.amotion,src,bl,dmg.flag,skill_id,skill_lv,damage,dmg.dmg_lv,dmg.dmotion, additional_effects); + } if( sc && sc->data[SC_DEVOTION] && skill_id != PA_PRESSURE ) { struct status_change_entry *sce = sc->data[SC_DEVOTION]; @@ -3059,8 +3068,23 @@ int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) { break; // Target not on Map if(src->m != target->m) break; // Different Maps - if(status->isdead(src)) - break; // Caster is Dead + if(status->isdead(src)){ + // Exceptions + switch(skl->skill_id){ + case WL_CHAINLIGHTNING_ATK: + case WL_TETRAVORTEX_FIRE: + case WL_TETRAVORTEX_WATER: + case WL_TETRAVORTEX_WIND: + case WL_TETRAVORTEX_GROUND: + case SR_FLASHCOMBO_ATK_STEP1: + case SR_FLASHCOMBO_ATK_STEP2: + case SR_FLASHCOMBO_ATK_STEP3: + case SR_FLASHCOMBO_ATK_STEP4: + break; + default: + continue; // Caster is Dead + } + } if(status->isdead(target) && skl->skill_id != RG_INTIMIDATE && skl->skill_id != WZ_WATERBALL) break; @@ -3134,7 +3158,7 @@ int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) { if( skl->type == 4 ){ const enum sc_type scs[] = { SC_BURNING, SC_BLOODING, SC_FROSTMISTY, SC_STUN }; // status inflicts are depend on what summoned element is used. int rate = skl->y, index = skl->x-1; - sc_start2(target, scs[index], rate, skl->skill_lv, src->id, skill->get_time(WL_TETRAVORTEX,index)); + sc_start2(target, scs[index], rate, skl->skill_lv, src->id, skill->get_time(WL_TETRAVORTEX,index+1)); } break; case WM_REVERBERATION_MELEE: @@ -3285,6 +3309,17 @@ int skill_cleartimerskill (struct block_list *src) for(i=0;i<MAX_SKILLTIMERSKILL;i++) { if(ud->skilltimerskill[i]) { + switch(ud->skilltimerskill[i]->skill_id){ + case WL_TETRAVORTEX_FIRE: + case WL_TETRAVORTEX_WATER: + case WL_TETRAVORTEX_WIND: + case WL_TETRAVORTEX_GROUND: + case SR_FLASHCOMBO_ATK_STEP1: + case SR_FLASHCOMBO_ATK_STEP2: + case SR_FLASHCOMBO_ATK_STEP3: + case SR_FLASHCOMBO_ATK_STEP4: + continue; + } timer->delete(ud->skilltimerskill[i]->timer, skill->timerskill); ers_free(skill->timer_ers, ud->skilltimerskill[i]); ud->skilltimerskill[i]=NULL; @@ -4185,7 +4220,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint } } if(cooldown) - skill->blockpc_start(sd, skill_id, cooldown, false); + skill->blockpc_start(sd, skill_id, cooldown); }else if( sc ){ // Summon Balls int i = SC_SUMMON5; for(; i >= SC_SUMMON1; i--){ @@ -4734,7 +4769,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) } } if(cooldown) - skill->blockpc_start(sd, ud->skill_id, cooldown, false); + 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); @@ -4785,7 +4820,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) sc->data[SC_SOULLINK]->val3 = 0; //Clear bounced spell check. if( sc->data[SC_DANCING] && skill->get_inf2(ud->skill_id)&INF2_SONG_DANCE && sd ) - skill->blockpc_start(sd,BD_ADAPTATION,3000, false); + skill->blockpc_start(sd,BD_ADAPTATION,3000); } if( sd && ud->skill_id != SA_ABRACADABRA && ud->skill_id != WM_RANDOMIZESPELL ) // they just set the data so leave it as it is.[Inkfish] @@ -5406,7 +5441,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui // Initiate 10% of your damage becomes fire element. sc_start4(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), false); + skill->blockpc_start(sd, skill_id, skill->get_time(skill_id, skill_lv)); else if( bl->type == BL_MER ) skill->blockmerc_start((TBL_MER*)bl, skill_id, skill->get_time(skill_id, skill_lv)); break; @@ -5575,7 +5610,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); if (sd) - skill->blockpc_start (sd, skill_id, skill->get_time2(skill_id,skill_lv), false); + skill->blockpc_start (sd, skill_id, skill->get_time2(skill_id,skill_lv)); break; case ALL_ANGEL_PROTECT: @@ -7098,7 +7133,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start4(bl,type,100,skill_lv,skill_id,src->id,skill->get_time(skill_id,skill_lv),1000)); #ifndef RENEWAL - if (sd) skill->blockpc_start (sd, skill_id, skill->get_time(skill_id, skill_lv)+3000, false); + if (sd) skill->blockpc_start (sd, skill_id, skill->get_time(skill_id, skill_lv)+3000); #endif break; @@ -8873,7 +8908,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui duration = 9000; break; } - skill->blockpc_start(sd, skill_id, duration, false); + skill->blockpc_start(sd, skill_id, duration); } break; @@ -9430,7 +9465,7 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data) { } } if(cooldown) - skill->blockpc_start(sd, ud->skill_id, cooldown, false); + 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); @@ -9908,7 +9943,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui clif->skill_poseffect(src,skill_id,skill_lv,src->x,src->y,tick); #endif if (sd) - skill->blockpc_start (sd, MO_EXTREMITYFIST, 2000, false); + skill->blockpc_start (sd, MO_EXTREMITYFIST, 2000); } break; case NJ_SHADOWJUMP: @@ -15046,6 +15081,39 @@ bool skill_check_camouflage(struct block_list *bl, struct status_change_entry *s return wall; } +bool skill_check_shadowform(struct block_list *bl, int64 damage, int hit){ + struct status_change *sc; + struct block_list *src; + + nullpo_retr(false, bl); + + sc = status->get_sc(bl); + + if( sc && sc->data[SC__SHADOWFORM] && damage ) { + src = map->id2bl(sc->data[SC__SHADOWFORM]->val2); + + if( !src || src->m != bl->m ) { + status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); + return false; + } + + if( src && (status->isdead(src) || !battle->check_target(bl,src,BCT_ENEMY)) ){ + if( src->type == BL_PC ) + ((TBL_PC*)src)->shadowform_id = 0; + status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); + return false; + } + + status->damage(bl, src, damage, 0, clif->damage(src, src, timer->gettick(), 500, 500, damage, hit, (hit > 1 ? 8 : 0), 0), 0); + if( (--sc->data[SC__SHADOWFORM]->val3) <= 0 ) { + status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); + if( src->type == BL_PC ) + ((TBL_PC*)src)->shadowform_id = 0; + } + return true; + } + return false; +} /*========================================== * *------------------------------------------*/ @@ -16918,7 +16986,8 @@ int skill_blockpc_end(int tid, unsigned int tick, int id, intptr_t data) { if (data <= 0 || data >= MAX_SKILL) return 0; - if (!sd) return 0; + if (!sd || !sd->blockskill[data]) + return 0; if( ( cd = idb_get(skill->cd_db,sd->status.char_id) ) ) { int i; @@ -16952,22 +17021,21 @@ int skill_blockpc_end(int tid, unsigned int tick, int id, intptr_t data) { } } - if (sd->blockskill[data] != (0x1|(tid&0xFE))) return 0; - - sd->blockskill[data] = 0; + sd->blockskill[data] = false; return 1; } /** * flags a singular skill as being blocked from persistent usage. * @param sd the player the skill delay affects - * @param skill_id the skill which should be delayed + * @param skill_id the skill which should be delayed * @param tick the length of time the delay should last - * @param load whether this assignment is being loaded upon player login * @return 0 if successful, -1 otherwise */ -int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick, bool load) { +int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick) { + struct skill_cd* cd = NULL; uint16 idx = skill->get_index(skill_id); + unsigned int now = timer->gettick(); nullpo_retr (-1, sd); @@ -16975,49 +17043,59 @@ int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick, return -1; if (tick < 1) { - sd->blockskill[idx] = 0; + sd->blockskill[idx] = false; return -1; } - if( !load && battle_config.display_status_timers ) + if( battle_config.display_status_timers ) clif->skill_cooldown(sd, skill_id, tick); - - if( !load ) {// not being loaded initially so ensure the skill delay is recorded - struct skill_cd* cd = NULL; + + if( !(cd = idb_get(skill->cd_db,sd->status.char_id)) ) {// create a new skill cooldown object for map storage + cd = ers_alloc(skill->cd_ers, struct skill_cd); + + cd->cursor = 0; + memset(cd->entry, 0, sizeof(cd->entry)); + + idb_put( skill->cd_db, sd->status.char_id, cd ); + } else { int i; - if( !(cd = idb_get(skill->cd_db,sd->status.char_id)) ) {// create a new skill cooldown object for map storage - cd = ers_alloc(skill->cd_ers, struct skill_cd); - - cd->cursor = 0; - memset(cd->entry, 0, sizeof(cd->entry)); - - idb_put( skill->cd_db, sd->status.char_id, cd ); - } - for(i = 0; i < MAX_SKILL_TREE; i++) { - if( !cd->entry[i] ) + if( cd->entry[i] && cd->entry[i]->skidx == idx ) break; } - - if( i == MAX_SKILL_TREE ) { - ShowError("skill_blockpc_start: '%s' got over '%d' skill cooldowns, no room to save!\n",sd->status.name,MAX_SKILL_TREE); - } else { - cd->entry[cd->cursor] = ers_alloc(skill->cd_entry_ers,struct skill_cd_entry); - - cd->entry[cd->cursor]->duration = tick; + + if( i != MAX_SKILL_TREE ) {/* duplicate, update necessary */ + cd->entry[i]->duration = tick; #if PACKETVER >= 20120604 - cd->entry[cd->cursor]->total = tick; + cd->entry[i]->total = tick; #endif - cd->entry[cd->cursor]->skidx = idx; - cd->entry[cd->cursor]->skill_id = skill_id; - cd->entry[cd->cursor]->started = timer->gettick(); - - cd->cursor++; + cd->entry[i]->started = now; + timer->settick(cd->entry[i]->timer,now+tick); + return 0; } + + } + + if( cd->cursor == MAX_SKILL_TREE ) { + ShowError("skill_blockpc_start: '%s' got over '%d' skill cooldowns, no room to save!\n",sd->status.name,MAX_SKILL_TREE); + return -1; } + + cd->entry[cd->cursor] = ers_alloc(skill->cd_entry_ers,struct skill_cd_entry); + + cd->entry[cd->cursor]->duration = tick; +#if PACKETVER >= 20120604 + cd->entry[cd->cursor]->total = tick; +#endif + cd->entry[cd->cursor]->skidx = idx; + cd->entry[cd->cursor]->skill_id = skill_id; + cd->entry[cd->cursor]->started = now; + cd->entry[cd->cursor]->timer = timer->add(now+tick,skill->blockpc_end,sd->bl.id,idx); + + cd->cursor++; - sd->blockskill[idx] = 0x1|(0xFE&timer->add(timer->gettick()+tick,skill->blockpc_end,sd->bl.id,idx)); + sd->blockskill[idx] = true; return 0; } @@ -17528,6 +17606,10 @@ void skill_cooldown_save(struct map_session_data * sd) { // process each individual cooldown associated with the character for( i = 0; i < cd->cursor; i++ ) { cd->entry[i]->duration = DIFF_TICK(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; + } } } @@ -17554,8 +17636,8 @@ void skill_cooldown_load(struct map_session_data * sd) { // process each individual cooldown associated with the character for( i = 0; i < cd->cursor; i++ ) { cd->entry[i]->started = now; - // block the skill from usage but ensure it is not recorded (load = true) - skill->blockpc_start( sd, cd->entry[i]->skill_id, cd->entry[i]->duration, true ); + cd->entry[i]->timer = timer->add(timer->gettick()+cd->entry[i]->duration,skill->blockpc_end,sd->bl.id,cd->entry[i]->skidx); + sd->blockskill[cd->entry[i]->skidx] = true; } } @@ -18292,4 +18374,5 @@ void skill_defaults(void) { skill->cooldown_save = skill_cooldown_save; skill->maelstrom_suction = skill_maelstrom_suction; skill->get_new_group_id = skill_get_new_group_id; + skill->check_shadowform = skill_check_shadowform; } |