Location de Qg de guilde
J'ai crée ce patch à partir du patch proposé par spgm sur trinity.
J'ai ensuite modifié le code pour avoir un système de location de Qg de guilde.
Le maitre de guilde achète son Qg de guilde contre des items du jeu. Le temps de location est configurable.

Le scriptname du pnj doit être ajouté dans la table creature_template et ajouté en jeu.

src\server\scripts\Custom\guildmaster.cpp
[code=cpp]#include "ScriptPCH.h"

#define MSG_GOSSIP_TELE "Se teleporter dans son qg de guilde"
#define MSG_GOSSIP_BUY "Acheter un Qg de guilde"
#define MSG_GOSSIP_NEXTPAGE "Next -->"
#define MSG_INCOMBAT "Vous etes en combat, vous ne pouvez pas etre teleporte dans votre Qg de guilde."
#define MSG_NOGUILDHOUSE "Votre guilde n'a pas encore de Qg de guilde."
#define MSG_NOFREEGH "Pas de chance! Tout les Qg de guilde sont pris."
#define MSG_ALREADYHAVEGH "Desole mais vous avez deja un Qg de guilde (%s)."
#define MSG_NOTENOUGHMONEY "Vous n'avez pas assez d'items pour louer un Qg de guilde."
#define MSG_GHOCCUPIED "Le Qg de guilde est deja pris par une autre guilde."
#define MSG_CONGRATULATIONS "Felicitation! Vous pouvez maintenant vous teleporter dans votre Qg."
#define MSG_NOTINGUILD "Vous devez etre dans une guilde pour pouvoir louer un Qg."
#define MSG_ERROR_PRIX "Une erreur est survenu (prix), merci de faire une requete a un mj."
#define MSG_ERROR_IDITEM "Une erreur est survenu (id item), merci de faire une requete a un mj."
#define IDMenuNpcGuild1 122300
#define IDMenuNpcGuild2 122301
#define MSG_NOT_ENABLE "Au revoir!."
#define MSG_GOSSIP_NOT_ENABLE "A bientot!"

#define OFFSET_GH_ID_TO_ACTION 1500
#define OFFSET_SHOWBUY_FROM 10000

#define ACTION_TELE 1001
#define ACTION_SHOW_BUYLIST 1002 //deprecated. Use (OFFSET_SHOWBUY_FROM + 0) instead
#define NOT_ENABLE 1004

#define ICON_GOSSIP_BALOON 0
#define ICON_GOSSIP_WING 2
#define ICON_GOSSIP_BOOK 3
#define ICON_GOSSIP_WHEEL1 4
#define ICON_GOSSIP_WHEEL2 5
#define ICON_GOSSIP_GOLD 6
#define ICON_GOSSIP_BALOONDOTS 7
#define ICON_GOSSIP_TABARD 8
#define ICON_GOSSIP_XSWORDS 9

#define GOSSIP_COUNT_MAX 10

class guildmaster : public CreatureScript
{
public:

guildmaster()
: CreatureScript("guildmaster")
{
}
bool isPlayerGuildLeader(Player *player)
{
return (player->GetRank() == 0) && (player->GetGuildId() != 0);
}

bool getGuildHouseCoords(uint32 guildId, float &x, float &y, float &z, uint32 &map)
{
if (guildId == 0)
{
//if player has no guild
return false;
}

QueryResult result;
result = LoginDatabase.PQuery("SELECT `x`, `y`, `z`, `map` FROM `guildhouses` WHERE `guildId` = %u", guildId);
if (result)
{
Field *fields = result->Fetch();
x = fields[0].GetFloat();
y = fields[1].GetFloat();
z = fields[2].GetFloat();
map = fields[3].GetUInt32();
return true;
}
return false;
}

void teleportPlayerToGuildHouse(Player *player, Creature *_creature)
{
if (player->GetGuildId() == 0)
{
//if player has no guild
_creature->MonsterWhisper(MSG_NOTINGUILD, player->GetGUID());
return;
}

if (!player->getAttackers().empty())
{
//if player in combat
_creature->MonsterSay(MSG_INCOMBAT, LANG_UNIVERSAL, player->GetGUID());
return;
}

float x, y, z;
uint32 map;

if (getGuildHouseCoords(player->GetGuildId(), x, y, z, map))
{
//teleport player to the specified location
player->TeleportTo(map, x, y, z, 0.0f);
}
else
_creature->MonsterWhisper(MSG_NOGUILDHOUSE, player->GetGUID());

}

bool showBuyList(Player *player, Creature *_creature, uint32 showFromId = 0)
{
//show not occupied guildhouses

QueryResult result;
result = LoginDatabase.PQuery("SELECT `id`, `comment` FROM `guildhouses` WHERE `guildId` = 0 AND `id` > %u ORDER BY `id` ASC LIMIT %u",
showFromId, GOSSIP_COUNT_MAX);

if (result)
{
uint32 guildhouseId = 0;
std::string comment = "";
do
{

Field *fields = result->Fetch();

guildhouseId = fields[0].GetInt32();
comment = fields[1].GetString();

//send comment as a gossip item
//transmit guildhouseId in Action variable
player->ADD_GOSSIP_ITEM(ICON_GOSSIP_TABARD, comment, GOSSIP_SENDER_MAIN,
guildhouseId + OFFSET_GH_ID_TO_ACTION);

}while (result->NextRow());

if (result->GetRowCount() == GOSSIP_COUNT_MAX)
{
//assume that we have additional page
//add link to next GOSSIP_COUNT_MAX items
player->ADD_GOSSIP_ITEM(ICON_GOSSIP_BALOONDOTS, MSG_GOSSIP_NEXTPAGE, GOSSIP_SENDER_MAIN,
guildhouseId + OFFSET_SHOWBUY_FROM);
}


player->PlayerTalkClass->SendGossipMenu(DEFAULT_GOSSIP_MESSAGE, _creature->GetGUID());

return true;
}
else
{
if (showFromId = 0)
{
//all guildhouses are occupied
_creature->MonsterWhisper(MSG_NOFREEGH, player->GetGUID());
player->CLOSE_GOSSIP_MENU();
}
else
{
//this condition occurs when COUNT(guildhouses) % GOSSIP_COUNT_MAX == 0
//just show GHs from beginning
showBuyList(player, _creature, 0);
}
}

return false;
}

void buyGuildhouse(Player *player, Creature *_creature, uint32 guildhouseId)
{
uint32 iditem1 = 0;
uint32 iditem2 = 0;
uint32 nbr1 = 0;
uint32 nbr2 = 0;
uint32 duration_secs = 0;
std::string config = "7d";
duration_secs = TimeStringToSecs(config);

QueryResult result = LoginDatabase.PQuery("SELECT iditempvp, iditempve, prixpvp, prixpve FROM guildhouses WHERE id = %u", guildhouseId);
if (!result)
{
_creature->MonsterWhisper(MSG_ERROR_PRIX, player->GetGUID());
return;
}
else
{
do
{
Field *fields = result->Fetch();
iditem2 = fields[0].GetInt32();
iditem1 = fields[1].GetInt32();
nbr2 = fields[2].GetInt32();
nbr1 = fields[3].GetInt32();
}while(result->NextRow());
}

if (iditem2 == 0 || iditem1 == 0)
{
_creature->MonsterWhisper(MSG_ERROR_IDITEM, player->GetGUID());
return;
}

if (!player->HasItemCount(iditem1, nbr1) || !player->HasItemCount(iditem2, nbr2))
{
_creature->MonsterWhisper(MSG_NOTENOUGHMONEY, player->GetGUID());
return;
}

result = LoginDatabase.PQuery("SELECT `comment` FROM `guildhouses` WHERE `guildId` = %u",
player->GetGuildId());

if (result)
{
//whisper to player "already have etc..."
Field *fields = result->Fetch();
char msg[100];
sprintf(msg, MSG_ALREADYHAVEGH, fields[0].GetString());
_creature->MonsterWhisper(msg, player->GetGUID());
return;
}

//check if somebody already occupied this GH
result = LoginDatabase.PQuery("SELECT `id` FROM `guildhouses` WHERE `id` = %u AND `guildId` <> 0", guildhouseId);

if (result)
{
_creature->MonsterWhisper(MSG_GHOCCUPIED, player->GetGUID());
return;
}

//update DB
LoginDatabase.PQuery("UPDATE `guildhouses` SET `guildId` = %u, setdate = UNIX_TIMESTAMP(), unsetdate = UNIX_TIMESTAMP()+%u WHERE `id` = %u", player->GetGuildId(), duration_secs, guildhouseId);

player->DestroyItemCount(iditem1, nbr1, true);
player->DestroyItemCount(iditem2, nbr2, true);

_creature->MonsterSay(MSG_CONGRATULATIONS, LANG_UNIVERSAL, player->GetGUID());

}

bool OnGossipHello(Player *player, Creature *_creature)
{
if (!sWorld.getBoolConfig(CONFIG_QG_NOT_ENABLE))
{
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, MSG_GOSSIP_NOT_ENABLE, GOSSIP_SENDER_MAIN, NOT_ENABLE);
player->PlayerTalkClass->SendGossipMenu(IDMenuNpcGuild1, _creature->GetGUID());
return true;
}
player->ADD_GOSSIP_ITEM(ICON_GOSSIP_BALOON, MSG_GOSSIP_TELE,
GOSSIP_SENDER_MAIN, ACTION_TELE);

if (isPlayerGuildLeader(player))
{
//show additional menu for guild leader
player->ADD_GOSSIP_ITEM(ICON_GOSSIP_GOLD, MSG_GOSSIP_BUY,
GOSSIP_SENDER_MAIN, ACTION_SHOW_BUYLIST);
}
player->PlayerTalkClass->SendGossipMenu(IDMenuNpcGuild2, _creature->GetGUID());
return true;
}


bool OnGossipSelect(Player *player, Creature *Creature, uint32 sender, uint32 action)
{
player->PlayerTalkClass->ClearMenus();
if (sender != GOSSIP_SENDER_MAIN)
return false;

switch (action)
{
case NOT_ENABLE:
player->CLOSE_GOSSIP_MENU();
Creature->MonsterWhisper(MSG_NOT_ENABLE, player->GetGUID());
break;
case ACTION_TELE:
//teleport player to GH

player->CLOSE_GOSSIP_MENU();
teleportPlayerToGuildHouse(player, Creature);
break;
case ACTION_SHOW_BUYLIST:
//show list of GHs which currently not occupied
showBuyList(player, Creature);
break;
default:
if (action > OFFSET_SHOWBUY_FROM)
{
showBuyList(player, Creature, action - OFFSET_SHOWBUY_FROM);
}
else if (action > OFFSET_GH_ID_TO_ACTION)
{
//player clicked on buy list
player->CLOSE_GOSSIP_MENU();
//get guildhouseId from action
//guildhouseId = action - OFFSET_GH_ID_TO_ACTION
buyGuildhouse(player, Creature, action - OFFSET_GH_ID_TO_ACTION);
}
break;
}

return true;
}
};

void AddSC_guildmaster()
{
new guildmaster();
}[/code]

Après il faut ajouter le fichier à la compilation dans le cmakefile et le script dans scriptloader.

src\server\game\World\World.cpp
[code=diff]m_int_configs[CONFIG_AUTOBROADCAST_CENTER] = sConfig.GetIntDefault("AutoBroadcast.Center", 0);
m_int_configs[CONFIG_AUTOBROADCAST_INTERVAL] = sConfig.GetIntDefault("AutoBroadcast.Timer", 60000);
+// Qg de guilde
+m_bool_configs[CONFIG_QG_NOT_ENABLE] = sConfig.GetBoolDefault("QG.Enable", false);[/code]

src\server\game\World\World.h
[code=diff]CONFIG_DUNGEON_FINDER_ENABLE,
CONFIG_AUTOBROADCAST,
+// Qg de guilde
+CONFIG_QG_NOT_ENABLE,[/code]

src\server\authserver\Server\AuthSocket.cpp
[code=diff]
LoginDatabase.Execute(
LoginDatabase.GetPreparedStatement(LOGIN_SET_EXPIREDACCBANS)​
);
+LoginDatabase.Execute(
+ +LoginDatabase.GetPreparedStatement(LOGIN_SET_EXPIREDACCGH)
+ );
[/code]

src\server\shared\Database\Implementation\LoginDatabase.cpp
[code=diff]PrepareStatement(LOGIN_SET_EXPIREDACCBANS, "UPDATE account_banned SET active = 0 WHERE unbandate<=UNIX_TIMESTAMP() AND unbandate<>bandate");
+PrepareStatement(LOGIN_SET_EXPIREDACCGH, "UPDATE guildhouses SET guildId = 0 WHERE unsetdate<=UNIX_TIMESTAMP() AND unsetdate<>setdate");[/code]

src\server\shared\Database\Implementation\LoginDatabase.h
[code=diff]LOGIN_SET_EXPIREDACCBANS,
+LOGIN_SET_EXPIREDACCGH,[/code]

src\server\worldserver\worldserver.conf.dist
[code=diff]
CharDelete.Method = 0
CharDelete.MinLevel = 0
CharDelete.KeepDays = 30

+###########################################################​####################
+# QG DE GUILDE
+#
+# QG.Enable
+# Active le système de Qg de guilde
+# Default: 0 - off
+# 1 - on
+#
+###########################################################​####################
+
+QG.Enable = 0[/code]

Voici le fichier sql
[code=sql]-- Login database
-- création de la table guildhouse
DROP TABLE IF EXISTS `guildhouses`;
CREATE TABLE IF NOT EXISTS `guildhouses` (
`id` int(8) unsigned NOT NULL auto_increment,
`guildId` bigint(40) NOT NULL default '0',
`x` double NOT NULL,
`y` double NOT NULL,
`z` double NOT NULL,
`setdate` bigint(40) NOT NULL default '0',
`unsetdate` bigint(40) NOT NULL default '0',
`map` int(11) NOT NULL,
`iditempvp` bigint(40) NOT NULL default '0',
`iditempve` bigint(40) NOT NULL default '0',
`prixpvp` bigint(40) NOT NULL default '0',
`prixpve` bigint(40) NOT NULL default '0',
`comment` varchar(255) NOT NULL default '',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=42 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

-- ajout des différents qg de guilde
INSERT INTO `guildhouses` VALUES ('1', '0', '16222', '16266', '14.2', '0', '0', '1', '0', '0', '0', '0', 'GM Island');
INSERT INTO `guildhouses` VALUES ('2', '0', '-10711', '2483', '8', '0', '0', '1', '0', '0', '0', '0', 'Tauren village at Veiled Sea (Silithus)');
INSERT INTO `guildhouses` VALUES ('3', '0', '-8323', '-343', '146', '0', '0', '0', '0', '0', '0', '0', 'Fishing outside an Northshire Abbey (Elwynn Forest');
INSERT INTO `guildhouses` VALUES ('4', '0', '7368', '-1560', '163', '0', '0', '1', '0', '0', '0', '0', 'Troll Village in mountains (Darkshore)');
INSERT INTO `guildhouses` VALUES ('5', '0', '-4151', '-1400', '198', '0', '0', '0', '0', '0', '0', '0', 'Dwarven village outside Ironforge (Wetlands)');
INSERT INTO `guildhouses` VALUES ('6', '0', '-1840', '-4233', '2.14', '0', '0', '0', '0', '0', '0', '0', 'Dwarven village (Arathi Highlands, Forbidding Sea)');
INSERT INTO `guildhouses` VALUES ('8', '0', '-723', '-1076', '179', '0', '0', '1', '0', '0', '0', '0', 'Tauren camp (Mulgore, Red Rock)');
INSERT INTO `guildhouses` VALUES ('9', '0', '-206', '1666', '80', '0', '0', '0', '0', '0', '0', '0', 'Shadowfang Keep an outside instance (Silverpine Forest)');
INSERT INTO `guildhouses` VALUES ('10', '0', '-6374', '1262', '7', '0', '0', '0', '0', '0', '0', '0', 'Harbor house outside Stormwind (Elwynn Forest)');
INSERT INTO `guildhouses` VALUES ('11', '0', '-8640', '580', '96', '0', '0', '0', '0', '0', '0', '0', 'Empty jail between canals (Stormwind) DELETE');
INSERT INTO `guildhouses` VALUES ('12', '0', '-4844', '-1066', '502', '0', '0', '0', '0', '0', '0', '0', 'Old Ironforge');
INSERT INTO `guildhouses` VALUES ('13', '0', '-4863', '-1658', '503.5', '0', '0', '0', '0', '0', '0', '0', 'Ironforge Airport');
INSERT INTO `guildhouses` VALUES ('14', '0', '1146', '-165', '313', '0', '0', '37', '0', '0', '0', '0', 'Azshara Crater instance (Alliance entrance)');
INSERT INTO `guildhouses` VALUES ('15', '0', '-123', '858', '298', '0', '0', '37', '0', '0', '0', '0', 'Azshara Crater instance (Horde entrance)');
INSERT INTO `guildhouses` VALUES ('16', '0', '4303', '-2760', '16.8', '0', '0', '0', '0', '0', '0', '0', 'Quel\'Thalas Tower');
INSERT INTO `guildhouses` VALUES ('17', '0', '-6161', '-790', '423', '0', '0', '0', '0', '0', '0', '0', 'Crashed gnome airplane (between Dun Morogh and Searing Gorge)');
INSERT INTO `guildhouses` VALUES ('18', '0', '-11790', '-1640', '54.7', '0', '0', '0', '0', '0', '0', '0', 'Zul\'Gurub an outside instance (Stranglethorn Vale)');
INSERT INTO `guildhouses` VALUES ('19', '0', '-11805', '-4754', '6', '0', '0', '1', '0', '0', '0', '0', 'Goblin village (Tanaris, South Seas)');
INSERT INTO `guildhouses` VALUES ('20', '0', '-9296', '670', '132', '0', '0', '0', '0', '0', '0', '0', 'Villains camp outside an Stormwind (Elwynn Forest)');
INSERT INTO `guildhouses` VALUES ('21', '0', '3414', '-3380', '142.2', '0', '0', '0', '0', '0', '0', '0', 'Stratholm an outside instance');
INSERT INTO `guildhouses` VALUES ('22', '0', '4654', '-3772', '944', '0', '0', '1', '0', '0', '0', '0', 'Kalimdor Hyjal (Aka World Tree)');
INSERT INTO `guildhouses` VALUES ('23', '0', '2176', '-4766', '55', '0', '0', '1', '0', '0', '0', '0', 'The Ring of Valor (Aka. Orgrimmar Arena)');
INSERT INTO `guildhouses` VALUES ('24', '0', '1951.512085', '1530.475586', '247.288147', '0', '0', '1', '0', '0', '0', '0', 'Stonetalon Logging Camp');
INSERT INTO `guildhouses` VALUES ('25', '0', '2813.660645', '2248.552979', '215.524643', '0', '0', '1', '0', '0', '0', '0', 'Stonetalon Ruins');
INSERT INTO `guildhouses` VALUES ('28', '0', '9725.27', '-21.43', '20.03', '0', '0', '1', '0', '0', '0', '0', 'Teldrassil Furbold camp');
INSERT INTO `guildhouses` VALUES ('29', '0', '-3855', '-3479', '579', '0', '0', '0', '0', '0', '0', '0', 'Wetlands mountain camp');
INSERT INTO `guildhouses` VALUES ('30', '0', '-5362', '-2540', '485', '0', '0', '0', '0', '0', '0', '0', 'Ortell\'s Hideout');
INSERT INTO `guildhouses` VALUES ('31', '0', '-12865', '-1396', '115', '0', '0', '0', '0', '0', '0', '0', 'Stranglethorn Secret Cave');
INSERT INTO `guildhouses` VALUES ('32', '0', '-11073', '-1956', '39', '0', '0', '0', '0', '0', '0', '0', 'Karazhan Smiley');
INSERT INTO `guildhouses` VALUES ('33', '0', '-11084', '-1801', '53', '0', '0', '0', '0', '0', '0', '0', 'Well of the Forgotten (Aka. Karazhan Crypt or Lower Karazhan)');
INSERT INTO `guildhouses` VALUES ('34', '0', '1683.235474', '286.458801', '-45.451775', '0', '0', '0', '0', '0', '0', '0', 'Undercity Top Tier');
INSERT INTO `guildhouses` VALUES ('35', '0', '-8521.3', '599.5', '101.399338', '0', '0', '0', '0', '0', '0', '0', 'Stormwind Cut-Throat Alley');
INSERT INTO `guildhouses` VALUES ('36', '0', '-5933', '452', '509', '0', '0', '0', '0', '0', '0', '0', 'Forgotten gnome camp');
INSERT INTO `guildhouses` VALUES ('37', '0', '-920.231323', '7096.489258', '170.35289', '0', '0', '530', '0', '0', '0', '0', 'Outland Nagrand : Newton\'s Remains');
INSERT INTO `guildhouses` VALUES ('38', '0', '-2140.501953', '9142.6875', '137.041855', '0', '0', '530', '0', '0', '0', '0', 'Outland Nagrand : Tomb');
INSERT INTO `guildhouses` VALUES ('39', '0', '-483.401794', '7461.944824', '186.120987', '0', '0', '530', '0', '0', '0', '0', 'Outland Nagrand: Challe\'s Home for Little Tykes');
INSERT INTO `guildhouses` VALUES ('40', '0', '2387.753906', '3191.757324', '152.669388', '0', '0', '530', '0', '0', '0', '0', 'Outland Netherstorm: Nova\'s Shrine');[/code]

Les différents Qg sont des exemples et peuvent être changé.

Voila je crois n'avoir rien oublié
Merci du Partage !
Du bon taff math, GG
Merci beaucoup, je l'utiliserais, quand je saurais compiler Smile
merci beaucoup
Merci beaucoup math !!!
Merci beaucoup !

Tu n'as pas une idee pour des gardes de guilde ? J'ai fait un post sur le forum trinitycore car j'avais un problème avec mon script et pas de soutien :/
slt merci
Hello,
Merci déjà pour ce patch! ensuite je l'ais tester sur mon serveur test mais le vendeur ne me propose rien, pourrait-tu nous mettres le npc en question ?
Luminos
Bonjour a tous,
J'ai un petit problème, j'ai suivis la procédure mais je n'arrive plus à redémarrer le core trinity du serveur, pouvait vous m'aider?
ps: je n'ai pas compris
"Après il faut ajouter le fichier à la compilation dans le cmakefile et le script dans scriptloader."

Merci à vous.

Retourner en haut Accueil