From 7d4cef5d03815911547efb37dce1c5ee9d5b05fa Mon Sep 17 00:00:00 2001 From: zephyrus Date: Thu, 21 Aug 2008 20:38:32 +0000 Subject: - Big update to Basilica, implementing official behavior. * Basilica caster cannot walk. * On Basilica area, only caster can use Basilica again to stop it. * On Basilica no one can use skills. (Previous bug on eA because you can use support skills on it, also caster). * Only Pressure can bypass Basilica protection. * Any enemy of the caster bounce 2 cells back from basilica, except Boss type. (Bugreport 2099). * Any monster can target you on basilica and try to attack you, also with skills, but damage is reduced to 0, except Boss. Notes: - Basilica Cell stuff is not used anymore... is it required? - Still need to add a check previous to cast basilica because if there are mobs, items, npcs, walls, skills around the caster (7x7 i think) the skill should fail. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@13106 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/battle.c | 12 +++++------- src/map/clif.c | 22 +++++++++++++++------ src/map/skill.c | 60 ++++++++++++++++++++++++++++++++++++++++---------------- src/map/status.c | 12 ------------ src/map/unit.c | 20 +++++++++---------- 5 files changed, 74 insertions(+), 52 deletions(-) (limited to 'src/map') diff --git a/src/map/battle.c b/src/map/battle.c index bc99e3793..23a548ec6 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -300,8 +300,12 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i sc = status_get_sc(bl); - if (sc && sc->count) { + if( sc && sc->count ) + { //First, sc_*'s that reduce damage to 0. + if( sc->data[SC_BASILICA] && !(status_get_mode(src)&MD_BOSS) && skill_num != PA_PRESSURE ) + return 0; // Basilica reduces damage to 0 except Pressure + if( sc->data[SC_SAFETYWALL] && (flag&(BF_SHORT|BF_MAGIC))==BF_SHORT ) { struct skill_unit_group *group = (struct skill_unit_group *)sc->data[SC_SAFETYWALL]->val3; @@ -3052,12 +3056,6 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f nullpo_retr(0, target); m = target->m; - if (flag&BCT_ENEMY && !map_flag_gvg(m) && !(status_get_mode(src)&MD_BOSS)) - { //No offensive stuff while in Basilica. - if (map_getcell(m,src->x,src->y,CELL_CHKBASILICA) || - map_getcell(m,target->x,target->y,CELL_CHKBASILICA)) - return -1; - } //t_bl/s_bl hold the 'master' of the attack, while src/target are the actual //objects involved. diff --git a/src/map/clif.c b/src/map/clif.c index a84622d54..f4ed8d1df 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -8369,10 +8369,13 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, case 0x00: // once attack case 0x07: // continuous attack - if (pc_cant_act(sd) || sd->sc.option&OPTION_HIDE) + if( pc_cant_act(sd) || sd->sc.option&OPTION_HIDE ) return; - if(sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER)) + if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER) ) + return; + + if( sd->sc.data[SC_BASILICA] ) return; if (!battle_config.sdelay_attack_enable && pc_checkskill(sd, SA_FREECAST) <= 0) { @@ -9226,8 +9229,11 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) return; } - if(sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER)) + if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER) ) return; + + if( sd->sc.data[SC_BASILICA] && (skillnum != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) ) + return; // On basilica only caster can use Basilica again to stop it. if(target_id<0 && -target_id == sd->bl.id) // for disguises [Valaris] target_id = sd->bl.id; @@ -9324,15 +9330,19 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, short skil if (sd->ud.skilltimer != -1) return; + if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) { clif_skill_fail(sd, skillnum, 4, 0); return; } - if(sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER)) + if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER) ) return; - + + if( sd->sc.data[SC_BASILICA] && (skillnum != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) ) + return; // On basilica only caster can use Basilica again to stop it. + if(sd->menuskill_id) { if (sd->menuskill_id == SA_TAMINGMONSTER) @@ -9402,7 +9412,7 @@ void clif_parse_UseSkillMap(int fd, struct map_session_data* sd) if(skill_num != sd->menuskill_id) return; - if (pc_cant_act(sd)) + if( pc_cant_act(sd) ) { sd->menuskill_id = sd->menuskill_val = 0; return; diff --git a/src/map/skill.c b/src/map/skill.c index 44e720834..064ceb849 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -1284,8 +1284,13 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in } break; case BL_PC: - if(src != target && ((TBL_PC*)target)->special_state.no_knockback) + { + struct map_session_data *sd = BL_CAST(BL_PC, target); + if( sd->sc.data[SC_BASILICA] && sd->sc.data[SC_BASILICA]->val4 == sd->bl.id ) + return 0; // Basilica caster can't be knocked-back + if( src != target && sd->special_state.no_knockback ) return 0; + } break; case BL_SKILL: su = (struct skill_unit *)target; @@ -5753,10 +5758,15 @@ int skill_castend_pos2(struct block_list* src, int x, int y, int skillid, int sk flag|=1; break; case HP_BASILICA: - skill_clear_unitgroup(src); - if (skill_unitsetting(src,skillid,skilllv,x,y,0)) - sc_start(src,type,100,skilllv,skill_get_time(skillid,skilllv)); - flag|=1; + if( sc->data[SC_BASILICA] ) + status_change_end(src, SC_BASILICA, -1); // Cancel Basilica + else + { // Create Basilica. Start SC on caster. Unit timer start SC on others. + skill_clear_unitgroup(src); + if( skill_unitsetting(src,skillid,skilllv,x,y,0) ) + sc_start4(src,type,100,skilllv,0,0,src->id,skill_get_time(skillid,skilllv)); + flag|=1; + } break; case CG_HERMODE: skill_clear_unitgroup(src); @@ -6028,6 +6038,7 @@ int skill_castend_map (struct map_session_data *sd, short skill_num, const char sd->sc.data[SC_STEELBODY] || sd->sc.data[SC_DANCING] || sd->sc.data[SC_BERSERK] || + sd->sc.data[SC_BASILICA] || sd->sc.data[SC_MARIONETTE] )) { skill_failed(sd); @@ -6110,13 +6121,6 @@ int skill_castend_map (struct map_session_data *sd, short skill_num, const char return 0; } - // This makes Warp Portal fail if the cell is not empty - //if(skill_check_unit_range2(&sd->bl,wx,wy,skill_num,lv) > 0) { - // clif_skill_fail(sd,0,0,0); - // skill_failed(sd); - // return 0; - //} - if((group=skill_unitsetting(&sd->bl,skill_num,lv,wx,wy,0))==NULL) { skill_failed(sd); return 0; @@ -6255,9 +6259,8 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli status = status_get_status_data(src); sc = status_get_sc(src); // for traps, firewall and fogwall - celest - switch(skillid) + switch( skillid ) { - case MG_SAFETYWALL: val2=skilllv+1; break; @@ -6281,6 +6284,9 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, short skilli val3 = group->val3; //as well as the mapindex to warp to. } break; + case HP_BASILICA: + val1 = src->id; // Store caster id. + break; case PR_SANCTUARY: case NPC_EVILLAND: @@ -7129,6 +7135,17 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns } } break; + + case UNT_BASILICA: + if( battle_check_target(&src->bl, bl, BCT_ENEMY) > 0 && !(status_get_mode(bl)&MD_BOSS) ) + { // knock-back any enemy except Boss + skill_blown(&src->bl, bl, 2, unit_getdir(bl), 0); + clif_fixpos(bl); + } + + if( sg->src_id != bl->id && battle_check_target(&src->bl, bl, BCT_ENEMY) <= 0 ) + status_change_start(bl, type, 100, src->bl.id, 0, 0, 0, sg->interval + 100, 0); + break; case UNT_GRAVITATION: skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); @@ -7192,6 +7209,11 @@ int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned in status_change_end(bl,type,-1); break; + case UNT_BASILICA: + if( sce && sce->val1 == src->val1 ) + status_change_end(bl,type,-1); + 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,-1); @@ -8362,7 +8384,9 @@ int skill_delayfix (struct block_list *bl, int skill_id, int skill_lv) { int delaynodex = skill_get_delaynodex(skill_id, skill_lv); int time = skill_get_delay(skill_id, skill_lv); - + struct map_session_data *sd = BL_CAST(BL_PC, bl); + struct status_change *sc = status_get_sc(bl); + nullpo_retr(0, bl); if (skill_id == SA_ABRACADABRA) @@ -8384,6 +8408,10 @@ int skill_delayfix (struct block_list *bl, int skill_id, int skill_lv) case CH_CHAINCRUSH: time -= 4*status_get_agi(bl) - 2*status_get_dex(bl); break; + case HP_BASILICA: + if( sc && !sc->data[SC_BASILICA] ) + time = 0; // There is no Delay on Basilica creation, only on cancel + break; default: if (battle_config.delay_dependon_dex && !(delaynodex&1)) { // if skill delay is allowed to be reduced by dex @@ -8405,8 +8433,6 @@ int skill_delayfix (struct block_list *bl, int skill_id, int skill_lv) if (!(delaynodex&2)) { - struct status_change *sc; - sc= status_get_sc(bl); if (sc && sc->count) { if (sc->data[SC_POEMBRAGI]) time -= time * sc->data[SC_POEMBRAGI]->val3 / 100; diff --git a/src/map/status.c b/src/map/status.c index 55b5918ce..3925a86d2 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -982,18 +982,6 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int return 1; } - if (((src && map_getcell(src->m,src->x,src->y,CELL_CHKBASILICA)) || - (target && target != src && map_getcell(target->m,target->x,target->y,CELL_CHKBASILICA))) - && !(status->mode&MD_BOSS)) - { //Basilica Check - if (!skill_num) return 0; - hide_flag = skill_get_inf(skill_num); - if (hide_flag&INF_ATTACK_SKILL) - return 0; - if (hide_flag&INF_GROUND_SKILL && skill_get_unit_target(skill_num)&BCT_ENEMY) - return 0; - } - //Should fail when used on top of Land Protector [Skotlex] if (src && skill_num == AL_TELEPORT && map_getcell(src->m, src->x, src->y, CELL_CHKLANDPROTECTOR) && !(status->mode&MD_BOSS)) diff --git a/src/map/unit.c b/src/map/unit.c index 521907c99..fb1fe0113 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -218,11 +218,6 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr data) else i = status_get_speed(bl); - if( md && map_getcell(bl->m,x,y,CELL_CHKBASILICA) ) { - skill_blown(bl,bl,2,unit_getdir(bl),0); - clif_fixpos(bl); - } - if(i > 0) ud->walktimer = add_timer(tick+i,unit_walktoxy_timer,id,i); else if(ud->state.running) { @@ -1013,6 +1008,10 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh if (sc && sc->data[SC_RUN]) casttime = 0; break; + case HP_BASILICA: + if( sc && sc->data[SC_BASILICA] ) + casttime = 0; // No Casting time on basilica cancel + break; case KN_CHARGEATK: { unsigned int k = (distance_bl(src,target)-1)/3; //+100% every 3 cells of distance @@ -1124,11 +1123,12 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, sh if (sc && !sc->count) sc = NULL; - if(sd) { - if (skillnotok(skill_num, sd) || !skill_check_condition(sd, skill_num, skill_lv,0)) - return 0; - } - + if( sd ) + { + if( skillnotok(skill_num, sd) || !skill_check_condition(sd, skill_num, skill_lv,0) ) + return 0; + } + if (!status_check_skilluse(src, NULL, skill_num, 0)) return 0; -- cgit v1.2.3-70-g09d2