Gamestudio Links
Zorro Links
Newest Posts
Newbie Questions
by fairtrader. 12/05/23 14:22
Zorro Trader GPT
by TipmyPip. 12/04/23 11:34
Square root rule
by Smallz. 12/02/23 09:15
RTest not found error
by TipmyPip. 12/01/23 21:43
neural function for Python to [Train]
by TipmyPip. 12/01/23 14:47
Xor Memory Problem.
by TipmyPip. 11/28/23 14:23
Training with command line parameters
by TipmyPip. 11/26/23 08:42
Combine USD & BTC Pairs In Asset Loop
by TipmyPip. 11/26/23 08:30
AUM Magazine
Latest Screens
A psychological thriller game
SHADOW (2014)
DEAD TASTE
Tactics of World War I
Who's Online Now
4 registered members (AndrewAMD, Quad, soulman3, Ayumi), 675 guests, and 2 spiders.
Key: Admin, Global Mod, Mod
Newest Members
fairtrader, hus, Vurtis, Harry5, KelvinC
19019 Registered Users
Previous Thread
Next Thread
Print Thread
Rate Thread
Page 1 of 2 1 2
multiplayer player missile projectile #434716
12/24/13 18:19
12/24/13 18:19
Joined: Dec 2011
Posts: 1,823
Netherlands
Reconnoiter Offline OP
Serious User
Reconnoiter  Offline OP
Serious User

Joined: Dec 2011
Posts: 1,823
Netherlands
Hey all,

I am making a multiplayer co-op shooter. Player movement etc. works well (thanks to the nice lite-c workshop 25 tutorial laugh ) and I am now trying to get the player projectiles working. While the projectile code work fine on the server+client/host, it is does not work properly on the client. The skills of the projectile are running on the client and sent to the server, which moves the projectile. But the server code does not seems to work (proectile does not move, it is not scaled, flags are not set correctly etc.). The code of projectile is below, thanks for taking the time.
dplay_localfunction = 2;

Code:
action gun_missile()
{
 //on client	
 if (my.client_id == dplay_id)	{
	
	my.WEAPONSELECTED = player.WEAPONSELECTED;
	
        //weapon 1 selected (now only 1 weapon for testing)
	my.LIFETIME = 400;
	my.DAMAGE = 20;
	my.MOVEMENTSPEED = 60;	
	my.AREAOFEFFECT = 40;
	my.EXPLOSIONSIZE = 0.5;
	my.GRAVITY = 0;
	my.AMBIENTSKILL = 100;
	my.SCALESKILL = 0.2;
	my.ALPHASKILL = 100;
	my.ROTATION_PAN = camera.pan+random(1)-0.5; // face same direction as player
	my.ROTATION_TILT = camera.tilt+random(1)-0.5;
	
	//sends info to server
	send_skill(my.WEAPONSELECTED,0);
	send_skill(my.DAMAGE,0); 
	send_skill(my.MOVEMENTSPEED,0); 	
	send_skill(my.AREAOFEFFECT,0); 
	send_skill(my.EXPLOSIONSIZE,0); 
	send_skill(my.GRAVITY,0); 
	send_skill(my.ROTATION_PAN,0);
	send_skill(my.ROTATION_TILT,0);
	send_skill(my.SCALESKILL,0);	
	send_skill(my.AMBIENTSKILL,0);
	if (my.ALPHASKILL != 100) send_skill(my.ALPHASKILL,0);
 }

 //on server	
 if (connection & CONNECT_SERVER) {
 	my.ambient = my.AMBIENTSKILL;  
	vec_scale(my.scale_x,my.SCALESKILL); 
	my.pan = my.ROTATION_PAN; 
	my.tilt = my.ROTATION_TILT;
	my.alpha = my.ALPHASKILL;
	if (my.WEAPONSELECTED != 1) set(my,BRIGHT | TRANSLUCENT);	
 }	
		
	set(my,FLAG2);
	my.group = 3; // runs through all entities with the same group value, group 3 = world & projectiles
	my.CREATOR = player;  
	my.STATE = 1;
	my.roll = random(360);
	my.GRAVITY_SUM = 0;
	
	while(1)
	{	
// state 1: flying ///////////////////////////////////////////  
		if (my.STATE == 1) 
		{
			//on client	
 			if (my.client_id == dplay_id)	{
			my.LIFETIME -= time_step *4;
			my.GRAVITY_SUM -= my.GRAVITY * time_step;
			//sends info to server
			send_skill(my.LIFETIME,SEND_UNRELIABLE);
			send_skill(my.GRAVITY_SUM,SEND_UNRELIABLE); 
			}
			
			//on server	
 			if (connection & CONNECT_SERVER) {
 			if (my.LIFETIME <= 0) my.STATE = 2;	
			c_move(me,vector(my.MOVEMENTSPEED*time_step,0,0),vector(0,0,my.GRAVITY_SUM),IGNORE_MODELS | IGNORE_SPRITES);
			if (HIT_TARGET) my.STATE = 2;  // go to next state
			c_ignore(1,3,0);
			if (c_scan(my.x, my.pan, vector(360, 360, my.AREAOFEFFECT), IGNORE_ME | IGNORE_FLAG2 | IGNORE_PASSABLE) > 0) my.STATE = 2;  // go to next state			
			}
		}

// state 2: exploding ////////////////////////////////////////  
		if (my.STATE == 2) 
		{
			//on server	
 			if (connection & CONNECT_SERVER) {
			set(me,ZNEAR);  // render in front of close objects\
			vec_scale(my.scale_x,1+0.8*time_step);
			if (my.scale_x > my.EXPLOSIONSIZE) { // explosion finished? 
				ent_remove(me);
				return;
			   }
			}   
		} 

		wait(1);	
	}
}


Re: multiplayer player missile projectile [Re: Reconnoiter] #434850
12/28/13 13:47
12/28/13 13:47
Joined: Dec 2011
Posts: 1,823
Netherlands
Reconnoiter Offline OP
Serious User
Reconnoiter  Offline OP
Serious User

Joined: Dec 2011
Posts: 1,823
Netherlands
I think I know what is wrong, but I don't know how to solve it. The problem is probably the following:
Code:
action gun_missile()
{
 //on client	
 if (my.client_id == dplay_id)	{ <- the 'my' is not recognized so the engine ignores the code within the if
	
	my.WEAPONSELECTED = player.WEAPONSELECTED;
....



where the my is not recognized in 'if (my.client_id == dplay_id)'. I don't understand why that the engine does not recognize it though, since it is created only by the player

Code:
// state 2: attack /////////////////////////////////// 
		if (my.STATE == 2) 
		{	
		//on client
		if (my.client_id == dplay_id) {
...ent_create("MissileEnergy.mdl",vector(camera.x+(40)*cos(camera.tilt)*cos(camera.pan),camera.y+(40)*cos(camera.tilt)*sin(camera.pan),camera.z+(40)*sin(camera.tilt)),gun_missile);
...



and the player is created in such a way that it is unique per user/client (I think so atleast):

Code:
function main()
{	
...
if (connection & CONNECT_SERVER) { // this instance of the game runs on the server
     STRING* title = str_create("Server: ");
     str_cat(title,server_ip);
     video_window(0,0,0,title);
     ent_create("PlayerBot.mdl",vector(0,0,70),player_control);
  } else { // otherwise, it runs on a connected client
     video_window(0,0,0,player_name);
     random_seed(0); // allow random player positions
     ent_create("PlayerBot.mdl",vector(50+random(100),50+random(100),70),player_control);



So I tried using 'you' in the first 'if' of the gun_missile code where 'you' should refer to the entity that creates the missile (the player entity of the client):

Code:
action gun_missile()
{
 //on client	
 if (you.client_id == dplay_id)	{



but this gives me a crash when the projectile is casted by a client (so when not casted by the server+client / host but by someone who joined the server).

Replacing the 'my' with 'player' in the first 'if' (like in the code below) does not help cause than obviously the server+client/host player pointer is used and not the client player pointer;

Code:
action gun_missile()
{
 //on client	
 if (player.client_id == dplay_id)	{



Anyone any ideas what to use instead of (or how to fix) the line 'if (my.client_id == dplay_id)' in the action gun_missile? Thanks for taking the time.

Re: multiplayer player missile projectile [Re: Reconnoiter] #434906
12/30/13 05:29
12/30/13 05:29
Joined: Jan 2006
Posts: 968
EpsiloN Offline
User
EpsiloN  Offline
User

Joined: Jan 2006
Posts: 968
I dont know if this is the problem, but you should always wait before an entity is created and confirmed on all clients.

Try something like "while(my.client_id == 0) { wait(1); }"
This will wait on both server and client until the entity is successfuly created.
Also , disable sending of alpha,frames and similar stuff. I usually disable all, but NOSEND. If you disable everything with NOSEND the ent wont be created on clients...

PS.: And a little advice, dont control the missile from the client. Create it on both and leave the server to control it. The client should only move it localy without sending anything. Just use the same movement/lifespan commands on both, and let the server control the hits. Otherwise the client can cheat.


Extensive Multiplayer tutorial:
http://mesetts.com/index.php?page=201
Re: multiplayer player missile projectile [Re: EpsiloN] #434976
12/31/13 12:27
12/31/13 12:27
Joined: Dec 2011
Posts: 1,823
Netherlands
Reconnoiter Offline OP
Serious User
Reconnoiter  Offline OP
Serious User

Joined: Dec 2011
Posts: 1,823
Netherlands
Hi Epsilon,

Thanks for the tip.

I still get an error with 'you' when firing the missile as a client (crash in action gun_missile). And when the server/host fires a missile, my.client_id stays 0.

Code:
action gun_missile()
{
//wait for entity to be created	
while(my.client_id == 0) {wait(1);}	
 
	my.WEAPONSELECTED = you.WEAPONSELECTED;
	my.CREATOR = you;
...



Now that I think about it, maybe it is cause the 'server' does not recognize 'you' (since the client than created it through "if (my.client_id == dplay_id):").

But what could I use instead of 'you' pointer?

Re: multiplayer player missile projectile [Re: Reconnoiter] #435229
01/04/14 05:16
01/04/14 05:16
Joined: Jan 2006
Posts: 968
EpsiloN Offline
User
EpsiloN  Offline
User

Joined: Jan 2006
Posts: 968
Dont rely on You pointer.
It is changed many times in one frame...Use it only directly after an instruction that modifies it, eg: you = ent_create...you.skill1 =...
You can use a temporary pointer to store handles, but the server and client dont share the pointers (and handles) between them.
What you can do, if you want to identify each client and use their entities, is to generate an unique ID for each client, synchronized with server and other clients. Then whenever you need a certain player's entity you search for that client ID...

I dont know exactly what you are trying to do in your script, so I can be more specific, but I cant read it in depth right now eighter laugh I'm late for work.

Also, dont forget all ent_create are actualy executed on the server,and you can pass pointers if you use functions...

Code:
function example()
{
  you = ent_create(dummy_mdl, NULLVECTOR , null);
  move_dummy(you);
}

function move_dummy( ENTITY* tempyou )
{
  me = tempyou;
}


Btw, this would also work on the client, move_dummy will be executed on the client with a pointer to the created entity and ent_create will be executed on the server. I'm using it to start local player movement and interaction.


Extensive Multiplayer tutorial:
http://mesetts.com/index.php?page=201
Re: multiplayer player missile projectile [Re: EpsiloN] #435389
01/07/14 08:55
01/07/14 08:55
Joined: Dec 2011
Posts: 1,823
Netherlands
Reconnoiter Offline OP
Serious User
Reconnoiter  Offline OP
Serious User

Joined: Dec 2011
Posts: 1,823
Netherlands
I can't get it working on the client. It works fine on the host/server, but the client is ignoring everything outside of its own action:

Code:
function create_gunmissile()
{		
you = ent_create("MissileEnergy.mdl",vector(my.x+(40)*cos(my.CAMERA_TILT_DUMMY)*cos(my.pan),my.y+(40)*cos(my.CAMERA_TILT_DUMMY)*sin(my.pan),(my.z+100)+(40)*sin(my.CAMERA_TILT_DUMMY)),gun_missile);	
while(!you) {wait(1);} //replacing this loop with e.g. wait(3); does also not work on client
you.pan = my.pan;
you.tilt = my.CAMERA_TILT_DUMMY;
you.WEAPONSELECTED = my.WEAPONSELECTED;
you.CREATOR = my;
}



I also tried replacing you with a custom ENTITY local pointer, but the exact same problem. I also put waits in the action gun_missile itself, but on the client the gun_missile still ignores the above written function.

Code:
action gun_missile()
{
////these all do not work on the client
//while(my.client_id == 0) {wait(1);}
//	while(my.pan == 0) {wait(1);}
//	while (my.client_id != dplay_id) wait(1);

        wait(3);

	my.LIFETIME = 400;
	my.DAMAGE = 20;
	my.MOVEMENTSPEED = 60;	
	my.AREAOFEFFECT = 40;
	my.EXPLOSIONSIZE = 0.5;
	my.GRAVITY = 0;
	my.AMBIENTSKILL = 100;
	my.SCALESKILL = 0.2;
	my.ALPHASKILL = 100;

 	my.ambient = my.AMBIENTSKILL;  // medium bright	
	vec_scale(my.scale_x,my.SCALESKILL); // small size
	my.alpha = my.ALPHASKILL;
	if (my.WEAPONSELECTED != 1) set(my,BRIGHT | TRANSLUCENT);	
		
	set(my,FLAG2);
	my.group = 3; // runs through all entities with the same group value, group 3 = world & projectiles  
	my.STATE = 1;
	my.roll = random(360);
	my.GRAVITY_SUM = 0;
	
	wait(1);
	
	while(1)
	{
........


Re: multiplayer player missile projectile [Re: Reconnoiter] #435611
01/09/14 16:22
01/09/14 16:22
Joined: Jan 2006
Posts: 968
EpsiloN Offline
User
EpsiloN  Offline
User

Joined: Jan 2006
Posts: 968
create_gunmissile() has to be called on the client. It'll create the missile on the server...
You get a pointer to the created entity (you) so you can modify it. If you need a local client function running, you have to call it on the client!
So, in create_gunmissile() you'd call a function wich takes an entity pointer as an argument and assign it to "my" or "me"... This function will run on the client.

Now...
On the server, gun_missile will be called and assigned to the created entity (wich you created ('requested') on the client) and will run ONLY on the server.

The logic here is this:
[Client]
you = missile_entity - no function running yet, created on server and client, but running only on server as a function
run_missile(you) - run a function on the client to steer the missile on client according to received data

[Server]
gun_missile called and an entity has been created by a client, but gin_missile runs only here, on server!
after creation, start moving the missile, perform collision detection and send data about position (and maby velocity) to client

And always perform the movement and collision on the server, or you'll have to deal with cheats and trainers.



PS.: If its not clear yet, you'd have to read and experiment more with functions in multiplayer. Dont create complicated functions, start with movement on both server and client (without collision) and work your way up to get a working entity. When you get an entity to move both on client and server simultaneously, you can start adding more code. laugh


Extensive Multiplayer tutorial:
http://mesetts.com/index.php?page=201
Re: multiplayer player missile projectile [Re: EpsiloN] #435651
01/10/14 10:26
01/10/14 10:26
Joined: Dec 2011
Posts: 1,823
Netherlands
Reconnoiter Offline OP
Serious User
Reconnoiter  Offline OP
Serious User

Joined: Dec 2011
Posts: 1,823
Netherlands
Thanks for tip.

I noticed through adding DEBUG_VAR(my.pan,10); in the gun_missile action that on the client side the pan is correctly, but on the server side the pan stays 0 and the server does the moving.

So I added an send_skill with a long wait in gun_missile right before the while loop;

Code:
wait(1);
if (my.client_id == dplay_id) send_skill(my.ROTATION_PAN,0);
wait(10);
my.pan = my.ROTATION_PAN;



This seems to do the trick. Apperently, in my previous code I used too short waits. With wait(3); the pan is rotated rarely. Probably use wait(5); than.

Anyway thanks for all the help!

Last edited by Reconnoiter; 01/10/14 10:26.
Re: multiplayer player missile projectile [Re: Reconnoiter] #435665
01/10/14 13:03
01/10/14 13:03
Joined: Apr 2007
Posts: 3,751
Canada
WretchedSid Offline
Expert
WretchedSid  Offline
Expert

Joined: Apr 2007
Posts: 3,751
Canada
This is a race condition waiting to happen. And it will happen the second your code has to face the real world and runs outside of your walled development garden.


Shitlord by trade and passion. Graphics programmer at Laminar Research.
I write blog posts at feresignum.com
Re: multiplayer player missile projectile [Re: WretchedSid] #435709
01/11/14 13:24
01/11/14 13:24
Joined: Dec 2011
Posts: 1,823
Netherlands
Reconnoiter Offline OP
Serious User
Reconnoiter  Offline OP
Serious User

Joined: Dec 2011
Posts: 1,823
Netherlands
What is a 'race condition' confused? I assume by that you mean it can give problems on e.g. networks with a high latency cause the wait does not adjust itself. Is that right?

And hey my development garden is quite nice actually tongue .

Anyway, I agree is it not perfect. What I don't get why it takes so long in the engine to sent a few variables (except for the part with latency). Maybe I tested it on a crappy network (still need to test it at home), next to that my code is lacking. Could it perhaps be that the missile is created at first only on the client and delayed on the server? (cause I call the function create_gun_missile within "if (my.client_id == dplay_id)" in the player action)

ps; if it helps, entrate is default.

- edit; I found a few AUMs about multiplayer which I have not yet read, that will probably clarify alot.

Last edited by Reconnoiter; 01/11/14 15:28.
Page 1 of 2 1 2

Moderated by  HeelX, Spirit 

Gamestudio download | chip programmers | Zorro platform | shop | Data Protection Policy

oP group Germany GmbH | Birkenstr. 25-27 | 63549 Ronneburg / Germany | info (at) opgroup.de

Powered by UBB.threads™ PHP Forum Software 7.7.1