geeq Posted April 24, 2022 Share Posted April 24, 2022 Heya, so I'm making a modded mob for my mod here, which is basically a grass gekko, but doesnt run away and is neutral towards the player. I successfully removed the scared mechanic whenever the player gets near it, but I'm having trouble making the grass gekko clone hostile when hit! My mob's brain: Spoiler require "behaviours/wander" require "behaviours/faceentity" require "behaviours/panic" require "behaviours/runaway" require "behaviours/leash" require "behaviours/chaseandattack" require "behaviours/attackwall" local BrainCommon = require("brains/braincommon") local MIN_FOLLOW_DIST = 0 local MAX_FOLLOW_DIST = 25 local TARGET_FOLLOW_DIST = 6 local MAX_WANDER_DIST = 8 local LEASH_RETURN_DIST = 15 local LEASH_MAX_DIST = 30 local MAX_CHASE_TIME = 4 local MAX_CHASE_DIST = 15 local RUN_AWAY_DIST = 6 local STOP_RUN_AWAY_DIST = 10 local AVOID_PLAYER_DIST = 7 local AVOID_PLAYER_STOP = 12 local AVOID_DIST = 7 local AVOID_STOP = 12 local NO_TAGS = {"FX", "NOCLICK", "DECOR","INLIMBO", "stump", "burnt"} local function GetWanderDistFn(inst) return MAX_WANDER_DIST end local RockroachBrain = Class(Brain, function(self, inst) Brain._ctor(self, inst) end) function RockroachBrain:OnStart() local root = PriorityNode( { WhileNode(function() return self.inst.components.health.takingfiredamage end, "OnFire", Panic(self.inst)), IfNode(function() return self.inst.components.combat.target ~= nil end, "hastarget", AttackWall(self.inst)), ChaseAndAttack(self.inst, MAX_CHASE_TIME), WhileNode( function() return self.inst.components.health.takingfiredamage end, "OnFire", Panic(self.inst)), --RunAway(self.inst, "scarytoprey", AVOID_PLAYER_DIST, AVOID_PLAYER_STOP , function() return true end ), --RunAway(self.inst, "player", AVOID_DIST, AVOID_STOP, nil, nil, NO_TAGS), --Wander(self.inst, function() return self.inst:GetPosition() end, MAX_WANDER_DIST), Wander(self.inst, function() return self.inst.components.knownlocations:GetLocation("herd") end, GetWanderDistFn) }, .25) self.bt = BT(self.inst, root) end return RockroachBrain Stagegraph: Spoiler require("stategraphs/commonstates") local actionhandlers = { ActionHandler(ACTIONS.GOHOME, "gohome"), } local events = { CommonHandlers.OnSleep(), CommonHandlers.OnFreeze(), CommonHandlers.OnAttacked(), CommonHandlers.OnDeath(), CommonHandlers.OnLocomote(false,true), EventHandler("attacked", function(inst) if not inst.components.health:IsDead() then inst.sg:GoToState("hit") end end), EventHandler("doattack", function(inst) if not (inst.sg:HasStateTag("busy") or inst.components.health:IsDead()) then inst.sg:GoToState("attack") end end), EventHandler("locomote", function(inst) if not inst.sg:HasStateTag("idle") and not inst.sg:HasStateTag("moving") then return end local is_moving = inst.sg:HasStateTag("moving") local is_running = inst.sg:HasStateTag("running") local is_idling = inst.sg:HasStateTag("idle") local should_move = inst.components.locomotor:WantsToMoveForward() local should_run = inst.components.locomotor:WantsToRun() if not should_move then if not inst.sg:HasStateTag("idle") then if not inst.sg:HasStateTag("running") then inst.sg:GoToState("idle") elseif is_moving then inst.sg:GoToState(is_running and "run_stop" or "walk_stop") else inst.sg:GoToState("idle") end end elseif should_run then if not inst.sg:HasStateTag("running") then inst.sg:GoToState("scare") end else if not inst.sg:HasStateTag("moving") then inst.sg:GoToState("walk_start") end end end), } local states= { State{ name = "idle", tags = {"idle", "canrotate"}, onenter = function(inst) inst.components.locomotor:StopMoving() if inst.tailGrowthPending then inst.sg:GoToState("regrow_tail") else inst.AnimState:PlayAnimation("idle_loop") end end, events = { EventHandler("animover", function(inst) inst.sg:GoToState("idle") end), }, }, State{ name = "walk_start", tags = {"moving", "canrotate"}, onenter = function(inst) inst.AnimState:PlayAnimation("walk_pre") end, events = { EventHandler("animover", function(inst) inst.sg:GoToState("walk") end ), }, }, State{ name = "walk", tags = {"moving", "canrotate"}, onenter = function(inst) inst.components.locomotor:WalkForward() inst.AnimState:PlayAnimation("walk_loop") end, events = { EventHandler("animover", function(inst) inst.sg:GoToState("walk") end ), }, timeline= { TimeEvent(FRAMES, function(inst) PlayFootstep(inst) end), TimeEvent(8*FRAMES, function(inst) PlayFootstep(inst) end), TimeEvent(15*FRAMES, function(inst) PlayFootstep(inst) end), TimeEvent(23*FRAMES, function(inst) PlayFootstep(inst) end), }, }, State{ name = "walk_stop", tags = {"canrotate"}, onenter = function(inst) inst.components.locomotor:StopMoving() inst.AnimState:PlayAnimation("walk_pst") end, events = { EventHandler("animover", function(inst) inst.sg:GoToState("idle") end ), }, }, State{ name = "run_start", tags = {"moving", "canrotate"}, onenter = function(inst) inst.AnimState:PlayAnimation("walk_pre") end, events = { EventHandler("animover", function(inst) inst.sg:GoToState("run") end ), }, }, State{ name = "scare", tags = {"moving", "canrotate","running"}, onenter = function(inst) inst.components.locomotor:StopMoving() inst.AnimState:PlayAnimation("tail_off") end, events= { EventHandler("animover", function(inst) inst.sg:GoToState("run") end ), }, timeline= { TimeEvent(3*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/creatures/together/grass_gekko/tail_off") end), TimeEvent(4*FRAMES, function(inst) if inst.hasTail then inst.components.lootdropper:SpawnLootPrefab("cutgrass") inst.hasTail = false inst.components.timer:StartTimer("growTail", TUNING.GRASSGEKKO_REGROW_TIME ) end end), TimeEvent(15*FRAMES, function(inst) inst.sg:GoToState("run") end), }, onexit = function(inst) if not inst.hasTail then inst.AnimState:Hide("tail") end end, }, State{ name = "run", tags = {"moving", "canrotate","running"}, onenter = function(inst) inst.components.locomotor:RunForward() inst.AnimState:PlayAnimation("run_loop") end, events= { EventHandler("animover", function(inst) inst.sg:GoToState("run") end ), }, timeline= { TimeEvent(FRAMES, function(inst) PlayFootstep(inst) end), TimeEvent(8*FRAMES, function(inst) PlayFootstep(inst) end), TimeEvent(15*FRAMES, function(inst) PlayFootstep(inst) end), TimeEvent(23*FRAMES, function(inst) PlayFootstep(inst) end), }, }, State{ name = "run_stop", tags = {"canrotate"}, onenter = function(inst) inst.components.locomotor:StopMoving() inst.AnimState:PlayAnimation("run_pst") end, events= { EventHandler("animover", function(inst) inst.sg:GoToState("idle") end ), }, }, State{ name = "regrow_tail", tags = {"busy"}, onenter = function(inst) inst.AnimState:PlayAnimation("tail_regrow") inst.tailGrowthPending = nil inst.AnimState:Show("tail") inst.hasTail = true end, events= { EventHandler("animover", function(inst) inst.sg:GoToState("idle") end ), }, timeline= { TimeEvent(5*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/creatures/together/grass_gekko/tail_regrow") end), }, }, State{ name = "attack", tags = { "attack" }, onenter = function(inst, cb) inst.Physics:Stop() inst.components.combat:StartAttack() inst.AnimState:PlayAnimation("idle_loop") end, timeline = { TimeEvent(10 * FRAMES, function(inst) inst.SoundEmitter:PlaySound(inst.sounds.attack) end), TimeEvent(15 * FRAMES, function(inst) inst.components.combat:DoAttack() end), }, events = { EventHandler("animover", function(inst) inst.sg:GoToState("idle") end), }, }, State{ name = "hit", tags = { "busy" }, onenter = function(inst) inst.SoundEmitter:PlaySound(inst.sounds.hit) inst.AnimState:PlayAnimation("hit") inst.Physics:Stop() end, events = { EventHandler("animover", function(inst) inst.sg:GoToState("idle") end), }, }, State{ name = "emerge", tags = { "busy" }, onenter = function(inst) inst.components.locomotor:StopMoving() local player = inst:GetNearestPlayer() if player ~= nil and inst:IsNear(player, 7) then inst:FaceAwayFromPoint(player:GetPosition(), true) else inst.Transform:SetRotation(math.random(360)) end inst.AnimState:PlayAnimation("gecko_pop") end, timeline = { TimeEvent(12 * FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/wilson/pickup_reeds") end), TimeEvent(32 * FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/creatures/together/grass_gekko/emerge") end), }, events = { EventHandler("animover", function(inst) if inst.AnimState:AnimDone() then inst.sg:GoToState("idle") end end), }, }, } --inst.components.locomotor:WantsToRun() CommonStates.AddCombatStates(states, { hittimeline = { TimeEvent(5*FRAMES, function(inst) inst.sg:GoToState("run") end), }, deathtimeline = { TimeEvent(3*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/creatures/together/grass_gekko/death") end), TimeEvent(9*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/creatures/together/grass_gekko/body_fall") end), }, }) CommonStates.AddSleepStates(states, { starttimeline = { TimeEvent(15*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/creatures/together/grass_gekko/sleep_pre") end) }, sleeptimeline = { TimeEvent(15*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/creatures/together/grass_gekko/sleep") end), TimeEvent(28*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve/creatures/together/grass_gekko/sleep") end) }, waketimeline = { TimeEvent(1*FRAMES, function(inst) if inst.components.locomotor:WantsToRun() then inst.sg:GoToState("scare") end end), TimeEvent(12*FRAMES, function(inst) inst.sg:GoToState("idle") end), }, }) CommonStates.AddFrozenStates(states) return StateGraph("rockroach", states, events, "idle", actionhandlers) Link to comment Share on other sites More sharing options...
geeq Posted May 17, 2022 Author Share Posted May 17, 2022 Progress report: The mob is neutral and all, but with a slight problem; The mob becomes invisible and stops moving whenever it comes in contact with me. I'm able to hit it whilst in this state, but when it tries to come back for round 2, it does the same thing again! Link to comment Share on other sites More sharing options...
Ziro2k Posted May 20, 2022 Share Posted May 20, 2022 (edited) Generally, the invisibility happens when you try to play an animation that an entity doesn't have. In this case, it seems that it is happening when it tries to attack. Looking at your code, your attack state uses the idle animation which shouldn't cause any problems, but then near the bottom you call CommonStates.AddCombatStates(). When you do this, it replaces the attack state you defined with the common attack state, which plays the "atk" animation. Your mob doesn't have this animation, which is why it turns invisible. Edited May 20, 2022 by Ziro2k Link to comment Share on other sites More sharing options...
geeq Posted May 21, 2022 Author Share Posted May 21, 2022 Thanks for replying, Ziro! After I removed CommonStates.AddCombatStates() & doing some fine-tuning, the mob doesn't turn invisible, and functions normally. But now, whenever I host a world with caves enabled just to double check, my mob crashes the world when it's attacked. Link to comment Share on other sites More sharing options...
Ziro2k Posted May 21, 2022 Share Posted May 21, 2022 Well I have a few possible guesses but there's really know way of knowing for sure without looking at the server log. What does the error message and LUA stack traceback say? I can help you debug if you post it. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now