Jump to content

Photo

Please help me with drawing scripted meters, assigning extra buttons &


  • Please log in to reply
87 replies to this topic

#1 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 16 May 2015 - 09:20 PM

So,yeah, like the title said, I'm having issues with drawing scripted meters on my subscreen, namely that I've got no idea how to use ZScript's draw functions, since I've never needed them, before (making a scripted active subscreen, so no worries about the drawn meters disappearing). I made up these tiles for the meters:

 

Meters.png

 

The meters,themselves are 100 pixels long (not including the frame), and I wanted them to display their fill in a percentage, rounded up (if possible), of what the counter it's assigned to says (for example, if you've got 30 experience, and you need 100 XP to level up,it will be filled in 30 pixels from the left,and the rest of the frame will be empty. I've got a couple other questions, too: If I use this method to create a custom life and magic meter, could I assign the Link's max HP or MP to a number that isn't divisible by 16 or 32, respectively? Like, maybe I want to give him 23 HP to start, would that be possible? Or is the engine restricted to using the 16 HP/32 MP containers, even if you don't use them on the subscreen or in the quest?

 

Anyways I drew this up as a mockup of what I'm going to have the subscreen look like, in its final version:

zelda653_1.png

 

The numbers by each word are the counters to display the current amount in the counter, while the other counter after the slash represents the counter's max value, so the counter should basically be filled by the equation  "(x/y)*100=z" where x=Current counter value, y=Max counter value and z=Number of pixels, from the left to be filled in.

 

Health: Pretty straightforward, first number is Link's current HP,second is his max HP,  functions pretty much just like the normal life gauge, except by percentage, rather than displaying portions of a heart.

 

Stamina: Kinda a "hunger" stat, it starts off full, but as the player moves, the counter drains; after a certain point, (say 33%), Link will start receiving penalties to his damage (I know how to do that part) and taking increased damage from enemies. If you reach 0 stamina, you die, regardless of current health. You'll need to keep stocked up on food and drink items to keep your stamina up.

 

Magic: Again, this is just like the magic gauge, but I'm trying to make it so it works by % and HOPEFULLY, with the option to assign MP to numbers that aren't multiples of 32

 

Experience: Simple (other than drawing the meter), counter and meter start empty. As you kill enemies, the counter increases, and the meter fills, when the counter maxes out,  it increases the "Level" counter by one and resets with a new value. I have a working experience and level script from Sunday Funeral: Destiny's Song, but it was making the quest  lag like a mofo, so I think I'm back to the drawing board with that.

 

Level: Self-explanatory, Link's current level.

 

Obviously none of the meters are functional (since making them function is kinda the point of this thread), but that brings me to my next two questions: You'll notice that I have two extra buttons up there, but I have no idea how to actually MAKE the EX1 and EX2 buttons function for jumping and as a pre-set interaction button (for talking to NPCs, checking signs, etc), respectively,so I could use a walking through of how to do that.

 

Lastly, I'm possibly going to have three separate denominations of currency (gold, silver and copper) as seen above and, between the meters; the extra counters for food, drink and money; and the extra buttons, there's basically no room left for other counters for items like arrows and bombs, is there away to make a counter appear in the lower corner of the "button item" area on the subscreen if you've got a counter item assigned, like if you have bombs,the number in the corner  tells you how many, if you have arrows, it displays the number of arrows, and if it doesn't use a counter, like most items,the counter doesn't show up.

 

I swear, this quest is almost starting to get away from me, in terms of how much scripting I'm using, but  I'm sure if I can learn tango properly, everything else will fall into place.



#2 justin

justin

    Adept

  • Members

Posted 16 May 2015 - 09:30 PM

You're gonna want to learn those draw functions if you're going to create a scripted subscreen .

I made some meters like this for a project I was working on. Basically what I did was draw the bar in whatever color by using the draw rectangle function. Then drew the tile (with transparency where the bar goes) over top using draw tile or draw fast tile. You want to draw to layer 7 and have the specific quest rule that enables drawing over the subscreen. Those draw functions are in zscript.txt under Screen->

This needs to be in your global loop. I can pull up my code if that didn't make sense to you.
  • ShadowTiger likes this

#3 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 16 May 2015 - 10:11 PM

You're gonna want to learn those draw functions if you're going to create a scripted subscreen .

I made some meters like this for a project I was working on. Basically what I did was draw the bar in whatever color by using the draw rectangle function. Then drew the tile (with transparency where the bar goes) over top using draw tile or draw fast tile. You want to draw to layer 7 and have the specific quest rule that enables drawing over the subscreen. Those draw functions are in zscript.txt under Screen->

This needs to be in your global loop. I can pull up my code if that didn't make sense to you.

So, basically,what you're telling me is that I wasted a whole bunch of time drawing tiles I didn't need. Oh well, you live and learn. I just looked through all the rules, and I couldn't find one that says anything about drawing over the subscreen. can you tell me which heading it's under? I'm a little confused on exactly how you draw over the subscreen, though, isn't the top-left corner of the game screen given the coordinate of (0,0)? So  how do you draw above that, where the subscreen is?



#4 MoscowModder

MoscowModder

    Sometimes lurking. Rarely posting.

  • Members
  • Location:Wisconsin

Posted 16 May 2015 - 10:22 PM

If "Subscreen appears over sprites" (or whatever it's called) is checked, you can draw to layer 7 over the subscreen. The subscreen has negative Y coordinates (I think -64 to -1).

 

I agree with justin that rectangle + caps is the easiest way to draw your meters. It might not be exactly pixel-perfect (what with the dark lines at the bottom going up at the ends) without some more tweaking, but the concept is sound.



#5 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 16 May 2015 - 10:42 PM

Oh, yeah,that's checked. What kind of tweaking would it need to give it that extra dimension (the darker line at the bottom)? It looks too flat without it.



#6 MoscowModder

MoscowModder

    Sometimes lurking. Rarely posting.

  • Members
  • Location:Wisconsin

Posted 16 May 2015 - 10:53 PM

You could draw the darker line with a second Rectangle() call, and the leftmost and rightmost pixels that curve up as separate PutPixel() commands.



#7 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 16 May 2015 - 11:38 PM

Ah, I see. and I assume the dimensions of the rectangle would be determined by the percentage of the counter is full? Something like this?

int HP_PERCENT = ((Link->HP / Link->MaxHP) * 100);

//Not sure how all of the variables are supposed to work
Screen->Rectangle(7, 6, -49, (6 + HP_Percent), -45, 121, 1, 0, 0, 0, true, OP_OPAQUE);

Y'know, except knowing what the hell the rangle, rx, ry and scale variables mean. I read it in the ZScript text file, but I didn't understand what I was reading.


Edited by Binx, 17 May 2015 - 01:49 AM.


#8 Lejes

Lejes

    Seeker of Runes

  • Members
  • Location:Flying High Above Monsteropolis

Posted 17 May 2015 - 01:29 AM

Scale should be 1, since you don't want it any smaller or larger than the given dimensions. rx, ry, and rangle should all be 0 since you don't want to rotate the rectangle. And it would be Screen->Rectangle, since that's how you call functions under the Screen namespace.


  • Binx likes this

#9 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 17 May 2015 - 01:50 AM

Oh, cool, thanks. I edited it, so now it should work?  



#10 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 17 May 2015 - 01:50 AM

I'd say, draw the empty gauges, and draw rectangles inside their coordinates on your passive subscreen tiles. Your source gauges would be dark, and fill with whatever light colour you want, with draw commands.
 
As to how to make ex buttons work, in your global active script:
 

void Ex1(int height){
    if ( Link->PressEx1 ){
        Link->Jump = height;
    }
}

void Ex2(){
    if ( Link->PressEx2 ){
        TalkingFunction();
    }
}

 
Put them in your while(true) loop, and the game will always make that button press control a specific routine. I'm pretty sure both of these need to be after Waitdraw(), but that's how you make any button hot at all times. I clearly wrote these as examples...

 

If you want to be able to disable them, tie each to a Boolean array, and use some simple return functions:
 


 
The talking function would be whatever you are using. If you have a function that engages NPCs within x distance and with line of sight, you'd do that here. Otherwise, you could do it directly in your NPC scripts, if you're running them with FFCs.
 
If you are going to use menus, you want to set up your Tango parameters to use the desired Ex button, unless you're using L/R for those.
 
Keep in mind that it doesn't particularly matter to what you map each button, as the user maps buttons to their gamepad however they wish; however, ZC opens the pane for mapping Ex buttons in its own menu choice (Settings->Controls->Extra), rather than storing them in the same set-up pane as the traditional buttons, so you'll need a way to remind players that they need to set those.


Edited by ZoriaRPG, 17 May 2015 - 01:57 AM.


#11 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 17 May 2015 - 03:20 AM

So, I decided to try and test it out, wrote up some counters, and put the following inside my global loop (well,except the constants, those were in a separate script file):

const int CR_GOLD = 7;
const int CR_SILVER = 8;
const int CR_COPPER = 9;
const int CR_MEAT = 10;
const int CR_ALE = 11;
const int CR_HP = 12;
const int CR_MAXHP = 13;
const int CR_SP = 14;
const int CR_MAXSP = 15;
const int CR_MP = 16;
const int CR_MAXMP = 17;
const int CR_XP = 18;
const int CR_MAXXP = 19;
const int CR_LV = 20;

int HP_PERCENT = 100;
int SP_PERCENT = 100;
int MP_PERCENT = 100;
int XP_PERCENT = 100;      




        Game->Counter[CR_HP] = Link->HP;
        Game->Counter[CR_MP] = Link->MP;
        Game->Counter[CR_MAXHP] = Link->MaxHP;
        Game->Counter[CR_MAXMP] = Link->MaxMP; 
        int HP_PERCENT = ((Game->Counter[CR_HP] / Game->Counter[CR_MAXHP]) * 100);
        int SP_PERCENT = ((Game->Counter[CR_SP] / Game->Counter[CR_MAXSP]) * 100);
        int MP_PERCENT = ((Game->Counter[CR_MP] / Game->Counter[CR_MAXMP]) * 100);
        int XP_PERCENT = ((Game->Counter[CR_XP] / Game->Counter[CR_MAXXP]) * 100);
            Screen->Rectangle(7, 6, -48, (6 + HP_PERCENT), -45, 130, 1, 0, 0, 0, true, OP_OPAQUE);
            Screen->Rectangle(7, 6, -36, (6 + SP_PERCENT), -33, 133, 1, 0, 0, 0, true, OP_OPAQUE);
            Screen->Rectangle(7, 6, -24, (6 + MP_PERCENT), -21, 114, 1, 0, 0, 0, true, OP_OPAQUE);
            Screen->Rectangle(7, 6, -12, (6 + XP_PERCENT), -9, 117, 1, 0, 0, 0, true, OP_OPAQUE);
            Screen->DrawTile(7, 0, -54, 41600, 7, 1, 8, 0, 0, 0, 0, 0, 0, true, OP_OPAQUE);
            Screen->DrawTile(7, 0, -42, 41600, 7, 1, 8, 0, 0, 0, 0, 0, 0, true, OP_OPAQUE);
            Screen->DrawTile(7, 0, -29, 41600, 7, 1, 8, 0, 0, 0, 0, 0, 0, true, OP_OPAQUE);
            Screen->DrawTile(7, 0, -45, 41600, 7, 1, 8, 0, 0, 0, 0, 0, 0, true, OP_OPAQUE);

I'm not sure what I am doing wrong, but for some reason the meters themselves work fine, but it's not drawing the frame. It compiled all right, just the frame doesn't show up.


Edited by Binx, 17 May 2015 - 03:20 AM.


#12 Lejes

Lejes

    Seeker of Runes

  • Members
  • Location:Flying High Above Monsteropolis

Posted 17 May 2015 - 03:26 AM

To use the default sizes of block w,h you must

* set xscale and yscale to -1.

 

 

So the two arguments after CSet must be set to -1. Otherwise it will think you want to draw them at a scale of 0 pixels.


  • Binx likes this

#13 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 17 May 2015 - 03:31 AM

Oh, must've missed that part, somehow.

 

EDIT: AHA! Success! Thank you guys! Now I just have to actually set up the stamina and XP counters and set up random max HP and MP at start and it'll be mostly functional!

 

Another edit: Set up the stat table, at least for HP and MP.Was a bit sloppy, had to initialize the stats using an item pickup code, because the global kept resetting them on continue.


Edited by Binx, 17 May 2015 - 04:37 AM.


#14 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 17 May 2015 - 07:01 AM

To be honest, I wouldn't bother using all those counters. You may need them later down the line for in-built functions, and your primary use here seems to be all scripted. You can update counters regularly to keep any in sync with an array index:

For example, if you have three currency types, for three regions, you can assign a single counter to diSplay currency, and only assign the proper currency type to it, based on player location. Copper, silver, and gold, I presume follow one of the standard AD&D value systems. In which case, your player probably won't need to see them constantly. If you're n ot automatically up-sizing the coins, then tracking them at all times is extraneous, because the player will only need to see them when spending, or banking them. You could display those in menus, or only on screens where a shop script is running, and otherwise move them to the active subscreen, so that a player can check therm when they're required.

My own subscreen is a chore, because of all the counters I originally used. I literally ran out of ZC internal counters, before I starting moving all my game vars into arrays.

Food, drink, and so forth, don't require inbuilt counters, as they use no inbuilt features of ZC. You can draw a gauge for them based on a strict percentage, with a tiny bit of math; and tie that to whatever game variables array you're using, so that you don't eat up a counter. Updating from the array is no more difficult. The basic formula, if you make bars 100px long, is:

% = (MAX_VALUE / 100 ) * PRESENT_VALUE

Thus, if you make a very simple function to update an array element BAR_LENGTH, you can call that from draw commands easily.
You can also use the line draw command, instead of rectangle, should you wish, and use the scale argument to widen it. I'm not certain, but I believe that lines are less likely to bog down ZC than rectangles, and given that you will have at least six drawn at all times, it may be prudent to optimise them. I'm going to be using lines as gauges for certain items in LoE, that are only shown when that item is equipped.

I was also planning to kill my ammo counters, and draw ammo counts with character drawing commands, so that only relevant information is seen during the action; but is available on a custom active subscreen, or in Inventory menus at any time.

I happen to like your passive design there too, however, many people will probably say that it's cramped, as they did with mine. Most people have difficulty tracking all their counters as-is...

One other thing to note, is that you can draw metres over the normal display too. I would suggest doing that with the stamina metre, maybe even drawing a small line near the PC at all times, so that people don't die by forgetting to check it. One thing you could do there, is to make a 'pie' gauge with tiles. Eight or ten segments, and have them fall away (by advancing the tile) and draw that somewhere that the player is always likely to be looking.

As long as you are scripting your subscreens, you may also want to ditch the in-built minimap, and draw minimap graphics in a translucent display on the bottom left of the screen, with an option to toggle them on, and off. That will give you more passive subscreen canvas, if you need it.

Using arrays instead of counters is also handy if you want to use for loops:



That's a template for how to draw many bars simultaneously, with one global function to draw them, and one to update their size. The functions allow the input of a specific bar (int bar) if the boolean 'all' is set false, or they will use an array input as 'int bar', and process the entire table if the boolean 'all' is set true.

Warning: This is between versions, and it may include typos, or other minor flaws. I'm pretty sure that I spotted a few, as I changed some values while making it, and I wrote that specifically to apply to this thread. PZC also ate it the first go, so here's round two.

You can see how the table would allow for expansion as needed, and the values can be set from anywhere. In theory, you could allow the player to change the X/Y coordinates to a number of presets.

Because the coordinates are stored in an array, that updates them based on a value also stored in the same array, you can tie them to any object's coordinates, including NPCs, the player, or anything else, and have them move with that object.

Note that you could do vertical bars with a slight modification of these functions:



I believe these should occur after Waitdraw() so that they are as current as possible.

Edited by ZoriaRPG, 17 May 2015 - 07:59 AM.


#15 justin

justin

    Adept

  • Members

Posted 17 May 2015 - 09:36 AM

binx,  i wasn't really paying attention when i posted my previous comment.  probably should have been sleeping instead of prowling the forums...

 

anyways, now i see you actually made tiles for the various percentages.  you could use these, but i'm sure it'll be less efficient than the previous method discussed.  every frame you'd have to run various if/else statements to determine which tiles to draw.

 

it looks like you have 10 tiles for the end caps, and 16 tiles for the middle of the bars.  i'm not sure how many tiles wide the middle of the bar is.  lets say 5 because that would make an even 100% (10+10+(16x5)).  you'd have an if block like this,

 

const int HP_METER_FULLEND = 0;  // tile number of first full end cap (the 100% tile)
const int HP_METER_EMPTYEND = 0 ; // tile number of first empty end cap (the 0% tile)
const int HP_METER_MID = 0; // tile number of the first mid tile
 
int tile2draw;
int hpPercent = (Link->HP / Link->MaxHP) * 100;
 
if(hpPercent > 90)
{
 tile2draw = HP_METER_FULLEND + (hpPercent - 100);
 
 // use the actual Screen->DrawTile or Screen->FastTile for this, i'm just gonna just pseudo code because i don't know all your values
// drawTile HP_METER_EMPTYEND
// drawTile HP_METER_MID x 5
// drawTile tile2draw
}
else if(hpPercent < 10)
{
 tile2draw = HP_METER_EMPTYEND + (hpPercent - 10);
 // as above with pseudo code
 // drawTile tile2draw
 // drawTile (HP_METER_MID+16) x 5
 // drawTile HP_METER_FULLEND+10
}
else
{
 int numFull = Floor( (hpPercent - 10) / 16);
 tile2draw = HP_METER_MID + ((hpPercent - 10) % 16);   // i think this math is wrong, but hopefully you get the idea
 // as above with pseudo code
 // drawTile HP_METER_EMPTYEND;
 // drawTile HP_METER_MID * numFull
 // drawTile tile2draw
 // drawTile HP_METER_FULLEND+10
}

Edited by justin, 17 May 2015 - 09:37 AM.



0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users