**1. Требуется редактор jngp(который может работать с мемхаком), либо jasscraft, либо иной способ, чтобы наработки с мемхаком корректно компились
  1. Сломанный массив Memory (который позволяет читать и писать в память)**
  2. Зачем это нужно ? для смены параметров скила (кд, дальность применения, и других данных), для определенного скила, который имеется у конкретного юнита
Собственно код.
function SetAbilityDataAInteger takes integer add,integer lvl,integer newdata returns nothing
    if Memory[add/4+0x54/4]>0 then
        set Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4 + (lvl-1)*26 + 8 ] = newdata
    endif
endfunction
function GetAbilityDataAInteger takes integer add,integer lvl  returns integer
    if Memory[add/4+0x54/4]>0 then
        return Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4 + (lvl-1)*26 + 8 ] 
    endif
    return 0
endfunction

function SetAbilityDataBInteger takes integer add,integer lvl,integer newdata returns nothing
    if Memory[add/4+0x54/4]>0 then
        set Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 + 9] = newdata
    endif
endfunction
function GetAbilityDataBInteger takes integer add,integer lvl returns integer
    if Memory[add/4+0x54/4]>0 then
      return Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 + 9]
    endif
    return 0
endfunction

function SetAbilityDataCInteger takes integer add,integer lvl,integer newdata returns nothing
    if Memory[add/4+0x54/4]>0 then
        set Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4 + (lvl-1)*26 + 10 ] = newdata
    endif
endfunction
function GetAbilityDataCInteger takes integer add,integer lvl returns integer
    if Memory[add/4+0x54/4]>0 then
        return Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4 + (lvl-1)*26 + 10 ]
    endif
    return 0
endfunction

function SetAbilityDataDInteger takes integer add,integer lvl,integer newdata returns nothing
    if Memory[add/4+0x54/4]>0 then
        set Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 + 11 ] = newdata
    endif
endfunction
function GetAbilityDataDInteger takes integer add,integer lvl returns integer
    if Memory[add/4+0x54/4]>0 then
        return Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 + 11 ]
    endif
    return 0
endfunction

function SetAbilityDataEInteger takes integer add,integer lvl,integer newdata returns nothing
    if Memory[add/4+0x54/4]>0 then
        set Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4 + (lvl-1)*26 + 12 ] = newdata
    endif
endfunction

function GetAbilityDataEInteger takes integer add,integer lvl,integer newdata returns integer
    if Memory[add/4+0x54/4]>0 then
        return Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4 + (lvl-1)*26 + 12 ]
    endif
    return 0
endfunction

function SetAbilityDataAReal takes integer add,integer lvl,real newdata returns nothing
    if Memory[add/4+0x54/4]>0 then
        set Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4 + (lvl-1)*26 + 8 ] = cleanInt(realToIndex(newdata))
    endif
endfunction
function GetAbilityDataAReal takes integer add,integer lvl returns real
    if Memory[add/4+0x54/4]>0 then
        return cleanReal(indexToReal( Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 + 8] ))
    endif
    return .0
endfunction

function SetAbilityDataBReal takes integer add,integer lvl,real newdata returns nothing
    if Memory[add/4+0x54/4]>0 then
        set Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 + 9] = cleanInt(realToIndex(newdata))
    endif
endfunction
function GetAbilityDataBReal takes integer add,integer lvl returns real
    if Memory[add/4+0x54/4]>0 then
        return cleanReal(indexToReal( Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 + 9] ))
    endif
    return .0
endfunction

function SetAbilityDataCReal takes integer add,integer lvl,real newdata returns nothing
    if Memory[add/4+0x54/4]>0 then
        set Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4 + (lvl-1)*26 + 10 ] = cleanInt(realToIndex(newdata))
    endif
endfunction
function GetAbilityDataCReal takes integer add,integer lvl returns real
    if Memory[add/4+0x54/4]>0 then
        return cleanReal(indexToReal( Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 + 10] ))
    endif
    return .0
endfunction

function SetAbilityDataDReal takes integer add,integer lvl,real newdata returns nothing
    if Memory[add/4+0x54/4]>0 then
        set Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 + 11 ] = cleanInt(realToIndex(newdata))
    endif
endfunction
function GetAbilityDataDReal takes integer add,integer lvl returns real
    if Memory[add/4+0x54/4]>0 then
        return cleanReal(indexToReal( Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 + 11] ))
    endif
    return .0
endfunction

function SetAbilityDataEReal takes integer add,integer lvl,real newdata returns nothing
    if Memory[add/4+0x54/4]>0 then
        set Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4 + (lvl-1)*26 + 12 ] = cleanInt(realToIndex(newdata))
    endif
endfunction
function GetAbilityDataEReal takes integer add,integer lvl returns real
    if Memory[add/4+0x54/4]>0 then
        return cleanReal(indexToReal( Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 + 12] ))
    endif
    return .0
endfunction

function SetAbilityDataCast takes integer add,integer lvl,real newdata returns nothing
    if Memory[add/4+0x54/4]>0 then
        set Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 + 1 ] = cleanInt(realToIndex(newdata))
    endif
endfunction

function GetAbilityDataCast takes integer add,integer lvl returns real
    if Memory[add/4+0x54/4]>0 then
        return cleanReal(indexToReal(Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 + 1 ] ))
    endif
    return .0
endfunction

function SetAbilityDataDur takes integer add,integer lvl,real newdata returns nothing
    if Memory[add/4+0x54/4]>0 then
        set Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 + 2 ] = cleanInt(realToIndex(newdata))
    endif
endfunction


function GetAbilityDataDur takes integer add,integer lvl returns real
    if Memory[add/4+0x54/4]>0 then
        return cleanReal(indexToReal(Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 +2] ))
    endif
    return .0
endfunction

function SetAbilityDataHeroDur takes integer add,integer lvl,real newdata returns nothing
    if Memory[add/4+0x54/4]>0 then
        set Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 + 3 ] = cleanInt(realToIndex(newdata))
    endif
endfunction
function GetAbilityDataHeroDur takes integer add,integer lvl returns real
    if Memory[add/4+0x54/4]>0 then
        return cleanReal(indexToReal(Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 +3] ))
    endif
    return .0
endfunction

function SetAbilityDataCooldown takes integer add,integer lvl,real newdata returns nothing
    if Memory[add/4+0x54/4]>0 then
        set Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4 + (lvl-1)*26 + 5 ] = cleanInt(realToIndex(newdata))
    endif
endfunction
function GetAbilityDataCooldown takes integer add,integer lvl returns real
    if Memory[add/4+0x54/4]>0 then
        return cleanReal(indexToReal(Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 +5] ))
    endif
    return .0
endfunction

function SetAbilityDataHeroArea takes integer add,integer lvl,real newdata returns nothing
    if Memory[add/4+0x54/4]>0 then
        set Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 + 6 ] = cleanInt(realToIndex(newdata))
    endif
endfunction
function GetAbilityDataHeroArea takes integer add,integer lvl returns real
    if Memory[add/4+0x54/4]>0 then
        return cleanReal(indexToReal(Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 +6] ))
    endif
    return .0
endfunction

function SetAbilityDataHeroRng takes integer add,integer lvl,real newdata returns nothing
    if Memory[add/4+0x54/4]>0 then
        set Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 + 7 ] = cleanInt(realToIndex(newdata))
    endif
endfunction
function GetAbilityDataHeroRng takes integer add,integer lvl returns real
    if Memory[add/4+0x54/4]>0 then
        return cleanReal(indexToReal(Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  + (lvl-1)*26 +7] ))
    endif
    return .0
endfunction

function SetAbilityManaCostAddr2 takes integer add,integer lvl,integer mc returns nothing
    if Memory[add/4+0x54/4]>0 then
        set Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4  +(lvl-1)*26 + 4 ] = mc
    endif
endfunction
function GetAbilityManaCostAddr2 takes integer add,integer lvl returns integer
    if Memory[add/4+0x54/4]>0 then
        return Memory[ Memory[Memory[add/4+0x54/4]/4+0x54/4]/4 + (lvl-1)*26 ]
    endif
    return 0
endfunction
function GetAbilityMaxLevel2 takes integer abil returns integer 
    return Memory[Memory[abil/4+0x54/4]/4+15]
endfunction


//Вспомогательные функции
function GetAbilityTableId takes integer a returns integer
    return Memory[Memory[a/4+0x54/4]/4+0x54/4]
endfunction
function SetAbilityTableId takes integer a,integer TableId returns nothing
    set Memory[Memory[a/4+0x54/4]/4+0x54/4] = TableId
endfunction
function GetAbilityDataId takes integer a returns integer 
    return Memory[a/4+0x54/4]
endfunction
function SetAbilityDataId takes integer a, integer DataId returns nothing 
    set Memory[a/4+0x54/4] = DataId
endfunction
// Копирование данных о скиле, и присвоению абилити новых данных.
function CloneAbilityData takes integer a returns nothing 
local integer Address = malloc(23*4)
local integer AddressTabl = malloc(22*4+26*4*GetAbilityMaxLevel2(a) + 4 )
call CopyMemory(Address,GetAbilityDataId(a),22*4)
call CopyMemory(AddressTabl,GetAbilityTableId(a),26*4*GetAbilityMaxLevel2(a) + 4)
call SetAbilityTableId(a,AddressTabl)
call SetAbilityDataId(a,Address)
endfunction
чтобы можно было менять данные, нужно использовать функцию: function CloneAbilityData takes integer a returns nothing
для конкретного скила у конкретного юнита. после применения этой функции, можно модифицировать скил, рекомендовано, часто не использовать эту функцию.
Пример:
local integer a = GetUnitAbility(u,'A001')
call CloneAbilityData(a)
call SetAbilityDataHeroRng(a,1,5000)
call SetAbilityDataBReal(a,1,450)
`
ОЖИДАНИЕ РЕКЛАМЫ...
15
Если я буду использовать либу из твоего анти мапхака, то это все будет работать?
3
Сломанный массив Memory, можна подробно про ето
32
Vitalik8:
Сломанный массив Memory, можна подробно про ето
Тему про мемхак читаем... ссылка
Этот комментарий удален
21
Короче, было лишних многобукаф, основная суть следующая:
  • Если в игре заюзать изменение ренджа абилки (во всяком случае, до 99999), то после выхода из вара за просмотром реплея такой игры или участием в ней будет сообщение про фатал еррор. Не смертельно и даже не то чтобы неприятно, но просто факт.
  • Такая абилка становится какой-то особенной, "отделенной" - не подвергается по крайней мере некоторым изменениям, которые должны глобально влиять на все такие абилки всех таких юнитов.
16
ClotPh:
Короче, было лишних многобукаф, основная суть следующая:
сколько уровней у абилки? какая абилка? какое поле менял?
21
Код рассчитан на то, чтобы менять рендж в принципе любой таргетабл-юнит абилити.
Да вот весь код, это изначально бафф, который накидывается на цель и отхиливает ей хп и ману, но это чтобы было.
А основная суть баффа - что если под ним скастовать любую таргетабл-юнит абилити, то она у кастера становится с анлимитед каст ренджем (на все уровни).
Тут из-за "предусмотрительности" на всякий случай прописано вплоть до 10 уровней (хотя на деле у абил практически никогда больше 5 не бывает, а у предметных вообще 1).
Мб в этом дело?
Тогда надо еще макс. лвл абилы узнавать и специально рендж продрючивать только на существующее число лвлов?

НО опять же - с глобальными изменениями кулдаунов таких траблов не было.
Вот весь код спелла (юнит для функции регистрируется при изучении заклинания). Все действует, "дагоны" с анлимитед каст ренджем рулят, "шаклы расты" тоже. Но фаталит.
***************************************
function UnlimitedAbility takes nothing returns nothing
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: u5, u6
local unit u5 = GetTriggerUnit()
local unit u6 = GetSpellTargetUnit()
local integer a = GetUnitAbility(u5,GetSpellAbilityId())
local integer i = 0
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
call CloneAbilityData(a)
ДЕЛАЕМ НЕОГРАНИЧЕННУЮ ДАЛЬНОСТЬ СПОСОБНОСТИ, ЕСЛИ ОНА УЖЕ НЕ НЕОГРАНИЧЕННАЯ
if (u6 != null) then
loop
exitwhen i > 10
set i = i+1
if GetAbilityDataHeroRng(a, i) < 99999 then
call SetAbilityDataHeroRng(a,i,99999)
call UnitRemoveAbilityBJ( 'A27A', u5 )
call UnitRemoveBuffBJ( 'B0H6', u5 )
endif
endloop
endif
ДЕЛАЕМ НЕОГРАНИЧЕННУЮ ДАЛЬНОСТЬ СПОСОБНОСТИ, ЕСЛИ ОНА УЖЕ НЕ НЕОГРАНИЧЕННАЯ - ЗАКРЫТО.
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: u5, u6
set u5 = null
set u6 = null
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
endfunction
function Unlimited2 takes nothing returns nothing
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: t, u5, u6, heroadded, heroaction
local timer t = GetExpiredTimer()
local unit u5=LoadUnitHandle(udg_Hash,GetHandleId(t),2)
local unit u6=LoadUnitHandle(udg_Hash,GetHandleId(t),1)
local trigger heroadded=LoadTriggerHandle(udg_Hash,GetHandleId(t),20)
local triggeraction heroaction=LoadTriggerActionHandle(udg_Hash,GetHandleId(t),21)
local integer i=LoadInteger(udg_Hash,GetHandleId(t),3)
local real r=LoadReal(udg_Hash,GetHandleId(t),4)
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
set i = i + 1
call SaveInteger(udg_Hash,GetHandleId(t),3,i)
if (i==100) or (i==200) or (i==300) or (i==400) or (i==500) or (i==600) or (i==700) or (i==800) or (i==900) or (i==1000) then
call AddSpecialEffectTargetUnitBJ( "chest", u6, "Irrespective4.mdl" )
call ConditionalTriggerExecute( gg_trg_destroyspeceffect )
call SetUnitManaBJ( u6, ( GetUnitStateSwap(UNIT_STATE_MANA, u6) + r ) )
call SetUnitLifeBJ( u6, ( GetUnitStateSwap(UNIT_STATE_LIFE, u6) + r ) )
else
endif
if i > 1000 or (GetUnitAbilityLevelSwapped('A27A',u6) == 0) then
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(udg_Hash,GetHandleId(t))
call UnitRemoveAbilityBJ( 'A27A', u6 )
call UnitRemoveBuffBJ( 'B0H6', u6 )
call TriggerRemoveAction(heroadded,heroaction)
call DestroyTrigger(heroadded)
endif
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: t, u5, u6, heroadded, heroaction
set t = null
set u5 = null
set u6 = null
set heroadded = null
set heroaction = null
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
endfunction
function Unlimited takes nothing returns nothing
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: t, u5, u6, heroadded, heroaction
local timer t = CreateTimer()
local unit u5 = GetTriggerUnit()
local unit u6 = GetSpellTargetUnit()
local trigger heroadded
local triggeraction heroaction
local real r
local integer i = 0
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
if ( GetSpellAbilityId() == 'A278' ) then
set r = 30 * (GetUnitAbilityLevelSwapped('A278',u5))
call UnitAddAbilityBJ( 'A27A', u6 )
call UnitMakeAbilityPermanent (u6, true, 'A27A')
set heroadded=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(heroadded, EVENT_PLAYER_UNIT_SPELL_EFFECT)
set heroaction = TriggerAddAction(heroadded,function UnlimitedAbility)
call SaveUnitHandle(udg_Hash,GetHandleId(t),2,u5)
call SaveUnitHandle(udg_Hash,GetHandleId(t),1,u6)
call SaveReal(udg_Hash,GetHandleId(t),4,r)
call SaveInteger (udg_Hash,GetHandleId(t),3,i)
call SaveTriggerHandle(udg_Hash,GetHandleId(t),20,heroadded)
call SaveTriggerActionHandle(udg_Hash,GetHandleId(t),21,heroaction)
call TimerStart (t, 0.01, true, function Unlimited2)
else
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(udg_Hash,GetHandleId(t))
endif
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: t, u5, u6, heroadded, heroaction
set t = null
set u5 = null
set u6 = null
set heroadded = null
set heroaction = null
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
endfunction
16
ClotPh:
мне кажется, или ты каждый раз клонируешь абилку, даже если её не требуется модифицировать?
21
Ага, спасибо. Занесу под ифзенэлс, в любом случае так правильнее будет.
Дело только в этом? Вообще у кого-нибудь еще сабж фаталил подобным образом?
16
ClotPh:
Дело только в этом? Вообще у кого-нибудь еще сабж фаталил подобным образом?
как и в любом случае, когда причина неизвестна - удаляй код построчно, пока проблема не исчезнет. так и найдешь причину
21
Да, на 99% уверенность, что дело в избыточном клонировании. Основную карту уже сейчас переоткрывать времени нет, но после проверки в дополнительной (клонировалась только одна абилка, у которой рендж фактически был увеличен) вар НЕ сфаталил при выходе. Все понятно, ок, потом разберемся.
***
Нет. Все равно фаталит в основной карте.
В тест-карте не фаталило.
Если играть в основную карту без героя с этой абилой - не фаталит.
У этого героя еще из того, что не используется ни у кого больше, в другом спелле юзается AddUnitMPRegen из основного мемхака, но крайне сомнительно, что дело в ней...
Текущий код (еще исправлено отсутствие проверки баффа, жесткая ошибка, теперь способность ДЕЙСТВИТЕЛЬНО работает правильно - в чем она ЖЕСТОКО косила раньше, пусть интересующиеся юзеры разберутся сами, но в основной карте фаталит).
PS Ниже я Клон в принципе не могу поставить, проблема-то в том, что для вызова GetAbilityDataHeroRng УЖЕ надо абилку склонировать.
***********
function UnlimitedAbility takes nothing returns nothing
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: u5, u6
local unit u5 = GetTriggerUnit()
local unit u6 = GetSpellTargetUnit()
local integer a = GetUnitAbility(u5,GetSpellAbilityId())
local integer i = 0
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
ДЕЛАЕМ НЕОГРАНИЧЕННУЮ ДАЛЬНОСТЬ СПОСОБНОСТИ, ЕСЛИ ОНА УЖЕ НЕ НЕОГРАНИЧЕННАЯ
if (u6 != null) and UnitHasBuffBJ(u5,'B0H6') == true then
loop
exitwhen i > 10
set i = i+1
call CloneAbilityData(a)
if GetAbilityDataHeroRng(a, i) < 99999 then
call SetAbilityDataHeroRng(a,i,99999)
call UnitRemoveAbilityBJ( 'A27A', u5 )
call UnitRemoveBuffBJ( 'B0H6', u5 )
endif
endloop
endif
ДЕЛАЕМ НЕОГРАНИЧЕННУЮ ДАЛЬНОСТЬ СПОСОБНОСТИ, ЕСЛИ ОНА УЖЕ НЕ НЕОГРАНИЧЕННАЯ - ЗАКРЫТО.
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: u5, u6
set u5 = null
set u6 = null
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
endfunction
function Unlimited2 takes nothing returns nothing
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: t, u5, u6, heroadded, heroaction
local timer t = GetExpiredTimer()
local unit u5=LoadUnitHandle(udg_Hash,GetHandleId(t),2)
local unit u6=LoadUnitHandle(udg_Hash,GetHandleId(t),1)
local trigger heroadded=LoadTriggerHandle(udg_Hash,GetHandleId(t),20)
local triggeraction heroaction=LoadTriggerActionHandle(udg_Hash,GetHandleId(t),21)
local integer i=LoadInteger(udg_Hash,GetHandleId(t),3)
local real r=LoadReal(udg_Hash,GetHandleId(t),4)
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
set i = i + 1
call SaveInteger(udg_Hash,GetHandleId(t),3,i)
if (i==100) or (i==200) or (i==300) or (i==400) or (i==500) or (i==600) or (i==700) or (i==800) or (i==900) or (i==1000) then
call AddSpecialEffectTargetUnitBJ( "chest", u6, "Irrespective4.mdl" )
call ConditionalTriggerExecute( gg_trg_destroyspeceffect )
call SetUnitManaBJ( u6, ( GetUnitStateSwap(UNIT_STATE_MANA, u6) + r ) )
call SetUnitLifeBJ( u6, ( GetUnitStateSwap(UNIT_STATE_LIFE, u6) + r ) )
else
endif
if i > 1000 or (GetUnitAbilityLevelSwapped('A27A',u6) == 0) then
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(udg_Hash,GetHandleId(t))
call UnitRemoveAbilityBJ( 'A27A', u6 )
call UnitRemoveBuffBJ( 'B0H6', u6 )
call TriggerRemoveAction(heroadded,heroaction)
call DestroyTrigger(heroadded)
endif
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: t, u5, u6, heroadded, heroaction
set t = null
set u5 = null
set u6 = null
set heroadded = null
set heroaction = null
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
endfunction
function Unlimited takes nothing returns nothing
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: t, u5, u6, heroadded, heroaction
local timer t = CreateTimer()
local unit u5 = GetTriggerUnit()
local unit u6 = GetSpellTargetUnit()
local trigger heroadded
local triggeraction heroaction
local real r
local integer i = 0
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
if ( GetSpellAbilityId() == 'A278' ) then
set r = 30 * (GetUnitAbilityLevelSwapped('A278',u5))
call UnitAddAbilityBJ( 'A27A', u6 )
call UnitMakeAbilityPermanent (u6, true, 'A27A')
set heroadded=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(heroadded, EVENT_PLAYER_UNIT_SPELL_EFFECT)
set heroaction = TriggerAddAction(heroadded,function UnlimitedAbility)
call SaveUnitHandle(udg_Hash,GetHandleId(t),2,u5)
call SaveUnitHandle(udg_Hash,GetHandleId(t),1,u6)
call SaveReal(udg_Hash,GetHandleId(t),4,r)
call SaveInteger (udg_Hash,GetHandleId(t),3,i)
call SaveTriggerHandle(udg_Hash,GetHandleId(t),20,heroadded)
call SaveTriggerActionHandle(udg_Hash,GetHandleId(t),21,heroaction)
call TimerStart (t, 0.01, true, function Unlimited2)
else
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(udg_Hash,GetHandleId(t))
endif
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: t, u5, u6, heroadded, heroaction
set t = null
set u5 = null
set u6 = null
set heroadded = null
set heroaction = null
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
endfunction
21
/
Так и не понятно...
Только что с игры на основной карте НЕ за Райза - фатала после выхода из игры нет.
Тест-карта с Райзом (проюзаны все его активные абилы, всем проставлен безлим рендж через ульту) - фатала после выхода из игры нет.
Основная карта, пикается Райз, вводится -lvlup, юзается его ульта и за ней любая абила, чтобы дать ей безлим рендж. Все, после выхода из игры (хоть немедленно, хоть когда) - однозначный фатал.
Дело не "в любой абиле" - точно были вот ща проюзаны все абилы без ульты и все нормально. Точно что-то связано с ультой, а она выше...
В чём прикол, не понятно. Даже равкоды абил абсолютно одинаковые... В основной карте гораздо больше кода, РО, ланда и вообще всего, но при чем тут это?
Мля, ну, может, код в основной карте чем-то отличается от вышенаписанного и это я идентифицировать не могу? Вот в основной
/
function UnlimitedAbility takes nothing returns nothing
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: u5, u6
local unit u5= GetTriggerUnit()
local unit u6= GetSpellTargetUnit()
local integer a= GetUnitAbility(u5 , GetSpellAbilityId())
local integer i= 0
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
ДЕЛАЕМ НЕОГРАНИЧЕННУЮ ДАЛЬНОСТЬ СПОСОБНОСТИ, ЕСЛИ ОНА УЖЕ НЕ НЕОГРАНИЧЕННАЯ
if ( u6 != null ) and UnitHasBuffBJ(u5, 'B0H6') == true then
loop
exitwhen i > 10
set i=i + 1
call CloneAbilityData(a)
if GetAbilityDataHeroRng(a , i) < 99999 then
call SetAbilityDataHeroRng(a , i , 99999)
call UnitRemoveAbilityBJ('A27A', u5)
call UnitRemoveBuffBJ('B0H6', u5)
endif
endloop
endif
ДЕЛАЕМ НЕОГРАНИЧЕННУЮ ДАЛЬНОСТЬ СПОСОБНОСТИ, ЕСЛИ ОНА УЖЕ НЕ НЕОГРАНИЧЕННАЯ - ЗАКРЫТО.
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: u5, u6
set u5=null
set u6=null
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
endfunction
function Unlimited2 takes nothing returns nothing
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: t, u5, u6, heroadded, heroaction
local timer t= GetExpiredTimer()
local unit u5=LoadUnitHandle(udg_Hash, GetHandleId(t), 2)
local unit u6=LoadUnitHandle(udg_Hash, GetHandleId(t), 1)
local trigger heroadded=LoadTriggerHandle(udg_Hash, GetHandleId(t), 20)
local triggeraction heroaction=LoadTriggerActionHandle(udg_Hash, GetHandleId(t), 21)
local integer i=LoadInteger(udg_Hash, GetHandleId(t), 3)
local real r=LoadReal(udg_Hash, GetHandleId(t), 4)
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
set i=i + 1
call SaveInteger(udg_Hash, GetHandleId(t), 3, i)
if ( i == 100 ) or ( i == 200 ) or ( i == 300 ) or ( i == 400 ) or ( i == 500 ) or ( i == 600 ) or ( i == 700 ) or ( i == 800 ) or ( i == 900 ) or ( i == 1000 ) then
call AddSpecialEffectTargetUnitBJ("chest", u6, "Irrespective4.mdl")
call ConditionalTriggerExecute(gg_trg_destroyspeceffect)
call SetUnitManaBJ(u6, ( GetUnitStateSwap(UNIT_STATE_MANA, u6) + r ))
call SetUnitLifeBJ(u6, ( GetUnitStateSwap(UNIT_STATE_LIFE, u6) + r ))
else
endif
if i > 1000 or ( GetUnitAbilityLevelSwapped('A27A', u6) == 0 ) then
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(udg_Hash, GetHandleId(t))
call UnitRemoveAbilityBJ('A27A', u6)
call UnitRemoveBuffBJ('B0H6', u6)
call TriggerRemoveAction(heroadded, heroaction)
call DestroyTrigger(heroadded)
endif
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: t, u5, u6, heroadded, heroaction
set t=null
set u5=null
set u6=null
set heroadded=null
set heroaction=null
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
endfunction
function Unlimited takes nothing returns nothing
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: t, u5, u6, heroadded, heroaction
local timer t= CreateTimer()
local unit u5= GetTriggerUnit()
local unit u6= GetSpellTargetUnit()
local trigger heroadded
local triggeraction heroaction
local real r
local integer i= 0
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
if ( GetSpellAbilityId() == 'A278' ) then
set r=30 * ( GetUnitAbilityLevelSwapped('A278', u5) )
call UnitAddAbilityBJ('A27A', u6)
call UnitMakeAbilityPermanent(u6, true, 'A27A')
set heroadded=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(heroadded, EVENT_PLAYER_UNIT_SPELL_EFFECT)
set heroaction=TriggerAddAction(heroadded, function UnlimitedAbility)
call SaveUnitHandle(udg_Hash, GetHandleId(t), 2, u5)
call SaveUnitHandle(udg_Hash, GetHandleId(t), 1, u6)
call SaveReal(udg_Hash, GetHandleId(t), 4, r)
call SaveInteger(udg_Hash, GetHandleId(t), 3, i)
call SaveTriggerHandle(udg_Hash, GetHandleId(t), 20, heroadded)
call SaveTriggerActionHandle(udg_Hash, GetHandleId(t), 21, heroaction)
call TimerStart(t, 0.01, true, function Unlimited2)
else
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(udg_Hash, GetHandleId(t))
endif
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: t, u5, u6, heroadded, heroaction
set t=null
set u5=null
set u6=null
set heroadded=null
set heroaction=null
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
endfunction
/
АГА! Появилась наконец идея... Основная-то карта через виджетайзер проходит!!!
А там абилы жмутся!!!
Может быть, что из-за этого?! И чо тогда - абилы не жать или с фаталом смириться?
WarCraft III Widgetizer 1.9 - мб снять галочку с Abilities? Но насколько тогда ухудшится скорость игры и загрузки? На размер-то пофигу...
16
ClotPh:
у тебя clone идет в цикле, создавая кучу мусора. достань его из цикла для начала.
раз у автора работает, то проблема в твоем написании где-то
21
Ну код станет оптимальнее, ок, но не в этом же дело сейчас.
Все-таки мне кажется, что это из-за виджетайзера. Потому что он мне так уже уничтожал москитных даммиков, считая их "неиспользуемыми объектами", а мне потом разбираться, почему вместо файерболлов пустота летала.
Он, наверное, что-то там корежит в данных способностей при сжатии.
Потому что коды ведь одинаковые в тест-карте и в основной? (Если нет - пальцем на различия). А в тест-карте не фаталит, а в основной фаталит. А основная отличается:
  • Тем, что в ней дохрена всего;
  • Тем, что сжималась виджетайзером и оптимайзером.
Влияет ли первая причина? Вряд ли. Вывод...
***
Нде. Чушь какая-то. Дошло сейчас прогнать тест-карту через виджик и оптимайзер (т. е. протестировать так же, как основную) - нет фатала.
Оптимизация одинаковая. Код спелла одинаковый.
Одна карта фаталит вар после выхода из него, если спелл юзается, другая нет. Втф?
А что вообще будет, кстати, если клонабилити не писать?
Функция не подействует, код не скомпилируется или?...
замечание от GF RaiseD: 1.4 (злоупотребление форматированием) Существуют каты, блоки кода и форматирование.
16
ClotPh:
Ну код станет оптимальнее, ок, но не в этом же дело сейчас.
?? ты вызываешь аллокацию сотен абилок, забивая память мусором. ты очень быстро израсходуешь лимит и упрешься в несовершенство представленной системы в плане того, что для данных уже не будет носителя нормального. поэтому это важно.
не знаю никаких багов, связанных со сжатием виджетайзером, тем более - если речь идет о том, что фатал именно в полной версии. сравни код, мб оптимизатор что-то поменял
21
Господи, ну что там за лимит-то еще такой, подробнее можно?
Но все равно переместить CloneAbility не проблема, просто не вижу смысла из-за все-таки НЕ наиглавнейшей задачи в XXX-й раз изменять код (у ульта очень большой кд, он слишком часто юзаться не будет, даже с этим лимитом мифическим "сотен" там не наберется, если за одно использование пройдет 10 клонабилитей, + любая абила, на которую ульт уже воздействовал, клонабилити новых уже НЕ вызывает, т. к. по ифзенэлсу не проходит).
Фатал в основной карте происходит после ОДНОГО юза ульты и ОДНОГО увеличения ренджа (т. е. вызывается десять клонабилитей). Точнее, его достаточно, чтобы после выхода из вара был фатал. Все еще уверенность, что дело в этом "превышении лимита"?
Зачем вообще, еще раз, юзается функция клонабилити и что будет, если ее не юзать? Вот почему, например, в основном мемхаке есть функции, которые просто меняют параметры, а тут еще необходима вот эта клонабилити? Проконсультируйте, если не трудно.
16
ClotPh:
Господи, ну что там за лимит-то еще такой, подробнее можно?
данные способностей, за редким исключением, хранятся в куче - объекте памяти, куда сбрасывается всё что угодно. когда способность первый раз запрашивается, движок создает под неё объект и размещает в куча память равную количеству уровней * 15 или сколько там полей на уровень. Затем он начинает компилировать абилку так, чтобы в любой момент можно было получить инфу о том, какие параметры нужны сейчас.
Например, у тебя болт с 10 уровнями. Как и все скиллы, он хранит ссылку на свои данные внутри себя. двиг идет туда, зная уровень, который щас-щас вот кинут. В определенных адресах этой таблицы-структуры данных лежат длительность и урон. А перед этим идет ссылка на точный адрес начала данных, для страховки.
И вот ты такой хочешь изменить абилку чисто для себя, например - для того, чтобы у конкретного героя абилка имела половинный манакост. При этом абилка может быть у кого-то еще, но у этого кого-то манакост резаться не должен. Если ты изменишь мк локально, поймаешь десинк, если дойдет до сравнения манапула. ПОэтому используется клонирование.
Клонирование основано на том, что создается изначально в редакторе/слк Х способностей с У уровней. Но вместо того, чтобы хранить свои данные в своих структурах, здесь автор записывает вместо стандартных значений те, которые нужны для клонированной абилки. Затем он подменяет ссылку, стоящую у болта, на ссылку, указывающую на структуру абилки-подмены. В результате получается два болта - один берет инфу из одного места, остальные - из другого. Эта технология вполне законна, но если ты выйдешь за лимит, и у тебя не будет споосбностей, на место которых можно склонировать данные, операция не удастся.
Болт 1: бла бла бла ссылка на инфу блабла
Болт 2: бла бла бла ссылка на другое место блаблалба
В твоем случае "другое место" могло быть занято. А может, и косяк в коде автора. Я данный прием не использую, поэтому судить не могу. Просто по опыту предполагаю самое очевидное - неправильное внедрение, раз у автора работает.
ну и да, если у тебя абилка гарантирвоано не повторяется, то и клонировать её не надо, очевидно. это так, мелочи уже
21
Ладно, спасибо... Пока выяснилось, что если CloneAbility не писать, карта просто не запускается (ну примерно этого и ожидалось).
16
ClotPh:
Ладно, спасибо... Пока выяснилось, что если CloneAbility не писать, карта просто не запускается (ну примерно этого и ожидалось).
эти факты друг с другом не связаны примерно никак, ибо при запуске анализируется только синтаксис, а не корректность
6
ClotPh:
Ну код станет оптимальнее, ок, но не в этом же дело сейчас.
Все-таки мне кажется, что это из-за виджетайзера. Потому что он мне так уже уничтожал москитных даммиков, считая их "неиспользуемыми объектами", а мне потом разбираться, почему вместо файерболлов пустота летала.
Он, наверное, что-то там корежит в данных способностей при сжатии.
Потому что коды ведь одинаковые в тест-карте и в основной? (Если нет - пальцем на различия). А в тест-карте не фаталит, а в основной фаталит. А основная отличается:
  • Тем, что в ней дохрена всего;
  • Тем, что сжималась виджетайзером и оптимайзером.
Влияет ли первая причина? Вряд ли. Вывод...
***
Нде. Чушь какая-то. Дошло сейчас прогнать тест-карту через виджик и оптимайзер (т. е. протестировать так же, как основную) - нет фатала.
Оптимизация одинаковая. Код спелла одинаковый.
Одна карта фаталит вар после выхода из него, если спелл юзается, другая нет. Втф?
А что вообще будет, кстати, если клонабилити не писать?
Функция не подействует, код не скомпилируется или?...
все из-за malloc, варик не может очистить память из данного диапазона. На днях выложу код, делал через абилу с 1кк лвл, туда и писал данные, фаталов после этого небыло (главное не создавать такую абилу в редакторе)
function CloneAbilityData takes integer a returns nothing 
local integer Address = malloc(23*4)
local integer AddressTabl = malloc(22*4+26*4*GetAbilityMaxLevel2(a) + 4 ) //Вот сдесь надо отказаться от malloc, и проблема решится.
call CopyMemory(Address,GetAbilityDataId(a),22*4)
call CopyMemory(AddressTabl,GetAbilityTableId(a),26*4*GetAbilityMaxLevel2(a) + 4)
call SetAbilityTableId(a,AddressTabl)
call SetAbilityDataId(a,Address)
endfunction
21
Ну т. е. функцию CloneAbilityData надо переписанную потом будет просто вставить?
Ок, жду, спасибо.
21
Есть еще смысл ждать? Потому что самостоятельно вообще не представляю, как заменить эти 2 строчки.
16
алекс, закинь обновленную функицю, там же не высшая математика, легко принцип пересказать
21
И тишина
Блин, серьезно, я лучше тут заплачу, не жалко, если определим способ анонимно перекинуть деньги
Чтобы оставить комментарий, пожалуйста, войдите на сайт.