Работаю в рамках 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
//
//
`
ОЖИДАНИЕ РЕКЛАМЫ...
0
9
3 месяца назад
0
пока адекватным решением для меня является следующее
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 можно заменить "немым" оператором, это будет решение
2
26
3 месяца назад
2
а зачем впринципе?
0
29
3 месяца назад
0
Забей на структуры, в 99% случаев можно и без них обойтись.
0
9
3 месяца назад
0
а зачем впринципе?
Я делал другой класс, который обрабатывает одномерные массивы юнитов group_alpha[номер юнита] , я хотел сделать методы для этой структуры , которые бы сохраняли в хэш-таблицу параметры юнита group_alpha[номер юнита].saveinteger(childid, integer) , и при присваивании присваивались через хэштаблицу также и все параметры group_alpha[номер юнита_1] = group_alpha[номер юнита_2]. Со вторым проблем нету, а вот с первым незадача.

Забей на структуры, в 99% случаев можно и без них обойтись.
У меня несколько библиотек, которые выполняют все это без структур, да. И я понимаю, что можно. Структура мне нужна , что бы 10 раз не переписывать одни и те же вещи. Аля проверка умер ли юнит из массива, если умер то на его место поставить последнего юнита из массива и разные методы дополнительные, которые работали бы через наследование.
0
9
3 месяца назад
0
Ну да, оказалось все намного сложнее, первый мой пример - ошибка. Если не вызывать 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
//
//
Принятый ответ
0
18
3 месяца назад
0
Решение через оператор unit
Обращение к полям юнита через индексы приведет к тому что с ростом проекта код станет сложно читать, `unit.target_y` против `unit.LoadReal(2)`
0
37
3 месяца назад
0
Мастера превратить код в нечитаемую кашу.
Привяжи айди инстанса структуры к unit custom value и расширяй сколько потребуется
0
9
3 месяца назад
0
Мастера превратить код в нечитаемую кашу
не не, тут прикол именно в том, что бы сделать код читаемым, например, вы создали такую структуру, как я описал в последнем сообщении, затем вы наследнуете ее, например так
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
Что позволяет, просто очень просто обращаться к отдельным свойствам класса через хэш-таблицу
0
18
2 месяца назад
0
Это можно сделать проще через функцию
func get_unit_gold(unit)
	return LoadInteger(GlobalHashtable, GetUnitHandle(unit), IDGold)
endfunc

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