diff options
Diffstat (limited to 'src/map/status.c')
-rw-r--r-- | src/map/status.c | 4551 |
1 files changed, 2451 insertions, 2100 deletions
diff --git a/src/map/status.c b/src/map/status.c index a8771c0a5..9a274c080 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -2,8 +2,8 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team - * Copyright (C) Athena Dev Teams + * Copyright (C) 2012-2020 Hercules Dev Team + * Copyright (C) Athena Dev Teams * * Hercules is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,6 +25,7 @@ #include "map/battle.h" #include "map/chrif.h" +#include "map/clan.h" #include "map/clif.h" #include "map/elemental.h" #include "map/guild.h" @@ -37,6 +38,7 @@ #include "map/path.h" #include "map/pc.h" #include "map/pet.h" +#include "map/refine.h" #include "map/script.h" #include "map/skill.h" #include "map/skill.h" @@ -60,17 +62,18 @@ #include <string.h> #include <time.h> -struct status_interface status_s; -struct s_status_dbs statusdbs; +static struct status_interface status_s; +static struct s_status_dbs statusdbs; struct status_interface *status; /** -* Returns the status change associated with a skill. -* @param skill The skill to look up -* @return The status registered for this skill -**/ -sc_type status_skill2sc(int skill_id) { + * Returns the status change associated with a skill. + * @param skill The skill to look up + * @return The status registered for this skill + */ +static sc_type status_skill2sc(int skill_id) +{ int idx; if( (idx = skill->get_index(skill_id)) == 0 ) { ShowError("status_skill2sc: Unsupported skill id %d\n", skill_id); @@ -80,12 +83,12 @@ sc_type status_skill2sc(int skill_id) { } /** -* Returns the FIRST skill (in order of definition in initChangeTables) to use a given status change. -* Utilized for various duration lookups. Use with caution! -* @param sc The status to look up -* @return A skill associated with the status -**/ -int status_sc2skill(sc_type sc) + * Returns the FIRST skill (in order of definition in initChangeTables) to use a given status change. + * Utilized for various duration lookups. Use with caution! + * @param sc The status to look up + * @return A skill associated with the status + */ +static int status_sc2skill(sc_type sc) { if( sc < 0 || sc >= SC_MAX ) { ShowError("status_sc2skill: Unsupported status change id %d\n", sc); @@ -96,11 +99,11 @@ int status_sc2skill(sc_type sc) } /** -* Returns the status calculation flag associated with a given status change. -* @param sc The status to look up -* @return The scb_flag registered for this status (see enum scb_flag) -**/ -unsigned int status_sc2scb_flag(sc_type sc) + * Returns the status calculation flag associated with a given status change. + * @param sc The status to look up + * @return The scb_flag registered for this status (see enum scb_flag) + */ +static unsigned int status_sc2scb_flag(sc_type sc) { if( sc < 0 || sc >= SC_MAX ) { ShowError("status_sc2scb_flag: Unsupported status change id %d\n", sc); @@ -111,21 +114,29 @@ unsigned int status_sc2scb_flag(sc_type sc) } /** -* Returns the bl types which require a status change packet to be sent for a given client status identifier. -* @param type The client-side status identifier to look up (see enum si_type) -* @return The bl types relevant to the type (see enum bl_type) -**/ -int status_type2relevant_bl_types(int type) -{ - if( type < 0 || type >= SI_MAX ) { - ShowError("status_type2relevant_bl_types: Unsupported type %d\n", type); + * Returns the bl types which require a status change packet to be sent for a given client status identifier. + * @param type status identifier to look up (see enum sc_type) + * @return The bl types relevant to the type (see enum bl_type) + */ +static int status_get_sc_relevant_bl_types(enum sc_type type) +{ + if (type < 0 || type >= SC_MAX) { + ShowError("status_get_sc_relevant_bl_types: Unsupported type %d\n", type); return BL_NUL; } - return status->dbs->RelevantBLTypes[type]; + return status->dbs->IconChangeTable[type].relevant_bl_types; } -static void set_sc(uint16 skill_id, sc_type sc, int icon, unsigned int flag) { +static int status_get_sc_icon(enum sc_type type) +{ + Assert_retr(SI_BLANK, type >= SC_NONE && type < SC_MAX); + + return status->dbs->IconChangeTable[type].id; +} + +static void status_set_sc(uint16 skill_id, sc_type sc, unsigned int flag) +{ uint16 idx; if( (idx = skill->get_index(skill_id)) == 0 ) { ShowError("set_sc: Unsupported skill id %d\n", skill_id); @@ -138,112 +149,110 @@ static void set_sc(uint16 skill_id, sc_type sc, int icon, unsigned int flag) { if( status->dbs->SkillChangeTable[sc] == 0 ) status->dbs->SkillChangeTable[sc] = skill_id; - if( status->dbs->IconChangeTable[sc] == SI_BLANK ) - status->dbs->IconChangeTable[sc] = icon; status->dbs->ChangeFlagTable[sc] |= flag; if( status->dbs->Skill2SCTable[idx] == SC_NONE ) status->dbs->Skill2SCTable[idx] = sc; } -void initChangeTables(void) { -#define add_sc(skill,sc) set_sc((skill),(sc),SI_BLANK,SCB_NONE) +static void initChangeTables(void) +{ +#define add_sc(skill,sc) status->set_sc((skill),(sc),SCB_NONE) // indicates that the status displays a visual effect for the affected unit, and should be sent to the client for all supported units -#define set_sc_with_vfx(skill, sc, icon, flag) do { set_sc((skill), (sc), (icon), (flag)); if((icon) < SI_MAX) status->dbs->RelevantBLTypes[(icon)] |= BL_SCEFFECT; } while(0) +#define set_sc_with_vfx(skill, sc, flag) do { status->set_sc((skill), (sc), (flag)); status->dbs->IconChangeTable[sc].relevant_bl_types |= BL_SCEFFECT; } while(0) int i; - for (i = 0; i < SC_MAX; i++) - status->dbs->IconChangeTable[i] = SI_BLANK; - - for (i = 0; i < MAX_SKILL; i++) + for (i = 0; i < MAX_SKILL_DB; i++) status->dbs->Skill2SCTable[i] = SC_NONE; - for (i = 0; i < SI_MAX; i++) - status->dbs->RelevantBLTypes[i] = BL_PC; + for (i = 0; i < SC_MAX; i++) { + status->dbs->IconChangeTable[i].id = SI_BLANK; + status->dbs->IconChangeTable[i].relevant_bl_types = BL_PC; + } memset(status->dbs->SkillChangeTable, 0, sizeof(status->dbs->SkillChangeTable)); memset(status->dbs->ChangeFlagTable, 0, sizeof(status->dbs->ChangeFlagTable)); memset(status->dbs->DisplayType, 0, sizeof(status->dbs->DisplayType)); //First we define the skill for common ailments. These are used in skill_additional_effect through sc cards. [Skotlex] - set_sc( NPC_PETRIFYATTACK , SC_STONE , SI_BLANK , SCB_DEF_ELE|SCB_DEF|SCB_MDEF ); - set_sc( NPC_WIDEFREEZE , SC_FREEZE , SI_BLANK , SCB_DEF_ELE|SCB_DEF|SCB_MDEF ); - set_sc( NPC_STUNATTACK , SC_STUN , SI_BLANK , SCB_NONE ); - set_sc( NPC_SLEEPATTACK , SC_SLEEP , SI_BLANK , SCB_NONE ); - set_sc( NPC_POISON , SC_POISON , SI_BLANK , SCB_DEF2|SCB_REGEN ); - set_sc( NPC_CURSEATTACK , SC_CURSE , SI_BLANK , SCB_LUK|SCB_BATK|SCB_WATK|SCB_SPEED ); - set_sc( NPC_SILENCEATTACK , SC_SILENCE , SI_BLANK , SCB_NONE ); - set_sc( NPC_WIDECONFUSE , SC_CONFUSION , SI_BLANK , SCB_NONE ); - set_sc( NPC_BLINDATTACK , SC_BLIND , SI_BLANK , SCB_HIT|SCB_FLEE ); - set_sc( NPC_BLEEDING , SC_BLOODING , SI_BLOODING , SCB_REGEN ); - set_sc( NPC_POISON , SC_DPOISON , SI_BLANK , SCB_DEF2|SCB_REGEN ); + status->set_sc( NPC_PETRIFYATTACK , SC_STONE , SCB_DEF_ELE|SCB_DEF|SCB_MDEF ); + status->set_sc( NPC_WIDEFREEZE , SC_FREEZE , SCB_DEF_ELE|SCB_DEF|SCB_MDEF ); + status->set_sc( NPC_STUNATTACK , SC_STUN , SCB_NONE ); + status->set_sc( NPC_SLEEPATTACK , SC_SLEEP , SCB_NONE ); + status->set_sc( NPC_POISON , SC_POISON , SCB_DEF2|SCB_REGEN ); + status->set_sc( NPC_CURSEATTACK , SC_CURSE , SCB_LUK|SCB_BATK|SCB_WATK|SCB_SPEED ); + status->set_sc( NPC_SILENCEATTACK , SC_SILENCE , SCB_NONE ); + status->set_sc( NPC_WIDECONFUSE , SC_CONFUSION , SCB_NONE ); + status->set_sc( NPC_BLINDATTACK , SC_BLIND , SCB_HIT|SCB_FLEE ); + status->set_sc( NPC_BLEEDING , SC_BLOODING , SCB_REGEN ); + status->set_sc( NPC_POISON , SC_DPOISON , SCB_DEF2|SCB_REGEN ); //The main status definitions add_sc( SM_BASH , SC_STUN ); - set_sc( SM_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK ); + status->set_sc( SM_PROVOKE , SC_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK ); add_sc( SM_MAGNUM , SC_SUB_WEAPONPROPERTY ); - set_sc( SM_ENDURE , SC_ENDURE , SI_ENDURE , SCB_MDEF|SCB_DSPD ); + status->set_sc( SM_ENDURE , SC_ENDURE , SCB_MDEF|SCB_DSPD ); add_sc( MG_SIGHT , SC_SIGHT ); add_sc( MG_SAFETYWALL , SC_SAFETYWALL ); add_sc( MG_FROSTDIVER , SC_FREEZE ); add_sc( MG_STONECURSE , SC_STONE ); add_sc( AL_RUWACH , SC_RUWACH ); add_sc( AL_PNEUMA , SC_PNEUMA ); - set_sc( AL_INCAGI , SC_INC_AGI , SI_INC_AGI , SCB_AGI|SCB_SPEED ); - set_sc( AL_DECAGI , SC_DEC_AGI , SI_DEC_AGI , SCB_AGI|SCB_SPEED ); - set_sc( AL_CRUCIS , SC_CRUCIS , SI_CRUCIS , SCB_DEF ); - set_sc( AL_ANGELUS , SC_ANGELUS , SI_ANGELUS , SCB_DEF2 ); - set_sc( AL_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX ); - set_sc( AC_CONCENTRATION , SC_CONCENTRATION , SI_CONCENTRATION , SCB_AGI|SCB_DEX ); - set_sc( TF_HIDING , SC_HIDING , SI_HIDING , SCB_SPEED ); + status->set_sc( AL_INCAGI , SC_INC_AGI , SCB_AGI|SCB_SPEED ); + status->set_sc( AL_DECAGI , SC_DEC_AGI , SCB_AGI|SCB_SPEED ); + status->set_sc( AL_CRUCIS , SC_CRUCIS , SCB_DEF ); + status->set_sc( AL_ANGELUS , SC_ANGELUS , SCB_DEF2 ); + status->set_sc( AL_BLESSING , SC_BLESSING , SCB_STR|SCB_INT|SCB_DEX ); + status->set_sc( AC_CONCENTRATION , SC_CONCENTRATION , SCB_AGI|SCB_DEX ); + status->set_sc( TF_HIDING , SC_HIDING , SCB_SPEED ); add_sc( TF_POISON , SC_POISON ); - set_sc( KN_TWOHANDQUICKEN , SC_TWOHANDQUICKEN , SI_TWOHANDQUICKEN , SCB_ASPD ); + status->set_sc( KN_TWOHANDQUICKEN , SC_TWOHANDQUICKEN , SCB_ASPD ); add_sc( KN_AUTOCOUNTER , SC_AUTOCOUNTER ); - set_sc( PR_IMPOSITIO , SC_IMPOSITIO , SI_IMPOSITIO , + status->set_sc( PR_IMPOSITIO , SC_IMPOSITIO , #ifdef RENEWAL SCB_NONE ); #else SCB_WATK ); #endif - set_sc( PR_SUFFRAGIUM , SC_SUFFRAGIUM , SI_SUFFRAGIUM , SCB_NONE ); - set_sc( PR_ASPERSIO , SC_ASPERSIO , SI_ASPERSIO , SCB_ATK_ELE ); - set_sc( PR_BENEDICTIO , SC_BENEDICTIO , SI_BENEDICTIO , SCB_DEF_ELE ); - set_sc( PR_SLOWPOISON , SC_SLOWPOISON , SI_SLOWPOISON , SCB_REGEN ); - set_sc( PR_KYRIE , SC_KYRIE , SI_KYRIE , SCB_NONE ); - set_sc( PR_MAGNIFICAT , SC_MAGNIFICAT , SI_MAGNIFICAT , SCB_REGEN ); - set_sc( PR_GLORIA , SC_GLORIA , SI_GLORIA , SCB_LUK ); + status->set_sc( PR_SUFFRAGIUM , SC_SUFFRAGIUM , SCB_NONE ); + status->set_sc( PR_ASPERSIO , SC_ASPERSIO , SCB_ATK_ELE ); + status->set_sc( PR_BENEDICTIO , SC_BENEDICTIO , SCB_DEF_ELE ); + status->set_sc( PR_SLOWPOISON , SC_SLOWPOISON , SCB_REGEN ); + status->set_sc( PR_KYRIE , SC_KYRIE , SCB_NONE ); + status->set_sc( PR_MAGNIFICAT , SC_MAGNIFICAT , SCB_REGEN ); + status->set_sc( PR_GLORIA , SC_GLORIA , SCB_LUK ); add_sc( PR_LEXDIVINA , SC_SILENCE ); - set_sc( PR_LEXAETERNA , SC_LEXAETERNA , SI_LEXAETERNA , SCB_NONE ); + status->set_sc( PR_LEXAETERNA , SC_LEXAETERNA , SCB_NONE ); add_sc( WZ_METEOR , SC_STUN ); add_sc( WZ_VERMILION , SC_BLIND ); add_sc( WZ_FROSTNOVA , SC_FREEZE ); add_sc( WZ_STORMGUST , SC_FREEZE ); - set_sc( WZ_QUAGMIRE , SC_QUAGMIRE , SI_QUAGMIRE , SCB_AGI|SCB_DEX|SCB_ASPD|SCB_SPEED ); - set_sc( BS_ADRENALINE , SC_ADRENALINE , SI_ADRENALINE , SCB_ASPD ); - 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 ); + status->set_sc( WZ_QUAGMIRE , SC_QUAGMIRE , SCB_AGI|SCB_DEX|SCB_ASPD|SCB_SPEED ); + status->set_sc( BS_ADRENALINE , SC_ADRENALINE , SCB_ASPD ); + status->set_sc( BS_WEAPONPERFECT , SC_WEAPONPERFECT , SCB_NONE ); + status->set_sc( BS_OVERTHRUST , SC_OVERTHRUST , SCB_NONE ); + status->set_sc( BS_MAXIMIZE , SC_MAXIMIZEPOWER , SCB_REGEN ); add_sc( HT_LANDMINE , SC_STUN ); - set_sc( HT_ANKLESNARE , SC_ANKLESNARE , SI_ANKLESNARE , SCB_NONE ); + status->set_sc( HT_ANKLESNARE , SC_ANKLESNARE , SCB_NONE ); add_sc( HT_SANDMAN , SC_SLEEP ); add_sc( HT_FLASHER , SC_BLIND ); add_sc( HT_FREEZINGTRAP , SC_FREEZE ); - set_sc( AS_CLOAKING , SC_CLOAKING , SI_CLOAKING , SCB_CRI|SCB_SPEED ); + status->set_sc( AS_CLOAKING , SC_CLOAKING , SCB_CRI|SCB_SPEED ); add_sc( AS_SONICBLOW , SC_STUN ); - set_sc( AS_ENCHANTPOISON , SC_ENCHANTPOISON , SI_ENCHANTPOISON, SCB_ATK_ELE ); - set_sc( AS_POISONREACT , SC_POISONREACT , SI_POISONREACT , SCB_NONE ); + status->set_sc( AS_ENCHANTPOISON , SC_ENCHANTPOISON , SCB_ATK_ELE ); + status->set_sc( AS_POISONREACT , SC_POISONREACT , SCB_NONE ); add_sc( AS_VENOMDUST , SC_POISON ); add_sc( AS_SPLASHER , SC_SPLASHER ); - set_sc( NV_TRICKDEAD , SC_TRICKDEAD , SI_TRICKDEAD , SCB_REGEN ); - set_sc( SM_AUTOBERSERK , SC_AUTOBERSERK , SI_AUTOBERSERK , SCB_NONE ); + status->set_sc( NV_TRICKDEAD , SC_TRICKDEAD , SCB_REGEN ); + status->set_sc( SM_AUTOBERSERK , SC_AUTOBERSERK , SCB_NONE ); add_sc( TF_SPRINKLESAND , SC_BLIND ); add_sc( TF_THROWSTONE , SC_STUN ); - set_sc( MC_LOUD , SC_SHOUT , SI_SHOUT , SCB_STR ); - set_sc( MG_ENERGYCOAT , SC_ENERGYCOAT , SI_ENERGYCOAT , SCB_NONE ); - set_sc( NPC_EMOTION , SC_MODECHANGE , SI_BLANK , SCB_MODE ); + status->set_sc( MC_LOUD , SC_SHOUT , SCB_STR ); + status->set_sc( MG_ENERGYCOAT , SC_ENERGYCOAT , SCB_NONE ); + status->set_sc( NPC_EMOTION , SC_MODECHANGE , SCB_MODE ); add_sc( NPC_EMOTION_ON , SC_MODECHANGE ); - set_sc( NPC_ATTRICHANGE , SC_ARMOR_PROPERTY , SI_ARMOR_PROPERTY , SCB_DEF_ELE ); + status->set_sc( NPC_ATTRICHANGE , SC_ARMOR_PROPERTY , SCB_DEF_ELE ); add_sc( NPC_CHANGEWATER , SC_ARMOR_PROPERTY ); add_sc( NPC_CHANGEGROUND , SC_ARMOR_PROPERTY ); add_sc( NPC_CHANGEFIRE , SC_ARMOR_PROPERTY ); @@ -260,184 +269,184 @@ void initChangeTables(void) { add_sc( NPC_CURSEATTACK , SC_CURSE ); add_sc( NPC_SLEEPATTACK , SC_SLEEP ); add_sc( NPC_MAGICALATTACK , SC_MAGICALATTACK ); - set_sc( NPC_KEEPING , SC_KEEPING , SI_BLANK , SCB_DEF ); + status->set_sc( NPC_KEEPING , SC_KEEPING , SCB_DEF ); add_sc( NPC_DARKBLESSING , SC_COMA ); - set_sc( NPC_BARRIER , SC_BARRIER , SI_BLANK , SCB_MDEF|SCB_DEF ); + status->set_sc( NPC_BARRIER , SC_BARRIER , SCB_MDEF|SCB_DEF ); add_sc( NPC_DEFENDER , SC_ARMOR ); add_sc( NPC_LICK , SC_STUN ); - set_sc( NPC_HALLUCINATION , SC_ILLUSION , SI_ILLUSION , SCB_NONE ); + status->set_sc( NPC_HALLUCINATION , SC_ILLUSION , SCB_NONE ); add_sc( NPC_REBIRTH , SC_REBIRTH ); add_sc( RG_RAID , SC_STUN ); #ifdef RENEWAL add_sc( RG_RAID , SC_RAID ); add_sc( RG_BACKSTAP , SC_STUN ); #endif - set_sc( RG_STRIPWEAPON , SC_NOEQUIPWEAPON , SI_NOEQUIPWEAPON , SCB_WATK ); - set_sc( RG_STRIPSHIELD , SC_NOEQUIPSHIELD , SI_NOEQUIPSHIELD , SCB_DEF ); - set_sc( RG_STRIPARMOR , SC_NOEQUIPARMOR , SI_NOEQUIPARMOR , SCB_VIT ); - set_sc( RG_STRIPHELM , SC_NOEQUIPHELM , SI_NOEQUIPHELM , SCB_INT ); + status->set_sc( RG_STRIPWEAPON , SC_NOEQUIPWEAPON , SCB_WATK ); + status->set_sc( RG_STRIPSHIELD , SC_NOEQUIPSHIELD , SCB_DEF ); + status->set_sc( RG_STRIPARMOR , SC_NOEQUIPARMOR , SCB_VIT ); + status->set_sc( RG_STRIPHELM , SC_NOEQUIPHELM , SCB_INT ); add_sc( AM_ACIDTERROR , SC_BLOODING ); - set_sc( AM_CP_WEAPON , SC_PROTECTWEAPON , SI_PROTECTWEAPON , SCB_NONE ); - set_sc( AM_CP_SHIELD , SC_PROTECTSHIELD , SI_PROTECTSHIELD , SCB_NONE ); - set_sc( AM_CP_ARMOR , SC_PROTECTARMOR , SI_PROTECTARMOR , SCB_NONE ); - set_sc( AM_CP_HELM , SC_PROTECTHELM , SI_PROTECTHELM , SCB_NONE ); - set_sc( CR_AUTOGUARD , SC_AUTOGUARD , SI_AUTOGUARD , SCB_NONE ); + status->set_sc( AM_CP_WEAPON , SC_PROTECTWEAPON , SCB_NONE ); + status->set_sc( AM_CP_SHIELD , SC_PROTECTSHIELD , SCB_NONE ); + status->set_sc( AM_CP_ARMOR , SC_PROTECTARMOR , SCB_NONE ); + status->set_sc( AM_CP_HELM , SC_PROTECTHELM , SCB_NONE ); + status->set_sc( CR_AUTOGUARD , SC_AUTOGUARD , SCB_NONE ); add_sc( CR_SHIELDCHARGE , SC_STUN ); - set_sc( CR_REFLECTSHIELD , SC_REFLECTSHIELD , SI_REFLECTSHIELD , SCB_NONE ); + status->set_sc( CR_REFLECTSHIELD , SC_REFLECTSHIELD , SCB_NONE ); add_sc( CR_HOLYCROSS , SC_BLIND ); add_sc( CR_GRANDCROSS , SC_BLIND ); add_sc( CR_DEVOTION , SC_DEVOTION ); - set_sc( CR_PROVIDENCE , SC_PROVIDENCE , SI_PROVIDENCE , SCB_ALL ); - set_sc( CR_DEFENDER , SC_DEFENDER , SI_DEFENDER , SCB_SPEED|SCB_ASPD ); - set_sc( CR_SPEARQUICKEN , SC_SPEARQUICKEN , SI_SPEARQUICKEN , SCB_ASPD|SCB_CRI|SCB_FLEE ); - set_sc( MO_STEELBODY , SC_STEELBODY , SI_STEELBODY , SCB_DEF|SCB_MDEF|SCB_ASPD|SCB_SPEED ); + status->set_sc( CR_PROVIDENCE , SC_PROVIDENCE , SCB_ALL ); + status->set_sc( CR_DEFENDER , SC_DEFENDER , SCB_SPEED|SCB_ASPD ); + status->set_sc( CR_SPEARQUICKEN , SC_SPEARQUICKEN , SCB_ASPD|SCB_CRI|SCB_FLEE ); + status->set_sc( MO_STEELBODY , SC_STEELBODY , SCB_DEF|SCB_MDEF|SCB_ASPD|SCB_SPEED ); add_sc( MO_BLADESTOP , SC_BLADESTOP_WAIT ); add_sc( MO_BLADESTOP , SC_BLADESTOP ); - set_sc( MO_EXPLOSIONSPIRITS , SC_EXPLOSIONSPIRITS, SI_EXPLOSIONSPIRITS, SCB_CRI|SCB_REGEN ); - set_sc( MO_EXTREMITYFIST , SC_EXTREMITYFIST , SI_BLANK , SCB_REGEN ); + status->set_sc( MO_EXPLOSIONSPIRITS , SC_EXPLOSIONSPIRITS, SCB_CRI|SCB_REGEN ); + status->set_sc( MO_EXTREMITYFIST , SC_EXTREMITYFIST , SCB_REGEN ); #ifdef RENEWAL - set_sc( MO_EXTREMITYFIST , SC_EXTREMITYFIST2 , SI_EXTREMITYFIST , SCB_NONE ); + status->set_sc( MO_EXTREMITYFIST , SC_EXTREMITYFIST2 , SCB_NONE ); #endif add_sc( SA_MAGICROD , SC_MAGICROD ); - set_sc( SA_AUTOSPELL , SC_AUTOSPELL , SI_AUTOSPELL , SCB_NONE ); - set_sc( SA_FLAMELAUNCHER , SC_PROPERTYFIRE , SI_PROPERTYFIRE , SCB_ATK_ELE ); - set_sc( SA_FROSTWEAPON , SC_PROPERTYWATER , SI_PROPERTYWATER , SCB_ATK_ELE ); - set_sc( SA_LIGHTNINGLOADER , SC_PROPERTYWIND , SI_PROPERTYWIND , SCB_ATK_ELE ); - set_sc( SA_SEISMICWEAPON , SC_PROPERTYGROUND , SI_PROPERTYGROUND , SCB_ATK_ELE ); - set_sc( SA_VOLCANO , SC_VOLCANO , SI_GROUNDMAGIC , SCB_WATK ); - set_sc( SA_DELUGE , SC_DELUGE , SI_GROUNDMAGIC , SCB_MAXHP ); - set_sc( SA_VIOLENTGALE , SC_VIOLENTGALE , SI_GROUNDMAGIC , SCB_FLEE ); + status->set_sc( SA_AUTOSPELL , SC_AUTOSPELL , SCB_NONE ); + status->set_sc( SA_FLAMELAUNCHER , SC_PROPERTYFIRE , SCB_ATK_ELE ); + status->set_sc( SA_FROSTWEAPON , SC_PROPERTYWATER , SCB_ATK_ELE ); + status->set_sc( SA_LIGHTNINGLOADER , SC_PROPERTYWIND , SCB_ATK_ELE ); + status->set_sc( SA_SEISMICWEAPON , SC_PROPERTYGROUND , SCB_ATK_ELE ); + status->set_sc( SA_VOLCANO , SC_VOLCANO , SCB_WATK ); + status->set_sc( SA_DELUGE , SC_DELUGE , SCB_MAXHP ); + status->set_sc( SA_VIOLENTGALE , SC_VIOLENTGALE , SCB_FLEE ); add_sc( SA_REVERSEORCISH , SC_ORCISH ); add_sc( SA_COMA , SC_COMA ); - set_sc( BD_ENCORE , SC_DANCING , SI_BLANK , SCB_SPEED|SCB_REGEN ); + status->set_sc( BD_ENCORE , SC_DANCING , SCB_SPEED|SCB_REGEN ); add_sc( BD_RICHMANKIM , SC_RICHMANKIM ); - set_sc( BD_ETERNALCHAOS , SC_ETERNALCHAOS , SI_BLANK , SCB_DEF2 ); - set_sc( BD_DRUMBATTLEFIELD , SC_DRUMBATTLE , SI_BLANK , SCB_WATK|SCB_DEF ); - set_sc( BD_RINGNIBELUNGEN , SC_NIBELUNGEN , SI_BLANK , SCB_WATK ); + status->set_sc( BD_ETERNALCHAOS , SC_ETERNALCHAOS , SCB_DEF2 ); + status->set_sc( BD_DRUMBATTLEFIELD , SC_DRUMBATTLE , SCB_WATK|SCB_DEF ); + status->set_sc( BD_RINGNIBELUNGEN , SC_NIBELUNGEN , SCB_WATK ); add_sc( BD_ROKISWEIL , SC_ROKISWEIL ); add_sc( BD_INTOABYSS , SC_INTOABYSS ); - set_sc( BD_SIEGFRIED , SC_SIEGFRIED , SI_BLANK , SCB_ALL ); + status->set_sc( BD_SIEGFRIED , SC_SIEGFRIED , SCB_ALL ); add_sc( BA_FROSTJOKER , SC_FREEZE ); - set_sc( BA_WHISTLE , SC_WHISTLE , SI_BLANK , SCB_FLEE|SCB_FLEE2 ); - set_sc( BA_ASSASSINCROSS , SC_ASSNCROS , SI_BLANK , SCB_ASPD ); + status->set_sc( BA_WHISTLE , SC_WHISTLE , SCB_FLEE|SCB_FLEE2 ); + status->set_sc( BA_ASSASSINCROSS , SC_ASSNCROS , SCB_ASPD ); add_sc( BA_POEMBRAGI , SC_POEMBRAGI ); - set_sc( BA_APPLEIDUN , SC_APPLEIDUN , SI_BLANK , SCB_MAXHP ); + status->set_sc( BA_APPLEIDUN , SC_APPLEIDUN , SCB_MAXHP ); add_sc( DC_SCREAM , SC_STUN ); - set_sc( DC_HUMMING , SC_HUMMING , SI_BLANK , SCB_HIT ); - set_sc( DC_DONTFORGETME , SC_DONTFORGETME , SI_BLANK , SCB_SPEED|SCB_ASPD ); - set_sc( DC_FORTUNEKISS , SC_FORTUNE , SI_BLANK , SCB_CRI ); - set_sc( DC_SERVICEFORYOU , SC_SERVICEFORYOU , SI_BLANK , SCB_ALL ); + status->set_sc( DC_HUMMING , SC_HUMMING , SCB_HIT ); + status->set_sc( DC_DONTFORGETME , SC_DONTFORGETME , SCB_SPEED|SCB_ASPD ); + status->set_sc( DC_FORTUNEKISS , SC_FORTUNE , SCB_CRI ); + status->set_sc( DC_SERVICEFORYOU , SC_SERVICEFORYOU , SCB_ALL ); add_sc( NPC_DARKCROSS , SC_BLIND ); add_sc( NPC_GRANDDARKNESS , SC_BLIND ); - set_sc( NPC_STOP , SC_STOP , SI_STOP , SCB_NONE ); - set_sc( NPC_WEAPONBRAKER , SC_BROKENWEAPON , SI_BROKENWEAPON , SCB_NONE ); - set_sc( NPC_ARMORBRAKE , SC_BROKENARMOR , SI_BROKENARMOR , SCB_NONE ); - set_sc( NPC_CHANGEUNDEAD , SC_PROPERTYUNDEAD , SI_PROPERTYUNDEAD , SCB_DEF_ELE ); - set_sc( NPC_POWERUP , SC_INCHITRATE , SI_BLANK , SCB_HIT ); - set_sc( NPC_AGIUP , SC_INCFLEERATE , SI_BLANK , SCB_FLEE ); + status->set_sc( NPC_STOP , SC_STOP , SCB_NONE ); + status->set_sc( NPC_WEAPONBRAKER , SC_BROKENWEAPON , SCB_NONE ); + status->set_sc( NPC_ARMORBRAKE , SC_BROKENARMOR , SCB_NONE ); + status->set_sc( NPC_CHANGEUNDEAD , SC_PROPERTYUNDEAD , SCB_DEF_ELE ); + status->set_sc( NPC_POWERUP , SC_INCHITRATE , SCB_HIT ); + status->set_sc( NPC_AGIUP , SC_INCFLEERATE , SCB_FLEE ); add_sc( NPC_INVISIBLE , SC_CLOAKING ); - set_sc( LK_AURABLADE , SC_AURABLADE , SI_AURABLADE , SCB_NONE ); - set_sc( LK_PARRYING , SC_PARRYING , SI_PARRYING , SCB_NONE ); + status->set_sc( LK_AURABLADE , SC_AURABLADE , SCB_NONE ); + status->set_sc( LK_PARRYING , SC_PARRYING , SCB_NONE ); #ifndef RENEWAL - set_sc( LK_CONCENTRATION , SC_LKCONCENTRATION , SI_LKCONCENTRATION , SCB_BATK|SCB_WATK|SCB_HIT|SCB_DEF|SCB_DEF2); + status->set_sc( LK_CONCENTRATION , SC_LKCONCENTRATION , SCB_BATK|SCB_WATK|SCB_HIT|SCB_DEF|SCB_DEF2); #else - set_sc( LK_CONCENTRATION , SC_LKCONCENTRATION , SI_LKCONCENTRATION , SCB_HIT|SCB_DEF); + status->set_sc( LK_CONCENTRATION , SC_LKCONCENTRATION , SCB_HIT|SCB_DEF); #endif - set_sc( LK_TENSIONRELAX , SC_TENSIONRELAX , SI_TENSIONRELAX , SCB_REGEN ); - set_sc( LK_BERSERK , SC_BERSERK , SI_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN ); - set_sc( HP_ASSUMPTIO , SC_ASSUMPTIO , SI_ASSUMPTIO , SCB_NONE ); + status->set_sc( LK_TENSIONRELAX , SC_TENSIONRELAX , SCB_REGEN ); + status->set_sc( LK_BERSERK , SC_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN ); + status->set_sc( HP_ASSUMPTIO , SC_ASSUMPTIO , SCB_NONE ); add_sc( HP_BASILICA , SC_BASILICA ); - set_sc( HW_MAGICPOWER , SC_MAGICPOWER , SI_MAGICPOWER , SCB_MATK ); + status->set_sc( HW_MAGICPOWER , SC_MAGICPOWER , SCB_MATK ); add_sc( PA_SACRIFICE , SC_SACRIFICE ); - set_sc( PA_GOSPEL , SC_GOSPEL , SI_BLANK , SCB_SPEED|SCB_ASPD ); + status->set_sc( PA_GOSPEL , SC_GOSPEL , SCB_SPEED|SCB_ASPD ); add_sc( PA_GOSPEL , SC_SCRESIST ); add_sc( CH_TIGERFIST , SC_STOP ); - set_sc( ASC_EDP , SC_EDP , SI_EDP , SCB_NONE ); - set_sc( SN_SIGHT , SC_TRUESIGHT , SI_TRUESIGHT , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK|SCB_CRI|SCB_HIT ); - set_sc( SN_WINDWALK , SC_WINDWALK , SI_WINDWALK , SCB_FLEE|SCB_SPEED ); - set_sc( WS_MELTDOWN , SC_MELTDOWN , SI_MELTDOWN , SCB_NONE ); - set_sc( WS_CARTBOOST , SC_CARTBOOST , SI_CARTBOOST , SCB_SPEED ); - set_sc( ST_CHASEWALK , SC_CHASEWALK , SI_BLANK , SCB_SPEED ); - set_sc( ST_REJECTSWORD , SC_SWORDREJECT , SI_SWORDREJECT , SCB_NONE ); + status->set_sc( ASC_EDP , SC_EDP , SCB_NONE ); + status->set_sc( SN_SIGHT , SC_TRUESIGHT , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK|SCB_CRI|SCB_HIT ); + status->set_sc( SN_WINDWALK , SC_WINDWALK , SCB_FLEE|SCB_SPEED ); + status->set_sc( WS_MELTDOWN , SC_MELTDOWN , SCB_NONE ); + status->set_sc( WS_CARTBOOST , SC_CARTBOOST , SCB_SPEED ); + status->set_sc( ST_CHASEWALK , SC_CHASEWALK , SCB_SPEED ); + status->set_sc( ST_REJECTSWORD , SC_SWORDREJECT , SCB_NONE ); add_sc( ST_REJECTSWORD , SC_AUTOCOUNTER ); - set_sc( CG_MARIONETTE , SC_MARIONETTE_MASTER , SI_MARIONETTE_MASTER , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); - set_sc( CG_MARIONETTE , SC_MARIONETTE , SI_MARIONETTE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); + status->set_sc( CG_MARIONETTE , SC_MARIONETTE_MASTER , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); + status->set_sc( CG_MARIONETTE , SC_MARIONETTE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); add_sc( LK_SPIRALPIERCE , SC_STOP ); add_sc( LK_HEADCRUSH , SC_BLOODING ); - set_sc( LK_JOINTBEAT , SC_JOINTBEAT , SI_JOINTBEAT , SCB_BATK|SCB_DEF2|SCB_SPEED|SCB_ASPD ); + status->set_sc( LK_JOINTBEAT , SC_JOINTBEAT , SCB_BATK|SCB_DEF2|SCB_SPEED|SCB_ASPD ); add_sc( HW_NAPALMVULCAN , SC_CURSE ); - set_sc( PF_MINDBREAKER , SC_MINDBREAKER , SI_BLANK , SCB_MATK|SCB_MDEF2 ); + status->set_sc( PF_MINDBREAKER , SC_MINDBREAKER , SCB_MATK|SCB_MDEF2 ); add_sc( PF_MEMORIZE , SC_MEMORIZE ); add_sc( PF_FOGWALL , SC_FOGWALL ); - set_sc( PF_SPIDERWEB , SC_SPIDERWEB , SI_BLANK , SCB_FLEE ); - set_sc( WE_BABY , SC_BABY , SI_PROTECTEXP , SCB_NONE ); - set_sc( TK_RUN , SC_RUN , SI_RUN , SCB_SPEED|SCB_DSPD ); - set_sc( TK_RUN , SC_STRUP , SI_STRUP , SCB_STR ); - set_sc( TK_READYSTORM , SC_STORMKICK_READY , SI_STORMKICK_ON , SCB_NONE ); - set_sc( TK_READYDOWN , SC_DOWNKICK_READY , SI_DOWNKICK_ON , SCB_NONE ); + status->set_sc( PF_SPIDERWEB , SC_SPIDERWEB , SCB_FLEE ); + status->set_sc( WE_BABY , SC_BABY , SCB_NONE ); + status->set_sc( TK_RUN , SC_RUN , SCB_SPEED|SCB_DSPD ); + status->set_sc( TK_RUN , SC_STRUP , SCB_STR ); + status->set_sc( TK_READYSTORM , SC_STORMKICK_READY , SCB_NONE ); + status->set_sc( TK_READYDOWN , SC_DOWNKICK_READY , SCB_NONE ); add_sc( TK_DOWNKICK , SC_STUN ); - set_sc( TK_READYTURN , SC_TURNKICK_READY , SI_TURNKICK_ON , SCB_NONE ); - set_sc( TK_READYCOUNTER , SC_COUNTERKICK_READY , SI_COUNTER_ON , SCB_NONE ); - set_sc( TK_DODGE , SC_DODGE_READY , SI_DODGE_ON , SCB_NONE ); - set_sc( TK_SPTIME , SC_EARTHSCROLL , SI_EARTHSCROLL , SCB_NONE ); + status->set_sc( TK_READYTURN , SC_TURNKICK_READY , SCB_NONE ); + status->set_sc( TK_READYCOUNTER , SC_COUNTERKICK_READY , SCB_NONE ); + status->set_sc( TK_DODGE , SC_DODGE_READY , SCB_NONE ); + status->set_sc( TK_SPTIME , SC_EARTHSCROLL , SCB_NONE ); add_sc( TK_SEVENWIND , SC_TK_SEVENWIND ); - set_sc( TK_SEVENWIND , SC_PROPERTYTELEKINESIS , SI_PROPERTYTELEKINESIS , SCB_ATK_ELE ); - set_sc( TK_SEVENWIND , SC_PROPERTYDARK , SI_PROPERTYDARK , SCB_ATK_ELE ); - set_sc( SG_SUN_WARM , SC_WARM , SI_SG_SUN_WARM , SCB_NONE ); + status->set_sc( TK_SEVENWIND , SC_PROPERTYTELEKINESIS , SCB_ATK_ELE ); + status->set_sc( TK_SEVENWIND , SC_PROPERTYDARK , SCB_ATK_ELE ); + status->set_sc( SG_SUN_WARM , SC_WARM , SCB_NONE ); add_sc( SG_MOON_WARM , SC_WARM ); add_sc( SG_STAR_WARM , SC_WARM ); - set_sc( SG_SUN_COMFORT , SC_SUN_COMFORT , SI_SUN_COMFORT , SCB_DEF2 ); - set_sc( SG_MOON_COMFORT , SC_MOON_COMFORT , SI_MOON_COMFORT , SCB_FLEE ); - set_sc( SG_STAR_COMFORT , SC_STAR_COMFORT , SI_STAR_COMFORT , SCB_ASPD ); + status->set_sc( SG_SUN_COMFORT , SC_SUN_COMFORT , SCB_DEF2 ); + status->set_sc( SG_MOON_COMFORT , SC_MOON_COMFORT , SCB_FLEE ); + status->set_sc( SG_STAR_COMFORT , SC_STAR_COMFORT , SCB_ASPD ); add_sc( SG_FRIEND , SC_SKILLRATE_UP ); - set_sc( SG_KNOWLEDGE , SC_KNOWLEDGE , SI_BLANK , SCB_ALL ); - set_sc( SG_FUSION , SC_FUSION , SI_BLANK , SCB_SPEED ); - set_sc( BS_ADRENALINE2 , SC_ADRENALINE2 , SI_ADRENALINE2 , SCB_ASPD ); - set_sc( SL_KAIZEL , SC_KAIZEL , SI_KAIZEL , SCB_NONE ); - set_sc( SL_KAAHI , SC_KAAHI , SI_KAAHI , SCB_NONE ); - set_sc( SL_KAUPE , SC_KAUPE , SI_KAUPE , SCB_NONE ); - set_sc( SL_KAITE , SC_KAITE , SI_KAITE , SCB_NONE ); + status->set_sc( SG_KNOWLEDGE , SC_KNOWLEDGE , SCB_ALL ); + status->set_sc( SG_FUSION , SC_FUSION , SCB_SPEED ); + status->set_sc( BS_ADRENALINE2 , SC_ADRENALINE2 , SCB_ASPD ); + status->set_sc( SL_KAIZEL , SC_KAIZEL , SCB_NONE ); + status->set_sc( SL_KAAHI , SC_KAAHI , SCB_NONE ); + status->set_sc( SL_KAUPE , SC_KAUPE , SCB_NONE ); + status->set_sc( SL_KAITE , SC_KAITE , SCB_NONE ); add_sc( SL_STUN , SC_STUN ); - set_sc( SL_SWOO , SC_SWOO , SI_BLANK , SCB_SPEED ); - set_sc( SL_SKE , SC_SKE , SI_BLANK , SCB_BATK|SCB_WATK|SCB_DEF|SCB_DEF2 ); - set_sc( SL_SKA , SC_SKA , SI_BLANK , SCB_DEF|SCB_MDEF|SCB_ASPD ); - set_sc( SL_SMA , SC_SMA_READY , SI_SMA_READY , SCB_NONE ); - set_sc( SM_SELFPROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK ); - set_sc( ST_PRESERVE , SC_PRESERVE , SI_PRESERVE , SCB_NONE ); - set_sc( PF_DOUBLECASTING , SC_DOUBLECASTING , SI_DOUBLECASTING , SCB_NONE ); - set_sc( HW_GRAVITATION , SC_GRAVITATION , SI_BLANK , SCB_ASPD ); + status->set_sc( SL_SWOO , SC_SWOO , SCB_SPEED ); + status->set_sc( SL_SKE , SC_SKE , SCB_BATK|SCB_WATK|SCB_DEF|SCB_DEF2 ); + status->set_sc( SL_SKA , SC_SKA , SCB_DEF|SCB_MDEF|SCB_ASPD ); + status->set_sc( SL_SMA , SC_SMA_READY , SCB_NONE ); + status->set_sc( SM_SELFPROVOKE , SC_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK ); + status->set_sc( ST_PRESERVE , SC_PRESERVE , SCB_NONE ); + status->set_sc( PF_DOUBLECASTING , SC_DOUBLECASTING , SCB_NONE ); + status->set_sc( HW_GRAVITATION , SC_GRAVITATION , SCB_ASPD ); add_sc( WS_CARTTERMINATION , SC_STUN ); - set_sc( WS_OVERTHRUSTMAX , SC_OVERTHRUSTMAX , SI_OVERTHRUSTMAX , SCB_NONE ); - set_sc( CG_LONGINGFREEDOM , SC_LONGING , SI_BLANK , SCB_SPEED|SCB_ASPD ); + status->set_sc( WS_OVERTHRUSTMAX , SC_OVERTHRUSTMAX , SCB_NONE ); + status->set_sc( CG_LONGINGFREEDOM , SC_LONGING , SCB_SPEED|SCB_ASPD ); add_sc( CG_HERMODE , SC_HERMODE ); - set_sc( CG_TAROTCARD , SC_TAROTCARD , SI_TAROTCARD , SCB_NONE ); - set_sc( ITEM_ENCHANTARMS , SC_ENCHANTARMS , SI_BLANK , SCB_ATK_ELE ); - set_sc( SL_HIGH , SC_SOULLINK , SI_SOULLINK , SCB_ALL ); - set_sc( KN_ONEHAND , SC_ONEHANDQUICKEN , SI_ONEHANDQUICKEN , SCB_ASPD ); - set_sc( GS_FLING , SC_FLING , SI_BLANK , SCB_DEF|SCB_DEF2 ); + status->set_sc( CG_TAROTCARD , SC_TAROTCARD , SCB_NONE ); + status->set_sc( ITEM_ENCHANTARMS , SC_ENCHANTARMS , SCB_ATK_ELE ); + status->set_sc( SL_HIGH , SC_SOULLINK , SCB_ALL ); + status->set_sc( KN_ONEHAND , SC_ONEHANDQUICKEN , SCB_ASPD ); + status->set_sc( GS_FLING , SC_FLING , SCB_DEF|SCB_DEF2 ); add_sc( GS_CRACKER , SC_STUN ); add_sc( GS_DISARM , SC_NOEQUIPWEAPON ); add_sc( GS_PIERCINGSHOT , SC_BLOODING ); - set_sc( GS_MADNESSCANCEL , SC_GS_MADNESSCANCEL , SI_GS_MADNESSCANCEL , SCB_ASPD + status->set_sc( GS_MADNESSCANCEL , SC_GS_MADNESSCANCEL , SCB_ASPD #ifndef RENEWAL |SCB_BATK ); #else ); #endif - set_sc( GS_ADJUSTMENT , SC_GS_ADJUSTMENT , SI_GS_ADJUSTMENT , SCB_HIT|SCB_FLEE ); - set_sc( GS_INCREASING , SC_GS_ACCURACY , SI_GS_ACCURACY , SCB_AGI|SCB_DEX|SCB_HIT ); - set_sc( GS_GATLINGFEVER , SC_GS_GATLINGFEVER , SI_GS_GATLINGFEVER , SCB_FLEE|SCB_SPEED|SCB_ASPD + status->set_sc( GS_ADJUSTMENT , SC_GS_ADJUSTMENT , SCB_HIT|SCB_FLEE ); + status->set_sc( GS_INCREASING , SC_GS_ACCURACY , SCB_AGI|SCB_DEX|SCB_HIT ); + status->set_sc( GS_GATLINGFEVER , SC_GS_GATLINGFEVER , SCB_FLEE|SCB_SPEED|SCB_ASPD #ifndef RENEWAL |SCB_BATK ); #else ); #endif - set_sc( NJ_TATAMIGAESHI , SC_NJ_TATAMIGAESHI , SI_BLANK , SCB_NONE ); - set_sc( NJ_SUITON , SC_NJ_SUITON , SI_NJ_SUITON , SCB_AGI|SCB_SPEED ); + status->set_sc( NJ_TATAMIGAESHI , SC_NJ_TATAMIGAESHI , SCB_NONE ); + status->set_sc( NJ_SUITON , SC_NJ_SUITON , SCB_AGI|SCB_SPEED ); add_sc( NJ_HYOUSYOURAKU , SC_FREEZE ); - set_sc( NJ_NEN , SC_NJ_NEN , SI_NJ_NEN , SCB_STR|SCB_INT ); - set_sc( NJ_UTSUSEMI , SC_NJ_UTSUSEMI , SI_NJ_UTSUSEMI , SCB_NONE ); - set_sc( NJ_BUNSINJYUTSU , SC_NJ_BUNSINJYUTSU , SI_NJ_BUNSINJYUTSU , SCB_DYE ); + status->set_sc( NJ_NEN , SC_NJ_NEN , SCB_STR|SCB_INT ); + status->set_sc( NJ_UTSUSEMI , SC_NJ_UTSUSEMI , SCB_NONE ); + status->set_sc( NJ_BUNSINJYUTSU , SC_NJ_BUNSINJYUTSU , SCB_DYE ); add_sc( NPC_ICEBREATH , SC_FREEZE ); add_sc( NPC_ACIDBREATH , SC_POISON ); @@ -451,202 +460,202 @@ void initChangeTables(void) { add_sc( NPC_WIDESIGHT , SC_SIGHT ); add_sc( NPC_EVILLAND , SC_BLIND ); add_sc( NPC_MAGICMIRROR , SC_MAGICMIRROR ); - set_sc( NPC_SLOWCAST , SC_SLOWCAST , SI_SLOWCAST , SCB_NONE ); - set_sc( NPC_CRITICALWOUND , SC_CRITICALWOUND , SI_CRITICALWOUND , SCB_NONE ); - set_sc( NPC_STONESKIN , SC_STONESKIN , SI_BLANK , SCB_DEF|SCB_MDEF ); + status->set_sc( NPC_SLOWCAST , SC_SLOWCAST , SCB_NONE ); + status->set_sc( NPC_CRITICALWOUND , SC_CRITICALWOUND , SCB_NONE ); + status->set_sc( NPC_STONESKIN , SC_STONESKIN , SCB_DEF|SCB_MDEF ); add_sc( NPC_ANTIMAGIC , SC_STONESKIN ); add_sc( NPC_WIDECURSE , SC_CURSE ); add_sc( NPC_WIDESTUN , SC_STUN ); - set_sc( NPC_HELLPOWER , SC_HELLPOWER , SI_HELLPOWER , SCB_NONE ); - set_sc( NPC_WIDEHELLDIGNITY , SC_HELLPOWER , SI_HELLPOWER , SCB_NONE ); - set_sc( NPC_INVINCIBLE , SC_INVINCIBLE , SI_INVINCIBLE , SCB_SPEED ); - set_sc( NPC_INVINCIBLEOFF , SC_INVINCIBLEOFF , SI_BLANK , SCB_SPEED ); + status->set_sc( NPC_HELLPOWER , SC_HELLPOWER , SCB_NONE ); + status->set_sc( NPC_WIDEHELLDIGNITY , SC_HELLPOWER , SCB_NONE ); + status->set_sc( NPC_INVINCIBLE , SC_INVINCIBLE , SCB_SPEED ); + status->set_sc( NPC_INVINCIBLEOFF , SC_INVINCIBLEOFF , SCB_SPEED ); - set_sc( CASH_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX ); - set_sc( CASH_INCAGI , SC_INC_AGI , SI_INC_AGI , SCB_AGI|SCB_SPEED ); - set_sc( CASH_ASSUMPTIO , SC_ASSUMPTIO , SI_ASSUMPTIO , SCB_NONE ); + status->set_sc( CASH_BLESSING , SC_BLESSING , SCB_STR|SCB_INT|SCB_DEX ); + status->set_sc( CASH_INCAGI , SC_INC_AGI , SCB_AGI|SCB_SPEED ); + status->set_sc( CASH_ASSUMPTIO , SC_ASSUMPTIO , SCB_NONE ); - set_sc( ALL_PARTYFLEE , SC_PARTYFLEE , SI_PARTYFLEE , SCB_NONE ); - set_sc( ALL_ODINS_POWER , SC_ODINS_POWER , SI_ODINS_POWER , SCB_WATK | SCB_MATK | SCB_MDEF | SCB_DEF); + status->set_sc( ALL_PARTYFLEE , SC_PARTYFLEE , SCB_NONE ); + status->set_sc( ALL_ODINS_POWER , SC_ODINS_POWER , SCB_WATK | SCB_MATK | SCB_MDEF | SCB_DEF); - set_sc( CR_SHRINK , SC_CR_SHRINK , SI_CR_SHRINK , SCB_NONE ); - set_sc( RG_CLOSECONFINE , SC_RG_CCONFINE_S , SI_RG_CCONFINE_S , SCB_NONE ); - set_sc( RG_CLOSECONFINE , SC_RG_CCONFINE_M , SI_RG_CCONFINE_M , SCB_FLEE ); - set_sc( WZ_SIGHTBLASTER , SC_WZ_SIGHTBLASTER , SI_WZ_SIGHTBLASTER , SCB_NONE ); - set_sc( DC_WINKCHARM , SC_DC_WINKCHARM , SI_DC_WINKCHARM , SCB_NONE ); + status->set_sc( CR_SHRINK , SC_CR_SHRINK , SCB_NONE ); + status->set_sc( RG_CLOSECONFINE , SC_RG_CCONFINE_S , SCB_NONE ); + status->set_sc( RG_CLOSECONFINE , SC_RG_CCONFINE_M , SCB_FLEE ); + status->set_sc( WZ_SIGHTBLASTER , SC_WZ_SIGHTBLASTER , SCB_NONE ); + status->set_sc( DC_WINKCHARM , SC_DC_WINKCHARM , SCB_NONE ); add_sc( MO_BALKYOUNG , SC_STUN ); add_sc( SA_ELEMENTWATER , SC_ARMOR_PROPERTY ); add_sc( SA_ELEMENTFIRE , SC_ARMOR_PROPERTY ); add_sc( SA_ELEMENTGROUND , SC_ARMOR_PROPERTY ); add_sc( SA_ELEMENTWIND , SC_ARMOR_PROPERTY ); - set_sc( HLIF_AVOID , SC_HLIF_AVOID , SI_BLANK , SCB_SPEED ); - set_sc( HLIF_CHANGE , SC_HLIF_CHANGE , SI_BLANK , SCB_VIT|SCB_INT ); - set_sc( HFLI_FLEET , SC_HLIF_FLEET , SI_BLANK , SCB_ASPD|SCB_BATK|SCB_WATK ); - set_sc( HFLI_SPEED , SC_HLIF_SPEED , SI_BLANK , SCB_FLEE ); - set_sc( HAMI_DEFENCE , SC_HAMI_DEFENCE , SI_BLANK , SCB_DEF ); - set_sc( HAMI_BLOODLUST , SC_HAMI_BLOODLUST , SI_BLANK , SCB_BATK|SCB_WATK ); + status->set_sc( HLIF_AVOID , SC_HLIF_AVOID , SCB_SPEED ); + status->set_sc( HLIF_CHANGE , SC_HLIF_CHANGE , SCB_VIT|SCB_INT ); + status->set_sc( HFLI_FLEET , SC_HLIF_FLEET , SCB_ASPD|SCB_BATK|SCB_WATK ); + status->set_sc( HFLI_SPEED , SC_HLIF_SPEED , SCB_FLEE ); + status->set_sc( HAMI_DEFENCE , SC_HAMI_DEFENCE , SCB_DEF ); + status->set_sc( HAMI_BLOODLUST , SC_HAMI_BLOODLUST , 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 ); + status->set_sc( MH_LIGHT_OF_REGENE , SC_LIGHT_OF_REGENE , SCB_NONE ); + status->set_sc( MH_OVERED_BOOST , SC_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); + status->set_sc(MH_ANGRIFFS_MODUS, SC_ANGRIFFS_MODUS, SCB_BATK | SCB_DEF | SCB_FLEE | SCB_MAXHP); + status->set_sc(MH_GOLDENE_FERSE, SC_GOLDENE_FERSE, SCB_ASPD|SCB_MAXHP); add_sc( MH_STEINWAND, SC_SAFETYWALL ); - 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); - set_sc(MH_PYROCLASTIC, SC_PYROCLASTIC, SI_PYROCLASTIC, SCB_BATK|SCB_ATK_ELE); + status->set_sc(MH_VOLCANIC_ASH, SC_VOLCANIC_ASH, SCB_DEF|SCB_DEF2|SCB_HIT|SCB_BATK|SCB_FLEE); + status->set_sc(MH_GRANITIC_ARMOR, SC_GRANITIC_ARMOR, SCB_NONE); + status->set_sc(MH_MAGMA_FLOW, SC_MAGMA_FLOW, SCB_NONE); + status->set_sc(MH_PYROCLASTIC, SC_PYROCLASTIC, SCB_BATK|SCB_ATK_ELE); add_sc(MH_LAVA_SLIDE, SC_BURNING); - set_sc(MH_NEEDLE_OF_PARALYZE, SC_NEEDLE_OF_PARALYZE, SI_NEEDLE_OF_PARALYZE, SCB_DEF2); + status->set_sc(MH_NEEDLE_OF_PARALYZE, SC_NEEDLE_OF_PARALYZE, SCB_DEF2); add_sc(MH_POISON_MIST, SC_BLIND); - set_sc(MH_PAIN_KILLER, SC_PAIN_KILLER, SI_PAIN_KILLER, SCB_ASPD); + status->set_sc(MH_PAIN_KILLER, SC_PAIN_KILLER, SCB_ASPD); - set_sc( MH_SILENT_BREEZE , SC_SILENCE , SI_SILENT_BREEZE , SCB_NONE ); + status->set_sc( MH_SILENT_BREEZE , SC_SILENCE , 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 ); + status->set_sc( MH_TINDER_BREAKER , SC_RG_CCONFINE_S , SCB_NONE ); + status->set_sc( MH_TINDER_BREAKER , SC_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 ); + status->set_sc( MER_PROVOKE , SC_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK ); add_sc( MS_MAGNUM , SC_SUB_WEAPONPROPERTY ); add_sc( MER_SIGHT , SC_SIGHT ); - set_sc( MER_DECAGI , SC_DEC_AGI , SI_DEC_AGI , SCB_AGI|SCB_SPEED ); - set_sc( MER_MAGNIFICAT , SC_MAGNIFICAT , SI_MAGNIFICAT , SCB_REGEN ); + status->set_sc( MER_DECAGI , SC_DEC_AGI , SCB_AGI|SCB_SPEED ); + status->set_sc( MER_MAGNIFICAT , SC_MAGNIFICAT , SCB_REGEN ); add_sc( MER_LEXDIVINA , SC_SILENCE ); add_sc( MA_LANDMINE , SC_STUN ); add_sc( MA_SANDMAN , SC_SLEEP ); add_sc( MA_FREEZINGTRAP , SC_FREEZE ); - set_sc( MER_AUTOBERSERK , SC_AUTOBERSERK , SI_AUTOBERSERK , SCB_NONE ); - set_sc( ML_AUTOGUARD , SC_AUTOGUARD , SI_AUTOGUARD , SCB_NONE ); - set_sc( MS_REFLECTSHIELD , SC_REFLECTSHIELD , SI_REFLECTSHIELD , SCB_NONE ); - set_sc( ML_DEFENDER , SC_DEFENDER , SI_DEFENDER , SCB_SPEED|SCB_ASPD ); - set_sc( MS_PARRYING , SC_PARRYING , SI_PARRYING , SCB_NONE ); - set_sc( MS_BERSERK , SC_BERSERK , SI_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN ); + status->set_sc( MER_AUTOBERSERK , SC_AUTOBERSERK , SCB_NONE ); + status->set_sc( ML_AUTOGUARD , SC_AUTOGUARD , SCB_NONE ); + status->set_sc( MS_REFLECTSHIELD , SC_REFLECTSHIELD , SCB_NONE ); + status->set_sc( ML_DEFENDER , SC_DEFENDER , SCB_SPEED|SCB_ASPD ); + status->set_sc( MS_PARRYING , SC_PARRYING , SCB_NONE ); + status->set_sc( MS_BERSERK , SC_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN ); add_sc( ML_SPIRALPIERCE , SC_STOP ); - set_sc( MER_QUICKEN , SC_MER_QUICKEN , SI_BLANK , SCB_ASPD ); + status->set_sc( MER_QUICKEN , SC_MER_QUICKEN , SCB_ASPD ); add_sc( ML_DEVOTION , SC_DEVOTION ); - set_sc( MER_KYRIE , SC_KYRIE , SI_KYRIE , SCB_NONE ); - set_sc( MER_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX ); - set_sc( MER_INCAGI , SC_INC_AGI , SI_INC_AGI , SCB_AGI|SCB_SPEED ); + status->set_sc( MER_KYRIE , SC_KYRIE , SCB_NONE ); + status->set_sc( MER_BLESSING , SC_BLESSING , SCB_STR|SCB_INT|SCB_DEX ); + status->set_sc( MER_INCAGI , SC_INC_AGI , SCB_AGI|SCB_SPEED ); - set_sc( GD_LEADERSHIP , SC_LEADERSHIP , SI_BLANK , SCB_STR ); - set_sc( GD_GLORYWOUNDS , SC_GLORYWOUNDS , SI_BLANK , SCB_VIT ); - set_sc( GD_SOULCOLD , SC_SOULCOLD , SI_BLANK , SCB_AGI ); - set_sc( GD_HAWKEYES , SC_HAWKEYES , SI_BLANK , SCB_DEX ); + status->set_sc( GD_LEADERSHIP , SC_LEADERSHIP , SCB_STR ); + status->set_sc( GD_GLORYWOUNDS , SC_GLORYWOUNDS , SCB_VIT ); + status->set_sc( GD_SOULCOLD , SC_SOULCOLD , SCB_AGI ); + status->set_sc( GD_HAWKEYES , SC_HAWKEYES , SCB_DEX ); - set_sc( GD_BATTLEORDER , SC_GDSKILL_BATTLEORDER , SI_BLANK , SCB_STR|SCB_INT|SCB_DEX ); - set_sc( GD_REGENERATION , SC_GDSKILL_REGENERATION , SI_BLANK , SCB_REGEN ); + status->set_sc( GD_BATTLEORDER , SC_GDSKILL_BATTLEORDER , SCB_STR|SCB_INT|SCB_DEX ); + status->set_sc( GD_REGENERATION , SC_GDSKILL_REGENERATION , SCB_REGEN ); /** * Rune Knight **/ - set_sc( RK_ENCHANTBLADE , SC_ENCHANTBLADE , SI_ENCHANTBLADE , SCB_NONE ); - set_sc( RK_DRAGONHOWLING , SC_FEAR , SI_BLANK , SCB_FLEE|SCB_HIT ); - set_sc( RK_DEATHBOUND , SC_DEATHBOUND , SI_DEATHBOUND , SCB_NONE ); - set_sc( RK_WINDCUTTER , SC_FEAR , SI_BLANK , SCB_FLEE|SCB_HIT ); + status->set_sc( RK_ENCHANTBLADE , SC_ENCHANTBLADE , SCB_NONE ); + status->set_sc( RK_DRAGONHOWLING , SC_FEAR , SCB_FLEE|SCB_HIT ); + status->set_sc( RK_DEATHBOUND , SC_DEATHBOUND , SCB_NONE ); + status->set_sc( RK_WINDCUTTER , SC_FEAR , SCB_FLEE|SCB_HIT ); add_sc( RK_DRAGONBREATH , SC_BURNING ); - set_sc( RK_MILLENNIUMSHIELD , SC_MILLENNIUMSHIELD , SI_BLANK , SCB_NONE ); - set_sc( RK_REFRESH , SC_REFRESH , SI_REFRESH , SCB_NONE ); - set_sc( RK_GIANTGROWTH , SC_GIANTGROWTH , SI_GIANTGROWTH , SCB_STR ); - set_sc( RK_STONEHARDSKIN , SC_STONEHARDSKIN , SI_STONEHARDSKIN , SCB_NONE ); - set_sc( RK_VITALITYACTIVATION, SC_VITALITYACTIVATION, SI_VITALITYACTIVATION, SCB_REGEN ); - set_sc( RK_FIGHTINGSPIRIT , SC_FIGHTINGSPIRIT , SI_FIGHTINGSPIRIT , SCB_WATK|SCB_ASPD ); - set_sc( RK_ABUNDANCE , SC_ABUNDANCE , SI_ABUNDANCE , SCB_NONE ); - set_sc( RK_CRUSHSTRIKE , SC_CRUSHSTRIKE , SI_CRUSHSTRIKE , SCB_NONE ); + status->set_sc( RK_MILLENNIUMSHIELD , SC_MILLENNIUMSHIELD , SCB_NONE ); + status->set_sc( RK_REFRESH , SC_REFRESH , SCB_NONE ); + status->set_sc( RK_GIANTGROWTH , SC_GIANTGROWTH , SCB_STR ); + status->set_sc( RK_STONEHARDSKIN , SC_STONEHARDSKIN , SCB_NONE ); + status->set_sc( RK_VITALITYACTIVATION, SC_VITALITYACTIVATION, SCB_REGEN ); + status->set_sc( RK_FIGHTINGSPIRIT , SC_FIGHTINGSPIRIT , SCB_WATK|SCB_ASPD ); + status->set_sc( RK_ABUNDANCE , SC_ABUNDANCE , SCB_NONE ); + status->set_sc( RK_CRUSHSTRIKE , SC_CRUSHSTRIKE , SCB_NONE ); add_sc( RK_DRAGONBREATH_WATER, SC_FROSTMISTY ); /** * GC Guillotine Cross **/ - set_sc_with_vfx( GC_VENOMIMPRESS , SC_VENOMIMPRESS , SI_VENOMIMPRESS , SCB_NONE ); - set_sc( GC_POISONINGWEAPON , SC_POISONINGWEAPON , SI_POISONINGWEAPON , SCB_NONE ); - set_sc( GC_WEAPONBLOCKING , SC_WEAPONBLOCKING , SI_WEAPONBLOCKING , SCB_NONE ); - set_sc( GC_CLOAKINGEXCEED , SC_CLOAKINGEXCEED , SI_CLOAKINGEXCEED , SCB_SPEED ); - set_sc( GC_HALLUCINATIONWALK , SC_HALLUCINATIONWALK, SI_HALLUCINATIONWALK, SCB_FLEE ); - set_sc( GC_ROLLINGCUTTER , SC_ROLLINGCUTTER , SI_ROLLINGCUTTER , SCB_NONE ); - set_sc_with_vfx( GC_DARKCROW , SC_DARKCROW , SI_DARKCROW , SCB_NONE ); + set_sc_with_vfx( GC_VENOMIMPRESS , SC_VENOMIMPRESS , SCB_NONE ); + status->set_sc( GC_POISONINGWEAPON , SC_POISONINGWEAPON , SCB_NONE ); + status->set_sc( GC_WEAPONBLOCKING , SC_WEAPONBLOCKING , SCB_NONE ); + status->set_sc( GC_CLOAKINGEXCEED , SC_CLOAKINGEXCEED , SCB_SPEED ); + status->set_sc( GC_HALLUCINATIONWALK , SC_HALLUCINATIONWALK, SCB_FLEE ); + status->set_sc( GC_ROLLINGCUTTER , SC_ROLLINGCUTTER , SCB_NONE ); + set_sc_with_vfx( GC_DARKCROW , SC_DARKCROW , SCB_NONE ); /** * Arch Bishop **/ - set_sc( AB_ADORAMUS , SC_ADORAMUS , SI_ADORAMUS , SCB_AGI|SCB_SPEED ); + status->set_sc( AB_ADORAMUS , SC_ADORAMUS , SCB_AGI|SCB_SPEED ); add_sc( AB_CLEMENTIA , SC_BLESSING ); add_sc( AB_CANTO , SC_INC_AGI ); - set_sc( AB_EPICLESIS , SC_EPICLESIS , SI_EPICLESIS , SCB_MAXHP ); + status->set_sc( AB_EPICLESIS , SC_EPICLESIS , SCB_MAXHP ); add_sc( AB_PRAEFATIO , SC_KYRIE ); - set_sc_with_vfx( AB_ORATIO , SC_ORATIO , SI_ORATIO , SCB_NONE ); - set_sc( AB_LAUDAAGNUS , SC_LAUDAAGNUS , SI_LAUDAAGNUS , SCB_VIT ); - set_sc( AB_LAUDARAMUS , SC_LAUDARAMUS , SI_LAUDARAMUS , SCB_LUK ); - set_sc( AB_RENOVATIO , SC_RENOVATIO , SI_RENOVATIO , SCB_REGEN ); - set_sc( AB_EXPIATIO , SC_EXPIATIO , SI_EXPIATIO , SCB_ATK_ELE ); - set_sc( AB_DUPLELIGHT , SC_DUPLELIGHT , SI_DUPLELIGHT , SCB_NONE ); - set_sc( AB_SECRAMENT , SC_SECRAMENT , SI_SECRAMENT , SCB_NONE ); - set_sc( AB_OFFERTORIUM , SC_OFFERTORIUM , SI_OFFERTORIUM , SCB_NONE ); + set_sc_with_vfx( AB_ORATIO , SC_ORATIO , SCB_NONE ); + status->set_sc( AB_LAUDAAGNUS , SC_LAUDAAGNUS , SCB_VIT ); + status->set_sc( AB_LAUDARAMUS , SC_LAUDARAMUS , SCB_LUK ); + status->set_sc( AB_RENOVATIO , SC_RENOVATIO , SCB_REGEN ); + status->set_sc( AB_EXPIATIO , SC_EXPIATIO , SCB_ATK_ELE ); + status->set_sc( AB_DUPLELIGHT , SC_DUPLELIGHT , SCB_NONE ); + status->set_sc( AB_SECRAMENT , SC_SECRAMENT , SCB_NONE ); + status->set_sc( AB_OFFERTORIUM , SC_OFFERTORIUM , SCB_NONE ); /** * Warlock **/ add_sc( WL_WHITEIMPRISON , SC_WHITEIMPRISON ); - set_sc_with_vfx( WL_FROSTMISTY , SC_FROSTMISTY , SI_FROSTMISTY , SCB_ASPD|SCB_SPEED|SCB_DEF ); - set_sc( WL_MARSHOFABYSS , SC_MARSHOFABYSS , SI_MARSHOFABYSS , SCB_SPEED|SCB_FLEE|SCB_AGI|SCB_DEX ); - set_sc(WL_RECOGNIZEDSPELL , SC_RECOGNIZEDSPELL , SI_RECOGNIZEDSPELL , SCB_MATK); - set_sc( WL_STASIS , SC_STASIS , SI_STASIS , SCB_NONE ); - set_sc( WL_TELEKINESIS_INTENSE, SC_TELEKINESIS_INTENSE , SI_TELEKINESIS_INTENSE , SCB_MATK ); + set_sc_with_vfx( WL_FROSTMISTY , SC_FROSTMISTY , SCB_ASPD|SCB_SPEED|SCB_DEF ); + status->set_sc( WL_MARSHOFABYSS , SC_MARSHOFABYSS , SCB_SPEED|SCB_FLEE|SCB_AGI|SCB_DEX ); + status->set_sc(WL_RECOGNIZEDSPELL , SC_RECOGNIZEDSPELL , SCB_MATK); + status->set_sc( WL_STASIS , SC_STASIS , SCB_NONE ); + status->set_sc( WL_TELEKINESIS_INTENSE, SC_TELEKINESIS_INTENSE , SCB_MATK ); /** * Ranger **/ - set_sc( RA_FEARBREEZE , SC_FEARBREEZE , SI_FEARBREEZE , SCB_NONE ); - set_sc( RA_ELECTRICSHOCKER , SC_ELECTRICSHOCKER , SI_ELECTRICSHOCKER , SCB_NONE ); - set_sc( RA_WUGDASH , SC_WUGDASH , SI_WUGDASH , SCB_SPEED ); - set_sc( RA_CAMOUFLAGE , SC_CAMOUFLAGE , SI_CAMOUFLAGE , SCB_SPEED ); + status->set_sc( RA_FEARBREEZE , SC_FEARBREEZE , SCB_NONE ); + status->set_sc( RA_ELECTRICSHOCKER , SC_ELECTRICSHOCKER , SCB_NONE ); + status->set_sc( RA_WUGDASH , SC_WUGDASH , SCB_SPEED ); + status->set_sc( RA_CAMOUFLAGE , SC_CAMOUFLAGE , SCB_SPEED ); add_sc( RA_MAGENTATRAP , SC_ARMOR_PROPERTY ); add_sc( RA_COBALTTRAP , SC_ARMOR_PROPERTY ); add_sc( RA_MAIZETRAP , SC_ARMOR_PROPERTY ); add_sc( RA_VERDURETRAP , SC_ARMOR_PROPERTY ); add_sc( RA_FIRINGTRAP , SC_BURNING ); add_sc( RA_ICEBOUNDTRAP , SC_FROSTMISTY ); - set_sc( RA_UNLIMIT , SC_UNLIMIT , SI_UNLIMIT , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2 ); + status->set_sc( RA_UNLIMIT , SC_UNLIMIT , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2 ); /** * Mechanic **/ - set_sc( NC_ACCELERATION , SC_ACCELERATION , SI_ACCELERATION , SCB_SPEED ); - set_sc( NC_HOVERING , SC_HOVERING , SI_HOVERING , SCB_SPEED ); - set_sc( NC_SHAPESHIFT , SC_SHAPESHIFT , SI_SHAPESHIFT , SCB_DEF_ELE ); - set_sc( NC_INFRAREDSCAN , SC_INFRAREDSCAN , SI_INFRAREDSCAN , SCB_FLEE ); - set_sc( NC_ANALYZE , SC_ANALYZE , SI_ANALYZE , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2 ); - set_sc( NC_MAGNETICFIELD , SC_MAGNETICFIELD , SI_MAGNETICFIELD , SCB_NONE ); - set_sc( NC_NEUTRALBARRIER , SC_NEUTRALBARRIER , SI_NEUTRALBARRIER , SCB_DEF|SCB_MDEF ); - set_sc( NC_STEALTHFIELD , SC_STEALTHFIELD , SI_STEALTHFIELD , SCB_NONE ); + status->set_sc( NC_ACCELERATION , SC_ACCELERATION , SCB_SPEED ); + status->set_sc( NC_HOVERING , SC_HOVERING , SCB_SPEED ); + status->set_sc( NC_SHAPESHIFT , SC_SHAPESHIFT , SCB_DEF_ELE ); + status->set_sc( NC_INFRAREDSCAN , SC_INFRAREDSCAN , SCB_FLEE ); + status->set_sc( NC_ANALYZE , SC_ANALYZE , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2 ); + status->set_sc( NC_MAGNETICFIELD , SC_MAGNETICFIELD , SCB_NONE ); + status->set_sc( NC_NEUTRALBARRIER , SC_NEUTRALBARRIER , SCB_DEF|SCB_MDEF ); + status->set_sc( NC_STEALTHFIELD , SC_STEALTHFIELD , SCB_NONE ); /** * Royal Guard **/ - set_sc( LG_REFLECTDAMAGE , SC_LG_REFLECTDAMAGE , SI_LG_REFLECTDAMAGE, SCB_NONE ); - set_sc( LG_FORCEOFVANGUARD , SC_FORCEOFVANGUARD , SI_FORCEOFVANGUARD , SCB_MAXHP ); - set_sc( LG_EXEEDBREAK , SC_EXEEDBREAK , SI_EXEEDBREAK , SCB_NONE ); - set_sc( LG_PRESTIGE , SC_PRESTIGE , SI_PRESTIGE , SCB_DEF ); - set_sc( LG_BANDING , SC_BANDING , SI_BANDING , SCB_DEF2|SCB_WATK );// Renewal: atk2 & def2 - set_sc( LG_PIETY , SC_BENEDICTIO , SI_BENEDICTIO , SCB_DEF_ELE ); - set_sc( LG_EARTHDRIVE , SC_EARTHDRIVE , SI_EARTHDRIVE , SCB_DEF|SCB_ASPD ); - set_sc( LG_INSPIRATION , SC_INSPIRATION , SI_INSPIRATION , SCB_MAXHP|SCB_WATK|SCB_HIT|SCB_VIT|SCB_AGI|SCB_STR|SCB_DEX|SCB_INT|SCB_LUK); - set_sc( LG_KINGS_GRACE , SC_KINGS_GRACE , SI_KINGS_GRACE , SCB_NONE ); + status->set_sc( LG_REFLECTDAMAGE , SC_LG_REFLECTDAMAGE , SCB_NONE ); + status->set_sc( LG_FORCEOFVANGUARD , SC_FORCEOFVANGUARD , SCB_MAXHP ); + status->set_sc( LG_EXEEDBREAK , SC_EXEEDBREAK , SCB_NONE ); + status->set_sc( LG_PRESTIGE , SC_PRESTIGE , SCB_DEF ); + status->set_sc( LG_BANDING , SC_BANDING , SCB_DEF2|SCB_WATK );// Renewal: atk2 & def2 + status->set_sc( LG_PIETY , SC_BENEDICTIO , SCB_DEF_ELE ); + status->set_sc( LG_EARTHDRIVE , SC_EARTHDRIVE , SCB_DEF|SCB_ASPD ); + status->set_sc( LG_INSPIRATION , SC_INSPIRATION , SCB_MAXHP|SCB_WATK|SCB_HIT|SCB_VIT|SCB_AGI|SCB_STR|SCB_DEX|SCB_INT|SCB_LUK); + status->set_sc( LG_KINGS_GRACE , SC_KINGS_GRACE , SCB_NONE ); /** * Shadow Chaser **/ - set_sc( SC_REPRODUCE , SC__REPRODUCE , SI_REPRODUCE , SCB_NONE ); - set_sc( SC_AUTOSHADOWSPELL , SC__AUTOSHADOWSPELL, SI_AUTOSHADOWSPELL , SCB_NONE ); - set_sc( SC_SHADOWFORM , SC__SHADOWFORM , SI_SHADOWFORM , SCB_NONE ); - set_sc( SC_BODYPAINT , SC__BODYPAINT , SI_BODYPAINT , SCB_ASPD ); - set_sc( SC_INVISIBILITY , SC__INVISIBILITY , SI_INVISIBILITY , SCB_ASPD|SCB_CRI|SCB_ATK_ELE ); - set_sc( SC_DEADLYINFECT , SC__DEADLYINFECT , SI_DEADLYINFECT , SCB_NONE ); - set_sc( SC_ENERVATION , SC__ENERVATION , SI_ENERVATION , SCB_BATK ); - set_sc( SC_GROOMY , SC__GROOMY , SI_GROOMY , SCB_ASPD|SCB_HIT|SCB_SPEED ); - set_sc( SC_IGNORANCE , SC__IGNORANCE , SI_IGNORANCE , SCB_NONE ); - set_sc( SC_LAZINESS , SC__LAZINESS , SI_LAZINESS , SCB_FLEE ); - set_sc( SC_UNLUCKY , SC__UNLUCKY , SI_UNLUCKY , SCB_CRI|SCB_FLEE2 ); - set_sc( SC_WEAKNESS , SC__WEAKNESS , SI_WEAKNESS , SCB_FLEE2|SCB_MAXHP ); - set_sc( SC_STRIPACCESSARY , SC__STRIPACCESSARY , SI_STRIPACCESSARY , SCB_DEX|SCB_INT|SCB_LUK ); - set_sc_with_vfx( SC_MANHOLE , SC__MANHOLE , SI_MANHOLE , SCB_NONE ); + status->set_sc( SC_REPRODUCE , SC__REPRODUCE , SCB_NONE ); + status->set_sc( SC_AUTOSHADOWSPELL , SC__AUTOSHADOWSPELL, SCB_NONE ); + status->set_sc( SC_SHADOWFORM , SC__SHADOWFORM , SCB_NONE ); + status->set_sc( SC_BODYPAINT , SC__BODYPAINT , SCB_ASPD ); + status->set_sc( SC_INVISIBILITY , SC__INVISIBILITY , SCB_ASPD|SCB_CRI|SCB_ATK_ELE ); + status->set_sc( SC_DEADLYINFECT , SC__DEADLYINFECT , SCB_NONE ); + status->set_sc( SC_ENERVATION , SC__ENERVATION , SCB_BATK ); + status->set_sc( SC_GROOMY , SC__GROOMY , SCB_ASPD|SCB_HIT|SCB_SPEED ); + status->set_sc( SC_IGNORANCE , SC__IGNORANCE , SCB_NONE ); + status->set_sc( SC_LAZINESS , SC__LAZINESS , SCB_FLEE ); + status->set_sc( SC_UNLUCKY , SC__UNLUCKY , SCB_CRI|SCB_FLEE2 ); + status->set_sc( SC_WEAKNESS , SC__WEAKNESS , SCB_FLEE2|SCB_MAXHP ); + status->set_sc( SC_STRIPACCESSARY , SC__STRIPACCESSARY , SCB_DEX|SCB_INT|SCB_LUK ); + set_sc_with_vfx( SC_MANHOLE , SC__MANHOLE , SCB_NONE ); add_sc( SC_CHAOSPANIC , SC__CHAOS ); add_sc( SC_MAELSTROM , SC__MAELSTROM ); add_sc( SC_BLOODYLUST , SC_BERSERK ); @@ -656,113 +665,132 @@ 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 ); - set_sc( SR_RAISINGDRAGON , SC_RAISINGDRAGON , SI_RAISINGDRAGON , SCB_REGEN|SCB_MAXHP|SCB_MAXSP ); - 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_DEF2|SCB_REGEN ); - set_sc( SR_FLASHCOMBO , SC_FLASHCOMBO , SI_FLASHCOMBO , SCB_WATK ); + status->set_sc( SR_FALLENEMPIRE , SC_FALLENEMPIRE , SCB_NONE ); + status->set_sc( SR_CRESCENTELBOW , SC_CRESCENTELBOW , SCB_NONE ); + set_sc_with_vfx( SR_CURSEDCIRCLE , SC_CURSEDCIRCLE_TARGET, SCB_NONE ); + status->set_sc( SR_LIGHTNINGWALK , SC_LIGHTNINGWALK , SCB_NONE ); + status->set_sc( SR_RAISINGDRAGON , SC_RAISINGDRAGON , SCB_REGEN|SCB_MAXHP|SCB_MAXSP ); + status->set_sc( SR_GENTLETOUCH_ENERGYGAIN, SC_GENTLETOUCH_ENERGYGAIN , SCB_NONE ); + status->set_sc( SR_GENTLETOUCH_CHANGE , SC_GENTLETOUCH_CHANGE , SCB_ASPD|SCB_MDEF|SCB_MAXHP ); + status->set_sc( SR_GENTLETOUCH_REVITALIZE, SC_GENTLETOUCH_REVITALIZE , SCB_MAXHP|SCB_DEF2|SCB_REGEN ); + status->set_sc( SR_FLASHCOMBO , SC_FLASHCOMBO , SCB_WATK ); /** * Wanderer / Minstrel **/ - set_sc( WA_SWING_DANCE , SC_SWING , SI_SWINGDANCE , SCB_SPEED|SCB_ASPD ); - set_sc( WA_SYMPHONY_OF_LOVER , SC_SYMPHONY_LOVE , SI_SYMPHONYOFLOVERS , SCB_MDEF ); - set_sc( WA_MOONLIT_SERENADE , SC_MOONLIT_SERENADE , SI_MOONLITSERENADE , SCB_MATK ); - set_sc( MI_RUSH_WINDMILL , SC_RUSH_WINDMILL , SI_RUSHWINDMILL , SCB_WATK ); - set_sc( MI_ECHOSONG , SC_ECHOSONG , SI_ECHOSONG , SCB_DEF2 ); - set_sc( MI_HARMONIZE , SC_HARMONIZE , SI_HARMONIZE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); - set_sc_with_vfx(WM_POEMOFNETHERWORLD, SC_NETHERWORLD , SI_NETHERWORLD , SCB_NONE); - set_sc_with_vfx( WM_VOICEOFSIREN , SC_SIREN , SI_SIREN , SCB_NONE ); - set_sc_with_vfx( WM_LULLABY_DEEPSLEEP , SC_DEEP_SLEEP , SI_DEEPSLEEP , SCB_NONE ); - set_sc( WM_SIRCLEOFNATURE , SC_SIRCLEOFNATURE , SI_SIRCLEOFNATURE , SCB_NONE ); - set_sc( WM_GLOOMYDAY , SC_GLOOMYDAY , SI_GLOOMYDAY , SCB_FLEE|SCB_ASPD ); - set_sc( WM_SONG_OF_MANA , SC_SONG_OF_MANA , SI_SONG_OF_MANA , SCB_NONE ); - set_sc( WM_DANCE_WITH_WUG , SC_DANCE_WITH_WUG , SI_DANCEWITHWUG , SCB_ASPD ); - set_sc( WM_SATURDAY_NIGHT_FEVER , SC_SATURDAY_NIGHT_FEVER , SI_SATURDAYNIGHTFEVER , SCB_BATK|SCB_DEF|SCB_FLEE|SCB_REGEN ); - set_sc( WM_LERADS_DEW , SC_LERADS_DEW , SI_LERADSDEW , SCB_MAXHP ); - set_sc( WM_MELODYOFSINK , SC_MELODYOFSINK , SI_MELODYOFSINK , SCB_INT ); - set_sc( WM_BEYOND_OF_WARCRY , SC_BEYOND_OF_WARCRY , SI_WARCRYOFBEYOND , SCB_STR|SCB_CRI|SCB_MAXHP ); - set_sc( WM_UNLIMITED_HUMMING_VOICE, SC_UNLIMITED_HUMMING_VOICE, SI_UNLIMITEDHUMMINGVOICE, SCB_NONE ); - set_sc( WM_FRIGG_SONG , SC_FRIGG_SONG , SI_FRIGG_SONG , SCB_MAXHP ); + status->set_sc( WA_SWING_DANCE , SC_SWING , SCB_SPEED|SCB_ASPD ); + status->set_sc( WA_SYMPHONY_OF_LOVER , SC_SYMPHONY_LOVE , SCB_MDEF ); + status->set_sc( WA_MOONLIT_SERENADE , SC_MOONLIT_SERENADE , SCB_MATK ); + status->set_sc( MI_RUSH_WINDMILL , SC_RUSH_WINDMILL , SCB_WATK ); + status->set_sc( MI_ECHOSONG , SC_ECHOSONG , SCB_DEF2 ); + status->set_sc( MI_HARMONIZE , SC_HARMONIZE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); + set_sc_with_vfx(WM_POEMOFNETHERWORLD, SC_NETHERWORLD , SCB_NONE); + set_sc_with_vfx( WM_VOICEOFSIREN , SC_SIREN , SCB_NONE ); + set_sc_with_vfx( WM_LULLABY_DEEPSLEEP , SC_DEEP_SLEEP , SCB_NONE ); + status->set_sc( WM_SIRCLEOFNATURE , SC_SIRCLEOFNATURE , SCB_NONE ); + status->set_sc( WM_GLOOMYDAY , SC_GLOOMYDAY , SCB_FLEE|SCB_ASPD ); + status->set_sc( WM_SONG_OF_MANA , SC_SONG_OF_MANA , SCB_NONE ); + status->set_sc( WM_DANCE_WITH_WUG , SC_DANCE_WITH_WUG , SCB_ASPD ); + status->set_sc( WM_SATURDAY_NIGHT_FEVER , SC_SATURDAY_NIGHT_FEVER , SCB_BATK|SCB_DEF|SCB_FLEE|SCB_REGEN ); + status->set_sc( WM_LERADS_DEW , SC_LERADS_DEW , SCB_MAXHP ); + status->set_sc( WM_MELODYOFSINK , SC_MELODYOFSINK , SCB_INT ); + status->set_sc( WM_BEYOND_OF_WARCRY , SC_BEYOND_OF_WARCRY , SCB_STR|SCB_CRI|SCB_MAXHP ); + status->set_sc( WM_UNLIMITED_HUMMING_VOICE, SC_UNLIMITED_HUMMING_VOICE, SCB_NONE ); + status->set_sc( WM_FRIGG_SONG , SC_FRIGG_SONG , SCB_MAXHP ); + status->set_sc( WM_SEVERE_RAINSTORM , SC_NO_SWITCH_EQUIP , SCB_NONE ); /** * Sorcerer **/ - 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_with_vfx( SO_DIAMONDDUST , SC_COLD , 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 ); + status->set_sc( SO_FIREWALK , SC_PROPERTYWALK , SCB_NONE ); + status->set_sc( SO_ELECTRICWALK , SC_PROPERTYWALK , SCB_NONE ); + status->set_sc( SO_SPELLFIST , SC_SPELLFIST , SCB_NONE ); + set_sc_with_vfx( SO_DIAMONDDUST , SC_COLD , SCB_NONE ); // it does show the snow icon on mobs but doesn't affect it. + status->set_sc( SO_CLOUD_KILL , SC_POISON , SCB_NONE ); + status->set_sc( SO_STRIKING , SC_STRIKING , SCB_WATK|SCB_CRI ); add_sc( SO_WARMER , SC_WARMER ); // At the moment, no icon on officials - set_sc( SO_VACUUM_EXTREME , SC_VACUUM_EXTREME , SI_VACUUM_EXTREME , SCB_NONE ); - set_sc( SO_ARRULLO , SC_DEEP_SLEEP , SI_DEEPSLEEP , SCB_NONE ); - set_sc( SO_FIRE_INSIGNIA , SC_FIRE_INSIGNIA , SI_FIRE_INSIGNIA , SCB_MATK | SCB_BATK | SCB_WATK | SCB_ATK_ELE | SCB_REGEN ); - set_sc( SO_WATER_INSIGNIA , SC_WATER_INSIGNIA , SI_WATER_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN ); - set_sc( SO_WIND_INSIGNIA , SC_WIND_INSIGNIA , SI_WIND_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN ); - set_sc( SO_EARTH_INSIGNIA , SC_EARTH_INSIGNIA , SI_EARTH_INSIGNIA , SCB_MDEF|SCB_DEF|SCB_MAXHP|SCB_MAXSP|SCB_WATK | SCB_ATK_ELE | SCB_REGEN ); + status->set_sc( SO_VACUUM_EXTREME , SC_VACUUM_EXTREME , SCB_NONE ); + status->set_sc( SO_ARRULLO , SC_DEEP_SLEEP , SCB_NONE ); + status->set_sc( SO_FIRE_INSIGNIA , SC_FIRE_INSIGNIA , SCB_MATK | SCB_BATK | SCB_WATK | SCB_ATK_ELE | SCB_REGEN ); + status->set_sc( SO_WATER_INSIGNIA , SC_WATER_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN ); + status->set_sc( SO_WIND_INSIGNIA , SC_WIND_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN ); + status->set_sc( SO_EARTH_INSIGNIA , SC_EARTH_INSIGNIA , SCB_MDEF|SCB_DEF|SCB_MAXHP|SCB_MAXSP|SCB_WATK | SCB_ATK_ELE | SCB_REGEN ); add_sc( SO_ELEMENTAL_SHIELD , SC_SAFETYWALL ); /** * Genetic **/ - set_sc( GN_CARTBOOST , SC_GN_CARTBOOST, SI_CARTSBOOST , SCB_SPEED ); - set_sc( GN_THORNS_TRAP , SC_THORNS_TRAP , SI_THORNTRAP , SCB_NONE ); - set_sc_with_vfx( GN_BLOOD_SUCKER , SC_BLOOD_SUCKER , SI_BLOODSUCKER , SCB_NONE ); - set_sc( GN_WALLOFTHORN , SC_STOP , SI_BLANK , SCB_NONE ); - set_sc( GN_FIRE_EXPANSION_SMOKE_POWDER, SC_FIRE_EXPANSION_SMOKE_POWDER , SI_FIRE_EXPANSION_SMOKE_POWDER, SCB_NONE ); - set_sc( GN_FIRE_EXPANSION_TEAR_GAS , SC_FIRE_EXPANSION_TEAR_GAS , SI_FIRE_EXPANSION_TEAR_GAS , SCB_NONE ); - set_sc( GN_MANDRAGORA , SC_MANDRAGORA , SI_MANDRAGORA , SCB_INT ); + status->set_sc( GN_CARTBOOST , SC_GN_CARTBOOST, SCB_SPEED ); + status->set_sc( GN_THORNS_TRAP , SC_THORNS_TRAP , SCB_NONE ); + set_sc_with_vfx( GN_BLOOD_SUCKER , SC_BLOOD_SUCKER , SCB_NONE ); + status->set_sc( GN_WALLOFTHORN , SC_STOP , SCB_NONE ); + status->set_sc( GN_FIRE_EXPANSION_SMOKE_POWDER, SC_FIRE_EXPANSION_SMOKE_POWDER , SCB_NONE ); + status->set_sc( GN_FIRE_EXPANSION_TEAR_GAS , SC_FIRE_EXPANSION_TEAR_GAS , SCB_NONE ); + status->set_sc( GN_MANDRAGORA , SC_MANDRAGORA , SCB_INT ); + + /** + * Summoner + */ + status->set_sc(SU_HIDE, SC_SUHIDE, SCB_SPEED); + add_sc(SU_SCRATCH, SC_BLOODING); + status->set_sc(SU_STOOP, SC_SU_STOOP, SCB_NONE); + status->set_sc(SU_FRESHSHRIMP, SC_FRESHSHRIMP, SCB_NONE); + add_sc(SU_SV_STEMSPEAR, SC_BLOODING); + status->set_sc(SU_CN_POWDERING, SC_CATNIPPOWDER, SCB_WATK | SCB_SPEED | SCB_REGEN); + add_sc(SU_CN_METEOR, SC_CURSE); + set_sc_with_vfx(SU_SV_ROOTTWIST, SC_SV_ROOTTWIST, SCB_NONE); + add_sc(SU_SCAROFTAROU, SC_STUN ); + status->set_sc(SU_SCAROFTAROU, SC_BITESCAR, SCB_NONE); + status->set_sc(SU_ARCLOUSEDASH, SC_ARCLOUSEDASH, SCB_AGI | SCB_SPEED); + add_sc(SU_LUNATICCARROTBEAT, SC_STUN); + status->set_sc(SU_TUNAPARTY, SC_TUNAPARTY, SCB_NONE); + status->set_sc(SU_BUNCHOFSHRIMP, SC_SHRIMP, SCB_BATK | SCB_MATK); // Elemental Spirit summoner's 'side' status changes. - set_sc( EL_CIRCLE_OF_FIRE , SC_CIRCLE_OF_FIRE_OPTION, SI_CIRCLE_OF_FIRE_OPTION, SCB_NONE ); - set_sc( EL_FIRE_CLOAK , SC_FIRE_CLOAK_OPTION , SI_FIRE_CLOAK_OPTION , SCB_ALL ); - set_sc( EL_WATER_SCREEN , SC_WATER_SCREEN_OPTION , SI_WATER_SCREEN_OPTION , SCB_NONE ); - set_sc( EL_WATER_DROP , SC_WATER_DROP_OPTION , SI_WATER_DROP_OPTION , SCB_ALL ); - set_sc( EL_WATER_BARRIER , SC_WATER_BARRIER , SI_WATER_BARRIER , SCB_WATK|SCB_FLEE ); - set_sc( EL_WIND_STEP , SC_WIND_STEP_OPTION , SI_WIND_STEP_OPTION , SCB_SPEED|SCB_FLEE ); - set_sc( EL_WIND_CURTAIN , SC_WIND_CURTAIN_OPTION , SI_WIND_CURTAIN_OPTION , SCB_ALL ); - set_sc( EL_ZEPHYR , SC_ZEPHYR , SI_ZEPHYR , SCB_FLEE ); - set_sc( EL_SOLID_SKIN , SC_SOLID_SKIN_OPTION , SI_SOLID_SKIN_OPTION , SCB_DEF|SCB_MAXHP ); - set_sc( EL_STONE_SHIELD , SC_STONE_SHIELD_OPTION , SI_STONE_SHIELD_OPTION , SCB_ALL ); - set_sc( EL_POWER_OF_GAIA , SC_POWER_OF_GAIA , SI_POWER_OF_GAIA , SCB_MAXHP|SCB_DEF|SCB_SPEED ); - set_sc( EL_PYROTECHNIC , SC_PYROTECHNIC_OPTION , SI_PYROTECHNIC_OPTION , SCB_WATK ); - set_sc( EL_HEATER , SC_HEATER_OPTION , SI_HEATER_OPTION , SCB_WATK ); - set_sc( EL_TROPIC , SC_TROPIC_OPTION , SI_TROPIC_OPTION , SCB_WATK ); - set_sc( EL_AQUAPLAY , SC_AQUAPLAY_OPTION , SI_AQUAPLAY_OPTION , SCB_MATK ); - set_sc( EL_COOLER , SC_COOLER_OPTION , SI_COOLER_OPTION , SCB_MATK ); - set_sc( EL_CHILLY_AIR , SC_CHILLY_AIR_OPTION , SI_CHILLY_AIR_OPTION , SCB_MATK ); - set_sc( EL_GUST , SC_GUST_OPTION , SI_GUST_OPTION , SCB_ASPD ); - set_sc( EL_BLAST , SC_BLAST_OPTION , SI_BLAST_OPTION , SCB_ASPD ); - set_sc( EL_WILD_STORM , SC_WILD_STORM_OPTION , SI_WILD_STORM_OPTION , SCB_ASPD ); - set_sc( EL_PETROLOGY , SC_PETROLOGY_OPTION , SI_PETROLOGY_OPTION , SCB_MAXHP ); - set_sc( EL_CURSED_SOIL , SC_CURSED_SOIL_OPTION , SI_CURSED_SOIL_OPTION , SCB_MAXHP ); - set_sc( EL_UPHEAVAL , SC_UPHEAVAL_OPTION , SI_UPHEAVAL_OPTION , SCB_MAXHP ); - set_sc( EL_TIDAL_WEAPON , SC_TIDAL_WEAPON_OPTION , SI_TIDAL_WEAPON_OPTION , SCB_ALL ); - set_sc( EL_ROCK_CRUSHER , SC_ROCK_CRUSHER , SI_ROCK_CRUSHER , SCB_DEF ); - set_sc( EL_ROCK_CRUSHER_ATK, SC_ROCK_CRUSHER_ATK , SI_ROCK_CRUSHER_ATK , SCB_SPEED ); + status->set_sc( EL_CIRCLE_OF_FIRE , SC_CIRCLE_OF_FIRE_OPTION, SCB_NONE ); + status->set_sc( EL_FIRE_CLOAK , SC_FIRE_CLOAK_OPTION , SCB_ALL ); + status->set_sc( EL_WATER_SCREEN , SC_WATER_SCREEN_OPTION , SCB_NONE ); + status->set_sc( EL_WATER_DROP , SC_WATER_DROP_OPTION , SCB_ALL ); + status->set_sc( EL_WATER_BARRIER , SC_WATER_BARRIER , SCB_WATK|SCB_FLEE ); + status->set_sc( EL_WIND_STEP , SC_WIND_STEP_OPTION , SCB_SPEED|SCB_FLEE ); + status->set_sc( EL_WIND_CURTAIN , SC_WIND_CURTAIN_OPTION , SCB_ALL ); + status->set_sc( EL_ZEPHYR , SC_ZEPHYR , SCB_FLEE ); + status->set_sc( EL_SOLID_SKIN , SC_SOLID_SKIN_OPTION , SCB_DEF|SCB_MAXHP ); + status->set_sc( EL_STONE_SHIELD , SC_STONE_SHIELD_OPTION , SCB_ALL ); + status->set_sc( EL_POWER_OF_GAIA , SC_POWER_OF_GAIA , SCB_MAXHP|SCB_DEF|SCB_SPEED ); + status->set_sc( EL_PYROTECHNIC , SC_PYROTECHNIC_OPTION , SCB_WATK ); + status->set_sc( EL_HEATER , SC_HEATER_OPTION , SCB_WATK ); + status->set_sc( EL_TROPIC , SC_TROPIC_OPTION , SCB_WATK ); + status->set_sc( EL_AQUAPLAY , SC_AQUAPLAY_OPTION , SCB_MATK ); + status->set_sc( EL_COOLER , SC_COOLER_OPTION , SCB_MATK ); + status->set_sc( EL_CHILLY_AIR , SC_CHILLY_AIR_OPTION , SCB_MATK ); + status->set_sc( EL_GUST , SC_GUST_OPTION , SCB_ASPD ); + status->set_sc( EL_BLAST , SC_BLAST_OPTION , SCB_ASPD ); + status->set_sc( EL_WILD_STORM , SC_WILD_STORM_OPTION , SCB_ASPD ); + status->set_sc( EL_PETROLOGY , SC_PETROLOGY_OPTION , SCB_MAXHP ); + status->set_sc( EL_CURSED_SOIL , SC_CURSED_SOIL_OPTION , SCB_MAXHP ); + status->set_sc( EL_UPHEAVAL , SC_UPHEAVAL_OPTION , SCB_MAXHP ); + status->set_sc( EL_TIDAL_WEAPON , SC_TIDAL_WEAPON_OPTION , SCB_ALL ); + status->set_sc( EL_ROCK_CRUSHER , SC_ROCK_CRUSHER , SCB_DEF ); + status->set_sc( EL_ROCK_CRUSHER_ATK, SC_ROCK_CRUSHER_ATK , SCB_SPEED ); add_sc( KO_YAMIKUMO , SC_HIDING ); - set_sc_with_vfx( KO_JYUMONJIKIRI , SC_KO_JYUMONJIKIRI , SI_KO_JYUMONJIKIRI , SCB_NONE ); + set_sc_with_vfx( KO_JYUMONJIKIRI , SC_KO_JYUMONJIKIRI , SCB_NONE ); add_sc( KO_MAKIBISHI , SC_STUN ); - set_sc( KO_MEIKYOUSISUI , SC_MEIKYOUSISUI , SI_MEIKYOUSISUI , SCB_NONE ); - set_sc( KO_KYOUGAKU , SC_KYOUGAKU , SI_KYOUGAKU , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); + status->set_sc( KO_MEIKYOUSISUI , SC_MEIKYOUSISUI , SCB_NONE ); + status->set_sc( KO_KYOUGAKU , SC_KYOUGAKU , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); add_sc( KO_JYUSATSU , SC_CURSE ); - set_sc( KO_ZENKAI , SC_ZENKAI , SI_ZENKAI , SCB_NONE ); - set_sc( KO_IZAYOI , SC_IZAYOI , SI_IZAYOI , SCB_MATK ); - set_sc( KG_KYOMU , SC_KYOMU , SI_KYOMU , SCB_NONE ); - set_sc( KG_KAGEMUSYA , SC_KAGEMUSYA , SI_KAGEMUSYA , SCB_NONE ); - set_sc( KG_KAGEHUMI , SC_KG_KAGEHUMI , SI_KG_KAGEHUMI , SCB_NONE ); - set_sc( OB_ZANGETSU , SC_ZANGETSU , SI_ZANGETSU , SCB_MATK|SCB_BATK ); - set_sc_with_vfx( OB_AKAITSUKI, SC_AKAITSUKI , SI_AKAITSUKI , SCB_NONE ); - set_sc( OB_OBOROGENSOU , SC_GENSOU , SI_GENSOU , SCB_NONE ); + status->set_sc( KO_ZENKAI , SC_ZENKAI , SCB_NONE ); + status->set_sc( KO_IZAYOI , SC_IZAYOI , SCB_MATK ); + status->set_sc( KG_KYOMU , SC_KYOMU , SCB_NONE ); + status->set_sc( KG_KAGEMUSYA , SC_KAGEMUSYA , SCB_NONE ); + status->set_sc( KG_KAGEHUMI , SC_KG_KAGEHUMI , SCB_NONE ); + status->set_sc( OB_ZANGETSU , SC_ZANGETSU , SCB_MATK|SCB_BATK ); + set_sc_with_vfx( OB_AKAITSUKI, SC_AKAITSUKI , SCB_NONE ); + status->set_sc( OB_OBOROGENSOU , SC_GENSOU , SCB_NONE ); - set_sc( ALL_FULL_THROTTLE , SC_FULL_THROTTLE , SI_FULL_THROTTLE , SCB_SPEED|SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); + status->set_sc( ALL_FULL_THROTTLE , SC_FULL_THROTTLE , SCB_SPEED|SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK ); add_sc( ALL_REVERSEORCISH , SC_ORCISH ); - set_sc( ALL_ANGEL_PROTECT , SC_ANGEL_PROTECT , SI_ANGEL_PROTECT , SCB_REGEN ); + status->set_sc( ALL_ANGEL_PROTECT , SC_ANGEL_PROTECT , SCB_REGEN ); add_sc( NPC_WIDEHEALTHFEAR , SC_FEAR ); add_sc( NPC_WIDEBODYBURNNING , SC_BURNING ); @@ -771,228 +799,24 @@ void initChangeTables(void) { add_sc( NPC_WIDE_DEEP_SLEEP , SC_DEEP_SLEEP ); add_sc( NPC_WIDESIREN , SC_SIREN ); - set_sc_with_vfx( GN_ILLUSIONDOPING , SC_ILLUSIONDOPING , SI_ILLUSIONDOPING , SCB_HIT ); + set_sc_with_vfx( GN_ILLUSIONDOPING , SC_ILLUSIONDOPING , SCB_HIT ); // Storing the target job rather than simply SC_SOULLINK simplifies code later on. - status->dbs->Skill2SCTable[SL_ALCHEMIST] = (sc_type)MAPID_ALCHEMIST, - status->dbs->Skill2SCTable[SL_MONK] = (sc_type)MAPID_MONK, - status->dbs->Skill2SCTable[SL_STAR] = (sc_type)MAPID_STAR_GLADIATOR, - status->dbs->Skill2SCTable[SL_SAGE] = (sc_type)MAPID_SAGE, - status->dbs->Skill2SCTable[SL_CRUSADER] = (sc_type)MAPID_CRUSADER, - status->dbs->Skill2SCTable[SL_SUPERNOVICE] = (sc_type)MAPID_SUPER_NOVICE, - status->dbs->Skill2SCTable[SL_KNIGHT] = (sc_type)MAPID_KNIGHT, - status->dbs->Skill2SCTable[SL_WIZARD] = (sc_type)MAPID_WIZARD, - status->dbs->Skill2SCTable[SL_PRIEST] = (sc_type)MAPID_PRIEST, - status->dbs->Skill2SCTable[SL_BARDDANCER] = (sc_type)MAPID_BARDDANCER, - status->dbs->Skill2SCTable[SL_ROGUE] = (sc_type)MAPID_ROGUE, - status->dbs->Skill2SCTable[SL_ASSASIN] = (sc_type)MAPID_ASSASSIN, - status->dbs->Skill2SCTable[SL_BLACKSMITH] = (sc_type)MAPID_BLACKSMITH, - status->dbs->Skill2SCTable[SL_HUNTER] = (sc_type)MAPID_HUNTER, - status->dbs->Skill2SCTable[SL_SOULLINKER] = (sc_type)MAPID_SOUL_LINKER, - - // Status that don't have a skill associated. - status->dbs->IconChangeTable[SC_WEIGHTOVER50] = SI_WEIGHTOVER50; - status->dbs->IconChangeTable[SC_WEIGHTOVER90] = SI_WEIGHTOVER90; - status->dbs->IconChangeTable[SC_ATTHASTE_POTION1] = SI_ATTHASTE_POTION1; - status->dbs->IconChangeTable[SC_ATTHASTE_POTION2] = SI_ATTHASTE_POTION2; - status->dbs->IconChangeTable[SC_ATTHASTE_POTION3] = SI_ATTHASTE_POTION3; - status->dbs->IconChangeTable[SC_MOVHASTE_POTION] = SI_MOVHASTE_POTION; - status->dbs->IconChangeTable[SC_ATTHASTE_INFINITY] = SI_ATTHASTE_INFINITY; - status->dbs->IconChangeTable[SC_MOVHASTE_HORSE] = SI_MOVHASTE_HORSE; - status->dbs->IconChangeTable[SC_MOVHASTE_INFINITY] = SI_MOVHASTE_INFINITY; - status->dbs->IconChangeTable[SC_MOVESLOW_POTION] = SI_MOVESLOW_POTION; - status->dbs->IconChangeTable[SC_CHASEWALK2] = SI_INCSTR; - status->dbs->IconChangeTable[SC_MIRACLE] = SI_SOULLINK; - status->dbs->IconChangeTable[SC_CLAIRVOYANCE] = SI_CLAIRVOYANCE; - status->dbs->IconChangeTable[SC_FOOD_STR] = SI_FOOD_STR; - status->dbs->IconChangeTable[SC_FOOD_AGI] = SI_FOOD_AGI; - status->dbs->IconChangeTable[SC_FOOD_VIT] = SI_FOOD_VIT; - status->dbs->IconChangeTable[SC_FOOD_INT] = SI_FOOD_INT; - status->dbs->IconChangeTable[SC_FOOD_DEX] = SI_FOOD_DEX; - status->dbs->IconChangeTable[SC_FOOD_LUK] = SI_FOOD_LUK; - status->dbs->IconChangeTable[SC_FOOD_BASICAVOIDANCE]= SI_FOOD_BASICAVOIDANCE; - status->dbs->IconChangeTable[SC_FOOD_BASICHIT] = SI_FOOD_BASICHIT; - status->dbs->IconChangeTable[SC_MANU_ATK] = SI_MANU_ATK; - status->dbs->IconChangeTable[SC_MANU_DEF] = SI_MANU_DEF; - status->dbs->IconChangeTable[SC_SPL_ATK] = SI_SPL_ATK; - status->dbs->IconChangeTable[SC_SPL_DEF] = SI_SPL_DEF; - status->dbs->IconChangeTable[SC_MANU_MATK] = SI_MANU_MATK; - status->dbs->IconChangeTable[SC_SPL_MATK] = SI_SPL_MATK; - status->dbs->IconChangeTable[SC_PLUSATTACKPOWER] = SI_PLUSATTACKPOWER; - status->dbs->IconChangeTable[SC_PLUSMAGICPOWER] = SI_PLUSMAGICPOWER; - status->dbs->IconChangeTable[SC_FOOD_CRITICALSUCCESSVALUE] = SI_FOOD_CRITICALSUCCESSVALUE; - status->dbs->IconChangeTable[SC_MORA_BUFF] = SI_MORA_BUFF; - status->dbs->IconChangeTable[SC_BUCHEDENOEL] = SI_BUCHEDENOEL; - status->dbs->IconChangeTable[SC_PHI_DEMON] = SI_PHI_DEMON; - - // Cash Items - status->dbs->IconChangeTable[SC_FOOD_STR_CASH] = SI_FOOD_STR_CASH; - status->dbs->IconChangeTable[SC_FOOD_AGI_CASH] = SI_FOOD_AGI_CASH; - status->dbs->IconChangeTable[SC_FOOD_VIT_CASH] = SI_FOOD_VIT_CASH; - status->dbs->IconChangeTable[SC_FOOD_DEX_CASH] = SI_FOOD_DEX_CASH; - status->dbs->IconChangeTable[SC_FOOD_INT_CASH] = SI_FOOD_INT_CASH; - status->dbs->IconChangeTable[SC_FOOD_LUK_CASH] = SI_FOOD_LUK_CASH; - status->dbs->IconChangeTable[SC_CASH_PLUSEXP] = SI_CASH_PLUSEXP; - status->dbs->IconChangeTable[SC_CASH_RECEIVEITEM] = SI_CASH_RECEIVEITEM; - status->dbs->IconChangeTable[SC_CASH_PLUSONLYJOBEXP] = SI_CASH_PLUSONLYJOBEXP; - status->dbs->IconChangeTable[SC_CASH_DEATHPENALTY] = SI_CASH_DEATHPENALTY; - status->dbs->IconChangeTable[SC_CASH_BOSS_ALARM] = SI_CASH_BOSS_ALARM; - status->dbs->IconChangeTable[SC_PROTECT_DEF] = SI_PROTECT_DEF; - status->dbs->IconChangeTable[SC_PROTECT_MDEF] = SI_PROTECT_MDEF; - status->dbs->IconChangeTable[SC_CRITICALPERCENT] = SI_CRITICALPERCENT; - status->dbs->IconChangeTable[SC_PLUSAVOIDVALUE] = SI_PLUSAVOIDVALUE; - status->dbs->IconChangeTable[SC_HEALPLUS] = SI_HEALPLUS; - status->dbs->IconChangeTable[SC_S_LIFEPOTION] = SI_S_LIFEPOTION; - status->dbs->IconChangeTable[SC_L_LIFEPOTION] = SI_L_LIFEPOTION; - status->dbs->IconChangeTable[SC_ATKER_BLOOD] = SI_ATKER_BLOOD; - status->dbs->IconChangeTable[SC_TARGET_BLOOD] = SI_TARGET_BLOOD; - status->dbs->IconChangeTable[SC_ACARAJE] = SI_ACARAJE; - status->dbs->IconChangeTable[SC_TARGET_ASPD] = SI_TARGET_ASPD; - status->dbs->IconChangeTable[SC_ATKER_ASPD] = SI_ATKER_ASPD; - status->dbs->IconChangeTable[SC_ATKER_MOVESPEED] = SI_ATKER_MOVESPEED; - status->dbs->IconChangeTable[SC_CUP_OF_BOZA] = SI_CUP_OF_BOZA; - status->dbs->IconChangeTable[SC_OVERLAPEXPUP] = SI_OVERLAPEXPUP; - status->dbs->IconChangeTable[SC_GM_BATTLE] = SI_GM_BATTLE; - status->dbs->IconChangeTable[SC_GM_BATTLE2] = SI_GM_BATTLE2; - status->dbs->IconChangeTable[SC_2011RWC] = SI_2011RWC; - status->dbs->IconChangeTable[SC_STR_SCROLL] = SI_STR_SCROLL; - status->dbs->IconChangeTable[SC_INT_SCROLL] = SI_INT_SCROLL; - status->dbs->IconChangeTable[SC_STEAMPACK] = SI_STEAMPACK; - status->dbs->IconChangeTable[SC_MAGIC_CANDY] = SI_MAGIC_CANDY; - status->dbs->IconChangeTable[SC_M_LIFEPOTION] = SI_M_LIFEPOTION; - status->dbs->IconChangeTable[SC_G_LIFEPOTION] = SI_G_LIFEPOTION; - status->dbs->IconChangeTable[SC_MYSTICPOWDER] = SI_MYSTICPOWDER; - - // Eden Crystal Synthesis - status->dbs->IconChangeTable[SC_QUEST_BUFF1] = SI_QUEST_BUFF1; - status->dbs->IconChangeTable[SC_QUEST_BUFF2] = SI_QUEST_BUFF2; - status->dbs->IconChangeTable[SC_QUEST_BUFF3] = SI_QUEST_BUFF3; - - // Geffen Magic Tournament - status->dbs->IconChangeTable[SC_GEFFEN_MAGIC1] = SI_GEFFEN_MAGIC1; - status->dbs->IconChangeTable[SC_GEFFEN_MAGIC2] = SI_GEFFEN_MAGIC2; - status->dbs->IconChangeTable[SC_GEFFEN_MAGIC3] = SI_GEFFEN_MAGIC3; - status->dbs->IconChangeTable[SC_FENRIR_CARD] = SI_FENRIR_CARD; - - // MVP Scrolls - status->dbs->IconChangeTable[SC_MVPCARD_TAOGUNKA] = SI_MVPCARD_TAOGUNKA; - status->dbs->IconChangeTable[SC_MVPCARD_MISTRESS] = SI_MVPCARD_MISTRESS; - status->dbs->IconChangeTable[SC_MVPCARD_ORCHERO] = SI_MVPCARD_ORCHERO; - status->dbs->IconChangeTable[SC_MVPCARD_ORCLORD] = SI_MVPCARD_ORCLORD; - - // Mercenary Bonus Effects - status->dbs->IconChangeTable[SC_MER_FLEE] = SI_MER_FLEE; - status->dbs->IconChangeTable[SC_MER_ATK] = SI_MER_ATK; - status->dbs->IconChangeTable[SC_MER_HP] = SI_MER_HP; - status->dbs->IconChangeTable[SC_MER_SP] = SI_MER_SP; - status->dbs->IconChangeTable[SC_MER_HIT] = SI_MER_HIT; - - // Warlock Spheres - status->dbs->IconChangeTable[SC_SUMMON1] = SI_SPHERE_1; - status->dbs->IconChangeTable[SC_SUMMON2] = SI_SPHERE_2; - status->dbs->IconChangeTable[SC_SUMMON3] = SI_SPHERE_3; - status->dbs->IconChangeTable[SC_SUMMON4] = SI_SPHERE_4; - status->dbs->IconChangeTable[SC_SUMMON5] = SI_SPHERE_5; - - // Warlock Preserved spells - status->dbs->IconChangeTable[SC_SPELLBOOK1] = SI_SPELLBOOK1; - status->dbs->IconChangeTable[SC_SPELLBOOK2] = SI_SPELLBOOK2; - status->dbs->IconChangeTable[SC_SPELLBOOK3] = SI_SPELLBOOK3; - status->dbs->IconChangeTable[SC_SPELLBOOK4] = SI_SPELLBOOK4; - status->dbs->IconChangeTable[SC_SPELLBOOK5] = SI_SPELLBOOK5; - status->dbs->IconChangeTable[SC_SPELLBOOK6] = SI_SPELLBOOK6; - status->dbs->IconChangeTable[SC_SPELLBOOK7] = SI_SPELLBOOK7; - - // Mechanic status icon - status->dbs->IconChangeTable[SC_NEUTRALBARRIER_MASTER] = SI_NEUTRALBARRIER_MASTER; - status->dbs->IconChangeTable[SC_STEALTHFIELD_MASTER] = SI_STEALTHFIELD_MASTER; - status->dbs->IconChangeTable[SC_OVERHEAT] = SI_OVERHEAT; - status->dbs->IconChangeTable[SC_OVERHEAT_LIMITPOINT] = SI_OVERHEAT_LIMITPOINT; - - // Guillotine Cross status icons - status->dbs->IconChangeTable[SC_HALLUCINATIONWALK_POSTDELAY] = SI_HALLUCINATIONWALK_POSTDELAY; - status->dbs->IconChangeTable[SC_TOXIN] = SI_TOXIN; - status->dbs->IconChangeTable[SC_PARALYSE] = SI_PARALYSE; - status->dbs->IconChangeTable[SC_VENOMBLEED] = SI_VENOMBLEED; - status->dbs->IconChangeTable[SC_MAGICMUSHROOM] = SI_MAGICMUSHROOM; - status->dbs->IconChangeTable[SC_DEATHHURT] = SI_DEATHHURT; - status->dbs->IconChangeTable[SC_PYREXIA] = SI_PYREXIA; - status->dbs->IconChangeTable[SC_OBLIVIONCURSE] = SI_OBLIVIONCURSE; - status->dbs->IconChangeTable[SC_LEECHESEND] = SI_LEECHESEND; - - // Royal Guard status icons - status->dbs->IconChangeTable[SC_SHIELDSPELL_DEF] = SI_SHIELDSPELL_DEF; - status->dbs->IconChangeTable[SC_SHIELDSPELL_MDEF] = SI_SHIELDSPELL_MDEF; - status->dbs->IconChangeTable[SC_SHIELDSPELL_REF] = SI_SHIELDSPELL_REF; - status->dbs->IconChangeTable[SC_BANDING_DEFENCE] = SI_BANDING_DEFENCE; - - // Sura status icon - status->dbs->IconChangeTable[SC_CURSEDCIRCLE_ATKER] = SI_CURSEDCIRCLE_ATKER; - - // Genetics Food items / Throwable items status icons - status->dbs->IconChangeTable[SC_SAVAGE_STEAK] = SI_SAVAGE_STEAK; - status->dbs->IconChangeTable[SC_COCKTAIL_WARG_BLOOD] = SI_COCKTAIL_WARG_BLOOD; - status->dbs->IconChangeTable[SC_MINOR_BBQ] = SI_MINOR_BBQ; - status->dbs->IconChangeTable[SC_SIROMA_ICE_TEA] = SI_SIROMA_ICE_TEA; - status->dbs->IconChangeTable[SC_DROCERA_HERB_STEAMED] = SI_DROCERA_HERB_STEAMED; - status->dbs->IconChangeTable[SC_PUTTI_TAILS_NOODLES] = SI_PUTTI_TAILS_NOODLES; - status->dbs->IconChangeTable[SC_BOOST500] |= SI_BOOST500; - status->dbs->IconChangeTable[SC_FULL_SWING_K] |= SI_FULL_SWING_K; - status->dbs->IconChangeTable[SC_MANA_PLUS] |= SI_MANA_PLUS; - status->dbs->IconChangeTable[SC_MUSTLE_M] |= SI_MUSTLE_M; - status->dbs->IconChangeTable[SC_LIFE_FORCE_F] |= SI_LIFE_FORCE_F; - status->dbs->IconChangeTable[SC_EXTRACT_WHITE_POTION_Z] |= SI_EXTRACT_WHITE_POTION_Z; - status->dbs->IconChangeTable[SC_VITATA_500] |= SI_VITATA_500; - status->dbs->IconChangeTable[SC_EXTRACT_SALAMINE_JUICE] |= SI_EXTRACT_SALAMINE_JUICE; - status->dbs->IconChangeTable[SC_STOMACHACHE] = SI_STOMACHACHE; - status->dbs->IconChangeTable[SC_MYSTERIOUS_POWDER] = SI_MYSTERIOUS_POWDER; - status->dbs->IconChangeTable[SC_MELON_BOMB] = SI_MELON_BOMB; - status->dbs->IconChangeTable[SC_BANANA_BOMB] = SI_BANANA_BOMB; - status->dbs->IconChangeTable[SC_BANANA_BOMB_SITDOWN_POSTDELAY] = SI_BANANA_BOMB_SITDOWN_POSTDELAY; - status->dbs->IconChangeTable[SC_PROMOTE_HEALTH_RESERCH] = SI_PROMOTE_HEALTH_RESERCH; - status->dbs->IconChangeTable[SC_ENERGY_DRINK_RESERCH] = SI_ENERGY_DRINK_RESERCH; - - // Elemental Spirit's 'side' status change icons. - status->dbs->IconChangeTable[SC_CIRCLE_OF_FIRE] = SI_CIRCLE_OF_FIRE; - status->dbs->IconChangeTable[SC_FIRE_CLOAK] = SI_FIRE_CLOAK; - status->dbs->IconChangeTable[SC_WATER_SCREEN] = SI_WATER_SCREEN; - status->dbs->IconChangeTable[SC_WATER_DROP] = SI_WATER_DROP; - status->dbs->IconChangeTable[SC_WIND_STEP] = SI_WIND_STEP; - status->dbs->IconChangeTable[SC_WIND_CURTAIN] = SI_WIND_CURTAIN; - status->dbs->IconChangeTable[SC_SOLID_SKIN] = SI_SOLID_SKIN; - status->dbs->IconChangeTable[SC_STONE_SHIELD] = SI_STONE_SHIELD; - status->dbs->IconChangeTable[SC_PYROTECHNIC] = SI_PYROTECHNIC; - status->dbs->IconChangeTable[SC_HEATER] = SI_HEATER; - status->dbs->IconChangeTable[SC_TROPIC] = SI_TROPIC; - status->dbs->IconChangeTable[SC_AQUAPLAY] = SI_AQUAPLAY; - status->dbs->IconChangeTable[SC_COOLER] = SI_COOLER; - status->dbs->IconChangeTable[SC_CHILLY_AIR] = SI_CHILLY_AIR; - status->dbs->IconChangeTable[SC_GUST] = SI_GUST; - status->dbs->IconChangeTable[SC_BLAST] = SI_BLAST; - status->dbs->IconChangeTable[SC_WILD_STORM] = SI_WILD_STORM; - status->dbs->IconChangeTable[SC_PETROLOGY] = SI_PETROLOGY; - status->dbs->IconChangeTable[SC_CURSED_SOIL] = SI_CURSED_SOIL; - status->dbs->IconChangeTable[SC_UPHEAVAL] = SI_UPHEAVAL; - status->dbs->IconChangeTable[SC_PUSH_CART] = SI_ON_PUSH_CART; - status->dbs->IconChangeTable[SC_REBOUND] = SI_REBOUND; - status->dbs->IconChangeTable[SC_ALL_RIDING] = SI_ALL_RIDING; - status->dbs->IconChangeTable[SC_MONSTER_TRANSFORM] = SI_MONSTER_TRANSFORM; - - // Costumes - status->dbs->IconChangeTable[SC_MOONSTAR] = SI_MOONSTAR; - status->dbs->IconChangeTable[SC_SUPER_STAR] = SI_SUPER_STAR; - status->dbs->IconChangeTable[SC_STRANGELIGHTS] = SI_STRANGELIGHTS; - status->dbs->IconChangeTable[SC_DECORATION_OF_MUSIC] = SI_DECORATION_OF_MUSIC; - status->dbs->IconChangeTable[SC_LJOSALFAR] = SI_LJOSALFAR; - status->dbs->IconChangeTable[SC_MERMAID_LONGING] = SI_MERMAID_LONGING; - status->dbs->IconChangeTable[SC_HAT_EFFECT] = SI_HAT_EFFECT; - status->dbs->IconChangeTable[SC_FLOWERSMOKE] = SI_FLOWERSMOKE; - status->dbs->IconChangeTable[SC_FSTONE] = SI_FSTONE; - status->dbs->IconChangeTable[SC_HAPPINESS_STAR] = SI_HAPPINESS_STAR; - status->dbs->IconChangeTable[SC_MAPLE_FALLS] = SI_MAPLE_FALLS; - status->dbs->IconChangeTable[SC_TIME_ACCESSORY] = SI_TIME_ACCESSORY; - status->dbs->IconChangeTable[SC_MAGICAL_FEATHER] = SI_MAGICAL_FEATHER; - status->dbs->IconChangeTable[SC_BLOSSOM_FLUTTERING] = SI_BLOSSOM_FLUTTERING; + status->dbs->Skill2SCTable[skill->get_index(SL_ALCHEMIST)] = (sc_type)MAPID_ALCHEMIST, + status->dbs->Skill2SCTable[skill->get_index(SL_MONK)] = (sc_type)MAPID_MONK, + status->dbs->Skill2SCTable[skill->get_index(SL_STAR)] = (sc_type)MAPID_STAR_GLADIATOR, + status->dbs->Skill2SCTable[skill->get_index(SL_SAGE)] = (sc_type)MAPID_SAGE, + status->dbs->Skill2SCTable[skill->get_index(SL_CRUSADER)] = (sc_type)MAPID_CRUSADER, + status->dbs->Skill2SCTable[skill->get_index(SL_SUPERNOVICE)] = (sc_type)MAPID_SUPER_NOVICE, + status->dbs->Skill2SCTable[skill->get_index(SL_KNIGHT)] = (sc_type)MAPID_KNIGHT, + status->dbs->Skill2SCTable[skill->get_index(SL_WIZARD)] = (sc_type)MAPID_WIZARD, + status->dbs->Skill2SCTable[skill->get_index(SL_PRIEST)] = (sc_type)MAPID_PRIEST, + status->dbs->Skill2SCTable[skill->get_index(SL_BARDDANCER)] = (sc_type)MAPID_BARDDANCER, + status->dbs->Skill2SCTable[skill->get_index(SL_ROGUE)] = (sc_type)MAPID_ROGUE, + status->dbs->Skill2SCTable[skill->get_index(SL_ASSASIN)] = (sc_type)MAPID_ASSASSIN, + status->dbs->Skill2SCTable[skill->get_index(SL_BLACKSMITH)] = (sc_type)MAPID_BLACKSMITH, + status->dbs->Skill2SCTable[skill->get_index(SL_HUNTER)] = (sc_type)MAPID_HUNTER, + status->dbs->Skill2SCTable[skill->get_index(SL_SOULLINKER)] = (sc_type)MAPID_SOUL_LINKER, // Other SC which are not necessarily associated to skills. status->dbs->ChangeFlagTable[SC_ATTHASTE_POTION1] |= SCB_ASPD; @@ -1061,6 +885,13 @@ void initChangeTables(void) { status->dbs->ChangeFlagTable[SC_PHI_DEMON] |= SCB_ALL; status->dbs->ChangeFlagTable[SC_MAGIC_CANDY] |= SCB_MATK | SCB_ALL; status->dbs->ChangeFlagTable[SC_MYSTICPOWDER] |= SCB_FLEE | SCB_LUK; + status->dbs->ChangeFlagTable[SC_POPECOOKIE] |= SCB_BASE | SCB_BATK | SCB_MATK; + status->dbs->ChangeFlagTable[SC_VITALIZE_POTION] |= SCB_BATK | SCB_MATK; + status->dbs->ChangeFlagTable[SC_SKF_MATK] |= SCB_MATK; + status->dbs->ChangeFlagTable[SC_SKF_ATK] |= SCB_BATK; + status->dbs->ChangeFlagTable[SC_SKF_ASPD] |= SCB_ASPD; + status->dbs->ChangeFlagTable[SC_SKF_CAST] |= SCB_NONE; + status->dbs->ChangeFlagTable[SC_ALMIGHTY] |= SCB_BATK | SCB_MATK; // Cash Items status->dbs->ChangeFlagTable[SC_FOOD_STR_CASH] |= SCB_STR; @@ -1153,7 +984,11 @@ void initChangeTables(void) { status->dbs->ChangeFlagTable[SC_MVPCARD_ORCHERO] |= SCB_ALL; status->dbs->ChangeFlagTable[SC_MVPCARD_ORCLORD] |= SCB_ALL; + // Clan System + status->dbs->ChangeFlagTable[SC_CLAN_INFO] |= SCB_NONE; + // Costumes + status->dbs->ChangeFlagTable[SC_DRESS_UP] |= SCB_NONE; status->dbs->ChangeFlagTable[SC_MOONSTAR] |= SCB_NONE; status->dbs->ChangeFlagTable[SC_SUPER_STAR] |= SCB_NONE; status->dbs->ChangeFlagTable[SC_STRANGELIGHTS] |= SCB_NONE; @@ -1169,53 +1004,11 @@ void initChangeTables(void) { status->dbs->ChangeFlagTable[SC_MAGICAL_FEATHER] |= SCB_NONE; status->dbs->ChangeFlagTable[SC_BLOSSOM_FLUTTERING] |= SCB_NONE; - /* status->dbs->DisplayType Table [Ind/Hercules] */ - status->dbs->DisplayType[SC_ALL_RIDING] = true; - status->dbs->DisplayType[SC_PUSH_CART] = true; - status->dbs->DisplayType[SC_SUMMON1] = true; - status->dbs->DisplayType[SC_SUMMON2] = true; - status->dbs->DisplayType[SC_SUMMON3] = true; - status->dbs->DisplayType[SC_SUMMON4] = true; - status->dbs->DisplayType[SC_SUMMON5] = true; - status->dbs->DisplayType[SC_CAMOUFLAGE] = true; - status->dbs->DisplayType[SC_DUPLELIGHT] = true; - status->dbs->DisplayType[SC_ORATIO] = true; - status->dbs->DisplayType[SC_FROSTMISTY] = true; - status->dbs->DisplayType[SC_VENOMIMPRESS] = true; - status->dbs->DisplayType[SC_HALLUCINATIONWALK] = true; - status->dbs->DisplayType[SC_ROLLINGCUTTER] = true; - status->dbs->DisplayType[SC_BANDING] = true; - status->dbs->DisplayType[SC_COLD] = true; - status->dbs->DisplayType[SC_DEEP_SLEEP] = true; - status->dbs->DisplayType[SC_CURSEDCIRCLE_ATKER] = true; - status->dbs->DisplayType[SC_CURSEDCIRCLE_TARGET] = true; - status->dbs->DisplayType[SC_BLOOD_SUCKER] = true; - status->dbs->DisplayType[SC__SHADOWFORM] = true; - status->dbs->DisplayType[SC_MONSTER_TRANSFORM] = true; - - // Costumes - status->dbs->DisplayType[SC_MOONSTAR] = true; - status->dbs->DisplayType[SC_SUPER_STAR] = true; - status->dbs->DisplayType[SC_STRANGELIGHTS] = true; - status->dbs->DisplayType[SC_DECORATION_OF_MUSIC] = true; - status->dbs->DisplayType[SC_LJOSALFAR] = true; - status->dbs->DisplayType[SC_MERMAID_LONGING] = true; - status->dbs->DisplayType[SC_HAT_EFFECT] = true; - status->dbs->DisplayType[SC_FLOWERSMOKE] = true; - status->dbs->DisplayType[SC_FSTONE] = true; - status->dbs->DisplayType[SC_HAPPINESS_STAR] = true; - status->dbs->DisplayType[SC_MAPLE_FALLS] = true; - status->dbs->DisplayType[SC_TIME_ACCESSORY] = true; - status->dbs->DisplayType[SC_MAGICAL_FEATHER] = true; - status->dbs->DisplayType[SC_BLOSSOM_FLUTTERING] = true; - - if( !battle_config.display_hallucination ) //Disable Hallucination. - status->dbs->IconChangeTable[SC_ILLUSION] = SI_BLANK; #undef add_sc #undef set_sc_with_vfx } -void initDummyData(void) +static void initDummyData(void) { memset(&status->dummy, 0, sizeof(status->dummy)); status->dummy.hp = @@ -1237,15 +1030,23 @@ void initDummyData(void) } //For copying a status_data structure from b to a, without overwriting current Hp and Sp -static inline void status_cpy(struct status_data* a, const struct status_data* b) +static void status_copy(struct status_data *a, const struct status_data *b) { + nullpo_retv(a); + nullpo_retv(b); memcpy((void*)&a->max_hp, (const void*)&b->max_hp, sizeof(struct status_data)-(sizeof(a->hp)+sizeof(a->sp))); } -//Sets HP to given value. Flag is the flag passed to status->heal in case -//final value is higher than current (use 2 to make a healing effect display -//on players) It will always succeed (overrides Berserk block), but it can't kill. -int status_set_hp(struct block_list *bl, unsigned int hp, int flag) { +/** + * Sets HP to the given value. + * + * @param bl The target unit. + * @param hp The desired HP value. + * @param flag Additional options. @see enum status_heal_flag. STATUS_HEAL_FORCED is always implied. + * @return The amount of HP gained. + */ +static int status_set_hp(struct block_list *bl, unsigned int hp, enum status_heal_flag flag) +{ struct status_data *st; if (hp < 1) return 0; st = status->get_status_data(bl); @@ -1255,14 +1056,20 @@ int status_set_hp(struct block_list *bl, unsigned int hp, int flag) { if (hp > st->max_hp) hp = st->max_hp; if (hp == st->hp) return 0; if (hp > st->hp) - return status->heal(bl, hp - st->hp, 0, 1|flag); + return status->heal(bl, hp - st->hp, 0, STATUS_HEAL_FORCED | flag); return status_zap(bl, st->hp - hp, 0); } -//Sets SP to given value. Flag is the flag passed to status->heal in case -//final value is higher than current (use 2 to make a healing effect display -//on players) -int status_set_sp(struct block_list *bl, unsigned int sp, int flag) { +/** + * Sets SP to the given value. + * + * @param bl The target unit. + * @param hp The desired SP value. + * @param flag Additional options. @see enum status_heal_flag. STATUS_HEAL_FORCED is always implied. + * @return The amount of SP gained. + */ +static int status_set_sp(struct block_list *bl, unsigned int sp, enum status_heal_flag flag) +{ struct status_data *st; st = status->get_status_data(bl); @@ -1272,11 +1079,13 @@ int status_set_sp(struct block_list *bl, unsigned int sp, int flag) { if (sp > st->max_sp) sp = st->max_sp; if (sp == st->sp) return 0; if (sp > st->sp) - return status->heal(bl, 0, sp - st->sp, 1|flag); + return status->heal(bl, 0, sp - st->sp, STATUS_HEAL_FORCED | flag); return status_zap(bl, 0, st->sp - sp); } -int status_charge(struct block_list* bl, int64 hp, int64 sp) { +static int status_charge(struct block_list *bl, int64 hp, int64 sp) +{ + nullpo_retr((int)(hp + sp), bl); if(!(bl->type&BL_CONSUME)) return (int)(hp+sp); //Assume all was charged so there are no 'not enough' fails. return status->damage(NULL, bl, hp, sp, 0, 3); @@ -1287,11 +1096,13 @@ int status_charge(struct block_list* bl, int64 hp, int64 sp) { //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) { +static int status_damage(struct block_list *src, struct block_list *target, int64 in_hp, int64 in_sp, int walkdelay, int flag) +{ struct status_data *st; struct status_change *sc; int hp,sp; + nullpo_ret(target); /* From here onwards, we consider it a 32-type as the client does not support higher and the value doesn't get through percentage modifiers */ hp = (int)cap_value(in_hp,INT_MIN,INT_MAX); sp = (int)cap_value(in_sp,INT_MIN,INT_MAX); @@ -1300,12 +1111,12 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, sp = 0; //Not a valid SP target. if (hp < 0) { //Assume absorbed damage. - status->heal(target, -hp, 0, 1); + status->heal(target, -hp, 0, STATUS_HEAL_FORCED); hp = 0; } if (sp < 0) { - status->heal(target, 0, -sp, 1); + status->heal(target, 0, -sp, STATUS_HEAL_FORCED); sp = 0; } @@ -1376,6 +1187,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, status_change_end(target, SC_CLOAKING, INVALID_TIMER); status_change_end(target, SC_CHASEWALK, INVALID_TIMER); status_change_end(target, SC_CAMOUFLAGE, INVALID_TIMER); + status_change_end(target, SC_SUHIDE, INVALID_TIMER); if ((sce=sc->data[SC_ENDURE]) && !sce->val4 && !sc->data[SC_LKCONCENTRATION]) { //Endure count is only reduced by non-players on non-gvg maps. //val4 signals infinite endure. [Skotlex] @@ -1522,16 +1334,27 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp, return (int)(hp+sp); } -//Heals a character. If flag&1, this is forced healing (otherwise stuff like Berserk can block it) -//If flag&2, when the player is healed, show the HP/SP heal effect. -int status_heal(struct block_list *bl,int64 in_hp,int64 in_sp, int flag) { +/** + * Heals a character. + * + * @param bl The target unit. + * @param in_hp Amount of HP to recover. + * @param in_sp Amount of SP to recover. + * @param flag Additional options, @see enum status_heal_flag. + * @return The amount of HP + SP healed. + */ +static int status_heal(struct block_list *bl, int64 in_hp, int64 in_sp, enum status_heal_flag flag) +{ struct status_data *st; struct status_change *sc; int hp,sp; + nullpo_ret(bl); st = status->get_status_data(bl); - if (st == &status->dummy || !st->hp) + if (st == &status->dummy) + return 0; + if (st->hp == 0 && (flag & STATUS_HEAL_ALLOWREVIVE) == 0) return 0; /* From here onwards, we consider it a 32-type as the client does not support higher and the value doesn't get through percentage modifiers */ @@ -1548,10 +1371,10 @@ int status_heal(struct block_list *bl,int64 in_hp,int64 in_sp, int flag) { hp = 0; } - if(hp) { - if( sc && sc->data[SC_BERSERK] ) { - if( flag&1 ) - flag &= ~2; + if (hp != 0) { + if (sc && sc->data[SC_BERSERK] != NULL) { + if ((flag & STATUS_HEAL_FORCED) != 0) + flag &= ~STATUS_HEAL_SHOWEFFECT; else hp = 0; } @@ -1586,7 +1409,7 @@ int status_heal(struct block_list *bl,int64 in_hp,int64 in_sp, int flag) { // send hp update to client switch(bl->type) { - case BL_PC: pc->heal(BL_UCAST(BL_PC, bl), hp, sp, (flag&2) ? 1 : 0); break; + case BL_PC: pc->heal(BL_UCAST(BL_PC, bl), hp, sp, (flag & STATUS_HEAL_SHOWEFFECT) != 0 ? 1 : 0); break; case BL_MOB: mob->heal(BL_UCAST(BL_MOB, bl), hp); break; case BL_HOM: homun->healed(BL_UCAST(BL_HOM, bl)); break; case BL_MER: mercenary->heal(BL_UCAST(BL_MER, bl), hp, sp); break; @@ -1602,7 +1425,8 @@ int status_heal(struct block_list *bl,int64 in_hp,int64 in_sp, int flag) { //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 subtraction. -int status_percent_change(struct block_list *src,struct block_list *target,signed char hp_rate, signed char sp_rate, int flag) { +static 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; @@ -1640,23 +1464,26 @@ int status_percent_change(struct block_list *src,struct block_list *target,signe if (flag) status->damage(src, target, INT_MAX, 0, 0, (!src||src==target?5:1)); else - status->heal(target, INT_MAX, 0, 0); + status->heal(target, INT_MAX, 0, STATUS_HEAL_DEFAULT); } if (sp > INT_MAX) { sp -= INT_MAX; if (flag) status->damage(src, target, 0, INT_MAX, 0, (!src||src==target?5:1)); else - status->heal(target, 0, INT_MAX, 0); + status->heal(target, 0, INT_MAX, STATUS_HEAL_DEFAULT); } if (flag) return status->damage(src, target, hp, sp, 0, (!src||src==target?5:1)); - return status->heal(target, hp, sp, 0); + return status->heal(target, hp, sp, STATUS_HEAL_DEFAULT); } -int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per_sp) { +static int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per_sp) +{ struct status_data *st; unsigned int hp, sp; + + nullpo_ret(bl); if (!status->isdead(bl)) return 0; st = status->get_status_data(bl); @@ -1690,11 +1517,13 @@ int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per return 1; } -int status_fixed_revive(struct block_list *bl, unsigned int per_hp, unsigned int per_sp) { +static int status_fixed_revive(struct block_list *bl, unsigned int per_hp, unsigned int per_sp) +{ struct status_data *st; unsigned int hp, sp; if (!status->isdead(bl)) return 0; + nullpo_ret(bl); st = status->get_status_data(bl); if (st == &status->dummy) return 0; //Invalid target. @@ -1726,17 +1555,18 @@ int status_fixed_revive(struct block_list *bl, unsigned int per_hp, unsigned int } /*========================================== -* Checks whether the src can use the skill on the target, -* taking into account status/option of both source/target. [Skotlex] -* flag: -* 0 - Trying to use skill on target. -* 1 - Cast bar is done. -* 2 - Skill already pulled off, check is due to ground-based skills or splash-damage ones. -* src MAY be null to indicate we shouldn't check it, this is a ground-based skill attack. -* target MAY Be null, in which case the checks are only to see -* whether the source can cast or not the skill on the ground. -*------------------------------------------*/ -int status_check_skilluse(struct block_list *src, struct block_list *target, uint16 skill_id, int flag) { + * Checks whether the src can use the skill on the target, + * taking into account status/option of both source/target. [Skotlex] + * flag: + * 0 - Trying to use skill on target. + * 1 - Cast bar is done. + * 2 - Skill already pulled off, check is due to ground-based skills or splash-damage ones. + * src MAY be null to indicate we shouldn't check it, this is a ground-based skill attack. + * target MAY Be null, in which case the checks are only to see + * whether the source can cast or not the skill on the ground. + *------------------------------------------*/ +static int status_check_skilluse(struct block_list *src, struct block_list *target, uint16 skill_id, int flag) +{ struct status_data *st; struct status_change *sc=NULL, *tsc; int hide_flag; @@ -1747,6 +1577,9 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin if (src != NULL && src->type != BL_PC && status->isdead(src)) return 0; + if (sd != NULL && sd->block_action.skill && skill_id) // *pcblock script command + return 0; + if (!skill_id) { //Normal attack checks. if (!(st->mode&MD_CANATTACK)) return 0; //This mode is only needed for melee attacking. @@ -1759,14 +1592,18 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin } if( skill_id ) { - if (src != NULL && (sd == NULL || sd->skillitem == 0)) { + if (src != NULL && (sd == NULL || sd->autocast.type != AUTOCAST_ITEM)) { // Items that cast skills using 'itemskill' will not be handled by map_zone_db. int i; for(i = 0; i < map->list[src->m].zone->disabled_skills_count; i++) { if( skill_id == map->list[src->m].zone->disabled_skills[i]->nameid && (map->list[src->m].zone->disabled_skills[i]->type&src->type) ) { if (src->type == BL_PC) { - clif->msgtable(sd, MSG_SKILL_CANT_USE_AREA); // This skill cannot be used within this area +#if PACKETVER >= 20080311 + clif->skill_mapinfomessage(sd, 2); +#else + clif->messagecolor_self(sd->fd, COLOR_CYAN, msg_sd(sd, 50)); +#endif } else if (src->type == BL_MOB && map->list[src->m].zone->disabled_skills[i]->subtype != MZS_NONE) { if( st->mode&MD_BOSS ) { /* is boss */ if( !( map->list[src->m].zone->disabled_skills[i]->subtype&MZS_BOSS ) ) @@ -1799,7 +1636,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin if (src != NULL && map->getcell(src->m, src, src->x, src->y, CELL_CHKLANDPROTECTOR) && !(st->mode&MD_BOSS) - && (src->type != BL_PC || sd->skillitem != skill_id)) + && (src->type != BL_PC || sd->autocast.type != AUTOCAST_ITEM)) return 0; break; default: @@ -1822,6 +1659,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin (sc->data[SC_TRICKDEAD] && skill_id != NV_TRICKDEAD) || (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_SUHIDE] && skill_id != SU_HIDE) ) return 0; @@ -1841,9 +1679,13 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin switch (sc->data[SC_BLADESTOP]->val1) { case 5: if (skill_id == MO_EXTREMITYFIST) break; + FALLTHROUGH case 4: if (skill_id == MO_CHAINCOMBO) break; + FALLTHROUGH case 3: if (skill_id == MO_INVESTIGATE) break; + FALLTHROUGH case 2: if (skill_id == MO_FINGEROFFENSIVE) break; + FALLTHROUGH default: return 0; } } @@ -1873,7 +1715,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin return 0; //Can't amp out of Wand of Hermode :/ [Skotlex] } - if (skill_id != 0 /* Do not block item-casted skills.*/ && (src->type != BL_PC || sd->skillitem != skill_id)) { + if (skill_id != 0 /* Do not block item-casted skills.*/ && (src->type != BL_PC || sd->autocast.type != AUTOCAST_ITEM)) { //Skills blocked through status changes... if (!flag && ( //Blocked only from using the skill (stuff like autospell may still go through sc->data[SC_SILENCE] || @@ -1985,7 +1827,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin || (tsc->data[SC_CLOAKINGEXCEED] != NULL && is_detect) )) return 0; - if (tsc->data[SC_CAMOUFLAGE] && !(is_boss || is_detect) && (!skill_id || (flag == 0 && src && src->type != BL_PC))) + if (tsc->data[SC_CAMOUFLAGE] && !(is_boss || is_detect) && flag == 0) return 0; if (tsc->data[SC_STEALTHFIELD] && !is_boss) return 0; @@ -2007,6 +1849,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin return 0; // Can't use Weapon endow skills on Mercenary (only Master) if( skill_id == AM_POTIONPITCHER && ( target->type == BL_MER || target->type == BL_ELEM) ) return 0; // Can't use Potion Pitcher on Mercenaries + FALLTHROUGH default: //Check for chase-walk/hiding/cloaking opponents. if( tsc ) { @@ -2022,12 +1865,14 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin //Skotlex: Calculates the initial status for the given mob //first will only be false when the mob leveled up or got a GuardUp level. -int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) { +static 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; + nullpo_retr(1, md); if(opt&SCO_FIRST) { //Set basic level on respawn. if (md->level > 0 && md->level <= MAX_LEVEL && md->level != md->db->lv) ; @@ -2191,7 +2036,7 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) { } //Skotlex: Calculates the stats of the given pet. -int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt) +static int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt) { nullpo_ret(pd); @@ -2208,9 +2053,7 @@ int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt) if (battle_config.pet_lv_rate && pd->msd) { struct map_session_data *sd = pd->msd; - int lv; - - lv =sd->status.base_level*battle_config.pet_lv_rate/100; + int lv = sd->status.base_level * battle_config.pet_lv_rate / 100; if (lv < 0) lv = 1; if (lv != pd->pet.level || opt&SCO_FIRST) { @@ -2255,17 +2098,20 @@ int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt) return 1; } -unsigned int status_get_base_maxsp(const struct map_session_data *sd, const struct status_data *st) +static unsigned int status_get_base_maxsp(const struct map_session_data *sd, const struct status_data *st) { - uint64 val = pc->class2idx(sd->status.class_); + uint64 val; + nullpo_ret(sd); + nullpo_ret(st); + val = pc->class2idx(sd->status.class); val = status->dbs->SP_table[val][sd->status.base_level]; - if ( sd->class_&JOBL_UPPER ) + if ((sd->job & JOBL_UPPER) != 0) val += val * 25 / 100; - else if ( sd->class_&JOBL_BABY ) + else if ((sd->job & JOBL_BABY) != 0) val = val * 70 / 100; - if ( (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) ) + if ((sd->job & MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->fame_rank(sd->status.char_id, RANKTYPE_TAEKWON) > 0) val *= 3; //Triple max SP for top ranking Taekwons over level 90. val += val * st->int_ / 100; @@ -2273,23 +2119,26 @@ unsigned int status_get_base_maxsp(const struct map_session_data *sd, const stru return (unsigned int)cap_value(val, 0, UINT_MAX); } -unsigned int status_get_base_maxhp(const struct map_session_data *sd, const struct status_data *st) +static unsigned int status_get_base_maxhp(const struct map_session_data *sd, const struct status_data *st) { - uint64 val = pc->class2idx(sd->status.class_); + uint64 val; + nullpo_ret(sd); + nullpo_ret(st); + val = pc->class2idx(sd->status.class); val = status->dbs->HP_table[val][sd->status.base_level]; - if ( (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.base_level >= 99 ) + if ((sd->job & MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.base_level >= 99) val += 2000; //Supernovice lvl99 hp bonus. - if ( (sd->class_&MAPID_THIRDMASK) == MAPID_SUPER_NOVICE_E && sd->status.base_level >= 150 ) + if ((sd->job & MAPID_THIRDMASK) == MAPID_SUPER_NOVICE_E && sd->status.base_level >= 150) val += 2000; //Extented Supernovice lvl150 hp bonus. - if ( sd->class_&JOBL_UPPER ) + if ((sd->job & JOBL_UPPER) != 0) val += val * 25 / 100; //Trans classes get a 25% hp bonus - else if ( sd->class_&JOBL_BABY ) + else if ((sd->job & JOBL_BABY) != 0) val = val * 70 / 100; //Baby classes get a 30% hp penalty - if ( (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) ) + if ((sd->job & MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc->fame_rank(sd->status.char_id, RANKTYPE_TAEKWON)) val *= 3; //Triple max HP for top ranking Taekwons over level 90. val += val * st->vit / 100; // +1% per each point of VIT @@ -2297,22 +2146,83 @@ unsigned int status_get_base_maxhp(const struct map_session_data *sd, const stru return (unsigned int)cap_value(val,0,UINT_MAX); } -void status_calc_pc_additional(struct map_session_data* sd, enum e_status_calc_opt opt) { +/** + * Calculates the HP that a character will have after death, on respawn. + * + * @param sd The character to calculate. + * @param st The character's status data. + */ +static unsigned int status_get_restart_hp(const struct map_session_data *sd, const struct status_data *st) +{ + unsigned int hp = 0; + + if (sd->special_state.restart_full_recover) + return st->max_hp; + + if ((sd->job & MAPID_BASEMASK) == MAPID_NOVICE && (sd->job & JOBL_2) == 0 && battle_config.restart_hp_rate < 50) + hp = st->max_hp / 2; + else + hp = APPLY_RATE(st->max_hp, battle_config.restart_hp_rate); + + if (hp > 0) + return hp; + + return 1; +} + +/** + * Calculates the SP that a character will have after death, on respawn. + * + * @param sd The character to calculate. + * @param st The character's status data. + */ +static unsigned int status_get_restart_sp(const struct map_session_data *sd, const struct status_data *st) +{ + unsigned int sp = 0; + + if (sd->special_state.restart_full_recover) + return st->max_sp; + + sp = APPLY_RATE(st->max_sp, battle_config.restart_sp_rate); + + if (sp > 0) + return sp; + + return 1; // the minimum for the respawn setting is SP:1 +} + +static void status_calc_pc_additional(struct map_session_data *sd, enum e_status_calc_opt opt) +{ /* Just used for Plugin to give bonuses. */ return; } +static void status_calc_pc_recover_hp(struct map_session_data *sd, struct status_data *bstatus) +{ + nullpo_retv(sd); + nullpo_retv(bstatus); + + if ((sd->job & MAPID_BASEMASK) == MAPID_NOVICE && (sd->job & JOBL_2) == 0 + && battle_config.restart_hp_rate < 50) + bstatus->hp = bstatus->max_hp>>1; + else + bstatus->hp = APPLY_RATE(bstatus->max_hp, battle_config.restart_hp_rate); +} + //Calculates player data from scratch without counting SC adjustments. //Should be invoked whenever players raise stats, learn passive skills or change equipment. -int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { +static int status_calc_pc_(struct map_session_data *sd, enum e_status_calc_opt opt) +{ static int calculating = 0; //Check for recursive call preemption. [Skotlex] struct status_data *bstatus; // pointer to the player's base status - const struct status_change *sc = &sd->sc; - struct s_skill b_skill[MAX_SKILL]; // previous skill tree + const struct status_change *sc; + struct s_skill b_skill[MAX_SKILL_DB]; // previous skill tree int b_weight, b_max_weight, b_cart_weight_max, // previous weight i, k, index, skill_lv,refinedef=0; int64 i64; + nullpo_retr(-1, sd); + sc = &sd->sc; if (++calculating > 10) //Too many recursive calls! return -1; @@ -2324,7 +2234,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { pc->calc_skilltree(sd); // SkillTree calculation - sd->max_weight = status->dbs->max_weight_base[pc->class2idx(sd->status.class_)]+sd->status.str*300; + sd->max_weight = status->dbs->max_weight_base[pc->class2idx(sd->status.class)]+sd->status.str*300; if(opt&SCO_FIRST) { //Load Hp/SP from char-received data. @@ -2333,7 +2243,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { sd->regen.sregen = &sd->sregen; sd->regen.ssregen = &sd->ssregen; sd->weight=0; - for(i=0;i<MAX_INVENTORY;i++){ + for (i = 0; i < sd->status.inventorySize; i++) { if(sd->status.inventory[i].nameid==0 || sd->inventory_data[i] == NULL) continue; sd->weight += sd->inventory_data[i]->weight*sd->status.inventory[i].amount; @@ -2369,7 +2279,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { memset(ZEROED_BLOCK_POS(&(sd->left_weapon)), 0, ZEROED_BLOCK_SIZE(&(sd->left_weapon))); if (sd->special_state.intravision && !sd->sc.data[SC_CLAIRVOYANCE]) //Clear intravision as long as nothing else is using it - clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_CLAIRVOYANCE); + clif->sc_end(&sd->bl, sd->bl.id, SELF, status->get_sc_icon(SC_CLAIRVOYANCE)); memset(&sd->special_state,0,sizeof(sd->special_state)); @@ -2382,13 +2292,13 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { bstatus->speed = pSpeed; } - //FIXME: Most of these stuff should be calculated once, but how do I fix the memset above to do that? [Skotlex] - //Give them all modes except these (useful for clones) + // FIXME: Most of these stuff should be calculated once, but how do I fix the memset above to do that? [Skotlex] + // Give them all modes except these (useful for clones) bstatus->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK); - bstatus->size = (sd->class_&JOBL_BABY)?SZ_SMALL:SZ_MEDIUM; + bstatus->size = ((sd->job & JOBL_BABY) != 0 || (sd->job & MAPID_BASEMASK) == MAPID_SUMMONER)?SZ_SMALL:SZ_MEDIUM; if (battle_config.character_size && (pc_isridingpeco(sd) || pc_isridingdragon(sd))) { //[Lupus] - if (sd->class_&JOBL_BABY) { + if ((sd->job & JOBL_BABY) != 0) { if (battle_config.character_size&SZ_BIG) bstatus->size++; } else { @@ -2398,7 +2308,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { } bstatus->aspd_rate = 1000; bstatus->ele_lv = 1; - bstatus->race = RC_PLAYER; + bstatus->race = ((sd->job & MAPID_BASEMASK) == MAPID_SUMMONER)?RC_BRUTE:RC_PLAYER; // Autobonus pc->delautobonus(sd,sd->autobonus,ARRAYLENGTH(sd->autobonus),true); @@ -2464,18 +2374,18 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { r = 0; if (r) - wa->atk2 = status->dbs->refine_info[wlv].bonus[r-1] / 100; + wa->atk2 = refine->get_bonus(wlv, r) / 100; #ifdef RENEWAL wa->matk += sd->inventory_data[index]->matk; wa->wlv = wlv; if( r && sd->weapontype1 != W_BOW ) // renewal magic attack refine bonus - wa->matk += status->dbs->refine_info[wlv].bonus[r-1] / 100; + wa->matk += refine->get_bonus(wlv, r) / 100; #endif //Overrefined bonus. if (r) - wd->overrefine = status->dbs->refine_info[wlv].randombonus_max[r-1] / 100; + wd->overrefine = refine->get_randombonus_max(wlv, r) / 100; wa->range += sd->inventory_data[index]->range; if(sd->inventory_data[index]->script) { @@ -2492,8 +2402,9 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { if (sd->status.inventory[index].card[0]==CARD0_FORGE) { // Forged weapon wd->star += (sd->status.inventory[index].card[1]>>8); - if(wd->star >= 15) wd->star = 40; // 3 Star Crumbs now give +40 dmg - if(pc->famerank(MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]) ,MAPID_BLACKSMITH)) + if (wd->star >= 15) + wd->star = 40; // 3 Star Crumbs now give +40 dmg + if (pc->fame_rank(MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]), RANKTYPE_BLACKSMITH) > 0) wd->star += 10; if (!wa->ele) //Do not overwrite element from previous bonuses. @@ -2509,7 +2420,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { r = 0; if (r) - refinedef += status->dbs->refine_info[REFINE_TYPE_ARMOR].bonus[r-1]; + refinedef += refine->get_bonus(REFINE_TYPE_ARMOR, r); if(sd->inventory_data[index]->script) { if( i == EQI_HAND_L ) //Shield @@ -2628,14 +2539,57 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { } } + /* parse item options [Smokexyz] */ + for (i = 0; i < EQI_MAX; i++) { + status->current_equip_item_index = index = sd->equip_index[i]; + status->current_equip_option_index = -1; + + if (i == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) + continue; + else if (i == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) + continue; + else if (i == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) + continue; + + if (index >= 0 && sd->inventory_data[index]) { + int j = 0; + for (j = 0; j < MAX_ITEM_OPTIONS; j++) { + int16 option_index = sd->status.inventory[index].option[j].index; + struct itemdb_option *ito = NULL; + + if (option_index == 0 || (ito = itemdb->option_exists(option_index)) == NULL || ito->script == NULL) + continue; + + status->current_equip_option_index = j; + script->run(ito->script, 0, sd->bl.id, 0); + + if (calculating == 0) //Abort, script->run his function. [Skotlex] + return 1; + } + } + } + + status->current_equip_option_index = -1; + status->current_equip_item_index = -1; + + // Clan Buffs + if (sd->status.clan_id > 0) { + struct clan *c = clan->search(sd->status.clan_id); + clan->buff_start(sd, c); + } + status->calc_pc_additional(sd, opt); - if( sd->pd ) { // Pet Bonus + if (sd->pd != NULL) { // Pet bonus. struct pet_data *pd = sd->pd; - if( pd && pd->petDB && pd->petDB->equip_script && pd->pet.intimate >= battle_config.pet_equip_min_friendly ) - script->run(pd->petDB->equip_script,0,sd->bl.id,0); - if( pd && pd->pet.intimate > 0 && (!battle_config.pet_equip_required || pd->pet.equip > 0) && pd->state.skillbonus == 1 && pd->bonus ) - pc->bonus(sd,pd->bonus->type, pd->bonus->val); + + if (pd->petDB != NULL && pd->petDB->equip_script != NULL) + script->run(pd->petDB->equip_script, 0, sd->bl.id, 0); + + if (pd->pet.intimate > PET_INTIMACY_NONE && pd->state.skillbonus == 1 && pd->bonus != NULL + && (battle_config.pet_equip_required == 0 || pd->pet.equip > 0)) { + pc->bonus(sd, pd->bonus->type, pd->bonus->val); + } } //param_bonus now holds card bonuses. @@ -2656,9 +2610,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { sd->left_weapon.atkmods[1] = status->dbs->atkmods[1][sd->weapontype2]; sd->left_weapon.atkmods[2] = status->dbs->atkmods[2][sd->weapontype2]; - if ((pc_isridingpeco(sd) || pc_isridingdragon(sd)) - && (sd->status.weapon==W_1HSPEAR || sd->status.weapon==W_2HSPEAR) - ) { + if ((pc_isridingpeco(sd) || pc_isridingdragon(sd)) && (sd->weapontype == W_1HSPEAR || sd->weapontype == W_2HSPEAR)) { //When Riding with spear, damage modifier to mid-class becomes //same as versus large size. sd->right_weapon.atkmods[1] = sd->right_weapon.atkmods[2]; @@ -2668,8 +2620,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { // ----- STATS CALCULATION ----- // Job bonuses - index = pc->class2idx(sd->status.class_); - for(i=0;i<(int)sd->status.job_level && i<MAX_LEVEL;i++){ + index = pc->class2idx(sd->status.class); + for (i = 0; i < sd->status.job_level && i < MAX_LEVEL; i++) { if(!status->dbs->job_bonus[index][i]) continue; switch(status->dbs->job_bonus[index][i]) { @@ -2683,7 +2635,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { } // If a Super Novice has never died and is at least joblv 70, he gets all stats +10 - if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->die_counter == 0 && sd->status.job_level >= 70) { + if ((sd->job & MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->die_counter == 0 && sd->status.job_level >= 70) { bstatus->str += 10; bstatus->agi += 10; bstatus->vit += 10; @@ -2701,6 +2653,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { bstatus->dex += skill_lv; if((skill_lv = pc->checkskill(sd,RA_RESEARCHTRAP))>0) bstatus->int_ += skill_lv; + if ((pc->checkskill(sd,SU_POWEROFLAND)) > 0) + bstatus->int_ += 20; // Bonuses from cards and equipment as well as base stat, remember to avoid overflows. i = bstatus->str + sd->status.str + sd->param_bonus[0] + sd->param_equip[0]; @@ -2720,8 +2674,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { // Base batk value is set on status->calc_misc // weapon-type bonus (FIXME: Why is the weapon_atk bonus applied to base attack?) - if (sd->status.weapon < MAX_SINGLE_WEAPON_TYPE && sd->weapon_atk[sd->status.weapon]) - bstatus->batk += sd->weapon_atk[sd->status.weapon]; + if (sd->weapontype < MAX_SINGLE_WEAPON_TYPE && sd->weapon_atk[sd->weapontype]) + bstatus->batk += sd->weapon_atk[sd->weapontype]; // Absolute modifiers from passive skills #ifndef RENEWAL if((skill_lv=pc->checkskill(sd,BS_HILTBINDING))>0) // it doesn't work in RE. @@ -2738,9 +2692,12 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { bstatus->max_hp = (unsigned int)cap_value(i64, 0, INT_MAX); // Absolute modifiers from passive skills - if((skill_lv=pc->checkskill(sd,CR_TRUST))>0) + if ((skill_lv=pc->checkskill(sd,CR_TRUST)) > 0) bstatus->max_hp += skill_lv*200; + if ((pc->checkskill(sd,SU_SPRITEMABLE)) > 0) + bstatus->max_hp += 1000; + // Apply relative modifiers from equipment if(sd->hprate < 0) sd->hprate = 0; @@ -2773,6 +2730,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { bstatus->max_sp += 200 + 20 * skill_lv; if( (skill_lv = pc->checkskill(sd,WM_LESSON)) > 0 ) bstatus->max_sp += 30 * skill_lv; + if ((pc->checkskill(sd,SU_SPRITEMABLE)) > 0) + bstatus->max_sp += 100; // Apply relative modifiers from equipment if(sd->sprate < 0) @@ -2790,24 +2749,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { // ----- RESPAWN HP/SP ----- // //Calc respawn hp and store it on base_status - if (sd->special_state.restart_full_recover) - { - bstatus->hp = bstatus->max_hp; - bstatus->sp = bstatus->max_sp; - } else { - if((sd->class_&MAPID_BASEMASK) == MAPID_NOVICE && !(sd->class_&JOBL_2) - && battle_config.restart_hp_rate < 50) - bstatus->hp = bstatus->max_hp>>1; - else - bstatus->hp = APPLY_RATE(bstatus->max_hp, battle_config.restart_hp_rate); - if(!bstatus->hp) - bstatus->hp = 1; - - bstatus->sp = APPLY_RATE(bstatus->max_sp, battle_config.restart_sp_rate); - - if( !bstatus->sp ) /* the minimum for the respawn setting is SP:1 */ - bstatus->sp = 1; - } + bstatus->hp = status->get_restart_hp(sd, bstatus); + bstatus->sp = status->get_restart_sp(sd, bstatus); // ----- MISC CALCULATION ----- status->calc_misc(&sd->bl, bstatus, sd->status.base_level); @@ -2845,6 +2788,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { sd->critical_rate = 0; if(sd->critical_rate != 100) bstatus->cri = bstatus->cri * sd->critical_rate/100; + if (pc->checkskill(sd, SU_POWEROFLIFE) > 0) + bstatus->cri += 20; if(sd->flee2_rate < 0) sd->flee2_rate = 0; @@ -2862,10 +2807,10 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { #ifndef RENEWAL bstatus->hit += skill_lv; #endif - if(sd->status.weapon == W_BOW) + if (sd->weapontype == W_BOW) bstatus->rhw.range += skill_lv; } - if(sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE) { + if (sd->weapontype >= W_REVOLVER && sd->weapontype <= W_GRENADE) { if((skill_lv=pc->checkskill(sd,GS_SINGLEACTION))>0) bstatus->hit += 2*skill_lv; if((skill_lv=pc->checkskill(sd,GS_SNAKEEYE))>0) { @@ -2873,18 +2818,22 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { bstatus->rhw.range += skill_lv; } } - if( (sd->status.weapon == W_1HAXE || sd->status.weapon == W_2HAXE) && (skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0 ) + if ((sd->weapontype == W_1HAXE || sd->weapontype == W_2HAXE) && (skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0) bstatus->hit += 3*skill_lv; - if((sd->status.weapon == W_MACE || sd->status.weapon == W_2HMACE) && (skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0) + if ((sd->weapontype == W_MACE || sd->weapontype == W_2HMACE) && (skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0) bstatus->hit += 2*skill_lv; + if (pc->checkskill(sd, SU_POWEROFLIFE) > 0) + bstatus->hit += 20; // ----- FLEE CALCULATION ----- // Absolute modifiers from passive skills if((skill_lv=pc->checkskill(sd,TF_MISS))>0) - bstatus->flee += skill_lv*(sd->class_&JOBL_2 && (sd->class_&MAPID_BASEMASK) == MAPID_THIEF? 4 : 3); + bstatus->flee += skill_lv*((sd->job & JOBL_2) != 0 && (sd->job & MAPID_BASEMASK) == MAPID_THIEF? 4 : 3); if((skill_lv=pc->checkskill(sd,MO_DODGE))>0) bstatus->flee += (skill_lv*3)>>1; + if (pc->checkskill(sd, SU_POWEROFLIFE) > 0) + bstatus->flee += 20; // ----- EQUIPMENT-DEF CALCULATION ----- // Apply relative modifiers from equipment @@ -2927,16 +2876,15 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { // Basic ASPD value i = status->base_amotion_pc(sd,bstatus); - bstatus->amotion = cap_value(i,((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd),2000); + bstatus->amotion = cap_value(i,((sd->job & JOBL_THIRD) != 0 ? battle_config.max_third_aspd : battle_config.max_aspd),2000); // Relative modifiers from passive skills #ifndef RENEWAL_ASPD - if((skill_lv=pc->checkskill(sd,SA_ADVANCEDBOOK))>0 && sd->status.weapon == W_BOOK) + if (sd->weapontype == W_BOOK && (skill_lv=pc->checkskill(sd,SA_ADVANCEDBOOK)) > 0) bstatus->aspd_rate -= 5*skill_lv; if((skill_lv = pc->checkskill(sd,SG_DEVIL)) > 0 && !pc->nextjobexp(sd)) bstatus->aspd_rate -= 30*skill_lv; - if((skill_lv=pc->checkskill(sd,GS_SINGLEACTION))>0 && - (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)) + if (sd->weapontype >= W_REVOLVER && sd->weapontype <= W_GRENADE && (skill_lv=pc->checkskill(sd,GS_SINGLEACTION)) > 0) bstatus->aspd_rate -= ((skill_lv+1)/2) * 10; if (pc_isridingpeco(sd)) bstatus->aspd_rate += 500-100*pc->checkskill(sd,KN_CAVALIERMASTERY); @@ -3102,6 +3050,18 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { sd->subele[ELE_EARTH] += i; sd->subele[ELE_FIRE] -= i; } + if (sc->data[SC_POPECOOKIE] != NULL) { + i = sc->data[SC_POPECOOKIE]->val3; + sd->subele[ELE_WATER] += i; + sd->subele[ELE_EARTH] += i; + sd->subele[ELE_FIRE] += i; + sd->subele[ELE_WIND] += i; + sd->subele[ELE_POISON] += i; + sd->subele[ELE_HOLY] += i; + sd->subele[ELE_DARK] += i; + sd->subele[ELE_GHOST] += i; + sd->subele[ELE_UNDEAD] += i; + } if (sc->data[SC_MTF_MLEATKED]) sd->subele[ELE_NEUTRAL] += sc->data[SC_MTF_MLEATKED]->val1; if (sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 3) @@ -3160,7 +3120,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { sd->left_weapon.addrace[RC_DEMON] += sc->data[SC_PHI_DEMON]->val1; } } - status_cpy(&sd->battle_status, bstatus); + status->copy(&sd->battle_status, bstatus); // ----- CLIENT-SIDE REFRESH ----- if(!sd->bl.prev) { @@ -3180,15 +3140,25 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { clif->updatestatus(sd,SP_CARTINFO); } + // Spirit Marble status activates automatically for a infinite + // amount of time when the skill is learned. Felt this was the + // best place to put this. [Rytech] + if (pc->checkskill(sd, SU_SPRITEMABLE)) + sc_start(&sd->bl, &sd->bl, SC_SPRITEMABLE, 100, 1, INFINITE_DURATION); + calculating = 0; return 0; } -int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt) { - struct status_data *mstatus = &md->base_status; - struct s_mercenary *merc = &md->mercenary; +static int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt) +{ + struct status_data *mstatus; + struct s_mercenary *merc; + nullpo_ret(md); + mstatus = &md->base_status; + merc = &md->mercenary; if( opt&SCO_FIRST ) { memcpy(mstatus, &md->db->status, sizeof(struct status_data)); mstatus->mode = MD_CANMOVE|MD_CANATTACK; @@ -3199,17 +3169,22 @@ int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt } status->calc_misc(&md->bl, mstatus, md->db->lv); - status_cpy(&md->battle_status, mstatus); + status->copy(&md->battle_status, mstatus); return 0; } -int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt) { - struct status_data *estatus = &ed->base_status; - struct s_elemental *ele = &ed->elemental; - struct map_session_data *sd = ed->master; +static int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt) +{ + struct status_data *estatus; + struct s_elemental *ele; + struct map_session_data *sd; - if ( !sd ) + nullpo_ret(ed); + estatus = &ed->base_status; + ele = &ed->elemental; + sd = ed->master; + if (sd == NULL) return 0; if ( opt&SCO_FIRST ) { @@ -3237,13 +3212,14 @@ int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt memcpy(&ed->battle_status, estatus, sizeof(struct status_data)); } else { status->calc_misc(&ed->bl, estatus, 0); - status_cpy(&ed->battle_status, estatus); + status->copy(&ed->battle_status, estatus); } return 0; } -int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt) { +static int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt) +{ struct status_data *nstatus; if (!nd) @@ -3274,17 +3250,21 @@ int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt) { nstatus->luk = nd->stat_point; status->calc_misc(&nd->bl, nstatus, nd->level); - status_cpy(&nd->status, nstatus); + status->copy(&nd->status, nstatus); return 0; } -int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) { - struct status_data *hstatus = &hd->base_status; - struct s_homunculus *hom = &hd->homunculus; +static int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) +{ + struct status_data *hstatus; + struct s_homunculus *hom; int skill_lv; int amotion; + nullpo_retr(1, hd); + hstatus = &hd->base_status; + hom = &hd->homunculus; hstatus->str = hom->str / 10; hstatus->agi = hom->agi / 10; hstatus->vit = hom->vit / 10; @@ -3360,12 +3340,13 @@ int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) { status->calc_misc(&hd->bl, hstatus, hom->level); - status_cpy(&hd->battle_status, hstatus); + status->copy(&hd->battle_status, hstatus); return 1; } //Calculates base regen values. -void status_calc_regen(struct block_list *bl, struct status_data *st, struct regen_data *regen) { +static 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); @@ -3465,8 +3446,9 @@ void status_calc_regen(struct block_list *bl, struct status_data *st, struct reg } //Calculates SC related regen rates. -void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, struct status_change *sc) +static void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, struct status_change *sc) { + nullpo_retv(bl); if (!(bl->type&BL_REGEN) || !regen) return; @@ -3509,7 +3491,7 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str || sc->data[SC_OBLIVIONCURSE] != NULL || sc->data[SC_MAXIMIZEPOWER] != NULL || sc->data[SC_REBOUND] != NULL - || (bl->type == BL_PC && (BL_UCAST(BL_PC, bl)->class_&MAPID_UPPERMASK) == MAPID_MONK + || (bl->type == BL_PC && (BL_UCAST(BL_PC, bl)->job & MAPID_UPPERMASK) == MAPID_MONK && (sc->data[SC_EXTREMITYFIST] != NULL || (sc->data[SC_EXPLOSIONSPIRITS] != NULL && (sc->data[SC_SOULLINK] == NULL || sc->data[SC_SOULLINK]->val2 != SL_MONK) @@ -3540,7 +3522,7 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str #endif regen->rate.sp += 1; } - + if (sc->data[SC_GDSKILL_REGENERATION]) { const struct status_change_entry *sce = sc->data[SC_GDSKILL_REGENERATION]; if (!sce->val4) { @@ -3573,6 +3555,10 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str regen->rate.hp += regen->rate.hp * sc->data[SC_BUCHEDENOEL]->val1 / 100; regen->rate.sp += regen->rate.sp * sc->data[SC_BUCHEDENOEL]->val2 / 100; } + if (sc->data[SC_CATNIPPOWDER]) { + regen->rate.hp *= 2; + regen->rate.sp *= 2; + } } #define status_get_homstr(st, hd) ((st)->str + (hd)->homunculus.str_value) @@ -3584,13 +3570,16 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str /// Recalculates parts of an object's battle status according to the specified flags. /// @param flag bitfield of values from enum scb_flag -void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) { +static void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) +{ const struct status_data *bst = status->get_base_status(bl); struct status_data *st = status->get_status_data(bl); struct status_change *sc = status->get_sc(bl); struct map_session_data *sd = BL_CAST(BL_PC,bl); int temp; + nullpo_retv(bl); + if (!bst || !st) return; @@ -3610,7 +3599,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) { } if((!(bl->type&BL_REGEN)) && (!sc || !sc->count)) { //No difference. - status_cpy(st, bst); + status->copy(st, bst); return; } @@ -3677,7 +3666,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) { temp = bst->batk - status->base_atk(bl,bst); if (temp) { temp += st->batk; - st->batk = cap_value(temp, 0, USHRT_MAX); + st->batk = cap_value(temp, battle_config.batk_min, battle_config.batk_max); } st->batk = status->calc_batk(bl, sc, st->batk, true); } @@ -3792,13 +3781,15 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) { } if(flag&SCB_CRI && bst->cri) { - if (st->luk == bst->luk) + if (st->luk == bst->luk) { st->cri = status->calc_critical(bl, sc, bst->cri, true); - else + } else { st->cri = status->calc_critical(bl, sc, bst->cri + 3*(st->luk - bst->luk), true); + } + if (battle_config.show_katar_crit_bonus && bl->type == BL_PC && BL_UCAST(BL_PC, bl)->weapontype == W_KATAR) { + st->cri *= 2; + } } - if (battle_config.show_katar_crit_bonus && bl->type == BL_PC && BL_UCAST(BL_PC, bl)->status.weapon == W_KATAR) - st->cri <<= 1; if(flag&SCB_FLEE2 && bst->flee2) { if (st->luk == bst->luk) @@ -3857,10 +3848,10 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) { if(flag&SCB_MAXSP) { if( bl->type&BL_PC ) { st->max_sp = status->get_base_maxsp(sd,st); - if (sd) + if (sd != NULL) { st->max_sp += bst->max_sp - sd->status.max_sp; - - st->max_sp = status->calc_maxsp(&sd->bl, &sd->sc, st->max_sp); + st->max_sp = status->calc_maxsp(&sd->bl, &sd->sc, st->max_sp); + } if( st->max_sp > (unsigned int)battle_config.max_sp ) st->max_sp = (unsigned int)battle_config.max_sp; @@ -3927,14 +3918,29 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) { #endif if ( st->aspd_rate != 1000 ) // absolute percentage modifier amotion = amotion * st->aspd_rate / 1000; - if ( sd && sd->ud.skilltimer != INVALID_TIMER && pc->checkskill(sd, SA_FREECAST) > 0 ) - amotion = amotion * 5 * (pc->checkskill(sd, SA_FREECAST) + 10) / 100; + if (sd && sd->ud.skilltimer != INVALID_TIMER) { + if (pc->checkskill(sd, SA_FREECAST) > 0) { + amotion = amotion * 5 * (pc->checkskill(sd, SA_FREECAST) + 10) / 100; + } else { + struct unit_data *ud = unit->bl2ud(bl); + if (ud && (skill->get_inf2(ud->skill_id) & INF2_FREE_CAST_REDUCED) != 0) { + amotion = amotion * 5 * (ud->skill_lv + 10) / 100; + } + } + } #ifdef RENEWAL_ASPD amotion += (max(0xc3 - amotion, 2) * (st->aspd_rate2 + status->calc_aspd(bl, sc, 2))) / 100; - amotion = 10 * (200 - amotion) + sd->bonus.aspd_add; + amotion = 10 * (200 - amotion); + if (sd != NULL) { + amotion += sd->bonus.aspd_add; + } #endif amotion = status->calc_fix_aspd(bl, sc, amotion); - st->amotion = cap_value(amotion, ((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd), 2000); + if (sd != NULL) { + st->amotion = cap_value(amotion, ((sd->job & JOBL_THIRD) != 0 ? battle_config.max_third_aspd : battle_config.max_aspd), 2000); + } else { + st->amotion = cap_value(amotion, battle_config.max_aspd, 2000); + } st->adelay = 2 * st->amotion; } else { // mercenary and mobs @@ -3958,15 +3964,17 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) { if(flag&SCB_REGEN && bl->type&BL_REGEN) status->calc_regen_rate(bl, status->get_regen_data(bl), sc); } + /// Recalculates parts of an object's base status and battle status according to the specified flags. /// Also sends updates to the client wherever applicable. /// @param flag bitfield of values from enum scb_flag /// @param first if true, will cause status_calc_* functions to run their base status initialization code -void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_calc_opt opt) +static void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_calc_opt opt) { struct status_data bst; // previous battle status struct status_data *st; // pointer to current battle status + nullpo_retv(bl); if (bl->type == BL_PC) { struct map_session_data *sd = BL_UCAST(BL_PC, bl); if (sd->delayed_damage != 0) { @@ -4144,11 +4152,16 @@ void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_ca clif->mercenary_updatestatus(ed->master, SP_SP); } } + //Checks whether the source can see and chase target. -int status_check_visibility(struct block_list *src, struct block_list *target) { +static int status_check_visibility(struct block_list *src, struct block_list *target) +{ int view_range; struct status_change *tsc = NULL; + nullpo_ret(src); + nullpo_ret(target); + switch ( src->type ) { case BL_MOB: view_range = BL_UCCAST(BL_MOB, src)->min_chase; @@ -4193,17 +4206,22 @@ int status_check_visibility(struct block_list *src, struct block_list *target) { } // Basic ASPD value -int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) { +static int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) +{ int amotion; #ifdef RENEWAL_ASPD /* [malufett/Hercules] */ float temp; int skill_lv, val = 0; - amotion = status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1]; - if ( sd->status.weapon > MAX_SINGLE_WEAPON_TYPE) - amotion += status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2] / 4; - if ( sd->status.shield ) - amotion += status->dbs->aspd_base[pc->class2idx(sd->status.class_)][MAX_SINGLE_WEAPON_TYPE]; - switch ( sd->status.weapon ) { + + nullpo_ret(sd); + nullpo_ret(st); + + amotion = status->dbs->aspd_base[pc->class2idx(sd->status.class)][sd->weapontype1]; + if (sd->weapontype > MAX_SINGLE_WEAPON_TYPE) + amotion += status->dbs->aspd_base[pc->class2idx(sd->status.class)][sd->weapontype2] / 4; + if (sd->has_shield) + amotion += status->dbs->aspd_base[pc->class2idx(sd->status.class)][MAX_SINGLE_WEAPON_TYPE]; + switch (sd->weapontype) { case W_BOW: case W_MUSICAL: case W_WHIP: @@ -4218,16 +4236,16 @@ int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) temp = st->dex * st->dex / 5.0f + st->agi * st->agi * 0.5f; } temp = (float)(sqrt(temp) * 0.25f) + 0xc4; - if ( (skill_lv = pc->checkskill(sd, SA_ADVANCEDBOOK)) > 0 && sd->status.weapon == W_BOOK ) + if (sd->weapontype == W_BOOK && (skill_lv = pc->checkskill(sd, SA_ADVANCEDBOOK)) > 0) val += (skill_lv - 1) / 2 + 1; if ( (skill_lv = pc->checkskill(sd, GS_SINGLEACTION)) > 0 ) val += ((skill_lv + 1) / 2); amotion = ((int)(temp + ((float)(status->calc_aspd(&sd->bl, &sd->sc, 1) + val) * st->agi / 200)) - min(amotion, 200)); #else // base weapon delay - amotion = (sd->status.weapon < MAX_SINGLE_WEAPON_TYPE) - ? (status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->status.weapon]) // single weapon - : (status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1] + status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2]) * 7 / 10; // dual-wield + amotion = (sd->weapontype < MAX_SINGLE_WEAPON_TYPE) + ? (status->dbs->aspd_base[pc->class2idx(sd->status.class)][sd->weapontype]) // single weapon + : (status->dbs->aspd_base[pc->class2idx(sd->status.class)][sd->weapontype1] + status->dbs->aspd_base[pc->class2idx(sd->status.class)][sd->weapontype2]) * 7 / 10; // dual-wield // percentual delay reduction from stats amotion -= amotion * (4 * st->agi + st->dex) / 1000; @@ -4243,14 +4261,17 @@ int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) return amotion; } -unsigned short status_base_atk(const struct block_list *bl, const struct status_data *st) { +static int status_base_atk(const struct block_list *bl, const struct status_data *st) +{ int flag = 0, str, dex, dstr; + nullpo_ret(bl); + nullpo_ret(st); if ( !(bl->type&battle_config.enable_baseatk) ) return 0; if (bl->type == BL_PC) { - switch (BL_UCCAST(BL_PC, bl)->status.weapon) { + switch (BL_UCCAST(BL_PC, bl)->weapontype) { case W_BOW: case W_MUSICAL: case W_WHIP: @@ -4297,34 +4318,61 @@ unsigned short status_base_atk(const struct block_list *bl, const struct status_ if (bl->type == BL_PC) str += dex / 5 + st->luk / 5; #endif // RENEWAL - return cap_value(str, 0, USHRT_MAX); + return cap_value(str, battle_config.batk_min, battle_config.batk_max); } -#ifndef RENEWAL -static inline unsigned short status_base_matk_min(const struct status_data *st) { return st->int_ + (st->int_ / 7)*(st->int_ / 7); } -#endif // not RENEWAL -static inline unsigned short status_base_matk_max(const struct status_data *st) { return st->int_ + (st->int_ / 5)*(st->int_ / 5); } +static int status_base_matk_min(const struct status_data *st) +{ + nullpo_ret(st); +#ifdef RENEWAL + Assert_ret(0); + return 0; +#else // not RENEWAL + int matk = st->int_ + (st->int_ / 7) * (st->int_ / 7); + return cap_value(matk, battle_config.matk_min, battle_config.matk_max); +#endif // RENEWAL +} + +static int status_base_matk_max(const struct status_data *st) +{ + nullpo_ret(st); + int matk = st->int_ + (st->int_ / 5) * (st->int_ / 5); + return cap_value(matk, battle_config.matk_min, battle_config.matk_max); +} -unsigned short status_base_matk(struct block_list *bl, const struct status_data *st, int level) { +static int status_base_matk(struct block_list *bl, const struct status_data *st, int level) +{ #ifdef RENEWAL - switch ( bl->type ) { + nullpo_ret(bl); + nullpo_ret(st); + int matk = 0; + switch (bl->type) { case BL_MOB: - return st->int_ + level; + matk = st->int_ + level; + break; case BL_HOM: - return status_get_homint(st, BL_UCCAST(BL_HOM, bl)) + level; + matk = status_get_homint(st, BL_UCCAST(BL_HOM, bl)) + level; + break; case BL_MER: - return st->int_ + st->int_ / 5 * st->int_ / 5; + matk = st->int_ + st->int_ / 5 * st->int_ / 5; + break; case BL_PC: default: // temporary until all are formulated - return st->int_ + (st->int_ / 2) + (st->dex / 5) + (st->luk / 3) + (level / 4); + matk = st->int_ + (st->int_ / 2) + (st->dex / 5) + (st->luk / 3) + (level / 4); + break; } + return cap_value(matk, battle_config.matk_min, battle_config.matk_max); #else + Assert_ret(0); return 0; #endif } //Fills in the misc data that can be calculated from the other status info (except for level) -void status_calc_misc(struct block_list *bl, struct status_data *st, int level) { +static void status_calc_misc(struct block_list *bl, struct status_data *st, int level) +{ + nullpo_retv(bl); + nullpo_retv(st); //Non players get the value set, players need to stack with previous bonuses. if ( bl->type != BL_PC ) st->batk = @@ -4350,8 +4398,8 @@ void status_calc_misc(struct block_list *bl, struct status_data *st, int level) st->mdef2 += (int)(bl->type == BL_PC ? (st->int_ + ((float)level / 4) + ((float)(st->dex + st->vit) / 5)) : ((float)(st->int_ + level) / 4)); //(every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef) } #else // not RENEWAL - st->matk_min = status_base_matk_min(st); - st->matk_max = status_base_matk_max(st); + st->matk_min = status->base_matk_min(st); + st->matk_max = status->base_matk_max(st); st->hit += level + st->dex; st->flee += level + st->agi; st->def2 += st->vit; @@ -4370,7 +4418,7 @@ void status_calc_misc(struct block_list *bl, struct status_data *st, int level) if ( st->batk ) { int temp = st->batk + status->base_atk(bl, st); - st->batk = cap_value(temp, 0, USHRT_MAX); + st->batk = cap_value(temp, battle_config.batk_min, battle_config.batk_max); } else st->batk = status->base_atk(bl, st); if ( st->cri ) { @@ -4386,7 +4434,7 @@ void status_calc_misc(struct block_list *bl, struct status_data *st, int level) break; case BL_MER: #ifdef RENEWAL - st->matk_min = st->matk_max = status_base_matk_max(st); + st->matk_min = st->matk_max = status->base_matk_max(st); st->def2 = st->vit + level / 10 + st->vit / 5; st->mdef2 = level / 10 + st->int_ / 5; #endif @@ -4403,9 +4451,9 @@ void status_calc_misc(struct block_list *bl, struct status_data *st, int level) } /*========================================== -* Apply shared stat mods from status changes [DracoRPG] -*------------------------------------------*/ -unsigned short status_calc_str(struct block_list *bl, struct status_change *sc, int str) + * Apply shared stat mods from status changes [DracoRPG] + *------------------------------------------*/ +static unsigned short status_calc_str(struct block_list *bl, struct status_change *sc, int str) { if(!sc || !sc->count) return cap_value(str,0,USHRT_MAX); @@ -4468,7 +4516,7 @@ unsigned short status_calc_str(struct block_list *bl, struct status_change *sc, return (unsigned short)cap_value(str,0,USHRT_MAX); } -unsigned short status_calc_agi(struct block_list *bl, struct status_change *sc, int agi) +static unsigned short status_calc_agi(struct block_list *bl, struct status_change *sc, int agi) { if(!sc || !sc->count) return cap_value(agi,0,USHRT_MAX); @@ -4522,13 +4570,16 @@ unsigned short status_calc_agi(struct block_list *bl, struct status_change *sc, if (sc->data[SC_2011RWC]) agi += sc->data[SC_2011RWC]->val1; - if(sc->data[SC_MARSHOFABYSS]) + if (sc->data[SC_MARSHOFABYSS]) agi -= agi * sc->data[SC_MARSHOFABYSS]->val2 / 100; + if (sc->data[SC_ARCLOUSEDASH]) + agi += sc->data[SC_ARCLOUSEDASH]->val2; + return (unsigned short)cap_value(agi,0,USHRT_MAX); } -unsigned short status_calc_vit(struct block_list *bl, struct status_change *sc, int vit) +static unsigned short status_calc_vit(struct block_list *bl, struct status_change *sc, int vit) { if(!sc || !sc->count) return cap_value(vit,0,USHRT_MAX); @@ -4579,8 +4630,9 @@ unsigned short status_calc_vit(struct block_list *bl, struct status_change *sc, return (unsigned short)cap_value(vit,0,USHRT_MAX); } -unsigned short status_calc_int(struct block_list *bl, struct status_change *sc, int int_) +static unsigned short status_calc_int(struct block_list *bl, struct status_change *sc, int int_) { + nullpo_ret(bl); if(!sc || !sc->count) return cap_value(int_,0,USHRT_MAX); @@ -4645,8 +4697,9 @@ unsigned short status_calc_int(struct block_list *bl, struct status_change *sc, return (unsigned short)cap_value(int_,0,USHRT_MAX); } -unsigned short status_calc_dex(struct block_list *bl, struct status_change *sc, int dex) +static unsigned short status_calc_dex(struct block_list *bl, struct status_change *sc, int dex) { + nullpo_ret(bl); if(!sc || !sc->count) return cap_value(dex,0,USHRT_MAX); @@ -4707,7 +4760,9 @@ unsigned short status_calc_dex(struct block_list *bl, struct status_change *sc, return (unsigned short)cap_value(dex,0,USHRT_MAX); } -unsigned short status_calc_luk(struct block_list *bl, struct status_change *sc, int luk) { +static unsigned short status_calc_luk(struct block_list *bl, struct status_change *sc, int luk) +{ + nullpo_ret(bl); if (!sc || !sc->count) return cap_value(luk, 0, USHRT_MAX); @@ -4759,16 +4814,22 @@ unsigned short status_calc_luk(struct block_list *bl, struct status_change *sc, return (unsigned short)cap_value(luk, 0, USHRT_MAX); } -unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc, int batk, bool viewable) + +static int status_calc_batk(struct block_list *bl, struct status_change *sc, int batk, bool viewable) { + nullpo_ret(bl); if(!sc || !sc->count) - return cap_value(batk,0,USHRT_MAX); + return cap_value(batk, battle_config.batk_min, battle_config.batk_max); if( !viewable ){ /* some statuses that are hidden in the status window */ if(sc->data[SC_PLUSATTACKPOWER]) batk += sc->data[SC_PLUSATTACKPOWER]->val1; - return (unsigned short)cap_value(batk,0,USHRT_MAX); + if (sc->data[SC_POPECOOKIE] != NULL) + batk += batk * sc->data[SC_POPECOOKIE]->val1 / 100; + if (sc->data[SC_VITALIZE_POTION] != NULL) + batk += batk * sc->data[SC_VITALIZE_POTION]->val1 / 100; + return cap_value(batk, battle_config.batk_min, battle_config.batk_max); } #ifndef RENEWAL if(sc->data[SC_PLUSATTACKPOWER]) @@ -4807,9 +4868,6 @@ unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc, #ifndef RENEWAL if(sc->data[SC_LKCONCENTRATION]) batk += batk * sc->data[SC_LKCONCENTRATION]->val2/100; -#else - if ( sc->data[SC_NOEQUIPWEAPON] && bl->type != BL_PC ) - batk -= batk * sc->data[SC_NOEQUIPWEAPON]->val2 / 100; #endif if(sc->data[SC_SKE]) batk += batk * 3; @@ -4850,14 +4908,22 @@ unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc, batk += batk * sc->data[SC_2011RWC]->val2 / 100; if (sc->data[SC_STEAMPACK]) batk += sc->data[SC_STEAMPACK]->val1; + if (sc->data[SC_SKF_ATK] != NULL) + batk += sc->data[SC_SKF_ATK]->val1; + if (sc->data[SC_ALMIGHTY] != NULL) + batk += sc->data[SC_ALMIGHTY]->val1; + + if (sc->data[SC_SHRIMP]) + batk += batk * sc->data[SC_SHRIMP]->val2 / 100; - return (unsigned short)cap_value(batk,0,USHRT_MAX); + return cap_value(batk, battle_config.batk_min, battle_config.batk_max); } -unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc, int watk, bool viewable) +static int status_calc_watk(struct block_list *bl, struct status_change *sc, int watk, bool viewable) { + nullpo_ret(bl); if(!sc || !sc->count) - return cap_value(watk,0,USHRT_MAX); + return cap_value(watk, battle_config.watk_min, battle_config.watk_max); if( !viewable ){ /* some statuses that are hidden in the status window */ @@ -4865,7 +4931,7 @@ unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc, watk -= sc->data[SC_WATER_BARRIER]->val3; if(sc->data[SC_GENTLETOUCH_CHANGE] && sc->data[SC_GENTLETOUCH_CHANGE]->val2) watk += sc->data[SC_GENTLETOUCH_CHANGE]->val2; - return (unsigned short)cap_value(watk,0,USHRT_MAX); + return cap_value(watk, battle_config.watk_min, battle_config.watk_max); } #ifndef RENEWAL if(sc->data[SC_IMPOSITIO]) @@ -4908,7 +4974,7 @@ unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc, if(sc->data[SC_LKCONCENTRATION]) watk += watk * sc->data[SC_LKCONCENTRATION]->val2/100; #endif - if(sc->data[SC_INCATKRATE] && bl->type != BL_MOB) + if(sc->data[SC_INCATKRATE]) watk += watk * sc->data[SC_INCATKRATE]->val1/100; if(sc->data[SC_PROVOKE]) watk += watk * sc->data[SC_PROVOKE]->val3/100; @@ -4918,10 +4984,8 @@ unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc, watk += watk * sc->data[SC_HLIF_FLEET]->val3/100; if(sc->data[SC_CURSE]) watk -= watk * 25/100; -#ifndef RENEWAL if(sc->data[SC_NOEQUIPWEAPON] && bl->type != BL_PC) watk -= watk * sc->data[SC_NOEQUIPWEAPON]->val2/100; -#endif if(sc->data[SC__ENERVATION]) watk -= watk * sc->data[SC__ENERVATION]->val2 / 100; if(sc->data[SC_RUSH_WINDMILL]) @@ -4942,14 +5006,17 @@ unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc, watk += watk * sc->data[SC_ANGRIFFS_MODUS]->val2/100; if( sc->data[SC_FLASHCOMBO] ) watk += sc->data[SC_FLASHCOMBO]->val2; + if (sc->data[SC_CATNIPPOWDER]) + watk -= watk * sc->data[SC_CATNIPPOWDER]->val2 / 100; - return (unsigned short)cap_value(watk,0,USHRT_MAX); + return cap_value(watk, battle_config.watk_min, battle_config.watk_max); } -unsigned short status_calc_ematk(struct block_list *bl, struct status_change *sc, int matk) { -#ifdef RENEWAL +static int status_calc_ematk(struct block_list *bl, struct status_change *sc, int matk) +{ +#ifdef RENEWAL if (!sc || !sc->count) - return cap_value(matk,0,USHRT_MAX); + return cap_value(matk, battle_config.matk_min, battle_config.matk_max); if (sc->data[SC_PLUSMAGICPOWER]) matk += sc->data[SC_PLUSMAGICPOWER]->val1; if (sc->data[SC_MATKFOOD]) @@ -4968,21 +5035,28 @@ unsigned short status_calc_ematk(struct block_list *bl, struct status_change *sc matk += 40 + 30 * sc->data[SC_ODINS_POWER]->val1; //70 lvl1, 100lvl2 if(sc->data[SC_IZAYOI]) matk += 25 * sc->data[SC_IZAYOI]->val1; - return (unsigned short)cap_value(matk,0,USHRT_MAX); + if (sc->data[SC_SHRIMP]) + matk += matk * sc->data[SC_SHRIMP]->val2 / 100; + return cap_value(matk, battle_config.matk_min, battle_config.matk_max); #else return 0; #endif } -unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc, int matk, bool viewable) { +static int status_calc_matk(struct block_list *bl, struct status_change *sc, int matk, bool viewable) +{ if (!sc || !sc->count) - return cap_value(matk,0,USHRT_MAX); + return cap_value(matk, battle_config.matk_min, battle_config.matk_max); if (!viewable) { /* some statuses that are hidden in the status window */ if (sc->data[SC_MINDBREAKER]) matk += matk * sc->data[SC_MINDBREAKER]->val2 / 100; - return (unsigned short)cap_value(matk, 0, USHRT_MAX); + if (sc->data[SC_POPECOOKIE] != NULL) + matk += matk * sc->data[SC_POPECOOKIE]->val2 / 100; + if (sc->data[SC_VITALIZE_POTION] != NULL) + matk += matk * sc->data[SC_VITALIZE_POTION]->val2 / 100; + return cap_value(matk, battle_config.matk_min, battle_config.matk_max); } #ifndef RENEWAL @@ -5039,18 +5113,22 @@ unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc, matk += matk * sc->data[SC_2011RWC]->val2 / 100; if (sc->data[SC_MAGIC_CANDY]) matk += sc->data[SC_MAGIC_CANDY]->val1; + if (sc->data[SC_SKF_MATK] != NULL) + matk += sc->data[SC_SKF_MATK]->val1; + if (sc->data[SC_ALMIGHTY] != NULL) + matk += sc->data[SC_ALMIGHTY]->val2; - return (unsigned short)cap_value(matk, 0, USHRT_MAX); + return cap_value(matk, battle_config.matk_min, battle_config.matk_max); } -signed short status_calc_critical(struct block_list *bl, struct status_change *sc, int critical, bool viewable) { - +static int status_calc_critical(struct block_list *bl, struct status_change *sc, int critical, bool viewable) +{ if (!sc || !sc->count) - return cap_value(critical, 10, SHRT_MAX); + return cap_value(critical, battle_config.critical_min, battle_config.critical_max); if (!viewable) { /* some statuses that are hidden in the status window */ - return (short)cap_value(critical, 10, SHRT_MAX); + return cap_value(critical, battle_config.critical_min, battle_config.critical_max); } if (sc->data[SC_CRITICALPERCENT]) @@ -5081,20 +5159,20 @@ signed short status_calc_critical(struct block_list *bl, struct status_change *s if (sc->data[SC_BUCHEDENOEL]) critical += sc->data[SC_BUCHEDENOEL]->val4 * 10; - return (short)cap_value(critical, 10, SHRT_MAX); + return cap_value(critical, battle_config.critical_min, battle_config.critical_max); } -signed short status_calc_hit(struct block_list *bl, struct status_change *sc, int hit, bool viewable) +static int status_calc_hit(struct block_list *bl, struct status_change *sc, int hit, bool viewable) { if (!sc || !sc->count) - return cap_value(hit, 1, SHRT_MAX); + return cap_value(hit, battle_config.hit_min, battle_config.hit_max); if (!viewable) { /* some statuses that are hidden in the status window */ if (sc->data[SC_MTF_ASPD]) hit += sc->data[SC_MTF_ASPD]->val2; - return (short)cap_value(hit, 1, SHRT_MAX); + return cap_value(hit, battle_config.hit_min, battle_config.hit_max); } if (sc->data[SC_INCHIT]) @@ -5136,24 +5214,26 @@ signed short status_calc_hit(struct block_list *bl, struct status_change *sc, in if (sc->data[SC_BUCHEDENOEL]) hit += sc->data[SC_BUCHEDENOEL]->val3; - return (short)cap_value(hit, 1, SHRT_MAX); + return cap_value(hit, battle_config.hit_min, battle_config.hit_max); } -signed short status_calc_flee(struct block_list *bl, struct status_change *sc, int flee, bool viewable) { +static int status_calc_flee(struct block_list *bl, struct status_change *sc, int flee, bool viewable) +{ + nullpo_retr(1, bl); if (bl->type == BL_PC) { if (map_flag_gvg2(bl->m)) flee -= flee * battle_config.gvg_flee_penalty / 100; - else if( map->list[bl->m].flag.battleground ) + else if (map->list[bl->m].flag.battleground) flee -= flee * battle_config.bg_flee_penalty / 100; } if (!sc || !sc->count) - return cap_value(flee, 1, SHRT_MAX); + return cap_value(flee, battle_config.flee_min, battle_config.flee_max); if (!viewable) { /* some statuses that are hidden in the status window */ - return (short)cap_value(flee, 1, SHRT_MAX); + return cap_value(flee, battle_config.flee_min, battle_config.flee_max); } if (sc->data[SC_INCFLEE]) @@ -5231,17 +5311,17 @@ signed short status_calc_flee(struct block_list *bl, struct status_change *sc, i if (sc->data[SC_MYSTICPOWDER]) flee += sc->data[SC_MYSTICPOWDER]->val2; - return (short)cap_value(flee, 1, SHRT_MAX); + return cap_value(flee, battle_config.flee_min, battle_config.flee_max); } -signed short status_calc_flee2(struct block_list *bl, struct status_change *sc, int flee2, bool viewable) +static int status_calc_flee2(struct block_list *bl, struct status_change *sc, int flee2, bool viewable) { if(!sc || !sc->count) - return cap_value(flee2,10,SHRT_MAX); + return cap_value(flee2, battle_config.flee2_min, battle_config.flee2_max); if( !viewable ){ /* some statuses that are hidden in the status window */ - return (short)cap_value(flee2,10,SHRT_MAX); + return cap_value(flee2, battle_config.flee2_min, battle_config.flee2_max); } if(sc->data[SC_PLUSAVOIDVALUE]) @@ -5253,10 +5333,12 @@ signed short status_calc_flee2(struct block_list *bl, struct status_change *sc, if (sc->data[SC_FREYJASCROLL]) flee2 += sc->data[SC_FREYJASCROLL]->val2; - return (short)cap_value(flee2,10,SHRT_MAX); + return cap_value(flee2, battle_config.flee2_min, battle_config.flee2_max); } -defType status_calc_def(struct block_list *bl, struct status_change *sc, int def, bool viewable) + +static defType status_calc_def(struct block_list *bl, struct status_change *sc, int def, bool viewable) { + nullpo_retr(DEFTYPE_MIN, bl); if (!sc || !sc->count) return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX); @@ -5359,8 +5441,9 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX); } -signed short status_calc_def2(struct block_list *bl, struct status_change *sc, int def2, bool viewable) +static signed short status_calc_def2(struct block_list *bl, struct status_change *sc, int def2, bool viewable) { + nullpo_retr(1, bl); if(!sc || !sc->count) #ifdef RENEWAL return (short)cap_value(def2,SHRT_MIN,SHRT_MAX); @@ -5435,7 +5518,8 @@ signed short status_calc_def2(struct block_list *bl, struct status_change *sc, i #endif } -defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int mdef, bool viewable) { +static defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int mdef, bool viewable) +{ if(!sc || !sc->count) return (defType)cap_value(mdef,DEFTYPE_MIN,DEFTYPE_MAX); @@ -5491,7 +5575,7 @@ defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int md return (defType)cap_value(mdef,DEFTYPE_MIN,DEFTYPE_MAX); } -signed short status_calc_mdef2(struct block_list *bl, struct status_change *sc, int mdef2, bool viewable) +static signed short status_calc_mdef2(struct block_list *bl, struct status_change *sc, int mdef2, bool viewable) { if(!sc || !sc->count) #ifdef RENEWAL @@ -5530,22 +5614,25 @@ signed short status_calc_mdef2(struct block_list *bl, struct status_change *sc, #endif } -unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc, int speed) +static unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc, int speed) { struct map_session_data *sd = BL_CAST(BL_PC, bl); - int speed_rate; + int speed_rate = -1; if( sc == NULL || ( sd && sd->state.permanent_speed ) ) return (unsigned short)cap_value(speed,MIN_WALK_SPEED,MAX_WALK_SPEED); - if( sd && sd->ud.skilltimer != INVALID_TIMER && (pc->checkskill(sd,SA_FREECAST) > 0 || sd->ud.skill_id == LG_EXEEDBREAK) ) + if (sd && sd->ud.skilltimer != INVALID_TIMER) { - if( sd->ud.skill_id == LG_EXEEDBREAK ) + if (sd->ud.skill_id == LG_EXEEDBREAK) { speed_rate = 160 - 10 * sd->ud.skill_lv; - else + } else if ((skill->get_inf2(sd->ud.skill_id) & INF2_FREE_CAST_REDUCED) != 0) { + speed_rate = 175 - 5 * sd->ud.skill_lv; + } else if (pc->checkskill(sd, SA_FREECAST) > 0) { speed_rate = 175 - 5 * pc->checkskill(sd,SA_FREECAST); + } } - else + if (speed_rate == -1) { speed_rate = 100; @@ -5576,9 +5663,9 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc { int val = 0; - if( sd && sc->data[SC_HIDING] && pc->checkskill(sd,RG_TUNNELDRIVE) > 0 ) + if ( sd && sc->data[SC_HIDING] && pc->checkskill(sd,RG_TUNNELDRIVE) > 0 ) { val = 120 - 6 * pc->checkskill(sd,RG_TUNNELDRIVE); - else + } else { if( sd && sc->data[SC_CHASEWALK] && sc->data[SC_CHASEWALK]->val3 < 0 ) val = sc->data[SC_CHASEWALK]->val3; else @@ -5644,12 +5731,14 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc if (sc->data[SC_DEC_AGI] || sc->data[SC_QUAGMIRE] || sc->data[SC_DONTFORGETME]) return 0; } + if (sc->data[SC_CATNIPPOWDER]) + val = max(val, sc->data[SC_CATNIPPOWDER]->val3); if( sd && sd->bonus.speed_rate + sd->bonus.speed_add_rate > 0 ) // permanent item-based speedup val = max( val, sd->bonus.speed_rate + sd->bonus.speed_add_rate ); } - - speed_rate += val; + } + speed_rate += val; } //GetMoveHasteValue1() @@ -5666,7 +5755,7 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc val = max( val, 2 * sc->data[SC_WINDWALK]->val1 ); if( sc->data[SC_CARTBOOST] ) val = max( val, 20 ); - if( sd && (sd->class_&MAPID_UPPERMASK) == MAPID_ASSASSIN && pc->checkskill(sd,TF_MISS) > 0 ) + if (sd != NULL && (sd->job & MAPID_UPPERMASK) == MAPID_ASSASSIN && pc->checkskill(sd,TF_MISS) > 0) val = max( val, 1 * pc->checkskill(sd,TF_MISS) ); if( sc->data[SC_CLOAKING] && (sc->data[SC_CLOAKING]->val4&1) == 1 ) val = max( val, sc->data[SC_CLOAKING]->val1 >= 10 ? 25 : 3 * sc->data[SC_CLOAKING]->val1 - 3 ); @@ -5694,6 +5783,8 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc val = max(val, sc->data[SC_MOVHASTE_HORSE]->val1); if( sd && sd->bonus.speed_rate + sd->bonus.speed_add_rate < 0 ) // permanent item-based speedup val = max( val, -(sd->bonus.speed_rate + sd->bonus.speed_add_rate) ); + if (sc->data[SC_ARCLOUSEDASH]) + val = max(val, sc->data[SC_ARCLOUSEDASH]->val3); speed_rate -= val; } @@ -5726,10 +5817,12 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc // flag&1 - fixed value [malufett] // flag&2 - percentage value -short status_calc_aspd(struct block_list *bl, struct status_change *sc, short flag) { +static short status_calc_aspd(struct block_list *bl, struct status_change *sc, short flag) +{ #ifdef RENEWAL_ASPD int pots = 0, bonus = 0; + nullpo_ret(bl); if (!sc || !sc->count) return 0; @@ -5764,7 +5857,7 @@ short status_calc_aspd(struct block_list *bl, struct status_change *sc, short fl if (bl->type != BL_PC) { bonus = sc->data[SC_ASSNCROS]->val2; } else { - switch (BL_UCCAST(BL_PC, bl)->status.weapon) { + switch (BL_UCCAST(BL_PC, bl)->weapontype) { case W_BOW: case W_REVOLVER: case W_RIFLE: @@ -5848,6 +5941,8 @@ short status_calc_aspd(struct block_list *bl, struct status_change *sc, short fl bonus += sc->data[SC_BATTLESCROLL]->val1; if (sc->data[SC_STEAMPACK]) bonus += sc->data[SC_STEAMPACK]->val2; + if (sc->data[SC_SKF_ASPD] != NULL) + bonus += sc->data[SC_SKF_ASPD]->val1; } return (bonus + pots); @@ -5856,7 +5951,9 @@ short status_calc_aspd(struct block_list *bl, struct status_change *sc, short fl #endif } -short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int aspd) { +static short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int aspd) +{ + nullpo_ret(bl); if (!sc || !sc->count) return cap_value(aspd, 0, 2000); @@ -5874,10 +5971,11 @@ short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int /// Calculates an object's ASPD modifier (alters the base amotion value). /// Note that the scale of aspd_rate is 1000 = 100%. -short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int aspd_rate) +static short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int aspd_rate) { int i; + nullpo_ret(bl); if(!sc || !sc->count) return cap_value(aspd_rate,0,SHRT_MAX); @@ -5922,7 +6020,7 @@ short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int if (bl->type != BL_PC) { max = sc->data[SC_ASSNCROS]->val2; } else { - switch (BL_UCCAST(BL_PC, bl)->status.weapon) { + switch (BL_UCCAST(BL_PC, bl)->weapontype) { case W_BOW: case W_REVOLVER: case W_RIFLE: @@ -6012,12 +6110,15 @@ short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int aspd_rate += sc->data[SC_BATTLESCROLL]->val1 * 10; if (sc->data[SC_STEAMPACK]) aspd_rate += sc->data[SC_STEAMPACK]->val2 * 10; + if (sc->data[SC_SKF_ASPD] != NULL) + aspd_rate -= sc->data[SC_SKF_ASPD]->val1 * 10; return (short)cap_value(aspd_rate,0,SHRT_MAX); } -unsigned short status_calc_dmotion(struct block_list *bl, struct status_change *sc, int dmotion) +static unsigned short status_calc_dmotion(struct block_list *bl, struct status_change *sc, int dmotion) { + nullpo_ret(bl); // It has been confirmed on official servers that MvP mobs have no dmotion even without endure if (bl->type == BL_MOB && (BL_UCCAST(BL_MOB, bl)->status.mode&MD_BOSS)) return 0; @@ -6033,7 +6134,8 @@ unsigned short status_calc_dmotion(struct block_list *bl, struct status_change * return (unsigned short)cap_value(dmotion,0,USHRT_MAX); } -unsigned int status_calc_maxhp(struct block_list *bl, struct status_change *sc, uint64 maxhp) { +static unsigned int status_calc_maxhp(struct block_list *bl, struct status_change *sc, uint64 maxhp) +{ if (!sc || !sc->count) return (unsigned int)cap_value(maxhp, 1, UINT_MAX); @@ -6112,8 +6214,8 @@ unsigned int status_calc_maxhp(struct block_list *bl, struct status_change *sc, return (unsigned int)cap_value(maxhp, 1, UINT_MAX); } -unsigned int status_calc_maxsp(struct block_list *bl, struct status_change *sc, unsigned int maxsp) { - +static unsigned int status_calc_maxsp(struct block_list *bl, struct status_change *sc, unsigned int maxsp) +{ if (!sc || !sc->count) return cap_value(maxsp, 1, UINT_MAX); @@ -6151,7 +6253,7 @@ unsigned int status_calc_maxsp(struct block_list *bl, struct status_change *sc, return cap_value(maxsp, 1, UINT_MAX); } -unsigned char status_calc_element(struct block_list *bl, struct status_change *sc, int element) +static unsigned char status_calc_element(struct block_list *bl, struct status_change *sc, int element) { if(!sc || !sc->count) return element; @@ -6172,7 +6274,7 @@ unsigned char status_calc_element(struct block_list *bl, struct status_change *s return (unsigned char)cap_value(element,0,UCHAR_MAX); } -unsigned char status_calc_element_lv(struct block_list *bl, struct status_change *sc, int lv) +static unsigned char status_calc_element_lv(struct block_list *bl, struct status_change *sc, int lv) { if(!sc || !sc->count) return lv; @@ -6195,7 +6297,7 @@ unsigned char status_calc_element_lv(struct block_list *bl, struct status_change return (unsigned char)cap_value(lv,1,4); } -unsigned char status_calc_attack_element(struct block_list *bl, struct status_change *sc, int element) +static unsigned char status_calc_attack_element(struct block_list *bl, struct status_change *sc, int element) { if(!sc || !sc->count) return element; @@ -6236,7 +6338,7 @@ unsigned char status_calc_attack_element(struct block_list *bl, struct status_ch * @param mode The starting mode. * @return The calculated mode. */ -uint32 status_calc_mode(const struct block_list *bl, const struct status_change *sc, uint32 mode) +static uint32 status_calc_mode(const struct block_list *bl, const struct status_change *sc, uint32 mode) { if (sc == NULL || sc->count == 0) return mode & MD_MASK; @@ -6257,7 +6359,7 @@ uint32 status_calc_mode(const struct block_list *bl, const struct status_change * @param bl The requested bl. * @return The bl's name or NULL if not available. */ -const char *status_get_name(const struct block_list *bl) +static const char *status_get_name(const struct block_list *bl) { nullpo_ret(bl); switch (bl->type) { @@ -6277,17 +6379,17 @@ const char *status_get_name(const struct block_list *bl) } /*========================================== -* Get the class of the current bl -* return -* 0 = fail -* class_id = success -*------------------------------------------*/ -int status_get_class(const struct block_list *bl) + * Get the class of the current bl + * return + * 0 = fail + * class_id = success + *------------------------------------------*/ +static int status_get_class(const struct block_list *bl) { nullpo_ret(bl); switch (bl->type) { - case BL_PC: return BL_UCCAST(BL_PC, bl)->status.class_; - case BL_MOB: return BL_UCCAST(BL_MOB, bl)->vd->class_; //Class used on all code should be the view class of the mob. + case BL_PC: return BL_UCCAST(BL_PC, bl)->status.class; + case BL_MOB: return BL_UCCAST(BL_MOB, bl)->vd->class; //Class used on all code should be the view class of the mob. case BL_PET: return BL_UCCAST(BL_PET, bl)->pet.class_; case BL_HOM: return BL_UCCAST(BL_HOM, bl)->homunculus.class_; case BL_MER: return BL_UCCAST(BL_MER, bl)->mercenary.class_; @@ -6297,12 +6399,12 @@ int status_get_class(const struct block_list *bl) return 0; } /*========================================== -* Get the base level of the current bl -* return -* 1 = fail -* level = success -*------------------------------------------*/ -int status_get_lv(const struct block_list *bl) + * Get the base level of the current bl + * return + * 1 = fail + * level = success + *------------------------------------------*/ +static int status_get_lv(const struct block_list *bl) { nullpo_ret(bl); switch (bl->type) { @@ -6317,7 +6419,7 @@ int status_get_lv(const struct block_list *bl) return 1; } -struct regen_data *status_get_regen_data(struct block_list *bl) +static struct regen_data *status_get_regen_data(struct block_list *bl) { nullpo_retr(NULL, bl); switch (bl->type) { @@ -6330,7 +6432,7 @@ struct regen_data *status_get_regen_data(struct block_list *bl) } } -struct status_data *status_get_status_data(struct block_list *bl) +static struct status_data *status_get_status_data(struct block_list *bl) { nullpo_retr(&status->dummy, bl); @@ -6351,7 +6453,7 @@ struct status_data *status_get_status_data(struct block_list *bl) } } -struct status_data *status_get_base_status(struct block_list *bl) +static struct status_data *status_get_base_status(struct block_list *bl) { nullpo_retr(NULL, bl); switch (bl->type) { @@ -6374,7 +6476,9 @@ struct status_data *status_get_base_status(struct block_list *bl) return NULL; } } -defType status_get_def(struct block_list *bl) { + +static defType status_get_def(struct block_list *bl) +{ struct unit_data *ud; struct status_data *st = status->get_status_data(bl); int def = st ? st->def : 0; @@ -6385,14 +6489,15 @@ defType status_get_def(struct block_list *bl) { return cap_value(def, DEFTYPE_MIN, DEFTYPE_MAX); } -unsigned short status_get_speed(struct block_list *bl) +static unsigned short status_get_speed(struct block_list *bl) { + nullpo_ret(bl); if (bl->type == BL_NPC) //Only BL with speed data but no status_data [Skotlex] return BL_UCCAST(BL_NPC, bl)->speed; return status->get_status_data(bl)->speed; } -int status_get_party_id(const struct block_list *bl) +static int status_get_party_id(const struct block_list *bl) { nullpo_ret(bl); switch (bl->type) { @@ -6448,7 +6553,7 @@ int status_get_party_id(const struct block_list *bl) return 0; } -int status_get_guild_id(const struct block_list *bl) +static int status_get_guild_id(const struct block_list *bl) { nullpo_ret(bl); switch (bl->type) { @@ -6514,7 +6619,7 @@ int status_get_guild_id(const struct block_list *bl) return 0; } -int status_get_emblem_id(const struct block_list *bl) +static int status_get_emblem_id(const struct block_list *bl) { nullpo_ret(bl); switch (bl->type) { @@ -6576,7 +6681,7 @@ int status_get_emblem_id(const struct block_list *bl) return 0; } -int status_get_mexp(const struct block_list *bl) +static int status_get_mexp(const struct block_list *bl) { nullpo_ret(bl); if (bl->type == BL_MOB) @@ -6586,7 +6691,7 @@ int status_get_mexp(const struct block_list *bl) return 0; } -int status_get_race2(const struct block_list *bl) +static int status_get_race2(const struct block_list *bl) { nullpo_ret(bl); if (bl->type == BL_MOB) @@ -6596,12 +6701,13 @@ int status_get_race2(const struct block_list *bl) return 0; } -int status_isdead(struct block_list *bl) { +static int status_isdead(struct block_list *bl) +{ nullpo_ret(bl); return status->get_status_data(bl)->hp == 0; } -int status_isimmune(struct block_list *bl) +static int status_isimmune(struct block_list *bl) { struct status_change *sc = NULL; nullpo_ret(bl); @@ -6618,14 +6724,14 @@ int status_isimmune(struct block_list *bl) return 0; } -struct view_data *status_get_viewdata(struct block_list *bl) +static struct view_data *status_get_viewdata(struct block_list *bl) { nullpo_retr(NULL, bl); switch (bl->type) { case BL_PC: return &BL_UCAST(BL_PC, bl)->vd; case BL_MOB: return BL_UCAST(BL_MOB, bl)->vd; case BL_PET: return &BL_UCAST(BL_PET, bl)->vd; - case BL_NPC: return BL_UCAST(BL_NPC, bl)->vd; + case BL_NPC: return &BL_UCAST(BL_NPC, bl)->vd; case BL_HOM: return BL_UCAST(BL_HOM, bl)->vd; case BL_MER: return BL_UCAST(BL_MER, bl)->vd; case BL_ELEM: return BL_UCAST(BL_ELEM, bl)->vd; @@ -6633,7 +6739,7 @@ struct view_data *status_get_viewdata(struct block_list *bl) return NULL; } -void status_set_viewdata(struct block_list *bl, int class_) +static void status_set_viewdata(struct block_list *bl, int class_) { struct view_data* vd; nullpo_retv(bl); @@ -6678,36 +6784,33 @@ void status_set_viewdata(struct block_list *bl, int class_) break; } } - sd->vd.class_ = class_; + sd->vd.class = class_; clif->get_weapon_view(sd, &sd->vd.weapon, &sd->vd.shield); - sd->vd.head_top = sd->status.head_top; - sd->vd.head_mid = sd->status.head_mid; - sd->vd.head_bottom = sd->status.head_bottom; + sd->vd.head_top = sd->status.look.head_top; + sd->vd.head_mid = sd->status.look.head_mid; + sd->vd.head_bottom = sd->status.look.head_bottom; sd->vd.hair_style = cap_value(sd->status.hair,0,battle_config.max_hair_style); sd->vd.hair_color = cap_value(sd->status.hair_color,0,battle_config.max_hair_color); sd->vd.cloth_color = cap_value(sd->status.clothes_color,0,battle_config.max_cloth_color); - sd->vd.robe = sd->status.robe; + sd->vd.robe = sd->status.look.robe; sd->vd.body_style = sd->status.body; sd->vd.sex = sd->status.sex; if (sd->vd.cloth_color) { - if (sd->sc.option&OPTION_WEDDING && battle_config.wedding_ignorepalette) - sd->vd.cloth_color = 0; - if (sd->sc.option&OPTION_XMAS && battle_config.xmas_ignorepalette) - sd->vd.cloth_color = 0; - if (sd->sc.option&OPTION_SUMMER && battle_config.summer_ignorepalette) - sd->vd.cloth_color = 0; - if (sd->sc.option&OPTION_HANBOK && battle_config.hanbok_ignorepalette) - sd->vd.cloth_color = 0; - if (sd->sc.option&OPTION_OKTOBERFEST /* TODO: config? */) + if ((sd->sc.option & OPTION_WEDDING) != 0 && battle_config.wedding_ignorepalette == true) + sd->vd.cloth_color = 0; + if ((sd->sc.option & OPTION_XMAS) != 0 && battle_config.xmas_ignorepalette == true) + sd->vd.cloth_color = 0; + if ((sd->sc.option & OPTION_SUMMER) != 0 && battle_config.summer_ignorepalette == true) + sd->vd.cloth_color = 0; + if ((sd->sc.option & OPTION_HANBOK) != 0 && battle_config.hanbok_ignorepalette == true) + sd->vd.cloth_color = 0; + if ((sd->sc.option & OPTION_OKTOBERFEST) != 0 && battle_config.oktoberfest_ignorepalette == true) + sd->vd.cloth_color = 0; + if ((sd->sc.option & OPTION_SUMMER2) != 0 && battle_config.summer2_ignorepalette == true) sd->vd.cloth_color = 0; } - if (sd->vd.body_style - && (sd->sc.option&OPTION_WEDDING - || sd->sc.option&OPTION_XMAS - || sd->sc.option&OPTION_SUMMER - || sd->sc.option&OPTION_HANBOK - || sd->sc.option&OPTION_OKTOBERFEST)) + if (sd->vd.body_style != 0 && (sd->sc.option & OPTION_COSTUME) != 0) sd->vd.body_style = 0; } else if (vd != NULL) { memcpy(&sd->vd, vd, sizeof(struct view_data)); @@ -6730,7 +6833,7 @@ void status_set_viewdata(struct block_list *bl, int class_) struct pet_data *pd = BL_UCAST(BL_PET, bl); if (vd != NULL) { memcpy(&pd->vd, vd, sizeof(struct view_data)); - if (!pc->db_checkid(vd->class_)) { + if (!pc->db_checkid(vd->class)) { pd->vd.hair_style = battle_config.pet_hair_style; if(pd->pet.equip) { pd->vd.head_bottom = itemdb_viewid(pd->pet.equip); @@ -6746,10 +6849,14 @@ void status_set_viewdata(struct block_list *bl, int class_) case BL_NPC: { struct npc_data *nd = BL_UCAST(BL_NPC, bl); - if (vd != NULL) - nd->vd = vd; - else + if (vd != NULL) { + memcpy(&nd->vd, vd, sizeof(struct view_data)); + } else if (pc->db_checkid(class_)) { + memset(&nd->vd, 0, sizeof(struct view_data)); + nd->vd.class = class_; + } else { ShowError("status_set_viewdata (NPC): No view data for class %d (name=%s)\n", class_, nd->name); + } } break; case BL_HOM: //[blackhole89] @@ -6783,7 +6890,7 @@ void status_set_viewdata(struct block_list *bl, int class_) } /// Returns the status_change data of bl or NULL if it doesn't exist. -struct status_change *status_get_sc(struct block_list *bl) +static struct status_change *status_get_sc(struct block_list *bl) { if (bl != NULL) { switch (bl->type) { @@ -6798,7 +6905,8 @@ struct status_change *status_get_sc(struct block_list *bl) return NULL; } -void status_change_init(struct block_list *bl) { +static void status_change_init(struct block_list *bl) +{ struct status_change *sc = status->get_sc(bl); nullpo_retv(sc); memset(sc, 0, sizeof (struct status_change)); @@ -6810,7 +6918,8 @@ void status_change_init(struct block_list *bl) { * @see status_change_start for the expected parameters. * @return the adjusted duration based on flag values. */ -int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int tick, int flag) { +static int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int tick, int flag) +{ //Percentual resistance: 10000 = 100% Resist //Example: 50% -> sc_def=5000 -> 25%; 5000ms -> tick_def=5000 -> 2500ms int sc_def = 0, tick_def = -1; //-1 = use sc_def @@ -6864,6 +6973,7 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ sd = BL_CAST(BL_PC,bl); st = status->get_status_data(bl); bst = status->get_base_status(bl); + nullpo_ret(bst); sc = status->get_sc(bl); if( sc && !sc->count ) sc = NULL; @@ -7157,6 +7267,9 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ case SC_NETHERWORLD: tick = max(tick, 4000); break; + case SC_SIREN: + tick = max(tick, 10000); // Minimum duration 10s + break; default: //Skills need to trigger even if the duration is reduced below 1ms tick = max(tick, 1); @@ -7167,11 +7280,14 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ #undef SCDEF_LVL_CAP #undef SCDEF_LVL_DIFF } + /* [Ind/Hercules] fast-checkin sc-display array */ -void status_display_add(struct map_session_data *sd, enum sc_type type, int dval1, int dval2, int dval3) { +static void status_display_add(struct map_session_data *sd, enum sc_type type, int dval1, int dval2, int dval3) +{ struct sc_display_entry *entry; int i; + nullpo_retv(sd); for( i = 0; i < sd->sc_display_count; i++ ) { if( sd->sc_display[i]->type == type ) break; @@ -7194,9 +7310,12 @@ void status_display_add(struct map_session_data *sd, enum sc_type type, int dval RECREATE(sd->sc_display, struct sc_display_entry *, ++sd->sc_display_count); sd->sc_display[ sd->sc_display_count - 1 ] = entry; } -void status_display_remove(struct map_session_data *sd, enum sc_type type) { + +static void status_display_remove(struct map_session_data *sd, enum sc_type type) +{ int i; + nullpo_retv(sd); for( i = 0; i < sd->sc_display_count; i++ ) { if( sd->sc_display[i]->type == type ) break; @@ -7226,8 +7345,9 @@ void status_display_remove(struct map_session_data *sd, enum sc_type type) { } } } + /** - * Starts a status change. + * Starts a status change with a set remaining time. * * @param src Status change source bl. * @param bl Status change target bl. @@ -7237,13 +7357,15 @@ void status_display_remove(struct map_session_data *sd, enum sc_type type) { * @param val2 Additional value (meaning depends on type). * @param val3 Additional value (meaning depends on type). * @param val4 Additional value (meaning depends on type). - * @param tick Base duration (milliseconds). + * @param tick Remaining duration (miliseconds). (if flag doesn't contain SCFLAG_LOADED, it will become the final total_tick) + * @param total_tick Base duration (milliseconds). * @param flag Special flags (@see enum scstart_flag). * * @retval 0 if no status change happened. * @retval 1 if the status change was successfully applied. */ -int status_change_start(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int flag) { +static int status_change_start_sub(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int total_tick, int flag) +{ struct map_session_data *sd = NULL; struct status_change* sc; struct status_change_entry* sce; @@ -7256,7 +7378,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t st = status->get_status_data(bl); if (type <= SC_NONE || type >= SC_MAX) { - ShowError("status_change_start: invalid status change (%d)!\n", type); + ShowError("status_change_start_sub: invalid status change (%d)!\n", type); return 0; } @@ -7276,84 +7398,19 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t #endif // 0 } - if( sc->data[SC_REFRESH] ) { - if( type >= SC_COMMON_MIN && type <= SC_COMMON_MAX) // Confirmed. - return 0; // Immune to status ailements - switch( type ) { - case SC_DEEP_SLEEP: - case SC__CHAOS: - case SC_BURNING: - case SC_STUN: - case SC_SLEEP: - case SC_CURSE: - case SC_STONE: - case SC_POISON: - case SC_BLIND: - case SC_SILENCE: - case SC_BLOODING: - case SC_FREEZE: - case SC_FROSTMISTY: - case SC_COLD: - case SC_TOXIN: - case SC_PARALYSE: - case SC_VENOMBLEED: - case SC_MAGICMUSHROOM: - case SC_DEATHHURT: - case SC_PYREXIA: - case SC_OBLIVIONCURSE: - case SC_MARSHOFABYSS: - case SC_MANDRAGORA: - return 0; - } - } else if( sc->data[SC_INSPIRATION] ) { - if( type >= SC_COMMON_MIN && type <= SC_COMMON_MAX ) - return 0; // Immune to status ailements - switch( type ) { - case SC_POISON: - case SC_BLIND: - case SC_STUN: - case SC_SILENCE: - case SC__CHAOS: - case SC_STONE: - case SC_SLEEP: - case SC_BLOODING: - case SC_CURSE: - case SC_BURNING: - case SC_FROSTMISTY: - case SC_FREEZE: - case SC_COLD: - case SC_FEAR: - case SC_TOXIN: - case SC_PARALYSE: - case SC_VENOMBLEED: - case SC_MAGICMUSHROOM: - case SC_DEATHHURT: - case SC_PYREXIA: - case SC_OBLIVIONCURSE: - case SC_LEECHESEND: - case SC_DEEP_SLEEP: - case SC_SATURDAY_NIGHT_FEVER: - case SC__BODYPAINT: - case SC__ENERVATION: - case SC__GROOMY: - case SC__IGNORANCE: - case SC__LAZINESS: - case SC__UNLUCKY: - case SC__WEAKNESS: - return 0; - } - } + if (status->is_immune_to_status(sc, type)) + return 0; sd = BL_CAST(BL_PC, bl); - //Adjust tick according to status resistances + //Adjust total_tick according to status resistances if( !(flag&(SCFLAG_NOAVOID|SCFLAG_LOADED)) ) { - tick = status->get_sc_def(src, bl, type, rate, tick, flag); - if( !tick ) return 0; + total_tick = status->get_sc_def(src, bl, type, rate, total_tick, flag); + if( !total_tick ) return 0; } - undead_flag = battle->check_undead(st->race,st->def_ele); - //Check for inmunities / sc fails + undead_flag = battle->check_undead(st->race, st->def_ele); + // Check for inmunities / sc fails switch (type) { case SC_DRUMBATTLE: case SC_NIBELUNGEN: @@ -7366,8 +7423,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_GOLDENE_FERSE: if ((type==SC_GOLDENE_FERSE && sc->data[SC_ANGRIFFS_MODUS]) || (type==SC_ANGRIFFS_MODUS && sc->data[SC_GOLDENE_FERSE]) - ) + ) { return 0; + } + FALLTHROUGH case SC_VACUUM_EXTREME: if(sc->data[SC_HALLUCINATIONWALK]) return 0; @@ -7375,10 +7434,15 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_STONE: if(sc->data[SC_POWER_OF_GAIA]) return 0; + FALLTHROUGH case SC_FREEZE: //Undead are immune to Freeze/Stone if (undead_flag && !(flag&SCFLAG_NOAVOID)) return 0; + // SC_LEXAETERNA should be removed when applying SC_STONE or SC_FREEZE + if (sc->data[SC_LEXAETERNA] != NULL) + status_change_end(bl, SC_LEXAETERNA, INVALID_TIMER); + FALLTHROUGH case SC_SLEEP: case SC_STUN: case SC_FROSTMISTY: @@ -7405,12 +7469,14 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t return 0; break; case SC_KYRIE: + case SC_TUNAPARTY: if (bl->type == BL_MOB) return 0; break; case SC_OVERTHRUST: if (sc->data[SC_OVERTHRUSTMAX]) return 0; // Overthrust can't take effect if under Max Overthrust. [Skotlex] + FALLTHROUGH case SC_OVERTHRUSTMAX: if (sc->option&OPTION_MADOGEAR) return 0; // Overthrust and Overthrust Max cannot be used on Mado Gear [Ind] @@ -7428,7 +7494,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t return 0; break; case SC_MAGNIFICAT: - if (sc->data[SC_OFFERTORIUM] || sc->option&OPTION_MADOGEAR) // Mado is immune to magnificat + if (sc->option&OPTION_MADOGEAR) // Mado is immune to magnificat return 0; break; case SC_ONEHANDQUICKEN: @@ -7436,6 +7502,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_TWOHANDQUICKEN: if (sc->data[SC_DEC_AGI]) return 0; + FALLTHROUGH case SC_CONCENTRATION: case SC_SPEARQUICKEN: case SC_TRUESIGHT: @@ -7444,6 +7511,7 @@ 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] + FALLTHROUGH case SC_INC_AGI: if (sc->data[SC_QUAGMIRE]) return 0; @@ -7492,11 +7560,12 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t } if (!opt_flag) return 0; } - if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC + if (total_tick == 1) return 1; //Minimal duration: Only strip without causing the SC break; case SC_NOEQUIPSHIELD: - if( val2 == 1 ) val2 = 0; //GX effect. Do not take shield off.. - else + if (val2 == 1) { + val2 = 0; //GX effect. Do not take shield off.. + } else { if (sd && !(flag&SCFLAG_LOADED)) { int i; if(sd->bonus.unstripable_equip&EQP_SHIELD) @@ -7506,8 +7575,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t return 0; pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); } - if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC - break; + } + if (total_tick == 1) + return 1; //Minimal duration: Only strip without causing the SC + break; case SC_NOEQUIPARMOR: if (sd && !(flag&SCFLAG_LOADED)) { int i; @@ -7518,7 +7589,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t return 0; pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); } - if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC + if (total_tick == 1) return 1; //Minimal duration: Only strip without causing the SC break; case SC_NOEQUIPHELM: if (sd && !(flag&SCFLAG_LOADED)) { @@ -7530,7 +7601,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t return 0; pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); } - if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC + if (total_tick == 1) return 1; //Minimal duration: Only strip without causing the SC break; case SC_MER_FLEE: case SC_MER_ATK: @@ -7564,30 +7635,6 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t if (sc->data[SC_FOOD_LUK_CASH] && sc->data[SC_FOOD_LUK_CASH]->val1 > val1) return 0; break; - case SC_FOOD_STR_CASH: - if (sc->data[SC_FOOD_STR] && sc->data[SC_FOOD_STR]->val1 > val1) - return 0; - break; - case SC_FOOD_AGI_CASH: - if (sc->data[SC_FOOD_AGI] && sc->data[SC_FOOD_AGI]->val1 > val1) - return 0; - break; - case SC_FOOD_VIT_CASH: - if (sc->data[SC_FOOD_VIT] && sc->data[SC_FOOD_VIT]->val1 > val1) - return 0; - break; - case SC_FOOD_INT_CASH: - if (sc->data[SC_FOOD_INT] && sc->data[SC_FOOD_INT]->val1 > val1) - return 0; - break; - case SC_FOOD_DEX_CASH: - if (sc->data[SC_FOOD_DEX] && sc->data[SC_FOOD_DEX]->val1 > val1) - return 0; - break; - case SC_FOOD_LUK_CASH: - if (sc->data[SC_FOOD_LUK] && sc->data[SC_FOOD_LUK]->val1 > val1) - return 0; - break; case SC_CAMOUFLAGE: if( sd && pc->checkskill(sd, RA_CAMOUFLAGE) < 3 && !skill->check_camouflage(bl,NULL) ) return 0; @@ -7608,7 +7655,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t if( i < 0 ) return 0; } - if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC + if (total_tick == 1) return 1; //Minimal duration: Only strip without causing the SC break; case SC_TOXIN: case SC_PARALYSE: @@ -7628,305 +7675,17 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t if(sc->data[SC_HOVERING]) return 0; break; - case SC_OFFERTORIUM: - if (sc->data[SC_MAGNIFICAT]) - return 0; - break; } //Check for BOSS resistances - if(st->mode&MD_BOSS && !(flag&SCFLAG_NOAVOID)) { - if (type>=SC_COMMON_MIN && type <= SC_COMMON_MAX) + if (st->mode & MD_BOSS && !(flag & SCFLAG_NOAVOID)) { + if (status->is_boss_resist_sc(type)) return 0; - switch (type) { - case SC_BLESSING: - case SC_DEC_AGI: - case SC_PROVOKE: - case SC_COMA: - case SC_GRAVITATION: - case SC_NJ_SUITON: - case SC_RICHMANKIM: - case SC_ROKISWEIL: - case SC_FOGWALL: - case SC_FROSTMISTY: - case SC_BURNING: - case SC_MARSHOFABYSS: - case SC_ADORAMUS: - case SC_NEEDLE_OF_PARALYZE: - case SC_DEEP_SLEEP: - case SC_COLD: - - // Exploit prevention - kRO Fix - case SC_PYREXIA: - case SC_DEATHHURT: - case SC_TOXIN: - case SC_PARALYSE: - case SC_VENOMBLEED: - case SC_MAGICMUSHROOM: - case SC_OBLIVIONCURSE: - case SC_LEECHESEND: - - // Ranger Effects - case SC_WUGBITE: - case SC_ELECTRICSHOCKER: - case SC_MAGNETICFIELD: - - // Masquerades - case SC__ENERVATION: - case SC__GROOMY: - case SC__LAZINESS: - case SC__UNLUCKY: - case SC__WEAKNESS: - case SC__IGNORANCE: - - // Other Effects - case SC_VACUUM_EXTREME: - case SC_NETHERWORLD: - - return 0; - } } //Before overlapping fail, one must check for status cured. - switch (type) { - case SC_BLESSING: - //TO-DO Blessing and Agi up should do 1 damage against players on Undead Status, even on PvM - //but cannot be plagiarized (this requires aegis investigation on packets and official behavior) [Brainstorm] - if ((!undead_flag && st->race!=RC_DEMON) || bl->type == BL_PC) { - status_change_end(bl, SC_CURSE, INVALID_TIMER); - if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) - status_change_end(bl, SC_STONE, INVALID_TIMER); - } - if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH) - status_change_end(bl, SC_SOULLINK, INVALID_TIMER); - break; - case SC_INC_AGI: - status_change_end(bl, SC_DEC_AGI, INVALID_TIMER); - if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH) - status_change_end(bl, SC_SOULLINK, INVALID_TIMER); - break; - case SC_QUAGMIRE: - status_change_end(bl, SC_CONCENTRATION, INVALID_TIMER); - status_change_end(bl, SC_TRUESIGHT, INVALID_TIMER); - status_change_end(bl, SC_WINDWALK, INVALID_TIMER); - //Also blocks the ones below... - case SC_DEC_AGI: - case SC_ADORAMUS: - status_change_end(bl, SC_CARTBOOST, INVALID_TIMER); - //Also blocks the ones below... - case SC_DONTFORGETME: - status_change_end(bl, SC_INC_AGI, INVALID_TIMER); - status_change_end(bl, SC_ADRENALINE, INVALID_TIMER); - status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER); - status_change_end(bl, SC_SPEARQUICKEN, INVALID_TIMER); - status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); - status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER); - status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER); - status_change_end(bl, SC_ACCELERATION, INVALID_TIMER); - break; - case SC_ONEHANDQUICKEN: - //Removes the Aspd potion effect, as reported by Vicious. [Skotlex] - status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER); - break; - case SC_OVERTHRUSTMAX: - //Cancels Normal Overthrust. [Skotlex] - status_change_end(bl, SC_OVERTHRUST, INVALID_TIMER); - break; - case SC_KYRIE: - //Cancels Assumptio - status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); - break; - case SC_DELUGE: - if (sc->data[SC_FOGWALL] && sc->data[SC_BLIND]) - status_change_end(bl, SC_BLIND, INVALID_TIMER); - break; - case SC_SILENCE: - if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) - status_change_end(bl, SC_GOSPEL, INVALID_TIMER); - break; - case SC_HIDING: - status_change_end(bl, SC_RG_CCONFINE_M, INVALID_TIMER); - status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER); - break; - case SC_BERSERK: - if( val3 == SC__BLOODYLUST ) - break; - if(battle_config.berserk_cancels_buffs) { - status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER); - status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); - status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER); - status_change_end(bl, SC_PARRYING, INVALID_TIMER); - status_change_end(bl, SC_AURABLADE, INVALID_TIMER); - status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER); - } - #ifdef RENEWAL - else { - status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); - } - #endif - break; - case SC_ASSUMPTIO: - status_change_end(bl, SC_KYRIE, INVALID_TIMER); - status_change_end(bl, SC_KAITE, INVALID_TIMER); - break; - case SC_KAITE: - status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); - break; - case SC_CARTBOOST: - if (sc->data[SC_DEC_AGI] || sc->data[SC_ADORAMUS]) { - //Cancel Decrease Agi, but take no further effect [Skotlex] - status_change_end(bl, SC_DEC_AGI, INVALID_TIMER); - status_change_end(bl, SC_ADORAMUS, INVALID_TIMER); - return 0; - } - break; - case SC_FUSION: - status_change_end(bl, SC_SOULLINK, INVALID_TIMER); - break; - case SC_GS_ADJUSTMENT: - status_change_end(bl, SC_GS_MADNESSCANCEL, INVALID_TIMER); - break; - case SC_GS_MADNESSCANCEL: - status_change_end(bl, SC_GS_ADJUSTMENT, INVALID_TIMER); - break; - //NPC_CHANGEUNDEAD will debuff Blessing and Agi Up - case SC_PROPERTYUNDEAD: - status_change_end(bl, SC_BLESSING, INVALID_TIMER); - status_change_end(bl, SC_INC_AGI, INVALID_TIMER); - break; - case SC_FOOD_STR: - status_change_end(bl, SC_FOOD_STR_CASH, INVALID_TIMER); - break; - case SC_FOOD_AGI: - status_change_end(bl, SC_FOOD_AGI_CASH, INVALID_TIMER); - break; - case SC_FOOD_VIT: - status_change_end(bl, SC_FOOD_VIT_CASH, INVALID_TIMER); - break; - case SC_FOOD_INT: - status_change_end(bl, SC_FOOD_INT_CASH, INVALID_TIMER); - break; - case SC_FOOD_DEX: - status_change_end(bl, SC_FOOD_DEX_CASH, INVALID_TIMER); - break; - case SC_FOOD_LUK: - status_change_end(bl, SC_FOOD_LUK_CASH, INVALID_TIMER); - break; - case SC_FOOD_STR_CASH: - status_change_end(bl, SC_FOOD_STR, INVALID_TIMER); - break; - case SC_FOOD_AGI_CASH: - status_change_end(bl, SC_FOOD_AGI, INVALID_TIMER); - break; - case SC_FOOD_VIT_CASH: - status_change_end(bl, SC_FOOD_VIT, INVALID_TIMER); - break; - case SC_FOOD_INT_CASH: - status_change_end(bl, SC_FOOD_INT, INVALID_TIMER); - break; - case SC_FOOD_DEX_CASH: - status_change_end(bl, SC_FOOD_DEX, INVALID_TIMER); - break; - case SC_FOOD_LUK_CASH: - status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER); - break; - case SC_GM_BATTLE: - status_change_end(bl, SC_GM_BATTLE2, INVALID_TIMER); - break; - case SC_GM_BATTLE2: - status_change_end(bl, SC_GM_BATTLE, INVALID_TIMER); - break; - case SC_ENDURE: - if( val4 == 1 ) - 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: - status_change_end(bl, SC_INCAGI, INVALID_TIMER); - status_change_end(bl, SC_WINDWALK, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER); - status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER); - break; - //Group A Status (doesn't overlap) - case SC_SWING: - case SC_SYMPHONY_LOVE: - case SC_MOONLIT_SERENADE: - case SC_RUSH_WINDMILL: - case SC_ECHOSONG: - case SC_HARMONIZE: - case SC_FRIGG_SONG: - if (type != SC_SWING) status_change_end(bl, SC_SWING, INVALID_TIMER); - if (type != SC_SYMPHONY_LOVE) status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER); - if (type != SC_MOONLIT_SERENADE) status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER); - if (type != SC_RUSH_WINDMILL) status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER); - if (type != SC_ECHOSONG) status_change_end(bl, SC_ECHOSONG, INVALID_TIMER); - if (type != SC_HARMONIZE) status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); - if (type != SC_FRIGG_SONG) status_change_end(bl, SC_FRIGG_SONG, INVALID_TIMER); - break; - //Group B Status - case SC_SIREN: - case SC_DEEP_SLEEP: - case SC_SIRCLEOFNATURE: - case SC_LERADS_DEW: - case SC_MELODYOFSINK: - case SC_BEYOND_OF_WARCRY: - case SC_UNLIMITED_HUMMING_VOICE: - case SC_GLOOMYDAY: - case SC_SONG_OF_MANA: - case SC_DANCE_WITH_WUG: - if (type != SC_SIREN) status_change_end(bl, SC_SIREN, INVALID_TIMER); - if (type != SC_DEEP_SLEEP) status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER); - if (type != SC_SIRCLEOFNATURE) status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER); - if (type != SC_LERADS_DEW) status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER); - if (type != SC_MELODYOFSINK) status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER); - if (type != SC_BEYOND_OF_WARCRY) status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER); - if (type != SC_UNLIMITED_HUMMING_VOICE) status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER); - if (type != SC_GLOOMYDAY) status_change_end(bl, SC_GLOOMYDAY, INVALID_TIMER); - if (type != SC_SONG_OF_MANA) status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER); - if (type != SC_DANCE_WITH_WUG) status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER); - break; - case SC_REFLECTSHIELD: - status_change_end(bl, SC_LG_REFLECTDAMAGE, INVALID_TIMER); - break; - case SC_LG_REFLECTDAMAGE: - status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER); - break; - case SC_SHIELDSPELL_DEF: - case SC_SHIELDSPELL_MDEF: - case SC_SHIELDSPELL_REF: - status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER); - status_change_end(bl, SC_SHIELDSPELL_DEF, INVALID_TIMER); - status_change_end(bl, SC_SHIELDSPELL_MDEF, INVALID_TIMER); - status_change_end(bl, SC_SHIELDSPELL_REF, INVALID_TIMER); - break; - case SC_GENTLETOUCH_ENERGYGAIN: - case SC_GENTLETOUCH_CHANGE: - case SC_GENTLETOUCH_REVITALIZE: - if( type != SC_GENTLETOUCH_REVITALIZE ) - status_change_end(bl, SC_GENTLETOUCH_REVITALIZE, INVALID_TIMER); - if( type != SC_GENTLETOUCH_ENERGYGAIN ) - status_change_end(bl, SC_GENTLETOUCH_ENERGYGAIN, INVALID_TIMER); - if( type != SC_GENTLETOUCH_CHANGE ) - status_change_end(bl, SC_GENTLETOUCH_CHANGE, INVALID_TIMER); - break; - case SC_INVINCIBLE: - status_change_end(bl, SC_INVINCIBLEOFF, INVALID_TIMER); - break; - case SC_INVINCIBLEOFF: - status_change_end(bl, SC_INVINCIBLE, INVALID_TIMER); - break; - case SC_MAGICPOWER: - status_change_end(bl, type, INVALID_TIMER); - break; - } + if (status->end_sc_before_start(bl, st, sc, type, undead_flag, val1, val2, val3, val4)) + return 0; //Check for overlapping fails if( (sce = sc->data[type]) ) { @@ -8026,6 +7785,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_LERADS_DEW: if (sc && sc->data[SC_BERSERK]) return 0; + FALLTHROUGH case SC_SHAPESHIFT: case SC_PROPERTYWALK: break; @@ -8038,6 +7798,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t break; case SC_JOINTBEAT: val2 |= sce->val2; // stackable ailments + FALLTHROUGH default: if(sce->val1 > val1) return 1; //Return true to not mess up skill animations. [Skotlex] @@ -8048,9 +7809,13 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t calc_flag = status->dbs->ChangeFlagTable[type]; if(!(flag&SCFLAG_LOADED)) { // Do not parse val settings when loading SCs switch(type) { + case SC_AUTOTRADE: + case SC_KSPROTECTED: + break; // Prevent calling status_change_start_unknown_sc(). case SC_ADORAMUS: sc_start(src,bl,SC_BLIND,100,val1,skill->get_time(status->sc2skill(type),val1)); // Fall through to SC_INC_AGI + FALLTHROUGH case SC_DEC_AGI: case SC_INC_AGI: val2 = 2 + val1; //Agi change @@ -8063,33 +7828,33 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t int i; for( i = 0; i < MAX_PC_DEVOTION; i++ ) { if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) != NULL) - status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, tick, SCFLAG_ALL); + status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, total_tick, SCFLAG_NOAVOID|SCFLAG_NOICON); } } else if (bl->type == BL_MER) { struct mercenary_data *mc = BL_UCAST(BL_MER, bl); if (mc->devotion_flag && (tsd = mc->master) != NULL) { - status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, tick, SCFLAG_ALL); + status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, total_tick, SCFLAG_NOAVOID|SCFLAG_NOICON); } } } //val4 signals infinite endure (if val4 == 2 it is infinite endure from Berserk) if (val4) - tick = INFINITE_DURATION; + total_tick = INFINITE_DURATION; break; case SC_AUTOBERSERK: if (st->hp < st->max_hp>>2 && (!sc->data[SC_PROVOKE] || sc->data[SC_PROVOKE]->val2==0)) sc_start4(src,bl,SC_PROVOKE,100,10,1,0,0,60000); - tick = INFINITE_DURATION; + total_tick = INFINITE_DURATION; break; case SC_CRUCIS: val2 = 10 + 4*val1; //Def reduction - tick = INFINITE_DURATION; + total_tick = INFINITE_DURATION; clif->emotion(bl,E_SWT); break; case SC_MAXIMIZEPOWER: - tick_time = val2 = tick>0?tick:60000; - tick = INFINITE_DURATION; // duration sent to the client should be infinite + tick_time = val2 = total_tick>0?total_tick:60000; + total_tick = INFINITE_DURATION; // duration sent to the client should be infinite break; case SC_EDP: // [Celest] //Chance to Poison enemies. @@ -8100,7 +7865,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t #endif val3 = 50 * (val1 + 1); //Damage increase (+50 +50*lv%) if( sd )//[Ind] - iROwiki says each level increases its duration by 3 seconds - tick += pc->checkskill(sd,GC_RESEARCHNEWPOISON)*3000; + total_tick += pc->checkskill(sd,GC_RESEARCHNEWPOISON)*3000; break; case SC_POISONREACT: val2=(val1+1)/2 + val1/10; // Number of counters [Skotlex] @@ -8130,10 +7895,11 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t break; case SC_SACRIFICE: val2 = 5; //Lasts 5 hits - tick = INFINITE_DURATION; + total_tick = INFINITE_DURATION; break; case SC_ENCHANTPOISON: val2= 250+50*val1; //Poisoning Chance (2.5+0.5%) in 1/10000 rate + FALLTHROUGH case SC_ASPERSIO: case SC_PROPERTYFIRE: case SC_PROPERTYWATER: @@ -8166,12 +7932,12 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t int i; for( i = 0; i < MAX_PC_DEVOTION; i++ ) { if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) != NULL) - status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL); + status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, total_tick, SCFLAG_NOAVOID|SCFLAG_NOICON); } } else if (bl->type == BL_MER) { struct mercenary_data *mc = BL_UCAST(BL_MER, bl); if (mc->devotion_flag && (tsd = mc->master) != NULL) { - status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL); + status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, total_tick, SCFLAG_NOAVOID|SCFLAG_NOICON); } } } @@ -8220,7 +7986,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t #endif break; case SC_NJ_SUITON: - if (!val2 || (sd && (sd->class_&MAPID_BASEMASK) == MAPID_NINJA)) { + if (val2 == 0 || (sd != NULL && (sd->job & MAPID_BASEMASK) == MAPID_NINJA)) { //No penalties. val2 = 0; //Agi penalty val3 = 0; //Walk speed penalty @@ -8250,9 +8016,9 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t //val3 : Brings the skill_lv (merged into val1 here) //val4 : Partner if (val1 == CG_MOONLIT) - clif->status_change(bl,SI_MOON,1,tick,0, 0, 0); + clif->status_change(bl, status->get_sc_icon(SC_MOON), status->get_sc_relevant_bl_types(SC_MOON), 1, total_tick, 0, 0, 0); val1|= (val3<<16); - val3 = tick/1000; //Tick duration + val3 = total_tick/1000; //Tick duration tick_time = 1000; // [GodLesZ] tick time break; case SC_LONGING: @@ -8278,8 +8044,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_SUMMER: case SC_HANBOK: case SC_OKTOBERFEST: - if (!vd) return 0; - //Store previous values as they could be removed. + case SC_DRESS_UP: + if (vd == NULL) + return 0; + // Store previous values as they could be removed. unit->stop_attack(bl); break; case SC_NOCHAT: @@ -8287,8 +8055,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t // mmocharstatus.manner, each negative point results in 1 minute with this status activated // This is done this way because the message that the client displays is hardcoded, and only // shows how many minutes are remaining. [Panikon] - tick = 60000; - val1 = battle_config.manner_system; //Mute filters. + total_tick = 60000; if (sd) { clif->changestatus(sd,SP_MANNER,sd->status.manner); @@ -8297,11 +8064,11 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t break; case SC_STONE: - val3 = tick/1000; //Petrified HP-damage iterations. + val3 = total_tick/1000; //Petrified HP-damage iterations. if(val3 < 1) val3 = 1; - tick = val4; //Petrifying time. + total_tick = val4; //Petrifying time. if(val4 > 500) // not with WL_SIENNAEXECRATE - tick = max(tick, 1000); //Min time + total_tick = max(total_tick, 1000); //Min time calc_flag = 0; //Actual status changes take effect on petrified state. break; @@ -8320,7 +8087,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t } // fall through case SC_POISON: - val3 = tick/1000; //Damage iterations + val3 = total_tick/1000; //Damage iterations if(val3 < 1) val3 = 1; tick_time = 1000; // [GodLesZ] tick time //val4: HP damage @@ -8334,7 +8101,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t clif->emotion(bl,E_WHAT); break; case SC_BLOODING: - val4 = tick/10000; + val4 = total_tick/10000; if (!val4) val4 = 1; tick_time = 10000; // [GodLesZ] tick time break; @@ -8347,7 +8114,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t // val2 = seconds between heals // val4 = total of heals if (val2 < 1) val2 = 1; - if ((val4 = tick / (val2 * 1000)) < 1) + if ((val4 = total_tick / (val2 * 1000)) < 1) val4 = 1; tick_time = val2 * 1000; // [GodLesZ] tick time break; @@ -8360,19 +8127,19 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t return 0; // No need to start SC } val1 = boss_md->bl.id; - if( (val4 = tick/1000) < 1 ) + if( (val4 = total_tick/1000) < 1 ) val4 = 1; tick_time = 1000; // [GodLesZ] tick time } break; case SC_HIDING: - val2 = tick/1000; + val2 = total_tick/1000; tick_time = 1000; // [GodLesZ] tick time val3 = 0; // unused, previously speed adjustment val4 = val1+3; //Seconds before SP substraction happen. break; case SC_CHASEWALK: - val2 = tick>0?tick:10000; //Interval at which SP is drained. + val2 = total_tick>0?total_tick:10000; //Interval at which SP is drained. val3 = 35 - 5 * val1; //Speed adjustment. if (sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_ROGUE) val3 -= 40; @@ -8382,8 +8149,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_CLOAKING: if (!sd) //Monsters should be able to walk with no penalties. [Skotlex] val1 = 10; - tick_time = val2 = tick>0?tick:60000; //SP consumption rate. - tick = INFINITE_DURATION; // duration sent to the client should be infinite + tick_time = val2 = total_tick>0?total_tick:60000; //SP consumption rate. + total_tick = INFINITE_DURATION; // duration sent to the client should be infinite val3 = 0; // unused, previously walk speed adjustment //val4&1 signals the presence of a wall. //val4&2 makes cloak not end on normal attacks [Skotlex] @@ -8397,7 +8164,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_RUWACH: case SC_WZ_SIGHTBLASTER: val3 = skill->get_splash(val2, val1); //Val2 should bring the skill-id. - val2 = tick/20; + val2 = total_tick/20; tick_time = 20; // [GodLesZ] tick time break; @@ -8414,7 +8181,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_TURNKICK_READY: case SC_DODGE_READY: case SC_PUSH_CART: - tick = INFINITE_DURATION; + case SC_DAILYSENDMAILCNT: + total_tick = INFINITE_DURATION; break; case SC_AUTOGUARD: @@ -8430,12 +8198,12 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t if( sd ) { for( i = 0; i < MAX_PC_DEVOTION; i++ ) { if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) != NULL) - status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL); + status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, total_tick, SCFLAG_NOAVOID|SCFLAG_NOICON); } } else if (bl->type == BL_MER) { struct mercenary_data *mc = BL_UCAST(BL_MER, bl); if (mc->devotion_flag && (tsd = mc->master) != NULL) { - status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL); + status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, total_tick, SCFLAG_NOAVOID|SCFLAG_NOICON); } } } @@ -8454,7 +8222,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t for (i = 0; i < MAX_PC_DEVOTION; i++) { //See if there are devoted characters, and pass the status to them. [Skotlex] if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) != NULL) - status->change_start(bl, &tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,SCFLAG_NOAVOID); + status->change_start(bl, &tsd->bl,type,10000,val1,5+val1*5,val3,val4,total_tick,SCFLAG_NOAVOID); } } } @@ -8467,8 +8235,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t } val2 = 12; //SP cost val4 = 10000; //Decrease at 10secs intervals. - val3 = tick/val4; - tick = INFINITE_DURATION; // duration sent to the client should be infinite + val3 = total_tick/val4; + total_tick = INFINITE_DURATION; // duration sent to the client should be infinite tick_time = val4; // [GodLesZ] tick time break; case SC_PARRYING: @@ -8486,21 +8254,21 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_BERSERK: if( val3 == SC__BLOODYLUST ) - sc_start(src,bl,(sc_type)val3,100,val1,tick); + sc_start(src,bl,(sc_type)val3,100,val1,total_tick); if (!val3 && (!sc->data[SC_ENDURE] || !sc->data[SC_ENDURE]->val4)) - sc_start4(src, bl, SC_ENDURE, 100,10,0,0,2, tick); + sc_start4(src, bl, SC_ENDURE, 100,10,0,0,2, total_tick); //HP healing is performing after the calc_status call. //Val2 holds HP penalty if (!val4) val4 = skill->get_time2(status->sc2skill(type),val1); if (!val4) val4 = 10000; //Val4 holds damage interval - val3 = tick/val4; //val3 holds skill duration + val3 = total_tick/val4; //val3 holds skill duration tick_time = val4; // [GodLesZ] tick time break; case SC_GOSPEL: if(val4 == BCT_SELF) { // self effect - val2 = tick/10000; + val2 = total_tick/10000; tick_time = 10000; // [GodLesZ] tick time status->change_clear_buffs(bl,3); //Remove buffs/debuffs } @@ -8553,23 +8321,23 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val3 = 0; val4 = 0; max_stat = (status->get_lv(bl)-10<50)?status->get_lv(bl)-10:50; - stat = max(0, max_stat - status2->str ); val3 |= cap_value(stat,0,0xFF)<<16; - stat = max(0, max_stat - status2->agi ); val3 |= cap_value(stat,0,0xFF)<<8; - stat = max(0, max_stat - status2->vit ); val3 |= cap_value(stat,0,0xFF); - stat = max(0, max_stat - status2->int_); val4 |= cap_value(stat,0,0xFF)<<16; - stat = max(0, max_stat - status2->dex ); val4 |= cap_value(stat,0,0xFF)<<8; - stat = max(0, max_stat - status2->luk ); val4 |= cap_value(stat,0,0xFF); + stat = max(0, max_stat - (int)status2->str ); val3 |= cap_value(stat,0,0xFF)<<16; + stat = max(0, max_stat - (int)status2->agi ); val3 |= cap_value(stat,0,0xFF)<<8; + stat = max(0, max_stat - (int)status2->vit ); val3 |= cap_value(stat,0,0xFF); + stat = max(0, max_stat - (int)status2->int_); val4 |= cap_value(stat,0,0xFF)<<16; + stat = max(0, max_stat - (int)status2->dex ); val4 |= cap_value(stat,0,0xFF)<<8; + stat = max(0, max_stat - (int)status2->luk ); val4 |= cap_value(stat,0,0xFF); } break; case SC_SWORDREJECT: val2 = 15*val1; //Reflect chance val3 = 3; //Reflections - tick = INFINITE_DURATION; + total_tick = INFINITE_DURATION; break; case SC_MEMORIZE: val2 = 5; //Memorized casts. - tick = INFINITE_DURATION; + total_tick = INFINITE_DURATION; break; case SC_GRAVITATION: @@ -8623,11 +8391,11 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t struct status_change_entry *sce2 = sc2 ? sc2->data[SC_RG_CCONFINE_M] : NULL; if (src2 && sc2) { if (!sce2) //Start lock on caster. - sc_start4(src,src2,SC_RG_CCONFINE_M,100,val1,1,0,0,tick+1000); + sc_start4(src,src2,SC_RG_CCONFINE_M,100,val1,1,0,0,total_tick+1000); else { //Increase count of locked enemies and refresh time. (sce2->val2)++; timer->delete(sce2->timer, status->change_timer); - sce2->timer = timer->add(timer->gettick()+tick+1000, status->change_timer, src2->id, SC_RG_CCONFINE_M); + sce2->timer = timer->add(timer->gettick()+total_tick+1000, status->change_timer, src2->id, SC_RG_CCONFINE_M); } } else //Status failed. return 0; @@ -8640,6 +8408,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t switch (val1) { case 3: //33*3 + 1 -> 100% val2++; + FALLTHROUGH case 1: case 2: //33, 66% val2 += 33*val1; @@ -8662,13 +8431,13 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t //val4: TK: Combo time struct unit_data *ud = unit->bl2ud(bl); if( ud && (!val3 || val3 == 2) ) { - tick += 300 * battle_config.combo_delay_rate/100; - ud->attackabletime = timer->gettick()+tick; + total_tick += 300 * battle_config.combo_delay_rate/100; + ud->attackabletime = timer->gettick()+total_tick; if( !val3 ) - unit->set_walkdelay(bl, timer->gettick(), tick, 1); + unit->set_walkdelay(bl, timer->gettick(), total_tick, 1); } val3 = 0; - val4 = tick; + val4 = total_tick; break; } case SC_EARTHSCROLL: @@ -8682,7 +8451,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val3 = (int)(currenttick&0x00000000ffffffffLL); val4 = (int)((currenttick&0xffffffff00000000LL)>>32); } - tick = INFINITE_DURATION; + total_tick = INFINITE_DURATION; break; case SC_KAAHI: val2 = 200*val1; //HP heal @@ -8697,7 +8466,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t break; case SC_TRICKDEAD: if (vd) vd->dead_sit = 1; - tick = INFINITE_DURATION; + total_tick = INFINITE_DURATION; break; case SC_CONCENTRATION: val2 = 2 + val1; @@ -8715,20 +8484,21 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t //val2 holds if it was casted on self, or is bonus received from others val3 = 5*val1; //Power increase if(sd && pc->checkskill(sd,BS_HILTBINDING)>0) - tick += tick / 10; + total_tick += total_tick / 10; break; case SC_ADRENALINE2: case SC_ADRENALINE: val3 = (val2) ? 300 : 200; // aspd increase + FALLTHROUGH case SC_WEAPONPERFECT: if(sd && pc->checkskill(sd,BS_HILTBINDING)>0) - tick += tick / 10; + total_tick += total_tick / 10; break; case SC_LKCONCENTRATION: val2 = 5*val1; //Batk/Watk Increase val3 = 10*val1; //Hit Increase val4 = 5*val1; //Def reduction - sc_start(src, bl, SC_ENDURE, 100, 1, tick); //Endure effect + sc_start(src, bl, SC_ENDURE, 100, 1, total_tick); //Endure effect break; case SC_ANGELUS: val2 = 5*val1; //def increase @@ -8798,7 +8568,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val3 = 12*val1; //mdef2 reduction. break; case SC_SKA: - val2 = tick/1000; + val2 = total_tick/1000; val3 = rnd()%100; //Def changes randomly every second... tick_time = 1000; // [GodLesZ] tick time break; @@ -8811,7 +8581,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t // When renewing status' information // val3 Return map_index // val4 return coordinates - tick = val1>0?1000:250; + total_tick = val1>0?1000:250; if (sd) { if (sd->mapindex != val2) @@ -8846,11 +8616,11 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t break; case SC_SWOO: if(st->mode&MD_BOSS) - tick /= 5; //TODO: Reduce skill's duration. But for how long? + total_tick /= 5; //TODO: Reduce skill's duration. But for how long? break; case SC_SPIDERWEB: if( bl->type == BL_PC ) - tick /= 2; + total_tick /= 2; break; case SC_ARMOR: //NPC_DEFENDER: @@ -8915,7 +8685,14 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_KAIZEL: val2 = 10*val1; //% of life to be revived with break; - // case SC_ARMORPROPERTY: + case SC_ARMORPROPERTY: + { + int ele = (val1 > 0 ? SC_RESIST_PROPERTY_WATER : + (val2 > 0 ? SC_RESIST_PROPERTY_GROUND : + (val3 > 0 ? SC_RESIST_PROPERTY_FIRE : + (val4 > 0 ? SC_RESIST_PROPERTY_WIND : SI_BLANK)))); + clif->status_change(bl, status->get_sc_icon(ele), status->get_sc_relevant_bl_types(ele), 1, total_tick, 0, 0, 0); + break; // case SC_ARMOR_RESIST: // Mod your resistance against elements: // val1 = water | val2 = earth | val3 = fire | val4 = wind @@ -8924,7 +8701,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t //Place here SCs that have no SCB_* data, no skill associated, no ICON //associated, and yet are not wrong/unknown. [Skotlex] //break; - + } case SC_MER_FLEE: case SC_MER_ATK: case SC_MER_HIT: @@ -8956,11 +8733,11 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t **/ case SC_FEAR: val2 = 2; - val4 = tick / 1000; + val4 = total_tick / 1000; tick_time = 1000; // [GodLesZ] tick time break; case SC_BURNING: - val4 = tick / 3000; // Total Ticks to Burn!! + val4 = total_tick / 3000; // Total Ticks to Burn!! tick_time = 3000; // [GodLesZ] tick time break; /** @@ -8974,14 +8751,14 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val1 = sd->status.job_level * pc->checkskill(sd, RK_RUNEMASTERY) / 4; //DEF/MDEF Increase break; case SC_ABUNDANCE: - val4 = tick / 10000; + val4 = total_tick / 10000; tick_time = 10000; // [GodLesZ] tick time break; /** * Arch Bishop **/ case SC_RENOVATIO: - val4 = tick / 5000; + val4 = total_tick / 5000; tick_time = 5000; break; case SC_SECRAMENT: @@ -8992,28 +8769,28 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t break; case SC_WEAPONBLOCKING: val2 = 10 + 2 * val1; // Chance - val4 = tick / 5000; + val4 = total_tick / 5000; tick_time = 5000; // [GodLesZ] tick time break; case SC_TOXIN: - val4 = tick / 10000; + val4 = total_tick / 10000; tick_time = 10000; // [GodLesZ] tick time break; case SC_MAGICMUSHROOM: - val4 = tick / 4000; + val4 = total_tick / 4000; tick_time = 4000; // [GodLesZ] tick time break; case SC_PYREXIA: status->change_start(src, bl,SC_BLIND,10000,val1,0,0,0,30000,SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE); // Blind status that last for 30 seconds - val4 = tick / 3000; + val4 = total_tick / 3000; tick_time = 3000; // [GodLesZ] tick time break; case SC_LEECHESEND: - val4 = tick / 1000; + val4 = total_tick / 1000; tick_time = 1000; // [GodLesZ] tick time break; case SC_OBLIVIONCURSE: - val4 = tick / 3000; + val4 = total_tick / 3000; tick_time = 3000; // [GodLesZ] tick time break; case SC_CLOAKINGEXCEED: @@ -9052,7 +8829,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_SUMMON3: case SC_SUMMON4: case SC_SUMMON5: - val4 = tick / 1000; + val4 = total_tick / 1000; if( val4 < 1 ) val4 = 1; tick_time = 1000; // [GodLesZ] tick time @@ -9067,19 +8844,19 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t } break; case SC_STEALTHFIELD_MASTER: - val4 = tick / 1000; + val4 = total_tick / 1000; tick_time = 2000 + (1000 * val1); break; case SC_ELECTRICSHOCKER: case SC_COLD: case SC_MEIKYOUSISUI: - val4 = tick / 1000; + val4 = total_tick / 1000; if( val4 < 1 ) val4 = 1; tick_time = 1000; // [GodLesZ] tick time break; case SC_CAMOUFLAGE: - val4 = tick/1000; + val4 = total_tick/1000; tick_time = 1000; // [GodLesZ] tick time break; case SC_WUGDASH: @@ -9090,17 +8867,17 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val3 = (int)(currenttick&0x00000000ffffffffLL); val4 = (int)((currenttick&0xffffffff00000000LL)>>32); } - tick = INFINITE_DURATION; + total_tick = INFINITE_DURATION; break; case SC__REPRODUCE: - val4 = tick / 1000; + val4 = total_tick / 1000; tick_time = 1000; break; case SC__SHADOWFORM: { struct map_session_data * s_sd = map->id2sd(val2); if( s_sd ) s_sd->shadowform_id = bl->id; - val4 = tick / 1000; + val4 = total_tick / 1000; tick_time = 1000; // [GodLesZ] tick time } break; @@ -9111,7 +8888,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC__INVISIBILITY: val2 = 50 - 10 * val1; // ASPD val3 = 200 * val1; // CRITICAL - val4 = tick / 1000; + val4 = total_tick / 1000; tick_time = 1000; // [GodLesZ] tick time break; case SC__ENERVATION: @@ -9138,7 +8915,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t if (sd->status.pet_id > 0) pet->menu(sd, 3); if (homun_alive(sd->hd)) - homun->vaporize(sd,HOM_ST_REST); + homun->vaporize(sd, HOM_ST_REST, true); if (sd->md) mercenary->delete(sd->md,3); } @@ -9153,8 +8930,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC__WEAKNESS: val2 = 10 * val1; // bypasses coating protection and MADO - sc_start(src, bl,SC_NOEQUIPWEAPON,100,val1,tick); - sc_start(src, bl,SC_NOEQUIPSHIELD,100,val1,tick); + sc_start(src, bl,SC_NOEQUIPWEAPON,100,val1,total_tick); + sc_start(src, bl,SC_NOEQUIPSHIELD,100,val1,total_tick); break; case SC_GN_CARTBOOST: if( val1 < 3 ) @@ -9174,7 +8951,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t break; case SC_STRIKING: val1 = 6 - val1;//spcost = 6 - level (lvl1:5 ... lvl 5: 1) - val4 = tick / 1000; + val4 = total_tick / 1000; tick_time = 1000; // [GodLesZ] tick time break; case SC_BLOOD_SUCKER: @@ -9183,7 +8960,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val3 = 1; if(src2) val3 = 200 + 100 * val1 + status_get_int(src2); - val4 = tick / 1000; + val4 = total_tick / 1000; tick_time = 1000; // [GodLesZ] tick time } break; @@ -9204,22 +8981,22 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val2 = 5 + 5 * val1; break; case SC_SIREN: - val4 = tick / 2000; + val4 = total_tick / 2000; tick_time = 2000; // [GodLesZ] tick time break; case SC_DEEP_SLEEP: - val4 = tick / 2000; + val4 = total_tick / 2000; tick_time = 2000; // [GodLesZ] tick time break; case SC_SIRCLEOFNATURE: val2 = 40 * val1;//HP recovery val3 = 4 * val1;//SP drain - val4 = tick / 1000; + val4 = total_tick / 1000; tick_time = 1000; // [GodLesZ] tick time break; case SC_SONG_OF_MANA: val3 = 10 + 5 * val2; - val4 = tick/5000; + val4 = total_tick/5000; tick_time = 5000; // [GodLesZ] tick time break; case SC_SATURDAY_NIGHT_FEVER: @@ -9227,7 +9004,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t if ( val2 < 1000 ) val2 = 1000;//Added to prevent val3 from dividing by 0 when using level 6 or higher through commands. [Rytech] val3 = tick/val2;*/ - val3 = tick / 3000; + val3 = total_tick / 3000; tick_time = 3000;// [GodLesZ] tick time break; case SC_GLOOMYDAY: @@ -9263,7 +9040,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t break; case SC_MELODYOFSINK: val3 = val1 * (2 + val2);//INT Reduction. Formula Includes Caster And 2nd Performer. - val4 = tick/1000; + val4 = total_tick/1000; tick_time = 1000; break; case SC_BEYOND_OF_WARCRY: @@ -9281,13 +9058,13 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_LG_REFLECTDAMAGE: val2 = 15 + 5 * val1; val3 = 25 + 5 * val1; //Number of Reflects - val4 = tick/1000; + val4 = total_tick/1000; tick_time = 1000; // [GodLesZ] tick time break; case SC_FORCEOFVANGUARD: val2 = 8 + 12 * val1; // Chance val3 = 5 + 2 * val1; // Max rage counters - tick = INFINITE_DURATION; //endless duration in the client + total_tick = INFINITE_DURATION; //endless duration in the client break; case SC_EXEEDBREAK: if( sd ){ @@ -9310,7 +9087,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t tick_time = 5000; // [GodLesZ] tick time break; case SC_MAGNETICFIELD: - val3 = tick / 1000; + val3 = total_tick / 1000; tick_time = 1000; // [GodLesZ] tick time break; case SC_INSPIRATION: @@ -9318,7 +9095,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val2 = 40 * val1 + 3 * sd->status.job_level;// ATK bonus val3 = sd->status.base_level / 10 + sd->status.job_level / 5;// All stat bonus } - val4 = tick / 5000; + val4 = total_tick / 5000; tick_time = 5000; // [GodLesZ] tick time status->change_clear_buffs(bl,3); //Remove buffs/debuffs break; @@ -9329,7 +9106,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val1 = (sd?sd->status.job_level:2)/2 + 40 + 5 * val1; break; case SC_RAISINGDRAGON: - val3 = tick / 5000; + val3 = total_tick / 5000; tick_time = 5000; // [GodLesZ] tick time break; case SC_GENTLETOUCH_CHANGE: @@ -9415,17 +9192,20 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_WILD_STORM: case SC_UPHEAVAL: val2 += 10; + FALLTHROUGH case SC_HEATER: case SC_COOLER: case SC_BLAST: case SC_CURSED_SOIL: val2 += 10; + FALLTHROUGH case SC_PYROTECHNIC: case SC_AQUAPLAY: case SC_GUST: case SC_PETROLOGY: val2 += 5; val3 += 9000; + FALLTHROUGH case SC_CIRCLE_OF_FIRE: case SC_WATER_SCREEN: case SC_WIND_STEP: @@ -9436,7 +9216,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_STONE_SHIELD: val2 += 5; val3 += 1000; - val4 = tick; + val4 = total_tick; tick_time = val3; break; case SC_WATER_BARRIER: @@ -9459,18 +9239,18 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t break; case SC_STOMACHACHE: val3 = 8; // SP consume. - val4 = tick / 10000; + val4 = total_tick / 10000; tick_time = 10000; // [GodLesZ] tick time break; case SC_STEAMPACK: // [Frost] val3 = 100; // HP Consume. - val4 = tick / 10000; + val4 = total_tick / 10000; tick_time = 10000; - sc_start(src, bl, SC_ENDURE, 100, 10, tick); // Endure effect + sc_start(src, bl, SC_ENDURE, 100, 10, total_tick); // Endure effect break; case SC_MAGIC_CANDY: // [Frost] val3 = 90; // SP Consume. - val4 = tick / 10000; + val4 = total_tick / 10000; tick_time = 10000; break; case SC_PROMOTE_HEALTH_RESERCH: @@ -9507,8 +9287,9 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t break; case SC_KAGEMUSYA: val3 = val1 * 2; + FALLTHROUGH case SC_IZAYOI: - val2 = tick/1000; + val2 = total_tick/1000; tick_time = 1000; break; case SC_ZANGETSU: @@ -9538,22 +9319,22 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t return 0; PER( 100 / (status_get_max_hp(bl) / hp), lv ); - status->heal(bl, (!(hp%2) ? (6-lv) *4 / 100 : -(lv*4) / 100), 0, 1); + status->heal(bl, (!(hp%2) ? (6-lv) *4 / 100 : -(lv*4) / 100), 0, STATUS_HEAL_FORCED); PER( 100 / (status_get_max_sp(bl) / sp), lv ); - status->heal(bl, 0,(!(sp%2) ? (6-lv) *3 / 100 : -(lv*3) / 100), 1); + status->heal(bl, 0,(!(sp%2) ? (6-lv) *3 / 100 : -(lv*3) / 100), STATUS_HEAL_FORCED); } #undef PER break; case SC_ANGRIFFS_MODUS: val2 = 50 + 20 * val1; //atk bonus val3 = 40 + 20 * val1; // Flee reduction. - val4 = tick/1000; // hp/sp reduction timer + val4 = total_tick/1000; // hp/sp reduction timer tick_time = 1000; break; case SC_NEUTRALBARRIER: - tick_time = tick; - tick = INFINITE_DURATION; + tick_time = total_tick; + total_tick = INFINITE_DURATION; break; case SC_GOLDENE_FERSE: val2 = 10 + 10*val1; //max hp bonus @@ -9582,10 +9363,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val2 = 2*val1; //aspd reduction % val3 = 2*val1; //dmg reduction % if(sc->data[SC_NEEDLE_OF_PARALYZE]) - sc_start(src, bl, SC_ENDURE, 100, val1, tick); //start endure for same duration + sc_start(src, bl, SC_ENDURE, 100, val1, total_tick); //start endure for same duration break; case SC_STYLE_CHANGE: //[Lighta] need real info - tick = INFINITE_DURATION; + total_tick = INFINITE_DURATION; if(val2 == MH_MD_FIGHTING) val2 = MH_MD_GRAPPLING; else val2 = MH_MD_FIGHTING; break; @@ -9593,12 +9374,12 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t status_percent_heal(bl,100,0); val2 = 7 - val1; tick_time = 1000; - val4 = tick / tick_time; + val4 = total_tick / tick_time; break; case SC_KINGS_GRACE: val2 = 3 + val1; tick_time = 1000; - val4 = tick / tick_time; + val4 = total_tick / tick_time; break; case SC_TELEKINESIS_INTENSE: val2 = 10 * val1; @@ -9611,7 +9392,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val2 = 5 * val1; val3 = (20 * val1) + 80; tick_time = 1000; - val4 = tick / tick_time; + val4 = total_tick / tick_time; break; case SC_DARKCROW: val2 = 30 * val1; @@ -9620,8 +9401,9 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t if (!mob->db_checkid(val1)) val1 = MOBID_PORING; break; + case SC_SPRITEMABLE: case SC_ALL_RIDING: - tick = INFINITE_DURATION; + total_tick = INFINITE_DURATION; break; case SC_FLASHCOMBO: /** @@ -9630,26 +9412,56 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t **/ val2 = 20+(20*val1); break; + /** + * Summoner + */ + case SC_FRESHSHRIMP: + val4 = total_tick / (10000 - ((val1 - 1) * 1000)); + tick_time = 10000 - ((val1 - 1) * 1000); + if (val4 <= 0) // Prevents a negeative value from happening + val4 = 0; + break; + case SC_ARCLOUSEDASH: + val2 = 15 + 5 * val1; // AGI + val3 = 25; // Move speed increase + if (sd != NULL && (sd->job & MAPID_BASEMASK) == MAPID_SUMMONER) + val4 = 10; // Ranged ATK increase + break; + case SC_TUNAPARTY: + val2 = (st->max_hp * (val1 * 10) / 100); // %Max HP to absorb + break; + case SC_BITESCAR: + val2 = 2 * val1; // MHP% damage + val4 = total_tick / 1000; + tick_time = 1000; + break; + case SC_SHRIMP: + val2 = 10; // BATK%, MATK% + break; + case SC_CATNIPPOWDER: + val2 = 50; // WATK%, MATK% + val3 = 25 * val1; // Move speed reduction + break; default: - if (calc_flag == SCB_NONE && status->dbs->SkillChangeTable[type] == 0 && status->dbs->IconChangeTable[type] == 0) { - //Status change with no calc, no icon, and no skill associated...? - ShowError("UnknownStatusChange [%d]\n", type); + if (status->change_start_unknown_sc(src, bl, type, calc_flag, rate, val1, val2, val3, val4, total_tick, flag)) { return 0; } } - } else { //Special considerations when loading SC data. - switch( type ) { + } else { // Special considerations when loading SC data. + switch (type) { case SC_WEDDING: case SC_XMAS: case SC_SUMMER: case SC_HANBOK: case SC_OKTOBERFEST: - if( !vd ) break; - clif->changelook(bl,LOOK_BASE,vd->class_); - clif->changelook(bl,LOOK_WEAPON,0); - clif->changelook(bl,LOOK_SHIELD,0); - clif->changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); - clif->changelook(bl,LOOK_BODY2,0); + case SC_DRESS_UP: + if (vd == NULL) + break; + clif->changelook(bl, LOOK_BASE, vd->class); + clif->changelook(bl, LOOK_WEAPON, 0); + clif->changelook(bl, LOOK_SHIELD, 0); + clif->changelook(bl, LOOK_CLOTHES_COLOR, vd->cloth_color); + clif->changelook(bl, LOOK_BODY2, 0); break; case SC_KAAHI: val4 = INVALID_TIMER; @@ -9658,27 +9470,272 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t } /* values that must be set regardless of SCFLAG_LOADED e.g. val_flag */ - switch(type) { + val_flag = status->get_val_flag(type); + + /* [Ind/Hercules] */ + status->change_start_display(sd, type, val1, val2, val3, val4); + + //Those that make you stop attacking/walking.... + status->change_start_stop_action(bl, type); + + // Set option as needed. + opt_flag = status->change_start_set_option(bl, sc, type, val1, val2, val3, val4); + + //On Aegis, when turning on a status change, first goes the option packet, then the sc packet. + if(opt_flag) { + clif->changeoption(bl); + if( sd && opt_flag&0x4 ) { + if (vd) + clif->changelook(bl, LOOK_BASE, vd->class); + clif->changelook(bl,LOOK_WEAPON,0); + clif->changelook(bl,LOOK_SHIELD,0); + if (vd) + clif->changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); + } + } + if (calc_flag&SCB_DYE) { + //Reset DYE color + if (vd && vd->cloth_color) { + val4 = vd->cloth_color; + clif->changelook(bl,LOOK_CLOTHES_COLOR,0); + } + calc_flag&=~SCB_DYE; + } + +#if 0 //Currently No SC's use this + if (calc_flag&SCB_BODY) { + //Reset Body Style + if (vd && vd->body_style) { + val4 = vd->body_style; + clif->changelook(bl,LOOK_BODY2,0); + } + calc_flag&=~SCB_BODY; + } +#endif + + if (!(flag & SCFLAG_LOADED)) + tick = total_tick; // When starting a new SC (not loading), its remaining duration is the same as the total + if(!(flag & SCFLAG_NOICON) && !(flag & SCFLAG_LOADED && status->dbs->DisplayType[type])) + clif->status_change_sub(bl, status->get_sc_icon(type), status->get_sc_relevant_bl_types(type), 1, tick, total_tick, (val_flag & 1) ? val1 : 1, (val_flag & 2) ? val2 : 0, (val_flag & 4) ? val3 : 0); + + /** + * used as temporary storage for scs with interval ticks, so that the actual duration is sent to the client first. + **/ + if(tick_time) + tick = tick_time; + + //Don't trust the previous sce assignment, in case the SC ended somewhere between there and here. + if((sce=sc->data[type])) {// reuse old sc + if( sce->timer != INVALID_TIMER ) + timer->delete(sce->timer, status->change_timer); + } else {// new sc + ++(sc->count); + sce = sc->data[type] = ers_alloc(status->data_ers, struct status_change_entry); + } + + sce->val1 = val1; + sce->val2 = val2; + sce->val3 = val3; + sce->val4 = val4; + sce->total_tick = total_tick; + + if (tick >= 0) { + sce->timer = timer->add(timer->gettick() + tick, status->change_timer, bl->id, type); + sce->infinite_duration = false; + } else { + sce->timer = INVALID_TIMER; //Infinite duration + sce->infinite_duration = true; + if( sd ) + chrif->save_scdata_single(sd->status.account_id,sd->status.char_id,type,sce); + } + + if (calc_flag) + status_calc_bl(bl,calc_flag); + + if(sd && sd->pd) + pet->sc_check(sd, type); //Skotlex: Pet Status Effect Healing + + switch (type) { + case SC_BERSERK: + if (!(sce->val2)) { //don't heal if already set + status->heal(bl, st->max_hp, 0, STATUS_HEAL_FORCED); //Do not use percent_heal as this healing must override BERSERK's block. + status->set_sp(bl, 0, STATUS_HEAL_DEFAULT); //Damage all SP + } + sce->val2 = 5 * st->max_hp / 100; + break; + case SC_HLIF_CHANGE: + status_percent_heal(bl, 100, 100); + break; + case SC_RUN: + { + struct unit_data *ud = unit->bl2ud(bl); + if( ud ) + ud->state.running = unit->run(bl, NULL, SC_RUN); + } + break; + case SC_CASH_BOSS_ALARM: + if( sd ) + clif->bossmapinfo(sd->fd, map->id2boss(sce->val1), 0); // First Message + break; + case SC_MER_HP: + status_percent_heal(bl, 100, 0); // Recover Full HP + break; + case SC_MER_SP: + status_percent_heal(bl, 0, 100); // Recover Full SP + break; + case SC_PROMOTE_HEALTH_RESERCH: + status_percent_heal(bl, sce->val4, 0); + break; + case SC_ENERGY_DRINK_RESERCH: + status_percent_heal(bl, 0, sce->val4); + break; + /** + * Ranger + **/ + case SC_WUGDASH: + { + struct unit_data *ud = unit->bl2ud(bl); + if( ud ) + ud->state.running = unit->run(bl, sd, SC_WUGDASH); + } + break; + case SC_COMBOATTACK: + switch (sce->val1) { + case TK_STORMKICK: + clif->skill_nodamage(bl,bl,TK_READYSTORM,1,1); + break; + case TK_DOWNKICK: + clif->skill_nodamage(bl,bl,TK_READYDOWN,1,1); + break; + case TK_TURNKICK: + clif->skill_nodamage(bl,bl,TK_READYTURN,1,1); + break; + case TK_COUNTER: + clif->skill_nodamage(bl,bl,TK_READYCOUNTER,1,1); + break; + case MO_COMBOFINISH: + case CH_TIGERFIST: + case CH_CHAINCRUSH: + if (sd) + clif->skillinfo(sd,MO_EXTREMITYFIST, INF_SELF_SKILL); + break; + case TK_JUMPKICK: + if (sd) + clif->skillinfo(sd,TK_JUMPKICK, INF_SELF_SKILL); + break; + case MO_TRIPLEATTACK: + if (sd && pc->checkskill(sd, SR_DRAGONCOMBO) > 0) + clif->skillinfo(sd,SR_DRAGONCOMBO, INF_SELF_SKILL); + break; + case SR_FALLENEMPIRE: + if (sd){ + clif->skillinfo(sd,SR_GATEOFHELL, INF_SELF_SKILL); + clif->skillinfo(sd,SR_TIGERCANNON, INF_SELF_SKILL); + } + break; + } + break; + case SC_RAISINGDRAGON: + sce->val2 = st->max_hp / 100;// Officially tested its 1%hp drain. [Jobbie] + break; + } + + if( opt_flag&2 && sd && sd->touching_id ) + npc->touchnext_areanpc(sd,false); // run OnTouch_ on next char in range + + return 1; +} + +static bool status_change_start_unknown_sc(struct block_list *src, struct block_list *bl, enum sc_type type, int calc_flag, int rate, int val1, int val2, int val3, int val4, int total_tick, int flag) +{ + Assert_retr(false, type >= SC_NONE && type < SC_MAX); + if (calc_flag == SCB_NONE && status->dbs->SkillChangeTable[type] == 0 && status->get_sc_icon(type) == SI_BLANK) { + //Status change with no calc, no icon, and no skill associated...? + ShowError("UnknownStatusChange [%d]\n", type); + return true; + } + return false; +} + +/** + * Starts a status change in its full duration. + * + * @param src Status change source bl. + * @param bl Status change target bl. + * @param type Status change type. + * @param rate Base success rate. 1 means 0.01%, 10000 means 100%. + * @param val1 Additional value (meaning depends on type). + * @param val2 Additional value (meaning depends on type). + * @param val3 Additional value (meaning depends on type). + * @param val4 Additional value (meaning depends on type). + * @param tick Base duration (milliseconds). + * @param flag Special flags (@see enum scstart_flag). + * + * @retval 0 if no status change happened. + * @retval 1 if the status change was successfully applied. + */ +static int status_change_start(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int flag) +{ + return status->change_start_sub(src, bl, type, rate, val1, val2, val3, val4, 0, tick, flag); +} + +static void status_change_start_display(struct map_session_data *sd, enum sc_type type, int val1, int val2, int val3, int val4) +{ + Assert_retv(type >= SC_NONE && type < SC_MAX); + + if (sd && status->dbs->DisplayType[type]) { + int dval1 = 0, dval2 = 0, dval3 = 0; + switch (type) { + case SC_ALL_RIDING: + dval1 = 1; + break; + case SC_CLAN_INFO: + dval1 = val1; + dval2 = val2; + dval3 = val3; + break; + default: /* all others: just copy val1 */ + dval1 = val1; + break; + } + status->display_add(sd, type, dval1, dval2, dval3); + } +} + +/** + * Return val_flag based on sc type. + * + * @param type Status change type. + * + * @retval val_flag. + */ +static int status_get_val_flag(enum sc_type type) +{ + int val_flag = 0; + switch (type) { + case SC_CLAN_INFO: + val_flag |= 1 | 2; + break; case SC_FIGHTINGSPIRIT: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_VENOMIMPRESS: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_POISONINGWEAPON: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_WEAPONBLOCKING: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_ROLLINGCUTTER: val_flag |= 1; break; case SC_CLOAKINGEXCEED: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_HALLUCINATIONWALK: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_SUMMON1: case SC_SUMMON2: @@ -9688,34 +9745,34 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val_flag |= 1; break; case SC__SHADOWFORM: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC__INVISIBILITY: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC__ENERVATION: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC__GROOMY: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC__LAZINESS: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC__UNLUCKY: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC__WEAKNESS: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_PROPERTYWALK: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_FORCEOFVANGUARD: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_PRESTIGE: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_BANDING: val_flag |= 1; @@ -9723,56 +9780,56 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_SHIELDSPELL_DEF: case SC_SHIELDSPELL_MDEF: case SC_SHIELDSPELL_REF: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_SPELLFIST: case SC_CURSEDCIRCLE_ATKER: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_CRESCENTELBOW: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_LIGHTNINGWALK: val_flag |= 1; break; case SC_PYROTECHNIC_OPTION: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_HEATER_OPTION: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_AQUAPLAY_OPTION: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_COOLER_OPTION: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_CHILLY_AIR_OPTION: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_GUST_OPTION: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_BLAST_OPTION: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_WILD_STORM_OPTION: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_PETROLOGY_OPTION: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_CURSED_SOIL_OPTION: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_UPHEAVAL_OPTION: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_CIRCLE_OF_FIRE_OPTION: - val_flag |= 1|2; + val_flag |= 1 | 2; break; case SC_WATER_BARRIER: - val_flag |= 1|2|4; + val_flag |= 1 | 2 | 4; break; case SC_KYOUGAKU: val_flag |= 1; @@ -9784,86 +9841,36 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_OVERLAPEXPUP: val_flag |= 1; break; - } - - /* [Ind/Hercules] */ - if( sd && status->dbs->DisplayType[type] ) { - int dval1 = 0, dval2 = 0, dval3 = 0; - switch( type ) { - case SC_ALL_RIDING: - dval1 = 1; - break; - default: /* all others: just copy val1 */ - dval1 = val1; - break; - } - status->display_add(sd,type,dval1,dval2,dval3); - } - - //Those that make you stop attacking/walking.... - switch (type) { - case SC_VACUUM_EXTREME: - if(!map_flag_gvg(bl->m)) - unit->stop_walking(bl,1); - break; - case SC_FREEZE: - case SC_STUN: - case SC_SLEEP: - case SC_STONE: - case SC_DEEP_SLEEP: - if (sd && pc_issit(sd)) //Avoid sprite sync problems. - pc->setstand(sd); - case SC_TRICKDEAD: - status_change_end(bl, SC_DANCING, INVALID_TIMER); - // 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: - case SC_CONFUSION: - case SC_RG_CCONFINE_M: - case SC_RG_CCONFINE_S: - case SC_SPIDERWEB: - case SC_ELECTRICSHOCKER: - case SC_WUGBITE: - case SC_THORNS_TRAP: - case SC__MANHOLE: - case SC__CHAOS: - case SC_COLD: - case SC_CURSEDCIRCLE_ATKER: - case SC_CURSEDCIRCLE_TARGET: - case SC_FEAR: - case SC_MEIKYOUSISUI: - case SC_NEEDLE_OF_PARALYZE: - case SC_DEATHBOUND: - case SC_NETHERWORLD: - unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); - break; - case SC_ANKLESNARE: - if( battle_config.skill_trap_type || !map_flag_gvg(bl->m) ) - unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); - break; - case SC_HIDING: - case SC_CLOAKING: - case SC_CLOAKINGEXCEED: - case SC_CHASEWALK: - case SC_WEIGHTOVER90: - case SC_CAMOUFLAGE: - case SC_SIREN: - case SC_ALL_RIDING: - unit->stop_attack(bl); + case SC_DAILYSENDMAILCNT: + val_flag |= 1 | 2; break; - case SC_SILENCE: - if (battle_config.sc_castcancel&bl->type) - unit->skillcastcancel(bl, 0); + case SC_MADOGEAR: + val_flag |= 1; break; } + return val_flag; +} - // Set option as needed. - opt_flag = 1; - switch(type) { +/** + * Set new status values. + * + * @param bl Status change target bl. + * @param sc Current statuses. + * @param type Status change type. + * @param val1 Additional value (meaning depends on type). + * @param val2 Additional value (meaning depends on type). + * @param val3 Additional value (meaning depends on type). + * @param val4 Additional value (meaning depends on type). + * + * @retval option flag. + */ +static int status_change_start_set_option(struct block_list *bl, struct status_change *sc, enum sc_type type, int val1, int val2, int val3, int val4) +{ + int opt_flag = 1; + + nullpo_retr(true, bl); + nullpo_retr(true, sc); + switch (type) { //OPT1 case SC_STONE: sc->opt1 = OPT1_STONEWAIT; break; case SC_FREEZE: sc->opt1 = OPT1_FREEZE; break; @@ -9912,6 +9919,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t opt_flag = 0; break; } + FALLTHROUGH case SC_EXPLOSIONSPIRITS: sc->opt3 |= OPT3_EXPLOSIONSPIRITS; opt_flag = 0; @@ -9940,7 +9948,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t break; #endif // 0 case SC_DANCING: - if ((val1&0xFFFF) == CG_MOONLIT) + if ((val1 & 0xFFFF) == CG_MOONLIT) sc->opt3 |= OPT3_MOONLIT; opt_flag = 0; break; @@ -10026,6 +10034,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t sc->option |= OPTION_OKTOBERFEST; opt_flag |= 0x4; break; + case SC_DRESS_UP: + sc->option |= OPTION_SUMMER2; + opt_flag |= 0x4; + break; case SC__FEINTBOMB_MASTER: sc->option |= OPTION_INVISIBLE; opt_flag |= 0x4; @@ -10033,178 +10045,464 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t default: opt_flag = 0; } + return opt_flag; +} - //On Aegis, when turning on a status change, first goes the option packet, then the sc packet. - if(opt_flag) { - clif->changeoption(bl); - if( sd && opt_flag&0x4 ) { - if (vd) - clif->changelook(bl,LOOK_BASE,vd->class_); - clif->changelook(bl,LOOK_WEAPON,0); - clif->changelook(bl,LOOK_SHIELD,0); - if (vd) - clif->changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); - } - } - if (calc_flag&SCB_DYE) { - //Reset DYE color - if (vd && vd->cloth_color) { - val4 = vd->cloth_color; - clif->changelook(bl,LOOK_CLOTHES_COLOR,0); - } - calc_flag&=~SCB_DYE; - } - -#if 0 //Currently No SC's use this - if (calc_flag&SCB_BODY) { - //Reset Body Style - if (vd && vd->body_style) { - val4 = vd->body_style; - clif->changelook(bl,LOOK_BODY2,0); +/** + * Stop actions before start new sc. + * + * @param bl Status change target bl. + * @param type Status change type. + */ +static void status_change_start_stop_action(struct block_list *bl, enum sc_type type) +{ + nullpo_retv(bl); + switch (type) { + case SC_VACUUM_EXTREME: + if (!map_flag_gvg(bl->m)) + unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); + break; + case SC_FREEZE: + case SC_STUN: + case SC_SLEEP: + case SC_STONE: + case SC_DEEP_SLEEP: { + struct map_session_data *sd = BL_CAST(BL_PC, bl); + if (sd && pc_issit(sd)) //Avoid sprite sync problems. + pc->setstand(sd); + FALLTHROUGH } - calc_flag&=~SCB_BODY; - } -#endif - - if(!(flag&SCFLAG_NOICON) && !(flag&SCFLAG_LOADED && status->dbs->DisplayType[type])) - clif->status_change(bl,status->dbs->IconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0); - - /** - * used as temporary storage for scs with interval ticks, so that the actual duration is sent to the client first. - **/ - if( tick_time ) - tick = tick_time; - - //Don't trust the previous sce assignment, in case the SC ended somewhere between there and here. - if((sce=sc->data[type])) {// reuse old sc - if( sce->timer != INVALID_TIMER ) - timer->delete(sce->timer, status->change_timer); - } else {// new sc - ++(sc->count); - sce = sc->data[type] = ers_alloc(status->data_ers, struct status_change_entry); - } - - sce->val1 = val1; - sce->val2 = val2; - sce->val3 = val3; - sce->val4 = val4; - - if (tick >= 0) { - sce->timer = timer->add(timer->gettick() + tick, status->change_timer, bl->id, type); - sce->infinite_duration = false; - } else { - sce->timer = INVALID_TIMER; //Infinite duration - sce->infinite_duration = true; - if( sd ) - chrif->save_scdata_single(sd->status.account_id,sd->status.char_id,type,sce); + case SC_TRICKDEAD: + status_change_end(bl, SC_DANCING, INVALID_TIMER); + // Cancel cast when get status [LuzZza] + if (battle_config.sc_castcancel&bl->type) + unit->skillcastcancel(bl, 0); + FALLTHROUGH + case SC_FALLENEMPIRE: + case SC_WHITEIMPRISON: + unit->stop_attack(bl); + FALLTHROUGH + case SC_STOP: + case SC_CONFUSION: + case SC_RG_CCONFINE_M: + case SC_RG_CCONFINE_S: + case SC_SPIDERWEB: + case SC_ELECTRICSHOCKER: + case SC_WUGBITE: + case SC_THORNS_TRAP: + case SC__MANHOLE: + case SC__CHAOS: + case SC_COLD: + case SC_CURSEDCIRCLE_ATKER: + case SC_CURSEDCIRCLE_TARGET: + case SC_FEAR: + case SC_MEIKYOUSISUI: + case SC_NEEDLE_OF_PARALYZE: + case SC_DEATHBOUND: + case SC_NETHERWORLD: + case SC_SV_ROOTTWIST: + unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); + break; + case SC_ANKLESNARE: + if (battle_config.skill_trap_type || !map_flag_gvg(bl->m)) + unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); + break; + case SC_HIDING: + case SC_CLOAKING: + case SC_CLOAKINGEXCEED: + case SC_CHASEWALK: + case SC_WEIGHTOVER90: + case SC_CAMOUFLAGE: + case SC_SIREN: + case SC_ALL_RIDING: + case SC_SUHIDE: + unit->stop_attack(bl); + break; + case SC_SILENCE: + if (battle_config.sc_castcancel & bl->type) + unit->skillcastcancel(bl, 0); + break; } +} - if (calc_flag) - status_calc_bl(bl,calc_flag); - - if(sd && sd->pd) - pet->sc_check(sd, type); //Skotlex: Pet Status Effect Healing +/** + * End sc before starting other sc. + * + * @param bl Status change target bl. + * @param st Status change data. + * @param sc Current statuses. + * @param type Status change type. + * @param undead_flag is bl undead. + * @param val1 Additional value (meaning depends on type). + * @param val2 Additional value (meaning depends on type). + * @param val3 Additional value (meaning depends on type). + * @param val4 Additional value (meaning depends on type). + * + * @retval false if no status change happened, or the other sc can be started regardless. + * @retval true if the status change was successfully applied and the other sc shouldn't be started. + */ +static bool status_end_sc_before_start(struct block_list *bl, struct status_data *st, struct status_change *sc, enum sc_type type, int undead_flag, int val1, int val2, int val3, int val4) +{ + nullpo_retr(true, bl); + nullpo_retr(true, st); + nullpo_retr(true, sc); switch (type) { - case SC_BERSERK: - if (!(sce->val2)) { //don't heal if already set - status->heal(bl, st->max_hp, 0, 1); //Do not use percent_heal as this healing must override BERSERK's block. - status->set_sp(bl, 0, 0); //Damage all SP + case SC_BLESSING: + // TODO: Blessing and Agi up should do 1 damage against players on Undead Status, even on PvM + // but cannot be plagiarized (this requires aegis investigation on packets and official behavior) [Brainstorm] + if ((undead_flag == 0 && st->race != RC_DEMON) || bl->type == BL_PC) { + bool prevent_start = false; + if (sc->data[SC_CURSE] != NULL) { + prevent_start = true; + status_change_end(bl, SC_CURSE, INVALID_TIMER); + } + if (sc->data[SC_STONE] != NULL && sc->opt1 == OPT1_STONE) { + prevent_start = true; + status_change_end(bl, SC_STONE, INVALID_TIMER); + } + if (prevent_start) + return true; } - sce->val2 = 5 * st->max_hp / 100; + if (sc->data[SC_SOULLINK] != NULL && sc->data[SC_SOULLINK]->val2 == SL_HIGH) + status_change_end(bl, SC_SOULLINK, INVALID_TIMER); break; - case SC_HLIF_CHANGE: - status_percent_heal(bl, 100, 100); + case SC_INC_AGI: + status_change_end(bl, SC_DEC_AGI, INVALID_TIMER); + if (sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH) + status_change_end(bl, SC_SOULLINK, INVALID_TIMER); break; - case SC_RUN: - { - struct unit_data *ud = unit->bl2ud(bl); - if( ud ) - ud->state.running = unit->run(bl, NULL, SC_RUN); - } + case SC_QUAGMIRE: + status_change_end(bl, SC_CONCENTRATION, INVALID_TIMER); + status_change_end(bl, SC_TRUESIGHT, INVALID_TIMER); + status_change_end(bl, SC_WINDWALK, INVALID_TIMER); + FALLTHROUGH + //Also blocks the ones below... + case SC_DEC_AGI: + case SC_ADORAMUS: + status_change_end(bl, SC_CARTBOOST, INVALID_TIMER); + //Also blocks the ones below... + FALLTHROUGH + case SC_DONTFORGETME: + status_change_end(bl, SC_INC_AGI, INVALID_TIMER); + status_change_end(bl, SC_ADRENALINE, INVALID_TIMER); + status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER); + status_change_end(bl, SC_SPEARQUICKEN, INVALID_TIMER); + status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); + status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER); + status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER); + status_change_end(bl, SC_ACCELERATION, INVALID_TIMER); break; - case SC_CASH_BOSS_ALARM: - if( sd ) - clif->bossmapinfo(sd->fd, map->id2boss(sce->val1), 0); // First Message + case SC_ONEHANDQUICKEN: + //Removes the Aspd potion effect, as reported by Vicious. [Skotlex] + status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER); break; - case SC_MER_HP: - status_percent_heal(bl, 100, 0); // Recover Full HP + case SC_OVERTHRUSTMAX: + //Cancels Normal Overthrust. [Skotlex] + status_change_end(bl, SC_OVERTHRUST, INVALID_TIMER); break; - case SC_MER_SP: - status_percent_heal(bl, 0, 100); // Recover Full SP + case SC_KYRIE: + //Cancels Assumptio + status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); break; - case SC_PROMOTE_HEALTH_RESERCH: - status_percent_heal(bl, sce->val4, 0); + case SC_MAGNIFICAT: + //Cancels Offertorium + status_change_end(bl, SC_OFFERTORIUM, INVALID_TIMER); break; - case SC_ENERGY_DRINK_RESERCH: - status_percent_heal(bl, 0, sce->val4); + case SC_OFFERTORIUM: + //Cancels Magnificat + status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER); break; - /** - * Ranger - **/ - case SC_WUGDASH: - { - struct unit_data *ud = unit->bl2ud(bl); - if( ud ) - ud->state.running = unit->run(bl, sd, SC_WUGDASH); - } + case SC_DELUGE: + if (sc->data[SC_FOGWALL] && sc->data[SC_BLIND]) + status_change_end(bl, SC_BLIND, INVALID_TIMER); break; - case SC_COMBOATTACK: - switch (sce->val1) { - case TK_STORMKICK: - clif->skill_nodamage(bl,bl,TK_READYSTORM,1,1); - break; - case TK_DOWNKICK: - clif->skill_nodamage(bl,bl,TK_READYDOWN,1,1); - break; - case TK_TURNKICK: - clif->skill_nodamage(bl,bl,TK_READYTURN,1,1); - break; - case TK_COUNTER: - clif->skill_nodamage(bl,bl,TK_READYCOUNTER,1,1); - break; - case MO_COMBOFINISH: - case CH_TIGERFIST: - case CH_CHAINCRUSH: - if (sd) - clif->skillinfo(sd,MO_EXTREMITYFIST, INF_SELF_SKILL); - break; - case TK_JUMPKICK: - if (sd) - clif->skillinfo(sd,TK_JUMPKICK, INF_SELF_SKILL); - break; - case MO_TRIPLEATTACK: - if (sd && pc->checkskill(sd, SR_DRAGONCOMBO) > 0) - clif->skillinfo(sd,SR_DRAGONCOMBO, INF_SELF_SKILL); - break; - case SR_FALLENEMPIRE: - if (sd){ - clif->skillinfo(sd,SR_GATEOFHELL, INF_SELF_SKILL); - clif->skillinfo(sd,SR_TIGERCANNON, INF_SELF_SKILL); - } + case SC_SILENCE: + if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) + status_change_end(bl, SC_GOSPEL, INVALID_TIMER); + break; + case SC_HIDING: + status_change_end(bl, SC_RG_CCONFINE_M, INVALID_TIMER); + status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER); + break; + case SC_BERSERK: + if (val3 == SC__BLOODYLUST) break; + if (battle_config.berserk_cancels_buffs) { + status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER); + status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); + status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER); + status_change_end(bl, SC_PARRYING, INVALID_TIMER); + status_change_end(bl, SC_AURABLADE, INVALID_TIMER); + status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER); } + #ifdef RENEWAL + else { + status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER); + } + #endif break; - case SC_RAISINGDRAGON: - sce->val2 = st->max_hp / 100;// Officially tested its 1%hp drain. [Jobbie] + case SC_ASSUMPTIO: + status_change_end(bl, SC_KYRIE, INVALID_TIMER); + status_change_end(bl, SC_KAITE, INVALID_TIMER); + break; + case SC_KAITE: + status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); + break; + case SC_CARTBOOST: + if (sc->data[SC_DEC_AGI] || sc->data[SC_ADORAMUS]) { + //Cancel Decrease Agi, but take no further effect [Skotlex] + status_change_end(bl, SC_DEC_AGI, INVALID_TIMER); + status_change_end(bl, SC_ADORAMUS, INVALID_TIMER); + return true; + } + break; + case SC_FUSION: + status_change_end(bl, SC_SOULLINK, INVALID_TIMER); + break; + case SC_GS_ADJUSTMENT: + status_change_end(bl, SC_GS_MADNESSCANCEL, INVALID_TIMER); + break; + case SC_GS_MADNESSCANCEL: + status_change_end(bl, SC_GS_ADJUSTMENT, INVALID_TIMER); + break; + //NPC_CHANGEUNDEAD will debuff Blessing and Agi Up + case SC_PROPERTYUNDEAD: + status_change_end(bl, SC_BLESSING, INVALID_TIMER); + status_change_end(bl, SC_INC_AGI, INVALID_TIMER); + break; + case SC_FOOD_STR: + status_change_end(bl, SC_FOOD_STR, INVALID_TIMER); + break; + case SC_FOOD_AGI: + status_change_end(bl, SC_FOOD_AGI, INVALID_TIMER); + break; + case SC_FOOD_VIT: + status_change_end(bl, SC_FOOD_VIT, INVALID_TIMER); + break; + case SC_FOOD_INT: + status_change_end(bl, SC_FOOD_INT, INVALID_TIMER); + break; + case SC_FOOD_DEX: + status_change_end(bl, SC_FOOD_DEX, INVALID_TIMER); + break; + case SC_FOOD_LUK: + status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER); + break; + case SC_FOOD_STR_CASH: + status_change_end(bl, SC_FOOD_STR, INVALID_TIMER); + status_change_end(bl, SC_FOOD_STR_CASH, INVALID_TIMER); + break; + case SC_FOOD_AGI_CASH: + status_change_end(bl, SC_FOOD_AGI, INVALID_TIMER); + status_change_end(bl, SC_FOOD_AGI_CASH, INVALID_TIMER); + break; + case SC_FOOD_VIT_CASH: + status_change_end(bl, SC_FOOD_VIT, INVALID_TIMER); + status_change_end(bl, SC_FOOD_VIT_CASH, INVALID_TIMER); + break; + case SC_FOOD_INT_CASH: + status_change_end(bl, SC_FOOD_INT, INVALID_TIMER); + status_change_end(bl, SC_FOOD_INT_CASH, INVALID_TIMER); + break; + case SC_FOOD_DEX_CASH: + status_change_end(bl, SC_FOOD_DEX, INVALID_TIMER); + status_change_end(bl, SC_FOOD_DEX_CASH, INVALID_TIMER); + break; + case SC_FOOD_LUK_CASH: + status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER); + status_change_end(bl, SC_FOOD_LUK_CASH, INVALID_TIMER); + break; + case SC_GM_BATTLE: + status_change_end(bl, SC_GM_BATTLE2, INVALID_TIMER); + break; + case SC_GM_BATTLE2: + status_change_end(bl, SC_GM_BATTLE, INVALID_TIMER); + break; + case SC_ENDURE: + if (val4 == 1) + 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: + status_change_end(bl, SC_INCAGI, INVALID_TIMER); + status_change_end(bl, SC_WINDWALK, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER); + status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER); + break; + //Group A Status (doesn't overlap) + case SC_SWING: + case SC_SYMPHONY_LOVE: + case SC_MOONLIT_SERENADE: + case SC_RUSH_WINDMILL: + case SC_ECHOSONG: + case SC_HARMONIZE: + case SC_FRIGG_SONG: + if (type != SC_SWING) status_change_end(bl, SC_SWING, INVALID_TIMER); + if (type != SC_SYMPHONY_LOVE) status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER); + if (type != SC_MOONLIT_SERENADE) status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER); + if (type != SC_RUSH_WINDMILL) status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER); + if (type != SC_ECHOSONG) status_change_end(bl, SC_ECHOSONG, INVALID_TIMER); + if (type != SC_HARMONIZE) status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); + if (type != SC_FRIGG_SONG) status_change_end(bl, SC_FRIGG_SONG, INVALID_TIMER); + break; + //Group B Status + case SC_SIREN: + case SC_DEEP_SLEEP: + case SC_SIRCLEOFNATURE: + case SC_LERADS_DEW: + case SC_MELODYOFSINK: + case SC_BEYOND_OF_WARCRY: + case SC_UNLIMITED_HUMMING_VOICE: + case SC_GLOOMYDAY: + case SC_SONG_OF_MANA: + case SC_DANCE_WITH_WUG: + if (type != SC_SIREN) status_change_end(bl, SC_SIREN, INVALID_TIMER); + if (type != SC_DEEP_SLEEP) status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER); + if (type != SC_SIRCLEOFNATURE) status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER); + if (type != SC_LERADS_DEW) status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER); + if (type != SC_MELODYOFSINK) status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER); + if (type != SC_BEYOND_OF_WARCRY) status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER); + if (type != SC_UNLIMITED_HUMMING_VOICE) status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER); + if (type != SC_GLOOMYDAY) status_change_end(bl, SC_GLOOMYDAY, INVALID_TIMER); + if (type != SC_SONG_OF_MANA) status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER); + if (type != SC_DANCE_WITH_WUG) status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER); + break; + case SC_REFLECTSHIELD: + status_change_end(bl, SC_LG_REFLECTDAMAGE, INVALID_TIMER); + break; + case SC_LG_REFLECTDAMAGE: + status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER); + break; + case SC_SHIELDSPELL_DEF: + case SC_SHIELDSPELL_MDEF: + case SC_SHIELDSPELL_REF: + status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER); + status_change_end(bl, SC_SHIELDSPELL_DEF, INVALID_TIMER); + status_change_end(bl, SC_SHIELDSPELL_MDEF, INVALID_TIMER); + status_change_end(bl, SC_SHIELDSPELL_REF, INVALID_TIMER); + break; + case SC_GENTLETOUCH_ENERGYGAIN: + case SC_GENTLETOUCH_CHANGE: + case SC_GENTLETOUCH_REVITALIZE: + if (type != SC_GENTLETOUCH_REVITALIZE) + status_change_end(bl, SC_GENTLETOUCH_REVITALIZE, INVALID_TIMER); + if (type != SC_GENTLETOUCH_ENERGYGAIN) + status_change_end(bl, SC_GENTLETOUCH_ENERGYGAIN, INVALID_TIMER); + if (type != SC_GENTLETOUCH_CHANGE) + status_change_end(bl, SC_GENTLETOUCH_CHANGE, INVALID_TIMER); + break; + case SC_INVINCIBLE: + status_change_end(bl, SC_INVINCIBLEOFF, INVALID_TIMER); + break; + case SC_INVINCIBLEOFF: + status_change_end(bl, SC_INVINCIBLE, INVALID_TIMER); + break; + case SC_MAGICPOWER: + status_change_end(bl, type, INVALID_TIMER); break; } - if( opt_flag&2 && sd && sd->touching_id ) - npc->touchnext_areanpc(sd,false); // run OnTouch_ on next char in range + return false; +} - return 1; +/** + * Check is boss resist to given sc. + * + * @param type Status change type. + * + * @retval true if boss resist. + * @retval false if boss not resist. + */ +static bool status_is_boss_resist_sc(enum sc_type type) +{ + if (type >= SC_COMMON_MIN && type <= SC_COMMON_MAX) + return true; + + if (status->get_sc_type(type) & SC_NO_BOSS) + return true; + + return false; +} + +/** + * Initial check for current statuses immune to given sc. + * + * @param sc Current statuses. + * @param type Status change type. + * + * @retval true if immune resist. + * @retval false if not immune resist. + */ +static bool status_is_immune_to_status(struct status_change *sc, enum sc_type type) +{ + nullpo_retr(true, sc); + if (sc->data[SC_REFRESH]) { + if (type >= SC_COMMON_MIN && type <= SC_COMMON_MAX) // Confirmed. + return true; // Immune to status ailements + switch (type) { + case SC__CHAOS: + case SC_STONE: + case SC_FROSTMISTY: + case SC_TOXIN: + case SC_PARALYSE: + case SC_VENOMBLEED: + case SC_MAGICMUSHROOM: + case SC_DEATHHURT: + case SC_PYREXIA: + case SC_OBLIVIONCURSE: + case SC_MARSHOFABYSS: + case SC_MANDRAGORA: + return true; + } + } else if (sc->data[SC_INSPIRATION]) { + if (type >= SC_COMMON_MIN && type <= SC_COMMON_MAX) + return true; // Immune to status ailements + switch (type) { + case SC__CHAOS: + case SC_STONE: + case SC_FROSTMISTY: + case SC_TOXIN: + case SC_PARALYSE: + case SC_VENOMBLEED: + case SC_MAGICMUSHROOM: + case SC_DEATHHURT: + case SC_PYREXIA: + case SC_OBLIVIONCURSE: + case SC_LEECHESEND: + case SC_SATURDAY_NIGHT_FEVER: + case SC__BODYPAINT: + case SC__ENERVATION: + case SC__GROOMY: + case SC__IGNORANCE: + case SC__LAZINESS: + case SC__UNLUCKY: + case SC__WEAKNESS: + return true; + } + } + return false; } + /*========================================== -* Ending all status except those listed. -* @TODO maybe usefull for dispel instead reseting a liste there. -* type: -* 0 - PC killed -> Place here statuses that do not dispel on death. -* 1 - If for some reason status_change_end decides to still keep the status when quitting. -* 2 - Do clif -* 3 - Do not remove some permanent/time-independent effects -*------------------------------------------*/ -int status_change_clear(struct block_list* bl, int type) { + * Ending all status except those listed. + * @TODO maybe usefull for dispel instead reseting a liste there. + * type: + * 0 - PC killed -> Place here statuses that do not dispel on death. + * 1 - If for some reason status_change_end decides to still keep the status when quitting. + * 2 - Do clif + * 3 - Do not remove some permanent/time-independent effects + *------------------------------------------*/ +static int status_change_clear(struct block_list *bl, int type) +{ struct status_change* sc; int i; @@ -10223,6 +10521,7 @@ int status_change_clear(struct block_list* bl, int type) { case SC_ARMOR_PROPERTY://Only when its Holy or Dark that it doesn't dispell on death if( sc->data[i]->val2 != ELE_HOLY && sc->data[i]->val2 != ELE_DARK ) break; + FALLTHROUGH default: continue; } @@ -10259,18 +10558,17 @@ int status_change_clear(struct block_list* bl, int type) { } /*========================================== -* Special condition we want to effectuate, check before ending a status. -*------------------------------------------*/ -int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const char* file, int line) { + * Special condition we want to effectuate, check before ending a status. + *------------------------------------------*/ +static int status_change_end_(struct block_list *bl, enum sc_type type, int tid, const char *file, int line) +{ struct map_session_data *sd; struct status_change *sc; struct status_change_entry *sce; struct status_data *st; struct view_data *vd; int opt_flag=0, calc_flag; -#ifdef ANTI_MAYAP_CHEAT bool invisible = false; -#endif nullpo_ret(bl); @@ -10302,6 +10600,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const //trigger when it also removed one case SC_STONE: sce->val3 = 0; //Petrify time counter. + FALLTHROUGH case SC_FREEZE: case SC_STUN: case SC_SLEEP: @@ -10324,10 +10623,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const status->display_remove(sd,type); } -#ifdef ANTI_MAYAP_CHEAT - if (sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE)) + if ((sc->option & (OPTION_HIDE | OPTION_CLOAK | OPTION_INVISIBLE)) != 0) invisible = true; -#endif vd = status->get_viewdata(bl); calc_flag = status->dbs->ChangeFlagTable[type]; @@ -10361,7 +10658,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const } if (begin_spurt && sce->val1 >= 7 && DIFF_TICK(timer->gettick(), starttick) <= 1000 - && (!sd || (sd->weapontype1 == 0 && sd->weapontype2 == 0)) + && (!sd || (sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST)) ) sc_start(bl, bl,SC_STRUP,100,sce->val1,skill->get_time2(status->sc2skill(type), sce->val1)); } @@ -10379,10 +10676,12 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const struct map_session_data *tsd; if( bl->type == BL_PC ) { // Clear Status from others - int i; - for( i = 0; i < MAX_PC_DEVOTION; i++ ) { - if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) != NULL && tsd->sc.data[type]) - status_change_end(&tsd->bl, type, INVALID_TIMER); + if (sd != NULL ) { + int i; + for( i = 0; i < MAX_PC_DEVOTION; i++ ) { + if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) != NULL && tsd->sc.data[type]) + status_change_end(&tsd->bl, type, INVALID_TIMER); + } } } else if (bl->type == BL_MER) { struct mercenary_data *mc = BL_UCAST(BL_MER, bl); @@ -10476,7 +10775,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const } if ((sce->val1&0xFFFF) == CG_MOONLIT) - clif->sc_end(bl,bl->id,AREA,SI_MOON); + clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(SC_MOON)); status_change_end(bl, SC_LONGING, INVALID_TIMER); } @@ -10562,7 +10861,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const status_percent_heal(bl, 100, 0); status_change_end(bl, SC__BLOODYLUST, INVALID_TIMER); } else if(st->hp > 100 && sce->val2) //If val2 is removed, no HP penalty (dispelled?) [Skotlex] - status->set_hp(bl, 100, 0); + status->set_hp(bl, 100, STATUS_HEAL_DEFAULT); if(sc->data[SC_ENDURE] && sc->data[SC_ENDURE]->val4 == 2) { sc->data[SC_ENDURE]->val4 = 0; status_change_end(bl, SC_ENDURE, INVALID_TIMER); @@ -10614,8 +10913,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const if (tid == INVALID_TIMER) break; // "lose almost all their HP and SP" on natural expiration. - status->set_hp(bl, 10, 0); - status->set_sp(bl, 10, 0); + status->set_hp(bl, 10, STATUS_HEAL_DEFAULT); + status->set_sp(bl, 10, STATUS_HEAL_DEFAULT); break; case SC_AUTOTRADE: if (tid == INVALID_TIMER) @@ -10688,10 +10987,11 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const break; case SC_NEUTRALBARRIER_MASTER: case SC_STEALTHFIELD_MASTER: - if( sce->val2 ) { + case SC_SV_ROOTTWIST: + if (sce->val2) { struct skill_unit_group* group = skill->id2group(sce->val2); sce->val2 = 0; - if( group ) /* might have been cleared before status ended, e.g. land protector */ + if (group) /* might have been cleared before status ended, e.g. land protector */ skill->del_unitgroup(group,ALC_MARK); } break; @@ -10826,6 +11126,10 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const sc->option &= ~OPTION_OKTOBERFEST; opt_flag |= 0x4; break; + case SC_DRESS_UP: + sc->option &= ~OPTION_SUMMER2; + opt_flag |= 0x4; + break; case SC__FEINTBOMB_MASTER: sc->option &= ~OPTION_INVISIBLE; opt_flag |= 0x4; @@ -10868,6 +11172,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const opt_flag = 0; break; } + FALLTHROUGH case SC_EXPLOSIONSPIRITS: sc->opt3 &= ~OPT3_EXPLOSIONSPIRITS; opt_flag = 0; @@ -10946,6 +11251,12 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const } #endif + // update HP bar when becoming visible again + if (invisible && (sc->option & (OPTION_HIDE | OPTION_CLOAK | OPTION_INVISIBLE)) == 0) { + if (sd != NULL && battle_config.party_hp_mode == 0 && sd->status.party_id != 0) + clif->party_hp(sd); + } + if (calc_flag&SCB_DYE) { //Restore DYE color if (vd && !vd->cloth_color && sce->val4) clif->changelook(bl,LOOK_CLOTHES_COLOR,sce->val4); @@ -10961,14 +11272,14 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const #endif //On Aegis, when turning off a status change, first goes the sc packet, then the option packet. - clif->sc_end(bl,bl->id,AREA,status->dbs->IconChangeTable[type]); + clif->sc_end(bl, bl->id, AREA, status->get_sc_icon(type)); if( opt_flag&8 ) //bugreport:681 clif->changeoption2(bl); else if(opt_flag) { clif->changeoption(bl); if( sd && opt_flag&0x4 ) { - clif->changelook(bl,LOOK_BASE,sd->vd.class_); + clif->changelook(bl, LOOK_BASE, sd->vd.class); clif->get_weapon_view(sd, &sd->vd.weapon, &sd->vd.shield); clif->changelook(bl,LOOK_WEAPON,sd->vd.weapon); clif->changelook(bl,LOOK_SHIELD,sd->vd.shield); @@ -10994,7 +11305,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const return 1; } -int kaahi_heal_timer(int tid, int64 tick, int id, intptr_t data) { +static int kaahi_heal_timer(int tid, int64 tick, int id, intptr_t data) +{ struct block_list *bl; struct status_change *sc; struct status_change_entry *sce; @@ -11019,17 +11331,18 @@ int kaahi_heal_timer(int tid, int64 tick, int id, intptr_t data) { hp = st->max_hp - st->hp; if (hp > sce->val2) hp = sce->val2; - if (hp) - status->heal(bl, hp, 0, 2); + if (hp != 0) + status->heal(bl, hp, 0, STATUS_HEAL_SHOWEFFECT); sce->val4 = INVALID_TIMER; return 1; } /*========================================== -* For recusive status, like for each 5s we drop sp etc. -* Reseting the end timer. -*------------------------------------------*/ -int status_change_timer(int tid, int64 tick, int id, intptr_t data) { + * For recusive status, like for each 5s we drop sp etc. + * Reseting the end timer. + *------------------------------------------*/ +static int status_change_timer(int tid, int64 tick, int id, intptr_t data) +{ enum sc_type type = (sc_type)data; struct block_list *bl; struct map_session_data *sd; @@ -11150,23 +11463,26 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { break; case SC_POISON: - if(st->hp <= max(st->max_hp>>2, sce->val4)) //Stop damaging after 25% HP left. + if (st->hp <= max(st->max_hp / 4, sce->val4)) //Stop damaging after 25% HP left. break; + FALLTHROUGH case SC_DPOISON: if (--(sce->val3) > 0) { - if (!sc->data[SC_SLOWPOISON]) { - if( sce->val2 && bl->type == BL_MOB ) { - struct block_list* src = map->id2bl(sce->val2); - if (src != NULL) - mob->log_damage(BL_UCAST(BL_MOB, bl), src, sce->val4); - } - map->freeblock_lock(); - status_zap(bl, sce->val4, 0); - if (sc->data[type]) { // Check if the status still last ( can be dead since then ). - sc_timer_next(1000 + tick, status->change_timer, bl->id, data ); - } - map->freeblock_unlock(); + if (sc->data[SC_SLOWPOISON] != NULL) { + sc_timer_next(1000 + tick, status->change_timer, bl->id, data); + return 0; + } + if (sce->val2 != 0 && bl->type == BL_MOB) { + struct block_list* src = map->id2bl(sce->val2); + if (src != NULL) + mob->log_damage(BL_UCAST(BL_MOB, bl), src, sce->val4); + } + map->freeblock_lock(); + status_zap(bl, sce->val4, 0); + if (sc->data[type] != NULL) { // Check if the status still last (can be dead since then). + sc_timer_next(1000 + tick, status->change_timer, bl->id, data); } + map->freeblock_unlock(); return 0; } break; @@ -11222,7 +11538,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { int hp = 0; if (st->hp < st->max_hp) hp = (sce->val1 < 0) ? (int)(sd->status.max_hp * -1 * sce->val1 / 100.) : sce->val1 ; - status->heal(bl, hp, 0, 2); + status->heal(bl, hp, 0, STATUS_HEAL_SHOWEFFECT); sc_timer_next((sce->val2 * 1000) + tick, status->change_timer, bl->id, data); return 0; } @@ -11282,6 +11598,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { //Moonlit's cost is 4sp*skill_lv [Skotlex] sp= 4*(sce->val1>>16); //Upkeep is also every 10 secs. + FALLTHROUGH case DC_DONTFORGETME: s=10; break; @@ -11319,10 +11636,10 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { case SC_SPLASHER: #if 0 // custom Venom Splasher countdown timer - if (sce->val4 % 1000 == 0) { + if (sce->val4 % 1000 == 0 && bl && bl->type == BL_PC) { char counter[10]; snprintf (counter, 10, "%d", sce->val4/1000); - clif->message(bl, counter); + clif->message(BL_UCCAST(BL_PC, bl)->fd, counter); } #endif // 0 if((sce->val4 -= 500) > 0) { @@ -11370,7 +11687,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { break; case SC_ABUNDANCE: if(--(sce->val4) > 0) { - status->heal(bl,0,60,0); + status->heal(bl, 0, 60, STATUS_HEAL_DEFAULT); sc_timer_next(10000+tick, status->change_timer, bl->id, data); } break; @@ -11429,17 +11746,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { mushroom_skill_id = skill->dbs->magicmushroom_db[i].skill_id; } while (mushroom_skill_id == 0); - switch( skill->get_casttype(mushroom_skill_id) ) { // Magic Mushroom skills are buffs or area damage - case CAST_GROUND: - skill->castend_pos2(bl,bl->x,bl->y,mushroom_skill_id,1,tick,0); - break; - case CAST_NODAMAGE: - skill->castend_nodamage_id(bl,bl,mushroom_skill_id,1,tick,0); - break; - case CAST_DAMAGE: - skill->castend_damage_id(bl,bl,mushroom_skill_id,1,tick,0); - break; - } + skill->castend_type(skill->get_casttype(mushroom_skill_id), bl, bl, mushroom_skill_id, 1, tick, 0); } clif->emotion(bl,E_HEH); @@ -11496,7 +11803,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { heal = ~heal + 1; map->freeblock_lock(); - status->heal(bl, heal, 0, 2); + status->heal(bl, heal, 0, STATUS_HEAL_SHOWEFFECT); if( sc->data[type] ) { sc_timer_next(5000 + tick, status->change_timer, bl->id, data); } @@ -11610,7 +11917,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { if( --(sce->val4) > 0 ) { struct block_list *src = map->id2bl(sce->val2); int damage; - if( !src || (src && (status->isdead(src) || src->m != bl->m || distance_bl(src, bl) >= 12)) ) + if (src == NULL || (status->isdead(src) || src->m != bl->m || distance_bl(src, bl) >= 12)) break; map->freeblock_lock(); damage = sce->val3; @@ -11619,7 +11926,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { if ( sc->data[type] ) { sc_timer_next(1000 + tick, status->change_timer, bl->id, data); } - status->heal(src, damage*(5 + 5 * sce->val1)/100, 0, 0); // 5 + 5% per level + status->heal(src, damage*(5 + 5 * sce->val1)/100, 0, STATUS_HEAL_DEFAULT); // 5 + 5% per level map->freeblock_unlock(); return 0; } @@ -11636,7 +11943,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { case SC_DEEP_SLEEP: if( --(sce->val4) >= 0 ) {// Recovers 3% of the player's MaxHP/MaxSP every 2 seconds. - status->heal(bl, st->max_hp * 3 / 100, st->max_sp * 3 / 100, 2); + status->heal(bl, st->max_hp * 3 / 100, st->max_sp * 3 / 100, STATUS_HEAL_SHOWEFFECT); sc_timer_next(2000 + tick, status->change_timer, bl->id, data); return 0; } @@ -11646,7 +11953,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { if( --(sce->val4) >= 0 ) { if( !status->charge(bl,0,sce->val3) ) break; - status->heal(bl, sce->val2, 0, 1); + status->heal(bl, sce->val2, 0, STATUS_HEAL_FORCED); sc_timer_next(1000 + tick, status->change_timer, bl->id, data); return 0; } @@ -11654,7 +11961,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { case SC_SONG_OF_MANA: if( --(sce->val4) >= 0 ) { - status->heal(bl,0,sce->val3,3); + status->heal(bl, 0, sce->val3, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT); sc_timer_next(5000 + tick, status->change_timer, bl->id, data); return 0; } @@ -11848,7 +12155,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { return 0; case SC_MEIKYOUSISUI: if( --(sce->val4) > 0 ) { - status->heal(bl, st->max_hp * (sce->val1+1) / 100, st->max_sp * sce->val1 / 100, 0); + status->heal(bl, st->max_hp * (sce->val1+1) / 100, st->max_sp * sce->val1 / 100, STATUS_HEAL_DEFAULT); sc_timer_next(1000 + tick, status->change_timer, bl->id, data); return 0; } @@ -11884,7 +12191,20 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { break; case SC_FRIGG_SONG: if( --(sce->val4) > 0 ) { - status->heal(bl, sce->val3, 0, 0); + status->heal(bl, sce->val3, 0, STATUS_HEAL_DEFAULT); + sc_timer_next(1000 + tick, status->change_timer, bl->id, data); + return 0; + } + break; + case SC_FRESHSHRIMP: + if (--(sce->val4) >= 0) { + status_heal(bl, st->max_hp / 100, 0, 2); + sc_timer_next((10000 - ((sce->val1 - 1) * 1000)) + tick, status->change_timer, bl->id, data); + } + break; + case SC_BITESCAR: + if (--(sce->val4) >= 0) { + status_percent_damage(bl, bl, -(sce->val2), 0, 0); sc_timer_next(1000 + tick, status->change_timer, bl->id, data); return 0; } @@ -11897,9 +12217,10 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { } /*========================================== -* Foreach iteration of repetitive status -*------------------------------------------*/ -int status_change_timer_sub(struct block_list* bl, va_list ap) { + * Foreach iteration of repetitive status + *------------------------------------------*/ +static int status_change_timer_sub(struct block_list *bl, va_list ap) +{ struct status_change* tsc; struct block_list* src = va_arg(ap,struct block_list*); @@ -11907,6 +12228,8 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) { enum sc_type type = (sc_type)va_arg(ap,int); //gcc: enum args get promoted to int int64 tick = va_arg(ap, int64); + nullpo_ret(bl); + if (status->isdead(bl)) return 0; @@ -11957,13 +12280,13 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) { break; case SC_RG_CCONFINE_M: //Lock char has released the hold on everyone... - if (tsc && tsc->data[SC_RG_CCONFINE_S] && tsc->data[SC_RG_CCONFINE_S]->val2 == src->id) { + if (tsc != NULL && src != NULL && tsc->data[SC_RG_CCONFINE_S] && tsc->data[SC_RG_CCONFINE_S]->val2 == src->id) { tsc->data[SC_RG_CCONFINE_S]->val2 = 0; status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER); } break; case SC_CURSEDCIRCLE_TARGET: - if( tsc && tsc->data[SC_CURSEDCIRCLE_TARGET] && tsc->data[SC_CURSEDCIRCLE_TARGET]->val2 == src->id ) { + if (tsc != NULL && src != NULL && tsc->data[SC_CURSEDCIRCLE_TARGET] && tsc->data[SC_CURSEDCIRCLE_TARGET]->val2 == src->id) { clif->bladestop(bl, tsc->data[SC_CURSEDCIRCLE_TARGET]->val2, 0); status_change_end(bl, type, INVALID_TIMER); } @@ -11972,14 +12295,24 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) { return 0; } -int status_get_total_def(struct block_list *src) { return status->get_status_data(src)->def2 + (short)status->get_def(src); } -int status_get_total_mdef(struct block_list *src) { return status->get_status_data(src)->mdef2 + (short)status_get_mdef(src); } -int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int flag) +static int status_get_total_def(struct block_list *src) +{ + return status->get_status_data(src)->def2 + (short)status->get_def(src); +} + +static int status_get_total_mdef(struct block_list *src) +{ + return status->get_status_data(src)->mdef2 + (short)status_get_mdef(src); +} + +static int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int flag) { #ifdef RENEWAL int min = 0, max = 0; struct status_change *sc = status->get_sc(bl); + nullpo_ret(bl); + nullpo_ret(watk); if (bl->type == BL_PC && watk->atk) { float strdex_bonus, variance; int dstr; @@ -12014,10 +12347,10 @@ int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int fl if ( bl->type == BL_PC && !(flag & 2) ) { const struct map_session_data *sd = BL_UCCAST(BL_PC, bl); - short index = sd->equip_index[EQI_HAND_R], refine; + short index = sd->equip_index[EQI_HAND_R], refine_level; if ( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON - && (refine = sd->status.inventory[index].refine) < 16 && refine ) { - int r = status->dbs->refine_info[watk->wlv].randombonus_max[refine + (4 - watk->wlv)] / 100; + && (refine_level = sd->status.inventory[index].refine) < 16 && refine_level) { + int r = refine->get_randombonus_max(watk->wlv, refine_level + (4 - watk->wlv) + 1) / 100; if ( r ) max += (rnd() % 100) % r + 1; } @@ -12035,13 +12368,14 @@ int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int fl } /** -* 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) { + * 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 + */ +static 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; @@ -12068,6 +12402,10 @@ void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_m // Any +MATK you get from skills and cards, including cards in weapon, is added here. if ( sd && sd->bonus.ematk > 0 && flag != 3 ) *matk_min += sd->bonus.ematk; + if (sd && pc->checkskill(sd, SU_POWEROFLAND) > 0) { + if (pc->checkskill(sd, SU_SV_STEMSPEAR) == 5 && pc->checkskill(sd, SU_CN_POWDERING) == 5 && pc->checkskill(sd, SU_CN_METEOR) == 5 && pc->checkskill(sd, SU_SV_ROOTTWIST) == 5) + *matk_min += *matk_min * 20 / 100; + } if ( flag != 3 ) *matk_min = status->calc_ematk(bl, sc, *matk_min); @@ -12079,6 +12417,8 @@ void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_m if ( (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 + if (sc != NULL && sc->data[SC_CATNIPPOWDER]) + wMatk -= wMatk * sc->data[SC_CATNIPPOWDER]->val2 / 100; *matk_min += wMatk - variance; *matk_max += wMatk + variance; } @@ -12107,8 +12447,8 @@ void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_m } #else // not RENEWAL - *matk_min = status_base_matk_min(st) + (sd ? sd->bonus.ematk : 0); - *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 ) { @@ -12122,10 +12462,10 @@ void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_m #ifdef RENEWAL if ( sd && !(flag & 2) ) { - short index = sd->equip_index[EQI_HAND_R], refine; + short index = sd->equip_index[EQI_HAND_R], refine_level; if ( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON - && (refine = sd->status.inventory[index].refine) < 16 && refine ) { - int r = status->dbs->refine_info[sd->inventory_data[index]->wlv].randombonus_max[refine + (4 - sd->inventory_data[index]->wlv)] / 100; + && (refine_level = sd->status.inventory[index].refine) < 16 && refine_level) { + int r = refine->get_randombonus_max(sd->inventory_data[index]->wlv, refine_level + (4 - sd->inventory_data[index]->wlv) + 1) / 100; if ( r ) *matk_max += (rnd() % 100) % r + 1; } @@ -12146,9 +12486,10 @@ void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_m #undef status_get_homluk /** -* 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) { + * Gets a random matk value depending on min matk and max matk + */ +static 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 @@ -12156,17 +12497,18 @@ unsigned short status_get_rand_matk(unsigned short matk_max, unsigned short matk } /** -* 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) { + * 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] + */ +static int status_get_matk(struct block_list *bl, int flag) +{ struct status_data *st; unsigned short matk_max, matk_min; @@ -12192,9 +12534,10 @@ int status_get_matk(struct block_list *bl, int flag) { } /** -* Updates bl's MATK values -**/ -void status_update_matk(struct block_list *bl) { + * Updates bl's MATK values + */ +static void status_update_matk(struct block_list *bl) +{ struct status_data *st; struct status_change *sc; unsigned short matk_max, matk_min; @@ -12218,11 +12561,12 @@ void status_update_matk(struct block_list *bl) { } /*========================================== -* Clears buffs/debuffs of a character. -* type&1 -> buffs, type&2 -> debuffs -* type&4 -> especific debuffs(implemented with refresh) -*------------------------------------------*/ -int status_change_clear_buffs (struct block_list* bl, int type) { + * Clears buffs/debuffs of a character. + * type&1 -> buffs, type&2 -> debuffs + * type&4 -> especific debuffs(implemented with refresh) + *------------------------------------------*/ +static int status_change_clear_buffs(struct block_list *bl, int type) +{ int i; struct status_change *sc= status->get_sc(bl); @@ -12283,7 +12627,8 @@ int status_change_clear_buffs (struct block_list* bl, int type) { return 0; } -int status_change_spread( struct block_list *src, struct block_list *bl ) { +static int status_change_spread(struct block_list *src, struct block_list *bl) +{ int i, flag = 0; struct status_change *sc = status->get_sc(src); int64 tick; @@ -12373,7 +12718,8 @@ int status_change_spread( struct block_list *src, struct block_list *bl ) { } //Natural regen related stuff. -int status_natural_heal(struct block_list* bl, va_list args) { +static int status_natural_heal(struct block_list *bl, va_list args) +{ struct regen_data *regen; struct status_data *st; struct status_change *sc; @@ -12383,6 +12729,7 @@ int status_natural_heal(struct block_list* bl, va_list args) { struct map_session_data *sd; int val,rate,bonus = 0,flag; + nullpo_ret(bl); regen = status->get_regen_data(bl); if (!regen) return 0; st = status->get_status_data(bl); @@ -12426,7 +12773,7 @@ int status_natural_heal(struct block_list* bl, va_list args) { sregen->tick.hp += val; while(sregen->tick.hp >= (unsigned int)battle_config.natural_heal_skill_interval) { sregen->tick.hp -= battle_config.natural_heal_skill_interval; - if(status->heal(bl, sregen->hp, 0, 3) < sregen->hp) { + if (status->heal(bl, sregen->hp, 0, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT) < sregen->hp) { //Full flag&=~(RGN_HP|RGN_SHP); break; @@ -12441,7 +12788,7 @@ int status_natural_heal(struct block_list* bl, va_list args) { sregen->tick.sp += val; while(sregen->tick.sp >= (unsigned int)battle_config.natural_heal_skill_interval) { sregen->tick.sp -= battle_config.natural_heal_skill_interval; - if(status->heal(bl, 0, sregen->sp, 3) < sregen->sp) { + if (status->heal(bl, 0, sregen->sp, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT) < sregen->sp) { //Full flag&=~(RGN_SP|RGN_SSP); break; @@ -12490,7 +12837,7 @@ int status_natural_heal(struct block_list* bl, va_list args) { val += regen->hp; regen->tick.hp -= battle_config.natural_healhp_interval; } while(regen->tick.hp >= (unsigned int)battle_config.natural_healhp_interval); - if (status->heal(bl, val, 0, 1) < val) + if (status->heal(bl, val, 0, STATUS_HEAL_FORCED) < val) flag&=~RGN_SHP; //full. } } @@ -12509,7 +12856,7 @@ int status_natural_heal(struct block_list* bl, va_list args) { val += regen->sp; regen->tick.sp -= battle_config.natural_healsp_interval; } while(regen->tick.sp >= (unsigned int)battle_config.natural_healsp_interval); - if (status->heal(bl, 0, val, 1) < val) + if (status->heal(bl, 0, val, STATUS_HEAL_FORCED) < val) flag&=~RGN_SSP; //full. } } @@ -12526,7 +12873,7 @@ int status_natural_heal(struct block_list* bl, va_list args) { while(sregen->tick.hp >= (unsigned int)battle_config.natural_heal_skill_interval) { sregen->tick.hp -= battle_config.natural_heal_skill_interval; - if(status->heal(bl, sregen->hp, 0, 3) < sregen->hp) + if (status->heal(bl, sregen->hp, 0, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT) < sregen->hp) break; //Full } } @@ -12541,7 +12888,7 @@ int status_natural_heal(struct block_list* bl, va_list args) { if ((rate = pc->checkskill(sd,TK_SPTIME))) sc_start(bl,bl,status->skill2sc(TK_SPTIME), 100,rate,skill->get_time(TK_SPTIME, rate)); - if ((sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR + if ((sd->job & MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR &&rnd()%10000 < battle_config.sg_angel_skill_ratio ) { //Angel of the Sun/Moon/Star @@ -12551,7 +12898,7 @@ int status_natural_heal(struct block_list* bl, va_list args) { } } sregen->tick.sp -= battle_config.natural_heal_skill_interval; - if(status->heal(bl, 0, val, 3) < val) + if (status->heal(bl, 0, val, STATUS_HEAL_FORCED | STATUS_HEAL_SHOWEFFECT) < val) break; //Full } } @@ -12559,7 +12906,8 @@ int status_natural_heal(struct block_list* bl, va_list args) { } //Natural heal main timer. -int status_natural_heal_timer(int tid, int64 tick, int id, intptr_t data) { +static int status_natural_heal_timer(int tid, int64 tick, int id, intptr_t data) +{ // This difference is always positive and lower than UINT_MAX (~24 days) status->natural_heal_diff_tick = (unsigned int)cap_value(DIFF_TICK(tick,status->natural_heal_prev_tick), 0, UINT_MAX); map->foreachregen(status->natural_heal); @@ -12567,21 +12915,8 @@ int status_natural_heal_timer(int tid, int64 tick, int id, intptr_t data) { return 0; } -/** -* Get the chance to upgrade a piece of equipment. -* @param wlv The weapon type of the item to refine (see see enum refine_type) -* @param refine The target refine level -* @return The chance to refine the item, in percent (0~100) -**/ -int status_get_refine_chance(enum refine_type wlv, int refine) { - - if ( refine < 0 || refine >= MAX_REFINE) - return 0; - - return status->dbs->refine_info[wlv].chance[refine]; -} - -int status_get_sc_type(sc_type type) { +static int status_get_sc_type(sc_type type) +{ if( type <= SC_NONE || type >= SC_MAX ) return 0; @@ -12589,10 +12924,11 @@ int status_get_sc_type(sc_type type) { return status->dbs->sc_conf[type]; } -void status_read_job_db_sub(int idx, const char *name, struct config_setting_t *jdb) +static void status_read_job_db_sub(int idx, const char *name, struct config_setting_t *jdb) { struct config_setting_t *temp = NULL; int i32 = 0; + const char *str = NULL; struct { const char *name; @@ -12627,6 +12963,38 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t * #endif }; + /** + * @field BaseExpGroup must be read before any other that deal with exp tables. + */ + if (libconfig->setting_lookup_string(jdb, "BaseExpGroup", &str) != 0) { + int i = 0; + ARR_FIND(0, VECTOR_LENGTH(pc->class_exp_groups[CLASS_EXP_TABLE_BASE]), i, strcmp(str, VECTOR_INDEX(pc->class_exp_groups[CLASS_EXP_TABLE_BASE], i).name) == 0); + if (i == VECTOR_LENGTH(pc->class_exp_groups[CLASS_EXP_TABLE_BASE])) { + ShowError("status_read_job_db: Unknown Base Exp Group '%s' provided for entry '%s'\n", str, name); + } else { + pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE] = &VECTOR_INDEX(pc->class_exp_groups[CLASS_EXP_TABLE_BASE], i); + } + } else { + ShowError("status_read_job_db: BaseExpGroup setting not found for entry '%s', skipping..\n", name); + return; + } + + /** + * @field JobExpGroup must be read before any other that deal with exp tables. + */ + if (libconfig->setting_lookup_string(jdb, "JobExpGroup", &str) != 0) { + int i = 0; + ARR_FIND(0, VECTOR_LENGTH(pc->class_exp_groups[CLASS_EXP_TABLE_JOB]), i, strcmp(str, VECTOR_INDEX(pc->class_exp_groups[CLASS_EXP_TABLE_JOB], i).name) == 0); + if (i == VECTOR_LENGTH(pc->class_exp_groups[CLASS_EXP_TABLE_JOB])) { + ShowError("status_read_job_db: Unknown Job Exp Group '%s' provided for entry '%s'\n", str, name); + } else { + pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_JOB] = &VECTOR_INDEX(pc->class_exp_groups[CLASS_EXP_TABLE_JOB], i); + } + } else { + ShowError("status_read_job_db: JobExpGroup setting not found for entry '%s', skipping..\n", name); + return; + } + if ((temp = libconfig->setting_get_member(jdb, "Inherit"))) { int nidx = 0; const char *iname; @@ -12651,7 +13019,7 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t * } else { avg_increment = 5; } - for ( ; i <= pc->max_level[idx][0]; i++) { + for ( ; i <= pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE]->max_level; i++) { status->dbs->HP_table[idx][i] = min(base + avg_increment * i, battle_config.max_hp); } @@ -12666,7 +13034,7 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t * } else { avg_increment = 1; } - for ( ; i <= pc->max_level[idx][0]; i++) { + for ( ; i <= pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE]->max_level; i++) { status->dbs->SP_table[idx][i] = min(base + avg_increment * i, battle_config.max_sp); } } @@ -12692,7 +13060,7 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t * } else { avg_increment = 5; } - for ( ; i <= pc->max_level[idx][0]; i++) { + for ( ; i <= pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE]->max_level; i++) { status->dbs->HP_table[idx][i] = min(base + avg_increment * i, battle_config.max_hp); } } @@ -12718,7 +13086,7 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t * } else { avg_increment = 1; } - for ( ; i <= pc->max_level[idx][0]; i++) { + for ( ; i <= pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE]->max_level; i++) { status->dbs->SP_table[idx][i] = min(base + avg_increment * i, battle_config.max_sp); } } @@ -12760,7 +13128,7 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t * } else { avg_increment = 5; } - for (++level; level <= pc->max_level[idx][0]; ++level) { /* limit only to possible maximum level of the given class */ + for (++level; level <= pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE]->max_level; ++level) { /* limit only to possible maximum level of the given class */ status->dbs->HP_table[idx][level] = min(base + avg_increment * level, battle_config.max_hp); /* some are still empty? then let's use the average increase */ } } @@ -12780,60 +13148,65 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t * } else { avg_increment = 1; } - for (++level; level <= pc->max_level[idx][0]; level++ ) { + for (++level; level <= pc->dbs->class_exp_table[idx][CLASS_EXP_TABLE_BASE]->max_level; level++) { status->dbs->SP_table[idx][level] = min(base + avg_increment * level, battle_config.max_sp); } } } +/* [malufett/Hercules] */ /*------------------------------------------ -* DB reading. -* job_db.conf - weight, hp, sp, aspd -* job_db2.txt - job level stat bonuses -* size_fix.txt - size adjustment table for weapons -* refine_db.txt - refining data table -*------------------------------------------*/ -void status_read_job_db(void) { /* [malufett/Hercules] */ + * DB reading. + * job_db.conf - weight, hp, sp, aspd + * job_db2.txt - job level stat bonuses + * size_fix.txt - size adjustment table for weapons + * refine_db.txt - refining data table + *------------------------------------------*/ +static void status_read_job_db(void) +{ int i = 0; struct config_t job_db_conf; struct config_setting_t *jdb = NULL; + char config_filename[256]; + #ifdef RENEWAL_ASPD - const char *config_filename = "db/re/job_db.conf"; + libconfig->format_db_path(DBPATH_RE"job_db.conf", config_filename, sizeof(config_filename)); #else - const char *config_filename = "db/pre-re/job_db.conf"; + libconfig->format_db_path(DBPATH_PRE"job_db.conf", config_filename, sizeof(config_filename)); #endif if (!libconfig->load_file(&job_db_conf, config_filename)) return; - while ( (jdb = libconfig->setting_get_elem(job_db_conf.root, i++)) ) { - int class_, idx; + while ((jdb = libconfig->setting_get_elem(job_db_conf.root, i++))) { + int class, idx; const char *name = config_setting_name(jdb); - if ( (class_ = pc->check_job_name(name)) == -1 ) { + if ((class = pc->check_job_name(name)) == -1) { ShowWarning("pc_read_job_db: '%s' unknown job name!\n", name); continue; } - idx = pc->class2idx(class_); + idx = pc->class2idx(class); status->read_job_db_sub(idx, name, jdb); } + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", i, config_filename); libconfig->destroy(&job_db_conf); } -bool status_readdb_job2(char* fields[], int columns, int current) +static bool status_readdb_job2(char *fields[], int columns, int current) { - int idx, class_, i; + int idx, class, i; - class_ = atoi(fields[0]); + nullpo_retr(false, fields); + class = atoi(fields[0]); - if(!pc->db_checkid(class_)) - { - ShowWarning("status_readdb_job2: Invalid job class %d specified.\n", class_); + if (!pc->db_checkid(class)) { + ShowWarning("status_readdb_job2: Invalid job class %d specified.\n", class); return false; } - idx = pc->class2idx(class_); + idx = pc->class2idx(class); for(i = 1; i < columns; i++) { @@ -12842,10 +13215,11 @@ bool status_readdb_job2(char* fields[], int columns, int current) return true; } -bool status_readdb_sizefix(char* fields[], int columns, int current) +static bool status_readdb_sizefix(char *fields[], int columns, int current) { unsigned int i; + nullpo_retr(false, fields); for(i = 0; i < MAX_SINGLE_WEAPON_TYPE; i++) { status->dbs->atkmods[current][i] = atoi(fields[i]); @@ -12853,150 +13227,114 @@ bool status_readdb_sizefix(char* fields[], int columns, int current) return true; } -/** - * Processes a refine_db.conf entry. - * - * @param r Libconfig setting entry. It is expected to be valid and it - * won't be freed (it is care of the caller to do so if - * necessary) - * @param n Ordinal number of the entry, to be displayed in case of - * validation errors. - * @param source Source of the entry (file name), to be displayed in case of - * validation errors. - * @return # of the validated entry, or 0 in case of failure. - */ -int status_readdb_refine_libconfig_sub(struct config_setting_t *r, const char *name, const char *source) -{ - struct config_setting_t *rate = NULL; - int type = REFINE_TYPE_ARMOR, bonus_per_level = 0, rnd_bonus_v = 0, rnd_bonus_lv = 0; - char lv[4]; - nullpo_ret(r); - nullpo_ret(name); - nullpo_ret(source); - - if (strncmp(name, "Armors", 6) == 0) { - type = REFINE_TYPE_ARMOR; - } else if (strncmp(name, "WeaponLevel", 11) != 0 || !strspn(&name[strlen(name)-1], "0123456789") || (type = atoi(strncpy(lv, name+11, 2))) == REFINE_TYPE_ARMOR) { - ShowError("status_readdb_refine_libconfig_sub: Invalid key name for entry '%s' in \"%s\", skipping.\n", name, source); - return 0; - } - if (type < REFINE_TYPE_ARMOR || type >= REFINE_TYPE_MAX) { - ShowError("status_readdb_refine_libconfig_sub: Out of range level for entry '%s' in \"%s\", skipping.\n", name, source); - return 0; - } - if (!libconfig->setting_lookup_int(r, "StatsPerLevel", &bonus_per_level)) { - ShowWarning("status_readdb_refine_libconfig_sub: Missing StatsPerLevel for entry '%s' in \"%s\", skipping.\n", name, source); - return 0; - } - if (!libconfig->setting_lookup_int(r, "RandomBonusStartLevel", &rnd_bonus_lv)) { - ShowWarning("status_readdb_refine_libconfig_sub: Missing RandomBonusStartLevel for entry '%s' in \"%s\", skipping.\n", name, source); - return 0; - } - if (!libconfig->setting_lookup_int(r, "RandomBonusValue", &rnd_bonus_v)) { - ShowWarning("status_readdb_refine_libconfig_sub: Missing RandomBonusValue for entry '%s' in \"%s\", skipping.\n", name, source); - return 0; - } - - if ((rate=libconfig->setting_get_member(r, "Rates")) != NULL && config_setting_is_group(rate)) { - struct config_setting_t *t = NULL; - bool duplicate[MAX_REFINE]; - int bonus[MAX_REFINE], rnd_bonus[MAX_REFINE], chance[MAX_REFINE]; - int i; - memset(&duplicate, 0, sizeof(duplicate)); - memset(&bonus, 0, sizeof(bonus)); - memset(&rnd_bonus, 0, sizeof(rnd_bonus)); - - for (i = 0; i < MAX_REFINE; i++) { - chance[i] = 100; - } - i = 0; - while ((t = libconfig->setting_get_elem(rate,i++)) != NULL && config_setting_is_group(t)) { - int level = 0, i32; - char *rlvl = config_setting_name(t); - memset(&lv, 0, sizeof(lv)); - if (!strspn(&rlvl[strlen(rlvl)-1], "0123456789") || (level = atoi(strncpy(lv, rlvl+2, 3))) <= 0) { - ShowError("status_readdb_refine_libconfig_sub: Invalid refine level format '%s' for entry %s in \"%s\"... skipping.\n", rlvl, name, source); - continue; - } - if (level <= 0 || level > MAX_REFINE) { - ShowError("status_readdb_refine_libconfig_sub: Out of range refine level '%s' for entry %s in \"%s\"... skipping.\n", rlvl, name, source); - continue; - } - level--; - if (duplicate[level]) { - ShowWarning("status_readdb_refine_libconfig_sub: duplicate rate '%s' for entry %s in \"%s\", overwriting previous entry...\n", rlvl, name, source); - } else { - duplicate[level] = true; - } - if (libconfig->setting_lookup_int(t, "Chance", &i32)) - chance[level] = i32; - else - chance[level] = 100; - if (libconfig->setting_lookup_int(t, "Bonus", &i32)) - bonus[level] += i32; - if (level >= rnd_bonus_lv - 1) - rnd_bonus[level] = rnd_bonus_v * (level - rnd_bonus_lv + 2); - } - for (i = 0; i < MAX_REFINE; i++) { - status->dbs->refine_info[type].chance[i] = chance[i]; - status->dbs->refine_info[type].randombonus_max[i] = rnd_bonus[i]; - bonus[i] += bonus_per_level + (i > 0 ? bonus[i-1] : 0); - status->dbs->refine_info[type].bonus[i] = bonus[i]; - } - } else { - ShowWarning("status_readdb_refine_libconfig_sub: Missing refine rates for entry '%s' in \"%s\", skipping.\n", name, source); - return 0; - } - return type+1; -} - -/** - * Reads from a libconfig-formatted refine_db.conf file. - * - * @param *filename File name, relative to the database path. - * @return The number of found entries. - */ -int status_readdb_refine_libconfig(const char *filename) { - bool duplicate[REFINE_TYPE_MAX]; - struct config_t refine_db_conf; - struct config_setting_t *r; +static bool status_read_scdb_libconfig(void) +{ + struct config_t status_conf; char filepath[256]; - int i = 0, count = 0,type = 0; + safesnprintf(filepath, sizeof(filepath), "%s/%s", map->db_path, "sc_config.conf"); - sprintf(filepath, "%s/%s", map->db_path, filename); - if (!libconfig->load_file(&refine_db_conf, filepath)) - return 0; + if (libconfig->load_file(&status_conf, filepath) == CONFIG_FALSE) { + ShowError("status_read_scdb_libconfig: can't read %s\n", filepath); + return false; + } - memset(&duplicate,0,sizeof(duplicate)); + int i = 0; + int count = 0; + struct config_setting_t *it = NULL; - while((r = libconfig->setting_get_elem(refine_db_conf.root,i++))) { - char *name = config_setting_name(r); - if((type=status->readdb_refine_libconfig_sub(r, name, filename))) { - if( duplicate[type-1] ) { - ShowWarning("status_readdb_refine_libconfig: duplicate entry for %s in \"%s\", overwriting previous entry...\n", name, filename); - } else duplicate[type-1] = true; - count++; - } + while ((it = libconfig->setting_get_elem(status_conf.root, i++)) != NULL) { + if (status->read_scdb_libconfig_sub(it, i - 1, filepath)) + ++count; } - libconfig->destroy(&refine_db_conf); - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename); - return count; + // @TODO: find a better way of handling this + if (!battle_config.display_hallucination) //Disable Hallucination. + status->dbs->IconChangeTable[SC_ILLUSION].id = SI_BLANK; + + libconfig->destroy(&status_conf); + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filepath); + return true; } -bool status_readdb_scconfig(char* fields[], int columns, int current) { - int val = 0; - char* type = fields[0]; +static bool status_read_scdb_libconfig_sub(struct config_setting_t *it, int idx, const char *source) +{ + nullpo_retr(false, it); + nullpo_retr(false, source); + + int i32; + int status_id; + const char *name = config_setting_name(it); - if( !script->get_constant(type, &val) ){ - ShowWarning("status_readdb_sc_conf: Invalid status type %s specified.\n", type); + if (!script->get_constant(name, &status_id) || status_id <= SC_NONE || status_id >= SC_MAX) { + ShowWarning("status_read_scdb_libconfig_sub: Invalid status type (%s) in \"%s\" entry #%d, skipping.\n", name, source, idx); return false; } - status->dbs->sc_conf[val] = (int)strtol(fields[1], NULL, 0); + libconfig->setting_lookup_bool_real(it, "Visible", &status->dbs->DisplayType[status_id]); + + struct config_setting_t *fg = libconfig->setting_get_member(it, "Flags"); + if (fg != NULL) + status->read_scdb_libconfig_sub_flag(fg, status_id, source); + if (itemdb->lookup_const(it, "Icon", &i32) && i32 >= 0) + status->dbs->IconChangeTable[status_id].id = i32; + else + status->dbs->IconChangeTable[status_id].id = SI_BLANK; + return true; +} + +static bool status_read_scdb_libconfig_sub_flag(struct config_setting_t *it, int type, const char *source) +{ + nullpo_retr(false, it); + nullpo_retr(false, source); + Assert_retr(false, type > SC_NONE && type < SC_MAX); + + int i = 0; + struct config_setting_t *t = NULL; + while ((t = libconfig->setting_get_elem(it, i++)) != NULL) { + const char *flag = config_setting_name(t); + bool on = libconfig->setting_get_bool_real(t); + int j; + + struct { + const char *name; + enum sc_conf_type value; + } flags[] = { + { "NoDeathReset", SC_NO_REM_DEATH }, + { "NoSave", SC_NO_SAVE }, + { "NoDispelReset", SC_NO_DISPELL }, + { "NoClearanceReset", SC_NO_CLEARANCE }, + { "Buff", SC_BUFF }, + { "Debuff", SC_DEBUFF }, + { "NoMadoReset", SC_MADO_NO_RESET }, + { "NoAllReset", SC_NO_CLEAR }, + { "NoBoss", SC_NO_BOSS }, + }; + + ARR_FIND(0, ARRAYLENGTH(flags), j, strcmpi(flag, flags[j].name) == 0); + if (j != ARRAYLENGTH(flags)) { + if (strcmp(flag, flags[j].name) != 0) { + ShowWarning("status_read_scdb_libconfig_sub_flag: flag (%s) for status effect (%d) is casesensitive, correct it to (%s).", flag, type, flags[i].name); + } + if (on) { + status->dbs->sc_conf[type] |= flags[j].value; + } else { + status->dbs->sc_conf[type] &= ~flags[j].value; + } + } else { + if (!status->read_scdb_libconfig_sub_flag_additional(it, type, source)) + ShowWarning("status_read_scdb_libconfig_sub_flag: invalid flag (%s) for status effect (%d).", flag, type); + } + } return true; } + +static bool status_read_scdb_libconfig_sub_flag_additional(struct config_setting_t *it, int type, const char *source) +{ + // to be used by plugins + return false; +} + /** * Read status db * job1.txt @@ -13004,7 +13342,7 @@ bool status_readdb_scconfig(char* fields[], int columns, int current) { * size_fixe.txt * refine_db.txt **/ -int status_readdb(void) +static int status_readdb(void) { int i, j; @@ -13031,30 +13369,23 @@ int status_readdb(void) for(j = 0; j < MAX_SINGLE_WEAPON_TYPE; j++) status->dbs->atkmods[i][j] = 100; - // refine_db.txt - for(i=0;i<ARRAYLENGTH(status->dbs->refine_info);i++) { - for(j=0;j<MAX_REFINE; j++) { - status->dbs->refine_info[i].chance[j] = 100; - status->dbs->refine_info[i].bonus[j] = 0; - status->dbs->refine_info[i].randombonus_max[j] = 0; - } - } - // read databases // sv->readdb(map->db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, status->readdb_job2); sv->readdb(map->db_path, DBPATH"size_fix.txt", ',', MAX_SINGLE_WEAPON_TYPE, MAX_SINGLE_WEAPON_TYPE, ARRAYLENGTH(status->dbs->atkmods), status->readdb_sizefix); - status->readdb_refine_libconfig(DBPATH"refine_db.conf"); - sv->readdb(map->db_path, "sc_config.txt", ',', 2, 2, SC_MAX, status->readdb_scconfig); + status->read_scdb_libconfig(); status->read_job_db(); + pc->validate_levels(); + return 0; } /*========================================== -* Status db init and destroy. -*------------------------------------------*/ -int do_init_status(bool minimal) { + * Status db init and destroy. + *------------------------------------------*/ +static int do_init_status(bool minimal) +{ if (minimal) return 0; @@ -13069,16 +13400,19 @@ int do_init_status(bool minimal) { timer->add_interval(status->natural_heal_prev_tick + NATURAL_HEAL_INTERVAL, status->natural_heal_timer, 0, 0, NATURAL_HEAL_INTERVAL); return 0; } -void do_final_status(void) { + +static void do_final_status(void) +{ ers_destroy(status->data_ers); } /*===================================== -* Default Functions : status.h -* Generated by HerculesInterfaceMaker -* created by Susu -*-------------------------------------*/ -void status_defaults(void) { + * Default Functions : status.h + * Generated by HerculesInterfaceMaker + * created by Susu + *-------------------------------------*/ +void status_defaults(void) +{ status = &status_s; status->dbs = &statusdbs; @@ -13096,13 +13430,13 @@ void status_defaults(void) { status->natural_heal_prev_tick = 0; status->natural_heal_diff_tick = 0; /* funcs */ - status->get_refine_chance = status_get_refine_chance; // for looking up associated data status->skill2sc = status_skill2sc; status->sc2skill = status_sc2skill; status->sc2scb_flag = status_sc2scb_flag; - status->type2relevant_bl_types = status_type2relevant_bl_types; + status->get_sc_relevant_bl_types = status_get_sc_relevant_bl_types; status->get_sc_type = status_get_sc_type; + status->get_sc_icon = status_get_sc_icon; status->damage = status_damage; //Define for standard HP/SP skill-related cost triggers (mobs require no HP/SP to use skills) @@ -13140,6 +13474,7 @@ void status_defaults(void) { status->get_sc_def = status_get_sc_def; status->change_start = status_change_start; + status->change_start_sub = status_change_start_sub; status->change_end_ = status_change_end_; status->kaahi_heal_timer = kaahi_heal_timer; status->change_timer = status_change_timer; @@ -13147,11 +13482,18 @@ void status_defaults(void) { status->change_clear = status_change_clear; status->change_clear_buffs = status_change_clear_buffs; + status->is_immune_to_status = status_is_immune_to_status; + status->is_boss_resist_sc = status_is_boss_resist_sc; + status->end_sc_before_start = status_end_sc_before_start; + status->change_start_stop_action = status_change_start_stop_action; + status->change_start_set_option = status_change_start_set_option; + status->get_val_flag = status_get_val_flag; status->calc_bl_ = status_calc_bl_; status->calc_mob_ = status_calc_mob_; status->calc_pet_ = status_calc_pet_; status->calc_pc_ = status_calc_pc_; status->calc_pc_additional = status_calc_pc_additional; + status->calc_pc_recover_hp = status_calc_pc_recover_hp; status->calc_homunculus_ = status_calc_homunculus_; status->calc_mercenary_ = status_calc_mercenary_; status->calc_elemental_ = status_calc_elemental_; @@ -13188,6 +13530,8 @@ void status_defaults(void) { status->base_atk = status_base_atk; status->get_base_maxhp = status_get_base_maxhp; status->get_base_maxsp = status_get_base_maxsp; + status->get_restart_hp = status_get_restart_hp; + status->get_restart_sp = status_get_restart_sp; status->calc_npc_ = status_calc_npc_; status->calc_str = status_calc_str; status->calc_agi = status_calc_agi; @@ -13214,14 +13558,21 @@ void status_defaults(void) { status->calc_ematk = status_calc_ematk; status->calc_bl_main = status_calc_bl_main; status->display_add = status_display_add; + status->change_start_display = status_change_start_display; + status->change_start_unknown_sc = status_change_start_unknown_sc; status->display_remove = status_display_remove; status->natural_heal = status_natural_heal; status->natural_heal_timer = status_natural_heal_timer; status->readdb_job2 = status_readdb_job2; status->readdb_sizefix = status_readdb_sizefix; - status->readdb_refine_libconfig = status_readdb_refine_libconfig; - status->readdb_refine_libconfig_sub = status_readdb_refine_libconfig_sub; - status->readdb_scconfig = status_readdb_scconfig; + status->read_scdb_libconfig = status_read_scdb_libconfig; + status->read_scdb_libconfig_sub = status_read_scdb_libconfig_sub; + status->read_scdb_libconfig_sub_flag = status_read_scdb_libconfig_sub_flag; + status->read_scdb_libconfig_sub_flag_additional = status_read_scdb_libconfig_sub_flag_additional; status->read_job_db = status_read_job_db; status->read_job_db_sub = status_read_job_db_sub; + status->set_sc = status_set_sc; + status->copy = status_copy; + status->base_matk_min = status_base_matk_min; + status->base_matk_max = status_base_matk_max; } |