Jump to content

Photo

RPG.zh, An RPG System Engine for Zelda Classic

header engine alpha xp script global functions rpg rpgzh

  • Please log in to reply
39 replies to this topic

#16 RetraRoyale

RetraRoyale

    Doyen(ne)

  • Members

Posted 22 April 2014 - 03:24 PM

 

Something like this:

 

void exRand(minvalue, maxvalue, exclude, excludeRange, excludeList)
exclude sets a specific number to exclude.

excludeRange sets a range of numbers to exclude

excludeList reads numbers from a list, and excludes those

If exRand produces a number from any of these excluded values, it clears that value, and produces another random value, repeating this, until it produces one that is not excluded.

 

I should probably add that function to something, as it shouldn't be hard to create, although the excludeList would be a tad tricky to work out in a way that isn't hideous.

 

 

 

 

This is a pretty inefficient implementation of this idea. In general, you should only need a rand() function that gives values between 0 and 1. With that, you can do:

minvalue + rand()*(maxvalue-minvalue)

which gives a range between minvalue and maxvalue, (rounding to int if necessary.) In fact, I wouldn't be surprised if this is how the function is defined. or

exclusionmap( minvalue + rand()*(maxvalue-minvalue-sum(excludelist)) )

where exclusion map adds to a value and offset given by the sum of values on the list that occur before the block that the value lands in. In fact, with this method you can treat zero-minvalue as just part of the excludelist.

 

If you are re-rolling rand(), you never actually know how long your function will run.


Edited by RetraRoyale, 22 April 2014 - 03:24 PM.


#17 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 05 June 2014 - 02:38 AM

For anyone interested, the basic function that I made for this, is as follows:
 
 
int reRand(int min, int max, int exclude){
        int value;
        do{
            value = Rand(min, max);
        }
            while(value < min || value == exclude);
            return value;
        }
 
This only allows a single exclusion, but you could expand it to allow others. I'm not sure what the best method would be to pass these, if you need a long list of excluded values except as elements of an array; else they'd need to be hard-coded in a function; but if anyone wanted an example of an exclusion function, and a use for a do-while loop, that's what this is.

I also updated the package in the OP.

Edited by ZoriaRPG, 05 June 2014 - 09:14 AM.


#18 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 25 July 2014 - 04:53 AM

Updated, 25th July, 2014 (alpha v0,84).



#19 Binx

Binx

    Formerly Lineas

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

Posted 31 January 2015 - 01:10 PM

I was thinking of replacing the HP/MP containers in my quest with a level/XP system that just raises your HP or MP by one container for every level gained (alternating between the two, at level 2 it adds 1 heart container, at level 3  it adds one magic container, at 4  a heart, etc., up to level 30, I believe, if you start with 16 HP and 32 MP and have 16  of each container) and increasing XP needed for each level by a factor of 2 (starting low, at 16 XP to achieve level 2, 32 XP for 3, 64 XP for level 4, etc),but I don't really need a lot (read: any) of the more complex RPG elements, like die rolls or stats, could I still use this header to accomplish my needs, or would I need to build the functions from scratch for this?

 

EDIT: Er... that looks like the max XP needed will be ridiculously high,  considering I was planning on most enemies only giving out 1-4 XP in a shot (except bosses)... maybe a factor of 1.265, starting at 10? That would leave the XP needed for level 30 at about 9,133, if my math is right. Or 1.25, for a total of 6462 xp to get from level 29 to level 30


Edited by Lineas, 31 January 2015 - 01:36 PM.


#20 Lejes

Lejes

    Seeker of Runes

  • Members
  • Location:Flying High Above Monsteropolis

Posted 31 January 2015 - 02:06 PM

It looks like Zoria's header for this is tied pretty heavily to his own stat system, on top of all the level up XP amounts being hardcoded (no convenient array to edit here). The portion that awards XP looks mostly sound, though. It would be pretty easy to modify the level up routine to award only HP and MP instead of all the extra stats that were added, but changing the XP requirements for levels would require a big rewrite. That should be pretty easy for your purposes, though, since your planned XP amounts aren't large enough to roll over any counters. You'd also need a new method for deciding how much XP an enemy is worth, since Zoria's system currently has it tied to the enemy's max HP.


  • Binx likes this

#21 Binx

Binx

    Formerly Lineas

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

Posted 31 January 2015 - 02:12 PM

Yeah, I was afraid of that. Oh well, at least my ability to tell how heavily tied to his stat system it is means I can read his header well enough to probably reverse-engineer a suitable system, I think. Still think I'm gonna use this for my overhaul of TotG, anyways, since it'll go nicely with the new theme and tileset.

 

EDIT: Also, I'm not sure how XP being tied to the enemy HP would be a problem, I'd probably do it differently, maybe make sure all enemy HPs are a power of 2, then assign the XP based on the exponent (not sure if ZScript can do this, otherwise, I could hard code it), so enemies with 2 HP would give 1 XP, 4=2, 8=3, 16=4, 32=5, etc, the only problem I really foresee is that it could cause bosses to give pitiful amounts of XP... Maybe set a misc attribute for bosses that will double or triple the XP drop?


Edited by Lineas, 31 January 2015 - 02:26 PM.


#22 justin

justin

    Adept

  • Members

Posted 31 January 2015 - 02:13 PM

i made a simple xp system awhile back, would be a lot easier to modify to your needs than ZRPGs method.  I'll see if I can find it.


  • Binx likes this

#23 justin

justin

    Adept

  • Members

Posted 31 January 2015 - 03:43 PM

ok, like i said, this is very simple, as in there isn't much to it...  it'll need a bunch of work to fit your needs, but its a start.
 
 
EDIT: i modded this to your request.  I didn't try and compile it.  
 
 
//Constants
const int HP_PER_ODD_LEVEL  = 16;   // a full heart container = 16
const int MP_PER_EVEN_LEVEL = 16;   // a full magic container = 32
 
const float LEVELXP_BASE  = 10;        // the xp required for level1
const float LEVELXP_RATIO = 1.25           
 
//Global variables
int XP = 0;
int level = 0;
 
// Global array for xp amount that each level requires.  number in [] is size of array.
float levelCosts[30];
 
 
// this function is called by XP() function, and checks for enemy HP <= 0, but not yet Dead.  It sets the enemy to Dead, and counts it for XP.  
 
void checkEnemiesKilled(){
    for ( int i = Screen->NumNPCs(); i > 0; i-- ){
        npc enem = Screen->LoadNPC(i);
        if ( enem->HP <= 0 && enem->HP > HP_DEAD ){
            enem->HP = HP_DEAD;
            
            XP += LogToBase(enem->HP,2);   // this is the one you asked for
 
            // XP += enem->Attributes[11];  //i used Enemy Misc Attribute 11 to give each enemy an XP amount.  
                                            //This doesn't conflict with any regular enemy, but it will with Ghosted enemies.
 
 
            // XP += enem->HP;              //ZoriaRPG uses HP as the enemies XP amount
 
            // XP += (enem->HP * enem->Damage) / 100;   // another xp idea
         }
     }
}
 
 
// called by XP() to level the player up.  Add whatever you want to happen with a level up here. 
void LevelUp()
{
    level++;
 
    if(level%2==0) Link->MaxMP += MP_PER_EVEN_LEVEL;    // level is even
    else Link->MaxHP += HP_PER_ODD_LEVEL;               // level is odd
 
    // whatever else should happen 
}   
 
// Call this in your Global loop.  It handles counting dead enemies for Xp, and leveling up.   
void XP() 
{
     checkEnemiesKilled();
     if(XP >= levelCosts[level]) LevelUp; 
}
 
 
// Call this before your Global loop to set the values of the levelCost array.
void SetArray_LevelXP()
{
   for(int i=0; i<=SizeOfArray(levelCosts); i++)
   {
      if(i=0)
      {
         levelCosts[i] = LEVELXP_BASE;
         continue;
      }
      levelCosts[i] = levelCosts[i-1]*LEVELXP_RATIO;
   }
}
 
 
 
// sample Global script
global script Slot_2{
   void run(){
 
      SetArray_LevelXP();
 
      while(true){
 
         XP();
 
         Waitframe();
      }
   }
}
 

Edited by justin, 31 January 2015 - 04:16 PM.


#24 Binx

Binx

    Formerly Lineas

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

Posted 01 February 2015 - 12:15 AM

So, LogToBase(h,2) essentially performs the equation 2^l=h (where l is the "level" of the NPC, and h is the NPC's max HP), then? EDIT: Oh... wait, it's a logarithm... I knew I should have stayed awake in math class. I can't believe I forgot what a logarithm is... I feel like a freaking moron. Seriously. Believe it or not, math used to be my best subject. Wow, I feel stupid. And what do ghosted enemies use Misc. 11 for, anyways? I'm wondering because, like I said, the one major drawback to this method is that in order for bosses to give decent XP, they'd have to have massive amounts of HP. I've figured on two possible ways to get around this, either set the boss drop (or room item, either way) to some kind of "XP Bundle" akin to a heart container, which is kinda messy, or set the misc. 11 attribute to a multiplier and use the following equation, to determine XP:

x= xp

l= enemy level, determined through above equation

m= Misc. 11 attribute

x=l(1+m) (not entirely sure how to write that in code, but I'm sure I can figure it out)

 

This would allow me to use a misc.11 slot to make varying multipliers for XP on enemies, for rare, or boss enemies, while still allowing me to not have to set a Misc.11 on every enemy. It's a much cleaner method of doing it, but, like you said, it will probably screw with ghosted enemies, and I know I'm going to have at least a few of them. But they will likely mostly be bosses, so, whatever autoghost uses Misc. 11 for, I'm sure I can find a way to make the Misc. 11 attribute function for both... well, maybe, like I said, it kinda depends on what the Misc. 11 attribute is used for.


Edited by Lineas, 01 February 2015 - 12:41 AM.


#25 Lejes

Lejes

    Seeker of Runes

  • Members
  • Location:Flying High Above Monsteropolis

Posted 01 February 2015 - 01:44 AM

Ghosted enemies use Misc. Attribute 11 for the combo number they use as a sprite. If it's -1, they use the tile set in the enemy editor instead. I got around this with something I did a while ago by using the Misc array as an intermediary (yes it's different from Miscellaneous Attributes). You add a bit to the global script to set some value in Misc to Miscellaneous Attribute 11. This will set the wrong value for ghosted enemies, but since they're scripted anyway, you just add a line at the beginning of their scripts to reset it.

 

ghost->Misc[0] = m;


#26 Binx

Binx

    Formerly Lineas

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

Posted 01 February 2015 - 02:14 AM

So, if I'm understanding this correctly, by adding that line of code to the global, and the other to all ghosted enemies, you essentially create a second Misc. attribute that you can use to free up the misc. 11 slot?



#27 Lejes

Lejes

    Seeker of Runes

  • Members
  • Location:Flying High Above Monsteropolis

Posted 01 February 2015 - 06:17 AM

That's the line you would add to the ghosted enemies. The global would check through all enemies continuously, and copy attribute 11 into Misc[0] if it's still at 0. Then the XP award function would check Misc[0] instead of looking at attribute 11 directly.



#28 justin

justin

    Adept

  • Members

Posted 01 February 2015 - 10:09 AM

don't feel too bad on the logarithm thing, it took me awhile to figure out what your pattern was mathematically.

 

if you like the Misc Attribute 11 method but want to have a few ghosted enemies and bosses.  you could use MA11 for every regular enemy, and just reference a list of your Ghost enemy#s and have those manually set.  the following code fragment won't compile, but shows the idea.

 

// where ghostid# would be the enemy editor #s of the ghosted enemies.  This could be just inputted as a number here, or create constants to represent.
 
if(enem->ID == ghostid#) XP += 10;
else if(enem->ID == ghostid#) XP += 15;
else XP += enem->Attributes[11];

 

another way could be to have an array that stores all the XP for each enemy#.

 

// where number in [] brackets is +1 the highest enemy# in your quest
// numbers in {} brackets are the xp amounts.  i set it up in a table format for easier inputting/changing.  random xp amounts added.
int enemyXP[255] = {
// 0      1      2      3      4       5       6        7         8         9          //enemy#s, rows are 10s
   2,     2,     4,    10,   15,     8,      5,       3,        1,        4,         //+0
   4,     ....                                                                                 //+10
   10, ....                                                                                  //+20
 //etc...
};
 
// then in the checkEnemiesKilled() function xp is set by...
XP += enemyXP[ enem->ID ];

 

for boss rooms you could have an FFC that checks for 0 enemies onscreen, and gives XP based on D0.

 

ffc script BossXP
{
   void run(int bossxp)
   {
       if(Screen->D[0] == 1) Quit();                // if other scripts are using Screen->D[0] you can change the number to something else unused less than 8.
       while(Screen->NumNPCs() > 0) Waitframe();
       XP += bossxp;
       Screen->D[0] = 1;                               // and then change this one too.
       Quit();
    }
}

 

sorry, i don't understand your xp equation.  seems like unnecessary math since you could just input the xp you want in the first place in misc->attribute 11 which is included in the formula.

and Lejes workaround seems overly complicated, and i don't quite get how its allowing you to use MA11 for multiple things.



#29 Binx

Binx

    Formerly Lineas

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

Posted 01 February 2015 - 10:28 AM

Oh, it's totally unnecessary math, basically,what it does is uses the logarithm to determine the "level" of the enemy based on  the base of 2 and enemy HP (an enemy  with 2 HP is level 1, 4 is level 2, 8 is level 3, and so on), then it would multiply that "level" by 1 plus the Misc 11 attribute, so, for most enemies, with a misc 11 attribute of 0, the XP will be the same as their level (which is the reason for the 1+ in the equation), while bosses, and rare enemies will have misc. 11 set to a number between 1 and 4 which will act as the multiplier (a misc. 11 attribute of 1 will double the XP dropped, 2 will triple it, 3 will quadruple it and 4 will quintuple it). Doing it this way would allow me to set the Misc. 11 attribute ONLY on the enemies that would have unusual XP totals. The boss room FFC is probably the cleanest way to do it; however, I'm not sure how well it'll work, for me, since the majority of my bosses will be a group of 3-5 enemies.



#30 justin

justin

    Adept

  • Members

Posted 01 February 2015 - 10:47 AM

i get what the formula does.  i just don't know why you'd do it like that.  your misc attribute11 is still used, even 0 is still using it, so you can't use ghosted enemies without workarounds.  if you're using MA11 why not just set it based on whatever xp formula you like.  doing all that math everytime is unnecessary when working with static numbers - just do the math once.

 

the boss room ffc only gives the xp when there are no enemies left on screen, so works perfectly fine with groups of enemies.   





Also tagged with one or more of these keywords: header, engine, alpha, xp, script, global, functions, rpg, rpgzh

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users