Работаю в рамках vjass. Хотел бы понять, можно ли в структуре или вне структуры дополнить тип данных unit методами, Например, я хочу подвинуть юнита, обычно мы пишем
call SetUnitPosition(unit, X, Y)
А я бы хотел некую структуру, чтобы можно было писать
call unit.SetUnitPosition(X, Y)
В этом такая проблема , что если создать супер структуру UNIT
struct UNIT
unit un
endstruct
То по сути это будет int и следующий код будет ошибкой
local unit loc_un = GetSomeUnit()
local UNIT loc_UN = UNIT.create(loc_un)
set un = loc_UN
вообще можно переопределить оператор [] и тогда можно ссылаться на что-то, но можно ли создать некий "немой" оператор , что бы при обращении к структуре UNIT возвращался именно тип unit, что записан у него в переменную? Или можно как-то реализовать дополнение типу unit? было бы конечно идеально, если бы unit был бы наследуемым, но struct UNIT extends unit не работает

Ну да, оказалось все намного сложнее, первый мой пример - ошибка. Если не вызывать thistype.allocate() то переменным не будет выделяться память, однако все можно решить через хэш-таблицу и переопределение свойств класса через оператор.
Если есть желание обозвать свойства класса также как и нативки - это можно, но через костыль в виде дополнительного приватного имени, ибо jusshelper багует и пытается обозвать вызванную функцию внутри класса именем метода, даже без обращение через this.~ . прошерстил весь хайв, решения без костыля не нашел.
Также как и не нашел способа возвращать handle unit'а при стандартном обращении , аля "немой" оператор. Решение через оператор unit , самое оптимальное
Решение
//
// ==== Макрос для публичного свойства ==== 
//! textmacro OperatorProprety takes NAME, DTYPE, dtype, CHILDKEY
    method operator $NAME$ takes nothing returns $dtype$
        return Load$DTYPE$(this.hash, this, $CHILDKEY$)
    endmethod
    method operator $NAME$= takes $dtype$ value returns nothing
        call Save$DTYPE$(this.hash, this, $CHILDKEY$, value)
    endmethod
//! endtextmacro
//
// ==== Макрос для приватного свойства ==== 
//! textmacro PrivateOperatorProprety takes NAME, DTYPE, dtype, CHILDKEY
    private method operator $NAME$ takes nothing returns $dtype$
        return Load$DTYPE$(this.hash, this, $CHILDKEY$)
    endmethod
    private method operator $NAME$= takes $dtype$ value returns nothing
        call Save$DTYPE$(this.hash, this, $CHILDKEY$, value)
    endmethod
//! endtextmacro
//
// ==== Макрос для свойства только для чтения ==== 
//! textmacro ReadonlyOperatorProprety takes NAME, DTYPE, dtype, CHILDKEY
    method operator $NAME$ takes nothing returns $dtype$
        return Lib_Load$DTYPE$(thistype.hash, this, $CHILDKEY$)
    endmethod
    private method operator $NAME$= takes $dtype$ value returns nothing
        call Lib_Save$DTYPE$(thistype.hash, this, $CHILDKEY$, value)
    endmethod
//! endtextmacro
//
//
// ==== Переименование нативных функций ====
private function Lib_SetUnitPosition takes unit whichUnit, real newX, real newY returns nothing
    call SetUnitPosition(whichUnit,newX,newY)
endfunction
//
// ==== перемеиннование Save/Load Hashtable value
//! textmacro RenameHashtableFunc takes DTYPE, dtype
private function Lib_Save$DTYPE$ takes hashtable table, integer parentKey, integer childKey, $dtype$ value returns nothing
    call Save$DTYPE$(table,parentKey,childKey,value)
endfunction

private function Lib_Load$DTYPE$ takes hashtable table, integer parentKey, integer childKey returns $dtype$
    return Load$DTYPE$(table,parentKey,childKey)
endfunction
//! endtextmacro
//! runtextmacro RenameHashtableFunc("Integer", "integer")
//! runtextmacro RenameHashtableFunc("Real", "real")
//! runtextmacro RenameHashtableFunc("Boolean", "boolean")
//! runtextmacro RenameHashtableFunc("UnitHandle", "unit")
// =========================================
//
private struct UNIT
    private static hashtable hash
    //! novjass
    //private unit unit // Получение хэндла юнита
    //! endnovjass
    //! runtextmacro ReadonlyOperatorProprety("isin", "Boolean", "boolean", "0")
    //! runtextmacro ReadonlyOperatorProprety("unit", "UnitHandle", "unit", "1")
    //
    //
    method SetUnitPosition takes real newX,real newY returns nothing
        call Lib_SetUnitPosition(this.unit, newX, newY)
    endmethod
    //
    // Макросы для загрузки и сохранения
    //! textmacro SaveLoadHashtableMethod takes DTYPE, dtype
    method Load$DTYPE$ takes integer childKey returns $dtype$
        return Lib_Load$DTYPE$(thistype.hash, this, childKey)
    endmethod
    method Save$DTYPE$ takes integer childKey, $dtype$ value returns nothing
        call Lib_Save$DTYPE$(thistype.hash,this, childKey, value)
    endmethod
    //! endtextmacro
    // ==== Загрузка/Сохранение целочисленного принадлежащего юниту ================
    //! runtextmacro SaveLoadHashtableMethod("Integer", "integer")
    // ==== Загрузка/Сохранение логического принадлежащего юниту ===================
    //! runtextmacro SaveLoadHashtableMethod("Boolean", "boolean")
    // ==== Загрузка/Сохранение числа с плавающей точкой принадлежащего юниту =======
    //! runtextmacro SaveLoadHashtableMethod("Real", "real")
    //
    // ==== Констуркор ========================================
    static method create takes unit un returns thistype
        local thistype this = GetHandleId(un)
        set this.unit = un
        set this.isin = true
        return this
    endmethod
    //
    // ==== Деструктор ========================================
    method flush takes nothing returns nothing
        call FlushChildHashtable(thistype.hash, this)
    endmethod
    //
    // ==== Инициализация =====================================
    private static method onInit takes nothing returns nothing
        set hash = InitHashtable()
    endmethod
endstruct
//
//
`
ОЖИДАНИЕ РЕКЛАМЫ...
11
пока адекватным решением для меня является следующее
struct UNIT
        private unit un
        method operator unit takes nothing returns unit
            return this.un
        endmethod
        
        method SetPosition takes real X,real Y returns nothing
            call SetUnitPosition(this.un, X, Y)
        endmethod
        
        static method create takes unit un returns UNIT
            local UNIT this = GetHandleId(un)
            set this.un = un
            return this
        endmethod
endstruct
Если в этом примере определение оператора unit можно заменить "немым" оператором, это будет решение
30
Забей на структуры, в 99% случаев можно и без них обойтись.
11
а зачем впринципе?
Я делал другой класс, который обрабатывает одномерные массивы юнитов group_alpha[номер юнита] , я хотел сделать методы для этой структуры , которые бы сохраняли в хэш-таблицу параметры юнита group_alpha[номер юнита].saveinteger(childid, integer) , и при присваивании присваивались через хэштаблицу также и все параметры group_alpha[номер юнита_1] = group_alpha[номер юнита_2]. Со вторым проблем нету, а вот с первым незадача.

Забей на структуры, в 99% случаев можно и без них обойтись.
У меня несколько библиотек, которые выполняют все это без структур, да. И я понимаю, что можно. Структура мне нужна , что бы 10 раз не переписывать одни и те же вещи. Аля проверка умер ли юнит из массива, если умер то на его место поставить последнего юнита из массива и разные методы дополнительные, которые работали бы через наследование.
11
Ну да, оказалось все намного сложнее, первый мой пример - ошибка. Если не вызывать thistype.allocate() то переменным не будет выделяться память, однако все можно решить через хэш-таблицу и переопределение свойств класса через оператор.
Если есть желание обозвать свойства класса также как и нативки - это можно, но через костыль в виде дополнительного приватного имени, ибо jusshelper багует и пытается обозвать вызванную функцию внутри класса именем метода, даже без обращение через this.~ . прошерстил весь хайв, решения без костыля не нашел.
Также как и не нашел способа возвращать handle unit'а при стандартном обращении , аля "немой" оператор. Решение через оператор unit , самое оптимальное
Решение
//
// ==== Макрос для публичного свойства ==== 
//! textmacro OperatorProprety takes NAME, DTYPE, dtype, CHILDKEY
    method operator $NAME$ takes nothing returns $dtype$
        return Load$DTYPE$(this.hash, this, $CHILDKEY$)
    endmethod
    method operator $NAME$= takes $dtype$ value returns nothing
        call Save$DTYPE$(this.hash, this, $CHILDKEY$, value)
    endmethod
//! endtextmacro
//
// ==== Макрос для приватного свойства ==== 
//! textmacro PrivateOperatorProprety takes NAME, DTYPE, dtype, CHILDKEY
    private method operator $NAME$ takes nothing returns $dtype$
        return Load$DTYPE$(this.hash, this, $CHILDKEY$)
    endmethod
    private method operator $NAME$= takes $dtype$ value returns nothing
        call Save$DTYPE$(this.hash, this, $CHILDKEY$, value)
    endmethod
//! endtextmacro
//
// ==== Макрос для свойства только для чтения ==== 
//! textmacro ReadonlyOperatorProprety takes NAME, DTYPE, dtype, CHILDKEY
    method operator $NAME$ takes nothing returns $dtype$
        return Lib_Load$DTYPE$(thistype.hash, this, $CHILDKEY$)
    endmethod
    private method operator $NAME$= takes $dtype$ value returns nothing
        call Lib_Save$DTYPE$(thistype.hash, this, $CHILDKEY$, value)
    endmethod
//! endtextmacro
//
//
// ==== Переименование нативных функций ====
private function Lib_SetUnitPosition takes unit whichUnit, real newX, real newY returns nothing
    call SetUnitPosition(whichUnit,newX,newY)
endfunction
//
// ==== перемеиннование Save/Load Hashtable value
//! textmacro RenameHashtableFunc takes DTYPE, dtype
private function Lib_Save$DTYPE$ takes hashtable table, integer parentKey, integer childKey, $dtype$ value returns nothing
    call Save$DTYPE$(table,parentKey,childKey,value)
endfunction

private function Lib_Load$DTYPE$ takes hashtable table, integer parentKey, integer childKey returns $dtype$
    return Load$DTYPE$(table,parentKey,childKey)
endfunction
//! endtextmacro
//! runtextmacro RenameHashtableFunc("Integer", "integer")
//! runtextmacro RenameHashtableFunc("Real", "real")
//! runtextmacro RenameHashtableFunc("Boolean", "boolean")
//! runtextmacro RenameHashtableFunc("UnitHandle", "unit")
// =========================================
//
private struct UNIT
    private static hashtable hash
    //! novjass
    //private unit unit // Получение хэндла юнита
    //! endnovjass
    //! runtextmacro ReadonlyOperatorProprety("isin", "Boolean", "boolean", "0")
    //! runtextmacro ReadonlyOperatorProprety("unit", "UnitHandle", "unit", "1")
    //
    //
    method SetUnitPosition takes real newX,real newY returns nothing
        call Lib_SetUnitPosition(this.unit, newX, newY)
    endmethod
    //
    // Макросы для загрузки и сохранения
    //! textmacro SaveLoadHashtableMethod takes DTYPE, dtype
    method Load$DTYPE$ takes integer childKey returns $dtype$
        return Lib_Load$DTYPE$(thistype.hash, this, childKey)
    endmethod
    method Save$DTYPE$ takes integer childKey, $dtype$ value returns nothing
        call Lib_Save$DTYPE$(thistype.hash,this, childKey, value)
    endmethod
    //! endtextmacro
    // ==== Загрузка/Сохранение целочисленного принадлежащего юниту ================
    //! runtextmacro SaveLoadHashtableMethod("Integer", "integer")
    // ==== Загрузка/Сохранение логического принадлежащего юниту ===================
    //! runtextmacro SaveLoadHashtableMethod("Boolean", "boolean")
    // ==== Загрузка/Сохранение числа с плавающей точкой принадлежащего юниту =======
    //! runtextmacro SaveLoadHashtableMethod("Real", "real")
    //
    // ==== Констуркор ========================================
    static method create takes unit un returns thistype
        local thistype this = GetHandleId(un)
        set this.unit = un
        set this.isin = true
        return this
    endmethod
    //
    // ==== Деструктор ========================================
    method flush takes nothing returns nothing
        call FlushChildHashtable(thistype.hash, this)
    endmethod
    //
    // ==== Инициализация =====================================
    private static method onInit takes nothing returns nothing
        set hash = InitHashtable()
    endmethod
endstruct
//
//
Принятый ответ
18
Решение через оператор unit
Обращение к полям юнита через индексы приведет к тому что с ростом проекта код станет сложно читать, unit.target_y против unit.LoadReal(2)
38
Мастера превратить код в нечитаемую кашу.
Привяжи айди инстанса структуры к unit custom value и расширяй сколько потребуется
11
Мастера превратить код в нечитаемую кашу
не не, тут прикол именно в том, что бы сделать код читаемым, например, вы создали такую структуру, как я описал в последнем сообщении, затем вы наследнуете ее, например так
struct CAVE extends UNIT    
    method operator LastGold takes nothing returns integer
        return this.LoadInteger(this.thishandler.p)
    endmethod
    method operator LastGold= takes integer value returns nothing
        call this.SaveInteger(this.thishandler.p, value)
    endmethod
endstruct
Что позволяет, просто очень просто обращаться к отдельным свойствам класса через хэш-таблицу
18
Это можно сделать проще через функцию
func get_unit_gold(unit)
	return LoadInteger(GlobalHashtable, GetUnitHandle(unit), IDGold)
endfunc

А то что указано в решении, и зачем то сделано через шаблоны - это именно обращение к полям по индексу
Чтобы оставить комментарий, пожалуйста, войдите на сайт.