game/_incl_data/class/Location/Shop.php
2023-11-09 19:24:47 +02:00

565 lines
23 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Location;
use Core\Config;
use Core\Db;
use Delo;
use Enum\ShopId;
use Helper\Conversion;
use Item\Data\Bonuses;
use Item\Data\Properties;
use Item\Data\Requirements;
use Item\DataModel;
use Model\Constant\ShopOtdel;
use User;
class Shop
{
public ShopOtdel $shopOtdel;
private ShopId $shopId;
private array $wares;
private int $otdel;
private int $itemId;
private $buyer;
public function __construct(ShopId $shopId, int $otdel = 1)
{
$this->shopOtdel = new ShopOtdel();
$this->otdel = $otdel;
$this->itemId = intval($_GET['itmid']);
$this->shopId = $shopId;
$this->wares = Db::getRows('select * from
items_shop
left join items_main on items_shop.item_id = items_main.id
where sid = ? and r = ? and kolvo > 0 order by pos', [$shopId->value, $otdel]);
$this->buyer = new class {
public function getId(): int
{
return User::start()->info['id'];
}
public function getCredits(): float
{
return User::start()->info['money'];
}
public function getEuroCredits(): float
{
return User::start()->info['money2'];
}
public function getVoinstvennost(): int
{
return (int)User::start()->rep['rep3'] - (int)User::start()->rep['rep3_buy'];
}
public function getNextAct()
{
return User::start()->info['nextAct']; // что ты такое?!
}
public function isAdmin(): bool
{
return User::start()->isAdmin();
}
public function hasEnough(string $parameter, int $value): bool
{
return User::start()->stats[$parameter] >= $value;
}
public function hasExactly(string $parameter, int $value): bool
{
return User::start()->stats[$parameter] === $value;
}
public function hasEnoughCredits(int $itemprice): bool
{
return $this->getCredits() >= $itemprice;
}
public function hasEnoughEuroCredits(int $itemprice): bool
{
return $this->getEuroCredits() >= $itemprice;
}
public function hasEnoughVoinstvennost(int $itemprice): bool
{
return $this->getVoinstvennost() >= $itemprice;
}
};
if ($this->buyer->isAdmin()) {
if (isset($_GET['itmup'])) {
$this->itemUp();
} elseif (isset($_GET['itmdown'])) {
$this->itemDown();
}
}
if ($_SERVER["REQUEST_METHOD"] === "GET") {
if ($_GET['itmup']) {
$this->itemUp();
}
}
}
private function itemUp(): void
{
$this->changeItemPositionByInt(-1);
}
private function changeItemPositionByInt(int $modificator): void
{
Db::sql('update items_shop set pos = pos + ? where sid = ? and r = ? and item_id = ? and kolvo > 0',
[$modificator, $this->shopId->value, $this->otdel, $this->itemId]);
}
private function itemDown(): void
{
$this->changeItemPositionByInt(1);
}
public function printWares(): void
{
foreach ($this->wares as $pl) {
$data = new DataModel($pl['item_id']);
$itemRequirements = new Requirements($data->getRequirements());
$itemBonuses = new Bonuses($data->getBonuses());
$itemProperties = new Properties($data->getProperties());
$itemData = $data->getAll();
$pl['price_1'] = $this->calculateMinimalPrice($pl['price1'], $pl['price_1'], $pl['tr_items']);
$pl['price_2'] = $this->calculateMinimalPrice($pl['price2'], $pl['price_2'], $pl['tr_items']);
if (($pl['type'] >= 18 && $pl['type'] <= 24) || $pl['type'] == 26 || $pl['type'] == 27) {
$itemBonuses->addZonb();
}
$is2 = $this->name($pl['name'], $pl['renameadd'], $pl['item_id']);
if ($pl['massa'] > 0) {
$is2 .= '(Масса: ' . round($pl['massa'], 2) . ')';
}
$is2 .= $this->icons($itemRequirements->getAlign(), $itemData['art'], $itemData['sudba']);
$is2 .= $this->price($pl['price_1'], $pl['price_2'], $pl['price_4']);
if ($pl['kolvo'] < 50) {
$is2 .= ' &nbsp; &nbsp; <small style="color: crimson;">(остаток на складе: <strong>' . $pl['kolvo'] . '</strong>)</small>';
}
$is2 .= $this->needItems($pl['tr_items']);
//долговечность
if ($pl['iznos'] > 0) {
$pl['iznosMAXi'] = $pl['iznos'];
}
if ($pl['iznosMAXi'] > 0 && $pl['iznosMAXi'] < 1000) {
$is2 .= 'Долговечность: 0/' . $pl['iznosMAXi'] . '<br>';
}
if ($itemData['battleUseZd'] > 0) {
$is2 .= 'Задержка использования: ' . Conversion::secondsToTimeout($itemData['battleUseZd']) . '<br>';
}
$is2 = rtrim($is2, '<br>');
//Срок годности предмета
if ($itemData['srok'] > 0) {
$pl['srok'] = $itemData['srok'];
}
if ($pl['srok'] > 0) {
$is2 .= '<br>Срок годности: ' . Conversion::secondsToTimeout($pl['srok']);
}
if ($pl['magic_chance'] > 0) {
$is2 .= '<br>Вероятность срабатывания: ' . min([$pl['magic_chance'], 100]) . '%';
}
//Продолжительность действия магии:
if ((int)$pl['magic_inci'] > 0) {
$magicDuration = Db::getValue('select actiontime from eff_main where id2 = ?', [(int)$pl['magic_inci']]);
if ($magicDuration > 0) {
$is2 .= '<br>Продолжительность действия: ' . Conversion::secondsToTimeout($magicDuration);
}
}
if ($itemRequirements->get()) {
$is2 .= '<br><strong>Требуется минимальное:</strong>';
$is2 .= '<ul style="margin: 0; padding: 0 30px;">';
foreach ($itemRequirements->get() as $dataName => $dataInfo) {
if ($dataName === 'align' || $dataName === 'sex') {
$value = $dataName === 'align' ? intval($dataInfo['sysvalue']) : intval($dataInfo['value']);
$is2 .= $this->buyer->hasExactly($dataName, $value) ? '<li>' : '<li style="color: crimson; list-style-type: \'× \';">';
} else {
$is2 .= $this->buyer->hasEnough($dataName, intval($dataInfo['value'])) ? '<li>' : '<li style="color: crimson; list-style-type: \'× \';">';
}
$name = empty($dataInfo['name']) ? $dataName : $dataInfo['name'];
$is2 .= $name . ': ' . $dataInfo['value'];
//$is2 .= $dataName . ': ' . $dataInfo;
$is2 .= '</li>';
}
$is2 .= '</ul>';
}
if ($itemBonuses->get()) {
$is2 .= '<br><strong>Действует на:</strong>';
$is2 .= '<ul style="margin: 0; padding: 0 30px;">';
foreach ($itemBonuses->get() as $name => $value) {
if ($name === 'Броня') {
$is2 .= '<li>' . $name . ': ' . $value . '</li>';
continue;
}
$color = $value > 0 ? 'darkgreen' : 'darkred';
$is2 .= '<li style="color: ' . $color . '">' . $name . ': ' . ($value > 0 ? '+' . $value : $value) . '</li>';
}
$is2 .= '</ul>';
}
$is2 .= '<br><strong>Свойства предмета:</strong>';
foreach ($itemProperties->get() as $name => $value) {
$is2 .= '<br>' . $name . ': ' . $value;
}
if ($pl['2too'] === 1) {
$is2 .= '<br>Второе оружие';
}
if ($pl['2h'] === 1) {
$is2 .= '<br>Двуручное оружие';
}
if (!empty($itemData['imposed'])) {
if (empty($itemData['imposed_name'])) {
$itemData['imposed_name'] = 'Неизвестное зачарование';
}
$itemData['imposed_name'] = str_replace('Чары ', '', $itemData['imposed_name']);
$is2 .= '<br><span style="color: maroon;">Зачарование:</span> ' . $itemData['imposed_name'];
}
if (!empty($itemData['free_stats']) && $itemData['free_stats'] > 0) {
$is2 .= '<br> +' . $itemData['free_stats'] . ' дополнительных характеристик';
}
//Встроенная магия
if (!empty($pl['magic_inci']) || !empty($pl['magic_inc'])) {
if (empty($pl['magic_inc'])) {
$pl['magic_inc'] = $pl['magic_inci'];
}
$magic = Db::getRow('select id2, mname, minfo, img from eff_main where type1 = 12345 and id2 = ?', [$pl['magic_inc']]);
if ($magic['id2']) {
$is2 .= '<br><div>Встроено заклятие <img alt="' . $magic['mname'] . '" src="' . Config::img() . '/i/eff/' . $magic['img'] . '"> ' . $magic['minfo'] . '</div>';
}
}
$is2 .= $this->getcomplect($itemData['complect']);
if ($pl['max_text'] - $pl['use_text'] > 0) {
$is2 .= '<div>Количество символов: ' . ($pl['max_text'] - $pl['use_text']) . '</div>';
}
$is2 .= '<small>';
if (!empty($itemData['gravi'])) {
$is2 .= '<br><span style="font-size: x-large; font-family: consolas, monospace; background-color: darkseagreen; color: ghostwhite; padding: 0 5px;">' . $itemData['gravi'] . '</span>';
}
if (!empty($itemData['info'])) {
$pl['info'] .= '<br>' . $itemData['info'];
}
if (!empty($pl['info'])) {
$is2 .= '<div style="border: 2px dashed whitesmoke; background-color: silver;">' . $pl['info'] . '</div>';
}
if (isset($itemData['noremont'])) {
$is2 .= '<div style="color:brown;">Предмет не подлежит ремонту</div>';
}
if (isset($itemData['nosale'])) {
$is2 .= '<div style="color:brown;">Предмет нельзя продать</div>';
}
if (isset($itemData['nomodif'])) {
$is2 .= '<div style="color:brown;">Предмет нельзя улучшать</div>';
}
if (isset($itemData['nodelete'])) {
$is2 .= '<div style="color:brown;">Предмет нельзя выбросить</div>';
}
if (isset($itemData['sleep_moroz']) && $itemData['sleep_moroz'] > 0) {
$is2 .= '<div style="color:brown;">Предмет не портится во время сна</div>';
}
$is2 .= '</small>';
$is1 = $this->imageAndControls($pl['id'], $pl['type'], $pl['img'], $pl['name'], $pl['price_1'], $pl['price_2']);
echo <<<HTML
<div style="padding: 7px; text-align: center; vertical-align: middle;" class="left">$is1</div>
<div style="padding: 7px;" class="right">{$this->adminOptions($pl['id'], $pl['pos'])} $is2</div>
HTML;
}
if (empty($this->wares)) {
echo '<div style="grid-column: 1 / 3; padding: 7px; margin: auto">Прилавок магазина пуст.</div>';
}
}
private function calculateMinimalPrice($basePrice, $shopPrice, $needItems)
{
if ($shopPrice < 0.01 && !$needItems) {
$shopPrice = $basePrice;
}
if ($shopPrice < 0) {
$shopPrice = 0;
}
return $shopPrice;
}
private function name(string $name, ?string $defaultName, int $itemid): string
{
$styleSuffix = '';
if ($this->shopId === ShopId::SHOP_2) {
$styleSuffix = 'WL';
}
if (!empty($defaultName)) {
$name .= ' (Предмет: ' . $defaultName . ')';
}
if (!empty($styleSuffix)) {
$name = '<span class="icos_' . $styleSuffix . '">' . $name . ' <small>&nbsp;' . $styleSuffix . '&nbsp;</small></span>';
}
return '<a id="sit_' . $itemid . '" href="/item/' . $itemid . '" target="_blank">' . $name . '</a> &nbsp; &nbsp;';
}
private function icons(?int $align, ?int $artefact, ?int $destiny): string
{
$str = '&nbsp;&nbsp;';
if (!empty($align)) {
$str .= '<img src="' . Config::img() . '/i/align/align' . $align . '.gif" alt="Требуется склонность">';
}
if (!empty($artefact)) {
$str .= '<img src="' . Config::img() . '/i/artefact.gif" alt="Артефакт">';
}
$str .= $this->destiny($destiny);
return $str;
}
private function destiny($d): string
{
if (empty($d)) {
return '';
}
if ($d == 0) {
$str = 'первым, кто наденет его';
} elseif ($d == 1) {
$str = 'первым, кто возьмёт его';
} else {
$str = $d;
}
return '<img
title="Этот предмет будет связан общей судьбой с ' . $str . '. Никто другой не сможет его использовать."
src="' . Config::img() . '/i/destiny0.gif"
alt="Общая судьба">';
}
private function price(int $credits, int $eurocredits, int $voinstvennost): string
{
$result = 'Цена: ';
if ($this->shopId === ShopId::SHOP_2) {
$result .= $this->printColoredValue($this->buyer->getVoinstvennost() >= $voinstvennost, $voinstvennost);
$result .= ' Воинственности ';
} elseif ($this->shopId === ShopId::BEREZKA || $this->shopId === ShopId::ARTEFACTS) {
$result .= '<span style="color: cornflowerblue;">';
$result .= $this->printColoredValue($this->buyer->getEuroCredits() >= $eurocredits, $eurocredits);
$result .= ' екр.</span> ';
} else {
$result .= $this->printColoredValue($this->buyer->getCredits() >= $credits, $credits);
$result .= ' кр.';
}
return '<br><strong>' . $result . '</strong> ';
}
/**
* Если в первом параметре передаётся false, строка во втором параметре красится в красный цвет.
* @param bool $check
* @param $value
* @return string
*/
private function printColoredValue(bool $check, $value): string
{
$color = $check ? 'inherit' : 'red';
return sprintf('<span style="color:%s;">%s</span>', $color, $value);
}
private function needItems(string $items): string
{
if (!$items || Config::get('noitembuy')) {
return '';
}
$result = '';
$trn = true;
$itemsArray = explode(',', $items);
foreach ($itemsArray as $keyvalue) {
[$key, $value] = explode('=', $keyvalue);
if (!empty($key) && !empty($value)) {
$neededItemName = Db::getValue('select name from items_main where id = ?', [$key]);
if ($neededItemName) {
$neededItemsInInventoryCount = Db::getValue(
'select count(*) from items_users where item_id = ? and inShop = 0 and inOdet = 0 and `delete` in (0,1000) and uid = ?',
[$key, $this->buyer->getId()]);
if ($neededItemsInInventoryCount < (int)$value) {
$trn = false;
}
$result .= '[<strong>' . $neededItemName . '</strong>] x' . $value . ', ';
}
}
}
return $this->printColoredValue($trn, '<br>Требует предмет: ' . rtrim($result, ', ') . ' ') . '<br>';
}
private function getcomplect(?int $complect): string
{
if (!isset($complect)) {
return '';
}
$cname = 'Неизвестный Комплект';
$text = '';
$stmt = Db::getRows('select * from complects where com = ? order by x', [$complect]);
foreach ($stmt as $row) {
$cname = $row['name'];
$text .= '&nbsp;&nbsp;&bull; <span style="color: green;">' . $row['x'] . ' предметов</span>:<br>';
//действие комплекта
$complectBonuses = new Bonuses(Conversion::dataStringToArray($row['data']));
foreach ($complectBonuses->get() as $name => $value) {
$text .= '&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: darkgreen;">';
if ($name === 'Броня') {
$text .= $name . ': ' . $value;
} else {
$text .= $name . ': ' . ($value > 0 ? '+' . $value : $value);
}
$text .= '</span><br>';
}
}
return "<br>Часть комплекта: <strong>$cname</strong><br><small>$text</small>";
}
private function imageAndControls(int $id, int $type, string $image, string $name, float $credits, float $eurocredits): string
{
if ($type == 71) {
$result = '<img src="' . Config::img() . '/i/items/' . $image . '" width="80" alt="' . $name . '"><br>';
} else {
$result = '<img src="' . Config::img() . '/i/items/' . $image . '" alt="' . $name . '"><br>';
}
if ($this->shopId == ShopId::SHOP_2) {
$js = <<<JS
<button onClick="top.buyShopNow($id,'?otdel=$this->otdel&buyVn=$id&sd4={$this->buyer->getNextAct()}','$name')">Купить</button>
JS;
} elseif (($this->shopId == ShopId::BEREZKA || $this->shopId == ShopId::ARTEFACTS) && $this->buyer->hasEnoughEuroCredits($eurocredits)) {
$js = <<<JS
<button onClick="top.buyShopNow($id,'?otdel=$this->otdel&buyEkr=$id&sd4={$this->buyer->getNextAct()}','$name',$eurocredits,'екр.')">Купить</button>
JS;
} elseif ($this->buyer->hasEnoughCredits($credits)) {
$js = <<<JS
<button onClick="top.buyShopNow($id,'?otdel=$this->otdel&buy=$id&sd4={$this->buyer->getNextAct()}','$name',$credits,'кр.')">Купить</button>
JS;
} else {
return '';
}
return $result . $js;
}
private function adminOptions(int $itemId, int $itemPosition): string
{
if (!$this->buyer->isAdmin()) {
return '';
}
$time = microtime();
return <<<HTML
<div style="float:right">
<a href="?otdel=$this->otdel&itmid=$itemId&itmup=1#itmdown$itemId">↿</a>
&nbsp; $itemPosition &nbsp;
<a href="?otdel=$this->otdel&itmid=$itemId&itmdown=1#itmdown$itemId">⇂</a>
<button onclick="window.open('/item_edit_data.php?edit_item_data=$itemId','winEdi1','width=850,height=400,top=400,left=500,resizable=no,scrollbars=yes,status=no')">
Редактировать предмет
</button>
<button onclick="location.href='/main.php?timeWorld=$time&otdel=$this->otdel#itmShop$itemId'">Обновить</button>
</div><br>
HTML;
}
public function buy(int $itemid): string
{
$sql = 'select sid, items_shop.price_1, name from items_shop left join items_main on item_id = id where item_id = ? and sid = ?';
$item = Db::getRow($sql, [$itemid, $this->shopId->value]);
if (!$this->buyer->hasEnoughCredits($item['price_1'])) {
return 'Покупка не удалась.';
}
$newId = User\ItemsModel::addItem($itemid, $this->buyer->getId());
Db::sql('update items_users set `1price` = ? where id = ?', [$item['price_1'], $newId]);
User::start()->info['money'] -= $item['price_1'];
User::start()->addKr(-$item['price_1']);
Delo::add(1, "shopid:{$item['sid']}", $this->buyer->getId(), "Покупка «{$item['name']}» по цене {$item['price_1']}.", $item['price_1']);
return "Вы купили «{$item['name']}» по цене {$item['price_1']}.";
}
public function buyEkr(int $itemid): string
{
$sql = 'select sid, items_shop.price_2, name from items_shop left join items_main on item_id = id where item_id = ? and sid = ?';
$item = Db::getRow($sql, [$itemid, $this->shopId->value]);
if (!$this->buyer->hasEnoughEuroCredits($item['price_2'])) {
return 'Покупка не удалась.';
}
$newId = User\ItemsModel::addItem($itemid, $this->buyer->getId());
Db::sql('update items_users set `2price` = ? where id = ?', [$item['price_2'], $newId]);
User::start()->info['money2'] -= $item['price_2'];
User::start()->addEkr(-$item['price_2']);
Delo::add(1, "shopid:{$item['sid']}", $this->buyer->getId(), "Покупка «{$item['name']}» по цене {$item['price_2']}.", $item['price_2']);
return "Вы купили «{$item['name']}» по цене {$item['price_2']}.";
}
public function buyVn(int $itemid): string
{
$sql = 'select sid, items_shop.price_4, name from items_shop left join items_main on item_id = id where item_id = ? and sid = ?';
$item = Db::getRow($sql, [$itemid, $this->shopId->value]);
if (!$this->buyer->hasEnoughVoinstvennost($item['price_4'])) {
return 'Покупка не удалась.';
}
$newId = User\ItemsModel::addItem($itemid, $this->buyer->getId());
Db::sql('update items_users set `4price` = ? where id = ?', [$item['price_4'], $newId]);
User::start()->rep['rep3'] -= $item['price_4'];
User::start()->addVoinstvennost(-$item['price_4']);
Delo::add(1, "shopid:{$item['sid']}", $this->buyer->getId(), "Покупка «{$item['name']}» по цене {$item['price_4']}.", $item['price_4']);
return "Вы купили «{$item['name']}» по цене {$item['price_4']}.";
}
public function getUsedOtdels(): array
{
$result = [];
foreach (Db::getColumn('select r from items_shop where sid = ? group by r', [$this->shopId->value]) as $v) {
$result[$v] = $this->shopOtdel->getName($v);
}
return $result;
}
public function getUserWallet(): string
{
$result = '';
if ($this->shopId === ShopId::MAIN) {
$result = $this->buyer->getCredits() . ' кр.';
} elseif (in_array($this->shopId, [ShopId::BEREZKA, ShopId::ARTEFACTS])) {
$result = $this->buyer->getEuroCredits() . ' екр.';
} elseif ($this->shopId === ShopId::SHOP_2) {
$result = $this->buyer->getVoinstvennost() . ' воинственности.';
}
return $result;
}
}