//For QuestJS v0.3
function isWearing(char,obj){
//char should be the object who can wear obj
var worn = (obj.getWorn() && obj.loc===char.name)?true:false
return worn
}
Imagine a game with a wearable object named "mask".
In the JS code, the mask is referred to as: w.mask
.
The default player object is set to w.me
, but I prefer to take the advice of mrangel and use game.player
in my code (just to make sure the code targets the actual player object, which is not always w.me
).
if (isWearing(game.player,w.mask)){
//The current player object is wearing the object named "mask".
//Do (or don't) stuff!
}else{
//The current player object is NOT wearing the object named "mask"!
//Do (or don't) do stuff!
}
I plan to add more custom code to this thread.
All comments and suggestions welcomed!
//I created this to help user 'Dakin Quelia' on the forum, and I find it useful.
// http://textadventures.co.uk/forum/questkit/topic/cvlcnikvo0oj3bt8nqsnig/solved-about-questjs-list-of-functions-avalaible-for-items-rooms
//This returns an object (aka dictionary).
//It only needs the obj argument: listItemAtts(obj)
//A true arg can be added to print data in-game as well: listItemAtts(obj,true)
// (Adding a false boolean arg is not necessary, as that is the default.)
//UPDATED 2020.12.4
function listItemAtts(obj,pt=false){
//IF pt is true, the properties will be printed in-game via msg()
var keys = Object.keys(obj);
var txt = '';
var a = 0;
keys.forEach(key => {txt+=a.toString() + ": " + keys[a]+"<br/>";a++;})
if(pt) { msg(obj.name + " PROPERTIES:");msg(txt);} //pt is false by default
return keys;
};
//Returns a list of objects comprised of all world (w) objects.
function allObjects(){
var arr = listItemAtts(w) //Create list of names of all objects in w object
arr.splice(arr.indexOf("game"),1) //Remove the game object
//arr.splice(arr.indexOf("me"),1) //Remove the default player object
//arr.splice(arr.indexOf("background"),1) //Remove the background object
var scriptArr = [] //Create temp array to hold scripts
arr.forEach(a => {if(typeof(w[a]["eventScript"])==='function') scriptArr.push(a)}) //Find the turnscripts
arr = array.subtract(arr,scriptArr) //Remove the turnscripts
//arr.forEach(a=>{console.log(a)}) //Debugging purposes
var arrTwo = [] //Create the actual array
arr.forEach(a => {arrTwo.push(w[a])}) //Use objects' names to add actual objects to arrTwo
return arrTwo
}
This is my Quest 6 equivalent of AllObjects.
It works the same. It returns an objectlist of all in-game objects.
NOTE
There may be an existing function that does this, but I couldn't find one after a good few minutes and decided it would be faster (and more fun) to make my own.
IMPORTANT NOTE
This requires my listItemAtts function!
NOTE
There may be an existing function that does this, but I couldn't find one after a good few minutes and decided it would be faster (and more fun) to make my own.
Top of my head:
function allObjects(){
return Object.keys(w).filter(x => (x !== "game" && typeof(w[x]["eventScript"])!=='function')).map(x => w[x]);
}
Dude...
.map(x => w[x])
is freaking awesome! I can use that to make another function much more efficient.
Thanks, mrangel!
I'm a little curious about this in your isWearing
:
var worn = (obj.getWorn() && obj.loc===char.name)?true:false
Is there a reason for the true and false at the end?
It seems to be an additional operator which has (almost) the same effect as:
var worn = (obj.getWorn() && obj.loc===char.name);
If you're worried that getWorn might return values that count as false but aren't boolean (such as zero or an empty string), the standard way to force a value to a boolean would be:
var worn = !!(obj.getWorn() && obj.loc===char.name);
I'm a little curious about this in your isWearing:
I'm just winging it. I know enough JS to be dangerous, is all.
Ha!
But, hey! The !!
is new to me, too! That will also negate numerous lines of my code!
But, hey! The
!!
is new to me, too! That will also negate numerous lines of my code!
If you're using it a lot I would be worried. In 99% of circumstances, there is no need to care about whether a value is boolean true
or another truthy value.
In fact, !!
is just the !
operator (logical not) twice. Putting !
before any truthy value gives false
, and putting it before any falsey value gives boolean true
, so using it twice can convert truthy to true
and falsey to false
.
I should have posted this in this thread, I guess.
Object.prototype.isWearing = function(obj){ return (obj.getWorn() && obj.loc===this.name)};
With that code (which pretty much came from mrangel), this can be done with any game object:
if (w.Ralph.isWearing(w.facemask))
OR
var vestWorn = w.Norton.isWearing(w.vest)
If you're using it a lot I would be worried.
Yeah, I played around with it a little and decided against using it liberally. It's still a nice trick to know, though!
This is in my settings.setup
:
//MODIFY 'ABOUT' COMMAND to include 'info' and 'information' (for old INFOCOM-heads, like me)
findCmd("MetaCredits").regexes = [/^info$|^information$|^about$|^credits?$|^version$/];
Yeah, I played around with it a little and decided against using it liberally. It's still a nice trick to know, though!
I have to wonder, why do you need it? Does the engine use type-based control somewhere? There are very few booleans in JS.
(The guy who showed me the !!
trick put it as "If you need to convert to boolean, there's probably a serious problem with your design. But here's how to do it.")
I have to wonder, why do you need it?
I was thinking about things that "might return values that count as false but aren't boolean (such as zero or an empty string)", but I quickly realized using !!
probably wasn't a good idea.
A lot of boolean functions actually return a value that you can treat as a boolean. (although JS doesn't do this quite as much as Perl does). A lot of people use them without even knowing.
In general, it's best to leave these values as the type they come out as; because once you get into more advanced coding you might learn why that value is useful.
!! is useful if you need a real boolean, but there are very few situations where a boolean value is needed. These can mostly be grouped into 3 classes: where you're passing it to a badly designed function, where the value is going out of your program (save file or over the network), and where it matters for reference counting.
Some random examples of things you might expect to return a boolean which don't:
a && b
is actually the same as a ? b : a
, and a || b
is treated as a ? a : b
.
Seems some people thing that using .match()
on a string returns true if the string matches the regex. For example, mystring.match(/\b\w{4}\b/g)
will return true if the string contains any four letter words. In fact it returns an array of all the four-letter words in the string; but if you treat that result as a boolean, it will do exactly what you want.