Jump to content

striking character with lightning when using item


Recommended Posts

I have minimal coding and modding knowledge, and I want to make an item for a modded character I am working on that is like an unlimited use pan flute, but where the character gets struck by lighting on use.

First of all, how do I find the code for the pan flute to copy?

The command TheWorld:PushEvent("ms_sendlightningstrike", ThePlayer:GetPosition()) appears to do the trick in the in game console, but I don't have the knowledge of if I could or how to incorporate that into the code.

Alternatively, is there a way to make it so the character just gets hurt and does the struck by lightning animation on use? That would almost be better.

Thanks!

Edited by bullbro
Link to comment
Share on other sites

@bullbro

All of the scripts are inside a zip file located at Steam/steamapps/common/Don't Starve Together/data/databundles/scripts.zip, I'd recommend extracting to a folder to peruse over.

Pushing the lightning strike event like that can have it go to other targets like a higher priority one such as the lightning rod.

All player prefabs get the playerlightningtarget component by default, which has the DoStrike function to call.

 

I notice you're using ThePlayer there which is fine for console commands but not so much for mods that have players.  You'd want to change that to use the player instance of whatever event/function you're wanting to hook into.

 

Effectively it would end up being something like:

inst.components.playerlightningtarget:DoStrike()

Where `inst` is your player instance that's to be zapped.

Do note that by default this function will not zap someone who is insulated, so you may need to write your own zapper function to make it do what you want in your use case.

  • Like 3
Link to comment
Share on other sites

13 minutes ago, CarlZalph said:

@bullbro

All of the scripts are inside a zip file located at Steam/steamapps/common/Don't Starve Together/data/databundles/scripts.zip, I'd recommend extracting to a folder to peruse over.

Pushing the lightning strike event like that can have it go to other targets like a higher priority one such as the lightning rod.

All player prefabs get the playerlightningtarget component by default, which has the DoStrike function to call.

 

I notice you're using ThePlayer there which is fine for console commands but not so much for mods that have players.  You'd want to change that to use the player instance of whatever event/function you're wanting to hook into.

 

Effectively it would end up being something like:


inst.components.playerlightningtarget:DoStrike()

Where `inst` is your player instance that's to be zapped.

Do note that by default this function will not zap someone who is insulated, so you may need to write your own zapper function to make it do what you want in your use case.

Ok this seems to help quite a bit. I probably will just avoid the lightning strike part all together because of the insulation you mentioned. Do you know how I would just damage and/or electrocute the player then?

Link to comment
Share on other sites

1 hour ago, TerriFried said:

@CarlZalph

Thank you for the help! May I ask whet the code would be  to just damage the player?

I assume it is an "inst." code, but I have not been able to find it.

Thank you in advance!

The playerlightningtarget component almost does what you want, here it is edited to ignore the insulation:

local ForceStrikeOn = function(inst)
    if inst.components.health and not (inst.components.health:IsDead() or inst.components.health:IsInvincible())
    then
        local x, y, z = inst.Transform:GetWorldPosition()
        SpawnPrefab("lightning").Transform:SetPosition(x, y, z)
        local mult = TUNING.ELECTRIC_WET_DAMAGE_MULT * (inst.components.moisture and inst.components.moisture:GetMoisturePercent() or 0)
        local damage = TUNING.LIGHTNING_DAMAGE + mult * TUNING.LIGHTNING_DAMAGE
        inst.components.health:DoDelta(-damage, false, "lightning")
        if not inst.sg:HasStateTag("dead")
        then
            inst.sg:GoToState("electrocute")
        end
    end
end

The spawn prefab bit you could have found in the weather component where lightning is controlled.

I've modified the mult variable to take into account characters that may not have the moisture component.

  • Like 2
Link to comment
Share on other sites

@CarlZalph thank you for the speedy replies! Just a couple more questions:

Where do I place your code, and how can I put a set damage? I assume I would just be able to replace the TUNING.LIGHTNING_DAMAGE with a number?

Second, how can I get the .scml file for the pan flute, is there something in Dont Starve Mod Tools that can do that? I figured out a solution here, however it does not give me an option to edit the animation, and I can't find the panflute player_[whatever]

However I found the player_actions_cowbell.scml which appears to be an even better animation for what I want to do, but doing inst:AddTag("bell") uses the old bell animation (for some reason) even though the .lua for the cowbell uses the same inst??? I dont know how to code it to appear in my players hand! I've been trying to figure this out all day, and need some help!

 

Thanks again!

 

Edited by TerriFried
Help me!
Link to comment
Share on other sites

@CarlZalph Every attempt to incorporate the code into the local function HearPanFlute(inst, musician, instrument) section has either resulted in the server not running, or the server crashing when I attempt to play the pan flute. Like I said, I have minimal coding knowledge, but do you know how and where I would put the code you so generously gave me? Happy Holidays btw!

local assets =
{
    Asset("ANIM", "anim/sigjam.zip"),

    Asset("ATLAS", "images/inventoryimages/sigjam.xml"),
    Asset("IMAGE", "images/inventoryimages/sigjam.tex"),
}

local function HearPanFlute(inst, musician, instrument)
    if inst ~= musician and
        (TheNet:GetPVPEnabled() or not inst:HasTag("player")) and
        not (inst.components.freezable ~= nil and inst.components.freezable:IsFrozen()) and
        not (inst.components.pinnable ~= nil and inst.components.pinnable:IsStuck()) and
        not (inst.components.fossilizable ~= nil and inst.components.fossilizable:IsFossilized()) then
        local mount = inst.components.rider ~= nil and inst.components.rider:GetMount() or nil
        if mount ~= nil then
            mount:PushEvent("ridersleep", { sleepiness = 10, sleeptime = TUNING.PANFLUTE_SLEEPTIME })
        end
        
        if inst ~= musician then
            local ForceStrikeOn = function(inst)
                if inst.components.health and not (inst.components.health:IsDead() or inst.components.health:IsInvincible())
                then
                local x, y, z = inst.Transform:GetWorldPosition()
                SpawnPrefab("lightning").Transform:SetPosition(x, y, z)
                local mult = TUNING.ELECTRIC_WET_DAMAGE_MULT * (inst.components.moisture and inst.components.moisture:GetMoisturePercent() or 0)
                local damage = TUNING.LIGHTNING_DAMAGE + mult * TUNING.LIGHTNING_DAMAGE
                inst.components.health:DoDelta(-damage, false, "lightning")
                if not inst.sg:HasStateTag("dead")
                then
                    inst.sg:GoToState("electrocute")
                end
            end
        end
        
        if inst.components.sleeper ~= nil then
            inst.components.sleeper:AddSleepiness(10, TUNING.PANFLUTE_SLEEPTIME)
        elseif inst.components.grogginess ~= nil then
            inst.components.grogginess:AddGrogginess(10, TUNING.PANFLUTE_SLEEPTIME)
        else
            inst:PushEvent("knockedout")
        end
    end
end

local function fn()
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddNetwork()

    MakeInventoryPhysics(inst)

    inst:AddTag("sigjam")

    inst.AnimState:SetBank("pan_flute")
    inst.AnimState:SetBuild("sigjam")
    inst.AnimState:PlayAnimation("idle")
    
    if not TheWorld.ismastersim then
        return inst
    end
    inst.entity:SetPristine()
    inst:AddComponent("inventoryitem")
    inst.components.inventoryitem.atlasname = "images/inventoryimages/sigjam.xml"
    
    inst.components.inventoryitem.cangoincontainer = true  
    inst.components.inventoryitem.onputininventoryfn = function(inst, player) 
    local owner = inst.components.inventoryitem:GetGrandOwner()
    if owner.components.inventory and owner.prefab ~= "absynth" then 
        inst:DoTaskInTime(0.1, function()
        
        player.components.inventory:DropItem(inst)
        player.components.talker:Say("I guess only holograms can use this?")
    end)
    end
    end

    --tool (from tool component) added to pristine state for optimization
    inst:AddTag("tool")

    MakeInventoryFloatable(inst, "small", 0.05, 0.8)
    inst.AnimState:AddOverrideBuild("sigjam")

    inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

    inst:AddComponent("inspectable")
    inst:AddComponent("instrument")
    inst.components.instrument.range = TUNING.PANFLUTE_SLEEPRANGE
    inst.components.instrument:SetOnHeardFn(HearPanFlute)

    inst:AddComponent("tool")
    inst.components.tool:SetAction(ACTIONS.PLAY)

    inst:AddComponent("inventoryitem")
    inst.components.inventoryitem.imagename = "sigjam"
    inst.components.inventoryitem.atlasname = "images/inventoryimages/sigjam.xml"
    

    MakeHauntableLaunch(inst)

    inst:ListenForEvent("floater_startfloating", function(inst) inst.AnimState:PlayAnimation("float") end)
    inst:ListenForEvent("floater_stopfloating", function(inst) inst.AnimState:PlayAnimation("idle") end)

    return inst
end

return Prefab("common/inventory/sigjam", fn, assets)

sigjam.lua

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