Variable AI & entity shuffle tutorial

Bloodbane

i have made this character as the "base" -
Code:
name zombieL-M
health 50
nolife 1
type enemy
#lifespan 3
shadow 3
gfxshadow 1
noquake 1
falldie 1
nodieblink 3
animationscript data/scripts/zombie.c
weapons zombiel zombiel-3 zombiel-6 zombiel-8 zombiel-10 zombiel-14 zombieL-M
weaploss 3
modelflag 3
palette data/chars/zombie/00a
alternatepal data/chars/zombie/alt1a
alternatepal data/chars/zombie/alt2a
alternatepal data/chars/zombie/alt3a
alternatepal data/chars/zombie/alt4a
alternatepal data/chars/zombie/alt2a
load zombiel
load zombiel-3
load zombiel-6
load zombiel-8
load zombiel-10
load zombiel-14

anim spawn
delay	1
offset  124 124
        bbox 0 0 0 0
@script
	if(frame == 0){
	void self = getlocalvar("self");
	int map = rand()%5;
	if(map < 0)
	{
	-map == map;
	}
	changeentityproperty(self, "map", map);
	}
	@end_script
	frame	data/chars/zombie/01
@script
    void self = getlocalvar("self");
    if( frame == 0){
      int r = rand()%45;
      if( r > 30){
        changeentityproperty(self, "animpos", 3);
      } else if( r < -29){
        changeentityproperty(self, "animpos", 5);
      } else if( r > 14){
        changeentityproperty(self, "animpos", 1);
      } else if( r < -14){
        changeentityproperty(self, "animpos", 7);
      } else if( r < 0){
        changeentityproperty(self, "animpos", 9);
      } else if( r > 0){
        changeentityproperty(self, "animpos", 11);
      }
    }
	@end_script
	@script
	void self = getlocalvar("self");
	if(frame == 2){
	changeentityproperty(self, "aiflag", "attacking", 1);
	changeentityproperty(self, "aiflag", "idling", 0);
	changeentityproperty(self, "takeaction", "common_attack_proc");
	changeentityproperty(self, "animation", openborconstant("ANI_FOLLOW1"));
	}
	@end_script
	frame	data/chars/zombie/01
        frame	data/chars/zombie/01
	
        @script
	void self = getlocalvar("self");
	if(frame == 4){
	changeentityproperty(self, "aiflag", "attacking", 1);
	changeentityproperty(self, "aiflag", "idling", 0);
	changeentityproperty(self, "takeaction", "common_attack_proc");
	changeentityproperty(self, "animation", openborconstant("ANI_FOLLOW2"));
	}
	@end_script
        frame	data/chars/zombie/01
        frame	data/chars/zombie/01

        @script
	void self = getlocalvar("self");
	if(frame == 6){
	changeentityproperty(self, "aiflag", "attacking", 1);
	changeentityproperty(self, "aiflag", "idling", 0);
	changeentityproperty(self, "takeaction", "common_attack_proc");
	changeentityproperty(self, "animation", openborconstant("ANI_FOLLOW3"));
	}
	@end_script
        frame	data/chars/zombie/01
        frame	data/chars/zombie/01

        @script
	void self = getlocalvar("self");
	if(frame == 8){
	changeentityproperty(self, "aiflag", "attacking", 1);
	changeentityproperty(self, "aiflag", "idling", 0);
	changeentityproperty(self, "takeaction", "common_attack_proc");
	changeentityproperty(self, "animation", openborconstant("ANI_FOLLOW4"));
	}
	@end_script    
        frame	data/chars/zombie/01
        frame	data/chars/zombie/01

        @script
	void self = getlocalvar("self");
	if(frame == 10){
	changeentityproperty(self, "aiflag", "attacking", 1);
	changeentityproperty(self, "aiflag", "idling", 0);
	changeentityproperty(self, "takeaction", "common_attack_proc");
	changeentityproperty(self, "animation", openborconstant("ANI_FOLLOW5"));
	}
	@end_script    
        frame	data/chars/zombie/01
        frame	data/chars/zombie/01

        @script
	void self = getlocalvar("self");
	if(frame == 12){
	changeentityproperty(self, "aiflag", "attacking", 1);
	changeentityproperty(self, "aiflag", "idling", 0);
	changeentityproperty(self, "takeaction", "common_attack_proc");
	changeentityproperty(self, "animation", openborconstant("ANI_FOLLOW6"));
	}
	@end_script    
        frame	data/chars/zombie/01
        frame	data/chars/zombie/01

anim follow1
delay	1
offset  124 124
        bbox 0 0 0 0
	weaponframe 0 1
        frame	data/chars/zombie/01

anim follow2
delay	1
offset  124 124
        bbox 0 0 0 0
	weaponframe 0 2
        frame	data/chars/zombie/01

anim follow3
delay	1
offset  124 124
        bbox 0 0 0 0
	weaponframe 0 3
        frame	data/chars/zombie/01

anim follow4
delay	1
offset  124 124
        bbox 0 0 0 0
	weaponframe 0 4
        frame	data/chars/zombie/01

anim follow5
delay	1
offset  124 124
        bbox 0 0 0 0
	weaponframe 0 5
        frame	data/chars/zombie/01

anim follow6
delay	1
offset  124 124
        bbox 0 0 0 0
	weaponframe 0 6
        frame	data/chars/zombie/01

as far as i can tell, the speed changes, the ai seems to match, but the thing that does not change is the health - it seems all versions keep the health the same - do i have to change the health with script before it loads the weapon model?
or is there a missing parameter that i have to change in order for the "weapon model"  to keep its own health?
 
Well I don't see any health change in the script, that might explain why zombie's health remain the same.
You can try adding random health change in the script  :)
 
Bloodbane
the script was a failure - but i got a better solution now with model changes.

it seems that you have to give this "prime" entity the highest health that a model possesses & after the entity changes to the models, the health will adjust to what the model has.

I will need a way to change the health tho - because when the doctor transforms to his new form any of them should have more health...
 
O_Ilusionista

i will try to make a bitwise logic code to see how it fares against the current %50+50 type, i just have to make sure that these two lines are like this right?

@script
void self = getlocalvar("self"); //Get calling entity.
void stage = getglobalvar("stageType");
int Sr = (rand() & 0x7fffffff) % 5 ;

if (frame==0 && stage !="elemental"){
changepal(0);

.............

}
if (frame==4 && stage !="elemental"){
changepal(4);
}


if (frame==5 && stage !="elemental"){
changeentityproperty(self, "map", Sr);
}
@end_script
 
oldyz  "% 5"  means 5 values, starting from 0: 0,1,2,3,4.
That is a 20% chance

the only part you need is this:
Code:
 @script
   void self = getlocalvar("self"); //Get calling entity.
   int Sr = (rand() & 0x7fffffff) % 5 ;
   if (frame=="INSERT FRAME NUMBER HERE"){
   changeentityproperty(self, "map", Sr);
}
@end_script
 
oldyz

As a suggestion, the "drawstring" function can be your best friend when you are developing a script. It will help to see what the engine is doing.

This way you can choose what method is best for your game. In the video below take a look at the left side of the screen, you will see the logic working.

https://www.youtube.com/watch?v=TOuqXUPH_Xs

Here's the code I'm using. I suggest to use in events like update.c, updateentity or ondraw script.
Use the "//" to enable or disable the line you want to test.

Code:
	int Sr;

	if((openborvariant("elapsed_time"))%40==0){ //THIS LINE IS USED ONLY TO SLOWER THE CODE SPEED AND TURN IT EASIER TO SEE, NO NEED TO ADD IT IN YOUR MAIN SCRIPT
		Sr = rand()%50+50;
		//Sr = (rand() & 0x7fffffff) % 5 ;
	}
	
	drawstring(50, 50, 0, Sr); //DRAW THE VALUE IN THE SCREEN
 
Kratus and there is another quick solution for that - text objects
They doesn't need to run on always update scripts, you can set for long they will stay on the screen.
The only thing is: they are level objects, so they will only work during levels

Like this:
Code:
@script
void self = getlocalvar("self"); //Get calling entity.
int Sr = (rand() & 0x7fffffff) % 5 ;
  int text_font   = 2;
  int text_x =  240;
  int text_y =  40;
  void text_z = 99999999;
if (frame=="INSERT FRAME NUMBER HERE"){
settextobj(1, text_x ,  text_y, text_font, text_z, "map: "+Sr, text_duration+openborvariant("elapsed_time")); // debug text
changeentityproperty(self, "map", Sr);
}
@end_script

 
I'll throw in a third - log(). Log is super handy, and follows text rules too (meaning you can add stuff like \n for line breaks and \t for tabs).

Code:
int some_variable = 0;

some_variable++;

log("\n\n Some Variable: " + some_variable);

I open the OpenBOR log with a browser as engine is running and refresh it to see scrolling results.

DC
 
O_Ilusionista
Thanks for the tips, long time I wanted to learn more about the "settextobj" function. It will be useful for me in some scripts.
However, especifically for debug purposes I prefer to use the "drawstring" function to see what the engine is doing in real time.

Damon Caskey
Great, I didn't know that there's a function to write text in the log file, it is very useful for me in some debug scripts I'm using. Thanks!
 
Damon Caskey Kratus O_Ilusionista

thank you guys , i will have to try the logs thing again tho because i was not able to make it work.

i am going to continue now with what i have - i found that the scarce characters make more frequent appearances  by using chance percentages in the double digits & then add 1 or 2 percent points to even out their scarcity.

I was not able to do the code like the codes O_Ilusionista made for the elementals -  i have this weird thing now:

Code:
@script
    void self = getlocalvar("self");
    if( frame == 0){
      int Sr = (rand() & 0x7fffffff) % 93 ;
      if (Sr >= 0 && Sr < 15){
        changeentityproperty(self, "animpos", 1);
      }else if (Sr >= 16 && Sr < 30){
        changeentityproperty(self, "animpos", 2);
      }else if (Sr >= 31 && Sr < 45){ 
        changeentityproperty(self, "animpos", 10);
      }else if (Sr >= 46 && Sr < 60){ 
        changeentityproperty(self, "animpos", 6);
      }else if (Sr >= 61 && Sr < 75){ 
        changeentityproperty(self, "animpos", 8);  
      }else if (Sr >= 76 && Sr < 93){
        changeentityproperty(self, "animpos", 4);   //----- this position would rarely make an appearance, so it has 17 points
      }
    }
	@end_script
 
oldyz there is a problem on your code, take a look:
      }else if (Sr >= 16 && Sr < 30){
        changeentityproperty(self, "animpos", 2);
      }else if (Sr >= 31 && Sr < 45){
        changeentityproperty(self, "animpos", 10);

What happens if Sr == 30? nothing. The same for 15,45, 60 or 93.
Either you have to fix those values or add a "else" on the end to take care of this

You should do in this way:
  if (Sr >= 0 && Sr <= 15){
bla bla bla
}else if (Sr >= 16 && Sr <= 30){
bla bla bla

etc
 
O_Ilusionista
wow , weirdly enough the blasted thing seems to be working as it is, but i will redo all with the corrections

I assume that is not the numbers that have to be corrected, but only the equal signs that are missing - correct? so it should be like this:

}else if (Sr >= 31 && Sr < =  45){

because overlapping numbers like this:

}else if (Sr >= 16 && Sr < =30){
        changeentityproperty(self, "animpos", 2);
      }else if (Sr >= 30 && Sr < = 45){
        changeentityproperty(self, "animpos", 10);
might cause truble
blast, lots to do again
 
Back
Top Bottom