Jump to content

Recommended Posts

Hello o/ this shouldn't be too hard to pull off, in your weapon's prefab file under where you would put the "weapon" component, you'll need to have at least these two fields with it

inst:AddComponent("weapon")
inst.components.weapon:SetDamage(YOUR_WEAPON_DAMAGE_PER_HIT)
inst.components.weapon:SetOnAttack(onattack)

Where SetDamage is self-explanitory, but SetOnAttack will be passed the argument "onattack" which is a function you haven't declared yet, but it'll go somewhere up above near your weapon prefab's other local functions (if any).

Then in your onattack function, you're able to pass it 3 parameters, inst, attacker, and target, where inst is your weapon, attacker is the player attacking, and the target is their target. The main one we're going to want is the target since we're going to want to apply the poison effect to them.

Inside your onattack function, you're basically just going to want to set up a periodic task to deal damage to your target for a certain amount of time. You're probably going to want to figure out how much poison damage you want it to do per swing beforehand, but it would essentially look like this

local poison_length = 30 -- seconds
local poison_interval = 3 -- seconds
local poison_damage = 50 -- total

-- If you want a wind-up time
poison_length = poison_length + poison_interval

local poison_tick = poison_damage / (poison_length / poison_interval)

local function onattack(inst, attacker, target)
	if not target or not target.components.health then return end
	if target.poison_task ~= nil then
		target.poison_task:Cancel()
	end
	target.poison_task = DoPeriodicTask(poison_interval, function(inst)
		-- By having the "false" in the DoDelta, it will enable the sound of your
		-- health falling whenever a poison tick happens, may be useful if a player
		-- gets poisoned, but if you dont want the sound then switch it to "true"
		target.components.health:DoDelta(poison_tick, false, "poison")
	end, poison_interval) -- you only need the poison_interval here if you want the windup

	if target.poisoncure_task ~= nil then
		target.poisoncure_task:Cancel()
	end
	target.poisoncure_task = DoTaskInTime(poison_length, function(inst)
		target.poison_task:Cancel()
		target.poison_task = nil
		target.poisoncure_task = nil
	end)
end

That should at least get the dot working, but you might want to add some other things like maybe tinting the target green temporarily while they're poisoned just for better conveyance. You could also add in things like a chance to get poisoned by adding in a math.random condition if you want as well.

EDIT: You may also have to filter out targets that aren't "poisonable" as well, as this may also affect inanimate objects with health such as walls. That can also be done in the onattack callback.

Edited by w00tyd00d
48 minutes ago, w00tyd00d said:

Hello o/ this shouldn't be too hard to pull off, in your weapon's prefab file under where you would put the "weapon" component, you'll need to have at least these two fields with it


inst:AddComponent("weapon")
inst.components.weapon:SetDamage(YOUR_WEAPON_DAMAGE_PER_HIT)
inst.components.weapon:SetOnAttack(onattack)

Where SetDamage is self-explanitory, but SetOnAttack will be passed the argument "onattack" which is a function you haven't declared yet, but it'll go somewhere up above near your weapon prefab's other local functions (if any).

Then in your onattack function, you're able to pass it 3 parameters, inst, attacker, and target, where inst is your weapon, attacker is the player attacking, and the target is their target. The main one we're going to want is the target since we're going to want to apply the poison effect to them.

Inside your onattack function, you're basically just going to want to set up a periodic task to deal damage to your target for a certain amount of time. You're probably going to want to figure out how much poison damage you want it to do per swing beforehand, but it would essentially look like this


local poison_length = 30 -- seconds
local poison_interval = 3 -- seconds
local poison_damage = 50 -- total

-- If you want a wind-up time
poison_length = poison_length + poison_interval

local poison_tick = poison_damage / (poison_length / poison_interval)

local function onattack(inst, attacker, target)
	if not target or not target.components.health then return end
	if target.poison_task ~= nil then
		target.poison_task:Cancel()
	end
	target.poison_task = DoPeriodicTask(poison_interval, function(inst)
		-- By having the "false" in the DoDelta, it will enable the sound of your
		-- health falling whenever a poison tick happens, may be useful if a player
		-- gets poisoned, but if you dont want the sound then switch it to "true"
		target.components.health:DoDelta(poison_tick, false, "poison")
	end, poison_interval) -- you only need the poison_interval here if you want the windup

	if target.poisoncure_task ~= nil then
		target.poisoncure_task:Cancel()
	end
	target.poisoncure_task = DoTaskInTime(poison_length, function(inst)
		target.poison_task:Cancel()
		target.poison_task = nil
		target.poisoncure_task = nil
	end)
end

That should at least get the dot working, but you might want to add some other things like maybe tinting the target green temporarily while they're poisoned just for better conveyance. You could also add in things like a chance to get poisoned by adding in a math.random condition if you want as well.

EDIT: You may also have to filter out targets that aren't "poisonable" as well, as this may also affect inanimate objects with health such as walls. That can also be done in the onattack callback.

for the onattack function where do I put it and this is the function, right? local SetOnAttack = onattack?

10 minutes ago, GreenDevil said:

for the onattack function where do I put it

Somewhere up above in your weapon's prefab file
 

10 minutes ago, GreenDevil said:

and this is the function, right? local SetOnAttack = onattack?

Noo haha you have to pass it as an argument to the SetOnAttack function in your weapon's "weapon" component, like I had written up above ^
This should also be located in your weapon's prefab somewhere below the TheWorld.ismastersim check

inst:AddComponent("weapon")
inst.components.weapon:SetDamage(YOUR_WEAPON_DAMAGE_PER_HIT)
inst.components.weapon:SetOnAttack(onattack)

 

53 minutes ago, w00tyd00d said:

Somewhere up above in your weapon's prefab file
 

Noo haha you have to pass it as an argument to the SetOnAttack function in your weapon's "weapon" component, like I had written up above ^
This should also be located in your weapon's prefab somewhere below the TheWorld.ismastersim check


inst:AddComponent("weapon")
inst.components.weapon:SetDamage(YOUR_WEAPON_DAMAGE_PER_HIT)
inst.components.weapon:SetOnAttack(onattack)

 

please help D: https://www.toptal.com/developers/hastebin/edocezicak.lua

6 minutes ago, w00tyd00d said:

It looks like you started a function declaration at line 28 but then never finished it, but in actuality it shouldn't even be there at all lol basically delete line 28 and then try it again

This is what I get once I attack.

780c907b285b5e94850ff50514f9a452.png

12 minutes ago, w00tyd00d said:

Oh that's my fault, both DoTaskInTime and DoPeriodicTask need to be called from the target, replace them with target:DoTaskInTime and target:DoPeriodicTask respectively

I can load in but when I attack it doesn't do the DoT damage, it just does the weapon damage.

Actually I just realized it should also be a negative number in the DoDelta call as well, else you'll actually end up healing your target over time instead of poisoning them lol so make sure that DoDelta receives -poison_tick as an argument.

Was your target healing over time or was that not having any effect either?

EDIT: Also in each nameless function passed in both task functions, switch out inst for target so it says function(target), again my b

Edited by w00tyd00d

Eyy happy to hear it!

The way it's set up it shouldn't stack, it will just refresh the duration of it (and restart the poison intervals). Though if you wanted to add a cooldown, just set up a third task and have your onattack check if that task exists and if it does, just return (same with the guard clause you already have at the top, you can just append it on the end of that) so something like this

local function onattack(inst, attacker, target)
	if not target or not target.components.health or target.poison_CD then return end
	if target.poison_task ~= nil then
		target.poison_task:Cancel()
	end
	target.poison_task = target:DoPeriodicTask(poison_interval, function(target)
		-- By having the "false" in the DoDelta, it will enable the sound of your
		-- health falling whenever a poison tick happens, may be useful if a player
		-- gets poisoned, but if you dont want the sound then switch it to "true"
		target.components.health:DoDelta(-poison_tick, false, "poison")
	end, poison_interval) -- you only need the poison_interval here if you want the windup

	if target.poisoncure_task ~= nil then
		target.poisoncure_task:Cancel()
	end
	target.poisoncure_task = target:DoTaskInTime(poison_length, function(target)
		target.poison_task:Cancel()
		target.poison_task = nil
		target.poisoncure_task = nil
	end)

	target.poison_CD = target:DoTaskInTime(COOLDOWN_TIME_HERE, function(target) target.poison_CD = nil end)
end


The nice thing about storing it on the target is that way even if they get attacked by another source of poison, the cooldown will still be in effect. If you want the cooldown to be tracked via the weapon instead, just replace target with inst with everything to do with the poison_CD variable
 

Edited by w00tyd00d
  • Like 1
5 minutes ago, w00tyd00d said:

Eyy happy to hear it!

The way it's set up it shouldn't stack, it will just refresh the duration of it (and restart the poison intervals). Though if you wanted to add a cooldown, just set up a third task and have your onattack check if that task exists and if it does, just return (same with the guard clause you already have at the top, you can just ammend it on the end of that) so something like this


local function onattack(inst, attacker, target)
	if not target or not target.components.health or target.poison_CD then return end
	if target.poison_task ~= nil then
		target.poison_task:Cancel()
	end
	target.poison_task = target:DoPeriodicTask(poison_interval, function(target)
		-- By having the "false" in the DoDelta, it will enable the sound of your
		-- health falling whenever a poison tick happens, may be useful if a player
		-- gets poisoned, but if you dont want the sound then switch it to "true"
		target.components.health:DoDelta(-poison_tick, false, "poison")
	end, poison_interval) -- you only need the poison_interval here if you want the windup

	if target.poisoncure_task ~= nil then
		target.poisoncure_task:Cancel()
	end
	target.poisoncure_task = target:DoTaskInTime(poison_length, function(target)
		target.poison_task:Cancel()
		target.poison_task = nil
		target.poisoncure_task = nil
	end)

	target.poison_CD = target:DoTaskInTime(COOLDOWN_TIME_HERE, function(target) target.poison_CD = nil end)
end


The nice thing about storing it on the target is that way even if they get attacked by another source of poison, the cooldown will still be in effect. If you want the cooldown to be tracked via the weapon instead, just replace target with inst with everything to do with the poison_CD variable
 

is there any way for particles to come out or to change the hue of the enemy when poison is inflicted?

This is unfortunately where my expertise ends, I'm not really too familiar with the art side of things much at all haha

I know you can use SpawnPrefab(prefab) to spawn in FX particles, tho I wouldn't know as far as which ones would work best for it. You can also use target.AnimeState:SetMultColour(r, g, b, a) or target.AnimeState:SetAddColour (r, g, b, a) to modulate color on the target, but I'm not 100% certain on how to reverse it lol my guess would be either setting the r,g,b values to all 0 or all 1 as they're additive/multiplicative, but you're going to have to experiment with it on your own.

Edited by w00tyd00d
  • Like 1
11 minutes ago, w00tyd00d said:

This is unfortunately where my expertise ends, I'm not really too familiar with the art side of things much at all haha

I know you can use SpawnPrefab(prefab) to spawn in FX particles, tho I wouldn't know as far as which ones would work best for it. You can also use target.AnimeState:SetMultColour(r, g, b, a) or target.AnimeState:SetAddColour (r, g, b, a) to modulate color on the target, but I'm not 100% certain on how to reverse it lol my guess would be either setting the r,g,b values to all 0 or all 1 as they're additive/multiplicative, but you're going to have to experiment with it on your own.

no worries I got the particles but how do i add another gui display for the cooldown? like the health but instead it shows a cooldown timer?

4 minutes ago, GreenDevil said:

but how do i add another gui display for the cooldown? like the health but instead it shows a cooldown timer?

Well I've never actually added a widget myself, but that's where you'll find your answer. First you'll need to adjust how the poison_CD variable works because there's no (easy) way of seeing how much time is left. If you want to keep track of the remaining seconds, I'd rename your current inst.poison_CD to inst.poison_CD_task and then add another variable called something like inst.poison_CD_time and track it like this

local function onattack(inst, attacker, target)
	if not target or not target.components.health or target.poison_CD_task then return end
	if target.poison_task ~= nil then
		target.poison_task:Cancel()
	end
	target.poison_task = target:DoPeriodicTask(poison_interval, function(target)
		-- By having the "false" in the DoDelta, it will enable the sound of your
		-- health falling whenever a poison tick happens, may be useful if a player
		-- gets poisoned, but if you dont want the sound then switch it to "true"
		target.components.health:DoDelta(-poison_tick, false, "poison")
	end, poison_interval) -- you only need the poison_interval here if you want the windup

	if target.poisoncure_task ~= nil then
		target.poisoncure_task:Cancel()
	end
	target.poisoncure_task = target:DoTaskInTime(poison_length, function(target)
		target.poison_task:Cancel()
		target.poison_task = nil
		target.poisoncure_task = nil
	end)

	target.poison_CD_time = YOUR_COOLDOWN_LENGTH
	target.poison_CD_task = target:DoPeriodicTask(1, function(target)
		target.poison_CD_time = target.poison_CD_time - 1
		if target.poison_CD_time == 0 then
			target.poison_CD_task:Cancel()
			target.poison_CD_task = nil
		end
	end)
end

Then your target will be able to read their own information to be able to able to reference it for the widget. Godspeed soldier o7

  • Like 1

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
×
  • Create New...