• All, Gmail is currently rejecting messages from my host. I have a ticket in process, but it may take some time to resolve. Until further notice, do NOT use Gmail for your accounts. You will be unable to receive confirmations and two factor messages to login.

Add the partner menu of streets of rage 2 by Kratus in all OpenBOR games.

Steven1985

Active member
Hello,
I would like to add the Streets of Rage 2 menu created by Kratus, which allows you to insert to the game a partner controlled by the CPU, in all OpenBOR games.
I read all the lines of the script related to the partner.
I would like to know which line of the script commands the game to have the energy bar moving with the character (see screenshot below) and how to make it fixed equal to that of the player.
In the game there is only the possibility of inserting Axel but I would like to have the choice of inserting the available characters (even later those to be unlocked in the game) until I have a maximum of 3 at the same time.
I would like the partner menu to appear immediately when I press select. What should I write to the script?
 
Hello Steven1985

I would like to know which line of the script commands the game to have the energy bar moving with the character (see screenshot below) and how to make it fixed equal to that of the player
The script that controls the lifebar is the one I posted below, you need to call it in a "ondraw.c" event at the character's header, like this:

Code:
ondrawscript		data/scripts/ondraw/lifebar.c

Here's the script:

Code:
void main()
{//Draw life bar in the screen, entity binded like RPG games
	void self = getlocalvar("self");
	
	if(openborvariant("in_level")){ //IN ANY LEVEL??
		int maxLife	= getentityproperty(self, "maxhealth");
		int life 	= getentityproperty(self, "health");
		int x 		= getentityproperty(self, "x");
		int y 		= getentityproperty(self, "y");
		int z 		= getentityproperty(self, "z");
		float xPos 	= openborvariant("xpos");
		float yPos 	= openborvariant("ypos");
		float xSize	= 20; //BAR WIDTH INCREASE FACTOR, MORE VALUE IS MORE SIZE
		float ySize	= 2; //BAR HEIGHT INCREASE FACTOR, MORE VALUE IS MORE SIZE
		float xDif	= 0; //BAR POSITION IN X AXIS, USE THIS TO MOVE ALL BARS TOGETHER
		float yDif	= 0; //BAR POSITION IN Y AXIS, USE THIS TO MOVE ALL BARS TOGETHER
		
		if(life > 0){ //ENTITY IS ALIVE??
			life 		= (life*xSize)/(maxLife); //CALCULATE REMAINING LIFE BAR SIZE
			maxLife		= (maxLife*xSize)/(maxLife); //CALCULATE MAX LIFE BAR SIZE
			x 			= x-xPos-(maxLife/2)+xDif; //CALCULATE X POSITION TO BIND BAR IN THE ENTITY, OFFSET IS ALWAYS THE CENTER
			y 			= z-yPos-y+yDif; //CALCULATE Y POSITION TO BIND BAR IN THE ENTITY
			drawbox(x, y, life, ySize, z+3, rgbcolor(0xFF,0xFF,0x00), 0); //YELLOW BAR, LIFE REMAINING
			drawbox(x, y, maxLife, ySize, z+1, rgbcolor(0xFF,0x00,0x00), 0); //RED BAR, LIFE LOST
			drawbox(x, y-1, maxLife, ySize*2, z, rgbcolor(0xFF,0xFF,0xFF), 0); //WHITE BORDER (UP/DOWN)
			drawbox(x-1, y, maxLife+2, ySize, z, rgbcolor(0xFF,0xFF,0xFF), 0); //WHITE BORDER (LEFT/RIGHT)
		}
	}
}

In the game there is only the possibility of inserting Axel but I would like to have the choice of inserting the available characters (even later those to be unlocked in the game) until I have a maximum of 3 at the same time.
I would like the partner menu to appear immediately when I press select. What should I write to the script?
Basically the menu is working based on two events, they are "keyall.c" (USED TO DETECT KEYS PRESSED AND CHANGE OPTIONS) and "updated.c" (USED TO WRITE ALL CONTENT IN THE SCREEN). A few other details related to the partners are working in some events like "level.c" and "endlevel.c".
I suggest you to open the SOR2X game, take a look in all codes and get the ones you want in your game. You can find all cpu partner's related scripts by searching for a keyword "partner" in your text editor.

Note that you will need to remove a lot of things you will not use in your project, but don't worry, I can help you during this process. A tip may help you, if you are using the Notepad++, press "Ctrl+F" and go to the option "Find in files". Select the "scripts" folder and write "partner" in the keyword section.
 
Kratus said:
Hello Steven1985

I would like to know which line of the script commands the game to have the energy bar moving with the character (see screenshot below) and how to make it fixed equal to that of the player
The script that controls the lifebar is the one I posted below, you need to call it in a "ondraw.c" event at the character's header, like this:

Code:
ondrawscript		data/scripts/ondraw/lifebar.c

Here's the script:

Code:
void main()
{//Draw life bar in the screen, entity binded like RPG games
	void self = getlocalvar("self");
	
	if(openborvariant("in_level")){ //IN ANY LEVEL??
		int maxLife	= getentityproperty(self, "maxhealth");
		int life 	= getentityproperty(self, "health");
		int x 		= getentityproperty(self, "x");
		int y 		= getentityproperty(self, "y");
		int z 		= getentityproperty(self, "z");
		float xPos 	= openborvariant("xpos");
		float yPos 	= openborvariant("ypos");
		float xSize	= 20; //BAR WIDTH INCREASE FACTOR, MORE VALUE IS MORE SIZE
		float ySize	= 2; //BAR HEIGHT INCREASE FACTOR, MORE VALUE IS MORE SIZE
		float xDif	= 0; //BAR POSITION IN X AXIS, USE THIS TO MOVE ALL BARS TOGETHER
		float yDif	= 0; //BAR POSITION IN Y AXIS, USE THIS TO MOVE ALL BARS TOGETHER
		
		if(life > 0){ //ENTITY IS ALIVE??
			life 		= (life*xSize)/(maxLife); //CALCULATE REMAINING LIFE BAR SIZE
			maxLife		= (maxLife*xSize)/(maxLife); //CALCULATE MAX LIFE BAR SIZE
			x 			= x-xPos-(maxLife/2)+xDif; //CALCULATE X POSITION TO BIND BAR IN THE ENTITY, OFFSET IS ALWAYS THE CENTER
			y 			= z-yPos-y+yDif; //CALCULATE Y POSITION TO BIND BAR IN THE ENTITY
			drawbox(x, y, life, ySize, z+3, rgbcolor(0xFF,0xFF,0x00), 0); //YELLOW BAR, LIFE REMAINING
			drawbox(x, y, maxLife, ySize, z+1, rgbcolor(0xFF,0x00,0x00), 0); //RED BAR, LIFE LOST
			drawbox(x, y-1, maxLife, ySize*2, z, rgbcolor(0xFF,0xFF,0xFF), 0); //WHITE BORDER (UP/DOWN)
			drawbox(x-1, y, maxLife+2, ySize, z, rgbcolor(0xFF,0xFF,0xFF), 0); //WHITE BORDER (LEFT/RIGHT)
		}
	}
}

In the game there is only the possibility of inserting Axel but I would like to have the choice of inserting the available characters (even later those to be unlocked in the game) until I have a maximum of 3 at the same time.
I would like the partner menu to appear immediately when I press select. What should I write to the script?
Basically the menu is working based on two events, they are "keyall.c" (USED TO DETECT KEYS PRESSED AND CHANGE OPTIONS) and "updated.c" (USED TO WRITE ALL CONTENT IN THE SCREEN). A few other details related to the partners are working in some events like "level.c" and "endlevel.c".
I suggest you to open the SOR2X game, take a look in all codes and get the ones you want in your game. You can find all cpu partner's related scripts by searching for a keyword "partner" in your text editor.

Note that you will need to remove a lot of things you will not use in your project, but don't worry, I can help you during this process. A tip may help you, if you are using the Notepad++, press "Ctrl+F" and go to the option "Find in files". Select the "scripts" folder and write "partner" in the keyword section.

Hi Kratus, I followed all that you wrote using the game Beats of Rage but it doesn't work. I had to remove the files updated, main, key1, key 2, key 4 and level bacause didn't start the game resulting error in OpenBorLog. I created a video that shows what I did. First I show the files that I removed and for second the files that I put in the folder data - scripts. Also I copied the file menu of the controls from "sor" to "bor". I chose as ally NPC the character Max.


This is the game:
 
Steven1985

First, for better code reading/editing I strongly suggest using another text editor, like the Notepad++.

About the script, it's not possible to make it work by copying exactly the same code inside your game. You need to analyze the code and make the necessary changes to adapt it for your game.
Please, send me a copy of the game you are editing in the video and I can make a reduced version of the extra menu as an example. After the script edition, I will post and explain the changes here because it can help other modders too.

About the events, I'm not using the "key1.c, key2.c, etc...", I'm using the keyall.c.
 
Kratus said:
Steven1985

First, for better code reading/editing I strongly suggest using another text editor, like the Notepad++.

About the script, it's not possible to make it work by copying exactly the same code inside your game. You need to analyze the code and make the necessary changes to adapt it for your game.
Please, send me a copy of the game you are editing in the video and I can make a reduced version of the extra menu as an example. After the script edition, I will post and explain the changes here because it can help other modders too.

About the events, I'm not using the "key1.c, key2.c, etc...", I'm using the keyall.c.

How can I send the copy of the game?
 
How can I send the copy of the game?
You can create a *.zip file and upload to a cloud service, like Google Drive or One Drive. After that, you can share the link here for download.
 
Kratus said:
How can I send the copy of the game?
You can create a *.zip file and upload to a cloud service, like Google Drive or One Drive. After that, you can share the link here for download.

Thank you. I'd like to play Final Fight LNS Ultimate with your script. Could you do it?
 
Thank you. I'd like to play Final Fight LNS Ultimate with your script. Could you do it?
Sorry man, this game uses a modified OpenBOR version and unfortunately I can't help. However I can still help you in other games that are using the official OpenBOR engine.
 
Kratus said:
Thank you. I'd like to play Final Fight LNS Ultimate with your script. Could you do it?
Sorry man, this game uses a modified OpenBOR version and unfortunately I can't help. However I can still help you in other games that are using the official OpenBOR engine.
Hi Kratus, I chose the game Beat'emUp Ultimate Alliance 2020 which has three bars: green one (health), celeste one (consumed when I block a punch so I believe it is the MP bar but you will tell me if I said correctly), red one (consumed when I perform the super and special moves). In other games I have seen that the mp bar is used both for parrying and for making special moves (example Final Fight Gold), here are two distinct ones.

You can download it from here: https://www.mediafire.com/file/y7ncmq4ry75ydz0/Beat%27emUpUltimateAlliance2020.rar/file
 
Steven1985 said:
Kratus said:
Thank you. I'd like to play Final Fight LNS Ultimate with your script. Could you do it?
Sorry man, this game uses a modified OpenBOR version and unfortunately I can't help. However I can still help you in other games that are using the official OpenBOR engine.
Hi Kratus, I chose the game Beat'emUp Ultimate Alliance 2020 which has three bars: green one (health), celeste one (consumed when I block a punch so I believe it is the MP bar but you will tell me if I said correctly), red one (consumed when I perform the super and special moves). In other games I have seen that the mp bar is used both for parrying and for making special moves (example Final Fight Gold), here are two distinct ones.

You can download it from here: https://www.mediafire.com/file/y7ncmq4ry75ydz0/Beat%27emUpUltimateAlliance2020.rar/file
Ok, I will check it. This Beat'emUp Ultimate Alliance 2020 is based on the first SOR2X versions, v1.0 or 1.1 if I'm not wrong.
 
Steven1985

As I promised, I created a small version of the SOR2X menu to add npc entities as cpu partners. Note that all codes below have only basic functions to show how it works as a start point, and along the way you can improve it.

This menu works only in the level by pressing the screenshot button, note that the screenshot function is disabled in this case. To spawn a cpu partner you will need to press the attack button when the menu is open and the "spawn" option is highlighted, but you can change it if you want.

Most script lines are commented to make it easier to understand.

Step 1: Create the npc entities and add in the MODELS.TXT file

MODELS.TXT
Code:
load	Galsia_			data/chars/galsia/galsia_partner.txt
load	Donovan_		data/chars/donovan/donovan_partner.txt

GALSIA_PARTNER.TXT
Code:
name				Galsia_
type				npc
hostile				enemy
candamage			enemy obstacle

DONOVAN_PARTNER.TXT
Code:
name				Donovan_
type				npc
hostile				enemy
candamage			enemy obstacle

Note that you will need to adjust all enemy properties like "candamage" or "hostile", to make them fight against the cpu partners properly.

Step 2: Create the file KEYALL.C inside the folder "data/scripts", and add a script used to capture the keys pressed and change the options

KEYALL.C
Code:
void main()
{
	menuPartners();
}

void menuPartners()
{//Change Partner Menu options

	int player	= getlocalvar("player");
	int highlight	= getglobalvar("highlight");
	int hasplayed	= getplayerproperty(player, "hasplayed"); //CHECK IF THE PLAYER ENTERED THE CURRENT GAME
	
	//MAIN COMMAND TO OPEN AND CLOSE PARTNER MENU
	if(playerkeys(player, 1, "screenshot") && hasplayed == 1){ //SELECT BUTTON IS PRESSED BY A PLAYER THAT ENTERED IN THE GAME??
		if(openborvariant("in_level")){ //CHECK IF THE GAME IS IN ANY LEVEL
			if(openborvariant("pause") == 0 && openborvariant("in_options") != 1){ //CHECK IF THE GAME IS NOT PAUSED OR IN OPTIONS
				if(getglobalvar("activeText") == 0){ //CHECK IF ANY MENU IS ALREADY ON
					playsample(openborconstant("SAMPLE_BEEP2"), 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0); //PLAY SAMPLE
					changeopenborvariant("nopause", 1); //LOCK PAUSE COMMAND
					changeopenborvariant("textbox", 1); //CALL TEXTBOX TO FREEZE THE GAME
					setglobalvar("highlight", 0); //SET TO THE FIRST HIGHLIGHTED OPTION
					setglobalvar("activeText", "Partner"); //SET ACTIVE TEXT ON SCREEN TO "PARTNER MENU" TO ACTIVATE OTHER SCRIPTS
				}
				else
				if(getglobalvar("activeText") == "Partner"){ //CHECK IF EXTRA MENU IS ALREADY ON
					playsample(openborconstant("SAMPLE_BEEP2"), 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0); //PLAY SAMPLE
					changeopenborvariant("nopause", 0); //UNLOCK PAUSE COMMAND
					changeopenborvariant("textbox", NULL()); //CLEAR TEXTBOX TO NOT FREEZE THE GAME
					setglobalvar("highlight", 0); //RESET HIGHLIGHT VARIABLE TO DEFAULT
					setglobalvar("activeText", 0); //SET ACTIVE TEXT ON SCREEN TO "0" TO DEACTIVATE OTHER SCRIPTS
				}
			}
		}
	}

	//HIGHLIGHT OPTIONS:
	//1 - PARTNER MODE
	//2 - PARTNER SPAWN
	
	void self	= getplayerproperty(player, "entity"); //GET THE CURRENT "SELF" ENTITY
	int lives	= getplayerproperty(player, "lives"); //GET THE CURRENT NUMBER OF LIVES
	int dir		= getentityproperty(self, "direction"); //GET THE CURRENT DIRECTION
	int min		= 0; //FIRST LINE OF THE MENU
	int max		= 1; //LAST LINE OF THE MENU
	int add		= 1; //HOW MUCH LINES IS ADDED EACH TIME THE DIRECTION BUTTON IS PRESSED
	float x		= getentityproperty(self, "x"); //CURRENT PLAYER X POSITION
	float y		= getentityproperty(self, "y"); //CURRENT PLAYER Y POSITION
	float z		= getentityproperty(self, "z"); //CURRENT PLAYER Z POSITION
	
	if(getglobalvar("activeText") == "Partner" && hasplayed == 1){ //PARTNER MENU IS ON?? RUN ALL TASKS BELOW

		//HIGHLIGHT OPTIONS WHEN MOVE DOWN
		if(playerkeys(player, 1, "movedown")){
			playsample(openborconstant("SAMPLE_BEEP"), 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
			if(highlight >= min && highlight < max){setglobalvar("highlight", highlight+1);}
			if(highlight == max){setglobalvar("highlight", min);}
		}
		
		//HIGHLIGHT OPTIONS WHEN MOVE UP
		if(playerkeys(player, 1, "moveup")){
			playsample(openborconstant("SAMPLE_BEEP"), 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
			if(highlight > min && highlight <= max){setglobalvar("highlight", highlight-1);}
			if(highlight == min){setglobalvar("highlight", max);}
		}
		
		//CHANGE ALL OPTIONS INSIDE THIS MENU WHEN MOVE RIGHT
		if(playerkeys(player, 1, "moveright")){
			playsample(openborconstant("SAMPLE_BEEP"), 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
			
			//IS PARTNER MODE HIGHLIGHTED??
			if(getglobalvar("highlight") == 0){
				if(getglobalvar("partnerMode") == "balanced"){setglobalvar("partnerMode", "aggressive");}else
				if(getglobalvar("partnerMode") == "aggressive"){setglobalvar("partnerMode", "defensive");}else
				if(getglobalvar("partnerMode") == "defensive"){setglobalvar("partnerMode", "balanced");}
			}
			
			//IS PARTNER NAME HIGHLIGHTED??
			if(getglobalvar("highlight") == 1){
				if(getglobalvar("selectPartner") == "Galsia_"){setglobalvar("selectPartner", "Donovan_");}else
				if(getglobalvar("selectPartner") == "Donovan_"){setglobalvar("selectPartner", "Galsia_");}
			}
		}
		
		//CHANGE ALL OPTIONS INSIDE THIS MENU WHEN MOVE LEFT
		if(playerkeys(player, 1, "moveleft")){
			playsample(openborconstant("SAMPLE_BEEP"), 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
			
			//IS PARTNER MODE HIGHLIGHTED??
			if(getglobalvar("highlight") == 0){
				if(getglobalvar("partnerMode") == "balanced"){setglobalvar("partnerMode", "defensive");}else
				if(getglobalvar("partnerMode") == "defensive"){setglobalvar("partnerMode", "aggressive");}else
				if(getglobalvar("partnerMode") == "aggressive"){setglobalvar("partnerMode", "balanced");}
			}
			
			//IS PARTNER NAME HIGHLIGHTED??
			if(getglobalvar("highlight") == 1){
				if(getglobalvar("selectPartner") == "Galsia_"){setglobalvar("selectPartner", "Donovan_");}else
				if(getglobalvar("selectPartner") == "Donovan_"){setglobalvar("selectPartner", "Galsia_");}
			}
		}
		
		//SPAWN CPU PARTNER IN-GAME
		if(playerkeys(player, 1, "attack")){ //ATTACK BUTTON IS PRESSED??
			if(getglobalvar("highlight") == max){ //IS PARTNER SPAWN OPTION HIGHLIGHTED??
				if(lives >= 2){ //HAVE THE PLAYER ENOUGH LIVES TO DEDUCT??

					void vSpawn; //START THE SPAWN OPERATION
					playsample(openborconstant("SAMPLE_BEEP2"), 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0); //PLAY SAMPLE
					changeplayerproperty(player, "lives", lives-1); //DEDUCT PLAYER LIVES
					clearspawnentry(); //CLEAR CURRENT SPAWN ENTRY
					setspawnentry("name", getglobalvar("selectPartner")); //ACQUIRE SPAWN ENTITY BY NAME
					vSpawn = spawn(); //SPAWN IN ENTITY
					changeentityproperty(vSpawn, "position", x, z, y+300); //SET SPAWN POSITION
					changeentityproperty(vSpawn, "direction", dir); //SET SPAWN DIRECTION
					setglobalvar("highlight", 0); //RESET THE HIGHLIGHT OPTION
					
					return vSpawn; //RETURN SPAWN
				}
			}
		}
	}
}

Step 3: Create the file LEVEL.C inside the folder "data/scripts" and add a script to start all necessary variables when a level starts. Note that you can run this script in other events too, choose the one that it's better for you.

LEVEL.C
Code:
void main()
{
	menuPartners();
}

void menuPartners()
{//Run some necessary tasks for the menu when any level starts
	
	//TURN OFF THE SCREENSHOT BUTTON
	if(openborvariant("noscreenshot") != 1){changeopenborvariant("noscreenshot", 1);}

	//LOAD ALL NECESSARY VARIABLES BY THE FIRST TIME
	if(getglobalvar("activeText") == NULL()){setglobalvar("activeText", 0);}
	if(getglobalvar("highlight") != 0){setglobalvar("highlight", 0);}
	if(getglobalvar("partnerMode") == NULL()){setglobalvar("partnerMode", "balanced");}
	if(getglobalvar("selectPartner") == NULL()){setglobalvar("selectPartner", "Galsia_");}
}

Step 4: Create the file UPDATED.C inside the folder "data/scripts" and add a script to draw all content in the screen.

Note that you can write all text by using other events like "ondrawscript", and you can use "settextobj" function instead of the "drawstring" if you want.

UPDATED.C
Code:
void main()
{
	menuPartners();
}

void menuPartners()
{//Draw a CPU Partner Menu in game
	
	//DRAW MENU IN-GAME
	if(getglobalvar("activeText") == "Partner"){
		void str;			//USED TO DEFINE THE CURRENT "STRING" TEXT
		int screen	= openborvariant("hresolution"); //CURRENT SCREEN RESOLUTION
		int align;			//USED BY THE "STRWIDTH" FUNCTION TO ALIGN TEXT AUTOMATICALLY
		int xCol1	= 231;		//BASE X POSITION, FIRST COLUMN (HIGHLIGHTED OPTIONS NAME)
		int xDif	= 20;		//DIFFERENCE BETWEEN THE FIRST AND THE SECOND COLUMNS
		int xCol2	= xCol1+xDif;	//BASE X POSITION, SECOND COLUMN (HIGHLIGHTED OPTIONS VALUE)
		int fontTitle	= 2;		//FONT USED ONLY FOR THE MENU TITLE
		int yPos	= 90;		//BASE Y POSITION FOR ALL MENU CONTENT IN GAME, USE THIS TO MOVE ALL OPTIONS TOGETHER
		int font0	= 0;		//THIS FONT CHANGES FROM 0 TO 1 IF THE OPTION IS HIGHLIGHTED
		int font1	= 0;		//THIS FONT CHANGES FROM 0 TO 1 IF THE OPTION IS HIGHLIGHTED
		int yLine	= 11;		//SPACE BETWEEN TEXT LINES
		int layer	= 1000000003;	//DEFAULT TEXT LAYER
		
		//DEFINE FONTS TO HIGHLIGHTED OPTIONS
		if(getglobalvar("highlight") == 0){font0 = 1;}else	//IS PARTNER MODE HIGHLIGHTED??
		if(getglobalvar("highlight") == 1){font1 = 1;}		//IS PARTNER SPAWN HIGHLIGHTED??
		
		//DRAW MENU TITLE
		drawstring((screen-strwidth("partner_menu", fontTitle))/2, yPos-yLine*2, fontTitle, "partner_menu", layer);

		//DRAW MENU CONTENT
		str  = "fighting_mode:";align = xCol1-strwidth(str, font0);
		drawstring(align, yPos, font0, str, layer);
		drawstring(xCol2, yPos, font0, getglobalvar("partnerMode"), layer);
		
		str  = "spawn:";align = xCol1-strwidth(str, font0);
		yPos = yPos+yLine;
		drawstring(align, yPos, font1, str, layer);
		drawstring(xCol2, yPos, font1, getglobalvar("selectPartner"), layer);
	}
}

Step 5 (OPTIONAL): Create the file THINK.C inside the folder "data/scripts" and add a script to change the cpu partner behaviour. Note that this step is optional, I'm using this event in SOR2X to change a lot of A.I. rules, but it's not mandatory if you want only to spawn a cpu partner in the level. In the example I made, this function changes the partner's "aimove" (avoid, chase, normal).

THINK.C
Code:
void main()
{
	menuPartners();
}

void menuPartners()
{//Changes options in Partner Menu
	void self	= getlocalvar("self");
	void pMode	= getglobalvar("partnerMode");
	void aimove	= getentityproperty(self, "aimove");
	
	//PARTNER MODE
	if(pMode == "balanced" && aimove != openborconstant("AIMOVE1_NORMAL")){changeentityproperty(self, "aimove", openborconstant("AIMOVE1_NORMAL"));}else
	if(pMode == "aggressive" && aimove != openborconstant("AIMOVE1_CHASE")){changeentityproperty(self, "aimove", openborconstant("AIMOVE1_CHASE"));}else
	if(pMode == "defensive" && aimove != openborconstant("AIMOVE1_AVOID")){changeentityproperty(self, "aimove", openborconstant("AIMOVE1_AVOID"));}
}

Don't forget to call the THINK.C script by adding the following line on all cpu partner's header
Code:
thinkscript		data/scripts/think.c

Step 6 (OPTIONAL): This step is used only for the BEAT'EM UP ALLIANCE OR SOR2X games due to the "onspawn" script event. In these games, some properties are applied by script instead of the character's header, and you will need to add the cpu partner's names on the respective files.

Note that you can use the properties applied by the character's header instead of the "onspawnscript" event, it's not mandatory.

For example, the Galsia partner can be edited in the file "data/scripts/onspawn/galsia.c" file, same goes for Donovan partner, like this:

GALSIA.C
Code:
}else if(vRName == "Galsia_"){
	vAlias		= "Brash";
	iMHealth	= 250;
	iHealth 	= iMHealth;
	iSpeed 		= 1.6;
	iAggre 		= 400;
	iMap		= 4;
}

DONOVAN.C
Code:
}else if(vRName == "Donovan_"){
	vAlias		= "Altet";
	iMHealth	= 250;
	iHealth 	= iMHealth;
	iSpeed 		= 1.6;
	iAggre 		= 400;
	iMap		= 4;	
}

In the video below I'm showing the script working:
https://www.youtube.com/watch?v=i1oVsP0dn8Y

And here's the game with all edited files:
https://drive.google.com/file/d/1ieNGZReb0CqRcSPCrqRUaSD1yN32JRLj/view?usp=sharing

I hope it helps :)
 
Kratus said:

You are a great boy!!! I don't know how to thank you! As soon as I have time I will see all that and I will let you know. Take care of yourself :)

Mod edit: please don't quote long posts.
 
I have seen only the video for now. I'd like that when the ally hits an enemy, his health bar is shown like if he was hit by player. I'd also like that the ally has the same bars on screen like the player: if I spawn the first ally, his bars should stay in the part of the second player , the second ally as third player ect.
 
Steven1985 said:
Kratus

I meant the red bar of the game above. That bar with the word MAX above the player :)

Steven1985

Sorry, now I understand what bar you are talking about :)

In this game, the green bar is the "lbarsize", the blue bar is a "custom" one to show the "guardpoints", and the red bar is the "mpbarsize".
This blue bar is scripted, I added it in older SOR2X versions but in the latest it was removed.
 
Great work my friend!

It really is a great addiction.
I have many doubts about it, but I will check it with time, to be able to understand better.

Thank you so much for sharing it!  ;)
 
Hi Kratus a question arose: if for example I have to insert the script of step 2 and the keyall.c file is already present in the game, just copy and paste the script under what is already written?

And another thing: I tried to put the menu to Final_Fight_X following carefully your instructions but the game doesn't run because it has an error.
 
Hello my friend!

I have followed your steps to implement this system in my mod, but I have problems with the KEYALL.C and the UPDATED.C.

Currently I already have these files in my mod, and I can't get your files to correctly insert into them without getting script errors.
There is no doubt that the error is mine, since although I have learned a lot over the years, scripts are not my greatest skill.

Can you help me to correctly insert the scripts in my files?

Here my KEYALL.C without changes:
Code:
#include "data/scripts/story/story_keys.c"

void main()
{
	storyKeys();
}

And here my UPDATED.C without changes :
Code:
#include "data/scripts/anititle.c"
#include "data/scripts/story/story_define.h"
#include "data/scripts/story.c"
#include "data/scripts/gettick.c"
#include "data/scripts/playsound.c"




void zoom()
{
   void vscreen = openborvariant("vscreen");
   int maxz=openborvariant("PLAYER_MAX_Z")+1000;
   int zoom_value=getglobalvar("zoomvalue");
   int zoom_x=getglobalvar("zoomx");
   int zoom_y=getglobalvar("zoomy");
   void ent=getglobalvar("zoomentity");
   int px=getentityproperty(ent,"x") +  zoom_x - openborvariant("xpos");
   int py=getentityproperty(ent,"z") + zoom_y - openborvariant("ypos") - getentityproperty(ent,"a");
   void zoom_scr = getglobalvar("zoomscreen");
   if(!zoom_scr){
      zoom_scr = allocscreen(openborvariant("hResolution"),openborvariant("vResolution"));
      setglobalvar("zoomscreen",zoom_scr);
   }
   clearscreen(zoom_scr);

   //draw what we need 
   drawspriteq(zoom_scr,0,openborconstant("MIN_INT"),maxz,0,0);
   //setup drawMethod
   //setdrawmethod(NULL(), 0); // ADDED - Nullify the trail effect
   changedrawmethod(NULL(),"reset",1);
   changedrawmethod(NULL(),"enabled",1);
   changedrawmethod(NULL(),"scalex",zoom_value);
   changedrawmethod(NULL(),"scaley",zoom_value);
   changedrawmethod(NULL(),"centerx",px);
   changedrawmethod(NULL(),"centery",py);
   //Draw the resized customized screen to main screen.
   drawscreen(zoom_scr,px,py, maxz+1);
   changedrawmethod(NULL(),"enabled", 0);
   drawspriteq(vscreen, 0, maxz+1,maxz+1, 0, 0);
   drawspriteq(vscreen, 0, maxz+2,openborconstant("MAX_INT"), 0, 0);
    changedrawmethod(NULL(),"reset",1);
   clearspriteq();
}


void main(){

   processRushCount();

   if(getglobalvar("zoomentity"))
   {
      zoom();      
   }
      mainLoop();
}

void mainLoop(){
	void scene=openborvariant("current_scene");
	if(openborvariant("in_level"))
	{
		turnWhite();
		storySystem();
	}
	if(openborvariant("in_titlescreen")){
		if (scene!="data/scenes/intro.txt"){
			inTitleLoop(1);
		}
	}
	else {
		inTitleLoop(0);	
	}
                selectScreenEvent();  
}


void selectScreenEvent(){
	int was_in_selectscreen = getlocalvar("was_in_selectscreen");
	if(openborvariant("in_selectscreen")){
		if(was_in_selectscreen == NULL() || !was_in_selectscreen){
			playSound("data/sounds/wellcome.wav");
			setlocalvar("was_in_selectscreen", 1);
		}
	} else {
		if(was_in_selectscreen != NULL() && was_in_selectscreen != 0) setlocalvar("was_in_selectscreen", 0);
	}
}

void rushCountSound(int rush_count){
	if (rush_count == 3) {
	int iSnd = loadsample("data/sounds/hits3_triple.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
	else if (rush_count == 4){
	int iSnd = loadsample("data/sounds/hits4_super.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
	else if (rush_count == 5){
	int iSnd = loadsample("data/sounds/hits5_hyper.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
	else if (rush_count == 6){
	int iSnd = loadsample("data/sounds/hits6_brutal.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
	else if (rush_count == 7){
	int iSnd = loadsample("data/sounds/hits7_master.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
	else if (rush_count == 8){
	int iSnd = loadsample("data/sounds/hits8_awesome.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
	else if (rush_count == 9){
	int iSnd = loadsample("data/sounds/hits9_blaster.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
	else if (rush_count == 10){
	int iSnd = loadsample("data/sounds/hits10_monster.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
	else if (rush_count == 11){
	int iSnd = loadsample("data/sounds/hits11_king.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
	else if (rush_count >= 12 && rush_count <=20){
	int iSnd = loadsample("data/sounds/hits12_killer.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
	else if (rush_count >= 21 && rush_count <=30){
	int iSnd = loadsample("data/sounds/hits13_ultra.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
   else if (rush_count >= 31){
   int iSnd = loadsample("data/sounds/hitsx_ultimate.wav");
   playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
   }   		
	
	
}


void processRushCount(){
	void vEnt = getplayerproperty(0, "entity");
	if(vEnt != NULL()){
		int lastRushCount = getentityvar(vEnt, "last_rush_count");
		int rushCount = getentityproperty(vEnt, "rush_count");
		
		if(lastRushCount != NULL() && rushCount < lastRushCount){ // Combo ended, play sound
			rushCountSound(lastRushCount);
		}
		setentityvar(vEnt, "last_rush_count", rushCount);
		
	}
	
}
 
Steven1985 dantedevil

Hi Kratus a question arose: if for example I have to insert the script of step 2 and the keyall.c file is already present in the game, just copy and paste the script under what is already written?
Yeah, you can copy the entire "menuPartners" function inside your current "keyall.c" file, and call it in your "void main" function, same as the script I posted before.

Below is an example of how to add a new script to an existing file, let's use the UPDATED.C file as example, same goes to an KEYALL.C script and other events too.
In this case we will add the "menuPartners" function to the dantedevil's UPDATED.C file:

Code:
#include "data/scripts/anititle.c"
#include "data/scripts/story/story_define.h"
#include "data/scripts/story.c"
#include "data/scripts/gettick.c"
#include "data/scripts/playsound.c"




void zoom()
{
   void vscreen = openborvariant("vscreen");
   int maxz=openborvariant("PLAYER_MAX_Z")+1000;
   int zoom_value=getglobalvar("zoomvalue");
   int zoom_x=getglobalvar("zoomx");
   int zoom_y=getglobalvar("zoomy");
   void ent=getglobalvar("zoomentity");
   int px=getentityproperty(ent,"x") +  zoom_x - openborvariant("xpos");
   int py=getentityproperty(ent,"z") + zoom_y - openborvariant("ypos") - getentityproperty(ent,"a");
   void zoom_scr = getglobalvar("zoomscreen");
   if(!zoom_scr){
      zoom_scr = allocscreen(openborvariant("hResolution"),openborvariant("vResolution"));
      setglobalvar("zoomscreen",zoom_scr);
   }
   clearscreen(zoom_scr);

   //draw what we need
   drawspriteq(zoom_scr,0,openborconstant("MIN_INT"),maxz,0,0);
   //setup drawMethod
   //setdrawmethod(NULL(), 0); // ADDED - Nullify the trail effect
   changedrawmethod(NULL(),"reset",1);
   changedrawmethod(NULL(),"enabled",1);
   changedrawmethod(NULL(),"scalex",zoom_value);
   changedrawmethod(NULL(),"scaley",zoom_value);
   changedrawmethod(NULL(),"centerx",px);
   changedrawmethod(NULL(),"centery",py);
   //Draw the resized customized screen to main screen.
   drawscreen(zoom_scr,px,py, maxz+1);
   changedrawmethod(NULL(),"enabled", 0);
   drawspriteq(vscreen, 0, maxz+1,maxz+1, 0, 0);
   drawspriteq(vscreen, 0, maxz+2,openborconstant("MAX_INT"), 0, 0);
    changedrawmethod(NULL(),"reset",1);
   clearspriteq();
}


void main(){

   processRushCount();
   menuPartners();

   if(getglobalvar("zoomentity"))
   {
      zoom();     
   }
      mainLoop();
}

void mainLoop(){
	void scene=openborvariant("current_scene");
	if(openborvariant("in_level"))
	{
		turnWhite();
		storySystem();
	}
	if(openborvariant("in_titlescreen")){
		if (scene!="data/scenes/intro.txt"){
			inTitleLoop(1);
		}
	}
	else {
		inTitleLoop(0);	
	}
                selectScreenEvent(); 
}


void selectScreenEvent(){
	int was_in_selectscreen = getlocalvar("was_in_selectscreen");
	if(openborvariant("in_selectscreen")){
		if(was_in_selectscreen == NULL() || !was_in_selectscreen){
			playSound("data/sounds/wellcome.wav");
			setlocalvar("was_in_selectscreen", 1);
		}
	} else {
		if(was_in_selectscreen != NULL() && was_in_selectscreen != 0) setlocalvar("was_in_selectscreen", 0);
	}
}

void rushCountSound(int rush_count){
	if (rush_count == 3) {
	int iSnd = loadsample("data/sounds/hits3_triple.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
	else if (rush_count == 4){
	int iSnd = loadsample("data/sounds/hits4_super.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
	else if (rush_count == 5){
	int iSnd = loadsample("data/sounds/hits5_hyper.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
	else if (rush_count == 6){
	int iSnd = loadsample("data/sounds/hits6_brutal.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
	else if (rush_count == 7){
	int iSnd = loadsample("data/sounds/hits7_master.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
	else if (rush_count == 8){
	int iSnd = loadsample("data/sounds/hits8_awesome.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
	else if (rush_count == 9){
	int iSnd = loadsample("data/sounds/hits9_blaster.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
	else if (rush_count == 10){
	int iSnd = loadsample("data/sounds/hits10_monster.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
	else if (rush_count == 11){
	int iSnd = loadsample("data/sounds/hits11_king.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
	else if (rush_count >= 12 && rush_count <=20){
	int iSnd = loadsample("data/sounds/hits12_killer.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
	else if (rush_count >= 21 && rush_count <=30){
	int iSnd = loadsample("data/sounds/hits13_ultra.wav");
	playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
	}
   else if (rush_count >= 31){
   int iSnd = loadsample("data/sounds/hitsx_ultimate.wav");
   playsample(iSnd, 0, openborvariant("effectvol"), openborvariant("effectvol"), 100, 0);
   }   		
	
	
}


void processRushCount(){
	void vEnt = getplayerproperty(0, "entity");
	if(vEnt != NULL()){
		int lastRushCount = getentityvar(vEnt, "last_rush_count");
		int rushCount = getentityproperty(vEnt, "rush_count");
		
		if(lastRushCount != NULL() && rushCount < lastRushCount){ // Combo ended, play sound
			rushCountSound(lastRushCount);
		}
		setentityvar(vEnt, "last_rush_count", rushCount);
		
	}
	
}

void menuPartners()
{//Draw a CPU Partner Menu in game
	
	//DRAW MENU IN-GAME
	if(getglobalvar("activeText") == "Partner"){
		void str;			//USED TO DEFINE THE CURRENT "STRING" TEXT
		int screen	= openborvariant("hresolution"); //CURRENT SCREEN RESOLUTION
		int align;			//USED BY THE "STRWIDTH" FUNCTION TO ALIGN TEXT AUTOMATICALLY
		int xCol1	= 231;		//BASE X POSITION, FIRST COLUMN (HIGHLIGHTED OPTIONS NAME)
		int xDif	= 20;		//DIFFERENCE BETWEEN THE FIRST AND THE SECOND COLUMNS
		int xCol2	= xCol1+xDif;	//BASE X POSITION, SECOND COLUMN (HIGHLIGHTED OPTIONS VALUE)
		int fontTitle	= 2;		//FONT USED ONLY FOR THE MENU TITLE
		int yPos	= 90;		//BASE Y POSITION FOR ALL MENU CONTENT IN GAME, USE THIS TO MOVE ALL OPTIONS TOGETHER
		int font0	= 0;		//THIS FONT CHANGES FROM 0 TO 1 IF THE OPTION IS HIGHLIGHTED
		int font1	= 0;		//THIS FONT CHANGES FROM 0 TO 1 IF THE OPTION IS HIGHLIGHTED
		int yLine	= 11;		//SPACE BETWEEN TEXT LINES
		int layer	= 1000000003;	//DEFAULT TEXT LAYER
		
		//DEFINE FONTS TO HIGHLIGHTED OPTIONS
		if(getglobalvar("highlight") == 0){font0 = 1;}else	//IS PARTNER MODE HIGHLIGHTED??
		if(getglobalvar("highlight") == 1){font1 = 1;}		//IS PARTNER SPAWN HIGHLIGHTED??
		
		//DRAW MENU TITLE
		drawstring((screen-strwidth("partner_menu", fontTitle))/2, yPos-yLine*2, fontTitle, "partner_menu", layer);

		//DRAW MENU CONTENT
		str  = "fighting_mode:";align = xCol1-strwidth(str, font0);
		drawstring(align, yPos, font0, str, layer);
		drawstring(xCol2, yPos, font0, getglobalvar("partnerMode"), layer);
		
		str  = "spawn:";align = xCol1-strwidth(str, font0);
		yPos = yPos+yLine;
		drawstring(align, yPos, font1, str, layer);
		drawstring(xCol2, yPos, font1, getglobalvar("selectPartner"), layer);
	}
}

And another thing: I tried to put the menu to Final_Fight_X following carefully your instructions but the game doesn't run because it has an error.
Please, post your log.txt file here and I can take a look. Maybe there's some conflict with existing scripts in this game.

Currently I already have these files in my mod, and I can't get your files to correctly insert into them without getting script errors
Same as Steven's game, would be good if I can take a look at your log.txt file
 
Back
Top Bottom