Jump to content

Modding custom weapon help


Recommended Posts

I'm making a dart that causes insanity in mobs. I've got it to work for passive creatures, who run around in a panic and then die after some time, but for neutral and hostile mobs I want them to freak out and start attacking their own kind. I'm kind of stumped on this part. I'm not looking for step-to-step instructions but some pointers would be appreciated.

 

Problems:

 

- The non-passive mobs shouldn't die at the end, instead the insanity effect should wear off after a while. I think I should use DoPeriodicTask() for this?

 

-Need to stop the insane mob from targeting the player (unless the player hits them) and tell them what to target instead. I can already see that the existing code's not working because it only executes once.

 

-The insane mob should run around panicked until they find a target to attack. Do I need a new behaviour, or can I just add the panic behaviour to their brain?

 

- Is there a better way to determine if the target is a passive mob? I've found that even rabbits and birds have the combat component. Right now I'm checking their tags but not all of them are tagged clearly.

 

I'm basing most of it off the blowdart code. Relevant bits below:

--determines whether the mob hit by the dart can fightlocal function canCombat(target)    if target:HasTag("hostile") then        return true    end    if target:HasTag("character") then        return true    end      return false    endlocal function findTarget(attacker)    --borrowed this from the merm code    --local victim = FindEntity(???) --how can i find the attacker's same species?    return victimendlocal function attack(inst, attacker, target)    if target.components.locomotor then        target.SoundEmitter:PlaySound("dontstarve/wilson/blowdart_impact_sleep")                if target.components.sleeper and target.components.sleeper:IsAsleep() then            target.components.sleeper:WakeUp()        end                if canCombat(target) then            --this is where I attempt to make the mob attack nearby other mobs            local newtarget = findTarget(target)            target.components.combat:SuggestTarget(newtarget)                    elseif target:HasTag("bird") then            target.sg:GoToState("distress_pre")            target:DoTaskInTime(10+math.random()*5, function() target.components.health:Kill() end)                    else            local behaviours = target.brain.bt.root.children            table.insert(behaviours, 1, Panic(target))            target:DoTaskInTime(10+math.random()*5, function() target.components.health:Kill() end)        end                --part of the blowdart code, I don't know if anything changed when I comment it out.        --if target.sg and target.sg.sg.states.hit then        --    target.sg:GoToState("hit")        --end    endend
Link to comment
Share on other sites

Whew, making mobs attack the nearest target sounds tough.

Maybe you could try something like "inst.components.combat:SetTarget(TheSim:FindNearestEntityWithTag("whatevertag"))

(That's not 'exactly' what the actual code would look like, I'm just making it up from what I can remember. But it could look something like that) also I'm not even sure if that would work.

You shouldn't need to make a new behavior, the existing panic should work. I can show you how to add behaviors to creatures brains priority nodes. Been there, done that.

I'll have to look it up later though, becaus I remember it being pretty complicated

Link to comment
Share on other sites

Don't use 'DoPeriodicTask' or 'DoTaskInTime', they aren't persistent. You'll need to have a component with a variable that counts down and stops the effect when it runs out, and saves the value across sessions.

 

You could just have a list of what mobs are considered passive, and check that each time (Or use 'AddPrefabPostInitAny' to add a tag when they are first created, so you only have to check the list once per prefab).

 

I'm pretty sure the 'combat' component is also about taking damage, not just dealing it.

Link to comment
Share on other sites

How do event listeners work? I don't quite understand this bit of code in the spider prefab:

 

local function OnAttacked(inst, data)    inst.components.combat:SetTarget(data.attacker)    inst.components.combat:ShareTarget(data.attacker, 30, function(dude)        return dude:HasTag("spider")               and not dude.components.health:IsDead()               and dude.components.follower               and dude.components.follower.leader == inst.components.follower.leader    end, 10)end
    inst:ListenForEvent("attacked", OnAttacked)

What is the "data" parameter? What's being passed into the function?

Link to comment
Share on other sites

Well I've just started learning all this recentlyand it's pretty complicated. But a simple way to use event listeners is to add that line of code, in this case "inst:ListenForEvent("attacked", OnAttacked)" and then somewhere else (probably in combat.lua)  you can activate the event with "inst:PushEvent("attacked")"  which will cause the spider's "OnAttacked" function to run.

 

Link to comment
Share on other sites

Yeah, I figured it out, the PushEvent was in combat.lua:

function Combat:GetAttacked(attacker, damage, weapon)    --blah blah    self.inst:PushEvent("attacked", {attacker = attacker, damage = damage, weapon = weapon})    --blah blahend

This is great since I can call a function whenever I want instead of just relying on the component's function handles.

 

Anyways, I made a new "panic" component. It doesn't do much right now, just stops the target's brain, but it properly wears off after a set time, so hooray. Although I don't know how to make it persist across sessions yet.

 

I'm thinking that if I'm going to inject some new complicated behaviour into the brain, I need to "reset" their brain when the effect runs out, right? Is the unmodified brain saved somewhere?

Link to comment
Share on other sites

Yeah, I figured it out, the PushEvent was in combat.lua:

function Combat:GetAttacked(attacker, damage, weapon)    --blah blah    self.inst:PushEvent("attacked", {attacker = attacker, damage = damage, weapon = weapon})    --blah blahend
This is great since I can call a function whenever I want instead of just relying on the component's function handles.

Anyways, I made a new "panic" component. It doesn't do much right now, just stops the target's brain, but it properly wears off after a set time, so hooray. Although I don't know how to make it persist across sessions yet.

I'm thinking that if I'm going to inject some new complicated behaviour into the brain, I need to "reset" their brain when the effect runs out, right? Is the unmodified brain saved somewhere?

Yep. And nah, the brain just resets itself to how it normally is.

You can check out some of my code in the mod "Kaji" I do some brain things with behaviors, but with "runaway" instead of "panic" (in both his character prefab and the fearcore prefab)

Link to comment
Share on other sites

I've gotten the "attack anything in sight" part to work by calling combat:SetRetargetFunction() and replacing it with a new function. Their old retarget function is saved in a variable, which gets put back when the effect ends (although they tend to die hilariously before that happens because they attacked their neighbour).

 

The only thing left to do is to add the panic behaviour. The problem is that they'll stop running around to eat food off the ground... I know that behaviours are prioritized in the brain, but I can't figure how you specify the priority of new behaviours. Obviously panic should come before eating food, but after combat.

Link to comment
Share on other sites

here try this:

table.insert(v.brain.bt.root.children, math.min(1, #behaviours), Panic(v))  

I'm actually pretty sure that will work.

I THINK behavior prioritization is defined by than number after math.min (I had a problem with spiders falling asleep when running away. I never actually fixed that bug and instead disabled spiders ability to fall asleep while running)

But maybe try changing that 1 to a 0. That might make it actual top priority

Link to comment
Share on other sites

I've tried changing that number. 1 works fine for most mobs, but spiders prefer eating and sleeping, at 0 it's broken and they don't panic at all. I think I might be inserting the panic behaviour into their brains multiple times when I shoot them with more than one dart... I'll have to fix that.

 

It looks like the brains use a tree to prioritize behaviours, so it's more complex than just a list of priorities from top to bottom, unfortunately I'm not good with trees...

 

But whatever, moving onto the next thing for now. I want to check if a creature has noticed the player. I can check combat.target for hostile creatures, but for ones that run away from the player like rabbits and pigs, I can't find any relevant variables that tell me who they're running away from. So how can I check if something's running away from me?

Link to comment
Share on other sites

I find it usefull to stop the creatures brain immediately after inserting the behavior. (they can't make any decisions while their brain is stopped)

 

The Panic behavior doesn't have a "target" to run away from. They just run in completely random directions.

The RunAway behavior does though. in RunAway.lua its "hunterparams". Not sure if that will really help you, but yea.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

Please be aware that the content of this thread may be outdated and no longer applicable.

×
  • Create New...