summaryrefslogtreecommitdiff
path: root/src/map/status.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/status.c')
-rw-r--r--src/map/status.c486
1 files changed, 307 insertions, 179 deletions
diff --git a/src/map/status.c b/src/map/status.c
index 9a2151971..c73f78c42 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -2,43 +2,46 @@
// See the LICENSE file
// Portions Copyright (c) Athena Dev Teams
-#include "../common/cbasetypes.h"
-#include "../common/timer.h"
-#include "../common/nullpo.h"
-#include "../common/random.h"
-#include "../common/showmsg.h"
-#include "../common/malloc.h"
-#include "../common/utils.h"
-#include "../common/ers.h"
-#include "../common/strlib.h"
+#define HERCULES_CORE
+
+#include "../config/core.h" // ANTI_MAYAP_CHEAT, DBPATH, DEFTYPE_MAX, DEFTYPE_MIN, DEVOTION_REFLECT_DAMAGE, RENEWAL, RENEWAL_ASPD, RENEWAL_EDP
+#include "status.h"
+
+#include <math.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "battle.h"
+#include "chrif.h"
+#include "clif.h"
+#include "elemental.h"
+#include "guild.h"
+#include "homunculus.h"
+#include "itemdb.h"
#include "map.h"
+#include "mercenary.h"
+#include "mob.h"
+#include "npc.h"
#include "path.h"
#include "pc.h"
#include "pet.h"
-#include "npc.h"
-#include "mob.h"
-#include "clif.h"
-#include "guild.h"
+#include "script.h"
#include "skill.h"
-#include "itemdb.h"
-#include "battle.h"
-#include "chrif.h"
#include "skill.h"
-#include "status.h"
-#include "script.h"
#include "unit.h"
-#include "homunculus.h"
-#include "mercenary.h"
-#include "elemental.h"
#include "vending.h"
-
-#include <time.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <memory.h>
-#include <string.h>
-#include <math.h>
+#include "../common/cbasetypes.h"
+#include "../common/ers.h"
+#include "../common/malloc.h"
+#include "../common/nullpo.h"
+#include "../common/random.h"
+#include "../common/showmsg.h"
+#include "../common/strlib.h"
+#include "../common/timer.h"
+#include "../common/utils.h"
struct status_interface status_s;
@@ -177,7 +180,7 @@ void initChangeTables(void) {
add_sc( TF_POISON , SC_POISON );
set_sc( KN_TWOHANDQUICKEN , SC_TWOHANDQUICKEN , SI_TWOHANDQUICKEN , SCB_ASPD );
add_sc( KN_AUTOCOUNTER , SC_AUTOCOUNTER );
- set_sc( PR_IMPOSITIO , SC_IMPOSITIO , SI_IMPOSITIO ,
+ set_sc( PR_IMPOSITIO , SC_IMPOSITIO , SI_IMPOSITIO ,
#ifdef RENEWAL
SCB_NONE );
#else
@@ -201,7 +204,7 @@ void initChangeTables(void) {
set_sc( BS_WEAPONPERFECT , SC_WEAPONPERFECT , SI_WEAPONPERFECT, SCB_NONE );
set_sc( BS_OVERTHRUST , SC_OVERTHRUST , SI_OVERTHRUST , SCB_NONE );
set_sc( BS_MAXIMIZE , SC_MAXIMIZEPOWER , SI_MAXIMIZE , SCB_REGEN );
- add_sc( HT_LANDMINE , SC_STUN );
+ add_sc( HT_LANDMINE , SC_STUN );
set_sc( HT_ANKLESNARE , SC_ANKLESNARE , SI_ANKLESNARE , SCB_NONE );
add_sc( HT_SANDMAN , SC_SLEEP );
add_sc( HT_FLASHER , SC_BLIND );
@@ -466,13 +469,13 @@ void initChangeTables(void) {
set_sc( HAMI_BLOODLUST , SC_HAMI_BLOODLUST , SI_BLANK , SCB_BATK|SCB_WATK );
// Homunculus S
+ set_sc( MH_LIGHT_OF_REGENE , SC_LIGHT_OF_REGENE , SI_LIGHT_OF_REGENE , SCB_NONE );
+ set_sc( MH_OVERED_BOOST , SC_OVERED_BOOST , SI_OVERED_BOOST , SCB_FLEE|SCB_ASPD|SCB_DEF );
+
add_sc(MH_STAHL_HORN, SC_STUN);
set_sc(MH_ANGRIFFS_MODUS, SC_ANGRIFFS_MODUS, SI_ANGRIFFS_MODUS, SCB_BATK | SCB_DEF | SCB_FLEE | SCB_MAXHP);
set_sc(MH_GOLDENE_FERSE, SC_GOLDENE_FERSE, SI_GOLDENE_FERSE, SCB_ASPD|SCB_MAXHP);
add_sc( MH_STEINWAND, SC_SAFETYWALL );
- add_sc(MH_ERASER_CUTTER, SC_ERASER_CUTTER);
- set_sc(MH_OVERED_BOOST, SC_OVERED_BOOST, SI_BLANK, SCB_FLEE|SCB_ASPD);
- add_sc(MH_LIGHT_OF_REGENE, SC_LIGHT_OF_REGENE);
set_sc(MH_VOLCANIC_ASH, SC_VOLCANIC_ASH, SI_VOLCANIC_ASH, SCB_DEF|SCB_DEF2|SCB_HIT|SCB_BATK|SCB_FLEE);
set_sc(MH_GRANITIC_ARMOR, SC_GRANITIC_ARMOR, SI_GRANITIC_ARMOR, SCB_NONE);
set_sc(MH_MAGMA_FLOW, SC_MAGMA_FLOW, SI_MAGMA_FLOW, SCB_NONE);
@@ -482,11 +485,11 @@ void initChangeTables(void) {
add_sc(MH_POISON_MIST, SC_BLIND);
set_sc(MH_PAIN_KILLER, SC_PAIN_KILLER, SI_PAIN_KILLER, SCB_ASPD);
- add_sc(MH_STYLE_CHANGE , SC_STYLE_CHANGE);
- set_sc( MH_TINDER_BREAKER , SC_RG_CCONFINE_S , SI_RG_CCONFINE_S , SCB_NONE );
+ set_sc( MH_SILENT_BREEZE , SC_SILENCE , SI_SILENT_BREEZE , SCB_NONE );
+ add_sc( MH_STYLE_CHANGE , SC_STYLE_CHANGE);
+ set_sc( MH_TINDER_BREAKER , SC_RG_CCONFINE_S , SI_RG_CCONFINE_S , SCB_NONE );
set_sc( MH_TINDER_BREAKER , SC_RG_CCONFINE_M , SI_RG_CCONFINE_M , SCB_FLEE );
-
add_sc( MER_CRASH , SC_STUN );
set_sc( MER_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
add_sc( MS_MAGNUM , SC_SUB_WEAPONPROPERTY );
@@ -633,6 +636,7 @@ void initChangeTables(void) {
**/
add_sc( SR_DRAGONCOMBO , SC_STUN );
add_sc( SR_EARTHSHAKER , SC_STUN );
+ set_sc( SR_FALLENEMPIRE , SC_FALLENEMPIRE , SI_FALLENEMPIRE , SCB_NONE );
set_sc( SR_CRESCENTELBOW , SC_CRESCENTELBOW , SI_CRESCENTELBOW , SCB_NONE );
set_sc_with_vfx( SR_CURSEDCIRCLE , SC_CURSEDCIRCLE_TARGET, SI_CURSEDCIRCLE_TARGET , SCB_NONE );
set_sc( SR_LIGHTNINGWALK , SC_LIGHTNINGWALK , SI_LIGHTNINGWALK , SCB_NONE );
@@ -640,6 +644,7 @@ void initChangeTables(void) {
set_sc( SR_GENTLETOUCH_ENERGYGAIN, SC_GENTLETOUCH_ENERGYGAIN , SI_GENTLETOUCH_ENERGYGAIN, SCB_NONE );
set_sc( SR_GENTLETOUCH_CHANGE , SC_GENTLETOUCH_CHANGE , SI_GENTLETOUCH_CHANGE , SCB_ASPD|SCB_MDEF|SCB_MAXHP );
set_sc( SR_GENTLETOUCH_REVITALIZE, SC_GENTLETOUCH_REVITALIZE , SI_GENTLETOUCH_REVITALIZE, SCB_MAXHP|SCB_REGEN );
+ set_sc( SR_FLASHCOMBO , SC_FLASHCOMBO , SI_FLASHCOMBO , SCB_WATK );
/**
* Wanderer / Minstrel
**/
@@ -1118,8 +1123,8 @@ int status_charge(struct block_list* bl, int64 hp, int64 sp) {
}
//Inflicts damage on the target with the according walkdelay.
-//If flag&1, damage is passive and does not triggers cancelling status changes.
-//If flag&2, fail if target does not has enough to substract.
+//If flag&1, damage is passive and does not triggers canceling status changes.
+//If flag&2, fail if target does not has enough to subtract.
//If flag&4, if killed, mob must not give exp/loot.
//flag will be set to &8 when damaging sp of a dead character
int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, int64 in_sp, int walkdelay, int flag) {
@@ -1266,7 +1271,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp,
st->hp = 1; //To let the dead function cast skills and all that.
//NOTE: These dead functions should return: [Skotlex]
- //0: Death cancelled, auto-revived.
+ //0: Death canceled, auto-revived.
//Non-zero: Standard death. Clear status, cancel move/attack, etc
//&2: Also remove object from map.
//&4: Also delete object from memory.
@@ -1281,7 +1286,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp,
break;
}
- if(!flag) //Death cancelled.
+ if(!flag) //Death canceled.
return (int)(hp+sp);
//Normal death
@@ -1319,16 +1324,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp,
return (int)(hp+sp);
}
- if(target->type == BL_PC) {
- TBL_PC *sd = BL_CAST(BL_PC,target);
- TBL_HOM *hd = sd->hd;
- if(hd && hd->sc.data[SC_LIGHT_OF_REGENE]){
- clif->skillcasting(&hd->bl, hd->bl.id, target->id, 0,0, MH_LIGHT_OF_REGENE, skill->get_ele(MH_LIGHT_OF_REGENE, 1), 10); //just to display usage
- clif->skill_nodamage(&sd->bl, target, ALL_RESURRECTION, 1, status->revive(&sd->bl,10*hd->sc.data[SC_LIGHT_OF_REGENE]->val1,0));
- status_change_end(&sd->hd->bl,SC_LIGHT_OF_REGENE,INVALID_TIMER);
- return (int)(hp + sp);
- }
- }
+
if (target->type == BL_MOB && sc && sc->data[SC_REBIRTH] && !((TBL_MOB*) target)->state.rebirth) {
// Ensure the monster has not already rebirthed before doing so.
status->revive(target, sc->data[SC_REBIRTH]->val2, 0);
@@ -1435,7 +1431,7 @@ int status_heal(struct block_list *bl,int64 in_hp,int64 in_sp, int flag) {
//If rates are > 0, percent is of current HP/SP
//If rates are < 0, percent is of max HP/SP
//If !flag, this is heal, otherwise it is damage.
-//Furthermore, if flag==2, then the target must not die from the substraction.
+//Furthermore, if flag==2, then the target must not die from the subtraction.
int status_percent_change(struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag) {
struct status_data *st;
unsigned int hp = 0, sp = 0;
@@ -1639,16 +1635,16 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
if( sc && sc->count ) {
- if (skill_id != RK_REFRESH && sc->opt1 >0 && !(sc->opt1 == OPT1_CRYSTALIZE && src->type == BL_MOB) && sc->opt1 != OPT1_BURNING && skill_id != SR_GENTLETOUCH_CURE) { //Stuned/Frozen/etc
+ if (skill_id != RK_REFRESH && sc->opt1 >0 && !(sc->opt1 == OPT1_CRYSTALIZE && src->type == BL_MOB) && sc->opt1 != OPT1_BURNING && skill_id != SR_GENTLETOUCH_CURE) { //Stunned/Frozen/etc
if (flag != 1) //Can't cast, casted stuff can't damage.
return 0;
if (!(skill->get_inf(skill_id)&INF_GROUND_SKILL))
- return 0; //Targetted spells can't come off.
+ return 0; //Targeted spells can't come off.
}
if (
(sc->data[SC_TRICKDEAD] && skill_id != NV_TRICKDEAD)
- || (sc->data[SC_AUTOCOUNTER] && !flag)
+ || (sc->data[SC_AUTOCOUNTER] && !flag && skill_id)
|| (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF && skill_id != PA_GOSPEL)
|| (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF && flag != 2)
)
@@ -1788,7 +1784,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
if( ( tsc->data[SC_STEALTHFIELD] || tsc->data[SC_CAMOUFLAGE] ) && !(st->mode&(MD_BOSS|MD_DETECTOR)) && flag == 4 )
return 0;
}
- //If targetting, cloak+hide protect you, otherwise only hiding does.
+ //If targeting, cloak+hide protect you, otherwise only hiding does.
hide_flag = flag?OPTION_HIDE:(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK);
//You cannot hide from ground skills.
@@ -1821,7 +1817,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
}
}
break;
- case BL_ITEM: //Allow targetting of items to pick'em up (or in the case of mobs, to loot them).
+ case BL_ITEM: //Allow targeting of items to pick'em up (or in the case of mobs, to loot them).
//TODO: Would be nice if this could be used to judge whether the player can or not pick up the item it targets. [Skotlex]
if (st->mode&MD_LOOTER)
return 1;
@@ -1897,7 +1893,7 @@ int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st)
#ifdef RENEWAL_ASPD
short mod = -1;
- switch( sd->weapontype2 ){ // adjustment for dual weilding
+ switch( sd->weapontype2 ){ // adjustment for dual wielding
case W_DAGGER: mod = 0; break; // 0, 1, 1
case W_1HSWORD:
case W_1HAXE: mod = 1;
@@ -2074,6 +2070,7 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) {
struct status_data *mstatus;
struct block_list *mbl = NULL;
int flag=0;
+ int guardup_lv = 0;
if(opt&SCO_FIRST) { //Set basic level on respawn.
if (md->level > 0 && md->level <= MAX_LEVEL && md->level != md->db->lv)
@@ -2089,7 +2086,8 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) {
if (md->special_state.size)
flag|=2;
- if (md->guardian_data && md->guardian_data->guardup_lv)
+ if( md->guardian_data && md->guardian_data->g
+ && (guardup_lv = guild->checkskill(md->guardian_data->g,GD_GUARDUP)) )
flag|=4;
if (battle_config.slaves_inherit_speed && md->master_id)
@@ -2224,10 +2222,10 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) {
mstatus->mdef += (gc->defense+2)/3;
}
if(md->class_ != MOBID_EMPERIUM) {
- mstatus->batk += mstatus->batk * 10*md->guardian_data->guardup_lv/100;
- mstatus->rhw.atk += mstatus->rhw.atk * 10*md->guardian_data->guardup_lv/100;
- mstatus->rhw.atk2 += mstatus->rhw.atk2 * 10*md->guardian_data->guardup_lv/100;
- mstatus->aspd_rate -= 100*md->guardian_data->guardup_lv;
+ mstatus->batk += mstatus->batk * 10*guardup_lv/100;
+ mstatus->rhw.atk += mstatus->rhw.atk * 10*guardup_lv/100;
+ mstatus->rhw.atk2 += mstatus->rhw.atk2 * 10*guardup_lv/100;
+ mstatus->aspd_rate -= 100*guardup_lv;
}
}
@@ -2561,7 +2559,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
return 1;
}
- // sanitize the refine level in case someone decreased the value inbetween
+ // sanitize the refine level in case someone decreased the value in between
if (sd->status.inventory[index].refine > MAX_REFINE)
sd->status.inventory[index].refine = MAX_REFINE;
@@ -2589,7 +2587,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
wa->matk += status->refine_info[wlv].bonus[r-1] / 100;
#endif
- //Overrefine bonus.
+ //Overrefined bonus.
if (r)
wd->overrefine = status->refine_info[wlv].randombonus_max[r-1] / 100;
@@ -3417,6 +3415,8 @@ int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt) {
void status_calc_regen(struct block_list *bl, struct status_data *st, struct regen_data *regen) {
struct map_session_data *sd;
int val, skill_lv, reg_flag;
+ nullpo_retv(bl);
+ nullpo_retv(st);
if( !(bl->type&BL_REGEN) || !regen )
return;
@@ -3678,7 +3678,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
st->batk = status->calc_batk(bl, sc, st->batk, true);
}
- if(flag&SCB_WATK) {
+ if(flag&SCB_WATK) {
st->rhw.atk = status->calc_watk(bl, sc, bst->rhw.atk, true);
if (!sd) //Should not affect weapon refine bonus
st->rhw.atk2 = status->calc_watk(bl, sc, bst->rhw.atk2, true);
@@ -3884,7 +3884,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
}
if(flag&SCB_MATK) {
- status->get_matk(bl, 0);
+ status->update_matk(bl);
}
if(flag&SCB_ASPD) {
@@ -4643,6 +4643,8 @@ unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc,
watk += watk * sc->data[SC_TIDAL_WEAPON]->val2 / 100;
if(sc->data[SC_ANGRIFFS_MODUS])
watk += watk * sc->data[SC_ANGRIFFS_MODUS]->val2/100;
+ if( sc->data[SC_FLASHCOMBO] )
+ watk += sc->data[SC_FLASHCOMBO]->val2;
return (unsigned short)cap_value(watk,0,USHRT_MAX);
}
@@ -4842,8 +4844,6 @@ signed short status_calc_flee(struct block_list *bl, struct status_change *sc, i
flee += 10;
if (sc->data[SC_ANGRIFFS_MODUS])
flee -= sc->data[SC_ANGRIFFS_MODUS]->val3;
- if (sc->data[SC_OVERED_BOOST])
- flee = max(flee,sc->data[SC_OVERED_BOOST]->val2);
if(sc->data[SC_GS_ADJUSTMENT])
flee += 30;
if(sc->data[SC_HLIF_SPEED])
@@ -4891,6 +4891,9 @@ signed short status_calc_flee(struct block_list *bl, struct status_change *sc, i
if(status_get_element(bl) == ELE_WATER) //water type
flee /= 2;
}
+
+ if( sc->data[SC_OVERED_BOOST] ) // should be final and unmodifiable by any means
+ flee = sc->data[SC_OVERED_BOOST]->val2;
return (short)cap_value(flee,1,SHRT_MAX);
}
@@ -4923,6 +4926,8 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def
/* some statuses that are hidden in the status window */
if( sc && sc->data[SC_CAMOUFLAGE] )
def -= def * 5 * (10-sc->data[SC_CAMOUFLAGE]->val4) / 100;
+ if( sc->data[SC_OVERED_BOOST] && bl->type == BL_PC )
+ def -= def * 50 / 100;
if( sc && sc->data[SC_GENTLETOUCH_REVITALIZE] && sc->data[SC_GENTLETOUCH_REVITALIZE]->val4 )
def += 2 * sc->data[SC_GENTLETOUCH_REVITALIZE]->val4;
if( sc->data[SC_FORCEOFVANGUARD] )
@@ -4942,27 +4947,32 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def
if(sc->data[SC_STEELBODY])
return 90;
#endif
+
+ if(sc->data[SC_STONEHARDSKIN])
+ def += sc->data[SC_STONEHARDSKIN]->val1;
+ if(sc->data[SC_DRUMBATTLE])
+ def += sc->data[SC_DRUMBATTLE]->val3;
if(sc->data[SC_STONESKIN])
def += sc->data[SC_STONESKIN]->val2;
- if(sc->data[SC_DRUMBATTLE])
- def += sc->data[SC_DRUMBATTLE]->val3;
if(sc->data[SC_HAMI_DEFENCE]) //[orn]
- def += sc->data[SC_HAMI_DEFENCE]->val2 ;
- if(sc->data[SC_INCDEFRATE])
- def += def * sc->data[SC_INCDEFRATE]->val1/100;
+ def += sc->data[SC_HAMI_DEFENCE]->val2;
+
if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2)
def += 50;
if(sc->data[SC_ODINS_POWER])
def -= 20;
- if( sc->data[SC_ANGRIFFS_MODUS] )
- def -= 30 + 20 * sc->data[SC_ANGRIFFS_MODUS]->val1;
- if(sc->data[SC_STONEHARDSKIN])
- def += sc->data[SC_STONEHARDSKIN]->val1;
+
+#ifndef RENEWAL
if(sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
def >>=1;
if(sc->data[SC_FREEZE])
def >>=1;
+ if(sc->data[SC_INCDEFRATE])
+ def += def * sc->data[SC_INCDEFRATE]->val1/100;
+#endif
+ if( sc->data[SC_ANGRIFFS_MODUS] )
+ def -= 30 + 20 * sc->data[SC_ANGRIFFS_MODUS]->val1;
if(sc->data[SC_CRUCIS])
def -= def * sc->data[SC_CRUCIS]->val2/100;
if(sc->data[SC_LKCONCENTRATION])
@@ -4971,7 +4981,7 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def
def >>=1;
if(sc->data[SC_PROVOKE] && bl->type != BL_PC) // Provoke doesn't alter player defense->
def -= def * sc->data[SC_PROVOKE]->val4/100;
- if(sc->data[SC_NOEQUIPSHIELD] && bl->type != BL_PC)
+ if(sc->data[SC_NOEQUIPSHIELD])
def -= def * sc->data[SC_NOEQUIPSHIELD]->val2/100;
if (sc->data[SC_FLING])
def -= def * (sc->data[SC_FLING]->val2)/100;
@@ -4981,20 +4991,17 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def
def -= def * (10 + 10 * sc->data[SC_SATURDAY_NIGHT_FEVER]->val1) / 100;
if(sc->data[SC_EARTHDRIVE])
def -= def * 25 / 100;
- if(sc->data[SC_SOLID_SKIN_OPTION])
- def += def * sc->data[SC_SOLID_SKIN_OPTION]->val2 / 100;
if( sc->data[SC_ROCK_CRUSHER] )
def -= def * sc->data[SC_ROCK_CRUSHER]->val2 / 100;
+ if( sc->data[SC_FROSTMISTY] )
+ def -= def * 10 / 100;
+ if( sc->data[SC_OVERED_BOOST] && bl->type == BL_HOM )
+ def -= def * 50 / 100;
+
if( sc->data[SC_POWER_OF_GAIA] )
def += def * sc->data[SC_POWER_OF_GAIA]->val2 / 100;
- if( sc->data[SC_NEUTRALBARRIER] )
- def += def * (5 * sc->data[SC_NEUTRALBARRIER]->val1 + 10) / 100;
- if( sc->data[SC_SHIELDSPELL_REF] && sc->data[SC_SHIELDSPELL_REF]->val1 == 2 )
- def += sc->data[SC_SHIELDSPELL_REF]->val2;
if( sc->data[SC_PRESTIGE] )
- def += sc->data[SC_PRESTIGE]->val1;
- if( sc->data[SC_FROSTMISTY] )
- def -= def * 10 / 100;
+ def += def * sc->data[SC_PRESTIGE]->val1 / 100;
if(sc->data[SC_VOLCANIC_ASH] && (bl->type==BL_MOB)){
if(status_get_race(bl)==RC_PLANT)
def /= 2;
@@ -5017,7 +5024,7 @@ signed short status_calc_def2(struct block_list *bl, struct status_change *sc, i
#ifdef RENEWAL
if( sc && sc->data[SC_ASSUMPTIO] )
def2 <<= 1;
-#endif
+#endif
if( sc && sc->data[SC_CAMOUFLAGE] )
def2 -= def2 * 5 * (10-sc->data[SC_CAMOUFLAGE]->val4) / 100;
#ifdef RENEWAL
@@ -5471,11 +5478,6 @@ short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int
if (!sc || !sc->count)
return cap_value(aspd, 0, 2000);
- if (!sc->data[SC_QUAGMIRE]) {
- if (sc->data[SC_OVERED_BOOST])
- aspd = 2000 - sc->data[SC_OVERED_BOOST]->val3*10;
- }
-
if ((sc->data[SC_GUST_OPTION] || sc->data[SC_BLAST_OPTION]
|| sc->data[SC_WILD_STORM_OPTION]))
aspd -= 50; // +5 ASPD
@@ -5484,6 +5486,8 @@ short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int
if( sc && sc->data[SC_MTF_ASPD] )
aspd -= 10;
+ if (sc->data[SC_OVERED_BOOST]) // should be final and unmodifiable by any means
+ aspd = 2000 - sc->data[SC_OVERED_BOOST]->val3 * 10;
return cap_value(aspd, 0, 2000); // will be recap for proper bl anyway
}
@@ -5916,7 +5920,7 @@ struct status_data *status_get_base_status(struct block_list *bl)
case BL_HOM: return &((TBL_HOM*)bl)->base_status;
case BL_MER: return &((TBL_MER*)bl)->base_status;
case BL_ELEM: return &((TBL_ELEM*)bl)->base_status;
- case BL_NPC: return ((mob->db_checkid(((TBL_NPC*)bl)->class_) == 0) ? &((TBL_NPC*)bl)->status : NULL);
+ case BL_NPC: return ((mob->db_checkid(((TBL_NPC*)bl)->class_) == 0) ? &((TBL_NPC*)bl)->status : NULL);
default:
return NULL;
}
@@ -5933,8 +5937,8 @@ defType status_get_def(struct block_list *bl) {
}
unsigned short status_get_speed(struct block_list *bl) {
- if(bl->type==BL_NPC)//Only BL with speed data but no status_data [Skotlex]
- return ((struct npc_data *)bl)->speed;
+ if(bl->type==BL_NPC)//Only BL with speed data but no status_data [Skotlex]
+ return ((struct npc_data *)bl)->speed;
return status->get_status_data(bl)->speed;
}
@@ -5984,15 +5988,18 @@ int status_get_guild_id(struct block_list *bl) {
if (((TBL_PET*)bl)->msd)
return ((TBL_PET*)bl)->msd->status.guild_id;
break;
- case BL_MOB: {
+ case BL_MOB:
+ {
struct map_session_data *msd;
struct mob_data *md = (struct mob_data *)bl;
- if (md->guardian_data) //Guardian's guild [Skotlex]
- return md->guardian_data->guild_id;
- if (md->special_state.ai && (msd = map->id2sd(md->master_id)) != NULL)
+ if( md->guardian_data ) { //Guardian's guild [Skotlex]
+ // Guardian guild data may not been available yet, castle data is always set
+ return (md->guardian_data->g)?md->guardian_data->g->guild_id:md->guardian_data->castle->guild_id;
+ }
+ if( md->special_state.ai && (msd = map->id2sd(md->master_id)) != NULL )
return msd->status.guild_id; //Alchemist's mobs [Skotlex]
- }
- break;
+ break;
+ }
case BL_HOM:
if (((TBL_HOM*)bl)->master)
return ((TBL_HOM*)bl)->master->status.guild_id;
@@ -6028,7 +6035,7 @@ int status_get_emblem_id(struct block_list *bl) {
struct map_session_data *msd;
struct mob_data *md = (struct mob_data *)bl;
if (md->guardian_data) //Guardian's guild [Skotlex]
- return md->guardian_data->emblem_id;
+ return (md->guardian_data->g) ? md->guardian_data->g->emblem_id:0;
if (md->special_state.ai && (msd = map->id2sd(md->master_id)) != NULL)
return msd->guild_emblem_id; //Alchemist's mobs [Skotlex]
}
@@ -6943,16 +6950,12 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_ASSNCROS:
if(sc->option&OPTION_MADOGEAR)
return 0;//Mado is immune to wind walk, cart boost, etc (others above) [Ind]
- case SC_INC_AGI:
+ case SC_INC_AGI:
if (sc->data[SC_QUAGMIRE])
- return 0;
+ return 0;
break;
case SC_CLOAKING:
- //Avoid cloaking with no wall and low skill level. [Skotlex]
- //Due to the cloaking card, we have to check the wall versus to known
- //skill level rather than the used one. [Skotlex]
- //if (sd && val1 < 3 && skill_check_cloaking(bl,NULL))
- if( sd && pc->checkskill(sd, AS_CLOAKING) < 3 && !skill->check_cloaking(bl,NULL) )
+ if (sd && !skill->can_cloak(sd))
return 0;
break;
case SC_MODECHANGE:
@@ -7147,7 +7150,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_ROKISWEIL:
case SC_FOGWALL:
case SC_FROSTMISTY:
- case SC_BURNING:
+ case SC_BURNING:
case SC_MARSHOFABYSS:
case SC_ADORAMUS:
case SC_NEEDLE_OF_PARALYZE:
@@ -7331,6 +7334,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER);
break;
case SC_FIGHTINGSPIRIT:
+ case SC_OVERED_BOOST:
status_change_end(bl, type, INVALID_TIMER); // Remove previous one.
break;
case SC_MARSHOFABYSS:
@@ -8102,22 +8106,25 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
}
break;
- case SC_COMBOATTACK: {
+ case SC_COMBOATTACK:
+ {
//val1: Skill ID
//val2: When given, target (for autotargetting skills)
//val3: When set, this combo time should NOT delay attack/movement
+ //val3: If set to 2 this combo will delay ONLY attack
//val3: TK: Last used kick
//val4: TK: Combo time
struct unit_data *ud = unit->bl2ud(bl);
- if (ud && !val3) {
+ if( ud && (!val3 || val3 == 2) ) {
tick += 300 * battle_config.combo_delay_rate/100;
ud->attackabletime = timer->gettick()+tick;
- unit->set_walkdelay(bl, timer->gettick(), tick, 1);
+ if( !val3 )
+ unit->set_walkdelay(bl, timer->gettick(), tick, 1);
}
val3 = 0;
val4 = tick;
- }
- break;
+ break;
+ }
case SC_EARTHSCROLL:
val2 = 11-val1; //Chance to consume: 11-skill_lv%
break;
@@ -8250,7 +8257,14 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
tick_time = 1000; // [GodLesZ] tick time
break;
case SC_JAILED:
- //Val1 is duration in minutes. Use INT_MAX to specify 'unlimited' time.
+ // val1 is duration in minutes. Use INT_MAX to specify 'unlimited' time.
+ // When first called:
+ // val2 Jail map_index
+ // val3 x
+ // val4 y
+ // When renewing status' information
+ // val3 Return map_index
+ // val4 return coordinates
tick = val1>0?1000:250;
if (sd)
{
@@ -8263,7 +8277,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
//2. Set restore point (val3 -> return map, val4 return coords
val3 = map_index;
val4 = pos;
- } else if (!val3 || val3 == sd->mapindex) { //Use save point.
+ } else if (!val3
+ || val3 == sd->mapindex
+ || !sd->sc.data[SC_JAILED] // If player is being jailed and is already in jail (issue: 8206)
+ ) { //Use save point.
val3 = sd->status.save_point.map;
val4 = (sd->status.save_point.x&0xFFFF)
|(sd->status.save_point.y<<16);
@@ -8827,16 +8844,34 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_STONE_SHIELD_OPTION:
val2 = 100; // Elemental modifier.
break;
+ case SC_TROPIC:
+ case SC_CHILLY_AIR:
+ case SC_WILD_STORM:
+ case SC_UPHEAVAL:
+ val2 += 10;
+ case SC_HEATER:
+ case SC_COOLER:
+ case SC_BLAST:
+ case SC_CURSED_SOIL:
+ val2 += 10;
+ case SC_PYROTECHNIC:
+ case SC_AQUAPLAY:
+ case SC_GUST:
+ case SC_PETROLOGY:
+ val2 += 5;
+ val3 += 9000;
case SC_CIRCLE_OF_FIRE:
+ case SC_WATER_SCREEN:
+ case SC_WIND_STEP:
+ case SC_SOLID_SKIN:
case SC_FIRE_CLOAK:
case SC_WATER_DROP:
- case SC_WATER_SCREEN:
case SC_WIND_CURTAIN:
- case SC_WIND_STEP:
case SC_STONE_SHIELD:
- case SC_SOLID_SKIN:
- val2 = 10;
- tick_time = 2000; // [GodLesZ] tick time
+ val2 += 5;
+ val3 += 1000;
+ val4 = tick;
+ tick_time = val3;
break;
case SC_WATER_BARRIER:
val2 = 40; // Increasement. Mdef1 ???
@@ -8979,9 +9014,15 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val1 = 1002; // default poring
break;
case SC_ALL_RIDING:
- unit->stop_attack(bl);
tick = -1;
break;
+ case SC_FLASHCOMBO:
+ /**
+ * val1 = <IN>skill_id
+ * val2 = <OUT>attack addition
+ **/
+ val2 = 20+(20*val1);
+ break;
default:
if( calc_flag == SCB_NONE && status->SkillChangeTable[type] == 0 && status->IconChangeTable[type] == 0 )
{ //Status change with no calc, no icon, and no skill associated...?
@@ -9168,6 +9209,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
// Cancel cast when get status [LuzZza]
if (battle_config.sc_castcancel&bl->type)
unit->skillcastcancel(bl, 0);
+ case SC_FALLENEMPIRE:
case SC_WHITEIMPRISON:
unit->stop_attack(bl);
case SC_STOP:
@@ -9201,6 +9243,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_WEIGHTOVER90:
case SC_CAMOUFLAGE:
case SC_SIREN:
+ case SC_ALL_RIDING:
unit->stop_attack(bl);
break;
case SC_SILENCE:
@@ -9404,7 +9447,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
}
//On Aegis, when turning on a status change, first goes the option packet, then the sc packet.
- if(opt_flag) {
+ if(opt_flag) {
clif->changeoption(bl);
if( sd && opt_flag&0x4 ) {
clif->changelook(bl,LOOK_BASE,vd->class_);
@@ -9471,7 +9514,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
{
struct unit_data *ud = unit->bl2ud(bl);
if( ud )
- ud->state.running = unit->run(bl);
+ ud->state.running = unit->run(bl, NULL, SC_RUN);
}
break;
case SC_CASH_BOSS_ALARM:
@@ -9490,7 +9533,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
{
struct unit_data *ud = unit->bl2ud(bl);
if( ud )
- ud->state.running = unit->wugdash(bl, sd);
+ ud->state.running = unit->run(bl, sd, SC_WUGDASH);
}
break;
case SC_COMBOATTACK:
@@ -10114,6 +10157,20 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
}
}
break;
+ case SC_OVERED_BOOST:
+ switch( bl->type ){
+ case BL_HOM:
+ {
+ struct homun_data *hd = BL_CAST(BL_HOM, bl);
+ if( hd )
+ hd->homunculus.hunger = max(1, hd->homunculus.hunger - 50);
+ }
+ break;
+ case BL_PC:
+ status_zap(bl, 0, status_get_max_sp(bl) / 2);
+ break;
+ }
+ break;
}
opt_flag = 1;
@@ -11108,22 +11165,31 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
}
break;
+ case SC_TROPIC:
+ case SC_CHILLY_AIR:
+ case SC_WILD_STORM:
+ case SC_UPHEAVAL:
+ case SC_HEATER:
+ case SC_COOLER:
+ case SC_BLAST:
+ case SC_CURSED_SOIL:
+ case SC_PYROTECHNIC:
+ case SC_AQUAPLAY:
+ case SC_GUST:
+ case SC_PETROLOGY:
case SC_CIRCLE_OF_FIRE:
+ case SC_WATER_SCREEN:
+ case SC_WIND_STEP:
+ case SC_SOLID_SKIN:
case SC_FIRE_CLOAK:
case SC_WATER_DROP:
- case SC_WATER_SCREEN:
case SC_WIND_CURTAIN:
- case SC_WIND_STEP:
case SC_STONE_SHIELD:
- case SC_SOLID_SKIN:
- if( !status->charge(bl,0,sce->val2) ){
- struct block_list *s_bl = battle->get_master(bl);
- if( s_bl )
- status_change_end(s_bl,type+1,INVALID_TIMER);
- status_change_end(bl,type,INVALID_TIMER);
- break;
- }
- sc_timer_next(2000 + tick, status->change_timer, bl->id, data);
+ if(status->charge(bl, 0, sce->val2) && (sce->val4==-1 || (sce->val4-=sce->val3)>=0))
+ sc_timer_next(sce->val3 + tick, status->change_timer, bl->id, data);
+ else
+ if (bl->type == BL_ELEM)
+ elemental->change_mode(BL_CAST(BL_ELEM,bl),MAX_ELESKILLTREE);
return 0;
case SC_STOMACHACHE:
@@ -11307,88 +11373,149 @@ int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int fl
#endif
}
-#define GETRANDMATK(st) do {\
- if( (st)->matk_max > (st)->matk_min ) \
- return (st)->matk_min + rnd()%((st)->matk_max - (st)->matk_min); \
- else \
- return (st)->matk_min; \
- } while(0)
+/**
+ * Gets a random matk value depending on min matk and max matk
+ **/
+unsigned short status_get_rand_matk( unsigned short matk_max, unsigned short matk_min ) {
+ if( matk_max > matk_min )
+ return matk_min + rnd()%(matk_max - matk_min);
+ else
+ return matk_min;
+}
-/*==========================================
-* flag [malufett]
-* 0 - update matk values
-* 1 - get matk w/o SC bonuses
-* 2 - get modified matk
-* 3 - get matk w/o eatk & SC bonuses
-*------------------------------------------*/
-int status_get_matk(struct block_list *bl, int flag) {
+/**
+ * Get bl's matk_max and matk_min values depending on flag
+ * @param flag
+ * 0 - Get MATK
+ * 1 - Get MATK w/o SC bonuses
+ * 3 - Get MATK w/o EATK & SC bonuses
+ **/
+void status_get_matk_sub( struct block_list *bl, int flag, unsigned short *matk_max, unsigned short *matk_min ) {
struct status_data *st;
struct status_change *sc;
struct map_session_data *sd;
if( bl == NULL )
- return 1;
+ return;
+
+ if( flag != 0 && flag != 1 && flag != 3 ) {
+ ShowError("status_get_matk_sub: Unknown flag %d!\n", flag);
+ return;
+ }
st = status->get_status_data(bl);
sc = status->get_sc(bl);
sd = BL_CAST(BL_PC, bl);
- if( flag == 2 ) // just get matk
- GETRANDMATK(st);
-
#ifdef RENEWAL
/**
* RE MATK Formula (from irowiki:http://irowiki.org/wiki/MATK)
* MATK = (sMATK + wMATK + eMATK) * Multiplicative Modifiers
**/
- st->matk_min = status->base_matk(st, status->get_lv(bl));
+ *matk_min = status->base_matk(st, status->get_lv(bl));
// Any +MATK you get from skills and cards, including cards in weapon, is added here.
if( sd && sd->bonus.ematk > 0 && flag != 3 )
- st->matk_min += sd->bonus.ematk;
+ *matk_min += sd->bonus.ematk;
if( flag != 3 )
- st->matk_min = status->calc_ematk(bl, sc, st->matk_min);
+ *matk_min = status->calc_ematk(bl, sc, *matk_min);
- st->matk_max = st->matk_min;
+ *matk_max = *matk_min;
//This is the only portion in MATK that varies depending on the weapon level and refinement rate.
if( bl->type&BL_PC && (st->rhw.matk + st->lhw.matk) > 0 ) {
int wMatk = st->rhw.matk + st->lhw.matk; // Left and right matk stacks
int variance = wMatk * st->rhw.wlv / 10; // Only use right hand weapon level
- st->matk_min += wMatk - variance;
- st->matk_max += wMatk + variance;
+ *matk_min += wMatk - variance;
+ *matk_max += wMatk + variance;
} else if( bl->type&BL_MOB ) {
- st->matk_min = st->matk_max = status_get_int(bl) + status->get_lv(bl);
- st->matk_min += 70 * ((TBL_MOB*)bl)->status.rhw.atk2 / 100;
- st->matk_max += 130 * ((TBL_MOB*)bl)->status.rhw.atk2 / 100;
+ *matk_min = *matk_max = status_get_int(bl) + status->get_lv(bl);
+ *matk_min += 70 * ((TBL_MOB*)bl)->status.rhw.atk2 / 100;
+ *matk_max += 130 * ((TBL_MOB*)bl)->status.rhw.atk2 / 100;
}
#else // not RENEWAL
- st->matk_min = status_base_matk_min(st) + (sd?sd->bonus.ematk:0);
- st->matk_max = status_base_matk_max(st) + (sd?sd->bonus.ematk:0);
+ *matk_min = status_base_matk_min(st) + (sd?sd->bonus.ematk:0);
+ *matk_max = status_base_matk_max(st) + (sd?sd->bonus.ematk:0);
#endif
+
if (sd && sd->matk_rate != 100) {
- st->matk_max = st->matk_max * sd->matk_rate/100;
- st->matk_min = st->matk_min * sd->matk_rate/100;
+ *matk_max = (*matk_max) * sd->matk_rate/100;
+ *matk_min = (*matk_min) * sd->matk_rate/100;
}
if ((bl->type&BL_HOM && battle_config.hom_setting&0x20) //Hom Min Matk is always the same as Max Matk
|| (sc && sc->data[SC_RECOGNIZEDSPELL]))
- st->matk_min = st->matk_max;
+ *matk_min = *matk_max;
#ifdef RENEWAL
- if( sd && sd->right_weapon.overrefine > 0){
- st->matk_min++;
- st->matk_max += sd->right_weapon.overrefine - 1;
+ if( sd && sd->right_weapon.overrefine > 0 ) {
+ (*matk_min)++;
+ *matk_max += sd->right_weapon.overrefine - 1;
}
#endif
+ return;
+}
- if( flag ) // get unmodified from sc matk
- GETRANDMATK(st);
+/**
+ * Get bl's matk value depending on flag
+ * @param flag [malufett]
+ * 1 - Get MATK w/o SC bonuses
+ * 2 - Get modified MATK
+ * 3 - Get MATK w/o eATK & SC bonuses
+ * @retval 1 failure
+ * @retval MATK success
+ *
+ * Shouldn't change _any_ value! [Panikon]
+ **/
+int status_get_matk( struct block_list *bl, int flag ) {
+ struct status_data *st;
+ unsigned short matk_max, matk_min;
- st->matk_min = status->calc_matk(bl, sc, st->matk_min, true);
- st->matk_max = status->calc_matk(bl, sc, st->matk_max, true);
+ if( bl == NULL )
+ return 1;
- return 0;
+ if( flag < 1 || flag > 3 ) {
+ ShowError("status_get_matk: Unknown flag %d!\n", flag);
+ return 1;
+ }
+
+ if( (st = status->get_status_data(bl)) == NULL )
+ return 0;
+
+ // Just get matk
+ if( flag == 2 )
+ return status_get_rand_matk(st->matk_max, st->matk_min);
+
+ status_get_matk_sub( bl, flag, &matk_max, &matk_min );
+
+ // Get unmodified from sc matk
+ return status_get_rand_matk(matk_max, matk_min);
+}
+
+/**
+ * Updates bl's MATK values
+ **/
+void status_update_matk( struct block_list *bl ) {
+ struct status_data *st;
+ struct status_change *sc;
+ unsigned short matk_max, matk_min;
+
+ if( bl == NULL )
+ return;
+
+ if( (st = status->get_status_data(bl)) == NULL )
+ return;
+
+ if( (sc = status->get_sc(bl)) == NULL )
+ return;
+
+ status_get_matk_sub( bl, 0, &matk_max, &matk_min );
+
+ // Update matk
+ st->matk_min = status->calc_matk(bl, sc, matk_min, true);
+ st->matk_max = status->calc_matk(bl, sc, matk_max, true);
+
+ return;
}
/*==========================================
@@ -11947,7 +12074,7 @@ void do_final_status(void) {
}
/*=====================================
-* Default Functions : status.h
+* Default Functions : status.h
* Generated by HerculesInterfaceMaker
* created by Susu
*-------------------------------------*/
@@ -12062,6 +12189,7 @@ void status_defaults(void) {
status->get_total_def = status_get_total_def;
status->get_matk = status_get_matk;
+ status->update_matk = status_update_matk;
status->readdb = status_readdb;
status->init = do_init_status;