瀏覽代碼

Land Protector, Ground Skill Splash, Storm Gust Knock-back
- Land Protector now behaves like on official servers (bugreport:5237)
* Land Protector now protects from units being placed on it, no matter if they have splash range or not
* Land Protector no longer protects from damage from units not outside Land Protector that splash inside
* Meteor Storm no longer shows meteors falling if they would land on Land Protector
* Pneuma can no longer be placed next to Land Protector
* Also cleaned up the code a bit, so the checks are done where they should be done
- Ground skill splash ranges updated to their official values (bugreport:5237)
* Lord of Vermilion places units in a 11x11 area with 3x3 splash range each
* Storm Gust places units in a 9x9 area with 3x3 splash range each
* Heaven's Drive places units in a 5x5 area with no splash range
* Venom Dust now has a splash range of 3x3 and is consequently larger than before
- Storm Gust's knock-back behavior updated to official (bugreport:5237)
* Each of Storm Gust's units will knock back "Away from center"
* As units in the south-west are processed first, the knock-back direction will usually be north-east
* At the edges the knock-back direction will be "to the outside"
* Land Protector and Ganbantein will influence the knock-back behavior strongly, e.g. if Storm Gust has a hole in the middle, it will have a "suck in" effect
* Added a config option for those who want the old "random direction" behavior from eAthena

Playtester 10 年之前
父節點
當前提交
e7e8b5454b
共有 7 個文件被更改,包括 32 次插入27 次删除
  1. 7 0
      conf/battle/skill.conf
  2. 5 5
      db/pre-re/skill_unit_db.txt
  3. 5 5
      db/re/skill_unit_db.txt
  4. 1 0
      src/map/battle.c
  5. 1 0
      src/map/battle.h
  6. 13 8
      src/map/skill.c
  7. 0 9
      src/map/unit.c

+ 7 - 0
conf/battle/skill.conf

@@ -323,3 +323,10 @@ cart_revo_knockback: yes
 
 // On official servers, Arrow Shower blow direction always rely on skill placed location to target instead of caster to target
 arrow_shower_knockback: yes
+
+// On official servers, Storm Gust consists of 81 units that all deal 3x3 splash damage "away from center". Due to
+// south-western cells being processed first, this usually leads to a knockback to the northeast. Knockback at the
+// edges will be away from SG. Knockback direction can also be influenced by Ganbantein and Land Protector. If you
+// punch a hole into SG it will for example create a "suck in" effect.
+// If you disable this setting, the knockback direction will be completely random (eAthena style).
+stormgust_knockback: yes

+ 5 - 5
db/pre-re/skill_unit_db.txt

@@ -7,7 +7,7 @@
 // target = friend (party +guildmates +neutral players) / party / guild
 //          ally (party +guildmates) / all / sameguild (guild but no allies) / enemy
 // flag 0x00001(UF_DEFNOTENEMY)			If 'defunit_not_enemy' is set, the target is changed to 'friend'
-//      0x00002(UF_NOREITERRATION)		Spell cannot be stacked
+//      0x00002(UF_NOREITERATION)		Spell cannot be stacked
 //      0x00004(UF_NOFOOTSET)			Spell cannot be cast near/on targets
 //      0x00008(UF_NOOVERLAP)			Spell effects do not overlap
 //      0x00010(UF_PATHCHECK)			Only cells with a shootable path will be placed
@@ -41,10 +41,10 @@
  79,0x84,    , -1, 1,3000,enemy, 0x8018	//PR_MAGNUS
  80,0x87,0x88,  0, 1,2000,enemy, 0x4006	//WZ_FIREPILLAR
  83,0x86,    ,  0, 3,1000,enemy, 0x010	//WZ_METEOR
- 85,0x86,    ,  0, 6:6:6:6:6:6:6:6:6:6:8,1250,enemy,0x018	//WZ_VERMILION
+ 85,0x86,    ,  5, 1:1:1:1:1:1:1:1:1:1:3,1250,enemy,0x018	//WZ_VERMILION
  87,0x8d,    , -1, 0,  -1,all,   0x9010	//WZ_ICEWALL
- 89,0x86,    ,  0, 5, 450,enemy, 0x018	//WZ_STORMGUST
- 91,0x86,    ,  0, 2,1000,enemy, 0x010	//WZ_HEAVENDRIVE
+ 89,0x86,    ,  4, 1, 450,enemy, 0x018	//WZ_STORMGUST
+ 91,0x86,    ,  2, 0,1000,enemy, 0x010	//WZ_HEAVENDRIVE
  92,0x8e,    ,  2, 0,  -1,enemy, 0x8010	//WZ_QUAGMIRE
 115,0x90,    ,  0, 1,1000,enemy, 0x8006	//HT_SKIDTRAP
 116,0x93,    ,  0, 1,1000,enemy, 0x8006	//HT_LANDMINE
@@ -56,7 +56,7 @@
 122,0x8f,    ,  0, 1,1000,enemy, 0x8006	//HT_BLASTMINE
 123,0x98,    ,  0, 1,1000,enemy, 0x8006	//HT_CLAYMORETRAP
 125,0x99,    ,  0, 1,1000,all,   0x8000	//HT_TALKIEBOX
-140,0x92,    , -1, 0,1000,enemy, 0x8000	//AS_VENOMDUST
+140,0x92,    , -1, 1,1000,enemy, 0x8000	//AS_VENOMDUST
 220,0xb0,    ,  0, 0,  -1,all,   0x8002	//RG_GRAFFITI
 229,0xb1,    ,  0, 1,1000,enemy, 0x006	//AM_DEMONSTRATION
 254,0x86,    , -1, 0, 300,enemy, 0x010	//CR_GRANDCROSS

+ 5 - 5
db/re/skill_unit_db.txt

@@ -7,7 +7,7 @@
 // target = friend (party +guildmates +neutral players) / party / guild
 //          ally (party +guildmates) / all / sameguild (guild but no allies) / enemy
 // flag 0x00001(UF_DEFNOTENEMY)			If 'defunit_not_enemy' is set, the target is changed to 'friend'
-//      0x00002(UF_NOREITERRATION)		Spell cannot be stacked
+//      0x00002(UF_NOREITERATION)		Spell cannot be stacked
 //      0x00004(UF_NOFOOTSET)			Spell cannot be cast near/on targets
 //      0x00008(UF_NOOVERLAP)			Spell effects do not overlap
 //      0x00010(UF_PATHCHECK)			Only cells with a shootable path will be placed
@@ -41,10 +41,10 @@
  79,0x84,    , -1, 1,3000,enemy, 0x8018	//PR_MAGNUS
  80,0x87,0x88,  0, 1,2000,enemy, 0x4006	//WZ_FIREPILLAR
  83,0x86,    ,  0, 3,1000,enemy, 0x010	//WZ_METEOR
- 85,0x86,    ,  0, 6:6:6:6:6:6:6:6:6:6:8,1250,enemy,0x018	//WZ_VERMILION
+ 85,0x86,    ,  5, 1:1:1:1:1:1:1:1:1:1:3,1250,enemy,0x018	//WZ_VERMILION
  87,0x8d,    , -1, 0,  -1,all,   0x9010	//WZ_ICEWALL
- 89,0x86,    ,  0, 5, 450,enemy, 0x018	//WZ_STORMGUST
- 91,0x86,    ,  0, 2,1000,enemy, 0x010	//WZ_HEAVENDRIVE
+ 89,0x86,    ,  4, 1, 450,enemy, 0x018	//WZ_STORMGUST
+ 91,0x86,    ,  2, 0,1000,enemy, 0x010	//WZ_HEAVENDRIVE
  92,0x8e,    ,  2, 0,  -1,enemy, 0x8010	//WZ_QUAGMIRE
 115,0x90,    ,  0, 1,1000,enemy, 0x8006	//HT_SKIDTRAP
 116,0x93,    ,  0, 1,1000,enemy, 0x8006	//HT_LANDMINE
@@ -56,7 +56,7 @@
 122,0x8f,    ,  0, 1,1000,enemy, 0x8006	//HT_BLASTMINE
 123,0x98,    ,  0, 1,1000,enemy, 0x8006	//HT_CLAYMORETRAP
 125,0x99,    ,  0, 1,1000,all,   0x8000	//HT_TALKIEBOX
-140,0x92,    , -1, 0,1000,enemy, 0x8000	//AS_VENOMDUST
+140,0x92,    , -1, 1,1000,enemy, 0x8000	//AS_VENOMDUST
 220,0xb0,    ,  0, 0,  -1,all,   0x8002	//RG_GRAFFITI
 229,0xb1,    ,  0, 1,1000,enemy, 0x006	//AM_DEMONSTRATION
 254,0x86,    , -1, 0, 300,enemy, 0x010	//CR_GRANDCROSS

+ 1 - 0
src/map/battle.c

@@ -7921,6 +7921,7 @@ static const struct _battle_data {
 	{ "mob_icewall_walk_block",             &battle_config.mob_icewall_walk_block,          75,     0,      255,            },
 	{ "boss_icewall_walk_block",            &battle_config.boss_icewall_walk_block,         0,      0,      255,            },
 	{ "snap_dodge",                         &battle_config.snap_dodge,                      0,      0,      1,              },
+	{ "stormgust_knockback",                &battle_config.stormgust_knockback,             1,      0,      1,              },
 };
 
 #ifndef STATS_OPT_OUT

+ 1 - 0
src/map/battle.h

@@ -577,6 +577,7 @@ extern struct Battle_Config
 	int mob_icewall_walk_block; //How a normal monster should be trapped in icewall [Playtester]
 	int boss_icewall_walk_block; //How a boss monster should be trapped in icewall [Playtester]
 	int snap_dodge; // Enable or disable dodging damage snapping away [csnv]
+	int stormgust_knockback;
 } battle_config;
 
 void do_init_battle(void);

+ 13 - 8
src/map/skill.c

@@ -2760,7 +2760,8 @@ void skill_attack_blow(struct block_list *src, struct block_list *dsrc, struct b
 			break;
 		// This ensures the storm randomly pushes instead of exactly a cell backwards per official mechanics.
 		case WZ_STORMGUST:
-			dir = rand()%8;
+			if(!battle_config.stormgust_knockback)
+				dir = rand()%8;
 			break;
 		case WL_CRIMSONROCK:
 			dir = map_calc_dir(target,skill_area_temp[4],skill_area_temp[5]);
@@ -3349,9 +3350,12 @@ static int skill_check_unit_range_sub(struct block_list *bl, va_list ap)
 	g_skill_id = unit->group->skill_id;
 
 	switch (skill_id) {
+		case AL_PNEUMA: //Pneuma doesn't work even if just one cell overlaps with Land Protector
+			if(g_skill_id == SA_LANDPROTECTOR)
+				break;
+			//Fall through
 		case MH_STEINWAND:
 		case MG_SAFETYWALL:
-		case AL_PNEUMA:
 		case SC_MAELSTROM:
 		case SO_ELEMENTAL_SHIELD:
 			if(g_skill_id != MH_STEINWAND && g_skill_id != MG_SAFETYWALL && g_skill_id != AL_PNEUMA && g_skill_id != SC_MAELSTROM && g_skill_id != SO_ELEMENTAL_SHIELD)
@@ -3873,7 +3877,8 @@ static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data)
 						int x = skl->type>>16, y = skl->type&0xFFFF;
 						if( path_search_long(NULL, src->m, src->x, src->y, x, y, CELL_CHKWALL) )
 							skill_unitsetting(src,skl->skill_id,skl->skill_lv,x,y,skl->flag);
-						if( path_search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) )
+						if( path_search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL)
+							&& !map_getcell(src->m, skl->x, skl->y, CELL_CHKLANDPROTECTOR) )
 							clif_skill_poseffect(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,tick);
 					}
 					else if( path_search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) )
@@ -11098,7 +11103,8 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
 				tmpx = x - area + rnd()%(area * 2 + 1);
 				tmpy = y - area + rnd()%(area * 2 + 1);
 
-				if( i == 0 && path_search_long(NULL, src->m, src->x, src->y, tmpx, tmpy, CELL_CHKWALL) )
+				if( i == 0 && path_search_long(NULL, src->m, src->x, src->y, tmpx, tmpy, CELL_CHKWALL)
+					&& !map_getcell(src->m, tmpx, tmpy, CELL_CHKLANDPROTECTOR))
 					clif_skill_poseffect(src,skill_id,skill_lv,tmpx,tmpy,tick);
 
 				if( i > 0 )
@@ -12321,8 +12327,7 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_
 			map_foreachincell(skill_maelstrom_suction,src->m,ux,uy,BL_SKILL,skill_id,skill_lv);
 
 		// Check active cell to failing or remove current unit
-		if( range <= 0 )
-			map_foreachincell(skill_cell_overlap,src->m,ux,uy,BL_SKILL,skill_id, &alive, src);
+		map_foreachincell(skill_cell_overlap,src->m,ux,uy,BL_SKILL,skill_id, &alive, src);
 		if( !alive )
 			continue;
 
@@ -12391,7 +12396,7 @@ static int skill_unit_onplace(struct skill_unit *unit, struct block_list *bl, un
 	nullpo_ret(sg = unit->group);
 	nullpo_ret(ss = map_id2bl(sg->src_id));
 
-	if( (skill_get_type(sg->skill_id) == BF_MAGIC && map_getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) && sg->skill_id != SA_LANDPROTECTOR) ||
+	if( (skill_get_type(sg->skill_id) == BF_MAGIC && map_getcell(unit->bl.m, unit->bl.x, unit->bl.y, CELL_CHKLANDPROTECTOR) && sg->skill_id != SA_LANDPROTECTOR) ||
 		map_getcell(bl->m, bl->x, bl->y, CELL_CHKMAELSTROM) )
 		return 0; //AoE skills are ineffective. [Skotlex]
 
@@ -17305,7 +17310,7 @@ int skill_unit_timer_sub_onplace(struct block_list* bl, va_list ap)
 
 	nullpo_ret(group = unit->group);
 
-	if( !(skill_get_inf2(group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP)) && !(skill_get_inf3(group->skill_id)&(INF3_NOLP)) && group->skill_id != NC_NEUTRALBARRIER && map_getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) )
+	if( !(skill_get_inf2(group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP)) && !(skill_get_inf3(group->skill_id)&(INF3_NOLP)) && group->skill_id != NC_NEUTRALBARRIER && map_getcell(unit->bl.m, unit->bl.x, unit->bl.y, CELL_CHKLANDPROTECTOR) )
 		return 0; //AoE skills are ineffective. [Skotlex]
 
 	if( battle_check_target(&unit->bl,bl,group->target_flag) <= 0 )

+ 0 - 9
src/map/unit.c

@@ -1947,15 +1947,6 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
 	if( sd ) {
 		if( skill_isNotOk(skill_id, sd) || !skill_check_condition_castbegin(sd, skill_id, skill_lv) )
 			return 0;
-
-		/**
-		 * Pneuma cannot be cancelled past this point, the client displays the animation even,
-		 * if we cancel it from nodamage_id, so it has to be here for it to not display the animation.
-		 */
-		if( skill_id == AL_PNEUMA && map_getcell(src->m, skill_x, skill_y, CELL_CHKLANDPROTECTOR) ) {
-			clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
-			return 0;
-		}
 	}
 
 	if( (skill_id >= SC_MANHOLE && skill_id <= SC_FEINTBOMB) && map_getcell(src->m, skill_x, skill_y, CELL_CHKMAELSTROM) ) {