*Better mob ai for quest an end to all things.
--HG-- branch : trunk
This commit is contained in:
@@ -115,9 +115,9 @@ UPDATE `gameobject_template` SET `ScriptName`='go_inconspicuous_mine_car' WHERE
|
|||||||
UPDATE `creature_template` SET `ScriptName`='npc_scarlet_miner_cart' WHERE (`entry`='28817');
|
UPDATE `creature_template` SET `ScriptName`='npc_scarlet_miner_cart' WHERE (`entry`='28817');
|
||||||
UPDATE `creature_template` SET `ScriptName`='npc_scarlet_miner' WHERE (`entry`='28841');
|
UPDATE `creature_template` SET `ScriptName`='npc_scarlet_miner' WHERE (`entry`='28841');
|
||||||
UPDATE `creature_template` SET `ScriptName`='npc_crusade_persuaded' WHERE `entry` IN (28939,28940,28610);
|
UPDATE `creature_template` SET `ScriptName`='npc_crusade_persuaded' WHERE `entry` IN (28939,28940,28610);
|
||||||
|
|
||||||
UPDATE `creature_template` SET `ScriptName`='mob_scarlet_courier' WHERE `entry`='29076';
|
UPDATE `creature_template` SET `ScriptName`='mob_scarlet_courier' WHERE `entry`='29076';
|
||||||
update creature_template set scriptname="mob_anti_air" where entry in (29102,29103,29104);
|
update creature_template set AIName = 'ArchorAI', scriptname='' where entry in (29102,29103);
|
||||||
|
update creature_template set AIName = 'TurretAI', scriptname='' where entry = 29104;
|
||||||
UPDATE `creature_template` SET `ScriptName`='npc_highlord_darion_mograine' WHERE `entry`='29173';
|
UPDATE `creature_template` SET `ScriptName`='npc_highlord_darion_mograine' WHERE `entry`='29173';
|
||||||
UPDATE `creature_template` SET `ScriptName`='npc_the_lich_king_tirion_dawn' WHERE `entry` in (29183,29175);
|
UPDATE `creature_template` SET `ScriptName`='npc_the_lich_king_tirion_dawn' WHERE `entry` in (29183,29175);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
update creature_template set AIName = 'ArchorAI', scriptname='' where entry in (29102,29103);
|
||||||
|
update creature_template set AIName = 'TurretAI', scriptname='' where entry = 29104;
|
||||||
@@ -100,55 +100,6 @@ CreatureAI* GetAI_npc_valkyr_battle_maiden(Creature* pCreature)
|
|||||||
return new npc_valkyr_battle_maidenAI (pCreature);
|
return new npc_valkyr_battle_maidenAI (pCreature);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TRINITY_DLL_DECL mob_anti_airAI : public ScriptedAI
|
|
||||||
{
|
|
||||||
mob_anti_airAI(Creature *c) : ScriptedAI(c)
|
|
||||||
{
|
|
||||||
assert(me->m_spells[0]);
|
|
||||||
range = DoGetSpellMaxRange(me->m_spells[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
float range;
|
|
||||||
|
|
||||||
void MoveInLineOfSight(Unit *who)
|
|
||||||
{
|
|
||||||
if(!me->getVictim() && me->canAttack(who)
|
|
||||||
&& me->IsWithinCombatRange(who, range)
|
|
||||||
&& me->IsWithinLOSInMap(who))
|
|
||||||
AttackStart(who);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AttackStart(Unit *who)
|
|
||||||
{
|
|
||||||
if(who->IsFlying() || !me->IsWithinMeleeRange(who))
|
|
||||||
{
|
|
||||||
if(me->Attack(who, false))
|
|
||||||
me->GetMotionMaster()->MoveIdle();
|
|
||||||
}
|
|
||||||
else if(me->Attack(who, true))
|
|
||||||
me->GetMotionMaster()->MoveChase(who);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateAI(const uint32 diff)
|
|
||||||
{
|
|
||||||
if(!UpdateVictim())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(me->getVictim()->IsFlying() || !me->IsWithinMeleeRange(me->getVictim()))
|
|
||||||
{
|
|
||||||
if(!DoSpellAttackIfReady(me->m_spells[0]))
|
|
||||||
EnterEvadeMode();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
DoMeleeAttackIfReady();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
CreatureAI* GetAI_mob_anti_air(Creature* pCreature)
|
|
||||||
{
|
|
||||||
return new mob_anti_airAI (pCreature);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddSC_the_scarlet_enclave()
|
void AddSC_the_scarlet_enclave()
|
||||||
{
|
{
|
||||||
Script *newscript;
|
Script *newscript;
|
||||||
@@ -158,11 +109,6 @@ void AddSC_the_scarlet_enclave()
|
|||||||
newscript->GetAI = &GetAI_npc_valkyr_battle_maiden;
|
newscript->GetAI = &GetAI_npc_valkyr_battle_maiden;
|
||||||
newscript->RegisterSelf();
|
newscript->RegisterSelf();
|
||||||
|
|
||||||
newscript = new Script;
|
|
||||||
newscript->Name="mob_anti_air";
|
|
||||||
newscript->GetAI = &GetAI_mob_anti_air;
|
|
||||||
newscript->RegisterSelf();
|
|
||||||
|
|
||||||
// Chapter 3: Scarlet Armies Approach... - An End To All Things...
|
// Chapter 3: Scarlet Armies Approach... - An End To All Things...
|
||||||
// Chapter 4: An End To All Things... - An End To All Things...
|
// Chapter 4: An End To All Things... - An End To All Things...
|
||||||
}
|
}
|
||||||
|
|||||||
+56
-30
@@ -38,11 +38,22 @@ void AggressorAI::UpdateAI(const uint32 /*diff*/)
|
|||||||
DoMeleeAttackIfReady();
|
DoMeleeAttackIfReady();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// some day we will delete these useless things
|
||||||
int CombatAI::Permissible(const Creature *creature)
|
int CombatAI::Permissible(const Creature *creature)
|
||||||
{
|
{
|
||||||
return PERMIT_BASE_NO;
|
return PERMIT_BASE_NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ArchorAI::Permissible(const Creature *creature)
|
||||||
|
{
|
||||||
|
return PERMIT_BASE_NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TurretAI::Permissible(const Creature *creature)
|
||||||
|
{
|
||||||
|
return PERMIT_BASE_NO;
|
||||||
|
}
|
||||||
|
|
||||||
void CombatAI::InitializeAI()
|
void CombatAI::InitializeAI()
|
||||||
{
|
{
|
||||||
for(uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i)
|
for(uint32 i = 0; i < CREATURE_MAX_SPELLS; ++i)
|
||||||
@@ -158,35 +169,31 @@ void CasterAI::UpdateAI(const uint32 diff)
|
|||||||
//ArchorAI
|
//ArchorAI
|
||||||
//////////////
|
//////////////
|
||||||
|
|
||||||
ArchorAI::ArchorAI(Creature *c) : CreatureAI(c), m_canMelee(true)
|
ArchorAI::ArchorAI(Creature *c) : CreatureAI(c)
|
||||||
{
|
{
|
||||||
assert(me->m_spells[0]);
|
assert(me->m_spells[0]);
|
||||||
m_minRange = GetSpellMinRange(me->m_spells[0], false);
|
m_minRange = GetSpellMinRange(me->m_spells[0], false);
|
||||||
m_maxRange = GetSpellMaxRange(me->m_spells[0], false);
|
|
||||||
if(!m_minRange)
|
if(!m_minRange)
|
||||||
m_minRange = MELEE_RANGE;
|
m_minRange = MELEE_RANGE;
|
||||||
}
|
me->m_CombatDistance = GetSpellMaxRange(me->m_spells[0], false);
|
||||||
|
me->m_SightDistance = me->m_CombatDistance;
|
||||||
void ArchorAI::MoveInLineOfSight(Unit *who)
|
|
||||||
{
|
|
||||||
if(!me->getVictim() && me->canAttack(who)
|
|
||||||
&& me->IsWithinCombatRange(who, m_maxRange)
|
|
||||||
&& me->IsWithinLOSInMap(who))
|
|
||||||
AttackStart(who);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArchorAI::AttackStart(Unit *who)
|
void ArchorAI::AttackStart(Unit *who)
|
||||||
{
|
{
|
||||||
if(who->IsFlying() || !me->IsWithinCombatRange(who, m_minRange))
|
if(me->IsWithinCombatRange(who, m_minRange))
|
||||||
{
|
{
|
||||||
if(me->Attack(who, false))
|
if(me->Attack(who, true) && !who->IsFlying())
|
||||||
me->GetMotionMaster()->MoveIdle();
|
|
||||||
}
|
|
||||||
else if(m_canMelee)
|
|
||||||
{
|
|
||||||
if(me->Attack(who, true))
|
|
||||||
me->GetMotionMaster()->MoveChase(who);
|
me->GetMotionMaster()->MoveChase(who);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(me->Attack(who, false) && !who->IsFlying())
|
||||||
|
me->GetMotionMaster()->MoveChase(who, me->m_CombatDistance);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(who->IsFlying())
|
||||||
|
me->GetMotionMaster()->MoveIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArchorAI::UpdateAI(const uint32 diff)
|
void ArchorAI::UpdateAI(const uint32 diff)
|
||||||
@@ -194,18 +201,37 @@ void ArchorAI::UpdateAI(const uint32 diff)
|
|||||||
if(!UpdateVictim())
|
if(!UpdateVictim())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(me->getVictim()->IsFlying() || !me->IsWithinCombatRange(me->getVictim(), m_minRange))
|
if(!me->IsWithinCombatRange(me->getVictim(), m_minRange))
|
||||||
{
|
DoSpellAttackIfReady(me->m_spells[0]);
|
||||||
if(!DoSpellAttackIfReady(me->m_spells[0]))
|
else
|
||||||
{
|
|
||||||
if(HostilReference *ref = me->getThreatManager().getCurrentVictim())
|
|
||||||
ref->removeReference();
|
|
||||||
else // i do not know when this could happen
|
|
||||||
EnterEvadeMode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(m_canMelee)
|
|
||||||
DoMeleeAttackIfReady();
|
DoMeleeAttackIfReady();
|
||||||
else if(HostilReference *ref = me->getThreatManager().getCurrentVictim())
|
}
|
||||||
ref->removeReference();
|
|
||||||
|
|
||||||
|
//////////////
|
||||||
|
//TurretAI
|
||||||
|
//////////////
|
||||||
|
|
||||||
|
TurretAI::TurretAI(Creature *c) : CreatureAI(c)
|
||||||
|
{
|
||||||
|
assert(me->m_spells[0]);
|
||||||
|
m_minRange = GetSpellMinRange(me->m_spells[0], false);
|
||||||
|
me->m_CombatDistance = GetSpellMaxRange(me->m_spells[0], false);
|
||||||
|
me->m_SightDistance = me->m_CombatDistance;
|
||||||
|
sLog.outError("turret ai begins!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void TurretAI::AttackStart(Unit *who)
|
||||||
|
{
|
||||||
|
me->Attack(who, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TurretAI::UpdateAI(const uint32 diff)
|
||||||
|
{
|
||||||
|
if(!UpdateVictim())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(m_minRange && me->IsWithinCombatRange(me->getVictim(), m_minRange) || !DoSpellAttackIfReady(me->m_spells[0]))
|
||||||
|
if(HostilReference *ref = me->getThreatManager().getCurrentVictim())
|
||||||
|
ref->removeReference();
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-3
@@ -69,12 +69,24 @@ struct TRINITY_DLL_SPEC ArchorAI : public CreatureAI
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit ArchorAI(Creature *c);
|
explicit ArchorAI(Creature *c);
|
||||||
void MoveInLineOfSight(Unit *who);
|
|
||||||
void AttackStart(Unit *who);
|
void AttackStart(Unit *who);
|
||||||
void UpdateAI(const uint32 diff);
|
void UpdateAI(const uint32 diff);
|
||||||
|
|
||||||
|
static int Permissible(const Creature *);
|
||||||
protected:
|
protected:
|
||||||
float m_maxRange, m_minRange;
|
float m_minRange;
|
||||||
bool m_canMelee;
|
};
|
||||||
|
|
||||||
|
struct TRINITY_DLL_SPEC TurretAI : public CreatureAI
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit TurretAI(Creature *c);
|
||||||
|
void AttackStart(Unit *who);
|
||||||
|
void UpdateAI(const uint32 diff);
|
||||||
|
|
||||||
|
static int Permissible(const Creature *);
|
||||||
|
protected:
|
||||||
|
float m_minRange;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ m_creatureInfo(NULL), m_reactState(REACT_AGGRESSIVE), m_formation(NULL), m_summo
|
|||||||
//m_unit_movement_flags = MONSTER_MOVE_WALK;
|
//m_unit_movement_flags = MONSTER_MOVE_WALK;
|
||||||
|
|
||||||
m_SightDistance = sWorld.getConfig(CONFIG_SIGHT_MONSTER);
|
m_SightDistance = sWorld.getConfig(CONFIG_SIGHT_MONSTER);
|
||||||
m_CombatDistance = MELEE_RANGE;
|
m_CombatDistance = 0;//MELEE_RANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Creature::~Creature()
|
Creature::~Creature()
|
||||||
@@ -1705,13 +1705,13 @@ bool Creature::canStartAttack(Unit const* who, bool force) const
|
|||||||
if(isCivilian())
|
if(isCivilian())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(!canFly() && (GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE))
|
if(!canFly() && (GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE + m_CombatDistance))
|
||||||
//|| who->IsControlledByPlayer() && who->IsFlying()))
|
//|| who->IsControlledByPlayer() && who->IsFlying()))
|
||||||
// we cannot check flying for other creatures, too much map/vmap calculation
|
// we cannot check flying for other creatures, too much map/vmap calculation
|
||||||
// TODO: should switch to range attack
|
// TODO: should switch to range attack
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(!force && (IsNeutralToAll() || !IsWithinDistInMap(who, GetAttackDistance(who))))
|
if(!force && (IsNeutralToAll() || !IsWithinDistInMap(who, GetAttackDistance(who) + m_CombatDistance)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(!canCreatureAttack(who, force))
|
if(!canCreatureAttack(who, force))
|
||||||
@@ -2193,14 +2193,13 @@ bool Creature::canCreatureAttack(Unit const *pVictim, bool force) const
|
|||||||
if(sMapStore.LookupEntry(GetMapId())->IsDungeon())
|
if(sMapStore.LookupEntry(GetMapId())->IsDungeon())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
float AttackDist = GetAttackDistance(pVictim);
|
|
||||||
uint32 ThreatRadius = sWorld.getConfig(CONFIG_THREAT_RADIUS);
|
|
||||||
|
|
||||||
//Use AttackDistance in distance check if threat radius is lower. This prevents creature bounce in and out of combat every update tick.
|
//Use AttackDistance in distance check if threat radius is lower. This prevents creature bounce in and out of combat every update tick.
|
||||||
|
float dist = std::max(GetAttackDistance(pVictim), (float)sWorld.getConfig(CONFIG_THREAT_RADIUS)) + m_CombatDistance;
|
||||||
|
|
||||||
if(Unit *unit = GetCharmerOrOwner())
|
if(Unit *unit = GetCharmerOrOwner())
|
||||||
return pVictim->IsWithinDist(unit, ThreatRadius > AttackDist ? ThreatRadius : AttackDist);
|
return pVictim->IsWithinDist(unit, dist);
|
||||||
else
|
else
|
||||||
return pVictim->IsWithinDist3d(mHome_X, mHome_Y, mHome_Z, ThreatRadius > AttackDist ? ThreatRadius : AttackDist);
|
return pVictim->IsWithinDist3d(mHome_X, mHome_Y, mHome_Z, dist);
|
||||||
}
|
}
|
||||||
|
|
||||||
CreatureDataAddon const* Creature::GetCreatureAddon() const
|
CreatureDataAddon const* Creature::GetCreatureAddon() const
|
||||||
|
|||||||
@@ -46,6 +46,8 @@ namespace AIRegistry
|
|||||||
(new CreatureAIFactory<PetAI>("PetAI"))->RegisterSelf();
|
(new CreatureAIFactory<PetAI>("PetAI"))->RegisterSelf();
|
||||||
(new CreatureAIFactory<TotemAI>("TotemAI"))->RegisterSelf();
|
(new CreatureAIFactory<TotemAI>("TotemAI"))->RegisterSelf();
|
||||||
(new CreatureAIFactory<CombatAI>("CombatAI"))->RegisterSelf();
|
(new CreatureAIFactory<CombatAI>("CombatAI"))->RegisterSelf();
|
||||||
|
(new CreatureAIFactory<ArchorAI>("ArchorAI"))->RegisterSelf();
|
||||||
|
(new CreatureAIFactory<TurretAI>("TurretAI"))->RegisterSelf();
|
||||||
(new CreatureAIFactory<CreatureEventAI>("EventAI"))->RegisterSelf();
|
(new CreatureAIFactory<CreatureEventAI>("EventAI"))->RegisterSelf();
|
||||||
|
|
||||||
(new MovementGeneratorFactory<RandomMovementGenerator<Creature> >(RANDOM_MOTION_TYPE))->RegisterSelf();
|
(new MovementGeneratorFactory<RandomMovementGenerator<Creature> >(RANDOM_MOTION_TYPE))->RegisterSelf();
|
||||||
|
|||||||
@@ -66,8 +66,21 @@ TargetedMovementGenerator<T>::_setTargetLocation(T &owner)
|
|||||||
if(i_destinationHolder.HasArrived())
|
if(i_destinationHolder.HasArrived())
|
||||||
{
|
{
|
||||||
// prevent redundant micro-movement
|
// prevent redundant micro-movement
|
||||||
if(i_offset ? i_target->IsWithinDistInMap(&owner, i_offset + 1.0f) : i_target->IsWithinMeleeRange(&owner))
|
if(!i_offset)
|
||||||
return false;
|
{
|
||||||
|
if(i_target->IsWithinMeleeRange(&owner))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if(!i_angle && !owner.hasUnitState(UNIT_STAT_FOLLOW))
|
||||||
|
{
|
||||||
|
if(i_target->IsWithinDistInMap(&owner, i_offset))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(i_target->IsWithinDistInMap(&owner, i_offset + 1.0f))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -79,7 +92,7 @@ TargetedMovementGenerator<T>::_setTargetLocation(T &owner)
|
|||||||
}
|
}
|
||||||
else if(!i_angle && !owner.hasUnitState(UNIT_STAT_FOLLOW))
|
else if(!i_angle && !owner.hasUnitState(UNIT_STAT_FOLLOW))
|
||||||
{
|
{
|
||||||
if(i_target->IsWithinDist(&owner, i_offset * 0.8))
|
if(i_target->IsWithinDist(&owner, i_offset * 0.8f))
|
||||||
stop = true;
|
stop = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +118,7 @@ TargetedMovementGenerator<T>::_setTargetLocation(T &owner)
|
|||||||
else if(!i_angle && !owner.hasUnitState(UNIT_STAT_FOLLOW))
|
else if(!i_angle && !owner.hasUnitState(UNIT_STAT_FOLLOW))
|
||||||
{
|
{
|
||||||
// caster chase
|
// caster chase
|
||||||
i_target->GetContactPoint(&owner, x, y, z, i_offset * urand(80, 100) * 0.01f);
|
i_target->GetContactPoint(&owner, x, y, z, i_offset * urand(80, 95) * 0.01f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user