Jump to content

Photo

Help with enemy script / leveling enemies


  • Please log in to reply
44 replies to this topic

#31 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 31 October 2015 - 12:43 AM

Link->Misc isn't saved between sessions. F6 Continue and saving and quitting both reset it to zero. A simple global variable for miscellaneous items like the Triforce would have to do. Since I was bored I went ahead and made this script.

 

Enemy Level Up

 

I included a debug display that shows the stats of an enemy in the room (press Ex1 to change which enemy's stats are displayed). This is just a first pass. The multipliers as-is produce ludicrously high values, and you'd probably want to add exceptions for certain enemy types, more specific item rules, etc.

 

Sigh. Nothing is ever saved. I should know that by now.

 

I'll need to remember to add a function to store that datum, and load it per session in the RPG header, as I'll probably use Link->Misc for a few minor things.

 

Would people by unhappy / would it break things if the Link->Misc vars were stored? I would be willing to do that, for a future ZC version, but I fear what terrible things it could cause...and I'm not willing to add a QR for that behaviour.


Edited by ZoriaRPG, 31 October 2015 - 12:45 AM.


#32 Flying Fish

Flying Fish

    King of the Fish

  • Members
  • Real Name:Flying fish
  • Location:Under the sea

Posted 31 October 2015 - 08:28 AM

Can ZCscript save changes to declared variables or does it reset to default similar to the Misc when you transition from screen to screen, F-6, quit or continue? 



#33 Lejes

Lejes

    Seeker of Runes

  • Members
  • Location:Flying High Above Monsteropolis

Posted 31 October 2015 - 07:11 PM

Only global variables (those declared outside of any script) are saved. Anything local to a function or script won't be.



#34 Flying Fish

Flying Fish

    King of the Fish

  • Members
  • Real Name:Flying fish
  • Location:Under the sea

Posted 31 October 2015 - 07:48 PM

can I make permanent changes to global variables from the declared value and if so i make changes to the global variables with-in a script and will that still save?



#35 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 31 October 2015 - 08:14 PM

can I make permanent changes to global variables from the declared value and if so i make changes to the global variables with-in a script and will that still save?

 
The easiest way to do this, is to use one large (global) array, and store your script variables in it.
 
You can copy any local vars to it, and then copy them back, when a game resumes, as needed too; but if you want to preserve values, it's best to plan ahead, use one array with constants for each index position.
 
I uploaded some ZScript files from RPG.zh to here so that you can see examples of how to do this.

 

RPG_Backup.zlib is a good reference, as I made functions purely for this kine of thing, as well as script saving (and restoring) routines.

 

If you look at RPG_Engine.zlib, you'll find the arrays, while RPG_Constants.zlib will demonstrate how to use constants for the index positions, and RPG_Functions.zlib has the routines for easily returning (or setting) values from them.

 

For more information on using arrays:

http://www.shardstor...cript_Tutorial)

http://www.shardstor...rrays_(ZScript)



#36 Flying Fish

Flying Fish

    King of the Fish

  • Members
  • Real Name:Flying fish
  • Location:Under the sea

Posted 31 October 2015 - 10:50 PM

I got this working and the enemies will increase their stats every time you acquire an item. I made a silly multiplier for now just to see the stats increase easier while in testing. 

This is what I have so far

import "std.zh"
import "ffcscript.zh"

int MEXPM = 7;
int enehealth = 1;
int enepow = 1;
int wenepow = 1;

global script Mexp
{
void run (){
while (true)
{
	ELevelup();
	Eapply();
	Waitframe();
}
}
}

void ELevelup() {
npc eexp;
if (MEXPM == 8)
	{
	enehealth = enehealth  * 2.1;
	enepow = enepow * 2.1;
	wenepow = wenepow * 2.1;
	MEXPM = 7;
	}
}

void Eapply(){
npc eexp;
for (int npccounter = 1; npccounter <= Screen->NumNPCs(); npccounter ++)
{
     eexp = Screen->LoadNPC(npccounter);
     if (eexp->Misc[0] == 0)
     {
          eexp->Damage *= enepow;
	  eexp->HP *= enehealth;
          eexp->Misc[0] = 1;
     }
}
}

item script Message{
    void run(int m){
	Screen->Message(m);
	MEXPM = 8;
    }
}

This script turn on the multiplier when Link picks up an item. I just combined a part with enemy level up script with the item pickup message script to active the multiplier. It just doesn't immediately apply the effect to the loaded enemies on the screen already and will if refreshed.   I just have to create limiters for the enemies to prevent some of the basic enemies from getting to strong, a formula that will scale nicely as the game progresses not making enemies to hard to handle during parts of the game, and with the quest i still finalizing all the items that we am going to use (which will impact the scale).  That item display script Lejes created really helped out testing this. I am going to work and research on fixing those issue with scaling/multiplier and setting up limitations to certain enemies.  Thanks for all the help so far with figuring out this and a better understanding of how the ZC coding works.



#37 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 01 November 2015 - 06:56 AM

Here's your script, tabbed, with a method to avoid using specific enemies:



...and here is the same, cleaned up, with constants, to improve readability. It also uses only four of the 256 (maximum) global registers: Two from the arrays, and two from the perpetual function calls. That is a reduction of 2 total, from the previous version.

Global variables of any type, eat up one register each, and each function call eats one, to two regs, on average. FUnction calls release, when they pop off, but as you are making them every frame, you need to count them as used.

I try to conserve as many gd registers as possible, as I have run out.



If you noted how this becomes easier to read, brilliant. I also need to re-read this topic, to see why you are using values '7' and '8' for storing if you should, or should not boost enemies. I could improve readability even further, if those values were 0/1.

Edited by ZoriaRPG, 01 November 2015 - 07:16 AM.


#38 Flying Fish

Flying Fish

    King of the Fish

  • Members
  • Real Name:Flying fish
  • Location:Under the sea

Posted 01 November 2015 - 08:16 AM

The seven and the eight have no purpose I just using it as a switch to turn on the multiplier. Those number are from a left over from trying other things and did not change it to a zero and one.



#39 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 01 November 2015 - 08:44 AM

In that case...
import "std.zh"
import "ffcscript.zh"

//Main arrays.

int EnemiesNotToBump[]={0,200}; 	//Populate this with the IDs of enemies for which you DO NOT want to 
					//increase stats. 

int EnemyStatBoosts[4]={0,1,1,1}; 	//Replace the four global vars with an array, and...


	
//EnemyStatBoost[] indices
const int ENEM_STATS_BOOSTED = 0;	//Assign constants to each index for easy use. 
const int ENEM_HEALTH = 1;
const int ENEM_POW = 2;
const int ENEM_WEAP_POW = 3;

//npc->Misc[] indices
const int ENEMY_LEVEL_INCREASE = 0; //npc->Misc[0]

//EnemyStatBoost[ENEM_STATS_BOOSTED] & npc->Misc[ENEMY_LEVEL_INCREASE] Values
const int ENEM_BOOST_NOT_APPLIED = 0; 
const int ENEM_BOOST_APPLIED = 1;





global script Mexp
{
	void run (){
		while (true)
		{
			ELevelup();
			Eapply();
			Waitdraw();
			Waitframe();
		}
	}
}

void ELevelup() {
	npc eexp;
	if ( EnemyStatBoosts[ENEM_STATS_BOOSTED] )
	{
		EnemyStatBoosts[ENEM_HEALTH] = EnemyStatBoosts[ENEM_HEALTH]  * 2.1;
		EnemyStatBoosts[ENEM_POW] = EnemyStatBoosts[ENEM_POW] * 2.1;
		EnemyStatBoosts[ENEM_WEAP_POW] = EnemyStatBoosts[ENEM_WEAP_POW] * 2.1;
		EnemyStatBoosts[ENEM_STATS_BOOSTED] = ENEM_BOOST_NOT_APPLIED;
	}
}

void Eapply(){
	npc eexp;
	for (int npccounter = 1; npccounter <= Screen->NumNPCs(); npccounter ++)
	{
		exp = Screen->LoadNPC(npccounter);
		for ( int q = 0; q <= SizeOfArray(EnemiesNotToBump); q++ ) {
			if ( !eexp->Misc[ENEMY_LEVEL_INCREASE] && eexp->ID != EnemiesNotToBump[q] )
			{
				eexp->Damage *= EnemyStatBoosts[ENEM_POW];
				eexp->HP *= EnemyStatBoosts[ENEM_HEALTH];
				eexp->Misc[ENEMY_LEVEL_INCREASE] = ENEM_BOOST_APPLIED;
			}
		}
	}
}

item script Message
{
	void run(int m)
	{
		Screen->Message(m);
		EnemyStatBoosts[ENEM_STATS_BOOSTED] = ENEM_BOOST_APPLIED;
	}
}

Edited by ZoriaRPG, 01 November 2015 - 08:55 AM.


#40 Flying Fish

Flying Fish

    King of the Fish

  • Members
  • Real Name:Flying fish
  • Location:Under the sea

Posted 01 November 2015 - 09:49 AM

I was planning on having all enemies stats increase but some will have a cap earlier than others. for example I do not want a keese to scale to have really high stats, but a reasonable stats when you approach the end game.

I would have to modify this ....

void Eapply(){
	npc eexp;
	for (int npccounter = 1; npccounter <= Screen->NumNPCs(); npccounter ++)
	{
		exp = Screen->LoadNPC(npccounter);
		for ( int q = 0; q <= SizeOfArray(EnemiesNotToBump); q++ ) {
			if ( !eexp->Misc[ENEMY_LEVEL_INCREASE] && eexp->ID != EnemiesNotToBump[q] )
			{
				eexp->Damage *= EnemyStatBoosts[ENEM_POW];
				eexp->HP *= EnemyStatBoosts[ENEM_HEALTH];
				eexp->Misc[ENEMY_LEVEL_INCREASE] = ENEM_BOOST_APPLIED;
			}
		}
	}
}

and the array to incorporate a cap for each monster so they do not get over powered and some monster to have an earlier cap versus the items you acquire.



#41 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 01 November 2015 - 10:16 AM

I was planning on having all enemies stats increase but some will have a cap earlier than others. for example I do not want a keese to scale to have really high stats, but a reasonable stats when you approach the end game.
I would have to modify this ....

void Eapply(){
	npc eexp;
	for (int npccounter = 1; npccounter <= Screen->NumNPCs(); npccounter ++)
	{
		exp = Screen->LoadNPC(npccounter);
		for ( int q = 0; q <= SizeOfArray(EnemiesNotToBump); q++ ) {
			if ( !eexp->Misc[ENEMY_LEVEL_INCREASE] && eexp->ID != EnemiesNotToBump[q] )
			{
				eexp->Damage *= EnemyStatBoosts[ENEM_POW];
				eexp->HP *= EnemyStatBoosts[ENEM_HEALTH];
				eexp->Misc[ENEMY_LEVEL_INCREASE] = ENEM_BOOST_APPLIED;
			}
		}
	}
}

and the array to incorporate a cap for each monster so they do not get over powered and some monster to have an earlier cap versus the items you acquire.


That's pretty much encroaching on the same ground that I've proved in the RPG header. Just make lists with a size of 512, and insert your caps. Then, you can compare enem->ID against the index of the list, and if it is already at its cap, don;t increase it.

#42 Flying Fish

Flying Fish

    King of the Fish

  • Members
  • Real Name:Flying fish
  • Location:Under the sea

Posted 02 November 2015 - 09:39 AM

Had to take a break from this, to much information and currently breaking it down for me to understand, which will take awhile. 

 

I will be starting to building the array for the capping system for certain enemies and a cap one for all the enemies to prevent them from getting way to powerful i make it stop after so many items are collected, since all items will trigger a stat buff but i might make the cap around 80% of the items collected. i think this will be fair and prevent impossible monsters, and because I am allowing the player free access to the all the dungeons after you acquire the basic items and there is no order in acquiring items/equipment I have to apply the multiplier effect on each item and having a final cap is the way i have to go.  

 

My last problem is getting over the truncated integers since the enemies have low stats to start with and the multiplier will most likely be truncated to 1x multiplier (for example I want the enemy to increase their base stats by 10% each time an item is collected and enemy like a Keese (which its base stats are 1 hp, 2 power, 2 w_power) will never have it stats increased since the multiplier will be truncated to 1 on each upgrade). I will not be able to work on this part till i get the total amount of items that are going to be added to the game and I come up with a good formula for the stat boost for the enemies.



#43 Lejes

Lejes

    Seeker of Runes

  • Members
  • Location:Flying High Above Monsteropolis

Posted 02 November 2015 - 09:57 AM

The multiplier itself would never be truncated, though. Only the actual enemy stats would be. As soon as the multiplier hits 1.5, Keese's damage and weapon damage will increase, and the HP will follow when the multiplier is 2.



#44 Flying Fish

Flying Fish

    King of the Fish

  • Members
  • Real Name:Flying fish
  • Location:Under the sea

Posted 02 November 2015 - 10:37 AM

I was running into that problem when I was testing an 10% increase and even gathering over the majority of items and heart containers, it was still showed the keese having base stats and still dying to the wooden sword in one hit.



#45 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 02 November 2015 - 01:56 PM

Add this anywhere in that while(true) loop:
 

if ( Link->InputEx1() && Link->InputEx2() ) TestEnemyStatBoosts();

Then add this anywhere at the end of that script:
 

void TestEnemyStatBooosts(){
    int testingStr[]="Tracing EnemyStatBoosts[]";
    int index0[]="Boost Applied?: ";
    int index1[]="Health Modifier: ";
    int index2[]="Power Modifier: ";
    int index3[]="Weapon Power Modifier: ";
    int yes[]="Yes.";
    int no[]="No.";

    TraceNL(); TraceS(testingStr); TraceNL();
    TraceS(index0); if ( EnemyStatBoosts[ENEM_STATS_BOOSTED] ) TraceS(yes); 
        else TraceS(no); Trace(EnemyStatBoosts[ENEM_STATS_BOOSTED]); TraceNL();
    TraceS(index1); Trace(EnemyStatBoosts[ENEM_HEALTH]); TraceNL();
    TraceS(index2); Trace(EnemyStatBoosts[ENEM_POW]); TraceNL();
    TraceS(index3); Trace(EnemyStatBoosts[ENEM_WEAP_POW]); TraceNL();
    
}

With that, if you press Ex1 and Ex2 at the same time, you will print out the information on the array, with verbose reporting, to allegro.log.

This is hos I set up my tracing routines, in general. Note that I make a function, put strings in it, so that they are local to the function, and use the strings with TraceS() ,  and TraceNL() for line breaks, to make a report that a human can both read, and easily find with a keyword search in allegro.log.

 

Using a button press combination like this, allows you to make several different types of reports, tied to different button pairs, and prevents flooding allegro.log with traces.

 

I also prefer to keep my related instruction son the same line, rather than making each Trace instruction on a separate line. They are grouped in threes, each for a particular string, and the information linked to it, except the one line with an if/else yes/no response. I included that, just so that you have an example of setting up a verbose logging function.

I also suggest using SciTE or Notepad++ (I prefer SciTE) to view the log...and to make your code, in general, if you don't already use them.

 

Spoiler

Edited by ZoriaRPG, 02 November 2015 - 01:58 PM.



1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users