local unit u = ... //герой
local integer Tp = GetUnitTypeId(u) //тип героя, точнее id или rawcode (это все целое число)
local integer LVHero = GetHeroLevel(u) //уровень героя
local integer ExHero = GetHeroXP(u) //опыт героя
local integer SP = GetHeroSkillPoints(u) //кол-во скилл-поинтов
local integer St = GetHeroStr(u, false) //стандартная сила (эта вся сила, исключая бонусы на нее)
local integer Ag = GetHeroAgi(u, false) //стандартная ловкость (эта вся ловкость, исключая бонусы на нее)
local integer In = GetHeroInt(u, false) //станд. интеллект (эта весь разум, исключая бонусы)
//для вычисления бонусных характеристик - не забудьте снять все итемы
local integer StB = GetHeroStr(u, true) - St //бонусная сила (разница короче с бонусной и не с бонусной)
local integer AgB = GetHeroAgi(u, true) - Ag //бонусная ловкость
local integer InB = GetHeroInt(u, true) - In //бонусный интеллект
local integer gold = GetPlayerState(GetOwningPlayer(u), PLAYER_STATE_RESOURCE_GOLD) //золото
local integer wood = GetPlayerState(GetOwningPlayer(u), PLAYER_STATE_RESOURCE_LUMBER) //древесина, лес
это все выше перечисленное сохраняем в кэш
для предметов
тут по слотам пробегаемся и все
local unit u = ... //герой
local integer i = 0 //для цикла
local integer s = UnitInventorySize(u) //максимальный размер слота
local item It
local boolean b
local integer idIt
loop
exitwhen i > s
set It = UnitItemInSlot(u, i) //итем в слоте
set b = (It != null) //проверяем, не пуст ли слот героя и сохраняем в булеан
set = GetItemTypeId(It) //id итем
//все сохраняем (номер слота, булеан, ид-итема), при загрузке достаем булеан и проверяем не пуста ли и потом создаем итем
//для создания в нужный слот используйте эту нативку UnitAddItemToSlotById
set i = i + 1
endloop
насчет способностей
Насчет способностей сложнее, приходится запоминать какие у героя есть способности. То есть какие могут быть абилки (равкоды) у данного типа героя.
Короче либо базу данных делать (у.героя по стандарту 4 абилки)
local integer rawcodeA = 'A000'
local integer LVS = GetUnitAbilityLevel(u, rawcodeA)
или сделать триггер, который ловит какие скиллы вы изучаете
систему лень писать, ибо много чего нужно сделать. Еще нужно сгенерировать случайный код и прочее. Сложностей много.
Artyom18, можно. только обычным не откроешь, а нужно скачать jngp и включить плагин USM. Этот плагин предоставляет новые гуишные функции (огромный набор) и много чего другого. Вообще-то это все есть на jass и можно было без этого плагина, но специально для гуишников предоставили функции. Походу у автора где-то используется нестандартная гуишная команда, и обычный редактор ее не распознает.
пример
Давно когда начинал. Я пытался сделать итем Power Threads из доты. там простая подмена. используется обычная нативка. Она есть в варкрафте 3, но в гуишном варианте не отображается. А если включишь плагин, то тебе даст эту нативку в гуи. Станд. редактор не видит это и поэтому закрывает карту
Есть допустим темы по варкрафту. Например, заклинания/иконки на заказ. Чтобы под сообщением заказа были прикреплены ответы (видел такое на других сайтах). Я думаю это классной идеей, чем листать n-количество страниц в поисках ответа. И приятно на глаз, чем видеть такое
это мое предположения, хотя этими разделами никто не пользуется, наверное
Вторая проблема - это нехватка наработок и интересных фитч. Хайв в этом плане интереснее, больше скилов триггерных и наработок с картинками (изображения отображают в мозгу какой это скилл и тд). У вас они разбросаны по всему сайту и форуму. Кстати я недавно нашел страничку, где было в ней кучу ссылок на наработки, алгоритмы и др.
если ты читал статью, то знаешь имеешь представление о том, что такое локальная переменная и в чем разница между глобальной переменной. И область их применения.
Kolya12, вот допустим есть два одинаковых юнитов с одинаковыми абилками. Один юнит принадлежит тебе, второй другому игроку. Ты применяешь скилл, который вешает эффект на 15 секунд. После чего должен удалиться эффект. Эффект нужно где-то сохранить, верно? И юнита, на которого повесили эффект, также нужно сохранить. Проще говоря нужны ссылки. нужно на что-то ссылать. Все переменные - это ссылки на объекты. Так вот, если вдруг другой игрок в это время возьмет и применит скилл, и перезапишет глобалки на юнита, и на эффект. Чтобы этого не было существуют локалки.
На самом деле локалки действуют внутри функции, это их недостаток (в гуи вообще не применимо, там часто будет вызов других функции). Внутри функции можно только с вэйтами поиграть. работает норм. Но, если вызвать отдельную функцию локалки не помогут, нужно с помощью глобалок переносить на другие функции или использовать аргументы функции. Ты берешь ссылку юнита и переносишь на другой триггер, где периодично что-то делает с ней (возможно там где-то по случайности переписали ее).
Есть проблема во времени, если будет задержка, то глобалки можно перезапить за это время. И в игре нарушится все. Нормально локалки работают с вэйтами внутри функции. Но, если хочется сделать что-то большое, например, каждую секунду наносить урон от лица юнита. То тут нужен таймер или триггер с периодичным таймером. Тут локалки не помогут. И кстати вэйт работает дольше указанного.
Если взять и создать несколько юнитов, и попробовать взять всех их заставить запустить одновременно одну способность. То тут выяснится, что триггер не выполняет параллельно, а последовательно. Можно проверить дебагом. Короче триггер выполняет поочередно, и мгновенное, если нет никаких временных задержек между ними. Может быть и есть исключение, но не проверял (например на ExecuteFunc). Проще говоря, локи не обязательны, не понятно зачем они нужны (но мне они нужны для удобства, еще плюсы в них есть), можно всю игру юзать глобалки (темповые глобалки, короче временные ссылки). На самом деле нужно посмотреть как используют МУИ (там используют массивы, для каждого потока можно создавать свой массив, например есть счетчик потока GetTriggerExecCount xgm.guru/p/wc3/184282 или использовать переменную в качестве счетчика).
Допустим, если два юнита запускают одновременно один скилл. Он обработает сначало первый запуск триггера, потом второй запуск. Короче два потока запускает последовательно. Но, если в триггере написано что между частями триггера есть вэйт, то пропустит и запустит следующий поток. То есть, первый поток остановится на паузу из-за вэйта, игра решит не ждать, и запустит следующий поток.
Кстати говоря, аргументы (параметры) функции - это тоже локальные переменные. Где-то прочел.
Представь, идет действие - потом какая задержка во времени (вэйтом или таймером) - затем продолжение триггера. Если во время задержки перезаписали ссылки. то все. Нужно делать так, чтобы не пересекались ссылки между собой. Для этого существует МУИ, хэш-таблица + хэндлы + локалки.
тут просто сложная система у тебя, так нагорожена и запутано. Я убрал лишнее и написал на jass. косяк в том, что между триггерами Jump и JumpFlyLoop есть ссылка (переменная), которую, видимо, перезаписывают. Также повторное использование другим юнитом перезапишет в Jump еще раз. Твои триггеры сложно было читать, все эти манипуляции локалками-глобалки, и наоборот, только путают. Где то в этих манипуляциях ты ошибся, раз не хотят опускать на землю. По логике их должно опустить после опр. времени (это после вэйта в Jump). Посмотрел бы как делаются прыжки на сайте. на хайве. Хотел недавно найти прыжок самурая-орка, когда в прыжке анимацию проигрывает, и показывает. что рубит сверху. Красиво сделано. Но не нашел (придеться самому делать), все время попадаются уродливые прыжки, особенно как у тебя (извини не хотел обидеть, просто прыжок не выглядит настоящим, реальным). гуи и муи много попадались.
жалуется редактор на JumpSecPoint, неправильно написали где-то название переменной вот и ошибка. То есть такая переменная не существует и игра не распознает ее. Подсказка: ошибка в триггере JumpFlyLoop убрал эту переменную, теперь указывается ошибку на другую строчку. Убрал, на еще одну. где-то с третьей попытки запустилось
ошибка локальные переменные объявляются всегда первыми. Если там будет какое-то другое действие, а объявление локалок ниже, то это ошибка. Ты вперед поставил действие "включить триггер ...", а потом начал объявлять локи
во-втором скрине там ты не объявил. Там на каждую функцию надо объявлять новые локальные переменные. то есть локалка работает внутри функции (конвентируй и посмотри как там устроено), в других функциях эта переменная не работает, ее не существует (короче область действия своя у локалки, вначале она объявляется, в конце блока функции перестает работать). вот пишешь: "set u = GetTriggerUnit()", но эта переменную игра может не распознать, так как не существует, даже, если она объявлена в другой функции (в другом триггере или где-то там еще) там другая локалка, хотя имена одинаковы. Во-втором скрине ты заново объяви
Doc, если бы локалку целочисленную объявил в начале и засунул хэндл, то можно было менять местами как хочешь? это можно проверить, сохранить что-нибудь в хэше и потом проверить дебагом
код
local timer t = GetExpiredTimer()
local integer id = GetHandleId(t)
//и потом мог бы и вот так
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(udg_Hash,id)
set t = null
первый скрин - это что-то с библиотекой. Скидывай карту.
со вторым ты не правильно делаешь, видимо ты новичок. надо статьи прочитать. Ты просто с локалками что-то не то делаешь, надо через CS прописывать, просто гуи не видит локи. xgm.guru/p/wc3/jass_local_vars Но я не сторонник слать, ибо нет норм статьи у нас "как превратить из новичка в jassера".
то что ты делаешь с локалками
я конвентировал в код
есть локалка JumpCaster и есть глобалка udg_JumpCaster - это две разные вещи
function Trig_Jump______________________2_Actions takes nothing returns nothing
//локалки
local unit JumpCaster
local location JumpCasterPoint
local location JumpTargetPoint
local location JumpSecSecPoint
call CreateNUnitsAtLoc( 1, 'hfoo', Player(PLAYER_NEUTRAL_PASSIVE), GetSpellTargetLoc(), bj_UNIT_FACING ) //GetSpellTargetLoc() - это точка, утечка и BJ можно раскрыть
set udg_JumpCaster = GetSpellAbilityUnit() //тут в глобалку засовываешь
set udg_JumpCasterPoint = GetUnitLoc(GetSpellAbilityUnit()) //тут тоже в глобалку засовываешь
set udg_JumpTargetPoint = GetUnitLoc(GetLastCreatedUnit()) //тоже в глобалку засовываешь
call RemoveUnit( GetLastCreatedUnit() ) //я так понял ты создал даймика для проверки проходимости раз сразу удаляешь. мб проверять точку на проходимость заранее, в варе есть нативка
call PauseUnitBJ( true, udg_JumpCaster ) //паузим кастера
call SetUnitPathing( udg_JumpCaster, false ) //снимаем проходимость
set udg_JumpTrailEffects[0] = GetLastCreatedEffectBJ() //это глобалка
set udg_JumpTrailEffects[1] = GetLastCreatedEffectBJ() //зачем повторно? GetLastCreatedEffectBJ() - эта одна и та же, но в разных массивах храниться будет
call UnitAddAbilityBJ( 'Amrf', udg_JumpCaster ) //глобалка, добавляем ворону
call EnableTrigger( gg_trg_JumpFlyLoop_____________________u ) //включаем триггер, перемещает каждую 0,01 сек. ближе к точке, ссылка на кастера это udg_JumpCaster и точку udg_JumpTargetPoint, в качестве ссылки нужен тут хэш или МУИ + таймер
call SetUnitFlyHeightBJ( udg_JumpCaster, 350.00, 350.00 ) //поднимаем
call TriggerSleepAction( 0.46 ) //вэйт, ждем
//после вэйта глобалки могут быть перезаписаны (например, тебе захочется нажать еще раз), лучше ссылать на локалки
call SetUnitFlyHeightBJ( udg_JumpCaster, 0.00, 350.00 ) //опускаем
call TriggerSleepAction( 0.30 ) //вэйт. ждем
call ResetUnitAnimation( udg_JumpCaster )
call DisableTrigger( gg_trg_JumpFlyLoop_____________________u ) //выкл. триггер
call TriggerSleepAction( 0.03 ) //ждем
call UnitRemoveAbilityBJ( 'Amrf', udg_JumpCaster ) //удаляем ворону
call PauseUnitBJ( false, udg_JumpCaster ) //паузу снимаем
call SetUnitPathing( udg_JumpCaster, true ) //проходимость включ.
call RemoveLocation(udg_JumpTargetPoint) //все точки удалил?
call RemoveLocation(udg_JumpCasterPoint)
set udg_JumpCaster = null
call DestroyEffectBJ( udg_JumpTrailEffects[0] )
call DestroyEffectBJ( udg_JumpTrailEffects[1] )
//забываешь обнулить локалки типа юнит. точки
endfunction
надо было так с локалками делать (не через менюшки ГУИ, а через код)
получился не полным
local unit JumpCaster = GetSpellAbilityUnit()
local location JumpCasterPoint = GetUnitLoc(GetSpellAbilityUnit())
local location JumpTargetPoint = GetSpellTargetLoc()
local location JumpSecSecPoint
call CreateNUnitsAtLoc( 1, 'hfoo', Player(PLAYER_NEUTRAL_PASSIVE), JumpTargetPoint, bj_UNIT_FACING )
call RemoveLocation(JumpTargetPoint)
set JumpTargetPoint = GetUnitLoc(GetLastCreatedUnit()) //не знаю зачем такая сложность. мб ты даймиком проверяешь можно ли туда телепортнуть
мои глаза
И почему при объявление спецэффектов локальными карта не запускается
local effect JumpTrailEffects[0]
local effect JumpTrailEffects[1]
потому что это неправильно тоже, нужно объявить что эта переменная с массивами, например
local effect array JumpTrailEffects
а потом уже
set JumpTrailEffects[0] = ...
set JumpTrailEffects[1] = ...
Можно еще вот это через Pick of Units (в предыдущей теме скидывал). Мб это уже было, но пригодится новичкам
код
globals
unit UNITHERO
integer CountUn = 0
endglobals
function Trig_g_Conditions takes nothing returns boolean
return( GetSpellAbilityId() == 'A000' )
endfunction
function Trig_X takes nothing returns nothing
if UNITHERO != GetEnumUnit() then
set CountUn = CountUn + 1
endif
endfunction
function F_D takes nothing returns boolean
local real x1 = GetUnitX(UNITHERO)
local real y1 = GetUnitY(UNITHERO)
local real x2 = GetUnitX(GetFilterUnit())
local real y2 = GetUnitY(GetFilterUnit())
local real dx = x2 - x1
local real dy = y2 - y1
local real r = 400. //здесь указываем радиус (сами укажите) !!!
return (dx*dx + dy*dx < r*r)
endfunction
function Trig_g_Actions takes nothing returns nothing
local group g = CreateGroup()
local real x = GetUnitX(GetTriggerUnit())
local real y = GetUnitY(GetTriggerUnit())
local location loc = Location(x,y)
local boolexpr f = null
local boolexpr f1 = Condition(function F_D)
set UNITHERO = GetTriggerUnit()
set CountUn = 0
//call GroupEnumUnitsInRange(g, x, y, 400., f) //ловит всех юнитов, находящихся в радиусе от точке, но москитов не ловит
//call GroupEnumUnitsInRangeCounted(g, x, y, 400., f, 4) //аналогична GroupEnumUnitsInRange, но берет определенное кол-во юнитов. Москитов не ловит
//call GroupEnumUnitsInRangeOfLoc(g, loc,400., f) //аналогична GroupEnumUnitsInRange. Москитов не ловит.
//call GroupEnumUnitsInRangeOfLocCounted(g, loc,400., f, 4) //аналогична GroupEnumUnitsInRangeCounted. Москитов не ловит.
//call GroupEnumUnitsInRect(g,bj_mapInitialPlayableArea ,f1) //ловит всех юнитов в области. Москитов не ловит.
//call GroupEnumUnitsInRectCounted(g,bj_mapInitialPlayableArea ,f1, 4) //ловит определенное кол-во юнитов в области. Москитов не ловит.
//call GroupEnumUnitsSelected(g,GetTriggerPlayer(),f) //ловит юнитов. выделенным игроком. Москитов. очевидно. не ловит.
call GroupEnumUnitsOfPlayer(g,GetTriggerPlayer(),f1) //ловит всех-всех юнитов игрока на карте. Москитов ловит нормально.
//call GroupEnumUnitsOfType(g,"Peasant", f) //ловит всех-всех юнитов с этим именем. Нужно писать английский аналог название (например работник = Peasant). Ловит москитов.
//call GroupEnumUnitsOfTypeCounted(g,"Peasant", f, 4) //ловит опреденное кол-во юнитов группу. Ловит Москитов.
call ForGroup(g, function Trig_X)
call BJDebugMsg("Кол-во юнитов: " + I2S(CountUn))
call RemoveLocation(loc)
call DestroyGroup(g)
call DestroyBoolExpr(f)
call DestroyBoolExpr(f1)
set g = null
set f = null
set f1 = null
set loc = null
endfunction
//===========================================================================
function InitTrig_g takes nothing returns nothing
set gg_trg_g = CreateTrigger( )
call TriggerRegisterPlayerUnitEventSimple( gg_trg_g, Player(0), EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( gg_trg_g, Condition( function Trig_g_Conditions ) )
call TriggerAddAction( gg_trg_g, function Trig_g_Actions )
endfunction
еще советую посмотреть наработки с отрядами (формациями как в total war), как там управляют с москитами
local rect R = //твоя область
local real x = GetRandomReal(GetRectMinX(R), GetRectMaxX(R))
local real y = GetRandomReal(GetRectMinY(R), GetRectMaxY(R))
у целей есть тип "Духи", но в триггерах нет такой фишки, как определить к какому типу цели относится юнит. Можно классификацию использовать. Заметил, что духи это есть у орочьих вардов, у них у всех есть классификация "страж", но такого типа классификации в триггерах тоже нет. Предлагаю использовать другие классы (добавь в РО)
во-вторых, как определить. что юнит спит. это другой вопрос. Тут в сон могут вогнать исскуственно с помощью абилки героя-вампира (проверяют с помощью классификации), или нейтралы ночью спят (там есть эти функции, только криво что-то работают)
Alexey86, это если триггерную цель молнию не сделать. раньше у меня была где-то наработка (сделал тогда в точь-точь как и станд. цепь молнии). эта орба у нее минусов много
есть еще один способ (это мне пришло в голову, вообще-то давно, но я это не реализовывал)
пример
берем GroupPickUnitsOfPlayer про которую сказал бедный quq_CCCP,
в этой функции прописываем фильтр
в фильтре проверяем попала ли точка юнита Caster в круг
function Find_Dummy takes nothing returns nothing
local real x1 = GetUnitX(Caster)
local real y1 = GetUnitY(Caster)
local real x2 = GetUnitX(GetFilterUnit())
local real y2 = GetUnitY(GetFilterUnit())
local real dx = x2 - x1
local real dy = y2 - y1
local real r = 500. //здесь указываем радиус (сами укажите) !!!
return (dx*dx + dy*dx < r*r)
endfunction
...
set Caster = GetTriggerUnit() //эта глобалка юнита
call GroupEnumUnitsOfPlayer( grp, pl, Condition( function Find_Dummy ))
...
Нет нельзя. Функция не выделяет юнитов с этой способностью, нужно заранее сначала выбрать всех, а потом дать всем "Москиты". Даже события "юнит вызывает боевую единицу" не ловит. Словить можно по событию "юнит входит в регион ... ", но только регион, а не вокруг точки, как вы хотите выше. Пробуйте. как предложил GetLocalPlayer
Ред. MpW
» WarCraft 3 / -save/load system целочисленной
Ред. MpW
» WarCraft 3 / Нужна модель которая будет критовать на варкрафте 1.27b?
https://www.xgm.guru/p/wc3/intentional-desync-player
Ред. MpW
» WarCraft 3 / Генератор предметов
Ред. MpW
» Он вам не клоун! / Брейншторм по контентной стратегии XGM
Вторая проблема - это нехватка наработок и интересных фитч. Хайв в этом плане интереснее, больше скилов триггерных и наработок с картинками (изображения отображают в мозгу какой это скилл и тд). У вас они разбросаны по всему сайту и форуму. Кстати я недавно нашел страничку, где было в ней кучу ссылок на наработки, алгоритмы и др.
Ред. MpW
» WarCraft 3 / Помогите исправить ошибку
https://www.xgm.guru/p/wc3/jass_local_vars
Ред. MpW
» WarCraft 3 / Помогите исправить ошибку
убрал эту переменную, теперь указывается ошибку на другую строчку. Убрал, на еще одну. где-то с третьей попытки запустилось
Ред. MpW
» WarCraft 3 / Помогите исправить ошибку
Ред. MpW
» WarCraft 3 / Простой вопрос по хэш-таблице
» WarCraft 3 / Смайлы
Ред. MpW
» WarCraft 3 / Помогите исправить ошибку
есть локалка JumpCaster и есть глобалка udg_JumpCaster - это две разные вещи
Ред. MpW
» WarCraft 3 / Как добавить итем в лавку?
Ред. MpW
» WarCraft 3 / Как определить и сравнить расстояние между точками.
Ред. MpW
» WarCraft 3 / Москиты
» WarCraft 3 / Как сделать триггерный приказ юниту двигаться к рандомной обл.?
Ред. MpW
» WarCraft 3 / тригер тд
Ред. MpW
» WarCraft 3 / Спящий юнит входит категорию целей духи?
https://www.xgm.guru/p/100/181514
» WarCraft 3 / Цепь молний пассивка
Ред. MpW
» WarCraft 3 / Не берет москитных юнитов в группу
» WarCraft 3 / Не берет москитных юнитов в группу
Ред. MpW
» WarCraft 3 / Юниты на борту транспорта.
https://www.xgm.guru/p/wc3/transporting