mirror of
https://github.com/mangosfour/server.git
synced 2025-12-12 10:37:03 +00:00
[7860] Implement creature event ai ACTION_T_CALL_FOR_HELP for explicit call for help in some script cases.
This commit is contained in:
parent
159258b668
commit
f332c000d1
8 changed files with 142 additions and 61 deletions
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -85,8 +85,7 @@ VendorItem const* VendorItemData::FindItem(uint32 item_id) 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())
|
||||
{
|
||||
|
|
@ -1725,26 +1724,34 @@ void Creature::CallAssistance()
|
|||
}
|
||||
}
|
||||
|
||||
bool Creature::CanAssistTo(const Unit* u, const Unit* enemy) const
|
||||
bool Creature::CanAssistTo(const Unit* u, const Unit* enemy, bool checkfaction /*= true*/) const
|
||||
{
|
||||
// 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;
|
||||
|
|
|
|||
|
|
@ -603,7 +603,7 @@ class MANGOS_DLL_SPEC Creature : public Unit
|
|||
|
||||
void CallAssistance();
|
||||
void SetNoCallAssistance(bool val) { m_AlreadyCallAssistance = val; }
|
||||
bool CanAssistTo(const Unit* u, const Unit* enemy) const;
|
||||
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; }
|
||||
|
|
|
|||
|
|
@ -30,6 +30,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)
|
||||
|
|
@ -705,7 +739,6 @@ void CreatureEventAI::ProcessAction(CreatureEventAI_Action const& action, uint32
|
|||
break;
|
||||
}
|
||||
case ACTION_T_UPDATE_TEMPLATE:
|
||||
{
|
||||
if (m_creature->GetEntry() == action.update_template.creatureId)
|
||||
{
|
||||
|
||||
|
|
@ -714,10 +747,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())
|
||||
{
|
||||
|
||||
|
|
@ -725,10 +756,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())
|
||||
{
|
||||
|
||||
|
|
@ -737,8 +766,26 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,45 +63,46 @@ 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_END,
|
||||
};
|
||||
|
|
@ -346,12 +347,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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -445,6 +445,25 @@ namespace MaNGOS
|
|||
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>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "7859"
|
||||
#define REVISION_NR "7860"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue