Добавлен PT153
Есть такой триггер.
Триггер
globals
constant trigger TriggerEnterFinish = CreateTrigger()
endglobals
function Trig_EnterFinish_Actions takes nothing returns nothing
local Minion m = GetUnitUserData(GetEnteringUnit())
local CustomPlayer p = m.foe
call p.leaked(m.data.livesconsume) // отнимаются жизни у игрока, что протёк.
call m.gainBounty(false) // протёкшему игроку даётся награда.
if p != m.owner and m.owner.inGame then // если протёкший игрок не является хозяином входящего юнита, то игроку-владельцу даются жизни.
call m.owner.leaked(m.data.livesgain)
endif
call CreateEffectPoint(EffectLifeConsume, GetUnitX(m.minion), GetUnitY(m.minion))
call m.remove() // удаление юнита.
if p.lives == 0 then
call FlushPlayer(p) // удаление игрока.
if bj_isSinglePlayer != (PlayingPlayers.top == 0) then
call FinishGame(10)
endif
endif
endfunction
function InitTrig_EnterFinish takes nothing returns nothing
call TriggerAddAction(TriggerEnterFinish, function Trig_EnterFinish_Actions)
endfunction
Он срабатывает при входе юнита в LeaveRegion. Чуть подробнее о функциях:
Функции игрока
method leaked takes integer l returns nothing
if l == 0 then
return
elseif l < -1 then
call message(SoundWarning, Color.Warnings.hex + "Warning|r: you lost " + Color.Numbers.hex + I2S(-l) + "|r lives.")
elseif l == -1 then
call message(SoundWarning, Color.Warnings.hex + "Warning|r: you lost " + Color.Numbers.hex + "1|r life.")
elseif l == 1 then
call message(SoundReceiveLife, Color.Hints.hex + "Note|r: you received " + Color.Numbers.hex + "1|r life.")
elseif l > 1 then
call message(SoundReceiveLife, Color.Hints.hex + "Note|r: you received " + Color.Numbers.hex + I2S(l) + "|r lives.")
endif
call addLives(l)
endmethod
method addLives takes integer l returns nothing
set lives = lives + l
if lives < 0 then
set lives = 0
elseif lives > MaxLives then
set lives = MaxLives
endif
call MultiboardSetItemValue(mblives, I2S(lives))
endmethod
method message takes sound snd, string s returns nothing
if isLocalPlayer then
if mescount == MessagesMaximum then
set mescount = 0
call ClearTextMessages()
endif
call StartSound(snd)
call DisplayTimedTextToPlayer(user, 0., 0., MessagesDuration, s)
set mescount = mescount + 1
endif
call TimerStart(t, MessagesDuration, false, function thistype.flushMessageCount)
endmethod
Функции миньона
method remove takes nothing returns nothing
call RemoveUnit(minion)
call delete()
endmethod
method delete takes nothing returns nothing
call owner.sentminions.deleteFromArray(this)
call FlushFieldMinion()
call DeleteLifeTimer()
call deallocate()
call DebugMsg("Minion " + I2S(this) + " is deleted.")
endmethod
method FlushFieldMinion takes nothing returns nothing
call foe.minions.deleteFromArray(this)
call owner.clearFoodUsed(data.foodused)
//call DebugMsg("Food cleared: " + R2SX(data.foodused))
// Timers
call buffs.destroy()
//call FlushChildHashtable(Hash, hid)
// Items
call RemoveItem(hpicon)
set hpicon = null
call RemoveItem(shldicon)
set shldicon = null
call RemoveItem(physarmicon)
set physarmicon = null
call RemoveItem(magcarmicon)
set magcarmicon = null
call RemoveItem(movespeedicon)
set movespeedicon = null
call RemoveItem(lifetimeicon)
set lifetimeicon = null
// Effects
call UnitRemoveAbility(minion, EffectShield)
call UnitRemoveAbility(minion, EffectSpeedup)
call UnitRemoveAbility(minion, EffectSlowdown)
call UnitRemoveAbility(minion, EffectStun)
call UnitRemoveAbility(minion, MagcArmorIncAbil)
call UnitRemoveAbility(minion, MagcArmorDecAbil)
call UnitRemoveAbility(minion, PhysArmorIncAbil)
call UnitRemoveAbility(minion, PhysArmorDecAbil)
//call DebugMsg("Minion " + I2S(this) + " is flushed.")
endmethod
FlushPlayer вызывает такой триггер:
FlushPlayer
globals
CustomPlayer FlushingPlayer
constant trigger TriggerFlushPlayer = CreateTrigger()
endglobals
//! textmacro Flush takes name, arrtyp, arr, cmd
function $name$ takes nothing returns nothing
local $arrtyp$ arr = FlushingPlayer.$arr$
local integer a = arr.top
loop
exitwhen a == -1
call arr[a].$cmd$()
set a = a - 1
endloop
call DebugMsg("$arr$ of player " + I2S(FlushingPlayer) + " is flushed.")
endfunction
//! endtextmacro
//! runtextmacro Flush("SellAllForces", "ForceArray", "forces", "sell")
//! runtextmacro Flush("RemoveAllSpawned", "SpawnArray", "spawned", "removeSpawned")
//! runtextmacro Flush("RemoveAllMinions", "MinionArray", "minions", "remove")
//! runtextmacro Flush("RemoveAllCorpses", "DeadArray", "dead", "removeCorpse")
//! runtextmacro Flush("RemoveAllTowers", "TowerArray", "towers", "remove")
function Trig_Flush_Actions takes nothing returns nothing
local CustomPlayer p = FlushingPlayer
call PlayingPlayers.deleteFromArray(p)
call ExecuteFunc("SellAllForces")
call ExecuteFunc("RemoveAllSpawned")
call ExecuteFunc("RemoveAllMinions")
call ExecuteFunc("RemoveAllCorpses")
call ExecuteFunc("RemoveAllTowers")
call p.flush()
call DebugMsg("Player " + I2S(p) + " is flushed.")
endfunction
// call p.flush()
method flush takes nothing returns nothing
call DeleteTimer()
call field.flush()
if isReady then
call DestroyGrid.execute()
call ShadowMultiboard()
call RemoveUnit(builder)
call RemoveUnit(barracks)
call RemoveUnit(altar)
call RemoveUnit(blacksmith)
call RemoveUnit(merccamp)
set builder = null
set barracks = null
set blacksmith = null
set altar = null
set merccamp = null
set blacksmith_swap_faction = null
set blacksmith_mhu_level = null
set blacksmith_mhu_cost = null
endif
set inGame = false
endmethod
// call field.flush()
method flush takes nothing returns nothing
local integer a = -1
local integer index = host.index
local thistype f
local CustomPlayer p
// Vision
loop
set a = a + 1
set p = Players[a]
if p.isReady then // Players that left before makeReady() method had called, do not have vision.
set f = p.field
call DestroyFogModifier(f.vision_player[index])
set f.vision_player[index] = null
call DestroyFogModifier(f.vision_forces[index])
set f.vision_forces[index] = null
call SetFogStateRect(p.user, FOG_OF_WAR_MASKED, playervision, true)
call SetFogStateRect(p.user, FOG_OF_WAR_MASKED, forcearea, true)
endif
exitwhen a == Players.top
endloop
// Rects
call RegionClearRect(SpawnRegion, spawnarea)
call RegionClearRect(LeaveRegion, leavearea)
call RemoveRect(playervision)
set playervision = null
call RemoveRect(forcearea)
set forcearea = null
call RemoveRect(spawnarea)
set spawnarea = null
call RemoveRect(leavearea)
set leavearea = null
call RemoveRect(towerarea)
set towerarea = null
// Cells
call DestroyCells.execute()
endmethod
Если нужны ещё функции - пишите.
А теперь к делу.
Мне всегда говорили, что код в игре выполняется последовательно, то есть, как я понимаю, сначала завершиться до конца триггер EnterFinish, и только потом он стартует заново, если новый миньон зашёл в область. То есть вот так: миньон зашёл в область, отнял жизни, их стало 0, игрок удалился, удаляя всех оставшихся миньонов.
Но это не так: если несколько миньонов заходят в область почти одновременно, триггер вызывается несколько раз, потому что код не успевает удалять миньонов, которые почти одновременно входят. Потому данный код багнут.
Мне всегда говорили, что код в игре выполняется последовательно, то есть, как я понимаю, сначала завершиться до конца триггер EnterFinish, и только потом он стартует заново, если новый миньон зашёл в область. То есть вот так: миньон зашёл в область, отнял жизни, их стало 0, игрок удалился, удаляя всех оставшихся миньонов.
Но это не так: если несколько миньонов заходят в область почти одновременно, триггер вызывается несколько раз, потому что код не успевает удалять миньонов, которые почти одновременно входят. Потому данный код багнут.
Вопрос: почему так происходит, если код выполняется последовательно? Когда выполнение "приостанавливается", чтобы запустить новый триггер и выполнить его?
Принятый ответ
Или сделай debounce для конкретного игрока
`
ОЖИДАНИЕ РЕКЛАМЫ...
Чтобы оставить комментарий, пожалуйста, войдите на сайт.
Отредактирован PT153
Отредактирован MpW
дебагом просто посмотри (в начале функции пишем название функции или триггера, в конец функции пишем end_name func и будет понятно кто за кем следует)
Отредактирован PT153
Отредактирован PT153
Путь у карты такой: Maps\Download\WispTD v3.-1.2 ndopt.w3x
Обязательно замени _ на пробелы в названии карты.
Полагаю, удаление тоже не моментально их удаляет из трекинга. Попробуй отдавать "стоп" перед удалением, например,
PT153:
Вообще, надо систему логов сделать, вместо вывода в сообщений в игру, ибо последние отключены в ndopt версиях.
Отредактирован ScorpioT1000