- Sacrifice no longer shows damage to self.

- When Asura fails, the skill display will still come off.
- Cleaned up AM_CALLHOMUN so that the required item is specified on skill_require_db
- Cleaned up function merc_call_homun and added function merc_hom_vaporize to handle the respective cases.
- Cleaned up a bit unit_remove_map/unit_free on regards to homun. it will display the /sob emotion when the homun dies due to low intimacy. Moved removal of timers and all that to unit_free
- Cleaned up function merc_hom_dead
- Simplified lots of code around by using the new merc functions.


git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@8279 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
skotlex 2006-08-14 19:48:16 +00:00
parent c8198b8ea7
commit 6e5a887656
9 changed files with 137 additions and 154 deletions

View File

@ -4,6 +4,11 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2006/08/14 2006/08/14
* Sacrifice no longer shows damage to self. [Skotlex]
* When Asura fails, the skill display will still come off. [Skotlex]
* Lots of cleaning of the Homun-code. Perhaps the crashes as of late will
be fixed now (reusing AM_CALLHOMUN seems to be the cause of them)
[Skotlex]
* Increased Run's walk speed bonus to 25->50% [Skotlex] * Increased Run's walk speed bonus to 25->50% [Skotlex]
* Modified emergency_call setting to allow for more specific configuration * Modified emergency_call setting to allow for more specific configuration
(woe/non-woe, gvg-grounds/non-gvg-grounds, disable from nowarpto maps), see (woe/non-woe, gvg-grounds/non-gvg-grounds, disable from nowarpto maps), see

View File

@ -172,7 +172,7 @@
236,0,0,25,0,0,0,99,0,0,none,0,7139,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //AM_CP_ARMOR#ケミカルア?マ?チャ?ジ# 236,0,0,25,0,0,0,99,0,0,none,0,7139,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //AM_CP_ARMOR#ケミカルア?マ?チャ?ジ#
237,0,0,25,0,0,0,99,0,0,none,0,7139,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //AM_CP_HELM#ケミカルヘルムチャ?ジ# 237,0,0,25,0,0,0,99,0,0,none,0,7139,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //AM_CP_HELM#ケミカルヘルムチャ?ジ#
243,0,0,10,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //AM_CALLHOMUNCULUS 243,0,0,10,0,0,0,99,0,0,none,0,7142,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //AM_CALLHOMUNCULUS
244,0,0,50,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //AM_REST 244,0,0,50,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //AM_REST
247,0,0,74:68:62:56:50,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //AM_RESURRECTHOMUN 247,0,0,74:68:62:56:50,0,0,0,99,0,0,none,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 //AM_RESURRECTHOMUN

View File

@ -1143,7 +1143,6 @@ static struct Damage battle_calc_weapon_attack(
case PA_SACRIFICE: case PA_SACRIFICE:
wd.damage = sstatus->max_hp* 9/100; wd.damage = sstatus->max_hp* 9/100;
status_zap(src, wd.damage, 0);//Damage to self is always 9% status_zap(src, wd.damage, 0);//Damage to self is always 9%
clif_damage(src,src, gettick(), 0, 0, wd.damage, 0 , 0, 0);
wd.damage2 = 0; wd.damage2 = 0;
if (sc && sc->data[SC_SACRIFICE].timer != -1) if (sc && sc->data[SC_SACRIFICE].timer != -1)

View File

@ -1670,8 +1670,7 @@ int map_quit(struct map_session_data *sd) {
sd->state.waitingdisconnect = 1; sd->state.waitingdisconnect = 1;
if (sd->pd) unit_free(&sd->pd->bl); if (sd->pd) unit_free(&sd->pd->bl);
if(sd->status.hom_id > 0 && sd->hd) //[orn] if (sd->hd) unit_free(&sd->hd->bl);
merc_hom_delete(sd->hd, 2) ;
unit_free(&sd->bl); unit_free(&sd->bl);
chrif_save(sd,1); chrif_save(sd,1);
} else { //Try to free some data, without saving anything (this could be invoked on map server change. [Skotlex] } else { //Try to free some data, without saving anything (this could be invoked on map server change. [Skotlex]

View File

@ -113,46 +113,69 @@ void merc_damage(struct homun_data *hd,struct block_list *src,int hp,int sp)
int merc_hom_dead(struct homun_data *hd, struct block_list *src) int merc_hom_dead(struct homun_data *hd, struct block_list *src)
{ {
hd->battle_status.hp = hd->master->homunculus.hp = 0 ; struct map_session_data *sd = hd->master;
clif_hominfo(hd->master,hd,0); // Send dead flag if (!sd)
if(!merc_hom_decrease_intimacy(hd, 100)) { // Intimacy was < 100 {
merc_stop_walking(hd, 1); clif_emotion(&hd->bl, 16) ; //wah
merc_stop_attack(hd); return 7;
clif_emotion(&hd->master->bl, 23) ; //omg
merc_hom_delete(hd,1) ;
return 1 ;
} }
sd->homunculus.hp = 0 ;
clif_hominfo(sd,hd,0); // Send dead flag
if(!merc_hom_decrease_intimacy(hd, 100)) { // Intimacy was < 100
clif_emotion(&sd->bl, 23) ; //omg
return 7; //Delete from memory.
}
clif_send_homdata(hd->master,SP_INTIMATE,hd->master->homunculus.intimacy / 100); clif_send_homdata(hd->master,SP_INTIMATE,hd->master->homunculus.intimacy / 100);
clif_emotion(&hd->bl, 16) ; //wah clif_emotion(&hd->bl, 16) ; //wah
clif_emotion(&hd->master->bl, 28) ; //sob clif_emotion(&sd->bl, 28) ; //sob
merc_hom_delete(hd, 0); return 3; //Remove from map.
return 1; // Removing is handled by merc_hom_delete
} }
int merc_hom_delete(struct homun_data *hd, int flag) //Vaporize a character's homun. If flag, HP needs to be 80% or above.
int merc_hom_vaporize(struct map_session_data *sd, int flag)
{ {
nullpo_retr(0, hd); struct homun_data *hd;
if ((flag & 2) && hd->bl.prev == NULL) nullpo_retr(0, sd);
{
// Homunc was already removed from map, so just free the bl
return unit_free(&hd->bl);
}
// Delete homunculus hd = sd->hd;
if ( flag&1 ) { //sabbath if (!hd || sd->homunculus.vaporize)
intif_homunculus_requestdelete(hd->master->homunculus.hom_id) ; return 0;
clif_emotion(&hd->bl, 28) ; //sob
hd->master->status.hom_id = 0; if (flag && hd->battle_status.hp < (hd->battle_status.max_hp*80/100))
hd->master->homunculus.hom_id = 0; return 0;
chrif_save(hd->master,0);
} else sd->homunculus.vaporize = 1;
clif_hominfo(sd, sd->hd, 0);
merc_save(hd); merc_save(hd);
return unit_remove_map(&hd->bl, 0); return unit_remove_map(&hd->bl, 0);
} }
//delete a homunculus, completely "killing it".
//Emote is the emotion the master should use, send negative to disable.
int merc_hom_delete(struct homun_data *hd, int emote)
{
struct map_session_data *sd;
nullpo_retr(0, hd);
sd = hd->master;
if (!sd)
return unit_free(&hd->bl);
if (emote >= 0)
clif_emotion(&sd->bl, emote);
//This makes it be deleted right away.
sd->homunculus.intimacy = 0;
// Send homunculus_dead to client
sd->homunculus.hp = 0;
clif_hominfo(sd, hd, 0);
return unit_free(&hd->bl);
}
int merc_hom_calc_skilltree(struct map_session_data *sd) int merc_hom_calc_skilltree(struct map_session_data *sd)
{ {
int i,id=0 ; int i,id=0 ;
@ -314,7 +337,7 @@ int merc_hom_evolution(struct homun_data *hd)
hd->master->homunculus.vaporize = 1; hd->master->homunculus.vaporize = 1;
merc_stop_walking(hd, 1); merc_stop_walking(hd, 1);
merc_stop_attack(hd); merc_stop_attack(hd);
merc_hom_delete(hd, 0) ; merc_hom_delete(hd, -1) ;
merc_call_homunculus(hd->master); merc_call_homunculus(hd->master);
clif_emotion(&hd->master->bl, 21) ; //no1 clif_emotion(&hd->master->bl, 21) ; //no1
clif_misceffect2(&hd->bl,568); clif_misceffect2(&hd->bl,568);
@ -442,10 +465,10 @@ static int merc_natural_heal_sub(struct homun_data *hd,int tick) {
// tick = va_arg(ap,int); // tick = va_arg(ap,int);
// -- moonsoul (if conditions below altered to disallow natural healing if under berserk status) // -- moonsoul (if conditions below altered to disallow natural healing if under berserk status)
if ( hd && ( status_isdead(&hd->bl) || if ( status_isdead(&hd->bl) ||
( ( hd->sc.count ) && ( ( hd->sc.count ) &&
( (hd->sc.data[SC_POISON].timer != -1 ) || ( hd->sc.data[SC_BLEEDING].timer != -1 ) ) ( (hd->sc.data[SC_POISON].timer != -1 ) || ( hd->sc.data[SC_BLEEDING].timer != -1 ) )
) ) )
) { //Cannot heal neither natural or special. ) { //Cannot heal neither natural or special.
hd->hp_sub = hd->inchealhptick = 0; hd->hp_sub = hd->inchealhptick = 0;
hd->sp_sub = hd->inchealsptick = 0; hd->sp_sub = hd->inchealsptick = 0;
@ -578,7 +601,7 @@ int merc_menu(struct map_session_data *sd,int menunum)
merc_hom_food(sd, sd->hd); merc_hom_food(sd, sd->hd);
break; break;
case 2: case 2:
merc_hom_delete(sd->hd, 1); merc_hom_delete(sd->hd, -1);
break; break;
default: default:
ShowError("merc_menu : unknown menu choice : %d\n", menunum) ; ShowError("merc_menu : unknown menu choice : %d\n", menunum) ;
@ -629,15 +652,9 @@ int merc_hom_food(struct map_session_data *sd, struct homun_data *hd)
clif_hom_food(sd,hd->homunculusDB->foodID,1); clif_hom_food(sd,hd->homunculusDB->foodID,1);
// Too much food :/ // Too much food :/
if(sd->homunculus.intimacy == 0) { if(sd->homunculus.intimacy == 0)
merc_stop_walking(hd, 1); return merc_hom_delete(sd->hd, 23); //omg
merc_stop_attack(hd);
// Send homunculus_dead to client
sd->homunculus.hp = 0;
clif_hominfo(sd, hd, 0);
merc_hom_delete(hd,1);
clif_emotion(&sd->bl, 23); //omg
}
return 0; return 0;
} }
@ -674,19 +691,10 @@ static int merc_hom_hungry(int tid,unsigned int tick,int id,int data)
if(sd->homunculus.hunger < 0) { if(sd->homunculus.hunger < 0) {
sd->homunculus.hunger = 0; sd->homunculus.hunger = 0;
// Delete the homunculus if intimacy <= 100 // Delete the homunculus if intimacy <= 100
if ( !merc_hom_decrease_intimacy(hd, 100) ) { if ( !merc_hom_decrease_intimacy(hd, 100) )
merc_stop_walking(hd, 1); return merc_hom_delete(sd->hd, 23); //omg
merc_stop_attack(hd);
// Send homunculus_dead to client
sd->homunculus.hp = 0;
clif_hominfo(sd, hd, 0);
merc_hom_delete(hd,1);
clif_emotion(&sd->bl, 23) ; //omg
return 0 ;
} else {
clif_send_homdata(sd,SP_INTIMATE,sd->homunculus.intimacy / 100); clif_send_homdata(sd,SP_INTIMATE,sd->homunculus.intimacy / 100);
} }
}
clif_send_homdata(sd,SP_HUNGRY,sd->homunculus.hunger); clif_send_homdata(sd,SP_HUNGRY,sd->homunculus.hunger);
hd->hungry_timer = add_timer(tick+hd->homunculusDB->hungryDelay,merc_hom_hungry,sd->bl.id,0); //simple Fix albator hd->hungry_timer = add_timer(tick+hd->homunculusDB->hungryDelay,merc_hom_hungry,sd->bl.id,0); //simple Fix albator
@ -812,45 +820,34 @@ int merc_hom_data_init(struct map_session_data *sd)
return 0; return 0;
} }
// FIX call_homunculus [albator]
int merc_call_homunculus(struct map_session_data *sd) int merc_call_homunculus(struct map_session_data *sd)
{ {
int class_ = 0 ; struct homun_data *hd;
nullpo_retr(0, sd);
if (!sd->status.hom_id) if (!sd->status.hom_id) //Create a new homun.
{ return merc_create_homunculus(sd, 6000 + rand(1, 8)) ;
class_ = 6000 + rand(1, 8) ;
return merc_create_homunculus(sd, class_) ;
}
// If homunc not yet loaded, load it, else just activate it //Recall homunculus to you.
if (sd->homunculus.vaporize)
return 0; //Can't use this when homun was vaporized.
// If homunc not yet loaded, load it
if (!sd->hd) if (!sd->hd)
merc_hom_create(sd); merc_hom_create(sd);
else
merc_hom_data_init(sd);
// call vaporized homunculus [albator] hd = sd->hd;
if(sd->homunculus.vaporize == 1) if (hd->bl.prev == NULL)
{ { //Spawn him
sd->homunculus.vaporize = 0; map_addblock(&hd->bl);
} clif_spawn(&hd->bl);
else
{
// Homunc was dead, set hp to 1
sd->homunculus.hp = 1 ;
}
if ( sd->homunculus.hp && sd->hd && sd->bl.prev != NULL) {
map_addblock(&sd->hd->bl);
clif_spawn(&sd->hd->bl);
clif_send_homdata(sd,SP_ACK,0); clif_send_homdata(sd,SP_ACK,0);
clif_hominfo(sd,sd->hd,1); clif_hominfo(sd,hd,1);
clif_hominfo(sd,sd->hd,0); // send this x2. dunno why, but kRO does that [blackhole89] clif_hominfo(sd,hd,0); // send this x2. dunno why, but kRO does that [blackhole89]
clif_homskillinfoblock(sd); clif_homskillinfoblock(sd);
} merc_save(hd);
// save } else
merc_save(sd->hd); //Warp him to master.
unit_warp(&hd->bl,sd->bl.m,sd->bl.x,sd->bl.y,0);
return 1; return 1;
} }

View File

@ -62,7 +62,7 @@ int merc_hom_gainexp(struct homun_data *hd,int exp) ;
int merc_hom_levelup(struct homun_data *hd) ; int merc_hom_levelup(struct homun_data *hd) ;
int merc_hom_evolution(struct homun_data *hd) ; int merc_hom_evolution(struct homun_data *hd) ;
void merc_hom_heal(struct homun_data *hd,int hp,int sp); void merc_hom_heal(struct homun_data *hd,int hp,int sp);
int merc_hom_delete(struct homun_data *hd, int flag) ; int merc_hom_vaporize(struct map_session_data *sd, int flag);
int merc_hom_revive(struct map_session_data *sd, int per); int merc_hom_revive(struct map_session_data *sd, int per);
void merc_save(struct homun_data *hd); void merc_save(struct homun_data *hd);
int merc_call_homunculus(struct map_session_data *sd); int merc_call_homunculus(struct map_session_data *sd);

View File

@ -4783,14 +4783,8 @@ int pc_dead(struct map_session_data *sd,struct block_list *src)
pet_unlocktarget(sd->pd); pet_unlocktarget(sd->pd);
} }
if(sd->status.hom_id > 0 && sd->hd) //orn if(sd->status.hom_id > 0) //orn
{ merc_hom_vaporize(sd, 0);
sd->homunculus.vaporize = 1;
clif_hominfo(sd,sd->hd,0);
merc_stop_walking(sd->hd, 1) ;
merc_stop_attack(sd->hd) ;
merc_hom_delete(sd->hd,0);
}
// Leave duel if you die [LuzZza] // Leave duel if you die [LuzZza]
if(battle_config.duel_autoleave_when_die) { if(battle_config.duel_autoleave_when_die) {

View File

@ -5487,37 +5487,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
break; break;
case AM_CALLHOMUN: //[orn] case AM_CALLHOMUN: //[orn]
if (sd) if (sd && !merc_call_homunculus(sd))
{
if (sd->status.hom_id == 0 || sd->homunculus.vaporize == 1) {
if (sd->status.hom_id == 0) {
i = pc_search_inventory(sd,7142);
if(i < 0) {
clif_skill_fail(sd,skillid,0,0); clif_skill_fail(sd,skillid,0,0);
break; break;
}
pc_delitem(sd,i,1,0);
}
if (merc_call_homunculus(sd))
break;
}
clif_skill_fail(sd,skillid,0,0);
}
break;
case AM_REST: //[orn] case AM_REST: //[orn]
{ if (sd && !merc_hom_vaporize(sd,1))
if (sd)
{
if (sd->hd && !sd->homunculus.vaporize && ( sd->hd->battle_status.hp >= (sd->hd->battle_status.max_hp * 80 / 100 ) ) ) {
sd->homunculus.vaporize = 1;
clif_hominfo(sd, sd->hd, 0);
merc_hom_delete(sd->hd, 0) ;
} else
clif_skill_fail(sd,skillid,0,0); clif_skill_fail(sd,skillid,0,0);
}
break; break;
}
case AM_RESURRECTHOMUN: //[orn] case AM_RESURRECTHOMUN: //[orn]
{ {
if (sd) if (sd)
@ -5821,8 +5799,10 @@ int skill_castend_id (int tid, unsigned int tick, int id, int data)
else if(dy < 0) dy--; else if(dy < 0) dy--;
if (unit_movepos(src, src->x+dx, src->y+dy, 1, 1)) if (unit_movepos(src, src->x+dx, src->y+dy, 1, 1))
{ //Display movement + animation.
clif_slide(src,src->x,src->y); clif_slide(src,src->x,src->y);
clif_skill_damage(src,target,tick,sd->battle_status.amotion,0,0,1,ud->skillid, ud->skilllv, 5);
}
clif_skill_fail(sd,ud->skillid,0,0); clif_skill_fail(sd,ud->skillid,0,0);
} }
} }
@ -8320,6 +8300,14 @@ int skill_check_condition (struct map_session_data *sd, int skill, int lv, int t
} }
zeny = 0; //Zeny is reduced on skill_attack. zeny = 0; //Zeny is reduced on skill_attack.
break; break;
case AM_CALLHOMUN: //Can't summon if a hom is already out (vaporized also counts).
if (sd->status.hom_id || sd->homunculus.vaporize) {
clif_skill_fail(sd,skill,0,0);
return 0;
}
if (sd->status.hom_id) //Don't delete items when hom is already out.
delitem_flag = 0;
break;
} }
if(!(type&2)){ if(!(type&2)){

View File

@ -1497,7 +1497,6 @@ int unit_remove_map(struct block_list *bl, int clrtype) {
unit_skillcastcancel(bl,0); unit_skillcastcancel(bl,0);
// Do not reset can-act delay. [Skotlex] // Do not reset can-act delay. [Skotlex]
ud->attackabletime = ud->canmove_tick /*= ud->canact_tick*/ = gettick(); ud->attackabletime = ud->canmove_tick /*= ud->canact_tick*/ = gettick();
clif_clearchar_area(bl,clrtype);
if(sc && sc->count ) { //map-change/warp dispells. if(sc && sc->count ) { //map-change/warp dispells.
if(sc->data[SC_BLADESTOP].timer!=-1) if(sc->data[SC_BLADESTOP].timer!=-1)
@ -1588,18 +1587,8 @@ int unit_remove_map(struct block_list *bl, int clrtype) {
struct pet_data *pd = (struct pet_data*)bl; struct pet_data *pd = (struct pet_data*)bl;
struct map_session_data *sd = pd->msd; struct map_session_data *sd = pd->msd;
if(!sd) { if(!sd || sd->pet.intimate <= 0) {
map_delblock(bl); clif_clearchar_area(bl,clrtype);
unit_free(bl);
map_freeblock_unlock();
return 0;
}
if (sd->pet.intimate <= 0)
{ //Remove pet.
intif_delete_petdata(sd->status.pet_id);
sd->status.pet_id = 0;
sd->pd = NULL;
pd->msd = NULL;
map_delblock(bl); map_delblock(bl);
unit_free(bl); unit_free(bl);
map_freeblock_unlock(); map_freeblock_unlock();
@ -1608,28 +1597,17 @@ int unit_remove_map(struct block_list *bl, int clrtype) {
} else if (bl->type == BL_HOM) { } else if (bl->type == BL_HOM) {
struct homun_data *hd = (struct homun_data *) bl; struct homun_data *hd = (struct homun_data *) bl;
struct map_session_data *sd = hd->master; struct map_session_data *sd = hd->master;
if(!sd || !sd->homunculus.intimacy)
// Desactive timers { //He's going to be deleted.
merc_hom_hungry_timer_delete(hd); clif_emotion(bl, 28) ; //sob
merc_natural_heal_timer_delete(hd); clif_clearchar_area(bl,clrtype);
if(!sd) {
map_delblock(bl); map_delblock(bl);
unit_free(bl); unit_free(bl);
map_freeblock_unlock(); map_freeblock_unlock();
return 0; return 0;
} }
// Homunc was deleted or player is leaving the server, remove it from memory
if (sd->homunculus.hom_id == 0 || sd->state.waitingdisconnect)
{ //Remove pet.
map_delblock(bl);
unit_free(bl);
sd->hd = NULL;
map_freeblock_unlock();
return 1;
}
} }
clif_clearchar_area(bl,clrtype);
map_delblock(bl); map_delblock(bl);
map_freeblock_unlock(); map_freeblock_unlock();
return 1; return 1;
@ -1761,9 +1739,14 @@ int unit_free(struct block_list *bl) {
pd->loot = NULL; pd->loot = NULL;
} }
if (sd) { if (sd) {
sd->pd = NULL;
if(sd->pet.intimate > 0) if(sd->pet.intimate > 0)
intif_save_petdata(sd->status.account_id,&sd->pet); intif_save_petdata(sd->status.account_id,&sd->pet);
sd->pd = NULL; else
{ //Remove pet.
intif_delete_petdata(sd->status.pet_id);
sd->status.pet_id = 0;
}
} }
} else if(bl->type == BL_MOB) { } else if(bl->type == BL_MOB) {
struct mob_data *md = (struct mob_data*)bl; struct mob_data *md = (struct mob_data*)bl;
@ -1794,6 +1777,24 @@ int unit_free(struct block_list *bl) {
} }
if(mob_is_clone(md->class_)) if(mob_is_clone(md->class_))
mob_clone_delete(md->class_); mob_clone_delete(md->class_);
} else if(bl->type == BL_HOM) {
struct homun_data *hd = (TBL_HOM*)bl;
struct map_session_data *sd = hd->master;
// Desactive timers
merc_hom_hungry_timer_delete(hd);
merc_natural_heal_timer_delete(hd);
if(sd) {
sd->hd = NULL;
hd->master = NULL;
if (sd->homunculus.intimacy > 0)
merc_save(hd);
else
{
intif_homunculus_requestdelete(sd->homunculus.hom_id) ;
sd->status.hom_id = 0;
sd->homunculus.hom_id = 0;
}
}
} }
skill_clear_unitgroup(bl); skill_clear_unitgroup(bl);