3 |
|
#include "Flatline_Client.h" |
4 |
|
#include "Flatline_Server.h" |
5 |
|
#include "Flatline_Events.h" |
6 |
+ |
#include <Windows.h> |
7 |
|
//#include <sys/time.h> |
8 |
|
#include <time.h> |
9 |
+ |
#include <float.h> |
10 |
+ |
#define isnan(x) ((x) != (x)) |
11 |
|
uint32_t last1 = 0; uint32_t last2 = 0; |
12 |
|
player_info Players[MAX_PLAYERS] = {{0}, {0}, {0}, {0}}; |
13 |
|
player_info * PlayerList[MAX_CONNECTIONS] = {0}; |
14 |
< |
|
14 |
> |
multiplayer_status MultiplayerStatus; |
15 |
|
unsigned int lastPingTime; |
16 |
|
|
17 |
|
const char * Rejection_Messages[][255] = { |
209 |
|
DoRareSync( packet->sync_request , &sender); |
210 |
|
break; |
211 |
|
case PK_PONG: |
212 |
< |
for(i = 0; i < max_connections; i++) { |
212 |
> |
for(i = 0; i < max_connections; i++) { |
213 |
|
if(PlayerList[i] != 0 && PlayerList[i]->ip == sender.sin_addr.S_un.S_addr) { |
214 |
|
found_player = 1; |
215 |
|
break; |
223 |
|
} |
224 |
|
else |
225 |
|
{ |
226 |
< |
PlayerList[i]->Ping = (ONgGameState->GameTime - packet->ping) * 1000 / 60; |
226 |
> |
PlayerList[i]->Ping = GetTickCount() - packet->ping; |
227 |
|
} |
228 |
|
break; |
229 |
|
default: |
280 |
|
|
281 |
|
//FLrClient_Run |
282 |
|
//Looping function that waits for packets from the server. |
280 |
– |
|
283 |
|
int client_slot = 0; |
284 |
+ |
|
285 |
+ |
void FLrClient_GetPackets() |
286 |
+ |
{ |
287 |
+ |
flatline_packet packet; |
288 |
+ |
uint16_t len; |
289 |
+ |
//#define SPAM_INPUT |
290 |
+ |
#ifdef SPAM_INPUT |
291 |
+ |
struct timeval lasttime; |
292 |
+ |
struct timeval thistime; |
293 |
+ |
gettimeofday(&lasttime, 0); |
294 |
+ |
#endif |
295 |
+ |
|
296 |
+ |
|
297 |
+ |
while(NetUDPSocket_Recieve(client_sock, (sockaddr_storage *) &client_address, &packet, &len)) { |
298 |
+ |
//packet = (flatline_packet*)data; |
299 |
+ |
//DDrConsole_PrintF("Data recieved, length %i, type %i", len, ((flatline_packet*)data)->id); |
300 |
+ |
switch(packet.id) { |
301 |
+ |
case MESSAGE: |
302 |
+ |
COrMessage_Print(packet.data, "chat", 0); |
303 |
+ |
break; |
304 |
+ |
case CONNECT_SEND: |
305 |
+ |
;if(1) { |
306 |
+ |
flatline_packet connect_recv; |
307 |
+ |
memcpy(&connect_recv.connect_reply.message,"This isn't a server!", sizeof("This isn't a server!")); |
308 |
+ |
NetUDPSocket_Send(client_sock, (sockaddr *) &address, (char*)&connect_recv, sizeof(bool) + FLATLINE_HEADER + sizeof("This isn't a server!")); |
309 |
+ |
} |
310 |
+ |
case CONNECT_REPLY: |
311 |
+ |
break; //extra packet or something. |
312 |
+ |
case NEW_PLAYER: |
313 |
+ |
;if(1) { //haxhaxhax |
314 |
+ |
CharacterObject* Char = &(packet.new_player.Character); |
315 |
+ |
uint32_t chr_index = 0; |
316 |
+ |
Character* PC; |
317 |
+ |
DDrConsole_PrintF("%i | %i", packet.new_player.Playernumber ,client_slot); |
318 |
+ |
//Char->OSD.Options = 0; |
319 |
+ |
if(packet.new_player.Playernumber == client_slot) { |
320 |
+ |
PlayerList[packet.new_player.Playernumber] = &Players[0]; |
321 |
+ |
PC = (ONgGameState->PlayerCharacter); |
322 |
+ |
Players[0].Chr = PC; |
323 |
+ |
|
324 |
+ |
} |
325 |
+ |
else { |
326 |
+ |
ONrGameState_NewCharacter(Char, NULL, NULL, &chr_index); |
327 |
+ |
ONgGameState->CharacterStorage[chr_index].charType = 0; |
328 |
+ |
PlayerList[packet.new_player.Playernumber] = &Players[chr_index]; |
329 |
+ |
Players[chr_index].Chr = &(ONgGameState->CharacterStorage[chr_index]); |
330 |
+ |
Players[chr_index].Chr->Flags &= 0xFFBFFFFF; |
331 |
+ |
Players[chr_index].spawnnumber = chr_index; |
332 |
+ |
DDrConsole_PrintF("Spawning player %s, class %s, slot %i", ((new_player*)(packet.data))->Character.OSD.Name, ((new_player*)(packet.data))->Character.OSD.Class,chr_index) ; |
333 |
+ |
} |
334 |
+ |
//Players[((new_player*)(packet.data))->Playernumber].spawnnumber = ONrGameState_NewCharacter(&(((new_player*)(packet.data))->Character), NULL, NULL, 0); |
335 |
+ |
break; |
336 |
+ |
} |
337 |
+ |
case PLAYER_DATA: |
338 |
+ |
if(1) { //haxhaxhax |
339 |
+ |
player_data* pd = &packet.player_data; |
340 |
+ |
uint16_t i = pd->PlayerNum; |
341 |
+ |
|
342 |
+ |
pd = (void*)packet.data; |
343 |
+ |
|
344 |
+ |
|
345 |
+ |
if (i > max_connections) break; |
346 |
+ |
if( !PlayerList[i] ) break; |
347 |
+ |
|
348 |
+ |
memcpy( &(PlayerList[i]->player_data), pd, sizeof(player_data) ); |
349 |
+ |
|
350 |
+ |
if( !server_started && pd->rare_sync_index > PlayerList[i]->rare_sync_index ) |
351 |
+ |
{ |
352 |
+ |
int sent_bytes; |
353 |
+ |
flatline_packet sync_request = {0}; |
354 |
+ |
sync_request.id = RARE_SYNC_DATA_REQUEST; |
355 |
+ |
sync_request.sync_request = i; |
356 |
+ |
DDrConsole_PrintF( "Requesting sync data for player %i, old index %u", i, PlayerList[i]->rare_sync_index); |
357 |
+ |
sent_bytes = NetUDPSocket_Send(client_sock,(sockaddr *) &address, (char*)&sync_request, FLATLINE_HEADER + sizeof(int) ); |
358 |
+ |
} |
359 |
+ |
|
360 |
+ |
PlayerList[i]->DataApplied = 0; |
361 |
+ |
|
362 |
+ |
|
363 |
+ |
break; |
364 |
+ |
} |
365 |
+ |
case RARE_SYNC_DATA: |
366 |
+ |
if(1) { |
367 |
+ |
sl_arg hax[2]; |
368 |
+ |
int dontuse; |
369 |
+ |
uint16_t i = packet.rare_sync_data.PlayerNum; |
370 |
+ |
|
371 |
+ |
if (i > max_connections) break; |
372 |
+ |
if( !PlayerList[i] ) break; |
373 |
+ |
|
374 |
+ |
//WEAPONS ARE DISABLED. Why? Pain in the arse to sync. |
375 |
+ |
packet.rare_sync_data.Inventory.Weapons[0] = NULL; |
376 |
+ |
packet.rare_sync_data.Inventory.Weapons[1] = NULL; |
377 |
+ |
packet.rare_sync_data.Inventory.Weapons[2] = NULL; |
378 |
+ |
// TMrInstance_GetDataPtr( 'ONCC', packet.rare_sync_data.Class, PlayerList[ i ]->Chr->ONCC ); |
379 |
+ |
|
380 |
+ |
//add the target character |
381 |
+ |
hax[0].type = sl_int32; |
382 |
+ |
hax[0].value_int32 = PlayerList[ packet.rare_sync_data.PlayerNum ]->spawnnumber; |
383 |
+ |
|
384 |
+ |
//add the new class |
385 |
+ |
//fix this later so we cant buffer overflow :O |
386 |
+ |
hax[1].type = sl_str32; |
387 |
+ |
hax[1].value_str32 = packet.rare_sync_data.Class; |
388 |
+ |
|
389 |
+ |
//we are directly calling a bsl function instead of using the normal method for two reasons |
390 |
+ |
//1. it has all the checking built in |
391 |
+ |
iSetCharacterClass( 0, 2, hax, &dontuse, &dontuse, hax ); |
392 |
+ |
//DDrConsole_PrintF( "Recieved sync data for player %i, class %s, old index %u, new index %u", i, packet.rare_sync_data.Class, PlayerList[i]->rare_sync_index, packet.rare_sync_data.index); |
393 |
+ |
memcpy( &(PlayerList[ i ]->Chr->Inventory), &(packet.rare_sync_data.Inventory), sizeof(Inventory )); |
394 |
+ |
|
395 |
+ |
PlayerList[i]->rare_sync_index = packet.rare_sync_data.index; |
396 |
+ |
} |
397 |
+ |
break; |
398 |
+ |
case FLATLINE_EVENT: |
399 |
+ |
FLcEventHandler( packet.flatline_event.event_index, packet.flatline_event.intArray ); |
400 |
+ |
break; |
401 |
+ |
case PK_PING: |
402 |
+ |
packet.id = PK_PONG; |
403 |
+ |
NetUDPSocket_Send(client_sock, (sockaddr *) &address, (char*)&packet, FLATLINE_HEADER + 4); |
404 |
+ |
break; |
405 |
+ |
case PK_ALL_INPUT: |
406 |
+ |
if(1) |
407 |
+ |
{ |
408 |
+ |
int Player, i; |
409 |
+ |
for(i = 0; packet.all_input[i].PlayerNum != -1; i++) |
410 |
+ |
{ |
411 |
+ |
Player = packet.all_input[i].PlayerNum; |
412 |
+ |
if(PlayerList[Player]) |
413 |
+ |
{ |
414 |
+ |
PlayerList[Player]->Actions1 = packet.all_input[Player].Actions1; |
415 |
+ |
PlayerList[Player]->Actions2 = packet.all_input[Player].Actions2; |
416 |
+ |
PlayerList[Player]->MouseDeltaX = packet.all_input[Player].MouseDeltaX; |
417 |
+ |
PlayerList[Player]->MouseDeltaY = packet.all_input[Player].MouseDeltaY; |
418 |
+ |
PlayerList[Player]->Facing = packet.all_input[Player].Facing; |
419 |
+ |
PlayerList[Player]->DesiredFacing = packet.all_input[Player].DesiredFacing; |
420 |
+ |
PlayerList[Player]->Position = packet.all_input[Player].Position; |
421 |
+ |
} |
422 |
+ |
} |
423 |
+ |
} |
424 |
+ |
break; |
425 |
+ |
default: |
426 |
+ |
DDrConsole_PrintF("Warning, recieved badly formed packet!"); |
427 |
+ |
break; |
428 |
+ |
} |
429 |
+ |
} |
430 |
+ |
} |
431 |
+ |
|
432 |
+ |
|
433 |
|
bool FLrClient_Run(flatline_packet* packet) |
434 |
|
{ |
435 |
|
|
452 |
|
packet = (flatline_packet*)data; |
453 |
|
if(packet->id == CONNECT_REPLY) { |
454 |
|
if(packet->connect_reply.goodtogo){ |
455 |
+ |
|
456 |
|
client_connected = 1; |
457 |
|
|
458 |
|
client_slot = ((connect_reply*)packet->data)->player_slot; |
464 |
|
|
465 |
|
//disable local input. |
466 |
|
DDrPatch_NOOP(0x004FA929, 5 + 6 + 5); |
467 |
+ |
|
468 |
+ |
//Disable local turning |
469 |
+ |
//DDrPatch_NOOP(0x004F7EA8, 2); |
470 |
+ |
//DDrPatch_Byte( 0x004F7EB1 , 0xE9); |
471 |
+ |
//DDrPatch_MakeJump( 0x004F7EB1, 0x004F8030 ); |
472 |
+ |
|
473 |
+ |
|
474 |
+ |
//DDrPatch_Byte(0x04ED6FB, 0xEB); |
475 |
|
|
476 |
|
//DDrConsole_PrintF("Slot %i", ((connect_reply*)packet)->player_slot); |
477 |
+ |
//DDrPatch_NOOP(0x43B23,0x10); |
478 |
+ |
//DDrPatch_NOOP(0x4EC248,(0x5A-0x48)); |
479 |
+ |
//DDrPatch_NOOP(0x4EC861, 6); |
480 |
|
break; |
481 |
|
} |
482 |
|
else { |
495 |
|
DDrConsole_PrintColored("Connection timed out.",0,red, grey); |
496 |
|
return false; |
497 |
|
} |
335 |
– |
else |
336 |
– |
{ |
337 |
– |
ActiveCharacter * Active; |
338 |
– |
flatline_packet packet; |
339 |
– |
//#define SPAM_INPUT |
340 |
– |
#ifdef SPAM_INPUT |
341 |
– |
struct timeval lasttime; |
342 |
– |
struct timeval thistime; |
343 |
– |
gettimeofday(&lasttime, 0); |
344 |
– |
#endif |
345 |
– |
while(1) { |
346 |
– |
#ifdef SPAM_INPUT |
347 |
– |
gettimeofday(&thistime, 0); |
348 |
– |
|
349 |
– |
//DDrConsole_PrintF("%i.%i | %i.%i | %i.%i",lasttime.tv_sec, lasttime.tv_usec, thistime.tv_sec, thistime.tv_usec, |
350 |
– |
// thistime.tv_sec - lasttime.tv_sec, thistime.tv_usec - lasttime.tv_usec); |
351 |
– |
//checks to see if enough time has passed since the last input update (by default once every 10ms) |
352 |
– |
if( |
353 |
– |
((thistime.tv_sec > lasttime.tv_sec) && ((thistime.tv_usec + 1000000 - lasttime.tv_usec ) > update_rate * 1000) ) |
354 |
– |
|| ((thistime.tv_sec == lasttime.tv_sec) && ((thistime.tv_usec - lasttime.tv_usec ) > update_rate * 1000)) |
355 |
– |
) { |
356 |
– |
|
357 |
– |
flatline_packet input_packet; |
358 |
– |
lasttime.tv_usec = ++thistime.tv_usec; //in case recieving packets takes less than 1 ms. |
359 |
– |
|
360 |
– |
input_packet.id = PLAYER_INPUT; |
361 |
– |
|
362 |
– |
if( ((GameState*)(ONgGameState))->Input.Current.Actions1 != last1 || ((GameState*)(ONgGameState))->Input.Current.Actions2 != last2) { |
363 |
– |
last1 =((GameState*)(ONgGameState))->Input.Current.Actions1; |
364 |
– |
last2 =((GameState*)(ONgGameState))->Input.Current.Actions2; |
365 |
– |
} |
366 |
– |
|
367 |
– |
((input_struct*)(void*)(input_packet.data))->Actions1 = ((GameState*)(ONgGameState))->Input.Current.Actions1; |
368 |
– |
((input_struct*)(void*)(input_packet.data))->Actions2 = ((GameState*)(ONgGameState))->Input.Current.Actions2; |
369 |
– |
((input_struct*)(void*)(input_packet.data))->MouseDeltaX = ((GameState*)(ONgGameState))->Input.MouseDeltaX; |
370 |
– |
((input_struct*)(void*)(input_packet.data))->MouseDeltaY = ((GameState*)(ONgGameState))->Input.MouseDeltaY; |
371 |
– |
sent_bytes = NetUDPSocket_Send(client_sock,(sockaddr *) &address, (char*)&input_packet, sizeof(input_struct) + FLATLINE_HEADER); |
372 |
– |
//if(sent_bytes == SOCKET_ERROR) NetCatchError(); |
373 |
– |
} |
374 |
– |
#endif |
375 |
– |
if(NetUDPSocket_Recieve(client_sock, (sockaddr_storage *) &client_address, &packet, &len)) { |
376 |
– |
//packet = (flatline_packet*)data; |
377 |
– |
//DDrConsole_PrintF("Data recieved, length %i, type %i", len, ((flatline_packet*)data)->id); |
378 |
– |
switch(packet.id) { |
379 |
– |
case MESSAGE: |
380 |
– |
COrMessage_Print(packet.data, "chat", 0); |
381 |
– |
break; |
382 |
– |
case CONNECT_SEND: |
383 |
– |
;if(1) { |
384 |
– |
flatline_packet connect_recv; |
385 |
– |
memcpy(&connect_recv.connect_reply.message,"This isn't a server!", sizeof("This isn't a server!")); |
386 |
– |
NetUDPSocket_Send(client_sock, (sockaddr *) &address, (char*)&connect_recv, sizeof(bool) + FLATLINE_HEADER + sizeof("This isn't a server!")); |
387 |
– |
} |
388 |
– |
case CONNECT_REPLY: |
389 |
– |
break; //extra packet or something. |
390 |
– |
case NEW_PLAYER: |
391 |
– |
;if(1) { //haxhaxhax |
392 |
– |
CharacterObject* Char = &(packet.new_player.Character); |
393 |
– |
uint32_t chr_index = 0; |
394 |
– |
Character* PC; |
395 |
– |
DDrConsole_PrintF("%i | %i", packet.new_player.Playernumber ,client_slot); |
396 |
– |
//Char->OSD.Options = 0; |
397 |
– |
if(packet.new_player.Playernumber == client_slot) { |
398 |
– |
PlayerList[packet.new_player.Playernumber] = &Players[0]; |
399 |
– |
PC = (ONgGameState->PlayerCharacter); |
400 |
– |
Players[0].Chr = PC; |
401 |
– |
|
402 |
– |
} |
403 |
– |
else { |
404 |
– |
ONrGameState_NewCharacter(Char, NULL, NULL, &chr_index); |
405 |
– |
ONgGameState->CharacterStorage[chr_index].charType = 0; |
406 |
– |
PlayerList[packet.new_player.Playernumber] = &Players[chr_index]; |
407 |
– |
Players[chr_index].Chr = &(ONgGameState->CharacterStorage[chr_index]); |
408 |
– |
Players[chr_index].Chr->Flags &= 0xFFBFFFFF; |
409 |
– |
Players[chr_index].spawnnumber = chr_index; |
410 |
– |
DDrConsole_PrintF("Spawning player %s, class %s, slot %i", ((new_player*)(packet.data))->Character.OSD.Name, ((new_player*)(packet.data))->Character.OSD.Class,chr_index) ; |
411 |
– |
} |
412 |
– |
//Players[((new_player*)(packet.data))->Playernumber].spawnnumber = ONrGameState_NewCharacter(&(((new_player*)(packet.data))->Character), NULL, NULL, 0); |
413 |
– |
break; |
414 |
– |
} |
415 |
– |
case PLAYER_DATA: |
416 |
– |
if(1) { //haxhaxhax |
417 |
– |
player_data* pd = &packet.player_data; |
418 |
– |
uint16_t i = pd->PlayerNum; |
419 |
– |
GameInput * Active_Input; |
420 |
– |
pd = (void*)packet.data; |
421 |
– |
|
422 |
– |
//DDrConsole_PrintF("Got data for Player %i, %x", i, PlayerList[i]); |
423 |
– |
if (i > max_connections) break; |
424 |
– |
if( !PlayerList[i] ) break; |
425 |
– |
//PlayerList[i]->Chr = ((GameState *)ONgGameState)->CharacterStorage; |
426 |
– |
|
427 |
– |
/* PlayerList[i]->Actions1 = pd->Inputs.Actions1; |
428 |
– |
PlayerList[i]->Actions2 = pd->Inputs.Actions2; |
429 |
– |
PlayerList[i]->MouseDeltaX = pd->Inputs.MouseDeltaX; |
430 |
– |
PlayerList[i]->MouseDeltaY = pd->Inputs.MouseDeltaY;*/ |
431 |
– |
memcpy( &(PlayerList[i]->player_data), pd, sizeof(player_data) ); |
432 |
– |
|
433 |
– |
if( !server_started && pd->rare_sync_index > PlayerList[i]->rare_sync_index ) |
434 |
– |
{ |
435 |
– |
int sent_bytes; |
436 |
– |
flatline_packet sync_request = {0}; |
437 |
– |
sync_request.id = RARE_SYNC_DATA_REQUEST; |
438 |
– |
sync_request.sync_request = i; |
439 |
– |
DDrConsole_PrintF( "Requesting sync data for player %i, old index %u", i, PlayerList[i]->rare_sync_index); |
440 |
– |
sent_bytes = NetUDPSocket_Send(client_sock,(sockaddr *) &address, (char*)&sync_request, FLATLINE_HEADER + sizeof(int) ); |
441 |
– |
} |
442 |
– |
|
443 |
– |
PlayerList[i]->DataApplied = 0; |
444 |
– |
|
498 |
|
|
446 |
– |
break; |
447 |
– |
} |
448 |
– |
case RARE_SYNC_DATA: |
449 |
– |
if(1) { |
450 |
– |
sl_arg hax[2]; |
451 |
– |
int dontuse; |
452 |
– |
uint16_t i = packet.rare_sync_data.PlayerNum; |
453 |
– |
|
454 |
– |
if (i > max_connections) break; |
455 |
– |
if( !PlayerList[i] ) break; |
456 |
– |
|
457 |
– |
//WEAPONS ARE DISABLED. Why? Pain in the arse to sync. |
458 |
– |
packet.rare_sync_data.Inventory.Weapons[0] = NULL; |
459 |
– |
packet.rare_sync_data.Inventory.Weapons[1] = NULL; |
460 |
– |
packet.rare_sync_data.Inventory.Weapons[2] = NULL; |
461 |
– |
// TMrInstance_GetDataPtr( 'ONCC', packet.rare_sync_data.Class, PlayerList[ i ]->Chr->ONCC ); |
462 |
– |
|
463 |
– |
//add the target character |
464 |
– |
hax[0].type = sl_int32; |
465 |
– |
hax[0].value_int32 = PlayerList[ packet.rare_sync_data.PlayerNum ]->spawnnumber; |
466 |
– |
|
467 |
– |
//add the new class |
468 |
– |
//fix this later so we cant buffer overflow :O |
469 |
– |
hax[1].type = sl_str32; |
470 |
– |
hax[1].value_str32 = packet.rare_sync_data.Class; |
471 |
– |
|
472 |
– |
//we are directly calling a bsl function instead of using the normal method for two reasons |
473 |
– |
//1. it has all the checking built in |
474 |
– |
iSetCharacterClass( 0, 2, hax, &dontuse, &dontuse, hax ); |
475 |
– |
//DDrConsole_PrintF( "Recieved sync data for player %i, class %s, old index %u, new index %u", i, packet.rare_sync_data.Class, PlayerList[i]->rare_sync_index, packet.rare_sync_data.index); |
476 |
– |
memcpy( &(PlayerList[ i ]->Chr->Inventory), &(packet.rare_sync_data.Inventory), sizeof(Inventory )); |
477 |
– |
|
478 |
– |
PlayerList[i]->rare_sync_index = packet.rare_sync_data.index; |
479 |
– |
} |
480 |
– |
break; |
481 |
– |
case FLATLINE_EVENT: |
482 |
– |
FLcEventHandler( packet.flatline_event.event_index, packet.flatline_event.intArray ); |
483 |
– |
break; |
484 |
– |
case PK_PING: |
485 |
– |
packet.id = PK_PONG; |
486 |
– |
NetUDPSocket_Send(client_sock, (sockaddr *) &address, (char*)&packet, FLATLINE_HEADER + 4); |
487 |
– |
break; |
488 |
– |
case PK_ALL_INPUT: |
489 |
– |
if(1) |
490 |
– |
{ |
491 |
– |
int Player; |
492 |
– |
for(Player = 0; Player < MAX_CONNECTIONS; Player++) |
493 |
– |
{ |
494 |
– |
if(PlayerList[Player]) |
495 |
– |
{ |
496 |
– |
PlayerList[Player]->Actions1 = packet.all_input[Player].Actions1; |
497 |
– |
PlayerList[Player]->Actions2 = packet.all_input[Player].Actions2; |
498 |
– |
PlayerList[Player]->MouseDeltaX = packet.all_input[Player].MouseDeltaX; |
499 |
– |
PlayerList[Player]->MouseDeltaY = packet.all_input[Player].MouseDeltaY; |
500 |
– |
} |
501 |
– |
} |
502 |
– |
} |
503 |
– |
break; |
504 |
– |
default: |
505 |
– |
DDrConsole_PrintF("Warning, recieved badly formed packet!"); |
506 |
– |
break; |
507 |
– |
} |
508 |
– |
} |
509 |
– |
else { |
510 |
– |
Sleep(1); |
511 |
– |
} |
512 |
– |
} |
513 |
– |
} |
499 |
|
return true; |
500 |
|
} |
501 |
|
|
527 |
|
|
528 |
|
} IMtPoint2D; |
529 |
|
static flatline_packet cache_input = {0}; |
530 |
< |
extern void* TSrTest; |
530 |
> |
enum |
531 |
> |
{ |
532 |
> |
FirstPass, |
533 |
> |
SecondPass, |
534 |
> |
NoPass, |
535 |
> |
}; |
536 |
> |
bool ShouldSendUpdate( int i, Character* Player, ActiveCharacter* Active_Player ) |
537 |
> |
{ |
538 |
> |
return |
539 |
> |
MultiplayerStatus.PleaseUpdateAllPlayers ? 1 : |
540 |
> |
strcmp(PlayerList[i]->player_data.Animation, |
541 |
> |
TMrInstance_GetInstanceName(Active_Player->Animation)) ? 1 : |
542 |
> |
PlayerList[i]->player_data.Health != Player->Health ? 1 : 0; |
543 |
> |
} |
544 |
> |
|
545 |
|
void * ONICALL FLrInput_Update_Keys(void) |
546 |
|
{ |
547 |
|
uint16_t i; |
548 |
|
flatline_packet all_input = {0}; |
549 |
< |
ActiveCharacter * Active_Player = ONgGameState->ActiveCharacters; |
550 |
< |
Active_Player->PhyContext->Rotation; |
551 |
< |
Active_Player->PhyContext->Position; |
553 |
< |
ONgGameState->PlayerCharacter->Position; |
554 |
< |
|
549 |
> |
int16_t InputIndex = 0; |
550 |
> |
//ActiveCharacter * Active_Player = ONgGameState->ActiveCharacters; |
551 |
> |
|
552 |
|
if(client_connected) |
553 |
|
{ |
554 |
|
int sent_bytes; |
555 |
|
flatline_packet input_packet = {0}; |
556 |
+ |
|
557 |
+ |
FLrClient_GetPackets(); |
558 |
+ |
|
559 |
|
input_packet.id = PLAYER_INPUT; |
560 |
|
input_packet.input_struct.Time = ONgGameState->GameTime; |
561 |
+ |
// ((GameState*)(ONgGameState))->Input.Current.Actions1 |= Action_Backward | Action_StepLeft; |
562 |
|
input_packet.input_struct.Actions1 = ((GameState*)(ONgGameState))->Input.Current.Actions1; |
563 |
|
input_packet.input_struct.Actions2 = ((GameState*)(ONgGameState))->Input.Current.Actions2; |
564 |
|
input_packet.input_struct.MouseDeltaX = ((GameState*)(ONgGameState))->Input.MouseDeltaX; |
579 |
|
FLsPingAll(); |
580 |
|
} |
581 |
|
|
582 |
+ |
if(server_started && PlayerList[0]) |
583 |
+ |
{ |
584 |
+ |
PlayerList[0]->Actions1 = ONgGameState->Input.Current.Actions1; |
585 |
+ |
PlayerList[0]->Actions2 = ONgGameState->Input.Current.Actions2; |
586 |
+ |
PlayerList[0]->MouseDeltaX = ONgGameState->Input.MouseDeltaX; |
587 |
+ |
PlayerList[0]->MouseDeltaY = ONgGameState->Input.MouseDeltaY; |
588 |
+ |
} |
589 |
+ |
|
590 |
|
for(i = 0; i < max_connections; i++) { |
591 |
|
ActiveCharacter * Active_Player; |
592 |
|
Character* Player; |
593 |
|
GameInput * Active_Input; |
594 |
|
if(PlayerList[i] == 0) continue; |
595 |
+ |
Player = PlayerList[i]->Chr; |
596 |
+ |
if(server_started) |
597 |
+ |
{ |
598 |
+ |
|
599 |
+ |
//Set up input packets |
600 |
|
|
601 |
+ |
all_input.all_input[InputIndex].Actions1 = PlayerList[i]->Actions1; |
602 |
+ |
all_input.all_input[InputIndex].Actions2 = PlayerList[i]->Actions2; |
603 |
+ |
all_input.all_input[InputIndex].MouseDeltaX = PlayerList[i]->MouseDeltaX; |
604 |
+ |
all_input.all_input[InputIndex].MouseDeltaY = PlayerList[i]->MouseDeltaY; |
605 |
|
|
606 |
< |
if(i == 0) { |
607 |
< |
all_input.all_input[i].Actions1 = ((GameState*)(ONgGameState))->Input.Current.Actions1; |
608 |
< |
all_input.all_input[i].Actions2 = ((GameState*)(ONgGameState))->Input.Current.Actions2; |
609 |
< |
all_input.all_input[i].MouseDeltaX = ONgGameState->Input.MouseDeltaX; |
610 |
< |
all_input.all_input[i].MouseDeltaY = ONgGameState->Input.MouseDeltaY; |
611 |
< |
} |
612 |
< |
else{ |
613 |
< |
all_input.all_input[i].Actions1 = PlayerList[i]->Actions1; |
596 |
< |
all_input.all_input[i].Actions2 = PlayerList[i]->Actions2; |
597 |
< |
all_input.all_input[i].MouseDeltaX = PlayerList[i]->MouseDeltaX; |
598 |
< |
all_input.all_input[i].MouseDeltaY = PlayerList[i]->MouseDeltaY; |
606 |
> |
all_input.all_input[InputIndex].Facing = Player->Facing; |
607 |
> |
all_input.all_input[InputIndex].DesiredFacing = Player->DesiredFacing; |
608 |
> |
|
609 |
> |
//Infinity... |
610 |
> |
*(int *)&all_input.all_input[InputIndex].Position.X = 0x7f800000; |
611 |
> |
|
612 |
> |
all_input.all_input[InputIndex].PlayerNum = i; |
613 |
> |
InputIndex++; |
614 |
|
} |
615 |
|
|
601 |
– |
Player = PlayerList[i]->Chr; |
616 |
|
if( Player->Health == 0) |
617 |
|
{ |
618 |
|
int Actions; |
627 |
|
} |
628 |
|
} |
629 |
|
|
630 |
< |
if(server_started & i == 0) |
630 |
> |
if(server_started && i == 0) |
631 |
|
{ |
632 |
|
Actions = ONgGameState->Input.Current.Actions1; |
633 |
|
} |
654 |
|
} |
655 |
|
|
656 |
|
Active_Player = ONrGetActiveCharacter( PlayerList[i]->Chr); |
657 |
< |
|
657 |
> |
|
658 |
|
if(Active_Player == 0) continue; |
645 |
– |
Active_Input = &(Active_Player->Input); |
659 |
|
|
660 |
< |
if(server_started && strcmp(PlayerList[i]->player_data.Animation, TMrInstance_GetInstanceName(Active_Player->Animation))) |
660 |
> |
|
661 |
> |
|
662 |
> |
//Active_Player->PlayingFilm.Flags = 1; |
663 |
> |
Active_Input = &(Active_Player->Input); |
664 |
> |
if(server_started) |
665 |
> |
{ |
666 |
> |
all_input.all_input[InputIndex - 1].Position = Active_Player->PhyContext->Position; |
667 |
> |
} |
668 |
> |
if(server_started && |
669 |
> |
ShouldSendUpdate( i, PlayerList[i]->Chr, Active_Player) ) |
670 |
|
{ |
671 |
|
player_data * data; |
672 |
|
flatline_packet data_out = {0}; |
677 |
|
data->PlayerNum = i; |
678 |
|
data->Health = PlayerList[i]->Chr->Health; |
679 |
|
data->MaxHealth = PlayerList[i]->Chr->MaxHealth; |
680 |
< |
data->Position = PlayerList[i]->Chr->Position; |
681 |
< |
data->Facing = PlayerList[i]->Chr->Facing; |
682 |
< |
data->DesiredFacing = PlayerList[i]->Chr->DesiredFacing; |
683 |
< |
data->Position = Active_Player->PhyContext->Position; |
680 |
> |
//data->Position = PlayerList[i]->Chr->Position; |
681 |
> |
//data->Facing = PlayerList[i]->Chr->Facing; |
682 |
> |
//data->DesiredFacing = PlayerList[i]->Chr->DesiredFacing; |
683 |
> |
//data->Position = Active_Player->PhyContext->Position; |
684 |
|
memcpy(data->Animation, TMrInstance_GetInstanceName(Active_Player->Animation), 31); |
685 |
|
data->Frame = Active_Player->Frame; |
686 |
|
|
687 |
+ |
data->UD = Active_Player->HeadPitch; |
688 |
+ |
data->LR = Active_Player->HeadFacing; |
689 |
+ |
|
690 |
|
if(Active_Player->targetThrow) |
691 |
|
{ |
692 |
|
data->throw_data.throwing = Players[Active_Player->throwing].list_slot; |
712 |
|
UDPServer_SendToAll(&data_out, sizeof(player_data) + FLATLINE_HEADER); |
713 |
|
} |
714 |
|
|
715 |
< |
if( (server_started && i !=0) || (!server_started/* && i != client_slot*/) ) |
715 |
> |
if( (server_started && i !=0) || !server_started ) |
716 |
|
{ |
717 |
|
Active_Input->Stop.Actions1 = ~PlayerList[i]->Actions1 & Active_Input->Current.Actions1; |
718 |
|
Active_Input->Stop.Actions2 = ~PlayerList[i]->Actions2 & Active_Input->Current.Actions2; |
731 |
|
void* OldAnimation; |
732 |
|
void* Animation; |
733 |
|
player_data* pd = &PlayerList[i]->player_data; |
734 |
+ |
|
735 |
+ |
PlayerList[i]->Chr->Facing = PlayerList[i]->Facing; |
736 |
+ |
PlayerList[i]->Chr->DesiredFacing = PlayerList[i]->DesiredFacing; |
737 |
+ |
|
738 |
+ |
if(*(int*)&PlayerList[i]->Chr->Position.X != 0x7f800000) |
739 |
+ |
{ |
740 |
+ |
Active_Player->PhyContext->Position = PlayerList[i]->Position; |
741 |
+ |
} |
742 |
+ |
else |
743 |
+ |
{ |
744 |
+ |
int breakfast = 0; |
745 |
+ |
} |
746 |
+ |
/* |
747 |
+ |
if(isnan(Active_Player->PhyContext->Position.Y) || |
748 |
+ |
isnan(Active_Player->PhyContext->Position.X) || |
749 |
+ |
isnan(Active_Player->PhyContext->Position.Z) ) |
750 |
+ |
{ |
751 |
+ |
//DDrConsole_PrintF("Player is NAN! %x %x", Active_Player->PhyContext->Position.Y, PlayerList[i]->Height); |
752 |
+ |
DDrConsole_PrintF("Player is NAN! %x %x %x", Active_Player->PhyContext->Position.X, Active_Player->PhyContext->Position.Y, Active_Player->PhyContext->Position.Z); |
753 |
+ |
//DDrConsole_PrintF("Velocity %x %x %x", Active_Player->PhyContext->Velocity.X, Active_Player->PhyContext->Velocity.Y, Active_Player->PhyContext->Velocity.Z); |
754 |
+ |
|
755 |
+ |
|
756 |
+ |
} |
757 |
+ |
*/ |
758 |
|
|
759 |
< |
|
711 |
< |
//Note to self: sort out which needs to be applied the first time and which the second. |
712 |
< |
switch(PlayerList[i]->DataApplied) |
759 |
> |
if( PlayerList[i]->DataApplied == FirstPass ) |
760 |
|
{ |
761 |
< |
case 1: |
762 |
< |
PlayerList[i]->DataApplied = 2; |
763 |
< |
break; |
764 |
< |
case 0: |
765 |
< |
PlayerList[i]->DataApplied = 1; |
719 |
< |
case 2: |
720 |
< |
continue; |
761 |
> |
PlayerList[i]->DataApplied = SecondPass; |
762 |
> |
|
763 |
> |
Player->Health = PlayerList[i]->player_data.Health; |
764 |
> |
PlayerList[i]->Chr->MaxHealth = PlayerList[i]->player_data.MaxHealth; |
765 |
> |
|
766 |
|
} |
767 |
< |
|
768 |
< |
Player->Health = PlayerList[i]->player_data.Health; |
769 |
< |
PlayerList[i]->Chr->MaxHealth = PlayerList[i]->player_data.MaxHealth; |
767 |
> |
else if( PlayerList[i]->DataApplied == SecondPass ) |
768 |
> |
{ |
769 |
> |
OldAnimation = Active_Player->Animation; |
770 |
> |
|
771 |
> |
PlayerList[i]->DataApplied = NoPass; |
772 |
|
|
773 |
< |
PlayerList[i]->Chr->Facing = PlayerList[i]->player_data.Facing; |
727 |
< |
PlayerList[i]->Chr->DesiredFacing = PlayerList[i]->player_data.DesiredFacing; |
773 |
> |
PlayerList[i]->player_data.Frame++; |
774 |
|
|
775 |
< |
/* PlayerList[i]->Actions1 = PlayerList[i]->player_data.Inputs.Actions1; |
776 |
< |
PlayerList[i]->Actions2 = PlayerList[i]->player_data.Inputs.Actions2; |
731 |
< |
PlayerList[i]->MouseDeltaX = PlayerList[i]->player_data.Inputs.MouseDeltaX; |
732 |
< |
PlayerList[i]->MouseDeltaY = PlayerList[i]->player_data.Inputs.MouseDeltaY;*/ |
733 |
< |
Active_Player->PhyContext->Position = PlayerList[i]->player_data.Position; |
734 |
< |
OldAnimation = Active_Player->Animation; |
735 |
< |
|
736 |
< |
if (!(Player->Flags & ONcCharacterFlag_BeingThrown) && |
737 |
< |
(pd->Animation != 0)) |
738 |
< |
{ |
739 |
< |
// get a pointer to the animation |
740 |
< |
|
741 |
< |
TMrInstance_GetDataPtr( |
742 |
< |
'TRAM', |
743 |
< |
pd->Animation, |
744 |
< |
&Animation); |
745 |
< |
if (Animation != OldAnimation) |
775 |
> |
if (!(Player->Flags & ONcCharacterFlag_BeingThrown) && |
776 |
> |
(pd->Animation[0] != 0)) |
777 |
|
{ |
778 |
< |
short num_frames; |
748 |
< |
bool updateAnimation = true; |
778 |
> |
// get a pointer to the animation |
779 |
|
|
780 |
< |
// if the character is dead, make sure this animation is appropriate for death |
781 |
< |
/* |
782 |
< |
if (Player->Flags & ONcCharacterFlag_Dead) |
780 |
> |
TMrInstance_GetDataPtr( |
781 |
> |
'TRAM', |
782 |
> |
pd->Animation, |
783 |
> |
&Animation); |
784 |
> |
if (Animation != OldAnimation) |
785 |
|
{ |
786 |
< |
short curToState = TRrAnimation_GetTo(Active_Player->Animation); |
787 |
< |
short newToState = TRrAnimation_GetTo(animation); |
786 |
> |
short num_frames; |
787 |
> |
bool updateAnimation = true; |
788 |
|
|
789 |
< |
// if we are currently heading towards fallen and the new animation would not |
790 |
< |
// then this is a better animation to run when we are dead |
791 |
< |
if ((ONrAnimState_IsFallen(curToState)) && |
792 |
< |
(!ONrAnimState_IsFallen(newToState))) |
793 |
< |
{ |
794 |
< |
updateAnimation = false; |
763 |
< |
} |
764 |
< |
} |
765 |
< |
*/ |
766 |
< |
if ((updateAnimation) && (Active_Player->Animation == Animation)) |
767 |
< |
{ |
768 |
< |
int oldFrame = Active_Player->Frame; |
769 |
< |
int newFrame = pd->Frame; |
789 |
> |
// if the character is dead, make sure this animation is appropriate for death |
790 |
> |
/* |
791 |
> |
if (Player->Flags & ONcCharacterFlag_Dead) |
792 |
> |
{ |
793 |
> |
short curToState = TRrAnimation_GetTo(Active_Player->Animation); |
794 |
> |
short newToState = TRrAnimation_GetTo(animation); |
795 |
|
|
796 |
< |
if (abs(oldFrame - newFrame) < 2) |
796 |
> |
// if we are currently heading towards fallen and the new animation would not |
797 |
> |
// then this is a better animation to run when we are dead |
798 |
> |
if ((ONrAnimState_IsFallen(curToState)) && |
799 |
> |
(!ONrAnimState_IsFallen(newToState))) |
800 |
|
{ |
801 |
< |
updateAnimation = false; |
801 |
> |
updateAnimation = false; |
802 |
|
} |
803 |
< |
} |
803 |
> |
} |
804 |
> |
*/ |
805 |
> |
if ((updateAnimation) && (Active_Player->Animation == Animation)) |
806 |
> |
{ |
807 |
> |
int oldFrame = Active_Player->Frame; |
808 |
> |
int newFrame = pd->Frame; |
809 |
|
|
810 |
< |
if (updateAnimation) |
811 |
< |
{ |
812 |
< |
// set the characters animation |
813 |
< |
/* ONrCharacter_SetAnimationInternal(Player, |
814 |
< |
Active_Player, |
782 |
< |
Active_Player->AnimationToState, |
783 |
< |
0, |
784 |
< |
Animation); |
785 |
< |
ONrCharacter_NewAnimationHook(Player, Active_Player);*/ |
786 |
< |
//Player->Flags |= 0x00000010; |
787 |
< |
ONrCharacter_SetAnimationExternal(Player, TRrAnimation_GetFrom(Animation), Animation, 0); |
788 |
< |
//ONrCharacter_NewAnimationHook(Player, Active_Player); |
789 |
< |
} |
810 |
> |
if (abs(oldFrame - newFrame) < 2) |
811 |
> |
{ |
812 |
> |
updateAnimation = false; |
813 |
> |
} |
814 |
> |
} |
815 |
|
|
816 |
< |
num_frames = TRrAnimation_GetDuration(Active_Player->Animation); |
816 |
> |
if (updateAnimation) |
817 |
> |
{ |
818 |
> |
// set the characters animation |
819 |
> |
/* ONrCharacter_SetAnimationInternal(Player, |
820 |
> |
Active_Player, |
821 |
> |
Active_Player->AnimationToState, |
822 |
> |
0, |
823 |
> |
Animation); |
824 |
> |
ONrCharacter_NewAnimationHook(Player, Active_Player);*/ |
825 |
> |
//Player->Flags |= 0x00000010; |
826 |
> |
ONrCharacter_SetAnimationExternal(Player, TRrAnimation_GetFrom(Animation), Animation, 0); |
827 |
> |
//ONrCharacter_NewAnimationHook(Player, Active_Player); |
828 |
> |
} |
829 |
|
|
830 |
< |
if (pd->Frame == num_frames) |
831 |
< |
{ |
832 |
< |
Active_Player->Frame = num_frames - 1; |
833 |
< |
//Active_Player->Frame = 0; |
834 |
< |
} |
835 |
< |
else |
836 |
< |
{ |
837 |
< |
Active_Player->Frame = pd->Frame; |
830 |
> |
num_frames = TRrAnimation_GetDuration(Active_Player->Animation); |
831 |
> |
|
832 |
> |
if (pd->Frame == num_frames) |
833 |
> |
{ |
834 |
> |
Active_Player->Frame = num_frames - 1; |
835 |
> |
//Active_Player->Frame = 0; |
836 |
> |
} |
837 |
> |
else |
838 |
> |
{ |
839 |
> |
Active_Player->Frame = pd->Frame; |
840 |
> |
} |
841 |
|
} |
842 |
< |
} |
803 |
< |
} |
842 |
> |
} //animation check |
843 |
|
|
844 |
< |
if (PlayerList[i]->player_data.throw_data.throwName[0] != 0) |
806 |
< |
{ |
807 |
< |
short throwTarget = PlayerList[pd->throw_data.throwing]->spawnnumber; |
808 |
< |
if ((throwTarget != Active_Player->throwing) && |
809 |
< |
(pd->throw_data.throwFrame < 10)) |
844 |
> |
if (PlayerList[i]->player_data.throw_data.throwName[0] != 0) |
845 |
|
{ |
846 |
< |
void *throw_animation; |
847 |
< |
ActiveCharacter* Target; |
848 |
< |
// get the animation |
814 |
< |
|
815 |
< |
TMrInstance_GetDataPtr( |
816 |
< |
'TRAM', |
817 |
< |
pd->throw_data.throwName, |
818 |
< |
&throw_animation); |
819 |
< |
//if (error) return; |
820 |
< |
|
821 |
< |
// set the throw target |
822 |
< |
Active_Player->ThrowTargetCharacter = &ONgGameState->CharacterStorage[throwTarget]; |
823 |
< |
Target = ONrGetActiveCharacter(Active_Player->ThrowTargetCharacter); |
824 |
< |
if ((Target->Animation != throw_animation) && |
825 |
< |
(OldAnimation != Animation) && |
826 |
< |
!(Active_Player->ThrowTargetCharacter->Flags & ONcCharacterFlag_BeingThrown)) |
846 |
> |
short throwTarget = PlayerList[pd->throw_data.throwing]->spawnnumber; |
847 |
> |
if ((throwTarget != Active_Player->throwing) && |
848 |
> |
(pd->throw_data.throwFrame < 10)) |
849 |
|
{ |
850 |
< |
// set the throw variables |
851 |
< |
Active_Player->targetThrow = throw_animation; |
852 |
< |
Active_Player->throwing = throwTarget; |
853 |
< |
|
854 |
< |
// run the throw |
855 |
< |
ONrCharacter_NewAnimationHook(Player, Active_Player); |
856 |
< |
|
857 |
< |
if (Active_Player->ThrowTargetCharacter) |
850 |
> |
void *throw_animation; |
851 |
> |
ActiveCharacter* Target; |
852 |
> |
// get the animation |
853 |
> |
|
854 |
> |
TMrInstance_GetDataPtr( |
855 |
> |
'TRAM', |
856 |
> |
pd->throw_data.throwName, |
857 |
> |
&throw_animation); |
858 |
> |
//if (error) return; |
859 |
> |
|
860 |
> |
// set the throw target |
861 |
> |
Active_Player->ThrowTargetCharacter = &ONgGameState->CharacterStorage[throwTarget]; |
862 |
> |
Target = ONrGetActiveCharacter(Active_Player->ThrowTargetCharacter); |
863 |
> |
if ((Target->Animation != throw_animation) && |
864 |
> |
(OldAnimation != Animation) && |
865 |
> |
!(Active_Player->ThrowTargetCharacter->Flags & ONcCharacterFlag_BeingThrown)) |
866 |
|
{ |
867 |
< |
Target->Frame += 2; |
868 |
< |
Target->thrownBy = Player->Number; |
867 |
> |
// set the throw variables |
868 |
> |
Active_Player->targetThrow = throw_animation; |
869 |
> |
Active_Player->throwing = throwTarget; |
870 |
> |
|
871 |
> |
// run the throw |
872 |
> |
ONrCharacter_NewAnimationHook(Player, Active_Player); |
873 |
> |
|
874 |
> |
if (Active_Player->ThrowTargetCharacter) |
875 |
> |
{ |
876 |
> |
Target->Frame += 2; |
877 |
> |
Target->thrownBy = Player->Number; |
878 |
> |
} |
879 |
|
} |
880 |
|
} |
881 |
< |
} |
881 |
> |
} //throw check |
882 |
> |
} //second pass |
883 |
> |
} //if not dead |
884 |
> |
} //if( (server_started && i !=0) || !server_started ) |
885 |
> |
|
886 |
> |
//Check for character switching requests |
887 |
> |
if(server_started && PlayerList[i]->Actions1 & Action_Block && PlayerList[i]->ShapeshiftCooldown < ONgGameState->GameTime) |
888 |
> |
{ |
889 |
> |
int error; |
890 |
> |
|
891 |
> |
|
892 |
> |
|
893 |
> |
ONCC *newClass; |
894 |
> |
short numClasses = (short)TMrInstance_GetTagCount('ONCC'); |
895 |
> |
/* |
896 |
> |
if(Active_Player->Input.Start.Actions1 & Action_Block) |
897 |
> |
{ |
898 |
> |
//This might not be getting hit. Find out why, eh? |
899 |
> |
PlayerList[i]->ShapeshiftCooldown = ONgGameState->GameTime + 15; |
900 |
> |
} |
901 |
> |
else |
902 |
> |
{ |
903 |
> |
PlayerList[i]->ShapeshiftCooldown = ONgGameState->GameTime + 5; |
904 |
> |
} |
905 |
> |
*/ |
906 |
> |
if (PlayerList[i]->Actions1 & Action_Crouch) { |
907 |
> |
Player->ONCCnumber += numClasses - 1; |
908 |
> |
} |
909 |
> |
else { |
910 |
> |
Player->ONCCnumber += 1; |
911 |
> |
} |
912 |
> |
|
913 |
> |
if (numClasses > 0) { |
914 |
> |
Player->ONCCnumber = Player->ONCCnumber % numClasses; |
915 |
> |
|
916 |
> |
error = TMrInstance_GetDataPtr_ByNumber('ONCC', Player->ONCCnumber, &newClass); |
917 |
> |
|
918 |
> |
if ((newClass != NULL) && (!error)) { |
919 |
> |
ONrCharacter_SetCharacterClass(Player, newClass); |
920 |
|
} |
921 |
+ |
} |
922 |
|
|
844 |
– |
} |
923 |
|
} |
924 |
|
|
925 |
+ |
|
926 |
|
} |
927 |
|
if(server_started) |
928 |
|
{ |
929 |
< |
UDPServer_SendToAll(&all_input, FLATLINE_HEADER + sizeof(player_input) * 32); |
929 |
> |
all_input.all_input[InputIndex].PlayerNum = -1; |
930 |
> |
UDPServer_SendToAll(&all_input, |
931 |
> |
FLATLINE_HEADER + sizeof(player_input) * InputIndex + sizeof(int16_t)); |
932 |
|
} |
933 |
< |
|
933 |
> |
MultiplayerStatus.PleaseUpdateAllPlayers = 0; |
934 |
|
return ONgGameState; |
935 |
|
} |
936 |
|
|
939 |
|
if(server_started) |
940 |
|
{ |
941 |
|
//FLsPublic_Event(EV_DISCONNECT, &Player ); |
942 |
+ |
MultiplayerStatus.PleaseUpdateAllPlayers = 1; |
943 |
|
} |
944 |
|
//Kill off the character in another function, please |
945 |
|
//ONrCharacter_SetHitPoints( PlayerList[Player]->Chr, 0); |
1013 |
|
} |
1014 |
|
} |
1015 |
|
} |
1016 |
+ |
|
1017 |
+ |
bool FlatlineInitialize() |
1018 |
+ |
{ |
1019 |
+ |
|
1020 |
+ |
memset( Players, 0, sizeof( player_info ) * MAX_PLAYERS ); |
1021 |
+ |
memset( PlayerList, 0, 4 * MAX_PLAYERS ); |
1022 |
+ |
memset( &MultiplayerStatus, 0, sizeof( multiplayer_status )); |
1023 |
+ |
return 1; |
1024 |
+ |
} |