Решено Конвертация атрибутов

  • Автор темы Автор темы kualla0
  • Дата начала Дата начала

kualla0

Пользователь
7 Фев 2020
16
3
Ребят, все привет. Очень прошу вашей помощи. В общем задумка у меня такая, хочу добавить врожденку персонажу которая будет конвертировать дополнительные статы от предметов(ловкость и интелект) в дополнительную силу. Скил сам по себе уже прописан, но на данный момент статы все скачут, либо при попытке фиксации этих значений после продажи предметов статы не убираются, что в принципе и понятно. По хорошему надо сделать проверку предметов и их статов в самом модификаторе скила, но вот незадача на мою голову, представить не могу как это сделать.
 
  • Нравится
Реакции: D1an1s
Я понимаю, что при таком написании не будет никакого отслеживания, а только фиксации, но пока вариантов никаких больше не придумал

Код:
LinkLuaModifier("modifier_clear_strength", "Heroes/Axe/axe_clear_strength", LUA_MODIFIER_MOTION_NONE)

axe_clear_strength = class ({})

function axe_clear_strength:GetIntrinsicModifierName()
    return "modifier_clear_strength"
end

modifier_clear_strength = class ({})

function modifier_clear_strength:OnCreated()
    self.Agility = 0
    self.Intellect = 0
    self:StartIntervalThink(0.3)
end

function modifier_clear_strength:OnIntervalThink()
    local Intellect = self:GetCaster():GetIntellect(false)
    local Agility = self:GetCaster():GetAgility()
    if Agility > 0 then
        self.Agility = Agility
    end
    if Intellect > 0 then
        self.Intellect = Intellect
    end
    print("Agility:", self.Agility)
end

function modifier_clear_strength:DeclareFunctions()
    return {
        MODIFIER_PROPERTY_STATS_INTELLECT_BONUS,
        MODIFIER_PROPERTY_STATS_AGILITY_BONUS,
        MODIFIER_PROPERTY_STATS_STRENGTH_BONUS
    }
end

function modifier_clear_strength:GetModifierBonusStats_Intellect()
    return -self.Intellect
end

function modifier_clear_strength:GetModifierBonusStats_Agility()
    return -self.Agility
end

function modifier_clear_strength:GetModifierBonusStats_Strength()
    return (self.Intellect + self.Agility)
end
 
Знаю, что можно через EntIndexToHScript() найти юнита и перебрать через for имеющиеся у него предметы с помощью GetItemInSlot(), но можно ли с помощью это как-то вытаскивать статы самих предметов?
 
Вот кастомная версия перекачки морфа попробуй )
Код:
    "morphling_morph_custom"
    {
        // General
        //-------------------------------------------------------------------------------------------------------------
        "BaseClass"                        "ability_lua"
        "ScriptFile"                    "abilities/heroes/hero_morphling/morph_custom"
        "AbilityTextureName"            "morphling/morph_none"
        "AbilityBehavior"                "DOTA_ABILITY_BEHAVIOR_NO_TARGET | DOTA_ABILITY_BEHAVIOR_IMMEDIATE"
        "AbilityCastAnimation"            "ACT_INVALID"
        "RequiredLevel"                    "1"
        "LevelsBetweenUpgrades"            "3"
        "MaxLevel"                        "9"

        // Time
        //-------------------------------------------------------------------------------------------------------------
        "AbilityCooldown"                "0.0"

        // Special
        //-------------------------------------------------------------------------------------------------------------
        "AbilityValues"
        {
            "transfer_speed"        "10 15 20 25 30 35 40 50"
            "transfer_speed_pct"    "0 0 0 0 1 2 3 4 5"
            "bonus_attributes"        "10 15 20 25 30 40 50 60 70"
            "min_model_scale_pct"    "-50"
            "max_model_scale_pct"    "200"
        }
    }
Код:
morphling_morph_custom = class({})

function morphling_morph_custom:GetIntrinsicModifierName()
    return "modifier_morphling_morph_custom_bonus"
end

function morphling_morph_custom:GetAbilityTextureName()
    local caster = self:GetCaster()
    if(not caster) then
        return self.BaseClass.GetAbilityTextureName()
    end
    local stacks = caster:GetModifierStackCount(self:GetIntrinsicModifierName(), caster)
    if (stacks == 0) then
        return "morphling/morph_none"
    elseif (stacks == 1) then
        return "morphling/morph_agi"
    elseif (stacks == 2) then
        return "morphling/morph_str"
    end
end

function morphling_morph_custom:OnSpellStart()
    local caster = self:GetCaster()
    local morph_ability = caster:FindAbilityByName("morphling_morph_custom_str")
    local morph_modifier = caster:FindModifierByName("modifier_morphling_morph_custom_bonus")
    local morph_state = morph_modifier:GetStackCount()

    if morph_state == 0 then
        morph_modifier:SetStackCount(1)
        caster:AddNewModifier( caster, self, "modifier_morphling_morph_custom_agi", nil )
        EmitSoundOn("Hero_Morphling.MorphAgility", caster)

     elseif morph_state == 1 then
        morph_modifier:SetStackCount(2)
        caster:AddNewModifier( caster, self, "modifier_morphling_morph_custom_str", nil )
        EmitSoundOn("Hero_Morphling.MorphStrengh", caster)

        caster:RemoveModifierByName("modifier_morphling_morph_custom_agi")
        StopSoundOn("Hero_Morphling.MorphAgility", caster)
    elseif morph_state == 2 then
        morph_modifier:SetStackCount(0)
        
        caster:RemoveModifierByName("modifier_morphling_morph_custom_str")
        StopSoundOn("Hero_Morphling.MorphStrengh", caster)
    end
end


--------------------------------------------------------------------------------

modifier_morphling_morph_custom_agi = class({
    IsHidden                = function(self) return false end,
    IsPurgable              = function(self) return false end,
 })

function modifier_morphling_morph_custom_agi:OnCreated()
    if not IsServer() then
        return
    end
    self:OnRefresh()
end

function modifier_morphling_morph_custom_agi:OnRefresh()
    local ability = self:GetAbility()
    local transfer_speed = ability:GetSpecialValueFor("transfer_speed")
    local transfer_speed_pct = ability:GetSpecialValueFor("transfer_speed_pct")
    local tick_interval = 0.1

    if transfer_speed <= 30 then --because of frame time 0.03
        tick_interval = 1/transfer_speed
    end

    self.transfer_amount = transfer_speed*tick_interval
    self.transfer_amount_pct = transfer_speed_pct*tick_interval

    self:StartIntervalThink(tick_interval)
end
function modifier_morphling_morph_custom_agi:GetEffectName()
    return "particles/units/heroes/hero_morphling/morphling_morph_agi.vpcf"
end
function modifier_morphling_morph_custom_agi:OnIntervalThink()
    if not IsServer() then return end   

    local caster = self:GetCaster()
    local ability = self:GetAbility()
    local strength = math.floor(caster:GetStrength())
    local agility = math.floor(caster:GetAgility())
    local atr_sum = strength + agility
    local total_transfer = self.transfer_amount + atr_sum*self.transfer_amount_pct/100

    if strength < total_transfer and strength > 2 then
        total_transfer = strength-1
    elseif strength <= 1 then
        return
    end

    caster:ModifyStrength(-total_transfer)
    caster:ModifyAgility(total_transfer)

    local transfer_health_amount = total_transfer*10
    -- ApplyDamage({
    --     victim          = caster,
    --     attacker        = caster,
    --     damage          = transfer_health_amount,
    --     damage_type     = DAMAGE_TYPE_PURE,
    --     damage_flags     = DOTA_DAMAGE_FLAG_NO_SPELL_AMPLIFICATION + DOTA_DAMAGE_FLAG_NON_LETHAL + DOTA_DAMAGE_FLAG_NO_SPELL_LIFESTEAL + DOTA_DAMAGE_FLAG_NO_DIRECTOR_EVENT,
    --     ability         = ability
    -- })   
end
modifier_morphling_morph_custom_str = class({
    IsHidden                = function(self) return false end,
    IsPurgable              = function(self) return false end,
})

function modifier_morphling_morph_custom_str:OnCreated()
    if not IsServer() then
        return
    end
    self:OnRefresh()
end

function modifier_morphling_morph_custom_str:OnRefresh()
    local ability = self:GetAbility()
    local transfer_speed = ability:GetSpecialValueFor("transfer_speed")
    local transfer_speed_pct = ability:GetSpecialValueFor("transfer_speed_pct")
    local tick_interval = 0.1
    
    if transfer_speed <= 30 then --because of frame time 0.03
        tick_interval = 1/transfer_speed
    end

    self.transfer_amount = transfer_speed*tick_interval
    self.transfer_amount_pct = transfer_speed_pct*tick_interval

    self:StartIntervalThink(tick_interval)
end

function modifier_morphling_morph_custom_str:GetEffectName()
    return "particles/units/heroes/hero_morphling/morphling_morph_str.vpcf"
end

function modifier_morphling_morph_custom_str:OnIntervalThink()
    local caster = self:GetCaster()
    local ability = self:GetAbility()
    local strength = math.floor(caster:GetStrength())
    local agility = math.floor(caster:GetAgility())
    local atr_sum = strength + agility
    local total_transfer = self.transfer_amount + atr_sum*self.transfer_amount_pct/100

    if agility < total_transfer and agility > 2 then
        total_transfer =  agility-1
    elseif agility <= 1 then
        return
    end

    caster:ModifyStrength(total_transfer)
    caster:ModifyAgility(-total_transfer)
    local transfer_health_amount = total_transfer*10
--    caster:Heal(total_transfer*10, ability, DOTA_HEAL_TYPE_HEALING)
end

modifier_morphling_morph_custom_bonus = class({
    IsHidden                = function(self) return true end,
    IsPurgable              = function(self) return false end,
    DeclareFunctions        = function(self) return {
        MODIFIER_PROPERTY_STATS_STRENGTH_BONUS,
        MODIFIER_PROPERTY_STATS_AGILITY_BONUS,
        MODIFIER_PROPERTY_MODEL_SCALE
    }end,
})

function modifier_morphling_morph_custom_bonus:OnCreated()
    if not IsServer() then
        return
    end
    self:OnRefresh()
end

function modifier_morphling_morph_custom_bonus:OnRefresh()
    local ability = self:GetAbility()
    self.bonus_attributes = ability:GetSpecialValueFor("bonus_attributes")
    self.min_model_scale_pct = ability:GetSpecialValueFor("min_model_scale_pct")
    self.max_model_scale_pct = ability:GetSpecialValueFor("max_model_scale_pct")
end

function modifier_morphling_morph_custom_bonus:GetModifierBonusStats_Agility()
    return self.bonus_attributes
end

function modifier_morphling_morph_custom_bonus:GetModifierBonusStats_Strength()
    return self.bonus_attributes
end

function modifier_morphling_morph_custom_bonus:GetModifierModelScale()
    local caster= self:GetCaster()
    local strength = caster:GetStrength()-1
    local agility = caster:GetAgility()-1
    local half_stats = (strength + agility)/2
    local strength_weight = (strength-half_stats)/half_stats
    if strength_weight > 0 then
        value = strength_weight*self.max_model_scale_pct
    else
        value = (-strength_weight)*self.min_model_scale_pct
    end
    return value
end

morphling_morph_custom_mega = class(morphling_morph_custom)

LinkLuaModifier( "modifier_morphling_morph_custom_agi", "abilities/heroes/hero_morphling/morph_custom", LUA_MODIFIER_MOTION_NONE, modifier_morphling_morph_custom_agi)
LinkLuaModifier( "modifier_morphling_morph_custom_str", "abilities/heroes/hero_morphling/morph_custom", LUA_MODIFIER_MOTION_NONE, modifier_morphling_morph_custom_str)
LinkLuaModifier( "modifier_morphling_morph_custom_bonus", "abilities/heroes/hero_morphling/morph_custom", LUA_MODIFIER_MOTION_NONE, modifier_morphling_morph_custom_bonus)
Однако в твоём случае нужно более глубокая логика, которая должна учитывать атрибуты только с предметов, а это значит надо пройтись по всем моифаерам на герое, записывать все модифаеры от предметов дающие силу/ловкость и потом если предмет снимается то возвращать атрибуты
 
Возможно многого прошу, но ты случаем не знаешь какими функциями можно подобного рода переборку модифаеров чисто из предметов сделать и как в последующем вытаскивать из них статы для их перемещения в другой атрибут
 
По морфу то понятно, что он просто берет общее значение стата и перекачивает их при нажатии в другой, но как ты правильно подметил тут нужна более точная отборка, что и куда перекачивать и при этом отслеживать состояние предметов которые их дают
 
Сначала найти все модифаеры
local modifiers = hero:FindAllModifiers()
Потом пройтись по всем модифаерам
for _,modifier in pairs(modifiers) do
if modifier:GetModifierBonusStats_Strength() > 0 or modifier:GetModifierBonusStats_Agility() > 0 then
...
end
end
Я сам не проверяд но должно быть как-то так
 
Сначала найти все модифаеры
local modifiers = hero:FindAllModifiers()
Потом пройтись по всем модифаерам
for _,modifier in pairs(modifiers) do
if modifier:GetModifierBonusStats_Strength() > 0 or modifier:GetModifierBonusStats_Agility() > 0 then
...
end
end
Я сам не проверяд но должно быть как-то так
Спасибо огромное, потестирую и отпишусь
 
Хмм, на проверке (if modifier:GetModifierBonusStats_Agility() > 0 or modifier:GetModifierBonusStats_Intellect() > 0 then) выдает ошибку, что значение nil, и при последующей попытке вывести, что либо через print, консоль молчит, то есть дальше этой проверки не проходит
 
if modifier:GetModifierBonusStats_Agility() or modifier:GetModifierBonusStats_Intellect() then
попробуй так
 
Тот же самый результат. Причем я вывел принт модификатора который проверяется и он какой-то первый находит и циклично его одного прогоняет. Не может ли это как-то вызвано из-за того, что модификаторы в таблице были приведены к виду "0x01f98d48"
 
Последнее редактирование:
А еще консолька выдает ошибку по функции GetModifierBonusStats_Agility() и GetModifierBonusStats_Intellect()
P.S.
Только заметил, что и на FindAllModifiers она тоже ругается, что значение nil
 
Последнее редактирование:
Теперь у меня складывается ощущение, что я hero как-то неправильно инициализирую. self:GetCaster() ведь?
 
Ну пока что получилось вот так
Код:
modifier_clear_strength = class ({})

function modifier_clear_strength:OnCreated()
    self:StartIntervalThink(0.3)
end

function modifier_clear_strength:OnIntervalThink()
    if IsServer() then
        local caster = self:GetCaster()
        local Intellect = caster:GetIntellect(false)
        local Agility = caster:GetAgility()
        local Strength = caster:GetStrength()
        local modifiers = caster:FindAllModifiers()
        local atr_int = 0
        local atr_agil = 0
        for _,modifier in ipairs(modifiers) do
            print("modifier:", modifier)
            if modifier:GetModifierBonusStats_Agility() or modifier:GetModifierBonusStats_Intellect() then
                if modifier:GetModifierBonusStats_Intellect() then
                    atr_int = atr_int + modifier:GetModifierBonusStats_Intellect()
                    print("atr_int", atr_int)
                    caster:ModifyIntellect(atr_int)
                elseif modifier:GetModifierBonusStats_Agility() then
                    atr_agil = atr_agil + modifier:GetModifierBonusStats_Agility()
                    print("atr_agil", atr_agil)
                    caster:ModifyAgility(atr_agil)
                end
                caster:ModifyStrength(atr_int + atr_agil)
            end
        end
    end
end
 
Если кому-то в будущем понадобиться, вот такой модификтор вышел по итогу

Код:
modifier_clear_strength = class({
    IsHidden = function(self) return false end,
    IsDebuff = function(self) return false end,
    IsPurgable = function(self) return false end,
    GetAttributes = function(self) return MODIFIER_ATTRIBUTE_PERMANENT end,
    DeclareFunctions = function(self)
        return {
            MODIFIER_PROPERTY_STATS_STRENGTH_BONUS,
            MODIFIER_PROPERTY_STATS_INTELLECT_BONUS,
            MODIFIER_PROPERTY_STATS_AGILITY_BONUS
        }
    end,
    OnCreated = function(self)
        if IsServer() then
            self.bonus_int = 0
            self.bonus_agi = 0
            self:StartIntervalThink(0.1)
        end
    end
})

function modifier_clear_strength:OnIntervalThink()
    if IsServer() then
        local caster = self:GetCaster()
        local modifiers = caster:FindAllModifiers()
        
        local old_bonus_int = self.bonus_int or 0
        local old_bonus_agi = self.bonus_agi or 0
        
        self.bonus_int = 0
        self.bonus_agi = 0
        
        for _, modifier in ipairs(modifiers) do
            if modifier ~= self then
                local parent_item = modifier:GetAbility()
                if parent_item then
                    local bonus_int = parent_item:GetSpecialValueFor("bonus_intellect") or 0
                    local bonus_agi = parent_item:GetSpecialValueFor("bonus_agility") or 0
                    
                    self.bonus_int = self.bonus_int + bonus_int
                    self.bonus_agi = self.bonus_agi + bonus_agi
                end
            end
        end
        
        if self.bonus_int ~= old_bonus_int or self.bonus_agi ~= old_bonus_agi then
            self:GetParent():CalculateStatBonus(true)
        end
    end
end

function modifier_clear_strength:GetModifierBonusStats_Strength()
    return (self.bonus_int or 0) + (self.bonus_agi or 0)
end

function modifier_clear_strength:GetModifierBonusStats_Intellect()
    return -(self.bonus_int or 0)
end

function modifier_clear_strength:GetModifierBonusStats_Agility()
    return -(self.bonus_agi or 0)
end

function modifier_clear_strength:OnDestroy()
    if IsServer() and (self.bonus_int or 0) > 0 then
        self:GetCaster():ModifyStrength(-(self.bonus_int or 0))
    end
    if IsServer() and (self.bonus_agi or 0) > 0 then
        self:GetCaster():ModifyAgility(-(self.bonus_agi or 0))
    end
end
 
  • Нравится
Реакции: fabio_longo
Реклама: