-upd homonS skills with Yommy leak infos, thx !

-fix summon_legion multiple spawn exploit and set summon stats.
-fix MH_LIGHT_OF_REGENE being broken since eleanor upd (typo)

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@17213 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
glighta 2013-03-26 12:01:07 +00:00
parent 9a1076b7e9
commit dad4da7241
6 changed files with 149 additions and 113 deletions

View File

@ -1730,45 +1730,45 @@
//-- MH_OVERED_BOOST //-- MH_OVERED_BOOST
8023,800:700:600:500:400,0,0,30000:45000:60000:75000:90000,0,0,200:300:400:500:600 8023,800:700:600:500:400,0,0,30000:45000:60000:75000:90000,0,0,200:300:400:500:600
//-- MH_ERASER_CUTTER //-- MH_ERASER_CUTTER
8024,1000:1500:2000:2500:3000,0,0,0,0,0,-1 8024,1000:1500:2000:2500:3000,2000,0,0,0,0,-1
//-- MH_XENO_SLASHER //-- MH_XENO_SLASHER
8025,1500:2500:3500:4500:5500,0,0,500,0,0,500 8025,1500:2500:3500:4500:5500,0,0,500,120000,0,500
//-- MH_SILENT_BREEZE //-- MH_SILENT_BREEZE
8026,2000,0,0,9000:12000:15000:18000:21000,0,0,1000:800:600:400:200 8026,2000,0,0,9000:12000:15000:18000:21000,0,0,1000:800:600:400:200
//-- MH_STYLE_CHANGE //-- MH_STYLE_CHANGE
8027,0,0,0,0,0,0,0 8027,0,1000,0,0,0,0,500
//-- MH_SONIC_CRAW //-- MH_SONIC_CRAW
//8028,0,0,0,0,0,0,0 //8028,0,0,0,0,0,0,0
//-- MH_SILVERVEIN_RUSH //-- MH_SILVERVEIN_RUSH
//8029,0,0,0,0,0,0,0 8029,0,0,0,5000,0,2000,0
//-- MH_MIDNIGHT_FRENZY //-- MH_MIDNIGHT_FRENZY
//8030,0,0,0,0,0,0,0 8030,0,0,0,10000,0,2000,0
//-- MH_STAHL_HORN //-- MH_STAHL_HORN
8031,800:600:400:200:0,0,0,5000,0,0,200:400:600:800:1000 8031,800:600:400:200:0,3000,0,5000,0,0,200:400:600:800:1000
//-- MH_GOLDENE_FERSE //-- MH_GOLDENE_FERSE
8032,1000:1200:1400:1600:1800,0,0,30000:45000:60000:75000:90000,0,0,-1 8032,1000:1200:1400:1600:1800,0,0,30000:45000:60000:75000:90000,0,0,-1
//-- MH_STEINWAND //-- MH_STEINWAND
8033,1000,0,0,30000:45000:60000:75000:90000,0,0,-1 8033,1000,0,0,30000:45000:60000:75000:90000,0,0,-1
//-- MH_HEILIGE_STANGE //-- MH_HEILIGE_STANGE
8034,200:400:600:800:1000,0,0,0,0,0,1800:1600:1400:1200:1000 8034,200:400:600:800:1000,5000,0,0,0,0,1800:1600:1400:1200:1000
//-- MH_ANGRIFFS_MODUS //-- MH_ANGRIFFS_MODUS
8035,200:400:600:800:1000,0,0,30000:45000:60000:75000:90000,0,0,-1 8035,200:400:600:800:1000,0,0,30000:45000:60000:75000:90000,0,0,-1
//-- MH_TINDER_BREAKER //-- MH_TINDER_BREAKER
8036,0,0,0,5000,0,0,0 8036,1000,0,0,5000,0,0,0
//-- MH_CBC //-- MH_CBC
8037,0,0,0,0,0,0,0 8037,0,0,0,0,0,0,0
//-- MH_EQC //-- MH_EQC
8038,0,0,0,0,0,0,0 8038,0,1000,0,0,0,0,0
//-- MH_MAGMA_FLOW //-- MH_MAGMA_FLOW
8039,2000:2500:3000:3500:4000,0,0,30000:45000:60000:75000:90000,0,0,2000:1500:1000:500:-1 8039,2000:2500:3000:3500:4000,1000,0,30000:45000:60000:75000:90000,0,0,2000:1500:1000:500:-1
//-- MH_GRANITIC_ARMOR //-- MH_GRANITIC_ARMOR
8040,6000:5500:5000:4500:4000,0,0,60000,0,0,1000 8040,5000:4500:4000:3500:3000,1000,0,60000,0,0,1000
//-- MH_LAVA_SLIDE //-- MH_LAVA_SLIDE
8041,6000:5500:5000:4500:4000,0,0,12000:14000:16000:18000:20000,0,0,1000 8041,5000:4500:4000:3500:3000,1000,0,12000:14000:16000:18000:20000,10000,0,1000
//-- MH_PYROCLASTIC //-- MH_PYROCLASTIC
8042,5000:4500:4000:3500:3000,0,0,60000:90000:120000:150000:180000,0,0,1000 8042,1000:1500:2000:2500:3000,1000,0,60000:90000:120000:150000:180000,0,0,200
//-- MH_VOLCANIC_ASH //-- MH_VOLCANIC_ASH
8043,5000:4500:4000:3500:3000,0,0,12000:14000:16000:18000:20000,0,0,1000 8043,4000:3500:3000:2500:2000,0,0,12000:14000:16000:18000:20000,0,0,1000
//===== Mercenary Skills =================== //===== Mercenary Skills ===================
//-- MS_MAGNUM //-- MS_MAGNUM

View File

@ -803,15 +803,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
struct skill_unit_group* group = skill_id2group(sc->data[SC_SAFETYWALL]->val3); struct skill_unit_group* group = skill_id2group(sc->data[SC_SAFETYWALL]->val3);
uint16 skill_id = sc->data[SC_SAFETYWALL]->val2; uint16 skill_id = sc->data[SC_SAFETYWALL]->val2;
if (group) { if (group) {
if(skill_id == MH_STEINWAND){ //in RE, SW possesses a lifetime equal to group val2, (3x caster hp, or homon formula)
if (--group->val2<=0)
skill_delunitgroup(group);
d->dmg_lv = ATK_BLOCK;
return 0;
}
/**
* in RE, SW possesses a lifetime equal to 3 times the caster's health
**/
#ifdef RENEWAL #ifdef RENEWAL
d->dmg_lv = ATK_BLOCK; d->dmg_lv = ATK_BLOCK;
if ( ( group->val2 - damage) > 0 ) { if ( ( group->val2 - damage) > 0 ) {
@ -1059,7 +1051,8 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
DAMAGE_SUBRATE(sc->data[SC_GRANITIC_ARMOR]->val2) DAMAGE_SUBRATE(sc->data[SC_GRANITIC_ARMOR]->val2)
} }
if(sc->data[SC_PAIN_KILLER]){ if(sc->data[SC_PAIN_KILLER]){
DAMAGE_SUBRATE(sc->data[SC_PAIN_KILLER]->val3) damage -= sc->data[SC_PAIN_KILLER]->val3;
damage = max(0,damage);
} }
if((sce=sc->data[SC_MAGMA_FLOW]) && (rnd()%100 <= sce->val2) ){ if((sce=sc->data[SC_MAGMA_FLOW]) && (rnd()%100 <= sce->val2) ){
skill_castend_damage_id(bl,src,MH_MAGMA_FLOW,sce->val1,gettick(),0); skill_castend_damage_id(bl,src,MH_MAGMA_FLOW,sce->val1,gettick(),0);
@ -1137,9 +1130,9 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
if( sd && (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON && rnd()%100 < sce->val2 ) if( sd && (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON && rnd()%100 < sce->val2 )
pc_addspiritball(sd,skill_get_time(LG_FORCEOFVANGUARD,sce->val1),sce->val3); pc_addspiritball(sd,skill_get_time(LG_FORCEOFVANGUARD,sce->val1),sce->val3);
if (sc->data[SC_STYLE_CHANGE] && rnd()%2) { if (sc->data[SC_STYLE_CHANGE]) {
TBL_HOM *hd = BL_CAST(BL_HOM,bl); TBL_HOM *hd = BL_CAST(BL_HOM,bl); //when being hit
if (hd) hom_addspiritball(hd, 10); //add a sphere if (hd && (rnd()%100<(status_get_lv(bl)/2)) ) hom_addspiritball(hd, 10); //add a sphere
} }
if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 ) if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 )
@ -1200,9 +1193,9 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag
sc_start(src,bl,sc->data[SC_POISONINGWEAPON]->val2,100,sc->data[SC_POISONINGWEAPON]->val1,skill_get_time2(GC_POISONINGWEAPON, 1)); sc_start(src,bl,sc->data[SC_POISONINGWEAPON]->val2,100,sc->data[SC_POISONINGWEAPON]->val1,skill_get_time2(GC_POISONINGWEAPON, 1));
if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 ) if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 )
status_change_spread(src, bl); status_change_spread(src, bl);
if (sc->data[SC_STYLE_CHANGE] && rnd()%2) { if (sc->data[SC_STYLE_CHANGE]) {
TBL_HOM *hd = BL_CAST(BL_HOM,src); TBL_HOM *hd = BL_CAST(BL_HOM,src); //when attacking
if (hd) hom_addspiritball(hd, 10); if (hd && (rnd()%100<(20+status_get_lv(bl)/5)) ) hom_addspiritball(hd, 10);
} }
} }
@ -2974,23 +2967,32 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
skillratio += 600 + 100 * skill_lv; skillratio += 600 + 100 * skill_lv;
break; break;
case MH_STAHL_HORN: case MH_STAHL_HORN:
skillratio += 400 + 100 * skill_lv; skillratio += 400 + 100 * skill_lv * status_get_lv(src);
skillratio = skillratio/100; //@TODO uv1 factor need to be confirmed
break; break;
case MH_LAVA_SLIDE: case MH_LAVA_SLIDE:
skillratio += -100 + 70 * skill_lv; skillratio += -100 + 70 * skill_lv;
break; break;
case MH_SONIC_CRAW: case MH_SONIC_CRAW:
skillratio += -100 + 40 * skill_lv; skillratio += -100 + 40 * skill_lv * status_get_lv(src);
skillratio = skillratio/100; //@TODO uv1 factor need to be confirmed
break; break;
case MH_SILVERVEIN_RUSH: case MH_SILVERVEIN_RUSH:
skillratio += -100 + 150 * skill_lv; skillratio += -100 + (150 * skill_lv * status_get_lv(src)) / 100;
break; break;
case MH_MIDNIGHT_FRENZY: case MH_MIDNIGHT_FRENZY:
skillratio += -100 + 300 * skill_lv; skillratio += -100 + (300 * skill_lv * status_get_lv(src)) / 150;
break; break;
case MH_TINDER_BREAKER: case MH_TINDER_BREAKER:
skillratio += -100 + (100 * skill_lv + status_get_str(src));
skillratio = (skillratio * status_get_lv(src)) / 120;
break;
case MH_CBC:
skillratio += 300 * skill_lv + 4 * status_get_lv(src);
break;
case MH_MAGMA_FLOW: case MH_MAGMA_FLOW:
skillratio += -100 + 100 * skill_lv; skillratio += -100 + 100 * skill_lv + 3 * status_get_lv(src);
skillratio = (skillratio * status_get_lv(src)) / 120;
break; break;
} }
#ifdef RENEWAL #ifdef RENEWAL
@ -4111,9 +4113,10 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
break; break;
case MH_HEILIGE_STANGE: case MH_HEILIGE_STANGE:
skillratio += 400 + 250 * skill_lv; skillratio += 400 + 250 * skill_lv;
skillratio = (skillratio * status_get_lv(src))/150;
break; break;
case MH_POISON_MIST: case MH_POISON_MIST:
skillratio += 100 * skill_lv; skillratio += -100 + 40 * skill_lv * status_get_lv(src) / 100;
break; break;
} }

View File

@ -135,6 +135,7 @@ struct mob_data {
//2: Alchemist Marine Sphere //2: Alchemist Marine Sphere
//3: Alchemist Summon Flora //3: Alchemist Summon Flora
//4: Summon Zanzou //4: Summon Zanzou
//5: Summon Legion
unsigned int clone : 1;/* is clone? 1:0 */ unsigned int clone : 1;/* is clone? 1:0 */
} special_state; //Special mob information that does not needs to be zero'ed on mob respawn. } special_state; //Special mob information that does not needs to be zero'ed on mob respawn.
struct { struct {

View File

@ -122,6 +122,7 @@ int skill_block_check(struct block_list *bl, enum sc_type type, uint16 skill_id)
static int skill_check_unit_range (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv); static int skill_check_unit_range (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv);
static int skill_check_unit_range2 (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv); static int skill_check_unit_range2 (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv);
static int skill_destroy_trap( struct block_list *bl, va_list ap ); static int skill_destroy_trap( struct block_list *bl, va_list ap );
static int skill_check_condition_mob_master_sub (struct block_list *bl, va_list ap);
//Since only mob-casted splash skills can hit ice-walls //Since only mob-casted splash skills can hit ice-walls
static inline int splash_target(struct block_list* bl) static inline int splash_target(struct block_list* bl)
{ {
@ -664,7 +665,7 @@ int skillnotok_hom(uint16 skill_id, struct homun_data *hd)
if(hd->homunculus.hunger <= 1) //if we starving if(hd->homunculus.hunger <= 1) //if we starving
return 1; return 1;
break; break;
case MH_GOLDENE_FERSE: //can be used with angriff case MH_GOLDENE_FERSE: //cant be used with angriff
if(hd->sc.data[SC_ANGRIFFS_MODUS]) if(hd->sc.data[SC_ANGRIFFS_MODUS])
return 1; return 1;
break; break;
@ -933,7 +934,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
(2000 - 4*sstatus->agi - 2*sstatus->dex)); (2000 - 4*sstatus->agi - 2*sstatus->dex));
} }
} }
if(sc && sc->data[SC_PYROCLASTIC] && (rnd() % 1000 <= sstatus->luk * 10 / 3 + 1) ) if(sc && sc->data[SC_PYROCLASTIC] && ((rnd()%100)<=sc->data[SC_PYROCLASTIC]->val3) )
skill_castend_pos2(src, bl->x, bl->y, BS_HAMMERFALL,sc->data[SC_PYROCLASTIC]->val1, tick, 0); skill_castend_pos2(src, bl->x, bl->y, BS_HAMMERFALL,sc->data[SC_PYROCLASTIC]->val1, tick, 0);
} }
@ -1489,8 +1490,14 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint
case MH_SILVERVEIN_RUSH: case MH_SILVERVEIN_RUSH:
sc_start4(src,bl,SC_STUN,20 + (5*skill_lv),skill_lv,src->id,0,0,skill_get_time(skill_id,skill_lv)); sc_start4(src,bl,SC_STUN,20 + (5*skill_lv),skill_lv,src->id,0,0,skill_get_time(skill_id,skill_lv));
break; break;
case MH_MIDNIGHT_FRENZY: case MH_MIDNIGHT_FRENZY: {
sc_start4(src,bl,SC_FEAR,20 + (4*skill_lv),skill_lv,src->id,0,0,skill_get_time(skill_id,skill_lv)); TBL_HOM *hd = BL_CAST(BL_HOM,src);
int spiritball = (hd?hd->homunculus.spiritball:1);
sc_start4(src,bl,SC_FEAR,spiritball*(10+2*skill_lv),skill_lv,src->id,0,0,skill_get_time(skill_id,skill_lv));
break;
}
case MH_XENO_SLASHER:
sc_start4(src,bl,SC_BLEEDING,skill_lv,skill_lv,src->id,0,0,skill_get_time2(skill_id,skill_lv)); //@TODO need real duration
break; break;
} }
@ -4700,10 +4707,11 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
//recursive homon skill //recursive homon skill
case MH_MAGMA_FLOW: case MH_MAGMA_FLOW:
case MH_XENO_SLASHER:
case MH_HEILIGE_STANGE: case MH_HEILIGE_STANGE:
if(flag & 1) if(flag & 1){
if((skill_id == MH_MAGMA_FLOW) && ((rnd()%100)>(3*skill_lv)) ) break;//chance to not trigger atk for magma
skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag); skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
}
else { else {
map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag | BCT_ENEMY | SD_SPLASH | 1, skill_castend_damage_id); map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag | BCT_ENEMY | SD_SPLASH | 1, skill_castend_damage_id);
} }
@ -4721,7 +4729,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
case MH_EQC: { case MH_EQC: {
TBL_HOM *hd = BL_CAST(BL_HOM,src); TBL_HOM *hd = BL_CAST(BL_HOM,src);
int8 k=0; int8 k=0;
int duration; int duration=0;
struct status_change_entry *sce; struct status_change_entry *sce;
struct block_list *tbl = NULL; //target struct block_list *tbl = NULL; //target
@ -4759,17 +4767,15 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
clif_skill_poseffect(src,skill_id,skill_lv,bl->x,bl->y,tick); clif_skill_poseffect(src,skill_id,skill_lv,bl->x,bl->y,tick);
#endif #endif
} }
case MH_CBC: case MH_CBC:
case MH_EQC: case MH_EQC:
duration = (status_get_str(src)*2 - status_get_str(bl))/10;//custom need real formula duration = max(skill_lv,(status_get_str(src)/7 - status_get_str(bl)/10))*1000; //Yommy formula
hom_delspiritball(hd,skill_id==MH_EQC?2:1,0); //only EQC consume 2 in grp 2 hom_delspiritball(hd,skill_id==MH_EQC?2:1,0); //only EQC consume 2 in grp 2
if(skill_id==MH_TINDER_BREAKER) if(skill_id==MH_TINDER_BREAKER)
sc_start2(src,src,status_skill2sc(skill_id),100,skill_lv,bl->id,duration); sc_start2(src,src,status_skill2sc(skill_id),100,skill_lv,bl->id,duration);
else else
sc_start(src,bl,status_skill2sc(skill_id),100,skill_lv,duration); sc_start(src,bl,status_skill2sc(skill_id),100,skill_lv,duration);
skill_attack(skill_get_type(skill_id),src,src,tbl,skill_id,skill_lv,tick,flag); skill_attack(skill_get_type(skill_id),src,src,tbl,skill_id,skill_lv,tick,flag);
//TODO add bonus for dmg SP ? on battle
break; break;
} }
break; break;
@ -9136,7 +9142,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
if (!tsc->data[SC_SILENCE]) //put inavoidable silence on target if (!tsc->data[SC_SILENCE]) //put inavoidable silence on target
status_change_start(src,bl, SC_SILENCE, 100, skill_lv, 0,0,0, skill_get_time(skill_id, skill_lv),1|2|8); status_change_start(src,bl, SC_SILENCE, 100, skill_lv, 0,0,0, skill_get_time(skill_id, skill_lv),1|2|8);
} }
heal = status_get_matk_min(src)*4; heal = status_get_sp(src) + status_get_lv(src); //cur_sp+blvl @TODO need real value
status_heal(bl, heal, 0, 7); status_heal(bl, heal, 0, 7);
//now inflict silence on everyone //now inflict silence on everyone
@ -9176,12 +9182,14 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
} }
break; break;
case MH_LIGHT_OF_REGENE: case MH_LIGHT_OF_REGENE: //self
sc_start2(src, src, type, 100, skill_lv, hd->homunculus.level, skill_get_time(skill_id, skill_lv));
if(hd){ if(hd){
hd->homunculus.intimacy = 251; //change to neutral (can't be cast if < 750) hd->homunculus.intimacy = 251; //change to neutral (can't be cast if < 750)
if(sd) clif_send_homdata(sd, SP_INTIMATE, hd->homunculus.intimacy); //refresh intimacy info if(sd) clif_send_homdata(sd, SP_INTIMATE, hd->homunculus.intimacy); //refresh intimacy info
skill_blockhomun_start(hd, skill_id, skill_get_cooldown(skill_id, skill_lv));
} }
//don't break need to start status and start block timer break;
case MH_STYLE_CHANGE: { case MH_STYLE_CHANGE: {
struct status_change_entry *sce; struct status_change_entry *sce;
if(hd && (sce=hd->sc.data[SC_STYLE_CHANGE])){ //in preparation for other bl usage if(hd && (sce=hd->sc.data[SC_STYLE_CHANGE])){ //in preparation for other bl usage
@ -9208,13 +9216,17 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
int summons[5] = {2158, 2159, 2159, 2160, 2160}; int summons[5] = {2158, 2159, 2159, 2160, 2160};
int qty[5] = {3 , 3 , 4 , 4 , 5}; int qty[5] = {3 , 3 , 4 , 4 , 5};
struct mob_data *sum_md; struct mob_data *sum_md;
int i; int i,c=0;
int maxcount = qty[skill_lv-1];
i = map_foreachinmap(skill_check_condition_mob_master_sub ,hd->bl.m, BL_MOB, hd->bl.id, summons[skill_lv-1], skill_id, &c);
if(c >= maxcount) return 0; //max qty already spawned
for(i=0; i<qty[skill_lv - 1]; i++){ //easy way for(i=0; i<qty[skill_lv - 1]; i++){ //easy way
sum_md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), summons[skill_lv - 1], "", SZ_SMALL, AI_ATTACK); sum_md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), summons[skill_lv - 1], "", SZ_SMALL, AI_ATTACK);
if (sum_md) { if (sum_md) {
sum_md->master_id = src->id; sum_md->master_id = src->id;
sum_md->special_state.ai = 1; sum_md->special_state.ai = 5;
if (sum_md->deletetimer != INVALID_TIMER) if (sum_md->deletetimer != INVALID_TIMER)
delete_timer(sum_md->deletetimer, mob_timer_delete); delete_timer(sum_md->deletetimer, mob_timer_delete);
sum_md->deletetimer = add_timer(gettick() + skill_get_time(skill_id, skill_lv), mob_timer_delete, sum_md->bl.id, 0); sum_md->deletetimer = add_timer(gettick() + skill_get_time(skill_id, skill_lv), mob_timer_delete, sum_md->bl.id, 0);
@ -10759,14 +10771,12 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill
switch( skill_id ) { switch( skill_id ) {
case MH_STEINWAND: case MH_STEINWAND:
val2 = 4 + skill_lv; //nb of attack blocked
break;
case MG_SAFETYWALL: case MG_SAFETYWALL:
#ifdef RENEWAL #ifdef RENEWAL
/** if(skill_id == MH_STEINWAND)
* According to data provided in RE, SW life is equal to 3 times caster's health val2 = 300 * skill_lv + 65 * ( status->int_ + status_get_lv(src) ) + status->max_sp; //nb hp
**/ else
val2 = status_get_max_hp(src) * 3; val2 = status_get_max_hp(src) * 3;
#else #else
val2 = skill_lv+1; val2 = skill_lv+1;
#endif #endif
@ -12141,7 +12151,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns
break; break;
case UNT_POISON_MIST: case UNT_POISON_MIST:
skill_attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); skill_attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
status_change_start(ss, bl, SC_BLIND, rnd() % 100 > sg->skill_lv * 10, sg->skill_lv, sg->skill_id, 0, 0, skill_get_time2(sg->skill_id, sg->skill_lv), 2|8); status_change_start(ss, bl, SC_BLIND, (10 + 10 * sg->skill_lv)*100, sg->skill_lv, sg->skill_id, 0, 0, skill_get_time2(sg->skill_id, sg->skill_lv), 2|8);
break; break;
} }
@ -12544,11 +12554,14 @@ int skill_check_pc_partner (struct map_session_data *sd, uint16 skill_id, short*
} }
/*========================================== /*==========================================
* * Sub function to count how many spawned mob is around
* return :
* x : numbers of mob of class with special ai
*------------------------------------------*/ *------------------------------------------*/
static int skill_check_condition_mob_master_sub (struct block_list *bl, va_list ap) static int skill_check_condition_mob_master_sub (struct block_list *bl, va_list ap)
{ {
int *c,src_id,mob_class,skill; int *c,src_id,mob_class,skill;
uint16 ai;
struct mob_data *md; struct mob_data *md;
md=(struct mob_data*)bl; md=(struct mob_data*)bl;
@ -12557,7 +12570,8 @@ static int skill_check_condition_mob_master_sub (struct block_list *bl, va_list
skill=va_arg(ap,int); skill=va_arg(ap,int);
c=va_arg(ap,int *); c=va_arg(ap,int *);
if( md->master_id != src_id || md->special_state.ai != (unsigned)(skill == AM_SPHEREMINE?2:skill == KO_ZANZOU?4:3) ) ai = (unsigned)(skill == AM_SPHEREMINE?2:skill == KO_ZANZOU?4:skill == MH_SUMMON_LEGION?5:3);
if( md->master_id != src_id || md->special_state.ai != ai)
return 0; //Non alchemist summoned mobs have nothing to do here. return 0; //Non alchemist summoned mobs have nothing to do here.
if(md->class_==mob_class) if(md->class_==mob_class)
@ -13509,10 +13523,10 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id,
if( c >= skill_get_maxcount(skill_id,skill_lv) || c != i) if( c >= skill_get_maxcount(skill_id,skill_lv) || c != i)
{ {
clif_skill_fail(sd , skill_id, USESKILL_FAIL_LEVEL, 0); clif_skill_fail(sd , skill_id, USESKILL_FAIL_LEVEL, 0);
return 0; return 0;
}
} }
break; break;
}
} }
status = &sd->battle_status; status = &sd->battle_status;

View File

@ -494,9 +494,8 @@ void initChangeTables(void) {
// Homunculus S // Homunculus S
add_sc(MH_STAHL_HORN, SC_STUN); add_sc(MH_STAHL_HORN, SC_STUN);
set_sc(MH_ANGRIFFS_MODUS, SC_ANGRIFFS_MODUS, SI_ANGRIFFS_MODUS, SCB_BATK | SCB_DEF | SCB_FLEE | SCB_MAXHP); set_sc(MH_ANGRIFFS_MODUS, SC_ANGRIFFS_MODUS, SI_ANGRIFFS_MODUS, SCB_BATK | SCB_DEF | SCB_FLEE | SCB_MAXHP);
set_sc(MH_GOLDENE_FERSE, SC_GOLDENE_FERSE, SI_GOLDENE_FERSE, SCB_ASPD|SCB_MAXHP); set_sc(MH_GOLDENE_FERSE, SC_GOLDENE_FERSE, SI_GOLDENE_FERSE, SCB_ASPD|SCB_FLEE);
add_sc( MH_STEINWAND, SC_SAFETYWALL ); add_sc( MH_STEINWAND, SC_SAFETYWALL );
add_sc(MH_ERASER_CUTTER, SC_ERASER_CUTTER);
set_sc(MH_OVERED_BOOST, SC_OVERED_BOOST, SI_BLANK, SCB_FLEE|SCB_ASPD); set_sc(MH_OVERED_BOOST, SC_OVERED_BOOST, SI_BLANK, SCB_FLEE|SCB_ASPD);
add_sc(MH_LIGHT_OF_REGENE, SC_LIGHT_OF_REGENE); add_sc(MH_LIGHT_OF_REGENE, SC_LIGHT_OF_REGENE);
set_sc(MH_VOLCANIC_ASH, SC_ASH, SI_VOLCANIC_ASH, SCB_DEF|SCB_DEF2|SCB_HIT|SCB_BATK|SCB_FLEE); set_sc(MH_VOLCANIC_ASH, SC_ASH, SI_VOLCANIC_ASH, SCB_DEF|SCB_DEF2|SCB_HIT|SCB_BATK|SCB_FLEE);
@ -511,7 +510,7 @@ void initChangeTables(void) {
add_sc(MH_STYLE_CHANGE, SC_STYLE_CHANGE); add_sc(MH_STYLE_CHANGE, SC_STYLE_CHANGE);
set_sc(MH_TINDER_BREAKER, SC_TINDER_BREAKER, SI_TINDER_BREAKER, SCB_FLEE); set_sc(MH_TINDER_BREAKER, SC_TINDER_BREAKER, SI_TINDER_BREAKER, SCB_FLEE);
set_sc(MH_CBC, SC_CBC, SI_CBC, SCB_FLEE); set_sc(MH_CBC, SC_CBC, SI_CBC, SCB_FLEE);
set_sc(MH_EQC, SC_EQC, SI_EQC, SCB_DEF2|SCB_BATK); set_sc(MH_EQC, SC_EQC, SI_EQC, SCB_DEF2|SCB_BATK|SCB_MAXHP);
add_sc( MER_CRASH , SC_STUN ); add_sc( MER_CRASH , SC_STUN );
set_sc( MER_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK ); set_sc( MER_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
@ -1320,7 +1319,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s
TBL_HOM *hd = sd->hd; TBL_HOM *hd = sd->hd;
if(hd && hd->sc.data[SC_LIGHT_OF_REGENE]){ if(hd && hd->sc.data[SC_LIGHT_OF_REGENE]){
clif_skillcasting(&hd->bl, hd->bl.id, target->id, 0,0, MH_LIGHT_OF_REGENE, skill_get_ele(MH_LIGHT_OF_REGENE, 1), 10); //just to display usage clif_skillcasting(&hd->bl, hd->bl.id, target->id, 0,0, MH_LIGHT_OF_REGENE, skill_get_ele(MH_LIGHT_OF_REGENE, 1), 10); //just to display usage
clif_skill_nodamage(&sd->bl, target, ALL_RESURRECTION, 1, status_revive(&sd->bl,10*hd->sc.data[SC_LIGHT_OF_REGENE]->val1,0)); clif_skill_nodamage(&sd->bl, target, ALL_RESURRECTION, 1, status_revive(&sd->bl,hd->sc.data[SC_LIGHT_OF_REGENE]->val2,0));
status_change_end(&sd->hd->bl,SC_LIGHT_OF_REGENE,INVALID_TIMER); status_change_end(&sd->hd->bl,SC_LIGHT_OF_REGENE,INVALID_TIMER);
return hp + sp; return hp + sp;
} }
@ -2040,13 +2039,26 @@ int status_calc_mob_(struct mob_data* md, bool first)
md->special_state.ai = 0; md->special_state.ai = 0;
if (ud) if (ud)
{ // different levels of HP according to skill level { // different levels of HP according to skill level
if (ud->skill_id == AM_SPHEREMINE) { switch(ud->skill_id){
status->max_hp = 2000 + 400*ud->skill_lv; case AM_SPHEREMINE:
} else if(ud->skill_id == KO_ZANZOU){ status->max_hp = 2000 + 400*ud->skill_lv;
status->max_hp = 3000 + 3000 * ud->skill_lv; break;
} else { //AM_CANNIBALIZE case KO_ZANZOU:
status->max_hp = 1500 + 200*ud->skill_lv + 10*status_get_lv(mbl); status->max_hp = 3000 + 3000 * ud->skill_lv;
status->mode|= MD_CANATTACK|MD_AGGRESSIVE; break;
case AM_CANNIBALIZE:
status->max_hp = 1500 + 200*ud->skill_lv + 10*status_get_lv(mbl);
status->mode|= MD_CANATTACK|MD_AGGRESSIVE;
break;
case MH_SUMMON_LEGION:{
int homblvl = status_get_lv(mbl);
status->max_hp = 10 * (100 * (ud->skill_lv + 2) + homblvl);
status->batk = 100 * (ud->skill_lv+5) / 2;
status->def = 10 * (100 * (ud->skill_lv+2) + homblvl);
// status->aspd_rate = 10 * (2 * (20 - ud->skill_lv) - homblvl/10);
// status->aspd_rate = max(100,status->aspd_rate);
break;
}
} }
status->hp = status->max_hp; status->hp = status->max_hp;
} }
@ -4525,10 +4537,8 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan
batk += sc->data[SC_FULL_SWING_K]->val1; batk += sc->data[SC_FULL_SWING_K]->val1;
if(sc->data[SC_ODINS_POWER]) if(sc->data[SC_ODINS_POWER])
batk += 70; batk += 70;
if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ if(sc->data[SC_ASH])
if(status_get_element(bl) == ELE_WATER) //water type batk -= batk * sc->data[SC_ASH]->val4 / 100;
batk /= 2;
}
if(sc->data[SC_PYROCLASTIC]) if(sc->data[SC_PYROCLASTIC])
batk += sc->data[SC_PYROCLASTIC]->val2; batk += sc->data[SC_PYROCLASTIC]->val2;
if (sc->data[SC_ANGRIFFS_MODUS]) if (sc->data[SC_ANGRIFFS_MODUS])
@ -4786,7 +4796,7 @@ static signed short status_calc_hit(struct block_list *bl, struct status_change
if(sc->data[SC_FEAR]) if(sc->data[SC_FEAR])
hit -= hit * 20 / 100; hit -= hit * 20 / 100;
if (sc->data[SC_ASH]) if (sc->data[SC_ASH])
hit /= 2; hit -= (hit * sc->data[SC_ASH]->val2) / 100;
return (short)cap_value(hit,1,SHRT_MAX); return (short)cap_value(hit,1,SHRT_MAX);
} }
@ -4867,10 +4877,10 @@ static signed short status_calc_flee(struct block_list *bl, struct status_change
flee += flee * sc->data[SC_WIND_STEP_OPTION]->val2 / 100; flee += flee * sc->data[SC_WIND_STEP_OPTION]->val2 / 100;
if( sc->data[SC_ZEPHYR] ) if( sc->data[SC_ZEPHYR] )
flee += flee * sc->data[SC_ZEPHYR]->val2 / 100; flee += flee * sc->data[SC_ZEPHYR]->val2 / 100;
if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ //mob if(sc->data[SC_ASH])
if(status_get_element(bl) == ELE_WATER) //water type flee -= flee * sc->data[SC_ASH]->val4 / 100;
flee /= 2; if (sc->data[SC_GOLDENE_FERSE])
} flee += flee * sc->data[SC_GOLDENE_FERSE]->val2 / 100;
return (short)cap_value(flee,1,SHRT_MAX); return (short)cap_value(flee,1,SHRT_MAX);
} }
@ -4957,10 +4967,10 @@ static defType status_calc_def(struct block_list *bl, struct status_change *sc,
def += def * sc->data[SC_POWER_OF_GAIA]->val2 / 100; def += def * sc->data[SC_POWER_OF_GAIA]->val2 / 100;
if( sc->data[SC_PRESTIGE] ) if( sc->data[SC_PRESTIGE] )
def += def * sc->data[SC_PRESTIGE]->val1 / 100; def += def * sc->data[SC_PRESTIGE]->val1 / 100;
if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ if(sc->data[SC_ASH])
if(status_get_race(bl)==RC_PLANT) def -= def * sc->data[SC_ASH]->val3/100;
def /= 2; if( sc->data[SC_OVERED_BOOST] )
} def -= def * sc->data[SC_OVERED_BOOST]->val3 / 100;
return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX);; return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX);;
} }
@ -5012,10 +5022,8 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change
def2 -= def2 * ( 14 * sc->data[SC_ANALYZE]->val1 ) / 100; def2 -= def2 * ( 14 * sc->data[SC_ANALYZE]->val1 ) / 100;
if( sc->data[SC_ECHOSONG] ) if( sc->data[SC_ECHOSONG] )
def2 += def2 * sc->data[SC_ECHOSONG]->val2/100; def2 += def2 * sc->data[SC_ECHOSONG]->val2/100;
if(sc->data[SC_ASH] && (bl->type==BL_MOB)){ if(sc->data[SC_ASH])
if(status_get_race(bl)==RC_PLANT) def2 -= def2 * sc->data[SC_ASH]->val3/100;
def2 /= 2;
}
if (sc->data[SC_PARALYSIS]) if (sc->data[SC_PARALYSIS])
def2 -= def2 * sc->data[SC_PARALYSIS]->val2 / 100; def2 -= def2 * sc->data[SC_PARALYSIS]->val2 / 100;
if(sc->data[SC_EQC]) if(sc->data[SC_EQC])
@ -5628,8 +5636,8 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang
maxhp += maxhp * sc->data[SC_PETROLOGY_OPTION]->val2 / 100; maxhp += maxhp * sc->data[SC_PETROLOGY_OPTION]->val2 / 100;
if (sc->data[SC_ANGRIFFS_MODUS]) if (sc->data[SC_ANGRIFFS_MODUS])
maxhp += maxhp * 5 * sc->data[SC_ANGRIFFS_MODUS]->val1 /100; maxhp += maxhp * 5 * sc->data[SC_ANGRIFFS_MODUS]->val1 /100;
if (sc->data[SC_GOLDENE_FERSE]) if(sc->data[SC_EQC])
maxhp += maxhp * sc->data[SC_GOLDENE_FERSE]->val2 / 100; maxhp -= maxhp * sc->data[SC_EQC]->val4 / 100;
return (unsigned int)cap_value(maxhp,1,UINT_MAX); return (unsigned int)cap_value(maxhp,1,UINT_MAX);
} }
@ -6209,7 +6217,7 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
struct map_session_data *sd; struct map_session_data *sd;
nullpo_ret(bl); nullpo_ret(bl);
nullpo_retr(tick?tick:1, src); //If no source, it can't be resisted (NPC given) if(src==NULL) return tick?tick:1;//If no source, it can't be resisted (NPC given)
//Status that are blocked by Golden Thief Bug card or Wand of Hermod //Status that are blocked by Golden Thief Bug card or Wand of Hermod
if (status_isimmune(bl)) if (status_isimmune(bl))
@ -8681,31 +8689,37 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
tick_time = 1000; tick_time = 1000;
break; break;
case SC_GOLDENE_FERSE: case SC_GOLDENE_FERSE:
val2 = 10 + 10*val1; //max hp bonus val2 = 10 + 10*val1; //flee bonus
val3 = 6 + 4 * val1; // Aspd Bonus val3 = 6 + 4 * val1; // Aspd Bonus
val4 = 2 + 2 * val1; // Chance of holy attack val4 = 2 + 2 * val1; // Chance of holy attack
break; break;
case SC_OVERED_BOOST: case SC_OVERED_BOOST:
val2 = 300 + 40*val1; //flee bonus val2 = 300 + 40*val1; //flee bonus
val3 = 179 + 2*val1; //aspd bonus val3 = 179 + 2*val1; //aspd bonus
val4 = 50; //def reduc %
break; break;
case SC_GRANITIC_ARMOR: case SC_GRANITIC_ARMOR:
val2 = 2*val1; //dmg reduction val2 = 2*val1; //dmg hp reduction
val3 = 6*val1; //dmg on status end val3 = (6*status_get_max_hp(src))/100; //dmg hp on status end
val4 = 5 * val1; //unknow formula
break; break;
case SC_MAGMA_FLOW: case SC_MAGMA_FLOW:
val2 = 3*val1; //activation chance val2 = 3*val1; //activation chance
break; break;
case SC_PYROCLASTIC: case SC_PYROCLASTIC:
val2 += 10*val1; //atk bonus val2 += 10*val1*status_get_lv(src); //atk bonus
val3 = 2*val1;//Chance To AutoCast Hammer Fall %
break; break;
case SC_PARALYSIS: //[Lighta] need real info case SC_PARALYSIS: //[Lighta] need real info
val2 = 2*val1; //def reduction val2 = 2*val1; //def reduction
val3 = 500*val1; //varcast augmentation val3 = 500*val1; //varcast augmentation
break; break;
case SC_PAIN_KILLER: //[Lighta] need real info case SC_LIGHT_OF_REGENE: //Yommy leak need confirm
val2 = 2*val1; //aspd reduction % val2 = 20 * val1; //hp reco on death %
val3 = 2*val1; //dmg reduction % break;
case SC_PAIN_KILLER: //Yommy leak need confirm
val2 = 10 * val1; //aspd reduction %
val3 = (( 200 * val1 ) * status_get_lv(src)) / 150; //dmg reduction linear
if(sc->data[SC_PARALYSIS]) if(sc->data[SC_PARALYSIS])
sc_start(src,bl, SC_ENDURE, 100, val1, tick); //start endure for same duration sc_start(src,bl, SC_ENDURE, 100, val1, tick); //start endure for same duration
break; break;
@ -8713,21 +8727,23 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
tick = -1; tick = -1;
break; break;
case SC_CBC: case SC_CBC:
val2 = 10; //hp % dmg [not sure] val3 = 10; //drain sp % dmg
val3 = 10; //sp % dmg [not sure]
tick = max(tick,5000); //min 5s (test)
val4 = tick/1000; //dmg each sec val4 = tick/1000; //dmg each sec
tick = 1000; tick = 1000;
break; break;
case SC_EQC: case SC_EQC:
val2 = 25; //def % reduc [not sure] val2 = 5 * val1; //def % reduc
val3 = 25; //atk % reduc [not sure] val3 = 5 * val1; //atk % reduc
tick = max(tick,5000); //min 5s (test) val4 = 2 * val1; //maxhp % reduc
break; break;
case SC_TINDER_BREAKER: case SC_ASH:
//val1 = skilllv val2 = 50; //hit % reduc
//val2 = src->id val3 = 0;//def % reduc
tick = max(tick,5000); //min 5s (test) val4 = 0;//atk flee & reduc
if(status_get_race(bl) == RC_PLANT) //plant type
val3 = 50;
if(status_get_element(bl) == ELE_WATER) // defense water type
val4 = 50;
break; break;
default: default:
if( calc_flag == SCB_NONE && StatusSkillChangeTable[type] == 0 && StatusIconChangeTable[type] == 0 ) if( calc_flag == SCB_NONE && StatusSkillChangeTable[type] == 0 && StatusIconChangeTable[type] == 0 )
@ -9090,6 +9106,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
sc_start2(src, map_id2bl(val2),SC_CLOSECONFINE2,100,val1,bl->id,tick); sc_start2(src, map_id2bl(val2),SC_CLOSECONFINE2,100,val1,bl->id,tick);
break; break;
case SC_EQC: case SC_EQC:
sc_start2(src, bl,SC_STUN,100,val1,bl->id,(1000*status_get_lv(src))/50+500*val1);
status_change_end(bl,SC_TINDER_BREAKER,INVALID_TIMER); status_change_end(bl,SC_TINDER_BREAKER,INVALID_TIMER);
break; break;
} }
@ -10749,8 +10766,9 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
break; break;
case SC_CBC: case SC_CBC:
if(--(sce->val4) >= 0) { //drain hp/sp if(--(sce->val4) >= 0) { //drain hp/sp
int hp = (status->max_hp * sce->val2) / 100; int hp=0;
int sp = (status->max_sp * sce->val3) / 100; int sp = (status->max_sp * sce->val3) / 100;
if(bl->type == BL_MOB) hp = sp*10;
if( !status_charge(bl,hp,sp) ) break; if( !status_charge(bl,hp,sp) ) break;
sc_timer_next(1000+tick,status_change_timer,bl->id, data); sc_timer_next(1000+tick,status_change_timer,bl->id, data);
return 0; return 0;

View File

@ -634,12 +634,12 @@ typedef enum sc_type {
//homon S //homon S
SC_STYLE_CHANGE, SC_STYLE_CHANGE,
SC_TINDER_BREAKER, SC_TINDER_BREAKER, //@TODO rewritte me plz
SC_TINDER_BREAKER2, //for rewritte and other icone
SC_CBC, SC_CBC,
SC_EQC, SC_EQC,
SC_GOLDENE_FERSE, SC_GOLDENE_FERSE,
SC_ANGRIFFS_MODUS, SC_ANGRIFFS_MODUS,
SC_ERASER_CUTTER,
SC_OVERED_BOOST, SC_OVERED_BOOST,
SC_LIGHT_OF_REGENE, SC_LIGHT_OF_REGENE,
SC_ASH, SC_ASH,