Оч редко, но вот таки снова вылетел
Заметки себе - это с крокодилом и та и другая катка, предположительно все-таки из-за повышения уровня абилы у мёртвого, наверное, там проверка недостаточно правильная

.Q..I.VW.bi...|$ == изменение абилки у мертвого юнита
в логе четко видно ид X82A
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
21
Не, ну бред какой-то
ну вот у него проверка перед заданием лвла дамми девотион ауры в спеллбуке
я грешу, что фатал может вылететь от повышения лвла абилы у мёртвой боевой единицы
if (u5 == null) then

call PauseTimer (t)
call DestroyTimer (t)
call FlushChildHashtable (udg_Hash, GetHandleId(t))

else

//ЕСЛИ БРОНЯ БОЛЬШЕ ДОПУСТИМОГО ЛВЛА - СНИЗИТЬ НОМЕР
if number > GetUnitAbilityLevelSwapped('A28T',u5) * 22 then
set number = GetUnitAbilityLevelSwapped('A28T',u5) * 22
endif
if number > 99 then
set number = 99
endif
//ЕСЛИ БРОНЯ БОЛЬШЕ ДОПУСТИМОГО ЛВЛА - СНИЗИТЬ НОМЕР - ЗАКРЫТО.

//ДОБАВКА И ДИЗЕЙБЛ СПЕЛЛБУКОВ, ЗАДАНИЕ НУЖНОГО УРОВНЯ СПОСОБНОСТИ, ТОЛЬКО ЕСЛИ ЖИВ!!!
if IsUnitAliveBJ(u5) == true and GetUnitState(u5,UNIT_STATE_LIFE)>1 and IsUnitDeadBJ(u5) == false then
call UnitAddAbility(u5,'A28W')
call SetPlayerAbilityAvailableBJ( false, 'A28W', GetOwningPlayer(u5) )
call UnitMakeAbilityPermanent(u5,true,'A28W')
call UnitMakeAbilityPermanent(u5,true,'A28X')
call SetUnitAbilityLevelSwapped('A28X',u5,R2I(number))
endif
//ДОБАВКА И ДИЗЕЙБЛ СПЕЛЛБУКОВ - ЗАКРЫТО.

endif
По-моему, проверка даже излишне осторожная немножко, т. к. если он будет живой с хп 1, то не получит ауры брони и повышения ее уровня (но вероятность этого < 0.1% по очевидной причине, а вероятность того, что он через секунду либо не умрёт, либо не отрегает хп, < 0.001%).
Тогда какого панциря фатал? Это не ульта, ни в той ни в другой катке крокодил до 8 уровня не докачивался. Остаются кушка - но это тупо АоЕ дамаг с накидыванием и сразу убиранием абилы ауры дамага... и... ешка, ну там увеличивается броня на сотые доли через мемхак, но без умножения, просто через мемхак плюсуются сотые доли брони, неужели что-то в ешке?
^^^^
Короче, выше это все лирика, просто интересно по логу причины фатала узнать.
32
Чет ваще ниче непонятно, аж 3 проверки, когда достаточно 1
GetUnitState( unit, UNIT_STATE_LIFE ) > 0.405
Да и проверять сдох ли юнит нужно в начале, а не сначала считать левелы а потом проверять жив ли он.
Есть функция GetUnitAbilityLevel - нафиг юзать бж огрызки?
так же есть IMinBJ если вам так нравится, set number = IMinBJ( 99, number )
Ты уверен что фаталит именно этот код?
21
quq_CCCP, в обеих катках с фаталом был крокодил, так что 90%, что из-за крокодила
а у крокодила это самая подозрительная абила
но это что-то очень-очень редкое, в каком бы коде ни было, потому что когда был словлен первый фатал с крокодилом, мной было поставлено 6 ботов-крокодилов и они 5 минут рубились без фатала, и вообще минимум 80% каток с крокодилами проходило без фатала, а точнее, все, кроме двух, вторая только что была
проверок до фига поставлено именно от греха подальше на всякий случай
замечания учту
Вот вся функция целиком на вторую абилу, в которой сильнее всего сомневаюсь:
смотреть сюда
function SkinForFriendsRefresh takes nothing returns nothing
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: t, u5
local timer t = GetExpiredTimer()
local unit u5=LoadUnitHandle(udg_Hash,GetHandleId(t),2)
local real number = GetUnitArmor(u5)
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
if (u5 == null) then
call PauseTimer (t)
call DestroyTimer (t)
call FlushChildHashtable (udg_Hash, GetHandleId(t))
else
ЕСЛИ БРОНЯ БОЛЬШЕ ДОПУСТИМОГО ЛВЛА - СНИЗИТЬ НОМЕР
if number > GetUnitAbilityLevelSwapped('A28T',u5) * 22 then
set number = GetUnitAbilityLevelSwapped('A28T',u5) * 22
endif
if number > 99 then
set number = 99
endif
ЕСЛИ БРОНЯ БОЛЬШЕ ДОПУСТИМОГО ЛВЛА - СНИЗИТЬ НОМЕР - ЗАКРЫТО.
ДОБАВКА И ДИЗЕЙБЛ СПЕЛЛБУКОВ, ЗАДАНИЕ НУЖНОГО УРОВНЯ СПОСОБНОСТИ, ТОЛЬКО ЕСЛИ ЖИВ!!!
if IsUnitAliveBJ(u5) == true and GetUnitState(u5,UNIT_STATE_LIFE)>1 and IsUnitDeadBJ(u5) == false then
call UnitAddAbility(u5,'A28W')
call SetPlayerAbilityAvailableBJ( false, 'A28W', GetOwningPlayer(u5) )
call UnitMakeAbilityPermanent(u5,true,'A28W')
call UnitMakeAbilityPermanent(u5,true,'A28X')
call SetUnitAbilityLevelSwapped('A28X',u5,R2I(number))
endif
ДОБАВКА И ДИЗЕЙБЛ СПЕЛЛБУКОВ - ЗАКРЫТО.
endif
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: t, u5
set t = null
set u5 = null
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
endfunction
Может, ещё гетюнитармор не надо в начале считать при объявлении переменных? Она не мемхачная, а старая с хайва и там селфдамаг... может, там если юнита вдруг оказалось, что нет, получается ноль и из-за этого трындец где-то дальше... попробую мб заменить на мемхачную
Я просто пока размышляю
Я по логу хочу причину фатала услышать
У меня два основных предположения - если от вылета из-за повышения уровня абилы у мёртвой боевой единицы, то это точно эта абила (вторая). Если от записи чего-то в память, то это третья.
Третья вот, если кому не лениво ещё и её смотреть:
смотреть сюда
function BlessingOfTheNileAttack takes nothing returns nothing
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: t, u5, u6
local timer t = CreateTimer()
local unit u5 = GetAttacker()
local unit u6 = GetAttackedUnitBJ()
local integer level = R2I(GetUnitAbilityLevelSwapped('A28U',u5))
local integer i = 0
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
if (u5 !=null) then
if ( GetUnitAbilityLevelSwapped('A28U', u5) > 0 ) and ( GetUnitAbilityLevelSwapped('A290', u5) > 0 ) then
Удаление маркера с атаковавшего
call UnitRemoveAbility(u5,'A290')
Удаление маркера с атаковавшего - закрыто.
ДОБАВКА БРОНИ
call SetUnitBaseArmor(u5, GetUnitBaseArmor(u5) + 0.01 * I2R(level))
ДОБАВКА БРОНИ - ЗАКРЫТО.
call SaveUnitHandle(udg_Hash,GetHandleId(t),2,u5)
call SaveUnitHandle(udg_Hash,GetHandleId(t),1,u6)
call SaveInteger(udg_Hash,GetHandleId(t),3,i)
call SaveInteger(udg_Hash,GetHandleId(t),4,level)
call TimerStart(t,0.25,true,function BlessingOfTheNileAttack2)
else
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(udg_Hash, GetHandleId(t))
endif
else
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(udg_Hash, GetHandleId(t))
endif
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: t, u5, u6
set t = null
set u5 = null
set u6 = null
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
endfunction
function BlessingOfTheNileRefresh takes nothing returns nothing
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: t, u5, u6, p, heroadded, heroaction, enemies
local timer t = GetExpiredTimer()
local unit u5=LoadUnitHandle(udg_Hash,GetHandleId(t),2)
local unit u6
local location p = GetUnitLoc(u5)
local trigger heroadded=LoadTriggerHandle(udg_Hash,GetHandleId(t),20)
local triggeraction heroaction=LoadTriggerActionHandle(udg_Hash,GetHandleId(t),21)
local group enemies=CreateGroup()
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
local integer i = LoadInteger(udg_Hash,GetHandleId(t),3)
set i = i+1
call SaveInteger (udg_Hash,GetHandleId(t),3,i)
Если героя нет, то разрушить таймер, чтобы не крутился и не жрал ресурсы.
if (u5 == null) then
call PauseTimer(t)
call DestroyTimer(t)
call FlushChildHashtable(udg_Hash,GetHandleId(t))
call TriggerRemoveAction(heroadded,heroaction)
call DestroyTrigger(heroadded)
else
call TriggerRemoveAction(heroadded,heroaction)
call DestroyTrigger(heroadded)
set heroadded=CreateTrigger()
set heroaction = TriggerAddAction(heroadded,function BlessingOfTheNileAttack)
set enemies = GetUnitsInRangeOfLocAll(800.00, p)

loop
set u6=FirstOfGroup(enemies)
exitwhen u6==null
call GroupRemoveUnit(enemies,u6)
if ( GetUnitAbilityLevelSwapped('Avul', u6) != 1 ) and ( IsUnitAliveBJ(u6) == true ) and ( IsUnitEnemy(u6,GetOwningPlayer(u5))==true ) then
call TriggerRegisterUnitEvent(heroadded, u6, EVENT_UNIT_ATTACKED)
else
endif
endloop
call DestroyGroup (enemies)
call SaveTriggerHandle(udg_Hash,GetHandleId(t),20,heroadded)
call SaveTriggerActionHandle(udg_Hash,GetHandleId(t),21,heroaction)
endif

call RemoveLocation (p)
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ: t, u5, u6, p, heroadded, heroaction, enemies
set t = null
set u5 = null
set u6 = null
set p = null
set heroadded = null
set heroaction = null
set enemies = null
ВНИМАНИЕ!!! ОБНУЛЯЕМЫЕ ПЕРЕМЕННЫЕ ЗДЕСЬ СПИСКОМ - НОВЫЙ ШАБЛОН СОВЕРШЕНСТВА, ВСЕ ТЕСТКАРТЫ БЕЗ ОНОГО БУДУТ УДАЛЕНЫ - ЗАКРЫТО
endfunction
Кушка простейшая, там фатала в принципе не должно быть, сейчас была перепроверена - ничего подозрительного не вижу...
16
.Q..I.VW.bi...|$ == изменение абилки у мертвого юнита
в логе четко видно ид X82A
Принятый ответ
21
Понятно...
Ну вот он код в первом сообщении, вот A28X абила... Какого панциря при проверке аж тремя функциями
if IsUnitAliveBJ(u5) == true and GetUnitState(u5,UNIT_STATE_LIFE)>1 and IsUnitDeadBJ(u5) == false
игра умудряется его в редком случае видеть НЕ мёртвым?!
Она тут его живого-то с 1 хп за мёртвого должна считать, а получается, что и мёртвого всё-таки иногда (хотя и КРАЙНЕ редко) живым видит.
30
проверка даже излишне осторожная немножко
Прямо поэзия в этих строках есть какая-то. А вообще, "излишне" и "немножко" это взаимоисключающие понятия.
IsUnitAliveBJ(u5) == true and GetUnitState(u5,UNIT_STATE_LIFE)>1 and IsUnitDeadBJ(u5) == false
Три абсолютно идентичные по сути проверки (слегка разные по быстродействию), достаточно одной.

Может, ещё гетюнитармор не надо в начале считать при объявлении переменных? Она не мемхачная, а старая с хайва и там селфдамаг... может, там если юнита вдруг оказалось, что нет, получается ноль и из-за этого трындец где-то дальше... попробую мб заменить на мемхачную
21
Clamp, вот с одной точно жопа будет, потому что уже есть опыт, IsUnitAlive и IsUnitDead точно косые какие-то.
Потому что у меня есть другой герой, Гидралиск, который вселяется в крипа, хайдится и типа входит внутрь него до смерти крипа (можно эту смерть вручную сделать через добавляемую крипу абилку, типа разорвать его изнутри и вылезти).
Там стояла одна проверка.
Так вот в большинстве случаев все было ок, но бывало, что, когда крип умирал, Гидралиск не анхайдился до его разложения (а это полная жопа).
Вот ща там проверка типа такой тройной по-моему и вроде тьфу-тьфу все норм.
Проверка именно поэтому такая хардкорная стоит и здесь, и вот даже её оказалось недостаточно.
Короче, не знаю, в крайнем случае поменяю единицу на цифру чуть побольше (правда, чем больше будет цифра - тем больше уже будет фактическая погрешность в действии способности, но вплоть до 100 хп это будет не сильно страшно), тут трудности в том, что фатал действительно очень редко, так что сложно будет понять, исправлен он окончательно или нет.
/
БД на броню в 2017 и во времена мемхака... как раз с GetUnitArmor от него отказ и произошёл, спасибо, если все через бд делать, так и варкрафт не очень нужен
30

Какого панциря
Сначала все возможные проверки, потом все зависящие от них действия, не наоборот. Кстати:
call UnitAddAbility(u5,'A28W')
call SetPlayerAbilityAvailableBJ( false, 'A28W', GetOwningPlayer(u5) )
call UnitMakeAbilityPermanent(u5,true,'A28W')
call UnitMakeAbilityPermanent(u5,true,'A28X')
call SetUnitAbilityLevelSwapped('A28X',u5,R2I(number))
Весь этот мусор можно вынести в отдельную функцию, намного проще будет дебажить.
И научись, пожалуйста, пользоваться таким построением при постинге:
((код
// тут код
))
21
Clamp, "Сначала все возможные проверки, потом все зависящие от них действия, не наоборот" - а у меня как?
Про функцию - справедливо, ну много чего можно посжимать в функции, да, но это дофига перелопачивать, хотя себя оправдает, ну это ок, но немного другой вопрос.
30
БД на броню в 2017 и во времена мемхака...
"Портируемость" явно не входит в список знакомых тебе понятий. Советую проникнуться ею достаточно глубоко, чтобы не использовать тот или иной недокументированный функционал (это вообще, не только про вц), так как он имеет свойство переставать существовать после багфиксов.

Про "дополнительные" проверки:
//===========================================================================
function IsUnitDeadBJ takes unit whichUnit returns boolean
    return GetUnitState(whichUnit, UNIT_STATE_LIFE) <= 0
endfunction

//===========================================================================
function IsUnitAliveBJ takes unit whichUnit returns boolean
    return not IsUnitDeadBJ(whichUnit)
endfunction

Ну ты понял. =)
21
Clamp, ага, всё понятно, то есть Alive и Dead проверки действительно лишние.
Пока получается так - может существовать фактически мёртвый юнит с количеством жизней, которое игра считает большим 0, и даже большим 1. Иначе не могу объяснить фатал.
Может, у меня там какой-то триггерный хил действует без проверки на мертвяков, хилит мертвяка и... gg.
Хотя вообще большинство функций у меня исключает мертвяков при проверке групп из обрабатываемых единиц, но... могло быть где-то пренебрежение для хила - типа он же мёртвый, какая разница, отхилится или нет, пока не реснется, не важно, а после реса все равно фулл хп будет. Ну вот разница и вылезла. Придётся эти пренебрежения искать.

И поставлю таки наверное вместо 1 конкретно в этой функции хотя бы 25, что ли, это будет не заметно в 99.5% случаев, а фаталы если и не устранит вообще, то сделает их еще меньше (их и ща мало, крокодилом было много норм игр сыграно, ему больше месяца уже и была вот дрочка с 6 ботами-крокодилами, но вот 2 раза таки вылезли).
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.