I've decided to release some of the scripts I used on my server. I will not provide support for these scripts, and I do not guarantee that they will be functional or stable.
Some of these scripts are rather old, and some are fairly new.
I will attempt to outline the specifications of each script but for the most part you will need to examine the code yourself to understand what all it has to offer or lack there of.
CityConquest (HearthStone Version?)
This is perhaps one of the scripts I'm most known for writing back in 2008. This is an updated prototype over the original design. I cannot recall how stable or functional this iteration of CityConquest was as it is always evolving and changing.
This was my first attempt at making a more dynamic approach to adding cities, if you've ever seen the original CityConquest Script you will recall the hundreds of lines of code which did nothing more than register each creature with the scripting interface via their entry id. This version uses user defined variables to determine the base location of the city, and max range of the city limits to attempt to automatically find creatures that will be within the affected areas. This happens only once upon the first load of the script assuming you do not have any creatures already registered to that city (Excluding the trigger/boss Npc's)
To answer the most obvious question, no this script will not run on your server, unless you happen to the a version of HS that uses shared pointers around and somehow have managed to avoid evolution for the past 2 years.
City.cpp
Code:
/* CityConquest
* Copyright (C) 2009 Spectre
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "../StdAfx.h"
#include "City.h"
#include "CityConquest.h"
#include "ConquestAI.h"
#define I_LIKE_DOING_THINGS_IN_WEIRD_WAYS_CUZ_ITS_COOL
//#define SAVE_CITY_DATA
City::City(uint8 CityId)
{
m_cityInfo.cityId = CityId;
m_mapMgr = NULLMAPMGR;
}
City::~City()
{
m_mobEntries.clear();
}
void City::Init()
{
LoadFromDB();
}
void City::WipeRefs()
{
}
// Database
void City::LoadFromDB()
{
LoadCityInfo();
LoadCityMobs();
}
void City::LoadCityInfo()
{
QueryResult *Result = WorldDatabase.Query("SELECT * FROM `conquest_city` WHERE `CityId` = '%u'", m_cityInfo.cityId);
if(Result)
{
// Skip field 0 as it = cityid which we have already
Field *Fields = Result->Fetch();
m_cityInfo.cityName = Fields[1].GetString();
m_cityInfo.mapId = Fields[2].GetUInt32();
m_cityInfo.baseCords.ChangeCoords(Fields[3].GetFloat(), Fields[4].GetFloat(), Fields[5].GetFloat());
m_cityInfo.maxDist = Fields[6].GetFloat();
m_cityInfo.triggerNpc = Fields[7].GetUInt32();
m_cityInfo.bossNpc = Fields[8].GetUInt32();
m_cityInfo.bossSpawnDelay = Fields[9].GetUInt32();
m_cityInfo.FactionId = Fields[10].GetUInt16();
m_cityInfo.bossCords.ChangeCoords(Fields[11].GetFloat(), Fields[12].GetFloat(), Fields[13].GetFloat(), Fields[14].GetFloat());
WorldDatabase.FreeQueryResult(Result);
}
else
Log.Error("CityConquest", "Attempted to load city %u with no database information", m_cityInfo.cityId);
}
void City::LoadCityMobs()
{
QueryResult *Result = WorldDatabase.Query("SELECT `Entry` FROM `conquest_mobs` WHERE `CityId` = '%u'", m_cityInfo.cityId);
if(Result)
{
do
{
m_mobEntries.insert(Result->Fetch()[0].GetUInt32());
}while(Result->NextRow());
WorldDatabase.FreeQueryResult(Result);
}
else
{
#ifdef I_LIKE_DOING_THINGS_IN_WEIRD_WAYS_CUZ_ITS_COOL
__LoadCityMobs();
#else
Log.Error("CityConquest", "Loading of mobs at city %u failed, no query result returned", m_cityInfo.cityId);
#endif
}
}
void City::__LoadCityMobs()
{
QueryResult *Result = WorldDatabase.Query("SELECT `entry`, `position_x`, `position_y`, `position_z` FROM `creature_spawns` WHERE `map` = '%u'", m_cityInfo.mapId);
if(Result)
{
do
{
float Dist = ConquestMgr.CalcDistance(m_cityInfo.baseCords, LocationVector(Result->Fetch()[1].GetFloat(), Result->Fetch()[2].GetFloat(), Result->Fetch()[3].GetFloat()));
uint32 Entry = Result->Fetch()[0].GetUInt32();
if(Dist <= m_cityInfo.maxDist && Entry != m_cityInfo.triggerNpc)
AddMobEntry(Result->Fetch()[0].GetUInt32());
}while(Result->NextRow());
WorldDatabase.FreeQueryResult(Result);
__SaveCityMobs();
Log.Notice("CityConquest", "Inserted %u New Mob Entries", uint32(m_mobEntries.size()));
}
}
void City::__SaveCityMobs()
{
set<uint32>::iterator Itr;
for(Itr = m_mobEntries.begin(); Itr != m_mobEntries.end(); Itr++)
{
WorldDatabase.Execute("INSERT INTO `conquest_mobs` VALUES('%u', '%u')", m_cityInfo.cityId, (*Itr));
}
}
void City::UpdateCityData()
{
// Only update fields that we'll actually change
WorldDatabase.Execute("UPDATE `conquest_city` SET `FactionController` = '%u' WHERE `CityId` = '%u'", m_cityInfo.FactionId, m_cityInfo.cityId);
}
// Events
int32 City::event_GetInstanceID()
{
if(m_mapMgr != NULLPTR)
return m_mapMgr->GetInstanceID();
return -1;
}
// MapMgr
MapMgrPointer City::GetMapMgr()
{
if(m_mapMgr == NULLPTR)
m_mapMgr = sInstanceMgr.GetMapMgr(m_cityInfo.mapId);
return m_mapMgr;
}
float City::CalcDistance(LocationVector aVect, LocationVector bVect)
{
return ConquestMgr.CalcDistance(aVect, bVect);
}
// CityInfo
CityInfo *City::GetCityInfo()
{
return &m_cityInfo;
}
// Mobs
void City::AddMobEntry(uint32 Entry)
{
set<uint32>::iterator Itr = m_mobEntries.find(Entry);
if(Itr == m_mobEntries.end())
m_mobEntries.insert(Entry);
}
void City::RemoveMobEntry(uint32 Entry)
{
set<uint32>::iterator Itr = m_mobEntries.find(Entry);
if(Itr != m_mobEntries.end())
m_mobEntries.erase(Itr);
}
void City::AddMob(CreaturePointer cObj)
{
set<CreaturePointer>::iterator Itr = m_creaturePtrs.find(cObj);
if(Itr == m_creaturePtrs.end())
m_creaturePtrs.insert(cObj);
}
void City::RemoveMob(CreaturePointer cObj)
{
set<CreaturePointer>::iterator Itr = m_creaturePtrs.find(cObj);
if(Itr != m_creaturePtrs.end())
m_creaturePtrs.erase(Itr);
}
bool City::IsInRage(ObjectPointer Obj)
{
if(CalcDistance(m_cityInfo.baseCords, Obj->GetPosition()) <= m_cityInfo.maxDist)
return true;
return false;
}
// Creature AI
void City::LoadMobAI(ScriptMgr *Mgr)
{
set<uint32>::iterator Itr;
for(Itr = m_mobEntries.begin(); Itr != m_mobEntries.end(); Itr++)
{
if((*Itr) == m_cityInfo.triggerNpc)
continue;
Mgr->register_creature_script((*Itr), GerneralConquestAI::Create);
}
Mgr->register_creature_script(29611, TriggerConquestAI::Create);
}
// Faction Switch
void City::SwitchFaction(uint16 FactionId)
{
set<CreaturePointer>::iterator Itr;
for(Itr = m_creaturePtrs.begin(); Itr != m_creaturePtrs.end(); Itr++)
{
CreaturePointer Tmp = (*Itr);
Tmp->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, FactionId);
Tmp->_setFaction();
Tmp->GetAIInterface()->WipeTargetList();
}
SendServerMessage("The %s have captured %s", FactionId == CONQUEST_HORDE_FACTION ? "Horde" : "Alliance", m_cityInfo.cityName.c_str());
m_cityInfo.FactionId = FactionId;
#ifdef SAVE_CITY_DATA
UpdateCityData();
#endif
}
// Messages
void City::SendServerMessage(const char *Msg, ...)
{
char Result[1024];
char Final[1024];
va_list List;
va_start(List, Msg);
vsnprintf(Result, 1024, Msg, List);
va_end(List);
sprintf(Final, "%sCityConquest:%s %s", MSG_COLOR_GOLD, MSG_COLOR_RED, Result);
sWorld.SendWorldText(Final);
}
City.h
Code:
/* CityConquest
* Copyright (C) 2009 Spectre
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef City_H
#define City_H
struct CityInfo
{
CityInfo()
{
mapId = 0;
triggerNpc = 0;
bossNpc = 0;
bossSpawnDelay = 0;
cityId = 0;
maxDist = 0.00f;
cityName = "";
baseCords.ChangeCoords(0.00f, 0.00f, 0.00f);
bossCords.ChangeCoords(0.00f, 0.00f, 0.00f);
triggerCords.ChangeCoords(0.00f, 0.00f, 0.00f);
}
uint32 mapId;
uint32 triggerNpc;
uint32 bossNpc;
uint32 bossSpawnDelay;
uint16 FactionId;
uint8 cityId;
float maxDist;
string cityName;
LocationVector baseCords;
LocationVector bossCords;
LocationVector triggerCords;
};
class City : public EventableObject, public std::tr1::enable_shared_from_this<City>
{
public:
City(uint8 CityId);
~City();
void Init();
void WipeRefs();
// Database
void LoadFromDB();
void LoadCityInfo();
void LoadCityMobs();
void UpdateCityData();
// Events
int32 event_GetInstanceID();
// MapMgr
MapMgrPointer GetMapMgr();
float CalcDistance(LocationVector aVect, LocationVector bVect);
// CityInfo
CityInfo *GetCityInfo();
// Mobs
void AddMobEntry(uint32 Entry);
void RemoveMobEntry(uint32 Entry);
void AddMob(CreaturePointer cObj);
void RemoveMob(CreaturePointer cObj);
bool IsInRage(ObjectPointer Obj);
// Faction Switch
void SwitchFaction(uint16 FactionId);
// Creature AI
void LoadMobAI(ScriptMgr *Mgr);
// Messages
void SendServerMessage(const char *Msg, ...);
private:
// MapMgr
MapMgrPointer m_mapMgr;
// CityInfo
CityInfo m_cityInfo;
// Mobs
set<uint32> m_mobEntries;
set<CreaturePointer> m_creaturePtrs;
void __LoadCityMobs();
void __SaveCityMobs();
protected:
};
#endif // City_H
CityConquest.cpp
Code:
/* CityConquest
* Copyright (C) 2009 Spectre
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "../StdAfx.h"
#include "CityConquest.h"
#include "City.h"
initialiseSingleInst(CityConquest);
CityConquest::CityConquest()
{
LoadCities();
}
CityConquest::~CityConquest()
{
}
void CityConquest::WipeRefs()
{
}
// Database
void CityConquest::LoadCities()
{
QueryResult *Res = WorldDatabase.Query("SELECT `CityId` FROM `conquest_city`");
if(Res)
{
do
{
CityPointer Tmp = CityPointer(new City(Res->Fetch()[0].GetUInt8()));
Tmp->Init();
m_cityMap.insert(make_pair(Res->Fetch()[0].GetUInt8(), Tmp));
}while(Res->NextRow());
WorldDatabase.FreeQueryResult(Res);
}
}
// City Management
CityPointer CityConquest::GetCity(uint8 CityId)
{
CityMap::iterator Itr = m_cityMap.find(CityId);
if(Itr != m_cityMap.end())
return Itr->second;
return CityPointer();
}
CityPointer CityConquest::GetCity(ObjectPointer Obj)
{
CityMap::iterator Itr;
for(Itr = m_cityMap.begin(); Itr != m_cityMap.end(); Itr++)
{
if(Itr->second->IsInRage(Obj))
return Itr->second;
}
return CityPointer();
}
// Creature AI
void CityConquest::LoadAIForCities(ScriptMgr *Mgr)
{
CityMap::iterator Itr;
for(Itr = m_cityMap.begin(); Itr != m_cityMap.end(); Itr++)
Itr->second->LoadMobAI(Mgr);
}
float CityConquest::CalcDistance(LocationVector aVect, LocationVector bVect)
{
float x = aVect.x - bVect.x;
float y = aVect.y - bVect.y;
float z = aVect.z - bVect.z;
return sqrtf(z*z + y*y + x*x);
}
// Setup
void SetupCityConquest(ScriptMgr *mgr)
{
new CityConquest;
ConquestMgr.LoadAIForCities(mgr);
}
CityConquest.h
Code:
/* CityConquest
* Copyright (C) 2009 Spectre
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef CityConquest_H
#define CityConquest_H
class CityConquest;
class City;
typedef shared_ptr<CityConquest> CityConquestPointer;
typedef shared_ptr<City> CityPointer;
typedef map<uint8, CityPointer> CityMap;
enum Conquest_FactionIds
{
CONQUEST_ALLIANCE_FACTION = 84,
CONQUEST_HORDE_FACTION = 85,
};
enum Conquest_CityIds
{
CONQUEST_STORMWIND_ID = 1,
};
class CityConquest : public SingleInst<CityConquest>, public EventableObject, public std::tr1::enable_shared_from_this<CityConquest>
{
public:
CityConquest();
~CityConquest();
void WipeRefs();
// Database
void LoadCities();
// City Management
CityPointer GetCity(uint8 CityId);
CityPointer GetCity(ObjectPointer Obj);
// Creature AI
void LoadAIForCities(ScriptMgr *Mgr);
float CalcDistance(LocationVector aVect, LocationVector bVect);
private:
CityMap m_cityMap;
protected:
};
#define ConquestMgr CityConquest::getSingleInst()
#endif // CityConquest_H
ConquestAI.h
Code:
/* CityConquest
* Copyright (C) 2009 Spectre
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "../StdAfx.h"
#include "CityConquest.h"
class GerneralConquestAI : public CreatureAIScript
{
public:
ADD_CREATURE_FACTORY_FUNCTION(GerneralConquestAI);
CityPointer m_city;
GerneralConquestAI(CreaturePointer pCreature) : CreatureAIScript(pCreature)
{
m_city = ConquestMgr.GetCity(_unit);
if(m_city == NULLPTR) // we're not inrange of a city so ignore
return;
m_city->AddMob(_unit);
RegisterAIUpdateEvent(3000);
}
void AIUpdate()
{
if(m_city)
{
_unit->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, m_city->GetCityInfo()->FactionId);
_unit->_setFaction();
_unit->GetAIInterface()->WipeTargetList();
}
RemoveAIUpdateEvent();
}
void OnCombatStart(UnitPointer mTarget)
{
if(!mTarget->IsPlayer())
return;
// Hack fix until I figure this issue out.
PlayerPointer Plr = TO_PLAYER(mTarget);
if(Plr->GetTeam() && _unit->GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE) == CONQUEST_HORDE_FACTION)
_unit->GetAIInterface()->WipeTargetList();
else if(!Plr->GetTeam() && _unit->GetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE) == CONQUEST_ALLIANCE_FACTION)
_unit->GetAIInterface()->WipeTargetList();
}
void OnDied(UnitPointer mKiller)
{
if(m_city)
{
m_city->RemoveMob(_unit);
m_city = CityPointer();
}
RemoveAIUpdateEvent();
}
void Destroy()
{
if(m_city)
{
m_city->RemoveMob(_unit);
m_city = CityPointer();
}
RemoveAIUpdateEvent();
delete this;
}
};
class TriggerConquestAI : public CreatureAIScript
{
public:
ADD_CREATURE_FACTORY_FUNCTION(TriggerConquestAI);
CityPointer m_city;
TriggerConquestAI(CreaturePointer pCreature) : CreatureAIScript(pCreature)
{
m_city = ConquestMgr.GetCity(_unit);
if(m_city == NULLPTR) // we're not inrange of a city so ignore
return;
_unit->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, m_city->GetCityInfo()->FactionId);
_unit->_setFaction();
_unit->m_noRespawn = true;
m_city->GetCityInfo()->triggerCords.ChangeCoords(_unit->GetPositionX(), _unit->GetPositionY(), _unit->GetPositionZ(), _unit->GetOrientation());
}
void OnDamageTaken(UnitPointer mAttacker, float fAmount)
{
if(mAttacker->IsPvPFlagged() == false)
mAttacker->SetPvPFlag();
}
void OnDied(UnitPointer mKiller)
{
if(m_city)
{
m_city->SendServerMessage("%s is under attack!", m_city->GetCityInfo()->cityName.c_str());
LocationVector Coords = m_city->GetCityInfo()->bossCords;
_unit->GetMapMgr()->GetInterface()->SpawnCreature(m_city->GetCityInfo()->bossNpc, Coords.x, Coords.y, Coords.z, Coords.o, true, false, 0, 0);
m_city = CityPointer();
}
}
void Destroy()
{
if(m_city)
{
m_city = CityPointer();
}
delete this;
}
};
Stormwind.cpp
Code:
/* CityConquest
* Copyright (C) 2009 Spectre
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "../StdAfx.h"
#include "CityConquest.h"
#include "City.h"
class StormwindBossAI : public CreatureAIScript
{
public:
ADD_CREATURE_FACTORY_FUNCTION(StormwindBossAI);
CityPointer m_city;
float HordeDamage;
float AllyDamage;
StormwindBossAI(CreaturePointer pCreature) : CreatureAIScript(pCreature)
{
m_city = ConquestMgr.GetCity(CONQUEST_STORMWIND_ID);
AllyDamage = 0.00f;
HordeDamage = 0.00f;
if(m_city == NULLPTR) // No city found? :(((((((
return;
}
void AIUpdate()
{
//_unit->SendChatMessage(CHAT_MSG_MONSTER_YELL, LANG_UNIVERSAL, "You've wasted too much time mortals, now you shall fall!");
}
void OnDamageTaken(UnitPointer mAttacker, float fAmount)
{
float Damage;
Damage = fAmount * 100 / _unit->GetUInt32Value(UNIT_FIELD_MAXHEALTH);
if(mAttacker->IsPlayer() == true)
{
PlayerPointer Plr = TO_PLAYER(mAttacker);;
if(Plr->GetTeam() > 0)
HordeDamage += Damage;
else
AllyDamage += Damage;
if(Plr->IsPvPFlagged() == false)
Plr->SetPvPFlag();
}
}
void OnDied(UnitPointer mKiller)
{
if(m_city)
{
if(HordeDamage > AllyDamage)
m_city->SwitchFaction(CONQUEST_HORDE_FACTION);
else
m_city->SwitchFaction(CONQUEST_ALLIANCE_FACTION);
_unit->GetMapMgr()->GetInterface()->SpawnCreature(m_city->GetCityInfo()->triggerNpc, m_city->GetCityInfo()->triggerCords.x, m_city->GetCityInfo()->triggerCords.y, m_city->GetCityInfo()->triggerCords.z, m_city->GetCityInfo()->triggerCords.o, true, false, 0, 0);
m_city = CityPointer();
}
}
void Destroy()
{
if(m_city)
{
m_city = CityPointer();
}
delete this;
}
};
void SetupStormwind(ScriptMgr *mgr)
{
mgr->register_creature_script(1234622, StormwindBossAI::Create);
}
City Conquest (Trinity-Core Version)
This version is pretty much the same as the above except that it went through many changes to accommodate TrinityCore / Xenos Scripting Interface. This script will not compile, and is more than likely missing reference files to other scripts such as XSI (which was publicly released on this forum already) This version I will say outright is not stable. I say this because my server was lapsing into a coma around the era I revised this script, and did not have a good amount of players to stress test it or enough sanity for that matter =p.
The script is in some disarray as can be seen by it's source, a lot of commented out sections from change overs and function changes.
CityConquest.h
Code:
/* CityConquest
* Copyright (C) 2009 - 2010 Spectre
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef CityConquest_H
#define CityConquest_H
#include "City.h"
#define CONQUEST_BOSS_MAX_HEALTH 8165150
#define CONQUEST_BOSS_MIN_HEALTH 6165150
typedef std::map<uint8, City*> CityMap;
enum Conquest_FactionIds
{
CONQUEST_ALL_HOSTILE_FACTION = 14,
CONQUEST_ALLIANCE_FACTION = 84,
CONQUEST_HORDE_FACTION = 85,
};
enum Conquest_CityIds
{
CONQUEST_STORMWIND_ID = 1,
CONQUEST_ORGRIMMAR_ID = 2,
};
enum CONQUEST_TEAMS
{
CONQUEST_TEAM_ALPHA,
CONQUEST_TEAM_BRAVO,
CONQUEST_MAX_TEAMS,
};
class CityConquest : public ScriptableObject
{
public:
CityConquest();
~CityConquest();
// Shutdown
void Shutdown();
// Database
void LoadCities();
// City Management
void GetCityFactionCount(uint32 &allyCount, uint32 &hordeCount);
void ResetCities();
City *GetCity(uint8 mCityId);
City *GetCity(Unit *mUnit);
City *GetCityByBonus(uint8 rewardType);
City *GetCityByBoss(Creature *pCreature);
uint8 GetTeamWithBonus(uint8 rewardType);
float CalcDistance(WorldLocation aVect, WorldLocation bVect);
// Messages
void SendServerMessage(const char *Msg, ...);
// Hooks
void OnCreatureAddToWorld(Creature *pCreature);
void OnCreatureRemoveFromWorld(Creature *pCreature);
void OnUnitDeath(Unit *pAttacker, Unit *pVictim);
void OnTempConquestBossDeath(Creature *pCreature, Player *pPlayer);
bool OnFactionTemplateUpdate(Unit *pUnit, Player *pPlayer, ByteBuffer *pBuffer);
bool OnIsHostileTo(Unit *pUnit, Unit *pTarget);
bool OnIsFriendlyTo(Unit *pUnit, Unit *pTarget);
private:
protected:
CityMap m_cityMap;
};
#define sCityConquest (*ACE_Singleton<CityConquest, ACE_Null_Mutex>::instance())
#endif // CityConquest_H
CityConquest.cpp
Code:
/* CityConquest
* Copyright (C) 2009 - 2010 Spectre
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "XenosPch.h"
#include "CityConquest.h"
#include "World.h"
CityConquest::CityConquest()
{
}
CityConquest::~CityConquest()
{
}
// Shutdown
void CityConquest::Shutdown()
{
ResetCities();
CityMap::iterator Itr;
for(Itr = m_cityMap.begin(); Itr != m_cityMap.end(); Itr++)
delete Itr->second;
m_cityMap.clear();
//SetShutdown(SHUTDOWN_STATUS_COMPLETE);
}
// Database
void CityConquest::LoadCities()
{
QueryResult_AutoPtr Res = WorldDatabase.Query("SELECT `CityId` FROM `conquest_city`");
if(Res)
{
do
{
City *Tmp = new City(Res->Fetch()[0].GetUInt8());
m_cityMap.insert(std::make_pair(Res->Fetch()[0].GetUInt8(), Tmp));
}while(Res->NextRow());
}
}
// City Management
void CityConquest::ResetCities()
{
CityMap::iterator Itr;
for(Itr = m_cityMap.begin(); Itr != m_cityMap.end(); ++Itr)
{
if(Itr->second->GetNativeFactionId() != Itr->second->GetCurrentFactionId())
Itr->second->SwitchFaction(Itr->second->GetNativeFactionId());
}
}
void CityConquest::GetCityFactionCount(uint32 &allyCount, uint32 &hordeCount)
{
allyCount = hordeCount = 0;
CityMap::iterator Itr;
for(Itr = m_cityMap.begin(); Itr != m_cityMap.end(); ++Itr)
{
if(Itr->second->GetControllingFactionId() == CONQUEST_TEAM_ALPHA)
allyCount++;
else
hordeCount++;
}
}
City *CityConquest::GetCity(uint8 mCityId)
{
CityMap::iterator Itr = m_cityMap.find(mCityId);
if(Itr != m_cityMap.end())
return Itr->second;
return NULL;
}
City *CityConquest::GetCity(Unit *mUnit)
{
CityMap::iterator Itr;
for(Itr = m_cityMap.begin(); Itr != m_cityMap.end(); Itr++)
{
if(Itr->second->IsInRange((Creature*)mUnit))
return Itr->second;
}
return NULL;
}
City *CityConquest::GetCityByBonus(uint8 rewardType)
{
CityMap::iterator Itr;
for(Itr = m_cityMap.begin(); Itr != m_cityMap.end(); Itr++)
{
if(Itr->second->GetCityInfo()->rewardType == rewardType)
return Itr->second;
}
return NULL;
}
City *CityConquest::GetCityByBoss(Creature *pCreature)
{
CityMap::iterator Itr;
for(Itr = m_cityMap.begin(); Itr != m_cityMap.end(); Itr++)
{
if(Itr->second->GetCityBoss() == pCreature)
return Itr->second;
}
return NULL;
}
uint8 CityConquest::GetTeamWithBonus(uint8 rewardType)
{
City *pCity = GetCityByBonus(rewardType);
if(pCity == NULL)
return CONQUEST_MAX_TEAMS;
if(pCity->GetCurrentFactionId() == CONQUEST_ALLIANCE_FACTION)
return CONQUEST_TEAM_ALPHA;
else
return CONQUEST_TEAM_BRAVO;
}
float CityConquest::CalcDistance(WorldLocation aVect, WorldLocation bVect)
{
float x = aVect.m_positionX - bVect.m_positionX;
float y = aVect.m_positionY - bVect.m_positionY;
float z = aVect.m_positionZ - bVect.m_positionZ;
return sqrtf(z*z + y*y + x*x);
}
// Messages
void CityConquest::SendServerMessage(const char *Msg, ...)
{
char Result[1024];
char Final[1024];
va_list List;
va_start(List, Msg);
vsnprintf(Result, 1024, Msg, List);
va_end(List);
sprintf(Final, "[CityConquest] %s", Result);
sWorld.SendGlobalText(Final, NULL);
}
// Hooks
void CityConquest::OnCreatureAddToWorld(Creature *pCreature)
{
if(City *pCity = GetCity(pCreature))
pCity->AddMob(pCreature);
}
void CityConquest::OnCreatureRemoveFromWorld(Creature *pCreature)
{
if(City *pCity = GetCity(pCreature))
pCity->RemoveMob(pCreature);
}
void CityConquest::OnUnitDeath(Unit *pAttacker, Unit *pVictim)
{
if(City *pCity = GetCity(pVictim))
{
if(pCity->IsTriggerNPC(pVictim))
pCity->OnKillTrigger();
}
}
void CityConquest::OnTempConquestBossDeath(Creature *pCreature, Player *pPlayer)
{
if(City *pCity = GetCityByBoss(pCreature))
pCity->SwitchFaction(pCreature, pPlayer);
}
bool CityConquest::OnFactionTemplateUpdate(Unit *pUnit, Player *pPlayer, ByteBuffer *pBuffer)
{
if(City *pCity = GetCity(pUnit))
{
if(pCity->GetCityInfo()->factionId == pPlayer->GetGuildId())
{
*pBuffer << pPlayer->getFaction();
return true;
}
}
return false;
}
bool CityConquest::OnIsHostileTo(Unit *pUnit, Unit *pTarget)
{
if(pTarget->GetTypeId() != TYPEID_PLAYER)
return false;
Player *pPlayer = static_cast<Player*>(pTarget);
if(City *pCity = GetCity(pUnit))
{
if(pCity->GetCityInfo()->factionId == pPlayer->GetGuildId())
return true;
}
return false;
}
bool CityConquest::OnIsFriendlyTo(Unit *pUnit, Unit*pTarget)
{
if(pTarget->GetTypeId() != TYPEID_PLAYER)
return false;
Player *pPlayer = static_cast<Player*>(pTarget);
if(City *pCity = GetCity(pUnit))
{
if(pCity->GetCityInfo()->factionId == pPlayer->GetGuildId())
return true;
}
return false;
}
City.h
Code:
/* CityConquest
* Copyright (C) 2009 - 2010 Spectre
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef City_H
#define City_H
//#define IM_A_JACKASS_AND_I_BREAK_THINGS // idk are you?
#define wut 1
struct CityInfo
{
#ifdef IM_A_JACKASS_AND_I_BREAK_THINGS
CityInfo()
{
// What the **** is this? retard proofing?!
mapId = 0;
triggerNpc = 0;
bossNpc = 0;
bossSpawnDelay = 0;
cityId = 0;
maxDist = 0.00f;
bossSpawned = false;
cityName = "";
baseCords.ChangeCoords(0.00f, 0.00f, 0.00f);
bossCords.ChangeCoords(0.00f, 0.00f, 0.00f);
triggerCords.ChangeCoords(0.00f, 0.00f, 0.00f);
}
#else
CityInfo() : cityBoss(NULL) {}
#endif
uint32 triggerNpc;
uint32 bossNpc;
uint32 bossSpawnDelay;
uint16 mapId;
uint16 factionId;
uint16 nativeFactionId;
uint8 cityId;
uint8 rewardType;
float maxDist;
std::string cityName;
WorldLocation baseCords;
WorldLocation bossCords;
WorldLocation triggerCords;
Creature *cityBoss;
};
enum CITY_BONUSES
{
CITY_BONUS_NONE = 0,
CITY_BONUS_RESOURCE_MULTIPLIER = 1
};
typedef std::set<uint64> CreatureGUIDSet;
class City
{
public:
City(uint8 mCityId);
~City();
// Database
void LoadFromDB();
void LoadCityInfo();
void LoadCityMobs();
void UpdateCityData();
float CalcDistance(WorldLocation aVect, WorldLocation bVect);
// CityInfo
void SetCityBoss(Creature *pCreature) { GetCityInfo()->cityBoss = pCreature; }
Creature *GetCityBoss() { return GetCityInfo()->cityBoss; }
CityInfo *GetCityInfo();
uint16 GetNativeFactionId() { return GetCityInfo()->nativeFactionId; }
uint16 GetCurrentFactionId() { return GetCityInfo()->factionId; }
uint8 GetControllingFactionId();
bool BossSpawned() { return GetCityBoss() != NULL; }
// Takeover
void CheckFactions();
void SwitchFaction(uint32 factionId);
void SwitchFaction(Creature *mCreature, Player *pKiller);
// Mobs
void AddMob(Creature *pCreature);
void RemoveMob(Creature *pCreature);
bool HasMob(Creature *pCreature);
bool IsInRange(Unit *mUnit);
bool IsTriggerNPC(Unit *mUnit);
// Creature Spawning
Creature* SpawnCreature(uint32 entryId, uint32 factionId, float x, float y, float z, float o);
// Hooks
void OnKillTrigger();
private:
// Takeover
void updateMobFactions();
// CityInfo
CityInfo m_cityInfo;
// Mobs
CreatureGUIDSet cityMobs;
void loadCityMobs();
void saveCityMobs();
protected:
};
#endif // City_H
City.cpp
Code:
/* CityConquest
* Copyright (C) 2009 - 2010 Spectre
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "XenosPch.h"
#include "CityConquest.h"
#include "MapManager.h"
#include "ObjectMgr.h"
#include "MapManager.h"
#define LOAD_CREATURE_SPAWNS_FROM_DATABASE
//#define SAVE_CITY_DATA
using namespace std;
const char *rewardNames [] =
{
"REWARD_NONE",
"Resource Deduction Multiplier x2"
};
City::City(uint8 mCityId)
{
m_cityInfo.cityId = mCityId;
LoadFromDB();
}
City::~City()
{
cityMobs.clear();
}
// Database
void City::LoadFromDB()
{
LoadCityInfo();
}
void City::LoadCityInfo()
{
QueryResult_AutoPtr Result = WorldDatabase.PQuery("SELECT * FROM `conquest_city` WHERE `CityId` = '%u'", m_cityInfo.cityId);
if(Result)
{
// Skip field 0 as it = cityid which we have already
Field *Fields = Result->Fetch();
m_cityInfo.cityName = Fields[1].GetString();
m_cityInfo.mapId = Fields[2].GetUInt32();
m_cityInfo.baseCords.Relocate(Fields[3].GetFloat(), Fields[4].GetFloat(), Fields[5].GetFloat());
m_cityInfo.maxDist = Fields[6].GetFloat();
m_cityInfo.triggerNpc = Fields[7].GetUInt32();
m_cityInfo.bossNpc = Fields[8].GetUInt32();
m_cityInfo.bossSpawnDelay = Fields[9].GetUInt32();
m_cityInfo.nativeFactionId = Fields[10].GetUInt16();
m_cityInfo.rewardType = Fields[11].GetUInt8();
m_cityInfo.bossCords.Relocate(Fields[12].GetFloat(), Fields[13].GetFloat(), Fields[14].GetFloat(), Fields[15].GetFloat());
m_cityInfo.factionId = m_cityInfo.nativeFactionId;
}
}
void City::LoadCityMobs()
{
/*QueryResult_AutoPtr Result = WorldDatabase.PQuery("SELECT `SpawnGUID` FROM `conquest_mobs` WHERE `CityId` = '%u'", m_cityInfo.cityId);
if(Result)
{
do
{
AddMobGUID(Result->Fetch()[0].GetUInt32());
}while(Result->NextRow());
}
else
{
#ifdef LOAD_CREATURE_SPAWNS_FROM_DATABASE
loadCityMobs();
#else
sLog.outError("Loading of mobs at Conquest City %u failed, no query result returned", m_cityInfo.cityId);
#endif
}*/
}
void City::loadCityMobs()
{
/*QueryResult_AutoPtr Result = WorldDatabase.PQuery("SELECT `guid`, `id`, `position_x`, `position_y`, `position_z` FROM `creature` WHERE `map` = '%u'", m_cityInfo.mapId);
if(Result)
{
do
{
float Dist = CalcDistance(m_cityInfo.baseCords, WorldLocation(0, Result->Fetch()[2].GetFloat(), Result->Fetch()[3].GetFloat(), Result->Fetch()[4].GetFloat()));
if(Dist <= m_cityInfo.maxDist && Result->Fetch()[1].GetUInt32() != m_cityInfo.triggerNpc)
AddMobGUID(Result->Fetch()[0].GetUInt32());
}while(Result->NextRow());
saveCityMobs();
}*/
}
void City::saveCityMobs()
{
CreatureGUIDSet::iterator Itr;
for(Itr = cityMobs.begin(); Itr != cityMobs.end(); ++Itr)
{
WorldDatabase.PExecute("INSERT INTO `conquest_mobs` VALUES('%u', '%u')", m_cityInfo.cityId, (*Itr));
}
}
void City::UpdateCityData()
{
#ifdef SAVE_CITY_DATA
// Only update fields that we'll actually change
WorldDatabase.PExecute("UPDATE `conquest_city` SET `FactionController` = '%u' WHERE `CityId` = '%u'", m_cityInfo.factionId, m_cityInfo.cityId);
#endif
}
float City::CalcDistance(WorldLocation aVect,WorldLocation bVect)
{
return sCityConquest.CalcDistance(aVect, bVect);
}
// CityInfo
CityInfo *City::GetCityInfo()
{
return &m_cityInfo;
}
uint8 City::GetControllingFactionId()
{
return GetCityInfo()->factionId == CONQUEST_ALLIANCE_FACTION ? CONQUEST_TEAM_ALPHA : CONQUEST_TEAM_BRAVO;
}
// Takeover
void City::SwitchFaction(uint32 factionId)
{
if(GetCityBoss())
{
GetCityBoss()->CombatStop();
GetCityBoss()->AddObjectToRemoveList();
}
m_cityInfo.factionId = factionId;
SetCityBoss(NULL);
updateMobFactions();
UpdateCityData();
}
void City::SwitchFaction(Creature *mCreature, Player *pKiller)
{
if(pKiller->GetGuildId() == 0)
return;
if(GetCityBoss())
{
GetCityBoss()->CombatStop();
GetCityBoss()->AddObjectToRemoveList();
}
m_cityInfo.factionId = pKiller->GetGuildId();
string factionName = pKiller->GetGuildName();
sCityConquest.SendServerMessage("%s have captured [%s]!", factionName.c_str(), GetCityInfo()->cityName.c_str());
SetCityBoss(NULL);
updateMobFactions();
UpdateCityData();
}
// Takeover
void City::updateMobFactions()
{
CreatureGUIDSet::iterator Itr;
Map *conquestMap = sMapMgr.FindMap(GetCityInfo()->mapId); //MapManager::Instance().FindMap(GetCityInfo()->mapId);
if(conquestMap == NULL)
return;
for(Itr = cityMobs.begin(); Itr != cityMobs.end(); Itr++)
{
if(Creature *mCreature = conquestMap->GetCreature(*Itr))
{
mCreature->setFaction(CONQUEST_ALL_HOSTILE_FACTION);
mCreature->ClearInCombat();
}
}
}
// Mobs
void City::AddMob(Creature *pCreature)
{
if(GetCityInfo()->factionId != CONQUEST_ALLIANCE_FACTION && GetCityInfo()->factionId != CONQUEST_HORDE_FACTION)
pCreature->setFaction(CONQUEST_ALL_HOSTILE_FACTION);
CreatureGUIDSet::iterator Itr = cityMobs.find(pCreature->GetGUID());
if(Itr == cityMobs.end())
cityMobs.insert(pCreature->GetGUID());
}
void City::RemoveMob(Creature *pCreature)
{
CreatureGUIDSet::iterator Itr = cityMobs.find(pCreature->GetGUID());
if(Itr != cityMobs.end())
cityMobs.erase(Itr);
}
bool City::HasMob(Creature *pCreature)
{
CreatureGUIDSet::iterator Itr = cityMobs.find(pCreature->GetGUID());
if(Itr != cityMobs.end())
return true;
return false;
}
bool City::IsInRange(Unit *mUnit)
{
WorldLocation tLoc;
mUnit->GetPosition(&tLoc);
if(CalcDistance(m_cityInfo.baseCords, tLoc) <= m_cityInfo.maxDist)
return true;
return false;
}
bool City::IsTriggerNPC(Unit *mUnit)
{
if(mUnit->GetEntry() == m_cityInfo.triggerNpc)
return true;
return false;
}
// Creature Spawning
Creature* City::SpawnCreature(uint32 entryId, uint32 factionId, float x, float y, float z, float o)
{
Map *mMap = sMapMgr.FindMap(m_cityInfo.mapId); //MapManager::Instance().FindMap(m_cityInfo.mapId);
if(mMap == NULL)
return NULL;
uint32 mGuid = objmgr.GenerateLowGuid(HIGHGUID_UNIT);
Creature *mCreature = new Creature;
if(mCreature->Create(mGuid, mMap, PHASEMASK_NORMAL, entryId, 0, 0, x, y, z, o) == false)
{
delete mCreature;
return NULL;
}
mCreature->SetHomePosition(x, y, z, o);
mMap->Add(mCreature);
//sDLLManager.MapAddCreature(mMap, mCreature);
mCreature->setFaction(CONQUEST_ALL_HOSTILE_FACTION);
return mCreature;
}
// Hooks
void City::OnKillTrigger()
{
if(BossSpawned() == true)
return;
SetCityBoss(SpawnCreature(200000, m_cityInfo.factionId, m_cityInfo.bossCords.m_positionX, m_cityInfo.bossCords.m_positionY, m_cityInfo.bossCords.m_positionZ, m_cityInfo.bossCords.GetOrientation()));
if(BossSpawned())
sCityConquest.SendServerMessage("%s has been spawned in [%s]!", GetCityBoss()->GetName(), m_cityInfo.cityName.c_str());
}
PvPSystem (Trinity-Core Version)
This script I have released publicly several times but always seem to find a way to change it later on. This script will not compile as it contains several references to scripts I have not released here. For the most part you can simply comment out the affected areas and receive no loss of functionality, as these references were intended for special events and so on which your server doesn't have anyway.
This script contains one of the versions of my PvPExp system, which was a small attempt at making pvp rewards more interesting than a simple token per kill which all servers seem to be obsessed with for some reason.
This script uses PvPTitles to display the rank of the player which is used to distinguish pvp exp levels. This is one of the latest iterations of the system, which I never completed due to my server collapsing.
It should be working and reasonably stable, but it will more than likely need updates to work with the latest TC version.
PvpSystem.h
Code:
/* PvPSystem
* Copyright (C) 2010 Spectre
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef PvPSystem_H
#define PvPSystem_H
#define MAX_PVP_RANKS 14
#define MAX_PVP_RANK_DIFF 3
#define PVP_EXP_MULTIPLIER 250
#define PVP_RANK_DIFF_COST 500
#define PVP_EXP_DIFF_COST 5
struct PvPSystemData;
struct PvPSystemRewardData;
enum TRANCE_SHOPS
{
TRANCE_SHOP_NONE,
TRANCE_SHOP_PVP,
TRANCE_SHOP_TITLE,
TRANCE_SHOP_MORPH,
MAX_TRANCE_SHOPS,
};
enum PVP_REWARD_CURRENCY
{
PVP_REWARD_NON_FFA = 1500,
PVP_REWARD_FFA = 3500,
};
enum PVP_REWARD_EXP
{
PVP_EXP_NON_FFA_KILL = 15,
PVP_EXP_FFA_KILL = 25,
};
enum PVP_STATS
{
PVP_STAT_RANK,
PVP_STAT_TOTAL_KILLS,
PVP_STAT_NON_FFA_KILLS,
PVP_STAT_FFA_KILLS,
PVP_STAT_TOTAL_DEATHS,
PVP_STAT_TOTAL_EXP
};
enum ALLIANCE_PVP_TITLES
{
ALLIANCE_TITLE_PRIVATE = 1,
ALLIANCE_TITLE_CORPORAL = 2,
ALLIANCE_TITLE_SERGEANT = 3,
ALLIANCE_TITLE_MASTER_SERGEANT = 4,
ALLIANCE_TITLE_SERGEANT_MAJOR = 5,
ALLIANCE_TITLE_KNIGHT = 6,
ALLIANCE_TITLE_KNIGHT_LT = 7,
ALLIANCE_TITLE_KNIGHT_CPT = 8,
ALLIANCE_TITLE_KNIGHT_CHAMP = 9,
ALLIANCE_TITLE_LT_COMMANDER = 10,
ALLIANCE_TITLE_COMMANDER = 11,
ALLIANCE_TITLE_MARSHAL = 12,
ALLIANCE_TITLE_FIELD_MARSHAL = 13,
ALLIANCE_TITLE_GRAND_MARSHAL = 14,
};
enum HORDE_PVP_TITLES
{
HORDE_TITLE_SCOUT = 15,
HORDE_TITLE_GRUNT = 16,
HORDE_TITLE_SERGEANT = 17,
HORDE_TITLE_SENIOR_SERGEANT = 18,
HORDE_TITLE_FIRST_SERGEANT = 19,
HORDE_TITLE_STONE_GUARD = 20,
HORDE_TITLE_BLOOD_GUARD = 21,
HORDE_TITLE_LEGIONNAIRE = 22,
HORDE_TITLE_CENTURION = 23,
HORDE_TITLE_CHAMPION = 24,
HORDE_TITLE_LT_GENERAL = 25,
HORDE_TITLE_GENERAL = 26,
HORDE_TITLE_WARLORD = 27,
HORDE_TITLE_HIGH_WARLORD = 28,
};
// PvPManager
class PvPManager : public ScriptableObject
{
typedef std::map<uint32, PvPSystemRewardData*> PvPRewardMap;
public:
PvPManager();
~PvPManager();
// Database Management
void LoadFromDatabase();
// Pvp Rewards
PvPSystemRewardData *GetPvPRewardData(uint8 rankId);
// Hooks
void OnPlayerPvPKill(Player *pVictim, Player *pKiller);
private:
// PvP Rewards
PvPRewardMap m_pvpRewards;
};
#define sPvPManager (*ACE_Singleton<PvPManager, ACE_Null_Mutex>::instance())
// PvPSystem
class PvPSystem
{
public:
typedef std::map<std::string, uint32> PvPTargetMap;
PvPSystem(Player *pPlayer);
~PvPSystem();
// Database
void LoadFromDatabase(Player *pPlayer);
void SaveToDatabase();
// Stats Management
void ModifyStat(uint8 statIndex, uint32 statValue);
uint32 GetStatValue(uint8 statIndex);
uint32 GetNextRankExp();
const char *GetRankName();
// Rally Area
void SetInRallyArea(bool inRally) { m_inRally = inRally; }
bool IsInRallyArea() { return m_inRally; }
float CalcDistance(WorldLocation aVect, WorldLocation bVect);
// PvP Interaction
void OnPvPKill(Player *pAttacker, Player *pVictim);
uint32 GetTimeStamp();
// Currency Management
void ModifyCurrency(Player *pPlayer, int32 Amt, bool Remove);
// Gossip System
void SetLastVendorListId(uint32 listId) { m_lastVendorListId = listId; }
uint32 GetLastVendorListId() { return m_lastVendorListId; }
uint32 GetShopDiscount(uint8 shopId, uint32 itemPrice);
uint8 GetShopAccessLevel(uint8 shopId) { return m_shopAccess[shopId]; }
void DisplayPvPRewards();
private:
// Internal PvP Checks
bool _isHonorable(Player *pAttacker, Player *pVictim);
void _addTarget(std::string Ip, uint32 Time);
uint32 _getLastKilledTime(std::string Ip);
// Currency Management
uint32 _getCurrencyIncrease(uint32 defaultCurrency);
uint16 _getDivisorForAmt(uint32 Amt);
std::string _getCurrencyName(uint32 Amt);
// PvP Exp
void _awardPvPRank(uint8 rankId);
void _applyRankRewards(int8 rankId = -1);
uint32 _getExpIncrease(uint32 defaultExp);
protected:
// PlayerData
PvPSystemData *m_pvpData;
Player *m_plr;
// Rally Area
bool m_inRally;
// Internal PvP Data Storage
PvPTargetMap m_pvpTargets;
// PvPRewards
uint32 m_lastVendorListId;
float m_shopDiscount;
float m_currencyIncrease;
float m_expIncrease;
uint8 m_shopAccess[MAX_TRANCE_SHOPS];
};
// Creature
class CreatureExtender
{
public:
CreatureExtender() { m_inRally = false; }
~CreatureExtender() {}
void SetInRally(bool inRally) { m_inRally = inRally; }
bool IsInRally() { return m_inRally; }
protected:
bool m_inRally;
};
#endif // PvPSystem_H/* PvPSystem
* Copyright (C) 2010 Spectre
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "XenosPch.h"
#include "WoWTranceStorage.h"
#include "WarZone.h"
#include "WarZoneManager.h"
const uint32 PvPRanks[MAX_PVP_RANKS+1][2] =
{
{0, 0},
{ALLIANCE_TITLE_PRIVATE, HORDE_TITLE_SCOUT},
{ALLIANCE_TITLE_CORPORAL, HORDE_TITLE_GRUNT},
{ALLIANCE_TITLE_SERGEANT, HORDE_TITLE_SERGEANT},
{ALLIANCE_TITLE_MASTER_SERGEANT, HORDE_TITLE_SENIOR_SERGEANT},
{ALLIANCE_TITLE_SERGEANT_MAJOR, HORDE_TITLE_FIRST_SERGEANT},
{ALLIANCE_TITLE_KNIGHT, HORDE_TITLE_STONE_GUARD},
{ALLIANCE_TITLE_KNIGHT_LT, HORDE_TITLE_BLOOD_GUARD},
{ALLIANCE_TITLE_KNIGHT_CPT, HORDE_TITLE_LEGIONNAIRE},
{ALLIANCE_TITLE_KNIGHT_CHAMP, HORDE_TITLE_CENTURION},
{ALLIANCE_TITLE_LT_COMMANDER, HORDE_TITLE_CHAMPION},
{ALLIANCE_TITLE_COMMANDER, HORDE_TITLE_LT_GENERAL},
{ALLIANCE_TITLE_MARSHAL, HORDE_TITLE_GENERAL},
{ALLIANCE_TITLE_FIELD_MARSHAL, HORDE_TITLE_WARLORD},
{ALLIANCE_TITLE_GRAND_MARSHAL, HORDE_TITLE_HIGH_WARLORD}
};
//PvPManager
PvPManager::PvPManager()
{
}
PvPManager::~PvPManager()
{
PvPRewardMap::iterator Itr;
for(Itr = m_pvpRewards.begin(); Itr != m_pvpRewards.end(); ++Itr)
delete Itr->second;
m_pvpRewards.clear();
}
// Database Management
void PvPManager::LoadFromDatabase()
{
PvPRewardMap::iterator Itr;
for(Itr = m_pvpRewards.begin(); Itr != m_pvpRewards.end(); ++Itr)
delete Itr->second;
m_pvpRewards.clear();
if(QueryResult queryResult = WorldDatabase.Query("SELECT * FROM `trance_pvpsystem_rewards`"))
{
do
{
PvPSystemRewardData *rewardData = new PvPSystemRewardData(queryResult->Fetch());
rewardData->Init();
m_pvpRewards.insert(make_pair(rewardData->rewardRank, rewardData));
}while(queryResult->NextRow());
}
}
// Pvp Rewards
PvPSystemRewardData *PvPManager::GetPvPRewardData(uint8 rankId)
{
PvPRewardMap::iterator Itr = m_pvpRewards.find(rankId);
return Itr == m_pvpRewards.end() ? NULL : Itr->second;
}
// Hooks
void PvPManager::OnPlayerPvPKill(Player *pVictim, Player *pKiller)
{
pKiller->GetPvPSystem()->OnPvPKill(pKiller, pVictim);
}
// PvPSystem
PvPSystem::PvPSystem(Player *pPlayer)
{
m_plr = pPlayer;
m_inRally = false;
m_pvpData = NULL;
m_shopDiscount = 0.00f;
SetLastVendorListId(0);
for(uint8 i = 0; i < MAX_TRANCE_SHOPS; i++)
m_shopAccess[i] = 0;
}
PvPSystem::~PvPSystem()
{
m_pvpTargets.clear();
}
// Database
void PvPSystem::LoadFromDatabase(Player *pPlayer)
{
if(m_pvpData != NULL)
return;
if(QueryResult queryResult = WorldDatabase.PQuery("SELECT * FROM `trance_pvpsystem` where `playerGuid` = '%u'", pPlayer->GetGUIDLow()))
{
m_pvpData = new PvPSystemData(queryResult->Fetch());
m_pvpData->Init();
}
else
{
m_pvpData = new PvPSystemData(NULL);
m_pvpData->playerGuid = pPlayer->GetGUIDLow();
m_pvpData->playerRank = 0;
m_pvpData->totalKills = 0;
m_pvpData->nonFFAKills = 0;
m_pvpData->ffaKills = 0;
m_pvpData->totalDeaths = 0;
m_pvpData->totalExp = 0;
}
_applyRankRewards();
}
void PvPSystem::SaveToDatabase()
{
if(m_pvpData)
WorldDatabase.PExecute("REPLACE INTO `trance_pvpsystem` VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '%u')", m_pvpData->playerGuid, m_pvpData->playerRank, m_pvpData->totalKills, m_pvpData->nonFFAKills, m_pvpData->ffaKills, m_pvpData->totalDeaths, m_pvpData->totalExp);
}
// Stats Management
void PvPSystem::ModifyStat(uint8 statIndex, uint32 statValue)
{
switch(statIndex)
{
case PVP_STAT_RANK: m_pvpData->playerRank += statValue; break;
case PVP_STAT_TOTAL_KILLS: m_pvpData->totalKills += statValue; break;
case PVP_STAT_NON_FFA_KILLS: m_pvpData->nonFFAKills += statValue; break;
case PVP_STAT_FFA_KILLS: m_pvpData->ffaKills += statValue; break;
case PVP_STAT_TOTAL_DEATHS: m_pvpData->totalDeaths += statValue; break;
case PVP_STAT_TOTAL_EXP:
{
m_pvpData->totalExp += statValue;
if(m_pvpData->totalExp >= GetNextRankExp())
_awardPvPRank(m_pvpData->playerRank+1);
else
m_plr->BroadcastMessage("PvP-Exp Increased by: %u", statValue);
}break;
}
}
uint32 PvPSystem::GetStatValue(uint8 statIndex)
{
switch(statIndex)
{
case PVP_STAT_RANK:
return m_pvpData->playerRank;
case PVP_STAT_TOTAL_KILLS:
return m_pvpData->totalKills;
case PVP_STAT_NON_FFA_KILLS:
return m_pvpData->nonFFAKills;
case PVP_STAT_FFA_KILLS:
return m_pvpData->ffaKills;
case PVP_STAT_TOTAL_DEATHS:
return m_pvpData->totalDeaths;
case PVP_STAT_TOTAL_EXP:
return m_pvpData->totalExp;
default:
return 0;
}
}
uint32 PvPSystem::GetNextRankExp()
{
return PVP_EXP_MULTIPLIER * (GetStatValue(PVP_STAT_RANK)+1);
}
const char *PvPSystem::GetRankName()
{
const CharTitlesEntry *charTitle = sCharTitlesStore.LookupEntry(PvPRanks[GetStatValue(PVP_STAT_RANK)][m_plr->GetTeamId()]);
if(charTitle)
return charTitle->name[sWorld.GetDefaultDbcLocale()];
return "None";
}
// Rally Area
float PvPSystem::CalcDistance(WorldLocation aVect, WorldLocation bVect)
{
float x = aVect.m_positionX - bVect.m_positionX;
float y = aVect.m_positionY - bVect.m_positionY;
float z = aVect.m_positionZ - bVect.m_positionZ;
return sqrtf(z*z + y*y + x*x);
}
// PvP Interaction
void PvPSystem::OnPvPKill(Player *pAttacker, Player *pVictim)
{
if(_isHonorable(pAttacker, pVictim) == false)
return;
uint32 currencyReward = pVictim->pvpInfo.inFFAPvPArea ? PVP_REWARD_FFA : PVP_REWARD_NON_FFA;
uint32 expReward = pVictim->pvpInfo.inFFAPvPArea ? PVP_EXP_FFA_KILL : PVP_EXP_NON_FFA_KILL;
if(pVictim->pvpInfo.inFFAPvPArea)
{
ModifyStat(PVP_STAT_FFA_KILLS, 1);
pAttacker->BroadcastMessage("Free-For-All-Area Bonus Granted");
}
else
ModifyStat(PVP_STAT_NON_FFA_KILLS, 1);
uint32 attackerRank = GetStatValue(PVP_STAT_RANK);
uint32 victimRank = pVictim->GetPvPSystem()->GetStatValue(PVP_STAT_RANK);
if(attackerRank > victimRank)
{
currencyReward -= PVP_RANK_DIFF_COST*(attackerRank-victimRank);
expReward -= PVP_EXP_DIFF_COST*(attackerRank-victimRank);
pAttacker->BroadcastMessage("Lower rank kill, points have been deducted");
}
if(WarZone *wZone = sWarZoneMgr.GetWarZoneBy(pAttacker))
{
currencyReward += wZone->GetPvPCurrencyIncrease();
expReward += wZone->GetPvPExpIncrease();
}
// Stats Logging
ModifyStat(PVP_STAT_TOTAL_KILLS, 1);
// Victim
pVictim->GetPvPSystem()->ModifyStat(PVP_STAT_TOTAL_DEATHS, 1);
ModifyCurrency(pAttacker, _getCurrencyIncrease(currencyReward), false);
ModifyStat(PVP_STAT_TOTAL_EXP, _getExpIncrease(expReward));
}
uint32 PvPSystem::GetTimeStamp()
{
time_t UNIXTIME = time(NULL);
tm LocalTime = *localtime(&UNIXTIME);
return uint32(UNIXTIME);
}
// Internal PvP Checks
bool PvPSystem::_isHonorable(Player *pAttacker, Player *pVictim)
{
if(!pVictim->GetSession() || !pAttacker->GetSession())
return false;
if(pVictim->HasAuraType(SPELL_AURA_NO_PVP_CREDIT) || pVictim->HasAura(SPELL_AURA_PLAYER_INACTIVE))
return false;
string aIp = pAttacker->GetSession()->GetRemoteAddress();
string vIp = pVictim->GetSession()->GetRemoteAddress();
if(aIp.compare(vIp) == 0 && pAttacker->isGameMaster() == false)
return false;
uint8 attackerRank = GetStatValue(PVP_STAT_RANK);
uint8 victimRank = pVictim->GetPvPSystem()->GetStatValue(PVP_STAT_RANK);
if(attackerRank > victimRank)
{
if(victimRank+MAX_PVP_RANK_DIFF < attackerRank)
{
pAttacker->BroadcastMessage("You cannot gain points from killer players %u ranks lower than your own", uint32(MAX_PVP_RANK_DIFF));
return false;
}
}
if(victimRank > attackerRank)
{
if(attackerRank+MAX_PVP_RANK_DIFF < victimRank)
{
pAttacker->BroadcastMessage("You cannot gain points from killer players %u ranks higher than your own", uint32(MAX_PVP_RANK_DIFF));
return false;
}
}
uint32 LastKilled = _getLastKilledTime(vIp);
uint32 CurrentTime = GetTimeStamp();
uint32 tMax = 180;
uint32 Time = CurrentTime - LastKilled;
uint32 tLeft = tMax - Time;
if(tMax && tLeft < tMax)
{
pAttacker->BroadcastMessage("You may not collect points from %s for another %u seconds", pVictim->GetName(), tLeft);
return false;
}
else
_addTarget(vIp, CurrentTime);
if(tMax)
pAttacker->BroadcastMessage("You have killed %s you will not gain points from killing him again until another 3 minutes", pVictim->GetName());
else
pAttacker->BroadcastMessage("You have killed %s", pVictim->GetName());
return true;
}
void PvPSystem::_addTarget(std::string Ip, uint32 Time)
{
PvPTargetMap::iterator Itr = m_pvpTargets.find(Ip);
if(Itr == m_pvpTargets.end())
m_pvpTargets.insert(std::make_pair(Ip, Time));
else
Itr->second = Time;
}
uint32 PvPSystem::_getLastKilledTime(std::string Ip)
{
PvPTargetMap::iterator Itr = m_pvpTargets.find(Ip);
return Itr != m_pvpTargets.end() ? Itr->second : 0;
}
// Currency Management
void PvPSystem::ModifyCurrency(Player *pPlayer, int32 Amt, bool Remove)
{
uint32 Current = pPlayer->GetMoney();
char curMsg[200];
if(Amt > 0 && Remove == false)
pPlayer->ModifyMoney(Amt);
else if(Amt <= Current && Remove)
pPlayer->SetMoney(Current - Amt);
else if (Remove)
pPlayer->SetMoney(0);
sprintf(curMsg, "Currency Modified %i %s %s", Amt/_getDivisorForAmt(Amt), _getCurrencyName(Amt).c_str(), Remove ? "Removed" : "Awarded");
pPlayer->BroadcastMessage(curMsg);
}
uint16 PvPSystem::_getDivisorForAmt(uint32 Amt)
{
float Res = Amt / 10000;
if(Res >= 1.0f)
return 10000;
Res = Amt / 100;
if(Res >= 1.0f)
return 100;
else return 1;
}
std::string PvPSystem::_getCurrencyName(uint32 Amt)
{
uint16 Divisor = _getDivisorForAmt(Amt);
string Blah;
switch(Divisor)
{
case 10000:
{
Blah += "Gold";
}break;
case 100:
{
Blah += "Silver";
}break;
case 1:
{
Blah += "Copper";
}break;
default:
{
Blah += "Unknown";
}break;
}
return Blah;
}
void PvPSystem::DisplayPvPRewards()
{
m_plr->BroadcastMessage("Dispalying Current PvP-Rewards");
m_plr->BroadcastMessage("------------------------------");
m_plr->BroadcastMessage("PvP-Shop Access Level: %u", m_shopAccess[TRANCE_SHOP_PVP]);
m_plr->BroadcastMessage("Title-Shop Access Level: %u", m_shopAccess[TRANCE_SHOP_TITLE]);
m_plr->BroadcastMessage("Morph-Shop Access Level: %u", m_shopAccess[TRANCE_SHOP_MORPH]);
m_plr->BroadcastMessage("Shop Discount: %.1f%%", m_shopDiscount);
m_plr->BroadcastMessage("Currency Gain Increase: %.1f%%", m_currencyIncrease);
m_plr->BroadcastMessage("Experience Gain Increase: %.1f%%", m_expIncrease);
}
// PvP Exp
void PvPSystem::_awardPvPRank(uint8 rankId)
{
const CharTitlesEntry *charTitle = sCharTitlesStore.LookupEntry(PvPRanks[rankId][m_plr->GetTeamId()]);
if(charTitle == NULL)
return;
m_pvpData->playerRank = rankId;
m_pvpData->totalExp = 0;
m_plr->SetTitle(charTitle);
m_plr->SetUInt32Value(PLAYER_CHOSEN_TITLE, PvPRanks[rankId][m_plr->GetTeamId()]);
m_plr->BroadcastMessage("You have achieved rank %s!", GetRankName());
_applyRankRewards(rankId);
SaveToDatabase();
}
void PvPSystem::_applyRankRewards(int8 rankId)
{
PvPSystemRewardData *rewardData = sPvPManager.GetPvPRewardData(rankId == -1 ? GetStatValue(PVP_STAT_RANK) : rankId);
if(rewardData == NULL)
return;
if(rankId != -1)
{
if(m_shopAccess[TRANCE_SHOP_PVP] < rewardData->rewardPvPShopLevel)
m_plr->BroadcastMessage("Your PvP-Shop Access has been upgraded to level %u", rewardData->rewardPvPShopLevel);
if(m_shopAccess[TRANCE_SHOP_TITLE] < rewardData->rewardTitleShopLevel)
m_plr->BroadcastMessage("Your Title-Shop Access has been upgraded to level %u", rewardData->rewardTitleShopLevel);
if(m_shopAccess[TRANCE_SHOP_MORPH] < rewardData->rewardMorphShopLevel)
m_plr->BroadcastMessage("Your Morph-Shop Access has been upgraded to level %u", rewardData->rewardMorphShopLevel);
if(m_shopDiscount < rewardData->rewardShopDiscount)
m_plr->BroadcastMessage("Your Store Discount has been upgraded to a total of %.1f%%", rewardData->rewardShopDiscount);
if(m_currencyIncrease < rewardData->rewardCurrencyIncrease)
m_plr->BroadcastMessage("Your Currency Gain has been increased to a total of %.1f%%", rewardData->rewardCurrencyIncrease);
if(m_expIncrease < rewardData->rewardExpIncrease)
m_plr->BroadcastMessage("Your Experience Gain has been increased to a total of %.1f%%", rewardData->rewardExpIncrease);
}
m_shopAccess[TRANCE_SHOP_PVP] = rewardData->rewardPvPShopLevel;
m_shopAccess[TRANCE_SHOP_TITLE] = rewardData->rewardTitleShopLevel;
m_shopAccess[TRANCE_SHOP_MORPH] = rewardData->rewardMorphShopLevel;
m_shopDiscount = rewardData->rewardShopDiscount;
m_currencyIncrease = rewardData->rewardCurrencyIncrease;
m_expIncrease = rewardData->rewardExpIncrease;
if(rankId != -1)
{
ModifyCurrency(m_plr, rewardData->rewardCurrency, false);
ModifyStat(PVP_STAT_TOTAL_EXP, rewardData->rewardExp);
}
}
// Rewards
uint32 PvPSystem::GetShopDiscount(uint8 shopId, uint32 itemPrice)
{
uint32 decreaseAmt = m_shopDiscount * itemPrice / 100;
return itemPrice - decreaseAmt;
}
uint32 PvPSystem::_getCurrencyIncrease(uint32 defaultCurrency)
{
uint32 increaseAmt = m_currencyIncrease * defaultCurrency / 100;
return defaultCurrency + increaseAmt;
}
uint32 PvPSystem::_getExpIncrease(uint32 defaultExp)
{
uint32 increaseAmt = m_expIncrease * defaultExp / 100;
return defaultExp + increaseAmt;
}
All these scripts contain some type of SQL-Dependency, sql files are not included in these releases. Most of the SQL's have been lost due to the script being outdated, others I'm just to lazy to dig up a version from my SQL backups. At any rate, my Load functions state their structures pretty clearly, so you shouldn't have a problem there.