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.
Obsah |
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 - 998 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 < 999))
- reqlevel - potřebný level pro portnutí (tuto volbu nelze nastavit u otevření submenu (id < 999))
- reqguild - id guildy pro který je daný port určen, pokud není pro guildy ponechat hodnotu -1. Lze tímto skrýt celé submenu.
- reqteam - položka je dostupná jen pro určitou frakci, -1 - pro všechny, 0 - aliance, 1 - horda
- len doplnim gossip items cislo znazornuje obrazok ktory sa ukaze pri kliknuti na NPC viac -----> http://filebeam.com/65c37b34f2236d758846e0349bff48b9.jpg
Akce s ID 999 je rezervovaná pro reload tabulky (volba se zobrazuje gamemasterům v gm režimu)
Příklad se submenu
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,
`reqguild` int(10) default '-1',
`reqteam` int(10) default '-1',
PRIMARY KEY (`entry`,`mid`,`id`)
) 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/DatabaseEnv.h" // db
extern DatabaseType SD2Database; // 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;
int32 reqguild, reqteam;
} substruct;
//id, detaily
typedef UNORDERED_MAP<uint32, substruct> subvector;
// mid, id kolekce
typedef UNORDERED_MAP<uint32, subvector> subentry;
// entry, mid kolekce
typedef UNORDERED_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++)
{
if ((*itd)->reqguild != -1 && (*itd)->reqguild != player->GetGuildId())
continue; // guildovni porty jsou neviditelne ostatnim hracum
if ((*itd)->reqteam != -1 && (
((*itd)->reqteam == 0 && player->GetTeam() != ALLIANCE) ||
((*itd)->reqteam == 1 && player->GetTeam() != HORDE)
))
continue;
// icon, text, mid, id
player->ADD_GOSSIP_ITEM(
(*itd)->icon,
(*itd)->text.c_str(),
mid,
(*itd)->id
);
}
if (player->isGameMaster())
{
player->ADD_GOSSIP_ITEM(
0,
"[Reload Table]",
1,
DBTELEPORT_SENDER_SUBMENU
);
}
}
bool GossipHello_npc_dbteleport(Player *player, Creature *_Creature)
{
// prazdna hashmapa v pameti, pokus se nacist data z db
if (TeleportMap.empty())
{
QueryResult* result = SD2Database.Query("SELECT entry, mid, id, icon, text, map, x, y, z, o, orderbyme, reqmoney, reqlevel, reqguild, reqteam 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();
s.reqguild = f[13].GetInt32();
s.reqteam = f[14].GetInt32();
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
{
if (action == DBTELEPORT_SENDER_SUBMENU && player->isGameMaster())
{
TeleportMap.clear();
player->CLOSE_GOSSIP_MENU();
return true;
}
// 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 teamu
if (itc->second.reqteam != -1)
{
if (
(itc->second.reqteam == 0 && player->GetTeam() != ALLIANCE) ||
(itc->second.reqteam == 1 && player->GetTeam() != HORDE)
)
{
player->CLOSE_GOSSIP_MENU();
return true;
}
}
// test guildy
if (itc->second.reqguild != -1)
{
if (player->GetGuildId() != itc->second.reqguild)
{
player->CLOSE_GOSSIP_MENU();
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(st.str().c_str(), player->GetGUID());
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(st.str().c_str(), player->GetGUID());
player->CLOSE_GOSSIP_MENU();
return true;
}
player->ModifyMoney(-(int32)(itc->second.reqmoney));
}
player->CLOSE_GOSSIP_MENU();
// 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;
newscript->RegisterSelf();
}
