Aquaterion Posted May 16, 2016 Share Posted May 16, 2016 So I modified spellcaster to support a "specific target" function that I need for my staff, which works fine. But when I went to try and change the string, which I thought should be here; GLOBAL.ACTIONS.CASTSPELL.strfn = function(act) return act.invobject ~= nil and act.invobject.components.spellcaster ~= nil and (act.invobject.components.spellcaster.specifictargetfn == nil or act.invobject.components.spellcaster.specifictargetfn(act.target)) and act.invobject.components.spellcaster.actiontype or nil end but apparently, even if i change the whole block of code to "return nil" it still shows "Cast Spell" So where am I suppose to put this change? I tried looking into how the telestaff does it, or in the spellcaster component, but I didn't notice anything of help. Thanks. Link to comment Share on other sites More sharing options...
Muche Posted May 16, 2016 Share Posted May 16, 2016 Have you added strings for actiontypes into GLOBAL.STRINGS.ACTIONS.CASTSPELL table? Link to comment Share on other sites More sharing options...
Aquaterion Posted May 16, 2016 Author Share Posted May 16, 2016 5 minutes ago, Muche said: Have you added strings for actiontypes into GLOBAL.STRINGS.ACTIONS.CASTSPELL table? no, but I'm trying to hide the option to "cast" if the target prefab doesnt meet the requirements. Am I messing with the wrong code? Link to comment Share on other sites More sharing options...
Muche Posted May 16, 2016 Share Posted May 16, 2016 (edited) IIRC, stringutil.lua|getmodifiedstring() returns generic string (in this case STRINGS.ACTIONS.CASTSPELL.GENERIC="Cast Spell") if it can't find one provided by strfn function in the appropriate table. Maybe you can try to overwrite/inject before spellcaster component action so it doesn't insert ACTIONS.CASTSPELL into actions table if it doesn't meet the requirements? Edited May 16, 2016 by Muche Link to comment Share on other sites More sharing options...
Aquaterion Posted May 16, 2016 Author Share Posted May 16, 2016 (edited) 29 minutes ago, Muche said: IIRC, stringutil.lua|getmodifiedstring() returns generic string (in this case STRINGS.ACTIONS.CASTSPELL.GENERIC="Cast Spell") if it can't find one provided by strfn function in the appropriate table. Maybe you can try to overwrite/inject before spellcaster component action so it doesn't insert ACTIONS.CASTSPELL into actions table if it doesn't meet the requirements? I don't really understand what you suggested I do, but it came to mind now to search for the tag that telestaff uses and it did lead me to "componentactions.lua" but i'm not sure how i can modify it without editing base files: spellcaster = function(inst, doer, target, actions, right) if right then if inst:HasTag("castontargets") then table.insert(actions, ACTIONS.CASTSPELL) else local castonrecipes = inst:HasTag("castonrecipes") local castonlocomotors = inst:HasTag("castonlocomotors") if (castonrecipes or castonlocomotors) and (not castonrecipes or AllRecipes[target.prefab] ~= nil) and (not castonlocomotors or target:HasTag("locomotor")) then table.insert(actions, ACTIONS.CASTSPELL) end end end end, for now i'm gonna try messing with the spellcaster code to remove the tag if the player cant cast it. Do you happen to know how to add more of these: "spell = oncancast" in a ComponentPostInit? I dont think I can actually do that since the targetcheckfn is dynamic Edited May 16, 2016 by Aquaterion Link to comment Share on other sites More sharing options...
Aquaterion Posted May 16, 2016 Author Share Posted May 16, 2016 I managed to get it to work by editing BASE files, so all I need now is to know how to do it in modmain instead. Link to comment Share on other sites More sharing options...
Muche Posted May 16, 2016 Share Posted May 16, 2016 There doesn't seem to be an easy way to change a base component action. Adding a custom one with higher priority could solve that: local actCastSpell2 = AddAction("CASTSPELL2", "My Cast Spell", function(act) -- copied from actions.lua|CASTSPELL, do something custom? local staff = act.invobject or act.doer.components.inventory:GetEquippedItem(GLOBAL.EQUIPSLOTS.HANDS) if staff and staff.components.spellcaster and staff.components.spellcaster:CanCast(act.doer, act.target, act.pos) then staff.components.spellcaster:CastSpell(act.target, act.pos) return true end end) actCastSpell2.priority = 0 -- higher than GLOBAL.ACTIONS.CASTSPELL actCastSpell2.distance = 20 actCastSpell2.mount_valid = true AddComponentAction("EQUIPPED", "spellcaster", function(inst, doer, target, actions, right) if right then if inst.components.spellcaster ~= nil -- component spellcaster is not available on clients, need to rewrite it using tags: -- and (act.invobject.components.spellcaster.specifictargetfn == nil or -- act.invobject.components.spellcaster.specifictargetfn(act.target) -- ) then table.insert(actions, actCastSpell2) end end end) -- handlers copied from SGwilson & SGwilson_client AddStategraphActionHandler("wilson", GLOBAL.ActionHandler(actCastSpell2, function(inst, action) return action.invobject.components.spellcaster.castingstate or "castspell" end)) AddStategraphActionHandler("wilson_client", GLOBAL.ActionHandler(actCastSpell2, "castspell")) The component action check needs some work to be done, as components are not available to clients, which the component actions run on. Also, the tags castontargets, castonrecipes and castonlocomotors have to be not present when the custom action is not added too, so it doesn't show up again. They can be present if the custom action is added, since that will take precedence due to higher priority. Â Link to comment Share on other sites More sharing options...
Aquaterion Posted May 16, 2016 Author Share Posted May 16, 2016 (edited) 1 hour ago, Muche said: -snip- I'm not sure how i can add tags to a dynamic check? Â Btw, the specificfn thing happens to also be saved on the staff, does that help? Well I just tested it in multiplayer and it didn't work D: and inst.staffdata.specificfn(target) gahhhh why does clientside have to be so hardd Edited May 16, 2016 by Aquaterion Link to comment Share on other sites More sharing options...
DarkXero Posted May 16, 2016 Share Posted May 16, 2016 26 minutes ago, Aquaterion said: I'm not sure how i can add tags to a dynamic check? You need to have those checks in the server, and it updates tags accordingly. What I'm gathering here is that you want to have a item with spellcaster component say the "Cast Spell" only on certain targets? Then give the prefabs you want to be targets a inst:AddTag("aqua_spellcastable") with AddPrefabPostInit and then check for that tag on the AddComponentAction. If your specifictargetfn does a complex check, and you want the client to do it, then you will need to send many tags, or make a replica with many netvars, so the client can make the check themselves. Â By the way GLOBAL.ACTIONS.CASTSPELL.strfn = function(act) return act.invobject ~= nil and act.invobject.components.spellcaster ~= nil and (act.invobject.components.spellcaster.specifictargetfn == nil or act.invobject.components.spellcaster.specifictargetfn(act.target)) and act.invobject.components.spellcaster.actiontype or nil end always returns nil for clients, and even the current code for it returns nil. Which is why the staff_tornado has "Use Gadget" for hosts, and "Cast Spell" for clients. If it returned an empty string, you would have a little mouse icon followed by nothing. Link to comment Share on other sites More sharing options...
Muche Posted May 16, 2016 Share Posted May 16, 2016 What does that dynamic check do? Maybe it can be reimplemented on the client side if it uses only prefab names? Or tags could be emloyed? Then there is the less option of always displaying the action availability prompt, only for the action to fizzle when used because the server (which has all information available) will deem the requirements not fulfilled. Alternatively, there is always the option of creating own replicable component that will supply required information through attached classified. Link to comment Share on other sites More sharing options...
Aquaterion Posted May 16, 2016 Author Share Posted May 16, 2016 2 minutes ago, Muche said: What does that dynamic check do? Maybe it can be reimplemented on the client side if it uses only prefab names? Or tags could be emloyed? Then there is the less option of always displaying the action availability prompt, only for the action to fizzle when used because the server (which has all information available) will deem the requirements not fulfilled. Alternatively, there is always the option of creating own replicable component that will supply required information through attached classified. I tried doing tags like "targetonly_"..target(while also simplifing the specific feature to just prefabs) but everything stopped working and at that moment I remembered I had the inst.staffdata and I wanted to try that instead. I'll try using it again. 10 minutes ago, DarkXero said: Then give the prefabs you want to be targets a inst:AddTag("aqua_spellcastable") with AddPrefabPostInit and then check for that tag on the AddComponentAction. Â If it doesn't work I'll try this method. Link to comment Share on other sites More sharing options...
Aquaterion Posted May 16, 2016 Author Share Posted May 16, 2016 (edited) Anddd for some reason this doesn't work for clients yet again.. Shockerr: inst:HasTag("targetonly_"..target.prefab) The staff definitely has that tag "targetonly_campfire" yet when I hover over a campfire nothing shows up.. I'm about to give up on this clientside bullsh** and just make the caster say "Invalid Target" or something.. Â As I was about to try DarkXero's method, and thinking how to implement it into Muche's component action, I saw if inst.components.spellcaster ~= nil and at that moment I remembed you said COMPONENTS DONT WORK THERE, so finallyyyyy I removed that and its working for specific prefabs(I woulda noticed sooner but you added that line yourself), however this makes it uncompatible with mod items. Â does the target have components for the client in the component action? Edited May 16, 2016 by Aquaterion Link to comment Share on other sites More sharing options...
DarkXero Posted May 16, 2016 Share Posted May 16, 2016 22 minutes ago, Aquaterion said: does the target have components for the client in the component action? No, just replicas and tags. Link to comment Share on other sites More sharing options...
Aquaterion Posted May 16, 2016 Author Share Posted May 16, 2016 (edited) 8 minutes ago, DarkXero said: No, just replicas and tags. would it be healthy for the game if I added every component name as a tag for EVERY prefab? Â idk im tired I cant think anymore Edited May 16, 2016 by Aquaterion Link to comment Share on other sites More sharing options...
DarkXero Posted May 16, 2016 Share Posted May 16, 2016 7 minutes ago, Aquaterion said: would it be healthy for the game if I added every component name as a tag for EVERY prefab? But why? What do you want to check? Link to comment Share on other sites More sharing options...
Aquaterion Posted May 16, 2016 Author Share Posted May 16, 2016 (edited) 4 minutes ago, DarkXero said: But why? What do you want to check? if the target has that component? but I think i'm just gonna give up on the clientside part.. I'd rather keep full serverside functionality. If for example you want to make a staff that idk takes sanity from the target, I wanted the "Cast Spell" to only show up on targets with sanity Edited May 16, 2016 by Aquaterion Link to comment Share on other sites More sharing options...
Muche Posted May 16, 2016 Share Posted May 16, 2016 3 minutes ago, Aquaterion said: would it be healthy for the game if I added every component name as a tag for EVERY prefab? Â idk im tired I cant think anymore There is a hard limit of 31 tags for an entity, so that could cause problems. How many differentiable targets are there? I mean, does the target need all, let's say 5, different tags for each component the target has, or is just one tag enough (indicating it's a valid target for the item, i.e. this entity has at least one of 5 components)? Link to comment Share on other sites More sharing options...
DarkXero Posted May 16, 2016 Share Posted May 16, 2016 2 minutes ago, Aquaterion said: if the target has that component? but I think i'm just gonna give up on the clientside part.. I'd rather keep full serverside functionality. Well, I don't know why would you want to know every single component a prefab has. But yes, you can make a AddPrefabPostInitAny that parses all components and attaches a tag if it has it. 2 minutes ago, Muche said: There is a hard limit of 31 tags for an entity, so that could cause problems. Instead of using tags, he could parse through all components, get their names, concatenate them into a single string, and then give the prefab a net_string holding it. Then the client only needs to read the string. Link to comment Share on other sites More sharing options...
Aquaterion Posted May 16, 2016 Author Share Posted May 16, 2016 4 minutes ago, DarkXero said: Well, I don't know why would you want to know every single component a prefab has. But yes, you can make a AddPrefabPostInitAny that parses all components and attaches a tag if it has it. Instead of using tags, he could parse through all components, get their names, concatenate them into a single string, and then give the prefab a net_string holding it. Then the client only needs to read the string. Why is it everything I try to mod in this game end up being super complicated.. darn you clientside.. maybe I should just go to DS.. Anyways. I'm sticking with server-side only. netvars scare me so that made me give up even more lol 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