8gabriel8, да, вот я новичок в модделинге. Пока что не пробовал
хорош пункт 2, и пункт 6 (но надо понять как сделать самому в модделинг-редакторе, ничего не соображаю на какие кнопки там нажимать. Вроде во 2 пункте все расписано. Щас попробую)
У меня слетел опять UMSWE (достало уже чего плагин слетает то? У меня 2-3 за год так). Хотел тайлы поставить, и еще клифы изменить (галочки на проходимость и строительство). И в результате, что то критануло из-за terrain.slk. Час настраивал, удалял. А нужно было эту сборку на помойку, и взять норм. И почему-то переустановка сборки не решает проблему.
короче поискал на сайте, и везде перессылки на эту страничку. А эта сборка не работает. =( Мне помогла старая сборка, которая хорошо что сохранилась (5d не сохранилась, но вот JNGP_R1.3_COMPAT осталась, хорошо что не удалил). другую сборку было не найти
Я видел эту карту (что-то сделано норм, а что-то на гуи):
код
function Trig_jingong_chufadanweiActions takes nothing returns nothing
set udg_unit04=GetTriggerUnit()
if((RectContainsUnit(udg_rect22,udg_unit04)==true))then
if((IsUnitInForce(udg_unit04,udg_forces04[1])==true))then
set udg_locations01[0]=GetRectCenter(udg_rect07)
call IssuePointOrderLoc(udg_unit04,"attack",udg_locations01[0])
call RemoveLocation(udg_locations01[0])
else
set udg_locations01[0]=GetRectCenter(udg_rect03)
call IssuePointOrderLoc(udg_unit04,"attack",udg_locations01[0])
call RemoveLocation(udg_locations01[0])
endif
else
if((RectContainsUnit(udg_rect23,udg_unit04)==true))then
if((IsUnitInForce(udg_unit04,udg_forces04[1])==true))then
set udg_locations01[0]=GetRectCenter(udg_rect08)
call IssuePointOrderLoc(udg_unit04,"attack",udg_locations01[0])
call RemoveLocation(udg_locations01[0])
else
set udg_locations01[0]=GetRectCenter(udg_rect04)
call IssuePointOrderLoc(udg_unit04,"attack",udg_locations01[0])
call RemoveLocation(udg_locations01[0])
endif
else
if((RectContainsUnit(udg_rect24,udg_unit04)==true))then
if((IsUnitInForce(udg_unit04,udg_forces04[1])==true))then
set udg_locations01[0]=GetRectCenter(udg_rect09)
call IssuePointOrderLoc(udg_unit04,"attack",udg_locations01[0])
call RemoveLocation(udg_locations01[0])
else
set udg_locations01[0]=GetRectCenter(udg_rect05)
call IssuePointOrderLoc(udg_unit04,"attack",udg_locations01[0])
call RemoveLocation(udg_locations01[0])
endif
else
if((RectContainsUnit(udg_rect25,udg_unit04)==true))then
if((IsUnitInForce(udg_unit04,udg_forces04[1])==true))then
set udg_locations01[0]=GetRectCenter(udg_rect10)
call IssuePointOrderLoc(udg_unit04,"attack",udg_locations01[0])
call RemoveLocation(udg_locations01[0])
else
set udg_locations01[0]=GetRectCenter(udg_rect06)
call IssuePointOrderLoc(udg_unit04,"attack",udg_locations01[0])
call RemoveLocation(udg_locations01[0])
endif
else
if((IsUnitInForce(udg_unit04,udg_forces04[1])==true))then
set udg_locations01[0]=GetRectCenter(udg_rect12)
call IssuePointOrderLoc(udg_unit04,"attack",udg_locations01[0])
call RemoveLocation(udg_locations01[0])
else
set udg_locations01[0]=GetRectCenter(udg_rect13)
call IssuePointOrderLoc(udg_unit04,"attack",udg_locations01[0])
call RemoveLocation(udg_locations01[0])
endif
endif
endif
endif
endif
endfunction
set udg_trigger432=CreateTrigger()
call TriggerAddAction(udg_trigger432,function Trig_jingong_chufadanweiActions)
function Trig_bunengbeikongzhiConditions takes nothing returns boolean
return(((IsUnitSelected(GetTriggerUnit(),Player(0))==true)or(IsUnitSelected(GetTriggerUnit(),Player(1))==true)or(IsUnitSelected(GetTriggerUnit(),Player(2))==true)or(IsUnitSelected(GetTriggerUnit(),Player(3))==true)or(IsUnitSelected(GetTriggerUnit(),Player(4))==true)or(IsUnitSelected(GetTriggerUnit(),Player(5))==true)or(IsUnitSelected(GetTriggerUnit(),Player(6))==true)or(IsUnitSelected(GetTriggerUnit(),Player(7))==true))and(IsUnitType(GetTriggerUnit(),UNIT_TYPE_GIANT)==true)and((GetIssuedOrderIdBJ()==String2OrderIdBJ("stop"))or(GetIssuedOrderIdBJ()==String2OrderIdBJ("move"))or(GetIssuedOrderIdBJ()==String2OrderIdBJ("smart"))or(GetIssuedOrderIdBJ()==String2OrderIdBJ("patrol"))or(GetIssuedOrderIdBJ()==String2OrderIdBJ("AImove"))or(GetIssuedOrderIdBJ()==String2OrderIdBJ("attack"))or(GetIssuedOrderIdBJ()==String2OrderIdBJ("attackgrouned"))or(GetIssuedOrderIdBJ()==String2OrderIdBJ("attackonce"))))
endfunction
function Trig_bunengbeikongzhiActions takes nothing returns nothing
call DisableTrigger(GetTriggeringTrigger())
if((GetUnitAbilityLevelSwapped('A0AI',GetTriggerUnit())>=1))then
call SelectUnitRemoveForPlayer(GetTriggerUnit(),GetTriggerPlayer())
if((GetUnitAbilityLevelSwapped('A0AI',GetTriggerUnit())>=8))then
if((IsUnitInForce(GetTriggerUnit(),udg_forces04[1])==true))then
call SetUnitOwner(GetTriggerUnit(),Player(bj_PLAYER_NEUTRAL_VICTIM),false)
else
call SetUnitOwner(GetTriggerUnit(),Player(bj_PLAYER_NEUTRAL_EXTRA),false)
endif
else
endif
else
endif
if((GetUnitAbilityLevelSwapped('A0AI',GetTriggerUnit())==0))then
call UnitAddAbilityBJ('A0AI',GetTriggerUnit())
else
call IncUnitAbilityLevelSwapped('A0AI',GetTriggerUnit())
endif
call TriggerExecute(udg_trigger432)
call EnableTrigger(GetTriggeringTrigger())
endfunction
set udg_trigger420=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(udg_trigger420,EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
call TriggerRegisterAnyUnitEventBJ(udg_trigger420,EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
call TriggerRegisterAnyUnitEventBJ(udg_trigger420,EVENT_PLAYER_UNIT_ISSUED_ORDER)
call TriggerAddCondition(udg_trigger420,Condition(function Trig_bunengbeikongzhiConditions))
мы могли взять и выделить юнита, и потом дать какой-нибудь order. Но не выполняет его, и с него снимается выборка.
в этой карте ловится приказ, и его перебивают. там самая простая реализация. У любой тд-шки нам не нужно запоминать приказ, просто отдай снова приказ в точку, и он туда пойдет. (даже когда застрянет)
Тоже не знал. Предположил что в приказах. Взломал карту, решил поискать события на приказы. Но к удивлени, их оказалось не много, 4 события. нашел куски кода, собрал воедино код. были сомнения, поэтому для проверки я удалил в этом куске кода (см. код выше) - события приказов, теперь они не запускаются, и как вследствие, ими можно управлять
скидываю 2 карты, одну взломанную и измененную, и оригинал
если бы идея была бы сложнее, скажем, запоминать все приказы и цели, это было бы сложнее. а тут мы знаем, что юнит бежит к точке 1 (запоминаем 1). Тут все просто.
у юнита не отображаются на панеле команды - норм, видимо там классификация "страж" дана, не видел никакого импорта типа текстовика, координаты.
Ну тут мало информации, что у вас за карта такая?
RPG - часто это жанр, в котором персонаж живет в своем мире. Где обычно присутствуют сюжет, квесты и прочее. Персонаж бегает по карте и пытается пройти игру, в этом то и смысл. Мб ошибаюсь. ссылка
Hero-Arena - герой, который участвует в дуэли с другими героями противников на арене.
Hero Defense - карта, в которой надо охранять героем от нападения орды крипов.
AOS (Aeon of Strife) - то же самая дота. от базы до базы.
Survival (в выживалке бывает один герой бегает и ему приходится выживать)
cast animation - полная анимация включающая в себя каст поинт и бэксвинг.
cast point - время необходимое для каста спелла или атаки
cast backswing - любая анимация после применения скилла. Например, опускание рук Лины после задувки 1-м скиллом или опускание лука дровкой после автоатаки. Ее можно отменить (не завершить эту анимацию, перебив другой анимой), если юнит получает другой приказ
тфу попутал с анимацией точки обратного хода и анимацией точки повреждения с анимация: обратный ход броска и анимация: точка броска
про анимацию точки обратного хода и точки поврежденияне знаю точно, сам не тестил эти два поля. См. выше ответ Факова и по ссылке, сравни, потести. Знаю, что можно поставить ноль, для быстрого воспроизведения каста даймика (например). Кто-то писал что Если у юнита поставить Art - Animation - Cast Backswing и Art - Animation - Cast Pint на 0, то он при касте не будет останавливаться чтобы воспроизвести аниму (те же Рёв и Провокация).
про автонаведениеэто есть у волшебниц и целителей хуманов. У эльфийских лучниц этого в параметре не стоит галочка. И летает прямо, снаряд промахивается, но урон все равно получает противник. Есть поставить галочку, то снаряд летает за противником.
Показать UI - вроде кнопка атаки пропадает при снятии галочки, если не ошибаюсь
урон (эффект от улучшения) - наскока будет у тебя улучшаться при завершении исследования. С каждым исследованием, у тебя будет улучшаться на заданное число.
урон кол-во граней и урон кол-во костей - можно найти в FAQпункт 4.2
native GetTerrainType takes real x, real y returns integer
или в моей карте делал через регион, в нее добавлял области. При чем области в разных местах могут быть. В моей карте идет обработка почвы (типа копание грядки в веселой ферме, квадратики), и потом циклом проверяешь. И GetTerrainType не всегда помогает понять, что этот участок уже обработан. Поэтому на помощь идут регионы, точнее мне достаточно одного региона, и одной вспомогательной области.
native IsPointInRegion takes region whichRegion, real x, real y returns boolean
native IsUnitInRegion takes region whichRegion, unit whichUnit returns boolean
например, выбираю участок областью Rect, задаю размеры, координаты и все такое. И потом этот участок добавляю в регион. могу несколько областей в регион добавить.
native RegionAddRect takes region whichRegion, rect r returns nothing
или чистить. точнее удалять этот участок из региона
native RegionClearRect takes region whichRegion, rect r returns nothing
раскрыть
В моей карте создание тайлов, терраина terrain сопровождается неприятным смещением. Как выяснил, он смещается центр таила на пересечении линии больших квадратиков, а в самих триггерах
я бы попробовал через гетлокалплеер затестил бы. попробовал бы через строку ввести разные тексты задании, и всунуть в задание. попробовать. но нужен напарник, и лень чутка, редактор открывать надо эх. не знаю так можно ли? получается когда ты квест создаешь, он всем создается?
Globder, судя по скрину ты не понял для чего нужны локалки. Их удобство в том, что создаются (объявляются) каждый раз новые, и работают в определенной области - внутри функции. В отличии от глобалок их невозможно переписать где-то вне функции. Лучше использовать где есть задержки, как показано здесь. Короче в мультиплеере полезны.
примеры
вот тема 1аргументы функции тоже являются локалками, и их обнулять не нужно
Приведу еще один пример с аргументами, не обязательно объявлять локалку, можно брать аргумент и что-то делать, правда аргумент перезапишется
раскрыть
function A takes integer i returns nothing
set i = 10 //видите, взял аргумент и присвоил новое значение
endfunction
тема 2примеры работы локалок
вот тема 3хотя локалки советуют использовать в динамических триггерах. Кстати, у меня бывала ситуация, писал наработку для новичков на гуи, но у меня она не работала. Тысячу раз перепроверил. Короче конвентировал в код, сократил добавил, локалки - у меня заработало. Тут неизвестно чего. Просто на jass наиболее читаемо, чем на гуи с ветвлениями и не работой чего-то там.
список локалокдля новичков, есть jngp там можно посмотреть. или взять в гуи триггерную комманду конвентировать в код
эффекты горения можно убрать, удаляя нужную способность или бафф раздел пустышки
но все равно это не выход.
И кстати, есть же разница между строительством и ремонтом. У работника есть ремонтно-строительные способности, они вот отвечают за это. В первый раз идет строительство, а если здание покоцано ремонт. раздел строительство У этих способностей указано как быстро строится здание, сколько ресурсов уходит.
Ну можно даймиком попробовать поставить, и тут же удалить. если нужно узнать строителя, то узнается через событие "юнит отдал приказ на цель". Есть карты вот тема вот карта
выяснил, что строителя вполне реально вычислить по приказам. получается, что приказ на цель выводится только тогда, когда здание поставил.
ну или то что PyCCKuu_4eJlпредложил
сделал в 12 версии ошибку, не заметил. Там с обычными рунами, и кое-что еще. кстати, еще вот такое нашел благодаря Факову тема - хотя это мне никак не помогло, у меня другое
Теперь не нужно всем писать, а только предметам с зарядами или с рунами. В остальных случаях вернет 0 (или 1).
код
// функция SaveR2I
// Сохраняем id копии по id оригинала (короче идишник оригинала - ключ. Из нее будем доставать нужный тип копии).
// Если итем не имеет копии, то вернет 0. Значит вернет id оригинал.
// Определяет какой тип итема будет создан в ячейке магазина (руна или оригинал). Если копии нет, то будет создан оригинал.
function SaveR2I takes integer original, integer rune returns nothing
call SaveInteger(udg_Hash, original, 66, rune) //66 - в качестве ключа
endfunction
// функция SaveR2Icharges
// Сохраняет связь id оригинала с id-копиями. Делано для сокращения части кода.
// У итемов с зарядами могут быть несколько копии, связано это с ценами.
// У зарядов есть своя цена, в инвентаре героя 1 заряд может стоить 50 золота, 2 заряда 100, 3 заряда 150.
// В магазине заряды никак не связаны с ценой, тут она всегда одна, постоянна. 1 заряд или 2 заряда = всегда будут стоить 50 золота
// В варкрафте у предметов есть такое поле "Характеристика - количество зарядов". При покупке или создании в инвентаре героя создается это число зарядов.
// Но в магазине снимается 1 стэк (лучше правильно его так называть, а не заряд), а не указанное число. Он может перезаряжаться.
// Было придумано так, что покупаешь указанное число зарядов. И с магазина это число снимается.
// Чтобы было понятно, у меня система такая как если покупаешь упаковку конфет или пояс гранат (стэки), внутри определенное число конфет или гранат (заряды).
//Если у заложенного итема count_charges > кол-во зарядов в РО, то ставить самый максимальный ценник. Иначе ставим требуемый.
// Для красоты добавляется несколько копии с разными ценами, и разным число указанных в "Редакторе Объектов" зарядов. При продаже наследуют charge.
// ВАЖНО: для правильной записи необходимо чтобы равкоды копии, заряды на одну единичку +1 отличались (и цены тоже)
function SaveR2Icharges takes integer original, integer rune, integer start_charges returns nothing
local integer i = 0
loop
exitwhen i == start_charges
call SaveInteger(udg_Hash, rune+i, 666, original) //Нужно связать ценники с одним типом. Это нужно для проверки, что занят ли он в магазине, также возвращает тип оригинала.
call SaveInteger(udg_Hash, original, 100 + i+1, rune + i )
//call BJDebugMsg( "i: " + I2S(i) )
set i = i + 1
endloop
call SaveInteger(udg_Hash, udg_ChargesTypeOfItem, original, start_charges)
endfunction
function Trig_data_Actions takes nothing returns nothing
call TriggerSleepAction( 2 )
//SaveR2I(original, rune)
call SaveR2I('I000', 'I004') //рецепт когти воина
call SaveR2I('I001', 'I005') //боевые когти
call SaveR2I('I002', 'I006') //туфли ловкости
//SaveR2Icharges(original, rune, charge)
call SaveR2Icharges('wild', 'I007', 1) //амулет леса х1 заряд
call SaveR2Icharges('whwd', 'I008', 3) //духи-целители х3 заряда I008-I009-I00:
call SaveR2Icharges('wlsd', 'I00;', 3) //жезл-молнии x3 заряда I00; - I00< - I00=
endfunction
//===========================================================================
function InitTrig_data takes nothing returns nothing
set gg_trg_data = CreateTrigger( )
call TriggerAddAction( gg_trg_data, function Trig_data_Actions )
endfunction
триггер PawnItem
// функция LoadR2I
// Загружает из хэш-таблицы id руны с помощью ключа original, где записан id подлинного итема.
// Определяет какой тип итема будет создан в ячейке магазина (руна или оригинал). Если копии нет, то будет создан оригинал.
function LoadR2I takes integer original returns integer
return LoadInteger(udg_Hash, original, 66) //66 - в качестве ключа
endfunction
function LoadTypeRune takes item it, integer charges returns integer
//local integer id_market = GetHandleId(market)
local integer id_item = GetItemTypeId(it) //продаем предмет-оригинал
local integer k = LoadInteger(udg_Hash, udg_ChargesTypeOfItem, id_item) //кол-во зарядов в одном стэке, или кол-во ценников
//local integer stock = LoadInteger(udg_Hash, id_market, id_item)
local integer ID
if GetItemType(it) == ITEM_TYPE_CHARGED then
if charges >= k then
set ID = LoadInteger(udg_Hash, id_item, 100 + k )
elseif charges < k then
set ID = LoadInteger(udg_Hash, id_item, 100 + charges )
endif
else
set ID = LoadR2I(id_item)
if ID == 0 then
set ID = id_item
endif
endif
return ID
endfunction
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 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 = GetItemTypeId(GetSoldItem()) //тип итема = продаем итем-оригинал
local integer id_rune //тип руны - это то, что закладываем в магазин. Если копии нет, вернет оригинал id_item
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) )
//достаем номер ячейки (достаем по id оригинала, так как удобнее)
set a = LoadInteger( udg_Hash, id_market, udg_NumberTypeItems + id_item )
//должны достать идишник будущей копии (у зарядных айтемов несколько копии, поэтому может достать одну из них. У обычных либо одна копия, либо вообще нет копии, вернет оригинал)
set id_rune = LoadTypeRune(GetSoldItem(), max_stock)
//обязательно должны удалить с рынка данный тип, иначе на него не сохранится ссылка, так как на этот номер, на эту ячейку перезапишут новый идишник
call RemoveItemFromStock( market, LoadInteger( udg_Hash, id_market, udg_TypeOfItem + a ))
//пересохраняем типы итема (сохраняем по номеру ячейки, потом перебирать будем)
call SaveInteger( udg_Hash, id_market, (udg_TypeOfItem+a), id_rune )
// сохраняем стэк в хэш (сохраняем по id оригинала - id_item)
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")
//должны достать идишник будущей копии (у зарядных айтемов несколько копии, поэтому может достать одну из них. У обычных либо одна копия, либо вообще нет копии, вернет оригинал)
set id_rune = LoadTypeRune(GetSoldItem(), charges)
//сохраняем какой-тип сохраняем (сохраняем по номеру ячейки, потом перебирать будем)
call SaveInteger( udg_Hash, id_market, udg_TypeOfItem + count, id_rune )
if id_item != id_rune and id_rune > 0 then
call BJDebugMsg( "тип руны: " + I2S(id_rune))
elseif id_rune == 0 then
call BJDebugMsg( "У этого типа нет руны. Тип руны = 0")
endif
// сохранить кол-во стэков предмета в магазине
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
set i = 0
// удаляем все итемы из магазина
loop
exitwhen i > 12
set id_rune = LoadInteger( udg_Hash, id_market, udg_TypeOfItem + i ) //загружаем ид руны и перебираем по номеру ячеек i
call RemoveItemFromStock( market, id_rune)
set i = i+1
endloop
set a = 0
set i = 0
// добавляем все итемы обратно
loop
exitwhen i > count
set id_rune = LoadInteger( udg_Hash, id_market, udg_TypeOfItem + i ) //загружаем ид руны и перебираем по номеру ячеек i
if id_rune > 0 then //проверяем, что ячейка магазина не пустует (взята переменная id_rune для работы в цикле пусть вас не путает и не смущает что здесь руна должна быть. здесь мб и оригинал)
set a = a + 1 //новый номер ячейки (короче новый порядок)
set id_item = SelectItem(id_rune) //достаем идишник оригинала (так как заряды сохранены по ид оригинала)
set stock = LoadInteger(udg_Hash, id_market, id_item) //загружаем заряды оригинала
call BJDebugMsg( "заряды stock: " + I2S(stock))
call SaveInteger( udg_Hash, id_market, (udg_TypeOfItem+a), id_rune ) //пересохраняем идишник на новый слот
call SaveInteger( udg_Hash, id_market, udg_NumberTypeItems + id_item, a ) //сохраняем по типу номер слота
call AddItemToStock( market, id_rune, 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
function SelectItem takes integer id_rune returns integer
local integer id = LoadInteger(udg_Hash, id_rune , 666)
if id == 0 then
set id = LoadInteger(udg_Hash, id_rune , 66)
if id == 0 then
set id = id_rune
endif
endif
return id
endfunction
function TypeOfItems2 takes item rune returns integer
//local integer id_market = GetHandleId(market) //ид магазина
local integer id_item = LoadInteger(udg_Hash, GetItemTypeId(rune), 666) //загружаем идишник оригинала от зарядовых
if id_item == 0 then //Если ничего не записано, вернет 0. Значит, ничего в базе данных не записано. Типа это не зарядовые итемы. Ищем следующие
set id_item = LoadR2I(id_item) //загружаем идишник оригинала от обычной руны
if id_item == 0 then //Если опять вернет ноль, значит это обычный итем
set id_item = GetItemTypeId(rune)
endif
endif
return id_item
endfunction
function ChargesTypeOfItem takes integer id_item returns integer
local integer k = LoadInteger(udg_Hash, udg_ChargesTypeOfItem, id_item)
if k <= 0 then
set k = 1 //если ничего не записано, то вернет ноль. значит надо записать 1. Так как беззарядовых быть не может, иначе из магазина не снять будет стэк
endif
return k
endfunction
function Trig_SellItem_Actions takes nothing returns nothing
local unit market = GetSellingUnit()
local integer id_market = GetHandleId(market) // номер хэндла магазина
local integer id_rune = GetItemTypeId(GetSoldItem()) //тип итема (или копии), ведь в магазинах могут быть изначально заложены копии. Если копии нет, то там будет оригинал.
local integer id_item = TypeOfItems2(GetSoldItem())//нам нужен ид оригинал, так как на него записаны многие вещи
local integer charges = 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" )
if stock>charges then
set min_stock = stock - charges
else//if LoadInteger(udg_Hash, udg_ChargesTypeOfItem, id_item) > 0 then
set min_stock = stock - stock //ModuloInteger(stock, charges)
//call SetItemCharges(GetSoldItem(), stock) //подправляем на нужное число зарядов. А то выдает указанное кол-во зарядов в РО. Если в магазине заряда становится на 1 меньше, то при создании выдает указанное кол-во в РО
endif
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 a = LoadInteger( udg_Hash, id_market, udg_NumberTypeItems + id_item )
set key2 = (udg_TypeOfItem+a)
//в базу пишем, что такого типа нет
call SaveInteger( udg_Hash, id_market, key2, 0 ) //хранится здесь тип, пересохраняем тип итема, сохраняем то, что такого типа нет = 0
call SaveBoolean( udg_Hash, id_market, key1, false ) // запоминаем в хэш что данного типа предмета больше нет (типа не занят)
// проверяем ячейки магазина
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 //если произошли изменения с кол-вом стэков (стало или больше или меньше), то изменяем число
//достаем номер ячейки
set a = LoadInteger( udg_Hash, id_market, udg_NumberTypeItems + id_item )
//обязательно должны удалить с рынка данный тип, иначе на него не сохранится ссылка, так как на этот номер, на эту ячейку перезапишут новый идишник
call RemoveItemFromStock( market, LoadInteger( udg_Hash, id_market, udg_TypeOfItem + a ))
//должны достать новый идишник будущей копии (если это зарядовый)
set id_rune = LoadTypeRune(GetSoldItem(), min_stock) //+1
//пересохраняем типы
call SaveInteger( udg_Hash, id_market, (udg_TypeOfItem+a), id_rune )
// сохраняем кол-во занимаемых ячеек
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
set a = 0
// добавляем все итемы обратно
loop
exitwhen i>count_items
set id_rune = LoadInteger( udg_Hash, id_market, (udg_TypeOfItem+i) ) //загружаем ид руны и перебираем по номеру ячеек i
if id_rune > 0 then //проверяем, что ячейка магазина не пустует
set a = a + 1 //новый номер ячейки (короче новый порядок)
set id_item = SelectItem(id_rune) //достаем идишник оригинала (так как заряды сохранены по ид оригинала)
set stock = LoadInteger(udg_Hash, id_market, id_item) //загружаем заряды оригинала
call SaveInteger( udg_Hash, id_market, (udg_TypeOfItem+a),id_rune ) //пересохраняем идишник на новый слот
call SaveInteger( udg_Hash, id_market, udg_NumberTypeItems + id_item, a ) //сохраняем новый номер слота по идишнику
//if SaveInteger(udg_Hash, udg_ChargesTypeOfItem, 'whwd', 3)
call AddItemToStock( market, id_rune, stock+1, 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
требуется
Внимание: при работе с зарядами базу данных заполняете так:
call SaveR2Icharges('whwd', 'I008', 3) духи-целители х3 заряда I008-I009-I00: SaveR2Icharges(original, rune, charges)
original - итем с зарядами, у него указано кол-во зарядов charges
rune - первая руна, у вас должен быть равкод забит заранее, например:
I008-первая руна I009- вторая руна I00: - третья руна
В остальном ничего сложного нет. Я уже третий раз расписываюсь. В карте написано все.
Казалось бы проще сделать: добавил или удалил. Что тут такого сложного? Но возникали баги.
Возможные баги:
Часто имеет свойство пропадать. При повторном добавлении итемы могли исчезать с рынка. Баг описан и иллюстрирован картинками в этой теме. Пришлось по-другому доделывать - запоминать все айтемы в хэше, и при каждом изменении (добавлении/удалении) сначала все ячейки вычищаешь, а потом заново добавляешь.
В некоторых предметах бывает не правильно складывают/убывают итемы. Например, возьмем, стандартный "Кинжал мага"
пример
Подбираю 3 кинжала
Продаю 2 кинжала, в магазине 2 заряда
Затем заново покупаю обратно 1 кинжал, должно быть остаться 1. Но нам показывает дебаг, что остался 1 заряд. Но в магазине ничего не остается, итем уходит в кулдаун. У меня даже код построен так, что должен очистить все (удалить все итемы), а потом заново вернуть (добавить итемы). А как видим, даже после такого кулдаун не спадает...
Или не стоит у итема не то значение после покупки.
Например, продал 9 зарядов духов-целителей. В магазине стало 9 зарядов.
Нажал, и в результате купил +3. Должно остаться +6, даже счетчик дебагом показывает +6. Но в магазине стало +5.
Вывод: Все это происходит из-за поля "Интервал пополнения".
Во избежания такой фигни рекомендую в продаваемых итемах ставить 0 в поле "интервал пополнения". С чем это связано, мне неизвестно.
Предположение: Короче как видим, кулдаун забирает единицу. Допустим, в магазине +5, покупаешь 2, в магазине должно остаться 3. Но кулдаун забирает 1, и остается 2. Но это предположение, не тестил пока
Это база данных. Третий пункт - это не баг, а ошибка, с которой можете столкнуться вы. Мы заранее составляем базу данных. Дело в том, что в базе данных может быть отсутствует какой-нибудь идишник, и поэтому в игре в магазине не создается итем. Поэтому будьте внимательны.
Дело в том, что у меня так база данных построена, код написан. А то логически в начале написал правильно, потом целый день не мог понять в чем дело.
Покажу пример, который допустил я:
зарядный итем
I008-итем с 1 зарядом цена 200
I009-итем с 2 зарядом цена 400
I00A-итем с 3 зарядом цена 600
казалось бы все правильно, равкод числа на одну единицу меньше. Но как оказалось, где-то допустил ошибку. Берем любой онлайн-калькулятор ASCII , и переводим 10-чную систему, проверяя насколько отличается.
I008=1227894840
I009=1227894841
I00A=1227894849 Тут отличается на целых 8 знаков, короче сбивается база данных
Давайте проверим что же под номером 1227894842 скрывается
1227894842=I00: не удивляйтесь, двоеточие - это тоже символ, в 256-ричной системе по-другому номеруются символы. Просто варкрафт не хочет вписывать этот символ, но мы можем вписать.
Беру копирую итем I00A, и в jngp выскакивает окошко Create Object, и туда копируете 'I00:'
можно паффинг отключить триггерно у наземного, и он ходит по дну
находил и скачивал похожие, но к сожалению не сохранилось, и не помню как. это надо протестить, но лень.
-> в массив предмет добавляется для того чтоб пока за этим предметом следуют на него не переключались другие юниты?
ну пометку boolean добавляют по handle item (когда перебираешь ближайшим итем, надо проверять и метки). когда на карте 10 артефактов, а все стадо идет за одним ^_^
еще можно ссылку в виде item по handle unit, если юнит сдохнет получит или другой приказ, метку с итема можно смело удалять.
периодически проверяем, что мобы не стоят
если триггером добавляется на карте итем, в группе циклом перебираем и ищем ближайших итемов. заново ищем. это если вдруг бежит раб, и внезапно перед носом появляется, а он бежит дальше
заметил, что не всегда ловит приказы IssuedOrder. Например, что вот отдал приказ продать в магазин, мне приказ IssuedOrder не выдаст.
А вот GetUnitCurrentOrder() выдает order_dropitem = 852001, когда юнит бежит к магазину, чтобы продать. Это как пример. Не надежный, надо еще проверять и координаты. Это что, таймером перебирать собрались группу?
Ред. MpW
» WarCraft 3 / Как на одну стандартную модель нацепить разные текстуры?
хорош пункт 2, и пункт 6 (но надо понять как сделать самому в модделинг-редакторе, ничего не соображаю на какие кнопки там нажимать. Вроде во 2 пункте все расписано. Щас попробую)
Ред. MpW
» WarCraft 3 / Jass New Gen Pack - Rebuild 1.4
короче поискал на сайте, и везде перессылки на эту страничку. А эта сборка не работает. =( Мне помогла старая сборка, которая хорошо что сохранилась (5d не сохранилась, но вот JNGP_R1.3_COMPAT осталась, хорошо что не удалил). другую сборку было не найти
Ред. MpW
» WarCraft 3 / Юнит и принадлежность
в этой карте ловится приказ, и его перебивают. там самая простая реализация. У любой тд-шки нам не нужно запоминать приказ, просто отдай снова приказ в точку, и он туда пойдет. (даже когда застрянет)
скидываю 2 карты, одну взломанную и измененную, и оригинал
у юнита не отображаются на панеле команды - норм, видимо там классификация "страж" дана, не видел никакого импорта типа текстовика, координаты.
Ред. MpW
» WarCraft 3 / Как назывется тип карты где играешь только героем?
RPG - часто это жанр, в котором персонаж живет в своем мире. Где обычно присутствуют сюжет, квесты и прочее. Персонаж бегает по карте и пытается пройти игру, в этом то и смысл. Мб ошибаюсь. ссылка
Hero-Arena - герой, который участвует в дуэли с другими героями противников на арене.
Hero Defense - карта, в которой надо охранять героем от нападения орды крипов.
AOS (Aeon of Strife) - то же самая дота. от базы до базы.
Survival (в выживалке бывает один герой бегает и ему приходится выживать)
Ред. MpW
» WarCraft 3 / Графика - Сдвиг окна
» WarCraft 3 / Хак на память Warcraft3
так понимаю, на пассивках это работать не будет. критует.
вот сделал систему когда прибавляет при убийстве blademaster-ом
» WarCraft 3 / Хак на память Warcraft3
вот карта
» WarCraft 3 / WC3RusTextOptimizer
Ред. MpW
» WarCraft 3 / Преобразовать подстроку в реальное
используй логику - сравнение реальных чисел
в таймер вводят только секунды
» WarCraft 3 / Преобразовать подстроку в реальное
Ред. MpW
» WarCraft 3 / Есть ли объяснение каждого параметра в редакторе объектов?
» Кузня Волчачки / Отзыв: Серебряная душа [Аниме]
Ред. MpW
» WarCraft 3 / Есть ли объяснение каждого параметра в редакторе объектов?
Ред. MpW
» WarCraft 3 / Что бы юнит мог проходить сквозь других юнитов?
Ред. MpW
» WarCraft 3 / Что бы юнит мог проходить сквозь других юнитов?
Ред. MpW
» WarCraft 3 / Лава
Ред. MpW
» Государь / Государь
» WarCraft 3 / Выборка конуса
Ред. MpW
» WarCraft 3 / 2-3. Локальные переменные
вот тема 3 хотя локалки советуют использовать в динамических триггерах. Кстати, у меня бывала ситуация, писал наработку для новичков на гуи, но у меня она не работала. Тысячу раз перепроверил. Короче конвентировал в код, сократил добавил, локалки - у меня заработало. Тут неизвестно чего. Просто на jass наиболее читаемо, чем на гуи с ветвлениями и не работой чего-то там.
» WarCraft 3 / триггер
но все равно это не выход.
И кстати, есть же разница между строительством и ремонтом. У работника есть ремонтно-строительные способности, они вот отвечают за это. В первый раз идет строительство, а если здание покоцано ремонт. раздел строительство У этих способностей указано как быстро строится здание, сколько ресурсов уходит.
Ну можно даймиком попробовать поставить, и тут же удалить. если нужно узнать строителя, то узнается через событие "юнит отдал приказ на цель". Есть карты
вот тема
вот карта
выяснил, что строителя вполне реально вычислить по приказам. получается, что приказ на цель выводится только тогда, когда здание поставил.
ну или то что PyCCKuu_4eJlпредложил
Ред. MpW
» WarCraft 3 / Система рынка (продажа и покупка итемов)
13 версия
кстати, еще вот такое нашел благодаря Факову тема - хотя это мне никак не помогло, у меня другое
Ред. MpW
» WarCraft 3 / Система рынка (продажа и покупка итемов)
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:'
» WarCraft 3 / Как ходить по дну?
находил и скачивал похожие, но к сожалению не сохранилось, и не помню как. это надо протестить, но лень.
https://www.xgm.guru/forum/showthread.php?t=43910
Ред. MpW
» WarCraft 3 / Отлов цели приказа
Ред. MpW
» WarCraft 3 / Отлов цели приказа
А вот GetUnitCurrentOrder() выдает order_dropitem = 852001, когда юнит бежит к магазину, чтобы продать. Это как пример. Не надежный, надо еще проверять и координаты. Это что, таймером перебирать собрались группу?