Knapsack as container

OurJud
Ignore me. I'm an idiot.

Having said that, is there a way to automatically move an object to a container on take?

Silver
Yes... I think... (you can certainly move objects with a script) but then the object wouldn't show up in your inventory list. Or at least I don't know how to do that.

OurJud
Silver wrote:Yes... I think... (you can certainly move objects with a script) but then the object wouldn't show up in your inventory list. Or at least I don't know how to do that.

It would show up, just as long as you're carrying the container to which you've moved it. I did fear that putting everything in a container (in this case a knapsack) would mean the player would have to type 'open knapsack' every time they wanted to grab something out of there, but luckily, you can set the container to 'open' and the player has immediate access. Knowing that, it would be handy if everything they collect in the game goes straight in there rather than me having to include a script each time to move it there.

Silver
Oh I didn't know that. Sounds interesting. Especially if you were to give the player an inventory limit that can be extended with bags.

OurJud
Silver wrote:Oh I didn't know that. Sounds interesting. Especially if you were to give the player an inventory limit that can be extended with bags.

It would be great for a wild camping game - huge 75ltr rucksack on your back! :D

HegemonKhan
in the GUI~Editor, I'm pretty sure that there's checkbox toggles for doing take+open upon 'take' and unlock+open upon 'unlock'
(I'd have to look up how it's done in code, as I'm not familiar with all the built-in stuff)

use the wiki's document search bar and look at these built-in Object Types:

(GUI~Editor: Container Tab -> Container Object Types)

container
container_open
container_closed
surface (simply set your container Object, your 'knapsack~bag', to this Object Type, for its contents~'child objects' to be always visable, no need for opening it)

and, there's this Object Type too:

container_lockable

--------

though, you don't really need an Object (such as a 'knapsack' for carrying capacity and~or and~or 'gold coins' for currency~cash), as all you need is Attributes, and some simple message scripting for the illusion of having~using 'knapsack' and~or 'gold coin' Objects.

think about the impractical'ity of:
(unless you use Sora's Stackable Library, hehe)

'gold coin' Objects...

instead of just using Attributes (This takes awhile to learn, especially with using the 'statusattributes', well in code anyways):

player.gold_coins_integer = Value
player.gold_coins_integer = player.gold_coins_integer + Value
player.gold_coins_integer = player.gold_coins_integer - Value
player.cash_string = "Knapsack: " + player.gold_coins_integer + " gold coins"
<statusattributes type="simplestringdictionary">cash_string = !</statusattributes>

OurJud
Having an object (in my case the knapsack) set to 'open' also has the desired effect of giving the player immediate access to their goodies. I would use this option over yours because pressing 'i' automatically gives a more logical answer of "You have a knapsack (containing): torch, gun...."

However, none of the options you highlight address my problem of having an object automatically 'moved' to the knapsack on 'take'.

HegemonKhan
for moving, you'd have to either:

edit the default 'take' scripting (Library -> Show Library Elements -> take -> copy -> edit it), adding in the Script: 'GUI~Editor: MoveObject (this, your_destination_object's_name)' or 'Alternative Code: this.parent = your_destination_object's_name'

OR

for your own 'take' Verb~Command:

adding in the Script: 'GUI~Editor: MoveObject (this, your_destination_object's_name)' or 'Alternative Code: this.parent = your_destination_object's_name'

OR

if you don't mind cloning the Object, you can use the Script: http://docs.textadventures.co.uk/quest/ ... dmove.html

Silver
There's a number of ways of doing it. As you don't have an object list and are just describing it in the room, the object could already be in the knapsack but invisible.

Then just set up a command in that room called take/get/pick up (object name)
Then just run a script for that command making that (object name) visible and a print message saying whatever you want like "you take the (object name)"

jaynabonne
Unfortunately, all the "take" overriding happens on the taken object. It's easy to change one object to have the behavior you describe, but there's no easy (read: GUI standard) way to automatically move them all without touching each one. I think you'd have to modify the take command itself (meaning the underlying "DoTake" function) to make it happen (as HK said). I'd think you would want to keep all the standard behavior, only modfifying where the object is moved to.

That might be easy to do actually, depending on how convoluted the code is. If you could find the line where the object is moved, you could change that one line to move it to the knapsack instead.

The Pixie
If it was me, I would just change the inventory limit when the player picks up the knapsack. If the player picks things up, they just go into the inventory, which is assumed to be spread across what you hold and what you have in your bag.

What benefit does it bring to your game to have the inventory track what is actually in the bag and what is not?

OurJud
The Pixie wrote:What benefit does it bring to your game to have the inventory track what is actually in the bag and what is not?

Not sure I fully understand the question, but if you're asking why it matters if items are in the bag or not, it doesn't in terms of mechanics. It would just seem odd to me if on checking my inventory I got: "You are carrying a gun, a torch, a notebook, a knapsack and a crowbar.", instead of: "You are carrying a knapsack (containing) a gun, a torch..."

Anyway, I've now got a few ways to go about it, so thanks to everyone for that.

Silver
Well then surely the easiest way about it is to have the player start the game with a knapsack that can't be dropped and to change the inventory response to "you are carrying a knapsack which contains..."

HegemonKhan
if you don't want to mess with the underlying 'take' code, you can use a global Turnscript, adding in scripts that will move all (except the 'knapsack' Object, obviously, lol: move 'knapsack' into the 'knapsack', lol) (or specificied) Objects from your inventory into your 'knapsack' Object in the inventory, for every turn.

take 'potion' -> inventory
auto global Turnscript: 'potion' -> 'knapsack'

// this code will move every object (except the knapsack) from the inventory to the knapsack, every turn.

// if you only want to move specified Objects, then let me know, and I'll give code for that. Example of specified Objects (instead of all Objects): only moving 'arrow' type of Objects into your 'quiver' Object, as a 'quiver' holds 'arrows' for archery, and not anything else.

<game name="xxx">
<attr name="turn" type="int">0</attr>
</game>
<object name="room">
<object name="player">
<object name="knapsack">
</object>
</object>
</object>
<turnscript name="global_turnscript">
<enabled />
<script>
foreach (object_x, ScopeInventory () ) {
if (not object_x.name = "knapsack") {
object_x.parent = knapsack // or: MoveObject (object_x, knapsack)
}
}
game.turn = game.turn + 1
</script>
</turnscript>

OurJud
Silver wrote:Well then surely the easiest way about it is to have the player start the game with a knapsack that can't be dropped and to change the inventory response to "you are carrying a knapsack which contains..."

That sounds great. My excuse is that I didn't know I could change the inventory response.

Having said that, is there a script which makes the player drop and take all? The one advantage of having it as a genuine container is because I have a scene in my game where the player hides all his equipment in a pile of boxes before entering a drug den, as he knows he will be body-searched (and would realistically probably have all his goodies stolen.

If I carry the items individually, it means scripting a long and laborious list of 'remove [item] from player' and then when he gets back outside and collects his bag, an equally long and laborious list of 'move [item] to player'. If I have a knapsack as a container, I only need say 'remove knapsack from player' / 'move knapsack to player'

HK, I will try that code as it sounds like just what I need. I won;t be doing it tonight cos I'm knackered, but just so I can be thinking on it, where does that code go?

jaynabonne
Just a note on HK's code (before you start): you don't need the "turn" attribute. You don't need to add it to the game object, and you don't need the line that goes

game.turn = game.turn + 1

That looks to be the leftover remnant of something else. You also can just compare object values directly, instead of going the name route. (See below.)

Just create a turnscript object, and put the script in there (using the GUI or whatever). Or just copy and paste this into code view, inserting just before the closing "</aslx>" tag:

<turnscript name="global_turnscript">
<enabled />
<script>
foreach (object_x, ScopeInventory () ) {
if (not object_x = knapsack) {
object_x.parent = knapsack
}
}
</script>
</turnscript>

If you have any trouble, it can easily be dropped into a library to be included.

HegemonKhan
GUI~Editor:

1. click on the most upper-left 'Object' on the left side's 'tree of stuff', so that it is highlighted.
2. at the top, in the bar, click on 'add', and choose ''Turnscript'
3. Add in the scripts...

-------

In Code:

actually to make this as simple as possible for you on where to put it, just put it directly after (under) your <game name="xxx">xxx</game>

<game name="xxx">
<attr name="turn" type="int">0</attr>
</game>

<turnscript name="global_turnscript">
<enabled />
<script>
foreach (object_x, ScopeInventory () ) {
if (not object_x.name = "knapsack") {
object_x.parent = knapsack // or: MoveObject (object_x, knapsack)
}
}
game.turn = game.turn + 1
</script>
</turnscript>

// blah, the rest of your entire game code


---------

oops, sorry Jay, as I wasn't sure whether the 'turn' Attribute was needed for the Turnscript to work (or execute~activate properly, at every ?turn? interval, I'm still not clear on how~when~why the Turnscript runs~activates~executes as it does) properly.

OurJud
Thank you, people. I think just dropping the code right in will be easiest.

I shall let you know tomorrow if it works.

jaynabonne
HK, it runs because it's a turn script and it's enabled. :) And I tried to simplify the code so he could just drop it in. The way you have it, it requires integrating the turn attribute into his existing game object, which seemed more effort than it was worth, since it wasn't needed anyway. He can't just drop it in under his game object. Eliminating that attribute makes it truly "dropin-able." (And an interesting trick, this turnscript, HK!)

HegemonKhan
what is the 'turn' (interval activator) then for the turnscript? every script that the game runs, causes the turnscript to then run, again?

I don't understand what with the underlying code sequence, is the 'tick' for how~when~why the turnscript executes repeatedly as it does.

jaynabonne
Turn scripts are fired automatically by the Quest engine after user input is processed. So when you input a command at the command prompt and it gets processed, the engine runs all enabled turn scripts before it goes idle again. (It also runs turn scripts whenever an ASLEvent is processed as well, which caused me grief for a while, but that's a rare case.) There is no "interval activator" for them. (I'm not really sure what that means, to be honest. But I don't think they have one.)

I hope that helps!

jaynabonne
Just to dive deep for a moment (OurJud - close your eyes!), there is a core function called FinishTurn, which is called after a player has had a turn, which basically means "when they have input a command and it has been processed". That core script, among other things, calls RunTurnScripts, which looks like this:

 <function name="RunTurnScripts">
if (IsGameRunning()) {
if (game.menucallback = null) {
foreach (turnscript, AllTurnScripts()) {
if (GetBoolean(turnscript, "enabled")) {
inscope = false
if (turnscript.parent = game or turnscript.parent = null) {
inscope = true
} else {
if (Contains(turnscript.parent, game.pov)) {
inscope = true
}
}
if (inscope) {
do (turnscript, "script")
}
}
}
}
}
</function>

In case you're curious, FinishTurn looks like this:
  <function name="FinishTurn">
RunTurnScripts
UpdateStatusAttributes
CheckDarkness
UpdateObjectLinks
</function>

OurJud
jaynabonne wrote:Just to dive deep for a moment (OurJud - close your eyes!)...

What you sayin', like?

OurJud
jaynabonne wrote:
Just create a turnscript object, and put the script in there (using the GUI or whatever). Or just copy and paste this into code view, inserting just before the closing "</aslx>" tag:

<turnscript name="global_turnscript">
<enabled />
<script>
foreach (object_x, ScopeInventory () ) {
if (not object_x = knapsack) {
object_x.parent = knapsack
}
}
</script>
</turnscript>

If you have any trouble, it can easily be dropped into a library to be included.

I don't have a </aslx> tag (I'm looking in my main game code?)

And HK's instructions on how to add it caused a 'failed to load game' error.

HegemonKhan
@Jay,

ya, that's what I was asking for, thank you. I couldn't think of somthing better than 'interval activator' at that moment in my post, lol. (wow, I just now thought of a good descriptor word, lol: 'trigger', hehe)

what about if you use the Verbs (Object buttons on right side) and hyperlinks, do those trigger the turnscript too? (as I'm not sure what are, or are all of, the ASLXEvents).

and thanks for the deeper code dive, I actually understand all of it (the undrelying code you gave), hehe, but, now... if I can just remember the order of 'FinishTurn'... that would be really useful... lol

--------

@OurJud:

open up your game file (using notepad, wordpad, or notepad++), remove~delete the turnscript block of mine or Jay's, and scroll down to the very bottom of your game file window, at the very bottom, you should have:

</asl>

re-paste mine or Jay's turnscript, so it looks like this:

(have the INDENTING be the SAME as shown below)

<asl version="550">
// the above is the very top of your game file
//(mass of rest of your code)
// the below is the very bottom of your game file
<turnscript name="global_turnscript">
<enabled />
<script>
foreach (object_x, ScopeInventory () ) {
if (not object_x.name = "knapsack") {
object_x.parent = knapsack // or: MoveObject (object_x, knapsack)
}
}
</script>
</turnscript>
</asl>

OurJud
Thanks, HK. Just followed that and tested it, and everything is going into the knapsack as requested :)

I can't find the post now, but you did say somewhere that if I wanted certain items to be excluded, you could fix that for me. I'm guessing it's the 'foreach (object_x, ScopeInventory () ) {' that needs changing, but I wouldn't know how.

jaynabonne
Verbs, commands, etc cause commands to be executed, just as if you had input them from the keyboard. So they cause turnscripts to fire as well.

What you sayin', like?


I just meant, "This is a tangent with some code unrelated to your question, so don't worry about it." :lol:

HegemonKhan
@Jay:

err.. I posted that without thinking, laughs. Ya, Verbs are~use Commands, I posted without thinking. Though, What are the ASLXEvents that you say also trigger the turnscript?

-----------

@OurJud:

yep, you got it almost, see here:

<asl version="550">
// the above is the very top of your game file
//(mass of rest of your code)
// the below is the very bottom of your game file
<turnscript name="global_turnscript">
<enabled />
<script>
foreach (object_x, ScopeInventory () ) {

// below is the area you'll want to work with in adding~changing what scripts you want, if you need help, if you just~only want to exclude more Objects, then I'll help you how to do that, or if you want to do other stuff, I can help too, but I need to know what you want done, to help you.

if (not object_x.name = "knapsack") {

// above is the area you'll want to work with in adding~changing what scripts you want, if you need help, if you just~only want to exclude more Objects, then I'll help you how to do that, or if you want to do other stuff, I can help too, but I need to know what you want done, to help you.

object_x.parent = knapsack // or: MoveObject (object_x, knapsack)
}
}
</script>
</turnscript>
</asl>


what the code (currently) does, in english:

(figuratively:taking) each Object, 1 by 1, in your inventory, if that Object's name is 'knapsack', then do *NOT* put it into your 'knapsack' Object (you leave it in your inventory), otherwise, put that Object into your 'knapsack' Object.

OurJud
jaynabonne wrote:Verbs, commands, etc cause commands to be executed, just as if you had input them from the keyboard. So they cause turnscripts to fire as well.

What you sayin', like?


I just meant, "This is a tangent with some code unrelated to your question, so don't worry about it." :lol:


I know, it was just my feeble attempt at a Geordie accent :D

HegemonKhan wrote:// below is the area you'll want to work with in adding~changing what scripts you want, if you need help, if you just~only want to exclude more Objects, then I'll help you how to do that, or if you want to do other stuff, I can help too, but I need to know what you want done, to help you.

Thanks, HK, it's really just aesthetics again, in that I don't think a person would carry certain things in their knapsack, namely (at this point in the game) the gun (gun) and a packet of cigarettes (cigarettes).

I would like to exclude those for now, and maybe others, but if you show me how to do it with one item, I'm sure I can exclude any other items I choose.

Silver
OurJud wrote:
I know, it was just my feeble attempt at a Geordie accent :D


Unfortuntely he isn't a Geordie. :shock:

OurJud
Silver wrote:

"OurJud"


I know, it was just my feeble attempt at a Geordie accent :D



Unfortuntely he isn't a Geordie. :shock:


Oooh, Newcastle Under Lyme :oops: :oops:

I'll get me coat!

Silver
Or Newcastle in Washington. Or someone who lived in Newcastle in Washington who moved to Newcastle under Lyme.

In unrelated news, the Cumberland Gap is near Middlesbrough. 15 miles. But I'm yet to find it.

http://youtu.be/jWA997xM9MI

HegemonKhan
@OurJud:

do you want to exclude groups~types (gun_group~type and cig_group~type) or just those 2 Objects only?

to exclude those 2 Objects only:

<asl version="550">
// the above is the very top of your game file
//(mass of rest of your code)
// the below is the very bottom of your game file
<turnscript name="global_turnscript">
<enabled />
<script>
foreach (object_x, ScopeInventory () ) {
if (not object_x.name = "knapsack" and not object_x.name = "your object1's name: ?gun?" and not object_x.name = "your object2's name: cigerette?") {
object_x.parent = knapsack // or: MoveObject (object_x, knapsack)
}
}
</script>
</turnscript>
</asl>


or, to exclude groups~types:

Set your Objects with an Attribute (String, Integer, Boolean, Object Type ~ Inherited, etc) to define it's group~type.

<asl version="550">
// the above is the very top of your game file
//(mass of rest of your code)
// the below is the very bottom of your game file
<turnscript name="global_turnscript">
<enabled />
<script>
foreach (object_x, ScopeInventory () ) {
if (not object_x.name = "knapsack" and not object_x.your_group_setting_Attribute_name = Value_depends_upon_Attribute_Type and not object_x.your_group_setting_Attribute_name and not object_x.your_group_setting_Attribute_name and not object_x.your_group_setting_Attribute_name and not object_x.your_group_setting_Attribute_name________etc_etc_etc) {
object_x.parent = knapsack // or: MoveObject (object_x, knapsack)
}
}
</script>
</turnscript>
</asl>


if you need help, let me know, if you're confused by anything, if you don't understand something, let me know.

OurJud
Thanks very much, HK. The first one does the job wonderfully :)

This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums