summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorrud0lp20 <rud0lp20@54d463be-8e91-2dee-dedb-b68131a5f0ec>2012-06-14 17:33:21 +0000
committerrud0lp20 <rud0lp20@54d463be-8e91-2dee-dedb-b68131a5f0ec>2012-06-14 17:33:21 +0000
commitc07a09726d9e94d75786192fc671cde81dc73176 (patch)
tree8cf57867e258ba4d4c1fbfff8c55d0af760b1a1e /src
parent7167494574430bdaa1fe7fa13d106e2eabbf0f08 (diff)
downloadhercules-c07a09726d9e94d75786192fc671cde81dc73176.tar.gz
hercules-c07a09726d9e94d75786192fc671cde81dc73176.tar.bz2
hercules-c07a09726d9e94d75786192fc671cde81dc73176.tar.xz
hercules-c07a09726d9e94d75786192fc671cde81dc73176.zip
Fixed bugreport:5954 SC_SHADOWFORM Can now be canceled with detecting skills which is check in every 2 seconds.
Fixed bugreport:6010 AB_EXPIATIO now give a piercing damage bonus. Fixed Diamond/Crystallize status to work only to non mob target and its official behavior(bugreport:5893) git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@16296 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src')
-rw-r--r--src/map/battle.c42
-rw-r--r--src/map/mob.c6
-rw-r--r--src/map/pc.c2
-rw-r--r--src/map/status.c35
-rw-r--r--src/map/status.h1
-rw-r--r--src/map/unit.c2
6 files changed, 67 insertions, 21 deletions
diff --git a/src/map/battle.c b/src/map/battle.c
index ce0f1b9a6..a6b422ccb 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -344,7 +344,13 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag
if( tsc->data[SC_THORNSTRAP] && atk_elem == ELE_FIRE )
status_change_end(target, SC_THORNSTRAP, -1);
if( tsc->data[SC_FIRE_CLOAK_OPTION] && atk_elem == ELE_FIRE )
- damage -= damage * tsc->data[SC_FIRE_CLOAK_OPTION]->val2 / 100;
+ damage -= damage * tsc->data[SC_FIRE_CLOAK_OPTION]->val2 / 100;
+ if( tsc->data[SC_CRYSTALIZE] && target->type != BL_MOB){
+ if( atk_elem == ELE_WIND)
+ damage = damage * 150 / 100;
+ if( atk_elem == ELE_FIRE )
+ status_change_end(target, SC_CRYSTALIZE, INVALID_TIMER);
+ }
}
return damage*ratio/100;
}
@@ -573,12 +579,36 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
#endif
if( damage ) {
-
+ struct map_session_data *tsd = BL_CAST(BL_PC, src);
if( sc->data[SC_DEEPSLEEP] ) {
damage += damage / 2; // 1.5 times more damage while in Deep Sleep.
status_change_end(bl,SC_DEEPSLEEP,INVALID_TIMER);
}
-
+ if( tsd && sd && sc->data[SC_CRYSTALIZE] && flag&BF_WEAPON ){
+ switch(tsd->status.weapon){
+ case W_MACE:
+ case W_2HMACE:
+ case W_1HAXE:
+ case W_2HAXE:
+ damage = damage * 150 / 100;
+ break;
+ case W_MUSICAL:
+ case W_WHIP:
+ if(!sd->state.arrow_atk)
+ break;
+ case W_BOW:
+ case W_REVOLVER:
+ case W_RIFLE:
+ case W_GATLING:
+ case W_SHOTGUN:
+ case W_GRENADE:
+ case W_DAGGER:
+ case W_1HSWORD:
+ case W_2HSWORD:
+ damage = damage * 50 / 100;
+ break;
+ }
+ }
if( sc->data[SC_VOICEOFSIREN] )
status_change_end(bl,SC_VOICEOFSIREN,INVALID_TIMER);
}
@@ -2550,6 +2580,12 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
}
}
+ if( sc && sc->data[SC_EXPIATIO] ){
+ i = 5 * sc->data[SC_EXPIATIO]->val1; // 5% per level
+ def1 -= def1 * i / 100;
+ def2 -= def2 * i / 100;
+ }
+
if( battle_config.vit_penalty_type && battle_config.vit_penalty_target&target->type ) {
unsigned char target_count; //256 max targets should be a sane max
target_count = unit_counttargeted(target);
diff --git a/src/map/mob.c b/src/map/mob.c
index 8924ae6eb..b3316b5e9 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -1416,7 +1416,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
return false;
// Abnormalities
- if(( md->sc.opt1 > 0 && md->sc.opt1 != OPT1_STONEWAIT && md->sc.opt1 != OPT1_BURNING )
+ if(( md->sc.opt1 > 0 && md->sc.opt1 != OPT1_STONEWAIT && md->sc.opt1 != OPT1_BURNING && md->sc.opt1 != OPT1_CRYSTALIZE )
|| md->sc.data[SC_BLADESTOP] || md->sc.data[SC__MANHOLE] || md->sc.data[SC_CURSEDCIRCLE_TARGET]) {//Should reset targets.
md->target_id = md->attacked_id = 0;
return false;
@@ -1456,7 +1456,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
if( !battle_check_range(&md->bl, tbl, md->status.rhw.range)
&& ( //Can't attack back and can't reach back.
(!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && (battle_config.mob_ai&0x2 || (md->sc.data[SC_SPIDERWEB] && md->sc.data[SC_SPIDERWEB]->val1)
- || md->sc.data[SC_BITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_CRYSTALIZE] || md->sc.data[SC_THORNSTRAP]
+ || md->sc.data[SC_BITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNSTRAP]
|| md->sc.data[SC__MANHOLE])) // Not yet confirmed if boss will teleport once it can't reach target.
|| !mob_can_reach(md, tbl, md->min_chase, MSS_RUSH)
)
@@ -1478,7 +1478,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick)
|| (!battle_check_range(&md->bl, abl, md->status.rhw.range) // Not on Melee Range and ...
&& ( // Reach check
(!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && (battle_config.mob_ai&0x2 || (md->sc.data[SC_SPIDERWEB] && md->sc.data[SC_SPIDERWEB]->val1)
- || md->sc.data[SC_BITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_CRYSTALIZE] || md->sc.data[SC_THORNSTRAP]
+ || md->sc.data[SC_BITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNSTRAP]
|| md->sc.data[SC__MANHOLE])) // Not yet confirmed if boss will teleport once it can't reach target.
|| !mob_can_reach(md, abl, dist+md->db->range3, MSS_RUSH)
)
diff --git a/src/map/pc.c b/src/map/pc.c
index b6f71d8e6..b69549b13 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -4312,7 +4312,7 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, int lv)
md = (TBL_MOB *)bl;
- if(md->state.steal_flag == UCHAR_MAX || ( md->sc.opt1 && md->sc.opt1 != OPT1_BURNING ) ) //already stolen from / status change check
+ if(md->state.steal_flag == UCHAR_MAX || ( md->sc.opt1 && md->sc.opt1 != OPT1_BURNING && md->sc.opt1 != OPT1_CRYSTALIZE ) ) //already stolen from / status change check
return 0;
sd_status= status_get_status_data(&sd->bl);
diff --git a/src/map/status.c b/src/map/status.c
index fefa63508..6a73bbb71 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -660,7 +660,7 @@ void initChangeTables(void) {
set_sc( SO_FIREWALK , SC_PROPERTYWALK , SI_PROPERTYWALK , SCB_NONE );
set_sc( SO_ELECTRICWALK , SC_PROPERTYWALK , SI_PROPERTYWALK , SCB_NONE );
set_sc( SO_SPELLFIST , SC_SPELLFIST , SI_SPELLFIST , SCB_NONE );
- set_sc( SO_DIAMONDDUST , SC_CRYSTALIZE , SI_COLD , SCB_NONE );//Will add flags in major balance update 8 [Rytech]
+ set_sc_with_vfx( SO_DIAMONDDUST , SC_CRYSTALIZE , SI_COLD , SCB_NONE ); // it does show the snow icon on mobs but doesn't affect it.
set_sc( SO_CLOUD_KILL , SC_POISON , SI_CLOUDKILL , SCB_NONE );
set_sc( SO_STRIKING , SC_STRIKING , SI_STRIKING , SCB_WATK|SCB_CRI );
set_sc( SO_WARMER , SC_WARMER , SI_WARMER , SCB_NONE );
@@ -966,6 +966,7 @@ void initChangeTables(void) {
StatusChangeStateTable[SC_VACUUM_EXTREME] |= SCS_NOMOVE;
StatusChangeStateTable[SC_CURSEDCIRCLE_ATKER] |= SCS_NOMOVE;
StatusChangeStateTable[SC_CURSEDCIRCLE_TARGET] |= SCS_NOMOVE;
+ StatusChangeStateTable[SC_CRYSTALIZE] |= SCS_NOMOVE|SCS_NOMOVECOND;
/* StatusChangeState (SCS_) NOPICKUPITEMS */
StatusChangeStateTable[SC_HIDING] |= SCS_NOPICKITEM;
@@ -987,7 +988,7 @@ void initChangeTables(void) {
StatusChangeStateTable[SC_OBLIVIONCURSE] |= SCS_NOCAST;
StatusChangeStateTable[SC_WHITEIMPRISON] |= SCS_NOCAST;
StatusChangeStateTable[SC__INVISIBILITY] |= SCS_NOCAST;
- StatusChangeStateTable[SC_CRYSTALIZE] |= SCS_NOCAST;
+ StatusChangeStateTable[SC_CRYSTALIZE] |= SCS_NOCAST|SCS_NOCASTCOND;
StatusChangeStateTable[SC__IGNORANCE] |= SCS_NOCAST;
StatusChangeStateTable[SC_DEEPSLEEP] |= SCS_NOCAST;
StatusChangeStateTable[SC_SATURDAYNIGHTFEVER] |= SCS_NOCAST;
@@ -1486,7 +1487,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int
//on dead characters, said checks are left to skill.c [Skotlex]
if (target && status_isdead(target))
return 0;
- if( src && (sc = status_get_sc(src)) && sc->data[SC_CRYSTALIZE] )
+ if( src && (sc = status_get_sc(src)) && sc->data[SC_CRYSTALIZE] && src->type != BL_MOB)
return 0;
}
@@ -1518,7 +1519,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int
if( sc && sc->count ) {
- if( sc->opt1 >0 && sc->opt1 != OPT1_BURNING && skill_num != SR_GENTLETOUCH_CURE ) { //Stuned/Frozen/etc
+ if( sc->opt1 >0 && (sc->opt1 != OPT1_CRYSTALIZE && src->type != BL_MOB) && sc->opt1 != OPT1_BURNING && skill_num != SR_GENTLETOUCH_CURE ) { //Stuned/Frozen/etc
if (flag != 1) //Can't cast, casted stuff can't damage.
return 0;
if (!(skill_get_inf(skill_num)&INF_GROUND_SKILL))
@@ -3371,7 +3372,8 @@ void status_calc_state( struct block_list *bl, struct status_change *sc, enum sc
|| (sc->data[SC_BASILICA] && sc->data[SC_BASILICA]->val4 == bl->id) // Basilica caster cannot move
|| (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF)
|| (sc->data[SC_CLOAKING] && //Need wall at level 1-2
- sc->data[SC_CLOAKING]->val1 < 3 && !(sc->data[SC_CLOAKING]->val4&1))
+ sc->data[SC_CLOAKING]->val1 < 3 && !(sc->data[SC_CLOAKING]->val4&1)
+ || (sc->data[SC_CRYSTALIZE] && bl->type != BL_MOB))
) {
sc->cant.move += ( start ? 1 : -1 );
}
@@ -3381,8 +3383,7 @@ void status_calc_state( struct block_list *bl, struct status_change *sc, enum sc
if( flag&SCS_NOCAST ) {
if( !(flag&SCS_NOCASTCOND) ) {
sc->cant.cast += ( start ? 1 : -1 );
- } else {
- /* to date there are usable conditions on nocast sclist */
+ } else if( (sc->data[SC_CRYSTALIZE] && bl->type != BL_MOB) ){
sc->cant.cast += ( start ? 1 : -1 );
}
}
@@ -8048,11 +8049,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_FREEZE: sc->opt1 = OPT1_FREEZE; break;
case SC_STUN: sc->opt1 = OPT1_STUN; break;
case SC_SLEEP:
- case SC_DEEPSLEEP:
- sc->opt1 = OPT1_SLEEP;
- break;
- case SC_BURNING: sc->opt1 = OPT1_BURNING; break; // Burning need this to be showed correctly. [pakpil]
- case SC_WHITEIMPRISON: sc->opt1 = OPT1_IMPRISON; break;
+ case SC_DEEPSLEEP: sc->opt1 = OPT1_SLEEP; break;
+ case SC_BURNING: sc->opt1 = OPT1_BURNING; break; // Burning need this to be showed correctly. [pakpil]
+ case SC_WHITEIMPRISON: sc->opt1 = OPT1_IMPRISON; break;
+ case SC_CRYSTALIZE: sc->opt1 = OPT1_CRYSTALIZE; break;
//OPT2
case SC_POISON: sc->opt2 |= OPT2_POISON; break;
case SC_CURSE: sc->opt2 |= OPT2_CURSE; break;
@@ -8895,6 +8895,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
case SC_DEEPSLEEP:
case SC_BURNING:
case SC_WHITEIMPRISON:
+ case SC_CRYSTALIZE:
sc->opt1 = 0;
break;
@@ -9194,6 +9195,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
map_foreachinrange( status_change_timer_sub, bl, sce->val3, BL_CHAR, bl, sce, type, tick);
if( --(sce->val2)>0 ){
+ sce->val4 += 250; // use for Shadow Form 2 seconds checking.
sc_timer_next(250+tick, status_change_timer, bl->id, data);
return 0;
}
@@ -9748,7 +9750,8 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
case SC_CRYSTALIZE:
if( --(sce->val4) >= 0 )
{ // Drains 2% of HP and 1% of SP every seconds.
- status_charge(bl, status->max_hp * 2 / 100, status->max_sp / 100);
+ if( bl->type != BL_MOB) // doesn't work on mobs
+ status_charge(bl, status->max_hp * 2 / 100, status->max_sp / 100);
sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
return 0;
}
@@ -9907,6 +9910,9 @@ int status_change_timer_sub(struct block_list* bl, va_list ap)
switch( type ) {
case SC_SIGHT: /* ƒTƒCƒg */
+ if( tsc && tsc->data[SC__SHADOWFORM] && (sce && sce->val4 >0 && sce->val4%2000 == 0) && // for every 2 seconds do the checking
+ rnd()%100 < 100-tsc->data[SC__SHADOWFORM]->val1*10 ) // [100 - (Skill Level x 10)] %
+ status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER);
case SC_CONCENTRATE:
status_change_end(bl, SC_HIDING, INVALID_TIMER);
status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
@@ -9926,6 +9932,9 @@ int status_change_timer_sub(struct block_list* bl, va_list ap)
if(battle_check_target( src, bl, BCT_ENEMY ) > 0)
skill_attack(BF_MAGIC,src,src,bl,AL_RUWACH,1,tick,0);
}
+ if( tsc && tsc->data[SC__SHADOWFORM] && (sce && sce->val4 >0 && sce->val4%2000 == 0) && // for every 2 seconds do the checking
+ rnd()%100 < 100-tsc->data[SC__SHADOWFORM]->val1*10 ) // [100 - (Skill Level x 10)] %
+ status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER);
break;
case SC_SIGHTBLASTER:
if (battle_check_target( src, bl, BCT_ENEMY ) > 0 &&
diff --git a/src/map/status.h b/src/map/status.h
index 5e52b572c..192ffd6d9 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -1324,6 +1324,7 @@ enum {
OPT1_STONEWAIT=6, //Petrifying
OPT1_BURNING,
OPT1_IMPRISON,
+ OPT1_CRYSTALIZE,
};
//opt2: Stackable status changes.
diff --git a/src/map/unit.c b/src/map/unit.c
index 71baef598..c955fa686 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -889,7 +889,7 @@ int unit_can_move(struct block_list *bl)
if( sc->cant.move || (sc->data[SC_FEAR] && sc->data[SC_FEAR]->val2 > 0) )
return 0;
- if (sc->opt1 > 0 && sc->opt1 != OPT1_STONEWAIT && sc->opt1 != OPT1_BURNING)
+ if (sc->opt1 > 0 && sc->opt1 != OPT1_STONEWAIT && sc->opt1 != OPT1_BURNING && (sc->opt1 != OPT1_CRYSTALIZE && bl->type != BL_MOB))
return 0;
if ((sc->option & OPTION_HIDE) && (!sd || pc_checkskill(sd, RG_TUNNELDRIVE) <= 0))