Système de QG de guilde
Voici quelques temps déjà que j'ai eu pour projet de créer un système de QG de guilde "Blizzlike", c'est à dire 100% automatisé et de la manière la plus propre possible.

Voici donc le repo git sur lequel se trouve ce projet, il est en source libre :
repo.

Listes des fichiers ajoutés/Modifiés

+ src/server/game/guilds/GuildQG.h
+ src/server/game/guilds/GuildQG.cpp
+ src/server/scripts/world/npc_guild.qg.cpp

src/server/game/guilds/Guild.h
src/server/game/guilds/Guild.cpp
src/server/game/entities/Player.h
src/server/game/entities/Player.cpp
src/server/game/scripting/ScriptLoad.cpp

Fonctionnalités actuelles :

- Définition des zones, des noms et du prix des Qg de guilde via la DB.
- Utilise le système de phasemask (par conséquent, 62 QGs maximum par zone définies en DB).
- Création automatique de QG de guilde via un PNJ.
- Permet d'ajouter des gameobjects dans le QG de guilde.
- Re-téléporte le joueur à son QG si il sort de l'area.

A venir :

- NPC vendeur d'items pour gameobject (liste des GOs disponible et de leur prix à définir)
- Items pour ajouter des Pnjs.

Si vous avez des remarques, des suggestions ou que vous ne comprenez pas bien le principe du système, n'hésitez pas à me demander.

Je peux répondre aux questions sur "comment l'installer" pour autant que vous soyez au minimum un utilisateur averti, sinon, débrouillez-vous Smile.
Question bête mais, Pour allez a sont QG le joueur vas voir un PNJ, qui le TP directement dans le bon QG ?
Voila le patch, pour ceux qui veulent essayer :

Here is the patch, work fine for me on commit 156d491c2771fcff1ff2 "Core/Spells: Add GetTriggeringSpell() method to SpellScript and use it to properly filter server side spell 18350's script."



Code :
From c1fbc323dc63c9f4b0ce3d74e5641f45bad5c341 Mon Sep 17 00:00:00 2001
From: mograine <[email protected]>
Date: Sat, 6 Aug 2011 21:15:08 +0200
Subject: [PATCH] GuildQG system

diff --git a/sql/GuildQG/GuildQg_characters_base.sql b/sql/GuildQG/GuildQg_characters_base.sql
new file mode 100644
index 0000000..24645fe
--- /dev/null
+++ b/sql/GuildQG/GuildQg_characters_base.sql
@@ -0,0 +1,27 @@
+DROP TABLE IF EXISTS `GuildQG_template`;
+CREATE TABLE `GuildQG_template` (
+  `id` int(16) NOT NULL AUTO_INCREMENT,
+  `name` text NOT NULL,
+  `map` int(8) NOT NULL,
+  `x` float NOT NULL DEFAULT '0',
+  `y` float NOT NULL DEFAULT '0',
+  `z` float NOT NULL DEFAULT '0',
+  `o` float NOT NULL DEFAULT '0',
+  `disabled` int(16) DEFAULT '0',
+  PRIMARY KEY (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+DROP TABLE IF EXISTS `GuildQG`;
+CREATE TABLE `GuildQG` (
+  `GuildId` int(16) NOT NULL,
+  `QG_Id` int(16) NOT NULL,
+  `phasemask` int(8) NOT NULL default '1',
+  `IsActivated` int(16) DEFAULT '0',
+  PRIMARY KEY (`GuildId`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+DROP TABLE IF EXISTS `character_QG`;
+CREATE TABLE `character_QG` (
+  `guid` int(16) NOT NULL,
+  PRIMARY KEY (`guid`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
diff --git a/sql/GuildQG/GuildQg_world_base.sql b/sql/GuildQG/GuildQg_world_base.sql
new file mode 100644
index 0000000..8efffb4
--- /dev/null
+++ b/sql/GuildQG/GuildQg_world_base.sql
@@ -0,0 +1,30 @@
+DROP TABLE IF EXISTS `GuildQG_AddList`;
+CREATE TABLE `GuildQG_AddList` (
+  `item_entry` int(8) NOT NULL,
+  `type` tinyint(1) NOT NULL,
+  `entry` int(8) NOT NULL default '1',
+  `comment` text,
+  PRIMARY KEY (`item_entry`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+INSERT INTO npc_text (`id`, `text0_0`) VALUES
+(100000, "welcome gm"),
+(100001, "gm"),
+(100002, "member"),
+(100003, "teleport"),
+(100004, "list"),
+(100005, "confirm"),
+(100006, "ok"),
+(100007, "desactive"),
+(100008, "not_gm"),
+(100009, "already GQ"),
+(100010, "no money"),
+(100011, "no template"),
+(100012, "no phase"),
+(100013, "tp error")
+(100014, "no guild");
+
+INSERT INTO `item_template` (`entry`, `class`, `subclass`, `unk0`, `name`, `displayid`, `Quality`, `Flags`, `FlagsExtra`, `BuyCount`, `BuyPrice`, `SellPrice`, `InventoryType`, `AllowableClass`, `AllowableRace`, `ItemLevel`, `RequiredLevel`, `RequiredSkill`, `RequiredSkillRank`, `requiredspell`, `requiredhonorrank`, `RequiredCityRank`, `RequiredReputationFaction`, `RequiredReputationRank`, `maxcount`, `stackable`, `ContainerSlots`, `StatsCount`, `stat_type1`, `stat_value1`, `stat_type2`, `stat_value2`, `stat_type3`, `stat_value3`, `stat_type4`, `stat_value4`, `stat_type5`, `stat_value5`, `stat_type6`, `stat_value6`, `stat_type7`, `stat_value7`, `stat_type8`, `stat_value8`, `stat_type9`, `stat_value9`, `stat_type10`, `stat_value10`, `ScalingStatDistribution`, `ScalingStatValue`, `dmg_min1`, `dmg_max1`, `dmg_type1`, `dmg_min2`, `dmg_max2`, `dmg_type2`, `armor`, `holy_res`, `fire_res`, `nature_res`, `frost_res`, `shadow_res`, `arcane_res`, `delay`, `ammo_type`, `RangedModRange`, `spellid_1`, `spelltrigger_1`, `spellcharges_1`, `spellppmRate_1`, `spellcooldown_1`, `spellcategory_1`, `spellcategorycooldown_1`, `spellid_2`, `spelltrigger_2`, `spellcharges_2`, `spellppmRate_2`, `spellcooldown_2`, `spellcategory_2`, `spellcategorycooldown_2`, `spellid_3`, `spelltrigger_3`, `spellcharges_3`, `spellppmRate_3`, `spellcooldown_3`, `spellcategory_3`, `spellcategorycooldown_3`, `spellid_4`, `spelltrigger_4`, `spellcharges_4`, `spellppmRate_4`, `spellcooldown_4`, `spellcategory_4`, `spellcategorycooldown_4`, `spellid_5`, `spelltrigger_5`, `spellcharges_5`, `spellppmRate_5`, `spellcooldown_5`, `spellcategory_5`, `spellcategorycooldown_5`, `bonding`, `description`, `PageText`, `LanguageID`, `PageMaterial`, `startquest`, `lockid`, `Material`, `sheath`, `RandomProperty`, `RandomSuffix`, `block`, `itemset`, `MaxDurability`, `area`, `Map`, `BagFamily`, `TotemCategory`, `socketColor_1`, `socketContent_1`, `socketColor_2`, `socketContent_2`, `socketColor_3`, `socketContent_3`, `socketBonus`, `GemProperties`, `RequiredDisenchantSkill`, `ArmorDamageModifier`, `Duration`, `ItemLimitCategory`, `HolidayId`, `ScriptName`, `DisenchantID`, `FoodType`, `minMoneyLoot`, `maxMoneyLoot`, `WDBVerified`) VALUES('80000','15','1','-1','Parchemin de portail','28862','1','0','0','1','2000','500','0','-1','-1','40','0','0','0','0','0','0','0','0','0','20','0','0','0'​,'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'​,'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'​,'0','0','0','0','0','0','0','67864','0','-1','0','-1','0','-1','0','0','0','0','-1','0','-1','0','0','0','0','-1','0','-1','0','0','0','0','-1','0','-1','0','0','0','0','-1','0','-1','1','Permet au Maître de guilde de créer un portail dans son QG','0','0','0','0','0','2','0','0','0','0','0','0','0','0',​'0','0','0','0','0','0','0','0','0','0','-1','0','0','0','0','item_guild_spawner','0','0','0','0','123​40');
+INSERT INTO `creature_template` (`entry`, `difficulty_entry_1`, `difficulty_entry_2`, `difficulty_entry_3`, `KillCredit1`, `KillCredit2`, `modelid1`, `modelid2`, `modelid3`, `modelid4`, `name`, `subname`, `IconName`, `gossip_menu_id`, `minlevel`, `maxlevel`, `exp`, `faction_A`, `faction_H`, `npcflag`, `speed_walk`, `speed_run`, `scale`, `rank`, `mindmg`, `maxdmg`, `dmgschool`, `attackpower`, `dmg_multiplier`, `baseattacktime`, `rangeattacktime`, `unit_class`, `unit_flags`, `dynamicflags`, `family`, `trainer_type`, `trainer_spell`, `trainer_class`, `trainer_race`, `minrangedmg`, `maxrangedmg`, `rangedattackpower`, `type`, `type_flags`, `lootid`, `pickpocketloot`, `skinloot`, `resistance1`, `resistance2`, `resistance3`, `resistance4`, `resistance5`, `resistance6`, `spell1`, `spell2`, `spell3`, `spell4`, `spell5`, `spell6`, `spell7`, `spell8`, `PetSpellDataId`, `VehicleId`, `mingold`, `maxgold`, `AIName`, `MovementType`, `InhabitType`, `Health_mod`, `Mana_mod`, `Armor_mod`, `RacialLeader`, `questItem1`, `questItem2`, `questItem3`, `questItem4`, `questItem5`, `questItem6`, `movementId`, `RegenHealth`, `equipment_id`, `mechanic_immune_mask`, `flags_extra`, `ScriptName`, `WDBVerified`) VALUES('159754','0','0','0','0','0','27465','0','0','0','Vic​kar','Maître des QG de Guilde','','0','82','82','2','35','35','1','1','1.14286','1'​,'4','500','500','0','500','500','500','500','1','0','0','0'​,'0','0','0','0','500','500','500','0','0','0','0','0','0','​0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','​0','0','','1','4','1.5','1','1','0','0','0','0','0','0','0',​'0','1','0','0','0','npc_guild_qg','12340');
+
+INSERT INTO `GuildQG_AddList values (80000, 0, 195682, "Portail vers Dalaran");
\ No newline at end of file
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index cf3512a..5709b1f 100755
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -73,6 +73,7 @@
#include "CharacterDatabaseCleaner.h"
#include "InstanceScript.h"
#include <cmath>
+#include "GuildQG.h"

#define ZONE_UPDATE_INTERVAL (1*IN_MILLISECONDS)

@@ -847,6 +848,8 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa
     isDebugAreaTriggers = false;

     SetPendingBind(NULL, 0);
+
+    pPlayerQG = new PlayerGuildQG();
}

Player::~Player ()
@@ -882,6 +885,7 @@ Player::~Player ()

     delete m_declinedname;
     delete m_runes;
+    delete pPlayerQG;

     sWorld->DecreasePlayerCount();
}
@@ -2307,6 +2311,22 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
         else
             return false;
     }
+
+    if (Guild* pGuild = sGuildMgr->GetGuildById(GetGuildId()))
+    {
+        if (pPlayerQG->IsPlayerWaitingForPhaseMask())
+        {
+            SetPhaseMask(pGuild->pGuildQG->GetPhaseMask(), true);
+            pPlayerQG->SetPlayerWaitingForPhaseMask(false);
+            pPlayerQG->SetIsInQG(true);
+        }
+        else if (pPlayerQG->IsInQG())
+        {
+            SetPhaseMask(1, true);
+            pPlayerQG->SetIsInQG(false);
+        }
+    }
+
     return true;
}

@@ -7375,6 +7395,15 @@ void Player::UpdateArea(uint32 newArea)
     }
     else
         RemoveByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_SANCTUARY);
+
+    if (Guild* pGuild = sGuildMgr->GetGuildById(GetGuildId()))
+    {
+        if (pPlayerQG->IsInQG())// If player is in GuildQG, he can't leave the Area
+        {
+            pPlayerQG->SetPlayerWaitingForPhaseMask(true); // Avoid removing phasemask
+            pGuild->pGuildQG->TeleportPlayerToQG(this);
+        }
+    }
}

void Player::UpdateZone(uint32 newZone, uint32 newArea)
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 17f43cc..6131f4b 100755
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -54,8 +54,8 @@ class PlayerMenu;
class PlayerSocial;
class SpellCastTargets;
class UpdateMask;
-
typedef std::deque<Mail*> PlayerMails;
+class PlayerGuildQG;

#define PLAYER_MAX_SKILLS           127
#define PLAYER_MAX_DAILY_QUESTS     25
@@ -2467,6 +2467,8 @@ class Player : public Unit, public GridObject<Player>
         float GetAverageItemLevel();
         bool isDebugAreaTriggers;

+        PlayerGuildQG * pPlayerQG;
+
     protected:
         uint32 m_regenTimerCount;
         float m_powerFraction[MAX_POWERS];
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp
index accfba7..b62fcf7 100755
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -24,6 +24,7 @@
#include "Config.h"
#include "SocialMgr.h"
#include "Log.h"
+#include "GuildQG.h"

#define MAX_GUILD_BANK_TAB_TEXT_LEN 500
#define EMBLEM_PRICE 10 * GOLD
@@ -1072,6 +1073,7 @@ InventoryResult Guild::BankMoveItemData::_CanStore(Item* pItem, bool swap)
Guild::Guild() : m_id(0), m_leaderGuid(0), m_createdDate(0), m_accountsNumber(0), m_bankMoney(0), m_eventLog(NULL)
{
     memset(&m_bankEventLog, 0, (GUILD_BANK_MAX_TABS + 1) * sizeof(LogHolder*));
+    pGuildQG = new GuildQG(this);
}

Guild::~Guild()
@@ -1087,6 +1089,8 @@ Guild::~Guild()
             delete m_bankEventLog[tabId];
     for (Members::iterator itr = m_members.begin(); itr != m_members.end(); ++itr)
         delete itr->second;
+
+    delete pGuildQG;
}

// Creates new guild with default data and saves it to database.
@@ -1851,6 +1855,7 @@ bool Guild::LoadFromDB(Field* fields)
     for (uint8 i = 0; i < purchasedTabs; ++i)
         m_bankTabs[i] = new BankTab(m_id, i);

+    pGuildQG->LoadFromDB();
     _CreateLogHolders();
     return true;
}
diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h
index f38d444..b55058d 100755
--- a/src/server/game/Guilds/Guild.h
+++ b/src/server/game/Guilds/Guild.h
@@ -25,6 +25,7 @@
#include "ObjectMgr.h"
#include "Player.h"

+class GuildQG;
class Item;

enum GuildMisc
@@ -666,6 +667,11 @@ public:

     // Bank tabs
     void SetBankTabText(uint8 tabId, const std::string& text);
+
+    // Bank Money
+    uint64 const GetBankMoney() { return m_bankMoney; }
+
+    GuildQG * pGuildQG;

protected:
     uint32 m_id;
diff --git a/src/server/game/Guilds/GuildQG.cpp b/src/server/game/Guilds/GuildQG.cpp
new file mode 100644
index 0000000..791b350
--- /dev/null
+++ b/src/server/game/Guilds/GuildQG.cpp
@@ -0,0 +1,423 @@
+#include "GuildQG.h"
+#include "Guild.h"
+
+/*********************
+***  GUILD QG MGR  ***
+*********************/
+
+GuildQGMgr::GuildQGMgr() {}
+
+GuildQGMgr::~GuildQGMgr() {}
+
+bool GuildQGMgr::GetTemplateById(uint32 QG_Id, GuildQG_Template & Qg_Template)
+{
+    for(std::vector< GuildQG_Template >::const_iterator Itr = QG_Template_List.begin(); Itr != QG_Template_List.end(); Itr++)
+    {
+        if((*Itr).m_id == QG_Id)
+        {
+            Qg_Template = (*Itr);
+            return true;
+        }
+    }
+
+    return false;
+}
+
+uint32 GuildQGMgr::GetFreePhaseMaskForId(uint32 QG_Id)
+{
+    std::vector<uint32> PhaseMaskListForId = PhaseMaskList[QG_Id];
+
+    if(PhaseMaskListForId.empty()) // No Phasemask for this QG_Id yet
+    {
+        PhaseMaskListForId.insert(PhaseMaskListForId.begin(), 2);
+        
+        PhaseMaskList.erase(QG_Id);
+        PhaseMaskList.insert(std::pair<uint32, std::vector<uint32> >(QG_Id, PhaseMaskListForId));
+        return 2;
+    }
+
+    uint32 Last_PhaseMask = 1;
+    uint8 PhaseMaskCount = 0; // Max 31 because of uint32
+
+    for(std::vector<uint32>::iterator Itr = PhaseMaskListForId.begin(); Itr != (++PhaseMaskListForId.end()); Itr++)
+    {
+        Last_PhaseMask *= 2;
+        PhaseMaskCount++;
+
+        if(PhaseMaskCount > MAX_QG_PHASES)
+            return 0;
+
+        if(Itr == PhaseMaskListForId.end()) // Reach the end without find a PhaseMask, but within the MAX_QG_PHASES limit
+        {
+            PhaseMaskListForId.insert(Itr, Last_PhaseMask);
+
+            PhaseMaskList.erase(QG_Id);
+            PhaseMaskList.insert(std::pair<uint32, std::vector<uint32> >(QG_Id, PhaseMaskListForId));
+
+            return Last_PhaseMask;
+        }
+
+        if((*Itr) != Last_PhaseMask)
+        {
+            PhaseMaskListForId.insert(Itr, Last_PhaseMask);
+
+            PhaseMaskList.erase(QG_Id);
+            PhaseMaskList.insert(std::pair<uint32, std::vector<uint32> >(QG_Id, PhaseMaskListForId));
+
+            return Last_PhaseMask;
+        }
+    }
+
+    return 0;
+}
+
+void GuildQGMgr::_AddTemplateInList(uint32 QG_Id, std::string QG_Name, uint32 map, float x, float y, float z, float o, uint64 price)
+{
+    WorldLocation GuildQG_Position(map, x, y, z, o);
+
+    GuildQG_Template QG_Template;
+    QG_Template.m_id = QG_Id;
+    QG_Template.m_name = QG_Name;
+    QG_Template.m_position = GuildQG_Position;
+    QG_Template.m_price = price;
+
+    QG_Template_List.push_back(QG_Template);
+        
+    std::vector<uint32> EmptyVector;
+    PhaseMaskList.insert( std::pair<uint32, std::vector<uint32> >(QG_Id, EmptyVector) ); // Prepare for load_phasemasks
+}
+
+void GuildQGMgr::LoadTemplates()
+{
+    uint32 oldMSTime = getMSTime();
+    QG_Template_List.clear();
+    PhaseMaskList.clear();
+
+    QueryResult result = CharacterDatabase.Query("SELECT id, name, map, x, y, z, o, price, disabled FROM GuildQG_Template ORDER BY id");
+
+    if(!result)
+    {
+        sLog->outString(">> Loaded 0 Guild QG template definitions. DB table `GuildQG_Template` is empty!");
+        sLog->outString();
+        return;
+    }
+
+    uint32 count = 0;
+
+    do
+    {
+        Field *fields = result->Fetch();
+
+        uint8 IsDisabled    = fields[8].GetUInt8();
+
+        if(IsDisabled)
+            continue;
+
+        uint32 QG_Id        = fields[0].GetUInt32();
+        std::string name    = fields[1].GetString();
+        uint32 map          = fields[2].GetUInt32();
+        float x             = fields[3].GetFloat();
+        float y             = fields[4].GetFloat();
+        float z             = fields[5].GetFloat();
+        float o             = fields[6].GetFloat();
+
+        uint64 price        = fields[7].GetUInt64();
+        price *= GOLD;
+        
+        _AddTemplateInList(QG_Id, name, map, x, y, z, o, price);
+
+        ++count;
+    } while (result->NextRow());
+
+    sLog->outString(">> Loaded %u Guild QG Template definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+    sLog->outString();
+}
+
+void GuildQGMgr::LoadPhaseMasks()
+{
+    uint32 oldMSTime = getMSTime();
+
+    QueryResult result = CharacterDatabase.Query("SELECT QG_Id, Phasemask FROM GuildQG ORDER BY QG_Id, Phasemask");
+    
+    if(!result)
+    {
+        sLog->outString(">> Loaded 0 Guild QG Phasemask. DB table `GuildQG` is empty!");
+        sLog->outString();
+        return;
+    }
+
+    uint32 count = 0;
+
+    do
+    {
+        Field *fields           = result->Fetch();
+        uint32 QG_Id            = fields[0].GetUInt32();
+        uint32 Last_Phasemask   = fields[1].GetUInt32();
+
+        std::vector<uint32> PhaseMaskListForId = PhaseMaskList[QG_Id];
+
+        PhaseMaskListForId.insert(PhaseMaskListForId.begin(), Last_Phasemask);
+        
+        PhaseMaskList.erase(QG_Id);
+        PhaseMaskList.insert(std::pair<uint32, std::vector<uint32> >(QG_Id, PhaseMaskListForId));
+
+        ++count;
+    } while (result->NextRow());
+
+    sLog->outString(">> Loaded %u Guild QG Phasemask in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+    sLog->outString();
+}
+
+void GuildQGMgr::LoadGobOrNpcList()
+{
+    uint32 oldMSTime = getMSTime();
+
+    QueryResult result = WorldDatabase.Query("SELECT item_entry, type, entry FROM GuildQG_AddList");
+
+    if(!result)
+    {
+        sLog->outString(">> Loaded 0 Guild QG possible adds definitions. DB table `GuildQG_AddList` is empty!");
+        sLog->outString();
+        return;
+    }
+
+    uint32 count = 0;
+
+    do
+    {
+        Field *fields = result->Fetch();
+        
+        uint32 item_entry   = fields[0].GetUInt32();
+        uint8  type         = fields[1].GetUInt32();
+        uint32 entry        = fields[2].GetUInt32();
+        
+        _AddGobOrNPCInList(item_entry, type, entry);
+
+        ++count;
+    } while (result->NextRow());
+
+    sLog->outString(">> Loaded %u Guild QG Gob or NPC list definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+    sLog->outString();
+}
+
+void GuildQGMgr::_AddGobOrNPCInList(uint32 item_entry, uint8 type, uint32 entry)
+{
+    switch(type)
+    {
+        case TYPE_OBJECT:
+            AddGobList.insert( std::pair<uint32, uint32>(item_entry, entry) );
+            break;
+        case TYPE_NPC:
+            AddNpcList.insert( std::pair<uint32, uint32>(item_entry, entry) );
+            break;
+    }
+}
+
+/*****************
+***  GUILD QG  ***
+*****************/
+
+GuildQG::GuildQG(Guild * pGuild)
+{
+    m_pGuild = pGuild;
+    m_Phase = 0;
+    IsActivated = false;
+}
+
+GuildQG::~GuildQG() {}
+
+QG_Errors GuildQG::BuyGuildQG(Player * pPlayer, uint32 QG_Template_Id)
+{
+    if(!CheckForPlayer(pPlayer))
+        return NO_PLAYER;
+
+    uint32 PhaseMask = 0;
+
+    /* TODO : add a configuration in .conf
+    if(!sWorld->getBoolConfig(CONFIG_GUILD_QG_SYSTEM))
+        return QG_SYSTEM_DESACTIVATED;*/
+
+    if(m_pGuild->GetLeaderGUID() != pPlayer->GetGUID())
+        return NOT_GUILD_MASTER;
+
+    if(IsActivated)
+        return ALREADY_HAVE_QG;
+
+    if(!sQGMgr->GetTemplateById(QG_Template_Id, QG_Template))
+        return NO_QG_TEMPLATE;
+
+    if(m_pGuild->GetBankMoney() < QG_Template.m_price)
+        return NOT_ENOUGH_MONEY;
+
+    if(!(PhaseMask = sQGMgr->GetFreePhaseMaskForId(QG_Template_Id))) // MUST BE THE LATEST
+        return NO_DISPONIBLE_PHASE;
+
+    m_Phase = PhaseMask;
+
+    uint32 WithDrawMoneyCount = MAX_UINT32;
+    uint64 TemplatePrice = QG_Template.m_price;
+
+    while(TemplatePrice > MAX_UINT32)
+    {
+        m_pGuild->HandleMemberWithdrawMoney(pPlayer->GetSession(), WithDrawMoneyCount);
+        TemplatePrice = TemplatePrice - MAX_UINT32;
+    }
+
+    m_pGuild->HandleMemberWithdrawMoney(pPlayer->GetSession(), TemplatePrice);
+
+    ActivateQG(true);
+
+    return OK;
+}
+
+QG_Errors GuildQG::SellGuildQG(Player * pPlayer)
+{
+    if(!CheckForPlayer(pPlayer))
+        return NO_PLAYER;
+
+    if(m_pGuild->GetLeaderGUID() != pPlayer->GetGUID())
+        return NOT_GUILD_MASTER;
+
+    m_pGuild->HandleMemberDepositMoney(pPlayer->GetSession(), uint32(QG_Template.m_price / 2));
+
+    ActivateQG(false);
+
+    return OK;
+}
+
+void GuildQG::ActivateQG(bool activate)
+{
+    IsActivated = activate;
+    SaveToDB();
+}
+
+void GuildQG::GetPosition(float & x, float & y)
+{
+    x = QG_Template.m_position.GetPositionX();
+    y = QG_Template.m_position.GetPositionY();
+}
+void GuildQG::GetPosition(float & x, float & y, float & z)
+{
+    GetPosition(x, y);
+    z = QG_Template.m_position.GetPositionZ();
+}
+void GuildQG::GetPosition(float & x, float & y, float & z, float & o)
+{
+    GetPosition(x, y, z);
+    o = QG_Template.m_position.GetOrientation();
+}
+void GuildQG::GetPosition(uint32 & map, float & x, float & y, float & z, float & o)
+{
+    GetPosition(x, y, z, o);
+    map = QG_Template.m_position.GetMapId();
+}
+
+bool GuildQG::TeleportPlayerToQG(uint64 PlayerGuid) const
+{
+    if(Player * pPlayer = ObjectAccessor::FindPlayer(PlayerGuid))
+        return TeleportPlayerToQG(pPlayer);
+    else
+        return false;
+}
+
+bool GuildQG::TeleportPlayerToQG(Player * pPlayer) const
+{
+    if(!CheckForPlayer(pPlayer))
+        return false;
+
+    pPlayer->pPlayerQG->SetPlayerWaitingForPhaseMask(true);
+
+    return pPlayer->TeleportTo(QG_Template.m_position);
+}
+
+void GuildQG::LoadFromDB()
+{
+    QueryResult result = CharacterDatabase.PQuery("SELECT QG_Id, PhaseMask, IsActivated FROM GuildQG WHERE GuildId = '%u'", m_pGuild->GetId());
+
+    if(!result)
+        return;
+    
+    Field *fields           = result->Fetch();
+    uint32 QG_Id            = fields[0].GetUInt32();
+    m_Phase                 = fields[1].GetUInt32();
+    uint8 IsActive          = fields[2].GetUInt8();
+
+    sQGMgr->GetTemplateById(QG_Id, QG_Template);
+
+    sLog->outString("Load : '%u', '%s'", QG_Template.m_id, QG_Template.m_name.c_str());
+
+    if(IsActive)
+        IsActivated = true;
+    else
+        IsActivated = false;
+
+}
+
+void GuildQG::SaveToDB() const
+{
+    uint8 IsActivatedInt = 0;
+
+    if(IsActivated)
+        IsActivatedInt = 1;
+
+    CharacterDatabase.PExecute("REPLACE INTO GuildQG (GuildId, QG_Id, PhaseMask, IsActivated) VALUES('%u', '%u', '%u', '%u')",
+        m_pGuild->GetId(), QG_Template.m_id, m_Phase, IsActivatedInt);
+}
+
+bool GuildQG::CheckForPlayer(Player * pPlayer) const
+{
+    if(!pPlayer)
+    {
+        sLog->outString("GuildQG function called without player ?");
+        return false;
+    }
+
+    return true;
+}
+
+/**************************
+***   PLAYER GUILD QG   ***
+**************************/
+
+PlayerGuildQG::PlayerGuildQG()
+{
+    IsPlayerInQG = false;
+    IsWaitingForPhaseMask = false;
+}
+
+PlayerGuildQG::~PlayerGuildQG() {}
+
+void PlayerGuildQG::SetIsInQG(bool IsInQg)
+{
+    if(IsPlayerInQG != IsInQg)
+    {
+        IsPlayerInQG = IsInQg;
+        SaveInDB();
+    }
+}
+
+void PlayerGuildQG::LoadFromDB(uint32 PlayerLowGUID)
+{
+    if(!PlayerLowGUID)
+        return;
+
+    _PlayerLowGUID = PlayerLowGUID;
+
+    QueryResult result = CharacterDatabase.PQuery("SELECT * FROM character_QG WHERE guid = '%u'", _PlayerLowGUID);
+    
+    if(result)
+        IsPlayerInQG = true;
+    else
+        IsPlayerInQG = false;
+}
+
+void PlayerGuildQG::SaveInDB() const
+{
+    if(!_PlayerLowGUID)
+        return;
+
+    if(IsPlayerInQG)
+        CharacterDatabase.PExecute("INSERT IGNORE INTO character_QG VALUES ('%u')", _PlayerLowGUID);
+    else
+        CharacterDatabase.PExecute("DELETE FROM character_QG WHERE guid = '%u'", _PlayerLowGUID);
+}
diff --git a/src/server/game/Guilds/GuildQG.h b/src/server/game/Guilds/GuildQG.h
new file mode 100644
index 0000000..2c7e28a
--- /dev/null
+++ b/src/server/game/Guilds/GuildQG.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2011-2012 Millenium Servers <http://www.millenium-servers.com/>
+ */
+
+#ifndef __TRINITYCORE_GUILDQG_H
+#define __TRINITYCORE_GUILDQG_H
+
+#include "Common.h"
+#include "Guild.h"
+
+class guild;
+
+/*
+   GuildQGMgr
+   GuildQG
+   PlayerGuildQG
+*/
+
+
+#define MAX_QG_PHASES       31
+#define MAX_UINT32          4294967295
+
+enum Add_Type
+{
+    TYPE_OBJECT     = 0,
+    TYPE_NPC        = 1,
+};
+
+enum QG_Errors
+{
+    OK                      = 0,
+    QG_SYSTEM_DESACTIVATED  = 1,
+    NOT_GUILD_MASTER        = 2,
+    ALREADY_HAVE_QG         = 3,
+    NOT_ENOUGH_MONEY        = 4,
+    NO_QG_TEMPLATE          = 5,
+    NO_DISPONIBLE_PHASE     = 6,
+    NO_PLAYER               = 7
+};
+
+struct GuildQG_Template
+{
+    uint32 m_id;
+    std::string m_name;
+    WorldLocation m_position;
+    uint64 m_price;
+};
+
+/*
+    Guild QG Mgr : used to load and get Templates & PhaseMasks
+*/
+
+typedef std::map<uint32, std::vector<uint32> > TypePhaseList;
+typedef std::vector<GuildQG_Template> TypeQGTemplateList;
+typedef std::map<uint32, uint32> TypeAddList;
+
+class GuildQGMgr
+{
+    public:
+
+        GuildQGMgr();
+        ~GuildQGMgr();
+
+        TypeQGTemplateList GetQGsTemplateList() const { return QG_Template_List; }
+        
+        TypeAddList GetNpcAddList() const { return AddNpcList; }
+        TypeAddList GetGobAddList() const { return AddGobList; }
+
+        bool GetTemplateById(uint32 QG_Id, GuildQG_Template & Qg_Template);
+
+        uint32 GetFreePhaseMaskForId(uint32 QG_Id);
+    
+        void LoadTemplates();
+        void LoadPhaseMasks();
+        void LoadGobOrNpcList();
+
+    private:
+
+        void _AddTemplateInList(uint32 QG_Id, std::string QG_Name, uint32 map, float x, float y, float z, float o, uint64 price);
+        void _AddGobOrNPCInList(uint32 item_entry, uint8 type, uint32 entry);
+    
+        TypeQGTemplateList QG_Template_List;
+        TypePhaseList PhaseMaskList;
+
+        TypeAddList AddNpcList;
+        TypeAddList AddGobList;
+};
+
+/*
+    Guild QG
+    Used by each guild
+*/
+
+class GuildQG
+{
+    public:
+        GuildQG(Guild * pGuild);
+        ~GuildQG();
+
+        QG_Errors BuyGuildQG(Player * pPlayer, uint32 QG_Template_Id);
+        QG_Errors SellGuildQG(Player * pPlayer);
+
+        GuildQG_Template GetQGTemplate() const { return QG_Template; }
+        uint32 GetPhaseMask() const { return m_Phase; }
+
+        void LoadFromDB();
+        void SaveToDB() const;
+
+        bool CheckForPlayer(Player * pPlayer) const;
+
+        void ActivateQG(bool activate);
+        bool IsQGActive() const { return IsActivated; }
+    
+        void GetPosition(WorldLocation & position) { position = QG_Template.m_position; }
+        void GetPosition(float & x, float & y);
+        void GetPosition(float & x, float & y, float & z);
+        void GetPosition(float & x, float & y, float & z, float & o);
+        void GetPosition(uint32 & map, float & x, float & y, float & z, float & o);
+    
+        bool TeleportPlayerToQG(uint64 PlayerGuid) const;
+        bool TeleportPlayerToQG(Player * pPlayer) const;
+
+    private:
+
+        Guild * m_pGuild;
+        uint32 m_Phase;
+        bool IsActivated;
+
+        GuildQG_Template QG_Template;
+};
+
+/*
+    Player Guild QG
+    Used by each player to know if he is in his QG or not
+    Usefull for TeleportTo function to know if we must change player's phasemask
+    Usefull for ChangeArea function to know if the player can leave the area
+*/
+
+class PlayerGuildQG
+{
+    public:
+        PlayerGuildQG();
+        ~PlayerGuildQG();
+        
+        void SetPlayerWaitingForPhaseMask(bool IsWaiting) { IsWaitingForPhaseMask = IsWaiting; }
+        bool IsPlayerWaitingForPhaseMask() const { return IsWaitingForPhaseMask; }
+        
+        void SetIsInQG(bool IsInQg);
+        bool IsInQG() const { return IsPlayerInQG; }
+
+        void LoadFromDB(uint32 PlayerLowGUID);
+        void SaveInDB()const;
+        
+    private:
+
+        uint32 _PlayerLowGUID;
+
+        bool IsPlayerInQG;
+        bool IsWaitingForPhaseMask;
+};
+
+#define sQGMgr ACE_Singleton<GuildQGMgr, ACE_Null_Mutex>::instance()
+
+#endif
diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp
index 5149308..dd6a1db 100755
--- a/src/server/game/Scripting/ScriptLoader.cpp
+++ b/src/server/game/Scripting/ScriptLoader.cpp
@@ -69,6 +69,7 @@ void AddSC_generic_creature();
void AddSC_go_scripts();
void AddSC_guards();
void AddSC_item_scripts();
+void AddSC_npc_guild_qg();
void AddSC_npc_professions();
void AddSC_npc_innkeeper();
void AddSC_npcs_special();
@@ -671,6 +672,7 @@ void AddWorldScripts()
     AddSC_go_scripts();
     AddSC_guards();
     AddSC_item_scripts();
+    AddSC_npc_guild_qg();
     AddSC_npc_professions();
     AddSC_npc_innkeeper();
     AddSC_npcs_special();
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 639af40..000ae18 100755
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -74,6 +74,7 @@
#include "CreatureTextMgr.h"
#include "SmartAI.h"
#include "Channel.h"
+#include "GuildQG.h"

volatile bool World::m_stopEvent = false;
uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE;
@@ -1522,6 +1523,11 @@ void World::SetInitialWorldSettings()
     sAuctionMgr->LoadAuctionItems();
     sLog->outString("Loading Auctions...");
     sAuctionMgr->LoadAuctions();
+    
+    sLog->outString("Loading GuildQG...");
+    sQGMgr->LoadTemplates();
+    sQGMgr->LoadPhaseMasks();
+    sQGMgr->LoadGobOrNpcList();

     sGuildMgr->LoadGuilds();

diff --git a/src/server/scripts/World/CMakeLists.txt b/src/server/scripts/World/CMakeLists.txt
index 41ba775..4a75269 100644
--- a/src/server/scripts/World/CMakeLists.txt
+++ b/src/server/scripts/World/CMakeLists.txt
@@ -18,6 +18,7 @@ set(scripts_STAT_SRCS
   World/guards.cpp
   World/item_scripts.cpp
   World/mob_generic_creature.cpp
+  World/npc_guild_qg.cpp
   World/npc_innkeeper.cpp
   World/npc_professions.cpp
   World/npc_taxi.cpp
diff --git a/src/server/scripts/World/npc_guild_qg.cpp b/src/server/scripts/World/npc_guild_qg.cpp
new file mode 100644
index 0000000..43c8f7f
--- /dev/null
+++ b/src/server/scripts/World/npc_guild_qg.cpp
@@ -0,0 +1,327 @@
+#include "ScriptPCH.h"
+#include "ScriptedEscortAI.h"
+#include "ObjectMgr.h"
+#include "ScriptMgr.h"
+#include "World.h"
+#include "GuildQG.h"
+#include "GuildMgr.h"
+
+/*######
+## npc_experience
+######*/
+
+#define GOSSIP_BUY                  "J'aimerais acheter un QG de guilde."
+#define GOSSIP_TELEPORT             "J'aimerais me rendre a notre QG de guilde."
+#define GOSSIP_SELL                 "J'aimerais revendre le QG de notre guilde."
+#define GOSSIP_CONFIRM              "Je confirme."
+
+enum Qg_Gossip_Texts
+{
+    GOSSIP_TEXT_WELCOME_GM      = 100000,
+    GOSSIP_TEXT_GM              = 100001,
+    GOSSIP_TEXT_MEMBER          = 100002,
+    GOSSIP_TEXT_TELEPORT        = 100003,
+    GOSSIP_TEXT_LIST            = 100004,
+
+    GOSSIP_TEXT_CONFIRM         = 100005,
+
+    GOSSIP_TEXT_OK              = 100006,
+    GOSSIP_TEXT_DESACTIVATED    = 100007,
+    GOSSIP_TEXT_NOT_GM          = 100008,
+    GOSSIP_TEXT_ALREADY_QG      = 100009,
+    GOSSIP_TEXT_NO_MONEY        = 100010,
+    GOSSIP_TEXT_NO_TEMPLATE     = 100011,
+    GOSSIP_TEXT_NO_PHASE        = 100012,
+    GOSSIP_TEXT_TP_ERROR        = 100013,
+    GOSSIP_TEXT_NO_GUILD        = 100014
+};
+
+enum Qg_Gossip_Senders
+{
+    GOSSIP_SENDER_LIST          = 1,
+    GOSSIP_SENDER_BUY           = 2,
+    GOSSIP_SENDER_BUY_CONFIRM   = 3,
+    GOSSIP_SENDER_TELEPORT      = 4,
+    GOSSIP_SENDER_SELL          = 5
+};
+
+enum Qg_Gossip_Actions
+{
+    GOSSIP_ACTION_FIRST         = 1,
+    GOSSIP_ACTION_CONFIRM       = 2
+};
+
+class npc_guild_qg : public CreatureScript
+{
+public:
+    npc_guild_qg() : CreatureScript("npc_guild_qg") { }
+
+    bool OnGossipHello(Player* pPlayer, Creature* pCreature)
+    {
+        Guild* pGuild = sGuildMgr->GetGuildById(pPlayer->GetGuildId());
+
+        if (!pGuild)
+        {
+            pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_NO_GUILD, pCreature->GetGUID());
+            return true;
+        }
+        
+        bool IsPlayerGuildMaster = (pGuild->GetLeaderGUID() == pPlayer->GetGUID());
+        bool IsQgActive = pGuild->pGuildQG->IsQGActive();
+
+        /* TODO : add a configuration in .conf
+        if(!sWorld->getBoolConfig(CONFIG_GUILD_QG_SYSTEM))
+        {
+            pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_DESACTIVATED, pCreature->GetGUID());
+            return false;
+        }*/
+
+        if(IsPlayerGuildMaster)
+        {
+            if(!IsQgActive) // If can buy
+            {
+                pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BUY, GOSSIP_SENDER_LIST, GOSSIP_ACTION_FIRST);
+                pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_WELCOME_GM, pCreature->GetGUID());
+            }
+            else
+            {
+                pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TELEPORT,  GOSSIP_SENDER_TELEPORT, GOSSIP_ACTION_FIRST);
+                pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SELL,      GOSSIP_SENDER_SELL,     GOSSIP_ACTION_FIRST);
+                pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_GM, pCreature->GetGUID());
+            }
+        }
+        else
+        {
+            if(!IsQgActive)
+            {
+                pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_NOT_GM, pCreature->GetGUID());
+            }
+            else
+            {
+                pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_TELEPORT,  GOSSIP_SENDER_TELEPORT, GOSSIP_ACTION_FIRST);
+                pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_MEMBER, pCreature->GetGUID());
+            }
+        }
+        
+        return true;
+    }
+
+    bool OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+    {
+        pPlayer->PlayerTalkClass->ClearMenus();
+
+        Guild* pGuild = sGuildMgr->GetGuildById(pPlayer->GetGuildId());
+        TypeQGTemplateList QGsTemplateList = sQGMgr->GetQGsTemplateList();
+
+        if (!pGuild || QGsTemplateList.empty())
+            return false;
+
+        switch(uiSender)
+        {
+            case GOSSIP_SENDER_LIST: // Send QG list to player
+            {
+                for(TypeQGTemplateList::iterator Itr = QGsTemplateList.begin(); Itr != QGsTemplateList.end(); ++Itr)
+                    pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, (*Itr).m_name,  GOSSIP_SENDER_BUY_CONFIRM, (*Itr).m_id);
+                pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_LIST, pCreature->GetGUID());
+                break;
+            }
+            case GOSSIP_SENDER_BUY_CONFIRM: // Ask confirm to buy
+            {
+                pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CONFIRM, GOSSIP_SENDER_BUY, uiAction);
+                pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_CONFIRM, pCreature->GetGUID());
+                break;
+            }
+            case GOSSIP_SENDER_BUY: // Buy QG or send errors
+            {
+                switch(pGuild->pGuildQG->BuyGuildQG(pPlayer, uiAction))
+                {
+                    case OK:
+                        pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_OK, pCreature->GetGUID());
+                        break;
+                    case QG_SYSTEM_DESACTIVATED:
+                        pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_DESACTIVATED, pCreature->GetGUID());
+                        break;
+                    case NOT_GUILD_MASTER:
+                        pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_NOT_GM, pCreature->GetGUID());
+                        break;
+                    case ALREADY_HAVE_QG:
+                        pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_ALREADY_QG, pCreature->GetGUID());
+                        break;
+                    case NOT_ENOUGH_MONEY:
+                        pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_NO_MONEY, pCreature->GetGUID());
+                        break;
+                    case NO_QG_TEMPLATE:
+                        pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_NO_TEMPLATE, pCreature->GetGUID());
+                        break;
+                    case NO_DISPONIBLE_PHASE:
+                        pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_NO_PHASE, pCreature->GetGUID());
+                        break;
+                }
+                break;
+            }
+            case GOSSIP_SENDER_SELL:
+            {
+                switch(uiAction)
+                {
+                    case GOSSIP_ACTION_FIRST: // Ask for confirmation
+                        pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CONFIRM, GOSSIP_SENDER_SELL, GOSSIP_ACTION_CONFIRM);
+                        pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_CONFIRM, pCreature->GetGUID());
+                        break;
+                    case GOSSIP_ACTION_CONFIRM: // Sell QG
+                        if(pGuild->pGuildQG->SellGuildQG(pPlayer) != OK)
+                            pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_NOT_GM, pCreature->GetGUID());
+                        else
+                            pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_OK, pCreature->GetGUID());
+                        break;
+                }
+                break;
+            }
+            case GOSSIP_SENDER_TELEPORT:
+            {
+                switch(uiAction)
+                {
+                    case GOSSIP_ACTION_FIRST: // Ask for confirmation
+                        pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CONFIRM, GOSSIP_SENDER_TELEPORT, GOSSIP_ACTION_CONFIRM);
+                        pPlayer->PlayerTalkClass->SendGossipMenu(GOSSIP_TEXT_CONFIRM, pCreature->GetGUID());
+                        break;
+                    case GOSSIP_ACTION_CONFIRM: // Teleport Player
+                        pGuild->pGuildQG->TeleportPlayerToQG(pPlayer);
+                        pPlayer->PlayerTalkClass->SendCloseGossip();
+                        break;
+                }
+                break;
+            }
+        }
+        return true;
+    }
+};
+
+bool AddQGNpc(uint32 entry, Player * pPlayer)
+{
+    float x = pPlayer->GetPositionX();
+    float y = pPlayer->GetPositionY();
+    float z = pPlayer->GetPositionZ();
+    float o = pPlayer->GetOrientation();
+    Map *map = pPlayer->GetMap();
+
+    Creature* creature = new Creature;
+    if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), map, pPlayer->GetPhaseMaskForSpawn(), entry, 0, 0, x, y, z, o))
+    {
+        delete creature;
+        return false;
+    }
+
+    creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), pPlayer->GetPhaseMaskForSpawn());
+
+    uint32 db_guid = creature->GetDBTableGUIDLow();
+
+    // To call _LoadGoods(); _LoadQuests(); CreateTrainerSpells();
+    creature->LoadFromDB(db_guid, map);
+
+    map->Add(creature);
+    sObjectMgr->AddCreatureToGrid(db_guid, sObjectMgr->GetCreatureData(db_guid));
+    return true;
+}
+
+bool AddQGGameObjects(uint32 entry, Player * pPlayer)
+{
+    float x = pPlayer->GetPositionX();
+    float y = pPlayer->GetPositionY();
+    float z = pPlayer->GetPositionZ();
+    float o = pPlayer->GetOrientation();
+    Map *map = pPlayer->GetMap();
+
+    const GameObjectTemplate *gInfo = sObjectMgr->GetGameObjectTemplate(entry);
+
+    if (!gInfo)
+        return false;
+
+    if (gInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(gInfo->displayId))
+        return false;
+
+    GameObject* pGameObj = new GameObject;
+    uint32 db_lowGUID = sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT);
+
+    if (!pGameObj->Create(db_lowGUID, gInfo->entry, map, pPlayer->GetPhaseMaskForSpawn(), x, y, z, o, 0.0f, 0.0f, 0.0f, 0.0f, 0, GO_STATE_READY))
+    {
+        delete pGameObj;
+        return false;
+    }
+
+    // fill the gameobject data and save to the db
+    pGameObj->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), pPlayer->GetPhaseMaskForSpawn());
+
+    // this will generate a new guid if the object is in an instance
+    if (!pGameObj->LoadFromDB(db_lowGUID, map))
+    {
+        delete pGameObj;
+        return false;
+    }
+
+    map->Add(pGameObj);
+
+    return true;
+}
+
+/*#####
+# item_guild_spawner
+#####*/
+
+class item_guild_spawner : public ItemScript
+{
+public:
+    item_guild_spawner() : ItemScript("item_guild_spawner") { }
+
+    bool OnUse(Player* pPlayer, Item* pItem, SpellCastTargets const& /*targets*/)
+    {
+        if(!pPlayer->pPlayerQG->IsInQG())
+            return false;
+
+        Add_Type type = TYPE_OBJECT;
+        TypeAddList AddList = sQGMgr->GetGobAddList();
+        
+        if(!AddList[pItem->GetEntry()]) // No Gob entry, maybe a NPC spawner
+        {
+            AddList = sQGMgr->GetNpcAddList();
+            Add_Type type = TYPE_NPC;
+                
+            if(!AddList[pItem->GetEntry()]) // No npc entry : error
+                return false;
+        }
+        
+        uint32 count = 1;
+        uint32 AddId = 0;
+
+        AddId = AddList[pItem->GetEntry()];
+
+        switch(type)
+        {
+            case TYPE_OBJECT:
+            {
+                if(AddQGGameObjects(AddId, pPlayer))
+                    pPlayer->DestroyItemCount(pItem, count, true);
+                else
+                    return false;
+
+                break;
+            }
+            case TYPE_NPC:
+            {
+                if(AddQGNpc(AddId, pPlayer))
+                    pPlayer->DestroyItemCount(pItem, count, true);
+                else
+                    return false;
+
+                break;
+            }
+        }
+
+        return true;
+    }
+};
+
+void AddSC_npc_guild_qg()
+{
+    new npc_guild_qg;
+    new item_guild_spawner;
+}
--
1.7.4.msysgit.0
J'ai voulu tester la chose en compilant les sources dans le repo, tout s'passe bien (mise à part les .sql, des oublies de virgules, rien de méchants), une fois en jeux, le PJN sait bien voir si je suis le GM ou si j'ai une Guild, mais j'ai beau cliquer pour vouloir acheter un QG, rien ne s'passe, j'ai raté un truc ? Langue

Retourner en haut Accueil