├── 11004 ├── 0001-Bots.patch ├── 0002-Ahbot.patch ├── 0003-Ahbot-Glyphs.patch ├── 0004-AC1.patch ├── 0005-TeleNPC2.patch └── 0006-Wintergrasp.patch ├── 11004-independent ├── 0001-AC1.patch ├── 0001-Ahbot-Glyphs.patch ├── 0001-Ahbot.patch ├── 0001-Telenpc2.patch ├── 0001-Wintergrasp.patch └── 0001-bots.patch ├── 11010-independent ├── 0001-AC1.patch ├── 0001-Ahbot-Glyphs.patch ├── 0001-Ahbot.patch ├── 0001-Telenpc2.patch ├── 0001-Wintergrasp.patch └── 0001-bots.patch ├── 11017-independent └── wintergrasp.patch ├── 11024-independent ├── 0001-ac1.patch ├── 0001-ahbot.patch ├── 0001-ahbot_glyphs.patch ├── 0001-passive_anticheat.patch ├── 0001-telenpc2.patch └── 0001-wintergrasp.patch ├── 11043-independent ├── 0001-ac1.patch ├── 0001-ahbot.patch ├── 0001-ahbot_glyphs.patch ├── 0001-passive_anticheat.patch ├── 0001-telenpc2.patch └── 0001-wintergrasp.patch ├── 11064-independent ├── 0001-ac1.patch ├── 0001-ahbot.patch ├── 0001-ahbot_glyphs.patch ├── 0001-passive_anticheat.patch ├── 0001-telenpc2.patch └── 0001-wintergrasp.patch ├── 11231-independent ├── 0001-ac1.patch ├── 0001-ahbot.patch ├── 0001-ahbot_glyphs.patch ├── 0001-passive_anticheat.patch ├── 0001-telenpc2.patch └── 0001-wintergrasp.patch └── README /11004-independent/0001-Telenpc2.patch: -------------------------------------------------------------------------------- 1 | From fedb4338e49eb9e31fac5ca2b1694b760d512150 Mon Sep 17 00:00:00 2001 2 | From: thedevnull 3 | Date: Wed, 12 Jan 2011 01:09:28 -0200 4 | Subject: [PATCH] Telenpc2 5 | Signed-off-by: thedevnull 6 | 7 | --- 8 | README.NPCTELEPORT | 14 + 9 | sql/tools/setup_npc_teleport.sql | 119 +++++++ 10 | src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp | 373 +++++++++++++++++++++ 11 | src/server/game/AI/ScriptedAI/sc_npc_teleport.h | 151 +++++++++ 12 | src/server/game/Scripting/ScriptLoader.cpp | 6 +- 13 | src/server/game/Scripting/ScriptMgr.cpp | 3 + 14 | src/server/scripts/CMakeLists.txt | 3 + 15 | src/server/scripts/Custom/npc_teleport.cpp | 221 ++++++++++++ 16 | 8 files changed, 889 insertions(+), 1 deletions(-) 17 | create mode 100644 README.NPCTELEPORT 18 | create mode 100644 sql/tools/setup_npc_teleport.sql 19 | create mode 100644 src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp 20 | create mode 100644 src/server/game/AI/ScriptedAI/sc_npc_teleport.h 21 | create mode 100644 src/server/scripts/Custom/npc_teleport.cpp 22 | 23 | diff --git a/README.NPCTELEPORT b/README.NPCTELEPORT 24 | new file mode 100644 25 | index 0000000..015c9c2 26 | --- /dev/null 27 | +++ b/README.NPCTELEPORT 28 | @@ -0,0 +1,14 @@ 29 | +NPC Teleport for Trinity 30 | + 31 | +Original author : Wilibald09 32 | + 33 | +Allows you to add a custom NPC for teleporting, using .npc add 100000. 34 | +The default NPC is entry 100000. 35 | + 36 | +All settings are located in the DB, so you can customize and add destinations, 37 | +set level restrictions and also charge the player for teleporting. 38 | + 39 | +Installation: 40 | + 41 | +Run the query setup_npc_teleport.sql located in the trinity sql directory on 42 | +your world DB. This will setup the DB and you can customize from there. 43 | diff --git a/sql/tools/setup_npc_teleport.sql b/sql/tools/setup_npc_teleport.sql 44 | new file mode 100644 45 | index 0000000..03b9e93 46 | --- /dev/null 47 | +++ b/sql/tools/setup_npc_teleport.sql 48 | @@ -0,0 +1,119 @@ 49 | +DROP TABLE IF EXISTS `custom_npc_tele_category`; 50 | +CREATE TABLE `custom_npc_tele_category` ( 51 | + `id` int(6) unsigned NOT NULL default '0', 52 | + `name` varchar(255) NOT NULL default '', 53 | + `flag` tinyint(3) unsigned NOT NULL default '0', 54 | + `data0` bigint(20) unsigned NOT NULL default '0', 55 | + `data1` int(6) unsigned NOT NULL default '0', 56 | + PRIMARY KEY (`id`) 57 | +) ENGINE=MyISAM DEFAULT CHARSET=utf8; 58 | + 59 | +DROP TABLE IF EXISTS `custom_npc_tele_destination`; 60 | +CREATE TABLE `custom_npc_tele_destination` ( 61 | + `id` int(6) unsigned NOT NULL auto_increment, 62 | + `name` char(100) NOT NULL default '', 63 | + `pos_X` float NOT NULL default '0', 64 | + `pos_Y` float NOT NULL default '0', 65 | + `pos_Z` float NOT NULL default '0', 66 | + `map` smallint(5) unsigned NOT NULL default '0', 67 | + `orientation` float NOT NULL default '0', 68 | + `level` tinyint(3) unsigned NOT NULL default '0', 69 | + `cost` int(10) unsigned NOT NULL default '0', 70 | + PRIMARY KEY (`id`) 71 | +) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 72 | + 73 | +DROP TABLE IF EXISTS `custom_npc_tele_association`; 74 | +CREATE TABLE `custom_npc_tele_association` ( 75 | + `cat_id` int(6) unsigned NOT NULL default '0', 76 | + `dest_id` int(6) unsigned NOT NULL default '0', 77 | + PRIMARY KEY (`cat_id`, `dest_id`) 78 | +) ENGINE=MyISAM DEFAULT CHARSET=utf8; 79 | + 80 | +TRUNCATE `custom_npc_tele_category`; 81 | +INSERT INTO `custom_npc_tele_category` 82 | + (`id`, `name`, `flag`, `data0`, `data1`) 83 | +VALUES 84 | + (1, 'Cities', 0, 1, 0), 85 | + (2, 'Cities', 0, 2, 0), 86 | + (3, 'Battlegrounds', 0, 1, 0), 87 | + (4, 'Battlegrounds', 0, 2, 0), 88 | + (5, 'Arenas', 0, 0, 0), 89 | + (6, '[Instances Lvl 1-60]', 0, 0, 0), 90 | + (7, '[Instances Lvl 60+]', 5, 60, 0), 91 | + (8, '[Instances Lvl 70+]', 5, 70, 0), 92 | + (9, 'Destinations MJ', 3, 0, 0); 93 | + 94 | +TRUNCATE `custom_npc_tele_destination`; 95 | +INSERT INTO `custom_npc_tele_destination` 96 | + (`id`, `name`, `pos_X`, `pos_Y`, `pos_Z`, `map`, `orientation`, `level`, `cost`) 97 | +VALUES 98 | + (1, 'Alterac Valley', 883.187, -489.375, 96.7618, 30, 3.06932, 0, 0), 99 | + (2, 'Alterac Valley', -818.155, -623.043, 54.0884, 30, 2.1, 0, 0), 100 | + (3, 'Arathi Basin', 686.053, 683.165, -12.9149, 529, 0.18, 0, 0), 101 | + (4, 'Arathi Basin', 1308.68, 1306.03, -9.0107, 529, 3.91285, 0, 0), 102 | + (5, 'Black Temple', -3610.72, 324.988, 37.4, 530, 3.28298, 0, 0), 103 | + (6, 'Blackfathom Deeps', 4254.58, 664.74, -29.04, 1, 1.97, 0, 0), 104 | + (7, 'Blackrock Depths', -7301.03, -913.19, 165.37, 0, 0.08, 0, 0), 105 | + (8, 'Blackrock Spire', -7535.43, -1212.04, 285.45, 0, 5.29, 0, 0), 106 | + (9, 'Blackwing Lair', -7665.55, -1102.49, 400.679, 469, 0, 0, 0), 107 | + (10, 'Caverns of Time', -8173.66, -4746.36, 33.8423, 1, 4.93989, 0, 0), 108 | + (11, 'Circle of Blood', 2839.44, 5930.17, 11.1002, 530, 3.16284, 0, 0), 109 | + (12, 'Coilfang Reservoir', 517.288, 6976.28, 32.0072, 530, 0, 0, 0), 110 | + (13, 'Darnassus', 9947.52, 2482.73, 1316.21, 1, 0, 0, 0), 111 | + (14, 'Dire Maul', -3982.47, 1127.79, 161.02, 1, 0.05, 0, 0), 112 | + (15, 'Exodar', -4073.03, -12020.4, -1.47, 530, 0, 0, 0), 113 | + (16, 'Eye of the Storm', 2487.72, 1609.12, 1224.64, 566, 3.35671, 0, 0), 114 | + (17, 'Eye of the Storm', 1843.73, 1529.77, 1224.43, 566, 0.297579, 0, 0), 115 | + (18, 'Goldshire', -9464, 62, 56, 0, 0, 0, 0), 116 | + (19, 'Gruul\'s Lair', 3539.01, 5082.36, 1.69107, 530, 0, 0, 0), 117 | + (20, 'Gurubashi', -13261.3, 168.294, 35.0792, 0, 1.00688, 0, 0), 118 | + (21, 'Hellfire Citadel', -305.816, 3056.4, -2.47318, 530, 2.01, 0, 0), 119 | + (22, 'Ironforge', -4924.07, -951.95, 501.55, 0, 5.4, 0, 0), 120 | + (23, 'Isle Of Quel\'Danas', 12947.4, -6893.31, 5.68398, 530, 3.09154, 0, 0), 121 | + (24, 'Karazhan', -11118.8, -2010.84, 47.0807, 0, 0, 0, 0), 122 | + (25, 'Maraudon', -1433.33, 2955.34, 96.21, 1, 4.82, 0, 0), 123 | + (26, 'Molten Core', 1121.45, -454.317, -101.33, 230, 3.5, 0, 0), 124 | + (27, 'Naxxramas', 3125.18, -3748.02, 136.049, 0, 0, 0, 0), 125 | + (28, 'Onyxia\'s Lair', -4707.44, -3726.82, 54.6723, 1, 3.8, 0, 0), 126 | + (29, 'Orgrimmar', 1552.5, -4420.66, 8.94802, 1, 0, 0, 0), 127 | + (30, 'Razor Hill', 315.721, -4743.4, 10.4867, 1, 0, 0, 0), 128 | + (31, 'Razorfen Downs', -4645.08, -2470.85, 85.53, 1, 4.39, 0, 0), 129 | + (32, 'Razorfen Kraul', -4484.04, -1739.4, 86.47, 1, 1.23, 0, 0), 130 | + (33, 'Ring of Trials', -1999.94, 6581.71, 11.32, 530, 2.3, 0, 0), 131 | + (34, 'Ruins of Ahn\'Qiraj', -8409.03, 1498.83, 27.3615, 1, 2.49757, 0, 0), 132 | + (35, 'Scholomance', 1219.01, -2604.66, 85.61, 0, 0.5, 0, 0), 133 | + (36, 'Shadowfang Keep', -254.47, 1524.68, 76.89, 0, 1.56, 0, 0), 134 | + (37, 'Shattrath City', -1850.21, 5435.82, -10.9614, 530, 3.40391, 0, 0), 135 | + (38, 'Silvermoon', 9338.74, -7277.27, 13.7895, 530, 0, 0, 0), 136 | + (39, 'Stormwind', -8960.14, 516.266, 96.3568, 0, 0, 0, 0), 137 | + (40, 'Stratholme', 3263.54, -3379.46, 143.59, 0, 0, 0, 0), 138 | + (41, 'Tempest Keep', 3089.58, 1399.05, 187.653, 530, 4.79407, 0, 0), 139 | + (42, 'Temple of Ahn\'Qiraj', -8245.84, 1983.74, 129.072, 1, 0.936195, 0, 0), 140 | + (43, 'The Deadmines', -11212, 1658.58, 25.67, 0, 1.45, 0, 0), 141 | + (44, 'The Maul', -3761.49, 1133.43, 132.083, 1, 4.57259, 0, 0), 142 | + (45, 'The Scarlet Monastery', 2843.89, -693.74, 139.32, 0, 5.11, 0, 0), 143 | + (46, 'The Sunken Temple', -10346.9, -3851.9, -43.41, 0, 6.09, 0, 0), 144 | + (47, 'The Wailing Caverns', -722.53, -2226.3, 16.94, 1, 2.71, 0, 0), 145 | + (48, 'Thunder Bluff', -1290, 147.034, 129.682, 1, 4.919, 0, 0), 146 | + (49, 'Uldaman', -6119.7, -2957.3, 204.11, 0, 0.03, 0, 0), 147 | + (50, 'Undercity', 1819.71, 238.79, 60.5321, 0, 0, 0, 0), 148 | + (51, 'Warsong Gulch', 930.851, 1431.57, 345.537, 489, 0.015704, 0, 0), 149 | + (52, 'Warsong Gulch', 1525.95, 1481.66, 352.001, 489, 3.20756, 0, 0), 150 | + (53, 'Zul\'Aman', 6846.95, -7954.5, 170.028, 530, 4.61501, 0, 0), 151 | + (54, 'Zul\'Farrak', -6839.39, -2911.03, 8.87, 1, 0.41, 0, 0), 152 | + (55, 'Zul\'Gurub', -11916.7, -1212.82, 92.2868, 0, 4.6095, 0, 0), 153 | + (56, 'Ile des MJ', 16254, 16276.9, 14.5082, 1, 1.70269, 0, 0); 154 | + 155 | +TRUNCATE `custom_npc_tele_association`; 156 | +INSERT INTO `custom_npc_tele_association` 157 | + (`cat_id`, `dest_id`) 158 | +VALUES 159 | + (1, 13), (1, 15), (1, 18), (1, 22), (1, 23), (1, 37), (1, 39), (2, 23), (2, 29), (2, 30), (2, 37), (2, 38), (2, 48), (2, 50), (3, 1), (3, 4), (3, 16), (3, 52), (4, 2), (4, 3), (4, 17), (4, 51), (5, 11), (5, 20), (5, 33), (5, 44), (6, 6), (6, 7), (6, 8), (6, 14), (6, 25), (6, 31), (6, 32), (6, 35), (6, 36), (6, 40), (6, 43), (6, 45), (6, 46), (6, 47), (6, 49), (6, 54), (7, 9), (7, 26), (7, 27), (7, 28), (7, 34), (7, 42), (7, 55), (8, 5), (8, 10), (8, 12), (8, 19), (8, 21), (8, 24), (8, 41), (8, 53), (9, 56); 160 | + 161 | +-- `npc_text` 162 | +REPLACE INTO `npc_text` (`ID`, `text0_0`) VALUES 163 | + (100000, 'Choose your Category.'), 164 | + (100001, 'Choose your Destination.'); 165 | + 166 | +-- `creature_template` 167 | +INSERT INTO `creature_template` VALUES (100000, 0, 0, 0, 0, 0, 26502, 0, 0, 0, 'Abisal Vortex', '', '', 0, 83, 83, 0, 35, 35, 1, 1, 1.14286, 2, 1, 509, 683, 0, 805, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 371, 535, 135, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 'npc_teleport', 1); 168 | diff --git a/src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp b/src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp 169 | new file mode 100644 170 | index 0000000..c40d861 171 | --- /dev/null 172 | +++ b/src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp 173 | @@ -0,0 +1,373 @@ 174 | +/** 175 | + * 176 | + * @File : sc_npc_teleport.cpp 177 | + * 178 | + * @Authors : Wilibald09 179 | + * 180 | + * @Date : 28/08/2008 181 | + * 182 | + * @Version : 1.2 183 | + * 184 | + **/ 185 | + 186 | + 187 | +#include "ScriptPCH.h" 188 | +#include "sc_npc_teleport.h" 189 | + 190 | +#define TELE nsNpcTel::CatDest 191 | +#define PAGE nsNpcTel::Page 192 | +#define PAGEI PAGE::Instance 193 | + 194 | + 195 | +nsNpcTel::VCatDest nsNpcTel::TabCatDest; 196 | + 197 | + 198 | +uint32 PAGE::operator [] (Player * const player) const 199 | +{ 200 | + for (VInst_t i(0); i < m_TabInstance.size(); ++i) 201 | + { 202 | + if (m_TabInstance[i].GetPlayer() == player) 203 | + return m_TabInstance[i].GetPageId(); 204 | + } 205 | + return 0; 206 | +} 207 | + 208 | +PAGE::Instance & PAGE::operator () (Player * const player) 209 | +{ 210 | + for (VInst_t i(0); i < m_TabInstance.size(); ++i) 211 | + { 212 | + if (m_TabInstance[i].GetPlayer() == player) 213 | + return m_TabInstance[i]; 214 | + } 215 | + m_TabInstance.push_back(Instance(player)); 216 | + return m_TabInstance.back(); 217 | +} 218 | + 219 | +PAGE::Instance & PAGEI::operator = (const uint32 &id) 220 | +{ 221 | + m_PageId = id; 222 | + return *this; 223 | +} 224 | + 225 | +PAGE::Instance & PAGEI::operator ++ (void) 226 | +{ 227 | + ++m_PageId; 228 | + return *this; 229 | +} 230 | + 231 | +PAGE::Instance PAGEI::operator ++ (int32) 232 | +{ 233 | + Instance tmp (*this); 234 | + ++m_PageId; 235 | + return tmp; 236 | +} 237 | + 238 | +PAGE::Instance & PAGEI::operator -- (void) 239 | +{ 240 | + --m_PageId; 241 | + return *this; 242 | +} 243 | + 244 | +PAGE::Instance PAGEI::operator -- (int32) 245 | +{ 246 | + Instance tmp (*this); 247 | + --m_PageId; 248 | + return tmp; 249 | +} 250 | + 251 | +TELE::CatDest(const uint32 &id, const std::string &name, 252 | + const Flag &flag, const uint64 &data0, const uint32 &data1) 253 | + : m_id(id), m_name(name), m_flag(flag), m_data0(data0), m_data1(data1) 254 | +{ 255 | + m_TabDest.clear(); 256 | +} 257 | + 258 | +std::string TELE::GetName(const bool IsGM /* = false */) const 259 | +{ 260 | + if (!IsGM || m_flag != FLAG_TEAM) 261 | + return m_name; 262 | + 263 | + switch (m_data0) 264 | + { 265 | + case TEAM_HORDE: return std::string(m_name + " (H)"); 266 | + case TEAM_ALLIANCE: return std::string(m_name + " (A)"); 267 | + } 268 | + return m_name; 269 | +} 270 | + 271 | +bool TELE::IsAllowedToTeleport(Player * const player) const 272 | +{ 273 | + if (player->isGameMaster()) 274 | + { 275 | + if (m_flag == FLAG_GMLEVEL) 276 | + return player->GetSession()->GetSecurity() >= m_data0; 277 | + return true; 278 | + } 279 | + 280 | + switch (m_flag) 281 | + { 282 | + case FLAG_TEAM: 283 | + switch (m_data0) 284 | + { 285 | + case TEAM_HORDE: return player->GetTeam() == HORDE; 286 | + case TEAM_ALLIANCE: return player->GetTeam() == ALLIANCE; 287 | + case TEAM_ALL: return true; 288 | + } 289 | + 290 | + case FLAG_GUILD: 291 | + return player->GetGuildId() == m_data0; 292 | + 293 | + case FLAG_GMLEVEL: 294 | + return player->GetSession()->GetSecurity() >= m_data0; 295 | + 296 | + case FLAG_ISGM: 297 | + return player->isGameMaster(); 298 | + 299 | + case FLAG_ACCOUNT: 300 | + return player->GetSession()->GetAccountId() == m_data0; 301 | + 302 | + case FLAG_LEVEL: 303 | + return player->getLevel() >= m_data0; 304 | + 305 | + case FLAG_ITEM: 306 | + return player->HasItemCount(m_data0, m_data1, true); 307 | + 308 | + case FLAG_QUEST: 309 | + if (m_data1 < MAX_QUEST_STATUS) 310 | + return player->GetQuestStatus(m_data0) == m_data1; 311 | + return player->GetQuestRewardStatus(m_data0); 312 | + 313 | + case FLAG_GENDER: 314 | + return player->getGender() == m_data0; 315 | + 316 | + case FLAG_RACE: 317 | + return player->getRace() == m_data0; 318 | + 319 | + case FLAG_CLASS: 320 | + return player->getClass() == m_data0; 321 | + 322 | + case FLAG_REPUTATION: 323 | + return player->GetReputationRank(m_data0) >= m_data1; 324 | + 325 | + case FLAG_PLAYER: 326 | + return player->GetGUID() == m_data0; 327 | + } 328 | + 329 | + sLog->outError("Invalid flag (category: %u). Important problem...", GetCatID()); 330 | + return false; 331 | +} 332 | + 333 | +uint32 TELE::CountOfCategoryAllowedBy(Player * const player) 334 | +{ 335 | + uint32 count (0); 336 | + for (VCatDest_t i(0); i < TabCatDest.size(); ++i) 337 | + { 338 | + if (TabCatDest[i].IsAllowedToTeleport(player)) 339 | + ++count; 340 | + } 341 | + return count; 342 | +} 343 | + 344 | +bool nsNpcTel::IsValidData(const uint32 &cat, const Flag &flag, 345 | + const uint64 &data0, const uint32 &data1) 346 | +{ 347 | + switch(flag) 348 | + { 349 | + case FLAG_TEAM: 350 | + if (data1) 351 | + sLog->outError("Invalid data1 (category: %u).", cat); 352 | + if (data0 < MAX_FLAG_TEAM) 353 | + return true; 354 | + sLog->outError("Invalid data0 (Team) (category: %u).", cat); 355 | + return false; 356 | + 357 | + case FLAG_GUILD: 358 | + if (data1) 359 | + sLog->outError("Invalid data1 (category: %u).", cat); 360 | + if (data0) 361 | + return true; 362 | + sLog->outError("Invalid data0 (GuildID) (category: %u).", cat); 363 | + return false; 364 | + 365 | + case FLAG_GMLEVEL: 366 | + if (data1) 367 | + sLog->outError("Invalid data1 (category: %u).", cat); 368 | + if (0 < data0 && data0 < 256) 369 | + return true; 370 | + sLog->outError("Invalid data0 (GmLevel) (category: %u).", cat); 371 | + return false; 372 | + 373 | + case FLAG_ISGM: 374 | + if (data0) 375 | + sLog->outError("Invalid data0 (category: %u).", cat); 376 | + if (data1) 377 | + sLog->outError("Invalid data1 (category: %u).", cat); 378 | + return true; 379 | + 380 | + case FLAG_ACCOUNT: 381 | + if (data1) 382 | + sLog->outError("Invalid data1 (category: %u).", cat); 383 | + if (data0) 384 | + return true; 385 | + sLog->outError("Invalid data0 (AccountID) (category: %u).", cat); 386 | + return false; 387 | + 388 | + case FLAG_LEVEL: 389 | + if (data1) 390 | + sLog->outError("Invalid data1 (category: %u).", cat); 391 | + if (0 < data0 && data0 < 256) 392 | + return true; 393 | + sLog->outError("Invalid data0 (Level) (category: %u).", cat); 394 | + return false; 395 | + 396 | + case FLAG_ITEM: 397 | + if (!data0) 398 | + { 399 | + sLog->outError("Invalid data0 (ItemID) (category: %u).", cat); 400 | + return false; 401 | + } 402 | + if (data1) 403 | + return true; 404 | + sLog->outError("Invalid data1 (Item Count) (category: %u).", cat); 405 | + return false; 406 | + 407 | + case FLAG_QUEST: 408 | + if (!data0) 409 | + { 410 | + sLog->outError("Invalid data0 (QuestID) (category: %u).", cat); 411 | + return false; 412 | + } 413 | + if (data1 < MAX_QUEST_STATUS + 1) 414 | + return true; 415 | + sLog->outError("Invalid data1 (Quest Status) (category: %u).", cat); 416 | + return false; 417 | + 418 | + case FLAG_GENDER: 419 | + if (data1) 420 | + sLog->outError("Invalid data1 (category: %u).", cat); 421 | + if (data0 < GENDER_NONE) 422 | + return true; 423 | + sLog->outError("Invalid data0 (Gender) (category: %u).", cat); 424 | + return false; 425 | + 426 | + case FLAG_RACE: 427 | + if (data1) 428 | + sLog->outError("Invalid data1 (category: %u).", cat); 429 | + if (0 < data0 && data0 < MAX_RACES) 430 | + return true; 431 | + sLog->outError("Invalid data0 (Race) (category: %u).", cat); 432 | + return false; 433 | + 434 | + case FLAG_CLASS: 435 | + if (data1) 436 | + sLog->outError("Invalid data1 (category: %u).", cat); 437 | + if (0 < data0 && data0 < MAX_CLASSES) 438 | + return true; 439 | + sLog->outError("Invalid data0 (Class) (category: %u).", cat); 440 | + return false; 441 | + 442 | + case FLAG_REPUTATION: 443 | + if (!data0) 444 | + { 445 | + sLog->outError("Invalid data0 (Faction/Reputation) (category: %u).", cat); 446 | + return false; 447 | + } 448 | + if (data1 <= REP_EXALTED) 449 | + return true; 450 | + sLog->outError("Invalid data1 (Faction/Reputation) (category: %u).", cat); 451 | + return false; 452 | + 453 | + case FLAG_PLAYER: 454 | + if (data1) 455 | + sLog->outError("Invalid data1 (category: %u).", cat); 456 | + if (data0) 457 | + return true; 458 | + sLog->outError("Invalid data0 (PlayerGuid) (category: %u).", cat); 459 | + return false; 460 | + } 461 | + 462 | + sLog->outError("Invalid flag (category: %u).", cat); 463 | + return false; 464 | +} 465 | + 466 | +void LoadNpcTele(void) 467 | +{ 468 | + const char *Table[] = 469 | + { 470 | + "custom_npc_tele_category", 471 | + "custom_npc_tele_destination", 472 | + "custom_npc_tele_association", 473 | + }; 474 | + 475 | + 476 | + QueryResult result = WorldDatabase.PQuery( 477 | + "SELECT `flag`, `data0`, `data1`, `cat_id`, C.`name` `namecat`, D.`name` `namedest`, " 478 | + // 0 1 2 3 4 5 479 | + "`pos_X`, `pos_Y`, `pos_Z`, `orientation`, `map`, `level`, `cost` " 480 | + // 6 7 8 9 10 11 12 481 | + "FROM `%s` C, `%s` D, `%s` A " 482 | + "WHERE C.`id` = `cat_id` AND D.`id` = `dest_id` " 483 | + "ORDER BY `namecat`, `cat_id`, `namedest`", Table[0], Table[1], Table[2]); 484 | + 485 | + nsNpcTel::TabCatDest.clear(); 486 | + 487 | + if (result) 488 | + { 489 | + sLog->outString( "TSCR: Loading %s, %s and %s...", Table[0], Table[1], Table[2]); 490 | + 491 | + uint32 catid = 0; 492 | + uint32 nbDest = 0; 493 | + bool IsValidCat = true; 494 | + bool FirstTime = true; 495 | + 496 | + do 497 | + { 498 | + Field *fields = result->Fetch(); 499 | + 500 | + if (!IsValidCat && catid == fields[3].GetUInt32() && !FirstTime) 501 | + continue; 502 | + 503 | + IsValidCat = true; 504 | + FirstTime = false; 505 | + 506 | + if (!nsNpcTel::IsValidData(fields[3].GetUInt32(), (nsNpcTel::Flag)fields[0].GetUInt8(), 507 | + fields[1].GetUInt64(), fields[2].GetUInt32())) 508 | + { 509 | + IsValidCat = false; 510 | + catid = fields[3].GetUInt32(); 511 | + continue; 512 | + } 513 | + 514 | + if (catid != fields[3].GetUInt32()) 515 | + { 516 | + catid = fields[3].GetUInt32(); 517 | + nsNpcTel::CatDest categorie (catid, fields[4].GetString(), (nsNpcTel::Flag)fields[0].GetUInt8(), 518 | + fields[1].GetUInt64(), fields[2].GetUInt32()); 519 | + nsNpcTel::TabCatDest.push_back(categorie); 520 | + } 521 | + 522 | + nsNpcTel::Dest item = 523 | + { 524 | + fields[5].GetString(), // Name 525 | + fields[6].GetFloat(), // X 526 | + fields[7].GetFloat(), // Y 527 | + fields[8].GetFloat(), // Z 528 | + fields[9].GetFloat(), // Orientation 529 | + fields[10].GetUInt16(), // Map 530 | + fields[11].GetUInt8(), // Level 531 | + fields[12].GetUInt32(), // Cost 532 | + }; 533 | + 534 | + nsNpcTel::TabCatDest.back().AddDest(item); 535 | + ++nbDest; 536 | + } while (result->NextRow()); 537 | + 538 | + sLog->outString(""); 539 | + sLog->outString("TSCR: >> Loaded %u npc_teleport.", nbDest); 540 | + } else sLog->outString("TSCR: WARNING >> Loaded 0 npc_teleport."); 541 | +} 542 | + 543 | + 544 | +#undef TELE 545 | +#undef PAGE 546 | +#undef PAGEI 547 | diff --git a/src/server/game/AI/ScriptedAI/sc_npc_teleport.h b/src/server/game/AI/ScriptedAI/sc_npc_teleport.h 548 | new file mode 100644 549 | index 0000000..4830245 550 | --- /dev/null 551 | +++ b/src/server/game/AI/ScriptedAI/sc_npc_teleport.h 552 | @@ -0,0 +1,151 @@ 553 | +/** 554 | + * 555 | + * @File : sc_npc_teleport.h 556 | + * 557 | + * @Authors : Wilibald09 558 | + * 559 | + * @Date : 19/08/2008 560 | + * 561 | + * @Version : 1.2 562 | + * 563 | + **/ 564 | + 565 | + 566 | +#ifndef SC_NPC_TELEPORT_H 567 | +#define SC_NPC_TELEPORT_H 568 | + 569 | +#include 570 | + 571 | + 572 | +namespace nsNpcTel 573 | +{ 574 | + // Different types of permissions 575 | + enum Flag 576 | + { 577 | + FLAG_TEAM = 0, 578 | + FLAG_GUILD = 1, 579 | + FLAG_GMLEVEL = 2, 580 | + FLAG_ISGM = 3, 581 | + FLAG_ACCOUNT = 4, 582 | + FLAG_LEVEL = 5, 583 | + FLAG_ITEM = 6, 584 | + FLAG_QUEST = 7, 585 | + FLAG_GENDER = 8, 586 | + FLAG_RACE = 9, 587 | + FLAG_CLASS = 10, 588 | + FLAG_REPUTATION = 11, 589 | + FLAG_PLAYER = 12, 590 | + MAX_FLAG, 591 | + }; 592 | + 593 | + // Different parameters of FLAG_TEAM 594 | + enum 595 | + { 596 | + TEAM_ALL = 0, 597 | + TEAM_ALLIANCE = 1, 598 | + TEAM_HORDE = 2, 599 | + MAX_FLAG_TEAM, 600 | + }; 601 | + 602 | + // Structure representing the destinations 603 | + struct Dest 604 | + { 605 | + std::string m_name; 606 | + float m_X, m_Y, m_Z, m_orient; 607 | + uint16 m_map; 608 | + uint8 m_level; 609 | + uint32 m_cost; 610 | + }; 611 | + 612 | + // Class representing the categories of destinations 613 | + class CatDest 614 | + { 615 | + public: 616 | + 617 | + typedef std::vector VDest; 618 | + typedef VDest::size_type VDest_t; 619 | + 620 | + CatDest(const uint32 &id, const std::string &name, 621 | + const Flag &flag, const uint64 &data0, const uint32 &data1); 622 | + 623 | + void AddDest (const Dest &item) { m_TabDest.push_back(item); } 624 | + Dest GetDest (const uint32 &id) const { return m_TabDest[id]; } 625 | + uint32 GetCatID (void) const { return m_id; } 626 | + uint32 size (void) const { return m_TabDest.size(); } 627 | + 628 | + std::string GetName(const bool IsGM = false) const; 629 | + bool IsAllowedToTeleport(Player * const player) const; 630 | + 631 | + static uint32 CountOfCategoryAllowedBy(Player * const player); 632 | + 633 | + private: 634 | + 635 | + uint32 m_id; 636 | + std::string m_name; 637 | + Flag m_flag; 638 | + uint64 m_data0; 639 | + uint32 m_data1; 640 | + VDest m_TabDest; 641 | + }; 642 | + 643 | + // Class page for current player 644 | + class Page 645 | + { 646 | + protected: 647 | + 648 | + // Class instance for current player 649 | + class Instance 650 | + { 651 | + public: 652 | + 653 | + Instance(Player * const player, const uint32 &PageId = 0) 654 | + : m_player(player), m_PageId(PageId) {} 655 | + 656 | + Instance & operator = (const uint32 &id); 657 | + Instance & operator ++ (void); 658 | + Instance operator ++ (int32); 659 | + Instance & operator -- (void); 660 | + Instance operator -- (int32); 661 | + 662 | + uint32 GetPageId(void) const { return m_PageId; } 663 | + Player * GetPlayer(void) const { return m_player; } 664 | + 665 | + private: 666 | + 667 | + Player *m_player; 668 | + uint32 m_PageId; 669 | + }; 670 | + 671 | + 672 | + public: 673 | + 674 | + typedef std::vector VInst; 675 | + typedef VInst::size_type VInst_t; 676 | + 677 | + Page(void) { m_TabInstance.clear(); } 678 | + 679 | + Instance & operator () (Player * const player); 680 | + uint32 operator [] (Player * const player) const; 681 | + 682 | + 683 | + private: 684 | + 685 | + VInst m_TabInstance; 686 | + }; 687 | + 688 | + typedef std::vector VCatDest; 689 | + typedef VCatDest::size_type VCatDest_t; 690 | + 691 | + // Verification of data integrity 692 | + bool IsValidData(const uint32 &cat, const Flag &flag, 693 | + const uint64 &data0, const uint32 &data1); 694 | + 695 | + extern VCatDest TabCatDest; 696 | +} 697 | + 698 | +// Loading contents of database 699 | +void LoadNpcTele(void); 700 | + 701 | +extern WorldDatabaseWorkerPool WorldDatabase; 702 | + 703 | +#endif 704 | diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp 705 | index 794bb10..8dcac68 100755 706 | --- a/src/server/game/Scripting/ScriptLoader.cpp 707 | +++ b/src/server/game/Scripting/ScriptLoader.cpp 708 | @@ -25,6 +25,9 @@ void AddSC_example_gossip_codebox(); 709 | void AddSC_example_misc(); 710 | void AddSC_example_commandscript(); 711 | 712 | +//TeleNPC2 713 | +void AddSC_npc_teleport(); 714 | + 715 | // spells 716 | void AddSC_deathknight_spell_scripts(); 717 | void AddSC_druid_spell_scripts(); 718 | @@ -1202,6 +1205,7 @@ void AddCustomScripts() 719 | { 720 | #ifdef SCRIPTS 721 | /* This is where custom scripts should be added. */ 722 | - 723 | + //TeleNPC2 724 | + AddSC_npc_teleport(); 725 | #endif 726 | } 727 | diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp 728 | index a0a1c82..66ce84b 100755 729 | --- a/src/server/game/Scripting/ScriptMgr.cpp 730 | +++ b/src/server/game/Scripting/ScriptMgr.cpp 731 | @@ -25,6 +25,7 @@ 732 | #include "ScriptLoader.h" 733 | #include "ScriptSystem.h" 734 | #include "Transport.h" 735 | +#include "sc_npc_teleport.h" 736 | 737 | // Utility macros to refer to the script registry. 738 | #define SCR_REG_MAP(T) ScriptRegistry::ScriptMap 739 | @@ -180,6 +181,8 @@ void ScriptMgr::Initialize() 740 | uint32 oldMSTime = getMSTime(); 741 | 742 | LoadDatabase(); 743 | + // Load TeleNPC2 - maybe not the best place to load it ... 744 | + LoadNpcTele(); 745 | 746 | sLog->outString("Loading C++ scripts"); 747 | 748 | diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt 749 | index 17d4bfc..90eae34 100644 750 | --- a/src/server/scripts/CMakeLists.txt 751 | +++ b/src/server/scripts/CMakeLists.txt 752 | @@ -31,6 +31,9 @@ include(Examples/CMakeLists.txt) 753 | 754 | set(scripts_STAT_SRCS 755 | ${scripts_STAT_SRCS} 756 | + Custom/npc_teleport.cpp 757 | + ../game/AI/ScriptedAI/sc_npc_teleport.cpp 758 | + ../game/AI/ScriptedAI/sc_npc_teleport.h 759 | ../game/AI/ScriptedAI/ScriptedEscortAI.cpp 760 | ../game/AI/ScriptedAI/ScriptedCreature.cpp 761 | ../game/AI/ScriptedAI/ScriptedFollowerAI.cpp 762 | diff --git a/src/server/scripts/Custom/npc_teleport.cpp b/src/server/scripts/Custom/npc_teleport.cpp 763 | new file mode 100644 764 | index 0000000..1e51336 765 | --- /dev/null 766 | +++ b/src/server/scripts/Custom/npc_teleport.cpp 767 | @@ -0,0 +1,221 @@ 768 | +/** 769 | + * 770 | + * @File : npc_teleport.cpp 771 | + * 772 | + * @Authors : Wilibald09 773 | + * 774 | + * @Date : 19/08/2008 775 | + * 776 | + * @Version : 1.2 777 | + * 778 | + **/ 779 | + 780 | + 781 | + 782 | +#include "ScriptPCH.h" 783 | +#include "sc_npc_teleport.h" 784 | +#include 785 | + 786 | +#define GOSSIP_SHOW_DEST 1000 787 | +#define GOSSIP_TELEPORT 1001 788 | +#define GOSSIP_NEXT_PAGEC 1002 789 | +#define GOSSIP_PREV_PAGEC 1003 790 | +#define GOSSIP_NEXT_PAGED 1004 791 | +#define GOSSIP_PREV_PAGED 1005 792 | +#define GOSSIP_MAIN_MENU 1006 793 | + 794 | +#define SPELL_ID_PASSIVE_RESURRECTION_SICKNESS 15007 795 | +#define SPELL_VISUAL_TELEPORT 35517 796 | + 797 | +#define NB_ITEM_PAGE 10 798 | +#define MSG_CAT 100000 799 | +#define MSG_DEST 100001 800 | + 801 | +#define NEXT_PAGE "-> [Next Page]" 802 | +#define PREV_PAGE "<- [Previous Page]" 803 | +#define MAIN_MENU "<= [Main Menu]" 804 | + 805 | + 806 | +using namespace nsNpcTel; 807 | + 808 | + 809 | +namespace 810 | +{ 811 | + Page PageC, PageD; 812 | + Page Cat; 813 | + 814 | + // Conversion function int->string 815 | + std::string ConvertStr(const int64 &val) 816 | + { 817 | + std::ostringstream ostr; 818 | + ostr << val; 819 | + return ostr.str(); 820 | + } 821 | + 822 | + // Conversion function intMoney->stringMoney 823 | + std::string ConvertMoney(const uint32 &Money) 824 | + { 825 | + std::string Str(ConvertStr(Money)); 826 | + uint32 SizeStr = Str.length(); 827 | + 828 | + if (SizeStr > 4) 829 | + Str = Str.insert(Str.length()-4, "po"); 830 | + if (SizeStr > 2) 831 | + Str = Str.insert(Str.length()-2, "pa"); 832 | + Str += "pc"; 833 | + 834 | + return Str; 835 | + } 836 | + 837 | + // Teleport Player 838 | + void Teleport(Player * const player, const uint16 &map, 839 | + const float &X, const float &Y, const float &Z, const float &orient) 840 | + { 841 | + player->CastSpell(player, SPELL_VISUAL_TELEPORT, true); 842 | + player->TeleportTo(map, X, Y, Z, orient); 843 | + } 844 | + 845 | + // Display categories 846 | + void AffichCat(Player * const player, Creature * const creature) 847 | + { 848 | + if (PageC[player] > 0) 849 | + player->ADD_GOSSIP_ITEM(7, PREV_PAGE, GOSSIP_PREV_PAGEC, 0); 850 | + 851 | + VCatDest_t i (PageC[player] * NB_ITEM_PAGE); 852 | + for ( ; i < TabCatDest.size() && i < (NB_ITEM_PAGE * (PageC[player] + 1)); ++i) 853 | + { 854 | + if (TabCatDest[i].IsAllowedToTeleport(player)) 855 | + player->ADD_GOSSIP_ITEM(7, TabCatDest[i].GetName(player->isGameMaster()).c_str(), GOSSIP_SHOW_DEST, i); 856 | + } 857 | + 858 | + if (i < TabCatDest.size()) 859 | + player->ADD_GOSSIP_ITEM(7, NEXT_PAGE, GOSSIP_NEXT_PAGEC, 0); 860 | + 861 | + player->SEND_GOSSIP_MENU(MSG_CAT, creature->GetGUID()); 862 | + } 863 | + 864 | + // Display destination categories 865 | + void AffichDest(Player * const player, Creature * const creature) 866 | + { 867 | + if (PageD[player] > 0) 868 | + player->ADD_GOSSIP_ITEM(7, PREV_PAGE, GOSSIP_PREV_PAGED, 0); 869 | + 870 | + CatDest::VDest_t i (PageD[player] * NB_ITEM_PAGE); 871 | + for ( ; i < TabCatDest[Cat[player]].size() && i < (NB_ITEM_PAGE * (PageD[player] + 1)); ++i) 872 | + { 873 | + player->ADD_GOSSIP_ITEM(5, TabCatDest[Cat[player]].GetDest(i).m_name.c_str(), GOSSIP_TELEPORT, i); 874 | + } 875 | + 876 | + if (i < TabCatDest[Cat[player]].size()) 877 | + player->ADD_GOSSIP_ITEM(7, NEXT_PAGE, GOSSIP_NEXT_PAGED, 0); 878 | + 879 | + if (CatDest::CountOfCategoryAllowedBy(player) > 1) 880 | + player->ADD_GOSSIP_ITEM(7, MAIN_MENU, GOSSIP_MAIN_MENU, 0); 881 | + 882 | + player->SEND_GOSSIP_MENU(MSG_DEST, creature->GetGUID()); 883 | + } 884 | + 885 | + // Verification before teleportation 886 | + void ActionTeleport(Player * const player, Creature * const creature, const uint32 &id) 887 | + { 888 | + Dest dest (TabCatDest[Cat[player]].GetDest(id)); 889 | + 890 | + if (player->getLevel() < dest.m_level && !player->isGameMaster()) 891 | + { 892 | + std::string msg ("You do not have the required level. This destination requires level " + ConvertStr(dest.m_level) + "."); 893 | + creature->MonsterWhisper(msg.c_str(), player->GetGUID()); 894 | + return; 895 | + } 896 | + 897 | + if (player->GetMoney() < dest.m_cost && !player->isGameMaster()) 898 | + { 899 | + std::string msg ("You do not have enough money. The price for teleportation is " + ConvertMoney(dest.m_cost) + "."); 900 | + creature->MonsterWhisper(msg.c_str(), player->GetGUID()); 901 | + return; 902 | + } 903 | + 904 | + if (!player->isGameMaster() && dest.m_cost) 905 | + player->ModifyMoney(-1 * dest.m_cost); 906 | + 907 | + Teleport(player, dest.m_map, dest.m_X, dest.m_Y, dest.m_Z, dest.m_orient); 908 | + } 909 | +} 910 | + 911 | +class npc_teleport : public CreatureScript 912 | +{ 913 | +public: 914 | + npc_teleport() : CreatureScript("npc_teleport") {} 915 | + 916 | +bool OnGossipHello(Player *player, Creature *creature) 917 | +{ 918 | + PageC(player) = PageD(player) = Cat(player) = 0; 919 | + 920 | + if(player->isInCombat()) 921 | + { 922 | + player->CLOSE_GOSSIP_MENU(); 923 | + creature->MonsterWhisper("You are in combat. Come back later", player->GetGUID()); 924 | + return true; 925 | + } 926 | + AffichCat(player, creature); 927 | + return true; 928 | +} 929 | + 930 | +bool OnGossipSelect(Player *player, Creature *creature, uint32 sender, uint32 param) 931 | +{ 932 | + player->PlayerTalkClass->ClearMenus(); 933 | + switch(sender) 934 | + { 935 | + // Display destinations 936 | + case GOSSIP_SHOW_DEST: 937 | + Cat(player) = param; 938 | + AffichDest(player, creature); 939 | + break; 940 | + 941 | + // Previous categories page 942 | + case GOSSIP_PREV_PAGEC: 943 | + --PageC(player); 944 | + AffichCat(player, creature); 945 | + break; 946 | + 947 | + // Next page categories 948 | + case GOSSIP_NEXT_PAGEC: 949 | + ++PageC(player); 950 | + AffichCat(player, creature); 951 | + break; 952 | + 953 | + // Previous destinations page 954 | + case GOSSIP_PREV_PAGED: 955 | + --PageD(player); 956 | + AffichDest(player, creature); 957 | + break; 958 | + 959 | + // Next destination page 960 | + case GOSSIP_NEXT_PAGED: 961 | + ++PageD(player); 962 | + AffichDest(player, creature); 963 | + break; 964 | + 965 | + // Display main menu 966 | + case GOSSIP_MAIN_MENU: 967 | + OnGossipHello(player, creature); 968 | + break; 969 | + 970 | + // Teleportation 971 | + case GOSSIP_TELEPORT: 972 | + player->CLOSE_GOSSIP_MENU(); 973 | + if(player->HasAura(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS,0)) { 974 | + creature->CastSpell(player,38588,false); // Healing effect 975 | + player->RemoveAurasDueToSpell(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS); 976 | + } 977 | + 978 | + ActionTeleport(player, creature, param); 979 | + break; 980 | + } 981 | + return true; 982 | +} 983 | +}; 984 | + 985 | +void AddSC_npc_teleport() 986 | +{ 987 | + new npc_teleport; 988 | +} 989 | -- 990 | 1.7.3.1.msysgit.0 991 | 992 | -------------------------------------------------------------------------------- /11004-independent/0001-Wintergrasp.patch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevnull/thedevnull-patches/903606c3c61ae92f78276c1c5b5afa2c480518be/11004-independent/0001-Wintergrasp.patch -------------------------------------------------------------------------------- /11004/0003-Ahbot-Glyphs.patch: -------------------------------------------------------------------------------- 1 | From c799250e511ef11532451a94b7ce6a66f41dbac5 Mon Sep 17 00:00:00 2001 2 | From: thedevnull 3 | Date: Tue, 11 Jan 2011 14:08:12 -0200 4 | Subject: [PATCH 3/6] Ahbot Glyphs 5 | Signed-off-by: thedevnull 6 | 7 | --- 8 | .../AuctionHouseBot/AuctionHouseBot.cpp | 151 ++++++++++++++++---- 9 | .../AuctionHouse/AuctionHouseBot/AuctionHouseBot.h | 10 ++ 10 | src/server/worldserver/worldserver.conf.dist | 17 +++ 11 | 3 files changed, 152 insertions(+), 26 deletions(-) 12 | 13 | diff --git a/src/server/game/AuctionHouse/AuctionHouseBot/AuctionHouseBot.cpp b/src/server/game/AuctionHouse/AuctionHouseBot/AuctionHouseBot.cpp 14 | index 536ec4b..0e25d02 100644 15 | --- a/src/server/game/AuctionHouse/AuctionHouseBot/AuctionHouseBot.cpp 16 | +++ b/src/server/game/AuctionHouse/AuctionHouseBot/AuctionHouseBot.cpp 17 | @@ -24,6 +24,7 @@ 18 | 19 | using namespace std; 20 | vector npcItems; 21 | +vector glyphItemsBin; 22 | vector lootItems; 23 | vector greyTradeGoodsBin; 24 | vector whiteTradeGoodsBin; 25 | @@ -101,6 +102,16 @@ AuctionHouseBot::AuctionHouseBot() 26 | DisableItemsAboveReqSkillRank = 0; 27 | DisableTGsBelowReqSkillRank = 0; 28 | DisableTGsAboveReqSkillRank = 0; 29 | + //glyphs patch 30 | + SellGlyphs = false; 31 | + GlyphsCount = 0; 32 | + DisableGlyphBelowLevel = 0; 33 | + DisableGlyphAboveLevel = 0; 34 | + GlyphBuyOutPriceMin = 0; 35 | + GlyphBuyOutPriceMax = 0; 36 | + GlyphBidPriceMin = 0; 37 | + GlyphBidPriceMax = 0; 38 | + // <- end glyphs patch 39 | 40 | //End Filters 41 | 42 | @@ -119,6 +130,8 @@ AuctionHouseBot::~AuctionHouseBot() 43 | 44 | void AuctionHouseBot::addNewAuctions(Player *AHBplayer, AHBConfig *config) 45 | { 46 | + bool glyphMode = false; 47 | + 48 | if (!AHBSeller) 49 | { 50 | if (debug_Out) sLog->outError("AHSeller: Disabled"); 51 | @@ -147,23 +160,43 @@ void AuctionHouseBot::addNewAuctions(Player *AHBplayer, AHBConfig *config) 52 | 53 | uint32 auctions = auctionHouse->Getcount(); 54 | 55 | - if (auctions >= minItems) 56 | - { 57 | - //if (debug_Out) sLog->outString("AHSeller: Auctions above minimum"); 58 | - return; 59 | - } 60 | - 61 | - if (auctions >= maxItems) 62 | - { 63 | - //if (debug_Out) sLog->outString("AHSeller: Auctions at or above maximum"); 64 | - return; 65 | - } 66 | - 67 | uint32 items = 0; 68 | - if ((maxItems - auctions) >= ItemsPerCycle) 69 | - items = ItemsPerCycle; 70 | - else 71 | - items = (maxItems - auctions); 72 | + 73 | + if(SellGlyphs) 74 | + { 75 | + if(GlyphsCount <= 0) 76 | + GlyphsCount = 400; 77 | + 78 | + if(auctions >= minItems) 79 | + glyphMode = true; 80 | + 81 | + if(auctions >= (maxItems + GlyphsCount)) 82 | + return; 83 | + 84 | + if (((maxItems + GlyphsCount) - auctions) >= ItemsPerCycle) 85 | + items = ItemsPerCycle; 86 | + else 87 | + items = ((maxItems + GlyphsCount) - auctions); 88 | + } 89 | + else 90 | + { 91 | + if (auctions >= minItems) 92 | + { 93 | + //if (debug_Out) sLog.outString("AHSeller: Auctions above minimum"); 94 | + return; 95 | + } 96 | + 97 | + if (auctions >= maxItems) 98 | + { 99 | + //if (debug_Out) sLog.outString("AHSeller: Auctions at or above maximum"); 100 | + return; 101 | + } 102 | + 103 | + if ((maxItems - auctions) >= ItemsPerCycle) 104 | + items = ItemsPerCycle; 105 | + else 106 | + items = (maxItems - auctions); 107 | + } 108 | 109 | if (debug_Out) sLog->outString("AHSeller: Adding %u Auctions", items); 110 | 111 | @@ -222,6 +255,7 @@ void AuctionHouseBot::addNewAuctions(Player *AHBplayer, AHBConfig *config) 112 | uint32 purpleItems = config->GetItemCounts(AHB_PURPLE_I); 113 | uint32 orangeItems = config->GetItemCounts(AHB_ORANGE_I); 114 | uint32 yellowItems = config->GetItemCounts(AHB_YELLOW_I); 115 | + 116 | if (debug_Out) sLog->outString("AHSeller: %u items", items); 117 | 118 | // only insert a few at a time, so as not to peg the processor 119 | @@ -235,6 +269,8 @@ void AuctionHouseBot::addNewAuctions(Player *AHBplayer, AHBConfig *config) 120 | { 121 | ++loopbreaker; 122 | uint32 choice = urand(0, 13); 123 | + if(glyphMode) 124 | + choice = 14; 125 | itemColor = choice; 126 | switch (choice) 127 | { 128 | @@ -336,6 +372,13 @@ void AuctionHouseBot::addNewAuctions(Player *AHBplayer, AHBConfig *config) 129 | else continue; 130 | break; 131 | } 132 | + case 14: 133 | + { 134 | + if (glyphItemsBin.size() > 0) 135 | + itemID = glyphItemsBin[urand(0, glyphItemsBin.size() - 1)]; 136 | + else continue; 137 | + break; 138 | + } 139 | default: 140 | { 141 | if (debug_Out) sLog->outError("AHSeller: itemID Switch - Default Reached"); 142 | @@ -384,16 +427,27 @@ void AuctionHouseBot::addNewAuctions(Player *AHBplayer, AHBConfig *config) 143 | 144 | if ((prototype->Quality >= 0) && (prototype->Quality <= AHB_MAX_QUALITY)) 145 | { 146 | - if (config->GetMaxStack(prototype->Quality) > 1 && item->GetMaxStackCount() > 1) 147 | - stackCount = urand(1, minValue(item->GetMaxStackCount(), config->GetMaxStack(prototype->Quality))); 148 | - else if (config->GetMaxStack(prototype->Quality) == 0 && item->GetMaxStackCount() > 1) 149 | - stackCount = urand(1, item->GetMaxStackCount()); 150 | - else 151 | - stackCount = 1; 152 | - buyoutPrice *= urand(config->GetMinPrice(prototype->Quality), config->GetMaxPrice(prototype->Quality)); 153 | - buyoutPrice /= 100; 154 | - bidPrice = buyoutPrice * urand(config->GetMinBidPrice(prototype->Quality), config->GetMaxBidPrice(prototype->Quality)); 155 | - bidPrice /= 100; 156 | + if(!glyphMode) 157 | + { 158 | + if (config->GetMaxStack(prototype->Quality) > 1 && item->GetMaxStackCount() > 1) 159 | + stackCount = urand(1, minValue(item->GetMaxStackCount(), config->GetMaxStack(prototype->Quality))); 160 | + else if (config->GetMaxStack(prototype->Quality) == 0 && item->GetMaxStackCount() > 1) 161 | + stackCount = urand(1, item->GetMaxStackCount()); 162 | + else 163 | + stackCount = 1; 164 | + buyoutPrice *= urand(config->GetMinPrice(prototype->Quality), config->GetMaxPrice(prototype->Quality)); 165 | + buyoutPrice /= 100; 166 | + bidPrice = buyoutPrice * urand(config->GetMinBidPrice(prototype->Quality), config->GetMaxBidPrice(prototype->Quality)); 167 | + bidPrice /= 100; 168 | + } 169 | + else 170 | + { 171 | + buyoutPrice = urand(GlyphBuyOutPriceMin, GlyphBuyOutPriceMax); 172 | + bidPrice = urand(GlyphBidPriceMin, GlyphBidPriceMax); 173 | + if(buyoutPriceGetIntDefault("AuctionHouseBot.DisableItemsAboveReqSkillRank", 0); 182 | DisableTGsBelowReqSkillRank = sConfig->GetIntDefault("AuctionHouseBot.DisableTGsBelowReqSkillRank", 0); 183 | DisableTGsAboveReqSkillRank = sConfig->GetIntDefault("AuctionHouseBot.DisableTGsAboveReqSkillRank", 0); 184 | + SellGlyphs = sConfig->GetBoolDefault("AuctionHouseBot.SellGlyphs", false); 185 | + GlyphsCount = sConfig->GetIntDefault("AuctionHouseBot.GlyphsCount", 0); 186 | + DisableGlyphBelowLevel = sConfig->GetIntDefault("AuctionHouseBot.DisableGlyphBelowLevel", 0); 187 | + DisableGlyphAboveLevel = sConfig->GetIntDefault("AuctionHouseBot.DisableGlyphAboveLevel", 0); 188 | + GlyphBuyOutPriceMin = sConfig->GetIntDefault("AuctionHouseBot.GlyphBuyOutPriceMin", 0); 189 | + GlyphBuyOutPriceMax = sConfig->GetIntDefault("AuctionHouseBot.GlyphBuyOutPriceMax", 0); 190 | + GlyphBidPriceMin = sConfig->GetIntDefault("AuctionHouseBot.GlyphBidPriceMin", 0); 191 | + GlyphBidPriceMax = sConfig->GetIntDefault("AuctionHouseBot.GlyphBidPriceMax", 0); 192 | 193 | //End Filters 194 | if (!sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) 195 | @@ -861,6 +923,41 @@ void AuctionHouseBot::Initialize() 196 | if (debug_Out) sLog->outString("AuctionHouseBot: \"%s\" failed", npcQuery); 197 | } 198 | 199 | + if(SellGlyphs) 200 | + { 201 | + if(DisableGlyphBelowLevel > 80) 202 | + DisableGlyphBelowLevel = 0; 203 | + if(DisableGlyphAboveLevel < DisableGlyphBelowLevel) 204 | + DisableGlyphAboveLevel = DisableGlyphBelowLevel; 205 | + if(DisableGlyphAboveLevel == 0) 206 | + DisableGlyphAboveLevel = 85; 207 | + 208 | + if(GlyphBidPriceMin <= 0) 209 | + GlyphBidPriceMin = 8000; 210 | + if(GlyphBidPriceMin > GlyphBidPriceMax) 211 | + GlyphBidPriceMax = GlyphBidPriceMin; 212 | + if(GlyphBuyOutPriceMin <= 0) 213 | + GlyphBuyOutPriceMin = 10000; 214 | + if(GlyphBuyOutPriceMin > GlyphBuyOutPriceMax) 215 | + GlyphBuyOutPriceMax = GlyphBuyOutPriceMin; 216 | + 217 | + 218 | + results = WorldDatabase.PQuery("SELECT entry FROM item_template WHERE class = 16 AND RequiredLevel >= %u AND RequiredLevel <= %u", DisableGlyphBelowLevel, DisableGlyphAboveLevel); 219 | + if (results != NULL) 220 | + { 221 | + do 222 | + { 223 | + Field* fields = results->Fetch(); 224 | + glyphItemsBin.push_back(fields[0].GetUInt32()); 225 | + 226 | + } while (results->NextRow()); 227 | + } 228 | + else 229 | + { 230 | + if (debug_Out) sLog->outString("AuctionHouseBot: query glyphs failed"); 231 | + } 232 | + } 233 | + 234 | char lootQuery[] = "SELECT item FROM creature_loot_template UNION " 235 | "SELECT item FROM reference_loot_template UNION " 236 | "SELECT item FROM disenchant_loot_template UNION " 237 | @@ -1377,6 +1474,8 @@ void AuctionHouseBot::Initialize() 238 | sLog->outString("loaded %u purple items", purpleItemsBin.size()); 239 | sLog->outString("loaded %u orange items", orangeItemsBin.size()); 240 | sLog->outString("loaded %u yellow items", yellowItemsBin.size()); 241 | + sLog->outString("loaded %u glyph items", glyphItemsBin.size()); 242 | + 243 | } 244 | sLog->outString("AuctionHouseBot and AuctionHouseBuyer have been loaded."); 245 | } 246 | diff --git a/src/server/game/AuctionHouse/AuctionHouseBot/AuctionHouseBot.h b/src/server/game/AuctionHouse/AuctionHouseBot/AuctionHouseBot.h 247 | index 6c3cf82..a7da388 100644 248 | --- a/src/server/game/AuctionHouse/AuctionHouseBot/AuctionHouseBot.h 249 | +++ b/src/server/game/AuctionHouse/AuctionHouseBot/AuctionHouseBot.h 250 | @@ -46,6 +46,7 @@ 251 | #define AHB_PURPLE_I 11 252 | #define AHB_ORANGE_I 12 253 | #define AHB_YELLOW_I 13 254 | +#define AHB_GLYPH 14 255 | 256 | class AHBConfig 257 | { 258 | @@ -1214,6 +1215,15 @@ private: 259 | uint32 DisableTGsBelowReqSkillRank; 260 | uint32 DisableTGsAboveReqSkillRank; 261 | 262 | + bool SellGlyphs; 263 | + uint32 GlyphsCount; 264 | + uint32 DisableGlyphBelowLevel; 265 | + uint32 DisableGlyphAboveLevel; 266 | + uint32 GlyphBuyOutPriceMin; 267 | + uint32 GlyphBuyOutPriceMax; 268 | + uint32 GlyphBidPriceMin; 269 | + uint32 GlyphBidPriceMax; 270 | + 271 | //End Filters 272 | 273 | AHBConfig AllianceConfig; 274 | diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist 275 | index 3bda2ca..bd5b4e9 100644 276 | --- a/src/server/worldserver/worldserver.conf.dist 277 | +++ b/src/server/worldserver/worldserver.conf.dist 278 | @@ -2750,6 +2750,23 @@ AuctionHouseBot.DisableItemsAboveReqSkillRank = 0 279 | AuctionHouseBot.DisableTGsBelowReqSkillRank = 0 280 | AuctionHouseBot.DisableTGsAboveReqSkillRank = 0 281 | 282 | +############################################################################### 283 | +# AUCTION HOUSE BOT GLYPHS PART 284 | +# 285 | +# AuctionHouseBot.SellGlyphs 286 | +# Default 0 (Off) 287 | +# 288 | +############################################################################### 289 | + 290 | +AuctionHouseBot.SellGlyphs = 0 291 | +AuctionHouseBot.GlyphsCount = 0 292 | +AuctionHouseBot.DisableGlyphBelowLevel = 0 293 | +AuctionHouseBot.DisableGlyphAboveLevel = 0 294 | +AuctionHouseBot.GlyphBuyOutPriceMin = 0 295 | +AuctionHouseBot.GlyphBuyOutPriceMax = 0 296 | +AuctionHouseBot.GlyphBidPriceMin = 0 297 | +AuctionHouseBot.GlyphBidPriceMax = 0 298 | + 299 | ################################################################################################### 300 | # CONSOLE AND REMOTE ACCESS 301 | # 302 | -- 303 | 1.7.3.1.msysgit.0 304 | 305 | -------------------------------------------------------------------------------- /11004/0005-TeleNPC2.patch: -------------------------------------------------------------------------------- 1 | From e4d0fb54a3f0d7250632893dffad5e2675222b3b Mon Sep 17 00:00:00 2001 2 | From: thedevnull 3 | Date: Tue, 11 Jan 2011 14:08:47 -0200 4 | Subject: [PATCH 5/6] TeleNPC2 5 | Signed-off-by: thedevnull 6 | 7 | --- 8 | README.NPCTELEPORT | 14 + 9 | sql/tools/setup_npc_teleport.sql | 119 +++++++ 10 | src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp | 373 +++++++++++++++++++++ 11 | src/server/game/AI/ScriptedAI/sc_npc_teleport.h | 151 +++++++++ 12 | src/server/game/Scripting/ScriptLoader.cpp | 6 +- 13 | src/server/game/Scripting/ScriptMgr.cpp | 3 + 14 | src/server/scripts/CMakeLists.txt | 3 + 15 | src/server/scripts/Custom/npc_teleport.cpp | 221 ++++++++++++ 16 | 8 files changed, 889 insertions(+), 1 deletions(-) 17 | create mode 100644 README.NPCTELEPORT 18 | create mode 100644 sql/tools/setup_npc_teleport.sql 19 | create mode 100644 src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp 20 | create mode 100644 src/server/game/AI/ScriptedAI/sc_npc_teleport.h 21 | create mode 100644 src/server/scripts/Custom/npc_teleport.cpp 22 | 23 | diff --git a/README.NPCTELEPORT b/README.NPCTELEPORT 24 | new file mode 100644 25 | index 0000000..015c9c2 26 | --- /dev/null 27 | +++ b/README.NPCTELEPORT 28 | @@ -0,0 +1,14 @@ 29 | +NPC Teleport for Trinity 30 | + 31 | +Original author : Wilibald09 32 | + 33 | +Allows you to add a custom NPC for teleporting, using .npc add 100000. 34 | +The default NPC is entry 100000. 35 | + 36 | +All settings are located in the DB, so you can customize and add destinations, 37 | +set level restrictions and also charge the player for teleporting. 38 | + 39 | +Installation: 40 | + 41 | +Run the query setup_npc_teleport.sql located in the trinity sql directory on 42 | +your world DB. This will setup the DB and you can customize from there. 43 | diff --git a/sql/tools/setup_npc_teleport.sql b/sql/tools/setup_npc_teleport.sql 44 | new file mode 100644 45 | index 0000000..03b9e93 46 | --- /dev/null 47 | +++ b/sql/tools/setup_npc_teleport.sql 48 | @@ -0,0 +1,119 @@ 49 | +DROP TABLE IF EXISTS `custom_npc_tele_category`; 50 | +CREATE TABLE `custom_npc_tele_category` ( 51 | + `id` int(6) unsigned NOT NULL default '0', 52 | + `name` varchar(255) NOT NULL default '', 53 | + `flag` tinyint(3) unsigned NOT NULL default '0', 54 | + `data0` bigint(20) unsigned NOT NULL default '0', 55 | + `data1` int(6) unsigned NOT NULL default '0', 56 | + PRIMARY KEY (`id`) 57 | +) ENGINE=MyISAM DEFAULT CHARSET=utf8; 58 | + 59 | +DROP TABLE IF EXISTS `custom_npc_tele_destination`; 60 | +CREATE TABLE `custom_npc_tele_destination` ( 61 | + `id` int(6) unsigned NOT NULL auto_increment, 62 | + `name` char(100) NOT NULL default '', 63 | + `pos_X` float NOT NULL default '0', 64 | + `pos_Y` float NOT NULL default '0', 65 | + `pos_Z` float NOT NULL default '0', 66 | + `map` smallint(5) unsigned NOT NULL default '0', 67 | + `orientation` float NOT NULL default '0', 68 | + `level` tinyint(3) unsigned NOT NULL default '0', 69 | + `cost` int(10) unsigned NOT NULL default '0', 70 | + PRIMARY KEY (`id`) 71 | +) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 72 | + 73 | +DROP TABLE IF EXISTS `custom_npc_tele_association`; 74 | +CREATE TABLE `custom_npc_tele_association` ( 75 | + `cat_id` int(6) unsigned NOT NULL default '0', 76 | + `dest_id` int(6) unsigned NOT NULL default '0', 77 | + PRIMARY KEY (`cat_id`, `dest_id`) 78 | +) ENGINE=MyISAM DEFAULT CHARSET=utf8; 79 | + 80 | +TRUNCATE `custom_npc_tele_category`; 81 | +INSERT INTO `custom_npc_tele_category` 82 | + (`id`, `name`, `flag`, `data0`, `data1`) 83 | +VALUES 84 | + (1, 'Cities', 0, 1, 0), 85 | + (2, 'Cities', 0, 2, 0), 86 | + (3, 'Battlegrounds', 0, 1, 0), 87 | + (4, 'Battlegrounds', 0, 2, 0), 88 | + (5, 'Arenas', 0, 0, 0), 89 | + (6, '[Instances Lvl 1-60]', 0, 0, 0), 90 | + (7, '[Instances Lvl 60+]', 5, 60, 0), 91 | + (8, '[Instances Lvl 70+]', 5, 70, 0), 92 | + (9, 'Destinations MJ', 3, 0, 0); 93 | + 94 | +TRUNCATE `custom_npc_tele_destination`; 95 | +INSERT INTO `custom_npc_tele_destination` 96 | + (`id`, `name`, `pos_X`, `pos_Y`, `pos_Z`, `map`, `orientation`, `level`, `cost`) 97 | +VALUES 98 | + (1, 'Alterac Valley', 883.187, -489.375, 96.7618, 30, 3.06932, 0, 0), 99 | + (2, 'Alterac Valley', -818.155, -623.043, 54.0884, 30, 2.1, 0, 0), 100 | + (3, 'Arathi Basin', 686.053, 683.165, -12.9149, 529, 0.18, 0, 0), 101 | + (4, 'Arathi Basin', 1308.68, 1306.03, -9.0107, 529, 3.91285, 0, 0), 102 | + (5, 'Black Temple', -3610.72, 324.988, 37.4, 530, 3.28298, 0, 0), 103 | + (6, 'Blackfathom Deeps', 4254.58, 664.74, -29.04, 1, 1.97, 0, 0), 104 | + (7, 'Blackrock Depths', -7301.03, -913.19, 165.37, 0, 0.08, 0, 0), 105 | + (8, 'Blackrock Spire', -7535.43, -1212.04, 285.45, 0, 5.29, 0, 0), 106 | + (9, 'Blackwing Lair', -7665.55, -1102.49, 400.679, 469, 0, 0, 0), 107 | + (10, 'Caverns of Time', -8173.66, -4746.36, 33.8423, 1, 4.93989, 0, 0), 108 | + (11, 'Circle of Blood', 2839.44, 5930.17, 11.1002, 530, 3.16284, 0, 0), 109 | + (12, 'Coilfang Reservoir', 517.288, 6976.28, 32.0072, 530, 0, 0, 0), 110 | + (13, 'Darnassus', 9947.52, 2482.73, 1316.21, 1, 0, 0, 0), 111 | + (14, 'Dire Maul', -3982.47, 1127.79, 161.02, 1, 0.05, 0, 0), 112 | + (15, 'Exodar', -4073.03, -12020.4, -1.47, 530, 0, 0, 0), 113 | + (16, 'Eye of the Storm', 2487.72, 1609.12, 1224.64, 566, 3.35671, 0, 0), 114 | + (17, 'Eye of the Storm', 1843.73, 1529.77, 1224.43, 566, 0.297579, 0, 0), 115 | + (18, 'Goldshire', -9464, 62, 56, 0, 0, 0, 0), 116 | + (19, 'Gruul\'s Lair', 3539.01, 5082.36, 1.69107, 530, 0, 0, 0), 117 | + (20, 'Gurubashi', -13261.3, 168.294, 35.0792, 0, 1.00688, 0, 0), 118 | + (21, 'Hellfire Citadel', -305.816, 3056.4, -2.47318, 530, 2.01, 0, 0), 119 | + (22, 'Ironforge', -4924.07, -951.95, 501.55, 0, 5.4, 0, 0), 120 | + (23, 'Isle Of Quel\'Danas', 12947.4, -6893.31, 5.68398, 530, 3.09154, 0, 0), 121 | + (24, 'Karazhan', -11118.8, -2010.84, 47.0807, 0, 0, 0, 0), 122 | + (25, 'Maraudon', -1433.33, 2955.34, 96.21, 1, 4.82, 0, 0), 123 | + (26, 'Molten Core', 1121.45, -454.317, -101.33, 230, 3.5, 0, 0), 124 | + (27, 'Naxxramas', 3125.18, -3748.02, 136.049, 0, 0, 0, 0), 125 | + (28, 'Onyxia\'s Lair', -4707.44, -3726.82, 54.6723, 1, 3.8, 0, 0), 126 | + (29, 'Orgrimmar', 1552.5, -4420.66, 8.94802, 1, 0, 0, 0), 127 | + (30, 'Razor Hill', 315.721, -4743.4, 10.4867, 1, 0, 0, 0), 128 | + (31, 'Razorfen Downs', -4645.08, -2470.85, 85.53, 1, 4.39, 0, 0), 129 | + (32, 'Razorfen Kraul', -4484.04, -1739.4, 86.47, 1, 1.23, 0, 0), 130 | + (33, 'Ring of Trials', -1999.94, 6581.71, 11.32, 530, 2.3, 0, 0), 131 | + (34, 'Ruins of Ahn\'Qiraj', -8409.03, 1498.83, 27.3615, 1, 2.49757, 0, 0), 132 | + (35, 'Scholomance', 1219.01, -2604.66, 85.61, 0, 0.5, 0, 0), 133 | + (36, 'Shadowfang Keep', -254.47, 1524.68, 76.89, 0, 1.56, 0, 0), 134 | + (37, 'Shattrath City', -1850.21, 5435.82, -10.9614, 530, 3.40391, 0, 0), 135 | + (38, 'Silvermoon', 9338.74, -7277.27, 13.7895, 530, 0, 0, 0), 136 | + (39, 'Stormwind', -8960.14, 516.266, 96.3568, 0, 0, 0, 0), 137 | + (40, 'Stratholme', 3263.54, -3379.46, 143.59, 0, 0, 0, 0), 138 | + (41, 'Tempest Keep', 3089.58, 1399.05, 187.653, 530, 4.79407, 0, 0), 139 | + (42, 'Temple of Ahn\'Qiraj', -8245.84, 1983.74, 129.072, 1, 0.936195, 0, 0), 140 | + (43, 'The Deadmines', -11212, 1658.58, 25.67, 0, 1.45, 0, 0), 141 | + (44, 'The Maul', -3761.49, 1133.43, 132.083, 1, 4.57259, 0, 0), 142 | + (45, 'The Scarlet Monastery', 2843.89, -693.74, 139.32, 0, 5.11, 0, 0), 143 | + (46, 'The Sunken Temple', -10346.9, -3851.9, -43.41, 0, 6.09, 0, 0), 144 | + (47, 'The Wailing Caverns', -722.53, -2226.3, 16.94, 1, 2.71, 0, 0), 145 | + (48, 'Thunder Bluff', -1290, 147.034, 129.682, 1, 4.919, 0, 0), 146 | + (49, 'Uldaman', -6119.7, -2957.3, 204.11, 0, 0.03, 0, 0), 147 | + (50, 'Undercity', 1819.71, 238.79, 60.5321, 0, 0, 0, 0), 148 | + (51, 'Warsong Gulch', 930.851, 1431.57, 345.537, 489, 0.015704, 0, 0), 149 | + (52, 'Warsong Gulch', 1525.95, 1481.66, 352.001, 489, 3.20756, 0, 0), 150 | + (53, 'Zul\'Aman', 6846.95, -7954.5, 170.028, 530, 4.61501, 0, 0), 151 | + (54, 'Zul\'Farrak', -6839.39, -2911.03, 8.87, 1, 0.41, 0, 0), 152 | + (55, 'Zul\'Gurub', -11916.7, -1212.82, 92.2868, 0, 4.6095, 0, 0), 153 | + (56, 'Ile des MJ', 16254, 16276.9, 14.5082, 1, 1.70269, 0, 0); 154 | + 155 | +TRUNCATE `custom_npc_tele_association`; 156 | +INSERT INTO `custom_npc_tele_association` 157 | + (`cat_id`, `dest_id`) 158 | +VALUES 159 | + (1, 13), (1, 15), (1, 18), (1, 22), (1, 23), (1, 37), (1, 39), (2, 23), (2, 29), (2, 30), (2, 37), (2, 38), (2, 48), (2, 50), (3, 1), (3, 4), (3, 16), (3, 52), (4, 2), (4, 3), (4, 17), (4, 51), (5, 11), (5, 20), (5, 33), (5, 44), (6, 6), (6, 7), (6, 8), (6, 14), (6, 25), (6, 31), (6, 32), (6, 35), (6, 36), (6, 40), (6, 43), (6, 45), (6, 46), (6, 47), (6, 49), (6, 54), (7, 9), (7, 26), (7, 27), (7, 28), (7, 34), (7, 42), (7, 55), (8, 5), (8, 10), (8, 12), (8, 19), (8, 21), (8, 24), (8, 41), (8, 53), (9, 56); 160 | + 161 | +-- `npc_text` 162 | +REPLACE INTO `npc_text` (`ID`, `text0_0`) VALUES 163 | + (100000, 'Choose your Category.'), 164 | + (100001, 'Choose your Destination.'); 165 | + 166 | +-- `creature_template` 167 | +INSERT INTO `creature_template` VALUES (100000, 0, 0, 0, 0, 0, 26502, 0, 0, 0, 'Abisal Vortex', '', '', 0, 83, 83, 0, 35, 35, 1, 1, 1.14286, 2, 1, 509, 683, 0, 805, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 371, 535, 135, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 'npc_teleport', 1); 168 | diff --git a/src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp b/src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp 169 | new file mode 100644 170 | index 0000000..c40d861 171 | --- /dev/null 172 | +++ b/src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp 173 | @@ -0,0 +1,373 @@ 174 | +/** 175 | + * 176 | + * @File : sc_npc_teleport.cpp 177 | + * 178 | + * @Authors : Wilibald09 179 | + * 180 | + * @Date : 28/08/2008 181 | + * 182 | + * @Version : 1.2 183 | + * 184 | + **/ 185 | + 186 | + 187 | +#include "ScriptPCH.h" 188 | +#include "sc_npc_teleport.h" 189 | + 190 | +#define TELE nsNpcTel::CatDest 191 | +#define PAGE nsNpcTel::Page 192 | +#define PAGEI PAGE::Instance 193 | + 194 | + 195 | +nsNpcTel::VCatDest nsNpcTel::TabCatDest; 196 | + 197 | + 198 | +uint32 PAGE::operator [] (Player * const player) const 199 | +{ 200 | + for (VInst_t i(0); i < m_TabInstance.size(); ++i) 201 | + { 202 | + if (m_TabInstance[i].GetPlayer() == player) 203 | + return m_TabInstance[i].GetPageId(); 204 | + } 205 | + return 0; 206 | +} 207 | + 208 | +PAGE::Instance & PAGE::operator () (Player * const player) 209 | +{ 210 | + for (VInst_t i(0); i < m_TabInstance.size(); ++i) 211 | + { 212 | + if (m_TabInstance[i].GetPlayer() == player) 213 | + return m_TabInstance[i]; 214 | + } 215 | + m_TabInstance.push_back(Instance(player)); 216 | + return m_TabInstance.back(); 217 | +} 218 | + 219 | +PAGE::Instance & PAGEI::operator = (const uint32 &id) 220 | +{ 221 | + m_PageId = id; 222 | + return *this; 223 | +} 224 | + 225 | +PAGE::Instance & PAGEI::operator ++ (void) 226 | +{ 227 | + ++m_PageId; 228 | + return *this; 229 | +} 230 | + 231 | +PAGE::Instance PAGEI::operator ++ (int32) 232 | +{ 233 | + Instance tmp (*this); 234 | + ++m_PageId; 235 | + return tmp; 236 | +} 237 | + 238 | +PAGE::Instance & PAGEI::operator -- (void) 239 | +{ 240 | + --m_PageId; 241 | + return *this; 242 | +} 243 | + 244 | +PAGE::Instance PAGEI::operator -- (int32) 245 | +{ 246 | + Instance tmp (*this); 247 | + --m_PageId; 248 | + return tmp; 249 | +} 250 | + 251 | +TELE::CatDest(const uint32 &id, const std::string &name, 252 | + const Flag &flag, const uint64 &data0, const uint32 &data1) 253 | + : m_id(id), m_name(name), m_flag(flag), m_data0(data0), m_data1(data1) 254 | +{ 255 | + m_TabDest.clear(); 256 | +} 257 | + 258 | +std::string TELE::GetName(const bool IsGM /* = false */) const 259 | +{ 260 | + if (!IsGM || m_flag != FLAG_TEAM) 261 | + return m_name; 262 | + 263 | + switch (m_data0) 264 | + { 265 | + case TEAM_HORDE: return std::string(m_name + " (H)"); 266 | + case TEAM_ALLIANCE: return std::string(m_name + " (A)"); 267 | + } 268 | + return m_name; 269 | +} 270 | + 271 | +bool TELE::IsAllowedToTeleport(Player * const player) const 272 | +{ 273 | + if (player->isGameMaster()) 274 | + { 275 | + if (m_flag == FLAG_GMLEVEL) 276 | + return player->GetSession()->GetSecurity() >= m_data0; 277 | + return true; 278 | + } 279 | + 280 | + switch (m_flag) 281 | + { 282 | + case FLAG_TEAM: 283 | + switch (m_data0) 284 | + { 285 | + case TEAM_HORDE: return player->GetTeam() == HORDE; 286 | + case TEAM_ALLIANCE: return player->GetTeam() == ALLIANCE; 287 | + case TEAM_ALL: return true; 288 | + } 289 | + 290 | + case FLAG_GUILD: 291 | + return player->GetGuildId() == m_data0; 292 | + 293 | + case FLAG_GMLEVEL: 294 | + return player->GetSession()->GetSecurity() >= m_data0; 295 | + 296 | + case FLAG_ISGM: 297 | + return player->isGameMaster(); 298 | + 299 | + case FLAG_ACCOUNT: 300 | + return player->GetSession()->GetAccountId() == m_data0; 301 | + 302 | + case FLAG_LEVEL: 303 | + return player->getLevel() >= m_data0; 304 | + 305 | + case FLAG_ITEM: 306 | + return player->HasItemCount(m_data0, m_data1, true); 307 | + 308 | + case FLAG_QUEST: 309 | + if (m_data1 < MAX_QUEST_STATUS) 310 | + return player->GetQuestStatus(m_data0) == m_data1; 311 | + return player->GetQuestRewardStatus(m_data0); 312 | + 313 | + case FLAG_GENDER: 314 | + return player->getGender() == m_data0; 315 | + 316 | + case FLAG_RACE: 317 | + return player->getRace() == m_data0; 318 | + 319 | + case FLAG_CLASS: 320 | + return player->getClass() == m_data0; 321 | + 322 | + case FLAG_REPUTATION: 323 | + return player->GetReputationRank(m_data0) >= m_data1; 324 | + 325 | + case FLAG_PLAYER: 326 | + return player->GetGUID() == m_data0; 327 | + } 328 | + 329 | + sLog->outError("Invalid flag (category: %u). Important problem...", GetCatID()); 330 | + return false; 331 | +} 332 | + 333 | +uint32 TELE::CountOfCategoryAllowedBy(Player * const player) 334 | +{ 335 | + uint32 count (0); 336 | + for (VCatDest_t i(0); i < TabCatDest.size(); ++i) 337 | + { 338 | + if (TabCatDest[i].IsAllowedToTeleport(player)) 339 | + ++count; 340 | + } 341 | + return count; 342 | +} 343 | + 344 | +bool nsNpcTel::IsValidData(const uint32 &cat, const Flag &flag, 345 | + const uint64 &data0, const uint32 &data1) 346 | +{ 347 | + switch(flag) 348 | + { 349 | + case FLAG_TEAM: 350 | + if (data1) 351 | + sLog->outError("Invalid data1 (category: %u).", cat); 352 | + if (data0 < MAX_FLAG_TEAM) 353 | + return true; 354 | + sLog->outError("Invalid data0 (Team) (category: %u).", cat); 355 | + return false; 356 | + 357 | + case FLAG_GUILD: 358 | + if (data1) 359 | + sLog->outError("Invalid data1 (category: %u).", cat); 360 | + if (data0) 361 | + return true; 362 | + sLog->outError("Invalid data0 (GuildID) (category: %u).", cat); 363 | + return false; 364 | + 365 | + case FLAG_GMLEVEL: 366 | + if (data1) 367 | + sLog->outError("Invalid data1 (category: %u).", cat); 368 | + if (0 < data0 && data0 < 256) 369 | + return true; 370 | + sLog->outError("Invalid data0 (GmLevel) (category: %u).", cat); 371 | + return false; 372 | + 373 | + case FLAG_ISGM: 374 | + if (data0) 375 | + sLog->outError("Invalid data0 (category: %u).", cat); 376 | + if (data1) 377 | + sLog->outError("Invalid data1 (category: %u).", cat); 378 | + return true; 379 | + 380 | + case FLAG_ACCOUNT: 381 | + if (data1) 382 | + sLog->outError("Invalid data1 (category: %u).", cat); 383 | + if (data0) 384 | + return true; 385 | + sLog->outError("Invalid data0 (AccountID) (category: %u).", cat); 386 | + return false; 387 | + 388 | + case FLAG_LEVEL: 389 | + if (data1) 390 | + sLog->outError("Invalid data1 (category: %u).", cat); 391 | + if (0 < data0 && data0 < 256) 392 | + return true; 393 | + sLog->outError("Invalid data0 (Level) (category: %u).", cat); 394 | + return false; 395 | + 396 | + case FLAG_ITEM: 397 | + if (!data0) 398 | + { 399 | + sLog->outError("Invalid data0 (ItemID) (category: %u).", cat); 400 | + return false; 401 | + } 402 | + if (data1) 403 | + return true; 404 | + sLog->outError("Invalid data1 (Item Count) (category: %u).", cat); 405 | + return false; 406 | + 407 | + case FLAG_QUEST: 408 | + if (!data0) 409 | + { 410 | + sLog->outError("Invalid data0 (QuestID) (category: %u).", cat); 411 | + return false; 412 | + } 413 | + if (data1 < MAX_QUEST_STATUS + 1) 414 | + return true; 415 | + sLog->outError("Invalid data1 (Quest Status) (category: %u).", cat); 416 | + return false; 417 | + 418 | + case FLAG_GENDER: 419 | + if (data1) 420 | + sLog->outError("Invalid data1 (category: %u).", cat); 421 | + if (data0 < GENDER_NONE) 422 | + return true; 423 | + sLog->outError("Invalid data0 (Gender) (category: %u).", cat); 424 | + return false; 425 | + 426 | + case FLAG_RACE: 427 | + if (data1) 428 | + sLog->outError("Invalid data1 (category: %u).", cat); 429 | + if (0 < data0 && data0 < MAX_RACES) 430 | + return true; 431 | + sLog->outError("Invalid data0 (Race) (category: %u).", cat); 432 | + return false; 433 | + 434 | + case FLAG_CLASS: 435 | + if (data1) 436 | + sLog->outError("Invalid data1 (category: %u).", cat); 437 | + if (0 < data0 && data0 < MAX_CLASSES) 438 | + return true; 439 | + sLog->outError("Invalid data0 (Class) (category: %u).", cat); 440 | + return false; 441 | + 442 | + case FLAG_REPUTATION: 443 | + if (!data0) 444 | + { 445 | + sLog->outError("Invalid data0 (Faction/Reputation) (category: %u).", cat); 446 | + return false; 447 | + } 448 | + if (data1 <= REP_EXALTED) 449 | + return true; 450 | + sLog->outError("Invalid data1 (Faction/Reputation) (category: %u).", cat); 451 | + return false; 452 | + 453 | + case FLAG_PLAYER: 454 | + if (data1) 455 | + sLog->outError("Invalid data1 (category: %u).", cat); 456 | + if (data0) 457 | + return true; 458 | + sLog->outError("Invalid data0 (PlayerGuid) (category: %u).", cat); 459 | + return false; 460 | + } 461 | + 462 | + sLog->outError("Invalid flag (category: %u).", cat); 463 | + return false; 464 | +} 465 | + 466 | +void LoadNpcTele(void) 467 | +{ 468 | + const char *Table[] = 469 | + { 470 | + "custom_npc_tele_category", 471 | + "custom_npc_tele_destination", 472 | + "custom_npc_tele_association", 473 | + }; 474 | + 475 | + 476 | + QueryResult result = WorldDatabase.PQuery( 477 | + "SELECT `flag`, `data0`, `data1`, `cat_id`, C.`name` `namecat`, D.`name` `namedest`, " 478 | + // 0 1 2 3 4 5 479 | + "`pos_X`, `pos_Y`, `pos_Z`, `orientation`, `map`, `level`, `cost` " 480 | + // 6 7 8 9 10 11 12 481 | + "FROM `%s` C, `%s` D, `%s` A " 482 | + "WHERE C.`id` = `cat_id` AND D.`id` = `dest_id` " 483 | + "ORDER BY `namecat`, `cat_id`, `namedest`", Table[0], Table[1], Table[2]); 484 | + 485 | + nsNpcTel::TabCatDest.clear(); 486 | + 487 | + if (result) 488 | + { 489 | + sLog->outString( "TSCR: Loading %s, %s and %s...", Table[0], Table[1], Table[2]); 490 | + 491 | + uint32 catid = 0; 492 | + uint32 nbDest = 0; 493 | + bool IsValidCat = true; 494 | + bool FirstTime = true; 495 | + 496 | + do 497 | + { 498 | + Field *fields = result->Fetch(); 499 | + 500 | + if (!IsValidCat && catid == fields[3].GetUInt32() && !FirstTime) 501 | + continue; 502 | + 503 | + IsValidCat = true; 504 | + FirstTime = false; 505 | + 506 | + if (!nsNpcTel::IsValidData(fields[3].GetUInt32(), (nsNpcTel::Flag)fields[0].GetUInt8(), 507 | + fields[1].GetUInt64(), fields[2].GetUInt32())) 508 | + { 509 | + IsValidCat = false; 510 | + catid = fields[3].GetUInt32(); 511 | + continue; 512 | + } 513 | + 514 | + if (catid != fields[3].GetUInt32()) 515 | + { 516 | + catid = fields[3].GetUInt32(); 517 | + nsNpcTel::CatDest categorie (catid, fields[4].GetString(), (nsNpcTel::Flag)fields[0].GetUInt8(), 518 | + fields[1].GetUInt64(), fields[2].GetUInt32()); 519 | + nsNpcTel::TabCatDest.push_back(categorie); 520 | + } 521 | + 522 | + nsNpcTel::Dest item = 523 | + { 524 | + fields[5].GetString(), // Name 525 | + fields[6].GetFloat(), // X 526 | + fields[7].GetFloat(), // Y 527 | + fields[8].GetFloat(), // Z 528 | + fields[9].GetFloat(), // Orientation 529 | + fields[10].GetUInt16(), // Map 530 | + fields[11].GetUInt8(), // Level 531 | + fields[12].GetUInt32(), // Cost 532 | + }; 533 | + 534 | + nsNpcTel::TabCatDest.back().AddDest(item); 535 | + ++nbDest; 536 | + } while (result->NextRow()); 537 | + 538 | + sLog->outString(""); 539 | + sLog->outString("TSCR: >> Loaded %u npc_teleport.", nbDest); 540 | + } else sLog->outString("TSCR: WARNING >> Loaded 0 npc_teleport."); 541 | +} 542 | + 543 | + 544 | +#undef TELE 545 | +#undef PAGE 546 | +#undef PAGEI 547 | diff --git a/src/server/game/AI/ScriptedAI/sc_npc_teleport.h b/src/server/game/AI/ScriptedAI/sc_npc_teleport.h 548 | new file mode 100644 549 | index 0000000..4830245 550 | --- /dev/null 551 | +++ b/src/server/game/AI/ScriptedAI/sc_npc_teleport.h 552 | @@ -0,0 +1,151 @@ 553 | +/** 554 | + * 555 | + * @File : sc_npc_teleport.h 556 | + * 557 | + * @Authors : Wilibald09 558 | + * 559 | + * @Date : 19/08/2008 560 | + * 561 | + * @Version : 1.2 562 | + * 563 | + **/ 564 | + 565 | + 566 | +#ifndef SC_NPC_TELEPORT_H 567 | +#define SC_NPC_TELEPORT_H 568 | + 569 | +#include 570 | + 571 | + 572 | +namespace nsNpcTel 573 | +{ 574 | + // Different types of permissions 575 | + enum Flag 576 | + { 577 | + FLAG_TEAM = 0, 578 | + FLAG_GUILD = 1, 579 | + FLAG_GMLEVEL = 2, 580 | + FLAG_ISGM = 3, 581 | + FLAG_ACCOUNT = 4, 582 | + FLAG_LEVEL = 5, 583 | + FLAG_ITEM = 6, 584 | + FLAG_QUEST = 7, 585 | + FLAG_GENDER = 8, 586 | + FLAG_RACE = 9, 587 | + FLAG_CLASS = 10, 588 | + FLAG_REPUTATION = 11, 589 | + FLAG_PLAYER = 12, 590 | + MAX_FLAG, 591 | + }; 592 | + 593 | + // Different parameters of FLAG_TEAM 594 | + enum 595 | + { 596 | + TEAM_ALL = 0, 597 | + TEAM_ALLIANCE = 1, 598 | + TEAM_HORDE = 2, 599 | + MAX_FLAG_TEAM, 600 | + }; 601 | + 602 | + // Structure representing the destinations 603 | + struct Dest 604 | + { 605 | + std::string m_name; 606 | + float m_X, m_Y, m_Z, m_orient; 607 | + uint16 m_map; 608 | + uint8 m_level; 609 | + uint32 m_cost; 610 | + }; 611 | + 612 | + // Class representing the categories of destinations 613 | + class CatDest 614 | + { 615 | + public: 616 | + 617 | + typedef std::vector VDest; 618 | + typedef VDest::size_type VDest_t; 619 | + 620 | + CatDest(const uint32 &id, const std::string &name, 621 | + const Flag &flag, const uint64 &data0, const uint32 &data1); 622 | + 623 | + void AddDest (const Dest &item) { m_TabDest.push_back(item); } 624 | + Dest GetDest (const uint32 &id) const { return m_TabDest[id]; } 625 | + uint32 GetCatID (void) const { return m_id; } 626 | + uint32 size (void) const { return m_TabDest.size(); } 627 | + 628 | + std::string GetName(const bool IsGM = false) const; 629 | + bool IsAllowedToTeleport(Player * const player) const; 630 | + 631 | + static uint32 CountOfCategoryAllowedBy(Player * const player); 632 | + 633 | + private: 634 | + 635 | + uint32 m_id; 636 | + std::string m_name; 637 | + Flag m_flag; 638 | + uint64 m_data0; 639 | + uint32 m_data1; 640 | + VDest m_TabDest; 641 | + }; 642 | + 643 | + // Class page for current player 644 | + class Page 645 | + { 646 | + protected: 647 | + 648 | + // Class instance for current player 649 | + class Instance 650 | + { 651 | + public: 652 | + 653 | + Instance(Player * const player, const uint32 &PageId = 0) 654 | + : m_player(player), m_PageId(PageId) {} 655 | + 656 | + Instance & operator = (const uint32 &id); 657 | + Instance & operator ++ (void); 658 | + Instance operator ++ (int32); 659 | + Instance & operator -- (void); 660 | + Instance operator -- (int32); 661 | + 662 | + uint32 GetPageId(void) const { return m_PageId; } 663 | + Player * GetPlayer(void) const { return m_player; } 664 | + 665 | + private: 666 | + 667 | + Player *m_player; 668 | + uint32 m_PageId; 669 | + }; 670 | + 671 | + 672 | + public: 673 | + 674 | + typedef std::vector VInst; 675 | + typedef VInst::size_type VInst_t; 676 | + 677 | + Page(void) { m_TabInstance.clear(); } 678 | + 679 | + Instance & operator () (Player * const player); 680 | + uint32 operator [] (Player * const player) const; 681 | + 682 | + 683 | + private: 684 | + 685 | + VInst m_TabInstance; 686 | + }; 687 | + 688 | + typedef std::vector VCatDest; 689 | + typedef VCatDest::size_type VCatDest_t; 690 | + 691 | + // Verification of data integrity 692 | + bool IsValidData(const uint32 &cat, const Flag &flag, 693 | + const uint64 &data0, const uint32 &data1); 694 | + 695 | + extern VCatDest TabCatDest; 696 | +} 697 | + 698 | +// Loading contents of database 699 | +void LoadNpcTele(void); 700 | + 701 | +extern WorldDatabaseWorkerPool WorldDatabase; 702 | + 703 | +#endif 704 | diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp 705 | index 165164c..3d5fac7 100755 706 | --- a/src/server/game/Scripting/ScriptLoader.cpp 707 | +++ b/src/server/game/Scripting/ScriptLoader.cpp 708 | @@ -25,6 +25,9 @@ void AddSC_example_gossip_codebox(); 709 | void AddSC_example_misc(); 710 | void AddSC_example_commandscript(); 711 | 712 | +//TeleNPC2 713 | +void AddSC_npc_teleport(); 714 | + 715 | // spells 716 | void AddSC_deathknight_spell_scripts(); 717 | void AddSC_druid_spell_scripts(); 718 | @@ -1225,6 +1228,7 @@ void AddCustomScripts() 719 | { 720 | #ifdef SCRIPTS 721 | /* This is where custom scripts should be added. */ 722 | - 723 | + //TeleNPC2 724 | + AddSC_npc_teleport(); 725 | #endif 726 | } 727 | diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp 728 | index 5cb3dd6..7ead67e 100755 729 | --- a/src/server/game/Scripting/ScriptMgr.cpp 730 | +++ b/src/server/game/Scripting/ScriptMgr.cpp 731 | @@ -25,6 +25,7 @@ 732 | #include "ScriptLoader.h" 733 | #include "ScriptSystem.h" 734 | #include "Transport.h" 735 | +#include "sc_npc_teleport.h" 736 | 737 | // Utility macros to refer to the script registry. 738 | #define SCR_REG_MAP(T) ScriptRegistry::ScriptMap 739 | @@ -180,6 +181,8 @@ void ScriptMgr::Initialize() 740 | uint32 oldMSTime = getMSTime(); 741 | 742 | LoadDatabase(); 743 | + // Load TeleNPC2 - maybe not the best place to load it ... 744 | + LoadNpcTele(); 745 | 746 | sLog->outString("Loading C++ scripts"); 747 | 748 | diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt 749 | index 95ec7b9..ef7619a 100644 750 | --- a/src/server/scripts/CMakeLists.txt 751 | +++ b/src/server/scripts/CMakeLists.txt 752 | @@ -31,6 +31,9 @@ include(Examples/CMakeLists.txt) 753 | 754 | set(scripts_STAT_SRCS 755 | ${scripts_STAT_SRCS} 756 | + Custom/npc_teleport.cpp 757 | + ../game/AI/ScriptedAI/sc_npc_teleport.cpp 758 | + ../game/AI/ScriptedAI/sc_npc_teleport.h 759 | ../game/AI/ScriptedAI/ScriptedEscortAI.cpp 760 | ../game/AI/ScriptedAI/ScriptedCreature.cpp 761 | ../game/AI/ScriptedAI/ScriptedFollowerAI.cpp 762 | diff --git a/src/server/scripts/Custom/npc_teleport.cpp b/src/server/scripts/Custom/npc_teleport.cpp 763 | new file mode 100644 764 | index 0000000..1e51336 765 | --- /dev/null 766 | +++ b/src/server/scripts/Custom/npc_teleport.cpp 767 | @@ -0,0 +1,221 @@ 768 | +/** 769 | + * 770 | + * @File : npc_teleport.cpp 771 | + * 772 | + * @Authors : Wilibald09 773 | + * 774 | + * @Date : 19/08/2008 775 | + * 776 | + * @Version : 1.2 777 | + * 778 | + **/ 779 | + 780 | + 781 | + 782 | +#include "ScriptPCH.h" 783 | +#include "sc_npc_teleport.h" 784 | +#include 785 | + 786 | +#define GOSSIP_SHOW_DEST 1000 787 | +#define GOSSIP_TELEPORT 1001 788 | +#define GOSSIP_NEXT_PAGEC 1002 789 | +#define GOSSIP_PREV_PAGEC 1003 790 | +#define GOSSIP_NEXT_PAGED 1004 791 | +#define GOSSIP_PREV_PAGED 1005 792 | +#define GOSSIP_MAIN_MENU 1006 793 | + 794 | +#define SPELL_ID_PASSIVE_RESURRECTION_SICKNESS 15007 795 | +#define SPELL_VISUAL_TELEPORT 35517 796 | + 797 | +#define NB_ITEM_PAGE 10 798 | +#define MSG_CAT 100000 799 | +#define MSG_DEST 100001 800 | + 801 | +#define NEXT_PAGE "-> [Next Page]" 802 | +#define PREV_PAGE "<- [Previous Page]" 803 | +#define MAIN_MENU "<= [Main Menu]" 804 | + 805 | + 806 | +using namespace nsNpcTel; 807 | + 808 | + 809 | +namespace 810 | +{ 811 | + Page PageC, PageD; 812 | + Page Cat; 813 | + 814 | + // Conversion function int->string 815 | + std::string ConvertStr(const int64 &val) 816 | + { 817 | + std::ostringstream ostr; 818 | + ostr << val; 819 | + return ostr.str(); 820 | + } 821 | + 822 | + // Conversion function intMoney->stringMoney 823 | + std::string ConvertMoney(const uint32 &Money) 824 | + { 825 | + std::string Str(ConvertStr(Money)); 826 | + uint32 SizeStr = Str.length(); 827 | + 828 | + if (SizeStr > 4) 829 | + Str = Str.insert(Str.length()-4, "po"); 830 | + if (SizeStr > 2) 831 | + Str = Str.insert(Str.length()-2, "pa"); 832 | + Str += "pc"; 833 | + 834 | + return Str; 835 | + } 836 | + 837 | + // Teleport Player 838 | + void Teleport(Player * const player, const uint16 &map, 839 | + const float &X, const float &Y, const float &Z, const float &orient) 840 | + { 841 | + player->CastSpell(player, SPELL_VISUAL_TELEPORT, true); 842 | + player->TeleportTo(map, X, Y, Z, orient); 843 | + } 844 | + 845 | + // Display categories 846 | + void AffichCat(Player * const player, Creature * const creature) 847 | + { 848 | + if (PageC[player] > 0) 849 | + player->ADD_GOSSIP_ITEM(7, PREV_PAGE, GOSSIP_PREV_PAGEC, 0); 850 | + 851 | + VCatDest_t i (PageC[player] * NB_ITEM_PAGE); 852 | + for ( ; i < TabCatDest.size() && i < (NB_ITEM_PAGE * (PageC[player] + 1)); ++i) 853 | + { 854 | + if (TabCatDest[i].IsAllowedToTeleport(player)) 855 | + player->ADD_GOSSIP_ITEM(7, TabCatDest[i].GetName(player->isGameMaster()).c_str(), GOSSIP_SHOW_DEST, i); 856 | + } 857 | + 858 | + if (i < TabCatDest.size()) 859 | + player->ADD_GOSSIP_ITEM(7, NEXT_PAGE, GOSSIP_NEXT_PAGEC, 0); 860 | + 861 | + player->SEND_GOSSIP_MENU(MSG_CAT, creature->GetGUID()); 862 | + } 863 | + 864 | + // Display destination categories 865 | + void AffichDest(Player * const player, Creature * const creature) 866 | + { 867 | + if (PageD[player] > 0) 868 | + player->ADD_GOSSIP_ITEM(7, PREV_PAGE, GOSSIP_PREV_PAGED, 0); 869 | + 870 | + CatDest::VDest_t i (PageD[player] * NB_ITEM_PAGE); 871 | + for ( ; i < TabCatDest[Cat[player]].size() && i < (NB_ITEM_PAGE * (PageD[player] + 1)); ++i) 872 | + { 873 | + player->ADD_GOSSIP_ITEM(5, TabCatDest[Cat[player]].GetDest(i).m_name.c_str(), GOSSIP_TELEPORT, i); 874 | + } 875 | + 876 | + if (i < TabCatDest[Cat[player]].size()) 877 | + player->ADD_GOSSIP_ITEM(7, NEXT_PAGE, GOSSIP_NEXT_PAGED, 0); 878 | + 879 | + if (CatDest::CountOfCategoryAllowedBy(player) > 1) 880 | + player->ADD_GOSSIP_ITEM(7, MAIN_MENU, GOSSIP_MAIN_MENU, 0); 881 | + 882 | + player->SEND_GOSSIP_MENU(MSG_DEST, creature->GetGUID()); 883 | + } 884 | + 885 | + // Verification before teleportation 886 | + void ActionTeleport(Player * const player, Creature * const creature, const uint32 &id) 887 | + { 888 | + Dest dest (TabCatDest[Cat[player]].GetDest(id)); 889 | + 890 | + if (player->getLevel() < dest.m_level && !player->isGameMaster()) 891 | + { 892 | + std::string msg ("You do not have the required level. This destination requires level " + ConvertStr(dest.m_level) + "."); 893 | + creature->MonsterWhisper(msg.c_str(), player->GetGUID()); 894 | + return; 895 | + } 896 | + 897 | + if (player->GetMoney() < dest.m_cost && !player->isGameMaster()) 898 | + { 899 | + std::string msg ("You do not have enough money. The price for teleportation is " + ConvertMoney(dest.m_cost) + "."); 900 | + creature->MonsterWhisper(msg.c_str(), player->GetGUID()); 901 | + return; 902 | + } 903 | + 904 | + if (!player->isGameMaster() && dest.m_cost) 905 | + player->ModifyMoney(-1 * dest.m_cost); 906 | + 907 | + Teleport(player, dest.m_map, dest.m_X, dest.m_Y, dest.m_Z, dest.m_orient); 908 | + } 909 | +} 910 | + 911 | +class npc_teleport : public CreatureScript 912 | +{ 913 | +public: 914 | + npc_teleport() : CreatureScript("npc_teleport") {} 915 | + 916 | +bool OnGossipHello(Player *player, Creature *creature) 917 | +{ 918 | + PageC(player) = PageD(player) = Cat(player) = 0; 919 | + 920 | + if(player->isInCombat()) 921 | + { 922 | + player->CLOSE_GOSSIP_MENU(); 923 | + creature->MonsterWhisper("You are in combat. Come back later", player->GetGUID()); 924 | + return true; 925 | + } 926 | + AffichCat(player, creature); 927 | + return true; 928 | +} 929 | + 930 | +bool OnGossipSelect(Player *player, Creature *creature, uint32 sender, uint32 param) 931 | +{ 932 | + player->PlayerTalkClass->ClearMenus(); 933 | + switch(sender) 934 | + { 935 | + // Display destinations 936 | + case GOSSIP_SHOW_DEST: 937 | + Cat(player) = param; 938 | + AffichDest(player, creature); 939 | + break; 940 | + 941 | + // Previous categories page 942 | + case GOSSIP_PREV_PAGEC: 943 | + --PageC(player); 944 | + AffichCat(player, creature); 945 | + break; 946 | + 947 | + // Next page categories 948 | + case GOSSIP_NEXT_PAGEC: 949 | + ++PageC(player); 950 | + AffichCat(player, creature); 951 | + break; 952 | + 953 | + // Previous destinations page 954 | + case GOSSIP_PREV_PAGED: 955 | + --PageD(player); 956 | + AffichDest(player, creature); 957 | + break; 958 | + 959 | + // Next destination page 960 | + case GOSSIP_NEXT_PAGED: 961 | + ++PageD(player); 962 | + AffichDest(player, creature); 963 | + break; 964 | + 965 | + // Display main menu 966 | + case GOSSIP_MAIN_MENU: 967 | + OnGossipHello(player, creature); 968 | + break; 969 | + 970 | + // Teleportation 971 | + case GOSSIP_TELEPORT: 972 | + player->CLOSE_GOSSIP_MENU(); 973 | + if(player->HasAura(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS,0)) { 974 | + creature->CastSpell(player,38588,false); // Healing effect 975 | + player->RemoveAurasDueToSpell(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS); 976 | + } 977 | + 978 | + ActionTeleport(player, creature, param); 979 | + break; 980 | + } 981 | + return true; 982 | +} 983 | +}; 984 | + 985 | +void AddSC_npc_teleport() 986 | +{ 987 | + new npc_teleport; 988 | +} 989 | -- 990 | 1.7.3.1.msysgit.0 991 | 992 | -------------------------------------------------------------------------------- /11004/0006-Wintergrasp.patch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevnull/thedevnull-patches/903606c3c61ae92f78276c1c5b5afa2c480518be/11004/0006-Wintergrasp.patch -------------------------------------------------------------------------------- /11010-independent/0001-Telenpc2.patch: -------------------------------------------------------------------------------- 1 | From 8d87cd6574a4662685957a683fe61acc59f2d38c Mon Sep 17 00:00:00 2001 2 | From: thedevnull 3 | Date: Wed, 12 Jan 2011 01:09:28 -0200 4 | Subject: [PATCH] Telenpc2 5 | Signed-off-by: thedevnull 6 | 7 | --- 8 | README.NPCTELEPORT | 14 + 9 | sql/tools/setup_npc_teleport.sql | 119 +++++++ 10 | src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp | 373 +++++++++++++++++++++ 11 | src/server/game/AI/ScriptedAI/sc_npc_teleport.h | 151 +++++++++ 12 | src/server/game/Scripting/ScriptLoader.cpp | 6 +- 13 | src/server/game/Scripting/ScriptMgr.cpp | 3 + 14 | src/server/scripts/CMakeLists.txt | 3 + 15 | src/server/scripts/Custom/npc_teleport.cpp | 221 ++++++++++++ 16 | 8 files changed, 889 insertions(+), 1 deletions(-) 17 | create mode 100644 README.NPCTELEPORT 18 | create mode 100644 sql/tools/setup_npc_teleport.sql 19 | create mode 100644 src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp 20 | create mode 100644 src/server/game/AI/ScriptedAI/sc_npc_teleport.h 21 | create mode 100644 src/server/scripts/Custom/npc_teleport.cpp 22 | 23 | diff --git a/README.NPCTELEPORT b/README.NPCTELEPORT 24 | new file mode 100644 25 | index 0000000..015c9c2 26 | --- /dev/null 27 | +++ b/README.NPCTELEPORT 28 | @@ -0,0 +1,14 @@ 29 | +NPC Teleport for Trinity 30 | + 31 | +Original author : Wilibald09 32 | + 33 | +Allows you to add a custom NPC for teleporting, using .npc add 100000. 34 | +The default NPC is entry 100000. 35 | + 36 | +All settings are located in the DB, so you can customize and add destinations, 37 | +set level restrictions and also charge the player for teleporting. 38 | + 39 | +Installation: 40 | + 41 | +Run the query setup_npc_teleport.sql located in the trinity sql directory on 42 | +your world DB. This will setup the DB and you can customize from there. 43 | diff --git a/sql/tools/setup_npc_teleport.sql b/sql/tools/setup_npc_teleport.sql 44 | new file mode 100644 45 | index 0000000..03b9e93 46 | --- /dev/null 47 | +++ b/sql/tools/setup_npc_teleport.sql 48 | @@ -0,0 +1,119 @@ 49 | +DROP TABLE IF EXISTS `custom_npc_tele_category`; 50 | +CREATE TABLE `custom_npc_tele_category` ( 51 | + `id` int(6) unsigned NOT NULL default '0', 52 | + `name` varchar(255) NOT NULL default '', 53 | + `flag` tinyint(3) unsigned NOT NULL default '0', 54 | + `data0` bigint(20) unsigned NOT NULL default '0', 55 | + `data1` int(6) unsigned NOT NULL default '0', 56 | + PRIMARY KEY (`id`) 57 | +) ENGINE=MyISAM DEFAULT CHARSET=utf8; 58 | + 59 | +DROP TABLE IF EXISTS `custom_npc_tele_destination`; 60 | +CREATE TABLE `custom_npc_tele_destination` ( 61 | + `id` int(6) unsigned NOT NULL auto_increment, 62 | + `name` char(100) NOT NULL default '', 63 | + `pos_X` float NOT NULL default '0', 64 | + `pos_Y` float NOT NULL default '0', 65 | + `pos_Z` float NOT NULL default '0', 66 | + `map` smallint(5) unsigned NOT NULL default '0', 67 | + `orientation` float NOT NULL default '0', 68 | + `level` tinyint(3) unsigned NOT NULL default '0', 69 | + `cost` int(10) unsigned NOT NULL default '0', 70 | + PRIMARY KEY (`id`) 71 | +) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 72 | + 73 | +DROP TABLE IF EXISTS `custom_npc_tele_association`; 74 | +CREATE TABLE `custom_npc_tele_association` ( 75 | + `cat_id` int(6) unsigned NOT NULL default '0', 76 | + `dest_id` int(6) unsigned NOT NULL default '0', 77 | + PRIMARY KEY (`cat_id`, `dest_id`) 78 | +) ENGINE=MyISAM DEFAULT CHARSET=utf8; 79 | + 80 | +TRUNCATE `custom_npc_tele_category`; 81 | +INSERT INTO `custom_npc_tele_category` 82 | + (`id`, `name`, `flag`, `data0`, `data1`) 83 | +VALUES 84 | + (1, 'Cities', 0, 1, 0), 85 | + (2, 'Cities', 0, 2, 0), 86 | + (3, 'Battlegrounds', 0, 1, 0), 87 | + (4, 'Battlegrounds', 0, 2, 0), 88 | + (5, 'Arenas', 0, 0, 0), 89 | + (6, '[Instances Lvl 1-60]', 0, 0, 0), 90 | + (7, '[Instances Lvl 60+]', 5, 60, 0), 91 | + (8, '[Instances Lvl 70+]', 5, 70, 0), 92 | + (9, 'Destinations MJ', 3, 0, 0); 93 | + 94 | +TRUNCATE `custom_npc_tele_destination`; 95 | +INSERT INTO `custom_npc_tele_destination` 96 | + (`id`, `name`, `pos_X`, `pos_Y`, `pos_Z`, `map`, `orientation`, `level`, `cost`) 97 | +VALUES 98 | + (1, 'Alterac Valley', 883.187, -489.375, 96.7618, 30, 3.06932, 0, 0), 99 | + (2, 'Alterac Valley', -818.155, -623.043, 54.0884, 30, 2.1, 0, 0), 100 | + (3, 'Arathi Basin', 686.053, 683.165, -12.9149, 529, 0.18, 0, 0), 101 | + (4, 'Arathi Basin', 1308.68, 1306.03, -9.0107, 529, 3.91285, 0, 0), 102 | + (5, 'Black Temple', -3610.72, 324.988, 37.4, 530, 3.28298, 0, 0), 103 | + (6, 'Blackfathom Deeps', 4254.58, 664.74, -29.04, 1, 1.97, 0, 0), 104 | + (7, 'Blackrock Depths', -7301.03, -913.19, 165.37, 0, 0.08, 0, 0), 105 | + (8, 'Blackrock Spire', -7535.43, -1212.04, 285.45, 0, 5.29, 0, 0), 106 | + (9, 'Blackwing Lair', -7665.55, -1102.49, 400.679, 469, 0, 0, 0), 107 | + (10, 'Caverns of Time', -8173.66, -4746.36, 33.8423, 1, 4.93989, 0, 0), 108 | + (11, 'Circle of Blood', 2839.44, 5930.17, 11.1002, 530, 3.16284, 0, 0), 109 | + (12, 'Coilfang Reservoir', 517.288, 6976.28, 32.0072, 530, 0, 0, 0), 110 | + (13, 'Darnassus', 9947.52, 2482.73, 1316.21, 1, 0, 0, 0), 111 | + (14, 'Dire Maul', -3982.47, 1127.79, 161.02, 1, 0.05, 0, 0), 112 | + (15, 'Exodar', -4073.03, -12020.4, -1.47, 530, 0, 0, 0), 113 | + (16, 'Eye of the Storm', 2487.72, 1609.12, 1224.64, 566, 3.35671, 0, 0), 114 | + (17, 'Eye of the Storm', 1843.73, 1529.77, 1224.43, 566, 0.297579, 0, 0), 115 | + (18, 'Goldshire', -9464, 62, 56, 0, 0, 0, 0), 116 | + (19, 'Gruul\'s Lair', 3539.01, 5082.36, 1.69107, 530, 0, 0, 0), 117 | + (20, 'Gurubashi', -13261.3, 168.294, 35.0792, 0, 1.00688, 0, 0), 118 | + (21, 'Hellfire Citadel', -305.816, 3056.4, -2.47318, 530, 2.01, 0, 0), 119 | + (22, 'Ironforge', -4924.07, -951.95, 501.55, 0, 5.4, 0, 0), 120 | + (23, 'Isle Of Quel\'Danas', 12947.4, -6893.31, 5.68398, 530, 3.09154, 0, 0), 121 | + (24, 'Karazhan', -11118.8, -2010.84, 47.0807, 0, 0, 0, 0), 122 | + (25, 'Maraudon', -1433.33, 2955.34, 96.21, 1, 4.82, 0, 0), 123 | + (26, 'Molten Core', 1121.45, -454.317, -101.33, 230, 3.5, 0, 0), 124 | + (27, 'Naxxramas', 3125.18, -3748.02, 136.049, 0, 0, 0, 0), 125 | + (28, 'Onyxia\'s Lair', -4707.44, -3726.82, 54.6723, 1, 3.8, 0, 0), 126 | + (29, 'Orgrimmar', 1552.5, -4420.66, 8.94802, 1, 0, 0, 0), 127 | + (30, 'Razor Hill', 315.721, -4743.4, 10.4867, 1, 0, 0, 0), 128 | + (31, 'Razorfen Downs', -4645.08, -2470.85, 85.53, 1, 4.39, 0, 0), 129 | + (32, 'Razorfen Kraul', -4484.04, -1739.4, 86.47, 1, 1.23, 0, 0), 130 | + (33, 'Ring of Trials', -1999.94, 6581.71, 11.32, 530, 2.3, 0, 0), 131 | + (34, 'Ruins of Ahn\'Qiraj', -8409.03, 1498.83, 27.3615, 1, 2.49757, 0, 0), 132 | + (35, 'Scholomance', 1219.01, -2604.66, 85.61, 0, 0.5, 0, 0), 133 | + (36, 'Shadowfang Keep', -254.47, 1524.68, 76.89, 0, 1.56, 0, 0), 134 | + (37, 'Shattrath City', -1850.21, 5435.82, -10.9614, 530, 3.40391, 0, 0), 135 | + (38, 'Silvermoon', 9338.74, -7277.27, 13.7895, 530, 0, 0, 0), 136 | + (39, 'Stormwind', -8960.14, 516.266, 96.3568, 0, 0, 0, 0), 137 | + (40, 'Stratholme', 3263.54, -3379.46, 143.59, 0, 0, 0, 0), 138 | + (41, 'Tempest Keep', 3089.58, 1399.05, 187.653, 530, 4.79407, 0, 0), 139 | + (42, 'Temple of Ahn\'Qiraj', -8245.84, 1983.74, 129.072, 1, 0.936195, 0, 0), 140 | + (43, 'The Deadmines', -11212, 1658.58, 25.67, 0, 1.45, 0, 0), 141 | + (44, 'The Maul', -3761.49, 1133.43, 132.083, 1, 4.57259, 0, 0), 142 | + (45, 'The Scarlet Monastery', 2843.89, -693.74, 139.32, 0, 5.11, 0, 0), 143 | + (46, 'The Sunken Temple', -10346.9, -3851.9, -43.41, 0, 6.09, 0, 0), 144 | + (47, 'The Wailing Caverns', -722.53, -2226.3, 16.94, 1, 2.71, 0, 0), 145 | + (48, 'Thunder Bluff', -1290, 147.034, 129.682, 1, 4.919, 0, 0), 146 | + (49, 'Uldaman', -6119.7, -2957.3, 204.11, 0, 0.03, 0, 0), 147 | + (50, 'Undercity', 1819.71, 238.79, 60.5321, 0, 0, 0, 0), 148 | + (51, 'Warsong Gulch', 930.851, 1431.57, 345.537, 489, 0.015704, 0, 0), 149 | + (52, 'Warsong Gulch', 1525.95, 1481.66, 352.001, 489, 3.20756, 0, 0), 150 | + (53, 'Zul\'Aman', 6846.95, -7954.5, 170.028, 530, 4.61501, 0, 0), 151 | + (54, 'Zul\'Farrak', -6839.39, -2911.03, 8.87, 1, 0.41, 0, 0), 152 | + (55, 'Zul\'Gurub', -11916.7, -1212.82, 92.2868, 0, 4.6095, 0, 0), 153 | + (56, 'Ile des MJ', 16254, 16276.9, 14.5082, 1, 1.70269, 0, 0); 154 | + 155 | +TRUNCATE `custom_npc_tele_association`; 156 | +INSERT INTO `custom_npc_tele_association` 157 | + (`cat_id`, `dest_id`) 158 | +VALUES 159 | + (1, 13), (1, 15), (1, 18), (1, 22), (1, 23), (1, 37), (1, 39), (2, 23), (2, 29), (2, 30), (2, 37), (2, 38), (2, 48), (2, 50), (3, 1), (3, 4), (3, 16), (3, 52), (4, 2), (4, 3), (4, 17), (4, 51), (5, 11), (5, 20), (5, 33), (5, 44), (6, 6), (6, 7), (6, 8), (6, 14), (6, 25), (6, 31), (6, 32), (6, 35), (6, 36), (6, 40), (6, 43), (6, 45), (6, 46), (6, 47), (6, 49), (6, 54), (7, 9), (7, 26), (7, 27), (7, 28), (7, 34), (7, 42), (7, 55), (8, 5), (8, 10), (8, 12), (8, 19), (8, 21), (8, 24), (8, 41), (8, 53), (9, 56); 160 | + 161 | +-- `npc_text` 162 | +REPLACE INTO `npc_text` (`ID`, `text0_0`) VALUES 163 | + (100000, 'Choose your Category.'), 164 | + (100001, 'Choose your Destination.'); 165 | + 166 | +-- `creature_template` 167 | +INSERT INTO `creature_template` VALUES (100000, 0, 0, 0, 0, 0, 26502, 0, 0, 0, 'Abisal Vortex', '', '', 0, 83, 83, 0, 35, 35, 1, 1, 1.14286, 2, 1, 509, 683, 0, 805, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 371, 535, 135, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 'npc_teleport', 1); 168 | diff --git a/src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp b/src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp 169 | new file mode 100644 170 | index 0000000..c40d861 171 | --- /dev/null 172 | +++ b/src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp 173 | @@ -0,0 +1,373 @@ 174 | +/** 175 | + * 176 | + * @File : sc_npc_teleport.cpp 177 | + * 178 | + * @Authors : Wilibald09 179 | + * 180 | + * @Date : 28/08/2008 181 | + * 182 | + * @Version : 1.2 183 | + * 184 | + **/ 185 | + 186 | + 187 | +#include "ScriptPCH.h" 188 | +#include "sc_npc_teleport.h" 189 | + 190 | +#define TELE nsNpcTel::CatDest 191 | +#define PAGE nsNpcTel::Page 192 | +#define PAGEI PAGE::Instance 193 | + 194 | + 195 | +nsNpcTel::VCatDest nsNpcTel::TabCatDest; 196 | + 197 | + 198 | +uint32 PAGE::operator [] (Player * const player) const 199 | +{ 200 | + for (VInst_t i(0); i < m_TabInstance.size(); ++i) 201 | + { 202 | + if (m_TabInstance[i].GetPlayer() == player) 203 | + return m_TabInstance[i].GetPageId(); 204 | + } 205 | + return 0; 206 | +} 207 | + 208 | +PAGE::Instance & PAGE::operator () (Player * const player) 209 | +{ 210 | + for (VInst_t i(0); i < m_TabInstance.size(); ++i) 211 | + { 212 | + if (m_TabInstance[i].GetPlayer() == player) 213 | + return m_TabInstance[i]; 214 | + } 215 | + m_TabInstance.push_back(Instance(player)); 216 | + return m_TabInstance.back(); 217 | +} 218 | + 219 | +PAGE::Instance & PAGEI::operator = (const uint32 &id) 220 | +{ 221 | + m_PageId = id; 222 | + return *this; 223 | +} 224 | + 225 | +PAGE::Instance & PAGEI::operator ++ (void) 226 | +{ 227 | + ++m_PageId; 228 | + return *this; 229 | +} 230 | + 231 | +PAGE::Instance PAGEI::operator ++ (int32) 232 | +{ 233 | + Instance tmp (*this); 234 | + ++m_PageId; 235 | + return tmp; 236 | +} 237 | + 238 | +PAGE::Instance & PAGEI::operator -- (void) 239 | +{ 240 | + --m_PageId; 241 | + return *this; 242 | +} 243 | + 244 | +PAGE::Instance PAGEI::operator -- (int32) 245 | +{ 246 | + Instance tmp (*this); 247 | + --m_PageId; 248 | + return tmp; 249 | +} 250 | + 251 | +TELE::CatDest(const uint32 &id, const std::string &name, 252 | + const Flag &flag, const uint64 &data0, const uint32 &data1) 253 | + : m_id(id), m_name(name), m_flag(flag), m_data0(data0), m_data1(data1) 254 | +{ 255 | + m_TabDest.clear(); 256 | +} 257 | + 258 | +std::string TELE::GetName(const bool IsGM /* = false */) const 259 | +{ 260 | + if (!IsGM || m_flag != FLAG_TEAM) 261 | + return m_name; 262 | + 263 | + switch (m_data0) 264 | + { 265 | + case TEAM_HORDE: return std::string(m_name + " (H)"); 266 | + case TEAM_ALLIANCE: return std::string(m_name + " (A)"); 267 | + } 268 | + return m_name; 269 | +} 270 | + 271 | +bool TELE::IsAllowedToTeleport(Player * const player) const 272 | +{ 273 | + if (player->isGameMaster()) 274 | + { 275 | + if (m_flag == FLAG_GMLEVEL) 276 | + return player->GetSession()->GetSecurity() >= m_data0; 277 | + return true; 278 | + } 279 | + 280 | + switch (m_flag) 281 | + { 282 | + case FLAG_TEAM: 283 | + switch (m_data0) 284 | + { 285 | + case TEAM_HORDE: return player->GetTeam() == HORDE; 286 | + case TEAM_ALLIANCE: return player->GetTeam() == ALLIANCE; 287 | + case TEAM_ALL: return true; 288 | + } 289 | + 290 | + case FLAG_GUILD: 291 | + return player->GetGuildId() == m_data0; 292 | + 293 | + case FLAG_GMLEVEL: 294 | + return player->GetSession()->GetSecurity() >= m_data0; 295 | + 296 | + case FLAG_ISGM: 297 | + return player->isGameMaster(); 298 | + 299 | + case FLAG_ACCOUNT: 300 | + return player->GetSession()->GetAccountId() == m_data0; 301 | + 302 | + case FLAG_LEVEL: 303 | + return player->getLevel() >= m_data0; 304 | + 305 | + case FLAG_ITEM: 306 | + return player->HasItemCount(m_data0, m_data1, true); 307 | + 308 | + case FLAG_QUEST: 309 | + if (m_data1 < MAX_QUEST_STATUS) 310 | + return player->GetQuestStatus(m_data0) == m_data1; 311 | + return player->GetQuestRewardStatus(m_data0); 312 | + 313 | + case FLAG_GENDER: 314 | + return player->getGender() == m_data0; 315 | + 316 | + case FLAG_RACE: 317 | + return player->getRace() == m_data0; 318 | + 319 | + case FLAG_CLASS: 320 | + return player->getClass() == m_data0; 321 | + 322 | + case FLAG_REPUTATION: 323 | + return player->GetReputationRank(m_data0) >= m_data1; 324 | + 325 | + case FLAG_PLAYER: 326 | + return player->GetGUID() == m_data0; 327 | + } 328 | + 329 | + sLog->outError("Invalid flag (category: %u). Important problem...", GetCatID()); 330 | + return false; 331 | +} 332 | + 333 | +uint32 TELE::CountOfCategoryAllowedBy(Player * const player) 334 | +{ 335 | + uint32 count (0); 336 | + for (VCatDest_t i(0); i < TabCatDest.size(); ++i) 337 | + { 338 | + if (TabCatDest[i].IsAllowedToTeleport(player)) 339 | + ++count; 340 | + } 341 | + return count; 342 | +} 343 | + 344 | +bool nsNpcTel::IsValidData(const uint32 &cat, const Flag &flag, 345 | + const uint64 &data0, const uint32 &data1) 346 | +{ 347 | + switch(flag) 348 | + { 349 | + case FLAG_TEAM: 350 | + if (data1) 351 | + sLog->outError("Invalid data1 (category: %u).", cat); 352 | + if (data0 < MAX_FLAG_TEAM) 353 | + return true; 354 | + sLog->outError("Invalid data0 (Team) (category: %u).", cat); 355 | + return false; 356 | + 357 | + case FLAG_GUILD: 358 | + if (data1) 359 | + sLog->outError("Invalid data1 (category: %u).", cat); 360 | + if (data0) 361 | + return true; 362 | + sLog->outError("Invalid data0 (GuildID) (category: %u).", cat); 363 | + return false; 364 | + 365 | + case FLAG_GMLEVEL: 366 | + if (data1) 367 | + sLog->outError("Invalid data1 (category: %u).", cat); 368 | + if (0 < data0 && data0 < 256) 369 | + return true; 370 | + sLog->outError("Invalid data0 (GmLevel) (category: %u).", cat); 371 | + return false; 372 | + 373 | + case FLAG_ISGM: 374 | + if (data0) 375 | + sLog->outError("Invalid data0 (category: %u).", cat); 376 | + if (data1) 377 | + sLog->outError("Invalid data1 (category: %u).", cat); 378 | + return true; 379 | + 380 | + case FLAG_ACCOUNT: 381 | + if (data1) 382 | + sLog->outError("Invalid data1 (category: %u).", cat); 383 | + if (data0) 384 | + return true; 385 | + sLog->outError("Invalid data0 (AccountID) (category: %u).", cat); 386 | + return false; 387 | + 388 | + case FLAG_LEVEL: 389 | + if (data1) 390 | + sLog->outError("Invalid data1 (category: %u).", cat); 391 | + if (0 < data0 && data0 < 256) 392 | + return true; 393 | + sLog->outError("Invalid data0 (Level) (category: %u).", cat); 394 | + return false; 395 | + 396 | + case FLAG_ITEM: 397 | + if (!data0) 398 | + { 399 | + sLog->outError("Invalid data0 (ItemID) (category: %u).", cat); 400 | + return false; 401 | + } 402 | + if (data1) 403 | + return true; 404 | + sLog->outError("Invalid data1 (Item Count) (category: %u).", cat); 405 | + return false; 406 | + 407 | + case FLAG_QUEST: 408 | + if (!data0) 409 | + { 410 | + sLog->outError("Invalid data0 (QuestID) (category: %u).", cat); 411 | + return false; 412 | + } 413 | + if (data1 < MAX_QUEST_STATUS + 1) 414 | + return true; 415 | + sLog->outError("Invalid data1 (Quest Status) (category: %u).", cat); 416 | + return false; 417 | + 418 | + case FLAG_GENDER: 419 | + if (data1) 420 | + sLog->outError("Invalid data1 (category: %u).", cat); 421 | + if (data0 < GENDER_NONE) 422 | + return true; 423 | + sLog->outError("Invalid data0 (Gender) (category: %u).", cat); 424 | + return false; 425 | + 426 | + case FLAG_RACE: 427 | + if (data1) 428 | + sLog->outError("Invalid data1 (category: %u).", cat); 429 | + if (0 < data0 && data0 < MAX_RACES) 430 | + return true; 431 | + sLog->outError("Invalid data0 (Race) (category: %u).", cat); 432 | + return false; 433 | + 434 | + case FLAG_CLASS: 435 | + if (data1) 436 | + sLog->outError("Invalid data1 (category: %u).", cat); 437 | + if (0 < data0 && data0 < MAX_CLASSES) 438 | + return true; 439 | + sLog->outError("Invalid data0 (Class) (category: %u).", cat); 440 | + return false; 441 | + 442 | + case FLAG_REPUTATION: 443 | + if (!data0) 444 | + { 445 | + sLog->outError("Invalid data0 (Faction/Reputation) (category: %u).", cat); 446 | + return false; 447 | + } 448 | + if (data1 <= REP_EXALTED) 449 | + return true; 450 | + sLog->outError("Invalid data1 (Faction/Reputation) (category: %u).", cat); 451 | + return false; 452 | + 453 | + case FLAG_PLAYER: 454 | + if (data1) 455 | + sLog->outError("Invalid data1 (category: %u).", cat); 456 | + if (data0) 457 | + return true; 458 | + sLog->outError("Invalid data0 (PlayerGuid) (category: %u).", cat); 459 | + return false; 460 | + } 461 | + 462 | + sLog->outError("Invalid flag (category: %u).", cat); 463 | + return false; 464 | +} 465 | + 466 | +void LoadNpcTele(void) 467 | +{ 468 | + const char *Table[] = 469 | + { 470 | + "custom_npc_tele_category", 471 | + "custom_npc_tele_destination", 472 | + "custom_npc_tele_association", 473 | + }; 474 | + 475 | + 476 | + QueryResult result = WorldDatabase.PQuery( 477 | + "SELECT `flag`, `data0`, `data1`, `cat_id`, C.`name` `namecat`, D.`name` `namedest`, " 478 | + // 0 1 2 3 4 5 479 | + "`pos_X`, `pos_Y`, `pos_Z`, `orientation`, `map`, `level`, `cost` " 480 | + // 6 7 8 9 10 11 12 481 | + "FROM `%s` C, `%s` D, `%s` A " 482 | + "WHERE C.`id` = `cat_id` AND D.`id` = `dest_id` " 483 | + "ORDER BY `namecat`, `cat_id`, `namedest`", Table[0], Table[1], Table[2]); 484 | + 485 | + nsNpcTel::TabCatDest.clear(); 486 | + 487 | + if (result) 488 | + { 489 | + sLog->outString( "TSCR: Loading %s, %s and %s...", Table[0], Table[1], Table[2]); 490 | + 491 | + uint32 catid = 0; 492 | + uint32 nbDest = 0; 493 | + bool IsValidCat = true; 494 | + bool FirstTime = true; 495 | + 496 | + do 497 | + { 498 | + Field *fields = result->Fetch(); 499 | + 500 | + if (!IsValidCat && catid == fields[3].GetUInt32() && !FirstTime) 501 | + continue; 502 | + 503 | + IsValidCat = true; 504 | + FirstTime = false; 505 | + 506 | + if (!nsNpcTel::IsValidData(fields[3].GetUInt32(), (nsNpcTel::Flag)fields[0].GetUInt8(), 507 | + fields[1].GetUInt64(), fields[2].GetUInt32())) 508 | + { 509 | + IsValidCat = false; 510 | + catid = fields[3].GetUInt32(); 511 | + continue; 512 | + } 513 | + 514 | + if (catid != fields[3].GetUInt32()) 515 | + { 516 | + catid = fields[3].GetUInt32(); 517 | + nsNpcTel::CatDest categorie (catid, fields[4].GetString(), (nsNpcTel::Flag)fields[0].GetUInt8(), 518 | + fields[1].GetUInt64(), fields[2].GetUInt32()); 519 | + nsNpcTel::TabCatDest.push_back(categorie); 520 | + } 521 | + 522 | + nsNpcTel::Dest item = 523 | + { 524 | + fields[5].GetString(), // Name 525 | + fields[6].GetFloat(), // X 526 | + fields[7].GetFloat(), // Y 527 | + fields[8].GetFloat(), // Z 528 | + fields[9].GetFloat(), // Orientation 529 | + fields[10].GetUInt16(), // Map 530 | + fields[11].GetUInt8(), // Level 531 | + fields[12].GetUInt32(), // Cost 532 | + }; 533 | + 534 | + nsNpcTel::TabCatDest.back().AddDest(item); 535 | + ++nbDest; 536 | + } while (result->NextRow()); 537 | + 538 | + sLog->outString(""); 539 | + sLog->outString("TSCR: >> Loaded %u npc_teleport.", nbDest); 540 | + } else sLog->outString("TSCR: WARNING >> Loaded 0 npc_teleport."); 541 | +} 542 | + 543 | + 544 | +#undef TELE 545 | +#undef PAGE 546 | +#undef PAGEI 547 | diff --git a/src/server/game/AI/ScriptedAI/sc_npc_teleport.h b/src/server/game/AI/ScriptedAI/sc_npc_teleport.h 548 | new file mode 100644 549 | index 0000000..4830245 550 | --- /dev/null 551 | +++ b/src/server/game/AI/ScriptedAI/sc_npc_teleport.h 552 | @@ -0,0 +1,151 @@ 553 | +/** 554 | + * 555 | + * @File : sc_npc_teleport.h 556 | + * 557 | + * @Authors : Wilibald09 558 | + * 559 | + * @Date : 19/08/2008 560 | + * 561 | + * @Version : 1.2 562 | + * 563 | + **/ 564 | + 565 | + 566 | +#ifndef SC_NPC_TELEPORT_H 567 | +#define SC_NPC_TELEPORT_H 568 | + 569 | +#include 570 | + 571 | + 572 | +namespace nsNpcTel 573 | +{ 574 | + // Different types of permissions 575 | + enum Flag 576 | + { 577 | + FLAG_TEAM = 0, 578 | + FLAG_GUILD = 1, 579 | + FLAG_GMLEVEL = 2, 580 | + FLAG_ISGM = 3, 581 | + FLAG_ACCOUNT = 4, 582 | + FLAG_LEVEL = 5, 583 | + FLAG_ITEM = 6, 584 | + FLAG_QUEST = 7, 585 | + FLAG_GENDER = 8, 586 | + FLAG_RACE = 9, 587 | + FLAG_CLASS = 10, 588 | + FLAG_REPUTATION = 11, 589 | + FLAG_PLAYER = 12, 590 | + MAX_FLAG, 591 | + }; 592 | + 593 | + // Different parameters of FLAG_TEAM 594 | + enum 595 | + { 596 | + TEAM_ALL = 0, 597 | + TEAM_ALLIANCE = 1, 598 | + TEAM_HORDE = 2, 599 | + MAX_FLAG_TEAM, 600 | + }; 601 | + 602 | + // Structure representing the destinations 603 | + struct Dest 604 | + { 605 | + std::string m_name; 606 | + float m_X, m_Y, m_Z, m_orient; 607 | + uint16 m_map; 608 | + uint8 m_level; 609 | + uint32 m_cost; 610 | + }; 611 | + 612 | + // Class representing the categories of destinations 613 | + class CatDest 614 | + { 615 | + public: 616 | + 617 | + typedef std::vector VDest; 618 | + typedef VDest::size_type VDest_t; 619 | + 620 | + CatDest(const uint32 &id, const std::string &name, 621 | + const Flag &flag, const uint64 &data0, const uint32 &data1); 622 | + 623 | + void AddDest (const Dest &item) { m_TabDest.push_back(item); } 624 | + Dest GetDest (const uint32 &id) const { return m_TabDest[id]; } 625 | + uint32 GetCatID (void) const { return m_id; } 626 | + uint32 size (void) const { return m_TabDest.size(); } 627 | + 628 | + std::string GetName(const bool IsGM = false) const; 629 | + bool IsAllowedToTeleport(Player * const player) const; 630 | + 631 | + static uint32 CountOfCategoryAllowedBy(Player * const player); 632 | + 633 | + private: 634 | + 635 | + uint32 m_id; 636 | + std::string m_name; 637 | + Flag m_flag; 638 | + uint64 m_data0; 639 | + uint32 m_data1; 640 | + VDest m_TabDest; 641 | + }; 642 | + 643 | + // Class page for current player 644 | + class Page 645 | + { 646 | + protected: 647 | + 648 | + // Class instance for current player 649 | + class Instance 650 | + { 651 | + public: 652 | + 653 | + Instance(Player * const player, const uint32 &PageId = 0) 654 | + : m_player(player), m_PageId(PageId) {} 655 | + 656 | + Instance & operator = (const uint32 &id); 657 | + Instance & operator ++ (void); 658 | + Instance operator ++ (int32); 659 | + Instance & operator -- (void); 660 | + Instance operator -- (int32); 661 | + 662 | + uint32 GetPageId(void) const { return m_PageId; } 663 | + Player * GetPlayer(void) const { return m_player; } 664 | + 665 | + private: 666 | + 667 | + Player *m_player; 668 | + uint32 m_PageId; 669 | + }; 670 | + 671 | + 672 | + public: 673 | + 674 | + typedef std::vector VInst; 675 | + typedef VInst::size_type VInst_t; 676 | + 677 | + Page(void) { m_TabInstance.clear(); } 678 | + 679 | + Instance & operator () (Player * const player); 680 | + uint32 operator [] (Player * const player) const; 681 | + 682 | + 683 | + private: 684 | + 685 | + VInst m_TabInstance; 686 | + }; 687 | + 688 | + typedef std::vector VCatDest; 689 | + typedef VCatDest::size_type VCatDest_t; 690 | + 691 | + // Verification of data integrity 692 | + bool IsValidData(const uint32 &cat, const Flag &flag, 693 | + const uint64 &data0, const uint32 &data1); 694 | + 695 | + extern VCatDest TabCatDest; 696 | +} 697 | + 698 | +// Loading contents of database 699 | +void LoadNpcTele(void); 700 | + 701 | +extern WorldDatabaseWorkerPool WorldDatabase; 702 | + 703 | +#endif 704 | diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp 705 | index 794bb10..8dcac68 100755 706 | --- a/src/server/game/Scripting/ScriptLoader.cpp 707 | +++ b/src/server/game/Scripting/ScriptLoader.cpp 708 | @@ -25,6 +25,9 @@ void AddSC_example_gossip_codebox(); 709 | void AddSC_example_misc(); 710 | void AddSC_example_commandscript(); 711 | 712 | +//TeleNPC2 713 | +void AddSC_npc_teleport(); 714 | + 715 | // spells 716 | void AddSC_deathknight_spell_scripts(); 717 | void AddSC_druid_spell_scripts(); 718 | @@ -1202,6 +1205,7 @@ void AddCustomScripts() 719 | { 720 | #ifdef SCRIPTS 721 | /* This is where custom scripts should be added. */ 722 | - 723 | + //TeleNPC2 724 | + AddSC_npc_teleport(); 725 | #endif 726 | } 727 | diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp 728 | index a0a1c82..66ce84b 100755 729 | --- a/src/server/game/Scripting/ScriptMgr.cpp 730 | +++ b/src/server/game/Scripting/ScriptMgr.cpp 731 | @@ -25,6 +25,7 @@ 732 | #include "ScriptLoader.h" 733 | #include "ScriptSystem.h" 734 | #include "Transport.h" 735 | +#include "sc_npc_teleport.h" 736 | 737 | // Utility macros to refer to the script registry. 738 | #define SCR_REG_MAP(T) ScriptRegistry::ScriptMap 739 | @@ -180,6 +181,8 @@ void ScriptMgr::Initialize() 740 | uint32 oldMSTime = getMSTime(); 741 | 742 | LoadDatabase(); 743 | + // Load TeleNPC2 - maybe not the best place to load it ... 744 | + LoadNpcTele(); 745 | 746 | sLog->outString("Loading C++ scripts"); 747 | 748 | diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt 749 | index 17d4bfc..90eae34 100644 750 | --- a/src/server/scripts/CMakeLists.txt 751 | +++ b/src/server/scripts/CMakeLists.txt 752 | @@ -31,6 +31,9 @@ include(Examples/CMakeLists.txt) 753 | 754 | set(scripts_STAT_SRCS 755 | ${scripts_STAT_SRCS} 756 | + Custom/npc_teleport.cpp 757 | + ../game/AI/ScriptedAI/sc_npc_teleport.cpp 758 | + ../game/AI/ScriptedAI/sc_npc_teleport.h 759 | ../game/AI/ScriptedAI/ScriptedEscortAI.cpp 760 | ../game/AI/ScriptedAI/ScriptedCreature.cpp 761 | ../game/AI/ScriptedAI/ScriptedFollowerAI.cpp 762 | diff --git a/src/server/scripts/Custom/npc_teleport.cpp b/src/server/scripts/Custom/npc_teleport.cpp 763 | new file mode 100644 764 | index 0000000..1e51336 765 | --- /dev/null 766 | +++ b/src/server/scripts/Custom/npc_teleport.cpp 767 | @@ -0,0 +1,221 @@ 768 | +/** 769 | + * 770 | + * @File : npc_teleport.cpp 771 | + * 772 | + * @Authors : Wilibald09 773 | + * 774 | + * @Date : 19/08/2008 775 | + * 776 | + * @Version : 1.2 777 | + * 778 | + **/ 779 | + 780 | + 781 | + 782 | +#include "ScriptPCH.h" 783 | +#include "sc_npc_teleport.h" 784 | +#include 785 | + 786 | +#define GOSSIP_SHOW_DEST 1000 787 | +#define GOSSIP_TELEPORT 1001 788 | +#define GOSSIP_NEXT_PAGEC 1002 789 | +#define GOSSIP_PREV_PAGEC 1003 790 | +#define GOSSIP_NEXT_PAGED 1004 791 | +#define GOSSIP_PREV_PAGED 1005 792 | +#define GOSSIP_MAIN_MENU 1006 793 | + 794 | +#define SPELL_ID_PASSIVE_RESURRECTION_SICKNESS 15007 795 | +#define SPELL_VISUAL_TELEPORT 35517 796 | + 797 | +#define NB_ITEM_PAGE 10 798 | +#define MSG_CAT 100000 799 | +#define MSG_DEST 100001 800 | + 801 | +#define NEXT_PAGE "-> [Next Page]" 802 | +#define PREV_PAGE "<- [Previous Page]" 803 | +#define MAIN_MENU "<= [Main Menu]" 804 | + 805 | + 806 | +using namespace nsNpcTel; 807 | + 808 | + 809 | +namespace 810 | +{ 811 | + Page PageC, PageD; 812 | + Page Cat; 813 | + 814 | + // Conversion function int->string 815 | + std::string ConvertStr(const int64 &val) 816 | + { 817 | + std::ostringstream ostr; 818 | + ostr << val; 819 | + return ostr.str(); 820 | + } 821 | + 822 | + // Conversion function intMoney->stringMoney 823 | + std::string ConvertMoney(const uint32 &Money) 824 | + { 825 | + std::string Str(ConvertStr(Money)); 826 | + uint32 SizeStr = Str.length(); 827 | + 828 | + if (SizeStr > 4) 829 | + Str = Str.insert(Str.length()-4, "po"); 830 | + if (SizeStr > 2) 831 | + Str = Str.insert(Str.length()-2, "pa"); 832 | + Str += "pc"; 833 | + 834 | + return Str; 835 | + } 836 | + 837 | + // Teleport Player 838 | + void Teleport(Player * const player, const uint16 &map, 839 | + const float &X, const float &Y, const float &Z, const float &orient) 840 | + { 841 | + player->CastSpell(player, SPELL_VISUAL_TELEPORT, true); 842 | + player->TeleportTo(map, X, Y, Z, orient); 843 | + } 844 | + 845 | + // Display categories 846 | + void AffichCat(Player * const player, Creature * const creature) 847 | + { 848 | + if (PageC[player] > 0) 849 | + player->ADD_GOSSIP_ITEM(7, PREV_PAGE, GOSSIP_PREV_PAGEC, 0); 850 | + 851 | + VCatDest_t i (PageC[player] * NB_ITEM_PAGE); 852 | + for ( ; i < TabCatDest.size() && i < (NB_ITEM_PAGE * (PageC[player] + 1)); ++i) 853 | + { 854 | + if (TabCatDest[i].IsAllowedToTeleport(player)) 855 | + player->ADD_GOSSIP_ITEM(7, TabCatDest[i].GetName(player->isGameMaster()).c_str(), GOSSIP_SHOW_DEST, i); 856 | + } 857 | + 858 | + if (i < TabCatDest.size()) 859 | + player->ADD_GOSSIP_ITEM(7, NEXT_PAGE, GOSSIP_NEXT_PAGEC, 0); 860 | + 861 | + player->SEND_GOSSIP_MENU(MSG_CAT, creature->GetGUID()); 862 | + } 863 | + 864 | + // Display destination categories 865 | + void AffichDest(Player * const player, Creature * const creature) 866 | + { 867 | + if (PageD[player] > 0) 868 | + player->ADD_GOSSIP_ITEM(7, PREV_PAGE, GOSSIP_PREV_PAGED, 0); 869 | + 870 | + CatDest::VDest_t i (PageD[player] * NB_ITEM_PAGE); 871 | + for ( ; i < TabCatDest[Cat[player]].size() && i < (NB_ITEM_PAGE * (PageD[player] + 1)); ++i) 872 | + { 873 | + player->ADD_GOSSIP_ITEM(5, TabCatDest[Cat[player]].GetDest(i).m_name.c_str(), GOSSIP_TELEPORT, i); 874 | + } 875 | + 876 | + if (i < TabCatDest[Cat[player]].size()) 877 | + player->ADD_GOSSIP_ITEM(7, NEXT_PAGE, GOSSIP_NEXT_PAGED, 0); 878 | + 879 | + if (CatDest::CountOfCategoryAllowedBy(player) > 1) 880 | + player->ADD_GOSSIP_ITEM(7, MAIN_MENU, GOSSIP_MAIN_MENU, 0); 881 | + 882 | + player->SEND_GOSSIP_MENU(MSG_DEST, creature->GetGUID()); 883 | + } 884 | + 885 | + // Verification before teleportation 886 | + void ActionTeleport(Player * const player, Creature * const creature, const uint32 &id) 887 | + { 888 | + Dest dest (TabCatDest[Cat[player]].GetDest(id)); 889 | + 890 | + if (player->getLevel() < dest.m_level && !player->isGameMaster()) 891 | + { 892 | + std::string msg ("You do not have the required level. This destination requires level " + ConvertStr(dest.m_level) + "."); 893 | + creature->MonsterWhisper(msg.c_str(), player->GetGUID()); 894 | + return; 895 | + } 896 | + 897 | + if (player->GetMoney() < dest.m_cost && !player->isGameMaster()) 898 | + { 899 | + std::string msg ("You do not have enough money. The price for teleportation is " + ConvertMoney(dest.m_cost) + "."); 900 | + creature->MonsterWhisper(msg.c_str(), player->GetGUID()); 901 | + return; 902 | + } 903 | + 904 | + if (!player->isGameMaster() && dest.m_cost) 905 | + player->ModifyMoney(-1 * dest.m_cost); 906 | + 907 | + Teleport(player, dest.m_map, dest.m_X, dest.m_Y, dest.m_Z, dest.m_orient); 908 | + } 909 | +} 910 | + 911 | +class npc_teleport : public CreatureScript 912 | +{ 913 | +public: 914 | + npc_teleport() : CreatureScript("npc_teleport") {} 915 | + 916 | +bool OnGossipHello(Player *player, Creature *creature) 917 | +{ 918 | + PageC(player) = PageD(player) = Cat(player) = 0; 919 | + 920 | + if(player->isInCombat()) 921 | + { 922 | + player->CLOSE_GOSSIP_MENU(); 923 | + creature->MonsterWhisper("You are in combat. Come back later", player->GetGUID()); 924 | + return true; 925 | + } 926 | + AffichCat(player, creature); 927 | + return true; 928 | +} 929 | + 930 | +bool OnGossipSelect(Player *player, Creature *creature, uint32 sender, uint32 param) 931 | +{ 932 | + player->PlayerTalkClass->ClearMenus(); 933 | + switch(sender) 934 | + { 935 | + // Display destinations 936 | + case GOSSIP_SHOW_DEST: 937 | + Cat(player) = param; 938 | + AffichDest(player, creature); 939 | + break; 940 | + 941 | + // Previous categories page 942 | + case GOSSIP_PREV_PAGEC: 943 | + --PageC(player); 944 | + AffichCat(player, creature); 945 | + break; 946 | + 947 | + // Next page categories 948 | + case GOSSIP_NEXT_PAGEC: 949 | + ++PageC(player); 950 | + AffichCat(player, creature); 951 | + break; 952 | + 953 | + // Previous destinations page 954 | + case GOSSIP_PREV_PAGED: 955 | + --PageD(player); 956 | + AffichDest(player, creature); 957 | + break; 958 | + 959 | + // Next destination page 960 | + case GOSSIP_NEXT_PAGED: 961 | + ++PageD(player); 962 | + AffichDest(player, creature); 963 | + break; 964 | + 965 | + // Display main menu 966 | + case GOSSIP_MAIN_MENU: 967 | + OnGossipHello(player, creature); 968 | + break; 969 | + 970 | + // Teleportation 971 | + case GOSSIP_TELEPORT: 972 | + player->CLOSE_GOSSIP_MENU(); 973 | + if(player->HasAura(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS,0)) { 974 | + creature->CastSpell(player,38588,false); // Healing effect 975 | + player->RemoveAurasDueToSpell(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS); 976 | + } 977 | + 978 | + ActionTeleport(player, creature, param); 979 | + break; 980 | + } 981 | + return true; 982 | +} 983 | +}; 984 | + 985 | +void AddSC_npc_teleport() 986 | +{ 987 | + new npc_teleport; 988 | +} 989 | -- 990 | 1.7.3.1.msysgit.0 991 | 992 | -------------------------------------------------------------------------------- /11010-independent/0001-Wintergrasp.patch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevnull/thedevnull-patches/903606c3c61ae92f78276c1c5b5afa2c480518be/11010-independent/0001-Wintergrasp.patch -------------------------------------------------------------------------------- /11024-independent/0001-passive_anticheat.patch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevnull/thedevnull-patches/903606c3c61ae92f78276c1c5b5afa2c480518be/11024-independent/0001-passive_anticheat.patch -------------------------------------------------------------------------------- /11024-independent/0001-telenpc2.patch: -------------------------------------------------------------------------------- 1 | From 9594c5038a6c810a2b09da2ea850e34bd0027649 Mon Sep 17 00:00:00 2001 2 | From: thedevnull 3 | Date: Fri, 14 Jan 2011 20:33:38 -0200 4 | Subject: [PATCH] telenpc2 5 | Signed-off-by: thedevnull 6 | 7 | --- 8 | README.NPCTELEPORT | 14 + 9 | sql/tools/setup_npc_teleport.sql | 119 +++++++ 10 | src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp | 373 +++++++++++++++++++++ 11 | src/server/game/AI/ScriptedAI/sc_npc_teleport.h | 151 +++++++++ 12 | src/server/game/Scripting/ScriptLoader.cpp | 6 +- 13 | src/server/game/Scripting/ScriptMgr.cpp | 3 + 14 | src/server/scripts/CMakeLists.txt | 3 + 15 | src/server/scripts/Custom/npc_teleport.cpp | 221 ++++++++++++ 16 | 8 files changed, 889 insertions(+), 1 deletions(-) 17 | create mode 100644 README.NPCTELEPORT 18 | create mode 100644 sql/tools/setup_npc_teleport.sql 19 | create mode 100644 src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp 20 | create mode 100644 src/server/game/AI/ScriptedAI/sc_npc_teleport.h 21 | create mode 100644 src/server/scripts/Custom/npc_teleport.cpp 22 | 23 | diff --git a/README.NPCTELEPORT b/README.NPCTELEPORT 24 | new file mode 100644 25 | index 0000000..015c9c2 26 | --- /dev/null 27 | +++ b/README.NPCTELEPORT 28 | @@ -0,0 +1,14 @@ 29 | +NPC Teleport for Trinity 30 | + 31 | +Original author : Wilibald09 32 | + 33 | +Allows you to add a custom NPC for teleporting, using .npc add 100000. 34 | +The default NPC is entry 100000. 35 | + 36 | +All settings are located in the DB, so you can customize and add destinations, 37 | +set level restrictions and also charge the player for teleporting. 38 | + 39 | +Installation: 40 | + 41 | +Run the query setup_npc_teleport.sql located in the trinity sql directory on 42 | +your world DB. This will setup the DB and you can customize from there. 43 | diff --git a/sql/tools/setup_npc_teleport.sql b/sql/tools/setup_npc_teleport.sql 44 | new file mode 100644 45 | index 0000000..03b9e93 46 | --- /dev/null 47 | +++ b/sql/tools/setup_npc_teleport.sql 48 | @@ -0,0 +1,119 @@ 49 | +DROP TABLE IF EXISTS `custom_npc_tele_category`; 50 | +CREATE TABLE `custom_npc_tele_category` ( 51 | + `id` int(6) unsigned NOT NULL default '0', 52 | + `name` varchar(255) NOT NULL default '', 53 | + `flag` tinyint(3) unsigned NOT NULL default '0', 54 | + `data0` bigint(20) unsigned NOT NULL default '0', 55 | + `data1` int(6) unsigned NOT NULL default '0', 56 | + PRIMARY KEY (`id`) 57 | +) ENGINE=MyISAM DEFAULT CHARSET=utf8; 58 | + 59 | +DROP TABLE IF EXISTS `custom_npc_tele_destination`; 60 | +CREATE TABLE `custom_npc_tele_destination` ( 61 | + `id` int(6) unsigned NOT NULL auto_increment, 62 | + `name` char(100) NOT NULL default '', 63 | + `pos_X` float NOT NULL default '0', 64 | + `pos_Y` float NOT NULL default '0', 65 | + `pos_Z` float NOT NULL default '0', 66 | + `map` smallint(5) unsigned NOT NULL default '0', 67 | + `orientation` float NOT NULL default '0', 68 | + `level` tinyint(3) unsigned NOT NULL default '0', 69 | + `cost` int(10) unsigned NOT NULL default '0', 70 | + PRIMARY KEY (`id`) 71 | +) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 72 | + 73 | +DROP TABLE IF EXISTS `custom_npc_tele_association`; 74 | +CREATE TABLE `custom_npc_tele_association` ( 75 | + `cat_id` int(6) unsigned NOT NULL default '0', 76 | + `dest_id` int(6) unsigned NOT NULL default '0', 77 | + PRIMARY KEY (`cat_id`, `dest_id`) 78 | +) ENGINE=MyISAM DEFAULT CHARSET=utf8; 79 | + 80 | +TRUNCATE `custom_npc_tele_category`; 81 | +INSERT INTO `custom_npc_tele_category` 82 | + (`id`, `name`, `flag`, `data0`, `data1`) 83 | +VALUES 84 | + (1, 'Cities', 0, 1, 0), 85 | + (2, 'Cities', 0, 2, 0), 86 | + (3, 'Battlegrounds', 0, 1, 0), 87 | + (4, 'Battlegrounds', 0, 2, 0), 88 | + (5, 'Arenas', 0, 0, 0), 89 | + (6, '[Instances Lvl 1-60]', 0, 0, 0), 90 | + (7, '[Instances Lvl 60+]', 5, 60, 0), 91 | + (8, '[Instances Lvl 70+]', 5, 70, 0), 92 | + (9, 'Destinations MJ', 3, 0, 0); 93 | + 94 | +TRUNCATE `custom_npc_tele_destination`; 95 | +INSERT INTO `custom_npc_tele_destination` 96 | + (`id`, `name`, `pos_X`, `pos_Y`, `pos_Z`, `map`, `orientation`, `level`, `cost`) 97 | +VALUES 98 | + (1, 'Alterac Valley', 883.187, -489.375, 96.7618, 30, 3.06932, 0, 0), 99 | + (2, 'Alterac Valley', -818.155, -623.043, 54.0884, 30, 2.1, 0, 0), 100 | + (3, 'Arathi Basin', 686.053, 683.165, -12.9149, 529, 0.18, 0, 0), 101 | + (4, 'Arathi Basin', 1308.68, 1306.03, -9.0107, 529, 3.91285, 0, 0), 102 | + (5, 'Black Temple', -3610.72, 324.988, 37.4, 530, 3.28298, 0, 0), 103 | + (6, 'Blackfathom Deeps', 4254.58, 664.74, -29.04, 1, 1.97, 0, 0), 104 | + (7, 'Blackrock Depths', -7301.03, -913.19, 165.37, 0, 0.08, 0, 0), 105 | + (8, 'Blackrock Spire', -7535.43, -1212.04, 285.45, 0, 5.29, 0, 0), 106 | + (9, 'Blackwing Lair', -7665.55, -1102.49, 400.679, 469, 0, 0, 0), 107 | + (10, 'Caverns of Time', -8173.66, -4746.36, 33.8423, 1, 4.93989, 0, 0), 108 | + (11, 'Circle of Blood', 2839.44, 5930.17, 11.1002, 530, 3.16284, 0, 0), 109 | + (12, 'Coilfang Reservoir', 517.288, 6976.28, 32.0072, 530, 0, 0, 0), 110 | + (13, 'Darnassus', 9947.52, 2482.73, 1316.21, 1, 0, 0, 0), 111 | + (14, 'Dire Maul', -3982.47, 1127.79, 161.02, 1, 0.05, 0, 0), 112 | + (15, 'Exodar', -4073.03, -12020.4, -1.47, 530, 0, 0, 0), 113 | + (16, 'Eye of the Storm', 2487.72, 1609.12, 1224.64, 566, 3.35671, 0, 0), 114 | + (17, 'Eye of the Storm', 1843.73, 1529.77, 1224.43, 566, 0.297579, 0, 0), 115 | + (18, 'Goldshire', -9464, 62, 56, 0, 0, 0, 0), 116 | + (19, 'Gruul\'s Lair', 3539.01, 5082.36, 1.69107, 530, 0, 0, 0), 117 | + (20, 'Gurubashi', -13261.3, 168.294, 35.0792, 0, 1.00688, 0, 0), 118 | + (21, 'Hellfire Citadel', -305.816, 3056.4, -2.47318, 530, 2.01, 0, 0), 119 | + (22, 'Ironforge', -4924.07, -951.95, 501.55, 0, 5.4, 0, 0), 120 | + (23, 'Isle Of Quel\'Danas', 12947.4, -6893.31, 5.68398, 530, 3.09154, 0, 0), 121 | + (24, 'Karazhan', -11118.8, -2010.84, 47.0807, 0, 0, 0, 0), 122 | + (25, 'Maraudon', -1433.33, 2955.34, 96.21, 1, 4.82, 0, 0), 123 | + (26, 'Molten Core', 1121.45, -454.317, -101.33, 230, 3.5, 0, 0), 124 | + (27, 'Naxxramas', 3125.18, -3748.02, 136.049, 0, 0, 0, 0), 125 | + (28, 'Onyxia\'s Lair', -4707.44, -3726.82, 54.6723, 1, 3.8, 0, 0), 126 | + (29, 'Orgrimmar', 1552.5, -4420.66, 8.94802, 1, 0, 0, 0), 127 | + (30, 'Razor Hill', 315.721, -4743.4, 10.4867, 1, 0, 0, 0), 128 | + (31, 'Razorfen Downs', -4645.08, -2470.85, 85.53, 1, 4.39, 0, 0), 129 | + (32, 'Razorfen Kraul', -4484.04, -1739.4, 86.47, 1, 1.23, 0, 0), 130 | + (33, 'Ring of Trials', -1999.94, 6581.71, 11.32, 530, 2.3, 0, 0), 131 | + (34, 'Ruins of Ahn\'Qiraj', -8409.03, 1498.83, 27.3615, 1, 2.49757, 0, 0), 132 | + (35, 'Scholomance', 1219.01, -2604.66, 85.61, 0, 0.5, 0, 0), 133 | + (36, 'Shadowfang Keep', -254.47, 1524.68, 76.89, 0, 1.56, 0, 0), 134 | + (37, 'Shattrath City', -1850.21, 5435.82, -10.9614, 530, 3.40391, 0, 0), 135 | + (38, 'Silvermoon', 9338.74, -7277.27, 13.7895, 530, 0, 0, 0), 136 | + (39, 'Stormwind', -8960.14, 516.266, 96.3568, 0, 0, 0, 0), 137 | + (40, 'Stratholme', 3263.54, -3379.46, 143.59, 0, 0, 0, 0), 138 | + (41, 'Tempest Keep', 3089.58, 1399.05, 187.653, 530, 4.79407, 0, 0), 139 | + (42, 'Temple of Ahn\'Qiraj', -8245.84, 1983.74, 129.072, 1, 0.936195, 0, 0), 140 | + (43, 'The Deadmines', -11212, 1658.58, 25.67, 0, 1.45, 0, 0), 141 | + (44, 'The Maul', -3761.49, 1133.43, 132.083, 1, 4.57259, 0, 0), 142 | + (45, 'The Scarlet Monastery', 2843.89, -693.74, 139.32, 0, 5.11, 0, 0), 143 | + (46, 'The Sunken Temple', -10346.9, -3851.9, -43.41, 0, 6.09, 0, 0), 144 | + (47, 'The Wailing Caverns', -722.53, -2226.3, 16.94, 1, 2.71, 0, 0), 145 | + (48, 'Thunder Bluff', -1290, 147.034, 129.682, 1, 4.919, 0, 0), 146 | + (49, 'Uldaman', -6119.7, -2957.3, 204.11, 0, 0.03, 0, 0), 147 | + (50, 'Undercity', 1819.71, 238.79, 60.5321, 0, 0, 0, 0), 148 | + (51, 'Warsong Gulch', 930.851, 1431.57, 345.537, 489, 0.015704, 0, 0), 149 | + (52, 'Warsong Gulch', 1525.95, 1481.66, 352.001, 489, 3.20756, 0, 0), 150 | + (53, 'Zul\'Aman', 6846.95, -7954.5, 170.028, 530, 4.61501, 0, 0), 151 | + (54, 'Zul\'Farrak', -6839.39, -2911.03, 8.87, 1, 0.41, 0, 0), 152 | + (55, 'Zul\'Gurub', -11916.7, -1212.82, 92.2868, 0, 4.6095, 0, 0), 153 | + (56, 'Ile des MJ', 16254, 16276.9, 14.5082, 1, 1.70269, 0, 0); 154 | + 155 | +TRUNCATE `custom_npc_tele_association`; 156 | +INSERT INTO `custom_npc_tele_association` 157 | + (`cat_id`, `dest_id`) 158 | +VALUES 159 | + (1, 13), (1, 15), (1, 18), (1, 22), (1, 23), (1, 37), (1, 39), (2, 23), (2, 29), (2, 30), (2, 37), (2, 38), (2, 48), (2, 50), (3, 1), (3, 4), (3, 16), (3, 52), (4, 2), (4, 3), (4, 17), (4, 51), (5, 11), (5, 20), (5, 33), (5, 44), (6, 6), (6, 7), (6, 8), (6, 14), (6, 25), (6, 31), (6, 32), (6, 35), (6, 36), (6, 40), (6, 43), (6, 45), (6, 46), (6, 47), (6, 49), (6, 54), (7, 9), (7, 26), (7, 27), (7, 28), (7, 34), (7, 42), (7, 55), (8, 5), (8, 10), (8, 12), (8, 19), (8, 21), (8, 24), (8, 41), (8, 53), (9, 56); 160 | + 161 | +-- `npc_text` 162 | +REPLACE INTO `npc_text` (`ID`, `text0_0`) VALUES 163 | + (100000, 'Choose your Category.'), 164 | + (100001, 'Choose your Destination.'); 165 | + 166 | +-- `creature_template` 167 | +INSERT INTO `creature_template` VALUES (100000, 0, 0, 0, 0, 0, 26502, 0, 0, 0, 'Abisal Vortex', '', '', 0, 83, 83, 0, 35, 35, 1, 1, 1.14286, 2, 1, 509, 683, 0, 805, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 371, 535, 135, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 'npc_teleport', 1); 168 | diff --git a/src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp b/src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp 169 | new file mode 100644 170 | index 0000000..c40d861 171 | --- /dev/null 172 | +++ b/src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp 173 | @@ -0,0 +1,373 @@ 174 | +/** 175 | + * 176 | + * @File : sc_npc_teleport.cpp 177 | + * 178 | + * @Authors : Wilibald09 179 | + * 180 | + * @Date : 28/08/2008 181 | + * 182 | + * @Version : 1.2 183 | + * 184 | + **/ 185 | + 186 | + 187 | +#include "ScriptPCH.h" 188 | +#include "sc_npc_teleport.h" 189 | + 190 | +#define TELE nsNpcTel::CatDest 191 | +#define PAGE nsNpcTel::Page 192 | +#define PAGEI PAGE::Instance 193 | + 194 | + 195 | +nsNpcTel::VCatDest nsNpcTel::TabCatDest; 196 | + 197 | + 198 | +uint32 PAGE::operator [] (Player * const player) const 199 | +{ 200 | + for (VInst_t i(0); i < m_TabInstance.size(); ++i) 201 | + { 202 | + if (m_TabInstance[i].GetPlayer() == player) 203 | + return m_TabInstance[i].GetPageId(); 204 | + } 205 | + return 0; 206 | +} 207 | + 208 | +PAGE::Instance & PAGE::operator () (Player * const player) 209 | +{ 210 | + for (VInst_t i(0); i < m_TabInstance.size(); ++i) 211 | + { 212 | + if (m_TabInstance[i].GetPlayer() == player) 213 | + return m_TabInstance[i]; 214 | + } 215 | + m_TabInstance.push_back(Instance(player)); 216 | + return m_TabInstance.back(); 217 | +} 218 | + 219 | +PAGE::Instance & PAGEI::operator = (const uint32 &id) 220 | +{ 221 | + m_PageId = id; 222 | + return *this; 223 | +} 224 | + 225 | +PAGE::Instance & PAGEI::operator ++ (void) 226 | +{ 227 | + ++m_PageId; 228 | + return *this; 229 | +} 230 | + 231 | +PAGE::Instance PAGEI::operator ++ (int32) 232 | +{ 233 | + Instance tmp (*this); 234 | + ++m_PageId; 235 | + return tmp; 236 | +} 237 | + 238 | +PAGE::Instance & PAGEI::operator -- (void) 239 | +{ 240 | + --m_PageId; 241 | + return *this; 242 | +} 243 | + 244 | +PAGE::Instance PAGEI::operator -- (int32) 245 | +{ 246 | + Instance tmp (*this); 247 | + --m_PageId; 248 | + return tmp; 249 | +} 250 | + 251 | +TELE::CatDest(const uint32 &id, const std::string &name, 252 | + const Flag &flag, const uint64 &data0, const uint32 &data1) 253 | + : m_id(id), m_name(name), m_flag(flag), m_data0(data0), m_data1(data1) 254 | +{ 255 | + m_TabDest.clear(); 256 | +} 257 | + 258 | +std::string TELE::GetName(const bool IsGM /* = false */) const 259 | +{ 260 | + if (!IsGM || m_flag != FLAG_TEAM) 261 | + return m_name; 262 | + 263 | + switch (m_data0) 264 | + { 265 | + case TEAM_HORDE: return std::string(m_name + " (H)"); 266 | + case TEAM_ALLIANCE: return std::string(m_name + " (A)"); 267 | + } 268 | + return m_name; 269 | +} 270 | + 271 | +bool TELE::IsAllowedToTeleport(Player * const player) const 272 | +{ 273 | + if (player->isGameMaster()) 274 | + { 275 | + if (m_flag == FLAG_GMLEVEL) 276 | + return player->GetSession()->GetSecurity() >= m_data0; 277 | + return true; 278 | + } 279 | + 280 | + switch (m_flag) 281 | + { 282 | + case FLAG_TEAM: 283 | + switch (m_data0) 284 | + { 285 | + case TEAM_HORDE: return player->GetTeam() == HORDE; 286 | + case TEAM_ALLIANCE: return player->GetTeam() == ALLIANCE; 287 | + case TEAM_ALL: return true; 288 | + } 289 | + 290 | + case FLAG_GUILD: 291 | + return player->GetGuildId() == m_data0; 292 | + 293 | + case FLAG_GMLEVEL: 294 | + return player->GetSession()->GetSecurity() >= m_data0; 295 | + 296 | + case FLAG_ISGM: 297 | + return player->isGameMaster(); 298 | + 299 | + case FLAG_ACCOUNT: 300 | + return player->GetSession()->GetAccountId() == m_data0; 301 | + 302 | + case FLAG_LEVEL: 303 | + return player->getLevel() >= m_data0; 304 | + 305 | + case FLAG_ITEM: 306 | + return player->HasItemCount(m_data0, m_data1, true); 307 | + 308 | + case FLAG_QUEST: 309 | + if (m_data1 < MAX_QUEST_STATUS) 310 | + return player->GetQuestStatus(m_data0) == m_data1; 311 | + return player->GetQuestRewardStatus(m_data0); 312 | + 313 | + case FLAG_GENDER: 314 | + return player->getGender() == m_data0; 315 | + 316 | + case FLAG_RACE: 317 | + return player->getRace() == m_data0; 318 | + 319 | + case FLAG_CLASS: 320 | + return player->getClass() == m_data0; 321 | + 322 | + case FLAG_REPUTATION: 323 | + return player->GetReputationRank(m_data0) >= m_data1; 324 | + 325 | + case FLAG_PLAYER: 326 | + return player->GetGUID() == m_data0; 327 | + } 328 | + 329 | + sLog->outError("Invalid flag (category: %u). Important problem...", GetCatID()); 330 | + return false; 331 | +} 332 | + 333 | +uint32 TELE::CountOfCategoryAllowedBy(Player * const player) 334 | +{ 335 | + uint32 count (0); 336 | + for (VCatDest_t i(0); i < TabCatDest.size(); ++i) 337 | + { 338 | + if (TabCatDest[i].IsAllowedToTeleport(player)) 339 | + ++count; 340 | + } 341 | + return count; 342 | +} 343 | + 344 | +bool nsNpcTel::IsValidData(const uint32 &cat, const Flag &flag, 345 | + const uint64 &data0, const uint32 &data1) 346 | +{ 347 | + switch(flag) 348 | + { 349 | + case FLAG_TEAM: 350 | + if (data1) 351 | + sLog->outError("Invalid data1 (category: %u).", cat); 352 | + if (data0 < MAX_FLAG_TEAM) 353 | + return true; 354 | + sLog->outError("Invalid data0 (Team) (category: %u).", cat); 355 | + return false; 356 | + 357 | + case FLAG_GUILD: 358 | + if (data1) 359 | + sLog->outError("Invalid data1 (category: %u).", cat); 360 | + if (data0) 361 | + return true; 362 | + sLog->outError("Invalid data0 (GuildID) (category: %u).", cat); 363 | + return false; 364 | + 365 | + case FLAG_GMLEVEL: 366 | + if (data1) 367 | + sLog->outError("Invalid data1 (category: %u).", cat); 368 | + if (0 < data0 && data0 < 256) 369 | + return true; 370 | + sLog->outError("Invalid data0 (GmLevel) (category: %u).", cat); 371 | + return false; 372 | + 373 | + case FLAG_ISGM: 374 | + if (data0) 375 | + sLog->outError("Invalid data0 (category: %u).", cat); 376 | + if (data1) 377 | + sLog->outError("Invalid data1 (category: %u).", cat); 378 | + return true; 379 | + 380 | + case FLAG_ACCOUNT: 381 | + if (data1) 382 | + sLog->outError("Invalid data1 (category: %u).", cat); 383 | + if (data0) 384 | + return true; 385 | + sLog->outError("Invalid data0 (AccountID) (category: %u).", cat); 386 | + return false; 387 | + 388 | + case FLAG_LEVEL: 389 | + if (data1) 390 | + sLog->outError("Invalid data1 (category: %u).", cat); 391 | + if (0 < data0 && data0 < 256) 392 | + return true; 393 | + sLog->outError("Invalid data0 (Level) (category: %u).", cat); 394 | + return false; 395 | + 396 | + case FLAG_ITEM: 397 | + if (!data0) 398 | + { 399 | + sLog->outError("Invalid data0 (ItemID) (category: %u).", cat); 400 | + return false; 401 | + } 402 | + if (data1) 403 | + return true; 404 | + sLog->outError("Invalid data1 (Item Count) (category: %u).", cat); 405 | + return false; 406 | + 407 | + case FLAG_QUEST: 408 | + if (!data0) 409 | + { 410 | + sLog->outError("Invalid data0 (QuestID) (category: %u).", cat); 411 | + return false; 412 | + } 413 | + if (data1 < MAX_QUEST_STATUS + 1) 414 | + return true; 415 | + sLog->outError("Invalid data1 (Quest Status) (category: %u).", cat); 416 | + return false; 417 | + 418 | + case FLAG_GENDER: 419 | + if (data1) 420 | + sLog->outError("Invalid data1 (category: %u).", cat); 421 | + if (data0 < GENDER_NONE) 422 | + return true; 423 | + sLog->outError("Invalid data0 (Gender) (category: %u).", cat); 424 | + return false; 425 | + 426 | + case FLAG_RACE: 427 | + if (data1) 428 | + sLog->outError("Invalid data1 (category: %u).", cat); 429 | + if (0 < data0 && data0 < MAX_RACES) 430 | + return true; 431 | + sLog->outError("Invalid data0 (Race) (category: %u).", cat); 432 | + return false; 433 | + 434 | + case FLAG_CLASS: 435 | + if (data1) 436 | + sLog->outError("Invalid data1 (category: %u).", cat); 437 | + if (0 < data0 && data0 < MAX_CLASSES) 438 | + return true; 439 | + sLog->outError("Invalid data0 (Class) (category: %u).", cat); 440 | + return false; 441 | + 442 | + case FLAG_REPUTATION: 443 | + if (!data0) 444 | + { 445 | + sLog->outError("Invalid data0 (Faction/Reputation) (category: %u).", cat); 446 | + return false; 447 | + } 448 | + if (data1 <= REP_EXALTED) 449 | + return true; 450 | + sLog->outError("Invalid data1 (Faction/Reputation) (category: %u).", cat); 451 | + return false; 452 | + 453 | + case FLAG_PLAYER: 454 | + if (data1) 455 | + sLog->outError("Invalid data1 (category: %u).", cat); 456 | + if (data0) 457 | + return true; 458 | + sLog->outError("Invalid data0 (PlayerGuid) (category: %u).", cat); 459 | + return false; 460 | + } 461 | + 462 | + sLog->outError("Invalid flag (category: %u).", cat); 463 | + return false; 464 | +} 465 | + 466 | +void LoadNpcTele(void) 467 | +{ 468 | + const char *Table[] = 469 | + { 470 | + "custom_npc_tele_category", 471 | + "custom_npc_tele_destination", 472 | + "custom_npc_tele_association", 473 | + }; 474 | + 475 | + 476 | + QueryResult result = WorldDatabase.PQuery( 477 | + "SELECT `flag`, `data0`, `data1`, `cat_id`, C.`name` `namecat`, D.`name` `namedest`, " 478 | + // 0 1 2 3 4 5 479 | + "`pos_X`, `pos_Y`, `pos_Z`, `orientation`, `map`, `level`, `cost` " 480 | + // 6 7 8 9 10 11 12 481 | + "FROM `%s` C, `%s` D, `%s` A " 482 | + "WHERE C.`id` = `cat_id` AND D.`id` = `dest_id` " 483 | + "ORDER BY `namecat`, `cat_id`, `namedest`", Table[0], Table[1], Table[2]); 484 | + 485 | + nsNpcTel::TabCatDest.clear(); 486 | + 487 | + if (result) 488 | + { 489 | + sLog->outString( "TSCR: Loading %s, %s and %s...", Table[0], Table[1], Table[2]); 490 | + 491 | + uint32 catid = 0; 492 | + uint32 nbDest = 0; 493 | + bool IsValidCat = true; 494 | + bool FirstTime = true; 495 | + 496 | + do 497 | + { 498 | + Field *fields = result->Fetch(); 499 | + 500 | + if (!IsValidCat && catid == fields[3].GetUInt32() && !FirstTime) 501 | + continue; 502 | + 503 | + IsValidCat = true; 504 | + FirstTime = false; 505 | + 506 | + if (!nsNpcTel::IsValidData(fields[3].GetUInt32(), (nsNpcTel::Flag)fields[0].GetUInt8(), 507 | + fields[1].GetUInt64(), fields[2].GetUInt32())) 508 | + { 509 | + IsValidCat = false; 510 | + catid = fields[3].GetUInt32(); 511 | + continue; 512 | + } 513 | + 514 | + if (catid != fields[3].GetUInt32()) 515 | + { 516 | + catid = fields[3].GetUInt32(); 517 | + nsNpcTel::CatDest categorie (catid, fields[4].GetString(), (nsNpcTel::Flag)fields[0].GetUInt8(), 518 | + fields[1].GetUInt64(), fields[2].GetUInt32()); 519 | + nsNpcTel::TabCatDest.push_back(categorie); 520 | + } 521 | + 522 | + nsNpcTel::Dest item = 523 | + { 524 | + fields[5].GetString(), // Name 525 | + fields[6].GetFloat(), // X 526 | + fields[7].GetFloat(), // Y 527 | + fields[8].GetFloat(), // Z 528 | + fields[9].GetFloat(), // Orientation 529 | + fields[10].GetUInt16(), // Map 530 | + fields[11].GetUInt8(), // Level 531 | + fields[12].GetUInt32(), // Cost 532 | + }; 533 | + 534 | + nsNpcTel::TabCatDest.back().AddDest(item); 535 | + ++nbDest; 536 | + } while (result->NextRow()); 537 | + 538 | + sLog->outString(""); 539 | + sLog->outString("TSCR: >> Loaded %u npc_teleport.", nbDest); 540 | + } else sLog->outString("TSCR: WARNING >> Loaded 0 npc_teleport."); 541 | +} 542 | + 543 | + 544 | +#undef TELE 545 | +#undef PAGE 546 | +#undef PAGEI 547 | diff --git a/src/server/game/AI/ScriptedAI/sc_npc_teleport.h b/src/server/game/AI/ScriptedAI/sc_npc_teleport.h 548 | new file mode 100644 549 | index 0000000..4830245 550 | --- /dev/null 551 | +++ b/src/server/game/AI/ScriptedAI/sc_npc_teleport.h 552 | @@ -0,0 +1,151 @@ 553 | +/** 554 | + * 555 | + * @File : sc_npc_teleport.h 556 | + * 557 | + * @Authors : Wilibald09 558 | + * 559 | + * @Date : 19/08/2008 560 | + * 561 | + * @Version : 1.2 562 | + * 563 | + **/ 564 | + 565 | + 566 | +#ifndef SC_NPC_TELEPORT_H 567 | +#define SC_NPC_TELEPORT_H 568 | + 569 | +#include 570 | + 571 | + 572 | +namespace nsNpcTel 573 | +{ 574 | + // Different types of permissions 575 | + enum Flag 576 | + { 577 | + FLAG_TEAM = 0, 578 | + FLAG_GUILD = 1, 579 | + FLAG_GMLEVEL = 2, 580 | + FLAG_ISGM = 3, 581 | + FLAG_ACCOUNT = 4, 582 | + FLAG_LEVEL = 5, 583 | + FLAG_ITEM = 6, 584 | + FLAG_QUEST = 7, 585 | + FLAG_GENDER = 8, 586 | + FLAG_RACE = 9, 587 | + FLAG_CLASS = 10, 588 | + FLAG_REPUTATION = 11, 589 | + FLAG_PLAYER = 12, 590 | + MAX_FLAG, 591 | + }; 592 | + 593 | + // Different parameters of FLAG_TEAM 594 | + enum 595 | + { 596 | + TEAM_ALL = 0, 597 | + TEAM_ALLIANCE = 1, 598 | + TEAM_HORDE = 2, 599 | + MAX_FLAG_TEAM, 600 | + }; 601 | + 602 | + // Structure representing the destinations 603 | + struct Dest 604 | + { 605 | + std::string m_name; 606 | + float m_X, m_Y, m_Z, m_orient; 607 | + uint16 m_map; 608 | + uint8 m_level; 609 | + uint32 m_cost; 610 | + }; 611 | + 612 | + // Class representing the categories of destinations 613 | + class CatDest 614 | + { 615 | + public: 616 | + 617 | + typedef std::vector VDest; 618 | + typedef VDest::size_type VDest_t; 619 | + 620 | + CatDest(const uint32 &id, const std::string &name, 621 | + const Flag &flag, const uint64 &data0, const uint32 &data1); 622 | + 623 | + void AddDest (const Dest &item) { m_TabDest.push_back(item); } 624 | + Dest GetDest (const uint32 &id) const { return m_TabDest[id]; } 625 | + uint32 GetCatID (void) const { return m_id; } 626 | + uint32 size (void) const { return m_TabDest.size(); } 627 | + 628 | + std::string GetName(const bool IsGM = false) const; 629 | + bool IsAllowedToTeleport(Player * const player) const; 630 | + 631 | + static uint32 CountOfCategoryAllowedBy(Player * const player); 632 | + 633 | + private: 634 | + 635 | + uint32 m_id; 636 | + std::string m_name; 637 | + Flag m_flag; 638 | + uint64 m_data0; 639 | + uint32 m_data1; 640 | + VDest m_TabDest; 641 | + }; 642 | + 643 | + // Class page for current player 644 | + class Page 645 | + { 646 | + protected: 647 | + 648 | + // Class instance for current player 649 | + class Instance 650 | + { 651 | + public: 652 | + 653 | + Instance(Player * const player, const uint32 &PageId = 0) 654 | + : m_player(player), m_PageId(PageId) {} 655 | + 656 | + Instance & operator = (const uint32 &id); 657 | + Instance & operator ++ (void); 658 | + Instance operator ++ (int32); 659 | + Instance & operator -- (void); 660 | + Instance operator -- (int32); 661 | + 662 | + uint32 GetPageId(void) const { return m_PageId; } 663 | + Player * GetPlayer(void) const { return m_player; } 664 | + 665 | + private: 666 | + 667 | + Player *m_player; 668 | + uint32 m_PageId; 669 | + }; 670 | + 671 | + 672 | + public: 673 | + 674 | + typedef std::vector VInst; 675 | + typedef VInst::size_type VInst_t; 676 | + 677 | + Page(void) { m_TabInstance.clear(); } 678 | + 679 | + Instance & operator () (Player * const player); 680 | + uint32 operator [] (Player * const player) const; 681 | + 682 | + 683 | + private: 684 | + 685 | + VInst m_TabInstance; 686 | + }; 687 | + 688 | + typedef std::vector VCatDest; 689 | + typedef VCatDest::size_type VCatDest_t; 690 | + 691 | + // Verification of data integrity 692 | + bool IsValidData(const uint32 &cat, const Flag &flag, 693 | + const uint64 &data0, const uint32 &data1); 694 | + 695 | + extern VCatDest TabCatDest; 696 | +} 697 | + 698 | +// Loading contents of database 699 | +void LoadNpcTele(void); 700 | + 701 | +extern WorldDatabaseWorkerPool WorldDatabase; 702 | + 703 | +#endif 704 | diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp 705 | index 794bb10..8dcac68 100755 706 | --- a/src/server/game/Scripting/ScriptLoader.cpp 707 | +++ b/src/server/game/Scripting/ScriptLoader.cpp 708 | @@ -25,6 +25,9 @@ void AddSC_example_gossip_codebox(); 709 | void AddSC_example_misc(); 710 | void AddSC_example_commandscript(); 711 | 712 | +//TeleNPC2 713 | +void AddSC_npc_teleport(); 714 | + 715 | // spells 716 | void AddSC_deathknight_spell_scripts(); 717 | void AddSC_druid_spell_scripts(); 718 | @@ -1202,6 +1205,7 @@ void AddCustomScripts() 719 | { 720 | #ifdef SCRIPTS 721 | /* This is where custom scripts should be added. */ 722 | - 723 | + //TeleNPC2 724 | + AddSC_npc_teleport(); 725 | #endif 726 | } 727 | diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp 728 | index a0a1c82..66ce84b 100755 729 | --- a/src/server/game/Scripting/ScriptMgr.cpp 730 | +++ b/src/server/game/Scripting/ScriptMgr.cpp 731 | @@ -25,6 +25,7 @@ 732 | #include "ScriptLoader.h" 733 | #include "ScriptSystem.h" 734 | #include "Transport.h" 735 | +#include "sc_npc_teleport.h" 736 | 737 | // Utility macros to refer to the script registry. 738 | #define SCR_REG_MAP(T) ScriptRegistry::ScriptMap 739 | @@ -180,6 +181,8 @@ void ScriptMgr::Initialize() 740 | uint32 oldMSTime = getMSTime(); 741 | 742 | LoadDatabase(); 743 | + // Load TeleNPC2 - maybe not the best place to load it ... 744 | + LoadNpcTele(); 745 | 746 | sLog->outString("Loading C++ scripts"); 747 | 748 | diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt 749 | index 17d4bfc..90eae34 100644 750 | --- a/src/server/scripts/CMakeLists.txt 751 | +++ b/src/server/scripts/CMakeLists.txt 752 | @@ -31,6 +31,9 @@ include(Examples/CMakeLists.txt) 753 | 754 | set(scripts_STAT_SRCS 755 | ${scripts_STAT_SRCS} 756 | + Custom/npc_teleport.cpp 757 | + ../game/AI/ScriptedAI/sc_npc_teleport.cpp 758 | + ../game/AI/ScriptedAI/sc_npc_teleport.h 759 | ../game/AI/ScriptedAI/ScriptedEscortAI.cpp 760 | ../game/AI/ScriptedAI/ScriptedCreature.cpp 761 | ../game/AI/ScriptedAI/ScriptedFollowerAI.cpp 762 | diff --git a/src/server/scripts/Custom/npc_teleport.cpp b/src/server/scripts/Custom/npc_teleport.cpp 763 | new file mode 100644 764 | index 0000000..1e51336 765 | --- /dev/null 766 | +++ b/src/server/scripts/Custom/npc_teleport.cpp 767 | @@ -0,0 +1,221 @@ 768 | +/** 769 | + * 770 | + * @File : npc_teleport.cpp 771 | + * 772 | + * @Authors : Wilibald09 773 | + * 774 | + * @Date : 19/08/2008 775 | + * 776 | + * @Version : 1.2 777 | + * 778 | + **/ 779 | + 780 | + 781 | + 782 | +#include "ScriptPCH.h" 783 | +#include "sc_npc_teleport.h" 784 | +#include 785 | + 786 | +#define GOSSIP_SHOW_DEST 1000 787 | +#define GOSSIP_TELEPORT 1001 788 | +#define GOSSIP_NEXT_PAGEC 1002 789 | +#define GOSSIP_PREV_PAGEC 1003 790 | +#define GOSSIP_NEXT_PAGED 1004 791 | +#define GOSSIP_PREV_PAGED 1005 792 | +#define GOSSIP_MAIN_MENU 1006 793 | + 794 | +#define SPELL_ID_PASSIVE_RESURRECTION_SICKNESS 15007 795 | +#define SPELL_VISUAL_TELEPORT 35517 796 | + 797 | +#define NB_ITEM_PAGE 10 798 | +#define MSG_CAT 100000 799 | +#define MSG_DEST 100001 800 | + 801 | +#define NEXT_PAGE "-> [Next Page]" 802 | +#define PREV_PAGE "<- [Previous Page]" 803 | +#define MAIN_MENU "<= [Main Menu]" 804 | + 805 | + 806 | +using namespace nsNpcTel; 807 | + 808 | + 809 | +namespace 810 | +{ 811 | + Page PageC, PageD; 812 | + Page Cat; 813 | + 814 | + // Conversion function int->string 815 | + std::string ConvertStr(const int64 &val) 816 | + { 817 | + std::ostringstream ostr; 818 | + ostr << val; 819 | + return ostr.str(); 820 | + } 821 | + 822 | + // Conversion function intMoney->stringMoney 823 | + std::string ConvertMoney(const uint32 &Money) 824 | + { 825 | + std::string Str(ConvertStr(Money)); 826 | + uint32 SizeStr = Str.length(); 827 | + 828 | + if (SizeStr > 4) 829 | + Str = Str.insert(Str.length()-4, "po"); 830 | + if (SizeStr > 2) 831 | + Str = Str.insert(Str.length()-2, "pa"); 832 | + Str += "pc"; 833 | + 834 | + return Str; 835 | + } 836 | + 837 | + // Teleport Player 838 | + void Teleport(Player * const player, const uint16 &map, 839 | + const float &X, const float &Y, const float &Z, const float &orient) 840 | + { 841 | + player->CastSpell(player, SPELL_VISUAL_TELEPORT, true); 842 | + player->TeleportTo(map, X, Y, Z, orient); 843 | + } 844 | + 845 | + // Display categories 846 | + void AffichCat(Player * const player, Creature * const creature) 847 | + { 848 | + if (PageC[player] > 0) 849 | + player->ADD_GOSSIP_ITEM(7, PREV_PAGE, GOSSIP_PREV_PAGEC, 0); 850 | + 851 | + VCatDest_t i (PageC[player] * NB_ITEM_PAGE); 852 | + for ( ; i < TabCatDest.size() && i < (NB_ITEM_PAGE * (PageC[player] + 1)); ++i) 853 | + { 854 | + if (TabCatDest[i].IsAllowedToTeleport(player)) 855 | + player->ADD_GOSSIP_ITEM(7, TabCatDest[i].GetName(player->isGameMaster()).c_str(), GOSSIP_SHOW_DEST, i); 856 | + } 857 | + 858 | + if (i < TabCatDest.size()) 859 | + player->ADD_GOSSIP_ITEM(7, NEXT_PAGE, GOSSIP_NEXT_PAGEC, 0); 860 | + 861 | + player->SEND_GOSSIP_MENU(MSG_CAT, creature->GetGUID()); 862 | + } 863 | + 864 | + // Display destination categories 865 | + void AffichDest(Player * const player, Creature * const creature) 866 | + { 867 | + if (PageD[player] > 0) 868 | + player->ADD_GOSSIP_ITEM(7, PREV_PAGE, GOSSIP_PREV_PAGED, 0); 869 | + 870 | + CatDest::VDest_t i (PageD[player] * NB_ITEM_PAGE); 871 | + for ( ; i < TabCatDest[Cat[player]].size() && i < (NB_ITEM_PAGE * (PageD[player] + 1)); ++i) 872 | + { 873 | + player->ADD_GOSSIP_ITEM(5, TabCatDest[Cat[player]].GetDest(i).m_name.c_str(), GOSSIP_TELEPORT, i); 874 | + } 875 | + 876 | + if (i < TabCatDest[Cat[player]].size()) 877 | + player->ADD_GOSSIP_ITEM(7, NEXT_PAGE, GOSSIP_NEXT_PAGED, 0); 878 | + 879 | + if (CatDest::CountOfCategoryAllowedBy(player) > 1) 880 | + player->ADD_GOSSIP_ITEM(7, MAIN_MENU, GOSSIP_MAIN_MENU, 0); 881 | + 882 | + player->SEND_GOSSIP_MENU(MSG_DEST, creature->GetGUID()); 883 | + } 884 | + 885 | + // Verification before teleportation 886 | + void ActionTeleport(Player * const player, Creature * const creature, const uint32 &id) 887 | + { 888 | + Dest dest (TabCatDest[Cat[player]].GetDest(id)); 889 | + 890 | + if (player->getLevel() < dest.m_level && !player->isGameMaster()) 891 | + { 892 | + std::string msg ("You do not have the required level. This destination requires level " + ConvertStr(dest.m_level) + "."); 893 | + creature->MonsterWhisper(msg.c_str(), player->GetGUID()); 894 | + return; 895 | + } 896 | + 897 | + if (player->GetMoney() < dest.m_cost && !player->isGameMaster()) 898 | + { 899 | + std::string msg ("You do not have enough money. The price for teleportation is " + ConvertMoney(dest.m_cost) + "."); 900 | + creature->MonsterWhisper(msg.c_str(), player->GetGUID()); 901 | + return; 902 | + } 903 | + 904 | + if (!player->isGameMaster() && dest.m_cost) 905 | + player->ModifyMoney(-1 * dest.m_cost); 906 | + 907 | + Teleport(player, dest.m_map, dest.m_X, dest.m_Y, dest.m_Z, dest.m_orient); 908 | + } 909 | +} 910 | + 911 | +class npc_teleport : public CreatureScript 912 | +{ 913 | +public: 914 | + npc_teleport() : CreatureScript("npc_teleport") {} 915 | + 916 | +bool OnGossipHello(Player *player, Creature *creature) 917 | +{ 918 | + PageC(player) = PageD(player) = Cat(player) = 0; 919 | + 920 | + if(player->isInCombat()) 921 | + { 922 | + player->CLOSE_GOSSIP_MENU(); 923 | + creature->MonsterWhisper("You are in combat. Come back later", player->GetGUID()); 924 | + return true; 925 | + } 926 | + AffichCat(player, creature); 927 | + return true; 928 | +} 929 | + 930 | +bool OnGossipSelect(Player *player, Creature *creature, uint32 sender, uint32 param) 931 | +{ 932 | + player->PlayerTalkClass->ClearMenus(); 933 | + switch(sender) 934 | + { 935 | + // Display destinations 936 | + case GOSSIP_SHOW_DEST: 937 | + Cat(player) = param; 938 | + AffichDest(player, creature); 939 | + break; 940 | + 941 | + // Previous categories page 942 | + case GOSSIP_PREV_PAGEC: 943 | + --PageC(player); 944 | + AffichCat(player, creature); 945 | + break; 946 | + 947 | + // Next page categories 948 | + case GOSSIP_NEXT_PAGEC: 949 | + ++PageC(player); 950 | + AffichCat(player, creature); 951 | + break; 952 | + 953 | + // Previous destinations page 954 | + case GOSSIP_PREV_PAGED: 955 | + --PageD(player); 956 | + AffichDest(player, creature); 957 | + break; 958 | + 959 | + // Next destination page 960 | + case GOSSIP_NEXT_PAGED: 961 | + ++PageD(player); 962 | + AffichDest(player, creature); 963 | + break; 964 | + 965 | + // Display main menu 966 | + case GOSSIP_MAIN_MENU: 967 | + OnGossipHello(player, creature); 968 | + break; 969 | + 970 | + // Teleportation 971 | + case GOSSIP_TELEPORT: 972 | + player->CLOSE_GOSSIP_MENU(); 973 | + if(player->HasAura(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS,0)) { 974 | + creature->CastSpell(player,38588,false); // Healing effect 975 | + player->RemoveAurasDueToSpell(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS); 976 | + } 977 | + 978 | + ActionTeleport(player, creature, param); 979 | + break; 980 | + } 981 | + return true; 982 | +} 983 | +}; 984 | + 985 | +void AddSC_npc_teleport() 986 | +{ 987 | + new npc_teleport; 988 | +} 989 | -- 990 | 1.7.3.1.msysgit.0 991 | 992 | -------------------------------------------------------------------------------- /11043-independent/0001-telenpc2.patch: -------------------------------------------------------------------------------- 1 | From 462bc594800b73568c9324e607f3b1eaff829c06 Mon Sep 17 00:00:00 2001 2 | From: thedevnull 3 | Date: Wed, 19 Jan 2011 10:28:37 -0200 4 | Subject: [PATCH] telenpc2 5 | Signed-off-by: thedevnull 6 | 7 | --- 8 | README.NPCTELEPORT | 14 + 9 | sql/tools/setup_npc_teleport.sql | 119 +++++++ 10 | src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp | 373 +++++++++++++++++++++ 11 | src/server/game/AI/ScriptedAI/sc_npc_teleport.h | 151 +++++++++ 12 | src/server/game/Scripting/ScriptLoader.cpp | 6 +- 13 | src/server/game/Scripting/ScriptMgr.cpp | 3 + 14 | src/server/scripts/CMakeLists.txt | 3 + 15 | src/server/scripts/Custom/npc_teleport.cpp | 221 ++++++++++++ 16 | 8 files changed, 889 insertions(+), 1 deletions(-) 17 | create mode 100644 README.NPCTELEPORT 18 | create mode 100644 sql/tools/setup_npc_teleport.sql 19 | create mode 100644 src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp 20 | create mode 100644 src/server/game/AI/ScriptedAI/sc_npc_teleport.h 21 | create mode 100644 src/server/scripts/Custom/npc_teleport.cpp 22 | 23 | diff --git a/README.NPCTELEPORT b/README.NPCTELEPORT 24 | new file mode 100644 25 | index 0000000..015c9c2 26 | --- /dev/null 27 | +++ b/README.NPCTELEPORT 28 | @@ -0,0 +1,14 @@ 29 | +NPC Teleport for Trinity 30 | + 31 | +Original author : Wilibald09 32 | + 33 | +Allows you to add a custom NPC for teleporting, using .npc add 100000. 34 | +The default NPC is entry 100000. 35 | + 36 | +All settings are located in the DB, so you can customize and add destinations, 37 | +set level restrictions and also charge the player for teleporting. 38 | + 39 | +Installation: 40 | + 41 | +Run the query setup_npc_teleport.sql located in the trinity sql directory on 42 | +your world DB. This will setup the DB and you can customize from there. 43 | diff --git a/sql/tools/setup_npc_teleport.sql b/sql/tools/setup_npc_teleport.sql 44 | new file mode 100644 45 | index 0000000..03b9e93 46 | --- /dev/null 47 | +++ b/sql/tools/setup_npc_teleport.sql 48 | @@ -0,0 +1,119 @@ 49 | +DROP TABLE IF EXISTS `custom_npc_tele_category`; 50 | +CREATE TABLE `custom_npc_tele_category` ( 51 | + `id` int(6) unsigned NOT NULL default '0', 52 | + `name` varchar(255) NOT NULL default '', 53 | + `flag` tinyint(3) unsigned NOT NULL default '0', 54 | + `data0` bigint(20) unsigned NOT NULL default '0', 55 | + `data1` int(6) unsigned NOT NULL default '0', 56 | + PRIMARY KEY (`id`) 57 | +) ENGINE=MyISAM DEFAULT CHARSET=utf8; 58 | + 59 | +DROP TABLE IF EXISTS `custom_npc_tele_destination`; 60 | +CREATE TABLE `custom_npc_tele_destination` ( 61 | + `id` int(6) unsigned NOT NULL auto_increment, 62 | + `name` char(100) NOT NULL default '', 63 | + `pos_X` float NOT NULL default '0', 64 | + `pos_Y` float NOT NULL default '0', 65 | + `pos_Z` float NOT NULL default '0', 66 | + `map` smallint(5) unsigned NOT NULL default '0', 67 | + `orientation` float NOT NULL default '0', 68 | + `level` tinyint(3) unsigned NOT NULL default '0', 69 | + `cost` int(10) unsigned NOT NULL default '0', 70 | + PRIMARY KEY (`id`) 71 | +) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 72 | + 73 | +DROP TABLE IF EXISTS `custom_npc_tele_association`; 74 | +CREATE TABLE `custom_npc_tele_association` ( 75 | + `cat_id` int(6) unsigned NOT NULL default '0', 76 | + `dest_id` int(6) unsigned NOT NULL default '0', 77 | + PRIMARY KEY (`cat_id`, `dest_id`) 78 | +) ENGINE=MyISAM DEFAULT CHARSET=utf8; 79 | + 80 | +TRUNCATE `custom_npc_tele_category`; 81 | +INSERT INTO `custom_npc_tele_category` 82 | + (`id`, `name`, `flag`, `data0`, `data1`) 83 | +VALUES 84 | + (1, 'Cities', 0, 1, 0), 85 | + (2, 'Cities', 0, 2, 0), 86 | + (3, 'Battlegrounds', 0, 1, 0), 87 | + (4, 'Battlegrounds', 0, 2, 0), 88 | + (5, 'Arenas', 0, 0, 0), 89 | + (6, '[Instances Lvl 1-60]', 0, 0, 0), 90 | + (7, '[Instances Lvl 60+]', 5, 60, 0), 91 | + (8, '[Instances Lvl 70+]', 5, 70, 0), 92 | + (9, 'Destinations MJ', 3, 0, 0); 93 | + 94 | +TRUNCATE `custom_npc_tele_destination`; 95 | +INSERT INTO `custom_npc_tele_destination` 96 | + (`id`, `name`, `pos_X`, `pos_Y`, `pos_Z`, `map`, `orientation`, `level`, `cost`) 97 | +VALUES 98 | + (1, 'Alterac Valley', 883.187, -489.375, 96.7618, 30, 3.06932, 0, 0), 99 | + (2, 'Alterac Valley', -818.155, -623.043, 54.0884, 30, 2.1, 0, 0), 100 | + (3, 'Arathi Basin', 686.053, 683.165, -12.9149, 529, 0.18, 0, 0), 101 | + (4, 'Arathi Basin', 1308.68, 1306.03, -9.0107, 529, 3.91285, 0, 0), 102 | + (5, 'Black Temple', -3610.72, 324.988, 37.4, 530, 3.28298, 0, 0), 103 | + (6, 'Blackfathom Deeps', 4254.58, 664.74, -29.04, 1, 1.97, 0, 0), 104 | + (7, 'Blackrock Depths', -7301.03, -913.19, 165.37, 0, 0.08, 0, 0), 105 | + (8, 'Blackrock Spire', -7535.43, -1212.04, 285.45, 0, 5.29, 0, 0), 106 | + (9, 'Blackwing Lair', -7665.55, -1102.49, 400.679, 469, 0, 0, 0), 107 | + (10, 'Caverns of Time', -8173.66, -4746.36, 33.8423, 1, 4.93989, 0, 0), 108 | + (11, 'Circle of Blood', 2839.44, 5930.17, 11.1002, 530, 3.16284, 0, 0), 109 | + (12, 'Coilfang Reservoir', 517.288, 6976.28, 32.0072, 530, 0, 0, 0), 110 | + (13, 'Darnassus', 9947.52, 2482.73, 1316.21, 1, 0, 0, 0), 111 | + (14, 'Dire Maul', -3982.47, 1127.79, 161.02, 1, 0.05, 0, 0), 112 | + (15, 'Exodar', -4073.03, -12020.4, -1.47, 530, 0, 0, 0), 113 | + (16, 'Eye of the Storm', 2487.72, 1609.12, 1224.64, 566, 3.35671, 0, 0), 114 | + (17, 'Eye of the Storm', 1843.73, 1529.77, 1224.43, 566, 0.297579, 0, 0), 115 | + (18, 'Goldshire', -9464, 62, 56, 0, 0, 0, 0), 116 | + (19, 'Gruul\'s Lair', 3539.01, 5082.36, 1.69107, 530, 0, 0, 0), 117 | + (20, 'Gurubashi', -13261.3, 168.294, 35.0792, 0, 1.00688, 0, 0), 118 | + (21, 'Hellfire Citadel', -305.816, 3056.4, -2.47318, 530, 2.01, 0, 0), 119 | + (22, 'Ironforge', -4924.07, -951.95, 501.55, 0, 5.4, 0, 0), 120 | + (23, 'Isle Of Quel\'Danas', 12947.4, -6893.31, 5.68398, 530, 3.09154, 0, 0), 121 | + (24, 'Karazhan', -11118.8, -2010.84, 47.0807, 0, 0, 0, 0), 122 | + (25, 'Maraudon', -1433.33, 2955.34, 96.21, 1, 4.82, 0, 0), 123 | + (26, 'Molten Core', 1121.45, -454.317, -101.33, 230, 3.5, 0, 0), 124 | + (27, 'Naxxramas', 3125.18, -3748.02, 136.049, 0, 0, 0, 0), 125 | + (28, 'Onyxia\'s Lair', -4707.44, -3726.82, 54.6723, 1, 3.8, 0, 0), 126 | + (29, 'Orgrimmar', 1552.5, -4420.66, 8.94802, 1, 0, 0, 0), 127 | + (30, 'Razor Hill', 315.721, -4743.4, 10.4867, 1, 0, 0, 0), 128 | + (31, 'Razorfen Downs', -4645.08, -2470.85, 85.53, 1, 4.39, 0, 0), 129 | + (32, 'Razorfen Kraul', -4484.04, -1739.4, 86.47, 1, 1.23, 0, 0), 130 | + (33, 'Ring of Trials', -1999.94, 6581.71, 11.32, 530, 2.3, 0, 0), 131 | + (34, 'Ruins of Ahn\'Qiraj', -8409.03, 1498.83, 27.3615, 1, 2.49757, 0, 0), 132 | + (35, 'Scholomance', 1219.01, -2604.66, 85.61, 0, 0.5, 0, 0), 133 | + (36, 'Shadowfang Keep', -254.47, 1524.68, 76.89, 0, 1.56, 0, 0), 134 | + (37, 'Shattrath City', -1850.21, 5435.82, -10.9614, 530, 3.40391, 0, 0), 135 | + (38, 'Silvermoon', 9338.74, -7277.27, 13.7895, 530, 0, 0, 0), 136 | + (39, 'Stormwind', -8960.14, 516.266, 96.3568, 0, 0, 0, 0), 137 | + (40, 'Stratholme', 3263.54, -3379.46, 143.59, 0, 0, 0, 0), 138 | + (41, 'Tempest Keep', 3089.58, 1399.05, 187.653, 530, 4.79407, 0, 0), 139 | + (42, 'Temple of Ahn\'Qiraj', -8245.84, 1983.74, 129.072, 1, 0.936195, 0, 0), 140 | + (43, 'The Deadmines', -11212, 1658.58, 25.67, 0, 1.45, 0, 0), 141 | + (44, 'The Maul', -3761.49, 1133.43, 132.083, 1, 4.57259, 0, 0), 142 | + (45, 'The Scarlet Monastery', 2843.89, -693.74, 139.32, 0, 5.11, 0, 0), 143 | + (46, 'The Sunken Temple', -10346.9, -3851.9, -43.41, 0, 6.09, 0, 0), 144 | + (47, 'The Wailing Caverns', -722.53, -2226.3, 16.94, 1, 2.71, 0, 0), 145 | + (48, 'Thunder Bluff', -1290, 147.034, 129.682, 1, 4.919, 0, 0), 146 | + (49, 'Uldaman', -6119.7, -2957.3, 204.11, 0, 0.03, 0, 0), 147 | + (50, 'Undercity', 1819.71, 238.79, 60.5321, 0, 0, 0, 0), 148 | + (51, 'Warsong Gulch', 930.851, 1431.57, 345.537, 489, 0.015704, 0, 0), 149 | + (52, 'Warsong Gulch', 1525.95, 1481.66, 352.001, 489, 3.20756, 0, 0), 150 | + (53, 'Zul\'Aman', 6846.95, -7954.5, 170.028, 530, 4.61501, 0, 0), 151 | + (54, 'Zul\'Farrak', -6839.39, -2911.03, 8.87, 1, 0.41, 0, 0), 152 | + (55, 'Zul\'Gurub', -11916.7, -1212.82, 92.2868, 0, 4.6095, 0, 0), 153 | + (56, 'Ile des MJ', 16254, 16276.9, 14.5082, 1, 1.70269, 0, 0); 154 | + 155 | +TRUNCATE `custom_npc_tele_association`; 156 | +INSERT INTO `custom_npc_tele_association` 157 | + (`cat_id`, `dest_id`) 158 | +VALUES 159 | + (1, 13), (1, 15), (1, 18), (1, 22), (1, 23), (1, 37), (1, 39), (2, 23), (2, 29), (2, 30), (2, 37), (2, 38), (2, 48), (2, 50), (3, 1), (3, 4), (3, 16), (3, 52), (4, 2), (4, 3), (4, 17), (4, 51), (5, 11), (5, 20), (5, 33), (5, 44), (6, 6), (6, 7), (6, 8), (6, 14), (6, 25), (6, 31), (6, 32), (6, 35), (6, 36), (6, 40), (6, 43), (6, 45), (6, 46), (6, 47), (6, 49), (6, 54), (7, 9), (7, 26), (7, 27), (7, 28), (7, 34), (7, 42), (7, 55), (8, 5), (8, 10), (8, 12), (8, 19), (8, 21), (8, 24), (8, 41), (8, 53), (9, 56); 160 | + 161 | +-- `npc_text` 162 | +REPLACE INTO `npc_text` (`ID`, `text0_0`) VALUES 163 | + (100000, 'Choose your Category.'), 164 | + (100001, 'Choose your Destination.'); 165 | + 166 | +-- `creature_template` 167 | +INSERT INTO `creature_template` VALUES (100000, 0, 0, 0, 0, 0, 26502, 0, 0, 0, 'Abisal Vortex', '', '', 0, 83, 83, 0, 35, 35, 1, 1, 1.14286, 2, 1, 509, 683, 0, 805, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 371, 535, 135, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 'npc_teleport', 1); 168 | diff --git a/src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp b/src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp 169 | new file mode 100644 170 | index 0000000..c40d861 171 | --- /dev/null 172 | +++ b/src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp 173 | @@ -0,0 +1,373 @@ 174 | +/** 175 | + * 176 | + * @File : sc_npc_teleport.cpp 177 | + * 178 | + * @Authors : Wilibald09 179 | + * 180 | + * @Date : 28/08/2008 181 | + * 182 | + * @Version : 1.2 183 | + * 184 | + **/ 185 | + 186 | + 187 | +#include "ScriptPCH.h" 188 | +#include "sc_npc_teleport.h" 189 | + 190 | +#define TELE nsNpcTel::CatDest 191 | +#define PAGE nsNpcTel::Page 192 | +#define PAGEI PAGE::Instance 193 | + 194 | + 195 | +nsNpcTel::VCatDest nsNpcTel::TabCatDest; 196 | + 197 | + 198 | +uint32 PAGE::operator [] (Player * const player) const 199 | +{ 200 | + for (VInst_t i(0); i < m_TabInstance.size(); ++i) 201 | + { 202 | + if (m_TabInstance[i].GetPlayer() == player) 203 | + return m_TabInstance[i].GetPageId(); 204 | + } 205 | + return 0; 206 | +} 207 | + 208 | +PAGE::Instance & PAGE::operator () (Player * const player) 209 | +{ 210 | + for (VInst_t i(0); i < m_TabInstance.size(); ++i) 211 | + { 212 | + if (m_TabInstance[i].GetPlayer() == player) 213 | + return m_TabInstance[i]; 214 | + } 215 | + m_TabInstance.push_back(Instance(player)); 216 | + return m_TabInstance.back(); 217 | +} 218 | + 219 | +PAGE::Instance & PAGEI::operator = (const uint32 &id) 220 | +{ 221 | + m_PageId = id; 222 | + return *this; 223 | +} 224 | + 225 | +PAGE::Instance & PAGEI::operator ++ (void) 226 | +{ 227 | + ++m_PageId; 228 | + return *this; 229 | +} 230 | + 231 | +PAGE::Instance PAGEI::operator ++ (int32) 232 | +{ 233 | + Instance tmp (*this); 234 | + ++m_PageId; 235 | + return tmp; 236 | +} 237 | + 238 | +PAGE::Instance & PAGEI::operator -- (void) 239 | +{ 240 | + --m_PageId; 241 | + return *this; 242 | +} 243 | + 244 | +PAGE::Instance PAGEI::operator -- (int32) 245 | +{ 246 | + Instance tmp (*this); 247 | + --m_PageId; 248 | + return tmp; 249 | +} 250 | + 251 | +TELE::CatDest(const uint32 &id, const std::string &name, 252 | + const Flag &flag, const uint64 &data0, const uint32 &data1) 253 | + : m_id(id), m_name(name), m_flag(flag), m_data0(data0), m_data1(data1) 254 | +{ 255 | + m_TabDest.clear(); 256 | +} 257 | + 258 | +std::string TELE::GetName(const bool IsGM /* = false */) const 259 | +{ 260 | + if (!IsGM || m_flag != FLAG_TEAM) 261 | + return m_name; 262 | + 263 | + switch (m_data0) 264 | + { 265 | + case TEAM_HORDE: return std::string(m_name + " (H)"); 266 | + case TEAM_ALLIANCE: return std::string(m_name + " (A)"); 267 | + } 268 | + return m_name; 269 | +} 270 | + 271 | +bool TELE::IsAllowedToTeleport(Player * const player) const 272 | +{ 273 | + if (player->isGameMaster()) 274 | + { 275 | + if (m_flag == FLAG_GMLEVEL) 276 | + return player->GetSession()->GetSecurity() >= m_data0; 277 | + return true; 278 | + } 279 | + 280 | + switch (m_flag) 281 | + { 282 | + case FLAG_TEAM: 283 | + switch (m_data0) 284 | + { 285 | + case TEAM_HORDE: return player->GetTeam() == HORDE; 286 | + case TEAM_ALLIANCE: return player->GetTeam() == ALLIANCE; 287 | + case TEAM_ALL: return true; 288 | + } 289 | + 290 | + case FLAG_GUILD: 291 | + return player->GetGuildId() == m_data0; 292 | + 293 | + case FLAG_GMLEVEL: 294 | + return player->GetSession()->GetSecurity() >= m_data0; 295 | + 296 | + case FLAG_ISGM: 297 | + return player->isGameMaster(); 298 | + 299 | + case FLAG_ACCOUNT: 300 | + return player->GetSession()->GetAccountId() == m_data0; 301 | + 302 | + case FLAG_LEVEL: 303 | + return player->getLevel() >= m_data0; 304 | + 305 | + case FLAG_ITEM: 306 | + return player->HasItemCount(m_data0, m_data1, true); 307 | + 308 | + case FLAG_QUEST: 309 | + if (m_data1 < MAX_QUEST_STATUS) 310 | + return player->GetQuestStatus(m_data0) == m_data1; 311 | + return player->GetQuestRewardStatus(m_data0); 312 | + 313 | + case FLAG_GENDER: 314 | + return player->getGender() == m_data0; 315 | + 316 | + case FLAG_RACE: 317 | + return player->getRace() == m_data0; 318 | + 319 | + case FLAG_CLASS: 320 | + return player->getClass() == m_data0; 321 | + 322 | + case FLAG_REPUTATION: 323 | + return player->GetReputationRank(m_data0) >= m_data1; 324 | + 325 | + case FLAG_PLAYER: 326 | + return player->GetGUID() == m_data0; 327 | + } 328 | + 329 | + sLog->outError("Invalid flag (category: %u). Important problem...", GetCatID()); 330 | + return false; 331 | +} 332 | + 333 | +uint32 TELE::CountOfCategoryAllowedBy(Player * const player) 334 | +{ 335 | + uint32 count (0); 336 | + for (VCatDest_t i(0); i < TabCatDest.size(); ++i) 337 | + { 338 | + if (TabCatDest[i].IsAllowedToTeleport(player)) 339 | + ++count; 340 | + } 341 | + return count; 342 | +} 343 | + 344 | +bool nsNpcTel::IsValidData(const uint32 &cat, const Flag &flag, 345 | + const uint64 &data0, const uint32 &data1) 346 | +{ 347 | + switch(flag) 348 | + { 349 | + case FLAG_TEAM: 350 | + if (data1) 351 | + sLog->outError("Invalid data1 (category: %u).", cat); 352 | + if (data0 < MAX_FLAG_TEAM) 353 | + return true; 354 | + sLog->outError("Invalid data0 (Team) (category: %u).", cat); 355 | + return false; 356 | + 357 | + case FLAG_GUILD: 358 | + if (data1) 359 | + sLog->outError("Invalid data1 (category: %u).", cat); 360 | + if (data0) 361 | + return true; 362 | + sLog->outError("Invalid data0 (GuildID) (category: %u).", cat); 363 | + return false; 364 | + 365 | + case FLAG_GMLEVEL: 366 | + if (data1) 367 | + sLog->outError("Invalid data1 (category: %u).", cat); 368 | + if (0 < data0 && data0 < 256) 369 | + return true; 370 | + sLog->outError("Invalid data0 (GmLevel) (category: %u).", cat); 371 | + return false; 372 | + 373 | + case FLAG_ISGM: 374 | + if (data0) 375 | + sLog->outError("Invalid data0 (category: %u).", cat); 376 | + if (data1) 377 | + sLog->outError("Invalid data1 (category: %u).", cat); 378 | + return true; 379 | + 380 | + case FLAG_ACCOUNT: 381 | + if (data1) 382 | + sLog->outError("Invalid data1 (category: %u).", cat); 383 | + if (data0) 384 | + return true; 385 | + sLog->outError("Invalid data0 (AccountID) (category: %u).", cat); 386 | + return false; 387 | + 388 | + case FLAG_LEVEL: 389 | + if (data1) 390 | + sLog->outError("Invalid data1 (category: %u).", cat); 391 | + if (0 < data0 && data0 < 256) 392 | + return true; 393 | + sLog->outError("Invalid data0 (Level) (category: %u).", cat); 394 | + return false; 395 | + 396 | + case FLAG_ITEM: 397 | + if (!data0) 398 | + { 399 | + sLog->outError("Invalid data0 (ItemID) (category: %u).", cat); 400 | + return false; 401 | + } 402 | + if (data1) 403 | + return true; 404 | + sLog->outError("Invalid data1 (Item Count) (category: %u).", cat); 405 | + return false; 406 | + 407 | + case FLAG_QUEST: 408 | + if (!data0) 409 | + { 410 | + sLog->outError("Invalid data0 (QuestID) (category: %u).", cat); 411 | + return false; 412 | + } 413 | + if (data1 < MAX_QUEST_STATUS + 1) 414 | + return true; 415 | + sLog->outError("Invalid data1 (Quest Status) (category: %u).", cat); 416 | + return false; 417 | + 418 | + case FLAG_GENDER: 419 | + if (data1) 420 | + sLog->outError("Invalid data1 (category: %u).", cat); 421 | + if (data0 < GENDER_NONE) 422 | + return true; 423 | + sLog->outError("Invalid data0 (Gender) (category: %u).", cat); 424 | + return false; 425 | + 426 | + case FLAG_RACE: 427 | + if (data1) 428 | + sLog->outError("Invalid data1 (category: %u).", cat); 429 | + if (0 < data0 && data0 < MAX_RACES) 430 | + return true; 431 | + sLog->outError("Invalid data0 (Race) (category: %u).", cat); 432 | + return false; 433 | + 434 | + case FLAG_CLASS: 435 | + if (data1) 436 | + sLog->outError("Invalid data1 (category: %u).", cat); 437 | + if (0 < data0 && data0 < MAX_CLASSES) 438 | + return true; 439 | + sLog->outError("Invalid data0 (Class) (category: %u).", cat); 440 | + return false; 441 | + 442 | + case FLAG_REPUTATION: 443 | + if (!data0) 444 | + { 445 | + sLog->outError("Invalid data0 (Faction/Reputation) (category: %u).", cat); 446 | + return false; 447 | + } 448 | + if (data1 <= REP_EXALTED) 449 | + return true; 450 | + sLog->outError("Invalid data1 (Faction/Reputation) (category: %u).", cat); 451 | + return false; 452 | + 453 | + case FLAG_PLAYER: 454 | + if (data1) 455 | + sLog->outError("Invalid data1 (category: %u).", cat); 456 | + if (data0) 457 | + return true; 458 | + sLog->outError("Invalid data0 (PlayerGuid) (category: %u).", cat); 459 | + return false; 460 | + } 461 | + 462 | + sLog->outError("Invalid flag (category: %u).", cat); 463 | + return false; 464 | +} 465 | + 466 | +void LoadNpcTele(void) 467 | +{ 468 | + const char *Table[] = 469 | + { 470 | + "custom_npc_tele_category", 471 | + "custom_npc_tele_destination", 472 | + "custom_npc_tele_association", 473 | + }; 474 | + 475 | + 476 | + QueryResult result = WorldDatabase.PQuery( 477 | + "SELECT `flag`, `data0`, `data1`, `cat_id`, C.`name` `namecat`, D.`name` `namedest`, " 478 | + // 0 1 2 3 4 5 479 | + "`pos_X`, `pos_Y`, `pos_Z`, `orientation`, `map`, `level`, `cost` " 480 | + // 6 7 8 9 10 11 12 481 | + "FROM `%s` C, `%s` D, `%s` A " 482 | + "WHERE C.`id` = `cat_id` AND D.`id` = `dest_id` " 483 | + "ORDER BY `namecat`, `cat_id`, `namedest`", Table[0], Table[1], Table[2]); 484 | + 485 | + nsNpcTel::TabCatDest.clear(); 486 | + 487 | + if (result) 488 | + { 489 | + sLog->outString( "TSCR: Loading %s, %s and %s...", Table[0], Table[1], Table[2]); 490 | + 491 | + uint32 catid = 0; 492 | + uint32 nbDest = 0; 493 | + bool IsValidCat = true; 494 | + bool FirstTime = true; 495 | + 496 | + do 497 | + { 498 | + Field *fields = result->Fetch(); 499 | + 500 | + if (!IsValidCat && catid == fields[3].GetUInt32() && !FirstTime) 501 | + continue; 502 | + 503 | + IsValidCat = true; 504 | + FirstTime = false; 505 | + 506 | + if (!nsNpcTel::IsValidData(fields[3].GetUInt32(), (nsNpcTel::Flag)fields[0].GetUInt8(), 507 | + fields[1].GetUInt64(), fields[2].GetUInt32())) 508 | + { 509 | + IsValidCat = false; 510 | + catid = fields[3].GetUInt32(); 511 | + continue; 512 | + } 513 | + 514 | + if (catid != fields[3].GetUInt32()) 515 | + { 516 | + catid = fields[3].GetUInt32(); 517 | + nsNpcTel::CatDest categorie (catid, fields[4].GetString(), (nsNpcTel::Flag)fields[0].GetUInt8(), 518 | + fields[1].GetUInt64(), fields[2].GetUInt32()); 519 | + nsNpcTel::TabCatDest.push_back(categorie); 520 | + } 521 | + 522 | + nsNpcTel::Dest item = 523 | + { 524 | + fields[5].GetString(), // Name 525 | + fields[6].GetFloat(), // X 526 | + fields[7].GetFloat(), // Y 527 | + fields[8].GetFloat(), // Z 528 | + fields[9].GetFloat(), // Orientation 529 | + fields[10].GetUInt16(), // Map 530 | + fields[11].GetUInt8(), // Level 531 | + fields[12].GetUInt32(), // Cost 532 | + }; 533 | + 534 | + nsNpcTel::TabCatDest.back().AddDest(item); 535 | + ++nbDest; 536 | + } while (result->NextRow()); 537 | + 538 | + sLog->outString(""); 539 | + sLog->outString("TSCR: >> Loaded %u npc_teleport.", nbDest); 540 | + } else sLog->outString("TSCR: WARNING >> Loaded 0 npc_teleport."); 541 | +} 542 | + 543 | + 544 | +#undef TELE 545 | +#undef PAGE 546 | +#undef PAGEI 547 | diff --git a/src/server/game/AI/ScriptedAI/sc_npc_teleport.h b/src/server/game/AI/ScriptedAI/sc_npc_teleport.h 548 | new file mode 100644 549 | index 0000000..4830245 550 | --- /dev/null 551 | +++ b/src/server/game/AI/ScriptedAI/sc_npc_teleport.h 552 | @@ -0,0 +1,151 @@ 553 | +/** 554 | + * 555 | + * @File : sc_npc_teleport.h 556 | + * 557 | + * @Authors : Wilibald09 558 | + * 559 | + * @Date : 19/08/2008 560 | + * 561 | + * @Version : 1.2 562 | + * 563 | + **/ 564 | + 565 | + 566 | +#ifndef SC_NPC_TELEPORT_H 567 | +#define SC_NPC_TELEPORT_H 568 | + 569 | +#include 570 | + 571 | + 572 | +namespace nsNpcTel 573 | +{ 574 | + // Different types of permissions 575 | + enum Flag 576 | + { 577 | + FLAG_TEAM = 0, 578 | + FLAG_GUILD = 1, 579 | + FLAG_GMLEVEL = 2, 580 | + FLAG_ISGM = 3, 581 | + FLAG_ACCOUNT = 4, 582 | + FLAG_LEVEL = 5, 583 | + FLAG_ITEM = 6, 584 | + FLAG_QUEST = 7, 585 | + FLAG_GENDER = 8, 586 | + FLAG_RACE = 9, 587 | + FLAG_CLASS = 10, 588 | + FLAG_REPUTATION = 11, 589 | + FLAG_PLAYER = 12, 590 | + MAX_FLAG, 591 | + }; 592 | + 593 | + // Different parameters of FLAG_TEAM 594 | + enum 595 | + { 596 | + TEAM_ALL = 0, 597 | + TEAM_ALLIANCE = 1, 598 | + TEAM_HORDE = 2, 599 | + MAX_FLAG_TEAM, 600 | + }; 601 | + 602 | + // Structure representing the destinations 603 | + struct Dest 604 | + { 605 | + std::string m_name; 606 | + float m_X, m_Y, m_Z, m_orient; 607 | + uint16 m_map; 608 | + uint8 m_level; 609 | + uint32 m_cost; 610 | + }; 611 | + 612 | + // Class representing the categories of destinations 613 | + class CatDest 614 | + { 615 | + public: 616 | + 617 | + typedef std::vector VDest; 618 | + typedef VDest::size_type VDest_t; 619 | + 620 | + CatDest(const uint32 &id, const std::string &name, 621 | + const Flag &flag, const uint64 &data0, const uint32 &data1); 622 | + 623 | + void AddDest (const Dest &item) { m_TabDest.push_back(item); } 624 | + Dest GetDest (const uint32 &id) const { return m_TabDest[id]; } 625 | + uint32 GetCatID (void) const { return m_id; } 626 | + uint32 size (void) const { return m_TabDest.size(); } 627 | + 628 | + std::string GetName(const bool IsGM = false) const; 629 | + bool IsAllowedToTeleport(Player * const player) const; 630 | + 631 | + static uint32 CountOfCategoryAllowedBy(Player * const player); 632 | + 633 | + private: 634 | + 635 | + uint32 m_id; 636 | + std::string m_name; 637 | + Flag m_flag; 638 | + uint64 m_data0; 639 | + uint32 m_data1; 640 | + VDest m_TabDest; 641 | + }; 642 | + 643 | + // Class page for current player 644 | + class Page 645 | + { 646 | + protected: 647 | + 648 | + // Class instance for current player 649 | + class Instance 650 | + { 651 | + public: 652 | + 653 | + Instance(Player * const player, const uint32 &PageId = 0) 654 | + : m_player(player), m_PageId(PageId) {} 655 | + 656 | + Instance & operator = (const uint32 &id); 657 | + Instance & operator ++ (void); 658 | + Instance operator ++ (int32); 659 | + Instance & operator -- (void); 660 | + Instance operator -- (int32); 661 | + 662 | + uint32 GetPageId(void) const { return m_PageId; } 663 | + Player * GetPlayer(void) const { return m_player; } 664 | + 665 | + private: 666 | + 667 | + Player *m_player; 668 | + uint32 m_PageId; 669 | + }; 670 | + 671 | + 672 | + public: 673 | + 674 | + typedef std::vector VInst; 675 | + typedef VInst::size_type VInst_t; 676 | + 677 | + Page(void) { m_TabInstance.clear(); } 678 | + 679 | + Instance & operator () (Player * const player); 680 | + uint32 operator [] (Player * const player) const; 681 | + 682 | + 683 | + private: 684 | + 685 | + VInst m_TabInstance; 686 | + }; 687 | + 688 | + typedef std::vector VCatDest; 689 | + typedef VCatDest::size_type VCatDest_t; 690 | + 691 | + // Verification of data integrity 692 | + bool IsValidData(const uint32 &cat, const Flag &flag, 693 | + const uint64 &data0, const uint32 &data1); 694 | + 695 | + extern VCatDest TabCatDest; 696 | +} 697 | + 698 | +// Loading contents of database 699 | +void LoadNpcTele(void); 700 | + 701 | +extern WorldDatabaseWorkerPool WorldDatabase; 702 | + 703 | +#endif 704 | diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp 705 | index 794bb10..8dcac68 100755 706 | --- a/src/server/game/Scripting/ScriptLoader.cpp 707 | +++ b/src/server/game/Scripting/ScriptLoader.cpp 708 | @@ -25,6 +25,9 @@ void AddSC_example_gossip_codebox(); 709 | void AddSC_example_misc(); 710 | void AddSC_example_commandscript(); 711 | 712 | +//TeleNPC2 713 | +void AddSC_npc_teleport(); 714 | + 715 | // spells 716 | void AddSC_deathknight_spell_scripts(); 717 | void AddSC_druid_spell_scripts(); 718 | @@ -1202,6 +1205,7 @@ void AddCustomScripts() 719 | { 720 | #ifdef SCRIPTS 721 | /* This is where custom scripts should be added. */ 722 | - 723 | + //TeleNPC2 724 | + AddSC_npc_teleport(); 725 | #endif 726 | } 727 | diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp 728 | index a0a1c82..66ce84b 100755 729 | --- a/src/server/game/Scripting/ScriptMgr.cpp 730 | +++ b/src/server/game/Scripting/ScriptMgr.cpp 731 | @@ -25,6 +25,7 @@ 732 | #include "ScriptLoader.h" 733 | #include "ScriptSystem.h" 734 | #include "Transport.h" 735 | +#include "sc_npc_teleport.h" 736 | 737 | // Utility macros to refer to the script registry. 738 | #define SCR_REG_MAP(T) ScriptRegistry::ScriptMap 739 | @@ -180,6 +181,8 @@ void ScriptMgr::Initialize() 740 | uint32 oldMSTime = getMSTime(); 741 | 742 | LoadDatabase(); 743 | + // Load TeleNPC2 - maybe not the best place to load it ... 744 | + LoadNpcTele(); 745 | 746 | sLog->outString("Loading C++ scripts"); 747 | 748 | diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt 749 | index 17d4bfc..90eae34 100644 750 | --- a/src/server/scripts/CMakeLists.txt 751 | +++ b/src/server/scripts/CMakeLists.txt 752 | @@ -31,6 +31,9 @@ include(Examples/CMakeLists.txt) 753 | 754 | set(scripts_STAT_SRCS 755 | ${scripts_STAT_SRCS} 756 | + Custom/npc_teleport.cpp 757 | + ../game/AI/ScriptedAI/sc_npc_teleport.cpp 758 | + ../game/AI/ScriptedAI/sc_npc_teleport.h 759 | ../game/AI/ScriptedAI/ScriptedEscortAI.cpp 760 | ../game/AI/ScriptedAI/ScriptedCreature.cpp 761 | ../game/AI/ScriptedAI/ScriptedFollowerAI.cpp 762 | diff --git a/src/server/scripts/Custom/npc_teleport.cpp b/src/server/scripts/Custom/npc_teleport.cpp 763 | new file mode 100644 764 | index 0000000..1e51336 765 | --- /dev/null 766 | +++ b/src/server/scripts/Custom/npc_teleport.cpp 767 | @@ -0,0 +1,221 @@ 768 | +/** 769 | + * 770 | + * @File : npc_teleport.cpp 771 | + * 772 | + * @Authors : Wilibald09 773 | + * 774 | + * @Date : 19/08/2008 775 | + * 776 | + * @Version : 1.2 777 | + * 778 | + **/ 779 | + 780 | + 781 | + 782 | +#include "ScriptPCH.h" 783 | +#include "sc_npc_teleport.h" 784 | +#include 785 | + 786 | +#define GOSSIP_SHOW_DEST 1000 787 | +#define GOSSIP_TELEPORT 1001 788 | +#define GOSSIP_NEXT_PAGEC 1002 789 | +#define GOSSIP_PREV_PAGEC 1003 790 | +#define GOSSIP_NEXT_PAGED 1004 791 | +#define GOSSIP_PREV_PAGED 1005 792 | +#define GOSSIP_MAIN_MENU 1006 793 | + 794 | +#define SPELL_ID_PASSIVE_RESURRECTION_SICKNESS 15007 795 | +#define SPELL_VISUAL_TELEPORT 35517 796 | + 797 | +#define NB_ITEM_PAGE 10 798 | +#define MSG_CAT 100000 799 | +#define MSG_DEST 100001 800 | + 801 | +#define NEXT_PAGE "-> [Next Page]" 802 | +#define PREV_PAGE "<- [Previous Page]" 803 | +#define MAIN_MENU "<= [Main Menu]" 804 | + 805 | + 806 | +using namespace nsNpcTel; 807 | + 808 | + 809 | +namespace 810 | +{ 811 | + Page PageC, PageD; 812 | + Page Cat; 813 | + 814 | + // Conversion function int->string 815 | + std::string ConvertStr(const int64 &val) 816 | + { 817 | + std::ostringstream ostr; 818 | + ostr << val; 819 | + return ostr.str(); 820 | + } 821 | + 822 | + // Conversion function intMoney->stringMoney 823 | + std::string ConvertMoney(const uint32 &Money) 824 | + { 825 | + std::string Str(ConvertStr(Money)); 826 | + uint32 SizeStr = Str.length(); 827 | + 828 | + if (SizeStr > 4) 829 | + Str = Str.insert(Str.length()-4, "po"); 830 | + if (SizeStr > 2) 831 | + Str = Str.insert(Str.length()-2, "pa"); 832 | + Str += "pc"; 833 | + 834 | + return Str; 835 | + } 836 | + 837 | + // Teleport Player 838 | + void Teleport(Player * const player, const uint16 &map, 839 | + const float &X, const float &Y, const float &Z, const float &orient) 840 | + { 841 | + player->CastSpell(player, SPELL_VISUAL_TELEPORT, true); 842 | + player->TeleportTo(map, X, Y, Z, orient); 843 | + } 844 | + 845 | + // Display categories 846 | + void AffichCat(Player * const player, Creature * const creature) 847 | + { 848 | + if (PageC[player] > 0) 849 | + player->ADD_GOSSIP_ITEM(7, PREV_PAGE, GOSSIP_PREV_PAGEC, 0); 850 | + 851 | + VCatDest_t i (PageC[player] * NB_ITEM_PAGE); 852 | + for ( ; i < TabCatDest.size() && i < (NB_ITEM_PAGE * (PageC[player] + 1)); ++i) 853 | + { 854 | + if (TabCatDest[i].IsAllowedToTeleport(player)) 855 | + player->ADD_GOSSIP_ITEM(7, TabCatDest[i].GetName(player->isGameMaster()).c_str(), GOSSIP_SHOW_DEST, i); 856 | + } 857 | + 858 | + if (i < TabCatDest.size()) 859 | + player->ADD_GOSSIP_ITEM(7, NEXT_PAGE, GOSSIP_NEXT_PAGEC, 0); 860 | + 861 | + player->SEND_GOSSIP_MENU(MSG_CAT, creature->GetGUID()); 862 | + } 863 | + 864 | + // Display destination categories 865 | + void AffichDest(Player * const player, Creature * const creature) 866 | + { 867 | + if (PageD[player] > 0) 868 | + player->ADD_GOSSIP_ITEM(7, PREV_PAGE, GOSSIP_PREV_PAGED, 0); 869 | + 870 | + CatDest::VDest_t i (PageD[player] * NB_ITEM_PAGE); 871 | + for ( ; i < TabCatDest[Cat[player]].size() && i < (NB_ITEM_PAGE * (PageD[player] + 1)); ++i) 872 | + { 873 | + player->ADD_GOSSIP_ITEM(5, TabCatDest[Cat[player]].GetDest(i).m_name.c_str(), GOSSIP_TELEPORT, i); 874 | + } 875 | + 876 | + if (i < TabCatDest[Cat[player]].size()) 877 | + player->ADD_GOSSIP_ITEM(7, NEXT_PAGE, GOSSIP_NEXT_PAGED, 0); 878 | + 879 | + if (CatDest::CountOfCategoryAllowedBy(player) > 1) 880 | + player->ADD_GOSSIP_ITEM(7, MAIN_MENU, GOSSIP_MAIN_MENU, 0); 881 | + 882 | + player->SEND_GOSSIP_MENU(MSG_DEST, creature->GetGUID()); 883 | + } 884 | + 885 | + // Verification before teleportation 886 | + void ActionTeleport(Player * const player, Creature * const creature, const uint32 &id) 887 | + { 888 | + Dest dest (TabCatDest[Cat[player]].GetDest(id)); 889 | + 890 | + if (player->getLevel() < dest.m_level && !player->isGameMaster()) 891 | + { 892 | + std::string msg ("You do not have the required level. This destination requires level " + ConvertStr(dest.m_level) + "."); 893 | + creature->MonsterWhisper(msg.c_str(), player->GetGUID()); 894 | + return; 895 | + } 896 | + 897 | + if (player->GetMoney() < dest.m_cost && !player->isGameMaster()) 898 | + { 899 | + std::string msg ("You do not have enough money. The price for teleportation is " + ConvertMoney(dest.m_cost) + "."); 900 | + creature->MonsterWhisper(msg.c_str(), player->GetGUID()); 901 | + return; 902 | + } 903 | + 904 | + if (!player->isGameMaster() && dest.m_cost) 905 | + player->ModifyMoney(-1 * dest.m_cost); 906 | + 907 | + Teleport(player, dest.m_map, dest.m_X, dest.m_Y, dest.m_Z, dest.m_orient); 908 | + } 909 | +} 910 | + 911 | +class npc_teleport : public CreatureScript 912 | +{ 913 | +public: 914 | + npc_teleport() : CreatureScript("npc_teleport") {} 915 | + 916 | +bool OnGossipHello(Player *player, Creature *creature) 917 | +{ 918 | + PageC(player) = PageD(player) = Cat(player) = 0; 919 | + 920 | + if(player->isInCombat()) 921 | + { 922 | + player->CLOSE_GOSSIP_MENU(); 923 | + creature->MonsterWhisper("You are in combat. Come back later", player->GetGUID()); 924 | + return true; 925 | + } 926 | + AffichCat(player, creature); 927 | + return true; 928 | +} 929 | + 930 | +bool OnGossipSelect(Player *player, Creature *creature, uint32 sender, uint32 param) 931 | +{ 932 | + player->PlayerTalkClass->ClearMenus(); 933 | + switch(sender) 934 | + { 935 | + // Display destinations 936 | + case GOSSIP_SHOW_DEST: 937 | + Cat(player) = param; 938 | + AffichDest(player, creature); 939 | + break; 940 | + 941 | + // Previous categories page 942 | + case GOSSIP_PREV_PAGEC: 943 | + --PageC(player); 944 | + AffichCat(player, creature); 945 | + break; 946 | + 947 | + // Next page categories 948 | + case GOSSIP_NEXT_PAGEC: 949 | + ++PageC(player); 950 | + AffichCat(player, creature); 951 | + break; 952 | + 953 | + // Previous destinations page 954 | + case GOSSIP_PREV_PAGED: 955 | + --PageD(player); 956 | + AffichDest(player, creature); 957 | + break; 958 | + 959 | + // Next destination page 960 | + case GOSSIP_NEXT_PAGED: 961 | + ++PageD(player); 962 | + AffichDest(player, creature); 963 | + break; 964 | + 965 | + // Display main menu 966 | + case GOSSIP_MAIN_MENU: 967 | + OnGossipHello(player, creature); 968 | + break; 969 | + 970 | + // Teleportation 971 | + case GOSSIP_TELEPORT: 972 | + player->CLOSE_GOSSIP_MENU(); 973 | + if(player->HasAura(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS,0)) { 974 | + creature->CastSpell(player,38588,false); // Healing effect 975 | + player->RemoveAurasDueToSpell(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS); 976 | + } 977 | + 978 | + ActionTeleport(player, creature, param); 979 | + break; 980 | + } 981 | + return true; 982 | +} 983 | +}; 984 | + 985 | +void AddSC_npc_teleport() 986 | +{ 987 | + new npc_teleport; 988 | +} 989 | -- 990 | 1.7.3.1.msysgit.0 991 | 992 | -------------------------------------------------------------------------------- /11231-independent/0001-telenpc2.patch: -------------------------------------------------------------------------------- 1 | From 848e880b40a29d958824f12ab69a865c3bfcade0 Mon Sep 17 00:00:00 2001 2 | From: thedevnull 3 | Date: Thu, 17 Feb 2011 09:48:19 -0300 4 | Subject: [PATCH] telenpc2 5 | Signed-off-by: thedevnull 6 | 7 | --- 8 | README.NPCTELEPORT | 14 + 9 | sql/tools/setup_npc_teleport.sql | 119 +++++++ 10 | src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp | 373 +++++++++++++++++++++ 11 | src/server/game/AI/ScriptedAI/sc_npc_teleport.h | 151 +++++++++ 12 | src/server/game/Scripting/ScriptLoader.cpp | 6 +- 13 | src/server/game/Scripting/ScriptMgr.cpp | 3 + 14 | src/server/scripts/CMakeLists.txt | 3 + 15 | src/server/scripts/Custom/npc_teleport.cpp | 221 ++++++++++++ 16 | 8 files changed, 889 insertions(+), 1 deletions(-) 17 | create mode 100644 README.NPCTELEPORT 18 | create mode 100644 sql/tools/setup_npc_teleport.sql 19 | create mode 100644 src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp 20 | create mode 100644 src/server/game/AI/ScriptedAI/sc_npc_teleport.h 21 | create mode 100644 src/server/scripts/Custom/npc_teleport.cpp 22 | 23 | diff --git a/README.NPCTELEPORT b/README.NPCTELEPORT 24 | new file mode 100644 25 | index 0000000..015c9c2 26 | --- /dev/null 27 | +++ b/README.NPCTELEPORT 28 | @@ -0,0 +1,14 @@ 29 | +NPC Teleport for Trinity 30 | + 31 | +Original author : Wilibald09 32 | + 33 | +Allows you to add a custom NPC for teleporting, using .npc add 100000. 34 | +The default NPC is entry 100000. 35 | + 36 | +All settings are located in the DB, so you can customize and add destinations, 37 | +set level restrictions and also charge the player for teleporting. 38 | + 39 | +Installation: 40 | + 41 | +Run the query setup_npc_teleport.sql located in the trinity sql directory on 42 | +your world DB. This will setup the DB and you can customize from there. 43 | diff --git a/sql/tools/setup_npc_teleport.sql b/sql/tools/setup_npc_teleport.sql 44 | new file mode 100644 45 | index 0000000..03b9e93 46 | --- /dev/null 47 | +++ b/sql/tools/setup_npc_teleport.sql 48 | @@ -0,0 +1,119 @@ 49 | +DROP TABLE IF EXISTS `custom_npc_tele_category`; 50 | +CREATE TABLE `custom_npc_tele_category` ( 51 | + `id` int(6) unsigned NOT NULL default '0', 52 | + `name` varchar(255) NOT NULL default '', 53 | + `flag` tinyint(3) unsigned NOT NULL default '0', 54 | + `data0` bigint(20) unsigned NOT NULL default '0', 55 | + `data1` int(6) unsigned NOT NULL default '0', 56 | + PRIMARY KEY (`id`) 57 | +) ENGINE=MyISAM DEFAULT CHARSET=utf8; 58 | + 59 | +DROP TABLE IF EXISTS `custom_npc_tele_destination`; 60 | +CREATE TABLE `custom_npc_tele_destination` ( 61 | + `id` int(6) unsigned NOT NULL auto_increment, 62 | + `name` char(100) NOT NULL default '', 63 | + `pos_X` float NOT NULL default '0', 64 | + `pos_Y` float NOT NULL default '0', 65 | + `pos_Z` float NOT NULL default '0', 66 | + `map` smallint(5) unsigned NOT NULL default '0', 67 | + `orientation` float NOT NULL default '0', 68 | + `level` tinyint(3) unsigned NOT NULL default '0', 69 | + `cost` int(10) unsigned NOT NULL default '0', 70 | + PRIMARY KEY (`id`) 71 | +) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 72 | + 73 | +DROP TABLE IF EXISTS `custom_npc_tele_association`; 74 | +CREATE TABLE `custom_npc_tele_association` ( 75 | + `cat_id` int(6) unsigned NOT NULL default '0', 76 | + `dest_id` int(6) unsigned NOT NULL default '0', 77 | + PRIMARY KEY (`cat_id`, `dest_id`) 78 | +) ENGINE=MyISAM DEFAULT CHARSET=utf8; 79 | + 80 | +TRUNCATE `custom_npc_tele_category`; 81 | +INSERT INTO `custom_npc_tele_category` 82 | + (`id`, `name`, `flag`, `data0`, `data1`) 83 | +VALUES 84 | + (1, 'Cities', 0, 1, 0), 85 | + (2, 'Cities', 0, 2, 0), 86 | + (3, 'Battlegrounds', 0, 1, 0), 87 | + (4, 'Battlegrounds', 0, 2, 0), 88 | + (5, 'Arenas', 0, 0, 0), 89 | + (6, '[Instances Lvl 1-60]', 0, 0, 0), 90 | + (7, '[Instances Lvl 60+]', 5, 60, 0), 91 | + (8, '[Instances Lvl 70+]', 5, 70, 0), 92 | + (9, 'Destinations MJ', 3, 0, 0); 93 | + 94 | +TRUNCATE `custom_npc_tele_destination`; 95 | +INSERT INTO `custom_npc_tele_destination` 96 | + (`id`, `name`, `pos_X`, `pos_Y`, `pos_Z`, `map`, `orientation`, `level`, `cost`) 97 | +VALUES 98 | + (1, 'Alterac Valley', 883.187, -489.375, 96.7618, 30, 3.06932, 0, 0), 99 | + (2, 'Alterac Valley', -818.155, -623.043, 54.0884, 30, 2.1, 0, 0), 100 | + (3, 'Arathi Basin', 686.053, 683.165, -12.9149, 529, 0.18, 0, 0), 101 | + (4, 'Arathi Basin', 1308.68, 1306.03, -9.0107, 529, 3.91285, 0, 0), 102 | + (5, 'Black Temple', -3610.72, 324.988, 37.4, 530, 3.28298, 0, 0), 103 | + (6, 'Blackfathom Deeps', 4254.58, 664.74, -29.04, 1, 1.97, 0, 0), 104 | + (7, 'Blackrock Depths', -7301.03, -913.19, 165.37, 0, 0.08, 0, 0), 105 | + (8, 'Blackrock Spire', -7535.43, -1212.04, 285.45, 0, 5.29, 0, 0), 106 | + (9, 'Blackwing Lair', -7665.55, -1102.49, 400.679, 469, 0, 0, 0), 107 | + (10, 'Caverns of Time', -8173.66, -4746.36, 33.8423, 1, 4.93989, 0, 0), 108 | + (11, 'Circle of Blood', 2839.44, 5930.17, 11.1002, 530, 3.16284, 0, 0), 109 | + (12, 'Coilfang Reservoir', 517.288, 6976.28, 32.0072, 530, 0, 0, 0), 110 | + (13, 'Darnassus', 9947.52, 2482.73, 1316.21, 1, 0, 0, 0), 111 | + (14, 'Dire Maul', -3982.47, 1127.79, 161.02, 1, 0.05, 0, 0), 112 | + (15, 'Exodar', -4073.03, -12020.4, -1.47, 530, 0, 0, 0), 113 | + (16, 'Eye of the Storm', 2487.72, 1609.12, 1224.64, 566, 3.35671, 0, 0), 114 | + (17, 'Eye of the Storm', 1843.73, 1529.77, 1224.43, 566, 0.297579, 0, 0), 115 | + (18, 'Goldshire', -9464, 62, 56, 0, 0, 0, 0), 116 | + (19, 'Gruul\'s Lair', 3539.01, 5082.36, 1.69107, 530, 0, 0, 0), 117 | + (20, 'Gurubashi', -13261.3, 168.294, 35.0792, 0, 1.00688, 0, 0), 118 | + (21, 'Hellfire Citadel', -305.816, 3056.4, -2.47318, 530, 2.01, 0, 0), 119 | + (22, 'Ironforge', -4924.07, -951.95, 501.55, 0, 5.4, 0, 0), 120 | + (23, 'Isle Of Quel\'Danas', 12947.4, -6893.31, 5.68398, 530, 3.09154, 0, 0), 121 | + (24, 'Karazhan', -11118.8, -2010.84, 47.0807, 0, 0, 0, 0), 122 | + (25, 'Maraudon', -1433.33, 2955.34, 96.21, 1, 4.82, 0, 0), 123 | + (26, 'Molten Core', 1121.45, -454.317, -101.33, 230, 3.5, 0, 0), 124 | + (27, 'Naxxramas', 3125.18, -3748.02, 136.049, 0, 0, 0, 0), 125 | + (28, 'Onyxia\'s Lair', -4707.44, -3726.82, 54.6723, 1, 3.8, 0, 0), 126 | + (29, 'Orgrimmar', 1552.5, -4420.66, 8.94802, 1, 0, 0, 0), 127 | + (30, 'Razor Hill', 315.721, -4743.4, 10.4867, 1, 0, 0, 0), 128 | + (31, 'Razorfen Downs', -4645.08, -2470.85, 85.53, 1, 4.39, 0, 0), 129 | + (32, 'Razorfen Kraul', -4484.04, -1739.4, 86.47, 1, 1.23, 0, 0), 130 | + (33, 'Ring of Trials', -1999.94, 6581.71, 11.32, 530, 2.3, 0, 0), 131 | + (34, 'Ruins of Ahn\'Qiraj', -8409.03, 1498.83, 27.3615, 1, 2.49757, 0, 0), 132 | + (35, 'Scholomance', 1219.01, -2604.66, 85.61, 0, 0.5, 0, 0), 133 | + (36, 'Shadowfang Keep', -254.47, 1524.68, 76.89, 0, 1.56, 0, 0), 134 | + (37, 'Shattrath City', -1850.21, 5435.82, -10.9614, 530, 3.40391, 0, 0), 135 | + (38, 'Silvermoon', 9338.74, -7277.27, 13.7895, 530, 0, 0, 0), 136 | + (39, 'Stormwind', -8960.14, 516.266, 96.3568, 0, 0, 0, 0), 137 | + (40, 'Stratholme', 3263.54, -3379.46, 143.59, 0, 0, 0, 0), 138 | + (41, 'Tempest Keep', 3089.58, 1399.05, 187.653, 530, 4.79407, 0, 0), 139 | + (42, 'Temple of Ahn\'Qiraj', -8245.84, 1983.74, 129.072, 1, 0.936195, 0, 0), 140 | + (43, 'The Deadmines', -11212, 1658.58, 25.67, 0, 1.45, 0, 0), 141 | + (44, 'The Maul', -3761.49, 1133.43, 132.083, 1, 4.57259, 0, 0), 142 | + (45, 'The Scarlet Monastery', 2843.89, -693.74, 139.32, 0, 5.11, 0, 0), 143 | + (46, 'The Sunken Temple', -10346.9, -3851.9, -43.41, 0, 6.09, 0, 0), 144 | + (47, 'The Wailing Caverns', -722.53, -2226.3, 16.94, 1, 2.71, 0, 0), 145 | + (48, 'Thunder Bluff', -1290, 147.034, 129.682, 1, 4.919, 0, 0), 146 | + (49, 'Uldaman', -6119.7, -2957.3, 204.11, 0, 0.03, 0, 0), 147 | + (50, 'Undercity', 1819.71, 238.79, 60.5321, 0, 0, 0, 0), 148 | + (51, 'Warsong Gulch', 930.851, 1431.57, 345.537, 489, 0.015704, 0, 0), 149 | + (52, 'Warsong Gulch', 1525.95, 1481.66, 352.001, 489, 3.20756, 0, 0), 150 | + (53, 'Zul\'Aman', 6846.95, -7954.5, 170.028, 530, 4.61501, 0, 0), 151 | + (54, 'Zul\'Farrak', -6839.39, -2911.03, 8.87, 1, 0.41, 0, 0), 152 | + (55, 'Zul\'Gurub', -11916.7, -1212.82, 92.2868, 0, 4.6095, 0, 0), 153 | + (56, 'Ile des MJ', 16254, 16276.9, 14.5082, 1, 1.70269, 0, 0); 154 | + 155 | +TRUNCATE `custom_npc_tele_association`; 156 | +INSERT INTO `custom_npc_tele_association` 157 | + (`cat_id`, `dest_id`) 158 | +VALUES 159 | + (1, 13), (1, 15), (1, 18), (1, 22), (1, 23), (1, 37), (1, 39), (2, 23), (2, 29), (2, 30), (2, 37), (2, 38), (2, 48), (2, 50), (3, 1), (3, 4), (3, 16), (3, 52), (4, 2), (4, 3), (4, 17), (4, 51), (5, 11), (5, 20), (5, 33), (5, 44), (6, 6), (6, 7), (6, 8), (6, 14), (6, 25), (6, 31), (6, 32), (6, 35), (6, 36), (6, 40), (6, 43), (6, 45), (6, 46), (6, 47), (6, 49), (6, 54), (7, 9), (7, 26), (7, 27), (7, 28), (7, 34), (7, 42), (7, 55), (8, 5), (8, 10), (8, 12), (8, 19), (8, 21), (8, 24), (8, 41), (8, 53), (9, 56); 160 | + 161 | +-- `npc_text` 162 | +REPLACE INTO `npc_text` (`ID`, `text0_0`) VALUES 163 | + (100000, 'Choose your Category.'), 164 | + (100001, 'Choose your Destination.'); 165 | + 166 | +-- `creature_template` 167 | +INSERT INTO `creature_template` VALUES (100000, 0, 0, 0, 0, 0, 26502, 0, 0, 0, 'Abisal Vortex', '', '', 0, 83, 83, 0, 35, 35, 1, 1, 1.14286, 2, 1, 509, 683, 0, 805, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 371, 535, 135, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 'npc_teleport', 1); 168 | diff --git a/src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp b/src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp 169 | new file mode 100644 170 | index 0000000..c40d861 171 | --- /dev/null 172 | +++ b/src/server/game/AI/ScriptedAI/sc_npc_teleport.cpp 173 | @@ -0,0 +1,373 @@ 174 | +/** 175 | + * 176 | + * @File : sc_npc_teleport.cpp 177 | + * 178 | + * @Authors : Wilibald09 179 | + * 180 | + * @Date : 28/08/2008 181 | + * 182 | + * @Version : 1.2 183 | + * 184 | + **/ 185 | + 186 | + 187 | +#include "ScriptPCH.h" 188 | +#include "sc_npc_teleport.h" 189 | + 190 | +#define TELE nsNpcTel::CatDest 191 | +#define PAGE nsNpcTel::Page 192 | +#define PAGEI PAGE::Instance 193 | + 194 | + 195 | +nsNpcTel::VCatDest nsNpcTel::TabCatDest; 196 | + 197 | + 198 | +uint32 PAGE::operator [] (Player * const player) const 199 | +{ 200 | + for (VInst_t i(0); i < m_TabInstance.size(); ++i) 201 | + { 202 | + if (m_TabInstance[i].GetPlayer() == player) 203 | + return m_TabInstance[i].GetPageId(); 204 | + } 205 | + return 0; 206 | +} 207 | + 208 | +PAGE::Instance & PAGE::operator () (Player * const player) 209 | +{ 210 | + for (VInst_t i(0); i < m_TabInstance.size(); ++i) 211 | + { 212 | + if (m_TabInstance[i].GetPlayer() == player) 213 | + return m_TabInstance[i]; 214 | + } 215 | + m_TabInstance.push_back(Instance(player)); 216 | + return m_TabInstance.back(); 217 | +} 218 | + 219 | +PAGE::Instance & PAGEI::operator = (const uint32 &id) 220 | +{ 221 | + m_PageId = id; 222 | + return *this; 223 | +} 224 | + 225 | +PAGE::Instance & PAGEI::operator ++ (void) 226 | +{ 227 | + ++m_PageId; 228 | + return *this; 229 | +} 230 | + 231 | +PAGE::Instance PAGEI::operator ++ (int32) 232 | +{ 233 | + Instance tmp (*this); 234 | + ++m_PageId; 235 | + return tmp; 236 | +} 237 | + 238 | +PAGE::Instance & PAGEI::operator -- (void) 239 | +{ 240 | + --m_PageId; 241 | + return *this; 242 | +} 243 | + 244 | +PAGE::Instance PAGEI::operator -- (int32) 245 | +{ 246 | + Instance tmp (*this); 247 | + --m_PageId; 248 | + return tmp; 249 | +} 250 | + 251 | +TELE::CatDest(const uint32 &id, const std::string &name, 252 | + const Flag &flag, const uint64 &data0, const uint32 &data1) 253 | + : m_id(id), m_name(name), m_flag(flag), m_data0(data0), m_data1(data1) 254 | +{ 255 | + m_TabDest.clear(); 256 | +} 257 | + 258 | +std::string TELE::GetName(const bool IsGM /* = false */) const 259 | +{ 260 | + if (!IsGM || m_flag != FLAG_TEAM) 261 | + return m_name; 262 | + 263 | + switch (m_data0) 264 | + { 265 | + case TEAM_HORDE: return std::string(m_name + " (H)"); 266 | + case TEAM_ALLIANCE: return std::string(m_name + " (A)"); 267 | + } 268 | + return m_name; 269 | +} 270 | + 271 | +bool TELE::IsAllowedToTeleport(Player * const player) const 272 | +{ 273 | + if (player->isGameMaster()) 274 | + { 275 | + if (m_flag == FLAG_GMLEVEL) 276 | + return player->GetSession()->GetSecurity() >= m_data0; 277 | + return true; 278 | + } 279 | + 280 | + switch (m_flag) 281 | + { 282 | + case FLAG_TEAM: 283 | + switch (m_data0) 284 | + { 285 | + case TEAM_HORDE: return player->GetTeam() == HORDE; 286 | + case TEAM_ALLIANCE: return player->GetTeam() == ALLIANCE; 287 | + case TEAM_ALL: return true; 288 | + } 289 | + 290 | + case FLAG_GUILD: 291 | + return player->GetGuildId() == m_data0; 292 | + 293 | + case FLAG_GMLEVEL: 294 | + return player->GetSession()->GetSecurity() >= m_data0; 295 | + 296 | + case FLAG_ISGM: 297 | + return player->isGameMaster(); 298 | + 299 | + case FLAG_ACCOUNT: 300 | + return player->GetSession()->GetAccountId() == m_data0; 301 | + 302 | + case FLAG_LEVEL: 303 | + return player->getLevel() >= m_data0; 304 | + 305 | + case FLAG_ITEM: 306 | + return player->HasItemCount(m_data0, m_data1, true); 307 | + 308 | + case FLAG_QUEST: 309 | + if (m_data1 < MAX_QUEST_STATUS) 310 | + return player->GetQuestStatus(m_data0) == m_data1; 311 | + return player->GetQuestRewardStatus(m_data0); 312 | + 313 | + case FLAG_GENDER: 314 | + return player->getGender() == m_data0; 315 | + 316 | + case FLAG_RACE: 317 | + return player->getRace() == m_data0; 318 | + 319 | + case FLAG_CLASS: 320 | + return player->getClass() == m_data0; 321 | + 322 | + case FLAG_REPUTATION: 323 | + return player->GetReputationRank(m_data0) >= m_data1; 324 | + 325 | + case FLAG_PLAYER: 326 | + return player->GetGUID() == m_data0; 327 | + } 328 | + 329 | + sLog->outError("Invalid flag (category: %u). Important problem...", GetCatID()); 330 | + return false; 331 | +} 332 | + 333 | +uint32 TELE::CountOfCategoryAllowedBy(Player * const player) 334 | +{ 335 | + uint32 count (0); 336 | + for (VCatDest_t i(0); i < TabCatDest.size(); ++i) 337 | + { 338 | + if (TabCatDest[i].IsAllowedToTeleport(player)) 339 | + ++count; 340 | + } 341 | + return count; 342 | +} 343 | + 344 | +bool nsNpcTel::IsValidData(const uint32 &cat, const Flag &flag, 345 | + const uint64 &data0, const uint32 &data1) 346 | +{ 347 | + switch(flag) 348 | + { 349 | + case FLAG_TEAM: 350 | + if (data1) 351 | + sLog->outError("Invalid data1 (category: %u).", cat); 352 | + if (data0 < MAX_FLAG_TEAM) 353 | + return true; 354 | + sLog->outError("Invalid data0 (Team) (category: %u).", cat); 355 | + return false; 356 | + 357 | + case FLAG_GUILD: 358 | + if (data1) 359 | + sLog->outError("Invalid data1 (category: %u).", cat); 360 | + if (data0) 361 | + return true; 362 | + sLog->outError("Invalid data0 (GuildID) (category: %u).", cat); 363 | + return false; 364 | + 365 | + case FLAG_GMLEVEL: 366 | + if (data1) 367 | + sLog->outError("Invalid data1 (category: %u).", cat); 368 | + if (0 < data0 && data0 < 256) 369 | + return true; 370 | + sLog->outError("Invalid data0 (GmLevel) (category: %u).", cat); 371 | + return false; 372 | + 373 | + case FLAG_ISGM: 374 | + if (data0) 375 | + sLog->outError("Invalid data0 (category: %u).", cat); 376 | + if (data1) 377 | + sLog->outError("Invalid data1 (category: %u).", cat); 378 | + return true; 379 | + 380 | + case FLAG_ACCOUNT: 381 | + if (data1) 382 | + sLog->outError("Invalid data1 (category: %u).", cat); 383 | + if (data0) 384 | + return true; 385 | + sLog->outError("Invalid data0 (AccountID) (category: %u).", cat); 386 | + return false; 387 | + 388 | + case FLAG_LEVEL: 389 | + if (data1) 390 | + sLog->outError("Invalid data1 (category: %u).", cat); 391 | + if (0 < data0 && data0 < 256) 392 | + return true; 393 | + sLog->outError("Invalid data0 (Level) (category: %u).", cat); 394 | + return false; 395 | + 396 | + case FLAG_ITEM: 397 | + if (!data0) 398 | + { 399 | + sLog->outError("Invalid data0 (ItemID) (category: %u).", cat); 400 | + return false; 401 | + } 402 | + if (data1) 403 | + return true; 404 | + sLog->outError("Invalid data1 (Item Count) (category: %u).", cat); 405 | + return false; 406 | + 407 | + case FLAG_QUEST: 408 | + if (!data0) 409 | + { 410 | + sLog->outError("Invalid data0 (QuestID) (category: %u).", cat); 411 | + return false; 412 | + } 413 | + if (data1 < MAX_QUEST_STATUS + 1) 414 | + return true; 415 | + sLog->outError("Invalid data1 (Quest Status) (category: %u).", cat); 416 | + return false; 417 | + 418 | + case FLAG_GENDER: 419 | + if (data1) 420 | + sLog->outError("Invalid data1 (category: %u).", cat); 421 | + if (data0 < GENDER_NONE) 422 | + return true; 423 | + sLog->outError("Invalid data0 (Gender) (category: %u).", cat); 424 | + return false; 425 | + 426 | + case FLAG_RACE: 427 | + if (data1) 428 | + sLog->outError("Invalid data1 (category: %u).", cat); 429 | + if (0 < data0 && data0 < MAX_RACES) 430 | + return true; 431 | + sLog->outError("Invalid data0 (Race) (category: %u).", cat); 432 | + return false; 433 | + 434 | + case FLAG_CLASS: 435 | + if (data1) 436 | + sLog->outError("Invalid data1 (category: %u).", cat); 437 | + if (0 < data0 && data0 < MAX_CLASSES) 438 | + return true; 439 | + sLog->outError("Invalid data0 (Class) (category: %u).", cat); 440 | + return false; 441 | + 442 | + case FLAG_REPUTATION: 443 | + if (!data0) 444 | + { 445 | + sLog->outError("Invalid data0 (Faction/Reputation) (category: %u).", cat); 446 | + return false; 447 | + } 448 | + if (data1 <= REP_EXALTED) 449 | + return true; 450 | + sLog->outError("Invalid data1 (Faction/Reputation) (category: %u).", cat); 451 | + return false; 452 | + 453 | + case FLAG_PLAYER: 454 | + if (data1) 455 | + sLog->outError("Invalid data1 (category: %u).", cat); 456 | + if (data0) 457 | + return true; 458 | + sLog->outError("Invalid data0 (PlayerGuid) (category: %u).", cat); 459 | + return false; 460 | + } 461 | + 462 | + sLog->outError("Invalid flag (category: %u).", cat); 463 | + return false; 464 | +} 465 | + 466 | +void LoadNpcTele(void) 467 | +{ 468 | + const char *Table[] = 469 | + { 470 | + "custom_npc_tele_category", 471 | + "custom_npc_tele_destination", 472 | + "custom_npc_tele_association", 473 | + }; 474 | + 475 | + 476 | + QueryResult result = WorldDatabase.PQuery( 477 | + "SELECT `flag`, `data0`, `data1`, `cat_id`, C.`name` `namecat`, D.`name` `namedest`, " 478 | + // 0 1 2 3 4 5 479 | + "`pos_X`, `pos_Y`, `pos_Z`, `orientation`, `map`, `level`, `cost` " 480 | + // 6 7 8 9 10 11 12 481 | + "FROM `%s` C, `%s` D, `%s` A " 482 | + "WHERE C.`id` = `cat_id` AND D.`id` = `dest_id` " 483 | + "ORDER BY `namecat`, `cat_id`, `namedest`", Table[0], Table[1], Table[2]); 484 | + 485 | + nsNpcTel::TabCatDest.clear(); 486 | + 487 | + if (result) 488 | + { 489 | + sLog->outString( "TSCR: Loading %s, %s and %s...", Table[0], Table[1], Table[2]); 490 | + 491 | + uint32 catid = 0; 492 | + uint32 nbDest = 0; 493 | + bool IsValidCat = true; 494 | + bool FirstTime = true; 495 | + 496 | + do 497 | + { 498 | + Field *fields = result->Fetch(); 499 | + 500 | + if (!IsValidCat && catid == fields[3].GetUInt32() && !FirstTime) 501 | + continue; 502 | + 503 | + IsValidCat = true; 504 | + FirstTime = false; 505 | + 506 | + if (!nsNpcTel::IsValidData(fields[3].GetUInt32(), (nsNpcTel::Flag)fields[0].GetUInt8(), 507 | + fields[1].GetUInt64(), fields[2].GetUInt32())) 508 | + { 509 | + IsValidCat = false; 510 | + catid = fields[3].GetUInt32(); 511 | + continue; 512 | + } 513 | + 514 | + if (catid != fields[3].GetUInt32()) 515 | + { 516 | + catid = fields[3].GetUInt32(); 517 | + nsNpcTel::CatDest categorie (catid, fields[4].GetString(), (nsNpcTel::Flag)fields[0].GetUInt8(), 518 | + fields[1].GetUInt64(), fields[2].GetUInt32()); 519 | + nsNpcTel::TabCatDest.push_back(categorie); 520 | + } 521 | + 522 | + nsNpcTel::Dest item = 523 | + { 524 | + fields[5].GetString(), // Name 525 | + fields[6].GetFloat(), // X 526 | + fields[7].GetFloat(), // Y 527 | + fields[8].GetFloat(), // Z 528 | + fields[9].GetFloat(), // Orientation 529 | + fields[10].GetUInt16(), // Map 530 | + fields[11].GetUInt8(), // Level 531 | + fields[12].GetUInt32(), // Cost 532 | + }; 533 | + 534 | + nsNpcTel::TabCatDest.back().AddDest(item); 535 | + ++nbDest; 536 | + } while (result->NextRow()); 537 | + 538 | + sLog->outString(""); 539 | + sLog->outString("TSCR: >> Loaded %u npc_teleport.", nbDest); 540 | + } else sLog->outString("TSCR: WARNING >> Loaded 0 npc_teleport."); 541 | +} 542 | + 543 | + 544 | +#undef TELE 545 | +#undef PAGE 546 | +#undef PAGEI 547 | diff --git a/src/server/game/AI/ScriptedAI/sc_npc_teleport.h b/src/server/game/AI/ScriptedAI/sc_npc_teleport.h 548 | new file mode 100644 549 | index 0000000..4830245 550 | --- /dev/null 551 | +++ b/src/server/game/AI/ScriptedAI/sc_npc_teleport.h 552 | @@ -0,0 +1,151 @@ 553 | +/** 554 | + * 555 | + * @File : sc_npc_teleport.h 556 | + * 557 | + * @Authors : Wilibald09 558 | + * 559 | + * @Date : 19/08/2008 560 | + * 561 | + * @Version : 1.2 562 | + * 563 | + **/ 564 | + 565 | + 566 | +#ifndef SC_NPC_TELEPORT_H 567 | +#define SC_NPC_TELEPORT_H 568 | + 569 | +#include 570 | + 571 | + 572 | +namespace nsNpcTel 573 | +{ 574 | + // Different types of permissions 575 | + enum Flag 576 | + { 577 | + FLAG_TEAM = 0, 578 | + FLAG_GUILD = 1, 579 | + FLAG_GMLEVEL = 2, 580 | + FLAG_ISGM = 3, 581 | + FLAG_ACCOUNT = 4, 582 | + FLAG_LEVEL = 5, 583 | + FLAG_ITEM = 6, 584 | + FLAG_QUEST = 7, 585 | + FLAG_GENDER = 8, 586 | + FLAG_RACE = 9, 587 | + FLAG_CLASS = 10, 588 | + FLAG_REPUTATION = 11, 589 | + FLAG_PLAYER = 12, 590 | + MAX_FLAG, 591 | + }; 592 | + 593 | + // Different parameters of FLAG_TEAM 594 | + enum 595 | + { 596 | + TEAM_ALL = 0, 597 | + TEAM_ALLIANCE = 1, 598 | + TEAM_HORDE = 2, 599 | + MAX_FLAG_TEAM, 600 | + }; 601 | + 602 | + // Structure representing the destinations 603 | + struct Dest 604 | + { 605 | + std::string m_name; 606 | + float m_X, m_Y, m_Z, m_orient; 607 | + uint16 m_map; 608 | + uint8 m_level; 609 | + uint32 m_cost; 610 | + }; 611 | + 612 | + // Class representing the categories of destinations 613 | + class CatDest 614 | + { 615 | + public: 616 | + 617 | + typedef std::vector VDest; 618 | + typedef VDest::size_type VDest_t; 619 | + 620 | + CatDest(const uint32 &id, const std::string &name, 621 | + const Flag &flag, const uint64 &data0, const uint32 &data1); 622 | + 623 | + void AddDest (const Dest &item) { m_TabDest.push_back(item); } 624 | + Dest GetDest (const uint32 &id) const { return m_TabDest[id]; } 625 | + uint32 GetCatID (void) const { return m_id; } 626 | + uint32 size (void) const { return m_TabDest.size(); } 627 | + 628 | + std::string GetName(const bool IsGM = false) const; 629 | + bool IsAllowedToTeleport(Player * const player) const; 630 | + 631 | + static uint32 CountOfCategoryAllowedBy(Player * const player); 632 | + 633 | + private: 634 | + 635 | + uint32 m_id; 636 | + std::string m_name; 637 | + Flag m_flag; 638 | + uint64 m_data0; 639 | + uint32 m_data1; 640 | + VDest m_TabDest; 641 | + }; 642 | + 643 | + // Class page for current player 644 | + class Page 645 | + { 646 | + protected: 647 | + 648 | + // Class instance for current player 649 | + class Instance 650 | + { 651 | + public: 652 | + 653 | + Instance(Player * const player, const uint32 &PageId = 0) 654 | + : m_player(player), m_PageId(PageId) {} 655 | + 656 | + Instance & operator = (const uint32 &id); 657 | + Instance & operator ++ (void); 658 | + Instance operator ++ (int32); 659 | + Instance & operator -- (void); 660 | + Instance operator -- (int32); 661 | + 662 | + uint32 GetPageId(void) const { return m_PageId; } 663 | + Player * GetPlayer(void) const { return m_player; } 664 | + 665 | + private: 666 | + 667 | + Player *m_player; 668 | + uint32 m_PageId; 669 | + }; 670 | + 671 | + 672 | + public: 673 | + 674 | + typedef std::vector VInst; 675 | + typedef VInst::size_type VInst_t; 676 | + 677 | + Page(void) { m_TabInstance.clear(); } 678 | + 679 | + Instance & operator () (Player * const player); 680 | + uint32 operator [] (Player * const player) const; 681 | + 682 | + 683 | + private: 684 | + 685 | + VInst m_TabInstance; 686 | + }; 687 | + 688 | + typedef std::vector VCatDest; 689 | + typedef VCatDest::size_type VCatDest_t; 690 | + 691 | + // Verification of data integrity 692 | + bool IsValidData(const uint32 &cat, const Flag &flag, 693 | + const uint64 &data0, const uint32 &data1); 694 | + 695 | + extern VCatDest TabCatDest; 696 | +} 697 | + 698 | +// Loading contents of database 699 | +void LoadNpcTele(void); 700 | + 701 | +extern WorldDatabaseWorkerPool WorldDatabase; 702 | + 703 | +#endif 704 | diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/game/Scripting/ScriptLoader.cpp 705 | index cb1b2c8..abd9706 100755 706 | --- a/src/server/game/Scripting/ScriptLoader.cpp 707 | +++ b/src/server/game/Scripting/ScriptLoader.cpp 708 | @@ -25,6 +25,9 @@ void AddSC_example_gossip_codebox(); 709 | void AddSC_example_misc(); 710 | void AddSC_example_commandscript(); 711 | 712 | +//TeleNPC2 713 | +void AddSC_npc_teleport(); 714 | + 715 | // spells 716 | void AddSC_deathknight_spell_scripts(); 717 | void AddSC_druid_spell_scripts(); 718 | @@ -1210,6 +1213,7 @@ void AddCustomScripts() 719 | { 720 | #ifdef SCRIPTS 721 | /* This is where custom scripts should be added. */ 722 | - 723 | + //TeleNPC2 724 | + AddSC_npc_teleport(); 725 | #endif 726 | } 727 | diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp 728 | index 8b97aa2..8b7e69f 100755 729 | --- a/src/server/game/Scripting/ScriptMgr.cpp 730 | +++ b/src/server/game/Scripting/ScriptMgr.cpp 731 | @@ -25,6 +25,7 @@ 732 | #include "ScriptLoader.h" 733 | #include "ScriptSystem.h" 734 | #include "Transport.h" 735 | +#include "sc_npc_teleport.h" 736 | 737 | // Utility macros to refer to the script registry. 738 | #define SCR_REG_MAP(T) ScriptRegistry::ScriptMap 739 | @@ -180,6 +181,8 @@ void ScriptMgr::Initialize() 740 | uint32 oldMSTime = getMSTime(); 741 | 742 | LoadDatabase(); 743 | + // Load TeleNPC2 - maybe not the best place to load it ... 744 | + LoadNpcTele(); 745 | 746 | sLog->outString("Loading C++ scripts"); 747 | 748 | diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt 749 | index 9fd63fd..047dff1 100644 750 | --- a/src/server/scripts/CMakeLists.txt 751 | +++ b/src/server/scripts/CMakeLists.txt 752 | @@ -31,6 +31,9 @@ include(Examples/CMakeLists.txt) 753 | 754 | set(scripts_STAT_SRCS 755 | ${scripts_STAT_SRCS} 756 | + Custom/npc_teleport.cpp 757 | + ../game/AI/ScriptedAI/sc_npc_teleport.cpp 758 | + ../game/AI/ScriptedAI/sc_npc_teleport.h 759 | ../game/AI/ScriptedAI/ScriptedEscortAI.cpp 760 | ../game/AI/ScriptedAI/ScriptedCreature.cpp 761 | ../game/AI/ScriptedAI/ScriptedFollowerAI.cpp 762 | diff --git a/src/server/scripts/Custom/npc_teleport.cpp b/src/server/scripts/Custom/npc_teleport.cpp 763 | new file mode 100644 764 | index 0000000..1e51336 765 | --- /dev/null 766 | +++ b/src/server/scripts/Custom/npc_teleport.cpp 767 | @@ -0,0 +1,221 @@ 768 | +/** 769 | + * 770 | + * @File : npc_teleport.cpp 771 | + * 772 | + * @Authors : Wilibald09 773 | + * 774 | + * @Date : 19/08/2008 775 | + * 776 | + * @Version : 1.2 777 | + * 778 | + **/ 779 | + 780 | + 781 | + 782 | +#include "ScriptPCH.h" 783 | +#include "sc_npc_teleport.h" 784 | +#include 785 | + 786 | +#define GOSSIP_SHOW_DEST 1000 787 | +#define GOSSIP_TELEPORT 1001 788 | +#define GOSSIP_NEXT_PAGEC 1002 789 | +#define GOSSIP_PREV_PAGEC 1003 790 | +#define GOSSIP_NEXT_PAGED 1004 791 | +#define GOSSIP_PREV_PAGED 1005 792 | +#define GOSSIP_MAIN_MENU 1006 793 | + 794 | +#define SPELL_ID_PASSIVE_RESURRECTION_SICKNESS 15007 795 | +#define SPELL_VISUAL_TELEPORT 35517 796 | + 797 | +#define NB_ITEM_PAGE 10 798 | +#define MSG_CAT 100000 799 | +#define MSG_DEST 100001 800 | + 801 | +#define NEXT_PAGE "-> [Next Page]" 802 | +#define PREV_PAGE "<- [Previous Page]" 803 | +#define MAIN_MENU "<= [Main Menu]" 804 | + 805 | + 806 | +using namespace nsNpcTel; 807 | + 808 | + 809 | +namespace 810 | +{ 811 | + Page PageC, PageD; 812 | + Page Cat; 813 | + 814 | + // Conversion function int->string 815 | + std::string ConvertStr(const int64 &val) 816 | + { 817 | + std::ostringstream ostr; 818 | + ostr << val; 819 | + return ostr.str(); 820 | + } 821 | + 822 | + // Conversion function intMoney->stringMoney 823 | + std::string ConvertMoney(const uint32 &Money) 824 | + { 825 | + std::string Str(ConvertStr(Money)); 826 | + uint32 SizeStr = Str.length(); 827 | + 828 | + if (SizeStr > 4) 829 | + Str = Str.insert(Str.length()-4, "po"); 830 | + if (SizeStr > 2) 831 | + Str = Str.insert(Str.length()-2, "pa"); 832 | + Str += "pc"; 833 | + 834 | + return Str; 835 | + } 836 | + 837 | + // Teleport Player 838 | + void Teleport(Player * const player, const uint16 &map, 839 | + const float &X, const float &Y, const float &Z, const float &orient) 840 | + { 841 | + player->CastSpell(player, SPELL_VISUAL_TELEPORT, true); 842 | + player->TeleportTo(map, X, Y, Z, orient); 843 | + } 844 | + 845 | + // Display categories 846 | + void AffichCat(Player * const player, Creature * const creature) 847 | + { 848 | + if (PageC[player] > 0) 849 | + player->ADD_GOSSIP_ITEM(7, PREV_PAGE, GOSSIP_PREV_PAGEC, 0); 850 | + 851 | + VCatDest_t i (PageC[player] * NB_ITEM_PAGE); 852 | + for ( ; i < TabCatDest.size() && i < (NB_ITEM_PAGE * (PageC[player] + 1)); ++i) 853 | + { 854 | + if (TabCatDest[i].IsAllowedToTeleport(player)) 855 | + player->ADD_GOSSIP_ITEM(7, TabCatDest[i].GetName(player->isGameMaster()).c_str(), GOSSIP_SHOW_DEST, i); 856 | + } 857 | + 858 | + if (i < TabCatDest.size()) 859 | + player->ADD_GOSSIP_ITEM(7, NEXT_PAGE, GOSSIP_NEXT_PAGEC, 0); 860 | + 861 | + player->SEND_GOSSIP_MENU(MSG_CAT, creature->GetGUID()); 862 | + } 863 | + 864 | + // Display destination categories 865 | + void AffichDest(Player * const player, Creature * const creature) 866 | + { 867 | + if (PageD[player] > 0) 868 | + player->ADD_GOSSIP_ITEM(7, PREV_PAGE, GOSSIP_PREV_PAGED, 0); 869 | + 870 | + CatDest::VDest_t i (PageD[player] * NB_ITEM_PAGE); 871 | + for ( ; i < TabCatDest[Cat[player]].size() && i < (NB_ITEM_PAGE * (PageD[player] + 1)); ++i) 872 | + { 873 | + player->ADD_GOSSIP_ITEM(5, TabCatDest[Cat[player]].GetDest(i).m_name.c_str(), GOSSIP_TELEPORT, i); 874 | + } 875 | + 876 | + if (i < TabCatDest[Cat[player]].size()) 877 | + player->ADD_GOSSIP_ITEM(7, NEXT_PAGE, GOSSIP_NEXT_PAGED, 0); 878 | + 879 | + if (CatDest::CountOfCategoryAllowedBy(player) > 1) 880 | + player->ADD_GOSSIP_ITEM(7, MAIN_MENU, GOSSIP_MAIN_MENU, 0); 881 | + 882 | + player->SEND_GOSSIP_MENU(MSG_DEST, creature->GetGUID()); 883 | + } 884 | + 885 | + // Verification before teleportation 886 | + void ActionTeleport(Player * const player, Creature * const creature, const uint32 &id) 887 | + { 888 | + Dest dest (TabCatDest[Cat[player]].GetDest(id)); 889 | + 890 | + if (player->getLevel() < dest.m_level && !player->isGameMaster()) 891 | + { 892 | + std::string msg ("You do not have the required level. This destination requires level " + ConvertStr(dest.m_level) + "."); 893 | + creature->MonsterWhisper(msg.c_str(), player->GetGUID()); 894 | + return; 895 | + } 896 | + 897 | + if (player->GetMoney() < dest.m_cost && !player->isGameMaster()) 898 | + { 899 | + std::string msg ("You do not have enough money. The price for teleportation is " + ConvertMoney(dest.m_cost) + "."); 900 | + creature->MonsterWhisper(msg.c_str(), player->GetGUID()); 901 | + return; 902 | + } 903 | + 904 | + if (!player->isGameMaster() && dest.m_cost) 905 | + player->ModifyMoney(-1 * dest.m_cost); 906 | + 907 | + Teleport(player, dest.m_map, dest.m_X, dest.m_Y, dest.m_Z, dest.m_orient); 908 | + } 909 | +} 910 | + 911 | +class npc_teleport : public CreatureScript 912 | +{ 913 | +public: 914 | + npc_teleport() : CreatureScript("npc_teleport") {} 915 | + 916 | +bool OnGossipHello(Player *player, Creature *creature) 917 | +{ 918 | + PageC(player) = PageD(player) = Cat(player) = 0; 919 | + 920 | + if(player->isInCombat()) 921 | + { 922 | + player->CLOSE_GOSSIP_MENU(); 923 | + creature->MonsterWhisper("You are in combat. Come back later", player->GetGUID()); 924 | + return true; 925 | + } 926 | + AffichCat(player, creature); 927 | + return true; 928 | +} 929 | + 930 | +bool OnGossipSelect(Player *player, Creature *creature, uint32 sender, uint32 param) 931 | +{ 932 | + player->PlayerTalkClass->ClearMenus(); 933 | + switch(sender) 934 | + { 935 | + // Display destinations 936 | + case GOSSIP_SHOW_DEST: 937 | + Cat(player) = param; 938 | + AffichDest(player, creature); 939 | + break; 940 | + 941 | + // Previous categories page 942 | + case GOSSIP_PREV_PAGEC: 943 | + --PageC(player); 944 | + AffichCat(player, creature); 945 | + break; 946 | + 947 | + // Next page categories 948 | + case GOSSIP_NEXT_PAGEC: 949 | + ++PageC(player); 950 | + AffichCat(player, creature); 951 | + break; 952 | + 953 | + // Previous destinations page 954 | + case GOSSIP_PREV_PAGED: 955 | + --PageD(player); 956 | + AffichDest(player, creature); 957 | + break; 958 | + 959 | + // Next destination page 960 | + case GOSSIP_NEXT_PAGED: 961 | + ++PageD(player); 962 | + AffichDest(player, creature); 963 | + break; 964 | + 965 | + // Display main menu 966 | + case GOSSIP_MAIN_MENU: 967 | + OnGossipHello(player, creature); 968 | + break; 969 | + 970 | + // Teleportation 971 | + case GOSSIP_TELEPORT: 972 | + player->CLOSE_GOSSIP_MENU(); 973 | + if(player->HasAura(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS,0)) { 974 | + creature->CastSpell(player,38588,false); // Healing effect 975 | + player->RemoveAurasDueToSpell(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS); 976 | + } 977 | + 978 | + ActionTeleport(player, creature, param); 979 | + break; 980 | + } 981 | + return true; 982 | +} 983 | +}; 984 | + 985 | +void AddSC_npc_teleport() 986 | +{ 987 | + new npc_teleport; 988 | +} 989 | -- 990 | 1.7.3.1.msysgit.0 991 | 992 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thedevnull/thedevnull-patches/903606c3c61ae92f78276c1c5b5afa2c480518be/README --------------------------------------------------------------------------------