XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Академия: форум для вопросов> Jass
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

Ответ
 
inoto
я буду крутым!
offline
Опыт: 6,891
Активность:
Проверьте спелл на всевозможные дури/косяки
долго долбился делая этот спелл и пораллельно изучая жасс. добился того чего хотел, но сомневаюсь в утечках и правильности в некоторых местах, особенно в работе таймера и хэша. гляньте пожалуйста 8)
а тагже интересно почему при смерти кучки мобов от спелла страшно тормозила игра. мб как-то надо грамотно удалять сразу юнитов из игры? если да то как скоро их удалять?
function Spell_SaintHole_Filter takes nothing returns boolean
    return IsPlayerEnemy(GetOwningPlayer(udg_SaintHoleCaster), GetOwningPlayer(GetFilterUnit())) and GetWidgetLife(GetFilterUnit()) > 0.405 and not IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE)
endfunction

function Spell_SaintHole_Action takes nothing returns nothing
    local timer t=GetExpiredTimer()
    local unit u=LoadUnitHandle(udg_Hash,GetHandleId(t),0)
    local location p=LoadLocationHandle(udg_Hash,GetHandleId(t),1)
    local real a
    local real b
    local real w=LoadReal(udg_Hash,GetHandleId(t),2)+0.05
    local effect f=LoadEffectHandle(udg_Hash,GetHandleId(t),3)
    local group g=CreateGroup()
    local unit ga
    local boolexpr e = Condition(function Spell_SaintHole_Filter)
    local real dm=5+udg_VeterancyInt[(GetConvertedPlayerId(GetOwningPlayer(u))-1)]
    call GroupEnumUnitsInRange(g,GetLocationX(p),GetLocationY(p),500,e)
    call SaveReal(udg_Hash,GetHandleId(t),2,w)
    call BJDebugMsg(R2S(w))
    if w < 9.95 then
        loop
            set ga=FirstOfGroup(g)
        exitwhen ga==null
            call SetUnitPathing(ga,false)
            set a = AngleBetweenPoints(p,GetUnitLoc(ga))
            set b = DistanceBetweenPoints(p,GetUnitLoc(ga))
            set a = Spiral1(a,b)
            set b = Spiral2(b)
            if b <= 50.00 then
                set b = 50.00
            endif
            call SetUnitPositionLoc(ga,PolarProjectionBJ(p,b,a))
            call UnitDamageTarget(u,ga,dm,true,false,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_DIVINE,null)
            call GroupRemoveUnit(g,ga)
        endloop
    else
        call DestroyEffect(f)
        call BJDebugMsg("exit")
        call DestroyGroup(g)
        call FlushChildHashtable(udg_Hash, GetHandleId(t)) 
        //call RemoveSavedHandle(udg_Hash, GetHandleId(t), 0)
        //call RemoveSavedHandle(udg_Hash, GetHandleId(t), 1)
        //call RemoveSavedReal(udg_Hash, GetHandleId(t), 2)
        call DestroyTimer(t)
        call DestroyBoolExpr(e)
        set udg_Hash=null
        set g=null
        set ga=null
    endif
endfunction

function Trig_SaintHole_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A02L'
endfunction

function Trig_SaintHole_Actions takes nothing returns nothing
    local unit u=GetTriggerUnit()
    local location p=GetSpellTargetLoc()
    local real w=0.00
    local timer t=CreateTimer()
    local effect f
    if udg_Hash==null then
        set udg_Hash = InitHashtable()
        call BJDebugMsg("hash init")
    endif
    set udg_SaintHoleCaster = GetTriggerUnit()
    call AddSpecialEffectLoc("war3mapImported\\HolyBlessing.mdx",p)
    set f=GetLastCreatedEffectBJ()
    call SaveUnitHandle(udg_Hash,GetHandleId(t),0,u)
    call SaveLocationHandle(udg_Hash,GetHandleId(t),1,p)
    call SaveReal(udg_Hash,GetHandleId(t),2,w)
    call SaveEffectHandle(udg_Hash,GetHandleId(t),3,f)
    call TimerStart(t,0.05,true, function Spell_SaintHole_Action)
    call BJDebugMsg("done.")
    set t=null
    set u=null
    set p=null
    
endfunction

//===========================================================================
function InitTrig_SaintHole takes nothing returns nothing
    set gg_trg_SaintHole = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_SaintHole, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(gg_trg_SaintHole, Condition( function Trig_SaintHole_Conditions))
    call TriggerAddAction(gg_trg_SaintHole, function Trig_SaintHole_Actions)
    call Preload("war3mapImported\\HolyBlessing.mdx")
endfunction
Старый 16.09.2010, 11:28
JassMan
свободен
offline
Опыт: 4,193
Активность:
function Trig_SaintHole_Conditions takes nothing returns boolean
return GetSpellAbilityId()=='A02L'
endfunction

function Spell_SaintHole_Filter takes nothing returns boolean
local timer t=GetExpiredTimer()
local unit u=LoadUnitHandle(udg_Hash,GetHandleId(t),0)
if(IsPlayerEnemy(GetOwningPlayer(u),GetOwningPlayer(GetFilterUnit()))and(GetWidgetLife(GetFilterUnit​())>0.404)and(not(IsUnitType(GetFilterUnit(),UNIT_TYPE_STRUCTURE))))then //При 0.405 юнит еще жив, поэтому строго после 0.404
    set t=null
    set u=null
    return true
else
    set t=null
    set u=null
    return false
endif
endfunction

function Spell_SaintHole_Action takes nothing returns nothing
local timer t=GetExpiredTimer()
local unit u=LoadUnitHandle(udg_Hash,GetHandleId(t),0)
local real X=LoadReal(udg_Hash,GetHandleId(t),1)
local real Y=LoadReal(udg_Hash,GetHandleId(t),2)
local real w=LoadReal(udg_Hash,GetHandleId(t),3)+0.05
local group g=LoadGroupHandle(udg_Hash,GetHandleId(t),5)
local unit c
local real a
local real L
local boolexpr b
if(w>10.)then //Всё, что до 10.00 (включительно) будет обрабатываться, а после выключать таймер и все прочее.
    set b=Condition(function Spell_SaintHole_Filter)
    call GroupEnumUnitsInRange(g,X,Y,500.,b)
    loop
        set c=FirstOfGroup(g)
        exitwhen c==null
        call SetUnitPathing(c,false)
        set a=Atan2(GetUnitY(u)-Y,GetUnitX(u)-X) //Получаем угол в радианах.
        set L=SquareRoot((GetUnitX(u)-X)*(GetUnitX(u)-X)+(GetUnitY(u)-Y)*(GetUnitY(u)-Y))
        set a=Spiral1(a*57.2958279,L) //Не знаю, что это за функции, но пришлось переводить их в градусы этой константой (180/PI)
        set L=Spiral2(L)
        if(L<50.)then
            set L=50.
        endif
        call SetUnitPosition(c,X+L*Cos(a),Y+L*Sin(a))
        call UnitDamageTarget(u,c,5+udg_VeterancyInt[GetPlayerId(GetOwningPlayer(u))],true,false,ATTACK_TYPE_CHAO​S,DAMAGE_TYPE_DIVINE,null)
        call GroupClear(g) //Этого достаточно, чтобы убрать всех юнитов из группы (это для нового пика юнитов. Она чиста и готова к использованию.)
    endloop
    call SaveReal(udg_Hash,GetHandleId(t),3,w)
    call DestroyBoolExpr(b)
    set b=null 
    set c=null
else
    call DestroyEffect(LoadEffectHandle(udg_Hash,GetHandleId(t),4))
    call DestroyGroup(g) //Когда всё кончилось, только тогда и удаляем объект из памяти.
    call PauseTimer(t)
    call FlushChildHashtable(udg_Hash,GetHandleId(t)) //Этого достаточно, чтобы очистить все ячейки в категории GetHandleId(t)
    call DestroyTimer(t)
endif
set t=null //Эти зачистки должны происходить независимо от if-а
set u=null
set g=null
endfunction

function Trig_SaintHole_Actions takes nothing returns nothing
local unit u=GetSpellAbilityUnit()
local timer t=CreateTimer()
local effect e=AddSpecialEffect("war3mapImported\\HolyBlessing.mdx",GetSpellTargetX(),GetSpellTargetY()​) //можно сразу переменной присваивать функцию которая возвращает нужный аргумент (в нашем случае эффект)
call SaveUnitHandle(udg_Hash,GetHandleId(t),0,u)
call SaveReal(udg_Hash,GetHandleId(t),1,GetSpellTargetX())
call SaveReal(udg_Hash,GetHandleId(t),2,GetSpellTargetY()) //Не используем память на объект (на точку), Варик быстрее работает с координатами (ибо тип Real).
call SaveReal(udg_Hash,GetHandleId(t),3,0.) //Если локалка используется 1 раз, то лучше не создавать её вообще, а сразу писать нужное значение в нужное место (ибо на объявление переменной тоже тратятся, хоть и маленькие, ресурсы оперативки).
call SaveEffectHandle(udg_Hash,GetHandleId(t),4,e)
call SavegroupHandle(udg_Hash,GetHandleId(t),5,CreateGroup()) //Создаём группу только 1 раз, и только с ней будем работать (многократное использование).
call TimerStart(t,0.05,true,function Spell_SaintHole_Action)
set t=null
set u=null
set e=null //Обнулять нужно всё кроме типов: Boolean, Integer, Real, Player, String.
endfunction

function InitTrig_SaintHole takes nothing returns nothing
set gg_trg_SaintHole=CreateTrigger()
set udg_Hash=InitHashtable() //Так как эта функция срабатывает при инициализации карты, мы тут инициализируем хеш-таблицу (это будет сделано однократно за всю игру)
call TriggerRegisterAnyUnitEventBJ(gg_trg_SaintHole,EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(gg_trg_SaintHole,Condition(function Trig_SaintHole_Conditions))
call TriggerAddAction(gg_trg_SaintHole,function Trig_SaintHole_Actions)
call Preload("war3mapImported\\HolyBlessing.mdx")
endfunction
Если выдаст ошибку, то наверно опечатался или скобку где-то не закрыл, а в остальном всё должно быть верно.

Отредактировано JassMan, 16.09.2010 в 22:28.
Старый 16.09.2010, 22:16
ScorpioT1000
Работаем
offline
Опыт: отключен
При 0.405 юнит еще жив, поэтому строго после 0.404
а 0.404000000000000000000000000000000000001 не может быть? лол) ещё как может !
Старый 16.09.2010, 23:27
JassMan
свободен
offline
Опыт: 4,193
Активность:
0.405 тогда знак >= нужен
Хотя столько нулей это бред. . . Мне кажется >0.404 хватает
обязательно придерутся к какой-нибудь фигне. . .
Старый 16.09.2010, 23:45
ScorpioT1000
Работаем
offline
Опыт: отключен
this is float, baby !
Старый 17.09.2010, 00:41
Toadcop

offline
Опыт: 54,313
Активность:
IsUnitType(u, UNIT_TYPE_DEAD), baby O_O
Старый 17.09.2010, 00:44
silumin

offline
Опыт: 11,153
Активность:
Цитата:
Сообщение от Toadcop
IsUnitType(u, UNIT_TYPE_DEAD)
ммм... Век живи - век учись. Это будет действительно практичнее нежели угадывать 0.405 или 0.404 или вообще 0.0...
Старый 17.09.2010, 00:52
Toadcop

offline
Опыт: 54,313
Активность:
там ньанс с "несуществующими" юнитами... т.е. надо еще (для полной уверености) делать проверку вида

GetUnitTypeId(u) > 0 (ака юнит есть)
Старый 17.09.2010, 01:00
ScorpioT1000
Работаем
offline
Опыт: отключен
таким образом имеем
bool IsUnitAliveX(unit x) {
    return ((GetUnitTypeId(x)>0) && (! IsUnitType(x, UNIT_TYPE_DEAD)));
}
Старый 17.09.2010, 01:21
silumin

offline
Опыт: 11,153
Активность:
Toadcop, думаю, что в фильтрах всяких GroupEnum... проверку на несуществующего юнита можно опустить. Так?
Старый 17.09.2010, 03:54
inoto
я буду крутым!
offline
Опыт: 6,891
Активность:
JassMan, спасибо. и отдельное что дал код с разъяснениями) оч помогло)
однако же резко перебрался на галакси, а вар забросил к чёрту..
Старый 20.09.2010, 16:18
Ответ

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 12:27.