В этой наработке представлена возможность использовать полноценный магазин. Изначально магазин пустой, но вы можете заложить вещичку в магазин, и она тут же появится на полке. Или наоборот, купив артефакт, он тут же пропадает с магазина.
Изначальная вдохновляющая идея была взята отсюда На тот момент я даже не думал, что такое возможно. Классная идея. Но она сделана была на гуи автором, и работает на один рынок. Поэтому, чтобы такая система работала сразу в нескольких магазинов, нужно переделывать полностью. Поэтому я переделал на хэш-таблицу.
Казалось бы проще сделать: добавил или удалил. Что тут такого сложного? Но возникали баги. При повторном добавлении итемы могли исчезать с рынка. Баг описан в этой теме. Пришлось по-другому доделывать - запоминать все айтемы в хэше, и при каждом изменении (добавлении/удалении) сначала все ячейки вычищаешь, а потом заново добавляешь.
Для работы требуется скачать папку триггеров "система рынка" + иметь те способности, которые указаны у рынка:
для работы нужно пункт 2.9
для работы нужно пункт 2.9
триггер инициализации
при инициализации запускаем еще базу данных (описано что нужно туда хранить)
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'bspd', 1) сапоги - сккороходы - здесь храним число снимаемых зарядов. Сделано специально. Если вы продаете два одинаковых итема, например, ботинки скорости - 2 шт, то они сложатся не в два отдельных слота, а в один но с +2 зарядом. При покупке нам надо снять определенное число, каждый раз будем снимать 1.
Но зачем тогда хранить эти значения? какой смысл? Дело в этом поле: Кол-во зарядов
Но зачем тогда хранить эти значения? какой смысл? Дело в этом поле: Кол-во зарядов
Когда вы покупаете предмет, или создаете триггерно предмет, у вашего героя предмет получается с указанным кол-вом зарядов.
Вот например, Жезл молнии = 3 заряда, Жезл похищения маны = 2 заряда, Камень жизни = 1 зарядов.
Большинство итемов в варкрафте без зарядов - те же когти, маска смерти, сапоги или перчатки. Но эти беззарядовые итемы не могут быть равны 0, так как в РО записано, но в базе данных нужно записать 1. Иначе не вычитается при покупке. Если не вписать туда, то предмет с магазина удаляться даже не будет (пример боевые когти +15 или сфера льда).
Вот например, Жезл молнии = 3 заряда, Жезл похищения маны = 2 заряда, Камень жизни = 1 зарядов.
Большинство итемов в варкрафте без зарядов - те же когти, маска смерти, сапоги или перчатки. Но эти беззарядовые итемы не могут быть равны 0, так как в РО записано, но в базе данных нужно записать 1. Иначе не вычитается при покупке. Если не вписать туда, то предмет с магазина удаляться даже не будет (пример боевые когти +15 или сфера льда).
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'I007', 1) амулет леса (руна)
Есть еще один аспект - руны. Если кто знает, можно скрещивать несколько итемов в один с помощью рун.
Есть еще один аспект - руны. Если кто знает, можно скрещивать несколько итемов в один с помощью рун.
- В таких системах в магазинах обычно продаются руны, а не оригиналы.
- При получении руна исчезает даже при заполненном инвентаре. Если совпадает рецепт, удаляем ненужные, создаем нужный. Иначе создаем и кладем обычный в инвентарь, при заполненном инвентаре дропаем.
- Если выбрасывают обычный итем на землю, на земле подменяется на руну.
- Очень удобно использовать не только при скрещивании, но при складываний зарядов однотипных. Особенно, когда у вас заполнен инвентарь. Например, амулет леса.
- Если продаем обратно в рынок, то необходимо, заложить не оригинал, а ее копию - руну
call SaveInteger(udg_Hash, original, key, rune) - здесь записываем базу данных рун. Это нужно, чтобы доставать нужный тип руны по оригиналу. В качестве ключа key взял число 66
call SaveInteger(udg_Hash, 'I000', 66, 'I004')
call SaveInteger(udg_Hash, 'I000', 66, 'I004')
function Trig_data_Actions takes nothing returns nothing
call TriggerSleepAction( 2 )
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'I007', 1) //амулет леса (руна)
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'I001', 1) //Боевые когти (руна)
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'I002', 1) //Туфли логкости (руна)
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'I003', 1) //когти воина (руна)
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'I000', 1) //рецепт когти воина (руна)
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'pghe', 1) //целебное зелье
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'rde3', 1) //кольцо защиты (+4)
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'afac', 1) //флейта меткости
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'kpin', 1) //флейта прозрения
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'odef', 1) //сфера тьмы
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'evtl', 1) //талисман защиты
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'bspd', 1) //сапоги - сккороходы
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'bgst', 1) //пос богатыря
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'gcel', 1) //перчатки скорости
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'lhst', 1) //рог ветров
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'rst1', 1) //руковица огра
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'brac', 1) //рунные браслеты
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'prvt', 1) //талисман здоровья
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'clfm', 1) //огненный плащ
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'ciri', 1) //одеяние мага
// Если является обычным предметов, связующий с руной. То можно заранее создать руну
call SaveInteger(udg_Hash, 'I000', 66, 'I004') //рецепт когти воина
call SaveInteger(udg_Hash, 'I001', 66, 'I005') //боевые когти
call SaveInteger(udg_Hash, 'I002', 66, 'I006') //туфли ловкости
call SaveInteger(udg_Hash, 'wild', 66, 'I007') //амулет леса
endfunction
//===========================================================================
function InitTrig_data takes nothing returns nothing
set gg_trg_data = CreateTrigger( )
call TriggerAddAction( gg_trg_data, function Trig_data_Actions )
endfunction
триггер PawnItem (закладываем итем в магазин)
GetSellingUnit() =продающий торговец (типа всякие предметы закладывает в магазин и получает деньги)
GetSoldUnit() = проданный юнит (типа продать живое существо, типа осла, коровы)
GetBuyingUnit()=GetTriggerUnit() = покупающий торговец (это обычно магазин)
GetSoldUnit() = проданный юнит (типа продать живое существо, типа осла, коровы)
GetBuyingUnit()=GetTriggerUnit() = покупающий торговец (это обычно магазин)
function ChargesItem takes integer charges returns integer
local integer count_charges
if ( charges > 0 ) then // обычные итемы не имеют зарядов (равен нулю).
set count_charges = charges //Поэтому приравниваем к единице
else
set count_charges = 1 // остальные итемы, имеющие заряды. у них приравнивают к зарядам
endif
return count_charges
endfunction
function TypeofItems takes integer Id returns integer
local integer i = LoadInteger(udg_Hash, Id, 66)
if i == 0 then
set i = Id
endif
return i
endfunction
function Trig_PawnItem_Conditions takes nothing returns boolean
return not LoadBoolean(udg_Hash, GetHandleId(GetBuyingUnit()), udg_sell_item) //проверяем может ли магазин продавать
endfunction
function Trig_PawnItem_Actions takes nothing returns nothing
local unit market = GetBuyingUnit() //магазин
local integer id_market = GetHandleId(GetBuyingUnit()) //ид-хэндл магазина
local integer id_item = TypeofItems(GetItemTypeId(GetSoldItem())) //тип итема
local integer charges = ChargesItem(GetItemCharges(GetSoldItem())) //кол-во зарядов
local integer key1 = ( id_item + udg_CountOfSlots ) //подсчитывает ключ для логическую busy_slot
local boolean busy_slot = LoadBoolean(udg_Hash, id_market, key1) // занимает ли данный тип предмета магазин
local integer count = LoadInteger(udg_Hash, id_market, udg_CountOfSlots) //кол-во занятых слотов
//local boolean sell_item = LoadBoolean(udg_Hash, id_market, udg_sell_item) //можно ли продавать в магазин
local integer stock
local integer max_stock
local integer i = 0
local integer a = 0
local integer MaxIT
local boolean can_set = false //логическая определяет устанавить ли изменения с данным типом предмета (в конце будет проверка)
call BJDebugMsg( "|cFFFFA500===========|r" )
call BJDebugMsg( "|cFFCDA54Bзакладываемый предмет в рынок |cFFFFDC00" + GetItemName(GetSoldItem()) + "|r" )
if (count >= 0 and count <= 11) then // ЕСЛИ у магазина есть свободные ячейки, то ...
// проверяем, данный тип у предмета есть в магазине или нет.
if ( busy_slot ) then // Если есть, то выгружаем из хэша и складываем все
// загружаем стэки из хэша (стэк - кол-во штук итемов в магазине)
set stock = LoadInteger(udg_Hash, id_market, id_item)
call BJDebugMsg( "|cFF12FC40" + I2S(stock) + " - кол-во стэков из хэша" + "|r" )
// складываем заряды и стэки в переменную max_stock
set max_stock = ( charges + stock )
call BJDebugMsg( "|cFFFFA500" + I2S(charges) + " кол-во зарядов Sold Item|r " + "+ " + "|cFF12FC40" + I2S(stock) + " кол-во стэков у предмета в магазине (из хэша)|r " + "= " + I2S(max_stock) )
// сохраняем стэк в хэш
call SaveInteger( udg_Hash, id_market, id_item, max_stock)
set MaxIT = max_stock
set can_set = true
elseif ( (not busy_slot) and (count < 11) ) then //Иначе, если нет в магазине, то создаем новый (ничего не выгружая).
// кол-во занятых ячеек в магазине стало больше на одну
set count = ( count + 1 )
// сохраняем кол-во занятых ячеек
call SaveInteger( udg_Hash, id_market, udg_CountOfSlots, count )
call BJDebugMsg("|cFF00FFFF" + "Кол-во занятых слотов стало больше, теперь их всего " + I2S(count) + "|r")
//сохраняем какой-тип сохраняем
call SaveInteger( udg_Hash, id_market, udg_TypeOfItem + count, id_item )
// сохранить кол-во стэков предмета в магазине
call SaveInteger( udg_Hash, id_market, id_item, charges )
set MaxIT = charges
set can_set = true
call BJDebugMsg( "|cFFFFA500" + I2S(charges) + " кол-во зарядов Sold Item|r ")
call SaveBoolean( udg_Hash, id_market, key1, true ) // сохраняем то, что юнит обладает данным типом
call SaveInteger( udg_Hash, id_market, udg_NumberTypeItems + id_item, count ) //сохраняем по типу номер слота
endif
if (can_set) then
// удаляем все итемы из магазина
loop
exitwhen i > 12
call RemoveItemFromStock( market, LoadInteger( udg_Hash, id_market, udg_TypeOfItem + i ))
set i = i+1
endloop
set i = 0
// добавляем все итемы обратно
loop
exitwhen i > 11
set id_item = LoadInteger( udg_Hash, id_market, udg_TypeOfItem + i )
if id_item > 0 then //проверяем, что ячейка магазина не пустует
set a = a + 1
set stock = LoadInteger(udg_Hash, id_market, id_item)
call SaveInteger( udg_Hash, id_market, udg_NumberTypeItems + id_item, a ) //сохраняем по типу номер слота
call AddItemToStock( market, id_item, stock, stock )
endif
set i=i+1
endloop
endif
// идет еще следующая проверка. Проверяет, стало ли занятых ячеек равно 11. Если да. то нужно ограничить
if ( count == 11 ) then
// если все ячейки заполнены. то удаляем способность продажа предметов, и никто больше не сможет продавать
// запоминаем, что способность удалена
call SaveBoolean( udg_Hash, id_market, udg_sell_item, true )
//call TriggerSleepAction(1.00) //очень нужна задержка, а то способность вместе с итемами пропадает
call UnitRemoveAbility( market, 'Apit')
call BJDebugMsg( "способность удалена, теперь нельзя продавать предметы" )
endif
endif
set market = null
endfunction
//===========================================================================
function InitTrig_PawnItem takes nothing returns nothing
set gg_trg_PawnItem = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_PawnItem, EVENT_PLAYER_UNIT_PAWN_ITEM )
call TriggerAddCondition( gg_trg_PawnItem, Condition( function Trig_PawnItem_Conditions ) )
call TriggerAddAction( gg_trg_PawnItem, function Trig_PawnItem_Actions )
endfunction
триггер SellItem (Покупка итема)
GetSellingUnit()=GetTriggerUnit() =продающий торговец (в данном случае магазин продает нам)
GetSoldUnit() = проданный юнит (типа продать живое существо, типа осла, коровы)
GetBuyingUnit() = покупающий торговец (это наш герой отдает денюшку, а сам получает артефает или лошадь)
GetSoldUnit() = проданный юнит (типа продать живое существо, типа осла, коровы)
GetBuyingUnit() = покупающий торговец (это наш герой отдает денюшку, а сам получает артефает или лошадь)
function Trig_SellItem_Actions takes nothing returns nothing
local unit market = GetSellingUnit()
local integer id_market = GetHandleId(market) // номер хэндла магазина
local integer id_item = GetItemTypeId(GetSoldItem()) //тип итема
local integer charges = LoadInteger(udg_Hash, udg_ChargesTypeOfItem, id_item) //стандартное кол-во зарядов в одном артефакте
local integer stock = LoadInteger(udg_Hash, id_market, id_item) //общее кол-во зарядов этого типа
local integer count_items = LoadInteger(udg_Hash, id_market, udg_CountOfSlots) //кол-во занятых слотов в магазине
local integer key1 = (id_item + udg_CountOfSlots) //ключ данного типа
local boolean busy_slot = LoadBoolean(udg_Hash, id_market, key1) // занимает ли данный тип предмета магазин
local boolean sell_item = LoadBoolean(udg_Hash, id_market, udg_sell_item) //можно ли продавать в магазин
local integer min_stock
local integer min_count_items
local integer i = 1
local integer a = 0
local integer key2
local integer count_stock
local boolean add_change = false
call BJDebugMsg( "|cFFFFFF00===========|r" )
call BJDebugMsg( "|cFFFF0000Купленный предмет в магазине |cFFFFDC00" + GetItemName(GetSoldItem()) + "|r" )
call BJDebugMsg( "|cFF12FC40Stocks = " + I2S(stock) + " - кол-во стэков из хэша" )
call BJDebugMsg( "|cFFFFA500Charges = " + I2S(charges) + " - кол-во отнимаемых зарядов у итема (загружается из базы данных типа итема)" + "|r" )
set min_stock = stock - charges // вычитаем, тут еще проверку надо что если зарядов больше стэков
call BJDebugMsg( "Кол-во зарядов = |cFF12FC40Stocks|r - |cFFFFA500Charges|r = " + I2S(stock) + " - " + I2S(charges) + " = " + I2S(min_stock))
if ( busy_slot and count_items > 0 and count_items <= 11 ) then
// сохраняем кол-во стэков
call SaveInteger( udg_Hash, id_market, id_item, min_stock )
if (min_stock==0) then //если кол-во стэков стало равно ноль (если зарядов совсем нет), то удаляем итем
set min_count_items = count_items - 1 //перерасчет кол-во итемов
set add_change = true //ВНИЗУ ИДЕТ ПОЛНОЕ вычищение ИТЕМА из магазина
call BJDebugMsg( "|cFF00FFFFКол-во занятых ячеек в магазине поубавилось: было = " + I2S(count_items) + ", но стало = " + I2S(min_count_items)+" |r" )
// сохраняем кол-во занимаемых ячеек
call SaveInteger( udg_Hash, id_market, udg_CountOfSlots, min_count_items )
set key2 = (udg_TypeOfItem+LoadInteger( udg_Hash, id_market, udg_NumberTypeItems + id_item ))
call SaveInteger( udg_Hash, id_market, key2, 0 ) //сохраняем что такого типа нет
//call BJDebugMsg( "есть ли тип: " + I2S(LoadInteger( udg_Hash, id_market, key2)) )
call SaveBoolean( udg_Hash, id_market, key1, false ) // запоминаем в хэш что данного типа предмета больше нет
call RemoveItemFromStock( market, id_item)
// проверяем ячейки магазина
if ( count_items == 11 and min_count_items == 10 ) then // если ячейка освободилась, то добавляем способность
call BJDebugMsg( "Свободных слотов в магазине было 11, стало 10. Ячейка освободилась" )
if ( sell_item ) then
call UnitAddAbility( market,'Apit' )
call BJDebugMsg( "НЕЛЬЗЯ БЫЛО ПРОДАВАТЬ - теперь МОЖНО" )
// запоминаем, что способность больше не удалена
call SaveBoolean( udg_Hash, id_market, udg_sell_item, false )
endif
endif
elseif (min_stock > 0) then //если произошли изменения с кол-вом стэков (стало или больше или меньше), то изменяем число
// сохраняем кол-во занимаемых ячеек
call BJDebugMsg( "итог " + I2S(min_stock) )
set add_change = true
//call AddItemToStock( market, id_item, min_stock, min_stock )
endif
endif
if add_change then
set i = 0
// удаляем все итемы из магазина
loop
exitwhen i > 12
call RemoveItemFromStock( market, LoadInteger( udg_Hash, id_market, udg_TypeOfItem + i ))
set i = i+1
endloop
set i = 0
loop
exitwhen i>count_items
set id_item = LoadInteger( udg_Hash, id_market, (udg_TypeOfItem+i) )
if id_item > 0 then
set a = a + 1
set stock = LoadInteger(udg_Hash, id_market, id_item)
call SaveInteger( udg_Hash, id_market, (udg_TypeOfItem+a), id_item )
call SaveInteger( udg_Hash, id_market, udg_NumberTypeItems + id_item, a ) //сохраняем по типу номер слота
call AddItemToStock( market, id_item, stock, stock )
endif
set i = i+1
endloop
endif
set market = null
endfunction
//===========================================================================
function InitTrig_SellItem takes nothing returns nothing
set gg_trg_SellItem = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( gg_trg_SellItem, EVENT_PLAYER_UNIT_SELL_ITEM )
call TriggerAddAction( gg_trg_SellItem, function Trig_SellItem_Actions )
endfunction
Необычные идеи:
- Когда забьете все слоты (максимум 11 штук, можно сделать 12), удаляете способность магазина "Лавка: продать итемы (Apit)". Тогда в магазин нельзя продать, но вы сможете у магазина что-нибудь купить. Когда слот какой-нибудь освободиться, вы сможете обратно добавить способность. Недостаток: когда у вас забит магазин, не получится в один слот одинаковые вещи складировать: типа рубашка + рубашка = 2 рубашки (потому что у магазина способность удалена, и он не может принять).
- Можно было и не запрещать продажу при забитом магазине. Надо было проверять, что за предмет продается, есть ли такой в магазине. Если есть, складываем, иначе, если нет, пробуем предотвратить продажу.
проблема
Пробовал выкидывать в момент продажи
выкидывает под ногами, но ссыпаются деньги от продажи. Короче продажа как-бы произошла, но итем как лежит под ногами. Не знаю, как отменить, чтобы деньги не ссыпались.
Пробовал ловить приказ, проблема еще та: надо понять какой приказ, как отследить предмет, и что в этот магазин продается. (Будет это реализовано, не знаю)
Пробовал ловить приказ, проблема еще та: надо понять какой приказ, как отследить предмет, и что в этот магазин продается. (Будет это реализовано, не знаю)
- Или можно вообще не запрещать. Использовать бесконечные ячейки с бесконечными листами. Можно было переворачивать листы.
- Использовать аукцион (можно продавать вещицу, и между игроками устраивать ставки).
- Можно попробовать изменять стоимость. Тогда на каждый оригинал нужно делать копию, как с руной. Или использовать MemoryHuck
- можно использовать дабл-клик. повторную покупку таймером отслеживайте (проверяете сколько секунд прошло с первой покупкой. Если таймер через 2 секунды проходит, то дабл-клик не работает). Короче что хочу сказать, можно двойным нажатием купить все зелья этого типа.
остаются проблемы с зарядами (не доработал, доработаю попозже)
- если покупаешь 1 итем, скажем тот же жезл молнии. Вам в инвентарь героя прибавляю +3 заряда, а в самом магазине вычли -1. А должны вычесть -3.
- Вот забыл с остатком поработать. вот например, у жезла = 3 заряда. За каждую покупку будет снимать 3. А если я продам в магазин 4 шт, а потом будут выкупать предметы обратно. при первой покупке получу 3 заряда, останется 1. При второй покупке должен получить +1, из-за поля Кол-во зарядов прибавит +3 (а надо +1). Надо тут отрегулировать с остатками .
- Также вытекает и проблема с ценой. В магазине при заряде +3, и при заряде +1 стоимость одинаковая. Жезл молнии 3 заряда = 150 стоимость; 1 заряд = 150 стоимость (а должен быть 1 заряд 50 стоимость)
Ред. MpW
call SaveR2Icharges('whwd', 'I008', 3) духи-целители х3 заряда I008-I009-I00:
SaveR2Icharges(original, rune, charges)
original - итем с зарядами, у него указано кол-во зарядов charges
rune - первая руна, у вас должен быть равкод забит заранее, например:
I008-первая руна I009- вторая руна I00: - третья руна
Например, продал 9 зарядов духов-целителей. В магазине стало 9 зарядов.
I008-итем с 1 зарядом цена 200
I009-итем с 2 зарядом цена 400
I00A-итем с 3 зарядом цена 600
I009=1227894841
I00A=1227894849 Тут отличается на целых 8 знаков, короче сбивается база данных
1227894842=I00: не удивляйтесь, двоеточие - это тоже символ, в 256-ричной системе по-другому номеруются символы. Просто варкрафт не хочет вписывать этот символ, но мы можем вписать.
Беру копирую итем I00A, и в jngp выскакивает окошко Create Object, и туда копируете 'I00:'
Ред. MpW
13 версия
кстати, еще вот такое нашел благодаря Факову тема - хотя это мне никак не помогло, у меня другое
Ред. Fakov
если шо вдруг
Ред. MpW
14 версия