View Full Version : zMUD Wound/Scar Indicator
Martaigne
04-13-2007, 01:20 PM
I'm now attempting to create the wound/scar indicator in zMUD. This is the toughest part of the front-end to create. I've looked at Lich's source (thank you for making it open-source!) in an attempt to adapt the functions to zMUD, but since my programming experience is mainly in VB-derived languages, my eyes are bleeding looking at this stuff.
This clip came from a piece of documentation given to me to translate the status strings sent to the Wizard:
'GSV0000000169000000016900000000100000000010000000 0185000000018500083886080000000000' This monster is, in order: max health, current health, max spirit, current spirit, max mana, current mana, wounds, scars. The individual tags are only sent when values change; this is mostly used to set your meters at login -- unnecessary to pay attention to it after that, since the individual tags are always sent if a value changes.
'GSa0008388608' Wounds. I don't want to bother with a detailed explanation... convert it from decimal to binary, and every body part gets 2 digits: 00 = none, 01 = rank 1, 10 = rank 2, 11 = rank 3. See Lich source if you really need the info, the list of what digits hold what body part's info are directly after the line 'class Status'
'GSb0008388608' Identical to wound info, but refers to scars.
Okay, easy enough... right? I took this advice and looked up the class in the Lich source (if it's a problem for me to post this here please let me know and I'll remove it, being that it's open source I didn't foresee any issues):
class Status
@@head = -2..-1
@@neck = -4..-3
@@rarm = -6..-5
@@larm = -8..-7
@@rleg = -10..-9
@@lleg = -12..-11
@@rhand = -14..-13
@@lhand = -16..-15
@@chest = -18..-17
@@abs = -20..-19
@@back = -22..-21
@@reye = -24..-23
@@leye = -26..-25
@@nerves = -28..-27
SFMAP = Hash[ 'nsys', 'nerves', 'leftArm', 'larm', 'rightArm', 'rarm', 'rightLeg', 'rleg', 'leftLeg', 'lleg',
'rightHand', 'rhand', 'leftHand', 'lhand', 'rightEye', 'reye', 'leftEye', 'leye', 'abdomen', 'abs',
]
def Status.method_missing(arg)
arg = arg.to_s
arg =~ /scar/ ? tag = "GSb" : tag = "GSa"
instance_eval("dec2bin($_TAGHASH_[tag].to_i).to_s[@@#{arg.slice(/head|neck|rarm|larm|rleg|lleg|rhand|lhand|chest|ab s|back|reye|leye|nerves/)}]",
if Script.self then Script.self.name else "Lich" end)
end
def Status.rank(val)
bin2dec(val.to_i)
end
def Status.sf_update(area, rank)
range = Status.class_eval(sprintf("@@%s", SFMAP.fetch(area) { |query| query }))
if rank =~ /Injury/i
tag = [ 'GSa' ]
elsif rank =~ /Scar/i
tag = [ 'GSb' ]
else
tag = [ 'GSa', 'GSb' ]
end
tag.each { |t|
buf = sprintf("%028b", $_TAGHASH_[t].to_i)
buf[range] = dec2bin(rank.slice(/\d/).to_i).to_s[-2..-1]
$_TAGHASH_[t] = sprintf("%010d", sprintf("0b0%s", buf))
}
end
end
Can anyone actually read this and help me figure out what it's doing? Thanks in advance.
Celephais
04-13-2007, 02:15 PM
Yeah I've no idea what Lich is don't, haven't used it, but getting your injuries out of the string is pretty easy, it's just a bitmask.
Just mod the value to get if a flag in the mask is flipped... I forget how zMud lang works but this would be it in VB...
WoundDecimal = %GSa% ' (or however you get the GSL tags in zMud)
Dim intHeadWound as Integer = 0
Dim intNeckWound as Integer = 0
If CBool(WoundDecimal mod 2 > 0) then
intHeadWound = 1
WoundDecimal -= 1
End If
If CBool(WoundDecimal mod 4 > 0) then
If intHeadWound = 0 then
intHeadWound = 2
Else
intHeadWound = 3
End If
WoundDecimal -= 2
End If
If CBool(WoundDecimal mod 8 > 0) then
intNeckWound = 1
WoundDecimal -= 4
End If
If CBool(WoundDecimal mod 16 > 0) then
If intNeckWound = 0 then
intNeckWound = 2
Else
intNeckWound = 3
End If
WoundDecimal -= 8
End If
and so on... keep raising the number to powers of two, down the list of wound areas.
Woops, forgot the -= part... that's important.
Martaigne
04-13-2007, 02:36 PM
Just posting this for information, I found it on the Zuggsoft forums:
GSa (int) Informs the wizard of the presence of any wounds (info is used in the injuy window and the paperdoll). This tag is sent to the client when any change in the state of your wounds occurs (add, upgrade, and remove).
The int parameter is a bitfield converted into decimal form. A bitfield is best thought of as a binary number in which each digit has a special meaning, like an array of true/false (1/0). To convert the bitfield into decimal, just treat it like a regular binary number instead of an array of 1/0.
Each bit, digit, place value, or whatever you want to call it indicates the presence (1) or absence (0) of a specific wound.
Known fields (woefully incomplete):
2^ 0 = head 1
2^ 4 = right arm 1
2^ 5 = right arm 2
2^ 6 = left arm 1
2^10 = left leg 1
2^18 = stomach 1
2^20 = back 1
GSb (int) Indicates the removal of a specific wound. The parameter works exactly as in GSa. This tag is sent every time a wound is removed, but not when a wound is upgraded (you can't have both a head 1 and a head 2 wound - the wizard overwrites the old wound with the new one in the graphic display, so there is no need to manually remove the old wound).
Martaigne
04-13-2007, 05:23 PM
Ow... my head...
Celephais
04-13-2007, 05:56 PM
That information you posted doesn't refute what I posted, all you've got to do is convert it from VB to ZMud... and use the list posted from your original to add the other locations (so I showed head and neck, keep going with...)
@@head = -2..-1
@@neck = -4..-3
@@rarm = -6..-5
@@larm = -8..-7
@@rleg = -10..-9
@@lleg = -12..-11
@@rhand = -14..-13
@@lhand = -16..-15
@@chest = -18..-17
@@abs = -20..-19
@@back = -22..-21
@@reye = -24..-23
@@leye = -26..-25
@@nerves = -28..-27
ignoring the -2..-1 crap, and just keep increaseing the numbers (I'll go back and bold them) by doubling them (power of two)
Shaelun
04-14-2007, 07:20 AM
Er... Kharok had the right idea, but I believe his information is "inaccurate." GSa is sent in full anytime your wounds change (there's no "upgrade/remove/add/whatever" business about it). GSb is identical, but for your current scars. And it's entirely possible to have "head 1" and "head 2" wounds at the same time. That would indicate "head 3." Here it is in plain English:
Let's take a real-life example: 'GSa0008388608'. In binary, that number is '100000000000000000000000'. The first 2 digits (er, the last 2 from an "English" perspective; the ones at the far right are the "first" in binary) refer to "head" -- that's what the "@@head = -2..-1" means; it's the offset of the digits (negative being from the end, not the front... -1 is the last number, -2 is the second-to-last, etc.).
Split that into groups of two and you have "10 00 00 00 00 00 00 00 00 00 00 00". The first two is your head. "00" means no wound (or no scar), "01" means rank 1 (in binary 01 is a decimal 1), "10" means rank 2 (in binary "10" is 2), and "11" is rank 3 (again, in binary, 11 is a decimal 3).
So, this GSa tag means the character has no wounds, except a rank 2 right eye wound. That's assuming I used a literal, real-world copy/paste in my text document (I think I did, but it's been almost 2 years since I wrote half the stuff in/about Lich).
An identical GSb tag would mean a rank 2 right eye scar, instead of a rank 2 right eye wound. You can easily have both. Again, there's no sort of updating or changing (the value sent each time is absolute, not to be added to previously sent data or some such), and it isn't just a bitfield/bitflag "true/false" boolean thing.
Presumably Kharok wasn't familiar with GemStone's wound system, and understandably mistook the data. So does programming sound fun yet...!?! Oh, and of course it isn't a problem for you to post my code here.
Now when you see those geeky shirts that say There are 10 kinds of people: those who get binary, and those who don't you can laugh too!
Shaelun
04-14-2007, 08:06 AM
Incase you want to know how to just access the bit in a specific location w/o converting...
(8388608 >> 22) & 1 would be logically true (as in return 1) if bit position 22 were a 1. If it were a 0, it would return 0. The '>>' is a "binary bit shift" operator, google should explain just fine. '&' is a "binary bitwise" AND operation (again, google is a fabulous teacher -- hence my quotations). You could just use a whole mess of complicated if/elseif checking, and test all of the 28 bits one at a time.
If you can't convert from decimal (base 10) to binary (base 2), perform a modulo (% or "mod") operation, or at the very least perform bitshifting and bitwise operations, it's going to be a thoroughly challenging little logic puzzle (that I'm leaving to someone else to play with).
G'luck.
TheEschaton
04-14-2007, 09:01 AM
God, I love binary. Brings back memories of my computer programming degree. Hex is even more fun.
-TheE-
Martaigne
04-14-2007, 09:55 AM
My lack of response in this thread wasn't due to confusion, it was due to me concentrating on this script... it's actually a challenge compared to all the others. As a web development programmer, I've never had cause to break into modulus math or binary, so this is sort of new to me. What I'm doing though, is converting from decimal to binary, then padding the binary figure with zeros to extend it to the proper 28 digits. zMUD didn't have a native method to convert to binary, so with the help of the guys on the zuggsoft forums, I've got these to help out:
#FUNC dec2bin {%if("%1"!="0",%concat(@dec2bin(%eval(%1/2)),%mod(%1,2)))}
#FUNC extendbin {%concat(%repeat("0",28-%len(%1)),%1)}
The first, obviously, converts the value to binary, the second pads the left side with zeroes. After that, it's super easy to loop through and pull the wound/scar bits.
Making these functions helps because I can call them at any time, so when I need to pull wound/scar info upon login, I can apply them to the values pulled from GSV:
#VAR StartWounds {@extendbin(@dec2bin(%left(%right(%gsl(V), 60),10)))}
#VAR StartScars {@extendbin(@dec2bin(%right(%gsl(V),70)))}
And when GSa is thrown:
#VAR NewWounds {@extendbin(@dec2bin(%gsl(a)))}
And when GSb is thrown:
#VAR NewScars {@extendbin(@dec2bin(%gsl(b)))}
Then it's just a matter of pulling out pairs of characters according to position, using Lich as a guide (thank you Shaelun), and assigning them to seperate variables for the client to keep track of.
I still haven't decided on the display, though. I flat-out refuse to use bitmaps as it causes issue with portability and longevity. It'll probably end up looking a lot like the compass.
Thanks guys, for all of your help, feedback, and patience thus far.
Oh, and as a reference, Kharok's post was from 2002, before zugg even incorporated the GSL language into zMUD.
Martaigne
04-14-2007, 02:59 PM
Success! Here's a screenshot, though I warn you, it's not too pretty:
> health
You have minor bruises about the head, and minor bruises on your neck.
You have several facial scars, and a black-and-blue right eye.
http://www.martaigne.com/images/zmud2.gif
Right now I'm in the process of deciding whether or not to make the indicators gauges to show the severity or not, and whether or not to turn the caption into a clickable button to toggle between view of injuries or scars, rather than putting them side-by-side. Comments, opinions?
Shaelun
04-14-2007, 04:08 PM
Well first of all, congrats :)
With zMUD, is changing the color from green to orange to red or something to represent rank feasible? Would certainly make it more "at-a-glance" friendly (and give more room to spell out the bodypart). Incase you haven't thought of it, both wounds and scars hinder or prevent casting: only allowing for the display of one or the other would irk me.
Out of curiosity, by "portable" do you just mean it's too much of a hassle for anyone other than you, or that zMUD actually supports more than just Windows platforms?
TheEschaton
04-14-2007, 04:09 PM
I think you should consider the graphical thing, despite your dislike of bitmaps. Parsing numbers and abbreviations for body parts is not as easy as looking at a body diagram.
And would definitely choose to toggle between the two - or make a combo thing, where scars are overlaid by wounds, which could be done in your present combo by having purple squares under the maroon ones, with a neutral color for nothing.
-theE-
Martaigne
04-14-2007, 09:01 PM
Well first of all, congrats :)
With zMUD, is changing the color from green to orange to red or something to represent rank feasible? Would certainly make it more "at-a-glance" friendly (and give more room to spell out the bodypart). Incase you haven't thought of it, both wounds and scars hinder or prevent casting: only allowing for the display of one or the other would irk me.
Out of curiosity, by "portable" do you just mean it's too much of a hassle for anyone other than you, or that zMUD actually supports more than just Windows platforms?
Thanks. :)
Yes, I plan to change the colors a bit to dictate severity of injury. I think I may make them gauges, as well, with the full limb name label, and the number. Can't hurt. I'm trying to figure out a way to neatly display both at the same time, other than how I have it.
By 'portable' I mean anyone can just copy and paste the script into zMUD, and it will work. There's no bitmaps to download and install. This became an issue with some older working versions of GS3 indicators, because the person hosting the images (Stregone, I think?) let his account die and voila, no more images. Making them file non-reliant makes them more portable.
I think you should consider the graphical thing, despite your dislike of bitmaps. Parsing numbers and abbreviations for body parts is not as easy as looking at a body diagram.
And would definitely choose to toggle between the two - or make a combo thing, where scars are overlaid by wounds, which could be done in your present combo by having purple squares under the maroon ones, with a neutral color for nothing.
-theE-
See above reason for not using bitmaps... I'm trying to figure out a way to streamline this display to make end users happy. I think I'll make the little 'title' at the bottom switchable to swap between Wounds, Scars, and if I can figure it out, Both.
Martaigne
04-14-2007, 09:53 PM
Well, I just made a few tweaks, and this is the easiest and simplest solution for a graphical injury indicator that I can come up with without spending several more hours on code:
http://www.martaigne.com/images/zmud2.gif
I opted to turn the indicators into gauges, remove the numbers, expand the limb names a bit, line all the L and R body parts along in a column on each side, and leave it so that both Wounds and Scars are readily available.
TheEschaton
04-14-2007, 11:14 PM
That's actually pretty good. I especially like the color brightening for "bleeder" type wounds.
-TheE-
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions Inc. All rights reserved.