• Новые темы в этом разделе публикуются автоматически при добавлении файла в менеджер ресурсов.
    Ручное создание новых тем невозможно.
Иконка ресурса

Данные по продаваемым торговцами предметами 2024-08-22

Нет прав для скачивания

Gaikotsu

яжпрограммист
Легенда
Сообщения
1 710
Розыгрыши
0
Решения
27
Репутация
6 178
Реакции
2 829
Баллы
2 188
Gaikotsu добавил(а) новый ресурс:

Данные по продаваемым торговцами предметами - Перегнанные в JSON данные по продаваемым предметам из PTS разных хроник


Узнать больше об этом ресурсе...
 
PHP-cкрипт, при помощи которого извлекались данные. Сразу говорю что говнокод тот еще, т.к. скрипт набрасывался на скорую руку по принципу "работает и ладно"

Для работы скрипта потребуется класс L2Data, расшаренный мною ранее.
PHP:
<?php
//
// Данный скрипт пытается вытащить из ai.obj всю информацию о предметах, продаваемых NPC, и сохраняет ее в файл формата JSON
//
require_once "L2Data.php";

// Путь к серверным скриптам
$serverFiles = "pts_scripts/";

echo "Reading ai.obj ...";
$fh = fopen("{$serverFiles}ai.obj", "r");

$data = [];
$show = false;

while (!feof($fh))
{
    $str = fgets($fh);
    $str = mb_convert_encoding($str, "CP1251", "Unicode");
    $str = trim($str);

    if (stripos($str, "class ") === 0)
    {
        $class = str_replace(["class", " 0 ", " 1 ", " 2 ", " "], "", $str);
        $temp = explode(":", $class);
        $class = $temp[0];
        $show = true;
    }

    if (stripos($str, "buyselllist_begin") !== false && stripos($str, " SellList") !== false)
    {
        if ($show)
        {
            echo "\n >>> {$class}:";
            $show = false;
        }

        $list = substr($str, stripos($str, "buyselllist_begin") + 18);
        echo " {$list}";
        $str = fgets($fh);
        $str = mb_convert_encoding($str, "CP1251", "Unicode");
        $str = trim($str);

        while (stripos($str, "buyselllist_end") === false)
        {
            $str = str_replace(" ", "", $str);

            if (stripos($str, "//") !== false)
                $str = trim(substr($str, 0, stripos($str, "//")));

            $data[$class][$list][] = explode(";", L2SData::trim($str));
            $str = fgets($fh);
            $str = mb_convert_encoding($str, "CP1251", "Unicode");
            $str = trim($str);
        }
    }
}

fclose($fh);

echo "\nReading npcdata ... ";
$npcs = L2SData::loadData("{$serverFiles}npcdata.txt");

echo "\nMaking relations between AI and npc id(s) ... ";
$npcAI = [];

foreach ($npcs as $npc)
{
    $id = $npc[2];
    $ai = L2SData::trim(L2SData::getValue($npc, "npc_ai", "{}"));
    $temp = explode(";", $ai);
    $ai = L2SData::trim($temp[0]);
    $npcAI[$ai] = $id;
}

echo "\nSearch npc id(s) by AI ...";

foreach ($data as $k => &$v)
{
    if (!isset($npcAI[$k]))
    {
        $v["id"] = -1;
        echo "\n >>> not found npc id for AI [{$k}]";
    }
    else
        $v["id"] = $npcAI[$k];
}

echo "\nSaving traders.json ...";
file_put_contents("traders.json", json_encode($data, JSON_PRETTY_PRINT));
?>
 
Последнее редактирование:
Насчет номерков в данных, где можно почитать о том что они значат? Вроде нашел описание тут Buyselllist Но там только понятно o первом и последних номерах. Третий вроде тоже понятно, идет как налог. Но второй, не понятно как с ним что-либо делать.
Если сравнить с L2J buylists, то у них меньше параметров записано. Но есть restock_delay почему-то... Да и цена прописана тоже. Налога нет.
 
по ссылке у тебя там неточность, про которую там же и Mangol пишет, на самом деле идет такая последовательность:

ид предмета; наценка к базовой цене предмета в %; модификатор времени обновления количества; количество

модификатор времени и количество используются для лимитированной продажи конкретных предметов, обычно в кх.

правда время обновления считается вроде бы не по той формуле что там Mangol написал, т.е. не просто 1440 * модификатор = время в минутах, а как-то более замудрено там это делается.

Не уверен на все 100%, но вроде бы по этому модификатору считается за какое время восстановится одна единица предмета и кажется это время высчитывается по формуле 60 / модификатор = время в минутах
 
Последнее редактирование:
Поправил.

Замени в скрипте везде L2Data:: на L2SData::
 
Формула обновлении по времени в мс

restockFactor * 24 * 60 * 60 * 1000
 
Кстати я хз - на оффе по одной штучке увеличивает предметы в стопке, при лимите количества в ней > 1, когда приходит время или разом всю стопку?
У себя я сделал что увеличивает по единичке в цикле, пока времени с последнего обновления хватает для увеличения количества.
В ситуациях с большим периодом обновления этот вариант просто более удобен, т.к. позволяет более часто покупать предмет хотя бы в не максимально возможном количестве вместо того чтобы ждать очень долго когда рефрешнется вся стопка.
Ну и в данных продаваемого храню именно период апдейта на +1 к количеству, а не полное время обновления всей стопки. Т.е. если к примеру продается лимитировано 10 штук и время обновления в хмл задано например 60 минут, то после парса это превратится в данных продаваемого предмета в период обновления количества равный 60 / 10 = 6 мин.
Java:
    public synchronized List<ItemInfo> getItems()
    {
        List<ItemInfo> items = new ArrayList<>();
        int currentTime = (int) (System.currentTimeMillis() / 60_000);

        for (ItemInfo item : _list)
        {
            if (item.isCountLimited())
            {
                if (item.getCurrentValue() < item.getCount() && currentTime > (item.getLastRefillTime() + item.getRefillTime()))
                {
                    if (item.getRefillTime() > 0)
                    {
                        while (currentTime > (item.getLastRefillTime() + item.getRefillTime()))
                        {
                            item.setLastRefillTime(item.getLastRefillTime() + item.getRefillTime());
                            item.incCurrentValue();
                        }
                    }

                    if (item.getCurrentValue() > item.getCount())
                        item.setCurrentValue(item.getCount());
                }

                item.setUseable(item.getCurrentValue() > 0);
            }

            items.add(item);
        }

        return items;
    }
 
Вместо
Java:
while ( currentTime > (item.getLastRefillTime() + item.getRefillTime())) { ... }

можно просто посчитать сколько вышло оборотов

Код:
int iterations = Math.max(0, (currentTime - item.LastRefillTime()) % item.getRefillTime())

ну и после добaвляем сколько нужно предметов обратно в buylist product

Код:
item.setCurrentValue(Math.min( iterations, item.getCount()));