|
@@ -4110,20 +4110,6 @@ static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data)
|
|
|
break;
|
|
|
switch( skl->skill_id )
|
|
|
{
|
|
|
- case WZ_METEOR:
|
|
|
- case SU_CN_METEOR:
|
|
|
- if( skl->type >= 0 )
|
|
|
- {
|
|
|
- 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)
|
|
|
- && !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) )
|
|
|
- skill_unitsetting(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,skl->flag);
|
|
|
- break;
|
|
|
case GN_CRAZYWEED_ATK:
|
|
|
{
|
|
|
int dummy = 1, i = skill_get_unit_range(skl->skill_id,skl->skill_lv);
|
|
@@ -11683,35 +11669,20 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
|
|
case WZ_METEOR:
|
|
|
case SU_CN_METEOR: {
|
|
|
int area = skill_get_splash(skill_id, skill_lv);
|
|
|
- short tmpx = 0, tmpy = 0, x1 = 0, y1 = 0;
|
|
|
-
|
|
|
+ short tmpx = 0, tmpy = 0;
|
|
|
if (sd && skill_id == SU_CN_METEOR) {
|
|
|
short item_idx = pc_search_inventory(sd, ITEMID_CATNIP_FRUIT);
|
|
|
-
|
|
|
if (item_idx >= 0) {
|
|
|
pc_delitem(sd, item_idx, 1, 0, 1, LOG_TYPE_CONSUME);
|
|
|
- skill_area_temp[3] = 1;
|
|
|
- } else
|
|
|
- skill_area_temp[3] = 0;
|
|
|
+ flag |= 1;
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- for( i = 0; i < 2 + (skill_lv>>1); i++ ) {
|
|
|
+ for (i = 1; i <= skill_get_time(skill_id, skill_lv)/skill_get_unit_interval(skill_id); i++) {
|
|
|
// Creates a random Cell in the Splash Area
|
|
|
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)
|
|
|
- && !map_getcell(src->m, tmpx, tmpy, CELL_CHKLANDPROTECTOR))
|
|
|
- clif_skill_poseffect(src,skill_id,skill_lv,tmpx,tmpy,tick);
|
|
|
-
|
|
|
- if( i > 0 )
|
|
|
- skill_addtimerskill(src,tick+i*1000,0,tmpx,tmpy,skill_id,skill_lv,(x1<<16)|y1,0);
|
|
|
-
|
|
|
- x1 = tmpx;
|
|
|
- y1 = tmpy;
|
|
|
+ skill_unitsetting(src, skill_id, skill_lv, tmpx, tmpy, flag+i*skill_get_unit_interval(skill_id));
|
|
|
}
|
|
|
-
|
|
|
- skill_addtimerskill(src,tick+i*1000,0,tmpx,tmpy,skill_id,skill_lv,-1,0);
|
|
|
}
|
|
|
break;
|
|
|
|
|
@@ -12496,6 +12467,7 @@ static bool skill_dance_switch(struct skill_unit* unit, int flag)
|
|
|
* @param x Position x
|
|
|
* @param y Position y
|
|
|
* @param flag &1: Used to determine when the skill 'morphs' (Warp portal becomes active, or Fire Pillar becomes active)
|
|
|
+ * xx_METEOR: flag &1 contains if the unit can cause curse, flag is also the duration of the unit in milliseconds
|
|
|
* @return skill_unit_group
|
|
|
*/
|
|
|
struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_id, uint16 skill_lv, int16 x, int16 y, int flag)
|
|
@@ -12566,7 +12538,11 @@ struct skill_unit_group *skill_unitsetting(struct block_list *src, uint16 skill_
|
|
|
case NPC_EVILLAND:
|
|
|
val1=skill_lv+3;
|
|
|
break;
|
|
|
-
|
|
|
+ case WZ_METEOR:
|
|
|
+ case SU_CN_METEOR:
|
|
|
+ limit = flag - (flag&1);
|
|
|
+ val1 = (flag&1);
|
|
|
+ break;
|
|
|
case WZ_FIREPILLAR:
|
|
|
if( map_getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) )
|
|
|
return NULL;
|
|
@@ -13430,28 +13406,36 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, uns
|
|
|
} while(sg->interval > 0 && x == bl->x && y == bl->y &&
|
|
|
++count < SKILLUNITTIMER_INTERVAL/sg->interval && !status_isdead(bl) );
|
|
|
}
|
|
|
- break;
|
|
|
+ break;
|
|
|
case WZ_HEAVENDRIVE:
|
|
|
status_change_end(bl, SC_SV_ROOTTWIST, INVALID_TIMER);
|
|
|
- break;
|
|
|
+ break;
|
|
|
#ifndef RENEWAL // The storm gust counter was dropped in renewal
|
|
|
case WZ_STORMGUST: //SG counter does not reset per stormgust. IE: One hit from a SG and two hits from another will freeze you.
|
|
|
if (tsc)
|
|
|
tsc->sg_counter++; //SG hit counter.
|
|
|
if (skill_attack(skill_get_type(sg->skill_id),ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick,0) <= 0 && tsc)
|
|
|
tsc->sg_counter=0; //Attack absorbed.
|
|
|
- break;
|
|
|
+ break;
|
|
|
#endif
|
|
|
case GS_DESPERADO:
|
|
|
if (rnd()%100 < unit->val1)
|
|
|
skill_attack(BF_WEAPON,ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
|
|
|
- break;
|
|
|
+ break;
|
|
|
+ case SU_CN_METEOR:
|
|
|
+ if (sg->val1)
|
|
|
+ skill_area_temp[3] = 1;
|
|
|
+ else
|
|
|
+ skill_area_temp[3] = 0;
|
|
|
+ skill_attack(skill_get_type(sg->skill_id),ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
|
|
|
+ break;
|
|
|
case GN_CRAZYWEED_ATK:
|
|
|
if( bl->type == BL_SKILL ) {
|
|
|
struct skill_unit *su = (struct skill_unit *)bl;
|
|
|
if( su && !(skill_get_inf2(su->group->skill_id)&INF2_TRAP) )
|
|
|
break;
|
|
|
}
|
|
|
+ //Fall through
|
|
|
default:
|
|
|
skill_attack(skill_get_type(sg->skill_id),ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
|
|
|
}
|
|
@@ -18165,7 +18149,12 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap)
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
+ if (group->val2 == 1 && (group->skill_id == WZ_METEOR || group->skill_id == SU_CN_METEOR)) {
|
|
|
+ // Deal damage before expiration
|
|
|
+ break;
|
|
|
+ }
|
|
|
skill_delunit(unit);
|
|
|
+ break;
|
|
|
}
|
|
|
} else {// skill unit is still active
|
|
|
switch( group->unit_id ) {
|
|
@@ -18220,6 +18209,20 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap)
|
|
|
skill_delunitgroup(group);
|
|
|
}
|
|
|
break;
|
|
|
+ default:
|
|
|
+ if (group->skill_id == WZ_METEOR || group->skill_id == SU_CN_METEOR) {
|
|
|
+ if (group->val2 == 0 && (DIFF_TICK(tick, group->tick) >= group->limit - group->interval || DIFF_TICK(tick, group->tick) >= unit->limit - group->interval)) {
|
|
|
+ // Unit will expire the next interval, start dropping Meteor
|
|
|
+ struct block_list* src;
|
|
|
+ if ((src = map_id2bl(group->src_id)) != NULL) {
|
|
|
+ clif_skill_poseffect(src, group->skill_id, group->skill_lv, bl->x, bl->y, tick);
|
|
|
+ group->val2 = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // No damage until expiration
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -18246,6 +18249,10 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap)
|
|
|
group->bl_flag= BL_NUL;
|
|
|
}
|
|
|
}
|
|
|
+ else if (group->skill_id == WZ_METEOR || group->skill_id == SU_CN_METEOR) {
|
|
|
+ skill_delunit(unit);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if( dissonance )
|