Jump to content

(Solved) Crit code


Recommended Posts

I am trying to get this code to work, while it does, one part of the code just wont work

 

AddComponentPostInit("combat", function(Combat)-- place in modmain
local OldCalcDamage = Combat.CalcDamage
Combat.CalcDamage = function(self, target, weapon, ...)
local old_damage = nil
local crit = 1 --crit chance (e.g. this is 50%)
local critdmg = 50 --crit damage (x2)
if math.random() <= crit and target and self.inst.prefab == "esctemplate" then --change to your prefab
if weapon then -- if its a weapon
old_damage = weapon.components.weapon.damage
weapon.components.weapon.damage = old_damage * critdmg
inst.components.talker:Say("CRIT") 
else -- if we attack with something not using the weapon component
old_damage = self.defaultdamage
self.defaultdamage = old_damage * critdmg
inst.components.talker:Say("CRIT") 
end
end
local ret = OldCalcDamage(self, target, weapon, ...)-- returning crit damage
if old_damage then-- reseting back to non crit damage
if weapon then
weapon.components.weapon.damage = old_damage
else
self.defaultdamage = old_damage
end
end
return ret
end

 

Does anyone have a fix to my little problem? the code works if i remove "inst.components.talker:Say("CRIT") "

plz HELP

Edited by chaosdc123
Link to comment
Share on other sites

EDIT: my answer is innacurate as I misread your post. I just leave it here for reference purpose.

 

inst is not defined in your piece of code.

The argument to your function is Combat, which will be the component ["combat"] when this function is executed as you do a AddComponentPostInit on it.

So you want to retrieve the entity which has this component combat attached.

Let's take a look at the combat.lua

local Combat = Class(function(self, inst)
    self.inst = inst

    self.nextbattlecrytime = nil
    self.battlecryenabled = true
    self.attackrange = 3
    self.hitrange = 3
    self.areahitrange = nil
    self.areahitdamagepercent = nil
    --self.areahitdisabled = nil
    self.defaultdamage = 0
    --
    --use nil for defaults
    --self.playerdamagepercent = 1 --modifier for NPC dmg on players, only works with NO WEAPON
    --self.pvp_damagemod = 1
    --self.damagemultiplier = 1
    --self.damagebonus = 0
    --
    self.min_attack_period = 4
    self.onhitfn = nil
    self.onhitotherfn = nil
    self.laststartattacktime = 0
    self.lastwasattackedtime = 0
    self.keeptargetfn = nil
    self.keeptargettimeout = 0
    self.hiteffectsymbol = "marker"
    self.canattack = true
    self.lasttargetGUID = nil
    self.target = nil
    self.panic_thresh = nil
    self.forcefacing = true
    self.bonusdamagefn = nil
    --self.playerstunlock = PLAYERSTUNLOCK.ALWAYS --nil for default
end,
nil,
{
    attackrange = onattackrange,
    min_attack_period = onminattackperiod,
    canattack = oncanattack,
    target = ontarget,
    panic_thresh = onpanicthresh,
})

You can see at the beginning that the entity which has the combat component attached is stored in a member of the ["combat"]  table called inst.

So you could retrieve it in your function by doing

Combat.inst.components.talker:Say("CRIT")

 

I also don't think it's the only issue in your function but at least this should compile and execute with this modification.

Then you will probably notice that some part of your code are never executed. But I let you see which one first and that will be another discussion.

Edited by ZupaleX
Link to comment
Share on other sites

 

The comments make me believe you got it from this thread, which explains how to use it.

Any instance of inst will have to be self.inst as inst is not defined by default.

If you are planning on calling inst a lot in the code, maybe define inst locally e.g.

local inst = self.inst at the top of your code around the same place as the other local variables are defined at the top.

Cheers

Link to comment
Share on other sites

EDIT: same as above, inaccurate answer from reading your post too fast.

 

In the way the function is written, I believe that calling self.inst would lead to "attempt to index global 'self' (a nil value)" or some undefined behaviour.

AddComponentPostInit adds a function to the table env.postinitfns.ComponentPostInit

	env.AddComponentPostInit = function(component, fn)
		initprint("AddComponentPostInit", component)
		if env.postinitfns.ComponentPostInit[component] == nil then
			env.postinitfns.ComponentPostInit[component] = {}
		end
		table.insert(env.postinitfns.ComponentPostInit[component], fn)
	end

Then this is retrieved and called when you add a component to an entity

function EntityScript:AddComponent(name)
    local lower_name = string.lower(name)
    if self.lower_components_shadow[lower_name] ~= nil then
		print("component "..name.." already exists!"..debugstack_oneline(3))
    end
    
    local cmp = LoadComponent(name)
    assert(cmp, "component ".. name .. " does not exist!")

    self:ReplicateComponent(name)

    local loadedcmp = cmp(self)
    self.components[name] = loadedcmp
    self.lower_components_shadow[lower_name] = true
    
    local postinitfns = ModManager:GetPostInitFns("ComponentPostInit", name)

    for k,fn in ipairs(postinitfns) do
        fn(loadedcmp,self)
    end

    self:RegisterComponentActions(name)
end

so that function takes 2 arguments, the first one is the component and the second one is the EntityScript. There is no "self" in the function you pass as second argument to the AddComponentPostInit like you would find in a "member function" (the ones declared with the : symbol).

Then I might be wrong and if so, please correct me.

Edited by ZupaleX
Link to comment
Share on other sites

I wrote similar code to the one that he is using, which is also the thread I linked in my previous post.

As long as he uses the self.inst within the function as this is where the magic is done that causes all the crits.

Combat.CalcDamage = function(self, target, weapon, ...)

Excuse the poor formating of the post, I am on mobile.

The thread I posted is a solved one with nearly identical code to this one.

E.g. self.inst.prefab == "esctemplate"

in the if statement.

Cheers

Link to comment
Share on other sites

OK so my issue comes from the poor formating of the OP function (no offense meant).

I missed that he defined a function inside the the function with "self" as the first argument. There is actually no magic involved here :)

So yeah self.inst will solve the problem indeed.

Edited by ZupaleX
Link to comment
Share on other sites

1 hour ago, IronHunter said:

 

The comments make me believe you got it from this thread, which explains how to use it.

Any instance of inst will have to be self.inst as inst is not defined by default.

If you are planning on calling inst a lot in the code, maybe define inst locally e.g.

local inst = self.inst at the top of your code around the same place as the other local variables are defined at the top.

Cheers

thank you, do not worry, I plan on crediting you

Link to comment
Share on other sites

38 minutes ago, ZupaleX said:

OK so my issue comes from the poor formating of the OP function (no offense meant).

I missed that he defined a function inside the the function with "self" as the first argument. There is actually no magic involved here :)

So yeah self.inst will solve the problem indeed.

do not worry, I am 100% noob when it comes to coding

Link to comment
Share on other sites

5 hours ago, IronHunter said:

No credit is needed, I am just happy to help.

=) no offense intended and taken we all make mistakes, just trying to clear up confusion.

Cheers

Do not worry, im not offended at all, Im really glad that you guys helped make it work

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
  • Create New...