aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormegamage <none@none>2009-05-21 10:15:09 -0500
committermegamage <none@none>2009-05-21 10:15:09 -0500
commitb7053ecc0d565ba2f91d56f34a616d1992a91562 (patch)
treeb9bf4053bb2258cfd68b60f3ae520fb2616cf287
parent0a5c465cdc0d537f9965e6acf3416cc61212c488 (diff)
[7860] Implement creature event ai ACTION_T_CALL_FOR_HELP for explicit call for help in some script cases. Author: VladimirMangos
--HG-- branch : trunk
-rw-r--r--doc/EventAI.txt1
-rw-r--r--src/game/Creature.cpp29
-rw-r--r--src/game/Creature.h2
-rw-r--r--src/game/CreatureEventAI.cpp66
-rw-r--r--src/game/CreatureEventAI.h87
-rw-r--r--src/game/CreatureEventAIMgr.cpp2
-rw-r--r--src/game/GridNotifiers.h19
7 files changed, 141 insertions, 65 deletions
diff --git a/doc/EventAI.txt b/doc/EventAI.txt
index 7a2087decc7..a22b94eea01 100644
--- a/doc/EventAI.txt
+++ b/doc/EventAI.txt
@@ -128,6 +128,7 @@ Params are always read from Param1, then Param2, then Param3.
36 ACTION_T_UPDATE_TEMPLATE TemplateId, Team Changes the creature to a new creature template of (param1) with team = Alliance if (param2) = false or Horde if (param2) = true
37 ACTION_T_DIE No Params Kills the creature
38 ACTION_T_ZONE_COMBAT_PULSE No Params Places all players within the instance into combat with the creature. Only works in combat and only works inside of instances.
+39 ACTION_T_CALL_FOR_HELP Radius Call any friendly creatures (if its not in combat/etc) in radius attack creature target.
* = Use -1 to specify that if this param is picked to do nothing. Random is constant between actions within an event. So if you have a random Yell and a random Sound they will match up (ex: param2 with param2)
diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp
index 17828752aac..007e224b1e7 100644
--- a/src/game/Creature.cpp
+++ b/src/game/Creature.cpp
@@ -111,8 +111,7 @@ uint32 CreatureInfo::GetFirstValidModelId() const
bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
{
- Unit* victim = Unit::GetUnit(m_owner, m_victim);
- if (victim)
+ if(Unit* victim = Unit::GetUnit(m_owner, m_victim))
{
while (!m_assistants.empty())
{
@@ -2003,30 +2002,38 @@ void Creature::CallAssistance(float radius)
}
}
-bool Creature::CanAssistTo(const Unit* u, const Unit* enemy) const
+bool Creature::CanAssistTo(const Unit* u, const Unit* enemy, bool checkfaction /*= true*/) const
{
// is it true?
if(!HasReactState(REACT_AGGRESSIVE))
return false;
// we don't need help from zombies :)
- if( !isAlive() )
+ if (!isAlive())
return false;
// skip fighting creature
- if( isInCombat() )
- return false;
-
- // only from same creature faction
- if(getFaction() != u->getFaction() )
+ if (isInCombat())
return false;
// only free creature
- if( GetCharmerOrOwnerGUID() )
+ if (GetCharmerOrOwnerGUID())
return false;
+ // only from same creature faction
+ if (checkfaction)
+ {
+ if (getFaction() != u->getFaction())
+ return false;
+ }
+ else
+ {
+ if (!IsFriendlyTo(u))
+ return false;
+ }
+
// skip non hostile to caster enemy creatures
- if( !IsHostileTo(enemy) )
+ if (!IsHostileTo(enemy))
return false;
return true;
diff --git a/src/game/Creature.h b/src/game/Creature.h
index 504261c3e1e..e89af04126c 100644
--- a/src/game/Creature.h
+++ b/src/game/Creature.h
@@ -636,8 +636,8 @@ class TRINITY_DLL_SPEC Creature : public Unit
Unit* SelectNearestTarget(float dist = 0) const;
void CallAssistance(float radius = 0);
void SetNoCallAssistance(bool val) { m_AlreadyCallAssistance = val; }
- bool CanAssistTo(const Unit* u, const Unit* enemy) const;
void DoFleeToGetAssistance(float radius = 50);
+ bool CanAssistTo(const Unit* u, const Unit* enemy, bool checkfaction = true) const;
MovementGeneratorType GetDefaultMovementType() const { return m_defaultMovementType; }
void SetDefaultMovementType(MovementGeneratorType mgt) { m_defaultMovementType = mgt; }
diff --git a/src/game/CreatureEventAI.cpp b/src/game/CreatureEventAI.cpp
index 0026658f319..7625ce0b74f 100644
--- a/src/game/CreatureEventAI.cpp
+++ b/src/game/CreatureEventAI.cpp
@@ -32,6 +32,40 @@
#include "WorldPacket.h"
#include "InstanceData.h"
+namespace MaNGOS
+{
+ class CallOfHelpCreatureInRangeDo // do attack at call of help to friendly crearture
+ {
+ public:
+ CallOfHelpCreatureInRangeDo(Unit* funit, Unit* enemy, float range)
+ : i_funit(funit), i_enemy(enemy), i_range(range)
+ {}
+ void operator()(Creature* u)
+ {
+ if (u == i_funit)
+ return;
+
+ if (!u->CanAssistTo(i_funit, i_enemy, false))
+ return;
+
+ // too far
+ if( !i_funit->IsWithinDistInMap(u, i_range) )
+ return;
+
+ // only if see assisted creature
+ if( !i_funit->IsWithinLOSInMap(u) )
+ return;
+
+ if(u->AI())
+ u->AI()->AttackStart(i_enemy);
+ }
+ private:
+ Unit* const i_funit;
+ Unit* const i_enemy;
+ float i_range;
+ };
+}
+
bool CreatureEventAIHolder::UpdateRepeatTimer( Creature* creature, uint32 repeatMin, uint32 repeatMax )
{
if (repeatMin == repeatMax)
@@ -697,7 +731,6 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
break;
}
case ACTION_T_UPDATE_TEMPLATE:
- {
if (m_creature->GetEntry() == action.update_template.creatureId)
{
@@ -706,10 +739,8 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
}
m_creature->UpdateEntry(action.update_template.creatureId, action.update_template.team ? HORDE : ALLIANCE);
- }
- break;
+ break;
case ACTION_T_DIE:
- {
if (m_creature->isDead())
{
@@ -717,10 +748,8 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
return;
}
m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
- }
- break;
+ break;
case ACTION_T_ZONE_COMBAT_PULSE:
- {
if (!m_creature->isInCombat() || !m_creature->GetMap()->IsDungeon())
{
@@ -729,6 +758,25 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
}
DoZoneInCombat(m_creature);
+ break;
+ case ACTION_T_CALL_FOR_HELP:
+ {
+ if (!m_creature->getVictim())
+ return;
+
+ CellPair p(MaNGOS::ComputeCellPair(m_creature->GetPositionX(), m_creature->GetPositionY()));
+ Cell cell(p);
+ cell.data.Part.reserved = ALL_DISTRICT;
+ cell.SetNoCreate();
+
+ MaNGOS::CallOfHelpCreatureInRangeDo u_do(m_creature, m_creature->getVictim(), action.call_for_help.radius);
+ MaNGOS::CreatureWorker<MaNGOS::CallOfHelpCreatureInRangeDo> worker(m_creature, u_do);
+
+ TypeContainerVisitor<MaNGOS::CreatureWorker<MaNGOS::CallOfHelpCreatureInRangeDo>, GridTypeMapContainer > grid_creature_searcher(worker);
+
+ CellLock<GridReadGuard> cell_lock(cell, p);
+ cell_lock->Visit(cell_lock, grid_creature_searcher, *m_creature->GetMap());
+ break;
}
break;
@@ -755,10 +803,6 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
}
break;
}
- case ACTION_T_CALL_ASSISTANCE:
- m_creature->SetNoCallAssistance(false);
- m_creature->CallAssistance(action.raw.param1);
- break;
}
}
diff --git a/src/game/CreatureEventAI.h b/src/game/CreatureEventAI.h
index 8baa551ec6a..3434a9cb55e 100644
--- a/src/game/CreatureEventAI.h
+++ b/src/game/CreatureEventAI.h
@@ -63,51 +63,51 @@ enum EventAI_Type
enum EventAI_ActionType
{
- ACTION_T_NONE = 0, //*No action
- ACTION_T_TEXT = 1, //*-TextId1, optionally -TextId2, optionally -TextId3(if -TextId2 exist). If more than just -TextId1 is defined, randomize. Negative values.
- ACTION_T_SET_FACTION = 2, //*FactionId (or 0 for default)
- ACTION_T_MORPH_TO_ENTRY_OR_MODEL = 3, //*Creature_template entry(param1) OR ModelId (param2) (or 0 for both to demorph)
- ACTION_T_SOUND = 4, //*SoundId
- ACTION_T_EMOTE = 5, //*EmoteId
- ACTION_T_RANDOM_SAY = 6, //*UNUSED
- ACTION_T_RANDOM_YELL = 7, //*UNUSED
- ACTION_T_RANDOM_TEXTEMOTE = 8, //*UNUSED
- ACTION_T_RANDOM_SOUND = 9, //SoundId1, SoundId2, SoundId3 (-1 in any field means no output if randomed that field)
- ACTION_T_RANDOM_EMOTE = 10, //*EmoteId1, EmoteId2, EmoteId3 (-1 in any field means no output if randomed that field)
- ACTION_T_CAST = 11, //*SpellId, Target, CastFlags
- ACTION_T_SUMMON = 12, //*CreatureID, Target, Duration in ms
- ACTION_T_THREAT_SINGLE_PCT = 13, //*Threat%, Target
- ACTION_T_THREAT_ALL_PCT = 14, //Threat%
- ACTION_T_QUEST_EVENT = 15, //*QuestID, Target
- ACTION_T_CAST_EVENT = 16, //*QuestID, SpellId, Target - must be removed as hack?
- ACTION_T_SET_UNIT_FIELD = 17, //*Field_Number, Value, Target
- ACTION_T_SET_UNIT_FLAG = 18, //*Flags (may be more than one field OR'd together), Target
- ACTION_T_REMOVE_UNIT_FLAG = 19, //*Flags (may be more than one field OR'd together), Target
- ACTION_T_AUTO_ATTACK = 20, //AllowAttackState (0 = stop attack, anything else means continue attacking)
- ACTION_T_COMBAT_MOVEMENT = 21, //AllowCombatMovement (0 = stop combat based movement, anything else continue attacking)
- ACTION_T_SET_PHASE = 22, //*Phase
- ACTION_T_INC_PHASE = 23, //*Value (may be negative to decrement phase, should not be 0)
- ACTION_T_EVADE = 24, //No Params
- ACTION_T_FLEE = 25, //No Params
- ACTION_T_QUEST_EVENT_ALL = 26, //*QuestID
- ACTION_T_CAST_EVENT_ALL = 27, //*QuestId, SpellId
- ACTION_T_REMOVEAURASFROMSPELL = 28, //*Target, Spellid
- ACTION_T_RANGED_MOVEMENT = 29, //Distance, Angle
- ACTION_T_RANDOM_PHASE = 30, //PhaseId1, PhaseId2, PhaseId3
- ACTION_T_RANDOM_PHASE_RANGE = 31, //PhaseMin, PhaseMax
- ACTION_T_SUMMON_ID = 32, //*CreatureId, Target, SpawnId
- ACTION_T_KILLED_MONSTER = 33, //*CreatureId, Target
- ACTION_T_SET_INST_DATA = 34, //*Field, Data
- ACTION_T_SET_INST_DATA64 = 35, //*Field, Target
- ACTION_T_UPDATE_TEMPLATE = 36, //*Entry, Team
- ACTION_T_DIE = 37, //No Params
- ACTION_T_ZONE_COMBAT_PULSE = 38, //No Params
+ ACTION_T_NONE = 0, // No action
+ ACTION_T_TEXT = 1, // TextId1, optionally -TextId2, optionally -TextId3(if -TextId2 exist). If more than just -TextId1 is defined, randomize. Negative values.
+ ACTION_T_SET_FACTION = 2, // FactionId (or 0 for default)
+ ACTION_T_MORPH_TO_ENTRY_OR_MODEL = 3, // Creature_template entry(param1) OR ModelId (param2) (or 0 for both to demorph)
+ ACTION_T_SOUND = 4, // SoundId
+ ACTION_T_EMOTE = 5, // EmoteId
+ ACTION_T_RANDOM_SAY = 6, // UNUSED
+ ACTION_T_RANDOM_YELL = 7, // UNUSED
+ ACTION_T_RANDOM_TEXTEMOTE = 8, // UNUSED
+ ACTION_T_RANDOM_SOUND = 9, // SoundId1, SoundId2, SoundId3 (-1 in any field means no output if randomed that field)
+ ACTION_T_RANDOM_EMOTE = 10, // EmoteId1, EmoteId2, EmoteId3 (-1 in any field means no output if randomed that field)
+ ACTION_T_CAST = 11, // SpellId, Target, CastFlags
+ ACTION_T_SUMMON = 12, // CreatureID, Target, Duration in ms
+ ACTION_T_THREAT_SINGLE_PCT = 13, // Threat%, Target
+ ACTION_T_THREAT_ALL_PCT = 14, // Threat%
+ ACTION_T_QUEST_EVENT = 15, // QuestID, Target
+ ACTION_T_CAST_EVENT = 16, // QuestID, SpellId, Target - must be removed as hack?
+ ACTION_T_SET_UNIT_FIELD = 17, // Field_Number, Value, Target
+ ACTION_T_SET_UNIT_FLAG = 18, // Flags (may be more than one field OR'd together), Target
+ ACTION_T_REMOVE_UNIT_FLAG = 19, // Flags (may be more than one field OR'd together), Target
+ ACTION_T_AUTO_ATTACK = 20, // AllowAttackState (0 = stop attack, anything else means continue attacking)
+ ACTION_T_COMBAT_MOVEMENT = 21, // AllowCombatMovement (0 = stop combat based movement, anything else continue attacking)
+ ACTION_T_SET_PHASE = 22, // Phase
+ ACTION_T_INC_PHASE = 23, // Value (may be negative to decrement phase, should not be 0)
+ ACTION_T_EVADE = 24, // No Params
+ ACTION_T_FLEE = 25, // No Params
+ ACTION_T_QUEST_EVENT_ALL = 26, // QuestID
+ ACTION_T_CAST_EVENT_ALL = 27, // CreatureId, SpellId
+ ACTION_T_REMOVEAURASFROMSPELL = 28, // Target, Spellid
+ ACTION_T_RANGED_MOVEMENT = 29, // Distance, Angle
+ ACTION_T_RANDOM_PHASE = 30, // PhaseId1, PhaseId2, PhaseId3
+ ACTION_T_RANDOM_PHASE_RANGE = 31, // PhaseMin, PhaseMax
+ ACTION_T_SUMMON_ID = 32, // CreatureId, Target, SpawnId
+ ACTION_T_KILLED_MONSTER = 33, // CreatureId, Target
+ ACTION_T_SET_INST_DATA = 34, // Field, Data
+ ACTION_T_SET_INST_DATA64 = 35, // Field, Target
+ ACTION_T_UPDATE_TEMPLATE = 36, // Entry, Team
+ ACTION_T_DIE = 37, // No Params
+ ACTION_T_ZONE_COMBAT_PULSE = 38, // No Params
+ ACTION_T_CALL_FOR_HELP = 39, // Radius
ACTION_T_SET_ACTIVE = 101, //Apply
ACTION_T_SET_AGGRESSIVE = 102, //Apply
ACTION_T_ATTACK_START_PULSE = 103, //Distance
ACTION_T_SUMMON_GO = 104, //GameObjectID, DespawnTime in ms
- ACTION_T_CALL_ASSISTANCE = 105, //Radius
ACTION_T_END,
};
@@ -352,12 +352,17 @@ struct CreatureEventAI_Action
uint32 field;
uint32 target;
} set_inst_data64;
- // ACTION_T_UPDATE_TEMPLATE = 36, //*Entry, Team
+ // ACTION_T_UPDATE_TEMPLATE = 36
struct
{
uint32 creatureId;
uint32 team;
} update_template;
+ // ACTION_T_CALL_FOR_HELP = 39
+ struct
+ {
+ uint32 radius;
+ } call_for_help;
// RAW
struct
{
diff --git a/src/game/CreatureEventAIMgr.cpp b/src/game/CreatureEventAIMgr.cpp
index a5f7395d68d..9bd262a5f9f 100644
--- a/src/game/CreatureEventAIMgr.cpp
+++ b/src/game/CreatureEventAIMgr.cpp
@@ -632,6 +632,7 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
case ACTION_T_AUTO_ATTACK: //AllowAttackState (0 = stop attack, anything else means continue attacking)
case ACTION_T_COMBAT_MOVEMENT: //AllowCombatMovement (0 = stop combat based movement, anything else continue attacking)
case ACTION_T_RANGED_MOVEMENT: //Distance, Angle
+ case ACTION_T_CALL_FOR_HELP: //Distance
break;
case ACTION_T_RANDOM_SAY:
@@ -644,7 +645,6 @@ void CreatureEventAIMgr::LoadCreatureEventAI_Scripts()
case ACTION_T_SET_AGGRESSIVE:
case ACTION_T_ATTACK_START_PULSE:
case ACTION_T_SUMMON_GO:
- case ACTION_T_CALL_ASSISTANCE:
break;
default:
diff --git a/src/game/GridNotifiers.h b/src/game/GridNotifiers.h
index b45f7f6d675..2295f72e4c9 100644
--- a/src/game/GridNotifiers.h
+++ b/src/game/GridNotifiers.h
@@ -440,6 +440,25 @@ namespace Trinity
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) {}
};
+ template<class Do>
+ struct MANGOS_DLL_DECL CreatureWorker
+ {
+ uint32 i_phaseMask;
+ Do& i_do;
+
+ CreatureWorker(WorldObject const* searcher, Do& _do)
+ : i_phaseMask(searcher->GetPhaseMask()), i_do(_do) {}
+
+ void Visit(CreatureMapType &m)
+ {
+ for(CreatureMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
+ if(itr->getSource()->InSamePhase(i_phaseMask))
+ i_do(itr->getSource());
+ }
+
+ template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) {}
+ };
+
// Player searchers
template<class Check>