diff --git a/db/pre-re/skill_db.txt b/db/pre-re/skill_db.txt index 1d4b727849..ed45fff34c 100644 --- a/db/pre-re/skill_db.txt +++ b/db/pre-re/skill_db.txt @@ -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 //**** diff --git a/db/pre-re/skill_unit_db.txt b/db/pre-re/skill_unit_db.txt index 74e1a6df76..b003cb9666 100644 --- a/db/pre-re/skill_unit_db.txt +++ b/db/pre-re/skill_unit_db.txt @@ -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 diff --git a/db/re/skill_db.txt b/db/re/skill_db.txt index 004a17c3de..92bbe51eb1 100644 --- a/db/re/skill_db.txt +++ b/db/re/skill_db.txt @@ -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 //**** diff --git a/db/re/skill_unit_db.txt b/db/re/skill_unit_db.txt index a7a50287ad..45a4c91fa4 100644 --- a/db/re/skill_unit_db.txt +++ b/db/re/skill_unit_db.txt @@ -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 diff --git a/src/map/pc.c b/src/map/pc.c index 2a55cac822..189b489f06 100755 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -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... diff --git a/src/map/skill.c b/src/map/skill.c index 40d6e8b2d3..e7dabfae09 100755 --- a/src/map/skill.c +++ b/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,20 +11804,26 @@ 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) { struct skill_unit_group *group; - int i,limit,val1=0,val2=0,val3=0; - int target,interval,range,unit_flag,req_item=0; + int i, limit, val1 = 0, val2 = 0, val3 = 0; + int target, interval, range, unit_flag, req_item = 0; struct s_skill_unit_layout *layout; struct map_session_data *sd; struct status_data *status; struct status_change *sc; - int active_flag=1; - int subunt=0; + int active_flag = 1; + int subunt = 0; nullpo_retr(NULL, src); @@ -11848,7 +11853,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill case MG_FIREWALL: if(sc && sc->data[SC_VIOLENTGALE]) limit = limit*3/2; - val2=4+skill_lv; + val2 = 4+skill_lv; break; case AL_WARP: @@ -12133,21 +12138,23 @@ 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)); - group->val1=val1; - group->val2=val2; - group->val3=val3; - group->target_flag=target; - group->bl_flag= skill_get_unit_bl_target(skill_id); + // 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; + group->target_flag = target; + group->bl_flag = skill_get_unit_bl_target(skill_id); group->state.ammo_consume = (sd && sd->state.arrow_atk && skill_id != GS_GROUNDDRIFT); //Store if this skill needs to consume ammo. 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; - if(skill_id==HT_TALKIEBOX || skill_id==RG_GRAFFITI){ + // 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) safestrncpy(group->valstr, sd->message, MESSAGE_SIZE); @@ -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){ + 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,65 +12195,64 @@ 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 ) - { - case MG_FIREWALL: - case NJ_KAENSIN: - val2_2=group->val2; - break; - case WZ_ICEWALL: - val1_2 = (skill_lv <= 1) ? 500 : 200 + 200*skill_lv; - val2_2 = map_getcell(src->m, ux, uy, CELL_GETTYPE); - break; - case HT_LANDMINE: - case MA_LANDMINE: - case HT_ANKLESNARE: - case HT_SHOCKWAVE: - case HT_SANDMAN: - case MA_SANDMAN: - case HT_FLASHER: - case HT_FREEZINGTRAP: - case MA_FREEZINGTRAP: - case HT_TALKIEBOX: - case HT_SKIDTRAP: - case MA_SKIDTRAP: - case HT_CLAYMORETRAP: - case HT_BLASTMINE: - case RA_ELECTRICSHOCKER: - case RA_CLUSTERBOMB: - case RA_MAGENTATRAP: - case RA_COBALTTRAP: - case RA_MAIZETRAP: - case RA_VERDURETRAP: - case RA_FIRINGTRAP: - case RA_ICEBOUNDTRAP: - case RL_B_TRAP: - val1_2 = 3500; - break; - case GS_DESPERADO: - val1_2 = abs(layout->dx[i]); - val2_2 = abs(layout->dy[i]); - if (val1_2 < 2 || val2_2 < 2) { //Nearby cross, linear decrease with no diagonals - if (val2_2 > val1_2) val1_2 = val2_2; - if (val1_2) val1_2--; - val1_2 = 36 -12*val1_2; - } else //Diagonal edges - val1_2 = 28 -4*val1_2 -4*val2_2; - if (val1_2 < 1) val1_2 = 1; - val2_2 = 0; - break; - case WM_REVERBERATION: - case WM_POEMOFNETHERWORLD: - val1_2 = 1 + skill_lv; - break; - case GN_WALLOFTHORN: - val1_2 = 2000 + 2000 * skill_lv; - val2_2 = 20; - break; - default: - if (group->state.song_dance&0x1) - val2_2 = unit_flag&(UF_DANCE|UF_SONG); //Store whether this is a song/dance - break; + switch( skill_id ) { + case MG_FIREWALL: + case NJ_KAENSIN: + val2_2 = group->val2; + break; + case WZ_ICEWALL: + val1_2 = (skill_lv <= 1) ? 500 : 200 + 200*skill_lv; + val2_2 = map_getcell(src->m, ux, uy, CELL_GETTYPE); + break; + case HT_LANDMINE: + case MA_LANDMINE: + case HT_ANKLESNARE: + case HT_SHOCKWAVE: + case HT_SANDMAN: + case MA_SANDMAN: + case HT_FLASHER: + case HT_FREEZINGTRAP: + case MA_FREEZINGTRAP: + case HT_TALKIEBOX: + case HT_SKIDTRAP: + case MA_SKIDTRAP: + case HT_CLAYMORETRAP: + case HT_BLASTMINE: + case RA_ELECTRICSHOCKER: + case RA_CLUSTERBOMB: + case RA_MAGENTATRAP: + case RA_COBALTTRAP: + case RA_MAIZETRAP: + case RA_VERDURETRAP: + case RA_FIRINGTRAP: + case RA_ICEBOUNDTRAP: + case RL_B_TRAP: + val1_2 = 3500; + break; + case GS_DESPERADO: + val1_2 = abs(layout->dx[i]); + val2_2 = abs(layout->dy[i]); + if (val1_2 < 2 || val2_2 < 2) { //Nearby cross, linear decrease with no diagonals + if (val2_2 > val1_2) val1_2 = val2_2; + if (val1_2) val1_2--; + val1_2 = 36 -12*val1_2; + } else //Diagonal edges + val1_2 = 28 -4*val1_2 -4*val2_2; + if (val1_2 < 1) val1_2 = 1; + val2_2 = 0; + break; + case WM_REVERBERATION: + case WM_POEMOFNETHERWORLD: + val1_2 = 1 + skill_lv; + break; + case GN_WALLOFTHORN: + val1_2 = 2000 + 2000 * skill_lv; + val2_2 = 20; + break; + default: + if (group->state.song_dance&0x1) + val2_2 = unit_flag&(UF_DANCE|UF_SONG); //Store whether this is a song/dance + break; } if (unit_flag&UF_RANGEDSINGLEUNIT && i == (layout->count / 2)) val2_2 |= UF_RANGEDSINGLEUNIT; // center. @@ -12254,14 +12260,15 @@ 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)); - unit->limit=limit; - unit->range=range; + nullpo_retr(NULL, (unit = skill_initunit(group,i,ux,uy,val1_2,val2_2))); + unit->limit = limit; + unit->range = range; if (skill_id == PF_FOGWALL && alive == 2) { //Double duration of cells on top of Deluge/Suiton @@ -12269,8 +12276,8 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill group->limit = unit->limit; } - // execute on all targets standing on this cell - if (range==0 && active_flag) + // 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;sbl.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) { @@ -15982,12 +16042,13 @@ int skill_frostjoke_scream (struct block_list *bl, va_list ap) unsigned int tick; nullpo_ret(bl); - nullpo_ret(src=va_arg(ap,struct block_list*)); + nullpo_ret(src = va_arg(ap,struct block_list*)); - skill_id=va_arg(ap,int); - skill_lv=va_arg(ap,int); - if(!skill_lv) return 0; - tick=va_arg(ap,unsigned int); + skill_id = va_arg(ap,int); + skill_lv = va_arg(ap,int); + if(!skill_lv) + return 0; + tick = va_arg(ap,unsigned int); if (src == bl || status_isdead(bl)) return 0; @@ -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) { @@ -16052,13 +16120,13 @@ int skill_attack_area (struct block_list *bl, va_list ap) return 0; atk_type = va_arg(ap,int); - src=va_arg(ap,struct block_list*); - dsrc=va_arg(ap,struct block_list*); - skill_id=va_arg(ap,int); - skill_lv=va_arg(ap,int); - tick=va_arg(ap,unsigned int); - flag=va_arg(ap,int); - type=va_arg(ap,int); + src = va_arg(ap,struct block_list*); + dsrc = va_arg(ap,struct block_list*); + skill_id = va_arg(ap,int); + skill_lv = va_arg(ap,int); + tick = va_arg(ap,unsigned int); + flag = va_arg(ap,int); + type = va_arg(ap,int); if (skill_area_temp[1] == bl->id) //This is the target of the skill, do a full attack and skip target checks. @@ -16070,33 +16138,36 @@ int skill_attack_area (struct block_list *bl, va_list ap) switch (skill_id) { - case WZ_FROSTNOVA: //Skills that don't require the animation to be removed - case NPC_ACIDBREATH: - case NPC_DARKNESSBREATH: - case NPC_FIREBREATH: - case NPC_ICEBREATH: - case NPC_THUNDERBREATH: - return (int)skill_attack(atk_type,src,dsrc,bl,skill_id,skill_lv,tick,flag); - default: - //Area-splash, disable skill animation. - return (int)skill_attack(atk_type,src,dsrc,bl,skill_id,skill_lv,tick,flag|SD_ANIMATION); + case WZ_FROSTNOVA: //Skills that don't require the animation to be removed + case NPC_ACIDBREATH: + case NPC_DARKNESSBREATH: + case NPC_FIREBREATH: + case NPC_ICEBREATH: + case NPC_THUNDERBREATH: + return (int)skill_attack(atk_type,src,dsrc,bl,skill_id,skill_lv,tick,flag); + default: + //Area-splash, disable skill animation. + 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; + 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;iskillunit[i];i++) - { + // 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++) { switch (ud->skillunit[i]->skill_id) { case SA_DELUGE: case SA_VOLCANO: @@ -16122,22 +16193,25 @@ int skill_clear_group (struct block_list *bl, int flag) } } - for (i=0;iskillunit[i];i++) { + for (i = 0; i < MAX_SKILLUNITGROUP && ud->skillunit[i];i++) { switch (ud->skillunit[i]->skill_id) { case SA_DELUGE: case SA_VOLCANO: @@ -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; @@ -16626,22 +16725,23 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int if(!unit->alive) group->alive_count++; - unit->bl.id=map_get_new_object_id(); - unit->bl.type=BL_SKILL; - unit->bl.m=group->map; - unit->bl.x=x; - unit->bl.y=y; - unit->group=group; - unit->alive=1; - unit->val1=val1; - unit->val2=val2; + unit->bl.id = map_get_new_object_id(); + unit->bl.type = BL_SKILL; + unit->bl.m = group->map; + unit->bl.x = x; + unit->bl.y = y; + unit->group = group; + unit->alive = 1; + 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,21 +16895,22 @@ 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 - int j=0; - unsigned maxdiff=0,tick=gettick(); - for(i=0;iskillunit[i];i++){ - unsigned int x=DIFF_TICK(tick,ud->skillunit[i]->tick); - if(x>maxdiff){ - maxdiff=x; - j=i; + // 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++){ + unsigned int x = DIFF_TICK(tick,ud->skillunit[i]->tick); + if(x > maxdiff){ + maxdiff = x; + j = i; } } skill_delunitgroup(ud->skillunit[j]); - //Since elements must have shifted, we use the last slot. + // Since elements must have shifted, we use the last slot. i = MAX_SKILLUNITGROUP-1; } @@ -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,11 +17073,11 @@ 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; - group->unit_count=0; + group->unit = NULL; + group->group_id = 0; + group->unit_count = 0; // locate this group, swap with the last entry and delete it ARR_FIND( 0, MAX_SKILLUNITGROUP, i, ud->skillunit[i] == group ); @@ -16973,34 +17094,38 @@ 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; + int i, j = -1, s, id; struct unit_data *ud; struct skill_unit_group_tickset *set; nullpo_ret(bl); - if (group->interval==-1) + if (group->interval == -1) 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); diff --git a/src/map/skill.h b/src/map/skill.h index fc83757b0e..6408f7a898 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -211,38 +211,43 @@ 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; + int val1, val2; + short alive, range; }; #define MAX_SKILLUNITGROUPTICKSET 25 @@ -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); diff --git a/src/map/status.c b/src/map/status.c index 4e0ab9dcfc..4d8fb1235d 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -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,7 +10729,8 @@ 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; - skill_delunitgroup(group); + if (group) + skill_delunitgroup(group); } break; case SC_HERMODE: @@ -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;