diff options
Diffstat (limited to 'src/game/GameObject.cpp')
-rw-r--r-- | src/game/GameObject.cpp | 266 |
1 files changed, 183 insertions, 83 deletions
diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index d1bb0362872..def17130372 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.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 @@ -22,15 +22,14 @@ #include "QuestDef.h" #include "GameObject.h" #include "ObjectMgr.h" +#include "PoolHandler.h" #include "SpellMgr.h" #include "Spell.h" #include "UpdateMask.h" #include "Opcodes.h" #include "WorldPacket.h" -#include "WorldSession.h" #include "World.h" #include "Database/DatabaseEnv.h" -#include "MapManager.h" #include "LootMgr.h" #include "GridNotifiers.h" #include "GridNotifiersImpl.h" @@ -46,7 +45,7 @@ GameObject::GameObject() : WorldObject() m_objectType |= TYPEMASK_GAMEOBJECT; m_objectTypeId = TYPEID_GAMEOBJECT; // 2.3.2 - 0x58 - m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HASPOSITION); + m_updateFlag = (UPDATEFLAG_LOWGUID | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION); m_valuesCount = GAMEOBJECT_END; m_respawnTime = 0; @@ -64,9 +63,9 @@ GameObject::GameObject() : WorldObject() GameObject::~GameObject() { - if(m_uint32Values) // field array can be not exist if GameOBject not loaded + /*if(m_uint32Values) // field array can be not exist if GameOBject not loaded { - // crash possible at access to deleted GO in Unit::m_gameobj + // Possible crash at access to deleted GO in Unit::m_gameobj uint64 owner_guid = GetOwnerGUID(); if(owner_guid) { @@ -76,7 +75,7 @@ GameObject::~GameObject() else if(!IS_PLAYER_GUID(owner_guid)) sLog.outError("Delete GameObject (GUID: %u Entry: %u ) that have references in not found creature %u GO list. Crash possible later.",GetGUIDLow(),GetGOInfo()->id,GUID_LOPART(owner_guid)); } - } + }*/ } void GameObject::AddToWorld() @@ -94,20 +93,30 @@ void GameObject::RemoveFromWorld() ///- Remove the gameobject from the accessor if(IsInWorld()) { - ObjectAccessor::Instance().RemoveObject(this); + // Possible crash at access to deleted GO in Unit::m_gameobj + if(uint64 owner_guid = GetOwnerGUID()) + { + Unit* owner = ObjectAccessor::GetUnit(*this,owner_guid); + if(owner) + owner->RemoveGameObject(this,false); + else if(!IS_PLAYER_GUID(owner_guid)) + sLog.outError("Delete GameObject (GUID: %u Entry: %u ) that have references in not found creature %u GO list. Crash possible later.",GetGUIDLow(),GetGOInfo()->id,GUID_LOPART(owner_guid)); + } WorldObject::RemoveFromWorld(); + ObjectAccessor::Instance().RemoveObject(this); } } -bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, uint32 go_state, uint32 ArtKit) +bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMask, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, uint32 go_state, uint32 ArtKit) { Relocate(x,y,z,ang); SetMapId(map->GetId()); SetInstanceId(map->GetInstanceId()); + SetPhaseMask(phaseMask,false); if(!IsPositionValid()) { - sLog.outError("ERROR: Gameobject (GUID: %u Entry: %u ) not created. Suggested coordinates isn't valid (X: %f Y: %f)",guidlow,name_id,x,y); + sLog.outError("Gameobject (GUID: %u Entry: %u ) not created. Suggested coordinates isn't valid (X: %f Y: %f)",guidlow,name_id,x,y); return false; } @@ -131,19 +140,18 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, float x, float SetFloatValue(GAMEOBJECT_POS_X, x); SetFloatValue(GAMEOBJECT_POS_Y, y); SetFloatValue(GAMEOBJECT_POS_Z, z); - SetFloatValue(GAMEOBJECT_FACING, ang); //this is not facing angle - SetFloatValue (GAMEOBJECT_ROTATION, rotation0); - SetFloatValue (GAMEOBJECT_ROTATION+1, rotation1); - SetFloatValue (GAMEOBJECT_ROTATION+2, rotation2); - SetFloatValue (GAMEOBJECT_ROTATION+3, rotation3); + SetFloatValue(GAMEOBJECT_PARENTROTATION+0, rotation0); + SetFloatValue(GAMEOBJECT_PARENTROTATION+1, rotation1); + + UpdateRotationFields(rotation2,rotation3); // GAMEOBJECT_FACING, GAMEOBJECT_ROTATION, GAMEOBJECT_PARENTROTATION+2/3 SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size); SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction); SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags); - SetUInt32Value(OBJECT_FIELD_ENTRY, goinfo->id); + SetEntry(goinfo->id); SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId); @@ -152,7 +160,7 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, float x, float SetGoAnimProgress(animprogress); - SetUInt32Value (GAMEOBJECT_ARTKIT, ArtKit); + SetByteValue(GAMEOBJECT_BYTES_1, 2, ArtKit); // Spell charges for GAMEOBJECT_TYPE_SPELLCASTER (22) if (goinfo->type == GAMEOBJECT_TYPE_SPELLCASTER) @@ -270,7 +278,11 @@ void GameObject::Update(uint32 /*p_time*/) return; } // respawn timer - MapManager::Instance().GetMap(GetMapId(), this)->Add(this); + uint16 poolid = poolhandler.IsPartOfAPool(GetGUIDLow(), TYPEID_GAMEOBJECT); + if (poolid) + poolhandler.UpdatePool(poolid, GetGUIDLow(), TYPEID_GAMEOBJECT); + else + GetMap()->Add(this); break; } } @@ -316,18 +328,18 @@ void GameObject::Update(uint32 /*p_time*/) if(owner && NeedDespawn) // hunter trap { Trinity::AnyUnfriendlyNoTotemUnitInObjectRangeCheck u_check(this, owner, radius); - Trinity::UnitSearcher<Trinity::AnyUnfriendlyNoTotemUnitInObjectRangeCheck> checker(ok, u_check); + Trinity::UnitSearcher<Trinity::AnyUnfriendlyNoTotemUnitInObjectRangeCheck> checker(this, ok, u_check); CellLock<GridReadGuard> cell_lock(cell, p); TypeContainerVisitor<Trinity::UnitSearcher<Trinity::AnyUnfriendlyNoTotemUnitInObjectRangeCheck>, GridTypeMapContainer > grid_object_checker(checker); - cell_lock->Visit(cell_lock, grid_object_checker, *MapManager::Instance().GetMap(GetMapId(), this)); + cell_lock->Visit(cell_lock, grid_object_checker, *GetMap()); // or unfriendly player/pet if(!ok) { TypeContainerVisitor<Trinity::UnitSearcher<Trinity::AnyUnfriendlyNoTotemUnitInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker); - cell_lock->Visit(cell_lock, world_object_checker, *MapManager::Instance().GetMap(GetMapId(), this)); + cell_lock->Visit(cell_lock, world_object_checker, *GetMap()); } } else // environmental trap @@ -336,13 +348,13 @@ void GameObject::Update(uint32 /*p_time*/) // affect only players Player* p_ok = NULL; - Trinity::AnyPlayerInObjectRangeCheck p_check(this, radius); - Trinity::PlayerSearcher<Trinity::AnyPlayerInObjectRangeCheck> checker(p_ok, p_check); + MaNGOS::AnyPlayerInObjectRangeCheck p_check(this, radius); + MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck> checker(this,p_ok, p_check); CellLock<GridReadGuard> cell_lock(cell, p); TypeContainerVisitor<Trinity::PlayerSearcher<Trinity::AnyPlayerInObjectRangeCheck>, WorldTypeMapContainer > world_object_checker(checker); - cell_lock->Visit(cell_lock, world_object_checker, *MapManager::Instance().GetMap(GetMapId(), this)); + cell_lock->Visit(cell_lock, world_object_checker, *GetMap()); ok = p_ok; } @@ -350,8 +362,8 @@ void GameObject::Update(uint32 /*p_time*/) { //Unit *caster = owner ? owner : ok; - //caster->CastSpell(ok, goInfo->trap.spellId, true); CastSpell(ok, goInfo->trap.spellId); + //caster->CastSpell(ok, goInfo->trap.spellId, true, 0, 0, GetGUID()); m_cooldownTime = time(NULL) + 4; // 4 seconds if(NeedDespawn) @@ -401,7 +413,7 @@ void GameObject::Update(uint32 /*p_time*/) for (; it != end; it++) { Unit* owner = Unit::GetUnit(*this, uint64(*it)); - if (owner) owner->CastSpell(owner, spellId, false); + if (owner) owner->CastSpell(owner, spellId, false, 0, 0, GetGUID()); } m_unique_users.clear(); @@ -420,7 +432,7 @@ void GameObject::Update(uint32 /*p_time*/) //burning flags in some battlegrounds, if you find better condition, just add it if (GetGoAnimProgress() > 0) { - SendObjectDeSpawnAnim(this->GetGUID()); + SendObjectDeSpawnAnim(GetGUID()); //reset flags SetUInt32Value(GAMEOBJECT_FLAGS, GetGOInfo()->flags); } @@ -457,7 +469,7 @@ void GameObject::Refresh() return; if(isSpawned()) - MapManager::Instance().GetMap(GetMapId(), this)->Add(this); + GetMap()->Add(this); } void GameObject::AddUniqueUse(Player* player) @@ -473,21 +485,26 @@ void GameObject::Delete() SetGoState(1); SetUInt32Value(GAMEOBJECT_FLAGS, GetGOInfo()->flags); - AddObjectToRemoveList(); + uint16 poolid = poolhandler.IsPartOfAPool(GetGUIDLow(), TYPEID_GAMEOBJECT); + if (poolid) + poolhandler.UpdatePool(poolid, GetGUIDLow(), TYPEID_GAMEOBJECT); + else + AddObjectToRemoveList(); } -void GameObject::getFishLoot(Loot *fishloot) +void GameObject::getFishLoot(Loot *fishloot, Player* loot_owner) { fishloot->clear(); - uint32 subzone = GetAreaId(); + uint32 zone, subzone; + GetZoneAndAreaId(zone,subzone); // if subzone loot exist use it if(LootTemplates_Fishing.HaveLootFor(subzone)) - fishloot->FillLoot(subzone, LootTemplates_Fishing, NULL); + fishloot->FillLoot(subzone, LootTemplates_Fishing, loot_owner,true); // else use zone loot else - fishloot->FillLoot(GetZoneId(), LootTemplates_Fishing, NULL); + fishloot->FillLoot(zone, LootTemplates_Fishing, loot_owner,true); } void GameObject::SaveToDB() @@ -501,10 +518,10 @@ void GameObject::SaveToDB() return; } - SaveToDB(GetMapId(), data->spawnMask); + SaveToDB(GetMapId(), data->spawnMask, data->phaseMask); } -void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask) +void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) { const GameObjectInfo *goI = GetGOInfo(); @@ -519,38 +536,40 @@ void GameObject::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.posX = GetFloatValue(GAMEOBJECT_POS_X); data.posY = GetFloatValue(GAMEOBJECT_POS_Y); data.posZ = GetFloatValue(GAMEOBJECT_POS_Z); data.orientation = GetFloatValue(GAMEOBJECT_FACING); - data.rotation0 = GetFloatValue(GAMEOBJECT_ROTATION+0); - data.rotation1 = GetFloatValue(GAMEOBJECT_ROTATION+1); - data.rotation2 = GetFloatValue(GAMEOBJECT_ROTATION+2); - data.rotation3 = GetFloatValue(GAMEOBJECT_ROTATION+3); + data.rotation0 = GetFloatValue(GAMEOBJECT_PARENTROTATION+0); + data.rotation1 = GetFloatValue(GAMEOBJECT_PARENTROTATION+1); + data.rotation2 = GetFloatValue(GAMEOBJECT_PARENTROTATION+2); + data.rotation3 = GetFloatValue(GAMEOBJECT_PARENTROTATION+3); data.spawntimesecs = m_spawnedByDefault ? m_respawnDelayTime : -(int32)m_respawnDelayTime; data.animprogress = GetGoAnimProgress(); data.go_state = GetGoState(); data.spawnMask = spawnMask; - data.ArtKit = GetUInt32Value (GAMEOBJECT_ARTKIT); + data.ArtKit = GetGoArtKit(); // updated in DB std::ostringstream ss; ss << "INSERT INTO gameobject VALUES ( " << m_DBTableGuid << ", " - << GetUInt32Value (OBJECT_FIELD_ENTRY) << ", " + << GetEntry() << ", " << mapid << ", " - << (uint32)spawnMask << ", " + << uint32(spawnMask) << "," // cast to prevent save as symbol + << uint16(GetPhaseMask()) << "," // prevent out of range error << GetFloatValue(GAMEOBJECT_POS_X) << ", " << GetFloatValue(GAMEOBJECT_POS_Y) << ", " << GetFloatValue(GAMEOBJECT_POS_Z) << ", " << GetFloatValue(GAMEOBJECT_FACING) << ", " - << GetFloatValue(GAMEOBJECT_ROTATION) << ", " - << GetFloatValue(GAMEOBJECT_ROTATION+1) << ", " - << GetFloatValue(GAMEOBJECT_ROTATION+2) << ", " - << GetFloatValue(GAMEOBJECT_ROTATION+3) << ", " + << GetFloatValue(GAMEOBJECT_PARENTROTATION) << ", " + << GetFloatValue(GAMEOBJECT_PARENTROTATION+1) << ", " + << GetFloatValue(GAMEOBJECT_PARENTROTATION+2) << ", " + << GetFloatValue(GAMEOBJECT_PARENTROTATION+3) << ", " << m_respawnDelayTime << ", " - << GetGoAnimProgress() << ", " - << GetGoState() << ")"; + << (uint32)GetGoAnimProgress() << ", " + << (uint32)GetGoState() << ")"; WorldDatabase.BeginTransaction(); WorldDatabase.PExecuteLog("DELETE FROM gameobject WHERE guid = '%u'", m_DBTableGuid); @@ -564,12 +583,13 @@ bool GameObject::LoadFromDB(uint32 guid, Map *map) if( !data ) { - sLog.outErrorDb("ERROR: Gameobject (GUID: %u) not found in table `gameobject`, can't load. ",guid); + sLog.outErrorDb("Gameobject (GUID: %u) not found in table `gameobject`, can't load. ",guid); return false; } uint32 entry = data->id; - uint32 map_id = data->mapid; + //uint32 map_id = data->mapid; // already used before call + uint32 phaseMask = data->phaseMask; float x = data->posX; float y = data->posY; float z = data->posZ; @@ -587,7 +607,7 @@ bool GameObject::LoadFromDB(uint32 guid, Map *map) m_DBTableGuid = guid; if (map->GetInstanceId() != 0) guid = objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT); - if (!Create(guid,entry, map, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state, ArtKit) ) + if (!Create(guid,entry, map, phaseMask, x, y, z, ang, rotation0, rotation1, rotation2, rotation3, animprogress, go_state, ArtKit) ) return false; switch(GetGOInfo()->type) @@ -730,14 +750,10 @@ bool GameObject::isVisibleForInState(Player const* u, bool inVisibleList) const if(owner && u->IsHostileTo(owner) && !canDetectTrap(u, GetDistance(u))) return false; } - - // Smuggled Mana Cell required 10 invisibility type detection/state - if(GetEntry()==187039 && ((u->m_detectInvisibilityMask | u->m_invisibilityMask) & (1<<10))==0) - return false; } // check distance - return IsWithinDistInMap(u,World::GetMaxVisibleDistanceForObject() + + return IsWithinDistInMap(u->m_seer,World::GetMaxVisibleDistanceForObject() + (inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false); } @@ -816,7 +832,20 @@ void GameObject::TriggeringLinkedGameObject( uint32 trapEntry, Unit* target) if(!trapSpell) // checked at load already return; - float range = GetSpellMaxRange(sSpellRangeStore.LookupEntry(trapSpell->rangeIndex)); + float range; + SpellRangeEntry const * srentry = sSpellRangeStore.LookupEntry(trapSpell->rangeIndex); + //get owner to check hostility of GameObject + if (GetSpellMaxRangeForHostile(srentry) == GetSpellMaxRangeForHostile(srentry)) + range = GetSpellMaxRangeForHostile(srentry); + else + { + Unit * owner=GetOwner(); + if (owner) + range = owner->GetSpellMaxRangeForTarget(target, srentry); + else + //if no owner assume that object is hostile to target + range = GetSpellMaxRangeForHostile(srentry); + } // search nearest linked GO GameObject* trapGO = NULL; @@ -826,18 +855,18 @@ void GameObject::TriggeringLinkedGameObject( uint32 trapEntry, Unit* target) Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; - Trinity::NearestGameObjectEntryInObjectRangeCheck go_check(*target,trapEntry,range); - Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> checker(trapGO,go_check); + MaNGOS::NearestGameObjectEntryInObjectRangeCheck go_check(*target,trapEntry,range); + MaNGOS::GameObjectLastSearcher<MaNGOS::NearestGameObjectEntryInObjectRangeCheck> checker(this, trapGO,go_check); TypeContainerVisitor<Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck>, GridTypeMapContainer > object_checker(checker); CellLock<GridReadGuard> cell_lock(cell, p); - cell_lock->Visit(cell_lock, object_checker, *MapManager::Instance().GetMap(GetMapId(), this)); + cell_lock->Visit(cell_lock, object_checker, *GetMap()); } // found correct GO // FIXME: when GO casting will be implemented trap must cast spell to target if(trapGO) - target->CastSpell(target,trapSpell,true); + target->CastSpell(target,trapSpell,true, 0, 0, GetGUID()); } GameObject* GameObject::LookupFishingHoleAround(float range) @@ -847,13 +876,13 @@ GameObject* GameObject::LookupFishingHoleAround(float range) CellPair p(Trinity::ComputeCellPair(GetPositionX(),GetPositionY())); Cell cell(p); cell.data.Part.reserved = ALL_DISTRICT; - Trinity::NearestGameObjectFishingHole u_check(*this, range); - Trinity::GameObjectSearcher<Trinity::NearestGameObjectFishingHole> checker(ok, u_check); + MaNGOS::NearestGameObjectFishingHole u_check(*this, range); + MaNGOS::GameObjectSearcher<MaNGOS::NearestGameObjectFishingHole> checker(this, ok, u_check); CellLock<GridReadGuard> cell_lock(cell, p); TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::NearestGameObjectFishingHole>, GridTypeMapContainer > grid_object_checker(checker); - cell_lock->Visit(cell_lock, grid_object_checker, *MapManager::Instance().GetMap(GetMapId(), this)); + cell_lock->Visit(cell_lock, grid_object_checker, *GetMap()); return ok; } @@ -873,9 +902,9 @@ void GameObject::UseDoorOrButton(uint32 time_to_restore) } -void GameObject::SetGoArtKit(uint32 kit) +void GameObject::SetGoArtKit(uint8 kit) { - SetUInt32Value(GAMEOBJECT_ARTKIT, kit); + SetByteValue(GAMEOBJECT_BYTES_1, 2, kit); GameObjectData *data = const_cast<GameObjectData*>(objmgr.GetGOData(m_DBTableGuid)); if(data) data->ArtKit = kit; @@ -899,6 +928,7 @@ void GameObject::Use(Unit* user) // by default spell caster is user Unit* spellCaster = user; uint32 spellId = 0; + bool triggered = false; switch(GetGoType()) { @@ -980,7 +1010,7 @@ void GameObject::Use(Unit* user) // fallback, will always work player->TeleportTo(GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation(),TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET); } - player->SetStandState(PLAYER_STATE_SIT_LOW_CHAIR+info->chair.height); + player->SetStandState(UNIT_STAND_STATE_SIT_LOW_CHAIR+info->chair.height); return; } //big gun, its a spell/aura @@ -1020,12 +1050,9 @@ void GameObject::Use(Unit* user) Player* player = (Player*)user; - if(info->camera.cinematicId) - { - WorldPacket data(SMSG_TRIGGER_CINEMATIC, 4); - data << info->camera.cinematicId; - player->GetSession()->SendPacket(&data); - } + if (info->camera.cinematicId) + player->SendCinematicStart(info->camera.cinematicId); + return; } //fishing bobber @@ -1047,11 +1074,12 @@ void GameObject::Use(Unit* user) // 2) if skill == base_zone_skill => 5% chance // 3) chance is linear dependence from (base_zone_skill-skill) - uint32 subzone = GetAreaId(); + uint32 zone, subzone; + GetZoneAndAreaId(zone,subzone); int32 zone_skill = objmgr.GetFishingBaseSkillLevel( subzone ); if(!zone_skill) - zone_skill = objmgr.GetFishingBaseSkillLevel( GetZoneId() ); + zone_skill = objmgr.GetFishingBaseSkillLevel( zone ); //provide error, no fishable zone or area should be 0 if(!zone_skill) @@ -1142,6 +1170,13 @@ void GameObject::Use(Unit* user) return; spellId = info->summoningRitual.spellId; + if(spellId==62330) // GO store not existed spell, replace by expected + { + // spell have reagent and mana cost but it not expected use its + // it triggered spell in fact casted at currently channeled GO + spellId = 61993; + triggered = true; + } // finish spell caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->SendChannelUpdate(0); @@ -1199,7 +1234,10 @@ void GameObject::Use(Unit* user) if (level < info->meetingstone.minLevel || level > info->meetingstone.maxLevel) return; - spellId = 23598; + if(info->id==194097) + spellId = 61994; // Ritual of Summoning + else + spellId = 59782; // Summoning Stone Effect break; } @@ -1211,7 +1249,7 @@ void GameObject::Use(Unit* user) Player* player = (Player*)user; - if( player->isAllowUseBattleGroundObject() ) + if( player->CanUseBattleGroundObject() ) { // in battleground check BattleGround *bg = player->GetBattleGround(); @@ -1236,7 +1274,7 @@ void GameObject::Use(Unit* user) Player* player = (Player*)user; - if( player->isAllowUseBattleGroundObject() ) + if( player->CanUseBattleGroundObject() ) { // in battleground check BattleGround *bg = player->GetBattleGround(); @@ -1274,6 +1312,26 @@ void GameObject::Use(Unit* user) } break; } + case GAMEOBJECT_TYPE_BARBER_CHAIR: //32 + { + GameObjectInfo const* info = GetGOInfo(); + if(!info) + return; + + if(user->GetTypeId()!=TYPEID_PLAYER) + return; + + Player* player = (Player*)user; + + // fallback, will always work + player->TeleportTo(GetMapId(), GetPositionX(), GetPositionY(), GetPositionZ(), GetOrientation(),TELE_TO_NOT_LEAVE_TRANSPORT | TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET); + + WorldPacket data(SMSG_ENABLE_BARBER_SHOP, 0); + player->GetSession()->SendPacket(&data); + + player->SetStandState(UNIT_STAND_STATE_SIT_LOW_CHAIR+info->barberChair.chairheight); + return; + } default: sLog.outDebug("Unknown Object Type %u", GetGoType()); break; @@ -1292,7 +1350,7 @@ void GameObject::Use(Unit* user) return; } - Spell *spell = new Spell(spellCaster, spellInfo, false); + Spell *spell = new Spell(spellCaster, spellInfo, triggered); // spell target is user of GO SpellCastTargets targets; @@ -1301,8 +1359,28 @@ void GameObject::Use(Unit* user) spell->prepare(&targets); } -void GameObject::CastSpell(Unit* target, uint32 spell) +void GameObject::CastSpell(Unit* target, uint32 spellId) { + SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId); + if(!spellInfo) + return; + + bool self = false; + for(int i = 0; i < 3; ++i) + { + if(spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_CASTER) + { + self = true; + break; + } + } + + if(self) + { + target->CastSpell(target, spellInfo, true); + return; + } + //summon world trigger Creature *trigger = SummonTrigger(GetPositionX(), GetPositionY(), GetPositionZ(), 0, 1); if(!trigger) return; @@ -1311,12 +1389,12 @@ void GameObject::CastSpell(Unit* target, uint32 spell) if(Unit *owner = GetOwner()) { trigger->setFaction(owner->getFaction()); - trigger->CastSpell(target, spell, true, 0, 0, owner->GetGUID()); + trigger->CastSpell(target, spellInfo, true, 0, 0, owner->GetGUID()); } else { trigger->setFaction(14); - trigger->CastSpell(target, spell, true, 0, 0, target->GetGUID()); + trigger->CastSpell(target, spellInfo, true, 0, 0, target->GetGUID()); } //trigger->setDeathState(JUST_DIED); //trigger->RemoveCorpse(); @@ -1338,3 +1416,25 @@ const char* GameObject::GetNameForLocaleIdx(int32 loc_idx) const return GetName(); } +void GameObject::UpdateRotationFields(float rotation2 /*=0.0f*/, float rotation3 /*=0.0f*/) +{ + static double const atan_pow = atan(pow(2.0f, -20.0f)); + + SetFloatValue(GAMEOBJECT_FACING, GetOrientation()); + + double f_rot1 = sin(GetOrientation() / 2.0f); + double f_rot2 = cos(GetOrientation() / 2.0f); + + int64 i_rot1 = int64(f_rot1 / atan_pow *(f_rot2 >= 0 ? 1.0f : -1.0f)); + int64 rotation = (i_rot1 << 43 >> 43) & 0x00000000001FFFFF; + SetUInt64Value(GAMEOBJECT_ROTATION, rotation); + + if(rotation2==0.0f && rotation3==0.0f) + { + rotation2 = f_rot1; + rotation3 = f_rot2; + } + + SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rotation2); + SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rotation3); +} |