Maniacal Wagon Posted April 25, 2019 Share Posted April 25, 2019 Heyo, so I'm working on a character and was having some trouble implementing a few things. First off Is it possible to give an inherent physical defense multiplier? I know there's inst.components.health:SetAbsorptionAmount() But that applies to all sources of damage. Additionally is it possible to give a physical poison immunity like the seashell suit and horned helmet to a character? If anybody can help, let me know, thanks! Link to comment https://forums.kleientertainment.com/forums/topic/105350-modding-help-defense-multipliers/ Share on other sites More sharing options...
Maniacal Wagon Posted April 26, 2019 Author Share Posted April 26, 2019 Ok, so I was able to find out how to do the poison part of this, but I'm still stuck on the damage. Also, poke Link to comment https://forums.kleientertainment.com/forums/topic/105350-modding-help-defense-multipliers/#findComment-1185347 Share on other sites More sharing options...
Ultroman Posted April 26, 2019 Share Posted April 26, 2019 Well, there's no descriptor on the damage about whether or not it is physical or meta-physical (joke, shadow creatures) or fire. If we look at how the code works, we can see that there are only a few things which can impact how much damage an attacker deals to you. This is the game code: if self.inst.components.health ~= nil and damage ~= nil and damageredirecttarget == nil then if self.inst.components.inventory ~= nil then damage = self.inst.components.inventory:ApplyDamage(damage, attacker, weapon) end damage = damage * self.externaldamagetakenmultipliers:Get() if damage > 0 and not self.inst.components.health:IsInvincible() then --Bonus damage only applies after unabsorbed damage gets through your armor if attacker ~= nil and attacker.components.combat ~= nil and attacker.components.combat.bonusdamagefn ~= nil then damage = damage + attacker.components.combat.bonusdamagefn(attacker, self.inst, damage, weapon) or 0 end local cause = attacker == self.inst and weapon or attacker --V2C: guess we should try not to crash old mods that overwrote the health component damageresolved = self.inst.components.health:DoDelta(-damage, nil, cause ~= nil and (cause.nameoverride or cause.prefab) or "NIL", nil, cause) damageresolved = damageresolved ~= nil and -damageresolved or damage if self.inst.components.health:IsDead() then if attacker ~= nil then attacker:PushEvent("killed", { victim = self.inst }) end if self.onkilledbyother ~= nil then self.onkilledbyother(self.inst, attacker) end end else blocked = true end end The things affecting the taken damage are: The ApplyDamage function on your inventory, which apply the absorption rates and resistances on your equipped items. Any externaldamagemultipliers in your combat component, which affect any damage taken Bonus damage of the attacker The DoDelta function of your health component, which in turn uses its SetVal function whose job it is to pass on the cause of death if the damage was a killing blow and enforce e.g. a minimum health restriction keeping this particular character from dying and in general clamp the health value being set. That's it. I don't see any other way of doing what you want to do, than to roll your own, or hook into something e.g. how armors figure out whether they should absorb the damage, and relay that through the inventory when it checks the equipped items. The inventory has its ApplyDamage function, and it does this: function Inventory:ApplyDamage(damage, attacker, weapon) --check resistance and specialised armor local absorbers = {} for k, v in pairs(self.equipslots) do if v.components.resistance ~= nil and v.components.resistance:HasResistance(attacker, weapon) and v.components.resistance:ShouldResistDamage() then v.components.resistance:ResistDamage(damage) return 0 elseif v.components.armor ~= nil then absorbers[v.components.armor] = v.components.armor:GetAbsorption(attacker, weapon) end end blablabla more code If any of the equipped items have the resistance component, and that component has been set up to resist this particular attacker or weapon, they make the damage 0 instantly! Otherwise, they gather up the absorber items in a dictionary with the component as key and the absorption value calculated by the GetAbsorption function on the armor component. GetAbsorption is pretty simple: function Armor:GetAbsorption(attacker, weapon) return self:CanResist(attacker, weapon) and self.absorb_percent or nil end The armor component has this function, CanResist, which GetAbsorption calls, and if that function returns true, then GetAbsorption returns the armor component's absorption value e.g. 0.6 (60%). function Armor:CanResist(attacker, weapon) if self.tags == nil then return true elseif attacker ~= nil then for i, v in ipairs(self.tags) do if attacker:HasTag(v) or (weapon ~= nil and weapon:HasTag(v)) then return true end end end return false end CanResist basically just says, that if the attacker or the weapon have any of the tags that are on the armor (self.tags), then the armor resists them. If the armor has the "sharp" tag, then its absorption applies to this damage. Notice that it returns true as soon as a matching tag is found. So, what I would do, is that I would contemplate exactly which weapons or attackers I would want my damage reduction perk to apply to, and then try to write something similar. Then you can override combat:GetAttacked and alter the damage with your own code, before the damage is even assessed by the original code. I couldn't help it, so I wrote it: -- This first part goes in your character LUA, ABOVE master_postinit() or fn() local attackerPrefabsToResist = {"crawlinghorror", "terrorbeak", "crawlingnightmare", "nightmarebeak"} local weaponTagsToResist = { "sharp", "blunt" } local weaponPrefabsToResist = {"spear", "nightsword"} local function contains(mytable, value) if mytable and value then for _, v in ipairs(mytable) do if v == value then return true end end end return false end local function tableContainsOneOf(mytable, values) if mytable and values then for _, v in ipairs(values) do if contains(mytable, v) then return true end end end return false end local function myDamageResistance(attacker, damage, weapon) if (attacker and contains(attackerPrefabsToResist, attacker.prefab)) or (weapon and (contains(weaponPrefabsToResist, weapon.prefab) or tableContainsOneOf(weaponTagsToResist, weapon.tags))) then -- subtract some fixed value damage = damage - 2 -- or apply a multiplier damage = damage * (1 - multiplier) -- where multiplier is e.g. 0.4 to apply 40% damage reduction if damage < 0 then damage = 0 end end end end -- The following goes IN your character LUA master_postinit() or fn() local orig_GetAttacked = inst.components.combat.GetAttacked inst.components.combat:GetAttacked = function(attacker, damage, weapon, stimuli, ...) damage = myDamageResistance(attacker, damage, weapon) orig_GetAttacked(self, attacker, damage, weapon, stimuli, ...) end You can write it in another way, if you want to apply different modifiers per weapon tag or weapon prefab or attacker prefab, but this will take care of your original question, with some work with defining the lists. Link to comment https://forums.kleientertainment.com/forums/topic/105350-modding-help-defense-multipliers/#findComment-1185652 Share on other sites More sharing options...
Maniacal Wagon Posted April 27, 2019 Author Share Posted April 27, 2019 Sorry about the late response, but thanks. I'll have to give it a shot there Link to comment https://forums.kleientertainment.com/forums/topic/105350-modding-help-defense-multipliers/#findComment-1186461 Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now