diff options
author | tartalo <none@none> | 2009-10-22 17:58:25 +0200 |
---|---|---|
committer | tartalo <none@none> | 2009-10-22 17:58:25 +0200 |
commit | b90f307f3e88e7b9cb456a6458cb8614e3765fab (patch) | |
tree | 03f8e70e89d23f1069483ec877fc2f78cecf8d7f | |
parent | 9e8961bc4cd9bb99b863031924f16c6306a1e35d (diff) |
*Wintergrasp: Implementation of spirit guides (Part 1), by Spp
*Wintergrasp: minor code optimizations, by Spp
*Wintergrasp: Fortress workshop are not capturable, by Spp
--HG--
branch : trunk
-rw-r--r-- | src/game/BattleGroundHandler.cpp | 39 | ||||
-rw-r--r-- | src/game/Wintergrasp.cpp | 363 | ||||
-rw-r--r-- | src/game/Wintergrasp.h | 27 |
3 files changed, 348 insertions, 81 deletions
diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index caf400f7364..bcd446cadfa 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -35,6 +35,11 @@ #include "Object.h" #include "Opcodes.h" +// Temporal fix to wintergrasp spirit guides till 3.2 +#include "Wintergrasp.h" +#include "OutdoorPvPMgr.h" +// WG end + void WorldSession::HandleBattlemasterHelloOpcode( WorldPacket & recv_data ) { uint64 guid; @@ -577,8 +582,6 @@ void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket & recv_data ) sLog.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUERY"); BattleGround *bg = _player->GetBattleGround(); - if (!bg) - return; uint64 guid; recv_data >> guid; @@ -590,7 +593,19 @@ void WorldSession::HandleAreaSpiritHealerQueryOpcode( WorldPacket & recv_data ) if(!unit->isSpiritService()) // it's not spirit service return; - sBattleGroundMgr.SendAreaSpiritHealerQueryOpcode(_player, bg, guid); + if (bg) + { + sBattleGroundMgr.SendAreaSpiritHealerQueryOpcode(_player, bg, guid); + } + else + { // Wintergrasp Hack till 3.2 and it's implemented as BG + if (GetPlayer()->GetZoneId() == 4197) + { + OPvPWintergrasp *pvpWG = (OPvPWintergrasp*)sOutdoorPvPMgr.GetOutdoorPvPToZoneId(4197); + if (pvpWG && pvpWG->isWarTime()) + pvpWG->SendAreaSpiritHealerQueryOpcode(_player, guid); + } + } } void WorldSession::HandleAreaSpiritHealerQueueOpcode( WorldPacket & recv_data ) @@ -598,8 +613,6 @@ void WorldSession::HandleAreaSpiritHealerQueueOpcode( WorldPacket & recv_data ) sLog.outDebug("WORLD: CMSG_AREA_SPIRIT_HEALER_QUEUE"); BattleGround *bg = _player->GetBattleGround(); - if (!bg) - return; uint64 guid; recv_data >> guid; @@ -611,7 +624,21 @@ void WorldSession::HandleAreaSpiritHealerQueueOpcode( WorldPacket & recv_data ) if(!unit->isSpiritService()) // it's not spirit service return; - bg->AddPlayerToResurrectQueue(guid, _player->GetGUID()); + if (bg) + { + bg->AddPlayerToResurrectQueue(guid, _player->GetGUID()); + } + else + { // Wintergrasp Hack till 3.2 and it's implemented as BG + if (GetPlayer()->GetZoneId() == 4197) + { + OPvPWintergrasp *pvpWG = (OPvPWintergrasp*)sOutdoorPvPMgr.GetOutdoorPvPToZoneId(4197); + if (pvpWG && pvpWG->isWarTime()) + pvpWG->AddPlayerToResurrectQueue(guid, _player->GetGUID()); + } + } + + } void WorldSession::HandleBattlemasterJoinArena( WorldPacket & recv_data ) diff --git a/src/game/Wintergrasp.cpp b/src/game/Wintergrasp.cpp index 778214ceecb..01cd5189c58 100644 --- a/src/game/Wintergrasp.cpp +++ b/src/game/Wintergrasp.cpp @@ -36,7 +36,8 @@ enum CreatureEntry { CRE_ENG_A = 30499, CRE_ENG_H = 30400, - SPIRIT_HEALER = 6491, + CRE_SPI_A = 31842, + CRE_SPI_H = 31841, }; const TeamPair CreatureEntryPair[] = @@ -52,14 +53,14 @@ const TeamPair CreatureEntryPair[] = {31053, 31054}, // Primalist & Anchorite {31091, 31036}, // Commander {32615, 32626}, // Warbringer & Brigadier General - {0,0} + {0,0} // Do not delete Used in LoadTeamPair }; const TeamPair GODisplayPair[] = { {5651, 5652}, {8256, 8257}, - {0,0} + {0,0} // Do not delete Used in LoadTeamPair }; void LoadTeamPair(TeamPairMap &pairMap, const TeamPair *pair) @@ -72,9 +73,21 @@ void LoadTeamPair(TeamPairMap &pairMap, const TeamPair *pair) } } +void RespawnCreatureIfNeeded(Creature *cr, uint32 guid) +{ + if (cr) + { + cr->SetOriginalEntry(guid); + if (guid != cr->GetEntry() || !cr->isAlive()) + cr->Respawn(true); + cr->SetVisibility(VISIBILITY_ON); + } +} + #define REMOVE_WARTIME_AURAS(p) (p)->RemoveAura(SPELL_RECRUIT);\ (p)->RemoveAura(SPELL_CORPORAL);(p)->RemoveAura(SPELL_LIEUTENANT);\ - (p)->RemoveAura(SPELL_TOWER_CONTROL);(p)->RemoveAura(SPELL_RULLERS_OF_WG) + (p)->RemoveAura(SPELL_TOWER_CONTROL);(p)->RemoveAura(SPELL_RULLERS_OF_WG);\ + (p)->RemoveAura(SPELL_SPIRITUAL_IMMUNITY) #define REMOVE_TENACITY_AURA(p) CastTenacity(p, 0) // Visual defines, easier to understand code @@ -86,6 +99,8 @@ typedef std::list<const AreaPOIEntry *> AreaPOIList; OPvPWintergrasp::OPvPWintergrasp() { m_TypeId = OPVP_WINTERGRASP; + + m_LastResurrectTime = 0; // Temporal copy of BG system till 3.2 } bool OPvPWintergrasp::SetupOutdoorPvP() @@ -100,6 +115,36 @@ bool OPvPWintergrasp::SetupOutdoorPvP() m_tenacityStack = 0; m_gate = NULL; + std::list<uint32> engGuids; + std::list<uint32> spiritGuids; + + // Store Eng and spirit guide guids for later use + QueryResult *result = WorldDatabase.PQuery("SELECT guid, id FROM creature" + " WHERE creature.map=571 AND creature.id IN (%u, %u, %u, %u);", + CRE_ENG_A, CRE_ENG_H, CRE_SPI_A, CRE_SPI_H); + + if (!result) + sLog.outError("Cannot find siege workshop master or spirit guides in creature!"); + else + { + do + { + Field *fields = result->Fetch(); + switch(fields[1].GetUInt32()) + { + case CRE_ENG_A: + case CRE_ENG_H: + engGuids.push_back(fields[0].GetUInt32()); + break; + case CRE_SPI_A: + case CRE_SPI_H: + spiritGuids.push_back(fields[0].GetUInt32()); + break; + } + }while(result->NextRow()); + delete result; + } + // Select POI AreaPOIList areaPOIs; float minX = 9999, minY = 9999, maxX = -9999, maxY = -9999; @@ -118,7 +163,7 @@ bool OPvPWintergrasp::SetupOutdoorPvP() minX -= 20; minY -= 20; maxX += 20; maxY += 20; // Coords: 4290.330078, 1790.359985 - 5558.379883, 4048.889893 - QueryResult *result = WorldDatabase.PQuery("SELECT guid FROM gameobject,gameobject_template" + result = WorldDatabase.PQuery("SELECT guid FROM gameobject,gameobject_template" " WHERE gameobject.map=571" " AND gameobject.position_x>%f AND gameobject.position_y>%f" " AND gameobject.position_x<%f AND gameobject.position_y<%f" @@ -179,27 +224,16 @@ bool OPvPWintergrasp::SetupOutdoorPvP() capturePointEntry = 190487; break; } - // TODO - Get Engs from DB only 1 time, not 6 + if (capturePointEntry) { uint32 engGuid = 0; - - QueryResult *result = WorldDatabase.PQuery("SELECT guid FROM creature" - " WHERE creature.map=571" - " AND creature.id IN (%u, %u);", CRE_ENG_A, CRE_ENG_H); - - if (!result) - { - sLog.outError("Cannot find siege workshop master in creature!"); - continue; - } - + uint32 spiritGuid = 0; + // Find closest Eng to Workshop float minDist = 100; - do + for (std::list<uint32>::iterator itr = engGuids.begin(); itr != engGuids.end(); ++itr) { - Field *fields = result->Fetch(); - uint32 guid = fields[0].GetUInt32(); - const CreatureData *creData = objmgr.GetCreatureData(guid); + const CreatureData *creData = objmgr.GetCreatureData(*itr); if (!creData) continue; @@ -207,35 +241,64 @@ bool OPvPWintergrasp::SetupOutdoorPvP() if (minDist > dist) { minDist = dist; - engGuid = guid; + engGuid = *itr; } - }while(result->NextRow()); - delete result; + } if (!engGuid) { sLog.outError("Cannot find nearby siege workshop master!"); continue; } + else + engGuids.remove(engGuid); + // Find closest Spirit Guide to Workshop + minDist = 255; + for (std::list<uint32>::iterator itr = spiritGuids.begin(); itr != spiritGuids.end(); ++itr) + { + const CreatureData *creData = objmgr.GetCreatureData(*itr); + if (!creData) + continue; + + float dist = (abs(creData->posX - x) + abs(creData->posY - y)); + if (minDist > dist) + { + minDist = dist; + spiritGuid = *itr; + } + } + // Inside fortress won't be capturable SiegeWorkshop *workshop = new SiegeWorkshop(this, m_buildingStates[guid]); - if (!workshop->SetCapturePointData(capturePointEntry, goData->mapid, goData->posX + 40 * cos(goData->orientation + M_PI / 2), goData->posY + 40 * sin(goData->orientation + M_PI / 2), goData->posZ)) + if (goData->posX < POS_X_CENTER && !workshop->SetCapturePointData(capturePointEntry, goData->mapid, goData->posX + 40 * cos(goData->orientation + M_PI / 2), goData->posY + 40 * sin(goData->orientation + M_PI / 2), goData->posZ)) { delete workshop; sLog.outError("Cannot add capture point!"); continue; } + const CreatureData *creData = objmgr.GetCreatureData(engGuid); if (!creData) continue; workshop->m_engEntry = const_cast<uint32*>(&creData->id); const_cast<CreatureData*>(creData)->displayid = 0; - workshop->m_workshopGuid = guid; workshop->m_engGuid = engGuid; - //workshop->AddGO(0, guid, goData->id); - //workshop->AddCre(0, engGuid, creData->id); - //sLog.outDebug("Demolisher Engineerer lowguid %u is linked to workshop lowguid %u.", engGuid, guid); + + // Back spirit is linked to one of the inside workshops, 1 workshop wont have spirit + if (spiritGuid) + { + spiritGuids.remove(spiritGuid); + + const CreatureData *spiritData = objmgr.GetCreatureData(spiritGuid); + if (!spiritData) + continue; + + workshop->m_spiEntry = const_cast<uint32*>(&spiritData->id); + const_cast<CreatureData*>(spiritData)->displayid = 0; + workshop->m_spiGuid = spiritGuid; + } + workshop->m_workshopGuid = guid; AddCapturePoint(workshop); m_buildingStates[guid]->type = BUILDING_WORKSHOP; workshop->SetTeamByBuildingState(); @@ -243,6 +306,9 @@ bool OPvPWintergrasp::SetupOutdoorPvP() }while(result->NextRow()); delete result; + engGuids.clear(); + spiritGuids.clear(); + if (!m_gate) { sLog.outError("Cannot find wintergrasp fortress gate!"); @@ -446,6 +512,11 @@ WintergraspCreType OPvPWintergrasp::GetCreatureType(uint32 entry) const case 30739:case 30740: // Champions case 32307:case 32308: // Guards return CREATURE_GUARD; + case CRE_SPI_A: // Dwarven Spirit Guide + case CRE_SPI_H: // Taunka Spirit Guide + return CREATURE_SPIRIT_GUIDE; + case 6491: // Spirit Healers + return CREATURE_SPIRIT_HEALER; case 31101:case 31051: // Hoodoo Master & Sorceress case 31102:case 31052: // Vieron Blazefeather & Bowyer case 31107:case 31109: // Lieutenant & Senior Demolitionist @@ -456,8 +527,6 @@ WintergraspCreType OPvPWintergrasp::GetCreatureType(uint32 entry) const case 32615:case 32626: // Warbringer && Brigadier General case 32296:case 32294: // Quartermaster case 30870:case 30869: // Flight Masters - case 31841:case 31842: // Spirit Guides - case SPIRIT_HEALER: // Spirit Healers return CREATURE_SPECIAL; default: return CREATURE_OTHER; // Revenants, Elementals, etc @@ -537,6 +606,18 @@ void OPvPWintergrasp::OnCreatureCreate(Creature *creature, bool add) } } break; + case CREATURE_SPIRIT_GUIDE: + for (OutdoorPvP::OPvPCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr) + { + if (SiegeWorkshop *workshop = dynamic_cast<SiegeWorkshop*>(itr->second)) + if (workshop->m_spiGuid == creature->GetDBTableGUIDLow()) + { + workshop->m_spiritguide = add ? creature : NULL; + break; + } + } + creature->CastSpell(creature, SPELL_SPIRITUAL_IMMUNITY, true); + case CREATURE_SPIRIT_HEALER: case CREATURE_TURRET: case CREATURE_OTHER: UpdateCreatureInfo(creature); @@ -696,22 +777,36 @@ bool OPvPWintergrasp::UpdateCreatureInfo(Creature *creature) const creature->SetVisibility(VISIBILITY_ON); } return false; + case CREATURE_SPIRIT_GUIDE: + if (isWarTime()) + { + creature->SetVisibility(VISIBILITY_ON); + //creature->setDeathState(ALIVE); + } + else + { + creature->SetVisibility(VISIBILITY_OFF); + //creature->setDeathState(DEAD); + } + return false; + case CREATURE_SPIRIT_HEALER: + creature->SetVisibility(isWarTime() ? VISIBILITY_OFF : VISIBILITY_ON); + return false; case CREATURE_ENGINEER: return false; case CREATURE_SIEGE_VEHICLE: creature->DisappearAndDie(); return false; + case CREATURE_GUARD: + case CREATURE_SPECIAL: + TeamPairMap::const_iterator itr = m_creEntryPair.find(creature->GetCreatureData()->id); + if (itr != m_creEntryPair.end()) + { + entry = getDefenderTeam() == TEAM_ALLIANCE ? itr->second : itr->first; + RespawnCreatureIfNeeded(creature, entry); + } + return false; } - - TeamPairMap::const_iterator itr = m_creEntryPair.find(creature->GetCreatureData()->id); - if (itr != m_creEntryPair.end()) - { - entry = getDefenderTeam() == TEAM_ALLIANCE ? itr->second : itr->first; - creature->SetOriginalEntry(entry); - if (entry != creature->GetEntry() || !creature->isAlive()) - creature->Respawn(true); - } - return false; } // Return false = Need to rebuild at battle End/Start @@ -766,10 +861,12 @@ bool OPvPWintergrasp::UpdateGameObjectInfo(GameObject *go) const void OPvPWintergrasp::HandlePlayerEnterZone(Player * plr, uint32 zone) { - if (!isWarTime() && (plr->GetTeamId() == getDefenderTeam())) - plr->CastSpell(plr,SPELL_ESSENCE_OF_WG,true); - - if (isWarTime() && !plr->HasAura(SPELL_RECRUIT) && !plr->HasAura(SPELL_CORPORAL) + if (!isWarTime()) + { + if (plr->GetTeamId() == getDefenderTeam()) + plr->CastSpell(plr,SPELL_ESSENCE_OF_WG, true); + } + else if (!plr->HasAura(SPELL_RECRUIT) && !plr->HasAura(SPELL_CORPORAL) && !plr->HasAura(SPELL_LIEUTENANT)) plr->CastSpell(plr, SPELL_RECRUIT, true); @@ -778,7 +875,7 @@ void OPvPWintergrasp::HandlePlayerEnterZone(Player * plr, uint32 zone) UpdateTenacityStack(); } -// Reapply Tenacity if needed +// Reapply Auras if needed void OPvPWintergrasp::HandlePlayerResurrects(Player * plr, uint32 zone) { if (isWarTime()) @@ -978,23 +1075,6 @@ void OPvPWintergrasp::UpdateTenacityStack() } } -void OPvPWintergrasp::VehicleCastSpell(TeamId team, int32 spellId) const -{ - if (spellId > 0) - for (CreatureSet::const_iterator itr = m_vehicles[team].begin(); itr != m_vehicles[team].end(); ++itr) - (*itr)->CastSpell(*itr, (uint32)spellId, true); - else - for (CreatureSet::const_iterator itr = m_vehicles[team].begin(); itr != m_vehicles[team].end(); ++itr) - (*itr)->RemoveAura((uint32)-spellId); // by stack? -} - -void OPvPWintergrasp::LieutenantCastSpell(TeamId team, int32 spellId) const -{ - for (PlayerSet::const_iterator itr = m_players[team].begin(); itr != m_players[team].end(); ++itr) - if ((*itr)->HasAura(SPELL_LIEUTENANT) && ((*itr)->getLevel() > 69)) - (*itr)->CastSpell(*itr, (uint32)spellId, true); -} - void OPvPWintergrasp::UpdateClockDigit(uint32 &timer, uint32 digit, uint32 mod) { uint32 value = timer%mod; @@ -1027,8 +1107,66 @@ bool OPvPWintergrasp::Update(uint32 diff) m_timer -= diff; if (isWarTime()) + { OutdoorPvP::Update(diff); // update capture points + /*********************************************************/ + /*** BATTLEGROUND RESSURECTION SYSTEM ***/ + /*********************************************************/ + + //this should be handled by spell system + m_LastResurrectTime += diff; + if (m_LastResurrectTime >= RESURRECTION_INTERVAL) + { + if (GetReviveQueueSize()) + { + for (std::map<uint64, std::vector<uint64> >::iterator itr = m_ReviveQueue.begin(); itr != m_ReviveQueue.end(); ++itr) + { + Creature *sh = NULL; + for (std::vector<uint64>::const_iterator itr2 = (itr->second).begin(); itr2 != (itr->second).end(); ++itr2) + { + Player *plr = objmgr.GetPlayer(*itr2); + if (!plr) + continue; + + if (!sh && plr->IsInWorld()) + { + sh = plr->GetMap()->GetCreature(itr->first); + // only for visual effect + if (sh) + // Spirit Heal, effect 117 + sh->CastSpell(sh, SPELL_SPIRIT_HEAL, true); + } + + // Resurrection visual + plr->CastSpell(plr, SPELL_RESURRECTION_VISUAL, true); + m_ResurrectQueue.push_back(*itr2); + } + (itr->second).clear(); + } + + m_ReviveQueue.clear(); + m_LastResurrectTime = 0; + } + else + // queue is clear and time passed, just update last resurrection time + m_LastResurrectTime = 0; + } + else if (m_LastResurrectTime > 500) // Resurrect players only half a second later, to see spirit heal effect on NPC + { + for (std::vector<uint64>::const_iterator itr = m_ResurrectQueue.begin(); itr != m_ResurrectQueue.end(); ++itr) + { + Player *plr = objmgr.GetPlayer(*itr); + if (!plr) + continue; + plr->ResurrectPlayer(1.0f); + plr->CastSpell(plr, 6962, true); + plr->CastSpell(plr, SPELL_SPIRIT_HEAL_MANA, true); + ObjectAccessor::Instance().ConvertCorpseForPlayer(*itr); + } + m_ResurrectQueue.clear(); + } + } UpdateClock(); } else @@ -1080,10 +1218,12 @@ void OPvPWintergrasp::StartBattle() // Add recruit Aura, Add Tenacity TeamCastSpell(getDefenderTeam(), SPELL_RECRUIT); TeamCastSpell(getAttackerTeam(), SPELL_RECRUIT); + // Add Towert Control to attackers for (PlayerSet::iterator itr = m_players[getAttackerTeam()].begin(); itr != m_players[getAttackerTeam()].end(); ++itr) if ((*itr)->getLevel() > 69) (*itr)->SetAuraStack(SPELL_TOWER_CONTROL, (*itr), 3); UpdateTenacityStack(); + // Remove non wartime auras TeamCastSpell(getDefenderTeam(),-SPELL_ESSENCE_OF_WG); } @@ -1307,13 +1447,84 @@ SiegeWorkshop *OPvPWintergrasp::GetWorkshopByGOGuid(uint32 lowguid) const return NULL; } +/*######################################################## + * Copy of Battleground system to make Spirit Guides Work + *#######################################################*/ +void OPvPWintergrasp::SendAreaSpiritHealerQueryOpcode(Player *pl, const uint64& guid) +{ + WorldPacket data(SMSG_AREA_SPIRIT_HEALER_TIME, 12); + uint32 time_ = 30000 - GetLastResurrectTime(); // resurrect every 30 seconds + if (time_ == uint32(-1)) + time_ = 0; + data << guid << time_; + pl->GetSession()->SendPacket(&data); +} + +void OPvPWintergrasp::AddPlayerToResurrectQueue(uint64 npc_guid, uint64 player_guid) +{ + m_ReviveQueue[npc_guid].push_back(player_guid); + + Player *plr = objmgr.GetPlayer(player_guid); + if (!plr) + return; + + plr->CastSpell(plr, SPELL_WAITING_FOR_RESURRECT, true); +} + +void OPvPWintergrasp::RemovePlayerFromResurrectQueue(uint64 player_guid) +{ + for (std::map<uint64, std::vector<uint64> >::iterator itr = m_ReviveQueue.begin(); itr != m_ReviveQueue.end(); ++itr) + { + for (std::vector<uint64>::iterator itr2 =(itr->second).begin(); itr2 != (itr->second).end(); ++itr2) + { + if (*itr2 == player_guid) + { + (itr->second).erase(itr2); + + Player *plr = objmgr.GetPlayer(player_guid); + if (!plr) + return; + + plr->RemoveAurasDueToSpell(SPELL_WAITING_FOR_RESURRECT); + + return; + } + } + } +} + +void OPvPWintergrasp::RelocateDeadPlayers(Creature *cr) +{ + if (!cr || GetCreatureType(cr->GetEntry()) != CREATURE_SPIRIT_GUIDE) + return; + + // Those who are waiting to resurrect at this node are taken to the closest own node's graveyard + std::vector<uint64> ghost_list = m_ReviveQueue[cr->GetGUID()]; + if (!ghost_list.empty()) + { + WorldSafeLocsEntry const *ClosestGrave = NULL; + for (std::vector<uint64>::const_iterator itr = ghost_list.begin(); itr != ghost_list.end(); ++itr) + { + Player* plr = objmgr.GetPlayer(*itr); + if (!plr) + continue; + + if (!ClosestGrave) + ClosestGrave = objmgr.GetClosestGraveYard(plr->GetPositionX(), plr->GetPositionY(), plr->GetPositionZ(), plr->GetMapId(), plr->GetTeam()); + + if (ClosestGrave) + plr->TeleportTo(plr->GetMapId(), ClosestGrave->x, ClosestGrave->y, ClosestGrave->z, plr->GetOrientation()); + } + } +} + /*###### ##SiegeWorkshop ######*/ SiegeWorkshop::SiegeWorkshop(OPvPWintergrasp *opvp, BuildingState *state) : OPvPCapturePoint(opvp), m_buildingState(state), m_wintergrasp(opvp) -, m_engineer(NULL), m_engGuid(0) +, m_engineer(NULL), m_engGuid(0), m_spiritguide(NULL), m_spiGuid(0) { } @@ -1348,15 +1559,20 @@ void SiegeWorkshop::SetTeamByBuildingState() void SiegeWorkshop::ChangeTeam(TeamId oldTeam) { uint32 entry = 0; + uint32 guide_entry = 0; + if (oldTeam != TEAM_NEUTRAL) m_wintergrasp->ModifyWorkshopCount(oldTeam, false); + if (m_team != TEAM_NEUTRAL) { entry = m_team == TEAM_ALLIANCE ? CRE_ENG_A : CRE_ENG_H; + guide_entry = m_team == TEAM_ALLIANCE ? CRE_SPI_A : CRE_SPI_H; m_wintergrasp->ModifyWorkshopCount(m_team, true); } - GameObject::SetGoArtKit(CapturePointArtKit[m_team], m_capturePoint, m_capturePointGUID); + if (m_capturePoint) + GameObject::SetGoArtKit(CapturePointArtKit[m_team], m_capturePoint, m_capturePointGUID); m_buildingState->SetTeam(m_team); // TODO: this may be sent twice @@ -1367,17 +1583,16 @@ void SiegeWorkshop::ChangeTeam(TeamId oldTeam) if (entry) { - *m_engEntry = entry; - if (m_engineer) { - m_engineer->SetOriginalEntry(entry); - if (entry != m_engineer->GetEntry() || !m_engineer->isAlive()) - { - m_engineer->Respawn(true); - //DespawnAllVehicles(); - } - m_engineer->SetVisibility(VISIBILITY_ON); + *m_engEntry = entry; + RespawnCreatureIfNeeded(m_engineer, entry); + } + if (m_spiritguide) + { + *m_spiEntry = guide_entry; + RespawnCreatureIfNeeded(m_spiritguide, guide_entry); + m_wintergrasp->RelocateDeadPlayers(m_spiritguide); } } else if (m_engineer) diff --git a/src/game/Wintergrasp.h b/src/game/Wintergrasp.h index 776b5b94b07..a9dab9ee63f 100644 --- a/src/game/Wintergrasp.h +++ b/src/game/Wintergrasp.h @@ -51,6 +51,7 @@ enum WintergraspSpell SPELL_DAMAGED_BUILDING = 59201, SPELL_INTACT_BUILDING = 59203, SPELL_ESSENCE_OF_WG = 58045, + SPELL_SPIRITUAL_IMMUNITY = 58729, // Unused: Not implemented // SPELL_VICTORY_AURA = 60044, }; @@ -105,6 +106,8 @@ enum WintergraspCreType CREATURE_ENGINEER, CREATURE_GUARD, CREATURE_SPECIAL, + CREATURE_SPIRIT_GUIDE, + CREATURE_SPIRIT_HEALER, }; enum BuildingType @@ -153,7 +156,8 @@ struct BuildingState { team = t; if(graveTeam) - *graveTeam = TeamId2Team[t]; + if (uint32 newTeam = TeamId2Team[t]) + *graveTeam = newTeam; } private: @@ -198,7 +202,24 @@ class OPvPWintergrasp : public OutdoorPvP uint32 GetTimer() const { return m_timer / 1000; }; TeamId GetTeam() const { return m_defender; }; bool isWarTime() const { return m_wartime; }; + + // Temporal BG specific till 3.2 + void SendAreaSpiritHealerQueryOpcode(Player *pl, const uint64& guid); + void AddPlayerToResurrectQueue(uint64 npc_guid, uint64 player_guid); + void RemovePlayerFromResurrectQueue(uint64 player_guid); + void RelocateDeadPlayers(Creature *cr); + // BG end protected: + // Temporal BG specific till 3.2 + std::vector<uint64> m_ResurrectQueue; // Player GUID + uint32 m_LastResurrectTime; + // Spirit Guide guid + Player list GUIDS + std::map<uint64, std::vector<uint64> > m_ReviveQueue; + + uint32 GetLastResurrectTime() const { return m_LastResurrectTime; } + uint32 GetReviveQueueSize() const { return m_ReviveQueue.size(); } + // BG end + TeamId m_defender; int32 m_tenacityStack; @@ -261,6 +282,10 @@ class SiegeWorkshop : public OPvPCapturePoint //bool CanBuildVehicle() const { return m_vehicles.size() < MAX_VEHICLE_PER_WORKSHOP && m_buildingState->damageState != DAMAGE_DESTROYED; } + uint32 *m_spiEntry; + uint32 m_spiGuid; + Creature *m_spiritguide; + uint32 *m_engEntry; uint32 m_engGuid; Creature *m_engineer; |