2007年4月7日 星期六

mangos 奧妮克希亞的AI

這基本上都是ScriptDev2裏的程式碼,我改成中文的
測試的感覺是,如果公主第2階段飛在空中時能再飛高一點,換位置時不要跑到地面上...就蠻不錯的了^^
還有召小龍的功能沒有@@
.addspawn 10184 <==如果進副本沒發現奧妮克西亞時,試試看這個指令能不能把它請出來^^

17136 變身成奧妮克希亞的外觀
17647 Create Onyxia Spawner(沒用@@)
18391 Onyxia Speed Burst(也沒什麼作用@@)
20279 召喚玩家 召喚一個敵人來面對奧妮克希亞的怒火
22905 放置未淬火的劍(我不知道這做什麼用的@@)
22906 刺殺奧妮克希亞(我不知道這做什麼用的@@)
18387 奧妮克希亞(點了也是沒反應@@)
18596 吐息 會冒煙的吐息術喔
21139 火息術 不會冒煙的吐火
11010 懸浮 變成龍可以飛蠻高的
17131 懸浮 好像不能用

//scripts/zone/onyxias_lair/sc_boss_onyxia.cpp
#include "../../sc_defines.h"

// **** 這個script尚在開發中 ****

#define SPELL_WINGBUFFET 18500 //龍翼攻擊 錐形區域造成563-937的傷害並擊退
#define SPELL_FLAMEBREATH 18435 //火息術
#define SPELL_CLEAVE 26350 //順劈斬
#define SPELL_TAILSWEEP 15847 //25653 英文版的龍尾掃擊 15847中文版
#define SPELL_FIREBALL 20692 //不用法力的火球術
#define SPELL_DEEPBREATH 18596 //吐息術,火息術 21139好像也行
#define SPELL_BELLOWINGROAR 18431 //低沉咆哮 大範圍的恐懼

//召喚雛龍功能尚未被核心實作出來
#define SPELL_SUMMONWHELP 17646 //10碼的召喚奧妮克希亞雛龍
#define SPELL_SUMMON_MULTI_WHELPS 20171 //召喚奧妮克希亞雛龍(被動技)

//#define SAY_AGGRO "How fortuitous. Usually, I must leave my lair to feed."
//#define SAY_KILL "Learn your place mortal!"
//#define SAY_PHASE_2_TRANS "I'll incinerate you from above!"
//#define SAY_PHASE_3_TRANS "It seems you'll need another lesson"
#define SAY_AGGRO "真幸運,通常我要離開巢穴才能找到食物."
#define SAY_KILL "要知道你的處境,凡人!"
#define SAY_PHASE_2_TRANS "這毫無意義的行動讓我很厭煩。我會從上空把你們都燒成灰!"
#define SAY_PHASE_3_TRANS "看起來需要再給你一次教訓,凡人!"

struct MANGOS_DLL_DECL boss_onyxiaAI : public ScriptedAI
{
boss_onyxiaAI(Creature *c) : ScriptedAI(c) {Reset();}

uint32 swingcounter;
uint32 flamebreath_timer;
uint32 cleave_timer;
uint32 tailsweep_timer;
uint32 movement_timer;
uint32 fireball_timer;
uint32 whelpspawn_timer;
uint32 bellowingroar_timer;
uint32 reset_timer;
uint32 phase;

void Reset()
{
swingcounter = 0;
flamebreath_timer = 20000;
cleave_timer = 15000;
tailsweep_timer = 10000;
movement_timer = 10000;
fireball_timer = 5000;
whelpspawn_timer = 45000;
bellowingroar_timer = 0;
phase = 1;

if (m_creature)
{
m_creature->InterruptSpell();
m_creature->SetHover(false);
(*m_creature)->Clear(false);
EnterEvadeMode();
}
}

void KilledUnit(Unit* victim)
{
if (rand()%5) //亂數決定是否要公主說話
return;

DoYell(SAY_KILL,LANG_UNIVERSAL,NULL);
}

void AttackStart(Unit *who)
{
if (!who)
return;

if (m_creature->getVictim() == NULL && who->isTargetableForAttack() && who != m_creature)
{
//開始攻擊
DoStartMeleeAttack(who);

//最一開始攻擊時,黑龍公主說的第一句話
DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL);
}
}

void MoveInLineOfSight(Unit *who)
{
if (!who || m_creature->getVictim())
return;

if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who))
{
float attackRadius = m_creature->GetAttackDistance(who);
if (m_creature->IsWithinDist(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE)
{
if(who->HasStealthAura())
who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);

//開始攻擊
DoStartMeleeAttack(who);

//最一開始攻擊時,黑龍公主說的第一句話
DoYell(SAY_AGGRO,LANG_UNIVERSAL,NULL);
}
}
}

void UpdateAI(const uint32 diff)
{
//If we had a target and it wasn't cleared then it means the target died from some unknown soruce
//But we still need to reset
if (!m_creature->SelectHostilTarget())
{
Reset();//黑龍公主重置
return;
}

//檢查是否有玩家存活著
if( m_creature->getVictim() && m_creature->isAlive())
{
//第1及第3階段的施法
if (phase == 1 || phase == 3)
{
//每15秒1次火焰吐息
if (flamebreath_timer < diff)
{
DoCast(m_creature->getVictim(),SPELL_FLAMEBREATH);
flamebreath_timer = 15000;

}else flamebreath_timer -= diff;

//每20秒一次順劈斬
if (cleave_timer < diff)
{
DoCast(m_creature->getVictim(),SPELL_CLEAVE);
cleave_timer = 20000;

}else cleave_timer -= diff;

//每10秒神龍擺尾一次
if (tailsweep_timer < diff)
{
//如果有人在公主擺尾的範圍內,則進行神龍擺尾的特攻
if (!m_creature->HasInArc( M_PI, m_creature->getVictim()))
DoCast(m_creature->getVictim(),SPELL_TAILSWEEP);

tailsweep_timer = 20000;

}else tailsweep_timer -= diff;
}

//第2階段
if (phase == 2)
{
//如果不是在盤旋的話,則飛起來
if (!m_creature->isHover())
{
m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
m_creature->SetHover(true);
}

//每10秒亂數移動位置一次
if (movement_timer < diff)
{
//不管是否在施法中一律中斷並移動到亂數選到的位置去
m_creature->InterruptSpell();
uint32 position = rand()%9;

switch (position)
{
case 0:
SpecialMove(-65.8444,-213.809,-84.2985,5000);
m_creature->Relocate(-65,-213,-84,0);
break;
case 1:
SpecialMove(22.8739,-217.152,-85.0548,5000);
m_creature->Relocate(22,-217,-85,0);
break;
case 2:
SpecialMove(-33.5561,-182.682,-88.9457,5000);
m_creature->Relocate(-33,-182,-88,0);
break;
case 3:
SpecialMove(-31.4963,-250.123,-89.1278,5000);
m_creature->Relocate(-31,-250,-89,0);
break;
case 4:
SpecialMove(-2.78999,-181.431,-86.8962,5000);
m_creature->Relocate(-2,-181,-86,0);
break;
case 5:
SpecialMove(-54.9415,-232.242,-85.5555,5000);
m_creature->Relocate(-54,-232,-85,0);
break;
case 6:
SpecialMove(-65.2653,-194.879,-84.6718,5000);
m_creature->Relocate(-65,-194,-84,0);
break;
case 7:
SpecialMove(10.5665,-241.478,-85.9426,5000);
m_creature->Relocate(10,-241,-85,0);
break;
case 8:
//1/9的機會施展一次深呼,否則的話移動位置
//DoTextEmote("takes a deep breath...",NULL);
//DoYell("Deep Breath would go here!", LANG_UNIVERSAL,NULL);
DoTextEmote("深深地吸了一口氣...",NULL);
DoYell("奧妮克希亞深呼吸即將出現!", LANG_UNIVERSAL,NULL);
break;
}

DoCast(m_creature,11010);//懸浮?
movement_timer = 10000;
}else movement_timer -= diff;

//每5秒亂數決定吐火球
if (fireball_timer < diff)
{
//應該要隨機選一個目標但是因沒有仇恨列表所以直接對現有的目標進行攻擊
DoCast(m_creature->getVictim(),SPELL_FIREBALL);
fireball_timer = 5000;
}else fireball_timer -= diff;

//每45秒重生一次小龍
if (whelpspawn_timer < diff)
{
//不過核心還不支援所以只顯示重生訊息
DoYell("小龍重生!",LANG_UNIVERSAL,NULL); //召喚小龍還沒有實作
whelpspawn_timer = 450000;
}else whelpspawn_timer -= diff;
}

//第3階段才會出現的特攻
if (phase == 3)
{
//每10-30秒出現一次
if (bellowingroar_timer < diff && phase == 3)
{
//大範圍恐懼,如果沒修正恐懼Bug的話請將下一行拿掉
DoCast(m_creature->getVictim(),SPELL_BELLOWINGROAR);
bellowingroar_timer = 10000 + rand()%20000;
}else bellowingroar_timer -= diff;
}

//第1階段到第2階段轉換時機為血低於60%
if ( phase == 1 && (m_creature->GetHealth()*100) / m_creature->GetMaxHealth() < 60)
{
phase = 2;
m_creature->InterruptSpell();
m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
(*m_creature)->Clear(false);
(*m_creature)->Idle();
DoCast(m_creature,11010);//懸浮?...
m_creature->SetHover(true);
DoCast(m_creature,18430);//公主空中盤旋? 學到的技能是龍類懸浮@@
DoYell(SAY_PHASE_2_TRANS,LANG_UNIVERSAL,NULL);
}

//第2階段到第3階段轉換時機為血低於40%
if ( phase == 2 && (m_creature->GetHealth()*100) / m_creature->GetMaxHealth() < 40)
{
phase = 3;
m_creature->InterruptSpell();
//m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,EMOTE_STATE_STAND);
m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
m_creature->SetHover(false);
(*m_creature)->Clear(false);
(*m_creature)->Mutate(new TargetedMovementGenerator(*m_creature->getVictim()));
DoYell(SAY_PHASE_3_TRANS,LANG_UNIVERSAL,NULL);
}

//如果正處於跟公主的混戰範圍又不在第二階段
if( phase!=2 && m_creature->getVictim() && m_creature->IsWithinDist(m_creature->getVictim(), ATTACK_DIST))
{
if( m_creature->isAttackReady() )
{
m_creature->AttackerStateUpdate(m_creature->getVictim());
m_creature->resetAttackTimer();

//在第1階段及第3階段每12次攻擊後做出一次龍翼打擊
if (swingcounter > 12 && m_creature->getVictim())
{
DoCast(m_creature->getVictim(),SPELL_WINGBUFFET);
swingcounter = 0;
}else swingcounter++;
}
}
}
}

void SpecialMove(float X, float Y, float Z, uint32 Time)
{
WorldPacket data( SMSG_MONSTER_MOVE, (41+m_creature->GetPackGUID().size()) );
data.append(m_creature->GetPackGUID());

data << m_creature->GetPositionX() << m_creature->GetPositionY() << m_creature->GetPositionZ();
// unknown field - unrelated to orientation
// seems to increment about 1000 for every 1.7 seconds
// for now, we'll just use mstime
data << getMSTime();

data << uint8(0); // walkback when walking from A to B
data << uint32(0x0200); // 旗標
/* 旗標:
512: 漂著, 或不是以跑或走的型態移動
*/
data << Time; // Time in between points
data << uint32(1); // 1 single waypoint
data << X << Y << Z; // the single waypoint Point B
m_creature->SendMessageToSet( &data, true );
}
};
CreatureAI* GetAI_boss_onyxiaAI(Creature *_Creature)
{
return new boss_onyxiaAI (_Creature);
}


void AddSC_boss_onyxia()
{
Script *newscript;
newscript = new Script;
newscript->Name="boss_onyxia";
newscript->GetAI = GetAI_boss_onyxiaAI;
m_scripts[nrscripts++] = newscript;
}

沒有留言: