[crossfire] Healthbars

Mark Wedel mwedel at sonic.net
Sun Mar 21 23:18:10 CDT 2010


On 03/21/10 01:37 PM, Brendan Lally wrote:
> 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.

  That makes a lot of sense.


> 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?

  Maybe - I'm not sure I'd like a different class of messages for creatures that 
don't normally show up - at some level, there are already too many message types.

  One possibility (at least so far as the gtk2 client) is have an 'attack' 
message pane, where attack messages go.  Players could basically just ignore 
that if they so choose, and if attacking a monster and need that, make that 
message pane the visible one.

  (I suppose that in the ideal world for the gtk2 client, one could have as many 
message panes as one wants, and call them whatever they want, so could route 
messages all over the place)

>
>>> 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.

  In theory, there should never be 2 living creatures on the same space (not 
that it doesn't happen).  But if there were 2 living creatures on the same 
space, I can't think of any sensible way to display stat bar information for 
both of them.

>
>>> 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.

  It is not too uncommon that via either errors or intentional effect, some 
monsters hp > maxhp.  Under current method, I would think those get sent every 
tick also.

>
>>    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)

  Yes - putting it in the mapspace struct makes sense.  And rather than having a 
different routine that fills in that hp value, it makes sense to just use 
update_position() to fill in that data - that gets preliminary data filled in.

  For any updates to monster HP during combat, a simple method would be to just 
set the NEED_UPDATE flag on the space the monster is at.  However, probably 
better for the combat code to just update the HP value for that space - the 
combat codes knows the map, x, y, hp values, so simple enough for it to do it. 
May want to have a generic macro like SET_MAP_HP_PERCENT(...) just like the 
other SET_MAP_... macros.


>>    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.

  True - only a concern if you need more than 7 bytes.

>
>>> 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.

  That makes sense, and follows with what you say above.

  My personal inclination (but more work) would be more spells actually have 
some aura or like around the player, but that doesn't work well if characters 
has multiple auras (as an example of this, you cast protection from fire and 
maybe a red aura surrounds the character).  That is beyond the scope of what you 
are doing here.

  But one thing is that for many spells, there is nothing to denote if the 
effect is obvious or not.  Does a protection spell have an obvious effect?  What 
about strength or other stat gains?  Something like regeneration might, simply 
on the basis creature is regaining hp (you would see wounds closing, etc)

  On that basis, however, it may not be long term duration spells you are 
watching - if a creature heals itself via spell, that would be an obvious effect 
(lots of wounds close really quickly), but not something the server could infer 
by looking at forces in the monster.

  I think trying to hunt those down may get pretty complicated/time consuming. 
You would need to look at the monsters inventory for these forces, and you'd 
almost have to do that every tick because there wouldn't be a good/fast way for 
that code to know that some force just disappeared (maybe adding some new FLAGs 
would do it)

>
>>    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'

  OTOH in the arena, it is probably one of those cases where you can watch the 
message pane more closely - there is only one other opponent.

>
>>> 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.

  Ah OK.  That works.

>
>
>>    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.

  That would work.

>
> 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,

  Might want to limit this to 200 to denote creature is at more than double 
maxhp, just to be clear.  I guess that is still screwy if the creature happens 
to be a 3 times maxhp - you'd do a lot of damage before seeing any indication, 
but presuming this isn't a design error, maybe such supernatural HP would not be 
obvious when they are lost.

> 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.

  Looks good.




More information about the crossfire mailing list