- Implemented official Bowling Bash with all its special behaviors including the gutter line (bugreport:4209)
* As many servers probably want to remove the gutter line problem, it is configurable; just adjust the bowling_bash_area setting in skill.conf - Sonic Blow now has a fixed range of 1, even for monsters; a monster can't use this skill if you tank it from farther away (bugreport:3453) git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@17295 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
parent
b5769e1c67
commit
a15cee063d
@ -280,3 +280,10 @@ dancing_weaponswitch_fix: yes
|
||||
// 0: (official) Traps in GvG only make player stop moving after its walk path is complete, and it activates other traps on the way.
|
||||
// 1: Traps in GvG make player stop moving right when stepping over it.
|
||||
skill_trap_type: 0
|
||||
|
||||
// Area of Bowling Bash chain reaction
|
||||
// 0: Use official gutter line system
|
||||
// 1: Gutter line system without demi gutter bug
|
||||
// 2-20: Area around caster (2 = 5x5, 3 = 7x7, 4 = 9x9, ..., 20 = 41x41)
|
||||
// Note: If you knock the target out of the area it will only be hit once and won't do splash damage
|
||||
bowling_bash_area: 0
|
||||
|
@ -179,7 +179,7 @@
|
||||
133,0,0,0,0,0,0,5,0,no,0,0,0,weapon,0, AS_LEFT,Lefthand Mastery
|
||||
134,0,0,0,0,0,0,10,0,no,0,0,0,weapon,0, AS_KATAR,Katar Mastery
|
||||
135,0,6,4,0,0x1,0,10,1,no,0,0,0,weapon,0, AS_CLOAKING,Cloaking
|
||||
136,-1,8,1,-1,0,0,10,8,no,0,0,0,weapon,0, AS_SONICBLOW,Sonic Blow
|
||||
136,1,8,1,-1,0,0,10,8,no,0,0,0,weapon,0, AS_SONICBLOW,Sonic Blow
|
||||
137,3:4:5:6:7,6,1,-1,0x2,1,5,1,no,0,0,0,weapon,0,AS_GRIMTOOTH,Grimtooth
|
||||
138,1,6,16,5,0x1,0,10,1,no,0,0x400,0,weapon,0, AS_ENCHANTPOISON,Enchant Poison
|
||||
139,0,6,4,0,0,0,10,1,no,0,0,0,weapon,0, AS_POISONREACT,Poison React
|
||||
|
@ -179,7 +179,7 @@
|
||||
133,0,0,0,0,0,0,5,0,no,0,0,0,weapon,0, AS_LEFT,Lefthand Mastery
|
||||
134,0,0,0,0,0,0,10,0,no,0,0,0,weapon,0, AS_KATAR,Katar Mastery
|
||||
135,0,6,4,0,0x1,0,10,1,no,0,0,0,weapon,0, AS_CLOAKING,Cloaking
|
||||
136,-1,8,1,-1,0,0,10,8,no,0,0,0,weapon,0, AS_SONICBLOW,Sonic Blow
|
||||
136,1,8,1,-1,0,0,10,8,no,0,0,0,weapon,0, AS_SONICBLOW,Sonic Blow
|
||||
137,3:4:5:6:7,6,1,-1,0x2,1,5,1,no,0,0,0,weapon,0,AS_GRIMTOOTH,Grimtooth
|
||||
138,1,6,16,5,0x1,0,10,1,no,0,0x400,0,weapon,0, AS_ENCHANTPOISON,Enchant Poison
|
||||
139,0,6,4,0,0,0,10,1,no,0,0,0,weapon,0, AS_POISONREACT,Poison React
|
||||
|
@ -5943,6 +5943,7 @@ static const struct _battle_data {
|
||||
{ "max_walk_path", &battle_config.max_walk_path, 17, 1, MAX_WALKPATH, },
|
||||
{ "item_enabled_npc", &battle_config.item_enabled_npc, 1, 0, 1, },
|
||||
{ "item_flooritem_check", &battle_config.item_onfloor, 1, 0, 1, },
|
||||
{ "bowling_bash_area", &battle_config.bowling_bash_area, 0, 0, 20, },
|
||||
};
|
||||
#ifndef STATS_OPT_OUT
|
||||
/**
|
||||
|
@ -487,6 +487,7 @@ extern struct Battle_Config
|
||||
int max_walk_path;
|
||||
int item_enabled_npc;
|
||||
int item_onfloor; // Whether to drop an undroppable item on the map or destroy it if inventory is full.
|
||||
int bowling_bash_area;
|
||||
} battle_config;
|
||||
|
||||
void do_init_battle(void);
|
||||
|
@ -59,6 +59,7 @@
|
||||
#endif
|
||||
static struct eri *skill_unit_ers = NULL; //For handling skill_unit's [Skotlex]
|
||||
static struct eri *skill_timer_ers = NULL; //For handling skill_timerskills [Skotlex]
|
||||
static DBMap* bowling_db = NULL; // int mob_id -> struct mob_data*
|
||||
|
||||
DBMap* skillunit_db = NULL; // int id -> struct skill_unit*
|
||||
|
||||
@ -1074,7 +1075,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
|
||||
break;
|
||||
case NPC_MENTALBREAKER:
|
||||
{ //Based on observations by Tharis, Mental Breaker should do SP damage
|
||||
//equal to Matk*skLevel.
|
||||
//equal to Matk*skLevel.
|
||||
rate = sstatus->matk_min;
|
||||
if (rate < sstatus->matk_max)
|
||||
rate += rnd()%(sstatus->matk_max - sstatus->matk_min);
|
||||
@ -1138,7 +1139,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
|
||||
break;
|
||||
default:
|
||||
sc_start2(src,bl,SC_BLEEDING,(5+skill_lv*5),skill_lv,src->id,skill_get_time2(skill_id,3));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case HW_NAPALMVULCAN:
|
||||
@ -3968,30 +3969,75 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
||||
|
||||
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
|
||||
{
|
||||
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;
|
||||
}
|
||||
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);
|
||||
// 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(bowling_db, bl->id))
|
||||
break;
|
||||
// Random direction
|
||||
dir = rand()%8;
|
||||
} else {
|
||||
// Create an empty list of already hit targets
|
||||
db_clear(bowling_db);
|
||||
// Direction is walkpath
|
||||
dir = (unit_getdir(src)+4)%8;
|
||||
}
|
||||
//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);
|
||||
// Add current target to the list of already hit targets
|
||||
idb_put(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;
|
||||
|
||||
@ -18191,6 +18237,7 @@ int do_init_skill (void)
|
||||
skillunit_db = idb_alloc(DB_OPT_BASE);
|
||||
skillcd_db = idb_alloc(DB_OPT_RELEASE_DATA);
|
||||
skillusave_db = idb_alloc(DB_OPT_RELEASE_DATA);
|
||||
bowling_db = idb_alloc(DB_OPT_BASE);
|
||||
skill_unit_ers = ers_new(sizeof(struct skill_unit_group),"skill.c::skill_unit_ers",ERS_OPT_NONE);
|
||||
skill_timer_ers = ers_new(sizeof(struct skill_timerskill),"skill.c::skill_timer_ers",ERS_OPT_NONE);
|
||||
|
||||
@ -18212,6 +18259,7 @@ int do_final_skill(void)
|
||||
db_destroy(skillunit_db);
|
||||
db_destroy(skillcd_db);
|
||||
db_destroy(skillusave_db);
|
||||
db_destroy(bowling_db);
|
||||
ers_destroy(skill_unit_ers);
|
||||
ers_destroy(skill_timer_ers);
|
||||
return 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user