Jump to content

Creature Mod Tutorials


Recommended Posts

Hello! I was looking around the interwebs for info on how to get a good creature mod tutorial to mod a creature into DST. There is supposed to be a tutorial made by Klei themselves, but does anyone know if it still works. Its several years old and hasn't been updated since 2013. If it doesn't, could someone please send me a working tutorial on the basics of mob creation for dst?

Link to comment
Share on other sites

I've hit another roadblock. @-t- you're the only one who has seemed to help me with my problems before. The mob I'm working on is supposed to drop materials for a new hat. I can't figure out how to make it equipable to the headslot even after finding a headslot item (seriously I had to download one they make it so hard to find).

Link to comment
Share on other sites

Assuming you already have the sprites for your item...

To make something equippable you need to add the equippable component to it, like this:

inst:AddComponent("equippable") -- Adding the component
inst.components.equippable.equipslot = GLOBAL.EQUIPSLOTS.HEAD -- Setting the right equip slot for the item

2 functions are also needed for the item to work properly:

local function onEquip(owner)
	owner.AnimState:OverrideSymbol("swap_body", "your_swap_item_name", "swap_body") -- Change player body sprite to show that your item is equipped
end

local function onUnequip(owner)
	owner.AnimState:ClearOverrideSymbol("swap_body") -- Clear the body sprite back to its base look
end

inst.components.equippable:SetOnEquip(onEquip) -- Setup the function
inst.components.equippable:SetOnUnequip(onUnequip) -- Setup the function

You might also want to add an inventoryitem component:

inst:AddComponent("inventoryitem")
inst.components.inventoryitem.imagename = "tex_file_name"
inst.components.inventoryitem.atlasname = "images/atlas_file_name"

 

If you have all of this and there still is a problem post it here. If it crashes the game post the client log and the server log, that almost always points to what's wrong.

  • Thanks 1
Link to comment
Share on other sites

On 4/8/2022 at 8:26 AM, -t- said:

Assuming you already have the sprites for your item...

To make something equippable you need to add the equippable component to it, like this:


inst:AddComponent("equippable") -- Adding the component
inst.components.equippable.equipslot = GLOBAL.EQUIPSLOTS.HEAD -- Setting the right equip slot for the item

2 functions are also needed for the item to work properly:


local function onEquip(owner)
	owner.AnimState:OverrideSymbol("swap_body", "your_swap_item_name", "swap_body") -- Change player body sprite to show that your item is equipped
end

local function onUnequip(owner)
	owner.AnimState:ClearOverrideSymbol("swap_body") -- Clear the body sprite back to its base look
end

inst.components.equippable:SetOnEquip(onEquip) -- Setup the function
inst.components.equippable:SetOnUnequip(onUnequip) -- Setup the function

You might also want to add an inventoryitem component:


inst:AddComponent("inventoryitem")
inst.components.inventoryitem.imagename = "tex_file_name"
inst.components.inventoryitem.atlasname = "images/atlas_file_name"

 

If you have all of this and there still is a problem post it here. If it crashes the game post the client log and the server log, that almost always points to what's wrong.

Thank you for this code! I'm sure this will help me a ton! I kinda shelved my mod for a bit as I got busy (distracted) with something (*cough cough* mhw *cough cough*). With this new piece of data I might be able to get my mod to a proper working prototype, if I can keep my focus on it.

  • Like 1
Link to comment
Share on other sites

hello again! I know its been awhile, but I'm getting to the brain part of the mob code. Some behaviors, like 'behaviors/avoidlight' and 'behaviors/attackwall' are self explanatory, but others, like 'behaviors/useshield' and 'behaviors/doaction' are less easy to understand their function.

I was wondering if there is anywhere I can find a list of these behaviors and what they do, as I personally do not want to have to script a custom behavior for my mob.

I'd just like to once again say thanks for helping me out with all this stuff, and I hope to potentially have a working prototype eventually.

Link to comment
Share on other sites

I doubt there is a complete list of fully documented behaviours.

If that helps the UseShield behaviour makes a mob hide when sufficient damage has been dealt. It is used in brains of:

  1. Cave spiders
  2. Rock Lobsters
  3. Slurtles and Snurtles
  4. Celestial Champion (first phase)

 

DoAction is a bit more flexible. It allows the mob to do practically any action that exists in the GLOBAL.ACTIONS table. The getactionfn needs to return a BufferedAction.

The simplest DoAction can look something like this:

DoAction(self.inst, GoHomeAction),

With the GoHomeAction looking like this:

local function GoHomeAction(inst)
    local spawnpoint_position = inst.components.knownlocations:GetLocation("spawnpoint") -- Get the spawn point from knownlocations component
  
    if spawnpoint_position == nil or inst:GetDistanceSqToPoint(spawnpoint_position:Get()) < TUNING.ALTERGUARDIAN_PHASE3_GOHOMEDSQ then -- If spawnpoint doesn't exist or the mob is already near it return nil (no action)
        return nil
    else
        return BufferedAction(inst, nil, ACTIONS.WALKTO, nil, spawnpoint_position) -- If spawn point exists and the mob is far away then return a BufferedAction
    end
end

This example was pulled from alterguardian_phase3brain.lua (Celestial Champion phase 3)

 

If you want to see exactly how BufferedAction looks it's in bufferedaction.lua

  • Thanks 1
Link to comment
Share on other sites

Thanks for the info!
 

While I didn't really need help with the UseShield behavior specifically, I do think the DoAction behavior is necessary in my mob (Even if it isn't required, I'll still probably need it for something).

 

I think It'd be good to elaborate on what I'm trying to implement.

I'm actually making two mobs, although the distinction between them is small. One of them is meant to be a pack leader of sorts, with the other mob serving as the pack leader's goons.

The basic goon as you could say would have about 200 health, making them a bit more of a nuisance than the normal spider, and the pack leader would have around 1000. Just to refresh on health values, the regular pack member would have double the health of a spider, and the pack leader would have half the health of a small treeguard.

Both mobs would possess a leap attack in addition to a basic melee, not unlike warrior spiders, and the pack leader would posses an ability to rally the rest of the pack, not unlike bee queen.

The only thing I am unsure of is the spawning mechanic. I want them to naturally spawn in the world, but I'm not sure how.

I'm wondering what behaviors I would need to accomplish this. I just felt I needed to clarify what it was I was trying to accomplish, as there is no definitive list, I figured you might know enough to tell me what behaviors I could use to make my job a lot easier.

Link to comment
Share on other sites

Checking the spider brain and the spider queen brain should give you the answers you need. About the spawning tho, generally mobs should have a set condition or a spawner to spawn. For example Deerclops spawns at the end of winter (condition), ocean fish spawn from fish spawners (spawner). If you want your mob to randomly spawn in the world somewhere near the player you could check how the Suspicious Dirt Piles spawn. They're bound to players hunter component. It handles random spawning of dirt piles, it might help you with that.

  • Thanks 1
Link to comment
Share on other sites

14 hours ago, -t- said:

Checking the spider brain and the spider queen brain should give you the answers you need. About the spawning tho, generally mobs should have a set condition or a spawner to spawn. For example Deerclops spawns at the end of winter (condition), ocean fish spawn from fish spawners (spawner). If you want your mob to randomly spawn in the world somewhere near the player you could check how the Suspicious Dirt Piles spawn. They're bound to players hunter component. It handles random spawning of dirt piles, it might help you with that.

Neat! When I was originally typing out my reply, while I also didn't know how to cause my mob to spawn naturally, I was really talking about how I was unsure how I actually wanted it to spawn. I was unsure if I wanted to tie it to the suspicious dirt piles, some spawner in a certain biome, or something else. I think I'm going to go with the suspicious dirt piles, setting it up kinda like the clay varg. Even if I don't use it (yet) all of this information will be helpful. I'll comment again if I run into any more roadblocks.

Link to comment
Share on other sites

Look @-t-, I apologize if it feels as if I'm wasting your time. I understand what I need to get my creature mod up and running, but I'm running into problems.

I'm trying to get a simple template creature up and running using that creature tutorial you posted. I got to a point, but I can't spawn my creature whatsoever. I basically replicated your code, aside from replacing any instances of custommob and CUSTOMMOB with my creature name in respective caps or no caps. The game only crashed once, and that was from an error when entering inspection dialogue for it. I feel this would be the last time I would need to ask for help, at least for a long while. Again, I hope I'm not wasting your time with all the questions, I would really be appreciative.

Link to comment
Share on other sites

Oh, I guess I should've mentioned it in the tutorial. Well, the PrefabFiles table contains the names of your prefab files. That way the game can run these specific files and create prefabs from them.

In modmain.lua you should add:

PrefabFiles = {
	"name_of_your_prefabs_file",
}

Whenever you create a prefab file it needs to be added to this list.

Link to comment
Share on other sites

After some messing around and figuring out what a PrefabFiles table was. I came to this error upon startup.

 

[string "../mods/workshop-2811951071/scripts/prefabs/mymob.lua"]:25: '<name>' expected near '('

Nvm, I'm stupid

Link to comment
Share on other sites

Now it's a problem with the locomotor. It attempts to call a nil value.

@-t- (I @ed you because I think we live in different time zones and I think it allows you to respond quicker). I think I can check for a nil value, but how do I do that, and if it is nil, what do I do?

Link to comment
Share on other sites

Spider Warriors jump attack is in SGspider.lua. Instead of adding a new action to the brain, spider warriors use normal attack node and simply use a different state to attack.

EventHandler("doattack", function(inst, data)
        if not (inst.sg:HasStateTag("busy") or inst.components.health:IsDead()) then
            if inst:HasTag("spider_warrior") then -- Here it checks whether the spider has the 'spider_warrior' tag
                inst.sg:GoToState(
                    data.target:IsValid()
                    and not inst:IsNear(data.target, TUNING.SPIDER_WARRIOR_MELEE_RANGE)
                    and "warrior_attack" -- If yes it goes to the 'warrior_attack' state
                    or "attack",
                    data.target
                )

 

warrior_attack state:

State{
    name = "warrior_attack",
    tags = {"attack", "canrotate", "busy", "jumping"},

    onenter = function(inst, target)
        inst.components.locomotor:Stop()
        inst.components.locomotor:EnableGroundSpeedMultiplier(false)

        inst.components.combat:StartAttack()
        inst.AnimState:PlayAnimation("warrior_atk")
        inst.sg.statemem.target = target
    end,

    onexit = function(inst)
        inst.components.locomotor:Stop()
        inst.components.locomotor:EnableGroundSpeedMultiplier(true)
        inst.Physics:ClearMotorVelOverride()
    end,

    timeline =
    {
        TimeEvent(0*FRAMES, function(inst) inst.SoundEmitter:PlaySound(SoundPath(inst, "attack_grunt")) end),
        TimeEvent(0*FRAMES, function(inst) inst.SoundEmitter:PlaySound(SoundPath(inst, "Jump")) end),
        TimeEvent(8*FRAMES, function(inst) inst.Physics:SetMotorVelOverride(20,0,0) end),
        TimeEvent(9*FRAMES, function(inst) inst.SoundEmitter:PlaySound(SoundPath(inst, "Attack")) end),
        TimeEvent(19*FRAMES, function(inst) inst.components.combat:DoAttack(inst.sg.statemem.target) end),
        TimeEvent(20*FRAMES,
            function(inst)
                inst.Physics:ClearMotorVelOverride()
                inst.components.locomotor:Stop()
            end),
    },

    events=
    {
        EventHandler("animover", function(inst) inst.sg:GoToState("taunt") end),
    },
},

 

  • Thanks 1
Link to comment
Share on other sites

This may be me not understanding some of the code, but I do not understand the ShouldWake and their complementary function ShouldSleep. ShouldWake is sometimes called ShouldWakeUp in some prefabs. I found this out while looking at the koalephant code trying to make sense of the function. I understand what this function does in game, it causes the mob to wake up or go to sleep respectively. What I don't understand is the trigger. I'm only looking at prefabs right now, but in the spider prefab, the shouldwake function looks like this:

local function ShouldWake(inst)
    return not TheWorld.state.iscaveday
        or BasicWakeCheck(inst)
        or (inst:HasTag("spider_warrior") and
            FindTarget(inst, TUNING.SPIDER_WARRIOR_WAKE_RADIUS) ~= nil)
end

and the koalephant shouldwakeup looks like this:

local function ShouldWakeUp(inst)
    local x, y, z = inst.Transform:GetWorldPosition()
    return DefaultWakeTest(inst) or IsAnyPlayerInRange(x, y, z, WAKE_TO_RUN_DISTANCE)
end

The differences between the wake and the sleep functions are very minor, so I didn't put them here. I wanted to send these to someone who actually knows how to read this kind of code. I can understand some of it, but I'm not understanding all of it.

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