NWoW Scripts - Core AI Updates
NWOW Developments - Fourth MMOwned Release
Hello there MMOwned! I am a representative from NWoW Developments, a new project team that will soon be bringing you everything from repacks and databases to content management systems (CMS) and forum skins! We are a quality developing group that was initated by an old MMOwned member, who has since left us, but we are now coming back to our roots!
Our team is made up of over 30 quality developers, ranging from C++, C#, and LUA scripters to Database and SQL Managers, and to web designers and php coders that have been involved in some of the web's most high profile design projects.
Well, enough with the ego boosting!
This is a small collection of scripts designed by our lead C++ team coder, Saldebanch. Saldebanch, when looking through Ascent's core, discovered numerous issues with the way AI Updates work. Here are some small scripts to aid with Blizzlike AI Updating. There are a few scritps here, each dealing with different issues. Enjoy!
Script:
Code:
#include "StdAfx.h"
#include "Setup.h"
/// Define NPC constants
#define GUARDIAN_OVERSEER 7000002
#define GUARDIAN_DEATHKNIGHT 7000003
#define ENEMY_TAROBAN 7000000
#define ENEMY_AGONYCASTER 7000001
#define ENEMY_VOIDZONE 16697
#define ADD_SCARLET_MELEE 7000004
#define ADD_SCARLET_MAGE 7000005
#define ADD_SCARLET_PRIEST 7000006
#define ADD_CRYPT_BEAST 7000007
#define ADD_AELTH_PRIEST 7000008
#define ALLIANCE_JOHN 8000000
#define ALLIANCE_ERIC 8000001
#define ALLIANCE_GERARD 8000004
/// Define Portal constants
#define PORTAL_DUSKWOOD 5000009
#define PORTAL_DARKROOM 5000010
#define PORTAL_TAROBAN 5000011
/// Define Game Object constants
#define GAMEOBJECT_KEEPERSTONE 19595
/// Define Spell constants
#define SPELL_RAINOFFIRE 34360
#define SPELL_VOIDZONE 46264
///Emote
#define EMOTE_STATE_2H_READY 375
int timerDarkroom, timerTaroban, timerGuardian, voidTimer, addsDead, addPhase, phase;
bool guardianSpawned, sSpawnDarkroom, sSpawnTaroban, spawnAdds;
/// Guardian spawn Location
float GUARDIAN_X = -10230.639648f;
float GUARDIAN_Y = 266.612091f;
float GUARDIAN_Z = 2.799766f;
float GUARDIAN_ORIENTATION = 4.858474f;
/// Portal Adds Location
float ADD_X = -10241.700195f;
float ADD_Y = 163.470001f;
float ADD_Z = 0.047488f;
class TarobanAI : public CreatureAIScript
{
public:
ADD_CREATURE_FACTORY_FUNCTION(TarobanAI);
SP_AI_Spell spells[1];
bool m_spellcheck[1];
TarobanAI(Creature* pCreature) : CreatureAIScript(pCreature)
{
nrspells = 1;
for(int i = 0; i < nrspells; i++)
m_spellcheck[i] = false;
spells[0].info = dbcSpell.LookupEntry(SPELL_RAINOFFIRE);
spells[0].targettype = TARGET_RANDOM_DESTINATION;
spells[0].instant = true;
spells[0].perctrigger = 15.0f;
spells[0].attackstoptimer = 1000;
spells[0].cooldown = 10;
spells[0].mindist2cast = 0.0f;
spells[0].maxdist2cast = 30.0f;
_unit->GetAIInterface()->setOutOfCombatRange(50000);
//_unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_9);
//_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 0);
_unit->GetAIInterface()->m_canMove = false;
}
void ResetCastTime()
{
for (int i = 0; i < nrspells; i++)
spells[i].casttime = spells[i].cooldown;
}
void OnCombatStart(Unit* mTarget)
{
ResetCastTime();
Script:
Code:
timerDarkroom = 30;
//timerTaroban is set at Darkroom portal spawn
voidTimer = 10;
phase = 1;
addPhase = 1;
addsDead = 0;
spawnAdds = false;
guardianSpawned = false; // spawn guardians once
sSpawnDarkroom = false; // don't stop spawning portals
sSpawnTaroban = false; // don't stop spawning portals
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_2H_READY);
//int updateTimer = rand()%1000+1000; //lolol randomness
RegisterAIUpdateEvent(1000);
//RegisterAIUpdateEvent(_unit->GetUInt32Value(UNIT_FIELD_BASEATTACKTIME));
}
void OnCombatStop(Unit *mTarget)
{
ResetCastTime();
//RemoveAIUpdateEvent();
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
}
void OnTargetDied(Unit* mTarget)
{
}
void OnDied(Unit * mKiller)
{
ResetCastTime();
//RemoveAIUpdateEvent();
}
void AIUpdateEvent()
{
if(timerGuardian != 0)
{
timerGuardian--;
}
else
{
int spawnGuardian = rand()%1+1;
switch(spawnGuardian)
{
case 0:
{
_unit->GetMapMgr()->GetInterface()->SpawnCreature(GUARDIAN_OVERSEER, GUARDIAN_X, GUARDIAN_Y, GUARDIAN_Z, GUARDIAN_ORIENTATION, false, false, 0, 0); // fill
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "Abandon all hope!"); // fill
}break;
case 1:
{
_unit->GetMapMgr()->GetInterface()->SpawnCreature(GUARDIAN_DEATHKNIGHT, GUARDIAN_X, GUARDIAN_Y, GUARDIAN_Z, GUARDIAN_ORIENTATION, false, false, 0, 0); // fill
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "You are not worth living!"); // fill
}break;
default: // prevent errors?
{
spawnGuardian = 1;
}break;
}
guardianSpawned = true;
}
if(timerDarkroom != 0)
{
timerDarkroom--;
}
else if( !sSpawnDarkroom )
{
int spawnPortal = rand()%5+1;
switch(spawnPortal)
{
case 0:
_unit->GetMapMgr()->GetInterface()->SpawnGameObject(PORTAL_DARKROOM, -10251.000000f, 180.580994f, 1.259120f, 5.322640f, false, 0, 0);
break;
case 1:
_unit->GetMapMgr()->GetInterface()->SpawnGameObject(PORTAL_DARKROOM, -10230.965820f, 179.672073f, 0.765837f, 4.490121f, false, 0, 0);
break;
case 2:
_unit->GetMapMgr()->GetInterface()->SpawnGameObject(PORTAL_DARKROOM, -10227.690430f, 165.147598f, 0.046790f, 3.009644f, false, 0, 0);
break;
case 3:
_unit->GetMapMgr()->GetInterface()->SpawnGameObject(PORTAL_DARKROOM, -10238.645508f, 151.660599f, 0.942535f, 1.964280f, false, 0, 0);
break;
case 4:
_unit->GetMapMgr()->GetInterface()->SpawnGameObject(PORTAL_DARKROOM, -10253.818359f, 153.165939f, 0.282296f, 0.006094f, false, 0, 0);
break;
case 5:
_unit->GetMapMgr()->GetInterface()->SpawnGameObject(PORTAL_DARKROOM, -10268.699219f, 161.929733f, 0.563954f, 56.260408f, false, 0, 0);
break;
};
sSpawnDarkroom = true; // Guardian death returns it back to FALSE
}
if(timerTaroban != 0 )
{
timerTaroban--;
}
else if( !sSpawnTaroban )
{
_unit->GetMapMgr()->GetInterface()->SpawnGameObject(PORTAL_TAROBAN, -10225.779297f, 245.429855f, 2.79935f, 56.260408f, false, 0, 0);
GameObject* tarobanPortal = _unit->GetMapMgr()->GetInterface()->GetGameObjectNearestCoords(-10225.779297f, 245.429855f, 2.79935f, PORTAL_TAROBAN);
tarobanPortal->Despawn(6000);
sSpawnTaroban = true;
}
/*if(timerEnrage != 0 )
{
timerEnrage--;
}
else
{
_unit->CastSpell(_unit, SPELL_ENRAGE, true);
_unit->SendChatMessage(); // fill
}*/
if(spawnAdds)
addSpawning();
if(addsDead == 5)
{
//Something happends
}
float val = (float)RandomFloat(100.0f);
SpellCast(val);
Script:
Code:
void addSpawning()
{
if(spawnAdds)
{
int chooseAdd[10];
if(addPhase != 2)
{
chooseAdd[0] = ADD_SCARLET_MELEE;
chooseAdd[1] = ADD_SCARLET_MAGE;
chooseAdd[2] = ADD_SCARLET_PRIEST;
}
else
{
chooseAdd[0] = ADD_CRYPT_BEAST;
chooseAdd[1] = ADD_AELTH_PRIEST;
}
if(addPhase == 3)
{
chooseAdd[0] = ADD_SCARLET_MELEE;
chooseAdd[1] = ADD_SCARLET_MAGE;
chooseAdd[2] = ADD_SCARLET_PRIEST;
chooseAdd[3] = ADD_CRYPT_BEAST;
chooseAdd[4] = ADD_AELTH_PRIEST;
}
for(int i = 0; i < 5; i++)
{
// spread them
ADD_X += 2;
ADD_Y += 2;
//randomly choose adds
chooseAdd[i] = rand()%2;
_unit->GetMapMgr()->GetInterface()->SpawnCreature(chooseAdd[i], ADD_X, ADD_Y, ADD_Z, 0.000000f, false, false, 0, 0); // fill
}
spawnAdds = false;
}
}
void phaseOne()
{
}
void phaseTwo()
{
}
void phaseThree()
{
}
void SpellCast(float val)
{
if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
{
float comulativeperc = 0;
Unit *target = NULL;
for(int i = 0; i < nrspells; i++)
{
if(!spells[i].perctrigger) continue;
if(m_spellcheck[i])
{
target = _unit->GetAIInterface()->GetNextTarget();
switch(spells[i].targettype)
{
case TARGET_SELF:
case TARGET_VARIOUS:
_unit->CastSpell(_unit, spells[i].info, spells[i].instant); break;
case TARGET_ATTACKING:
_unit->CastSpell(target, spells[i].info, spells[i].instant); break;
case TARGET_DESTINATION:
_unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break;
case TARGET_RANDOM_FRIEND:
case TARGET_RANDOM_SINGLE:
case TARGET_RANDOM_DESTINATION:
CastSpellOnRandomTarget(i, spells[i].mindist2cast, spells[i].maxdist2cast); break;
}
m_spellcheck[i] = false;
return;
}
uint32 t = (uint32)time(NULL);
if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger) && t > spells[i].casttime)
{
_unit->setAttackTimer(spells[i].attackstoptimer, false);
spells[i].casttime = t + spells[i].cooldown;
m_spellcheck[i] = true;
}
comulativeperc += spells[i].perctrigger;
}
}
}
void CastSpellOnRandomTarget(uint32 i, float mindist2cast, float maxdist2cast)
{
if (!maxdist2cast) maxdist2cast = 100.0f;
Unit* RandomTarget = NULL;
std::vector<Unit*> TargetTable; /* From M4ksiu - Big THX to Capt who helped me with std stuff to make it simple and fully working <3 */
/* If anyone wants to use this function, then leave this note! */
for(set<Object*>::iterator itr = _unit->GetInRangeSetBegin(); itr != _unit->GetInRangeSetEnd(); ++itr)
{
if (isHostile(_unit, (*itr)) && ((*itr)->GetTypeId()== TYPEID_UNIT || (*itr)->GetTypeId() == TYPEID_PLAYER))
{
RandomTarget = (Unit*)(*itr);
if (RandomTarget->isAlive() && _unit->GetDistance2dSq(RandomTarget) >= mindist2cast*mindist2cast && _unit->GetDistance2dSq(RandomTarget) <= maxdist2cast*maxdist2cast)
TargetTable.push_back(RandomTarget);
}
}
if (!TargetTable.size())
return;
Unit * RTarget = *(TargetTable.begin()+rand()%TargetTable.size());
if (!RTarget)
return;
switch (spells[i].targettype)
{
case TARGET_RANDOM_SINGLE:
_unit->CastSpell(RTarget, spells[i].info, spells[i].instant); break;
case TARGET_RANDOM_DESTINATION:
_unit->CastSpellAoF(RTarget->GetPositionX(), RTarget->GetPositionY(), RTarget->GetPositionZ(), spells[i].info, spells[i].instant); break;
}
TargetTable.clear();
}
protected:
int nrspells;
};
#define SPELL_MANARESTORE 8358
#define SPELL_SEALOFCOMMAND 33127
#define SPELL_JUDGEMENT 33554
#define SPELL_DIVINESHIELD 1020
#define SPELL_HOLYLIGHT 43451
#define SPELL_PROTECTION 10278
#define SPELL_BLESSINGS 20217
#define SPELL_TAUNT 29060
int judgementTimer, divineshieldTimer, protectionTimer, healTimer;
class JohnAI : public CreatureAIScript
{
public:
ADD_CREATURE_FACTORY_FUNCTION(JohnAI);
SP_AI_Spell spells[2];
bool m_spellcheck[2];
JohnAI(Creature* pCreature) : CreatureAIScript(pCreature)
{
nrspells = 2;
for(int i = 0; i < nrspells; i++)
m_spellcheck[i] = false;
spells[0].info = dbcSpell.LookupEntry(SPELL_MANARESTORE);
spells[0].targettype = TARGET_SELF;
spells[0].instant = true;
spells[0].perctrigger = 60.0f;
spells[0].attackstoptimer = 0;
spells[0].cooldown = 10;
Script:
Code:
spells[1].info = dbcSpell.LookupEntry(SPELL_TAUNT);
spells[1].targettype = TARGET_ATTACKING;
spells[1].instant = true;
spells[1].perctrigger = 15.0f;
spells[1].attackstoptimer = 0;
spells[1].cooldown = 10;
_unit->GetAIInterface()->setOutOfCombatRange(50000);
//_unit->SetUInt64Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_9);
//_unit->GetAIInterface()->SetAllowedToEnterCombat(false);
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
_unit->SetUInt32Value(UNIT_FIELD_BYTES_2, 0);
//_unit->GetAIInterface()->m_canMove = false;
}
void ResetCastTime()
{
for (int i = 0; i < nrspells; i++)
spells[i].casttime = spells[i].cooldown;
}
void OnCombatStart(Unit* mTarget)
{
ResetCastTime();
healTimer = 0;
judgementTimer = 10;
divineshieldTimer = 300; // CD ready
protectionTimer = 300; // CD ready
_unit->CastSpell(_unit, SPELL_SEALOFCOMMAND, true);
_unit->GetAIInterface()->m_canMove = true;
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_2H_READY);
RegisterAIUpdateEvent(_unit->GetUInt32Value(UNIT_FIELD_BASEATTACKTIME));
}
void OnCombatStop(Unit *mTarget)
{
ResetCastTime();
//RemoveAIUpdateEvent();
_unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
}
void OnTargetDied(Unit* mTarget)
{
}
void OnDied(Unit * mKiller)
{
ResetCastTime();
//RemoveAIUpdateEvent();
}
void AIUpdateEvent()
{
if(judgementTimer != 0)
{
judgementTimer--;
}
else
{
_unit->CastSpell(_unit->GetAIInterface()->GetNextTarget(), SPELL_JUDGEMENT, true);
judgementTimer = 10;
}
///reset Seal of Command on aura loss
if( !_unit->FindAura(20424) ) // seal of command buff
_unit->CastSpell(_unit, SPELL_SEALOFCOMMAND, true);
if(_unit->GetHealthPct() <= 10 && divineshieldTimer == 300)
{
healTimer++;
switch(healTimer)
{
case 0: // so he casts it right away when he reaches 10% health, not with a 1 second delay.
{
_unit->CastSpell(_unit, SPELL_DIVINESHIELD, true);
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "This trick will only last one time soldiers, I will help myself for now!"); /// fill
divineshieldTimer = 0;
}break;
case 1:
{
_unit->CastSpell(_unit, SPELL_HOLYLIGHT, false);
_unit->GetAIInterface()->StopMovement(2000);
_unit->setAttackTimer(2000, false);
}break;
case 3:
{
_unit->RemoveAura(1020); // divine shield buff id
healTimer = 0;
}break;
}
}
if(divineshieldTimer != 300)
divineshieldTimer++;
if( protectionTimer >= 300 && _unit->CombatStatus.IsInCombat() ) // don't ****ing cast on newbs, running by with low health
{
for( set<Object*>::iterator itr = _unit->GetInRangeSetBegin(); itr != _unit->GetInRangeSetEnd(); ++itr )
{
if( !isHostile(_unit, (*itr)) )
{
if( (*itr)->IsPlayer() && ((Player*)(*itr))->isAlive() && ((Player*)(*itr))->GetHealthPct() <= 25 && ((Player*)(*itr))->isInRange(_unit->GetAIInterface()->GetNextTarget(), 30.0) )
{
_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "TAKE COVER!");
_unit->CastSpell(((Player*)(*itr)), SPELL_PROTECTION, true);
protectionTimer = 0;
return;
}
}
}
}
}
void SpellCast(float val)
{
if(_unit->GetCurrentSpell() == NULL && _unit->GetAIInterface()->GetNextTarget())
{
float comulativeperc = 0;
Unit *target = NULL;
for(int i=0;i<nrspells;i++)
{
if(!spells[i].perctrigger) continue;
if(m_spellcheck[i])
{
target = _unit->GetAIInterface()->GetNextTarget();
switch(spells[i].targettype)
{
case TARGET_SELF:
case TARGET_VARIOUS:
_unit->CastSpell(_unit, spells[i].info, spells[i].instant); break;
case TARGET_ATTACKING:
_unit->CastSpell(target, spells[i].info, spells[i].instant); break;
case TARGET_DESTINATION:
_unit->CastSpellAoF(target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(), spells[i].info, spells[i].instant); break;
//case TARGET_RANDOM_SINGLE:
/*case TARGET_RANDOM_DESTINATION:
CastSpellOnRandomTarget(i, spells[i].mindist2cast, spells[i].maxdist2cast, spells[i].minhp2cast, spells[i].maxhp2cast); break; */
}
m_spellcheck[i] = false;
return;
}
if(val > comulativeperc && val <= (comulativeperc + spells[i].perctrigger))
{
_unit->setAttackTimer(spells[i].attackstoptimer, false);
m_spellcheck[i] = true;
}
comulativeperc += spells[i].perctrigger;
}
}
}
protected:
Player * Plr;
int nrspells;
};
void SetupTaroban(ScriptMgr * mgr)
{
mgr->register_creature_script(ALLIANCE_JOHN, &JohnAI::Create);
mgr->register_creature_script(ENEMY_TAROBAN, &TarobanAI::Create);
I don't know what any of this does.. I just post what is posted in our "MMOwned Queue". >.<