|
@@ -33,6 +33,12 @@
|
|
//For specifying where in the SkillStatusChangeTableArray the "out of bounds" skills get stored. [Skotlex]
|
|
//For specifying where in the SkillStatusChangeTableArray the "out of bounds" skills get stored. [Skotlex]
|
|
#define SC_HM_BASE 800
|
|
#define SC_HM_BASE 800
|
|
#define SC_GD_BASE 900
|
|
#define SC_GD_BASE 900
|
|
|
|
+//Regen related flags.
|
|
|
|
+#define RGN_HP 0x01
|
|
|
|
+#define RGN_SP 0x02
|
|
|
|
+#define RGN_SHP 0x04
|
|
|
|
+#define RGN_SSP 0x08
|
|
|
|
+
|
|
int SkillStatusChangeTableArray[MAX_SKILL]; //Stores the status that should be associated to this skill.
|
|
int SkillStatusChangeTableArray[MAX_SKILL]; //Stores the status that should be associated to this skill.
|
|
int StatusIconChangeTable[SC_MAX]; //Stores the icon that should be associated to this status change.
|
|
int StatusIconChangeTable[SC_MAX]; //Stores the icon that should be associated to this status change.
|
|
int StatusSkillChangeTable[SC_MAX]; //Stores the skill that should be considered associated to this status change.
|
|
int StatusSkillChangeTable[SC_MAX]; //Stores the skill that should be considered associated to this status change.
|
|
@@ -111,13 +117,13 @@ void initChangeTables(void) {
|
|
StatusChangeFlagTable[SC_FREEZE] = SCB_DEF_ELE|SCB_DEF|SCB_MDEF;
|
|
StatusChangeFlagTable[SC_FREEZE] = SCB_DEF_ELE|SCB_DEF|SCB_MDEF;
|
|
// StatusChangeFlagTable[SC_STUN] = SCB_NONE;
|
|
// StatusChangeFlagTable[SC_STUN] = SCB_NONE;
|
|
// StatusChangeFlagTable[SC_SLEEP] = SCB_NONE;
|
|
// StatusChangeFlagTable[SC_SLEEP] = SCB_NONE;
|
|
- StatusChangeFlagTable[SC_POISON] = SCB_DEF2;
|
|
|
|
|
|
+ StatusChangeFlagTable[SC_POISON] = SCB_DEF2|SCB_REGEN;
|
|
StatusChangeFlagTable[SC_CURSE] = SCB_LUK|SCB_BATK|SCB_WATK|SCB_SPEED;
|
|
StatusChangeFlagTable[SC_CURSE] = SCB_LUK|SCB_BATK|SCB_WATK|SCB_SPEED;
|
|
// StatusChangeFlagTable[SC_SILENCE] = SCB_NONE;
|
|
// StatusChangeFlagTable[SC_SILENCE] = SCB_NONE;
|
|
// StatusChangeFlagTable[SC_CONFUSION] = SCB_NONE;
|
|
// StatusChangeFlagTable[SC_CONFUSION] = SCB_NONE;
|
|
StatusChangeFlagTable[SC_BLIND] = SCB_HIT|SCB_FLEE;
|
|
StatusChangeFlagTable[SC_BLIND] = SCB_HIT|SCB_FLEE;
|
|
-// StatusChangeFlagTable[SC_BLEEDING] = SCB_NONE;
|
|
|
|
- StatusChangeFlagTable[SC_DPOISON] = SCB_DEF2;
|
|
|
|
|
|
+ StatusChangeFlagTable[SC_BLEEDING] = SCB_REGEN;
|
|
|
|
+ StatusChangeFlagTable[SC_DPOISON] = SCB_DEF2|SCB_REGEN;
|
|
|
|
|
|
//The icons for the common ailments
|
|
//The icons for the common ailments
|
|
// StatusIconChangeTable[SC_STONE] = SI_BLANK;
|
|
// StatusIconChangeTable[SC_STONE] = SI_BLANK;
|
|
@@ -156,9 +162,9 @@ void initChangeTables(void) {
|
|
set_sc(PR_SUFFRAGIUM, SC_SUFFRAGIUM, SI_SUFFRAGIUM, SCB_NONE);
|
|
set_sc(PR_SUFFRAGIUM, SC_SUFFRAGIUM, SI_SUFFRAGIUM, SCB_NONE);
|
|
set_sc(PR_ASPERSIO, SC_ASPERSIO, SI_ASPERSIO, SCB_ATK_ELE);
|
|
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_BENEDICTIO, SC_BENEDICTIO, SI_BENEDICTIO, SCB_DEF_ELE);
|
|
- set_sc(PR_SLOWPOISON, SC_SLOWPOISON, SI_SLOWPOISON, SCB_NONE);
|
|
|
|
|
|
+ set_sc(PR_SLOWPOISON, SC_SLOWPOISON, SI_SLOWPOISON, SCB_REGEN);
|
|
set_sc(PR_KYRIE, SC_KYRIE, SI_KYRIE, SCB_NONE);
|
|
set_sc(PR_KYRIE, SC_KYRIE, SI_KYRIE, SCB_NONE);
|
|
- set_sc(PR_MAGNIFICAT, SC_MAGNIFICAT, SI_MAGNIFICAT, SCB_NONE);
|
|
|
|
|
|
+ set_sc(PR_MAGNIFICAT, SC_MAGNIFICAT, SI_MAGNIFICAT, SCB_REGEN);
|
|
set_sc(PR_GLORIA, SC_GLORIA, SI_GLORIA, SCB_LUK);
|
|
set_sc(PR_GLORIA, SC_GLORIA, SI_GLORIA, SCB_LUK);
|
|
add_sc(PR_LEXDIVINA, SC_SILENCE);
|
|
add_sc(PR_LEXDIVINA, SC_SILENCE);
|
|
set_sc(PR_LEXAETERNA, SC_AETERNA, SI_AETERNA, SCB_NONE);
|
|
set_sc(PR_LEXAETERNA, SC_AETERNA, SI_AETERNA, SCB_NONE);
|
|
@@ -183,7 +189,7 @@ void initChangeTables(void) {
|
|
set_sc(AS_POISONREACT, SC_POISONREACT, SI_POISONREACT, SCB_NONE);
|
|
set_sc(AS_POISONREACT, SC_POISONREACT, SI_POISONREACT, SCB_NONE);
|
|
add_sc(AS_VENOMDUST, SC_POISON);
|
|
add_sc(AS_VENOMDUST, SC_POISON);
|
|
add_sc(AS_SPLASHER, SC_SPLASHER);
|
|
add_sc(AS_SPLASHER, SC_SPLASHER);
|
|
- set_sc(NV_TRICKDEAD, SC_TRICKDEAD, SI_TRICKDEAD, SCB_NONE);
|
|
|
|
|
|
+ set_sc(NV_TRICKDEAD, SC_TRICKDEAD, SI_TRICKDEAD, SCB_REGEN);
|
|
set_sc(SM_AUTOBERSERK, SC_AUTOBERSERK, SI_STEELBODY, SCB_NONE);
|
|
set_sc(SM_AUTOBERSERK, SC_AUTOBERSERK, SI_STEELBODY, SCB_NONE);
|
|
add_sc(TF_SPRINKLESAND, SC_BLIND);
|
|
add_sc(TF_SPRINKLESAND, SC_BLIND);
|
|
add_sc(TF_THROWSTONE, SC_STUN);
|
|
add_sc(TF_THROWSTONE, SC_STUN);
|
|
@@ -235,8 +241,8 @@ void initChangeTables(void) {
|
|
set_sc(MO_STEELBODY, SC_STEELBODY, SI_STEELBODY, SCB_DEF|SCB_MDEF|SCB_ASPD|SCB_SPEED);
|
|
set_sc(MO_STEELBODY, SC_STEELBODY, SI_STEELBODY, SCB_DEF|SCB_MDEF|SCB_ASPD|SCB_SPEED);
|
|
add_sc(MO_BLADESTOP, SC_BLADESTOP_WAIT);
|
|
add_sc(MO_BLADESTOP, SC_BLADESTOP_WAIT);
|
|
add_sc(MO_BLADESTOP, SC_BLADESTOP);
|
|
add_sc(MO_BLADESTOP, SC_BLADESTOP);
|
|
- set_sc(MO_EXPLOSIONSPIRITS, SC_EXPLOSIONSPIRITS, SI_EXPLOSIONSPIRITS, SCB_CRI);
|
|
|
|
- add_sc(MO_EXTREMITYFIST, SC_EXTREMITYFIST);
|
|
|
|
|
|
+ set_sc(MO_EXPLOSIONSPIRITS, SC_EXPLOSIONSPIRITS, SI_EXPLOSIONSPIRITS, SCB_CRI|SCB_REGEN);
|
|
|
|
+ set_sc(MO_EXTREMITYFIST, SC_EXTREMITYFIST, SI_BLANK, SCB_REGEN);
|
|
add_sc(SA_MAGICROD, SC_MAGICROD);
|
|
add_sc(SA_MAGICROD, SC_MAGICROD);
|
|
set_sc(SA_AUTOSPELL, SC_AUTOSPELL, SI_AUTOSPELL, SCB_NONE);
|
|
set_sc(SA_AUTOSPELL, SC_AUTOSPELL, SI_AUTOSPELL, SCB_NONE);
|
|
set_sc(SA_FLAMELAUNCHER, SC_FIREWEAPON, SI_FIREWEAPON, SCB_ATK_ELE);
|
|
set_sc(SA_FLAMELAUNCHER, SC_FIREWEAPON, SI_FIREWEAPON, SCB_ATK_ELE);
|
|
@@ -248,7 +254,7 @@ void initChangeTables(void) {
|
|
set_sc(SA_VIOLENTGALE, SC_VIOLENTGALE, SI_LANDENDOW, SCB_FLEE);
|
|
set_sc(SA_VIOLENTGALE, SC_VIOLENTGALE, SI_LANDENDOW, SCB_FLEE);
|
|
add_sc(SA_REVERSEORCISH, SC_ORCISH);
|
|
add_sc(SA_REVERSEORCISH, SC_ORCISH);
|
|
add_sc(SA_COMA, SC_COMA);
|
|
add_sc(SA_COMA, SC_COMA);
|
|
- set_sc(BD_ENCORE, SC_DANCING, SI_BLANK, SCB_SPEED);
|
|
|
|
|
|
+ set_sc(BD_ENCORE, SC_DANCING, SI_BLANK, SCB_SPEED|SCB_REGEN);
|
|
add_sc(BD_RICHMANKIM, SC_RICHMANKIM);
|
|
add_sc(BD_RICHMANKIM, SC_RICHMANKIM);
|
|
set_sc(BD_ETERNALCHAOS, SC_ETERNALCHAOS, SI_BLANK, SCB_DEF2);
|
|
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_DRUMBATTLEFIELD, SC_DRUMBATTLE, SI_BLANK, SCB_WATK|SCB_DEF);
|
|
@@ -278,8 +284,8 @@ void initChangeTables(void) {
|
|
set_sc(LK_AURABLADE, SC_AURABLADE, SI_AURABLADE, SCB_NONE);
|
|
set_sc(LK_AURABLADE, SC_AURABLADE, SI_AURABLADE, SCB_NONE);
|
|
set_sc(LK_PARRYING, SC_PARRYING, SI_PARRYING, SCB_NONE);
|
|
set_sc(LK_PARRYING, SC_PARRYING, SI_PARRYING, SCB_NONE);
|
|
set_sc(LK_CONCENTRATION, SC_CONCENTRATION, SI_CONCENTRATION, SCB_BATK|SCB_WATK|SCB_HIT|SCB_DEF|SCB_DEF2|SCB_DSPD);
|
|
set_sc(LK_CONCENTRATION, SC_CONCENTRATION, SI_CONCENTRATION, SCB_BATK|SCB_WATK|SCB_HIT|SCB_DEF|SCB_DEF2|SCB_DSPD);
|
|
- set_sc(LK_TENSIONRELAX, SC_TENSIONRELAX, SI_TENSIONRELAX, SCB_NONE);
|
|
|
|
- set_sc(LK_BERSERK, SC_BERSERK, SI_BERSERK, SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP);
|
|
|
|
|
|
+ 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(LK_FURY, SC_FURY, SI_FURY, SCB_NONE); //Unused skill
|
|
// set_sc(LK_FURY, SC_FURY, SI_FURY, SCB_NONE); //Unused skill
|
|
set_sc(HP_ASSUMPTIO, SC_ASSUMPTIO, SI_ASSUMPTIO, SCB_NONE);
|
|
set_sc(HP_ASSUMPTIO, SC_ASSUMPTIO, SI_ASSUMPTIO, SCB_NONE);
|
|
add_sc(HP_BASILICA, SC_BASILICA);
|
|
add_sc(HP_BASILICA, SC_BASILICA);
|
|
@@ -378,6 +384,7 @@ void initChangeTables(void) {
|
|
|
|
|
|
set_sc(GD_LEADERSHIP, SC_GUILDAURA, SI_BLANK, SCB_STR|SCB_AGI|SCB_VIT|SCB_DEX);
|
|
set_sc(GD_LEADERSHIP, SC_GUILDAURA, SI_BLANK, SCB_STR|SCB_AGI|SCB_VIT|SCB_DEX);
|
|
set_sc(GD_BATTLEORDER, SC_BATTLEORDERS, SI_BLANK, SCB_STR|SCB_INT|SCB_DEX);
|
|
set_sc(GD_BATTLEORDER, SC_BATTLEORDERS, SI_BLANK, SCB_STR|SCB_INT|SCB_DEX);
|
|
|
|
+ set_sc(GD_REGENERATION, SC_REGENERATION, SI_BLANK, SCB_REGEN);
|
|
|
|
|
|
// Storing the target job rather than simply SC_SPIRIT simplifies code later on.
|
|
// Storing the target job rather than simply SC_SPIRIT simplifies code later on.
|
|
SkillStatusChangeTableArray[SL_ALCHEMIST] = MAPID_ALCHEMIST,
|
|
SkillStatusChangeTableArray[SL_ALCHEMIST] = MAPID_ALCHEMIST,
|
|
@@ -698,6 +705,12 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
|
|
skill_clear_unitgroup(target);
|
|
skill_clear_unitgroup(target);
|
|
status_change_clear(target,0);
|
|
status_change_clear(target,0);
|
|
|
|
|
|
|
|
+ if(target->type&BL_REGEN)
|
|
|
|
+ { //Reset regen ticks.
|
|
|
|
+ struct regen_data *regen = status_get_regen_data(target);
|
|
|
|
+ if (regen)
|
|
|
|
+ memset(®en->tick, 0, sizeof(regen->tick));
|
|
|
|
+ }
|
|
if(flag&4) //Delete from memory. (also invokes map removal code)
|
|
if(flag&4) //Delete from memory. (also invokes map removal code)
|
|
unit_free(target);
|
|
unit_free(target);
|
|
else
|
|
else
|
|
@@ -1518,7 +1531,8 @@ int status_calc_pc(struct map_session_data* sd,int first)
|
|
sd->atk_rate = sd->matk_rate = 100;
|
|
sd->atk_rate = sd->matk_rate = 100;
|
|
sd->critical_rate = sd->hit_rate = sd->flee_rate = sd->flee2_rate = 100;
|
|
sd->critical_rate = sd->hit_rate = sd->flee_rate = sd->flee2_rate = 100;
|
|
sd->def_rate = sd->def2_rate = sd->mdef_rate = sd->mdef2_rate = 100;
|
|
sd->def_rate = sd->def2_rate = sd->mdef_rate = sd->mdef2_rate = 100;
|
|
-
|
|
|
|
|
|
+ sd->regen.state.block = 0;
|
|
|
|
+
|
|
// zeroed arays, order follows the order in map.h.
|
|
// zeroed arays, order follows the order in map.h.
|
|
// add new arrays to the end of zeroed area in map.h (see comments) and size here. [zzo]
|
|
// add new arrays to the end of zeroed area in map.h (see comments) and size here. [zzo]
|
|
memset (sd->param_bonus, 0, sizeof(sd->param_bonus)
|
|
memset (sd->param_bonus, 0, sizeof(sd->param_bonus)
|
|
@@ -1587,10 +1601,6 @@ int status_calc_pc(struct map_session_data* sd,int first)
|
|
+ sizeof(sd->arrow_ele)
|
|
+ sizeof(sd->arrow_ele)
|
|
+ sizeof(sd->arrow_cri)
|
|
+ sizeof(sd->arrow_cri)
|
|
+ sizeof(sd->arrow_hit)
|
|
+ sizeof(sd->arrow_hit)
|
|
- + sizeof(sd->nhealhp)
|
|
|
|
- + sizeof(sd->nhealsp)
|
|
|
|
- + sizeof(sd->nshealhp)
|
|
|
|
- + sizeof(sd->nshealsp)
|
|
|
|
+ sizeof(sd->nsshealhp)
|
|
+ sizeof(sd->nsshealhp)
|
|
+ sizeof(sd->nsshealsp)
|
|
+ sizeof(sd->nsshealsp)
|
|
+ sizeof(sd->critical_def)
|
|
+ sizeof(sd->critical_def)
|
|
@@ -1635,7 +1645,6 @@ int status_calc_pc(struct map_session_data* sd,int first)
|
|
+ sizeof(sd->unbreakable)
|
|
+ sizeof(sd->unbreakable)
|
|
+ sizeof(sd->unbreakable_equip)
|
|
+ sizeof(sd->unbreakable_equip)
|
|
+ sizeof(sd->unstripable_equip)
|
|
+ sizeof(sd->unstripable_equip)
|
|
- + sizeof(sd->no_regen)
|
|
|
|
+ sizeof(sd->add_def_count)
|
|
+ sizeof(sd->add_def_count)
|
|
+ sizeof(sd->add_mdef_count)
|
|
+ sizeof(sd->add_mdef_count)
|
|
+ sizeof(sd->add_dmg_count)
|
|
+ sizeof(sd->add_dmg_count)
|
|
@@ -2058,7 +2067,12 @@ int status_calc_pc(struct map_session_data* sd,int first)
|
|
sd->max_weight += 10000;
|
|
sd->max_weight += 10000;
|
|
if(sd->sc.data[SC_KNOWLEDGE].timer != -1)
|
|
if(sd->sc.data[SC_KNOWLEDGE].timer != -1)
|
|
sd->max_weight += sd->max_weight*sd->sc.data[SC_KNOWLEDGE].val1/10;
|
|
sd->max_weight += sd->max_weight*sd->sc.data[SC_KNOWLEDGE].val1/10;
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ if (pc_checkskill(sd,SM_MOVINGRECOVERY)>0)
|
|
|
|
+ sd->regen.state.walk = 1;
|
|
|
|
+ else
|
|
|
|
+ sd->regen.state.walk = 0;
|
|
|
|
+
|
|
// Skill SP cost
|
|
// Skill SP cost
|
|
if((skill=pc_checkskill(sd,HP_MANARECHARGE))>0 )
|
|
if((skill=pc_checkskill(sd,HP_MANARECHARGE))>0 )
|
|
sd->dsprate -= 4*skill;
|
|
sd->dsprate -= 4*skill;
|
|
@@ -2182,23 +2196,66 @@ int status_calc_pc(struct map_session_data* sd,int first)
|
|
int status_calc_homunculus(struct homun_data *hd, int first)
|
|
int status_calc_homunculus(struct homun_data *hd, int first)
|
|
{
|
|
{
|
|
struct status_data b_status, *status;
|
|
struct status_data b_status, *status;
|
|
|
|
+ struct map_session_data *sd;
|
|
|
|
+ struct s_homunculus *hom;
|
|
|
|
+ int skill;
|
|
|
|
+
|
|
memcpy(&b_status, &hd->base_status, sizeof(struct status_data));
|
|
memcpy(&b_status, &hd->base_status, sizeof(struct status_data));
|
|
|
|
+ sd = hd->master;
|
|
|
|
+ hom = &sd->homunculus;
|
|
|
|
+
|
|
status = &hd->base_status;
|
|
status = &hd->base_status;
|
|
|
|
+
|
|
|
|
+ status->str = (int) (hom->str / 10);
|
|
|
|
+ status->agi = (int) (hom->agi / 10);
|
|
|
|
+ status->vit = (int) (hom->vit / 10);
|
|
|
|
+ status->dex = (int) (hom->dex / 10);
|
|
|
|
+ status->int_ = (int) (hom->int_ / 10);
|
|
|
|
+ status->luk = (int) (hom->luk / 10);
|
|
|
|
|
|
status->def_ele = hd->homunculusDB->element ; //[orn]
|
|
status->def_ele = hd->homunculusDB->element ; //[orn]
|
|
- status->ele_lv = 1 ; //[orn]
|
|
|
|
|
|
+ status->ele_lv = 1;
|
|
status->race = hd->homunculusDB->race ; //[orn]
|
|
status->race = hd->homunculusDB->race ; //[orn]
|
|
status->size = hd->homunculusDB->size ; //[orn]
|
|
status->size = hd->homunculusDB->size ; //[orn]
|
|
status->rhw.range = 1 + status->size; //[orn]
|
|
status->rhw.range = 1 + status->size; //[orn]
|
|
status->mode = MD_CANMOVE|MD_CANATTACK|MD_ASSIST|MD_AGGRESSIVE|MD_CASTSENSOR; //[orn]
|
|
status->mode = MD_CANMOVE|MD_CANATTACK|MD_ASSIST|MD_AGGRESSIVE|MD_CASTSENSOR; //[orn]
|
|
status->speed = DEFAULT_WALK_SPEED;
|
|
status->speed = DEFAULT_WALK_SPEED;
|
|
status->aspd_rate = 1000;
|
|
status->aspd_rate = 1000;
|
|
|
|
+ status->def = hom->level/10 + status->vit/5;
|
|
|
|
+ status->mdef = hom->level/10 + status->int_/5;
|
|
|
|
|
|
- merc_hom_calc_skilltree(hd->master);
|
|
|
|
|
|
+ status->hp = 1;
|
|
|
|
+ status->sp = 1;
|
|
|
|
+ status->max_hp = hom->max_hp ;
|
|
|
|
+ status->max_sp = hom->max_sp ;
|
|
|
|
|
|
- status_cpy(&hd->battle_status, status);
|
|
|
|
- status_calc_misc(status, BL_HOM, hd->master->homunculus.level);
|
|
|
|
|
|
+ merc_hom_calc_skilltree(sd);
|
|
|
|
|
|
|
|
+ if((skill=merc_hom_checkskill(sd,HAMI_SKIN)) > 0)
|
|
|
|
+ status->def += skill * 4;
|
|
|
|
+
|
|
|
|
+ if((skill = merc_hom_checkskill(hd->master,HVAN_INSTRUCT)) > 0)
|
|
|
|
+ {
|
|
|
|
+ status->int_+= 1 +skill/2 +skill/4 +skill/5;
|
|
|
|
+ status->str += 1 +2*(skill/3) +skill/4;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if((skill=merc_hom_checkskill(sd,HAMI_SKIN)) > 0)
|
|
|
|
+ status->max_hp += skill * 2 * status->max_hp / 100;
|
|
|
|
+
|
|
|
|
+ if((skill = merc_hom_checkskill(hd->master,HLIF_BRAIN)) > 0)
|
|
|
|
+ status->max_sp += skill * 1 * status->max_sp / 100 ;
|
|
|
|
+
|
|
|
|
+ if (first) {
|
|
|
|
+ hd->battle_status.hp = hom->hp ;
|
|
|
|
+ hd->battle_status.sp = hom->sp ;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ status->batk = status_base_atk(&hd->bl, status);
|
|
|
|
+ status->rhw.atk = status->dex;
|
|
|
|
+ status->rhw.atk2 = status->str + hom->level;
|
|
|
|
+
|
|
|
|
+ status_calc_misc(status, BL_HOM, hom->level);
|
|
status_calc_bl(&hd->bl, SCB_ALL); //Status related changes.
|
|
status_calc_bl(&hd->bl, SCB_ALL); //Status related changes.
|
|
|
|
|
|
if (memcmp(&b_status, status, sizeof(struct status_data)))
|
|
if (memcmp(&b_status, status, sizeof(struct status_data)))
|
|
@@ -2233,6 +2290,140 @@ static unsigned char status_calc_element(struct block_list *bl, struct status_ch
|
|
static 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);
|
|
static unsigned short status_calc_mode(struct block_list *bl, struct status_change *sc, int mode);
|
|
static unsigned short status_calc_mode(struct block_list *bl, struct status_change *sc, int mode);
|
|
|
|
|
|
|
|
+//Calculates base regen values.
|
|
|
|
+void status_calc_regen(struct block_list *bl, struct status_data *status, struct regen_data *regen)
|
|
|
|
+{
|
|
|
|
+ struct map_session_data *sd;
|
|
|
|
+ int val, skill;
|
|
|
|
+
|
|
|
|
+ if (!(bl->type&BL_REGEN) || !regen)
|
|
|
|
+ return;
|
|
|
|
+ BL_CAST(BL_PC,bl,sd);
|
|
|
|
+
|
|
|
|
+ val = 1 + (status->vit/5) + (status->max_hp/200);
|
|
|
|
+
|
|
|
|
+ if (sd && sd->hprecov_rate != 100)
|
|
|
|
+ val = val*sd->hprecov_rate/100;
|
|
|
|
+
|
|
|
|
+ regen->hp = cap_value(val, 1, SHRT_MAX);
|
|
|
|
+
|
|
|
|
+ val = 1 + (status->int_/6) + (status->max_sp/100);
|
|
|
|
+ if(status->int_ >= 120)
|
|
|
|
+ val += ((status->int_-120)>>1) + 4;
|
|
|
|
+
|
|
|
|
+ if(sd && sd->sprecov_rate != 100)
|
|
|
|
+ val = val*sd->sprecov_rate/100;
|
|
|
|
+
|
|
|
|
+ regen->sp = cap_value(val, 1, SHRT_MAX);
|
|
|
|
+
|
|
|
|
+ if(sd)
|
|
|
|
+ {
|
|
|
|
+ if((skill=pc_checkskill(sd,HP_MEDITATIO)) > 0)
|
|
|
|
+ {
|
|
|
|
+ val = regen->sp*(100+3*skill)/100;
|
|
|
|
+ regen->sp = cap_value(val, 1, SHRT_MAX);
|
|
|
|
+ }
|
|
|
|
+ val = 0;
|
|
|
|
+ if((skill=pc_checkskill(sd,SM_RECOVERY)) > 0)
|
|
|
|
+ val += skill*5 + (status->max_hp*skill/500);
|
|
|
|
+ regen->shp = cap_value(val, 0, SHRT_MAX);
|
|
|
|
+
|
|
|
|
+ val = 0;
|
|
|
|
+ if((skill=pc_checkskill(sd,MG_SRECOVERY)) > 0)
|
|
|
|
+ val += skill*3 + (status->max_sp*skill/500);
|
|
|
|
+ if((skill=pc_checkskill(sd,NJ_NINPOU)) > 0)
|
|
|
|
+ val += skill*3 + (status->max_sp*skill/500);
|
|
|
|
+ regen->ssp = cap_value(val, 0, SHRT_MAX);
|
|
|
|
+
|
|
|
|
+ // Skill-related recovery (only when sit)
|
|
|
|
+ sd->nsshealhp = sd->nsshealsp = 0;
|
|
|
|
+ if((skill=pc_checkskill(sd,MO_SPIRITSRECOVERY)) > 0)
|
|
|
|
+ {
|
|
|
|
+ sd->nsshealhp+= skill*4 + (status->max_hp*skill/500);
|
|
|
|
+ sd->nsshealsp+= skill*2 + (status->max_sp*skill/500);
|
|
|
|
+ }
|
|
|
|
+ if((skill=pc_checkskill(sd,TK_HPTIME)) > 0 && sd->state.rest)
|
|
|
|
+ sd->nsshealhp+= skill*30 + (status->max_hp*skill/500);
|
|
|
|
+ if((skill=pc_checkskill(sd,TK_SPTIME)) > 0 && sd->state.rest)
|
|
|
|
+ {
|
|
|
|
+ sd->nsshealsp+= skill*3 + (status->max_sp*skill/500);
|
|
|
|
+ if ((skill=pc_checkskill(sd,SL_KAINA)) > 0) //Power up Enjoyable Rest
|
|
|
|
+ sd->nsshealsp += (30+10*skill)*sd->nsshealsp/100;
|
|
|
|
+ }
|
|
|
|
+ if(sd->nsshealhp > SHRT_MAX) sd->nsshealhp = SHRT_MAX;
|
|
|
|
+ if(sd->nsshealsp > SHRT_MAX) sd->nsshealsp = SHRT_MAX;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(bl->type==BL_HOM && ((TBL_HOM*)bl)->master)
|
|
|
|
+ {
|
|
|
|
+ sd = ((TBL_HOM*)bl)->master;
|
|
|
|
+ if((skill=merc_hom_checkskill(sd,HAMI_SKIN)) > 0)
|
|
|
|
+ {
|
|
|
|
+ val = regen->hp*(100+5*skill)/100;
|
|
|
|
+ regen->hp = cap_value(val, 1, SHRT_MAX);
|
|
|
|
+ }
|
|
|
|
+ if((skill = merc_hom_checkskill(sd,HLIF_BRAIN)) > 0)
|
|
|
|
+ {
|
|
|
|
+ val = regen->sp*(100+3*skill)/100;
|
|
|
|
+ regen->sp = cap_value(val, 1, SHRT_MAX);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//Calculates SC related regen rates.
|
|
|
|
+void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, struct status_change *sc)
|
|
|
|
+{
|
|
|
|
+ if (!(bl->type&BL_REGEN) || !regen)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ regen->flag = RGN_HP|RGN_SP;
|
|
|
|
+ if (regen->shp)
|
|
|
|
+ regen->flag|=RGN_SHP;
|
|
|
|
+ if (regen->ssp)
|
|
|
|
+ regen->flag|=RGN_SSP;
|
|
|
|
+
|
|
|
|
+ regen->rate.hp = regen->rate.sp =
|
|
|
|
+ regen->rate.shp = regen->rate.ssp = 1;
|
|
|
|
+
|
|
|
|
+ if (!sc || !sc->count)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ if (
|
|
|
|
+ (sc->data[SC_POISON].timer != -1 && sc->data[SC_SLOWPOISON].timer == -1)
|
|
|
|
+ || (sc->data[SC_DPOISON].timer != -1 && sc->data[SC_SLOWPOISON].timer == -1)
|
|
|
|
+ || sc->data[SC_BERSERK].timer != -1
|
|
|
|
+ || sc->data[SC_TRICKDEAD].timer != -1
|
|
|
|
+ || sc->data[SC_BLEEDING].timer != -1
|
|
|
|
+ || (sc->data[SC_REGENERATION].timer != -1 && sc->data[SC_REGENERATION].val4)
|
|
|
|
+ ) //No regen
|
|
|
|
+ regen->flag = 0;
|
|
|
|
+
|
|
|
|
+ if (
|
|
|
|
+ sc->data[SC_EXTREMITYFIST].timer != -1
|
|
|
|
+ || sc->data[SC_DANCING].timer != -1
|
|
|
|
+ || (sc->data[SC_EXPLOSIONSPIRITS].timer != -1
|
|
|
|
+ && (sc->data[SC_SPIRIT].timer==-1 || sc->data[SC_SPIRIT].val2 != SL_MONK))
|
|
|
|
+ ) //No SP regen
|
|
|
|
+ regen->flag &=~(RGN_SP|RGN_SSP);
|
|
|
|
+
|
|
|
|
+ if(
|
|
|
|
+ sc->data[SC_TENSIONRELAX].timer!=-1
|
|
|
|
+ ) {
|
|
|
|
+ regen->rate.hp += 2;
|
|
|
|
+ regen->rate.shp += 3;
|
|
|
|
+ }
|
|
|
|
+ if (sc->data[SC_MAGNIFICAT].timer != -1)
|
|
|
|
+ {
|
|
|
|
+ regen->rate.hp += 1;
|
|
|
|
+ regen->rate.sp += 1;
|
|
|
|
+ }
|
|
|
|
+ if (sc->data[SC_REGENERATION].timer != -1 && !sc->data[SC_REGENERATION].val4)
|
|
|
|
+ {
|
|
|
|
+ regen->rate.hp += sc->data[SC_REGENERATION].val2;
|
|
|
|
+ regen->rate.sp += sc->data[SC_REGENERATION].val3;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
//Calculates some attributes that depends on modified stats from status changes.
|
|
//Calculates some attributes that depends on modified stats from status changes.
|
|
void status_calc_bl_sub_pc(struct map_session_data *sd, unsigned long flag)
|
|
void status_calc_bl_sub_pc(struct map_session_data *sd, unsigned long flag)
|
|
{
|
|
{
|
|
@@ -2262,27 +2453,6 @@ void status_calc_bl_sub_pc(struct map_session_data *sd, unsigned long flag)
|
|
status->hp = status->max_hp;
|
|
status->hp = status->max_hp;
|
|
clif_updatestatus(sd,SP_HP);
|
|
clif_updatestatus(sd,SP_HP);
|
|
}
|
|
}
|
|
-
|
|
|
|
- sd->nhealhp = 1 + (status->vit/5) + (status->max_hp/200);
|
|
|
|
-
|
|
|
|
- // Apply relative modifiers from equipment
|
|
|
|
- if(sd->hprecov_rate != 100)
|
|
|
|
- sd->nhealhp = sd->nhealhp*sd->hprecov_rate/100;
|
|
|
|
-
|
|
|
|
- if(sd->nhealhp < 1) sd->nhealhp = 1;
|
|
|
|
- else if(sd->nhealhp > SHRT_MAX) sd->nhealhp = SHRT_MAX;
|
|
|
|
-
|
|
|
|
- // Skill-related HP recovery
|
|
|
|
- if((skill=pc_checkskill(sd,SM_RECOVERY)) > 0)
|
|
|
|
- sd->nshealhp = skill*5 + (status->max_hp*skill/500);
|
|
|
|
- // Skill-related HP recovery (only when sit)
|
|
|
|
- if((skill=pc_checkskill(sd,MO_SPIRITSRECOVERY)) > 0)
|
|
|
|
- sd->nsshealhp = skill*4 + (status->max_hp*skill/500);
|
|
|
|
- if((skill=pc_checkskill(sd,TK_HPTIME)) > 0 && sd->state.rest)
|
|
|
|
- sd->nsshealhp = skill*30 + (status->max_hp*skill/500);
|
|
|
|
-
|
|
|
|
- if(sd->nshealhp > SHRT_MAX) sd->nshealhp = SHRT_MAX;
|
|
|
|
- if(sd->nsshealhp > SHRT_MAX) sd->nsshealhp = SHRT_MAX;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
if(flag&(SCB_MAXSP|SCB_INT))
|
|
if(flag&(SCB_MAXSP|SCB_INT))
|
|
@@ -2314,38 +2484,6 @@ void status_calc_bl_sub_pc(struct map_session_data *sd, unsigned long flag)
|
|
status->sp = status->max_sp;
|
|
status->sp = status->max_sp;
|
|
clif_updatestatus(sd,SP_SP);
|
|
clif_updatestatus(sd,SP_SP);
|
|
}
|
|
}
|
|
-
|
|
|
|
- sd->nhealsp = 1 + (status->int_/6) + (status->max_sp/100);
|
|
|
|
- if(status->int_ >= 120)
|
|
|
|
- sd->nhealsp += ((status->int_-120)>>1) + 4;
|
|
|
|
-
|
|
|
|
- // Relative modifiers from passive skills
|
|
|
|
- if((skill=pc_checkskill(sd,HP_MEDITATIO)) > 0)
|
|
|
|
- sd->nhealsp += sd->nhealsp * 3*skill/100;
|
|
|
|
-
|
|
|
|
- // Apply relative modifiers from equipment
|
|
|
|
- if(sd->sprecov_rate != 100)
|
|
|
|
- sd->nhealsp = sd->nhealsp*sd->sprecov_rate/100;
|
|
|
|
-
|
|
|
|
- if(sd->nhealsp > SHRT_MAX) sd->nhealsp = SHRT_MAX;
|
|
|
|
- else if(sd->nhealsp < 1) sd->nhealsp = 1;
|
|
|
|
-
|
|
|
|
- // Skill-related SP recovery
|
|
|
|
- if((skill=pc_checkskill(sd,MG_SRECOVERY)) > 0)
|
|
|
|
- sd->nshealsp = skill*3 + (status->max_sp*skill/500);
|
|
|
|
- if((skill=pc_checkskill(sd,NJ_NINPOU)) > 0)
|
|
|
|
- sd->nshealsp = skill*3 + (status->max_sp*skill/500);
|
|
|
|
- // Skill-related SP recovery (only when sit)
|
|
|
|
- if((skill = pc_checkskill(sd,MO_SPIRITSRECOVERY)) > 0)
|
|
|
|
- sd->nsshealsp = skill*2 + (status->max_sp*skill/500);
|
|
|
|
- if((skill=pc_checkskill(sd,TK_SPTIME)) > 0 && sd->state.rest)
|
|
|
|
- {
|
|
|
|
- sd->nsshealsp = skill*3 + (status->max_sp*skill/500);
|
|
|
|
- if ((skill=pc_checkskill(sd,SL_KAINA)) > 0) //Power up Enjoyable Rest
|
|
|
|
- sd->nsshealsp += (30+10*skill)*sd->nsshealsp/100;
|
|
|
|
- }
|
|
|
|
- if(sd->nshealsp > SHRT_MAX) sd->nshealsp = SHRT_MAX;
|
|
|
|
- if(sd->nsshealsp > SHRT_MAX) sd->nsshealsp = SHRT_MAX;
|
|
|
|
}
|
|
}
|
|
|
|
|
|
if(flag&SCB_MATK) {
|
|
if(flag&SCB_MATK) {
|
|
@@ -2475,14 +2613,22 @@ void status_calc_bl_sub_pc(struct map_session_data *sd, unsigned long flag)
|
|
|
|
|
|
if(status->flee2 < 10) status->flee2 = 10;
|
|
if(status->flee2 < 10) status->flee2 = 10;
|
|
}
|
|
}
|
|
- if (flag == SCB_ALL)
|
|
|
|
- return; //Refresh is done on invoking function (status_calc_pc)
|
|
|
|
|
|
|
|
if(flag&SCB_SPEED) {
|
|
if(flag&SCB_SPEED) {
|
|
clif_updatestatus(sd,SP_SPEED);
|
|
clif_updatestatus(sd,SP_SPEED);
|
|
if (sd->ud.walktimer != -1) //Re-walk to adjust speed. [Skotlex]
|
|
if (sd->ud.walktimer != -1) //Re-walk to adjust speed. [Skotlex]
|
|
unit_walktoxy(&sd->bl, sd->ud.to_x, sd->ud.to_y, sd->ud.state.walk_easy);
|
|
unit_walktoxy(&sd->bl, sd->ud.to_x, sd->ud.to_y, sd->ud.state.walk_easy);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ if(flag&(SCB_INT|SCB_MAXSP|SCB_VIT|SCB_MAXHP))
|
|
|
|
+ status_calc_regen(&sd->bl, status, &sd->regen);
|
|
|
|
+
|
|
|
|
+ if(flag&SCB_REGEN)
|
|
|
|
+ status_calc_regen_rate(&sd->bl, &sd->regen, &sd->sc);
|
|
|
|
+
|
|
|
|
+ if (flag == SCB_ALL)
|
|
|
|
+ return; //Refresh is done on invoking function (status_calc_pc)
|
|
|
|
+
|
|
if(flag&SCB_STR)
|
|
if(flag&SCB_STR)
|
|
clif_updatestatus(sd,SP_STR);
|
|
clif_updatestatus(sd,SP_STR);
|
|
if(flag&SCB_AGI)
|
|
if(flag&SCB_AGI)
|
|
@@ -2532,126 +2678,51 @@ void status_calc_bl_sub_pc(struct map_session_data *sd, unsigned long flag)
|
|
//Calculates some attributes that depends on modified stats from status changes.
|
|
//Calculates some attributes that depends on modified stats from status changes.
|
|
void status_calc_bl_sub_hom(struct homun_data *hd, unsigned long flag) //[orn]
|
|
void status_calc_bl_sub_hom(struct homun_data *hd, unsigned long flag) //[orn]
|
|
{
|
|
{
|
|
- TBL_PC * sd;
|
|
|
|
struct status_data *status = &hd->battle_status, *b_status = &hd->base_status;
|
|
struct status_data *status = &hd->battle_status, *b_status = &hd->base_status;
|
|
int skill = 0;
|
|
int skill = 0;
|
|
|
|
|
|
- if (!(sd = hd->master))
|
|
|
|
- return; //Don't do anything if there isn't a master...
|
|
|
|
|
|
|
|
if(flag&(SCB_MAXHP|SCB_VIT))
|
|
if(flag&(SCB_MAXHP|SCB_VIT))
|
|
{
|
|
{
|
|
flag|=SCB_MAXHP; //Ensures client-side refresh
|
|
flag|=SCB_MAXHP; //Ensures client-side refresh
|
|
-
|
|
|
|
// Apply relative modifiers from equipment
|
|
// Apply relative modifiers from equipment
|
|
if(status->max_hp > (unsigned int)battle_config.max_hp)
|
|
if(status->max_hp > (unsigned int)battle_config.max_hp)
|
|
status->max_hp = battle_config.max_hp;
|
|
status->max_hp = battle_config.max_hp;
|
|
else if(!status->max_hp)
|
|
else if(!status->max_hp)
|
|
status->max_hp = 1;
|
|
status->max_hp = 1;
|
|
-
|
|
|
|
- // hp recovery
|
|
|
|
- hd->regenhp = 1 + (status->vit/5) + (status->max_hp/200);
|
|
|
|
-
|
|
|
|
- if(hd->regenhp < 1) hd->regenhp = 1;
|
|
|
|
-
|
|
|
|
- // Skill-related Adamantium Skin
|
|
|
|
- if((skill=merc_hom_checkskill(sd,HAMI_SKIN)) > 0) {
|
|
|
|
- status->max_hp = sd->homunculus.max_hp + skill * 2 * sd->homunculus.max_hp / 100 ;
|
|
|
|
- hd->regenhp += skill * 5 * hd->regenhp / 100 ;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- status->max_hp = status_calc_maxhp(&hd->bl, &hd->sc, status->max_hp);
|
|
|
|
-
|
|
|
|
|
|
+ if(status->hp > status->max_hp)
|
|
|
|
+ status->hp = status->max_hp;
|
|
}
|
|
}
|
|
- if(flag&SCB_DEF)
|
|
|
|
|
|
+ if(flag&SCB_VIT)
|
|
{
|
|
{
|
|
- status->def = sd->homunculus.level / 10 + status->vit / 5 ;
|
|
|
|
- if(hd->sc.data[SC_DEFENCE].timer != -1)
|
|
|
|
- status->def += hd->sc.data[SC_DEFENCE].val2;
|
|
|
|
- if((skill=merc_hom_checkskill(sd,HAMI_SKIN)) > 0) {
|
|
|
|
- status->def += skill * 4 ;
|
|
|
|
- }
|
|
|
|
|
|
+ flag|=SCB_DEF;
|
|
|
|
+ status->def += (status->vit/5 - b_status->vit/5);
|
|
}
|
|
}
|
|
if(flag&(SCB_MAXSP|SCB_INT))
|
|
if(flag&(SCB_MAXSP|SCB_INT))
|
|
{
|
|
{
|
|
flag|=SCB_MAXSP;
|
|
flag|=SCB_MAXSP;
|
|
-
|
|
|
|
- // Skill-related Instruction Change
|
|
|
|
- if((skill = merc_hom_checkskill(sd,HVAN_INSTRUCT)) > 0) {
|
|
|
|
- if ( skill == 5 ) {
|
|
|
|
- status->int_ += 3 ;
|
|
|
|
- } else if ( skill == 1 ) {
|
|
|
|
- status->int_ += 1 ;
|
|
|
|
- } else {
|
|
|
|
- status->int_ += 2 ;
|
|
|
|
- }
|
|
|
|
- if ( skill > 3 ) {
|
|
|
|
- status->str += 4 ;
|
|
|
|
- } else if ( skill == 3 ) {
|
|
|
|
- status->str += 3 ;
|
|
|
|
- } else {
|
|
|
|
- status->str += 1 ;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if((skill = merc_hom_checkskill(sd,HLIF_BRAIN)) > 0) {
|
|
|
|
- status->max_sp = sd->homunculus.max_sp + skill * 2 * sd->homunculus.max_sp / 100 ;
|
|
|
|
- hd->regensp += skill * 3 * hd->regensp / 100 ;
|
|
|
|
- if ( skill == 5 ) {
|
|
|
|
- status->max_sp *= 103 / 100 ;
|
|
|
|
- } else if ( skill == 1 ) {
|
|
|
|
- status->max_sp *= 101 / 100 ;
|
|
|
|
- } else {
|
|
|
|
- status->max_sp *= 102 / 100 ;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- status->mdef = sd->homunculus.level / 10 + status->int_ / 5 ;
|
|
|
|
- status->max_sp = status_calc_maxsp(&hd->bl, &hd->sc, status->max_sp);
|
|
|
|
-
|
|
|
|
if(status->max_sp > (unsigned int)battle_config.max_sp)
|
|
if(status->max_sp > (unsigned int)battle_config.max_sp)
|
|
status->max_sp = battle_config.max_sp;
|
|
status->max_sp = battle_config.max_sp;
|
|
else if(!status->max_sp)
|
|
else if(!status->max_sp)
|
|
status->max_sp = 1;
|
|
status->max_sp = 1;
|
|
-
|
|
|
|
- if(status->sp > status->max_sp) {
|
|
|
|
|
|
+ if(status->sp > status->max_sp)
|
|
status->sp = status->max_sp;
|
|
status->sp = status->max_sp;
|
|
- }
|
|
|
|
-
|
|
|
|
- // sp recovery
|
|
|
|
- hd->regensp = 1 + (status->int_/6) + (status->max_sp/100);
|
|
|
|
- if(status->int_ >= 120)
|
|
|
|
- hd->regensp += ((status->int_-120)>>1) + 4;
|
|
|
|
-
|
|
|
|
- if(hd->regensp < 1) hd->regensp = 1;
|
|
|
|
-
|
|
|
|
}
|
|
}
|
|
-
|
|
|
|
- if(flag&(SCB_BATK|SCB_WATK)) {
|
|
|
|
- status->rhw.atk = status->rhw.atk2 = status->str + ( status->str / 10 ) * ( status->str / 10 ) ;
|
|
|
|
- status->rhw.atk += status->dex ;
|
|
|
|
- if ( (status->str + sd->homunculus.level) > status->dex )
|
|
|
|
- status->rhw.atk2 += status->str + sd->homunculus.level ;
|
|
|
|
- else
|
|
|
|
- status->rhw.atk2 += status->dex ;
|
|
|
|
-
|
|
|
|
- if(hd->sc.data[SC_FLEET].timer!=-1)
|
|
|
|
- status->rhw.atk2 += status->rhw.atk2 * hd->sc.data[SC_FLEET].val3/100;
|
|
|
|
|
|
+ if(flag&SCB_INT) {
|
|
|
|
+ flag|=SCB_MDEF;
|
|
|
|
+ status->mdef += (status->int_/5 - b_status->int_/5);
|
|
}
|
|
}
|
|
-
|
|
|
|
- if(flag&SCB_MATK) {
|
|
|
|
- status->matk_min = status->int_+(status->int_/7)*(status->int_/7);
|
|
|
|
- status->matk_max = status->int_+(status->int_/5)*(status->int_/5);
|
|
|
|
-
|
|
|
|
- status->matk_min = status_calc_matk(&hd->bl, &hd->sc, status->matk_min);
|
|
|
|
- status->matk_max = status_calc_matk(&hd->bl, &hd->sc, status->matk_max);
|
|
|
|
-
|
|
|
|
|
|
+ if(flag&SCB_DEX) {
|
|
|
|
+ flag |=SCB_WATK;
|
|
|
|
+ status->rhw.atk += (status->dex - b_status->dex);
|
|
}
|
|
}
|
|
-
|
|
|
|
- if(flag&SCB_SPEED) {
|
|
|
|
- if(status->speed < battle_config.max_walk_speed)
|
|
|
|
- status->speed = battle_config.max_walk_speed;
|
|
|
|
|
|
+ if(flag&SCB_STR) {
|
|
|
|
+ flag |=SCB_WATK;
|
|
|
|
+ status->rhw.atk += (status->str - b_status->str);
|
|
}
|
|
}
|
|
|
|
+ if(flag|SCB_WATK && status->rhw.atk2 < status->rhw.atk)
|
|
|
|
+ status->rhw.atk2 = status->rhw.atk;
|
|
|
|
+
|
|
if(flag&(SCB_ASPD|SCB_AGI|SCB_DEX)) {
|
|
if(flag&(SCB_ASPD|SCB_AGI|SCB_DEX)) {
|
|
flag|=SCB_ASPD;
|
|
flag|=SCB_ASPD;
|
|
status->amotion = hd->homunculusDB->baseASPD - ((status->agi*4+status->dex)* hd->homunculusDB->baseASPD / 1000);
|
|
status->amotion = hd->homunculusDB->baseASPD - ((status->agi*4+status->dex)* hd->homunculusDB->baseASPD / 1000);
|
|
@@ -2666,26 +2737,28 @@ void status_calc_bl_sub_hom(struct homun_data *hd, unsigned long flag) //[orn]
|
|
}
|
|
}
|
|
|
|
|
|
if(flag&(SCB_AGI|SCB_DSPD)) {
|
|
if(flag&(SCB_AGI|SCB_DSPD)) {
|
|
- //Even though people insist this is too slow, packet data reports this is the actual real equation.
|
|
|
|
skill = 800-status->agi*4;
|
|
skill = 800-status->agi*4;
|
|
status->dmotion = cap_value(skill, 400, 800);
|
|
status->dmotion = cap_value(skill, 400, 800);
|
|
-
|
|
|
|
- if(battle_config.pc_damage_delay_rate != 100)
|
|
|
|
- status->dmotion = status->dmotion*battle_config.pc_damage_delay_rate/100;
|
|
|
|
status->dmotion = status_calc_dmotion(&hd->bl, &hd->sc, b_status->dmotion);
|
|
status->dmotion = status_calc_dmotion(&hd->bl, &hd->sc, b_status->dmotion);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if(flag&(SCB_INT|SCB_MAXSP|SCB_VIT|SCB_MAXHP))
|
|
|
|
+ status_calc_regen(&hd->bl, status, &hd->regen);
|
|
|
|
+
|
|
|
|
+ if(flag&SCB_REGEN)
|
|
|
|
+ status_calc_regen_rate(&hd->bl, &hd->regen, &hd->sc);
|
|
|
|
+
|
|
if (flag == SCB_ALL)
|
|
if (flag == SCB_ALL)
|
|
return; //Refresh is done on invoking function (status_calc_hom)
|
|
return; //Refresh is done on invoking function (status_calc_hom)
|
|
|
|
|
|
- if (flag&(
|
|
|
|
|
|
+ if (hd->master && flag&(
|
|
SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK|
|
|
SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK|
|
|
SCB_HIT|SCB_FLEE|SCB_CRI|SCB_FLEE2|
|
|
SCB_HIT|SCB_FLEE|SCB_CRI|SCB_FLEE2|
|
|
SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|
|
|
SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|
|
|
SCB_BATK|SCB_WATK|SCB_MATK|SCB_ASPD|SCB_SPEED|
|
|
SCB_BATK|SCB_WATK|SCB_MATK|SCB_ASPD|SCB_SPEED|
|
|
SCB_RANGE|SCB_MAXHP|SCB_MAXSP)
|
|
SCB_RANGE|SCB_MAXHP|SCB_MAXSP)
|
|
)
|
|
)
|
|
- clif_hominfo(sd,hd,0);
|
|
|
|
|
|
+ clif_hominfo(hd->master,hd,0);
|
|
}
|
|
}
|
|
|
|
|
|
void status_calc_bl(struct block_list *bl, unsigned long flag)
|
|
void status_calc_bl(struct block_list *bl, unsigned long flag)
|
|
@@ -2855,12 +2928,6 @@ void status_calc_bl(struct block_list *bl, unsigned long flag)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- if(bl->type == BL_HOM) {
|
|
|
|
- //The remaining are handled quite different by homunculus, so use their own function.
|
|
|
|
- status_calc_bl_sub_hom((TBL_HOM*)bl, flag);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
if(flag&SCB_MAXHP) {
|
|
if(flag&SCB_MAXHP) {
|
|
status->max_hp = status_calc_maxhp(bl, sc, b_status->max_hp);
|
|
status->max_hp = status_calc_maxhp(bl, sc, b_status->max_hp);
|
|
if (status->hp > status->max_hp) //FIXME: Should perhaps a status_zap should be issued?
|
|
if (status->hp > status->max_hp) //FIXME: Should perhaps a status_zap should be issued?
|
|
@@ -2883,7 +2950,13 @@ void status_calc_bl(struct block_list *bl, unsigned long flag)
|
|
sc->data[SC_MAGICPOWER].val4 = status->matk_max;
|
|
sc->data[SC_MAGICPOWER].val4 = status->matk_max;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+ if(bl->type == BL_HOM) {
|
|
|
|
+ //The remaining are handled quite different by homunculus, so use their own function.
|
|
|
|
+ status_calc_bl_sub_hom((TBL_HOM*)bl, flag);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
if(flag&SCB_ASPD) {
|
|
if(flag&SCB_ASPD) {
|
|
status->aspd_rate = status_calc_aspd_rate(bl, sc , b_status->aspd_rate);
|
|
status->aspd_rate = status_calc_aspd_rate(bl, sc , b_status->aspd_rate);
|
|
temp = status->aspd_rate*b_status->amotion/1000;
|
|
temp = status->aspd_rate*b_status->amotion/1000;
|
|
@@ -2895,6 +2968,12 @@ void status_calc_bl(struct block_list *bl, unsigned long flag)
|
|
|
|
|
|
if(flag&SCB_DSPD)
|
|
if(flag&SCB_DSPD)
|
|
status->dmotion = status_calc_dmotion(bl, sc, b_status->dmotion);
|
|
status->dmotion = status_calc_dmotion(bl, sc, b_status->dmotion);
|
|
|
|
+
|
|
|
|
+ if(bl->type&BL_REGEN && flag&(SCB_VIT|SCB_MAXHP|SCB_INT|SCB_MAXSP))
|
|
|
|
+ status_calc_regen(bl, status, status_get_regen_data(bl));
|
|
|
|
+
|
|
|
|
+ if(flag&SCB_REGEN && bl->type&BL_REGEN)
|
|
|
|
+ status_calc_regen_rate(bl, status_get_regen_data(bl), sc);
|
|
}
|
|
}
|
|
/*==========================================
|
|
/*==========================================
|
|
* Apply shared stat mods from status changes [DracoRPG]
|
|
* Apply shared stat mods from status changes [DracoRPG]
|
|
@@ -3177,6 +3256,8 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan
|
|
}
|
|
}
|
|
if(sc->data[SC_BLOODLUST].timer!=-1)
|
|
if(sc->data[SC_BLOODLUST].timer!=-1)
|
|
watk += watk * sc->data[SC_BLOODLUST].val2/100;
|
|
watk += watk * sc->data[SC_BLOODLUST].val2/100;
|
|
|
|
+ if(sc->data[SC_FLEET].timer!=-1)
|
|
|
|
+ watk += watk * sc->data[SC_FLEET].val3/100;
|
|
if(sc->data[SC_CURSE].timer!=-1)
|
|
if(sc->data[SC_CURSE].timer!=-1)
|
|
watk -= watk * 25/100;
|
|
watk -= watk * 25/100;
|
|
if(sc->data[SC_STRIPWEAPON].timer!=-1)
|
|
if(sc->data[SC_STRIPWEAPON].timer!=-1)
|
|
@@ -3761,6 +3842,18 @@ int status_get_lv(struct block_list *bl)
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+struct regen_data *status_get_regen_data(struct block_list *bl)
|
|
|
|
+{
|
|
|
|
+ nullpo_retr(NULL, bl);
|
|
|
|
+ switch (bl->type) {
|
|
|
|
+ case BL_PC:
|
|
|
|
+ return &((TBL_PC*)bl)->regen;
|
|
|
|
+ case BL_HOM:
|
|
|
|
+ return &((TBL_HOM*)bl)->regen;
|
|
|
|
+ default:
|
|
|
|
+ return NULL;
|
|
|
|
+ }
|
|
|
|
+}
|
|
struct status_data *status_get_status_data(struct block_list *bl)
|
|
struct status_data *status_get_status_data(struct block_list *bl)
|
|
{
|
|
{
|
|
nullpo_retr(NULL, bl);
|
|
nullpo_retr(NULL, bl);
|
|
@@ -3904,6 +3997,7 @@ int status_get_race2(struct block_list *bl)
|
|
return ((struct pet_data *)bl)->db->race2;
|
|
return ((struct pet_data *)bl)->db->race2;
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
+
|
|
int status_isdead(struct block_list *bl)
|
|
int status_isdead(struct block_list *bl)
|
|
{
|
|
{
|
|
nullpo_retr(0, bl);
|
|
nullpo_retr(0, bl);
|
|
@@ -4997,7 +5091,6 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val
|
|
if (sc->data[SC_ENDURE].timer == -1 || !sc->data[SC_ENDURE].val4)
|
|
if (sc->data[SC_ENDURE].timer == -1 || !sc->data[SC_ENDURE].val4)
|
|
sc_start4(bl, SC_ENDURE, 100,10,0,0,1, tick);
|
|
sc_start4(bl, SC_ENDURE, 100,10,0,0,1, tick);
|
|
//HP healing is performing after the calc_status call.
|
|
//HP healing is performing after the calc_status call.
|
|
- if (sd) sd->canregen_tick = gettick() + 300000;
|
|
|
|
//Val2 holds HP penalty
|
|
//Val2 holds HP penalty
|
|
if (!val4) val4 = skill_get_time2(StatusSkillChangeTable[type],val1);
|
|
if (!val4) val4 = skill_get_time2(StatusSkillChangeTable[type],val1);
|
|
if (!val4) val4 = 10000; //Val4 holds damage interval
|
|
if (!val4) val4 = 10000; //Val4 holds damage interval
|
|
@@ -5183,6 +5276,7 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val
|
|
else
|
|
else
|
|
val2 = val1; //HP Regerenation rate: 200% 200% 300%
|
|
val2 = val1; //HP Regerenation rate: 200% 200% 300%
|
|
val3 = val1; //SP Regeneration Rate: 100% 200% 300%
|
|
val3 = val1; //SP Regeneration Rate: 100% 200% 300%
|
|
|
|
+ //if val4 comes set, this blocks regen rather than increase it.
|
|
break;
|
|
break;
|
|
|
|
|
|
case SC_DEVOTION:
|
|
case SC_DEVOTION:
|
|
@@ -5918,6 +6012,8 @@ int status_change_end( struct block_list* bl , int type,int tid )
|
|
status_set_hp(bl, 100, 0);
|
|
status_set_hp(bl, 100, 0);
|
|
if(sc->data[SC_ENDURE].timer != -1)
|
|
if(sc->data[SC_ENDURE].timer != -1)
|
|
status_change_end(bl, SC_ENDURE, -1);
|
|
status_change_end(bl, SC_ENDURE, -1);
|
|
|
|
+ sc_start4(bl, SC_REGENERATION, 100, 10,0,0,1,
|
|
|
|
+ gettick()+skill_get_time(LK_BERSERK, sc->data[type].val1));
|
|
break;
|
|
break;
|
|
case SC_GRAVITATION:
|
|
case SC_GRAVITATION:
|
|
if (sc->data[type].val3 == BCT_SELF) {
|
|
if (sc->data[type].val3 == BCT_SELF) {
|
|
@@ -6428,8 +6524,6 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
|
|
bl->id, data);
|
|
bl->id, data);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
- else if (sd)
|
|
|
|
- sd->canregen_tick = gettick() + 300000;
|
|
|
|
break;
|
|
break;
|
|
case SC_NOCHAT:
|
|
case SC_NOCHAT:
|
|
if(sd && battle_config.manner_system){
|
|
if(sd && battle_config.manner_system){
|
|
@@ -6668,6 +6762,146 @@ int status_change_clear_buffs (struct block_list *bl, int type)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+//Natural regen related stuff.
|
|
|
|
+static unsigned int natural_heal_prev_tick,natural_heal_diff_tick;
|
|
|
|
+static int status_natural_heal(DBKey key,void * data,va_list app)
|
|
|
|
+{
|
|
|
|
+ struct block_list *bl = (struct block_list*)data;
|
|
|
|
+ struct regen_data *regen;
|
|
|
|
+ struct status_data *status;
|
|
|
|
+ struct status_change *sc;
|
|
|
|
+ struct unit_data *ud;
|
|
|
|
+ struct map_session_data *sd;
|
|
|
|
+ int val,rate,bonus,flag;
|
|
|
|
+
|
|
|
|
+ if (!(bl->type&BL_REGEN))
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ regen = status_get_regen_data(bl);
|
|
|
|
+ if (!regen) return 0;
|
|
|
|
+ status = status_get_status_data(bl);
|
|
|
|
+ sc = status_get_sc(bl);
|
|
|
|
+ if (sc && !sc->count)
|
|
|
|
+ sc = NULL;
|
|
|
|
+ BL_CAST(BL_PC,bl,sd);
|
|
|
|
+
|
|
|
|
+ flag = regen->flag;
|
|
|
|
+ if (flag&RGN_HP && (status->hp >= status->max_hp || regen->state.block&1))
|
|
|
|
+ flag&=~(RGN_HP|RGN_SHP);
|
|
|
|
+ if (flag&RGN_SP && (status->sp >= status->max_sp || regen->state.block&2))
|
|
|
|
+ flag&=~(RGN_SP|RGN_SSP);
|
|
|
|
+
|
|
|
|
+ if (flag && (
|
|
|
|
+ status_isdead(bl) ||
|
|
|
|
+ (sc && sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK))
|
|
|
|
+ ))
|
|
|
|
+ flag=0;
|
|
|
|
+
|
|
|
|
+ if (sd)
|
|
|
|
+ {
|
|
|
|
+ if (sd->hp_loss_value > 0 || sd->sp_loss_value > 0)
|
|
|
|
+ pc_bleeding(sd, natural_heal_diff_tick);
|
|
|
|
+ if (sd->nsshealhp && flag&RGN_HP &&
|
|
|
|
+ pc_spirit_heal_hp(sd, natural_heal_diff_tick))
|
|
|
|
+ flag&=~RGN_HP;
|
|
|
|
+ if (sd->nsshealsp && flag&RGN_SP &&
|
|
|
|
+ pc_spirit_heal_sp(sd, natural_heal_diff_tick))
|
|
|
|
+ flag&=~RGN_SP;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (flag && regen->state.overweight)
|
|
|
|
+ flag=0;
|
|
|
|
+
|
|
|
|
+ ud = unit_bl2ud(bl);
|
|
|
|
+
|
|
|
|
+ if (flag&(RGN_HP|RGN_SHP|RGN_SSP) && ud && ud->walktimer != -1)
|
|
|
|
+ {
|
|
|
|
+ flag&=~(RGN_SHP|RGN_SSP);
|
|
|
|
+ if(!regen->state.walk)
|
|
|
|
+ flag&=~RGN_HP;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (!flag)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ if (flag&(RGN_HP|RGN_SP))
|
|
|
|
+ {
|
|
|
|
+ struct view_data *vd = status_get_viewdata(bl);
|
|
|
|
+ bonus = 0;
|
|
|
|
+ if(vd && vd->dead_sit)
|
|
|
|
+ bonus++;
|
|
|
|
+ if(map_getcell(bl->m,bl->x,bl->y,CELL_CHKREGEN))
|
|
|
|
+ bonus++;
|
|
|
|
+ if(regen->state.gc)
|
|
|
|
+ bonus++;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (flag&RGN_HP)
|
|
|
|
+ {
|
|
|
|
+ rate = natural_heal_diff_tick*(regen->rate.hp+bonus);
|
|
|
|
+ if (ud && ud->walktimer != -1)
|
|
|
|
+ rate/=2;
|
|
|
|
+ regen->tick.hp += rate;
|
|
|
|
+
|
|
|
|
+ if(regen->tick.hp >= battle_config.natural_healhp_interval)
|
|
|
|
+ {
|
|
|
|
+ val = 0;
|
|
|
|
+ do {
|
|
|
|
+ val += regen->hp;
|
|
|
|
+ regen->tick.hp -= battle_config.natural_healhp_interval;
|
|
|
|
+ } while(regen->tick.hp >= battle_config.natural_healhp_interval);
|
|
|
|
+ if (status_heal(bl, val, 0, 1) < val)
|
|
|
|
+ flag&=~RGN_SHP; //full.
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if(flag&RGN_SHP)
|
|
|
|
+ {
|
|
|
|
+ regen->tick.shp += natural_heal_diff_tick * regen->rate.shp;
|
|
|
|
+
|
|
|
|
+ while(regen->tick.shp >= battle_config.natural_heal_skill_interval)
|
|
|
|
+ {
|
|
|
|
+ regen->tick.shp -= battle_config.natural_heal_skill_interval;
|
|
|
|
+ if(status_heal(bl, regen->shp, 0, 3) < regen->shp)
|
|
|
|
+ break; //Full
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if(flag&RGN_SP)
|
|
|
|
+ {
|
|
|
|
+ regen->tick.sp += natural_heal_diff_tick*(regen->rate.sp+bonus);
|
|
|
|
+
|
|
|
|
+ if(regen->tick.sp >= battle_config.natural_healsp_interval)
|
|
|
|
+ {
|
|
|
|
+ val = 0;
|
|
|
|
+ do {
|
|
|
|
+ val += regen->sp;
|
|
|
|
+ regen->tick.sp -= battle_config.natural_healsp_interval;
|
|
|
|
+ } while(regen->tick.sp >= battle_config.natural_healsp_interval);
|
|
|
|
+ if (status_heal(bl, 0, val, 1) < val)
|
|
|
|
+ flag&=~RGN_SSP; //full.
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if(flag&RGN_SSP)
|
|
|
|
+ {
|
|
|
|
+ regen->tick.ssp += natural_heal_diff_tick * regen->rate.ssp;
|
|
|
|
+ while(regen->tick.ssp >= battle_config.natural_heal_skill_interval)
|
|
|
|
+ {
|
|
|
|
+ regen->tick.ssp -= battle_config.natural_heal_skill_interval;
|
|
|
|
+ if(status_heal(bl, 0, regen->ssp, 3) < regen->ssp)
|
|
|
|
+ break; //Full
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return flag;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+//Natural heal main timer.
|
|
|
|
+static int status_natural_heal_timer(int tid,unsigned int tick,int id,int data)
|
|
|
|
+{
|
|
|
|
+ natural_heal_diff_tick = DIFF_TICK(tick,natural_heal_prev_tick);
|
|
|
|
+ map_foreachiddb(status_natural_heal);
|
|
|
|
+ natural_heal_prev_tick = tick;
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
static int status_calc_sigma(void)
|
|
static int status_calc_sigma(void)
|
|
{
|
|
{
|
|
int i,j;
|
|
int i,j;
|
|
@@ -6836,9 +7070,12 @@ int do_init_status(void)
|
|
}
|
|
}
|
|
add_timer_func_list(status_change_timer,"status_change_timer");
|
|
add_timer_func_list(status_change_timer,"status_change_timer");
|
|
add_timer_func_list(kaahi_heal_timer,"kaahi_heal_timer");
|
|
add_timer_func_list(kaahi_heal_timer,"kaahi_heal_timer");
|
|
|
|
+ add_timer_func_list(status_natural_heal_timer,"status_natural_heal_timer");
|
|
initChangeTables();
|
|
initChangeTables();
|
|
initDummyData();
|
|
initDummyData();
|
|
status_readdb();
|
|
status_readdb();
|
|
status_calc_sigma();
|
|
status_calc_sigma();
|
|
|
|
+ natural_heal_prev_tick = gettick();
|
|
|
|
+ add_timer_interval(natural_heal_prev_tick + NATURAL_HEAL_INTERVAL, status_natural_heal_timer, 0, 0, NATURAL_HEAL_INTERVAL);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|