diff options
Diffstat (limited to 'src/map/skill.c')
-rw-r--r-- | src/map/skill.c | 117 |
1 files changed, 79 insertions, 38 deletions
diff --git a/src/map/skill.c b/src/map/skill.c index 1431d27a7..dc89f3170 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -46,7 +46,7 @@ #define SKILLUNITTIMER_INTERVAL 100 // ranges reserved for mapping skill ids to skilldb offsets -#define HM_SKILLRANGEMIN 700 +#define HM_SKILLRANGEMIN 750 #define HM_SKILLRANGEMAX HM_SKILLRANGEMIN + MAX_HOMUNSKILL #define MC_SKILLRANGEMIN HM_SKILLRANGEMAX + 1 #define MC_SKILLRANGEMAX MC_SKILLRANGEMIN + MAX_MERCSKILL @@ -64,20 +64,6 @@ static struct eri *skill_timer_ers = NULL; //For handling skill_timerskills [Sko DBMap* skillunit_db = NULL; // int id -> struct skill_unit* /** - * Skill Cool Down Delay Saving - * Struct skill_cd is not a member of struct map_session_data - * to keep cooldowns in memory between player log-ins. - * All cooldowns are reset when server is restarted. - **/ -DBMap* skillcd_db = NULL; // char_id -> struct skill_cd -struct skill_cd { - int duration[MAX_SKILL_TREE];//milliseconds - short skidx[MAX_SKILL_TREE];//the skill index entries belong to - short nameid[MAX_SKILL_TREE];//skill id - unsigned char cursor; -}; - -/** * Skill Unit Persistency during endack routes (mostly for songs see bugreport:4574) **/ DBMap* skillusave_db = NULL; // char_id -> struct skill_usave @@ -118,6 +104,9 @@ struct s_skill_unit_layout skill_unit_layout[MAX_SKILL_UNIT_LAYOUT]; int firewall_unit_pos; int icewall_unit_pos; int earthstrain_unit_pos; + +struct skill_interface skill_s; + //Since only mob-casted splash skills can hit ice-walls static inline int splash_target(struct block_list* bl) { #ifndef RENEWAL @@ -851,11 +840,9 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint break; case SM_BASH: - if( sd && skill_lv > 5 && pc->checkskill(sd,SM_FATALBLOW)>0 ){ - //TODO: How much % per base level it actually is? - sc_start(bl,SC_STUN,(5*(skill_lv-5)+(int)sd->status.base_level/10), - skill_lv,skill->get_time2(SM_FATALBLOW,skill_lv)); - } + if( sd && skill_lv > 5 && pc->checkskill(sd,SM_FATALBLOW)>0 ) + status_change_start(bl,SC_STUN,500*(skill_lv-5)*sd->status.base_level/50, + skill_lv,0,0,0,skill->get_time2(SM_FATALBLOW,skill_lv),0); break; case MER_CRASH: @@ -949,8 +936,8 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint break; case TF_THROWSTONE: - sc_start(bl,SC_STUN,3,skill_lv,skill->get_time(skill_id,skill_lv)); - sc_start(bl,SC_BLIND,3,skill_lv,skill->get_time2(skill_id,skill_lv)); + if( !sc_start(bl,SC_STUN,3,skill_lv,skill->get_time(skill_id,skill_lv)) ) + sc_start(bl,SC_BLIND,3,skill_lv,skill->get_time2(skill_id,skill_lv)); break; case NPC_DARKCROSS: @@ -1182,7 +1169,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint sc_start4(bl,SC_BURNING,5+5*skill_lv,skill_lv,0,src->id,0,skill->get_time(skill_id,skill_lv)); break; case RK_DRAGONBREATH_WATER: - sc_start4(bl,SC_FROSTMISTY,5+5*skill_lv,skill_lv,0,src->id,0,skill->get_time(skill_id,skill_lv)); + sc_start(bl,SC_FROSTMISTY,5+5*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); break; case AB_ADORAMUS: if( tsc && !tsc->data[SC_DEC_AGI] ) //Prevent duplicate agi-down effect. @@ -1344,7 +1331,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint rate = 5 + 5 * skill_lv; if( sc && sc->data[SC_COOLER_OPTION] ) rate += rate * sc->data[SC_COOLER_OPTION]->val2 / 100; - sc_start(bl, SC_CRYSTALIZE, rate, skill_lv, skill->get_time2(skill_id, skill_lv)); + sc_start(bl, SC_COLD, rate, skill_lv, skill->get_time2(skill_id, skill_lv)); break; case SO_VARETYR_SPEAR: sc_start(bl, SC_STUN, 5 + 5 * skill_lv, skill_lv, skill->get_time2(skill_id, skill_lv)); @@ -7676,9 +7663,24 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui case NPC_WIDESTUN: case NPC_SLOWCAST: case NPC_WIDEHELLDIGNITY: - if (flag&1) - sc_start2(bl,type,100,skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); - else { + case NPC_WIDEHEALTHFEAR: + case NPC_WIDEBODYBURNNING: + case NPC_WIDEFROSTMISTY: + case NPC_WIDECOLD: + case NPC_WIDE_DEEP_SLEEP: + case NPC_WIDESIREN: + if (flag&1){ + switch( type ){ + case SC_BURNING: + sc_start4(bl,type,100,skill_lv,0,src->id,0,skill->get_time2(skill_id,skill_lv)); + break; + case SC_SIREN: + sc_start2(bl,type,100,skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); + break; + default: + sc_start2(bl,type,100,skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); + } + }else { skill_area_temp[2] = 0; //For SD_PREAMBLE clif->skill_nodamage(src,bl,skill_id,skill_lv,1); iMap->foreachinrange(skill->area_sub, bl, @@ -7939,7 +7941,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui case AB_LAUDAAGNUS: if( flag&1 || sd == NULL ) { if( tsc && (tsc->data[SC_FREEZE] || tsc->data[SC_STONE] || tsc->data[SC_BLIND] || - tsc->data[SC_BURNING] || tsc->data[SC_FROSTMISTY] || tsc->data[SC_CRYSTALIZE])) { + tsc->data[SC_BURNING] || tsc->data[SC_FROSTMISTY] || tsc->data[SC_COLD])) { // Success Chance: (40 + 10 * Skill Level) % if( rnd()%100 > 40+10*skill_lv ) break; status_change_end(bl, SC_FREEZE, INVALID_TIMER); @@ -7947,7 +7949,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui status_change_end(bl, SC_BLIND, INVALID_TIMER); status_change_end(bl, SC_BURNING, INVALID_TIMER); status_change_end(bl, SC_FROSTMISTY, INVALID_TIMER); - status_change_end(bl, SC_CRYSTALIZE, INVALID_TIMER); + status_change_end(bl, SC_COLD, INVALID_TIMER); }else //Success rate only applies to the curing effect and not stat bonus. Bonus status only applies to non infected targets clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); @@ -8037,9 +8039,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui else if(bl->type == BL_PC) rate += 20 + 10 * skill_lv; // On Players, (20 + 10 * Skill Level) % else rate += 40 + 10 * skill_lv; // On Monsters, (40 + 10 * Skill Level) % - if( sd ) - skill->blockpc_start(sd,skill_id,4000, false); - if( !(tsc && tsc->data[type]) ){ i = sc_start2(bl,type,rate,skill_lv,src->id,(src == bl)?5000:(bl->type == BL_PC)?skill->get_time(skill_id,skill_lv):skill->get_time2(skill_id, skill_lv)); clif->skill_nodamage(src,bl,skill_id,skill_lv,i); @@ -8451,7 +8450,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui case SC_BLOODING: case SC_CURSE: case SC_CONFUSION: case SC_ILLUSION: case SC_SILENCE: case SC_BURNING: - case SC_CRYSTALIZE: case SC_FROSTMISTY: + case SC_COLD: case SC_FROSTMISTY: case SC_DEEP_SLEEP: case SC_FEAR: case SC_MANDRAGORA: status_change_end(bl, (sc_type)i, INVALID_TIMER); @@ -8556,7 +8555,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui status_change_end(bl, SC_POISON, INVALID_TIMER); status_change_end(bl, SC_SILENCE, INVALID_TIMER); status_change_end(bl, SC_BLIND, INVALID_TIMER); - status_change_end(bl, SC_ILLUSION, INVALID_TIMER); + status_change_end(bl, SC_ILLUSION, INVALID_TIMER); status_change_end(bl, SC_BURNING, INVALID_TIMER); status_change_end(bl, SC_FROSTMISTY, INVALID_TIMER); } @@ -11801,7 +11800,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns if( battle->check_target(&src->bl,bl,BCT_ENEMY) > 0 ){ switch( sg->unit_id ){ case UNT_ZENKAI_WATER: - sc_start(bl, SC_CRYSTALIZE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start(bl, SC_COLD, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); sc_start(bl, SC_FREEZE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); sc_start(bl, SC_FROSTMISTY, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); break; @@ -16875,16 +16874,24 @@ int skill_blockpc_end(int tid, unsigned int tick, int id, intptr_t data) { int i,cursor; ARR_FIND( 0, cd->cursor+1, cursor, cd->skidx[cursor] == data ); cd->duration[cursor] = 0; +#if PACKETVER >= 20120604 + cd->total[cursor] = 0; +#endif cd->skidx[cursor] = 0; cd->nameid[cursor] = 0; + cd->started[cursor] = 0; // compact the cool down list for( i = 0, cursor = 0; i < cd->cursor; i++ ) { if( cd->duration[i] == 0 ) continue; if( cursor != i ) { cd->duration[cursor] = cd->duration[i]; +#if PACKETVER >= 20120604 + cd->total[cursor] = cd->total[i]; +#endif cd->skidx[cursor] = cd->skidx[i]; cd->nameid[cursor] = cd->nameid[i]; + cd->started[cursor] = cd->started[i]; } cursor++; } @@ -16920,7 +16927,7 @@ int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick, return -1; } - if( battle_config.display_status_timers ) + if( !load && 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 @@ -16931,8 +16938,12 @@ int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick, // record the skill duration in the database map cd->duration[cd->cursor] = tick; +#if PACKETVER >= 20120604 + cd->total[cd->cursor] = tick; +#endif cd->skidx[cd->cursor] = idx; cd->nameid[cd->cursor] = skill_id; + cd->started[cd->cursor] = iTimer->gettick(); cd->cursor++; } @@ -17425,13 +17436,37 @@ int skill_get_elemental_type( uint16 skill_id , uint16 skill_lv ) { } /** + * update stored skill cooldowns for player logout + * @param sd the affected player structure + */ +void skill_cooldown_save(struct map_session_data * sd) { + int i; + struct skill_cd* cd = NULL; + unsigned int now = 0; + + // always check to make sure the session properly exists + nullpo_retv(sd); + + if( !(cd = idb_get(skillcd_db, sd->status.char_id)) ) {// no skill cooldown is associated with this character + return; + } + + now = iTimer->gettick(); + + // process each individual cooldown associated with the character + for( i = 0; i < cd->cursor; i++ ) { + cd->duration[i] = DIFF_TICK(cd->started[i]+cd->duration[i],now); + } +} + +/** * reload stored skill cooldowns when a player logs in. * @param sd the affected player structure */ -void skill_cooldown_load(struct map_session_data * sd) -{ +void skill_cooldown_load(struct map_session_data * sd) { int i; struct skill_cd* cd = NULL; + unsigned int now = 0; // always check to make sure the session properly exists nullpo_retv(sd); @@ -17440,8 +17475,13 @@ void skill_cooldown_load(struct map_session_data * sd) return; } + clif->cooldown_list(sd->fd,cd); + + now = iTimer->gettick(); + // process each individual cooldown associated with the character for( i = 0; i < cd->cursor; i++ ) { + cd->started[i] = now; // block the skill from usage but ensure it is not recorded (load = true) skill->blockpc_start( sd, cd->nameid[i], cd->duration[i], true ); } @@ -18132,5 +18172,6 @@ void skill_defaults(void) { skill->elementalanalysis = skill_elementalanalysis; skill->changematerial = skill_changematerial; skill->get_elemental_type = skill_get_elemental_type; + skill->cooldown_save = skill_cooldown_save; } |