. . . Posted July 18, 2017 Share Posted July 18, 2017 Hello, if someone can help me with this that'd be great ! So, I'd like to know if there's a way I can disable the player from preforming any actions like attacking, picking up items, ect.. & all they can do is move around? Basically like how the player ghost acts? Is there someway to disable all player actions except locomoting? Thanks for reading my question, have a good day/night ! Link to comment Share on other sites More sharing options...
IronHunter Posted July 18, 2017 Share Posted July 18, 2017 The werebeaver code might be a good place too look. It overides actions and other default features and resets them when transforming back. It should mostly be in the woodie.lua file at least its a start. Link to comment Share on other sites More sharing options...
ZupaleX Posted July 18, 2017 Share Posted July 18, 2017 You need to override the playeractionpicker. Link to comment Share on other sites More sharing options...
. . . Posted July 19, 2017 Author Share Posted July 19, 2017 (edited) @IronHunter Thanks!! I looked through woodie.lua & now I know how disable actions with Spoiler local function Nothing(inst) end local function RemovePlayerActions(inst, enable) if enable then if inst.components.playercontroller ~= nil then inst.components.playercontroller.actionbuttonoverride = Nothing end if inst.components.playeractionpicker ~= nil then inst.components.playeractionpicker.leftclickoverride = Nothing inst.components.playeractionpicker.rightclickoverride = Nothing end else if inst.components.playercontroller ~= nil then inst.components.playercontroller.actionbuttonoverride = nil end if inst.components.playeractionpicker ~= nil then inst.components.playeractionpicker.leftclickoverride = nil inst.components.playeractionpicker.rightclickoverride = nil end end end Now the only problems left is my character can still force_attack & I looked through playercontroller.lua & woodie.lua & couldn't find out how to stop that from working .. I found these but they seem to have nothing to do with force_attack since he still would do force attack even when I disable them inst.components.playercontroller.controller_attack_override = nil inst.components.playercontroller.attack_buffer = nil inst.components.playercontroller.force_target = nil Also, does someone know if there's a code that checks if the character's picking or wants to pick up/harvest something? Then I can make my action not work if the player is trying to pickup an item since my character gets glitchy cause he tries to do both actions at the same time.. And thanks for your help !! Edited July 19, 2017 by SuperDavid Link to comment Share on other sites More sharing options...
ZupaleX Posted July 19, 2017 Share Posted July 19, 2017 For the force attack you might find what you want in playercontroller component. For the second point I am not sure I understand. Link to comment Share on other sites More sharing options...
. . . Posted July 19, 2017 Author Share Posted July 19, 2017 2 hours ago, ZupaleX said: For the force attack you might find what you want in playercontroller component. I already looked through there & couldn't find any attackoverride thing. 2 hours ago, ZupaleX said: For the second point I am not sure I understand. I want to know if there's some code like "inst:WantsToPickupItem()" then I can put a if check for my jump action to not happen if the character is trying to pickup or walking towards an item to pick it up. Link to comment Share on other sites More sharing options...
ZupaleX Posted July 19, 2017 Share Posted July 19, 2017 You prioritize your actions so it should not happens that both are executed at the same time. Where do you implement that new action and How? Link to comment Share on other sites More sharing options...
. . . Posted July 19, 2017 Author Share Posted July 19, 2017 (edited) Well it's not a real, real action..it's just a action that plays a state when you press a key since I don't know how to add real, real actions .. & it's in modmain.lua Spoiler local function jump(act) if act.target.gelid_mode == true or act.target.heavy_armor == true then return end if act.target.jump == nil and not act.target.sg:HasStateTag("busy") and not act.target.components.rider:IsRiding() then if act.target.components.locomotor:WantsToMoveForward() then act.target.sg:GoToState("run_jump") elseif not act.target.components.locomotor:WantsToMoveForward() and act.target:IsOnValidGround() then act.target.sg:GoToState("jump") end end end Edited July 19, 2017 by SuperDavid Link to comment Share on other sites More sharing options...
ZupaleX Posted July 20, 2017 Share Posted July 20, 2017 What do you do with this function? When is it called? Could you link your complete modmain.lua> Link to comment Share on other sites More sharing options...
ZupaleX Posted July 20, 2017 Share Posted July 20, 2017 (edited) The issue that you have is that you need to define your jump as an action so the game can actually prioritize them. You can find example on how to do that in various mods. Again, I am not advertising my mod, but you can see a working example in my "Archery Mod" on the workshop, which add several custom actions. You can find other mods doing it but I don't know them. It has not been updated in a while though so it is using a deprecated function to add ACTION but it is still working and the new way is almost exactly the same (save for one line). If you decide to take a look into the code and have questions let me know. If you would rather get help step by step to do it without an example, I guess we can work something out as well, it will just take more time probably. Edited July 20, 2017 by ZupaleX Link to comment Share on other sites More sharing options...
. . . Posted July 20, 2017 Author Share Posted July 20, 2017 (edited) Where can I find in your archery mod the place to add a action? Wow your mod is very big I don't know where to look xD!! Edited July 20, 2017 by SuperDavid Link to comment Share on other sites More sharing options...
ZupaleX Posted July 20, 2017 Share Posted July 20, 2017 in the modmain.lua, look for the word "action" (remove the case sensitivity to find all the occurences). It is also not really well organized, sorry. Link to comment Share on other sites More sharing options...
. . . Posted July 20, 2017 Author Share Posted July 20, 2017 (edited) Okay, so I do something like this.. is this correct way? I have no idea what I'm doing really xD... jump_action.priority = 10 local function jump(act) local JUMPACTION = ACTIONS.JUMP actions = act.target:SortActionList({JUMPACTION}) return actions end local jump_action = AddAction("JUMP", "Jump", function(act) if act.target.gelid_mode == true or act.target.heavy_armor == true then return end if act.target.jump == nil and not act.target.sg:HasStateTag("busy") and not act.target.components.rider:IsRiding() then if act.target.components.locomotor:WantsToMoveForward() then act.target.sg:GoToState("run_jump") elseif not act.target.components.locomotor:WantsToMoveForward() and act.target:IsOnValidGround() then act.target.sg:GoToState("jump") end end end) local JUMP = GLOBAL.Action() JUMP.str = "Jump" JUMP.id = "JUMP" JUMP.fn = function(act) jump(act) end AddAction(JUMP) Edited July 20, 2017 by SuperDavid Link to comment Share on other sites More sharing options...
ZupaleX Posted July 20, 2017 Share Posted July 20, 2017 Not quite, you need to define the action before adding it. Look at the items GLOBAL.Action(...) Link to comment Share on other sites More sharing options...
. . . Posted July 20, 2017 Author Share Posted July 20, 2017 1 minute ago, ZupaleX said: Not quite, you need to define the action before adding it. Look at the items GLOBAL.Action(...) I don't really know what that mean by this cause I'm dumb, sorry xD! From your modmain.lua I see this action local ARMCROSSBOW = GLOBAL.Action( 5, -- priority nil, -- instant (set to not instant) true, -- right mouse button nil, -- distance check nil, -- ghost valid (set to not ghost valid) nil, -- ghost exclusive nil, -- can force action nil) -- Range check function And you say my action need priority to not be able to preform other action while doing it, right? So, in my action I see it's similar to your archery action thing, so I put 10 priority which's more than yours but my character still can do other actions while in jump(act) ! local JUMP = GLOBAL.Action(10) JUMP.str = "Jump" JUMP.id = "JUMP" JUMP.fn = function(act) jump(act) end AddAction(JUMP) Did I do something wrong? And thanks for your help ! Link to comment Share on other sites More sharing options...
ZupaleX Posted July 20, 2017 Share Posted July 20, 2017 That's better. You now have an action and you say what to do when this action is performed. You now need to say WHEN you can perform it Link to comment Share on other sites More sharing options...
. . . Posted July 20, 2017 Author Share Posted July 20, 2017 2 minutes ago, ZupaleX said: You now need to say WHEN you can perform it How do I do this xD ? Link to comment Share on other sites More sharing options...
ZupaleX Posted July 20, 2017 Share Posted July 20, 2017 That's the tricky part Look at AddComponentAction Link to comment Share on other sites More sharing options...
. . . Posted July 20, 2017 Author Share Posted July 20, 2017 (edited) Okay, I found this in your archery modmain.lua AddComponentAction("USEITEM", "zupalexsrangedweapons", bow_attack_useitem) But I have no idea what to do with it? I'm guessing the first thing I put my JUMP action? local JUMP = GLOBAL.Action(10) JUMP.str = "Jump" JUMP.id = "JUMP" JUMP.fn = function(act) jump(act) end AddAction(JUMP) AddComponentAction("JUMP", "zupalexsrangedweapons", bow_attack_useitem) I don't know what the other 2 things mean though EDIT: Okay, I think the last one is the name of the function you're doing? So I would just put my "jump"(act) function, but I have no idea what the middle one is & thanks for your help man !! Edited July 20, 2017 by SuperDavid Link to comment Share on other sites More sharing options...
ZupaleX Posted July 20, 2017 Share Posted July 20, 2017 I will write an expanation about this function soon. Link to comment Share on other sites More sharing options...
ZupaleX Posted July 20, 2017 Share Posted July 20, 2017 So you have several types of predefined Component Actions: SCENE: clicking on something on the screen while not having any active item USEITEM: clicking on something else on the surounding area with an object "in hand" (active item, appearing under your cursor) POINT: same as USEITEM but clicking on anywhere on the screen (like when you use the blinkstaff) EQUIPPED: if the item is equipped INVENTORY: right clicking it in your inventory Each of these types apply in specific situations when you want to use an item. AddComponentAction takes several arguments. The first one is which type of action you want to deal with and must belong to the list above. Second argument is which component you want to attach this new action. Third is a function saying which specific action you want to have as a choice and under which circumstances. Try to read again that part in my modmain and see if it makes more sense. Now you want to be able to jump while you use a special item or it's just that your character is supposed to be able to jump by default? Link to comment Share on other sites More sharing options...
. . . Posted July 20, 2017 Author Share Posted July 20, 2017 I was hoping to make the character jump when I press spacebar since that's how it's like for most games. Which's also why it conflicts with picking up items so much xD.. Also, what if I don't have any component related to this jump action? Can I just put it "nil" or do I have to make a component? Link to comment Share on other sites More sharing options...
ZupaleX Posted July 20, 2017 Share Posted July 20, 2017 (edited) If it is not linked to a item but to the player locomotor and playeractionpicker component. It is not so trivial anymore but doable. @SuperDavid: so I looked a bit more into it because it's not something I've really done before (I worked with custom actions but always linked to an item). This will be in playeractionpicker.lua and playercontroller.lua You have in playeractionpicker.lua a function which is called each "tick" (each time the game refresh everything) to sort through the possible actions and pick the one which has the highest priority. Spoiler function PlayerActionPicker:GetLeftClickActions(position, target) if self.leftclickoverride ~= nil then local actions, usedefault = self.leftclickoverride(self.inst, target, position) if not usedefault or (actions ~= nil and #actions > 0) then return actions or {} end end local actions = nil local useitem = self.inst.replica.inventory:GetActiveItem() local equipitem = self.inst.replica.inventory:GetEquippedItem(EQUIPSLOTS.HANDS) local ispassable = self.map:IsPassableAtPoint(position:Get()) --if we're specifically using an item, see if we can use it on the target entity if useitem ~= nil then if useitem:IsValid() then if target == self.inst then actions = self:GetInventoryActions(useitem) elseif target ~= nil then actions = self:GetUseItemActions(target, useitem) elseif ispassable then actions = self:GetPointActions(position, useitem) end end elseif target ~= nil and target ~= self.inst then --if we're clicking on a scene entity, see if we can use our equipped object on it, or just use it if self.inst.components.playercontroller:IsControlPressed(CONTROL_FORCE_INSPECT) and target:HasTag("inspectable") and (self.inst.CanExamine == nil or self.inst:CanExamine()) and (self.inst.sg == nil or self.inst.sg:HasStateTag("moving") or self.inst.sg:HasStateTag("idle") or self.inst.sg:HasStateTag("channeling")) and (self.inst:HasTag("moving") or self.inst:HasTag("idle") or self.inst:HasTag("channeling")) then actions = self:SortActionList({ ACTIONS.LOOKAT }, target, nil) elseif self.inst.components.playercontroller:IsControlPressed(CONTROL_FORCE_ATTACK) and target.replica.combat ~= nil and self.inst.replica.combat:CanTarget(target) then actions = self:SortActionList({ ACTIONS.ATTACK }, target, nil) elseif equipitem ~= nil and equipitem:IsValid() then actions = self:GetEquippedItemActions(target, equipitem) end if actions == nil or #actions == 0 then actions = self:GetSceneActions(target) end end if actions == nil and target == nil and equipitem ~= nil and equipitem:IsValid() and ispassable then --can we use our equipped item at the point? actions = self:GetPointActions(position, equipitem) --this is to make it so you don't auto-drop equipped items when you left click the ground. kinda ugly. if actions ~= nil then for i, v in ipairs(actions) do if v.action == ACTIONS.DROP then table.remove(actions, i) break end end end end return actions or {} end You need to insert your action in the table which is sorted, and give it a priority which is high enough that it ends up being the first one. PICKUP action has priority 1 so anything above will be executed first. PICK doesn't have a priority specified so in this case it will be 0. (from actions.lua) Spoiler ACTIONS = { REPAIR = Action({ mount_valid=true, encumbered_valid=true }), READ = Action({ mount_valid=true }), DROP = Action({ priority=-1, mount_valid=true, encumbered_valid=true }), TRAVEL = Action(), CHOP = Action(), ATTACK = Action({ priority=2, canforce=true, mount_valid=true }), -- No custom range check, attack already handles that EAT = Action({ mount_valid=true }), PICK = Action({ canforce=true, rangecheckfn=DefaultRangeCheck }), PICKUP = Action({ priority=1 }), MINE = Action(), DIG = Action({ rmb=true }), GIVE = Action({ mount_valid=true, canforce=true, rangecheckfn=DefaultRangeCheck }), GIVETOPLAYER = Action({ priority=3, canforce=true, rangecheckfn=DefaultRangeCheck }), GIVEALLTOPLAYER = Action({ priority=3, canforce=true, rangecheckfn=DefaultRangeCheck }), FEEDPLAYER = Action({ priority=3, rmb=true, canforce=true, rangecheckfn=DefaultRangeCheck }), DECORATEVASE = Action(), COOK = Action({ priority=1, mount_valid=true }), FILL = Action(), DRY = Action(), ADDFUEL = Action({ mount_valid=true }), ADDWETFUEL = Action({ mount_valid=true }), LIGHT = Action({ priority=-4 }), EXTINGUISH = Action({ priority=0 }), LOOKAT = Action({ priority=-3, instant=true, ghost_valid=true, mount_valid=true, encumbered_valid=true }), TALKTO = Action({ priority=3, instant=true, mount_valid=true, encumbered_valid=true }), WALKTO = Action({ priority=-4, ghost_valid=true, mount_valid=true, encumbered_valid=true }), BAIT = Action(), CHECKTRAP = Action({ priority=2 }), BUILD = Action({ mount_valid=true }), PLANT = Action(), HARVEST = Action(), GOHOME = Action(), SLEEPIN = Action(), CHANGEIN = Action({ priority=-1 }), EQUIP = Action({ priority=0,instant=true, mount_valid=true, encumbered_valid=true }), UNEQUIP = Action({ priority=-2,instant=true, mount_valid=true, encumbered_valid=true }), --OPEN_SHOP = Action(), SHAVE = Action({ mount_valid=true }), STORE = Action(), RUMMAGE = Action({ priority=-1, mount_valid=true }), DEPLOY = Action({ distance=1.1 }), PLAY = Action({ mount_valid=true }), CREATE = Action(), JOIN = Action(), NET = Action({ priority=3, canforce=true, rangecheckfn=DefaultRangeCheck }), CATCH = Action({ priority=3, distance=math.huge, mount_valid=true }), FISH = Action(), REEL = Action({ instant=true }), POLLINATE = Action(), FERTILIZE = Action(), SMOTHER = Action({ priority=1 }), MANUALEXTINGUISH = Action({ priority=1 }), LAYEGG = Action(), HAMMER = Action({ priority=3 }), TERRAFORM = Action(), JUMPIN = Action({ ghost_valid=true, encumbered_valid=true }), TELEPORT = Action({ rmb=true, distance=2 }), RESETMINE = Action({ priority=3 }), ACTIVATE = Action(), MURDER = Action({ priority=0, mount_valid=true }), HEAL = Action({ mount_valid=true }), INVESTIGATE = Action(), UNLOCK = Action(), USEKLAUSSACKKEY = Action(), TEACH = Action({ mount_valid=true }), TURNON = Action({ priority=2 }), TURNOFF = Action({ priority=2 }), SEW = Action({ mount_valid=true }), STEAL = Action(), USEITEM = Action({ priority=1, instant=true }), TAKEITEM = Action(), MAKEBALLOON = Action({ mount_valid=true }), CASTSPELL = Action({ priority=-1, rmb=true, distance=20, mount_valid=true }), BLINK = Action({ priority=10, rmb=true, distance=36, mount_valid=true }), COMBINESTACK = Action({ mount_valid=true }), TOGGLE_DEPLOY_MODE = Action({ priority=1, instant=true }), SUMMONGUARDIAN = Action({ rmb=false, distance=5 }), HAUNT = Action({ rmb=false, mindistance=2, ghost_valid=true, ghost_exclusive=true, canforce=true, rangecheckfn=DefaultRangeCheck }), UNPIN = Action(), STEALMOLEBAIT = Action({ rmb=false, distance=.75 }), MAKEMOLEHILL = Action({ priority=4, rmb=false, distance=0 }), MOLEPEEK = Action({ rmb=false, distance=1 }), FEED = Action({ rmb=true, mount_valid=true }), UPGRADE = Action({ rmb=true }), HAIRBALL = Action({ rmb=false, distance=3 }), CATPLAYGROUND = Action({ rmb=false, distance=1 }), CATPLAYAIR = Action({ rmb=false, distance=2 }), FAN = Action({ rmb=true, mount_valid=true }), DRAW = Action(), BUNDLE = Action({ rmb=true, priority=2 }), BUNDLESTORE = Action({ instant=true }), WRAPBUNDLE = Action({ instant=true }), UNWRAP = Action({ rmb=true, priority=2 }), STARTCHANNELING = Action({ distance=2.1 }), STOPCHANNELING = Action({ instant=true, distance=2.1 }), TOSS = Action({ rmb=true, distance=8, mount_valid=true }), NUZZLE = Action(), WRITE = Action(), ATTUNE = Action(), REMOTERESURRECT = Action({ rmb=false, ghost_valid=true, ghost_exclusive=true }), MIGRATE = Action({ rmb=false, encumbered_valid = true, ghost_valid=true }), MOUNT = Action({ priority=1, rmb=true, encumbered_valid=true }), DISMOUNT = Action({ priority=1, instant=true, rmb=true, mount_valid=true, encumbered_valid=true }), SADDLE = Action({ priority=1 }), UNSADDLE = Action({ priority=3, rmb=false }), BRUSH = Action({ priority=3, rmb=false }), ABANDON = Action({ rmb=true }), PET = Action(), } Then you have in playercontroller.lua the function which is executed when you left click Spoiler function PlayerController:OnLeftClick(down) if not self:UsingMouse() then return elseif not down then self:OnLeftUp() return end self.startdragtime = nil if not self:IsEnabled() then return elseif TheInput:GetHUDEntityUnderMouse() ~= nil then self:CancelPlacement() return end if self.placer_recipe ~= nil and self.placer ~= nil then --do the placement if self.placer.components.placer.can_build and self.inst.replica.builder ~= nil and not self.inst.replica.builder:IsBusy() then self.inst.replica.builder:MakeRecipeAtPoint(self.placer_recipe, TheInput:GetWorldPosition(), self.placer:GetRotation(), self.placer_recipe_skin) self:CancelPlacement() end return end local act = self:GetLeftMouseAction() or BufferedAction(self.inst, nil, ACTIONS.WALKTO, nil, TheInput:GetWorldPosition()) if act.action == ACTIONS.WALKTO then if act.target == nil and TheInput:GetWorldEntityUnderMouse() == nil then self.startdragtime = GetTime() end elseif act.action == ACTIONS.ATTACK then if self.inst.sg ~= nil then if self.inst.sg:HasStateTag("attack") then return end elseif self.inst:HasTag("attack") then return end elseif act.action == ACTIONS.LOOKAT and act.target ~= nil and act.target.components.playeravatardata ~= nil and self.inst.HUD ~= nil then local client_obj = act.target.components.playeravatardata:GetData() if client_obj ~= nil then client_obj.inst = act.target self.inst.HUD:TogglePlayerAvatarPopup(client_obj.name, client_obj, true) end end if self.ismastersim then self.inst.components.combat:SetTarget(nil) else local position = TheInput:GetWorldPosition() local mouseover = act.action ~= ACTIONS.DROP and TheInput:GetWorldEntityUnderMouse() or nil local controlmods = self:EncodeControlMods() if self.locomotor == nil then self.remote_controls[CONTROL_PRIMARY] = 0 SendRPCToServer(RPC.LeftClick, act.action.code, position.x, position.z, mouseover, nil, controlmods, act.action.canforce, act.action.mod_name) elseif act.action ~= ACTIONS.WALKTO and self:CanLocomote() then act.preview_cb = function() self.remote_controls[CONTROL_PRIMARY] = 0 local isreleased = not TheInput:IsControlPressed(CONTROL_PRIMARY) SendRPCToServer(RPC.LeftClick, act.action.code, position.x, position.z, mouseover, isreleased, controlmods, nil, act.action.mod_name) end end end self:DoAction(act) end This will execute the action which has been tagged aas having the highest priority. BUT: you want to perform your action when you press the space bar, which is the "ActionButton". This is again a different story but the same principle. This time everything happens in playercontroller.lua When you press the space bar, this is executed: Spoiler function PlayerController:DoActionButton() if self.placer == nil then local buffaction = self:GetActionButtonAction() if buffaction ~= nil then if self.ismastersim then self.locomotor:PushAction(buffaction, true) return elseif self.locomotor == nil then self:RemoteActionButton(buffaction) return elseif self:CanLocomote() then if buffaction.action ~= ACTIONS.WALKTO then buffaction.preview_cb = function() self:RemoteActionButton(buffaction, not TheInput:IsControlPressed(CONTROL_ACTION) or nil) end end self.locomotor:PreviewAction(buffaction, true) end end elseif self.placer.components.placer.can_build and self.inst.replica.builder ~= nil and not self.inst.replica.builder:IsBusy() then --do the placement self.inst.replica.builder:MakeRecipeAtPoint(self.placer_recipe, self.placer:GetPosition(), self.placer:GetRotation(), self.placer_recipe_skin) end --Still need to let the server know our action button is down if not self.ismastersim and self.remote_controls[CONTROL_ACTION] == nil then self:RemoteActionButton() end end This function uses its own action picker which is the following Spoiler function PlayerController:GetActionButtonAction(force_target) --Don't want to spam the action button before the server actually starts the buffered action --Also check if playercontroller is enabled --Also check if force_target is still valid if (not self.ismastersim and (self.remote_controls[CONTROL_ACTION] or 0) > 0) or not self:IsEnabled() or (force_target ~= nil and (not force_target.entity:IsVisible() or force_target:HasTag("INLIMBO") or force_target:HasTag("NOCLICK"))) then --"DECOR" should never change, should be safe to skip that check return elseif self.actionbuttonoverride ~= nil then local buffaction, usedefault = self.actionbuttonoverride(self.inst, force_target) if not usedefault or buffaction ~= nil then return buffaction end elseif self.inst.replica.inventory:IsHeavyLifting() and not (self.inst.replica.rider ~= nil and self.inst.replica.rider:IsRiding()) then --hands are full! return elseif not self:IsDoingOrWorking() then local force_target_distsq = force_target ~= nil and self.inst:GetDistanceSqToInst(force_target) or nil if self.inst:HasTag("playerghost") then --haunt if force_target == nil then local target = FindEntity(self.inst, self.directwalking and 3 or 6, ValidateHaunt, nil, HAUNT_TARGET_EXCLUDE_TAGS) if CanEntitySeeTarget(self.inst, target) then return BufferedAction(self.inst, target, ACTIONS.HAUNT) end elseif force_target_distsq <= (self.directwalking and 9 or 36) and not (force_target:HasTag("haunted") or force_target:HasTag("catchable")) and ValidateHaunt(force_target) then return BufferedAction(self.inst, force_target, ACTIONS.HAUNT) end return end local tool = self.inst.replica.inventory:GetEquippedItem(EQUIPSLOTS.HANDS) --bug catching (has to go before combat) if tool ~= nil and tool:HasTag(ACTIONS.NET.id.."_tool") then if force_target == nil then local target = FindEntity(self.inst, 5, ValidateBugNet, { "_health", ACTIONS.NET.id.."_workable" }, TARGET_EXCLUDE_TAGS) if CanEntitySeeTarget(self.inst, target) then return BufferedAction(self.inst, target, ACTIONS.NET, tool) end elseif force_target_distsq <= 25 and force_target.replica.health ~= nil and ValidateBugNet(force_target) and force_target:HasTag(ACTIONS.NET.id.."_workable") then return BufferedAction(self.inst, force_target, ACTIONS.NET, tool) end end --catching if self.inst:HasTag("cancatch") then if force_target == nil then local target = FindEntity(self.inst, 10, nil, { "catchable" }, TARGET_EXCLUDE_TAGS) if CanEntitySeeTarget(self.inst, target) then return BufferedAction(self.inst, target, ACTIONS.CATCH) end elseif force_target_distsq <= 100 and force_target:HasTag("catchable") then return BufferedAction(self.inst, force_target, ACTIONS.CATCH) end end --unstick if force_target == nil then local target = FindEntity(self.inst, self.directwalking and 3 or 6, nil, { "pinned" }, TARGET_EXCLUDE_TAGS) if CanEntitySeeTarget(self.inst, target) then return BufferedAction(self.inst, target, ACTIONS.UNPIN) end elseif force_target_distsq <= (self.directwalking and 9 or 36) and force_target:HasTag("pinned") then return BufferedAction(self.inst, force_target, ACTIONS.UNPIN) end --misc: pickup, tool work, smother if force_target == nil then local pickup_tags = { "_inventoryitem", "pickable", "donecooking", "readyforharvest", "notreadyforharvest", "harvestable", "trapsprung", "minesprung", "dried", "inactive", "smolder", "saddled", "brushable", } if tool ~= nil then for k, v in pairs(TOOLACTIONS) do if tool:HasTag(k.."_tool") then table.insert(pickup_tags, k.."_workable") end end end local x, y, z = self.inst.Transform:GetWorldPosition() local ents = TheSim:FindEntities(x, y, z, self.directwalking and 3 or 6, nil, PICKUP_TARGET_EXCLUDE_TAGS, pickup_tags) for i, v in ipairs(ents) do if v ~= self.inst and v.entity:IsVisible() and CanEntitySeeTarget(self.inst, v) then local action = GetPickupAction(self.inst, v, tool) if action ~= nil then return BufferedAction(self.inst, v, action, action ~= ACTIONS.SMOTHER and tool or nil) end end end elseif force_target_distsq <= (self.directwalking and 9 or 36) then local action = GetPickupAction(self.inst, force_target, tool) if action ~= nil then return BufferedAction(self.inst, force_target, action, action ~= ACTIONS.SMOTHER and tool or nil) end end end end This last function is the one you need to modify to have your jump action returned in priority. I will try to write a simple example which demonstrates how it would work. Edited July 20, 2017 by ZupaleX Link to comment Share on other sites More sharing options...
ZupaleX Posted July 20, 2017 Share Posted July 20, 2017 Sorry for the double post but I decided that it deserve another post instead of a third edit. Please find attached a working skeleton for a custom action not using an object and performed when pressing the space bar. You'll have to adapt it to your needs and keep it mind it will probably not work well with a gamepad (if you want to make it compatible with using a gamepad you would need to override the function corresponding to the gamepad button the same way I override the space bar in my proof of principle). Spoiler local CHEATYHEAL = GLOBAL.Action({priority = 10, mount_valid=true, encumbered_valid=true}) CHEATYHEAL.strfn = function(act) return "Free Heal" end CHEATYHEAL.id = "CHEATYHEAL" CHEATYHEAL.fn = function(act) local doer = act.doer print("Howdy") if GLOBAL.TheWorld.ismastersim then if doer.components and doer.components.health then doer.components.health:DoDelta(20) -- Our custom action is simple: it heals the player for 20 HP end end return true end AddAction(CHEATYHEAL) AddStategraphActionHandler("wilson", ActionHandler(ACTIONS.CHEATYHEAL, "doshortaction")) -- doshortaction is the default state for short actions like picking up something from the ground. --Replace that with the name of the state you want the character to go to upon performing the action AddStategraphActionHandler("wilson_client", ActionHandler(ACTIONS.CHEATYHEAL, "doshortaction")) -- Don't forget to create a state for the client as well and to add the link between the action and the state for the client local function NewGetActionButtonAction(self, force_target) if (not self.ismastersim and (self.remote_controls[CONTROL_ACTION] or 0) > 0) or not self:IsEnabled() or (force_target ~= nil and (not force_target.entity:IsVisible() or force_target:HasTag("INLIMBO") or force_target:HasTag("NOCLICK"))) then --"DECOR" should never change, should be safe to skip that check return elseif self.actionbuttonoverride ~= nil then -- Remove that part if you want to ignore the action button override when you are supposed to perform your special action (like if the player press CONTROL button or something like that...) local buffaction, usedefault = self.actionbuttonoverride(self.inst, force_target) if not usedefault or buffaction ~= nil then return buffaction end else local nearbyFlower = GLOBAL.FindEntity(self.inst, 10, nil, {"flower"}) -- check if a flower is within a radius of 10 from the player (self.inst) if nearbyFlower ~= nil then print("Got a flower here!") return GLOBAL.BufferedAction(self.inst, nil, ACTIONS.CHEATYHEAL) -- So if a flower is found within a radius on 10, the CHEATYHEAL action will be performed upon pressing the space bar end end end AddComponentPostInit("playercontroller", function(controller) local OriginalGetActionButtonAction = controller.GetActionButtonAction controller.GetActionButtonAction = function(self, force_target) local buffAction = NewGetActionButtonAction(self, force_target) if buffAction ~= nil then return buffAction end -- If the function did not return yet, then it means our custom action cannot be performed right now, so we return the original function to get the valid actions (PICKUP, PICK, CHOP, etc...) return OriginalGetActionButtonAction(self, force_target) end end) This can go directly in your modmain.lua if you want to test it out. Cheers Link to comment Share on other sites More sharing options...
. . . Posted July 20, 2017 Author Share Posted July 20, 2017 Wow, thanks very much @ZupaleX now spacebar is jump button with no glitches !! Though, my character can still force_attack while doing this action ! Maybe I messed something in the code up?? Spoiler local JUMP_ADAM = GLOBAL.Action({priority = 10, mount_valid=nil, encumbered_valid=nil}) JUMP_ADAM.strfn = function(act) return "Jump" end JUMP_ADAM.id = "JUMP_ADAM" JUMP_ADAM.fn = function(act) jump(act) return true end local RUN_JUMP_ADAM = GLOBAL.Action({priority = 10, mount_valid=nil, encumbered_valid=nil}) RUN_JUMP_ADAM.strfn = function(act) return "Jump" end RUN_JUMP_ADAM.id = "RUN_JUMP_ADAM" RUN_JUMP_ADAM.fn = function(act) run_jump(act) return true end AddAction(JUMP_ADAM) AddStategraphActionHandler("wilson", ActionHandler(ACTIONS.JUMP_ADAM)) AddStategraphActionHandler("wilson_client", ActionHandler(ACTIONS.JUMP_ADAM)) AddAction(RUN_JUMP_ADAM) AddStategraphActionHandler("wilson", ActionHandler(ACTIONS.RUN_JUMP_ADAM)) AddStategraphActionHandler("wilson_client", ActionHandler(ACTIONS.RUN_JUMP_ADAM)) local function NewGetActionButtonAction(self, force_target) RemovePlayerActions(self.inst, true) RemovePlayerActions(self.inst, false) if (not self.ismastersim and (self.remote_controls[CONTROL_ACTION] or 0) > 0) or not self:IsEnabled() or (force_target ~= nil and (not force_target.entity:IsVisible() or force_target:HasTag("INLIMBO") or force_target:HasTag("NOCLICK"))) then --"DECOR" should never change, should be safe to skip that check return elseif self.actionbuttonoverride ~= nil then -- Remove that part if you want to ignore the action button override when you are supposed to perform your special action (like if the player press CONTROL button or something like that...) local buffaction, usedefault = self.actionbuttonoverride(self.inst, force_target) if not usedefault or buffaction ~= nil then return buffaction end elseif self.inst.components.locomotor:WantsToMoveForward() then return GLOBAL.BufferedAction(self.inst, nil, ACTIONS.RUN_JUMP_ADAM) else return GLOBAL.BufferedAction(self.inst, nil, ACTIONS.JUMP_ADAM) end end AddComponentPostInit("playercontroller", function(controller) local OriginalGetActionButtonAction = controller.GetActionButtonAction controller.GetActionButtonAction = function(self, force_target) local buffAction = NewGetActionButtonAction(self, force_target) if buffAction ~= nil then return buffAction end return OriginalGetActionButtonAction(self, force_target) end end) One more thing can you maybe tell me what this code does? Cause I don't really understand what it does .. Spoiler elseif self.actionbuttonoverride ~= nil then -- Remove that part if you want to ignore the action button override when you are supposed to perform your special action (like if the player press CONTROL button or something like that...) local buffaction, usedefault = self.actionbuttonoverride(self.inst, force_target) if not usedefault or buffaction ~= nil then return buffaction end I don't want to bother you anymore with this force_attack stuff so I think maybe I can solve it by just editing the attack state to not do a attack with some values (though the character would still go up to the entity probably). And thanks a lot for your help man, I definitely wouldn't be able to make spacebar be jump button without your help !!! 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