|
@@ -3812,12 +3812,12 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
|
|
|
dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, CR_HOLYCROSS, -1, DMG_SPLASH);
|
|
|
break;
|
|
|
//Skills that need be passed as a normal attack for the client to display correctly.
|
|
|
- case HVAN_EXPLOSION:
|
|
|
case NPC_SELFDESTRUCTION:
|
|
|
if(src->type == BL_PC)
|
|
|
dmg.blewcount = 10;
|
|
|
dmg.amotion = 0; //Disable delay or attack will do no damage since source is dead by the time it takes effect. [Skotlex]
|
|
|
[[fallthrough]];
|
|
|
+ case HVAN_EXPLOSION:
|
|
|
case KN_AUTOCOUNTER:
|
|
|
case NPC_CRITICALSLASH:
|
|
|
case TF_DOUBLE:
|
|
@@ -4762,6 +4762,9 @@ static TIMER_FUNC(skill_timerskill){
|
|
|
case ABC_FRENZY_SHOT:
|
|
|
skill_castend_damage_id(src, target, skl->skill_id, skl->skill_lv, tick, skl->flag);
|
|
|
break;
|
|
|
+ case HVAN_EXPLOSION:
|
|
|
+ status_kill(src);
|
|
|
+ break;
|
|
|
default:
|
|
|
skill_attack(skl->type,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag);
|
|
|
break;
|
|
@@ -6193,18 +6196,11 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
|
|
sc_start(src,src,SC_MAGICALATTACK,100,skill_lv,skill_get_time(skill_id,skill_lv));
|
|
|
break;
|
|
|
|
|
|
- case HVAN_CAPRICE: //[blackhole89]
|
|
|
+ case HVAN_CAPRICE:
|
|
|
{
|
|
|
- int ran=rnd()%4;
|
|
|
- int sid = 0;
|
|
|
- switch(ran)
|
|
|
- {
|
|
|
- case 0: sid=MG_COLDBOLT; break;
|
|
|
- case 1: sid=MG_FIREBOLT; break;
|
|
|
- case 2: sid=MG_LIGHTNINGBOLT; break;
|
|
|
- case 3: sid=WZ_EARTHSPIKE; break;
|
|
|
- }
|
|
|
- skill_attack(BF_MAGIC,src,src,bl,sid,skill_lv,tick,flag|SD_LEVEL);
|
|
|
+ static const std::array<e_skill, 4> subskills = { MG_COLDBOLT, MG_FIREBOLT, MG_LIGHTNINGBOLT, WZ_EARTHSPIKE };
|
|
|
+ e_skill subskill_id = subskills.at(rnd() % subskills.size());
|
|
|
+ skill_attack(skill_get_type(subskill_id), src, src, bl, subskill_id, skill_lv, tick, flag);
|
|
|
}
|
|
|
break;
|
|
|
|
|
@@ -6324,7 +6320,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint
|
|
|
[[fallthrough]];
|
|
|
case HVAN_EXPLOSION:
|
|
|
if (src != bl)
|
|
|
- skill_attack(BF_MISC,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);
|
|
|
break;
|
|
|
|
|
|
// Celest
|
|
@@ -8817,13 +8813,11 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|
|
BF_MAGIC, src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY);
|
|
|
break;
|
|
|
|
|
|
- case HVAN_EXPLOSION: //[orn]
|
|
|
case NPC_SELFDESTRUCTION:
|
|
|
//Self Destruction hits everyone in range (allies+enemies)
|
|
|
//Except for Summoned Marine spheres on non-versus maps, where it's just enemy.
|
|
|
i = ((!md || md->special_state.ai == AI_SPHERE) && !map_flag_vs(src->m))?
|
|
|
BCT_ENEMY:BCT_ALL;
|
|
|
- clif_skill_nodamage(src, *src, skill_id, -1);
|
|
|
map_delblock(src); //Required to prevent chain-self-destructions hitting back.
|
|
|
map_foreachinshootrange(skill_area_sub, bl,
|
|
|
skill_get_splash(skill_id, skill_lv), BL_CHAR|BL_SKILL,
|
|
@@ -8833,14 +8827,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|
|
map_freeblock_unlock();
|
|
|
return 1;
|
|
|
}
|
|
|
- status_damage(src, src, sstatus->max_hp,0,0,1, skill_id);
|
|
|
- if(skill_id == HVAN_EXPLOSION && src->type == BL_HOM) {
|
|
|
- homun_data& hd = reinterpret_cast<homun_data&>( *src );
|
|
|
-
|
|
|
- hd.homunculus.intimacy = hom_intimacy_grade2intimacy(HOMGRADE_HATE_WITH_PASSION);
|
|
|
-
|
|
|
- clif_send_homdata( hd, SP_INTIMATE );
|
|
|
- }
|
|
|
+ status_kill(src);
|
|
|
break;
|
|
|
case AL_ANGELUS:
|
|
|
#ifdef RENEWAL
|
|
@@ -10703,26 +10690,58 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
|
|
else if (sd != nullptr)
|
|
|
clif_skill_fail( *sd, skill_id );
|
|
|
break;
|
|
|
- case HVAN_CHAOTIC: //[orn]
|
|
|
+ case HVAN_CHAOTIC:
|
|
|
{
|
|
|
- static const int per[5][2]={{20,50},{50,60},{25,75},{60,64},{34,67}};
|
|
|
- int r = rnd()%100;
|
|
|
- i = (skill_lv-1)%5;
|
|
|
- if(r<per[i][0]) //Self
|
|
|
+ // Chance per skill level
|
|
|
+ static const std::array<uint8, 5> chance_homunculus = {
|
|
|
+ 20,
|
|
|
+ 50,
|
|
|
+ 25,
|
|
|
+ 50,
|
|
|
+ 34
|
|
|
+ };
|
|
|
+ static const std::array<uint8, 5> chance_master = {
|
|
|
+ static_cast<uint8>(chance_homunculus[0] + 30),
|
|
|
+ static_cast<uint8>(chance_homunculus[1] + 10),
|
|
|
+ static_cast<uint8>(chance_homunculus[2] + 50),
|
|
|
+ static_cast<uint8>(chance_homunculus[3] + 4),
|
|
|
+ static_cast<uint8>(chance_homunculus[4] + 33)
|
|
|
+ };
|
|
|
+
|
|
|
+ uint8 chance = rnd_value(1, 100);
|
|
|
+
|
|
|
+ // Homunculus
|
|
|
+ if (chance <= chance_homunculus[skill_lv - 1])
|
|
|
bl = src;
|
|
|
- else if(r<per[i][1]) //Master
|
|
|
+ // Master
|
|
|
+ else if (chance <= chance_master[skill_lv - 1])
|
|
|
bl = battle_get_master(src);
|
|
|
- else //Enemy
|
|
|
- bl = map_id2bl(battle_gettarget(src));
|
|
|
+ // Enemy (A random enemy targeting the master)
|
|
|
+ else
|
|
|
+ bl = battle_gettargeted(battle_get_master(src));
|
|
|
|
|
|
- if (!bl) bl = src;
|
|
|
- i = skill_calc_heal(src, bl, skill_id, 1+rnd()%skill_lv, true);
|
|
|
- //Eh? why double skill packet?
|
|
|
- clif_skill_nodamage(src,*bl,AL_HEAL,i);
|
|
|
- clif_skill_nodamage(src,*bl,skill_id,i);
|
|
|
- status_heal(bl, i, 0, 0);
|
|
|
- }
|
|
|
- break;
|
|
|
+ // If there's no enemy the chance reverts to the homunculus
|
|
|
+ if (bl == nullptr)
|
|
|
+ bl = src;
|
|
|
+
|
|
|
+ int32 heal = skill_calc_heal(src, bl, skill_id, rnd_value<uint16>(1, skill_lv), true);
|
|
|
+
|
|
|
+ // Official servers send the Heal skill packet with the healed amount, and then the skill packet with 1 as healed amount
|
|
|
+ clif_skill_nodamage(src, *bl, AL_HEAL, heal);
|
|
|
+ clif_skill_nodamage(src, *bl, skill_id, 1);
|
|
|
+ status_heal(bl, heal, 0, 0);
|
|
|
+ } break;
|
|
|
+ case HVAN_EXPLOSION:
|
|
|
+ if( hd != nullptr ){
|
|
|
+ clif_skill_nodamage(src, *src, skill_id, skill_lv, 1);
|
|
|
+ map_foreachinshootrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), BL_CHAR | BL_SKILL, src, skill_id, skill_lv, tick, flag | BCT_ENEMY, skill_castend_damage_id);
|
|
|
+
|
|
|
+ hd->homunculus.intimacy = hom_intimacy_grade2intimacy(HOMGRADE_HATE_WITH_PASSION);
|
|
|
+ clif_send_homdata(*hd, SP_INTIMATE);
|
|
|
+
|
|
|
+ // There's a delay between the explosion and the homunculus death
|
|
|
+ skill_addtimerskill(src, tick + skill_get_time(skill_id, skill_lv), src->id, 0, 0, skill_id, skill_lv, 0, flag);
|
|
|
+ } break;
|
|
|
// Homun single-target support skills [orn]
|
|
|
case HLIF_CHANGE:
|
|
|
#ifndef RENEWAL
|