* Fixed bugreport:9211. Basilica causes map-server crashed when caster changing map
* Some source docs for skill.c/h Signed-off-by: Cydh Ramdh <house.bad@gmail.com>
This commit is contained in:
parent
adabedba23
commit
d270047312
@ -507,7 +507,7 @@
|
||||
//****
|
||||
// High Priest
|
||||
361,9,6,16,0,0x1,1,5,1,yes,0,0,0,magic,0,0x0, HP_ASSUMPTIO,Assumptio
|
||||
362,4,6,4,0,0x1,0,5,1,yes,0,0,0,magic,2,0x0, HP_BASILICA,Basilica
|
||||
362,4,6,4,0,0x1,0,5,1,yes,0,0,1,magic,2,0x0, HP_BASILICA,Basilica
|
||||
363,0,0,0,0,0,0,10,0,no,0,0,0,magic,0,0x0, HP_MEDITATIO,Meditatio
|
||||
|
||||
//****
|
||||
|
@ -83,7 +83,7 @@
|
||||
330,0xaf, , 3, 0, -1,all, 0x140 //DC_SERVICEFORYOU
|
||||
336,0xb2, , 0,-1, -1,noone, 0x000 //WE_CALLPARTNER
|
||||
339,0x86, , -1, 0, 300,enemy, 0x000 //NPC_DARKGRANDCROSS
|
||||
362,0xb4, , 0, 2, 300,all, 0x000 //HP_BASILICA
|
||||
362,0xb4, , 2, 0, 300,all, 0x2000 //HP_BASILICA
|
||||
369,0xb3, , -1, 0,10000,all, 0x008 //PA_GOSPEL
|
||||
395,0xb5, , 4, 0, -1,all, 0x200 //CG_MOONLIT
|
||||
404,0xb6, , -1, 0, -1,all, 0x8000 //PF_FOGWALL
|
||||
|
@ -507,7 +507,7 @@
|
||||
//****
|
||||
// High Priest
|
||||
361,9,6,16,0,0x1,1,5,1,yes,0,0,0,magic,0,0x0, HP_ASSUMPTIO,Assumptio
|
||||
362,4,6,4,0,0x1,0,5,1,yes,0,0,0,magic,2,0x0, HP_BASILICA,Basilica
|
||||
362,4,6,4,0,0x1,0,5,1,yes,0,0,1,magic,2,0x0, HP_BASILICA,Basilica
|
||||
363,0,0,0,0,0,0,10,0,no,0,0,0,magic,0,0x0, HP_MEDITATIO,Meditatio
|
||||
|
||||
//****
|
||||
|
@ -83,7 +83,7 @@
|
||||
330,0xaf, , 3, 0, -1,all, 0x140 //DC_SERVICEFORYOU
|
||||
336,0xb2, , 0,-1, -1,noone, 0x000 //WE_CALLPARTNER
|
||||
339,0x86, , -1, 0, 300,enemy, 0x000 //NPC_DARKGRANDCROSS
|
||||
362,0xb4, , 0, 2, 300,all, 0x000 //HP_BASILICA
|
||||
362,0xb4, , 2, 0, 300,all, 0x2000 //HP_BASILICA
|
||||
369,0xb3, , -1, 0,10000,all, 0x008 //PA_GOSPEL
|
||||
395,0xb5, , 4, 0, -1,all, 0x200 //CG_MOONLIT
|
||||
404,0xb6, , -1, 0, -1,all, 0x8000 //PF_FOGWALL
|
||||
|
@ -8418,6 +8418,9 @@ bool pc_candrop(struct map_session_data *sd, struct item *item)
|
||||
bool pc_can_attack( struct map_session_data *sd, int target_id ) {
|
||||
nullpo_retr(false, sd);
|
||||
|
||||
if (!&sd->sc)
|
||||
return true;
|
||||
|
||||
if( sd->sc.data[SC_BASILICA] ||
|
||||
sd->sc.data[SC__SHADOWFORM] ||
|
||||
sd->sc.data[SC__MANHOLE] ||
|
||||
@ -9394,7 +9397,7 @@ bool pc_unequipitem(struct map_session_data *sd,int n,int flag) {
|
||||
|
||||
if((sd->status.inventory[n].equip & EQP_ARMS) &&
|
||||
sd->weapontype1 == 0 && sd->weapontype2 == 0 && (!sd->sc.data[SC_SEVENWIND] || sd->sc.data[SC_ASPERSIO])) //Check for seven wind (but not level seven!)
|
||||
skill_enchant_elemental_end(&sd->bl,-1);
|
||||
skill_enchant_elemental_end(&sd->bl,SC_NONE);
|
||||
|
||||
if(sd->status.inventory[n].equip & EQP_ARMOR) {
|
||||
// On Armor Change...
|
||||
|
323
src/map/skill.c
323
src/map/skill.c
@ -10974,8 +10974,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
|
||||
return 0;
|
||||
}
|
||||
skill_clear_unitgroup(src);
|
||||
if( skill_unitsetting(src,skill_id,skill_lv,x,y,0) )
|
||||
sc_start4(src,src,type,100,skill_lv,0,0,src->id,skill_get_time(skill_id,skill_lv));
|
||||
skill_unitsetting(src,skill_id,skill_lv,x,y,0);
|
||||
flag|=1;
|
||||
}
|
||||
break;
|
||||
@ -11805,8 +11804,14 @@ static int skill_icewall_block(struct block_list *bl,va_list ap) {
|
||||
return 0;
|
||||
}
|
||||
/*==========================================
|
||||
* Initializes and sets a ground skill.
|
||||
* flag&1 is used to determine when the skill 'morphs' (Warp portal becomes active, or Fire Pillar becomes active)
|
||||
* Initializes and sets a ground skill / skill unit. Usually called after skill_casted_pos() or skill_castend_map()
|
||||
* @param src Object that triggers the skill
|
||||
* @param skill_id Skill ID
|
||||
* @param skill_lv Skill level of used skill
|
||||
* @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)
|
||||
* @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)
|
||||
{
|
||||
@ -12133,7 +12138,8 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
|
||||
break;
|
||||
}
|
||||
|
||||
nullpo_retr(NULL, group=skill_initunitgroup(src,layout->count,skill_id,skill_lv,skill_get_unit_id(skill_id,flag&1)+subunt, limit, interval));
|
||||
// Init skill unit group
|
||||
nullpo_retr(NULL, (group = skill_initunitgroup(src,layout->count,skill_id,skill_lv,skill_get_unit_id(skill_id,flag&1)+subunt, limit, interval)));
|
||||
group->val1 = val1;
|
||||
group->val2 = val2;
|
||||
group->val3 = val3;
|
||||
@ -12143,10 +12149,11 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
|
||||
group->state.song_dance = (unit_flag&(UF_DANCE|UF_SONG)?1:0)|(unit_flag&UF_ENSEMBLE?2:0); //Signals if this is a song/dance/duet
|
||||
group->state.guildaura = ( skill_id >= GD_LEADERSHIP && skill_id <= GD_HAWKEYES )?1:0;
|
||||
group->item_id = req_item;
|
||||
//if tick is greater than current, do not invoke onplace function just yet. [Skotlex]
|
||||
// If tick is greater than current, do not invoke onplace function just yet. [Skotlex]
|
||||
if (DIFF_TICK(group->tick, gettick()) > SKILLUNITTIMER_INTERVAL)
|
||||
active_flag = 0;
|
||||
|
||||
// Put message for Talkie Box & Graffiti
|
||||
if (skill_id == HT_TALKIEBOX || skill_id == RG_GRAFFITI) {
|
||||
group->valstr=(char *) aMalloc(MESSAGE_SIZE*sizeof(char));
|
||||
if (sd)
|
||||
@ -12155,22 +12162,22 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
|
||||
safestrncpy(group->valstr, "Boo!", MESSAGE_SIZE);
|
||||
}
|
||||
|
||||
// Dance skill
|
||||
if (group->state.song_dance) {
|
||||
if(sd) {
|
||||
sd->skill_id_dance = skill_id;
|
||||
sd->skill_lv_dance = skill_lv;
|
||||
}
|
||||
if (
|
||||
sc_start4(src, src, SC_DANCING, 100, skill_id, group->group_id, skill_lv,
|
||||
(group->state.song_dance&2?BCT_SELF:0), limit+1000) &&
|
||||
sc_start4(src, src, SC_DANCING, 100, skill_id, group->group_id, skill_lv, (group->state.song_dance&2?BCT_SELF:0), limit+1000) &&
|
||||
sd && group->state.song_dance&2 && skill_id != CG_HERMODE //Hermod is a encore with a warp!
|
||||
)
|
||||
skill_check_pc_partner(sd, skill_id, &skill_lv, 1, 1);
|
||||
}
|
||||
|
||||
// Set skill unit
|
||||
limit = group->limit;
|
||||
for( i = 0; i < layout->count; i++ )
|
||||
{
|
||||
for( i = 0; i < layout->count; i++ ) {
|
||||
struct skill_unit *unit;
|
||||
int ux = x + layout->dx[i];
|
||||
int uy = y + layout->dy[i];
|
||||
@ -12188,8 +12195,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
|
||||
if( battle_config.skill_wall_check && unit_flag&UF_PATHCHECK && !path_search_long(NULL,src->m,ux,uy,x,y,CELL_CHKWALL) )
|
||||
continue; // no path between cell and center of casting.
|
||||
|
||||
switch( skill_id )
|
||||
{
|
||||
switch( skill_id ) {
|
||||
case MG_FIREWALL:
|
||||
case NJ_KAENSIN:
|
||||
val2_2 = group->val2;
|
||||
@ -12254,12 +12260,13 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
|
||||
if( sd && map_getcell(src->m, ux, uy, CELL_CHKMAELSTROM) ) //Does not recover SP from monster skills
|
||||
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);
|
||||
if( !alive )
|
||||
continue;
|
||||
|
||||
nullpo_retr(NULL, unit=skill_initunit(group,i,ux,uy,val1_2,val2_2));
|
||||
nullpo_retr(NULL, (unit = skill_initunit(group,i,ux,uy,val1_2,val2_2)));
|
||||
unit->limit = limit;
|
||||
unit->range = range;
|
||||
|
||||
@ -12269,7 +12276,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
|
||||
group->limit = unit->limit;
|
||||
}
|
||||
|
||||
// execute on all targets standing on this cell
|
||||
// Execute on all targets standing on this cell
|
||||
if (range == 0 && active_flag)
|
||||
map_foreachincell(skill_unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,gettick(),1);
|
||||
}
|
||||
@ -12297,10 +12304,17 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
|
||||
*
|
||||
*------------------------------------------*/
|
||||
void ext_skill_unit_onplace(struct skill_unit *unit, struct block_list *bl, unsigned int tick){skill_unit_onplace(unit, bl, tick);}
|
||||
/**
|
||||
* Triggeres when 'target' (based on skill unit target) is step in unit area.
|
||||
* As a follow of skill_unit_effect flag &1
|
||||
* @param unit
|
||||
* @param bl Target
|
||||
* @param tick
|
||||
*/
|
||||
static int skill_unit_onplace (struct skill_unit *unit, struct block_list *bl, unsigned int tick)
|
||||
{
|
||||
struct skill_unit_group *sg;
|
||||
struct block_list *ss;
|
||||
struct block_list *ss; // Actual source that cast the skill unit
|
||||
struct status_change *sc;
|
||||
struct status_change_entry *sce;
|
||||
enum sc_type type;
|
||||
@ -12478,6 +12492,20 @@ static int skill_unit_onplace (struct skill_unit *unit, struct block_list *bl, u
|
||||
sc_start4(ss, bl,type,100,sg->skill_lv,0,BCT_ENEMY,sg->group_id,sg->limit);
|
||||
break;
|
||||
|
||||
case UNT_BASILICA:
|
||||
{
|
||||
int i = battle_check_target(bl, bl, BCT_ENEMY);
|
||||
if( i > 0 && !(status_get_mode(bl)&MD_BOSS) )
|
||||
{ // knock-back any enemy except Boss
|
||||
skill_blown(ss, bl, skill_get_blewcount(skill_id, sg->skill_lv), unit_getdir(bl), 0);
|
||||
clif_fixpos(bl);
|
||||
break;
|
||||
}
|
||||
if (!sce && i <= 0)
|
||||
sc_start4(ss, bl, type, 100, 0, 0, sg->group_id, ss->id, sg->limit);
|
||||
}
|
||||
break;
|
||||
|
||||
// officially, icewall has no problems existing on occupied cells [ultramage]
|
||||
// case UNT_ICEWALL: //Destroy the cell. [Skotlex]
|
||||
// unit->val1 = 0;
|
||||
@ -12522,7 +12550,10 @@ static int skill_unit_onplace (struct skill_unit *unit, struct block_list *bl, u
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
* Process skill unit each interval (sg->interval, see interval field of skill_unit_db.txt)
|
||||
* @param src Skill unit
|
||||
* @param bl Valid 'target' above the unit, that has been check in skill_unit_timer_sub_onplace
|
||||
* @param tick
|
||||
*------------------------------------------*/
|
||||
int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, unsigned int tick)
|
||||
{
|
||||
@ -12959,12 +12990,12 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
int i = battle_check_target(&src->bl, bl, BCT_ENEMY);
|
||||
if( i > 0 && !(status_get_mode(bl)&MD_BOSS) )
|
||||
{ // knock-back any enemy except Boss
|
||||
skill_blown(&src->bl, bl, 2, unit_getdir(bl), 0);
|
||||
skill_blown(&src->bl, bl, skill_get_blewcount(skill_id, sg->skill_lv), unit_getdir(bl), 0);
|
||||
clif_fixpos(bl);
|
||||
break;
|
||||
}
|
||||
|
||||
if( sg->src_id != bl->id && i <= 0 )
|
||||
sc_start4(ss, bl, type, 100, 0, 0, 0, src->bl.id, sg->interval + 100);
|
||||
if (i <= 0 && (!tsc || !tsc->data[SC_BASILICA]))
|
||||
sc_start4(ss, bl, type, 100, 0, 0, sg->group_id, ss->id, sg->limit);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -12995,7 +13026,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
**/
|
||||
case UNT_POISONSMOKE:
|
||||
if( battle_check_target(ss,bl,BCT_ENEMY) > 0 && !(tsc && tsc->data[sg->val2]) && rnd()%100 < 20 )
|
||||
sc_start(ss, bl,sg->val2,100,sg->val3,skill_get_time2(GC_POISONINGWEAPON, 1));
|
||||
sc_start(ss,bl,(sc_type)sg->val2,100,sg->val3,skill_get_time2(GC_POISONINGWEAPON, 1));
|
||||
break;
|
||||
|
||||
case UNT_EPICLESIS:
|
||||
@ -13040,7 +13071,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
|
||||
case UNT_DIMENSIONDOOR:
|
||||
if( tsd && !map[bl->m].flag.noteleport )
|
||||
pc_randomwarp(tsd,3);
|
||||
pc_randomwarp(tsd,CLR_TELEPORT);
|
||||
else if( bl->type == BL_MOB && battle_config.mob_warp&8 )
|
||||
unit_warp(bl,-1,-1,-1,CLR_TELEPORT);
|
||||
break;
|
||||
@ -13260,7 +13291,10 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
|
||||
return skill_id;
|
||||
}
|
||||
/*==========================================
|
||||
* Triggered when a char steps out of a skill cell
|
||||
* Triggered when a char steps out of a skill unit
|
||||
* @param src Skill unit from char moved out
|
||||
* @param bl Char
|
||||
* @param tick
|
||||
*------------------------------------------*/
|
||||
int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned int tick)
|
||||
{
|
||||
@ -13290,9 +13324,10 @@ int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned in
|
||||
break;
|
||||
|
||||
case UNT_BASILICA:
|
||||
if (sce)
|
||||
if (sce && sce->val4 != bl->id)
|
||||
status_change_end(bl, type, INVALID_TIMER);
|
||||
break;
|
||||
|
||||
case UNT_HERMODE: //Clear Hermode if the owner moved.
|
||||
if (sce && sce->val3 == BCT_SELF && sce->val4 == sg->group_id)
|
||||
status_change_end(bl, type, INVALID_TIMER);
|
||||
@ -13337,6 +13372,9 @@ int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned in
|
||||
|
||||
/*==========================================
|
||||
* Triggered when a char steps out of a skill group (entirely) [Skotlex]
|
||||
* @param skill_id Skill ID
|
||||
* @param bl A char
|
||||
* @param tick
|
||||
*------------------------------------------*/
|
||||
int skill_unit_onleft (uint16 skill_id, struct block_list *bl, unsigned int tick)
|
||||
{
|
||||
@ -13516,9 +13554,13 @@ static int skill_unit_effect (struct block_list* bl, va_list ap)
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
* Check skill unit while receiving damage
|
||||
* @param unit Skill unit
|
||||
* @param bl Attacker
|
||||
* @param damage Received damage
|
||||
* @return Damage
|
||||
*------------------------------------------*/
|
||||
int64 skill_unit_ondamaged (struct skill_unit *unit, struct block_list *bl, int64 damage, unsigned int tick)
|
||||
int64 skill_unit_ondamaged (struct skill_unit *unit, struct block_list *bl, int64 damage)
|
||||
{
|
||||
struct skill_unit_group *sg;
|
||||
|
||||
@ -13550,7 +13592,12 @@ int64 skill_unit_ondamaged (struct skill_unit *unit, struct block_list *bl, int6
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
* Check char condition around the skill caster
|
||||
* @param bl Char around area
|
||||
* @param *c Counter for 'valid' condition found
|
||||
* @param *p_sd Stores 'rid' of char found
|
||||
* @param skill_id Skill ID
|
||||
* @param skill_lv Level of used skill
|
||||
*------------------------------------------*/
|
||||
int skill_check_condition_char_sub (struct block_list *bl, va_list ap)
|
||||
{
|
||||
@ -13639,6 +13686,12 @@ int skill_check_condition_char_sub (struct block_list *bl, va_list ap)
|
||||
|
||||
/*==========================================
|
||||
* Checks and stores partners for ensemble skills [Skotlex]
|
||||
* Max partners is 2.
|
||||
* @param sd Caster
|
||||
* @param skill_id
|
||||
* @param skill_lv
|
||||
* @param range Area range to check
|
||||
* @param cast_flag Special handle
|
||||
*------------------------------------------*/
|
||||
int skill_check_pc_partner (struct map_session_data *sd, uint16 skill_id, uint16 *skill_lv, int range, int cast_flag)
|
||||
{
|
||||
@ -13699,9 +13752,12 @@ int skill_check_pc_partner (struct map_session_data *sd, uint16 skill_id, uint16
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
* Sub function to count how many spawned mob is around
|
||||
* return :
|
||||
* x : numbers of mob of class with special ai
|
||||
* Sub function to count how many spawned mob is around.
|
||||
* Some skills check with matched AI.
|
||||
* @param rid Source ID
|
||||
* @param mob_class Monster ID
|
||||
* @param skill_id Used skill
|
||||
* @param *c Counter for found monster
|
||||
*------------------------------------------*/
|
||||
static int skill_check_condition_mob_master_sub (struct block_list *bl, va_list ap)
|
||||
{
|
||||
@ -13728,16 +13784,19 @@ static int skill_check_condition_mob_master_sub (struct block_list *bl, va_list
|
||||
/*==========================================
|
||||
* Determines if a given skill should be made to consume ammo
|
||||
* when used by the player. [Skotlex]
|
||||
* @param sd Player
|
||||
* @param skill Skill ID
|
||||
* @return True if skill is need ammo; False otherwise.
|
||||
*------------------------------------------*/
|
||||
int skill_isammotype (struct map_session_data *sd, int skill)
|
||||
int skill_isammotype (struct map_session_data *sd, unsigned short skill_id)
|
||||
{
|
||||
return (
|
||||
battle_config.arrow_decrement==2 &&
|
||||
(sd->status.weapon == W_BOW || (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)) &&
|
||||
skill != HT_PHANTASMIC &&
|
||||
skill_get_type(skill) == BF_WEAPON &&
|
||||
!(skill_get_nk(skill)&NK_NO_DAMAGE) &&
|
||||
!skill_get_spiritball(skill,1) //Assume spirit spheres are used as ammo instead.
|
||||
skill_id != HT_PHANTASMIC &&
|
||||
skill_get_type(skill_id) == BF_WEAPON &&
|
||||
!(skill_get_nk(skill_id)&NK_NO_DAMAGE) &&
|
||||
!skill_get_spiritball(skill_id,1) //Assume spirit spheres are used as ammo instead.
|
||||
);
|
||||
}
|
||||
|
||||
@ -14062,7 +14121,8 @@ bool skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_i
|
||||
case HP_BASILICA:
|
||||
if( !sc || (sc && !sc->data[SC_BASILICA])) {
|
||||
if( sd ) {
|
||||
int s,range = skill_get_unit_range(skill_id,skill_lv)+1;
|
||||
// When castbegin, needs 7x7 clear area
|
||||
int s,range = skill_get_unit_layout_type(skill_id,skill_lv)+1;
|
||||
int size = range*2+1;
|
||||
for( s=0;s<size*size;s++ ) {
|
||||
int x = sd->bl.x+(s%size-range);
|
||||
@ -15973,7 +16033,7 @@ int skill_sit (struct map_session_data *sd, int type)
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
* Do Forstjoke/Scream effect
|
||||
*------------------------------------------*/
|
||||
int skill_frostjoke_scream (struct block_list *bl, va_list ap)
|
||||
{
|
||||
@ -15986,7 +16046,8 @@ int skill_frostjoke_scream (struct block_list *bl, va_list ap)
|
||||
|
||||
skill_id = va_arg(ap,int);
|
||||
skill_lv = va_arg(ap,int);
|
||||
if(!skill_lv) return 0;
|
||||
if(!skill_lv)
|
||||
return 0;
|
||||
tick = va_arg(ap,unsigned int);
|
||||
|
||||
if (src == bl || status_isdead(bl))
|
||||
@ -16027,7 +16088,12 @@ int skill_check_target_c_marker(struct block_list *bl, va_list ap) {
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
* Set map cell flag as skill unit effect
|
||||
* @param src Skill unit
|
||||
* @param skill_id
|
||||
* @param skill_lv
|
||||
* @param cell Cell type cell_t
|
||||
* @param flag 0/1
|
||||
*------------------------------------------*/
|
||||
static void skill_unitsetmapcell (struct skill_unit *src, uint16 skill_id, uint16 skill_lv, cell_t cell, bool flag)
|
||||
{
|
||||
@ -16040,7 +16106,9 @@ static void skill_unitsetmapcell (struct skill_unit *src, uint16 skill_id, uint1
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
* Do skill attack area (such splash effect) around the 'first' target.
|
||||
* First target will skill skill condition, always receive damage. But,
|
||||
* around it, still need target/condition validation
|
||||
*------------------------------------------*/
|
||||
int skill_attack_area (struct block_list *bl, va_list ap)
|
||||
{
|
||||
@ -16082,21 +16150,24 @@ int skill_attack_area (struct block_list *bl, va_list ap)
|
||||
return (int)skill_attack(atk_type,src,dsrc,bl,skill_id,skill_lv,tick,flag|SD_ANIMATION);
|
||||
}
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
* Clear skill unit group
|
||||
* @param bl
|
||||
* @param flag &1
|
||||
*------------------------------------------*/
|
||||
int skill_clear_group (struct block_list *bl, int flag)
|
||||
{
|
||||
struct unit_data *ud = unit_bl2ud(bl);
|
||||
struct unit_data *ud;
|
||||
struct skill_unit_group *group[MAX_SKILLUNITGROUP];
|
||||
int i, count = 0;
|
||||
|
||||
nullpo_ret(bl);
|
||||
if (!ud) return 0;
|
||||
if (!(ud = unit_bl2ud(bl)))
|
||||
return 0;
|
||||
|
||||
// All groups to be deleted are first stored on an array since the array elements shift around when you delete them. [Skotlex]
|
||||
for (i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i];i++)
|
||||
{
|
||||
for (i = 0; i < MAX_SKILLUNITGROUP && ud->skillunit[i]; i++) {
|
||||
switch (ud->skillunit[i]->skill_id) {
|
||||
case SA_DELUGE:
|
||||
case SA_VOLCANO:
|
||||
@ -16129,13 +16200,16 @@ int skill_clear_group (struct block_list *bl, int flag)
|
||||
|
||||
/*==========================================
|
||||
* Returns the first element field found [Skotlex]
|
||||
* @param bl
|
||||
* @return skill_unit_group
|
||||
*------------------------------------------*/
|
||||
struct skill_unit_group *skill_locate_element_field(struct block_list *bl)
|
||||
{
|
||||
struct unit_data *ud = unit_bl2ud(bl);
|
||||
struct unit_data *ud;
|
||||
int i;
|
||||
nullpo_ret(bl);
|
||||
if (!ud) return NULL;
|
||||
if (!(ud = unit_bl2ud(bl)))
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < MAX_SKILLUNITGROUP && ud->skillunit[i];i++) {
|
||||
switch (ud->skillunit[i]->skill_id) {
|
||||
@ -16152,7 +16226,7 @@ struct skill_unit_group *skill_locate_element_field(struct block_list *bl)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// for graffiti cleaner [Valaris]
|
||||
/// Graffiti cleaner [Valaris]
|
||||
int skill_graffitiremover (struct block_list *bl, va_list ap) {
|
||||
struct skill_unit *unit=NULL;
|
||||
|
||||
@ -16168,6 +16242,7 @@ int skill_graffitiremover (struct block_list *bl, va_list ap) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// Greed effect
|
||||
int skill_greed (struct block_list *bl, va_list ap) {
|
||||
struct block_list *src;
|
||||
struct map_session_data *sd=NULL;
|
||||
@ -16181,7 +16256,8 @@ int skill_greed (struct block_list *bl, va_list ap) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
//For Ranger's Detonator [Jobbie/3CeAM]
|
||||
|
||||
/// Ranger's Detonator [Jobbie/3CeAM]
|
||||
int skill_detonator(struct block_list *bl, va_list ap)
|
||||
{
|
||||
struct skill_unit *unit=NULL;
|
||||
@ -16230,7 +16306,9 @@ int skill_detonator(struct block_list *bl, va_list ap)
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
* Check new skill unit cell when overlapping in other skill unit cell.
|
||||
* Catched skill in cell value pushed to *unit pointer.
|
||||
* Set (*alive) to 0 will ends 'new unit' check
|
||||
*------------------------------------------*/
|
||||
static int skill_cell_overlap(struct block_list *bl, va_list ap)
|
||||
{
|
||||
@ -16351,7 +16429,8 @@ int skill_changetarget(struct block_list *bl, va_list ap)
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
* Splash effect for skill unit 'trap type'.
|
||||
* Chance triggered when damaged, timeout, or char step on it.
|
||||
*------------------------------------------*/
|
||||
static int skill_trap_splash (struct block_list *bl, va_list ap)
|
||||
{
|
||||
@ -16490,25 +16569,31 @@ int skill_maelstrom_suction(struct block_list *bl, va_list ap)
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
* Remove current enchanted element for new element
|
||||
* @param bl Char
|
||||
* @param type New element
|
||||
*------------------------------------------*/
|
||||
int skill_enchant_elemental_end (struct block_list *bl, int type)
|
||||
{
|
||||
void skill_enchant_elemental_end (struct block_list *bl, int type) {
|
||||
struct status_change *sc;
|
||||
const enum sc_type scs[] = { SC_ENCPOISON, SC_ASPERSIO, SC_FIREWEAPON, SC_WATERWEAPON, SC_WINDWEAPON, SC_EARTHWEAPON, SC_SHADOWWEAPON, SC_GHOSTWEAPON, SC_ENCHANTARMS };
|
||||
int i;
|
||||
nullpo_ret(bl);
|
||||
nullpo_ret(sc= status_get_sc(bl));
|
||||
nullpo_retv(bl);
|
||||
nullpo_retv(sc= status_get_sc(bl));
|
||||
|
||||
if (!sc->count) return 0;
|
||||
if (!sc->count)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAYLENGTH(scs); i++)
|
||||
if (type != scs[i] && sc->data[scs[i]])
|
||||
status_change_end(bl, scs[i], INVALID_TIMER);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check camouflage condition
|
||||
* @param bl
|
||||
* @param sce
|
||||
* @return True if near wall; False otherwise
|
||||
**/
|
||||
bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce)
|
||||
{
|
||||
bool wall = true;
|
||||
@ -16585,6 +16670,13 @@ bool skill_check_shadowform(struct block_list *bl, int64 damage, int hit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check camouflage condition
|
||||
* @param bl
|
||||
* @param sce
|
||||
* @return True if near wall; False otherwise
|
||||
* @TODO: Seems wrong
|
||||
**/
|
||||
bool skill_check_camouflage(struct block_list *bl, struct status_change_entry *sce)
|
||||
{
|
||||
bool wall = true;
|
||||
@ -16610,7 +16702,14 @@ bool skill_check_camouflage(struct block_list *bl, struct status_change_entry *s
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
* Initialize new skill unit for skill unit group.
|
||||
* Overall, Skill Unit makes skill unit group which each group holds their cell datas (skill unit)
|
||||
* @param group Skill unit group
|
||||
* @param idx
|
||||
* @param x
|
||||
* @param y
|
||||
* @param val1
|
||||
* @param val2
|
||||
*------------------------------------------*/
|
||||
struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int x, int y, int val1, int val2)
|
||||
{
|
||||
@ -16618,7 +16717,7 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int
|
||||
|
||||
nullpo_retr(NULL, group);
|
||||
nullpo_retr(NULL, group->unit); // crash-protection against poor coding
|
||||
nullpo_retr(NULL, unit=&group->unit[idx]);
|
||||
nullpo_retr(NULL, (unit = &group->unit[idx]));
|
||||
|
||||
if( map_getcell(map_id2bl(group->src_id)->m, x, y, CELL_CHKMAELSTROM) )
|
||||
return unit;
|
||||
@ -16636,12 +16735,13 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int
|
||||
unit->val1 = val1;
|
||||
unit->val2 = val2;
|
||||
|
||||
// Stores new skill unit
|
||||
idb_put(skillunit_db, unit->bl.id, unit);
|
||||
map_addiddb(&unit->bl);
|
||||
if(map_addblock(&unit->bl))
|
||||
return NULL;
|
||||
|
||||
// perform oninit actions
|
||||
// Perform oninit actions
|
||||
switch (group->skill_id) {
|
||||
case WZ_ICEWALL:
|
||||
map_setgatcell(unit->bl.m,unit->bl.x,unit->bl.y,5);
|
||||
@ -16665,12 +16765,12 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int
|
||||
}
|
||||
|
||||
clif_getareachar_skillunit(&unit->bl, unit, AREA);
|
||||
|
||||
return unit;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
* Remove unit
|
||||
* @param unit
|
||||
*------------------------------------------*/
|
||||
int skill_delunit (struct skill_unit* unit) {
|
||||
struct skill_unit_group *group;
|
||||
@ -16709,8 +16809,6 @@ int skill_delunit (struct skill_unit* unit) {
|
||||
break;
|
||||
case HP_BASILICA:
|
||||
skill_unitsetmapcell(unit,HP_BASILICA,group->skill_lv,CELL_BASILICA,false);
|
||||
// Because of Basilica's range we need to specifically update the players inside when it's cancelled prematurely
|
||||
map_foreachincell(skill_unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,0,4);
|
||||
break;
|
||||
case RA_ELECTRICSHOCKER: {
|
||||
struct block_list* target = map_id2bl(group->val2);
|
||||
@ -16742,22 +16840,20 @@ int skill_delunit (struct skill_unit* unit) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*==========================================
|
||||
*
|
||||
*------------------------------------------*/
|
||||
static DBMap* group_db = NULL;// int group_id -> struct skill_unit_group*
|
||||
|
||||
static DBMap* skillunit_group_db = NULL; /// Skill unit group DB. Key int group_id -> struct skill_unit_group*
|
||||
|
||||
/// Returns the target skill_unit_group or NULL if not found.
|
||||
struct skill_unit_group* skill_id2group(int group_id)
|
||||
{
|
||||
return (struct skill_unit_group*)idb_get(group_db, group_id);
|
||||
struct skill_unit_group* skill_id2group(int group_id) {
|
||||
return (struct skill_unit_group*)idb_get(skillunit_group_db, group_id);
|
||||
}
|
||||
|
||||
static int skill_unit_group_newid = MAX_SKILL_DB; /// Skill Unit Group ID
|
||||
|
||||
static int skill_unit_group_newid = MAX_SKILL_DB;
|
||||
|
||||
/// Returns a new group_id that isn't being used in group_db.
|
||||
/// Fatal error if nothing is available.
|
||||
/**
|
||||
* Returns a new group_id that isn't being used in skillunit_group_db.
|
||||
* Fatal error if nothing is available.
|
||||
**/
|
||||
static int skill_get_new_group_id(void)
|
||||
{
|
||||
if( skill_unit_group_newid >= MAX_SKILL_DB && skill_id2group(skill_unit_group_newid) == NULL )
|
||||
@ -16777,6 +16873,17 @@ static int skill_get_new_group_id(void)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize skill unit group called while setting new unit (skill unit/ground skill) in skill_unitsetting()
|
||||
* @param src Object that cast the skill
|
||||
* @param count How many 'cells' used that needed. Related with skill layout
|
||||
* @param skill_id ID of used skill
|
||||
* @param skill_lv Skill level of used skill
|
||||
* @param unit_id Unit ID (look at skill_unit_db.txt)
|
||||
* @param limit Lifetime for skill unit, uses skill_get_time(skill_id, skill_lv)
|
||||
* @param interval Time interval
|
||||
* @return skill_unit_group
|
||||
**/
|
||||
struct skill_unit_group* skill_initunitgroup (struct block_list* src, int count, uint16 skill_id, uint16 skill_lv, int unit_id, int limit, int interval)
|
||||
{
|
||||
struct unit_data* ud = unit_bl2ud( src );
|
||||
@ -16788,10 +16895,11 @@ struct skill_unit_group* skill_initunitgroup (struct block_list* src, int count,
|
||||
nullpo_retr(NULL, src);
|
||||
nullpo_retr(NULL, ud);
|
||||
|
||||
// find a free spot to store the new unit group
|
||||
// Find a free spot to store the new unit group
|
||||
// TODO: Make this flexible maybe by changing this fixed array?
|
||||
ARR_FIND( 0, MAX_SKILLUNITGROUP, i, ud->skillunit[i] == NULL );
|
||||
if(i == MAX_SKILLUNITGROUP) {
|
||||
// array is full, make room by discarding oldest group
|
||||
// Array is full, make room by discarding oldest group
|
||||
int j = 0;
|
||||
unsigned maxdiff = 0, tick = gettick();
|
||||
for(i = 0; i < MAX_SKILLUNITGROUP && ud->skillunit[i];i++){
|
||||
@ -16832,12 +16940,17 @@ struct skill_unit_group* skill_initunitgroup (struct block_list* src, int count,
|
||||
if (skill_id == PR_SANCTUARY) //Sanctuary starts healing +1500ms after casted. [Skotlex]
|
||||
group->tick += 1500;
|
||||
|
||||
idb_put(group_db, group->group_id, group);
|
||||
// Stores this new group to DBMap
|
||||
idb_put(skillunit_group_db, group->group_id, group);
|
||||
return group;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
* Remove skill unit group
|
||||
* @param group
|
||||
* @param file
|
||||
* @param line
|
||||
* @param *func
|
||||
*------------------------------------------*/
|
||||
int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int line, const char* func)
|
||||
{
|
||||
@ -16895,6 +17008,14 @@ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int li
|
||||
}
|
||||
}
|
||||
|
||||
if (group->unit_id == UNT_BASILICA) {
|
||||
struct status_change *sc = status_get_sc(src);
|
||||
if(sc && sc->data[SC_BASILICA]) {
|
||||
sc->data[SC_BASILICA]->val3 = 0;
|
||||
status_change_end(src, SC_BASILICA, INVALID_TIMER);
|
||||
}
|
||||
}
|
||||
|
||||
switch( group->skill_id ) {
|
||||
case SG_SUN_WARM:
|
||||
case SG_MOON_WARM:
|
||||
@ -16952,7 +17073,7 @@ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int li
|
||||
group->valstr = NULL;
|
||||
}
|
||||
|
||||
idb_remove(group_db, group->group_id);
|
||||
idb_remove(skillunit_group_db, group->group_id);
|
||||
map_freeblock(&group->unit->bl); // schedules deallocation of whole array (HACK)
|
||||
group->unit = NULL;
|
||||
group->group_id = 0;
|
||||
@ -16973,22 +17094,25 @@ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int li
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
* Clear all Skill Unit Group from an Object, example usage when player logged off or dead
|
||||
* @param src
|
||||
*------------------------------------------*/
|
||||
int skill_clear_unitgroup (struct block_list *src)
|
||||
{
|
||||
struct unit_data *ud = unit_bl2ud(src);
|
||||
void skill_clear_unitgroup (struct block_list *src) {
|
||||
struct unit_data *ud;
|
||||
|
||||
nullpo_ret(ud);
|
||||
nullpo_retv(src);
|
||||
nullpo_retv((ud = unit_bl2ud(src)));
|
||||
|
||||
while (ud->skillunit[0])
|
||||
skill_delunitgroup(ud->skillunit[0]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
* Search tickset for skill unit in skill unit group
|
||||
* @param bl Block List for skill_unit
|
||||
* @param group Skill unit group
|
||||
* @param tick
|
||||
* @return skill_unit_group_tickset if found
|
||||
*------------------------------------------*/
|
||||
struct skill_unit_group_tickset *skill_unitgrouptickset_search (struct block_list *bl, struct skill_unit_group *group, int tick) {
|
||||
int i, j = -1, s, id;
|
||||
@ -17000,7 +17124,8 @@ struct skill_unit_group_tickset *skill_unitgrouptickset_search (struct block_lis
|
||||
return NULL;
|
||||
|
||||
ud = unit_bl2ud(bl);
|
||||
if (!ud) return NULL;
|
||||
if (!ud)
|
||||
return NULL;
|
||||
|
||||
set = ud->skillunittick;
|
||||
|
||||
@ -17028,7 +17153,8 @@ struct skill_unit_group_tickset *skill_unitgrouptickset_search (struct block_lis
|
||||
}
|
||||
|
||||
/*==========================================
|
||||
*
|
||||
* Check for validity skill unit that triggered by skill_unit_timer_sub
|
||||
* And trigger skill_unit_onplace_timer for object that maybe stands there (catched object is *bl)
|
||||
*------------------------------------------*/
|
||||
int skill_unit_timer_sub_onplace (struct block_list* bl, va_list ap) {
|
||||
struct skill_unit* unit = va_arg(ap,struct skill_unit *);
|
||||
@ -17047,12 +17173,12 @@ int skill_unit_timer_sub_onplace (struct block_list* bl, va_list ap) {
|
||||
return 0;
|
||||
|
||||
skill_unit_onplace_timer(unit,bl,tick);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DBApply
|
||||
* Sub function of skill_unit_timer for executing each skill unit from skillunit_db
|
||||
*/
|
||||
static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap)
|
||||
{
|
||||
@ -17067,7 +17193,7 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap)
|
||||
|
||||
nullpo_ret(group);
|
||||
|
||||
// check for expiration
|
||||
// Check for expiration
|
||||
if( !group->state.guildaura && (DIFF_TICK(tick,group->tick) >= group->limit || DIFF_TICK(tick,group->tick) >= unit->limit) )
|
||||
{// skill unit expired (inlined from skill_unit_onlimit())
|
||||
switch( group->unit_id )
|
||||
@ -17271,7 +17397,8 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap)
|
||||
}
|
||||
}
|
||||
|
||||
if( dissonance ) skill_dance_switch(unit, 1);
|
||||
if( dissonance )
|
||||
skill_dance_switch(unit, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -17284,7 +17411,6 @@ int skill_unit_timer(int tid, unsigned int tick, int id, intptr_t data) {
|
||||
skillunit_db->foreach(skillunit_db, skill_unit_timer_sub, tick);
|
||||
|
||||
map_freeblock_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -17933,7 +18059,6 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, unsigned sh
|
||||
|
||||
if(make_per < 1) make_per = 1;
|
||||
|
||||
|
||||
if(rnd()%10000 < make_per || qty > 1){ //Success, or crafting multiple items.
|
||||
struct item tmp_item;
|
||||
memset(&tmp_item,0,sizeof(tmp_item));
|
||||
@ -19963,7 +20088,7 @@ void do_init_skill (void){
|
||||
skilldb_name2id = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, 0);
|
||||
skill_readdb();
|
||||
|
||||
group_db = idb_alloc(DB_OPT_BASE);
|
||||
skillunit_group_db = idb_alloc(DB_OPT_BASE);
|
||||
skillunit_db = idb_alloc(DB_OPT_BASE);
|
||||
skillusave_db = idb_alloc(DB_OPT_RELEASE_DATA);
|
||||
bowling_db = idb_alloc(DB_OPT_BASE);
|
||||
@ -19982,7 +20107,7 @@ void do_init_skill (void){
|
||||
void do_final_skill(void){
|
||||
skill_destroy_requirement();
|
||||
db_destroy(skilldb_name2id);
|
||||
db_destroy(group_db);
|
||||
db_destroy(skillunit_group_db);
|
||||
db_destroy(skillunit_db);
|
||||
db_destroy(skillusave_db);
|
||||
db_destroy(bowling_db);
|
||||
|
@ -211,35 +211,40 @@ struct skill_timerskill {
|
||||
int flag;
|
||||
};
|
||||
|
||||
#define MAX_SKILLUNITGROUP 25
|
||||
#define MAX_SKILLUNITGROUP 25 /// Maximum skill unit group (for same skill each source)
|
||||
/// Skill unit group
|
||||
struct skill_unit_group {
|
||||
int src_id;
|
||||
int party_id;
|
||||
int guild_id;
|
||||
int bg_id;
|
||||
int map;
|
||||
int target_flag; //Holds BCT_* flag for battle_check_target
|
||||
int bl_flag; //Holds BL_* flag for map_foreachin* functions
|
||||
unsigned int tick;
|
||||
int limit,interval;
|
||||
uint16 skill_id,skill_lv;
|
||||
int val1,val2,val3;
|
||||
char *valstr;
|
||||
int unit_id;
|
||||
int group_id;
|
||||
int unit_count,alive_count;
|
||||
int item_id; //store item used.
|
||||
struct skill_unit *unit;
|
||||
int src_id; /// Caster ID/RID, if player is account_id
|
||||
int party_id; /// Party ID
|
||||
int guild_id; /// Guild ID
|
||||
int bg_id; /// Battleground ID
|
||||
int map; /// Map
|
||||
int target_flag; /// Holds BCT_* flag for battle_check_target
|
||||
int bl_flag; /// Holds BL_* flag for map_foreachin* functions
|
||||
unsigned int tick; /// Tick when skill unit initialized
|
||||
int limit, /// Life time
|
||||
interval; /// Timer interval
|
||||
uint16 skill_id, /// Skill ID
|
||||
skill_lv; /// Skill level
|
||||
int val1, val2, val3; /// Values
|
||||
char *valstr; /// String value, used for HT_TALKIEBOX & RG_GRAFFITI
|
||||
int unit_id; /// Unit ID (for client effect)
|
||||
int group_id; /// Skill Group ID
|
||||
int unit_count, /// Number of unit at this group
|
||||
alive_count; /// Number of alive unit
|
||||
int item_id; /// Store item used.
|
||||
struct skill_unit *unit; /// Skill Unit
|
||||
struct {
|
||||
unsigned ammo_consume : 1;
|
||||
unsigned ammo_consume : 1; // Need to consume ammo
|
||||
unsigned song_dance : 2; //0x1 Song/Dance, 0x2 Ensemble
|
||||
unsigned guildaura : 1;
|
||||
unsigned guildaura : 1; // Guild Aura
|
||||
} state;
|
||||
};
|
||||
|
||||
/// Skill unit
|
||||
struct skill_unit {
|
||||
struct block_list bl;
|
||||
struct skill_unit_group *group;
|
||||
struct skill_unit_group *group; /// Skill group reference
|
||||
int limit;
|
||||
int val1, val2;
|
||||
short alive, range;
|
||||
@ -358,7 +363,7 @@ int skill_get_itemqty( uint16 skill_id, int idx );
|
||||
|
||||
int skill_name2id(const char* name);
|
||||
|
||||
int skill_isammotype(struct map_session_data *sd, int skill);
|
||||
int skill_isammotype(struct map_session_data *sd, unsigned short skill_id);
|
||||
int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data);
|
||||
int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data);
|
||||
int skill_castend_map( struct map_session_data *sd,uint16 skill_id, const char *map);
|
||||
@ -380,10 +385,10 @@ int skill_delunit(struct skill_unit *unit);
|
||||
struct skill_unit_group *skill_initunitgroup(struct block_list* src, int count, uint16 skill_id, uint16 skill_lv, int unit_id, int limit, int interval);
|
||||
int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int line, const char* func);
|
||||
#define skill_delunitgroup(group) skill_delunitgroup_(group,__FILE__,__LINE__,__func__)
|
||||
int skill_clear_unitgroup(struct block_list *src);
|
||||
void skill_clear_unitgroup(struct block_list *src);
|
||||
int skill_clear_group(struct block_list *bl, int flag);
|
||||
void ext_skill_unit_onplace(struct skill_unit *unit, struct block_list *bl, unsigned int tick);
|
||||
int64 skill_unit_ondamaged(struct skill_unit *unit,struct block_list *bl,int64 damage,unsigned int tick);
|
||||
int64 skill_unit_ondamaged(struct skill_unit *unit,struct block_list *bl,int64 damage);
|
||||
|
||||
int skill_castfix( struct block_list *bl, uint16 skill_id, uint16 skill_lv);
|
||||
int skill_castfix_sc( struct block_list *bl, int time);
|
||||
@ -425,7 +430,7 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk
|
||||
bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce);
|
||||
|
||||
// Abnormal status
|
||||
int skill_enchant_elemental_end(struct block_list *bl, int type);
|
||||
void skill_enchant_elemental_end(struct block_list *bl, int type);
|
||||
bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd);
|
||||
bool skill_isNotOk_hom(uint16 skill_id, struct homun_data *hd);
|
||||
bool skill_isNotOk_mercenary(uint16 skill_id, struct mercenary_data *md);
|
||||
|
@ -1196,7 +1196,6 @@ void initChangeTables(void)
|
||||
/* StatusChangeState (SCS_) NOCAST (skills) */
|
||||
StatusChangeStateTable[SC_SILENCE] |= SCS_NOCAST;
|
||||
StatusChangeStateTable[SC_STEELBODY] |= SCS_NOCAST;
|
||||
StatusChangeStateTable[SC_BASILICA] |= SCS_NOCAST;
|
||||
StatusChangeStateTable[SC_BERSERK] |= SCS_NOCAST;
|
||||
StatusChangeStateTable[SC__BLOODYLUST] |= SCS_NOCAST;
|
||||
StatusChangeStateTable[SC_DEATHBOUND] |= SCS_NOCAST;
|
||||
@ -1353,7 +1352,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
|
||||
}
|
||||
|
||||
if (target->type == BL_SKILL)
|
||||
return (int)skill_unit_ondamaged((struct skill_unit *)target, src, hp, gettick());
|
||||
return (int)skill_unit_ondamaged((struct skill_unit *)target, src, hp);
|
||||
|
||||
status = status_get_status_data(target);
|
||||
if(!status || status == &dummy_status )
|
||||
@ -1866,6 +1865,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
|
||||
) { // Skills blocked through status changes...
|
||||
if (!flag && ( // Blocked only from using the skill (stuff like autospell may still go through
|
||||
sc->cant.cast ||
|
||||
(sc->data[SC_BASILICA] && (sc->data[SC_BASILICA]->val4 != src->id || skill_id != HP_BASILICA)) || // Only Basilica caster that can cast, and only Basilica to cancel it
|
||||
(sc->data[SC_MARIONETTE] && skill_id != CG_MARIONETTE) || // Only skill you can use is marionette again to cancel it
|
||||
(sc->data[SC_MARIONETTE2] && skill_id == CG_MARIONETTE) || // Cannot use marionette if you are being buffed by another
|
||||
(sc->data[SC_STASIS] && skill_block_check(src, SC_STASIS, skill_id)) ||
|
||||
@ -10729,6 +10729,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
|
||||
if (sce->val3) { // Clear the group.
|
||||
struct skill_unit_group* group = skill_id2group(sce->val3);
|
||||
sce->val3 = 0;
|
||||
if (group)
|
||||
skill_delunitgroup(group);
|
||||
}
|
||||
break;
|
||||
@ -10737,7 +10738,12 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
|
||||
skill_clear_unitgroup(bl);
|
||||
break;
|
||||
case SC_BASILICA: // Clear the skill area. [Skotlex]
|
||||
skill_clear_unitgroup(bl);
|
||||
if (sce->val3 && sce->val4 == bl->id) {
|
||||
struct skill_unit_group* group = skill_id2group(sce->val3);
|
||||
sce->val3 = 0;
|
||||
if (group)
|
||||
skill_delunitgroup(group);
|
||||
}
|
||||
break;
|
||||
case SC_TRICKDEAD:
|
||||
if (vd) vd->dead_sit = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user