Jump to content

Recommended Posts

Hi! So as the title says, i'm looking to add some sort of Fx effect to my character when attacking enimes below half sanity. I've been trying to learn LUA, right now I have a basic understanding of what functions are, varibles and syntax. I was thinking it would use the same effect as obelisks use when the skitts shadow moves out of it. I do plan on releaseing my character on the workshop, he already has a damage mutiplier that scales with sanity so this would mostly be a cool thing to add!

Any help on how to go about doing this would be really awesome!

 image.png.3751e67d4ec201f75694709f54662225.png

I took a look through Wanda's prefab file to see how it's done there, I think I found where the game spawns the FX but I want it to be pretty different. I know what functions are, but in the context of dst I don't really know what i'm looking at. any help would be really appreciated!

Here's what I think does it;

local function ShadowWeaponFx(inst, target, damage, stimuli, weapon, damageresolved)
    if weapon ~= nil and target ~= nil and target:IsValid() and weapon:IsValid() and weapon:HasTag("shadow_item") then
        local fx_prefab = inst.age_state == "old" and (weapon:HasTag("pocketwatch") and "wanda_attack_pocketwatch_old_fx" or "wanda_attack_shadowweapon_old_fx")
                or inst.age_state == "normal" and (weapon:HasTag("pocketwatch") and "wanda_attack_pocketwatch_normal_fx" or "wanda_attack_shadowweapon_normal_fx")
                or nil
 
        if fx_prefab ~= nil then
            local fx = SpawnPrefab(fx_prefab)
 
            local x, y, z = target.Transform:GetWorldPosition()
            local radius = target:GetPhysicsRadius(.5)
            local angle = (inst.Transform:GetRotation() - 90) * DEGREES
            fx.Transform:SetPosition(x + math.sin(angle) * radius, 0, z + math.cos(angle) * radius)
        end
    end
end

Okay! So I took a crack at makeing the fx effect from Wanda onto my character, I wrote my own function which should be spawning the FX effect when sanity is below a certain point AND Wramp has a wepon.

Problem is, the FX won't spawn in, but the game isn't crashing which is unusal for me. Here's the function I wrote;

inst:ListenForEvent "sanitydelta", function(inst, data)
 
    if inst.components.sanity.current >= 100 then
 
        if weapon ~= nil and target ~= nil and target:IsValid() and weapon:IsValid()    then
            local fx_prefab = "wanda_attack_shadowweapon_normal_fx"
                    or nil
   
            if fx_prefab ~= nil then
                local fx = SpawnPrefab(fx_prefab)
   
                local x, y, z = target.Transform:GetWorldPosition()
                local radius = target:GetPhysicsRadius(.5)
                local angle = (inst.Transform:GetRotation() - 90) * DEGREES
                fx.Transform:SetPosition(x + math.sin(angle) * radius, 0, z + math.cos(angle) * radius)
 
    elseif inst.components.sanity.current <= 50 then
 
        if weapon ~= nil and target ~= nil and target:IsValid() and weapon:IsValid()    then
            local fx_prefab = "wanda_attack_shadowweapon_old_fx"
                    or nil
   
            if fx_prefab ~= nil then
                local fx = SpawnPrefab(fx_prefab)
   
                local x, y, z = target.Transform:GetWorldPosition()
                local radius = target:GetPhysicsRadius(.5)
                local angle = (inst.Transform:GetRotation() - 90) * DEGREES
                fx.Transform:SetPosition(x + math.sin(angle) * radius, 0, z + math.cos(angle) * radius)
 
    end
end

I do plan on useing the skitts FX that obelisks use, the Wanda effect is just to test!

I found a problem, I added the component that calls for the function to run on hit. But for whatever reason I cannot get the function to run all all. Which would explain why there's no crashing. I changed the name of the function to match but somehow the function won't run. I added a print statement to test and it's definitely not runing, Does anyone know how to fix this?

    inst.components.combat.onhitotherfn = WrampShadowWeaponFx
4 hours ago, Doodle Monster said:

I found a problem, I added the component that calls for the function to run on hit. But for whatever reason I cannot get the function to run all all. Which would explain why there's no crashing. I changed the name of the function to match but somehow the function won't run. I added a print statement to test and it's definitely not runing, Does anyone know how to fix this?

    inst.components.combat.onhitotherfn = WrampShadowWeaponFx

What does the "WrampShadowWeaponFx" function currently look like? And where do you have the "inst.components.combat.onhitotherfn" located in your file?

Okay so here's the function;

inst:ListenForEvent "sanitydelta", function WrampShadowWeaponFx(inst, data)
 
    if inst.components.sanity.current <= 100 then
 
        if weapon ~= nil and target ~= nil and target:IsValid() and weapon:IsValid()    then
            local fx_prefab = "wanda_attack_shadowweapon_normal_fx" and print("NORMAL FX")
                    or nil
   
            if fx_prefab ~= nil then
                local fx = SpawnPrefab(fx_prefab)
   
                local x, y, z = target.Transform:GetWorldPosition()
                local radius = target:GetPhysicsRadius(.5)
                local angle = (inst.Transform:GetRotation() - 90) * DEGREES
                fx.Transform:SetPosition(x + math.sin(angle) * radius, 0, z + math.cos(angle) * radius)
 
    elseif inst.components.sanity.current <= 50 then
 
        if weapon ~= nil and target ~= nil and target:IsValid() and weapon:IsValid()    then
            local fx_prefab = "wanda_attack_shadowweapon_old_fx" and print("BIG FX")
                    or nil
   
            if fx_prefab ~= nil then
                local fx = SpawnPrefab(fx_prefab)
   
                local x, y, z = target.Transform:GetWorldPosition()
                local radius = target:GetPhysicsRadius(.5)
                local angle = (inst.Transform:GetRotation() - 90) * DEGREES
                fx.Transform:SetPosition(x + math.sin(angle) * radius, 0, z + math.cos(angle) * radius)
 
    end
end

Sorry! I posted my reply and then was kinda busy all yesterday.

22 hours ago, Doodle Monster said:

Okay so here's the function;

inst:ListenForEvent "sanitydelta", function WrampShadowWeaponFx(inst, data)
 
    if inst.components.sanity.current <= 100 then
 
        if weapon ~= nil and target ~= nil and target:IsValid() and weapon:IsValid()    then
            local fx_prefab = "wanda_attack_shadowweapon_normal_fx" and print("NORMAL FX")
                    or nil
   
            if fx_prefab ~= nil then
                local fx = SpawnPrefab(fx_prefab)
   
                local x, y, z = target.Transform:GetWorldPosition()
                local radius = target:GetPhysicsRadius(.5)
                local angle = (inst.Transform:GetRotation() - 90) * DEGREES
                fx.Transform:SetPosition(x + math.sin(angle) * radius, 0, z + math.cos(angle) * radius)
 
    elseif inst.components.sanity.current <= 50 then
 
        if weapon ~= nil and target ~= nil and target:IsValid() and weapon:IsValid()    then
            local fx_prefab = "wanda_attack_shadowweapon_old_fx" and print("BIG FX")
                    or nil
   
            if fx_prefab ~= nil then
                local fx = SpawnPrefab(fx_prefab)
   
                local x, y, z = target.Transform:GetWorldPosition()
                local radius = target:GetPhysicsRadius(.5)
                local angle = (inst.Transform:GetRotation() - 90) * DEGREES
                fx.Transform:SetPosition(x + math.sin(angle) * radius, 0, z + math.cos(angle) * radius)
 
    end
end

As for this, the 'inst.components.combat.onhitotherfn =' doesn't actually know what 'WrampShadowWeaponFx' is, since in this instance its not a function local to the prefab.

If you want both the listenforevent and onhitotherfn to use this same function, you'll want to separate it out from the listenforevent and make it local.

-- outside master_postinit
local function WrampShadowWeaponFx(inst, data)
  -- The rest of the function here
end

-- then in master_postinit
inst:ListenForEvent("sanitydelta," WrampShadowWeaponFx)

though keep in mind that you'll run into a problem like this where the parameters being passed from the sanitydelta event and the onhitother function are going to be different. the sanitydelta event gives a bunch of parameters in a list (data) which can all be called like 'data.weapon' and the onhitother function passes the parameters "attacker, self.inst, damage, stimuli, weapon, damageresolved, spdamage, damageredirecttarget" in that order, which means that when WrampShadowWeaponFx is called for onhitother, 'data' in your function is actually just the entity you're attacking (the self.inst parameter that was passed to it).

However, given your original post, I don't believe what you're trying to accomplish actually requires the ListenForEvent at all? You are checking for your current sanity whenever the function is called regardless, so you don't really need to know when your sanity is changed at any other point in time. You can probably just remove that entirely and instead do this for the WrampShadowWeaponFx function:

local function WrampShadowWeaponFx(inst, target, damage, stimuli, weapon)
  -- rest of function
end

 

Okay, So I no longer need the "inst.components.combat.onhitotherfn = WrampShadowWeaponFx"?

And I don't need to check when sanity is changed all the time, only when the function runs. How would I do that? (I've mostly just looked at take apart the function that wanda has, I'm not really sure how to go about writeing my own.

Thanks for the help!

9 minutes ago, Doodle Monster said:

Okay, So I no longer need the "inst.components.combat.onhitotherfn = WrampShadowWeaponFx"?

And I don't need to check when sanity is changed all the time, only when the function runs. How would I do that? (I've mostly just looked at take apart the function that wanda has, I'm not really sure how to go about writeing my own.

Thanks for the help!

You would want to keep the inst.components.combat.onhitotherfn part, just need to replace to put the WrampShadowWeaponFx function outside master_postinit somewhere with the word 'local in front like I posted at the end of my last reply.

the if statements you added in the function should be sufficient for telling if your sanity is at a certain point whenever you attack something, though I'd change them to be more like this:

if inst.components.sanity:GetPercent() >= .5 then
  -- Code
else
  -- Other code
end

Using "GetPercent" is better than just checking sanity directly, both because its just better to use a component's getter function than grabbing the variable directly, and because GetPercent will give you a percentage rather than using the actual current sanity, meaning you won't have to come back and change this code if you ever change the max sanity of your character. Its .5 because GetPercent returns a decimal between 0 and 1.

Just now, Doodle Monster said:

I actualy don't know what componets to use, I've never written my own function before just taken things from other characters

You're on the right track, using the combat component to call your own function onhitother is good, and using the sanity component to check sanity is obviously also good. There's just a lot of depth to each component that you'd have to figure out from looking at their individual code really.

2 minutes ago, Doodle Monster said:

I put the inst:ListenForEvent("sanitydelta," WrampShadowWeaponFx) under the master and not the common correct?

That's correct, but honestly I'd just leave it out cause its not really doing anything for you. The ListenForEvent would call the function whenever your sanity changes, which isn't really necessary unless you wanted something to happen specifically when your sanity changes and no other factor involved. Checking sanity in the function itself is enough.

7 minutes ago, Doodle Monster said:

Should I put my prefab file? 

Yeah the full file could help

8 minutes ago, Doodle Monster said:

Hmm, I'm not sure what's going on but nothing is happening. Do you think it's the specific Fx i'm testing with?

You can kinda test by making something else happen, either with print("test") and then looking in the server txt log or doing inst.components.health:DoDelta(-5) which will noticeably cause damage whenever u hit something. I can open my game in a bit and toy around with it to see.

I took a look in my server log and wasn't able to find anything, I put two print statements in the function and neither appear. Hopefully you can see the problem

Edited by Doodle Monster

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