这个脚本主要用于测试,*OSS的攻击分三个阶段,根据生命值的百分比进入各个阶段,各阶段会使用不同的魔法,进入第三阶段时会变身(具体包括增强攻击力、提升自己的等级、变成另一个怪物模样、体型增大4倍),并进入狂怒模式。并且当死亡或退出战斗后,会恢复原有的显示大小及相关属性。



//*OSS的AI测试脚本


#include "sc_defines.h"


//*OSS魔法定义

#define SPELL_*UFF      25661

#define SPELL_ONE      12555

#define SPELL_ONE_ALT  24099

#define SPELL_TWO      10017

#define SPELL_THREE    26027

#define SPELL_ENRAGE    23537

#define SPELL_*ESERK    32309


//拉格纳罗斯的魔法

#define SPELL_HANDOFRAGNAROS        19780

#define SPELL_WRATHOFRAGNAROS      20566

#define SPELL_LAVA*URST            21158

#define SPELL_MAGMA*URST            20565      //Ranged attack 范围攻击

#define SPELL_SONSOFFLAME_DUMMY    21108      //Server side effect

#define SPELL_RAGSU*MERGE          21107      //Stealth aura


//奈法利安的魔法

#define SPELL_SHADOWFLAME_INITIAL  22972

#define SPELL_SHADOWFLAME          22539  //应该是火息术吧

#define SPELL_*ELLOWINGROAR        22686  //怒吼

#define SPELL_VEILOFSHADOW          7068    //应该是暗影魔法攻击

#define SPELL_CLEAVE                20691  //劈, 劈开, 裂开 vi.粘着, 忠于, 坚持

#define SPELL_TAILLASH              23364  //租税

#define SPELL_*ONECONTRUST          23363 //23362, 23361 骨  亲密的


#define SPELL_MAGE                  23410  //wild magic 法师 狂暴状态

#define SPELL_WARRIOR              23397 //beserk 困扰战士

#define SPELL_DRUID                23398 // cat form小D变猫

#define SPELL_PRIEST                23401 // corrupted healing 牧师邪恶康复

#define SPELL_PALADIN              23418 //syphon blessing 骑士X祝福

#define SPELL_SHAMAN                23425  //totems SM未知

#define SPELL_WARLOCK              23427 //infernals 术士

#define SPELL_HUNTER                23436 //bow broke 猎人 弓,一文不名的

#define SPELL_ROGUE                23414 //Paralise 盗贼 视差的


//*OSS说话定义

#define SAY_AGGRO      "鍒児鎴戯紝鍚﹀垯浼氳浣犱滑灏濆埌鑻﹀ご鐨勶紒"  //别惹我,否则会让你们尝到苦头的!

#define SAY_RANDOM_0    "鍝庯紝浣犱滑浣曞繀瑕佹潵閫佹鍛紒"                //哎,你们何必要来送死呢!

#define SAY_RANDOM_1    "Muahahahaha"

#define SAY_RANDOM_2    "These mortal infedels my lord, they have invaded your sanctum and seek to steal your secrets."

#define SAY_RANDOM_3    "You are already dead."

#define SAY_RANDOM_4    "Where to go? What to do? So many choices that all end in pain, end in death."

#define SAY_*ESERK      "$N, I sentance you to death!"

#define SAY_PHASE      "璁╀綘浠璇嗘垜鐪熸鐨勫姏閲忓惂锛乻"                //让你们见识我真正的力量吧!

#define SAY_PHASE2      "灏忛浠紝鐪熺殑瑕佹垜鏉€浜嗕綘浠悧锛?"                //小鬼们,真的要我杀了你们吗?

#define GOSSIP_ITEM    "I'm looking for a fight"

#define SAY_DANCE      "I always thought I was a good dancer"

#define SAY_SALUTE      "Move out Soldier!"


struct MANGOS_DLL_DECL myboss_testAI : public ScriptedAI

{

    //*** HANDLED FUNCTION *** 

    //This is the constructor, called only once when the creature is first created

    myboss_testAI(Creature *c) : ScriptedAI(c) {Reset();}


    //*** CUSTOM VARIA*LES ****

    //These variables are for use only by this individual script.

    //Nothing else will ever call them but us.


    uint32 Say_Timer;    //随机说话的时间

    uint32 Rebuff_Timer; //Timer for rebuffing

    uint32 Spell_1_Timer;//Timer for spell 1 when in combat

    uint32 Spell_2_Timer;//Timer for spell 1 when in combat

    uint32 Spell_3_Timer;//Timer for spell 1 when in combat

    uint32 Spell_4_Timer;//Timer for spell 1 when in combat

    uint32 Spell_5_Timer;//Timer for spell 1 when in combat

    uint32 *eserk_Timer; //困扰魔法的时间

    uint32 Phase;        //当前阶段

    uint32 Phase_Timer;  //Timer until phase transition  //阶段转变的时间


    //*** CUSTOM FUNCTION ***

    //This resets the creature to before the fight began

    void Reset()

    {

        Phase = 1;              //Start in phase 1 开始第一阶段

        Phase_Timer = 60000;    //60 seconds

        Spell_1_Timer = 5000;  //5 seconds

        Spell_2_Timer = 37000;  //37 seconds

        Spell_3_Timer = 19000;  //19 seconds

        Spell_4_Timer = 15000;  //15 seconds

        Spell_5_Timer = 25000;  //25 seconds

        *eserk_Timer = 120000;  //2 minutes


        m_creature->SetUInt32Value(UNIT_FIELD_LEVEL,103);            //恢复级

        m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,11311 );        //恢复显示

        m_creature->SetFloatValue(O*JECT_FIELD_SCALE_X, 1);                //恢复大小

        m_creature->SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE,1350 * 30);  //恢复攻击力

        m_creature->SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE,1700 * 30);    //恢复攻击力


        //Return to home position  怪物返回开始位置

        if (m_creature)

            EnterEvadeMode();

    }


    //死亡以后触发

    void JustDied(Unit* Killer)

    {

        DoYell("杩欎笅鎴戝氨鏀惧績浜嗭紝淇濇姢涓栫晫鐨勯噸浠诲皢钀藉埌浣犱滑澶翠笂锛屾湅鍙嬩滑锛屽姞娌瑰惂銆傘€傘€俿",LANG_UNIVERSAL,NULL);  //这下我就放心了,保护世界的重任将落到你们头上,朋友们,加油吧。。。


        Phase = 1;              //Start in phase 1 开始第一阶段

        Phase_Timer = 60000;    //60 seconds

        Spell_1_Timer = 5000;  //5 seconds

        Spell_2_Timer = 37000;  //37 seconds

        Spell_3_Timer = 19000;  //19 seconds

        Spell_4_Timer = 15000;  //15 seconds

        Spell_5_Timer = 25000;  //25 seconds

        *eserk_Timer = 120000;  //2 minutes


        m_creature->SetUInt32Value(UNIT_FIELD_LEVEL,103);            //恢复级

        m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,11311 );        //恢复显示

        m_creature->SetFloatValue(O*JECT_FIELD_SCALE_X, 1);                //恢复大小

        m_creature->SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE,1350 * 30);  //恢复攻击力

        m_creature->SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE,1700 * 30);    //恢复攻击力

    }


    //*** HANDLED FUNCTION *** 

    //Attack Start is called whenever someone hits us.

    //受到攻击时开始触发

    void AttackStart(Unit *who)

    {

        if (!who)

            return;


        //Don't attack back if we already have a victim or of the person who hit us is untargettable

        //We have to say who!= m_creature because currently AoE that apply dots will trigger the creature into attack itself

        //Since AoEs casted by monsters hit themselves

        if (m_creature->getVictim() == NULL && who->isTargetableForAttack() && who != m_creature)

        {

            if(who->GetTypeId() == TYPEID_PLAYER)                              //是说明ID是不是攻击玩家

            {

                //debug_log("Kobold is casting spell on player %s",((Player*)who)->GetName());

            }

            else

            {

                //debug_log("Kobold is casting spell on creature");

            }

            //*egin attack

            //开始攻击

            DoStartMeleeAttack(who);


            //Say some stuff

            //说话

            DoSay(SAY_AGGRO,LANG_UNIVERSAL,NULL);

            //客户端的声音效果  可以查到大部份的ID

            //DoPlaySoundToSet(m_creature,8280);

        }

    }


    //*** HANDLED FUNCTION *** 

    //Move in line of sight is called whenever any unit moves within our sight radius (something like 50 yards)

    //当任何玩家进入怪物的视野范围,则会触发,大约50码

    void MoveInLineOfSight(Unit *who)

    {

        if (!who || m_creature->getVictim())

            return;


        //判断进入视野的生物是否同阵营(IsHostileTo)

        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);        //移除玩家身上的隐形魔法


                //*egin melee attack if we are within range

                //进入攻击范围则进行攻击

                if (m_creature->IsWithinDist(who, ATTACK_DIST))

                    DoStartMeleeAttack(who);

                else DoStartRangedAttack(who);


                //Say some stuff

                //说些话

                DoSay(SAY_AGGRO,LANG_UNIVERSAL,NULL);

                //对应的声音效果

                //DoPlaySoundToSet(m_creature,8280);

            }

        }

    }


    //*** HANDLED FUNCTION *** 

    //Update AI is called Every single map update (roughly once every 100ms if a player is within the grid)

    //大约100ms触发一次,调整怪物的AI

    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

        //*ut we still need to reset

        //如果无目标,则返回原位

        if (!m_creature->SelectHostilTarget())

        {

            Reset();

            return;

        }


        uint32 cHealth=m_creature->GetHealth();                                //获取怪物当前血量

        uint32 cMaxHealth=m_creature->GetMaxHealth();                        //获取怪物最大血量

        uint32 cPower=m_creature->GetPower(POWER_MANA);                        //获取怪物当前魔法量

        uint32 cMaxPower=m_creature->GetMaxPower(POWER_MANA);                //获取怪物最大魔法量


        //Out of combat timers

        //判断是否有被攻击者

        if (!m_creature->getVictim())

        {

            //Random Say timer

            if (Say_Timer < diff)

            {

                //Random switch between 5 outcomes

                //随机选择说话

                switch (rand()%5)

                {

                case 0:

                    DoYell(SAY_RANDOM_0,LANG_UNIVERSAL,NULL);

                    DoPlaySoundToSet(m_creature,8831); //8831 is the index of the sound we are playing. You find these numbers in SoundEntries.dbc

                    break;

                    

                case 1:

                    DoYell(SAY_RANDOM_1,LANG_UNIVERSAL,NULL);

                    DoPlaySoundToSet(m_creature,8818); 

                    break;


                case 2:

                    DoYell(SAY_RANDOM_2,LANG_UNIVERSAL,NULL);

                    DoPlaySoundToSet(m_creature,8041); 

                    break;


                case 3:

                    DoYell(SAY_RANDOM_3,LANG_UNIVERSAL,NULL);

                    DoPlaySoundToSet(m_creature,8581);

                    break;


                case 4:

                    DoYell(SAY_RANDOM_4,LANG_UNIVERSAL,NULL);

                    DoPlaySoundToSet(m_creature,8791); 

                    break;

                }


               //设置说话间隔时间

                Say_Timer = 45000; //Say something agian in 45 seconds

            }else Say_Timer -= diff;


            //Rebuff timer

            //为自己加*UFF

            if (Rebuff_Timer < diff)

            {

                DoCast(m_creature,SPELL_*UFF);

                Rebuff_Timer = 900000; //Rebuff agian in 15 minutes

            }else Rebuff_Timer -= diff;

        }


        //Check if we have a current target

        //重新检查当前目标

        //isAlive判断目标是否还活着

        if( m_creature->getVictim() && m_creature->isAlive())

        {

            //Check if we should stop attacking because our victim is no longer in range or we are to far from spawnpoint

            //检查是否超出控制范围太远,如果是则返回原点

            if (CheckTether())

            {

                Reset();

                return;

            }




            //不同阶段的AI

            switch(Phase)

            {

                case 1 :

                    //Spell 1 timer

                    if (Spell_1_Timer < diff)

                    {

                        DoFaceTarget(m_creature->getVictim());


                        //Cast spell one on our current target.

                        //80%的机率施入一个XX法术

                        if (rand()%50 > 10)

                        {

                            DoYell("濂ョ垎",LANG_UNIVERSAL,NULL);

                            DoCast(m_creature->getVictim(),25672);        //奥爆

                        }

                        else 

                        {

                            //20%的机率施放另一个法术

                            if (m_creature->GetDistanceSq(m_creature->getVictim()) < 250)

                            {

                                DoYell("鍌寲",LANG_UNIVERSAL,NULL);

                                DoCast(m_creature->getVictim(),25187);        //催化

                            }

                        }


                        Spell_1_Timer = 5000;

                    }else Spell_1_Timer -= diff;


                    //Spell 2 timer

                    if (Spell_2_Timer < diff)

                    {

                        //Cast spell one on our current target.

                        //

                        DoYell("鏃堕棿娴侀€",LANG_UNIVERSAL,NULL);

                        DoCast(m_creature->getVictim(),23310);            //时间流逝


                        Spell_2_Timer = 37000;

                    }else Spell_2_Timer -= diff;


                    break;


                case 2:

                    if (Spell_2_Timer < diff)

                    {

                        //Cast spell one on our current target.

                        //

                        DoYell("閲嶅帇鎵撳嚮",LANG_UNIVERSAL,NULL);

                        DoCast(m_creature->getVictim(),26613);            //重压打击


                        Spell_2_Timer = 37000;

                    }else Spell_2_Timer -= diff;


                    if (Spell_3_Timer < diff)

                    {

                        //Cast spell one on our current target.

                        DoYell("杩炲彂瀵掑啺绠",LANG_UNIVERSAL,NULL);

                        DoCast(m_creature->getVictim(),22643);        //连发寒冰箭


                        Spell_3_Timer = 14000;

                    }else Spell_3_Timer -= diff;

                    break;


                case 3:

                    //

                    //if((rand()%20) > 15)

                    //{

                    //    DoYell("鑽嗘鏈",LANG_UNIVERSAL,NULL);

                    //    //DoCast(m_creature->getVictim(),21139); //吐息术,强23000+伤害

                    //    DoCast(m_creature->getVictim(),25059);        //荆棘术

                    //}

                    //else

                    //{

                        if (*eserk_Timer < diff)

                        {

                            //Say our line then cast uber death spell

                            DoYell("鍏嶇柅",LANG_UNIVERSAL,NULL);

                            DoPlaySoundToSet(m_creature,8588);

                            //DoYell(SAY_*ESERK,LANG_UNIVERSAL,m_creature->getVictim());

                            DoCast(m_creature,25282);        //免疫  对怪自身使用


                            //Cast our beserk spell agian in 12 seconds if we didn't kill everyone

                            *eserk_Timer = 12000;

                        }else *eserk_Timer -= diff;


                        if (Spell_4_Timer < diff)

                        {

                            DoYell("鏆楀奖杩烽浘",LANG_UNIVERSAL,NULL);

                            DoCast(m_creature->getVictim(),23224);            //暗影迷雾

                            Spell_4_Timer = 15000;

                        }else Spell_4_Timer -= diff;


                        if (Spell_5_Timer < diff)

                        {

                            DoYell("姘存櫠闂",LANG_UNIVERSAL,NULL);

                            DoCast(m_creature->getVictim(),5106);  //水晶闪耀

                            Spell_5_Timer = 25000;

                        }else Spell_5_Timer -= diff;

                    //}


                    break;

            }


            //如果血少于80% 进入第二阶段

            if (Phase == 1)

                if( cHealth<(cMaxHealth*0.8) )

                {

                    Phase++;

                    //大叫

                    DoYell(SAY_PHASE,LANG_UNIVERSAL,NULL);

                    //进入狂怒模式

                    //DoCast(m_creature,SPELL_ENRAGE);

                }


            //如果血少于50% 进入第三阶段

            if (Phase == 2)

                if( cHealth<(cMaxHealth*0.5) )

                {

                    Phase++;

                    //大叫

                    DoYell(SAY_PHASE2,LANG_UNIVERSAL,NULL);


                    //变身

                    m_creature->SetName("无间魔道");

                    m_creature->SetUInt32Value(UNIT_FIELD_LEVEL,m_creature->getLevel()+3);            //升级 

                    m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID,7029 );        //改变显示

                    m_creature->SetFloatValue(O*JECT_FIELD_SCALE_X, 4);            //改变大小

                    m_creature->SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE,1350 * 40);  //增强攻击力 可以考虑每死一次就增加攻击力

                    m_creature->SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE,1700 * 40);    //增强攻击力


                    //进入狂怒模式

                    DoCast(m_creature,SPELL_ENRAGE);


                }


            //If we are within range melee the target

            if( m_creature->getVictim() && m_creature->IsWithinDist(m_creature->getVictim(), ATTACK_DIST))

            {

                //Check if our attack is ready (swing timer)

                if( m_creature->isAttackReady() )

                {

                    //This here causes us to flip between targets.

                    //It doesn't do very much right now but it is a decent placeholder

                    //for when we get an aggro system in place


                    //Send our melee swing and then reset our attack timer

                    m_creature->AttackerStateUpdate(m_creature->getVictim());

                    m_creature->resetAttackTimer();

                }

            }

        }

    }

}; 





//This is the GetAI method used by all scripts that involve AI

//It is called every time a new creature using this script is created

CreatureAI* GetAI_myboss_test(Creature *_Creature)

{

    return new myboss_testAI (_Creature);

}


//This function is called when the player clicks an option on the gossip menu

void SendDefaultMenu_myboss_test(Player *player, Creature *_Creature, uint32 action)

{

    if (action == GOSSIP_ACTION_INFO_DEF + 1)//Fight time

    {

        //Set our faction to hostile twoards all

        _Creature->setFaction(24);

        _Creature->Attack(player);

        player->PlayerTalkClass->CloseGossip();

    }

}


//This function is called when the player clicks an option on the gossip menu

bool GossipSelect_myboss_test(Player *player, Creature *_Creature, uint32 sender, uint32 action )

{

    if (sender == GOSSIP_SENDER_MAIN)

        SendDefaultMenu_myboss_test(player, _Creature, action);


    return true;

}


//This function is called when the player opens the gossip menu

bool GossipHello_myboss_test(Player *player, Creature *_Creature)

{

    player->ADD_GOSSIP_ITEM( 0, GOSSIP_ITEM        , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);

    player->PlayerTalkClass->SendGossipMenu(907,_Creature->GetGUID());


    return true;

}


//Our Recive emote function

bool ReciveEmote_myboss_test(Player *player, Creature *_Creature, uint32 emote)

{

    _Creature->HandleEmoteCommand(emote);


    if (emote == EMOTE_STATE_DANCE)

        ((myboss_testAI&)_Creature->AI()).DoSay(SAY_DANCE,LANG_UNIVERSAL,NULL);


    if (emote == EMOTE_ONESHOT_SALUTE)

        ((myboss_testAI&)_Creature->AI()).DoSay(SAY_SALUTE,LANG_UNIVERSAL,NULL);


    return true;

}



//This is the actual function called only once durring InitScripts()

//It must define all handled functions that are to be run in this script

//For example if you want this Script to handle Emotes you must include

//newscript->ReciveEmote = My_Emote_Function;

void AddSC_myboss_test()

{

    Script *newscript;

    newscript = new Script;

    newscript->Name="myboss_test";

    newscript->GetAI = GetAI_myboss_test;

    newscript->pGossipHello = &GossipHello_myboss_test;

    newscript->pGossipSelect = &GossipSelect_myboss_test;

    newscript->pReceiveEmote = &ReciveEmote_myboss_test;


    m_scripts[nrscripts++] = newscript;

}