MQ2Data Introduction, Explanations, and Examples

General announcements relating to the modularized MacroQuest2 system.

Moderator: MacroQuest Developers

Lax
We're not worthy!
We're not worthy!
Posts: 3524
Joined: Thu Oct 17, 2002 1:01 pm
Location: ISBoxer
Contact:

MQ2Data Introduction, Explanations, and Examples

Post by Lax » Thu Apr 08, 2004 12:35 pm

MQ2Data is designed to be incredibly easy to use, and allow you much more flexibility than the old decrepit MQ2Parm system. It is also more intuitive and follows a non-programmer's perspective on things much more closely. For example, in the old system if you wanted to get a piece of information about something, you might have had to find the something, store some information about it, and then use the information with a completely different context in order to get your final result. MQ2Data on the other hand is all about context.

Say you want to know what direction to move to get to your target. With MQ2Parm, you would use "$target(headingto)" or "$heading($target(y),$target(x))". this would theoretically give you your heading in degrees (although it was counter-clockwise). Well, what if you wanted your heading as something like "north" "northeast" etc? You had to use "$target(direction)"... but isn't that just about the same thing? And why wasnt there a $direction? And why is $target the only thing you could get the direction to in that fashion? After all, your target is just a spawn... you'd have to target something just to get the direction to it in something other than degrees. Alright, to the point. MQ2Data looks at heading as an "object". You can determine some of this "object"'s properties. If you are heading 90 degrees on compass, you know you are heading due east, or 3 o'clock. With MQ2Data, you can take *any* heading and have degrees, clocks, short direction (N,NE,E), or long direction (north, northeast) just by using different properties of the object...
${Target.HeadingTo} will get you the default property of your "Target"'s "HeadingTo". HeadingTo is the direction you must travel to meet it. Let's break this down a little bit. "Target" is a top-level object. Top level object means it can be used alone in MQ2Data, or as the "top level" or "root". MQ2Data uses ${} to easily determine where the data begins and ends. ${Target} is valid, and will give the name of your target if you have a target, or NULL if you do not. It's not inherently obvious what will happen when you do ${Target} because it doesnt say "Name" in there. Every object type has a default behavior when it is the "tail" or last part of the requested data. This can be found by looking in the MQ2Data reference and finding the "To String" for the object type. Target is of type "spawn", this can be found by finding "Target" in the top-level object list in the reference. The "To String" for the "spawn" type says "Same as Name", so you know that if a spawn is the final part, the name of the spawn will be the result. "HeadingTo" is a "member" of the type "spawn". The reference says this:
...heading HeadingTo: Heading player must travel in to reach this spawn
This means that ${Target.HeadingTo} ends in the "heading" type. The "To String" for the heading type says "Same as ShortName", which means ${Target.HeadingTo} gives you the same thing as ${Target.HeadingTo.ShortName}. ShortName is a member of heading. Any time you need to access a "member" you use a period to separate the parent object from its member. Here's what the reference says for heading.ShortName (note that when describing a member of a given type -- not a specific object of that type -- the lower case name of the type is used, such as heading.ShortName):
...string ShortName: "S" "SSE" etc
This means that ${Target.HeadingTo.ShortName} is of the "string" type, and the "To String" for the string type says "... this IS a string, assface". If you're confused on that, this indicates that the result is the text contained by the string object. "string" just means "text".

Additionally, the string type has members of its own. Yes yes this might seem crazy, but consider that you might want to know something about the string itself. Maybe you want it lower case, maybe you only want part of it, maybe you only want to know how long it is, maybe you want to know if its the same as another string. All possible, directly from the string object's members. ${Target.HeadingTo.ShortName.Length} gets you the length of the short name of the heading toward your target. Want to determine if the direction is due north? ${Target.HeadingTo.ShortName.Equal[N]}... this brings us to the next topic, the "index" or actual "parameter". Some things do not vary, like Target.HeadingTo will never be Target.North, it will always be Target.HeadingTo. Some things do vary, like if you want a certain amount of the string, or a certain part, or you want to compare it to something else. For these, MQ2Data uses [] to contain anything that varies. Everything else is looked for *exactly*, but whatever is inside the [] is specific to the top-level object or member it is used on (and yes this implies that top-level objects like Spawn will use the brackets, not just members like string.Equal). Any time you use brackets, if the first thing inside is a quote, the last thing inside is also assumed to be a quote, and the two are stripped and ignored. You'll need to be careful with that, and keep in mind that you do not need to use the quotes at all with MQ2Data. ${Target.HeadingTo.ShortName.Equal[N]} is the same as ${Target.HeadingTo.ShortName.Equal["N"]}. Now on to string.Equal. The reference says this:
...bool Equal[text]: Strings equal? Case does not count...
This means that the string object is compared to whatever you gave it, and if the strings are equal not counting the case (so "NORTH" is the same as "north") the answer you would give to the question is "yes". This leads us to a type that is extremely easy to understand, yet seems scary to someone who looks at the word "bool" or "boolean" not knowing what it is. Like OMFG WHAT IS BOOL, IM GIVING UP THIS IS GREEK. All "bool" or "boolean" is, is the answer to a yes or no question (or true/false). The reference says this for bool's "To String": "TRUE" for non-zero, or "FALSE" for zero. All you really need to know is TRUE/FALSE. If the answer to the question was "yes", the result is "TRUE". So... ${Target.HeadingTo.ShortName.Equal[N]} equal? Yes, provided the short name is "N" or "n".

And this leads to yet another topic, although it is not directly a part of MQ2Data it is new and coinciding with the implementation of MQ2Data. The old "/if" had two different modes of comparison -- one for strings, and one for numbers. The new if (which is /newif until phase 3, at which time /if and /newif will be the same) only does numeric comparisons, and leaves string comparisons to MQ2Data. This leads to the question "are TRUE, FALSE, and NULL strings? or are they numbers?"... the answer quite simply is... both! They are converted during calculation routines to 1 or 0 (1 for TRUE, 0 for FALSE or NULL) if necessary. /newif really does a ${Math.Calc[conditions]}, and then ends up with a numeric result. This means that there IS no real "conditions", just a math operation. How then, you ask, do == != < > <= >= && || work with this system? They are very simple math operations, all resulting in what amounts to a bool. True or false. The questions are like so.. "is value A *EQUAL* to value B?" "is value A *NOT EQUAL* to value B?" "is value A *LESS THAN* value B?" and so on up to "is value A non-zero AND value B non-zero?" and "is value A non-zero OR value B non-zero?". Therefore the answer to 1==0 is false, because 1 is not 0. The answer to 1>0 is true, because 1 is greater than 0. The answer to 1&&0 is false, because there is a zero. The answer to 1||0 is true, because there is a one. And for the normal math stuff, thats obvious... 1*2 is 2, 1+2 is 3, etc. I hope I dont need to teach you that. All of this is mostly explanation of upgrades to the calculation routines, not to /newif in particular. Calc also supports parentheses, multiple operations, etc. smoothly, whereas previously you may have had to use extra calcs to find your result. Now back to /newif. Essentially all /newif is looking for is zero or non-zero as the result of a calculation. This means that /newif 0, /newif 43531, /newif TRUE, /newif FALSE, /newif NULL are all probable end results (note that TRUE, FALSE, and NULL get replaced by 1.00, 0.000 and 0.00 respectively during the calculate step, but I wrote them normally here for demonstration that it will work) and .. will work. /newif whatever /echo hi, is the same as /newif ${Math.Calc[whatever]} /echo hi.. so to determine the result, you can /echo ${Math.Calc[whatever]}. If the result is 0, the false branch will be executed by /newif.

This is a fairly complete explanation of everything, so how about some examples for you to help you along a bit.

${Spawn[gm].ID} - Searches for a gm, gets spawn ID (NULL if the spawn was not found)
${Target.X} - Target's X coordinate (NULL if no target)
${Me.CurrentHPs} - Your current hit points
${Me.PctHPs} - Your current hit points like 100.00
${Me.PctHPs.Deci} - Your current hit points like 100.0
${Me.PctHPs.Int} - Your current hit points like 100
${Me.Buff[1]} - The name of the buff in your first buff slot
${Me.Buff[1].Duration} - The duration in ticks (6 seconds per tick) of the buff in slot 1
${Me.Buff[Spirit of Wolf].Duration} - The duration in ticks of Spirit of Wolf, if this buff is on you
${Me.Buff[Spirit of Wolf].Duration.Time} - The duration in mm:ss of Spirit of Wolf, if this buff is on you, like 60:00
${Target.Class} - Target's long class name, like Cleric
${Target.Class.ShortName} - Target's short class name, like CLR
${Float[12.345].Deci} - The number with decimal precision of tenths, so 12.3
${Float[12.3456789].Precision[4]} - The number with 4 places after the decimal point, so 12.3457 (rounded!)
${Math.Calc[1+2*2+1]} - 6
${Math.Calc[(1+2)*(2+1)]} - 9
${Group[1]} - Name of the first player in your group
${Group[1].CurrentHPs} - Current hit points of the first player in your group (note: for all spawns other than yourself, you only know their PERCENT hit points, so this will be a number up to 100)
${Group[1].HeadingTo.Degrees} - Compass heading to reach the first player in your group
${Spell[Spirit of Wolf].Duration} - The normal duration of this spell
${Spell[Spirit of Wolf].MyCastTime} - The amount of time it would take you to cast this spell
${Me.Buff[1].MyCastTime} - The amount of time it would take you to cast this spell! (note: MyCastTime is not a member of "buff" itself, but is inherited from "spell". This means you can use any member of "spell" from "buff")
${Me.Gem[1]} - The spell in spell gem #1
${Me.Gem[Spirit of Wolf]} - The gem #, if any, that this spell is in
Lax Lacks
Master of MQ2 Disaster
Purveyor of premium, EULA-safe MMORPG Multiboxing Software
* Multiboxing with ISBoxer: Quick Start Video
* EQPlayNice, WinEQ 2.0