diff options
Diffstat (limited to 'src/map/skill.c')
-rw-r--r-- | src/map/skill.c | 119 |
1 files changed, 88 insertions, 31 deletions
diff --git a/src/map/skill.c b/src/map/skill.c index e16cb0cc7..e31e8f61e 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -439,6 +439,10 @@ int can_copy (struct map_session_data *sd, uint16 skill_id, struct block_list* b else if( sd->sc.data[SC__REPRODUCE] && !skill->reproduce_db[skill->get_index(skill_id)] ) return 0; + //Never copy new 3rd class skills By OmegaRed
+ if(skill_id >= GC_DARKCROW && skill_id <= ALL_FULL_THROTTLE)
+ return 0; + return 1; } @@ -1384,6 +1388,14 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 if( rate ) skill->break_equip(bl, EQP_ARMOR, rate, BCT_ENEMY); } + if (sd && !skill_id && bl->type == BL_PC) { // This effect does not work with skills.
+ if (sd->def_set_race[tstatus->race].rate)
+ status->change_start(src,bl, SC_DEFSET, sd->def_set_race[tstatus->race].rate, sd->def_set_race[tstatus->race].value,
+ 0, 0, 0, sd->def_set_race[tstatus->race].tick, 2);
+ if (sd->def_set_race[tstatus->race].rate)
+ status->change_start(src,bl, SC_MDEFSET, sd->mdef_set_race[tstatus->race].rate, sd->mdef_set_race[tstatus->race].value,
+ 0, 0, 0, sd->mdef_set_race[tstatus->race].tick, 2);
+ } } if( sd && sd->ed && sc && !status->isdead(bl) && !skill_id ) { @@ -3225,10 +3237,9 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd = NULL; if( src->type == BL_PC && (sd = ((TBL_PC*)src)) ) { - if( distance_xy(src->x, src->y, target->x, target->y) >= 3 ) // FIXME: Don't combos ignore distance? [Panikon] + if( distance_xy(src->x, src->y, target->x, target->y) >= 3 ) break; - skill->consume_requirement(sd, skl->skill_id, pc->checkskill(sd, skl->skill_id),1); skill->castend_damage_id(src, target, skl->skill_id, pc->checkskill(sd, skl->skill_id), tick, 0); } break; @@ -3847,33 +3858,78 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag); break; - case KN_BOWLINGBASH: - case MS_BOWLINGBASH: - if(flag&1){ - if(bl->id==skill->area_temp[1]) - break; - //two hits for 500% - skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,SD_ANIMATION); - skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,SD_ANIMATION); - } else { - int i,c; - c = skill->get_blewcount(skill_id,skill_lv); - // keep moving target in the direction that src is looking, square by square - for(i=0;i<c;i++){ - if (!skill->blown(src,bl,1,(unit->getdir(src)+4)%8,0x1)) - break; //Can't knockback - skill->area_temp[0] = map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY, skill->area_sub_count); - if( skill->area_temp[0] > 1 ) break; // collision - } - clif->blown(bl); //Update target pos. - if (i!=c) { //Splash - skill->area_temp[1] = bl->id; - map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_damage_id); - } - //Weirdo dual-hit property, two attacks for 500% - skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,0); - skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,0); - } + case KN_BOWLINGBASH:
+ case MS_BOWLINGBASH:
+ {
+ int min_x,max_x,min_y,max_y,i,c,dir,tx,ty;
+ // Chain effect and check range gets reduction by recursive depth, as this can reach 0, we don't use blowcount
+ c = (skill_lv-(flag&0xFFF)+1)/2;
+ // Determine the Bowling Bash area depending on configuration
+ if (battle_config.bowling_bash_area == 0) {
+ // Gutter line system
+ min_x = ((src->x)-c) - ((src->x)-c)%40;
+ if(min_x < 0) min_x = 0;
+ max_x = min_x + 39;
+ min_y = ((src->y)-c) - ((src->y)-c)%40;
+ if(min_y < 0) min_y = 0;
+ max_y = min_y + 39;
+ } else if (battle_config.bowling_bash_area == 1) {
+ // Gutter line system without demi gutter bug
+ min_x = src->x - (src->x)%40;
+ max_x = min_x + 39;
+ min_y = src->y - (src->y)%40;
+ max_y = min_y + 39;
+ } else {
+ // Area around caster
+ min_x = src->x - battle_config.bowling_bash_area;
+ max_x = src->x + battle_config.bowling_bash_area;
+ min_y = src->y - battle_config.bowling_bash_area;
+ max_y = src->y + battle_config.bowling_bash_area;
+ }
+ // Initialization, break checks, direction
+ if((flag&0xFFF) > 0) {
+ // Ignore monsters outside area
+ if(bl->x < min_x || bl->x > max_x || bl->y < min_y || bl->y > max_y)
+ break;
+ // Ignore monsters already in list
+ if(idb_exists(skill->bowling_db, bl->id))
+ break;
+ // Random direction
+ dir = rnd()%8;
+ } else {
+ // Create an empty list of already hit targets
+ db_clear(skill->bowling_db);
+ // Direction is walkpath
+ dir = (unit->getdir(src)+4)%8;
+ }
+ // Add current target to the list of already hit targets
+ idb_put(skill->bowling_db, bl->id, bl);
+ // Keep moving target in direction square by square
+ tx = bl->x;
+ ty = bl->y;
+ for(i=0;i<c;i++) {
+ // Target coordinates (get changed even if knockback fails)
+ tx -= dirx[dir];
+ ty -= diry[dir];
+ // If target cell is a wall then break
+ if(map->getcell(bl->m,tx,ty,CELL_CHKWALL))
+ break;
+ skill_blown(src,bl,1,dir,0);
+ // Splash around target cell, but only cells inside area; we first have to check the area is not negative
+ if((max(min_x,tx-1) <= min(max_x,tx+1)) &&
+ (max(min_y,ty-1) <= min(max_y,ty+1)) &&
+ (map->foreachinarea(skill->area_sub, bl->m, max(min_x,tx-1), max(min_y,ty-1), min(max_x,tx+1), min(max_y,ty+1), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY, skill->area_sub_count))) {
+ // Recursive call
+ map->foreachinarea(skill->area_sub, bl->m, max(min_x,tx-1), max(min_y,ty-1), min(max_x,tx+1), min(max_y,ty+1), splash_target(src), src, skill_id, skill_lv, tick, (flag|BCT_ENEMY)+1, skill->castend_damage_id);
+ // Self-collision
+ if(bl->x >= min_x && bl->x <= max_x && bl->y >= min_y && bl->y <= max_y)
+ skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,(flag&0xFFF)>0?SD_ANIMATION:0);
+ break;
+ }
+ }
+ // Original hit or chain hit depending on flag
+ skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,(flag&0xFFF)>0?SD_ANIMATION:0);
+ }
break; case KN_SPEARSTAB: @@ -18442,7 +18498,7 @@ int do_init_skill(bool minimal) { skill->unit_db = idb_alloc(DB_OPT_BASE); skill->cd_db = idb_alloc(DB_OPT_BASE); skill->usave_db = idb_alloc(DB_OPT_RELEASE_DATA); - + skill->bowling_db = idb_alloc(DB_OPT_BASE); skill->unit_ers = ers_new(sizeof(struct skill_unit_group),"skill.c::skill_unit_ers",ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK); skill->timer_ers = ers_new(sizeof(struct skill_timerskill),"skill.c::skill_timer_ers",ERS_OPT_NONE|ERS_OPT_FLEX_CHUNK); skill->cd_ers = ers_new(sizeof(struct skill_cd),"skill.c::skill_cd_ers",ERS_OPT_CLEAR|ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK); @@ -18471,7 +18527,7 @@ int do_final_skill(void) { db_destroy(skill->unit_db); db_destroy(skill->cd_db); db_destroy(skill->usave_db); - + db_destroy(skill->bowling_db); ers_destroy(skill->unit_ers); ers_destroy(skill->timer_ers); ers_destroy(skill->cd_ers); @@ -18493,6 +18549,7 @@ void skill_defaults(void) { skill->name2id_db = NULL; skill->unit_db = NULL; skill->usave_db = NULL; + skill->bowling_db = NULL; skill->group_db = NULL; /* */ skill->unit_ers = NULL; |