Эта
library Kill initializer Init{

    globals
        
        private timer TMR = CreateTimer()
    endglobals

    struct resp{
        unit ru
        player p
        integer time
        real x
        real y
        boolean b
        private static integer array next
        private static integer array prev
        
        method destroy takes nothing returns nothing
            //Remove from the List
            set next[prev[this]] = next[this]
            set prev[next[this]] = prev[this]
            //Timer
            if next[0] == 0 {
                call PauseTimer(TMR)
            }
            //Clean Handles
            
            //Clean References
            set .ru = null
            set .p = null
            call deallocate()
        endmethod
        
        private static nothing update(){
            local thistype this = next[0]
            loop{
                exitwhen this == 0
                if .time < 1 {
                    call ReviveHero(.ru, .x, .y, .b)
                    if GetLocalPlayer() == p {
                        call PanCameraTo(.x, .y)
                        call ClearSelection()
                        call SelectUnit(.ru, true)
                    }
                    call destroy()
                } else {
                    set .time -= 1
                }
                set this = next[this]
            }
        }
        
        static thistype create(unit u, integer t, boolean b){
            local thistype this = allocate()
            
            //Setting
            set .ru = u
            set .time = t
            set .b = b
            set .p = GetOwningPlayer(u)
            if IsUnitAlly(u, Player(0)){
                set .x = GetRectCenterX(gg_rct_BaseRed)
                set .y = GetRectCenterY(gg_rct_BaseRed)
            } else {
                set .x = GetRectCenterX(gg_rct_BaseBlue)
                set .y = GetRectCenterY(gg_rct_BaseBlue)
            }
            
            //Insert in the list
            set next[this] = 0
            set prev[this] = prev[0]
            set next[prev[this]] = this
            set prev[0] = this
            
            if prev[this] == 0 {
                call TimerStart(TMR, 1.0, true, function thistype.update)
            }
            
            return this
        }
    }

    boolean Revive(){
        local integer time
        debug call BJDebugMsg(GetUnitName(GetTriggerUnit()))
        if IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) {
            set time = GetHeroLevel(GetTriggerUnit())
            call resp.create(GetTriggerUnit(), time, true)
        }
        return false
    }

    private nothing Init(){
        local trigger trg = CreateTrigger()
        local integer index = 0
        loop{
            call TriggerRegisterPlayerUnitEvent(trg, Player(index), EVENT_PLAYER_UNIT_DEATH, null)
        set index += 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
        }
        call TriggerAddCondition(trg, Condition(function Revive))
        set trg = null
    }

}
В общем. Захотел посмотреть как работают структуры.
Почитал статьи, написал код. Всё работает, но есть моменты которые я не понимаю.
Что за тип thistype?
Как работает эта часть кода?
раскрыть
            loop{
                exitwhen this == 0
				
                set this = next[this]
            }
И эта
	        set next[this] = 0
            set prev[this] = prev[0]
            set next[prev[this]] = this
            set prev[0] = this
			//
            set next[prev[this]] = next[this]
            set prev[next[this]] = prev[this]
Как всё работает через один таймер.
Да и в целом, что за манипуляции с thistype и this.
Если есть статья и я её пропустил, сори c:

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

А можно их вообще убрать?
Можно. Но понадобится массив для хранения всех экземпляров структуры. Дело в том, что таймер обходит все экземпляры чтобы убавить оставшееся время воскрешения на 1 каждую секунду, это происходит внутри функции
static nothing update()
Ну и разумеется внутри функциий create и destroy вносить и убирать отработанные экземпляры в/из этого массива.
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
0
10
6 лет назад
0
Это реализация двусвязного списка.
Как она работает? Где об этом можно почитать?
GetLocalPlayer:
В показанном тобой коде ужасная помесь vJass и cJass, а используемый подход с this делает логику запутанной. Не рекомендую пытаться на нём учиться.
cJass использую исключительно для своего удобства.
Да вроде всё вполне понятно.
С thistype и this разобрался.
Теперь остался вопрос, как работает это список с next и prev?
0
27
6 лет назад
Отредактирован MpW
0
пример векторов MF
//Система мистера MF https://xgm.guru/forum/showthread.php?t=27122

library vectors
    
    struct vector
        real x
        real y
        real z
        //Статичный метод создающий вектор, принимает координаты возвращает вектор. 
        //Вектор - отрезок AB, соединяющий из точки A в точку B. Вектор кроме того имеет направление. 
        //V = (x, y, z)  => казалось храним координаты точки, не совсем точно. Храним отрезок с направлением.
        //правильнее V = (Bx-Ax, By-Ay, Bz-Az)  => из конца вычитаем начало
        //эта функция создаем вектор. создается структура, короче выделяется место под массивы. максимум доступно 8190
        //прописываем: local vector v = vector.create(0,0,0) <= координаты
        static method create takes real x, real y, real z returns vector
            local vector v = vector.allocate() // <= что-то вроде перебора индекса массива
            set v.x=x
            set v.y=y
            set v.z=z
            return v //<= возвращает на самом деле индекс, номер структуры
        endmethod

        //Умножает вектор на какое либо число.
        //V = V * r
        //если раскрыть: 
        //set v_x[this]=v_x[this] * r
        //set v_y[this]=v_y[this] * r
        //set v_z[this]=v_z[this] * r
        //пишем: local vector v = vector.create(1,1,1)
        //пишем: call v.realmul(2)  // <= результат вектор с координатами 2 2 2
        method realmul takes real r returns nothing
            set .x=.x*r
            set .y=.y*r
            set .z=.z*r
        endmethod
        
        //Модуль вектора - метод возвращающий длину вектора (число всегда >0)
        //|V| = sqrt(x*x + y*y + z*z)
        //пишем: local vector v = vector.create(0,0,1)
        //пишем: local real r = v.getlength() <= результат равен 1
        method getlength takes nothing returns real
            return SquareRoot(.x*.x+.y*.y+.z*.z)
        endmethod
        
        //Устанавливет длину вектора равным 1
        //Нормализация — приведение к единичному размеру; 
        //нормализация в трехмерном пространстве - по сути является масштабированием в куб единичного размера 
        //Для нормализации вектора нужно каждую компоненту поделить на длину вектора, или умножить инверсию длины на данный вектор.
        //V/|V| = (x/|V|, y/|V|, z/|V|) <= короче складываем кажду координату, больше вычислении нужно
        //set InvLength = 1/legth  <=инверсия, здесь меньше вычислении
        method normalize takes nothing returns nothing
            local real l = .getlength()
            if l>0 then
                call .realmul(1/l)
            endif
        endmethod   
        
        //Принимает число. Устанавливает длину вектора равной этому числу.
        //похожий метод у функции normalize
        //пишем: local vector v = vector.create(54,0,0)
        //пишем: call v.setlength(30) <= результат: вектор а равен 30 0 0
        method setlength takes real r returns nothing
            local real l = .getlength()
            if l>0 then
                call .realmul(r/l)
            endif
        endmethod
        
        //Принимает вектор. Возвращает число равное скалярному произведению этих векторов.
        //Пусть в этом методе A - первый вектор, B - второй вектор (не путайте, выше был предоставлен вектор AB, сейчас поменял обозначения)
        // A*B = Ax*Bx + Ay*By + Az*Bz
        //используется часто для вычисления углов между векторами
        //пишем: local vector v = vector.create(1,2,3)
        //пишем: local vector w = vector.create(1,0,3)
        //пишем: local real r = v.scalarmul(w)
        //результат равен 10
        method scalarmul takes vector v returns real
            return .x*v.x+.y*v.y+.z*v.z
        endmethod
        
        //Принимает вектор. Устанавливает вызывающий вектор равным сумме самого себя и принятого вектора.
        //Пусть в этом методе A - первый вектор, B - второй вектор (не путайте, выше был предоставлен вектор AB, сейчас поменял обозначения)
        // Bx= Ax+Bx, By= Ay+By, Bz = Az+Bz   <= изменяются параметры вектора B
        //пишем: local vector v = vector.create(1,2,3)
        //пишем: local vector w = vector.create(1,0,3)
        //пишем: local real r = v.vectoradd(w)
        //результат: вектор v равен 2 2 6, вектор w не изменился
        method vectoradd takes vector v returns nothing
            set .x=.x+v.x
            set .y=.y+v.y
            set .z=.z+v.z
        endmethod
        //аналогично как и метод vectoradd, только вычитывает
        method vectorsub takes vector v returns nothing
            set .x=.x-v.x
            set .y=.y-v.y
            set .z=.z-v.z
        endmethod
        
        //Принимает вектор. Устанавливает вызывающий вектор равным векторному произведению самого себя и принятого вектора.
        //Пусть в этом методе A - первый вектор, B - второй вектор (не путайте, выше был предоставлен вектор AB, сейчас поменял обозначения)
        //Bx= (Ay*Bz - By*Az), By= (Az*Bx - Bz*Ax), Bz = (Ax*By - Bx*Ay)
        //пишем: local vector v = vector.create(1,0,0)
        //пишем: local vector w = vector.create(0,1,0)
        //пишем: local real r = v.vectormul(w)
        //результат: вектор v равен 0 0 1, вектор w не изменился
        method vectormul takes vector v returns nothing
            local real x = .y*v.z-v.y*.z
            local real y = .z*v.x-v.z*.x
            local real z = .x*v.y-v.x*.y
            set .x = x
            set .y = y
            set .z = z
        endmethod
        
        //Принимает вектор. Возвращает вектор равный вызывающему.
        //Смысл: эта функция создает копию-вектор, который принимает те же значения что у оригинала
        //пишем: local vector v = vector.create(1,0,0)
        //пишем: local vector w = vector.clone()
        //результат: вектор v равен 1 0 0, вектор w равен 1 0 0
        method clone takes nothing returns vector
            local vector v=vector.allocate()
            set v.x=.x
            set v.y=.y
            set v.z=.z
            return v
        endmethod      
        
        //Принимает вектор. Устанавливает значение вызывающего вектора равным принятому вектору.
        //В отличии от метода clone здесь не создается двойник, у нас уже имеется вектор. Не всегда имеет смысл создавать двойников
        //пишем: local vector v = vector.create(1,0,0)
        //пишем: local vector w = vector.create(0,1,0)
        //пишем: call v.copy(w)
        //результат: вектор v равен 0 1 0, вектор w равен 0 1 0
        method copy takes vector p returns nothing
            set .x=p.x
            set .y=p.y
            set .z=p.z            
        endmethod
        
        //Принимает координаты x, y и z. Форсированное изменение координат вектора.
        //Изменяет текущий вектор.
        //пишем: local vector v = vector.create(1,0,0)
        //пишем: call v.change(1,1,1)
        //результат: вектор v равен 1 1 1
        method change takes real x, real y, real z returns nothing
            set .x=x
            set .y=y
            set .z=z
        endmethod
        
        
        //Принимает вектор. Вычисляет угол между двумя векторами.
        //Пусть в этом методе A - первый вектор, B - второй вектор (не путайте, выше был предоставлен вектор AB, сейчас поменял обозначения)
        //Вытекает из скалярного произведения AB*Cos(A)
        //CosA = AB/|A|*|B|, где AB = ax*bx + ay*by + az*bz и |A| = sqrt(ax*ax + ay*ay + az*az), |B| = sqrt(bx*bx + by*by + bz*bz)
        method AngleBetweenVectors takes vector b returns real //в радинах
            local real ab =.scalarmul(b)/(.getlength()*b.getlength())
            return ab
        endmethod
        method AngleBetweenVectors2 takes vector b returns real //в градусах
            local real ab =.scalarmul(b)/(.getlength()*b.getlength())
            return Acos(ab)
        endmethod
        
    endstruct    
    
endlibrary
скомпилированный код
globals
//globals from vectors:
constant boolean LIBRARY_vectors=true
//endglobals from vectors
    // Generated
trigger gg_trg_vectors= null


//JASSHelper struct globals:
constant integer si__vector=1
integer si__vector_F=0
integer si__vector_I=0
integer array si__vector_V
real array s__vector_x
real array s__vector_y
real array s__vector_z

endglobals


//Generated allocator of vector
function s__vector__allocate takes nothing returns integer
 local integer this=si__vector_F
    if (this!=0) then
        set si__vector_F=si__vector_V[this]
    else
        set si__vector_I=si__vector_I+1
        set this=si__vector_I
    endif
    if (this>8190) then
        return 0
    endif

    set si__vector_V[this]=-1
 return this
endfunction

//Generated destructor of vector
function s__vector_deallocate takes integer this returns nothing
    if this==null then
        return
    elseif (si__vector_V[this]!=-1) then
        return
    endif
    set si__vector_V[this]=si__vector_F
    set si__vector_F=this
endfunction

//library vectors:
    
        //Статичный метод создающий вектор, принимает координаты возвращает вектор. 
        //Вектор - отрезок AB, соединяющий из точки A в точку B. Вектор кроме того имеет направление. 
        //V = (x, y, z)  => казалось храним координаты точки, не совсем точно. Храним отрезок с направлением.
        //правильнее V = (Bx-Ax, By-Ay, Bz-Az)  => из конца вычитаем начало
        //эта функция создаем вектор. создается структура, короче выделяется место под массивы. максимум доступно 8190
        //прописываем: local vector v = vector.create(0,0,0) <= координаты
        function s__vector_create takes real x,real y,real z returns integer
            local integer v= s__vector__allocate()
            set s__vector_x[v]=x
            set s__vector_y[v]=y
            set s__vector_z[v]=z
            return v //<= возвращает на самом деле индекс, номер структуры
        endfunction

        //Умножает вектор на какое либо число.
        //V = V * r
        //если раскрыть: 
        //set v_x[this]=v_x[this] * r
        //set v_y[this]=v_y[this] * r
        //set v_z[this]=v_z[this] * r
        //пишем: local vector v = vector.create(1,1,1)
        //пишем: call v.realmul(2)  // <= результат вектор с координатами 2 2 2
        function s__vector_realmul takes integer this,real r returns nothing
            set s__vector_x[this]=s__vector_x[this] * r
            set s__vector_y[this]=s__vector_y[this] * r
            set s__vector_z[this]=s__vector_z[this] * r
        endfunction
        
        //Модуль вектора - метод возвращающий длину вектора (число всегда >0)
        //|V| = sqrt(x*x + y*y + z*z)
        //пишем: local vector v = vector.create(0,0,1)
        //пишем: local real r = v.getlength() <= результат равен 1
        function s__vector_getlength takes integer this returns real
            return SquareRoot(s__vector_x[this] * s__vector_x[this] + s__vector_y[this] * s__vector_y[this] + s__vector_z[this] * s__vector_z[this])
        endfunction
        
        //Устанавливет длину вектора равным 1
        //Нормализация — приведение к единичному размеру; 
        //нормализация в трехмерном пространстве - по сути является масштабированием в куб единичного размера 
        //Для нормализации вектора нужно каждую компоненту поделить на длину вектора, или умножить инверсию длины на данный вектор.
        //V/|V| = (x/|V|, y/|V|, z/|V|) <= короче складываем кажду координату, больше вычислении нужно
        //set InvLength = 1/legth  <=инверсия, здесь меньше вычислении
        function s__vector_normalize takes integer this returns nothing
            local real l= s__vector_getlength(this)
            if l > 0 then
                call s__vector_realmul(this,1 / l)
            endif
        endfunction   
        
        //Принимает число. Устанавливает длину вектора равной этому числу.
        //похожий метод у функции normalize
        //пишем: local vector v = vector.create(54,0,0)
        //пишем: call v.setlength(30) <= результат: вектор а равен 30 0 0
        function s__vector_setlength takes integer this,real r returns nothing
            local real l= s__vector_getlength(this)
            if l > 0 then
                call s__vector_realmul(this,r / l)
            endif
        endfunction
        
        //Принимает вектор. Возвращает число равное скалярному произведению этих векторов.
        //Пусть в этом методе A - первый вектор, B - второй вектор (не путайте, выше был предоставлен вектор AB, сейчас поменял обозначения)
        // A*B = Ax*Bx + Ay*By + Az*Bz
        //используется часто для вычисления углов между векторами
        //пишем: local vector v = vector.create(1,2,3)
        //пишем: local vector w = vector.create(1,0,3)
        //пишем: local real r = v.scalarmul(w)
        //результат равен 10
        function s__vector_scalarmul takes integer this,integer v returns real
            return s__vector_x[this] * s__vector_x[v] + s__vector_y[this] * s__vector_y[v] + s__vector_z[this] * s__vector_z[v]
        endfunction
        
        //Принимает вектор. Устанавливает вызывающий вектор равным сумме самого себя и принятого вектора.
        //Пусть в этом методе A - первый вектор, B - второй вектор (не путайте, выше был предоставлен вектор AB, сейчас поменял обозначения)
        // Bx= Ax+Bx, By= Ay+By, Bz = Az+Bz   <= изменяются параметры вектора B
        //пишем: local vector v = vector.create(1,2,3)
        //пишем: local vector w = vector.create(1,0,3)
        //пишем: local real r = v.vectoradd(w)
        //результат: вектор v равен 2 2 6, вектор w не изменился
        function s__vector_vectoradd takes integer this,integer v returns nothing
            set s__vector_x[this]=s__vector_x[this] + s__vector_x[v]
            set s__vector_y[this]=s__vector_y[this] + s__vector_y[v]
            set s__vector_z[this]=s__vector_z[this] + s__vector_z[v]
        endfunction
        //аналогично как и метод vectoradd, только вычитывает
        function s__vector_vectorsub takes integer this,integer v returns nothing
            set s__vector_x[this]=s__vector_x[this] - s__vector_x[v]
            set s__vector_y[this]=s__vector_y[this] - s__vector_y[v]
            set s__vector_z[this]=s__vector_z[this] - s__vector_z[v]
        endfunction
        
        //Принимает вектор. Устанавливает вызывающий вектор равным векторному произведению самого себя и принятого вектора.
        //Пусть в этом методе A - первый вектор, B - второй вектор (не путайте, выше был предоставлен вектор AB, сейчас поменял обозначения)
        //Bx= (Ay*Bz - By*Az), By= (Az*Bx - Bz*Ax), Bz = (Ax*By - Bx*Ay)
        //пишем: local vector v = vector.create(1,0,0)
        //пишем: local vector w = vector.create(0,1,0)
        //пишем: local real r = v.vectormul(w)
        //результат: вектор v равен 0 0 1, вектор w не изменился
        function s__vector_vectormul takes integer this,integer v returns nothing
            local real x= s__vector_y[this] * s__vector_z[v] - s__vector_y[v] * s__vector_z[this]
            local real y= s__vector_z[this] * s__vector_x[v] - s__vector_z[v] * s__vector_x[this]
            local real z= s__vector_x[this] * s__vector_y[v] - s__vector_x[v] * s__vector_y[this]
            set s__vector_x[this]=x
            set s__vector_y[this]=y
            set s__vector_z[this]=z
        endfunction
        
        //Принимает вектор. Возвращает вектор равный вызывающему.
        //Смысл: эта функция создает копию-вектор, который принимает те же значения что у оригинала
        //пишем: local vector v = vector.create(1,0,0)
        //пишем: local vector w = vector.clone()
        //результат: вектор v равен 1 0 0, вектор w равен 1 0 0
        function s__vector_clone takes integer this returns integer
            local integer v=s__vector__allocate()
            set s__vector_x[v]=s__vector_x[this]
            set s__vector_y[v]=s__vector_y[this]
            set s__vector_z[v]=s__vector_z[this]
            return v
        endfunction      
        
        //Принимает вектор. Устанавливает значение вызывающего вектора равным принятому вектору.
        //В отличии от метода clone здесь не создается двойник, у нас уже имеется вектор. Не всегда имеет смысл создавать двойников
        //пишем: local vector v = vector.create(1,0,0)
        //пишем: local vector w = vector.create(0,1,0)
        //пишем: call v.copy(w)
        //результат: вектор v равен 0 1 0, вектор w равен 0 1 0
        function s__vector_copy takes integer this,integer p returns nothing
            set s__vector_x[this]=s__vector_x[p]
            set s__vector_y[this]=s__vector_y[p]
            set s__vector_z[this]=s__vector_z[p]
        endfunction
        
        //Принимает координаты x, y и z. Форсированное изменение координат вектора.
        //Изменяет текущий вектор.
        //пишем: local vector v = vector.create(1,0,0)
        //пишем: call v.change(1,1,1)
        //результат: вектор v равен 1 1 1
        function s__vector_change takes integer this,real x,real y,real z returns nothing
            set s__vector_x[this]=x
            set s__vector_y[this]=y
            set s__vector_z[this]=z
        endfunction
        
        
        //Принимает вектор. Вычисляет угол между двумя векторами.
        //Пусть в этом методе A - первый вектор, B - второй вектор (не путайте, выше был предоставлен вектор AB, сейчас поменял обозначения)
        //Вытекает из скалярного произведения AB*Cos(A)
        //CosA = AB/|A|*|B|, где AB = ax*bx + ay*by + az*bz и |A| = sqrt(ax*ax + ay*ay + az*az), |B| = sqrt(bx*bx + by*by + bz*bz)
        function s__vector_AngleBetweenVectors takes integer this,integer b returns real
            local real ab=s__vector_scalarmul(this,b) / ( s__vector_getlength(this) * s__vector_getlength(b) )
            return ab
        endfunction
        function s__vector_AngleBetweenVectors2 takes integer this,integer b returns real
            local real ab=s__vector_scalarmul(this,b) / ( s__vector_getlength(this) * s__vector_getlength(b) )
            return Acos(ab)
        endfunction
        
    

//library vectors ends
//===========================================================================
// 
// Еще одна карта
// 
//   Warcraft III map script
//   Generated by the Warcraft III World Editor
//   Date: Sun Oct 21 23:52:07 2018
//   Map Author: Неизвестно
// 
//===========================================================================

//***************************************************************************
//*
//*  Global Variables
//*
//***************************************************************************


function InitGlobals takes nothing returns nothing
endfunction

//***************************************************************************
//*
//*  Triggers
//*
//***************************************************************************

//===========================================================================
// Trigger: vectors
//
// Инициализация стандартного режима сражения для всех игроков
//===========================================================================
//TESH.scrollpos=60
//TESH.alwaysfold=0


function InitCustomTriggers takes nothing returns nothing
    //Function not found: call InitTrig_vectors()
endfunction

//===========================================================================
function RunInitializationTriggers takes nothing returns nothing
    call ConditionalTriggerExecute(gg_trg_vectors)
endfunction

//***************************************************************************
//*
//*  Players
//*
//***************************************************************************

function InitCustomPlayerSlots takes nothing returns nothing

    // Player 0
    call SetPlayerStartLocation(Player(0), 0)
    call SetPlayerColor(Player(0), ConvertPlayerColor(0))
    call SetPlayerRacePreference(Player(0), RACE_PREF_HUMAN)
    call SetPlayerRaceSelectable(Player(0), true)
    call SetPlayerController(Player(0), MAP_CONTROL_USER)

endfunction

function InitCustomTeams takes nothing returns nothing
    // Force: TRIGSTR_002
    call SetPlayerTeam(Player(0), 0)

endfunction

//***************************************************************************
//*
//*  Main Initialization
//*
//***************************************************************************

//===========================================================================
function main takes nothing returns nothing
    call SetCameraBounds(- 3328.0 + GetCameraMargin(CAMERA_MARGIN_LEFT), - 3584.0 + GetCameraMargin(CAMERA_MARGIN_BOTTOM), 3328.0 - GetCameraMargin(CAMERA_MARGIN_RIGHT), 3072.0 - GetCameraMargin(CAMERA_MARGIN_TOP), - 3328.0 + GetCameraMargin(CAMERA_MARGIN_LEFT), 3072.0 - GetCameraMargin(CAMERA_MARGIN_TOP), 3328.0 - GetCameraMargin(CAMERA_MARGIN_RIGHT), - 3584.0 + GetCameraMargin(CAMERA_MARGIN_BOTTOM))
    call SetDayNightModels("Environment\\DNC\\DNCLordaeron\\DNCLordaeronTerrain\\DNCLordaeronTerrain.mdl", "Environment\\DNC\\DNCLordaeron\\DNCLordaeronUnit\\DNCLordaeronUnit.mdl")
    call NewSoundEnvironment("Default")
    call SetAmbientDaySound("LordaeronSummerDay")
    call SetAmbientNightSound("LordaeronSummerNight")
    call SetMapMusic("Music", true, 0)
    call InitBlizzard()

call ExecuteFunc("jasshelper__initstructs15269843")

    call InitGlobals()
    call InitCustomTriggers()
    call ConditionalTriggerExecute(gg_trg_vectors) // INLINED!!

endfunction

//***************************************************************************
//*
//*  Map Configuration
//*
//***************************************************************************

function config takes nothing returns nothing
    call SetMapName("Еще одна карта")
    call SetMapDescription("Описание отсутствует")
    call SetPlayers(1)
    call SetTeams(1)
    call SetGamePlacement(MAP_PLACEMENT_USE_MAP_SETTINGS)

    call DefineStartLocation(0, 1792.0, - 1728.0)

    // Player setup
    call InitCustomPlayerSlots()
    call SetPlayerSlotAvailable(Player(0), MAP_CONTROL_USER)
    call InitGenericPlayerSlots()
endfunction




//Struct method generated initializers/callers:

function jasshelper__initstructs15269843 takes nothing returns nothing


endfunction
this - номер массива. работаем с двумя значениями.
сравни
Загруженные файлы
0
10
6 лет назад
0
Код воскрешает юнита через некоторое время после его смерти. Для этого нужен таймер. Но вместо того чтобы создавать новый таймер для каждого экземпляра структуры, автор создал 1 общий таймер, а в экземплярах хранит оставшееся время до воскрешения юнита, отнимая 1 через каждую секунду работы общего таймера. Так себе подход.
Я просто хотел туда потом еще добавить изменение строки в борде. Чтобы было видно сколько осталось до воскрешения.
Да и воскрешение я просто так сделал. Мне в основном интересно как работает конструкция с next и prev.
Steal nerves:
пример векторов MF
//Система мистера MF https://xgm.guru/forum/showthread.php?t=27122

library vectors
    
    struct vector
        real x
        real y
        real z
        //Статичный метод создающий вектор, принимает координаты возвращает вектор. 
        //Вектор - отрезок AB, соединяющий из точки A в точку B. Вектор кроме того имеет направление. 
        //V = (x, y, z)  => казалось храним координаты точки, не совсем точно. Храним отрезок с направлением.
        //правильнее V = (Bx-Ax, By-Ay, Bz-Az)  => из конца вычитаем начало
        //эта функция создаем вектор. создается структура, короче выделяется место под массивы. максимум доступно 8190
        //прописываем: local vector v = vector.create(0,0,0) <= координаты
        static method create takes real x, real y, real z returns vector
            local vector v = vector.allocate() // <= что-то вроде перебора индекса массива
            set v.x=x
            set v.y=y
            set v.z=z
            return v //<= возвращает на самом деле индекс, номер структуры
        endmethod

        //Умножает вектор на какое либо число.
        //V = V * r
        //если раскрыть: 
        //set v_x[this]=v_x[this] * r
        //set v_y[this]=v_y[this] * r
        //set v_z[this]=v_z[this] * r
        //пишем: local vector v = vector.create(1,1,1)
        //пишем: call v.realmul(2)  // <= результат вектор с координатами 2 2 2
        method realmul takes real r returns nothing
            set .x=.x*r
            set .y=.y*r
            set .z=.z*r
        endmethod
        
        //Модуль вектора - метод возвращающий длину вектора (число всегда >0)
        //|V| = sqrt(x*x + y*y + z*z)
        //пишем: local vector v = vector.create(0,0,1)
        //пишем: local real r = v.getlength() <= результат равен 1
        method getlength takes nothing returns real
            return SquareRoot(.x*.x+.y*.y+.z*.z)
        endmethod
        
        //Устанавливет длину вектора равным 1
        //Нормализация — приведение к единичному размеру; 
        //нормализация в трехмерном пространстве - по сути является масштабированием в куб единичного размера 
        //Для нормализации вектора нужно каждую компоненту поделить на длину вектора, или умножить инверсию длины на данный вектор.
        //V/|V| = (x/|V|, y/|V|, z/|V|) <= короче складываем кажду координату, больше вычислении нужно
        //set InvLength = 1/legth  <=инверсия, здесь меньше вычислении
        method normalize takes nothing returns nothing
            local real l = .getlength()
            if l>0 then
                call .realmul(1/l)
            endif
        endmethod   
        
        //Принимает число. Устанавливает длину вектора равной этому числу.
        //похожий метод у функции normalize
        //пишем: local vector v = vector.create(54,0,0)
        //пишем: call v.setlength(30) <= результат: вектор а равен 30 0 0
        method setlength takes real r returns nothing
            local real l = .getlength()
            if l>0 then
                call .realmul(r/l)
            endif
        endmethod
        
        //Принимает вектор. Возвращает число равное скалярному произведению этих векторов.
        //Пусть в этом методе A - первый вектор, B - второй вектор (не путайте, выше был предоставлен вектор AB, сейчас поменял обозначения)
        // A*B = Ax*Bx + Ay*By + Az*Bz
        //используется часто для вычисления углов между векторами
        //пишем: local vector v = vector.create(1,2,3)
        //пишем: local vector w = vector.create(1,0,3)
        //пишем: local real r = v.scalarmul(w)
        //результат равен 10
        method scalarmul takes vector v returns real
            return .x*v.x+.y*v.y+.z*v.z
        endmethod
        
        //Принимает вектор. Устанавливает вызывающий вектор равным сумме самого себя и принятого вектора.
        //Пусть в этом методе A - первый вектор, B - второй вектор (не путайте, выше был предоставлен вектор AB, сейчас поменял обозначения)
        // Bx= Ax+Bx, By= Ay+By, Bz = Az+Bz   <= изменяются параметры вектора B
        //пишем: local vector v = vector.create(1,2,3)
        //пишем: local vector w = vector.create(1,0,3)
        //пишем: local real r = v.vectoradd(w)
        //результат: вектор v равен 2 2 6, вектор w не изменился
        method vectoradd takes vector v returns nothing
            set .x=.x+v.x
            set .y=.y+v.y
            set .z=.z+v.z
        endmethod
        //аналогично как и метод vectoradd, только вычитывает
        method vectorsub takes vector v returns nothing
            set .x=.x-v.x
            set .y=.y-v.y
            set .z=.z-v.z
        endmethod
        
        //Принимает вектор. Устанавливает вызывающий вектор равным векторному произведению самого себя и принятого вектора.
        //Пусть в этом методе A - первый вектор, B - второй вектор (не путайте, выше был предоставлен вектор AB, сейчас поменял обозначения)
        //Bx= (Ay*Bz - By*Az), By= (Az*Bx - Bz*Ax), Bz = (Ax*By - Bx*Ay)
        //пишем: local vector v = vector.create(1,0,0)
        //пишем: local vector w = vector.create(0,1,0)
        //пишем: local real r = v.vectormul(w)
        //результат: вектор v равен 0 0 1, вектор w не изменился
        method vectormul takes vector v returns nothing
            local real x = .y*v.z-v.y*.z
            local real y = .z*v.x-v.z*.x
            local real z = .x*v.y-v.x*.y
            set .x = x
            set .y = y
            set .z = z
        endmethod
        
        //Принимает вектор. Возвращает вектор равный вызывающему.
        //Смысл: эта функция создает копию-вектор, который принимает те же значения что у оригинала
        //пишем: local vector v = vector.create(1,0,0)
        //пишем: local vector w = vector.clone()
        //результат: вектор v равен 1 0 0, вектор w равен 1 0 0
        method clone takes nothing returns vector
            local vector v=vector.allocate()
            set v.x=.x
            set v.y=.y
            set v.z=.z
            return v
        endmethod      
        
        //Принимает вектор. Устанавливает значение вызывающего вектора равным принятому вектору.
        //В отличии от метода clone здесь не создается двойник, у нас уже имеется вектор. Не всегда имеет смысл создавать двойников
        //пишем: local vector v = vector.create(1,0,0)
        //пишем: local vector w = vector.create(0,1,0)
        //пишем: call v.copy(w)
        //результат: вектор v равен 0 1 0, вектор w равен 0 1 0
        method copy takes vector p returns nothing
            set .x=p.x
            set .y=p.y
            set .z=p.z            
        endmethod
        
        //Принимает координаты x, y и z. Форсированное изменение координат вектора.
        //Изменяет текущий вектор.
        //пишем: local vector v = vector.create(1,0,0)
        //пишем: call v.change(1,1,1)
        //результат: вектор v равен 1 1 1
        method change takes real x, real y, real z returns nothing
            set .x=x
            set .y=y
            set .z=z
        endmethod
        
        
        //Принимает вектор. Вычисляет угол между двумя векторами.
        //Пусть в этом методе A - первый вектор, B - второй вектор (не путайте, выше был предоставлен вектор AB, сейчас поменял обозначения)
        //Вытекает из скалярного произведения AB*Cos(A)
        //CosA = AB/|A|*|B|, где AB = ax*bx + ay*by + az*bz и |A| = sqrt(ax*ax + ay*ay + az*az), |B| = sqrt(bx*bx + by*by + bz*bz)
        method AngleBetweenVectors takes vector b returns real //в радинах
            local real ab =.scalarmul(b)/(.getlength()*b.getlength())
            return ab
        endmethod
        method AngleBetweenVectors2 takes vector b returns real //в градусах
            local real ab =.scalarmul(b)/(.getlength()*b.getlength())
            return Acos(ab)
        endmethod
        
    endstruct    
    
endlibrary
скомпилированный код
globals
//globals from vectors:
constant boolean LIBRARY_vectors=true
//endglobals from vectors
    // Generated
trigger gg_trg_vectors= null


//JASSHelper struct globals:
constant integer si__vector=1
integer si__vector_F=0
integer si__vector_I=0
integer array si__vector_V
real array s__vector_x
real array s__vector_y
real array s__vector_z

endglobals


//Generated allocator of vector
function s__vector__allocate takes nothing returns integer
 local integer this=si__vector_F
    if (this!=0) then
        set si__vector_F=si__vector_V[this]
    else
        set si__vector_I=si__vector_I+1
        set this=si__vector_I
    endif
    if (this>8190) then
        return 0
    endif

    set si__vector_V[this]=-1
 return this
endfunction

//Generated destructor of vector
function s__vector_deallocate takes integer this returns nothing
    if this==null then
        return
    elseif (si__vector_V[this]!=-1) then
        return
    endif
    set si__vector_V[this]=si__vector_F
    set si__vector_F=this
endfunction

//library vectors:
    
        //Статичный метод создающий вектор, принимает координаты возвращает вектор. 
        //Вектор - отрезок AB, соединяющий из точки A в точку B. Вектор кроме того имеет направление. 
        //V = (x, y, z)  => казалось храним координаты точки, не совсем точно. Храним отрезок с направлением.
        //правильнее V = (Bx-Ax, By-Ay, Bz-Az)  => из конца вычитаем начало
        //эта функция создаем вектор. создается структура, короче выделяется место под массивы. максимум доступно 8190
        //прописываем: local vector v = vector.create(0,0,0) <= координаты
        function s__vector_create takes real x,real y,real z returns integer
            local integer v= s__vector__allocate()
            set s__vector_x[v]=x
            set s__vector_y[v]=y
            set s__vector_z[v]=z
            return v //<= возвращает на самом деле индекс, номер структуры
        endfunction

        //Умножает вектор на какое либо число.
        //V = V * r
        //если раскрыть: 
        //set v_x[this]=v_x[this] * r
        //set v_y[this]=v_y[this] * r
        //set v_z[this]=v_z[this] * r
        //пишем: local vector v = vector.create(1,1,1)
        //пишем: call v.realmul(2)  // <= результат вектор с координатами 2 2 2
        function s__vector_realmul takes integer this,real r returns nothing
            set s__vector_x[this]=s__vector_x[this] * r
            set s__vector_y[this]=s__vector_y[this] * r
            set s__vector_z[this]=s__vector_z[this] * r
        endfunction
        
        //Модуль вектора - метод возвращающий длину вектора (число всегда >0)
        //|V| = sqrt(x*x + y*y + z*z)
        //пишем: local vector v = vector.create(0,0,1)
        //пишем: local real r = v.getlength() <= результат равен 1
        function s__vector_getlength takes integer this returns real
            return SquareRoot(s__vector_x[this] * s__vector_x[this] + s__vector_y[this] * s__vector_y[this] + s__vector_z[this] * s__vector_z[this])
        endfunction
        
        //Устанавливет длину вектора равным 1
        //Нормализация — приведение к единичному размеру; 
        //нормализация в трехмерном пространстве - по сути является масштабированием в куб единичного размера 
        //Для нормализации вектора нужно каждую компоненту поделить на длину вектора, или умножить инверсию длины на данный вектор.
        //V/|V| = (x/|V|, y/|V|, z/|V|) <= короче складываем кажду координату, больше вычислении нужно
        //set InvLength = 1/legth  <=инверсия, здесь меньше вычислении
        function s__vector_normalize takes integer this returns nothing
            local real l= s__vector_getlength(this)
            if l > 0 then
                call s__vector_realmul(this,1 / l)
            endif
        endfunction   
        
        //Принимает число. Устанавливает длину вектора равной этому числу.
        //похожий метод у функции normalize
        //пишем: local vector v = vector.create(54,0,0)
        //пишем: call v.setlength(30) <= результат: вектор а равен 30 0 0
        function s__vector_setlength takes integer this,real r returns nothing
            local real l= s__vector_getlength(this)
            if l > 0 then
                call s__vector_realmul(this,r / l)
            endif
        endfunction
        
        //Принимает вектор. Возвращает число равное скалярному произведению этих векторов.
        //Пусть в этом методе A - первый вектор, B - второй вектор (не путайте, выше был предоставлен вектор AB, сейчас поменял обозначения)
        // A*B = Ax*Bx + Ay*By + Az*Bz
        //используется часто для вычисления углов между векторами
        //пишем: local vector v = vector.create(1,2,3)
        //пишем: local vector w = vector.create(1,0,3)
        //пишем: local real r = v.scalarmul(w)
        //результат равен 10
        function s__vector_scalarmul takes integer this,integer v returns real
            return s__vector_x[this] * s__vector_x[v] + s__vector_y[this] * s__vector_y[v] + s__vector_z[this] * s__vector_z[v]
        endfunction
        
        //Принимает вектор. Устанавливает вызывающий вектор равным сумме самого себя и принятого вектора.
        //Пусть в этом методе A - первый вектор, B - второй вектор (не путайте, выше был предоставлен вектор AB, сейчас поменял обозначения)
        // Bx= Ax+Bx, By= Ay+By, Bz = Az+Bz   <= изменяются параметры вектора B
        //пишем: local vector v = vector.create(1,2,3)
        //пишем: local vector w = vector.create(1,0,3)
        //пишем: local real r = v.vectoradd(w)
        //результат: вектор v равен 2 2 6, вектор w не изменился
        function s__vector_vectoradd takes integer this,integer v returns nothing
            set s__vector_x[this]=s__vector_x[this] + s__vector_x[v]
            set s__vector_y[this]=s__vector_y[this] + s__vector_y[v]
            set s__vector_z[this]=s__vector_z[this] + s__vector_z[v]
        endfunction
        //аналогично как и метод vectoradd, только вычитывает
        function s__vector_vectorsub takes integer this,integer v returns nothing
            set s__vector_x[this]=s__vector_x[this] - s__vector_x[v]
            set s__vector_y[this]=s__vector_y[this] - s__vector_y[v]
            set s__vector_z[this]=s__vector_z[this] - s__vector_z[v]
        endfunction
        
        //Принимает вектор. Устанавливает вызывающий вектор равным векторному произведению самого себя и принятого вектора.
        //Пусть в этом методе A - первый вектор, B - второй вектор (не путайте, выше был предоставлен вектор AB, сейчас поменял обозначения)
        //Bx= (Ay*Bz - By*Az), By= (Az*Bx - Bz*Ax), Bz = (Ax*By - Bx*Ay)
        //пишем: local vector v = vector.create(1,0,0)
        //пишем: local vector w = vector.create(0,1,0)
        //пишем: local real r = v.vectormul(w)
        //результат: вектор v равен 0 0 1, вектор w не изменился
        function s__vector_vectormul takes integer this,integer v returns nothing
            local real x= s__vector_y[this] * s__vector_z[v] - s__vector_y[v] * s__vector_z[this]
            local real y= s__vector_z[this] * s__vector_x[v] - s__vector_z[v] * s__vector_x[this]
            local real z= s__vector_x[this] * s__vector_y[v] - s__vector_x[v] * s__vector_y[this]
            set s__vector_x[this]=x
            set s__vector_y[this]=y
            set s__vector_z[this]=z
        endfunction
        
        //Принимает вектор. Возвращает вектор равный вызывающему.
        //Смысл: эта функция создает копию-вектор, который принимает те же значения что у оригинала
        //пишем: local vector v = vector.create(1,0,0)
        //пишем: local vector w = vector.clone()
        //результат: вектор v равен 1 0 0, вектор w равен 1 0 0
        function s__vector_clone takes integer this returns integer
            local integer v=s__vector__allocate()
            set s__vector_x[v]=s__vector_x[this]
            set s__vector_y[v]=s__vector_y[this]
            set s__vector_z[v]=s__vector_z[this]
            return v
        endfunction      
        
        //Принимает вектор. Устанавливает значение вызывающего вектора равным принятому вектору.
        //В отличии от метода clone здесь не создается двойник, у нас уже имеется вектор. Не всегда имеет смысл создавать двойников
        //пишем: local vector v = vector.create(1,0,0)
        //пишем: local vector w = vector.create(0,1,0)
        //пишем: call v.copy(w)
        //результат: вектор v равен 0 1 0, вектор w равен 0 1 0
        function s__vector_copy takes integer this,integer p returns nothing
            set s__vector_x[this]=s__vector_x[p]
            set s__vector_y[this]=s__vector_y[p]
            set s__vector_z[this]=s__vector_z[p]
        endfunction
        
        //Принимает координаты x, y и z. Форсированное изменение координат вектора.
        //Изменяет текущий вектор.
        //пишем: local vector v = vector.create(1,0,0)
        //пишем: call v.change(1,1,1)
        //результат: вектор v равен 1 1 1
        function s__vector_change takes integer this,real x,real y,real z returns nothing
            set s__vector_x[this]=x
            set s__vector_y[this]=y
            set s__vector_z[this]=z
        endfunction
        
        
        //Принимает вектор. Вычисляет угол между двумя векторами.
        //Пусть в этом методе A - первый вектор, B - второй вектор (не путайте, выше был предоставлен вектор AB, сейчас поменял обозначения)
        //Вытекает из скалярного произведения AB*Cos(A)
        //CosA = AB/|A|*|B|, где AB = ax*bx + ay*by + az*bz и |A| = sqrt(ax*ax + ay*ay + az*az), |B| = sqrt(bx*bx + by*by + bz*bz)
        function s__vector_AngleBetweenVectors takes integer this,integer b returns real
            local real ab=s__vector_scalarmul(this,b) / ( s__vector_getlength(this) * s__vector_getlength(b) )
            return ab
        endfunction
        function s__vector_AngleBetweenVectors2 takes integer this,integer b returns real
            local real ab=s__vector_scalarmul(this,b) / ( s__vector_getlength(this) * s__vector_getlength(b) )
            return Acos(ab)
        endfunction
        
    

//library vectors ends
//===========================================================================
// 
// Еще одна карта
// 
//   Warcraft III map script
//   Generated by the Warcraft III World Editor
//   Date: Sun Oct 21 23:52:07 2018
//   Map Author: Неизвестно
// 
//===========================================================================

//***************************************************************************
//*
//*  Global Variables
//*
//***************************************************************************


function InitGlobals takes nothing returns nothing
endfunction

//***************************************************************************
//*
//*  Triggers
//*
//***************************************************************************

//===========================================================================
// Trigger: vectors
//
// Инициализация стандартного режима сражения для всех игроков
//===========================================================================
//TESH.scrollpos=60
//TESH.alwaysfold=0


function InitCustomTriggers takes nothing returns nothing
    //Function not found: call InitTrig_vectors()
endfunction

//===========================================================================
function RunInitializationTriggers takes nothing returns nothing
    call ConditionalTriggerExecute(gg_trg_vectors)
endfunction

//***************************************************************************
//*
//*  Players
//*
//***************************************************************************

function InitCustomPlayerSlots takes nothing returns nothing

    // Player 0
    call SetPlayerStartLocation(Player(0), 0)
    call SetPlayerColor(Player(0), ConvertPlayerColor(0))
    call SetPlayerRacePreference(Player(0), RACE_PREF_HUMAN)
    call SetPlayerRaceSelectable(Player(0), true)
    call SetPlayerController(Player(0), MAP_CONTROL_USER)

endfunction

function InitCustomTeams takes nothing returns nothing
    // Force: TRIGSTR_002
    call SetPlayerTeam(Player(0), 0)

endfunction

//***************************************************************************
//*
//*  Main Initialization
//*
//***************************************************************************

//===========================================================================
function main takes nothing returns nothing
    call SetCameraBounds(- 3328.0 + GetCameraMargin(CAMERA_MARGIN_LEFT), - 3584.0 + GetCameraMargin(CAMERA_MARGIN_BOTTOM), 3328.0 - GetCameraMargin(CAMERA_MARGIN_RIGHT), 3072.0 - GetCameraMargin(CAMERA_MARGIN_TOP), - 3328.0 + GetCameraMargin(CAMERA_MARGIN_LEFT), 3072.0 - GetCameraMargin(CAMERA_MARGIN_TOP), 3328.0 - GetCameraMargin(CAMERA_MARGIN_RIGHT), - 3584.0 + GetCameraMargin(CAMERA_MARGIN_BOTTOM))
    call SetDayNightModels("Environment\\DNC\\DNCLordaeron\\DNCLordaeronTerrain\\DNCLordaeronTerrain.mdl", "Environment\\DNC\\DNCLordaeron\\DNCLordaeronUnit\\DNCLordaeronUnit.mdl")
    call NewSoundEnvironment("Default")
    call SetAmbientDaySound("LordaeronSummerDay")
    call SetAmbientNightSound("LordaeronSummerNight")
    call SetMapMusic("Music", true, 0)
    call InitBlizzard()

call ExecuteFunc("jasshelper__initstructs15269843")

    call InitGlobals()
    call InitCustomTriggers()
    call ConditionalTriggerExecute(gg_trg_vectors) // INLINED!!

endfunction

//***************************************************************************
//*
//*  Map Configuration
//*
//***************************************************************************

function config takes nothing returns nothing
    call SetMapName("Еще одна карта")
    call SetMapDescription("Описание отсутствует")
    call SetPlayers(1)
    call SetTeams(1)
    call SetGamePlacement(MAP_PLACEMENT_USE_MAP_SETTINGS)

    call DefineStartLocation(0, 1792.0, - 1728.0)

    // Player setup
    call InitCustomPlayerSlots()
    call SetPlayerSlotAvailable(Player(0), MAP_CONTROL_USER)
    call InitGenericPlayerSlots()
endfunction




//Struct method generated initializers/callers:

function jasshelper__initstructs15269843 takes nothing returns nothing


endfunction
this - номер массива. работаем с двумя значениями.
сравни
Т.е по сути каждый я вызываю метод create, а конкретно allocator, то уже работает как next и prev в моем примере, ну и deallocate?
0
17
6 лет назад
0
Как она работает? Где об этом можно почитать?
В гугле. Это общая концепция программирования. Суть проста - каждый экземпляр какого-то типа хранит в себе ссылку на предыдущий экземпляр этого типа и на следующий (в твоем примере это массивы next и prev), таким образом позволяя пройтись по всем экземплярам этого типа. Но в показанном тобой коде реализация стремная, поскольку использование статичных массивов в виде
            set next[prev[this]] = next[this]
            set prev[next[this]] = prev[this]
это просто избыток. Если next и prev изменить из массва в обычные атрибуты, работа алгоритма не изменится, но код станет на много проще.
0
10
6 лет назад
0
GetLocalPlayer:
Как она работает? Где об этом можно почитать?
В гугле. Это общая концепция программирования. Суть проста - каждый экземпляр какого-то типа хранит в себе ссылку на предыдущий экземпляр этого типа и на следующий (в твоем примере это массивы next и prev), таким образом позволяя пройтись по всем экземплярам этого типа. Но в показанном тобой коде реализация стремная, поскольку использование статичных массивов в виде
            set next[prev[this]] = next[this]
            set prev[next[this]] = prev[this]
это просто избыток. Если next и prev изменить из массва в обычные атрибуты, работа алгоритма не изменится, но код станет на много проще.
А можно их вообще убрать?
1
17
6 лет назад
1
А можно их вообще убрать?
Можно. Но понадобится массив для хранения всех экземпляров структуры. Дело в том, что таймер обходит все экземпляры чтобы убавить оставшееся время воскрешения на 1 каждую секунду, это происходит внутри функции
static nothing update()
Ну и разумеется внутри функциий create и destroy вносить и убирать отработанные экземпляры в/из этого массива.
Принятый ответ
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.