[crossfire] Healthbars

Brendan Lally brenlally at gmail.com
Sun Mar 21 15:37:40 CDT 2010


On Sat, 20 Mar 2010 21:14:41 -0700
Mark Wedel <mwedel at sonic.net> wrote:

> On 03/19/10 11:24 AM, Brendan Lally wrote:  
> > The following is a proposed addition to the crossfire protocol to
> > enable the clients to show monster health bars.  
> 
>   Just a note, this was discussed several years back, and at that
> time, there was concern that that 'gives away' information to the
> player that perhaps should not be given away (how close a monster is
> to death as an example, or fast regeneration).
> 
>   I don't know if we still consider that a concern or not - I know
> lots of other games show something similar, but is something I
> thought I'd mention.  

The overriding principle I have been working to is that what should be
presented is information that the player's character may reasonably be
expected to infer from looking at a monster, so if there is something
that has a direct visible effect on a monster, then the character would
know about it, so the client should, if there is no direct visible
effect, then the character won't know about it, so the client shouldn't
either.

>   
> <snip>
> > In order to implement this, the following is altered.
> >
> > A setup command 'healthbars' is added, if a client request it with
> > argument '1' then the server will send healthbar information to the
> > client, if they do not, then there is no visible change.
> > 	[Possible expansion, if the setup flag is sent and
> > confirmed, expect that the client will ignore attack messages ('you
> > cut foo', 'you miss foo', etc)]  
> 
>   I'd have the player ignore attack messages be some option.  While
> for the most part, they are not needed, I don't know there are some
> attack messages which you would care about (I'm not 100% sure what
> all messages fall into the attack category).  But dropping them all
> could result in information not being displayed that is important.  

The gtk2 client already has client message configuration, so it would
be a question of changing the default to 'off' for that type of message.

As it stands, there are a couple of cases where you might want to keep
attack messages, invisible creatures would be the obvious ones, because
they wouldn't get healthbars sent. - maybe the answer is to use one of
the subtypes of attack message to allow those ones to be kept and the
others to be filtered out?

> > The map2 command is extended to have another type of data that may
> > be sent. type 4 is a healthbar. There follow 2 bytes, the first is
> > the hitpoints as a proportion of maxhp, the second is the flags
> > that apply to the hitpoint bar.  
> 
>   I haven't looked in detail, but it sounds like this information is
> now space specific (eg, this space has flags 0x02 and hp 0x40).  Is
> that correct?  

Yes, the information is sent for the highest (by layer) ALIVE object
on the map square. - This does potentially mean that there are
creatures on lower layers that aren't displayed, but there probably
isn't a sensible way to display health bars for multiple creatures on a
square anyway.

> > The healthbar is sent for an alive creature that is either a
> > monster or a player. It is sent whenever a face changes on the
> > square, or always if the creature is below their maximum health.
> > The client should show healthbars until the information for the
> > square is updated.  
> 
>   I'm a little concerned about sending it all the time if creature is
> not at full health.  Maybe with modern connections, the bandwidth
> isn't a concern, but there are still lots of maps with large mobs of
> monsters - I could imagine them getting hit with a burning hands, and
> now sending update for all those monsters every tick (while the 3
> bytes for the data isn't bad, there are additional bytes needed for
> each space to denote the coordinates, etc).  

The other thing I have come across is that some maps seem to do odd
things with locked doors, I think it probably is useful to be able to
see information for them, but they seem to have their maxhp set oddly
and are getting sent a lot.

>   If this is a per space attribute, it would be better to cache that
> data - both in the map structure itself (so fast to fetch) and in
> socket structure that holds the player map.
> 
>   In that way, server would only need to send data if it has changed
> in any way.  

Caching like that is a really interesting idea, the other thing this
does, if there are many players viewing the same squares, is mean that
the flags only need to be calculated once per tick.

Probably the place to store it is in the mapspace struct, then on each
tick update all the mapspace information for the maps that either have a
player on, or are loaded and linked to a map that does. 

I would probably add, if other face information is being sent anyway,
then always send the healthbar because it is probably better that a map2
clear would clear the healthbars anyway (and things like newmap commands
should too)

> > The first byte has a value between 0 and 255, 128 means that the
> > creature is at full health, above that means the creature is above
> > max health (which doesn't normally happen, but potentially might be
> > possible) 128 has been chosen because it is a multiple of 32 (the
> > size of the tile), so calculating the length of a bar should be
> > trivial for clients.  
> 
>   IIRC, the java client resizes tiles to match the screen
> resolution.  I'd also think that in most cases, you want to leave at
> least one pixel border so if you have 2 monsters next to each other,
> the stat bars don't run together.
> 
>   I think expressing that number as a percentage (100 being full
> health) is a bit more intuitive, and doesn't really make processing
> harder on the client side (it's all math).  

Ok, that's a fair point.

>   
> >
> > The second byte provides information about the flags that apply to
> > the creature, this is a bitmask, currently the values that are used
> > are:
> >
> > Bit 1, creature is another player or belongs to another player.
> > Bit 2, creature is friendly (someone's pet)  
> 
>   Note there are cases where monsters are set friendly but are not
> pets  

Yes, I think I found a couple of those.


> > Clients are required to ignore any additional flags that they do not
> > understand.  
> 
>   When you say ignore, does that mean they should just ignore the
> flags, or ignore this HP total all together?  Doesn't matter much to
> me either way, but that should be clarified.  

I mean ignore the flags that it doesn't understand.

>   Would it make sense to expressly set a bit for monsters (instead of
> assuming if no bits are set, it is a monster?)  Would it also make
> sense of instead of using a bitmask here, to actually enumerate the
> values (1=monster, 2=player, 3=this players pet, 4=another players
> pet, 5=door, 6=..., etc)?  I'm just thinking that with a bitmask, you
> pretty quickly run out of bits if you start adding other things.  One
> way the map command handled this for some things was the low order
> bits were enumerated value, high order bits were the bitmask, and
> they worked towards each other (so first bitmask was 0x80, and the
> enumeration may have had a max of 15 types.  In that way, if the
> enumeration needed to grow, it could, and if the bitmask needed to,
> it could go to 0x40, etc).  

I'm going to modify the proposed change in combination with your
comments about faces below.

>   Or for that matter, might want to make note that 0x80 is reserved,
> and denotes that another flag value follows, so you build in some
> expansion just in case you run out of bits.  

The map2 command sends the length of the data that follows it, so the
client should be able to look to see if there are additional
flags from there.
 
> > The remaining bits are reserved for later use, the intention being
> > that they should correspond to effects that are on the creature in
> > some way.
> >
> > Provisionally, the suggestion is to include
> > * Monster is moving slowly (slowed or paralysed)
> > * Monster is poisoned
> > * Monster has some form of beneficial effect working on them  
> 
>   That last one is pretty vague - might want to break it down into
> protections, attribute gains, etc.  I don't know.  

The suggestion on IRC was that this is something the 'probe' spell
could do. - I think this really comes back to the question of 'is this
something my character might reasonably be able to observe by looking?'
In this case, my inclination would be to say that you'd be able to spot
glowing magic stuff around a monster, without being able to tell what
it is doing.
 
>   I also wonder, going back above to discussion about giving too much
> away, if this should perhaps be limited to players/pets.  So you can
> easily monitor your party members, but don't know that the monster
> just cast protection on themselves (the monster AI is already pretty
> stupid - if players can visually see if monster has beneficial
> spells, the monster code should get modified so monster can 'figure
> out' if player has spells on them, what the best form of attack the
> monster should use, etc).
> 
>   As an aside, should stat bar display perhaps be disabled on some
> maps (map attribute)?  In particular, I'm thinking the arena, but I
> could also imagine that maybe in some places where combat should not
> happen, there may not be much reason to display it.  

The arena is one of the places where I think this would be most
useful to have this, it gives players a way to tell whether they are
winning or need to try something else, and may make the first battle
with someone more tactical than merely 'run to the right and see if I
win'

> > Currently I have a working implementation against the server, and
> > Ragnor has created a modification to jxclient to handle this, that
> > leads to something like the following in use:
> > 	http://imagebin.ca/view/wD2lvaI.html
> >
> > Since that screenshot was taken, some additional work has been done
> > to change the colouring of the bars to reflect the flags that are
> > sent. the creature has (eg, that sage has been hit, so is now
> > hostile, should have a different colour to the non-hostile
> > townsfolk) There may still need to be something done from a display
> > perspective to have the bars offset to appear in the bottom of the
> > cell above the creature's face (although I do not suggest using
> > such an offset in the data sent from the server.).  
> 
>   If this becomes a default setting, then it may be that the correct
> answer is to adjust the monster images, etc, so that there is space
> above the monsters head for the stat bars.  I think from a player, it
> makes a lot more sense for the stat bar to be above the monsters
> head, and not below their feet (alternatively, you might be able to
> do it along the left side of the cell - for many monsters, there may
> be more space there)  

Sorry, I maybe didn't make that bit clear, I mean offset the bars so
they appear above the player, but drawn in the next cell up (the same
way the bars above the player are drawn.


>   Random question (and I know this is a pure client issue, so maybe
> something Ragnar can answer it) - what do you do for big monsters,
> like trolls or titans? Size the statbar for the entire creature?
> 
>   I suppose an issue here is that the client doesn't know the
> relation of the statbar to the image it goes with.  It would be
> screwy to display it just above the creatures feet, but I don't know
> if the client otherwise would know what to do with it.  

hmm, this is a good point, maybe the thing to do is send the layer that
the healthbar corresponds to? The client would then be able to identify
the face that is drawn on that layer, and scale to the appropriate
width.
 
Ok, so taking all of this together then, I end up with the following:

The setup command is as described.

The map2 command gets a new type (4) which sends a number of bytes
after it as defined in the length mask.

There will be two bytes that are always sent, 
The first contains the hp, scaled so that 100 = full health, 
The second is for client display hinting, it contains two nybbles, 
	the first is the layer that the healthbar is 'on'
	the second is the type of healthbar - clients should ignore
	any healthbars for types they do not know
There may then be some number of further bytes, making up to the byte
count in the type byte. These contain flags, clients may choose to
interpret them if they know how, any flags the client doesn't recognise
it must ignore.

>   Other than those various comments, it all looks good to me, and IMO
> is worth adding.  I think it may be better to wait until after the
> release in a week or two to get more testing time, but depends on how
> much work it needs to be finished.  

I'd be inclined to agree with that, I have a few more changes
to make anyway.

Brendan.



More information about the crossfire mailing list