Item/ExtendedCost

* display a "sells" entry for every combination of currencies the vendor accepts per item
 * display every cost combination in the quick infos on the item detail page
This commit is contained in:
Sarjuuk
2018-05-10 19:20:07 +02:00
parent 761da59ee9
commit 3bbd7f97da
4 changed files with 198 additions and 154 deletions

View File

@@ -17,6 +17,8 @@ abstract class BaseType
protected $queryBase = ''; protected $queryBase = '';
protected $queryOpts = []; protected $queryOpts = [];
private $itrStack = [];
public static $contribute = CONTRIBUTE_ANY; public static $contribute = CONTRIBUTE_ANY;
/* /*
@@ -287,7 +289,7 @@ abstract class BaseType
public function &iterate() public function &iterate()
{ {
$oldIdx = $this->id; $this->itrStack[] = $this->id;
// reset on __construct // reset on __construct
$this->reset(); $this->reset();
@@ -304,6 +306,7 @@ abstract class BaseType
// fforward to old index // fforward to old index
$this->reset(); $this->reset();
$oldIdx = array_pop($this->itrStack);
do do
{ {
if (key($this->templates) != $oldIdx) if (key($this->templates) != $oldIdx)
@@ -311,6 +314,7 @@ abstract class BaseType
$this->curTpl = current($this->templates); $this->curTpl = current($this->templates);
$this->id = key($this->templates); $this->id = key($this->templates);
next($this->templates);
break; break;
} }
while (next($this->templates)); while (next($this->templates));

View File

@@ -90,70 +90,83 @@ class ItemList extends BaseType
if (empty($this->vendors)) if (empty($this->vendors))
{ {
$itemz = DB::World()->select(' $itemz = [];
SELECT nv.item AS ARRAY_KEY1, nv.entry AS ARRAY_KEY2, 0 AS eventId, nv.maxcount, nv.extendedCost FROM npc_vendor nv WHERE {nv.entry IN (?a) AND} nv.item IN (?a) $xCostData = [];
$rawEntries = DB::World()->select('
SELECT nv.item, nv.entry, 0 AS eventId, nv.maxcount, nv.extendedCost FROM npc_vendor nv WHERE {nv.entry IN (?a) AND} nv.item IN (?a)
UNION UNION
SELECT genv.item AS ARRAY_KEY1, c.id AS ARRAY_KEY2, ge.eventEntry AS eventId, genv.maxcount, genv.extendedCost FROM game_event_npc_vendor genv LEFT JOIN game_event ge ON genv.eventEntry = ge.eventEntry JOIN creature c ON c.guid = genv.guid WHERE {c.id IN (?a) AND} genv.item IN (?a)', SELECT genv.item, c.id AS `entry`, ge.eventEntry AS eventId, genv.maxcount, genv.extendedCost FROM game_event_npc_vendor genv LEFT JOIN game_event ge ON genv.eventEntry = ge.eventEntry JOIN creature c ON c.guid = genv.guid WHERE {c.id IN (?a) AND} genv.item IN (?a)',
empty($filter[TYPE_NPC]) || !is_array($filter[TYPE_NPC]) ? DBSIMPLE_SKIP : $filter[TYPE_NPC], empty($filter[TYPE_NPC]) || !is_array($filter[TYPE_NPC]) ? DBSIMPLE_SKIP : $filter[TYPE_NPC],
array_keys($this->templates), array_keys($this->templates),
empty($filter[TYPE_NPC]) || !is_array($filter[TYPE_NPC]) ? DBSIMPLE_SKIP : $filter[TYPE_NPC], empty($filter[TYPE_NPC]) || !is_array($filter[TYPE_NPC]) ? DBSIMPLE_SKIP : $filter[TYPE_NPC],
array_keys($this->templates) array_keys($this->templates)
); );
$xCosts = []; foreach ($rawEntries as $costEntry)
foreach ($itemz as $i => $vendors) {
$xCosts = array_merge($xCosts, array_column($vendors, 'extendedCost')); if ($costEntry['extendedCost'])
$xCostData[] = $costEntry['extendedCost'];
if ($xCosts) if (!isset($itemz[$costEntry['item']][$costEntry['entry']]))
$xCosts = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM ?_itemextendedcost WHERE id IN (?a)', $xCosts); $itemz[$costEntry['item']][$costEntry['entry']] = [$costEntry];
else
$itemz[$costEntry['item']][$costEntry['entry']][] = $costEntry;
}
if ($xCostData)
$xCostData = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM ?_itemextendedcost WHERE id IN (?a)', $xCostData);
$cItems = []; $cItems = [];
foreach ($itemz as $k => $vendors) foreach ($itemz as $k => $vendors)
{ {
foreach ($vendors as $l => $vInfo) foreach ($vendors as $l => $vendor)
{ {
$costs = []; foreach ($vendor as $m => $vInfo)
if (!empty($xCosts[$vInfo['extendedCost']]))
$costs = $xCosts[$vInfo['extendedCost']];
$data = array(
'stock' => $vInfo['maxcount'] ?: -1,
'event' => $vInfo['eventId'],
'reqRating' => $costs ? $costs['reqPersonalRating'] : 0,
'reqBracket' => $costs ? $costs['reqArenaSlot'] : 0
);
// hardcode arena(103) & honor(104)
if (!empty($costs['reqArenaPoints']))
{ {
$data[-103] = $costs['reqArenaPoints']; $costs = [];
$this->jsGlobals[TYPE_CURRENCY][103] = 103; if (!empty($xCostData[$vInfo['extendedCost']]))
} $costs = $xCostData[$vInfo['extendedCost']];
if (!empty($costs['reqHonorPoints'])) $data = array(
{ 'stock' => $vInfo['maxcount'] ?: -1,
$data[-104] = $costs['reqHonorPoints']; 'event' => $vInfo['eventId'],
$this->jsGlobals[TYPE_CURRENCY][104] = 104; 'reqRating' => $costs ? $costs['reqPersonalRating'] : 0,
} 'reqBracket' => $costs ? $costs['reqArenaSlot'] : 0
);
for ($i = 1; $i < 6; $i++) // hardcode arena(103) & honor(104)
{ if (!empty($costs['reqArenaPoints']))
if (!empty($costs['reqItemId'.$i]) && $costs['itemCount'.$i] > 0)
{ {
$data[$costs['reqItemId'.$i]] = $costs['itemCount'.$i]; $data[-103] = $costs['reqArenaPoints'];
$cItems[] = $costs['reqItemId'.$i]; $this->jsGlobals[TYPE_CURRENCY][103] = 103;
} }
}
// no extended cost or additional gold required if (!empty($costs['reqHonorPoints']))
if (!$costs || $this->getField('flagsExtra') & 0x04) {
{ $data[-104] = $costs['reqHonorPoints'];
$this->getEntry($k); $this->jsGlobals[TYPE_CURRENCY][104] = 104;
if ($_ = $this->getField('buyPrice')) }
$data[0] = $_;
}
$vendors[$l] = $data; for ($i = 1; $i < 6; $i++)
{
if (!empty($costs['reqItemId'.$i]) && $costs['itemCount'.$i] > 0)
{
$data[$costs['reqItemId'.$i]] = $costs['itemCount'.$i];
$cItems[] = $costs['reqItemId'.$i];
}
}
// no extended cost or additional gold required
if (!$costs || $this->getField('flagsExtra') & 0x04)
{
$this->getEntry($k);
if ($_ = $this->getField('buyPrice'))
$data[0] = $_;
}
$vendor[$m] = $data;
}
$vendors[$l] = $vendor;
} }
$itemz[$k] = $vendors; $itemz[$k] = $vendors;
@@ -167,33 +180,37 @@ class ItemList extends BaseType
foreach ($jsData as $k => $v) foreach ($jsData as $k => $v)
$this->jsGlobals[$type][$k] = $v; $this->jsGlobals[$type][$k] = $v;
foreach ($itemz as $id => $vendors) foreach ($itemz as $itemId => $vendors)
{ {
foreach ($vendors as $l => $costs) foreach ($vendors as $npcId => $costData)
{ {
foreach ($costs as $k => $v) foreach ($costData as $itr => $cost)
{ {
if (in_array($k, $cItems)) foreach ($cost as $k => $v)
{ {
$found = false; if (in_array($k, $cItems))
foreach ($moneyItems->iterate() as $__)
{ {
if ($moneyItems->getField('itemId') == $k) $found = false;
foreach ($moneyItems->iterate() as $__)
{ {
unset($costs[$k]); if ($moneyItems->getField('itemId') == $k)
$costs[-$moneyItems->id] = $v; {
$found = true; unset($cost[$k]);
break; $cost[-$moneyItems->id] = $v;
$found = true;
break;
}
} }
}
if (!$found) if (!$found)
$this->jsGlobals[TYPE_ITEM][$k] = $k; $this->jsGlobals[TYPE_ITEM][$k] = $k;
}
} }
$costData[$itr] = $cost;
} }
$vendors[$l] = $costs; $vendors[$npcId] = $costData;
} }
$itemz[$id] = $vendors; $itemz[$itemId] = $vendors;
} }
} }
@@ -209,28 +226,31 @@ class ItemList extends BaseType
foreach ($result as $itemId => &$data) foreach ($result as $itemId => &$data)
{ {
$reqRating = []; $reqRating = [];
foreach ($data as $npcId => $costs) foreach ($data as $npcId => $entries)
{ {
if ($tok || $cur) // bought with specific token or currency foreach ($entries as $costs)
{ {
$valid = false; if ($tok || $cur) // bought with specific token or currency
foreach ($costs as $k => $qty)
{ {
if ((!$tok || $k == $tok) && (!$cur || $k == -$cur)) $valid = false;
foreach ($costs as $k => $qty)
{ {
$valid = true; if ((!$tok || $k == $tok) && (!$cur || $k == -$cur))
break; {
$valid = true;
break;
}
} }
if (!$valid)
unset($data[$npcId]);
} }
if (!$valid) // reqRating ins't really a cost .. so pass it by ref instead of return
unset($data[$npcId]); // use highest total value
if (isset($data[$npcId]) && $costs['reqRating'] && (!$reqRating || $reqRating[0] < $costs['reqRating']))
$reqRating = [$costs['reqRating'], $costs['reqBracket']];
} }
// reqRating ins't really a cost .. so pass it by ref instead of return
// use highest total value
if (isset($data[$npcId]) && $costs['reqRating'] && (!$reqRating || $reqRating[0] < $costs['reqRating']))
$reqRating = [$costs['reqRating'], $costs['reqBracket']];
} }
if ($reqRating) if ($reqRating)
@@ -266,6 +286,7 @@ class ItemList extends BaseType
if ($addInfoMask & ITEMINFO_VENDOR) if ($addInfoMask & ITEMINFO_VENDOR)
$extCosts = $this->getExtendedCost($miscData); $extCosts = $this->getExtendedCost($miscData);
$extCostOther = [];
foreach ($this->iterate() as $__) foreach ($this->iterate() as $__)
{ {
foreach ($this->json[$this->id] as $k => $v) foreach ($this->json[$this->id] as $k => $v)
@@ -300,42 +321,51 @@ class ItemList extends BaseType
if ($addInfoMask & ITEMINFO_VENDOR) if ($addInfoMask & ITEMINFO_VENDOR)
{ {
// just use the first results // just use the first results
// todo (med): dont use first result; search for the right one // todo (med): dont use first vendor; search for the right one
if (!empty($extCosts[$this->id])) if (!empty($extCosts[$this->id]))
{ {
$cost = reset($extCosts[$this->id]); $cost = reset($extCosts[$this->id]);
$currency = []; foreach ($cost as $itr => $entries)
$tokens = [];
foreach ($cost as $k => $qty)
{ {
if (is_string($k)) $currency = [];
continue; $tokens = [];
$costArr = [];
if ($k > 0) foreach ($entries as $k => $qty)
$tokens[] = [$k, $qty]; {
else if ($k < 0) if (is_string($k))
$currency[] = [-$k, $qty]; continue;
if ($k > 0)
$tokens[] = [$k, $qty];
else if ($k < 0)
$currency[] = [-$k, $qty];
}
$costArr['stock'] = $entries['stock'];// display as column in lv
$costArr['avail'] = $entries['stock'];// display as number on icon
$costArr['cost'] = [empty($entries[0]) ? 0 : $entries[0]];
if ($entries['event'])
{
$this->jsGlobals[TYPE_WORLDEVENT][$entries['event']] = $entries['event'];
$costArr['condition'][0][$this->id][] = [[CND_ACTIVE_EVENT, $entries['event']]];
}
if ($currency || $tokens) // fill idx:3 if required
$costArr['cost'][] = $currency;
if ($tokens)
$costArr['cost'][] = $tokens;
if (!empty($entries['reqRating']))
$costArr['reqarenartng'] = $entries['reqRating'];
if ($itr > 0)
$extCostOther[$this->id][] = $costArr;
else
$data[$this->id] = array_merge($data[$this->id], $costArr);
} }
$data[$this->id]['stock'] = $cost['stock']; // display as column in lv
$data[$this->id]['avail'] = $cost['stock']; // display as number on icon
$data[$this->id]['cost'] = [empty($cost[0]) ? 0 : $cost[0]];
if ($cost['event'])
{
$this->jsGlobals[TYPE_WORLDEVENT][$cost['event']] = $cost['event'];
$row['condition'][0][$this->id][] = [[CND_ACTIVE_EVENT, $cost['event']]];
}
if ($currency || $tokens) // fill idx:3 if required
$data[$this->id]['cost'][] = $currency;
if ($tokens)
$data[$this->id]['cost'][] = $tokens;
if (!empty($cost['reqRating']))
$data[$this->id]['reqarenartng'] = $cost['reqRating'];
} }
if ($x = $this->curTpl['buyPrice']) if ($x = $this->curTpl['buyPrice'])
@@ -397,6 +427,10 @@ class ItemList extends BaseType
$data[$this->id]['cooldown'] = $this->curTpl['cooldown'] / 1000; $data[$this->id]['cooldown'] = $this->curTpl['cooldown'] / 1000;
} }
foreach ($extCostOther as $itemId => $duplicates)
foreach ($duplicates as $d)
$data[] = array_merge($data[$itemId], $d); // we dont really use keys on data, but this may cause errors in future
/* even more complicated crap /* even more complicated crap
modelviewer {type:X, displayid:Y, slot:z} .. not sure, when to set modelviewer {type:X, displayid:Y, slot:z} .. not sure, when to set
*/ */

View File

@@ -109,7 +109,8 @@ class CurrencyPage extends GenericPage
{ {
$items = []; $items = [];
$tokens = []; $tokens = [];
foreach ($vendors[$k] as $id => $qty) // note: can only display one entry per row, so only use first entry of each vendor
foreach ($vendors[$k][0] as $id => $qty)
{ {
if (is_string($id)) if (is_string($id))
continue; continue;
@@ -120,16 +121,16 @@ class CurrencyPage extends GenericPage
$items[] = [-$id, $qty]; $items[] = [-$id, $qty];
} }
if ($vendors[$k]['event']) if ($vendors[$k][0]['event'])
{ {
if (count($extraCols) == 3) // not already pushed if (count($extraCols) == 3) // not already pushed
$extraCols[] = '$Listview.extraCols.condition'; $extraCols[] = '$Listview.extraCols.condition';
$this->extendGlobalIds(TYPE_WORLDEVENT, $vendors[$k]['event']); $this->extendGlobalIds(TYPE_WORLDEVENT, $vendors[$k][0]['event']);
$row['condition'][0][$this->typeId][] = [[CND_ACTIVE_EVENT, $vendors[$k]['event']]]; $row['condition'][0][$this->typeId][] = [[CND_ACTIVE_EVENT, $vendors[$k][0]['event']]];
} }
$row['stock'] = $vendors[$k]['stock']; $row['stock'] = $vendors[$k][0]['stock'];
$row['stack'] = $itemObj->getField('buyCount'); $row['stack'] = $itemObj->getField('buyCount');
$row['cost'] = array( $row['cost'] = array(
$itemObj->getField('buyPrice'), $itemObj->getField('buyPrice'),

View File

@@ -185,45 +185,54 @@ class ItemPage extends genericPage
$each = $this->subject->getField('stackable') > 1 ? '[color=q0] ('.Lang::item('each').')[/color]' : null; $each = $this->subject->getField('stackable') > 1 ? '[color=q0] ('.Lang::item('each').')[/color]' : null;
$handled = []; $handled = [];
$costList = []; $costList = [];
foreach ($vendors as $npcId => $data) foreach ($vendors as $npcId => $entries)
{ {
$tokens = []; foreach ($entries as $data)
$currency = [];
if (!is_array($data))
continue;
foreach ($data as $c => $qty)
{ {
if (is_string($c)) $tokens = [];
{ $currency = [];
unset($data[$c]); // unset miscData to prevent having two vendors /w the same cost being cached, because of different stock or rating-requirements
if (!is_array($data))
continue; continue;
foreach ($data as $c => $qty)
{
if (is_string($c))
{
unset($data[$c]); // unset miscData to prevent having two vendors /w the same cost being cached, because of different stock or rating-requirements
continue;
}
if ($c < 0) // currency items (and honor or arena)
{
$currency[] = -$c.','.$qty;
$this->extendGlobalIds(TYPE_CURRENCY, -$c);
}
else if ($c > 0) // plain items (item1,count1,item2,count2,...)
{
$tokens[$c] = $c.','.$qty;
$this->extendGlobalIds(TYPE_ITEM, $c);
}
} }
if ($c < 0) // currency items (and honor or arena) // display every cost-combination only once
$currency[] = -$c.','.$qty; if (in_array(md5(serialize($data)), $handled))
else if ($c > 0) // plain items (item1,count1,item2,count2,...) continue;
$tokens[$c] = $c.','.$qty;
$handled[] = md5(serialize($data));
$cost = isset($data[0]) ? '[money='.$data[0] : '[money';
if ($tokens)
$cost .= ' items='.implode(',', $tokens);
if ($currency)
$cost .= ' currency='.implode(',', $currency);
$cost .= ']';
$costList[] = $cost;
} }
// display every cost-combination only once
if (in_array(md5(serialize($data)), $handled))
continue;
$handled[] = md5(serialize($data));
$cost = isset($data[0]) ? '[money='.$data[0] : '[money';
if ($tokens)
$cost .= ' items='.implode(',', $tokens);
if ($currency)
$cost .= ' currency='.implode(',', $currency);
$cost .= ']';
$costList[] = $cost;
} }
if (count($costList) == 1) if (count($costList) == 1)
@@ -760,7 +769,9 @@ class ItemPage extends genericPage
{ {
$currency = []; $currency = [];
$tokens = []; $tokens = [];
foreach ($vendors[$k] as $id => $qty)
// note: can only display one entry per row, so only use first entry of each vendor
foreach ($vendors[$k][0] as $id => $qty)
{ {
if (is_string($id)) if (is_string($id))
continue; continue;
@@ -771,16 +782,10 @@ class ItemPage extends genericPage
$currency[] = [-$id, $qty]; $currency[] = [-$id, $qty];
} }
if ($currency) $row['stock'] = $vendors[$k][0]['stock'];
$this->extendGlobalIds(TYPE_CURRENCY, array_column($currency, 0)); $row['cost'] = [empty($vendors[$k][0][0]) ? 0 : $vendors[$k][0][0]];
if ($tokens) if ($e = $vendors[$k][0]['event'])
$this->extendGlobalIds(TYPE_ITEM, array_column($tokens, 0));
$row['stock'] = $vendors[$k]['stock'];
$row['cost'] = [empty($vendors[$k][0]) ? 0 : $vendors[$k][0]];
if ($e = $vendors[$k]['event'])
{ {
if (count($extraCols) == 3) if (count($extraCols) == 3)
$extraCols[] = '$Listview.extraCols.condition'; $extraCols[] = '$Listview.extraCols.condition';