diff options
Diffstat (limited to 'src/game/Creature.cpp')
-rw-r--r-- | src/game/Creature.cpp | 147 |
1 files changed, 73 insertions, 74 deletions
diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index 00e826404e6..0f1b0dd0efc 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -1,7 +1,7 @@ /* - * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/> + * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/> * - * Copyright (C) 2008 Trinity <http://www.trinitycore.org/> + * Copyright (C) 2008-2009 Trinity <http://www.trinitycore.org/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,6 +29,7 @@ #include "QuestDef.h" #include "GossipDef.h" #include "Player.h" +#include "PoolHandler.h" #include "Opcodes.h" #include "Log.h" #include "LootMgr.h" @@ -39,30 +40,23 @@ #include "SpellAuras.h" #include "WaypointMovementGenerator.h" #include "InstanceData.h" -#include "BattleGround.h" +#include "BattleGroundMgr.h" #include "Util.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" #include "CellImpl.h" #include "OutdoorPvPMgr.h" -#include "GameEvent.h" +#include "GameEventMgr.h" #include "PossessedAI.h" #include "CreatureGroups.h" // apply implementation of the singletons #include "Policies/SingletonImp.h" -void TrainerSpellData::Clear() -{ - for (TrainerSpellList::iterator itr = spellList.begin(); itr != spellList.end(); ++itr) - delete (*itr); - spellList.empty(); -} - TrainerSpell const* TrainerSpellData::Find(uint32 spell_id) const { - for(TrainerSpellList::const_iterator itr = spellList.begin(); itr != spellList.end(); ++itr) - if((*itr)->spell == spell_id) - return *itr; + TrainerSpellMap::const_iterator itr = spellList.find(spell_id); + if (itr != spellList.end()) + return &itr->second; return NULL; } @@ -145,14 +139,15 @@ Unit(), i_AI(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_reactState(REACT_AGGRESSIVE), -m_regenTimer(2000), m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0), -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_formationID(0) +m_gossipOptionLoaded(false), m_emoteState(0), m_isPet(false), m_isVehicle(false), m_isTotem(false), +m_defaultMovementType(IDLE_MOTION_TYPE), m_DBTableGuid(0), m_equipmentId(0), m_AlreadyCallAssistance(false), +m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false), m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), +m_creatureInfo(NULL), m_reactState(REACT_AGGRESSIVE), m_formationID(0) { + m_regenTimer = 200; m_valuesCount = UNIT_END; - for(int i =0; i<4; ++i) + for(int i =0; i<CREATURE_MAX_SPELLS; ++i) m_spells[i] = 0; m_CreatureSpellCooldowns.clear(); @@ -310,7 +305,6 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data ) // creatures always have melee weapon ready if any SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE ); - SetByteValue(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_AURAS ); SelectLevel(GetCreatureInfo()); if (team == HORDE) @@ -354,10 +348,8 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData *data ) SetPvP(true); } - m_spells[0] = GetCreatureInfo()->spell1; - m_spells[1] = GetCreatureInfo()->spell2; - m_spells[2] = GetCreatureInfo()->spell3; - m_spells[3] = GetCreatureInfo()->spell4; + for(int i=0; i < CREATURE_MAX_SPELLS; ++i) + m_spells[i] = GetCreatureInfo()->spells[i]; // HACK: trigger creature is always not selectable if(isTrigger()) @@ -426,7 +418,11 @@ void Creature::Update(uint32 diff) //Call AI respawn virtual function i_AI->JustRespawned(); - GetMap()->Add(this); + uint16 poolid = poolhandler.IsPartOfAPool(GetGUIDLow(), GetTypeId()); + if (poolid) + poolhandler.UpdatePool(poolid, GetGUIDLow(), GetTypeId()); + else + GetMap()->Add(this); } break; } @@ -605,11 +601,11 @@ bool Creature::AIM_Initialize(CreatureAI* ai) return true; } -bool Creature::Create (uint32 guidlow, Map *map, uint32 Entry, uint32 team, const CreatureData *data) +bool Creature::Create (uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 team, const CreatureData *data) { SetMapId(map->GetId()); SetInstanceId(map->GetInstanceId()); - //m_DBTableGuid = guidlow; + SetPhaseMask(phaseMask,false); //oX = x; oY = y; dX = x; dY = y; m_moveTime = 0; m_startMove = 0; const bool bResult = CreateFromProto(guidlow, Entry, team, data); @@ -730,7 +726,7 @@ bool Creature::isCanInteractWithBattleMaster(Player* pPlayer, bool msg) const if(!isBattleMaster()) return false; - uint32 bgTypeId = objmgr.GetBattleMasterBG(GetEntry()); + BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(GetEntry()); if(!msg) return pPlayer->GetBGAccessByLevel(bgTypeId); @@ -746,8 +742,11 @@ bool Creature::isCanInteractWithBattleMaster(Player* pPlayer, bool msg) const case BATTLEGROUND_NA: case BATTLEGROUND_BE: case BATTLEGROUND_AA: - case BATTLEGROUND_RL: pPlayer->PlayerTalkClass->SendGossipMenu(10024,GetGUID()); break; - break; + case BATTLEGROUND_RL: + case BATTLEGROUND_SA: + case BATTLEGROUND_DS: + case BATTLEGROUND_RV: pPlayer->PlayerTalkClass->SendGossipMenu(10024,GetGUID()); break; + default: break; } return false; } @@ -783,7 +782,7 @@ void Creature::prepareGossipMenu( Player *pPlayer,uint32 gossipid ) if(gso->Id==1) { uint32 textid=GetNpcTextId(); - GossipText * gossiptext=objmgr.GetGossipText(textid); + GossipText const* gossiptext=objmgr.GetGossipText(textid); if(!gossiptext) cantalking=false; } @@ -894,13 +893,11 @@ void Creature::sendPreparedGossip(Player* player) if(!player) return; - GossipMenu& gossipmenu = player->PlayerTalkClass->GetGossipMenu(); - if(GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_WORLDEVENT) // if world event npc then gameeventmgr.HandleWorldEventGossip(player, this); // update world state with progress - // in case empty gossip menu open quest menu if any - if (gossipmenu.Empty() && GetNpcTextId() == 0) + // in case no gossip flag and quest menu not empty, open quest menu (client expect gossip menu with this flag) + if (!HasFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_GOSSIP) && !player->PlayerTalkClass->GetQuestMenu().Empty()) { player->SendPreparedQuest(GetGUID()); return; @@ -1001,7 +998,7 @@ void Creature::OnGossipSelect(Player* player, uint32 option) break; case GOSSIP_OPTION_BATTLEFIELD: { - uint32 bgTypeId = objmgr.GetBattleMasterBG(GetEntry()); + BattleGroundTypeId bgTypeId = sBattleGroundMgr.GetBattleMasterBG(GetEntry()); player->GetSession()->SendBattlegGroundList( GetGUID(), bgTypeId ); break; } @@ -1016,12 +1013,12 @@ void Creature::OnPoiSelect(Player* player, GossipOption const *gossip) { if(gossip->GossipId==GOSSIP_GUARD_SPELLTRAINER || gossip->GossipId==GOSSIP_GUARD_SKILLTRAINER) { - Poi_Icon icon = ICON_POI_0; + Poi_Icon icon = ICON_POI_BLANK; //need add more case. switch(gossip->Action) { case GOSSIP_GUARD_BANK: - icon=ICON_POI_HOUSE; + icon=ICON_POI_SMALL_HOUSE; break; case GOSSIP_GUARD_RIDE: icon=ICON_POI_RWHORSE; @@ -1030,7 +1027,7 @@ void Creature::OnPoiSelect(Player* player, GossipOption const *gossip) icon=ICON_POI_BLUETOWER; break; default: - icon=ICON_POI_TOWER; + icon=ICON_POI_GREYTOWER; break; } uint32 textid = GetGossipTextId( gossip->Action, GetZoneId() ); @@ -1164,10 +1161,10 @@ void Creature::SaveToDB() return; } - SaveToDB(GetMapId(), data->spawnMask); + SaveToDB(GetMapId(), data->spawnMask,GetPhaseMask()); } -void Creature::SaveToDB(uint32 mapid, uint8 spawnMask) +void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) { // update in loaded data if (!m_DBTableGuid) @@ -1187,6 +1184,7 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask) // data->guid = guid don't must be update at save data.id = GetEntry(); data.mapid = mapid; + data.phaseMask = phaseMask; data.displayid = displayId; data.equipmentId = GetEquipmentId(); data.posX = GetPositionX(); @@ -1215,7 +1213,8 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask) << m_DBTableGuid << "," << GetEntry() << "," << mapid <<"," - << (uint32)spawnMask << "," + << uint32(spawnMask) << "," // cast to prevent save as symbol + << uint16(GetPhaseMask()) << "," // prevent out of range error << displayId <<"," << GetEquipmentId() <<"," << GetPositionX() << "," @@ -1385,7 +1384,7 @@ bool Creature::LoadFromDB(uint32 guid, Map *map) if (map->GetInstanceId() != 0) guid = objmgr.GenerateLowGuid(HIGHGUID_UNIT); uint16 team = 0; - if(!Create(guid,map,data->id,team,data)) + if(!Create(guid,map,data->phaseMask,data->id,team,data)) return false; Relocate(data->posX,data->posY,data->posZ,data->orientation); @@ -1446,11 +1445,7 @@ void Creature::LoadEquipment(uint32 equip_entry, bool force) if (force) { for (uint8 i = 0; i < 3; i++) - { - SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + i, 0); - SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2), 0); - SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2) + 1, 0); - } + SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i, 0); m_equipmentId = 0; } return; @@ -1462,11 +1457,7 @@ void Creature::LoadEquipment(uint32 equip_entry, bool force) m_equipmentId = equip_entry; for (uint8 i = 0; i < 3; i++) - { - SetUInt32Value( UNIT_VIRTUAL_ITEM_SLOT_DISPLAY + i, einfo->equipmodel[i]); - SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2), einfo->equipinfo[i]); - SetUInt32Value( UNIT_VIRTUAL_ITEM_INFO + (i * 2) + 1, einfo->equipslot[i]); - } + SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + i, einfo->equipentry[i]); } bool Creature::hasQuest(uint32 quest_id) const @@ -1524,6 +1515,10 @@ bool Creature::canSeeOrDetect(Unit const* u, bool detect, bool inVisibleList, bo if (u == this) return true; + // phased visibility (both must phased in same way) + if(!InSamePhase(u)) + return false; + // always seen by owner if(GetGUID() == u->GetCharmerOrOwnerGUID()) return true; @@ -1612,7 +1607,7 @@ void Creature::setDeathState(DeathState s) { if((s == JUST_DIED && !m_isDeadByDefault)||(s == JUST_ALIVED && m_isDeadByDefault)) { - m_deathTimer = m_corpseDelay*1000; + m_deathTimer = m_corpseDelay*IN_MILISECONDS; // always save boss respawn time at death to prevent crash cheating if(sWorld.getConfig(CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY) || isWorldBoss()) @@ -1697,7 +1692,7 @@ void Creature::Respawn() } } -bool Creature::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges) +bool Creature::IsImmunedToSpell(SpellEntry const* spellInfo) { if (!spellInfo) return false; @@ -1705,15 +1700,15 @@ bool Creature::IsImmunedToSpell(SpellEntry const* spellInfo, bool useCharges) if (GetCreatureInfo()->MechanicImmuneMask & (1 << (spellInfo->Mechanic - 1))) return true; - return Unit::IsImmunedToSpell(spellInfo, useCharges); + return Unit::IsImmunedToSpell(spellInfo); } -bool Creature::IsImmunedToSpellEffect(uint32 effect, uint32 mechanic) const +bool Creature::IsImmunedToSpellEffect(SpellEntry const* spellInfo, uint32 index) const { - if (GetCreatureInfo()->MechanicImmuneMask & (1 << (mechanic-1))) + if (GetCreatureInfo()->MechanicImmuneMask & (1 << (spellInfo->EffectMechanic[index] - 1))) return true; - return Unit::IsImmunedToSpellEffect(effect, mechanic); + return Unit::IsImmunedToSpellEffect(spellInfo, index); } SpellEntry const *Creature::reachWithSpellAttack(Unit *pVictim) @@ -1750,14 +1745,16 @@ SpellEntry const *Creature::reachWithSpellAttack(Unit *pVictim) if(spellInfo->manaCost > GetPower(POWER_MANA)) continue; SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); - float range = GetSpellMaxRange(srange); - float minrange = GetSpellMinRange(srange); + float range = GetSpellMaxRangeForHostile(srange); + float minrange = GetSpellMinRangeForHostile(srange); float dist = GetDistance(pVictim); //if(!isInFront( pVictim, range ) && spellInfo->AttributesEx ) // continue; if( dist > range || dist < minrange ) continue; - if(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) + if(spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) + continue; + if(spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED)) continue; return spellInfo; } @@ -1794,14 +1791,16 @@ SpellEntry const *Creature::reachWithSpellCure(Unit *pVictim) if(spellInfo->manaCost > GetPower(POWER_MANA)) continue; SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(spellInfo->rangeIndex); - float range = GetSpellMaxRange(srange); - float minrange = GetSpellMinRange(srange); + float range = GetSpellMaxRangeForFriend(srange); + float minrange = GetSpellMinRangeForFriend( srange); float dist = GetDistance(pVictim); //if(!isInFront( pVictim, range ) && spellInfo->AttributesEx ) // continue; if( dist > range || dist < minrange ) continue; - if(HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) + if(spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED)) + continue; + if(spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY && HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED)) continue; return spellInfo; } @@ -1849,7 +1848,7 @@ void Creature::DoFleeToGetAssistance(float radius) // Optional parameter Creature* pCreature = NULL; Trinity::NearestAssistCreatureInCreatureRangeCheck u_check(this,getVictim(),radius); - Trinity::CreatureLastSearcher<Trinity::NearestAssistCreatureInCreatureRangeCheck> searcher(pCreature, u_check); + Trinity::CreatureLastSearcher<Trinity::NearestAssistCreatureInCreatureRangeCheck> searcher(this, pCreature, u_check); VisitNearbyGridObject(radius, searcher); if(!pCreature) @@ -1869,7 +1868,7 @@ Unit* Creature::SelectNearestTarget(float dist) const { Trinity::NearestHostileUnitInAttackDistanceCheck u_check(this, dist); - Trinity::UnitLastSearcher<Trinity::NearestHostileUnitInAttackDistanceCheck> searcher(target, u_check); + Trinity::UnitLastSearcher<Trinity::NearestHostileUnitInAttackDistanceCheck> searcher(this, target, u_check); TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::NearestHostileUnitInAttackDistanceCheck>, WorldTypeMapContainer > world_unit_searcher(searcher); TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::NearestHostileUnitInAttackDistanceCheck>, GridTypeMapContainer > grid_unit_searcher(searcher); @@ -1899,8 +1898,8 @@ void Creature::CallAssistance() cell.data.Part.reserved = ALL_DISTRICT; cell.SetNoCreate(); - Trinity::AnyAssistCreatureInRangeCheck u_check(this, getVictim(), radius); - Trinity::CreatureListSearcher<Trinity::AnyAssistCreatureInRangeCheck> searcher(assistList, u_check); + MaNGOS::AnyAssistCreatureInRangeCheck u_check(this, getVictim(), radius); + MaNGOS::CreatureListSearcher<MaNGOS::AnyAssistCreatureInRangeCheck> searcher(this, assistList, u_check); TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AnyAssistCreatureInRangeCheck>, GridTypeMapContainer > grid_creature_searcher(searcher); @@ -1960,7 +1959,7 @@ void Creature::SaveRespawnTime() if(m_respawnTime > time(NULL)) // dead (no corpse) objmgr.SaveCreatureRespawnTime(m_DBTableGuid,GetInstanceId(),m_respawnTime); else if(m_deathTimer > 0) // dead (corpse) - objmgr.SaveCreatureRespawnTime(m_DBTableGuid,GetInstanceId(),time(NULL)+m_respawnDelay+m_deathTimer/1000); + objmgr.SaveCreatureRespawnTime(m_DBTableGuid,GetInstanceId(),time(NULL)+m_respawnDelay+m_deathTimer/IN_MILISECONDS); } bool Creature::IsOutOfThreatArea(Unit* pVictim) const @@ -2085,7 +2084,7 @@ void Creature::AddCreatureSpellCooldown(uint32 spellid) uint32 cooldown = GetSpellRecoveryTime(spellInfo); if(cooldown) - _AddCreatureSpellCooldown(spellid, time(NULL) + cooldown/1000); + _AddCreatureSpellCooldown(spellid, time(NULL) + cooldown/IN_MILISECONDS); if(spellInfo->Category) _AddCreatureCategoryCooldown(spellInfo->Category, time(NULL)); @@ -2104,7 +2103,7 @@ bool Creature::HasCategoryCooldown(uint32 spell_id) const return true; CreatureSpellCooldowns::const_iterator itr = m_CreatureCategoryCooldowns.find(spellInfo->Category); - return(itr != m_CreatureCategoryCooldowns.end() && time_t(itr->second + (spellInfo->CategoryRecoveryTime / 1000)) > time(NULL)); + return(itr != m_CreatureCategoryCooldowns.end() && time_t(itr->second + (spellInfo->CategoryRecoveryTime / IN_MILISECONDS)) > time(NULL)); } bool Creature::HasSpellCooldown(uint32 spell_id) const @@ -2133,7 +2132,7 @@ time_t Creature::GetRespawnTimeEx() const if(m_respawnTime > now) // dead (no corpse) return m_respawnTime; else if(m_deathTimer > 0) // dead (corpse) - return now+m_respawnDelay+m_deathTimer/1000; + return now+m_respawnDelay+m_deathTimer/IN_MILISECONDS; else return now; } @@ -2175,7 +2174,7 @@ void Creature::AllLootRemovedFromCorpse() // corpse was not skinnable -> apply corpse looted timer if (!cinfo || !cinfo->SkinLootId) - nDeathTimer = (uint32)((m_corpseDelay * 1000) * sWorld.getRate(RATE_CORPSE_DECAY_LOOTED)); + nDeathTimer = (uint32)((m_corpseDelay * IN_MILISECONDS) * sWorld.getRate(RATE_CORPSE_DECAY_LOOTED)); // corpse skinnable, but without skinning flag, and then skinned, corpse will despawn next update else nDeathTimer = 0; |