- 1 Июл 2021
- 4
- 0
Всем привет, решил обновить свою кастомку (22 года последняя обнова), карту и пару скриптов пофиксил, но теперь вылетает игра при ивенте: DOTA_GAMERULES_STATE_GAME_IN_PROGRESS
Я уже неделю лазию и не могу найти из-за чего, вот скрипт из-за которого по идеи вылетает
Суть скрипта в том, что подобрав предмет, предмет ломается и вешаеться модификация с статами предмета
Вот еще один срипт уже самой шмотки с модификаторами (Сатаник)
При ивенте DOTA_GAMERULES_STATE_PRE_GAME все работает, предметы пропадают модификаторы даются, но как только ивент переходит в DOTA_GAMERULES_STATE_GAME_IN_PROGRESS при подборе предмета вылетает игра, нашел дамп, код вылета 0xC0000005 (accessviolation)
причина: Потоком была предпринята попытка прочитать или записать данные на виртуальный адрес, к которому он не имеет соответствующего доступа.
UPD: Ребята, все починил, путем долгих тестов и дебагов, понял что нужно добавить небольшую задержку перед тем как шмотка пропадет
Вот код мб кому то пригодится
Я уже неделю лазию и не могу найти из-за чего, вот скрипт из-за которого по идеи вылетает
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
причина: Потоком была предпринята попытка прочитать или записать данные на виртуальный адрес, к которому он не имеет соответствующего доступа.
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
Последнее редактирование: