Invoke Script on Cloned Object?
onimike
01 Sept 2016, 07:41Hello Quest! So what im trying to do is make a storage chest that can be cloned and hold items from inventory. Well I made a verb on chest called "store" when clicked it gets all inventory items and showsmenu, well after I call if (result =" axe") i wanted to move axe to "this" being its a clone. But that doesn't work so I tried to add a attribute called "addaxe" then after I call my (if axe) then (invoke (this, "addaxe")) but always end up with same error as it can't refer to itself after trying to run new script. How can i refer to the cloned chest EVEN after If and then statement is called? I know its probably simple as always but always have the hardest times with these clones thanks for your time.
Mike
The Pixie
01 Sept 2016, 09:02You have a space between the first double quote and axe; if that is in your code, Quest will be trying to match the wrong thing. However, the basic problem is that this
is only valid for the script attached to the chest. The ShowMenu has its own script, which is not associated with anything, and inside there this
is meaningless.
It is not neat, but the work around is to set an attribute on the game object.
game.showmenuitem = this
ShowMenu(...whatever...) {
if (result = "axe") {
ace.parent = game.showmenuitem
}
}
In fact, a neater way would be to get the object from the result (if the menu shows names, not aliases). The bit inside the ShowMenu script becomes this, and will hadle any object:
obj = GetObject(result)
obj.parent = game.showmenuitem
By the way, if you use invoke
, you cannot use this
. I always use do
, as it is otherwise the same, but gives you this
(and is four letters less typing!).
http://docs.textadventures.co.uk/quest/scripts/do.html
hegemonkhan
01 Sept 2016, 12:57for calling simple Script Attributes you can use 'invoke' (well I do anyways), but the 'do' is much more powerful/useful than is 'invoke'. Pixie's point that it is less typing is also a good point, but I use 'invoke' as it's quick/easy to code in, for example:
invoke (game.start) // the built-in 'start' Script Attribute is found in the GUI~Editor: 'game' Game Object -> 'Scripts' Tab -> the 'start' Script, which is the first thing that is done/run/activated/executed after the game loads up/is initialzed/built-up. 'invoke' and 'do' is a way of looping/repeating/re-doing Script Attributes ('invoke/do' the Script Attribute inside of the Script Attribute), just as you would to loop Functions (calling the Function within the Function). Or, 'invoke/do' can just be used to call/activate the Script Attribute too (from anywhere), you don't have to use them to do looping.
what makes 'do' more powerful (at least in one way), is that you can concatenate for your Object's Name and/or its Attribute's Name, (I am still confused at, what are and how the, dictionary arguments/parameters work, lol), for a very lame/impractical example:
(pretend that the 'show menu' is inside a Function, which is called when you level up --- which would be done through/within a global Turnscript or the special 'changed' Script on, in this case, the 'player' Player Object, let's say, via checking your 'experience' Integer Attribute to your 'experience needed to level up')
<object name="player">
<attr name="strength_integer_attribute" type="int">0</attr>
<attr name="endurance_integer_attribute" type="int">0</attr>
<attr name="dexterity_integer_attribute" type="int">0</attr>
<attr name="strength_script_attribute" type="script">
this.strength_integer_attribute = this.strength_integer_attribute + 1
</attr>
<attr name="endurance_script_attribute" type="script">
this.endurance_integer_attribute = this.endurance_integer_attribute + 1
</attr>
<attr name="dexterity_script_attribute" type="script">
this.dexterity_integer_attribute = this.dexterity_integer_attribute + 1
</attr>
</object>
show menu ("Stat?", split ("strength;endurance;dexterity", ";"), false) {
do (player, result + "_script_attribute")
}
but if I wanted to use 'invoke', I'd have to do this instead (as there's no concatenation available with 'invoke', at least I don't think so... lol):
<object name="player">
<attr name="strength_integer_attribute" type="int">0</attr>
<attr name="endurance_integer_attribute" type="int">0</attr>
<attr name="dexterity_integer_attribute" type="int">0</attr>
<attr name="strength_script_attribute" type="script">
this.strength_integer_attribute = this.strength_integer_attribute + 1
</attr>
<attr name="endurance_script_attribute" type="script">
this.endurance_integer_attribute = this.endurance_integer_attribute + 1
</attr>
<attr name="dexterity_script_attribute" type="script">
this.dexterity_integer_attribute = this.dexterity_integer_attribute + 1
</attr>
</object>
show menu ("Stat?", split ("strength;endurance;dexterity", ";"), false) {
if (result = "strength") {
invoke (player.strength_script_attribute)
} else if (result = "endurance") {
invoke (player.endurance_script_attribute)
} else if (result = "dexterity") {
invoke (player.dexterity_script_attribute
}
}
// or, if you prefer using the 'switch' Script/Function instead of 'if' Script:
show menu ("Stat?", split ("strength;endurance;dexterity", ";"), false) {
switch (result) {
case ("strength") {
invoke (player.strength_script_attribute)
}
case ("endurance") {
invoke (player.endurance_script_attribute)
}
case ("dexterity") {
invoke (player.dexterity_script_attribute)
}
}
}
and ya, possibly good spot by Pixie:
ALWAYS be careful of accidental spaces... especially when you go to copy and paste, as if you accidentally highlight too far and copy those extra spaces, then you're going to get errors, as string matching includes spaces/white-spaces:
"strength" = "strength" // TRUE
" strenth" = "strength" // FALSE
"strength " = "strength" // FALSE
"stre ngth" = "strength" // FALSE
" strength" = "strength" // FALSE
"strength " = "strength" // FALSE
"stre ngth" = "strength" // FALSE
noticing a spacing issue is extremely hard... lol. So try to catch it in the moment it occurs, otherwise, you'll and we'll be pulling our hair out, in trying to figure out what/where is the cause of the error(s), lol.
for example, if you have a very long/large scripting block... the error will show the the entire scripting block, and thus good luck scouring through that long/large scripting block for the issue(s) causing the error(s) with it... as you don't even know if it's a spacing issue or something else that is wrong with it... and even if/when you're checking for a spacing issue... actually spotting it is very difficult... it's easy for your eyes/brain to go right by it even when you're checking for it, due to how the brain works.
---------
Humans LOVE spaces:
hkisan18yearoldmalehumanwarrior // YUCK!
hk is an 18 year old male human warrior // Much better! (HK wishes he was still 18, lol)
Whereas, computers HATE spaces! (ignoring using spaces for parsing of course --- but that's still a lot of work/operations for a computer and for you to code in, as well. So the 'HATE' is still accurate, and the statement true, lol)
onimike
01 Sept 2016, 15:26Hey thanks guys no spaces just typed in by accident but im still confused, when I add the showmenuitem to game I get errors non stop and yes I seen the ace.parent and changed it but get loads of errors. So i tried the "do" which as i understand "do" is a "then" statement right? Here is the code I call in my cloned chest
if (ListContains(ScopeVisible(), this)) {
string_dict = NewStringDictionary()
foreach (obj, ScopeInventory()) {
dictionary add (string_dict, obj.name, GetDisplayName(obj))
}
ShowMenu ("Pick an item", string_dict, true) {
obj = GetObject(result)
msg ("You selected the " + GetDisplayName(obj))
if (result = "stoneaxe") {
invoke (this, "addaxe") // Which does (CloneObjectAndMove (stoneaxe, this)) MoveObject (stoneaxe, Items)
}
}
}
else {
msg ("You need to be by a storage chest to store this item.")
}
Every thing works up until the Invoke obviously lol
I know "this" doesn't work neither does "do" in our "Invoke script" and would rather have the code beside it(Which is the clone axe and move to "this") but doesn't work, I know after menu showed calls new script so "this" is now null and Kind of understand what Pixies taking about by setting the var in the game, but seems to be getting really complicating adding a item to a cloned container.
Thanks again guys always love the Info you all leave gives me lots to read and play with :)
Mike
EDIT:
Ok so working with the code Pixie gave where setting var in game and casting menu so all works now besides moving object axe to cloned chest
heres code in game
game.showmenuitems = this
string_dict = NewStringDictionary()
foreach (obj, ScopeInventory()) {
dictionary add (string_dict, obj.name, GetDisplayName(obj))
}
ShowMenu ("Pick an item", string_dict, true) {
obj = GetObject(result)
msg ("You selected the " + GetDisplayName(obj))
if (result = "stoneaxe") {
stoneaxe.parent = game.showmenuitems
CloneObjectAndMove (stoneaxe, this)
MoveObject (stoneaxe, Items)
}
}
The Pixie
01 Sept 2016, 19:59The line:
stoneaxe.parent = game.showmenuitems
... will move the axe to the chest. It looks like the last two lines are trying to do that too, but one to this
, which has no meaning inside the ShowMenu
script, and the other to Items
, and it is not clear what that is. I think if you just get rid of those two lines it should work.
By the way, these two lines of code do the same thing:
stoneaxe.parent = game.showmenuitems
MoveObject (stoneaxe, game.showmenuitems)
onimike
02 Sept 2016, 03:18Oh wow thank you so much I also had script in wrong place had it in game attribute had to run it in chest thank you so so much!
Mike