*Wintergrasp: only allow a workshop to build 4 vehicles.
*remove all existing vehicles when workshop is destroyed or captured. --HG-- branch : trunk
This commit is contained in:
@@ -17,19 +17,43 @@
|
||||
#include "precompiled.h"
|
||||
#include "Wintergrasp.h"
|
||||
|
||||
|
||||
struct TRINITY_DLL_DECL npc_demolisher_engineererAI : public ScriptedAI
|
||||
{
|
||||
npc_demolisher_engineererAI(Creature* pCreature) : ScriptedAI(pCreature) {}
|
||||
|
||||
/*
|
||||
void JustDied(Unit *killer)
|
||||
{
|
||||
if(me->GetZoneScript())
|
||||
me->GetZoneScript()->SetData(DATA_ENGINEER_DIE, me->GetDBTableGUIDLow());
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
CreatureAI* GetAI_npc_demolisher_engineerer(Creature* pCreature)
|
||||
{
|
||||
return new npc_demolisher_engineererAI (pCreature);
|
||||
}
|
||||
|
||||
bool GossipHello_npc_demolisher_engineerer(Player* pPlayer, Creature* pCreature)
|
||||
{
|
||||
if (pCreature->isQuestGiver())
|
||||
pPlayer->PrepareQuestMenu(pCreature->GetGUID());
|
||||
|
||||
if (pPlayer->HasAura(SPELL_CORPORAL))
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Build catapult.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
|
||||
else if (pPlayer->HasAura(SPELL_LIEUTENANT))
|
||||
if(pPlayer->isGameMaster() || pCreature->GetZoneScript() && pCreature->GetZoneScript()->GetData(pCreature->GetDBTableGUIDLow()))
|
||||
{
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Build catapult.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Build demolisher.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Build siege engine.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
|
||||
if (pPlayer->HasAura(SPELL_CORPORAL))
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Build catapult.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
|
||||
else if (pPlayer->HasAura(SPELL_LIEUTENANT))
|
||||
{
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Build catapult.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Build demolisher.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Build siege engine.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
|
||||
}
|
||||
}
|
||||
else
|
||||
pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "I cannot build more!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+9);
|
||||
|
||||
pPlayer->SEND_GOSSIP_MENU(pCreature->GetNpcTextId(), pCreature->GetGUID());
|
||||
return true;
|
||||
@@ -54,6 +78,7 @@ void AddSC_wintergrasp()
|
||||
|
||||
newscript = new Script;
|
||||
newscript->Name = "npc_demolisher_engineerer";
|
||||
newscript->GetAI = &GetAI_npc_demolisher_engineerer;
|
||||
newscript->pGossipHello = &GossipHello_npc_demolisher_engineerer;
|
||||
newscript->pGossipSelect = &GossipSelect_npc_demolisher_engineerer;
|
||||
newscript->RegisterSelf();
|
||||
|
||||
@@ -584,7 +584,6 @@ void OutdoorPvP::OnGameObjectCreate(GameObject *go, bool add)
|
||||
if(go->GetGoType() != GAMEOBJECT_TYPE_CAPTURE_POINT)
|
||||
return;
|
||||
|
||||
OutdoorPvP::OPvPCapturePointMap::iterator itr = m_capturePoints.find(go->GetDBTableGUIDLow());
|
||||
if(itr != m_capturePoints.end())
|
||||
itr->second->m_capturePoint = add ? go : NULL;
|
||||
if(OPvPCapturePoint *cp = GetCapturePoint(go->GetDBTableGUIDLow()))
|
||||
cp->m_capturePoint = add ? go : NULL;
|
||||
}
|
||||
|
||||
@@ -226,6 +226,14 @@ protected:
|
||||
m_capturePoints[cp->m_CapturePointGUID] = cp;
|
||||
}
|
||||
|
||||
OPvPCapturePoint * GetCapturePoint(uint32 lowguid) const
|
||||
{
|
||||
OutdoorPvP::OPvPCapturePointMap::const_iterator itr = m_capturePoints.find(lowguid);
|
||||
if(itr != m_capturePoints.end())
|
||||
return itr->second;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void RegisterZone(uint32 zoneid);
|
||||
bool HasPlayer(Player *plr) const;
|
||||
void TeamCastSpell(TeamId team, int32 spellId);
|
||||
|
||||
@@ -57,6 +57,8 @@ class TRINITY_DLL_SPEC UnitAI
|
||||
|
||||
// Pass parameters between AI
|
||||
virtual void DoAction(const int32 param = 0) {}
|
||||
virtual uint32 GetData(uint32 id = 0) { return 0; }
|
||||
virtual void SetData(uint32 id, uint32 value) {}
|
||||
virtual void SetGUID(const uint64 &guid, int32 id = 0) {}
|
||||
virtual uint64 GetGUID(int32 id = 0) { return 0; }
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ typedef std::list<const AreaPOIEntry *> AreaPOIList;
|
||||
|
||||
SiegeWorkshop::SiegeWorkshop(OPvPWintergrasp *opvp, BuildingState *state)
|
||||
: OPvPCapturePoint(opvp), m_buildingState(state), m_wintergrasp(opvp)
|
||||
, m_vehNum(0), m_engineer(NULL), m_engGuid(0)
|
||||
, m_engineer(NULL), m_engGuid(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -133,12 +133,21 @@ void SiegeWorkshop::ChangeState()
|
||||
{
|
||||
m_engineer->SetOriginalEntry(entry);
|
||||
if(entry != m_engineer->GetEntry() || !m_engineer->isAlive())
|
||||
{
|
||||
m_engineer->Respawn(true);
|
||||
DespawnAllVehicles();
|
||||
}
|
||||
}
|
||||
|
||||
sLog.outDebug("Wintergrasp workshop now belongs to %u.", (uint32)m_buildingState->team);
|
||||
}
|
||||
|
||||
void SiegeWorkshop::DespawnAllVehicles()
|
||||
{
|
||||
while(!m_vehicles.empty())
|
||||
(*m_vehicles.begin())->Dismiss();
|
||||
}
|
||||
|
||||
bool OPvPWintergrasp::SetupOutdoorPvP()
|
||||
{
|
||||
m_defender = TeamId(rand()%2);
|
||||
@@ -277,11 +286,13 @@ bool OPvPWintergrasp::SetupOutdoorPvP()
|
||||
|
||||
workshop->m_engEntry = const_cast<uint32*>(&creData->id);
|
||||
const_cast<CreatureData*>(creData)->displayid = 0;
|
||||
workshop->AddGO(0, guid, goData->id);
|
||||
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);
|
||||
AddCapturePoint(workshop);
|
||||
m_buildingStates[guid]->type = BUILDING_WORKSHOP;
|
||||
workshop->SetStateByBuildingState();
|
||||
}
|
||||
}while(result->NextRow());
|
||||
@@ -322,6 +333,10 @@ void OPvPWintergrasp::ProcessEvent(GameObject *obj, uint32 eventId)
|
||||
else
|
||||
itr->second->damageState = DAMAGE_DESTROYED;
|
||||
BroadcastStateChange(itr->second);
|
||||
|
||||
if(itr->second->type == BUILDING_WORKSHOP)
|
||||
if(SiegeWorkshop *workshop = GetWorkshop(obj->GetDBTableGUIDLow()))
|
||||
workshop->DespawnAllVehicles();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -359,6 +374,25 @@ void OPvPWintergrasp::OnCreatureCreate(Creature *creature, bool add)
|
||||
case 28094:
|
||||
case 28312:
|
||||
case 32627:
|
||||
if(uint32 engLowguid = GUID_LOPART(creature->GetOwnerGUID()))
|
||||
{
|
||||
if(SiegeWorkshop *workshop = GetWorkshopByEngGuid(engLowguid))
|
||||
{
|
||||
if(add)
|
||||
{
|
||||
if(workshop->m_vehicles.size() >= MAX_VEHICLE_PER_WORKSHOP)
|
||||
{
|
||||
creature->setDeathState(DEAD);
|
||||
creature->SetRespawnTime(DAY);
|
||||
return;
|
||||
}
|
||||
workshop->m_vehicles.insert((Vehicle*)creature);
|
||||
}
|
||||
// TODO: now you have to wait until the corpse of vehicle disappear to build a new one
|
||||
else if(!workshop->m_vehicles.erase((Vehicle*)creature))
|
||||
sLog.outError("OPvPWintergrasp::OnCreatureCreate: a vehicle is removed but it does not have record in workshop!");
|
||||
}
|
||||
}
|
||||
//case 28366: tower
|
||||
if(add)
|
||||
{
|
||||
@@ -723,16 +757,43 @@ void OPvPWintergrasp::EndBattle()
|
||||
}
|
||||
}
|
||||
|
||||
void OPvPWintergrasp::SetData(uint32 id, uint32 value)
|
||||
{
|
||||
if(id == DATA_ENGINEER_DIE)
|
||||
if(SiegeWorkshop *workshop = GetWorkshopByEngGuid(value))
|
||||
workshop->DespawnAllVehicles();
|
||||
}
|
||||
|
||||
uint32 OPvPWintergrasp::GetData(uint32 id)
|
||||
{
|
||||
for(OutdoorPvP::OPvPCapturePointMap::iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr)
|
||||
if(SiegeWorkshop *workshop = dynamic_cast<SiegeWorkshop*>(itr->second))
|
||||
if(workshop->m_engGuid == id)
|
||||
return itr->first;
|
||||
// if can build more vehicles
|
||||
if(SiegeWorkshop *workshop = GetWorkshopByEngGuid(id))
|
||||
return workshop->m_vehicles.size() < MAX_VEHICLE_PER_WORKSHOP ? 1 : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OPvPWintergrasp::SetData(uint32 id, uint32 value)
|
||||
SiegeWorkshop *OPvPWintergrasp::GetWorkshop(uint32 lowguid) const
|
||||
{
|
||||
|
||||
if(OPvPCapturePoint *cp = GetCapturePoint(lowguid))
|
||||
return dynamic_cast<SiegeWorkshop*>(cp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SiegeWorkshop *OPvPWintergrasp::GetWorkshopByEngGuid(uint32 lowguid) const
|
||||
{
|
||||
for(OutdoorPvP::OPvPCapturePointMap::const_iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr)
|
||||
if(SiegeWorkshop *workshop = dynamic_cast<SiegeWorkshop*>(itr->second))
|
||||
if(workshop->m_engGuid == lowguid)
|
||||
return workshop;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SiegeWorkshop *OPvPWintergrasp::GetWorkshopByGOGuid(uint32 lowguid) const
|
||||
{
|
||||
for(OutdoorPvP::OPvPCapturePointMap::const_iterator itr = m_capturePoints.begin(); itr != m_capturePoints.end(); ++itr)
|
||||
if(SiegeWorkshop *workshop = dynamic_cast<SiegeWorkshop*>(itr->second))
|
||||
if(workshop->m_workshopGuid == lowguid)
|
||||
return workshop;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+25
-3
@@ -58,6 +58,11 @@ enum OutdoorPvP_WG_Sounds
|
||||
*/
|
||||
};
|
||||
|
||||
enum DataId
|
||||
{
|
||||
DATA_ENGINEER_DIE,
|
||||
};
|
||||
|
||||
enum OutdoorPvP_WG_KeepStatus
|
||||
{
|
||||
OutdoorPvP_WG_KEEP_TYPE_NEUTRAL = 0,
|
||||
@@ -69,6 +74,13 @@ enum OutdoorPvP_WG_KeepStatus
|
||||
OutdoorPvP_WG_KEEP_STATUS_HORDE_OCCUPIED = 4
|
||||
};
|
||||
|
||||
enum BuildingType
|
||||
{
|
||||
BUILDING_WALL,
|
||||
BUILDING_WORKSHOP,
|
||||
BUILDING_TOWER,
|
||||
};
|
||||
|
||||
enum DamageState
|
||||
{
|
||||
DAMAGE_INTACT,
|
||||
@@ -83,13 +95,14 @@ struct BuildingState
|
||||
explicit BuildingState(uint32 _worldState, TeamId _team, bool asDefault)
|
||||
: worldState(_worldState), health(0)
|
||||
, defaultTeam(asDefault ? _team : OTHER_TEAM(_team)), team(_team), damageState(DAMAGE_INTACT)
|
||||
, building(NULL)
|
||||
, building(NULL), type(BUILDING_WALL)
|
||||
{}
|
||||
uint32 worldState;
|
||||
uint32 health;
|
||||
TeamId team, defaultTeam;
|
||||
DamageState damageState;
|
||||
GameObject *building;
|
||||
BuildingType type;
|
||||
|
||||
void SendUpdate(Player *player)
|
||||
{
|
||||
@@ -104,12 +117,15 @@ struct BuildingState
|
||||
|
||||
typedef std::map<uint32, uint32> TeamPairMap;
|
||||
|
||||
class SiegeWorkshop;
|
||||
|
||||
typedef std::set<Vehicle*> VehicleSet;
|
||||
|
||||
class OPvPWintergrasp : public OutdoorPvP
|
||||
{
|
||||
protected:
|
||||
typedef std::map<uint32, BuildingState *> BuildingStateMap;
|
||||
typedef std::set<Creature*> CreatureSet;
|
||||
typedef std::set<Vehicle*> VehicleSet;
|
||||
typedef std::set<GameObject*> GameObjectSet;
|
||||
public:
|
||||
explicit OPvPWintergrasp() : m_tenacityStack(0) {}
|
||||
@@ -148,6 +164,10 @@ class OPvPWintergrasp : public OutdoorPvP
|
||||
bool m_wartime;
|
||||
uint32 m_timer;
|
||||
|
||||
SiegeWorkshop *GetWorkshop(uint32 lowguid) const;
|
||||
SiegeWorkshop *GetWorkshopByEngGuid(uint32 lowguid) const;
|
||||
SiegeWorkshop *GetWorkshopByGOGuid(uint32 lowguid) const;
|
||||
|
||||
void ChangeDefender();
|
||||
|
||||
void UpdateTenacityStack();
|
||||
@@ -171,10 +191,12 @@ class SiegeWorkshop : public OPvPCapturePoint
|
||||
explicit SiegeWorkshop(OPvPWintergrasp *opvp, BuildingState *state);
|
||||
void SetStateByBuildingState();
|
||||
void ChangeState();
|
||||
uint32 m_vehNum;
|
||||
void DespawnAllVehicles();
|
||||
uint32 *m_engEntry;
|
||||
uint32 m_engGuid;
|
||||
Creature *m_engineer;
|
||||
uint32 m_workshopGuid;
|
||||
VehicleSet m_vehicles;
|
||||
protected:
|
||||
BuildingState *m_buildingState;
|
||||
OPvPWintergrasp *m_wintergrasp;
|
||||
|
||||
Reference in New Issue
Block a user