Jump to content

Dodge Chance for Character


Recommended Posts

Hello!

I was wondering a couple of things, Firstly how would I make a character have the ability to dodge say 40% of all attacks done to them? I guess it would en tale no damage being given on a random chance basic and maybe a "miss" sound being played. I can do the sound just the dodge part I have no idea where to start.

Also speaking of starting, I made a couple mods a while ago and am getting back into it but forgot alot of stuff, what are some good resources to have for the scripting aspect of modding? Every tutorial I have seen thus far is always just the basics and never really explains any scripting or anything. Thank you!

Link to comment
Share on other sites

Spoiler

--------------------------To use this code simply add the variable inst.dodgechance = 0 
----<  Dodge Users   >----a number between 0 and 1 with 1 being 100% chance to dodge for that character
--------------------------For example if you want 40% simply add inst.dodgechance = 0.4 to your character
AddComponentPostInit("combat", function(self)
	local oldGetAttacked = self.GetAttacked
	function self:GetAttacked(attacker, damage, weapon, stimuli)
		local dodgechance = self.inst.dodgechance or 0 --default dodgechance for all characters is 0 do not change this unless you want enemies to dodge as well.
		if self.inst.components.inventory then --if you want items to also bestow dodgechance simply add inst.dodgechance to the respective item, this stacks multiplicatively
			local dodgegear = {}--otherwise this if statement can be commented out.
			for k, v in pairs(GLOBAL.EQUIPSLOTS) do
				table.insert(dodgegear, self.inst.components.inventory:GetEquippedItem(v))
			end
			for k,v in pairs(dodgegear) do
				if v.dodgechance then dodgechance = 1-((1-dodgechance)*(1-v.dodgechance)) end --stacks multiplicatively
			end	
		end
		if dodgechance > 0 and math.random() <= dodgechance then
			--print("dodged")
			-- visual effects and other stuff you can add
			local x, y, z = self.inst.Transform:GetWorldPosition()
				SpawnPrefab("sand_puff_large_back").Transform:SetPosition(x, y - .1, z)
				SpawnPrefab("sand_puff_large_front").Transform:SetPosition(x, y, z)
			--damage = 0.01	--use this if u want to still do the attacked animation
			return false 	--use this if u want to skip the attacked animation
		end
		return oldGetAttacked(self, attacker, damage, weapon, stimuli)
	end
end)

This is loosely something I use in my personal mod, which features dodgechance and items that provide it.

If you want a more personal version you can modify it, to just affect your prefab instead.


AddComponentPostInit("combat", function(self)
	local oldGetAttacked = self.GetAttacked
	function self:GetAttacked(attacker, damage, weapon, stimuli)
      	if self.inst.prefab == "wilson" then --change to your character
			local dodgechance = 0.4 --change this number between 0-1 with this example being 40%
			if dodgechance > 0 and math.random() <= dodgechance then
                --print("dodged")
                -- visual effects and other stuff you can add
                local x, y, z = self.inst.Transform:GetWorldPosition()
                SpawnPrefab("sand_puff_large_back").Transform:SetPosition(x, y - .1, z)
                SpawnPrefab("sand_puff_large_front").Transform:SetPosition(x, y, z)
                --damage = 0.01	--use this if u want to still do the attacked animation
                return false 	--use this if u want to skip the attacked animation
            end
        end
		return oldGetAttacked(self, attacker, damage, weapon, stimuli)
	end
end)

Choose one and place it into your modmain.lua

For scripting I would google lua scripting, this is a great way to understand basic programming interactions as well as prebuilt functions.

It is also ideal to look at how other people made similar mods to what you are looking to do and learn from what they did. Reverse engineering to a degree. Using notepad++ find in files feature has been a game changer for me and has made modding much easier being able to find code that is similar to what I am designing.

Cheers,

Iron_Hunter

Link to comment
Share on other sites

On 2/27/2018 at 3:27 AM, IronHunter said:
  Hide contents


--------------------------To use this code simply add the variable inst.dodgechance = 0 
----<  Dodge Users   >----a number between 0 and 1 with 1 being 100% chance to dodge for that character
--------------------------For example if you want 40% simply add inst.dodgechance = 0.4 to your character
AddComponentPostInit("combat", function(self)
	local oldGetAttacked = self.GetAttacked
	function self:GetAttacked(attacker, damage, weapon, stimuli)
		local dodgechance = self.inst.dodgechance or 0 --default dodgechance for all characters is 0 do not change this unless you want enemies to dodge as well.
		if self.inst.components.inventory then --if you want items to also bestow dodgechance simply add inst.dodgechance to the respective item, this stacks multiplicatively
			local dodgegear = {}--otherwise this if statement can be commented out.
			for k, v in pairs(GLOBAL.EQUIPSLOTS) do
				table.insert(dodgegear, self.inst.components.inventory:GetEquippedItem(v))
			end
			for k,v in pairs(dodgegear) do
				if v.dodgechance then dodgechance = 1-((1-dodgechance)*(1-v.dodgechance)) end --stacks multiplicatively
			end	
		end
		if dodgechance > 0 and math.random() <= dodgechance then
			--print("dodged")
			-- visual effects and other stuff you can add
			local x, y, z = self.inst.Transform:GetWorldPosition()
				SpawnPrefab("sand_puff_large_back").Transform:SetPosition(x, y - .1, z)
				SpawnPrefab("sand_puff_large_front").Transform:SetPosition(x, y, z)
			--damage = 0.01	--use this if u want to still do the attacked animation
			return false 	--use this if u want to skip the attacked animation
		end
		return oldGetAttacked(self, attacker, damage, weapon, stimuli)
	end
end)

This is loosely something I use in my personal mod, which features dodgechance and items that provide it.

If you want a more personal version you can modify it, to just affect your prefab instead.



AddComponentPostInit("combat", function(self)
	local oldGetAttacked = self.GetAttacked
	function self:GetAttacked(attacker, damage, weapon, stimuli)
      	if self.inst.prefab == "wilson" then --change to your character
			local dodgechance = 0.4 --change this number between 0-1 with this example being 40%
			if dodgechance > 0 and math.random() <= dodgechance then
                --print("dodged")
                -- visual effects and other stuff you can add
                local x, y, z = self.inst.Transform:GetWorldPosition()
                SpawnPrefab("sand_puff_large_back").Transform:SetPosition(x, y - .1, z)
                SpawnPrefab("sand_puff_large_front").Transform:SetPosition(x, y, z)
                --damage = 0.01	--use this if u want to still do the attacked animation
                return false 	--use this if u want to skip the attacked animation
            end
        end
		return oldGetAttacked(self, attacker, damage, weapon, stimuli)
	end
end)

Choose one and place it into your modmain.lua

For scripting I would google lua scripting, this is a great way to understand basic programming interactions as well as prebuilt functions.

It is also ideal to look at how other people made similar mods to what you are looking to do and learn from what they did. Reverse engineering to a degree. Using notepad++ find in files feature has been a game changer for me and has made modding much easier being able to find code that is similar to what I am designing.

Cheers,

Iron_Hunter

So I tried both of them, both giving the same error it seems.

[00:00:28]: [string "scripts/modutil.lua"]:330: Must specify a string for your custom action! Example: "Perform My Action"
LUA ERROR stack traceback:
        =[C] in function 'assert'
        scripts/modutil.lua(330,1) in function 'AddAction'
        ../mods/WD Gaster/modmain.lua(116,1) in main chunk
        =[C] in function 'xpcall'
        scripts/util.lua(709,1) in function 'RunInEnvironment'
        scripts/mods.lua(511,1) in function 'InitializeModMain'
        scripts/mods.lua(485,1) in function 'LoadMods'
        scripts/main.lua(267,1) in function 'ModSafeStartup'
        scripts/main.lua(327,1)
        =[C] in function 'SetPersistentString'
        scripts/mainfunctions.lua(26,1) in function 'SavePersistentString'
        scripts/modindex.lua(77,1)
        =[C] in function 'GetPersistentString'
        scripts/modindex.lua(64,1) in function 'BeginStartupSequence'
        scripts/main.lua(326,1) in function 'callback'
        scripts/modindex.lua(542,1)
        =[C] in function 'GetPersistentString'
        scripts/modindex.lua(516,1) in function 'Load'
        scripts/main.lua(325,1) in main chunk
[00:00:28]: [string "scripts/mainfunctions.lua"]:1029: variable 'global_error_widget' is not declared
LUA ERROR stack traceback:
        =[C] in function 'error'
        scripts/strict.lua(23,1)
        scripts/mainfunctions.lua(1029,1)
        =[C] in function 'SetPersistentString'
        scripts/mainfunctions.lua(26,1) in function 'SavePersistentString'
        scripts/modindex.lua(77,1)
        =[C] in function 'GetPersistentString'
        scripts/modindex.lua(64,1) in function 'BeginStartupSequence'
        scripts/main.lua(326,1) in function 'callback'
        scripts/modindex.lua(542,1)
        =[C] in function 'GetPersistentString'
        scripts/modindex.lua(516,1) in function 'Load'
        scripts/main.lua(325,1) in main chunk

I put the dodgechance to 1 to see it work before I make it an actually balanced number.

Also thanks, I will have to google it and find a good tutorial.

Link to comment
Share on other sites

Here is my modmain. dodge is near the bottom. Error only happened once I added it.

EDIT: Actually it seems to be doing it regardless.... removed file and I'll reply when I figure out whats causing it... now its a mystery.

 

ALRIGHT, got the crash to not happen, Other issues persist and hopefully I can fix those. But as for the dodging it's saying "attempt to call global 'SpawnPrefab' (a nil value) LUA ERROR stack traceback: then it gives the error back to this line:

                SpawnPrefab("sand_puff_large_back").Transform:SetPosition(x, y - .1, z)

Alright i removed the spawnprefabs and it works flawlessly, now to just get that line to work.

Edited by TheBigDeal
Link to comment
Share on other sites

1 hour ago, TheBigDeal said:

Here is my modmain. dodge is near the bottom. Error only happened once I added it.

EDIT: Actually it seems to be doing it regardless.... removed file and I'll reply when I figure out whats causing it... now its a mystery.

 

ALRIGHT, got the crash to not happen, Other issues persist and hopefully I can fix those. But as for the dodging it's saying "attempt to call global 'SpawnPrefab' (a nil value) LUA ERROR stack traceback: then it gives the error back to this line:


                SpawnPrefab("sand_puff_large_back").Transform:SetPosition(x, y - .1, z)

Alright i removed the spawnprefabs and it works flawlessly, now to just get that line to work.

Simply add

local SpawnPrefab = Global.SpawnPrefab

before the addcomponentpostinit or use Global.SpawnPrefab in front of the SpawnPrefabs which ever works for you.

Cheers,

Iron_Hunter

Link to comment
Share on other sites

AddComponentPostInit("combat", function(self)
	local oldGetAttacked = self.GetAttacked
	function self:GetAttacked(attacker, damage, weapon, stimuli)
		local dodgechance = self.inst.dodgechance or 0 
		if dodgechance > 0 and math.random() <= dodgechance then
			local x, y, z = self.inst.Transform:GetWorldPosition()
				Global.SpawnPrefab("sand_puff_large_back").Transform:SetPosition(x, y - .1, z)
				Global.SpawnPrefab("sand_puff_large_front").Transform:SetPosition(x, y, z)
			return false 
		end
		return oldGetAttacked(self, attacker, damage, weapon, stimuli)
	end
end)

So I made it into this but it's saying "attempt to index global 'Global' (a nil value). I also tried to do this:

local SpawnPrefab = Global.SpawnPrefab
AddComponentPostInit("combat", function(self)
	local oldGetAttacked = self.GetAttacked
	function self:GetAttacked(attacker, damage, weapon, stimuli)
		local dodgechance = self.inst.dodgechance or 0 
		if dodgechance > 0 and math.random() <= dodgechance then
			local x, y, z = self.inst.Transform:GetWorldPosition()
				SpawnPrefab("sand_puff_large_back").Transform:SetPosition(x, y - .1, z)
				SpawnPrefab("sand_puff_large_front").Transform:SetPosition(x, y, z)
			return false 
		end
		return oldGetAttacked(self, attacker, damage, weapon, stimuli)
	end
end)

And that also did not work it seems.

Edited by TheBigDeal
Link to comment
Share on other sites

Spoiler
27 minutes ago, TheBigDeal said:


AddComponentPostInit("combat", function(self)
	local oldGetAttacked = self.GetAttacked
	function self:GetAttacked(attacker, damage, weapon, stimuli)
		local dodgechance = self.inst.dodgechance or 0 
		if dodgechance > 0 and math.random() <= dodgechance then
			local x, y, z = self.inst.Transform:GetWorldPosition()
				Global.SpawnPrefab("sand_puff_large_back").Transform:SetPosition(x, y - .1, z)
				Global.SpawnPrefab("sand_puff_large_front").Transform:SetPosition(x, y, z)
			return false 
		end
		return oldGetAttacked(self, attacker, damage, weapon, stimuli)
	end
end)

So I made it into this but it's saying "attempt to index global 'Global' (a nil value). I also tried to do this:



local SpawnPrefab = Global.SpawnPrefab
AddComponentPostInit("combat", function(self)
	local oldGetAttacked = self.GetAttacked
	function self:GetAttacked(attacker, damage, weapon, stimuli)
		local dodgechance = self.inst.dodgechance or 0 
		if dodgechance > 0 and math.random() <= dodgechance then
			local x, y, z = self.inst.Transform:GetWorldPosition()
				SpawnPrefab("sand_puff_large_back").Transform:SetPosition(x, y - .1, z)
				SpawnPrefab("sand_puff_large_front").Transform:SetPosition(x, y, z)
			return false 
		end
		return oldGetAttacked(self, attacker, damage, weapon, stimuli)
	end
end)

And that also did not work it seems.

Derp...Global needs to be all caps GLOBAL... my bad, the same way I had it for GLOBAL.EQUIPSLOTS in the original post.

Work and late night coding don't mix lols.

Cheers,

Iron_Hunter

Edited by IronHunter
quote size
Link to comment
Share on other sites

3 minutes ago, IronHunter said:
  Reveal hidden contents

Derp...Global needs to be all caps GLOBAL... my bad, the same way I had it for GLOBAL.EQUIPSLOTS in the original post.

Work and late night coding don't mix lols.

Cheers,

Iron_Hunter

Alright! that worked, even though it seems setting the dodge chance to 1 isn't 100% dodgeable, its fine as it wont be set to that anyways.

To continue with the dodging, my character has two forms also so the dodge needs to be adaptable, I already tried act.dodge chance = 1 in my modmain for him changing forms. if the inst.dodge chance isn't 1 also it doesn't seem to be all the time leading me to think its not working as it should be. Any idea why/how I can make it change?

Also, this is a bit off the current topic. But I also have a teleportation system in place with an item (Right click and it teleports you to the cursor). I want to transfer the teleportation to a key bind X. How could I make it so X will teleport the character to the position of the mouse and lose a bit of sanity? If that's even possible.

Here is the code for that so you have an idea of how it works.

local TRANSFORM = GLOBAL.Action()
	TRANSFORM.str = "Transform"
	TRANSFORM.id = "TRANSFORM"
TRANSFORM.fn = function(act)
	if act.target.normal_mode == true and act.target.transform_cooldown == nil then
		act.target.normal_mode = nil
		act.target.transform_cooldown = true
		act.target.AnimState:SetBuild("transformationform")
		act.target.components.talker:Say("Transforming...")
		act.target:DoTaskInTime(5, function() act.target.transform_cooldown = nil end)
		act.dodgechance = 1
	elseif act.target.normal_mode == nil and act.target.transform_cooldown == nil then
		act.target.normal_mode = true
		act.target.AnimState:SetBuild("regularform)
		act.target.components.talker:Say("Undoing the Transformation...")
		act.dodgechance = 1
	elseif act.target.transform_cooldown == true then
		act.target.components.talker:Say("That's impossible...")
		act.target:PushEvent("emote", { anim = "emoteXL_facepalm", mounted = true })
	end
end

Thank you so much for answering my questions!

Link to comment
Share on other sites

I'll look at your other code tomorrow, but if you copied the code correctly, it should be working. I tested the original code on my own mod and it works just fine, do note that this only allows you to dodge stuff that would cause you to take damage, not health loss from fire/starvation/temperature etc.

There are a number of mods on the workshop that bind a key to do something, you can pretty much copy that bind key function and use those. I don't usually like using keybinds as they aren't friendly to controllers, which a lot of my friends use to play this game.

I am out of time for tonight, got to go to bed.

Cheers,

Iron_Hunter

Link to comment
Share on other sites

21 minutes ago, IronHunter said:

I'll look at your other code tomorrow, but if you copied the code correctly, it should be working. I tested the original code on my own mod and it works just fine, do note that this only allows you to dodge stuff that would cause you to take damage, not health loss from fire/starvation/temperature etc.

There are a number of mods on the workshop that bind a key to do something, you can pretty much copy that bind key function and use those. I don't usually like using keybinds as they aren't friendly to controllers, which a lot of my friends use to play this game.

I am out of time for tonight, got to go to bed.

Cheers,

Iron_Hunter

Hmm, that's a fair point, sadly with the character i am making it's an ability he can do and not an item so I'm not sure how I would get around that. Maybe some configuration that will give you a item or use a key bind in the mod config could work. Or maybe I can bind or for controllers to be a mix, say X + A or something like that.

And as for the damage, I was checking it by spawning Hounds and letting them attack me, having inst.dodgechance = 1 in my character.lua makes it 100%, just not sure is the act.dodge chance is working, Sorry if I worded that weirdly beforehand.

Link to comment
Share on other sites

On 3/2/2018 at 3:04 AM, IronHunter said:

I'll look at your other code tomorrow, but if you copied the code correctly, it should be working. I tested the original code on my own mod and it works just fine, do note that this only allows you to dodge stuff that would cause you to take damage, not health loss from fire/starvation/temperature etc.

There are a number of mods on the workshop that bind a key to do something, you can pretty much copy that bind key function and use those. I don't usually like using keybinds as they aren't friendly to controllers, which a lot of my friends use to play this game.

I am out of time for tonight, got to go to bed.

Cheers,

Iron_Hunter

Ey, don't mean to be a bug but have you been able to look it over yet?

Link to comment
Share on other sites

53 minutes ago, TheBigDeal said:

Ey, don't mean to be a bug but have you been able to look it over yet?

Been busy with Work, and life, from a quick look have you tried using act.doer.dodgechance?

act.doer references the prefab performing the action, as for the keybind thing I'll have to look at that when I have more time.

I seriously recommend you check out somebody else's mod that uses keybinds and just copy that for your character, then use it to run the action.

If anybody else wants to help him with the keybind thing, that is cool too.

Cheers,

Iron_Hunter

Link to comment
Share on other sites

22 hours ago, IronHunter said:

Been busy with Work, and life, from a quick look have you tried using act.doer.dodgechance?

act.doer references the prefab performing the action, as for the keybind thing I'll have to look at that when I have more time.

I seriously recommend you check out somebody else's mod that uses keybinds and just copy that for your character, then use it to run the action.

If anybody else wants to help him with the keybind thing, that is cool too.

Cheers,

Iron_Hunter

Alright, I'll give that a try, thank you so much for all the help you've given.

Though I already have the transform key to a keybind so it's not so much the keybind that troubles me it's more of getting the keybind to teleport.

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...