ID:274001
 
I can't seem to get my head around how best to do this:

My System
Players learn skills. When a new skill is learnt, a new obj is created in their contents and attached to that object is the verb for the skill.

These objs are visible when going into a certain window. In this window players may drag and drop the obj around it as they wish (using a series of grids, one per skill).

Players may also drop these skill cards into a hotbar on the side of the main window. There are 13 slots.
I've already set it up so that clicking on the obj when in one of these 13 slots executes the relevant verb.


My problem
I also wish to have a verb (or 13 verbs) that will dynamically execut the skills for each of the 13 slots(grids).
So, for example, if I have nothing in slot1, and I use the verb for slot1, nothing happens.

BUT, if I drag and drop the PUNCH skill into slot1, and then use the verb for slot1 - I punch.

Seems a simple enough concept to me, but I can't figure out an appropriate way to code it.


If I could somehow save /mob/verb/Punch() to a var such as HotbarCommands[slotnumberhere]
I thought about doing this with the call() proc, but I will also need to be able to save a verb such as /mob/verb/Spell(mob/m in oview())

Alternatively, if it is possible to find an obj in usr.contents with a specific variable and execute a verb that is defined within it?
mob/verb/HB_Slot2()
for(var/obj/o in usr.contents)
if(o.InHotbarSlot=="2")
o.Execute() //execute being a generic verb for all such objs that in turn executes each one's specific attack?


I don't know if the methods I suggested are even possible. And even if they are, I'm clueless as to which one would be best, if any.

Any help will be much appreciated.


EDIT:
After a few attempts and intense confusion I've kinda concluded I need 13 different verbs, one for each slot. And to dynamically allocate a verb to be executed to each one.
call(Object,ProcName)(Arguments)

You could probably just store the proc/verb path (/mob/verb/Punch) in a variable function and use call(src, o.function)().
In response to Kaiochao (#1)
mob/verb/Spell(mob/M in oview(usr))
M<<"Hit by a spell!"

mob/verb/HB_Slot2()
for(var/obj/o in usr.contents)
if(o.InHotbarSlot=="2")
call(src, o.function)()


I've tried going down that path; as you can see above: it doesn't work for verbs that have arguments.
In response to Saucepan Man (#2)
To simplify:
if obj/Skill has a verb in it called test(mob/M in world), complete the verb to call the test(mob/M in world) verb ob behalf of usr?
mob/verb/CallingVerb()
for(var/obj/Skill/S in usr.contents)
if(S.variable=x)
//call test(mob/M in world)

obj/Skill
name="blah"
variable=x
Click()
test() //A solution would also allow this to work :)
verb/test(mob/M in world)
usr<<"You selected [M]!"
In response to Saucepan Man (#3)
Always feel rude if i gotta bump a thread :\
In response to Saucepan Man (#4)
I can't think of a clean way to call verbs with arguments dynamically. I would suggest just doing an input() in the verbs and ditching the arguments. Or better yet, get rid of those ugly input boxes entirely and use something like Garthor's GetClick to let the user select a target.

The only situation where that might be a problem is if you're relying on text-based execution from an input control or user-defined macros. In the unlikely event that this is the case, you could always do both, and just do M as null|mob in world so it allows the argument-free version through, and only runs the alternative input if M was unset.
Are you using a /list to keep track of what is in each hotkey spot or merely assigning variable numbers?

You can actually have one verb called and pass the value of which hotkey was pressed as an argument, ex:
In the macro: ` = Hot 0, 1 = Hot 1, ..., 0 = Hot 11, - = Hot 12 and + = Hot 13

"Hot" would be the verb that is called when a hot key is pressed and the numbers are the arguments sent, indicating which ... well, hotkey was pressed:
mob/verb/Hot(pos as num)
set hidden = 1
src << "You have pressed hotkey [pos]!"


Now, if you have an array for the hotkeys, you can simply use the argument value to obtain the reference to the object set... otherwise, if you manually set a variable... may I recommend changing its tag variable instead, so you can use locate()... either ways, you can always loop through all items and find the object with that hotkey spot...

Anyways, once you got the reference to the object, as mentionedpreviously, use call()... BUT if all the hotkey stuff belong to the same path (ex: /Hotkey), you can define the variable as that path and call the function:
mob/verb/Hot(pos)
set hidden = 1
// Make sure pos = 1 - 13
var/Hotkey/H = Hotkey_array[pos] // gets the object reference
if(H) // if it exists
H.Use()


Though if all of these hotkey calls a verb, I suppose you can have an array with their verb names assigned when set (ex: 1 = "punch", 2 = "OMG_BAM_BAM_PEW"), which corresponds to /mob/verb/[name]... then, all you have to do after checking if it exists is use call() to call() the variable:
call(src, "/mob/verb/[array[pos]]").
In response to Saucepan Man (#4)
proc
escape_text(txt)
txt = replacetext(txt,"\\","\\\\")
txt = replacetext(txt,"\"","\\\"")
return txt

replacetext(txt,txt1,txt2)
var/found = findtext(txt,txt1)
if(found)
return copytext(txt,1,found)+txt2+replacetext(copytext(txt,found+lentext(txt1)),txt1,txt2)
return txt

obj/Skill
var/command
proc
Execute(var/user)
winset(user,null,"command=\"[escape_text(command)]\"")
Click()
Execute(usr)

test
command = "test"
verb
test(blah blah)
blah blah blah
blah blah


PS: Read GhostAnime's post.