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

.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, "Сначала все возможные проверки, потом все зависящие от них действия, не наоборот" - а у меня как?
Про функцию - справедливо, ну много чего можно посжимать в функции, да, но это дофига перелопачивать, хотя себя оправдает, ну это ок, но немного другой вопрос.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.