转贴的一个AI脚本
这个脚本主要用于测试,*OSS的攻击分三个阶段,根据生命值的百分比进入各个阶段,各阶段会使用不同的魔法,进入第三阶段时会变身(具体包括增强攻击力、提升自己的等级、变成另一个怪物模样、体型增大4倍),并进入狂怒模式。并且当死亡或退出战斗后,会恢复原有的显示大小及相关属性。
这个脚本给大伙做个参考,如果你也会用C++编写mangos的程序,欢迎加入我的群一起交流,号码是:41526014
//*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;
}
爱东东
我的各类资源收集收集网站 http://tag.iddgame.com
我的实验性技术网站 http://www.iddgame.com
我的魔兽世界网站 http://www.iddwow.com.cn