Vendor valamennyi szint felett[TC2]

Indította Action, 2010 július 19, 10:03:19 DÉLUTÁN

Előző téma - Következő téma

Action

Ü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 !
A WORD elszáll, az írás megmarad.

Bluerák

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

MacBook Pro 13' 2.26 GHZ, 4 GB RAM - White
iPhone 4S 16GB - Black
iPad 3 - Black

NEW PC:
Asus EAH6670 (1GB 128 bit)
AMD FX AM3+ (4x3.8GHZ)
ASRock 970 EXTREME3
8GB RAM

coker

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?:)

$0undX

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?

coker

be, persze :) azért nem értem mibaja, minden ami a leírásba van sql azt beraktam

$0undX

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.  :)

coker

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...

ident

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.
Fhatys, a sors által kirótt, elkerülhetetlen feladat szava.
http://eu.battle.net/wow/en/character/arathor/Ident/advanced

coker

Ujraraktam, de mégmindig megál ott :S lehet elnéztem valamit a leírásba?:) xD

kagebunshin

#9
Hmmm, h
"-Egy dolgot viszont elárulhatnál nekem. Ki találta ki, hogy a fák őreinek erejével szálljatok szembe velem, mert nem te ugye? Te nem tudtad!
-Nem... de azért vagyunk többen, hogy valaki tudja."

Skyne

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

coker


Powered by EzPortal