Jump to content

Recommended Posts

So for my character mod I though I would add a laser gun, a ranged weapon that would spawn a projectile. Would modifying the code for the ice staff be a viable option to create my weapon and how exactly would I go about doing that? As far as I know the ice staff coding is in the prefabs staff.lua, staff_projectile.lua, and shatter.lua excluding the anim files.

  • Like 1

Well... you both don't need to anyhow modify existing code, what you need to do is to open your weapons prefab files and simply paste some code and play with parameters. For simply firing staff-like projectiles that does not deal fire effect nor ice effect you could use something like that:
 

local assets = {
    Asset("ANIM", "anim/custom_staffs.zip"),
    Asset("ANIM", "anim/custom_staffs_swap.zip"),
}

local prefabs = {
    "fire_projectile",
}

local function onattack_magic(inst, attacker, target, skipsanity)
    if not skipsanity and attacker ~= nil then
        if attacker.components.sanity ~= nil then
            attacker.components.sanity:DoDelta(-TUNING.SANITY_SUPERTINY)
        end
    end

    attacker.SoundEmitter:PlaySound("dontstarve/wilson/fireball_explo")

    if not target:IsValid() then
        return
    end

    -- Wake up sleeping creatures
    if target.components.sleeper ~= nil and target.components.sleeper:IsAsleep() then
        target.components.sleeper:WakeUp()
    end

    -- Make target aggressive towards attacker
    if target.components.combat ~= nil then
        target.components.combat:SuggestTarget(attacker)
    end

    target:PushEvent("attacked", { attacker = attacker, damage = 0, weapon = inst })
end

local function magicstaff()
    local inst = CreateEntity()

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

    MakeInventoryPhysics(inst)

    inst.AnimState:SetBank("custom_staffs")
    inst.AnimState:SetBuild("custom_staffs")
    inst.AnimState:PlayAnimation("magicstaff")

    inst:AddTag("magicstaff")
    inst:AddTag("weapon")
    inst:AddTag("rangedweapon")

    inst.projectiledelay = FRAMES

    if not TheWorld.ismastersim then
        return inst
    end

    inst:AddComponent("weapon")
    inst.components.weapon:SetDamage(0)
    inst.components.weapon:SetRange(8, 10)
    inst.components.weapon:SetOnAttack(onattack_magic)    
    inst.components.weapon:SetProjectile("fire_projectile")

    inst:AddComponent("finiteuses")
    inst.components.finiteuses:SetMaxUses(TUNING.FIRESTAFF_USES)
    inst.components.finiteuses:SetUses(TUNING.FIRESTAFF_USES)
    inst.components.finiteuses:SetOnFinished(function(inst) 
        inst.SoundEmitter:PlaySound("dontstarve/common/gem_shatter")
        inst:Remove()
    end)

    inst:AddComponent("inspectable")
    inst:AddComponent("inventoryitem")
    inst:AddComponent("equippable")

    inst.components.equippable:SetOnEquip(function(inst, owner)
        owner.AnimState:OverrideSymbol("swap_object", "custom_staffs_swap", "swap_magicstaff")
        owner.AnimState:Show("ARM_carry")
        owner.AnimState:Hide("ARM_normal")
    end)

    inst.components.equippable:SetOnUnequip(function(inst, owner)
        owner.AnimState:Hide("ARM_carry")
        owner.AnimState:Show("ARM_normal")
    end)

    return inst
end

For teleporting you shall use other code:
 

local function getrandomposition(caster)
    local centers = {}
    for i, node in ipairs(TheWorld.topology.nodes) do
        if TheWorld.Map:IsPassableAtPoint(node.x, 0, node.y) and node.type ~= NODE_TYPE.SeparatedRoom then
            table.insert(centers, {x = node.x, z = node.y})
        end
    end
    if #centers > 0 then
        local pos = centers[math.random(#centers)]
        return Point(pos.x, 0, pos.z)
    else
        return caster:GetPosition()
    end
end

local function teleport_start(teleportee, staff, caster)
    local ground = TheWorld
    local locpos = getrandomposition(caster)

    if teleportee.components.locomotor ~= nil then
        teleportee.components.locomotor:StopMoving()
    end

    staff.components.finiteuses:Use(1)

    if teleportee:HasTag("player") then
        teleportee.sg:GoToState("forcetele")
    end

    ground:PushEvent("ms_sendlightningstrike", teleportee:GetPosition())

    if caster ~= nil and caster.components.sanity ~= nil then
        caster.components.sanity:DoDelta(-TUNING.SANITY_HUGE)
    end

    if teleportee:HasTag("player") then
        teleportee:DoTaskInTime(1, function()
            if teleportee.Physics ~= nil then
                teleportee.Physics:Teleport(locpos.x, 0, locpos.z)
            else
                teleportee.Transform:SetPosition(locpos.x, 0, locpos.z)
            end
            teleportee:SnapCamera()
            teleportee.sg:GoToState("wakeup")
        end)
    end
end

local function teleportstaff()
    local inst = CreateEntity()

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

    MakeInventoryPhysics(inst)

    inst.AnimState:SetBank("custom_staffs")
    inst.AnimState:SetBuild("custom_staffs")
    inst.AnimState:PlayAnimation("teleportstaff")

    inst:AddTag("teleportstaff")
    inst:AddTag("nopunch")

    if not TheWorld.ismastersim then
        return inst
    end

    inst:AddComponent("spellcaster")
    inst.components.spellcaster:SetSpellFn(function(staff, target, pos, caster)
        teleport_start(caster, staff, caster)
    end)
    inst.components.spellcaster.canuseonself = true
    inst.components.spellcaster.canusefrominventory = true

    inst:AddComponent("finiteuses")
    inst.components.finiteuses:SetMaxUses(TUNING.TELESTAFF_USES)
    inst.components.finiteuses:SetUses(TUNING.TELESTAFF_USES)
    inst.components.finiteuses:SetOnFinished(function(inst) 
        inst.SoundEmitter:PlaySound("dontstarve/common/gem_shatter")
        inst:Remove()
    end)

    inst:AddComponent("inspectable")
    inst:AddComponent("inventoryitem")
    inst:AddComponent("equippable")

    inst.components.equippable:SetOnEquip(function(inst, owner)
        owner.AnimState:OverrideSymbol("swap_object", "custom_staffs_swap", "swap_teleportstaff")
        owner.AnimState:Show("ARM_carry")
        owner.AnimState:Hide("ARM_normal")
    end)

    inst.components.equippable:SetOnUnequip(function(inst, owner)
        owner.AnimState:Hide("ARM_carry")
        owner.AnimState:Show("ARM_normal")
    end)

    return inst
end

Don't forget to return it with

return Prefab("magicstaff", magicstaff, assets, prefabs),
       Prefab("teleportstaff", teleportstaff, assets)

If you want to do something based on what already done in code, you just need to read the files and use methods in it, it's really easy. For example in laser-like staff I made it so it uses fire projectiles but not really dealing any fire damage. If you're doing laser you could make spawning projectiles red with MultColour. You can make it deal some damage, I made it deal only 0 but you could change it. It's all about reading the code if something simillar already exist.

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