>>>А вообще странно, что этот скрипт делает в коде - ему самое место в EventAI - там это легко реализуется.
наверно, такой фичи в ЕвентАИ еще не было тогда. А вообщем, НоФантази сказал, что если скрипт легко сделать через ЕвентАИ - то делайте и не заморачивайтесь.
Продолжу мануал по скриптам, в более общем виде (опять по примеру, который можна сделать и через ЕвентАИ).
- Код:
struct MANGOS_DLL_DECL boss_spiritlynxAI : public ScriptedAI
{
boss_spiritlynxAI(Creature* pCreature) : ScriptedAI(pCreature)
{
pInstance = ((ScriptedInstance*)pCreature->GetInstanceData());
Reset();
}
ScriptedInstance* pInstance;
uint32 uiFrenzyTimer;
uint32 uiShredArmorTimer;
void Reset()
{
uiFrenzyTimer = (10+rand()%10)*1000; //first frenzy after 10-20 seconds
uiShredArmorTimer = 4000;
}
void EnterCombat(Unit* pWho)
{
DoZoneInCombat();
}
void KilledUnit(Unit* pVictim)
{
if (!pInstance)
return;
if (Creature* pHalazzi = ((Creature*)Unit::GetUnit(*m_creature, pInstance->GetData64(DATA_HALAZZI))))
((boss_halazziAI*)pHalazzi->AI())->KilledUnit(pVictim);
}
void UpdateAI(const uint32 uiDiff)
{
if (!m_creature->SelectHostilTarget() || !m_creature->getVictim())
return;
if (uiFrenzyTimer < uiDiff)
{
DoCast(m_creature, SPELL_LYNX_FRENZY);
uiFrenzyTimer = (20+rand()%10)*1000; //subsequent frenzys casted every 20-30 seconds
}
else
uiFrenzyTimer -= uiDiff;
if (uiShredArmorTimer < uiDiff)
{
DoCast(m_creature->getVictim(), SPELL_SHRED_ARMOR);
uiShredArmorTimer = 4000;
}
else
uiShredArmorTimer -= uiDiff;
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI_boss_spiritlynxAI(Creature* pCreature)
{
return new boss_spiritlynxAI (pCreature);
}
void AddSC_boss_halazzi()
{
Script* newscript;
newscript = new Script;
newscript->Name = "boss_halazzi";
newscript->GetAI = &GetAI_boss_halazzi;
newscript->RegisterSelf();
newscript = new Script;
newscript->Name = "boss_spiritlynx";
newscript->GetAI = &GetAI_boss_spiritlynxAI;
newscript->RegisterSelf();
}
boss_spiritlynxAI(Creature* pCreature) : ScriptedAI(pCreature) - конструктор класса. Тоесть, все что записано в конструкторе выполнится
единожды за время существования кричера. Обязателен
void Reset() - тут мы устанавливаем дефолтные значения (таймеры и прочая лабудень). Пример: моб создался - установили дефолт, моб заагрился и вышел из боя - установили дефолт, моб умер - установили дефолт (да да, если моб создается сразу мертвым, мы можем попасть в эту ф-ию и сделать необходимые нам проверки)
void EnterCombat(Unit* pWho) - (бывшая Aggro(Unit *who)) ф-ия вызывается при аггро игрока (или моба), который и передается через параметр.Не вызывается при смене игроков, только один раз за бой. Если был передан игрок - то можем делать так:
if (who->GetTypeId() == TYPEID_PLAYER)
((Player*)who)->DoSomeThing();
DoZoneInCombat() - заставить всех игроков вокруг моба войти в бой с этим мобом
void KilledUnit(Unit* pVictim) - комментарии лишние
void UpdateAI(const uint32 uiDiff) - очень важная ф-ия. Позволяет мобу делать что-то по таймерам и событиям. Вызывается постоянно, через каждые
uiDiff миллисекунд. В данном примере показаны реализации двух таймеров.
Важная часть, о которой не упомянул админчеГ. Чтоб скрипт заработал, его нужно зарегистрировать. Если вы дописываете скрипт в уже существующий файл, то вконце как правило есть ф-ия
void AddSC_blabla_bla() . В нее мы и регистрируем скрипт по примеру выше. Если же вы пишете совсем новый скрипт в совсем новом файле (типу новые инсты ВотЛКа скриптуете) - то этого недостаточно. Необходимо потом включить вашу ф-ию
void AddSC_blabla_bla() в основной файл - ScriptMgr.cpp. Делаеться просто - вставляем строчку
AddSC_blabla_bla(); где-нибудь между подобных, а также строчку
extern void AddSC_blabla_bla(); между подобных. Все.
Очень просто изучать скрипты, рассматривая уже готовые. Благо их очень много и много разнообразных. Как идеал, смотрите скрипт Иллидана - там реализованы почти все возможности скриптов.
Ну и весь список дополнительных функций в сриптдеве (взято из файла sc_creature.h), если нужны русские каменты - пишите:
- Код:
//*************
//CreatureAI Functions
//*************
//Определяет, видимый ли игрок мобу. Сдесь можно вставить проверку на стелс, на расстояние и тп..
bool IsVisible(Unit *who) const;
//Вызывается каждый раз, когда предыдущая ф-ия возвращает значение true
void MoveInLineOfSight(Unit *);
//Called at each attack of m_creature by any victim
void AttackStart(Unit *);
// Вызывается при аггро моба, единожды за бой
void EnterCombat(Unit *);
// Ивейд моба, то есть нету больше целей и выход из боя
void EnterEvadeMode();
//Called at any heal cast/item used (call non implemented in mangos)
void HealBy(Unit *healer, uint32 amount_healed) {}
// Вызывается каждый раз, когда моб наносит удар врагу. Вызывается ДО реального нанесения урона, поэтому сдесь можна подредактировать урон
void DamageDeal(Unit *done_to, uint32 &damage) {}
// Аналогично, если кто-то бьет по мобу
void DamageTaken(Unit *done_by, uint32 &damage) {}
// Вызывается при каждом обновлении мира, главная
void UpdateAI(const uint32);
// Вызывается ПЕРЕД смертью моба
void JustDied(Unit*){}
//Called at creature killing another unit
void KilledUnit(Unit*){}
// Если вы использовали SummonCreature(), то сдесь можна инициализовать суммона, вызывается при каждом суммоне
void JustSummoned(Creature* ) {}
// Called when a summoned creature is despawned
void SummonedCreatureDespawn(Creature* /*unit*/) {}
// Called when hit by a spell
void SpellHit(Unit*, const SpellEntry*) {}
// Called when creature is spawned or respawned (for reseting variables)
void JustRespawned();
//Called at waypoint reached or PointMovement end
void MovementInform(uint32, uint32){}
//*************
// Variables
//*************
//*************
//Pure virtual functions
//*************
// Если существо только респаунилось, только что ивейдилось, только-что умерло - вызывается эта ф-ия, установка дефолтных значений
virtual void Reset() = 0;
//*************
//AI Helper Functions
//*************
//Start movement toward victim
void DoStartMovement(Unit* victim, float distance = 0, float angle = 0);
//Start no movement on victim
void DoStartNoMovement(Unit* victim);
// Эта ф-ия делает мили удары. Как правило, нужно вставлять в void UpdateAI(const uint32); чтоб било постоянно, но можна и убрать. Тогда моб не будет физ демажить
void DoMeleeAttackIfReady();
//Stop attack of current victim
void DoStopAttack();
//Cast spell by Id
void DoCast(Unit* victim, uint32 spellId, bool triggered = false);
//Cast spell by spell info
void DoCastSpell(Unit* who,SpellEntry const *spellInfo, bool triggered = false);
//Plays a sound to all nearby players
void DoPlaySoundToSet(Unit* unit, uint32 sound);
//Places the entire map into combat with creature
void DoZoneInCombat(Unit* pUnit = 0);
//Drops all threat to 0%. Does not remove players from the threat list
void DoResetThreat();
//Teleports a player without dropping threat (only teleports to same map)
void DoTeleportPlayer(Unit* pUnit, float x, float y, float z, float o);
//Returns friendly unit with the most amount of hp missing from max hp
Unit* DoSelectLowestHpFriendly(float range, uint32 MinHPDiff = 1);
//Returns a list of friendly CC'd units within range
std::list DoFindFriendlyCC(float range);
//Returns a list of all friendly units missing a specific buff within range
std::list DoFindFriendlyMissingBuff(float range, uint32 spellid);
// Функция суммонинга
Creature* DoSpawnCreature(uint32 id, float x, float y, float z, float angle, uint32 type, uint32 despawntime);
// Выбрать юнита. Можно выбрать рандомного, топаггро, самый маленький аггро
Unit* SelectUnit(SelectAggroTarget target, uint32 position);
//Returns spells that meet the specified criteria from the creatures spell list
SpellEntry const* SelectSpell(Unit* Target, int32 School, int32 Mechanic, SelectTarget Targets, uint32 PowerCostMin, uint32 PowerCostMax, float RangeMin, float RangeMax, SelectEffect Effect);
//Checks if you can cast the specified spell
bool CanCast(Unit* Target, SpellEntry const *Spell, bool Triggered = false);
void SetEquipmentSlots(bool bLoadDefault, int32 uiMainHand = EQUIP_NO_CHANGE, int32 uiOffHand = EQUIP_NO_CHANGE, int32 uiRanged = EQUIP_NO_CHANGE);
void SetSheathState(SheathState newState);
void SetCombatMovement(bool bCombatMove);
Последний раз редактировалось: danbst (Пт Май 08, 2009 12:46 am), всего редактировалось 1 раз(а)