From a15cee063d9b1c8240e5104599745519933f6ae0 Mon Sep 17 00:00:00 2001 From: playtester Date: Thu, 25 Apr 2013 19:52:09 +0000 Subject: [PATCH] - 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 --- conf/battle/skill.conf | 7 +++ db/pre-re/skill_db.txt | 2 +- db/re/skill_db.txt | 2 +- src/map/battle.c | 1 + src/map/battle.h | 1 + src/map/skill.c | 96 +++++++++++++++++++++++++++++++----------- 6 files changed, 83 insertions(+), 26 deletions(-) diff --git a/conf/battle/skill.conf b/conf/battle/skill.conf index ee28fec43b..5ddbdd6661 100644 --- a/conf/battle/skill.conf +++ b/conf/battle/skill.conf @@ -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 diff --git a/db/pre-re/skill_db.txt b/db/pre-re/skill_db.txt index d80b8f6709..0a01d245e1 100644 --- a/db/pre-re/skill_db.txt +++ b/db/pre-re/skill_db.txt @@ -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 diff --git a/db/re/skill_db.txt b/db/re/skill_db.txt index bade879ebc..272617b879 100644 --- a/db/re/skill_db.txt +++ b/db/re/skill_db.txt @@ -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 diff --git a/src/map/battle.c b/src/map/battle.c index 3d237dd933..13b60b3415 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -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 /** diff --git a/src/map/battle.h b/src/map/battle.h index 8f6c68445e..d76439e630 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -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); diff --git a/src/map/skill.c b/src/map/skill.c index 7151c06749..456ecb1509 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -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 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;im,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;