поставил проверку по GetEventDamageSource() все работает как надо, только утекает где-то. Надо теперь утечку искать. Склояюсь к том, что утекает boolexpr
Hexing, не понимаю ход твоих мыслей, относительно кода. Дублирую код еще раз, вылетает сволоч, пишет переполнение стека. Если убрать строку call IssueTargetOrder(d, "frostnova", c), то вылета не будет. Но вылетает не из-за строки, если вместо нее поставить call UnitDamageTarget(d, c, 1.0, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNKNOWN, WEAPON_TYPE_WHOKNOWS) эффект тот же.
Code
function DestroyPasSpell takes nothing returns nothing local trigger t = GetTriggeringTrigger() local unit c = LoadUnitHandle(udg_HashDMG,GetHandleId(t),1) local trigger d = LoadTriggerHandle(udg_HashDMG,GetHandleId(c),1) //унитчожаем триггер на получение урона call TriggerRemoveAction(d,LoadTriggerActionHandle(udg_HashDMG,GetHandleId(c),2)) call TriggerRemoveCondition(d,LoadTriggerConditionHandle(udg_HashDMG,GetHandleId(c),3)) call DestroyBoolExpr(LoadBooleanExprHandle(udg_HashDMG,GetHandleId(c),4)) call DestroyTrigger(d) //уничтожаем этот триггер call TriggerRemoveAction(t,LoadTriggerActionHandle(udg_HashDMG,GetHandleId(t),0)) call DestroyTrigger(t) call FlushChildHashtable(udg_HashDMG, GetHandleId(t)) call FlushChildHashtable(udg_HashDMG, GetHandleId(c)) set t = null set c = null set d = null endfunction
//проверка на имение абилы, и расчет шанса function PasSpell_Conditions takes nothing returns boolean return GetUnitAbilityLevel(GetEventDamageSource(), 'AHwe') > 0 and not(IsUnitType(GetTriggerUnit(), UNIT_TYPE_STRUCTURE)) and 100>GetRandomInt(1,100) and GetEventDamageSource() == LoadUnitHandle(udg_HashDMG,GetHandleId(GetTriggerUnit()),5) endfunction
//действия при выпадении шанса function PasSpell_Actions takes nothing returns nothing local unit u = GetEventDamageSource() local unit c = GetTriggerUnit() local unit d = CreateUnit(GetOwningPlayer(u),'u000',GetUnitX(c),GetUnitY(c),0.) call UnitAddAbility(d,'A000') call IssueTargetOrder(d, "frostnova", c) call UnitApplyTimedLife(d, 'BTLF', 1.00) set udg_i = udg_i +1 call BJDebugMsg(I2S(udg_i)) set u = null set c = null set d = null endfunction
function UnitAttack takes nothing returns nothing local unit u = GetTriggerUnit() local unit c = GetEventTargetUnit() local trigger t = null local triggeraction tra = null local triggercondition trc = null local boolexpr b = null if(not(LoadBoolean(udg_HashDMG,GetHandleId(c),0)))then //создаем триггер на получение урона set t = CreateTrigger() set tra = TriggerAddAction(t, function PasSpell_Actions) set b = Condition(function PasSpell_Conditions) set trc = TriggerAddCondition(t, b) call TriggerRegisterUnitEvent(t, c, EVENT_UNIT_DAMAGED) call SaveBoolean(udg_HashDMG,GetHandleId(c),0,true) call SaveTriggerHandle(udg_HashDMG,GetHandleId(c),1,t) call SaveTriggerActionHandle(udg_HashDMG,GetHandleId(c),2,tra) call SaveTriggerConditionHandle(udg_HashDMG,GetHandleId(c),3,trc) call SaveBooleanExprHandle(udg_HashDMG,GetHandleId(c),4,b) call SaveUnitHandle(udg_HashDMG,GetHandleId(c),5,u) //триггер на уничтожения трггера получения урона при смерти юнита set t = CreateTrigger() set tra = TriggerAddAction(t, function DestroyPasSpell) call TriggerRegisterUnitEvent(t, c, EVENT_UNIT_DEATH) call SaveTriggerActionHandle(udg_HashDMG,GetHandleId(t),0,tra) call SaveUnitHandle(udg_HashDMG,GetHandleId(t),1,c) set t = null set tra = null set trc = null set b = null endif set c = null set u = null endfunction
//проверка на прокачиваемую абилу function Trig_LearningSkill_Conditions takes nothing returns boolean return GetLearnedSkill() == 'AHwe' and GetUnitAbilityLevel(GetLearningUnit(),'AHwe')==1 endfunction
//создаем новый триггер, конкретно на нашего юнита function Trig_LearningSkill_Actions takes nothing returns nothing local trigger t = CreateTrigger() call TriggerRegisterUnitEvent( t, GetLearningUnit(), EVENT_UNIT_TARGET_IN_RANGE ) call TriggerAddAction( t, function UnitAttack ) set t = null endfunction
//=========================================================================== function InitTrig_LearningSkill takes nothing returns nothing set gg_trg_LearningSkill = CreateTrigger( ) call TriggerRegisterAnyUnitEventBJ( gg_trg_LearningSkill, EVENT_PLAYER_HERO_SKILL ) call TriggerAddCondition( gg_trg_LearningSkill, Condition( function Trig_LearningSkill_Conditions ) ) call TriggerAddAction( gg_trg_LearningSkill, function Trig_LearningSkill_Actions ) endfunction
kapa6acvlk, перечитал я весь ваш код, короче скажу одно - локальные триггеры - это зло, используйте один триггер и проверку в группе ли юнит, вы проигрываете и по времени выполнения, и по памяти, кстати гдето ктото говорил что в триггерах событие не уничтожается, что приводит к утечке даже при полном уничтожении триггера, вообщем по делу: ваша чудная функция DestroyPasSpell ни в одном месте не вызывается, а значит триггер зацикливается: наносится урон - срабатывает триггер - наносится урон - срабатывает триггер, тут даже дело не в переменной, тут вы с кодом намудрили, вы триггер нихрена не уничтожаете, тобишь функцию в хэш сохранили, а вызывать кто будет? исправлять код не буду, т.к. в нём трудно ориентироваться, но думаю не помешало бы переписать его, когда закончу все мои другие долги, могу помочь
Ужасный он, только тем, что ключи для сохранения в хеш используются числа, и в них можно путаться, а так я не вижу в нем ничего заумного. Может он в каком-то месте туп, но я не программист, мне сложно об этом рассуждать и склад ума у меня не программерский (математически-логический).
Ужасный он, только тем, что ключи для сохранения в хеш используются числа, и в них можно путаться, а так я не вижу в нем ничего заумного. Может он в каком-то месте туп, но я не программист, мне сложно об этом рассуждать и склад ума у меня не программерский (математически-логический).
function Trig_ChainIllusory_RemoveLightning takes nothing returns nothing local timer t = GetExpiredTimer() local integer id = GetHandleId(t) call DestroyLightning(LoadLightningHandle(udg_Hashtable, id, 0)) call DestroyLightning(LoadLightningHandle(udg_Hashtable, id, 1)) call DestroyLightning(LoadLightningHandle(udg_Hashtable, id, 2)) call DestroyLightning(LoadLightningHandle(udg_Hashtable, id, 3)) call DestroyTimer(t) set t = null endfunction
function Trig_ChainIllusory_RemoveIllusions takes nothing returns nothing local timer t = GetExpiredTimer() local integer id = GetHandleId(t) local unit u local unit u2 local integer i = 0 loop set u = LoadUnitHandle(udg_Hashtable, id, i*2) set u2 = LoadUnitHandle(udg_Hashtable, id, 1 + i*2) if(u2 != null) then if(u != null and GetWidgetLife(u) > 0.405 and GetWidgetLife(u2) > 0.405) then call SetWidgetLife(u, GetWidgetLife(u) + GetWidgetLife(u2)) endif call KillUnit(u2) endif set i = i + 1 exitwhen(i == 4) endloop call DestroyTimer(t) set u = null set u2 = null set t = null endfunction
function Trig_ChainIllusory_Actions takes nothing returns nothing local lightning l local unit caster = GetTriggerUnit() local unit target = GetSpellTargetUnit() local integer level = GetUnitAbilityLevel(caster, GetSpellAbilityId()) local real length = level * 5.0 + 10.0 local real life = level * 10.0 + 20.0 local group g = CreateGroup() local integer i = 0 local timer t = CreateTimer() local timer t2 = CreateTimer() local integer id = GetHandleId(t) local integer id2 = GetHandleId(t2) local group targets = CreateGroup() local unit u local unit u2 local boolean found set l = AddLightning("FORK", false, GetUnitX(caster), GetUnitY(caster), GetUnitX(target), GetUnitY(target)) set u2 = CreateUnit(GetOwningPlayer(caster), GetUnitTypeId(target), GetUnitX(target), GetUnitY(target), 0.0) call SetWidgetLife(u2, GetWidgetLife(target) * life / 100) call SetWidgetLife(target, GetWidgetLife(target) - GetWidgetLife(target) * life / 100) call SetUnitVertexColor(u2, 155, 15, 155, 155) call SaveUnitHandle(udg_Hashtable, id2, 0, target) call SaveUnitHandle(udg_Hashtable, id2, 1, u2) call SaveLightningHandle(udg_Hashtable, id, 0, l) call TimerStart(t, 0.4, false, function Trig_ChainIllusory_RemoveLightning) call SetSoundPosition(gg_snd_ShadowStrikeBirth1, GetUnitX(target), GetUnitY(target), 150.0) call StartSound(gg_snd_ShadowStrikeBirth1) call GroupAddUnit(targets, target) loop set found = false call GroupEnumUnitsInRange(g, GetUnitX(target), GetUnitY(target), 300.0, null) loop set u = FirstOfGroup(g) exitwhen(u == null or found == true) if(IsUnitEnemy(u, GetOwningPlayer(caster)) and GetWidgetLife(u) > 0.405 and not IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE)) then if not IsUnitInGroup(u, targets) then set found = true call GroupAddUnit(targets, u)
set l = AddLightning("FORK", false, GetUnitX(target), GetUnitY(target), GetUnitX(u), GetUnitY(u)) set u2 = CreateUnit(GetOwningPlayer(caster), GetUnitTypeId(u), GetUnitX(u), GetUnitY(u), 0.0) call SetWidgetLife(u2, GetWidgetLife(u) * life / 100) call SetWidgetLife(u, GetWidgetLife(u) - GetWidgetLife(u) * life / 100) call SetUnitVertexColor(u2, 155, 15, 155, 155) call SaveUnitHandle(udg_Hashtable, id2, 2+i*2, u) call SaveUnitHandle(udg_Hashtable, id2, 3+i*2, u2) set target = u call SaveLightningHandle(udg_Hashtable, id, i+1, l) call TimerStart(t, 0.4, false, function Trig_ChainIllusory_RemoveLightning) endif endif call GroupRemoveUnit(g, u) endloop set i = i + 1 exitwhen(i == 3 or found == false) endloop call TimerStart(t2, length, false, function Trig_ChainIllusory_RemoveIllusions) call DestroyGroup(g) set l = null set caster = null set target = null set u = null set u2 = null set t = null set t2 = null set g = null endfunction
//=========================================================================== function InitTrig_ChainIllusory takes nothing returns nothing set udg_Hashtable = InitHashtable() set gg_trg_ChainIllusory = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(gg_trg_ChainIllusory, EVENT_PLAYER_UNIT_SPELL_EFFECT) //Ðåãèñòðèðóåì ñîáûòèå call TriggerAddCondition(gg_trg_ChainIllusory, Condition(function Trig_ChailIllusiry_Conditions)) // call TriggerAddAction(gg_trg_ChainIllusory, function Trig_ChainIllusory_Actions) //Õîòü ñîáûòèÿ ó òðèããåðà è íåò, ó íåãî óæå äîáàâëÿåòñÿ äåéñòâèå - endfunction
По поводу статьи Кстати по поводу твоего примера, группа targets объевлена но не уничтожена, сравнение found == true не нужно, ибо found булин. Исправь в статье.
По поводу статьи Кстати по поводу твоего примера, группа targets объевлена но не уничтожена, сравнение found == true не нужно, ибо found булин. Исправь в статье.
я до кучи геморился со статьёй, исправлять её могу только модеры, мне приходилось два раза давать исправленный текст модератору ведь пишешь всё это в блакнотике, сам путаешь уже что удалил а что нет, а на счёт found - надо, это плохая привычка if(bool) а с группой - чёрт с ней
Почему? Всегда все норм работает, зачем сравнивать true == true?
Smartaros, Уж не знаю почему, но убрав проверку, вылета нет. По всей видимости, если какие-то огранечения на использование boolexpr либо TriggerCondition, вот карта наработка с этот системой: http://rghost.ru/39806031 Я ждал до 100000 срабатываний триггера, что в простой игре невозможно. Для теста введи 1. Создадутся юниты, и герои прокачают абилу. Код отдельно выкладывать не буду, думаю в карте посмотришь.
обычно что бы наносить чистый урон который ничем не будет увеличен, я, обычно, наношу его от лица особого даммика а во всех триггерах с событием получения урона стоит условие "тип юнита наносящего урон не равно Dammy p_dmg"