RadiantRoma Posted March 5, 2017 Share Posted March 5, 2017 (edited) For a custom character I am making, I want to be able to sneak around enemies or be able to get closer to a mob without it knowing I'm there. For example, I could get closer to a rabbit before it notices me and runs back to its home, or I can get closer to a bird before it flies off. I'm aware of the "scarytoprey" and "notarget" tags, but they basically remove detection altogether. Any help would be greatly appreciated! Edited March 10, 2017 by Romanful Link to comment Share on other sites More sharing options...
RadiantRoma Posted March 7, 2017 Author Share Posted March 7, 2017 Update, I had the idea to look in tuning.lua and found some lines that might be helpful. Each mob has a "(mob)_TARGET_DIST = (#)" line. If if could figure out how to insert this into my mod and modify the values, I might have figured out what I was looking for. Update, Started looking in brain files, and found what I'm certain I'm looking for; local STOP_RUN_DIST = 10 local SEE_PLAYER_DIST = 5 local AVOID_PLAYER_DIST = 3 local AVOID_PLAYER_STOP = 6 is what I found in rabbitbrains.lua local SEE_THREAT_DIST = 5 local function ShouldFlyAway(inst) return not (inst.sg:HasStateTag("sleeping") or inst.sg:HasStateTag("busy") or inst.sg:HasStateTag("flight")) and (TheWorld.state.isnight or (inst.components.health ~= nil and inst.components.health.takingfiredamage and not (inst.components.burnable and inst.components.burnable:IsBurning())) or FindEntity(inst, SEE_THREAT_DIST, nil, nil, { "notarget", "INLIMBO" }, { "player", "monster", "scarytoprey" }) ~= nil) end was found in birdbrains.lua. So I'm sure if I change these variables in modmain.lua, it would work correctly. The only thing is, I'm not adept with coding right now, so I'm not exactly sure how to do it exactly. I only wish for passive animals that run away when the player gets close not to run away until half the default player distance. So the player can get closer to rabbits before they run, closer to butterflies, etc. Any help would be greatly appreciated. Link to comment Share on other sites More sharing options...
. . . Posted March 7, 2017 Share Posted March 7, 2017 Just wanted to say I really hope someone can help you with thiss because I want to do something similar but have no idea how xD... Link to comment Share on other sites More sharing options...
PanAzej Posted March 7, 2017 Share Posted March 7, 2017 (edited) I'm no expert on editing already existing brains, but... You have to edit the brain - replace the function that determines the distance with your custom one. Download a mod that edits these things (for example The Tallbird Mod) and look how the author did it. The best way to do things would be to check entity tag (so you know if it's your character or not). Use old function for other characters and a new function for your custom character. Edited March 7, 2017 by PanAzej Link to comment Share on other sites More sharing options...
RadiantRoma Posted March 8, 2017 Author Share Posted March 8, 2017 3 hours ago, PanAzej said: I'm no expert on editing already existing brains, but... You have to edit the brain - replace the function that determines the distance with your custom one. Download a mod that edits these things (for example The Tallbird Mod) and look how the author did it. The best way to do things would be to check entity tag (so you know if it's your character or not). Use old function for other characters and a new function for your custom character. Alright well I learned from that mod is that it can all be done from modmain.lua! maybe that was really obvious already. I looked through the tallbird mod's modmain and the only references I could find were towards the end: local function DumpBT(bnode, indent) local s = "" for i=1,indent do s = s.."| " end s = s..bnode.name print(s) if bnode.children then for i,childnode in ipairs(bnode.children) do DumpBT(childnode, indent+1) end end end AddBrainPostInit("smallbirdbrain", function(brain) --print("\n\n\t\t\t\tDumping a smallbirdbrain") --DumpBT(brain.bt.root, 0) --print("\n\n") --[[ local function CustomFollow(inst, oldfn) print("Confirmed CustomFollow run from main code that edits RunAway") return oldfn(inst) end --]] local function CustomRunAway(inst, target, oldfn) --print("Confirmed CustomRunAway run from main code that edits RunAway") if target and target:HasTag("player") then if not inst.components.follower.leader then inst.components.trader:SetAcceptTest(ShouldAcceptItem) inst.components.trader.onaccept = OnGetItemFromPlayer inst.components.trader.onrefuse = OnRefuseItem inst.components.follower:SetLeader(target) --target.components.leader:AddFollower(inst) --inst:AddComponent("named") --inst.components.named.possiblenames = STRINGS.PIGNAMES --inst.components.named:PickNewName() end --print("returning false - do not run away..") return false -- Do not run away. else --print("returning original function") return oldfn(inst,target) -- Return the old function to handle it end end local index = nil local index2 = nil for i,v in ipairs(brain.bt.root.children) do if v.name == "RunAway" then index = i break end end for i,v in ipairs(brain.bt.root.children[3].children[2].children[2].children) do if v.name == "Follow" then index2 = i break end end if not index then --print("RunAway Not Found!") return end --print("RunAway Found!") local old_shouldrunfn = brain.bt.root.children[index].shouldrunfn brain.bt.root.children[index].shouldrunfn = function(target) return CustomRunAway(brain.inst, target, old_shouldrunfn) end if not index2 then --print("Follow Not Found!") return end local old_shouldrunfn2 = brain.bt.root.children[3].children[2].children[2].children[index2].shouldrunfn end) I feel like the answer to it all is really simple, like in the end it will only be 3 lines of code. Well, until we can figure it out! Link to comment Share on other sites More sharing options...
RadiantRoma Posted March 8, 2017 Author Share Posted March 8, 2017 4 hours ago, SuperDavid said: Just wanted to say I really hope someone can help you with thiss because I want to do something similar but have no idea how xD... I hope someone figures it out too. Otherwise I'll probably just do the "remove scarytoprey" thing. I feel like that would be too easy and underwhelming though. Link to comment Share on other sites More sharing options...
realitymeltdown Posted March 8, 2017 Share Posted March 8, 2017 I think the variables you want are local variables in the brain file. There's no global context that you can change them in to easily switch between on and off. Also, the action definitions are also loaded once when the brain is created, so to change them in the middle of a creature's lifecycle isn't really something you can do either. In theory you could go to the brain logic on the instance, access the brain, pull out the priority nodes, grab the specific actions you want to alter, and then change their inner variables to change the sight distance. I think that might be fragile, and may not work as new actions are created. Someone else may know a way to do it, but from what I know, it's not a matter of changing one variable. Sorry Link to comment Share on other sites More sharing options...
PanAzej Posted March 8, 2017 Share Posted March 8, 2017 3 hours ago, Romanful said: I feel like the answer to it all is really simple, like in the end it will only be 3 lines of code. Well, until we can figure it out! It's not this easy, really. You can't change local variables and editing tuning variables would change them for all players. You can see how this person did it: They used AddBrainPostInit function, in which they created a custom behaviour function, then they checked the original brain and from there they executed their custom function, while also sending the old function in a variable. It's probably the best, most bug-free way of doing it. Link to comment Share on other sites More sharing options...
CarlZalph Posted March 8, 2017 Share Posted March 8, 2017 Unfortunately for this method I came up with it's not very mod-friendly due to Klei using a local variable to determine aggro ranges. I have provided a base template for assisting with adding in different prefabs, but there's also the SpringCombatMod and other nuances for different prefabs not being taken into consideration that will need to be done for a perfect aggro range modifier. local AGGRO_MULTIPLIER = 0.5 local AGGRO_EDITED_SQ = {} AGGRO_EDITED_SQ.spider = GLOBAL.TUNING.SPIDER_TARGET_DIST AGGRO_EDITED_SQ.bat = GLOBAL.TUNING.BAT_TARGET_DIST AGGRO_EDITED_SQ.lightninggoat = GLOBAL.TUNING.LIGHTNING_GOAT_TARGET_DIST AGGRO_MULTIPLIER = AGGRO_MULTIPLIER*AGGRO_MULTIPLIER for k,v in pairs(AGGRO_EDITED_SQ) do AGGRO_EDITED_SQ[k] = AGGRO_MULTIPLIER*v*v end AddClassPostConstruct( "components/combat_replica", function(self) local CanTarget_old = self.CanTarget self.CanTarget = function(self, target, ...) if target and target:IsValid() and target:HasTag("player") then local radcheck = AGGRO_EDITED_SQ[self.inst.prefab] if radcheck and (GLOBAL.distsq(target:GetPosition(), self.inst:GetPosition()) > radcheck) then return false end end return CanTarget_old(self, target, ...) end end ) I didn't put a global aggro range cap because some prefabs may act very odd when having their ranges edited. Link to comment Share on other sites More sharing options...
. . . Posted March 8, 2017 Share Posted March 8, 2017 (edited) Welp, CarlZalph put code before me xD, but I'll post my code I came up with anyways ! Here it is @Romanful inst:DoPeriodicTask(0.1, function() local CAN_ATTACK = { CHOP = false, DIG = false, HAMMER = false, MINE = false, ATTACK = true, } local ATTACK_TAGS = {"_combat"} for k, v in pairs(CAN_ATTACK) do table.insert(ATTACK_TAGS, k.."_workable") end local NON_ATTACK_TAGS = {"INLIMBO", "playerghost"} local x, y, z = inst.Transform:GetWorldPosition() local ents = TheSim:FindEntities(x, y, z, 2, nil, NON_ATTACK_TAGS, ATTACK_TAGS) for i, v in ipairs(ents) do if not v:HasTag("player") and not v:HasTag("shadow") and not v:HasTag("shadowminion") and not v:HasTag("shadowchesspiece") and v.components.health and not v.components.health:IsDead() and inst.components.health and not inst.components.health:IsDead() then -- No hiding from nightmare creatures, mwuhahaha! inst:RemoveTag("notarget") inst:AddTag("scarytoprey") else inst:AddTag("notarget") inst:RemoveTag("scarytoprey") end end end) You'd put this inside your character's master_postinit & change the number 2 to whatever you want your detection range to be, pretty simple & straight forward, I think ! I dunno if my code would effect performance since it's being called every .1 seconds...though my performance was the same with or without this code, so it probably doesn't effect performance ! Edited March 8, 2017 by SuperDavid Link to comment Share on other sites More sharing options...
RadiantRoma Posted March 8, 2017 Author Share Posted March 8, 2017 (edited) Thank you @SuperDavid and @CarlZalph for your codes, I'll test them out when I get home! I do understand David's code more than Carl's (aka i don't understand Carl's at all, but that doesn't mean it won't work). David, would this work for all creatures (spiders, rabbits, birds, gobblers, grass geckos, etc)? But thanks again for putting in the effort of writing it! Edited March 8, 2017 by Romanful Link to comment Share on other sites More sharing options...
. . . Posted March 8, 2017 Share Posted March 8, 2017 5 hours ago, Romanful said: David, would this work for all creatures (spiders, rabbits, birds, gobblers, grass geckos, etc)? But thanks again for putting in the effort of writing it! It works for all entities except Nighmares, if you want it to work for them too then get rid of and not v:HasTag("shadow") and not v:HasTag("shadowminion") and not v:HasTag("shadowchesspiece") from for i, v in ipairs(ents) do if not v:HasTag("player") and not v:HasTag("shadow") and not v:HasTag("shadowminion") and not v:HasTag("shadowchesspiece") and v.components.health and not v.components.health:IsDead() and inst.components.health and not inst.components.health:IsDead() then -- No hiding from nightmare creatures, mwuhahaha! inst:RemoveTag("notarget") inst:AddTag("scarytoprey") else inst:AddTag("notarget") inst:RemoveTag("scarytoprey") end end Link to comment Share on other sites More sharing options...
TheAsianInfluence Posted March 9, 2017 Share Posted March 9, 2017 I was having the same problem for just about the exact same thing! I want to try some of these out when I get a chance 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