Health and Experience and Bars, oh my!

Posted by Caelen on Thu 10 Feb 2011 08:45 PM — 52 posts, 182,019 views.

#0
I took a shot at combining the health and experience bar plugins into a single, one-window plugin. So far, I have met with a lot of success! I have, however, hit one snag. I can't figure out how to separate the draw_the_bars function in a way that will let me draw the hp/sp/ep gauges whenever I get the prompt, while also drawing the experience/money gauges whenever I use the commands that display my XP and CP. With no prompt configuration available, I can't use the easy route of a single trigger. So! I made a lot of triggers. The triggers work, they all return the values I need, and the draw_the_bars function is sending the right information to the DoGauge function. How do I separate it all out to redraw the xp/cp bars without erasing the hp/sp/ep bars?

Here are a couple snips from my script.
These triggers grab the values I need to level.

  <trigger
   enabled="y"
   match="^LEVEL (\d+) ADVANCEMENT$"
   regexp="y"
   script="do_prompt_level"
   sequence="100"
  >
  </trigger>
  <trigger
   enabled="y"
   match="^Advancement will cost (\d+) experience and (\d+) coppers\.$"
   regexp="y"
   script="do_prompt_cost"
   sequence="100"
  >
  </trigger>
  <trigger
   enabled="y"
   match="^You will need (\d+) more experience and (\d+) more coppers\.$"
   regexp="y"
   script="do_prompt_tnl"
   sequence="100"
  >
  </trigger>


These functions store the values.

function do_prompt_level (name, line, wildcards)

  next_level = tonumber (wildcards [1])
  level = next_level - 1
  
end -- do_prompt_level

function do_prompt_cost (name, line, wildcards)

  max_xp = tonumber (wildcards [1])
  max_cp = tonumber (wildcards [2])
  
end -- do_prompt_cost

function do_prompt_tnl (name, line, wildcards)

  tnl_xp = tonumber (wildcards [1])
  tnl_cp = tonumber (wildcards [2])
  xp = max_xp - tnl_xp
  cp = max_cp - tnl_cp
  
end -- do_prompt_tnl


This function draws it all, and is only called by my hp/sp/ep functions.

function draw_the_bars ()

  -- fill entire box to clear it
  check (WindowRectOp (win, 2, 0, 0, 0, 0, BACKGROUND_COLOUR))  -- fill entire box
  
  -- Edge around box rectangle
  check (WindowCircleOp (win, 3, 0, 0, 0, 0, BORDER_COLOUR, 0, 2, 0, 1))

  vertical = 6  -- pixel to start at

  DoGauge ("HP: ",  hp,  max_hp,  ColourNameToRGB "darkgreen")
  DoGauge ("SP: ",  sp,  max_sp,  ColourNameToRGB "mediumblue")
  DoGauge ("EP: ",  ep,  max_ep,  ColourNameToRGB "red")
  DoGauge ("XP: ",  xp,  max_xp,  ColourNameToRGB "darkviolet")
  DoGauge ("CP: ",  cp,  max_cp,  ColourNameToRGB "gold")

  WindowShow (win, true)

end -- draw_the_bars


I tried splitting out the xp and cp parts into a second draw_the_xp_bars function, but when that was called it would erase my hp/sp/ep bars, which I don't want to do. I'd also like to somehow get the XP bar display to show "L5: " (or whatever my current level is) instead of "XP: ", which is why that first trigger and function is in there. Any idea how I can get this mess to work?

edit: Something I tried earlier was having the xp/cp triggers also call the draw_the_bars function, but when first installing the plugin, those values aren't all there, so it can't draw the bars!
Amended on Thu 10 Feb 2011 08:48 PM by Caelen
Australia Forum Administrator #1
Just omit the line where it does the "fill entire box to clear it" (the line, not the comment) and then just draw each bar as you get it. I don't think clearing the bars is critical, as you are drawing over them anyway.
#2
success! now I can draw either set of bars in the single large window :D


function draw_the_bars ()
  
  -- Edge around box rectangle
  check (WindowCircleOp (win, 3, 0, 0, 0, 0, BORDER_COLOUR, 0, 2, 0, 1))

  vertical = 6  -- pixel to start at

  DoGauge ("HP: ",  hp,  max_hp,  ColourNameToRGB "darkgreen")
  DoGauge ("SP: ",  sp,  max_sp,  ColourNameToRGB "mediumblue")
  DoGauge ("EP: ",  ep,  max_ep,  ColourNameToRGB "red")

  WindowShow (win, true)

end -- draw_the_bars

function draw_the_xp_bars ()
  
  -- Edge around box rectangle
  check (WindowCircleOp (win, 3, 0, 0, 0, 0, BORDER_COLOUR, 0, 2, 0, 1))

  vertical = 64  -- pixel to start at

  DoGauge ("XP: ",  xp,  max_xp,  ColourNameToRGB "darkviolet")
  DoGauge ("CP: ",  cp,  max_cp,  ColourNameToRGB "gold")

  WindowShow (win, true)

end -- draw_the_xp_bars


I'd still like to figure out how to change the "XP" part to read "L#" though... any ideas?
Amended on Fri 11 Feb 2011 04:39 AM by Caelen
Australia Forum Administrator #3
I'm not sure I understand the question. You mean to change the label?
#4
Right, change the label to be a variable. I don't know how to include variables inside quotes, if that's even possible.
#5
Is there any way to get that full script for what you are doing posted here please?
Australia Forum Administrator #6
Caelen said:

Right, change the label to be a variable. I don't know how to include variables inside quotes, if that's even possible.


Do you mean:


DoGauge ("L#: ",  xp,  max_xp,  ColourNameToRGB "darkviolet")


Or if you want to "include a variable inside quotes" you can do something like this:


myvar = "foo"
DoGauge (myvar .. ": ",  xp,  max_xp,  ColourNameToRGB "darkviolet")


That concatenates a variable (myvar) with stuff in quotes.
#7
Nick Gammon said:

That concatenates a variable (myvar) with stuff in quotes.


Exactly what I want :D assuming I'm interpreting what "concatenates" means correctly :x Thanks!
-checks google to see what it actually means-

edit: Indeed, does exactly what I want :D
Amended on Sat 12 Feb 2011 06:44 AM by Caelen
#8
So! The plugin is a hit with everyone on Ateraan XD I now have some fun requests I'm trying to do!

Project one: Catch the experience gain from introductions and bonuses. The text is always the same sentence, and I know how to make it accept all the possible variables... but, the problem is that it's multiple lines. Is there a way to tell the client to "catch this sentence, ignoring extra spaces (indents), and trigger"?


Kethlyn tells you her name and a lot about herself. You feel
enlightened by the information and gain 2900 experience from the encounter.

Sythrivum tells you his name. You feel some enlightenment and gain 1100
experience from the encounter.


----------------

Project 2: Make the window more transparent! Several people don't like how much space it takes up, or don't like how it blocks some of the view. Is there a way to make the background clear, so that text can be read through it, and make the gauges themselves transparent as well?

----------------

Project 3: Expanded configuration. This one I know how to do, it's just a matter of doing it. I'm planning on pulling all the options I like tinkering with, like the font and colors and such, into the configuration.
USA #9
Caelen said:
Project one: Catch the experience gain from introductions and bonuses. The text is always the same sentence, and I know how to make it accept all the possible variables... but, the problem is that it's multiple lines. Is there a way to tell the client to "catch this sentence, ignoring extra spaces (indents), and trigger"?


Kethlyn tells you her name and a lot about herself. You feel
enlightened by the information and gain 2900 experience from the encounter.

Sythrivum tells you his name. You feel some enlightenment and gain 1100
experience from the encounter.

Even though it's possible, it's not exactly clean or easy to do. It would be orders of magnitude easier if there were a config option for your MUD to disable line wrapping; on Achaea we have 'config screenwidth 0'.


Caelen said:
Project 2: Make the window more transparent! Several people don't like how much space it takes up, or don't like how it blocks some of the view. Is there a way to make the background clear, so that text can be read through it, and make the gauges themselves transparent as well?

As far as I recall, window pixels can only be 100% opaque or 100% transparent. Images have lots of leeway, but at some point they need to be drawn onto the window, and window pixels are all-or-nothing.

Caelen said:
Project 3: Expanded configuration. This one I know how to do, it's just a matter of doing it. I'm planning on pulling all the options I like tinkering with, like the font and colors and such, into the configuration.

Sounds like a great idea. I personally like having a separate file for configuration, but if you'd like to keep everything in one file that's fine too.
#10
How can I make the window 100% transparent?
USA #11
100% transparent means the window itself is totally invisible. I don't think that's what you want. Window transparency is mostly only useful for making your windows into non-square shapes.

MUSHclient miniwindows use something called chroma-keying to implement transparency. What this means is, if a pixel on the window is a specific color, it will draw whatever's underneath it instead. So to use this, you need to pass flag 4 to WindowCreate(), so the background color you specify is the color marking transparency.

Template:function=WindowCreate
WindowCreate

The documentation for the WindowCreate script function is available online. It is also in the MUSHclient help file.



I'm guessing you want the window to blend with the background, which means making pixels on the window semitransparent. Unfortunately that's not possible. (Believe me, I'd like that too.)
#12
Not quite wanting it to blend, actually... what I want is opaque gauges with an invisible background. Rather than a background color of "black", I want no background at all. So, only the box around the gauge (including ticks), the text to the left of it, and the colored bar the fills the gauge will be visible.
USA #13
That's pretty easy then. Just pick a color you think you'll never ever use, set it as the window background in WindowCreate, and pass the transparency flag (4) to WindowCreate as well. For example, if you picked #0F0532, then any window pixel with a value of #0F0532 will be replaced with the pixel behind it.
#14
Twisol said:

That's pretty easy then. Just pick a color you think you'll never ever use, set it as the window background in WindowCreate, and pass the transparency flag (4) to WindowCreate as well. For example, if you picked #0F0532, then any window pixel with a value of #0F0532 will be replaced with the pixel behind it.



function OnPluginInstall ()
  
  win = GetPluginID ()
  font_id = "fn"
  
  require "movewindow"  -- load the movewindow.lua module

  -- install the window movement handler, get back the window position
  windowinfo = movewindow.install (win, 7)  -- default to 7 (on right, center top/bottom)
    
  -- make miniwindow so I can grab the font info
  WindowCreate (win, 
                windowinfo.window_left,
                windowinfo.window_top,
                WINDOW_WIDTH, 
                WINDOW_HEIGHT,  
                windowinfo.window_mode,   
                windowinfo.window_flags,    
                BACKGROUND_COLOUR)

  -- add the drag handler so they can move the window around
  movewindow.add_drag_handler (win, 0, 0, 0, 0)
                 
  WindowFont (win, font_id, FONT_NAME, FONT_SIZE)
  font_height = WindowFontInfo (win, font_id, 1)  -- height


How do I get at the "windowinfo.window_flags" to make it "4"? Do I just change it to 4?
Australia Forum Administrator #15
I think the movewindow sets one of the flags so you should really "or" it in. Like this:


-- make miniwindow so I can grab the font info
  WindowCreate (win, 
                windowinfo.window_left,
                windowinfo.window_top,
                WINDOW_WIDTH, 
                WINDOW_HEIGHT,  
                windowinfo.window_mode,   
                bit.bor (windowinfo.window_flags, 4),    
                BACKGROUND_COLOUR)

#16
Twisol said:

Sounds like a great idea. I personally like having a separate file for configuration, but if you'd like to keep everything in one file that's fine too.


What's the trick to getting a single config file for these plugins? Considering it's three plugins total (one for health bars, one for xp bars, and one for both combined), it'd be nice if there was just one file for configuration ^^

Nick Gammon said:

I think the movewindow sets one of the flags so you should really "or" it in.


Works wonderfully, except for one snag. It draws the window how I want it, with the background completely invisible... then after about half a second it fills it with black (my chosen background color for testing).

http://www.mediafire.com/?pl3n1hfj03b9vc9

This is the plugin file. It also has some slight issues, mostly because I had to remove the line that drew over the entire window to "erase" it in order to get parts to draw independently. The text smudges a bit after a while, and if I level the level counter gets all screwy as it writes numbers over numbers.

It also has the layout for my intended config setup in it.
Amended on Sat 26 Feb 2011 06:59 AM by Caelen
USA #17
Caelen said:
What's the trick to getting a single config file for these plugins? Considering it's three plugins total (one for health bars, one for xp bars, and one for both combined), it'd be nice if there was just one file for configuration ^^

I'd put the plugin XML file in its own directory (e.g. "health_bar_miniwindow.plugin/plugin.xml"), and add another file next to it called config.lua. Then you can use GetPluginInfo(GetPluginID(), 20) to get the directory the plugin is in, allowing you to do something like this to load the config file:

require(GetPluginInfo(GetPluginID(), 20) .. "/config.lua")

My "structured plugin" guidelines[1] define my ideal plugin structure, based on the idea that a plugin should be within its own directory. It lets you modularize your plugin by separating scripts out into their own files, and it keeps things tidy by packaging resources (like images or audio files) with the plugin. I even built a simple "plugin stub" library called Plugger[2] that lets you keep the scripts entirely separate from the plugin XML file. If you want an example, you can find a number of my plugins at my website[3]. In particular, RoomName.plugin is a pretty good foundation to begin from.

[1] http://www.gammon.com.au/forum/?id=10011
[2] http://www.gammon.com.au/forum/?id=10081
[3] http://jonathan.com/new-gmcp-plugins-for-achaea
#18
I've been going through those plugins, reading the files and such, but I'm a bit lost...

First, is semantic versioning a requirement? I don't understand it at all.

Second, what is PPI? In terms someone who knows very little about programming can understand, please. Is PPI needed, or is it only something used with GMCP/ATCP? New Worlds Ateraan uses nothing fancy like that sadly (or not that I'm aware of... they are very tight-lipped about the code).

I intend to have only one version, and one plugin file, for the final product, and I'm going to use that plugger.xml to help configure it so people can choose which setup they want with a simple number choice.

Also, still have a problem with the transparency, but everything else seems to be working just fine, including my ever increasing volume of triggers.

Can those triggers be pulled into a separate file as well? Like... plugindirectory/triggers/triggers.xml and have them be called by the main.lua file?
USA #19
Caelen said:
I've been going through those plugins, reading the files and such, but I'm a bit lost...

No worries. I use several things together in my plugins, but most of them are unrelated to each-other.

Caelen said:
First, is semantic versioning a requirement? I don't understand it at all.

No. It's just a way of versioning software so you can tell what it changes or breaks at a glance. Bugfix and minor version changes are supposed to be backwards-compatible, while bugfix chnges shouldn't add any new functionality.

I learned about it at semver.org.

Caelen said:
Second, what is PPI? In terms someone who knows very little about programming can understand, please. Is PPI needed, or is it only something used with GMCP/ATCP? New Worlds Ateraan uses nothing fancy like that sadly (or not that I'm aware of... they are very tight-lipped about the code).

PPI stands for "Plugin to Plugin Interface", and it lets plugins expose methods to other plugins. I use this in particular for my GMCP-based plugins because it lets them listen for GMCP events. You can ignore it if you don't plan on doing any complex plugin communication. It shows how easy it is to bundle a library in with a plugin though.

Caelen said:
I intend to have only one version, and one plugin file, for the final product, and I'm going to use that plugger.xml to help configure it so people can choose which setup they want with a simple number choice.

I'm not sure what you mean? Plugger is an aid for building complex plugins. You include it through the plugin XML and it automatically runs scripts/main.lua.

Caelen said:
Can those triggers be pulled into a separate file as well? Like... plugindirectory/triggers/triggers.xml and have them be called by the main.lua file?

Kind of. Yes, you can put them in a separate XML file, and use Lua's 'io' library to read the file into memory. Then you can use ImportXML() to take that file and turn the XML into actual triggers and stuff.

Alternatively, just use an <include> tag from the main plugin XML file.
#20
Twisol said:

PPI stands for "Plugin to Plugin Interface", and it lets plugins expose methods to other plugins. I use this in particular for my GMCP-based plugins because it lets them listen for GMCP events. You can ignore it if you don't plan on doing any complex plugin communication. It shows how easy it is to bundle a library in with a plugin though.


PPI won't be needed then, I don't think... the amount of complexity I can implement with Ateraan is quite limited. Zero automation is tolerated, not even something to make certain consumables when the cooldown is up.

Twisol said:

I'm not sure what you mean? Plugger is an aid for building complex plugins. You include it through the plugin XML and it automatically runs scripts/main.lua.


I was thinking Plugger lets you put things into sub directories instead of having all the files within the one folder... But, with only a few files, I should be fine if I just keep the filenames consistent, no? A single plugin.xml, a main.lua, a config.lua, and a triggers.xml? That should let me use a single setup for all of them, no?

EDIT: While I'm at it, is there any rhyme or reason to the "plugin id"?

<plugin
   name="Health_Bar_Miniwindow_Plus"
   author="Nick Gammon and Caelen Foss"
   id="48062dcd6b968c590df50f32"
   language="Lua"
   purpose="Shows stats in a mini window"
   date_written="2010-02-14 09:00"
   requires="4.40"
   version="2.0"
   save_state="y"
   >


EDIT2: I can't seem to find any documentation on the <include> tag... what are the details on how to use this?
EDIT3: Found it. http://www.gammon.com.au/forum/?id=10630
Amended on Sun 27 Feb 2011 07:46 AM by Caelen
Australia Forum Administrator #21
Caelen said:

EDIT: While I'm at it, is there any rhyme or reason to the "plugin id"?


That was my idea, so let me explain ...

When I initially designed plugins I wanted to have some way of knowing plugin A from plugin B. For example, the CallPlugin function. Now initially I thought of having plugin names, but there was no real way of making sure that people all around the world wouldn't make names that clashed (eg. "mapper", or "health bars").

So then, along similar lines to the Windows GUID for COM objects, I just decided to have a randomly-generated hex string (effectively a hash of a GUID). This way each plugin author could get a different one (you can generate them with a function call or from the GUI interface of MUSHclient).

*This* string is what uniquely identifies plugins, even if you change their names (eg. correcting spelling errors). Of course, I can't stop you using someone else's plugin ID, but why would you want to? They aren't particularly exciting per se.

BTW, in recent versions, the CallPlugin function lets you pass multiple arguments (in Lua) and also get results returned. So the need for PPI (which was developed before this extra functionality) is reduced somewhat.

Both PPI and now, CallPlugin, let you have one plugin call another one, passing data (like, multiple arguments), and get one or more results back. So you might have a generic database-query plugin, for example.
USA #22
Caelen said:
PPI won't be needed then, I don't think... the amount of complexity I can implement with Ateraan is quite limited. Zero automation is tolerated, not even something to make certain consumables when the cooldown is up.

Well, PPI just lets plugins talk to eachother. Whether or not you use that for automation is up to you. But no, you don't need PPI for this. :)

Caelen said:
I was thinking Plugger lets you put things into sub directories instead of having all the files within the one folder... But, with only a few files, I should be fine if I just keep the filenames consistent, no? A single plugin.xml, a main.lua, a config.lua, and a triggers.xml? That should let me use a single setup for all of them, no?

Yeah, that's pretty much what Plugger does. I like to keep the same directory structure through all my plugins, because it's just a simple plugger.path() call to get the path to one of the subdirectories.

Nick Gammon said:
BTW, in recent versions, the CallPlugin function lets you pass multiple arguments (in Lua) and also get results returned. So the need for PPI (which was developed before this extra functionality) is reduced somewhat.

Both PPI and now, CallPlugin, let you have one plugin call another one, passing data (like, multiple arguments), and get one or more results back. So you might have a generic database-query plugin, for example.

The primary difference is that PPI lets you pass and return functions and tables, so if that's something you ever want you may want to look into PPI. (It also alerts you when a plugin is installed, which really helps with dependency issues.)
#23
Okay, some questions about how to get this mess working. I am going to use Plugger to use the subdirectory setup, because it looks pretty. I have subdirectories set up, and main files in the folders.

Current Setup, for each plugin:
plugins
  plugin name
    plugin.xml
    config.lua
    readme.txt
    libraries
      plugger.xml
    scripts
      main.lua
    triggers
      triggers.xml


On to the questions!

1) Using the original plugin I started with, the triggers were before the scripts. Does this order matter, or can I put the <include/> part later on in the plugin.xml file?

</plugin>

<!--  Triggers  -->

<include name="$PLUGINDIR\triggers.xml" />

<!--  Script  -->

<script>


2) How can I use the readme.txt file as the long description? I want to be able to just edit the readme and have that be the description.

<description trim="y">
<![CDATA[
long description

]]>
</description>


3) Assuming the "Name" has been entered into Game > Configure > Connecting, is there a way to call this to create a trigger that catches the matching name? For instance, when you report your health status for everyone to see, you get "Name reports (stats)", where Name is your character name (or someone else). It does not say "You report". I want to catch this Name variable as the trigger text.

4) Is there a way to call the world's font (or the global font if the world font is being overridden), rather than having it left to the config file?
Amended on Mon 28 Feb 2011 01:13 AM by Caelen
USA #24
Caelen said:

1) Using the original plugin I started with, the triggers were before the scripts. Does this order matter, or can I put the <include/> part later on in the plugin.xml file?

</plugin>

<!--  Triggers  -->

<include name="$PLUGINDIR\triggers.xml" />

<!--  Script  -->

<script>

Mmmmmm.... this is a good question. I think it shouldn't matter, from what I remember of the source.

Caelen said:
2) How can I use the readme.txt file as the long description? I want to be able to just edit the readme and have that be the description.

<description trim="y">
<![CDATA[
long description

]]>
</description>

That's a good question! I don't know of any way to make the <description> tag scripted, but if you're using an alias to display the description (like that the Plugin Builder adds), you can just change it to read in the readme.txt file and display that.

Caelen said:
3) Assuming the "Name" has been entered into Game > Configure > Connecting, is there a way to call this to create a trigger that catches the matching name? For instance, when you report your health status for everyone to see, you get "Name reports (stats)", where Name is your character name (or someone else). It does not say "You report". I want to catch this Name variable as the trigger text.

You can use GetInfo(3) to get the value in the character name field, and either create a trigger using AddTriggerEx() or update an existing one with SetTriggerOption().

Caelen said:
4) Is there a way to call the world's font (or the global font if the world font is being overridden), rather than having it left to the config file?

GetInfo(20) contains the name of the font being used, I believe.
#25
Twisol said:

You can use GetInfo(3) to get the value in the character name field, and either create a trigger using AddTriggerEx() or update an existing one with SetTriggerOption().


in triggers/triggers.xml
  <trigger
   enabled="y"
   match="^.* Reports\: HP\:(\d+)\%  SP\:(\d+)\%  EP\:(\d+)\%$"
   name="hpall"
   regexp="y"
   script="do_prompt_currentpercentname"
   sequence="100"
  >
  </trigger>
in config.lua
CHARACTER_NAME = GetInfo(3)
if CHARACTER_NAME then
  SetTriggerOption("hpall", "match", "^" .. GetInfo(3) .. " Reports\: HP\:(\d+)\%  SP\:(\d+)\%  EP\:(\d+)\%$")
end
Would this work?



Twisol said:

GetInfo(20) contains the name of the font being used, I believe.


Any way to get the font size as well? I searched through the GetInfo documentation, but couldn't find anything for it :(
Amended on Mon 28 Feb 2011 03:23 AM by Caelen
USA #26
Caelen said:
Would this work?

I do believe so! Though for efficiency, you might want to use ".*?" instead of ".*".

And for safety, you might want to check if the returned name is empty (like "") and just leave it as .*? if that's the case.

Caelen said:
Any way to get the font size as well? I searched through the GetInfo documentation, but couldn't find anything for it :(

Hmm. Try printing the GetOptionList() return table, it might have both the font and the font size somewhere in there. The options aren't documented anywhere unfortunately.
Amended on Mon 28 Feb 2011 04:01 AM by Twisol
#27
These triggers don't seem to be working at all. First is the triggers from the file, second is the script for the triggers, third is what it's supposed to match.
  <trigger
   enabled="y"
   match="^HP\:(\d+)\%  SP\:(\d+)\%  EP\:(\d+)\%$"
   regexp="y"
   script="do_prompt_currentpercent"
   sequence="100"
  >
  </trigger>
  <trigger
   enabled="y"
   match="^.*? Reports\: HP\:(\d+)\%  SP\:(\d+)\%  EP\:(\d+)\%$"
   name="hpall"
   regexp="y"
   script="do_prompt_currentpercent"
   sequence="100"
  >
  </trigger>
function do_prompt_currentpercent (name, line, wildcards)

  hpp = tonumber (wildcards [1])
  spp = tonumber (wildcards [2])
  epp = tonumber (wildcards [3])
  hp = (max_hp * hpp) / 100
  sp = (max_sp * spp) / 100
  ep = (max_ep * spp) / 100

  draw_the_bars ()
      
end -- do_prompt_currentpercent
HP:100%  SP:100%  EP:79%
Verren Reports: HP:100%  SP:100%  EP:79%


The first one always returns 100%, and the second one doesn't trigger at all.

EDIT: Oh, and I still can't get transparency to work... XD
Amended on Mon 28 Feb 2011 05:01 AM by Caelen
Australia Forum Administrator #28
Caelen said:

Any way to get the font size as well? I searched through the GetInfo documentation, but couldn't find anything for it :(


A lot of this stuff is given by GetOption, so GetInfo doesn't necessarily have all of it. GetInfo is more for stuff computed at run time (like, how big the window is right now) but GetOption gives the values of the various options.

Try doing this in the Immediate window (from the help for GetOptionList):


for k, v in pairs (GetOptionList()) do 
  Note (v, " = ", GetOption (v)) 
end


Scrolling through that you'll see stuff about output_font_xxxx.
Australia Forum Administrator #29
Caelen said:


The first one always returns 100%, and the second one doesn't trigger at all.



On your triggers and test data they both fired for me. Using the "summary" feature I got this:


------ Trigger: *trigger1122 ------

  <trigger
   enabled="y"
   match="^HP\:(\d+)\%  SP\:(\d+)\%  EP\:(\d+)\%$"
   regexp="y"
   script="do_prompt_currentpercent"
   sequence="100"
  >
  </trigger>

         Matched count: 5
            Has script: No
   Times script called: 0
     When last matched: 16:36:30
               Send to: world
             Temporary: No
         Time to match: 0.000314
        Match attempts: 15


------ Trigger: hpall ------

  <trigger
   enabled="y"
   match="^.*? Reports\: HP\:(\d+)\%  SP\:(\d+)\%  EP\:(\d+)\%$"
   name="hpall"
   regexp="y"
   script="do_prompt_currentpercent"
   sequence="100"
  >
  </trigger>

         Matched count: 5
            Has script: No
   Times script called: 0
     When last matched: 16:36:30
               Send to: world
             Temporary: No
         Time to match: 0.000052
        Match attempts: 20



I tested 5 times, and both fired 5 times. (I got an error on draw_the_bars () but that wasn't germane to whether the trigger fired or not).

Caelen said:

EDIT: Oh, and I still can't get transparency to work... XD


Well you will have to post more details than that. Like, code that you think should work.
Australia Forum Administrator #30
Caelen said:

in config.lua

CHARACTER_NAME = GetInfo(3)
if CHARACTER_NAME then
SetTriggerOption("hpall", "match", "^" .. GetInfo(3) .. " Reports\: HP\:(\d+)\% SP\:(\d+)\% EP\:(\d+)\%$")
end

Would this work?


Why not do this?


CHARACTER_NAME = GetInfo(3)
if CHARACTER_NAME then
  SetTriggerOption("hpall", "match", "^" .. CHARACTER_NAME .. " Reports\: HP\:(\d+)\%  SP\:(\d+)\%  EP\:(\d+)\%$")
end


But more to the point, triggers can incorporate variables. So just make it:


SetVariable ("my_character", GetAlphaOption ("player"))

SetTriggerOption("hpall", "match", "^@my_character Reports\: HP\:(\d+)\%  SP\:(\d+)\%  EP\:(\d+)\%$")


Make sure "expand variables" is on. Of course, you don't need to do the SetTriggerOption now, because that part won't change. Just incorporate the variable into the original trigger.
Amended on Mon 28 Feb 2011 05:52 AM by Nick Gammon
USA #31
Nick Gammon said:

SetVariable ("my_character", GetAlphaOption ("player"))

SetTriggerOption("hpall", "match", "^@my_character Reports\: HP\:(\d+)\%  SP\:(\d+)\%  EP\:(\d+)\%$")


Forewarning: the @variable tokens are evaluated BEFORE any code is run, so if you have the below script, it won't do what you expect:

-- assume 'foo' contains "11" right now

SetVariable("foo", "42")
Note("@foo") -- shows 11, not 42!
Australia Forum Administrator #32
Absolutely, but his character name won't change from minute to minute, will it?
USA #33
Not at all. It was just in the same [code] block and I wanted to make sure nobody got the wrong idea.
#34
Didn't know I could use variables in the trigger matches like that! Awesome. Let me finish retesting those, and I'll post a link to the file.

Any idea why the first trigger was always returning a value of 100% though?
#35
http://www.mediafire.com/?7enc168d682e6kc

Everything is working except for two things. Transparency, and the "do_prompt_percent" function.
Amended on Mon 28 Feb 2011 09:04 AM by Caelen
USA #36
Can you explain what you mean by "returning" please? As I understand the term, it means "the value returned by a function", as in the imaginary function 'add(2, 2)' returns 4. A trigger doesn't return anything in particular, unless you're talking about the wildcard parameters (which would be matches) or the displayed value of the health bar (which is just output).

Sorry to get pedantic, but it's hard to reproduce the problem if I don't know what I should be looking at. :)
Amended on Mon 28 Feb 2011 11:01 AM by Twisol
#37
Ah, sorry. I mean the "function DoGauge" always draws the bars at 100% full when the two triggers in question match. I tested the triggers using "print", and they are grabbing the correct numbers in both cases. The problem is either in function DoGauge or function do_prompt_percent.
USA #38
Nitpick, but this is unnecessary:
  if current > max then
     current = max
  end -- cannot have more than max

  if current < 0 then
     current = 0
  end -- cannot have less than zero
  
  -- fraction in range 0 to 1
  local Fraction = math.min (math.max (current / max, 0), 1) 

By locking current between 0 and max, you're already ensuring that Fraction is between 0 and 1 (as 0/max is 0 and max//max is 1). I'd prefer just to forgo the if-checks because the math.min and math.max do it neatly in one line.
local Fraction = math.min (math.max (current / max, 0), 1)


Secondly, you're passing 'current' and 'max' in to DoGauge so it can figure out how much of the gauge should be filled, but you already -have- that in the percentage. Just (hpp / 100) gives you the fraction of the gauge that needs filling.


I can't actually run the plugin currently, but I don't see any actual bugs, so I'm probably missing something.
#39
Twisol said:

local Fraction = math.min (math.max (current / max, 0), 1)



Cleaned up :D Thanks.

Twisol said:

Secondly, you're passing 'current' and 'max' in to DoGauge so it can figure out how much of the gauge should be filled, but you already -have- that in the percentage. Just (hpp / 100) gives you the fraction of the gauge that needs filling.


What I'm trying to do is get do_prompt_percent to send the current and max values so that the mouseover hotspot will display the correct (or at least somewhat close) information when only supplied with the percentage. The math looks fine to me... but I just don't see why it isn't sending the correct info.
Australia Forum Administrator #40
I always find it helps to put in debugging print statements. Perhaps the values are 100 times what you expect, or one is missing, or something?
USA #41
Caelen said:

What I'm trying to do is get do_prompt_percent to send the current and max values so that the mouseover hotspot will display the correct (or at least somewhat close) information when only supplied with the percentage. The math looks fine to me... but I just don't see why it isn't sending the correct info.

Oh, I see. I must've skipped over that part.
#42
Nick Gammon said:

I always find it helps to put in debugging print statements. Perhaps the values are 100 times what you expect, or one is missing, or something?


Results of the printing: (printed added before what was printed)
hp
HP:306/306  SP:238/238  EP:111/155
printed HP: 306/306 current/max
printed SP: 238/238 current/max
printed EP: 111/155 current/max
> 
hpp
HP:100%  SP:100%  EP:71%
printed HP:306/306%100
printed SP:238/238%100
printed EP:155/155%71
printed HP: 306/306 current/max
printed SP: 238/238 current/max
printed EP: 155/155 current/max


Modifications to DoGauge:
  print (sPrompt .. current .. "/" .. max .. " current/max")


Modifications to do_prompt_percent:
  print ("HP:" .. hp .. "/" .. max_hp .. "%" .. hpp)
  print ("SP:" .. sp .. "/" .. max_sp .. "%" .. spp)
  print ("EP:" .. ep .. "/" .. max_ep .. "%" .. epp)


So, do_prompt_percent is the problem... it's catching the right value for the percentage (71), but it's not doing the math right.

function do_prompt_percent (name, line, wildcards)

  hpp = tonumber (wildcards [1])
  spp = tonumber (wildcards [2])
  epp = tonumber (wildcards [3])
  hp = max_hp * ( hpp / 100 )
  sp = max_sp * ( spp / 100 )
  ep = max_ep * ( spp / 100 )
  print ("HP:" .. hp .. "/" .. max_hp .. "%" .. hpp)
  print ("SP:" .. sp .. "/" .. max_sp .. "%" .. spp)
  print ("EP:" .. ep .. "/" .. max_ep .. "%" .. epp)

  draw_the_bars ()
      
end -- do_prompt_percent


Ideas?

EDIT: changed that middle part to
  hp = math.floor(max_hp * (hpp / 100))
  sp = math.floor(max_sp * (spp / 100))
  ep = math.floor(max_ep * (spp / 100))


Doesn't change the results, but I don't want any decimal values gumming it up.

EDIT2: I have decided to, for now, scrap the idea of making the background transparent. It would be nice, but without the background it would get quite messy as text appeared beneath the gauges. Plus, I can't do the blend thing, which seems to be what people were wanting actually XD
Amended on Tue 01 Mar 2011 03:23 AM by Caelen
USA #43
Well, I just installed the plugin and ran this small script:
Simulate("HP:100/500  SP:100/400  EP:100/300\r\n")

The gauges seem to work just fine. Can you paste a few actual examples of that hp/sp/ep line? My hunch is that, for some reason, the max_* variables are always less than the current values, so you're always drawing the gauges at 100%. It all works for me, so the only thing left is the data coming in via the trigger.
#44
I'm not sure what you're asking for... what I pasted above included the command (hp and hpp respectively), the output from the game (the line with HP quantity and HP %), and then what was printed by the debugg scripts.

What you've simulated there is actually the match for the one trigger that -does- work. I've tested the three triggers, and all three return the proper wildcard values. The third trigger catches the command "hpall", and the mud gives the "Verren Reports: %%%" line (the match I'm using the variable for now).

It's the % ones that are returning incorrect values for current, but the max values are always correct.


hp -- command
HP:306/306  SP:238/238  EP:111/155 -- mud output
HP: 306/306 current/max -- printed by DoGauge called by do_prompt_max
SP: 238/238 current/max -- printed by DoGauge called by do_prompt_max
EP: 111/155 current/max -- printed by DoGauge called by do_prompt_max

hpp -- command
HP:100%  SP:100%  EP:71% -- mud output
HP:306/306%100 -- printed by do_prompt_percent
SP:238/238%100 -- printed by do_prompt_percent
EP:155/155%71 -- printed by do_prompt_percent
HP: 306/306 current/max -- printed by DoGauge called by do_prompt_percent
SP: 238/238 current/max -- printed by DoGauge called by do_prompt_percent
EP: 155/155 current/max -- printed by DoGauge called by do_prompt_percent


Note that EP is the only one that was not at max.
Amended on Tue 01 Mar 2011 06:41 AM by Caelen
USA #45
Caelen said:
I'm not sure what you're asking for... what I pasted above included the command (hp and hpp respectively), the output from the game (the line with HP quantity and HP %), and then what was printed by the debugg scripts.

Oh, heh. I must be more tired than I thought.
#46
Twisol said:

Oh, heh. I must be more tired than I thought.

I broke it down for ya in an edit :x
#47
hp
HP:246/306  SP:33/238  EP:113/155
> 
hpp
HP:80%  SP:13%  EP:72%
HP:244/306%80 -- printed
SP:30/238%13 -- printed
EP:20/155%72 -- printed
> 


printing all from the do_prompt_percent...

the HP one looks right, and the SP one too...

but the EP? O_o
#48
Caelen said:

function do_prompt_percent (name, line, wildcards)

  hpp = tonumber (wildcards [1])
  spp = tonumber (wildcards [2])
  epp = tonumber (wildcards [3])
  hp = max_hp * ( hpp / 100 )
  sp = max_sp * ( spp / 100 )
  ep = max_ep * ( spp / 100 )
  print ("HP:" .. hp .. "/" .. max_hp .. "%" .. hpp)
  print ("SP:" .. sp .. "/" .. max_sp .. "%" .. spp)
  print ("EP:" .. ep .. "/" .. max_ep .. "%" .. epp)

  draw_the_bars ()
      
end -- do_prompt_percent



...

I found the problem XD

ep = max_ep * ( spp / 100 )

spp, not epp... fixed!
Australia Forum Administrator #49
So the debugging prints helped, huh?

That's what usually happens to me. I'm not trying to be smart, I make lots of mistakes. But debugging techniques help find them.
USA #50
D'oh! :D
#51
Definitely helped. Also took a bit more testing to find the problem... I was only testing the EP, which was the problem!

Now... to work on my other project! http://www.gammon.com.au/forum/?id=10962