Wearables and cloned items

Pykrete
05 Jul 2016, 15:09

Not sure if I should post this here or make a post in one of the wearable library topics; apologies if this isn't the right place.

In either the Extended Wearables Library or the Alternate Clothing Library, is there any way to remotely manage cloned items?

For example, say I'm just using 1 'slot', which is body. One of my characters has 'casual clothing' on. A possible event leads to them being put in jail, which would require removing that 'casual clothing' and putting them in 'orange jumpsuit'. This is easy enough - 'Do Remove' with the parameter 'casual clothing', and then 'DoWear' with the parameter 'orange jumpsuit'. Furthermore, I can make a function to check if they're wearing something else; say, 'business suit', or the rest of the potential clothing, and then have it only attempt to remove that one object instead of all of them.

So far so breezy, but problems arise when my objects are cloned...

In this example, the character has bought their clothing from a store. 'casual clothing' and 'business suit' were both bought, and because I want there to be more than 1 instance of these objects, they've been cloned rather than simply moved. This works out fine, right up until I run into a situation like above where I need to use DoRemove and DoWear. Attempting to 'DoRemove' 'casual clothing', when the object in question is actually a clone, results in nothing happening. Ditto for trying to 'DoWear' a clone of the orange jumpsuit.

Is there any way around this, short of making a huge function with 'if casual clothing1, if casual clothing2, is casual clothing3', etc...'? That would be a massive pain to do. Is there a way to do, say, Remove Body, to remove whatever is being worn in a certain slot? If not, would that be possible to implement on my end?

I'm not sure how to go about applying cloned clothing, either. Removing it could be handled by removing anything in a certain slot, but adding it... eesch. I don't even know where to begin.

Any help would be appreciated.


hegemonkhan
05 Jul 2016, 17:21

Pixie and others probably have better solutions, but here's a way of doing it (not sure how to implement this into/with the library/ies you're using though):

when you clone something and due to that the 'name' String Attribute is the ID for quest, it has to give your cloned Objects different names, which it does by adding numbers to its name.

the way around this, is to use the String/Text Manipulation Functions:

http://docs.textadventures.co.uk/quest/functions/ (scroll down to the very bottom, to the 'String Functions' section/category)

where you can check the Object's name, such as using the 'StartsWith', as your cloned Objects look like this, for examples:

original Object's Name: potion
cloned Objects' Names: potion1, potion2, etc ect etc

thus by checking if the start of their name is "potion", then you got a script that'll work:

if (StartsWith (this.name, "potion")) {
  // 'whatever' Script(s)
}

another method, would to be give your Object an 'indicator/flag' Attribute, which you can check:

<object name="potion">
  <attr name="type_of_object_string_attribute" type="string">potion</attr>
</object>

<object name="apple">
  <attr name="type_of_object_string_attribute" type="string">food</attr>
</object>

if (GetString (this, "type_of_object_string_attribute") = "potion") {
  // 'whatever' Script(s)
}

as, the clones will also have this same indicator/flag Attribute too.


Pykrete
05 Jul 2016, 17:58

Hey, HK.

That's some pretty useful info, thanks. Unfortunately, while it's great for detecting these cloned items, I don't know if it'll be much use in pinpointing them for the Wear/Remove functions, unless I'm missing something.

The library I need to work with is either the Extended Wearables Library or the Alternate Clothing Library. Alternate Clothing Library is the original, which I'm currently using with some tweaks, and the Extended Wearables Library is a version Pixie made with some extra functions and tweaks (among them, the ones I had to make. I've not upgraded as I don't need the other functions, but the option is there.)

Both function more or less the same, aside from those tweaks and additional functions. Wear and Remove are used to put on and take off an article of clothing or gear on the current game.pov.

DoWear and DoRemove, when pointed to an item in the parameters section, perform these functions automatically/remotely. For example, as long as the character has the 'orange jumpsuit' in their inventory and isn't wearing anything else, DoWear (orange jumpsuit) would run the Wear function, including the 'after wearing' script and the 'message to display when worn' bit, allowing attribute changes to be made normally and for my own scripts to be run in turn. Conversely, if the character is already wearing something, it won't work.

In turn, DoRemove (orange jumpsuit) will remove the orange jumpsuit and run the appropriate scripts that follow that event, if any.

My problem, then is trying to pinpoint DoWear or DoRemove to cloned objects, instead of the original. (this is non-negotiable - I have multiple characters to play as, and multiple versions of the same clothing, gear and/or weapon are a must.) I can make a long long list for every piece of gear for every potential duplicate up to a point... but that's obviously not ideal. I need a way of scripting it so that it can either pinpoint, say, 'orange jumpsuit2' or 'orange jumpsuit5', or a way of looping through until it finds the right one to Remove.


hegemonkhan
05 Jul 2016, 18:30

I don't know the libraries (too lazy to open them up and study them, at the moment, lol), but you'll have to insert the stuff in my post into them (such as probably the 'DoWear' and 'DoRemove' Functions), but unless you know what you're doing, I'd wait for Pixie (or whoever else) to help you, and he/she may have better methods than mine, anyways.


Pykrete
05 Jul 2016, 18:32

Noted, thank you for your time.


hegemonkhan
05 Jul 2016, 19:13

would this be soemthing like to what you need:

(using a 'potion' Object as an example)

foreach (object_variable, AllObjects()) {
  if (StartsWith (object_variable, "potion") and object_variable.parent = game.pov) {
    // do whatever script you want with this/these cloned potion Object/s in your inventory
  }
}

// or:

foreach (object_variable, AllObjects()) {
  if (GetString (object_variable, "type_of_object_string_attribute") = "potion" and object_variable.parent = game.pov) {
    // do whatever script you want with this/these cloned potion Object/s in your inventory
  }
}

or, do you want/need the opposite, searching through your inventory (of your cloned objects) and you want to do actions upon the original object?

could you explain more in terms of exactly what you need (as I'm too lazy to study the libraries you're using), as that would help me in trying to be able to help you.


Pykrete
05 Jul 2016, 19:56

Sorry man, but if I knew exactly what I needed, I don't think I'd be having this trouble. The best way I can explain it is that I need a way to automatically set the parameters for DoRemove and DoWear, as I can't set them manually on cloned objects. If you've explained a way to do that, I'm afraid it's beyond my understanding as a novice scripter.


The Pixie
05 Jul 2016, 20:41

In this example, the character has bought their clothing from a store. 'casual clothing' and 'business suit' were both bought, and because I want there to be more than 1 instance of these objects, they've been cloned rather than simply moved. This works out fine, right up until I run into a situation like above where I need to use DoRemove and DoWear. Attempting to 'DoRemove' 'casual clothing', when the object in question is actually a clone, results in nothing happening. Ditto for trying to 'DoWear' a clone of the orange jumpsuit.

As HK says, clones get a new name, as every name has to be unique. If you do DoRemove (orange jumpsuit), then it will try to remove the original, which I guess is still in the shop.

The trick is to use a stand-in for the orange jumpsuit object, something that represents it, whichever one it is, i.e., a variable containing the object. The question then is, how do you make sure the variable is pointing to the right clone? If you look in the libraries, the commands use object as a variable. For all Quest commands, this is the matched object. the player types WEAR JUMPSUIT, and Quest matches that to an object in the vicinity.

I am not sure quite what your code is, but it seems likely that what you want to do is:

DoRemove (object)

By the way, a good way to check what the clone is is to give the original an alias, say "orange jumpsuit", and then in you code test to see what the alias is - unlike the name, the alias will be the same.

if (object.alias = "orange jumpsuit") {
  msg("You are wearing an orange jumpsuit")
}

Pykrete
05 Jul 2016, 21:52

Yes, if I just do DoRemove (orange jumpsuit) then the original would be removed, naturally. So what I'm looking for is a way to tell Quest it needs to remove the right clone, which could be (orange jumpsuit1), (orange jumpsuit7), etc.

'DoRemove (object)'

Ok, that seems about right. How do I tell Quest what to set (object) to? Is that a variable I can adjust on my end? Or is there a variable I can adjust which in turn adjusts that?

When a character wears an object, does it alter any variables outside of the ones it alters on the object itself? In essence, is there an attribute on the character or somewhere else that gets updated, which I can just hook into for 'if thing.thing = x then blah blah'?


bergedorfcacher
06 Jul 2016, 04:40

A disclaimer first: I'm a total quest beginner (though not a total coding beginner), so possibly what I say may be totallly beside the point. :-) If that's the case I apologise in advance.

How about writing a wrapper function for DoRemove? Let's call it DoRemoveClone(object):

DoRemoveClone(object)

Find an object that the player is actually wearing with alias = object.alias and call that wornobject
call DoRemoveClone(wornobject)

Wherever you wanted to use DoRemove(object) before, now use DoRemoveClone(object).

In case I have understood your problem and quest correctly (however unlikely that might be), the problem boils down to implementing 'find an object that ...'. I'd hope there is some list you can iterate over for that.


The Pixie
06 Jul 2016, 08:21

Pykrete, it depends on how you are using DoRemove. Is it in a command? If so, then the object variable should already by pointed to the right clone. If not, then give us some details, and we can try to solve it

bergedorfcacher, that is probably the way forward. This code might work, assuming Pykrete gives the objects you will clone an alias.

foreach (obj, ScopeInventory()) {
  if (object.alias = obj.alias) {
    result = obj
  }
}
if (not result = null) {
  DoRemove(result) 
}
else {
  msg("You're not wearing that.")
}

Pykrete
06 Jul 2016, 10:57

It's not in a command, no. My 'strip' and 'force wear' are separate functions, called upon once a character progresses far enough in the story. So, they enter a room, story stuff happens, and they wake up in a prison, with the functions called in order before they wake up - at the end of the first room, before the next one is moved to.

So my original plan was just to have a 'strip' function to remove any possibly clothing they might have on, and then a 'force wear' function to place the appropriate clothes on them automatically.

In the code you posted above, is that something I need to fill in the blanks for, or, theoretically, might it work 'out of the box', so to speak?


The Pixie
06 Jul 2016, 13:42

Should work out of the box.

There may be better ways in your situation, however. To strip the player, go through his inventory and destroy any worn item (or move to another location, and set "worn" to false). When putting on the orange jumpsuit. you should be able to get the object from the clone function.

foreach (obj, ScopeInventory()) {
  if (GetBoolean(obj, "worn")) {
    destroy(obj.name)
  }
}
ojs = CloneObjectAndMove(orange jumpsuit, player)
ojs.worn = true

Pykrete
06 Jul 2016, 14:14

Tried to run that as seperate function, and as a verb on a piece of clothing to be removed. Both instances give me this error;

' Error running script: Error compiling expression 'object.worn': Unknown object or variable 'object' '

One thing that might be bringing up an issue here is that the characters I'm trying it on aren't the original 'player' object. Perhaps, anyway.

The same thing happens with the first bit of code you posted, though with a different error message.

' Error running script: Error compiling expression 'object.alias = obj.alias': Unknown object or variable 'object' '

In both instances, Quest seems pretty adamant that 'object' isn't a thing... hmm.

I feel like we're definitely almost there! But I'm not sure if I'm messing something up here, causing Quest to go 'object? What's that?'


The Pixie
06 Jul 2016, 14:59

Sorry, my bad. Should be "obj". Also, it now uses GetBoolean, which is safer, as some things will not have the "worn" attribute.


Pykrete
06 Jul 2016, 15:35

Aha! Perfect, perfect. That works like a charm. I don't want the items destroyed, so I'll just move them instead, after setting 'worn' to false.

However, when my items are equipped and unequipped, I use those events to change stats on the current game.pov for RPG purposes. So, now I need a way of finding out what clothing they were wearing, so I can subtract the appropriate bonuses added earlier. Hmm...

So I need a list that checks to see what the alias of the item that got removed was. How might I go about that?

And thank you very much for your time, by the way. Appreciated muchly!

Edit: So, if I add a 'if obj.alias = "casual clothes (worn)", for example, I can then remove the status alterations made when it was put on, and reclone the object to place it back in either the player's inventory, or move it elsewhere. Excellent! Destroying the object also gets rid of the issue of trying to undo all the alterations made when it's worn. Destroying and recloning it is... well, it's a little 'shock and awe' when you think about it, but it works.

In turn, I can force equip the new gear, assign the stats required, and change the alias and 'worn' to be correct so it'll play nice with the normal system. I think - knock on wood - that that's me sorted.


The Pixie
06 Jul 2016, 20:36

However, when my items are equipped and unequipped, I use those events to change stats on the current game.pov for RPG purposes. So, now I need a way of finding out what clothing they were wearing, so I can subtract the appropriate bonuses added earlier. Hmm...

In the loop:

foreach (obj, ScopeInventory()) {
  if (GetBoolean(obj, "worn")) {
    obj.parent = limbo
    obj.worn = false
    // change any stats due to obj here
  }
}