Teleportační NPC (ScriptDev2)
Z WoWResource Wiki
Teleportační NPC slouží k portování hráčů na administrátorem zvolená místa, tento skript pracuje s nastavením v databázi a je ho možné použít pro několik různých teleportačních NPC.
Popis tabulky
- entry - Entry NPC ke kterému záznam přísluší
- icon - id ikony, která se zobrazí na začátku řádku ve výpisu voleb
- text - popisek položky
- mid (sender) - slouží k identifikaci menu, po zavolání GossipHello se standardně otevře menu s MID = 1. Ostatní MID v rozsahu 2 - 999 lze otevřít přes jinou položku.
- id (action) - slouží jako identifikátor čísla portu, pokud je id >= 1000 tak při kliknutí na tuto položku se provede portnutí na dané souřadnice, pokud je nižší otevře se další menu, které má MID hodnotu aktuálního id. Je nutné udržovat entry - mid - id unikátní!
- map,x,y,z,o - cílové souřadnice
- orderbyme - podle této položky se řadí výpis položek (nižší číslo je výše)
- reqmoney - počet peněz (v bronzácích) potřebných k portnutí (tuto volbu nelze nastavit u otevření submenu (id < 1000))
- reqlevel - potřebný level pro portnutí (tuto volbu nelze nastavit u otevření submenu (id < 1000))
e, text mid id pos orderbyme // hlavní menu (mid/1) 10, Port A, 1, 1000, 0, 0, 0, 500, 0, 0 10, Submenu A, 1, 2, 0, 0, 0, 0, 0, 1 // menu mid/2 10, SA Port B, 2, 1001, 1, 500, 500, 1500, 0, 0 10, SA Port A, 2, 1000, 1, 0, 0, 1500, 0, 1 10, Return..., 2, 1, 0, 0, 0, 0, 0, 999
Po promluvení s npc se zobrazí položky Port A a Submenu A. Položka Submenu A způsobí vyvolání dalšího menu, kde mid = 2
SQL tabulka
Tabulku je nutné vytvořit v databázi ScriptDev2!
CREATE TABLE `teleport` ( `entry` int(10) unsigned default NULL, `icon` int(10) unsigned default NULL, `text` tinytext collate utf8_bin, `mid` int(10) unsigned default '1', `id` int(10) unsigned default '1000', `map` int(10) unsigned default NULL, `x` float default NULL, `y` float default NULL, `z` float default NULL, `o` float default NULL, `orderbyme` int(10) unsigned default NULL, `reqmoney` int(10) unsigned default NULL, `reqlevel` int(10) unsigned default NULL, KEY `entry` (`entry`), KEY `mid` (`mid`,`id`), KEY `orderbyme` (`orderbyme`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC
Zdrojový kód skriptu
#include "precompiled.h" // pch #include "Database/DatabaseMysql.h" // db extern DatabaseMysql ScriptDev2DB; // db // action < DBTELEPORT_SENDER_SUBMENU - otevri submenu s MID = action #define DBTELEPORT_SENDER_SUBMENU 999 // pri GossipHello je zobrazen vypis s mid = DBTELEPORT_SENDER_MAIN #define DBTELEPORT_SENDER_MAIN 1 typedef struct _substruct { uint32 id; uint8 icon; std::string text; uint32 map; float x,y,z,o; uint32 ordererbyme; uint32 reqmoney, reqlevel; } substruct; //id, detaily typedef HM_NAMESPACE::hash_map<uint32, substruct> subvector; // mid, id kolekce typedef HM_NAMESPACE::hash_map<uint32, subvector> subentry; // entry, mid kolekce typedef HM_NAMESPACE::hash_map<uint32, subentry> portmap; portmap TeleportMap; typedef std::vector<substruct*> sortvector; // stuktura pro sorting struct sorter { bool operator() (substruct* a, substruct* b) { return a->ordererbyme < b->ordererbyme; } }; // vypsani seznamu dle entry, mid void doGossipTeleport(uint32 entry, uint32 mid, Player* player) { portmap::iterator ita = TeleportMap.find(entry); if (ita == TeleportMap.end()) return; subentry::iterator itb = ita->second.find(mid); if (itb == ita->second.end()) return; sortvector sorted; for(subvector::iterator itc = itb->second.begin(); itc != itb->second.end(); itc++) { sorted.push_back(&(itc->second)); } std::sort(sorted.begin(), sorted.end(), sorter()); for(sortvector::iterator itd = sorted.begin(); itd != sorted.end(); itd++) { // icon, text, mid, id player->ADD_GOSSIP_ITEM( (*itd)->icon, (*itd)->text.c_str(), mid, (*itd)->id ); } } bool GossipHello_npc_dbteleport(Player *player, Creature *_Creature) { // prazdna hashmapa v pameti, pokus se nacist data z db if (TeleportMap.empty()) { QueryResult* result = ScriptDev2DB.Query("SELECT entry, mid, id, icon, text, map, x, y, z, o, orderbyme, reqmoney, reqlevel FROM teleport"); if (!result) { _Creature->Yell("Huh! Data chybi...", 0, player->GetGUID()); return false; } do { Field* f = result->Fetch(); substruct s; s.id = f[2].GetUInt32(); s.icon = f[3].GetUInt8(); s.text = f[4].GetCppString(); s.map = f[5].GetUInt32(); s.x = f[6].GetFloat(); s.y = f[7].GetFloat(); s.z = f[8].GetFloat(); s.o = f[9].GetFloat(); s.ordererbyme = f[10].GetUInt32(); s.reqmoney = f[11].GetUInt32(); s.reqlevel = f[12].GetUInt32(); TeleportMap[ f[0].GetUInt32() ][ f[1].GetUInt32() ][ f[2].GetUInt32() ] = s; } while(result->NextRow()); delete result; } // generuj hlavni menu uint32 e = _Creature->GetCreatureInfo()->Entry; doGossipTeleport(e, DBTELEPORT_SENDER_MAIN, player); player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); return true; } bool GossipSelect_npc_dbteleport(Player *player, Creature *_Creature, uint32 sender, uint32 action ) { uint32 e = _Creature->GetCreatureInfo()->Entry; // pokud action je mensi nez DBTELEPORT_SENDER_SUBMENU vypis submenu if (action < DBTELEPORT_SENDER_SUBMENU) { doGossipTeleport(e, action, player); player->SEND_GOSSIP_MENU(_Creature->GetNpcTextId(), _Creature->GetGUID()); return true; } else { // test combat rezimu if (player->isInCombat()) { _Creature->Yell("Nesmis bojovat!", 0, player->GetGUID()); player->CLOSE_GOSSIP_MENU(); return true; } portmap::iterator ita = TeleportMap.find(e); if (ita == TeleportMap.end()) return true; subentry::iterator itb = ita->second.find(sender); if (itb == ita->second.end()) return true; subvector::iterator itc = itb->second.find(action); if (itc == itb->second.end()) return true; // test levelu if (itc->second.reqlevel) { if (player->getLevel() < itc->second.reqlevel) { std::stringstream st; st << "Nemas potrebny level ("; st << itc->second.reqlevel << ")"; _Creature->Whisper(player->GetGUID(), st.str().c_str()); player->CLOSE_GOSSIP_MENU(); return true; } } // test penez if (itc->second.reqmoney) { if (player->GetMoney() < itc->second.reqmoney) { uint32 g = itc->second.reqmoney/10000, s = itc->second.reqmoney/100%100, b = itc->second.reqmoney%100; std::stringstream st; st << "Nemas dost penez, je potreba "; st << g << "g "; st << s << "s "; st << b << "b"; _Creature->Whisper(player->GetGUID(), st.str().c_str()); player->CLOSE_GOSSIP_MENU(); return true; } player->ModifyMoney(-(int32)(itc->second.reqmoney)); } // teleportni player->TeleportTo( itc->second.map, itc->second.x, itc->second.y, itc->second.z, itc->second.o ); } return true; } void AddSC_npc_dbteleport() { Script *newscript; newscript = new Script; newscript->Name = "npc_dbteleport"; newscript->pGossipHello = &GossipHello_npc_dbteleport; newscript->pGossipSelect = &GossipSelect_npc_dbteleport; m_scripts[nrscripts++] = newscript; }