ТРИГГЕР 1:
scope SpellHook initializer InitSpellHook{
define{
  private ABILITY      = 'A000'          //| Способность
  private HOOK         = 'h001'          //| ИД пустышки крюка
  private CHAIN        = 'h000'          //| ИД пустышки цепи
  private SPEED_HOOK   = 40              //| Скорость/Расстояние
  private AOE(a)       = 100+50*GetUnitAbilityLevel(a,ABILITY)  //| Радиус выбора врагов/союзников
  private DMG(a)       = 50*GetUnitAbilityLevel(a,ABILITY)      //| Урон
  private RANGE_MAX(a) = 1500*GetUnitAbilityLevel(a,ABILITY)    //| Дальность крюка
  private TYPE_DMG     = ATTACK_TYPE_MAGIC,DAMAGE_TYPE_MAGIC,WEAPON_TYPE_WHOKNOWS    //| Тип урона
  private EFFECT       = "Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl"  //| Эффект на юните
  private BODY         = "chest"         //| Точка крепления эффекта на юните
}

private bool MaxXY(real x,real y){return GetRectMinX(bj_mapInitialPlayableArea)<=x&&x<=GetRectMaxX(bj_mapInitialPlayableArea)&&GetRectMinY(bj_mapInitialPlayableArea)<=y&&y<=GetRectMaxY(bj_mapInitialPlayableArea)}

private struct Hook{
  static timer t = CreateTimer()
  static int M = 0
  static int m[]
  unit a,c,B
  unit h[200]
  int id
  bool f
  real ang,d

Struct_Dest(this,i,t)
  
Metod(Time)
  local stype this
  local int i = 0
  local real x,y,angle
  local int e
  local group g
  local unit C
whilenot(++i>M){
  set this = m[i]
  set x = GetUnitX(a)
  set y = GetUnitY(a)
if id>0&&DistXY(x,y,GetUnitX(h[id]),GetUnitY(h[id]))>SPEED_HOOK{
  set e = R2I(DistXY(x,y,GetUnitX(h[id]),GetUnitY(h[id])))/SPEED_HOOK
whilenot(e<=0){
  id++
  set angle = AngleXY(x,y,GetUnitX(h[id-1]),GetUnitY(h[id-1]))
  set h[id] = NewUnit(a,CHAIN,x+(SPEED_HOOK*e)*Cos(angle*DG),y+(SPEED_HOOK*e)*Sin(angle*DG),angle)
  e--
}}
if !f{
  id++
  set h[id] = NewUnit(a,CHAIN,x,y,ang)
  call MoveXY(B,GetUnitX(B),GetUnitY(B),SPEED_HOOK,ang)
  set e = 0
whilenot(e>id){
if e<2{
    SetUnitPosition(h[e],GetUnitX(h[e])+SPEED_HOOK*Cos(ang*0.0174),GetUnitY(h[e])+SPEED_HOOK*Sin(ang*0.0174))
  call SetUnitFacing(h[e],ang)
else
    SetUnitPosition(h[e],GetUnitX(h[e-1])+SPEED_HOOK*Cos(AngleXY(GetUnitX(h[e-1]),GetUnitY(h[e-1]),GetUnitX(h[e]),GetUnitY(h[e]))*0.0174),GetUnitY(h[e-1])+SPEED_HOOK*Sin(AngleXY(GetUnitX(h[e-1]),GetUnitY(h[e-1]),GetUnitX(h[e]),GetUnitY(h[e]))*0.0174))
  call SetUnitFacing(h[e],AngleXY(GetUnitX(h[e]),GetUnitY(h[e]),GetUnitX(h[e-1]),GetUnitY(h[e-1])))
}
  e++
}
  set g = CreateGroup()
  call GroupEnumUnitsInRange(g,GetUnitX(B),GetUnitY(B),AOE(a),null)
for(){
  set C = FirstOfGroup(g)
  exitwhen C==null||c!=null
if Life(C)&&a!=C{
if IsUnitEnemy(C,GetOwningPlayer(a)){UnitDamageTarget(a,C,DMG(a),false,false,TYPE_DMG)}
  call DestroyEffect(AddSpecialEffectTarget(EFFECT,C,BODY))
  call PauseUnit(C,true)
  set c = C
}
  call GroupRemoveUnit(g,C)
}
  call DestroyGroup(g)
  set d = d - SPEED_HOOK
    f = d<=0||MaxXY(GetUnitX(B),GetUnitY(B))==false||c!=null
else
if id>0{
  call MoveXY(B,GetUnitX(h[1]),GetUnitY(h[1]),0,GetUnitFacing(h[1]))
if c!=null{MoveXY(c,GetUnitX(B),GetUnitY(B),0,GetUnitFacing(c))}
  set e = id
whilenot(e<=0){
if e==id{
    SetUnitPosition(h[e],GetUnitX(h[e])+SPEED_HOOK*Cos(AngleXY(GetUnitX(h[e]),GetUnitY(h[e]),GetUnitX(a),GetUnitY(a))*0.0174),GetUnitY(h[e])+SPEED_HOOK*Sin(AngleXY(GetUnitX(h[e]),GetUnitY(h[e]),GetUnitX(a),GetUnitY(a))*0.0174))
  call SetUnitFacing(h[e],AngleXY(GetUnitX(a),GetUnitY(a),GetUnitX(h[e]),GetUnitY(h[e])))
if IsUnitInRange(a,h[e],SPEED_HOOK){
  call RemoveUnit(h[e])
  set h[e] = null
  id--
}
else
    SetUnitPosition(h[e],GetUnitX(h[e+1])+SPEED_HOOK*Cos(AngleXY(GetUnitX(h[e+1]),GetUnitY(h[e+1]),GetUnitX(h[e]),GetUnitY(h[e]))*0.0174),GetUnitY(h[e+1])+SPEED_HOOK*Sin(AngleXY(GetUnitX(h[e+1]),GetUnitY(h[e+1]),GetUnitX(h[e]),GetUnitY(h[e]))*0.0174))
  call SetUnitFacing(h[e],AngleXY(GetUnitX(h[e+1]),GetUnitY(h[e+1]),GetUnitX(h[e]),GetUnitY(h[e])))
}
  e--
}
else
if c!=null{
  call PauseUnit(c,false)
  set c = null
}
  call RemoveUnit(B)
  set a = null
  set B = null
  call Destroy(this,i,t)
}}}
endmethod

Metod(act)
  M++
  local stype this = stype.create()
if M<13{
  set m[M] = this
  set a = GetSpellAbilityUnit()
  set c = null
  set ang = AngleXY(GetUnitX(a),GetUnitY(a),GetSpellTargetX(),GetSpellTargetY())
  set B = NewUnit(a,HOOK,GetUnitX(a),GetUnitY(a),ang)
  set id = 0
  set d = RANGE_MAX(a)
  set f = false
if M==1{TimerStart(t,0.04,true,fun stype.Time)}
else
  call deallocate()
  M--
}
endmethod
}

Struct_Cond(ABILITY,Hook.act())
void InitSpellHook(){TR_EC(cond)}}
ТРИГГЕР 2:
define{
  bool = boolean
  int = integer
  void = nothing
  fun = function
  stype = thistype
  DG = 0.0174
  AngleXY(x,y,x1,y1) = 180.0 / 3.14159 * Atan2(y1 - y,x1 - x)
  DistXY(x,y,x1,y1) = SquareRoot((x-x1)*(x-x1)+(y-y1)*(y-y1))
  NewUnit(a,id,x,y,ang) = CreateUnit(GetOwningPlayer(a),id,x,y,ang)
  Life(a) = GetWidgetLife(a)>.405
  FilterE(b,a) = IsUnitEnemy(b,GetOwningPlayer(a))&&Life(b)
  MoveXY(a,x,y,s,ang) = {
  SetUnitX(a,x+s*Cos(ang*DG))
  SetUnitY(a,y+s*Sin(ang*DG))
  }
  Struct_Cond(ABILITY,Name_Struct) = {
  private bool cond(){
  if GetSpellAbilityId()==ABILITY{Name_Struct}
  return false
  }}
  Struct_Dest(Struct,i,t) = {
  static method Destroy takes stype Struct,int i,timer t returns void
  destroy()
  m[i] = m[M]
  M--
  if M==0{PauseTimer(t)}
  endmethod
  }
  Metod(Name) = static method Name takes void returns void
  TR_EC(cond) = {
  trigger t = CreateTrigger()
  TriggerRegisterPlayerUnitEvent(t,Player(0x00),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
  TriggerRegisterPlayerUnitEvent(t,Player(0x01),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
  TriggerRegisterPlayerUnitEvent(t,Player(0x02),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
  TriggerRegisterPlayerUnitEvent(t,Player(0x03),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
  TriggerRegisterPlayerUnitEvent(t,Player(0x04),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
  TriggerRegisterPlayerUnitEvent(t,Player(0x05),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
  TriggerRegisterPlayerUnitEvent(t,Player(0x06),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
  TriggerRegisterPlayerUnitEvent(t,Player(0x07),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
  TriggerRegisterPlayerUnitEvent(t,Player(0x08),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
  TriggerRegisterPlayerUnitEvent(t,Player(0x09),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
  TriggerRegisterPlayerUnitEvent(t,Player(0x0a),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
  TriggerRegisterPlayerUnitEvent(t,Player(0x0b),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
  TriggerRegisterPlayerUnitEvent(t,Player(0x0c),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
  TriggerAddCondition(t,Condition(fun cond))
  }

}
В общем, расскажите, пожалуйста, как этот код в двух триггерах начинает работать при запуске карты. Весь код я скинул для наглядности, но мне интересно, почему тот участок, который инициализирует СОБЫТИЕ запускается. До этого я работал лишь с функциями, которые переводятся в джасс с ГУИ(именно инициализация событий), но вот этот случай что-то не очень понятен. Чуйка говорит, что дело в ключевом слове Initializer сверху, но если кто знает, обьясните немного подробней, или скиньте, пожалуйста норм статьи, а то лично я ничего не нарыл(

Принятый ответ

действие вызывается в условии, вот в этом куске кода
Name_Struct - параметр действия (дефайном подставляется Hook.act())
define ... Struct_Cond(ABILITY,Name_Struct) = {
 private bool cond(){ 
    if GetSpellAbilityId()==ABILITY {
      Name_Struct // заменится на Hook.act()
    }
    return false
  }
}
... 
Struct_Cond(ABILITY,Hook.act()) // вот эта линия превращается в то что выше но с подстановкой этих параметров
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
0
19
3 года назад
0
Похожие вопросы:

ответ
Black Soul:
ArhiMEN:
Я посмотрел, но возникла проблема. Я тупой и не могу написать также, но моменте добаления юнита в хеш таблицу. Я Save Handle of (Last created unit) as 0 of (а дальше я не нашёл, как добавть "Key(Constructed structure))" in Hash
и соответсвенно любое другое действие, где прописанно Key
Так не нужно ничего самому делать. Я прикрепил к тому сообщению карту. В ней я уже все сделал сам. Тебе осталось только скопировать триггеры оттуда в свою карту и заменить юнитов на тех, которые тебе нужны. Вот та карта:
Bergi_Bear, хеш-таблицы — это проще простого. Они не требуют множество действий для работы. Достаточно только понять принцип.
ответ
Drulia_san, посмотрел код, если this есть 0 в обычном методе, то это значит, что там где ты вызываешь Restore для StructuresSnapshot ты передаешь 0.
call obj.Restore()  // obj равен 0, а его тип есть StructuresSnapshot.
ответ
Ответ выше - для стандартного редактора WE. Однако, рекомендуется использовать с Lua внешний редактор кода и внешний же сборщик карты. Это чревато маленьким неудобством в виде необходимости запускать карту на проверку только из внешней программы т.к. запуск из WE будет без значительной части кода в карте, но дает огромное преимущество в виде несравнимо более удобной работы с кодом.
К сожалению, пока слишком мало информации об этом на сайте.
Вариант NazarPunk, пока без сборки карты, код придется копировать в карту вручную.

Мой вариант, пока не рабочий т.к. перед релизом нужно исправить несколько багов, но включает в себя и работу с кодом и сборку карты, не нужно вручную копировать код в карту.
Даже здесь на сайте есть еще пара вариантов, но мне лень их искать
И немного саморекламы, как выглядели бы ответы на вопрос выше при использовании моего тулсета
  1. Использовать макрос RAW('A0E5'), который превратит равкод в число при сборке карты.
  2. Инжект в функцию main, с заменой оригинальной функции main на свою и вызовом оригинальной функции изнутри нашей.
  3. Аналогично ответу на этот вопрос для чистого WE, но без объявления переменных в WE т.к. то уже не так удобно становится когда код во внешнем редакторе.

Теперь о точках входа и инжекте.
Луа позволяет делать такой финт ушами
do
  local f = FunctionName -- записываем функцию в переменную
  function FunctionName() -- заменяем оригинальную функцию своей
   f() -- вызываем оригинальную функцию из переменной
   -- здесь могла быть ваша реклама или ваш код
  end
end
Это позволит нам сохранить оригинальную функцию в переменную, заменить оригинал своей функцией и вызвать оригинал из переменной. Применимо к любой функции, которая была объявлена раньше, не работает если функция объявлена после выполнения этого кода. Для создания точки входа отлично подходит InitGlobals, она всегда объявляется раньше кастомного кода в WE и вызывается из main.

У себя в коде я пользуюсь немного более сложным способом, этот код не будет работать в WE т.к. цепляет main, а не InitGlobals и не дает серьеных преимуществ перед описаным выше, привожу просто для расширения кругозора
local function InjectMain()
    local alpha_main = main
    return function()
        local alpha_init = RunInitializationTriggers
        RunInitializationTriggers = function() end
        alpha_main()
        InitLibraries() --моя функция, которая должна быть выполнена после всего, но до триггеров инициализации карты
        alpha_init()
    end
end
main = InjectMain()
ответ
ну не обнулили g
во-вторых, не привязали группу при ее создании к выбранному юниту. Короче, это уже ошибка.
    if g == null then
        set g = CreateGroup()
		//надо в хэш на зэндл выбранного записать группу
		set g = null //переменная - это просто ссылка
    endif
при смерти овцы удаляем ее из группы
при смерти выбранного юнита удаляем группу
может стоит подумать сделать на всю игру одну группу овечек или вообще обойтись без группы. будет фиксировать заход/выход овцы. На каждого выбранного заводим счетчик. А каждой овце привязываем выбранного. Когда овца умирает, то зная к кому привязана, у выбранного понижаем счетчик.
ответ
В целом не нужно, я думаю, если ты все поля при создании структуры инициализируешь (я не уверен обнуляет ли их аллокатор)
Структура просто integer потому что в коде в итоге генерирутся параллельные массивы т.е. например
real array cord_x
real array cord_y
real array cord_z
unit array cord_u
Для каждого члена структуры. Поэтом сама cord это просто индекс в эти массивы. Когда ты делаешь cord.create() находится свободный индекс в этих "параллельных" массивах и помечается заполненным.

0
32
3 года назад
0
Это cjass и работа с jngp, тебе ещё рановато, сперва vjass мануал почитай, про структуры и библиотеки, что такое initializer там есть.
0
5
3 года назад
0
quq_CCCP:
Это cjass и работа с jngp, тебе ещё рановато, сперва vjass мануал почитай, про структуры и библиотеки, что такое initializer там есть.
а зачем все эти извращения с vjass и cjass, если есть обычный jass
0
17
3 года назад
0
а зачем все эти извращения с vjass и cjass, если есть обычный jass
Это просто инструменты. Кому оно нужно а кому нет, личное дело каждого.
0
3
3 года назад
0
quq_CCCP:
Это cjass и работа с jngp, тебе ещё рановато, сперва vjass мануал почитай, про структуры и библиотеки, что такое initializer там есть.
А что ты имеешь в виду про "работу с jgnp"? Просто я давно уже там пишу код, мб какие-то фичи, или что?
0
3
3 года назад
0
Мне бы хоть какой намёк, где тут реализуются действия(реакция на событие) Я вижу, как инициализатор инициализирует события и кондишн для тригера t. Но в каком участке кода идёт намёк(добавление) на "действия"? До этого я лишь с TriggerAddAction работал.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.