Fix build, sql and crashes - NPC's and GO's load on purchase (#30)

* Add files via upload

* Add files via upload

* fix %u in queries

* fix name

* Add files via upload

Update from local work

* Delete loader.h

* Update Creatures.sql

Missed two NPC's
Added Innkeeper and DK Trainer with edited columns to update old sql

* Delete CMakeLists.txt

* Cleanup Code and remove broken work

* Update README.md

* FInal Cleanup 

Updated sql queries to add NPC's and creatures. Reworked layout for current AC databases
Fixed code to solve build errors
fixed code to solve core crash on object spawn (StarterPortal etc)
With core updates creatures now load scripts on manual summon - Thanks!
Added new chat commands for teleport ".gh tele" and NPC Assistant ".gh butler"
GameObjects now spawn on purchase - no core restart required


Issues still remaining:
NPC assistant is present at GH creation but is gone after core restart. Can be summoned with chat command and he
stays in place after chat command summon.

* Updated to use unique NPCs and to make the ammo & repairs vendor consistent.

* Updated all of the Portal ids and moved code check in SpawnObject to make it consistent with SpawnNPC.

* Refactored to use existing 'map' variable.

* Updated to include new shortened command.

* Updated to match the return type.

* Fixed usage of 'map' variable.

* Fixed various typos and updated to be more consistent in messaging.

* Fixed commented out calls.

* Updated to create all new Portal objects.

* Updated command shortcut message.

* Updated NPC ids to be consistent with the new Portal ids.

* Updated to fix vendor positioning.

* Fixed SQL to include new NPC ids.

* Updated to use existing NPC for Food & Drink Vendor.

* Updated to reflect moved custom NPC.

* Adjusted vendor positioning.

* Rearranged various vendors.

* Adjusted Tabard Vendor position.

* Updated tailoring trainer.

* Updated herbalism trainer.

* Updated blacksmithing and alchemy trainers.

* Updated engineering trainer.

* Updated first aid trainer.

* Updated cooking trainer.

* Updated fishing trainer.

* Updated mining trainer.

* Updated enchanting trainer and added support for both factions.

* Updated jewelcrafting and inscription trainers and added support for both factions.

* Updated leatherworking trainer.

* Updated skinner trainer.

* Updated alchemy trainer to a master trainer.

* Hide the Ammo & Repair Vendor since it's broken anyway.

* Hide Spirit Healer since that's broken anyway.

* Update Creatures.sql

Mistakenly removed column names

* Added Neutral Auctioneer.

* Revert "Hide Spirit Healer since that's broken anyway."

This reverts commit dee436787cf39cad055bbda36b2a9e874295aca1.

* Updated Innkeeper position.

* Updated Banker position.

* Replaced curly braces.

* Updated menus.

* Added Poisons Vendor.

* Update Creatures.sql

Old Column Names Snuck back in.
Fixed

* Fixed Ammo & Repair Vendor.

* Updated to use existing Death Knight Trainer.

* Fixed SQL error.

* Updated method to be more descriptive.

* Updated to allow anyone to purchase by default but only allow Guild Master to sell.

* Fixed command typo in README.md.

* Removed the V2 designation.

* Updated filenames to be consistent.

* Changed assistant to butler to match the new command.

* Updated to fix compile error.

* Updated again to fix compile error.

* Renamed configuration file to match the rest of the module.

* Updated so that the sell guild house menu is displayed if the permission requirement is met instead of requiring guild master.

* Code cleanup and added test code.

* Tweaked test code.

* Tweaked test code.

* Removed test code.

* Fixed sell guild house permission check.

* Updated to fix deprecation warnings.

* Added required using.

* Removed parameters that were not used anyway.

* Updated to fix parameters.

* Cleaned up SQL queries.

* Updated to include orientation for the Guild House maps, this fixes teleporting there and facing weird directions.

* Updated portal locations.

* Fixed starter portal locations.

* Fixed portal locations.

* Updated files to match new command.

* Delete Creatures.sql

* Update README.md

* chore: add npcflag 1 by default

* Update mod_guildhouse_butler.cpp

* add overrides to fix warnings

Co-authored-by: Bogir[rus] <m-1@bk.ru>
Co-authored-by: SoulSeekkor <soulseekkor@live.com>
Co-authored-by: Helias <stefanoborzi32@gmail.com>
This commit is contained in:
Greg Wilkinson
2022-04-04 02:49:40 -05:00
committed by GitHub
parent 127183d414
commit 48b936227a
14 changed files with 1069 additions and 1002 deletions

View File

@@ -1,7 +0,0 @@
AC_ADD_SCRIPT("${CMAKE_CURRENT_LIST_DIR}/src/mod_guild_house_v2.cpp")
AC_ADD_SCRIPT("${CMAKE_CURRENT_LIST_DIR}/src/mod_guild_house_npc.cpp")
AC_ADD_SCRIPT_LOADER("GuildHouseV2" "${CMAKE_CURRENT_LIST_DIR}/src/loader.h")
AC_ADD_SCRIPT_LOADER("GuildHouseV2NPC" "${CMAKE_CURRENT_LIST_DIR}/src/loader.h")
AC_ADD_CONFIG_FILE("${CMAKE_CURRENT_LIST_DIR}/conf/mod_guild_house_v2.conf.dist")

View File

@@ -5,7 +5,7 @@
## Important notes
You have to use at least AzerothCore commit [8f5c628](https://github.com/azerothcore/azerothcore-wotlk/commit/8f5c628836f7446d8d876bee7f5bdff5a35aaa2f).
You have to use at least AzerothCore commit [77f1363](https://github.com/azerothcore/azerothcore-wotlk/commit/77f13636b75f9b25fc1290e297cd002e7df3c89b).
## Description
@@ -26,19 +26,16 @@ All guilds will get their own phasing system and then the guild master can purch
## How to use ingame
1) After installation, as GM you will need to: `.npc add 70101` -> somewhere public and accessible by other players.
2) Players can purchase a guild house from the added NPC, then either teleport to the guildhouse via the NPC or chat: `.guildhouse tele`
1) After installation, as GM you will need to: `.npc add 500030` -> somewhere public and accessible by other players.
2) Players can purchase a guild house from the added NPC, then either teleport to the guildhouse via the NPC or chat: `.guildhouse tele` or `.gh tele`
3) Each new Guild House starts with a portal to either Orgrimmar or Stormwind, based on Team (ALLIANCE / HORDE), and the Guild House Assistant.
4) Speak with the Guild House Assistant to begin purchasing additions to your Guild House!
## Requirements
- AzerothCore v1.0.1+
5) Players in guild with proper rank will be able to spawn the Assistant with chat commands `.guildhouse butler` or `.gh butler`
## Installation
```
1) Place the module under the `modules` directory of your AzerothCore source.
1) Place the module under the `modules` directory of your AzerothCore source.
2) Import the SQL files manually to the right Database (auth, world or characters)
3) Re-run cmake and launch a clean build of AzerothCore.
```
@@ -52,5 +49,7 @@ If you need to change the module configuration, go to your server configuration
* [Talamortis](https://github.com/talamortis) (Original author of the module)
* [Rochet2](https://github.com/Rochet2/): Thanks for the help with the phasing situation & General support
* [rbedfordpro](https://github.com/rbedfordpro) & [WiZZy](https://github.com/wizzymore)
* [Nelnamara - Porkserver](https://github.com/Porkserver) & [SoulSeekkor](https://github.com/SoulSeekkor) 2022 rework, crash fixes and new additions
* [Bogir](https://github.com/Bogir) For being amazing and forever helpful
AzerothCore: [repository](https://github.com/azerothcore) - [website](http://azerothcore.org/) - [discord chat community](https://discord.gg/64FH6Y8)

View File

@@ -80,6 +80,19 @@ GuildHouseSpirit = 100000
# GuildHouseBuyRank
#
# Minimum GuildRank able to make purchases in guild house
# default = 4 (Initiate)
# GR_GUILDMASTER = 0
# GR_OFFICER = 1
# GR_VETERAN = 2
# GR_MEMBER = 3
# GR_INITIATE = 4
#
GuildHouseBuyRank = 4
# GuildHouseSellRank
#
# Minimum GuildRank able to sell the guild house
# default = 0 (Guild Master)
# GR_GUILDMASTER = 0
# GR_OFFICER = 1
@@ -87,5 +100,4 @@ GuildHouseSpirit = 100000
# GR_MEMBER = 3
# GR_INITIATE = 4
#
GuildHouseBuyRank = 0
GuildHouseSellRank = 0

View File

@@ -1,30 +0,0 @@
-- --------------------------------------------------------
-- Host: 127.0.0.1
-- Server version: 5.6.28 - MySQL Community Server (GPL)
-- Server OS: Win64
-- HeidiSQL Version: 9.4.0.5125
-- --------------------------------------------------------
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET NAMES utf8 */;
/*!50503 SET NAMES utf8mb4 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-- Dumping structure for table acore_char.guild_house
CREATE TABLE IF NOT EXISTS `guild_house` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`guild` int(11) NOT NULL DEFAULT '0',
`phase` int(11) NOT NULL,
`map` int(11) NOT NULL DEFAULT '0',
`positionX` float NOT NULL DEFAULT '0',
`positionY` float NOT NULL DEFAULT '0',
`positionZ` float NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `guild` (`guild`)
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8;
-- Data exporting was unselected.
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;

View File

@@ -0,0 +1,12 @@
CREATE TABLE IF NOT EXISTS `guild_house` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`guild` int(11) NOT NULL DEFAULT '0',
`phase` int(11) NOT NULL,
`map` int(11) NOT NULL DEFAULT '0',
`positionX` float NOT NULL DEFAULT '0',
`positionY` float NOT NULL DEFAULT '0',
`positionZ` float NOT NULL DEFAULT '0',
`orientation` float NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `guild` (`guild`)
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8;

View File

@@ -1,11 +0,0 @@
REPLACE INTO `creature_template` VALUES (70101, 0, 0, 0, 0, 0, 25901, 0, 0, 0, 'Talamortis', 'Guild House Seller', '', 0, 35, 35, 0, 35, 1, 1, 1.14286, 1, 0, 49, 64, 0, 118, 1, 2000, 2000, 1, 33536, 2048, 0, 0, 0, 0, 0, 0, 33, 49, 11, 7, 4096, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 3, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 'GuildHouseSeller', 12340),
(18649, 0, 0, 0, 0, 0, 18234, 0, 0, 0, 'Innkeeper Monica', NULL, NULL, 0, 1, 2, 0, 35, 65537, 0.8, 0.28571, 1, 0, 2, 2, 0, 26, 4.6, 2000, 1900, 1, 0, 2048, 0, 0, 0, 0, 0, 0, 1, 1, 100, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', 1, 3, 1, 1, 1, 1, 0, 70, 1, 0, 0, 2, 'npc_innkeeper', 12340),
(33251, 0, 0, 0, 0, 0, 28516, 0, 0, 0, 'Death Knight Trainer', '', '', 9691, 80, 80, 2, 35, 51, 1, 1.14286, 1, 1, 422, 586, 0, 642, 7.5, 2000, 2000, 1, 32768, 2048, 0, 0, 0, 0, 6, 0, 345, 509, 103, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 3, 1, 10, 1, 1, 0, 0, 1, 8388624, 0, 0, '', 12340),
(70102, 0, 0, 0, 0, 0, 25901, 0, 0, 0, 'Xrispins', 'Guild House Assistant', '', 0, 35, 35, 0, 35, 1, 1, 1.14286, 1, 0, 49, 64, 0, 118, 1, 2000, 2000, 1, 33536, 2048, 0, 0, 0, 0, 0, 0, 33, 49, 11, 7, 4096, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 3, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 'GuildHouseSpawner', 12340),
(70103, 0, 0, 0, 0, 0, 27211, 0, 0, 0, 'Essenbaum', 'Food & Water Vendor', '', 0, 80, 80, 0, 2007, 640, 1, 1.4286, 1, 0, 49, 64, 0, 118, 1, 2000, 2000, 1, 0, 2048, 0, 0, 0, 0, 0, 0, 33, 49, 11, 7, 4096, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 3, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340),
(70104, 0, 0, 0, 0, 0, 26307, 0, 0, 0, 'Archie', 'Ammo & Repairs', '', 0, 80, 80, 0, 2007, 4480, 1, 1.4286, 1, 0, 49, 64, 0, 118, 1, 2000, 2000, 1, 33536, 2048, 0, 0, 0, 0, 0, 0, 33, 49, 11, 7, 4096, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 3, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340);
-- To revert the original NPCs (who are unused anyway), run the query below:
-- REPLACE 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`, `npcflag`, `speed_walk`, `speed_run`, `scale`, `rank`, `mindmg`, `maxdmg`, `dmgschool`, `attackpower`, `DamageModifier`, `BaseAttackTime`, `RangeAttackTime`, `unit_class`, `unit_flags`, `unit_flags2`, `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`, `HoverHeight`, `HealthModifier`, `ManaModifier`, `ArmorModifier`, `RacialLeader`, `movementId`, `RegenHealth`, `mechanic_immune_mask`, `spell_school_immune_mask`, `flags_extra`, `ScriptName`, `VerifiedBuild`) VALUES
-- (18649, 0, 0, 0, 0, 0, 18234, 0, 0, 0, 'Innkeeper Monica', NULL, NULL, 0, 1, 2, 0, 35, 0, 0.8, 0.28571, 1, 0, 2, 2, 0, 26, 4.6, 2000, 1900, 1, 0, 2048, 0, 0, 0, 0, 0, 0, 1, 1, 100, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', 1, 3, 1, 1, 1, 1, 0, 70, 1, 0, 0, 2, 'npc_innkeeper', 12340),
-- (33251, 0, 0, 0, 0, 0, 28516, 0, 0, 0, 'Death Knight Trainer and Runeforge', '', '', 0, 80, 80, 0, 35, 0, 1, 1.14286, 1, 0, 2, 2, 0, 24, 1, 2000, 2000, 1, 0, 2048, 0, 0, 0, 0, 0, 0, 1, 1, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 3, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 12340);

View File

@@ -0,0 +1,41 @@
-- !!! NOTE: set these before running the queries in order to avoid conflicts !!!
SET @C_TEMPLATE = 500030;
DELETE FROM `creature_template` WHERE `entry` IN (
@C_TEMPLATE + 0,
@C_TEMPLATE + 1,
@C_TEMPLATE + 2
);
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`, `npcflag`, `speed_walk`, `speed_run`, `speed_swim`, `speed_flight`, `detection_range`, `scale`, `rank`, `dmgschool`, `DamageModifier`, `BaseAttackTime`, `RangeAttackTime`, `BaseVariance`, `RangeVariance`, `unit_class`, `unit_flags`, `unit_flags2`, `dynamicflags`, `family`, `trainer_type`, `trainer_spell`, `trainer_class`, `trainer_race`, `type`, `type_flags`, `lootid`, `pickpocketloot`, `skinloot`, `PetSpellDataId`, `VehicleId`, `mingold`, `maxgold`, `AIName`, `MovementType`, `HoverHeight`, `HealthModifier`, `ManaModifier`, `ArmorModifier`, `ExperienceModifier`, `RacialLeader`, `movementId`, `RegenHealth`, `mechanic_immune_mask`, `spell_school_immune_mask`, `flags_extra`, `ScriptName`, `VerifiedBuild`) VALUES
(@C_TEMPLATE + 0, 0, 0, 0, 0, 0, 25901, 0, 0, 0, 'Talamortis', 'Guild House Seller', '', 0, 35, 35, 0, 35, 0, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 33536, 2048, 0, 0, 0, 0, 0, 0, 7, 4096, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 'GuildHouseSeller', 12340),
(@C_TEMPLATE + 1, 0, 0, 0, 0, 0, 25901, 0, 0, 0, 'Xrispins', 'Guild House Butler', '', 0, 35, 35, 0, 35, 0, 1, 1.14286, 1, 1, 20, 1, 0, 0, 1, 2000, 2000, 1, 1, 1, 33536, 2048, 0, 0, 0, 0, 0, 0, 7, 4096, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 'GuildHouseSpawner', 12340),
(@C_TEMPLATE + 2, 0, 0, 0, 0, 0, 18234, 0, 0, 0, 'Innkeeper Monica', NULL, NULL, 0, 1, 2, 0, 35, 65536, 0.8, 0.28571, 1, 1, 20, 1, 0, 0, 4.6, 2000, 1900, 1, 1, 1, 0, 2048, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, '', 1, 1, 1, 1, 1, 1, 0, 70, 1, 0, 0, 2, 'npc_innkeeper', 12340);
-- !!! NOTE: set these before running the queries in order to avoid conflicts !!!
SET @GO_TEMPLATE = 500000;
DELETE FROM `gameobject_template` WHERE `entry` IN (
@GO_TEMPLATE + 0,
@GO_TEMPLATE + 1,
@GO_TEMPLATE + 2,
@GO_TEMPLATE + 3,
@GO_TEMPLATE + 4,
@GO_TEMPLATE + 5,
@GO_TEMPLATE + 6,
@GO_TEMPLATE + 7,
@GO_TEMPLATE + 8,
@GO_TEMPLATE + 9
);
INSERT INTO `gameobject_template` (`entry`, `type`, `displayId`, `name`, `IconName`, `castBarCaption`, `unk1`, `size`, `Data0`, `Data1`, `Data2`, `Data3`, `Data4`, `Data5`, `Data6`, `Data7`, `Data8`, `Data9`, `Data10`, `Data11`, `Data12`, `Data13`, `Data14`, `Data15`, `Data16`, `Data17`, `Data18`, `Data19`, `Data20`, `Data21`, `Data22`, `Data23`, `AIName`, `ScriptName`, `VerifiedBuild`) VALUES
(@GO_TEMPLATE + 0, 22, 4396, 'Portal to Stormwind', '', '', '', 1, 17334, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0),
(@GO_TEMPLATE + 1, 22, 4393, 'Portal to Darnassus', '', '', '', 1, 17608, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0),
(@GO_TEMPLATE + 2, 22, 6955, 'Portal to Exodar', '', '', '', 1, 32268, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0),
(@GO_TEMPLATE + 3, 22, 4394, 'Portal to Ironforge', '', '', '', 1, 17607, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0),
(@GO_TEMPLATE + 4, 22, 4395, 'Portal to Orgrimmar', '', '', '', 1, 17609, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0),
(@GO_TEMPLATE + 5, 22, 6956, 'Portal to Silvermoon', '', '', '', 1, 32270, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0),
(@GO_TEMPLATE + 6, 22, 4397, 'Portal to Thunder Bluff', '', '', '', 1, 17610, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0),
(@GO_TEMPLATE + 7, 22, 4398, 'Portal to Undercity', '', '', '', 1, 17611, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0),
(@GO_TEMPLATE + 8, 22, 7146, 'Portal to Shattrath', '', '', '', 1, 35718, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0),
(@GO_TEMPLATE + 9, 22, 8111, 'Portal to Dalaran', '', '', '', 1, 53141, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '', 0);

View File

@@ -1,106 +0,0 @@
-- --------------------------------------------------------
-- Host: 127.0.0.1
-- Server version: 5.6.28 - MySQL Community Server (GPL)
-- Server OS: Win64
-- HeidiSQL Version: 9.4.0.5125
-- --------------------------------------------------------
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET NAMES utf8 */;
/*!50503 SET NAMES utf8mb4 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-- Dumping structure for table acore_char.guild_house
CREATE TABLE IF NOT EXISTS `guild_house` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`guild` int(11) NOT NULL DEFAULT '0',
`phase` int(11) NOT NULL,
`map` int(11) NOT NULL DEFAULT '0',
`positionX` float NOT NULL DEFAULT '0',
`positionY` float NOT NULL DEFAULT '0',
`positionZ` float NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `guild` (`guild`)
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8;
-- Dumping data for table acore_char.guild_house: ~2 rows (approximately)
/*!40000 ALTER TABLE `guild_house` DISABLE KEYS */;
REPLACE INTO `guild_house` (`id`, `guild`, `phase`, `map`, `positionX`, `positionY`, `positionZ`) VALUES
(19, 1, 1, 1, 16226.1, 16258, 13.2576),
(23, 2, 2, 1, 16226.1, 16258, 13.2576);
/*!40000 ALTER TABLE `guild_house` ENABLE KEYS */;
-- Dumping structure for table acore_world.guild_house_spawns
CREATE TABLE IF NOT EXISTS `guild_house_spawns` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`entry` int(11) NOT NULL DEFAULT '0',
`posX` float NOT NULL DEFAULT '0',
`posY` float NOT NULL DEFAULT '0',
`posZ` float NOT NULL DEFAULT '0',
`orientation` float NOT NULL DEFAULT '0',
`comment` varchar(500) DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `entry` (`entry`)
) ENGINE=InnoDB AUTO_INCREMENT=51 DEFAULT CHARSET=utf8;
-- Dumping data for table acore_world.guild_house_spawns: ~56 rows (approximately)
/*!40000 ALTER TABLE `guild_house_spawns` DISABLE KEYS */;
REPLACE INTO `guild_house_spawns` (`id`, `entry`, `posX`, `posY`, `posZ`, `orientation`, `comment`) VALUES
(1, 26327, 16216.5, 16279.4, 20.9306, 0.552869, 'Paladin Trainer'),
(2, 26324, 16221.3, 16275.7, 20.9285, 1.37363, 'Druid Trainer'),
(3, 26325, 16218.6, 16277, 20.9872, 0.967188, 'Hunter Trainer'),
(4, 26326, 16224.9, 16274.9, 20.9319, 1.58765, 'Mage Trainer'),
(5, 26328, 16227.9, 16275.9, 20.9254, 1.9941, 'Priest Trainer'),
(6, 26329, 16231.4, 16278.1, 20.9222, 2.20026, 'Rogue Trainer'),
(7, 26330, 16235.5, 16280.8, 20.9257, 2.18652, 'Shaman Trainer'),
(8, 26331, 16240.8, 16283.3, 20.9299, 1.86843, 'Warlock Trainer'),
(9, 26332, 16246.6, 16284.5, 20.9301, 1.68975, 'Warrior Trainer'),
(10, 18649, 16224.1, 16284.2, 13.1755, 4.65225, 'Inkeeper'),
(11, 30605, 16238.2, 16291.8, 22.9306, 1.55386, 'Banker'),
(12, 33251, 16252.3, 16284.9, 20.9324, 1.79537, 'Death Knight Trainer'),
(13, 33609, 16220.5, 16302.3, 13.176, 6.14647, 'Blacksmithing Trainer'),
(14, 33617, 16220.2, 16299.6, 13.178, 6.22894, 'Mining Trainer'),
(15, 33611, 16219.8, 16296.9, 13.1746, 6.24465, 'Engineering Trainer'),
(16, 33614, 16222.4, 16293, 13.1813, 1.51263, 'Jewelcrafting Trainer'),
(17, 33610, 16227.5, 16292.3, 13.1839, 1.49691, 'Enchanting Trainer'),
(18, 33615, 16231.6, 16301, 13.1757, 3.07372, 'Inscription Trainer'),
(19, 33612, 16231.2, 16295, 13.1761, 3.06574, 'Leatherworking Trainer'),
(20, 33618, 16228.9, 16304.7, 13.1819, 4.64831, 'Skinning Trainer'),
(21, 33608, 16218.1, 16281.8, 13.1756, 6.1975, 'Alchemy Trainer'),
(22, 33616, 16218.3, 16284.3, 13.1756, 6.1975, 'Herbalism Trainer'),
(23, 33613, 16220.4, 16278.7, 13.1756, 1.46157, 'Tailoring Trainer'),
(24, 33621, 16225, 16310.9, 29.262, 6.22119, 'First Aid Trainer'),
(25, 33623, 16225.3, 16313.9, 29.262, 6.28231, 'Fishing Trainer'),
(26, 33619, 16227, 16278, 13.1762, 1.4872, 'Cooking Trainer'),
(27, 8719, 16242, 16291.6, 22.9311, 1.52061, 'Alliance Auctioneer'),
(30, 9856, 16242, 16291.6, 22.9311, 1.52061, 'Horde Auctioneer'),
(31, 184137, 16220.3, 16272, 12.9736, 4.45592, 'Mailbox (Object)'),
(33, 1685, 16253.8, 16294.3, 13.1758, 6.11938, 'Forge (Object)'),
(34, 4087, 16254.4, 16298.7, 13.1758, 3.36027, 'Anvil (Object)'),
(36, 183325, 16214.8, 16218, 1.11903, 1.35357, 'Portal: Stormwind (Object)'),
(37, 183323, 16214.8, 16218, 1.11903, 1.35357, 'Portal: Orgrimmar (Object)'),
(38, 183322, 16222.8, 16216.9, 1.22016, 1.57937, 'Portal: Ironforge (Object)'),
(39, 183327, 16222.8, 16216.9, 1.22016, 1.57937, 'Portal: Undercity (Object)'),
(40, 183317, 16202.1, 16223.1, 1.03401, 0.829316, 'Portal: Darnassus (Object)'),
(41, 183326, 16202.1, 16223.1, 1.03401, 0.829316, 'Portal: Thunder Bluff (Object)'),
(42, 183324, 16196.8, 16227.5, 1.37206, 0.762557, 'Portal: Silvermoon (Object)'),
(43, 183321, 16196.8, 16227.5, 1.37206, 0.762557, 'Portal: Exodar (Object)'),
(44, 195682, 16207, 16216, 1.10669, 1.0453, 'Portal: Dalaran (Object)'),
(45, 187293, 16230.5, 16283.5, 13.9061, 3, 'Guild Vault (Object)'),
(46, 28692, 16230.2, 16316.4, 20.8455, 6.25643, 'Trade Supplies'),
(48, 28776, 16236.3, 16316.1, 20.8454, 3.06771, 'Tabard Vendor'),
(49, 70103, 16223.7, 16293.3, 20.852, 4.57958, 'Food & Drink'),
(50, 6491, 16319.937, 16242.404, 24.4747, 2.206830, 'Spirit Healer'),
(51, 191028, 16255.5, 16304.9, 20.9785, 2.97516, 'Barber Chair (Object)'),
(52, 191013, 16203, 16216, 1.10669, 1.0453, 'Portal: Shattrath (Object) - Alliance'),
(53, 29636, 16233.5, 16316.1, 20.8455, 3.07558, 'Reagent Vendor'),
(54, 191014, 16203, 16216, 1.10669, 1.0453, 'Portal: Shattrath (Object) - Horde'),
(55, 70104, 16242.8, 16302.1, 13.174, 4.6153, 'Ammo & Repair Vendor'),
(56, 28690, 16226.97, 16267.9, 13.15, 4.6533, 'Stable Master');
/*!40000 ALTER TABLE `guild_house_spawns` ENABLE KEYS */;
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;

View File

@@ -0,0 +1,68 @@
CREATE TABLE IF NOT EXISTS `guild_house_spawns` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`entry` int(11) NOT NULL DEFAULT '0',
`posX` float NOT NULL DEFAULT '0',
`posY` float NOT NULL DEFAULT '0',
`posZ` float NOT NULL DEFAULT '0',
`orientation` float NOT NULL DEFAULT '0',
`comment` varchar(500) DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `entry` (`entry`)
) ENGINE=InnoDB AUTO_INCREMENT=51 DEFAULT CHARSET=utf8;
REPLACE INTO `guild_house_spawns` (`id`, `entry`, `posX`, `posY`, `posZ`, `orientation`, `comment`) VALUES
(1, 26327, 16216.5, 16279.4, 20.9306, 0.552869, 'Paladin Trainer'),
(2, 26324, 16221.3, 16275.7, 20.9285, 1.37363, 'Druid Trainer'),
(3, 26325, 16218.6, 16277, 20.9872, 0.967188, 'Hunter Trainer'),
(4, 26326, 16224.9, 16274.9, 20.9319, 1.58765, 'Mage Trainer'),
(5, 26328, 16227.9, 16275.9, 20.9254, 1.9941, 'Priest Trainer'),
(6, 26329, 16231.4, 16278.1, 20.9222, 2.20026, 'Rogue Trainer'),
(7, 26330, 16235.5, 16280.8, 20.9257, 2.18652, 'Shaman Trainer'),
(8, 26331, 16240.8, 16283.3, 20.9299, 1.86843, 'Warlock Trainer'),
(9, 26332, 16246.6, 16284.5, 20.9301, 1.68975, 'Warrior Trainer'),
(10, 500032, 16218.9, 16284.5, 13.1761, 6.18533, 'Innkeeper'),
(11, 30605, 16228.0, 16280.5, 13.1761, 2.98877, 'Banker'),
(12, 29195, 16252.3, 16284.9, 20.9324, 1.79537, 'Death Knight Trainer'),
(13, 2836, 16220.5, 16302.3, 13.176, 6.14647, 'Blacksmithing Trainer'),
(14, 8128, 16220.2, 16299.6, 13.178, 6.22894, 'Mining Trainer'),
(15, 8736, 16219.8, 16296.9, 13.1746, 6.24465, 'Engineering Trainer'),
(16, 18774, 16222.4, 16293, 13.1813, 1.51263, 'Jewelcrafting Trainer (Alliance)'),
(17, 18751, 16222.4, 16293, 13.1813, 1.51263, 'Jewelcrafting Trainer (Horde)'),
(18, 18773, 16227.5, 16292.3, 13.1839, 1.49691, 'Enchanting Trainer (Alliance)'),
(19, 18753, 16227.5, 16292.3, 13.1839, 1.49691, 'Enchanting Trainer (Horde)'),
(20, 30721, 16231.6, 16301, 13.1757, 3.07372, 'Inscription Trainer (Alliance)'),
(21, 30722, 16231.6, 16301, 13.1757, 3.07372, 'Inscription Trainer (Horde)'),
(22, 19187, 16231.2, 16295, 13.1761, 3.06574, 'Leatherworking Trainer'),
(23, 19180, 16228.9, 16304.7, 13.1819, 4.64831, 'Skinning Trainer'),
(24, 19052, 16218.1, 16281.8, 13.1756, 6.1975, 'Alchemy Trainer'),
(25, 908, 16218.3, 16284.3, 13.1756, 6.1975, 'Herbalism Trainer'),
(26, 2627, 16220.4, 16278.7, 13.1756, 1.46157, 'Tailoring Trainer'),
(27, 19184, 16225, 16310.9, 29.262, 6.22119, 'First Aid Trainer'),
(28, 2834, 16225.3, 16313.9, 29.262, 6.28231, 'Fishing Trainer'),
(29, 19185, 16227, 16278, 13.1762, 1.4872, 'Cooking Trainer'),
(30, 8719, 16242, 16291.6, 22.9311, 1.52061, 'Alliance Auctioneer'),
(31, 9856, 16242, 16291.6, 22.9311, 1.52061, 'Horde Auctioneer'),
(32, 184137, 16220.3, 16272, 12.9736, 4.45592, 'Mailbox (Object)'),
(33, 1685, 16253.8, 16294.3, 13.1758, 6.11938, 'Forge (Object)'),
(34, 4087, 16254.4, 16298.7, 13.1758, 3.36027, 'Anvil (Object)'),
(35, 500000, 16232.9, 16264.1, 13.55570, 3.028813, 'Portal: Stormwind (Object)'),
(36, 500001, 16232.8, 16257.1, 13.93456, 3.028813, 'Portal: Darnassus (Object)'),
(37, 500002, 16231.3, 16254.2, 13.65647, 3.028813, 'Portal: Exodar (Object)'),
(38, 500003, 16233.4, 16260.6, 13.84770, 3.028813, 'Portal: Ironforge (Object)'),
(39, 500004, 16232.9, 16264.1, 13.55570, 3.028813, 'Portal: Orgrimmar (Object)'),
(40, 500005, 16231.3, 16254.2, 13.65647, 3.028813, 'Portal: Silvermoon (Object)'),
(41, 500006, 16233.4, 16260.6, 13.84770, 3.028813, 'Portal: Thunder Bluff (Object)'),
(42, 500007, 16232.8, 16257.1, 13.93456, 3.028813, 'Portal: Undercity (Object)'),
(43, 500008, 16211.1, 16266.9, 13.7458, 5.6724, 'Portal: Shattrath (Object)'),
(44, 500009, 16213.9, 16270.5, 13.1378, 5.4996, 'Portal: Dalaran (Object)'),
(45, 187293, 16230.5, 16283.5, 13.9061, 3, 'Guild Vault (Object)'),
(46, 28692, 16236.2, 16315.7, 20.8454, 4.64365, 'Trade Supplies'),
(47, 28776, 16223.7, 16297.9, 20.8454, 6.17044, 'Tabard Vendor'),
(48, 4255, 16230.2, 16316.1, 20.8455, 4.64365, 'Food & Drink Vendor'),
(49, 6491, 16319.937, 16242.404, 24.4747, 2.206830, 'Spirit Healer'),
(50, 191028, 16255.5, 16304.9, 20.9785, 2.97516, 'Barber Chair (Object)'),
(51, 29636, 16233.2, 16315.9, 20.8454, 4.64365, 'Reagent Vendor'),
(52, 29493, 16229.1, 16286.4, 13.176, 3.03831, 'Ammo & Repair Vendor'),
(53, 28690, 16226.97, 16267.9, 13.15, 4.6533, 'Stable Master'),
(54, 9858, 16238.2, 16291.8, 22.9306, 1.55386, 'Neutral Auctioneer'),
(55, 2622, 16242.8, 16302.1, 13.176, 4.55570, 'Poisons Vendor');

7
src/loader.cpp Executable file
View File

@@ -0,0 +1,7 @@
void AddGuildHouseScripts();
void AddGuildHouseButlerScripts();
void Addmod_guildhouseScripts() {
AddGuildHouseScripts();
AddGuildHouseButlerScripts();
}

View File

@@ -1,2 +0,0 @@
void AddGuildHouseV2Scripts();
void AddGuildHouseV2NPCScripts();

View File

@@ -1,695 +0,0 @@
#include "ScriptMgr.h"
#include "Player.h"
#include "Configuration/Config.h"
#include "Creature.h"
#include "Guild.h"
#include "SpellAuraEffects.h"
#include "Chat.h"
#include "ScriptedGossip.h"
#include "GuildMgr.h"
#include "Define.h"
#include "GossipDef.h"
#include "DataMap.h"
#include "GameObject.h"
#include "Transport.h"
#include "Maps/MapManager.h"
class GuildData : public DataMap::Base
{
public:
GuildData() {}
GuildData(uint32 phase, float posX, float posY, float posZ) : phase(phase), posX(posX), posY(posY), posZ(posZ) {}
uint32 phase;
float posX;
float posY;
float posZ;
};
class GuildHelper : public GuildScript {
public:
GuildHelper() : GuildScript("GuildHelper") {}
void OnCreate(Guild*, Player* leader, const std::string&)
{
ChatHandler(leader->GetSession()).PSendSysMessage("You now own a guild. You can purchase a guild house!");
}
uint32 GetGuildPhase(Guild* guild) {
return guild->GetId() + 10;
}
void OnDisband(Guild* guild)
{
if (RemoveGuildHouse(guild))
{
sLog->outBasic("GUILDHOUSE: Deleting guild house data due to disbanding of guild...");
} else { sLog->outBasic("GUILDHOUSE: Error deleting guild house data during disbanding of guild!!"); }
}
bool RemoveGuildHouse(Guild* guild)
{
uint32 guildPhase = GetGuildPhase(guild);
QueryResult CreatureResult;
QueryResult GameobjResult;
// Lets find all of the gameobjects to be removed
GameobjResult = WorldDatabase.PQuery("SELECT `guid` FROM `gameobject` WHERE `map` = 1 AND `phaseMask` = '%u'", guildPhase);
// Lets find all of the creatures to be removed
CreatureResult = WorldDatabase.PQuery("SELECT `guid` FROM `creature` WHERE `map` = 1 AND `phaseMask` = '%u'", guildPhase);
// remove creatures from the deleted guild house map
if (CreatureResult) {
do
{
Field* fields = CreatureResult->Fetch();
uint32 lowguid = fields[0].GetInt32();
if (CreatureData const* cr_data = sObjectMgr->GetCreatureData(lowguid)) {
if (Creature* creature = ObjectAccessor::GetObjectInWorld(MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT), (Creature*)NULL))
{
creature->CombatStop();
creature->DeleteFromDB();
creature->AddObjectToRemoveList();
}
}
} while (CreatureResult->NextRow());
}
// remove gameobjects from the deleted guild house map
if (GameobjResult) {
do
{
Field* fields = GameobjResult->Fetch();
uint32 lowguid = fields[0].GetInt32();
if (GameObjectData const* go_data = sObjectMgr->GetGOData(lowguid)) {
//if (GameObject* gobject = ObjectAccessor::GetObjectInWorld(lowguid, (GameObject*)NULL))
if (GameObject* gobject = ObjectAccessor::GetObjectInWorld(MAKE_NEW_GUID(lowguid, go_data->id, HIGHGUID_GAMEOBJECT), (GameObject*)NULL))
{
gobject->SetRespawnTime(0);
gobject->Delete();
gobject->DeleteFromDB();
gobject->CleanupsBeforeDelete();
//delete gobject;
}
}
} while (GameobjResult->NextRow());
}
// Delete actual guild_house data from characters database
CharacterDatabase.PQuery("DELETE FROM `guild_house` WHERE `guild` = '%u'", guild->GetId());
return true;
}
};
class GuildHouseSeller : public CreatureScript {
public:
GuildHouseSeller() : CreatureScript("GuildHouseSeller") {}
bool OnGossipHello(Player *player, Creature * creature)
{
if (!player->GetGuild())
{
ChatHandler(player->GetSession()).PSendSysMessage("You are not a member of a guild.");
CloseGossipMenuFor(player);
return false;
}
QueryResult has_gh = CharacterDatabase.PQuery("SELECT id, `guild` FROM `guild_house` WHERE guild = %u", player->GetGuildId());
// Only show Teleport option if guild owns a guildhouse
if (has_gh)
{
AddGossipItemFor(player, GOSSIP_ICON_TABARD, "Teleport to Guild House", GOSSIP_SENDER_MAIN, 1);
}
if (player->GetGuild()->GetLeaderGUID() == player->GetGUID())
{
// Only show "Sell" option if they have a guild house & are guild leader
if (has_gh)
{
AddGossipItemFor(player, GOSSIP_ICON_TABARD, "Sell Guild House!", GOSSIP_SENDER_MAIN, 3, "Are you sure you want to sell your Guild house?", 0, false);
}
else {
// Only leader of the guild can buy guild house & only if they don't already have a guild house
AddGossipItemFor(player, GOSSIP_ICON_TABARD, "Buy Guild House!", GOSSIP_SENDER_MAIN, 2);
}
}
AddGossipItemFor(player, GOSSIP_ICON_CHAT, "Close", GOSSIP_SENDER_MAIN, 5);
SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
return true;
}
bool OnGossipSelect(Player *player, Creature * m_creature, uint32, uint32 action)
{
uint32 map;
float posX;
float posY;
float posZ;
switch (action)
{
case 100: // gmsiland
map = 1;
posX = 16226.117f;
posY = 16258.046f;
posZ = 13.257628f;
break;
case 5: // close
CloseGossipMenuFor(player);
break;
case 4: // --- MORE TO COME ---
BuyGuildHouse(player->GetGuild(), player, m_creature);
break;
case 3: // Sell back guild house
{
QueryResult has_gh = CharacterDatabase.PQuery("SELECT id, `guild` FROM `guild_house` WHERE guild = %u", player->GetGuildId());
if (!has_gh)
{
ChatHandler(player->GetSession()).PSendSysMessage("Your guild does not own a Guild House!");
CloseGossipMenuFor(player);
return false;
}
// Calculate total gold returned: 1) cost of guildhouse and cost of each purchase made.
if (RemoveGuildHouse(player))
{
ChatHandler(player->GetSession()).PSendSysMessage("You have successfully sold your guild house.");
player->GetGuild()->BroadcastToGuild(player->GetSession(), false, "We just sold our guild house.", LANG_UNIVERSAL);
player->ModifyMoney(+(sConfigMgr->GetIntDefault("CostGuildHouse", 10000000) / 2));
sLog->outBasic("GUILDHOUSE: Successfully returned money and sold guildhouse");
CloseGossipMenuFor(player);
} else {
ChatHandler(player->GetSession()).PSendSysMessage("There was an error selling your guild house.");
CloseGossipMenuFor(player);
}
break;
}
case 2: // buy guild house
BuyGuildHouse(player->GetGuild(), player, m_creature);
break;
case 1: // teleport to guild house
TeleportGuildHouse(player->GetGuild(), player, m_creature);
break;
}
if (action >= 100)
{
CharacterDatabase.PQuery("INSERT INTO `guild_house` (guild, phase, map, positionX, positionY, positionZ) VALUES (%u, %u, %u, %f, %f, %f)",
player->GetGuildId(), GetGuildPhase(player), map, posX, posY, posZ);
player->ModifyMoney(-(sConfigMgr->GetIntDefault("CostGuildHouse", 10000000)));
// Msg to purchaser and Msg Guild as purchaser
ChatHandler(player->GetSession()).PSendSysMessage("You have successfully purchased a guild house");
player->GetGuild()->BroadcastToGuild(player->GetSession(), false, "We now have a Guild House!", LANG_UNIVERSAL);
player->GetGuild()->BroadcastToGuild(player->GetSession(), false, "In chat, type `.guildhouse teleport` to meet me there!", LANG_UNIVERSAL);
sLog->outBasic("GUILDHOUSE: GuildId: '%u' has purchased a guildhouse", player->GetGuildId());
// Spawn a portal and the guild assistant automatically as part of purchase.
SpawnStarterPortal(player);
SpawnAssistantNPC(player);
CloseGossipMenuFor(player);
}
return true;
}
uint32 GetGuildPhase(Player* player) {
return player->GetGuildId() + 10;
}
bool RemoveGuildHouse(Player* player)
{
uint32 guildPhase = GetGuildPhase(player);
QueryResult CreatureResult;
QueryResult GameobjResult;
// Lets find all of the gameobjects to be removed
GameobjResult = WorldDatabase.PQuery("SELECT `guid` FROM `gameobject` WHERE `map` = 1 AND `phaseMask` = '%u'", guildPhase);
// Lets find all of the creatures to be removed
CreatureResult = WorldDatabase.PQuery("SELECT `guid` FROM `creature` WHERE `map` = 1 AND `phaseMask` = '%u'", guildPhase);
// remove creatures from the deleted guild house map
if (CreatureResult) {
do
{
Field* fields = CreatureResult->Fetch();
uint32 lowguid = fields[0].GetInt32();
if (CreatureData const* cr_data = sObjectMgr->GetCreatureData(lowguid)) {
if (Creature* creature = ObjectAccessor::GetObjectInWorld(MAKE_NEW_GUID(lowguid, cr_data->id, HIGHGUID_UNIT), (Creature*)NULL))
{
creature->CombatStop();
creature->DeleteFromDB();
creature->AddObjectToRemoveList();
}
}
} while (CreatureResult->NextRow());
}
// remove gameobjects from the deleted guild house map
if (GameobjResult) {
do
{
Field* fields = GameobjResult->Fetch();
uint32 lowguid = fields[0].GetInt32();
if (GameObjectData const* go_data = sObjectMgr->GetGOData(lowguid)) {
//if (GameObject* gobject = ObjectAccessor::GetObjectInWorld(lowguid, (GameObject*)NULL))
if (GameObject* gobject = ObjectAccessor::GetObjectInWorld(MAKE_NEW_GUID(lowguid, go_data->id, HIGHGUID_GAMEOBJECT), (GameObject*)NULL))
{
gobject->SetRespawnTime(0);
gobject->Delete();
gobject->DeleteFromDB();
gobject->CleanupsBeforeDelete();
//delete gobject;
}
}
} while (GameobjResult->NextRow());
}
// Delete actual guild_house data from characters database
CharacterDatabase.PQuery("DELETE FROM `guild_house` WHERE `guild` = '%u'", player->GetGuildId());
return true;
}
void SpawnStarterPortal(Player* player)
{
uint32 entry = 0;
float posX;
float posY;
float posZ;
float ori;
Map* map = sMapMgr->FindMap(1,0);
if (player->GetTeamId() == TEAM_ALLIANCE)
{
// Portal to Stormwind
entry = 183325;
} else {
// Portal to Orgrimmar
entry = 183323;
}
if (entry == 0) { sLog->outBasic("Error with SpawnStarterPortal in GuildHouse Module!"); return; }
QueryResult result = WorldDatabase.PQuery("SELECT `posX`, `posY`, `posZ`, `orientation` FROM `guild_house_spawns` WHERE `entry` = %u", entry);
if (!result)
{
sLog->outBasic("GUILDHOUSE: Unable to find data on portal for entry: '%u'", entry);
return;
}
do
{
Field* fields = result->Fetch();
posX = fields[0].GetFloat();
posY = fields[1].GetFloat();
posZ = fields[2].GetFloat();
ori = fields[3].GetFloat();
} while (result->NextRow());
uint32 objectId = entry;
if (!objectId)
{
sLog->outBasic("GUILDHOUSE: objectId IS NULL, should be '%u'", entry);
return;
}
const GameObjectTemplate* objectInfo = sObjectMgr->GetGameObjectTemplate(objectId);
if (!objectInfo)
{
sLog->outBasic("GUILDHOUSE: objectInfo is NULL!");
return;
}
if (objectInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(objectInfo->displayId))
{
sLog->outBasic("GUILDHOUSE: Unable to find displayId??");
return;
}
GameObject* object = sObjectMgr->IsGameObjectStaticTransport(objectInfo->entry) ? new StaticTransport() : new GameObject();
uint32 guidLow = sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT);
if (!object->Create(guidLow, objectInfo->entry, map, GetGuildPhase(player), posX, posY, posZ, ori, G3D::Quat(), 0, GO_STATE_READY))
{
delete object;
sLog->outBasic("GUILDHOUSE: Unable to create object!!");
return;
}
// fill the gameobject data and save to the db
object->SaveToDB(sMapMgr->FindMap(1, 0)->GetId(), (1 << sMapMgr->FindMap(1, 0)->GetSpawnMode()), GetGuildPhase(player));
// delete the old object and do a clean load from DB with a fresh new GameObject instance.
// this is required to avoid weird behavior and memory leaks
delete object;
object = sObjectMgr->IsGameObjectStaticTransport(objectInfo->entry) ? new StaticTransport() : new GameObject();
// this will generate a new guid if the object is in an instance
if (!object->LoadGameObjectFromDB(guidLow, sMapMgr->FindMap(1, 0)))
{
delete object;
return;
}
// TODO: is it really necessary to add both the real and DB table guid here ?
sObjectMgr->AddGameobjectToGrid(guidLow, sObjectMgr->GetGOData(guidLow));
CloseGossipMenuFor(player);
}
void SpawnAssistantNPC(Player* player)
{
uint32 entry = 70102;
float posX = 16202.185547f;
float posY = 16255.916992f;
float posZ = 21.160221f;
float ori = 6.195375f;
Creature* creature = new Creature();
if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), sMapMgr->FindMap(1, 0), GetGuildPhase(player), entry, 0, posX, posY, posZ, ori))
{
delete creature;
return;
}
creature->SaveToDB(sMapMgr->FindMap(1, 0)->GetId(), (1 << sMapMgr->FindMap(1, 0)->GetSpawnMode()), GetGuildPhase(player));
uint32 db_guid = creature->GetDBTableGUIDLow();
creature->CleanupsBeforeDelete();
delete creature;
creature = new Creature();
if (!creature->LoadCreatureFromDB(db_guid, sMapMgr->FindMap(1, 0)))
{
delete creature;
return;
}
sObjectMgr->AddCreatureToGrid(db_guid, sObjectMgr->GetCreatureData(db_guid));
return;
}
bool BuyGuildHouse(Guild* guild, Player* player, Creature* creature)
{
QueryResult result = CharacterDatabase.PQuery("SELECT `id`, `guild` FROM guild_house WHERE `guild` = %u", guild->GetId());
if (result)
{
ChatHandler(player->GetSession()).PSendSysMessage("Your guild already has a Guild House.");
CloseGossipMenuFor(player);
return false;
}
ClearGossipMenuFor(player);
AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "GM Island", GOSSIP_SENDER_MAIN, 100, "Buy Guild House on GM Island?", sConfigMgr->GetIntDefault("CostGuildHouse", 10000000), false);
// Removing this tease for now, as right now the phasing code is specific go GM Island, so its not a simple thing to add new areas yet.
//AddGossipItemFor(player, GOSSIP_ICON_CHAT, " ----- More to Come ----", GOSSIP_SENDER_MAIN, 4);
SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
return true;
}
void TeleportGuildHouse(Guild* guild, Player* player, Creature* creature)
{
GuildData* guildData = player->CustomData.GetDefault<GuildData>("phase");
QueryResult result = CharacterDatabase.PQuery("SELECT `phase`, `map`,`positionX`, `positionY`, `positionZ` FROM guild_house WHERE `guild` = %u", guild->GetId());
if (!result)
{
ClearGossipMenuFor(player);
if (player->GetGuild()->GetLeaderGUID() == player->GetGUID())
{
// Only leader of the guild can buy / sell guild house
AddGossipItemFor(player, GOSSIP_ICON_TABARD, "Buy Guild House!", GOSSIP_SENDER_MAIN, 2);
AddGossipItemFor(player, GOSSIP_ICON_TABARD, "Sell Guild House!", GOSSIP_SENDER_MAIN, 3, "Are you sure you want to sell your Guild house?", 0, false);
}
AddGossipItemFor(player, GOSSIP_ICON_TABARD, "Teleport to Guild House", GOSSIP_SENDER_MAIN, 1);
AddGossipItemFor(player, GOSSIP_ICON_CHAT, "Close", GOSSIP_SENDER_MAIN, 5);
SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
ChatHandler(player->GetSession()).PSendSysMessage("Your Guild does not own a guild house");
return;
}
do {
Field* fields = result->Fetch();
guildData->phase = fields[0].GetUInt32();
uint32 map = fields[1].GetUInt32();
guildData->posX = fields[2].GetFloat();
guildData->posY = fields[3].GetFloat();
guildData->posZ = fields[4].GetFloat();
player->TeleportTo(map, guildData->posX, guildData->posY, guildData->posZ, player->GetOrientation());
} while (result->NextRow());
}
};
class GuildHouseV2PlayerScript : public PlayerScript
{
public:
GuildHouseV2PlayerScript() : PlayerScript("GuildHouseV2PlayerScript") { }
void OnLogin(Player* player)
{
CheckPlayer(player);
}
void OnUpdateZone(Player* player, uint32 newZone, uint32 /*newArea*/)
{
if (newZone == 876)
CheckPlayer(player);
else
player->SetPhaseMask(GetNormalPhase(player), true);
}
uint32 GetNormalPhase(Player* player) const
{
if (player->IsGameMaster())
return PHASEMASK_ANYWHERE;
uint32 phase = player->GetPhaseByAuras();
if (!phase)
return PHASEMASK_NORMAL;
else
return phase;
}
void CheckPlayer(Player* player)
{
GuildData* guildData = player->CustomData.GetDefault<GuildData>("phase");
QueryResult result = CharacterDatabase.PQuery("SELECT `id`, `guild`, `phase`, `map`,`positionX`, `positionY`, `positionZ` FROM guild_house WHERE `guild` = %u", player->GetGuildId());
if (result)
{
do {
// commented out due to travis, but keeping for future expansion into other areas
Field* fields = result->Fetch();
//uint32 id = fields[0].GetUInt32(); // fix for travis
//uint32 guild = fields[1].GetUInt32(); // fix for travis
guildData->phase = fields[2].GetUInt32();
//uint32 map = fields[3].GetUInt32(); // fix for travis
//guildData->posX = fields[4].GetFloat(); // fix for travis
//guildData->posY = fields[5].GetFloat(); // fix for travis
//guildData->posZ = fields[6].GetFloat(); // fix for travis
} while (result->NextRow());
}
if (player->GetZoneId() == 876 && player->GetAreaId() == 876) // GM Island
{
// If player is not in a guild he doesnt have a guild house teleport away
// TODO: What if they are in a guild, but somehow are in the wrong phaseMask and seeing someone else's area?
if (!result || !player->GetGuild())
{
ChatHandler(player->GetSession()).PSendSysMessage("Your Guild does not own a guild house.");
teleport(player);
return;
}
player->SetPhaseMask(guildData->phase, true);
}
else
player->SetPhaseMask(GetNormalPhase(player), true);
}
void teleport(Player* player)
{
if (player->GetTeamId() == TEAM_ALLIANCE)
player->TeleportTo(0, -8833.379883f, 628.627991f, 94.006599f, 1.0f);
else
player->TeleportTo(1, 1486.048340f, -4415.140625f, 24.187496f, 0.13f);
}
};
class GuildHouseCommand : public CommandScript
{
public:
GuildHouseCommand() : CommandScript("GuildHouseCommand") { }
std::vector<ChatCommand> GetCommands() const override
{
static std::vector<ChatCommand> GuildHouseCommandTable =
{
// View Command
{ "Teleport", SEC_PLAYER, false, &HandleGuildHouseTeleCommand, "" },
// Set Command
{ "SpawnNpc", SEC_PLAYER, false, &HandleSpawnNPCCommand, "" },
};
static std::vector<ChatCommand> GuildHouseCommandBaseTable =
{
{ "Guildhouse", SEC_PLAYER, false, nullptr, "", GuildHouseCommandTable }
};
return GuildHouseCommandBaseTable;
}
static uint32 GetGuildPhase(Player* player) {
return player->GetGuildId() + 10;
}
static bool HandleSpawnNPCCommand(ChatHandler* handler, char const* /*args*/)
{
Player* player = handler->GetSession()->GetPlayer();
if (!player->GetGuild() || (player->GetGuild()->GetLeaderGUID() != player->GetGUID())) {
handler->SendSysMessage("You must be the Guild Master of a guild to use this command!");
handler->SetSentErrorMessage(true);
return false;
}
if (player->GetAreaId() != 876) {
handler->SendSysMessage("You must be in your Guild House to use this command!");
handler->SetSentErrorMessage(true);
return false;
}
if (player->FindNearestCreature(70102, VISIBLE_RANGE, true)) {
handler->SendSysMessage("You already have the Guild House Assistant!");
handler->SetSentErrorMessage(true);
return false;
}
float posX = 16202.185547f;
float posY = 16255.916992f;
float posZ = 21.160221f;
float ori = 6.195375f;
Creature* creature = new Creature();
if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), player->GetMap(), GetGuildPhase(player), 70102, 0, posX, posY, posZ, ori))
{
handler->SendSysMessage("You already have the Guild House Assistant!");
handler->SetSentErrorMessage(true);
delete creature;
return false;
}
creature->SaveToDB(player->GetMapId(), (1 << player->GetMap()->GetSpawnMode()), GetGuildPhase(player));
uint32 db_guid = creature->GetDBTableGUIDLow();
creature->CleanupsBeforeDelete();
delete creature;
creature = new Creature();
if (!creature->LoadCreatureFromDB(db_guid, player->GetMap()))
{
handler->SendSysMessage("Something went wrong when adding the NPC.");
handler->SetSentErrorMessage(true);
delete creature;
return false;
}
sObjectMgr->AddCreatureToGrid(db_guid, sObjectMgr->GetCreatureData(db_guid));
return true;
}
static bool HandleGuildHouseTeleCommand(ChatHandler* handler, char const* /*args*/)
{
Player* player = handler->GetSession()->GetPlayer();
if (!player)
return false;
if (player->IsInCombat()) {
handler->SendSysMessage("You can't use this command while in combat!");
handler->SetSentErrorMessage(true);
return false;
}
GuildData* guildData = player->CustomData.GetDefault<GuildData>("phase");
QueryResult result = CharacterDatabase.PQuery("SELECT `id`, `guild`, `phase`, `map`,`positionX`, `positionY`, `positionZ` FROM guild_house WHERE `guild` = %u", player->GetGuildId());
if (!result)
{
handler->SendSysMessage("Your Guild does not own a guild house!");
handler->SetSentErrorMessage(true);
return false;
}
do {
Field* fields = result->Fetch();
//uint32 id = fields[0].GetUInt32(); // fix for travis
//uint32 guild = fields[1].GetUInt32(); // fix for travis
guildData->phase = fields[2].GetUInt32();
uint32 map = fields[3].GetUInt32();
guildData->posX = fields[4].GetFloat();
guildData->posY = fields[5].GetFloat();
guildData->posZ = fields[6].GetFloat();
player->TeleportTo(map, guildData->posX, guildData->posY, guildData->posZ, player->GetOrientation());
} while (result->NextRow());
return true;
}
};
class GuildHouseGlobal : public GlobalScript
{
public:
GuildHouseGlobal() : GlobalScript("GuildHouseGlobal") {}
void OnBeforeWorldObjectSetPhaseMask(WorldObject const* worldObject, uint32& /*oldPhaseMask*/, uint32& /*newPhaseMask*/, bool& useCombinedPhases, bool& /*update*/) override
{
if (worldObject->GetZoneId() == 876)
useCombinedPhases = false;
else
useCombinedPhases = true;
}
};
void AddGuildHouseV2Scripts() {
new GuildHelper();
new GuildHouseSeller();
new GuildHouseV2PlayerScript();
new GuildHouseCommand();
new GuildHouseGlobal();
}

738
src/mod_guildhouse.cpp Normal file
View File

@@ -0,0 +1,738 @@
#include "ScriptMgr.h"
#include "Player.h"
#include "Configuration/Config.h"
#include "Creature.h"
#include "Guild.h"
#include "SpellAuraEffects.h"
#include "Chat.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "GuildMgr.h"
#include "Define.h"
#include "GossipDef.h"
#include "DataMap.h"
#include "GameObject.h"
#include "Transport.h"
#include "Maps/MapMgr.h"
class GuildData : public DataMap::Base
{
public:
GuildData() {}
GuildData(uint32 phase, float posX, float posY, float posZ, float ori) : phase(phase), posX(posX), posY(posY), posZ(posZ), ori(ori) {}
uint32 phase;
float posX;
float posY;
float posZ;
float ori;
};
class GuildHelper : public GuildScript
{
public:
GuildHelper() : GuildScript("GuildHelper") {}
void OnCreate(Guild *, Player *leader, const std::string &)
{
ChatHandler(leader->GetSession()).PSendSysMessage("You now own a guild. You can purchase a Guild House!");
}
uint32 GetGuildPhase(Guild *guild)
{
return guild->GetId() + 10;
}
void OnDisband(Guild *guild)
{
if (RemoveGuildHouse(guild))
{
LOG_INFO("modules", "GUILDHOUSE: Deleting Guild House data due to disbanding of guild...");
}
else
{
LOG_INFO("modules", "GUILDHOUSE: Error deleting Guild House data during disbanding of guild!!");
}
}
bool RemoveGuildHouse(Guild *guild)
{
uint32 guildPhase = GetGuildPhase(guild);
QueryResult CreatureResult;
QueryResult GameobjResult;
// Lets find all of the gameobjects to be removed
GameobjResult = WorldDatabase.Query("SELECT `guid` FROM `gameobject` WHERE `map` = 1 AND `phaseMask` = '{}'", guildPhase);
// Lets find all of the creatures to be removed
CreatureResult = WorldDatabase.Query("SELECT `guid` FROM `creature` WHERE `map` = 1 AND `phaseMask` = '{}'", guildPhase);
Map *map = sMapMgr->FindMap(1, 0);
// Remove creatures from the deleted guild house map
if (CreatureResult)
{
do
{
Field *fields = CreatureResult->Fetch();
uint32 lowguid = fields[0].Get<int32>();
if (CreatureData const *cr_data = sObjectMgr->GetCreatureData(lowguid))
{
if (Creature *creature = map->GetCreature(ObjectGuid::Create<HighGuid::Unit>(cr_data->id1, lowguid)))
{
creature->CombatStop();
creature->DeleteFromDB();
creature->AddObjectToRemoveList();
}
}
} while (CreatureResult->NextRow());
}
// Remove gameobjects from the deleted guild house map
if (GameobjResult)
{
do
{
Field *fields = GameobjResult->Fetch();
uint32 lowguid = fields[0].Get<int32>();
if (GameObjectData const *go_data = sObjectMgr->GetGOData(lowguid))
{
if (GameObject *gobject = map->GetGameObject(ObjectGuid::Create<HighGuid::GameObject>(go_data->id, lowguid)))
{
gobject->SetRespawnTime(0);
gobject->Delete();
gobject->DeleteFromDB();
gobject->CleanupsBeforeDelete();
// delete gobject;
}
}
} while (GameobjResult->NextRow());
}
// Delete actual guild_house data from characters database
CharacterDatabase.Query("DELETE FROM `guild_house` WHERE `guild` = '{}'", guild->GetId());
return true;
}
};
class GuildHouseSeller : public CreatureScript
{
public:
GuildHouseSeller() : CreatureScript("GuildHouseSeller")
{
}
struct GuildHouseSellerAI : public ScriptedAI
{
GuildHouseSellerAI(Creature *creature) : ScriptedAI(creature) {}
void UpdateAI(uint32 /* diff */) override
{
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
}
};
CreatureAI *
GetAI(Creature *creature) const override
{
return new GuildHouseSellerAI(creature);
}
bool OnGossipHello(Player *player, Creature *creature) override
{
if (!player->GetGuild())
{
ChatHandler(player->GetSession()).PSendSysMessage("You are not a member of a guild.");
CloseGossipMenuFor(player);
return false;
}
QueryResult has_gh = CharacterDatabase.Query("SELECT id, `guild` FROM `guild_house` WHERE guild = {}", player->GetGuildId());
// Only show Teleport option if guild owns a guild house
if (has_gh)
{
AddGossipItemFor(player, GOSSIP_ICON_TABARD, "Teleport to Guild House", GOSSIP_SENDER_MAIN, 1);
// Only show "Sell" option if they have a guild house & have permission to sell it
Guild *guild = sGuildMgr->GetGuildById(player->GetGuildId());
Guild::Member const *memberMe = guild->GetMember(player->GetGUID());
if (memberMe->IsRankNotLower(sConfigMgr->GetOption<int32>("GuildHouseSellRank", 0)))
{
AddGossipItemFor(player, GOSSIP_ICON_TABARD, "Sell Guild House!", GOSSIP_SENDER_MAIN, 3, "Are you sure you want to sell your Guild House?", 0, false);
}
}
else
{
// Only leader of the guild can buy guild house & only if they don't already have a guild house
if (player->GetGuild()->GetLeaderGUID() == player->GetGUID())
{
AddGossipItemFor(player, GOSSIP_ICON_TABARD, "Buy Guild House!", GOSSIP_SENDER_MAIN, 2);
}
}
AddGossipItemFor(player, GOSSIP_ICON_CHAT, "Close", GOSSIP_SENDER_MAIN, 5);
SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
return true;
}
bool OnGossipSelect(Player *player, Creature *m_creature, uint32, uint32 action) override
{
uint32 map;
float posX;
float posY;
float posZ;
float ori;
switch (action)
{
case 100: // GM Island
map = 1;
posX = 16222.972f;
posY = 16267.802f;
posZ = 13.136777f;
ori = 1.461173f;
break;
case 5: // close
CloseGossipMenuFor(player);
break;
case 4: // --- MORE TO COME ---
BuyGuildHouse(player->GetGuild(), player, m_creature);
break;
case 3: // sell back guild house
{
QueryResult has_gh = CharacterDatabase.Query("SELECT id, `guild` FROM `guild_house` WHERE guild = {}", player->GetGuildId());
if (!has_gh)
{
ChatHandler(player->GetSession()).PSendSysMessage("Your guild does not own a Guild House!");
CloseGossipMenuFor(player);
return false;
}
// calculate total gold returned: 1) cost of guild house and cost of each purchase made
if (RemoveGuildHouse(player))
{
ChatHandler(player->GetSession()).PSendSysMessage("You have successfully sold your Guild House.");
player->GetGuild()->BroadcastToGuild(player->GetSession(), false, "We just sold our Guild House.", LANG_UNIVERSAL);
player->ModifyMoney(+(sConfigMgr->GetOption<int32>("CostGuildHouse", 10000000) / 2));
LOG_INFO("modules", "GUILDHOUSE: Successfully returned money and sold Guild House");
CloseGossipMenuFor(player);
}
else
{
ChatHandler(player->GetSession()).PSendSysMessage("There was an error selling your Guild House.");
CloseGossipMenuFor(player);
}
break;
}
case 2: // buy guild house
BuyGuildHouse(player->GetGuild(), player, m_creature);
break;
case 1: // teleport to guild house
TeleportGuildHouse(player->GetGuild(), player, m_creature);
break;
}
if (action >= 100)
{
CharacterDatabase.Query("INSERT INTO `guild_house` (guild, phase, map, positionX, positionY, positionZ, orientation) VALUES ({}, {}, {}, {}, {}, {}, {})", player->GetGuildId(), GetGuildPhase(player), map, posX, posY, posZ, ori);
player->ModifyMoney(-(sConfigMgr->GetOption<int32>("CostGuildHouse", 10000000)));
// Msg to purchaser and Msg Guild as purchaser
ChatHandler(player->GetSession()).PSendSysMessage("You have successfully purchased a Guild House");
player->GetGuild()->BroadcastToGuild(player->GetSession(), false, "We now have a Guild House!", LANG_UNIVERSAL);
player->GetGuild()->BroadcastToGuild(player->GetSession(), false, "In chat, type `.guildhouse teleport` or `.gh tele` to meet me there!", LANG_UNIVERSAL);
LOG_INFO("modules", "GUILDHOUSE: GuildId: '{}' has purchased a guildhouse", player->GetGuildId());
// Spawn a portal and the guild house butler automatically as part of purchase.
SpawnStarterPortal(player);
SpawnButlerNPC(player);
CloseGossipMenuFor(player);
}
return true;
}
uint32 GetGuildPhase(Player *player)
{
return player->GetGuildId() + 10;
}
bool RemoveGuildHouse(Player *player)
{
uint32 guildPhase = GetGuildPhase(player);
QueryResult CreatureResult;
QueryResult GameobjResult;
Map *map = sMapMgr->FindMap(1, 0);
// Lets find all of the gameobjects to be removed
GameobjResult = WorldDatabase.Query("SELECT `guid` FROM `gameobject` WHERE `map` = 1 AND `phaseMask` = '{}'", guildPhase);
// Lets find all of the creatures to be removed
CreatureResult = WorldDatabase.Query("SELECT `guid` FROM `creature` WHERE `map` = 1 AND `phaseMask` = '{}'", guildPhase);
// Remove creatures from the deleted guild house map
if (CreatureResult)
{
do
{
Field *fields = CreatureResult->Fetch();
uint32 lowguid = fields[0].Get<uint32>();
if (CreatureData const *cr_data = sObjectMgr->GetCreatureData(lowguid))
{
if (Creature *creature = map->GetCreature(ObjectGuid::Create<HighGuid::Unit>(cr_data->id1, lowguid)))
{
creature->CombatStop();
creature->DeleteFromDB();
creature->AddObjectToRemoveList();
}
}
} while (CreatureResult->NextRow());
}
// Remove gameobjects from the deleted guild house map
if (GameobjResult)
{
do
{
Field *fields = GameobjResult->Fetch();
uint32 lowguid = fields[0].Get<uint32>();
if (GameObjectData const *go_data = sObjectMgr->GetGOData(lowguid))
{
if (GameObject *gobject = map->GetGameObject(ObjectGuid::Create<HighGuid::GameObject>(go_data->id, lowguid)))
{
gobject->SetRespawnTime(0);
gobject->Delete();
gobject->DeleteFromDB();
gobject->CleanupsBeforeDelete();
// delete gobject;
}
}
} while (GameobjResult->NextRow());
}
// Delete actual guild_house data from characters database
CharacterDatabase.Query("DELETE FROM `guild_house` WHERE `guild` = '{}'", player->GetGuildId());
return true;
}
void SpawnStarterPortal(Player *player)
{
uint32 entry = 0;
float posX;
float posY;
float posZ;
float ori;
Map *map = sMapMgr->FindMap(1, 0);
if (player->GetTeamId() == TEAM_ALLIANCE)
{
// Portal to Stormwind
entry = 500000;
}
else
{
// Portal to Orgrimmar
entry = 500004;
}
if (entry == 0)
{
LOG_INFO("modules", "Error with SpawnStarterPortal in GuildHouse Module!");
return;
}
QueryResult result = WorldDatabase.Query("SELECT `posX`, `posY`, `posZ`, `orientation` FROM `guild_house_spawns` WHERE `entry` = {}", entry);
if (!result)
{
LOG_INFO("modules", "GUILDHOUSE: Unable to find data on portal for entry: {}", entry);
return;
}
do
{
Field *fields = result->Fetch();
posX = fields[0].Get<float>();
posY = fields[1].Get<float>();
posZ = fields[2].Get<float>();
ori = fields[3].Get<float>();
} while (result->NextRow());
uint32 objectId = entry;
if (!objectId)
{
LOG_INFO("modules", "GUILDHOUSE: objectId IS NULL, should be '{}'", entry);
return;
}
const GameObjectTemplate *objectInfo = sObjectMgr->GetGameObjectTemplate(objectId);
if (!objectInfo)
{
LOG_INFO("modules", "GUILDHOUSE: objectInfo is NULL!");
return;
}
if (objectInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(objectInfo->displayId))
{
LOG_INFO("modules", "GUILDHOUSE: Unable to find displayId??");
return;
}
GameObject *object = sObjectMgr->IsGameObjectStaticTransport(objectInfo->entry) ? new StaticTransport() : new GameObject();
ObjectGuid::LowType guidLow = player->GetMap()->GenerateLowGuid<HighGuid::GameObject>();
if (!object->Create(guidLow, objectInfo->entry, map, GetGuildPhase(player), posX, posY, posZ, ori, G3D::Quat(), 0, GO_STATE_READY))
{
delete object;
LOG_INFO("modules", "GUILDHOUSE: Unable to create object!!");
return;
}
// fill the gameobject data and save to the db
object->SaveToDB(sMapMgr->FindMap(1, 0)->GetId(), (1 << sMapMgr->FindMap(1, 0)->GetSpawnMode()), GetGuildPhase(player));
guidLow = object->GetSpawnId();
// delete the old object and do a clean load from DB with a fresh new GameObject instance.
// this is required to avoid weird behavior and memory leaks
delete object;
object = sObjectMgr->IsGameObjectStaticTransport(objectInfo->entry) ? new StaticTransport() : new GameObject();
// this will generate a new guid if the object is in an instance
if (!object->LoadGameObjectFromDB(guidLow, sMapMgr->FindMap(1, 0), true))
{
delete object;
return;
}
// TODO: is it really necessary to add both the real and DB table guid here ?
sObjectMgr->AddGameobjectToGrid(guidLow, sObjectMgr->GetGOData(guidLow));
CloseGossipMenuFor(player);
}
void SpawnButlerNPC(Player *player)
{
uint32 entry = 500031;
float posX = 16202.185547f;
float posY = 16255.916992f;
float posZ = 21.160221f;
float ori = 6.195375f;
Map *map = sMapMgr->FindMap(1, 0);
Creature *creature = new Creature();
if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, player->GetPhaseMaskForSpawn(), entry, 0, posX, posY, posZ, ori))
{
delete creature;
return;
}
creature->SaveToDB(map->GetId(), (1 << map->GetSpawnMode()), GetGuildPhase(player));
uint32 lowguid = creature->GetSpawnId();
creature->CleanupsBeforeDelete();
delete creature;
creature = new Creature();
if (!creature->LoadCreatureFromDB(lowguid, map))
{
delete creature;
return;
}
sObjectMgr->AddCreatureToGrid(lowguid, sObjectMgr->GetCreatureData(lowguid));
return;
}
bool BuyGuildHouse(Guild *guild, Player *player, Creature *creature)
{
QueryResult result = CharacterDatabase.Query("SELECT `id`, `guild` FROM guild_house WHERE `guild` = {}", guild->GetId());
if (result)
{
ChatHandler(player->GetSession()).PSendSysMessage("Your guild already has a Guild House.");
CloseGossipMenuFor(player);
return false;
}
ClearGossipMenuFor(player);
AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "GM Island", GOSSIP_SENDER_MAIN, 100, "Buy Guild House on GM Island?", sConfigMgr->GetOption<int32>("CostGuildHouse", 10000000), false);
// Removing this tease for now, as right now the phasing code is specific go GM Island, so it's not a simple thing to add new areas yet.
// AddGossipItemFor(player, GOSSIP_ICON_CHAT, " ----- More to Come ----", GOSSIP_SENDER_MAIN, 4);
SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
return true;
}
void TeleportGuildHouse(Guild *guild, Player *player, Creature *creature)
{
GuildData *guildData = player->CustomData.GetDefault<GuildData>("phase");
QueryResult result = CharacterDatabase.Query("SELECT `phase`, `map`,`positionX`, `positionY`, `positionZ`, `orientation` FROM guild_house WHERE `guild` = {}", guild->GetId());
if (!result)
{
ClearGossipMenuFor(player);
if (player->GetGuild()->GetLeaderGUID() == player->GetGUID())
{
// Only leader of the guild can buy / sell guild house
AddGossipItemFor(player, GOSSIP_ICON_TABARD, "Buy Guild House!", GOSSIP_SENDER_MAIN, 2);
AddGossipItemFor(player, GOSSIP_ICON_TABARD, "Sell Guild House!", GOSSIP_SENDER_MAIN, 3, "Are you sure you want to sell your Guild House?", 0, false);
}
AddGossipItemFor(player, GOSSIP_ICON_TABARD, "Teleport to Guild House", GOSSIP_SENDER_MAIN, 1);
AddGossipItemFor(player, GOSSIP_ICON_CHAT, "Close", GOSSIP_SENDER_MAIN, 5);
SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
ChatHandler(player->GetSession()).PSendSysMessage("Your Guild does not own a Guild House");
return;
}
do
{
Field *fields = result->Fetch();
guildData->phase = fields[0].Get<uint32>();
uint32 map = fields[1].Get<uint32>();
guildData->posX = fields[2].Get<float>();
guildData->posY = fields[3].Get<float>();
guildData->posZ = fields[4].Get<float>();
guildData->ori = fields[5].Get<float>();
player->TeleportTo(map, guildData->posX, guildData->posY, guildData->posZ, guildData->ori);
} while (result->NextRow());
}
};
class GuildHousePlayerScript : public PlayerScript
{
public:
GuildHousePlayerScript() : PlayerScript("GuildHousePlayerScript") {}
void OnLogin(Player *player)
{
CheckPlayer(player);
}
void OnUpdateZone(Player *player, uint32 newZone, uint32 /*newArea*/)
{
if (newZone == 876)
CheckPlayer(player);
else
player->SetPhaseMask(GetNormalPhase(player), true);
}
uint32 GetNormalPhase(Player *player) const
{
if (player->IsGameMaster())
return PHASEMASK_ANYWHERE;
uint32 phase = player->GetPhaseByAuras();
if (!phase)
return PHASEMASK_NORMAL;
else
return phase;
}
void CheckPlayer(Player *player)
{
GuildData *guildData = player->CustomData.GetDefault<GuildData>("phase");
QueryResult result = CharacterDatabase.Query("SELECT `id`, `guild`, `phase`, `map`,`positionX`, `positionY`, `positionZ`, `orientation` FROM guild_house WHERE `guild` = {}", player->GetGuildId());
if (result)
{
do
{
// commented out due to travis, but keeping for future expansion into other areas
Field *fields = result->Fetch();
// uint32 id = fields[0].Get<uint32>(); // fix for travis
// uint32 guild = fields[1].Get<uint32>(); // fix for travis
guildData->phase = fields[2].Get<uint32>();
// uint32 map = fields[3].Get<uint32>(); // fix for travis
// guildData->posX = fields[4].Get<float>(); // fix for travis
// guildData->posY = fields[5].Get<float>(); // fix for travis
// guildData->posZ = fields[6].Get<float>(); // fix for travis
// guildData->ori = fields[7].Get<float>(); // fix for travis
} while (result->NextRow());
}
if (player->GetZoneId() == 876 && player->GetAreaId() == 876) // GM Island
{
// If player is not in a guild he doesnt have a guild house teleport away
// TODO: What if they are in a guild, but somehow are in the wrong phaseMask and seeing someone else's area?
if (!result || !player->GetGuild())
{
ChatHandler(player->GetSession()).PSendSysMessage("Your guild does not own a Guild House.");
teleportToDefault(player);
return;
}
player->SetPhaseMask(guildData->phase, true);
}
else
player->SetPhaseMask(GetNormalPhase(player), true);
}
void teleportToDefault(Player *player)
{
if (player->GetTeamId() == TEAM_ALLIANCE)
player->TeleportTo(0, -8833.379883f, 628.627991f, 94.006599f, 1.0f);
else
player->TeleportTo(1, 1486.048340f, -4415.140625f, 24.187496f, 0.13f);
}
};
using namespace Acore::ChatCommands;
class GuildHouseCommand : public CommandScript
{
public:
GuildHouseCommand() : CommandScript("GuildHouseCommand") {}
ChatCommandTable GetCommands() const override
{
static ChatCommandTable GuildHouseCommandTable =
{
{"teleport", HandleGuildHouseTeleCommand, SEC_PLAYER, Console::Yes},
{"butler", HandleSpawnButlerCommand, SEC_PLAYER, Console::Yes},
};
static ChatCommandTable GuildHouseCommandBaseTable =
{
{"guildhouse", GuildHouseCommandTable},
{"gh", GuildHouseCommandTable}};
return GuildHouseCommandBaseTable;
}
static uint32 GetGuildPhase(Player *player)
{
return player->GetGuildId() + 10;
}
static bool HandleSpawnButlerCommand(ChatHandler *handler)
{
Player *player = handler->GetSession()->GetPlayer();
Map *map = player->GetMap();
if (!player->GetGuild() || (player->GetGuild()->GetLeaderGUID() != player->GetGUID()))
{
handler->SendSysMessage("You must be the Guild Master of a guild to use this command!");
handler->SetSentErrorMessage(true);
return false;
}
if (player->GetAreaId() != 876)
{
handler->SendSysMessage("You must be in your Guild House to use this command!");
handler->SetSentErrorMessage(true);
return false;
}
if (player->FindNearestCreature(500031, VISIBLE_RANGE, true))
{
handler->SendSysMessage("You already have the Guild House Butler!");
handler->SetSentErrorMessage(true);
return false;
}
float posX = 16202.185547f;
float posY = 16255.916992f;
float posZ = 21.160221f;
float ori = 6.195375f;
Creature *creature = new Creature();
if (!creature->Create(map->GenerateLowGuid<HighGuid::Unit>(), map, GetGuildPhase(player), 500031, 0, posX, posY, posZ, ori))
{
handler->SendSysMessage("You already have the Guild House Butler!");
handler->SetSentErrorMessage(true);
delete creature;
return false;
}
creature->SaveToDB(player->GetMapId(), (1 << player->GetMap()->GetSpawnMode()), GetGuildPhase(player));
uint32 lowguid = creature->GetSpawnId();
creature->CleanupsBeforeDelete();
delete creature;
creature = new Creature();
if (!creature->LoadCreatureFromDB(lowguid, player->GetMap()))
{
handler->SendSysMessage("Something went wrong when adding the Butler.");
handler->SetSentErrorMessage(true);
delete creature;
return false;
}
sObjectMgr->AddCreatureToGrid(lowguid, sObjectMgr->GetCreatureData(lowguid));
return true;
}
static bool HandleGuildHouseTeleCommand(ChatHandler *handler)
{
Player *player = handler->GetSession()->GetPlayer();
if (!player)
return false;
if (player->IsInCombat())
{
handler->SendSysMessage("You can't use this command while in combat!");
handler->SetSentErrorMessage(true);
return false;
}
GuildData *guildData = player->CustomData.GetDefault<GuildData>("phase");
QueryResult result = CharacterDatabase.Query("SELECT `id`, `guild`, `phase`, `map`,`positionX`, `positionY`, `positionZ`, `orientation` FROM guild_house WHERE `guild` = {}", player->GetGuildId());
if (!result)
{
handler->SendSysMessage("Your guild does not own a Guild House!");
handler->SetSentErrorMessage(true);
return false;
}
do
{
Field *fields = result->Fetch();
// uint32 id = fields[0].Get<uint32>(); // fix for travis
// uint32 guild = fields[1].Get<uint32>(); // fix for travis
guildData->phase = fields[2].Get<uint32>();
uint32 map = fields[3].Get<uint32>();
guildData->posX = fields[4].Get<float>();
guildData->posY = fields[5].Get<float>();
guildData->posZ = fields[6].Get<float>();
guildData->ori = fields[7].Get<float>();
player->TeleportTo(map, guildData->posX, guildData->posY, guildData->posZ, guildData->ori);
} while (result->NextRow());
return true;
}
};
class GuildHouseGlobal : public GlobalScript
{
public:
GuildHouseGlobal() : GlobalScript("GuildHouseGlobal") {}
void OnBeforeWorldObjectSetPhaseMask(WorldObject const *worldObject, uint32 & /*oldPhaseMask*/, uint32 & /*newPhaseMask*/, bool &useCombinedPhases, bool & /*update*/) override
{
if (worldObject->GetZoneId() == 876)
useCombinedPhases = false;
else
useCombinedPhases = true;
}
};
void AddGuildHouseScripts()
{
new GuildHelper();
new GuildHouseSeller();
new GuildHousePlayerScript();
new GuildHouseCommand();
new GuildHouseGlobal();
}

View File

@@ -1,6 +1,7 @@
#include "ScriptMgr.h"
#include "Player.h"
#include "Chat.h"
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "Configuration/Config.h"
#include "Creature.h"
@@ -15,21 +16,38 @@
int cost, GuildHouseInnKeeper, GuildHouseBank, GuildHouseMailBox, GuildHouseAuctioneer, GuildHouseTrainer, GuildHouseVendor, GuildHouseObject, GuildHousePortal, GuildHouseSpirit, GuildHouseProf, GuildHouseBuyRank;
class GuildHouseSpawner : public CreatureScript {
class GuildHouseSpawner : public CreatureScript
{
public:
GuildHouseSpawner() : CreatureScript("GuildHouseSpawner") { }
GuildHouseSpawner() : CreatureScript("GuildHouseSpawner") {}
bool OnGossipHello(Player *player, Creature * creature)
struct GuildHouseSpawnerAI : public ScriptedAI
{
GuildHouseSpawnerAI(Creature *creature) : ScriptedAI(creature) {}
void UpdateAI(uint32 /* diff */) override
{
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
}
};
CreatureAI *
GetAI(Creature *creature) const override
{
return new GuildHouseSpawnerAI(creature);
}
bool OnGossipHello(Player *player, Creature *creature) override
{
if (player->GetGuild())
{
Guild* guild = sGuildMgr->GetGuildById(player->GetGuildId());
Guild::Member const* memberMe = guild->GetMember(player->GetGUID());
Guild *guild = sGuildMgr->GetGuildById(player->GetGuildId());
Guild::Member const *memberMe = guild->GetMember(player->GetGUID());
if (!memberMe->IsRankNotLower(GuildHouseBuyRank))
{
ChatHandler(player->GetSession()).PSendSysMessage("You are not authorized to make guild house purchases.");
ChatHandler(player->GetSession()).PSendSysMessage("You are not authorized to make Guild House purchases.");
return false;
}
}
@@ -40,29 +58,30 @@ public:
}
ClearGossipMenuFor(player);
AddGossipItemFor(player, GOSSIP_ICON_TALK, "Spawn Innkeeper", GOSSIP_SENDER_MAIN, 18649, "Add an Innkeeper?", GuildHouseInnKeeper, false);
AddGossipItemFor(player, GOSSIP_ICON_TALK, "Spawn Mailbox", GOSSIP_SENDER_MAIN, 184137, "Spawn a mailbox?", GuildHouseMailBox, false);
AddGossipItemFor(player, GOSSIP_ICON_TALK, "Spawn Innkeeper", GOSSIP_SENDER_MAIN, 500032, "Add an Innkeeper?", GuildHouseInnKeeper, false);
AddGossipItemFor(player, GOSSIP_ICON_TALK, "Spawn Mailbox", GOSSIP_SENDER_MAIN, 184137, "Spawn a Mailbox?", GuildHouseMailBox, false);
AddGossipItemFor(player, GOSSIP_ICON_TALK, "Spawn Stable Master", GOSSIP_SENDER_MAIN, 28690, "Spawn a Stable Master?", GuildHouseVendor, false);
AddGossipItemFor(player, GOSSIP_ICON_TALK, "Spawn Class Trainer", GOSSIP_SENDER_MAIN, 2);
AddGossipItemFor(player, GOSSIP_ICON_TALK, "Spawn Vendor", GOSSIP_SENDER_MAIN, 3);
AddGossipItemFor(player, GOSSIP_ICON_TALK, "Spawn City Portals / Objects", GOSSIP_SENDER_MAIN, 4);
AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "Spawn Bank", GOSSIP_SENDER_MAIN, 30605, "Spawn a banker?", GuildHouseBank, false);
AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "Spawn Auctioneer", GOSSIP_SENDER_MAIN, 6, "Spawn an auctioneer", GuildHouseAuctioneer, false);
AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "Spawn Bank", GOSSIP_SENDER_MAIN, 30605, "Spawn a Banker?", GuildHouseBank, false);
AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "Spawn Auctioneer", GOSSIP_SENDER_MAIN, 6, "Spawn an Auctioneer?", GuildHouseAuctioneer, false);
AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "Spawn Neutral Auctioneer", GOSSIP_SENDER_MAIN, 9858, "Spawn a Neutral Auctioneer?", GuildHouseAuctioneer, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Spawn Primary Profession Trainers", GOSSIP_SENDER_MAIN, 7);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Spawn Secondry Profession Trainers", GOSSIP_SENDER_MAIN, 8);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Spawn Secondary Profession Trainers", GOSSIP_SENDER_MAIN, 8);
AddGossipItemFor(player, GOSSIP_ICON_TALK, "Spawn Sprirt Healer", GOSSIP_SENDER_MAIN, 6491, "Spawn a Spirit Healer?", GuildHouseSpirit, false);
SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
return true;
}
bool OnGossipSelect(Player *player, Creature * m_creature, uint32, uint32 action)
bool OnGossipSelect(Player *player, Creature *m_creature, uint32, uint32 action) override
{
switch (action)
{
case 2: // spawn class trainer
case 2: // Spawn Class Trainer
ClearGossipMenuFor(player);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Death Knight", GOSSIP_SENDER_MAIN, 33251, "Spawn Death Knight Trainer?", GuildHouseTrainer, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Death Knight", GOSSIP_SENDER_MAIN, 29195, "Spawn Death Knight Trainer?", GuildHouseTrainer, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Druid", GOSSIP_SENDER_MAIN, 26324, "Spawn Druid Trainer?", GuildHouseTrainer, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Hunter", GOSSIP_SENDER_MAIN, 26325, "Spawn Hunter Trainer?", GuildHouseTrainer, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Mage", GOSSIP_SENDER_MAIN, 26326, "Spawn Mage Trainer?", GuildHouseTrainer, false);
@@ -79,38 +98,38 @@ public:
ClearGossipMenuFor(player);
AddGossipItemFor(player, GOSSIP_ICON_TALK, "Trade Supplies", GOSSIP_SENDER_MAIN, 28692, "Spawn Trade Supplies?", GuildHouseVendor, false);
AddGossipItemFor(player, GOSSIP_ICON_TALK, "Tabard Vendor", GOSSIP_SENDER_MAIN, 28776, "Spawn Tabard Vendor?", GuildHouseVendor, false);
AddGossipItemFor(player, GOSSIP_ICON_TALK, "Food & Drink", GOSSIP_SENDER_MAIN, 70103, "Spawn Food & Drink?", GuildHouseVendor, false);
AddGossipItemFor(player, GOSSIP_ICON_TALK, "Food & Drink Vendor", GOSSIP_SENDER_MAIN, 4255, "Spawn Food & Drink Vendor?", GuildHouseVendor, false);
AddGossipItemFor(player, GOSSIP_ICON_TALK, "Reagent Vendor", GOSSIP_SENDER_MAIN, 29636, "Spawn Reagent Vendor?", GuildHouseVendor, false);
AddGossipItemFor(player, GOSSIP_ICON_TALK, "Ammo & Repair Vendor", GOSSIP_SENDER_MAIN, 70104, "Spawn Ammo & Repair Vendor?", GuildHouseVendor, false);
AddGossipItemFor(player, GOSSIP_ICON_TALK, "Ammo & Repair Vendor", GOSSIP_SENDER_MAIN, 29493, "Spawn Ammo & Repair Vendor?", GuildHouseVendor, false);
AddGossipItemFor(player, GOSSIP_ICON_TALK, "Poisons Vendor", GOSSIP_SENDER_MAIN, 2622, "Spawn Poisons Vendor?", GuildHouseVendor, false);
AddGossipItemFor(player, GOSSIP_ICON_CHAT, "Go Back!", GOSSIP_SENDER_MAIN, 9);
SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, m_creature->GetGUID());
break;
case 4: //objects / portals
case 4: // Objects & Portals
ClearGossipMenuFor(player);
AddGossipItemFor(player, GOSSIP_ICON_TALK, "Forge", GOSSIP_SENDER_MAIN, 1685, "Add a forge?", GuildHouseObject, false);
AddGossipItemFor(player, GOSSIP_ICON_TALK, "Anvil", GOSSIP_SENDER_MAIN, 4087, "Add an Anvil?", GuildHouseObject, false);
AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "Guild Vault", GOSSIP_SENDER_MAIN, 187293, "Add Guild Vault?", GuildHouseObject, false);
AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "Barber Chair", GOSSIP_SENDER_MAIN, 191028, "Add a Barber Chair?", GuildHouseObject, false);
AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "Guild Vault", GOSSIP_SENDER_MAIN, 187293, "Add Guild Vault?", GuildHouseObject, false);
AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "Barber Chair", GOSSIP_SENDER_MAIN, 191028, "Add a Barber Chair?", GuildHouseObject, false);
if (player->GetTeamId() == TEAM_ALLIANCE) // ALLIANCE players get these options
if (player->GetTeamId() == TEAM_ALLIANCE)
{
// Commenting out as we are auto-creating Stormwind portal upon guild purchase
//AddGossipItemFor(player, GOSSIP_ICON_TAXI, "Portal: Stormwind", GOSSIP_SENDER_MAIN, 183325, "Add Stormwind Portal?", GuildHousePortal, false);
AddGossipItemFor(player, GOSSIP_ICON_TAXI, "Portal: Ironforge", GOSSIP_SENDER_MAIN, 183322, "Add Ironforge Portal?", GuildHousePortal, false);
AddGossipItemFor(player, GOSSIP_ICON_TAXI, "Portal: Darnassus", GOSSIP_SENDER_MAIN, 183317, "Add Darnassus Portal?", GuildHousePortal, false);
AddGossipItemFor(player, GOSSIP_ICON_TAXI, "Portal: Exodar", GOSSIP_SENDER_MAIN, 183321, "Add Exodar Portal?", GuildHousePortal, false);
// ALLIANCE players get these options
AddGossipItemFor(player, GOSSIP_ICON_TAXI, "Portal: Ironforge", GOSSIP_SENDER_MAIN, 500003, "Add Ironforge Portal?", GuildHousePortal, false);
AddGossipItemFor(player, GOSSIP_ICON_TAXI, "Portal: Darnassus", GOSSIP_SENDER_MAIN, 500001, "Add Darnassus Portal?", GuildHousePortal, false);
AddGossipItemFor(player, GOSSIP_ICON_TAXI, "Portal: Exodar", GOSSIP_SENDER_MAIN, 500002, "Add Exodar Portal?", GuildHousePortal, false);
}
else // HORDE players get these options:
else
{
// Commenting out as we are auto-creating Orgrimmar portal upon guild purchase
//AddGossipItemFor(player, GOSSIP_ICON_TAXI, "Portal: Orgrimmar", GOSSIP_SENDER_MAIN, 183323, "Add Orgrimmar Portal?", GuildHousePortal, false);
AddGossipItemFor(player, GOSSIP_ICON_TAXI, "Portal: Undercity", GOSSIP_SENDER_MAIN, 183327, "Add Undercity Portal?", GuildHousePortal, false);
AddGossipItemFor(player, GOSSIP_ICON_TAXI, "Portal: Thunderbluff", GOSSIP_SENDER_MAIN, 183326, "Add Thunderbuff Portal?", GuildHousePortal, false);
AddGossipItemFor(player, GOSSIP_ICON_TAXI, "Portal: Silvermoon", GOSSIP_SENDER_MAIN, 183324, "Add Silvermoon Portal?", GuildHousePortal, false);
// HORDE players get these options
AddGossipItemFor(player, GOSSIP_ICON_TAXI, "Portal: Undercity", GOSSIP_SENDER_MAIN, 500007, "Add Undercity Portal?", GuildHousePortal, false);
AddGossipItemFor(player, GOSSIP_ICON_TAXI, "Portal: Thunderbluff", GOSSIP_SENDER_MAIN, 500006, "Add Thunderbuff Portal?", GuildHousePortal, false);
AddGossipItemFor(player, GOSSIP_ICON_TAXI, "Portal: Silvermoon", GOSSIP_SENDER_MAIN, 500005, "Add Silvermoon Portal?", GuildHousePortal, false);
}
// These two portals work for either Team
AddGossipItemFor(player, GOSSIP_ICON_TAXI, "Portal: Shattrath", GOSSIP_SENDER_MAIN, 191013, "Add Shattrath Portal?", GuildHousePortal, false);
AddGossipItemFor(player, GOSSIP_ICON_TAXI, "Portal: Dalaran", GOSSIP_SENDER_MAIN, 195682, "Add Dalaran Portal?", GuildHousePortal, false);
// These two portals work for either Team
AddGossipItemFor(player, GOSSIP_ICON_TAXI, "Portal: Shattrath", GOSSIP_SENDER_MAIN, 500008, "Add Shattrath Portal?", GuildHousePortal, false);
AddGossipItemFor(player, GOSSIP_ICON_TAXI, "Portal: Dalaran", GOSSIP_SENDER_MAIN, 500009, "Add Dalaran Portal?", GuildHousePortal, false);
AddGossipItemFor(player, GOSSIP_ICON_CHAT, "Go Back!", GOSSIP_SENDER_MAIN, 9);
SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, m_creature->GetGUID());
@@ -122,109 +141,129 @@ public:
SpawnNPC(auctioneer, player);
break;
}
case 7: // spawn profession trainers
case 9858: // Neutral Auctioneer
cost = GuildHouseAuctioneer;
SpawnNPC(action, player);
break;
case 7: // Spawn Profession Trainers
ClearGossipMenuFor(player);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Alchemy Trainer", GOSSIP_SENDER_MAIN, 33608, "Spawn Alchemy Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Blacksmithing Trainer", GOSSIP_SENDER_MAIN, 33609, "Spawn Blacksmithing Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Enchanting Trainer", GOSSIP_SENDER_MAIN, 33610, "Spawn Enchanting Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Engineering Trainer", GOSSIP_SENDER_MAIN, 33611, "Spawn Engineering Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Tailoring Trainer", GOSSIP_SENDER_MAIN, 33613, "Spawn Tailoring Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Leatherworking Trainer", GOSSIP_SENDER_MAIN, 33612, "Spawn Leatherworking Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Jewlelcrafing Trainer", GOSSIP_SENDER_MAIN, 33614, "Spawn Jewelcrafting Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Inscription Trainer", GOSSIP_SENDER_MAIN, 33615, "Spawn Inscription Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Skinning Trainer", GOSSIP_SENDER_MAIN, 33618, "Spawn Skinning Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Mining Trainer", GOSSIP_SENDER_MAIN, 33617, "Spawn Mining Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Herbalism Trainer", GOSSIP_SENDER_MAIN, 33616, "Spawn Herbalism Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Alchemy Trainer", GOSSIP_SENDER_MAIN, 19052, "Spawn Alchemy Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Blacksmithing Trainer", GOSSIP_SENDER_MAIN, 2836, "Spawn Blacksmithing Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Engineering Trainer", GOSSIP_SENDER_MAIN, 8736, "Spawn Engineering Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Tailoring Trainer", GOSSIP_SENDER_MAIN, 2627, "Spawn Tailoring Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Leatherworking Trainer", GOSSIP_SENDER_MAIN, 19187, "Spawn Leatherworking Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Skinning Trainer", GOSSIP_SENDER_MAIN, 19180, "Spawn Skinning Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Mining Trainer", GOSSIP_SENDER_MAIN, 8128, "Spawn Mining Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Herbalism Trainer", GOSSIP_SENDER_MAIN, 908, "Spawn Herbalism Trainer?", GuildHouseProf, false);
if (player->GetTeamId() == TEAM_ALLIANCE)
{
// ALLIANCE players get these options
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Enchanting Trainer", GOSSIP_SENDER_MAIN, 18773, "Spawn Enchanting Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Jewelcrafing Trainer", GOSSIP_SENDER_MAIN, 18774, "Spawn Jewelcrafting Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Inscription Trainer", GOSSIP_SENDER_MAIN, 30721, "Spawn Inscription Trainer?", GuildHouseProf, false);
}
else
{
// HORDE players get these options
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Enchanting Trainer", GOSSIP_SENDER_MAIN, 18753, "Spawn Enchanting Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Jewelcrafing Trainer", GOSSIP_SENDER_MAIN, 18751, "Spawn Jewelcrafting Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_TRAINER, "Inscription Trainer", GOSSIP_SENDER_MAIN, 30722, "Spawn Inscription Trainer?", GuildHouseProf, false);
}
AddGossipItemFor(player, GOSSIP_ICON_CHAT, "Go Back!", GOSSIP_SENDER_MAIN, 9);
SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, m_creature->GetGUID());
break;
case 8: // secondry prof trainers
case 8: // Secondary Profession Trainers
ClearGossipMenuFor(player);
AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "First Aid Trainer", GOSSIP_SENDER_MAIN, 33621, "Spawn Fist Aid Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "Fishing Trainer", GOSSIP_SENDER_MAIN, 33623, "Spawn Fishing Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "Cooking Trainer", GOSSIP_SENDER_MAIN, 33619, "Spawn Cooking Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "First Aid Trainer", GOSSIP_SENDER_MAIN, 19184, "Spawn First Aid Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "Fishing Trainer", GOSSIP_SENDER_MAIN, 2834, "Spawn Fishing Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_MONEY_BAG, "Cooking Trainer", GOSSIP_SENDER_MAIN, 19185, "Spawn Cooking Trainer?", GuildHouseProf, false);
AddGossipItemFor(player, GOSSIP_ICON_CHAT, "Go Back!", GOSSIP_SENDER_MAIN, 9);
SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, m_creature->GetGUID());
break;
case 9: // go back!
case 9: // Go back!
OnGossipHello(player, m_creature);
break;
case 10: //PVP toggle
case 10: // PVP toggle
break;
case 30605: // Banker
cost = GuildHouseBank;
SpawnNPC(action, player);
break;
case 18649: // Innkeeper
case 500032: // Innkeeper
cost = GuildHouseInnKeeper;
SpawnNPC(action, player);
break;
case 26327: // Paladin
case 26324: // Druid
case 26325: // Hunter
case 26326: // Mage
case 26328: // Priest.
case 26326: // Mage
case 26328: // Priest
case 26329: // Rogue
case 26330: // Shaman
case 26331: // Warlock
case 26332: // Warrior
case 33251: // Death Knight
case 29195: // Death Knight
cost = GuildHouseTrainer;
SpawnNPC(action, player);
break;
case 33609: // Blacksmithing
case 33617: // Mining
case 33611: // Engineering
case 33614: // Jewelcrafting
case 33610: // Enchanting
case 33615: // Inscription
case 33612: // Leatherworking
case 33618: // Skinning
case 33608: // Alchemy
case 33616: // Herbalism
case 33613: // Tailoring
case 33619: // Cooking
case 33623: // Fishing
case 33621: // First Aid
case 2836: // Blacksmithing
case 8128: // Mining
case 8736: // Engineering
case 18774: // Jewelcrafting (Alliance)
case 18751: // Jewelcrafting (Horde)
case 18773: // Enchanting (Alliance)
case 18753: // Enchanting (Horde)
case 30721: // Inscription (Alliance)
case 30722: // Inscription (Horde)
case 19187: // Leatherworking
case 19180: // Skinning
case 19052: // Alchemy
case 908: // Herbalism
case 2627: // Tailoring
case 19185: // Cooking
case 2834: // Fishing
case 19184: // First Aid
cost = GuildHouseProf;
SpawnNPC(action, player);
break;
case 28692: // Trade supplies
case 28692: // Trade Supplies
case 28776: // Tabard Vendor
case 70103: // Food & Drink
case 4255: // Food & Drink Vendor
case 29636: // Reagent Vendor
case 70104: // Ammo & Repair Vendor
case 29493: // Ammo & Repair Vendor
case 28690: // Stable Master
case 2622: // Poisons Vendor
cost = GuildHouseVendor;
SpawnNPC(action, player);
break;
//
// Objects
//
case 184137: // mailbox
case 184137: // Mailbox
cost = GuildHouseMailBox;
SpawnObject(action, player);
break;
case 6491: // spirit healer
case 6491: // Spirit Healer
cost = GuildHouseSpirit;
SpawnNPC(action, player);
break;
case 1685: // forge
case 4087: // Anvil
break;
case 1685: // Forge
case 4087: // Anvil
case 187293: // Guild Vault
case 191028: // Barber Chair
cost = GuildHouseObject;
SpawnObject(action, player);
break;
case 183322: // Ironforge Portal
case 183327: // Undercity Portal
case 183317: // Darnassus Portal
case 183326: // Thunder bluff portal
case 183324: // Silvermoon Portal
case 183321: // Exodar Portal
case 191013: // Shattrath Portal:Alliance
case 191014: // Shattrath Portal:Horde
case 195682: // Dalaran Portal
case 500001: // Darnassus Portal
case 500002: // Exodar Portal
case 500003: // Ironforge Portal
case 500005: // Silvermoon Portal
case 500006: // Thunder Bluff Portal
case 500007: // Undercity Portal
case 500008: // Shattrath Portal
case 500009: // Dalaran Portal
cost = GuildHousePortal;
SpawnObject(action, player);
break;
@@ -232,11 +271,12 @@ public:
return true;
}
uint32 GetGuildPhase(Player* player) {
return player->GetGuildId() + 10;
}
uint32 GetGuildPhase(Player *player)
{
return player->GetGuildId() + 10;
}
void SpawnNPC(uint32 entry, Player* player)
void SpawnNPC(uint32 entry, Player *player)
{
if (player->FindNearestCreature(entry, VISIBILITY_RANGE, true))
{
@@ -250,30 +290,30 @@ public:
float posZ;
float ori;
QueryResult result = WorldDatabase.PQuery("SELECT `posX`, `posY`, `posZ`, `orientation` FROM `guild_house_spawns` WHERE `entry` = %u", entry);
QueryResult result = WorldDatabase.Query("SELECT `posX`, `posY`, `posZ`, `orientation` FROM `guild_house_spawns` WHERE `entry` = {}", entry);
if (!result)
return;
do
{
Field* fields = result->Fetch();
posX = fields[0].GetFloat();
posY = fields[1].GetFloat();
posZ = fields[2].GetFloat();
ori = fields[3].GetFloat();
Field *fields = result->Fetch();
posX = fields[0].Get<float>();
posY = fields[1].Get<float>();
posZ = fields[2].Get<float>();
ori = fields[3].Get<float>();
} while (result->NextRow());
Creature* creature = new Creature();
Creature *creature = new Creature();
if (!creature->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_UNIT), player->GetMap(), GetGuildPhase(player), entry, 0, posX,posY, posZ, ori))
if (!creature->Create(player->GetMap()->GenerateLowGuid<HighGuid::Unit>(), player->GetMap(), GetGuildPhase(player), entry, 0, posX, posY, posZ, ori))
{
delete creature;
return;
}
creature->SaveToDB(player->GetMapId(), (1 << player->GetMap()->GetSpawnMode()), GetGuildPhase(player));
uint32 db_guid = creature->GetDBTableGUIDLow();
uint32 db_guid = creature->GetSpawnId();
creature->CleanupsBeforeDelete();
delete creature;
@@ -289,28 +329,8 @@ public:
CloseGossipMenuFor(player);
}
void SpawnObject(uint32 entry, Player* player)
void SpawnObject(uint32 entry, Player *player)
{
float posX;
float posY;
float posZ;
float ori;
QueryResult result = WorldDatabase.PQuery("SELECT `posX`, `posY`, `posZ`, `orientation` FROM `guild_house_spawns` WHERE `entry` = %u", entry);
if (!result)
return;
do
{
Field* fields = result->Fetch();
posX = fields[0].GetFloat();
posY = fields[1].GetFloat();
posZ = fields[2].GetFloat();
ori = fields[3].GetFloat();
} while (result->NextRow());
if (player->FindNearestGameObject(entry, VISIBLE_RANGE))
{
ChatHandler(player->GetSession()).PSendSysMessage("You already have this object!");
@@ -318,20 +338,40 @@ public:
return;
}
float posX;
float posY;
float posZ;
float ori;
QueryResult result = WorldDatabase.Query("SELECT `posX`, `posY`, `posZ`, `orientation` FROM `guild_house_spawns` WHERE `entry` = {}", entry);
if (!result)
return;
do
{
Field *fields = result->Fetch();
posX = fields[0].Get<float>();
posY = fields[1].Get<float>();
posZ = fields[2].Get<float>();
ori = fields[3].Get<float>();
} while (result->NextRow());
uint32 objectId = entry;
if (!objectId)
return;
const GameObjectTemplate* objectInfo = sObjectMgr->GetGameObjectTemplate(objectId);
const GameObjectTemplate *objectInfo = sObjectMgr->GetGameObjectTemplate(objectId);
if (!objectInfo)
return;
if (objectInfo->displayId && !sGameObjectDisplayInfoStore.LookupEntry(objectInfo->displayId))
return ;
return;
GameObject* object = sObjectMgr->IsGameObjectStaticTransport(objectInfo->entry) ? new StaticTransport() : new GameObject();
uint32 guidLow = sObjectMgr->GenerateLowGuid(HIGHGUID_GAMEOBJECT);
GameObject *object = sObjectMgr->IsGameObjectStaticTransport(objectInfo->entry) ? new StaticTransport() : new GameObject();
ObjectGuid::LowType guidLow = player->GetMap()->GenerateLowGuid<HighGuid::GameObject>();
if (!object->Create(guidLow, objectInfo->entry, player->GetMap(), GetGuildPhase(player), posX, posY, posZ, ori, G3D::Quat(), 0, GO_STATE_READY))
{
@@ -341,13 +381,14 @@ public:
// fill the gameobject data and save to the db
object->SaveToDB(player->GetMapId(), (1 << player->GetMap()->GetSpawnMode()), GetGuildPhase(player));
guidLow = object->GetSpawnId();
// delete the old object and do a clean load from DB with a fresh new GameObject instance.
// this is required to avoid weird behavior and memory leaks
delete object;
object = sObjectMgr->IsGameObjectStaticTransport(objectInfo->entry) ? new StaticTransport() : new GameObject();
// this will generate a new guid if the object is in an instance
if (!object->LoadGameObjectFromDB(guidLow, player->GetMap()))
if (!object->LoadGameObjectFromDB(guidLow, player->GetMap(), true))
{
delete object;
return;
@@ -360,29 +401,29 @@ public:
}
};
class GuildHouseNPCConf : public WorldScript
class GuildHouseButlerConf : public WorldScript
{
public:
GuildHouseNPCConf() : WorldScript("GuildHouseNPCConf") {}
GuildHouseButlerConf() : WorldScript("GuildHouseButlerConf") {}
void OnBeforeConfigLoad(bool /*reload*/) override
{
GuildHouseInnKeeper = sConfigMgr->GetIntDefault("GuildHouseInnKeeper", 1000000);
GuildHouseBank = sConfigMgr->GetIntDefault("GuildHouseBank", 1000000);
GuildHouseMailBox = sConfigMgr->GetIntDefault("GuildHouseMailbox", 500000);
GuildHouseAuctioneer = sConfigMgr->GetIntDefault("GuildHouseAuctioneer", 500000);
GuildHouseTrainer = sConfigMgr->GetIntDefault("GuildHouseTrainerCost", 1000000);
GuildHouseVendor = sConfigMgr->GetIntDefault("GuildHouseVendor", 500000);
GuildHouseObject = sConfigMgr->GetIntDefault("GuildHouseObject", 500000);
GuildHousePortal = sConfigMgr->GetIntDefault("GuildHousePortal", 500000);
GuildHouseProf = sConfigMgr->GetIntDefault("GuildHouseProf", 500000);
GuildHouseSpirit = sConfigMgr->GetIntDefault("GuildHouseSpirit", 100000);
GuildHouseBuyRank = sConfigMgr->GetIntDefault("GuildHouseBuyRank", 0);
GuildHouseInnKeeper = sConfigMgr->GetOption<int32>("GuildHouseInnKeeper", 1000000);
GuildHouseBank = sConfigMgr->GetOption<int32>("GuildHouseBank", 1000000);
GuildHouseMailBox = sConfigMgr->GetOption<int32>("GuildHouseMailbox", 500000);
GuildHouseAuctioneer = sConfigMgr->GetOption<int32>("GuildHouseAuctioneer", 500000);
GuildHouseTrainer = sConfigMgr->GetOption<int32>("GuildHouseTrainerCost", 1000000);
GuildHouseVendor = sConfigMgr->GetOption<int32>("GuildHouseVendor", 500000);
GuildHouseObject = sConfigMgr->GetOption<int32>("GuildHouseObject", 500000);
GuildHousePortal = sConfigMgr->GetOption<int32>("GuildHousePortal", 500000);
GuildHouseProf = sConfigMgr->GetOption<int32>("GuildHouseProf", 500000);
GuildHouseSpirit = sConfigMgr->GetOption<int32>("GuildHouseSpirit", 100000);
GuildHouseBuyRank = sConfigMgr->GetOption<int32>("GuildHouseBuyRank", 4);
}
};
void AddGuildHouseV2NPCScripts()
void AddGuildHouseButlerScripts()
{
new GuildHouseSpawner();
new GuildHouseNPCConf();
new GuildHouseButlerConf();
}