diff options
Diffstat (limited to 'src/game/Creature.cpp')
-rw-r--r-- | src/game/Creature.cpp | 143 |
1 files changed, 122 insertions, 21 deletions
diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 8a58deb7f91..7802dcd2922 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -117,14 +117,36 @@ uint32 CreatureInfo::GetFirstValidModelId() const return 0; } +bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) +{ + Unit* victim = Unit::GetUnit(m_owner, m_victim); + if (victim) + { + while (!m_assistants.empty()) + { + Creature* assistant = (Creature*)Unit::GetUnit(m_owner, *m_assistants.begin()); + m_assistants.pop_front(); + + if (assistant && assistant->CanAssistTo(&m_owner, victim)) + { + assistant->SetNoCallAssistance(true); + assistant->CombatStart(victim); + if(assistant->AI()) + assistant->AI()->AttackStart(victim); + } + } + } + return true; +} + Creature::Creature() : Unit(), i_AI(NULL), i_AI_possessed(NULL), lootForPickPocketed(false), lootForBody(false), m_groupLootTimer(0), lootingGroupLeaderGUID(0), m_lootMoney(0), m_lootRecipient(0), m_deathTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(0.0f), -m_gossipOptionLoaded(false), m_emoteState(0), m_isPet(false), m_isTotem(false), +m_gossipOptionLoaded(false), m_emoteState(0), m_isPet(false), m_isTotem(false), m_isAggressive(true), m_regenTimer(2000), m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0), -m_AlreadyCallAssistence(false), m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), +m_AlreadyCallAssistance(false), m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL),m_creatureInfo(NULL), m_DBTableGuid(0) { m_valuesCount = UNIT_END; @@ -147,7 +169,11 @@ Creature::~Creature() delete i_AI; i_AI = NULL; - DeletePossessedAI(); + if (i_AI_possessed) + { + delete i_AI_possessed; + i_AI_possessed = NULL; + } } void Creature::AddToWorld() @@ -293,6 +319,7 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data ) SetUInt32Value(UNIT_FIELD_FLAGS,GetCreatureInfo()->unit_flags); SetUInt32Value(UNIT_DYNAMIC_FLAGS,GetCreatureInfo()->dynamicflags); + SetMeleeDamageSchool(SpellSchools(GetCreatureInfo()->dmgschool)); SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(GetCreatureInfo()->armor)); SetModifierValue(UNIT_MOD_RESISTANCE_HOLY, BASE_VALUE, float(GetCreatureInfo()->resistance1)); SetModifierValue(UNIT_MOD_RESISTANCE_FIRE, BASE_VALUE, float(GetCreatureInfo()->resistance2)); @@ -323,6 +350,12 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data ) if(GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER) SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if(isTotem() || isCivilian() || GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_TRIGGER + || GetCreatureType() == CREATURE_TYPE_CRITTER) + m_isAggressive = false; + else + m_isAggressive = true; + return true; } @@ -555,13 +588,10 @@ void Creature::InitPossessedAI() i_AI->OnPossess(true); } -void Creature::DeletePossessedAI() +void Creature::DisablePossessedAI() { if (!i_AI_possessed) return; - delete i_AI_possessed; - i_AI_possessed = NULL; - // Signal the old AI that it's been re-enabled i_AI->OnPossess(false); } @@ -570,6 +600,7 @@ bool Creature::Create (uint32 guidlow, Map *map, uint32 Entry, uint32 team, cons { SetMapId(map->GetId()); SetInstanceId(map->GetInstanceId()); + //m_DBTableGuid = guidlow; //oX = x; oY = y; dX = x; dY = y; m_moveTime = 0; m_startMove = 0; const bool bResult = CreateFromProto(guidlow, Entry, team, data); @@ -596,7 +627,6 @@ bool Creature::Create (uint32 guidlow, Map *map, uint32 Entry, uint32 team, cons } LoadCreaturesAddon(); } - return bResult; } @@ -1271,8 +1301,11 @@ void Creature::SelectLevel(const CreatureInfo *cinfo) SetBaseWeaponDamage(RANGED_ATTACK, MINDAMAGE, cinfo->minrangedmg * damagemod); SetBaseWeaponDamage(RANGED_ATTACK, MAXDAMAGE, cinfo->maxrangedmg * damagemod); - SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, cinfo->attackpower * damagemod); - SetModifierValue(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, cinfo->rangedattackpower * damagemod); + // this value is not accurate, but should be close to the real value + SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, level * 5); + SetModifierValue(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, level * 5); + //SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, cinfo->attackpower * damagemod); + //SetModifierValue(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, cinfo->rangedattackpower * damagemod); } float Creature::_GetHealthMod(int32 Rank) @@ -1410,8 +1443,6 @@ bool Creature::LoadFromDB(uint32 guid, Map *map) SetHealth(m_deathState == ALIVE ? curhealth : 0); SetPower(POWER_MANA,data->curmana); - SetMeleeDamageSchool(SpellSchools(GetCreatureInfo()->dmgschool)); - // checked at creature_template loading m_defaultMovementType = MovementGeneratorType(data->movementType); @@ -1538,6 +1569,19 @@ bool Creature::IsWithinSightDist(Unit const* u) const return IsWithinDistInMap(u, sWorld.getConfig(CONFIG_SIGHT_MONSTER)); } +bool Creature::canStartAttack(Unit const* who) const +{ + if(!who->isInAccessiblePlaceFor(this) + || !canFly() && GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE + || !IsWithinDistInMap(who, GetAttackDistance(who))) + return false; + + if(!canAttack(who, false)) + return false; + + return IsWithinLOSInMap(who); +} + float Creature::GetAttackDistance(Unit const* pl) const { float aggroRate = sWorld.getRate(RATE_CREATURE_AGGRO); @@ -1817,13 +1861,37 @@ void Creature::DoFleeToGetAssistance(float radius) // Optional parameter } } -void Creature::CallAssistence() +Unit* Creature::SelectNearestTarget(float dist) const { - if( !m_AlreadyCallAssistence && getVictim() && !isPet() && !isCharmed()) + CellPair p(Trinity::ComputeCellPair(GetPositionX(), GetPositionY())); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Unit *target = NULL; + { - SetNoCallAssistence(true); + Trinity::NearestHostileUnitInAttackDistanceCheck u_check(this, dist); + Trinity::UnitLastSearcher<Trinity::NearestHostileUnitInAttackDistanceCheck> searcher(target, u_check); + + TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::NearestHostileUnitInAttackDistanceCheck>, WorldTypeMapContainer > world_unit_searcher(searcher); + TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::NearestHostileUnitInAttackDistanceCheck>, GridTypeMapContainer > grid_unit_searcher(searcher); + + CellLock<GridReadGuard> cell_lock(cell, p); + cell_lock->Visit(cell_lock, world_unit_searcher, *GetMap()); + cell_lock->Visit(cell_lock, grid_unit_searcher, *GetMap()); + } + + return target; +} - float radius = sWorld.getConfig(CONFIG_CREATURE_FAMILY_ASSISTEMCE_RADIUS); +void Creature::CallAssistance() +{ + if( !m_AlreadyCallAssistance && getVictim() && !isPet() && !isCharmed()) + { + SetNoCallAssistance(true); + + float radius = sWorld.getConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS); if(radius > 0) { std::list<Creature*> assistList; @@ -1843,16 +1911,49 @@ void Creature::CallAssistence() cell_lock->Visit(cell_lock, grid_creature_searcher, *MapManager::Instance().GetMap(GetMapId(), this)); } - for(std::list<Creature*>::iterator iter = assistList.begin(); iter != assistList.end(); ++iter) + if (!assistList.empty()) { - (*iter)->SetNoCallAssistence(true); - if((*iter)->AI()) - (*iter)->AI()->AttackStart(getVictim()); + AssistDelayEvent *e = new AssistDelayEvent(getVictim()->GetGUID(), *this); + while (!assistList.empty()) + { + // Pushing guids because in delay can happen some creature gets despawned => invalid pointer + e->AddAssistant((*assistList.begin())->GetGUID()); + assistList.pop_front(); + } + m_Events.AddEvent(e, m_Events.CalculateTime(sWorld.getConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY))); } } } } +bool Creature::CanAssistTo(const Unit* u, const Unit* enemy) const +{ + if(!isAggressive()) + return false; + + // we don't need help from zombies :) + if( !isAlive() ) + return false; + + // skip fighting creature + if( isInCombat() ) + return false; + + // only from same creature faction + if(getFaction() != u->getFaction() ) + return false; + + // only free creature + if( GetCharmerOrOwnerGUID() ) + return false; + + // skip non hostile to caster enemy creatures + if( !IsHostileTo(enemy) ) + return false; + + return true; +} + void Creature::SaveRespawnTime() { if(isPet() || !m_DBTableGuid) @@ -1878,7 +1979,7 @@ bool Creature::IsOutOfThreatArea(Unit* pVictim) const if(!pVictim->isInAccessiblePlaceFor(this)) return true; - if(sMapStore.LookupEntry(GetMapId())->Instanceable()) + if(sMapStore.LookupEntry(GetMapId())->IsDungeon()) return false; float length = pVictim->GetDistance(CombatStartX,CombatStartY,CombatStartZ); |