From 97166dfb92d7cbdef8731771c38923cc219a4fc3 Mon Sep 17 00:00:00 2001 From: rud0lp20 Date: Tue, 11 Dec 2012 17:20:44 +0000 Subject: Happy Holidays and Happy 12/12/12 :) Update Elemental summon to its official behavior - Fixed missing skill features of Ventus(bugreport:6792,bugreport:6723,bugreport:6511) - Note: upgrade_svn17014.sql - And other elemental skills are to follow :) Fixed bugreport:6889 updated const.txt where it cause error to some items. Fixed bugreport:6999 where matk damage deals miss atk to plant type targets. Fixed status calculation where it doesn't give accurate result or how official calculation does. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@17014 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/char/int_elemental.c | 34 ++--- src/common/mmo.h | 3 +- src/map/battle.c | 213 +++++++++++----------------- src/map/clif.c | 2 +- src/map/elemental.c | 134 ++++++++++++++++-- src/map/elemental.h | 5 +- src/map/pc.c | 4 + src/map/skill.c | 107 ++++++++++---- src/map/status.c | 358 ++++++++++++++++++++++++----------------------- src/map/status.h | 6 +- src/map/unit.c | 17 +++ 11 files changed, 510 insertions(+), 373 deletions(-) (limited to 'src') diff --git a/src/char/int_elemental.c b/src/char/int_elemental.c index 7c76c4496..3c2f6672d 100644 --- a/src/char/int_elemental.c +++ b/src/char/int_elemental.c @@ -20,9 +20,9 @@ bool mapif_elemental_save(struct s_elemental* ele) { if( ele->elemental_id == 0 ) { // Create new DB entry if( SQL_ERROR == Sql_Query(sql_handle, - "INSERT INTO `elemental` (`char_id`,`class`,`mode`,`hp`,`sp`,`max_hp`,`max_sp`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`life_time`)" - "VALUES ('%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%u')", - ele->char_id, ele->class_, ele->mode, ele->hp, ele->sp, ele->max_hp, ele->max_sp, ele->str, ele->agi, ele->vit, ele->int_, ele->dex, ele->luk, ele->life_time) ) + "INSERT INTO `elemental` (`char_id`,`class`,`mode`,`hp`,`sp`,`max_hp`,`max_sp`,`atk1`,`atk2`,`matk`,`aspd`,`def`,`mdef`,`flee`,`hit`,`life_time`)" + "VALUES ('%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%u')", + ele->char_id, ele->class_, ele->mode, ele->hp, ele->sp, ele->max_hp, ele->max_sp, ele->atk, ele->atk2, ele->matk, ele->amotion, ele->def, ele->mdef, ele->flee, ele->hit, ele->life_time) ) { Sql_ShowDebug(sql_handle); flag = false; @@ -31,10 +31,10 @@ bool mapif_elemental_save(struct s_elemental* ele) { ele->elemental_id = (int)Sql_LastInsertId(sql_handle); } else if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `elemental` SET `char_id` = '%d', `class` = '%d', `mode` = '%d', `hp` = '%d', `sp` = '%d'," - "`max_hp` = '%d', `max_sp` = '%d', `str` = '%d', `agi` = '%d', `vit` = '%d', `int` = '%d', `dex` = '%d'," - "`luk` = '%d', `life_time` = '%u' WHERE `ele_id` = '%d'", - ele->char_id, ele->class_, ele->mode, ele->hp, ele->sp, ele->max_hp, ele->max_sp, ele->str, ele->agi, - ele->vit, ele->int_, ele->dex, ele->luk, ele->life_time, ele->elemental_id) ) + "`max_hp` = '%d', `max_sp` = '%d', `atk1` = '%d', `atk2` = '%d', `matk` = '%d', `aspd` = '%d', `def` = '%d'," + "`mdef` = '%d', `flee` = '%d', `hit` = '%d', `life_time` = '%u' WHERE `ele_id` = '%d'", + ele->char_id, ele->class_, ele->mode, ele->hp, ele->sp, ele->max_hp, ele->max_sp, ele->atk, ele->atk2, + ele->matk, ele->amotion, ele->def, ele->mdef, ele->flee, ele->hit, ele->life_time, ele->elemental_id) ) { // Update DB entry Sql_ShowDebug(sql_handle); flag = false; @@ -49,8 +49,8 @@ bool mapif_elemental_load(int ele_id, int char_id, struct s_elemental *ele) { ele->elemental_id = ele_id; ele->char_id = char_id; - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `class`, `mode`, `hp`, `sp`, `max_hp`, `max_sp`, `str`, `agi`, `vit`, `int`, `dex`," - "`luk`, `life_time` FROM `elemental` WHERE `ele_id` = '%d' AND `char_id` = '%d'", + if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `class`, `mode`, `hp`, `sp`, `max_hp`, `max_sp`, `atk1`, `atk2`, `matk`, `aspd`," + "`def`, `mdef`, `flee`, `hit`, `life_time` FROM `elemental` WHERE `ele_id` = '%d' AND `char_id` = '%d'", ele_id, char_id) ) { Sql_ShowDebug(sql_handle); return false; @@ -67,13 +67,15 @@ bool mapif_elemental_load(int ele_id, int char_id, struct s_elemental *ele) { Sql_GetData(sql_handle, 3, &data, NULL); ele->sp = atoi(data); Sql_GetData(sql_handle, 4, &data, NULL); ele->max_hp = atoi(data); Sql_GetData(sql_handle, 5, &data, NULL); ele->max_sp = atoi(data); - Sql_GetData(sql_handle, 6, &data, NULL); ele->str = atoi(data); - Sql_GetData(sql_handle, 7, &data, NULL); ele->agi = atoi(data); - Sql_GetData(sql_handle, 8, &data, NULL); ele->vit = atoi(data); - Sql_GetData(sql_handle, 9, &data, NULL); ele->int_ = atoi(data); - Sql_GetData(sql_handle, 10, &data, NULL); ele->dex = atoi(data); - Sql_GetData(sql_handle, 11, &data, NULL); ele->luk = atoi(data); - Sql_GetData(sql_handle, 12, &data, NULL); ele->life_time = atoi(data); + Sql_GetData(sql_handle, 6, &data, NULL); ele->atk = atoi(data); + Sql_GetData(sql_handle, 7, &data, NULL); ele->atk2 = atoi(data); + Sql_GetData(sql_handle, 8, &data, NULL); ele->matk = atoi(data); + Sql_GetData(sql_handle, 9, &data, NULL); ele->amotion = atoi(data); + Sql_GetData(sql_handle, 10, &data, NULL); ele->def = atoi(data); + Sql_GetData(sql_handle, 11, &data, NULL); ele->mdef = atoi(data); + Sql_GetData(sql_handle, 12, &data, NULL); ele->flee = atoi(data); + Sql_GetData(sql_handle, 13, &data, NULL); ele->hit = atoi(data); + Sql_GetData(sql_handle, 14, &data, NULL); ele->life_time = atoi(data); Sql_FreeResult(sql_handle); if( save_log ) ShowInfo("Elemental loaded (%d - %d).\n", ele->elemental_id, ele->char_id); diff --git a/src/common/mmo.h b/src/common/mmo.h index 5f6108b33..ad2800010 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -306,7 +306,8 @@ struct s_elemental { int char_id; short class_; int mode; - int hp, sp, max_hp, max_sp, str, agi, vit, int_, dex, luk; + int hp, sp, max_hp, max_sp, matk, atk, atk2; + short hit, flee, amotion, def, mdef; int life_time; }; diff --git a/src/map/battle.c b/src/map/battle.c index 810b44e48..0c3c2c24d 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -2868,10 +2868,10 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo } else skillratio += 300; // Bombs break; - case SO_VARETYR_SPEAR: //Assumed Formula. - skillratio += -100 + 200 * ( sd ? pc_checkskill(sd, SA_LIGHTNINGLOADER) : 1 ); + case SO_VARETYR_SPEAR://ATK [{( Striking Level x 50 ) + ( Varetyr Spear Skill Level x 50 )} x Caster’s Base Level / 100 ] % + skillratio = 50 * skill_lv + ( sd ? pc_checkskill(sd, SO_STRIKING) * 50 : 0 ); if( sc && sc->data[SC_BLAST_OPTION] ) - skillratio += skillratio * sc->data[SC_BLAST_OPTION]->val2 / 100; + skillratio += sd ? sd->status.job_level * 5 : 0; break; // Physical Elemantal Spirits Attack Skills case EL_CIRCLE_OF_FIRE: @@ -3513,6 +3513,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list TBL_PC *sd; // TBL_PC *tsd; + struct status_change *sc, *tsc; struct Damage ad; struct status_data *sstatus = status_get_status_data(src); struct status_data *tstatus = status_get_status_data(target); @@ -3530,6 +3531,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list return ad; } //Initial Values + ad.damage = 1; ad.div_=skill_get_num(skill_num,skill_lv); ad.amotion=skill_get_inf(skill_num)&INF_GROUND_SKILL?0:sstatus->amotion; //Amotion should be 0 for ground skills. ad.dmotion=tstatus->dmotion; @@ -3541,43 +3543,32 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list sd = BL_CAST(BL_PC, src); // tsd = BL_CAST(BL_PC, target); + sc = status_get_sc(src); + tsc = status_get_sc(target); + + //Initialize variables that will be used afterwards + s_ele = skill_get_ele(skill_num, skill_lv); + + if (s_ele == -1){ // pl=-1 : the skill takes the weapon's element + s_ele = sstatus->rhw.ele; + if( sd ){ //Summoning 10 talisman will endow your weapon + ARR_FIND(1, 6, i, sd->talisman[i] >= 10); + if( i < 5 ) s_ele = i; + } + }else if (s_ele == -2) //Use status element + s_ele = status_get_attack_sc_element(src,status_get_sc(src)); + else if( s_ele == -3 ) //Use random element + s_ele = rnd()%ELE_MAX; if( skill_num == SO_PSYCHIC_WAVE ) { - struct status_change *sc = status_get_sc(src); - if( sc && sc->count && ( sc->data[SC_HEATER_OPTION] || sc->data[SC_COOLER_OPTION] || - sc->data[SC_BLAST_OPTION] || sc->data[SC_CURSED_SOIL_OPTION] ) ) { + if( sc && sc->count ) { if( sc->data[SC_HEATER_OPTION] ) s_ele = sc->data[SC_HEATER_OPTION]->val4; else if( sc->data[SC_COOLER_OPTION] ) s_ele = sc->data[SC_COOLER_OPTION]->val4; else if( sc->data[SC_BLAST_OPTION] ) s_ele = sc->data[SC_BLAST_OPTION]->val3; else if( sc->data[SC_CURSED_SOIL_OPTION] ) s_ele = sc->data[SC_CURSED_SOIL_OPTION]->val4; - } else { - //#HALP# I didn't get a clue on how to do this without unnecessary adding a overhead of status_change on every call while this is a per-skill case. - //, - so i duplicated this code. make yourself comfortable to fix if you have any better ideas. - //Initialize variables that will be used afterwards - s_ele = skill_get_ele(skill_num, skill_lv); - - if (s_ele == -1) // pl=-1 : the skill takes the weapon's element - s_ele = sstatus->rhw.ele; - else if (s_ele == -2) //Use status element - s_ele = status_get_attack_sc_element(src,status_get_sc(src)); - else if( s_ele == -3 ) //Use random element - s_ele = rnd()%ELE_MAX; } - } else { - //Initialize variables that will be used afterwards - s_ele = skill_get_ele(skill_num, skill_lv); - - if (s_ele == -1){ // pl=-1 : the skill takes the weapon's element - s_ele = sstatus->rhw.ele; - if( sd ){ //Summoning 10 talisman will endow your weapon - ARR_FIND(1, 6, i, sd->talisman[i] >= 10); - if( i < 5 ) s_ele = i; - } - }else if (s_ele == -2) //Use status element - s_ele = status_get_attack_sc_element(src,status_get_sc(src)); - else if( s_ele == -3 ) //Use random element - s_ele = rnd()%ELE_MAX; } + //Set miscellaneous data that needs be filled if(sd) { sd->state.arrow_atk = 0; @@ -3608,7 +3599,9 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list if (!flag.infdef) //No need to do the math for plants { - +#ifdef RENEWAL + ad.damage = 0; //reinitialize.. +#endif //MATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc #define MATK_RATE( a ) { ad.damage= ad.damage*(a)/100; } //Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage @@ -3695,66 +3688,26 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list if (battle_check_undead(tstatus->race,tstatus->def_ele)) skillratio += 5*skill_lv; break; - case MG_FIREWALL: { - struct status_change *sc = status_get_sc(src); - skillratio -= 50; - if( sc && sc->data[SC_PYROTECHNIC_OPTION] ) - skillratio += skillratio * sc->data[SC_PYROTECHNIC_OPTION]->val3 / 100; - } - break; - case MG_COLDBOLT: { - struct status_change *sc = status_get_sc(src); - if ( sc && sc->count ) { - if ( sc->data[SC_SPELLFIST] && mflag&BF_SHORT ) { - skillratio += (sc->data[SC_SPELLFIST]->val4 * 100) + (sc->data[SC_SPELLFIST]->val2 * 100) - 100;// val4 = used bolt level, val2 = used spellfist level. [Rytech] - ad.div_ = 1;// ad mods, to make it work similar to regular hits [Xazax] - ad.flag = BF_WEAPON|BF_SHORT; - ad.type = 0; - } - if( sc->data[SC_AQUAPLAY_OPTION] ) - skillratio += skillratio * sc->data[SC_AQUAPLAY_OPTION]->val3 / 100; - } - } - break; - case MG_FIREBOLT: { - struct status_change *sc = status_get_sc(src); - if ( sc && sc->count ) { - if ( sc->data[SC_SPELLFIST] && mflag&BF_SHORT ) { - skillratio += (sc->data[SC_SPELLFIST]->val4 * 100) + (sc->data[SC_SPELLFIST]->val2 * 100) - 100; - ad.div_ = 1; - ad.flag = BF_WEAPON|BF_SHORT; - ad.type = 0; - } - if( sc->data[SC_PYROTECHNIC_OPTION] ) - skillratio += skillratio * sc->data[SC_PYROTECHNIC_OPTION]->val3 / 100; - } - } + case MG_FIREWALL: + skillratio -= 50; break; - case MG_LIGHTNINGBOLT: { - struct status_change *sc = status_get_sc(src); - if ( sc && sc->count ) { - if ( sc->data[SC_SPELLFIST] && mflag&BF_SHORT ) { - skillratio += (sc->data[SC_SPELLFIST]->val4 * 100) + (sc->data[SC_SPELLFIST]->val2 * 100) - 100; - ad.div_ = 1; - ad.flag = BF_WEAPON|BF_SHORT; - ad.type = 0; - } - if( sc->data[SC_GUST_OPTION] ) - skillratio += skillratio * sc->data[SC_GUST_OPTION]->val2 / 100; - } + case MG_FIREBOLT: + case MG_COLDBOLT: + case MG_LIGHTNINGBOLT: + if ( sc && sc->data[SC_SPELLFIST] && mflag&BF_SHORT ) { + skillratio += (sc->data[SC_SPELLFIST]->val4 * 100) + (sc->data[SC_SPELLFIST]->val2 * 100) - 100;// val4 = used bolt level, val2 = used spellfist level. [Rytech] + ad.div_ = 1;// ad mods, to make it work similar to regular hits [Xazax] + ad.flag = BF_WEAPON|BF_SHORT; + ad.type = 0; } break; - case MG_THUNDERSTORM: { - struct status_change *sc = status_get_sc(src); + case MG_THUNDERSTORM: /** * in Renewal Thunder Storm boost is 100% (in pre-re, 80%) **/ #ifndef RENEWAL skillratio -= 20; #endif - if( sc && sc->data[SC_GUST_OPTION] ) - skillratio += skillratio * sc->data[SC_GUST_OPTION]->val2 / 100; - } break; case MG_FROSTDIVER: skillratio += 10*skill_lv; @@ -3870,15 +3823,13 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list skillratio += 100 + 100 * skill_lv; RE_LVL_DMOD(100); break; - case WL_JACKFROST: { - struct status_change *tsc = status_get_sc(target); - if( tsc && tsc->data[SC_FREEZING] ){ - skillratio += 900 + 300 * skill_lv; - RE_LVL_DMOD(100); - }else{ - skillratio += 400 + 100 * skill_lv; - RE_LVL_DMOD(150); - } + case WL_JACKFROST: + if( tsc && tsc->data[SC_FREEZING] ){ + skillratio += 900 + 300 * skill_lv; + RE_LVL_DMOD(100); + }else{ + skillratio += 400 + 100 * skill_lv; + RE_LVL_DMOD(150); } break; case WL_DRAINLIFE: @@ -3954,76 +3905,60 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list skillratio += 100 * (sd ? pc_checkskill(sd, WM_REVERBERATION) : 1); RE_LVL_DMOD(100); break; - case SO_FIREWALK: { - struct status_change * sc = status_get_sc(src); + case SO_FIREWALK: skillratio = 300; RE_LVL_DMOD(100); if( sc && sc->data[SC_HEATER_OPTION] ) - skillratio += skillratio * sc->data[SC_HEATER_OPTION]->val3 / 100; - } + skillratio += sc->data[SC_HEATER_OPTION]->val3; break; - case SO_ELECTRICWALK: { - struct status_change * sc = status_get_sc(src); + case SO_ELECTRICWALK: skillratio = 300; RE_LVL_DMOD(100); if( sc && sc->data[SC_BLAST_OPTION] ) - skillratio += skillratio * sc->data[SC_BLAST_OPTION]->val2 / 100; - } + skillratio += sd ? sd->status.job_level / 2 : 0; break; - case SO_EARTHGRAVE: { - struct status_change * sc = status_get_sc(src); + case SO_EARTHGRAVE: skillratio = ( 200 * ( sd ? pc_checkskill(sd, SA_SEISMICWEAPON) : 10 ) + sstatus->int_ * skill_lv ); RE_LVL_DMOD(100); if( sc && sc->data[SC_CURSED_SOIL_OPTION] ) - skillratio += skillratio * sc->data[SC_CURSED_SOIL_OPTION]->val2 / 100; - } + skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val2; break; - case SO_DIAMONDDUST: { - struct status_change * sc = status_get_sc(src); + case SO_DIAMONDDUST: skillratio = ( 200 * ( sd ? pc_checkskill(sd, SA_FROSTWEAPON) : 10 ) + sstatus->int_ * skill_lv ); RE_LVL_DMOD(100); if( sc && sc->data[SC_COOLER_OPTION] ) - skillratio += skillratio * sc->data[SC_COOLER_OPTION]->val3 / 100; - } + skillratio += sc->data[SC_COOLER_OPTION]->val3; break; - case SO_POISON_BUSTER: { - struct status_change * sc = status_get_sc(src); + case SO_POISON_BUSTER: skillratio += 1100 + 300 * skill_lv; if( sc && sc->data[SC_CURSED_SOIL_OPTION] ) - skillratio += skillratio * sc->data[SC_CURSED_SOIL_OPTION]->val2 / 100; - } + skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val2; break; - case SO_PSYCHIC_WAVE: { - struct status_change * sc = status_get_sc(src); + case SO_PSYCHIC_WAVE: skillratio += -100 + skill_lv * 70 + (sstatus->int_ * 3); RE_LVL_DMOD(100); if( sc ){ if( sc->data[SC_HEATER_OPTION] ) - skillratio += skillratio * sc->data[SC_HEATER_OPTION]->val3 / 100; + skillratio += sc->data[SC_HEATER_OPTION]->val3; else if(sc->data[SC_COOLER_OPTION] ) - skillratio += skillratio * sc->data[SC_COOLER_OPTION]->val3 / 100; + skillratio += sc->data[SC_COOLER_OPTION]->val3; else if(sc->data[SC_BLAST_OPTION] ) - skillratio += skillratio * sc->data[SC_BLAST_OPTION]->val2 / 100; + skillratio += sc->data[SC_BLAST_OPTION]->val2; else if(sc->data[SC_CURSED_SOIL_OPTION] ) - skillratio += skillratio * sc->data[SC_CURSED_SOIL_OPTION]->val3 / 100; - } + skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val3; } break; - case SO_VARETYR_SPEAR: { - struct status_change * sc = status_get_sc(src); - skillratio += -100 + ( 100 * ( sd ? pc_checkskill(sd, SA_LIGHTNINGLOADER) : 10 ) + sstatus->int_ * skill_lv ); + case SO_VARETYR_SPEAR: //MATK [{( Endow Tornado skill level x 50 ) + ( Caster’s INT x Varetyr Spear Skill level )} x Caster’s Base Level / 100 ] % + skillratio = status_get_int(src) * skill_lv + ( sd ? pc_checkskill(sd, SA_LIGHTNINGLOADER) * 50 : 0 ); RE_LVL_DMOD(100); if( sc && sc->data[SC_BLAST_OPTION] ) - skillratio += skillratio * sc->data[SC_BLAST_OPTION]->val2 / 100; - } + skillratio += sd ? sd->status.job_level * 5 : 0; break; - case SO_CLOUD_KILL: { - struct status_change * sc = status_get_sc(src); + case SO_CLOUD_KILL: skillratio += -100 + skill_lv * 40; RE_LVL_DMOD(100); if( sc && sc->data[SC_CURSED_SOIL_OPTION] ) - skillratio += skillratio * sc->data[SC_CURSED_SOIL_OPTION]->val2 / 100; - } + skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val2; break; case GN_DEMONIC_FIRE: if( skill_lv > 20) @@ -4136,6 +4071,23 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list if(ad.damage<1) ad.damage=1; + else if(sc){//only applies when hit + // TODO: there is another factor that contribute with the damage and need to be formulated. [malufett] + switch(skill_num){ + case MG_LIGHTNINGBOLT: + case MG_THUNDERSTORM: + case MG_FIREBOLT: + case MG_FIREWALL: + case MG_COLDBOLT: + case MG_FROSTDIVER: + case WZ_EARTHSPIKE: + case WZ_HEAVENDRIVE: + if(sc->data[SC_GUST_OPTION] || sc->data[SC_PETROLOGY_OPTION] + || sc->data[SC_PYROTECHNIC_OPTION] || sc->data[SC_AQUAPLAY_OPTION]) + ad.damage += (6 + sstatus->int_/4) + max(sstatus->dex-10,0)/30; + break; + } + } if (!(nk&NK_NO_ELEFIX)) ad.damage=battle_attr_fix(src, target, ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); @@ -4172,7 +4124,8 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list switch( skill_num ) { /* post-calc modifiers */ case SO_VARETYR_SPEAR: { // Physical damage. struct Damage wd = battle_calc_weapon_attack(src,target,skill_num,skill_lv,mflag); - ad.damage += wd.damage; + if(!flag.infdef && ad.damage > 1) + ad.damage += wd.damage; break; } //case HM_ERASER_CUTTER: diff --git a/src/map/clif.c b/src/map/clif.c index 5ae67d77b..5c2f56d38 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -9251,7 +9251,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) clif_spawn(&sd->ed->bl); clif_elemental_info(sd); clif_elemental_updatestatus(sd,SP_HP); - clif_hpmeter_single(sd->fd,sd->ed->bl.id,sd->ed->battle_status.hp,sd->ed->battle_status.matk_max); + clif_hpmeter_single(sd->fd,sd->ed->bl.id,sd->ed->battle_status.hp,sd->ed->battle_status.max_hp); clif_elemental_updatestatus(sd,SP_SP); status_calc_bl(&sd->ed->bl, SCB_SPEED); //Elemental mimic their master's speed on each map change } diff --git a/src/map/elemental.c b/src/map/elemental.c index 770047138..7bcb9a294 100644 --- a/src/map/elemental.c +++ b/src/map/elemental.c @@ -73,8 +73,56 @@ int elemental_create(struct map_session_data *sd, int class_, unsigned int lifet ele.char_id = sd->status.char_id; ele.class_ = class_; ele.mode = EL_MODE_PASSIVE; // Initial mode - ele.hp = db->status.max_hp; - ele.sp = db->status.max_sp; + i = db->status.size+1; // summon level + + //[(Caster’s Max HP/ 3 ) + (Caster’s INT x 10 )+ (Caster’s Job Level x 20 )] x [(Elemental Summon Level + 2) / 3] + ele.hp = ele.max_hp = (sd->battle_status.max_hp/3 + sd->battle_status.int_*10 + sd->status.job_level) * ((i + 2) / 3) * 5 * pc_checkskill(sd,SO_EL_SYMPATHY) / 100; + //Caster’s Max SP /4 + ele.sp = ele.max_sp = sd->battle_status.max_sp/4 * 5 * pc_checkskill(sd,SO_EL_SYMPATHY) / 100; + //Caster’s [ Max SP / (18 / Elemental Summon Skill Level) 1- 100 ] + ele.atk = (sd->battle_status.max_sp / (18 / i) * 1 - 100) + 25 * pc_checkskill(sd,SO_EL_SYMPATHY); + //Caster’s [ Max SP / (18 / Elemental Summon Skill Level) ] + ele.atk2 = sd->battle_status.max_sp / 18 + 25 * pc_checkskill(sd,SO_EL_SYMPATHY); + //Caster’s HIT + (Caster’s Base Level ) + ele.hit = sd->battle_status.hit + sd->status.base_level; + //[Elemental Summon Skill Level x (Caster’s INT / 2 + Caster’s DEX / 4)] + ele.matk = i * (sd->battle_status.int_ / 2 + sd->battle_status.dex / 4) + 25 * pc_checkskill(sd,SO_EL_SYMPATHY); + //150 + [Caster’s DEX / 10] + [Elemental Summon Skill Level x 3 ] + ele.amotion = 150 + sd->battle_status.dex / 10 + i * 3; + //Caster’s DEF + (Caster’s Base Level / (5 – Elemental Summon Skill Level) + ele.def = sd->battle_status.def + sd->status.base_level / (5-i); + //Caster’s MDEF + (Caster’s INT / (5 - Elemental Summon Skill Level) + ele.mdef = sd->battle_status.mdef + sd->battle_status.int_ / (5-i); + //Caster’s FLEE + (Caster’s Base Level / (5 – Elemental Summon Skill Level) + ele.flee = sd->status.base_level / (5-i); + //Caster’s HIT + (Caster’s Base Level ) + ele.hit = sd->battle_status.hit + sd->status.base_level; + + //per individual bonuses + switch(db->class_){ + case 2114: case 2115: + case 2116: //ATK + (Summon Agni Skill Level x 20) / HIT + (Summon Agni Skill Level x 10) + ele.atk += i * 20; + ele.atk2 += i * 20; + ele.hit += i * 10; + break; + case 2117: case 2118: + case 2119: //MDEF + (Summon Aqua Skill Level x 10) / MATK + (Summon Aqua Skill Level x 20) + ele.mdef += i * 10; + ele.matk += i * 20; + break; + case 2120: case 2121: + case 2122: //FLEE + (Summon Ventus Skill Level x 20) / MATK + (Summon Ventus Skill Level x 10) + ele.flee += i * 20; + ele.matk += i * 10; + break; + case 2123: case 2124: + case 2125: //DEF + (Summon Tera Skill Level x 25) / ATK + (Summon Tera Skill Level x 5) + ele.def += i * 25; + ele.atk += i * 5; + ele.atk2 += i * 5; + break; + } ele.life_time = lifetime; // Request Char Server to create this elemental @@ -93,10 +141,19 @@ int elemental_get_lifetime(struct elemental_data *ed) { } int elemental_save(struct elemental_data *ed) { + ed->elemental.mode = ed->battle_status.mode; ed->elemental.hp = ed->battle_status.hp; ed->elemental.sp = ed->battle_status.sp; + ed->elemental.max_hp = ed->battle_status.max_hp; + ed->elemental.max_sp = ed->battle_status.max_sp; + ed->elemental.atk = ed->battle_status.rhw.atk; + ed->elemental.atk2 = ed->battle_status.rhw.atk2; + ed->elemental.matk = ed->battle_status.matk_min; + ed->elemental.def = ed->battle_status.def; + ed->elemental.mdef = ed->battle_status.mdef; + ed->elemental.flee = ed->battle_status.flee; + ed->elemental.hit = ed->battle_status.hit; ed->elemental.life_time = elemental_get_lifetime(ed); - intif_elemental_save(&ed->elemental); return 1; } @@ -192,9 +249,8 @@ int elemental_data_received(struct s_elemental *ele, bool flag) { map_addiddb(&ed->bl); status_calc_elemental(ed,1); - ed->last_thinktime = gettick(); + ed->last_spdrain_time = ed->last_thinktime = gettick(); ed->summon_timer = INVALID_TIMER; - ed->battle_status.mode = ele->mode = EL_MODE_PASSIVE; // Initial mode. elemental_summon_init(ed); } else { memcpy(&sd->ed->elemental, ele, sizeof(struct s_elemental)); @@ -202,14 +258,13 @@ int elemental_data_received(struct s_elemental *ele, bool flag) { } sd->status.ele_id = ele->elemental_id; - ed->battle_status.mode = ele->mode = EL_MODE_PASSIVE; // Initial mode. if( ed->bl.prev == NULL && sd->bl.prev != NULL ) { map_addblock(&ed->bl); clif_spawn(&ed->bl); clif_elemental_info(sd); clif_elemental_updatestatus(sd,SP_HP); - clif_hpmeter_single(sd->fd,ed->bl.id,ed->battle_status.hp,ed->battle_status.matk_max); + clif_hpmeter_single(sd->fd,ed->bl.id,ed->battle_status.hp,ed->battle_status.max_hp); clif_elemental_updatestatus(sd,SP_SP); } @@ -259,8 +314,6 @@ int elemental_clean_single_effect(struct elemental_data *ed, int skill_num) { break; } } - if( skill_get_unit_id(skill_num,0) ) - skill_clear_unitgroup(&ed->bl); return 1; } @@ -292,9 +345,7 @@ int elemental_clean_effect(struct elemental_data *ed) { status_change_end(&ed->bl, SC_UPHEAVAL, INVALID_TIMER); status_change_end(&ed->bl, SC_CIRCLE_OF_FIRE, INVALID_TIMER); status_change_end(&ed->bl, SC_TIDAL_WEAPON, INVALID_TIMER); - - skill_clear_unitgroup(&ed->bl); - + if( (sd = ed->master) == NULL ) return 0; @@ -328,6 +379,7 @@ int elemental_clean_effect(struct elemental_data *ed) { } int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned int tick) { + struct skill_condition req; short skillnum, skilllv; int i; @@ -377,6 +429,20 @@ int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned return 1; } + + req = elemental_skill_get_requirements(skillnum, skilllv); + + if(req.hp || req.sp){ + struct map_session_data *sd = BL_CAST(BL_PC, battle_get_master(&ed->bl)); + if( sd ){ + if( sd->skillid_old != SO_EL_ACTION && //regardless of remaining HP/SP it can be cast + (status_get_hp(&ed->bl) < req.hp || status_get_sp(&ed->bl) < req.sp) ) + return 1; + else + status_zap(&ed->bl, req.hp, req.sp); + } + } + //Otherwise, just cast the skill. if( skill_get_inf(skillnum) & INF_GROUND_SKILL ) unit_skilluse_pos(&ed->bl, bl->x, bl->y, skillnum, skilllv); @@ -488,6 +554,24 @@ int elemental_skillnotok(int skillid, struct elemental_data *ed) { return skillnotok(skillid, ed->master); } +struct skill_condition elemental_skill_get_requirements(int skill, int lv){ + struct skill_condition req; + int id = skill_get_index(skill); + + memset(&req,0,sizeof(req)); + + if( id == 0 ) // invalid skill id + return req; + + if( lv < 1 || lv > MAX_SKILL_LEVEL ) + return req; + + req.hp = skill_db[id].hp[lv-1]; + req.sp = skill_db[id].sp[lv-1]; + + return req; +} + int elemental_set_target( struct map_session_data *sd, struct block_list *bl ) { struct elemental_data *ed = sd->ed; @@ -551,6 +635,30 @@ static int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_ if( ed->bl.prev == NULL || sd == NULL || sd->bl.prev == NULL ) return 0; + + // Check if caster can sustain the summoned elemental + if( DIFF_TICK(tick,ed->last_spdrain_time) >= 10000 ){// Drain SP every 10 seconds + int sp = 5; + + switch(ed->vd->class_){ + case 2115: case 2118: + case 2121: case 2124: + sp = 8; + break; + case 2116: case 2119: + case 2122: case 2125: + sp = 11; + break; + } + + if( status_get_sp(&sd->bl) < sp ){ // Can't sustain delete it. + elemental_delete(sd->ed,0); + return 0; + } + + status_zap(&sd->bl,0,sp); + ed->last_spdrain_time = tick; + } if( DIFF_TICK(tick,ed->last_thinktime) < MIN_ELETHINKTIME ) return 0; @@ -687,7 +795,7 @@ int read_elementaldb(void) { status->max_sp = atoi(str[5]); status->rhw.range = atoi(str[6]); status->rhw.atk = atoi(str[7]); - status->rhw.atk2 = status->rhw.atk + atoi(str[8]); + status->rhw.atk2 = atoi(str[8]); status->def = atoi(str[9]); status->mdef = atoi(str[10]); status->str = atoi(str[11]); diff --git a/src/map/elemental.h b/src/map/elemental.h index 1f99bcba9..ce8818563 100644 --- a/src/map/elemental.h +++ b/src/map/elemental.h @@ -9,7 +9,7 @@ #define MIN_ELETHINKTIME 100 #define MIN_ELEDISTANCE 2 -#define MAX_ELEDISTANCE 6 +#define MAX_ELEDISTANCE 5 #define EL_MODE_AGGRESSIVE (MD_CANMOVE|MD_AGGRESSIVE|MD_CANATTACK) #define EL_MODE_ASSIST (MD_CANMOVE|MD_ASSIST) @@ -51,7 +51,7 @@ struct elemental_data { int summon_timer; int skill_timer; - unsigned last_thinktime, last_linktime; + unsigned last_thinktime, last_linktime, last_spdrain_time; short min_chase; int target_id, attacked_id; }; @@ -80,6 +80,7 @@ int elemental_set_target( struct map_session_data *sd, struct block_list *bl ); int elemental_clean_single_effect(struct elemental_data *ed, int skill_num); int elemental_clean_effect(struct elemental_data *ed); int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned int tick); +struct skill_condition elemental_skill_get_requirements(int skill, int lv); #define elemental_stop_walking(ed, type) unit_stop_walking(&(ed)->bl, type) #define elemental_stop_attack(ed) unit_stop_attack(&(ed)->bl) diff --git a/src/map/pc.c b/src/map/pc.c index c6c28edcc..a4796e347 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -6343,10 +6343,14 @@ int pc_resethate(struct map_session_data* sd) int pc_skillatk_bonus(struct map_session_data *sd, int skill_num) { int i, bonus = 0; + nullpo_ret(sd); ARR_FIND(0, ARRAYLENGTH(sd->skillatk), i, sd->skillatk[i].id == skill_num); if( i < ARRAYLENGTH(sd->skillatk) ) bonus = sd->skillatk[i].val; + if(sd->sc.data[SC_PYROTECHNIC_OPTION] || sd->sc.data[SC_AQUAPLAY_OPTION]) + bonus += 10; + return bonus; } diff --git a/src/map/skill.c b/src/map/skill.c index ad7749828..1939fe948 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -1467,6 +1467,34 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int } } + if( sd && sd->ed && sc && !status_isdead(bl) && !skillid ){ + struct unit_data *ud = unit_bl2ud(src); + + if( sc->data[SC_WILD_STORM_OPTION] ) + skill = sc->data[SC_WILD_STORM_OPTION]->val2; + else if( sc->data[SC_UPHEAVAL_OPTION] ) + skill = sc->data[SC_WILD_STORM_OPTION]->val2; + else if( sc->data[SC_TROPIC_OPTION] ) + skill = sc->data[SC_TROPIC_OPTION]->val3; + else if( sc->data[SC_CHILLY_AIR_OPTION] ) + skill = sc->data[SC_CHILLY_AIR_OPTION]->val3; + else + skill = 0; + + if ( rnd()%100 < 25 && skill ){ + skill_castend_damage_id(src, bl, skill, 5, tick, 0); + + if (ud) { + rate = skill_delayfix(src, skill, skilllv); + if (DIFF_TICK(ud->canact_tick, tick + rate) < 0){ + ud->canact_tick = tick+rate; + if ( battle_config.display_status_timers ) + clif_status_change(src, SI_ACTIONDELAY, 1, rate, 0, 0, 0); + } + } + } + } + // Autospell when attacking if( sd && !status_isdead(bl) && sd->autospell[0].id ) { @@ -2443,8 +2471,6 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds case EL_ROCK_CRUSHER_ATK: case EL_HURRICANE: case EL_HURRICANE_ATK: - case EL_TYPOON_MIS: - case EL_TYPOON_MIS_ATK: case KO_BAKURETSU: case GN_CRAZYWEED_ATK: dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skillid,-1,5); @@ -4518,7 +4544,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int else { int i = skill_get_splash(skillid,skilllv); clif_skill_nodamage(src,battle_get_master(src),skillid,skilllv,1); - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + clif_skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); if( rnd()%100 < 30 ) map_foreachinrange(skill_area_sub,bl,i,BL_CHAR,src,skillid,skilllv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); else @@ -4554,7 +4580,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int case EL_WIND_SLASH: case EL_STONE_HAMMER: clif_skill_nodamage(src,battle_get_master(src),skillid,skilllv,1); - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + clif_skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); skill_attack(skill_get_type(skillid),src,src,bl,skillid,skilllv,tick,flag); break; @@ -5859,6 +5885,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case MG_STONECURSE: { + int brate = 0; if (tstatus->mode&MD_BOSS) { if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); break; @@ -5866,12 +5893,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in if(status_isimmune(bl) || !tsc) break; + if (sd && sd->sc.data[SC_PETROLOGY_OPTION]) + brate = sd->sc.data[SC_PETROLOGY_OPTION]->val3; + if (tsc->data[SC_STONE]) { status_change_end(bl, SC_STONE, INVALID_TIMER); if (sd) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); break; } - if (sc_start4(bl,SC_STONE,(skilllv*4+20), + if (sc_start4(bl,SC_STONE,(skilllv*4+20)+brate, skilllv, 0, 0, skill_get_time(skillid, skilllv), skill_get_time2(skillid,skilllv))) clif_skill_nodamage(src,bl,skillid,skilllv,1); @@ -8573,10 +8603,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in int elemental_class = skill_get_elemental_type(skillid,skilllv); // Remove previous elemental fisrt. - if( sd->ed && elemental_delete(sd->ed,0) ) { - clif_skill_fail(sd,skillid,0,0); - break; - } + if( sd->ed ) + elemental_delete(sd->ed,0); + // Summoning the new one. if( !elemental_create(sd,elemental_class,skill_get_time(skillid,skilllv)) ) { clif_skill_fail(sd,skillid,0,0); @@ -8589,22 +8618,19 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case SO_EL_CONTROL: if( sd ) { int mode = EL_MODE_PASSIVE; // Standard mode. - if( !sd->ed ) { - clif_skill_fail(sd,skillid,0,0); - break; - } + + if( !sd->ed ) break; + if( skilllv == 4 ) {// At level 4 delete elementals. - if( elemental_delete(sd->ed, 0) ) - clif_skill_fail(sd,skillid,0,0); + elemental_delete(sd->ed, 0); break; } switch( skilllv ) {// Select mode bassed on skill level used. - case 1: mode = EL_MODE_PASSIVE; break; case 2: mode = EL_MODE_ASSIST; break; case 3: mode = EL_MODE_AGGRESSIVE; break; } if( !elemental_change_mode(sd->ed,mode) ) { - clif_skill_fail(sd,skillid,0,0); + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); break; } clif_skill_nodamage(src,bl,skillid,skilllv,1); @@ -8614,8 +8640,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case SO_EL_ACTION: if( sd ) { int duration = 3000; - if( !sd->ed ) - break; + if( !sd->ed ) break; + sd->skillid_old = skillid; elemental_action(sd->ed, bl, tick); clif_skill_nodamage(src,bl,skillid,skilllv,1); switch(sd->ed->db->class_){ @@ -8637,12 +8663,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in struct elemental_data *ed = sd->ed; int s_hp = sd->battle_status.hp * 10 / 100, s_sp = sd->battle_status.sp * 10 / 100; int e_hp, e_sp; - if( !ed ) { - clif_skill_fail(sd,skillid,0,0); - break; - } + + if( !ed ) break; if( !status_charge(&sd->bl,s_hp,s_sp) ) { - clif_skill_fail(sd,skillid,0,0); + clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); break; } e_hp = ed->battle_status.max_hp * 10 / 100; @@ -8761,10 +8785,10 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) { elemental_clean_single_effect(ele, skillid); } else { - clif_skill_nodamage(src,bl,skillid,skilllv,1); - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); - if( skillid == EL_WIND_STEP ) // There aren't telemport, just push to the master. - skill_blown(src,bl,skill_get_blewcount(skillid,skilllv),(map_calc_dir(src,bl->x,bl->y)+4)%8,0); + clif_skill_nodamage(src,src,skillid,skilllv,1); + clif_skill_damage(src, ( skillid == EL_GUST || skillid == EL_BLAST || skillid == EL_WILD_STORM )?src:bl, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + if( skillid == EL_WIND_STEP ) // There aren't teleport, just push the master away. + skill_blown(src,bl,(rnd()%skill_get_blewcount(skillid,skilllv))+1,rand()%8,0); sc_start(src,type2,100,skilllv,skill_get_time(skillid,skilllv)); sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv)); } @@ -8777,7 +8801,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case EL_ZEPHYR: case EL_POWER_OF_GAIA: clif_skill_nodamage(src,src,skillid,skilllv,1); - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); + clif_skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skillid, skilllv, 6); skill_unitsetting(src,skillid,skilllv,bl->x,bl->y,0); break; @@ -13512,6 +13536,25 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, short if( i < 3 ) continue; break; + case SA_SEISMICWEAPON: + if( sc->data[SC_UPHEAVAL_OPTION] && rnd()%100 < 50 ) + continue; + break; + case SA_FLAMELAUNCHER: + case SA_VOLCANO: + if( sc->data[SC_TROPIC_OPTION] && rnd()%100 < 50 ) + continue; + break; + case SA_FROSTWEAPON: + case SA_DELUGE: + if( sc->data[SC_CHILLY_AIR_OPTION] && rnd()%100 < 50 ) + continue; + break; + case SA_LIGHTNINGLOADER: + case SA_VIOLENTGALE: + if( sc && sc->data[SC_WILD_STORM_OPTION] && rnd()%100 < 50 ) + continue; + break; } req.itemid[i] = skill_db[j].itemid[i]; @@ -13632,6 +13675,10 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, short case SO_SUMMON_TERA: req.sp -= req.sp * (5 + 5 * pc_checkskill(sd,SO_EL_SYMPATHY)) / 100; break; + case SO_PSYCHIC_WAVE: + if( sc && sc->data[SC_BLAST_OPTION] ) + req.sp += req.sp * 150 / 100; + break; } return req; @@ -13791,6 +13838,8 @@ int skill_vfcastfix (struct block_list *bl, double time, int skill_id, int skill fixed += sc->data[SC_MANDRAGORA]->val1 * 1000 / 2; if (sc->data[SC_IZAYOI] && (skill_id >= NJ_TOBIDOUGU && skill_id <= NJ_ISSEN)) fixed = 0; + if( sc->data[SC_GUST_OPTION] || sc->data[SC_BLAST_OPTION] || sc->data[SC_WILD_STORM_OPTION] ) + fixed -= 1000; } if( sd && !(skill_get_castnodex(skill_id, skill_lv)&4) ){ diff --git a/src/map/status.c b/src/map/status.c index 7cf76c56e..d9081ede8 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -723,10 +723,10 @@ void initChangeTables(void) { 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_NONE ); - set_sc( EL_BLAST , SC_BLAST_OPTION , SI_BLAST_OPTION , SCB_NONE ); - set_sc( EL_WILD_STORM , SC_WILD_STORM_OPTION , SI_WILD_STORM_OPTION , SCB_NONE ); - set_sc( EL_PETROLOGY , SC_PETROLOGY_OPTION , SI_PETROLOGY_OPTION , SCB_NONE ); + 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_NONE ); set_sc( EL_UPHEAVAL , SC_UPHEAVAL_OPTION , SI_UPHEAVAL_OPTION , SCB_NONE ); set_sc( EL_TIDAL_WEAPON , SC_TIDAL_WEAPON_OPTION , SI_TIDAL_WEAPON_OPTION , SCB_ALL ); @@ -3196,31 +3196,31 @@ int status_calc_elemental_(struct elemental_data *ed, bool first) { if( !sd ) return 0; - status->str = ele->str; - status->agi = ele->agi; - status->vit = ele->vit; - status->dex = ele->dex; - status->int_ = ele->int_; - status->luk = ele->luk; - if( first ) { memcpy(status, &ed->db->status, sizeof(struct status_data)); - status->mode = MD_CANMOVE|MD_CANATTACK; - status->max_hp += 4000 + 500 * pc_checkskill(sd,SO_EL_SYMPATHY); - status->max_sp += 300 + 50 * pc_checkskill(sd,SO_EL_SYMPATHY); - status->hp = status->max_hp; - status->sp = status->max_sp; - status->str += sd->base_status.str * 25 / 100; - status->agi += sd->base_status.agi * 25 / 100; - status->vit += sd->base_status.vit * 25 / 100; - status->int_ += sd->base_status.int_ * 25 / 100; - status->def += sd->base_status.dex * 25 / 100; - status->luk += sd->base_status.luk * 25 / 100; - - status_calc_misc(&ed->bl, status, ed->db->lv); + if( !ele->mode ) + status->mode = EL_MODE_PASSIVE; + else + status->mode = ele->mode; + + status_calc_misc(&ed->bl, status, 0); + + status->max_hp = ele->max_hp; + status->max_sp = ele->max_sp; + status->hp = ele->hp; + status->sp = ele->sp; + status->rhw.atk = ele->atk; + status->rhw.atk2 = ele->atk2; + + status->matk_min += ele->matk; + status->def += ele->def; + status->mdef += ele->mdef; + status->flee = ele->flee; + status->hit = ele->hit; + memcpy(&ed->battle_status,status,sizeof(struct status_data)); } else { - status_calc_misc(&ed->bl, status, ed->db->lv); + status_calc_misc(&ed->bl, status, 0); status_cpy(&ed->battle_status, status); } @@ -3827,9 +3827,6 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) if(status->aspd_rate != 1000) // absolute percentage modifier amotion = ( 200 - (200-amotion/10) * status->aspd_rate / 1000 ) * 10; #endif - //@TODO move FIGHTINGSPIRIT in fix_aspd - if( sc && sc->data[SC_FIGHTINGSPIRIT] && sc->data[SC_FIGHTINGSPIRIT]->val2 ) - amotion -= (sd?pc_checkskill(sd, RK_RUNEMASTERY):10) / 10 * 40; amotion = status_calc_fix_aspd(bl, sc, amotion); status->amotion = cap_value(amotion,((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd),2000); @@ -4202,8 +4199,6 @@ static unsigned short status_calc_vit(struct block_list *bl, struct status_chang vit += sc->data[SC_GLORYWOUNDS]->val1; if(sc->data[SC_TRUESIGHT]) vit += 5; - if(sc->data[SC_STRIPARMOR]) - vit -= vit * sc->data[SC_STRIPARMOR]->val2/100; if(sc->data[SC_MARIONETTE]) vit -= sc->data[SC_MARIONETTE]->val3&0xFF; if(sc->data[SC_MARIONETTE2]) @@ -4219,6 +4214,9 @@ static unsigned short status_calc_vit(struct block_list *bl, struct status_chang if(sc->data[SC_KYOUGAKU]) vit -= sc->data[SC_KYOUGAKU]->val2; + if(sc->data[SC_STRIPARMOR]) + vit -= vit * sc->data[SC_STRIPARMOR]->val2/100; + return (unsigned short)cap_value(vit,0,USHRT_MAX); } @@ -4253,8 +4251,6 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang else int_ >>= 1; } - if(sc->data[SC_STRIPHELM]) - int_ -= int_ * sc->data[SC_STRIPHELM]->val2/100; if(sc->data[SC_NEN]) int_ += sc->data[SC_NEN]->val1; if(sc->data[SC_MARIONETTE]) @@ -4263,8 +4259,6 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang int_ += ((sc->data[SC_MARIONETTE2]->val4)>>16)&0xFF; if(sc->data[SC_MANDRAGORA]) int_ -= 5 + 5 * sc->data[SC_MANDRAGORA]->val1; - if(sc->data[SC__STRIPACCESSORY]) - int_ -= int_ * sc->data[SC__STRIPACCESSORY]->val2 / 100; if(sc->data[SC_COCKTAIL_WARG_BLOOD]) int_ += sc->data[SC_COCKTAIL_WARG_BLOOD]->val1; if(sc->data[SC_INSPIRATION]) @@ -4273,6 +4267,11 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang int_ -= sc->data[SC_STOMACHACHE]->val1; if(sc->data[SC_KYOUGAKU]) int_ -= sc->data[SC_KYOUGAKU]->val2; + + if(sc->data[SC_STRIPHELM]) + int_ -= int_ * sc->data[SC_STRIPHELM]->val2/100; + if(sc->data[SC__STRIPACCESSORY]) + int_ -= int_ * sc->data[SC__STRIPACCESSORY]->val2 / 100; return (unsigned short)cap_value(int_,0,USHRT_MAX); } @@ -4318,8 +4317,6 @@ static unsigned short status_calc_dex(struct block_list *bl, struct status_chang dex -= ((sc->data[SC_MARIONETTE]->val4)>>8)&0xFF; if(sc->data[SC_MARIONETTE2]) dex += ((sc->data[SC_MARIONETTE2]->val4)>>8)&0xFF; - if(sc->data[SC__STRIPACCESSORY]) - dex -= dex * sc->data[SC__STRIPACCESSORY]->val2 / 100; if(sc->data[SC_SIROMA_ICE_TEA]) dex += sc->data[SC_SIROMA_ICE_TEA]->val1; if(sc->data[SC_INSPIRATION]) @@ -4329,6 +4326,9 @@ static unsigned short status_calc_dex(struct block_list *bl, struct status_chang if(sc->data[SC_KYOUGAKU]) dex -= sc->data[SC_KYOUGAKU]->val2; + if(sc->data[SC__STRIPACCESSORY]) + dex -= dex * sc->data[SC__STRIPACCESSORY]->val2 / 100; + return (unsigned short)cap_value(dex,0,USHRT_MAX); } @@ -4361,20 +4361,21 @@ static unsigned short status_calc_luk(struct block_list *bl, struct status_chang luk -= sc->data[SC_MARIONETTE]->val4&0xFF; if(sc->data[SC_MARIONETTE2]) luk += sc->data[SC_MARIONETTE2]->val4&0xFF; - if(sc->data[SC_LAUDARAMUS]) - luk += 4 + sc->data[SC_LAUDARAMUS]->val1; - if(sc->data[SC__STRIPACCESSORY]) - luk -= luk * sc->data[SC__STRIPACCESSORY]->val2 / 100; if(sc->data[SC_PUTTI_TAILS_NOODLES]) luk += sc->data[SC_PUTTI_TAILS_NOODLES]->val1; if(sc->data[SC_INSPIRATION]) luk += sc->data[SC_INSPIRATION]->val3; if(sc->data[SC_STOMACHACHE]) luk -= sc->data[SC_STOMACHACHE]->val1; - if(sc->data[SC_BANANA_BOMB]) - luk -= luk * sc->data[SC_BANANA_BOMB]->val1 / 100; if(sc->data[SC_KYOUGAKU]) luk -= sc->data[SC_KYOUGAKU]->val2; + if(sc->data[SC_LAUDARAMUS]) + luk += 4 + sc->data[SC_LAUDARAMUS]->val1; + + if(sc->data[SC__STRIPACCESSORY]) + luk -= luk * sc->data[SC__STRIPACCESSORY]->val2 / 100; + if(sc->data[SC_BANANA_BOMB]) + luk -= luk * sc->data[SC_BANANA_BOMB]->val1 / 100; return (unsigned short)cap_value(luk,0,USHRT_MAX); } @@ -4388,6 +4389,32 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan batk += sc->data[SC_ATKPOTION]->val1; if(sc->data[SC_BATKFOOD]) batk += sc->data[SC_BATKFOOD]->val1; + if(sc->data[SC_GATLINGFEVER]) + batk += sc->data[SC_GATLINGFEVER]->val3; + if(sc->data[SC_MADNESSCANCEL]) + batk += 100; + if(sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2) + batk += 50; + if(bl->type == BL_ELEM + && ((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 1) + || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 1) + || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 1) + || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 1)) + ) + batk += batk / 5; + if(sc->data[SC_FULL_SWING_K]) + batk += sc->data[SC_FULL_SWING_K]->val1; + if(sc->data[SC_ODINS_POWER]) + batk += 70; + if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ + if(status_get_element(bl) == ELE_WATER) //water type + batk /= 2; + } + if(sc->data[SC_PYROCLASTIC]) + batk += sc->data[SC_PYROCLASTIC]->val2; + if (sc->data[SC_ANGRIFFS_MODUS]) + batk += sc->data[SC_ANGRIFFS_MODUS]->val2; + if(sc->data[SC_INCATKRATE]) batk += batk * sc->data[SC_INCATKRATE]->val1/100; if(sc->data[SC_PROVOKE]) @@ -4407,10 +4434,6 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan // batk -= batk * 25/100; if(sc->data[SC_FLEET]) batk += batk * sc->data[SC_FLEET]->val3/100; - if(sc->data[SC_GATLINGFEVER]) - batk += sc->data[SC_GATLINGFEVER]->val3; - if(sc->data[SC_MADNESSCANCEL]) - batk += 100; if(sc->data[SC__ENERVATION]) batk -= batk * sc->data[SC__ENERVATION]->val2 / 100; if(sc->data[SC_RUSHWINDMILL]) @@ -4421,29 +4444,8 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan batk -= batk * sc->data[SC_MELODYOFSINK]->val3/100; if(sc->data[SC_BEYONDOFWARCRY]) batk += batk * sc->data[SC_BEYONDOFWARCRY]->val3/100; - if(sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2) - batk += 50; - if(bl->type == BL_ELEM - && ((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 1) - || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 1) - || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 1) - || (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 1)) - ) - batk += batk / 5; - if(sc->data[SC_FULL_SWING_K]) - batk += sc->data[SC_FULL_SWING_K]->val1; - if(sc->data[SC_ODINS_POWER]) - batk += 70; if( sc->data[SC_ZANGETSU] ) batk += batk * sc->data[SC_ZANGETSU]->val2 / 100; - if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ - if(status_get_element(bl) == ELE_WATER) //water type - batk /= 2; - } - if(sc->data[SC_PYROCLASTIC]) - batk += sc->data[SC_PYROCLASTIC]->val2; - if (sc->data[SC_ANGRIFFS_MODUS]) - batk += sc->data[SC_ANGRIFFS_MODUS]->val2; return (unsigned short)cap_value(batk,0,USHRT_MAX); } @@ -4461,14 +4463,26 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan watk += sc->data[SC_DRUMBATTLE]->val2; if(sc->data[SC_VOLCANO]) watk += sc->data[SC_VOLCANO]->val2; - 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; - if(sc->data[SC_CONCENTRATION]) - watk += watk * sc->data[SC_CONCENTRATION]->val2/100; - if(sc->data[SC_SKE]) - watk += watk * 3; + if(sc->data[SC_MERC_ATKUP]) + watk += sc->data[SC_MERC_ATKUP]->val2; + if(sc->data[SC_FIGHTINGSPIRIT]) + watk += sc->data[SC_FIGHTINGSPIRIT]->val1; + if(sc->data[SC_STRIKING]) + watk += sc->data[SC_STRIKING]->val2; + if(sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 3) + watk += sc->data[SC_SHIELDSPELL_DEF]->val2; + if(sc->data[SC_INSPIRATION]) + watk += sc->data[SC_INSPIRATION]->val2; + if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 0 ) + watk += (10 + 10 * sc->data[SC_BANDING]->val1) * (sc->data[SC_BANDING]->val2); + if( sc->data[SC_TROPIC_OPTION] ) + watk += sc->data[SC_TROPIC_OPTION]->val2; + if( sc->data[SC_HEATER_OPTION] ) + watk += sc->data[SC_HEATER_OPTION]->val2; + if( sc->data[SC_WATER_BARRIER] ) + watk -= sc->data[SC_WATER_BARRIER]->val3; + if( sc->data[SC_PYROTECHNIC_OPTION] ) + watk += sc->data[SC_PYROTECHNIC_OPTION]->val2; if(sc->data[SC_NIBELUNGEN]) { if (bl->type != BL_PC) watk += sc->data[SC_NIBELUNGEN]->val2; @@ -4481,6 +4495,15 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan watk += sc->data[SC_NIBELUNGEN]->val2; } } + + 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; + if(sc->data[SC_CONCENTRATION]) + watk += watk * sc->data[SC_CONCENTRATION]->val2/100; + if(sc->data[SC_SKE]) + watk += watk * 3; if(sc->data[SC__ENERVATION]) watk -= watk * sc->data[SC__ENERVATION]->val2 / 100; if(sc->data[SC_FLEET]) @@ -4489,28 +4512,8 @@ static unsigned short status_calc_watk(struct block_list *bl, struct status_chan watk -= watk * 25/100; if(sc->data[SC_STRIPWEAPON]) watk -= watk * sc->data[SC_STRIPWEAPON]->val2/100; - if(sc->data[SC_MERC_ATKUP]) - watk += sc->data[SC_MERC_ATKUP]->val2; - if(sc->data[SC_FIGHTINGSPIRIT]) - watk += sc->data[SC_FIGHTINGSPIRIT]->val1; if(sc->data[SC__ENERVATION]) watk -= watk * sc->data[SC__ENERVATION]->val2 / 100; - if(sc->data[SC_STRIKING]) - watk += sc->data[SC_STRIKING]->val2; - if(sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 3) - watk += sc->data[SC_SHIELDSPELL_DEF]->val2; - if(sc->data[SC_INSPIRATION]) - watk += sc->data[SC_INSPIRATION]->val2; - if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 0 ) - watk += (10 + 10 * sc->data[SC_BANDING]->val1) * (sc->data[SC_BANDING]->val2); - if( sc->data[SC_TROPIC_OPTION] ) - watk += sc->data[SC_TROPIC_OPTION]->val2; - if( sc->data[SC_HEATER_OPTION] ) - watk += sc->data[SC_HEATER_OPTION]->val2; - if( sc->data[SC_WATER_BARRIER] ) - watk -= sc->data[SC_WATER_BARRIER]->val3; - if( sc->data[SC_PYROTECHNIC_OPTION] ) - watk += sc->data[SC_PYROTECHNIC_OPTION]->val2; if((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 2) || (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 2) || (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 2) @@ -4615,15 +4618,16 @@ static signed short status_calc_critical(struct block_list *bl, struct status_ch critical += critical; if(sc->data[SC_STRIKING]) critical += sc->data[SC_STRIKING]->val1; - if(sc->data[SC__INVISIBILITY]) - critical += critical * sc->data[SC__INVISIBILITY]->val3 / 100; - if(sc->data[SC__UNLUCKY]) - critical -= critical * sc->data[SC__UNLUCKY]->val2 / 100; #ifdef RENEWAL if (sc->data[SC_SPEARQUICKEN]) critical += 3*sc->data[SC_SPEARQUICKEN]->val1*10; #endif + if(sc->data[SC__INVISIBILITY]) + critical += critical * sc->data[SC__INVISIBILITY]->val3 / 100; + if(sc->data[SC__UNLUCKY]) + critical -= critical * sc->data[SC__UNLUCKY]->val2 / 100; + return (short)cap_value(critical,10,SHRT_MAX); } @@ -4643,22 +4647,23 @@ static signed short status_calc_hit(struct block_list *bl, struct status_change hit += sc->data[SC_HUMMING]->val2; if(sc->data[SC_CONCENTRATION]) hit += sc->data[SC_CONCENTRATION]->val3; - if(sc->data[SC_INCHITRATE]) - hit += hit * sc->data[SC_INCHITRATE]->val1/100; - if(sc->data[SC_BLIND]) - hit -= hit * 25/100; + if(sc->data[SC_INSPIRATION]) + hit += 5 * sc->data[SC_INSPIRATION]->val1; if(sc->data[SC_ADJUSTMENT]) hit -= 30; if(sc->data[SC_INCREASING]) hit += 20; // RockmanEXE; changed based on updated [Reddozen] if(sc->data[SC_MERC_HITUP]) hit += sc->data[SC_MERC_HITUP]->val2; + + if(sc->data[SC_INCHITRATE]) + hit += hit * sc->data[SC_INCHITRATE]->val1/100; + if(sc->data[SC_BLIND]) + hit -= hit * 25/100; if(sc->data[SC__GROOMY]) hit -= hit * sc->data[SC__GROOMY]->val3 / 100; if(sc->data[SC_FEAR]) hit -= hit * 20 / 100; - if(sc->data[SC_INSPIRATION]) - hit += 5 * sc->data[SC_INSPIRATION]->val1; if (sc->data[SC_ASH]) hit /= 2; @@ -4686,30 +4691,45 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change flee += sc->data[SC_WHISTLE]->val2; if(sc->data[SC_WINDWALK]) flee += sc->data[SC_WINDWALK]->val2; - if(sc->data[SC_INCFLEERATE]) - flee += flee * sc->data[SC_INCFLEERATE]->val1/100; if(sc->data[SC_VIOLENTGALE]) flee += sc->data[SC_VIOLENTGALE]->val2; if(sc->data[SC_MOON_COMFORT]) //SG skill [Komurka] flee += sc->data[SC_MOON_COMFORT]->val2; if(sc->data[SC_CLOSECONFINE]) flee += 10; - if(sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1) - flee -= flee * 50/100; - if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) - flee -= flee * 50/100; - if(sc->data[SC_BLIND]) - flee -= flee * 25/100; + if (sc->data[SC_ANGRIFFS_MODUS]) + flee -= sc->data[SC_ANGRIFFS_MODUS]->val3; + if (sc->data[SC_OVERED_BOOST]) + flee = max(flee,sc->data[SC_OVERED_BOOST]->val2); if(sc->data[SC_ADJUSTMENT]) flee += 30; - if(sc->data[SC_GATLINGFEVER]) - flee -= sc->data[SC_GATLINGFEVER]->val4; if(sc->data[SC_SPEED]) flee += 10 + sc->data[SC_SPEED]->val1 * 10; + if(sc->data[SC_GATLINGFEVER]) + flee -= sc->data[SC_GATLINGFEVER]->val4; if(sc->data[SC_PARTYFLEE]) flee += sc->data[SC_PARTYFLEE]->val1 * 10; if(sc->data[SC_MERC_FLEEUP]) flee += sc->data[SC_MERC_FLEEUP]->val2; + if( sc->data[SC_HALLUCINATIONWALK] ) + flee += sc->data[SC_HALLUCINATIONWALK]->val2; + if( sc->data[SC_WATER_BARRIER] ) + flee -= sc->data[SC_WATER_BARRIER]->val3; + if( sc->data[SC_MARSHOFABYSS] ) + flee -= (9 * sc->data[SC_MARSHOFABYSS]->val3 / 10 + sc->data[SC_MARSHOFABYSS]->val2 / 10) * (bl->type == BL_MOB ? 2 : 1); +#ifdef RENEWAL + if( sc->data[SC_SPEARQUICKEN] ) + flee += 2 * sc->data[SC_SPEARQUICKEN]->val1; +#endif + + if(sc->data[SC_INCFLEERATE]) + flee += flee * sc->data[SC_INCFLEERATE]->val1/100; + if(sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1) + flee -= flee * 50/100; + if (sc->data[SC_BERSERK] || sc->data[SC__BLOODYLUST]) + flee -= flee * 50/100; + if(sc->data[SC_BLIND]) + flee -= flee * 25/100; if(sc->data[SC_FEAR]) flee -= flee * 20 / 100; if(sc->data[SC_PARALYSE]) @@ -4720,26 +4740,12 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change flee -= flee * sc->data[SC__LAZINESS]->val3 / 100; if( sc->data[SC_GLOOMYDAY] ) flee -= flee * sc->data[SC_GLOOMYDAY]->val2 / 100; - if( sc->data[SC_HALLUCINATIONWALK] ) - flee += sc->data[SC_HALLUCINATIONWALK]->val2; if( sc->data[SC_SATURDAYNIGHTFEVER] ) flee -= flee * (40 + 10 * sc->data[SC_SATURDAYNIGHTFEVER]->val1) / 100; - if( sc->data[SC_WATER_BARRIER] ) - flee -= sc->data[SC_WATER_BARRIER]->val3; if( sc->data[SC_WIND_STEP_OPTION] ) flee += flee * sc->data[SC_WIND_STEP_OPTION]->val2 / 100; if( sc->data[SC_ZEPHYR] ) flee += flee * sc->data[SC_ZEPHYR]->val2 / 100; - if( sc->data[SC_MARSHOFABYSS] ) - flee -= (9 * sc->data[SC_MARSHOFABYSS]->val3 / 10 + sc->data[SC_MARSHOFABYSS]->val2 / 10) * (bl->type == BL_MOB ? 2 : 1); -#ifdef RENEWAL - if( sc->data[SC_SPEARQUICKEN] ) - flee += 2 * sc->data[SC_SPEARQUICKEN]->val1; -#endif - if (sc->data[SC_ANGRIFFS_MODUS]) - flee -= sc->data[SC_ANGRIFFS_MODUS]->val3; - if (sc->data[SC_OVERED_BOOST]) - flee = max(flee,sc->data[SC_OVERED_BOOST]->val2); if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ //mob if(status_get_element(bl) == ELE_WATER) //water type flee /= 2; @@ -4788,6 +4794,14 @@ static defType status_calc_def(struct block_list *bl, struct status_change *sc, def += sc->data[SC_DEFENCE]->val2 ; if(sc->data[SC_INCDEFRATE]) def += def * sc->data[SC_INCDEFRATE]->val1/100; + if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2) + def += 50; + if(sc->data[SC_ODINS_POWER]) + def -= 20; + if( sc->data[SC_ANGRIFFS_MODUS] ) + def -= 30 + 20 * sc->data[SC_ANGRIFFS_MODUS]->val1; + if(sc->data[SC_STONEHARDSKIN])// Final DEF increase divided by 10 since were using classic (pre-renewal) mechanics. [Rytech] + def += sc->data[SC_STONEHARDSKIN]->val1; if(sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) def >>=1; if(sc->data[SC_FREEZE]) @@ -4808,8 +4822,6 @@ static defType status_calc_def(struct block_list *bl, struct status_change *sc, def -= def * sc->data[SC_STRIPSHIELD]->val2/100; if (sc->data[SC_FLING]) def -= def * (sc->data[SC_FLING]->val2)/100; - if(sc->data[SC_STONEHARDSKIN])// Final DEF increase divided by 10 since were using classic (pre-renewal) mechanics. [Rytech] - def += sc->data[SC_STONEHARDSKIN]->val1; if( sc->data[SC_FREEZING] ) def -= def * 10 / 100; if( sc->data[SC_MARSHOFABYSS] ) @@ -4828,12 +4840,6 @@ static defType status_calc_def(struct block_list *bl, struct status_change *sc, def += def * sc->data[SC_POWER_OF_GAIA]->val2 / 100; if( sc->data[SC_PRESTIGE] ) def += def * sc->data[SC_PRESTIGE]->val1 / 100; - if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2) - def += 50; - if(sc->data[SC_ODINS_POWER]) - def -= 20; - if( sc->data[SC_ANGRIFFS_MODUS] ) - def -= 30 + 20 * sc->data[SC_ANGRIFFS_MODUS]->val1; if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ if(status_get_race(bl)==RC_PLANT) def /= 2; @@ -4857,6 +4863,10 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change return 0; if(sc->data[SC_SUN_COMFORT]) def2 += sc->data[SC_SUN_COMFORT]->val2; + if( sc->data[SC_SHIELDSPELL_REF] && sc->data[SC_SHIELDSPELL_REF]->val1 == 1 ) + def2 += sc->data[SC_SHIELDSPELL_REF]->val2; + if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 0 ) + def2 += (5 + sc->data[SC_BANDING]->val1) * (sc->data[SC_BANDING]->val2); if(sc->data[SC_ANGELUS]) #ifdef RENEWAL //in renewal only the VIT stat bonus is boosted by angelus @@ -4889,10 +4899,6 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change def2 -= def2 * ( 14 * sc->data[SC_ANALYZE]->val1 ) / 100; if( sc->data[SC_ECHOSONG] ) def2 += def2 * sc->data[SC_ECHOSONG]->val2/100; - if( sc->data[SC_SHIELDSPELL_REF] && sc->data[SC_SHIELDSPELL_REF]->val1 == 1 ) - def2 += sc->data[SC_SHIELDSPELL_REF]->val2; - if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 0 ) - def2 += (5 + sc->data[SC_BANDING]->val1) * (sc->data[SC_BANDING]->val2); if( sc->data[SC_GT_REVITALIZE] && sc->data[SC_GT_REVITALIZE]->val4) def2 += def2 * sc->data[SC_GT_REVITALIZE]->val4 / 100; if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ @@ -4927,20 +4933,26 @@ static defType status_calc_mdef(struct block_list *bl, struct status_change *sc, if(sc->data[SC_ARMORCHANGE]) mdef += sc->data[SC_ARMORCHANGE]->val3; - if(sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) - mdef += 25*mdef/100; - if(sc->data[SC_FREEZE]) - mdef += 25*mdef/100; + if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 3) + mdef += 50; if(sc->data[SC_ENDURE])// It has been confirmed that eddga card grants 1 MDEF, not 0, not 10, but 1. mdef += (sc->data[SC_ENDURE]->val4 == 0) ? sc->data[SC_ENDURE]->val1 : 1; if(sc->data[SC_CONCENTRATION]) mdef += 1; //Skill info says it adds a fixed 1 Mdef point. + if(sc->data[SC_STONEHARDSKIN])// Final MDEF increase divided by 10 since were using classic (pre-renewal) mechanics. [Rytech] + mdef += sc->data[SC_STONEHARDSKIN]->val1; + if(sc->data[SC_WATER_BARRIER]) + mdef += sc->data[SC_WATER_BARRIER]->val2; + #ifdef RENEWAL if(sc->data[SC_ASSUMPTIO]) mdef *= 2; #endif - if(sc->data[SC_STONEHARDSKIN])// Final MDEF increase divided by 10 since were using classic (pre-renewal) mechanics. [Rytech] - mdef += sc->data[SC_STONEHARDSKIN]->val1; + + if(sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) + mdef += 25*mdef/100; + if(sc->data[SC_FREEZE]) + mdef += 25*mdef/100; if( sc->data[SC_MARSHOFABYSS] ) mdef -= mdef * ( 6 + 6 * sc->data[SC_MARSHOFABYSS]->val3/10 + (bl->type == BL_MOB ? 5 : 3) * sc->data[SC_MARSHOFABYSS]->val2/36 ) / 100; if(sc->data[SC_ANALYZE]) @@ -4949,12 +4961,8 @@ static defType status_calc_mdef(struct block_list *bl, struct status_change *sc, mdef += mdef * sc->data[SC_SYMPHONYOFLOVER]->val2 / 100; if(sc->data[SC_GT_CHANGE] && sc->data[SC_GT_CHANGE]->val4) mdef -= mdef * sc->data[SC_GT_CHANGE]->val4 / 100; - if(sc->data[SC_WATER_BARRIER]) - mdef += sc->data[SC_WATER_BARRIER]->val2; if (sc->data[SC_ODINS_POWER]) mdef -= 20 * sc->data[SC_ODINS_POWER]->val1; - if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 3) - mdef += 50; return (defType)cap_value(mdef,DEFTYPE_MIN,DEFTYPE_MAX); } @@ -5295,20 +5303,16 @@ static short status_calc_fix_aspd(struct block_list *bl, struct status_change *s return cap_value(aspd, 0, 2000); if (!sc->data[SC_QUAGMIRE]) { - if (sc->data[SC_FIGHTINGSPIRIT]) - aspd += sc->data[SC_FIGHTINGSPIRIT]->val3; - if ((sc->data[SC_GUST_OPTION] - || sc->data[SC_BLAST_OPTION] - || sc->data[SC_WILD_STORM_OPTION]) - ) - aspd -= 50; // ventus passive = +5 ASPD - if (sc->data[SC_OVERED_BOOST]){ - aspd = 2000 - sc->data[SC_OVERED_BOOST]->val3*10; - } -// if(sc->data[SC_FIGHTINGSPIRIT] && sc->data[SC_FIGHTINGSPIRIT]->val2 ) -// aspd -= (sd?pc_checkskill(sd, RK_RUNEMASTERY):10) * 4; + if (sc->data[SC_OVERED_BOOST]) + aspd = 2000 - sc->data[SC_OVERED_BOOST]->val3*10; } + if ((sc->data[SC_GUST_OPTION] || sc->data[SC_BLAST_OPTION] + || sc->data[SC_WILD_STORM_OPTION])) + aspd -= 50; // +5 ASPD + if( sc && sc->data[SC_FIGHTINGSPIRIT] && sc->data[SC_FIGHTINGSPIRIT]->val2 ) + aspd -= (bl->type==BL_PC?pc_checkskill((TBL_PC *)bl, RK_RUNEMASTERY):10) / 10 * 40; + return cap_value(aspd, 0, 2000); // will be recap for proper bl anyway } @@ -5485,6 +5489,12 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang maxhp += maxhp * 2; if(sc->data[SC_MARIONETTE]) maxhp -= 1000; + if(sc->data[SC_SOLID_SKIN_OPTION]) + maxhp += 2000;// Fix amount. + if(sc->data[SC_POWER_OF_GAIA]) + maxhp += 3000; + if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2) + maxhp += 500; if(sc->data[SC_MERC_HPUP]) maxhp += maxhp * sc->data[SC_MERC_HPUP]->val2/100; @@ -5509,18 +5519,14 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang maxhp += maxhp * (2 * sc->data[SC_GT_REVITALIZE]->val1) / 100; if(sc->data[SC_MUSTLE_M]) maxhp += maxhp * sc->data[SC_MUSTLE_M]->val1/100; - if(sc->data[SC_SOLID_SKIN_OPTION]) - maxhp += 2000;// Fix amount. - if(sc->data[SC_POWER_OF_GAIA]) - maxhp += 3000; if(sc->data[SC_MYSTERIOUS_POWDER]) maxhp -= sc->data[SC_MYSTERIOUS_POWDER]->val1 / 100; - if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2) - maxhp += 500; + if(sc->data[SC_PETROLOGY_OPTION]) + maxhp += maxhp * sc->data[SC_PETROLOGY_OPTION]->val2 / 100; if (sc->data[SC_ANGRIFFS_MODUS]) maxhp += maxhp * 5 * sc->data[SC_ANGRIFFS_MODUS]->val1 /100; if (sc->data[SC_GOLDENE_FERSE]) - maxhp += (maxhp * sc->data[SC_GOLDENE_FERSE]->val2) / 100; + maxhp += maxhp * sc->data[SC_GOLDENE_FERSE]->val2 / 100; return cap_value(maxhp,1,UINT_MAX); } @@ -8328,8 +8334,6 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val } break; case SC_PYROTECHNIC_OPTION: - val2 = 60; // Watk TODO: Renewal (Atk2) - val3 = 11; // % Increase damage. val_flag |= 1|2|4; break; case SC_HEATER_OPTION: @@ -8343,8 +8347,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val3 = MG_FIREBOLT; break; case SC_AQUAPLAY_OPTION: - val2 = 40; // Matk. TODO: Renewal (Matk1) - val3 = 33; // % Increase effects. + val2 = 40; val_flag |= 1|2|4; break; case SC_COOLER_OPTION: @@ -8359,15 +8362,14 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val val_flag |= 1|2; break; case SC_GUST_OPTION: - val2 = 33; val_flag |= 1|2; break; case SC_WIND_STEP_OPTION: val2 = 50; // % Increase speed and flee. break; case SC_BLAST_OPTION: - val2 = 33; - val3 = 4; + val2 = 20; + val3 = ELE_WIND; val_flag |= 1|2|4; break; case SC_WILD_STORM_OPTION: @@ -8376,7 +8378,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val break; case SC_PETROLOGY_OPTION: val2 = 5; - val3 = 33; + val3 = 50; val_flag |= 1|2|4; break; case SC_CURSED_SOIL_OPTION: diff --git a/src/map/status.h b/src/map/status.h index 82bd7ba8a..9871128b0 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -1554,11 +1554,11 @@ enum scb_flag }; //Define to determine who gets HP/SP consumed on doing skills/etc. [Skotlex] -#define BL_CONSUME (BL_PC|BL_HOM|BL_MER) +#define BL_CONSUME (BL_PC|BL_HOM|BL_MER|BL_ELEM) //Define to determine who has regen -#define BL_REGEN (BL_PC|BL_HOM|BL_MER) +#define BL_REGEN (BL_PC|BL_HOM|BL_MER|BL_ELEM) //Define to determine who will receive a clif_status_change packet for effects that require one to display correctly -#define BL_SCEFFECT (BL_PC|BL_HOM|BL_MER|BL_MOB) +#define BL_SCEFFECT (BL_PC|BL_HOM|BL_MER|BL_MOB|BL_ELEM) //Basic damage info of a weapon //Required because players have two of these, one in status_data diff --git a/src/map/unit.c b/src/map/unit.c index a49385071..e3a371b74 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -1250,6 +1250,23 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh if (sc && sc->data[SC_WUGDASH]) casttime = -1; break; + case EL_WIND_SLASH: + case EL_HURRICANE: + case EL_TYPOON_MIS: + case EL_STONE_HAMMER: + case EL_ROCK_CRUSHER: + case EL_STONE_RAIN: + case EL_ICE_NEEDLE: + case EL_WATER_SCREW: + case EL_TIDAL_WEAPON: + if( src->type == BL_ELEM ){ + sd = BL_CAST(BL_PC, battle_get_master(src)); + if( sd && sd->skillid_old == SO_EL_ACTION ){ + casttime = -1; + sd->skillid_old = 0; + } + } + break; } // moved here to prevent Suffragium from ending if skill fails -- cgit v1.2.3-70-g09d2