Решено Вылетает игра

vladik_II

Новичок
1 Июл 2021
4
0
Всем привет, решил обновить свою кастомку (22 года последняя обнова), карту и пару скриптов пофиксил, но теперь вылетает игра при ивенте: DOTA_GAMERULES_STATE_GAME_IN_PROGRESS
Я уже неделю лазию и не могу найти из-за чего, вот скрипт из-за которого по идеи вылетает
Lua:
-- Item Pickup Event
if pickupListener == nil then pickupListener = ListenToGameEvent("dota_item_picked_up", function(kv)
        --for k, v in pairs(kv) do print(k, v) end
        if IsClient() or kv.HeroEntityIndex == nil then return end

        -- List of useful variables from kv
        local playerID = kv.PlayerID
        local itemName = kv.itemname
        local itemIndex = kv.ItemEntityIndex
        local heroIndex = kv.HeroEntityIndex
 
        local item = EntIndexToHScript(itemIndex)
        local hero = EntIndexToHScript(heroIndex)
 
        -- Tries to add the item buff onto the hero, if it does, "consume it" (Remove item as soon as it gets picked up) --print(itemName) --print(heroIndex) --print(hero)
        local success = hero:PickupDroppedItem(hero, itemName)
        print(success)
        if success then
            hero:RemoveItem(item)
            EmitSoundOnLocationWithCaster(hero:GetAbsOrigin(), "Hero_Alchemist.Scepter.Cast", hero)
        end
    end, nil)
end

-- Function to attempt to add
function CDOTA_BaseNPC:PickupDroppedItem(caster, itemName)
    local PickupName = "pickup_"..itemName
    local file = "pickup_items/"..PickupName
    if pcall(require,file) then
        LinkLuaModifier(PickupName, file, LUA_MODIFIER_MOTION_NONE)
    end
 
    -- First checks if the modifier exists, refreshes if it does.
    local currentModifier = caster:FindModifierByName(PickupName) --print(currentModifier)
    if currentModifier then
        -- Runs when hero already has the buff, assumes that the buff exists (LinkLuaModifier)
        currentModifier:ForceRefresh() --print("returned true when trying to force refresh")
        return true
    else
        -- Attempts to add buff. Will remove the item from inventory if the buff is implemented.
        local newModifier = caster:AddNewModifier(caster, nil, PickupName, {})
        print(newModifier)
        if newModifier then --print("returned true when trying to make the modifier")
            return true
        end
    end
 
    -- Default Return --print("returned false")
    return false
end

-- ILLUSION HELPER
-- Helper Listener to help illusions
ListenToGameEvent("npc_spawned", function(keys)
    -- entindex numbers repeat after a while
    local illusion = EntIndexToHScript(keys.entindex)
    if IsClient() then return end
    if not illusion:IsIllusion() then return end
 
    -- Need a delay to make sure the modifiers are being added
    illusion:AddNewModifier(illusion, nil, "pickup_modifier", {})
end, nil)

-- Illusion Modifier to fix the stacks
LinkLuaModifier("pickup_modifier", "pickup_items/itemPickup.lua", LUA_MODIFIER_MOTION_NONE)
pickup_modifier = class({})

function pickup_modifier:OnCreated()
    self:StartIntervalThink(0.01)
end

function pickup_modifier:OnIntervalThink()
    self:Destroy()
end

function pickup_modifier:OnDestroy()
    local illusion = self:GetParent()

    -- Get illusion owner
    local owner = illusion:GetPlayerOwner():GetAssignedHero()
    print(owner:GetUnitName())
 
    -- Modifier list to return pickup items
    local modifierList = owner:FindAllModifiers()
 
    for i = 1, #modifierList do
        local modifierName = modifierList[i]:GetName()
        --print(modifierName)
   
        -- Solves the item problem
        if string.find(modifierName, "pickup") and modifierName ~= "pickup_modifier" then
            local modifierStack = modifierList[i]:GetStackCount()
            local modifierIllusion = illusion:FindModifierByName(modifierName)
       
            if modifierIllusion then modifierIllusion:SetStackCount(modifierStack) end
        end
    end
end
Суть скрипта в том, что подобрав предмет, предмет ломается и вешаеться модификация с статами предмета
Вот еще один срипт уже самой шмотки с модификаторами (Сатаник)
Lua:
- Class
pickup_item_satanic = class({})

-- Modifier Properties
function pickup_item_satanic:GetTexture()
    return string.gsub(self:GetClass(), "pickup_", "")
end

function pickup_item_satanic:IsPurgable() return false end
function pickup_item_satanic:IsHidden() return true end
function pickup_item_satanic:RemoveOnDeath() return false end
function pickup_item_satanic:AllowIllusionDuplicate() return false end

-- Methods
function pickup_item_satanic:OnCreated()
    if IsClient() then return end --print(self:GetClass())
    self:SetStackCount(1)
end

function pickup_item_satanic:OnRefresh()
    if IsClient() then return end --print(self:GetClass())
    self:IncrementStackCount()
end

-- ESSENTIAL REQUIRED FIELDS ABOVE
-- REST OF THE ITEM MECHANICS BELOW

-- Declares Functions that will simulate item properties
function pickup_item_satanic:DeclareFunctions()
    return {
        MODIFIER_PROPERTY_PREATTACK_BONUS_DAMAGE,
        MODIFIER_PROPERTY_STATS_STRENGTH_BONUS,
        MODIFIER_PROPERTY_STATUS_RESISTANCE_STACKING,
   
        MODIFIER_EVENT_ON_TAKEDAMAGE,
    }
end

-- Property Functions
function pickup_item_satanic:GetModifierPreAttack_BonusDamage()
    local bonus = 25
    return self:GetStackCount() * bonus
end

function pickup_item_satanic:GetModifierBonusStats_Strength()
    local bonus = 50
    return self:GetStackCount() * bonus
end

function pickup_item_satanic:GetModifierStatusResistanceStacking()
    local bonus = 30
 
    -- Resistance Calculation
    return 100 - math.pow((100 - bonus)/100, self:GetStackCount()) * 100
end

function pickup_item_satanic:OnTakeDamage(keys)
    if IsClient() then return end

    -- Lifesteal Passive Conditions:
    -- The parent must be the attacker
    -- The damage must come from a right-click
    if keys.attacker == self:GetParent() and keys.damage_category == DOTA_DAMAGE_CATEGORY_ATTACK then
        local lifesteal_percent = 25
 
        -- Lifesteal particles
        local lifesteal_pfx = ParticleManager:CreateParticle("particles/generic_gameplay/generic_lifesteal.vpcf", PATTACH_ABSORIGIN_FOLLOW, keys.attacker)
        ParticleManager:SetParticleControl(lifesteal_pfx, 0, keys.attacker:GetAbsOrigin())
        ParticleManager:ReleaseParticleIndex(lifesteal_pfx)
 
        -- HEAL
        keys.attacker:Heal(keys.damage * lifesteal_percent/100 * self:GetStackCount(), keys.attacker)
    end
 
    -- Unholy Rage Conditions:
    -- The parent must be below 50% HP
    -- No cooldown
 
    if keys.unit == self:GetParent() and self:GetParent():GetHealthPercent() < 50 then
        local target = self:GetParent()
        if target:FindModifierByName("pickup_item_satanic_active_cooldown") == nil then
            local buffDuration = 5
            local cooldown = 35
       
            target:EmitSound("DOTA_Item.Satanic.Activate")
            local modifier = target:AddNewModifier(target, self, "pickup_item_satanic_active", {duration = buffDuration})
            target:AddNewModifier(target, self, "pickup_item_satanic_active_cooldown", {duration = cooldown})
            if modifier then modifier:SetStackCount(self:GetStackCount()) end
        end
    end
end

-- Satanic Active
LinkLuaModifier("pickup_item_satanic_active", "pickup_items/pickup_item_satanic", LUA_MODIFIER_MOTION_NONE)
LinkLuaModifier("pickup_item_satanic_active_cooldown", "pickup_items/pickup_item_satanic", LUA_MODIFIER_MOTION_NONE)
pickup_item_satanic_active = class({})
pickup_item_satanic_active_cooldown = class({})

-- metadata
function pickup_item_satanic_active:IsPurgable() return false end
function pickup_item_satanic_active:GetTexture() return "item_satanic" end
function pickup_item_satanic_active:GetAttributes() return MODIFIER_ATTRIBUTE_MULTIPLE end

function pickup_item_satanic_active_cooldown:IsPurgable() return false end
function pickup_item_satanic_active_cooldown:RemoveOnDeath()    return false end
function pickup_item_satanic_active_cooldown:GetTexture() return "item_satanic" end

-- Declares Functions that will simulate item properties
function pickup_item_satanic_active:DeclareFunctions()
    return {
        MODIFIER_EVENT_ON_TAKEDAMAGE,
    }
end

-- Property Functions
function pickup_item_satanic_active:OnTakeDamage(keys)
    -- Conditions:
    -- The parent must be the attacker
    -- The damage must come from a right-click
    if IsClient() or keys.attacker ~= self:GetParent() or keys.damage_category ~= DOTA_DAMAGE_CATEGORY_ATTACK then return end
    local lifesteal_percent = 175
 
    -- Lifesteal particles
    local lifesteal_pfx = ParticleManager:CreateParticle("particles/generic_gameplay/generic_lifesteal.vpcf", PATTACH_ABSORIGIN_FOLLOW, keys.attacker)
    ParticleManager:SetParticleControl(lifesteal_pfx, 0, keys.attacker:GetAbsOrigin())
    ParticleManager:ReleaseParticleIndex(lifesteal_pfx)
 
    -- HEAL
    keys.attacker:Heal(keys.damage * lifesteal_percent/100 * self:GetStackCount(), keys.attacker)
end
При ивенте DOTA_GAMERULES_STATE_PRE_GAME все работает, предметы пропадают модификаторы даются, но как только ивент переходит в DOTA_GAMERULES_STATE_GAME_IN_PROGRESS при подборе предмета вылетает игра, нашел дамп, код вылета 0xC0000005 (accessviolation)
причина: Потоком была предпринята попытка прочитать или записать данные на виртуальный адрес, к которому он не имеет соответствующего доступа.


UPD: Ребята, все починил, путем долгих тестов и дебагов, понял что нужно добавить небольшую задержку перед тем как шмотка пропадет
Вот код мб кому то пригодится
Lua:
-- Item Pickup Event
ListenToGameEvent("dota_item_picked_up", function(keys)
    -- Проверяем, что событие вызвано на сервере и герой существует
    if IsClient() or keys.HeroEntityIndex == nil then
        --print("Ошибка: событие вызвано на клиенте или герой не найден.")
        return
    end

    -- Получаем данные из события
    local playerID = keys.PlayerID
    local itemName = keys.itemname -- Имя предмета
    local itemIndex = keys.ItemEntityIndex
    local heroIndex = keys.HeroEntityIndex

    -- Получаем объект предмета и героя
    local item = EntIndexToHScript(itemIndex) -- Предмет
    local hero = EntIndexToHScript(heroIndex) -- Герой, который подобрал предмет

    -- Проверяем, что предмет и герой существуют
    if not item or item:IsNull() then
        --print("Ошибка: предмет не найден.")
        return
    end
    if not hero or hero:IsNull() then
        --print("Ошибка: герой не найден.")
        return
    end

    -- Вызываем функцию и передаем предмет
    local success = hero:PickupDroppedItem(hero, itemName, item)

    --print("Результат PickupDroppedItem:", success)
    if success then
        -- Добавляем задержку перед удалением предмета
        Timers:CreateTimer(0.1, function() -- Задержка 0.1 секунды (def 0.5)
            if item and not item:IsNull() then
                hero:RemoveItem(item)
                --print("Предмет удален:", itemName)
            else
                --print("Ошибка: предмет не существует или был уничтожен.")
            end
        end)
    else
        --print("Не удалось обработать предмет:", itemName)
    end
end, nil)

function CDOTA_BaseNPC:PickupDroppedItem(caster, itemName, item)
    -- Проверяем, что caster, itemName и item переданы корректно
    if not caster or caster:IsNull() then
        --print("Ошибка: caster не найден или уничтожен.")
        return false
    end
    if not itemName then
        --print("Ошибка: itemName не указан.")
        return false
    end
    if not item or item:IsNull() then
        --print("Ошибка: item не найден или уничтожен.")
        return false
    end

    local PickupName = "pickup_" .. itemName
    local file = "pickup_items/" .. PickupName
--[[
    -- Пытаемся загрузить файл модификатора
    local status, err = pcall(require, file)
    if not status then
        --print("Ошибка при загрузке файла модификатора:", err)
        return false
    end
]]
    -- Подключаем модификатор
    LinkLuaModifier(PickupName, file, LUA_MODIFIER_MOTION_NONE)

    -- Проверяем, есть ли уже такой модификатор у героя
    local currentModifier = caster:FindModifierByName(PickupName)

    if currentModifier then
        -- Если модификатор уже есть, обновляем его
        currentModifier:ForceRefresh()
        --print("Модификатор обновлен:", PickupName)
        return true
    else
        -- Если модификатора нет, добавляем новый
        local newModifier = caster:AddNewModifier(caster, nil, PickupName, {})
        if newModifier then
            newModifier:SetStackCount(1)
            --print("Модификатор добавлен:", PickupName)
            return true
        else
            -- Если не удалось добавить модификатор, возвращаем false
            print("Ошибка: не удалось добавить модификатор:", PickupName)
            return false
        end
    end
end
 
Последнее редактирование:
скорее всего из за нейтралок, либо у тебя файл неактуальный, либо предмета нету в items
 
скорее всего из за нейтралок, либо у тебя файл неактуальный, либо предмета нету в items
Я каждый предмет отдельно добавлял, если предмета нету, он просто подберется и игра не крашнится, нейтралки ванильные, они не как не задействованы. Единственное я убедился что проблема именно в 1 коде, щас тестил шмотки без модификаторов, в pre_game вешается пустой модификатор, в in_progress снова вылеты. Буду думать пока как переписать код по другому. А так спаибо.
 
Реклама: