Informatikai Barkács Fórum

WORLD OF WARCRAFT SZERVER => Core/Mag Modifikációk => A témát indította: Action Dátum 2010 július 19, 10:03:19 DÉLUTÁN

Cím: Vendor valamennyi szint felett[TC2]
Írta: Action Dátum 2010 július 19, 10:03:19 DÉLUTÁN
Üdv mindenkinek!

Csak úgy alapjáraton kezdtem el foglalkozni a problémával hátha összejön belőle valami. Végül sikerült is egy megoldásnak mondható valami. Ami nekem annyira megtetszett mikor sikerült működésre bírnom, hogy most égek a vágytól, hogy megoszthassam valakivel.
Előrebocsátom nem sok leírást készítettem még, de igyekszem érthetően írni.
Nem is szaporítom tovább a szót. Jöjjön a leírás.

Felhasznált emulátor:
TrinityCore2 8307

Felhasznált adatbázis:
TDB_333.9.30 8307

Módosított táblák:
npc_vendor
trinity_string

Módosított file-ok:
Creature.h
  struct VendorItem
  struct VendorItemData
ObjectMgr.cpp
  ObjectMgr::LoadReferenceVendor
  ObjectMgr::LoadVendors
  ObjectMgr::AddVendorItem
ObjectMgr.h
  AddVendorItem
ItemHandler.cpp
  WorldSession::SendListInventory
Level2.cpp
  ChatHandler::HandleNpcAddVendorItemCommand
GameEventMgr.cpp
  GameEventMgr::UpdateEventNPCVendor


Az npc_vendor táblát kell kibővíteni a megfelelő mezőkkel. Jelen esetben én a minlvl, maxlvl mezőket használtam.
Ezekkel ugye el lehet azt érni, hogy egy bizonyos szintig ne jelenjen meg az item és egy bizonyos szint után már ne legyen látható.

használt SQL parancs:
Idéz
ALTER TABLE npc_vendor
ADD minlvl INT(3) NOT NULL DEFAULT 0,
ADD maxlvl INT(3) NOT NULL DEFAULT 0;


A core-ban is módosítani kell a vendor struktúráját.
Ehhez a Creature.h ban lévő VendorItem és VendorItemData struktúrákat kell módosítnani.

ezt:
Idéz
VendorItem(uint32 _item, int32 _maxcount, uint32 _incrtime, uint32 _ExtendedCost)
   : item(_item), maxcount(_maxcount), incrtime(_incrtime), ExtendedCost(_ExtendedCost) {}

erre:
Idéz
VendorItem(uint32 _item, int32 _maxcount, uint32 _incrtime, uint32 _ExtendedCost, int32 _minlvl, int32 _maxlvl)
   : item(_item), maxcount(_maxcount), incrtime(_incrtime), ExtendedCost(_ExtendedCost), minlvl(_minlvl), maxlvl(_maxlvl) {}
ez után:
Idéz
uint32 ExtendedCost;

ezt:
Idéz
int32 minlvl;
int32 maxlvl;
VendorItem-nél csak definiálni kell neki az új változókat és betenni őket a konstruktorba.
A VendorItemData-ba pedig csak az AddItem függvényt kell kiegészíteni.

ezt:
Idéz
void AddItem(uint32 item, int32 maxcount, uint32 ptime, uint32 ExtendedCost)
{
   m_items.push_back(new VendorItem(item, maxcount, ptime, ExtendedCost));
}
Erre:
Idéz
void AddItem(uint32 item, int32 maxcount, uint32 ptime, uint32 ExtendedCost, int32 minlvl, int32 maxlvl)
{
   m_items.push_back(new VendorItem(item, maxcount, ptime, ExtendedCost, minlvl, maxlvl));
}

Következő lépésben a vendorok beolvasását kell módosítani, hogy adatbázisból a mi mezőinket is beolvassa.
Ezeket a ObjectMgr.cpp file-ban találjuk.
Az ObjectMgr::LoadReferenceVendor és az ObjectMgr::LoadVendors.
Mindkét függvényt 3 helyen kell módosítani.
1. Az SQL kérést kell kibővíteni az új mezőkkel.

ezt:
Idéz
QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT item, maxcount, incrtime, ExtendedCost FROM npc_vendor WHERE entry='%d' ORDER BY slot ASC", item);
erre:
Idéz
QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT item, maxcount, incrtime, ExtendedCost, minlvl, maxlvl FROM npc_vendor WHERE entry='%d' ORDER BY slot ASC", item);
2. Egy változóba lekérni őket.

ez után:
Idéz
uint32 ExtendedCost = fields[3].GetUInt32();
ezt:
Idéz
int32 minlvl = fields[4].GetInt32();
int32 maxlvl = fields[5].GetInt32();
3. Majd a listához hozzáadni. Itt használjuk a VendorItemData-ban átírt AddItem függvényt.

ezt:
Idéz
vList.AddItem(item_id,maxcount,incrtime,ExtendedCost);
erre:
Idéz
vList.AddItem(item_id, maxcount, incrtime, ExtendedCost, minlvl, maxlvl);

Most az ItemHandler.cpp WorldSession::SendListInventory függvényére lesz szükségünk.
Ez küldi el a játékosnak a vendornál lévő tárgyak listáját. Itt csak annyi a dolgunk, hogy hozzáadjuk a mi feltételeinket is a többi mögé.
Így csak az fogja látni az árult tárgyakat, aki a megadott szintek között van. Ha valamelyik paraméter 0 azt nem veszi figyelembe.

pl.: ha csak minlvl-t adunk meg akkor egy bizonyos szint alatt nem látható a tárgy.
ha csak maxlvl-t akkor egy bizonyos szint után már nem vásárolható.
A feltétel végén pedig ellenőrizzük, hogy a játékos gm on-ban van-e. Ilyenkor megkapja a teljes listát. Gm-ként így ellenőrizhető, hogy minden tárgyat árul-e.
gm off-ban pedig szintek addolásával ellenőrizhető, hogy adott szinten tényleg csak azok a tárgyak vásárolhatók, amiket megadott.

ez után:
Idéz
if (pProto->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && _player->GetTeam() == ALLIANCE || pProto->Flags2 == ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && _player->GetTeam() == HORDE && !_player->isGameMaster())
   continue;
ezt:
Idéz
if(crItem->minlvl != 0 && _player->getLevel() < crItem->minlvl && !_player->isGameMaster())
   continue;
if(crItem->maxlvl != 0 && _player->getLevel() > crItem->maxlvl && !_player->isGameMaster())
   continue;
Utolsó lépésként módosítani kell még az 'npc additem' parancsot is.
Első ránézésre ez a lépés sem hagyható ki.
Ugyanis ez a függvény is használja az AddItem függvényt amit ugye már módosítottunk.
Hogy helyesen működjön a ObjectMgr.cpp file ObjectMgr::AddVendorItem függvényét kell átalakítani.
Itt sincs különösebb nehézség. Csak a paraméterlistákat kell átírni. Na meg az SQL utasítást a végén.

ezt:
Idéz
void ObjectMgr::AddVendorItem(uint32 entry,uint32 item, int32 maxcount, uint32 incrtime, uint32 extendedcost, bool savetodb)
{
   VendorItemData& vList = m_mCacheVendorItemMap[entry];
   vList.AddItem(item,maxcount,incrtime,extendedcost);

   if (savetodb) WorldDatabase.PExecuteLog("INSERT INTO npc_vendor (entry,item,maxcount,incrtime,extendedcost) VALUES('%u','%u','%u','%u','%u')", entry, item, maxcount,incrtime,extendedcost);
}

erre:
Idéz
void ObjectMgr::AddVendorItem(uint32 entry,uint32 item, int32 maxcount, uint32 incrtime, uint32 extendedcost, int32 minlvl, int32 maxlvl, bool savetodb)
{
   VendorItemData& vList = m_mCacheVendorItemMap[entry];

   vList.AddItem(item, maxcount, incrtime, extendedcost, minlvl, maxlvl);
   if (savetodb) WorldDatabase.PExecuteLog("INSERT INTO npc_vendor (entry, item, maxcount,incrtime, extendedcost, minlvl, maxlvl) VALUES('%u','%u','%u','%u','%u','%u','%u')",entry, item, maxcount, incrtime, extendedcost, minlvl, maxlvl);
}
Ne feledkezzünk meg az ObjectMgr.h-ban a függvény prototípusáról sem.

ezt:
Idéz
void AddVendorItem(uint32 entry,uint32 item, int32 maxcount, uint32 incrtime, uint32 ExtendedCost, bool savetodb = true); // for event
erre:
Idéz
void AddVendorItem(uint32 entry,uint32 item, int32 maxcount, uint32 incrtime, uint32 ExtendedCost, int32 minlvl, int32 maxlvl, bool savetodb = true); // for event
Módosítani kell még a Level2.cpp, hatHandler::HandleNpcAddVendorItemCommand függvényét.
Ez azért kell, hogy az 'npc additem' parancs felismerje a mi paraméterinket is.
Definiálni kell az általunk használt változókat.

ez után:
Idéz
char* fextendedcost = strtok(NULL, " ");                //add ExtendedCost, default: 0
uint32 extendedcost = fextendedcost ? atol(fextendedcost) : 0;
ezt:
Idéz
char* fminlvl = strtok(NULL, " ");         //add minlvl, default: 0
uint32 minlvl = fminlvl ? atol(fminlvl) : 0;
char* fmaxlvl = strtok(NULL, " ");         //add maxlvl, default: 0
uint32 maxlvl = fmaxlvl ? atol(fmaxlvl) : 0;

Majd átadni az objmgr.AddVendorItem és PSendSysMessage függvényeknek.

ezt:
Idéz
objmgr.AddVendorItem(vendor_entry,itemId,maxcount,incrtime,extendedcost);
erre:
Idéz
objmgr.AddVendorItem(vendor_entry, itemId, maxcount, incrtime, extendedcost, minlvl, maxlvl);
ezt:
Idéz
PSendSysMessage(LANG_ITEM_ADDED_TO_LIST,itemId,pProto->Name1,maxcount,incrtime,extendedcost);
erre:
Idéz
PSendSysMessage(LANG_ITEM_ADDED_TO_LIST, itemId, pProto->Name1, maxcount, incrtime, extendedcost, minlvl, maxlvl);

Értelemszerűen az objmgr.AddVendorItem hozzáadja az adatbázishoz.
A PSendSysMessage pedig egy visszajelzést a parancs használójának.
Ami még nem teljesen tökéletes, mert a saját paramétereinkről nem ad visszajelzést.
Ehhez a trinity_string 206-os entry-jének tartalmát kell átírni.

használt SQL parancs:
Idéz
UPDATE trinity_string SET content_default = "Item '%i' '%s' added to list with maxcount '%i' and incrtime '%i' and extendedcost '%i' and minlvl '%i' and maxlvl '%i'" WHERE entry = 206;
És most már tényleg csak egy dolog van hátra .
Event vendoroknál előfordulhat, hogy úgy kap a vendor árut, hogy az nem kerül be adatbázisba. Erre szolgál az objmgr.AddVendorItem függvény savetodb változója.
És mivel az eventvendor is ezt a függvényt használja neki is meg kell adni az új paraméterlistát.
Ezt a GameEventMgr.cpp, GameEventMgr::UpdateEventNPCVendor függvényében találjuk.

ezt:
Idéz
objmgr.AddVendorItem(itr->entry, itr->item, itr->maxcount, itr->incrtime, itr->ExtendedCost, false);
erre:
Idéz
objmgr.AddVendorItem(itr->entry, itr->item, itr->maxcount, itr->incrtime, itr->ExtendedCost, 0, 0, false);
Végre kimondhatjuk, hogy 'Kész'. Most már csak a gépnek kell elvégeznie a rabszolgamunkát.
Gondolom felesleges, de azért mondom, hogy újraforgatás és szerver restart azért kell hozzá, hogy működjön

Természetesen itt még tovább lehetne vinni a dolgot, hogy ne fixen legyenek ott azok a nullák az eventvendorban.
De azt hiszem az eredeti problémát ez is megoldja.
Aki meg szeretné, hogy eventes vendoroknál is beállítható legyen az ezek után szerintem már meg tudja oldani.
Ha mégsem és van rá igény szívesen továbbviszem a leírást.

Köszönöm azoknak, akik eljutottak a végére. Remélem hasznos lesz a leírás valakinek.
Építő jellegű kritikát szívesen fogadok a leírással kapcsolatban.
Ha valaki elakadna, annak segítek ha kell. De most szólok, hogy nem vagyok éjjel-nappal online .

És végre én is kimondhatom 'Végeztem a leírással' .


A leírást készítette Kagebunshin !
Cím: Re:Vendor valamennyi szint felett[TC2]
Írta: Bluerák Dátum 2010 július 20, 11:08:44 DÉLUTÁN
Ez nagyon szép leírás lett egyébként  :D
Ajánlom mindenkinek, hogy használja, főleg, ahol custom vendor van létrehozva  :)
Még sok-sok ehhez hasonlo tutorial kéne  ;D
Cím: Re:Vendor valamennyi szint felett[TC2]
Írta: coker Dátum 2010 augusztus 02, 12:41:58 DÉLUTÁN
Sziasztok..lenne egy kérdésem, mindent megcsináltam ami levan írva, leforgatással semmi baj se volt nincs hiba, de mikor elinditom a TrinityCore.exe-et akkkor megáll a "loading Vendors"-nál, és aztán bezáródik..mi lehet a probléma?:)
Cím: Re:Vendor valamennyi szint felett[TC2]
Írta: $0undX Dátum 2010 augusztus 02, 02:29:17 DÉLUTÁN
Hát ha csak ezzel van baj akkor mindenképp ebben a módosításban van a hiba, amúgy npc_vendor -ba benyomtad az sql-t?
Cím: Re:Vendor valamennyi szint felett[TC2]
Írta: coker Dátum 2010 augusztus 02, 03:22:15 DÉLUTÁN
be, persze :) azért nem értem mibaja, minden ami a leírásba van sql azt beraktam
Cím: Re:Vendor valamennyi szint felett[TC2]
Írta: $0undX Dátum 2010 augusztus 02, 05:56:18 DÉLUTÁN
ha bezáródik akkor minden bizonyára a server.log-ban meg tudod nézni mit írt ki utoljára, a log végét esetleg felraknád pastebin-re, és ide 1 linket kérnénk.  :)
Cím: Re:Vendor valamennyi szint felett[TC2]
Írta: coker Dátum 2010 augusztus 02, 06:07:17 DÉLUTÁN
ennyi va na log végén :s

2010-08-02 18:04:16 >> Loaded 3279 gossip_menu_option entries
2010-08-02 18:04:16 Loading Vendors...
Cím: Re:Vendor valamennyi szint felett[TC2]
Írta: ident Dátum 2010 augusztus 02, 07:49:42 DÉLUTÁN
Idézetet írta: coker Dátum 2010 augusztus 02, 06:07:17 DÉLUTÁN
ennyi va na log végén :s

2010-08-02 18:04:16 >> Loaded 3279 gossip_menu_option entries
2010-08-02 18:04:16 Loading Vendors...


Ez általában DB hiba, tedd újra a world adatbázisod.
Cím: Re:Vendor valamennyi szint felett[TC2]
Írta: coker Dátum 2010 augusztus 02, 08:53:31 DÉLUTÁN
Ujraraktam, de mégmindig megál ott :S lehet elnéztem valamit a leírásba?:) xD
Cím: Re:Vendor valamennyi szint felett[TC2]
Írta: kagebunshin Dátum 2010 augusztus 03, 02:13:26 DÉLELŐTT
Hmmm, h
Cím: Re:Vendor valamennyi szint felett[TC2]
Írta: Skyne Dátum 2010 augusztus 03, 09:05:39 DÉLELŐTT
A leírás bővített formában megtalálható a Gnome-Lak DevBlogon, még egyszer köszönjük, és várjuk a további hasonlóakat ;) link:Item vásárlás csak megadott szint felett (http://skyne.gnome-lak.hu/index.php?option=com_content&view=article&id=7:item-vasarlas-csak-megadott-szint-felett&catid=1:scriptek&Itemid=2)
Cím: Re:Vendor valamennyi szint felett[TC2]
Írta: coker Dátum 2010 augusztus 04, 10:14:10 DÉLUTÁN
megy, ezer köszönet:)